]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - drivers/scsi/bfa/bfad.c
include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[net-next-2.6.git] / drivers / scsi / bfa / bfad.c
index b52b773d49d9de6f64439899310cd16211a3b4d9..13f5feb308c2304bb2559d33332670fe2f28b73f 100644 (file)
@@ -19,7 +19,9 @@
  *  bfad.c Linux driver PCI interface module.
  */
 
+#include <linux/slab.h>
 #include <linux/module.h>
+#include <linux/kthread.h>
 #include "bfad_drv.h"
 #include "bfad_im.h"
 #include "bfad_tm.h"
@@ -53,6 +55,7 @@ static int      log_level = BFA_LOG_WARNING;
 static int      ioc_auto_recover = BFA_TRUE;
 static int      ipfc_enable = BFA_FALSE;
 static int      ipfc_mtu = -1;
+static int     fdmi_enable = BFA_TRUE;
 int            bfa_lun_queue_depth = BFAD_LUN_QUEUE_DEPTH;
 int            bfa_linkup_delay = -1;
 
@@ -74,6 +77,7 @@ module_param(log_level, int, S_IRUGO | S_IWUSR);
 module_param(ioc_auto_recover, int, S_IRUGO | S_IWUSR);
 module_param(ipfc_enable, int, S_IRUGO | S_IWUSR);
 module_param(ipfc_mtu, int, S_IRUGO | S_IWUSR);
+module_param(fdmi_enable, int, S_IRUGO | S_IWUSR);
 module_param(bfa_linkup_delay, int, S_IRUGO | S_IWUSR);
 
 /*
@@ -95,6 +99,8 @@ bfad_fc4_probe(struct bfad_s *bfad)
 
        if (ipfc_enable)
                bfad_ipfc_probe(bfad);
+
+       bfad->bfad_flags |= BFAD_FC4_PROBE_DONE;
 ext:
        return rc;
 }
@@ -106,6 +112,7 @@ bfad_fc4_probe_undo(struct bfad_s *bfad)
        bfad_tm_probe_undo(bfad);
        if (ipfc_enable)
                bfad_ipfc_probe_undo(bfad);
+       bfad->bfad_flags &= ~BFAD_FC4_PROBE_DONE;
 }
 
 static void
@@ -173,9 +180,19 @@ bfa_cb_init(void *drv, bfa_status_t init_status)
 {
        struct bfad_s  *bfad = drv;
 
-       if (init_status == BFA_STATUS_OK)
+       if (init_status == BFA_STATUS_OK) {
                bfad->bfad_flags |= BFAD_HAL_INIT_DONE;
 
+               /* If BFAD_HAL_INIT_FAIL flag is set:
+                * Wake up the kernel thread to start
+                * the bfad operations after HAL init done
+                */
+               if ((bfad->bfad_flags & BFAD_HAL_INIT_FAIL)) {
+                       bfad->bfad_flags &= ~BFAD_HAL_INIT_FAIL;
+                       wake_up_process(bfad->bfad_tsk);
+               }
+       }
+
        complete(&bfad->comp);
 }
 
@@ -648,7 +665,7 @@ bfad_fcs_port_cfg(struct bfad_s *bfad)
 
        sprintf(symname, "%s-%d", BFAD_DRIVER_NAME, bfad->inst_no);
        memcpy(port_cfg.sym_name.symname, symname, strlen(symname));
-       bfa_pport_get_attr(&bfad->bfa, &attr);
+       bfa_fcport_get_attr(&bfad->bfa, &attr);
        port_cfg.nwwn = attr.nwwn;
        port_cfg.pwwn = attr.pwwn;
 
@@ -661,7 +678,6 @@ bfad_drv_init(struct bfad_s *bfad)
        bfa_status_t    rc;
        unsigned long   flags;
        struct bfa_fcs_driver_info_s driver_info;
-       int             i;
 
        bfad->cfg_data.rport_del_timeout = rport_del_timeout;
        bfad->cfg_data.lun_queue_depth = bfa_lun_queue_depth;
@@ -681,12 +697,7 @@ bfad_drv_init(struct bfad_s *bfad)
        bfa_init_log(&bfad->bfa, bfad->logmod);
        bfa_init_trc(&bfad->bfa, bfad->trcmod);
        bfa_init_aen(&bfad->bfa, bfad->aen);
-       INIT_LIST_HEAD(&bfad->file_q);
-       INIT_LIST_HEAD(&bfad->file_free_q);
-       for (i = 0; i < BFAD_AEN_MAX_APPS; i++) {
-               bfa_q_qe_init(&bfad->file_buf[i].qe);
-               list_add_tail(&bfad->file_buf[i].qe, &bfad->file_free_q);
-       }
+       memset(bfad->file_map, 0, sizeof(bfad->file_map));
        bfa_init_plog(&bfad->bfa, &bfad->plog_buf);
        bfa_plog_init(&bfad->plog_buf);
        bfa_plog_str(&bfad->plog_buf, BFA_PL_MID_DRVR, BFA_PL_EID_DRIVER_START,
@@ -746,8 +757,16 @@ bfad_drv_init(struct bfad_s *bfad)
        bfa_fcs_log_init(&bfad->bfa_fcs, bfad->logmod);
        bfa_fcs_trc_init(&bfad->bfa_fcs, bfad->trcmod);
        bfa_fcs_aen_init(&bfad->bfa_fcs, bfad->aen);
-       bfa_fcs_init(&bfad->bfa_fcs, &bfad->bfa, bfad, BFA_FALSE);
+       bfa_fcs_attach(&bfad->bfa_fcs, &bfad->bfa, bfad, BFA_FALSE);
+
+       /* Do FCS init only when HAL init is done */
+       if ((bfad->bfad_flags & BFAD_HAL_INIT_DONE)) {
+               bfa_fcs_init(&bfad->bfa_fcs);
+               bfad->bfad_flags |= BFAD_FCS_INIT_DONE;
+       }
+
        bfa_fcs_driver_info_init(&bfad->bfa_fcs, &driver_info);
+       bfa_fcs_set_fdmi_param(&bfad->bfa_fcs, fdmi_enable);
        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 
        bfad->bfad_flags |= BFAD_DRV_INIT_DONE;
@@ -763,12 +782,21 @@ out_hal_mem_alloc_failure:
 void
 bfad_drv_uninit(struct bfad_s *bfad)
 {
+       unsigned long   flags;
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       init_completion(&bfad->comp);
+       bfa_stop(&bfad->bfa);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+       wait_for_completion(&bfad->comp);
+
        del_timer_sync(&bfad->hal_tmo);
        bfa_isr_disable(&bfad->bfa);
        bfa_detach(&bfad->bfa);
        bfad_remove_intr(bfad);
-       bfa_assert(list_empty(&bfad->file_q));
        bfad_hal_mem_release(bfad);
+
+       bfad->bfad_flags &= ~BFAD_DRV_INIT_DONE;
 }
 
 void
@@ -859,6 +887,86 @@ bfad_drv_log_level_set(struct bfad_s *bfad)
                bfa_log_set_level_all(&bfad->log_data, log_level);
 }
 
+bfa_status_t
+bfad_start_ops(struct bfad_s *bfad)
+{
+       int retval;
+
+       /* PPORT FCS config */
+       bfad_fcs_port_cfg(bfad);
+
+       retval = bfad_cfg_pport(bfad, BFA_PORT_ROLE_FCP_IM);
+       if (retval != BFA_STATUS_OK)
+               goto out_cfg_pport_failure;
+
+       /* BFAD level FC4 (IM/TM/IPFC) specific resource allocation */
+       retval = bfad_fc4_probe(bfad);
+       if (retval != BFA_STATUS_OK) {
+               printk(KERN_WARNING "bfad_fc4_probe failed\n");
+               goto out_fc4_probe_failure;
+       }
+
+       bfad_drv_start(bfad);
+
+       /*
+        * If bfa_linkup_delay is set to -1 default; try to retrive the
+        * value using the bfad_os_get_linkup_delay(); else use the
+        * passed in module param value as the bfa_linkup_delay.
+        */
+       if (bfa_linkup_delay < 0) {
+
+               bfa_linkup_delay = bfad_os_get_linkup_delay(bfad);
+               bfad_os_rport_online_wait(bfad);
+               bfa_linkup_delay = -1;
+
+       } else {
+               bfad_os_rport_online_wait(bfad);
+       }
+
+       bfa_log(bfad->logmod, BFA_LOG_LINUX_DEVICE_CLAIMED, bfad->pci_name);
+
+       return BFA_STATUS_OK;
+
+out_fc4_probe_failure:
+       bfad_fc4_probe_undo(bfad);
+       bfad_uncfg_pport(bfad);
+out_cfg_pport_failure:
+       return BFA_STATUS_FAILED;
+}
+
+int
+bfad_worker (void *ptr)
+{
+       struct bfad_s *bfad;
+       unsigned long   flags;
+
+       bfad = (struct bfad_s *)ptr;
+
+       while (!kthread_should_stop()) {
+
+               /* Check if the FCS init is done from bfad_drv_init;
+                * if not done do FCS init and set the flag.
+                */
+               if (!(bfad->bfad_flags & BFAD_FCS_INIT_DONE)) {
+                       spin_lock_irqsave(&bfad->bfad_lock, flags);
+                       bfa_fcs_init(&bfad->bfa_fcs);
+                       bfad->bfad_flags |= BFAD_FCS_INIT_DONE;
+                       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+               }
+
+               /* Start the bfad operations after HAL init done */
+               bfad_start_ops(bfad);
+
+               spin_lock_irqsave(&bfad->bfad_lock, flags);
+               bfad->bfad_tsk = NULL;
+               spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+               break;
+       }
+
+       return 0;
+}
+
  /*
   *  PCI_entry PCI driver entries * {
   */
