RE: [RFC PATCH 10/11] PCI/MSI: Split the generic MSI code into new file

2014-08-20 Thread bharat.bhus...@freescale.com


 -Original Message-
 From: linux-pci-ow...@vger.kernel.org [mailto:linux-pci-ow...@vger.kernel.org]
 On Behalf Of Yijing Wang
 Sent: Saturday, July 26, 2014 8:39 AM
 To: linux-ker...@vger.kernel.org
 Cc: Xinwei Hu; Wuyun; Bjorn Helgaas; linux-...@vger.kernel.org;
 paul.mu...@huawei.com; James E.J. Bottomley; Marc Zyngier; linux-arm-
 ker...@lists.infradead.org; Russell King; linux-a...@vger.kernel.org; Basu
 Arnab-B45036; virtualization@lists.linux-foundation.org; Hanjun Guo; Yijing 
 Wang
 Subject: [RFC PATCH 10/11] PCI/MSI: Split the generic MSI code into new file
 
 MSI interrupt will not only used in PCI device, more
 and more Non-PCI device also want to use MSI. ARM
 GIC v3 spec says in ARM platform with GIC v3 controller,
 Non-PCI device can also be design to support MSI to
 simplify interrupt wires, for the existing Non-PCI
 device, consolidator is designed and used to translate
 legacy interrupt to MSI. So for support Non-PCI MSI
 device, generic MSI driver is needed. Split the generic
 MSI code into new location, drivers/msi/msi.c. Then
 MSI driver does not depend PCI anymore.
 
 Signed-off-by: Yijing Wang wangyij...@huawei.com
 ---
  drivers/Kconfig  |1 +
  drivers/Makefile |1 +
  drivers/msi/Kconfig  |8 +
  drivers/msi/Makefile |1 +
  drivers/msi/msi.c|  540 
 ++
  drivers/pci/Kconfig  |6 +-
  drivers/pci/msi.c|  500 ---
  include/linux/msi.h  |   31 +++-
  8 files changed, 617 insertions(+), 471 deletions(-)
  create mode 100644 drivers/msi/Kconfig
  create mode 100644 drivers/msi/Makefile
  create mode 100644 drivers/msi/msi.c
 
 diff --git a/drivers/Kconfig b/drivers/Kconfig
 index 0e87a34..4d05749 100644
 --- a/drivers/Kconfig
 +++ b/drivers/Kconfig
 @@ -176,4 +176,5 @@ source drivers/powercap/Kconfig
 
  source drivers/mcb/Kconfig
 
 +source drivers/msi/Kconfig
  endmenu
 diff --git a/drivers/Makefile b/drivers/Makefile
 index f98b50d..47ae3d1 100644
 --- a/drivers/Makefile
 +++ b/drivers/Makefile
 @@ -158,3 +158,4 @@ obj-$(CONFIG_NTB) += ntb/
  obj-$(CONFIG_FMC)+= fmc/
  obj-$(CONFIG_POWERCAP)   += powercap/
  obj-$(CONFIG_MCB)+= mcb/
 +obj-$(CONFIG_MSI)+= msi/
 diff --git a/drivers/msi/Kconfig b/drivers/msi/Kconfig
 new file mode 100644
 index 000..739bd13
 --- /dev/null
 +++ b/drivers/msi/Kconfig
 @@ -0,0 +1,8 @@
 +config MSI
 + bool Message Signaled Interrupts (MSI and MSI-X)
 + default y
 + help
 + This allows device drivers to use generic MSI(Message
 + Signaled Interrupt). Message Signaled Interrupts enable
 + a device to generate an interrupt using an inbound Memory
 + Write to a specific target address.
 diff --git a/drivers/msi/Makefile b/drivers/msi/Makefile
 new file mode 100644
 index 000..39cb026
 --- /dev/null
 +++ b/drivers/msi/Makefile
 @@ -0,0 +1 @@
 +obj-$(CONFIG_MSI) += msi.o
 diff --git a/drivers/msi/msi.c b/drivers/msi/msi.c
 new file mode 100644
 index 000..3fbd539
 --- /dev/null
 +++ b/drivers/msi/msi.c
 @@ -0,0 +1,540 @@
 +/*
 + * File: msi.c
 + * Purpose:  Message Signaled Interrupt (MSI)
 + *
 + * Copyright (C) 2014 Huawei Ltd.
 + * Copyright (C) Yijing Wang wangyij...@huawei.com
 + */
 +#include linux/err.h
 +#include linux/mm.h
 +#include linux/irq.h
 +#include linux/interrupt.h
 +#include linux/export.h
 +#include linux/ioport.h
 +#include linux/proc_fs.h
 +#include linux/msi.h
 +#include linux/smp.h
 +#include linux/errno.h
 +#include linux/io.h
 +#include linux/slab.h
 +#include linux/device.h
 +#include linux/pci.h
 +
 +/* Arch hooks */
 +
 +int __weak arch_setup_msi_irq(struct msi_irqs *msi, struct msi_desc *desc)
 +{
 + struct pci_dev *dev = msi-data;
 + struct msi_chip *chip = dev-bus-msi; //TO BE DONE: rework msi_chip to
 support Non-PCI MSI
 + int err;
 +
 + if (!chip || !chip-setup_irq)
 + return -EINVAL;
 +
 + err = chip-setup_irq(chip, dev, desc);
 + if (err  0)
 + return err;
 +
 + irq_set_chip_data(desc-irq, chip);
 + return 0;
 +}
 +
 +void __weak arch_teardown_msi_irq(unsigned int irq)
 +{
 + struct msi_chip *chip = irq_get_chip_data(irq);
 +
 + if (!chip || !chip-teardown_irq)
 + return;
 +
 + chip-teardown_irq(chip, irq);
 +}
 +
 +int __weak arch_msi_check_device(struct msi_irqs *msi, int nvec, int type)
 +{
 + struct pci_dev *dev = msi-data;
 + struct msi_chip *chip = dev-bus-msi; //TO BE DONE: rework msi_chip to
 support Non-PCI MSI
 +
 + if (!chip || !chip-check_device)
 + return 0;
 +
 + return chip-check_device(chip, dev, nvec, type);
 +}
 +
 +int __weak arch_setup_msi_irqs(struct msi_irqs *msi, int nvec, int type)
 +{
 + struct msi_desc *entry;
 + int ret;
 +
 + /*
 +  * If an architecture wants to support multiple MSI, it needs to
 +  * override

Re: [RFC PATCH 10/11] PCI/MSI: Split the generic MSI code into new file

2014-08-20 Thread Yijing Wang
 +int msi_capability_init(struct msi_irqs *msi, int nvec)
 +{
 +struct msi_desc *entry;
 +int ret;
 +unsigned mask;
 +
 +msi_set_enable(msi, 0, MSI_TYPE);   /* Disable MSI during set up */
 +
 +/* MSI Entry Initialization */
 +entry = msi_setup_entry(msi);
 +if (!entry)
 +return -ENOMEM;
 +
 +/* All MSIs are unmasked by default, Mask them all */
 
 Will this be true for non-pci devices as well?

In my opinion, yes, I think all msi devices should be masked during the setup.
Of course, mask and unmask functions will be override by private mask/unmask 
functions.


 
 Thanks
 -Bharat
 
 +mask = msi_mask(entry-msi_attrib.multi_cap);
 +msi_mask_irq(entry, mask, mask);
 +
 +/* Configure MSI capability structure */
 +ret = arch_setup_msi_irqs(msi, nvec, MSI_TYPE);
 +if (ret)
 +goto err;
 +
 +/* Set MSI enabled bits  */
 +msi_set_intx(msi, 0);
 +msi_set_enable(msi, 1, MSI_TYPE);
 +msi-msi_enabled = 1;
 +
 +return 0;
 +
 +err:
 +msi_mask_irq(entry, mask, ~mask);
 +free_msi_irqs(msi);
 +return ret;
 +}
 +
 +static void msix_program_entries(struct msi_irqs *msi,
 + struct msix_entry *entries)
 +{
 +struct msi_desc *entry;
 +int i = 0;
 +
 +list_for_each_entry(entry, msi-msi_list, list) {
 +entries[i].vector = entry-irq;
 +irq_set_msi_desc(entry-irq, entry);
 +i++;
 +}
 +}
 +
 +/**
 + * msix_capability_init - configure device's MSI-X capability
 + * @dev: pointer to the pci_dev data structure of MSI-X device function
 + * @entries: pointer to an array of struct msix_entry entries
 + * @nvec: number of @entries
 + *
 + * Setup the MSI-X capability structure of device function with a
 + * single MSI-X irq. A return of zero indicates the successful setup of
 + * requested MSI-X entries with allocated irqs or non-zero for otherwise.
 + **/
 +int msix_capability_init(struct msi_irqs *msi, void __iomem *base,
 +struct msix_entry *entries, int nvec)
 +{
 +int ret;
 +
 +/* Ensure MSI-X is disabled while it is set up */
 +msi_set_enable(msi, 0, MSIX_TYPE);
 +
 +ret = msix_setup_entries(msi, base, entries, nvec);
 +if (ret)
 +return ret;
 +
 +ret = arch_setup_msi_irqs(msi, nvec, MSIX_TYPE);
 +if (ret)
 +goto out_avail;
 +
 +msix_program_entries(msi, entries);
 +
 +/* Set MSI-X enabled bits and unmask the function */
 +msi_set_intx(msi, 0);
 +msi-msix_enabled = 1;
 +
 +msi_set_enable(msi, 1, MSIX_TYPE);
 +
 +return 0;
 +
 +out_avail:
 +if (ret  0) {
 +/*
 + * If we had some success, report the number of irqs
 + * we succeeded in setting up.
 + */
 +struct msi_desc *entry;
 +int avail = 0;
 +
 +list_for_each_entry(entry, msi-msi_list, list) {
 +if (entry-irq != 0)
 +avail++;
 +}
 +if (avail != 0)
 +ret = avail;
 +}
 +
 +free_msi_irqs(msi);
 +
 +return ret;
 +}
 +
 diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
 index 893503f..1a10488 100644
 --- a/drivers/pci/Kconfig
 +++ b/drivers/pci/Kconfig
 @@ -2,10 +2,10 @@
  # PCI configuration
  #
  config PCI_MSI
 -bool Message Signaled Interrupts (MSI and MSI-X)
 -depends on PCI
 +bool PCI Message Signaled Interrupts (MSI and MSI-X)
 +depends on PCI  MSI
  help
 -   This allows device drivers to enable MSI (Message Signaled
 +   This allows PCI device drivers to enable MSI (Message Signaled
 Interrupts).  Message Signaled Interrupts enable a device to
 generate an interrupt using an inbound Memory Write on its
 PCI bus instead of asserting a device IRQ pin.
 diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
 index f0c5989..df7223c 100644
 --- a/drivers/pci/msi.c
 +++ b/drivers/pci/msi.c
 @@ -26,121 +26,8 @@ static int pci_msi_enable = 1;

  #define msix_table_size(flags)  ((flags  PCI_MSIX_FLAGS_QSIZE) + 1)

 -
 -/* Arch hooks */
 -
 -int __weak arch_setup_msi_irq(struct msi_irqs *msi, struct msi_desc *desc)
 -{
 -struct pci_dev *dev = msi-data; //TO BE DONE: rework msi_chip to 
 support
 Non-PCI
 -struct msi_chip *chip = dev-bus-msi;
 -int err;
 -
 -if (!chip || !chip-setup_irq)
 -return -EINVAL;
 -
 -err = chip-setup_irq(chip, dev, desc);
 -if (err  0)
 -return err;
 -
 -irq_set_chip_data(desc-irq, chip);
 -
 -return 0;
 -}
 -
 -void __weak arch_teardown_msi_irq(unsigned int irq)
 -{
 -struct msi_chip *chip = irq_get_chip_data(irq);
 -
 -if (!chip || !chip-teardown_irq)
 -return;
 -
 -chip-teardown_irq(chip, irq);
 -}
 -
 -int __weak arch_msi_check_device(struct msi_irqs *msi, int nvec, int type)
 -{
 -struct pci_dev *dev = msi-data; //TO BE DONE: rework 

[RFC PATCH 10/11] PCI/MSI: Split the generic MSI code into new file

2014-07-25 Thread Yijing Wang
MSI interrupt will not only used in PCI device, more
and more Non-PCI device also want to use MSI. ARM
GIC v3 spec says in ARM platform with GIC v3 controller,
Non-PCI device can also be design to support MSI to
simplify interrupt wires, for the existing Non-PCI
device, consolidator is designed and used to translate
legacy interrupt to MSI. So for support Non-PCI MSI
device, generic MSI driver is needed. Split the generic
MSI code into new location, drivers/msi/msi.c. Then
MSI driver does not depend PCI anymore.

Signed-off-by: Yijing Wang wangyij...@huawei.com
---
 drivers/Kconfig  |1 +
 drivers/Makefile |1 +
 drivers/msi/Kconfig  |8 +
 drivers/msi/Makefile |1 +
 drivers/msi/msi.c|  540 ++
 drivers/pci/Kconfig  |6 +-
 drivers/pci/msi.c|  500 ---
 include/linux/msi.h  |   31 +++-
 8 files changed, 617 insertions(+), 471 deletions(-)
 create mode 100644 drivers/msi/Kconfig
 create mode 100644 drivers/msi/Makefile
 create mode 100644 drivers/msi/msi.c

diff --git a/drivers/Kconfig b/drivers/Kconfig
index 0e87a34..4d05749 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -176,4 +176,5 @@ source drivers/powercap/Kconfig
 
 source drivers/mcb/Kconfig
 
+source drivers/msi/Kconfig
 endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index f98b50d..47ae3d1 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -158,3 +158,4 @@ obj-$(CONFIG_NTB)   += ntb/
 obj-$(CONFIG_FMC)  += fmc/
 obj-$(CONFIG_POWERCAP) += powercap/
 obj-$(CONFIG_MCB)  += mcb/
+obj-$(CONFIG_MSI)  += msi/
diff --git a/drivers/msi/Kconfig b/drivers/msi/Kconfig
new file mode 100644
index 000..739bd13
--- /dev/null
+++ b/drivers/msi/Kconfig
@@ -0,0 +1,8 @@
+config MSI
+   bool Message Signaled Interrupts (MSI and MSI-X)
+   default y
+   help
+   This allows device drivers to use generic MSI(Message
+   Signaled Interrupt). Message Signaled Interrupts enable 
+   a device to generate an interrupt using an inbound Memory 
+   Write to a specific target address.
diff --git a/drivers/msi/Makefile b/drivers/msi/Makefile
new file mode 100644
index 000..39cb026
--- /dev/null
+++ b/drivers/msi/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_MSI) += msi.o
diff --git a/drivers/msi/msi.c b/drivers/msi/msi.c
new file mode 100644
index 000..3fbd539
--- /dev/null
+++ b/drivers/msi/msi.c
@@ -0,0 +1,540 @@
+/*
+ * File:   msi.c
+ * Purpose:Message Signaled Interrupt (MSI)
+ *
+ * Copyright (C) 2014 Huawei Ltd.
+ * Copyright (C) Yijing Wang wangyij...@huawei.com 
+ */
+#include linux/err.h
+#include linux/mm.h
+#include linux/irq.h
+#include linux/interrupt.h
+#include linux/export.h
+#include linux/ioport.h
+#include linux/proc_fs.h
+#include linux/msi.h
+#include linux/smp.h
+#include linux/errno.h
+#include linux/io.h
+#include linux/slab.h
+#include linux/device.h
+#include linux/pci.h
+
+/* Arch hooks */
+
+int __weak arch_setup_msi_irq(struct msi_irqs *msi, struct msi_desc *desc)
+{
+   struct pci_dev *dev = msi-data;
+   struct msi_chip *chip = dev-bus-msi; //TO BE DONE: rework msi_chip to 
support Non-PCI MSI
+   int err;
+
+   if (!chip || !chip-setup_irq)
+   return -EINVAL;
+
+   err = chip-setup_irq(chip, dev, desc);
+   if (err  0)
+   return err;
+
+   irq_set_chip_data(desc-irq, chip);
+   return 0;
+}
+
+void __weak arch_teardown_msi_irq(unsigned int irq)
+{
+   struct msi_chip *chip = irq_get_chip_data(irq);
+
+   if (!chip || !chip-teardown_irq)
+   return;
+
+   chip-teardown_irq(chip, irq);
+}
+
+int __weak arch_msi_check_device(struct msi_irqs *msi, int nvec, int type)
+{
+   struct pci_dev *dev = msi-data;
+   struct msi_chip *chip = dev-bus-msi; //TO BE DONE: rework msi_chip to 
support Non-PCI MSI
+
+   if (!chip || !chip-check_device)
+   return 0;
+
+   return chip-check_device(chip, dev, nvec, type);
+}
+
+int __weak arch_setup_msi_irqs(struct msi_irqs *msi, int nvec, int type)
+{
+   struct msi_desc *entry;
+   int ret;
+
+   /*
+* If an architecture wants to support multiple MSI, it needs to
+* override arch_setup_msi_irqs()
+*/
+   if (type == MSI_TYPE  nvec  1)
+   return 1;
+
+   list_for_each_entry(entry, msi-msi_list, list) {
+   ret = arch_setup_msi_irq(msi, entry);
+   if (ret  0)
+   return ret;
+   if (ret  0)
+   return -ENOSPC;
+   }
+   return 0;
+}
+
+
+void __weak arch_teardown_msi_irqs(struct msi_irqs *msi)
+{
+   return default_teardown_msi_irqs(msi);
+}
+
+/*
+ * We have a default implementation available as a separate non-weak
+ * function, as it is used by the Xen x86 PCI code
+ */
+void