--- zzzz-none-000/linux-3.10.107/drivers/pci/ats.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/drivers/pci/ats.c 2021-02-04 17:41:59.000000000 +0000 @@ -17,34 +17,15 @@ #include "pci.h" -static int ats_alloc_one(struct pci_dev *dev, int ps) +void pci_ats_init(struct pci_dev *dev) { int pos; - u16 cap; - struct pci_ats *ats; pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ATS); if (!pos) - return -ENODEV; - - ats = kzalloc(sizeof(*ats), GFP_KERNEL); - if (!ats) - return -ENOMEM; - - ats->pos = pos; - ats->stu = ps; - pci_read_config_word(dev, pos + PCI_ATS_CAP, &cap); - ats->qdep = PCI_ATS_CAP_QDEP(cap) ? PCI_ATS_CAP_QDEP(cap) : - PCI_ATS_MAX_QDEP; - dev->ats = ats; + return; - return 0; -} - -static void ats_free_one(struct pci_dev *dev) -{ - kfree(dev->ats); - dev->ats = NULL; + dev->ats_cap = pos; } /** @@ -56,43 +37,36 @@ */ int pci_enable_ats(struct pci_dev *dev, int ps) { - int rc; u16 ctrl; + struct pci_dev *pdev; - BUG_ON(dev->ats && dev->ats->is_enabled); - - if (ps < PCI_ATS_MIN_STU) + if (!dev->ats_cap) return -EINVAL; - if (dev->is_physfn || dev->is_virtfn) { - struct pci_dev *pdev = dev->is_physfn ? dev : dev->physfn; - - mutex_lock(&pdev->sriov->lock); - if (pdev->ats) - rc = pdev->ats->stu == ps ? 0 : -EINVAL; - else - rc = ats_alloc_one(pdev, ps); - - if (!rc) - pdev->ats->ref_cnt++; - mutex_unlock(&pdev->sriov->lock); - if (rc) - return rc; - } + if (WARN_ON(dev->ats_enabled)) + return -EBUSY; - if (!dev->is_physfn) { - rc = ats_alloc_one(dev, ps); - if (rc) - return rc; - } + if (ps < PCI_ATS_MIN_STU) + return -EINVAL; + /* + * Note that enabling ATS on a VF fails unless it's already enabled + * with the same STU on the PF. + */ ctrl = PCI_ATS_CTRL_ENABLE; - if (!dev->is_virtfn) - ctrl |= PCI_ATS_CTRL_STU(ps - PCI_ATS_MIN_STU); - pci_write_config_word(dev, dev->ats->pos + PCI_ATS_CTRL, ctrl); - - dev->ats->is_enabled = 1; + if (dev->is_virtfn) { + pdev = pci_physfn(dev); + if (pdev->ats_stu != ps) + return -EINVAL; + + atomic_inc(&pdev->ats_ref_cnt); /* count enabled VFs */ + } else { + dev->ats_stu = ps; + ctrl |= PCI_ATS_CTRL_STU(dev->ats_stu - PCI_ATS_MIN_STU); + } + pci_write_config_word(dev, dev->ats_cap + PCI_ATS_CTRL, ctrl); + dev->ats_enabled = 1; return 0; } EXPORT_SYMBOL_GPL(pci_enable_ats); @@ -103,28 +77,25 @@ */ void pci_disable_ats(struct pci_dev *dev) { + struct pci_dev *pdev; u16 ctrl; - BUG_ON(!dev->ats || !dev->ats->is_enabled); - - pci_read_config_word(dev, dev->ats->pos + PCI_ATS_CTRL, &ctrl); - ctrl &= ~PCI_ATS_CTRL_ENABLE; - pci_write_config_word(dev, dev->ats->pos + PCI_ATS_CTRL, ctrl); - - dev->ats->is_enabled = 0; + if (WARN_ON(!dev->ats_enabled)) + return; - if (dev->is_physfn || dev->is_virtfn) { - struct pci_dev *pdev = dev->is_physfn ? dev : dev->physfn; + if (atomic_read(&dev->ats_ref_cnt)) + return; /* VFs still enabled */ - mutex_lock(&pdev->sriov->lock); - pdev->ats->ref_cnt--; - if (!pdev->ats->ref_cnt) - ats_free_one(pdev); - mutex_unlock(&pdev->sriov->lock); + if (dev->is_virtfn) { + pdev = pci_physfn(dev); + atomic_dec(&pdev->ats_ref_cnt); } - if (!dev->is_physfn) - ats_free_one(dev); + pci_read_config_word(dev, dev->ats_cap + PCI_ATS_CTRL, &ctrl); + ctrl &= ~PCI_ATS_CTRL_ENABLE; + pci_write_config_word(dev, dev->ats_cap + PCI_ATS_CTRL, ctrl); + + dev->ats_enabled = 0; } EXPORT_SYMBOL_GPL(pci_disable_ats); @@ -132,16 +103,13 @@ { u16 ctrl; - if (!pci_ats_enabled(dev)) + if (!dev->ats_enabled) return; - if (!pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ATS)) - BUG(); ctrl = PCI_ATS_CTRL_ENABLE; if (!dev->is_virtfn) - ctrl |= PCI_ATS_CTRL_STU(dev->ats->stu - PCI_ATS_MIN_STU); - - pci_write_config_word(dev, dev->ats->pos + PCI_ATS_CTRL, ctrl); + ctrl |= PCI_ATS_CTRL_STU(dev->ats_stu - PCI_ATS_MIN_STU); + pci_write_config_word(dev, dev->ats_cap + PCI_ATS_CTRL, ctrl); } EXPORT_SYMBOL_GPL(pci_restore_ats_state); @@ -159,23 +127,16 @@ */ int pci_ats_queue_depth(struct pci_dev *dev) { - int pos; u16 cap; + if (!dev->ats_cap) + return -EINVAL; + if (dev->is_virtfn) return 0; - if (dev->ats) - return dev->ats->qdep; - - pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ATS); - if (!pos) - return -ENODEV; - - pci_read_config_word(dev, pos + PCI_ATS_CAP, &cap); - - return PCI_ATS_CAP_QDEP(cap) ? PCI_ATS_CAP_QDEP(cap) : - PCI_ATS_MAX_QDEP; + pci_read_config_word(dev, dev->ats_cap + PCI_ATS_CAP, &cap); + return PCI_ATS_CAP_QDEP(cap) ? PCI_ATS_CAP_QDEP(cap) : PCI_ATS_MAX_QDEP; } EXPORT_SYMBOL_GPL(pci_ats_queue_depth); @@ -235,27 +196,6 @@ EXPORT_SYMBOL_GPL(pci_disable_pri); /** - * pci_pri_enabled - Checks if PRI capability is enabled - * @pdev: PCI device structure - * - * Returns true if PRI is enabled on the device, false otherwise - */ -bool pci_pri_enabled(struct pci_dev *pdev) -{ - u16 control; - int pos; - - pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI); - if (!pos) - return false; - - pci_read_config_word(pdev, pos + PCI_PRI_CTRL, &control); - - return (control & PCI_PRI_CTRL_ENABLE) ? true : false; -} -EXPORT_SYMBOL_GPL(pci_pri_enabled); - -/** * pci_reset_pri - Resets device's PRI state * @pdev: PCI device structure * @@ -282,67 +222,6 @@ return 0; } EXPORT_SYMBOL_GPL(pci_reset_pri); - -/** - * pci_pri_stopped - Checks whether the PRI capability is stopped - * @pdev: PCI device structure - * - * Returns true if the PRI capability on the device is disabled and the - * device has no outstanding PRI requests, false otherwise. The device - * indicates this via the STOPPED bit in the status register of the - * capability. - * The device internal state can be cleared by resetting the PRI state - * with pci_reset_pri(). This can force the capability into the STOPPED - * state. - */ -bool pci_pri_stopped(struct pci_dev *pdev) -{ - u16 control, status; - int pos; - - pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI); - if (!pos) - return true; - - pci_read_config_word(pdev, pos + PCI_PRI_CTRL, &control); - pci_read_config_word(pdev, pos + PCI_PRI_STATUS, &status); - - if (control & PCI_PRI_CTRL_ENABLE) - return false; - - return (status & PCI_PRI_STATUS_STOPPED) ? true : false; -} -EXPORT_SYMBOL_GPL(pci_pri_stopped); - -/** - * pci_pri_status - Request PRI status of a device - * @pdev: PCI device structure - * - * Returns negative value on failure, status on success. The status can - * be checked against status-bits. Supported bits are currently: - * PCI_PRI_STATUS_RF: Response failure - * PCI_PRI_STATUS_UPRGI: Unexpected Page Request Group Index - * PCI_PRI_STATUS_STOPPED: PRI has stopped - */ -int pci_pri_status(struct pci_dev *pdev) -{ - u16 status, control; - int pos; - - pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI); - if (!pos) - return -EINVAL; - - pci_read_config_word(pdev, pos + PCI_PRI_CTRL, &control); - pci_read_config_word(pdev, pos + PCI_PRI_STATUS, &status); - - /* Stopped bit is undefined when enable == 1, so clear it */ - if (control & PCI_PRI_CTRL_ENABLE) - status &= ~PCI_PRI_STATUS_STOPPED; - - return status; -} -EXPORT_SYMBOL_GPL(pci_pri_status); #endif /* CONFIG_PCI_PRI */ #ifdef CONFIG_PCI_PASID @@ -410,7 +289,7 @@ * Otherwise is returns a bitmask with supported features. Current * features reported are: * PCI_PASID_CAP_EXEC - Execute permission supported - * PCI_PASID_CAP_PRIV - Priviledged mode supported + * PCI_PASID_CAP_PRIV - Privileged mode supported */ int pci_pasid_features(struct pci_dev *pdev) {