@@ -871,7 +979,6 @@ bfad_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid)
 {
        struct bfad_s  *bfad;
        int             error = -ENODEV, retval;
-       char            buf[16];
 
        /*
         * For single port cards - only claim function 0
@@ -902,8 +1009,7 @@ bfad_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid)
        bfa_trc(bfad, bfad_inst);
 
        bfad->logmod = &bfad->log_data;
-       sprintf(buf, "%d", bfad_inst);
-       bfa_log_init(bfad->logmod, buf, bfa_os_printf);
+       bfa_log_init(bfad->logmod, (char *)pci_name(pdev), bfa_os_printf);
 
        bfad_drv_log_level_set(bfad);
 
@@ -933,57 +1039,39 @@ bfad_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid)
        bfad->ref_count = 0;
        bfad->pport.bfad = bfad;
 
+       bfad->bfad_tsk = kthread_create(bfad_worker, (void *) bfad, "%s",
+                                       "bfad_worker");
+       if (IS_ERR(bfad->bfad_tsk)) {
+               printk(KERN_INFO "bfad[%d]: Kernel thread"
+                       " creation failed!\n",
+                       bfad->inst_no);
+               goto out_kthread_create_failure;
+       }
+
        retval = bfad_drv_init(bfad);
        if (retval != BFA_STATUS_OK)
                goto out_drv_init_failure;
        if (!(bfad->bfad_flags & BFAD_HAL_INIT_DONE)) {
+               bfad->bfad_flags |= BFAD_HAL_INIT_FAIL;
                printk(KERN_WARNING "bfad%d: hal init failed\n", bfad->inst_no);
                goto ok;
        }
 
-       /*
-        * PPORT FCS config
-        */
-       bfad_fcs_port_cfg(bfad);
-
-       retval = bfad_cfg_pport(bfad, BFA_PORT_ROLE_FCP_IM);
+       retval = bfad_start_ops(bfad);
        if (retval != BFA_STATUS_OK)
-               goto out_cfg_pport_failure;
-
-       /*
-        * BFAD level FC4 (IM/TM/IPFC) specific resource allocation
-        */
-       retval = bfad_fc4_probe(bfad);
-       if (retval != BFA_STATUS_OK) {
-               printk(KERN_WARNING "bfad_fc4_probe failed\n");
-               goto out_fc4_probe_failure;
-       }
+               goto out_start_ops_failure;
 
-       bfad_drv_start(bfad);
-
-       /*
-        * If bfa_linkup_delay is set to -1 default; try to retrive the
-        * value using the bfad_os_get_linkup_delay(); else use the
-        * passed in module param value as the bfa_linkup_delay.
-        */
-       if (bfa_linkup_delay < 0) {
-               bfa_linkup_delay = bfad_os_get_linkup_delay(bfad);
-               bfad_os_rport_online_wait(bfad);
-               bfa_linkup_delay = -1;
-       } else {
-               bfad_os_rport_online_wait(bfad);
-       }
+       kthread_stop(bfad->bfad_tsk);
+       bfad->bfad_tsk = NULL;
 
-       bfa_log(bfad->logmod, BFA_LOG_LINUX_DEVICE_CLAIMED, bfad->pci_name);
 ok:
        return 0;
 
-out_fc4_probe_failure:
-       bfad_fc4_probe_undo(bfad);
-       bfad_uncfg_pport(bfad);
-out_cfg_pport_failure:
+out_start_ops_failure:
        bfad_drv_uninit(bfad);
 out_drv_init_failure:
+       kthread_stop(bfad->bfad_tsk);
+out_kthread_create_failure:
        mutex_lock(&bfad_mutex);
        bfad_inst--;
        list_del(&bfad->list_entry);
@@ -1008,6 +1096,11 @@ bfad_pci_remove(struct pci_dev *pdev)
 
        bfa_trc(bfad, bfad->inst_no);
 
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       if (bfad->bfad_tsk != NULL)
+               kthread_stop(bfad->bfad_tsk);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
        if ((bfad->bfad_flags & BFAD_DRV_INIT_DONE)
            && !(bfad->bfad_flags & BFAD_HAL_INIT_DONE)) {
 
@@ -1024,13 +1117,25 @@ bfad_pci_remove(struct pci_dev *pdev)
                goto remove_sysfs;
        }
 
-       if (bfad->bfad_flags & BFAD_HAL_START_DONE)
+       if (bfad->bfad_flags & BFAD_HAL_START_DONE) {
                bfad_drv_stop(bfad);
+       } else if (bfad->bfad_flags & BFAD_DRV_INIT_DONE) {
+               /* Invoking bfa_stop() before bfa_detach
+                * when HAL and DRV init are success
+                * but HAL start did not occur.
+                */
+               spin_lock_irqsave(&bfad->bfad_lock, flags);
+               init_completion(&bfad->comp);
+               bfa_stop(&bfad->bfa);
+               spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+               wait_for_completion(&bfad->comp);
+       }
 
        bfad_remove_intr(bfad);
-
        del_timer_sync(&bfad->hal_tmo);
-       bfad_fc4_probe_undo(bfad);
+
+       if (bfad->bfad_flags & BFAD_FC4_PROBE_DONE)
+               bfad_fc4_probe_undo(bfad);
 
        if (bfad->bfad_flags & BFAD_CFG_PPORT_DONE)
                bfad_uncfg_pport(bfad);