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