Merge branch 'pci/msi' into next
authorBjorn Helgaas <bhelgaas@google.com>
Wed, 8 Jan 2014 00:34:39 +0000 (17:34 -0700)
committerBjorn Helgaas <bhelgaas@google.com>
Wed, 8 Jan 2014 00:34:39 +0000 (17:34 -0700)
* pci/msi:
  PCI/MSI: Add pci_enable_msi_range() and pci_enable_msix_range()
  PCI/MSI: Add pci_msix_vec_count()
  PCI/MSI: Remove pci_enable_msi_block_auto()
  PCI/MSI: Add pci_msi_vec_count()

1  2 
drivers/pci/msi.c
drivers/pci/pcie/portdrv_core.c
include/linux/pci.h

diff --combined drivers/pci/msi.c
index 22957aa51edc4b2a26852cfac15d796b8fc1203e,e6bd8e57d92d81fd4047702dc05d2ea39751c86b..7a0fec6ce5717baac5ef564c743d129cbc03a892
@@@ -116,7 -116,7 +116,7 @@@ void __weak arch_teardown_msi_irqs(stru
        return default_teardown_msi_irqs(dev);
  }
  
 -void default_restore_msi_irqs(struct pci_dev *dev, int irq)
 +static void default_restore_msi_irq(struct pci_dev *dev, int irq)
  {
        struct msi_desc *entry;
  
                write_msi_msg(irq, &entry->msg);
  }
  
 -void __weak arch_restore_msi_irqs(struct pci_dev *dev, int irq)
 +void __weak arch_restore_msi_irqs(struct pci_dev *dev)
  {
 -      return default_restore_msi_irqs(dev, irq);
 +      return default_restore_msi_irqs(dev);
  }
  
  static void msi_set_enable(struct pci_dev *dev, int enable)
@@@ -262,15 -262,6 +262,15 @@@ void unmask_msi_irq(struct irq_data *da
        msi_set_mask_bit(data, 0);
  }
  
 +void default_restore_msi_irqs(struct pci_dev *dev)
 +{
 +      struct msi_desc *entry;
 +
 +      list_for_each_entry(entry, &dev->msi_list, list) {
 +              default_restore_msi_irq(dev, entry->irq);
 +      }
 +}
 +
  void __read_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
  {
        BUG_ON(entry->dev->current_state != PCI_D0);
@@@ -458,7 -449,7 +458,7 @@@ static void __pci_restore_msi_state(str
  
        pci_intx_for_msi(dev, 0);
        msi_set_enable(dev, 0);
 -      arch_restore_msi_irqs(dev, dev->irq);
 +      arch_restore_msi_irqs(dev);
  
        pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control);
        msi_mask_irq(entry, msi_capable_mask(control), entry->masked);
@@@ -483,8 -474,8 +483,8 @@@ static void __pci_restore_msix_state(st
        control |= PCI_MSIX_FLAGS_ENABLE | PCI_MSIX_FLAGS_MASKALL;
        pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control);
  
 +      arch_restore_msi_irqs(dev);
        list_for_each_entry(entry, &dev->msi_list, list) {
 -              arch_restore_msi_irqs(dev, entry->irq);
                msix_mask_irq(entry, entry->masked);
        }
  
@@@ -851,6 -842,31 +851,31 @@@ static int pci_msi_check_device(struct 
        return 0;
  }
  
+ /**
+  * pci_msi_vec_count - Return the number of MSI vectors a device can send
+  * @dev: device to report about
+  *
+  * This function returns the number of MSI vectors a device requested via
+  * Multiple Message Capable register. It returns a negative errno if the
+  * device is not capable sending MSI interrupts. Otherwise, the call succeeds
+  * and returns a power of two, up to a maximum of 2^5 (32), according to the
+  * MSI specification.
+  **/
+ int pci_msi_vec_count(struct pci_dev *dev)
+ {
+       int ret;
+       u16 msgctl;
+       if (!dev->msi_cap)
+               return -EINVAL;
+       pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &msgctl);
+       ret = 1 << ((msgctl & PCI_MSI_FLAGS_QMASK) >> 1);
+       return ret;
+ }
+ EXPORT_SYMBOL(pci_msi_vec_count);
  /**
   * pci_enable_msi_block - configure device's MSI capability structure
   * @dev: device to configure
  int pci_enable_msi_block(struct pci_dev *dev, int nvec)
  {
        int status, maxvec;
-       u16 msgctl;
  
-       if (!dev->msi_cap || dev->current_state != PCI_D0)
+       if (dev->current_state != PCI_D0)
                return -EINVAL;
  
-       pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &msgctl);
-       maxvec = 1 << ((msgctl & PCI_MSI_FLAGS_QMASK) >> 1);
+       maxvec = pci_msi_vec_count(dev);
+       if (maxvec < 0)
+               return maxvec;
        if (nvec > maxvec)
                return maxvec;
  
  }
  EXPORT_SYMBOL(pci_enable_msi_block);
  
- int pci_enable_msi_block_auto(struct pci_dev *dev, int *maxvec)
- {
-       int ret, nvec;
-       u16 msgctl;
-       if (!dev->msi_cap || dev->current_state != PCI_D0)
-               return -EINVAL;
-       pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &msgctl);
-       ret = 1 << ((msgctl & PCI_MSI_FLAGS_QMASK) >> 1);
-       if (maxvec)
-               *maxvec = ret;
-       do {
-               nvec = ret;
-               ret = pci_enable_msi_block(dev, nvec);
-       } while (ret > 0);
-       if (ret < 0)
-               return ret;
-       return nvec;
- }
- EXPORT_SYMBOL(pci_enable_msi_block_auto);
  void pci_msi_shutdown(struct pci_dev *dev)
  {
        struct msi_desc *desc;
@@@ -957,19 -948,25 +957,25 @@@ void pci_disable_msi(struct pci_dev *de
  EXPORT_SYMBOL(pci_disable_msi);
  
  /**
-  * pci_msix_table_size - return the number of device's MSI-X table entries
+  * pci_msix_vec_count - return the number of device's MSI-X table entries
   * @dev: pointer to the pci_dev data structure of MSI-X device function
-  */
- int pci_msix_table_size(struct pci_dev *dev)
+  * This function returns the number of device's MSI-X table entries and
+  * therefore the number of MSI-X vectors device is capable of sending.
+  * It returns a negative errno if the device is not capable of sending MSI-X
+  * interrupts.
+  **/
+ int pci_msix_vec_count(struct pci_dev *dev)
  {
        u16 control;
  
        if (!dev->msix_cap)
-               return 0;
+               return -EINVAL;
  
        pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control);
        return msix_table_size(control);
  }
