aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorJames Smart <James.Smart@Emulex.Com>2008-12-04 22:39:40 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-12-29 12:24:27 -0500
commit9f1e1b50ab43a281dbc75c25f11e1926a9ea367a (patch)
treea88f66e6205bd1dbff333b1a9da9fb62cd6f0cd5 /drivers/scsi
parent5b75da2fa2c9570c3c3dbb2f63cae5b4183e0ca3 (diff)
[SCSI] lpfc 8.3.0 : Fix some memory handling issues
- Fix mailbox buffer leak on dump mailbox completion - Fix mbuf leak in lpfc_pci_probe_one() SLI-2 mode error path - Don't allocate HBQs in interrupt context - Use correct size for FCP response buffer so that all available sense data is copied - Fix jiffies calculation to prevent crash when collecting statistical data Signed-off-by: James Smart <James.Smart@emulex.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c7
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c14
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c76
3 files changed, 23 insertions, 74 deletions
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index e07f12a0871b..7a216d478a94 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -255,8 +255,10 @@ lpfc_dump_wakeup_param_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
255 /* character array used for decoding dist type. */ 255 /* character array used for decoding dist type. */
256 char dist_char[] = "nabx"; 256 char dist_char[] = "nabx";
257 257
258 if (pmboxq->mb.mbxStatus != MBX_SUCCESS) 258 if (pmboxq->mb.mbxStatus != MBX_SUCCESS) {
259 mempool_free(pmboxq, phba->mbox_mem_pool);
259 return; 260 return;
261 }
260 262
261 prg = (struct prog_id *) &prog_id_word; 263 prg = (struct prog_id *) &prog_id_word;
262 264
@@ -274,6 +276,7 @@ lpfc_dump_wakeup_param_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
274 sprintf(phba->OptionROMVersion, "%d.%d%d%c%d", 276 sprintf(phba->OptionROMVersion, "%d.%d%d%c%d",
275 prg->ver, prg->rev, prg->lev, 277 prg->ver, prg->rev, prg->lev,
276 dist, prg->num); 278 dist, prg->num);
279 mempool_free(pmboxq, phba->mbox_mem_pool);
277 return; 280 return;
278} 281}
279 282
@@ -2889,6 +2892,8 @@ out_remove_device:
2889 lpfc_stop_phba_timers(phba); 2892 lpfc_stop_phba_timers(phba);
2890 phba->pport->work_port_events = 0; 2893 phba->pport->work_port_events = 0;
2891 lpfc_disable_intr(phba); 2894 lpfc_disable_intr(phba);
2895 lpfc_sli_hba_down(phba);
2896 lpfc_sli_brdrestart(phba);
2892out_free_sysfs_attr: 2897out_free_sysfs_attr:
2893 lpfc_free_sysfs_attr(vport); 2898 lpfc_free_sysfs_attr(vport);
2894out_destroy_port: 2899out_destroy_port:
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 51e6a6394951..5f697ace9706 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -66,6 +66,8 @@ lpfc_update_stats(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
66 if (cmd->result) 66 if (cmd->result)
67 return; 67 return;
68 68
69 latency = jiffies_to_msecs((long)jiffies - (long)lpfc_cmd->start_time);
70
69 spin_lock_irqsave(shost->host_lock, flags); 71 spin_lock_irqsave(shost->host_lock, flags);
70 if (!vport->stat_data_enabled || 72 if (!vport->stat_data_enabled ||
71 vport->stat_data_blocked || 73 vport->stat_data_blocked ||
@@ -74,13 +76,15 @@ lpfc_update_stats(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
74 spin_unlock_irqrestore(shost->host_lock, flags); 76 spin_unlock_irqrestore(shost->host_lock, flags);
75 return; 77 return;
76 } 78 }
77 latency = jiffies_to_msecs(jiffies - lpfc_cmd->start_time);
78 79
79 if (phba->bucket_type == LPFC_LINEAR_BUCKET) { 80 if (phba->bucket_type == LPFC_LINEAR_BUCKET) {
80 i = (latency + phba->bucket_step - 1 - phba->bucket_base)/ 81 i = (latency + phba->bucket_step - 1 - phba->bucket_base)/
81 phba->bucket_step; 82 phba->bucket_step;
82 if (i >= LPFC_MAX_BUCKET_COUNT) 83 /* check array subscript bounds */
83 i = LPFC_MAX_BUCKET_COUNT; 84 if (i < 0)
85 i = 0;
86 else if (i >= LPFC_MAX_BUCKET_COUNT)
87 i = LPFC_MAX_BUCKET_COUNT - 1;
84 } else { 88 } else {
85 for (i = 0; i < LPFC_MAX_BUCKET_COUNT-1; i++) 89 for (i = 0; i < LPFC_MAX_BUCKET_COUNT-1; i++)
86 if (latency <= (phba->bucket_base + 90 if (latency <= (phba->bucket_base +
@@ -444,14 +448,14 @@ lpfc_new_scsi_buf(struct lpfc_vport *vport)
444 bpl[0].addrLow = le32_to_cpu(putPaddrLow(pdma_phys_fcp_cmd)); 448 bpl[0].addrLow = le32_to_cpu(putPaddrLow(pdma_phys_fcp_cmd));
445 bpl[0].tus.f.bdeSize = sizeof(struct fcp_cmnd); 449 bpl[0].tus.f.bdeSize = sizeof(struct fcp_cmnd);
446 bpl[0].tus.f.bdeFlags = BUFF_TYPE_BDE_64; 450 bpl[0].tus.f.bdeFlags = BUFF_TYPE_BDE_64;
447 bpl[0].tus.w = le32_to_cpu(bpl->tus.w); 451 bpl[0].tus.w = le32_to_cpu(bpl[0].tus.w);
448 452
449 /* Setup the physical region for the FCP RSP */ 453 /* Setup the physical region for the FCP RSP */
450 bpl[1].addrHigh = le32_to_cpu(putPaddrHigh(pdma_phys_fcp_rsp)); 454 bpl[1].addrHigh = le32_to_cpu(putPaddrHigh(pdma_phys_fcp_rsp));
451 bpl[1].addrLow = le32_to_cpu(putPaddrLow(pdma_phys_fcp_rsp)); 455 bpl[1].addrLow = le32_to_cpu(putPaddrLow(pdma_phys_fcp_rsp));
452 bpl[1].tus.f.bdeSize = sizeof(struct fcp_rsp); 456 bpl[1].tus.f.bdeSize = sizeof(struct fcp_rsp);
453 bpl[1].tus.f.bdeFlags = BUFF_TYPE_BDE_64; 457 bpl[1].tus.f.bdeFlags = BUFF_TYPE_BDE_64;
454 bpl[1].tus.w = le32_to_cpu(bpl->tus.w); 458 bpl[1].tus.w = le32_to_cpu(bpl[1].tus.w);
455 459
456 /* 460 /*
457 * Since the IOCB for the FCP I/O is built into this lpfc_scsi_buf, 461 * Since the IOCB for the FCP I/O is built into this lpfc_scsi_buf,
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 4e5b4ee121f1..632feee233ca 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -1259,68 +1259,6 @@ lpfc_sli_handle_mb_event(struct lpfc_hba *phba)
1259} 1259}
1260 1260
1261/** 1261/**
1262 * lpfc_sli_replace_hbqbuff: Replace the HBQ buffer with a new buffer.
1263 * @phba: Pointer to HBA context object.
1264 * @tag: Tag for the HBQ buffer.
1265 *
1266 * This function is called from unsolicited event handler code path to get the
1267 * HBQ buffer associated with an unsolicited iocb. This function is called with
1268 * no lock held. It returns the buffer associated with the given tag and posts
1269 * another buffer to the firmware. Note that the new buffer must be allocated
1270 * before taking the hbalock and that the hba lock must be held until it is
1271 * finished with the hbq entry swap.
1272 **/
1273static struct lpfc_dmabuf *
1274lpfc_sli_replace_hbqbuff(struct lpfc_hba *phba, uint32_t tag)
1275{
1276 struct hbq_dmabuf *hbq_entry, *new_hbq_entry;
1277 uint32_t hbqno;
1278 void *virt; /* virtual address ptr */
1279 dma_addr_t phys; /* mapped address */
1280 unsigned long flags;
1281
1282 hbqno = tag >> 16;
1283 new_hbq_entry = (phba->hbqs[hbqno].hbq_alloc_buffer)(phba);
1284 /* Check whether HBQ is still in use */
1285 spin_lock_irqsave(&phba->hbalock, flags);
1286 if (!phba->hbq_in_use) {
1287 if (new_hbq_entry)
1288 (phba->hbqs[hbqno].hbq_free_buffer)(phba,
1289 new_hbq_entry);
1290 spin_unlock_irqrestore(&phba->hbalock, flags);
1291 return NULL;
1292 }
1293
1294 hbq_entry = lpfc_sli_hbqbuf_find(phba, tag);
1295 if (hbq_entry == NULL) {
1296 if (new_hbq_entry)
1297 (phba->hbqs[hbqno].hbq_free_buffer)(phba,
1298 new_hbq_entry);
1299 spin_unlock_irqrestore(&phba->hbalock, flags);
1300 return NULL;
1301 }
1302 list_del(&hbq_entry->dbuf.list);
1303
1304 if (new_hbq_entry == NULL) {
1305 list_add_tail(&hbq_entry->dbuf.list, &phba->hbqbuf_in_list);
1306 spin_unlock_irqrestore(&phba->hbalock, flags);
1307 return &hbq_entry->dbuf;
1308 }
1309 new_hbq_entry->tag = -1;
1310 phys = new_hbq_entry->dbuf.phys;
1311 virt = new_hbq_entry->dbuf.virt;
1312 new_hbq_entry->dbuf.phys = hbq_entry->dbuf.phys;
1313 new_hbq_entry->dbuf.virt = hbq_entry->dbuf.virt;
1314 hbq_entry->dbuf.phys = phys;
1315 hbq_entry->dbuf.virt = virt;
1316 lpfc_sli_free_hbq(phba, hbq_entry);
1317 list_add_tail(&new_hbq_entry->dbuf.list, &phba->hbqbuf_in_list);
1318 spin_unlock_irqrestore(&phba->hbalock, flags);
1319
1320 return &new_hbq_entry->dbuf;
1321}
1322
1323/**
1324 * lpfc_sli_get_buff: Get the buffer associated with the buffer tag. 1262 * lpfc_sli_get_buff: Get the buffer associated with the buffer tag.
1325 * @phba: Pointer to HBA context object. 1263 * @phba: Pointer to HBA context object.
1326 * @pring: Pointer to driver SLI ring object. 1264 * @pring: Pointer to driver SLI ring object.
@@ -1334,13 +1272,17 @@ lpfc_sli_replace_hbqbuff(struct lpfc_hba *phba, uint32_t tag)
1334 **/ 1272 **/
1335static struct lpfc_dmabuf * 1273static struct lpfc_dmabuf *
1336lpfc_sli_get_buff(struct lpfc_hba *phba, 1274lpfc_sli_get_buff(struct lpfc_hba *phba,
1337 struct lpfc_sli_ring *pring, 1275 struct lpfc_sli_ring *pring,
1338 uint32_t tag) 1276 uint32_t tag)
1339{ 1277{
1278 struct hbq_dmabuf *hbq_entry;
1279
1340 if (tag & QUE_BUFTAG_BIT) 1280 if (tag & QUE_BUFTAG_BIT)
1341 return lpfc_sli_ring_taggedbuf_get(phba, pring, tag); 1281 return lpfc_sli_ring_taggedbuf_get(phba, pring, tag);
1342 else 1282 hbq_entry = lpfc_sli_hbqbuf_find(phba, tag);
1343 return lpfc_sli_replace_hbqbuff(phba, tag); 1283 if (!hbq_entry)
1284 return NULL;
1285 return &hbq_entry->dbuf;
1344} 1286}
1345 1287
1346 1288
@@ -1372,8 +1314,6 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
1372 match = 0; 1314 match = 0;
1373 irsp = &(saveq->iocb); 1315 irsp = &(saveq->iocb);
1374 1316
1375 if (irsp->ulpStatus == IOSTAT_NEED_BUFFER)
1376 return 1;
1377 if (irsp->ulpCommand == CMD_ASYNC_STATUS) { 1317 if (irsp->ulpCommand == CMD_ASYNC_STATUS) {
1378 if (pring->lpfc_sli_rcv_async_status) 1318 if (pring->lpfc_sli_rcv_async_status)
1379 pring->lpfc_sli_rcv_async_status(phba, pring, saveq); 1319 pring->lpfc_sli_rcv_async_status(phba, pring, saveq);