X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fscsi%2Flpfc%2Flpfc_init.c;h=86c2f2b15b688bfae2689eefa7d5f12445d084bd;hb=7ee5d43e2ea25336a7638715420c75583bd2ed69;hp=07bd0dcdf0d65dc4b9a4a4b704b41e12399ec71a;hpb=2fe83b3ad12d43799af5f3156886eca443a88bac;p=linux-2.6-omap-h63xx.git diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 07bd0dcdf0d..86c2f2b15b6 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -43,7 +43,6 @@ #include "lpfc_crtn.h" #include "lpfc_vport.h" #include "lpfc_version.h" -#include "lpfc_vport.h" static int lpfc_parse_vpd(struct lpfc_hba *, uint8_t *, int); static void lpfc_get_hba_model_desc(struct lpfc_hba *, uint8_t *, uint8_t *); @@ -53,8 +52,6 @@ static struct scsi_transport_template *lpfc_transport_template = NULL; static struct scsi_transport_template *lpfc_vport_transport_template = NULL; static DEFINE_IDR(lpfc_hba_index); - - /************************************************************************/ /* */ /* lpfc_config_port_prep */ @@ -107,10 +104,9 @@ lpfc_config_port_prep(struct lpfc_hba *phba) if (rc != MBX_SUCCESS) { lpfc_printf_log(phba, KERN_ERR, LOG_MBOX, - "%d:0324 Config Port initialization " + "0324 Config Port initialization " "error, mbxCmd x%x READ_NVPARM, " "mbxStatus x%x\n", - phba->brd_no, mb->mbxCommand, mb->mbxStatus); mempool_free(pmb, phba->mbox_mem_pool); return -ERESTART; @@ -128,9 +124,8 @@ lpfc_config_port_prep(struct lpfc_hba *phba) rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL); if (rc != MBX_SUCCESS) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "%d:0439 Adapter failed to init, mbxCmd x%x " + "0439 Adapter failed to init, mbxCmd x%x " "READ_REV, mbxStatus x%x\n", - phba->brd_no, mb->mbxCommand, mb->mbxStatus); mempool_free( pmb, phba->mbox_mem_pool); return -ERESTART; @@ -144,9 +139,8 @@ lpfc_config_port_prep(struct lpfc_hba *phba) if (mb->un.varRdRev.rr == 0) { vp->rev.rBit = 0; lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "%d:0440 Adapter failed to init, READ_REV has " - "missing revision information.\n", - phba->brd_no); + "0440 Adapter failed to init, READ_REV has " + "missing revision information.\n"); mempool_free(pmb, phba->mbox_mem_pool); return -ERESTART; } @@ -197,9 +191,8 @@ lpfc_config_port_prep(struct lpfc_hba *phba) if (rc != MBX_SUCCESS) { lpfc_printf_log(phba, KERN_INFO, LOG_INIT, - "%d:0441 VPD not present on adapter, " + "0441 VPD not present on adapter, " "mbxCmd x%x DUMP VPD, mbxStatus x%x\n", - phba->brd_no, mb->mbxCommand, mb->mbxStatus); mb->un.varDmp.word_cnt = 0; } @@ -219,6 +212,18 @@ out_free_mbox: return 0; } +/* Completion handler for config async event mailbox command. */ +static void +lpfc_config_async_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq) +{ + if (pmboxq->mb.mbxStatus == MBX_SUCCESS) + phba->temp_sensor_support = 1; + else + phba->temp_sensor_support = 0; + mempool_free(pmboxq, phba->mbox_mem_pool); + return; +} + /************************************************************************/ /* */ /* lpfc_config_port_post */ @@ -253,9 +258,8 @@ lpfc_config_port_post(struct lpfc_hba *phba) pmb->vport = vport; if (lpfc_sli_issue_mbox(phba, pmb, MBX_POLL) != MBX_SUCCESS) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "%d:0448 Adapter failed init, mbxCmd x%x " + "0448 Adapter failed init, mbxCmd x%x " "READ_SPARM mbxStatus x%x\n", - phba->brd_no, mb->mbxCommand, mb->mbxStatus); phba->link_state = LPFC_HBA_ERROR; mp = (struct lpfc_dmabuf *) pmb->context1; @@ -312,9 +316,8 @@ lpfc_config_port_post(struct lpfc_hba *phba) pmb->vport = vport; if (lpfc_sli_issue_mbox(phba, pmb, MBX_POLL) != MBX_SUCCESS) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "%d:0453 Adapter failed to init, mbxCmd x%x " + "0453 Adapter failed to init, mbxCmd x%x " "READ_CONFIG, mbxStatus x%x\n", - phba->brd_no, mb->mbxCommand, mb->mbxStatus); phba->link_state = LPFC_HBA_ERROR; mempool_free( pmb, phba->mbox_mem_pool); @@ -344,9 +347,8 @@ lpfc_config_port_post(struct lpfc_hba *phba) && !(phba->lmt & LMT_10Gb))) { /* Reset link speed to auto */ lpfc_printf_log(phba, KERN_WARNING, LOG_LINK_EVENT, - "%d:1302 Invalid speed for this board: " + "1302 Invalid speed for this board: " "Reset link speed to auto: x%x\n", - phba->brd_no, phba->cfg_link_speed); phba->cfg_link_speed = LINK_SPEED_AUTO; } @@ -402,9 +404,8 @@ lpfc_config_port_post(struct lpfc_hba *phba) lpfc_set_loopback_flag(phba); if (rc != MBX_SUCCESS) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "%d:0454 Adapter failed to init, mbxCmd x%x " + "0454 Adapter failed to init, mbxCmd x%x " "INIT_LINK, mbxStatus x%x\n", - phba->brd_no, mb->mbxCommand, mb->mbxStatus); /* Clear all interrupt enable conditions */ @@ -420,7 +421,21 @@ lpfc_config_port_post(struct lpfc_hba *phba) return -EIO; } /* MBOX buffer will be freed in mbox compl */ + pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); + lpfc_config_async(phba, pmb, LPFC_ELS_RING); + pmb->mbox_cmpl = lpfc_config_async_cmpl; + pmb->vport = phba->pport; + rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); + if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { + lpfc_printf_log(phba, + KERN_ERR, + LOG_INIT, + "0456 Adapter failed to issue " + "ASYNCEVT_ENABLE mbox status x%x \n.", + rc); + mempool_free(pmb, phba->mbox_mem_pool); + } return (0); } @@ -437,16 +452,11 @@ lpfc_config_port_post(struct lpfc_hba *phba) int lpfc_hba_down_prep(struct lpfc_hba *phba) { - struct lpfc_vport *vport = phba->pport; - /* Disable interrupts */ writel(0, phba->HCregaddr); readl(phba->HCregaddr); /* flush */ - list_for_each_entry(vport, &phba->port_list, listentry) { - lpfc_cleanup_discovery_resources(vport); - } - + lpfc_cleanup_discovery_resources(phba->pport); return 0; } @@ -518,7 +528,7 @@ lpfc_hb_mbox_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq) mempool_free(pmboxq, phba->mbox_mem_pool); if (!(phba->pport->fc_flag & FC_OFFLINE_MODE) && !(phba->link_state == LPFC_HBA_ERROR) && - !(phba->pport->fc_flag & FC_UNLOADING)) + !(phba->pport->load_flag & FC_UNLOADING)) mod_timer(&phba->hb_tmofunc, jiffies + HZ * LPFC_HB_MBOX_INTERVAL); return; @@ -532,7 +542,7 @@ lpfc_hb_timeout_handler(struct lpfc_hba *phba) struct lpfc_sli *psli = &phba->sli; if ((phba->link_state == LPFC_HBA_ERROR) || - (phba->pport->fc_flag & FC_UNLOADING) || + (phba->pport->load_flag & FC_UNLOADING) || (phba->pport->fc_flag & FC_OFFLINE_MODE)) return; @@ -586,8 +596,8 @@ lpfc_hb_timeout_handler(struct lpfc_hba *phba) * need to take the HBA offline. */ lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "%d:0459 Adapter heartbeat failure, taking " - "this port offline.\n", phba->brd_no); + "0459 Adapter heartbeat failure, taking " + "this port offline.\n"); spin_lock_irq(&phba->hbalock); psli->sli_flag &= ~LPFC_SLI2_ACTIVE; @@ -615,9 +625,12 @@ lpfc_handle_eratt(struct lpfc_hba *phba) struct lpfc_vport *vport = phba->pport; struct lpfc_sli *psli = &phba->sli; struct lpfc_sli_ring *pring; - struct lpfc_vport *port_iterator; + struct lpfc_vport **vports; uint32_t event_data; + unsigned long temperature; + struct temp_event temp_event_data; struct Scsi_Host *shost; + int i; /* If the pci channel is offline, ignore possible errors, * since we cannot communicate with the pci card anyway. */ @@ -628,18 +641,21 @@ lpfc_handle_eratt(struct lpfc_hba *phba) phba->work_hs & HS_FFER5) { /* Re-establishing Link */ lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT, - "%d:1301 Re-establishing Link " + "1301 Re-establishing Link " "Data: x%x x%x x%x\n", - phba->brd_no, phba->work_hs, + phba->work_hs, phba->work_status[0], phba->work_status[1]); - list_for_each_entry(port_iterator, &phba->port_list, - listentry) { - shost = lpfc_shost_from_vport(port_iterator); - - spin_lock_irq(shost->host_lock); - port_iterator->fc_flag |= FC_ESTABLISH_LINK; - spin_unlock_irq(shost->host_lock); - } + vports = lpfc_create_vport_work_array(phba); + if (vports != NULL) + for(i = 0; + i < LPFC_MAX_VPORTS && vports[i] != NULL; + i++){ + shost = lpfc_shost_from_vport(vports[i]); + spin_lock_irq(shost->host_lock); + vports[i]->fc_flag |= FC_ESTABLISH_LINK; + spin_unlock_irq(shost->host_lock); + } + lpfc_destroy_vport_work_array(vports); spin_lock_irq(&phba->hbalock); psli->sli_flag &= ~LPFC_SLI2_ACTIVE; spin_unlock_irq(&phba->hbalock); @@ -667,15 +683,42 @@ lpfc_handle_eratt(struct lpfc_hba *phba) return; } lpfc_unblock_mgmt_io(phba); + } else if (phba->work_hs & HS_CRIT_TEMP) { + temperature = readl(phba->MBslimaddr + TEMPERATURE_OFFSET); + temp_event_data.event_type = FC_REG_TEMPERATURE_EVENT; + temp_event_data.event_code = LPFC_CRIT_TEMP; + temp_event_data.data = (uint32_t)temperature; + + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "0459 Adapter maximum temperature exceeded " + "(%ld), taking this port offline " + "Data: x%x x%x x%x\n", + temperature, phba->work_hs, + phba->work_status[0], phba->work_status[1]); + + shost = lpfc_shost_from_vport(phba->pport); + fc_host_post_vendor_event(shost, fc_get_event_number(), + sizeof(temp_event_data), + (char *) &temp_event_data, + SCSI_NL_VID_TYPE_PCI + | PCI_VENDOR_ID_EMULEX); + + psli->sli_flag &= ~LPFC_SLI2_ACTIVE; + lpfc_offline_prep(phba); + lpfc_offline(phba); + lpfc_unblock_mgmt_io(phba); + phba->link_state = LPFC_HBA_ERROR; + lpfc_hba_down_post(phba); + } else { /* The if clause above forces this code path when the status * failure is a value other than FFER6. Do not call the offline * twice. This is the adapter hardware error path. */ lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "%d:0457 Adapter Hardware Error " + "0457 Adapter Hardware Error " "Data: x%x x%x x%x\n", - phba->brd_no, phba->work_hs, + phba->work_hs, phba->work_status[0], phba->work_status[1]); event_data = FC_REG_DUMP_EVENT; @@ -708,7 +751,6 @@ lpfc_handle_latt(struct lpfc_hba *phba) { struct lpfc_vport *vport = phba->pport; struct lpfc_sli *psli = &phba->sli; - struct lpfc_vport *port_iterator; LPFC_MBOXQ_t *pmb; volatile uint32_t control; struct lpfc_dmabuf *mp; @@ -729,8 +771,7 @@ lpfc_handle_latt(struct lpfc_hba *phba) rc = -EIO; /* Cleanup any outstanding ELS commands */ - list_for_each_entry(port_iterator, &phba->port_list, listentry) - lpfc_els_flush_cmd(port_iterator); + lpfc_els_flush_all_cmd(phba); psli->slistat.link_event++; lpfc_read_la(phba, pmb, mp); @@ -773,8 +814,7 @@ lpfc_handle_latt_err_exit: /* The other case is an error from issue_mbox */ if (rc == -ENOMEM) lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX, - "%d:0300 READ_LA: no buffers\n", - phba->brd_no); + "0300 READ_LA: no buffers\n"); return; } @@ -799,8 +839,7 @@ lpfc_parse_vpd(struct lpfc_hba *phba, uint8_t *vpd, int len) /* Vital Product */ lpfc_printf_log(phba, KERN_INFO, LOG_INIT, - "%d:0455 Vital Product Data: x%x x%x x%x x%x\n", - phba->brd_no, + "0455 Vital Product Data: x%x x%x x%x x%x\n", (uint32_t) vpd[0], (uint32_t) vpd[1], (uint32_t) vpd[2], (uint32_t) vpd[3]); while (!finished && (index < (len - 4))) { @@ -1281,11 +1320,10 @@ lpfc_hba_init(struct lpfc_hba *phba, uint32_t *hbainit) uint32_t *HashWorking; uint32_t *pwwnn = (uint32_t *) phba->wwnn; - HashWorking = kmalloc(80 * sizeof(uint32_t), GFP_KERNEL); + HashWorking = kcalloc(80, sizeof(uint32_t), GFP_KERNEL); if (!HashWorking) return; - memset(HashWorking, 0, (80 * sizeof(uint32_t))); HashWorking[0] = HashWorking[78] = *pwwnn++; HashWorking[1] = HashWorking[79] = *pwwnn; @@ -1313,22 +1351,25 @@ static void lpfc_establish_link_tmo(unsigned long ptr) { struct lpfc_hba *phba = (struct lpfc_hba *) ptr; - struct lpfc_vport *vport = phba->pport; + struct lpfc_vport **vports; unsigned long iflag; + int i; /* Re-establishing Link, timer expired */ lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT, - "%d:1300 Re-establishing Link, timer expired " + "1300 Re-establishing Link, timer expired " "Data: x%x x%x\n", - phba->brd_no, vport->fc_flag, - vport->port_state); - list_for_each_entry(vport, &phba->port_list, listentry) { - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); - - spin_lock_irqsave(shost->host_lock, iflag); - vport->fc_flag &= ~FC_ESTABLISH_LINK; - spin_unlock_irqrestore(shost->host_lock, iflag); - } + phba->pport->fc_flag, phba->pport->port_state); + vports = lpfc_create_vport_work_array(phba); + if (vports != NULL) + for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) { + struct Scsi_Host *shost; + shost = lpfc_shost_from_vport(vports[i]); + spin_lock_irqsave(shost->host_lock, iflag); + vports[i]->fc_flag &= ~FC_ESTABLISH_LINK; + spin_unlock_irqrestore(shost->host_lock, iflag); + } + lpfc_destroy_vport_work_array(vports); } void @@ -1343,12 +1384,9 @@ lpfc_stop_vport_timers(struct lpfc_vport *vport) static void lpfc_stop_phba_timers(struct lpfc_hba *phba) { - struct lpfc_vport *vport; - del_timer_sync(&phba->fcp_poll_timer); del_timer_sync(&phba->fc_estabtmo); - list_for_each_entry(vport, &phba->port_list, listentry) - lpfc_stop_vport_timers(vport); + lpfc_stop_vport_timers(phba->pport); del_timer_sync(&phba->sli.mbox_tmo); del_timer_sync(&phba->fabric_block_timer); phba->hb_outstanding = 0; @@ -1360,6 +1398,8 @@ int lpfc_online(struct lpfc_hba *phba) { struct lpfc_vport *vport = phba->pport; + struct lpfc_vport **vports; + int i; if (!phba) return 0; @@ -1368,8 +1408,7 @@ lpfc_online(struct lpfc_hba *phba) return 0; lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, - "%d:0458 Bring Adapter online\n", - phba->brd_no); + "0458 Bring Adapter online\n"); lpfc_block_mgmt_io(phba); @@ -1383,14 +1422,18 @@ lpfc_online(struct lpfc_hba *phba) return 1; } - list_for_each_entry(vport, &phba->port_list, listentry) { - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); - spin_lock_irq(shost->host_lock); - vport->fc_flag &= ~FC_OFFLINE_MODE; - if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) - vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; - spin_unlock_irq(shost->host_lock); - } + vports = lpfc_create_vport_work_array(phba); + if (vports != NULL) + for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) { + struct Scsi_Host *shost; + shost = lpfc_shost_from_vport(vports[i]); + spin_lock_irq(shost->host_lock); + vports[i]->fc_flag &= ~FC_OFFLINE_MODE; + if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) + vports[i]->fc_flag |= FC_VPORT_NEEDS_REG_VPI; + spin_unlock_irq(shost->host_lock); + } + lpfc_destroy_vport_work_array(vports); lpfc_unblock_mgmt_io(phba); return 0; @@ -1440,39 +1483,39 @@ lpfc_offline_prep(struct lpfc_hba * phba) void lpfc_offline(struct lpfc_hba *phba) { - struct lpfc_vport *vport = phba->pport; - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); - struct lpfc_vport *port_iterator; + struct Scsi_Host *shost; + struct lpfc_vport **vports; + int i; - if (vport->fc_flag & FC_OFFLINE_MODE) + if (phba->pport->fc_flag & FC_OFFLINE_MODE) return; /* stop all timers associated with this hba */ lpfc_stop_phba_timers(phba); - list_for_each_entry(port_iterator, &phba->port_list, listentry) { - port_iterator->work_port_events = 0; - } - + vports = lpfc_create_vport_work_array(phba); + if (vports != NULL) + for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) + lpfc_stop_vport_timers(vports[i]); + lpfc_destroy_vport_work_array(vports); lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, - "%d:0460 Bring Adapter offline\n", - phba->brd_no); - + "0460 Bring Adapter offline\n"); /* Bring down the SLI Layer and cleanup. The HBA is offline now. */ lpfc_sli_hba_down(phba); spin_lock_irq(&phba->hbalock); phba->work_ha = 0; - vport->fc_flag |= FC_OFFLINE_MODE; spin_unlock_irq(&phba->hbalock); - list_for_each_entry(port_iterator, &phba->port_list, listentry) { - shost = lpfc_shost_from_vport(port_iterator); - - lpfc_cleanup(port_iterator); - spin_lock_irq(shost->host_lock); - vport->work_port_events = 0; - vport->fc_flag |= FC_OFFLINE_MODE; - spin_unlock_irq(shost->host_lock); - } + vports = lpfc_create_vport_work_array(phba); + if (vports != NULL) + for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) { + shost = lpfc_shost_from_vport(vports[i]); + lpfc_cleanup(vports[i]); + spin_lock_irq(shost->host_lock); + vports[i]->work_port_events = 0; + vports[i]->fc_flag |= FC_OFFLINE_MODE; + spin_unlock_irq(shost->host_lock); + } + lpfc_destroy_vport_work_array(vports); } /****************************************************************************** @@ -1509,15 +1552,19 @@ lpfc_scsi_free(struct lpfc_hba *phba) return 0; } - struct lpfc_vport * -lpfc_create_port(struct lpfc_hba *phba, int instance, struct fc_vport *fc_vport) +lpfc_create_port(struct lpfc_hba *phba, int instance, struct device *dev) { struct lpfc_vport *vport; struct Scsi_Host *shost; int error = 0; - shost = scsi_host_alloc(&lpfc_template, sizeof(struct lpfc_vport)); + if (dev != &phba->pcidev->dev) + shost = scsi_host_alloc(&lpfc_vport_template, + sizeof(struct lpfc_vport)); + else + shost = scsi_host_alloc(&lpfc_template, + sizeof(struct lpfc_vport)); if (!shost) goto out; @@ -1527,9 +1574,10 @@ lpfc_create_port(struct lpfc_hba *phba, int instance, struct fc_vport *fc_vport) vport->load_flag |= FC_LOADING; vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; + lpfc_get_vport_cfgparam(vport); shost->unique_id = instance; shost->max_id = LPFC_MAX_TARGET; - shost->max_lun = phba->cfg_max_luns; + shost->max_lun = vport->cfg_max_luns; shost->this_id = -1; shost->max_cmd_len = 16; /* @@ -1538,7 +1586,7 @@ lpfc_create_port(struct lpfc_hba *phba, int instance, struct fc_vport *fc_vport) * max xri value determined in hba setup. */ shost->can_queue = phba->cfg_hba_queue_depth - 10; - if (fc_vport != NULL) { + if (dev != &phba->pcidev->dev) { shost->transportt = lpfc_vport_transport_template; vport->port_type = LPFC_NPIV_PORT; } else { @@ -1562,15 +1610,13 @@ lpfc_create_port(struct lpfc_hba *phba, int instance, struct fc_vport *fc_vport) vport->els_tmofunc.function = lpfc_els_timeout; vport->els_tmofunc.data = (unsigned long)vport; - if (fc_vport != NULL) { - error = scsi_add_host(shost, &fc_vport->dev); - } else { - error = scsi_add_host(shost, &phba->pcidev->dev); - } + error = scsi_add_host(shost, dev); if (error) goto out_put_shost; + spin_lock_irq(&phba->hbalock); list_add_tail(&vport->listentry, &phba->port_list); + spin_unlock_irq(&phba->hbalock); return vport; out_put_shost: @@ -1625,23 +1671,21 @@ int lpfc_scan_finished(struct Scsi_Host *shost, unsigned long time) spin_lock_irq(shost->host_lock); - if (vport->fc_flag & FC_UNLOADING) { + if (vport->load_flag & FC_UNLOADING) { stat = 1; goto finished; } if (time >= 30 * HZ) { lpfc_printf_log(phba, KERN_INFO, LOG_INIT, - "%d:0461 Scanning longer than 30 " - "seconds. Continuing initialization\n", - phba->brd_no); + "0461 Scanning longer than 30 " + "seconds. Continuing initialization\n"); stat = 1; goto finished; } if (time >= 15 * HZ && phba->link_state <= LPFC_LINK_DOWN) { lpfc_printf_log(phba, KERN_INFO, LOG_INIT, - "%d:0465 Link down longer than 15 " - "seconds. Continuing initialization\n", - phba->brd_no); + "0465 Link down longer than 15 " + "seconds. Continuing initialization\n"); stat = 1; goto finished; } @@ -1704,7 +1748,7 @@ void lpfc_host_attrib_init(struct Scsi_Host *shost) fc_host_max_npiv_vports(shost) = phba->max_vpi; spin_lock_irq(shost->host_lock); - vport->fc_flag &= ~FC_LOADING; + vport->load_flag &= ~FC_LOADING; spin_unlock_irq(shost->host_lock); } @@ -1716,9 +1760,10 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) struct lpfc_sli *psli; struct lpfc_iocbq *iocbq_entry = NULL, *iocbq_next = NULL; struct Scsi_Host *shost = NULL; + void *ptr; unsigned long bar0map_len, bar2map_len; int error = -ENODEV; - int i; + int i, hbq_count; uint16_t iotag; if (pci_enable_device(pdev)) @@ -1739,7 +1784,6 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) goto out_free_phba; INIT_LIST_HEAD(&phba->port_list); - INIT_LIST_HEAD(&phba->hbq_buffer_list); /* * Get all the module params for configuring this host and then * establish the host. @@ -1817,6 +1861,17 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) if (!phba->hbqslimp.virt) goto out_free_slim; + hbq_count = lpfc_sli_hbq_count(); + ptr = phba->hbqslimp.virt; + for (i = 0; i < hbq_count; ++i) { + phba->hbqs[i].hbq_virt = ptr; + INIT_LIST_HEAD(&phba->hbqs[i].hbq_buffer_list); + ptr += (lpfc_hbq_defs[i]->entry_count * + sizeof(struct lpfc_hbq_entry)); + } + phba->hbqs[LPFC_ELS_HBQ].hbq_alloc_buffer = lpfc_els_hbq_alloc; + phba->hbqs[LPFC_ELS_HBQ].hbq_free_buffer = lpfc_els_hbq_free; + memset(phba->hbqslimp.virt, 0, lpfc_sli_hbq_size()); /* Initialize the SLI Layer to run with lpfc HBAs. */ @@ -1880,7 +1935,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) /* Initialize list of fabric iocbs */ INIT_LIST_HEAD(&phba->fabric_iocb_list); - vport = lpfc_create_port(phba, phba->brd_no, NULL); + vport = lpfc_create_port(phba, phba->brd_no, &phba->pcidev->dev); if (!vport) goto out_kthread_stop; @@ -1892,18 +1947,19 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) if (phba->cfg_use_msi) { error = pci_enable_msi(phba->pcidev); - if (error) - lpfc_printf_log(phba, KERN_INFO, LOG_INIT, "%d:0452 " - "Enable MSI failed, continuing with " - "IRQ\n", phba->brd_no); + if (!error) + phba->using_msi = 1; + else + lpfc_printf_log(phba, KERN_INFO, LOG_INIT, + "0452 Enable MSI failed, continuing " + "with IRQ\n"); } error = request_irq(phba->pcidev->irq, lpfc_intr_handler, IRQF_SHARED, LPFC_DRIVER_NAME, phba); if (error) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "%d:0451 Enable interrupt handler failed\n", - phba->brd_no); + "0451 Enable interrupt handler failed\n"); goto out_disable_msi; } @@ -1940,14 +1996,15 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) out_remove_device: lpfc_free_sysfs_attr(vport); spin_lock_irq(shost->host_lock); - vport->fc_flag |= FC_UNLOADING; + vport->load_flag |= FC_UNLOADING; spin_unlock_irq(shost->host_lock); out_free_irq: lpfc_stop_phba_timers(phba); phba->pport->work_port_events = 0; free_irq(phba->pcidev->irq, phba); out_disable_msi: - pci_disable_msi(phba->pcidev); + if (phba->using_msi) + pci_disable_msi(phba->pcidev); destroy_port(vport); out_kthread_stop: kthread_stop(phba->worker_thread); @@ -1989,16 +2046,15 @@ lpfc_pci_remove_one(struct pci_dev *pdev) struct Scsi_Host *shost = pci_get_drvdata(pdev); struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; struct lpfc_hba *phba = vport->phba; - struct lpfc_vport *port_iterator; - list_for_each_entry(port_iterator, &phba->port_list, listentry) - port_iterator->load_flag |= FC_UNLOADING; + spin_lock_irq(&phba->hbalock); + vport->load_flag |= FC_UNLOADING; + spin_unlock_irq(&phba->hbalock); kfree(vport->vname); lpfc_free_sysfs_attr(vport); fc_remove_host(shost); scsi_remove_host(shost); - /* * Bring down the SLI Layer. This step disable all interrupts, * clears the rings, discards all mailbox commands, and resets @@ -2012,7 +2068,6 @@ lpfc_pci_remove_one(struct pci_dev *pdev) list_del_init(&vport->listentry); spin_unlock_irq(&phba->hbalock); - lpfc_debugfs_terminate(vport); lpfc_cleanup(vport); @@ -2020,7 +2075,8 @@ lpfc_pci_remove_one(struct pci_dev *pdev) /* Release the irq reservation */ free_irq(phba->pcidev->irq, phba); - pci_disable_msi(phba->pcidev); + if (phba->using_msi) + pci_disable_msi(phba->pcidev); pci_set_drvdata(pdev, NULL); scsi_host_put(shost); @@ -2062,8 +2118,8 @@ lpfc_pci_remove_one(struct pci_dev *pdev) static pci_ers_result_t lpfc_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state) { - struct Scsi_Host *host = pci_get_drvdata(pdev); - struct lpfc_hba *phba = (struct lpfc_hba *)host->hostdata; + struct Scsi_Host *shost = pci_get_drvdata(pdev); + struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; struct lpfc_sli *psli = &phba->sli; struct lpfc_sli_ring *pring; @@ -2079,6 +2135,11 @@ static pci_ers_result_t lpfc_io_error_detected(struct pci_dev *pdev, pring = &psli->ring[psli->fcp_ring]; lpfc_sli_abort_iocb_ring(phba, pring); + /* Release the irq reservation */ + free_irq(phba->pcidev->irq, phba); + if (phba->using_msi) + pci_disable_msi(phba->pcidev); + /* Request a slot reset. */ return PCI_ERS_RESULT_NEED_RESET; } @@ -2091,8 +2152,8 @@ static pci_ers_result_t lpfc_io_error_detected(struct pci_dev *pdev, */ static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev) { - struct Scsi_Host *host = pci_get_drvdata(pdev); - struct lpfc_hba *phba = (struct lpfc_hba *)host->hostdata; + struct Scsi_Host *shost = pci_get_drvdata(pdev); + struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; struct lpfc_sli *psli = &phba->sli; int bars = pci_select_bars(pdev, IORESOURCE_MEM); @@ -2106,9 +2167,9 @@ static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev) pci_set_master(pdev); /* Re-establishing Link */ - spin_lock_irq(host->host_lock); + spin_lock_irq(shost->host_lock); phba->pport->fc_flag |= FC_ESTABLISH_LINK; - spin_unlock_irq(host->host_lock); + spin_unlock_irq(shost->host_lock); spin_lock_irq(&phba->hbalock); psli->sli_flag &= ~LPFC_SLI2_ACTIVE; @@ -2131,8 +2192,8 @@ static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev) */ static void lpfc_io_resume(struct pci_dev *pdev) { - struct Scsi_Host *host = pci_get_drvdata(pdev); - struct lpfc_hba *phba = (struct lpfc_hba *)host->hostdata; + struct Scsi_Host *shost = pci_get_drvdata(pdev); + struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; if (lpfc_online(phba) == 0) { mod_timer(&phba->fc_estabtmo, jiffies + HZ * 60); @@ -2233,12 +2294,24 @@ lpfc_init(void) printk(LPFC_MODULE_DESC "\n"); printk(LPFC_COPYRIGHT "\n"); + if (lpfc_enable_npiv) { + lpfc_transport_functions.vport_create = lpfc_vport_create; + lpfc_transport_functions.vport_delete = lpfc_vport_delete; + } lpfc_transport_template = fc_attach_transport(&lpfc_transport_functions); - lpfc_vport_transport_template = - fc_attach_transport(&lpfc_vport_transport_functions); - if (!lpfc_transport_template || !lpfc_vport_transport_template) + if (lpfc_transport_template == NULL) return -ENOMEM; + if (lpfc_enable_npiv) { + lpfc_transport_functions.vport_create = NULL; + lpfc_transport_functions.vport_delete = NULL; + lpfc_transport_functions.issue_fc_host_lip = NULL; + lpfc_transport_functions.vport_disable = lpfc_vport_disable; + lpfc_vport_transport_template = + fc_attach_transport(&lpfc_transport_functions); + if (lpfc_vport_transport_template == NULL) + return -ENOMEM; + } error = pci_register_driver(&lpfc_driver); if (error) { fc_release_transport(lpfc_transport_template); @@ -2253,7 +2326,8 @@ lpfc_exit(void) { pci_unregister_driver(&lpfc_driver); fc_release_transport(lpfc_transport_template); - fc_release_transport(lpfc_vport_transport_template); + if (lpfc_enable_npiv) + fc_release_transport(lpfc_vport_transport_template); } module_init(lpfc_init);