+ EXPORT_SYMBOL(pci_msix_vec_count);
  
  /**
   * pci_enable_msix - configure device's MSI-X capability structure
@@@ -998,7 -995,9 +1004,9 @@@ int pci_enable_msix(struct pci_dev *dev
        if (status)
                return status;
  
-       nr_entries = pci_msix_table_size(dev);
+       nr_entries = pci_msix_vec_count(dev);
+       if (nr_entries < 0)
+               return nr_entries;
        if (nvec > nr_entries)
                return nr_entries;
  
@@@ -1103,3 -1102,77 +1111,77 @@@ void pci_msi_init_pci_dev(struct pci_de
        if (dev->msix_cap)
                msix_set_enable(dev, 0);
  }
+ /**
+  * pci_enable_msi_range - configure device's MSI capability structure
+  * @dev: device to configure
+  * @minvec: minimal number of interrupts to configure
+  * @maxvec: maximum number of interrupts to configure
+  *
+  * This function tries to allocate a maximum possible number of interrupts in a
+  * range between @minvec and @maxvec. It returns a negative errno if an error
+  * occurs. If it succeeds, it returns the actual number of interrupts allocated
+  * and updates the @dev's irq member to the lowest new interrupt number;
+  * the other interrupt numbers allocated to this device are consecutive.
+  **/
+ int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec)
+ {
+       int nvec = maxvec;
+       int rc;
+       if (maxvec < minvec)
+               return -ERANGE;
+       do {
+               rc = pci_enable_msi_block(dev, nvec);
+               if (rc < 0) {
+                       return rc;
+               } else if (rc > 0) {
+                       if (rc < minvec)
+                               return -ENOSPC;
+                       nvec = rc;
+               }
+       } while (rc);
+       return nvec;
+ }
+ EXPORT_SYMBOL(pci_enable_msi_range);
+ /**
+  * pci_enable_msix_range - configure device's MSI-X capability structure
+  * @dev: pointer to the pci_dev data structure of MSI-X device function
+  * @entries: pointer to an array of MSI-X entries
+  * @minvec: minimum number of MSI-X irqs requested
+  * @maxvec: maximum number of MSI-X irqs requested
+  *
+  * Setup the MSI-X capability structure of device function with a maximum
+  * possible number of interrupts in the range between @minvec and @maxvec
+  * upon its software driver call to request for MSI-X mode enabled on its
+  * hardware device function. It returns a negative errno if an error occurs.
+  * If it succeeds, it returns the actual number of interrupts allocated and
+  * indicates the successful configuration of MSI-X capability structure
+  * with new allocated MSI-X interrupts.
+  **/
+ int pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries,
+                              int minvec, int maxvec)
+ {
+       int nvec = maxvec;
+       int rc;
+       if (maxvec < minvec)
+               return -ERANGE;
+       do {
+               rc = pci_enable_msix(dev, entries, nvec);
+               if (rc < 0) {
+                       return rc;
+               } else if (rc > 0) {
+                       if (rc < minvec)
+                               return -ENOSPC;
+                       nvec = rc;
+               }
+       } while (rc);
+       return nvec;
+ }
+ EXPORT_SYMBOL(pci_enable_msix_range);
index 16a1ce4f6b18b3f323b785f261afc4d5ee136c81,4ab719826dd70e3d4f36550746252d48d99f5fde..986f8eadfd39397aff7d38c71452d86b3e6fa530
@@@ -79,9 -79,10 +79,10 @@@ static int pcie_port_enable_msix(struc
        u16 reg16;
        u32 reg32;
  
-       nr_entries = pci_msix_table_size(dev);
-       if (!nr_entries)
-               return -EINVAL;
+       nr_entries = pci_msix_vec_count(dev);
+       if (nr_entries < 0)
+               return nr_entries;
+       BUG_ON(!nr_entries);
        if (nr_entries > PCIE_PORT_MAX_MSIX_ENTRIES)
                nr_entries = PCIE_PORT_MAX_MSIX_ENTRIES;
  
@@@ -344,12 -345,11 +345,12 @@@ static int pcie_device_init(struct pci_
        device_enable_async_suspend(device);
  
        retval = device_register(device);
 -      if (retval)
 -              kfree(pcie);
 -      else
 -              get_device(device);
 -      return retval;
 +      if (retval) {
 +              put_device(device);
 +              return retval;
 +      }
 +
 +      return 0;
  }
  
  /**
@@@ -455,8 -455,10 +456,8 @@@ int pcie_port_device_resume(struct devi
  
  static int remove_iter(struct device *dev, void *data)
  {
 -      if (dev->bus == &pcie_port_bus_type) {
 -              put_device(dev);
 +      if (dev->bus == &pcie_port_bus_type)
                device_unregister(dev);
 -      }
        return 0;
  }
  
@@@ -497,12 -499,12 +498,12 @@@ static int pcie_port_probe_service(stru
  
        pciedev = to_pcie_device(dev);
        status = driver->probe(pciedev);
 -      if (!status) {
 -              dev_printk(KERN_DEBUG, dev, "service driver %s loaded\n",
 -                      driver->name);
 -              get_device(dev);
 -      }
 -      return status;
 +      if (status)
 +              return status;
 +
 +      dev_printk(KERN_DEBUG, dev, "service driver %s loaded\n", driver->name);
 +      get_device(dev);
 +      return 0;
  }
  
  /**
@@@ -553,7 -555,7 +554,7 @@@ int pcie_port_service_register(struct p
        if (pcie_ports_disabled)
                return -ENODEV;
  
 -      new->driver.name = (char *)new->name;
 +      new->driver.name = new->name;
        new->driver.bus = &pcie_port_bus_type;
        new->driver.probe = pcie_port_probe_service;
        new->driver.remove = pcie_port_remove_service;
diff --combined include/linux/pci.h
index 4b7cf4c954fe89c6130829ae76ad46810aa27b95,6e32a2820126b416cbede5ccd89e24fb7df11905..b89069839020a123babc049bd200f0586cc8f22e
@@@ -224,8 -224,7 +224,8 @@@ enum pci_bus_speed 
  };
  
  struct pci_cap_saved_data {
 -      char cap_nr;
 +      u16 cap_nr;
 +      bool cap_extended;
        unsigned int size;
        u32 data[0];
  };
@@@ -635,7 -634,8 +635,7 @@@ struct pci_driver 
   * DEFINE_PCI_DEVICE_TABLE - macro used to describe a pci device table
   * @_table: device table name
   *
 - * This macro is used to create a struct pci_device_id array (a device table)
 - * in a generic manner.
 + * This macro is deprecated and should not be used in new code.
   */
  #define DEFINE_PCI_DEVICE_TABLE(_table) \
        const struct pci_device_id _table[]
@@@ -938,7 -938,6 +938,7 @@@ bool pci_check_and_unmask_intx(struct p
  void pci_msi_off(struct pci_dev *dev);
  int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size);
  int pci_set_dma_seg_boundary(struct pci_dev *dev, unsigned long mask);
 +int pci_wait_for_pending(struct pci_dev *dev, int pos, u16 mask);
  int pci_wait_for_pending_transaction(struct pci_dev *dev);
  int pcix_get_max_mmrbc(struct pci_dev *dev);
  int pcix_get_mmrbc(struct pci_dev *dev);
@@@ -977,12 -976,6 +977,12 @@@ struct pci_saved_state *pci_store_saved
  int pci_load_saved_state(struct pci_dev *dev, struct pci_saved_state *state);
  int pci_load_and_free_saved_state(struct pci_dev *dev,
                                  struct pci_saved_state **state);
 +struct pci_cap_saved_state *pci_find_saved_cap(struct pci_dev *dev, char cap);
 +struct pci_cap_saved_state *pci_find_saved_ext_cap(struct pci_dev *dev,
 +                                                 u16 cap);
 +int pci_add_cap_save_buffer(struct pci_dev *dev, char cap, unsigned int size);
 +int pci_add_ext_cap_save_buffer(struct pci_dev *dev,
 +                              u16 cap, unsigned int size);
  int __pci_complete_power_transition(struct pci_dev *dev, pci_power_t state);
  int pci_set_power_state(struct pci_dev *dev, pci_power_t state);
  pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state);
@@@ -1004,11 -997,6 +1004,11 @@@ static inline int pci_enable_wake(struc
        return __pci_enable_wake(dev, state, false, enable);
  }
  
 +/* PCI Virtual Channel */
 +int pci_save_vc_state(struct pci_dev *dev);
 +void pci_restore_vc_state(struct pci_dev *dev);
 +void pci_allocate_vc_save_buffers(struct pci_dev *dev);
 +
  #define PCI_EXP_IDO_REQUEST   (1<<0)
  #define PCI_EXP_IDO_COMPLETION        (1<<1)
  void pci_enable_ido(struct pci_dev *dev, unsigned long type);
@@@ -1166,13 -1154,12 +1166,12 @@@ struct msix_entry 
  
  
  #ifndef CONFIG_PCI_MSI
- static inline int pci_enable_msi_block(struct pci_dev *dev, int nvec)
+ static inline int pci_msi_vec_count(struct pci_dev *dev)
  {
        return -ENOSYS;
  }
  
- static inline int
- pci_enable_msi_block_auto(struct pci_dev *dev, int *maxvec)
+ static inline int pci_enable_msi_block(struct pci_dev *dev, int nvec)
  {
        return -ENOSYS;
  }
@@@ -1182,9 -1169,9 +1181,9 @@@ static inline void pci_msi_shutdown(str
  static inline void pci_disable_msi(struct pci_dev *dev)
  { }
  
- static inline int pci_msix_table_size(struct pci_dev *dev)
+ static inline int pci_msix_vec_count(struct pci_dev *dev)
  {
-       return 0;
+       return -ENOSYS;
  }
  static inline int pci_enable_msix(struct pci_dev *dev,
                                  struct msix_entry *entries, int nvec)
@@@ -1206,18 -1193,32 +1205,32 @@@ 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_msix_range(struct pci_dev *dev,
+                     struct msix_entry *entries, int minvec, int maxvec)
+ {
+       return -ENOSYS;
+ }
  #else
+ int pci_msi_vec_count(struct pci_dev *dev);
  int pci_enable_msi_block(struct pci_dev *dev, int nvec);
- int pci_enable_msi_block_auto(struct pci_dev *dev, int *maxvec);
  void pci_msi_shutdown(struct pci_dev *dev);
  void pci_disable_msi(struct pci_dev *dev);
- int pci_msix_table_size(struct pci_dev *dev);
+ int pci_msix_vec_count(struct pci_dev *dev);
  int pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, int nvec);
  void pci_msix_shutdown(struct pci_dev *dev);
  void pci_disable_msix(struct pci_dev *dev);
  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);
