Commit 1823fcbf authored by H Hartley Sweeten's avatar H Hartley Sweeten Committed by Greg Kroah-Hartman

staging: comedi: usbduxsigma: push usb (*probe) into comedi (*auto_attach)

The usb_driver (*probe) already calls comedi_usb_auto_config(), which
will call the comedi_driver (*auto_attach). Move the bulk of the (*probe)
to the (*auto_attach).

This allows the comedi_device private data to be kzalloc'ed and the static
array used to pass the private data from the usb_driver to the comedi_driver
can be removed along with the static semaphore that protected it.

We can also drop a couple variables from the private data since they no
longer are used or needed.
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 9319d4ab
...@@ -145,9 +145,6 @@ Status: testing ...@@ -145,9 +145,6 @@ Status: testing
/* must have more buffers due to buggy USB ctr */ /* must have more buffers due to buggy USB ctr */
#define NUMOFOUTBUFFERSHIGH 10 #define NUMOFOUTBUFFERSHIGH 10
/* Total number of usbdux devices */
#define NUMUSBDUX 16
/* Analogue in subdevice */ /* Analogue in subdevice */
#define SUBDEV_AD 0 #define SUBDEV_AD 0
...@@ -172,10 +169,6 @@ static const struct comedi_lrange range_usbdux_ai_range = { 1, { ...@@ -172,10 +169,6 @@ static const struct comedi_lrange range_usbdux_ai_range = { 1, {
}; };
struct usbduxsigma_private { struct usbduxsigma_private {
/* attached? */
int attached;
/* is it associated with a subdevice? */
int probed;
/* pointer to the usb-device */ /* pointer to the usb-device */
struct usb_device *usbdev; struct usb_device *usbdev;
/* actual number of in-buffers */ /* actual number of in-buffers */
...@@ -199,8 +192,6 @@ struct usbduxsigma_private { ...@@ -199,8 +192,6 @@ struct usbduxsigma_private {
int8_t *insnBuffer; int8_t *insnBuffer;
/* output buffer for single DA outputs */ /* output buffer for single DA outputs */
int16_t *outBuffer; int16_t *outBuffer;
/* interface number */
int ifnum;
/* interface structure in 2.6 */ /* interface structure in 2.6 */
struct usb_interface *interface; struct usb_interface *interface;
/* comedi device for the interrupt context */ /* comedi device for the interrupt context */
...@@ -233,17 +224,6 @@ struct usbduxsigma_private { ...@@ -233,17 +224,6 @@ struct usbduxsigma_private {
struct semaphore sem; struct semaphore sem;
}; };
/*
* The pointer to the private usb-data of the driver is also the private data
* for the comedi-device. This has to be global as the usb subsystem needs
* global variables. The other reason is that this structure must be there
* _before_ any comedi command is issued. The usb subsystem must be initialised
* before comedi can access it.
*/
static struct usbduxsigma_private usbduxsub[NUMUSBDUX];
static DEFINE_SEMAPHORE(start_stop_sem);
static void usbdux_ai_stop(struct usbduxsigma_private *devpriv, int do_unlink) static void usbdux_ai_stop(struct usbduxsigma_private *devpriv, int do_unlink)
{ {
if (do_unlink) { if (do_unlink) {
...@@ -1737,8 +1717,6 @@ static void tidy_up(struct usbduxsigma_private *usbduxsub_tmp) ...@@ -1737,8 +1717,6 @@ static void tidy_up(struct usbduxsigma_private *usbduxsub_tmp)
if (usbduxsub_tmp->interface) if (usbduxsub_tmp->interface)
usb_set_intfdata(usbduxsub_tmp->interface, NULL); usb_set_intfdata(usbduxsub_tmp->interface, NULL);
usbduxsub_tmp->probed = 0;
if (usbduxsub_tmp->urbIn) { if (usbduxsub_tmp->urbIn) {
/* force unlink all urbs */ /* force unlink all urbs */
usbdux_ai_stop(usbduxsub_tmp, 1); usbdux_ai_stop(usbduxsub_tmp, 1);
...@@ -1789,9 +1767,9 @@ static void tidy_up(struct usbduxsigma_private *usbduxsub_tmp) ...@@ -1789,9 +1767,9 @@ static void tidy_up(struct usbduxsigma_private *usbduxsub_tmp)
usbduxsub_tmp->dux_commands = NULL; usbduxsub_tmp->dux_commands = NULL;
} }
static int usbduxsigma_attach_common(struct comedi_device *dev, static int usbduxsigma_attach_common(struct comedi_device *dev)
struct usbduxsigma_private *uds)
{ {
struct usbduxsigma_private *uds = dev->private;
int ret; int ret;
struct comedi_subdevice *s; struct comedi_subdevice *s;
int n_subdevs; int n_subdevs;
...@@ -1811,8 +1789,6 @@ static int usbduxsigma_attach_common(struct comedi_device *dev, ...@@ -1811,8 +1789,6 @@ static int usbduxsigma_attach_common(struct comedi_device *dev,
up(&uds->sem); up(&uds->sem);
return ret; return ret;
} }
/* private structure is also simply the usb-structure */
dev->private = uds;
/* the first subdevice is the A/D converter */ /* the first subdevice is the A/D converter */
s = &dev->subdevices[SUBDEV_AD]; s = &dev->subdevices[SUBDEV_AD];
/* the URBs get the comedi subdevice */ /* the URBs get the comedi subdevice */
...@@ -1890,8 +1866,6 @@ static int usbduxsigma_attach_common(struct comedi_device *dev, ...@@ -1890,8 +1866,6 @@ static int usbduxsigma_attach_common(struct comedi_device *dev,
s->insn_config = usbdux_pwm_config; s->insn_config = usbdux_pwm_config;
usbdux_pwm_period(dev, s, PWM_DEFAULT_PERIOD); usbdux_pwm_period(dev, s, PWM_DEFAULT_PERIOD);
} }
/* finally decide that it's attached */
uds->attached = 1;
up(&uds->sem); up(&uds->sem);
offset = usbdux_getstatusinfo(dev, 0); offset = usbdux_getstatusinfo(dev, 0);
if (offset < 0) if (offset < 0)
...@@ -1991,34 +1965,51 @@ static int usbduxsigma_alloc_usb_buffers(struct usbduxsigma_private *devpriv) ...@@ -1991,34 +1965,51 @@ static int usbduxsigma_alloc_usb_buffers(struct usbduxsigma_private *devpriv)
static int usbduxsigma_auto_attach(struct comedi_device *dev, static int usbduxsigma_auto_attach(struct comedi_device *dev,
unsigned long context_unused) unsigned long context_unused)
{ {
struct usb_interface *uinterf = comedi_to_usb_interface(dev); struct usb_interface *intf = comedi_to_usb_interface(dev);
struct usbduxsigma_private *uds = usb_get_intfdata(uinterf); struct usb_device *usb = comedi_to_usb_dev(dev);
struct usb_device *usb = uds->usbdev; struct usbduxsigma_private *devpriv;
int ret; int ret;
dev->private = uds; /* This is temporary... */ devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
ret = comedi_load_firmware(dev, &usb->dev, FIRMWARE, if (!devpriv)
usbduxsigma_firmware_upload, 0); return -ENOMEM;
dev->private = devpriv;
sema_init(&devpriv->sem, 1);
devpriv->usbdev = usb;
devpriv->interface = intf;
usb_set_intfdata(intf, devpriv);
ret = usb_set_interface(usb,
intf->altsetting->desc.bInterfaceNumber, 3);
if (ret < 0) { if (ret < 0) {
dev->private = NULL; dev_err(dev->class_dev,
"could not set alternate setting 3 in high speed\n");
return -ENODEV;
}
/* 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 {
devpriv->numOfInBuffers = NUMOFINBUFFERSFULL;
devpriv->numOfOutBuffers = NUMOFOUTBUFFERSFULL;
}
ret = usbduxsigma_alloc_usb_buffers(devpriv);
if (ret) {
tidy_up(devpriv);
return ret; return ret;
} }
dev->private = NULL; ret = comedi_load_firmware(dev, &usb->dev, FIRMWARE,
usbduxsigma_firmware_upload, 0);
if (ret)
return ret;
down(&start_stop_sem); return usbduxsigma_attach_common(dev);
if (!uds) {
dev_err(dev->class_dev,
"usbduxsigma: error: auto_attach failed, not connected\n");
ret = -ENODEV;
} else if (uds->attached) {
dev_err(dev->class_dev,
"usbduxsigma: error: auto_attach failed, already attached\n");
ret = -ENODEV;
} else
ret = usbduxsigma_attach_common(dev, uds);
up(&start_stop_sem);
return ret;
} }
static void usbduxsigma_detach(struct comedi_device *dev) static void usbduxsigma_detach(struct comedi_device *dev)
...@@ -2032,14 +2023,10 @@ static void usbduxsigma_detach(struct comedi_device *dev) ...@@ -2032,14 +2023,10 @@ static void usbduxsigma_detach(struct comedi_device *dev)
usbdux_ai_stop(devpriv, devpriv->ai_cmd_running); usbdux_ai_stop(devpriv, devpriv->ai_cmd_running);
usbdux_ao_stop(devpriv, devpriv->ao_cmd_running); usbdux_ao_stop(devpriv, devpriv->ao_cmd_running);
down(&start_stop_sem);
down(&devpriv->sem); down(&devpriv->sem);
dev->private = NULL;
devpriv->attached = 0;
devpriv->comedidev = NULL; devpriv->comedidev = NULL;
tidy_up(devpriv); tidy_up(devpriv);
up(&devpriv->sem); up(&devpriv->sem);
up(&start_stop_sem);
} }
static struct comedi_driver usbduxsigma_driver = { static struct comedi_driver usbduxsigma_driver = {
...@@ -2052,66 +2039,6 @@ static struct comedi_driver usbduxsigma_driver = { ...@@ -2052,66 +2039,6 @@ static struct comedi_driver usbduxsigma_driver = {
static int usbduxsigma_usb_probe(struct usb_interface *intf, static int usbduxsigma_usb_probe(struct usb_interface *intf,
const struct usb_device_id *id) const struct usb_device_id *id)
{ {
struct usb_device *usb = interface_to_usbdev(intf);
struct device *dev = &intf->dev;
struct usbduxsigma_private *devpriv = NULL;
int ret;
int i;
down(&start_stop_sem);
for (i = 0; i < NUMUSBDUX; i++) {
if (!usbduxsub[i].probed) {
devpriv = &usbduxsub[i];
break;
}
}
if (!devpriv) {
dev_err(dev, "Too many usbduxsigma-devices connected.\n");
up(&start_stop_sem);
return -EMFILE;
}
sema_init(&devpriv->sem, 1);
devpriv->usbdev = usb;
devpriv->interface = intf;
devpriv->ifnum = intf->altsetting->desc.bInterfaceNumber;
usb_set_intfdata(intf, devpriv);
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;
}
/* 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 {
devpriv->numOfInBuffers = NUMOFINBUFFERSFULL;
devpriv->numOfOutBuffers = NUMOFOUTBUFFERSFULL;
}
ret = usbduxsigma_alloc_usb_buffers(devpriv);
if (ret) {
tidy_up(devpriv);
up(&start_stop_sem);
return ret;
}
devpriv->ai_cmd_running = 0;
devpriv->ao_cmd_running = 0;
devpriv->pwm_cmd_running = 0;
/* we've reached the bottom of the function */
devpriv->probed = 1;
up(&start_stop_sem);
return comedi_usb_auto_config(intf, &usbduxsigma_driver, 0);; return comedi_usb_auto_config(intf, &usbduxsigma_driver, 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