Module Name:    src
Committed By:   msaitoh
Date:           Thu Aug 13 04:56:43 UTC 2015

Modified Files:
        src/sys/dev/pci/ixgbe: ixgbe.c ixgbe_82599.c ixgbe_osdep.h ixgbe_type.h
            ixv.c

Log Message:
 - Add MSI/MSI-X support. The multiqueue function is not supported yet.
 - Make ixv.c compilable. _NOT_TESTED_YET_


To generate a diff of this commit:
cvs rdiff -u -r1.33 -r1.34 src/sys/dev/pci/ixgbe/ixgbe.c
cvs rdiff -u -r1.10 -r1.11 src/sys/dev/pci/ixgbe/ixgbe_82599.c \
    src/sys/dev/pci/ixgbe/ixv.c
cvs rdiff -u -r1.9 -r1.10 src/sys/dev/pci/ixgbe/ixgbe_osdep.h
cvs rdiff -u -r1.11 -r1.12 src/sys/dev/pci/ixgbe/ixgbe_type.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/pci/ixgbe/ixgbe.c
diff -u src/sys/dev/pci/ixgbe/ixgbe.c:1.33 src/sys/dev/pci/ixgbe/ixgbe.c:1.34
--- src/sys/dev/pci/ixgbe/ixgbe.c:1.33	Wed Aug  5 04:08:44 2015
+++ src/sys/dev/pci/ixgbe/ixgbe.c	Thu Aug 13 04:56:43 2015
@@ -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 @@ static int	ixgbe_legacy_irq(void *);
 
 #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 @@ SYSCTL_INT("hw.ixgbe.enable_msix", &ixgb
  * 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 @@ ixgbe_attach(device_t parent, device_t d
 {
 	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 @@ ixgbe_attach(device_t parent, device_t d
 		*/
 		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 @@ ixgbe_attach(device_t parent, device_t d
 	/* 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 @@ ixgbe_legacy_irq(void *arg)
  *  MSIX Queue Interrupt Service routine
  *
  **********************************************************************/
-void
+static int
 ixgbe_msix_que(void *arg)
 {
 	struct ix_queue	*que = arg;
@@ -1705,7 +1707,7 @@ ixgbe_msix_que(void *arg)
 
 	/* 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_msix_que(void *arg)
 	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 @@ no_calc:
 		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 @@ ixgbe_msix_link(void *arg)
 		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_msix_link(void *arg)
 	}
 
 	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, IXGBE_EIMS_OTHER);
-	return;
+	return 1;
 }
 #endif
 
@@ -2477,32 +2480,79 @@ ixgbe_setup_optics(struct adapter *adapt
  *
  **********************************************************************/
 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
-	char intrbuf[PCI_INTRSTR_LEN];
-#if 0
-	int		rid = 0;
-
-	/* MSI RID at 1 */
-	if (adapter->msix == 1)
-		rid = 1;
+#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];
+	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 @@ ixgbe_allocate_legacy(struct adapter *ad
 		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 @@ ixgbe_allocate_msix(struct adapter *adap
 	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;
-#ifdef	RSS
-	cpuset_t cpu_mask;
-#endif
+	kcpuset_t	*affinity;
 
+	pc = adapter->osdep.pc;
 #ifdef	RSS
+	cpuset_t cpu_mask;
 	/*
 	 * If we're doing RSS, the number of queues needs to
 	 * match the number of RSS buckets that are configured.
@@ -2599,28 +2639,33 @@ ixgbe_allocate_msix(struct adapter *adap
 	}
 #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);
-		if (que->res == NULL) {
-			aprint_error_dev(dev,"Unable to allocate"
-		    	    " bus resource: que interrupt [%d]\n", vector);
-			return (ENXIO);
-		}
+		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 */
-		error = bus_setup_intr(dev, que->res,
-		    INTR_TYPE_NET | INTR_MPSAFE, NULL,
-		    ixgbe_msix_que, que, &que->tag);
-		if (error) {
-			que->res = NULL;
+		que->res = adapter->osdep.ihs[i] = pci_intr_establish(pc,
+		    adapter->osdep.intrs[i], IPL_NET, ixgbe_msix_que, que);
+		if (que->res == NULL) {
+			pci_intr_release(pc, adapter->osdep.intrs,
+			    adapter->osdep.nintrs);
 			aprint_error_dev(dev,
 			    "Failed to register QUE handler\n");
-			return error;
+			kcpuset_destroy(affinity);
+			return ENXIO;
 		}
-#if __FreeBSD_version >= 800504
-		bus_describe_intr(dev, que->res, que->tag, "que %d", i);
-#endif
 		que->msix = vector;
         	adapter->que_mask |= (u64)(1 << que->msix);
 #ifdef	RSS
@@ -2640,18 +2685,23 @@ ixgbe_allocate_msix(struct adapter *adap
 		if (adapter->num_queues > 1)
 			cpu_id = i;
 #endif
-		if (adapter->num_queues > 1)
-			bus_bind_intr(dev, que->res, cpu_id);
-
+		/* Round-robin affinity */
+		kcpuset_zero(affinity);
+		kcpuset_set(affinity, cpu_id % ncpu);
+		error = pci_intr_distribute(adapter->osdep.ihs[i], affinity,
+		    NULL);
+		aprint_normal_dev(dev, "for TX/RX, interrupting at %s",
+		    intrstr);
+		if (error == 0) {
 #ifdef	RSS
-		device_printf(dev,
-		    "Bound RSS bucket %d to CPU %d\n",
-		    i, cpu_id);
+			aprintf_normal(", bound RSS bucket %d to CPU %d\n",
+			    i, cpu_id);
 #else
-		device_printf(dev,
-		    "Bound queue %d to cpu %d\n",
-		    i, cpu_id);
+			aprint_normal(", bound queue %d to cpu %d\n",
+			    i, cpu_id);
 #endif
+		} else
+			aprint_normal("\n");
 
 #ifndef IXGBE_LEGACY_TX
 		txr->txq_si = softint_establish(SOFTINT_NET,
@@ -2666,26 +2716,34 @@ ixgbe_allocate_msix(struct adapter *adap
 	}
 
 	/* and Link */
-	rid = vector + 1;
-	adapter->res = bus_alloc_resource_any(dev,
-    	    SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE);
-	if (!adapter->res) {
-		aprint_error_dev(dev,"Unable to allocate bus resource: "
-		    "Link interrupt [%d]\n", rid);
-		return (ENXIO);
-	}
+	cpu_id++;
+	intrstr = pci_intr_string(pc, adapter->osdep.intrs[vector], intrbuf,
+	    sizeof(intrbuf));
+#ifdef IXG_MPSAFE
+	pci_intr_setattr(pc, &adapter->osdep.intrs[vector], PCI_INTR_MPSAFE,
+	    true);
+#endif
 	/* Set the link handler function */
-	error = bus_setup_intr(dev, adapter->res,
-	    INTR_TYPE_NET | INTR_MPSAFE, NULL,
-	    ixgbe_msix_link, adapter, &adapter->tag);
-	if (error) {
+	adapter->osdep.ihs[vector] = pci_intr_establish(pc,
+	    adapter->osdep.intrs[vector], IPL_NET, ixgbe_msix_link, adapter);
+	if (adapter->osdep.ihs[vector] == NULL) {
 		adapter->res = NULL;
 		aprint_error_dev(dev, "Failed to register LINK handler\n");
-		return (error);
+		kcpuset_destroy(affinity);
+		return (ENXIO);
 	}
-#if __FreeBSD_version >= 800504
-	bus_describe_intr(dev, adapter->res, adapter->tag, "link");
-#endif
+	/* Round-robin affinity */
+	kcpuset_zero(affinity);
+	kcpuset_set(affinity, cpu_id % ncpu);
+	error = pci_intr_distribute(adapter->osdep.ihs[vector], affinity,NULL);
+
+	aprint_normal_dev(dev,
+	    "for link, interrupting at %s", intrstr);
+	if (error == 0)
+		aprint_normal(", affinity to cpu %d\n", cpu_id);
+	else
+		aprint_normal("\n");
+
 	adapter->linkvec = vector;
 	/* Tasklets for Link, SFP and Multispeed Fiber */
 	adapter->link_si =
@@ -2699,6 +2757,7 @@ ixgbe_allocate_msix(struct adapter *adap
 	    softint_establish(SOFTINT_NET, ixgbe_reinit_fdir, adapter);
 #endif
 
+	kcpuset_destroy(affinity);
 	return (0);
 #endif
 }
@@ -2713,33 +2772,21 @@ ixgbe_setup_msix(struct adapter *adapter
 	return 0;
 #else
 	device_t dev = adapter->dev;
-	int rid, want, queues, msgs;
+	int want, queues, msgs;
 
 	/* Override by tuneable */
 	if (ixgbe_enable_msix == 0)
 		goto msi;
 
 	/* First try MSI/X */
-	msgs = pci_msix_count(dev); 
-	if (msgs == 0)
-		goto msi;
-	rid = PCI_BAR(MSIX_82598_BAR);
-	adapter->msix_mem = bus_alloc_resource_any(dev,
-	    SYS_RES_MEMORY, &rid, RF_ACTIVE);
-       	if (adapter->msix_mem == NULL) {
-		rid += 4;	/* 82599 maps in higher BAR */
-		adapter->msix_mem = bus_alloc_resource_any(dev,
-		    SYS_RES_MEMORY, &rid, RF_ACTIVE);
-	}
-       	if (adapter->msix_mem == NULL) {
-		/* May not be enabled */
-		device_printf(adapter->dev,
-		    "Unable to map MSIX table \n");
+	msgs = pci_msix_count(adapter->osdep.pc, adapter->osdep.tag);
+	if (msgs < IXG_MSIX_NINTR)
 		goto msi;
-	}
+
+	adapter->msix_mem = (void *)1; /* XXX */
 
 	/* Figure out a reasonable auto config value */
-	queues = (mp_ncpus > (msgs-1)) ? (msgs-1) : mp_ncpus;
+	queues = (ncpu > (msgs-1)) ? (msgs-1) : ncpu;
 
 	/* Override based on tuneable */
 	if (ixgbe_num_queues != 0)
@@ -2762,44 +2809,34 @@ ixgbe_setup_msix(struct adapter *adapter
 	if (msgs >= want)
 		msgs = want;
 	else {
-               	device_printf(adapter->dev,
+               	aprint_error_dev(dev,
 		    "MSIX Configuration Problem, "
 		    "%d vectors but %d queues wanted!\n",
 		    msgs, want);
 		goto msi;
 	}
-	if ((pci_alloc_msix(dev, &msgs) == 0) && (msgs == want)) {
-               	device_printf(adapter->dev,
-		    "Using MSIX interrupts with %d vectors\n", msgs);
-		adapter->num_queues = queues;
-		return (msgs);
-	}
+	device_printf(dev,
+	    "Using MSIX interrupts with %d vectors\n", msgs);
+	adapter->num_queues = queues;
+	return (msgs);
+
 	/*
 	** If MSIX alloc failed or provided us with
 	** less than needed, free and fall through to MSI
 	*/
-	pci_release_msi(dev);
-
 msi:
-       	msgs = pci_msi_count(dev);
-       	if (adapter->msix_mem != NULL) {
-		bus_release_resource(dev, SYS_RES_MEMORY,
-		    rid, adapter->msix_mem);
-		adapter->msix_mem = NULL;
-	}
+       	msgs = pci_msi_count(adapter->osdep.pc, adapter->osdep.tag);
+	adapter->msix_mem = NULL; /* XXX */
        	msgs = 1;
-       	if (pci_alloc_msi(dev, &msgs) == 0) {
-               	device_printf(adapter->dev,"Using an MSI interrupt\n");
-		return (msgs);
-	}
-	device_printf(adapter->dev,"Using a Legacy interrupt\n");
-	return (0);
+	aprint_normal_dev(dev,"Using an MSI interrupt\n");
+	return (msgs);
 #endif
 }
 
 
 static int
-ixgbe_allocate_pci_resources(struct adapter *adapter, const struct pci_attach_args *pa)
+ixgbe_allocate_pci_resources(struct adapter *adapter,
+    const struct pci_attach_args *pa)
 {
 	pcireg_t	memtype;
 	device_t        dev = adapter->dev;
@@ -2850,60 +2887,35 @@ ixgbe_free_pci_resources(struct adapter 
 {
 #if defined(NETBSD_MSI_OR_MSIX)
 	struct 		ix_queue *que = adapter->queues;
-	device_t	dev = adapter->dev;
 #endif
 	int		rid;
 
 #if defined(NETBSD_MSI_OR_MSIX)
-	int		 memrid;
-	if (adapter->hw.mac.type == ixgbe_mac_82598EB)
-		memrid = PCI_BAR(MSIX_82598_BAR);
-	else
-		memrid = PCI_BAR(MSIX_82599_BAR);
-
-	/*
-	** There is a slight possibility of a failure mode
-	** in attach that will result in entering this function
-	** before interrupt resources have been initialized, and
-	** in that case we do not want to execute the loops below
-	** We can detect this reliably by the state of the adapter
-	** res pointer.
-	*/
-	if (adapter->res == NULL)
-		goto mem;
-
 	/*
 	**  Release all msix queue resources:
 	*/
 	for (int i = 0; i < adapter->num_queues; i++, que++) {
-		rid = que->msix + 1;
-		if (que->tag != NULL) {
-			bus_teardown_intr(dev, que->res, que->tag);
-			que->tag = NULL;
-		}
 		if (que->res != NULL)
-			bus_release_resource(dev, SYS_RES_IRQ, rid, que->res);
+			pci_intr_disestablish(adapter->osdep.pc,
+			    adapter->osdep.ihs[i]);
 	}
 #endif
 
 	/* Clean the Legacy or Link interrupt last */
 	if (adapter->linkvec) /* we are doing MSIX */
-		rid = adapter->linkvec + 1;
+		rid = adapter->linkvec;
 	else
-		(adapter->msix != 0) ? (rid = 1):(rid = 0);
+		rid = 0;
 
-	if (adapter->osdep.intr != NULL)
-		pci_intr_disestablish(adapter->osdep.pc, adapter->osdep.intr);
-	adapter->osdep.intr = NULL;
+	if (adapter->osdep.ihs[rid] != NULL) {
+		pci_intr_disestablish(adapter->osdep.pc,
+		    adapter->osdep.ihs[rid]);
+		adapter->osdep.ihs[rid] = NULL;
+	}
 
 #if defined(NETBSD_MSI_OR_MSIX)
-mem:
-	if (adapter->msix)
-		pci_release_msi(dev);
-
-	if (adapter->msix_mem != NULL)
-		bus_release_resource(dev, SYS_RES_MEMORY,
-		    memrid, adapter->msix_mem);
+	pci_intr_release(adapter->osdep.pc, adapter->osdep.intrs,
+	    adapter->osdep.nintrs);
 #endif
 
 	if (adapter->osdep.mem_size != 0) {

Index: src/sys/dev/pci/ixgbe/ixgbe_82599.c
diff -u src/sys/dev/pci/ixgbe/ixgbe_82599.c:1.10 src/sys/dev/pci/ixgbe/ixgbe_82599.c:1.11
--- src/sys/dev/pci/ixgbe/ixgbe_82599.c:1.10	Wed Aug  5 04:08:44 2015
+++ src/sys/dev/pci/ixgbe/ixgbe_82599.c	Thu Aug 13 04:56:43 2015
@@ -31,7 +31,7 @@
 
 ******************************************************************************/
 /*$FreeBSD: head/sys/dev/ixgbe/ixgbe_82599.c 251964 2013-06-18 21:28:19Z jfv $*/
-/*$NetBSD: ixgbe_82599.c,v 1.10 2015/08/05 04:08:44 msaitoh Exp $*/
+/*$NetBSD: ixgbe_82599.c,v 1.11 2015/08/13 04:56:43 msaitoh Exp $*/
 
 #include "ixgbe_type.h"
 #include "ixgbe_82599.h"
@@ -793,8 +793,8 @@ s32 ixgbe_setup_mac_link_multispeed_fibe
 			msec_delay(100);
 
 			/* If we have link, just jump out */
-			status = ixgbe_check_link(hw, &link_speed,
-						  &link_up, FALSE);
+			status = ixgbe_check_link(hw, &link_speed, &link_up,
+			    FALSE);
 			if (status != IXGBE_SUCCESS)
 				return status;
 
Index: src/sys/dev/pci/ixgbe/ixv.c
diff -u src/sys/dev/pci/ixgbe/ixv.c:1.10 src/sys/dev/pci/ixgbe/ixv.c:1.11
--- src/sys/dev/pci/ixgbe/ixv.c:1.10	Wed Aug  5 04:08:44 2015
+++ src/sys/dev/pci/ixgbe/ixv.c	Thu Aug 13 04:56:43 2015
@@ -31,7 +31,7 @@
 
 ******************************************************************************/
 /*$FreeBSD: head/sys/dev/ixgbe/ixv.c 275358 2014-12-01 11:45:24Z hselasky $*/
-/*$NetBSD: ixv.c,v 1.10 2015/08/05 04:08:44 msaitoh Exp $*/
+/*$NetBSD: ixv.c,v 1.11 2015/08/13 04:56:43 msaitoh Exp $*/
 
 #include "opt_inet.h"
 #include "opt_inet6.h"
@@ -96,7 +96,8 @@ static int      ixv_media_change(struct 
 static void     ixv_identify_hardware(struct adapter *);
 static int      ixv_allocate_pci_resources(struct adapter *,
 		    const struct pci_attach_args *);
-static int      ixv_allocate_msix(struct adapter *);
+static int      ixv_allocate_msix(struct adapter *,
+		    const struct pci_attach_args *);
 static int	ixv_allocate_queues(struct adapter *);
 static int	ixv_setup_msix(struct adapter *);
 static void	ixv_free_pci_resources(struct adapter *);
@@ -157,8 +158,8 @@ static __inline void ixv_rx_input(struct
 		    struct mbuf *, u32);
 
 /* The MSI/X Interrupt handlers */
-static void	ixv_msix_que(void *);
-static void	ixv_msix_mbx(void *);
+static int	ixv_msix_que(void *);
+static int	ixv_msix_mbx(void *);
 
 /* Deferred interrupt tasklets */
 static void	ixv_handle_que(void *);
@@ -443,7 +444,7 @@ ixv_attach(device_t parent, device_t dev
 		goto err_late;
 	}
 	
-	error = ixv_allocate_msix(adapter); 
+	error = ixv_allocate_msix(adapter, pa); 
 	if (error) 
 		goto err_late;
 
@@ -589,7 +590,7 @@ ixv_start_locked(struct tx_ring *txr, st
 		if (m_head == NULL)
 			break;
 
-		if (ixv_xmit(txr, m_head) == EAGAIN) {
+		if ((rc = ixv_xmit(txr, m_head)) == EAGAIN) {
 			ifp->if_flags |= IFF_OACTIVE;
 			break;
 		}
@@ -1063,7 +1064,7 @@ ixv_handle_que(void *context)
  *  MSI Queue Interrupt Service routine
  *
  **********************************************************************/
-void
+int
 ixv_msix_que(void *arg)
 {
 	struct ix_queue	*que = arg;
@@ -1148,10 +1149,10 @@ no_calc:
 		softint_schedule(que->que_si);
 	else /* Reenable this interrupt */
 		ixv_enable_queue(adapter, que->msix);
-	return;
+	return 1;
 }
 
-static void
+static int
 ixv_msix_mbx(void *arg)
 {
 	struct adapter	*adapter = arg;
@@ -1170,7 +1171,7 @@ ixv_msix_mbx(void *arg)
 		softint_schedule(adapter->mbx_si);
 
 	IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, IXGBE_EIMS_OTHER);
-	return;
+	return 1;
 }
 
 /*********************************************************************
@@ -1260,7 +1261,7 @@ ixv_xmit(struct tx_ring *txr, struct mbu
 	struct ethercom *ec = &adapter->osdep.ec;
 	u32		olinfo_status = 0, cmd_type_len;
 	u32		paylen = 0;
-	int             i, j, error, nsegs;
+	int             i, j, error;
 	int		first, last = 0;
 	bus_dmamap_t	map;
 	struct ixv_tx_buf *txbuf;
@@ -1309,7 +1310,7 @@ ixv_xmit(struct tx_ring *txr, struct mbu
 	}
 
 	/* Make certain there are enough descriptors */
-	if (nsegs > txr->tx_avail - 2) {
+	if (map->dm_nsegs > txr->tx_avail - 2) {
 		txr->no_desc_avail.ev_count++;
 		/* XXX s/ixgbe/ixv/ */
 		ixgbe_dmamap_unload(txr->txtag, txbuf->map);
@@ -1655,76 +1656,97 @@ ixv_identify_hardware(struct adapter *ad
  *
  **********************************************************************/
 static int
-ixv_allocate_msix(struct adapter *adapter)
+ixv_allocate_msix(struct adapter *adapter, const struct pci_attach_args *pa)
 {
 #if !defined(NETBSD_MSI_OR_MSIX)
 	return 0;
 #else
 	device_t        dev = adapter->dev;
-	struct 		ix_queue *que = adapter->queues;
+	struct ix_queue *que = adapter->queues;
 	int 		error, rid, vector = 0;
-	pcitag_t tag;
 	pci_chipset_tag_t pc;
+	pcitag_t	tag;
+	char intrbuf[PCI_INTRSTR_LEN];
+	const char	*intrstr = NULL;
+	kcpuset_t	*affinity;
+	int		cpu_id = 0;
 
 	pc = adapter->osdep.pc;
 	tag = adapter->osdep.tag;
 
+	if (pci_msix_alloc_exact(pa,
+		&adapter->osdep.intrs, IXG_MSIX_NINTR) != 0)
+		return (ENXIO);
+
+	kcpuset_create(&affinity, false);
 	for (int i = 0; i < adapter->num_queues; i++, vector++, que++) {
-		rid = vector + 1;
-		que->res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
-		    RF_SHAREABLE | RF_ACTIVE);
-		if (que->res == NULL) {
-			aprint_error_dev(dev,"Unable to allocate"
-		    	    " bus resource: que interrupt [%d]\n", vector);
-			return (ENXIO);
-		}
+		intrstr = pci_intr_string(pc, adapter->osdep.intrs[i], intrbuf,
+		    sizeof(intrbuf));
+#ifdef IXV_MPSAFE
+		pci_intr_setattr(pc, adapter->osdep.intrs[i], PCI_INTR_MPSAFE,
+		    true);
+#endif
 		/* Set the handler function */
-		error = bus_setup_intr(dev, que->res,
-		    INTR_TYPE_NET | INTR_MPSAFE, NULL,
-		    ixv_msix_que, que, &que->tag);
-		if (error) {
+		adapter->osdep.ihs[i] = pci_intr_establish(pc,
+		    adapter->osdep.intrs[i], IPL_NET, ixv_msix_que, que);
+		if (adapter->osdep.ihs[i] == NULL) {
 			que->res = NULL;
 			aprint_error_dev(dev,
 			    "Failed to register QUE handler");
-			return (error);
+			kcpuset_destroy(affinity);
+			return (ENXIO);
 		}
-#if __FreeBSD_version >= 800504
-		bus_describe_intr(dev, que->res, que->tag, "que %d", i);
-#endif
 		que->msix = vector;
         	adapter->que_mask |= (u64)(1 << que->msix);
-		/*
-		** Bind the msix vector, and thus the
-		** ring to the corresponding cpu.
-		*/
-		if (adapter->num_queues > 1)
-			bus_bind_intr(dev, que->res, i);
 
+		cpu_id = i;
+		/* Round-robin affinity */
+		kcpuset_zero(affinity);
+		kcpuset_set(affinity, cpu_id % ncpu);
+		error = pci_intr_distribute(adapter->osdep.ihs[i], affinity,
+		    NULL);
+		aprint_normal_dev(dev, "for TX/RX, interrupting at %s",
+		    intrstr);
+		if (error == 0)
+			aprint_normal(", bound queue %d to cpu %d\n",
+			    i, cpu_id);
+		else
+			aprint_normal("\n");
+		
 		que->que_si = softint_establish(SOFTINT_NET, ixv_handle_que,
 		    que);
+		if (que->que_si == NULL) {
+			aprint_error_dev(dev,
+			    "could not establish software interrupt\n"); 
+		}
 	}
 
 	/* and Mailbox */
-	rid = vector + 1;
-	adapter->res = bus_alloc_resource_any(dev,
-    	    SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE);
-	if (!adapter->res) {
-		aprint_error_dev(dev,"Unable to allocate"
-    	    " bus resource: MBX interrupt [%d]\n", rid);
-		return (ENXIO);
-	}
+	cpu_id++;
+	intrstr = pci_intr_string(pc, adapter->osdep.intrs[vector], intrbuf,
+	    sizeof(intrbuf));
+#ifdef IXG_MPSAFE
+	pci_intr_setattr(pc, &adapter->osdep.intrs[vector], PCI_INTR_MPSAFE, true);
+#endif
 	/* Set the mbx handler function */
-	error = bus_setup_intr(dev, adapter->res,
-	    INTR_TYPE_NET | INTR_MPSAFE, NULL,
-	    ixv_msix_mbx, adapter, &adapter->tag);
-	if (error) {
+	adapter->osdep.ihs[vector] = pci_intr_establish(pc,
+	    adapter->osdep.intrs[vector], IPL_NET, ixv_msix_mbx, adapter);
+	if (adapter->osdep.ihs[vector] == NULL) {
 		adapter->res = NULL;
-		aprint_error_dev(dev, "Failed to register LINK handler");
-		return (error);
+		aprint_error_dev(dev, "Failed to register LINK handler\n");
+		kcpuset_destroy(affinity);
+		return (ENXIO);
+	}
+	/* Round-robin affinity */
+	kcpuset_zero(affinity);
+	kcpuset_set(affinity, cpu_id % ncpu);
+	error = pci_intr_distribute(adapter->osdep.ihs[vector], affinity,NULL);
+
+	aprint_normal_dev(dev,
+	    "for link, interrupting at %s, ", intrstr);
+	if (error == 0) {
+		aprint_normal("affinity to cpu %d\n", cpu_id);
 	}
-#if __FreeBSD_version >= 800504
-	bus_describe_intr(dev, adapter->res, adapter->tag, "mbx");
-#endif
 	adapter->mbxvec = vector;
 	/* Tasklets for Mailbox */
 	adapter->mbx_si = softint_establish(SOFTINT_NET, ixv_handle_mbx,
@@ -1740,9 +1762,9 @@ ixv_allocate_msix(struct adapter *adapte
 		int msix_ctrl;
 		pci_get_capability(pc, tag, PCI_CAP_MSIX, &rid, NULL);
 		rid += PCI_MSIX_CTL;
-		msix_ctrl = pci_read_config(pc, tag, rid);
+		msix_ctrl = pci_conf_read(pc, tag, rid);
 		msix_ctrl |= PCI_MSIX_CTL_ENABLE;
-		pci_conf_write(pc, tag, msix_ctrl);
+		pci_conf_write(pc, tag, rid, msix_ctrl);
 	}
 
 	return (0);
@@ -1760,39 +1782,23 @@ ixv_setup_msix(struct adapter *adapter)
 	return 0;
 #else
 	device_t dev = adapter->dev;
-	int rid, want;
+	int want, msgs;
 
 
-	/* First try MSI/X */
-	rid = PCIR_BAR(3);
-	adapter->msix_mem = bus_alloc_resource_any(dev,
-	    SYS_RES_MEMORY, &rid, RF_ACTIVE);
-       	if (adapter->msix_mem == NULL) {
-		device_printf(adapter->dev,
-		    "Unable to map MSIX table \n");
-		goto out;
-	}
-
 	/*
 	** Want two vectors: one for a queue,
 	** plus an additional for mailbox.
 	*/
-	want = 2;
-	if ((pci_alloc_msix(dev, &want) == 0) && (want == 2)) {
-               	device_printf(adapter->dev,
-		    "Using MSIX interrupts with %d vectors\n", want);
-		return (want);
-	}
-	/* Release in case alloc was insufficient */
-	pci_release_msi(dev);
-out:
-       	if (adapter->msix_mem != NULL) {
-		bus_release_resource(dev, SYS_RES_MEMORY,
-		    rid, adapter->msix_mem);
-		adapter->msix_mem = NULL;
+	msgs = pci_msix_count(adapter->osdep.pc, adapter->osdep.tag);
+	if (msgs < IXG_MSIX_NINTR) {
+		aprint_error_dev(dev,"MSIX config error\n");
+		return (ENXIO);
 	}
-	device_printf(adapter->dev,"MSIX config error\n");
-	return (ENXIO);
+
+	adapter->msix_mem = (void *)1; /* XXX */
+	aprint_normal_dev(dev,
+	    "Using MSIX interrupts with %d vectors\n", msgs);
+	return (want);
 #endif
 }
 
@@ -1851,62 +1857,42 @@ map_err:
 static void
 ixv_free_pci_resources(struct adapter * adapter)
 {
-#if defined(NETBSD_MSI_OR_MSIX)
+#if !defined(NETBSD_MSI_OR_MSIX)
+#else
 	struct 		ix_queue *que = adapter->queues;
-	device_t	dev = adapter->dev;
-	int		rid, memrid;
-
-	memrid = PCI_BAR(MSIX_BAR);
-
-	/*
-	** There is a slight possibility of a failure mode
-	** in attach that will result in entering this function
-	** before interrupt resources have been initialized, and
-	** in that case we do not want to execute the loops below
-	** We can detect this reliably by the state of the adapter
-	** res pointer.
-	*/
-	if (adapter->res == NULL)
-		goto mem;
+	int		rid;
 
 	/*
 	**  Release all msix queue resources:
 	*/
 	for (int i = 0; i < adapter->num_queues; i++, que++) {
 		rid = que->msix + 1;
-		if (que->tag != NULL) {
-			bus_teardown_intr(dev, que->res, que->tag);
-			que->tag = NULL;
-		}
 		if (que->res != NULL)
-			bus_release_resource(dev, SYS_RES_IRQ, rid, que->res);
+			pci_intr_disestablish(adapter->osdep.pc,
+			    adapter->osdep.ihs[i]);
 	}
 
-
 	/* Clean the Legacy or Link interrupt last */
 	if (adapter->mbxvec) /* we are doing MSIX */
 		rid = adapter->mbxvec + 1;
 	else
 		(adapter->msix != 0) ? (rid = 1):(rid = 0);
 
-	if (adapter->tag != NULL) {
-		bus_teardown_intr(dev, adapter->res, adapter->tag);
-		adapter->tag = NULL;
-	}
-	if (adapter->res != NULL)
-		bus_release_resource(dev, SYS_RES_IRQ, rid, adapter->res);
-
-mem:
-	if (adapter->msix)
-		pci_release_msi(dev);
-
-	if (adapter->msix_mem != NULL)
-		bus_release_resource(dev, SYS_RES_MEMORY,
-		    memrid, adapter->msix_mem);
-
-	if (adapter->pci_mem != NULL)
-		bus_release_resource(dev, SYS_RES_MEMORY,
-		    PCIR_BAR(0), adapter->pci_mem);
+	if (adapter->osdep.ihs[rid] != NULL)
+		pci_intr_disestablish(adapter->osdep.pc,
+		    adapter->osdep.ihs[rid]);
+	adapter->osdep.ihs[rid] = NULL;
+
+#if defined(NETBSD_MSI_OR_MSIX)
+	pci_intr_release(adapter->osdep.pc, adapter->osdep.intrs,
+	    adapter->osdep.nintrs);
+#endif
+
+	if (adapter->osdep.mem_size != 0) {
+		bus_space_unmap(adapter->osdep.mem_bus_space_tag,
+		    adapter->osdep.mem_bus_space_handle,
+		    adapter->osdep.mem_size);
+	}
 
 #endif
 	return;
@@ -4004,18 +3990,18 @@ ixv_print_hw_stats(struct adapter * adap
 {
         device_t dev = adapter->dev;
 
-        device_printf(dev,"Std Mbuf Failed = %lu\n",
+        device_printf(dev,"Std Mbuf Failed = %"PRIu64"\n",
                adapter->mbuf_defrag_failed.ev_count);
-        device_printf(dev,"Driver dropped packets = %lu\n",
+        device_printf(dev,"Driver dropped packets = %"PRIu64"\n",
                adapter->dropped_pkts.ev_count);
-        device_printf(dev, "watchdog timeouts = %ld\n",
+        device_printf(dev, "watchdog timeouts = %"PRIu64"\n",
                adapter->watchdog_events.ev_count);
 
-        device_printf(dev,"Good Packets Rcvd = %llu\n",
+        device_printf(dev,"Good Packets Rcvd = %lld\n",
                (long long)adapter->stats.vfgprc);
-        device_printf(dev,"Good Packets Xmtd = %llu\n",
+        device_printf(dev,"Good Packets Xmtd = %lld\n",
                (long long)adapter->stats.vfgptc);
-        device_printf(dev,"TSO Transmissions = %lu\n",
+        device_printf(dev,"TSO Transmissions = %"PRIu64"\n",
                adapter->tso_tx.ev_count);
 
 }

Index: src/sys/dev/pci/ixgbe/ixgbe_osdep.h
diff -u src/sys/dev/pci/ixgbe/ixgbe_osdep.h:1.9 src/sys/dev/pci/ixgbe/ixgbe_osdep.h:1.10
--- src/sys/dev/pci/ixgbe/ixgbe_osdep.h:1.9	Wed Aug  5 04:08:44 2015
+++ src/sys/dev/pci/ixgbe/ixgbe_osdep.h	Thu Aug 13 04:56:43 2015
@@ -31,7 +31,7 @@
 
 ******************************************************************************/
 /*$FreeBSD: head/sys/dev/ixgbe/ixgbe_osdep.h 251964 2013-06-18 21:28:19Z jfv $*/
-/*$NetBSD: ixgbe_osdep.h,v 1.9 2015/08/05 04:08:44 msaitoh Exp $*/
+/*$NetBSD: ixgbe_osdep.h,v 1.10 2015/08/13 04:56:43 msaitoh Exp $*/
 
 #ifndef _IXGBE_OS_H_
 #define _IXGBE_OS_H_
@@ -59,7 +59,7 @@
 #define usec_delay(x) DELAY(x)
 #define msec_delay(x) DELAY(1000*(x))
 
-#define DBG 0 
+#define DBG 0
 #define MSGOUT(S, A, B)     printf(S "\n", A, B)
 #define DEBUGFUNC(F)        DEBUGOUT(F);
 #if DBG
@@ -71,9 +71,9 @@
 	#define DEBUGOUT5(S,A,B,C,D,E)  printf(S "\n",A,B,C,D,E)
 	#define DEBUGOUT6(S,A,B,C,D,E,F)  printf(S "\n",A,B,C,D,E,F)
 	#define DEBUGOUT7(S,A,B,C,D,E,F,G)  printf(S "\n",A,B,C,D,E,F,G)
-	#define ERROR_REPORT1(S,A)      printf(S "\n",A)
-	#define ERROR_REPORT2(S,A,B)    printf(S "\n",A,B)
-	#define ERROR_REPORT3(S,A,B,C)  printf(S "\n",A,B,C)
+	#define ERROR_REPORT1(S,A)      printf(S A "\n")
+	#define ERROR_REPORT2(S,A,B)    printf(S A "\n",B)
+	#define ERROR_REPORT3(S,A,B,C)  printf(S A "\n",B,C)
 #else
 	#define DEBUGOUT(S)		do { } while (/*CONSTCOND*/false)
 	#define DEBUGOUT1(S,A)		do { } while (/*CONSTCOND*/false)
@@ -125,6 +125,20 @@ typedef uint64_t	u64;
 
 #define le16_to_cpu 
 
+#ifdef __HAVE_PCI_MSI_MSIX
+#define NETBSD_MSI_OR_MSIX
+/*
+ * This device driver divides interrupt to TX, RX and link state.
+ * Each MSI-X vector indexes are below.
+ */
+#define IXG_MSIX_NINTR		2
+#define IXG_MSIX_TXRXINTR_IDX	0
+#define IXG_MSIX_LINKINTR_IDX	1
+#define IXG_MAX_NINTR		IXG_MSIX_NINTR
+#else
+#define IXG_MAX_NINTR		1
+#endif
+
 #if __FreeBSD_version < 800000
 #if defined(__i386__) || defined(__amd64__)
 #define mb()	__asm volatile("mfence" ::: "memory")
@@ -176,8 +190,9 @@ struct ixgbe_osdep
 	bus_size_t         mem_size;
 	bus_dma_tag_t      dmat;
 	device_t           dev;
-	pci_intr_handle_t  ih;
-	void               *intr;
+	pci_intr_handle_t  *intrs;
+	int		   nintrs;
+	void               *ihs[IXG_MAX_NINTR];
 	bool		   attached;
 };
 

Index: src/sys/dev/pci/ixgbe/ixgbe_type.h
diff -u src/sys/dev/pci/ixgbe/ixgbe_type.h:1.11 src/sys/dev/pci/ixgbe/ixgbe_type.h:1.12
--- src/sys/dev/pci/ixgbe/ixgbe_type.h:1.11	Wed Aug  5 04:08:44 2015
+++ src/sys/dev/pci/ixgbe/ixgbe_type.h	Thu Aug 13 04:56:43 2015
@@ -31,7 +31,7 @@
 
 ******************************************************************************/
 /*$FreeBSD: head/sys/dev/ixgbe/ixgbe_type.h 251964 2013-06-18 21:28:19Z jfv $*/
-/*$NetBSD: ixgbe_type.h,v 1.11 2015/08/05 04:08:44 msaitoh Exp $*/
+/*$NetBSD: ixgbe_type.h,v 1.12 2015/08/13 04:56:43 msaitoh Exp $*/
 
 #ifndef _IXGBE_TYPE_H_
 #define _IXGBE_TYPE_H_
@@ -80,6 +80,13 @@
  * (Ex: Flow control autonegotiation or an unsupported SFP+ module.)
  */
 
+#define IXGBE_ERROR_INVALID_STATE "invalid state: "
+#define IXGBE_ERROR_POLLING	"polling: "
+#define IXGBE_ERROR_CAUTION	"caution: "
+#define IXGBE_ERROR_SOFTWARE	"software: "
+#define IXGBE_ERROR_ARGUMENT	"arg: "
+#define IXGBE_ERROR_UNSUPPORTED	"unsupported: "
+
 #include "ixgbe_osdep.h"
 
 

Reply via email to