Skip to content

Commit 4c5cd8d

Browse files
committed
Merge branch 'pci/pm'
- If a device has already been disconnected, e.g., by a hotplug removal, don't bother trying to resume it to D0 when detaching the driver (Mario Limonciello) - Ensure devices are powered up before config reads for 'max_link_width', 'current_link_speed', 'current_link_width', 'secondary_bus_number', and 'subordinate_bus_number' sysfs files (Brian Norris) * pci/pm: PCI/sysfs: Ensure devices are powered for config reads PCI/PM: Skip resuming to D0 if device is disconnected
2 parents 0bb65e3 + 48991e4 commit 4c5cd8d

2 files changed

Lines changed: 24 additions & 1 deletion

File tree

drivers/pci/pci-sysfs.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,8 +201,14 @@ static ssize_t max_link_width_show(struct device *dev,
201201
struct device_attribute *attr, char *buf)
202202
{
203203
struct pci_dev *pdev = to_pci_dev(dev);
204+
ssize_t ret;
204205

205-
return sysfs_emit(buf, "%u\n", pcie_get_width_cap(pdev));
206+
/* We read PCI_EXP_LNKCAP, so we need the device to be accessible. */
207+
pci_config_pm_runtime_get(pdev);
208+
ret = sysfs_emit(buf, "%u\n", pcie_get_width_cap(pdev));
209+
pci_config_pm_runtime_put(pdev);
210+
211+
return ret;
206212
}
207213
static DEVICE_ATTR_RO(max_link_width);
208214

@@ -214,7 +220,10 @@ static ssize_t current_link_speed_show(struct device *dev,
214220
int err;
215221
enum pci_bus_speed speed;
216222

223+
pci_config_pm_runtime_get(pci_dev);
217224
err = pcie_capability_read_word(pci_dev, PCI_EXP_LNKSTA, &linkstat);
225+
pci_config_pm_runtime_put(pci_dev);
226+
218227
if (err)
219228
return -EINVAL;
220229

@@ -231,7 +240,10 @@ static ssize_t current_link_width_show(struct device *dev,
231240
u16 linkstat;
232241
int err;
233242

243+
pci_config_pm_runtime_get(pci_dev);
234244
err = pcie_capability_read_word(pci_dev, PCI_EXP_LNKSTA, &linkstat);
245+
pci_config_pm_runtime_put(pci_dev);
246+
235247
if (err)
236248
return -EINVAL;
237249

@@ -247,7 +259,10 @@ static ssize_t secondary_bus_number_show(struct device *dev,
247259
u8 sec_bus;
248260
int err;
249261

262+
pci_config_pm_runtime_get(pci_dev);
250263
err = pci_read_config_byte(pci_dev, PCI_SECONDARY_BUS, &sec_bus);
264+
pci_config_pm_runtime_put(pci_dev);
265+
251266
if (err)
252267
return -EINVAL;
253268

@@ -263,7 +278,10 @@ static ssize_t subordinate_bus_number_show(struct device *dev,
263278
u8 sub_bus;
264279
int err;
265280

281+
pci_config_pm_runtime_get(pci_dev);
266282
err = pci_read_config_byte(pci_dev, PCI_SUBORDINATE_BUS, &sub_bus);
283+
pci_config_pm_runtime_put(pci_dev);
284+
267285
if (err)
268286
return -EINVAL;
269287

drivers/pci/pci.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1374,6 +1374,11 @@ int pci_power_up(struct pci_dev *dev)
13741374
return -EIO;
13751375
}
13761376

1377+
if (pci_dev_is_disconnected(dev)) {
1378+
dev->current_state = PCI_D3cold;
1379+
return -EIO;
1380+
}
1381+
13771382
pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr);
13781383
if (PCI_POSSIBLE_ERROR(pmcsr)) {
13791384
pci_err(dev, "Unable to change power state from %s to D0, device inaccessible\n",

0 commit comments

Comments
 (0)