[core] refactor unlocked codepath into it's own function

This commit is contained in:
Geoffrey McRae 2020-11-12 08:30:43 +11:00
parent c8d538e68f
commit 4865020e2c
3 changed files with 37 additions and 26 deletions

View File

@ -69,3 +69,31 @@ long vendor_reset_dev_locked(struct vendor_reset_cfg *cfg, struct pci_dev *dev)
return ret; return ret;
} }
long vendor_reset_dev(struct vendor_reset_cfg *cfg, struct pci_dev *dev)
{
int ret;
if (!pci_cfg_access_trylock(dev))
{
pci_warn(dev, "Could not acquire cfg lock\n");
ret = -EAGAIN;
goto err;
}
if (!device_trylock(&dev->dev))
{
pci_warn(dev, "Could not acquire device lock\n");
ret = -EAGAIN;
goto unlock;
}
ret = vendor_reset_dev_locked(cfg, dev);
device_unlock(&dev->dev);
unlock:
pci_cfg_access_unlock(dev);
err:
return ret;
}

View File

@ -63,5 +63,6 @@ struct vendor_reset_cfg * vendor_reset_cfg_find(unsigned int vendor,
/* perform the device reset */ /* perform the device reset */
long vendor_reset_dev_locked(struct vendor_reset_cfg *cfg, struct pci_dev *dev); long vendor_reset_dev_locked(struct vendor_reset_cfg *cfg, struct pci_dev *dev);
long vendor_reset_dev(struct vendor_reset_cfg *cfg, struct pci_dev *dev);
#endif #endif

View File

@ -38,47 +38,29 @@ module_param(install_hook, bool, 0);
static long vendor_reset_ioctl_reset(struct file * filp, unsigned long arg) static long vendor_reset_ioctl_reset(struct file * filp, unsigned long arg)
{ {
struct vendor_reset_ioctl dev; struct vendor_reset_ioctl iodev;
struct vendor_reset_cfg *cfg; struct vendor_reset_cfg *cfg;
struct pci_dev * pcidev; struct pci_dev * dev;
int ret; int ret;
if (copy_from_user(&dev, (void __user *)arg, sizeof(dev))) if (copy_from_user(&iodev, (void __user *)arg, sizeof(iodev)))
return -EFAULT; return -EFAULT;
pcidev = pci_get_domain_bus_and_slot(dev.domain, dev.bus, dev.devfn); dev = pci_get_domain_bus_and_slot(iodev.domain, iodev.bus, iodev.devfn);
if (!pcidev) if (!dev)
return -ENODEV; return -ENODEV;
cfg = vendor_reset_cfg_find(pcidev->vendor, pcidev->device); cfg = vendor_reset_cfg_find(dev->vendor, dev->device);
if (!cfg) if (!cfg)
{ {
ret = -EOPNOTSUPP; ret = -EOPNOTSUPP;
goto err; goto err;
} }
/* we probably always want to lock the device */ ret = vendor_reset_dev(cfg, dev);
if (!pci_cfg_access_trylock(pcidev))
{
pci_warn(pcidev, "Could not acquire cfg lock\n");
ret = -EAGAIN;
goto err;
}
if (!device_trylock(&pcidev->dev))
{
pci_warn(pcidev, "Could not acquire device lock\n");
ret = -EAGAIN;
goto unlock;
}
ret = vendor_reset_dev_locked(cfg, pcidev);
device_unlock(&pcidev->dev);
unlock:
pci_cfg_access_unlock(pcidev);
err: err:
pci_dev_put(pcidev); pci_dev_put(dev);
return ret; return ret;
} }