On Wed, 2014-07-02 at 17:53 +0200, Stefan Klug wrote:

> @@ -1471,6 +1526,57 @@ static int proc_do_submiturb(struct
> usb_dev_state 
> *ps, struct usbdevfs_urb *uurb
>               }
>               totlen -= u;
>           }
> +    } else if(num_pages) {
> +        pages = kmalloc(num_pages*sizeof(struct page*), GFP_KERNEL);
> +        if(!pages) {
> +            ret = -ENOMEM;
> +            goto error;
> +        }
> +
> +        //create the scatterlist
> +        as->urb->sg = kmalloc(num_pages * sizeof(struct
> scatterlist), 
> GFP_KERNEL);
> +        if (!as->urb->sg) {
> +            ret = -ENOMEM;
> +            goto error;
> +        }
> +
> +        ret = get_user_pages_fast((unsigned long)buf_aligned,
> +                   num_pages,
> +                   is_in,
> +                   pages);
> +
> +        if(ret < 0) {
> +            printk("get_user_pages failed %i\n", ret);
> +            goto error;
> +        }
> +
> +        //did we get all pages?
> +        if(ret < num_pages) {
> +            printk("get_user_pages didn't deliver all pages %i\n",
> ret);
> +            //free the pages and error out
> +            for(i=0; i<ret; i++) {
> +                page_cache_release(pages[i]);
> +            }
> +            ret = -ENOMEM;
> +            goto error;
> +        }
> +
> +        as->is_user_mem = 1;
> +        as->urb->num_sgs = num_pages;
> +        sg_init_table(as->urb->sg, as->urb->num_sgs);
> +
> +        totlen = uurb->buffer_length + buf_offset;
> +        o = buf_offset;
> +        for (i = 0; i < as->urb->num_sgs; i++) {
> +            u = (totlen > PAGE_SIZE) ? PAGE_SIZE : totlen;
> +            u-= o;
> +            sg_set_page(&as->urb->sg[i], pages[i], u, o);
> +            totlen -= u + o;
> +            o = 0;
> +        }
> +
> +        kfree(pages);
> +        pages = NULL;
>       } else if (uurb->buffer_length > 0) {
>           as->urb->transfer_buffer = kmalloc(uurb->buffer_length,
>                   GFP_KERNEL)


One more thing: Where do you check that the memory the user has passed
a pointer to is actually writable? It seems to me that for zerocopy you
must do the check before you submit the URB to the HCD.

        Regards
                Oliver


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to