linux-next: manual merge of the kmap_atomic tree with the staging tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Cong,

Today's linux-next merge of the kmap_atomic tree got a conflict in
drivers/staging/hv/storvsc_drv.c between various commits from the staging
tree and commit c41a603a7235 ("hv: remove the second argument of k
[un]map_atomic()") from the kmap_atomic tree.

I fixed it up (see below) and can carry the fix as necessary.
-- 
Cheers,
Stephen Rothwell                    sfr@xxxxxxxxxxxxxxxx

diff --cc drivers/staging/hv/storvsc_drv.c
index 695ffc3,ddbdec8..0000000
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@@ -408,339 -398,113 +408,335 @@@ get_in_err
  
  }
  
 -static int storvsc_channel_init(struct hv_device *device)
 +static void destroy_bounce_buffer(struct scatterlist *sgl,
 +				  unsigned int sg_count)
  {
 -	struct storvsc_device *stor_device;
 -	struct hv_storvsc_request *request;
 -	struct vstor_packet *vstor_packet;
 -	int ret, t;
 +	int i;
 +	struct page *page_buf;
  
 -	stor_device = get_out_stor_device(device);
 -	if (!stor_device)
 -		return -ENODEV;
 +	for (i = 0; i < sg_count; i++) {
 +		page_buf = sg_page((&sgl[i]));
 +		if (page_buf != NULL)
 +			__free_page(page_buf);
 +	}
  
 -	request = &stor_device->init_request;
 -	vstor_packet = &request->vstor_packet;
 +	kfree(sgl);
 +}
  
 -	/*
 -	 * Now, initiate the vsc/vsp initialization protocol on the open
 -	 * channel
 -	 */
 -	memset(request, 0, sizeof(struct hv_storvsc_request));
 -	init_completion(&request->wait_event);
 -	vstor_packet->operation = VSTOR_OPERATION_BEGIN_INITIALIZATION;
 -	vstor_packet->flags = REQUEST_COMPLETION_FLAG;
 +static int do_bounce_buffer(struct scatterlist *sgl, unsigned int sg_count)
 +{
 +	int i;
  
 -	ret = vmbus_sendpacket(device->channel, vstor_packet,
 -			       sizeof(struct vstor_packet),
 -			       (unsigned long)request,
 -			       VM_PKT_DATA_INBAND,
 -			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
 -	if (ret != 0)
 -		goto cleanup;
 +	/* No need to check */
 +	if (sg_count < 2)
 +		return -1;
  
 -	t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
 -	if (t == 0) {
 -		ret = -ETIMEDOUT;
 -		goto cleanup;
 +	/* We have at least 2 sg entries */
 +	for (i = 0; i < sg_count; i++) {
 +		if (i == 0) {
 +			/* make sure 1st one does not have hole */
 +			if (sgl[i].offset + sgl[i].length != PAGE_SIZE)
 +				return i;
 +		} else if (i == sg_count - 1) {
 +			/* make sure last one does not have hole */
 +			if (sgl[i].offset != 0)
 +				return i;
 +		} else {
 +			/* make sure no hole in the middle */
 +			if (sgl[i].length != PAGE_SIZE || sgl[i].offset != 0)
 +				return i;
 +		}
  	}
 +	return -1;
 +}
  
 -	if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO ||
 -	    vstor_packet->status != 0)
 -		goto cleanup;
 -
 -
 -	/* reuse the packet for version range supported */
 -	memset(vstor_packet, 0, sizeof(struct vstor_packet));
 -	vstor_packet->operation = VSTOR_OPERATION_QUERY_PROTOCOL_VERSION;
 -	vstor_packet->flags = REQUEST_COMPLETION_FLAG;
 +static struct scatterlist *create_bounce_buffer(struct scatterlist *sgl,
 +						unsigned int sg_count,
 +						unsigned int len,
 +						int write)
 +{
 +	int i;
 +	int num_pages;
 +	struct scatterlist *bounce_sgl;
 +	struct page *page_buf;
 +	unsigned int buf_len = ((write == WRITE_TYPE) ? 0 : PAGE_SIZE);
  
 -	vstor_packet->version.major_minor = VMSTOR_PROTOCOL_VERSION_CURRENT;
 -	FILL_VMSTOR_REVISION(vstor_packet->version.revision);
 +	num_pages = ALIGN(len, PAGE_SIZE) >> PAGE_SHIFT;
  
 -	ret = vmbus_sendpacket(device->channel, vstor_packet,
 -			       sizeof(struct vstor_packet),
 -			       (unsigned long)request,
 -			       VM_PKT_DATA_INBAND,
 -			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
 -	if (ret != 0)
 -		goto cleanup;
 +	bounce_sgl = kcalloc(num_pages, sizeof(struct scatterlist), GFP_ATOMIC);
 +	if (!bounce_sgl)
 +		return NULL;
  
 -	t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
 -	if (t == 0) {
 -		ret = -ETIMEDOUT;
 -		goto cleanup;
 +	for (i = 0; i < num_pages; i++) {
 +		page_buf = alloc_page(GFP_ATOMIC);
 +		if (!page_buf)
 +			goto cleanup;
 +		sg_set_page(&bounce_sgl[i], page_buf, buf_len, 0);
  	}
  
 -	if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO ||
 -	    vstor_packet->status != 0)
 -		goto cleanup;
 +	return bounce_sgl;
  
 +cleanup:
 +	destroy_bounce_buffer(bounce_sgl, num_pages);
 +	return NULL;
 +}
  
 -	memset(vstor_packet, 0, sizeof(struct vstor_packet));
 -	vstor_packet->operation = VSTOR_OPERATION_QUERY_PROPERTIES;
 -	vstor_packet->flags = REQUEST_COMPLETION_FLAG;
 -	vstor_packet->storage_channel_properties.port_number =
 -					stor_device->port_number;
 +/* Assume the original sgl has enough room */
 +static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl,
 +					    struct scatterlist *bounce_sgl,
 +					    unsigned int orig_sgl_count,
 +					    unsigned int bounce_sgl_count)
 +{
 +	int i;
 +	int j = 0;
 +	unsigned long src, dest;
 +	unsigned int srclen, destlen, copylen;
 +	unsigned int total_copied = 0;
 +	unsigned long bounce_addr = 0;
 +	unsigned long dest_addr = 0;
 +	unsigned long flags;
  
 -	ret = vmbus_sendpacket(device->channel, vstor_packet,
 -			       sizeof(struct vstor_packet),
 -			       (unsigned long)request,
 -			       VM_PKT_DATA_INBAND,
 -			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
 +	local_irq_save(flags);
  
 -	if (ret != 0)
 -		goto cleanup;
 +	for (i = 0; i < orig_sgl_count; i++) {
- 		dest_addr = (unsigned long)kmap_atomic(sg_page((&orig_sgl[i])),
- 					KM_IRQ0) + orig_sgl[i].offset;
++		dest_addr = (unsigned long)kmap_atomic(sg_page((&orig_sgl[i])))
++					+ orig_sgl[i].offset;
 +		dest = dest_addr;
 +		destlen = orig_sgl[i].length;
  
 -	t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
 -	if (t == 0) {
 -		ret = -ETIMEDOUT;
 -		goto cleanup;
 -	}
 +		if (bounce_addr == 0)
 +			bounce_addr =
- 			(unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])),
- 							KM_IRQ0);
++			(unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])));
  
 -	if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO ||
 -	    vstor_packet->status != 0)
 -		goto cleanup;
 +		while (destlen) {
 +			src = bounce_addr + bounce_sgl[j].offset;
 +			srclen = bounce_sgl[j].length - bounce_sgl[j].offset;
  
 -	stor_device->path_id = vstor_packet->storage_channel_properties.path_id;
 -	stor_device->target_id
 -		= vstor_packet->storage_channel_properties.target_id;
 +			copylen = min(srclen, destlen);
 +			memcpy((void *)dest, (void *)src, copylen);
  
 -	memset(vstor_packet, 0, sizeof(struct vstor_packet));
 -	vstor_packet->operation = VSTOR_OPERATION_END_INITIALIZATION;
 -	vstor_packet->flags = REQUEST_COMPLETION_FLAG;
 +			total_copied += copylen;
 +			bounce_sgl[j].offset += copylen;
 +			destlen -= copylen;
 +			dest += copylen;
  
 -	ret = vmbus_sendpacket(device->channel, vstor_packet,
 -			       sizeof(struct vstor_packet),
 -			       (unsigned long)request,
 -			       VM_PKT_DATA_INBAND,
 -			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
 +			if (bounce_sgl[j].offset == bounce_sgl[j].length) {
 +				/* full */
- 				kunmap_atomic((void *)bounce_addr, KM_IRQ0);
++				kunmap_atomic((void *)bounce_addr);
 +				j++;
 +
 +				/*
 +				 * It is possible that the number of elements
 +				 * in the bounce buffer may not be equal to
 +				 * the number of elements in the original
 +				 * scatter list. Handle this correctly.
 +				 */
 +
 +				if (j == bounce_sgl_count) {
 +					/*
 +					 * We are done; cleanup and return.
 +					 */
 +					kunmap_atomic((void *)(dest_addr -
- 							orig_sgl[i].offset),
- 							KM_IRQ0);
++							orig_sgl[i].offset));
 +					local_irq_restore(flags);
 +					return total_copied;
 +				}
 +
 +				/* if we need to use another bounce buffer */
 +				if (destlen || i != orig_sgl_count - 1)
 +					bounce_addr =
 +					(unsigned long)kmap_atomic(
- 					sg_page((&bounce_sgl[j])), KM_IRQ0);
++					sg_page((&bounce_sgl[j])));
 +			} else if (destlen == 0 && i == orig_sgl_count - 1) {
 +				/* unmap the last bounce that is < PAGE_SIZE */
- 				kunmap_atomic((void *)bounce_addr, KM_IRQ0);
++				kunmap_atomic((void *)bounce_addr);
 +			}
 +		}
 +
- 		kunmap_atomic((void *)(dest_addr - orig_sgl[i].offset),
- 			      KM_IRQ0);
++		kunmap_atomic((void *)(dest_addr - orig_sgl[i].offset));
 +	}
 +
 +	local_irq_restore(flags);
 +
 +	return total_copied;
 +}
 +
 +/* Assume the bounce_sgl has enough room ie using the create_bounce_buffer() */
 +static unsigned int copy_to_bounce_buffer(struct scatterlist *orig_sgl,
 +					  struct scatterlist *bounce_sgl,
 +					  unsigned int orig_sgl_count)
 +{
 +	int i;
 +	int j = 0;
 +	unsigned long src, dest;
 +	unsigned int srclen, destlen, copylen;
 +	unsigned int total_copied = 0;
 +	unsigned long bounce_addr = 0;
 +	unsigned long src_addr = 0;
 +	unsigned long flags;
 +
 +	local_irq_save(flags);
 +
 +	for (i = 0; i < orig_sgl_count; i++) {
- 		src_addr = (unsigned long)kmap_atomic(sg_page((&orig_sgl[i])),
- 				KM_IRQ0) + orig_sgl[i].offset;
++		src_addr = (unsigned long)kmap_atomic(sg_page((&orig_sgl[i])))
++				+ orig_sgl[i].offset;
 +		src = src_addr;
 +		srclen = orig_sgl[i].length;
 +
 +		if (bounce_addr == 0)
 +			bounce_addr =
- 			(unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])),
- 						KM_IRQ0);
++			(unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])));
 +
 +		while (srclen) {
 +			/* assume bounce offset always == 0 */
 +			dest = bounce_addr + bounce_sgl[j].length;
 +			destlen = PAGE_SIZE - bounce_sgl[j].length;
 +
 +			copylen = min(srclen, destlen);
 +			memcpy((void *)dest, (void *)src, copylen);
 +
 +			total_copied += copylen;
 +			bounce_sgl[j].length += copylen;
 +			srclen -= copylen;
 +			src += copylen;
 +
 +			if (bounce_sgl[j].length == PAGE_SIZE) {
 +				/* full..move to next entry */
- 				kunmap_atomic((void *)bounce_addr, KM_IRQ0);
++				kunmap_atomic((void *)bounce_addr);
 +				j++;
 +
 +				/* if we need to use another bounce buffer */
 +				if (srclen || i != orig_sgl_count - 1)
 +					bounce_addr =
 +					(unsigned long)kmap_atomic(
- 					sg_page((&bounce_sgl[j])), KM_IRQ0);
++					sg_page((&bounce_sgl[j])));
 +
 +			} else if (srclen == 0 && i == orig_sgl_count - 1) {
 +				/* unmap the last bounce that is < PAGE_SIZE */
- 				kunmap_atomic((void *)bounce_addr, KM_IRQ0);
++				kunmap_atomic((void *)bounce_addr);
 +			}
 +		}
 +
