Skip to content

Commit

Permalink
[SCSI] lpfc 8.1.12 : Misc bug fixes and code cleanup
Browse files Browse the repository at this point in the history
Misc bug fixes and code cleanup:
 - Fix system hang while running on systems with IOMMU
 - Fix use after free issues with rports
 - Don't free mailbox structure if it's still on the mboxq list
 - Decrement txq_cnt rather than txcmplq_cnt when parsing the txq list
 - Use msleep for long delays to prevent soft lockup bug check
 - Don't remove node during dev_loss_tmo if discovery is active
 - Fix memory leaks in get/reset statistics and link attention paths
 - Fixed lpfc_ns_rsp to handle entire GID_FT response.
 - mbox interface should use MAILBOX_CMD_SIZE rather than sizeof(MAILBOX_t)
 - Fixed bug check in add_timer.
 - Fixup messages 0116, 0117, and 0128 to report ELS I/O tag.
 - Remove unused parameter to lpfc_cleanup.
 - Change mailbox timeout handling.
 - Remove unused buflist. Code cleanup.

Signed-off-by: James Smart <James.Smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
  • Loading branch information
James Smart authored and James Bottomley committed May 6, 2007
1 parent e555db9 commit 1dcb58e
Show file tree
Hide file tree
Showing 8 changed files with 80 additions and 129 deletions.
3 changes: 0 additions & 3 deletions drivers/scsi/lpfc/lpfc.h
Original file line number Diff line number Diff line change
Expand Up @@ -387,9 +387,6 @@ struct lpfc_hba {

mempool_t *mbox_mem_pool;
mempool_t *nlp_mem_pool;
struct list_head freebufList;
struct list_head ctrspbuflist;
struct list_head rnidrspbuflist;

struct fc_host_statistics link_stats;
};
Expand Down
19 changes: 14 additions & 5 deletions drivers/scsi/lpfc/lpfc_attr.c
Original file line number Diff line number Diff line change
Expand Up @@ -1227,11 +1227,11 @@ sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
int rc;

if (off > sizeof(MAILBOX_t))
if (off > MAILBOX_CMD_SIZE)
return -ERANGE;

if ((count + off) > sizeof(MAILBOX_t))
count = sizeof(MAILBOX_t) - off;
if ((count + off) > MAILBOX_CMD_SIZE)
count = MAILBOX_CMD_SIZE - off;

if (off % 4 || count % 4 || (unsigned long)buf % 4)
return -EINVAL;
Expand Down Expand Up @@ -1326,6 +1326,11 @@ sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
}

if (rc != MBX_SUCCESS) {
if (rc == MBX_TIMEOUT) {
phba->sysfs_mbox.mbox->mbox_cmpl =
lpfc_sli_def_mbox_cmpl;
phba->sysfs_mbox.mbox = NULL;
}
sysfs_mbox_idle(phba);
spin_unlock_irq(host->host_lock);
return (rc == MBX_TIMEOUT) ? -ETIME : -ENODEV;
Expand All @@ -1344,7 +1349,7 @@ sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count)

phba->sysfs_mbox.offset = off + count;

if (phba->sysfs_mbox.offset == sizeof(MAILBOX_t))
if (phba->sysfs_mbox.offset == MAILBOX_CMD_SIZE)
sysfs_mbox_idle(phba);

spin_unlock_irq(phba->host->host_lock);
Expand All @@ -1358,7 +1363,7 @@ static struct bin_attribute sysfs_mbox_attr = {
.mode = S_IRUSR | S_IWUSR,
.owner = THIS_MODULE,
},
.size = sizeof(MAILBOX_t),
.size = MAILBOX_CMD_SIZE,
.read = sysfs_mbox_read,
.write = sysfs_mbox_write,
};
Expand Down Expand Up @@ -1631,6 +1636,8 @@ lpfc_get_stats(struct Scsi_Host *shost)
else
hs->seconds_since_last_reset = seconds - psli->stats_start;

mempool_free(pmboxq, phba->mbox_mem_pool);

return hs;
}

Expand Down Expand Up @@ -1699,6 +1706,8 @@ lpfc_reset_stats(struct Scsi_Host *shost)

psli->stats_start = get_seconds();

mempool_free(pmboxq, phba->mbox_mem_pool);

return;
}

Expand Down
5 changes: 3 additions & 2 deletions drivers/scsi/lpfc/lpfc_ct.c
Original file line number Diff line number Diff line change
Expand Up @@ -342,9 +342,10 @@ lpfc_ns_rsp(struct lpfc_hba * phba, struct lpfc_dmabuf * mp, uint32_t Size)

Size -= Cnt;

if (!ctptr)
if (!ctptr) {
Cnt = FCELSSIZE;
ctptr = (uint32_t *) mlast->virt;
else
} else
Cnt -= 16; /* subtract length of CT header */

