aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVarun Prakash <varun@chelsio.com>2015-03-24 09:44:46 -0400
committerDavid S. Miller <davem@davemloft.net>2015-03-24 15:24:38 -0400
commit84a200b390d60fd84293670a089d0c864e35d0b1 (patch)
tree805c31ca63e49be9d7ac31cf336c0e33283c0e9a
parent76fed8a989ba673b15979ba35457020c1716e1f2 (diff)
cxgb4: add cxgb4_fcoe.c for FCoE
This patch adds cxgb4_fcoe.c and enables FCOE_CRC, FCOE_MTU net device features. Signed-off-by: Varun Prakash <varun@chelsio.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_fcoe.c122
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c8
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/sge.c74
3 files changed, 201 insertions, 3 deletions
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_fcoe.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_fcoe.c
new file mode 100644
index 000000000000..062d3c0b5818
--- /dev/null
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_fcoe.c
@@ -0,0 +1,122 @@
1/*
2 * This file is part of the Chelsio T4 Ethernet driver for Linux.
3 *
4 * Copyright (c) 2015 Chelsio Communications, Inc. All rights reserved.
5 *
6 * This software is available to you under a choice of one of two
7 * licenses. You may choose to be licensed under the terms of the GNU
8 * General Public License (GPL) Version 2, available from the file
9 * COPYING in the main directory of this source tree, or the
10 * OpenIB.org BSD license below:
11 *
12 * Redistribution and use in source and binary forms, with or
13 * without modification, are permitted provided that the following
14 * conditions are met:
15 *
16 * - Redistributions of source code must retain the above
17 * copyright notice, this list of conditions and the following
18 * disclaimer.
19 *
20 * - Redistributions in binary form must reproduce the above
21 * copyright notice, this list of conditions and the following
22 * disclaimer in the documentation and/or other materials
23 * provided with the distribution.
24 *
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32 * SOFTWARE.
33 */
34
35#ifdef CONFIG_CHELSIO_T4_FCOE
36
37#include <scsi/fc/fc_fs.h>
38#include <scsi/libfcoe.h>
39#include "cxgb4.h"
40
41bool cxgb_fcoe_sof_eof_supported(struct adapter *adap, struct sk_buff *skb)
42{
43 struct fcoe_hdr *fcoeh = (struct fcoe_hdr *)skb_network_header(skb);
44 u8 sof = fcoeh->fcoe_sof;
45 u8 eof = 0;
46
47 if ((sof != FC_SOF_I3) && (sof != FC_SOF_N3)) {
48 dev_err(adap->pdev_dev, "Unsupported SOF 0x%x\n", sof);
49 return 0;
50 }
51
52 skb_copy_bits(skb, skb->len - 4, &eof, 1);
53
54 if ((eof != FC_EOF_N) && (eof != FC_EOF_T)) {
55 dev_err(adap->pdev_dev, "Unsupported EOF 0x%x\n", eof);
56 return 0;
57 }
58
59 return 1;
60}
61
62/**
63 * cxgb_fcoe_enable - enable FCoE offload features
64 * @netdev: net device
65 *
66 * Returns 0 on success or -EINVAL on failure.
67 */
68int cxgb_fcoe_enable(struct net_device *netdev)
69{
70 struct port_info *pi = netdev_priv(netdev);
71 struct adapter *adap = pi->adapter;
72 struct cxgb_fcoe *fcoe = &pi->fcoe;
73
74 if (is_t4(adap->params.chip))
75 return -EINVAL;
76
77 if (!(adap->flags & FULL_INIT_DONE))
78 return -EINVAL;
79
80 dev_info(adap->pdev_dev, "Enabling FCoE offload features\n");
81
82 netdev->features |= NETIF_F_FCOE_CRC;
83 netdev->vlan_features |= NETIF_F_FCOE_CRC;
84 netdev->features |= NETIF_F_FCOE_MTU;
85 netdev->vlan_features |= NETIF_F_FCOE_MTU;
86
87 netdev_features_change(netdev);
88
89 fcoe->flags |= CXGB_FCOE_ENABLED;
90
91 return 0;
92}
93
94/**
95 * cxgb_fcoe_disable - disable FCoE offload
96 * @netdev: net device
97 *
98 * Returns 0 on success or -EINVAL on failure.
99 */
100int cxgb_fcoe_disable(struct net_device *netdev)
101{
102 struct port_info *pi = netdev_priv(netdev);
103 struct adapter *adap = pi->adapter;
104 struct cxgb_fcoe *fcoe = &pi->fcoe;
105
106 if (!(fcoe->flags & CXGB_FCOE_ENABLED))
107 return -EINVAL;
108
109 dev_info(adap->pdev_dev, "Disabling FCoE offload features\n");
110
111 fcoe->flags &= ~CXGB_FCOE_ENABLED;
112
113 netdev->features &= ~NETIF_F_FCOE_CRC;
114 netdev->vlan_features &= ~NETIF_F_FCOE_CRC;
115 netdev->features &= ~NETIF_F_FCOE_MTU;
116 netdev->vlan_features &= ~NETIF_F_FCOE_MTU;
117
118 netdev_features_change(netdev);
119
120 return 0;
121}
122#endif /* CONFIG_CHELSIO_T4_FCOE */
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index dd4b2da6e468..e40e283ff36c 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -1271,6 +1271,10 @@ static u16 cxgb_select_queue(struct net_device *dev, struct sk_buff *skb,
1271 txq = 0; 1271 txq = 0;
1272 } else { 1272 } else {
1273 txq = (vlan_tci & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT; 1273 txq = (vlan_tci & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT;
1274#ifdef CONFIG_CHELSIO_T4_FCOE
1275 if (skb->protocol == htons(ETH_P_FCOE))
1276 txq = skb->priority & 0x7;
1277#endif /* CONFIG_CHELSIO_T4_FCOE */
1274 } 1278 }
1275 return txq; 1279 return txq;
1276 } 1280 }
@@ -4578,6 +4582,10 @@ static const struct net_device_ops cxgb4_netdev_ops = {
4578#ifdef CONFIG_NET_POLL_CONTROLLER 4582#ifdef CONFIG_NET_POLL_CONTROLLER
4579 .ndo_poll_controller = cxgb_netpoll, 4583 .ndo_poll_controller = cxgb_netpoll,
4580#endif 4584#endif
4585#ifdef CONFIG_CHELSIO_T4_FCOE
4586 .ndo_fcoe_enable = cxgb_fcoe_enable,
4587 .ndo_fcoe_disable = cxgb_fcoe_disable,
4588#endif /* CONFIG_CHELSIO_T4_FCOE */
4581#ifdef CONFIG_NET_RX_BUSY_POLL 4589#ifdef CONFIG_NET_RX_BUSY_POLL
4582 .ndo_busy_poll = cxgb_busy_poll, 4590 .ndo_busy_poll = cxgb_busy_poll,
4583#endif 4591#endif
diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c
index b4b9f6048fe7..c46e7a938317 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c
@@ -46,6 +46,9 @@
46#ifdef CONFIG_NET_RX_BUSY_POLL 46#ifdef CONFIG_NET_RX_BUSY_POLL
47#include <net/busy_poll.h> 47#include <net/busy_poll.h>
48#endif /* CONFIG_NET_RX_BUSY_POLL */ 48#endif /* CONFIG_NET_RX_BUSY_POLL */
49#ifdef CONFIG_CHELSIO_T4_FCOE
50#include <scsi/fc/fc_fcoe.h>
51#endif /* CONFIG_CHELSIO_T4_FCOE */
49#include "cxgb4.h" 52#include "cxgb4.h"
50#include "t4_regs.h" 53#include "t4_regs.h"
51#include "t4_values.h" 54#include "t4_values.h"
@@ -1044,6 +1047,38 @@ static inline void txq_advance(struct sge_txq *q, unsigned int n)
1044 q->pidx -= q->size; 1047 q->pidx -= q->size;
1045} 1048}
1046 1049
1050#ifdef CONFIG_CHELSIO_T4_FCOE
1051static inline int
1052cxgb_fcoe_offload(struct sk_buff *skb, struct adapter *adap,
1053 const struct port_info *pi, u64 *cntrl)
1054{
1055 const struct cxgb_fcoe *fcoe = &pi->fcoe;
1056
1057 if (!(fcoe->flags & CXGB_FCOE_ENABLED))
1058 return 0;
1059
1060 if (skb->protocol != htons(ETH_P_FCOE))
1061 return 0;
1062
1063 skb_reset_mac_header(skb);
1064 skb->mac_len = sizeof(struct ethhdr);
1065
1066 skb_set_network_header(skb, skb->mac_len);
1067 skb_set_transport_header(skb, skb->mac_len + sizeof(struct fcoe_hdr));
1068
1069 if (!cxgb_fcoe_sof_eof_supported(adap, skb))
1070 return -ENOTSUPP;
1071
1072 /* FC CRC offload */
1073 *cntrl = TXPKT_CSUM_TYPE(TX_CSUM_FCOE) |
1074 TXPKT_L4CSUM_DIS | TXPKT_IPCSUM_DIS |
1075 TXPKT_CSUM_START(CXGB_FCOE_TXPKT_CSUM_START) |
1076 TXPKT_CSUM_END(CXGB_FCOE_TXPKT_CSUM_END) |
1077 TXPKT_CSUM_LOC(CXGB_FCOE_TXPKT_CSUM_END);
1078 return 0;
1079}
1080#endif /* CONFIG_CHELSIO_T4_FCOE */
1081
1047/** 1082/**
1048 * t4_eth_xmit - add a packet to an Ethernet Tx queue 1083 * t4_eth_xmit - add a packet to an Ethernet Tx queue
1049 * @skb: the packet 1084 * @skb: the packet
@@ -1066,6 +1101,9 @@ netdev_tx_t t4_eth_xmit(struct sk_buff *skb, struct net_device *dev)
1066 const struct skb_shared_info *ssi; 1101 const struct skb_shared_info *ssi;
1067 dma_addr_t addr[MAX_SKB_FRAGS + 1]; 1102 dma_addr_t addr[MAX_SKB_FRAGS + 1];
1068 bool immediate = false; 1103 bool immediate = false;
1104#ifdef CONFIG_CHELSIO_T4_FCOE
1105 int err;
1106#endif /* CONFIG_CHELSIO_T4_FCOE */
1069 1107
1070 /* 1108 /*
1071 * The chip min packet length is 10 octets but play safe and reject 1109 * The chip min packet length is 10 octets but play safe and reject
@@ -1082,6 +1120,13 @@ out_free: dev_kfree_skb_any(skb);
1082 q = &adap->sge.ethtxq[qidx + pi->first_qset]; 1120 q = &adap->sge.ethtxq[qidx + pi->first_qset];
1083 1121
1084 reclaim_completed_tx(adap, &q->q, true); 1122 reclaim_completed_tx(adap, &q->q, true);
1123 cntrl = TXPKT_L4CSUM_DIS | TXPKT_IPCSUM_DIS;
1124
1125#ifdef CONFIG_CHELSIO_T4_FCOE
1126 err = cxgb_fcoe_offload(skb, adap, pi, &cntrl);
1127 if (unlikely(err == -ENOTSUPP))
1128 goto out_free;
1129#endif /* CONFIG_CHELSIO_T4_FCOE */
1085 1130
1086 flits = calc_tx_flits(skb); 1131 flits = calc_tx_flits(skb);
1087 ndesc = flits_to_desc(flits); 1132 ndesc = flits_to_desc(flits);
@@ -1153,13 +1198,17 @@ out_free: dev_kfree_skb_any(skb);
1153 if (skb->ip_summed == CHECKSUM_PARTIAL) { 1198 if (skb->ip_summed == CHECKSUM_PARTIAL) {
1154 cntrl = hwcsum(skb) | TXPKT_IPCSUM_DIS; 1199 cntrl = hwcsum(skb) | TXPKT_IPCSUM_DIS;
1155 q->tx_cso++; 1200 q->tx_cso++;
1156 } else 1201 }
1157 cntrl = TXPKT_L4CSUM_DIS | TXPKT_IPCSUM_DIS;
1158 } 1202 }
1159 1203
1160 if (skb_vlan_tag_present(skb)) { 1204 if (skb_vlan_tag_present(skb)) {
1161 q->vlan_ins++; 1205 q->vlan_ins++;
1162 cntrl |= TXPKT_VLAN_VLD | TXPKT_VLAN(skb_vlan_tag_get(skb)); 1206 cntrl |= TXPKT_VLAN_VLD | TXPKT_VLAN(skb_vlan_tag_get(skb));
1207#ifdef CONFIG_CHELSIO_T4_FCOE
1208 if (skb->protocol == htons(ETH_P_FCOE))
1209 cntrl |= TXPKT_VLAN(
1210 ((skb->priority & 0x7) << VLAN_PRIO_SHIFT));
1211#endif /* CONFIG_CHELSIO_T4_FCOE */
1163 } 1212 }
1164 1213
1165 cpl->ctrl0 = htonl(TXPKT_OPCODE(CPL_TX_PKT_XT) | 1214 cpl->ctrl0 = htonl(TXPKT_OPCODE(CPL_TX_PKT_XT) |
@@ -1759,6 +1808,9 @@ int t4_ethrx_handler(struct sge_rspq *q, const __be64 *rsp,
1759 struct sge *s = &q->adap->sge; 1808 struct sge *s = &q->adap->sge;
1760 int cpl_trace_pkt = is_t4(q->adap->params.chip) ? 1809 int cpl_trace_pkt = is_t4(q->adap->params.chip) ?
1761 CPL_TRACE_PKT : CPL_TRACE_PKT_T5; 1810 CPL_TRACE_PKT : CPL_TRACE_PKT_T5;
1811#ifdef CONFIG_CHELSIO_T4_FCOE
1812 struct port_info *pi;
1813#endif
1762 1814
1763 if (unlikely(*(u8 *)rsp == cpl_trace_pkt)) 1815 if (unlikely(*(u8 *)rsp == cpl_trace_pkt))
1764 return handle_trace_pkt(q->adap, si); 1816 return handle_trace_pkt(q->adap, si);
@@ -1799,8 +1851,24 @@ int t4_ethrx_handler(struct sge_rspq *q, const __be64 *rsp,
1799 skb->ip_summed = CHECKSUM_COMPLETE; 1851 skb->ip_summed = CHECKSUM_COMPLETE;
1800 rxq->stats.rx_cso++; 1852 rxq->stats.rx_cso++;
1801 } 1853 }
1802 } else 1854 } else {
1803 skb_checksum_none_assert(skb); 1855 skb_checksum_none_assert(skb);
1856#ifdef CONFIG_CHELSIO_T4_FCOE
1857#define CPL_RX_PKT_FLAGS (RXF_PSH_F | RXF_SYN_F | RXF_UDP_F | \
1858 RXF_TCP_F | RXF_IP_F | RXF_IP6_F | RXF_LRO_F)
1859
1860 pi = netdev_priv(skb->dev);
1861 if (!(pkt->l2info & cpu_to_be32(CPL_RX_PKT_FLAGS))) {
1862 if ((pkt->l2info & cpu_to_be32(RXF_FCOE_F)) &&
1863 (pi->fcoe.flags & CXGB_FCOE_ENABLED)) {
1864 if (!(pkt->err_vec & cpu_to_be16(RXERR_CSUM_F)))
1865 skb->ip_summed = CHECKSUM_UNNECESSARY;
1866 }
1867 }
1868
1869#undef CPL_RX_PKT_FLAGS
1870#endif /* CONFIG_CHELSIO_T4_FCOE */
1871 }
1804 1872
1805 if (unlikely(pkt->vlan_ex)) { 1873 if (unlikely(pkt->vlan_ex)) {
1806 __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), ntohs(pkt->vlan)); 1874 __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), ntohs(pkt->vlan));