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