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