|
@@ -46,6 +46,9 @@
|
|
|
#ifdef CONFIG_NET_RX_BUSY_POLL
|
|
|
#include <net/busy_poll.h>
|
|
|
#endif /* CONFIG_NET_RX_BUSY_POLL */
|
|
|
+#ifdef CONFIG_CHELSIO_T4_FCOE
|
|
|
+#include <scsi/fc/fc_fcoe.h>
|
|
|
+#endif /* CONFIG_CHELSIO_T4_FCOE */
|
|
|
#include "cxgb4.h"
|
|
|
#include "t4_regs.h"
|
|
|
#include "t4_values.h"
|
|
@@ -1044,6 +1047,38 @@ static inline void txq_advance(struct sge_txq *q, unsigned int n)
|
|
|
q->pidx -= q->size;
|
|
|
}
|
|
|
|
|
|
+#ifdef CONFIG_CHELSIO_T4_FCOE
|
|
|
+static inline int
|
|
|
+cxgb_fcoe_offload(struct sk_buff *skb, struct adapter *adap,
|
|
|
+ const struct port_info *pi, u64 *cntrl)
|
|
|
+{
|
|
|
+ const struct cxgb_fcoe *fcoe = &pi->fcoe;
|
|
|
+
|
|
|
+ if (!(fcoe->flags & CXGB_FCOE_ENABLED))
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ if (skb->protocol != htons(ETH_P_FCOE))
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ skb_reset_mac_header(skb);
|
|
|
+ skb->mac_len = sizeof(struct ethhdr);
|
|
|
+
|
|
|
+ skb_set_network_header(skb, skb->mac_len);
|
|
|
+ skb_set_transport_header(skb, skb->mac_len + sizeof(struct fcoe_hdr));
|
|
|
+
|
|
|
+ if (!cxgb_fcoe_sof_eof_supported(adap, skb))
|
|
|
+ return -ENOTSUPP;
|
|
|
+
|
|
|
+ /* FC CRC offload */
|
|
|
+ *cntrl = TXPKT_CSUM_TYPE(TX_CSUM_FCOE) |
|
|
|
+ TXPKT_L4CSUM_DIS | TXPKT_IPCSUM_DIS |
|
|
|
+ TXPKT_CSUM_START(CXGB_FCOE_TXPKT_CSUM_START) |
|
|
|
+ TXPKT_CSUM_END(CXGB_FCOE_TXPKT_CSUM_END) |
|
|
|
+ TXPKT_CSUM_LOC(CXGB_FCOE_TXPKT_CSUM_END);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+#endif /* CONFIG_CHELSIO_T4_FCOE */
|
|
|
+
|
|
|
/**
|
|
|
* t4_eth_xmit - add a packet to an Ethernet Tx queue
|
|
|
* @skb: the packet
|
|
@@ -1066,6 +1101,9 @@ netdev_tx_t t4_eth_xmit(struct sk_buff *skb, struct net_device *dev)
|
|
|
const struct skb_shared_info *ssi;
|
|
|
dma_addr_t addr[MAX_SKB_FRAGS + 1];
|
|
|
bool immediate = false;
|
|
|
+#ifdef CONFIG_CHELSIO_T4_FCOE
|
|
|
+ int err;
|
|
|
+#endif /* CONFIG_CHELSIO_T4_FCOE */
|
|
|
|
|
|
/*
|
|
|
* The chip min packet length is 10 octets but play safe and reject
|
|
@@ -1082,6 +1120,13 @@ out_free: dev_kfree_skb_any(skb);
|
|
|
q = &adap->sge.ethtxq[qidx + pi->first_qset];
|
|
|
|
|
|
reclaim_completed_tx(adap, &q->q, true);
|
|
|
+ cntrl = TXPKT_L4CSUM_DIS | TXPKT_IPCSUM_DIS;
|
|
|
+
|
|
|
+#ifdef CONFIG_CHELSIO_T4_FCOE
|
|
|
+ err = cxgb_fcoe_offload(skb, adap, pi, &cntrl);
|
|
|
+ if (unlikely(err == -ENOTSUPP))
|
|
|
+ goto out_free;
|
|
|
+#endif /* CONFIG_CHELSIO_T4_FCOE */
|
|
|
|
|
|
flits = calc_tx_flits(skb);
|
|
|
ndesc = flits_to_desc(flits);
|
|
@@ -1153,13 +1198,17 @@ out_free: dev_kfree_skb_any(skb);
|
|
|
if (skb->ip_summed == CHECKSUM_PARTIAL) {
|
|
|
cntrl = hwcsum(skb) | TXPKT_IPCSUM_DIS;
|
|
|
q->tx_cso++;
|
|
|
- } else
|
|
|
- cntrl = TXPKT_L4CSUM_DIS | TXPKT_IPCSUM_DIS;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
if (skb_vlan_tag_present(skb)) {
|
|
|
q->vlan_ins++;
|
|
|
cntrl |= TXPKT_VLAN_VLD | TXPKT_VLAN(skb_vlan_tag_get(skb));
|
|
|
+#ifdef CONFIG_CHELSIO_T4_FCOE
|
|
|
+ if (skb->protocol == htons(ETH_P_FCOE))
|
|
|
+ cntrl |= TXPKT_VLAN(
|
|
|
+ ((skb->priority & 0x7) << VLAN_PRIO_SHIFT));
|
|
|
+#endif /* CONFIG_CHELSIO_T4_FCOE */
|
|
|
}
|
|
|
|
|
|
cpl->ctrl0 = htonl(TXPKT_OPCODE(CPL_TX_PKT_XT) |
|
|
@@ -1759,6 +1808,9 @@ int t4_ethrx_handler(struct sge_rspq *q, const __be64 *rsp,
|
|
|
struct sge *s = &q->adap->sge;
|
|
|
int cpl_trace_pkt = is_t4(q->adap->params.chip) ?
|
|
|
CPL_TRACE_PKT : CPL_TRACE_PKT_T5;
|
|
|
+#ifdef CONFIG_CHELSIO_T4_FCOE
|
|
|
+ struct port_info *pi;
|
|
|
+#endif
|
|
|
|
|
|
if (unlikely(*(u8 *)rsp == cpl_trace_pkt))
|
|
|
return handle_trace_pkt(q->adap, si);
|
|
@@ -1799,8 +1851,24 @@ int t4_ethrx_handler(struct sge_rspq *q, const __be64 *rsp,
|
|
|
skb->ip_summed = CHECKSUM_COMPLETE;
|
|
|
rxq->stats.rx_cso++;
|
|
|
}
|
|
|
- } else
|
|
|
+ } else {
|
|
|
skb_checksum_none_assert(skb);
|
|
|
+#ifdef CONFIG_CHELSIO_T4_FCOE
|
|
|
+#define CPL_RX_PKT_FLAGS (RXF_PSH_F | RXF_SYN_F | RXF_UDP_F | \
|
|
|
+ RXF_TCP_F | RXF_IP_F | RXF_IP6_F | RXF_LRO_F)
|
|
|
+
|
|
|
+ pi = netdev_priv(skb->dev);
|
|
|
+ if (!(pkt->l2info & cpu_to_be32(CPL_RX_PKT_FLAGS))) {
|
|
|
+ if ((pkt->l2info & cpu_to_be32(RXF_FCOE_F)) &&
|
|
|
+ (pi->fcoe.flags & CXGB_FCOE_ENABLED)) {
|
|
|
+ if (!(pkt->err_vec & cpu_to_be16(RXERR_CSUM_F)))
|
|
|
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+#undef CPL_RX_PKT_FLAGS
|
|
|
+#endif /* CONFIG_CHELSIO_T4_FCOE */
|
|
|
+ }
|
|
|
|
|
|
if (unlikely(pkt->vlan_ex)) {
|
|
|
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), ntohs(pkt->vlan));
|