Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/dev/pci/if_msk.c,v rcsdiff: /ftp/cvs/cvsroot/src/sys/dev/pci/if_msk.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.16 retrieving revision 1.16.6.2 diff -u -p -r1.16 -r1.16.6.2 --- src/sys/dev/pci/if_msk.c 2008/02/07 01:21:56 1.16 +++ src/sys/dev/pci/if_msk.c 2008/06/02 13:23:39 1.16.6.2 @@ -1,4 +1,4 @@ -/* $NetBSD: if_msk.c,v 1.16 2008/02/07 01:21:56 dyoung Exp $ */ +/* $NetBSD: if_msk.c,v 1.16.6.2 2008/06/02 13:23:39 mjf Exp $ */ /* $OpenBSD: if_msk.c,v 1.42 2007/01/17 02:43:02 krw Exp $ */ /* @@ -52,7 +52,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: if_msk.c,v 1.16 2008/02/07 01:21:56 dyoung Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_msk.c,v 1.16.6.2 2008/06/02 13:23:39 mjf Exp $"); #include "bpfilter.h" #include "rnd.h" @@ -100,7 +100,8 @@ __KERNEL_RCSID(0, "$NetBSD: if_msk.c,v 1 int mskc_probe(struct device *, struct cfdata *, void *); void mskc_attach(struct device *, struct device *self, void *aux); -void mskc_shutdown(void *); +static bool mskc_suspend(device_t PMF_FN_PROTO); +static bool mskc_resume(device_t PMF_FN_PROTO); int msk_probe(struct device *, struct cfdata *, void *); void msk_attach(struct device *, struct device *self, void *aux); int mskcprint(void *, const char *); @@ -242,8 +243,7 @@ msk_miibus_readreg(struct device *dev, i } if (i == SK_TIMEOUT) { - aprint_error("%s: phy failed to come ready\n", - sc_if->sk_dev.dv_xname); + aprint_error_dev(&sc_if->sk_dev, "phy failed to come ready\n"); return (0); } @@ -278,7 +278,7 @@ msk_miibus_writereg(struct device *dev, } if (i == SK_TIMEOUT) - aprint_error("%s: phy write timed out\n", sc_if->sk_dev.dv_xname); + aprint_error_dev(&sc_if->sk_dev, "phy write timed out\n"); } void @@ -428,8 +428,7 @@ msk_init_rx_ring(struct sk_if_softc *sc_ for (i = 0; i < MSK_RX_RING_CNT; i++) { if (msk_newbuf(sc_if, i, NULL, sc_if->sk_cdata.sk_rx_jumbo_map) == ENOBUFS) { - aprint_error("%s: failed alloc of %dth mbuf\n", - sc_if->sk_dev.dv_xname, i); + aprint_error_dev(&sc_if->sk_dev, "failed alloc of %dth mbuf\n", i); return (ENOBUFS); } } @@ -689,40 +688,27 @@ msk_jfree(struct mbuf *m, void *buf, siz } int -msk_ioctl(struct ifnet *ifp, u_long command, void *data) +msk_ioctl(struct ifnet *ifp, u_long cmd, void *data) { struct sk_if_softc *sc_if = ifp->if_softc; - struct ifreq *ifr = (struct ifreq *) data; int s, error = 0; s = splnet(); - switch(command) { - case SIOCSIFMTU: - if (ifr->ifr_mtu < ETHERMIN) - return EINVAL; - else if (sc_if->sk_softc->sk_type != SK_YUKON_FE) { - if (ifr->ifr_mtu > SK_JUMBO_MTU) - error = EINVAL; - } else if (ifr->ifr_mtu > ETHERMTU) - error = EINVAL; - else if ((error = ifioctl_common(ifp, command, data)) == ENETRESET) - error = 0; - break; - default: - DPRINTFN(2, ("msk_ioctl ETHER\n")); - error = ether_ioctl(ifp, command, data); + DPRINTFN(2, ("msk_ioctl ETHER\n")); + error = ether_ioctl(ifp, cmd, data); - if (error == ENETRESET) { + if (error == ENETRESET) { + error = 0; + if (cmd != SIOCADDMULTI && cmd != SIOCDELMULTI) + ; + else if (ifp->if_flags & IFF_RUNNING) { /* * Multicast list has changed; set the hardware * filter accordingly. */ - if (ifp->if_flags & IFF_RUNNING) - msk_setmulti(sc_if); - error = 0; + msk_setmulti(sc_if); } - break; } splx(s); @@ -757,8 +743,8 @@ msk_update_int_mod(struct sk_softc *sc) default: imtimer_ticks = SK_IMTIMER_TICKS_YUKON; } - aprint_verbose("%s: interrupt moderation is %d us\n", - sc->sk_dev.dv_xname, sc->sk_int_mod); + aprint_verbose_dev(&sc->sk_dev, "interrupt moderation is %d us\n", + sc->sk_int_mod); sk_win_write_4(sc, SK_IMTIMERINIT, SK_IM_USECS(sc->sk_int_mod)); sk_win_write_4(sc, SK_IMMR, SK_ISR_TX1_S_EOF|SK_ISR_TX2_S_EOF| SK_ISR_RX1_EOF|SK_ISR_RX2_EOF); @@ -893,7 +879,10 @@ void msk_reset(struct sk_softc *sc) /* Reset status ring. */ bzero((char *)sc->sk_status_ring, MSK_STATUS_RING_CNT * sizeof(struct msk_status_desc)); + bus_dmamap_sync(sc->sc_dmatag, sc->sk_status_map, 0, + sc->sk_status_map->dm_mapsize, BUS_DMASYNC_PREREAD); sc->sk_status_idx = 0; + sc->sk_status_own_idx = 0; sk_win_write_4(sc, SK_STAT_BMU_CSR, SK_STAT_BMU_RESET); sk_win_write_4(sc, SK_STAT_BMU_CSR, SK_STAT_BMU_UNRESET); @@ -949,6 +938,15 @@ msk_probe(struct device *parent, struct return (0); } +static bool +msk_resume(device_t dv PMF_FN_ARGS) +{ + struct sk_if_softc *sc_if = device_private(dv); + + msk_init_yukon(sc_if); + return true; +} + /* * Each XMAC chip is attached as a separate logical IP interface. * Single port cards will have only one logical interface of course. @@ -1045,8 +1043,9 @@ msk_attach(struct device *parent, struct aprint_error(": jumbo buffer allocation failed\n"); goto fail_3; } - sc_if->sk_ethercom.ec_capabilities = ETHERCAP_VLAN_MTU - | ETHERCAP_JUMBO_MTU; + sc_if->sk_ethercom.ec_capabilities = ETHERCAP_VLAN_MTU; + if (sc->sk_type != SK_YUKON_FE) + sc_if->sk_ethercom.ec_capabilities |= ETHERCAP_JUMBO_MTU; ifp->if_softc = sc_if; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; @@ -1058,7 +1057,7 @@ msk_attach(struct device *parent, struct ifp->if_baudrate = 1000000000; IFQ_SET_MAXLEN(&ifp->if_snd, MSK_TX_RING_CNT - 1); IFQ_SET_READY(&ifp->if_snd); - strcpy(ifp->if_xname, sc_if->sk_dev.dv_xname); + strlcpy(ifp->if_xname, device_xname(&sc_if->sk_dev), IFNAMSIZ); /* * Do miibus setup. @@ -1078,7 +1077,7 @@ msk_attach(struct device *parent, struct mii_attach(self, &sc_if->sk_mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, MIIF_DOPAUSE|MIIF_FORCEANEG); if (LIST_FIRST(&sc_if->sk_mii.mii_phys) == NULL) { - aprint_error("%s: no PHY found!\n", sc_if->sk_dev.dv_xname); + aprint_error_dev(&sc_if->sk_dev, "no PHY found!\n"); ifmedia_add(&sc_if->sk_mii.mii_media, IFM_ETHER|IFM_MANUAL, 0, NULL); ifmedia_set(&sc_if->sk_mii.mii_media, IFM_ETHER|IFM_MANUAL); @@ -1095,10 +1094,13 @@ msk_attach(struct device *parent, struct if_attach(ifp); ether_ifattach(ifp, sc_if->sk_enaddr); - shutdownhook_establish(mskc_shutdown, sc); + if (!pmf_device_register(self, NULL, msk_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); + else + pmf_class_network_register(self, ifp); #if NRND > 0 - rnd_attach_source(&sc->rnd_source, sc->sk_dev.dv_xname, + rnd_attach_source(&sc->rnd_source, device_xname(&sc->sk_dev), RND_TYPE_NET, 0); #endif @@ -1169,8 +1171,8 @@ mskc_attach(struct device *parent, struc irq = pci_conf_read(pc, pa->pa_tag, SK_PCI_INTLINE); /* Reset the power state. */ - aprint_normal("%s chip is in D%d power mode " - "-- setting to D0\n", sc->sk_dev.dv_xname, + aprint_normal_dev(&sc->sk_dev, "chip is in D%d power mode " + "-- setting to D0\n", command & SK_PSTATE_MASK); command &= 0xFFFFFFFC; pci_conf_write(pc, pa->pa_tag, @@ -1256,8 +1258,6 @@ mskc_attach(struct device *parent, struc goto fail_5; } sc->sk_status_ring = (struct msk_status_desc *)kva; - bzero(sc->sk_status_ring, - MSK_STATUS_RING_CNT * sizeof(struct msk_status_desc)); /* Reset the adapter. */ msk_reset(sc); @@ -1403,12 +1403,11 @@ mskc_attach(struct device *parent, struc sc->sk_int_mod_pending = 0; if ((rc = sysctl_createv(&sc->sk_clog, 0, NULL, &node, - 0, CTLTYPE_NODE, sc->sk_dev.dv_xname, + 0, CTLTYPE_NODE, device_xname(&sc->sk_dev), SYSCTL_DESCR("mskc per-controller controls"), NULL, 0, NULL, 0, CTL_HW, msk_root_num, CTL_CREATE, CTL_EOL)) != 0) { - aprint_normal("%s: couldn't create sysctl node\n", - sc->sk_dev.dv_xname); + aprint_normal_dev(&sc->sk_dev, "couldn't create sysctl node\n"); goto fail_6; } @@ -1422,11 +1421,13 @@ mskc_attach(struct device *parent, struc msk_sysctl_handler, 0, sc, 0, CTL_HW, msk_root_num, sk_nodenum, CTL_CREATE, CTL_EOL)) != 0) { - aprint_normal("%s: couldn't create int_mod sysctl node\n", - sc->sk_dev.dv_xname); + aprint_normal_dev(&sc->sk_dev, "couldn't create int_mod sysctl node\n"); goto fail_6; } + if (!pmf_device_register(self, mskc_suspend, mskc_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); + return; fail_6: @@ -1613,7 +1614,7 @@ msk_watchdog(struct ifnet *ifp) if (sc_if->sk_cdata.sk_tx_cons != idx) { msk_txeof(sc_if, idx); if (sc_if->sk_cdata.sk_tx_cnt != 0) { - aprint_error("%s: watchdog timeout\n", sc_if->sk_dev.dv_xname); + aprint_error_dev(&sc_if->sk_dev, "watchdog timeout\n"); ifp->if_oerrors++; @@ -1624,17 +1625,30 @@ msk_watchdog(struct ifnet *ifp) } } -void -mskc_shutdown(void *v) +static bool +mskc_suspend(device_t dv PMF_FN_ARGS) { - struct sk_softc *sc = v; + struct sk_softc *sc = device_private(dv); - DPRINTFN(2, ("msk_shutdown\n")); + DPRINTFN(2, ("mskc_suspend\n")); /* Turn off the 'driver is loaded' LED. */ CSR_WRITE_2(sc, SK_LED, SK_LED_GREEN_OFF); + return true; +} + +static bool +mskc_resume(device_t dv PMF_FN_ARGS) +{ + struct sk_softc *sc = device_private(dv); + + DPRINTFN(2, ("mskc_resume\n")); + msk_reset(sc); + CSR_WRITE_2(sc, SK_LED, SK_LED_GREEN_ON); + + return true; } __inline int @@ -1679,7 +1693,7 @@ msk_rxeof(struct sk_if_softc *sc_if, u_i cur_rx->sk_mbuf = NULL; if (total_len < SK_MIN_FRAMELEN || - total_len > SK_JUMBO_FRAMELEN || + total_len > ETHER_MAX_LEN_JUMBO || msk_rxvalid(sc, rxstat, total_len) == 0) { ifp->if_ierrors++; msk_newbuf(sc_if, cur, m, dmamap); @@ -1741,11 +1755,12 @@ msk_txeof(struct sk_if_softc *sc_if, int if (sc_if->sk_cdata.sk_tx_cnt <= 0) break; prog++; + cur_tx = &sc_if->sk_rdata->sk_tx_ring[cons]; + MSK_CDTXSYNC(sc_if, cons, 1, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); - - cur_tx = &sc_if->sk_rdata->sk_tx_ring[cons]; sk_ctl = cur_tx->sk_ctl; + MSK_CDTXSYNC(sc_if, cons, 1, BUS_DMASYNC_PREREAD); #ifdef MSK_DEBUG if (mskdebug >= 2) msk_dump_txdesc(cur_tx, cons); @@ -1816,6 +1831,9 @@ msk_intr(void *xsc) struct ifnet *ifp0 = NULL, *ifp1 = NULL; int claimed = 0; u_int32_t status; + uint32_t st_status; + uint16_t st_len; + uint8_t st_opcode, st_link; struct msk_status_desc *cur_st; status = CSR_READ_4(sc, SK_Y2_ISSR2); @@ -1841,42 +1859,56 @@ msk_intr(void *xsc) msk_intr_yukon(sc_if1); } - MSK_CDSTSYNC(sc, sc->sk_status_idx, - BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); - cur_st = &sc->sk_status_ring[sc->sk_status_idx]; + for (;;) { + cur_st = &sc->sk_status_ring[sc->sk_status_idx]; + MSK_CDSTSYNC(sc, sc->sk_status_idx, + BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); + st_opcode = cur_st->sk_opcode; + if ((st_opcode & SK_Y2_STOPC_OWN) == 0) { + MSK_CDSTSYNC(sc, sc->sk_status_idx, + BUS_DMASYNC_PREREAD); + break; + } + st_status = le32toh(cur_st->sk_status); + st_len = le16toh(cur_st->sk_len); + st_link = cur_st->sk_link; + st_opcode &= ~SK_Y2_STOPC_OWN; - while (cur_st->sk_opcode & SK_Y2_STOPC_OWN) { - cur_st->sk_opcode &= ~SK_Y2_STOPC_OWN; - switch (cur_st->sk_opcode) { + switch (st_opcode) { case SK_Y2_STOPC_RXSTAT: - msk_rxeof(sc->sk_if[cur_st->sk_link], - letoh16(cur_st->sk_len), - letoh32(cur_st->sk_status)); - SK_IF_WRITE_2(sc->sk_if[cur_st->sk_link], 0, + msk_rxeof(sc->sk_if[st_link], st_len, st_status); + SK_IF_WRITE_2(sc->sk_if[st_link], 0, SK_RXQ1_Y2_PREF_PUTIDX, - sc->sk_if[cur_st->sk_link]->sk_cdata.sk_rx_prod); + sc->sk_if[st_link]->sk_cdata.sk_rx_prod); break; case SK_Y2_STOPC_TXSTAT: if (sc_if0) - msk_txeof(sc_if0, - letoh32(cur_st->sk_status) + msk_txeof(sc_if0, st_status & SK_Y2_ST_TXA1_MSKL); if (sc_if1) msk_txeof(sc_if1, - ((letoh32(cur_st->sk_status) - & SK_Y2_ST_TXA2_MSKL) + ((st_status & SK_Y2_ST_TXA2_MSKL) >> SK_Y2_ST_TXA2_SHIFTL) - | ((letoh16(cur_st->sk_len) & SK_Y2_ST_TXA2_MSKH) << SK_Y2_ST_TXA2_SHIFTH)); + | ((st_len & SK_Y2_ST_TXA2_MSKH) << SK_Y2_ST_TXA2_SHIFTH)); break; default: - aprint_error("opcode=0x%x\n", cur_st->sk_opcode); + aprint_error("opcode=0x%x\n", st_opcode); break; } SK_INC(sc->sk_status_idx, MSK_STATUS_RING_CNT); + } - MSK_CDSTSYNC(sc, sc->sk_status_idx, - BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); - cur_st = &sc->sk_status_ring[sc->sk_status_idx]; +#define MSK_STATUS_RING_OWN_CNT(sc) \ + (((sc)->sk_status_idx + MSK_STATUS_RING_CNT - \ + (sc)->sk_status_own_idx) % MSK_STATUS_RING_CNT) + + while (MSK_STATUS_RING_OWN_CNT(sc) > MSK_STATUS_RING_CNT / 2) { + cur_st = &sc->sk_status_ring[sc->sk_status_own_idx]; + cur_st->sk_opcode &= ~SK_Y2_STOPC_OWN; + MSK_CDSTSYNC(sc, sc->sk_status_own_idx, + BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); + + SK_INC(sc->sk_status_own_idx, MSK_STATUS_RING_CNT); } if (status & SK_Y2_IMR_BMU) { @@ -2096,16 +2128,16 @@ msk_init(struct ifnet *ifp) /* Init descriptors */ if (msk_init_rx_ring(sc_if) == ENOBUFS) { - aprint_error("%s: initialization failed: no " - "memory for rx buffers\n", sc_if->sk_dev.dv_xname); + aprint_error_dev(&sc_if->sk_dev, "initialization failed: no " + "memory for rx buffers\n"); msk_stop(ifp,0); splx(s); return ENOBUFS; } if (msk_init_tx_ring(sc_if) == ENOBUFS) { - aprint_error("%s: initialization failed: no " - "memory for tx buffers\n", sc_if->sk_dev.dv_xname); + aprint_error_dev(&sc_if->sk_dev, "initialization failed: no " + "memory for tx buffers\n"); msk_stop(ifp,0); splx(s); return ENOBUFS; @@ -2130,8 +2162,8 @@ msk_init(struct ifnet *ifp) if (imr != SK_IM_USECS(sc->sk_int_mod)) { sk_win_write_4(sc, SK_IMTIMERINIT, SK_IM_USECS(sc->sk_int_mod)); - aprint_verbose("%s: interrupt moderation is %d us\n", - sc->sk_dev.dv_xname, sc->sk_int_mod); + aprint_verbose_dev(&sc->sk_dev, "interrupt moderation is %d us\n", + sc->sk_int_mod); } /* Initialize prefetch engine. */