Commit 6389a775 authored by Dave Jiang's avatar Dave Jiang Committed by Dan Williams
Browse files

isci: have the driver use native SG calls and DMA-API



Remove abstraction for SG building and get rid of callbacks for getting
DMA memory mapping.

Signed-off-by: default avatarDave Jiang <dave.jiang@intel.com>
Signed-off-by: default avatarDan Williams <dan.j.williams@intel.com>
parent 103a00c2
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -84,3 +84,18 @@ void *scic_request_get_virt_addr(struct scic_sds_request *sci_req, dma_addr_t ph
	return (char *)ireq + offset;
}

dma_addr_t scic_io_request_get_dma_addr(struct scic_sds_request *sds_request,
					void *virt_addr)
{
	struct isci_request *isci_request =
		(struct isci_request *)sci_object_get_association(sds_request);

	char *requested_addr = (char *)virt_addr;
	char *base_addr = (char *)isci_request;

	BUG_ON(requested_addr < base_addr);
	BUG_ON((requested_addr - base_addr) >=
			isci_request->request_alloc_size);

	return isci_request->request_daddr + (requested_addr - base_addr);
}
+3 −0
Original line number Diff line number Diff line
@@ -102,4 +102,7 @@ void scic_word_copy_with_swap(u32 *destination, u32 *source, u32 word_count);
void *scic_request_get_virt_addr(struct scic_sds_request *sds_request,
				 dma_addr_t phys_addr);

dma_addr_t scic_io_request_get_dma_addr(struct scic_sds_request *sds_request,
					void *virt_addr);

