mirror of https://gitee.com/openkylin/linux.git
[media] staging: easycap: Split buffer and video urb allocation
When the device is probed, this driver allocates frame buffers, field buffers, isoc buffers and urbs. This patch just split this into separate functions, which helps clearing the currently gigantic probe function. Signed-off-by: Ezequiel Garcia <elezegarcia@gmail.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
parent
ab019fd41d
commit
20c50af28a
|
@ -3045,6 +3045,203 @@ static int populate_inputset(struct easycap *peasycap)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int alloc_framebuffers(struct easycap *peasycap)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
void *pbuf;
|
||||||
|
|
||||||
|
JOM(4, "allocating %i frame buffers of size %li\n",
|
||||||
|
FRAME_BUFFER_MANY, (long int)FRAME_BUFFER_SIZE);
|
||||||
|
JOM(4, ".... each scattered over %li pages\n",
|
||||||
|
FRAME_BUFFER_SIZE/PAGE_SIZE);
|
||||||
|
|
||||||
|
for (i = 0; i < FRAME_BUFFER_MANY; i++) {
|
||||||
|
for (j = 0; j < FRAME_BUFFER_SIZE/PAGE_SIZE; j++) {
|
||||||
|
if (peasycap->frame_buffer[i][j].pgo)
|
||||||
|
SAM("attempting to reallocate framebuffers\n");
|
||||||
|
else {
|
||||||
|
pbuf = (void *)__get_free_page(GFP_KERNEL);
|
||||||
|
if (!pbuf) {
|
||||||
|
SAM("ERROR: Could not allocate "
|
||||||
|
"framebuffer %i page %i\n", i, j);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
peasycap->allocation_video_page += 1;
|
||||||
|
peasycap->frame_buffer[i][j].pgo = pbuf;
|
||||||
|
}
|
||||||
|
peasycap->frame_buffer[i][j].pto =
|
||||||
|
peasycap->frame_buffer[i][j].pgo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
peasycap->frame_fill = 0;
|
||||||
|
peasycap->frame_read = 0;
|
||||||
|
JOM(4, "allocation of frame buffers done: %i pages\n", i*j);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int alloc_fieldbuffers(struct easycap *peasycap)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
void *pbuf;
|
||||||
|
|
||||||
|
JOM(4, "allocating %i field buffers of size %li\n",
|
||||||
|
FIELD_BUFFER_MANY, (long int)FIELD_BUFFER_SIZE);
|
||||||
|
JOM(4, ".... each scattered over %li pages\n",
|
||||||
|
FIELD_BUFFER_SIZE/PAGE_SIZE);
|
||||||
|
|
||||||
|
for (i = 0; i < FIELD_BUFFER_MANY; i++) {
|
||||||
|
for (j = 0; j < FIELD_BUFFER_SIZE/PAGE_SIZE; j++) {
|
||||||
|
if (peasycap->field_buffer[i][j].pgo) {
|
||||||
|
SAM("ERROR: attempting to reallocate "
|
||||||
|
"fieldbuffers\n");
|
||||||
|
} else {
|
||||||
|
pbuf = (void *) __get_free_page(GFP_KERNEL);
|
||||||
|
if (!pbuf) {
|
||||||
|
SAM("ERROR: Could not allocate "
|
||||||
|
"fieldbuffer %i page %i\n", i, j);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
peasycap->allocation_video_page += 1;
|
||||||
|
peasycap->field_buffer[i][j].pgo = pbuf;
|
||||||
|
}
|
||||||
|
peasycap->field_buffer[i][j].pto =
|
||||||
|
peasycap->field_buffer[i][j].pgo;
|
||||||
|
}
|
||||||
|
/* TODO: Hardcoded 0x0200 meaning? */
|
||||||
|
peasycap->field_buffer[i][0].kount = 0x0200;
|
||||||
|
}
|
||||||
|
peasycap->field_fill = 0;
|
||||||
|
peasycap->field_page = 0;
|
||||||
|
peasycap->field_read = 0;
|
||||||
|
JOM(4, "allocation of field buffers done: %i pages\n", i*j);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int alloc_isocbuffers(struct easycap *peasycap)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
void *pbuf;
|
||||||
|
|
||||||
|
JOM(4, "allocating %i isoc video buffers of size %i\n",
|
||||||
|
VIDEO_ISOC_BUFFER_MANY,
|
||||||
|
peasycap->video_isoc_buffer_size);
|
||||||
|
JOM(4, ".... each occupying contiguous memory pages\n");
|
||||||
|
|
||||||
|
for (i = 0; i < VIDEO_ISOC_BUFFER_MANY; i++) {
|
||||||
|
pbuf = (void *)__get_free_pages(GFP_KERNEL,
|
||||||
|
VIDEO_ISOC_ORDER);
|
||||||
|
if (!pbuf) {
|
||||||
|
SAM("ERROR: Could not allocate isoc "
|
||||||
|
"video buffer %i\n", i);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
peasycap->allocation_video_page += BIT(VIDEO_ISOC_ORDER);
|
||||||
|
|
||||||
|
peasycap->video_isoc_buffer[i].pgo = pbuf;
|
||||||
|
peasycap->video_isoc_buffer[i].pto =
|
||||||
|
pbuf + peasycap->video_isoc_buffer_size;
|
||||||
|
peasycap->video_isoc_buffer[i].kount = i;
|
||||||
|
}
|
||||||
|
JOM(4, "allocation of isoc video buffers done: %i pages\n",
|
||||||
|
i * (0x01 << VIDEO_ISOC_ORDER));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int create_video_urbs(struct easycap *peasycap)
|
||||||
|
{
|
||||||
|
struct urb *purb;
|
||||||
|
struct data_urb *pdata_urb;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
JOM(4, "allocating %i struct urb.\n", VIDEO_ISOC_BUFFER_MANY);
|
||||||
|
JOM(4, "using %i=peasycap->video_isoc_framesperdesc\n",
|
||||||
|
peasycap->video_isoc_framesperdesc);
|
||||||
|
JOM(4, "using %i=peasycap->video_isoc_maxframesize\n",
|
||||||
|
peasycap->video_isoc_maxframesize);
|
||||||
|
JOM(4, "using %i=peasycap->video_isoc_buffer_sizen",
|
||||||
|
peasycap->video_isoc_buffer_size);
|
||||||
|
|
||||||
|
for (i = 0; i < VIDEO_ISOC_BUFFER_MANY; i++) {
|
||||||
|
purb = usb_alloc_urb(peasycap->video_isoc_framesperdesc,
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!purb) {
|
||||||
|
SAM("ERROR: usb_alloc_urb returned NULL for buffer "
|
||||||
|
"%i\n", i);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
peasycap->allocation_video_urb += 1;
|
||||||
|
pdata_urb = kzalloc(sizeof(struct data_urb), GFP_KERNEL);
|
||||||
|
if (!pdata_urb) {
|
||||||
|
SAM("ERROR: Could not allocate struct data_urb.\n");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
peasycap->allocation_video_struct +=
|
||||||
|
sizeof(struct data_urb);
|
||||||
|
|
||||||
|
pdata_urb->purb = purb;
|
||||||
|
pdata_urb->isbuf = i;
|
||||||
|
pdata_urb->length = 0;
|
||||||
|
list_add_tail(&(pdata_urb->list_head),
|
||||||
|
peasycap->purb_video_head);
|
||||||
|
|
||||||
|
if (!i) {
|
||||||
|
JOM(4, "initializing video urbs thus:\n");
|
||||||
|
JOM(4, " purb->interval = 1;\n");
|
||||||
|
JOM(4, " purb->dev = peasycap->pusb_device;\n");
|
||||||
|
JOM(4, " purb->pipe = usb_rcvisocpipe"
|
||||||
|
"(peasycap->pusb_device,%i);\n",
|
||||||
|
peasycap->video_endpointnumber);
|
||||||
|
JOM(4, " purb->transfer_flags = URB_ISO_ASAP;\n");
|
||||||
|
JOM(4, " purb->transfer_buffer = peasycap->"
|
||||||
|
"video_isoc_buffer[.].pgo;\n");
|
||||||
|
JOM(4, " purb->transfer_buffer_length = %i;\n",
|
||||||
|
peasycap->video_isoc_buffer_size);
|
||||||
|
JOM(4, " purb->complete = easycap_complete;\n");
|
||||||
|
JOM(4, " purb->context = peasycap;\n");
|
||||||
|
JOM(4, " purb->start_frame = 0;\n");
|
||||||
|
JOM(4, " purb->number_of_packets = %i;\n",
|
||||||
|
peasycap->video_isoc_framesperdesc);
|
||||||
|
JOM(4, " for (j = 0; j < %i; j++)\n",
|
||||||
|
peasycap->video_isoc_framesperdesc);
|
||||||
|
JOM(4, " {\n");
|
||||||
|
JOM(4, " purb->iso_frame_desc[j].offset = j*%i;\n",
|
||||||
|
peasycap->video_isoc_maxframesize);
|
||||||
|
JOM(4, " purb->iso_frame_desc[j].length = %i;\n",
|
||||||
|
peasycap->video_isoc_maxframesize);
|
||||||
|
JOM(4, " }\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
purb->interval = 1;
|
||||||
|
purb->dev = peasycap->pusb_device;
|
||||||
|
purb->pipe = usb_rcvisocpipe(peasycap->pusb_device,
|
||||||
|
peasycap->video_endpointnumber);
|
||||||
|
|
||||||
|
purb->transfer_flags = URB_ISO_ASAP;
|
||||||
|
purb->transfer_buffer = peasycap->video_isoc_buffer[i].pgo;
|
||||||
|
purb->transfer_buffer_length =
|
||||||
|
peasycap->video_isoc_buffer_size;
|
||||||
|
|
||||||
|
purb->complete = easycap_complete;
|
||||||
|
purb->context = peasycap;
|
||||||
|
purb->start_frame = 0;
|
||||||
|
purb->number_of_packets = peasycap->video_isoc_framesperdesc;
|
||||||
|
|
||||||
|
for (j = 0; j < peasycap->video_isoc_framesperdesc; j++) {
|
||||||
|
purb->iso_frame_desc[j].offset =
|
||||||
|
j * peasycap->video_isoc_maxframesize;
|
||||||
|
purb->iso_frame_desc[j].length =
|
||||||
|
peasycap->video_isoc_maxframesize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
JOM(4, "allocation of %i struct urb done.\n", i);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct v4l2_file_operations v4l2_fops = {
|
static const struct v4l2_file_operations v4l2_fops = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.open = easycap_open_noinode,
|
.open = easycap_open_noinode,
|
||||||
|
@ -3067,7 +3264,7 @@ static int easycap_usb_probe(struct usb_interface *intf,
|
||||||
struct urb *purb;
|
struct urb *purb;
|
||||||
struct easycap *peasycap;
|
struct easycap *peasycap;
|
||||||
struct data_urb *pdata_urb;
|
struct data_urb *pdata_urb;
|
||||||
int i, j, k, m, rc;
|
int i, j, k, rc;
|
||||||
u8 bInterfaceNumber;
|
u8 bInterfaceNumber;
|
||||||
u8 bInterfaceClass;
|
u8 bInterfaceClass;
|
||||||
u8 bInterfaceSubClass;
|
u8 bInterfaceSubClass;
|
||||||
|
@ -3416,173 +3613,23 @@ static int easycap_usb_probe(struct usb_interface *intf,
|
||||||
*/
|
*/
|
||||||
INIT_LIST_HEAD(&(peasycap->urb_video_head));
|
INIT_LIST_HEAD(&(peasycap->urb_video_head));
|
||||||
peasycap->purb_video_head = &(peasycap->urb_video_head);
|
peasycap->purb_video_head = &(peasycap->urb_video_head);
|
||||||
JOM(4, "allocating %i frame buffers of size %li\n",
|
|
||||||
FRAME_BUFFER_MANY, (long int)FRAME_BUFFER_SIZE);
|
|
||||||
JOM(4, ".... each scattered over %li pages\n",
|
|
||||||
FRAME_BUFFER_SIZE/PAGE_SIZE);
|
|
||||||
|
|
||||||
for (k = 0; k < FRAME_BUFFER_MANY; k++) {
|
rc = alloc_framebuffers(peasycap);
|
||||||
for (m = 0; m < FRAME_BUFFER_SIZE/PAGE_SIZE; m++) {
|
if (rc < 0)
|
||||||
if (peasycap->frame_buffer[k][m].pgo)
|
return rc;
|
||||||
SAM("attempting to reallocate frame "
|
|
||||||
" buffers\n");
|
|
||||||
else {
|
|
||||||
pbuf = (void *)__get_free_page(GFP_KERNEL);
|
|
||||||
if (!pbuf) {
|
|
||||||
SAM("ERROR: Could not allocate frame "
|
|
||||||
"buffer %i page %i\n", k, m);
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
peasycap->allocation_video_page += 1;
|
rc = alloc_fieldbuffers(peasycap);
|
||||||
peasycap->frame_buffer[k][m].pgo = pbuf;
|
if (rc < 0)
|
||||||
}
|
return rc;
|
||||||
peasycap->frame_buffer[k][m].pto =
|
|
||||||
peasycap->frame_buffer[k][m].pgo;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
peasycap->frame_fill = 0;
|
rc = alloc_isocbuffers(peasycap);
|
||||||
peasycap->frame_read = 0;
|
if (rc < 0)
|
||||||
JOM(4, "allocation of frame buffers done: %i pages\n", k *
|
return rc;
|
||||||
m);
|
|
||||||
JOM(4, "allocating %i field buffers of size %li\n",
|
|
||||||
FIELD_BUFFER_MANY, (long int)FIELD_BUFFER_SIZE);
|
|
||||||
JOM(4, ".... each scattered over %li pages\n",
|
|
||||||
FIELD_BUFFER_SIZE/PAGE_SIZE);
|
|
||||||
|
|
||||||
for (k = 0; k < FIELD_BUFFER_MANY; k++) {
|
/* Allocate and initialize video urbs */
|
||||||
for (m = 0; m < FIELD_BUFFER_SIZE/PAGE_SIZE; m++) {
|
rc = create_video_urbs(peasycap);
|
||||||
if (peasycap->field_buffer[k][m].pgo) {
|
if (rc < 0)
|
||||||
SAM("ERROR: attempting to reallocate "
|
return rc;
|
||||||
"field buffers\n");
|
|
||||||
} else {
|
|
||||||
pbuf = (void *) __get_free_page(GFP_KERNEL);
|
|
||||||
if (!pbuf) {
|
|
||||||
SAM("ERROR: Could not allocate field"
|
|
||||||
" buffer %i page %i\n", k, m);
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
peasycap->allocation_video_page += 1;
|
|
||||||
peasycap->field_buffer[k][m].pgo = pbuf;
|
|
||||||
}
|
|
||||||
peasycap->field_buffer[k][m].pto =
|
|
||||||
peasycap->field_buffer[k][m].pgo;
|
|
||||||
}
|
|
||||||
peasycap->field_buffer[k][0].kount = 0x0200;
|
|
||||||
}
|
|
||||||
peasycap->field_fill = 0;
|
|
||||||
peasycap->field_page = 0;
|
|
||||||
peasycap->field_read = 0;
|
|
||||||
JOM(4, "allocation of field buffers done: %i pages\n", k *
|
|
||||||
m);
|
|
||||||
JOM(4, "allocating %i isoc video buffers of size %i\n",
|
|
||||||
VIDEO_ISOC_BUFFER_MANY,
|
|
||||||
peasycap->video_isoc_buffer_size);
|
|
||||||
JOM(4, ".... each occupying contiguous memory pages\n");
|
|
||||||
|
|
||||||
for (k = 0; k < VIDEO_ISOC_BUFFER_MANY; k++) {
|
|
||||||
pbuf = (void *)__get_free_pages(GFP_KERNEL,
|
|
||||||
VIDEO_ISOC_ORDER);
|
|
||||||
if (!pbuf) {
|
|
||||||
SAM("ERROR: Could not allocate isoc video buffer "
|
|
||||||
"%i\n", k);
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
peasycap->allocation_video_page +=
|
|
||||||
BIT(VIDEO_ISOC_ORDER);
|
|
||||||
|
|
||||||
peasycap->video_isoc_buffer[k].pgo = pbuf;
|
|
||||||
peasycap->video_isoc_buffer[k].pto =
|
|
||||||
pbuf + peasycap->video_isoc_buffer_size;
|
|
||||||
peasycap->video_isoc_buffer[k].kount = k;
|
|
||||||
}
|
|
||||||
JOM(4, "allocation of isoc video buffers done: %i pages\n",
|
|
||||||
k * (0x01 << VIDEO_ISOC_ORDER));
|
|
||||||
|
|
||||||
/* Allocate and initialize multiple struct usb */
|
|
||||||
JOM(4, "allocating %i struct urb.\n", VIDEO_ISOC_BUFFER_MANY);
|
|
||||||
JOM(4, "using %i=peasycap->video_isoc_framesperdesc\n",
|
|
||||||
peasycap->video_isoc_framesperdesc);
|
|
||||||
JOM(4, "using %i=peasycap->video_isoc_maxframesize\n",
|
|
||||||
peasycap->video_isoc_maxframesize);
|
|
||||||
JOM(4, "using %i=peasycap->video_isoc_buffer_sizen",
|
|
||||||
peasycap->video_isoc_buffer_size);
|
|
||||||
|
|
||||||
for (k = 0; k < VIDEO_ISOC_BUFFER_MANY; k++) {
|
|
||||||
purb = usb_alloc_urb(peasycap->video_isoc_framesperdesc,
|
|
||||||
GFP_KERNEL);
|
|
||||||
if (!purb) {
|
|
||||||
SAM("ERROR: usb_alloc_urb returned NULL for buffer "
|
|
||||||
"%i\n", k);
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
peasycap->allocation_video_urb += 1;
|
|
||||||
pdata_urb = kzalloc(sizeof(struct data_urb), GFP_KERNEL);
|
|
||||||
if (!pdata_urb) {
|
|
||||||
SAM("ERROR: Could not allocate struct data_urb.\n");
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
peasycap->allocation_video_struct +=
|
|
||||||
sizeof(struct data_urb);
|
|
||||||
|
|
||||||
pdata_urb->purb = purb;
|
|
||||||
pdata_urb->isbuf = k;
|
|
||||||
pdata_urb->length = 0;
|
|
||||||
list_add_tail(&(pdata_urb->list_head),
|
|
||||||
peasycap->purb_video_head);
|
|
||||||
|
|
||||||
/* Initialize allocated urbs */
|
|
||||||
if (!k) {
|
|
||||||
JOM(4, "initializing video urbs thus:\n");
|
|
||||||
JOM(4, " purb->interval = 1;\n");
|
|
||||||
JOM(4, " purb->dev = peasycap->pusb_device;\n");
|
|
||||||
JOM(4, " purb->pipe = usb_rcvisocpipe"
|
|
||||||
"(peasycap->pusb_device,%i);\n",
|
|
||||||
peasycap->video_endpointnumber);
|
|
||||||
JOM(4, " purb->transfer_flags = URB_ISO_ASAP;\n");
|
|
||||||
JOM(4, " purb->transfer_buffer = peasycap->"
|
|
||||||
"video_isoc_buffer[.].pgo;\n");
|
|
||||||
JOM(4, " purb->transfer_buffer_length = %i;\n",
|
|
||||||
peasycap->video_isoc_buffer_size);
|
|
||||||
JOM(4, " purb->complete = easycap_complete;\n");
|
|
||||||
JOM(4, " purb->context = peasycap;\n");
|
|
||||||
JOM(4, " purb->start_frame = 0;\n");
|
|
||||||
JOM(4, " purb->number_of_packets = %i;\n",
|
|
||||||
peasycap->video_isoc_framesperdesc);
|
|
||||||
JOM(4, " for (j = 0; j < %i; j++)\n",
|
|
||||||
peasycap->video_isoc_framesperdesc);
|
|
||||||
JOM(4, " {\n");
|
|
||||||
JOM(4, " purb->iso_frame_desc[j].offset = j*%i;\n",
|
|
||||||
peasycap->video_isoc_maxframesize);
|
|
||||||
JOM(4, " purb->iso_frame_desc[j].length = %i;\n",
|
|
||||||
peasycap->video_isoc_maxframesize);
|
|
||||||
JOM(4, " }\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
purb->interval = 1;
|
|
||||||
purb->dev = peasycap->pusb_device;
|
|
||||||
purb->pipe = usb_rcvisocpipe(peasycap->pusb_device,
|
|
||||||
peasycap->video_endpointnumber);
|
|
||||||
purb->transfer_flags = URB_ISO_ASAP;
|
|
||||||
purb->transfer_buffer = peasycap->video_isoc_buffer[k].pgo;
|
|
||||||
purb->transfer_buffer_length =
|
|
||||||
peasycap->video_isoc_buffer_size;
|
|
||||||
purb->complete = easycap_complete;
|
|
||||||
purb->context = peasycap;
|
|
||||||
purb->start_frame = 0;
|
|
||||||
purb->number_of_packets = peasycap->video_isoc_framesperdesc;
|
|
||||||
for (j = 0; j < peasycap->video_isoc_framesperdesc; j++) {
|
|
||||||
purb->iso_frame_desc[j].offset = j *
|
|
||||||
peasycap->video_isoc_maxframesize;
|
|
||||||
purb->iso_frame_desc[j].length =
|
|
||||||
peasycap->video_isoc_maxframesize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
JOM(4, "allocation of %i struct urb done.\n", k);
|
|
||||||
|
|
||||||
/* Save pointer peasycap in this interface */
|
/* Save pointer peasycap in this interface */
|
||||||
usb_set_intfdata(intf, peasycap);
|
usb_set_intfdata(intf, peasycap);
|
||||||
|
|
Loading…
Reference in New Issue