Commit | Line | Data |
---|---|---|
a1a69369 VD |
1 | /******************************************************************************* |
2 | * | |
3 | * Intel Ethernet Controller XL710 Family Linux Driver | |
51616018 | 4 | * Copyright(c) 2013 - 2015 Intel Corporation. |
a1a69369 VD |
5 | * |
6 | * This program is free software; you can redistribute it and/or modify it | |
7 | * under the terms and conditions of the GNU General Public License, | |
8 | * version 2, as published by the Free Software Foundation. | |
9 | * | |
10 | * This program is distributed in the hope it will be useful, but WITHOUT | |
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
13 | * more details. | |
14 | * | |
15 | * You should have received a copy of the GNU General Public License along | |
16 | * with this program. If not, see <http://www.gnu.org/licenses/>. | |
17 | * | |
18 | * The full GNU General Public License is included in this distribution in | |
19 | * the file called "COPYING". | |
20 | * | |
21 | * Contact Information: | |
22 | * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> | |
23 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | |
24 | * | |
25 | ******************************************************************************/ | |
26 | ||
a1a69369 VD |
27 | #include <linux/if_ether.h> |
28 | #include <scsi/scsi_cmnd.h> | |
29 | #include <scsi/scsi_device.h> | |
30 | #include <scsi/fc/fc_fs.h> | |
31 | #include <scsi/fc/fc_fip.h> | |
32 | #include <scsi/fc/fc_fcoe.h> | |
33 | #include <scsi/libfc.h> | |
34 | #include <scsi/libfcoe.h> | |
e222ade6 | 35 | #include <uapi/linux/dcbnl.h> |
a1a69369 VD |
36 | |
37 | #include "i40e.h" | |
38 | #include "i40e_fcoe.h" | |
39 | ||
a1a69369 VD |
40 | /** |
41 | * i40e_rx_is_fcoe - returns true if the rx packet type is FCoE | |
42 | * @ptype: the packet type field from rx descriptor write-back | |
43 | **/ | |
44 | static inline bool i40e_rx_is_fcoe(u16 ptype) | |
45 | { | |
46 | return (ptype >= I40E_RX_PTYPE_L2_FCOE_PAY3) && | |
47 | (ptype <= I40E_RX_PTYPE_L2_FCOE_VFT_FCOTHER); | |
48 | } | |
49 | ||
50 | /** | |
51 | * i40e_fcoe_sof_is_class2 - returns true if this is a FC Class 2 SOF | |
52 | * @sof: the FCoE start of frame delimiter | |
53 | **/ | |
54 | static inline bool i40e_fcoe_sof_is_class2(u8 sof) | |
55 | { | |
56 | return (sof == FC_SOF_I2) || (sof == FC_SOF_N2); | |
57 | } | |
58 | ||
59 | /** | |
60 | * i40e_fcoe_sof_is_class3 - returns true if this is a FC Class 3 SOF | |
61 | * @sof: the FCoE start of frame delimiter | |
62 | **/ | |
63 | static inline bool i40e_fcoe_sof_is_class3(u8 sof) | |
64 | { | |
65 | return (sof == FC_SOF_I3) || (sof == FC_SOF_N3); | |
66 | } | |
67 | ||
68 | /** | |
69 | * i40e_fcoe_sof_is_supported - returns true if the FC SOF is supported by HW | |
70 | * @sof: the input SOF value from the frame | |
71 | **/ | |
72 | static inline bool i40e_fcoe_sof_is_supported(u8 sof) | |
73 | { | |
74 | return i40e_fcoe_sof_is_class2(sof) || | |
75 | i40e_fcoe_sof_is_class3(sof); | |
76 | } | |
77 | ||
78 | /** | |
79 | * i40e_fcoe_fc_sof - pull the SOF from FCoE header in the frame | |
80 | * @skb: the frame whose EOF is to be pulled from | |
81 | **/ | |
82 | static inline int i40e_fcoe_fc_sof(struct sk_buff *skb, u8 *sof) | |
83 | { | |
84 | *sof = ((struct fcoe_hdr *)skb_network_header(skb))->fcoe_sof; | |
85 | ||
86 | if (!i40e_fcoe_sof_is_supported(*sof)) | |
87 | return -EINVAL; | |
88 | return 0; | |
89 | } | |
90 | ||
91 | /** | |
92 | * i40e_fcoe_eof_is_supported - returns true if the EOF is supported by HW | |
93 | * @eof: the input EOF value from the frame | |
94 | **/ | |
95 | static inline bool i40e_fcoe_eof_is_supported(u8 eof) | |
96 | { | |
97 | return (eof == FC_EOF_N) || (eof == FC_EOF_T) || | |
98 | (eof == FC_EOF_NI) || (eof == FC_EOF_A); | |
99 | } | |
100 | ||
101 | /** | |
102 | * i40e_fcoe_fc_eof - pull EOF from FCoE trailer in the frame | |
103 | * @skb: the frame whose EOF is to be pulled from | |
104 | **/ | |
105 | static inline int i40e_fcoe_fc_eof(struct sk_buff *skb, u8 *eof) | |
106 | { | |
107 | /* the first byte of the last dword is EOF */ | |
108 | skb_copy_bits(skb, skb->len - 4, eof, 1); | |
109 | ||
110 | if (!i40e_fcoe_eof_is_supported(*eof)) | |
111 | return -EINVAL; | |
112 | return 0; | |
113 | } | |
114 | ||
115 | /** | |
116 | * i40e_fcoe_ctxt_eof - convert input FC EOF for descriptor programming | |
117 | * @eof: the input eof value from the frame | |
118 | * | |
119 | * The FC EOF is converted to the value understood by HW for descriptor | |
120 | * programming. Never call this w/o calling i40e_fcoe_eof_is_supported() | |
121 | * first. | |
122 | **/ | |
123 | static inline u32 i40e_fcoe_ctxt_eof(u8 eof) | |
124 | { | |
125 | switch (eof) { | |
126 | case FC_EOF_N: | |
127 | return I40E_TX_DESC_CMD_L4T_EOFT_EOF_N; | |
128 | case FC_EOF_T: | |
129 | return I40E_TX_DESC_CMD_L4T_EOFT_EOF_T; | |
130 | case FC_EOF_NI: | |
131 | return I40E_TX_DESC_CMD_L4T_EOFT_EOF_NI; | |
132 | case FC_EOF_A: | |
133 | return I40E_TX_DESC_CMD_L4T_EOFT_EOF_A; | |
134 | default: | |
135 | /* FIXME: still returns 0 */ | |
136 | pr_err("Unrecognized EOF %x\n", eof); | |
137 | return 0; | |
138 | } | |
139 | } | |
140 | ||
141 | /** | |
142 | * i40e_fcoe_xid_is_valid - returns true if the exchange id is valid | |
143 | * @xid: the exchange id | |
144 | **/ | |
145 | static inline bool i40e_fcoe_xid_is_valid(u16 xid) | |
146 | { | |
147 | return (xid != FC_XID_UNKNOWN) && (xid < I40E_FCOE_DDP_MAX); | |
148 | } | |
149 | ||
150 | /** | |
151 | * i40e_fcoe_ddp_unmap - unmap the mapped sglist associated | |
b40c82e6 | 152 | * @pf: pointer to PF |
a1a69369 VD |
153 | * @ddp: sw DDP context |
154 | * | |
155 | * Unmap the scatter-gather list associated with the given SW DDP context | |
156 | * | |
157 | * Returns: data length already ddp-ed in bytes | |
158 | * | |
159 | **/ | |
160 | static inline void i40e_fcoe_ddp_unmap(struct i40e_pf *pf, | |
161 | struct i40e_fcoe_ddp *ddp) | |
162 | { | |
163 | if (test_and_set_bit(__I40E_FCOE_DDP_UNMAPPED, &ddp->flags)) | |
164 | return; | |
165 | ||
166 | if (ddp->sgl) { | |
167 | dma_unmap_sg(&pf->pdev->dev, ddp->sgl, ddp->sgc, | |
168 | DMA_FROM_DEVICE); | |
169 | ddp->sgl = NULL; | |
170 | ddp->sgc = 0; | |
171 | } | |
172 | ||
173 | if (ddp->pool) { | |
174 | dma_pool_free(ddp->pool, ddp->udl, ddp->udp); | |
175 | ddp->pool = NULL; | |
176 | } | |
177 | } | |
178 | ||
179 | /** | |
180 | * i40e_fcoe_ddp_clear - clear the given SW DDP context | |
181 | * @ddp - SW DDP context | |
182 | **/ | |
183 | static inline void i40e_fcoe_ddp_clear(struct i40e_fcoe_ddp *ddp) | |
184 | { | |
185 | memset(ddp, 0, sizeof(struct i40e_fcoe_ddp)); | |
186 | ddp->xid = FC_XID_UNKNOWN; | |
187 | ddp->flags = __I40E_FCOE_DDP_NONE; | |
188 | } | |
189 | ||
190 | /** | |
191 | * i40e_fcoe_progid_is_fcoe - check if the prog_id is for FCoE | |
192 | * @id: the prog id for the programming status Rx descriptor write-back | |
193 | **/ | |
194 | static inline bool i40e_fcoe_progid_is_fcoe(u8 id) | |
195 | { | |
196 | return (id == I40E_RX_PROG_STATUS_DESC_FCOE_CTXT_PROG_STATUS) || | |
197 | (id == I40E_RX_PROG_STATUS_DESC_FCOE_CTXT_INVL_STATUS); | |
198 | } | |
199 | ||
200 | /** | |
201 | * i40e_fcoe_fc_get_xid - get xid from the frame header | |
202 | * @fh: the fc frame header | |
203 | * | |
204 | * In case the incoming frame's exchange is originated from | |
205 | * the initiator, then received frame's exchange id is ANDed | |
206 | * with fc_cpu_mask bits to get the same cpu on which exchange | |
207 | * was originated, otherwise just use the current cpu. | |
208 | * | |
209 | * Returns ox_id if exchange originator, rx_id if responder | |
210 | **/ | |
211 | static inline u16 i40e_fcoe_fc_get_xid(struct fc_frame_header *fh) | |
212 | { | |
213 | u32 f_ctl = ntoh24(fh->fh_f_ctl); | |
214 | ||
215 | return (f_ctl & FC_FC_EX_CTX) ? | |
216 | be16_to_cpu(fh->fh_ox_id) : | |
217 | be16_to_cpu(fh->fh_rx_id); | |
218 | } | |
219 | ||
220 | /** | |
221 | * i40e_fcoe_fc_frame_header - get fc frame header from skb | |
222 | * @skb: packet | |
223 | * | |
224 | * This checks if there is a VLAN header and returns the data | |
225 | * pointer to the start of the fc_frame_header. | |
226 | * | |
227 | * Returns pointer to the fc_frame_header | |
228 | **/ | |
229 | static inline struct fc_frame_header *i40e_fcoe_fc_frame_header( | |
230 | struct sk_buff *skb) | |
231 | { | |
232 | void *fh = skb->data + sizeof(struct fcoe_hdr); | |
233 | ||
234 | if (eth_hdr(skb)->h_proto == htons(ETH_P_8021Q)) | |
235 | fh += sizeof(struct vlan_hdr); | |
236 | ||
237 | return (struct fc_frame_header *)fh; | |
238 | } | |
239 | ||
240 | /** | |
241 | * i40e_fcoe_ddp_put - release the DDP context for a given exchange id | |
242 | * @netdev: the corresponding net_device | |
243 | * @xid: the exchange id that corresponding DDP context will be released | |
244 | * | |
245 | * This is the implementation of net_device_ops.ndo_fcoe_ddp_done | |
246 | * and it is expected to be called by ULD, i.e., FCP layer of libfc | |
247 | * to release the corresponding ddp context when the I/O is done. | |
248 | * | |
249 | * Returns : data length already ddp-ed in bytes | |
250 | **/ | |
251 | static int i40e_fcoe_ddp_put(struct net_device *netdev, u16 xid) | |
252 | { | |
253 | struct i40e_netdev_priv *np = netdev_priv(netdev); | |
254 | struct i40e_pf *pf = np->vsi->back; | |
255 | struct i40e_fcoe *fcoe = &pf->fcoe; | |
256 | int len = 0; | |
257 | struct i40e_fcoe_ddp *ddp = &fcoe->ddp[xid]; | |
258 | ||
259 | if (!fcoe || !ddp) | |
260 | goto out; | |
261 | ||
262 | if (test_bit(__I40E_FCOE_DDP_DONE, &ddp->flags)) | |
263 | len = ddp->len; | |
264 | i40e_fcoe_ddp_unmap(pf, ddp); | |
265 | out: | |
266 | return len; | |
267 | } | |
268 | ||
269 | /** | |
270 | * i40e_fcoe_sw_init - sets up the HW for FCoE | |
b40c82e6 | 271 | * @pf: pointer to PF |
a1a69369 VD |
272 | * |
273 | * Returns 0 if FCoE is supported otherwise the error code | |
274 | **/ | |
275 | int i40e_init_pf_fcoe(struct i40e_pf *pf) | |
276 | { | |
277 | struct i40e_hw *hw = &pf->hw; | |
278 | u32 val; | |
279 | ||
280 | pf->flags &= ~I40E_FLAG_FCOE_ENABLED; | |
281 | pf->num_fcoe_qps = 0; | |
282 | pf->fcoe_hmc_cntx_num = 0; | |
283 | pf->fcoe_hmc_filt_num = 0; | |
284 | ||
285 | if (!pf->hw.func_caps.fcoe) { | |
286 | dev_info(&pf->pdev->dev, "FCoE capability is disabled\n"); | |
287 | return 0; | |
288 | } | |
289 | ||
290 | if (!pf->hw.func_caps.dcb) { | |
291 | dev_warn(&pf->pdev->dev, | |
292 | "Hardware is not DCB capable not enabling FCoE.\n"); | |
293 | return 0; | |
294 | } | |
295 | ||
296 | /* enable FCoE hash filter */ | |
297 | val = rd32(hw, I40E_PFQF_HENA(1)); | |
298 | val |= 1 << (I40E_FILTER_PCTYPE_FCOE_OX - 32); | |
299 | val |= 1 << (I40E_FILTER_PCTYPE_FCOE_RX - 32); | |
300 | val &= I40E_PFQF_HENA_PTYPE_ENA_MASK; | |
301 | wr32(hw, I40E_PFQF_HENA(1), val); | |
302 | ||
303 | /* enable flag */ | |
304 | pf->flags |= I40E_FLAG_FCOE_ENABLED; | |
305 | pf->num_fcoe_qps = I40E_DEFAULT_FCOE; | |
306 | ||
307 | /* Reserve 4K DDP contexts and 20K filter size for FCoE */ | |
308 | pf->fcoe_hmc_cntx_num = (1 << I40E_DMA_CNTX_SIZE_4K) * | |
309 | I40E_DMA_CNTX_BASE_SIZE; | |
310 | pf->fcoe_hmc_filt_num = pf->fcoe_hmc_cntx_num + | |
311 | (1 << I40E_HASH_FILTER_SIZE_16K) * | |
312 | I40E_HASH_FILTER_BASE_SIZE; | |
313 | ||
314 | /* FCoE object: max 16K filter buckets and 4K DMA contexts */ | |
315 | pf->filter_settings.fcoe_filt_num = I40E_HASH_FILTER_SIZE_16K; | |
316 | pf->filter_settings.fcoe_cntx_num = I40E_DMA_CNTX_SIZE_4K; | |
317 | ||
318 | /* Setup max frame with FCoE_MTU plus L2 overheads */ | |
319 | val = rd32(hw, I40E_GLFCOE_RCTL); | |
320 | val &= ~I40E_GLFCOE_RCTL_MAX_SIZE_MASK; | |
321 | val |= ((FCOE_MTU + ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN) | |
322 | << I40E_GLFCOE_RCTL_MAX_SIZE_SHIFT); | |
323 | wr32(hw, I40E_GLFCOE_RCTL, val); | |
324 | ||
325 | dev_info(&pf->pdev->dev, "FCoE is supported.\n"); | |
326 | return 0; | |
327 | } | |
328 | ||
329 | /** | |
330 | * i40e_get_fcoe_tc_map - Return TC map for FCoE APP | |
b40c82e6 | 331 | * @pf: pointer to PF |
a1a69369 VD |
332 | * |
333 | **/ | |
334 | u8 i40e_get_fcoe_tc_map(struct i40e_pf *pf) | |
335 | { | |
9fa61dd2 | 336 | struct i40e_dcb_app_priority_table app; |
a1a69369 VD |
337 | struct i40e_hw *hw = &pf->hw; |
338 | u8 enabled_tc = 0; | |
339 | u8 tc, i; | |
340 | /* Get the FCoE APP TLV */ | |
341 | struct i40e_dcbx_config *dcbcfg = &hw->local_dcbx_config; | |
342 | ||
343 | for (i = 0; i < dcbcfg->numapps; i++) { | |
344 | app = dcbcfg->app[i]; | |
345 | if (app.selector == IEEE_8021QAZ_APP_SEL_ETHERTYPE && | |
346 | app.protocolid == ETH_P_FCOE) { | |
347 | tc = dcbcfg->etscfg.prioritytable[app.priority]; | |
348 | enabled_tc |= (1 << tc); | |
349 | break; | |
350 | } | |
351 | } | |
352 | ||
353 | /* TC0 if there is no TC defined for FCoE APP TLV */ | |
354 | enabled_tc = enabled_tc ? enabled_tc : 0x1; | |
355 | ||
356 | return enabled_tc; | |
357 | } | |
358 | ||
359 | /** | |
360 | * i40e_fcoe_vsi_init - prepares the VSI context for creating a FCoE VSI | |
361 | * @vsi: pointer to the associated VSI struct | |
362 | * @ctxt: pointer to the associated VSI context to be passed to HW | |
363 | * | |
364 | * Returns 0 on success or < 0 on error | |
365 | **/ | |
366 | int i40e_fcoe_vsi_init(struct i40e_vsi *vsi, struct i40e_vsi_context *ctxt) | |
367 | { | |
368 | struct i40e_aqc_vsi_properties_data *info = &ctxt->info; | |
369 | struct i40e_pf *pf = vsi->back; | |
370 | struct i40e_hw *hw = &pf->hw; | |
371 | u8 enabled_tc = 0; | |
372 | ||
373 | if (!(pf->flags & I40E_FLAG_FCOE_ENABLED)) { | |
374 | dev_err(&pf->pdev->dev, | |
375 | "FCoE is not enabled for this device\n"); | |
376 | return -EPERM; | |
377 | } | |
378 | ||
379 | /* initialize the hardware for FCoE */ | |
380 | ctxt->pf_num = hw->pf_id; | |
381 | ctxt->vf_num = 0; | |
382 | ctxt->uplink_seid = vsi->uplink_seid; | |
2b18e591 | 383 | ctxt->connection_type = I40E_AQ_VSI_CONN_TYPE_NORMAL; |
a1a69369 VD |
384 | ctxt->flags = I40E_AQ_VSI_TYPE_PF; |
385 | ||
386 | /* FCoE VSI would need the following sections */ | |
51616018 | 387 | info->valid_sections |= cpu_to_le16(I40E_AQ_VSI_PROP_QUEUE_OPT_VALID); |
a1a69369 VD |
388 | |
389 | /* FCoE VSI does not need these sections */ | |
390 | info->valid_sections &= cpu_to_le16(~(I40E_AQ_VSI_PROP_SECURITY_VALID | | |
391 | I40E_AQ_VSI_PROP_VLAN_VALID | | |
392 | I40E_AQ_VSI_PROP_CAS_PV_VALID | | |
393 | I40E_AQ_VSI_PROP_INGRESS_UP_VALID | | |
394 | I40E_AQ_VSI_PROP_EGRESS_UP_VALID)); | |
395 | ||
51616018 NP |
396 | if (i40e_is_vsi_uplink_mode_veb(vsi)) { |
397 | info->valid_sections |= | |
398 | cpu_to_le16(I40E_AQ_VSI_PROP_SWITCH_VALID); | |
399 | info->switch_id = | |
400 | cpu_to_le16(I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB); | |
401 | } | |
a1a69369 VD |
402 | enabled_tc = i40e_get_fcoe_tc_map(pf); |
403 | i40e_vsi_setup_queue_map(vsi, ctxt, enabled_tc, true); | |
404 | ||
405 | /* set up queue option section: only enable FCoE */ | |
406 | info->queueing_opt_flags = I40E_AQ_VSI_QUE_OPT_FCOE_ENA; | |
407 | ||
408 | return 0; | |
409 | } | |
410 | ||
411 | /** | |
412 | * i40e_fcoe_enable - this is the implementation of ndo_fcoe_enable, | |
413 | * indicating the upper FCoE protocol stack is ready to use FCoE | |
414 | * offload features. | |
415 | * | |
416 | * @netdev: pointer to the netdev that FCoE is created on | |
417 | * | |
418 | * Returns 0 on success | |
419 | * | |
420 | * in RTNL | |
421 | * | |
422 | **/ | |
423 | int i40e_fcoe_enable(struct net_device *netdev) | |
424 | { | |
425 | struct i40e_netdev_priv *np = netdev_priv(netdev); | |
426 | struct i40e_vsi *vsi = np->vsi; | |
427 | struct i40e_pf *pf = vsi->back; | |
428 | struct i40e_fcoe *fcoe = &pf->fcoe; | |
429 | ||
430 | if (!(pf->flags & I40E_FLAG_FCOE_ENABLED)) { | |
431 | netdev_err(netdev, "HW does not support FCoE.\n"); | |
432 | return -ENODEV; | |
433 | } | |
434 | ||
435 | if (vsi->type != I40E_VSI_FCOE) { | |
436 | netdev_err(netdev, "interface does not support FCoE.\n"); | |
437 | return -EBUSY; | |
438 | } | |
439 | ||
440 | atomic_inc(&fcoe->refcnt); | |
441 | ||
442 | return 0; | |
443 | } | |
444 | ||
445 | /** | |
446 | * i40e_fcoe_disable- disables FCoE for upper FCoE protocol stack. | |
447 | * @dev: pointer to the netdev that FCoE is created on | |
448 | * | |
449 | * Returns 0 on success | |
450 | * | |
451 | **/ | |
452 | int i40e_fcoe_disable(struct net_device *netdev) | |
453 | { | |
454 | struct i40e_netdev_priv *np = netdev_priv(netdev); | |
455 | struct i40e_vsi *vsi = np->vsi; | |
456 | struct i40e_pf *pf = vsi->back; | |
457 | struct i40e_fcoe *fcoe = &pf->fcoe; | |
458 | ||
459 | if (!(pf->flags & I40E_FLAG_FCOE_ENABLED)) { | |
460 | netdev_err(netdev, "device does not support FCoE\n"); | |
461 | return -ENODEV; | |
462 | } | |
463 | if (vsi->type != I40E_VSI_FCOE) | |
464 | return -EBUSY; | |
465 | ||
466 | if (!atomic_dec_and_test(&fcoe->refcnt)) | |
467 | return -EINVAL; | |
468 | ||
469 | netdev_info(netdev, "FCoE disabled\n"); | |
470 | ||
471 | return 0; | |
472 | } | |
473 | ||
474 | /** | |
475 | * i40e_fcoe_dma_pool_free - free the per cpu pool for FCoE DDP | |
476 | * @fcoe: the FCoE sw object | |
477 | * @dev: the device that the pool is associated with | |
478 | * @cpu: the cpu for this pool | |
479 | * | |
480 | **/ | |
481 | static void i40e_fcoe_dma_pool_free(struct i40e_fcoe *fcoe, | |
482 | struct device *dev, | |
483 | unsigned int cpu) | |
484 | { | |
485 | struct i40e_fcoe_ddp_pool *ddp_pool; | |
486 | ||
487 | ddp_pool = per_cpu_ptr(fcoe->ddp_pool, cpu); | |
488 | if (!ddp_pool->pool) { | |
489 | dev_warn(dev, "DDP pool already freed for cpu %d\n", cpu); | |
490 | return; | |
491 | } | |
492 | dma_pool_destroy(ddp_pool->pool); | |
493 | ddp_pool->pool = NULL; | |
494 | } | |
495 | ||
496 | /** | |
497 | * i40e_fcoe_dma_pool_create - per cpu pool for FCoE DDP | |
498 | * @fcoe: the FCoE sw object | |
499 | * @dev: the device that the pool is associated with | |
500 | * @cpu: the cpu for this pool | |
501 | * | |
502 | * Returns 0 on successful or non zero on failure | |
503 | * | |
504 | **/ | |
505 | static int i40e_fcoe_dma_pool_create(struct i40e_fcoe *fcoe, | |
506 | struct device *dev, | |
507 | unsigned int cpu) | |
508 | { | |
509 | struct i40e_fcoe_ddp_pool *ddp_pool; | |
510 | struct dma_pool *pool; | |
511 | char pool_name[32]; | |
512 | ||
513 | ddp_pool = per_cpu_ptr(fcoe->ddp_pool, cpu); | |
514 | if (ddp_pool && ddp_pool->pool) { | |
515 | dev_warn(dev, "DDP pool already allocated for cpu %d\n", cpu); | |
516 | return 0; | |
517 | } | |
518 | snprintf(pool_name, sizeof(pool_name), "i40e_fcoe_ddp_%d", cpu); | |
519 | pool = dma_pool_create(pool_name, dev, I40E_FCOE_DDP_PTR_MAX, | |
520 | I40E_FCOE_DDP_PTR_ALIGN, PAGE_SIZE); | |
521 | if (!pool) { | |
522 | dev_err(dev, "dma_pool_create %s failed\n", pool_name); | |
523 | return -ENOMEM; | |
524 | } | |
525 | ddp_pool->pool = pool; | |
526 | return 0; | |
527 | } | |
528 | ||
529 | /** | |
530 | * i40e_fcoe_free_ddp_resources - release FCoE DDP resources | |
531 | * @vsi: the vsi FCoE is associated with | |
532 | * | |
533 | **/ | |
534 | void i40e_fcoe_free_ddp_resources(struct i40e_vsi *vsi) | |
535 | { | |
536 | struct i40e_pf *pf = vsi->back; | |
537 | struct i40e_fcoe *fcoe = &pf->fcoe; | |
538 | int cpu, i; | |
539 | ||
540 | /* do nothing if not FCoE VSI */ | |
541 | if (vsi->type != I40E_VSI_FCOE) | |
542 | return; | |
543 | ||
544 | /* do nothing if no DDP pools were allocated */ | |
545 | if (!fcoe->ddp_pool) | |
546 | return; | |
547 | ||
548 | for (i = 0; i < I40E_FCOE_DDP_MAX; i++) | |
549 | i40e_fcoe_ddp_put(vsi->netdev, i); | |
550 | ||
551 | for_each_possible_cpu(cpu) | |
552 | i40e_fcoe_dma_pool_free(fcoe, &pf->pdev->dev, cpu); | |
553 | ||
554 | free_percpu(fcoe->ddp_pool); | |
555 | fcoe->ddp_pool = NULL; | |
556 | ||
557 | netdev_info(vsi->netdev, "VSI %d,%d FCoE DDP resources released\n", | |
558 | vsi->id, vsi->seid); | |
559 | } | |
560 | ||
561 | /** | |
562 | * i40e_fcoe_setup_ddp_resources - allocate per cpu DDP resources | |
563 | * @vsi: the VSI FCoE is associated with | |
564 | * | |
565 | * Returns 0 on successful or non zero on failure | |
566 | * | |
567 | **/ | |
568 | int i40e_fcoe_setup_ddp_resources(struct i40e_vsi *vsi) | |
569 | { | |
570 | struct i40e_pf *pf = vsi->back; | |
571 | struct device *dev = &pf->pdev->dev; | |
572 | struct i40e_fcoe *fcoe = &pf->fcoe; | |
573 | unsigned int cpu; | |
574 | int i; | |
575 | ||
576 | if (vsi->type != I40E_VSI_FCOE) | |
577 | return -ENODEV; | |
578 | ||
579 | /* do nothing if no DDP pools were allocated */ | |
580 | if (fcoe->ddp_pool) | |
581 | return -EEXIST; | |
582 | ||
583 | /* allocate per CPU memory to track DDP pools */ | |
584 | fcoe->ddp_pool = alloc_percpu(struct i40e_fcoe_ddp_pool); | |
585 | if (!fcoe->ddp_pool) { | |
586 | dev_err(&pf->pdev->dev, "failed to allocate percpu DDP\n"); | |
587 | return -ENOMEM; | |
588 | } | |
589 | ||
590 | /* allocate pci pool for each cpu */ | |
591 | for_each_possible_cpu(cpu) { | |
592 | if (!i40e_fcoe_dma_pool_create(fcoe, dev, cpu)) | |
593 | continue; | |
594 | ||
595 | dev_err(dev, "failed to alloc DDP pool on cpu:%d\n", cpu); | |
596 | i40e_fcoe_free_ddp_resources(vsi); | |
597 | return -ENOMEM; | |
598 | } | |
599 | ||
600 | /* initialize the sw context */ | |
601 | for (i = 0; i < I40E_FCOE_DDP_MAX; i++) | |
602 | i40e_fcoe_ddp_clear(&fcoe->ddp[i]); | |
603 | ||
604 | netdev_info(vsi->netdev, "VSI %d,%d FCoE DDP resources allocated\n", | |
605 | vsi->id, vsi->seid); | |
606 | ||
607 | return 0; | |
608 | } | |
609 | ||
610 | /** | |
611 | * i40e_fcoe_handle_status - check the Programming Status for FCoE | |
612 | * @rx_ring: the Rx ring for this descriptor | |
613 | * @rx_desc: the Rx descriptor for Programming Status, not a packet descriptor. | |
614 | * | |
615 | * Check if this is the Rx Programming Status descriptor write-back for FCoE. | |
616 | * This is used to verify if the context/filter programming or invalidation | |
617 | * requested by SW to the HW is successful or not and take actions accordingly. | |
618 | **/ | |
619 | void i40e_fcoe_handle_status(struct i40e_ring *rx_ring, | |
620 | union i40e_rx_desc *rx_desc, u8 prog_id) | |
621 | { | |
622 | struct i40e_pf *pf = rx_ring->vsi->back; | |
623 | struct i40e_fcoe *fcoe = &pf->fcoe; | |
624 | struct i40e_fcoe_ddp *ddp; | |
625 | u32 error; | |
626 | u16 xid; | |
627 | u64 qw; | |
628 | ||
629 | /* we only care for FCoE here */ | |
630 | if (!i40e_fcoe_progid_is_fcoe(prog_id)) | |
631 | return; | |
632 | ||
633 | xid = le32_to_cpu(rx_desc->wb.qword0.hi_dword.fcoe_param) & | |
634 | (I40E_FCOE_DDP_MAX - 1); | |
635 | ||
636 | if (!i40e_fcoe_xid_is_valid(xid)) | |
637 | return; | |
638 | ||
639 | ddp = &fcoe->ddp[xid]; | |
640 | WARN_ON(xid != ddp->xid); | |
641 | ||
642 | qw = le64_to_cpu(rx_desc->wb.qword1.status_error_len); | |
643 | error = (qw & I40E_RX_PROG_STATUS_DESC_QW1_ERROR_MASK) >> | |
644 | I40E_RX_PROG_STATUS_DESC_QW1_ERROR_SHIFT; | |
645 | ||
646 | /* DDP context programming status: failure or success */ | |
647 | if (prog_id == I40E_RX_PROG_STATUS_DESC_FCOE_CTXT_PROG_STATUS) { | |
648 | if (I40E_RX_PROG_FCOE_ERROR_TBL_FULL(error)) { | |
649 | dev_err(&pf->pdev->dev, "xid %x ddp->xid %x TABLE FULL\n", | |
650 | xid, ddp->xid); | |
651 | ddp->prerr |= I40E_RX_PROG_FCOE_ERROR_TBL_FULL_BIT; | |
652 | } | |
653 | if (I40E_RX_PROG_FCOE_ERROR_CONFLICT(error)) { | |
654 | dev_err(&pf->pdev->dev, "xid %x ddp->xid %x CONFLICT\n", | |
655 | xid, ddp->xid); | |
656 | ddp->prerr |= I40E_RX_PROG_FCOE_ERROR_CONFLICT_BIT; | |
657 | } | |
658 | } | |
659 | ||
660 | /* DDP context invalidation status: failure or success */ | |
661 | if (prog_id == I40E_RX_PROG_STATUS_DESC_FCOE_CTXT_INVL_STATUS) { | |
662 | if (I40E_RX_PROG_FCOE_ERROR_INVLFAIL(error)) { | |
663 | dev_err(&pf->pdev->dev, "xid %x ddp->xid %x INVALIDATION FAILURE\n", | |
664 | xid, ddp->xid); | |
665 | ddp->prerr |= I40E_RX_PROG_FCOE_ERROR_INVLFAIL_BIT; | |
666 | } | |
667 | /* clear the flag so we can retry invalidation */ | |
668 | clear_bit(__I40E_FCOE_DDP_ABORTED, &ddp->flags); | |
669 | } | |
670 | ||
671 | /* unmap DMA */ | |
672 | i40e_fcoe_ddp_unmap(pf, ddp); | |
673 | i40e_fcoe_ddp_clear(ddp); | |
674 | } | |
675 | ||
676 | /** | |
677 | * i40e_fcoe_handle_offload - check ddp status and mark it done | |
678 | * @adapter: i40e adapter | |
679 | * @rx_desc: advanced rx descriptor | |
680 | * @skb: the skb holding the received data | |
681 | * | |
682 | * This checks ddp status. | |
683 | * | |
684 | * Returns : < 0 indicates an error or not a FCOE ddp, 0 indicates | |
685 | * not passing the skb to ULD, > 0 indicates is the length of data | |
686 | * being ddped. | |
687 | * | |
688 | **/ | |
689 | int i40e_fcoe_handle_offload(struct i40e_ring *rx_ring, | |
690 | union i40e_rx_desc *rx_desc, | |
691 | struct sk_buff *skb) | |
692 | { | |
693 | struct i40e_pf *pf = rx_ring->vsi->back; | |
694 | struct i40e_fcoe *fcoe = &pf->fcoe; | |
695 | struct fc_frame_header *fh = NULL; | |
696 | struct i40e_fcoe_ddp *ddp = NULL; | |
697 | u32 status, fltstat; | |
698 | u32 error, fcerr; | |
699 | int rc = -EINVAL; | |
700 | u16 ptype; | |
701 | u16 xid; | |
702 | u64 qw; | |
703 | ||
704 | /* check this rxd is for programming status */ | |
705 | qw = le64_to_cpu(rx_desc->wb.qword1.status_error_len); | |
706 | /* packet descriptor, check packet type */ | |
707 | ptype = (qw & I40E_RXD_QW1_PTYPE_MASK) >> I40E_RXD_QW1_PTYPE_SHIFT; | |
708 | if (!i40e_rx_is_fcoe(ptype)) | |
709 | goto out_no_ddp; | |
710 | ||
711 | error = (qw & I40E_RXD_QW1_ERROR_MASK) >> I40E_RXD_QW1_ERROR_SHIFT; | |
712 | fcerr = (error >> I40E_RX_DESC_ERROR_L3L4E_SHIFT) & | |
713 | I40E_RX_DESC_FCOE_ERROR_MASK; | |
714 | ||
715 | /* check stateless offload error */ | |
716 | if (unlikely(fcerr == I40E_RX_DESC_ERROR_L3L4E_PROT)) { | |
717 | dev_err(&pf->pdev->dev, "Protocol Error\n"); | |
718 | skb->ip_summed = CHECKSUM_NONE; | |
719 | } else { | |
720 | skb->ip_summed = CHECKSUM_UNNECESSARY; | |
721 | } | |
722 | ||
723 | /* check hw status on ddp */ | |
724 | status = (qw & I40E_RXD_QW1_STATUS_MASK) >> I40E_RXD_QW1_STATUS_SHIFT; | |
725 | fltstat = (status >> I40E_RX_DESC_STATUS_FLTSTAT_SHIFT) & | |
726 | I40E_RX_DESC_FLTSTAT_FCMASK; | |
727 | ||
728 | /* now we are ready to check DDP */ | |
729 | fh = i40e_fcoe_fc_frame_header(skb); | |
730 | xid = i40e_fcoe_fc_get_xid(fh); | |
731 | if (!i40e_fcoe_xid_is_valid(xid)) | |
732 | goto out_no_ddp; | |
733 | ||
734 | /* non DDP normal receive, return to the protocol stack */ | |
735 | if (fltstat == I40E_RX_DESC_FLTSTAT_NOMTCH) | |
736 | goto out_no_ddp; | |
737 | ||
738 | /* do we have a sw ddp context setup ? */ | |
739 | ddp = &fcoe->ddp[xid]; | |
740 | if (!ddp->sgl) | |
741 | goto out_no_ddp; | |
742 | ||
743 | /* fetch xid from hw rxd wb, which should match up the sw ctxt */ | |
744 | xid = le16_to_cpu(rx_desc->wb.qword0.lo_dword.mirr_fcoe.fcoe_ctx_id); | |
745 | if (ddp->xid != xid) { | |
746 | dev_err(&pf->pdev->dev, "xid 0x%x does not match ctx_xid 0x%x\n", | |
747 | ddp->xid, xid); | |
748 | goto out_put_ddp; | |
749 | } | |
750 | ||
751 | /* the same exchange has already errored out */ | |
752 | if (ddp->fcerr) { | |
753 | dev_err(&pf->pdev->dev, "xid 0x%x fcerr 0x%x reported fcer 0x%x\n", | |
754 | xid, ddp->fcerr, fcerr); | |
755 | goto out_put_ddp; | |
756 | } | |
757 | ||
758 | /* fcoe param is valid by now with correct DDPed length */ | |
759 | ddp->len = le32_to_cpu(rx_desc->wb.qword0.hi_dword.fcoe_param); | |
760 | ddp->fcerr = fcerr; | |
761 | /* header posting only, useful only for target mode and debugging */ | |
762 | if (fltstat == I40E_RX_DESC_FLTSTAT_DDP) { | |
763 | /* For target mode, we get header of the last packet but it | |
764 | * does not have the FCoE trailer field, i.e., CRC and EOF | |
765 | * Ordered Set since they are offloaded by the HW, so fill | |
766 | * it up correspondingly to allow the packet to pass through | |
767 | * to the upper protocol stack. | |
768 | */ | |
769 | u32 f_ctl = ntoh24(fh->fh_f_ctl); | |
770 | ||
771 | if ((f_ctl & FC_FC_END_SEQ) && | |
772 | (fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA)) { | |
773 | struct fcoe_crc_eof *crc = NULL; | |
774 | ||
775 | crc = (struct fcoe_crc_eof *)skb_put(skb, sizeof(*crc)); | |
776 | crc->fcoe_eof = FC_EOF_T; | |
777 | } else { | |
778 | /* otherwise, drop the header only frame */ | |
779 | rc = 0; | |
780 | goto out_no_ddp; | |
781 | } | |
782 | } | |
783 | ||
784 | out_put_ddp: | |
785 | /* either we got RSP or we have an error, unmap DMA in both cases */ | |
786 | i40e_fcoe_ddp_unmap(pf, ddp); | |
787 | if (ddp->len && !ddp->fcerr) { | |
788 | int pkts; | |
789 | ||
790 | rc = ddp->len; | |
791 | i40e_fcoe_ddp_clear(ddp); | |
792 | ddp->len = rc; | |
793 | pkts = DIV_ROUND_UP(rc, 2048); | |
794 | rx_ring->stats.bytes += rc; | |
795 | rx_ring->stats.packets += pkts; | |
796 | rx_ring->q_vector->rx.total_bytes += rc; | |
797 | rx_ring->q_vector->rx.total_packets += pkts; | |
798 | set_bit(__I40E_FCOE_DDP_DONE, &ddp->flags); | |
799 | } | |
800 | ||
801 | out_no_ddp: | |
802 | return rc; | |
803 | } | |
804 | ||
805 | /** | |
806 | * i40e_fcoe_ddp_setup - called to set up ddp context | |
807 | * @netdev: the corresponding net_device | |
808 | * @xid: the exchange id requesting ddp | |
809 | * @sgl: the scatter-gather list for this request | |
810 | * @sgc: the number of scatter-gather items | |
811 | * @target_mode: indicates this is a DDP request for target | |
812 | * | |
813 | * Returns : 1 for success and 0 for no DDP on this I/O | |
814 | **/ | |
815 | static int i40e_fcoe_ddp_setup(struct net_device *netdev, u16 xid, | |
816 | struct scatterlist *sgl, unsigned int sgc, | |
817 | int target_mode) | |
818 | { | |
819 | static const unsigned int bufflen = I40E_FCOE_DDP_BUF_MIN; | |
820 | struct i40e_netdev_priv *np = netdev_priv(netdev); | |
821 | struct i40e_fcoe_ddp_pool *ddp_pool; | |
822 | struct i40e_pf *pf = np->vsi->back; | |
823 | struct i40e_fcoe *fcoe = &pf->fcoe; | |
824 | unsigned int i, j, dmacount; | |
825 | struct i40e_fcoe_ddp *ddp; | |
826 | unsigned int firstoff = 0; | |
827 | unsigned int thisoff = 0; | |
828 | unsigned int thislen = 0; | |
829 | struct scatterlist *sg; | |
830 | dma_addr_t addr = 0; | |
831 | unsigned int len; | |
832 | ||
833 | if (xid >= I40E_FCOE_DDP_MAX) { | |
834 | dev_warn(&pf->pdev->dev, "xid=0x%x out-of-range\n", xid); | |
835 | return 0; | |
836 | } | |
837 | ||
838 | /* no DDP if we are already down or resetting */ | |
839 | if (test_bit(__I40E_DOWN, &pf->state) || | |
840 | test_bit(__I40E_NEEDS_RESTART, &pf->state)) { | |
841 | dev_info(&pf->pdev->dev, "xid=0x%x device in reset/down\n", | |
842 | xid); | |
843 | return 0; | |
844 | } | |
845 | ||
846 | ddp = &fcoe->ddp[xid]; | |
847 | if (ddp->sgl) { | |
848 | dev_info(&pf->pdev->dev, "xid 0x%x w/ non-null sgl=%p nents=%d\n", | |
849 | xid, ddp->sgl, ddp->sgc); | |
850 | return 0; | |
851 | } | |
852 | i40e_fcoe_ddp_clear(ddp); | |
853 | ||
854 | if (!fcoe->ddp_pool) { | |
855 | dev_info(&pf->pdev->dev, "No DDP pool, xid 0x%x\n", xid); | |
856 | return 0; | |
857 | } | |
858 | ||
859 | ddp_pool = per_cpu_ptr(fcoe->ddp_pool, get_cpu()); | |
860 | if (!ddp_pool->pool) { | |
861 | dev_info(&pf->pdev->dev, "No percpu ddp pool, xid 0x%x\n", xid); | |
862 | goto out_noddp; | |
863 | } | |
864 | ||
865 | /* setup dma from scsi command sgl */ | |
866 | dmacount = dma_map_sg(&pf->pdev->dev, sgl, sgc, DMA_FROM_DEVICE); | |
867 | if (dmacount == 0) { | |
868 | dev_info(&pf->pdev->dev, "dma_map_sg for sgl %p, sgc %d failed\n", | |
869 | sgl, sgc); | |
870 | goto out_noddp_unmap; | |
871 | } | |
872 | ||
873 | /* alloc the udl from our ddp pool */ | |
874 | ddp->udl = dma_pool_alloc(ddp_pool->pool, GFP_ATOMIC, &ddp->udp); | |
875 | if (!ddp->udl) { | |
876 | dev_info(&pf->pdev->dev, | |
877 | "Failed allocated ddp context, xid 0x%x\n", xid); | |
878 | goto out_noddp_unmap; | |
879 | } | |
880 | ||
881 | j = 0; | |
882 | ddp->len = 0; | |
883 | for_each_sg(sgl, sg, dmacount, i) { | |
884 | addr = sg_dma_address(sg); | |
885 | len = sg_dma_len(sg); | |
886 | ddp->len += len; | |
887 | while (len) { | |
888 | /* max number of buffers allowed in one DDP context */ | |
889 | if (j >= I40E_FCOE_DDP_BUFFCNT_MAX) { | |
890 | dev_info(&pf->pdev->dev, | |
891 | "xid=%x:%d,%d,%d:addr=%llx not enough descriptors\n", | |
892 | xid, i, j, dmacount, (u64)addr); | |
893 | goto out_noddp_free; | |
894 | } | |
895 | ||
896 | /* get the offset of length of current buffer */ | |
897 | thisoff = addr & ((dma_addr_t)bufflen - 1); | |
898 | thislen = min_t(unsigned int, (bufflen - thisoff), len); | |
899 | /* all but the 1st buffer (j == 0) | |
900 | * must be aligned on bufflen | |
901 | */ | |
902 | if ((j != 0) && (thisoff)) | |
903 | goto out_noddp_free; | |
904 | ||
905 | /* all but the last buffer | |
906 | * ((i == (dmacount - 1)) && (thislen == len)) | |
907 | * must end at bufflen | |
908 | */ | |
909 | if (((i != (dmacount - 1)) || (thislen != len)) && | |
910 | ((thislen + thisoff) != bufflen)) | |
911 | goto out_noddp_free; | |
912 | ||
913 | ddp->udl[j] = (u64)(addr - thisoff); | |
914 | /* only the first buffer may have none-zero offset */ | |
915 | if (j == 0) | |
916 | firstoff = thisoff; | |
917 | len -= thislen; | |
918 | addr += thislen; | |
919 | j++; | |
920 | } | |
921 | } | |
922 | /* only the last buffer may have non-full bufflen */ | |
923 | ddp->lastsize = thisoff + thislen; | |
924 | ddp->firstoff = firstoff; | |
925 | ddp->list_len = j; | |
926 | ddp->pool = ddp_pool->pool; | |
927 | ddp->sgl = sgl; | |
928 | ddp->sgc = sgc; | |
929 | ddp->xid = xid; | |
930 | if (target_mode) | |
931 | set_bit(__I40E_FCOE_DDP_TARGET, &ddp->flags); | |
932 | set_bit(__I40E_FCOE_DDP_INITALIZED, &ddp->flags); | |
933 | ||
934 | put_cpu(); | |
935 | return 1; /* Success */ | |
936 | ||
937 | out_noddp_free: | |
938 | dma_pool_free(ddp->pool, ddp->udl, ddp->udp); | |
939 | i40e_fcoe_ddp_clear(ddp); | |
940 | ||
941 | out_noddp_unmap: | |
942 | dma_unmap_sg(&pf->pdev->dev, sgl, sgc, DMA_FROM_DEVICE); | |
943 | out_noddp: | |
944 | put_cpu(); | |
945 | return 0; | |
946 | } | |
947 | ||
948 | /** | |
949 | * i40e_fcoe_ddp_get - called to set up ddp context in initiator mode | |
950 | * @netdev: the corresponding net_device | |
951 | * @xid: the exchange id requesting ddp | |
952 | * @sgl: the scatter-gather list for this request | |
953 | * @sgc: the number of scatter-gather items | |
954 | * | |
955 | * This is the implementation of net_device_ops.ndo_fcoe_ddp_setup | |
956 | * and is expected to be called from ULD, e.g., FCP layer of libfc | |
957 | * to set up ddp for the corresponding xid of the given sglist for | |
958 | * the corresponding I/O. | |
959 | * | |
960 | * Returns : 1 for success and 0 for no ddp | |
961 | **/ | |
962 | static int i40e_fcoe_ddp_get(struct net_device *netdev, u16 xid, | |
963 | struct scatterlist *sgl, unsigned int sgc) | |
964 | { | |
965 | return i40e_fcoe_ddp_setup(netdev, xid, sgl, sgc, 0); | |
966 | } | |
967 | ||
968 | /** | |
969 | * i40e_fcoe_ddp_target - called to set up ddp context in target mode | |
970 | * @netdev: the corresponding net_device | |
971 | * @xid: the exchange id requesting ddp | |
972 | * @sgl: the scatter-gather list for this request | |
973 | * @sgc: the number of scatter-gather items | |
974 | * | |
975 | * This is the implementation of net_device_ops.ndo_fcoe_ddp_target | |
976 | * and is expected to be called from ULD, e.g., FCP layer of libfc | |
977 | * to set up ddp for the corresponding xid of the given sglist for | |
978 | * the corresponding I/O. The DDP in target mode is a write I/O request | |
979 | * from the initiator. | |
980 | * | |
981 | * Returns : 1 for success and 0 for no ddp | |
982 | **/ | |
983 | static int i40e_fcoe_ddp_target(struct net_device *netdev, u16 xid, | |
984 | struct scatterlist *sgl, unsigned int sgc) | |
985 | { | |
986 | return i40e_fcoe_ddp_setup(netdev, xid, sgl, sgc, 1); | |
987 | } | |
988 | ||
989 | /** | |
990 | * i40e_fcoe_program_ddp - programs the HW DDP related descriptors | |
991 | * @tx_ring: transmit ring for this packet | |
992 | * @skb: the packet to be sent out | |
993 | * @sof: the SOF to indicate class of service | |
994 | * | |
995 | * Determine if it is READ/WRITE command, and finds out if there is | |
996 | * a matching SW DDP context for this command. DDP is applicable | |
997 | * only in case of READ if initiator or WRITE in case of | |
998 | * responder (via checking XFER_RDY). | |
999 | * | |
1000 | * Note: caller checks sof and ddp sw context | |
1001 | * | |
1002 | * Returns : none | |
1003 | * | |
1004 | **/ | |
1005 | static void i40e_fcoe_program_ddp(struct i40e_ring *tx_ring, | |
1006 | struct sk_buff *skb, | |
1007 | struct i40e_fcoe_ddp *ddp, u8 sof) | |
1008 | { | |
1009 | struct i40e_fcoe_filter_context_desc *filter_desc = NULL; | |
1010 | struct i40e_fcoe_queue_context_desc *queue_desc = NULL; | |
1011 | struct i40e_fcoe_ddp_context_desc *ddp_desc = NULL; | |
1012 | struct i40e_pf *pf = tx_ring->vsi->back; | |
1013 | u16 i = tx_ring->next_to_use; | |
1014 | struct fc_frame_header *fh; | |
1015 | u64 flags_rsvd_lanq = 0; | |
1016 | bool target_mode; | |
1017 | ||
1018 | /* check if abort is still pending */ | |
1019 | if (test_bit(__I40E_FCOE_DDP_ABORTED, &ddp->flags)) { | |
1020 | dev_warn(&pf->pdev->dev, | |
1021 | "DDP abort is still pending xid:%hx and ddp->flags:%lx:\n", | |
1022 | ddp->xid, ddp->flags); | |
1023 | return; | |
1024 | } | |
1025 | ||
1026 | /* set the flag to indicate this is programmed */ | |
1027 | if (test_and_set_bit(__I40E_FCOE_DDP_PROGRAMMED, &ddp->flags)) { | |
1028 | dev_warn(&pf->pdev->dev, | |
1029 | "DDP is already programmed for xid:%hx and ddp->flags:%lx:\n", | |
1030 | ddp->xid, ddp->flags); | |
1031 | return; | |
1032 | } | |
1033 | ||
1034 | /* Prepare the DDP context descriptor */ | |
1035 | ddp_desc = I40E_DDP_CONTEXT_DESC(tx_ring, i); | |
1036 | i++; | |
1037 | if (i == tx_ring->count) | |
1038 | i = 0; | |
1039 | ||
1040 | ddp_desc->type_cmd_foff_lsize = | |
1041 | cpu_to_le64(I40E_TX_DESC_DTYPE_DDP_CTX | | |
1042 | ((u64)I40E_FCOE_DDP_CTX_DESC_BSIZE_4K << | |
1043 | I40E_FCOE_DDP_CTX_QW1_CMD_SHIFT) | | |
1044 | ((u64)ddp->firstoff << | |
1045 | I40E_FCOE_DDP_CTX_QW1_FOFF_SHIFT) | | |
1046 | ((u64)ddp->lastsize << | |
1047 | I40E_FCOE_DDP_CTX_QW1_LSIZE_SHIFT)); | |
1048 | ddp_desc->rsvd = cpu_to_le64(0); | |
1049 | ||
1050 | /* target mode needs last packet in the sequence */ | |
1051 | target_mode = test_bit(__I40E_FCOE_DDP_TARGET, &ddp->flags); | |
1052 | if (target_mode) | |
1053 | ddp_desc->type_cmd_foff_lsize |= | |
1054 | cpu_to_le64(I40E_FCOE_DDP_CTX_DESC_LASTSEQH); | |
1055 | ||
1056 | /* Prepare queue_context descriptor */ | |
1057 | queue_desc = I40E_QUEUE_CONTEXT_DESC(tx_ring, i++); | |
1058 | if (i == tx_ring->count) | |
1059 | i = 0; | |
1060 | queue_desc->dmaindx_fbase = cpu_to_le64(ddp->xid | ((u64)ddp->udp)); | |
1061 | queue_desc->flen_tph = cpu_to_le64(ddp->list_len | | |
1062 | ((u64)(I40E_FCOE_QUEUE_CTX_DESC_TPHRDESC | | |
1063 | I40E_FCOE_QUEUE_CTX_DESC_TPHDATA) << | |
1064 | I40E_FCOE_QUEUE_CTX_QW1_TPH_SHIFT)); | |
1065 | ||
1066 | /* Prepare filter_context_desc */ | |
1067 | filter_desc = I40E_FILTER_CONTEXT_DESC(tx_ring, i); | |
1068 | i++; | |
1069 | if (i == tx_ring->count) | |
1070 | i = 0; | |
1071 | ||
1072 | fh = (struct fc_frame_header *)skb_transport_header(skb); | |
1073 | filter_desc->param = cpu_to_le32(ntohl(fh->fh_parm_offset)); | |
1074 | filter_desc->seqn = cpu_to_le16(ntohs(fh->fh_seq_cnt)); | |
1075 | filter_desc->rsvd_dmaindx = cpu_to_le16(ddp->xid << | |
1076 | I40E_FCOE_FILTER_CTX_QW0_DMAINDX_SHIFT); | |
1077 | ||
1078 | flags_rsvd_lanq = I40E_FCOE_FILTER_CTX_DESC_CTYP_DDP; | |
1079 | flags_rsvd_lanq |= (u64)(target_mode ? | |
1080 | I40E_FCOE_FILTER_CTX_DESC_ENODE_RSP : | |
1081 | I40E_FCOE_FILTER_CTX_DESC_ENODE_INIT); | |
1082 | ||
1083 | flags_rsvd_lanq |= (u64)((sof == FC_SOF_I2 || sof == FC_SOF_N2) ? | |
1084 | I40E_FCOE_FILTER_CTX_DESC_FC_CLASS2 : | |
1085 | I40E_FCOE_FILTER_CTX_DESC_FC_CLASS3); | |
1086 | ||
1087 | flags_rsvd_lanq |= ((u64)skb->queue_mapping << | |
1088 | I40E_FCOE_FILTER_CTX_QW1_LANQINDX_SHIFT); | |
1089 | filter_desc->flags_rsvd_lanq = cpu_to_le64(flags_rsvd_lanq); | |
1090 | ||
1091 | /* By this time, all offload related descriptors has been programmed */ | |
1092 | tx_ring->next_to_use = i; | |
1093 | } | |
1094 | ||
1095 | /** | |
1096 | * i40e_fcoe_invalidate_ddp - invalidates DDP in case of abort | |
1097 | * @tx_ring: transmit ring for this packet | |
1098 | * @skb: the packet associated w/ this DDP invalidation, i.e., ABTS | |
1099 | * @ddp: the SW DDP context for this DDP | |
1100 | * | |
1101 | * Programs the Tx context descriptor to do DDP invalidation. | |
1102 | **/ | |
1103 | static void i40e_fcoe_invalidate_ddp(struct i40e_ring *tx_ring, | |
1104 | struct sk_buff *skb, | |
1105 | struct i40e_fcoe_ddp *ddp) | |
1106 | { | |
1107 | struct i40e_tx_context_desc *context_desc; | |
1108 | int i; | |
1109 | ||
1110 | if (test_and_set_bit(__I40E_FCOE_DDP_ABORTED, &ddp->flags)) | |
1111 | return; | |
1112 | ||
1113 | i = tx_ring->next_to_use; | |
1114 | context_desc = I40E_TX_CTXTDESC(tx_ring, i); | |
1115 | i++; | |
1116 | if (i == tx_ring->count) | |
1117 | i = 0; | |
1118 | ||
1119 | context_desc->tunneling_params = cpu_to_le32(0); | |
1120 | context_desc->l2tag2 = cpu_to_le16(0); | |
1121 | context_desc->rsvd = cpu_to_le16(0); | |
1122 | context_desc->type_cmd_tso_mss = cpu_to_le64( | |
1123 | I40E_TX_DESC_DTYPE_FCOE_CTX | | |
1124 | (I40E_FCOE_TX_CTX_DESC_OPCODE_DDP_CTX_INVL << | |
1125 | I40E_TXD_CTX_QW1_CMD_SHIFT) | | |
1126 | (I40E_FCOE_TX_CTX_DESC_OPCODE_SINGLE_SEND << | |
1127 | I40E_TXD_CTX_QW1_CMD_SHIFT)); | |
1128 | tx_ring->next_to_use = i; | |
1129 | } | |
1130 | ||
1131 | /** | |
1132 | * i40e_fcoe_handle_ddp - check we should setup or invalidate DDP | |
1133 | * @tx_ring: transmit ring for this packet | |
1134 | * @skb: the packet to be sent out | |
1135 | * @sof: the SOF to indicate class of service | |
1136 | * | |
1137 | * Determine if it is ABTS/READ/XFER_RDY, and finds out if there is | |
1138 | * a matching SW DDP context for this command. DDP is applicable | |
1139 | * only in case of READ if initiator or WRITE in case of | |
1140 | * responder (via checking XFER_RDY). In case this is an ABTS, send | |
1141 | * just invalidate the context. | |
1142 | **/ | |
1143 | static void i40e_fcoe_handle_ddp(struct i40e_ring *tx_ring, | |
1144 | struct sk_buff *skb, u8 sof) | |
1145 | { | |
1146 | struct i40e_pf *pf = tx_ring->vsi->back; | |
1147 | struct i40e_fcoe *fcoe = &pf->fcoe; | |
1148 | struct fc_frame_header *fh; | |
1149 | struct i40e_fcoe_ddp *ddp; | |
1150 | u32 f_ctl; | |
1151 | u8 r_ctl; | |
1152 | u16 xid; | |
1153 | ||
1154 | fh = (struct fc_frame_header *)skb_transport_header(skb); | |
1155 | f_ctl = ntoh24(fh->fh_f_ctl); | |
1156 | r_ctl = fh->fh_r_ctl; | |
1157 | ddp = NULL; | |
1158 | ||
1159 | if ((r_ctl == FC_RCTL_DD_DATA_DESC) && (f_ctl & FC_FC_EX_CTX)) { | |
1160 | /* exchange responder? if so, XFER_RDY for write */ | |
1161 | xid = ntohs(fh->fh_rx_id); | |
1162 | if (i40e_fcoe_xid_is_valid(xid)) { | |
1163 | ddp = &fcoe->ddp[xid]; | |
1164 | if ((ddp->xid == xid) && | |
1165 | (test_bit(__I40E_FCOE_DDP_TARGET, &ddp->flags))) | |
1166 | i40e_fcoe_program_ddp(tx_ring, skb, ddp, sof); | |
1167 | } | |
1168 | } else if (r_ctl == FC_RCTL_DD_UNSOL_CMD) { | |
1169 | /* exchange originator, check READ cmd */ | |
1170 | xid = ntohs(fh->fh_ox_id); | |
1171 | if (i40e_fcoe_xid_is_valid(xid)) { | |
1172 | ddp = &fcoe->ddp[xid]; | |
1173 | if ((ddp->xid == xid) && | |
1174 | (!test_bit(__I40E_FCOE_DDP_TARGET, &ddp->flags))) | |
1175 | i40e_fcoe_program_ddp(tx_ring, skb, ddp, sof); | |
1176 | } | |
1177 | } else if (r_ctl == FC_RCTL_BA_ABTS) { | |
1178 | /* exchange originator, check ABTS */ | |
1179 | xid = ntohs(fh->fh_ox_id); | |
1180 | if (i40e_fcoe_xid_is_valid(xid)) { | |
1181 | ddp = &fcoe->ddp[xid]; | |
1182 | if ((ddp->xid == xid) && | |
1183 | (!test_bit(__I40E_FCOE_DDP_TARGET, &ddp->flags))) | |
1184 | i40e_fcoe_invalidate_ddp(tx_ring, skb, ddp); | |
1185 | } | |
1186 | } | |
1187 | } | |
1188 | ||
1189 | /** | |
1190 | * i40e_fcoe_tso - set up FCoE TSO | |
1191 | * @tx_ring: ring to send buffer on | |
1192 | * @skb: send buffer | |
1193 | * @tx_flags: collected send information | |
1194 | * @hdr_len: the tso header length | |
1195 | * @sof: the SOF to indicate class of service | |
1196 | * | |
1197 | * Note must already have sof checked to be either class 2 or class 3 before | |
1198 | * calling this function. | |
1199 | * | |
1200 | * Returns 1 to indicate sequence segmentation offload is properly setup | |
1201 | * or returns 0 to indicate no tso is needed, otherwise returns error | |
1202 | * code to drop the frame. | |
1203 | **/ | |
1204 | static int i40e_fcoe_tso(struct i40e_ring *tx_ring, | |
1205 | struct sk_buff *skb, | |
1206 | u32 tx_flags, u8 *hdr_len, u8 sof) | |
1207 | { | |
1208 | struct i40e_tx_context_desc *context_desc; | |
1209 | u32 cd_type, cd_cmd, cd_tso_len, cd_mss; | |
1210 | struct fc_frame_header *fh; | |
1211 | u64 cd_type_cmd_tso_mss; | |
1212 | ||
1213 | /* must match gso type as FCoE */ | |
1214 | if (!skb_is_gso(skb)) | |
1215 | return 0; | |
1216 | ||
1217 | /* is it the expected gso type for FCoE ?*/ | |
1218 | if (skb_shinfo(skb)->gso_type != SKB_GSO_FCOE) { | |
1219 | netdev_err(skb->dev, | |
1220 | "wrong gso type %d:expecting SKB_GSO_FCOE\n", | |
1221 | skb_shinfo(skb)->gso_type); | |
1222 | return -EINVAL; | |
1223 | } | |
1224 | ||
1225 | /* header and trailer are inserted by hw */ | |
1226 | *hdr_len = skb_transport_offset(skb) + sizeof(struct fc_frame_header) + | |
1227 | sizeof(struct fcoe_crc_eof); | |
1228 | ||
1229 | /* check sof to decide a class 2 or 3 TSO */ | |
1230 | if (likely(i40e_fcoe_sof_is_class3(sof))) | |
1231 | cd_cmd = I40E_FCOE_TX_CTX_DESC_OPCODE_TSO_FC_CLASS3; | |
1232 | else | |
1233 | cd_cmd = I40E_FCOE_TX_CTX_DESC_OPCODE_TSO_FC_CLASS2; | |
1234 | ||
1235 | /* param field valid? */ | |
1236 | fh = (struct fc_frame_header *)skb_transport_header(skb); | |
1237 | if (fh->fh_f_ctl[2] & FC_FC_REL_OFF) | |
1238 | cd_cmd |= I40E_FCOE_TX_CTX_DESC_RELOFF; | |
1239 | ||
1240 | /* fill the field values */ | |
1241 | cd_type = I40E_TX_DESC_DTYPE_FCOE_CTX; | |
1242 | cd_tso_len = skb->len - *hdr_len; | |
1243 | cd_mss = skb_shinfo(skb)->gso_size; | |
1244 | cd_type_cmd_tso_mss = | |
1245 | ((u64)cd_type << I40E_TXD_CTX_QW1_DTYPE_SHIFT) | | |
1246 | ((u64)cd_cmd << I40E_TXD_CTX_QW1_CMD_SHIFT) | | |
1247 | ((u64)cd_tso_len << I40E_TXD_CTX_QW1_TSO_LEN_SHIFT) | | |
1248 | ((u64)cd_mss << I40E_TXD_CTX_QW1_MSS_SHIFT); | |
1249 | ||
1250 | /* grab the next descriptor */ | |
1251 | context_desc = I40E_TX_CTXTDESC(tx_ring, tx_ring->next_to_use); | |
1252 | tx_ring->next_to_use++; | |
1253 | if (tx_ring->next_to_use == tx_ring->count) | |
1254 | tx_ring->next_to_use = 0; | |
1255 | ||
1256 | context_desc->tunneling_params = 0; | |
1257 | context_desc->l2tag2 = cpu_to_le16((tx_flags & I40E_TX_FLAGS_VLAN_MASK) | |
1258 | >> I40E_TX_FLAGS_VLAN_SHIFT); | |
1259 | context_desc->type_cmd_tso_mss = cpu_to_le64(cd_type_cmd_tso_mss); | |
1260 | ||
1261 | return 1; | |
1262 | } | |
1263 | ||
1264 | /** | |
1265 | * i40e_fcoe_tx_map - build the tx descriptor | |
1266 | * @tx_ring: ring to send buffer on | |
1267 | * @skb: send buffer | |
1268 | * @first: first buffer info buffer to use | |
1269 | * @tx_flags: collected send information | |
1270 | * @hdr_len: ptr to the size of the packet header | |
1271 | * @eof: the frame eof value | |
1272 | * | |
1273 | * Note, for FCoE, sof and eof are already checked | |
1274 | **/ | |
1275 | static void i40e_fcoe_tx_map(struct i40e_ring *tx_ring, | |
1276 | struct sk_buff *skb, | |
1277 | struct i40e_tx_buffer *first, | |
1278 | u32 tx_flags, u8 hdr_len, u8 eof) | |
1279 | { | |
1280 | u32 td_offset = 0; | |
1281 | u32 td_cmd = 0; | |
1282 | u32 maclen; | |
1283 | ||
1284 | /* insert CRC */ | |
1285 | td_cmd = I40E_TX_DESC_CMD_ICRC; | |
1286 | ||
1287 | /* setup MACLEN */ | |
1288 | maclen = skb_network_offset(skb); | |
1289 | if (tx_flags & I40E_TX_FLAGS_SW_VLAN) | |
1290 | maclen += sizeof(struct vlan_hdr); | |
1291 | ||
1292 | if (skb->protocol == htons(ETH_P_FCOE)) { | |
1293 | /* for FCoE, maclen should exclude ether type */ | |
1294 | maclen -= 2; | |
1295 | /* setup type as FCoE and EOF insertion */ | |
1296 | td_cmd |= (I40E_TX_DESC_CMD_FCOET | i40e_fcoe_ctxt_eof(eof)); | |
1297 | /* setup FCoELEN and FCLEN */ | |
1298 | td_offset |= ((((sizeof(struct fcoe_hdr) + 2) >> 2) << | |
1299 | I40E_TX_DESC_LENGTH_IPLEN_SHIFT) | | |
1300 | ((sizeof(struct fc_frame_header) >> 2) << | |
1301 | I40E_TX_DESC_LENGTH_L4_FC_LEN_SHIFT)); | |
1302 | /* trim to exclude trailer */ | |
1303 | pskb_trim(skb, skb->len - sizeof(struct fcoe_crc_eof)); | |
1304 | } | |
1305 | ||
1306 | /* MACLEN is ether header length in words not bytes */ | |
1307 | td_offset |= (maclen >> 1) << I40E_TX_DESC_LENGTH_MACLEN_SHIFT; | |
1308 | ||
b38da401 | 1309 | i40e_tx_map(tx_ring, skb, first, tx_flags, hdr_len, td_cmd, td_offset); |
a1a69369 VD |
1310 | } |
1311 | ||
1312 | /** | |
1313 | * i40e_fcoe_set_skb_header - adjust skb header point for FIP/FCoE/FC | |
1314 | * @skb: the skb to be adjusted | |
1315 | * | |
1316 | * Returns true if this skb is a FCoE/FIP or VLAN carried FCoE/FIP and then | |
1317 | * adjusts the skb header pointers correspondingly. Otherwise, returns false. | |
1318 | **/ | |
1319 | static inline int i40e_fcoe_set_skb_header(struct sk_buff *skb) | |
1320 | { | |
1321 | __be16 protocol = skb->protocol; | |
1322 | ||
1323 | skb_reset_mac_header(skb); | |
1324 | skb->mac_len = sizeof(struct ethhdr); | |
1325 | if (protocol == htons(ETH_P_8021Q)) { | |
1326 | struct vlan_ethhdr *veth = (struct vlan_ethhdr *)eth_hdr(skb); | |
1327 | ||
1328 | protocol = veth->h_vlan_encapsulated_proto; | |
1329 | skb->mac_len += sizeof(struct vlan_hdr); | |
1330 | } | |
1331 | ||
1332 | /* FCoE or FIP only */ | |
1333 | if ((protocol != htons(ETH_P_FIP)) && | |
1334 | (protocol != htons(ETH_P_FCOE))) | |
1335 | return -EINVAL; | |
1336 | ||
1337 | /* set header to L2 of FCoE/FIP */ | |
1338 | skb_set_network_header(skb, skb->mac_len); | |
1339 | if (protocol == htons(ETH_P_FIP)) | |
1340 | return 0; | |
1341 | ||
1342 | /* set header to L3 of FC */ | |
1343 | skb_set_transport_header(skb, skb->mac_len + sizeof(struct fcoe_hdr)); | |
1344 | return 0; | |
1345 | } | |
1346 | ||
1347 | /** | |
1348 | * i40e_fcoe_xmit_frame - transmit buffer | |
1349 | * @skb: send buffer | |
1350 | * @netdev: the fcoe netdev | |
1351 | * | |
1352 | * Returns 0 if sent, else an error code | |
1353 | **/ | |
1354 | static netdev_tx_t i40e_fcoe_xmit_frame(struct sk_buff *skb, | |
1355 | struct net_device *netdev) | |
1356 | { | |
1357 | struct i40e_netdev_priv *np = netdev_priv(skb->dev); | |
1358 | struct i40e_vsi *vsi = np->vsi; | |
1359 | struct i40e_ring *tx_ring = vsi->tx_rings[skb->queue_mapping]; | |
1360 | struct i40e_tx_buffer *first; | |
a1a69369 VD |
1361 | u32 tx_flags = 0; |
1362 | u8 hdr_len = 0; | |
1363 | u8 sof = 0; | |
1364 | u8 eof = 0; | |
1365 | int fso; | |
1366 | ||
1367 | if (i40e_fcoe_set_skb_header(skb)) | |
1368 | goto out_drop; | |
1369 | ||
1370 | if (!i40e_xmit_descriptor_count(skb, tx_ring)) | |
1371 | return NETDEV_TX_BUSY; | |
1372 | ||
1373 | /* prepare the xmit flags */ | |
1374 | if (i40e_tx_prepare_vlan_flags(skb, tx_ring, &tx_flags)) | |
1375 | goto out_drop; | |
1376 | ||
1377 | /* record the location of the first descriptor for this packet */ | |
1378 | first = &tx_ring->tx_bi[tx_ring->next_to_use]; | |
1379 | ||
a1a69369 | 1380 | /* FIP is a regular L2 traffic w/o offload */ |
38e00438 | 1381 | if (skb->protocol == htons(ETH_P_FIP)) |
a1a69369 VD |
1382 | goto out_send; |
1383 | ||
1384 | /* check sof and eof, only supports FC Class 2 or 3 */ | |
1385 | if (i40e_fcoe_fc_sof(skb, &sof) || i40e_fcoe_fc_eof(skb, &eof)) { | |
1386 | netdev_err(netdev, "SOF/EOF error:%02x - %02x\n", sof, eof); | |
1387 | goto out_drop; | |
1388 | } | |
1389 | ||
1390 | /* always do FCCRC for FCoE */ | |
1391 | tx_flags |= I40E_TX_FLAGS_FCCRC; | |
1392 | ||
1393 | /* check we should do sequence offload */ | |
1394 | fso = i40e_fcoe_tso(tx_ring, skb, tx_flags, &hdr_len, sof); | |
1395 | if (fso < 0) | |
1396 | goto out_drop; | |
1397 | else if (fso) | |
1398 | tx_flags |= I40E_TX_FLAGS_FSO; | |
1399 | else | |
1400 | i40e_fcoe_handle_ddp(tx_ring, skb, sof); | |
1401 | ||
1402 | out_send: | |
1403 | /* send out the packet */ | |
1404 | i40e_fcoe_tx_map(tx_ring, skb, first, tx_flags, hdr_len, eof); | |
1405 | ||
1406 | i40e_maybe_stop_tx(tx_ring, DESC_NEEDED); | |
1407 | return NETDEV_TX_OK; | |
1408 | ||
1409 | out_drop: | |
1410 | dev_kfree_skb_any(skb); | |
1411 | return NETDEV_TX_OK; | |
1412 | } | |
1413 | ||
1414 | /** | |
1415 | * i40e_fcoe_change_mtu - NDO callback to change the Maximum Transfer Unit | |
1416 | * @netdev: network interface device structure | |
1417 | * @new_mtu: new value for maximum frame size | |
1418 | * | |
1419 | * Returns error as operation not permitted | |
1420 | * | |
1421 | **/ | |
1422 | static int i40e_fcoe_change_mtu(struct net_device *netdev, int new_mtu) | |
1423 | { | |
1424 | netdev_warn(netdev, "MTU change is not supported on FCoE interfaces\n"); | |
1425 | return -EPERM; | |
1426 | } | |
1427 | ||
1428 | /** | |
1429 | * i40e_fcoe_set_features - set the netdev feature flags | |
1430 | * @netdev: ptr to the netdev being adjusted | |
1431 | * @features: the feature set that the stack is suggesting | |
1432 | * | |
1433 | **/ | |
1434 | static int i40e_fcoe_set_features(struct net_device *netdev, | |
1435 | netdev_features_t features) | |
1436 | { | |
1437 | struct i40e_netdev_priv *np = netdev_priv(netdev); | |
1438 | struct i40e_vsi *vsi = np->vsi; | |
1439 | ||
1440 | if (features & NETIF_F_HW_VLAN_CTAG_RX) | |
1441 | i40e_vlan_stripping_enable(vsi); | |
1442 | else | |
1443 | i40e_vlan_stripping_disable(vsi); | |
1444 | ||
1445 | return 0; | |
1446 | } | |
1447 | ||
a1a69369 VD |
1448 | static const struct net_device_ops i40e_fcoe_netdev_ops = { |
1449 | .ndo_open = i40e_open, | |
1450 | .ndo_stop = i40e_close, | |
1451 | .ndo_get_stats64 = i40e_get_netdev_stats_struct, | |
1452 | .ndo_set_rx_mode = i40e_set_rx_mode, | |
1453 | .ndo_validate_addr = eth_validate_addr, | |
1454 | .ndo_set_mac_address = i40e_set_mac, | |
1455 | .ndo_change_mtu = i40e_fcoe_change_mtu, | |
1456 | .ndo_do_ioctl = i40e_ioctl, | |
1457 | .ndo_tx_timeout = i40e_tx_timeout, | |
1458 | .ndo_vlan_rx_add_vid = i40e_vlan_rx_add_vid, | |
1459 | .ndo_vlan_rx_kill_vid = i40e_vlan_rx_kill_vid, | |
1460 | .ndo_setup_tc = i40e_setup_tc, | |
1461 | ||
1462 | #ifdef CONFIG_NET_POLL_CONTROLLER | |
1463 | .ndo_poll_controller = i40e_netpoll, | |
1464 | #endif | |
1465 | .ndo_start_xmit = i40e_fcoe_xmit_frame, | |
1466 | .ndo_fcoe_enable = i40e_fcoe_enable, | |
1467 | .ndo_fcoe_disable = i40e_fcoe_disable, | |
1468 | .ndo_fcoe_ddp_setup = i40e_fcoe_ddp_get, | |
1469 | .ndo_fcoe_ddp_done = i40e_fcoe_ddp_put, | |
1470 | .ndo_fcoe_ddp_target = i40e_fcoe_ddp_target, | |
1471 | .ndo_set_features = i40e_fcoe_set_features, | |
1472 | }; | |
1473 | ||
ccafbce4 VD |
1474 | /* fcoe network device type */ |
1475 | static struct device_type fcoe_netdev_type = { | |
1476 | .name = "fcoe", | |
1477 | }; | |
1478 | ||
a1a69369 VD |
1479 | /** |
1480 | * i40e_fcoe_config_netdev - prepares the VSI context for creating a FCoE VSI | |
1481 | * @vsi: pointer to the associated VSI struct | |
1482 | * @ctxt: pointer to the associated VSI context to be passed to HW | |
1483 | * | |
1484 | * Returns 0 on success or < 0 on error | |
1485 | **/ | |
1486 | void i40e_fcoe_config_netdev(struct net_device *netdev, struct i40e_vsi *vsi) | |
1487 | { | |
1488 | struct i40e_hw *hw = &vsi->back->hw; | |
1489 | struct i40e_pf *pf = vsi->back; | |
1490 | ||
1491 | if (vsi->type != I40E_VSI_FCOE) | |
1492 | return; | |
1493 | ||
1494 | netdev->features = (NETIF_F_HW_VLAN_CTAG_TX | | |
1495 | NETIF_F_HW_VLAN_CTAG_RX | | |
1496 | NETIF_F_HW_VLAN_CTAG_FILTER); | |
1497 | ||
1498 | netdev->vlan_features = netdev->features; | |
1499 | netdev->vlan_features &= ~(NETIF_F_HW_VLAN_CTAG_TX | | |
1500 | NETIF_F_HW_VLAN_CTAG_RX | | |
1501 | NETIF_F_HW_VLAN_CTAG_FILTER); | |
1502 | netdev->fcoe_ddp_xid = I40E_FCOE_DDP_MAX - 1; | |
1503 | netdev->features |= NETIF_F_ALL_FCOE; | |
1504 | netdev->vlan_features |= NETIF_F_ALL_FCOE; | |
1505 | netdev->hw_features |= netdev->features; | |
1506 | netdev->priv_flags |= IFF_UNICAST_FLT; | |
1507 | netdev->priv_flags |= IFF_SUPP_NOFCS; | |
1508 | ||
1509 | strlcpy(netdev->name, "fcoe%d", IFNAMSIZ-1); | |
1510 | netdev->mtu = FCOE_MTU; | |
1511 | SET_NETDEV_DEV(netdev, &pf->pdev->dev); | |
ccafbce4 | 1512 | SET_NETDEV_DEVTYPE(netdev, &fcoe_netdev_type); |
4d48b566 VD |
1513 | /* set different dev_port value 1 for FCoE netdev than the default |
1514 | * zero dev_port value for PF netdev, this helps biosdevname user | |
1515 | * tool to differentiate them correctly while both attached to the | |
1516 | * same PCI function. | |
1517 | */ | |
1518 | netdev->dev_port = 1; | |
a1a69369 VD |
1519 | i40e_add_filter(vsi, hw->mac.san_addr, 0, false, false); |
1520 | i40e_add_filter(vsi, (u8[6]) FC_FCOE_FLOGI_MAC, 0, false, false); | |
1521 | i40e_add_filter(vsi, FIP_ALL_FCOE_MACS, 0, false, false); | |
1522 | i40e_add_filter(vsi, FIP_ALL_ENODE_MACS, 0, false, false); | |
a1a69369 VD |
1523 | |
1524 | /* use san mac */ | |
1525 | ether_addr_copy(netdev->dev_addr, hw->mac.san_addr); | |
1526 | ether_addr_copy(netdev->perm_addr, hw->mac.san_addr); | |
1527 | /* fcoe netdev ops */ | |
1528 | netdev->netdev_ops = &i40e_fcoe_netdev_ops; | |
1529 | } | |
1530 | ||
1531 | /** | |
1532 | * i40e_fcoe_vsi_setup - allocate and set up FCoE VSI | |
b40c82e6 | 1533 | * @pf: the PF that VSI is associated with |
a1a69369 VD |
1534 | * |
1535 | **/ | |
1536 | void i40e_fcoe_vsi_setup(struct i40e_pf *pf) | |
1537 | { | |
1538 | struct i40e_vsi *vsi; | |
1539 | u16 seid; | |
1540 | int i; | |
1541 | ||
1542 | if (!(pf->flags & I40E_FLAG_FCOE_ENABLED)) | |
1543 | return; | |
1544 | ||
1545 | BUG_ON(!pf->vsi[pf->lan_vsi]); | |
1546 | ||
1547 | for (i = 0; i < pf->num_alloc_vsi; i++) { | |
1548 | vsi = pf->vsi[i]; | |
1549 | if (vsi && vsi->type == I40E_VSI_FCOE) { | |
1550 | dev_warn(&pf->pdev->dev, | |
1551 | "FCoE VSI already created\n"); | |
1552 | return; | |
1553 | } | |
1554 | } | |
1555 | ||
1556 | seid = pf->vsi[pf->lan_vsi]->seid; | |
1557 | vsi = i40e_vsi_setup(pf, I40E_VSI_FCOE, seid, 0); | |
1558 | if (vsi) { | |
1559 | dev_dbg(&pf->pdev->dev, | |
b40c82e6 | 1560 | "Successfully created FCoE VSI seid %d id %d uplink_seid %d PF seid %d\n", |
a1a69369 VD |
1561 | vsi->seid, vsi->id, vsi->uplink_seid, seid); |
1562 | } else { | |
1563 | dev_info(&pf->pdev->dev, "Failed to create FCoE VSI\n"); | |
1564 | } | |
1565 | } |