#endif /* _SCI_UTIL_H_ */
+108 −100
Original line number Diff line number Diff line
@@ -259,56 +259,70 @@ static struct scu_sgl_element_pair *scic_sds_request_get_sgl_element_pair(
 *    the Scatter-Gather List.
 *
 */
void scic_sds_request_build_sgl(
	struct scic_sds_request *this_request)
void scic_sds_request_build_sgl(struct scic_sds_request *sds_request)
{
	void *os_sge;
	void *os_handle;
	dma_addr_t physical_address;
	u32 sgl_pair_index = 0;
	struct scu_sgl_element_pair *scu_sgl_list   = NULL;
	struct scu_sgl_element_pair *previous_pair  = NULL;

	os_handle = scic_sds_request_get_user_request(this_request);
	scic_cb_io_request_get_next_sge(os_handle, NULL, &os_sge);

	while (os_sge != NULL) {
		scu_sgl_list =
			scic_sds_request_get_sgl_element_pair(this_request, sgl_pair_index);

		SCU_SGL_COPY(os_handle, scu_sgl_list->A, os_sge);
	struct isci_request *isci_request =
		(struct isci_request *)sci_object_get_association(sds_request);
	struct isci_host *isci_host = isci_request->isci_host;
	struct sas_task *task = isci_request_access_task(isci_request);
	struct scatterlist *sg = NULL;
	dma_addr_t dma_addr;
	u32 sg_idx = 0;
	struct scu_sgl_element_pair *scu_sg   = NULL;
	struct scu_sgl_element_pair *prev_sg  = NULL;

	if (task->num_scatter > 0) {
		sg = task->scatter;

		while (sg) {
			scu_sg = scic_sds_request_get_sgl_element_pair(
					sds_request,
					sg_idx);

			SCU_SGL_COPY(scu_sg->A, sg);

			sg = sg_next(sg);

			if (sg) {
				SCU_SGL_COPY(scu_sg->B, sg);
				sg = sg_next(sg);
			} else
				SCU_SGL_ZERO(scu_sg->B);

		scic_cb_io_request_get_next_sge(os_handle, os_sge, &os_sge);
			if (prev_sg) {
				dma_addr =
					scic_io_request_get_dma_addr(
							sds_request,
							scu_sg);

		if (os_sge != NULL) {
			SCU_SGL_COPY(os_handle, scu_sgl_list->B, os_sge);
				prev_sg->next_pair_upper =
					upper_32_bits(dma_addr);
				prev_sg->next_pair_lower =
					lower_32_bits(dma_addr);
			}

			scic_cb_io_request_get_next_sge(os_handle, os_sge, &os_sge);
		} else {
			SCU_SGL_ZERO(scu_sgl_list->B);
			prev_sg = scu_sg;
			sg_idx++;
		}
	} else {	/* handle when no sg */
		scu_sg = scic_sds_request_get_sgl_element_pair(sds_request,
							       sg_idx);

		if (previous_pair != NULL) {
			scic_cb_io_request_get_physical_address(
				scic_sds_request_get_controller(this_request),
				this_request,
				scu_sgl_list,
				&physical_address
				);
		dma_addr = dma_map_single(&isci_host->pdev->dev,
					  task->scatter,
					  task->total_xfer_len,
					  task->data_dir);

			previous_pair->next_pair_upper =
				upper_32_bits(physical_address);
			previous_pair->next_pair_lower =
				lower_32_bits(physical_address);
		}
		isci_request->zero_scatter_daddr = dma_addr;

		previous_pair = scu_sgl_list;
		sgl_pair_index++;
		scu_sg->A.length = task->total_xfer_len;
		scu_sg->A.address_upper = upper_32_bits(dma_addr);
		scu_sg->A.address_lower = lower_32_bits(dma_addr);
	}

	if (scu_sgl_list != NULL) {
		scu_sgl_list->next_pair_upper = 0;
		scu_sgl_list->next_pair_lower = 0;
	if (scu_sg) {
		scu_sg->next_pair_upper = 0;
		scu_sg->next_pair_lower = 0;
	}
}

@@ -473,17 +487,17 @@ static void scic_sds_task_request_build_ssp_task_iu(
 *
 */
static void scu_ssp_reqeust_construct_task_context(
	struct scic_sds_request *this_request,
	struct scic_sds_request *sds_request,
	struct scu_task_context *task_context)
{
	dma_addr_t physical_address;
	struct scic_sds_controller *owning_controller;
	dma_addr_t dma_addr;
	struct scic_sds_controller *controller;
	struct scic_sds_remote_device *target_device;
	struct scic_sds_port *target_port;

	owning_controller = scic_sds_request_get_controller(this_request);
	target_device = scic_sds_request_get_device(this_request);
	target_port = scic_sds_request_get_port(this_request);
	controller = scic_sds_request_get_controller(sds_request);
	target_device = scic_sds_request_get_device(sds_request);
	target_port = scic_sds_request_get_port(sds_request);

	/* Fill in the TC with the its required data */
	task_context->abort = 0;
@@ -492,7 +506,7 @@ static void scu_ssp_reqeust_construct_task_context(
	task_context->connection_rate =
		scic_remote_device_get_connection_rate(target_device);
	task_context->protocol_engine_index =
		scic_sds_controller_get_protocol_engine_group(owning_controller);
		scic_sds_controller_get_protocol_engine_group(controller);
	task_context->logical_port_index =
		scic_sds_port_get_index(target_port);
	task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SSP;
@@ -500,7 +514,7 @@ static void scu_ssp_reqeust_construct_task_context(
	task_context->context_type = SCU_TASK_CONTEXT_TYPE;

	task_context->remote_node_index =
		scic_sds_remote_device_get_index(this_request->target_device);
		scic_sds_remote_device_get_index(sds_request->target_device);
	task_context->command_code = 0;

	task_context->link_layer_control = 0;
@@ -515,61 +529,55 @@ static void scu_ssp_reqeust_construct_task_context(
	/* task_context->type.ssp.tag = this_request->io_tag; */
	task_context->task_phase = 0x01;

	if (this_request->was_tag_assigned_by_user) {
		/* Build the task context now since we have already read the data */
		this_request->post_context = (
			SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC
			| (
				scic_sds_controller_get_protocol_engine_group(owning_controller)
				<< SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT
				)
			| (
				scic_sds_port_get_index(target_port)
				<< SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT
				)
			| scic_sds_io_tag_get_index(this_request->io_tag)
			);
	if (sds_request->was_tag_assigned_by_user) {
		/*
		 * Build the task context now since we have already read
		 * the data
		 */
		sds_request->post_context =
			(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC |
			 (scic_sds_controller_get_protocol_engine_group(
							controller) <<
			  SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) |
			 (scic_sds_port_get_index(target_port) <<
			  SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) |
			 scic_sds_io_tag_get_index(sds_request->io_tag));
	} else {
		/* Build the task context now since we have already read the data */
		this_request->post_context = (
			SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC
			| (
				scic_sds_controller_get_protocol_engine_group(owning_controller)
				<< SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT
				)
			| (
				scic_sds_port_get_index(target_port)
				<< SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT
				)
			/* This is not assigned because we have to wait until we get a TCi */
			);
		/*
		 * Build the task context now since we have already read
		 * the data
		 *
		 * I/O tag index is not assigned because we have to wait
		 * until we get a TCi
		 */
		sds_request->post_context =
			(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC |
			 (scic_sds_controller_get_protocol_engine_group(
							owning_controller) <<
			  SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) |
			 (scic_sds_port_get_index(target_port) <<
			  SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT));
	}

	/* Copy the physical address for the command buffer to the SCU Task Context */
	scic_cb_io_request_get_physical_address(
		scic_sds_request_get_controller(this_request),
		this_request,
		this_request->command_buffer,
		&physical_address
		);
	/*
	 * Copy the physical address for the command buffer to the
	 * SCU Task Context
	 */
	dma_addr = scic_io_request_get_dma_addr(sds_request,
						sds_request->command_buffer);

	task_context->command_iu_upper =
		upper_32_bits(physical_address);
	task_context->command_iu_lower =
		lower_32_bits(physical_address);
	task_context->command_iu_upper = upper_32_bits(dma_addr);
	task_context->command_iu_lower = lower_32_bits(dma_addr);

	/* Copy the physical address for the response buffer to the SCU Task Context */
	scic_cb_io_request_get_physical_address(
		scic_sds_request_get_controller(this_request),
		this_request,
		this_request->response_buffer,
		&physical_address
		);
	/*
	 * Copy the physical address for the response buffer to the
	 * SCU Task Context
	 */
	dma_addr = scic_io_request_get_dma_addr(sds_request,
						sds_request->response_buffer);

	task_context->response_iu_upper =
		upper_32_bits(physical_address);
	task_context->response_iu_lower =
		lower_32_bits(physical_address);
	task_context->response_iu_upper = upper_32_bits(dma_addr);
	task_context->response_iu_lower = lower_32_bits(dma_addr);
}

/**
+4 −5
Original line number Diff line number Diff line
@@ -389,14 +389,13 @@ extern const struct scic_sds_io_request_state_handler scic_sds_smp_request_start
 * This macro copys the SGL Element data from the host os to the hardware SGL
 * elment data
 */
#define SCU_SGL_COPY(os_handle, scu_sge, os_sge) \
#define SCU_SGL_COPY(scu_sge, os_sge) \
	{ \
		(scu_sge).length = \
			scic_cb_sge_get_length_field(os_handle, os_sge); \
		(scu_sge).length = sg_dma_len(sg); \
		(scu_sge).address_upper = \
			upper_32_bits(scic_cb_sge_get_address_field(os_handle, os_sge)); \
			upper_32_bits(sg_dma_address(sg)); \
		(scu_sge).address_lower = \
			lower_32_bits(scic_cb_sge_get_address_field(os_handle, os_sge)); \
			lower_32_bits(sg_dma_address(sg)); \
		(scu_sge).address_modifier = 0;	\
	}

+59 −60
Original line number Diff line number Diff line
@@ -234,37 +234,36 @@ enum sci_status scic_io_request_construct_smp(
 *
 */
static void scu_smp_request_construct_task_context(
	struct scic_sds_request *this_request,
	struct scic_sds_request *sds_request,
	struct smp_request *smp_request)
{
	dma_addr_t physical_address;
	struct scic_sds_controller *owning_controller;
	dma_addr_t dma_addr;
	struct scic_sds_controller *controller;
	struct scic_sds_remote_device *target_device;
	struct scic_sds_port *target_port;
	struct scu_task_context *task_context;

	/* byte swap the smp request. */
	scic_word_copy_with_swap(
		this_request->command_buffer,
	scic_word_copy_with_swap(sds_request->command_buffer,
				 (u32 *)smp_request,
		sizeof(struct smp_request) / sizeof(u32)
		);
				 sizeof(struct smp_request) / sizeof(u32));

	task_context = scic_sds_request_get_task_context(this_request);
	task_context = scic_sds_request_get_task_context(sds_request);

	owning_controller = scic_sds_request_get_controller(this_request);
	target_device = scic_sds_request_get_device(this_request);
	target_port = scic_sds_request_get_port(this_request);
	controller = scic_sds_request_get_controller(sds_request);
	target_device = scic_sds_request_get_device(sds_request);
	target_port = scic_sds_request_get_port(sds_request);

	/*
	 * Fill in the TC with the its required data
	 * 00h */
	 * 00h
	 */
	task_context->priority = 0;
	task_context->initiator_request = 1;
	task_context->connection_rate =
		scic_remote_device_get_connection_rate(target_device);
	task_context->protocol_engine_index =
		scic_sds_controller_get_protocol_engine_group(owning_controller);
		scic_sds_controller_get_protocol_engine_group(controller);
	task_context->logical_port_index =
		scic_sds_port_get_index(target_port);
	task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SMP;
@@ -273,7 +272,8 @@ static void scu_smp_request_construct_task_context(
	task_context->context_type = SCU_TASK_CONTEXT_TYPE;

	/* 04h */
	task_context->remote_node_index = this_request->target_device->rnc->remote_node_index;
	task_context->remote_node_index =
		sds_request->target_device->rnc->remote_node_index;
	task_context->command_code = 0;
	task_context->task_type = SCU_TASK_TYPE_SMP_REQUEST;

@@ -289,7 +289,8 @@ static void scu_smp_request_construct_task_context(
	task_context->address_modifier = 0;

	/* 10h */
	task_context->ssp_command_iu_length = smp_request->header.request_length;
	task_context->ssp_command_iu_length =
		smp_request->header.request_length;

	/* 14h */
	task_context->transfer_length_bytes = 0;
@@ -298,59 +299,57 @@ static void scu_smp_request_construct_task_context(
	 * 18h ~ 30h, protocol specific
	 * since commandIU has been build by framework at this point, we just
	 * copy the frist DWord from command IU to this location. */
	memcpy((void *)(&task_context->type.smp), this_request->command_buffer, sizeof(u32));
	memcpy((void *)(&task_context->type.smp),
	       sds_request->command_buffer,
	       sizeof(u32));

	/*
	 * 40h
	 * "For SMP you could program it to zero. We would prefer that way so that
	 * done code will be consistent." - Venki */
	 * "For SMP you could program it to zero. We would prefer that way
	 * so that done code will be consistent." - Venki
	 */
	task_context->task_phase = 0;

	if (this_request->was_tag_assigned_by_user) {
		/* Build the task context now since we have already read the data */
		this_request->post_context = (
			SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC
			| (
				scic_sds_controller_get_protocol_engine_group(owning_controller)
				<< SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT
				)
			| (
				scic_sds_port_get_index(target_port)
				<< SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT
				)
			| scic_sds_io_tag_get_index(this_request->io_tag)
			);
	if (sds_request->was_tag_assigned_by_user) {
		/*
		 * Build the task context now since we have already read
		 * the data
		 */
		sds_request->post_context =
			(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC |
			 (scic_sds_controller_get_protocol_engine_group(
							controller) <<
			  SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) |
			 (scic_sds_port_get_index(target_port) <<
			  SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) |
			 scic_sds_io_tag_get_index(sds_request->io_tag));
	} else {
		/* Build the task context now since we have already read the data */
		this_request->post_context = (
			SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC
			| (
				scic_sds_controller_get_protocol_engine_group(owning_controller)
				<< SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT
				)
			| (
				scic_sds_port_get_index(target_port)
				<< SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT
				)
			/* This is not assigned because we have to wait until we get a TCi */
			);
		/*
		 * Build the task context now since we have already read
		 * the data.
		 * I/O tag index is not assigned because we have to wait
		 * until we get a TCi.
		 */
		sds_request->post_context =
			(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC |
			 (scic_sds_controller_get_protocol_engine_group(
							controller) <<
			  SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) |
			 (scic_sds_port_get_index(target_port) <<
			  SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT));
	}

	/*
	 * Copy the physical address for the command buffer to the SCU Task Context
	 * command buffer should not contain command header. */
	scic_cb_io_request_get_physical_address(
		scic_sds_request_get_controller(this_request),
		this_request,
		((char *)(this_request->command_buffer) + sizeof(u32)),
		&physical_address
		);

	task_context->command_iu_upper =
		upper_32_bits(physical_address);
	task_context->command_iu_lower =
		lower_32_bits(physical_address);
	 * Copy the physical address for the command buffer to the SCU Task
	 * Context command buffer should not contain command header.
	 */
	dma_addr = scic_io_request_get_dma_addr(sds_request,
						(char *)
						(sds_request->command_buffer) +
						sizeof(u32));

	task_context->command_iu_upper = upper_32_bits(dma_addr);
	task_context->command_iu_lower = lower_32_bits(dma_addr);

	/* SMP response comes as UF, so no need to set response IU address. */
	task_context->response_iu_upper = 0;
Loading