ieee1394: sbp2: check for DMA mapping failures
authorStefan Richter <stefanr@s5r6.in-berlin.de>
Sat, 9 Aug 2008 18:16:24 +0000 (20:16 +0200)
committerStefan Richter <stefanr@s5r6.in-berlin.de>
Wed, 15 Oct 2008 20:21:07 +0000 (22:21 +0200)
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
drivers/ieee1394/sbp2.c

index 7a8119e0c9107e27d40ef75333fdd00f7ddd0509..0037305f599ef1e6e8fefb8630c25e2d476c1df2 100644 (file)
@@ -526,26 +526,41 @@ static void sbp2util_write_doorbell(struct work_struct *work)
 
 static int sbp2util_create_command_orb_pool(struct sbp2_lu *lu)
 {
-       struct sbp2_fwhost_info *hi = lu->hi;
        struct sbp2_command_info *cmd;
+       struct device *dmadev = lu->hi->host->device.parent;
        int i, orbs = sbp2_serialize_io ? 2 : SBP2_MAX_CMDS;
 
        for (i = 0; i < orbs; i++) {
                cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
                if (!cmd)
-                       return -ENOMEM;
-               cmd->command_orb_dma = dma_map_single(hi->host->device.parent,
-                                               &cmd->command_orb,
-                                               sizeof(struct sbp2_command_orb),
-                                               DMA_TO_DEVICE);
-               cmd->sge_dma = dma_map_single(hi->host->device.parent,
-                                       &cmd->scatter_gather_element,
-                                       sizeof(cmd->scatter_gather_element),
-                                       DMA_TO_DEVICE);
+                       goto failed_alloc;
+
+               cmd->command_orb_dma =
+                   dma_map_single(dmadev, &cmd->command_orb,
+                                  sizeof(struct sbp2_command_orb),
+                                  DMA_TO_DEVICE);
+               if (dma_mapping_error(dmadev, cmd->command_orb_dma))
+                       goto failed_orb;
+
+               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);
                list_add_tail(&cmd->list, &lu->cmd_orb_completed);
        }
        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,
@@ -1494,14 +1509,16 @@ static int sbp2_agent_reset(struct sbp2_lu *lu, int wait)
        return 0;
 }
 
-static void sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb,
-                                    struct sbp2_fwhost_info *hi,
-                                    struct sbp2_command_info *cmd,
-                                    unsigned int scsi_use_sg,
-                                    struct scatterlist *sg,
-                                    u32 orb_direction,
-                                    enum dma_data_direction dma_dir)
+static int sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb,
+                                   struct sbp2_fwhost_info *hi,
+                                   struct sbp2_command_info *cmd,
+                                   unsigned int scsi_use_sg,
+                                   struct scatterlist *sg,
+                                   u32 orb_direction,
+                                   enum dma_data_direction dma_dir)
 {
+       struct device *dmadev = hi->host->device.parent;
+
        cmd->dma_dir = dma_dir;
        orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
        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_type = CMD_DMA_PAGE;
-               cmd->cmd_dma = dma_map_page(hi->host->device.parent,
-                                           sg_page(sg), sg->offset,
+               cmd->cmd_dma = dma_map_page(dmadev, sg_page(sg), sg->offset,
                                            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->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];
                u32 sg_count, sg_len;
                dma_addr_t sg_addr;
-               int i, count = dma_map_sg(hi->host->device.parent, sg,
-                                         scsi_use_sg, dma_dir);
+               int i, count = dma_map_sg(dmadev, sg, scsi_use_sg, dma_dir);
 
                cmd->dma_size = scsi_use_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->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),
                                        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)) *
                                sg_count);
 
-               dma_sync_single_for_device(hi->host->device.parent,
-                                          cmd->sge_dma,
+               dma_sync_single_for_device(dmadev, cmd->sge_dma,
                                           sizeof(cmd->scatter_gather_element),
                                           DMA_TO_DEVICE);
        }
+       return 0;
 }
 
-static void sbp2_create_command_orb(struct sbp2_lu *lu,
-                                   struct sbp2_command_info *cmd,
-                                   struct scsi_cmnd *SCpnt)
+static int sbp2_create_command_orb(struct sbp2_lu *lu,
+                                  struct sbp2_command_info *cmd,
+                                  struct scsi_cmnd *SCpnt)
 {
        struct device *dmadev = lu->hi->host->device.parent;
        struct sbp2_command_orb *orb = &cmd->command_orb;
-       u32 orb_direction;
        unsigned int scsi_request_bufflen = scsi_bufflen(SCpnt);
        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,
                                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_lo = 0x0;
                orb->misc |= ORB_SET_DIRECTION(1);
-       } else
-               sbp2_prep_command_orb_sg(orb, lu->hi, cmd, scsi_sg_count(SCpnt),
-                                        scsi_sglist(SCpnt),
-                                        orb_direction, dma_dir);
-
+               ret = 0;
+       } else {
+               ret = sbp2_prep_command_orb_sg(orb, lu->hi, cmd,
+                                              scsi_sg_count(SCpnt),
+                                              scsi_sglist(SCpnt),
+                                              orb_direction, dma_dir);
+       }
        sbp2util_cpu_to_be32_buffer(orb, sizeof(*orb));
 
        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,
                        sizeof(struct sbp2_command_orb), DMA_TO_DEVICE);
+       return ret;
 }
 
 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)
                return -EIO;
 
-       sbp2_create_command_orb(lu, cmd, SCpnt);
-       sbp2_link_orb_command(lu, cmd);
+       if (sbp2_create_command_orb(lu, cmd, SCpnt))
+               return -ENOMEM;
 
+       sbp2_link_orb_command(lu, cmd);
        return 0;
 }