Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/ixl/ixl_txrx.c
Show First 20 Lines • Show All 240 Lines • ▼ Show 20 Lines | ixl_xmit(struct ixl_queue *que, struct mbuf **m_headp) | ||||
int i, j, error, nsegs, maxsegs; | int i, j, error, nsegs, maxsegs; | ||||
int first, last = 0; | int first, last = 0; | ||||
u16 vtag = 0; | u16 vtag = 0; | ||||
u32 cmd, off; | u32 cmd, off; | ||||
bus_dmamap_t map; | bus_dmamap_t map; | ||||
bus_dma_tag_t tag; | bus_dma_tag_t tag; | ||||
bus_dma_segment_t segs[IXL_MAX_TSO_SEGS]; | bus_dma_segment_t segs[IXL_MAX_TSO_SEGS]; | ||||
cmd = off = 0; | cmd = off = 0; | ||||
m_head = *m_headp; | m_head = *m_headp; | ||||
/* | /* | ||||
* Important to capture the first descriptor | * Important to capture the first descriptor | ||||
* used because it will contain the index of | * used because it will contain the index of | ||||
* the one we tell the hardware to report back | * the one we tell the hardware to report back | ||||
*/ | */ | ||||
Show All 22 Lines | ixl_xmit(struct ixl_queue *que, struct mbuf **m_headp) | ||||
* Map the packet for DMA. | * Map the packet for DMA. | ||||
*/ | */ | ||||
error = bus_dmamap_load_mbuf_sg(tag, map, | error = bus_dmamap_load_mbuf_sg(tag, map, | ||||
*m_headp, segs, &nsegs, BUS_DMA_NOWAIT); | *m_headp, segs, &nsegs, BUS_DMA_NOWAIT); | ||||
if (error == EFBIG) { | if (error == EFBIG) { | ||||
struct mbuf *m; | struct mbuf *m; | ||||
m = m_collapse(*m_headp, M_NOWAIT, maxsegs); | m = m_defrag(*m_headp, M_NOWAIT); | ||||
if (m == NULL) { | if (m == NULL) { | ||||
que->mbuf_defrag_failed++; | que->mbuf_defrag_failed++; | ||||
m_freem(*m_headp); | m_freem(*m_headp); | ||||
*m_headp = NULL; | *m_headp = NULL; | ||||
return (ENOBUFS); | return (ENOBUFS); | ||||
} | } | ||||
*m_headp = m; | *m_headp = m; | ||||
▲ Show 20 Lines • Show All 87 Lines • ▼ Show 20 Lines | buf->eop_index = last; | ||||
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); | BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); | ||||
/* | /* | ||||
* Advance the Transmit Descriptor Tail (Tdt), this tells the | * Advance the Transmit Descriptor Tail (Tdt), this tells the | ||||
* hardware that this frame is available to transmit. | * hardware that this frame is available to transmit. | ||||
*/ | */ | ||||
++txr->total_packets; | ++txr->total_packets; | ||||
wr32(hw, txr->tail, i); | wr32(hw, txr->tail, i); | ||||
ixl_flush(hw); | |||||
/* Mark outstanding work */ | /* Mark outstanding work */ | ||||
if (que->busy == 0) | if (que->busy == 0) | ||||
que->busy = 1; | que->busy = 1; | ||||
return (0); | return (0); | ||||
xmit_fail: | xmit_fail: | ||||
bus_dmamap_unload(tag, buf->map); | bus_dmamap_unload(tag, buf->map); | ||||
return (error); | return (error); | ||||
▲ Show 20 Lines • Show All 224 Lines • ▼ Show 20 Lines | |||||
#ifdef INET6 | #ifdef INET6 | ||||
struct ip6_hdr *ip6; | struct ip6_hdr *ip6; | ||||
#endif | #endif | ||||
int elen, ip_hlen = 0, tcp_hlen; | int elen, ip_hlen = 0, tcp_hlen; | ||||
u16 etype; | u16 etype; | ||||
u8 ipproto = 0; | u8 ipproto = 0; | ||||
bool tso = FALSE; | bool tso = FALSE; | ||||
/* Set up the TSO context descriptor if required */ | /* Set up the TSO context descriptor if required */ | ||||
if (mp->m_pkthdr.csum_flags & CSUM_TSO) { | if (mp->m_pkthdr.csum_flags & CSUM_TSO) { | ||||
tso = ixl_tso_setup(que, mp); | tso = ixl_tso_setup(que, mp); | ||||
if (tso) | if (tso) | ||||
++que->tso; | ++que->tso; | ||||
else | else | ||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 121 Lines • ▼ Show 20 Lines | #ifdef INET6 | ||||
case ETHERTYPE_IPV6: | case ETHERTYPE_IPV6: | ||||
ip6 = (struct ip6_hdr *)(mp->m_data + elen); | ip6 = (struct ip6_hdr *)(mp->m_data + elen); | ||||
if (ip6->ip6_nxt != IPPROTO_TCP) | if (ip6->ip6_nxt != IPPROTO_TCP) | ||||
return (ENXIO); | return (ENXIO); | ||||
ip_hlen = sizeof(struct ip6_hdr); | ip_hlen = sizeof(struct ip6_hdr); | ||||
th = (struct tcphdr *)((caddr_t)ip6 + ip_hlen); | th = (struct tcphdr *)((caddr_t)ip6 + ip_hlen); | ||||
th->th_sum = in6_cksum_pseudo(ip6, 0, IPPROTO_TCP, 0); | th->th_sum = in6_cksum_pseudo(ip6, 0, IPPROTO_TCP, 0); | ||||
tcp_hlen = th->th_off << 2; | tcp_hlen = th->th_off << 2; | ||||
/* | |||||
* The corresponding flag is set by the stack in the IPv4 | |||||
* TSO case, but not in IPv6 (at least in FreeBSD 10.2). | |||||
* So, set it here because the rest of the flow requires it. | |||||
*/ | |||||
mp->m_pkthdr.csum_flags |= CSUM_TCP_IPV6; | |||||
break; | break; | ||||
#endif | #endif | ||||
#ifdef INET | #ifdef INET | ||||
case ETHERTYPE_IP: | case ETHERTYPE_IP: | ||||
ip = (struct ip *)(mp->m_data + elen); | ip = (struct ip *)(mp->m_data + elen); | ||||
if (ip->ip_p != IPPROTO_TCP) | if (ip->ip_p != IPPROTO_TCP) | ||||
return (ENXIO); | return (ENXIO); | ||||
ip->ip_sum = 0; | ip->ip_sum = 0; | ||||
▲ Show 20 Lines • Show All 795 Lines • ▼ Show 20 Lines | else | ||||
vtag = 0; | vtag = 0; | ||||
/* | /* | ||||
** Make sure bad packets are discarded, | ** Make sure bad packets are discarded, | ||||
** note that only EOP descriptor has valid | ** note that only EOP descriptor has valid | ||||
** error results. | ** error results. | ||||
*/ | */ | ||||
if (eop && (error & (1 << I40E_RX_DESC_ERROR_RXE_SHIFT))) { | if (eop && (error & (1 << I40E_RX_DESC_ERROR_RXE_SHIFT))) { | ||||
rxr->discarded++; | rxr->desc_errs++; | ||||
ixl_rx_discard(rxr, i); | ixl_rx_discard(rxr, i); | ||||
goto next_desc; | goto next_desc; | ||||
} | } | ||||
/* Prefetch the next buffer */ | /* Prefetch the next buffer */ | ||||
if (!eop) { | if (!eop) { | ||||
nextp = i + 1; | nextp = i + 1; | ||||
if (nextp == que->num_desc) | if (nextp == que->num_desc) | ||||
▲ Show 20 Lines • Show All 241 Lines • Show Last 20 Lines |