Date: Mon, 9 Jul 2007 12:54:04 +0900 From: Pyun YongHyeon <pyunyh@gmail.com> To: freebsd-current@FreeBSD.org Subject: CFT: re(4) MSI support Message-ID: <20070709035404.GF1062@cdnetworks.co.kr>
next in thread | raw e-mail | index | archive | help
--ALfTUftag+2gvp1h Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Hi, I've added MSI capability to re(4) and it would fix occasional watchdog timeout erros seen on re(4) when its interrupt is shared with other devices. The fix only affects PCIe based hardwares. In these days, more and more hardwares use PCIe based hardwares and these hardwares surly share interrupts with other devices. If you ever encountered watchdog timeouts on re(4) with PCIe hardwares please try attached patch and report back the result. Thanks. -- Regards, Pyun YongHyeon --ALfTUftag+2gvp1h Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="re.msi.patch" Index: if_re.c =================================================================== RCS file: /home/ncvs/src/sys/dev/re/if_re.c,v retrieving revision 1.91 diff -u -r1.91 if_re.c --- if_re.c 6 Jul 2007 00:05:11 -0000 1.91 +++ if_re.c 9 Jul 2007 01:52:23 -0000 @@ -160,6 +160,10 @@ #include <pci/if_rlreg.h> +/* Tunables. */ +static int msi_disable = 0; +TUNABLE_INT("hw.re.msi_disable", &msi_disable); + #define RE_CSUM_FEATURES (CSUM_IP | CSUM_TCP | CSUM_UDP) /* @@ -1159,6 +1163,7 @@ int hwrev; u_int16_t re_did = 0; int error = 0, rid, i; + int msic, reg; sc = device_get_softc(dev); sc->rl_dev = dev; @@ -1185,15 +1190,45 @@ sc->rl_btag = rman_get_bustag(sc->rl_res); sc->rl_bhandle = rman_get_bushandle(sc->rl_res); - /* Allocate interrupt */ - rid = 0; - sc->rl_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, - RF_SHAREABLE | RF_ACTIVE); + msic = 0; + if (pci_find_extcap(dev, PCIY_EXPRESS, ®) == 0) { + msic = pci_msi_count(dev); + if (bootverbose) + device_printf(dev, "MSI count : %d\n", msic); + } + if (msic == RL_MSI_MESSAGES && msi_disable == 0) { + if (pci_alloc_msi(dev, &msic) == 0) { + if (msic == RL_MSI_MESSAGES) { + device_printf(dev, "Using %d MSI messages\n", + msic); + sc->rl_msi = 1; + } else + pci_release_msi(dev); + } + } - if (sc->rl_irq == NULL) { - device_printf(dev, "couldn't map interrupt\n"); - error = ENXIO; - goto fail; + /* Allocate interrupt */ + if (sc->rl_msi == 0) { + rid = 0; + sc->rl_irq[0] = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, + RF_SHAREABLE | RF_ACTIVE); + if (sc->rl_irq[0] == NULL) { + device_printf(dev, "couldn't allocate IRQ resources\n"); + error = ENXIO; + goto fail; + } + } else { + for (i = 0, rid = 1; i < RL_MSI_MESSAGES; i++, rid++) { + sc->rl_irq[i] = bus_alloc_resource_any(dev, + SYS_RES_IRQ, &rid, RF_ACTIVE); + if (sc->rl_irq[i] == NULL) { + device_printf(dev, + "couldn't llocate IRQ resources for " + "message %d\n", rid); + error = ENXIO; + goto fail; + } + } } /* Reset the adapter. */ @@ -1320,8 +1355,19 @@ #endif /* Hook interrupt last to avoid having to lock softc */ - error = bus_setup_intr(dev, sc->rl_irq, INTR_TYPE_NET | INTR_MPSAFE, - re_intr, NULL, sc, &sc->rl_intrhand); + if (sc->rl_msi == 0) + error = bus_setup_intr(dev, sc->rl_irq[0], + INTR_TYPE_NET | INTR_MPSAFE, re_intr, NULL, sc, + &sc->rl_intrhand[0]); + else { + for (i = 0; i < RL_MSI_MESSAGES; i++) { + error = bus_setup_intr(dev, sc->rl_irq[i], + INTR_TYPE_NET | INTR_MPSAFE, re_intr, NULL, sc, + &sc->rl_intrhand[i]); + if (error != 0) + break; + } + } if (error) { device_printf(dev, "couldn't set up irq\n"); ether_ifdetach(ifp); @@ -1348,7 +1394,7 @@ { struct rl_softc *sc; struct ifnet *ifp; - int i; + int i, rid; sc = device_get_softc(dev); ifp = sc->rl_ifp; @@ -1393,12 +1439,31 @@ * stopped here. */ - if (sc->rl_intrhand) - bus_teardown_intr(dev, sc->rl_irq, sc->rl_intrhand); + for (i = 0; i < RL_MSI_MESSAGES; i++) { + if (sc->rl_intrhand[i] != NULL) { + bus_teardown_intr(dev, sc->rl_irq[i], + sc->rl_intrhand[i]); + sc->rl_intrhand[i] = NULL; + } + } if (ifp != NULL) if_free(ifp); - if (sc->rl_irq) - bus_release_resource(dev, SYS_RES_IRQ, 0, sc->rl_irq); + if (sc->rl_msi == 0) { + if (sc->rl_irq[0] != NULL) { + bus_release_resource(dev, SYS_RES_IRQ, 0, + sc->rl_irq[0]); + sc->rl_irq[0] = NULL; + } + } else { + for (i = 0, rid = 1; i < RL_MSI_MESSAGES; i++, rid++) { + if (sc->rl_irq[i] != NULL) { + bus_release_resource(dev, SYS_RES_IRQ, rid, + sc->rl_irq[i]); + sc->rl_irq[i] = NULL; + } + } + pci_release_msi(dev); + } if (sc->rl_res) bus_release_resource(dev, RL_RES, RL_RID, sc->rl_res); Index: ../../pci/if_rl.c =================================================================== RCS file: /home/ncvs/src/sys/pci/if_rl.c,v retrieving revision 1.169 diff -u -r1.169 if_rl.c --- ../../pci/if_rl.c 23 Feb 2007 12:19:03 -0000 1.169 +++ ../../pci/if_rl.c 9 Jul 2007 01:52:24 -0000 @@ -828,10 +828,10 @@ /* Allocate interrupt */ rid = 0; - sc->rl_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, + sc->rl_irq[0] = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE); - if (sc->rl_irq == NULL) { + if (sc->rl_irq[0] == NULL) { device_printf(dev, "couldn't map interrupt\n"); error = ENXIO; goto fail; @@ -971,8 +971,8 @@ ether_ifattach(ifp, eaddr); /* Hook interrupt last to avoid having to lock softc */ - error = bus_setup_intr(dev, sc->rl_irq, INTR_TYPE_NET | INTR_MPSAFE, - NULL, rl_intr, sc, &sc->rl_intrhand); + error = bus_setup_intr(dev, sc->rl_irq[0], INTR_TYPE_NET | INTR_MPSAFE, + NULL, rl_intr, sc, &sc->rl_intrhand[0]); if (error) { device_printf(sc->rl_dev, "couldn't set up irq\n"); ether_ifdetach(ifp); @@ -1022,10 +1022,10 @@ device_delete_child(dev, sc->rl_miibus); bus_generic_detach(dev); - if (sc->rl_intrhand) - bus_teardown_intr(dev, sc->rl_irq, sc->rl_intrhand); - if (sc->rl_irq) - bus_release_resource(dev, SYS_RES_IRQ, 0, sc->rl_irq); + if (sc->rl_intrhand[0]) + bus_teardown_intr(dev, sc->rl_irq[0], sc->rl_intrhand[0]); + if (sc->rl_irq[0]) + bus_release_resource(dev, SYS_RES_IRQ, 0, sc->rl_irq[0]); if (sc->rl_res) bus_release_resource(dev, RL_RES, RL_RID, sc->rl_res); Index: ../../pci/if_rlreg.h =================================================================== RCS file: /home/ncvs/src/sys/pci/if_rlreg.h,v retrieving revision 1.66 diff -u -r1.66 if_rlreg.h --- ../../pci/if_rlreg.h 6 Jul 2007 00:05:12 -0000 1.66 +++ ../../pci/if_rlreg.h 9 Jul 2007 01:52:24 -0000 @@ -664,6 +664,8 @@ #define RE_RX_DESC_BUFLEN MCLBYTES #endif +#define RL_MSI_MESSAGES 2 + #define RL_ADDR_LO(y) ((uint64_t) (y) & 0xFFFFFFFF) #define RL_ADDR_HI(y) ((uint64_t) (y) >> 32) @@ -710,8 +712,8 @@ bus_space_tag_t rl_btag; /* bus space tag */ device_t rl_dev; struct resource *rl_res; - struct resource *rl_irq; - void *rl_intrhand; + struct resource *rl_irq[RL_MSI_MESSAGES]; + void *rl_intrhand[RL_MSI_MESSAGES]; device_t rl_miibus; bus_dma_tag_t rl_parent_tag; bus_dma_tag_t rl_tag; @@ -742,6 +744,7 @@ struct mtx rl_intlock; int rl_txstart; int rl_link; + int rl_msi; }; #define RL_LOCK(_sc) mtx_lock(&(_sc)->rl_mtx) --ALfTUftag+2gvp1h--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20070709035404.GF1062>