+ int pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries,
+                         int minvec, int maxvec);
  #endif
  
  #ifdef CONFIG_PCIEPORTBUS
@@@ -1579,65 -1580,65 +1592,65 @@@ enum pci_fixup_pass 
  /* Anonymous variables would be nice... */
  #define DECLARE_PCI_FIXUP_SECTION(section, name, vendor, device, class,       \
                                  class_shift, hook)                    \
 -      static const struct pci_fixup __pci_fixup_##name __used         \
 +      static const struct pci_fixup __PASTE(__pci_fixup_##name,__LINE__) __used       \
        __attribute__((__section__(#section), aligned((sizeof(void *)))))    \
                = { vendor, device, class, class_shift, hook };
  
  #define DECLARE_PCI_FIXUP_CLASS_EARLY(vendor, device, class,          \
                                         class_shift, hook)             \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_early,                     \
 -              vendor##device##hook, vendor, device, class, class_shift, hook)
 +              hook, vendor, device, class, class_shift, hook)
  #define DECLARE_PCI_FIXUP_CLASS_HEADER(vendor, device, class,         \
                                         class_shift, hook)             \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_header,                    \
 -              vendor##device##hook, vendor, device, class, class_shift, hook)
 +              hook, vendor, device, class, class_shift, hook)
  #define DECLARE_PCI_FIXUP_CLASS_FINAL(vendor, device, class,          \
                                         class_shift, hook)             \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_final,                     \
 -              vendor##device##hook, vendor, device, class, class_shift, hook)
 +              hook, vendor, device, class, class_shift, hook)
  #define DECLARE_PCI_FIXUP_CLASS_ENABLE(vendor, device, class,         \
                                         class_shift, hook)             \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_enable,                    \
 -              vendor##device##hook, vendor, device, class, class_shift, hook)
 +              hook, vendor, device, class, class_shift, hook)
  #define DECLARE_PCI_FIXUP_CLASS_RESUME(vendor, device, class,         \
                                         class_shift, hook)             \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_resume,                    \
 -              resume##vendor##device##hook, vendor, device, class,    \
 +              resume##hook, vendor, device, class,    \
                class_shift, hook)
  #define DECLARE_PCI_FIXUP_CLASS_RESUME_EARLY(vendor, device, class,   \
                                         class_shift, hook)             \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_resume_early,              \
 -              resume_early##vendor##device##hook, vendor, device,     \
 +              resume_early##hook, vendor, device,     \
                class, class_shift, hook)
  #define DECLARE_PCI_FIXUP_CLASS_SUSPEND(vendor, device, class,                \
                                         class_shift, hook)             \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_suspend,                   \
 -              suspend##vendor##device##hook, vendor, device, class,   \
 +              suspend##hook, vendor, device, class,   \
                class_shift, hook)
  
  #define DECLARE_PCI_FIXUP_EARLY(vendor, device, hook)                 \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_early,                     \
 -              vendor##device##hook, vendor, device, PCI_ANY_ID, 0, hook)
 +              hook, vendor, device, PCI_ANY_ID, 0, hook)
  #define DECLARE_PCI_FIXUP_HEADER(vendor, device, hook)                        \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_header,                    \
 -              vendor##device##hook, vendor, device, PCI_ANY_ID, 0, hook)
 +              hook, vendor, device, PCI_ANY_ID, 0, hook)
  #define DECLARE_PCI_FIXUP_FINAL(vendor, device, hook)                 \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_final,                     \
 -              vendor##device##hook, vendor, device, PCI_ANY_ID, 0, hook)
 +              hook, vendor, device, PCI_ANY_ID, 0, hook)
  #define DECLARE_PCI_FIXUP_ENABLE(vendor, device, hook)                        \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_enable,                    \
 -              vendor##device##hook, vendor, device, PCI_ANY_ID, 0, hook)
 +              hook, vendor, device, PCI_ANY_ID, 0, hook)
  #define DECLARE_PCI_FIXUP_RESUME(vendor, device, hook)                        \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_resume,                    \
 -              resume##vendor##device##hook, vendor, device,           \
 +              resume##hook, vendor, device,           \
                PCI_ANY_ID, 0, hook)
  #define DECLARE_PCI_FIXUP_RESUME_EARLY(vendor, device, hook)          \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_resume_early,              \
 -              resume_early##vendor##device##hook, vendor, device,     \
 +              resume_early##hook, vendor, device,     \
                PCI_ANY_ID, 0, hook)
  #define DECLARE_PCI_FIXUP_SUSPEND(vendor, device, hook)                       \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_suspend,                   \
 -              suspend##vendor##device##hook, vendor, device,          \
 +              suspend##hook, vendor, device,          \
                PCI_ANY_ID, 0, hook)
  
  #ifdef CONFIG_PCI_QUIRKS