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
/* must have more buffers due to buggy USB ctr */
#define NUMOFOUTBUFFERSHIGH 10
/* Total number of usbdux devices */
#define NUMUSBDUX 16
/* Analogue in subdevice */
#define SUBDEV_AD 0
......@@ -172,10 +169,6 @@ static const struct comedi_lrange range_usbdux_ai_range = { 1, {
};
struct usbduxsigma_private {
/* attached? */
int attached;
/* is it associated with a subdevice? */
int probed;
/* pointer to the usb-device */
struct usb_device *usbdev;
/* actual number of in-buffers */
......@@ -199,8 +192,6 @@ struct usbduxsigma_private {
int8_t *insnBuffer;
/* output buffer for single DA outputs */
int16_t *outBuffer;
/* interface number */
int ifnum;
/* interface structure in 2.6 */
struct usb_interface *interface;
/* comedi device for the interrupt context */
......@@ -233,17 +224,6 @@ struct usbduxsigma_private {
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)
{
if (do_unlink) {
......@@ -1737,8 +1717,6 @@ static void tidy_up(struct usbduxsigma_private *usbduxsub_tmp)
if (usbduxsub_tmp->interface)
usb_set_intfdata(usbduxsub_tmp->interface, NULL);
usbduxsub_tmp->probed = 0;
if (usbduxsub_tmp->urbIn) {
/* force unlink all urbs */
usbdux_ai_stop(usbduxsub_tmp, 1);
......@@ -1789,9 +1767,9 @@ static void tidy_up(struct usbduxsigma_private *usbduxsub_tmp)
usbduxsub_tmp->dux_commands = NULL;
}
static int usbduxsigma_attach_common(struct comedi_device *dev,
struct usbduxsigma_private *uds)
static int usbduxsigma_attach_common(struct comedi_device *dev)
{
struct usbduxsigma_private *uds = dev->private;
int ret;
struct comedi_subdevice *s;
int n_subdevs;
......@@ -1811,8 +1789,6 @@ static int usbduxsigma_attach_common(struct comedi_device *dev,
up(&uds->sem);
return ret;
}
/* private structure is also simply the usb-structure */
dev->private = uds;
/* the first subdevice is the A/D converter */
s = &dev->subdevices[SUBDEV_AD];
/* the URBs get the comedi subdevice */
......@@ -1890,8 +1866,6 @@ static int usbduxsigma_attach_common(struct comedi_device *dev,
s->insn_config = usbdux_pwm_config;
usbdux_pwm_period(dev, s, PWM_DEFAULT_PERIOD);
}
/* finally decide that it's attached */
uds->attached = 1;
up(&uds->sem);
offset = usbdux_getstatusinfo(dev, 0);
if (offset < 0)
......@@ -1991,34 +1965,51 @@ static int usbduxsigma_alloc_usb_buffers(struct usbduxsigma_private *devpriv)
static int usbduxsigma_auto_attach(struct comedi_device *dev,
unsigned long context_unused)
{
struct usb_interface *uinterf = comedi_to_usb_interface(dev);
struct usbduxsigma_private *uds = usb_get_intfdata(uinterf);
struct usb_device *usb = uds->usbdev;
struct usb_interface *intf = comedi_to_usb_interface(dev);
struct usb_device *usb = comedi_to_usb_dev(dev);
struct usbduxsigma_private *devpriv;
int ret;
dev->private = uds; /* This is temporary... */
ret = comedi_load_firmware(dev, &usb->dev, FIRMWARE,
usbduxsigma_firmware_upload, 0);
devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
if (!devpriv)
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) {
dev->private = NULL;
return ret;
dev_err(dev->class_dev,
"could not set alternate setting 3 in high speed\n");
return -ENODEV;
}
dev->private = NULL;
/* 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;
}
down(&start_stop_sem);
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);
ret = usbduxsigma_alloc_usb_buffers(devpriv);
if (ret) {
tidy_up(devpriv);
return ret;
}
ret = comedi_load_firmware(dev, &usb->dev, FIRMWARE,
usbduxsigma_firmware_upload, 0);
if (ret)
return ret;
return usbduxsigma_attach_common(dev);
}
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_ao_stop(devpriv, devpriv->ao_cmd_running);
down(&start_stop_sem);
down(&devpriv->sem);
dev->private = NULL;
devpriv->attached = 0;
devpriv->comedidev = NULL;
tidy_up(devpriv);
up(&devpriv->sem);
up(&start_stop_sem);
}
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,
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);;
}
......
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