/* Loop through entire NameServer list of DIDs */
Expand Down
17 changes: 8 additions & 9 deletions drivers/scsi/lpfc/lpfc_els.c
Original file line number Diff line number Diff line change
Expand Up @@ -222,16 +222,16 @@ lpfc_prep_els_iocb(struct lpfc_hba * phba, uint8_t expectRsp,
/* Xmit ELS command <elsCmd> to remote NPORT <did> */
lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
"%d:0116 Xmit ELS command x%x to remote "
"NPORT x%x Data: x%x x%x\n",
"NPORT x%x I/O tag: x%x, HBA state: x%x\n",
phba->brd_no, elscmd,
did, icmd->ulpIoTag, phba->hba_state);
did, elsiocb->iotag, phba->hba_state);
} else {
/* Xmit ELS response <elsCmd> to remote NPORT <did> */
lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
"%d:0117 Xmit ELS response x%x to remote "
"NPORT x%x Data: x%x x%x\n",
"NPORT x%x I/O tag: x%x, size: x%x\n",
phba->brd_no, elscmd,
ndlp->nlp_DID, icmd->ulpIoTag, cmdSize);
ndlp->nlp_DID, elsiocb->iotag, cmdSize);
}

return elsiocb;
Expand Down Expand Up @@ -2017,10 +2017,9 @@ lpfc_els_rsp_acc(struct lpfc_hba * phba, uint32_t flag,

/* Xmit ELS ACC response tag <ulpIoTag> */
lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
"%d:0128 Xmit ELS ACC response tag x%x "
"Data: x%x x%x x%x x%x x%x\n",
phba->brd_no,
elsiocb->iocb.ulpIoTag,
"%d:0128 Xmit ELS ACC response tag x%x, XRI: x%x, "
"DID: x%x, nlp_flag: x%x nlp_state: x%x RPI: x%x\n",
phba->brd_no, elsiocb->iotag,
elsiocb->iocb.ulpContext, ndlp->nlp_DID,
ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);

Expand Down Expand Up @@ -3363,7 +3362,7 @@ lpfc_els_flush_cmd(struct lpfc_hba * phba)
els_command = *elscmd;

list_del(&piocb->list);
pring->txcmplq_cnt--;
pring->txq_cnt--;

cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
Expand Down
29 changes: 15 additions & 14 deletions drivers/scsi/lpfc/lpfc_hbadisc.c
Original file line number Diff line number Diff line change
Expand Up @@ -147,11 +147,14 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
ndlp->nlp_state, ndlp->nlp_rpi);
}

ndlp->rport = NULL;
rdata->pnode = NULL;

if (!(phba->fc_flag & FC_UNLOADING))
if (!(phba->fc_flag & FC_UNLOADING) &&
!(ndlp->nlp_flag & NLP_DELAY_TMO) &&
!(ndlp->nlp_flag & NLP_NPR_2B_DISC))
lpfc_disc_state_machine(phba, ndlp, NULL, NLP_EVT_DEVICE_RM);
else {
rdata->pnode = NULL;
ndlp->rport = NULL;
}

return;
}
Expand Down Expand Up @@ -1569,16 +1572,6 @@ lpfc_freenode(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)

lpfc_nlp_list(phba, ndlp, NLP_JUST_DQ);

/*
* if unloading the driver - just leave the remote port in place.
* The driver unload will force the attached devices to detach
* and flush cache's w/o generating flush errors.
*/
if ((ndlp->rport) && !(phba->fc_flag & FC_UNLOADING)) {
lpfc_unregister_remote_port(phba, ndlp);
ndlp->nlp_sid = NLP_NO_SID;
}

