Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 080bcc18 authored by H Hartley Sweeten's avatar H Hartley Sweeten Committed by Greg Kroah-Hartman
Browse files

staging: comedi: usbdux: move usb buffer allocation into new function



Move all the usb buffer allocation code in the usb_driver (*probe)
into a new function, usbdux_alloc_usb_buffers(). This allows tidying
up the error path 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 da903590
Loading
Loading
Loading
Loading
+128 −146
Original line number Diff line number Diff line
@@ -2238,6 +2238,117 @@ static int usbdux_attach_common(struct comedi_device *dev,
	return 0;
}

static int usbdux_alloc_usb_buffers(struct usbdux_private *devpriv)
{
	struct urb *urb;
	int i;

	/* create space for the commands of the DA converter */
	devpriv->dac_commands = kzalloc(NUMOUTCHANNELS, GFP_KERNEL);
	if (!devpriv->dac_commands)
		return -ENOMEM;

	/* create space for the commands going to the usb device */
	devpriv->dux_commands = kzalloc(SIZEOFDUXBUFFER, GFP_KERNEL);
	if (!devpriv->dux_commands)
		return -ENOMEM;

	/* create space for the in buffer and set it to zero */
	devpriv->in_buffer = kzalloc(SIZEINBUF, GFP_KERNEL);
	if (!devpriv->in_buffer)
		return -ENOMEM;

	/* create space of the instruction buffer */
	devpriv->insn_buffer = kzalloc(SIZEINSNBUF, GFP_KERNEL);
	if (!devpriv->insn_buffer)
		return -ENOMEM;

	/* create space for the outbuffer */
	devpriv->out_buffer = kzalloc(SIZEOUTBUF, GFP_KERNEL);
	if (!devpriv->out_buffer)
		return -ENOMEM;

	/* in urbs */
	devpriv->urb_in = kcalloc(devpriv->num_in_buffers, sizeof(*urb),
				  GFP_KERNEL);
	if (!devpriv->urb_in)
		return -ENOMEM;

	for (i = 0; i < devpriv->num_in_buffers; i++) {
		/* one frame: 1ms */
		urb = usb_alloc_urb(1, GFP_KERNEL);
		if (!urb)
			return -ENOMEM;
		devpriv->urb_in[i] = urb;

		urb->dev = devpriv->usbdev;
		/* 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(devpriv->usbdev, ISOINEP);
		urb->transfer_flags = URB_ISO_ASAP;
		urb->transfer_buffer = kzalloc(SIZEINBUF, GFP_KERNEL);
		if (!urb->transfer_buffer)
			return -ENOMEM;

		urb->complete = usbduxsub_ai_isoc_irq;
		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 urbs */
	devpriv->urb_out = kcalloc(devpriv->num_out_buffers, sizeof(*urb),
				   GFP_KERNEL);
	if (!devpriv->urb_out)
		return -ENOMEM;

	for (i = 0; i < devpriv->num_out_buffers; i++) {
		/* one frame: 1ms */
		urb = usb_alloc_urb(1, GFP_KERNEL);
		if (!urb)
			return -ENOMEM;
		devpriv->urb_out[i] = urb;

		urb->dev = devpriv->usbdev;
		/* 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(devpriv->usbdev, ISOOUTEP);
		urb->transfer_flags = URB_ISO_ASAP;
		urb->transfer_buffer = kzalloc(SIZEOUTBUF, GFP_KERNEL);
		if (!urb->transfer_buffer)
			return -ENOMEM;

		urb->complete = usbduxsub_ao_isoc_irq;
		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->size_pwm_buf) {
		urb = usb_alloc_urb(0, GFP_KERNEL);
		if (!urb)
			return -ENOMEM;
		devpriv->urb_pwm = urb;

		/* max bulk ep size in high speed */
		urb->transfer_buffer = kzalloc(devpriv->size_pwm_buf,
					       GFP_KERNEL);
		if (!urb->transfer_buffer)
			return -ENOMEM;
	}

	return 0;
}

static int usbdux_auto_attach(struct comedi_device *dev,
			      unsigned long context_unused)
{
@@ -2297,7 +2408,7 @@ static int usbdux_usb_probe(struct usb_interface *uinterf,
	struct usb_device *udev = interface_to_usbdev(uinterf);
	struct device *dev = &uinterf->dev;
	struct usbdux_private *devpriv = NULL;
	struct urb *urb;
	int ret;
	int i;

	down(&start_stop_sem);
@@ -2322,160 +2433,31 @@ static int usbdux_usb_probe(struct usb_interface *uinterf,
	usb_set_intfdata(uinterf, devpriv);

	devpriv->high_speed = (devpriv->usbdev->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->in_buffer = kzalloc(SIZEINBUF, GFP_KERNEL);
	if (!devpriv->in_buffer) {
		tidy_up(devpriv);
		up(&start_stop_sem);
		return -ENOMEM;
	}
	/* create space of the instruction buffer */
	devpriv->insn_buffer = kzalloc(SIZEINSNBUF, GFP_KERNEL);
	if (!devpriv->insn_buffer) {
		tidy_up(devpriv);
		up(&start_stop_sem);
		return -ENOMEM;
	}
	/* create space for the outbuffer */
	devpriv->out_buffer = kzalloc(SIZEOUTBUF, GFP_KERNEL);
	if (!devpriv->out_buffer) {
		tidy_up(devpriv);
		up(&start_stop_sem);
		return -ENOMEM;
	}
	/* setting to alternate setting 3: enabling iso ep and bulk ep. */
	i = usb_set_interface(devpriv->usbdev, devpriv->ifnum, 3);
	if (i < 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)
	if (devpriv->high_speed) {
		devpriv->num_in_buffers = NUMOFINBUFFERSHIGH;
	else
		devpriv->num_in_buffers = NUMOFINBUFFERSFULL;

	devpriv->urb_in = kcalloc(devpriv->num_in_buffers, sizeof(*urb),
				  GFP_KERNEL);
	if (!devpriv->urb_in) {
		tidy_up(devpriv);
		up(&start_stop_sem);
		return -ENOMEM;
	}
	for (i = 0; i < devpriv->num_in_buffers; i++) {
		/* one frame: 1ms */
		urb = usb_alloc_urb(1, GFP_KERNEL);
		if (!urb) {
			tidy_up(devpriv);
			up(&start_stop_sem);
			return -ENOMEM;
		}
		devpriv->urb_in[i] = urb;

		urb->dev = devpriv->usbdev;
		/* 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(devpriv->usbdev, 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_isoc_irq;
		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)
		devpriv->num_out_buffers = NUMOFOUTBUFFERSHIGH;
	else
		devpriv->size_pwm_buf = 512;
	} else {
		devpriv->num_in_buffers = NUMOFINBUFFERSFULL;
		devpriv->num_out_buffers = NUMOFOUTBUFFERSFULL;

	devpriv->urb_out = kcalloc(devpriv->num_out_buffers, sizeof(*urb),
				   GFP_KERNEL);
	if (!devpriv->urb_out) {
		tidy_up(devpriv);
		up(&start_stop_sem);
		return -ENOMEM;
	}
	for (i = 0; i < devpriv->num_out_buffers; i++) {
		/* one frame: 1ms */
		urb = usb_alloc_urb(1, GFP_KERNEL);
		if (!urb) {
			tidy_up(devpriv);
			up(&start_stop_sem);
			return -ENOMEM;
		}
		devpriv->urb_out[i] = urb;

		urb->dev = devpriv->usbdev;
		/* 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(devpriv->usbdev, 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_isoc_irq;
		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 */
		devpriv->size_pwm_buf = 0;
	}

	/* pwm */
	if (devpriv->high_speed) {
		urb = usb_alloc_urb(0, GFP_KERNEL);
		if (!urb) {
	ret = usbdux_alloc_usb_buffers(devpriv);
	if (ret) {
		tidy_up(devpriv);
		up(&start_stop_sem);
			return -ENOMEM;
		return ret;
	}
		devpriv->urb_pwm = urb;

		/* max bulk ep size in high speed */
		devpriv->size_pwm_buf = 512;
		urb->transfer_buffer = kzalloc(devpriv->size_pwm_buf,
					       GFP_KERNEL);
		if (!urb->transfer_buffer) {
	/* setting to alternate setting 3: enabling iso ep and bulk ep. */
	ret = usb_set_interface(devpriv->usbdev, 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 -ENOMEM;
		}
	} else {
		devpriv->urb_pwm = NULL;
		devpriv->size_pwm_buf = 0;
		return ret;
	}

	devpriv->ai_cmd_running = 0;