aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ixgbe/ixgbe_fcoe.c
diff options
context:
space:
mode:
authorYi Zou <yi.zou@intel.com>2009-05-13 09:10:44 -0400
committerDavid S. Miller <davem@davemloft.net>2009-05-17 15:00:03 -0400
commitbc079228e74d63742255c466d2bce1f42423f219 (patch)
treeb0052256c7883ed7f87424945366b049250a3eb0 /drivers/net/ixgbe/ixgbe_fcoe.c
parentd3a2ae6d315382b2dcc7747c5b3b70f0490e9157 (diff)
ixgbe: Add infrastructure code for FCoE large send offload to 82599
This adds infrastructure code for FCoE Tx side offload feature to 82599, including Fiber Channel CRC calculation, auto insertion of the start of frame (SOF) and end of frame (EOF) of FCoE packets, and large send by FCoE Sequence Offload (FSO). Signed-off-by: Yi Zou <yi.zou@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ixgbe/ixgbe_fcoe.c')
-rw-r--r--drivers/net/ixgbe/ixgbe_fcoe.c132
1 files changed, 132 insertions, 0 deletions
diff --git a/drivers/net/ixgbe/ixgbe_fcoe.c b/drivers/net/ixgbe/ixgbe_fcoe.c
index f8c4d357636d..e20facd1f2df 100644
--- a/drivers/net/ixgbe/ixgbe_fcoe.c
+++ b/drivers/net/ixgbe/ixgbe_fcoe.c
@@ -36,6 +36,138 @@
36#include <scsi/libfcoe.h> 36#include <scsi/libfcoe.h>
37 37
38/** 38/**
39 * ixgbe_fso - ixgbe FCoE Sequence Offload (FSO)
40 * @adapter: ixgbe adapter
41 * @tx_ring: tx desc ring
42 * @skb: associated skb
43 * @tx_flags: tx flags
44 * @hdr_len: hdr_len to be returned
45 *
46 * This sets up large send offload for FCoE
47 *
48 * Returns : 0 indicates no FSO, > 0 for FSO, < 0 for error
49 */
50int ixgbe_fso(struct ixgbe_adapter *adapter,
51 struct ixgbe_ring *tx_ring, struct sk_buff *skb,
52 u32 tx_flags, u8 *hdr_len)
53{
54 u8 sof, eof;
55 u32 vlan_macip_lens;
56 u32 fcoe_sof_eof;
57 u32 type_tucmd;
58 u32 mss_l4len_idx;
59 int mss = 0;
60 unsigned int i;
61 struct ixgbe_tx_buffer *tx_buffer_info;
62 struct ixgbe_adv_tx_context_desc *context_desc;
63 struct fc_frame_header *fh;
64
65 if (skb_is_gso(skb) && (skb_shinfo(skb)->gso_type != SKB_GSO_FCOE)) {
66 DPRINTK(DRV, ERR, "Wrong gso type %d:expecting SKB_GSO_FCOE\n",
67 skb_shinfo(skb)->gso_type);
68 return -EINVAL;
69 }
70
71 /* resets the header to point fcoe/fc */
72 skb_set_network_header(skb, skb->mac_len);
73 skb_set_transport_header(skb, skb->mac_len +
74 sizeof(struct fcoe_hdr));
75
76 /* sets up SOF and ORIS */
77 fcoe_sof_eof = 0;
78 sof = ((struct fcoe_hdr *)skb_network_header(skb))->fcoe_sof;
79 switch (sof) {
80 case FC_SOF_I2:
81 fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_ORIS;
82 break;
83 case FC_SOF_I3:
84 fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_SOF;
85 fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_ORIS;
86 break;
87 case FC_SOF_N2:
88 break;
89 case FC_SOF_N3:
90 fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_SOF;
91 break;
92 default:
93 DPRINTK(DRV, WARNING, "unknown sof = 0x%x\n", sof);
94 return -EINVAL;
95 }
96
97 /* the first byte of the last dword is EOF */
98 skb_copy_bits(skb, skb->len - 4, &eof, 1);
99 /* sets up EOF and ORIE */
100 switch (eof) {
101 case FC_EOF_N:
102 fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_EOF_N;
103 break;
104 case FC_EOF_T:
105 /* lso needs ORIE */
106 if (skb_is_gso(skb)) {
107 fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_EOF_N;
108 fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_ORIE;
109 } else {
110 fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_EOF_T;
111 }
112 break;
113 case FC_EOF_NI:
114 fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_EOF_NI;
115 break;
116 case FC_EOF_A:
117 fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_EOF_A;
118 break;
119 default:
120 DPRINTK(DRV, WARNING, "unknown eof = 0x%x\n", eof);
121 return -EINVAL;
122 }
123
124 /* sets up PARINC indicating data offset */
125 fh = (struct fc_frame_header *)skb_transport_header(skb);
126 if (fh->fh_f_ctl[2] & FC_FC_REL_OFF)
127 fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_PARINC;
128
129 /* hdr_len includes fc_hdr if FCoE lso is enabled */
130 *hdr_len = sizeof(struct fcoe_crc_eof);
131 if (skb_is_gso(skb))
132 *hdr_len += (skb_transport_offset(skb) +
133 sizeof(struct fc_frame_header));
134 /* vlan_macip_lens: HEADLEN, MACLEN, VLAN tag */
135 vlan_macip_lens = (skb_transport_offset(skb) +
136 sizeof(struct fc_frame_header));
137 vlan_macip_lens |= ((skb_transport_offset(skb) - 4)
138 << IXGBE_ADVTXD_MACLEN_SHIFT);
139 vlan_macip_lens |= (tx_flags & IXGBE_TX_FLAGS_VLAN_MASK);
140
141 /* type_tycmd and mss: set TUCMD.FCoE to enable offload */
142 type_tucmd = IXGBE_TXD_CMD_DEXT | IXGBE_ADVTXD_DTYP_CTXT |
143 IXGBE_ADVTXT_TUCMD_FCOE;
144 if (skb_is_gso(skb))
145 mss = skb_shinfo(skb)->gso_size;
146 /* mss_l4len_id: use 1 for FSO as TSO, no need for L4LEN */
147 mss_l4len_idx = (mss << IXGBE_ADVTXD_MSS_SHIFT) |
148 (1 << IXGBE_ADVTXD_IDX_SHIFT);
149
150 /* write context desc */
151 i = tx_ring->next_to_use;
152 context_desc = IXGBE_TX_CTXTDESC_ADV(*tx_ring, i);
153 context_desc->vlan_macip_lens = cpu_to_le32(vlan_macip_lens);
154 context_desc->seqnum_seed = cpu_to_le32(fcoe_sof_eof);
155 context_desc->type_tucmd_mlhl = cpu_to_le32(type_tucmd);
156 context_desc->mss_l4len_idx = cpu_to_le32(mss_l4len_idx);
157
158 tx_buffer_info = &tx_ring->tx_buffer_info[i];
159 tx_buffer_info->time_stamp = jiffies;
160 tx_buffer_info->next_to_watch = i;
161
162 i++;
163 if (i == tx_ring->count)
164 i = 0;
165 tx_ring->next_to_use = i;
166
167 return skb_is_gso(skb);
168}
169
170/**
39 * ixgbe_configure_fcoe - configures registers for fcoe at start 171 * ixgbe_configure_fcoe - configures registers for fcoe at start
40 * @adapter: ptr to ixgbe adapter 172 * @adapter: ptr to ixgbe adapter
41 * 173 *