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

Commit 97d552e3 authored by Stefan Richter's avatar Stefan Richter
Browse files

ieee1394: sbp2: fix bogus dma mapping

Need to use a PCI device, not a FireWire host device.  Problem found by
Andreas Schwab, mistake pointed out by Benjamin Herrenschmidt.
http://ozlabs.org/pipermail/linuxppc-dev/2006-December/029595.html



Signed-off-by: default avatarStefan Richter <stefanr@s5r6.in-berlin.de>
Tested-by: default avatarAndreas Schwab <schwab@suse.de>
parent b2bb550c
Loading
Loading
Loading
Loading
+40 −33
Original line number Original line Diff line number Diff line
@@ -490,11 +490,11 @@ static int sbp2util_create_command_orb_pool(struct sbp2_lu *lu)
			spin_unlock_irqrestore(&lu->cmd_orb_lock, flags);
			spin_unlock_irqrestore(&lu->cmd_orb_lock, flags);
			return -ENOMEM;
			return -ENOMEM;
		}
		}
		cmd->command_orb_dma = dma_map_single(&hi->host->device,
		cmd->command_orb_dma = dma_map_single(hi->host->device.parent,
						&cmd->command_orb,
						&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,
		cmd->sge_dma = dma_map_single(hi->host->device.parent,
					&cmd->scatter_gather_element,
					&cmd->scatter_gather_element,
					sizeof(cmd->scatter_gather_element),
					sizeof(cmd->scatter_gather_element),
					DMA_BIDIRECTIONAL);
					DMA_BIDIRECTIONAL);
@@ -516,10 +516,11 @@ static void sbp2util_remove_command_orb_pool(struct sbp2_lu *lu)
	if (!list_empty(&lu->cmd_orb_completed))
	if (!list_empty(&lu->cmd_orb_completed))
		list_for_each_safe(lh, next, &lu->cmd_orb_completed) {
		list_for_each_safe(lh, next, &lu->cmd_orb_completed) {
			cmd = list_entry(lh, struct sbp2_command_info, list);
			cmd = list_entry(lh, struct sbp2_command_info, list);
			dma_unmap_single(&host->device, cmd->command_orb_dma,
			dma_unmap_single(host->device.parent,
					 cmd->command_orb_dma,
					 sizeof(struct sbp2_command_orb),
					 sizeof(struct sbp2_command_orb),
					 DMA_TO_DEVICE);
					 DMA_TO_DEVICE);
			dma_unmap_single(&host->device, cmd->sge_dma,
			dma_unmap_single(host->device.parent, cmd->sge_dma,
					 sizeof(cmd->scatter_gather_element),
					 sizeof(cmd->scatter_gather_element),
					 DMA_BIDIRECTIONAL);
					 DMA_BIDIRECTIONAL);
			kfree(cmd);
			kfree(cmd);
@@ -601,17 +602,17 @@ static void sbp2util_mark_command_completed(struct sbp2_lu *lu,


	if (cmd->cmd_dma) {
	if (cmd->cmd_dma) {
		if (cmd->dma_type == CMD_DMA_SINGLE)
		if (cmd->dma_type == CMD_DMA_SINGLE)
			dma_unmap_single(&host->device, cmd->cmd_dma,
			dma_unmap_single(host->device.parent, cmd->cmd_dma,
					 cmd->dma_size, cmd->dma_dir);
					 cmd->dma_size, cmd->dma_dir);
		else if (cmd->dma_type == CMD_DMA_PAGE)
		else if (cmd->dma_type == CMD_DMA_PAGE)
			dma_unmap_page(&host->device, cmd->cmd_dma,
			dma_unmap_page(host->device.parent, cmd->cmd_dma,
				       cmd->dma_size, cmd->dma_dir);
				       cmd->dma_size, cmd->dma_dir);
		/* XXX: Check for CMD_DMA_NONE bug */
		/* XXX: Check for CMD_DMA_NONE bug */
		cmd->dma_type = CMD_DMA_NONE;
		cmd->dma_type = CMD_DMA_NONE;
		cmd->cmd_dma = 0;
		cmd->cmd_dma = 0;
	}
	}
	if (cmd->sge_buffer) {
	if (cmd->sge_buffer) {
		dma_unmap_sg(&host->device, cmd->sge_buffer,
		dma_unmap_sg(host->device.parent, cmd->sge_buffer,
			     cmd->dma_size, cmd->dma_dir);
			     cmd->dma_size, cmd->dma_dir);
		cmd->sge_buffer = NULL;
		cmd->sge_buffer = NULL;
	}
	}
@@ -836,37 +837,37 @@ static int sbp2_start_device(struct sbp2_lu *lu)
	struct sbp2_fwhost_info *hi = lu->hi;
	struct sbp2_fwhost_info *hi = lu->hi;
	int error;
	int error;


	lu->login_response = dma_alloc_coherent(&hi->host->device,
	lu->login_response = dma_alloc_coherent(hi->host->device.parent,
				     sizeof(struct sbp2_login_response),
				     sizeof(struct sbp2_login_response),
				     &lu->login_response_dma, GFP_KERNEL);
				     &lu->login_response_dma, GFP_KERNEL);
	if (!lu->login_response)
	if (!lu->login_response)
		goto alloc_fail;
		goto alloc_fail;


	lu->query_logins_orb = dma_alloc_coherent(&hi->host->device,
	lu->query_logins_orb = dma_alloc_coherent(hi->host->device.parent,
				     sizeof(struct sbp2_query_logins_orb),
				     sizeof(struct sbp2_query_logins_orb),
				     &lu->query_logins_orb_dma, GFP_KERNEL);
				     &lu->query_logins_orb_dma, GFP_KERNEL);
	if (!lu->query_logins_orb)
	if (!lu->query_logins_orb)
		goto alloc_fail;
		goto alloc_fail;


	lu->query_logins_response = dma_alloc_coherent(&hi->host->device,
	lu->query_logins_response = dma_alloc_coherent(hi->host->device.parent,
				     sizeof(struct sbp2_query_logins_response),
				     sizeof(struct sbp2_query_logins_response),
				     &lu->query_logins_response_dma, GFP_KERNEL);
				     &lu->query_logins_response_dma, GFP_KERNEL);
	if (!lu->query_logins_response)
	if (!lu->query_logins_response)
		goto alloc_fail;
		goto alloc_fail;


	lu->reconnect_orb = dma_alloc_coherent(&hi->host->device,
	lu->reconnect_orb = dma_alloc_coherent(hi->host->device.parent,
				     sizeof(struct sbp2_reconnect_orb),
				     sizeof(struct sbp2_reconnect_orb),
				     &lu->reconnect_orb_dma, GFP_KERNEL);
				     &lu->reconnect_orb_dma, GFP_KERNEL);
	if (!lu->reconnect_orb)
	if (!lu->reconnect_orb)
		goto alloc_fail;
		goto alloc_fail;


	lu->logout_orb = dma_alloc_coherent(&hi->host->device,
	lu->logout_orb = dma_alloc_coherent(hi->host->device.parent,
				     sizeof(struct sbp2_logout_orb),
				     sizeof(struct sbp2_logout_orb),
				     &lu->logout_orb_dma, GFP_KERNEL);
				     &lu->logout_orb_dma, GFP_KERNEL);
	if (!lu->logout_orb)
	if (!lu->logout_orb)
		goto alloc_fail;
		goto alloc_fail;


	lu->login_orb = dma_alloc_coherent(&hi->host->device,
	lu->login_orb = dma_alloc_coherent(hi->host->device.parent,
				     sizeof(struct sbp2_login_orb),
				     sizeof(struct sbp2_login_orb),
				     &lu->login_orb_dma, GFP_KERNEL);
				     &lu->login_orb_dma, GFP_KERNEL);
	if (!lu->login_orb)
	if (!lu->login_orb)
@@ -929,32 +930,32 @@ static void sbp2_remove_device(struct sbp2_lu *lu)
	list_del(&lu->lu_list);
	list_del(&lu->lu_list);


	if (lu->login_response)
	if (lu->login_response)
		dma_free_coherent(&hi->host->device,
		dma_free_coherent(hi->host->device.parent,
				    sizeof(struct sbp2_login_response),
				    sizeof(struct sbp2_login_response),
				    lu->login_response,
				    lu->login_response,
				    lu->login_response_dma);
				    lu->login_response_dma);
	if (lu->login_orb)
	if (lu->login_orb)
		dma_free_coherent(&hi->host->device,
		dma_free_coherent(hi->host->device.parent,
				    sizeof(struct sbp2_login_orb),
				    sizeof(struct sbp2_login_orb),
				    lu->login_orb,
				    lu->login_orb,
				    lu->login_orb_dma);
				    lu->login_orb_dma);
	if (lu->reconnect_orb)
	if (lu->reconnect_orb)
		dma_free_coherent(&hi->host->device,
		dma_free_coherent(hi->host->device.parent,
				    sizeof(struct sbp2_reconnect_orb),
				    sizeof(struct sbp2_reconnect_orb),
				    lu->reconnect_orb,
				    lu->reconnect_orb,
				    lu->reconnect_orb_dma);
				    lu->reconnect_orb_dma);
	if (lu->logout_orb)
	if (lu->logout_orb)
		dma_free_coherent(&hi->host->device,
		dma_free_coherent(hi->host->device.parent,
				    sizeof(struct sbp2_logout_orb),
				    sizeof(struct sbp2_logout_orb),
				    lu->logout_orb,
				    lu->logout_orb,
				    lu->logout_orb_dma);
				    lu->logout_orb_dma);
	if (lu->query_logins_orb)
	if (lu->query_logins_orb)
		dma_free_coherent(&hi->host->device,
		dma_free_coherent(hi->host->device.parent,
				    sizeof(struct sbp2_query_logins_orb),
				    sizeof(struct sbp2_query_logins_orb),
				    lu->query_logins_orb,
				    lu->query_logins_orb,
				    lu->query_logins_orb_dma);
				    lu->query_logins_orb_dma);
	if (lu->query_logins_response)
	if (lu->query_logins_response)
		dma_free_coherent(&hi->host->device,
		dma_free_coherent(hi->host->device.parent,
				    sizeof(struct sbp2_query_logins_response),
				    sizeof(struct sbp2_query_logins_response),
				    lu->query_logins_response,
				    lu->query_logins_response,
				    lu->query_logins_response_dma);
				    lu->query_logins_response_dma);
@@ -1445,7 +1446,7 @@ static void sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb,


		cmd->dma_size = sgpnt[0].length;
		cmd->dma_size = sgpnt[0].length;
		cmd->dma_type = CMD_DMA_PAGE;
		cmd->dma_type = CMD_DMA_PAGE;
		cmd->cmd_dma = dma_map_page(&hi->host->device,
		cmd->cmd_dma = dma_map_page(hi->host->device.parent,
					    sgpnt[0].page, sgpnt[0].offset,
					    sgpnt[0].page, sgpnt[0].offset,
					    cmd->dma_size, cmd->dma_dir);
					    cmd->dma_size, cmd->dma_dir);


@@ -1457,8 +1458,8 @@ 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, sgpnt, scsi_use_sg,
		int i, count = dma_map_sg(hi->host->device.parent, sgpnt,
					  dma_dir);
					  scsi_use_sg, dma_dir);


		cmd->dma_size = scsi_use_sg;
		cmd->dma_size = scsi_use_sg;
		cmd->sge_buffer = sgpnt;
		cmd->sge_buffer = sgpnt;
@@ -1508,7 +1509,8 @@ static void sbp2_prep_command_orb_no_sg(struct sbp2_command_orb *orb,
	cmd->dma_dir = dma_dir;
	cmd->dma_dir = dma_dir;
	cmd->dma_size = scsi_request_bufflen;
	cmd->dma_size = scsi_request_bufflen;
	cmd->dma_type = CMD_DMA_SINGLE;
	cmd->dma_type = CMD_DMA_SINGLE;
	cmd->cmd_dma = dma_map_single(&hi->host->device, scsi_request_buffer,
	cmd->cmd_dma = dma_map_single(hi->host->device.parent,
				      scsi_request_buffer,
				      cmd->dma_size, cmd->dma_dir);
				      cmd->dma_size, cmd->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);
@@ -1626,10 +1628,11 @@ static void sbp2_link_orb_command(struct sbp2_lu *lu,
	size_t length;
	size_t length;
	unsigned long flags;
	unsigned long flags;


	dma_sync_single_for_device(&hi->host->device, cmd->command_orb_dma,
	dma_sync_single_for_device(hi->host->device.parent,
				   cmd->command_orb_dma,
				   sizeof(struct sbp2_command_orb),
				   sizeof(struct sbp2_command_orb),
				   DMA_TO_DEVICE);
				   DMA_TO_DEVICE);
	dma_sync_single_for_device(&hi->host->device, cmd->sge_dma,
	dma_sync_single_for_device(hi->host->device.parent, cmd->sge_dma,
				   sizeof(cmd->scatter_gather_element),
				   sizeof(cmd->scatter_gather_element),
				   DMA_BIDIRECTIONAL);
				   DMA_BIDIRECTIONAL);


@@ -1655,14 +1658,15 @@ static void sbp2_link_orb_command(struct sbp2_lu *lu,
		 * The target's fetch agent may or may not have read this
		 * The target's fetch agent may or may not have read this
		 * previous ORB yet.
		 * previous ORB yet.
		 */
		 */
		dma_sync_single_for_cpu(&hi->host->device, last_orb_dma,
		dma_sync_single_for_cpu(hi->host->device.parent, last_orb_dma,
					sizeof(struct sbp2_command_orb),
					sizeof(struct sbp2_command_orb),
					DMA_TO_DEVICE);
					DMA_TO_DEVICE);
		last_orb->next_ORB_lo = cpu_to_be32(cmd->command_orb_dma);
		last_orb->next_ORB_lo = cpu_to_be32(cmd->command_orb_dma);
		wmb();
		wmb();
		/* Tells hardware that this pointer is valid */
		/* Tells hardware that this pointer is valid */
		last_orb->next_ORB_hi = 0;
		last_orb->next_ORB_hi = 0;
		dma_sync_single_for_device(&hi->host->device, last_orb_dma,
		dma_sync_single_for_device(hi->host->device.parent,
					   last_orb_dma,
					   sizeof(struct sbp2_command_orb),
					   sizeof(struct sbp2_command_orb),
					   DMA_TO_DEVICE);
					   DMA_TO_DEVICE);
		addr += SBP2_DOORBELL_OFFSET;
		addr += SBP2_DOORBELL_OFFSET;
@@ -1790,10 +1794,11 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid,
	else
	else
		cmd = sbp2util_find_command_for_orb(lu, sb->ORB_offset_lo);
		cmd = sbp2util_find_command_for_orb(lu, sb->ORB_offset_lo);
	if (cmd) {
	if (cmd) {
		dma_sync_single_for_cpu(&hi->host->device, cmd->command_orb_dma,
		dma_sync_single_for_cpu(hi->host->device.parent,
					cmd->command_orb_dma,
					sizeof(struct sbp2_command_orb),
					sizeof(struct sbp2_command_orb),
					DMA_TO_DEVICE);
					DMA_TO_DEVICE);
		dma_sync_single_for_cpu(&hi->host->device, cmd->sge_dma,
		dma_sync_single_for_cpu(hi->host->device.parent, cmd->sge_dma,
					sizeof(cmd->scatter_gather_element),
					sizeof(cmd->scatter_gather_element),
					DMA_BIDIRECTIONAL);
					DMA_BIDIRECTIONAL);
		/* Grab SCSI command pointers and check status. */
		/* Grab SCSI command pointers and check status. */
@@ -1921,10 +1926,11 @@ static void sbp2scsi_complete_all_commands(struct sbp2_lu *lu, u32 status)
	while (!list_empty(&lu->cmd_orb_inuse)) {
	while (!list_empty(&lu->cmd_orb_inuse)) {
		lh = lu->cmd_orb_inuse.next;
		lh = lu->cmd_orb_inuse.next;
		cmd = list_entry(lh, struct sbp2_command_info, list);
		cmd = list_entry(lh, struct sbp2_command_info, list);
		dma_sync_single_for_cpu(&hi->host->device, cmd->command_orb_dma,
		dma_sync_single_for_cpu(hi->host->device.parent,
				        cmd->command_orb_dma,
					sizeof(struct sbp2_command_orb),
					sizeof(struct sbp2_command_orb),
					DMA_TO_DEVICE);
					DMA_TO_DEVICE);
		dma_sync_single_for_cpu(&hi->host->device, cmd->sge_dma,
		dma_sync_single_for_cpu(hi->host->device.parent, cmd->sge_dma,
					sizeof(cmd->scatter_gather_element),
					sizeof(cmd->scatter_gather_element),
					DMA_BIDIRECTIONAL);
					DMA_BIDIRECTIONAL);
		sbp2util_mark_command_completed(lu, cmd);
		sbp2util_mark_command_completed(lu, cmd);
@@ -2049,11 +2055,12 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt)
		spin_lock_irqsave(&lu->cmd_orb_lock, flags);
		spin_lock_irqsave(&lu->cmd_orb_lock, flags);
		cmd = sbp2util_find_command_for_SCpnt(lu, SCpnt);
		cmd = sbp2util_find_command_for_SCpnt(lu, SCpnt);
		if (cmd) {
		if (cmd) {
			dma_sync_single_for_cpu(&hi->host->device,
			dma_sync_single_for_cpu(hi->host->device.parent,
					cmd->command_orb_dma,
					cmd->command_orb_dma,
					sizeof(struct sbp2_command_orb),
					sizeof(struct sbp2_command_orb),
					DMA_TO_DEVICE);
					DMA_TO_DEVICE);
			dma_sync_single_for_cpu(&hi->host->device, cmd->sge_dma,
			dma_sync_single_for_cpu(hi->host->device.parent,
					cmd->sge_dma,
					sizeof(cmd->scatter_gather_element),
					sizeof(cmd->scatter_gather_element),
					DMA_BIDIRECTIONAL);
					DMA_BIDIRECTIONAL);
			sbp2util_mark_command_completed(lu, cmd);
			sbp2util_mark_command_completed(lu, cmd);