mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 11:11:45 -04:00
PCI: Rework config space blocking services
pci_block_user_cfg_access was designed for the use case that a single context, the IPR driver, temporarily delays user space accesses to the config space via sysfs. This assumption became invalid by the time pci_dev_reset was added as locking instance. Today, if you run two loops in parallel that reset the same device via sysfs, you end up with a kernel BUG as pci_block_user_cfg_access detect the broken assumption. This reworks the pci_block_user_cfg_access to a sleeping service pci_cfg_access_lock and an atomic-compatible variant called pci_cfg_access_trylock. The former not only blocks user space access as before but also waits if access was already locked. The latter service just returns false in this case, allowing the caller to resolve the conflict instead of raising a BUG. Adaptions of the ipr driver were originally written by Brian King. Acked-by: Brian King <[email protected]> Acked-by: Michael S. Tsirkin <[email protected]> Signed-off-by: Jan Kiszka <[email protected]> Signed-off-by: Jesse Barnes <[email protected]>
This commit is contained in:
parent
ae5cd86455
commit
fb51ccbf21
7 changed files with 131 additions and 50 deletions
|
|
@ -55,7 +55,8 @@ static irqreturn_t irqhandler(int irq, struct uio_info *info)
|
|||
BUILD_BUG_ON(PCI_COMMAND % 4);
|
||||
BUILD_BUG_ON(PCI_COMMAND + 2 != PCI_STATUS);
|
||||
|
||||
pci_block_user_cfg_access(pdev);
|
||||
if (!pci_cfg_access_trylock(pdev))
|
||||
goto error;
|
||||
|
||||
/* Read both command and status registers in a single 32-bit operation.
|
||||
* Note: we could cache the value for command and move the status read
|
||||
|
|
@ -79,7 +80,7 @@ static irqreturn_t irqhandler(int irq, struct uio_info *info)
|
|||
ret = IRQ_HANDLED;
|
||||
done:
|
||||
|
||||
pci_unblock_user_cfg_access(pdev);
|
||||
pci_cfg_access_lock(pdev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -91,7 +92,7 @@ static int __devinit verify_pci_2_3(struct pci_dev *pdev)
|
|||
u16 orig, new;
|
||||
int err = 0;
|
||||
|
||||
pci_block_user_cfg_access(pdev);
|
||||
pci_cfg_access_lock(pdev);
|
||||
pci_read_config_word(pdev, PCI_COMMAND, &orig);
|
||||
pci_write_config_word(pdev, PCI_COMMAND,
|
||||
orig ^ PCI_COMMAND_INTX_DISABLE);
|
||||
|
|
@ -114,7 +115,7 @@ static int __devinit verify_pci_2_3(struct pci_dev *pdev)
|
|||
/* Now restore the original value. */
|
||||
pci_write_config_word(pdev, PCI_COMMAND, orig);
|
||||
err:
|
||||
pci_unblock_user_cfg_access(pdev);
|
||||
pci_cfg_access_unlock(pdev);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue