From 486c79b5002e4a75c1c3614180702196ec6d904d Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 24 Jan 2014 15:25:10 -0700 Subject: ACPI / numa: Fix acpi_get_node() prototype acpi_get_node() takes an acpi_handle, not an "acpi_handle *". This fixes the prototype and the definitions. Signed-off-by: Bjorn Helgaas Acked-by: Rafael J. Wysocki --- include/linux/acpi.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 1151a1dcfe41..17bee650a0cb 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -260,13 +260,13 @@ extern void acpi_osi_setup(char *str); #ifdef CONFIG_ACPI_NUMA int acpi_get_pxm(acpi_handle handle); -int acpi_get_node(acpi_handle *handle); +int acpi_get_node(acpi_handle handle); #else static inline int acpi_get_pxm(acpi_handle handle) { return 0; } -static inline int acpi_get_node(acpi_handle *handle) +static inline int acpi_get_node(acpi_handle handle) { return 0; } -- cgit v1.2.3 From d79ed248d923f219053760376a33371894a6d47c Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 24 Jan 2014 15:48:01 -0700 Subject: ACPI / numa: Make __acpi_map_pxm_to_node(), acpi_get_pxm() static __acpi_map_pxm_to_node() and acpi_get_pxm() are only used within drivers/acpi/numa.c. This makes them static and removes their declarations. Signed-off-by: Bjorn Helgaas Acked-by: Rafael J. Wysocki --- drivers/acpi/numa.c | 4 ++-- include/acpi/acpi_numa.h | 1 - include/linux/acpi.h | 5 ----- 3 files changed, 2 insertions(+), 8 deletions(-) (limited to 'include/linux') diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index a7e779bfa2f6..359a43bdd948 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c @@ -60,7 +60,7 @@ int node_to_pxm(int node) return node_to_pxm_map[node]; } -void __acpi_map_pxm_to_node(int pxm, int node) +static void __acpi_map_pxm_to_node(int pxm, int node) { if (pxm_to_node_map[pxm] == NUMA_NO_NODE || node < pxm_to_node_map[pxm]) pxm_to_node_map[pxm] = node; @@ -314,7 +314,7 @@ int __init acpi_numa_init(void) return 0; } -int acpi_get_pxm(acpi_handle h) +static int acpi_get_pxm(acpi_handle h) { unsigned long long pxm; acpi_status status; diff --git a/include/acpi/acpi_numa.h b/include/acpi/acpi_numa.h index 451823cb8837..94a37cd7fbda 100644 --- a/include/acpi/acpi_numa.h +++ b/include/acpi/acpi_numa.h @@ -13,7 +13,6 @@ extern int pxm_to_node(int); extern int node_to_pxm(int); -extern void __acpi_map_pxm_to_node(int, int); extern int acpi_map_pxm_to_node(int); extern unsigned char acpi_srat_revision; diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 17bee650a0cb..6c29abbefd41 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -259,13 +259,8 @@ extern void acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d); extern void acpi_osi_setup(char *str); #ifdef CONFIG_ACPI_NUMA -int acpi_get_pxm(acpi_handle handle); int acpi_get_node(acpi_handle handle); #else -static inline int acpi_get_pxm(acpi_handle handle) -{ - return 0; -} static inline int acpi_get_node(acpi_handle handle) { return 0; -- cgit v1.2.3 From 2c74424470a0f98df8d6540642aff96d1a0b94b3 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Mon, 3 Feb 2014 14:27:33 -0700 Subject: PCI: Add device-specific PCI ACS enable Some devices support PCI ACS-like features, but don't report it using the standard PCIe capabilities. We already provide hooks for device-specific testing of ACS, but not for device-specific enabling of ACS. This provides that setup hook. Signed-off-by: Alex Williamson Signed-off-by: Bjorn Helgaas --- drivers/pci/pci.c | 26 ++++++++++++++++++++------ drivers/pci/quirks.c | 25 +++++++++++++++++++++++++ include/linux/pci.h | 2 ++ 3 files changed, 47 insertions(+), 6 deletions(-) (limited to 'include/linux') diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 1febe90831b4..b89502ff3139 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -2180,21 +2180,18 @@ void pci_request_acs(void) } /** - * pci_enable_acs - enable ACS if hardware support it + * pci_std_enable_acs - enable ACS on devices using standard ACS capabilites * @dev: the PCI device */ -void pci_enable_acs(struct pci_dev *dev) +static int pci_std_enable_acs(struct pci_dev *dev) { int pos; u16 cap; u16 ctrl; - if (!pci_acs_enable) - return; - pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS); if (!pos) - return; + return -ENODEV; pci_read_config_word(dev, pos + PCI_ACS_CAP, &cap); pci_read_config_word(dev, pos + PCI_ACS_CTRL, &ctrl); @@ -2212,6 +2209,23 @@ void pci_enable_acs(struct pci_dev *dev) ctrl |= (cap & PCI_ACS_UF); pci_write_config_word(dev, pos + PCI_ACS_CTRL, ctrl); + + return 0; +} + +/** + * pci_enable_acs - enable ACS if hardware support it + * @dev: the PCI device + */ +void pci_enable_acs(struct pci_dev *dev) +{ + if (!pci_acs_enable) + return; + + if (!pci_std_enable_acs(dev)) + return; + + pci_dev_specific_enable_acs(dev); } static bool pci_acs_flags_enabled(struct pci_dev *pdev, u16 acs_flags) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 5cb726c193de..f681fb08f5e4 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -3461,3 +3461,28 @@ int pci_dev_specific_acs_enabled(struct pci_dev *dev, u16 acs_flags) return -ENOTTY; } + +static const struct pci_dev_enable_acs { + u16 vendor; + u16 device; + int (*enable_acs)(struct pci_dev *dev); +} pci_dev_enable_acs[] = { + { 0 } +}; + +void pci_dev_specific_enable_acs(struct pci_dev *dev) +{ + const struct pci_dev_enable_acs *i; + int ret; + + for (i = pci_dev_enable_acs; i->enable_acs; i++) { + if ((i->vendor == dev->vendor || + i->vendor == (u16)PCI_ANY_ID) && + (i->device == dev->device || + i->device == (u16)PCI_ANY_ID)) { + ret = i->enable_acs(dev); + if (ret >= 0) + return; + } + } +} diff --git a/include/linux/pci.h b/include/linux/pci.h index fb57c892b214..0f76d0f66365 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1510,6 +1510,7 @@ enum pci_fixup_pass { void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev); struct pci_dev *pci_get_dma_source(struct pci_dev *dev); int pci_dev_specific_acs_enabled(struct pci_dev *dev, u16 acs_flags); +void pci_dev_specific_enable_acs(struct pci_dev *dev); #else static inline void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev) { } @@ -1522,6 +1523,7 @@ static inline int pci_dev_specific_acs_enabled(struct pci_dev *dev, { return -ENOTTY; } +static inline void pci_dev_specific_enable_acs(struct pci_dev *dev) { } #endif void __iomem *pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen); -- cgit v1.2.3 From 5757a769ea4e094df6ec92d9ce7d05a90d5bf3e6 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Mon, 3 Feb 2014 14:27:39 -0700 Subject: PCI: Add pci_dev_flag for ACS enable quirks Quirks that enable ACS-compatible functionality on a device need some way to track whether a given device has been enabled. Rather than create new data structures for this, allocate one of the pci_dev_flags to indicate this setup. Signed-off-by: Alex Williamson Signed-off-by: Bjorn Helgaas --- include/linux/pci.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/linux') diff --git a/include/linux/pci.h b/include/linux/pci.h index 0f76d0f66365..60ab8d782f8c 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -170,6 +170,8 @@ enum pci_dev_flags { PCI_DEV_FLAGS_NO_D3 = (__force pci_dev_flags_t) 2, /* Provide indication device is assigned by a Virtual Machine Manager */ PCI_DEV_FLAGS_ASSIGNED = (__force pci_dev_flags_t) 4, + /* Flag for quirk use to store if quirk-specific ACS is enabled */ + PCI_DEV_FLAGS_ACS_ENABLED_QUIRK = (__force pci_dev_flags_t) 8, }; enum pci_irq_reroute_variant { -- cgit v1.2.3 From f7fc32cb2073902b3ee67d036656889ea75ffcb7 Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Thu, 13 Feb 2014 15:25:02 +0100 Subject: PCI/MSI: Add pci_enable_msi_exact() and pci_enable_msix_exact() The new functions are special cases for pci_enable_msi_range() and pci_enable_msix_range() when a particular number of MSI or MSI-X is needed. By contrast with pci_enable_msi_range() and pci_enable_msix_range() functions, pci_enable_msi_exact() and pci_enable_msix_exact() return zero in case of success, which indicates MSI or MSI-X interrupts have been successfully allocated. Signed-off-by: Alexander Gordeev Signed-off-by: Bjorn Helgaas --- Documentation/PCI/MSI-HOWTO.txt | 86 ++++++++++++++++++++++++++++++++++++++++- include/linux/pci.h | 20 ++++++++++ 2 files changed, 104 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/Documentation/PCI/MSI-HOWTO.txt b/Documentation/PCI/MSI-HOWTO.txt index 96ee5eb9d4d4..10a93696e55a 100644 --- a/Documentation/PCI/MSI-HOWTO.txt +++ b/Documentation/PCI/MSI-HOWTO.txt @@ -159,6 +159,11 @@ static int foo_driver_enable_msi(struct pci_dev *pdev, int nvec) return pci_enable_msi_range(pdev, nvec, nvec); } +Note, unlike pci_enable_msi_exact() function, which could be also used to +enable a particular number of MSI-X interrupts, pci_enable_msi_range() +returns either a negative errno or 'nvec' (not negative errno or 0 - as +pci_enable_msi_exact() does). + 4.2.1.3 Single MSI mode The most notorious example of the request type described above is @@ -175,7 +180,22 @@ enable the single MSI mode, pci_enable_msi_range() returns either a negative errno or 1 (not negative errno or 0 - as pci_enable_msi() does). -4.2.3 pci_disable_msi +4.2.3 pci_enable_msi_exact + +int pci_enable_msi_exact(struct pci_dev *dev, int nvec) + +This variation on pci_enable_msi_range() call allows a device driver to +request exactly 'nvec' MSIs. + +If this function returns a negative number, it indicates an error and +the driver should not attempt to request any more MSI interrupts for +this device. + +By contrast with pci_enable_msi_range() function, pci_enable_msi_exact() +returns zero in case of success, which indicates MSI interrupts have been +successfully allocated. + +4.2.4 pci_disable_msi void pci_disable_msi(struct pci_dev *dev) @@ -303,6 +323,11 @@ static int foo_driver_enable_msix(struct foo_adapter *adapter, int nvec) nvec, nvec); } +Note, unlike pci_enable_msix_exact() function, which could be also used to +enable a particular number of MSI-X interrupts, pci_enable_msix_range() +returns either a negative errno or 'nvec' (not negative errno or 0 - as +pci_enable_msix_exact() does). + 4.3.1.3 Specific requirements to the number of MSI-X interrupts As noted above, there could be devices that can not operate with just any @@ -349,7 +374,64 @@ Note how pci_enable_msix_range() return value is analized for a fallback - any error code other than -ENOSPC indicates a fatal error and should not be retried. -4.3.2 pci_disable_msix +4.3.2 pci_enable_msix_exact + +int pci_enable_msix_exact(struct pci_dev *dev, + struct msix_entry *entries, int nvec) + +This variation on pci_enable_msix_range() call allows a device driver to +request exactly 'nvec' MSI-Xs. + +If this function returns a negative number, it indicates an error and +the driver should not attempt to allocate any more MSI-X interrupts for +this device. + +By contrast with pci_enable_msix_range() function, pci_enable_msix_exact() +returns zero in case of success, which indicates MSI-X interrupts have been +successfully allocated. + +Another version of a routine that enables MSI-X mode for a device with +specific requirements described in chapter 4.3.1.3 might look like this: + +/* + * Assume 'minvec' and 'maxvec' are non-zero + */ +static int foo_driver_enable_msix(struct foo_adapter *adapter, + int minvec, int maxvec) +{ + int rc; + + minvec = roundup_pow_of_two(minvec); + maxvec = rounddown_pow_of_two(maxvec); + + if (minvec > maxvec) + return -ERANGE; + +retry: + rc = pci_enable_msix_exact(adapter->pdev, + adapter->msix_entries, maxvec); + + /* + * -ENOSPC is the only error code allowed to be analyzed + */ + if (rc == -ENOSPC) { + if (maxvec == 1) + return -ENOSPC; + + maxvec /= 2; + + if (minvec > maxvec) + return -ENOSPC; + + goto retry; + } else if (rc < 0) { + return rc; + } + + return maxvec; +} + +4.3.3 pci_disable_msix void pci_disable_msix(struct pci_dev *dev) diff --git a/include/linux/pci.h b/include/linux/pci.h index fb57c892b214..33aa2caf0f0c 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1169,8 +1169,23 @@ void msi_remove_pci_irq_vectors(struct pci_dev *dev); void pci_restore_msi_state(struct pci_dev *dev); int pci_msi_enabled(void); int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec); +static inline int pci_enable_msi_exact(struct pci_dev *dev, int nvec) +{ + int rc = pci_enable_msi_range(dev, nvec, nvec); + if (rc < 0) + return rc; + return 0; +} int pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries, int minvec, int maxvec); +static inline int pci_enable_msix_exact(struct pci_dev *dev, + struct msix_entry *entries, int nvec) +{ + int rc = pci_enable_msix_range(dev, entries, nvec, nvec); + if (rc < 0) + return rc; + return 0; +} #else static inline int pci_msi_vec_count(struct pci_dev *dev) { return -ENOSYS; } static inline int pci_enable_msi_block(struct pci_dev *dev, int nvec) @@ -1189,9 +1204,14 @@ static inline int pci_msi_enabled(void) { return 0; } static inline int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec) { return -ENOSYS; } +static inline int pci_enable_msi_exact(struct pci_dev *dev, int nvec) +{ return -ENOSYS; } static inline int pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries, int minvec, int maxvec) { return -ENOSYS; } +static inline int pci_enable_msix_exact(struct pci_dev *dev, + struct msix_entry *entries, int nvec) +{ return -ENOSYS; } #endif #ifdef CONFIG_PCIEPORTBUS -- cgit v1.2.3 From 94e6a9b93064b49024b8701d2d81fcb4a821fa09 Mon Sep 17 00:00:00 2001 From: Yijing Wang Date: Thu, 13 Feb 2014 21:14:03 +0800 Subject: PCI: Remove pci_bus_b() and use list_for_each_entry() directly Replace list_for_each() with list_for_each_entry(), which means we no longer need pci_bus_b() and can remove it. Signed-off-by: Yijing Wang Signed-off-by: Bjorn Helgaas --- drivers/pci/pci.c | 6 +++--- drivers/pci/search.c | 10 +++++----- include/linux/pci.h | 1 - 3 files changed, 8 insertions(+), 9 deletions(-) (limited to 'include/linux') diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 1febe90831b4..6f5ed88ca126 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -108,12 +108,12 @@ static bool pcie_ari_disabled; */ unsigned char pci_bus_max_busnr(struct pci_bus* bus) { - struct list_head *tmp; + struct pci_bus *tmp; unsigned char max, n; max = bus->busn_res.end; - list_for_each(tmp, &bus->children) { - n = pci_bus_max_busnr(pci_bus_b(tmp)); + list_for_each_entry(tmp, &bus->children, node) { + n = pci_bus_max_busnr(tmp); if(n > max) max = n; } diff --git a/drivers/pci/search.c b/drivers/pci/search.c index 3ff2ac7c14e2..4a1b972efe7f 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c @@ -54,14 +54,14 @@ pci_find_upstream_pcie_bridge(struct pci_dev *pdev) static struct pci_bus *pci_do_find_bus(struct pci_bus *bus, unsigned char busnr) { - struct pci_bus* child; - struct list_head *tmp; + struct pci_bus *child; + struct pci_bus *tmp; if(bus->number == busnr) return bus; - list_for_each(tmp, &bus->children) { - child = pci_do_find_bus(pci_bus_b(tmp), busnr); + list_for_each_entry(tmp, &bus->children, node) { + child = pci_do_find_bus(tmp, busnr); if(child) return child; } @@ -111,7 +111,7 @@ pci_find_next_bus(const struct pci_bus *from) down_read(&pci_bus_sem); n = from ? from->node.next : pci_root_buses.next; if (n != &pci_root_buses) - b = pci_bus_b(n); + b = list_entry(n, struct pci_bus, node); up_read(&pci_bus_sem); return b; } diff --git a/include/linux/pci.h b/include/linux/pci.h index fb57c892b214..e1b5752f3b1b 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -461,7 +461,6 @@ struct pci_bus { unsigned int is_added:1; }; -#define pci_bus_b(n) list_entry(n, struct pci_bus, node) #define to_pci_bus(n) container_of(n, struct pci_bus, dev) /* -- cgit v1.2.3 From 46cb7b1bd86fc227a5325ba8fa4c8be70fade4e8 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 30 Jan 2014 11:28:15 -0700 Subject: PCI: Remove unused SR-IOV VF Migration support This reverts commit 74bb1bcc7dbb ("PCI: handle SR-IOV Virtual Function Migration"), removing this exported interface: pci_sriov_migration() Since pci_sriov_migration() is unused, it is impossible to schedule sriov_migration_task() or use any of the other migration infrastructure. This is based on Stephen Hemminger's patch (see link below), but goes a bit further. Link: http://lkml.kernel.org/r/20131227132710.7190647c@nehalam.linuxnetplumber.net Signed-off-by: Bjorn Helgaas CC: Stephen Hemminger --- Documentation/PCI/pci-iov-howto.txt | 4 -- drivers/pci/iov.c | 119 ------------------------------------ drivers/pci/pci.h | 4 -- include/linux/pci.h | 4 -- 4 files changed, 131 deletions(-) (limited to 'include/linux') diff --git a/Documentation/PCI/pci-iov-howto.txt b/Documentation/PCI/pci-iov-howto.txt index 86551cc72e03..2d91ae251982 100644 --- a/Documentation/PCI/pci-iov-howto.txt +++ b/Documentation/PCI/pci-iov-howto.txt @@ -68,10 +68,6 @@ To disable SR-IOV capability: echo 0 > \ /sys/bus/pci/devices//sriov_numvfs -To notify SR-IOV core of Virtual Function Migration: -(a) In the driver: - irqreturn_t pci_sriov_migration(struct pci_dev *dev); - 3.2 Usage example Following piece of code illustrates the usage of the SR-IOV API. diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c index 9dce7c5e2a77..de7a74782f92 100644 --- a/drivers/pci/iov.c +++ b/drivers/pci/iov.c @@ -170,97 +170,6 @@ static void virtfn_remove(struct pci_dev *dev, int id, int reset) pci_dev_put(dev); } -static int sriov_migration(struct pci_dev *dev) -{ - u16 status; - struct pci_sriov *iov = dev->sriov; - - if (!iov->num_VFs) - return 0; - - if (!(iov->cap & PCI_SRIOV_CAP_VFM)) - return 0; - - pci_read_config_word(dev, iov->pos + PCI_SRIOV_STATUS, &status); - if (!(status & PCI_SRIOV_STATUS_VFM)) - return 0; - - schedule_work(&iov->mtask); - - return 1; -} - -static void sriov_migration_task(struct work_struct *work) -{ - int i; - u8 state; - u16 status; - struct pci_sriov *iov = container_of(work, struct pci_sriov, mtask); - - for (i = iov->initial_VFs; i < iov->num_VFs; i++) { - state = readb(iov->mstate + i); - if (state == PCI_SRIOV_VFM_MI) { - writeb(PCI_SRIOV_VFM_AV, iov->mstate + i); - state = readb(iov->mstate + i); - if (state == PCI_SRIOV_VFM_AV) - virtfn_add(iov->self, i, 1); - } else if (state == PCI_SRIOV_VFM_MO) { - virtfn_remove(iov->self, i, 1); - writeb(PCI_SRIOV_VFM_UA, iov->mstate + i); - state = readb(iov->mstate + i); - if (state == PCI_SRIOV_VFM_AV) - virtfn_add(iov->self, i, 0); - } - } - - pci_read_config_word(iov->self, iov->pos + PCI_SRIOV_STATUS, &status); - status &= ~PCI_SRIOV_STATUS_VFM; - pci_write_config_word(iov->self, iov->pos + PCI_SRIOV_STATUS, status); -} - -static int sriov_enable_migration(struct pci_dev *dev, int nr_virtfn) -{ - int bir; - u32 table; - resource_size_t pa; - struct pci_sriov *iov = dev->sriov; - - if (nr_virtfn <= iov->initial_VFs) - return 0; - - pci_read_config_dword(dev, iov->pos + PCI_SRIOV_VFM, &table); - bir = PCI_SRIOV_VFM_BIR(table); - if (bir > PCI_STD_RESOURCE_END) - return -EIO; - - table = PCI_SRIOV_VFM_OFFSET(table); - if (table + nr_virtfn > pci_resource_len(dev, bir)) - return -EIO; - - pa = pci_resource_start(dev, bir) + table; - iov->mstate = ioremap(pa, nr_virtfn); - if (!iov->mstate) - return -ENOMEM; - - INIT_WORK(&iov->mtask, sriov_migration_task); - - iov->ctrl |= PCI_SRIOV_CTRL_VFM | PCI_SRIOV_CTRL_INTR; - pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl); - - return 0; -} - -static void sriov_disable_migration(struct pci_dev *dev) -{ - struct pci_sriov *iov = dev->sriov; - - iov->ctrl &= ~(PCI_SRIOV_CTRL_VFM | PCI_SRIOV_CTRL_INTR); - pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl); - - cancel_work_sync(&iov->mtask); - iounmap(iov->mstate); -} - static int sriov_enable(struct pci_dev *dev, int nr_virtfn) { int rc; @@ -351,12 +260,6 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn) goto failed; } - if (iov->cap & PCI_SRIOV_CAP_VFM) { - rc = sriov_enable_migration(dev, nr_virtfn); - if (rc) - goto failed; - } - kobject_uevent(&dev->dev.kobj, KOBJ_CHANGE); iov->num_VFs = nr_virtfn; @@ -387,9 +290,6 @@ static void sriov_disable(struct pci_dev *dev) if (!iov->num_VFs) return; - if (iov->cap & PCI_SRIOV_CAP_VFM) - sriov_disable_migration(dev); - for (i = 0; i < iov->num_VFs; i++) virtfn_remove(dev, i, 0); @@ -687,25 +587,6 @@ void pci_disable_sriov(struct pci_dev *dev) } EXPORT_SYMBOL_GPL(pci_disable_sriov); -/** - * pci_sriov_migration - notify SR-IOV core of Virtual Function Migration - * @dev: the PCI device - * - * Returns IRQ_HANDLED if the IRQ is handled, or IRQ_NONE if not. - * - * Physical Function driver is responsible to register IRQ handler using - * VF Migration Interrupt Message Number, and call this function when the - * interrupt is generated by the hardware. - */ -irqreturn_t pci_sriov_migration(struct pci_dev *dev) -{ - if (!dev->is_physfn) - return IRQ_NONE; - - return sriov_migration(dev) ? IRQ_HANDLED : IRQ_NONE; -} -EXPORT_SYMBOL_GPL(pci_sriov_migration); - /** * pci_num_vf - return number of VFs associated with a PF device_release_driver * @dev: the PCI device diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 4df38df224f4..6bd082299e31 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -1,8 +1,6 @@ #ifndef DRIVERS_PCI_H #define DRIVERS_PCI_H -#include - #define PCI_CFG_SPACE_SIZE 256 #define PCI_CFG_SPACE_EXP_SIZE 4096 @@ -240,8 +238,6 @@ struct pci_sriov { struct pci_dev *dev; /* lowest numbered PF */ struct pci_dev *self; /* this PF */ struct mutex lock; /* lock for VF bus */ - struct work_struct mtask; /* VF Migration task */ - u8 __iomem *mstate; /* VF Migration State Array */ }; #ifdef CONFIG_PCI_ATS diff --git a/include/linux/pci.h b/include/linux/pci.h index fb57c892b214..230a8dabc5a3 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -29,7 +29,6 @@ #include #include #include -#include #include #include @@ -1577,7 +1576,6 @@ void __iomem *pci_ioremap_bar(struct pci_dev *pdev, int bar); #ifdef CONFIG_PCI_IOV int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn); void pci_disable_sriov(struct pci_dev *dev); -irqreturn_t pci_sriov_migration(struct pci_dev *dev); int pci_num_vf(struct pci_dev *dev); int pci_vfs_assigned(struct pci_dev *dev); int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs); @@ -1586,8 +1584,6 @@ int pci_sriov_get_totalvfs(struct pci_dev *dev); static inline int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn) { return -ENODEV; } static inline void pci_disable_sriov(struct pci_dev *dev) { } -static inline irqreturn_t pci_sriov_migration(struct pci_dev *dev) -{ return IRQ_NONE; } static inline int pci_num_vf(struct pci_dev *dev) { return 0; } static inline int pci_vfs_assigned(struct pci_dev *dev) { return 0; } -- cgit v1.2.3 From 5edb93b89f6cc3089ee283656555e7a9ad36a8a0 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 4 Feb 2014 19:32:28 -0800 Subject: resource: Add resource_contains() We have two identical copies of resource_contains() already, and more places that could use it. This moves it to ioport.h where it can be shared. resource_contains(struct resource *r1, struct resource *r2) returns true iff r1 and r2 are the same type (most callers already checked this separately) and the r1 address range completely contains r2. In addition, the new resource_contains() checks that both r1 and r2 have addresses assigned to them. If a resource is IORESOURCE_UNSET, it doesn't have a valid address and can't contain or be contained by another resource. Some callers already check this or for res->start. No functional change. Signed-off-by: Bjorn Helgaas --- drivers/pci/host-bridge.c | 8 -------- include/linux/ioport.h | 10 ++++++++++ kernel/resource.c | 8 ++------ 3 files changed, 12 insertions(+), 14 deletions(-) (limited to 'include/linux') diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c index 06ace6248c61..47aaf22d814e 100644 --- a/drivers/pci/host-bridge.c +++ b/drivers/pci/host-bridge.c @@ -32,11 +32,6 @@ void pci_set_host_bridge_release(struct pci_host_bridge *bridge, bridge->release_data = release_data; } -static bool resource_contains(struct resource *res1, struct resource *res2) -{ - return res1->start <= res2->start && res1->end >= res2->end; -} - void pcibios_resource_to_bus(struct pci_bus *bus, struct pci_bus_region *region, struct resource *res) { @@ -45,9 +40,6 @@ void pcibios_resource_to_bus(struct pci_bus *bus, struct pci_bus_region *region, resource_size_t offset = 0; list_for_each_entry(window, &bridge->windows, list) { - if (resource_type(res) != resource_type(window->res)) - continue; - if (resource_contains(window->res, res)) { offset = window->offset; break; diff --git a/include/linux/ioport.h b/include/linux/ioport.h index 89b7c24a36e9..9fcaac8bc4f6 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h @@ -169,6 +169,16 @@ static inline unsigned long resource_type(const struct resource *res) { return res->flags & IORESOURCE_TYPE_BITS; } +/* True iff r1 completely contains r2 */ +static inline bool resource_contains(struct resource *r1, struct resource *r2) +{ + if (resource_type(r1) != resource_type(r2)) + return false; + if (r1->flags & IORESOURCE_UNSET || r2->flags & IORESOURCE_UNSET) + return false; + return r1->start <= r2->start && r1->end >= r2->end; +} + /* Convenience shorthand with allocation */ #define request_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name), 0) diff --git a/kernel/resource.c b/kernel/resource.c index 3f285dce9347..a8344dda7049 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -432,11 +432,6 @@ static void resource_clip(struct resource *res, resource_size_t min, res->end = max; } -static bool resource_contains(struct resource *res1, struct resource *res2) -{ - return res1->start <= res2->start && res1->end >= res2->end; -} - /* * Find empty slot in the resource tree with the given range and * alignment constraints @@ -471,10 +466,11 @@ static int __find_resource(struct resource *root, struct resource *old, arch_remove_reservations(&tmp); /* Check for overflow after ALIGN() */ - avail = *new; avail.start = ALIGN(tmp.start, constraint->align); avail.end = tmp.end; + avail.flags = new->flags & ~IORESOURCE_UNSET; if (avail.start >= tmp.start) { + alloc.flags = avail.flags; alloc.start = constraint->alignf(constraint->alignf_data, &avail, size, constraint->align); alloc.end = alloc.start + size - 1; -- cgit v1.2.3 From d19cb803a2ff85d1b64b9628e1aec2aa76a9260b Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 26 Feb 2014 11:25:56 -0700 Subject: vsprintf: Add support for IORESOURCE_UNSET in %pR Sometimes we have a struct resource where we know the type (MEM/IO/etc.) and the size, but we haven't assigned address space for it. The IORESOURCE_UNSET flag is a way to indicate this situation. For these "unset" resources, the start address is meaningless, so print only the size, e.g., - pci 0000:0c:00.0: reg 184: [mem 0x00000000-0x00001fff 64bit] + pci 0000:0c:00.0: reg 184: [mem size 0x2000 64bit] For %pr (printing with raw flags), we still print the address range, because %pr is mostly used for debugging anyway. Thanks to Fengguang Wu for suggesting resource_size(). Signed-off-by: Bjorn Helgaas --- include/linux/ioport.h | 2 +- lib/vsprintf.c | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) (limited to 'include/linux') diff --git a/include/linux/ioport.h b/include/linux/ioport.h index 9fcaac8bc4f6..5e3a906cc089 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h @@ -51,7 +51,7 @@ struct resource { #define IORESOURCE_EXCLUSIVE 0x08000000 /* Userland may not map this resource */ #define IORESOURCE_DISABLED 0x10000000 -#define IORESOURCE_UNSET 0x20000000 +#define IORESOURCE_UNSET 0x20000000 /* No address assigned yet */ #define IORESOURCE_AUTO 0x40000000 #define IORESOURCE_BUSY 0x80000000 /* Driver has marked this resource busy */ diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 185b6d300ebc..5e2cf6f342f8 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -719,10 +719,15 @@ char *resource_string(char *buf, char *end, struct resource *res, specp = &mem_spec; decode = 0; } - p = number(p, pend, res->start, *specp); - if (res->start != res->end) { - *p++ = '-'; - p = number(p, pend, res->end, *specp); + if (decode && res->flags & IORESOURCE_UNSET) { + p = string(p, pend, "size ", str_spec); + p = number(p, pend, resource_size(res), *specp); + } else { + p = number(p, pend, res->start, *specp); + if (res->start != res->end) { + *p++ = '-'; + p = number(p, pend, res->end, *specp); + } } if (decode) { if (res->flags & IORESOURCE_MEM_64) -- cgit v1.2.3 From 664c28480c90fb8541bcdd1d4b349e9436165ec7 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 7 Mar 2014 13:51:12 -0700 Subject: PCI: Change pci_bus_alloc_resource() type_mask to unsigned long The pci_bus_alloc_resource() "type_mask" parameter is used to compare with the "flags" member of a struct resource, so it should be the same type, namely "unsigned long". No functional change because all current IORESOURCE_* flags fit in 32 bits. Signed-off-by: Bjorn Helgaas --- drivers/pci/bus.c | 4 ++-- include/linux/pci.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index e3bdc88668ec..fb8aed307c28 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -132,7 +132,7 @@ static void pci_clip_resource_to_region(struct pci_bus *bus, static int pci_bus_alloc_from_region(struct pci_bus *bus, struct resource *res, resource_size_t size, resource_size_t align, - resource_size_t min, unsigned int type_mask, + resource_size_t min, unsigned long type_mask, resource_size_t (*alignf)(void *, const struct resource *, resource_size_t, @@ -200,7 +200,7 @@ static int pci_bus_alloc_from_region(struct pci_bus *bus, struct resource *res, */ int pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, resource_size_t size, resource_size_t align, - resource_size_t min, unsigned int type_mask, + resource_size_t min, unsigned long type_mask, resource_size_t (*alignf)(void *, const struct resource *, resource_size_t, diff --git a/include/linux/pci.h b/include/linux/pci.h index fb57c892b214..60ebc17fe909 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1066,7 +1066,7 @@ void pci_bus_remove_resources(struct pci_bus *bus); int __must_check pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, resource_size_t size, resource_size_t align, resource_size_t min, - unsigned int type_mask, + unsigned long type_mask, resource_size_t (*alignf)(void *, const struct resource *, resource_size_t, -- cgit v1.2.3