aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorJames Smart <James.Smart@Emulex.Com>2009-11-18 15:40:49 -0500
committerJames Bottomley <James.Bottomley@suse.de>2009-12-04 13:01:52 -0500
commit1c6f4ef5d6be7ef4cbe92a86286217971f52e2cd (patch)
tree6415ea806d637bae7e3894f509f08a3196147337 /drivers/scsi
parent891478a2442d8d0077651bc8316afaec8d85dd4d (diff)
[SCSI] lpfc 8.3.6 : Fix critical errors
Fix errors relating to crashes and hangs. - Fix crash due to list corruption while unloading driver. - Fix panic during pci-hot-plug testing. - Fix panic when unmapping luns. - Fixed total_scsi_bufs counting could cause exhausted memory. - Fixed locking issue causing hang. - Fixed the call from lpfc_new_scsi_buf_s3 to use lpfc_release_scsi_buf_s3. Signed-off-by: James Smart <james.smart@emulex.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi')
-rwxr-xr-xdrivers/scsi/lpfc/lpfc_hbadisc.c14
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c4
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c33
3 files changed, 38 insertions, 13 deletions
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index 4d7d8846b4da..3b9424427652 100755
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -1018,13 +1018,12 @@ lpfc_mbx_cmpl_reg_fcfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
1018 mempool_free(mboxq, phba->mbox_mem_pool); 1018 mempool_free(mboxq, phba->mbox_mem_pool);
1019 return; 1019 return;
1020 } 1020 }
1021 spin_lock_irqsave(&phba->hbalock, flags);
1021 phba->fcf.fcf_flag |= (FCF_DISCOVERED | FCF_IN_USE); 1022 phba->fcf.fcf_flag |= (FCF_DISCOVERED | FCF_IN_USE);
1022 phba->hba_flag &= ~FCF_DISC_INPROGRESS; 1023 phba->hba_flag &= ~FCF_DISC_INPROGRESS;
1023 if (vport->port_state != LPFC_FLOGI) { 1024 spin_unlock_irqrestore(&phba->hbalock, flags);
1024 spin_lock_irqsave(&phba->hbalock, flags); 1025 if (vport->port_state != LPFC_FLOGI)
1025 spin_unlock_irqrestore(&phba->hbalock, flags);
1026 lpfc_initial_flogi(vport); 1026 lpfc_initial_flogi(vport);
1027 }
1028 1027
1029 mempool_free(mboxq, phba->mbox_mem_pool); 1028 mempool_free(mboxq, phba->mbox_mem_pool);
1030 return; 1029 return;
@@ -1460,12 +1459,15 @@ lpfc_check_pending_fcoe_event(struct lpfc_hba *phba, uint8_t unreg_fcf)
1460 1459
1461 if (phba->link_state >= LPFC_LINK_UP) 1460 if (phba->link_state >= LPFC_LINK_UP)
1462 lpfc_sli4_read_fcf_record(phba, LPFC_FCOE_FCF_GET_FIRST); 1461 lpfc_sli4_read_fcf_record(phba, LPFC_FCOE_FCF_GET_FIRST);
1463 else 1462 else {
1464 /* 1463 /*
1465 * Do not continue FCF discovery and clear FCF_DISC_INPROGRESS 1464 * Do not continue FCF discovery and clear FCF_DISC_INPROGRESS
1466 * flag 1465 * flag
1467 */ 1466 */
1467 spin_lock_irq(&phba->hbalock);
1468 phba->hba_flag &= ~FCF_DISC_INPROGRESS; 1468 phba->hba_flag &= ~FCF_DISC_INPROGRESS;
1469 spin_unlock_irq(&phba->hbalock);
1470 }
1469 1471
1470 if (unreg_fcf) { 1472 if (unreg_fcf) {
1471 spin_lock_irq(&phba->hbalock); 1473 spin_lock_irq(&phba->hbalock);
@@ -2264,7 +2266,7 @@ lpfc_mbx_cmpl_unreg_vpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
2264 * This shost reference might have been taken at the beginning of 2266 * This shost reference might have been taken at the beginning of
2265 * lpfc_vport_delete() 2267 * lpfc_vport_delete()
2266 */ 2268 */
2267 if (vport->load_flag & FC_UNLOADING) 2269 if ((vport->load_flag & FC_UNLOADING) && (vport != phba->pport))
2268 scsi_host_put(shost); 2270 scsi_host_put(shost);
2269} 2271}
2270 2272
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 93679f30a5af..5f5b2283d58c 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -2320,6 +2320,7 @@ lpfc_scsi_free(struct lpfc_hba *phba)
2320 2320
2321 spin_lock_irq(&phba->hbalock); 2321 spin_lock_irq(&phba->hbalock);
2322 /* Release all the lpfc_scsi_bufs maintained by this host. */ 2322 /* Release all the lpfc_scsi_bufs maintained by this host. */
2323 spin_lock(&phba->scsi_buf_list_lock);
2323 list_for_each_entry_safe(sb, sb_next, &phba->lpfc_scsi_buf_list, list) { 2324 list_for_each_entry_safe(sb, sb_next, &phba->lpfc_scsi_buf_list, list) {
2324 list_del(&sb->list); 2325 list_del(&sb->list);
2325 pci_pool_free(phba->lpfc_scsi_dma_buf_pool, sb->data, 2326 pci_pool_free(phba->lpfc_scsi_dma_buf_pool, sb->data,
@@ -2327,6 +2328,7 @@ lpfc_scsi_free(struct lpfc_hba *phba)
2327 kfree(sb); 2328 kfree(sb);
2328 phba->total_scsi_bufs--; 2329 phba->total_scsi_bufs--;
2329 } 2330 }
2331 spin_unlock(&phba->scsi_buf_list_lock);
2330 2332
2331 /* Release all the lpfc_iocbq entries maintained by this host. */ 2333 /* Release all the lpfc_iocbq entries maintained by this host. */
2332 list_for_each_entry_safe(io, io_next, &phba->lpfc_iocb_list, list) { 2334 list_for_each_entry_safe(io, io_next, &phba->lpfc_iocb_list, list) {
@@ -2334,9 +2336,7 @@ lpfc_scsi_free(struct lpfc_hba *phba)
2334 kfree(io); 2336 kfree(io);
2335 phba->total_iocbq_bufs--; 2337 phba->total_iocbq_bufs--;
2336 } 2338 }
2337
2338 spin_unlock_irq(&phba->hbalock); 2339 spin_unlock_irq(&phba->hbalock);
2339
2340 return 0; 2340 return 0;
2341} 2341}
2342 2342
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index bf80cdefb506..a246410ce9df 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -59,6 +59,8 @@ static char *dif_op_str[] = {
59}; 59};
60static void 60static void
61lpfc_release_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb); 61lpfc_release_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb);
62static void
63lpfc_release_scsi_buf_s3(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb);
62 64
63static void 65static void
64lpfc_debug_save_data(struct lpfc_hba *phba, struct scsi_cmnd *cmnd) 66lpfc_debug_save_data(struct lpfc_hba *phba, struct scsi_cmnd *cmnd)
@@ -596,7 +598,7 @@ lpfc_new_scsi_buf_s3(struct lpfc_vport *vport, int num_to_alloc)
596 iocb->ulpClass = CLASS3; 598 iocb->ulpClass = CLASS3;
597 psb->status = IOSTAT_SUCCESS; 599 psb->status = IOSTAT_SUCCESS;
598 /* Put it back into the SCSI buffer list */ 600 /* Put it back into the SCSI buffer list */
599 lpfc_release_scsi_buf_s4(phba, psb); 601 lpfc_release_scsi_buf_s3(phba, psb);
600 602
601 } 603 }
602 604
@@ -2766,7 +2768,7 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
2766 struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 2768 struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
2767 struct lpfc_hba *phba = vport->phba; 2769 struct lpfc_hba *phba = vport->phba;
2768 struct lpfc_rport_data *rdata = cmnd->device->hostdata; 2770 struct lpfc_rport_data *rdata = cmnd->device->hostdata;
2769 struct lpfc_nodelist *ndlp = rdata->pnode; 2771 struct lpfc_nodelist *ndlp;
2770 struct lpfc_scsi_buf *lpfc_cmd; 2772 struct lpfc_scsi_buf *lpfc_cmd;
2771 struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device)); 2773 struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device));
2772 int err; 2774 int err;
@@ -2776,6 +2778,7 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
2776 cmnd->result = err; 2778 cmnd->result = err;
2777 goto out_fail_command; 2779 goto out_fail_command;
2778 } 2780 }
2781 ndlp = rdata->pnode;
2779 2782
2780 if (!(phba->sli3_options & LPFC_SLI3_BG_ENABLED) && 2783 if (!(phba->sli3_options & LPFC_SLI3_BG_ENABLED) &&
2781 scsi_get_prot_op(cmnd) != SCSI_PROT_NORMAL) { 2784 scsi_get_prot_op(cmnd) != SCSI_PROT_NORMAL) {
@@ -3154,9 +3157,15 @@ static int
3154lpfc_chk_tgt_mapped(struct lpfc_vport *vport, struct scsi_cmnd *cmnd) 3157lpfc_chk_tgt_mapped(struct lpfc_vport *vport, struct scsi_cmnd *cmnd)
3155{ 3158{
3156 struct lpfc_rport_data *rdata = cmnd->device->hostdata; 3159 struct lpfc_rport_data *rdata = cmnd->device->hostdata;
3157 struct lpfc_nodelist *pnode = rdata->pnode; 3160 struct lpfc_nodelist *pnode;
3158 unsigned long later; 3161 unsigned long later;
3159 3162
3163 if (!rdata) {
3164 lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
3165 "0797 Tgt Map rport failure: rdata x%p\n", rdata);
3166 return FAILED;
3167 }
3168 pnode = rdata->pnode;
3160 /* 3169 /*
3161 * If target is not in a MAPPED state, delay until 3170 * If target is not in a MAPPED state, delay until
3162 * target is rediscovered or devloss timeout expires. 3171 * target is rediscovered or devloss timeout expires.
@@ -3241,12 +3250,18 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd)
3241 struct Scsi_Host *shost = cmnd->device->host; 3250 struct Scsi_Host *shost = cmnd->device->host;
3242 struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 3251 struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
3243 struct lpfc_rport_data *rdata = cmnd->device->hostdata; 3252 struct lpfc_rport_data *rdata = cmnd->device->hostdata;
3244 struct lpfc_nodelist *pnode = rdata->pnode; 3253 struct lpfc_nodelist *pnode;
3245 unsigned tgt_id = cmnd->device->id; 3254 unsigned tgt_id = cmnd->device->id;
3246 unsigned int lun_id = cmnd->device->lun; 3255 unsigned int lun_id = cmnd->device->lun;
3247 struct lpfc_scsi_event_header scsi_event; 3256 struct lpfc_scsi_event_header scsi_event;
3248 int status; 3257 int status;
3249 3258
3259 if (!rdata) {
3260 lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
3261 "0798 Device Reset rport failure: rdata x%p\n", rdata);
3262 return FAILED;
3263 }
3264 pnode = rdata->pnode;
3250 fc_block_scsi_eh(cmnd); 3265 fc_block_scsi_eh(cmnd);
3251 3266
3252 status = lpfc_chk_tgt_mapped(vport, cmnd); 3267 status = lpfc_chk_tgt_mapped(vport, cmnd);
@@ -3300,12 +3315,18 @@ lpfc_target_reset_handler(struct scsi_cmnd *cmnd)
3300 struct Scsi_Host *shost = cmnd->device->host; 3315 struct Scsi_Host *shost = cmnd->device->host;
3301 struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 3316 struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
3302 struct lpfc_rport_data *rdata = cmnd->device->hostdata; 3317 struct lpfc_rport_data *rdata = cmnd->device->hostdata;
3303 struct lpfc_nodelist *pnode = rdata->pnode; 3318 struct lpfc_nodelist *pnode;
3304 unsigned tgt_id = cmnd->device->id; 3319 unsigned tgt_id = cmnd->device->id;
3305 unsigned int lun_id = cmnd->device->lun; 3320 unsigned int lun_id = cmnd->device->lun;
3306 struct lpfc_scsi_event_header scsi_event; 3321 struct lpfc_scsi_event_header scsi_event;
3307 int status; 3322 int status;
3308 3323
3324 if (!rdata) {
3325 lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
3326 "0799 Target Reset rport failure: rdata x%p\n", rdata);
3327 return FAILED;
3328 }
3329 pnode = rdata->pnode;
3309 fc_block_scsi_eh(cmnd); 3330 fc_block_scsi_eh(cmnd);
3310 3331
3311 status = lpfc_chk_tgt_mapped(vport, cmnd); 3332 status = lpfc_chk_tgt_mapped(vport, cmnd);
@@ -3486,6 +3507,8 @@ lpfc_slave_alloc(struct scsi_device *sdev)
3486 "Allocated %d buffers.\n", 3507 "Allocated %d buffers.\n",
3487 num_to_alloc, num_allocated); 3508 num_to_alloc, num_allocated);
3488 } 3509 }
3510 if (num_allocated > 0)
3511 phba->total_scsi_bufs += num_allocated;
3489 return 0; 3512 return 0;
3490} 3513}
3491 3514