--- /Users/ozaki-r/tmp/awin_can.c 2017-05-24 12:28:49.000000000 +0900 +++ /Users/ozaki-r/tmp/awin_can.c.new 2017-05-24 12:47:49.000000000 +0900 @@ -209,6 +209,7 @@ awin_can_attach(device_t parent, device_ * Attach the interface. */ can_ifattach(ifp); + if_deferred_start_init(ifp, NULL); rnd_attach_source(&sc->sc_rnd_source, device_xname(self), RND_TYPE_NET, RND_FLAG_DEFAULT); #ifdef MBUFTRACE @@ -275,7 +276,7 @@ awin_can_rx_intr(struct awin_can_softc * ifp->if_ipackets++; ifp->if_ibytes += m->m_len; m_set_rcvif(m, ifp); - can_bpf_mtap(ifp, m); + can_bpf_mtap_softint(ifp, m); can_input(ifp, m); } @@ -284,10 +285,6 @@ awin_can_tx_intr(struct awin_can_softc * { struct ifnet * const ifp = sc->sc_ifp; struct mbuf *m; - struct can_frame *cf; - int regd; - uint32_t reg0val; - int i; KASSERT(mutex_owned(&sc->sc_intr_lock)); if ((m = sc->sc_m_transmit) != NULL) { @@ -298,58 +295,10 @@ awin_can_tx_intr(struct awin_can_softc * can_input(ifp, m); /* loopback */ sc->sc_m_transmit = NULL; ifp->if_timer = 0; - } - - IF_DEQUEUE(&ifp->if_snd, m); - - if (m == NULL) { ifp->if_flags &= ~IFF_OACTIVE; - return; } - MCLAIM(m, ifp->if_mowner); - sc->sc_m_transmit = m; - - KASSERT((m->m_flags & M_PKTHDR) != 0); - KASSERT(m->m_len == m->m_pkthdr.len); - - cf = mtod(m, struct can_frame *); - reg0val = cf->can_dlc & AWIN_CAN_TXBUF0_DL; - if (cf->can_id & CAN_RTR_FLAG) - reg0val |= AWIN_CAN_TXBUF0_RTR; - if (cf->can_id & CAN_EFF_FLAG) { - reg0val |= AWIN_CAN_TXBUF0_EFF; - awin_can_write(sc, AWIN_CAN_TXBUF1_REG, - (cf->can_id >> 21) & 0xff); - awin_can_write(sc, AWIN_CAN_TXBUF2_REG, - (cf->can_id >> 13) & 0xff); - awin_can_write(sc, AWIN_CAN_TXBUF3_REG, - (cf->can_id >> 5) & 0xff); - awin_can_write(sc, AWIN_CAN_TXBUF4_REG, - (cf->can_id << 3) & 0xf8); - regd = AWIN_CAN_TXBUF5_REG; - } else { - awin_can_write(sc, AWIN_CAN_TXBUF1_REG, - (cf->can_id >> 3) & 0xff); - awin_can_write(sc, AWIN_CAN_TXBUF2_REG, - (cf->can_id << 5) & 0xe0); - regd = AWIN_CAN_TXBUF3_REG; - } - - for (i = 0; i < cf->can_dlc; i++) { - awin_can_write(sc, regd + i * 4, cf->data[i]); - } - awin_can_write(sc, AWIN_CAN_TXBUF0_REG, reg0val); - - if (sc->sc_linkmodes & CAN_LINKMODE_LOOPBACK) { - awin_can_write(sc, AWIN_CAN_CMD_REG, - AWIN_CAN_CMD_TANS_REQ | AWIN_CAN_CMD_SELF_REQ); - } else { - awin_can_write(sc, AWIN_CAN_CMD_REG, AWIN_CAN_CMD_TANS_REQ); - } - ifp->if_flags |= IFF_OACTIVE; - ifp->if_timer = 5; - can_bpf_mtap(ifp, m); + if_schedule_deferred_start(ifp); } static int @@ -446,10 +395,65 @@ void awin_can_ifstart(struct ifnet *ifp) { struct awin_can_softc * const sc = ifp->if_softc; + struct mbuf *m; + struct can_frame *cf; + int regd; + uint32_t reg0val; + int i; mutex_enter(&sc->sc_intr_lock); - KASSERT((ifp->if_flags & IFF_OACTIVE) == 0); - awin_can_tx_intr(sc); + + IF_DEQUEUE(&ifp->if_snd, m); + + if (m == NULL) { + ifp->if_flags &= ~IFF_OACTIVE; + goto out; + } + MCLAIM(m, ifp->if_mowner); + sc->sc_m_transmit = m; + + KASSERT((m->m_flags & M_PKTHDR) != 0); + KASSERT(m->m_len == m->m_pkthdr.len); + + cf = mtod(m, struct can_frame *); + reg0val = cf->can_dlc & AWIN_CAN_TXBUF0_DL; + if (cf->can_id & CAN_RTR_FLAG) + reg0val |= AWIN_CAN_TXBUF0_RTR; + + if (cf->can_id & CAN_EFF_FLAG) { + reg0val |= AWIN_CAN_TXBUF0_EFF; + awin_can_write(sc, AWIN_CAN_TXBUF1_REG, + (cf->can_id >> 21) & 0xff); + awin_can_write(sc, AWIN_CAN_TXBUF2_REG, + (cf->can_id >> 13) & 0xff); + awin_can_write(sc, AWIN_CAN_TXBUF3_REG, + (cf->can_id >> 5) & 0xff); + awin_can_write(sc, AWIN_CAN_TXBUF4_REG, + (cf->can_id << 3) & 0xf8); + regd = AWIN_CAN_TXBUF5_REG; + } else { + awin_can_write(sc, AWIN_CAN_TXBUF1_REG, + (cf->can_id >> 3) & 0xff); + awin_can_write(sc, AWIN_CAN_TXBUF2_REG, + (cf->can_id << 5) & 0xe0); + regd = AWIN_CAN_TXBUF3_REG; + } + + for (i = 0; i < cf->can_dlc; i++) { + awin_can_write(sc, regd + i * 4, cf->data[i]); + } + awin_can_write(sc, AWIN_CAN_TXBUF0_REG, reg0val); + + if (sc->sc_linkmodes & CAN_LINKMODE_LOOPBACK) { + awin_can_write(sc, AWIN_CAN_CMD_REG, + AWIN_CAN_CMD_TANS_REQ | AWIN_CAN_CMD_SELF_REQ); + } else { + awin_can_write(sc, AWIN_CAN_CMD_REG, AWIN_CAN_CMD_TANS_REQ); + } + ifp->if_flags |= IFF_OACTIVE; + ifp->if_timer = 5; + can_bpf_mtap(ifp, m); +out: mutex_exit(&sc->sc_intr_lock); }