Tue Oct 13 08:20:02 2015 UTC ()
refactor: separate interrupts setup processing from wm_attach


(knakahara)
diff -r1.359 -r1.360 src/sys/dev/pci/if_wm.c

cvs diff -r1.359 -r1.360 src/sys/dev/pci/if_wm.c (expand / switch to unified diff)

--- src/sys/dev/pci/if_wm.c 2015/10/13 08:17:15 1.359
+++ src/sys/dev/pci/if_wm.c 2015/10/13 08:20:02 1.360
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: if_wm.c,v 1.359 2015/10/13 08:17:15 knakahara Exp $ */ 1/* $NetBSD: if_wm.c,v 1.360 2015/10/13 08:20:02 knakahara Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc. 4 * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Written by Jason R. Thorpe for Wasabi Systems, Inc. 7 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
@@ -73,27 +73,27 @@ @@ -73,27 +73,27 @@
73 * TODO (in order of importance): 73 * TODO (in order of importance):
74 * 74 *
75 * - Check XXX'ed comments 75 * - Check XXX'ed comments
76 * - EEE (Energy Efficiency Ethernet) 76 * - EEE (Energy Efficiency Ethernet)
77 * - Multi queue 77 * - Multi queue
78 * - Image Unique ID 78 * - Image Unique ID
79 * - LPLU other than PCH* 79 * - LPLU other than PCH*
80 * - Virtual Function 80 * - Virtual Function
81 * - Set LED correctly (based on contents in EEPROM) 81 * - Set LED correctly (based on contents in EEPROM)
82 * - Rework how parameters are loaded from the EEPROM. 82 * - Rework how parameters are loaded from the EEPROM.
83 */ 83 */
84 84
85#include <sys/cdefs.h> 85#include <sys/cdefs.h>
86__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.359 2015/10/13 08:17:15 knakahara Exp $"); 86__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.360 2015/10/13 08:20:02 knakahara Exp $");
87 87
88#ifdef _KERNEL_OPT 88#ifdef _KERNEL_OPT
89#include "opt_net_mpsafe.h" 89#include "opt_net_mpsafe.h"
90#endif 90#endif
91 91
92#include <sys/param.h> 92#include <sys/param.h>
93#include <sys/systm.h> 93#include <sys/systm.h>
94#include <sys/callout.h> 94#include <sys/callout.h>
95#include <sys/mbuf.h> 95#include <sys/mbuf.h>
96#include <sys/malloc.h> 96#include <sys/malloc.h>
97#include <sys/kmem.h> 97#include <sys/kmem.h>
98#include <sys/kernel.h> 98#include <sys/kernel.h>
99#include <sys/socket.h> 99#include <sys/socket.h>
@@ -603,26 +603,28 @@ static void wm_start_locked(struct ifnet @@ -603,26 +603,28 @@ static void wm_start_locked(struct ifnet
603static int wm_nq_tx_offload(struct wm_softc *, struct wm_txsoft *, 603static int wm_nq_tx_offload(struct wm_softc *, struct wm_txsoft *,
604 uint32_t *, uint32_t *, bool *); 604 uint32_t *, uint32_t *, bool *);
605static void wm_nq_start(struct ifnet *); 605static void wm_nq_start(struct ifnet *);
606static void wm_nq_start_locked(struct ifnet *); 606static void wm_nq_start_locked(struct ifnet *);
607/* Interrupt */ 607/* Interrupt */
608static int wm_txeof(struct wm_softc *); 608static int wm_txeof(struct wm_softc *);
609static void wm_rxeof(struct wm_softc *); 609static void wm_rxeof(struct wm_softc *);
610static void wm_linkintr_gmii(struct wm_softc *, uint32_t); 610static void wm_linkintr_gmii(struct wm_softc *, uint32_t);
611static void wm_linkintr_tbi(struct wm_softc *, uint32_t); 611static void wm_linkintr_tbi(struct wm_softc *, uint32_t);
612static void wm_linkintr_serdes(struct wm_softc *, uint32_t); 612static void wm_linkintr_serdes(struct wm_softc *, uint32_t);
613static void wm_linkintr(struct wm_softc *, uint32_t); 613static void wm_linkintr(struct wm_softc *, uint32_t);
614static int wm_intr_legacy(void *); 614static int wm_intr_legacy(void *);
615#ifdef WM_MSI_MSIX 615#ifdef WM_MSI_MSIX
 616static int wm_setup_legacy(struct wm_softc *);
 617static int wm_setup_msix(struct wm_softc *);
616static int wm_txintr_msix(void *); 618static int wm_txintr_msix(void *);
617static int wm_rxintr_msix(void *); 619static int wm_rxintr_msix(void *);
618static int wm_linkintr_msix(void *); 620static int wm_linkintr_msix(void *);
619#endif 621#endif
620 622
621/* 623/*
622 * Media related. 624 * Media related.
623 * GMII, SGMII, TBI, SERDES and SFP. 625 * GMII, SGMII, TBI, SERDES and SFP.
624 */ 626 */
625/* Common */ 627/* Common */
626static void wm_tbi_serdes_set_linkled(struct wm_softc *); 628static void wm_tbi_serdes_set_linkled(struct wm_softc *);
627/* GMII related */ 629/* GMII related */
628static void wm_gmii_reset(struct wm_softc *); 630static void wm_gmii_reset(struct wm_softc *);
@@ -751,40 +753,26 @@ static void wm_set_eee_i350(struct wm_so @@ -751,40 +753,26 @@ static void wm_set_eee_i350(struct wm_so
751 * Basically, PHY's workarounds are in the PHY drivers. 753 * Basically, PHY's workarounds are in the PHY drivers.
752 */ 754 */
753static void wm_kmrn_lock_loss_workaround_ich8lan(struct wm_softc *); 755static void wm_kmrn_lock_loss_workaround_ich8lan(struct wm_softc *);
754static void wm_gig_downshift_workaround_ich8lan(struct wm_softc *); 756static void wm_gig_downshift_workaround_ich8lan(struct wm_softc *);
755static void wm_hv_phy_workaround_ich8lan(struct wm_softc *); 757static void wm_hv_phy_workaround_ich8lan(struct wm_softc *);
756static void wm_lv_phy_workaround_ich8lan(struct wm_softc *); 758static void wm_lv_phy_workaround_ich8lan(struct wm_softc *);
757static void wm_k1_gig_workaround_hv(struct wm_softc *, int); 759static void wm_k1_gig_workaround_hv(struct wm_softc *, int);
758static void wm_set_mdio_slow_mode_hv(struct wm_softc *); 760static void wm_set_mdio_slow_mode_hv(struct wm_softc *);
759static void wm_configure_k1_ich8lan(struct wm_softc *, int); 761static void wm_configure_k1_ich8lan(struct wm_softc *, int);
760static void wm_reset_init_script_82575(struct wm_softc *); 762static void wm_reset_init_script_82575(struct wm_softc *);
761static void wm_reset_mdicnfg_82580(struct wm_softc *); 763static void wm_reset_mdicnfg_82580(struct wm_softc *);
762static void wm_pll_workaround_i210(struct wm_softc *); 764static void wm_pll_workaround_i210(struct wm_softc *);
763 765
764#ifdef WM_MSI_MSIX 
765struct _msix_matrix { 
766 const char *intrname; 
767 int(*func)(void *); 
768 int intridx; 
769 int cpuid; 
770} msix_matrix[WM_MSIX_NINTR] = { 
771 { "TX", wm_txintr_msix, WM_MSIX_TXINTR_IDX, WM_MSIX_TXINTR_CPUID }, 
772 { "RX", wm_rxintr_msix, WM_MSIX_RXINTR_IDX, WM_MSIX_RXINTR_CPUID }, 
773 { "LINK", wm_linkintr_msix, WM_MSIX_LINKINTR_IDX, 
774 WM_MSIX_LINKINTR_CPUID }, 
775}; 
776#endif 
777 
778CFATTACH_DECL3_NEW(wm, sizeof(struct wm_softc), 766CFATTACH_DECL3_NEW(wm, sizeof(struct wm_softc),
779 wm_match, wm_attach, wm_detach, NULL, NULL, NULL, DVF_DETACH_SHUTDOWN); 767 wm_match, wm_attach, wm_detach, NULL, NULL, NULL, DVF_DETACH_SHUTDOWN);
780 768
781/* 769/*
782 * Devices supported by this driver. 770 * Devices supported by this driver.
783 */ 771 */
784static const struct wm_product { 772static const struct wm_product {
785 pci_vendor_id_t wmp_vendor; 773 pci_vendor_id_t wmp_vendor;
786 pci_product_id_t wmp_product; 774 pci_product_id_t wmp_product;
787 const char *wmp_name; 775 const char *wmp_name;
788 wm_chip_type wmp_type; 776 wm_chip_type wmp_type;
789 uint32_t wmp_flags; 777 uint32_t wmp_flags;
790#define WMP_F_UNKNOWN WM_MEDIATYPE_UNKNOWN 778#define WMP_F_UNKNOWN WM_MEDIATYPE_UNKNOWN
@@ -1459,48 +1447,48 @@ wm_match(device_t parent, cfdata_t cf, v @@ -1459,48 +1447,48 @@ wm_match(device_t parent, cfdata_t cf, v
1459} 1447}
1460 1448
1461/* The attach function (ca_attach) */ 1449/* The attach function (ca_attach) */
1462static void 1450static void
1463wm_attach(device_t parent, device_t self, void *aux) 1451wm_attach(device_t parent, device_t self, void *aux)
1464{ 1452{
1465 struct wm_softc *sc = device_private(self); 1453 struct wm_softc *sc = device_private(self);
1466 struct pci_attach_args *pa = aux; 1454 struct pci_attach_args *pa = aux;
1467 prop_dictionary_t dict; 1455 prop_dictionary_t dict;
1468 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 1456 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1469 pci_chipset_tag_t pc = pa->pa_pc; 1457 pci_chipset_tag_t pc = pa->pa_pc;
1470#ifndef WM_MSI_MSIX 1458#ifndef WM_MSI_MSIX
1471 pci_intr_handle_t ih; 1459 pci_intr_handle_t ih;
 1460 const char *intrstr = NULL;
 1461 char intrbuf[PCI_INTRSTR_LEN];
1472#else 1462#else
1473 int counts[PCI_INTR_TYPE_SIZE]; 1463 int counts[PCI_INTR_TYPE_SIZE];
1474 pci_intr_type_t max_type; 1464 pci_intr_type_t max_type;
1475#endif 1465#endif
1476 const char *intrstr = NULL; 
1477 const char *eetype, *xname; 1466 const char *eetype, *xname;
1478 bus_space_tag_t memt; 1467 bus_space_tag_t memt;
1479 bus_space_handle_t memh; 1468 bus_space_handle_t memh;
1480 bus_size_t memsize; 1469 bus_size_t memsize;
1481 int memh_valid; 1470 int memh_valid;
1482 int i, error; 1471 int i, error;
1483 const struct wm_product *wmp; 1472 const struct wm_product *wmp;
1484 prop_data_t ea; 1473 prop_data_t ea;
1485 prop_number_t pn; 1474 prop_number_t pn;
1486 uint8_t enaddr[ETHER_ADDR_LEN]; 1475 uint8_t enaddr[ETHER_ADDR_LEN];
1487 uint16_t cfg1, cfg2, swdpin, nvmword; 1476 uint16_t cfg1, cfg2, swdpin, nvmword;
1488 pcireg_t preg, memtype; 1477 pcireg_t preg, memtype;
1489 uint16_t eeprom_data, apme_mask; 1478 uint16_t eeprom_data, apme_mask;
1490 bool force_clear_smbi; 1479 bool force_clear_smbi;
1491 uint32_t link_mode; 1480 uint32_t link_mode;
1492 uint32_t reg; 1481 uint32_t reg;
1493 char intrbuf[PCI_INTRSTR_LEN]; 
1494 1482
1495 sc->sc_dev = self; 1483 sc->sc_dev = self;
1496 callout_init(&sc->sc_tick_ch, CALLOUT_FLAGS); 1484 callout_init(&sc->sc_tick_ch, CALLOUT_FLAGS);
1497 sc->sc_stopping = false; 1485 sc->sc_stopping = false;
1498 1486
1499 wmp = wm_lookup(pa); 1487 wmp = wm_lookup(pa);
1500#ifdef DIAGNOSTIC 1488#ifdef DIAGNOSTIC
1501 if (wmp == NULL) { 1489 if (wmp == NULL) {
1502 printf("\n"); 1490 printf("\n");
1503 panic("wm_attach: impossible"); 1491 panic("wm_attach: impossible");
1504 } 1492 }
1505#endif 1493#endif
1506 sc->sc_mediatype = WMP_MEDIATYPE(wmp->wmp_flags); 1494 sc->sc_mediatype = WMP_MEDIATYPE(wmp->wmp_flags);
@@ -1673,114 +1661,55 @@ wm_attach(device_t parent, device_t self @@ -1673,114 +1661,55 @@ wm_attach(device_t parent, device_t self
1673 /* Allocation settings */ 1661 /* Allocation settings */
1674 max_type = PCI_INTR_TYPE_MSIX; 1662 max_type = PCI_INTR_TYPE_MSIX;
1675 counts[PCI_INTR_TYPE_MSIX] = WM_MAX_NINTR; 1663 counts[PCI_INTR_TYPE_MSIX] = WM_MAX_NINTR;
1676 counts[PCI_INTR_TYPE_MSI] = 1; 1664 counts[PCI_INTR_TYPE_MSI] = 1;
1677 counts[PCI_INTR_TYPE_INTX] = 1; 1665 counts[PCI_INTR_TYPE_INTX] = 1;
1678 1666
1679alloc_retry: 1667alloc_retry:
1680 if (pci_intr_alloc(pa, &sc->sc_intrs, counts, max_type) != 0) { 1668 if (pci_intr_alloc(pa, &sc->sc_intrs, counts, max_type) != 0) {
1681 aprint_error_dev(sc->sc_dev, "failed to allocate interrupt\n"); 1669 aprint_error_dev(sc->sc_dev, "failed to allocate interrupt\n");
1682 return; 1670 return;
1683 } 1671 }
1684 1672
1685 if (pci_intr_type(sc->sc_intrs[0]) == PCI_INTR_TYPE_MSIX) { 1673 if (pci_intr_type(sc->sc_intrs[0]) == PCI_INTR_TYPE_MSIX) {
1686 void *vih; 1674 error = wm_setup_msix(sc);
1687 kcpuset_t *affinity; 1675 if (error) {
1688 char intr_xname[INTRDEVNAMEBUF]; 1676 pci_intr_release(pc, sc->sc_intrs,
1689 1677 counts[PCI_INTR_TYPE_MSIX]);
1690 kcpuset_create(&affinity, false); 1678
1691 1679 /* Setup for MSI: Disable MSI-X */
1692 for (i = 0; i < WM_MSIX_NINTR; i++) { 1680 max_type = PCI_INTR_TYPE_MSI;
1693 intrstr = pci_intr_string(pc, 1681 counts[PCI_INTR_TYPE_MSI] = 1;
1694 sc->sc_intrs[msix_matrix[i].intridx], intrbuf, 1682 counts[PCI_INTR_TYPE_INTX] = 1;
1695 sizeof(intrbuf)); 1683 goto alloc_retry;
1696#ifdef WM_MPSAFE 
1697 pci_intr_setattr(pc, 
1698 &sc->sc_intrs[msix_matrix[i].intridx], 
1699 PCI_INTR_MPSAFE, true); 
1700#endif 
1701 memset(intr_xname, 0, sizeof(intr_xname)); 
1702 strlcat(intr_xname, device_xname(sc->sc_dev), 
1703 sizeof(intr_xname)); 
1704 strlcat(intr_xname, msix_matrix[i].intrname, 
1705 sizeof(intr_xname)); 
1706 vih = pci_intr_establish_xname(pc, 
1707 sc->sc_intrs[msix_matrix[i].intridx], IPL_NET, 
1708 msix_matrix[i].func, sc, intr_xname); 
1709 if (vih == NULL) { 
1710 aprint_error_dev(sc->sc_dev, 
1711 "unable to establish MSI-X(for %s)%s%s\n", 
1712 msix_matrix[i].intrname, 
1713 intrstr ? " at " : "", 
1714 intrstr ? intrstr : ""); 
1715 pci_intr_release(sc->sc_pc, sc->sc_intrs, 
1716 WM_MSIX_NINTR); 
1717 kcpuset_destroy(affinity); 
1718 
1719 /* Setup for MSI: Disable MSI-X */ 
1720 max_type = PCI_INTR_TYPE_MSI; 
1721 counts[PCI_INTR_TYPE_MSI] = 1; 
1722 counts[PCI_INTR_TYPE_INTX] = 1; 
1723 goto alloc_retry; 
1724 } 
1725 kcpuset_zero(affinity); 
1726 /* Round-robin affinity */ 
1727 kcpuset_set(affinity, msix_matrix[i].cpuid % ncpu); 
1728 error = interrupt_distribute(vih, affinity, NULL); 
1729 if (error == 0) { 
1730 aprint_normal_dev(sc->sc_dev, 
1731 "for %s interrupting at %s affinity to %u\n", 
1732 msix_matrix[i].intrname, intrstr, 
1733 msix_matrix[i].cpuid % ncpu); 
1734 } else { 
1735 aprint_normal_dev(sc->sc_dev, 
1736 "for %s interrupting at %s\n", 
1737 msix_matrix[i].intrname, intrstr); 
1738 } 
1739 sc->sc_ihs[msix_matrix[i].intridx] = vih; 
1740 } 1684 }
 1685 } else if (pci_intr_type(sc->sc_intrs[0]) == PCI_INTR_TYPE_MSI) {
 1686 error = wm_setup_legacy(sc);
 1687 if (error) {
 1688 pci_intr_release(sc->sc_pc, sc->sc_intrs,
 1689 counts[PCI_INTR_TYPE_MSI]);
1741 1690
1742 sc->sc_nintrs = WM_MSIX_NINTR; 1691 /* The next try is for INTx: Disable MSI */
1743 kcpuset_destroy(affinity); 1692 max_type = PCI_INTR_TYPE_INTX;
 1693 counts[PCI_INTR_TYPE_INTX] = 1;
 1694 goto alloc_retry;
 1695 }
1744 } else { 1696 } else {
1745 /* MSI or INTx */ 1697 error = wm_setup_legacy(sc);
1746 intrstr = pci_intr_string(pc, sc->sc_intrs[0], intrbuf, 1698 if (error) {
1747 sizeof(intrbuf)); 1699 pci_intr_release(sc->sc_pc, sc->sc_intrs,
1748#ifdef WM_MPSAFE 1700 counts[PCI_INTR_TYPE_INTX]);
1749 pci_intr_setattr(pc, &sc->sc_intrs[0], PCI_INTR_MPSAFE, true); 1701 return;
1750#endif 
1751 sc->sc_ihs[0] = pci_intr_establish_xname(pc, sc->sc_intrs[0], 
1752 IPL_NET, wm_intr_legacy, sc, device_xname(sc->sc_dev)); 
1753 if (sc->sc_ihs[0] == NULL) { 
1754 aprint_error_dev(sc->sc_dev,"unable to establish %s\n", 
1755 (pci_intr_type(sc->sc_intrs[0]) 
1756 == PCI_INTR_TYPE_MSI) ? "MSI" : "INTx"); 
1757 pci_intr_release(sc->sc_pc, sc->sc_intrs, 1); 
1758 switch (pci_intr_type(sc->sc_intrs[0])) { 
1759 case PCI_INTR_TYPE_MSI: 
1760 /* The next try is for INTx: Disable MSI */ 
1761 max_type = PCI_INTR_TYPE_INTX; 
1762 counts[PCI_INTR_TYPE_INTX] = 1; 
1763 goto alloc_retry; 
1764 case PCI_INTR_TYPE_INTX: 
1765 default: 
1766 return; 
1767 } 
1768 } 1702 }
1769 aprint_normal_dev(sc->sc_dev, "%s at %s\n", 
1770 (pci_intr_type(sc->sc_intrs[0]) == PCI_INTR_TYPE_MSI) 
1771 ? "MSI" : "interrupting", intrstr); 
1772 
1773 sc->sc_nintrs = 1; 
1774 } 1703 }
1775#endif /* WM_MSI_MSIX */ 1704#endif /* WM_MSI_MSIX */
1776 1705
1777 /* 1706 /*
1778 * Check the function ID (unit number of the chip). 1707 * Check the function ID (unit number of the chip).
1779 */ 1708 */
1780 if ((sc->sc_type == WM_T_82546) || (sc->sc_type == WM_T_82546_3) 1709 if ((sc->sc_type == WM_T_82546) || (sc->sc_type == WM_T_82546_3)
1781 || (sc->sc_type == WM_T_82571) || (sc->sc_type == WM_T_80003) 1710 || (sc->sc_type == WM_T_82571) || (sc->sc_type == WM_T_80003)
1782 || (sc->sc_type == WM_T_82575) || (sc->sc_type == WM_T_82576) 1711 || (sc->sc_type == WM_T_82575) || (sc->sc_type == WM_T_82576)
1783 || (sc->sc_type == WM_T_82580) 1712 || (sc->sc_type == WM_T_82580)
1784 || (sc->sc_type == WM_T_I350) || (sc->sc_type == WM_T_I354)) 1713 || (sc->sc_type == WM_T_I350) || (sc->sc_type == WM_T_I354))
1785 sc->sc_funcid = (CSR_READ(sc, WMREG_STATUS) 1714 sc->sc_funcid = (CSR_READ(sc, WMREG_STATUS)
1786 >> STATUS_FUNCID_SHIFT) & STATUS_FUNCID_MASK; 1715 >> STATUS_FUNCID_SHIFT) & STATUS_FUNCID_MASK;
@@ -4094,26 +4023,132 @@ wm_rxdrain(struct wm_softc *sc) @@ -4094,26 +4023,132 @@ wm_rxdrain(struct wm_softc *sc)
4094 4023
4095 KASSERT(WM_RX_LOCKED(rxq)); 4024 KASSERT(WM_RX_LOCKED(rxq));
4096 4025
4097 for (i = 0; i < WM_NRXDESC; i++) { 4026 for (i = 0; i < WM_NRXDESC; i++) {
4098 rxs = &rxq->rxq_soft[i]; 4027 rxs = &rxq->rxq_soft[i];
4099 if (rxs->rxs_mbuf != NULL) { 4028 if (rxs->rxs_mbuf != NULL) {
4100 bus_dmamap_unload(sc->sc_dmat, rxs->rxs_dmamap); 4029 bus_dmamap_unload(sc->sc_dmat, rxs->rxs_dmamap);
4101 m_freem(rxs->rxs_mbuf); 4030 m_freem(rxs->rxs_mbuf);
4102 rxs->rxs_mbuf = NULL; 4031 rxs->rxs_mbuf = NULL;
4103 } 4032 }
4104 } 4033 }
4105} 4034}
4106 4035
 4036
 4037#ifdef WM_MSI_MSIX
 4038/*
 4039 * Both single interrupt MSI and INTx can use this function.
 4040 */
 4041static int
 4042wm_setup_legacy(struct wm_softc *sc)
 4043{
 4044 pci_chipset_tag_t pc = sc->sc_pc;
 4045 const char *intrstr = NULL;
 4046 char intrbuf[PCI_INTRSTR_LEN];
 4047
 4048 intrstr = pci_intr_string(pc, sc->sc_intrs[0], intrbuf,
 4049 sizeof(intrbuf));
 4050#ifdef WM_MPSAFE
 4051 pci_intr_setattr(pc, &sc->sc_intrs[0], PCI_INTR_MPSAFE, true);
 4052#endif
 4053 sc->sc_ihs[0] = pci_intr_establish_xname(pc, sc->sc_intrs[0],
 4054 IPL_NET, wm_intr_legacy, sc, device_xname(sc->sc_dev));
 4055 if (sc->sc_ihs[0] == NULL) {
 4056 aprint_error_dev(sc->sc_dev,"unable to establish %s\n",
 4057 (pci_intr_type(sc->sc_intrs[0])
 4058 == PCI_INTR_TYPE_MSI) ? "MSI" : "INTx");
 4059 return ENOMEM;
 4060 }
 4061
 4062 aprint_normal_dev(sc->sc_dev, "interrupting at %s\n", intrstr);
 4063 sc->sc_nintrs = 1;
 4064 return 0;
 4065}
 4066
 4067struct _msix_matrix {
 4068 const char *intrname;
 4069 int(*func)(void *);
 4070 int intridx;
 4071 int cpuid;
 4072} msix_matrix[WM_MSIX_NINTR] = {
 4073 { "TX", wm_txintr_msix, WM_MSIX_TXINTR_IDX, WM_MSIX_TXINTR_CPUID },
 4074 { "RX", wm_rxintr_msix, WM_MSIX_RXINTR_IDX, WM_MSIX_RXINTR_CPUID },
 4075 { "LINK", wm_linkintr_msix, WM_MSIX_LINKINTR_IDX,
 4076 WM_MSIX_LINKINTR_CPUID },
 4077};
 4078
 4079static int
 4080wm_setup_msix(struct wm_softc *sc)
 4081{
 4082 void *vih;
 4083 kcpuset_t *affinity;
 4084 int i, error;
 4085 pci_chipset_tag_t pc = sc->sc_pc;
 4086 const char *intrstr = NULL;
 4087 char intrbuf[PCI_INTRSTR_LEN];
 4088 char intr_xname[INTRDEVNAMEBUF];
 4089
 4090 kcpuset_create(&affinity, false);
 4091
 4092 for (i = 0; i < WM_MSIX_NINTR; i++) {
 4093 intrstr = pci_intr_string(pc,
 4094 sc->sc_intrs[msix_matrix[i].intridx], intrbuf,
 4095 sizeof(intrbuf));
 4096#ifdef WM_MPSAFE
 4097 pci_intr_setattr(pc,
 4098 &sc->sc_intrs[msix_matrix[i].intridx],
 4099 PCI_INTR_MPSAFE, true);
 4100#endif
 4101 memset(intr_xname, 0, sizeof(intr_xname));
 4102 strlcat(intr_xname, device_xname(sc->sc_dev),
 4103 sizeof(intr_xname));
 4104 strlcat(intr_xname, msix_matrix[i].intrname,
 4105 sizeof(intr_xname));
 4106 vih = pci_intr_establish_xname(pc,
 4107 sc->sc_intrs[msix_matrix[i].intridx], IPL_NET,
 4108 msix_matrix[i].func, sc, intr_xname);
 4109 if (vih == NULL) {
 4110 aprint_error_dev(sc->sc_dev,
 4111 "unable to establish MSI-X(for %s)%s%s\n",
 4112 msix_matrix[i].intrname,
 4113 intrstr ? " at " : "",
 4114 intrstr ? intrstr : "");
 4115 kcpuset_destroy(affinity);
 4116
 4117 return ENOMEM;
 4118 }
 4119 kcpuset_zero(affinity);
 4120 /* Round-robin affinity */
 4121 kcpuset_set(affinity, msix_matrix[i].cpuid % ncpu);
 4122 error = interrupt_distribute(vih, affinity, NULL);
 4123 if (error == 0) {
 4124 aprint_normal_dev(sc->sc_dev,
 4125 "for %s interrupting at %s affinity to %u\n",
 4126 msix_matrix[i].intrname, intrstr,
 4127 msix_matrix[i].cpuid % ncpu);
 4128 } else {
 4129 aprint_normal_dev(sc->sc_dev,
 4130 "for %s interrupting at %s\n",
 4131 msix_matrix[i].intrname, intrstr);
 4132 }
 4133 sc->sc_ihs[msix_matrix[i].intridx] = vih;
 4134 }
 4135
 4136 sc->sc_nintrs = WM_MSIX_NINTR;
 4137 kcpuset_destroy(affinity);
 4138 return 0;
 4139}
 4140#endif
 4141
4107/* 4142/*
4108 * wm_init: [ifnet interface function] 4143 * wm_init: [ifnet interface function]
4109 * 4144 *
4110 * Initialize the interface. 4145 * Initialize the interface.
4111 */ 4146 */
4112static int 4147static int
4113wm_init(struct ifnet *ifp) 4148wm_init(struct ifnet *ifp)
4114{ 4149{
4115 struct wm_softc *sc = ifp->if_softc; 4150 struct wm_softc *sc = ifp->if_softc;
4116 int ret; 4151 int ret;
4117 4152
4118 WM_CORE_LOCK(sc); 4153 WM_CORE_LOCK(sc);
4119 ret = wm_init_locked(ifp); 4154 ret = wm_init_locked(ifp);