Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

James Smart and committed by
James Bottomley
9f1e1b50 5b75da2f

+23 -74
+6 -1
drivers/scsi/lpfc/lpfc_init.c
··· 255 255 /* character array used for decoding dist type. */ 256 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 260 return; 261 + } 260 262 261 263 prg = (struct prog_id *) &prog_id_word; 262 264 ··· 276 274 sprintf(phba->OptionROMVersion, "%d.%d%d%c%d", 277 275 prg->ver, prg->rev, prg->lev, 278 276 dist, prg->num); 277 + mempool_free(pmboxq, phba->mbox_mem_pool); 279 278 return; 280 279 } 281 280 ··· 2892 2889 lpfc_stop_phba_timers(phba); 2893 2890 phba->pport->work_port_events = 0; 2894 2891 lpfc_disable_intr(phba); 2892 + lpfc_sli_hba_down(phba); 2893 + lpfc_sli_brdrestart(phba); 2895 2894 out_free_sysfs_attr: 2896 2895 lpfc_free_sysfs_attr(vport); 2897 2896 out_destroy_port:
+9 -5
drivers/scsi/lpfc/lpfc_scsi.c
··· 66 66 if (cmd->result) 67 67 return; 68 68 69 + latency = jiffies_to_msecs((long)jiffies - (long)lpfc_cmd->start_time); 70 + 69 71 spin_lock_irqsave(shost->host_lock, flags); 70 72 if (!vport->stat_data_enabled || 71 73 vport->stat_data_blocked || ··· 76 74 spin_unlock_irqrestore(shost->host_lock, flags); 77 75 return; 78 76 } 79 - latency = jiffies_to_msecs(jiffies - lpfc_cmd->start_time); 80 77 81 78 if (phba->bucket_type == LPFC_LINEAR_BUCKET) { 82 79 i = (latency + phba->bucket_step - 1 - phba->bucket_base)/ 83 80 phba->bucket_step; 84 - if (i >= LPFC_MAX_BUCKET_COUNT) 85 - i = LPFC_MAX_BUCKET_COUNT; 81 + /* check array subscript bounds */ 82 + if (i < 0) 83 + i = 0; 84 + else if (i >= LPFC_MAX_BUCKET_COUNT) 85 + i = LPFC_MAX_BUCKET_COUNT - 1; 86 86 } else { 87 87 for (i = 0; i < LPFC_MAX_BUCKET_COUNT-1; i++) 88 88 if (latency <= (phba->bucket_base + ··· 448 444 bpl[0].addrLow = le32_to_cpu(putPaddrLow(pdma_phys_fcp_cmd)); 449 445 bpl[0].tus.f.bdeSize = sizeof(struct fcp_cmnd); 450 446 bpl[0].tus.f.bdeFlags = BUFF_TYPE_BDE_64; 451 - bpl[0].tus.w = le32_to_cpu(bpl->tus.w); 447 + bpl[0].tus.w = le32_to_cpu(bpl[0].tus.w); 452 448 453 449 /* Setup the physical region for the FCP RSP */ 454 450 bpl[1].addrHigh = le32_to_cpu(putPaddrHigh(pdma_phys_fcp_rsp)); 455 451 bpl[1].addrLow = le32_to_cpu(putPaddrLow(pdma_phys_fcp_rsp)); 456 452 bpl[1].tus.f.bdeSize = sizeof(struct fcp_rsp); 457 453 bpl[1].tus.f.bdeFlags = BUFF_TYPE_BDE_64; 458 - bpl[1].tus.w = le32_to_cpu(bpl->tus.w); 454 + bpl[1].tus.w = le32_to_cpu(bpl[1].tus.w); 459 455 460 456 /* 461 457 * Since the IOCB for the FCP I/O is built into this lpfc_scsi_buf,
+8 -68
drivers/scsi/lpfc/lpfc_sli.c
··· 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 - **/ 1273 - static struct lpfc_dmabuf * 1274 - lpfc_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 1262 * lpfc_sli_get_buff: Get the buffer associated with the buffer tag. 1325 1263 * @phba: Pointer to HBA context object. 1326 1264 * @pring: Pointer to driver SLI ring object. ··· 1272 1334 **/ 1273 1335 static struct lpfc_dmabuf * 1274 1336 lpfc_sli_get_buff(struct lpfc_hba *phba, 1275 - struct lpfc_sli_ring *pring, 1276 - uint32_t tag) 1337 + struct lpfc_sli_ring *pring, 1338 + uint32_t tag) 1277 1339 { 1340 + struct hbq_dmabuf *hbq_entry; 1341 + 1278 1342 if (tag & QUE_BUFTAG_BIT) 1279 1343 return lpfc_sli_ring_taggedbuf_get(phba, pring, tag); 1280 - else 1281 - return lpfc_sli_replace_hbqbuff(phba, tag); 1344 + hbq_entry = lpfc_sli_hbqbuf_find(phba, tag); 1345 + if (!hbq_entry) 1346 + return NULL; 1347 + return &hbq_entry->dbuf; 1282 1348 } 1283 1349 1284 1350 ··· 1314 1372 match = 0; 1315 1373 irsp = &(saveq->iocb); 1316 1374 1317 - if (irsp->ulpStatus == IOSTAT_NEED_BUFFER) 1318 - return 1; 1319 1375 if (irsp->ulpCommand == CMD_ASYNC_STATUS) { 1320 1376 if (pring->lpfc_sli_rcv_async_status) 1321 1377 pring->lpfc_sli_rcv_async_status(phba, pring, saveq);