1 | /* bnx2fc_fcoe.c: QLogic Linux FCoE offload driver. |
2 | * This file contains the code that interacts with libfc, libfcoe, |
3 | * cnic modules to create FCoE instances, send/receive non-offloaded |
4 | * FIP/FCoE packets, listen to link events etc. |
5 | * |
6 | * Copyright (c) 2008-2013 Broadcom Corporation |
7 | * Copyright (c) 2014-2016 QLogic Corporation |
8 | * Copyright (c) 2016-2017 Cavium Inc. |
9 | * |
10 | * This program is free software; you can redistribute it and/or modify |
11 | * it under the terms of the GNU General Public License as published by |
12 | * the Free Software Foundation. |
13 | * |
14 | * Written by: Bhanu Prakash Gollapudi (bprakash@broadcom.com) |
15 | */ |
16 | |
17 | #include "bnx2fc.h" |
18 | |
19 | #include <linux/ethtool.h> |
20 | |
21 | static struct list_head adapter_list; |
22 | static struct list_head if_list; |
23 | static u32 adapter_count; |
24 | static DEFINE_MUTEX(bnx2fc_dev_lock); |
25 | DEFINE_PER_CPU(struct bnx2fc_percpu_s, bnx2fc_percpu); |
26 | |
27 | #define DRV_MODULE_NAME "bnx2fc" |
28 | #define DRV_MODULE_VERSION BNX2FC_VERSION |
29 | #define DRV_MODULE_RELDATE "October 15, 2015" |
30 | |
31 | |
32 | static char version[] = |
33 | "QLogic FCoE Driver " DRV_MODULE_NAME \ |
34 | " v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n" ; |
35 | |
36 | |
37 | MODULE_AUTHOR("Bhanu Prakash Gollapudi <bprakash@broadcom.com>" ); |
38 | MODULE_DESCRIPTION("QLogic FCoE Driver" ); |
39 | MODULE_LICENSE("GPL" ); |
40 | MODULE_VERSION(DRV_MODULE_VERSION); |
41 | |
42 | #define BNX2FC_MAX_QUEUE_DEPTH 256 |
43 | #define BNX2FC_MIN_QUEUE_DEPTH 32 |
44 | #define FCOE_WORD_TO_BYTE 4 |
45 | |
46 | static struct scsi_transport_template *bnx2fc_transport_template; |
47 | static struct scsi_transport_template *bnx2fc_vport_xport_template; |
48 | |
49 | struct workqueue_struct *bnx2fc_wq; |
50 | |
51 | /* bnx2fc structure needs only one instance of the fcoe_percpu_s structure. |
52 | * Here the io threads are per cpu but the l2 thread is just one |
53 | */ |
54 | struct fcoe_percpu_s bnx2fc_global; |
55 | static DEFINE_SPINLOCK(bnx2fc_global_lock); |
56 | |
57 | static struct cnic_ulp_ops bnx2fc_cnic_cb; |
58 | static struct libfc_function_template bnx2fc_libfc_fcn_templ; |
59 | static struct scsi_host_template bnx2fc_shost_template; |
60 | static struct fc_function_template bnx2fc_transport_function; |
61 | static struct fcoe_sysfs_function_template bnx2fc_fcoe_sysfs_templ; |
62 | static struct fc_function_template bnx2fc_vport_xport_function; |
63 | static int bnx2fc_create(struct net_device *netdev, enum fip_mode fip_mode); |
64 | static void __bnx2fc_destroy(struct bnx2fc_interface *interface); |
65 | static int bnx2fc_destroy(struct net_device *net_device); |
66 | static int bnx2fc_enable(struct net_device *netdev); |
67 | static int bnx2fc_disable(struct net_device *netdev); |
68 | |
69 | /* fcoe_syfs control interface handlers */ |
70 | static int bnx2fc_ctlr_alloc(struct net_device *netdev); |
71 | static int bnx2fc_ctlr_enabled(struct fcoe_ctlr_device *cdev); |
72 | |
73 | static void bnx2fc_recv_frame(struct sk_buff *skb); |
74 | |
75 | static void bnx2fc_start_disc(struct bnx2fc_interface *interface); |
76 | static int bnx2fc_shost_config(struct fc_lport *lport, struct device *dev); |
77 | static int bnx2fc_lport_config(struct fc_lport *lport); |
78 | static int bnx2fc_em_config(struct fc_lport *lport, struct bnx2fc_hba *hba); |
79 | static int bnx2fc_bind_adapter_devices(struct bnx2fc_hba *hba); |
80 | static void bnx2fc_unbind_adapter_devices(struct bnx2fc_hba *hba); |
81 | static int bnx2fc_bind_pcidev(struct bnx2fc_hba *hba); |
82 | static void bnx2fc_unbind_pcidev(struct bnx2fc_hba *hba); |
83 | static struct fc_lport *bnx2fc_if_create(struct bnx2fc_interface *interface, |
84 | struct device *parent, int npiv); |
85 | static void bnx2fc_port_destroy(struct fcoe_port *port); |
86 | |
87 | static struct bnx2fc_hba *bnx2fc_hba_lookup(struct net_device *phys_dev); |
88 | static struct bnx2fc_interface *bnx2fc_interface_lookup(struct net_device |
89 | *phys_dev); |
90 | static inline void bnx2fc_interface_put(struct bnx2fc_interface *interface); |
91 | static struct bnx2fc_hba *bnx2fc_find_hba_for_cnic(struct cnic_dev *cnic); |
92 | |
93 | static int bnx2fc_fw_init(struct bnx2fc_hba *hba); |
94 | static void bnx2fc_fw_destroy(struct bnx2fc_hba *hba); |
95 | |
96 | static void bnx2fc_port_shutdown(struct fc_lport *lport); |
97 | static void bnx2fc_stop(struct bnx2fc_interface *interface); |
98 | static int __init bnx2fc_mod_init(void); |
99 | static void __exit bnx2fc_mod_exit(void); |
100 | |
101 | unsigned int bnx2fc_debug_level; |
102 | module_param_named(debug_logging, bnx2fc_debug_level, int, S_IRUGO|S_IWUSR); |
103 | MODULE_PARM_DESC(debug_logging, |
104 | "Option to enable extended logging,\n" |
105 | "\t\tDefault is 0 - no logging.\n" |
106 | "\t\t0x01 - SCSI cmd error, cleanup.\n" |
107 | "\t\t0x02 - Session setup, cleanup, etc.\n" |
108 | "\t\t0x04 - lport events, link, mtu, etc.\n" |
109 | "\t\t0x08 - ELS logs.\n" |
110 | "\t\t0x10 - fcoe L2 fame related logs.\n" |
111 | "\t\t0xff - LOG all messages." ); |
112 | |
113 | static uint bnx2fc_devloss_tmo; |
114 | module_param_named(devloss_tmo, bnx2fc_devloss_tmo, uint, S_IRUGO); |
115 | MODULE_PARM_DESC(devloss_tmo, " Change devloss_tmo for the remote ports " |
116 | "attached via bnx2fc." ); |
117 | |
118 | static uint bnx2fc_max_luns = BNX2FC_MAX_LUN; |
119 | module_param_named(max_luns, bnx2fc_max_luns, uint, S_IRUGO); |
120 | MODULE_PARM_DESC(max_luns, " Change the default max_lun per SCSI host. Default " |
121 | "0xffff." ); |
122 | |
123 | static uint bnx2fc_queue_depth; |
124 | module_param_named(queue_depth, bnx2fc_queue_depth, uint, S_IRUGO); |
125 | MODULE_PARM_DESC(queue_depth, " Change the default queue depth of SCSI devices " |
126 | "attached via bnx2fc." ); |
127 | |
128 | static uint bnx2fc_log_fka; |
129 | module_param_named(log_fka, bnx2fc_log_fka, uint, S_IRUGO|S_IWUSR); |
130 | MODULE_PARM_DESC(log_fka, " Print message to kernel log when fcoe is " |
131 | "initiating a FIP keep alive when debug logging is enabled." ); |
132 | |
133 | static inline struct net_device *bnx2fc_netdev(const struct fc_lport *lport) |
134 | { |
135 | return ((struct bnx2fc_interface *) |
136 | ((struct fcoe_port *)lport_priv(lport))->priv)->netdev; |
137 | } |
138 | |
139 | static void bnx2fc_fcf_get_vlan_id(struct fcoe_fcf_device *fcf_dev) |
140 | { |
141 | struct fcoe_ctlr_device *ctlr_dev = |
142 | fcoe_fcf_dev_to_ctlr_dev(fcf_dev); |
143 | struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr: ctlr_dev); |
144 | struct bnx2fc_interface *fcoe = fcoe_ctlr_priv(ctlr); |
145 | |
146 | fcf_dev->vlan_id = fcoe->vlan_id; |
147 | } |
148 | |
149 | static void bnx2fc_clean_rx_queue(struct fc_lport *lp) |
150 | { |
151 | struct fcoe_percpu_s *bg; |
152 | struct fcoe_rcv_info *fr; |
153 | struct sk_buff_head *list; |
154 | struct sk_buff *skb, *next; |
155 | |
156 | bg = &bnx2fc_global; |
157 | spin_lock_bh(lock: &bg->fcoe_rx_list.lock); |
158 | list = &bg->fcoe_rx_list; |
159 | skb_queue_walk_safe(list, skb, next) { |
160 | fr = fcoe_dev_from_skb(skb); |
161 | if (fr->fr_dev == lp) { |
162 | __skb_unlink(skb, list); |
163 | kfree_skb(skb); |
164 | } |
165 | } |
166 | spin_unlock_bh(lock: &bg->fcoe_rx_list.lock); |
167 | } |
168 | |
169 | int bnx2fc_get_paged_crc_eof(struct sk_buff *skb, int tlen) |
170 | { |
171 | int rc; |
172 | spin_lock(lock: &bnx2fc_global_lock); |
173 | rc = fcoe_get_paged_crc_eof(skb, tlen, fps: &bnx2fc_global); |
174 | spin_unlock(lock: &bnx2fc_global_lock); |
175 | |
176 | return rc; |
177 | } |
178 | |
179 | static void bnx2fc_abort_io(struct fc_lport *lport) |
180 | { |
181 | /* |
182 | * This function is no-op for bnx2fc, but we do |
183 | * not want to leave it as NULL either, as libfc |
184 | * can call the default function which is |
185 | * fc_fcp_abort_io. |
186 | */ |
187 | } |
188 | |
189 | static void bnx2fc_cleanup(struct fc_lport *lport) |
190 | { |
191 | struct fcoe_port *port = lport_priv(lport); |
192 | struct bnx2fc_interface *interface = port->priv; |
193 | struct bnx2fc_hba *hba = interface->hba; |
194 | struct bnx2fc_rport *tgt; |
195 | int i; |
196 | |
197 | BNX2FC_MISC_DBG("Entered %s\n" , __func__); |
198 | mutex_lock(&hba->hba_mutex); |
199 | spin_lock_bh(lock: &hba->hba_lock); |
200 | for (i = 0; i < BNX2FC_NUM_MAX_SESS; i++) { |
201 | tgt = hba->tgt_ofld_list[i]; |
202 | if (tgt) { |
203 | /* Cleanup IOs belonging to requested vport */ |
204 | if (tgt->port == port) { |
205 | spin_unlock_bh(lock: &hba->hba_lock); |
206 | BNX2FC_TGT_DBG(tgt, fmt: "flush/cleanup\n" ); |
207 | bnx2fc_flush_active_ios(tgt); |
208 | spin_lock_bh(lock: &hba->hba_lock); |
209 | } |
210 | } |
211 | } |
212 | spin_unlock_bh(lock: &hba->hba_lock); |
213 | mutex_unlock(lock: &hba->hba_mutex); |
214 | } |
215 | |
216 | static int bnx2fc_xmit_l2_frame(struct bnx2fc_rport *tgt, |
217 | struct fc_frame *fp) |
218 | { |
219 | struct fc_rport_priv *rdata = tgt->rdata; |
220 | struct fc_frame_header *fh; |
221 | int rc = 0; |
222 | |
223 | fh = fc_frame_header_get(fp); |
224 | BNX2FC_TGT_DBG(tgt, fmt: "Xmit L2 frame rport = 0x%x, oxid = 0x%x, " |
225 | "r_ctl = 0x%x\n" , rdata->ids.port_id, |
226 | ntohs(fh->fh_ox_id), fh->fh_r_ctl); |
227 | if ((fh->fh_type == FC_TYPE_ELS) && |
228 | (fh->fh_r_ctl == FC_RCTL_ELS_REQ)) { |
229 | |
230 | switch (fc_frame_payload_op(fp)) { |
231 | case ELS_ADISC: |
232 | rc = bnx2fc_send_adisc(tgt, fp); |
233 | break; |
234 | case ELS_LOGO: |
235 | rc = bnx2fc_send_logo(tgt, fp); |
236 | break; |
237 | case ELS_RLS: |
238 | rc = bnx2fc_send_rls(tgt, fp); |
239 | break; |
240 | default: |
241 | break; |
242 | } |
243 | } else if ((fh->fh_type == FC_TYPE_BLS) && |
244 | (fh->fh_r_ctl == FC_RCTL_BA_ABTS)) |
245 | BNX2FC_TGT_DBG(tgt, fmt: "ABTS frame\n" ); |
246 | else { |
247 | BNX2FC_TGT_DBG(tgt, fmt: "Send L2 frame type 0x%x " |
248 | "rctl 0x%x thru non-offload path\n" , |
249 | fh->fh_type, fh->fh_r_ctl); |
250 | return -ENODEV; |
251 | } |
252 | if (rc) |
253 | return -ENOMEM; |
254 | else |
255 | return 0; |
256 | } |
257 | |
258 | /** |
259 | * bnx2fc_xmit - bnx2fc's FCoE frame transmit function |
260 | * |
261 | * @lport: the associated local port |
262 | * @fp: the fc_frame to be transmitted |
263 | */ |
264 | static int bnx2fc_xmit(struct fc_lport *lport, struct fc_frame *fp) |
265 | { |
266 | struct ethhdr *eh; |
267 | struct fcoe_crc_eof *cp; |
268 | struct sk_buff *skb; |
269 | struct fc_frame_header *fh; |
270 | struct bnx2fc_interface *interface; |
271 | struct fcoe_ctlr *ctlr; |
272 | struct bnx2fc_hba *hba; |
273 | struct fcoe_port *port; |
274 | struct fcoe_hdr *hp; |
275 | struct bnx2fc_rport *tgt; |
276 | u8 sof, eof; |
277 | u32 crc; |
278 | unsigned int hlen, tlen, elen; |
279 | int wlen, rc = 0; |
280 | |
281 | port = (struct fcoe_port *)lport_priv(lport); |
282 | interface = port->priv; |
283 | ctlr = bnx2fc_to_ctlr(interface); |
284 | hba = interface->hba; |
285 | |
286 | fh = fc_frame_header_get(fp); |
287 | |
288 | skb = fp_skb(fp); |
289 | if (!lport->link_up) { |
290 | BNX2FC_HBA_DBG(lport, fmt: "bnx2fc_xmit link down\n" ); |
291 | kfree_skb(skb); |
292 | return 0; |
293 | } |
294 | |
295 | if (unlikely(fh->fh_r_ctl == FC_RCTL_ELS_REQ)) { |
296 | if (!ctlr->sel_fcf) { |
297 | BNX2FC_HBA_DBG(lport, fmt: "FCF not selected yet!\n" ); |
298 | kfree_skb(skb); |
299 | return -EINVAL; |
300 | } |
301 | if (fcoe_ctlr_els_send(ctlr, lport, skb)) |
302 | return 0; |
303 | } |
304 | |
305 | sof = fr_sof(fp); |
306 | eof = fr_eof(fp); |
307 | |
308 | /* |
309 | * Snoop the frame header to check if the frame is for |
310 | * an offloaded session |
311 | */ |
312 | /* |
313 | * tgt_ofld_list access is synchronized using |
314 | * both hba mutex and hba lock. Atleast hba mutex or |
315 | * hba lock needs to be held for read access. |
316 | */ |
317 | |
318 | spin_lock_bh(lock: &hba->hba_lock); |
319 | tgt = bnx2fc_tgt_lookup(port, port_id: ntoh24(p: fh->fh_d_id)); |
320 | if (tgt && (test_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags))) { |
321 | /* This frame is for offloaded session */ |
322 | BNX2FC_HBA_DBG(lport, fmt: "xmit: Frame is for offloaded session " |
323 | "port_id = 0x%x\n" , ntoh24(p: fh->fh_d_id)); |
324 | spin_unlock_bh(lock: &hba->hba_lock); |
325 | rc = bnx2fc_xmit_l2_frame(tgt, fp); |
326 | if (rc != -ENODEV) { |
327 | kfree_skb(skb); |
328 | return rc; |
329 | } |
330 | } else { |
331 | spin_unlock_bh(lock: &hba->hba_lock); |
332 | } |
333 | |
334 | elen = sizeof(struct ethhdr); |
335 | hlen = sizeof(struct fcoe_hdr); |
336 | tlen = sizeof(struct fcoe_crc_eof); |
337 | wlen = (skb->len - tlen + sizeof(crc)) / FCOE_WORD_TO_BYTE; |
338 | |
339 | skb->ip_summed = CHECKSUM_NONE; |
340 | crc = fcoe_fc_crc(fp); |
341 | |
342 | /* copy port crc and eof to the skb buff */ |
343 | if (skb_is_nonlinear(skb)) { |
344 | skb_frag_t *frag; |
345 | if (bnx2fc_get_paged_crc_eof(skb, tlen)) { |
346 | kfree_skb(skb); |
347 | return -ENOMEM; |
348 | } |
349 | frag = &skb_shinfo(skb)->frags[skb_shinfo(skb)->nr_frags - 1]; |
350 | cp = kmap_atomic(page: skb_frag_page(frag)) + skb_frag_off(frag); |
351 | } else { |
352 | cp = skb_put(skb, len: tlen); |
353 | } |
354 | |
355 | memset(cp, 0, sizeof(*cp)); |
356 | cp->fcoe_eof = eof; |
357 | cp->fcoe_crc32 = cpu_to_le32(~crc); |
358 | if (skb_is_nonlinear(skb)) { |
359 | kunmap_atomic(cp); |
360 | cp = NULL; |
361 | } |
362 | |
363 | /* adjust skb network/transport offsets to match mac/fcoe/port */ |
364 | skb_push(skb, len: elen + hlen); |
365 | skb_reset_mac_header(skb); |
366 | skb_reset_network_header(skb); |
367 | skb->mac_len = elen; |
368 | skb->protocol = htons(ETH_P_FCOE); |
369 | skb->dev = interface->netdev; |
370 | |
371 | /* fill up mac and fcoe headers */ |
372 | eh = eth_hdr(skb); |
373 | eh->h_proto = htons(ETH_P_FCOE); |
374 | if (ctlr->map_dest) |
375 | fc_fcoe_set_mac(mac: eh->h_dest, did: fh->fh_d_id); |
376 | else |
377 | /* insert GW address */ |
378 | memcpy(eh->h_dest, ctlr->dest_addr, ETH_ALEN); |
379 | |
380 | if (unlikely(ctlr->flogi_oxid != FC_XID_UNKNOWN)) |
381 | memcpy(eh->h_source, ctlr->ctl_src_addr, ETH_ALEN); |
382 | else |
383 | memcpy(eh->h_source, port->data_src_addr, ETH_ALEN); |
384 | |
385 | hp = (struct fcoe_hdr *)(eh + 1); |
386 | memset(hp, 0, sizeof(*hp)); |
387 | if (FC_FCOE_VER) |
388 | FC_FCOE_ENCAPS_VER(hp, FC_FCOE_VER); |
389 | hp->fcoe_sof = sof; |
390 | |
391 | /* fcoe lso, mss is in max_payload which is non-zero for FCP data */ |
392 | if (lport->seq_offload && fr_max_payload(fp)) { |
393 | skb_shinfo(skb)->gso_type = SKB_GSO_FCOE; |
394 | skb_shinfo(skb)->gso_size = fr_max_payload(fp); |
395 | } else { |
396 | skb_shinfo(skb)->gso_type = 0; |
397 | skb_shinfo(skb)->gso_size = 0; |
398 | } |
399 | |
400 | /*update tx stats */ |
401 | this_cpu_inc(lport->stats->TxFrames); |
402 | this_cpu_add(lport->stats->TxWords, wlen); |
403 | |
404 | /* send down to lld */ |
405 | fr_dev(fp) = lport; |
406 | if (port->fcoe_pending_queue.qlen) |
407 | fcoe_check_wait_queue(lport, skb); |
408 | else if (fcoe_start_io(skb)) |
409 | fcoe_check_wait_queue(lport, skb); |
410 | |
411 | return 0; |
412 | } |
413 | |
414 | /** |
415 | * bnx2fc_rcv - This is bnx2fc's receive function called by NET_RX_SOFTIRQ |
416 | * |
417 | * @skb: the receive socket buffer |
418 | * @dev: associated net device |
419 | * @ptype: context |
420 | * @olddev: last device |
421 | * |
422 | * This function receives the packet and builds FC frame and passes it up |
423 | */ |
424 | static int bnx2fc_rcv(struct sk_buff *skb, struct net_device *dev, |
425 | struct packet_type *ptype, struct net_device *olddev) |
426 | { |
427 | struct fc_lport *lport; |
428 | struct bnx2fc_interface *interface; |
429 | struct fcoe_ctlr *ctlr; |
430 | struct fcoe_rcv_info *fr; |
431 | struct fcoe_percpu_s *bg; |
432 | |
433 | interface = container_of(ptype, struct bnx2fc_interface, |
434 | fcoe_packet_type); |
435 | ctlr = bnx2fc_to_ctlr(interface); |
436 | lport = ctlr->lp; |
437 | |
438 | if (unlikely(lport == NULL)) { |
439 | printk(KERN_ERR PFX "bnx2fc_rcv: lport is NULL\n" ); |
440 | goto err; |
441 | } |
442 | |
443 | skb = skb_share_check(skb, GFP_ATOMIC); |
444 | if (!skb) |
445 | return -1; |
446 | |
447 | if (unlikely(eth_hdr(skb)->h_proto != htons(ETH_P_FCOE))) { |
448 | printk(KERN_ERR PFX "bnx2fc_rcv: Wrong FC type frame\n" ); |
449 | goto err; |
450 | } |
451 | |
452 | /* |
453 | * Check for minimum frame length, and make sure required FCoE |
454 | * and FC headers are pulled into the linear data area. |
455 | */ |
456 | if (unlikely((skb->len < FCOE_MIN_FRAME) || |
457 | !pskb_may_pull(skb, FCOE_HEADER_LEN))) |
458 | goto err; |
459 | |
460 | skb_set_transport_header(skb, offset: sizeof(struct fcoe_hdr)); |
461 | |
462 | fr = fcoe_dev_from_skb(skb); |
463 | fr->fr_dev = lport; |
464 | |
465 | bg = &bnx2fc_global; |
466 | spin_lock(lock: &bg->fcoe_rx_list.lock); |
467 | |
468 | __skb_queue_tail(list: &bg->fcoe_rx_list, newsk: skb); |
469 | if (bg->fcoe_rx_list.qlen == 1) |
470 | wake_up_process(tsk: bg->kthread); |
471 | |
472 | spin_unlock(lock: &bg->fcoe_rx_list.lock); |
473 | |
474 | return 0; |
475 | err: |
476 | kfree_skb(skb); |
477 | return -1; |
478 | } |
479 | |
480 | static int bnx2fc_l2_rcv_thread(void *arg) |
481 | { |
482 | struct fcoe_percpu_s *bg = arg; |
483 | struct sk_buff *skb; |
484 | |
485 | set_user_nice(current, MIN_NICE); |
486 | set_current_state(TASK_INTERRUPTIBLE); |
487 | while (!kthread_should_stop()) { |
488 | schedule(); |
489 | spin_lock_bh(lock: &bg->fcoe_rx_list.lock); |
490 | while ((skb = __skb_dequeue(list: &bg->fcoe_rx_list)) != NULL) { |
491 | spin_unlock_bh(lock: &bg->fcoe_rx_list.lock); |
492 | bnx2fc_recv_frame(skb); |
493 | spin_lock_bh(lock: &bg->fcoe_rx_list.lock); |
494 | } |
495 | __set_current_state(TASK_INTERRUPTIBLE); |
496 | spin_unlock_bh(lock: &bg->fcoe_rx_list.lock); |
497 | } |
498 | __set_current_state(TASK_RUNNING); |
499 | return 0; |
500 | } |
501 | |
502 | |
503 | static void bnx2fc_recv_frame(struct sk_buff *skb) |
504 | { |
505 | u64 crc_err; |
506 | u32 fr_len, fr_crc; |
507 | struct fc_lport *lport; |
508 | struct fcoe_rcv_info *fr; |
509 | struct fc_frame_header *fh; |
510 | struct fcoe_crc_eof crc_eof; |
511 | struct fc_frame *fp; |
512 | struct fc_lport *vn_port; |
513 | struct fcoe_port *port, *phys_port; |
514 | u8 *mac = NULL; |
515 | u8 *dest_mac = NULL; |
516 | struct fcoe_hdr *hp; |
517 | struct bnx2fc_interface *interface; |
518 | struct fcoe_ctlr *ctlr; |
519 | |
520 | fr = fcoe_dev_from_skb(skb); |
521 | lport = fr->fr_dev; |
522 | if (unlikely(lport == NULL)) { |
523 | printk(KERN_ERR PFX "Invalid lport struct\n" ); |
524 | kfree_skb(skb); |
525 | return; |
526 | } |
527 | |
528 | if (skb_is_nonlinear(skb)) |
529 | skb_linearize(skb); |
530 | mac = eth_hdr(skb)->h_source; |
531 | dest_mac = eth_hdr(skb)->h_dest; |
532 | |
533 | /* Pull the header */ |
534 | hp = (struct fcoe_hdr *) skb_network_header(skb); |
535 | fh = (struct fc_frame_header *) skb_transport_header(skb); |
536 | skb_pull(skb, len: sizeof(struct fcoe_hdr)); |
537 | fr_len = skb->len - sizeof(struct fcoe_crc_eof); |
538 | |
539 | this_cpu_inc(lport->stats->RxFrames); |
540 | this_cpu_add(lport->stats->RxWords, fr_len / FCOE_WORD_TO_BYTE); |
541 | |
542 | fp = (struct fc_frame *)skb; |
543 | fc_frame_init(fp); |
544 | fr_dev(fp) = lport; |
545 | fr_sof(fp) = hp->fcoe_sof; |
546 | if (skb_copy_bits(skb, offset: fr_len, to: &crc_eof, len: sizeof(crc_eof))) { |
547 | kfree_skb(skb); |
548 | return; |
549 | } |
550 | fr_eof(fp) = crc_eof.fcoe_eof; |
551 | fr_crc(fp) = crc_eof.fcoe_crc32; |
552 | if (pskb_trim(skb, len: fr_len)) { |
553 | kfree_skb(skb); |
554 | return; |
555 | } |
556 | |
557 | phys_port = lport_priv(lport); |
558 | interface = phys_port->priv; |
559 | ctlr = bnx2fc_to_ctlr(interface); |
560 | |
561 | fh = fc_frame_header_get(fp); |
562 | |
563 | if (ntoh24(p: &dest_mac[3]) != ntoh24(p: fh->fh_d_id)) { |
564 | BNX2FC_HBA_DBG(lport, fmt: "FC frame d_id mismatch with MAC %pM.\n" , |
565 | dest_mac); |
566 | kfree_skb(skb); |
567 | return; |
568 | } |
569 | |
570 | vn_port = fc_vport_id_lookup(lport, port_id: ntoh24(p: fh->fh_d_id)); |
571 | if (vn_port) { |
572 | port = lport_priv(lport: vn_port); |
573 | if (!ether_addr_equal(addr1: port->data_src_addr, addr2: dest_mac)) { |
574 | BNX2FC_HBA_DBG(lport, fmt: "fpma mismatch\n" ); |
575 | kfree_skb(skb); |
576 | return; |
577 | } |
578 | } |
579 | if (ctlr->state) { |
580 | if (!ether_addr_equal(addr1: mac, addr2: ctlr->dest_addr)) { |
581 | BNX2FC_HBA_DBG(lport, fmt: "Wrong source address: mac:%pM dest_addr:%pM.\n" , |
582 | mac, ctlr->dest_addr); |
583 | kfree_skb(skb); |
584 | return; |
585 | } |
586 | } |
587 | if (fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA && |
588 | fh->fh_type == FC_TYPE_FCP) { |
589 | /* Drop FCP data. We dont this in L2 path */ |
590 | kfree_skb(skb); |
591 | return; |
592 | } |
593 | if (fh->fh_r_ctl == FC_RCTL_ELS_REQ && |
594 | fh->fh_type == FC_TYPE_ELS) { |
595 | switch (fc_frame_payload_op(fp)) { |
596 | case ELS_LOGO: |
597 | if (ntoh24(p: fh->fh_s_id) == FC_FID_FLOGI) { |
598 | /* drop non-FIP LOGO */ |
599 | kfree_skb(skb); |
600 | return; |
601 | } |
602 | break; |
603 | } |
604 | } |
605 | |
606 | if (fh->fh_r_ctl == FC_RCTL_BA_ABTS) { |
607 | /* Drop incoming ABTS */ |
608 | kfree_skb(skb); |
609 | return; |
610 | } |
611 | |
612 | /* |
613 | * If the destination ID from the frame header does not match what we |
614 | * have on record for lport and the search for a NPIV port came up |
615 | * empty then this is not addressed to our port so simply drop it. |
616 | */ |
617 | if (lport->port_id != ntoh24(p: fh->fh_d_id) && !vn_port) { |
618 | BNX2FC_HBA_DBG(lport, fmt: "Dropping frame due to destination mismatch: lport->port_id=%x fh->d_id=%x.\n" , |
619 | lport->port_id, ntoh24(p: fh->fh_d_id)); |
620 | kfree_skb(skb); |
621 | return; |
622 | } |
623 | |
624 | fr_crc = le32_to_cpu(fr_crc(fp)); |
625 | |
626 | if (unlikely(fr_crc != ~crc32(~0, skb->data, fr_len))) { |
627 | crc_err = this_cpu_inc_return(lport->stats->InvalidCRCCount); |
628 | if (crc_err < 5) |
629 | printk(KERN_WARNING PFX "dropping frame with " |
630 | "CRC error\n" ); |
631 | kfree_skb(skb); |
632 | return; |
633 | } |
634 | fc_exch_recv(lport, fp); |
635 | } |
636 | |
637 | /** |
638 | * bnx2fc_percpu_io_thread - thread per cpu for ios |
639 | * |
640 | * @arg: ptr to bnx2fc_percpu_info structure |
641 | */ |
642 | static int bnx2fc_percpu_io_thread(void *arg) |
643 | { |
644 | struct bnx2fc_percpu_s *p = arg; |
645 | struct bnx2fc_work *work, *tmp; |
646 | LIST_HEAD(work_list); |
647 | |
648 | set_user_nice(current, MIN_NICE); |
649 | set_current_state(TASK_INTERRUPTIBLE); |
650 | while (!kthread_should_stop()) { |
651 | schedule(); |
652 | spin_lock_bh(lock: &p->fp_work_lock); |
653 | while (!list_empty(head: &p->work_list)) { |
654 | list_splice_init(list: &p->work_list, head: &work_list); |
655 | spin_unlock_bh(lock: &p->fp_work_lock); |
656 | |
657 | list_for_each_entry_safe(work, tmp, &work_list, list) { |
658 | list_del_init(entry: &work->list); |
659 | bnx2fc_process_cq_compl(tgt: work->tgt, wqe: work->wqe, |
660 | rq_data: work->rq_data, |
661 | num_rq: work->num_rq, |
662 | task: work->task); |
663 | kfree(objp: work); |
664 | } |
665 | |
666 | spin_lock_bh(lock: &p->fp_work_lock); |
667 | } |
668 | __set_current_state(TASK_INTERRUPTIBLE); |
669 | spin_unlock_bh(lock: &p->fp_work_lock); |
670 | } |
671 | __set_current_state(TASK_RUNNING); |
672 | |
673 | return 0; |
674 | } |
675 | |
676 | static struct fc_host_statistics *bnx2fc_get_host_stats(struct Scsi_Host *shost) |
677 | { |
678 | struct fc_host_statistics *bnx2fc_stats; |
679 | struct fc_lport *lport = shost_priv(shost); |
680 | struct fcoe_port *port = lport_priv(lport); |
681 | struct bnx2fc_interface *interface = port->priv; |
682 | struct bnx2fc_hba *hba = interface->hba; |
683 | struct fcoe_statistics_params *fw_stats; |
684 | int rc = 0; |
685 | |
686 | fw_stats = (struct fcoe_statistics_params *)hba->stats_buffer; |
687 | if (!fw_stats) |
688 | return NULL; |
689 | |
690 | mutex_lock(&hba->hba_stats_mutex); |
691 | |
692 | bnx2fc_stats = fc_get_host_stats(shost); |
693 | |
694 | init_completion(x: &hba->stat_req_done); |
695 | if (bnx2fc_send_stat_req(hba)) |
696 | goto unlock_stats_mutex; |
697 | rc = wait_for_completion_timeout(x: &hba->stat_req_done, timeout: (2 * HZ)); |
698 | if (!rc) { |
699 | BNX2FC_HBA_DBG(lport, fmt: "FW stat req timed out\n" ); |
700 | goto unlock_stats_mutex; |
701 | } |
702 | BNX2FC_STATS(hba, rx_stat2, fc_crc_cnt); |
703 | bnx2fc_stats->invalid_crc_count += hba->bfw_stats.fc_crc_cnt; |
704 | BNX2FC_STATS(hba, tx_stat, fcoe_tx_pkt_cnt); |
705 | bnx2fc_stats->tx_frames += hba->bfw_stats.fcoe_tx_pkt_cnt; |
706 | BNX2FC_STATS(hba, tx_stat, fcoe_tx_byte_cnt); |
707 | bnx2fc_stats->tx_words += ((hba->bfw_stats.fcoe_tx_byte_cnt) / 4); |
708 | BNX2FC_STATS(hba, rx_stat0, fcoe_rx_pkt_cnt); |
709 | bnx2fc_stats->rx_frames += hba->bfw_stats.fcoe_rx_pkt_cnt; |
710 | BNX2FC_STATS(hba, rx_stat0, fcoe_rx_byte_cnt); |
711 | bnx2fc_stats->rx_words += ((hba->bfw_stats.fcoe_rx_byte_cnt) / 4); |
712 | |
713 | bnx2fc_stats->dumped_frames = 0; |
714 | bnx2fc_stats->lip_count = 0; |
715 | bnx2fc_stats->nos_count = 0; |
716 | bnx2fc_stats->loss_of_sync_count = 0; |
717 | bnx2fc_stats->loss_of_signal_count = 0; |
718 | bnx2fc_stats->prim_seq_protocol_err_count = 0; |
719 | |
720 | memcpy(&hba->prev_stats, hba->stats_buffer, |
721 | sizeof(struct fcoe_statistics_params)); |
722 | |
723 | unlock_stats_mutex: |
724 | mutex_unlock(lock: &hba->hba_stats_mutex); |
725 | return bnx2fc_stats; |
726 | } |
727 | |
728 | static int bnx2fc_shost_config(struct fc_lport *lport, struct device *dev) |
729 | { |
730 | struct fcoe_port *port = lport_priv(lport); |
731 | struct bnx2fc_interface *interface = port->priv; |
732 | struct bnx2fc_hba *hba = interface->hba; |
733 | struct Scsi_Host *shost = lport->host; |
734 | int rc = 0; |
735 | |
736 | shost->max_cmd_len = BNX2FC_MAX_CMD_LEN; |
737 | shost->max_lun = bnx2fc_max_luns; |
738 | shost->max_id = BNX2FC_MAX_FCP_TGT; |
739 | shost->max_channel = 0; |
740 | if (lport->vport) |
741 | shost->transportt = bnx2fc_vport_xport_template; |
742 | else |
743 | shost->transportt = bnx2fc_transport_template; |
744 | |
745 | /* Add the new host to SCSI-ml */ |
746 | rc = scsi_add_host(host: lport->host, dev); |
747 | if (rc) { |
748 | printk(KERN_ERR PFX "Error on scsi_add_host\n" ); |
749 | return rc; |
750 | } |
751 | if (!lport->vport) |
752 | fc_host_max_npiv_vports(lport->host) = USHRT_MAX; |
753 | snprintf(fc_host_symbolic_name(lport->host), size: 256, |
754 | fmt: "%s (QLogic %s) v%s over %s" , |
755 | BNX2FC_NAME, hba->chip_num, BNX2FC_VERSION, |
756 | interface->netdev->name); |
757 | |
758 | return 0; |
759 | } |
760 | |
761 | static int bnx2fc_link_ok(struct fc_lport *lport) |
762 | { |
763 | struct fcoe_port *port = lport_priv(lport); |
764 | struct bnx2fc_interface *interface = port->priv; |
765 | struct bnx2fc_hba *hba = interface->hba; |
766 | struct net_device *dev = hba->phys_dev; |
767 | int rc = 0; |
768 | |
769 | if ((dev->flags & IFF_UP) && netif_carrier_ok(dev)) |
770 | clear_bit(ADAPTER_STATE_LINK_DOWN, addr: &hba->adapter_state); |
771 | else { |
772 | set_bit(ADAPTER_STATE_LINK_DOWN, addr: &hba->adapter_state); |
773 | rc = -1; |
774 | } |
775 | return rc; |
776 | } |
777 | |
778 | /** |
779 | * bnx2fc_get_link_state - get network link state |
780 | * |
781 | * @hba: adapter instance pointer |
782 | * |
783 | * updates adapter structure flag based on netdev state |
784 | */ |
785 | void bnx2fc_get_link_state(struct bnx2fc_hba *hba) |
786 | { |
787 | if (test_bit(__LINK_STATE_NOCARRIER, &hba->phys_dev->state)) |
788 | set_bit(ADAPTER_STATE_LINK_DOWN, addr: &hba->adapter_state); |
789 | else |
790 | clear_bit(ADAPTER_STATE_LINK_DOWN, addr: &hba->adapter_state); |
791 | } |
792 | |
793 | static int bnx2fc_net_config(struct fc_lport *lport, struct net_device *netdev) |
794 | { |
795 | struct bnx2fc_hba *hba; |
796 | struct bnx2fc_interface *interface; |
797 | struct fcoe_ctlr *ctlr; |
798 | struct fcoe_port *port; |
799 | u64 wwnn, wwpn; |
800 | |
801 | port = lport_priv(lport); |
802 | interface = port->priv; |
803 | ctlr = bnx2fc_to_ctlr(interface); |
804 | hba = interface->hba; |
805 | |
806 | /* require support for get_pauseparam ethtool op. */ |
807 | if (!hba->phys_dev->ethtool_ops || |
808 | !hba->phys_dev->ethtool_ops->get_pauseparam) |
809 | return -EOPNOTSUPP; |
810 | |
811 | if (fc_set_mfs(lport, BNX2FC_MFS)) |
812 | return -EINVAL; |
813 | |
814 | skb_queue_head_init(list: &port->fcoe_pending_queue); |
815 | port->fcoe_pending_queue_active = 0; |
816 | timer_setup(&port->timer, fcoe_queue_timer, 0); |
817 | |
818 | fcoe_link_speed_update(lport); |
819 | |
820 | if (!lport->vport) { |
821 | if (fcoe_get_wwn(netdev, wwn: &wwnn, NETDEV_FCOE_WWNN)) |
822 | wwnn = fcoe_wwn_from_mac(mac: ctlr->ctl_src_addr, |
823 | scheme: 1, port: 0); |
824 | BNX2FC_HBA_DBG(lport, fmt: "WWNN = 0x%llx\n" , wwnn); |
825 | fc_set_wwnn(lport, wwnn); |
826 | |
827 | if (fcoe_get_wwn(netdev, wwn: &wwpn, NETDEV_FCOE_WWPN)) |
828 | wwpn = fcoe_wwn_from_mac(mac: ctlr->ctl_src_addr, |
829 | scheme: 2, port: 0); |
830 | |
831 | BNX2FC_HBA_DBG(lport, fmt: "WWPN = 0x%llx\n" , wwpn); |
832 | fc_set_wwpn(lport, wwpn); |
833 | } |
834 | |
835 | return 0; |
836 | } |
837 | |
838 | static void bnx2fc_destroy_timer(struct timer_list *t) |
839 | { |
840 | struct bnx2fc_hba *hba = from_timer(hba, t, destroy_timer); |
841 | |
842 | printk(KERN_ERR PFX "ERROR:bnx2fc_destroy_timer - " |
843 | "Destroy compl not received!!\n" ); |
844 | set_bit(BNX2FC_FLAG_DESTROY_CMPL, addr: &hba->flags); |
845 | wake_up_interruptible(&hba->destroy_wait); |
846 | } |
847 | |
848 | /** |
849 | * bnx2fc_indicate_netevent - Generic netdev event handler |
850 | * |
851 | * @context: adapter structure pointer |
852 | * @event: event type |
853 | * @vlan_id: vlan id - associated vlan id with this event |
854 | * |
855 | * Handles NETDEV_UP, NETDEV_DOWN, NETDEV_GOING_DOWN,NETDEV_CHANGE and |
856 | * NETDEV_CHANGE_MTU events. Handle NETDEV_UNREGISTER only for vlans. |
857 | */ |
858 | static void bnx2fc_indicate_netevent(void *context, unsigned long event, |
859 | u16 vlan_id) |
860 | { |
861 | struct bnx2fc_hba *hba = (struct bnx2fc_hba *)context; |
862 | struct fcoe_ctlr_device *cdev; |
863 | struct fc_lport *lport; |
864 | struct fc_lport *vport; |
865 | struct bnx2fc_interface *interface, *tmp; |
866 | struct fcoe_ctlr *ctlr; |
867 | int wait_for_upload = 0; |
868 | u32 link_possible = 1; |
869 | |
870 | if (vlan_id != 0 && event != NETDEV_UNREGISTER) |
871 | return; |
872 | |
873 | switch (event) { |
874 | case NETDEV_UP: |
875 | if (!test_bit(ADAPTER_STATE_UP, &hba->adapter_state)) |
876 | printk(KERN_ERR "indicate_netevent: " \ |
877 | "hba is not UP!!\n" ); |
878 | break; |
879 | |
880 | case NETDEV_DOWN: |
881 | clear_bit(ADAPTER_STATE_GOING_DOWN, addr: &hba->adapter_state); |
882 | clear_bit(ADAPTER_STATE_UP, addr: &hba->adapter_state); |
883 | link_possible = 0; |
884 | break; |
885 | |
886 | case NETDEV_GOING_DOWN: |
887 | set_bit(ADAPTER_STATE_GOING_DOWN, addr: &hba->adapter_state); |
888 | link_possible = 0; |
889 | break; |
890 | |
891 | case NETDEV_CHANGE: |
892 | break; |
893 | |
894 | case NETDEV_UNREGISTER: |
895 | if (!vlan_id) |
896 | return; |
897 | mutex_lock(&bnx2fc_dev_lock); |
898 | list_for_each_entry_safe(interface, tmp, &if_list, list) { |
899 | if (interface->hba == hba && |
900 | interface->vlan_id == (vlan_id & VLAN_VID_MASK)) |
901 | __bnx2fc_destroy(interface); |
902 | } |
903 | mutex_unlock(lock: &bnx2fc_dev_lock); |
904 | return; |
905 | |
906 | default: |
907 | return; |
908 | } |
909 | |
910 | mutex_lock(&bnx2fc_dev_lock); |
911 | list_for_each_entry(interface, &if_list, list) { |
912 | |
913 | if (interface->hba != hba) |
914 | continue; |
915 | |
916 | ctlr = bnx2fc_to_ctlr(interface); |
917 | lport = ctlr->lp; |
918 | BNX2FC_HBA_DBG(lport, fmt: "netevent handler - event=%s %ld\n" , |
919 | interface->netdev->name, event); |
920 | |
921 | fcoe_link_speed_update(lport); |
922 | |
923 | cdev = fcoe_ctlr_to_ctlr_dev(ctlr); |
924 | |
925 | if (link_possible && !bnx2fc_link_ok(lport)) { |
926 | switch (cdev->enabled) { |
927 | case FCOE_CTLR_DISABLED: |
928 | pr_info("Link up while interface is disabled.\n" ); |
929 | break; |
930 | case FCOE_CTLR_ENABLED: |
931 | case FCOE_CTLR_UNUSED: |
932 | /* Reset max recv frame size to default */ |
933 | fc_set_mfs(lport, BNX2FC_MFS); |
934 | /* |
935 | * ctlr link up will only be handled during |
936 | * enable to avoid sending discovery |
937 | * solicitation on a stale vlan |
938 | */ |
939 | if (interface->enabled) |
940 | fcoe_ctlr_link_up(ctlr); |
941 | } |
942 | } else if (fcoe_ctlr_link_down(ctlr)) { |
943 | switch (cdev->enabled) { |
944 | case FCOE_CTLR_DISABLED: |
945 | pr_info("Link down while interface is disabled.\n" ); |
946 | break; |
947 | case FCOE_CTLR_ENABLED: |
948 | case FCOE_CTLR_UNUSED: |
949 | mutex_lock(&lport->lp_mutex); |
950 | list_for_each_entry(vport, &lport->vports, list) |
951 | fc_host_port_type(vport->host) = |
952 | FC_PORTTYPE_UNKNOWN; |
953 | mutex_unlock(lock: &lport->lp_mutex); |
954 | fc_host_port_type(lport->host) = |
955 | FC_PORTTYPE_UNKNOWN; |
956 | this_cpu_inc(lport->stats->LinkFailureCount); |
957 | fcoe_clean_pending_queue(lport); |
958 | wait_for_upload = 1; |
959 | } |
960 | } |
961 | } |
962 | mutex_unlock(lock: &bnx2fc_dev_lock); |
963 | |
964 | if (wait_for_upload) { |
965 | clear_bit(ADAPTER_STATE_READY, addr: &hba->adapter_state); |
966 | init_waitqueue_head(&hba->shutdown_wait); |
967 | BNX2FC_MISC_DBG("indicate_netevent " |
968 | "num_ofld_sess = %d\n" , |
969 | hba->num_ofld_sess); |
970 | hba->wait_for_link_down = 1; |
971 | wait_event_interruptible(hba->shutdown_wait, |
972 | (hba->num_ofld_sess == 0)); |
973 | BNX2FC_MISC_DBG("wakeup - num_ofld_sess = %d\n" , |
974 | hba->num_ofld_sess); |
975 | hba->wait_for_link_down = 0; |
976 | |
977 | if (signal_pending(current)) |
978 | flush_signals(current); |
979 | } |
980 | } |
981 | |
982 | static int bnx2fc_libfc_config(struct fc_lport *lport) |
983 | { |
984 | |
985 | /* Set the function pointers set by bnx2fc driver */ |
986 | memcpy(&lport->tt, &bnx2fc_libfc_fcn_templ, |
987 | sizeof(struct libfc_function_template)); |
988 | fc_elsct_init(lport); |
989 | fc_exch_init(lport); |
990 | fc_disc_init(lport); |
991 | fc_disc_config(lport, lport); |
992 | return 0; |
993 | } |
994 | |
995 | static int bnx2fc_em_config(struct fc_lport *lport, struct bnx2fc_hba *hba) |
996 | { |
997 | int fcoe_min_xid, fcoe_max_xid; |
998 | |
999 | fcoe_min_xid = hba->max_xid + 1; |
1000 | if (nr_cpu_ids <= 2) |
1001 | fcoe_max_xid = hba->max_xid + FCOE_XIDS_PER_CPU_OFFSET; |
1002 | else |
1003 | fcoe_max_xid = hba->max_xid + FCOE_MAX_XID_OFFSET; |
1004 | if (!fc_exch_mgr_alloc(lport, class: FC_CLASS_3, min_xid: fcoe_min_xid, |
1005 | max_xid: fcoe_max_xid, NULL)) { |
1006 | printk(KERN_ERR PFX "em_config:fc_exch_mgr_alloc failed\n" ); |
1007 | return -ENOMEM; |
1008 | } |
1009 | |
1010 | return 0; |
1011 | } |
1012 | |
1013 | static int bnx2fc_lport_config(struct fc_lport *lport) |
1014 | { |
1015 | lport->link_up = 0; |
1016 | lport->qfull = 0; |
1017 | lport->max_retry_count = BNX2FC_MAX_RETRY_CNT; |
1018 | lport->max_rport_retry_count = BNX2FC_MAX_RPORT_RETRY_CNT; |
1019 | lport->e_d_tov = 2 * 1000; |
1020 | lport->r_a_tov = 10 * 1000; |
1021 | |
1022 | lport->service_params = (FCP_SPPF_INIT_FCN | FCP_SPPF_RD_XRDY_DIS | |
1023 | FCP_SPPF_RETRY | FCP_SPPF_CONF_COMPL); |
1024 | lport->does_npiv = 1; |
1025 | |
1026 | memset(&lport->rnid_gen, 0, sizeof(struct fc_els_rnid_gen)); |
1027 | lport->rnid_gen.rnid_atype = BNX2FC_RNID_HBA; |
1028 | |
1029 | /* alloc stats structure */ |
1030 | if (fc_lport_init_stats(lport)) |
1031 | return -ENOMEM; |
1032 | |
1033 | /* Finish fc_lport configuration */ |
1034 | fc_lport_config(lport); |
1035 | |
1036 | return 0; |
1037 | } |
1038 | |
1039 | /** |
1040 | * bnx2fc_fip_recv - handle a received FIP frame. |
1041 | * |
1042 | * @skb: the received skb |
1043 | * @dev: associated &net_device |
1044 | * @ptype: the &packet_type structure which was used to register this handler. |
1045 | * @orig_dev: original receive &net_device, in case @ dev is a bond. |
1046 | * |
1047 | * Returns: 0 for success |
1048 | */ |
1049 | static int bnx2fc_fip_recv(struct sk_buff *skb, struct net_device *dev, |
1050 | struct packet_type *ptype, |
1051 | struct net_device *orig_dev) |
1052 | { |
1053 | struct bnx2fc_interface *interface; |
1054 | struct fcoe_ctlr *ctlr; |
1055 | interface = container_of(ptype, struct bnx2fc_interface, |
1056 | fip_packet_type); |
1057 | ctlr = bnx2fc_to_ctlr(interface); |
1058 | fcoe_ctlr_recv(ctlr, skb); |
1059 | return 0; |
1060 | } |
1061 | |
1062 | /** |
1063 | * bnx2fc_update_src_mac - Update Ethernet MAC filters. |
1064 | * |
1065 | * @lport: The local port |
1066 | * @addr: Location of data to copy |
1067 | * |
1068 | * Remove any previously-set unicast MAC filter. |
1069 | * Add secondary FCoE MAC address filter for our OUI. |
1070 | */ |
1071 | static void bnx2fc_update_src_mac(struct fc_lport *lport, u8 *addr) |
1072 | { |
1073 | struct fcoe_port *port = lport_priv(lport); |
1074 | |
1075 | memcpy(port->data_src_addr, addr, ETH_ALEN); |
1076 | } |
1077 | |
1078 | /** |
1079 | * bnx2fc_get_src_mac - return the ethernet source address for an lport |
1080 | * |
1081 | * @lport: libfc port |
1082 | */ |
1083 | static u8 *bnx2fc_get_src_mac(struct fc_lport *lport) |
1084 | { |
1085 | struct fcoe_port *port; |
1086 | |
1087 | port = (struct fcoe_port *)lport_priv(lport); |
1088 | return port->data_src_addr; |
1089 | } |
1090 | |
1091 | /** |
1092 | * bnx2fc_fip_send - send an Ethernet-encapsulated FIP frame. |
1093 | * |
1094 | * @fip: FCoE controller. |
1095 | * @skb: FIP Packet. |
1096 | */ |
1097 | static void bnx2fc_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb) |
1098 | { |
1099 | struct fip_header *fiph; |
1100 | struct ethhdr *eth_hdr; |
1101 | u16 op; |
1102 | u8 sub; |
1103 | |
1104 | fiph = (struct fip_header *) ((void *)skb->data + 2 * ETH_ALEN + 2); |
1105 | eth_hdr = (struct ethhdr *)skb_mac_header(skb); |
1106 | op = ntohs(fiph->fip_op); |
1107 | sub = fiph->fip_subcode; |
1108 | |
1109 | if (op == FIP_OP_CTRL && sub == FIP_SC_SOL && bnx2fc_log_fka) |
1110 | BNX2FC_MISC_DBG("Sending FKA from %pM to %pM.\n" , |
1111 | eth_hdr->h_source, eth_hdr->h_dest); |
1112 | |
1113 | skb->dev = bnx2fc_from_ctlr(fip)->netdev; |
1114 | dev_queue_xmit(skb); |
1115 | } |
1116 | |
1117 | static int bnx2fc_vport_create(struct fc_vport *vport, bool disabled) |
1118 | { |
1119 | struct Scsi_Host *shost = vport_to_shost(vport); |
1120 | struct fc_lport *n_port = shost_priv(shost); |
1121 | struct fcoe_port *port = lport_priv(lport: n_port); |
1122 | struct bnx2fc_interface *interface = port->priv; |
1123 | struct net_device *netdev = interface->netdev; |
1124 | struct fc_lport *vn_port; |
1125 | int rc; |
1126 | char buf[32]; |
1127 | |
1128 | rc = fcoe_validate_vport_create(vport); |
1129 | if (rc) { |
1130 | fcoe_wwn_to_str(wwn: vport->port_name, buf, len: sizeof(buf)); |
1131 | printk(KERN_ERR PFX "Failed to create vport, " |
1132 | "WWPN (0x%s) already exists\n" , |
1133 | buf); |
1134 | return rc; |
1135 | } |
1136 | |
1137 | if (!test_bit(BNX2FC_FLAG_FW_INIT_DONE, &interface->hba->flags)) { |
1138 | printk(KERN_ERR PFX "vn ports cannot be created on" |
1139 | "this interface\n" ); |
1140 | return -EIO; |
1141 | } |
1142 | rtnl_lock(); |
1143 | mutex_lock(&bnx2fc_dev_lock); |
1144 | vn_port = bnx2fc_if_create(interface, parent: &vport->dev, npiv: 1); |
1145 | mutex_unlock(lock: &bnx2fc_dev_lock); |
1146 | rtnl_unlock(); |
1147 | |
1148 | if (!vn_port) { |
1149 | printk(KERN_ERR PFX "bnx2fc_vport_create (%s) failed\n" , |
1150 | netdev->name); |
1151 | return -EIO; |
1152 | } |
1153 | |
1154 | if (bnx2fc_devloss_tmo) |
1155 | fc_host_dev_loss_tmo(vn_port->host) = bnx2fc_devloss_tmo; |
1156 | |
1157 | if (disabled) { |
1158 | fc_vport_set_state(vport, new_state: FC_VPORT_DISABLED); |
1159 | } else { |
1160 | vn_port->boot_time = jiffies; |
1161 | fc_lport_init(vn_port); |
1162 | fc_fabric_login(vn_port); |
1163 | fc_vport_setlink(vn_port); |
1164 | } |
1165 | return 0; |
1166 | } |
1167 | |
1168 | static void bnx2fc_free_vport(struct bnx2fc_hba *hba, struct fc_lport *lport) |
1169 | { |
1170 | struct bnx2fc_lport *blport, *tmp; |
1171 | |
1172 | spin_lock_bh(lock: &hba->hba_lock); |
1173 | list_for_each_entry_safe(blport, tmp, &hba->vports, list) { |
1174 | if (blport->lport == lport) { |
1175 | list_del(entry: &blport->list); |
1176 | kfree(objp: blport); |
1177 | } |
1178 | } |
1179 | spin_unlock_bh(lock: &hba->hba_lock); |
1180 | } |
1181 | |
1182 | static int bnx2fc_vport_destroy(struct fc_vport *vport) |
1183 | { |
1184 | struct Scsi_Host *shost = vport_to_shost(vport); |
1185 | struct fc_lport *n_port = shost_priv(shost); |
1186 | struct fc_lport *vn_port = vport->dd_data; |
1187 | struct fcoe_port *port = lport_priv(lport: vn_port); |
1188 | struct bnx2fc_interface *interface = port->priv; |
1189 | struct fc_lport *v_port; |
1190 | bool found = false; |
1191 | |
1192 | mutex_lock(&n_port->lp_mutex); |
1193 | list_for_each_entry(v_port, &n_port->vports, list) |
1194 | if (v_port->vport == vport) { |
1195 | found = true; |
1196 | break; |
1197 | } |
1198 | |
1199 | if (!found) { |
1200 | mutex_unlock(lock: &n_port->lp_mutex); |
1201 | return -ENOENT; |
1202 | } |
1203 | list_del(entry: &vn_port->list); |
1204 | mutex_unlock(lock: &n_port->lp_mutex); |
1205 | bnx2fc_free_vport(hba: interface->hba, lport: port->lport); |
1206 | bnx2fc_port_shutdown(lport: port->lport); |
1207 | bnx2fc_port_destroy(port); |
1208 | bnx2fc_interface_put(interface); |
1209 | return 0; |
1210 | } |
1211 | |
1212 | static int bnx2fc_vport_disable(struct fc_vport *vport, bool disable) |
1213 | { |
1214 | struct fc_lport *lport = vport->dd_data; |
1215 | |
1216 | if (disable) { |
1217 | fc_vport_set_state(vport, new_state: FC_VPORT_DISABLED); |
1218 | fc_fabric_logoff(lport); |
1219 | } else { |
1220 | lport->boot_time = jiffies; |
1221 | fc_fabric_login(lport); |
1222 | fc_vport_setlink(lport); |
1223 | } |
1224 | return 0; |
1225 | } |
1226 | |
1227 | |
1228 | static int bnx2fc_interface_setup(struct bnx2fc_interface *interface) |
1229 | { |
1230 | struct net_device *netdev = interface->netdev; |
1231 | struct net_device *physdev = interface->hba->phys_dev; |
1232 | struct fcoe_ctlr *ctlr = bnx2fc_to_ctlr(interface); |
1233 | struct netdev_hw_addr *ha; |
1234 | int sel_san_mac = 0; |
1235 | |
1236 | /* setup Source MAC Address */ |
1237 | rcu_read_lock(); |
1238 | for_each_dev_addr(physdev, ha) { |
1239 | BNX2FC_MISC_DBG("net_config: ha->type = %d, fip_mac = " , |
1240 | ha->type); |
1241 | printk(KERN_INFO "%2x:%2x:%2x:%2x:%2x:%2x\n" , ha->addr[0], |
1242 | ha->addr[1], ha->addr[2], ha->addr[3], |
1243 | ha->addr[4], ha->addr[5]); |
1244 | |
1245 | if ((ha->type == NETDEV_HW_ADDR_T_SAN) && |
1246 | (is_valid_ether_addr(addr: ha->addr))) { |
1247 | memcpy(ctlr->ctl_src_addr, ha->addr, |
1248 | ETH_ALEN); |
1249 | sel_san_mac = 1; |
1250 | BNX2FC_MISC_DBG("Found SAN MAC\n" ); |
1251 | } |
1252 | } |
1253 | rcu_read_unlock(); |
1254 | |
1255 | if (!sel_san_mac) |
1256 | return -ENODEV; |
1257 | |
1258 | interface->fip_packet_type.func = bnx2fc_fip_recv; |
1259 | interface->fip_packet_type.type = htons(ETH_P_FIP); |
1260 | interface->fip_packet_type.dev = netdev; |
1261 | dev_add_pack(pt: &interface->fip_packet_type); |
1262 | |
1263 | interface->fcoe_packet_type.func = bnx2fc_rcv; |
1264 | interface->fcoe_packet_type.type = __constant_htons(ETH_P_FCOE); |
1265 | interface->fcoe_packet_type.dev = netdev; |
1266 | dev_add_pack(pt: &interface->fcoe_packet_type); |
1267 | |
1268 | return 0; |
1269 | } |
1270 | |
1271 | static int bnx2fc_attach_transport(void) |
1272 | { |
1273 | bnx2fc_transport_template = |
1274 | fc_attach_transport(&bnx2fc_transport_function); |
1275 | |
1276 | if (bnx2fc_transport_template == NULL) { |
1277 | printk(KERN_ERR PFX "Failed to attach FC transport\n" ); |
1278 | return -ENODEV; |
1279 | } |
1280 | |
1281 | bnx2fc_vport_xport_template = |
1282 | fc_attach_transport(&bnx2fc_vport_xport_function); |
1283 | if (bnx2fc_vport_xport_template == NULL) { |
1284 | printk(KERN_ERR PFX |
1285 | "Failed to attach FC transport for vport\n" ); |
1286 | fc_release_transport(bnx2fc_transport_template); |
1287 | bnx2fc_transport_template = NULL; |
1288 | return -ENODEV; |
1289 | } |
1290 | return 0; |
1291 | } |
1292 | static void bnx2fc_release_transport(void) |
1293 | { |
1294 | fc_release_transport(bnx2fc_transport_template); |
1295 | fc_release_transport(bnx2fc_vport_xport_template); |
1296 | bnx2fc_transport_template = NULL; |
1297 | bnx2fc_vport_xport_template = NULL; |
1298 | } |
1299 | |
1300 | static void bnx2fc_interface_release(struct kref *kref) |
1301 | { |
1302 | struct fcoe_ctlr_device *ctlr_dev; |
1303 | struct bnx2fc_interface *interface; |
1304 | struct fcoe_ctlr *ctlr; |
1305 | struct net_device *netdev; |
1306 | |
1307 | interface = container_of(kref, struct bnx2fc_interface, kref); |
1308 | BNX2FC_MISC_DBG("Interface is being released\n" ); |
1309 | |
1310 | ctlr = bnx2fc_to_ctlr(interface); |
1311 | ctlr_dev = fcoe_ctlr_to_ctlr_dev(ctlr); |
1312 | netdev = interface->netdev; |
1313 | |
1314 | /* tear-down FIP controller */ |
1315 | if (test_and_clear_bit(BNX2FC_CTLR_INIT_DONE, addr: &interface->if_flags)) |
1316 | fcoe_ctlr_destroy(ctlr); |
1317 | |
1318 | fcoe_ctlr_device_delete(ctlr_dev); |
1319 | |
1320 | dev_put(dev: netdev); |
1321 | module_put(THIS_MODULE); |
1322 | } |
1323 | |
1324 | static inline void bnx2fc_interface_get(struct bnx2fc_interface *interface) |
1325 | { |
1326 | kref_get(kref: &interface->kref); |
1327 | } |
1328 | |
1329 | static inline void bnx2fc_interface_put(struct bnx2fc_interface *interface) |
1330 | { |
1331 | kref_put(kref: &interface->kref, release: bnx2fc_interface_release); |
1332 | } |
1333 | static void bnx2fc_hba_destroy(struct bnx2fc_hba *hba) |
1334 | { |
1335 | /* Free the command manager */ |
1336 | if (hba->cmd_mgr) { |
1337 | bnx2fc_cmd_mgr_free(cmgr: hba->cmd_mgr); |
1338 | hba->cmd_mgr = NULL; |
1339 | } |
1340 | kfree(objp: hba->tgt_ofld_list); |
1341 | bnx2fc_unbind_pcidev(hba); |
1342 | kfree(objp: hba); |
1343 | } |
1344 | |
1345 | /** |
1346 | * bnx2fc_hba_create - create a new bnx2fc hba |
1347 | * |
1348 | * @cnic: pointer to cnic device |
1349 | * |
1350 | * Creates a new FCoE hba on the given device. |
1351 | * |
1352 | */ |
1353 | static struct bnx2fc_hba *bnx2fc_hba_create(struct cnic_dev *cnic) |
1354 | { |
1355 | struct bnx2fc_hba *hba; |
1356 | struct fcoe_capabilities *fcoe_cap; |
1357 | int rc; |
1358 | |
1359 | hba = kzalloc(size: sizeof(*hba), GFP_KERNEL); |
1360 | if (!hba) { |
1361 | printk(KERN_ERR PFX "Unable to allocate hba structure\n" ); |
1362 | return NULL; |
1363 | } |
1364 | spin_lock_init(&hba->hba_lock); |
1365 | mutex_init(&hba->hba_mutex); |
1366 | mutex_init(&hba->hba_stats_mutex); |
1367 | |
1368 | hba->cnic = cnic; |
1369 | |
1370 | hba->max_tasks = cnic->max_fcoe_exchanges; |
1371 | hba->elstm_xids = (hba->max_tasks / 2); |
1372 | hba->max_outstanding_cmds = hba->elstm_xids; |
1373 | hba->max_xid = (hba->max_tasks - 1); |
1374 | |
1375 | rc = bnx2fc_bind_pcidev(hba); |
1376 | if (rc) { |
1377 | printk(KERN_ERR PFX "create_adapter: bind error\n" ); |
1378 | goto bind_err; |
1379 | } |
1380 | hba->phys_dev = cnic->netdev; |
1381 | hba->next_conn_id = 0; |
1382 | |
1383 | hba->tgt_ofld_list = |
1384 | kcalloc(BNX2FC_NUM_MAX_SESS, size: sizeof(struct bnx2fc_rport *), |
1385 | GFP_KERNEL); |
1386 | if (!hba->tgt_ofld_list) { |
1387 | printk(KERN_ERR PFX "Unable to allocate tgt offload list\n" ); |
1388 | goto tgtofld_err; |
1389 | } |
1390 | |
1391 | hba->num_ofld_sess = 0; |
1392 | |
1393 | hba->cmd_mgr = bnx2fc_cmd_mgr_alloc(hba); |
1394 | if (!hba->cmd_mgr) { |
1395 | printk(KERN_ERR PFX "em_config:bnx2fc_cmd_mgr_alloc failed\n" ); |
1396 | goto cmgr_err; |
1397 | } |
1398 | fcoe_cap = &hba->fcoe_cap; |
1399 | |
1400 | fcoe_cap->capability1 = BNX2FC_TM_MAX_SQES << |
1401 | FCOE_IOS_PER_CONNECTION_SHIFT; |
1402 | fcoe_cap->capability1 |= BNX2FC_NUM_MAX_SESS << |
1403 | FCOE_LOGINS_PER_PORT_SHIFT; |
1404 | fcoe_cap->capability2 = hba->max_outstanding_cmds << |
1405 | FCOE_NUMBER_OF_EXCHANGES_SHIFT; |
1406 | fcoe_cap->capability2 |= BNX2FC_MAX_NPIV << |
1407 | FCOE_NPIV_WWN_PER_PORT_SHIFT; |
1408 | fcoe_cap->capability3 = BNX2FC_NUM_MAX_SESS << |
1409 | FCOE_TARGETS_SUPPORTED_SHIFT; |
1410 | fcoe_cap->capability3 |= hba->max_outstanding_cmds << |
1411 | FCOE_OUTSTANDING_COMMANDS_SHIFT; |
1412 | fcoe_cap->capability4 = FCOE_CAPABILITY4_STATEFUL; |
1413 | |
1414 | init_waitqueue_head(&hba->shutdown_wait); |
1415 | init_waitqueue_head(&hba->destroy_wait); |
1416 | INIT_LIST_HEAD(list: &hba->vports); |
1417 | |
1418 | return hba; |
1419 | |
1420 | cmgr_err: |
1421 | kfree(objp: hba->tgt_ofld_list); |
1422 | tgtofld_err: |
1423 | bnx2fc_unbind_pcidev(hba); |
1424 | bind_err: |
1425 | kfree(objp: hba); |
1426 | return NULL; |
1427 | } |
1428 | |
1429 | static struct bnx2fc_interface * |
1430 | bnx2fc_interface_create(struct bnx2fc_hba *hba, |
1431 | struct net_device *netdev, |
1432 | enum fip_mode fip_mode) |
1433 | { |
1434 | struct fcoe_ctlr_device *ctlr_dev; |
1435 | struct bnx2fc_interface *interface; |
1436 | struct fcoe_ctlr *ctlr; |
1437 | int size; |
1438 | int rc = 0; |
1439 | |
1440 | size = (sizeof(*interface) + sizeof(struct fcoe_ctlr)); |
1441 | ctlr_dev = fcoe_ctlr_device_add(parent: &netdev->dev, f: &bnx2fc_fcoe_sysfs_templ, |
1442 | priv_size: size); |
1443 | if (!ctlr_dev) { |
1444 | printk(KERN_ERR PFX "Unable to allocate interface structure\n" ); |
1445 | return NULL; |
1446 | } |
1447 | ctlr = fcoe_ctlr_device_priv(ctlr: ctlr_dev); |
1448 | ctlr->cdev = ctlr_dev; |
1449 | interface = fcoe_ctlr_priv(ctlr); |
1450 | dev_hold(dev: netdev); |
1451 | kref_init(kref: &interface->kref); |
1452 | interface->hba = hba; |
1453 | interface->netdev = netdev; |
1454 | |
1455 | /* Initialize FIP */ |
1456 | fcoe_ctlr_init(ctlr, fip_mode); |
1457 | ctlr->send = bnx2fc_fip_send; |
1458 | ctlr->update_mac = bnx2fc_update_src_mac; |
1459 | ctlr->get_src_addr = bnx2fc_get_src_mac; |
1460 | set_bit(BNX2FC_CTLR_INIT_DONE, addr: &interface->if_flags); |
1461 | |
1462 | rc = bnx2fc_interface_setup(interface); |
1463 | if (!rc) |
1464 | return interface; |
1465 | |
1466 | fcoe_ctlr_destroy(ctlr); |
1467 | dev_put(dev: netdev); |
1468 | fcoe_ctlr_device_delete(ctlr_dev); |
1469 | return NULL; |
1470 | } |
1471 | |
1472 | /** |
1473 | * bnx2fc_if_create - Create FCoE instance on a given interface |
1474 | * |
1475 | * @interface: FCoE interface to create a local port on |
1476 | * @parent: Device pointer to be the parent in sysfs for the SCSI host |
1477 | * @npiv: Indicates if the port is vport or not |
1478 | * |
1479 | * Creates a fc_lport instance and a Scsi_Host instance and configure them. |
1480 | * |
1481 | * Returns: Allocated fc_lport or an error pointer |
1482 | */ |
1483 | static struct fc_lport *bnx2fc_if_create(struct bnx2fc_interface *interface, |
1484 | struct device *parent, int npiv) |
1485 | { |
1486 | struct fcoe_ctlr *ctlr = bnx2fc_to_ctlr(interface); |
1487 | struct fc_lport *lport, *n_port; |
1488 | struct fcoe_port *port; |
1489 | struct Scsi_Host *shost; |
1490 | struct fc_vport *vport = dev_to_vport(parent); |
1491 | struct bnx2fc_lport *blport; |
1492 | struct bnx2fc_hba *hba = interface->hba; |
1493 | int rc = 0; |
1494 | |
1495 | blport = kzalloc(size: sizeof(struct bnx2fc_lport), GFP_KERNEL); |
1496 | if (!blport) { |
1497 | BNX2FC_HBA_DBG(lport: ctlr->lp, fmt: "Unable to alloc blport\n" ); |
1498 | return NULL; |
1499 | } |
1500 | |
1501 | /* Allocate Scsi_Host structure */ |
1502 | bnx2fc_shost_template.can_queue = hba->max_outstanding_cmds; |
1503 | if (!npiv) |
1504 | lport = libfc_host_alloc(sht: &bnx2fc_shost_template, priv_size: sizeof(*port)); |
1505 | else |
1506 | lport = libfc_vport_create(vport, privsize: sizeof(*port)); |
1507 | |
1508 | if (!lport) { |
1509 | printk(KERN_ERR PFX "could not allocate scsi host structure\n" ); |
1510 | goto free_blport; |
1511 | } |
1512 | shost = lport->host; |
1513 | port = lport_priv(lport); |
1514 | port->lport = lport; |
1515 | port->priv = interface; |
1516 | port->get_netdev = bnx2fc_netdev; |
1517 | |
1518 | /* Configure fcoe_port */ |
1519 | rc = bnx2fc_lport_config(lport); |
1520 | if (rc) |
1521 | goto lp_config_err; |
1522 | |
1523 | if (npiv) { |
1524 | printk(KERN_ERR PFX "Setting vport names, 0x%llX 0x%llX\n" , |
1525 | vport->node_name, vport->port_name); |
1526 | fc_set_wwnn(lport, wwnn: vport->node_name); |
1527 | fc_set_wwpn(lport, wwpn: vport->port_name); |
1528 | } |
1529 | /* Configure netdev and networking properties of the lport */ |
1530 | rc = bnx2fc_net_config(lport, netdev: interface->netdev); |
1531 | if (rc) { |
1532 | printk(KERN_ERR PFX "Error on bnx2fc_net_config\n" ); |
1533 | goto lp_config_err; |
1534 | } |
1535 | |
1536 | rc = bnx2fc_shost_config(lport, dev: parent); |
1537 | if (rc) { |
1538 | printk(KERN_ERR PFX "Couldn't configure shost for %s\n" , |
1539 | interface->netdev->name); |
1540 | goto lp_config_err; |
1541 | } |
1542 | |
1543 | /* Initialize the libfc library */ |
1544 | rc = bnx2fc_libfc_config(lport); |
1545 | if (rc) { |
1546 | printk(KERN_ERR PFX "Couldn't configure libfc\n" ); |
1547 | goto shost_err; |
1548 | } |
1549 | fc_host_port_type(lport->host) = FC_PORTTYPE_UNKNOWN; |
1550 | |
1551 | if (bnx2fc_devloss_tmo) |
1552 | fc_host_dev_loss_tmo(shost) = bnx2fc_devloss_tmo; |
1553 | |
1554 | /* Allocate exchange manager */ |
1555 | if (!npiv) |
1556 | rc = bnx2fc_em_config(lport, hba); |
1557 | else { |
1558 | shost = vport_to_shost(vport); |
1559 | n_port = shost_priv(shost); |
1560 | rc = fc_exch_mgr_list_clone(src: n_port, dst: lport); |
1561 | } |
1562 | |
1563 | if (rc) { |
1564 | printk(KERN_ERR PFX "Error on bnx2fc_em_config\n" ); |
1565 | goto shost_err; |
1566 | } |
1567 | |
1568 | bnx2fc_interface_get(interface); |
1569 | |
1570 | spin_lock_bh(lock: &hba->hba_lock); |
1571 | blport->lport = lport; |
1572 | list_add_tail(new: &blport->list, head: &hba->vports); |
1573 | spin_unlock_bh(lock: &hba->hba_lock); |
1574 | |
1575 | return lport; |
1576 | |
1577 | shost_err: |
1578 | scsi_remove_host(shost); |
1579 | lp_config_err: |
1580 | scsi_host_put(t: lport->host); |
1581 | free_blport: |
1582 | kfree(objp: blport); |
1583 | return NULL; |
1584 | } |
1585 | |
1586 | static void bnx2fc_net_cleanup(struct bnx2fc_interface *interface) |
1587 | { |
1588 | /* Dont listen for Ethernet packets anymore */ |
1589 | __dev_remove_pack(pt: &interface->fcoe_packet_type); |
1590 | __dev_remove_pack(pt: &interface->fip_packet_type); |
1591 | synchronize_net(); |
1592 | } |
1593 | |
1594 | static void bnx2fc_interface_cleanup(struct bnx2fc_interface *interface) |
1595 | { |
1596 | struct fcoe_ctlr *ctlr = bnx2fc_to_ctlr(interface); |
1597 | struct fc_lport *lport = ctlr->lp; |
1598 | struct fcoe_port *port = lport_priv(lport); |
1599 | struct bnx2fc_hba *hba = interface->hba; |
1600 | |
1601 | /* Stop the transmit retry timer */ |
1602 | del_timer_sync(timer: &port->timer); |
1603 | |
1604 | /* Free existing transmit skbs */ |
1605 | fcoe_clean_pending_queue(lport); |
1606 | |
1607 | bnx2fc_net_cleanup(interface); |
1608 | |
1609 | bnx2fc_free_vport(hba, lport); |
1610 | } |
1611 | |
1612 | static void bnx2fc_if_destroy(struct fc_lport *lport) |
1613 | { |
1614 | |
1615 | /* Free queued packets for the receive thread */ |
1616 | bnx2fc_clean_rx_queue(lp: lport); |
1617 | |
1618 | /* Detach from scsi-ml */ |
1619 | fc_remove_host(lport->host); |
1620 | scsi_remove_host(lport->host); |
1621 | |
1622 | /* |
1623 | * Note that only the physical lport will have the exchange manager. |
1624 | * for vports, this function is NOP |
1625 | */ |
1626 | fc_exch_mgr_free(lport); |
1627 | |
1628 | /* Free memory used by statistical counters */ |
1629 | fc_lport_free_stats(lport); |
1630 | |
1631 | /* Release Scsi_Host */ |
1632 | scsi_host_put(t: lport->host); |
1633 | } |
1634 | |
1635 | static void __bnx2fc_destroy(struct bnx2fc_interface *interface) |
1636 | { |
1637 | struct fcoe_ctlr *ctlr = bnx2fc_to_ctlr(interface); |
1638 | struct fc_lport *lport = ctlr->lp; |
1639 | struct fcoe_port *port = lport_priv(lport); |
1640 | |
1641 | bnx2fc_interface_cleanup(interface); |
1642 | bnx2fc_stop(interface); |
1643 | list_del(entry: &interface->list); |
1644 | bnx2fc_port_destroy(port); |
1645 | bnx2fc_interface_put(interface); |
1646 | } |
1647 | |
1648 | /** |
1649 | * bnx2fc_destroy - Destroy a bnx2fc FCoE interface |
1650 | * |
1651 | * @netdev: The net device that the FCoE interface is on |
1652 | * |
1653 | * Called from sysfs. |
1654 | * |
1655 | * Returns: 0 for success |
1656 | */ |
1657 | static int bnx2fc_destroy(struct net_device *netdev) |
1658 | { |
1659 | struct bnx2fc_interface *interface = NULL; |
1660 | struct workqueue_struct *timer_work_queue; |
1661 | struct fcoe_ctlr *ctlr; |
1662 | int rc = 0; |
1663 | |
1664 | rtnl_lock(); |
1665 | mutex_lock(&bnx2fc_dev_lock); |
1666 | |
1667 | interface = bnx2fc_interface_lookup(phys_dev: netdev); |
1668 | ctlr = bnx2fc_to_ctlr(interface); |
1669 | if (!interface || !ctlr->lp) { |
1670 | rc = -ENODEV; |
1671 | printk(KERN_ERR PFX "bnx2fc_destroy: interface or lport not found\n" ); |
1672 | goto netdev_err; |
1673 | } |
1674 | |
1675 | timer_work_queue = interface->timer_work_queue; |
1676 | __bnx2fc_destroy(interface); |
1677 | destroy_workqueue(wq: timer_work_queue); |
1678 | |
1679 | netdev_err: |
1680 | mutex_unlock(lock: &bnx2fc_dev_lock); |
1681 | rtnl_unlock(); |
1682 | return rc; |
1683 | } |
1684 | |
1685 | static void bnx2fc_port_destroy(struct fcoe_port *port) |
1686 | { |
1687 | struct fc_lport *lport; |
1688 | |
1689 | lport = port->lport; |
1690 | BNX2FC_HBA_DBG(lport, fmt: "Entered %s, destroying lport %p\n" , __func__, lport); |
1691 | |
1692 | bnx2fc_if_destroy(lport); |
1693 | } |
1694 | |
1695 | static void bnx2fc_unbind_adapter_devices(struct bnx2fc_hba *hba) |
1696 | { |
1697 | bnx2fc_free_fw_resc(hba); |
1698 | bnx2fc_free_task_ctx(hba); |
1699 | } |
1700 | |
1701 | /** |
1702 | * bnx2fc_bind_adapter_devices - binds bnx2fc adapter with the associated |
1703 | * pci structure |
1704 | * |
1705 | * @hba: Adapter instance |
1706 | */ |
1707 | static int bnx2fc_bind_adapter_devices(struct bnx2fc_hba *hba) |
1708 | { |
1709 | if (bnx2fc_setup_task_ctx(hba)) |
1710 | goto mem_err; |
1711 | |
1712 | if (bnx2fc_setup_fw_resc(hba)) |
1713 | goto mem_err; |
1714 | |
1715 | return 0; |
1716 | mem_err: |
1717 | bnx2fc_unbind_adapter_devices(hba); |
1718 | return -ENOMEM; |
1719 | } |
1720 | |
1721 | static int bnx2fc_bind_pcidev(struct bnx2fc_hba *hba) |
1722 | { |
1723 | struct cnic_dev *cnic; |
1724 | struct pci_dev *pdev; |
1725 | |
1726 | if (!hba->cnic) { |
1727 | printk(KERN_ERR PFX "cnic is NULL\n" ); |
1728 | return -ENODEV; |
1729 | } |
1730 | cnic = hba->cnic; |
1731 | pdev = hba->pcidev = cnic->pcidev; |
1732 | if (!hba->pcidev) |
1733 | return -ENODEV; |
1734 | |
1735 | switch (pdev->device) { |
1736 | case PCI_DEVICE_ID_NX2_57710: |
1737 | strscpy(hba->chip_num, "BCM57710" , sizeof(hba->chip_num)); |
1738 | break; |
1739 | case PCI_DEVICE_ID_NX2_57711: |
1740 | strscpy(hba->chip_num, "BCM57711" , sizeof(hba->chip_num)); |
1741 | break; |
1742 | case PCI_DEVICE_ID_NX2_57712: |
1743 | case PCI_DEVICE_ID_NX2_57712_MF: |
1744 | case PCI_DEVICE_ID_NX2_57712_VF: |
1745 | strscpy(hba->chip_num, "BCM57712" , sizeof(hba->chip_num)); |
1746 | break; |
1747 | case PCI_DEVICE_ID_NX2_57800: |
1748 | case PCI_DEVICE_ID_NX2_57800_MF: |
1749 | case PCI_DEVICE_ID_NX2_57800_VF: |
1750 | strscpy(hba->chip_num, "BCM57800" , sizeof(hba->chip_num)); |
1751 | break; |
1752 | case PCI_DEVICE_ID_NX2_57810: |
1753 | case PCI_DEVICE_ID_NX2_57810_MF: |
1754 | case PCI_DEVICE_ID_NX2_57810_VF: |
1755 | strscpy(hba->chip_num, "BCM57810" , sizeof(hba->chip_num)); |
1756 | break; |
1757 | case PCI_DEVICE_ID_NX2_57840: |
1758 | case PCI_DEVICE_ID_NX2_57840_MF: |
1759 | case PCI_DEVICE_ID_NX2_57840_VF: |
1760 | case PCI_DEVICE_ID_NX2_57840_2_20: |
1761 | case PCI_DEVICE_ID_NX2_57840_4_10: |
1762 | strscpy(hba->chip_num, "BCM57840" , sizeof(hba->chip_num)); |
1763 | break; |
1764 | default: |
1765 | pr_err(PFX "Unknown device id 0x%x\n" , pdev->device); |
1766 | break; |
1767 | } |
1768 | pci_dev_get(dev: hba->pcidev); |
1769 | return 0; |
1770 | } |
1771 | |
1772 | static void bnx2fc_unbind_pcidev(struct bnx2fc_hba *hba) |
1773 | { |
1774 | if (hba->pcidev) { |
1775 | hba->chip_num[0] = '\0'; |
1776 | pci_dev_put(dev: hba->pcidev); |
1777 | } |
1778 | hba->pcidev = NULL; |
1779 | } |
1780 | |
1781 | /** |
1782 | * bnx2fc_ulp_get_stats - cnic callback to populate FCoE stats |
1783 | * |
1784 | * @handle: transport handle pointing to adapter structure |
1785 | */ |
1786 | static int bnx2fc_ulp_get_stats(void *handle) |
1787 | { |
1788 | struct bnx2fc_hba *hba = handle; |
1789 | struct cnic_dev *cnic; |
1790 | struct fcoe_stats_info *stats_addr; |
1791 | |
1792 | if (!hba) |
1793 | return -EINVAL; |
1794 | |
1795 | cnic = hba->cnic; |
1796 | stats_addr = &cnic->stats_addr->fcoe_stat; |
1797 | if (!stats_addr) |
1798 | return -EINVAL; |
1799 | |
1800 | strscpy(stats_addr->version, BNX2FC_VERSION, |
1801 | sizeof(stats_addr->version)); |
1802 | stats_addr->txq_size = BNX2FC_SQ_WQES_MAX; |
1803 | stats_addr->rxq_size = BNX2FC_CQ_WQES_MAX; |
1804 | |
1805 | return 0; |
1806 | } |
1807 | |
1808 | |
1809 | /** |
1810 | * bnx2fc_ulp_start - cnic callback to initialize & start adapter instance |
1811 | * |
1812 | * @handle: transport handle pointing to adapter structure |
1813 | * |
1814 | * This function maps adapter structure to pcidev structure and initiates |
1815 | * firmware handshake to enable/initialize on-chip FCoE components. |
1816 | * This bnx2fc - cnic interface api callback is used after following |
1817 | * conditions are met - |
1818 | * a) underlying network interface is up (marked by event NETDEV_UP |
1819 | * from netdev |
1820 | * b) bnx2fc adatper structure is registered. |
1821 | */ |
1822 | static void bnx2fc_ulp_start(void *handle) |
1823 | { |
1824 | struct bnx2fc_hba *hba = handle; |
1825 | struct bnx2fc_interface *interface; |
1826 | struct fcoe_ctlr *ctlr; |
1827 | struct fc_lport *lport; |
1828 | |
1829 | mutex_lock(&bnx2fc_dev_lock); |
1830 | |
1831 | if (!test_bit(BNX2FC_FLAG_FW_INIT_DONE, &hba->flags)) |
1832 | bnx2fc_fw_init(hba); |
1833 | |
1834 | BNX2FC_MISC_DBG("bnx2fc started.\n" ); |
1835 | |
1836 | list_for_each_entry(interface, &if_list, list) { |
1837 | if (interface->hba == hba) { |
1838 | ctlr = bnx2fc_to_ctlr(interface); |
1839 | lport = ctlr->lp; |
1840 | /* Kick off Fabric discovery*/ |
1841 | printk(KERN_ERR PFX "ulp_init: start discovery\n" ); |
1842 | lport->tt.frame_send = bnx2fc_xmit; |
1843 | bnx2fc_start_disc(interface); |
1844 | } |
1845 | } |
1846 | |
1847 | mutex_unlock(lock: &bnx2fc_dev_lock); |
1848 | } |
1849 | |
1850 | static void bnx2fc_port_shutdown(struct fc_lport *lport) |
1851 | { |
1852 | BNX2FC_MISC_DBG("Entered %s\n" , __func__); |
1853 | fc_fabric_logoff(lport); |
1854 | fc_lport_destroy(lport); |
1855 | } |
1856 | |
1857 | static void bnx2fc_stop(struct bnx2fc_interface *interface) |
1858 | { |
1859 | struct fcoe_ctlr *ctlr = bnx2fc_to_ctlr(interface); |
1860 | struct fc_lport *lport; |
1861 | struct fc_lport *vport; |
1862 | |
1863 | if (!test_bit(BNX2FC_FLAG_FW_INIT_DONE, &interface->hba->flags)) |
1864 | return; |
1865 | |
1866 | lport = ctlr->lp; |
1867 | bnx2fc_port_shutdown(lport); |
1868 | |
1869 | mutex_lock(&lport->lp_mutex); |
1870 | list_for_each_entry(vport, &lport->vports, list) |
1871 | fc_host_port_type(vport->host) = |
1872 | FC_PORTTYPE_UNKNOWN; |
1873 | mutex_unlock(lock: &lport->lp_mutex); |
1874 | fc_host_port_type(lport->host) = FC_PORTTYPE_UNKNOWN; |
1875 | fcoe_ctlr_link_down(ctlr); |
1876 | fcoe_clean_pending_queue(lport); |
1877 | } |
1878 | |
1879 | static int bnx2fc_fw_init(struct bnx2fc_hba *hba) |
1880 | { |
1881 | #define BNX2FC_INIT_POLL_TIME (1000 / HZ) |
1882 | int rc = -1; |
1883 | int i = HZ; |
1884 | |
1885 | rc = bnx2fc_bind_adapter_devices(hba); |
1886 | if (rc) { |
1887 | printk(KERN_ALERT PFX |
1888 | "bnx2fc_bind_adapter_devices failed - rc = %d\n" , rc); |
1889 | goto err_out; |
1890 | } |
1891 | |
1892 | rc = bnx2fc_send_fw_fcoe_init_msg(hba); |
1893 | if (rc) { |
1894 | printk(KERN_ALERT PFX |
1895 | "bnx2fc_send_fw_fcoe_init_msg failed - rc = %d\n" , rc); |
1896 | goto err_unbind; |
1897 | } |
1898 | |
1899 | /* |
1900 | * Wait until the adapter init message is complete, and adapter |
1901 | * state is UP. |
1902 | */ |
1903 | while (!test_bit(ADAPTER_STATE_UP, &hba->adapter_state) && i--) |
1904 | msleep(BNX2FC_INIT_POLL_TIME); |
1905 | |
1906 | if (!test_bit(ADAPTER_STATE_UP, &hba->adapter_state)) { |
1907 | printk(KERN_ERR PFX "bnx2fc_start: %s failed to initialize. " |
1908 | "Ignoring...\n" , |
1909 | hba->cnic->netdev->name); |
1910 | rc = -1; |
1911 | goto err_unbind; |
1912 | } |
1913 | |
1914 | |
1915 | set_bit(BNX2FC_FLAG_FW_INIT_DONE, addr: &hba->flags); |
1916 | return 0; |
1917 | |
1918 | err_unbind: |
1919 | bnx2fc_unbind_adapter_devices(hba); |
1920 | err_out: |
1921 | return rc; |
1922 | } |
1923 | |
1924 | static void bnx2fc_fw_destroy(struct bnx2fc_hba *hba) |
1925 | { |
1926 | if (test_and_clear_bit(BNX2FC_FLAG_FW_INIT_DONE, addr: &hba->flags)) { |
1927 | if (bnx2fc_send_fw_fcoe_destroy_msg(hba) == 0) { |
1928 | timer_setup(&hba->destroy_timer, bnx2fc_destroy_timer, |
1929 | 0); |
1930 | hba->destroy_timer.expires = BNX2FC_FW_TIMEOUT + |
1931 | jiffies; |
1932 | add_timer(timer: &hba->destroy_timer); |
1933 | wait_event_interruptible(hba->destroy_wait, |
1934 | test_bit(BNX2FC_FLAG_DESTROY_CMPL, |
1935 | &hba->flags)); |
1936 | clear_bit(BNX2FC_FLAG_DESTROY_CMPL, addr: &hba->flags); |
1937 | /* This should never happen */ |
1938 | if (signal_pending(current)) |
1939 | flush_signals(current); |
1940 | |
1941 | del_timer_sync(timer: &hba->destroy_timer); |
1942 | } |
1943 | bnx2fc_unbind_adapter_devices(hba); |
1944 | } |
1945 | } |
1946 | |
1947 | /** |
1948 | * bnx2fc_ulp_stop - cnic callback to shutdown adapter instance |
1949 | * |
1950 | * @handle: transport handle pointing to adapter structure |
1951 | * |
1952 | * Driver checks if adapter is already in shutdown mode, if not start |
1953 | * the shutdown process. |
1954 | */ |
1955 | static void bnx2fc_ulp_stop(void *handle) |
1956 | { |
1957 | struct bnx2fc_hba *hba = handle; |
1958 | struct bnx2fc_interface *interface; |
1959 | |
1960 | printk(KERN_ERR "ULP_STOP\n" ); |
1961 | |
1962 | mutex_lock(&bnx2fc_dev_lock); |
1963 | if (!test_bit(BNX2FC_FLAG_FW_INIT_DONE, &hba->flags)) |
1964 | goto exit; |
1965 | list_for_each_entry(interface, &if_list, list) { |
1966 | if (interface->hba == hba) |
1967 | bnx2fc_stop(interface); |
1968 | } |
1969 | BUG_ON(hba->num_ofld_sess != 0); |
1970 | |
1971 | mutex_lock(&hba->hba_mutex); |
1972 | clear_bit(ADAPTER_STATE_UP, addr: &hba->adapter_state); |
1973 | clear_bit(ADAPTER_STATE_GOING_DOWN, |
1974 | addr: &hba->adapter_state); |
1975 | |
1976 | clear_bit(ADAPTER_STATE_READY, addr: &hba->adapter_state); |
1977 | mutex_unlock(lock: &hba->hba_mutex); |
1978 | |
1979 | bnx2fc_fw_destroy(hba); |
1980 | exit: |
1981 | mutex_unlock(lock: &bnx2fc_dev_lock); |
1982 | } |
1983 | |
1984 | static void bnx2fc_start_disc(struct bnx2fc_interface *interface) |
1985 | { |
1986 | struct fcoe_ctlr *ctlr = bnx2fc_to_ctlr(interface); |
1987 | struct fc_lport *lport; |
1988 | int wait_cnt = 0; |
1989 | |
1990 | BNX2FC_MISC_DBG("Entered %s\n" , __func__); |
1991 | /* Kick off FIP/FLOGI */ |
1992 | if (!test_bit(BNX2FC_FLAG_FW_INIT_DONE, &interface->hba->flags)) { |
1993 | printk(KERN_ERR PFX "Init not done yet\n" ); |
1994 | return; |
1995 | } |
1996 | |
1997 | lport = ctlr->lp; |
1998 | BNX2FC_HBA_DBG(lport, fmt: "calling fc_fabric_login\n" ); |
1999 | |
2000 | if (!bnx2fc_link_ok(lport) && interface->enabled) { |
2001 | BNX2FC_HBA_DBG(lport, fmt: "ctlr_link_up\n" ); |
2002 | fcoe_ctlr_link_up(ctlr); |
2003 | fc_host_port_type(lport->host) = FC_PORTTYPE_NPORT; |
2004 | set_bit(ADAPTER_STATE_READY, addr: &interface->hba->adapter_state); |
2005 | } |
2006 | |
2007 | /* wait for the FCF to be selected before issuing FLOGI */ |
2008 | while (!ctlr->sel_fcf) { |
2009 | msleep(msecs: 250); |
2010 | /* give up after 3 secs */ |
2011 | if (++wait_cnt > 12) |
2012 | break; |
2013 | } |
2014 | |
2015 | /* Reset max receive frame size to default */ |
2016 | if (fc_set_mfs(lport, BNX2FC_MFS)) |
2017 | return; |
2018 | |
2019 | fc_lport_init(lport); |
2020 | fc_fabric_login(lport); |
2021 | } |
2022 | |
2023 | |
2024 | /** |
2025 | * bnx2fc_ulp_init - Initialize an adapter instance |
2026 | * |
2027 | * @dev : cnic device handle |
2028 | * Called from cnic_register_driver() context to initialize all |
2029 | * enumerated cnic devices. This routine allocates adapter structure |
2030 | * and other device specific resources. |
2031 | */ |
2032 | static void bnx2fc_ulp_init(struct cnic_dev *dev) |
2033 | { |
2034 | struct bnx2fc_hba *hba; |
2035 | int rc = 0; |
2036 | |
2037 | BNX2FC_MISC_DBG("Entered %s\n" , __func__); |
2038 | /* bnx2fc works only when bnx2x is loaded */ |
2039 | if (!test_bit(CNIC_F_BNX2X_CLASS, &dev->flags) || |
2040 | (dev->max_fcoe_conn == 0)) { |
2041 | printk(KERN_ERR PFX "bnx2fc FCoE not supported on %s," |
2042 | " flags: %lx fcoe_conn: %d\n" , |
2043 | dev->netdev->name, dev->flags, dev->max_fcoe_conn); |
2044 | return; |
2045 | } |
2046 | |
2047 | hba = bnx2fc_hba_create(cnic: dev); |
2048 | if (!hba) { |
2049 | printk(KERN_ERR PFX "hba initialization failed\n" ); |
2050 | return; |
2051 | } |
2052 | |
2053 | pr_info(PFX "FCoE initialized for %s.\n" , dev->netdev->name); |
2054 | |
2055 | /* Add HBA to the adapter list */ |
2056 | mutex_lock(&bnx2fc_dev_lock); |
2057 | list_add_tail(new: &hba->list, head: &adapter_list); |
2058 | adapter_count++; |
2059 | mutex_unlock(lock: &bnx2fc_dev_lock); |
2060 | |
2061 | dev->fcoe_cap = &hba->fcoe_cap; |
2062 | clear_bit(BNX2FC_CNIC_REGISTERED, addr: &hba->reg_with_cnic); |
2063 | rc = dev->register_device(dev, CNIC_ULP_FCOE, |
2064 | (void *) hba); |
2065 | if (rc) |
2066 | printk(KERN_ERR PFX "register_device failed, rc = %d\n" , rc); |
2067 | else |
2068 | set_bit(BNX2FC_CNIC_REGISTERED, addr: &hba->reg_with_cnic); |
2069 | } |
2070 | |
2071 | /* Assumes rtnl_lock and the bnx2fc_dev_lock are already taken */ |
2072 | static int __bnx2fc_disable(struct fcoe_ctlr *ctlr) |
2073 | { |
2074 | struct bnx2fc_interface *interface = fcoe_ctlr_priv(ctlr); |
2075 | |
2076 | if (interface->enabled) { |
2077 | if (!ctlr->lp) { |
2078 | pr_err(PFX "__bnx2fc_disable: lport not found\n" ); |
2079 | return -ENODEV; |
2080 | } else { |
2081 | interface->enabled = false; |
2082 | fcoe_ctlr_link_down(ctlr); |
2083 | fcoe_clean_pending_queue(ctlr->lp); |
2084 | } |
2085 | } |
2086 | return 0; |
2087 | } |
2088 | |
2089 | /* |
2090 | * Deperecated: Use bnx2fc_enabled() |
2091 | */ |
2092 | static int bnx2fc_disable(struct net_device *netdev) |
2093 | { |
2094 | struct bnx2fc_interface *interface; |
2095 | struct fcoe_ctlr *ctlr; |
2096 | int rc = 0; |
2097 | |
2098 | rtnl_lock(); |
2099 | mutex_lock(&bnx2fc_dev_lock); |
2100 | |
2101 | interface = bnx2fc_interface_lookup(phys_dev: netdev); |
2102 | ctlr = bnx2fc_to_ctlr(interface); |
2103 | |
2104 | if (!interface) { |
2105 | rc = -ENODEV; |
2106 | pr_err(PFX "bnx2fc_disable: interface not found\n" ); |
2107 | } else { |
2108 | rc = __bnx2fc_disable(ctlr); |
2109 | } |
2110 | mutex_unlock(lock: &bnx2fc_dev_lock); |
2111 | rtnl_unlock(); |
2112 | return rc; |
2113 | } |
2114 | |
2115 | static uint bnx2fc_npiv_create_vports(struct fc_lport *lport, |
2116 | struct cnic_fc_npiv_tbl *npiv_tbl) |
2117 | { |
2118 | struct fc_vport_identifiers vpid; |
2119 | uint i, created = 0; |
2120 | u64 wwnn = 0; |
2121 | char wwpn_str[32]; |
2122 | char wwnn_str[32]; |
2123 | |
2124 | if (npiv_tbl->count > MAX_NPIV_ENTRIES) { |
2125 | BNX2FC_HBA_DBG(lport, fmt: "Exceeded count max of npiv table\n" ); |
2126 | goto done; |
2127 | } |
2128 | |
2129 | /* Sanity check the first entry to make sure it's not 0 */ |
2130 | if (wwn_to_u64(wwn: npiv_tbl->wwnn[0]) == 0 && |
2131 | wwn_to_u64(wwn: npiv_tbl->wwpn[0]) == 0) { |
2132 | BNX2FC_HBA_DBG(lport, fmt: "First NPIV table entries invalid.\n" ); |
2133 | goto done; |
2134 | } |
2135 | |
2136 | vpid.roles = FC_PORT_ROLE_FCP_INITIATOR; |
2137 | vpid.vport_type = FC_PORTTYPE_NPIV; |
2138 | vpid.disable = false; |
2139 | |
2140 | for (i = 0; i < npiv_tbl->count; i++) { |
2141 | wwnn = wwn_to_u64(wwn: npiv_tbl->wwnn[i]); |
2142 | if (wwnn == 0) { |
2143 | /* |
2144 | * If we get a 0 element from for the WWNN then assume |
2145 | * the WWNN should be the same as the physical port. |
2146 | */ |
2147 | wwnn = lport->wwnn; |
2148 | } |
2149 | vpid.node_name = wwnn; |
2150 | vpid.port_name = wwn_to_u64(wwn: npiv_tbl->wwpn[i]); |
2151 | scnprintf(buf: vpid.symbolic_name, size: sizeof(vpid.symbolic_name), |
2152 | fmt: "NPIV[%u]:%016llx-%016llx" , |
2153 | created, vpid.port_name, vpid.node_name); |
2154 | fcoe_wwn_to_str(wwn: vpid.node_name, buf: wwnn_str, len: sizeof(wwnn_str)); |
2155 | fcoe_wwn_to_str(wwn: vpid.port_name, buf: wwpn_str, len: sizeof(wwpn_str)); |
2156 | BNX2FC_HBA_DBG(lport, fmt: "Creating vport %s:%s.\n" , wwnn_str, |
2157 | wwpn_str); |
2158 | if (fc_vport_create(shost: lport->host, channel: 0, &vpid)) |
2159 | created++; |
2160 | else |
2161 | BNX2FC_HBA_DBG(lport, fmt: "Failed to create vport\n" ); |
2162 | } |
2163 | done: |
2164 | return created; |
2165 | } |
2166 | |
2167 | static int __bnx2fc_enable(struct fcoe_ctlr *ctlr) |
2168 | { |
2169 | struct bnx2fc_interface *interface = fcoe_ctlr_priv(ctlr); |
2170 | struct bnx2fc_hba *hba; |
2171 | struct cnic_fc_npiv_tbl *npiv_tbl; |
2172 | struct fc_lport *lport; |
2173 | |
2174 | if (!interface->enabled) { |
2175 | if (!ctlr->lp) { |
2176 | pr_err(PFX "__bnx2fc_enable: lport not found\n" ); |
2177 | return -ENODEV; |
2178 | } else if (!bnx2fc_link_ok(lport: ctlr->lp)) { |
2179 | fcoe_ctlr_link_up(ctlr); |
2180 | interface->enabled = true; |
2181 | } |
2182 | } |
2183 | |
2184 | /* Create static NPIV ports if any are contained in NVRAM */ |
2185 | hba = interface->hba; |
2186 | lport = ctlr->lp; |
2187 | |
2188 | if (!hba) |
2189 | goto done; |
2190 | |
2191 | if (!hba->cnic) |
2192 | goto done; |
2193 | |
2194 | if (!lport) |
2195 | goto done; |
2196 | |
2197 | if (!lport->host) |
2198 | goto done; |
2199 | |
2200 | if (!hba->cnic->get_fc_npiv_tbl) |
2201 | goto done; |
2202 | |
2203 | npiv_tbl = kzalloc(size: sizeof(struct cnic_fc_npiv_tbl), GFP_KERNEL); |
2204 | if (!npiv_tbl) |
2205 | goto done; |
2206 | |
2207 | if (hba->cnic->get_fc_npiv_tbl(hba->cnic, npiv_tbl)) |
2208 | goto done_free; |
2209 | |
2210 | bnx2fc_npiv_create_vports(lport, npiv_tbl); |
2211 | done_free: |
2212 | kfree(objp: npiv_tbl); |
2213 | done: |
2214 | return 0; |
2215 | } |
2216 | |
2217 | /* |
2218 | * Deprecated: Use bnx2fc_enabled() |
2219 | */ |
2220 | static int bnx2fc_enable(struct net_device *netdev) |
2221 | { |
2222 | struct bnx2fc_interface *interface; |
2223 | struct fcoe_ctlr *ctlr; |
2224 | int rc = 0; |
2225 | |
2226 | rtnl_lock(); |
2227 | mutex_lock(&bnx2fc_dev_lock); |
2228 | |
2229 | interface = bnx2fc_interface_lookup(phys_dev: netdev); |
2230 | ctlr = bnx2fc_to_ctlr(interface); |
2231 | if (!interface) { |
2232 | rc = -ENODEV; |
2233 | pr_err(PFX "bnx2fc_enable: interface not found\n" ); |
2234 | } else { |
2235 | rc = __bnx2fc_enable(ctlr); |
2236 | } |
2237 | |
2238 | mutex_unlock(lock: &bnx2fc_dev_lock); |
2239 | rtnl_unlock(); |
2240 | return rc; |
2241 | } |
2242 | |
2243 | /** |
2244 | * bnx2fc_ctlr_enabled() - Enable or disable an FCoE Controller |
2245 | * @cdev: The FCoE Controller that is being enabled or disabled |
2246 | * |
2247 | * fcoe_sysfs will ensure that the state of 'enabled' has |
2248 | * changed, so no checking is necessary here. This routine simply |
2249 | * calls fcoe_enable or fcoe_disable, both of which are deprecated. |
2250 | * When those routines are removed the functionality can be merged |
2251 | * here. |
2252 | */ |
2253 | static int bnx2fc_ctlr_enabled(struct fcoe_ctlr_device *cdev) |
2254 | { |
2255 | struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr: cdev); |
2256 | |
2257 | switch (cdev->enabled) { |
2258 | case FCOE_CTLR_ENABLED: |
2259 | return __bnx2fc_enable(ctlr); |
2260 | case FCOE_CTLR_DISABLED: |
2261 | return __bnx2fc_disable(ctlr); |
2262 | case FCOE_CTLR_UNUSED: |
2263 | default: |
2264 | return -ENOTSUPP; |
2265 | } |
2266 | } |
2267 | |
2268 | enum bnx2fc_create_link_state { |
2269 | BNX2FC_CREATE_LINK_DOWN, |
2270 | BNX2FC_CREATE_LINK_UP, |
2271 | }; |
2272 | |
2273 | /** |
2274 | * _bnx2fc_create() - Create bnx2fc FCoE interface |
2275 | * @netdev : The net_device object the Ethernet interface to create on |
2276 | * @fip_mode: The FIP mode for this creation |
2277 | * @link_state: The ctlr link state on creation |
2278 | * |
2279 | * Called from either the libfcoe 'create' module parameter |
2280 | * via fcoe_create or from fcoe_syfs's ctlr_create file. |
2281 | * |
2282 | * libfcoe's 'create' module parameter is deprecated so some |
2283 | * consolidation of code can be done when that interface is |
2284 | * removed. |
2285 | * |
2286 | * Returns: 0 for success |
2287 | */ |
2288 | static int _bnx2fc_create(struct net_device *netdev, |
2289 | enum fip_mode fip_mode, |
2290 | enum bnx2fc_create_link_state link_state) |
2291 | { |
2292 | struct fcoe_ctlr_device *cdev; |
2293 | struct fcoe_ctlr *ctlr; |
2294 | struct bnx2fc_interface *interface; |
2295 | struct bnx2fc_hba *hba; |
2296 | struct net_device *phys_dev = netdev; |
2297 | struct fc_lport *lport; |
2298 | struct ethtool_drvinfo drvinfo; |
2299 | int rc = 0; |
2300 | int vlan_id = 0; |
2301 | |
2302 | BNX2FC_MISC_DBG("Entered bnx2fc_create\n" ); |
2303 | if (fip_mode != FIP_MODE_FABRIC) { |
2304 | printk(KERN_ERR "fip mode not FABRIC\n" ); |
2305 | return -EIO; |
2306 | } |
2307 | |
2308 | rtnl_lock(); |
2309 | |
2310 | mutex_lock(&bnx2fc_dev_lock); |
2311 | |
2312 | if (!try_module_get(THIS_MODULE)) { |
2313 | rc = -EINVAL; |
2314 | goto mod_err; |
2315 | } |
2316 | |
2317 | /* obtain physical netdev */ |
2318 | if (is_vlan_dev(dev: netdev)) |
2319 | phys_dev = vlan_dev_real_dev(dev: netdev); |
2320 | |
2321 | /* verify if the physical device is a netxtreme2 device */ |
2322 | if (phys_dev->ethtool_ops && phys_dev->ethtool_ops->get_drvinfo) { |
2323 | memset(&drvinfo, 0, sizeof(drvinfo)); |
2324 | phys_dev->ethtool_ops->get_drvinfo(phys_dev, &drvinfo); |
2325 | if (strncmp(drvinfo.driver, "bnx2x" , strlen("bnx2x" ))) { |
2326 | printk(KERN_ERR PFX "Not a netxtreme2 device\n" ); |
2327 | rc = -EINVAL; |
2328 | goto netdev_err; |
2329 | } |
2330 | } else { |
2331 | printk(KERN_ERR PFX "unable to obtain drv_info\n" ); |
2332 | rc = -EINVAL; |
2333 | goto netdev_err; |
2334 | } |
2335 | |
2336 | /* obtain interface and initialize rest of the structure */ |
2337 | hba = bnx2fc_hba_lookup(phys_dev); |
2338 | if (!hba) { |
2339 | rc = -ENODEV; |
2340 | printk(KERN_ERR PFX "bnx2fc_create: hba not found\n" ); |
2341 | goto netdev_err; |
2342 | } |
2343 | |
2344 | if (bnx2fc_interface_lookup(phys_dev: netdev)) { |
2345 | rc = -EEXIST; |
2346 | goto netdev_err; |
2347 | } |
2348 | |
2349 | interface = bnx2fc_interface_create(hba, netdev, fip_mode); |
2350 | if (!interface) { |
2351 | printk(KERN_ERR PFX "bnx2fc_interface_create failed\n" ); |
2352 | rc = -ENOMEM; |
2353 | goto netdev_err; |
2354 | } |
2355 | |
2356 | if (is_vlan_dev(dev: netdev)) { |
2357 | vlan_id = vlan_dev_vlan_id(dev: netdev); |
2358 | interface->vlan_enabled = 1; |
2359 | } |
2360 | |
2361 | ctlr = bnx2fc_to_ctlr(interface); |
2362 | cdev = fcoe_ctlr_to_ctlr_dev(ctlr); |
2363 | interface->vlan_id = vlan_id; |
2364 | interface->tm_timeout = BNX2FC_TM_TIMEOUT; |
2365 | |
2366 | interface->timer_work_queue = |
2367 | create_singlethread_workqueue("bnx2fc_timer_wq" ); |
2368 | if (!interface->timer_work_queue) { |
2369 | printk(KERN_ERR PFX "ulp_init could not create timer_wq\n" ); |
2370 | rc = -EINVAL; |
2371 | goto ifput_err; |
2372 | } |
2373 | |
2374 | lport = bnx2fc_if_create(interface, parent: &cdev->dev, npiv: 0); |
2375 | if (!lport) { |
2376 | printk(KERN_ERR PFX "Failed to create interface (%s)\n" , |
2377 | netdev->name); |
2378 | rc = -EINVAL; |
2379 | goto if_create_err; |
2380 | } |
2381 | |
2382 | /* Add interface to if_list */ |
2383 | list_add_tail(new: &interface->list, head: &if_list); |
2384 | |
2385 | lport->boot_time = jiffies; |
2386 | |
2387 | /* Make this master N_port */ |
2388 | ctlr->lp = lport; |
2389 | |
2390 | if (link_state == BNX2FC_CREATE_LINK_UP) |
2391 | cdev->enabled = FCOE_CTLR_ENABLED; |
2392 | else |
2393 | cdev->enabled = FCOE_CTLR_DISABLED; |
2394 | |
2395 | if (link_state == BNX2FC_CREATE_LINK_UP && |
2396 | !bnx2fc_link_ok(lport)) { |
2397 | fcoe_ctlr_link_up(ctlr); |
2398 | fc_host_port_type(lport->host) = FC_PORTTYPE_NPORT; |
2399 | set_bit(ADAPTER_STATE_READY, addr: &interface->hba->adapter_state); |
2400 | } |
2401 | |
2402 | BNX2FC_HBA_DBG(lport, fmt: "create: START DISC\n" ); |
2403 | bnx2fc_start_disc(interface); |
2404 | |
2405 | if (link_state == BNX2FC_CREATE_LINK_UP) |
2406 | interface->enabled = true; |
2407 | |
2408 | /* |
2409 | * Release from kref_init in bnx2fc_interface_setup, on success |
2410 | * lport should be holding a reference taken in bnx2fc_if_create |
2411 | */ |
2412 | bnx2fc_interface_put(interface); |
2413 | /* put netdev that was held while calling dev_get_by_name */ |
2414 | mutex_unlock(lock: &bnx2fc_dev_lock); |
2415 | rtnl_unlock(); |
2416 | return 0; |
2417 | |
2418 | if_create_err: |
2419 | destroy_workqueue(wq: interface->timer_work_queue); |
2420 | ifput_err: |
2421 | bnx2fc_net_cleanup(interface); |
2422 | bnx2fc_interface_put(interface); |
2423 | goto mod_err; |
2424 | netdev_err: |
2425 | module_put(THIS_MODULE); |
2426 | mod_err: |
2427 | mutex_unlock(lock: &bnx2fc_dev_lock); |
2428 | rtnl_unlock(); |
2429 | return rc; |
2430 | } |
2431 | |
2432 | /** |
2433 | * bnx2fc_create() - Create a bnx2fc interface |
2434 | * @netdev : The net_device object the Ethernet interface to create on |
2435 | * @fip_mode: The FIP mode for this creation |
2436 | * |
2437 | * Called from fcoe transport |
2438 | * |
2439 | * Returns: 0 for success |
2440 | */ |
2441 | static int bnx2fc_create(struct net_device *netdev, enum fip_mode fip_mode) |
2442 | { |
2443 | return _bnx2fc_create(netdev, fip_mode, link_state: BNX2FC_CREATE_LINK_UP); |
2444 | } |
2445 | |
2446 | /** |
2447 | * bnx2fc_ctlr_alloc() - Allocate a bnx2fc interface from fcoe_sysfs |
2448 | * @netdev: The net_device to be used by the allocated FCoE Controller |
2449 | * |
2450 | * This routine is called from fcoe_sysfs. It will start the fcoe_ctlr |
2451 | * in a link_down state. The allows the user an opportunity to configure |
2452 | * the FCoE Controller from sysfs before enabling the FCoE Controller. |
2453 | * |
2454 | * Creating in with this routine starts the FCoE Controller in Fabric |
2455 | * mode. The user can change to VN2VN or another mode before enabling. |
2456 | */ |
2457 | static int bnx2fc_ctlr_alloc(struct net_device *netdev) |
2458 | { |
2459 | return _bnx2fc_create(netdev, fip_mode: FIP_MODE_FABRIC, |
2460 | link_state: BNX2FC_CREATE_LINK_DOWN); |
2461 | } |
2462 | |
2463 | /** |
2464 | * bnx2fc_find_hba_for_cnic - maps cnic instance to bnx2fc hba instance |
2465 | * |
2466 | * @cnic: Pointer to cnic device instance |
2467 | * |
2468 | **/ |
2469 | static struct bnx2fc_hba *bnx2fc_find_hba_for_cnic(struct cnic_dev *cnic) |
2470 | { |
2471 | struct bnx2fc_hba *hba; |
2472 | |
2473 | /* Called with bnx2fc_dev_lock held */ |
2474 | list_for_each_entry(hba, &adapter_list, list) { |
2475 | if (hba->cnic == cnic) |
2476 | return hba; |
2477 | } |
2478 | return NULL; |
2479 | } |
2480 | |
2481 | static struct bnx2fc_interface *bnx2fc_interface_lookup(struct net_device |
2482 | *netdev) |
2483 | { |
2484 | struct bnx2fc_interface *interface; |
2485 | |
2486 | /* Called with bnx2fc_dev_lock held */ |
2487 | list_for_each_entry(interface, &if_list, list) { |
2488 | if (interface->netdev == netdev) |
2489 | return interface; |
2490 | } |
2491 | return NULL; |
2492 | } |
2493 | |
2494 | static struct bnx2fc_hba *bnx2fc_hba_lookup(struct net_device |
2495 | *phys_dev) |
2496 | { |
2497 | struct bnx2fc_hba *hba; |
2498 | |
2499 | /* Called with bnx2fc_dev_lock held */ |
2500 | list_for_each_entry(hba, &adapter_list, list) { |
2501 | if (hba->phys_dev == phys_dev) |
2502 | return hba; |
2503 | } |
2504 | printk(KERN_ERR PFX "adapter_lookup: hba NULL\n" ); |
2505 | return NULL; |
2506 | } |
2507 | |
2508 | /** |
2509 | * bnx2fc_ulp_exit - shuts down adapter instance and frees all resources |
2510 | * |
2511 | * @dev: cnic device handle |
2512 | */ |
2513 | static void bnx2fc_ulp_exit(struct cnic_dev *dev) |
2514 | { |
2515 | struct bnx2fc_hba *hba; |
2516 | struct bnx2fc_interface *interface, *tmp; |
2517 | |
2518 | BNX2FC_MISC_DBG("Entered bnx2fc_ulp_exit\n" ); |
2519 | |
2520 | if (!test_bit(CNIC_F_BNX2X_CLASS, &dev->flags)) { |
2521 | printk(KERN_ERR PFX "bnx2fc port check: %s, flags: %lx\n" , |
2522 | dev->netdev->name, dev->flags); |
2523 | return; |
2524 | } |
2525 | |
2526 | mutex_lock(&bnx2fc_dev_lock); |
2527 | hba = bnx2fc_find_hba_for_cnic(cnic: dev); |
2528 | if (!hba) { |
2529 | printk(KERN_ERR PFX "bnx2fc_ulp_exit: hba not found, dev 0%p\n" , |
2530 | dev); |
2531 | mutex_unlock(lock: &bnx2fc_dev_lock); |
2532 | return; |
2533 | } |
2534 | |
2535 | list_del_init(entry: &hba->list); |
2536 | adapter_count--; |
2537 | |
2538 | list_for_each_entry_safe(interface, tmp, &if_list, list) |
2539 | /* destroy not called yet, move to quiesced list */ |
2540 | if (interface->hba == hba) |
2541 | __bnx2fc_destroy(interface); |
2542 | mutex_unlock(lock: &bnx2fc_dev_lock); |
2543 | |
2544 | bnx2fc_ulp_stop(handle: hba); |
2545 | /* unregister cnic device */ |
2546 | if (test_and_clear_bit(BNX2FC_CNIC_REGISTERED, addr: &hba->reg_with_cnic)) |
2547 | hba->cnic->unregister_device(hba->cnic, CNIC_ULP_FCOE); |
2548 | bnx2fc_hba_destroy(hba); |
2549 | } |
2550 | |
2551 | static void bnx2fc_rport_terminate_io(struct fc_rport *rport) |
2552 | { |
2553 | /* This is a no-op */ |
2554 | } |
2555 | |
2556 | /** |
2557 | * bnx2fc_fcoe_reset - Resets the fcoe |
2558 | * |
2559 | * @shost: shost the reset is from |
2560 | * |
2561 | * Returns: always 0 |
2562 | */ |
2563 | static int bnx2fc_fcoe_reset(struct Scsi_Host *shost) |
2564 | { |
2565 | struct fc_lport *lport = shost_priv(shost); |
2566 | fc_lport_reset(lport); |
2567 | return 0; |
2568 | } |
2569 | |
2570 | |
2571 | static bool bnx2fc_match(struct net_device *netdev) |
2572 | { |
2573 | struct net_device *phys_dev = netdev; |
2574 | |
2575 | mutex_lock(&bnx2fc_dev_lock); |
2576 | if (is_vlan_dev(dev: netdev)) |
2577 | phys_dev = vlan_dev_real_dev(dev: netdev); |
2578 | |
2579 | if (bnx2fc_hba_lookup(phys_dev)) { |
2580 | mutex_unlock(lock: &bnx2fc_dev_lock); |
2581 | return true; |
2582 | } |
2583 | |
2584 | mutex_unlock(lock: &bnx2fc_dev_lock); |
2585 | return false; |
2586 | } |
2587 | |
2588 | |
2589 | static struct fcoe_transport bnx2fc_transport = { |
2590 | .name = {"bnx2fc" }, |
2591 | .attached = false, |
2592 | .list = LIST_HEAD_INIT(bnx2fc_transport.list), |
2593 | .alloc = bnx2fc_ctlr_alloc, |
2594 | .match = bnx2fc_match, |
2595 | .create = bnx2fc_create, |
2596 | .destroy = bnx2fc_destroy, |
2597 | .enable = bnx2fc_enable, |
2598 | .disable = bnx2fc_disable, |
2599 | }; |
2600 | |
2601 | /** |
2602 | * bnx2fc_cpu_online - Create a receive thread for an online CPU |
2603 | * |
2604 | * @cpu: cpu index for the online cpu |
2605 | */ |
2606 | static int bnx2fc_cpu_online(unsigned int cpu) |
2607 | { |
2608 | struct bnx2fc_percpu_s *p; |
2609 | struct task_struct *thread; |
2610 | |
2611 | p = &per_cpu(bnx2fc_percpu, cpu); |
2612 | |
2613 | thread = kthread_create_on_node(threadfn: bnx2fc_percpu_io_thread, |
2614 | data: (void *)p, cpu_to_node(cpu), |
2615 | namefmt: "bnx2fc_thread/%d" , cpu); |
2616 | if (IS_ERR(ptr: thread)) |
2617 | return PTR_ERR(ptr: thread); |
2618 | |
2619 | /* bind thread to the cpu */ |
2620 | kthread_bind(k: thread, cpu); |
2621 | p->iothread = thread; |
2622 | wake_up_process(tsk: thread); |
2623 | return 0; |
2624 | } |
2625 | |
2626 | static int bnx2fc_cpu_offline(unsigned int cpu) |
2627 | { |
2628 | struct bnx2fc_percpu_s *p; |
2629 | struct task_struct *thread; |
2630 | struct bnx2fc_work *work, *tmp; |
2631 | |
2632 | BNX2FC_MISC_DBG("destroying io thread for CPU %d\n" , cpu); |
2633 | |
2634 | /* Prevent any new work from being queued for this CPU */ |
2635 | p = &per_cpu(bnx2fc_percpu, cpu); |
2636 | spin_lock_bh(lock: &p->fp_work_lock); |
2637 | thread = p->iothread; |
2638 | p->iothread = NULL; |
2639 | |
2640 | /* Free all work in the list */ |
2641 | list_for_each_entry_safe(work, tmp, &p->work_list, list) { |
2642 | list_del_init(entry: &work->list); |
2643 | bnx2fc_process_cq_compl(tgt: work->tgt, wqe: work->wqe, rq_data: work->rq_data, |
2644 | num_rq: work->num_rq, task: work->task); |
2645 | kfree(objp: work); |
2646 | } |
2647 | |
2648 | spin_unlock_bh(lock: &p->fp_work_lock); |
2649 | |
2650 | if (thread) |
2651 | kthread_stop(k: thread); |
2652 | return 0; |
2653 | } |
2654 | |
2655 | static int bnx2fc_slave_configure(struct scsi_device *sdev) |
2656 | { |
2657 | if (!bnx2fc_queue_depth) |
2658 | return 0; |
2659 | |
2660 | scsi_change_queue_depth(sdev, bnx2fc_queue_depth); |
2661 | return 0; |
2662 | } |
2663 | |
2664 | static enum cpuhp_state bnx2fc_online_state; |
2665 | |
2666 | /** |
2667 | * bnx2fc_mod_init - module init entry point |
2668 | * |
2669 | * Initialize driver wide global data structures, and register |
2670 | * with cnic module |
2671 | **/ |
2672 | static int __init bnx2fc_mod_init(void) |
2673 | { |
2674 | struct fcoe_percpu_s *bg; |
2675 | struct task_struct *l2_thread; |
2676 | int rc = 0; |
2677 | unsigned int cpu = 0; |
2678 | struct bnx2fc_percpu_s *p; |
2679 | |
2680 | printk(KERN_INFO PFX "%s" , version); |
2681 | |
2682 | /* register as a fcoe transport */ |
2683 | rc = fcoe_transport_attach(ft: &bnx2fc_transport); |
2684 | if (rc) { |
2685 | printk(KERN_ERR "failed to register an fcoe transport, check " |
2686 | "if libfcoe is loaded\n" ); |
2687 | goto out; |
2688 | } |
2689 | |
2690 | INIT_LIST_HEAD(list: &adapter_list); |
2691 | INIT_LIST_HEAD(list: &if_list); |
2692 | mutex_init(&bnx2fc_dev_lock); |
2693 | adapter_count = 0; |
2694 | |
2695 | /* Attach FC transport template */ |
2696 | rc = bnx2fc_attach_transport(); |
2697 | if (rc) |
2698 | goto detach_ft; |
2699 | |
2700 | bnx2fc_wq = alloc_workqueue(fmt: "bnx2fc" , flags: 0, max_active: 0); |
2701 | if (!bnx2fc_wq) { |
2702 | rc = -ENOMEM; |
2703 | goto release_bt; |
2704 | } |
2705 | |
2706 | bg = &bnx2fc_global; |
2707 | skb_queue_head_init(list: &bg->fcoe_rx_list); |
2708 | l2_thread = kthread_run(bnx2fc_l2_rcv_thread, |
2709 | (void *)bg, |
2710 | "bnx2fc_l2_thread" ); |
2711 | if (IS_ERR(ptr: l2_thread)) { |
2712 | rc = PTR_ERR(ptr: l2_thread); |
2713 | goto free_wq; |
2714 | } |
2715 | spin_lock_bh(lock: &bg->fcoe_rx_list.lock); |
2716 | bg->kthread = l2_thread; |
2717 | spin_unlock_bh(lock: &bg->fcoe_rx_list.lock); |
2718 | |
2719 | for_each_possible_cpu(cpu) { |
2720 | p = &per_cpu(bnx2fc_percpu, cpu); |
2721 | INIT_LIST_HEAD(list: &p->work_list); |
2722 | spin_lock_init(&p->fp_work_lock); |
2723 | } |
2724 | |
2725 | rc = cpuhp_setup_state(state: CPUHP_AP_ONLINE_DYN, name: "scsi/bnx2fc:online" , |
2726 | startup: bnx2fc_cpu_online, teardown: bnx2fc_cpu_offline); |
2727 | if (rc < 0) |
2728 | goto stop_thread; |
2729 | bnx2fc_online_state = rc; |
2730 | |
2731 | cnic_register_driver(CNIC_ULP_FCOE, ulp_ops: &bnx2fc_cnic_cb); |
2732 | return 0; |
2733 | |
2734 | stop_thread: |
2735 | kthread_stop(k: l2_thread); |
2736 | free_wq: |
2737 | destroy_workqueue(wq: bnx2fc_wq); |
2738 | release_bt: |
2739 | bnx2fc_release_transport(); |
2740 | detach_ft: |
2741 | fcoe_transport_detach(ft: &bnx2fc_transport); |
2742 | out: |
2743 | return rc; |
2744 | } |
2745 | |
2746 | static void __exit bnx2fc_mod_exit(void) |
2747 | { |
2748 | LIST_HEAD(to_be_deleted); |
2749 | struct bnx2fc_hba *hba, *next; |
2750 | struct fcoe_percpu_s *bg; |
2751 | struct task_struct *l2_thread; |
2752 | struct sk_buff *skb; |
2753 | |
2754 | /* |
2755 | * NOTE: Since cnic calls register_driver routine rtnl_lock, |
2756 | * it will have higher precedence than bnx2fc_dev_lock. |
2757 | * unregister_device() cannot be called with bnx2fc_dev_lock |
2758 | * held. |
2759 | */ |
2760 | mutex_lock(&bnx2fc_dev_lock); |
2761 | list_splice_init(list: &adapter_list, head: &to_be_deleted); |
2762 | adapter_count = 0; |
2763 | mutex_unlock(lock: &bnx2fc_dev_lock); |
2764 | |
2765 | /* Unregister with cnic */ |
2766 | list_for_each_entry_safe(hba, next, &to_be_deleted, list) { |
2767 | list_del_init(entry: &hba->list); |
2768 | printk(KERN_ERR PFX "MOD_EXIT:destroy hba = 0x%p\n" , |
2769 | hba); |
2770 | bnx2fc_ulp_stop(handle: hba); |
2771 | /* unregister cnic device */ |
2772 | if (test_and_clear_bit(BNX2FC_CNIC_REGISTERED, |
2773 | addr: &hba->reg_with_cnic)) |
2774 | hba->cnic->unregister_device(hba->cnic, |
2775 | CNIC_ULP_FCOE); |
2776 | bnx2fc_hba_destroy(hba); |
2777 | } |
2778 | cnic_unregister_driver(CNIC_ULP_FCOE); |
2779 | |
2780 | /* Destroy global thread */ |
2781 | bg = &bnx2fc_global; |
2782 | spin_lock_bh(lock: &bg->fcoe_rx_list.lock); |
2783 | l2_thread = bg->kthread; |
2784 | bg->kthread = NULL; |
2785 | while ((skb = __skb_dequeue(list: &bg->fcoe_rx_list)) != NULL) |
2786 | kfree_skb(skb); |
2787 | |
2788 | spin_unlock_bh(lock: &bg->fcoe_rx_list.lock); |
2789 | |
2790 | if (l2_thread) |
2791 | kthread_stop(k: l2_thread); |
2792 | |
2793 | cpuhp_remove_state(state: bnx2fc_online_state); |
2794 | |
2795 | destroy_workqueue(wq: bnx2fc_wq); |
2796 | /* |
2797 | * detach from scsi transport |
2798 | * must happen after all destroys are done |
2799 | */ |
2800 | bnx2fc_release_transport(); |
2801 | |
2802 | /* detach from fcoe transport */ |
2803 | fcoe_transport_detach(ft: &bnx2fc_transport); |
2804 | } |
2805 | |
2806 | module_init(bnx2fc_mod_init); |
2807 | module_exit(bnx2fc_mod_exit); |
2808 | |
2809 | static struct fcoe_sysfs_function_template bnx2fc_fcoe_sysfs_templ = { |
2810 | .set_fcoe_ctlr_enabled = bnx2fc_ctlr_enabled, |
2811 | .get_fcoe_ctlr_link_fail = fcoe_ctlr_get_lesb, |
2812 | .get_fcoe_ctlr_vlink_fail = fcoe_ctlr_get_lesb, |
2813 | .get_fcoe_ctlr_miss_fka = fcoe_ctlr_get_lesb, |
2814 | .get_fcoe_ctlr_symb_err = fcoe_ctlr_get_lesb, |
2815 | .get_fcoe_ctlr_err_block = fcoe_ctlr_get_lesb, |
2816 | .get_fcoe_ctlr_fcs_error = fcoe_ctlr_get_lesb, |
2817 | |
2818 | .get_fcoe_fcf_selected = fcoe_fcf_get_selected, |
2819 | .get_fcoe_fcf_vlan_id = bnx2fc_fcf_get_vlan_id, |
2820 | }; |
2821 | |
2822 | static struct fc_function_template bnx2fc_transport_function = { |
2823 | .show_host_node_name = 1, |
2824 | .show_host_port_name = 1, |
2825 | .show_host_supported_classes = 1, |
2826 | .show_host_supported_fc4s = 1, |
2827 | .show_host_active_fc4s = 1, |
2828 | .show_host_maxframe_size = 1, |
2829 | |
2830 | .show_host_port_id = 1, |
2831 | .show_host_supported_speeds = 1, |
2832 | .get_host_speed = fc_get_host_speed, |
2833 | .show_host_speed = 1, |
2834 | .show_host_port_type = 1, |
2835 | .get_host_port_state = fc_get_host_port_state, |
2836 | .show_host_port_state = 1, |
2837 | .show_host_symbolic_name = 1, |
2838 | |
2839 | .dd_fcrport_size = (sizeof(struct fc_rport_libfc_priv) + |
2840 | sizeof(struct bnx2fc_rport)), |
2841 | .show_rport_maxframe_size = 1, |
2842 | .show_rport_supported_classes = 1, |
2843 | |
2844 | .show_host_fabric_name = 1, |
2845 | .show_starget_node_name = 1, |
2846 | .show_starget_port_name = 1, |
2847 | .show_starget_port_id = 1, |
2848 | .set_rport_dev_loss_tmo = fc_set_rport_loss_tmo, |
2849 | .show_rport_dev_loss_tmo = 1, |
2850 | .get_fc_host_stats = bnx2fc_get_host_stats, |
2851 | |
2852 | .issue_fc_host_lip = bnx2fc_fcoe_reset, |
2853 | |
2854 | .terminate_rport_io = bnx2fc_rport_terminate_io, |
2855 | |
2856 | .vport_create = bnx2fc_vport_create, |
2857 | .vport_delete = bnx2fc_vport_destroy, |
2858 | .vport_disable = bnx2fc_vport_disable, |
2859 | .bsg_request = fc_lport_bsg_request, |
2860 | }; |
2861 | |
2862 | static struct fc_function_template bnx2fc_vport_xport_function = { |
2863 | .show_host_node_name = 1, |
2864 | .show_host_port_name = 1, |
2865 | .show_host_supported_classes = 1, |
2866 | .show_host_supported_fc4s = 1, |
2867 | .show_host_active_fc4s = 1, |
2868 | .show_host_maxframe_size = 1, |
2869 | |
2870 | .show_host_port_id = 1, |
2871 | .show_host_supported_speeds = 1, |
2872 | .get_host_speed = fc_get_host_speed, |
2873 | .show_host_speed = 1, |
2874 | .show_host_port_type = 1, |
2875 | .get_host_port_state = fc_get_host_port_state, |
2876 | .show_host_port_state = 1, |
2877 | .show_host_symbolic_name = 1, |
2878 | |
2879 | .dd_fcrport_size = (sizeof(struct fc_rport_libfc_priv) + |
2880 | sizeof(struct bnx2fc_rport)), |
2881 | .show_rport_maxframe_size = 1, |
2882 | .show_rport_supported_classes = 1, |
2883 | |
2884 | .show_host_fabric_name = 1, |
2885 | .show_starget_node_name = 1, |
2886 | .show_starget_port_name = 1, |
2887 | .show_starget_port_id = 1, |
2888 | .set_rport_dev_loss_tmo = fc_set_rport_loss_tmo, |
2889 | .show_rport_dev_loss_tmo = 1, |
2890 | .get_fc_host_stats = fc_get_host_stats, |
2891 | .issue_fc_host_lip = bnx2fc_fcoe_reset, |
2892 | .terminate_rport_io = fc_rport_terminate_io, |
2893 | .bsg_request = fc_lport_bsg_request, |
2894 | }; |
2895 | |
2896 | /* |
2897 | * Additional scsi_host attributes. |
2898 | */ |
2899 | static ssize_t |
2900 | bnx2fc_tm_timeout_show(struct device *dev, struct device_attribute *attr, |
2901 | char *buf) |
2902 | { |
2903 | struct Scsi_Host *shost = class_to_shost(dev); |
2904 | struct fc_lport *lport = shost_priv(shost); |
2905 | struct fcoe_port *port = lport_priv(lport); |
2906 | struct bnx2fc_interface *interface = port->priv; |
2907 | |
2908 | sprintf(buf, fmt: "%u\n" , interface->tm_timeout); |
2909 | return strlen(buf); |
2910 | } |
2911 | |
2912 | static ssize_t |
2913 | bnx2fc_tm_timeout_store(struct device *dev, |
2914 | struct device_attribute *attr, const char *buf, size_t count) |
2915 | { |
2916 | struct Scsi_Host *shost = class_to_shost(dev); |
2917 | struct fc_lport *lport = shost_priv(shost); |
2918 | struct fcoe_port *port = lport_priv(lport); |
2919 | struct bnx2fc_interface *interface = port->priv; |
2920 | int rval, val; |
2921 | |
2922 | rval = kstrtouint(s: buf, base: 10, res: &val); |
2923 | if (rval) |
2924 | return rval; |
2925 | if (val > 255) |
2926 | return -ERANGE; |
2927 | |
2928 | interface->tm_timeout = (u8)val; |
2929 | return strlen(buf); |
2930 | } |
2931 | |
2932 | static DEVICE_ATTR(tm_timeout, S_IRUGO|S_IWUSR, bnx2fc_tm_timeout_show, |
2933 | bnx2fc_tm_timeout_store); |
2934 | |
2935 | static struct attribute *bnx2fc_host_attrs[] = { |
2936 | &dev_attr_tm_timeout.attr, |
2937 | NULL, |
2938 | }; |
2939 | |
2940 | ATTRIBUTE_GROUPS(bnx2fc_host); |
2941 | |
2942 | /* |
2943 | * scsi_host_template structure used while registering with SCSI-ml |
2944 | */ |
2945 | static struct scsi_host_template bnx2fc_shost_template = { |
2946 | .module = THIS_MODULE, |
2947 | .name = "QLogic Offload FCoE Initiator" , |
2948 | .queuecommand = bnx2fc_queuecommand, |
2949 | .eh_timed_out = fc_eh_timed_out, |
2950 | .eh_abort_handler = bnx2fc_eh_abort, /* abts */ |
2951 | .eh_device_reset_handler = bnx2fc_eh_device_reset, /* lun reset */ |
2952 | .eh_target_reset_handler = bnx2fc_eh_target_reset, /* tgt reset */ |
2953 | .eh_host_reset_handler = fc_eh_host_reset, |
2954 | .slave_alloc = fc_slave_alloc, |
2955 | .change_queue_depth = scsi_change_queue_depth, |
2956 | .this_id = -1, |
2957 | .cmd_per_lun = 3, |
2958 | .sg_tablesize = BNX2FC_MAX_BDS_PER_CMD, |
2959 | .dma_boundary = 0x7fff, |
2960 | .max_sectors = 0x3fbf, |
2961 | .track_queue_depth = 1, |
2962 | .slave_configure = bnx2fc_slave_configure, |
2963 | .shost_groups = bnx2fc_host_groups, |
2964 | .cmd_size = sizeof(struct bnx2fc_priv), |
2965 | }; |
2966 | |
2967 | static struct libfc_function_template bnx2fc_libfc_fcn_templ = { |
2968 | .frame_send = bnx2fc_xmit, |
2969 | .elsct_send = bnx2fc_elsct_send, |
2970 | .fcp_abort_io = bnx2fc_abort_io, |
2971 | .fcp_cleanup = bnx2fc_cleanup, |
2972 | .get_lesb = fcoe_get_lesb, |
2973 | .rport_event_callback = bnx2fc_rport_event_handler, |
2974 | }; |
2975 | |
2976 | /* |
2977 | * bnx2fc_cnic_cb - global template of bnx2fc - cnic driver interface |
2978 | * structure carrying callback function pointers |
2979 | */ |
2980 | static struct cnic_ulp_ops bnx2fc_cnic_cb = { |
2981 | .owner = THIS_MODULE, |
2982 | .cnic_init = bnx2fc_ulp_init, |
2983 | .cnic_exit = bnx2fc_ulp_exit, |
2984 | .cnic_start = bnx2fc_ulp_start, |
2985 | .cnic_stop = bnx2fc_ulp_stop, |
2986 | .indicate_kcqes = bnx2fc_indicate_kcqe, |
2987 | .indicate_netevent = bnx2fc_indicate_netevent, |
2988 | .cnic_get_stats = bnx2fc_ulp_get_stats, |
2989 | }; |
2990 | |