diff options
| author | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2009-01-27 19:03:34 -0500 |
|---|---|---|
| committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2009-01-28 14:31:08 -0500 |
| commit | 5e2125677fd72d36396cc537466e07ffcbbd4b2b (patch) | |
| tree | ad20a0cf11e5cafa83064412ccf91c05baba6e2e | |
| parent | f746072abc12d0e10ecd7847f1846157fde15987 (diff) | |
firewire: sbp2: fix DMA mapping leak on the failure path
Reported-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
who also provided a first version of the fix.
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
| -rw-r--r-- | drivers/firewire/fw-sbp2.c | 27 |
1 files changed, 17 insertions, 10 deletions
diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c index 5739caaaec7b..6635925a3758 100644 --- a/drivers/firewire/fw-sbp2.c +++ b/drivers/firewire/fw-sbp2.c | |||
| @@ -1284,6 +1284,19 @@ static struct fw_driver sbp2_driver = { | |||
| 1284 | .id_table = sbp2_id_table, | 1284 | .id_table = sbp2_id_table, |
| 1285 | }; | 1285 | }; |
| 1286 | 1286 | ||
| 1287 | static void sbp2_unmap_scatterlist(struct device *card_device, | ||
| 1288 | struct sbp2_command_orb *orb) | ||
| 1289 | { | ||
| 1290 | if (scsi_sg_count(orb->cmd)) | ||
| 1291 | dma_unmap_sg(card_device, scsi_sglist(orb->cmd), | ||
| 1292 | scsi_sg_count(orb->cmd), | ||
| 1293 | orb->cmd->sc_data_direction); | ||
| 1294 | |||
| 1295 | if (orb->request.misc & cpu_to_be32(COMMAND_ORB_PAGE_TABLE_PRESENT)) | ||
| 1296 | dma_unmap_single(card_device, orb->page_table_bus, | ||
| 1297 | sizeof(orb->page_table), DMA_TO_DEVICE); | ||
| 1298 | } | ||
| 1299 | |||
| 1287 | static unsigned int | 1300 | static unsigned int |
| 1288 | sbp2_status_to_sense_data(u8 *sbp2_status, u8 *sense_data) | 1301 | sbp2_status_to_sense_data(u8 *sbp2_status, u8 *sense_data) |
| 1289 | { | 1302 | { |
| @@ -1363,15 +1376,7 @@ complete_command_orb(struct sbp2_orb *base_orb, struct sbp2_status *status) | |||
| 1363 | 1376 | ||
| 1364 | dma_unmap_single(device->card->device, orb->base.request_bus, | 1377 | dma_unmap_single(device->card->device, orb->base.request_bus, |
| 1365 | sizeof(orb->request), DMA_TO_DEVICE); | 1378 | sizeof(orb->request), DMA_TO_DEVICE); |
| 1366 | 1379 | sbp2_unmap_scatterlist(device->card->device, orb); | |
| 1367 | if (scsi_sg_count(orb->cmd) > 0) | ||
| 1368 | dma_unmap_sg(device->card->device, scsi_sglist(orb->cmd), | ||
| 1369 | scsi_sg_count(orb->cmd), | ||
| 1370 | orb->cmd->sc_data_direction); | ||
| 1371 | |||
| 1372 | if (orb->page_table_bus != 0) | ||
| 1373 | dma_unmap_single(device->card->device, orb->page_table_bus, | ||
| 1374 | sizeof(orb->page_table), DMA_TO_DEVICE); | ||
| 1375 | 1380 | ||
| 1376 | orb->cmd->result = result; | 1381 | orb->cmd->result = result; |
| 1377 | orb->done(orb->cmd); | 1382 | orb->done(orb->cmd); |
| @@ -1493,8 +1498,10 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done) | |||
| 1493 | orb->base.request_bus = | 1498 | orb->base.request_bus = |
| 1494 | dma_map_single(device->card->device, &orb->request, | 1499 | dma_map_single(device->card->device, &orb->request, |
| 1495 | sizeof(orb->request), DMA_TO_DEVICE); | 1500 | sizeof(orb->request), DMA_TO_DEVICE); |
| 1496 | if (dma_mapping_error(device->card->device, orb->base.request_bus)) | 1501 | if (dma_mapping_error(device->card->device, orb->base.request_bus)) { |
| 1502 | sbp2_unmap_scatterlist(device->card->device, orb); | ||
| 1497 | goto out; | 1503 | goto out; |
| 1504 | } | ||
| 1498 | 1505 | ||
| 1499 | sbp2_send_orb(&orb->base, lu, lu->tgt->node_id, generation, | 1506 | sbp2_send_orb(&orb->base, lu, lu->tgt->node_id, generation, |
| 1500 | lu->command_block_agent_address + SBP2_ORB_POINTER); | 1507 | lu->command_block_agent_address + SBP2_ORB_POINTER); |
