bfad.c revision 604158ade0d5378622541232a007bf975c8bd03f
17725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang/*
27725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
37725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang * All rights reserved
47725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang * www.brocade.com
57725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang *
67725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang * Linux driver for Brocade Fibre Channel Host Bus Adapter.
77725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang *
87725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang * This program is free software; you can redistribute it and/or modify it
97725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang * under the terms of the GNU General Public License (GPL) Version 2 as
107725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang * published by the Free Software Foundation
117725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang *
127725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang * This program is distributed in the hope that it will be useful, but
137725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang * WITHOUT ANY WARRANTY; without even the implied warranty of
147725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
157725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang * General Public License for more details.
167725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang */
177725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
187725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang/**
197725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang *  bfad.c Linux driver PCI interface module.
207725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang */
217725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
225a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
237725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang#include <linux/module.h>
24e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati#include <linux/kthread.h>
257725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang#include "bfad_drv.h"
267725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang#include "bfad_im.h"
277725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang#include "bfad_tm.h"
287725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang#include "bfad_ipfc.h"
297725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang#include "bfad_trcmod.h"
307725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang#include <fcb/bfa_fcb_vf.h>
317725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang#include <fcb/bfa_fcb_rport.h>
327725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang#include <fcb/bfa_fcb_port.h>
337725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang#include <fcb/bfa_fcb.h>
347725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
357725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing HuangBFA_TRC_FILE(LDRV, BFAD);
3642b426ecb453cf49c3d16cf1d7a5e5d8cab9869dJing HuangDEFINE_MUTEX(bfad_mutex);
377725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing HuangLIST_HEAD(bfad_list);
387725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangstatic int      bfad_inst;
397725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangint bfad_supported_fc4s;
407725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
417725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangstatic char     *host_name;
427725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangstatic char     *os_name;
437725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangstatic char     *os_patch;
447725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangstatic int      num_rports;
457725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangstatic int      num_ios;
467725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangstatic int      num_tms;
477725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangstatic int      num_fcxps;
487725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangstatic int      num_ufbufs;
497725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangstatic int      reqq_size;
507725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangstatic int      rspq_size;
517725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangstatic int      num_sgpgs;
527725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangstatic int      rport_del_timeout = BFA_FCS_RPORT_DEF_DEL_TIMEOUT;
537725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangstatic int      bfa_io_max_sge = BFAD_IO_MAX_SGE;
547725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangstatic int      log_level = BFA_LOG_WARNING;
557725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangstatic int      ioc_auto_recover = BFA_TRUE;
567725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangstatic int      ipfc_enable = BFA_FALSE;
575b098082e22c168b7df4c5c3cd924047cee7d995Krishna Gudipatistatic int	fdmi_enable = BFA_TRUE;
587725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangint 		bfa_lun_queue_depth = BFAD_LUN_QUEUE_DEPTH;
597725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangint      	bfa_linkup_delay = -1;
607725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
617725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangmodule_param(os_name, charp, S_IRUGO | S_IWUSR);
62604158ade0d5378622541232a007bf975c8bd03fJing HuangMODULE_PARM_DESC(os_name, "OS name of the hba host machine");
637725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangmodule_param(os_patch, charp, S_IRUGO | S_IWUSR);
64604158ade0d5378622541232a007bf975c8bd03fJing HuangMODULE_PARM_DESC(os_patch, "OS patch level of the hba host machine");
657725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangmodule_param(host_name, charp, S_IRUGO | S_IWUSR);
66604158ade0d5378622541232a007bf975c8bd03fJing HuangMODULE_PARM_DESC(host_name, "Hostname of the hba host machine");
677725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangmodule_param(num_rports, int, S_IRUGO | S_IWUSR);
68604158ade0d5378622541232a007bf975c8bd03fJing HuangMODULE_PARM_DESC(num_rports, "Max number of rports supported per port"
69604158ade0d5378622541232a007bf975c8bd03fJing Huang		" (physical/logical), default=1024");
707725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangmodule_param(num_ios, int, S_IRUGO | S_IWUSR);
71604158ade0d5378622541232a007bf975c8bd03fJing HuangMODULE_PARM_DESC(num_ios, "Max number of ioim requests, default=2000");
727725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangmodule_param(num_tms, int, S_IRUGO | S_IWUSR);
73604158ade0d5378622541232a007bf975c8bd03fJing HuangMODULE_PARM_DESC(num_tms, "Max number of task im requests, default=128");
747725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangmodule_param(num_fcxps, int, S_IRUGO | S_IWUSR);
75604158ade0d5378622541232a007bf975c8bd03fJing HuangMODULE_PARM_DESC(num_fcxps, "Max number of fcxp requests, default=64");
767725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangmodule_param(num_ufbufs, int, S_IRUGO | S_IWUSR);
77604158ade0d5378622541232a007bf975c8bd03fJing HuangMODULE_PARM_DESC(num_ufbufs, "Max number of unsolicited frame buffers,"
78604158ade0d5378622541232a007bf975c8bd03fJing Huang		" default=64");
797725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangmodule_param(reqq_size, int, S_IRUGO | S_IWUSR);
80604158ade0d5378622541232a007bf975c8bd03fJing HuangMODULE_PARM_DESC(reqq_size, "Max number of request queue elements,"
81604158ade0d5378622541232a007bf975c8bd03fJing Huang		" default=256");
827725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangmodule_param(rspq_size, int, S_IRUGO | S_IWUSR);
83604158ade0d5378622541232a007bf975c8bd03fJing HuangMODULE_PARM_DESC(rspq_size, "Max number of response queue elements,"
84604158ade0d5378622541232a007bf975c8bd03fJing Huang		" default=64");
857725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangmodule_param(num_sgpgs, int, S_IRUGO | S_IWUSR);
86604158ade0d5378622541232a007bf975c8bd03fJing HuangMODULE_PARM_DESC(num_sgpgs, "Number of scatter/gather pages, default=2048");
877725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangmodule_param(rport_del_timeout, int, S_IRUGO | S_IWUSR);
88604158ade0d5378622541232a007bf975c8bd03fJing HuangMODULE_PARM_DESC(rport_del_timeout, "Rport delete timeout, default=90 secs,"
89604158ade0d5378622541232a007bf975c8bd03fJing Huang		" Range[>0]");
907725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangmodule_param(bfa_lun_queue_depth, int, S_IRUGO | S_IWUSR);
91604158ade0d5378622541232a007bf975c8bd03fJing HuangMODULE_PARM_DESC(bfa_lun_queue_depth, "Lun queue depth, default=32,"
92604158ade0d5378622541232a007bf975c8bd03fJing Huang		" Range[>0]");
937725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangmodule_param(bfa_io_max_sge, int, S_IRUGO | S_IWUSR);
94604158ade0d5378622541232a007bf975c8bd03fJing HuangMODULE_PARM_DESC(bfa_io_max_sge, "Max io scatter/gather elements, default=255");
957725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangmodule_param(log_level, int, S_IRUGO | S_IWUSR);
96604158ade0d5378622541232a007bf975c8bd03fJing HuangMODULE_PARM_DESC(log_level, "Driver log level, default=3,"
97604158ade0d5378622541232a007bf975c8bd03fJing Huang		" Range[Critical:1|Error:2|Warning:3|Info:4]");
987725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangmodule_param(ioc_auto_recover, int, S_IRUGO | S_IWUSR);
99604158ade0d5378622541232a007bf975c8bd03fJing HuangMODULE_PARM_DESC(ioc_auto_recover, "IOC auto recovery, default=1,"
100604158ade0d5378622541232a007bf975c8bd03fJing Huang		" Range[off:0|on:1]");
1017725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangmodule_param(ipfc_enable, int, S_IRUGO | S_IWUSR);
102604158ade0d5378622541232a007bf975c8bd03fJing HuangMODULE_PARM_DESC(ipfc_enable, "Enable IPoFC, default=0, Range[off:0|on:1]");
1037725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangmodule_param(bfa_linkup_delay, int, S_IRUGO | S_IWUSR);
104604158ade0d5378622541232a007bf975c8bd03fJing HuangMODULE_PARM_DESC(bfa_linkup_delay, "Link up delay, default=30 secs for boot"
105604158ade0d5378622541232a007bf975c8bd03fJing Huang		" port. Otherwise Range[>0]");
106604158ade0d5378622541232a007bf975c8bd03fJing Huangmodule_param(fdmi_enable, int, S_IRUGO | S_IWUSR);
107604158ade0d5378622541232a007bf975c8bd03fJing HuangMODULE_PARM_DESC(fdmi_enable, "Enables fdmi registration, default=1,"
108604158ade0d5378622541232a007bf975c8bd03fJing Huang		" Range[false:0|true:1]");
1097725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
1107725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang/*
1117725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang * Stores the module parm num_sgpgs value;
1127725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang * used to reset for bfad next instance.
1137725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang */
1147725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangstatic int num_sgpgs_parm;
1157725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
1167725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangstatic bfa_status_t
1177725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangbfad_fc4_probe(struct bfad_s *bfad)
1187725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang{
1197725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	int             rc;
1207725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
1217725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	rc = bfad_im_probe(bfad);
1227725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (rc != BFA_STATUS_OK)
1237725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		goto ext;
1247725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
1257725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad_tm_probe(bfad);
1267725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
1277725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (ipfc_enable)
1287725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		bfad_ipfc_probe(bfad);
129e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati
130e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	bfad->bfad_flags |= BFAD_FC4_PROBE_DONE;
1317725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangext:
1327725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	return rc;
1337725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang}
1347725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
1357725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangstatic void
1367725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangbfad_fc4_probe_undo(struct bfad_s *bfad)
1377725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang{
1387725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad_im_probe_undo(bfad);
1397725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad_tm_probe_undo(bfad);
1407725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (ipfc_enable)
1417725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		bfad_ipfc_probe_undo(bfad);
142e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	bfad->bfad_flags &= ~BFAD_FC4_PROBE_DONE;
1437725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang}
1447725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
1457725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangstatic void
1467725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangbfad_fc4_probe_post(struct bfad_s *bfad)
1477725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang{
1487725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (bfad->im)
1497725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		bfad_im_probe_post(bfad->im);
1507725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
1517725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad_tm_probe_post(bfad);
1527725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (ipfc_enable)
1537725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		bfad_ipfc_probe_post(bfad);
1547725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang}
1557725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
1567725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangstatic bfa_status_t
1577725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangbfad_fc4_port_new(struct bfad_s *bfad, struct bfad_port_s *port, int roles)
1587725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang{
1597725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	int             rc = BFA_STATUS_FAILED;
1607725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
1617725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (roles & BFA_PORT_ROLE_FCP_IM)
1627725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		rc = bfad_im_port_new(bfad, port);
1637725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (rc != BFA_STATUS_OK)
1647725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		goto ext;
1657725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
1667725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (roles & BFA_PORT_ROLE_FCP_TM)
1677725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		rc = bfad_tm_port_new(bfad, port);
1687725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (rc != BFA_STATUS_OK)
1697725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		goto ext;
1707725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
1717725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if ((roles & BFA_PORT_ROLE_FCP_IPFC) && ipfc_enable)
1727725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		rc = bfad_ipfc_port_new(bfad, port, port->pvb_type);
1737725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangext:
1747725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	return rc;
1757725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang}
1767725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
1777725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangstatic void
1787725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangbfad_fc4_port_delete(struct bfad_s *bfad, struct bfad_port_s *port, int roles)
1797725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang{
1807725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (roles & BFA_PORT_ROLE_FCP_IM)
1817725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		bfad_im_port_delete(bfad, port);
1827725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
1837725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (roles & BFA_PORT_ROLE_FCP_TM)
1847725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		bfad_tm_port_delete(bfad, port);
1857725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
1867725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if ((roles & BFA_PORT_ROLE_FCP_IPFC) && ipfc_enable)
1877725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		bfad_ipfc_port_delete(bfad, port);
1887725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang}
1897725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
1907725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang/**
1917725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang *  BFA callbacks
1927725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang */
1937725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangvoid
1947725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangbfad_hcb_comp(void *arg, bfa_status_t status)
1957725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang{
1967725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	struct bfad_hal_comp *fcomp = (struct bfad_hal_comp *)arg;
1977725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
1987725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	fcomp->status = status;
1997725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	complete(&fcomp->comp);
2007725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang}
2017725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
2027725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang/**
2037725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang * bfa_init callback
2047725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang */
2057725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangvoid
2067725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangbfa_cb_init(void *drv, bfa_status_t init_status)
2077725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang{
2087725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	struct bfad_s  *bfad = drv;
2097725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
210e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	if (init_status == BFA_STATUS_OK) {
2117725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		bfad->bfad_flags |= BFAD_HAL_INIT_DONE;
2127725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
213e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati		/* If BFAD_HAL_INIT_FAIL flag is set:
214e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati		 * Wake up the kernel thread to start
215e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati		 * the bfad operations after HAL init done
216e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati		 */
217e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati		if ((bfad->bfad_flags & BFAD_HAL_INIT_FAIL)) {
218e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati			bfad->bfad_flags &= ~BFAD_HAL_INIT_FAIL;
219e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati			wake_up_process(bfad->bfad_tsk);
220e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati		}
221e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	}
222e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati
2237725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	complete(&bfad->comp);
2247725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang}
2257725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
2267725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
2277725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
2287725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang/**
2297725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang *  BFA_FCS callbacks
2307725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang */
2317725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangstatic struct bfad_port_s *
2327725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangbfad_get_drv_port(struct bfad_s *bfad, struct bfad_vf_s *vf_drv,
2337725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		  struct bfad_vport_s *vp_drv)
2347725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang{
235f8ceafde6f5bf6b4b7087c7f5e9da1b2a5284a2eJing Huang	return (vp_drv) ? (&(vp_drv)->drv_port)
236f8ceafde6f5bf6b4b7087c7f5e9da1b2a5284a2eJing Huang		: ((vf_drv) ? (&(vf_drv)->base_port) : (&(bfad)->pport));
2377725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang}
2387725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
2397725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangstruct bfad_port_s *
2407725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangbfa_fcb_port_new(struct bfad_s *bfad, struct bfa_fcs_port_s *port,
2417725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		 enum bfa_port_role roles, struct bfad_vf_s *vf_drv,
2427725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		 struct bfad_vport_s *vp_drv)
2437725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang{
2447725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfa_status_t    rc;
2457725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	struct bfad_port_s *port_drv;
2467725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
2477725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (!vp_drv && !vf_drv) {
2487725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		port_drv = &bfad->pport;
2497725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		port_drv->pvb_type = BFAD_PORT_PHYS_BASE;
2507725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	} else if (!vp_drv && vf_drv) {
2517725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		port_drv = &vf_drv->base_port;
2527725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		port_drv->pvb_type = BFAD_PORT_VF_BASE;
2537725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	} else if (vp_drv && !vf_drv) {
2547725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		port_drv = &vp_drv->drv_port;
2557725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		port_drv->pvb_type = BFAD_PORT_PHYS_VPORT;
2567725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	} else {
2577725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		port_drv = &vp_drv->drv_port;
2587725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		port_drv->pvb_type = BFAD_PORT_VF_VPORT;
2597725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	}
2607725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
2617725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	port_drv->fcs_port = port;
2627725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	port_drv->roles = roles;
2637725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	rc = bfad_fc4_port_new(bfad, port_drv, roles);
2647725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (rc != BFA_STATUS_OK) {
2657725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		bfad_fc4_port_delete(bfad, port_drv, roles);
2667725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		port_drv = NULL;
2677725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	}
2687725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
2697725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	return port_drv;
2707725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang}
2717725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
2727725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangvoid
2737725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangbfa_fcb_port_delete(struct bfad_s *bfad, enum bfa_port_role roles,
2747725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		    struct bfad_vf_s *vf_drv, struct bfad_vport_s *vp_drv)
2757725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang{
2767725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	struct bfad_port_s *port_drv;
2777725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
2787725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	/*
2797725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	 * this will be only called from rmmod context
2807725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	 */
2817725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (vp_drv && !vp_drv->comp_del) {
2827725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		port_drv = bfad_get_drv_port(bfad, vf_drv, vp_drv);
2837725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		bfa_trc(bfad, roles);
2847725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		bfad_fc4_port_delete(bfad, port_drv, roles);
2857725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	}
2867725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang}
2877725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
2887725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangvoid
2897725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangbfa_fcb_port_online(struct bfad_s *bfad, enum bfa_port_role roles,
2907725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		    struct bfad_vf_s *vf_drv, struct bfad_vport_s *vp_drv)
2917725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang{
2927725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	struct bfad_port_s *port_drv = bfad_get_drv_port(bfad, vf_drv, vp_drv);
2937725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
2947725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (roles & BFA_PORT_ROLE_FCP_IM)
2957725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		bfad_im_port_online(bfad, port_drv);
2967725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
2977725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (roles & BFA_PORT_ROLE_FCP_TM)
2987725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		bfad_tm_port_online(bfad, port_drv);
2997725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
3007725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if ((roles & BFA_PORT_ROLE_FCP_IPFC) && ipfc_enable)
3017725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		bfad_ipfc_port_online(bfad, port_drv);
3027725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
3037725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad->bfad_flags |= BFAD_PORT_ONLINE;
3047725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang}
3057725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
3067725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangvoid
3077725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangbfa_fcb_port_offline(struct bfad_s *bfad, enum bfa_port_role roles,
3087725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		     struct bfad_vf_s *vf_drv, struct bfad_vport_s *vp_drv)
3097725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang{
3107725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	struct bfad_port_s *port_drv = bfad_get_drv_port(bfad, vf_drv, vp_drv);
3117725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
3127725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (roles & BFA_PORT_ROLE_FCP_IM)
3137725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		bfad_im_port_offline(bfad, port_drv);
3147725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
3157725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (roles & BFA_PORT_ROLE_FCP_TM)
3167725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		bfad_tm_port_offline(bfad, port_drv);
3177725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
3187725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if ((roles & BFA_PORT_ROLE_FCP_IPFC) && ipfc_enable)
3197725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		bfad_ipfc_port_offline(bfad, port_drv);
3207725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang}
3217725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
3227725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangvoid
3237725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangbfa_fcb_vport_delete(struct bfad_vport_s *vport_drv)
3247725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang{
3257725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (vport_drv->comp_del) {
3267725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		complete(vport_drv->comp_del);
3277725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		return;
3287725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	}
3297725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang}
3307725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
3317725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang/**
3327725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang * FCS RPORT alloc callback, after successful PLOGI by FCS
3337725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang */
3347725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangbfa_status_t
3357725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangbfa_fcb_rport_alloc(struct bfad_s *bfad, struct bfa_fcs_rport_s **rport,
3367725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		    struct bfad_rport_s **rport_drv)
3377725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang{
3387725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfa_status_t    rc = BFA_STATUS_OK;
3397725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
3407725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	*rport_drv = kzalloc(sizeof(struct bfad_rport_s), GFP_ATOMIC);
3417725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (*rport_drv == NULL) {
3427725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		rc = BFA_STATUS_ENOMEM;
3437725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		goto ext;
3447725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	}
3457725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
3467725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	*rport = &(*rport_drv)->fcs_rport;
3477725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
3487725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangext:
3497725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	return rc;
3507725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang}
3517725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
352d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang/**
353d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang * @brief
354d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang * FCS PBC VPORT Create
355d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang */
356d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huangvoid
357d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huangbfa_fcb_pbc_vport_create(struct bfad_s *bfad, struct bfi_pbc_vport_s pbc_vport)
358d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang{
359d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang
360d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang	struct bfad_pcfg_s *pcfg;
361d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang
362d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang	pcfg = kzalloc(sizeof(struct bfad_pcfg_s), GFP_ATOMIC);
363d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang	if (!pcfg) {
364d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang		bfa_trc(bfad, 0);
365d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang		return;
366d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang	}
3677725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
368d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang	pcfg->port_cfg.roles = BFA_PORT_ROLE_FCP_IM;
369d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang	pcfg->port_cfg.pwwn = pbc_vport.vp_pwwn;
370d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang	pcfg->port_cfg.nwwn = pbc_vport.vp_nwwn;
371d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang	pcfg->port_cfg.preboot_vp  = BFA_TRUE;
372d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang
373d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang	list_add_tail(&pcfg->list_entry, &bfad->pbc_pcfg_list);
374d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang
375d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang	return;
376d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang}
3777725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
3787725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangvoid
3797725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangbfad_hal_mem_release(struct bfad_s *bfad)
3807725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang{
3817725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	int             i;
3827725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	struct bfa_meminfo_s *hal_meminfo = &bfad->meminfo;
3837725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	struct bfa_mem_elem_s *meminfo_elem;
3847725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
3857725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	for (i = 0; i < BFA_MEM_TYPE_MAX; i++) {
3867725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		meminfo_elem = &hal_meminfo->meminfo[i];
3877725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		if (meminfo_elem->kva != NULL) {
3887725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang			switch (meminfo_elem->mem_type) {
3897725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang			case BFA_MEM_TYPE_KVA:
3907725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang				vfree(meminfo_elem->kva);
3917725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang				break;
3927725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang			case BFA_MEM_TYPE_DMA:
3937725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang				dma_free_coherent(&bfad->pcidev->dev,
3947725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang						meminfo_elem->mem_len,
3957725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang						meminfo_elem->kva,
3967725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang						(dma_addr_t) meminfo_elem->dma);
3977725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang				break;
3987725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang			default:
3997725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang				bfa_assert(0);
4007725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang				break;
4017725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang			}
4027725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		}
4037725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	}
4047725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
4057725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	memset(hal_meminfo, 0, sizeof(struct bfa_meminfo_s));
4067725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang}
4077725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
4087725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangvoid
4097725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangbfad_update_hal_cfg(struct bfa_iocfc_cfg_s *bfa_cfg)
4107725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang{
4117725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (num_rports > 0)
4127725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		bfa_cfg->fwcfg.num_rports = num_rports;
4137725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (num_ios > 0)
4147725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		bfa_cfg->fwcfg.num_ioim_reqs = num_ios;
4157725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (num_tms > 0)
4167725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		bfa_cfg->fwcfg.num_tskim_reqs = num_tms;
4177725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (num_fcxps > 0)
4187725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		bfa_cfg->fwcfg.num_fcxp_reqs = num_fcxps;
4197725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (num_ufbufs > 0)
4207725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		bfa_cfg->fwcfg.num_uf_bufs = num_ufbufs;
4217725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (reqq_size > 0)
4227725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		bfa_cfg->drvcfg.num_reqq_elems = reqq_size;
4237725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (rspq_size > 0)
4247725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		bfa_cfg->drvcfg.num_rspq_elems = rspq_size;
4257725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (num_sgpgs > 0)
4267725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		bfa_cfg->drvcfg.num_sgpgs = num_sgpgs;
4277725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
4287725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	/*
4297725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	 * populate the hal values back to the driver for sysfs use.
4307725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	 * otherwise, the default values will be shown as 0 in sysfs
4317725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	 */
4327725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	num_rports = bfa_cfg->fwcfg.num_rports;
4337725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	num_ios    = bfa_cfg->fwcfg.num_ioim_reqs;
4347725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	num_tms	   = bfa_cfg->fwcfg.num_tskim_reqs;
4357725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	num_fcxps  = bfa_cfg->fwcfg.num_fcxp_reqs;
4367725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	num_ufbufs = bfa_cfg->fwcfg.num_uf_bufs;
4377725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	reqq_size  = bfa_cfg->drvcfg.num_reqq_elems;
4387725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	rspq_size  = bfa_cfg->drvcfg.num_rspq_elems;
4397725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	num_sgpgs  = bfa_cfg->drvcfg.num_sgpgs;
4407725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang}
4417725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
4427725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangbfa_status_t
4437725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangbfad_hal_mem_alloc(struct bfad_s *bfad)
4447725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang{
4457725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	struct bfa_meminfo_s *hal_meminfo = &bfad->meminfo;
4467725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	struct bfa_mem_elem_s *meminfo_elem;
4477725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfa_status_t    rc = BFA_STATUS_OK;
4487725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	dma_addr_t      phys_addr;
4497725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	int             retry_count = 0;
4507725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	int             reset_value = 1;
4517725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	int             min_num_sgpgs = 512;
4527725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	void           *kva;
4537725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	int             i;
4547725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
4557725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfa_cfg_get_default(&bfad->ioc_cfg);
4567725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
4577725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangretry:
4587725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad_update_hal_cfg(&bfad->ioc_cfg);
4597725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad->cfg_data.ioc_queue_depth = bfad->ioc_cfg.fwcfg.num_ioim_reqs;
4607725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfa_cfg_get_meminfo(&bfad->ioc_cfg, hal_meminfo);
4617725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
4627725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	for (i = 0; i < BFA_MEM_TYPE_MAX; i++) {
4637725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		meminfo_elem = &hal_meminfo->meminfo[i];
4647725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		switch (meminfo_elem->mem_type) {
4657725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		case BFA_MEM_TYPE_KVA:
4667725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang			kva = vmalloc(meminfo_elem->mem_len);
4677725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang			if (kva == NULL) {
4687725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang				bfad_hal_mem_release(bfad);
4697725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang				rc = BFA_STATUS_ENOMEM;
4707725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang				goto ext;
4717725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang			}
4727725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang			memset(kva, 0, meminfo_elem->mem_len);
4737725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang			meminfo_elem->kva = kva;
4747725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang			break;
4757725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		case BFA_MEM_TYPE_DMA:
4767725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang			kva = dma_alloc_coherent(&bfad->pcidev->dev,
4777725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang					meminfo_elem->mem_len,
4787725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang					&phys_addr, GFP_KERNEL);
4797725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang			if (kva == NULL) {
4807725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang				bfad_hal_mem_release(bfad);
4817725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang				/*
4827725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang				 * If we cannot allocate with default
4837725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang				 * num_sgpages try with half the value.
4847725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang				 */
4857725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang				if (num_sgpgs > min_num_sgpgs) {
4867725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang					printk(KERN_INFO "bfad[%d]: memory"
4877725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang						" allocation failed with"
4887725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang						" num_sgpgs: %d\n",
4897725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang						bfad->inst_no, num_sgpgs);
4907725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang					nextLowerInt(&num_sgpgs);
4917725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang					printk(KERN_INFO "bfad[%d]: trying to"
4927725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang						" allocate memory with"
4937725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang						" num_sgpgs: %d\n",
4947725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang						bfad->inst_no, num_sgpgs);
4957725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang					retry_count++;
4967725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang					goto retry;
4977725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang				} else {
4987725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang					if (num_sgpgs_parm > 0)
4997725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang						num_sgpgs = num_sgpgs_parm;
5007725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang					else {
5017725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang						reset_value =
5027725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang							(1 << retry_count);
5037725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang						num_sgpgs *= reset_value;
5047725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang					}
5057725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang					rc = BFA_STATUS_ENOMEM;
5067725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang					goto ext;
5077725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang				}
5087725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang			}
5097725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
5107725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang			if (num_sgpgs_parm > 0)
5117725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang				num_sgpgs = num_sgpgs_parm;
5127725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang			else {
5137725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang				reset_value = (1 << retry_count);
5147725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang				num_sgpgs *= reset_value;
5157725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang			}
5167725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
5177725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang			memset(kva, 0, meminfo_elem->mem_len);
5187725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang			meminfo_elem->kva = kva;
5197725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang			meminfo_elem->dma = phys_addr;
5207725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang			break;
5217725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		default:
5227725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang			break;
5237725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
5247725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		}
5257725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	}
5267725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangext:
5277725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	return rc;
5287725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang}
5297725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
5307725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang/**
5317725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang * Create a vport under a vf.
5327725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang */
5337725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangbfa_status_t
5347725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangbfad_vport_create(struct bfad_s *bfad, u16 vf_id,
535d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang			struct bfa_port_cfg_s *port_cfg, struct device *dev)
5367725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang{
5377725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	struct bfad_vport_s *vport;
538d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang	int rc = BFA_STATUS_OK;
5397725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	unsigned long   flags;
5407725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	struct completion fcomp;
5417725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
5427725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	vport = kzalloc(sizeof(struct bfad_vport_s), GFP_KERNEL);
5437725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (!vport) {
5447725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		rc = BFA_STATUS_ENOMEM;
5457725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		goto ext;
5467725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	}
5477725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
5487725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	vport->drv_port.bfad = bfad;
5497725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	spin_lock_irqsave(&bfad->bfad_lock, flags);
550d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang	if (port_cfg->preboot_vp == BFA_TRUE)
551d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang		rc = bfa_fcs_pbc_vport_create(&vport->fcs_vport,
552d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang				&bfad->bfa_fcs, vf_id, port_cfg, vport);
553d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang	else
554d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang		rc = bfa_fcs_vport_create(&vport->fcs_vport,
555d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang				&bfad->bfa_fcs, vf_id, port_cfg, vport);
5567725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
5577725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
5587725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (rc != BFA_STATUS_OK)
5597725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		goto ext_free_vport;
5607725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
5617725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (port_cfg->roles & BFA_PORT_ROLE_FCP_IM) {
562b504293fe9dc42917a919044f2b672fb361329d0Jing Huang		rc = bfad_im_scsi_host_alloc(bfad, vport->drv_port.im_port,
563b504293fe9dc42917a919044f2b672fb361329d0Jing Huang							dev);
5647725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		if (rc != BFA_STATUS_OK)
5657725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang			goto ext_free_fcs_vport;
5667725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	}
5677725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
5687725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	spin_lock_irqsave(&bfad->bfad_lock, flags);
5697725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfa_fcs_vport_start(&vport->fcs_vport);
5707725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
5717725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
5727725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	return BFA_STATUS_OK;
5737725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
5747725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangext_free_fcs_vport:
5757725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	spin_lock_irqsave(&bfad->bfad_lock, flags);
5767725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	vport->comp_del = &fcomp;
5777725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	init_completion(vport->comp_del);
5787725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfa_fcs_vport_delete(&vport->fcs_vport);
5797725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
5807725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	wait_for_completion(vport->comp_del);
5817725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangext_free_vport:
5827725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	kfree(vport);
5837725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangext:
5847725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	return rc;
5857725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang}
5867725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
5877725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang/**
5887725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang * Create a vf and its base vport implicitely.
5897725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang */
5907725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangbfa_status_t
5917725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangbfad_vf_create(struct bfad_s *bfad, u16 vf_id,
5927725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	       struct bfa_port_cfg_s *port_cfg)
5937725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang{
5947725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	struct bfad_vf_s *vf;
5957725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	int             rc = BFA_STATUS_OK;
5967725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
5977725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	vf = kzalloc(sizeof(struct bfad_vf_s), GFP_KERNEL);
5987725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (!vf) {
5997725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		rc = BFA_STATUS_FAILED;
6007725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		goto ext;
6017725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	}
6027725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
6037725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	rc = bfa_fcs_vf_create(&vf->fcs_vf, &bfad->bfa_fcs, vf_id, port_cfg,
6047725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang			       vf);
6057725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (rc != BFA_STATUS_OK)
6067725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		kfree(vf);
6077725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangext:
6087725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	return rc;
6097725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang}
6107725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
6117725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangvoid
6127725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangbfad_bfa_tmo(unsigned long data)
6137725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang{
6147725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	struct bfad_s  *bfad = (struct bfad_s *)data;
6157725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	unsigned long   flags;
6167725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	struct list_head  doneq;
6177725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
6187725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	spin_lock_irqsave(&bfad->bfad_lock, flags);
6197725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
6207725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfa_timer_tick(&bfad->bfa);
6217725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
6227725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfa_comp_deq(&bfad->bfa, &doneq);
6237725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
6247725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
6257725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (!list_empty(&doneq)) {
6267725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		bfa_comp_process(&bfad->bfa, &doneq);
6277725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		spin_lock_irqsave(&bfad->bfad_lock, flags);
6287725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		bfa_comp_free(&bfad->bfa, &doneq);
6297725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
6307725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	}
6317725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
6327725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	mod_timer(&bfad->hal_tmo, jiffies + msecs_to_jiffies(BFA_TIMER_FREQ));
6337725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang}
6347725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
6357725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangvoid
6367725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangbfad_init_timer(struct bfad_s *bfad)
6377725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang{
6387725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	init_timer(&bfad->hal_tmo);
6397725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad->hal_tmo.function = bfad_bfa_tmo;
6407725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad->hal_tmo.data = (unsigned long)bfad;
6417725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
6427725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	mod_timer(&bfad->hal_tmo, jiffies + msecs_to_jiffies(BFA_TIMER_FREQ));
6437725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang}
6447725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
6457725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangint
6467725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangbfad_pci_init(struct pci_dev *pdev, struct bfad_s *bfad)
6477725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang{
6487725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	int             rc = -ENODEV;
6497725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
6507725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (pci_enable_device(pdev)) {
6517725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		BFA_PRINTF(BFA_ERR, "pci_enable_device fail %p\n", pdev);
6527725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		goto out;
6537725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	}
6547725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
6557725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (pci_request_regions(pdev, BFAD_DRIVER_NAME))
6567725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		goto out_disable_device;
6577725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
6587725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	pci_set_master(pdev);
6597725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
6607725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
6617725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0)
6627725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0) {
6637725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang			BFA_PRINTF(BFA_ERR, "pci_set_dma_mask fail %p\n", pdev);
6647725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang			goto out_release_region;
6657725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		}
6667725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
667b3522f08ec7011aed0abc477bfedd00d189e9cd6Jing Huang	bfad->pci_bar0_kva = pci_iomap(pdev, 0, pci_resource_len(pdev, 0));
6687725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
6697725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (bfad->pci_bar0_kva == NULL) {
6707725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		BFA_PRINTF(BFA_ERR, "Fail to map bar0\n");
6717725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		goto out_release_region;
6727725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	}
6737725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
6747725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad->hal_pcidev.pci_slot = PCI_SLOT(pdev->devfn);
6757725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad->hal_pcidev.pci_func = PCI_FUNC(pdev->devfn);
6767725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad->hal_pcidev.pci_bar_kva = bfad->pci_bar0_kva;
6777725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad->hal_pcidev.device_id = pdev->device;
6787725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad->pci_name = pci_name(pdev);
6797725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
6807725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad->pci_attr.vendor_id = pdev->vendor;
6817725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad->pci_attr.device_id = pdev->device;
6827725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad->pci_attr.ssid = pdev->subsystem_device;
6837725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad->pci_attr.ssvid = pdev->subsystem_vendor;
6847725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad->pci_attr.pcifn = PCI_FUNC(pdev->devfn);
6857725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
6867725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad->pcidev = pdev;
6877725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	return 0;
6887725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
6897725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangout_release_region:
6907725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	pci_release_regions(pdev);
6917725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangout_disable_device:
6927725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	pci_disable_device(pdev);
6937725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangout:
6947725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	return rc;
6957725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang}
6967725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
6977725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangvoid
6987725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangbfad_pci_uninit(struct pci_dev *pdev, struct bfad_s *bfad)
6997725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang{
7007725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	pci_iounmap(pdev, bfad->pci_bar0_kva);
7017725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	pci_release_regions(pdev);
7027725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	pci_disable_device(pdev);
7037725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	pci_set_drvdata(pdev, NULL);
7047725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang}
7057725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
7067725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangvoid
7077725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangbfad_fcs_port_cfg(struct bfad_s *bfad)
7087725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang{
7097725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	struct bfa_port_cfg_s port_cfg;
7107725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	struct bfa_pport_attr_s attr;
7117725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	char            symname[BFA_SYMNAME_MAXLEN];
7127725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
7137725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	sprintf(symname, "%s-%d", BFAD_DRIVER_NAME, bfad->inst_no);
7147725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	memcpy(port_cfg.sym_name.symname, symname, strlen(symname));
7151c8a4c37494932acd59079b4fc8d8f69fb329c2aKrishna Gudipati	bfa_fcport_get_attr(&bfad->bfa, &attr);
7167725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	port_cfg.nwwn = attr.nwwn;
7177725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	port_cfg.pwwn = attr.pwwn;
7187725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
7197725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfa_fcs_cfg_base_port(&bfad->bfa_fcs, &port_cfg);
7207725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang}
7217725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
7227725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangbfa_status_t
7237725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangbfad_drv_init(struct bfad_s *bfad)
7247725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang{
7257725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfa_status_t    rc;
7267725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	unsigned long   flags;
7277725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	struct bfa_fcs_driver_info_s driver_info;
7287725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
7297725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad->cfg_data.rport_del_timeout = rport_del_timeout;
7307725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad->cfg_data.lun_queue_depth = bfa_lun_queue_depth;
7317725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad->cfg_data.io_max_sge = bfa_io_max_sge;
7327725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad->cfg_data.binding_method = FCP_PWWN_BINDING;
7337725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
7347725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	rc = bfad_hal_mem_alloc(bfad);
7357725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (rc != BFA_STATUS_OK) {
7367725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		printk(KERN_WARNING "bfad%d bfad_hal_mem_alloc failure\n",
7377725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		       bfad->inst_no);
7387725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		printk(KERN_WARNING
7397725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang			"Not enough memory to attach all Brocade HBA ports,"
7407725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang			" System may need more memory.\n");
7417725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		goto out_hal_mem_alloc_failure;
7427725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	}
7437725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
7447725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfa_init_log(&bfad->bfa, bfad->logmod);
7457725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfa_init_trc(&bfad->bfa, bfad->trcmod);
7467725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfa_init_aen(&bfad->bfa, bfad->aen);
7472993cc71d1bff61999ade7f2b6b3ea2dd1e2c8d9Krishna Gudipati	memset(bfad->file_map, 0, sizeof(bfad->file_map));
7487725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfa_init_plog(&bfad->bfa, &bfad->plog_buf);
7497725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfa_plog_init(&bfad->plog_buf);
7507725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfa_plog_str(&bfad->plog_buf, BFA_PL_MID_DRVR, BFA_PL_EID_DRIVER_START,
7517725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		     0, "Driver Attach");
7527725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
7537725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfa_attach(&bfad->bfa, bfad, &bfad->ioc_cfg, &bfad->meminfo,
7547725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		   &bfad->hal_pcidev);
7557725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
7567725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	init_completion(&bfad->comp);
7577725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
7587725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	/*
7597725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	 * Enable Interrupt and wait bfa_init completion
7607725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	 */
7617725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (bfad_setup_intr(bfad)) {
7627725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		printk(KERN_WARNING "bfad%d: bfad_setup_intr failed\n",
7637725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		       bfad->inst_no);
7647725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		goto out_setup_intr_failure;
7657725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	}
7667725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
7677725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	spin_lock_irqsave(&bfad->bfad_lock, flags);
7687725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfa_init(&bfad->bfa);
7697725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
7707725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
7717725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	/*
7727725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	 * Set up interrupt handler for each vectors
7737725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	 */
7747725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if ((bfad->bfad_flags & BFAD_MSIX_ON)
7757725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	    && bfad_install_msix_handler(bfad)) {
7767725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		printk(KERN_WARNING "%s: install_msix failed, bfad%d\n",
777f8ceafde6f5bf6b4b7087c7f5e9da1b2a5284a2eJing Huang		       __func__, bfad->inst_no);
7787725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	}
7797725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
7807725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad_init_timer(bfad);
7817725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
7827725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	wait_for_completion(&bfad->comp);
7837725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
7847725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	memset(&driver_info, 0, sizeof(driver_info));
7857725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	strncpy(driver_info.version, BFAD_DRIVER_VERSION,
7867725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		sizeof(driver_info.version) - 1);
7877725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (host_name)
7887725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		strncpy(driver_info.host_machine_name, host_name,
7897725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang			sizeof(driver_info.host_machine_name) - 1);
7907725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (os_name)
7917725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		strncpy(driver_info.host_os_name, os_name,
7927725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang			sizeof(driver_info.host_os_name) - 1);
7937725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (os_patch)
7947725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		strncpy(driver_info.host_os_patch, os_patch,
7957725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang			sizeof(driver_info.host_os_patch) - 1);
7967725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
7977725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	strncpy(driver_info.os_device_name, bfad->pci_name,
7987725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		sizeof(driver_info.os_device_name - 1));
7997725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
8007725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	/*
8017725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	 * FCS INIT
8027725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	 */
8037725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	spin_lock_irqsave(&bfad->bfad_lock, flags);
8047725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfa_fcs_log_init(&bfad->bfa_fcs, bfad->logmod);
8057725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfa_fcs_trc_init(&bfad->bfa_fcs, bfad->trcmod);
8067725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfa_fcs_aen_init(&bfad->bfa_fcs, bfad->aen);
80782794a2e4153657d12a0c29272e40b47eaadb748Krishna Gudipati	bfa_fcs_attach(&bfad->bfa_fcs, &bfad->bfa, bfad, BFA_FALSE);
808e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati
809e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	/* Do FCS init only when HAL init is done */
810e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	if ((bfad->bfad_flags & BFAD_HAL_INIT_DONE)) {
811e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati		bfa_fcs_init(&bfad->bfa_fcs);
812e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati		bfad->bfad_flags |= BFAD_FCS_INIT_DONE;
813e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	}
814e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati
8157725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfa_fcs_driver_info_init(&bfad->bfa_fcs, &driver_info);
8165b098082e22c168b7df4c5c3cd924047cee7d995Krishna Gudipati	bfa_fcs_set_fdmi_param(&bfad->bfa_fcs, fdmi_enable);
8177725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
8187725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
8197725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad->bfad_flags |= BFAD_DRV_INIT_DONE;
8207725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	return BFA_STATUS_OK;
8217725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
8227725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangout_setup_intr_failure:
8237725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfa_detach(&bfad->bfa);
8247725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad_hal_mem_release(bfad);
8257725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangout_hal_mem_alloc_failure:
8267725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	return BFA_STATUS_FAILED;
8277725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang}
8287725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
8297725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangvoid
8307725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangbfad_drv_uninit(struct bfad_s *bfad)
8317725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang{
832e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	unsigned long   flags;
833e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati
834e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	spin_lock_irqsave(&bfad->bfad_lock, flags);
835e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	init_completion(&bfad->comp);
836e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	bfa_stop(&bfad->bfa);
837e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
838e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	wait_for_completion(&bfad->comp);
839e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati
8407725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	del_timer_sync(&bfad->hal_tmo);
8417725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfa_isr_disable(&bfad->bfa);
8427725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfa_detach(&bfad->bfa);
8437725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad_remove_intr(bfad);
8447725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad_hal_mem_release(bfad);
845e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati
846e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	bfad->bfad_flags &= ~BFAD_DRV_INIT_DONE;
8477725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang}
8487725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
8497725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangvoid
8507725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangbfad_drv_start(struct bfad_s *bfad)
8517725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang{
8527725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	unsigned long   flags;
8537725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
8547725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	spin_lock_irqsave(&bfad->bfad_lock, flags);
8557725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfa_start(&bfad->bfa);
8567725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfa_fcs_start(&bfad->bfa_fcs);
8577725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad->bfad_flags |= BFAD_HAL_START_DONE;
8587725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
8597725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
8607725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad_fc4_probe_post(bfad);
8617725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang}
8627725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
8637725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangvoid
8647725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangbfad_drv_stop(struct bfad_s *bfad)
8657725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang{
8667725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	unsigned long   flags;
8677725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
8687725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	spin_lock_irqsave(&bfad->bfad_lock, flags);
8697725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	init_completion(&bfad->comp);
8707725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad->pport.flags |= BFAD_PORT_DELETE;
8717725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfa_fcs_exit(&bfad->bfa_fcs);
8727725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
8737725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	wait_for_completion(&bfad->comp);
8747725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
8757725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	spin_lock_irqsave(&bfad->bfad_lock, flags);
8767725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	init_completion(&bfad->comp);
8777725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfa_stop(&bfad->bfa);
8787725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad->bfad_flags &= ~BFAD_HAL_START_DONE;
8797725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
8807725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	wait_for_completion(&bfad->comp);
8817725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang}
8827725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
8837725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangbfa_status_t
8847725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangbfad_cfg_pport(struct bfad_s *bfad, enum bfa_port_role role)
8857725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang{
8867725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	int             rc = BFA_STATUS_OK;
8877725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
8887725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	/*
8897725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	 * Allocate scsi_host for the physical port
8907725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	 */
8917725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if ((bfad_supported_fc4s & BFA_PORT_ROLE_FCP_IM)
8927725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	    && (role & BFA_PORT_ROLE_FCP_IM)) {
8937725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		if (bfad->pport.im_port == NULL) {
8947725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang			rc = BFA_STATUS_FAILED;
8957725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang			goto out;
8967725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		}
8977725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
898b504293fe9dc42917a919044f2b672fb361329d0Jing Huang		rc = bfad_im_scsi_host_alloc(bfad, bfad->pport.im_port,
899b504293fe9dc42917a919044f2b672fb361329d0Jing Huang						&bfad->pcidev->dev);
9007725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		if (rc != BFA_STATUS_OK)
9017725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang			goto out;
9027725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
9037725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		bfad->pport.roles |= BFA_PORT_ROLE_FCP_IM;
9047725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	}
9057725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
9067725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad->bfad_flags |= BFAD_CFG_PPORT_DONE;
9077725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
9087725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangout:
9097725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	return rc;
9107725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang}
9117725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
9127725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangvoid
9137725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangbfad_uncfg_pport(struct bfad_s *bfad)
9147725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang{
9157725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if ((bfad->pport.roles & BFA_PORT_ROLE_FCP_IPFC) && ipfc_enable) {
9167725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		bfad_ipfc_port_delete(bfad, &bfad->pport);
9177725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		bfad->pport.roles &= ~BFA_PORT_ROLE_FCP_IPFC;
9187725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	}
9197725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
9207725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if ((bfad_supported_fc4s & BFA_PORT_ROLE_FCP_IM)
9217725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	    && (bfad->pport.roles & BFA_PORT_ROLE_FCP_IM)) {
9227725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		bfad_im_scsi_host_free(bfad, bfad->pport.im_port);
9237725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		bfad_im_port_clean(bfad->pport.im_port);
9247725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		kfree(bfad->pport.im_port);
9257725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		bfad->pport.roles &= ~BFA_PORT_ROLE_FCP_IM;
9267725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	}
9277725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
9287725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad->bfad_flags &= ~BFAD_CFG_PPORT_DONE;
9297725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang}
9307725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
9317725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangvoid
9327725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangbfad_drv_log_level_set(struct bfad_s *bfad)
9337725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang{
9347725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (log_level > BFA_LOG_INVALID && log_level <= BFA_LOG_LEVEL_MAX)
9357725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		bfa_log_set_level_all(&bfad->log_data, log_level);
9367725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang}
9377725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
938e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipatibfa_status_t
939e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipatibfad_start_ops(struct bfad_s *bfad)
940e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati{
941e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	int retval;
942d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang	struct bfad_pcfg_s *pcfg, *pcfg_new;
943e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati
944e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	/* PPORT FCS config */
945e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	bfad_fcs_port_cfg(bfad);
946e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati
947e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	retval = bfad_cfg_pport(bfad, BFA_PORT_ROLE_FCP_IM);
948e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	if (retval != BFA_STATUS_OK)
949e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati		goto out_cfg_pport_failure;
950e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati
951e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	/* BFAD level FC4 (IM/TM/IPFC) specific resource allocation */
952e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	retval = bfad_fc4_probe(bfad);
953e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	if (retval != BFA_STATUS_OK) {
954e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati		printk(KERN_WARNING "bfad_fc4_probe failed\n");
955e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati		goto out_fc4_probe_failure;
956e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	}
957e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati
958e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	bfad_drv_start(bfad);
959e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati
960d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang	/* pbc vport creation */
961d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang	list_for_each_entry_safe(pcfg, pcfg_new,  &bfad->pbc_pcfg_list,
962d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang					list_entry) {
963d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang		struct fc_vport_identifiers vid;
964d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang		struct fc_vport *fc_vport;
965d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang
966d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang		memset(&vid, 0, sizeof(vid));
967d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang		vid.roles = FC_PORT_ROLE_FCP_INITIATOR;
968d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang		vid.vport_type = FC_PORTTYPE_NPIV;
969d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang		vid.disable = false;
970d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang		vid.node_name = wwn_to_u64((u8 *)&pcfg->port_cfg.nwwn);
971d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang		vid.port_name = wwn_to_u64((u8 *)&pcfg->port_cfg.pwwn);
972d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang		fc_vport = fc_vport_create(bfad->pport.im_port->shost, 0, &vid);
973d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang		if (!fc_vport)
974d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang			printk(KERN_WARNING "bfad%d: failed to create pbc vport"
975d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang				" %llx\n", bfad->inst_no, vid.port_name);
976d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang		list_del(&pcfg->list_entry);
977d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang		kfree(pcfg);
978d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang
979d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang	}
980d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang
981e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	/*
982e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	 * If bfa_linkup_delay is set to -1 default; try to retrive the
983e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	 * value using the bfad_os_get_linkup_delay(); else use the
984e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	 * passed in module param value as the bfa_linkup_delay.
985e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	 */
986e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	if (bfa_linkup_delay < 0) {
987e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati
988e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati		bfa_linkup_delay = bfad_os_get_linkup_delay(bfad);
989e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati		bfad_os_rport_online_wait(bfad);
990e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati		bfa_linkup_delay = -1;
991e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati
992e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	} else {
993e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati		bfad_os_rport_online_wait(bfad);
994e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	}
995e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati
996e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	bfa_log(bfad->logmod, BFA_LOG_LINUX_DEVICE_CLAIMED, bfad->pci_name);
997e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati
998e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	return BFA_STATUS_OK;
999e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati
1000e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipatiout_fc4_probe_failure:
1001e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	bfad_fc4_probe_undo(bfad);
1002e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	bfad_uncfg_pport(bfad);
1003e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipatiout_cfg_pport_failure:
1004e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	return BFA_STATUS_FAILED;
1005e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati}
1006e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati
1007e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipatiint
1008d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huangbfad_worker(void *ptr)
1009e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati{
1010e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	struct bfad_s *bfad;
1011e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	unsigned long   flags;
1012e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati
1013e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	bfad = (struct bfad_s *)ptr;
1014e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati
1015e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	while (!kthread_should_stop()) {
1016e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati
1017e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati		/* Check if the FCS init is done from bfad_drv_init;
1018e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati		 * if not done do FCS init and set the flag.
1019e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati		 */
1020e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati		if (!(bfad->bfad_flags & BFAD_FCS_INIT_DONE)) {
1021e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati			spin_lock_irqsave(&bfad->bfad_lock, flags);
1022e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati			bfa_fcs_init(&bfad->bfa_fcs);
1023e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati			bfad->bfad_flags |= BFAD_FCS_INIT_DONE;
1024e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati			spin_unlock_irqrestore(&bfad->bfad_lock, flags);
1025e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati		}
1026e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati
1027e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati		/* Start the bfad operations after HAL init done */
1028e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati		bfad_start_ops(bfad);
1029e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati
1030e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati		spin_lock_irqsave(&bfad->bfad_lock, flags);
1031e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati		bfad->bfad_tsk = NULL;
1032e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
1033e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati
1034e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati		break;
1035e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	}
1036e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati
1037e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	return 0;
1038e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati}
1039e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati
10407725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang /*
10417725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang  *  PCI_entry PCI driver entries * {
10427725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang  */
10437725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
10447725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang/**
10457725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang * PCI probe entry.
10467725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang */
10477725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangint
10487725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangbfad_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid)
10497725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang{
10507725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	struct bfad_s  *bfad;
10517725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	int             error = -ENODEV, retval;
10527725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
10537725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	/*
10547725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	 * For single port cards - only claim function 0
10557725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	 */
10567725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if ((pdev->device == BFA_PCI_DEVICE_ID_FC_8G1P)
10577725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	    && (PCI_FUNC(pdev->devfn) != 0))
10587725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		return -ENODEV;
10597725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
10607725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	BFA_TRACE(BFA_INFO, "bfad_pci_probe entry");
10617725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
10627725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad = kzalloc(sizeof(struct bfad_s), GFP_KERNEL);
10637725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (!bfad) {
10647725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		error = -ENOMEM;
10657725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		goto out;
10667725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	}
10677725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
10687725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad->trcmod = kzalloc(sizeof(struct bfa_trc_mod_s), GFP_KERNEL);
10697725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (!bfad->trcmod) {
10707725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		printk(KERN_WARNING "Error alloc trace buffer!\n");
10717725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		error = -ENOMEM;
10727725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		goto out_alloc_trace_failure;
10737725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	}
10747725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
10757725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	/*
10767725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	 * LOG/TRACE INIT
10777725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	 */
10787725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfa_trc_init(bfad->trcmod);
10797725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfa_trc(bfad, bfad_inst);
10807725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
10817725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad->logmod = &bfad->log_data;
10820a4b1fc0b24fc7adbaf8413f2992ce1395991a78Krishna Gudipati	bfa_log_init(bfad->logmod, (char *)pci_name(pdev), bfa_os_printf);
10837725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
10847725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad_drv_log_level_set(bfad);
10857725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
10867725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad->aen = &bfad->aen_buf;
10877725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
10887725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (!(bfad_load_fwimg(pdev))) {
10897725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		printk(KERN_WARNING "bfad_load_fwimg failure!\n");
10907725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		kfree(bfad->trcmod);
10917725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		goto out_alloc_trace_failure;
10927725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	}
10937725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
10947725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	retval = bfad_pci_init(pdev, bfad);
10957725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (retval) {
10967725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		printk(KERN_WARNING "bfad_pci_init failure!\n");
10977725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		error = retval;
10987725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		goto out_pci_init_failure;
10997725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	}
11007725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
11017725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	mutex_lock(&bfad_mutex);
11027725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad->inst_no = bfad_inst++;
11037725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	list_add_tail(&bfad->list_entry, &bfad_list);
11047725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	mutex_unlock(&bfad_mutex);
11057725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
11067725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	spin_lock_init(&bfad->bfad_lock);
11077725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	pci_set_drvdata(pdev, bfad);
11087725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
11097725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad->ref_count = 0;
11107725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad->pport.bfad = bfad;
1111d9883548a0b0afec4786e6c5cd8d03d43a30b779Jing Huang	INIT_LIST_HEAD(&bfad->pbc_pcfg_list);
11127725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
1113e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	bfad->bfad_tsk = kthread_create(bfad_worker, (void *) bfad, "%s",
1114e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati					"bfad_worker");
1115e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	if (IS_ERR(bfad->bfad_tsk)) {
1116e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati		printk(KERN_INFO "bfad[%d]: Kernel thread"
1117e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati			" creation failed!\n",
1118e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati			bfad->inst_no);
1119e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati		goto out_kthread_create_failure;
1120e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	}
1121e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati
11227725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	retval = bfad_drv_init(bfad);
11237725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (retval != BFA_STATUS_OK)
11247725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		goto out_drv_init_failure;
11257725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (!(bfad->bfad_flags & BFAD_HAL_INIT_DONE)) {
1126e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati		bfad->bfad_flags |= BFAD_HAL_INIT_FAIL;
11277725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		printk(KERN_WARNING "bfad%d: hal init failed\n", bfad->inst_no);
11287725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		goto ok;
11297725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	}
11307725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
1131e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	retval = bfad_start_ops(bfad);
11327725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (retval != BFA_STATUS_OK)
1133e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati		goto out_start_ops_failure;
11347725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
1135e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	kthread_stop(bfad->bfad_tsk);
1136e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	bfad->bfad_tsk = NULL;
11377725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
11387725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangok:
11397725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	return 0;
11407725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
1141e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipatiout_start_ops_failure:
11427725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad_drv_uninit(bfad);
11437725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangout_drv_init_failure:
1144e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	kthread_stop(bfad->bfad_tsk);
1145e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipatiout_kthread_create_failure:
11467725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	mutex_lock(&bfad_mutex);
11477725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad_inst--;
11487725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	list_del(&bfad->list_entry);
11497725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	mutex_unlock(&bfad_mutex);
11507725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad_pci_uninit(pdev, bfad);
11517725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangout_pci_init_failure:
11527725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	kfree(bfad->trcmod);
11537725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangout_alloc_trace_failure:
11547725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	kfree(bfad);
11557725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangout:
11567725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	return error;
11577725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang}
11587725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
11597725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang/**
11607725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang * PCI remove entry.
11617725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang */
11627725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangvoid
11637725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangbfad_pci_remove(struct pci_dev *pdev)
11647725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang{
11657725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	struct bfad_s  *bfad = pci_get_drvdata(pdev);
11667725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	unsigned long   flags;
11677725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
11687725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfa_trc(bfad, bfad->inst_no);
11697725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
1170e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	spin_lock_irqsave(&bfad->bfad_lock, flags);
1171e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	if (bfad->bfad_tsk != NULL)
1172e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati		kthread_stop(bfad->bfad_tsk);
1173e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
1174e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati
11757725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if ((bfad->bfad_flags & BFAD_DRV_INIT_DONE)
11767725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	    && !(bfad->bfad_flags & BFAD_HAL_INIT_DONE)) {
11777725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
11787725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		spin_lock_irqsave(&bfad->bfad_lock, flags);
11797725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		init_completion(&bfad->comp);
11807725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		bfa_stop(&bfad->bfa);
11817725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
11827725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		wait_for_completion(&bfad->comp);
11837725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
11847725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		bfad_remove_intr(bfad);
11857725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		del_timer_sync(&bfad->hal_tmo);
11867725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		goto hal_detach;
11877725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	} else if (!(bfad->bfad_flags & BFAD_DRV_INIT_DONE)) {
11887725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		goto remove_sysfs;
11897725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	}
11907725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
1191e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	if (bfad->bfad_flags & BFAD_HAL_START_DONE) {
11927725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		bfad_drv_stop(bfad);
1193e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	} else if (bfad->bfad_flags & BFAD_DRV_INIT_DONE) {
1194e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati		/* Invoking bfa_stop() before bfa_detach
1195e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati		 * when HAL and DRV init are success
1196e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati		 * but HAL start did not occur.
1197e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati		 */
1198e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati		spin_lock_irqsave(&bfad->bfad_lock, flags);
1199e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati		init_completion(&bfad->comp);
1200e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati		bfa_stop(&bfad->bfa);
1201e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
1202e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati		wait_for_completion(&bfad->comp);
1203e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	}
12047725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
12057725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad_remove_intr(bfad);
12067725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	del_timer_sync(&bfad->hal_tmo);
1207e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati
1208e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati	if (bfad->bfad_flags & BFAD_FC4_PROBE_DONE)
1209e67143243a1a6b47e1bdcda189ffac46d2a8744dKrishna Gudipati		bfad_fc4_probe_undo(bfad);
12107725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
12117725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (bfad->bfad_flags & BFAD_CFG_PPORT_DONE)
12127725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		bfad_uncfg_pport(bfad);
12137725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
12147725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huanghal_detach:
12157725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	spin_lock_irqsave(&bfad->bfad_lock, flags);
12167725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfa_detach(&bfad->bfa);
12177725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
12187725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad_hal_mem_release(bfad);
12197725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangremove_sysfs:
12207725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
12217725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	mutex_lock(&bfad_mutex);
12227725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad_inst--;
12237725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	list_del(&bfad->list_entry);
12247725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	mutex_unlock(&bfad_mutex);
12257725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad_pci_uninit(pdev, bfad);
12267725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
12277725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	kfree(bfad->trcmod);
12287725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	kfree(bfad);
12297725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang}
12307725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
12317725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
12327725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangstatic struct pci_device_id bfad_id_table[] = {
12337725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	{
12347725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	 .vendor = BFA_PCI_VENDOR_ID_BROCADE,
12357725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	 .device = BFA_PCI_DEVICE_ID_FC_8G2P,
12367725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	 .subvendor = PCI_ANY_ID,
12377725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	 .subdevice = PCI_ANY_ID,
12387725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	 },
12397725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	{
12407725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	 .vendor = BFA_PCI_VENDOR_ID_BROCADE,
12417725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	 .device = BFA_PCI_DEVICE_ID_FC_8G1P,
12427725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	 .subvendor = PCI_ANY_ID,
12437725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	 .subdevice = PCI_ANY_ID,
12447725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	 },
12457725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	{
12467725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	 .vendor = BFA_PCI_VENDOR_ID_BROCADE,
12477725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	 .device = BFA_PCI_DEVICE_ID_CT,
12487725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	 .subvendor = PCI_ANY_ID,
12497725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	 .subdevice = PCI_ANY_ID,
12507725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	 .class = (PCI_CLASS_SERIAL_FIBER << 8),
12517725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	 .class_mask = ~0,
12527725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	 },
1253293f82d59ed8b6d61d242e40ee7a6a146fae5eaaJing Huang	{
1254293f82d59ed8b6d61d242e40ee7a6a146fae5eaaJing Huang	 .vendor = BFA_PCI_VENDOR_ID_BROCADE,
1255293f82d59ed8b6d61d242e40ee7a6a146fae5eaaJing Huang	 .device = BFA_PCI_DEVICE_ID_CT_FC,
1256293f82d59ed8b6d61d242e40ee7a6a146fae5eaaJing Huang	 .subvendor = PCI_ANY_ID,
1257293f82d59ed8b6d61d242e40ee7a6a146fae5eaaJing Huang	 .subdevice = PCI_ANY_ID,
1258293f82d59ed8b6d61d242e40ee7a6a146fae5eaaJing Huang	 .class = (PCI_CLASS_SERIAL_FIBER << 8),
1259293f82d59ed8b6d61d242e40ee7a6a146fae5eaaJing Huang	 .class_mask = ~0,
1260293f82d59ed8b6d61d242e40ee7a6a146fae5eaaJing Huang	},
12617725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
12627725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	{0, 0},
12637725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang};
12647725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
12657725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing HuangMODULE_DEVICE_TABLE(pci, bfad_id_table);
12667725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
12677725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangstatic struct pci_driver bfad_pci_driver = {
12687725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	.name = BFAD_DRIVER_NAME,
12697725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	.id_table = bfad_id_table,
12707725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	.probe = bfad_pci_probe,
12717725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	.remove = __devexit_p(bfad_pci_remove),
12727725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang};
12737725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
12747725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang/**
12757725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang *  Linux driver module functions
12767725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang */
12777725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangbfa_status_t
12787725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangbfad_fc4_module_init(void)
12797725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang{
12807725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	int             rc;
12817725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
12827725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	rc = bfad_im_module_init();
12837725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (rc != BFA_STATUS_OK)
12847725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		goto ext;
12857725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
12867725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad_tm_module_init();
12877725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (ipfc_enable)
12887725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		bfad_ipfc_module_init();
12897725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangext:
12907725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	return rc;
12917725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang}
12927725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
12937725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangvoid
12947725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangbfad_fc4_module_exit(void)
12957725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang{
12967725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (ipfc_enable)
12977725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		bfad_ipfc_module_exit();
12987725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad_tm_module_exit();
12997725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad_im_module_exit();
13007725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang}
13017725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
13027725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang/**
13037725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang * Driver module init.
13047725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang */
13057725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangstatic int      __init
13067725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangbfad_init(void)
13077725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang{
13087725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	int             error = 0;
13097725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
13107725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	printk(KERN_INFO "Brocade BFA FC/FCOE SCSI driver - version: %s\n",
13117725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	       BFAD_DRIVER_VERSION);
13127725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
13137725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (num_sgpgs > 0)
13147725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		num_sgpgs_parm = num_sgpgs;
13157725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
13167725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	error = bfad_fc4_module_init();
13177725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (error) {
13187725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		error = -ENOMEM;
13197725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		printk(KERN_WARNING "bfad_fc4_module_init failure\n");
13207725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		goto ext;
13217725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	}
13227725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
13237725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (!strcmp(FCPI_NAME, " fcpim"))
13247725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		bfad_supported_fc4s |= BFA_PORT_ROLE_FCP_IM;
13257725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (!strcmp(FCPT_NAME, " fcptm"))
13267725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		bfad_supported_fc4s |= BFA_PORT_ROLE_FCP_TM;
13277725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (!strcmp(IPFC_NAME, " ipfc"))
13287725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		bfad_supported_fc4s |= BFA_PORT_ROLE_FCP_IPFC;
13297725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
13307725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfa_ioc_auto_recover(ioc_auto_recover);
13317725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfa_fcs_rport_set_del_timeout(rport_del_timeout);
13327725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	error = pci_register_driver(&bfad_pci_driver);
13337725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
13347725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	if (error) {
13357725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		printk(KERN_WARNING "bfad pci_register_driver failure\n");
13367725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang		goto ext;
13377725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	}
13387725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
13397725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	return 0;
13407725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
13417725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangext:
13427725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad_fc4_module_exit();
13437725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	return error;
13447725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang}
13457725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
13467725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang/**
13477725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang * Driver module exit.
13487725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang */
13497725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangstatic void     __exit
13507725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangbfad_exit(void)
13517725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang{
13527725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	pci_unregister_driver(&bfad_pci_driver);
13537725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad_fc4_module_exit();
13547725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang	bfad_free_fwimg();
13557725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang}
13567725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
13577725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang#define BFAD_PROTO_NAME FCPI_NAME FCPT_NAME IPFC_NAME
13587725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
13597725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangmodule_init(bfad_init);
13607725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huangmodule_exit(bfad_exit);
13617725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing HuangMODULE_LICENSE("GPL");
13627725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing HuangMODULE_DESCRIPTION("Brocade Fibre Channel HBA Driver" BFAD_PROTO_NAME);
13637725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing HuangMODULE_AUTHOR("Brocade Communications Systems, Inc.");
13647725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing HuangMODULE_VERSION(BFAD_DRIVER_VERSION);
13657725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
13667725ccfda59715ecf8f99e3b520a0b84cc2ea79eJing Huang
1367