diff options
author | James Smart <James.Smart@Emulex.Com> | 2008-12-04 22:39:40 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-12-29 12:24:27 -0500 |
commit | 9f1e1b50ab43a281dbc75c25f11e1926a9ea367a (patch) | |
tree | a88f66e6205bd1dbff333b1a9da9fb62cd6f0cd5 /drivers/scsi/lpfc/lpfc_sli.c | |
parent | 5b75da2fa2c9570c3c3dbb2f63cae5b4183e0ca3 (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/lpfc/lpfc_sli.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 76 |
1 files changed, 8 insertions, 68 deletions
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 | **/ | ||
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 | * 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 | **/ |
1335 | static struct lpfc_dmabuf * | 1273 | static struct lpfc_dmabuf * |
1336 | lpfc_sli_get_buff(struct lpfc_hba *phba, | 1274 | lpfc_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); |