Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cd8c79f1 authored by Stefan Richter's avatar Stefan Richter
Browse files

ieee1394: sbp2: check for DMA mapping failures

parent 0a77b17c
Loading
Loading
Loading
Loading
+59 −35
Original line number Original line Diff line number Diff line
@@ -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 =
		    dma_map_single(dmadev, &cmd->command_orb,
				   sizeof(struct sbp2_command_orb),
				   sizeof(struct sbp2_command_orb),
				   DMA_TO_DEVICE);
				   DMA_TO_DEVICE);
		cmd->sge_dma = dma_map_single(hi->host->device.parent,
		if (dma_mapping_error(dmadev, cmd->command_orb_dma))
					&cmd->scatter_gather_element,
			goto failed_orb;

		cmd->sge_dma =
		    dma_map_single(dmadev, &cmd->scatter_gather_element,
				   sizeof(cmd->scatter_gather_element),
				   sizeof(cmd->scatter_gather_element),
				   DMA_TO_DEVICE);
				   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,7 +1509,7 @@ 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,
@@ -1502,6 +1517,8 @@ static void sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb,
				    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 {
		ret = sbp2_prep_command_orb_sg(orb, lu->hi, cmd,
					       scsi_sg_count(SCpnt),
					       scsi_sglist(SCpnt),
					       scsi_sglist(SCpnt),
					       orb_direction, dma_dir);
					       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;
}
}