ieee1394: sbp2: check for DMA mapping failures
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
This commit is contained in:
Родитель
0a77b17c85
Коммит
cd8c79f17a
|
@ -526,26 +526,41 @@ static void sbp2util_write_doorbell(struct work_struct *work)
|
||||||
|
|
||||||
static int sbp2util_create_command_orb_pool(struct sbp2_lu *lu)
|
static int sbp2util_create_command_orb_pool(struct sbp2_lu *lu)
|
||||||
{
|
{
|
||||||
struct sbp2_fwhost_info *hi = lu->hi;
|
|
||||||
struct sbp2_command_info *cmd;
|
struct sbp2_command_info *cmd;
|
||||||
|
struct device *dmadev = lu->hi->host->device.parent;
|
||||||
int i, orbs = sbp2_serialize_io ? 2 : SBP2_MAX_CMDS;
|
int i, orbs = sbp2_serialize_io ? 2 : SBP2_MAX_CMDS;
|
||||||
|
|
||||||
for (i = 0; i < orbs; i++) {
|
for (i = 0; i < orbs; i++) {
|
||||||
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
|
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
|
||||||
if (!cmd)
|
if (!cmd)
|
||||||
return -ENOMEM;
|
goto failed_alloc;
|
||||||
cmd->command_orb_dma = dma_map_single(hi->host->device.parent,
|
|
||||||
&cmd->command_orb,
|
cmd->command_orb_dma =
|
||||||
sizeof(struct sbp2_command_orb),
|
dma_map_single(dmadev, &cmd->command_orb,
|
||||||
DMA_TO_DEVICE);
|
sizeof(struct sbp2_command_orb),
|
||||||
cmd->sge_dma = dma_map_single(hi->host->device.parent,
|
DMA_TO_DEVICE);
|
||||||
&cmd->scatter_gather_element,
|
if (dma_mapping_error(dmadev, cmd->command_orb_dma))
|
||||||
sizeof(cmd->scatter_gather_element),
|
goto failed_orb;
|
||||||
DMA_TO_DEVICE);
|
|
||||||
|
cmd->sge_dma =
|
||||||
|
dma_map_single(dmadev, &cmd->scatter_gather_element,
|
||||||
|
sizeof(cmd->scatter_gather_element),
|
||||||
|
DMA_TO_DEVICE);
|
||||||
|
if (dma_mapping_error(dmadev, cmd->sge_dma))
|
||||||
|
goto failed_sge;
|
||||||
|
|
||||||
INIT_LIST_HEAD(&cmd->list);
|
INIT_LIST_HEAD(&cmd->list);
|
||||||
list_add_tail(&cmd->list, &lu->cmd_orb_completed);
|
list_add_tail(&cmd->list, &lu->cmd_orb_completed);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
failed_sge:
|
||||||
|
dma_unmap_single(dmadev, cmd->command_orb_dma,
|
||||||
|
sizeof(struct sbp2_command_orb), DMA_TO_DEVICE);
|
||||||
|
failed_orb:
|
||||||
|
kfree(cmd);
|
||||||
|
failed_alloc:
|
||||||
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sbp2util_remove_command_orb_pool(struct sbp2_lu *lu,
|
static void sbp2util_remove_command_orb_pool(struct sbp2_lu *lu,
|
||||||
|
@ -1494,14 +1509,16 @@ static int sbp2_agent_reset(struct sbp2_lu *lu, int wait)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb,
|
static int sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb,
|
||||||
struct sbp2_fwhost_info *hi,
|
struct sbp2_fwhost_info *hi,
|
||||||
struct sbp2_command_info *cmd,
|
struct sbp2_command_info *cmd,
|
||||||
unsigned int scsi_use_sg,
|
unsigned int scsi_use_sg,
|
||||||
struct scatterlist *sg,
|
struct scatterlist *sg,
|
||||||
u32 orb_direction,
|
u32 orb_direction,
|
||||||
enum dma_data_direction dma_dir)
|
enum dma_data_direction dma_dir)
|
||||||
{
|
{
|
||||||
|
struct device *dmadev = hi->host->device.parent;
|
||||||
|
|
||||||
cmd->dma_dir = dma_dir;
|
cmd->dma_dir = dma_dir;
|
||||||
orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
|
orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
|
||||||
orb->misc |= ORB_SET_DIRECTION(orb_direction);
|
orb->misc |= ORB_SET_DIRECTION(orb_direction);
|
||||||
|
@ -1511,9 +1528,12 @@ static void sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb,
|
||||||
|
|
||||||
cmd->dma_size = sg->length;
|
cmd->dma_size = sg->length;
|
||||||
cmd->dma_type = CMD_DMA_PAGE;
|
cmd->dma_type = CMD_DMA_PAGE;
|
||||||
cmd->cmd_dma = dma_map_page(hi->host->device.parent,
|
cmd->cmd_dma = dma_map_page(dmadev, sg_page(sg), sg->offset,
|
||||||
sg_page(sg), sg->offset,
|
|
||||||
cmd->dma_size, cmd->dma_dir);
|
cmd->dma_size, cmd->dma_dir);
|
||||||
|
if (dma_mapping_error(dmadev, cmd->cmd_dma)) {
|
||||||
|
cmd->cmd_dma = 0;
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
orb->data_descriptor_lo = cmd->cmd_dma;
|
orb->data_descriptor_lo = cmd->cmd_dma;
|
||||||
orb->misc |= ORB_SET_DATA_SIZE(cmd->dma_size);
|
orb->misc |= ORB_SET_DATA_SIZE(cmd->dma_size);
|
||||||
|
@ -1523,8 +1543,7 @@ static void sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb,
|
||||||
&cmd->scatter_gather_element[0];
|
&cmd->scatter_gather_element[0];
|
||||||
u32 sg_count, sg_len;
|
u32 sg_count, sg_len;
|
||||||
dma_addr_t sg_addr;
|
dma_addr_t sg_addr;
|
||||||
int i, count = dma_map_sg(hi->host->device.parent, sg,
|
int i, count = dma_map_sg(dmadev, sg, scsi_use_sg, dma_dir);
|
||||||
scsi_use_sg, dma_dir);
|
|
||||||
|
|
||||||
cmd->dma_size = scsi_use_sg;
|
cmd->dma_size = scsi_use_sg;
|
||||||
cmd->sge_buffer = sg;
|
cmd->sge_buffer = sg;
|
||||||
|
@ -1533,7 +1552,7 @@ static void sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb,
|
||||||
orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1);
|
orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1);
|
||||||
orb->data_descriptor_lo = cmd->sge_dma;
|
orb->data_descriptor_lo = cmd->sge_dma;
|
||||||
|
|
||||||
dma_sync_single_for_cpu(hi->host->device.parent, cmd->sge_dma,
|
dma_sync_single_for_cpu(dmadev, cmd->sge_dma,
|
||||||
sizeof(cmd->scatter_gather_element),
|
sizeof(cmd->scatter_gather_element),
|
||||||
DMA_TO_DEVICE);
|
DMA_TO_DEVICE);
|
||||||
|
|
||||||
|
@ -1564,22 +1583,23 @@ static void sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb,
|
||||||
(sizeof(struct sbp2_unrestricted_page_table)) *
|
(sizeof(struct sbp2_unrestricted_page_table)) *
|
||||||
sg_count);
|
sg_count);
|
||||||
|
|
||||||
dma_sync_single_for_device(hi->host->device.parent,
|
dma_sync_single_for_device(dmadev, cmd->sge_dma,
|
||||||
cmd->sge_dma,
|
|
||||||
sizeof(cmd->scatter_gather_element),
|
sizeof(cmd->scatter_gather_element),
|
||||||
DMA_TO_DEVICE);
|
DMA_TO_DEVICE);
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sbp2_create_command_orb(struct sbp2_lu *lu,
|
static int sbp2_create_command_orb(struct sbp2_lu *lu,
|
||||||
struct sbp2_command_info *cmd,
|
struct sbp2_command_info *cmd,
|
||||||
struct scsi_cmnd *SCpnt)
|
struct scsi_cmnd *SCpnt)
|
||||||
{
|
{
|
||||||
struct device *dmadev = lu->hi->host->device.parent;
|
struct device *dmadev = lu->hi->host->device.parent;
|
||||||
struct sbp2_command_orb *orb = &cmd->command_orb;
|
struct sbp2_command_orb *orb = &cmd->command_orb;
|
||||||
u32 orb_direction;
|
|
||||||
unsigned int scsi_request_bufflen = scsi_bufflen(SCpnt);
|
unsigned int scsi_request_bufflen = scsi_bufflen(SCpnt);
|
||||||
enum dma_data_direction dma_dir = SCpnt->sc_data_direction;
|
enum dma_data_direction dma_dir = SCpnt->sc_data_direction;
|
||||||
|
u32 orb_direction;
|
||||||
|
int ret;
|
||||||
|
|
||||||
dma_sync_single_for_cpu(dmadev, cmd->command_orb_dma,
|
dma_sync_single_for_cpu(dmadev, cmd->command_orb_dma,
|
||||||
sizeof(struct sbp2_command_orb), DMA_TO_DEVICE);
|
sizeof(struct sbp2_command_orb), DMA_TO_DEVICE);
|
||||||
|
@ -1613,11 +1633,13 @@ static void sbp2_create_command_orb(struct sbp2_lu *lu,
|
||||||
orb->data_descriptor_hi = 0x0;
|
orb->data_descriptor_hi = 0x0;
|
||||||
orb->data_descriptor_lo = 0x0;
|
orb->data_descriptor_lo = 0x0;
|
||||||
orb->misc |= ORB_SET_DIRECTION(1);
|
orb->misc |= ORB_SET_DIRECTION(1);
|
||||||
} else
|
ret = 0;
|
||||||
sbp2_prep_command_orb_sg(orb, lu->hi, cmd, scsi_sg_count(SCpnt),
|
} else {
|
||||||
scsi_sglist(SCpnt),
|
ret = sbp2_prep_command_orb_sg(orb, lu->hi, cmd,
|
||||||
orb_direction, dma_dir);
|
scsi_sg_count(SCpnt),
|
||||||
|
scsi_sglist(SCpnt),
|
||||||
|
orb_direction, dma_dir);
|
||||||
|
}
|
||||||
sbp2util_cpu_to_be32_buffer(orb, sizeof(*orb));
|
sbp2util_cpu_to_be32_buffer(orb, sizeof(*orb));
|
||||||
|
|
||||||
memset(orb->cdb, 0, sizeof(orb->cdb));
|
memset(orb->cdb, 0, sizeof(orb->cdb));
|
||||||
|
@ -1625,6 +1647,7 @@ static void sbp2_create_command_orb(struct sbp2_lu *lu,
|
||||||
|
|
||||||
dma_sync_single_for_device(dmadev, cmd->command_orb_dma,
|
dma_sync_single_for_device(dmadev, cmd->command_orb_dma,
|
||||||
sizeof(struct sbp2_command_orb), DMA_TO_DEVICE);
|
sizeof(struct sbp2_command_orb), DMA_TO_DEVICE);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sbp2_link_orb_command(struct sbp2_lu *lu,
|
static void sbp2_link_orb_command(struct sbp2_lu *lu,
|
||||||
|
@ -1705,9 +1728,10 @@ static int sbp2_send_command(struct sbp2_lu *lu, struct scsi_cmnd *SCpnt,
|
||||||
if (!cmd)
|
if (!cmd)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
sbp2_create_command_orb(lu, cmd, SCpnt);
|
if (sbp2_create_command_orb(lu, cmd, SCpnt))
|
||||||
sbp2_link_orb_command(lu, cmd);
|
return -ENOMEM;
|
||||||
|
|
||||||
|
sbp2_link_orb_command(lu, cmd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче