Re: Infrastructure for zerocopy I/O

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

 



On Mon, 7 Dec 2015, Steinar H. Gunderson wrote:

> On Mon, Dec 07, 2015 at 10:45:55AM -0500, Alan Stern wrote:
> >> Here we are. Lightly tested, I believe all comments should be addressed.
> > This looks quite good.  I have only a couple of comments.
> 
> Excellent. I'm sorry we've needed so many rounds; this is what happens when
> you pick up someone else's patch against a code base you've never touched
> before. :-)

Of course.  And this was not a particularly simple patch.

> +static void dec_usb_memory_use_count(struct usb_memory *usbm, int *count)
> +{
> +	struct usb_dev_state *ps = usbm->ps;
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&ps->lock, flags);
> +	--*count;
> +	if (usbm->urb_use_count == 0 && usbm->vma_use_count == 0) {
> +		list_del(&usbm->memlist);
> +		spin_unlock_irqrestore(&ps->lock, flags);
> +
> +		usb_free_coherent(ps->dev, usbm->size, usbm->mem,
> +				usbm->dma_handle);
> +		usbfs_decrease_memory_usage(
> +			usbm->size + sizeof(struct usb_memory));
> +		kfree(usbm);
> +	} else {
> +		spin_unlock_irqrestore(&ps->lock, flags);
> +	}
> +}

> +static int usbdev_mmap(struct file *file, struct vm_area_struct *vma)
> +{
> +	struct usb_memory *usbm = NULL;
> +	struct usb_dev_state *ps = file->private_data;
> +	size_t size = vma->vm_end - vma->vm_start;
> +	void *mem;
> +	unsigned long flags;
> +	dma_addr_t dma_handle;
> +	int ret;
> +
> +	ret = usbfs_increase_memory_usage(size + sizeof(struct usb_memory));
> +	if (ret) {
> +		return ret;
> +	}
> +
> +	usbm = kzalloc(sizeof(struct usb_memory), GFP_KERNEL);
> +	if (!usbm) {
> +		usbfs_decrease_memory_usage(
> +				size + sizeof(struct usb_memory));
> +		return -ENOMEM;
> +	}
> +
> +	mem = usb_alloc_coherent(ps->dev, size, GFP_KERNEL, &dma_handle);
> +	if (!mem) {
> +		usbfs_decrease_memory_usage(
> +				size + sizeof(struct usb_memory));
> +		kfree(usbm);
> +		return -ENOMEM;
> +	}
> +
> +	memset(mem, 0, size);
> +
> +	usbm->mem = mem;
> +	usbm->dma_handle = dma_handle;
> +	usbm->size = size;
> +	usbm->ps = ps;
> +	usbm->vm_start = vma->vm_start;
> +	usbm->vma_use_count = 1;
> +
> +	if (remap_pfn_range(vma, vma->vm_start,
> +			virt_to_phys(usbm->mem) >> PAGE_SHIFT,
> +			size, vma->vm_page_prot) < 0) {
> +		dec_usb_memory_use_count(usbm, &usbm->vma_use_count);
> +		return -EAGAIN;
> +	}

I just noticed this -- usbm->memlist needs to be initialized before
dec_usb_memory_use_count() can be called.  INIT_LIST_HEAD before the
"if" statement will fix the problem.

The patch could use one more ingredient.  In
include/uapi/linux/usbdevicefs_h, add a #define for USBDEVFS_CAP_MMAP
and fix up proc_get_capabilities() to report the new capability.  In
theory, user programs could just try an mmap() call and see if it
works, but this seems cleaner.

Alan Stern

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux