ieee1394: sbp2: check for DMA mapping failures

Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index 7a8119e..0037305 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -526,26 +526,41 @@
 
 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 @@
 	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 @@
 
 		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 @@
 						&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 @@
 		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 @@
 				(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 @@
 		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 @@
 
 	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 @@
 	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;
 }