- 		kunmap_atomic((void *)(src_addr - orig_sgl[i].offset), KM_IRQ0);
++		kunmap_atomic((void *)(src_addr - orig_sgl[i].offset));
 +	}
 +
 +	local_irq_restore(flags);
 +
 +	return total_copied;
 +}
 +
 +static int storvsc_channel_init(struct hv_device *device)
 +{
 +	struct storvsc_device *stor_device;
 +	struct storvsc_cmd_request *request;
 +	struct vstor_packet *vstor_packet;
 +	int ret, t;
 +
 +	stor_device = get_out_stor_device(device);
 +	if (!stor_device)
 +		return -ENODEV;
 +
 +	request = &stor_device->init_request;
 +	vstor_packet = &request->vstor_packet;
 +
 +	/*
 +	 * Now, initiate the vsc/vsp initialization protocol on the open
 +	 * channel
 +	 */
 +	memset(request, 0, sizeof(struct storvsc_cmd_request));
 +	init_completion(&request->wait_event);
 +	vstor_packet->operation = VSTOR_OPERATION_BEGIN_INITIALIZATION;
 +	vstor_packet->flags = REQUEST_COMPLETION_FLAG;
 +
 +	ret = vmbus_sendpacket(device->channel, vstor_packet,
 +			       sizeof(struct vstor_packet),
 +			       (unsigned long)request,
 +			       VM_PKT_DATA_INBAND,
 +			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
 +	if (ret != 0)
 +		goto cleanup;
 +
 +	t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
 +	if (t == 0) {
 +		ret = -ETIMEDOUT;
 +		goto cleanup;
 +	}
 +
 +	if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO ||
 +	    vstor_packet->status != 0)
 +		goto cleanup;
 +
 +
 +	/* reuse the packet for version range supported */
 +	memset(vstor_packet, 0, sizeof(struct vstor_packet));
 +	vstor_packet->operation = VSTOR_OPERATION_QUERY_PROTOCOL_VERSION;
 +	vstor_packet->flags = REQUEST_COMPLETION_FLAG;
 +
 +	vstor_packet->version.major_minor =
 +		storvsc_get_version(VMSTOR_CURRENT_MAJOR, VMSTOR_CURRENT_MINOR);
 +
 +	/*
 +	 * The revision number is only used in Windows; set it to 0.
 +	 */
 +	vstor_packet->version.revision = 0;
 +
 +	ret = vmbus_sendpacket(device->channel, vstor_packet,
 +			       sizeof(struct vstor_packet),
 +			       (unsigned long)request,
 +			       VM_PKT_DATA_INBAND,
 +			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
 +	if (ret != 0)
 +		goto cleanup;
 +
 +	t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
 +	if (t == 0) {
 +		ret = -ETIMEDOUT;
 +		goto cleanup;
 +	}
 +
 +	if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO ||
 +	    vstor_packet->status != 0)
 +		goto cleanup;
 +
 +
 +	memset(vstor_packet, 0, sizeof(struct vstor_packet));
 +	vstor_packet->operation = VSTOR_OPERATION_QUERY_PROPERTIES;
 +	vstor_packet->flags = REQUEST_COMPLETION_FLAG;
 +	vstor_packet->storage_channel_properties.port_number =
 +					stor_device->port_number;
 +
 +	ret = vmbus_sendpacket(device->channel, vstor_packet,
 +			       sizeof(struct vstor_packet),
 +			       (unsigned long)request,
 +			       VM_PKT_DATA_INBAND,
 +			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
 +
 +	if (ret != 0)
 +		goto cleanup;
 +
 +	t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
 +	if (t == 0) {
 +		ret = -ETIMEDOUT;
 +		goto cleanup;
 +	}
 +
 +	if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO ||
 +	    vstor_packet->status != 0)
 +		goto cleanup;
 +
 +	stor_device->path_id = vstor_packet->storage_channel_properties.path_id;
 +	stor_device->target_id
 +		= vstor_packet->storage_channel_properties.target_id;
 +
 +	memset(vstor_packet, 0, sizeof(struct vstor_packet));
 +	vstor_packet->operation = VSTOR_OPERATION_END_INITIALIZATION;
 +	vstor_packet->flags = REQUEST_COMPLETION_FLAG;
 +
 +	ret = vmbus_sendpacket(device->channel, vstor_packet,
 +			       sizeof(struct vstor_packet),
 +			       (unsigned long)request,
 +			       VM_PKT_DATA_INBAND,
 +			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
  
  	if (ret != 0)
  		goto cleanup;

Attachment: pgprXew1Yp6r4.pgp
Description: PGP signature


[Index of Archives]     [Linux Kernel]     [Linux USB Development]     [Yosemite News]     [Linux SCSI]

  Powered by Linux