Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/pci/ixgbe - Add MSI/MSI-X support. The multiqueue fu...
details: https://anonhg.NetBSD.org/src/rev/ed363cf56009
branches: trunk
changeset: 339840:ed363cf56009
user: msaitoh <msaitoh%NetBSD.org@localhost>
date: Thu Aug 13 04:56:43 2015 +0000
description:
- Add MSI/MSI-X support. The multiqueue function is not supported yet.
- Make ixv.c compilable. _NOT_TESTED_YET_
diffstat:
sys/dev/pci/ixgbe/ixgbe.c | 344 ++++++++++++++++++++-------------------
sys/dev/pci/ixgbe/ixgbe_82599.c | 6 +-
sys/dev/pci/ixgbe/ixgbe_osdep.h | 29 ++-
sys/dev/pci/ixgbe/ixgbe_type.h | 9 +-
sys/dev/pci/ixgbe/ixv.c | 244 +++++++++++++---------------
5 files changed, 326 insertions(+), 306 deletions(-)
diffs (truncated from 1100 to 300 lines):
diff -r 12f1890a1211 -r ed363cf56009 sys/dev/pci/ixgbe/ixgbe.c
--- a/sys/dev/pci/ixgbe/ixgbe.c Thu Aug 13 04:52:40 2015 +0000
+++ b/sys/dev/pci/ixgbe/ixgbe.c Thu Aug 13 04:56:43 2015 +0000
@@ -59,7 +59,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
/*$FreeBSD: head/sys/dev/ixgbe/ixgbe.c 279805 2015-03-09 10:29:15Z araujo $*/
-/*$NetBSD: ixgbe.c,v 1.33 2015/08/05 04:08:44 msaitoh Exp $*/
+/*$NetBSD: ixgbe.c,v 1.34 2015/08/13 04:56:43 msaitoh Exp $*/
#include "opt_inet.h"
#include "opt_inet6.h"
@@ -232,8 +232,8 @@
#if defined(NETBSD_MSI_OR_MSIX)
/* The MSI/X Interrupt handlers */
-static void ixgbe_msix_que(void *);
-static void ixgbe_msix_link(void *);
+static int ixgbe_msix_que(void *);
+static int ixgbe_msix_link(void *);
#endif
/* Software interrupts for deferred work */
@@ -317,7 +317,7 @@
* number of cpus with a max of 8. This
* can be overriden manually here.
*/
-static int ixgbe_num_queues = 0;
+static int ixgbe_num_queues = 1;
SYSCTL_INT("hw.ixgbe.num_queues", &ixgbe_num_queues);
#endif
@@ -508,7 +508,7 @@
{
struct adapter *adapter;
struct ixgbe_hw *hw;
- int error = 0;
+ int error = -1;
u16 csum;
u32 ctrl_ext;
ixgbe_vendor_info_t *ent;
@@ -608,7 +608,8 @@
*/
adapter->sfp_probe = TRUE;
error = 0;
- } else if (error == IXGBE_ERR_SFP_NOT_SUPPORTED) {
+ } else if ((error == IXGBE_ERR_SFP_NOT_SUPPORTED)
+ && (hw->allow_unsupported_sfp == false)) {
aprint_error_dev(dev,"Unsupported SFP+ module detected!\n");
error = EIO;
goto err_late;
@@ -649,10 +650,11 @@
/* Detect and set physical type */
ixgbe_setup_optics(adapter);
+ error = -1;
if ((adapter->msix > 1) && (ixgbe_enable_msix))
- error = ixgbe_allocate_msix(adapter, pa);
- else
- error = ixgbe_allocate_legacy(adapter, pa);
+ error = ixgbe_allocate_msix(adapter, pa);
+ if (error != 0)
+ error = ixgbe_allocate_legacy(adapter, pa);
if (error)
goto err_late;
@@ -1692,7 +1694,7 @@
* MSIX Queue Interrupt Service routine
*
**********************************************************************/
-void
+static int
ixgbe_msix_que(void *arg)
{
struct ix_queue *que = arg;
@@ -1705,7 +1707,7 @@
/* Protect against spurious interrupts */
if ((ifp->if_flags & IFF_RUNNING) == 0)
- return;
+ return 0;
ixgbe_disable_queue(adapter, que->msix);
++que->irqs;
@@ -1716,6 +1718,7 @@
ixgbe_txeof(txr);
#ifdef IXGBE_LEGACY_TX
if (!IFQ_IS_EMPTY(&adapter->ifp->if_snd))
+ ixgbe_start_locked(txr, ifp);
#else
if (!drbr_empty(ifp, txr->br))
ixgbe_mq_start_locked(ifp, txr);
@@ -1777,11 +1780,11 @@
softint_schedule(que->que_si);
else
ixgbe_enable_queue(adapter, que->msix);
- return;
+ return 1;
}
-static void
+static int
ixgbe_msix_link(void *arg)
{
struct adapter *adapter = arg;
@@ -1806,7 +1809,7 @@
if (reg_eicr & IXGBE_EICR_FLOW_DIR) {
/* This is probably overkill :) */
if (!atomic_cmpset_int(&adapter->fdir_reinit, 0, 1))
- return;
+ return 1;
/* Disable the interrupt */
IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EICR_FLOW_DIR);
softint_schedule(adapter->fdir_si);
@@ -1847,7 +1850,7 @@
}
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, IXGBE_EIMS_OTHER);
- return;
+ return 1;
}
#endif
@@ -2477,32 +2480,79 @@
*
**********************************************************************/
static int
-ixgbe_allocate_legacy(struct adapter *adapter, const struct pci_attach_args *pa)
+ixgbe_allocate_legacy(struct adapter *adapter,
+ const struct pci_attach_args *pa)
{
device_t dev = adapter->dev;
struct ix_queue *que = adapter->queues;
#ifndef IXGBE_LEGACY_TX
struct tx_ring *txr = adapter->tx_rings;
#endif
+#ifndef NETBSD_MSI_OR_MSIX
+ pci_intr_handle_t ih;
+#else
+ int counts[PCI_INTR_TYPE_SIZE];
+ pci_intr_type_t intr_type, max_type;
+#endif
char intrbuf[PCI_INTRSTR_LEN];
-#if 0
- int rid = 0;
-
- /* MSI RID at 1 */
- if (adapter->msix == 1)
- rid = 1;
-#endif
+ const char *intrstr = NULL;
+#ifndef NETBSD_MSI_OR_MSIX
/* We allocate a single interrupt resource */
- if (pci_intr_map(pa, &adapter->osdep.ih) != 0) {
+ if (pci_intr_map(pa, &ih) != 0) {
aprint_error_dev(dev, "unable to map interrupt\n");
return ENXIO;
} else {
- aprint_normal_dev(dev, "interrupting at %s\n",
- pci_intr_string(adapter->osdep.pc, adapter->osdep.ih,
- intrbuf, sizeof(intrbuf)));
- }
-
+ intrstr = pci_intr_string(adapter->osdep.pc, ih, intrbuf,
+ sizeof(intrbuf));
+ }
+ adapter->osdep.ihs[0] = pci_intr_establish(adapter->osdep.pc, ih,
+ IPL_NET, ixgbe_legacy_irq, que);
+#else
+ /* Allocation settings */
+ max_type = PCI_INTR_TYPE_MSI;
+ counts[PCI_INTR_TYPE_MSIX] = 0;
+ counts[PCI_INTR_TYPE_MSI] = 1;
+ counts[PCI_INTR_TYPE_INTX] = 1;
+
+alloc_retry:
+ if (pci_intr_alloc(pa, &adapter->osdep.intrs, counts, max_type) != 0) {
+ aprint_error_dev(dev, "couldn't alloc interrupt\n");
+ return ENXIO;
+ }
+ adapter->osdep.nintrs = 1;
+ intrstr = pci_intr_string(adapter->osdep.pc, adapter->osdep.intrs[0],
+ intrbuf, sizeof(intrbuf));
+ adapter->osdep.ihs[0] = pci_intr_establish(adapter->osdep.pc,
+ adapter->osdep.intrs[0], IPL_NET, ixgbe_legacy_irq, que);
+ if (adapter->osdep.ihs[0] == NULL) {
+ intr_type = pci_intr_type(adapter->osdep.intrs[0]);
+ aprint_error_dev(dev,"unable to establish %s\n",
+ (intr_type == PCI_INTR_TYPE_MSI) ? "MSI" : "INTx");
+ pci_intr_release(adapter->osdep.pc, adapter->osdep.intrs, 1);
+ switch (intr_type) {
+ case PCI_INTR_TYPE_MSI:
+ /* The next try is for INTx: Disable MSI */
+ max_type = PCI_INTR_TYPE_INTX;
+ counts[PCI_INTR_TYPE_INTX] = 1;
+ goto alloc_retry;
+ case PCI_INTR_TYPE_INTX:
+ default:
+ /* See below */
+ break;
+ }
+ }
+#endif
+ if (adapter->osdep.ihs[0] == NULL) {
+ aprint_error_dev(dev,
+ "couldn't establish interrupt%s%s\n",
+ intrstr ? " at " : "", intrstr ? intrstr : "");
+#ifdef NETBSD_MSI_OR_MSIX
+ pci_intr_release(adapter->osdep.pc, adapter->osdep.intrs, 1);
+#endif
+ return ENXIO;
+ }
+ aprint_normal_dev(dev, "interrupting at %s\n", intrstr);
/*
* Try allocating a fast interrupt and the associated deferred
* processing contexts.
@@ -2537,19 +2587,6 @@
return ENXIO;
}
- adapter->osdep.intr = pci_intr_establish(adapter->osdep.pc,
- adapter->osdep.ih, IPL_NET, ixgbe_legacy_irq, que);
- if (adapter->osdep.intr == NULL) {
- aprint_error_dev(dev, "failed to register interrupt handler\n");
- softint_disestablish(que->que_si);
- softint_disestablish(adapter->link_si);
- softint_disestablish(adapter->mod_si);
- softint_disestablish(adapter->msf_si);
-#ifdef IXGBE_FDIR
- softint_disestablish(adapter->fdir_si);
-#endif
- return ENXIO;
- }
/* For simplicity in the handlers */
adapter->que_mask = IXGBE_EIMS_ENABLE_MASK;
@@ -2571,13 +2608,16 @@
device_t dev = adapter->dev;
struct ix_queue *que = adapter->queues;
struct tx_ring *txr = adapter->tx_rings;
- int error, rid, vector = 0;
+ pci_chipset_tag_t pc;
+ char intrbuf[PCI_INTRSTR_LEN];
+ const char *intrstr = NULL;
+ int error, vector = 0;
int cpu_id = 0;
+ kcpuset_t *affinity;
+
+ pc = adapter->osdep.pc;
#ifdef RSS
cpuset_t cpu_mask;
-#endif
-
-#ifdef RSS
/*
* If we're doing RSS, the number of queues needs to
* match the number of RSS buckets that are configured.
@@ -2599,28 +2639,33 @@
}
#endif
+ adapter->osdep.nintrs = adapter->num_queues + 1;
+ if (pci_msix_alloc_exact(pa, &adapter->osdep.intrs,
+ adapter->osdep.nintrs) != 0) {
+ aprint_error_dev(dev,
+ "failed to allocate MSI-X interrupt\n");
+ return (ENXIO);
+ }
+
+ kcpuset_create(&affinity, false);
for (int i = 0; i < adapter->num_queues; i++, vector++, que++, txr++) {
- rid = vector + 1;
- que->res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
- RF_SHAREABLE | RF_ACTIVE);
+ intrstr = pci_intr_string(pc, adapter->osdep.intrs[i], intrbuf,
+ sizeof(intrbuf));
+#ifdef IXG_MPSAFE
+ pci_intr_setattr(pc, adapter->osdep.intrs[i], PCI_INTR_MPSAFE,
+ true);
+#endif
+ /* Set the handler function */
+ que->res = adapter->osdep.ihs[i] = pci_intr_establish(pc,
+ adapter->osdep.intrs[i], IPL_NET, ixgbe_msix_que, que);
if (que->res == NULL) {
- aprint_error_dev(dev,"Unable to allocate"
- " bus resource: que interrupt [%d]\n", vector);
- return (ENXIO);
- }
- /* Set the handler function */
- error = bus_setup_intr(dev, que->res,
- INTR_TYPE_NET | INTR_MPSAFE, NULL,
- ixgbe_msix_que, que, &que->tag);
- if (error) {
- que->res = NULL;
+ pci_intr_release(pc, adapter->osdep.intrs,
+ adapter->osdep.nintrs);
aprint_error_dev(dev,
"Failed to register QUE handler\n");
Home |
Main Index |
Thread Index |
Old Index