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