Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'platform-drivers-x86-v6.7-6' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86

Pull x86 platform driver fixes from Ilpo Järvinen:

- Intel PMC GBE LTR regression

- P2SB / PCI deadlock fix

* tag 'platform-drivers-x86-v6.7-6' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86:
platform/x86/intel/pmc: Move GBE LTR ignore to suspend callback
platform/x86/intel/pmc: Allow reenabling LTRs
platform/x86/intel/pmc: Add suspend callback
platform/x86: p2sb: Allow p2sb_bar() calls during PCI device probe

+179 -71
+3 -6
drivers/platform/x86/intel/pmc/adl.c
··· 314 314 struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; 315 315 int ret; 316 316 317 + pmcdev->suspend = cnl_suspend; 318 + pmcdev->resume = cnl_resume; 319 + 317 320 pmc->map = &adl_reg_map; 318 321 ret = get_primary_reg_base(pmc); 319 322 if (ret) 320 323 return ret; 321 - 322 - /* Due to a hardware limitation, the GBE LTR blocks PC10 323 - * when a cable is attached. Tell the PMC to ignore it. 324 - */ 325 - dev_dbg(&pmcdev->pdev->dev, "ignoring GBE LTR\n"); 326 - pmc_core_send_ltr_ignore(pmcdev, 3); 327 324 328 325 return 0; 329 326 }
+20 -6
drivers/platform/x86/intel/pmc/cnp.c
··· 204 204 .etr3_offset = ETR3_OFFSET, 205 205 }; 206 206 207 + void cnl_suspend(struct pmc_dev *pmcdev) 208 + { 209 + /* 210 + * Due to a hardware limitation, the GBE LTR blocks PC10 211 + * when a cable is attached. To unblock PC10 during suspend, 212 + * tell the PMC to ignore it. 213 + */ 214 + pmc_core_send_ltr_ignore(pmcdev, 3, 1); 215 + } 216 + 217 + int cnl_resume(struct pmc_dev *pmcdev) 218 + { 219 + pmc_core_send_ltr_ignore(pmcdev, 3, 0); 220 + 221 + return pmc_core_resume_common(pmcdev); 222 + } 223 + 207 224 int cnp_core_init(struct pmc_dev *pmcdev) 208 225 { 209 226 struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; 210 227 int ret; 211 228 229 + pmcdev->suspend = cnl_suspend; 230 + pmcdev->resume = cnl_resume; 231 + 212 232 pmc->map = &cnp_reg_map; 213 233 ret = get_primary_reg_base(pmc); 214 234 if (ret) 215 235 return ret; 216 - 217 - /* Due to a hardware limitation, the GBE LTR blocks PC10 218 - * when a cable is attached. Tell the PMC to ignore it. 219 - */ 220 - dev_dbg(&pmcdev->pdev->dev, "ignoring GBE LTR\n"); 221 - pmc_core_send_ltr_ignore(pmcdev, 3); 222 236 223 237 return 0; 224 238 }
+9 -3
drivers/platform/x86/intel/pmc/core.c
··· 460 460 } 461 461 DEFINE_SHOW_ATTRIBUTE(pmc_core_pll); 462 462 463 - int pmc_core_send_ltr_ignore(struct pmc_dev *pmcdev, u32 value) 463 + int pmc_core_send_ltr_ignore(struct pmc_dev *pmcdev, u32 value, int ignore) 464 464 { 465 465 struct pmc *pmc; 466 466 const struct pmc_reg_map *map; ··· 498 498 mutex_lock(&pmcdev->lock); 499 499 500 500 reg = pmc_core_reg_read(pmc, map->ltr_ignore_offset); 501 - reg |= BIT(ltr_index); 501 + if (ignore) 502 + reg |= BIT(ltr_index); 503 + else 504 + reg &= ~BIT(ltr_index); 502 505 pmc_core_reg_write(pmc, map->ltr_ignore_offset, reg); 503 506 504 507 mutex_unlock(&pmcdev->lock); ··· 524 521 if (err) 525 522 return err; 526 523 527 - err = pmc_core_send_ltr_ignore(pmcdev, value); 524 + err = pmc_core_send_ltr_ignore(pmcdev, value, 1); 528 525 529 526 return err == 0 ? count : err; 530 527 } ··· 1281 1278 { 1282 1279 struct pmc_dev *pmcdev = dev_get_drvdata(dev); 1283 1280 struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; 1281 + 1282 + if (pmcdev->suspend) 1283 + pmcdev->suspend(pmcdev); 1284 1284 1285 1285 /* Check if the syspend will actually use S0ix */ 1286 1286 if (pm_suspend_via_firmware())
+6 -1
drivers/platform/x86/intel/pmc/core.h
··· 363 363 * @s0ix_counter: S0ix residency (step adjusted) 364 364 * @num_lpm_modes: Count of enabled modes 365 365 * @lpm_en_modes: Array of enabled modes from lowest to highest priority 366 + * @suspend: Function to perform platform specific suspend 366 367 * @resume: Function to perform platform specific resume 367 368 * 368 369 * pmc_dev contains info about power management controller device. ··· 380 379 u64 s0ix_counter; 381 380 int num_lpm_modes; 382 381 int lpm_en_modes[LPM_MAX_NUM_MODES]; 382 + void (*suspend)(struct pmc_dev *pmcdev); 383 383 int (*resume)(struct pmc_dev *pmcdev); 384 384 385 385 bool has_die_c6; ··· 488 486 extern const struct pmc_reg_map mtl_ioem_reg_map; 489 487 490 488 extern void pmc_core_get_tgl_lpm_reqs(struct platform_device *pdev); 491 - extern int pmc_core_send_ltr_ignore(struct pmc_dev *pmcdev, u32 value); 489 + int pmc_core_send_ltr_ignore(struct pmc_dev *pmcdev, u32 value, int ignore); 492 490 493 491 int pmc_core_resume_common(struct pmc_dev *pmcdev); 494 492 int get_primary_reg_base(struct pmc *pmc); ··· 501 499 int tgl_core_init(struct pmc_dev *pmcdev); 502 500 int adl_core_init(struct pmc_dev *pmcdev); 503 501 int mtl_core_init(struct pmc_dev *pmcdev); 502 + 503 + void cnl_suspend(struct pmc_dev *pmcdev); 504 + int cnl_resume(struct pmc_dev *pmcdev); 504 505 505 506 #define pmc_for_each_mode(i, mode, pmcdev) \ 506 507 for (i = 0, mode = pmcdev->lpm_en_modes[i]; \
+3 -6
drivers/platform/x86/intel/pmc/mtl.c
··· 979 979 static int mtl_resume(struct pmc_dev *pmcdev) 980 980 { 981 981 mtl_d3_fixup(); 982 + pmc_core_send_ltr_ignore(pmcdev, 3, 0); 983 + 982 984 return pmc_core_resume_common(pmcdev); 983 985 } 984 986 ··· 991 989 992 990 mtl_d3_fixup(); 993 991 992 + pmcdev->suspend = cnl_suspend; 994 993 pmcdev->resume = mtl_resume; 995 994 996 995 pmcdev->regmap_list = mtl_pmc_info_list; ··· 1004 1001 if (ret) 1005 1002 return ret; 1006 1003 } 1007 - 1008 - /* Due to a hardware limitation, the GBE LTR blocks PC10 1009 - * when a cable is attached. Tell the PMC to ignore it. 1010 - */ 1011 - dev_dbg(&pmcdev->pdev->dev, "ignoring GBE LTR\n"); 1012 - pmc_core_send_ltr_ignore(pmcdev, 3); 1013 1004 1014 1005 return 0; 1015 1006 }
+4 -5
drivers/platform/x86/intel/pmc/tgl.c
··· 259 259 int ret; 260 260 261 261 pmc->map = &tgl_reg_map; 262 + 263 + pmcdev->suspend = cnl_suspend; 264 + pmcdev->resume = cnl_resume; 265 + 262 266 ret = get_primary_reg_base(pmc); 263 267 if (ret) 264 268 return ret; 265 269 266 270 pmc_core_get_tgl_lpm_reqs(pmcdev->pdev); 267 - /* Due to a hardware limitation, the GBE LTR blocks PC10 268 - * when a cable is attached. Tell the PMC to ignore it. 269 - */ 270 - dev_dbg(&pmcdev->pdev->dev, "ignoring GBE LTR\n"); 271 - pmc_core_send_ltr_ignore(pmcdev, 3); 272 271 273 272 return 0; 274 273 }
+134 -44
drivers/platform/x86/p2sb.c
··· 26 26 {} 27 27 }; 28 28 29 + /* 30 + * Cache BAR0 of P2SB device functions 0 to 7. 31 + * TODO: The constant 8 is the number of functions that PCI specification 32 + * defines. Same definitions exist tree-wide. Unify this definition and 33 + * the other definitions then move to include/uapi/linux/pci.h. 34 + */ 35 + #define NR_P2SB_RES_CACHE 8 36 + 37 + struct p2sb_res_cache { 38 + u32 bus_dev_id; 39 + struct resource res; 40 + }; 41 + 42 + static struct p2sb_res_cache p2sb_resources[NR_P2SB_RES_CACHE]; 43 + 29 44 static int p2sb_get_devfn(unsigned int *devfn) 30 45 { 31 46 unsigned int fn = P2SB_DEVFN_DEFAULT; ··· 54 39 return 0; 55 40 } 56 41 42 + static bool p2sb_valid_resource(struct resource *res) 43 + { 44 + if (res->flags) 45 + return true; 46 + 47 + return false; 48 + } 49 + 57 50 /* Copy resource from the first BAR of the device in question */ 58 - static int p2sb_read_bar0(struct pci_dev *pdev, struct resource *mem) 51 + static void p2sb_read_bar0(struct pci_dev *pdev, struct resource *mem) 59 52 { 60 53 struct resource *bar0 = &pdev->resource[0]; 61 54 ··· 79 56 mem->end = bar0->end; 80 57 mem->flags = bar0->flags; 81 58 mem->desc = bar0->desc; 59 + } 60 + 61 + static void p2sb_scan_and_cache_devfn(struct pci_bus *bus, unsigned int devfn) 62 + { 63 + struct p2sb_res_cache *cache = &p2sb_resources[PCI_FUNC(devfn)]; 64 + struct pci_dev *pdev; 65 + 66 + pdev = pci_scan_single_device(bus, devfn); 67 + if (!pdev) 68 + return; 69 + 70 + p2sb_read_bar0(pdev, &cache->res); 71 + cache->bus_dev_id = bus->dev.id; 72 + 73 + pci_stop_and_remove_bus_device(pdev); 74 + return; 75 + } 76 + 77 + static int p2sb_scan_and_cache(struct pci_bus *bus, unsigned int devfn) 78 + { 79 + unsigned int slot, fn; 80 + 81 + if (PCI_FUNC(devfn) == 0) { 82 + /* 83 + * When function number of the P2SB device is zero, scan it and 84 + * other function numbers, and if devices are available, cache 85 + * their BAR0s. 86 + */ 87 + slot = PCI_SLOT(devfn); 88 + for (fn = 0; fn < NR_P2SB_RES_CACHE; fn++) 89 + p2sb_scan_and_cache_devfn(bus, PCI_DEVFN(slot, fn)); 90 + } else { 91 + /* Scan the P2SB device and cache its BAR0 */ 92 + p2sb_scan_and_cache_devfn(bus, devfn); 93 + } 94 + 95 + if (!p2sb_valid_resource(&p2sb_resources[PCI_FUNC(devfn)].res)) 96 + return -ENOENT; 82 97 83 98 return 0; 84 99 } 85 100 86 - static int p2sb_scan_and_read(struct pci_bus *bus, unsigned int devfn, struct resource *mem) 101 + static struct pci_bus *p2sb_get_bus(struct pci_bus *bus) 87 102 { 88 - struct pci_dev *pdev; 89 - int ret; 103 + static struct pci_bus *p2sb_bus; 90 104 91 - pdev = pci_scan_single_device(bus, devfn); 92 - if (!pdev) 93 - return -ENODEV; 105 + bus = bus ?: p2sb_bus; 106 + if (bus) 107 + return bus; 94 108 95 - ret = p2sb_read_bar0(pdev, mem); 96 - 97 - pci_stop_and_remove_bus_device(pdev); 98 - return ret; 109 + /* Assume P2SB is on the bus 0 in domain 0 */ 110 + p2sb_bus = pci_find_bus(0, 0); 111 + return p2sb_bus; 99 112 } 100 113 101 - /** 102 - * p2sb_bar - Get Primary to Sideband (P2SB) bridge device BAR 103 - * @bus: PCI bus to communicate with 104 - * @devfn: PCI slot and function to communicate with 105 - * @mem: memory resource to be filled in 106 - * 107 - * The BIOS prevents the P2SB device from being enumerated by the PCI 108 - * subsystem, so we need to unhide and hide it back to lookup the BAR. 109 - * 110 - * if @bus is NULL, the bus 0 in domain 0 will be used. 111 - * If @devfn is 0, it will be replaced by devfn of the P2SB device. 112 - * 113 - * Caller must provide a valid pointer to @mem. 114 - * 115 - * Locking is handled by pci_rescan_remove_lock mutex. 116 - * 117 - * Return: 118 - * 0 on success or appropriate errno value on error. 119 - */ 120 - int p2sb_bar(struct pci_bus *bus, unsigned int devfn, struct resource *mem) 114 + static int p2sb_cache_resources(void) 121 115 { 122 - struct pci_dev *pdev_p2sb; 116 + struct pci_bus *bus; 123 117 unsigned int devfn_p2sb; 124 118 u32 value = P2SBC_HIDE; 125 119 int ret; ··· 146 106 if (ret) 147 107 return ret; 148 108 149 - /* if @bus is NULL, use bus 0 in domain 0 */ 150 - bus = bus ?: pci_find_bus(0, 0); 109 + bus = p2sb_get_bus(NULL); 110 + if (!bus) 111 + return -ENODEV; 151 112 152 113 /* 153 114 * Prevent concurrent PCI bus scan from seeing the P2SB device and ··· 156 115 */ 157 116 pci_lock_rescan_remove(); 158 117 159 - /* Unhide the P2SB device, if needed */ 118 + /* 119 + * The BIOS prevents the P2SB device from being enumerated by the PCI 120 + * subsystem, so we need to unhide and hide it back to lookup the BAR. 121 + * Unhide the P2SB device here, if needed. 122 + */ 160 123 pci_bus_read_config_dword(bus, devfn_p2sb, P2SBC, &value); 161 124 if (value & P2SBC_HIDE) 162 125 pci_bus_write_config_dword(bus, devfn_p2sb, P2SBC, 0); 163 126 164 - pdev_p2sb = pci_scan_single_device(bus, devfn_p2sb); 165 - if (devfn) 166 - ret = p2sb_scan_and_read(bus, devfn, mem); 167 - else 168 - ret = p2sb_read_bar0(pdev_p2sb, mem); 169 - pci_stop_and_remove_bus_device(pdev_p2sb); 127 + ret = p2sb_scan_and_cache(bus, devfn_p2sb); 170 128 171 129 /* Hide the P2SB device, if it was hidden */ 172 130 if (value & P2SBC_HIDE) ··· 173 133 174 134 pci_unlock_rescan_remove(); 175 135 176 - if (ret) 177 - return ret; 136 + return ret; 137 + } 178 138 179 - if (mem->flags == 0) 139 + /** 140 + * p2sb_bar - Get Primary to Sideband (P2SB) bridge device BAR 141 + * @bus: PCI bus to communicate with 142 + * @devfn: PCI slot and function to communicate with 143 + * @mem: memory resource to be filled in 144 + * 145 + * If @bus is NULL, the bus 0 in domain 0 will be used. 146 + * If @devfn is 0, it will be replaced by devfn of the P2SB device. 147 + * 148 + * Caller must provide a valid pointer to @mem. 149 + * 150 + * Return: 151 + * 0 on success or appropriate errno value on error. 152 + */ 153 + int p2sb_bar(struct pci_bus *bus, unsigned int devfn, struct resource *mem) 154 + { 155 + struct p2sb_res_cache *cache; 156 + int ret; 157 + 158 + bus = p2sb_get_bus(bus); 159 + if (!bus) 180 160 return -ENODEV; 181 161 162 + if (!devfn) { 163 + ret = p2sb_get_devfn(&devfn); 164 + if (ret) 165 + return ret; 166 + } 167 + 168 + cache = &p2sb_resources[PCI_FUNC(devfn)]; 169 + if (cache->bus_dev_id != bus->dev.id) 170 + return -ENODEV; 171 + 172 + if (!p2sb_valid_resource(&cache->res)) 173 + return -ENOENT; 174 + 175 + memcpy(mem, &cache->res, sizeof(*mem)); 182 176 return 0; 183 177 } 184 178 EXPORT_SYMBOL_GPL(p2sb_bar); 179 + 180 + static int __init p2sb_fs_init(void) 181 + { 182 + p2sb_cache_resources(); 183 + return 0; 184 + } 185 + 186 + /* 187 + * pci_rescan_remove_lock to avoid access to unhidden P2SB devices can 188 + * not be locked in sysfs pci bus rescan path because of deadlock. To 189 + * avoid the deadlock, access to P2SB devices with the lock at an early 190 + * step in kernel initialization and cache required resources. This 191 + * should happen after subsys_initcall which initializes PCI subsystem 192 + * and before device_initcall which requires P2SB resources. 193 + */ 194 + fs_initcall(p2sb_fs_init);