152fa7bf9SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
27725ccfdSJing Huang /*
3889d0d42SAnil Gurumurthy * Copyright (c) 2005-2014 Brocade Communications Systems, Inc.
4889d0d42SAnil Gurumurthy * Copyright (c) 2014- QLogic Corporation.
57725ccfdSJing Huang * All rights reserved
6889d0d42SAnil Gurumurthy * www.qlogic.com
77725ccfdSJing Huang *
831e1d569SAnil Gurumurthy * Linux driver for QLogic BR-series Fibre Channel Host Bus Adapter.
97725ccfdSJing Huang */
107725ccfdSJing Huang
115fbe25c7SJing Huang /*
127725ccfdSJing Huang * bfad.c Linux driver PCI interface module.
137725ccfdSJing Huang */
147725ccfdSJing Huang #include <linux/module.h>
15e6714324SKrishna Gudipati #include <linux/kthread.h>
16a36c61f9SKrishna Gudipati #include <linux/errno.h>
17a36c61f9SKrishna Gudipati #include <linux/sched.h>
18a36c61f9SKrishna Gudipati #include <linux/init.h>
19a36c61f9SKrishna Gudipati #include <linux/fs.h>
20a36c61f9SKrishna Gudipati #include <linux/pci.h>
21a36c61f9SKrishna Gudipati #include <linux/firmware.h>
227c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
23a36c61f9SKrishna Gudipati #include <asm/fcntl.h>
24a36c61f9SKrishna Gudipati
257725ccfdSJing Huang #include "bfad_drv.h"
267725ccfdSJing Huang #include "bfad_im.h"
27a36c61f9SKrishna Gudipati #include "bfa_fcs.h"
28a36c61f9SKrishna Gudipati #include "bfa_defs.h"
29a36c61f9SKrishna Gudipati #include "bfa.h"
307725ccfdSJing Huang
317725ccfdSJing Huang BFA_TRC_FILE(LDRV, BFAD);
3242b426ecSJing Huang DEFINE_MUTEX(bfad_mutex);
337725ccfdSJing Huang LIST_HEAD(bfad_list);
347725ccfdSJing Huang
35a36c61f9SKrishna Gudipati static int bfad_inst;
36a36c61f9SKrishna Gudipati static int num_sgpgs_parm;
37a36c61f9SKrishna Gudipati int supported_fc4s;
38a36c61f9SKrishna Gudipati char *host_name, *os_name, *os_patch;
39a36c61f9SKrishna Gudipati int num_rports, num_ios, num_tms;
40a36c61f9SKrishna Gudipati int num_fcxps, num_ufbufs;
41a36c61f9SKrishna Gudipati int reqq_size, rspq_size, num_sgpgs;
42a36c61f9SKrishna Gudipati int rport_del_timeout = BFA_FCS_RPORT_DEF_DEL_TIMEOUT;
437725ccfdSJing Huang int bfa_lun_queue_depth = BFAD_LUN_QUEUE_DEPTH;
44a36c61f9SKrishna Gudipati int bfa_io_max_sge = BFAD_IO_MAX_SGE;
4588166242SJing Huang int bfa_log_level = 3; /* WARNING log level */
46a36c61f9SKrishna Gudipati int ioc_auto_recover = BFA_TRUE;
477725ccfdSJing Huang int bfa_linkup_delay = -1;
48a36c61f9SKrishna Gudipati int fdmi_enable = BFA_TRUE;
49a36c61f9SKrishna Gudipati int pcie_max_read_reqsz;
50ab2a9ba1SJing Huang int bfa_debugfs_enable = 1;
51a36c61f9SKrishna Gudipati int msix_disable_cb = 0, msix_disable_ct = 0;
5261e62e21SKrishna Gudipati int max_xfer_size = BFAD_MAX_SECTORS >> 1;
534d5956fbSJason Yan static int max_rport_logins = BFA_FCS_MAX_RPORT_LOGINS;
54a36c61f9SKrishna Gudipati
5561338a0bSJing Huang /* Firmware releated */
5611189208SKrishna Gudipati u32 bfi_image_cb_size, bfi_image_ct_size, bfi_image_ct2_size;
5711189208SKrishna Gudipati u32 *bfi_image_cb, *bfi_image_ct, *bfi_image_ct2;
58a36c61f9SKrishna Gudipati
592d1148f0SBenjamin Poirier #define BFAD_FW_FILE_CB "cbfw-3.2.5.1.bin"
602d1148f0SBenjamin Poirier #define BFAD_FW_FILE_CT "ctfw-3.2.5.1.bin"
612d1148f0SBenjamin Poirier #define BFAD_FW_FILE_CT2 "ct2fw-3.2.5.1.bin"
6261338a0bSJing Huang
6361338a0bSJing Huang static u32 *bfad_load_fwimg(struct pci_dev *pdev);
6461338a0bSJing Huang static void bfad_free_fwimg(void);
6561338a0bSJing Huang static void bfad_read_firmware(struct pci_dev *pdev, u32 **bfi_image,
6661338a0bSJing Huang u32 *bfi_image_size, char *fw_name);
6761338a0bSJing Huang
6852f94b6fSMaggie static const char *msix_name_ct[] = {
6911189208SKrishna Gudipati "ctrl",
70a36c61f9SKrishna Gudipati "cpe0", "cpe1", "cpe2", "cpe3",
7111189208SKrishna Gudipati "rme0", "rme1", "rme2", "rme3" };
72a36c61f9SKrishna Gudipati
7352f94b6fSMaggie static const char *msix_name_cb[] = {
74a36c61f9SKrishna Gudipati "cpe0", "cpe1", "cpe2", "cpe3",
75a36c61f9SKrishna Gudipati "rme0", "rme1", "rme2", "rme3",
76a36c61f9SKrishna Gudipati "eemc", "elpu0", "elpu1", "epss", "mlpu" };
77a36c61f9SKrishna Gudipati
7811189208SKrishna Gudipati MODULE_FIRMWARE(BFAD_FW_FILE_CB);
7911189208SKrishna Gudipati MODULE_FIRMWARE(BFAD_FW_FILE_CT);
8011189208SKrishna Gudipati MODULE_FIRMWARE(BFAD_FW_FILE_CT2);
817725ccfdSJing Huang
827725ccfdSJing Huang module_param(os_name, charp, S_IRUGO | S_IWUSR);
83604158adSJing Huang MODULE_PARM_DESC(os_name, "OS name of the hba host machine");
847725ccfdSJing Huang module_param(os_patch, charp, S_IRUGO | S_IWUSR);
85604158adSJing Huang MODULE_PARM_DESC(os_patch, "OS patch level of the hba host machine");
867725ccfdSJing Huang module_param(host_name, charp, S_IRUGO | S_IWUSR);
87604158adSJing Huang MODULE_PARM_DESC(host_name, "Hostname of the hba host machine");
887725ccfdSJing Huang module_param(num_rports, int, S_IRUGO | S_IWUSR);
89604158adSJing Huang MODULE_PARM_DESC(num_rports, "Max number of rports supported per port "
90604158adSJing Huang "(physical/logical), default=1024");
917725ccfdSJing Huang module_param(num_ios, int, S_IRUGO | S_IWUSR);
92604158adSJing Huang MODULE_PARM_DESC(num_ios, "Max number of ioim requests, default=2000");
937725ccfdSJing Huang module_param(num_tms, int, S_IRUGO | S_IWUSR);
94604158adSJing Huang MODULE_PARM_DESC(num_tms, "Max number of task im requests, default=128");
957725ccfdSJing Huang module_param(num_fcxps, int, S_IRUGO | S_IWUSR);
96604158adSJing Huang MODULE_PARM_DESC(num_fcxps, "Max number of fcxp requests, default=64");
977725ccfdSJing Huang module_param(num_ufbufs, int, S_IRUGO | S_IWUSR);
98a36c61f9SKrishna Gudipati MODULE_PARM_DESC(num_ufbufs, "Max number of unsolicited frame "
99a36c61f9SKrishna Gudipati "buffers, default=64");
1007725ccfdSJing Huang module_param(reqq_size, int, S_IRUGO | S_IWUSR);
101604158adSJing Huang MODULE_PARM_DESC(reqq_size, "Max number of request queue elements, "
102604158adSJing Huang "default=256");
1037725ccfdSJing Huang module_param(rspq_size, int, S_IRUGO | S_IWUSR);
104604158adSJing Huang MODULE_PARM_DESC(rspq_size, "Max number of response queue elements, "
105604158adSJing Huang "default=64");
1067725ccfdSJing Huang module_param(num_sgpgs, int, S_IRUGO | S_IWUSR);
107604158adSJing Huang MODULE_PARM_DESC(num_sgpgs, "Number of scatter/gather pages, default=2048");
1087725ccfdSJing Huang module_param(rport_del_timeout, int, S_IRUGO | S_IWUSR);
109604158adSJing Huang MODULE_PARM_DESC(rport_del_timeout, "Rport delete timeout, default=90 secs, "
110604158adSJing Huang "Range[>0]");
1117725ccfdSJing Huang module_param(bfa_lun_queue_depth, int, S_IRUGO | S_IWUSR);
112a36c61f9SKrishna Gudipati MODULE_PARM_DESC(bfa_lun_queue_depth, "Lun queue depth, default=32, Range[>0]");
1137725ccfdSJing Huang module_param(bfa_io_max_sge, int, S_IRUGO | S_IWUSR);
114604158adSJing Huang MODULE_PARM_DESC(bfa_io_max_sge, "Max io scatter/gather elements, default=255");
11588166242SJing Huang module_param(bfa_log_level, int, S_IRUGO | S_IWUSR);
11688166242SJing Huang MODULE_PARM_DESC(bfa_log_level, "Driver log level, default=3, "
117604158adSJing Huang "Range[Critical:1|Error:2|Warning:3|Info:4]");
1187725ccfdSJing Huang module_param(ioc_auto_recover, int, S_IRUGO | S_IWUSR);
119604158adSJing Huang MODULE_PARM_DESC(ioc_auto_recover, "IOC auto recovery, default=1, "
120604158adSJing Huang "Range[off:0|on:1]");
1217725ccfdSJing Huang module_param(bfa_linkup_delay, int, S_IRUGO | S_IWUSR);
122a36c61f9SKrishna Gudipati MODULE_PARM_DESC(bfa_linkup_delay, "Link up delay, default=30 secs for "
123a36c61f9SKrishna Gudipati "boot port. Otherwise 10 secs in RHEL4 & 0 for "
124a36c61f9SKrishna Gudipati "[RHEL5, SLES10, ESX40] Range[>0]");
125a36c61f9SKrishna Gudipati module_param(msix_disable_cb, int, S_IRUGO | S_IWUSR);
12631e1d569SAnil Gurumurthy MODULE_PARM_DESC(msix_disable_cb, "Disable Message Signaled Interrupts for QLogic-415/425/815/825 cards, default=0 Range[false:0|true:1]");
127a36c61f9SKrishna Gudipati module_param(msix_disable_ct, int, S_IRUGO | S_IWUSR);
12831e1d569SAnil Gurumurthy MODULE_PARM_DESC(msix_disable_ct, "Disable Message Signaled Interrupts if possible for QLogic-1010/1020/804/1007/902/1741 cards, default=0, Range[false:0|true:1]");
129604158adSJing Huang module_param(fdmi_enable, int, S_IRUGO | S_IWUSR);
130604158adSJing Huang MODULE_PARM_DESC(fdmi_enable, "Enables fdmi registration, default=1, "
131604158adSJing Huang "Range[false:0|true:1]");
132a36c61f9SKrishna Gudipati module_param(pcie_max_read_reqsz, int, S_IRUGO | S_IWUSR);
133a36c61f9SKrishna Gudipati MODULE_PARM_DESC(pcie_max_read_reqsz, "PCIe max read request size, default=0 "
134a36c61f9SKrishna Gudipati "(use system setting), Range[128|256|512|1024|2048|4096]");
135ab2a9ba1SJing Huang module_param(bfa_debugfs_enable, int, S_IRUGO | S_IWUSR);
136ab2a9ba1SJing Huang MODULE_PARM_DESC(bfa_debugfs_enable, "Enables debugfs feature, default=1,"
137ab2a9ba1SJing Huang " Range[false:0|true:1]");
13861e62e21SKrishna Gudipati module_param(max_xfer_size, int, S_IRUGO | S_IWUSR);
13961e62e21SKrishna Gudipati MODULE_PARM_DESC(max_xfer_size, "default=32MB,"
14061e62e21SKrishna Gudipati " Range[64k|128k|256k|512k|1024k|2048k]");
14161ba4394SKrishna Gudipati module_param(max_rport_logins, int, S_IRUGO | S_IWUSR);
14261ba4394SKrishna Gudipati MODULE_PARM_DESC(max_rport_logins, "Max number of logins to initiator and target rports on a port (physical/logical), default=1024");
1437725ccfdSJing Huang
144a36c61f9SKrishna Gudipati static void
145a36c61f9SKrishna Gudipati bfad_sm_uninit(struct bfad_s *bfad, enum bfad_sm_event event);
146a36c61f9SKrishna Gudipati static void
147a36c61f9SKrishna Gudipati bfad_sm_created(struct bfad_s *bfad, enum bfad_sm_event event);
148a36c61f9SKrishna Gudipati static void
149a36c61f9SKrishna Gudipati bfad_sm_initializing(struct bfad_s *bfad, enum bfad_sm_event event);
150a36c61f9SKrishna Gudipati static void
151a36c61f9SKrishna Gudipati bfad_sm_operational(struct bfad_s *bfad, enum bfad_sm_event event);
152a36c61f9SKrishna Gudipati static void
153a36c61f9SKrishna Gudipati bfad_sm_stopping(struct bfad_s *bfad, enum bfad_sm_event event);
154a36c61f9SKrishna Gudipati static void
155a36c61f9SKrishna Gudipati bfad_sm_failed(struct bfad_s *bfad, enum bfad_sm_event event);
156a36c61f9SKrishna Gudipati static void
157a36c61f9SKrishna Gudipati bfad_sm_fcs_exit(struct bfad_s *bfad, enum bfad_sm_event event);
158a36c61f9SKrishna Gudipati
1595fbe25c7SJing Huang /*
160a36c61f9SKrishna Gudipati * Beginning state for the driver instance, awaiting the pci_probe event
1617725ccfdSJing Huang */
162a36c61f9SKrishna Gudipati static void
bfad_sm_uninit(struct bfad_s * bfad,enum bfad_sm_event event)163a36c61f9SKrishna Gudipati bfad_sm_uninit(struct bfad_s *bfad, enum bfad_sm_event event)
1647725ccfdSJing Huang {
165a36c61f9SKrishna Gudipati bfa_trc(bfad, event);
1667725ccfdSJing Huang
167a36c61f9SKrishna Gudipati switch (event) {
168a36c61f9SKrishna Gudipati case BFAD_E_CREATE:
169a36c61f9SKrishna Gudipati bfa_sm_set_state(bfad, bfad_sm_created);
170a36c61f9SKrishna Gudipati bfad->bfad_tsk = kthread_create(bfad_worker, (void *) bfad,
171a36c61f9SKrishna Gudipati "%s", "bfad_worker");
172a36c61f9SKrishna Gudipati if (IS_ERR(bfad->bfad_tsk)) {
173a36c61f9SKrishna Gudipati printk(KERN_INFO "bfad[%d]: Kernel thread "
174a36c61f9SKrishna Gudipati "creation failed!\n", bfad->inst_no);
175a36c61f9SKrishna Gudipati bfa_sm_send_event(bfad, BFAD_E_KTHREAD_CREATE_FAILED);
176a36c61f9SKrishna Gudipati }
177a36c61f9SKrishna Gudipati bfa_sm_send_event(bfad, BFAD_E_INIT);
178a36c61f9SKrishna Gudipati break;
1797725ccfdSJing Huang
180a36c61f9SKrishna Gudipati case BFAD_E_STOP:
181a36c61f9SKrishna Gudipati /* Ignore stop; already in uninit */
182a36c61f9SKrishna Gudipati break;
1837725ccfdSJing Huang
184a36c61f9SKrishna Gudipati default:
185a36c61f9SKrishna Gudipati bfa_sm_fault(bfad, event);
186a36c61f9SKrishna Gudipati }
187a36c61f9SKrishna Gudipati }
188e6714324SKrishna Gudipati
1895fbe25c7SJing Huang /*
190a36c61f9SKrishna Gudipati * Driver Instance is created, awaiting event INIT to initialize the bfad
191a36c61f9SKrishna Gudipati */
192a36c61f9SKrishna Gudipati static void
bfad_sm_created(struct bfad_s * bfad,enum bfad_sm_event event)193a36c61f9SKrishna Gudipati bfad_sm_created(struct bfad_s *bfad, enum bfad_sm_event event)
194a36c61f9SKrishna Gudipati {
195a36c61f9SKrishna Gudipati unsigned long flags;
196da3e0beeSVijaya Mohan Guvva bfa_status_t ret;
197a36c61f9SKrishna Gudipati
198a36c61f9SKrishna Gudipati bfa_trc(bfad, event);
199a36c61f9SKrishna Gudipati
200a36c61f9SKrishna Gudipati switch (event) {
201a36c61f9SKrishna Gudipati case BFAD_E_INIT:
202a36c61f9SKrishna Gudipati bfa_sm_set_state(bfad, bfad_sm_initializing);
203a36c61f9SKrishna Gudipati
204a36c61f9SKrishna Gudipati init_completion(&bfad->comp);
205a36c61f9SKrishna Gudipati
206a36c61f9SKrishna Gudipati /* Enable Interrupt and wait bfa_init completion */
207a36c61f9SKrishna Gudipati if (bfad_setup_intr(bfad)) {
208a36c61f9SKrishna Gudipati printk(KERN_WARNING "bfad%d: bfad_setup_intr failed\n",
209a36c61f9SKrishna Gudipati bfad->inst_no);
210da3e0beeSVijaya Mohan Guvva bfa_sm_send_event(bfad, BFAD_E_INIT_FAILED);
211a36c61f9SKrishna Gudipati break;
212a36c61f9SKrishna Gudipati }
213a36c61f9SKrishna Gudipati
214a36c61f9SKrishna Gudipati spin_lock_irqsave(&bfad->bfad_lock, flags);
215f7f73812SMaggie Zhang bfa_iocfc_init(&bfad->bfa);
216a36c61f9SKrishna Gudipati spin_unlock_irqrestore(&bfad->bfad_lock, flags);
217a36c61f9SKrishna Gudipati
218a36c61f9SKrishna Gudipati /* Set up interrupt handler for each vectors */
219a36c61f9SKrishna Gudipati if ((bfad->bfad_flags & BFAD_MSIX_ON) &&
220a36c61f9SKrishna Gudipati bfad_install_msix_handler(bfad)) {
221a36c61f9SKrishna Gudipati printk(KERN_WARNING "%s: install_msix failed, bfad%d\n",
222a36c61f9SKrishna Gudipati __func__, bfad->inst_no);
223a36c61f9SKrishna Gudipati }
224a36c61f9SKrishna Gudipati
225a36c61f9SKrishna Gudipati bfad_init_timer(bfad);
226a36c61f9SKrishna Gudipati
227a36c61f9SKrishna Gudipati wait_for_completion(&bfad->comp);
228a36c61f9SKrishna Gudipati
229a36c61f9SKrishna Gudipati if ((bfad->bfad_flags & BFAD_HAL_INIT_DONE)) {
230a36c61f9SKrishna Gudipati bfa_sm_send_event(bfad, BFAD_E_INIT_SUCCESS);
231a36c61f9SKrishna Gudipati } else {
2327c38c05bSKrishna Gudipati printk(KERN_WARNING
2337c38c05bSKrishna Gudipati "bfa %s: bfa init failed\n",
2347c38c05bSKrishna Gudipati bfad->pci_name);
235da3e0beeSVijaya Mohan Guvva spin_lock_irqsave(&bfad->bfad_lock, flags);
236da3e0beeSVijaya Mohan Guvva bfa_fcs_init(&bfad->bfa_fcs);
237da3e0beeSVijaya Mohan Guvva spin_unlock_irqrestore(&bfad->bfad_lock, flags);
238da3e0beeSVijaya Mohan Guvva
239da3e0beeSVijaya Mohan Guvva ret = bfad_cfg_pport(bfad, BFA_LPORT_ROLE_FCP_IM);
240da3e0beeSVijaya Mohan Guvva if (ret != BFA_STATUS_OK) {
241da3e0beeSVijaya Mohan Guvva init_completion(&bfad->comp);
242da3e0beeSVijaya Mohan Guvva
243da3e0beeSVijaya Mohan Guvva spin_lock_irqsave(&bfad->bfad_lock, flags);
244da3e0beeSVijaya Mohan Guvva bfad->pport.flags |= BFAD_PORT_DELETE;
245da3e0beeSVijaya Mohan Guvva bfa_fcs_exit(&bfad->bfa_fcs);
246da3e0beeSVijaya Mohan Guvva spin_unlock_irqrestore(&bfad->bfad_lock, flags);
247da3e0beeSVijaya Mohan Guvva
248da3e0beeSVijaya Mohan Guvva wait_for_completion(&bfad->comp);
249da3e0beeSVijaya Mohan Guvva
250a36c61f9SKrishna Gudipati bfa_sm_send_event(bfad, BFAD_E_INIT_FAILED);
251da3e0beeSVijaya Mohan Guvva break;
252da3e0beeSVijaya Mohan Guvva }
253da3e0beeSVijaya Mohan Guvva bfad->bfad_flags |= BFAD_HAL_INIT_FAIL;
254da3e0beeSVijaya Mohan Guvva bfa_sm_send_event(bfad, BFAD_E_HAL_INIT_FAILED);
255a36c61f9SKrishna Gudipati }
256a36c61f9SKrishna Gudipati
257a36c61f9SKrishna Gudipati break;
258a36c61f9SKrishna Gudipati
259a36c61f9SKrishna Gudipati case BFAD_E_KTHREAD_CREATE_FAILED:
260a36c61f9SKrishna Gudipati bfa_sm_set_state(bfad, bfad_sm_uninit);
261a36c61f9SKrishna Gudipati break;
262a36c61f9SKrishna Gudipati
263a36c61f9SKrishna Gudipati default:
264a36c61f9SKrishna Gudipati bfa_sm_fault(bfad, event);
265a36c61f9SKrishna Gudipati }
2667725ccfdSJing Huang }
2677725ccfdSJing Huang
2687725ccfdSJing Huang static void
bfad_sm_initializing(struct bfad_s * bfad,enum bfad_sm_event event)269a36c61f9SKrishna Gudipati bfad_sm_initializing(struct bfad_s *bfad, enum bfad_sm_event event)
2707725ccfdSJing Huang {
271a36c61f9SKrishna Gudipati int retval;
272a36c61f9SKrishna Gudipati unsigned long flags;
273a36c61f9SKrishna Gudipati
274a36c61f9SKrishna Gudipati bfa_trc(bfad, event);
275a36c61f9SKrishna Gudipati
276a36c61f9SKrishna Gudipati switch (event) {
277a36c61f9SKrishna Gudipati case BFAD_E_INIT_SUCCESS:
278a36c61f9SKrishna Gudipati kthread_stop(bfad->bfad_tsk);
279a36c61f9SKrishna Gudipati spin_lock_irqsave(&bfad->bfad_lock, flags);
280a36c61f9SKrishna Gudipati bfad->bfad_tsk = NULL;
281a36c61f9SKrishna Gudipati spin_unlock_irqrestore(&bfad->bfad_lock, flags);
282a36c61f9SKrishna Gudipati
283a36c61f9SKrishna Gudipati retval = bfad_start_ops(bfad);
284da3e0beeSVijaya Mohan Guvva if (retval != BFA_STATUS_OK) {
285da3e0beeSVijaya Mohan Guvva bfa_sm_set_state(bfad, bfad_sm_failed);
286a36c61f9SKrishna Gudipati break;
287da3e0beeSVijaya Mohan Guvva }
288a36c61f9SKrishna Gudipati bfa_sm_set_state(bfad, bfad_sm_operational);
289a36c61f9SKrishna Gudipati break;
290a36c61f9SKrishna Gudipati
291da3e0beeSVijaya Mohan Guvva case BFAD_E_INIT_FAILED:
292a36c61f9SKrishna Gudipati bfa_sm_set_state(bfad, bfad_sm_uninit);
293a36c61f9SKrishna Gudipati kthread_stop(bfad->bfad_tsk);
294a36c61f9SKrishna Gudipati spin_lock_irqsave(&bfad->bfad_lock, flags);
295a36c61f9SKrishna Gudipati bfad->bfad_tsk = NULL;
296a36c61f9SKrishna Gudipati spin_unlock_irqrestore(&bfad->bfad_lock, flags);
297a36c61f9SKrishna Gudipati break;
298a36c61f9SKrishna Gudipati
299da3e0beeSVijaya Mohan Guvva case BFAD_E_HAL_INIT_FAILED:
300a36c61f9SKrishna Gudipati bfa_sm_set_state(bfad, bfad_sm_failed);
301a36c61f9SKrishna Gudipati break;
302a36c61f9SKrishna Gudipati default:
303a36c61f9SKrishna Gudipati bfa_sm_fault(bfad, event);
304a36c61f9SKrishna Gudipati }
305a36c61f9SKrishna Gudipati }
306a36c61f9SKrishna Gudipati
307a36c61f9SKrishna Gudipati static void
bfad_sm_failed(struct bfad_s * bfad,enum bfad_sm_event event)308a36c61f9SKrishna Gudipati bfad_sm_failed(struct bfad_s *bfad, enum bfad_sm_event event)
309a36c61f9SKrishna Gudipati {
310a36c61f9SKrishna Gudipati int retval;
311a36c61f9SKrishna Gudipati
312a36c61f9SKrishna Gudipati bfa_trc(bfad, event);
313a36c61f9SKrishna Gudipati
314a36c61f9SKrishna Gudipati switch (event) {
315a36c61f9SKrishna Gudipati case BFAD_E_INIT_SUCCESS:
316a36c61f9SKrishna Gudipati retval = bfad_start_ops(bfad);
317a36c61f9SKrishna Gudipati if (retval != BFA_STATUS_OK)
318a36c61f9SKrishna Gudipati break;
319a36c61f9SKrishna Gudipati bfa_sm_set_state(bfad, bfad_sm_operational);
320a36c61f9SKrishna Gudipati break;
321a36c61f9SKrishna Gudipati
322a36c61f9SKrishna Gudipati case BFAD_E_STOP:
323da3e0beeSVijaya Mohan Guvva bfa_sm_set_state(bfad, bfad_sm_fcs_exit);
324da3e0beeSVijaya Mohan Guvva bfa_sm_send_event(bfad, BFAD_E_FCS_EXIT_COMP);
325a36c61f9SKrishna Gudipati break;
3267725ccfdSJing Huang
327a36c61f9SKrishna Gudipati case BFAD_E_EXIT_COMP:
328a36c61f9SKrishna Gudipati bfa_sm_set_state(bfad, bfad_sm_uninit);
329a36c61f9SKrishna Gudipati bfad_remove_intr(bfad);
330a36c61f9SKrishna Gudipati del_timer_sync(&bfad->hal_tmo);
331a36c61f9SKrishna Gudipati break;
3327725ccfdSJing Huang
333a36c61f9SKrishna Gudipati default:
334a36c61f9SKrishna Gudipati bfa_sm_fault(bfad, event);
3357725ccfdSJing Huang }
3367725ccfdSJing Huang }
3377725ccfdSJing Huang
3387725ccfdSJing Huang static void
bfad_sm_operational(struct bfad_s * bfad,enum bfad_sm_event event)339a36c61f9SKrishna Gudipati bfad_sm_operational(struct bfad_s *bfad, enum bfad_sm_event event)
3407725ccfdSJing Huang {
341a36c61f9SKrishna Gudipati bfa_trc(bfad, event);
3427725ccfdSJing Huang
343a36c61f9SKrishna Gudipati switch (event) {
344a36c61f9SKrishna Gudipati case BFAD_E_STOP:
345a36c61f9SKrishna Gudipati bfa_sm_set_state(bfad, bfad_sm_fcs_exit);
346a36c61f9SKrishna Gudipati bfad_fcs_stop(bfad);
347a36c61f9SKrishna Gudipati break;
3487725ccfdSJing Huang
349a36c61f9SKrishna Gudipati default:
350a36c61f9SKrishna Gudipati bfa_sm_fault(bfad, event);
351a36c61f9SKrishna Gudipati }
352a36c61f9SKrishna Gudipati }
353a36c61f9SKrishna Gudipati
354a36c61f9SKrishna Gudipati static void
bfad_sm_fcs_exit(struct bfad_s * bfad,enum bfad_sm_event event)355a36c61f9SKrishna Gudipati bfad_sm_fcs_exit(struct bfad_s *bfad, enum bfad_sm_event event)
356a36c61f9SKrishna Gudipati {
357a36c61f9SKrishna Gudipati bfa_trc(bfad, event);
358a36c61f9SKrishna Gudipati
359a36c61f9SKrishna Gudipati switch (event) {
360a36c61f9SKrishna Gudipati case BFAD_E_FCS_EXIT_COMP:
361a36c61f9SKrishna Gudipati bfa_sm_set_state(bfad, bfad_sm_stopping);
362a36c61f9SKrishna Gudipati bfad_stop(bfad);
363a36c61f9SKrishna Gudipati break;
364a36c61f9SKrishna Gudipati
365a36c61f9SKrishna Gudipati default:
366a36c61f9SKrishna Gudipati bfa_sm_fault(bfad, event);
367a36c61f9SKrishna Gudipati }
368a36c61f9SKrishna Gudipati }
369a36c61f9SKrishna Gudipati
370a36c61f9SKrishna Gudipati static void
bfad_sm_stopping(struct bfad_s * bfad,enum bfad_sm_event event)371a36c61f9SKrishna Gudipati bfad_sm_stopping(struct bfad_s *bfad, enum bfad_sm_event event)
372a36c61f9SKrishna Gudipati {
373a36c61f9SKrishna Gudipati bfa_trc(bfad, event);
374a36c61f9SKrishna Gudipati
375a36c61f9SKrishna Gudipati switch (event) {
376a36c61f9SKrishna Gudipati case BFAD_E_EXIT_COMP:
377a36c61f9SKrishna Gudipati bfa_sm_set_state(bfad, bfad_sm_uninit);
378a36c61f9SKrishna Gudipati bfad_remove_intr(bfad);
379a36c61f9SKrishna Gudipati del_timer_sync(&bfad->hal_tmo);
380a36c61f9SKrishna Gudipati bfad_im_probe_undo(bfad);
381a36c61f9SKrishna Gudipati bfad->bfad_flags &= ~BFAD_FC4_PROBE_DONE;
382a36c61f9SKrishna Gudipati bfad_uncfg_pport(bfad);
383a36c61f9SKrishna Gudipati break;
384a36c61f9SKrishna Gudipati
385a36c61f9SKrishna Gudipati default:
386a36c61f9SKrishna Gudipati bfa_sm_fault(bfad, event);
387a36c61f9SKrishna Gudipati break;
388a36c61f9SKrishna Gudipati }
3897725ccfdSJing Huang }
3907725ccfdSJing Huang
3915fbe25c7SJing Huang /*
3927725ccfdSJing Huang * BFA callbacks
3937725ccfdSJing Huang */
3947725ccfdSJing Huang void
bfad_hcb_comp(void * arg,bfa_status_t status)3957725ccfdSJing Huang bfad_hcb_comp(void *arg, bfa_status_t status)
3967725ccfdSJing Huang {
3977725ccfdSJing Huang struct bfad_hal_comp *fcomp = (struct bfad_hal_comp *)arg;
3987725ccfdSJing Huang
3997725ccfdSJing Huang fcomp->status = status;
4007725ccfdSJing Huang complete(&fcomp->comp);
4017725ccfdSJing Huang }
4027725ccfdSJing Huang
4035fbe25c7SJing Huang /*
4047725ccfdSJing Huang * bfa_init callback
4057725ccfdSJing Huang */
4067725ccfdSJing Huang void
bfa_cb_init(void * drv,bfa_status_t init_status)4077725ccfdSJing Huang bfa_cb_init(void *drv, bfa_status_t init_status)
4087725ccfdSJing Huang {
4097725ccfdSJing Huang struct bfad_s *bfad = drv;
4107725ccfdSJing Huang
411e6714324SKrishna Gudipati if (init_status == BFA_STATUS_OK) {
4127725ccfdSJing Huang bfad->bfad_flags |= BFAD_HAL_INIT_DONE;
4137725ccfdSJing Huang
414a36c61f9SKrishna Gudipati /*
415a36c61f9SKrishna Gudipati * If BFAD_HAL_INIT_FAIL flag is set:
416e6714324SKrishna Gudipati * Wake up the kernel thread to start
417e6714324SKrishna Gudipati * the bfad operations after HAL init done
418e6714324SKrishna Gudipati */
419e6714324SKrishna Gudipati if ((bfad->bfad_flags & BFAD_HAL_INIT_FAIL)) {
420e6714324SKrishna Gudipati bfad->bfad_flags &= ~BFAD_HAL_INIT_FAIL;
421e6714324SKrishna Gudipati wake_up_process(bfad->bfad_tsk);
422e6714324SKrishna Gudipati }
423e6714324SKrishna Gudipati }
424e6714324SKrishna Gudipati
4257725ccfdSJing Huang complete(&bfad->comp);
4267725ccfdSJing Huang }
4277725ccfdSJing Huang
4285fbe25c7SJing Huang /*
4297725ccfdSJing Huang * BFA_FCS callbacks
4307725ccfdSJing Huang */
4317725ccfdSJing Huang struct bfad_port_s *
bfa_fcb_lport_new(struct bfad_s * bfad,struct bfa_fcs_lport_s * port,enum bfa_lport_role roles,struct bfad_vf_s * vf_drv,struct bfad_vport_s * vp_drv)432a36c61f9SKrishna Gudipati bfa_fcb_lport_new(struct bfad_s *bfad, struct bfa_fcs_lport_s *port,
433a36c61f9SKrishna Gudipati enum bfa_lport_role roles, struct bfad_vf_s *vf_drv,
4347725ccfdSJing Huang struct bfad_vport_s *vp_drv)
4357725ccfdSJing Huang {
4367725ccfdSJing Huang bfa_status_t rc;
4377725ccfdSJing Huang struct bfad_port_s *port_drv;
4387725ccfdSJing Huang
4397725ccfdSJing Huang if (!vp_drv && !vf_drv) {
4407725ccfdSJing Huang port_drv = &bfad->pport;
4417725ccfdSJing Huang port_drv->pvb_type = BFAD_PORT_PHYS_BASE;
4427725ccfdSJing Huang } else if (!vp_drv && vf_drv) {
4437725ccfdSJing Huang port_drv = &vf_drv->base_port;
4447725ccfdSJing Huang port_drv->pvb_type = BFAD_PORT_VF_BASE;
4457725ccfdSJing Huang } else if (vp_drv && !vf_drv) {
4467725ccfdSJing Huang port_drv = &vp_drv->drv_port;
4477725ccfdSJing Huang port_drv->pvb_type = BFAD_PORT_PHYS_VPORT;
4487725ccfdSJing Huang } else {
4497725ccfdSJing Huang port_drv = &vp_drv->drv_port;
4507725ccfdSJing Huang port_drv->pvb_type = BFAD_PORT_VF_VPORT;
4517725ccfdSJing Huang }
4527725ccfdSJing Huang
4537725ccfdSJing Huang port_drv->fcs_port = port;
4547725ccfdSJing Huang port_drv->roles = roles;
455a36c61f9SKrishna Gudipati
456a36c61f9SKrishna Gudipati if (roles & BFA_LPORT_ROLE_FCP_IM) {
457a36c61f9SKrishna Gudipati rc = bfad_im_port_new(bfad, port_drv);
4587725ccfdSJing Huang if (rc != BFA_STATUS_OK) {
459a36c61f9SKrishna Gudipati bfad_im_port_delete(bfad, port_drv);
4607725ccfdSJing Huang port_drv = NULL;
4617725ccfdSJing Huang }
462a36c61f9SKrishna Gudipati }
4637725ccfdSJing Huang
4647725ccfdSJing Huang return port_drv;
4657725ccfdSJing Huang }
4667725ccfdSJing Huang
4675fbe25c7SJing Huang /*
4687725ccfdSJing Huang * FCS RPORT alloc callback, after successful PLOGI by FCS
4697725ccfdSJing Huang */
4707725ccfdSJing Huang bfa_status_t
bfa_fcb_rport_alloc(struct bfad_s * bfad,struct bfa_fcs_rport_s ** rport,struct bfad_rport_s ** rport_drv)4717725ccfdSJing Huang bfa_fcb_rport_alloc(struct bfad_s *bfad, struct bfa_fcs_rport_s **rport,
4727725ccfdSJing Huang struct bfad_rport_s **rport_drv)
4737725ccfdSJing Huang {
4747725ccfdSJing Huang bfa_status_t rc = BFA_STATUS_OK;
4757725ccfdSJing Huang
4767725ccfdSJing Huang *rport_drv = kzalloc(sizeof(struct bfad_rport_s), GFP_ATOMIC);
4777725ccfdSJing Huang if (*rport_drv == NULL) {
4787725ccfdSJing Huang rc = BFA_STATUS_ENOMEM;
4797725ccfdSJing Huang goto ext;
4807725ccfdSJing Huang }
4817725ccfdSJing Huang
4827725ccfdSJing Huang *rport = &(*rport_drv)->fcs_rport;
4837725ccfdSJing Huang
4847725ccfdSJing Huang ext:
4857725ccfdSJing Huang return rc;
4867725ccfdSJing Huang }
4877725ccfdSJing Huang
4885fbe25c7SJing Huang /*
489d9883548SJing Huang * FCS PBC VPORT Create
490d9883548SJing Huang */
491d9883548SJing Huang void
bfa_fcb_pbc_vport_create(struct bfad_s * bfad,struct bfi_pbc_vport_s pbc_vport)492d9883548SJing Huang bfa_fcb_pbc_vport_create(struct bfad_s *bfad, struct bfi_pbc_vport_s pbc_vport)
493d9883548SJing Huang {
4947725ccfdSJing Huang
495a36c61f9SKrishna Gudipati struct bfa_lport_cfg_s port_cfg = {0};
496a36c61f9SKrishna Gudipati struct bfad_vport_s *vport;
497a36c61f9SKrishna Gudipati int rc;
498d9883548SJing Huang
499dc6d2a0fSAlexey Khoroshilov vport = kzalloc(sizeof(struct bfad_vport_s), GFP_ATOMIC);
500a36c61f9SKrishna Gudipati if (!vport) {
501d9883548SJing Huang bfa_trc(bfad, 0);
502d9883548SJing Huang return;
503d9883548SJing Huang }
504d9883548SJing Huang
505a36c61f9SKrishna Gudipati vport->drv_port.bfad = bfad;
506a36c61f9SKrishna Gudipati port_cfg.roles = BFA_LPORT_ROLE_FCP_IM;
507a36c61f9SKrishna Gudipati port_cfg.pwwn = pbc_vport.vp_pwwn;
508a36c61f9SKrishna Gudipati port_cfg.nwwn = pbc_vport.vp_nwwn;
509a36c61f9SKrishna Gudipati port_cfg.preboot_vp = BFA_TRUE;
510d9883548SJing Huang
511a36c61f9SKrishna Gudipati rc = bfa_fcs_pbc_vport_create(&vport->fcs_vport, &bfad->bfa_fcs, 0,
512a36c61f9SKrishna Gudipati &port_cfg, vport);
513d9883548SJing Huang
514a36c61f9SKrishna Gudipati if (rc != BFA_STATUS_OK) {
515a36c61f9SKrishna Gudipati bfa_trc(bfad, 0);
516d9883548SJing Huang return;
517d9883548SJing Huang }
5187725ccfdSJing Huang
519a36c61f9SKrishna Gudipati list_add_tail(&vport->list_entry, &bfad->pbc_vport_list);
520a36c61f9SKrishna Gudipati }
521a36c61f9SKrishna Gudipati
5227725ccfdSJing Huang void
bfad_hal_mem_release(struct bfad_s * bfad)5237725ccfdSJing Huang bfad_hal_mem_release(struct bfad_s *bfad)
5247725ccfdSJing Huang {
5257725ccfdSJing Huang struct bfa_meminfo_s *hal_meminfo = &bfad->meminfo;
5264507025dSKrishna Gudipati struct bfa_mem_dma_s *dma_info, *dma_elem;
5274507025dSKrishna Gudipati struct bfa_mem_kva_s *kva_info, *kva_elem;
5284507025dSKrishna Gudipati struct list_head *dm_qe, *km_qe;
5297725ccfdSJing Huang
5304507025dSKrishna Gudipati dma_info = &hal_meminfo->dma_info;
5314507025dSKrishna Gudipati kva_info = &hal_meminfo->kva_info;
5324507025dSKrishna Gudipati
5334507025dSKrishna Gudipati /* Iterate through the KVA meminfo queue */
5344507025dSKrishna Gudipati list_for_each(km_qe, &kva_info->qe) {
5354507025dSKrishna Gudipati kva_elem = (struct bfa_mem_kva_s *) km_qe;
5364507025dSKrishna Gudipati vfree(kva_elem->kva);
5374507025dSKrishna Gudipati }
5384507025dSKrishna Gudipati
5394507025dSKrishna Gudipati /* Iterate through the DMA meminfo queue */
5404507025dSKrishna Gudipati list_for_each(dm_qe, &dma_info->qe) {
5414507025dSKrishna Gudipati dma_elem = (struct bfa_mem_dma_s *) dm_qe;
5427725ccfdSJing Huang dma_free_coherent(&bfad->pcidev->dev,
5434507025dSKrishna Gudipati dma_elem->mem_len, dma_elem->kva,
5444507025dSKrishna Gudipati (dma_addr_t) dma_elem->dma);
5457725ccfdSJing Huang }
5467725ccfdSJing Huang
5477725ccfdSJing Huang memset(hal_meminfo, 0, sizeof(struct bfa_meminfo_s));
5487725ccfdSJing Huang }
5497725ccfdSJing Huang
5507725ccfdSJing Huang void
bfad_update_hal_cfg(struct bfa_iocfc_cfg_s * bfa_cfg)5517725ccfdSJing Huang bfad_update_hal_cfg(struct bfa_iocfc_cfg_s *bfa_cfg)
5527725ccfdSJing Huang {
5537725ccfdSJing Huang if (num_rports > 0)
5547725ccfdSJing Huang bfa_cfg->fwcfg.num_rports = num_rports;
5557725ccfdSJing Huang if (num_ios > 0)
5567725ccfdSJing Huang bfa_cfg->fwcfg.num_ioim_reqs = num_ios;
5577725ccfdSJing Huang if (num_tms > 0)
5587725ccfdSJing Huang bfa_cfg->fwcfg.num_tskim_reqs = num_tms;
5594507025dSKrishna Gudipati if (num_fcxps > 0 && num_fcxps <= BFA_FCXP_MAX)
5607725ccfdSJing Huang bfa_cfg->fwcfg.num_fcxp_reqs = num_fcxps;
5614507025dSKrishna Gudipati if (num_ufbufs > 0 && num_ufbufs <= BFA_UF_MAX)
5627725ccfdSJing Huang bfa_cfg->fwcfg.num_uf_bufs = num_ufbufs;
5637725ccfdSJing Huang if (reqq_size > 0)
5647725ccfdSJing Huang bfa_cfg->drvcfg.num_reqq_elems = reqq_size;
5657725ccfdSJing Huang if (rspq_size > 0)
5667725ccfdSJing Huang bfa_cfg->drvcfg.num_rspq_elems = rspq_size;
5674507025dSKrishna Gudipati if (num_sgpgs > 0 && num_sgpgs <= BFA_SGPG_MAX)
5687725ccfdSJing Huang bfa_cfg->drvcfg.num_sgpgs = num_sgpgs;
5697725ccfdSJing Huang
5707725ccfdSJing Huang /*
5717725ccfdSJing Huang * populate the hal values back to the driver for sysfs use.
5727725ccfdSJing Huang * otherwise, the default values will be shown as 0 in sysfs
5737725ccfdSJing Huang */
5747725ccfdSJing Huang num_rports = bfa_cfg->fwcfg.num_rports;
5757725ccfdSJing Huang num_ios = bfa_cfg->fwcfg.num_ioim_reqs;
5767725ccfdSJing Huang num_tms = bfa_cfg->fwcfg.num_tskim_reqs;
5777725ccfdSJing Huang num_fcxps = bfa_cfg->fwcfg.num_fcxp_reqs;
5787725ccfdSJing Huang num_ufbufs = bfa_cfg->fwcfg.num_uf_bufs;
5797725ccfdSJing Huang reqq_size = bfa_cfg->drvcfg.num_reqq_elems;
5807725ccfdSJing Huang rspq_size = bfa_cfg->drvcfg.num_rspq_elems;
5817725ccfdSJing Huang num_sgpgs = bfa_cfg->drvcfg.num_sgpgs;
5827725ccfdSJing Huang }
5837725ccfdSJing Huang
5847725ccfdSJing Huang bfa_status_t
bfad_hal_mem_alloc(struct bfad_s * bfad)5857725ccfdSJing Huang bfad_hal_mem_alloc(struct bfad_s *bfad)
5867725ccfdSJing Huang {
5877725ccfdSJing Huang struct bfa_meminfo_s *hal_meminfo = &bfad->meminfo;
5884507025dSKrishna Gudipati struct bfa_mem_dma_s *dma_info, *dma_elem;
5894507025dSKrishna Gudipati struct bfa_mem_kva_s *kva_info, *kva_elem;
5904507025dSKrishna Gudipati struct list_head *dm_qe, *km_qe;
591a36c61f9SKrishna Gudipati bfa_status_t rc = BFA_STATUS_OK;
5924507025dSKrishna Gudipati dma_addr_t phys_addr;
5937725ccfdSJing Huang
5947725ccfdSJing Huang bfa_cfg_get_default(&bfad->ioc_cfg);
5957725ccfdSJing Huang bfad_update_hal_cfg(&bfad->ioc_cfg);
5967725ccfdSJing Huang bfad->cfg_data.ioc_queue_depth = bfad->ioc_cfg.fwcfg.num_ioim_reqs;
5974507025dSKrishna Gudipati bfa_cfg_get_meminfo(&bfad->ioc_cfg, hal_meminfo, &bfad->bfa);
5987725ccfdSJing Huang
5994507025dSKrishna Gudipati dma_info = &hal_meminfo->dma_info;
6004507025dSKrishna Gudipati kva_info = &hal_meminfo->kva_info;
6014507025dSKrishna Gudipati
6024507025dSKrishna Gudipati /* Iterate through the KVA meminfo queue */
6034507025dSKrishna Gudipati list_for_each(km_qe, &kva_info->qe) {
6044507025dSKrishna Gudipati kva_elem = (struct bfa_mem_kva_s *) km_qe;
605bde70f3cSHimanshu Jha kva_elem->kva = vzalloc(kva_elem->mem_len);
6064507025dSKrishna Gudipati if (kva_elem->kva == NULL) {
6077725ccfdSJing Huang bfad_hal_mem_release(bfad);
6087725ccfdSJing Huang rc = BFA_STATUS_ENOMEM;
6097725ccfdSJing Huang goto ext;
6107725ccfdSJing Huang }
6117725ccfdSJing Huang }
6124507025dSKrishna Gudipati
6134507025dSKrishna Gudipati /* Iterate through the DMA meminfo queue */
6144507025dSKrishna Gudipati list_for_each(dm_qe, &dma_info->qe) {
6154507025dSKrishna Gudipati dma_elem = (struct bfa_mem_dma_s *) dm_qe;
6164507025dSKrishna Gudipati dma_elem->kva = dma_alloc_coherent(&bfad->pcidev->dev,
6174507025dSKrishna Gudipati dma_elem->mem_len,
6184507025dSKrishna Gudipati &phys_addr, GFP_KERNEL);
6194507025dSKrishna Gudipati if (dma_elem->kva == NULL) {
6204507025dSKrishna Gudipati bfad_hal_mem_release(bfad);
6217725ccfdSJing Huang rc = BFA_STATUS_ENOMEM;
6227725ccfdSJing Huang goto ext;
6237725ccfdSJing Huang }
6244507025dSKrishna Gudipati dma_elem->dma = phys_addr;
6254507025dSKrishna Gudipati memset(dma_elem->kva, 0, dma_elem->mem_len);
6267725ccfdSJing Huang }
6277725ccfdSJing Huang ext:
6287725ccfdSJing Huang return rc;
6297725ccfdSJing Huang }
6307725ccfdSJing Huang
6315fbe25c7SJing Huang /*
6327725ccfdSJing Huang * Create a vport under a vf.
6337725ccfdSJing Huang */
6347725ccfdSJing Huang bfa_status_t
bfad_vport_create(struct bfad_s * bfad,u16 vf_id,struct bfa_lport_cfg_s * port_cfg,struct device * dev)6357725ccfdSJing Huang bfad_vport_create(struct bfad_s *bfad, u16 vf_id,
636a36c61f9SKrishna Gudipati struct bfa_lport_cfg_s *port_cfg, struct device *dev)
6377725ccfdSJing Huang {
6387725ccfdSJing Huang struct bfad_vport_s *vport;
6397725ccfdSJing Huang int rc = BFA_STATUS_OK;
6407725ccfdSJing Huang unsigned long flags;
6417725ccfdSJing Huang struct completion fcomp;
6427725ccfdSJing Huang
6437725ccfdSJing Huang vport = kzalloc(sizeof(struct bfad_vport_s), GFP_KERNEL);
6447725ccfdSJing Huang if (!vport) {
6457725ccfdSJing Huang rc = BFA_STATUS_ENOMEM;
6467725ccfdSJing Huang goto ext;
6477725ccfdSJing Huang }
6487725ccfdSJing Huang
6497725ccfdSJing Huang vport->drv_port.bfad = bfad;
6507725ccfdSJing Huang spin_lock_irqsave(&bfad->bfad_lock, flags);
651a36c61f9SKrishna Gudipati rc = bfa_fcs_vport_create(&vport->fcs_vport, &bfad->bfa_fcs, vf_id,
652a36c61f9SKrishna Gudipati port_cfg, vport);
6537725ccfdSJing Huang spin_unlock_irqrestore(&bfad->bfad_lock, flags);
6547725ccfdSJing Huang
6557725ccfdSJing Huang if (rc != BFA_STATUS_OK)
6567725ccfdSJing Huang goto ext_free_vport;
6577725ccfdSJing Huang
658a36c61f9SKrishna Gudipati if (port_cfg->roles & BFA_LPORT_ROLE_FCP_IM) {
659b504293fSJing Huang rc = bfad_im_scsi_host_alloc(bfad, vport->drv_port.im_port,
660b504293fSJing Huang dev);
6617725ccfdSJing Huang if (rc != BFA_STATUS_OK)
6627725ccfdSJing Huang goto ext_free_fcs_vport;
6637725ccfdSJing Huang }
6647725ccfdSJing Huang
6657725ccfdSJing Huang spin_lock_irqsave(&bfad->bfad_lock, flags);
6667725ccfdSJing Huang bfa_fcs_vport_start(&vport->fcs_vport);
6675b7db7afSKrishna Gudipati list_add_tail(&vport->list_entry, &bfad->vport_list);
6687725ccfdSJing Huang spin_unlock_irqrestore(&bfad->bfad_lock, flags);
6697725ccfdSJing Huang
6707725ccfdSJing Huang return BFA_STATUS_OK;
6717725ccfdSJing Huang
6727725ccfdSJing Huang ext_free_fcs_vport:
6737725ccfdSJing Huang spin_lock_irqsave(&bfad->bfad_lock, flags);
6747725ccfdSJing Huang vport->comp_del = &fcomp;
6757725ccfdSJing Huang init_completion(vport->comp_del);
6767725ccfdSJing Huang bfa_fcs_vport_delete(&vport->fcs_vport);
6777725ccfdSJing Huang spin_unlock_irqrestore(&bfad->bfad_lock, flags);
6787725ccfdSJing Huang wait_for_completion(vport->comp_del);
6797725ccfdSJing Huang ext_free_vport:
6807725ccfdSJing Huang kfree(vport);
6817725ccfdSJing Huang ext:
6827725ccfdSJing Huang return rc;
6837725ccfdSJing Huang }
6847725ccfdSJing Huang
6857725ccfdSJing Huang void
bfad_bfa_tmo(struct timer_list * t)686e99e88a9SKees Cook bfad_bfa_tmo(struct timer_list *t)
6877725ccfdSJing Huang {
688e99e88a9SKees Cook struct bfad_s *bfad = from_timer(bfad, t, hal_tmo);
6897725ccfdSJing Huang unsigned long flags;
6907725ccfdSJing Huang struct list_head doneq;
6917725ccfdSJing Huang
6927725ccfdSJing Huang spin_lock_irqsave(&bfad->bfad_lock, flags);
6937725ccfdSJing Huang
694f7f73812SMaggie Zhang bfa_timer_beat(&bfad->bfa.timer_mod);
6957725ccfdSJing Huang
6967725ccfdSJing Huang bfa_comp_deq(&bfad->bfa, &doneq);
6977725ccfdSJing Huang spin_unlock_irqrestore(&bfad->bfad_lock, flags);
6987725ccfdSJing Huang
6997725ccfdSJing Huang if (!list_empty(&doneq)) {
7007725ccfdSJing Huang bfa_comp_process(&bfad->bfa, &doneq);
7017725ccfdSJing Huang spin_lock_irqsave(&bfad->bfad_lock, flags);
7027725ccfdSJing Huang bfa_comp_free(&bfad->bfa, &doneq);
7037725ccfdSJing Huang spin_unlock_irqrestore(&bfad->bfad_lock, flags);
7047725ccfdSJing Huang }
7057725ccfdSJing Huang
706a36c61f9SKrishna Gudipati mod_timer(&bfad->hal_tmo,
707a36c61f9SKrishna Gudipati jiffies + msecs_to_jiffies(BFA_TIMER_FREQ));
7087725ccfdSJing Huang }
7097725ccfdSJing Huang
7107725ccfdSJing Huang void
bfad_init_timer(struct bfad_s * bfad)7117725ccfdSJing Huang bfad_init_timer(struct bfad_s *bfad)
7127725ccfdSJing Huang {
713e99e88a9SKees Cook timer_setup(&bfad->hal_tmo, bfad_bfa_tmo, 0);
7147725ccfdSJing Huang
715a36c61f9SKrishna Gudipati mod_timer(&bfad->hal_tmo,
716a36c61f9SKrishna Gudipati jiffies + msecs_to_jiffies(BFA_TIMER_FREQ));
7177725ccfdSJing Huang }
7187725ccfdSJing Huang
7197725ccfdSJing Huang int
bfad_pci_init(struct pci_dev * pdev,struct bfad_s * bfad)7207725ccfdSJing Huang bfad_pci_init(struct pci_dev *pdev, struct bfad_s *bfad)
7217725ccfdSJing Huang {
7227725ccfdSJing Huang int rc = -ENODEV;
7237725ccfdSJing Huang
7247725ccfdSJing Huang if (pci_enable_device(pdev)) {
725a36c61f9SKrishna Gudipati printk(KERN_ERR "pci_enable_device fail %p\n", pdev);
7267725ccfdSJing Huang goto out;
7277725ccfdSJing Huang }
7287725ccfdSJing Huang
7297725ccfdSJing Huang if (pci_request_regions(pdev, BFAD_DRIVER_NAME))
7307725ccfdSJing Huang goto out_disable_device;
7317725ccfdSJing Huang
7327725ccfdSJing Huang pci_set_master(pdev);
7337725ccfdSJing Huang
73411ea3824SHannes Reinecke rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
73511ea3824SHannes Reinecke if (rc) {
73611ea3824SHannes Reinecke rc = -ENODEV;
737a69b0800SChristoph Hellwig printk(KERN_ERR "dma_set_mask_and_coherent fail %p\n", pdev);
7387725ccfdSJing Huang goto out_release_region;
7397725ccfdSJing Huang }
7407725ccfdSJing Huang
741b3522f08SJing Huang bfad->pci_bar0_kva = pci_iomap(pdev, 0, pci_resource_len(pdev, 0));
74211189208SKrishna Gudipati bfad->pci_bar2_kva = pci_iomap(pdev, 2, pci_resource_len(pdev, 2));
7437725ccfdSJing Huang
7447725ccfdSJing Huang if (bfad->pci_bar0_kva == NULL) {
745a36c61f9SKrishna Gudipati printk(KERN_ERR "Fail to map bar0\n");
746f0f6c3a4SJing Xiangfeng rc = -ENODEV;
7477725ccfdSJing Huang goto out_release_region;
7487725ccfdSJing Huang }
7497725ccfdSJing Huang
7507725ccfdSJing Huang bfad->hal_pcidev.pci_slot = PCI_SLOT(pdev->devfn);
7517725ccfdSJing Huang bfad->hal_pcidev.pci_func = PCI_FUNC(pdev->devfn);
7527725ccfdSJing Huang bfad->hal_pcidev.pci_bar_kva = bfad->pci_bar0_kva;
7537725ccfdSJing Huang bfad->hal_pcidev.device_id = pdev->device;
7541a4d8e1bSKrishna Gudipati bfad->hal_pcidev.ssid = pdev->subsystem_device;
7557725ccfdSJing Huang bfad->pci_name = pci_name(pdev);
7567725ccfdSJing Huang
7577725ccfdSJing Huang bfad->pci_attr.vendor_id = pdev->vendor;
7587725ccfdSJing Huang bfad->pci_attr.device_id = pdev->device;
7597725ccfdSJing Huang bfad->pci_attr.ssid = pdev->subsystem_device;
7607725ccfdSJing Huang bfad->pci_attr.ssvid = pdev->subsystem_vendor;
7617725ccfdSJing Huang bfad->pci_attr.pcifn = PCI_FUNC(pdev->devfn);
7627725ccfdSJing Huang
7637725ccfdSJing Huang bfad->pcidev = pdev;
764a36c61f9SKrishna Gudipati
765a36c61f9SKrishna Gudipati /* Adjust PCIe Maximum Read Request Size */
766c0102c00SYijing Wang if (pci_is_pcie(pdev) && pcie_max_read_reqsz) {
767c0102c00SYijing Wang if (pcie_max_read_reqsz >= 128 &&
768c0102c00SYijing Wang pcie_max_read_reqsz <= 4096 &&
769c0102c00SYijing Wang is_power_of_2(pcie_max_read_reqsz)) {
770c0102c00SYijing Wang int max_rq = pcie_get_readrq(pdev);
771a36c61f9SKrishna Gudipati printk(KERN_WARNING "BFA[%s]: "
772a36c61f9SKrishna Gudipati "pcie_max_read_request_size is %d, "
773c0102c00SYijing Wang "reset to %d\n", bfad->pci_name, max_rq,
774a36c61f9SKrishna Gudipati pcie_max_read_reqsz);
775c0102c00SYijing Wang pcie_set_readrq(pdev, pcie_max_read_reqsz);
776c0102c00SYijing Wang } else {
777c0102c00SYijing Wang printk(KERN_WARNING "BFA[%s]: invalid "
778c0102c00SYijing Wang "pcie_max_read_request_size %d ignored\n",
779c0102c00SYijing Wang bfad->pci_name, pcie_max_read_reqsz);
780a36c61f9SKrishna Gudipati }
781a36c61f9SKrishna Gudipati }
782a36c61f9SKrishna Gudipati
783881c1b3cSKrishna Gudipati pci_save_state(pdev);
784881c1b3cSKrishna Gudipati
7857725ccfdSJing Huang return 0;
7867725ccfdSJing Huang
7877725ccfdSJing Huang out_release_region:
7887725ccfdSJing Huang pci_release_regions(pdev);
7897725ccfdSJing Huang out_disable_device:
7907725ccfdSJing Huang pci_disable_device(pdev);
7917725ccfdSJing Huang out:
7927725ccfdSJing Huang return rc;
7937725ccfdSJing Huang }
7947725ccfdSJing Huang
7957725ccfdSJing Huang void
bfad_pci_uninit(struct pci_dev * pdev,struct bfad_s * bfad)7967725ccfdSJing Huang bfad_pci_uninit(struct pci_dev *pdev, struct bfad_s *bfad)
7977725ccfdSJing Huang {
7987725ccfdSJing Huang pci_iounmap(pdev, bfad->pci_bar0_kva);
79911189208SKrishna Gudipati pci_iounmap(pdev, bfad->pci_bar2_kva);
8007725ccfdSJing Huang pci_release_regions(pdev);
8017725ccfdSJing Huang pci_disable_device(pdev);
8027725ccfdSJing Huang }
8037725ccfdSJing Huang
8047725ccfdSJing Huang bfa_status_t
bfad_drv_init(struct bfad_s * bfad)8057725ccfdSJing Huang bfad_drv_init(struct bfad_s *bfad)
8067725ccfdSJing Huang {
8077725ccfdSJing Huang bfa_status_t rc;
8087725ccfdSJing Huang unsigned long flags;
8097725ccfdSJing Huang
8107725ccfdSJing Huang bfad->cfg_data.rport_del_timeout = rport_del_timeout;
8117725ccfdSJing Huang bfad->cfg_data.lun_queue_depth = bfa_lun_queue_depth;
8127725ccfdSJing Huang bfad->cfg_data.io_max_sge = bfa_io_max_sge;
8137725ccfdSJing Huang bfad->cfg_data.binding_method = FCP_PWWN_BINDING;
8147725ccfdSJing Huang
8157725ccfdSJing Huang rc = bfad_hal_mem_alloc(bfad);
8167725ccfdSJing Huang if (rc != BFA_STATUS_OK) {
8177725ccfdSJing Huang printk(KERN_WARNING "bfad%d bfad_hal_mem_alloc failure\n",
8187725ccfdSJing Huang bfad->inst_no);
8197725ccfdSJing Huang printk(KERN_WARNING
82031e1d569SAnil Gurumurthy "Not enough memory to attach all QLogic BR-series HBA ports. System may need more memory.\n");
821da3e0beeSVijaya Mohan Guvva return BFA_STATUS_FAILED;
8227725ccfdSJing Huang }
8237725ccfdSJing Huang
824f7f73812SMaggie Zhang bfad->bfa.trcmod = bfad->trcmod;
825f7f73812SMaggie Zhang bfad->bfa.plog = &bfad->plog_buf;
8267725ccfdSJing Huang bfa_plog_init(&bfad->plog_buf);
8277725ccfdSJing Huang bfa_plog_str(&bfad->plog_buf, BFA_PL_MID_DRVR, BFA_PL_EID_DRIVER_START,
8287725ccfdSJing Huang 0, "Driver Attach");
8297725ccfdSJing Huang
8307725ccfdSJing Huang bfa_attach(&bfad->bfa, bfad, &bfad->ioc_cfg, &bfad->meminfo,
8317725ccfdSJing Huang &bfad->hal_pcidev);
8327725ccfdSJing Huang
833a36c61f9SKrishna Gudipati /* FCS INIT */
8347725ccfdSJing Huang spin_lock_irqsave(&bfad->bfad_lock, flags);
835f7f73812SMaggie Zhang bfad->bfa_fcs.trcmod = bfad->trcmod;
83682794a2eSKrishna Gudipati bfa_fcs_attach(&bfad->bfa_fcs, &bfad->bfa, bfad, BFA_FALSE);
837f7f73812SMaggie Zhang bfad->bfa_fcs.fdmi_enabled = fdmi_enable;
8387725ccfdSJing Huang spin_unlock_irqrestore(&bfad->bfad_lock, flags);
8397725ccfdSJing Huang
8407725ccfdSJing Huang bfad->bfad_flags |= BFAD_DRV_INIT_DONE;
841a36c61f9SKrishna Gudipati
8427725ccfdSJing Huang return BFA_STATUS_OK;
8437725ccfdSJing Huang }
8447725ccfdSJing Huang
8457725ccfdSJing Huang void
bfad_drv_uninit(struct bfad_s * bfad)8467725ccfdSJing Huang bfad_drv_uninit(struct bfad_s *bfad)
8477725ccfdSJing Huang {
848e6714324SKrishna Gudipati unsigned long flags;
849e6714324SKrishna Gudipati
850e6714324SKrishna Gudipati spin_lock_irqsave(&bfad->bfad_lock, flags);
851e6714324SKrishna Gudipati init_completion(&bfad->comp);
852f7f73812SMaggie Zhang bfa_iocfc_stop(&bfad->bfa);
853e6714324SKrishna Gudipati spin_unlock_irqrestore(&bfad->bfad_lock, flags);
854e6714324SKrishna Gudipati wait_for_completion(&bfad->comp);
855e6714324SKrishna Gudipati
8567725ccfdSJing Huang del_timer_sync(&bfad->hal_tmo);
8577725ccfdSJing Huang bfa_isr_disable(&bfad->bfa);
8587725ccfdSJing Huang bfa_detach(&bfad->bfa);
8597725ccfdSJing Huang bfad_remove_intr(bfad);
8607725ccfdSJing Huang bfad_hal_mem_release(bfad);
861e6714324SKrishna Gudipati
862e6714324SKrishna Gudipati bfad->bfad_flags &= ~BFAD_DRV_INIT_DONE;
8637725ccfdSJing Huang }
8647725ccfdSJing Huang
8657725ccfdSJing Huang void
bfad_drv_start(struct bfad_s * bfad)8667725ccfdSJing Huang bfad_drv_start(struct bfad_s *bfad)
8677725ccfdSJing Huang {
8687725ccfdSJing Huang unsigned long flags;
8697725ccfdSJing Huang
8707725ccfdSJing Huang spin_lock_irqsave(&bfad->bfad_lock, flags);
871f7f73812SMaggie Zhang bfa_iocfc_start(&bfad->bfa);
87275332a70SKrishna Gudipati bfa_fcs_pbc_vport_init(&bfad->bfa_fcs);
873f7f73812SMaggie Zhang bfa_fcs_fabric_modstart(&bfad->bfa_fcs);
8747725ccfdSJing Huang bfad->bfad_flags |= BFAD_HAL_START_DONE;
8757725ccfdSJing Huang spin_unlock_irqrestore(&bfad->bfad_lock, flags);
8767725ccfdSJing Huang
877a36c61f9SKrishna Gudipati if (bfad->im)
878a36c61f9SKrishna Gudipati flush_workqueue(bfad->im->drv_workq);
8797725ccfdSJing Huang }
8807725ccfdSJing Huang
8817725ccfdSJing Huang void
bfad_fcs_stop(struct bfad_s * bfad)882a36c61f9SKrishna Gudipati bfad_fcs_stop(struct bfad_s *bfad)
8837725ccfdSJing Huang {
8847725ccfdSJing Huang unsigned long flags;
8857725ccfdSJing Huang
8867725ccfdSJing Huang spin_lock_irqsave(&bfad->bfad_lock, flags);
8877725ccfdSJing Huang init_completion(&bfad->comp);
8887725ccfdSJing Huang bfad->pport.flags |= BFAD_PORT_DELETE;
8897725ccfdSJing Huang bfa_fcs_exit(&bfad->bfa_fcs);
8907725ccfdSJing Huang spin_unlock_irqrestore(&bfad->bfad_lock, flags);
8917725ccfdSJing Huang wait_for_completion(&bfad->comp);
8927725ccfdSJing Huang
893a36c61f9SKrishna Gudipati bfa_sm_send_event(bfad, BFAD_E_FCS_EXIT_COMP);
894a36c61f9SKrishna Gudipati }
895a36c61f9SKrishna Gudipati
896a36c61f9SKrishna Gudipati void
bfad_stop(struct bfad_s * bfad)897a36c61f9SKrishna Gudipati bfad_stop(struct bfad_s *bfad)
898a36c61f9SKrishna Gudipati {
899a36c61f9SKrishna Gudipati unsigned long flags;
900a36c61f9SKrishna Gudipati
9017725ccfdSJing Huang spin_lock_irqsave(&bfad->bfad_lock, flags);
9027725ccfdSJing Huang init_completion(&bfad->comp);
903f7f73812SMaggie Zhang bfa_iocfc_stop(&bfad->bfa);
9047725ccfdSJing Huang bfad->bfad_flags &= ~BFAD_HAL_START_DONE;
9057725ccfdSJing Huang spin_unlock_irqrestore(&bfad->bfad_lock, flags);
9067725ccfdSJing Huang wait_for_completion(&bfad->comp);
907a36c61f9SKrishna Gudipati
908a36c61f9SKrishna Gudipati bfa_sm_send_event(bfad, BFAD_E_EXIT_COMP);
9097725ccfdSJing Huang }
9107725ccfdSJing Huang
9117725ccfdSJing Huang bfa_status_t
bfad_cfg_pport(struct bfad_s * bfad,enum bfa_lport_role role)912a36c61f9SKrishna Gudipati bfad_cfg_pport(struct bfad_s *bfad, enum bfa_lport_role role)
9137725ccfdSJing Huang {
9147725ccfdSJing Huang int rc = BFA_STATUS_OK;
9157725ccfdSJing Huang
916a36c61f9SKrishna Gudipati /* Allocate scsi_host for the physical port */
917a36c61f9SKrishna Gudipati if ((supported_fc4s & BFA_LPORT_ROLE_FCP_IM) &&
918a36c61f9SKrishna Gudipati (role & BFA_LPORT_ROLE_FCP_IM)) {
9197725ccfdSJing Huang if (bfad->pport.im_port == NULL) {
9207725ccfdSJing Huang rc = BFA_STATUS_FAILED;
9217725ccfdSJing Huang goto out;
9227725ccfdSJing Huang }
9237725ccfdSJing Huang
924b504293fSJing Huang rc = bfad_im_scsi_host_alloc(bfad, bfad->pport.im_port,
925b504293fSJing Huang &bfad->pcidev->dev);
9267725ccfdSJing Huang if (rc != BFA_STATUS_OK)
9277725ccfdSJing Huang goto out;
9287725ccfdSJing Huang
929a36c61f9SKrishna Gudipati bfad->pport.roles |= BFA_LPORT_ROLE_FCP_IM;
9307725ccfdSJing Huang }
9317725ccfdSJing Huang
9327725ccfdSJing Huang bfad->bfad_flags |= BFAD_CFG_PPORT_DONE;
9337725ccfdSJing Huang
9347725ccfdSJing Huang out:
9357725ccfdSJing Huang return rc;
9367725ccfdSJing Huang }
9377725ccfdSJing Huang
9387725ccfdSJing Huang void
bfad_uncfg_pport(struct bfad_s * bfad)9397725ccfdSJing Huang bfad_uncfg_pport(struct bfad_s *bfad)
9407725ccfdSJing Huang {
941a36c61f9SKrishna Gudipati if ((supported_fc4s & BFA_LPORT_ROLE_FCP_IM) &&
942a36c61f9SKrishna Gudipati (bfad->pport.roles & BFA_LPORT_ROLE_FCP_IM)) {
9437725ccfdSJing Huang bfad_im_scsi_host_free(bfad, bfad->pport.im_port);
9447725ccfdSJing Huang bfad_im_port_clean(bfad->pport.im_port);
9457725ccfdSJing Huang kfree(bfad->pport.im_port);
946a36c61f9SKrishna Gudipati bfad->pport.roles &= ~BFA_LPORT_ROLE_FCP_IM;
9477725ccfdSJing Huang }
9487725ccfdSJing Huang
9497725ccfdSJing Huang bfad->bfad_flags &= ~BFAD_CFG_PPORT_DONE;
9507725ccfdSJing Huang }
9517725ccfdSJing Huang
952e6714324SKrishna Gudipati bfa_status_t
bfad_start_ops(struct bfad_s * bfad)953a36c61f9SKrishna Gudipati bfad_start_ops(struct bfad_s *bfad) {
954a36c61f9SKrishna Gudipati
955e6714324SKrishna Gudipati int retval;
956a36c61f9SKrishna Gudipati unsigned long flags;
957a36c61f9SKrishna Gudipati struct bfad_vport_s *vport, *vport_new;
958a36c61f9SKrishna Gudipati struct bfa_fcs_driver_info_s driver_info;
959a36c61f9SKrishna Gudipati
96061e62e21SKrishna Gudipati /* Limit min/max. xfer size to [64k-32MB] */
96161e62e21SKrishna Gudipati if (max_xfer_size < BFAD_MIN_SECTORS >> 1)
96261e62e21SKrishna Gudipati max_xfer_size = BFAD_MIN_SECTORS >> 1;
96361e62e21SKrishna Gudipati if (max_xfer_size > BFAD_MAX_SECTORS >> 1)
96461e62e21SKrishna Gudipati max_xfer_size = BFAD_MAX_SECTORS >> 1;
96561e62e21SKrishna Gudipati
966a36c61f9SKrishna Gudipati /* Fill the driver_info info to fcs*/
967a36c61f9SKrishna Gudipati memset(&driver_info, 0, sizeof(driver_info));
968973464fdSAzeem Shaikh strscpy(driver_info.version, BFAD_DRIVER_VERSION,
9698c5a50e8SArnd Bergmann sizeof(driver_info.version));
970a36c61f9SKrishna Gudipati if (host_name)
971973464fdSAzeem Shaikh strscpy(driver_info.host_machine_name, host_name,
9728c5a50e8SArnd Bergmann sizeof(driver_info.host_machine_name));
973a36c61f9SKrishna Gudipati if (os_name)
974973464fdSAzeem Shaikh strscpy(driver_info.host_os_name, os_name,
9758c5a50e8SArnd Bergmann sizeof(driver_info.host_os_name));
976a36c61f9SKrishna Gudipati if (os_patch)
977973464fdSAzeem Shaikh strscpy(driver_info.host_os_patch, os_patch,
9788c5a50e8SArnd Bergmann sizeof(driver_info.host_os_patch));
979a36c61f9SKrishna Gudipati
980973464fdSAzeem Shaikh strscpy(driver_info.os_device_name, bfad->pci_name,
9818c5a50e8SArnd Bergmann sizeof(driver_info.os_device_name));
982a36c61f9SKrishna Gudipati
98375332a70SKrishna Gudipati /* FCS driver info init */
984a36c61f9SKrishna Gudipati spin_lock_irqsave(&bfad->bfad_lock, flags);
985a36c61f9SKrishna Gudipati bfa_fcs_driver_info_init(&bfad->bfa_fcs, &driver_info);
986da3e0beeSVijaya Mohan Guvva
987da3e0beeSVijaya Mohan Guvva if (bfad->bfad_flags & BFAD_CFG_PPORT_DONE)
988da3e0beeSVijaya Mohan Guvva bfa_fcs_update_cfg(&bfad->bfa_fcs);
989da3e0beeSVijaya Mohan Guvva else
990da3e0beeSVijaya Mohan Guvva bfa_fcs_init(&bfad->bfa_fcs);
991da3e0beeSVijaya Mohan Guvva
992a36c61f9SKrishna Gudipati spin_unlock_irqrestore(&bfad->bfad_lock, flags);
993e6714324SKrishna Gudipati
994da3e0beeSVijaya Mohan Guvva if (!(bfad->bfad_flags & BFAD_CFG_PPORT_DONE)) {
995da3e0beeSVijaya Mohan Guvva retval = bfad_cfg_pport(bfad, BFA_LPORT_ROLE_FCP_IM);
996da3e0beeSVijaya Mohan Guvva if (retval != BFA_STATUS_OK)
997da3e0beeSVijaya Mohan Guvva return BFA_STATUS_FAILED;
998da3e0beeSVijaya Mohan Guvva }
99975332a70SKrishna Gudipati
100075332a70SKrishna Gudipati /* Setup fc host fixed attribute if the lk supports */
100175332a70SKrishna Gudipati bfad_fc_host_init(bfad->pport.im_port);
1002e6714324SKrishna Gudipati
1003a36c61f9SKrishna Gudipati /* BFAD level FC4 IM specific resource allocation */
1004a36c61f9SKrishna Gudipati retval = bfad_im_probe(bfad);
1005a36c61f9SKrishna Gudipati if (retval != BFA_STATUS_OK) {
1006a36c61f9SKrishna Gudipati printk(KERN_WARNING "bfad_im_probe failed\n");
1007a36c61f9SKrishna Gudipati if (bfa_sm_cmp_state(bfad, bfad_sm_initializing))
1008a36c61f9SKrishna Gudipati bfa_sm_set_state(bfad, bfad_sm_failed);
1009a36c61f9SKrishna Gudipati return BFA_STATUS_FAILED;
1010a36c61f9SKrishna Gudipati } else
1011a36c61f9SKrishna Gudipati bfad->bfad_flags |= BFAD_FC4_PROBE_DONE;
1012a36c61f9SKrishna Gudipati
1013e6714324SKrishna Gudipati bfad_drv_start(bfad);
1014e6714324SKrishna Gudipati
1015a36c61f9SKrishna Gudipati /* Complete pbc vport create */
1016a36c61f9SKrishna Gudipati list_for_each_entry_safe(vport, vport_new, &bfad->pbc_vport_list,
1017d9883548SJing Huang list_entry) {
1018d9883548SJing Huang struct fc_vport_identifiers vid;
1019d9883548SJing Huang struct fc_vport *fc_vport;
1020a36c61f9SKrishna Gudipati char pwwn_buf[BFA_STRING_32];
1021d9883548SJing Huang
1022d9883548SJing Huang memset(&vid, 0, sizeof(vid));
1023d9883548SJing Huang vid.roles = FC_PORT_ROLE_FCP_INITIATOR;
1024d9883548SJing Huang vid.vport_type = FC_PORTTYPE_NPIV;
1025d9883548SJing Huang vid.disable = false;
1026a36c61f9SKrishna Gudipati vid.node_name = wwn_to_u64((u8 *)
1027a36c61f9SKrishna Gudipati (&((vport->fcs_vport).lport.port_cfg.nwwn)));
1028a36c61f9SKrishna Gudipati vid.port_name = wwn_to_u64((u8 *)
1029a36c61f9SKrishna Gudipati (&((vport->fcs_vport).lport.port_cfg.pwwn)));
1030d9883548SJing Huang fc_vport = fc_vport_create(bfad->pport.im_port->shost, 0, &vid);
1031a36c61f9SKrishna Gudipati if (!fc_vport) {
1032a36c61f9SKrishna Gudipati wwn2str(pwwn_buf, vid.port_name);
1033d9883548SJing Huang printk(KERN_WARNING "bfad%d: failed to create pbc vport"
1034a36c61f9SKrishna Gudipati " %s\n", bfad->inst_no, pwwn_buf);
1035a36c61f9SKrishna Gudipati }
1036a36c61f9SKrishna Gudipati list_del(&vport->list_entry);
1037a36c61f9SKrishna Gudipati kfree(vport);
1038d9883548SJing Huang }
1039d9883548SJing Huang
1040e6714324SKrishna Gudipati /*
1041e6714324SKrishna Gudipati * If bfa_linkup_delay is set to -1 default; try to retrive the
1042f16a1750SMaggie Zhang * value using the bfad_get_linkup_delay(); else use the
1043e6714324SKrishna Gudipati * passed in module param value as the bfa_linkup_delay.
1044e6714324SKrishna Gudipati */
1045e6714324SKrishna Gudipati if (bfa_linkup_delay < 0) {
1046f16a1750SMaggie Zhang bfa_linkup_delay = bfad_get_linkup_delay(bfad);
1047f16a1750SMaggie Zhang bfad_rport_online_wait(bfad);
1048e6714324SKrishna Gudipati bfa_linkup_delay = -1;
1049a36c61f9SKrishna Gudipati } else
1050f16a1750SMaggie Zhang bfad_rport_online_wait(bfad);
1051e6714324SKrishna Gudipati
105288166242SJing Huang BFA_LOG(KERN_INFO, bfad, bfa_log_level, "bfa device claimed\n");
1053e6714324SKrishna Gudipati
1054e6714324SKrishna Gudipati return BFA_STATUS_OK;
1055e6714324SKrishna Gudipati }
1056e6714324SKrishna Gudipati
1057e6714324SKrishna Gudipati int
bfad_worker(void * ptr)1058e6714324SKrishna Gudipati bfad_worker(void *ptr)
1059e6714324SKrishna Gudipati {
10608f7d3f0fSJiri Slaby struct bfad_s *bfad = ptr;
1061e6714324SKrishna Gudipati unsigned long flags;
1062e6714324SKrishna Gudipati
10638f7d3f0fSJiri Slaby if (kthread_should_stop())
10648f7d3f0fSJiri Slaby return 0;
1065e6714324SKrishna Gudipati
1066a36c61f9SKrishna Gudipati /* Send event BFAD_E_INIT_SUCCESS */
1067a36c61f9SKrishna Gudipati bfa_sm_send_event(bfad, BFAD_E_INIT_SUCCESS);
1068e6714324SKrishna Gudipati
1069e6714324SKrishna Gudipati spin_lock_irqsave(&bfad->bfad_lock, flags);
1070e6714324SKrishna Gudipati bfad->bfad_tsk = NULL;
1071e6714324SKrishna Gudipati spin_unlock_irqrestore(&bfad->bfad_lock, flags);
1072e6714324SKrishna Gudipati
1073e6714324SKrishna Gudipati return 0;
1074e6714324SKrishna Gudipati }
1075e6714324SKrishna Gudipati
10765fbe25c7SJing Huang /*
1077a36c61f9SKrishna Gudipati * BFA driver interrupt functions
10787725ccfdSJing Huang */
1079a36c61f9SKrishna Gudipati irqreturn_t
bfad_intx(int irq,void * dev_id)1080a36c61f9SKrishna Gudipati bfad_intx(int irq, void *dev_id)
1081a36c61f9SKrishna Gudipati {
1082a36c61f9SKrishna Gudipati struct bfad_s *bfad = dev_id;
1083a36c61f9SKrishna Gudipati struct list_head doneq;
1084a36c61f9SKrishna Gudipati unsigned long flags;
1085a36c61f9SKrishna Gudipati bfa_boolean_t rc;
1086a36c61f9SKrishna Gudipati
1087a36c61f9SKrishna Gudipati spin_lock_irqsave(&bfad->bfad_lock, flags);
1088a36c61f9SKrishna Gudipati rc = bfa_intx(&bfad->bfa);
1089a36c61f9SKrishna Gudipati if (!rc) {
1090a36c61f9SKrishna Gudipati spin_unlock_irqrestore(&bfad->bfad_lock, flags);
1091a36c61f9SKrishna Gudipati return IRQ_NONE;
1092a36c61f9SKrishna Gudipati }
1093a36c61f9SKrishna Gudipati
1094a36c61f9SKrishna Gudipati bfa_comp_deq(&bfad->bfa, &doneq);
1095a36c61f9SKrishna Gudipati spin_unlock_irqrestore(&bfad->bfad_lock, flags);
1096a36c61f9SKrishna Gudipati
1097a36c61f9SKrishna Gudipati if (!list_empty(&doneq)) {
1098a36c61f9SKrishna Gudipati bfa_comp_process(&bfad->bfa, &doneq);
1099a36c61f9SKrishna Gudipati
1100a36c61f9SKrishna Gudipati spin_lock_irqsave(&bfad->bfad_lock, flags);
1101a36c61f9SKrishna Gudipati bfa_comp_free(&bfad->bfa, &doneq);
1102a36c61f9SKrishna Gudipati spin_unlock_irqrestore(&bfad->bfad_lock, flags);
1103a36c61f9SKrishna Gudipati }
1104a36c61f9SKrishna Gudipati
1105a36c61f9SKrishna Gudipati return IRQ_HANDLED;
1106a36c61f9SKrishna Gudipati
1107a36c61f9SKrishna Gudipati }
1108a36c61f9SKrishna Gudipati
1109a36c61f9SKrishna Gudipati static irqreturn_t
bfad_msix(int irq,void * dev_id)1110a36c61f9SKrishna Gudipati bfad_msix(int irq, void *dev_id)
1111a36c61f9SKrishna Gudipati {
1112a36c61f9SKrishna Gudipati struct bfad_msix_s *vec = dev_id;
1113a36c61f9SKrishna Gudipati struct bfad_s *bfad = vec->bfad;
1114a36c61f9SKrishna Gudipati struct list_head doneq;
1115a36c61f9SKrishna Gudipati unsigned long flags;
1116a36c61f9SKrishna Gudipati
1117a36c61f9SKrishna Gudipati spin_lock_irqsave(&bfad->bfad_lock, flags);
1118a36c61f9SKrishna Gudipati
1119a36c61f9SKrishna Gudipati bfa_msix(&bfad->bfa, vec->msix.entry);
1120a36c61f9SKrishna Gudipati bfa_comp_deq(&bfad->bfa, &doneq);
1121a36c61f9SKrishna Gudipati spin_unlock_irqrestore(&bfad->bfad_lock, flags);
1122a36c61f9SKrishna Gudipati
1123a36c61f9SKrishna Gudipati if (!list_empty(&doneq)) {
1124a36c61f9SKrishna Gudipati bfa_comp_process(&bfad->bfa, &doneq);
1125a36c61f9SKrishna Gudipati
1126a36c61f9SKrishna Gudipati spin_lock_irqsave(&bfad->bfad_lock, flags);
1127a36c61f9SKrishna Gudipati bfa_comp_free(&bfad->bfa, &doneq);
1128a36c61f9SKrishna Gudipati spin_unlock_irqrestore(&bfad->bfad_lock, flags);
1129a36c61f9SKrishna Gudipati }
1130a36c61f9SKrishna Gudipati
1131a36c61f9SKrishna Gudipati return IRQ_HANDLED;
1132a36c61f9SKrishna Gudipati }
1133a36c61f9SKrishna Gudipati
11345fbe25c7SJing Huang /*
1135a36c61f9SKrishna Gudipati * Initialize the MSIX entry table.
1136a36c61f9SKrishna Gudipati */
1137a36c61f9SKrishna Gudipati static void
bfad_init_msix_entry(struct bfad_s * bfad,struct msix_entry * msix_entries,int mask,int max_bit)1138a36c61f9SKrishna Gudipati bfad_init_msix_entry(struct bfad_s *bfad, struct msix_entry *msix_entries,
1139a36c61f9SKrishna Gudipati int mask, int max_bit)
1140a36c61f9SKrishna Gudipati {
1141a36c61f9SKrishna Gudipati int i;
1142a36c61f9SKrishna Gudipati int match = 0x00000001;
1143a36c61f9SKrishna Gudipati
1144a36c61f9SKrishna Gudipati for (i = 0, bfad->nvec = 0; i < MAX_MSIX_ENTRY; i++) {
1145a36c61f9SKrishna Gudipati if (mask & match) {
1146a36c61f9SKrishna Gudipati bfad->msix_tab[bfad->nvec].msix.entry = i;
1147a36c61f9SKrishna Gudipati bfad->msix_tab[bfad->nvec].bfad = bfad;
1148a36c61f9SKrishna Gudipati msix_entries[bfad->nvec].entry = i;
1149a36c61f9SKrishna Gudipati bfad->nvec++;
1150a36c61f9SKrishna Gudipati }
1151a36c61f9SKrishna Gudipati
1152a36c61f9SKrishna Gudipati match <<= 1;
1153a36c61f9SKrishna Gudipati }
1154a36c61f9SKrishna Gudipati
1155a36c61f9SKrishna Gudipati }
1156a36c61f9SKrishna Gudipati
1157a36c61f9SKrishna Gudipati int
bfad_install_msix_handler(struct bfad_s * bfad)1158a36c61f9SKrishna Gudipati bfad_install_msix_handler(struct bfad_s *bfad)
1159a36c61f9SKrishna Gudipati {
1160a36c61f9SKrishna Gudipati int i, error = 0;
1161a36c61f9SKrishna Gudipati
1162a36c61f9SKrishna Gudipati for (i = 0; i < bfad->nvec; i++) {
1163a36c61f9SKrishna Gudipati sprintf(bfad->msix_tab[i].name, "bfa-%s-%s",
1164a36c61f9SKrishna Gudipati bfad->pci_name,
116511189208SKrishna Gudipati ((bfa_asic_id_cb(bfad->hal_pcidev.device_id)) ?
116611189208SKrishna Gudipati msix_name_cb[i] : msix_name_ct[i]));
1167a36c61f9SKrishna Gudipati
1168a36c61f9SKrishna Gudipati error = request_irq(bfad->msix_tab[i].msix.vector,
1169a36c61f9SKrishna Gudipati (irq_handler_t) bfad_msix, 0,
1170a36c61f9SKrishna Gudipati bfad->msix_tab[i].name, &bfad->msix_tab[i]);
1171a36c61f9SKrishna Gudipati bfa_trc(bfad, i);
1172a36c61f9SKrishna Gudipati bfa_trc(bfad, bfad->msix_tab[i].msix.vector);
1173a36c61f9SKrishna Gudipati if (error) {
1174a36c61f9SKrishna Gudipati int j;
1175a36c61f9SKrishna Gudipati
1176a36c61f9SKrishna Gudipati for (j = 0; j < i; j++)
1177a36c61f9SKrishna Gudipati free_irq(bfad->msix_tab[j].msix.vector,
1178a36c61f9SKrishna Gudipati &bfad->msix_tab[j]);
1179a36c61f9SKrishna Gudipati
118061e62e21SKrishna Gudipati bfad->bfad_flags &= ~BFAD_MSIX_ON;
118161e62e21SKrishna Gudipati pci_disable_msix(bfad->pcidev);
118261e62e21SKrishna Gudipati
1183a36c61f9SKrishna Gudipati return 1;
1184a36c61f9SKrishna Gudipati }
1185a36c61f9SKrishna Gudipati }
1186a36c61f9SKrishna Gudipati
1187a36c61f9SKrishna Gudipati return 0;
1188a36c61f9SKrishna Gudipati }
1189a36c61f9SKrishna Gudipati
11905fbe25c7SJing Huang /*
1191a36c61f9SKrishna Gudipati * Setup MSIX based interrupt.
1192a36c61f9SKrishna Gudipati */
1193a36c61f9SKrishna Gudipati int
bfad_setup_intr(struct bfad_s * bfad)1194a36c61f9SKrishna Gudipati bfad_setup_intr(struct bfad_s *bfad)
1195a36c61f9SKrishna Gudipati {
11968cb7f63dSAlexander Gordeev int error;
1197a36c61f9SKrishna Gudipati u32 mask = 0, i, num_bit = 0, max_bit = 0;
1198a36c61f9SKrishna Gudipati struct msix_entry msix_entries[MAX_MSIX_ENTRY];
1199a36c61f9SKrishna Gudipati struct pci_dev *pdev = bfad->pcidev;
120010a07379SKrishna Gudipati u16 reg;
1201a36c61f9SKrishna Gudipati
1202a36c61f9SKrishna Gudipati /* Call BFA to get the msix map for this PCI function. */
1203a36c61f9SKrishna Gudipati bfa_msix_getvecs(&bfad->bfa, &mask, &num_bit, &max_bit);
1204a36c61f9SKrishna Gudipati
1205a36c61f9SKrishna Gudipati /* Set up the msix entry table */
1206a36c61f9SKrishna Gudipati bfad_init_msix_entry(bfad, msix_entries, mask, max_bit);
1207a36c61f9SKrishna Gudipati
120811189208SKrishna Gudipati if ((bfa_asic_id_ctc(pdev->device) && !msix_disable_ct) ||
120911189208SKrishna Gudipati (bfa_asic_id_cb(pdev->device) && !msix_disable_cb)) {
1210a36c61f9SKrishna Gudipati
1211b427d00fSAlexander Gordeev error = pci_enable_msix_exact(bfad->pcidev,
1212b427d00fSAlexander Gordeev msix_entries, bfad->nvec);
1213881c1b3cSKrishna Gudipati /* In CT1 & CT2, try to allocate just one vector */
1214b427d00fSAlexander Gordeev if (error == -ENOSPC && bfa_asic_id_ctc(pdev->device)) {
1215881c1b3cSKrishna Gudipati printk(KERN_WARNING "bfa %s: trying one msix "
1216881c1b3cSKrishna Gudipati "vector failed to allocate %d[%d]\n",
1217881c1b3cSKrishna Gudipati bfad->pci_name, bfad->nvec, error);
1218881c1b3cSKrishna Gudipati bfad->nvec = 1;
1219b427d00fSAlexander Gordeev error = pci_enable_msix_exact(bfad->pcidev,
1220b427d00fSAlexander Gordeev msix_entries, 1);
1221881c1b3cSKrishna Gudipati }
1222881c1b3cSKrishna Gudipati
1223881c1b3cSKrishna Gudipati if (error) {
1224a36c61f9SKrishna Gudipati printk(KERN_WARNING "bfad%d: "
1225b427d00fSAlexander Gordeev "pci_enable_msix_exact failed (%d), "
1226881c1b3cSKrishna Gudipati "use line based.\n",
1227881c1b3cSKrishna Gudipati bfad->inst_no, error);
1228a36c61f9SKrishna Gudipati goto line_based;
1229a36c61f9SKrishna Gudipati }
1230a36c61f9SKrishna Gudipati
123110a07379SKrishna Gudipati /* Disable INTX in MSI-X mode */
123210a07379SKrishna Gudipati pci_read_config_word(pdev, PCI_COMMAND, ®);
123310a07379SKrishna Gudipati
123410a07379SKrishna Gudipati if (!(reg & PCI_COMMAND_INTX_DISABLE))
123510a07379SKrishna Gudipati pci_write_config_word(pdev, PCI_COMMAND,
123610a07379SKrishna Gudipati reg | PCI_COMMAND_INTX_DISABLE);
123710a07379SKrishna Gudipati
1238a36c61f9SKrishna Gudipati /* Save the vectors */
1239a36c61f9SKrishna Gudipati for (i = 0; i < bfad->nvec; i++) {
1240a36c61f9SKrishna Gudipati bfa_trc(bfad, msix_entries[i].vector);
1241a36c61f9SKrishna Gudipati bfad->msix_tab[i].msix.vector = msix_entries[i].vector;
1242a36c61f9SKrishna Gudipati }
1243a36c61f9SKrishna Gudipati
1244a36c61f9SKrishna Gudipati bfa_msix_init(&bfad->bfa, bfad->nvec);
1245a36c61f9SKrishna Gudipati
1246a36c61f9SKrishna Gudipati bfad->bfad_flags |= BFAD_MSIX_ON;
1247a36c61f9SKrishna Gudipati
12488cb7f63dSAlexander Gordeev return 0;
1249a36c61f9SKrishna Gudipati }
1250a36c61f9SKrishna Gudipati
1251a36c61f9SKrishna Gudipati line_based:
12528cb7f63dSAlexander Gordeev error = request_irq(bfad->pcidev->irq, (irq_handler_t)bfad_intx,
12538cb7f63dSAlexander Gordeev BFAD_IRQ_FLAGS, BFAD_DRIVER_NAME, bfad);
12548cb7f63dSAlexander Gordeev if (error)
12558cb7f63dSAlexander Gordeev return error;
12568cb7f63dSAlexander Gordeev
125761e62e21SKrishna Gudipati bfad->bfad_flags |= BFAD_INTX_ON;
1258a36c61f9SKrishna Gudipati
12598cb7f63dSAlexander Gordeev return 0;
1260a36c61f9SKrishna Gudipati }
1261a36c61f9SKrishna Gudipati
1262a36c61f9SKrishna Gudipati void
bfad_remove_intr(struct bfad_s * bfad)1263a36c61f9SKrishna Gudipati bfad_remove_intr(struct bfad_s *bfad)
1264a36c61f9SKrishna Gudipati {
1265a36c61f9SKrishna Gudipati int i;
1266a36c61f9SKrishna Gudipati
1267a36c61f9SKrishna Gudipati if (bfad->bfad_flags & BFAD_MSIX_ON) {
1268a36c61f9SKrishna Gudipati for (i = 0; i < bfad->nvec; i++)
1269a36c61f9SKrishna Gudipati free_irq(bfad->msix_tab[i].msix.vector,
1270a36c61f9SKrishna Gudipati &bfad->msix_tab[i]);
1271a36c61f9SKrishna Gudipati
1272a36c61f9SKrishna Gudipati pci_disable_msix(bfad->pcidev);
1273a36c61f9SKrishna Gudipati bfad->bfad_flags &= ~BFAD_MSIX_ON;
127461e62e21SKrishna Gudipati } else if (bfad->bfad_flags & BFAD_INTX_ON) {
1275a36c61f9SKrishna Gudipati free_irq(bfad->pcidev->irq, bfad);
1276a36c61f9SKrishna Gudipati }
1277a36c61f9SKrishna Gudipati }
12787725ccfdSJing Huang
12795fbe25c7SJing Huang /*
12807725ccfdSJing Huang * PCI probe entry.
12817725ccfdSJing Huang */
12827725ccfdSJing Huang int
bfad_pci_probe(struct pci_dev * pdev,const struct pci_device_id * pid)12837725ccfdSJing Huang bfad_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid)
12847725ccfdSJing Huang {
12857725ccfdSJing Huang struct bfad_s *bfad;
12867826f304SKrishna Gudipati int error = -ENODEV, retval, i;
12877725ccfdSJing Huang
1288a36c61f9SKrishna Gudipati /* For single port cards - only claim function 0 */
12898b070b4aSKrishna Gudipati if ((pdev->device == BFA_PCI_DEVICE_ID_FC_8G1P) &&
1290a36c61f9SKrishna Gudipati (PCI_FUNC(pdev->devfn) != 0))
12917725ccfdSJing Huang return -ENODEV;
12927725ccfdSJing Huang
12937725ccfdSJing Huang bfad = kzalloc(sizeof(struct bfad_s), GFP_KERNEL);
12947725ccfdSJing Huang if (!bfad) {
12957725ccfdSJing Huang error = -ENOMEM;
12967725ccfdSJing Huang goto out;
12977725ccfdSJing Huang }
12987725ccfdSJing Huang
12997725ccfdSJing Huang bfad->trcmod = kzalloc(sizeof(struct bfa_trc_mod_s), GFP_KERNEL);
13007725ccfdSJing Huang if (!bfad->trcmod) {
13017725ccfdSJing Huang printk(KERN_WARNING "Error alloc trace buffer!\n");
13027725ccfdSJing Huang error = -ENOMEM;
13037725ccfdSJing Huang goto out_alloc_trace_failure;
13047725ccfdSJing Huang }
13057725ccfdSJing Huang
1306a36c61f9SKrishna Gudipati /* TRACE INIT */
13077725ccfdSJing Huang bfa_trc_init(bfad->trcmod);
13087725ccfdSJing Huang bfa_trc(bfad, bfad_inst);
13097725ccfdSJing Huang
13107826f304SKrishna Gudipati /* AEN INIT */
13117826f304SKrishna Gudipati INIT_LIST_HEAD(&bfad->free_aen_q);
13127826f304SKrishna Gudipati INIT_LIST_HEAD(&bfad->active_aen_q);
13137826f304SKrishna Gudipati for (i = 0; i < BFA_AEN_MAX_ENTRY; i++)
13147826f304SKrishna Gudipati list_add_tail(&bfad->aen_list[i].qe, &bfad->free_aen_q);
13157826f304SKrishna Gudipati
13167725ccfdSJing Huang if (!(bfad_load_fwimg(pdev))) {
13177725ccfdSJing Huang kfree(bfad->trcmod);
13187725ccfdSJing Huang goto out_alloc_trace_failure;
13197725ccfdSJing Huang }
13207725ccfdSJing Huang
13217725ccfdSJing Huang retval = bfad_pci_init(pdev, bfad);
13227725ccfdSJing Huang if (retval) {
13237725ccfdSJing Huang printk(KERN_WARNING "bfad_pci_init failure!\n");
13247725ccfdSJing Huang error = retval;
13257725ccfdSJing Huang goto out_pci_init_failure;
13267725ccfdSJing Huang }
13277725ccfdSJing Huang
13287725ccfdSJing Huang mutex_lock(&bfad_mutex);
13297725ccfdSJing Huang bfad->inst_no = bfad_inst++;
13307725ccfdSJing Huang list_add_tail(&bfad->list_entry, &bfad_list);
13317725ccfdSJing Huang mutex_unlock(&bfad_mutex);
13327725ccfdSJing Huang
1333a36c61f9SKrishna Gudipati /* Initializing the state machine: State set to uninit */
1334a36c61f9SKrishna Gudipati bfa_sm_set_state(bfad, bfad_sm_uninit);
1335a36c61f9SKrishna Gudipati
13367725ccfdSJing Huang spin_lock_init(&bfad->bfad_lock);
13370b1017aaSKyle McMartin spin_lock_init(&bfad->bfad_aen_spinlock);
13380b1017aaSKyle McMartin
13397725ccfdSJing Huang pci_set_drvdata(pdev, bfad);
13407725ccfdSJing Huang
13417725ccfdSJing Huang bfad->ref_count = 0;
13427725ccfdSJing Huang bfad->pport.bfad = bfad;
1343a36c61f9SKrishna Gudipati INIT_LIST_HEAD(&bfad->pbc_vport_list);
13445b7db7afSKrishna Gudipati INIT_LIST_HEAD(&bfad->vport_list);
1345e6714324SKrishna Gudipati
13467c38c05bSKrishna Gudipati /* Setup the debugfs node for this bfad */
13477c38c05bSKrishna Gudipati if (bfa_debugfs_enable)
13487c38c05bSKrishna Gudipati bfad_debugfs_init(&bfad->pport);
13497c38c05bSKrishna Gudipati
13507725ccfdSJing Huang retval = bfad_drv_init(bfad);
13517725ccfdSJing Huang if (retval != BFA_STATUS_OK)
13527725ccfdSJing Huang goto out_drv_init_failure;
13537725ccfdSJing Huang
1354a36c61f9SKrishna Gudipati bfa_sm_send_event(bfad, BFAD_E_CREATE);
13557725ccfdSJing Huang
1356a36c61f9SKrishna Gudipati if (bfa_sm_cmp_state(bfad, bfad_sm_uninit))
1357a36c61f9SKrishna Gudipati goto out_bfad_sm_failure;
13587725ccfdSJing Huang
13597725ccfdSJing Huang return 0;
13607725ccfdSJing Huang
1361a36c61f9SKrishna Gudipati out_bfad_sm_failure:
1362a36c61f9SKrishna Gudipati bfad_hal_mem_release(bfad);
13637725ccfdSJing Huang out_drv_init_failure:
13647c38c05bSKrishna Gudipati /* Remove the debugfs node for this bfad */
13657c38c05bSKrishna Gudipati kfree(bfad->regdata);
13667c38c05bSKrishna Gudipati bfad_debugfs_exit(&bfad->pport);
13677725ccfdSJing Huang mutex_lock(&bfad_mutex);
13687725ccfdSJing Huang bfad_inst--;
13697725ccfdSJing Huang list_del(&bfad->list_entry);
13707725ccfdSJing Huang mutex_unlock(&bfad_mutex);
13717725ccfdSJing Huang bfad_pci_uninit(pdev, bfad);
13727725ccfdSJing Huang out_pci_init_failure:
13737725ccfdSJing Huang kfree(bfad->trcmod);
13747725ccfdSJing Huang out_alloc_trace_failure:
13757725ccfdSJing Huang kfree(bfad);
13767725ccfdSJing Huang out:
13777725ccfdSJing Huang return error;
13787725ccfdSJing Huang }
13797725ccfdSJing Huang
13805fbe25c7SJing Huang /*
13817725ccfdSJing Huang * PCI remove entry.
13827725ccfdSJing Huang */
13837725ccfdSJing Huang void
bfad_pci_remove(struct pci_dev * pdev)13847725ccfdSJing Huang bfad_pci_remove(struct pci_dev *pdev)
13857725ccfdSJing Huang {
13867725ccfdSJing Huang struct bfad_s *bfad = pci_get_drvdata(pdev);
13877725ccfdSJing Huang unsigned long flags;
13887725ccfdSJing Huang
13897725ccfdSJing Huang bfa_trc(bfad, bfad->inst_no);
13907725ccfdSJing Huang
1391e6714324SKrishna Gudipati spin_lock_irqsave(&bfad->bfad_lock, flags);
1392a36c61f9SKrishna Gudipati if (bfad->bfad_tsk != NULL) {
1393a36c61f9SKrishna Gudipati spin_unlock_irqrestore(&bfad->bfad_lock, flags);
1394e6714324SKrishna Gudipati kthread_stop(bfad->bfad_tsk);
1395a36c61f9SKrishna Gudipati } else {
1396e6714324SKrishna Gudipati spin_unlock_irqrestore(&bfad->bfad_lock, flags);
13977725ccfdSJing Huang }
13987725ccfdSJing Huang
1399a36c61f9SKrishna Gudipati /* Send Event BFAD_E_STOP */
1400a36c61f9SKrishna Gudipati bfa_sm_send_event(bfad, BFAD_E_STOP);
14017725ccfdSJing Huang
1402a36c61f9SKrishna Gudipati /* Driver detach and dealloc mem */
14037725ccfdSJing Huang spin_lock_irqsave(&bfad->bfad_lock, flags);
14047725ccfdSJing Huang bfa_detach(&bfad->bfa);
14057725ccfdSJing Huang spin_unlock_irqrestore(&bfad->bfad_lock, flags);
14067725ccfdSJing Huang bfad_hal_mem_release(bfad);
14077725ccfdSJing Huang
14087c38c05bSKrishna Gudipati /* Remove the debugfs node for this bfad */
14097c38c05bSKrishna Gudipati kfree(bfad->regdata);
14107c38c05bSKrishna Gudipati bfad_debugfs_exit(&bfad->pport);
14117c38c05bSKrishna Gudipati
1412a36c61f9SKrishna Gudipati /* Cleaning the BFAD instance */
14137725ccfdSJing Huang mutex_lock(&bfad_mutex);
14147725ccfdSJing Huang bfad_inst--;
14157725ccfdSJing Huang list_del(&bfad->list_entry);
14167725ccfdSJing Huang mutex_unlock(&bfad_mutex);
14177725ccfdSJing Huang bfad_pci_uninit(pdev, bfad);
14187725ccfdSJing Huang
14197725ccfdSJing Huang kfree(bfad->trcmod);
14207725ccfdSJing Huang kfree(bfad);
14217725ccfdSJing Huang }
14227725ccfdSJing Huang
1423881c1b3cSKrishna Gudipati /*
1424881c1b3cSKrishna Gudipati * PCI Error Recovery entry, error detected.
1425881c1b3cSKrishna Gudipati */
1426881c1b3cSKrishna Gudipati static pci_ers_result_t
bfad_pci_error_detected(struct pci_dev * pdev,pci_channel_state_t state)1427881c1b3cSKrishna Gudipati bfad_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
1428881c1b3cSKrishna Gudipati {
1429881c1b3cSKrishna Gudipati struct bfad_s *bfad = pci_get_drvdata(pdev);
1430881c1b3cSKrishna Gudipati unsigned long flags;
1431881c1b3cSKrishna Gudipati pci_ers_result_t ret = PCI_ERS_RESULT_NONE;
1432881c1b3cSKrishna Gudipati
1433881c1b3cSKrishna Gudipati dev_printk(KERN_ERR, &pdev->dev,
1434881c1b3cSKrishna Gudipati "error detected state: %d - flags: 0x%x\n",
1435881c1b3cSKrishna Gudipati state, bfad->bfad_flags);
1436881c1b3cSKrishna Gudipati
1437881c1b3cSKrishna Gudipati switch (state) {
1438881c1b3cSKrishna Gudipati case pci_channel_io_normal: /* non-fatal error */
1439881c1b3cSKrishna Gudipati spin_lock_irqsave(&bfad->bfad_lock, flags);
1440881c1b3cSKrishna Gudipati bfad->bfad_flags &= ~BFAD_EEH_BUSY;
1441881c1b3cSKrishna Gudipati /* Suspend/fail all bfa operations */
1442881c1b3cSKrishna Gudipati bfa_ioc_suspend(&bfad->bfa.ioc);
1443881c1b3cSKrishna Gudipati spin_unlock_irqrestore(&bfad->bfad_lock, flags);
1444881c1b3cSKrishna Gudipati del_timer_sync(&bfad->hal_tmo);
1445881c1b3cSKrishna Gudipati ret = PCI_ERS_RESULT_CAN_RECOVER;
1446881c1b3cSKrishna Gudipati break;
1447881c1b3cSKrishna Gudipati case pci_channel_io_frozen: /* fatal error */
1448881c1b3cSKrishna Gudipati init_completion(&bfad->comp);
1449881c1b3cSKrishna Gudipati spin_lock_irqsave(&bfad->bfad_lock, flags);
1450881c1b3cSKrishna Gudipati bfad->bfad_flags |= BFAD_EEH_BUSY;
1451881c1b3cSKrishna Gudipati /* Suspend/fail all bfa operations */
1452881c1b3cSKrishna Gudipati bfa_ioc_suspend(&bfad->bfa.ioc);
1453881c1b3cSKrishna Gudipati bfa_fcs_stop(&bfad->bfa_fcs);
1454881c1b3cSKrishna Gudipati spin_unlock_irqrestore(&bfad->bfad_lock, flags);
1455881c1b3cSKrishna Gudipati wait_for_completion(&bfad->comp);
1456881c1b3cSKrishna Gudipati
1457881c1b3cSKrishna Gudipati bfad_remove_intr(bfad);
1458881c1b3cSKrishna Gudipati del_timer_sync(&bfad->hal_tmo);
1459881c1b3cSKrishna Gudipati pci_disable_device(pdev);
1460881c1b3cSKrishna Gudipati ret = PCI_ERS_RESULT_NEED_RESET;
1461881c1b3cSKrishna Gudipati break;
1462881c1b3cSKrishna Gudipati case pci_channel_io_perm_failure: /* PCI Card is DEAD */
1463881c1b3cSKrishna Gudipati spin_lock_irqsave(&bfad->bfad_lock, flags);
1464881c1b3cSKrishna Gudipati bfad->bfad_flags |= BFAD_EEH_BUSY |
1465881c1b3cSKrishna Gudipati BFAD_EEH_PCI_CHANNEL_IO_PERM_FAILURE;
1466881c1b3cSKrishna Gudipati spin_unlock_irqrestore(&bfad->bfad_lock, flags);
1467881c1b3cSKrishna Gudipati
1468881c1b3cSKrishna Gudipati /* If the error_detected handler is called with the reason
1469881c1b3cSKrishna Gudipati * pci_channel_io_perm_failure - it will subsequently call
1470881c1b3cSKrishna Gudipati * pci_remove() entry point to remove the pci device from the
1471881c1b3cSKrishna Gudipati * system - So defer the cleanup to pci_remove(); cleaning up
1472881c1b3cSKrishna Gudipati * here causes inconsistent state during pci_remove().
1473881c1b3cSKrishna Gudipati */
1474881c1b3cSKrishna Gudipati ret = PCI_ERS_RESULT_DISCONNECT;
1475881c1b3cSKrishna Gudipati break;
1476881c1b3cSKrishna Gudipati default:
1477881c1b3cSKrishna Gudipati WARN_ON(1);
1478881c1b3cSKrishna Gudipati }
1479881c1b3cSKrishna Gudipati
1480881c1b3cSKrishna Gudipati return ret;
1481881c1b3cSKrishna Gudipati }
1482881c1b3cSKrishna Gudipati
restart_bfa(struct bfad_s * bfad)14837cd4cb94SYueHaibing static int restart_bfa(struct bfad_s *bfad)
1484881c1b3cSKrishna Gudipati {
1485881c1b3cSKrishna Gudipati unsigned long flags;
1486881c1b3cSKrishna Gudipati struct pci_dev *pdev = bfad->pcidev;
1487881c1b3cSKrishna Gudipati
1488881c1b3cSKrishna Gudipati bfa_attach(&bfad->bfa, bfad, &bfad->ioc_cfg,
1489881c1b3cSKrishna Gudipati &bfad->meminfo, &bfad->hal_pcidev);
1490881c1b3cSKrishna Gudipati
1491881c1b3cSKrishna Gudipati /* Enable Interrupt and wait bfa_init completion */
1492881c1b3cSKrishna Gudipati if (bfad_setup_intr(bfad)) {
1493881c1b3cSKrishna Gudipati dev_printk(KERN_WARNING, &pdev->dev,
1494881c1b3cSKrishna Gudipati "%s: bfad_setup_intr failed\n", bfad->pci_name);
1495da3e0beeSVijaya Mohan Guvva bfa_sm_send_event(bfad, BFAD_E_INIT_FAILED);
1496881c1b3cSKrishna Gudipati return -1;
1497881c1b3cSKrishna Gudipati }
1498881c1b3cSKrishna Gudipati
1499881c1b3cSKrishna Gudipati init_completion(&bfad->comp);
1500881c1b3cSKrishna Gudipati spin_lock_irqsave(&bfad->bfad_lock, flags);
1501881c1b3cSKrishna Gudipati bfa_iocfc_init(&bfad->bfa);
1502881c1b3cSKrishna Gudipati spin_unlock_irqrestore(&bfad->bfad_lock, flags);
1503881c1b3cSKrishna Gudipati
1504881c1b3cSKrishna Gudipati /* Set up interrupt handler for each vectors */
1505881c1b3cSKrishna Gudipati if ((bfad->bfad_flags & BFAD_MSIX_ON) &&
1506881c1b3cSKrishna Gudipati bfad_install_msix_handler(bfad))
1507881c1b3cSKrishna Gudipati dev_printk(KERN_WARNING, &pdev->dev,
1508881c1b3cSKrishna Gudipati "%s: install_msix failed.\n", bfad->pci_name);
1509881c1b3cSKrishna Gudipati
1510881c1b3cSKrishna Gudipati bfad_init_timer(bfad);
1511881c1b3cSKrishna Gudipati wait_for_completion(&bfad->comp);
1512881c1b3cSKrishna Gudipati bfad_drv_start(bfad);
1513881c1b3cSKrishna Gudipati
1514881c1b3cSKrishna Gudipati return 0;
1515881c1b3cSKrishna Gudipati }
1516881c1b3cSKrishna Gudipati
1517881c1b3cSKrishna Gudipati /*
1518881c1b3cSKrishna Gudipati * PCI Error Recovery entry, re-initialize the chip.
1519881c1b3cSKrishna Gudipati */
1520881c1b3cSKrishna Gudipati static pci_ers_result_t
bfad_pci_slot_reset(struct pci_dev * pdev)1521881c1b3cSKrishna Gudipati bfad_pci_slot_reset(struct pci_dev *pdev)
1522881c1b3cSKrishna Gudipati {
1523881c1b3cSKrishna Gudipati struct bfad_s *bfad = pci_get_drvdata(pdev);
1524881c1b3cSKrishna Gudipati u8 byte;
152511ea3824SHannes Reinecke int rc;
1526881c1b3cSKrishna Gudipati
1527881c1b3cSKrishna Gudipati dev_printk(KERN_ERR, &pdev->dev,
1528881c1b3cSKrishna Gudipati "bfad_pci_slot_reset flags: 0x%x\n", bfad->bfad_flags);
1529881c1b3cSKrishna Gudipati
1530881c1b3cSKrishna Gudipati if (pci_enable_device(pdev)) {
1531881c1b3cSKrishna Gudipati dev_printk(KERN_ERR, &pdev->dev, "Cannot re-enable "
1532881c1b3cSKrishna Gudipati "PCI device after reset.\n");
1533881c1b3cSKrishna Gudipati return PCI_ERS_RESULT_DISCONNECT;
1534881c1b3cSKrishna Gudipati }
1535881c1b3cSKrishna Gudipati
1536881c1b3cSKrishna Gudipati pci_restore_state(pdev);
1537881c1b3cSKrishna Gudipati
1538881c1b3cSKrishna Gudipati /*
1539881c1b3cSKrishna Gudipati * Read some byte (e.g. DMA max. payload size which can't
1540881c1b3cSKrishna Gudipati * be 0xff any time) to make sure - we did not hit another PCI error
1541881c1b3cSKrishna Gudipati * in the middle of recovery. If we did, then declare permanent failure.
1542881c1b3cSKrishna Gudipati */
1543881c1b3cSKrishna Gudipati pci_read_config_byte(pdev, 0x68, &byte);
1544881c1b3cSKrishna Gudipati if (byte == 0xff) {
1545881c1b3cSKrishna Gudipati dev_printk(KERN_ERR, &pdev->dev,
1546881c1b3cSKrishna Gudipati "slot_reset failed ... got another PCI error !\n");
1547881c1b3cSKrishna Gudipati goto out_disable_device;
1548881c1b3cSKrishna Gudipati }
1549881c1b3cSKrishna Gudipati
1550881c1b3cSKrishna Gudipati pci_save_state(pdev);
1551881c1b3cSKrishna Gudipati pci_set_master(pdev);
1552881c1b3cSKrishna Gudipati
155311ea3824SHannes Reinecke rc = dma_set_mask_and_coherent(&bfad->pcidev->dev, DMA_BIT_MASK(64));
155411ea3824SHannes Reinecke if (rc)
1555881c1b3cSKrishna Gudipati goto out_disable_device;
1556881c1b3cSKrishna Gudipati
1557881c1b3cSKrishna Gudipati if (restart_bfa(bfad) == -1)
1558881c1b3cSKrishna Gudipati goto out_disable_device;
1559881c1b3cSKrishna Gudipati
1560881c1b3cSKrishna Gudipati dev_printk(KERN_WARNING, &pdev->dev,
1561881c1b3cSKrishna Gudipati "slot_reset completed flags: 0x%x!\n", bfad->bfad_flags);
1562881c1b3cSKrishna Gudipati
1563881c1b3cSKrishna Gudipati return PCI_ERS_RESULT_RECOVERED;
1564881c1b3cSKrishna Gudipati
1565881c1b3cSKrishna Gudipati out_disable_device:
1566881c1b3cSKrishna Gudipati pci_disable_device(pdev);
1567881c1b3cSKrishna Gudipati return PCI_ERS_RESULT_DISCONNECT;
1568881c1b3cSKrishna Gudipati }
1569881c1b3cSKrishna Gudipati
1570881c1b3cSKrishna Gudipati static pci_ers_result_t
bfad_pci_mmio_enabled(struct pci_dev * pdev)1571881c1b3cSKrishna Gudipati bfad_pci_mmio_enabled(struct pci_dev *pdev)
1572881c1b3cSKrishna Gudipati {
1573881c1b3cSKrishna Gudipati unsigned long flags;
1574881c1b3cSKrishna Gudipati struct bfad_s *bfad = pci_get_drvdata(pdev);
1575881c1b3cSKrishna Gudipati
1576881c1b3cSKrishna Gudipati dev_printk(KERN_INFO, &pdev->dev, "mmio_enabled\n");
1577881c1b3cSKrishna Gudipati
1578881c1b3cSKrishna Gudipati /* Fetch FW diagnostic information */
1579881c1b3cSKrishna Gudipati bfa_ioc_debug_save_ftrc(&bfad->bfa.ioc);
1580881c1b3cSKrishna Gudipati
1581881c1b3cSKrishna Gudipati /* Cancel all pending IOs */
1582881c1b3cSKrishna Gudipati spin_lock_irqsave(&bfad->bfad_lock, flags);
1583881c1b3cSKrishna Gudipati init_completion(&bfad->comp);
1584881c1b3cSKrishna Gudipati bfa_fcs_stop(&bfad->bfa_fcs);
1585881c1b3cSKrishna Gudipati spin_unlock_irqrestore(&bfad->bfad_lock, flags);
1586881c1b3cSKrishna Gudipati wait_for_completion(&bfad->comp);
1587881c1b3cSKrishna Gudipati
1588881c1b3cSKrishna Gudipati bfad_remove_intr(bfad);
1589881c1b3cSKrishna Gudipati del_timer_sync(&bfad->hal_tmo);
1590881c1b3cSKrishna Gudipati pci_disable_device(pdev);
1591881c1b3cSKrishna Gudipati
1592881c1b3cSKrishna Gudipati return PCI_ERS_RESULT_NEED_RESET;
1593881c1b3cSKrishna Gudipati }
1594881c1b3cSKrishna Gudipati
1595881c1b3cSKrishna Gudipati static void
bfad_pci_resume(struct pci_dev * pdev)1596881c1b3cSKrishna Gudipati bfad_pci_resume(struct pci_dev *pdev)
1597881c1b3cSKrishna Gudipati {
1598881c1b3cSKrishna Gudipati unsigned long flags;
1599881c1b3cSKrishna Gudipati struct bfad_s *bfad = pci_get_drvdata(pdev);
1600881c1b3cSKrishna Gudipati
1601881c1b3cSKrishna Gudipati dev_printk(KERN_WARNING, &pdev->dev, "resume\n");
1602881c1b3cSKrishna Gudipati
1603881c1b3cSKrishna Gudipati /* wait until the link is online */
1604881c1b3cSKrishna Gudipati bfad_rport_online_wait(bfad);
1605881c1b3cSKrishna Gudipati
1606881c1b3cSKrishna Gudipati spin_lock_irqsave(&bfad->bfad_lock, flags);
1607881c1b3cSKrishna Gudipati bfad->bfad_flags &= ~BFAD_EEH_BUSY;
1608881c1b3cSKrishna Gudipati spin_unlock_irqrestore(&bfad->bfad_lock, flags);
1609881c1b3cSKrishna Gudipati }
1610881c1b3cSKrishna Gudipati
1611a36c61f9SKrishna Gudipati struct pci_device_id bfad_id_table[] = {
16127725ccfdSJing Huang {
16137725ccfdSJing Huang .vendor = BFA_PCI_VENDOR_ID_BROCADE,
16147725ccfdSJing Huang .device = BFA_PCI_DEVICE_ID_FC_8G2P,
16157725ccfdSJing Huang .subvendor = PCI_ANY_ID,
16167725ccfdSJing Huang .subdevice = PCI_ANY_ID,
16177725ccfdSJing Huang },
16187725ccfdSJing Huang {
16197725ccfdSJing Huang .vendor = BFA_PCI_VENDOR_ID_BROCADE,
16207725ccfdSJing Huang .device = BFA_PCI_DEVICE_ID_FC_8G1P,
16217725ccfdSJing Huang .subvendor = PCI_ANY_ID,
16227725ccfdSJing Huang .subdevice = PCI_ANY_ID,
16237725ccfdSJing Huang },
16247725ccfdSJing Huang {
16257725ccfdSJing Huang .vendor = BFA_PCI_VENDOR_ID_BROCADE,
16267725ccfdSJing Huang .device = BFA_PCI_DEVICE_ID_CT,
16277725ccfdSJing Huang .subvendor = PCI_ANY_ID,
16287725ccfdSJing Huang .subdevice = PCI_ANY_ID,
16297725ccfdSJing Huang .class = (PCI_CLASS_SERIAL_FIBER << 8),
16307725ccfdSJing Huang .class_mask = ~0,
16317725ccfdSJing Huang },
1632293f82d5SJing Huang {
1633293f82d5SJing Huang .vendor = BFA_PCI_VENDOR_ID_BROCADE,
1634293f82d5SJing Huang .device = BFA_PCI_DEVICE_ID_CT_FC,
1635293f82d5SJing Huang .subvendor = PCI_ANY_ID,
1636293f82d5SJing Huang .subdevice = PCI_ANY_ID,
1637293f82d5SJing Huang .class = (PCI_CLASS_SERIAL_FIBER << 8),
1638293f82d5SJing Huang .class_mask = ~0,
1639293f82d5SJing Huang },
164011189208SKrishna Gudipati {
164111189208SKrishna Gudipati .vendor = BFA_PCI_VENDOR_ID_BROCADE,
164211189208SKrishna Gudipati .device = BFA_PCI_DEVICE_ID_CT2,
164311189208SKrishna Gudipati .subvendor = PCI_ANY_ID,
164411189208SKrishna Gudipati .subdevice = PCI_ANY_ID,
164511189208SKrishna Gudipati .class = (PCI_CLASS_SERIAL_FIBER << 8),
164611189208SKrishna Gudipati .class_mask = ~0,
164711189208SKrishna Gudipati },
16487725ccfdSJing Huang
1649f9c867b4SVijaya Mohan Guvva {
1650f9c867b4SVijaya Mohan Guvva .vendor = BFA_PCI_VENDOR_ID_BROCADE,
1651f9c867b4SVijaya Mohan Guvva .device = BFA_PCI_DEVICE_ID_CT2_QUAD,
1652f9c867b4SVijaya Mohan Guvva .subvendor = PCI_ANY_ID,
1653f9c867b4SVijaya Mohan Guvva .subdevice = PCI_ANY_ID,
1654f9c867b4SVijaya Mohan Guvva .class = (PCI_CLASS_SERIAL_FIBER << 8),
1655f9c867b4SVijaya Mohan Guvva .class_mask = ~0,
1656f9c867b4SVijaya Mohan Guvva },
16577725ccfdSJing Huang {0, 0},
16587725ccfdSJing Huang };
16597725ccfdSJing Huang
16607725ccfdSJing Huang MODULE_DEVICE_TABLE(pci, bfad_id_table);
16617725ccfdSJing Huang
1662881c1b3cSKrishna Gudipati /*
1663881c1b3cSKrishna Gudipati * PCI error recovery handlers.
1664881c1b3cSKrishna Gudipati */
1665881c1b3cSKrishna Gudipati static struct pci_error_handlers bfad_err_handler = {
1666881c1b3cSKrishna Gudipati .error_detected = bfad_pci_error_detected,
1667881c1b3cSKrishna Gudipati .slot_reset = bfad_pci_slot_reset,
1668881c1b3cSKrishna Gudipati .mmio_enabled = bfad_pci_mmio_enabled,
1669881c1b3cSKrishna Gudipati .resume = bfad_pci_resume,
1670881c1b3cSKrishna Gudipati };
1671881c1b3cSKrishna Gudipati
16727725ccfdSJing Huang static struct pci_driver bfad_pci_driver = {
16737725ccfdSJing Huang .name = BFAD_DRIVER_NAME,
16747725ccfdSJing Huang .id_table = bfad_id_table,
16757725ccfdSJing Huang .probe = bfad_pci_probe,
16766f039790SGreg Kroah-Hartman .remove = bfad_pci_remove,
1677881c1b3cSKrishna Gudipati .err_handler = &bfad_err_handler,
16787725ccfdSJing Huang };
16797725ccfdSJing Huang
16805fbe25c7SJing Huang /*
16817725ccfdSJing Huang * Driver module init.
16827725ccfdSJing Huang */
16837725ccfdSJing Huang static int __init
bfad_init(void)16847725ccfdSJing Huang bfad_init(void)
16857725ccfdSJing Huang {
16867725ccfdSJing Huang int error = 0;
16877725ccfdSJing Huang
168831e1d569SAnil Gurumurthy pr_info("QLogic BR-series BFA FC/FCOE SCSI driver - version: %s\n",
16897725ccfdSJing Huang BFAD_DRIVER_VERSION);
16907725ccfdSJing Huang
16917725ccfdSJing Huang if (num_sgpgs > 0)
16927725ccfdSJing Huang num_sgpgs_parm = num_sgpgs;
16937725ccfdSJing Huang
1694a36c61f9SKrishna Gudipati error = bfad_im_module_init();
16957725ccfdSJing Huang if (error) {
1696a36c61f9SKrishna Gudipati printk(KERN_WARNING "bfad_im_module_init failure\n");
1697*c28409f8SYe Bin return -ENOMEM;
16987725ccfdSJing Huang }
16997725ccfdSJing Huang
1700a36c61f9SKrishna Gudipati if (strcmp(FCPI_NAME, " fcpim") == 0)
1701a36c61f9SKrishna Gudipati supported_fc4s |= BFA_LPORT_ROLE_FCP_IM;
17027725ccfdSJing Huang
1703f7f73812SMaggie Zhang bfa_auto_recover = ioc_auto_recover;
17047725ccfdSJing Huang bfa_fcs_rport_set_del_timeout(rport_del_timeout);
170561ba4394SKrishna Gudipati bfa_fcs_rport_set_max_logins(max_rport_logins);
17067725ccfdSJing Huang
1707a36c61f9SKrishna Gudipati error = pci_register_driver(&bfad_pci_driver);
17087725ccfdSJing Huang if (error) {
1709a36c61f9SKrishna Gudipati printk(KERN_WARNING "pci_register_driver failure\n");
17107725ccfdSJing Huang goto ext;
17117725ccfdSJing Huang }
17127725ccfdSJing Huang
17137725ccfdSJing Huang return 0;
17147725ccfdSJing Huang
17157725ccfdSJing Huang ext:
1716a36c61f9SKrishna Gudipati bfad_im_module_exit();
17177725ccfdSJing Huang return error;
17187725ccfdSJing Huang }
17197725ccfdSJing Huang
17205fbe25c7SJing Huang /*
17217725ccfdSJing Huang * Driver module exit.
17227725ccfdSJing Huang */
17237725ccfdSJing Huang static void __exit
bfad_exit(void)17247725ccfdSJing Huang bfad_exit(void)
17257725ccfdSJing Huang {
17267725ccfdSJing Huang pci_unregister_driver(&bfad_pci_driver);
1727a36c61f9SKrishna Gudipati bfad_im_module_exit();
17287725ccfdSJing Huang bfad_free_fwimg();
17297725ccfdSJing Huang }
17307725ccfdSJing Huang
1731a36c61f9SKrishna Gudipati /* Firmware handling */
173261338a0bSJing Huang static void
bfad_read_firmware(struct pci_dev * pdev,u32 ** bfi_image,u32 * bfi_image_size,char * fw_name)1733a36c61f9SKrishna Gudipati bfad_read_firmware(struct pci_dev *pdev, u32 **bfi_image,
1734a36c61f9SKrishna Gudipati u32 *bfi_image_size, char *fw_name)
1735a36c61f9SKrishna Gudipati {
1736a36c61f9SKrishna Gudipati const struct firmware *fw;
1737a36c61f9SKrishna Gudipati
1738a36c61f9SKrishna Gudipati if (request_firmware(&fw, fw_name, &pdev->dev)) {
1739a36c61f9SKrishna Gudipati printk(KERN_ALERT "Can't locate firmware %s\n", fw_name);
174061338a0bSJing Huang *bfi_image = NULL;
174161338a0bSJing Huang goto out;
1742a36c61f9SKrishna Gudipati }
1743a36c61f9SKrishna Gudipati
1744a36c61f9SKrishna Gudipati *bfi_image = vmalloc(fw->size);
1745a36c61f9SKrishna Gudipati if (NULL == *bfi_image) {
1746a36c61f9SKrishna Gudipati printk(KERN_ALERT "Fail to allocate buffer for fw image "
1747a36c61f9SKrishna Gudipati "size=%x!\n", (u32) fw->size);
174861338a0bSJing Huang goto out;
1749a36c61f9SKrishna Gudipati }
1750a36c61f9SKrishna Gudipati
1751a36c61f9SKrishna Gudipati memcpy(*bfi_image, fw->data, fw->size);
1752a36c61f9SKrishna Gudipati *bfi_image_size = fw->size/sizeof(u32);
175361338a0bSJing Huang out:
175461338a0bSJing Huang release_firmware(fw);
1755a36c61f9SKrishna Gudipati }
1756a36c61f9SKrishna Gudipati
175761338a0bSJing Huang static u32 *
bfad_load_fwimg(struct pci_dev * pdev)175861338a0bSJing Huang bfad_load_fwimg(struct pci_dev *pdev)
1759a36c61f9SKrishna Gudipati {
1760dcaf9aedSVijaya Mohan Guvva if (bfa_asic_id_ct2(pdev->device)) {
176111189208SKrishna Gudipati if (bfi_image_ct2_size == 0)
176211189208SKrishna Gudipati bfad_read_firmware(pdev, &bfi_image_ct2,
176311189208SKrishna Gudipati &bfi_image_ct2_size, BFAD_FW_FILE_CT2);
176411189208SKrishna Gudipati return bfi_image_ct2;
176511189208SKrishna Gudipati } else if (bfa_asic_id_ct(pdev->device)) {
176611189208SKrishna Gudipati if (bfi_image_ct_size == 0)
176711189208SKrishna Gudipati bfad_read_firmware(pdev, &bfi_image_ct,
176811189208SKrishna Gudipati &bfi_image_ct_size, BFAD_FW_FILE_CT);
176911189208SKrishna Gudipati return bfi_image_ct;
1770dcaf9aedSVijaya Mohan Guvva } else if (bfa_asic_id_cb(pdev->device)) {
177111189208SKrishna Gudipati if (bfi_image_cb_size == 0)
177211189208SKrishna Gudipati bfad_read_firmware(pdev, &bfi_image_cb,
177311189208SKrishna Gudipati &bfi_image_cb_size, BFAD_FW_FILE_CB);
177411189208SKrishna Gudipati return bfi_image_cb;
1775a36c61f9SKrishna Gudipati }
1776dcaf9aedSVijaya Mohan Guvva
1777dcaf9aedSVijaya Mohan Guvva return NULL;
1778a36c61f9SKrishna Gudipati }
17797725ccfdSJing Huang
178061338a0bSJing Huang static void
bfad_free_fwimg(void)178161338a0bSJing Huang bfad_free_fwimg(void)
178261338a0bSJing Huang {
178311189208SKrishna Gudipati if (bfi_image_ct2_size && bfi_image_ct2)
178411189208SKrishna Gudipati vfree(bfi_image_ct2);
178511189208SKrishna Gudipati if (bfi_image_ct_size && bfi_image_ct)
178611189208SKrishna Gudipati vfree(bfi_image_ct);
178711189208SKrishna Gudipati if (bfi_image_cb_size && bfi_image_cb)
178811189208SKrishna Gudipati vfree(bfi_image_cb);
178961338a0bSJing Huang }
179061338a0bSJing Huang
17917725ccfdSJing Huang module_init(bfad_init);
17927725ccfdSJing Huang module_exit(bfad_exit);
17937725ccfdSJing Huang MODULE_LICENSE("GPL");
179431e1d569SAnil Gurumurthy MODULE_DESCRIPTION("QLogic BR-series Fibre Channel HBA Driver" BFAD_PROTO_NAME);
179531e1d569SAnil Gurumurthy MODULE_AUTHOR("QLogic Corporation");
17967725ccfdSJing Huang MODULE_VERSION(BFAD_DRIVER_VERSION);
1797