/* cleanup any ndlp on mbox q waiting for reglogin cmpl */
if ((mb = phba->sli.mbox_active)) {
if ((mb->mb.mbxCommand == MBX_REG_LOGIN64) &&
Expand Down Expand Up @@ -1627,6 +1620,7 @@ lpfc_freenode(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
int
lpfc_nlp_remove(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
{
struct lpfc_rport_data *rdata;

if (ndlp->nlp_flag & NLP_DELAY_TMO) {
lpfc_cancel_retry_delay_tmo(phba, ndlp);
Expand All @@ -1638,6 +1632,13 @@ lpfc_nlp_remove(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
spin_unlock_irq(phba->host->host_lock);
} else {
lpfc_freenode(phba, ndlp);

if ((ndlp->rport) && !(phba->fc_flag & FC_UNLOADING)) {
rdata = ndlp->rport->dd_data;
rdata->pnode = NULL;
ndlp->rport = NULL;
}

mempool_free( ndlp, phba->nlp_mem_pool);
}
return 0;
Expand Down
31 changes: 6 additions & 25 deletions drivers/scsi/lpfc/lpfc_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -386,8 +386,7 @@ lpfc_config_port_post(struct lpfc_hba * phba)
* Setup the ring 0 (els) timeout handler
*/
timeout = phba->fc_ratov << 1;
phba->els_tmofunc.expires = jiffies + HZ * timeout;
add_timer(&phba->els_tmofunc);
mod_timer(&phba->els_tmofunc, jiffies + HZ * timeout);

lpfc_init_link(phba, pmb, phba->cfg_topology, phba->cfg_link_speed);
pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
Expand Down Expand Up @@ -633,7 +632,7 @@ lpfc_handle_latt(struct lpfc_hba * phba)
lpfc_handle_latt_free_mp:
kfree(mp);
lpfc_handle_latt_free_pmb:
kfree(pmb);
mempool_free(pmb, phba->mbox_mem_pool);
lpfc_handle_latt_err_exit:
/* Enable Link attention interrupts */
spin_lock_irq(phba->host->host_lock);
Expand Down Expand Up @@ -1174,7 +1173,7 @@ lpfc_hba_init(struct lpfc_hba *phba, uint32_t *hbainit)
}

static void
lpfc_cleanup(struct lpfc_hba * phba, uint32_t save_bind)
lpfc_cleanup(struct lpfc_hba * phba)
{
struct lpfc_nodelist *ndlp, *next_ndlp;

Expand Down Expand Up @@ -1262,21 +1261,6 @@ lpfc_stop_timer(struct lpfc_hba * phba)
{
struct lpfc_sli *psli = &phba->sli;

/* Instead of a timer, this has been converted to a
* deferred procedding list.
*/
while (!list_empty(&phba->freebufList)) {

struct lpfc_dmabuf *mp = NULL;

list_remove_head((&phba->freebufList), mp,
struct lpfc_dmabuf, list);
if (mp) {
lpfc_mbuf_free(phba, mp->virt, mp->phys);
kfree(mp);
}
}

del_timer_sync(&phba->fcp_poll_timer);
del_timer_sync(&phba->fc_estabtmo);
del_timer_sync(&phba->fc_disctmo);
Expand Down Expand Up @@ -1339,7 +1323,7 @@ lpfc_offline(struct lpfc_hba * phba)
pring = &psli->ring[i];
/* The linkdown event takes 30 seconds to timeout. */
while (pring->txcmplq_cnt) {
mdelay(10);
msleep(10);
if (cnt++ > 3000) {
lpfc_printf_log(phba,
KERN_WARNING, LOG_INIT,
Expand All @@ -1366,7 +1350,7 @@ lpfc_offline(struct lpfc_hba * phba)
/* Bring down the SLI Layer and cleanup. The HBA is offline
now. */
lpfc_sli_hba_down(phba);
lpfc_cleanup(phba, 1);
lpfc_cleanup(phba);
spin_lock_irqsave(phba->host->host_lock, iflag);
phba->fc_flag |= FC_OFFLINE_MODE;
spin_unlock_irqrestore(phba->host->host_lock, iflag);
Expand Down Expand Up @@ -1445,9 +1429,6 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
goto out_put_host;

host->unique_id = phba->brd_no;
INIT_LIST_HEAD(&phba->ctrspbuflist);
INIT_LIST_HEAD(&phba->rnidrspbuflist);
INIT_LIST_HEAD(&phba->freebufList);

/* Initialize timers used by driver */
init_timer(&phba->fc_estabtmo);
Expand Down Expand Up @@ -1773,7 +1754,7 @@ lpfc_pci_remove_one(struct pci_dev *pdev)
free_irq(phba->pcidev->irq, phba);
pci_disable_msi(phba->pcidev);

lpfc_cleanup(phba, 0);
lpfc_cleanup(phba);
lpfc_stop_timer(phba);
phba->work_hba_events = 0;

Expand Down
7 changes: 5 additions & 2 deletions drivers/scsi/lpfc/lpfc_scsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,10 @@ lpfc_get_scsi_buf(struct lpfc_hba * phba)

spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag);
list_remove_head(scsi_buf_list, lpfc_cmd, struct lpfc_scsi_buf, list);
if (lpfc_cmd) {
lpfc_cmd->seg_cnt = 0;
lpfc_cmd->nonsg_phys = 0;
}
spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag);
return lpfc_cmd;
}
Expand Down Expand Up @@ -466,10 +470,10 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,

result = cmd->result;
sdev = cmd->device;
lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd);
cmd->scsi_done(cmd);

if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd);
lpfc_release_scsi_buf(phba, lpfc_cmd);
return;
}
Expand Down Expand Up @@ -527,7 +531,6 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
}
}

lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd);
lpfc_release_scsi_buf(phba, lpfc_cmd);
}

Expand Down
Loading

0 comments on commit 1dcb58e

Please sign in to comment.