blob: 8e2b2a26cb74ece1cb91256e8b5bc6ad21446be1 [file] [log] [blame]
Jing Huang7725ccf2009-09-23 17:46:15 -07001/*
2 * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
3 * All rights reserved
4 * www.brocade.com
5 *
6 * Linux driver for Brocade Fibre Channel Host Bus Adapter.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License (GPL) Version 2 as
10 * published by the Free Software Foundation
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 */
17
18/**
19 * bfad.c Linux driver PCI interface module.
20 */
21
22#include <linux/module.h>
23#include "bfad_drv.h"
24#include "bfad_im.h"
25#include "bfad_tm.h"
26#include "bfad_ipfc.h"
27#include "bfad_trcmod.h"
28#include <fcb/bfa_fcb_vf.h>
29#include <fcb/bfa_fcb_rport.h>
30#include <fcb/bfa_fcb_port.h>
31#include <fcb/bfa_fcb.h>
32
33BFA_TRC_FILE(LDRV, BFAD);
34static DEFINE_MUTEX(bfad_mutex);
35LIST_HEAD(bfad_list);
36static int bfad_inst;
37int bfad_supported_fc4s;
38
39static char *host_name;
40static char *os_name;
41static char *os_patch;
42static int num_rports;
43static int num_ios;
44static int num_tms;
45static int num_fcxps;
46static int num_ufbufs;
47static int reqq_size;
48static int rspq_size;
49static int num_sgpgs;
50static int rport_del_timeout = BFA_FCS_RPORT_DEF_DEL_TIMEOUT;
51static int bfa_io_max_sge = BFAD_IO_MAX_SGE;
52static int log_level = BFA_LOG_WARNING;
53static int ioc_auto_recover = BFA_TRUE;
54static int ipfc_enable = BFA_FALSE;
55static int ipfc_mtu = -1;
Krishna Gudipati5b098082010-03-03 17:43:19 -080056static int fdmi_enable = BFA_TRUE;
Jing Huang7725ccf2009-09-23 17:46:15 -070057int bfa_lun_queue_depth = BFAD_LUN_QUEUE_DEPTH;
58int bfa_linkup_delay = -1;
59
60module_param(os_name, charp, S_IRUGO | S_IWUSR);
61module_param(os_patch, charp, S_IRUGO | S_IWUSR);
62module_param(host_name, charp, S_IRUGO | S_IWUSR);
63module_param(num_rports, int, S_IRUGO | S_IWUSR);
64module_param(num_ios, int, S_IRUGO | S_IWUSR);
65module_param(num_tms, int, S_IRUGO | S_IWUSR);
66module_param(num_fcxps, int, S_IRUGO | S_IWUSR);
67module_param(num_ufbufs, int, S_IRUGO | S_IWUSR);
68module_param(reqq_size, int, S_IRUGO | S_IWUSR);
69module_param(rspq_size, int, S_IRUGO | S_IWUSR);
70module_param(num_sgpgs, int, S_IRUGO | S_IWUSR);
71module_param(rport_del_timeout, int, S_IRUGO | S_IWUSR);
72module_param(bfa_lun_queue_depth, int, S_IRUGO | S_IWUSR);
73module_param(bfa_io_max_sge, int, S_IRUGO | S_IWUSR);
74module_param(log_level, int, S_IRUGO | S_IWUSR);
75module_param(ioc_auto_recover, int, S_IRUGO | S_IWUSR);
76module_param(ipfc_enable, int, S_IRUGO | S_IWUSR);
77module_param(ipfc_mtu, int, S_IRUGO | S_IWUSR);
Krishna Gudipati5b098082010-03-03 17:43:19 -080078module_param(fdmi_enable, int, S_IRUGO | S_IWUSR);
Jing Huang7725ccf2009-09-23 17:46:15 -070079module_param(bfa_linkup_delay, int, S_IRUGO | S_IWUSR);
80
81/*
82 * Stores the module parm num_sgpgs value;
83 * used to reset for bfad next instance.
84 */
85static int num_sgpgs_parm;
86
87static bfa_status_t
88bfad_fc4_probe(struct bfad_s *bfad)
89{
90 int rc;
91
92 rc = bfad_im_probe(bfad);
93 if (rc != BFA_STATUS_OK)
94 goto ext;
95
96 bfad_tm_probe(bfad);
97
98 if (ipfc_enable)
99 bfad_ipfc_probe(bfad);
100ext:
101 return rc;
102}
103
104static void
105bfad_fc4_probe_undo(struct bfad_s *bfad)
106{
107 bfad_im_probe_undo(bfad);
108 bfad_tm_probe_undo(bfad);
109 if (ipfc_enable)
110 bfad_ipfc_probe_undo(bfad);
111}
112
113static void
114bfad_fc4_probe_post(struct bfad_s *bfad)
115{
116 if (bfad->im)
117 bfad_im_probe_post(bfad->im);
118
119 bfad_tm_probe_post(bfad);
120 if (ipfc_enable)
121 bfad_ipfc_probe_post(bfad);
122}
123
124static bfa_status_t
125bfad_fc4_port_new(struct bfad_s *bfad, struct bfad_port_s *port, int roles)
126{
127 int rc = BFA_STATUS_FAILED;
128
129 if (roles & BFA_PORT_ROLE_FCP_IM)
130 rc = bfad_im_port_new(bfad, port);
131 if (rc != BFA_STATUS_OK)
132 goto ext;
133
134 if (roles & BFA_PORT_ROLE_FCP_TM)
135 rc = bfad_tm_port_new(bfad, port);
136 if (rc != BFA_STATUS_OK)
137 goto ext;
138
139 if ((roles & BFA_PORT_ROLE_FCP_IPFC) && ipfc_enable)
140 rc = bfad_ipfc_port_new(bfad, port, port->pvb_type);
141ext:
142 return rc;
143}
144
145static void
146bfad_fc4_port_delete(struct bfad_s *bfad, struct bfad_port_s *port, int roles)
147{
148 if (roles & BFA_PORT_ROLE_FCP_IM)
149 bfad_im_port_delete(bfad, port);
150
151 if (roles & BFA_PORT_ROLE_FCP_TM)
152 bfad_tm_port_delete(bfad, port);
153
154 if ((roles & BFA_PORT_ROLE_FCP_IPFC) && ipfc_enable)
155 bfad_ipfc_port_delete(bfad, port);
156}
157
158/**
159 * BFA callbacks
160 */
161void
162bfad_hcb_comp(void *arg, bfa_status_t status)
163{
164 struct bfad_hal_comp *fcomp = (struct bfad_hal_comp *)arg;
165
166 fcomp->status = status;
167 complete(&fcomp->comp);
168}
169
170/**
171 * bfa_init callback
172 */
173void
174bfa_cb_init(void *drv, bfa_status_t init_status)
175{
176 struct bfad_s *bfad = drv;
177
178 if (init_status == BFA_STATUS_OK)
179 bfad->bfad_flags |= BFAD_HAL_INIT_DONE;
180
181 complete(&bfad->comp);
182}
183
184
185
186/**
187 * BFA_FCS callbacks
188 */
189static struct bfad_port_s *
190bfad_get_drv_port(struct bfad_s *bfad, struct bfad_vf_s *vf_drv,
191 struct bfad_vport_s *vp_drv)
192{
Jing Huangf8ceafd2009-09-25 12:29:54 -0700193 return (vp_drv) ? (&(vp_drv)->drv_port)
194 : ((vf_drv) ? (&(vf_drv)->base_port) : (&(bfad)->pport));
Jing Huang7725ccf2009-09-23 17:46:15 -0700195}
196
197struct bfad_port_s *
198bfa_fcb_port_new(struct bfad_s *bfad, struct bfa_fcs_port_s *port,
199 enum bfa_port_role roles, struct bfad_vf_s *vf_drv,
200 struct bfad_vport_s *vp_drv)
201{
202 bfa_status_t rc;
203 struct bfad_port_s *port_drv;
204
205 if (!vp_drv && !vf_drv) {
206 port_drv = &bfad->pport;
207 port_drv->pvb_type = BFAD_PORT_PHYS_BASE;
208 } else if (!vp_drv && vf_drv) {
209 port_drv = &vf_drv->base_port;
210 port_drv->pvb_type = BFAD_PORT_VF_BASE;
211 } else if (vp_drv && !vf_drv) {
212 port_drv = &vp_drv->drv_port;
213 port_drv->pvb_type = BFAD_PORT_PHYS_VPORT;
214 } else {
215 port_drv = &vp_drv->drv_port;
216 port_drv->pvb_type = BFAD_PORT_VF_VPORT;
217 }
218
219 port_drv->fcs_port = port;
220 port_drv->roles = roles;
221 rc = bfad_fc4_port_new(bfad, port_drv, roles);
222 if (rc != BFA_STATUS_OK) {
223 bfad_fc4_port_delete(bfad, port_drv, roles);
224 port_drv = NULL;
225 }
226
227 return port_drv;
228}
229
230void
231bfa_fcb_port_delete(struct bfad_s *bfad, enum bfa_port_role roles,
232 struct bfad_vf_s *vf_drv, struct bfad_vport_s *vp_drv)
233{
234 struct bfad_port_s *port_drv;
235
236 /*
237 * this will be only called from rmmod context
238 */
239 if (vp_drv && !vp_drv->comp_del) {
240 port_drv = bfad_get_drv_port(bfad, vf_drv, vp_drv);
241 bfa_trc(bfad, roles);
242 bfad_fc4_port_delete(bfad, port_drv, roles);
243 }
244}
245
246void
247bfa_fcb_port_online(struct bfad_s *bfad, enum bfa_port_role roles,
248 struct bfad_vf_s *vf_drv, struct bfad_vport_s *vp_drv)
249{
250 struct bfad_port_s *port_drv = bfad_get_drv_port(bfad, vf_drv, vp_drv);
251
252 if (roles & BFA_PORT_ROLE_FCP_IM)
253 bfad_im_port_online(bfad, port_drv);
254
255 if (roles & BFA_PORT_ROLE_FCP_TM)
256 bfad_tm_port_online(bfad, port_drv);
257
258 if ((roles & BFA_PORT_ROLE_FCP_IPFC) && ipfc_enable)
259 bfad_ipfc_port_online(bfad, port_drv);
260
261 bfad->bfad_flags |= BFAD_PORT_ONLINE;
262}
263
264void
265bfa_fcb_port_offline(struct bfad_s *bfad, enum bfa_port_role roles,
266 struct bfad_vf_s *vf_drv, struct bfad_vport_s *vp_drv)
267{
268 struct bfad_port_s *port_drv = bfad_get_drv_port(bfad, vf_drv, vp_drv);
269
270 if (roles & BFA_PORT_ROLE_FCP_IM)
271 bfad_im_port_offline(bfad, port_drv);
272
273 if (roles & BFA_PORT_ROLE_FCP_TM)
274 bfad_tm_port_offline(bfad, port_drv);
275
276 if ((roles & BFA_PORT_ROLE_FCP_IPFC) && ipfc_enable)
277 bfad_ipfc_port_offline(bfad, port_drv);
278}
279
280void
281bfa_fcb_vport_delete(struct bfad_vport_s *vport_drv)
282{
283 if (vport_drv->comp_del) {
284 complete(vport_drv->comp_del);
285 return;
286 }
287
288 kfree(vport_drv);
289}
290
291/**
292 * FCS RPORT alloc callback, after successful PLOGI by FCS
293 */
294bfa_status_t
295bfa_fcb_rport_alloc(struct bfad_s *bfad, struct bfa_fcs_rport_s **rport,
296 struct bfad_rport_s **rport_drv)
297{
298 bfa_status_t rc = BFA_STATUS_OK;
299
300 *rport_drv = kzalloc(sizeof(struct bfad_rport_s), GFP_ATOMIC);
301 if (*rport_drv == NULL) {
302 rc = BFA_STATUS_ENOMEM;
303 goto ext;
304 }
305
306 *rport = &(*rport_drv)->fcs_rport;
307
308ext:
309 return rc;
310}
311
312
313
314void
315bfad_hal_mem_release(struct bfad_s *bfad)
316{
317 int i;
318 struct bfa_meminfo_s *hal_meminfo = &bfad->meminfo;
319 struct bfa_mem_elem_s *meminfo_elem;
320
321 for (i = 0; i < BFA_MEM_TYPE_MAX; i++) {
322 meminfo_elem = &hal_meminfo->meminfo[i];
323 if (meminfo_elem->kva != NULL) {
324 switch (meminfo_elem->mem_type) {
325 case BFA_MEM_TYPE_KVA:
326 vfree(meminfo_elem->kva);
327 break;
328 case BFA_MEM_TYPE_DMA:
329 dma_free_coherent(&bfad->pcidev->dev,
330 meminfo_elem->mem_len,
331 meminfo_elem->kva,
332 (dma_addr_t) meminfo_elem->dma);
333 break;
334 default:
335 bfa_assert(0);
336 break;
337 }
338 }
339 }
340
341 memset(hal_meminfo, 0, sizeof(struct bfa_meminfo_s));
342}
343
344void
345bfad_update_hal_cfg(struct bfa_iocfc_cfg_s *bfa_cfg)
346{
347 if (num_rports > 0)
348 bfa_cfg->fwcfg.num_rports = num_rports;
349 if (num_ios > 0)
350 bfa_cfg->fwcfg.num_ioim_reqs = num_ios;
351 if (num_tms > 0)
352 bfa_cfg->fwcfg.num_tskim_reqs = num_tms;
353 if (num_fcxps > 0)
354 bfa_cfg->fwcfg.num_fcxp_reqs = num_fcxps;
355 if (num_ufbufs > 0)
356 bfa_cfg->fwcfg.num_uf_bufs = num_ufbufs;
357 if (reqq_size > 0)
358 bfa_cfg->drvcfg.num_reqq_elems = reqq_size;
359 if (rspq_size > 0)
360 bfa_cfg->drvcfg.num_rspq_elems = rspq_size;
361 if (num_sgpgs > 0)
362 bfa_cfg->drvcfg.num_sgpgs = num_sgpgs;
363
364 /*
365 * populate the hal values back to the driver for sysfs use.
366 * otherwise, the default values will be shown as 0 in sysfs
367 */
368 num_rports = bfa_cfg->fwcfg.num_rports;
369 num_ios = bfa_cfg->fwcfg.num_ioim_reqs;
370 num_tms = bfa_cfg->fwcfg.num_tskim_reqs;
371 num_fcxps = bfa_cfg->fwcfg.num_fcxp_reqs;
372 num_ufbufs = bfa_cfg->fwcfg.num_uf_bufs;
373 reqq_size = bfa_cfg->drvcfg.num_reqq_elems;
374 rspq_size = bfa_cfg->drvcfg.num_rspq_elems;
375 num_sgpgs = bfa_cfg->drvcfg.num_sgpgs;
376}
377
378bfa_status_t
379bfad_hal_mem_alloc(struct bfad_s *bfad)
380{
381 struct bfa_meminfo_s *hal_meminfo = &bfad->meminfo;
382 struct bfa_mem_elem_s *meminfo_elem;
383 bfa_status_t rc = BFA_STATUS_OK;
384 dma_addr_t phys_addr;
385 int retry_count = 0;
386 int reset_value = 1;
387 int min_num_sgpgs = 512;
388 void *kva;
389 int i;
390
391 bfa_cfg_get_default(&bfad->ioc_cfg);
392
393retry:
394 bfad_update_hal_cfg(&bfad->ioc_cfg);
395 bfad->cfg_data.ioc_queue_depth = bfad->ioc_cfg.fwcfg.num_ioim_reqs;
396 bfa_cfg_get_meminfo(&bfad->ioc_cfg, hal_meminfo);
397
398 for (i = 0; i < BFA_MEM_TYPE_MAX; i++) {
399 meminfo_elem = &hal_meminfo->meminfo[i];
400 switch (meminfo_elem->mem_type) {
401 case BFA_MEM_TYPE_KVA:
402 kva = vmalloc(meminfo_elem->mem_len);
403 if (kva == NULL) {
404 bfad_hal_mem_release(bfad);
405 rc = BFA_STATUS_ENOMEM;
406 goto ext;
407 }
408 memset(kva, 0, meminfo_elem->mem_len);
409 meminfo_elem->kva = kva;
410 break;
411 case BFA_MEM_TYPE_DMA:
412 kva = dma_alloc_coherent(&bfad->pcidev->dev,
413 meminfo_elem->mem_len,
414 &phys_addr, GFP_KERNEL);
415 if (kva == NULL) {
416 bfad_hal_mem_release(bfad);
417 /*
418 * If we cannot allocate with default
419 * num_sgpages try with half the value.
420 */
421 if (num_sgpgs > min_num_sgpgs) {
422 printk(KERN_INFO "bfad[%d]: memory"
423 " allocation failed with"
424 " num_sgpgs: %d\n",
425 bfad->inst_no, num_sgpgs);
426 nextLowerInt(&num_sgpgs);
427 printk(KERN_INFO "bfad[%d]: trying to"
428 " allocate memory with"
429 " num_sgpgs: %d\n",
430 bfad->inst_no, num_sgpgs);
431 retry_count++;
432 goto retry;
433 } else {
434 if (num_sgpgs_parm > 0)
435 num_sgpgs = num_sgpgs_parm;
436 else {
437 reset_value =
438 (1 << retry_count);
439 num_sgpgs *= reset_value;
440 }
441 rc = BFA_STATUS_ENOMEM;
442 goto ext;
443 }
444 }
445
446 if (num_sgpgs_parm > 0)
447 num_sgpgs = num_sgpgs_parm;
448 else {
449 reset_value = (1 << retry_count);
450 num_sgpgs *= reset_value;
451 }
452
453 memset(kva, 0, meminfo_elem->mem_len);
454 meminfo_elem->kva = kva;
455 meminfo_elem->dma = phys_addr;
456 break;
457 default:
458 break;
459
460 }
461 }
462ext:
463 return rc;
464}
465
466/**
467 * Create a vport under a vf.
468 */
469bfa_status_t
470bfad_vport_create(struct bfad_s *bfad, u16 vf_id,
471 struct bfa_port_cfg_s *port_cfg)
472{
473 struct bfad_vport_s *vport;
474 int rc = BFA_STATUS_OK;
475 unsigned long flags;
476 struct completion fcomp;
477
478 vport = kzalloc(sizeof(struct bfad_vport_s), GFP_KERNEL);
479 if (!vport) {
480 rc = BFA_STATUS_ENOMEM;
481 goto ext;
482 }
483
484 vport->drv_port.bfad = bfad;
485 spin_lock_irqsave(&bfad->bfad_lock, flags);
486 rc = bfa_fcs_vport_create(&vport->fcs_vport, &bfad->bfa_fcs, vf_id,
487 port_cfg, vport);
488 spin_unlock_irqrestore(&bfad->bfad_lock, flags);
489
490 if (rc != BFA_STATUS_OK)
491 goto ext_free_vport;
492
493 if (port_cfg->roles & BFA_PORT_ROLE_FCP_IM) {
494 rc = bfad_im_scsi_host_alloc(bfad, vport->drv_port.im_port);
495 if (rc != BFA_STATUS_OK)
496 goto ext_free_fcs_vport;
497 }
498
499 spin_lock_irqsave(&bfad->bfad_lock, flags);
500 bfa_fcs_vport_start(&vport->fcs_vport);
501 spin_unlock_irqrestore(&bfad->bfad_lock, flags);
502
503 return BFA_STATUS_OK;
504
505ext_free_fcs_vport:
506 spin_lock_irqsave(&bfad->bfad_lock, flags);
507 vport->comp_del = &fcomp;
508 init_completion(vport->comp_del);
509 bfa_fcs_vport_delete(&vport->fcs_vport);
510 spin_unlock_irqrestore(&bfad->bfad_lock, flags);
511 wait_for_completion(vport->comp_del);
512ext_free_vport:
513 kfree(vport);
514ext:
515 return rc;
516}
517
518/**
519 * Create a vf and its base vport implicitely.
520 */
521bfa_status_t
522bfad_vf_create(struct bfad_s *bfad, u16 vf_id,
523 struct bfa_port_cfg_s *port_cfg)
524{
525 struct bfad_vf_s *vf;
526 int rc = BFA_STATUS_OK;
527
528 vf = kzalloc(sizeof(struct bfad_vf_s), GFP_KERNEL);
529 if (!vf) {
530 rc = BFA_STATUS_FAILED;
531 goto ext;
532 }
533
534 rc = bfa_fcs_vf_create(&vf->fcs_vf, &bfad->bfa_fcs, vf_id, port_cfg,
535 vf);
536 if (rc != BFA_STATUS_OK)
537 kfree(vf);
538ext:
539 return rc;
540}
541
542void
543bfad_bfa_tmo(unsigned long data)
544{
545 struct bfad_s *bfad = (struct bfad_s *)data;
546 unsigned long flags;
547 struct list_head doneq;
548
549 spin_lock_irqsave(&bfad->bfad_lock, flags);
550
551 bfa_timer_tick(&bfad->bfa);
552
553 bfa_comp_deq(&bfad->bfa, &doneq);
554 spin_unlock_irqrestore(&bfad->bfad_lock, flags);
555
556 if (!list_empty(&doneq)) {
557 bfa_comp_process(&bfad->bfa, &doneq);
558 spin_lock_irqsave(&bfad->bfad_lock, flags);
559 bfa_comp_free(&bfad->bfa, &doneq);
560 spin_unlock_irqrestore(&bfad->bfad_lock, flags);
561 }
562
563 mod_timer(&bfad->hal_tmo, jiffies + msecs_to_jiffies(BFA_TIMER_FREQ));
564}
565
566void
567bfad_init_timer(struct bfad_s *bfad)
568{
569 init_timer(&bfad->hal_tmo);
570 bfad->hal_tmo.function = bfad_bfa_tmo;
571 bfad->hal_tmo.data = (unsigned long)bfad;
572
573 mod_timer(&bfad->hal_tmo, jiffies + msecs_to_jiffies(BFA_TIMER_FREQ));
574}
575
576int
577bfad_pci_init(struct pci_dev *pdev, struct bfad_s *bfad)
578{
579 unsigned long bar0_len;
580 int rc = -ENODEV;
581
582 if (pci_enable_device(pdev)) {
583 BFA_PRINTF(BFA_ERR, "pci_enable_device fail %p\n", pdev);
584 goto out;
585 }
586
587 if (pci_request_regions(pdev, BFAD_DRIVER_NAME))
588 goto out_disable_device;
589
590 pci_set_master(pdev);
591
592
593 if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0)
594 if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0) {
595 BFA_PRINTF(BFA_ERR, "pci_set_dma_mask fail %p\n", pdev);
596 goto out_release_region;
597 }
598
599 bfad->pci_bar0_map = pci_resource_start(pdev, 0);
600 bar0_len = pci_resource_len(pdev, 0);
601 bfad->pci_bar0_kva = ioremap(bfad->pci_bar0_map, bar0_len);
602
603 if (bfad->pci_bar0_kva == NULL) {
604 BFA_PRINTF(BFA_ERR, "Fail to map bar0\n");
605 goto out_release_region;
606 }
607
608 bfad->hal_pcidev.pci_slot = PCI_SLOT(pdev->devfn);
609 bfad->hal_pcidev.pci_func = PCI_FUNC(pdev->devfn);
610 bfad->hal_pcidev.pci_bar_kva = bfad->pci_bar0_kva;
611 bfad->hal_pcidev.device_id = pdev->device;
612 bfad->pci_name = pci_name(pdev);
613
614 bfad->pci_attr.vendor_id = pdev->vendor;
615 bfad->pci_attr.device_id = pdev->device;
616 bfad->pci_attr.ssid = pdev->subsystem_device;
617 bfad->pci_attr.ssvid = pdev->subsystem_vendor;
618 bfad->pci_attr.pcifn = PCI_FUNC(pdev->devfn);
619
620 bfad->pcidev = pdev;
621 return 0;
622
623out_release_region:
624 pci_release_regions(pdev);
625out_disable_device:
626 pci_disable_device(pdev);
627out:
628 return rc;
629}
630
631void
632bfad_pci_uninit(struct pci_dev *pdev, struct bfad_s *bfad)
633{
634#if defined(__ia64__)
635 pci_iounmap(pdev, bfad->pci_bar0_kva);
636#else
637 iounmap(bfad->pci_bar0_kva);
638#endif
639 pci_release_regions(pdev);
640 pci_disable_device(pdev);
641 pci_set_drvdata(pdev, NULL);
642}
643
644void
645bfad_fcs_port_cfg(struct bfad_s *bfad)
646{
647 struct bfa_port_cfg_s port_cfg;
648 struct bfa_pport_attr_s attr;
649 char symname[BFA_SYMNAME_MAXLEN];
650
651 sprintf(symname, "%s-%d", BFAD_DRIVER_NAME, bfad->inst_no);
652 memcpy(port_cfg.sym_name.symname, symname, strlen(symname));
653 bfa_pport_get_attr(&bfad->bfa, &attr);
654 port_cfg.nwwn = attr.nwwn;
655 port_cfg.pwwn = attr.pwwn;
656
657 bfa_fcs_cfg_base_port(&bfad->bfa_fcs, &port_cfg);
658}
659
660bfa_status_t
661bfad_drv_init(struct bfad_s *bfad)
662{
663 bfa_status_t rc;
664 unsigned long flags;
665 struct bfa_fcs_driver_info_s driver_info;
666 int i;
667
668 bfad->cfg_data.rport_del_timeout = rport_del_timeout;
669 bfad->cfg_data.lun_queue_depth = bfa_lun_queue_depth;
670 bfad->cfg_data.io_max_sge = bfa_io_max_sge;
671 bfad->cfg_data.binding_method = FCP_PWWN_BINDING;
672
673 rc = bfad_hal_mem_alloc(bfad);
674 if (rc != BFA_STATUS_OK) {
675 printk(KERN_WARNING "bfad%d bfad_hal_mem_alloc failure\n",
676 bfad->inst_no);
677 printk(KERN_WARNING
678 "Not enough memory to attach all Brocade HBA ports,"
679 " System may need more memory.\n");
680 goto out_hal_mem_alloc_failure;
681 }
682
683 bfa_init_log(&bfad->bfa, bfad->logmod);
684 bfa_init_trc(&bfad->bfa, bfad->trcmod);
685 bfa_init_aen(&bfad->bfa, bfad->aen);
686 INIT_LIST_HEAD(&bfad->file_q);
687 INIT_LIST_HEAD(&bfad->file_free_q);
688 for (i = 0; i < BFAD_AEN_MAX_APPS; i++) {
689 bfa_q_qe_init(&bfad->file_buf[i].qe);
690 list_add_tail(&bfad->file_buf[i].qe, &bfad->file_free_q);
691 }
692 bfa_init_plog(&bfad->bfa, &bfad->plog_buf);
693 bfa_plog_init(&bfad->plog_buf);
694 bfa_plog_str(&bfad->plog_buf, BFA_PL_MID_DRVR, BFA_PL_EID_DRIVER_START,
695 0, "Driver Attach");
696
697 bfa_attach(&bfad->bfa, bfad, &bfad->ioc_cfg, &bfad->meminfo,
698 &bfad->hal_pcidev);
699
700 init_completion(&bfad->comp);
701
702 /*
703 * Enable Interrupt and wait bfa_init completion
704 */
705 if (bfad_setup_intr(bfad)) {
706 printk(KERN_WARNING "bfad%d: bfad_setup_intr failed\n",
707 bfad->inst_no);
708 goto out_setup_intr_failure;
709 }
710
711 spin_lock_irqsave(&bfad->bfad_lock, flags);
712 bfa_init(&bfad->bfa);
713 spin_unlock_irqrestore(&bfad->bfad_lock, flags);
714
715 /*
716 * Set up interrupt handler for each vectors
717 */
718 if ((bfad->bfad_flags & BFAD_MSIX_ON)
719 && bfad_install_msix_handler(bfad)) {
720 printk(KERN_WARNING "%s: install_msix failed, bfad%d\n",
Jing Huangf8ceafd2009-09-25 12:29:54 -0700721 __func__, bfad->inst_no);
Jing Huang7725ccf2009-09-23 17:46:15 -0700722 }
723
724 bfad_init_timer(bfad);
725
726 wait_for_completion(&bfad->comp);
727
728 memset(&driver_info, 0, sizeof(driver_info));
729 strncpy(driver_info.version, BFAD_DRIVER_VERSION,
730 sizeof(driver_info.version) - 1);
731 if (host_name)
732 strncpy(driver_info.host_machine_name, host_name,
733 sizeof(driver_info.host_machine_name) - 1);
734 if (os_name)
735 strncpy(driver_info.host_os_name, os_name,
736 sizeof(driver_info.host_os_name) - 1);
737 if (os_patch)
738 strncpy(driver_info.host_os_patch, os_patch,
739 sizeof(driver_info.host_os_patch) - 1);
740
741 strncpy(driver_info.os_device_name, bfad->pci_name,
742 sizeof(driver_info.os_device_name - 1));
743
744 /*
745 * FCS INIT
746 */
747 spin_lock_irqsave(&bfad->bfad_lock, flags);
748 bfa_fcs_log_init(&bfad->bfa_fcs, bfad->logmod);
749 bfa_fcs_trc_init(&bfad->bfa_fcs, bfad->trcmod);
750 bfa_fcs_aen_init(&bfad->bfa_fcs, bfad->aen);
751 bfa_fcs_init(&bfad->bfa_fcs, &bfad->bfa, bfad, BFA_FALSE);
752 bfa_fcs_driver_info_init(&bfad->bfa_fcs, &driver_info);
Krishna Gudipati5b098082010-03-03 17:43:19 -0800753 bfa_fcs_set_fdmi_param(&bfad->bfa_fcs, fdmi_enable);
Jing Huang7725ccf2009-09-23 17:46:15 -0700754 spin_unlock_irqrestore(&bfad->bfad_lock, flags);
755
756 bfad->bfad_flags |= BFAD_DRV_INIT_DONE;
757 return BFA_STATUS_OK;
758
759out_setup_intr_failure:
760 bfa_detach(&bfad->bfa);
761 bfad_hal_mem_release(bfad);
762out_hal_mem_alloc_failure:
763 return BFA_STATUS_FAILED;
764}
765
766void
767bfad_drv_uninit(struct bfad_s *bfad)
768{
769 del_timer_sync(&bfad->hal_tmo);
770 bfa_isr_disable(&bfad->bfa);
771 bfa_detach(&bfad->bfa);
772 bfad_remove_intr(bfad);
773 bfa_assert(list_empty(&bfad->file_q));
774 bfad_hal_mem_release(bfad);
775}
776
777void
778bfad_drv_start(struct bfad_s *bfad)
779{
780 unsigned long flags;
781
782 spin_lock_irqsave(&bfad->bfad_lock, flags);
783 bfa_start(&bfad->bfa);
784 bfa_fcs_start(&bfad->bfa_fcs);
785 bfad->bfad_flags |= BFAD_HAL_START_DONE;
786 spin_unlock_irqrestore(&bfad->bfad_lock, flags);
787
788 bfad_fc4_probe_post(bfad);
789}
790
791void
792bfad_drv_stop(struct bfad_s *bfad)
793{
794 unsigned long flags;
795
796 spin_lock_irqsave(&bfad->bfad_lock, flags);
797 init_completion(&bfad->comp);
798 bfad->pport.flags |= BFAD_PORT_DELETE;
799 bfa_fcs_exit(&bfad->bfa_fcs);
800 spin_unlock_irqrestore(&bfad->bfad_lock, flags);
801 wait_for_completion(&bfad->comp);
802
803 spin_lock_irqsave(&bfad->bfad_lock, flags);
804 init_completion(&bfad->comp);
805 bfa_stop(&bfad->bfa);
806 bfad->bfad_flags &= ~BFAD_HAL_START_DONE;
807 spin_unlock_irqrestore(&bfad->bfad_lock, flags);
808 wait_for_completion(&bfad->comp);
809}
810
811bfa_status_t
812bfad_cfg_pport(struct bfad_s *bfad, enum bfa_port_role role)
813{
814 int rc = BFA_STATUS_OK;
815
816 /*
817 * Allocate scsi_host for the physical port
818 */
819 if ((bfad_supported_fc4s & BFA_PORT_ROLE_FCP_IM)
820 && (role & BFA_PORT_ROLE_FCP_IM)) {
821 if (bfad->pport.im_port == NULL) {
822 rc = BFA_STATUS_FAILED;
823 goto out;
824 }
825
826 rc = bfad_im_scsi_host_alloc(bfad, bfad->pport.im_port);
827 if (rc != BFA_STATUS_OK)
828 goto out;
829
830 bfad->pport.roles |= BFA_PORT_ROLE_FCP_IM;
831 }
832
833 bfad->bfad_flags |= BFAD_CFG_PPORT_DONE;
834
835out:
836 return rc;
837}
838
839void
840bfad_uncfg_pport(struct bfad_s *bfad)
841{
842 if ((bfad->pport.roles & BFA_PORT_ROLE_FCP_IPFC) && ipfc_enable) {
843 bfad_ipfc_port_delete(bfad, &bfad->pport);
844 bfad->pport.roles &= ~BFA_PORT_ROLE_FCP_IPFC;
845 }
846
847 if ((bfad_supported_fc4s & BFA_PORT_ROLE_FCP_IM)
848 && (bfad->pport.roles & BFA_PORT_ROLE_FCP_IM)) {
849 bfad_im_scsi_host_free(bfad, bfad->pport.im_port);
850 bfad_im_port_clean(bfad->pport.im_port);
851 kfree(bfad->pport.im_port);
852 bfad->pport.roles &= ~BFA_PORT_ROLE_FCP_IM;
853 }
854
855 bfad->bfad_flags &= ~BFAD_CFG_PPORT_DONE;
856}
857
858void
859bfad_drv_log_level_set(struct bfad_s *bfad)
860{
861 if (log_level > BFA_LOG_INVALID && log_level <= BFA_LOG_LEVEL_MAX)
862 bfa_log_set_level_all(&bfad->log_data, log_level);
863}
864
865 /*
866 * PCI_entry PCI driver entries * {
867 */
868
869/**
870 * PCI probe entry.
871 */
872int
873bfad_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid)
874{
875 struct bfad_s *bfad;
876 int error = -ENODEV, retval;
877 char buf[16];
878
879 /*
880 * For single port cards - only claim function 0
881 */
882 if ((pdev->device == BFA_PCI_DEVICE_ID_FC_8G1P)
883 && (PCI_FUNC(pdev->devfn) != 0))
884 return -ENODEV;
885
886 BFA_TRACE(BFA_INFO, "bfad_pci_probe entry");
887
888 bfad = kzalloc(sizeof(struct bfad_s), GFP_KERNEL);
889 if (!bfad) {
890 error = -ENOMEM;
891 goto out;
892 }
893
894 bfad->trcmod = kzalloc(sizeof(struct bfa_trc_mod_s), GFP_KERNEL);
895 if (!bfad->trcmod) {
896 printk(KERN_WARNING "Error alloc trace buffer!\n");
897 error = -ENOMEM;
898 goto out_alloc_trace_failure;
899 }
900
901 /*
902 * LOG/TRACE INIT
903 */
904 bfa_trc_init(bfad->trcmod);
905 bfa_trc(bfad, bfad_inst);
906
907 bfad->logmod = &bfad->log_data;
908 sprintf(buf, "%d", bfad_inst);
909 bfa_log_init(bfad->logmod, buf, bfa_os_printf);
910
911 bfad_drv_log_level_set(bfad);
912
913 bfad->aen = &bfad->aen_buf;
914
915 if (!(bfad_load_fwimg(pdev))) {
916 printk(KERN_WARNING "bfad_load_fwimg failure!\n");
917 kfree(bfad->trcmod);
918 goto out_alloc_trace_failure;
919 }
920
921 retval = bfad_pci_init(pdev, bfad);
922 if (retval) {
923 printk(KERN_WARNING "bfad_pci_init failure!\n");
924 error = retval;
925 goto out_pci_init_failure;
926 }
927
928 mutex_lock(&bfad_mutex);
929 bfad->inst_no = bfad_inst++;
930 list_add_tail(&bfad->list_entry, &bfad_list);
931 mutex_unlock(&bfad_mutex);
932
933 spin_lock_init(&bfad->bfad_lock);
934 pci_set_drvdata(pdev, bfad);
935
936 bfad->ref_count = 0;
937 bfad->pport.bfad = bfad;
938
939 retval = bfad_drv_init(bfad);
940 if (retval != BFA_STATUS_OK)
941 goto out_drv_init_failure;
942 if (!(bfad->bfad_flags & BFAD_HAL_INIT_DONE)) {
943 printk(KERN_WARNING "bfad%d: hal init failed\n", bfad->inst_no);
944 goto ok;
945 }
946
947 /*
948 * PPORT FCS config
949 */
950 bfad_fcs_port_cfg(bfad);
951
952 retval = bfad_cfg_pport(bfad, BFA_PORT_ROLE_FCP_IM);
953 if (retval != BFA_STATUS_OK)
954 goto out_cfg_pport_failure;
955
956 /*
957 * BFAD level FC4 (IM/TM/IPFC) specific resource allocation
958 */
959 retval = bfad_fc4_probe(bfad);
960 if (retval != BFA_STATUS_OK) {
961 printk(KERN_WARNING "bfad_fc4_probe failed\n");
962 goto out_fc4_probe_failure;
963 }
964
965 bfad_drv_start(bfad);
966
967 /*
968 * If bfa_linkup_delay is set to -1 default; try to retrive the
969 * value using the bfad_os_get_linkup_delay(); else use the
970 * passed in module param value as the bfa_linkup_delay.
971 */
972 if (bfa_linkup_delay < 0) {
973 bfa_linkup_delay = bfad_os_get_linkup_delay(bfad);
974 bfad_os_rport_online_wait(bfad);
975 bfa_linkup_delay = -1;
976 } else {
977 bfad_os_rport_online_wait(bfad);
978 }
979
980 bfa_log(bfad->logmod, BFA_LOG_LINUX_DEVICE_CLAIMED, bfad->pci_name);
981ok:
982 return 0;
983
984out_fc4_probe_failure:
985 bfad_fc4_probe_undo(bfad);
986 bfad_uncfg_pport(bfad);
987out_cfg_pport_failure:
988 bfad_drv_uninit(bfad);
989out_drv_init_failure:
990 mutex_lock(&bfad_mutex);
991 bfad_inst--;
992 list_del(&bfad->list_entry);
993 mutex_unlock(&bfad_mutex);
994 bfad_pci_uninit(pdev, bfad);
995out_pci_init_failure:
996 kfree(bfad->trcmod);
997out_alloc_trace_failure:
998 kfree(bfad);
999out:
1000 return error;
1001}
1002
1003/**
1004 * PCI remove entry.
1005 */
1006void
1007bfad_pci_remove(struct pci_dev *pdev)
1008{
1009 struct bfad_s *bfad = pci_get_drvdata(pdev);
1010 unsigned long flags;
1011
1012 bfa_trc(bfad, bfad->inst_no);
1013
1014 if ((bfad->bfad_flags & BFAD_DRV_INIT_DONE)
1015 && !(bfad->bfad_flags & BFAD_HAL_INIT_DONE)) {
1016
1017 spin_lock_irqsave(&bfad->bfad_lock, flags);
1018 init_completion(&bfad->comp);
1019 bfa_stop(&bfad->bfa);
1020 spin_unlock_irqrestore(&bfad->bfad_lock, flags);
1021 wait_for_completion(&bfad->comp);
1022
1023 bfad_remove_intr(bfad);
1024 del_timer_sync(&bfad->hal_tmo);
1025 goto hal_detach;
1026 } else if (!(bfad->bfad_flags & BFAD_DRV_INIT_DONE)) {
1027 goto remove_sysfs;
1028 }
1029
1030 if (bfad->bfad_flags & BFAD_HAL_START_DONE)
1031 bfad_drv_stop(bfad);
1032
1033 bfad_remove_intr(bfad);
1034
1035 del_timer_sync(&bfad->hal_tmo);
1036 bfad_fc4_probe_undo(bfad);
1037
1038 if (bfad->bfad_flags & BFAD_CFG_PPORT_DONE)
1039 bfad_uncfg_pport(bfad);
1040
1041hal_detach:
1042 spin_lock_irqsave(&bfad->bfad_lock, flags);
1043 bfa_detach(&bfad->bfa);
1044 spin_unlock_irqrestore(&bfad->bfad_lock, flags);
1045 bfad_hal_mem_release(bfad);
1046remove_sysfs:
1047
1048 mutex_lock(&bfad_mutex);
1049 bfad_inst--;
1050 list_del(&bfad->list_entry);
1051 mutex_unlock(&bfad_mutex);
1052 bfad_pci_uninit(pdev, bfad);
1053
1054 kfree(bfad->trcmod);
1055 kfree(bfad);
1056}
1057
1058
1059static struct pci_device_id bfad_id_table[] = {
1060 {
1061 .vendor = BFA_PCI_VENDOR_ID_BROCADE,
1062 .device = BFA_PCI_DEVICE_ID_FC_8G2P,
1063 .subvendor = PCI_ANY_ID,
1064 .subdevice = PCI_ANY_ID,
1065 },
1066 {
1067 .vendor = BFA_PCI_VENDOR_ID_BROCADE,
1068 .device = BFA_PCI_DEVICE_ID_FC_8G1P,
1069 .subvendor = PCI_ANY_ID,
1070 .subdevice = PCI_ANY_ID,
1071 },
1072 {
1073 .vendor = BFA_PCI_VENDOR_ID_BROCADE,
1074 .device = BFA_PCI_DEVICE_ID_CT,
1075 .subvendor = PCI_ANY_ID,
1076 .subdevice = PCI_ANY_ID,
1077 .class = (PCI_CLASS_SERIAL_FIBER << 8),
1078 .class_mask = ~0,
1079 },
1080
1081 {0, 0},
1082};
1083
1084MODULE_DEVICE_TABLE(pci, bfad_id_table);
1085
1086static struct pci_driver bfad_pci_driver = {
1087 .name = BFAD_DRIVER_NAME,
1088 .id_table = bfad_id_table,
1089 .probe = bfad_pci_probe,
1090 .remove = __devexit_p(bfad_pci_remove),
1091};
1092
1093/**
1094 * Linux driver module functions
1095 */
1096bfa_status_t
1097bfad_fc4_module_init(void)
1098{
1099 int rc;
1100
1101 rc = bfad_im_module_init();
1102 if (rc != BFA_STATUS_OK)
1103 goto ext;
1104
1105 bfad_tm_module_init();
1106 if (ipfc_enable)
1107 bfad_ipfc_module_init();
1108ext:
1109 return rc;
1110}
1111
1112void
1113bfad_fc4_module_exit(void)
1114{
1115 if (ipfc_enable)
1116 bfad_ipfc_module_exit();
1117 bfad_tm_module_exit();
1118 bfad_im_module_exit();
1119}
1120
1121/**
1122 * Driver module init.
1123 */
1124static int __init
1125bfad_init(void)
1126{
1127 int error = 0;
1128
1129 printk(KERN_INFO "Brocade BFA FC/FCOE SCSI driver - version: %s\n",
1130 BFAD_DRIVER_VERSION);
1131
1132 if (num_sgpgs > 0)
1133 num_sgpgs_parm = num_sgpgs;
1134
1135 error = bfad_fc4_module_init();
1136 if (error) {
1137 error = -ENOMEM;
1138 printk(KERN_WARNING "bfad_fc4_module_init failure\n");
1139 goto ext;
1140 }
1141
1142 if (!strcmp(FCPI_NAME, " fcpim"))
1143 bfad_supported_fc4s |= BFA_PORT_ROLE_FCP_IM;
1144 if (!strcmp(FCPT_NAME, " fcptm"))
1145 bfad_supported_fc4s |= BFA_PORT_ROLE_FCP_TM;
1146 if (!strcmp(IPFC_NAME, " ipfc"))
1147 bfad_supported_fc4s |= BFA_PORT_ROLE_FCP_IPFC;
1148
1149 bfa_ioc_auto_recover(ioc_auto_recover);
1150 bfa_fcs_rport_set_del_timeout(rport_del_timeout);
1151 error = pci_register_driver(&bfad_pci_driver);
1152
1153 if (error) {
1154 printk(KERN_WARNING "bfad pci_register_driver failure\n");
1155 goto ext;
1156 }
1157
1158 return 0;
1159
1160ext:
1161 bfad_fc4_module_exit();
1162 return error;
1163}
1164
1165/**
1166 * Driver module exit.
1167 */
1168static void __exit
1169bfad_exit(void)
1170{
1171 pci_unregister_driver(&bfad_pci_driver);
1172 bfad_fc4_module_exit();
1173 bfad_free_fwimg();
1174}
1175
1176#define BFAD_PROTO_NAME FCPI_NAME FCPT_NAME IPFC_NAME
1177
1178module_init(bfad_init);
1179module_exit(bfad_exit);
1180MODULE_LICENSE("GPL");
1181MODULE_DESCRIPTION("Brocade Fibre Channel HBA Driver" BFAD_PROTO_NAME);
1182MODULE_AUTHOR("Brocade Communications Systems, Inc.");
1183MODULE_VERSION(BFAD_DRIVER_VERSION);
1184
1185