Commit 65989c03 authored by H Hartley Sweeten's avatar H Hartley Sweeten Committed by Greg Kroah-Hartman

staging: comedi: usbduxsigma: factor usb buffer allocation out of (*probe)

To make pushing the usb_driver (*probe) into the comedi_driver (*auto_attach)
cleaner, factor the usb buffer allocation out of the (*probe). This also
cleans up the failure paths in the (*probe).
Signed-off-by: default avatarH Hartley Sweeten <hsweeten@visionengravers.com>
Cc: Ian Abbott <abbotti@mev.co.uk>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 902add47
......@@ -1902,6 +1902,92 @@ static int usbduxsigma_attach_common(struct comedi_device *dev,
return 0;
}
static int usbduxsigma_alloc_usb_buffers(struct usbduxsigma_private *devpriv)
{
struct usb_device *usb = devpriv->usbdev;
struct urb *urb;
int i;
devpriv->dac_commands = kzalloc(NUMOUTCHANNELS, GFP_KERNEL);
devpriv->dux_commands = kzalloc(SIZEOFDUXBUFFER, GFP_KERNEL);
devpriv->inBuffer = kzalloc(SIZEINBUF, GFP_KERNEL);
devpriv->insnBuffer = kzalloc(SIZEINSNBUF, GFP_KERNEL);
devpriv->outBuffer = kzalloc(SIZEOUTBUF, GFP_KERNEL);
devpriv->urbIn = kcalloc(devpriv->numOfInBuffers, sizeof(*urb),
GFP_KERNEL);
devpriv->urbOut = kcalloc(devpriv->numOfOutBuffers, sizeof(*urb),
GFP_KERNEL);
if (!devpriv->dac_commands || !devpriv->dux_commands ||
!devpriv->inBuffer || !devpriv->insnBuffer ||
!devpriv->outBuffer || !devpriv->urbIn || !devpriv->urbOut)
return -ENOMEM;
for (i = 0; i < devpriv->numOfInBuffers; i++) {
/* one frame: 1ms */
urb = usb_alloc_urb(1, GFP_KERNEL);
if (!urb)
return -ENOMEM;
devpriv->urbIn[i] = urb;
urb->dev = usb;
/* will be filled later with a pointer to the comedi-device */
/* and ONLY then the urb should be submitted */
urb->context = NULL;
urb->pipe = usb_rcvisocpipe(usb, ISOINEP);
urb->transfer_flags = URB_ISO_ASAP;
urb->transfer_buffer = kzalloc(SIZEINBUF, GFP_KERNEL);
if (!urb->transfer_buffer)
return -ENOMEM;
urb->complete = usbduxsub_ai_IsocIrq;
urb->number_of_packets = 1;
urb->transfer_buffer_length = SIZEINBUF;
urb->iso_frame_desc[0].offset = 0;
urb->iso_frame_desc[0].length = SIZEINBUF;
}
for (i = 0; i < devpriv->numOfOutBuffers; i++) {
/* one frame: 1ms */
urb = usb_alloc_urb(1, GFP_KERNEL);
if (!urb)
return -ENOMEM;
devpriv->urbOut[i] = urb;
urb->dev = usb;
/* will be filled later with a pointer to the comedi-device */
/* and ONLY then the urb should be submitted */
urb->context = NULL;
urb->pipe = usb_sndisocpipe(usb, ISOOUTEP);
urb->transfer_flags = URB_ISO_ASAP;
urb->transfer_buffer = kzalloc(SIZEOUTBUF, GFP_KERNEL);
if (!urb->transfer_buffer)
return -ENOMEM;
urb->complete = usbduxsub_ao_IsocIrq;
urb->number_of_packets = 1;
urb->transfer_buffer_length = SIZEOUTBUF;
urb->iso_frame_desc[0].offset = 0;
urb->iso_frame_desc[0].length = SIZEOUTBUF;
if (devpriv->high_speed)
urb->interval = 8; /* uframes */
else
urb->interval = 1; /* frames */
}
if (devpriv->high_speed) {
/* max bulk ep size in high speed */
devpriv->sizePwmBuf = 512;
urb = usb_alloc_urb(0, GFP_KERNEL);
if (!urb)
return -ENOMEM;
devpriv->urbPwm = urb;
urb->transfer_buffer = kzalloc(devpriv->sizePwmBuf, GFP_KERNEL);
if (!urb->transfer_buffer)
return -ENOMEM;
} else {
devpriv->urbPwm = NULL;
devpriv->sizePwmBuf = 0;
}
return 0;
}
static int usbduxsigma_auto_attach(struct comedi_device *dev,
unsigned long context_unused)
{
......@@ -1961,7 +2047,7 @@ static int usbduxsigma_usb_probe(struct usb_interface *intf,
struct usb_device *usb = interface_to_usbdev(intf);
struct device *dev = &intf->dev;
struct usbduxsigma_private *devpriv = NULL;
struct urb *urb;
int ret;
int i;
down(&start_stop_sem);
......@@ -1984,158 +2070,30 @@ static int usbduxsigma_usb_probe(struct usb_interface *intf,
devpriv->ifnum = intf->altsetting->desc.bInterfaceNumber;
usb_set_intfdata(intf, devpriv);
/* test if it is high speed (USB 2.0) */
devpriv->high_speed = (usb->speed == USB_SPEED_HIGH);
/* create space for the commands of the DA converter */
devpriv->dac_commands = kzalloc(NUMOUTCHANNELS, GFP_KERNEL);
if (!devpriv->dac_commands) {
tidy_up(devpriv);
up(&start_stop_sem);
return -ENOMEM;
}
/* create space for the commands going to the usb device */
devpriv->dux_commands = kzalloc(SIZEOFDUXBUFFER, GFP_KERNEL);
if (!devpriv->dux_commands) {
tidy_up(devpriv);
up(&start_stop_sem);
return -ENOMEM;
}
/* create space for the in buffer and set it to zero */
devpriv->inBuffer = kzalloc(SIZEINBUF, GFP_KERNEL);
if (!devpriv->inBuffer) {
tidy_up(devpriv);
up(&start_stop_sem);
return -ENOMEM;
}
/* create space of the instruction buffer */
devpriv->insnBuffer = kzalloc(SIZEINSNBUF, GFP_KERNEL);
if (!devpriv->insnBuffer) {
tidy_up(devpriv);
up(&start_stop_sem);
return -ENOMEM;
}
/* create space for the outbuffer */
devpriv->outBuffer = kzalloc(SIZEOUTBUF, GFP_KERNEL);
if (!devpriv->outBuffer) {
tidy_up(devpriv);
up(&start_stop_sem);
return -ENOMEM;
}
/* setting to alternate setting 3: enabling iso ep and bulk ep. */
i = usb_set_interface(usb, devpriv->ifnum, 3);
if (i < 0) {
ret = usb_set_interface(usb, devpriv->ifnum, 3);
if (ret < 0) {
dev_err(dev,
"could not set alternate setting 3 in high speed\n");
tidy_up(devpriv);
up(&start_stop_sem);
return -ENODEV;
}
if (devpriv->high_speed)
devpriv->numOfInBuffers = NUMOFINBUFFERSHIGH;
else
devpriv->numOfInBuffers = NUMOFINBUFFERSFULL;
devpriv->urbIn = kcalloc(devpriv->numOfInBuffers, sizeof(*urb),
GFP_KERNEL);
if (!devpriv->urbIn) {
tidy_up(devpriv);
up(&start_stop_sem);
return -ENOMEM;
}
for (i = 0; i < devpriv->numOfInBuffers; i++) {
/* one frame: 1ms */
urb = usb_alloc_urb(1, GFP_KERNEL);
if (!urb) {
tidy_up(devpriv);
up(&start_stop_sem);
return -ENOMEM;
}
devpriv->urbIn[i] = urb;
urb->dev = usb;
/* will be filled later with a pointer to the comedi-device */
/* and ONLY then the urb should be submitted */
urb->context = NULL;
urb->pipe = usb_rcvisocpipe(usb, ISOINEP);
urb->transfer_flags = URB_ISO_ASAP;
urb->transfer_buffer = kzalloc(SIZEINBUF, GFP_KERNEL);
if (!urb->transfer_buffer) {
tidy_up(devpriv);
up(&start_stop_sem);
return -ENOMEM;
}
urb->complete = usbduxsub_ai_IsocIrq;
urb->number_of_packets = 1;
urb->transfer_buffer_length = SIZEINBUF;
urb->iso_frame_desc[0].offset = 0;
urb->iso_frame_desc[0].length = SIZEINBUF;
}
/* out */
if (devpriv->high_speed)
/* test if it is high speed (USB 2.0) */
devpriv->high_speed = (usb->speed == USB_SPEED_HIGH);
if (devpriv->high_speed) {
devpriv->numOfInBuffers = NUMOFINBUFFERSHIGH;
devpriv->numOfOutBuffers = NUMOFOUTBUFFERSHIGH;
else
} else {
devpriv->numOfInBuffers = NUMOFINBUFFERSFULL;
devpriv->numOfOutBuffers = NUMOFOUTBUFFERSFULL;
}
devpriv->urbOut = kcalloc(devpriv->numOfOutBuffers, sizeof(*urb),
GFP_KERNEL);
if (!devpriv->urbOut) {
ret = usbduxsigma_alloc_usb_buffers(devpriv);
if (ret) {
tidy_up(devpriv);
up(&start_stop_sem);
return -ENOMEM;
}
for (i = 0; i < devpriv->numOfOutBuffers; i++) {
/* one frame: 1ms */
urb = usb_alloc_urb(1, GFP_KERNEL);
if (!urb) {
tidy_up(devpriv);
up(&start_stop_sem);
return -ENOMEM;
}
devpriv->urbOut[i] = urb;
urb->dev = usb;
/* will be filled later with a pointer to the comedi-device */
/* and ONLY then the urb should be submitted */
urb->context = NULL;
urb->pipe = usb_sndisocpipe(usb, ISOOUTEP);
urb->transfer_flags = URB_ISO_ASAP;
urb->transfer_buffer = kzalloc(SIZEOUTBUF, GFP_KERNEL);
if (!urb->transfer_buffer) {
tidy_up(devpriv);
up(&start_stop_sem);
return -ENOMEM;
}
urb->complete = usbduxsub_ao_IsocIrq;
urb->number_of_packets = 1;
urb->transfer_buffer_length = SIZEOUTBUF;
urb->iso_frame_desc[0].offset = 0;
urb->iso_frame_desc[0].length = SIZEOUTBUF;
if (devpriv->high_speed)
urb->interval = 8; /* uframes */
else
urb->interval = 1; /* frames */
}
/* pwm */
if (devpriv->high_speed) {
/* max bulk ep size in high speed */
devpriv->sizePwmBuf = 512;
urb = usb_alloc_urb(0, GFP_KERNEL);
if (!urb) {
tidy_up(devpriv);
up(&start_stop_sem);
return -ENOMEM;
}
devpriv->urbPwm = urb;
urb->transfer_buffer = kzalloc(devpriv->sizePwmBuf, GFP_KERNEL);
if (!urb->transfer_buffer) {
tidy_up(devpriv);
up(&start_stop_sem);
return -ENOMEM;
}
} else {
devpriv->urbPwm = NULL;
devpriv->sizePwmBuf = 0;
return ret;
}
devpriv->ai_cmd_running = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment