static void reclaim_tx_desc(struct sge_txq *q, unsigned int n)
{
+ struct tx_sw_desc *d;
unsigned int cidx = q->cidx;
+ d = &q->sdesc[cidx];
while (n--) {
- if (++cidx == q->size)
+ if (d->mbuf) { /* an SGL is present */
+ rte_pktmbuf_free(d->mbuf);
+ d->mbuf = NULL;
+ }
+ ++d;
+ if (++cidx == q->size) {
cidx = 0;
+ d = q->sdesc;
+ }
}
q->cidx = cidx;
}
u32 wr_mid;
u64 cntrl, *end;
bool v6;
+ u32 max_pkt_len = txq->eth_dev->data->dev_conf.rxmode.max_rx_pkt_len;
/* Reject xmit if queue is stopped */
if (unlikely(txq->flags & EQ_STOPPED))
return 0;
}
+ if ((!(m->ol_flags & PKT_TX_TCP_SEG)) &&
+ (unlikely(m->pkt_len > max_pkt_len)))
+ goto out_free;
+
pi = (struct port_info *)txq->eth_dev->data->dev_private;
adap = pi->adapter;
/* align the end of coalesce WR to a 512 byte boundary */
txq->q.coalesce.max = (8 - (txq->q.pidx & 7)) * 8;
- if (!(m->ol_flags & PKT_TX_TCP_SEG)) {
+ if (!((m->ol_flags & PKT_TX_TCP_SEG) || (m->pkt_len > ETHER_MAX_LEN))) {
if (should_tx_packet_coalesce(txq, mbuf, &cflits, adap)) {
if (unlikely(map_mbuf(mbuf, addr) < 0)) {
dev_warn(adap, "%s: mapping err for coalesce\n",
len = 0;
len += sizeof(*cpl);
- lso = (void *)(wr + 1);
- v6 = (m->ol_flags & PKT_TX_IPV6) != 0;
- l3hdr_len = m->l3_len;
- l4hdr_len = m->l4_len;
- eth_xtra_len = m->l2_len - ETHER_HDR_LEN;
- len += sizeof(*lso);
- wr->op_immdlen = htonl(V_FW_WR_OP(FW_ETH_TX_PKT_WR) |
- V_FW_WR_IMMDLEN(len));
- lso->lso_ctrl = htonl(V_LSO_OPCODE(CPL_TX_PKT_LSO) |
- F_LSO_FIRST_SLICE | F_LSO_LAST_SLICE |
- V_LSO_IPV6(v6) |
- V_LSO_ETHHDR_LEN(eth_xtra_len / 4) |
- V_LSO_IPHDR_LEN(l3hdr_len / 4) |
- V_LSO_TCPHDR_LEN(l4hdr_len / 4));
- lso->ipid_ofst = htons(0);
- lso->mss = htons(m->tso_segsz);
- lso->seqno_offset = htonl(0);
- if (is_t4(adap->params.chip))
- lso->len = htonl(m->pkt_len);
- else
- lso->len = htonl(V_LSO_T5_XFER_SIZE(m->pkt_len));
- cpl = (void *)(lso + 1);
- cntrl = V_TXPKT_CSUM_TYPE(v6 ? TX_CSUM_TCPIP6 : TX_CSUM_TCPIP) |
- V_TXPKT_IPHDR_LEN(l3hdr_len) |
- V_TXPKT_ETHHDR_LEN(eth_xtra_len);
- txq->stats.tso++;
- txq->stats.tx_cso += m->tso_segsz;
+
+ /* Coalescing skipped and we send through normal path */
+ if (!(m->ol_flags & PKT_TX_TCP_SEG)) {
+ wr->op_immdlen = htonl(V_FW_WR_OP(FW_ETH_TX_PKT_WR) |
+ V_FW_WR_IMMDLEN(len));
+ cpl = (void *)(wr + 1);
+ if (m->ol_flags & PKT_TX_IP_CKSUM) {
+ cntrl = hwcsum(adap->params.chip, m) |
+ F_TXPKT_IPCSUM_DIS;
+ txq->stats.tx_cso++;
+ }
+ } else {
+ lso = (void *)(wr + 1);
+ v6 = (m->ol_flags & PKT_TX_IPV6) != 0;
+ l3hdr_len = m->l3_len;
+ l4hdr_len = m->l4_len;
+ eth_xtra_len = m->l2_len - ETHER_HDR_LEN;
+ len += sizeof(*lso);
+ wr->op_immdlen = htonl(V_FW_WR_OP(FW_ETH_TX_PKT_WR) |
+ V_FW_WR_IMMDLEN(len));
+ lso->lso_ctrl = htonl(V_LSO_OPCODE(CPL_TX_PKT_LSO) |
+ F_LSO_FIRST_SLICE | F_LSO_LAST_SLICE |
+ V_LSO_IPV6(v6) |
+ V_LSO_ETHHDR_LEN(eth_xtra_len / 4) |
+ V_LSO_IPHDR_LEN(l3hdr_len / 4) |
+ V_LSO_TCPHDR_LEN(l4hdr_len / 4));
+ lso->ipid_ofst = htons(0);
+ lso->mss = htons(m->tso_segsz);
+ lso->seqno_offset = htonl(0);
+ if (is_t4(adap->params.chip))
+ lso->len = htonl(m->pkt_len);
+ else
+ lso->len = htonl(V_LSO_T5_XFER_SIZE(m->pkt_len));
+ cpl = (void *)(lso + 1);
+ cntrl = V_TXPKT_CSUM_TYPE(v6 ? TX_CSUM_TCPIP6 : TX_CSUM_TCPIP) |
+ V_TXPKT_IPHDR_LEN(l3hdr_len) |
+ V_TXPKT_ETHHDR_LEN(eth_xtra_len);
+ txq->stats.tso++;
+ txq->stats.tx_cso += m->tso_segsz;
+ }
if (m->ol_flags & PKT_TX_VLAN_PKT) {
txq->stats.vlan_ins++;
last_desc -= txq->q.size;
d = &txq->q.sdesc[last_desc];
- if (d->mbuf) {
- rte_pktmbuf_free(d->mbuf);
- d->mbuf = NULL;
+ if (d->coalesce.idx) {
+ int i;
+
+ for (i = 0; i < d->coalesce.idx; i++) {
+ rte_pktmbuf_free(d->coalesce.mbuf[i]);
+ d->coalesce.mbuf[i] = NULL;
+ }
+ d->coalesce.idx = 0;
}
write_sgl(m, &txq->q, (struct ulptx_sgl *)(cpl + 1), end, 0,
addr);