Skip to content

Commit 5833291

Browse files
committed
Merge tag 'pci-v5.16-fixes-1' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci
Pull PCI fixes from Bjorn Helgaas: "Revert conversion to struct device.driver instead of struct pci_dev.driver. The device.driver is set earlier, and using it caused the PCI core to call driver PM entry points before .probe() and after .remove(), when the driver isn't prepared. This caused NULL pointer dereferences in i2c_designware_pci and probably other driver issues" * tag 'pci-v5.16-fixes-1' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: Revert "PCI: Use to_pci_driver() instead of pci_dev->driver" Revert "PCI: Remove struct pci_dev->driver"
2 parents ca2ef2d + e0217c5 commit 5833291

File tree

5 files changed

+42
-45
lines changed

5 files changed

+42
-45
lines changed

drivers/pci/iov.c

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -164,15 +164,13 @@ static ssize_t sriov_vf_total_msix_show(struct device *dev,
164164
char *buf)
165165
{
166166
struct pci_dev *pdev = to_pci_dev(dev);
167-
struct pci_driver *pdrv;
168167
u32 vf_total_msix = 0;
169168

170169
device_lock(dev);
171-
pdrv = to_pci_driver(dev->driver);
172-
if (!pdrv || !pdrv->sriov_get_vf_total_msix)
170+
if (!pdev->driver || !pdev->driver->sriov_get_vf_total_msix)
173171
goto unlock;
174172

175-
vf_total_msix = pdrv->sriov_get_vf_total_msix(pdev);
173+
vf_total_msix = pdev->driver->sriov_get_vf_total_msix(pdev);
176174
unlock:
177175
device_unlock(dev);
178176
return sysfs_emit(buf, "%u\n", vf_total_msix);
@@ -185,7 +183,6 @@ static ssize_t sriov_vf_msix_count_store(struct device *dev,
185183
{
186184
struct pci_dev *vf_dev = to_pci_dev(dev);
187185
struct pci_dev *pdev = pci_physfn(vf_dev);
188-
struct pci_driver *pdrv;
189186
int val, ret = 0;
190187

191188
if (kstrtoint(buf, 0, &val) < 0)
@@ -195,14 +192,13 @@ static ssize_t sriov_vf_msix_count_store(struct device *dev,
195192
return -EINVAL;
196193

197194
device_lock(&pdev->dev);
198-
pdrv = to_pci_driver(dev->driver);
199-
if (!pdrv || !pdrv->sriov_set_msix_vec_count) {
195+
if (!pdev->driver || !pdev->driver->sriov_set_msix_vec_count) {
200196
ret = -EOPNOTSUPP;
201197
goto err_pdev;
202198
}
203199

204200
device_lock(&vf_dev->dev);
205-
if (to_pci_driver(vf_dev->dev.driver)) {
201+
if (vf_dev->driver) {
206202
/*
207203
* A driver is already attached to this VF and has configured
208204
* itself based on the current MSI-X vector count. Changing
@@ -212,7 +208,7 @@ static ssize_t sriov_vf_msix_count_store(struct device *dev,
212208
goto err_dev;
213209
}
214210

215-
ret = pdrv->sriov_set_msix_vec_count(vf_dev, val);
211+
ret = pdev->driver->sriov_set_msix_vec_count(vf_dev, val);
216212

217213
err_dev:
218214
device_unlock(&vf_dev->dev);
@@ -379,7 +375,6 @@ static ssize_t sriov_numvfs_store(struct device *dev,
379375
const char *buf, size_t count)
380376
{
381377
struct pci_dev *pdev = to_pci_dev(dev);
382-
struct pci_driver *pdrv;
383378
int ret = 0;
384379
u16 num_vfs;
385380

@@ -395,23 +390,22 @@ static ssize_t sriov_numvfs_store(struct device *dev,
395390
goto exit;
396391

397392
/* is PF driver loaded */
398-
pdrv = to_pci_driver(dev->driver);
399-
if (!pdrv) {
393+
if (!pdev->driver) {
400394
pci_info(pdev, "no driver bound to device; cannot configure SR-IOV\n");
401395
ret = -ENOENT;
402396
goto exit;
403397
}
404398

405399
/* is PF driver loaded w/callback */
406-
if (!pdrv->sriov_configure) {
400+
if (!pdev->driver->sriov_configure) {
407401
pci_info(pdev, "driver does not support SR-IOV configuration via sysfs\n");
408402
ret = -ENOENT;
409403
goto exit;
410404
}
411405

412406
if (num_vfs == 0) {
413407
/* disable VFs */
414-
ret = pdrv->sriov_configure(pdev, 0);
408+
ret = pdev->driver->sriov_configure(pdev, 0);
415409
goto exit;
416410
}
417411

@@ -423,7 +417,7 @@ static ssize_t sriov_numvfs_store(struct device *dev,
423417
goto exit;
424418
}
425419

426-
ret = pdrv->sriov_configure(pdev, num_vfs);
420+
ret = pdev->driver->sriov_configure(pdev, num_vfs);
427421
if (ret < 0)
428422
goto exit;
429423

drivers/pci/pci-driver.c

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -319,10 +319,12 @@ static long local_pci_probe(void *_ddi)
319319
* its remove routine.
320320
*/
321321
pm_runtime_get_sync(dev);
322+
pci_dev->driver = pci_drv;
322323
rc = pci_drv->probe(pci_dev, ddi->id);
323324
if (!rc)
324325
return rc;
325326
if (rc < 0) {
327+
pci_dev->driver = NULL;
326328
pm_runtime_put_sync(dev);
327329
return rc;
328330
}
@@ -388,6 +390,7 @@ static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev,
388390
* @pci_dev: PCI device being probed
389391
*
390392
* returns 0 on success, else error.
393+
* side-effect: pci_dev->driver is set to drv when drv claims pci_dev.
391394
*/
392395
static int __pci_device_probe(struct pci_driver *drv, struct pci_dev *pci_dev)
393396
{
@@ -454,14 +457,15 @@ static int pci_device_probe(struct device *dev)
454457
static void pci_device_remove(struct device *dev)
455458
{
456459
struct pci_dev *pci_dev = to_pci_dev(dev);
457-
struct pci_driver *drv = to_pci_driver(dev->driver);
460+
struct pci_driver *drv = pci_dev->driver;
458461

459462
if (drv->remove) {
460463
pm_runtime_get_sync(dev);
461464
drv->remove(pci_dev);
462465
pm_runtime_put_noidle(dev);
463466
}
464467
pcibios_free_irq(pci_dev);
468+
pci_dev->driver = NULL;
465469
pci_iov_remove(pci_dev);
466470

467471
/* Undo the runtime PM settings in local_pci_probe() */
@@ -489,7 +493,7 @@ static void pci_device_remove(struct device *dev)
489493
static void pci_device_shutdown(struct device *dev)
490494
{
491495
struct pci_dev *pci_dev = to_pci_dev(dev);
492-
struct pci_driver *drv = to_pci_driver(dev->driver);
496+
struct pci_driver *drv = pci_dev->driver;
493497

494498
pm_runtime_resume(dev);
495499

@@ -585,7 +589,7 @@ static int pci_pm_reenable_device(struct pci_dev *pci_dev)
585589
static int pci_legacy_suspend(struct device *dev, pm_message_t state)
586590
{
587591
struct pci_dev *pci_dev = to_pci_dev(dev);
588-
struct pci_driver *drv = to_pci_driver(dev->driver);
592+
struct pci_driver *drv = pci_dev->driver;
589593

590594
if (drv && drv->suspend) {
591595
pci_power_t prev = pci_dev->current_state;
@@ -626,7 +630,7 @@ static int pci_legacy_suspend_late(struct device *dev, pm_message_t state)
626630
static int pci_legacy_resume(struct device *dev)
627631
{
628632
struct pci_dev *pci_dev = to_pci_dev(dev);
629-
struct pci_driver *drv = to_pci_driver(dev->driver);
633+
struct pci_driver *drv = pci_dev->driver;
630634

631635
pci_fixup_device(pci_fixup_resume, pci_dev);
632636

@@ -645,7 +649,7 @@ static void pci_pm_default_suspend(struct pci_dev *pci_dev)
645649

646650
static bool pci_has_legacy_pm_support(struct pci_dev *pci_dev)
647651
{
648-
struct pci_driver *drv = to_pci_driver(pci_dev->dev.driver);
652+
struct pci_driver *drv = pci_dev->driver;
649653
bool ret = drv && (drv->suspend || drv->resume);
650654

651655
/*
@@ -1238,11 +1242,11 @@ static int pci_pm_runtime_suspend(struct device *dev)
12381242
int error;
12391243

12401244
/*
1241-
* If the device has no driver, we leave it in D0, but it may go to
1242-
* D3cold when the bridge above it runtime suspends. Save its
1243-
* config space in case that happens.
1245+
* If pci_dev->driver is not set (unbound), we leave the device in D0,
1246+
* but it may go to D3cold when the bridge above it runtime suspends.
1247+
* Save its config space in case that happens.
12441248
*/
1245-
if (!to_pci_driver(dev->driver)) {
1249+
if (!pci_dev->driver) {
12461250
pci_save_state(pci_dev);
12471251
return 0;
12481252
}
@@ -1299,7 +1303,7 @@ static int pci_pm_runtime_resume(struct device *dev)
12991303
*/
13001304
pci_restore_standard_config(pci_dev);
13011305

1302-
if (!to_pci_driver(dev->driver))
1306+
if (!pci_dev->driver)
13031307
return 0;
13041308

13051309
pci_fixup_device(pci_fixup_resume_early, pci_dev);
@@ -1318,13 +1322,14 @@ static int pci_pm_runtime_resume(struct device *dev)
13181322

13191323
static int pci_pm_runtime_idle(struct device *dev)
13201324
{
1325+
struct pci_dev *pci_dev = to_pci_dev(dev);
13211326
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
13221327

13231328
/*
1324-
* If the device has no driver, it should always remain in D0
1325-
* regardless of the runtime PM status
1329+
* If pci_dev->driver is not set (unbound), the device should
1330+
* always remain in D0 regardless of the runtime PM status
13261331
*/
1327-
if (!to_pci_driver(dev->driver))
1332+
if (!pci_dev->driver)
13281333
return 0;
13291334

13301335
if (!pm)
@@ -1431,10 +1436,8 @@ static struct pci_driver pci_compat_driver = {
14311436
*/
14321437
struct pci_driver *pci_dev_driver(const struct pci_dev *dev)
14331438
{
1434-
struct pci_driver *drv = to_pci_driver(dev->dev.driver);
1435-
1436-
if (drv)
1437-
return drv;
1439+
if (dev->driver)
1440+
return dev->driver;
14381441
else {
14391442
int i;
14401443
for (i = 0; i <= PCI_ROM_RESOURCE; i++)

drivers/pci/pci.c

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5135,14 +5135,13 @@ EXPORT_SYMBOL_GPL(pci_dev_unlock);
51355135

51365136
static void pci_dev_save_and_disable(struct pci_dev *dev)
51375137
{
5138-
struct pci_driver *drv = to_pci_driver(dev->dev.driver);
51395138
const struct pci_error_handlers *err_handler =
5140-
drv ? drv->err_handler : NULL;
5139+
dev->driver ? dev->driver->err_handler : NULL;
51415140

51425141
/*
5143-
* drv->err_handler->reset_prepare() is protected against races
5144-
* with ->remove() by the device lock, which must be held by the
5145-
* caller.
5142+
* dev->driver->err_handler->reset_prepare() is protected against
5143+
* races with ->remove() by the device lock, which must be held by
5144+
* the caller.
51465145
*/
51475146
if (err_handler && err_handler->reset_prepare)
51485147
err_handler->reset_prepare(dev);
@@ -5167,15 +5166,15 @@ static void pci_dev_save_and_disable(struct pci_dev *dev)
51675166

51685167
static void pci_dev_restore(struct pci_dev *dev)
51695168
{
5170-
struct pci_driver *drv = to_pci_driver(dev->dev.driver);
51715169
const struct pci_error_handlers *err_handler =
5172-
drv ? drv->err_handler : NULL;
5170+
dev->driver ? dev->driver->err_handler : NULL;
51735171

51745172
pci_restore_state(dev);
51755173

51765174
/*
5177-
* drv->err_handler->reset_done() is protected against races with
5178-
* ->remove() by the device lock, which must be held by the caller.
5175+
* dev->driver->err_handler->reset_done() is protected against
5176+
* races with ->remove() by the device lock, which must be held by
5177+
* the caller.
51795178
*/
51805179
if (err_handler && err_handler->reset_done)
51815180
err_handler->reset_done(dev);

drivers/pci/pcie/err.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ static int report_error_detected(struct pci_dev *dev,
5454
const struct pci_error_handlers *err_handler;
5555

5656
device_lock(&dev->dev);
57-
pdrv = to_pci_driver(dev->dev.driver);
57+
pdrv = dev->driver;
5858
if (!pci_dev_set_io_state(dev, state) ||
5959
!pdrv ||
6060
!pdrv->err_handler ||
@@ -98,7 +98,7 @@ static int report_mmio_enabled(struct pci_dev *dev, void *data)
9898
const struct pci_error_handlers *err_handler;
9999

100100
device_lock(&dev->dev);
101-
pdrv = to_pci_driver(dev->dev.driver);
101+
pdrv = dev->driver;
102102
if (!pdrv ||
103103
!pdrv->err_handler ||
104104
!pdrv->err_handler->mmio_enabled)
@@ -119,7 +119,7 @@ static int report_slot_reset(struct pci_dev *dev, void *data)
119119
const struct pci_error_handlers *err_handler;
120120

121121
device_lock(&dev->dev);
122-
pdrv = to_pci_driver(dev->dev.driver);
122+
pdrv = dev->driver;
123123
if (!pdrv ||
124124
!pdrv->err_handler ||
125125
!pdrv->err_handler->slot_reset)
@@ -139,7 +139,7 @@ static int report_resume(struct pci_dev *dev, void *data)
139139
const struct pci_error_handlers *err_handler;
140140

141141
device_lock(&dev->dev);
142-
pdrv = to_pci_driver(dev->dev.driver);
142+
pdrv = dev->driver;
143143
if (!pci_dev_set_io_state(dev, pci_channel_io_normal) ||
144144
!pdrv ||
145145
!pdrv->err_handler ||

include/linux/pci.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,7 @@ struct pci_dev {
342342
u16 pcie_flags_reg; /* Cached PCIe Capabilities Register */
343343
unsigned long *dma_alias_mask;/* Mask of enabled devfn aliases */
344344

345+
struct pci_driver *driver; /* Driver bound to this device */
345346
u64 dma_mask; /* Mask of the bits of bus address this
346347
device implements. Normally this is
347348
0xffffffff. You only need to change

0 commit comments

Comments
 (0)