usbatm usb_atm.c,1.12,1.13 usb_atm.h,1.4,1.5 cxacru.c,1.5,1.6

kagan at infradead.org kagan at infradead.org
Tue Jan 25 04:36:09 EST 2005


Update of /home/cvs/usbatm
In directory phoenix.infradead.org:/tmp/cvs-serv29610

Modified Files:
	usb_atm.c usb_atm.h cxacru.c 
Log Message:
Redone using subdriver infrastructure registered at probe time.


Index: usb_atm.c
===================================================================
RCS file: /home/cvs/usbatm/usb_atm.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- usb_atm.c	29 Dec 2004 21:18:32 -0000	1.12
+++ usb_atm.c	25 Jan 2005 09:36:05 -0000	1.13
@@ -139,6 +139,9 @@
 		 __MODULE_STRING(UDSL_MAX_SND_BUF_SIZE) ", default: "
 		 __MODULE_STRING(UDSL_DEFAULT_SND_BUF_SIZE) ")");
 
+#define ATM_CELL_HEADER			(ATM_CELL_SIZE - ATM_CELL_PAYLOAD)
+#define UDSL_NUM_CELLS(x)		(((x) + ATM_AAL5_TRAILER + ATM_CELL_PAYLOAD - 1) / ATM_CELL_PAYLOAD)
+
 /* ATM */
 
 static void udsl_atm_dev_close(struct atm_dev *dev);
@@ -148,16 +151,6 @@
 static int udsl_atm_send(struct atm_vcc *vcc, struct sk_buff *skb);
 static int udsl_atm_proc_read(struct atm_dev *atm_dev, loff_t * pos, char *page);
 
-static struct atmdev_ops udsl_atm_devops = {
-	.dev_close	= udsl_atm_dev_close,
-	.open		= udsl_atm_open,
-	.close		= udsl_atm_close,
-	.ioctl		= udsl_atm_ioctl,
-	.send		= udsl_atm_send,
-	.proc_read	= udsl_atm_proc_read,
-	.owner		= THIS_MODULE,
-};
-
 /***********
 **  misc  **
 ***********/
@@ -174,7 +167,7 @@
 **  decode  **
 *************/
 
-static inline struct udsl_vcc_data *udsl_find_vcc(struct udsl_instance_data *instance,
+static inline struct udsl_vcc_data *udsl_find_vcc(struct usbatm_data *instance,
 						  short vpi, int vci)
 {
 	struct udsl_vcc_data *vcc;
@@ -185,7 +178,7 @@
 	return NULL;
 }
 
-static void udsl_extract_cells(struct udsl_instance_data *instance,
+static void udsl_extract_cells(struct usbatm_data *instance,
 			       unsigned char *source, unsigned int howmany)
 {
 	struct udsl_vcc_data *cached_vcc = NULL;
@@ -200,7 +193,7 @@
 	short vpi;
 
 	for (i = 0; i < howmany;
-	     i++, source += ATM_CELL_SIZE + instance->rcv_padding) {
+	     i++, source += ATM_CELL_SIZE + instance->rx_padding) {
 		vpi = ((source[0] & 0x0f) << 4) | (source[1] >> 4);
 		vci = ((source[1] & 0x0f) << 12) | (source[2] << 4) | (source[3] >> 4);
 		pti = (source[3] & 0x2) != 0;
@@ -339,7 +332,7 @@
 	ctrl->aal5_trailer[7] = crc;
 }
 
-static unsigned int udsl_write_cells(struct udsl_instance_data *instance,
+static unsigned int udsl_write_cells(struct usbatm_data *instance,
 				     unsigned int howmany, struct sk_buff *skb,
 				     unsigned char **target_p)
 {
@@ -357,9 +350,9 @@
 		target += ATM_CELL_HEADER;
 		memcpy(target, skb->data, ATM_CELL_PAYLOAD);
 		target += ATM_CELL_PAYLOAD;
-		if (instance->snd_padding) {
-			memset(target, 0, instance->snd_padding);
-			target += instance->snd_padding;
+		if (instance->tx_padding) {
+			memset(target, 0, instance->tx_padding);
+			target += instance->tx_padding;
 		}
 		__skb_pull(skb, ATM_CELL_PAYLOAD);
 	}
@@ -383,9 +376,9 @@
 			goto out;
 		}
 
-		if (instance->snd_padding) {
-			memset(target, 0, instance->snd_padding);
-			target += instance->snd_padding;
+		if (instance->tx_padding) {
+			memset(target, 0, instance->tx_padding);
+			target += instance->tx_padding;
 		}
 		udsl_fill_cell_header(target, ctrl->atm_data.vcc);
 		target += ATM_CELL_HEADER;
@@ -400,9 +393,9 @@
 	target += ATM_AAL5_TRAILER;
 	/* set pti bit in last cell */
 	*(target + 3 - ATM_CELL_SIZE) |= 0x2;
-	if (instance->snd_padding) {
-		memset(target, 0, instance->snd_padding);
-		target += instance->snd_padding;
+	if (instance->tx_padding) {
+		memset(target, 0, instance->tx_padding);
+		target += instance->tx_padding;
 	}
  out:
 	*target_p = target;
@@ -416,7 +409,7 @@
 static void udsl_complete_receive(struct urb *urb, struct pt_regs *regs)
 {
 	struct udsl_receive_buffer *buf;
-	struct udsl_instance_data *instance;
+	struct usbatm_data *instance;
 	struct udsl_receiver *rcv;
 	unsigned long flags;
 
@@ -428,7 +421,7 @@
 	instance = rcv->instance;
 	buf = rcv->buffer;
 
-	buf->filled_cells = urb->actual_length / (ATM_CELL_SIZE + instance->rcv_padding);
+	buf->filled_cells = urb->actual_length / (ATM_CELL_SIZE + instance->rx_padding);
 
 	vdbg("udsl_complete_receive: urb 0x%p, status %d, actual_length %d, filled_cells %u, rcv 0x%p, buf 0x%p", urb, urb->status, urb->actual_length, buf->filled_cells, rcv, buf);
 
@@ -446,7 +439,7 @@
 static void udsl_process_receive(unsigned long data)
 {
 	struct udsl_receive_buffer *buf;
-	struct udsl_instance_data *instance = (struct udsl_instance_data *)data;
+	struct usbatm_data *instance = (struct usbatm_data *)data;
 	struct udsl_receiver *rcv;
 	int err;
 
@@ -468,10 +461,9 @@
 
 		rcv->buffer = buf;
 
-		usb_fill_bulk_urb(rcv->urb, instance->usb_dev,
-				  usb_rcvbulkpipe(instance->usb_dev, instance->data_endpoint),
+		usb_fill_bulk_urb(rcv->urb, instance->usb_dev, instance->rx_pipe,
 				  buf->base,
-				  rcv_buf_size * (ATM_CELL_SIZE + instance->rcv_padding),
+				  rcv_buf_size * (ATM_CELL_SIZE + instance->rx_padding),
 				  udsl_complete_receive, rcv);
 
 		vdbg("udsl_process_receive: sending urb 0x%p, rcv 0x%p, buf 0x%p",
@@ -509,7 +501,7 @@
 
 static void udsl_complete_send(struct urb *urb, struct pt_regs *regs)
 {
-	struct udsl_instance_data *instance;
+	struct usbatm_data *instance;
 	struct udsl_sender *snd;
 	unsigned long flags;
 
@@ -532,7 +524,7 @@
 static void udsl_process_send(unsigned long data)
 {
 	struct udsl_send_buffer *buf;
-	struct udsl_instance_data *instance = (struct udsl_instance_data *)data;
+	struct usbatm_data *instance = (struct usbatm_data *)data;
 	struct sk_buff *skb;
 	struct udsl_sender *snd;
 	int err;
@@ -556,10 +548,9 @@
 		spin_unlock_irq(&instance->send_lock);
 
 		snd->buffer = buf;
-		usb_fill_bulk_urb(snd->urb, instance->usb_dev,
-				  usb_sndbulkpipe(instance->usb_dev, instance->data_endpoint),
+		usb_fill_bulk_urb(snd->urb, instance->usb_dev, instance->tx_pipe,
 				  buf->base,
-				  (snd_buf_size - buf->free_cells) * (ATM_CELL_SIZE + instance->snd_padding),
+				  (snd_buf_size - buf->free_cells) * (ATM_CELL_SIZE + instance->tx_padding),
 				  udsl_complete_send, snd);
 
 		vdbg("udsl_process_send: submitting urb 0x%p (%d cells), snd 0x%p, buf 0x%p",
@@ -628,7 +619,7 @@
 	goto made_progress;
 }
 
-static void udsl_cancel_send(struct udsl_instance_data *instance,
+static void udsl_cancel_send(struct usbatm_data *instance,
 			     struct atm_vcc *vcc)
 {
 	struct sk_buff *skb, *n;
@@ -657,7 +648,7 @@
 
 static int udsl_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
 {
-	struct udsl_instance_data *instance = vcc->dev->dev_data;
+	struct usbatm_data *instance = vcc->dev->dev_data;
 	int err;
 
 	vdbg("udsl_atm_send called (skb 0x%p, len %u)", skb, skb->len);
@@ -700,21 +691,24 @@
 
 static void udsl_destroy_instance(struct kref *kref)
 {
-	struct udsl_instance_data *instance =
-	    container_of(kref, struct udsl_instance_data, refcount);
+	struct usbatm_data *instance =
+		container_of(kref, struct usbatm_data, refcount);
+	struct usb_device *usb_dev = instance->usb_dev;
 
 	tasklet_kill(&instance->receive_tasklet);
 	tasklet_kill(&instance->send_tasklet);
-	usb_put_dev(instance->usb_dev);
-	kfree(instance);
+
+	mb();
+	instance->driver->cleanup(instance);
+	usb_put_dev(usb_dev);
 }
 
-void udsl_get_instance(struct udsl_instance_data *instance)
+static void udsl_get_instance(struct usbatm_data *instance)
 {
 	kref_get(&instance->refcount);
 }
 
-void udsl_put_instance(struct udsl_instance_data *instance)
+static void udsl_put_instance(struct usbatm_data *instance)
 {
 	kref_put(&instance->refcount, udsl_destroy_instance);
 }
@@ -725,7 +719,7 @@
 
 static void udsl_atm_dev_close(struct atm_dev *dev)
 {
-	struct udsl_instance_data *instance = dev->dev_data;
+	struct usbatm_data *instance = dev->dev_data;
 
 	dev->dev_data = NULL;
 	udsl_put_instance(instance);
@@ -733,7 +727,7 @@
 
 static int udsl_atm_proc_read(struct atm_dev *atm_dev, loff_t * pos, char *page)
 {
-	struct udsl_instance_data *instance = atm_dev->dev_data;
+	struct usbatm_data *instance = atm_dev->dev_data;
 	int left = *pos;
 
 	if (!instance) {
@@ -774,14 +768,8 @@
 
 		if (instance->usb_dev->state == USB_STATE_NOTATTACHED)
 			strcat(page, ", disconnected\n");
-		else {
-			if (instance->status == UDSL_LOADED_FIRMWARE)
-				strcat(page, ", firmware loaded\n");
-			else if (instance->status == UDSL_LOADING_FIRMWARE)
-				strcat(page, ", firmware loading\n");
-			else
-				strcat(page, ", no firmware\n");
-		}
+		else
+			strcat(page, "\n");
 
 		return strlen(page);
 	}
@@ -791,12 +779,11 @@
 
 static int udsl_atm_open(struct atm_vcc *vcc)
 {
-	struct udsl_instance_data *instance = vcc->dev->dev_data;
+	struct usbatm_data *instance = vcc->dev->dev_data;
 	struct udsl_vcc_data *new;
 	unsigned int max_pdu;
 	int vci = vcc->vci;
 	short vpi = vcc->vpi;
-	int err;
 
 	dbg("udsl_atm_open: vpi %hd, vci %d", vpi, vci);
 
@@ -812,12 +799,6 @@
 		return -EINVAL;
 	}
 
-	if (instance->firmware_wait &&
-	    (err = instance->firmware_wait(instance)) < 0) {
-		dbg("udsl_atm_open: firmware not loaded (%d)!", err);
-		return err;
-	}
-
 	down(&instance->serialize);	/* vs self, udsl_atm_close */
 
 	if (udsl_find_vcc(instance, vpi, vci)) {
@@ -867,7 +848,7 @@
 
 static void udsl_atm_close(struct atm_vcc *vcc)
 {
-	struct udsl_instance_data *instance = vcc->dev->dev_data;
+	struct usbatm_data *instance = vcc->dev->dev_data;
 	struct udsl_vcc_data *vcc_data = vcc->dev_data;
 
 	dbg("udsl_atm_close called");
@@ -920,23 +901,27 @@
 **  USB  **
 **********/
 
-int udsl_instance_setup(struct usb_device *dev,
-			struct udsl_instance_data *instance)
+int usbatm_init(struct usbatm_data *instance,
+		struct usbatm_driver *driver, struct usb_device *usb_dev)
 {
 	char *buf;
 	int i, length;
 
-	kref_init(&instance->refcount);	/* one for USB */
-	udsl_get_instance(instance);	/* one for ATM */
+	kref_init(&instance->refcount);		/* released in usbatm_disconnect */
 
 	init_MUTEX(&instance->serialize);
 
-	instance->usb_dev = dev;
+	instance->driver = driver;
+	instance->usb_dev = usb_dev;
 
-	INIT_LIST_HEAD(&instance->vcc_list);
+	/* FIXME: handle iso pipes */
+	instance->rx_pipe = usb_rcvbulkpipe(usb_dev, driver->rx_endpoint);
+	instance->tx_pipe = usb_sndbulkpipe(usb_dev, driver->tx_endpoint);
 
-	instance->status = UDSL_NO_FIRMWARE;
-	init_waitqueue_head(&instance->firmware_waiters);
+	instance->rx_padding = driver->rx_padding;
+	instance->tx_padding = driver->tx_padding;
+
+	INIT_LIST_HEAD(&instance->vcc_list);
 
 	spin_lock_init(&instance->receive_lock);
 	INIT_LIST_HEAD(&instance->spare_receivers);
@@ -960,7 +945,7 @@
 		struct udsl_receiver *rcv = &(instance->receivers[i]);
 
 		if (!(rcv->urb = usb_alloc_urb(0, GFP_KERNEL))) {
-			dbg("udsl_usb_probe: no memory for receive urb %d!", i);
+			dbg("usbatm_init: no memory for receive urb %d!", i);
 			goto fail;
 		}
 
@@ -973,10 +958,10 @@
 		struct udsl_receive_buffer *buf =
 		    &(instance->receive_buffers[i]);
 
-		buf->base = kmalloc(rcv_buf_size * (ATM_CELL_SIZE + instance->rcv_padding),
+		buf->base = kmalloc(rcv_buf_size * (ATM_CELL_SIZE + instance->rx_padding),
 				    GFP_KERNEL);
 		if (!buf->base) {
-			dbg("udsl_usb_probe: no memory for receive buffer %d!", i);
+			dbg("usbatm_init: no memory for receive buffer %d!", i);
 			goto fail;
 		}
 
@@ -988,7 +973,7 @@
 		struct udsl_sender *snd = &(instance->senders[i]);
 
 		if (!(snd->urb = usb_alloc_urb(0, GFP_KERNEL))) {
-			dbg("udsl_usb_probe: no memory for send urb %d!", i);
+			dbg("usbatm_init: no memory for send urb %d!", i);
 			goto fail;
 		}
 
@@ -1000,37 +985,24 @@
 	for (i = 0; i < num_snd_bufs; i++) {
 		struct udsl_send_buffer *buf = &(instance->send_buffers[i]);
 
-		buf->base = kmalloc(snd_buf_size * (ATM_CELL_SIZE + instance->snd_padding),
+		buf->base = kmalloc(snd_buf_size * (ATM_CELL_SIZE + instance->tx_padding),
 				    GFP_KERNEL);
 		if (!buf->base) {
-			dbg("udsl_usb_probe: no memory for send buffer %d!", i);
+			dbg("usbatm_init: no memory for send buffer %d!", i);
 			goto fail;
 		}
 
 		list_add(&buf->list, &instance->spare_send_buffers);
 	}
 
-	/* ATM init */
-	instance->atm_dev = atm_dev_register(instance->driver_name,
-					     &udsl_atm_devops, -1, NULL);
-	if (!instance->atm_dev) {
-		dbg("udsl_usb_probe: failed to register ATM device!");
-		goto fail;
-	}
-
-	instance->atm_dev->ci_range.vpi_bits = ATM_CI_MAX;
-	instance->atm_dev->ci_range.vci_bits = ATM_CI_MAX;
-	instance->atm_dev->signal = ATM_PHY_SIG_UNKNOWN;
-
-	/* temp init ATM device, set to 128kbit */
-	instance->atm_dev->link_rate = 128 * 1000 / 424;
+	usb_get_dev(usb_dev);		/* released in udsl_destroy_instance */
 
 	/* device description */
 	buf = instance->description;
 	length = sizeof(instance->description);
 
-	if ((i = usb_string(dev, dev->descriptor.iProduct, buf, length)) < 0)
-		goto finish;
+	if ((i = usb_string(usb_dev, usb_dev->descriptor.iProduct, buf, length)) < 0)
+		return 1;
 
 	buf += i;
 	length -= i;
@@ -1039,22 +1011,14 @@
 	buf += i;
 	length -= i;
 
-	if (length <= 0 || (i = usb_make_path(dev, buf, length)) < 0)
-		goto finish;
+	if (length <= 0 || (i = usb_make_path(usb_dev, buf, length)) < 0)
+		return 1;
 
 	buf += i;
 	length -= i;
 
 	snprintf(buf, length, ")");
-
- finish:
-	/* ready for ATM callbacks */
-	wmb();
-	instance->atm_dev->dev_data = instance;
-
-	usb_get_dev(dev);
-
-	return 0;
+	return 1;
 
  fail:
 	for (i = 0; i < num_snd_bufs; i++)
@@ -1072,14 +1036,66 @@
 	return -ENOMEM;
 }
 
-void udsl_instance_disconnect(struct udsl_instance_data *instance)
+EXPORT_SYMBOL_GPL(usbatm_init);
+
+int usbatm_atm_setup(struct usbatm_data *instance, const unsigned char *esi)
 {
 	int i;
 
-	dbg("udsl_instance_disconnect entered");
+	/* fill it here so that ATM stack maintains correct owner */
+	instance->atm_devops.dev_close	= udsl_atm_dev_close,
+	instance->atm_devops.open	= udsl_atm_open,
+	instance->atm_devops.close	= udsl_atm_close,
+	instance->atm_devops.ioctl	= udsl_atm_ioctl,
+	instance->atm_devops.send	= udsl_atm_send,
+	instance->atm_devops.proc_read	= udsl_atm_proc_read,
+	instance->atm_devops.owner	= instance->driver->owner;
+
+	down(&instance->serialize);
+
+	/* ATM init */
+	instance->atm_dev = atm_dev_register(instance->driver->name,
+					     &instance->atm_devops, -1, NULL);
+	if (!instance->atm_dev) {
+		dbg("usbatm_atm_setup: failed to register ATM device!");
+		up(&instance->serialize);
+		return -1;
+	}
+
+	udsl_get_instance(instance);		/* released in udsl_atm_dev_close */
+
+	instance->atm_dev->ci_range.vpi_bits = ATM_CI_MAX;
+	instance->atm_dev->ci_range.vci_bits = ATM_CI_MAX;
+	instance->atm_dev->signal = ATM_PHY_SIG_UNKNOWN;
+
+	memcpy(instance->atm_dev->esi, esi, sizeof(instance->atm_dev->esi));
+	dev_info(&instance->usb_dev->dev, "%s: MAC = %02x", instance->driver->name, esi[0]);
+	for (i = 1; i < sizeof(instance->atm_dev->esi); i++)
+		printk(":%02x", esi[i]);
+	printk("\n");
+
+	/* temp init ATM device, set to 128kbit */
+	instance->atm_dev->link_rate = 128 * 1000 / 424;
+
+	/* ready for ATM callbacks */
+	wmb();
+	instance->atm_dev->dev_data = instance;
+
+	up(&instance->serialize);
+
+	return 1;
+}
+
+EXPORT_SYMBOL_GPL(usbatm_atm_setup);
+
+void usbatm_disconnect(struct usbatm_data *instance)
+{
+	int i;
+
+	dbg("usbatm_disconnect entered");
 
 	if (!instance) {
-		dbg("udsl_instance_disconnect: NULL instance!");
+		dbg("usbatm_disconnect: NULL instance!");
 		return;
 	}
 
@@ -1121,13 +1137,55 @@
 		kfree(instance->send_buffers[i].base);
 
 	/* ATM finalize */
-	shutdown_atm_dev(instance->atm_dev);
+	down(&instance->serialize);
+	if (instance->atm_dev) {
+		up(&instance->serialize);
+		shutdown_atm_dev(instance->atm_dev);
+	}
+	up(&instance->serialize);
+
+	udsl_put_instance(instance);
+}
+
+EXPORT_SYMBOL_GPL(usbatm_disconnect);
+
+static int usbatm_heavy_init_thread(void *arg)
+{
+	struct usbatm_data *instance = arg;
+	struct module *owner = instance->driver->owner;
+
+	daemonize("%s/init", instance->driver->name);
+
+	instance->driver->heavy_init(instance);
+
+	mb();
+	udsl_put_instance(instance);
+	module_put(owner);
+	return 0;
+}
+
+int usbatm_heavy_init(struct usbatm_data *instance)
+{
+	struct module *owner = instance->driver->owner;
+	int ret;
+
+	try_module_get(owner);
+	udsl_get_instance(instance);
+
+	ret = kernel_thread(usbatm_heavy_init_thread, instance,
+			CLONE_FS | CLONE_FILES);
+	if (ret >= 0)
+		return 1;	/* OK */
+
+	dbg("cxacru_firmware_start: kernel_thread failed (%d)!", ret);
+
+	mb();
+	udsl_put_instance(instance);
+	module_put(owner);
+	return ret;
 }
 
-EXPORT_SYMBOL_GPL(udsl_get_instance);
-EXPORT_SYMBOL_GPL(udsl_put_instance);
-EXPORT_SYMBOL_GPL(udsl_instance_setup);
-EXPORT_SYMBOL_GPL(udsl_instance_disconnect);
+EXPORT_SYMBOL_GPL(usbatm_heavy_init);
 
 /***********
 **  init  **

Index: usb_atm.h
===================================================================
RCS file: /home/cvs/usbatm/usb_atm.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- usb_atm.h	29 Dec 2004 21:18:32 -0000	1.4
+++ usb_atm.h	25 Jan 2005 09:36:05 -0000	1.5
@@ -58,8 +58,22 @@
 #define UDSL_DEFAULT_RCV_BUF_SIZE	64	/* ATM cells */
 #define UDSL_DEFAULT_SND_BUF_SIZE	64	/* ATM cells */
 
-#define ATM_CELL_HEADER			(ATM_CELL_SIZE - ATM_CELL_PAYLOAD)
-#define UDSL_NUM_CELLS(x)		(((x) + ATM_AAL5_TRAILER + ATM_CELL_PAYLOAD - 1) / ATM_CELL_PAYLOAD)
+struct usbatm_data;
+
+struct usbatm_driver {
+	struct module *owner;
+	const char *name;
+
+	void (*heavy_init)(struct usbatm_data *);
+	void (*cleanup)(struct usbatm_data *);
+
+	int rx_endpoint;
+	int tx_endpoint;
+
+	unsigned rx_padding;
+	unsigned tx_padding;
+};
+
 
 /* receive */
 
@@ -73,7 +87,7 @@
 	struct list_head list;
 	struct udsl_receive_buffer *buffer;
 	struct urb *urb;
-	struct udsl_instance_data *instance;
+	struct usbatm_data *instance;
 };
 
 struct udsl_vcc_data {
@@ -100,7 +114,7 @@
 	struct list_head list;
 	struct udsl_send_buffer *buffer;
 	struct urb *urb;
-	struct udsl_instance_data *instance;
+	struct usbatm_data *instance;
 };
 
 struct udsl_control {
@@ -115,33 +129,27 @@
 
 /* main driver data */
 
-enum udsl_status {
-	UDSL_NO_FIRMWARE,
-	UDSL_LOADING_FIRMWARE,
-	UDSL_LOADED_FIRMWARE
-};
+struct usbatm_data {
+	struct atmdev_ops atm_devops;
 
-struct udsl_instance_data {
 	struct kref refcount;
 	struct semaphore serialize;
 
+	/* driver part */
+	struct usbatm_driver *driver;
+	
 	/* USB device part */
 	struct usb_device *usb_dev;
+	unsigned int rx_pipe;
+	unsigned int tx_pipe;
+	int rx_padding;
+	int tx_padding;
 	char description[64];
-	int data_endpoint;
-	int snd_padding;
-	int rcv_padding;
-	const char *driver_name;
 
 	/* ATM device part */
 	struct atm_dev *atm_dev;
 	struct list_head vcc_list;
 
-	/* firmware */
-	int (*firmware_wait) (struct udsl_instance_data *);
-	enum udsl_status status;
-	wait_queue_head_t firmware_waiters;
-
 	/* receive */
 	struct udsl_receiver receivers[UDSL_MAX_RCV_URBS];
 	struct udsl_receive_buffer receive_buffers[UDSL_MAX_RCV_BUFS];
@@ -169,8 +177,8 @@
 	struct list_head filled_send_buffers;
 };
 
-extern int udsl_instance_setup(struct usb_device *dev,
-			       struct udsl_instance_data *instance);
-extern void udsl_instance_disconnect(struct udsl_instance_data *instance);
-extern void udsl_get_instance(struct udsl_instance_data *instance);
-extern void udsl_put_instance(struct udsl_instance_data *instance);
+extern int usbatm_init(struct usbatm_data *instance,
+		struct usbatm_driver *driver, struct usb_device *usb_dev);
+extern int usbatm_atm_setup(struct usbatm_data *instance, const unsigned char *esi);
+extern void usbatm_disconnect(struct usbatm_data *instance);
+extern int usbatm_heavy_init(struct usbatm_data *instance);

Index: cxacru.c
===================================================================
RCS file: /home/cvs/usbatm/cxacru.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- cxacru.c	20 Jan 2005 18:30:36 -0000	1.5
+++ cxacru.c	25 Jan 2005 09:36:06 -0000	1.6
@@ -51,9 +51,6 @@
 
 static const char cxacru_driver_name[] = "cxacru";
 
-#define UDSL_IOCTL_LINE_UP		1
-#define UDSL_IOCTL_LINE_DOWN		2
-
 #define CXACRU_EP_CMD		0x01	/* Bulk/interrupt in/out */
 #define CXACRU_EP_DATA		0x02	/* Bulk in/out */
 
@@ -159,17 +156,27 @@
 	CXINF_MAX = 0x1c,
 };
 
-struct cxacru_instance_data {
-	struct udsl_instance_data u;
+static void cxacru_heavy_init(struct usbatm_data *);
+static void cxacru_cleanup(struct usbatm_data *);
 
-	struct semaphore start_serialize;
-#ifdef USE_FW_LOADER
-	int firmware_start_run;
-#endif
+static struct usbatm_driver cxacru_driver = {
+	.owner		= THIS_MODULE,
+	.name		= cxacru_driver_name,
+	.heavy_init	= cxacru_heavy_init,
+	.cleanup	= cxacru_cleanup,
+	.rx_endpoint	= CXACRU_EP_DATA,
+	.tx_endpoint	= CXACRU_EP_DATA,
+	.rx_padding	= 3,
+	.tx_padding	= 11,
+};
+
+struct cxacru_data {
+	struct usbatm_data usbatm;
 
 	int line_status; 
 	struct work_struct poll_work;
 	struct timer_list poll_timer;
+
 	/* contol handles */
 	struct semaphore cm_serialize;
 	u8 *rcv_buf;
@@ -180,6 +187,8 @@
 	struct completion snd_done;
 };
 
+#define to_cxacru_data(ua) container_of(ua, struct cxacru_data, usbatm)
+
 /* the following three functions are stolen from drivers/usb/core/message.c */
 static void cxacru_blocking_completion(struct urb *urb, struct pt_regs *regs)
 {
@@ -213,7 +222,7 @@
 	return status;
 }
 
-static int cxacru_cm(struct cxacru_instance_data *instance, enum cxacru_cm_request cm,
+static int cxacru_cm(struct cxacru_data *instance, enum cxacru_cm_request cm,
 		     u8 *wdata, int wsize, u8 *rdata, int rsize)
 {
 	int ret, actlen;
@@ -230,6 +239,8 @@
 		goto fail;
 	}
 
+	dbg("cxacru_cm: cm %#x instance %p usb_dev %p",
+			cm, instance, instance->usbatm.usb_dev);
 	down(&instance->cm_serialize);
 
 	/* submit reading urb before the writing one */
@@ -303,7 +314,7 @@
 	return ret;
 }
 
-static int cxacru_cm_get_array(struct cxacru_instance_data *instance, enum cxacru_cm_request cm,
+static int cxacru_cm_get_array(struct cxacru_data *instance, enum cxacru_cm_request cm,
 			       u32 *data, int size)
 {
 	int ret, len;
@@ -347,7 +358,7 @@
 	return ret;
 }
 
-static void cxacru_do_timer_poll(struct cxacru_instance_data *instance)
+static void cxacru_do_timer_poll(struct cxacru_data *instance)
 {
 	schedule_work(&instance->poll_work);
 	mod_timer(&instance->poll_timer, jiffies + (5 * HZ));
@@ -355,77 +366,65 @@
 
 static void cxacru_timer_poll(unsigned long data)
 {
-	cxacru_do_timer_poll((struct cxacru_instance_data *)data);
+	cxacru_do_timer_poll((struct cxacru_data *)data);
 }
 
-#ifdef USE_FW_LOADER
-static void cxacru_firmware_start(struct cxacru_instance_data *instance);
-#endif
+static int cxacru_is_up(struct cxacru_data *instance)
+{
+	int ret = cxacru_cm(instance, CM_REQUEST_CARD_GET_STATUS, NULL, 0, NULL, 0);
+	if (ret < 0) {		/* firmware not loaded */
+		dbg("cxacru_adsl_start: CARD_GET_STATUS returned %d", ret);
+		return 0;
+	}
+	return 1;
+}
 
-static void cxacru_adsl_start(struct cxacru_instance_data *instance)
+static void cxacru_adsl_start(struct cxacru_data *instance)
 {
+	struct device *dev = &instance->usbatm.usb_dev->dev;
 	int ret;
-	u8 esi[sizeof(instance->u.atm_dev->esi)] = {};
+	u8 esi[sizeof(instance->usbatm.atm_dev->esi)] = {};
 
 	dbg("cxacru_adsl_start");
-	down(&instance->start_serialize);
-
-	ret = cxacru_cm(instance, CM_REQUEST_CARD_GET_STATUS, NULL, 0, NULL, 0);
-	if (ret < 0) {		/* firmware not loaded */
-		dbg("cxacru_adsl_start: CARD_GET_STATUS returned %d", ret);
-#ifdef USE_FW_LOADER
-		if (!instance->firmware_start_run) {
-			instance->firmware_start_run = 1;
-			cxacru_firmware_start(instance);
-		}
-#endif /* USE_FW_LOADER */
-		goto out;
-	}
 
 	/* Read MAC address */
 	ret = cxacru_cm(instance, CM_REQUEST_CARD_GET_MAC_ADDRESS, NULL, 0, 
 			esi, sizeof(esi));
 	if (ret < 0) {
-		err("cxacru_adsl_start: CARD_GET_MAC_ADDRESS returned %d", ret);
-		goto out;
+		dev_err(dev, "cxacru_adsl_start: CARD_GET_MAC_ADDRESS returned %d\n", ret);
+		return;
 	}
 
-	/* FIXME: remove dev from args; should have been set in probe */
-	ret = udsl_instance_setup(instance->u.usb_dev, &instance->u);
-	if (ret)
-		goto out;
-	memcpy(instance->u.atm_dev->esi, esi, sizeof(esi));
-	/* FIXME: remove */
-	instance->u.status = UDSL_LOADED_FIRMWARE;
-
-	dev_info(&instance->u.usb_dev->dev, "cxacru: MAC = %02x", esi[0]);
-	for (ret = 1; ret < sizeof(esi); ret++)
-		printk(":%02x", esi[ret]);
-	printk("\n");
+	ret = usbatm_atm_setup(&instance->usbatm, esi);
+	if (ret < 0) {
+		dev_err(dev, "cxacru_adsl_start: usbatm_atm_setup returned %d\n", ret);
+		return;
+	}
 
 	/* start ADSL */
 	ret = cxacru_cm(instance, CM_REQUEST_CHIP_ADSL_LINE_START, NULL, 0, NULL, 0);
 	if (ret < 0) {
-		err("cxacru_adst_start: CHIP_ADSL_LINE_START returned %d", ret);
-		goto out;
+		dev_err(dev, "cxacru_adst_start: CHIP_ADSL_LINE_START returned %d\n", ret);
+		return;
 	}
 
 	/* Start status polling */
 	cxacru_do_timer_poll(instance);
 
-	tasklet_schedule(&instance->u.receive_tasklet);
-out:
-	up(&instance->start_serialize);
+	/* FIXME: is it needed here? */
+	tasklet_schedule(&instance->usbatm.receive_tasklet);
 }
 
-static void cxacru_poll_status(struct cxacru_instance_data *instance)
+static void cxacru_poll_status(struct cxacru_data *instance)
 {
 	u32 buf[CXINF_MAX] = {};
+	struct device *dev = &instance->usbatm.usb_dev->dev;
+	struct atm_dev *atm_dev = instance->usbatm.atm_dev;
 	int ret;
 
 	ret = cxacru_cm_get_array(instance, CM_REQUEST_CARD_INFO_GET, buf, CXINF_MAX);
 	if (ret < 0) {
-		dev_warn(&instance->u.usb_dev->dev, "poll status: error %d\n", ret);
+		dev_warn(dev, "poll status: error %d\n", ret);
 		return;
 	}
 
@@ -435,65 +434,63 @@
 	instance->line_status = buf[CXINF_LINE_STATUS];
 	switch (instance->line_status) {
 	case 0:
-		instance->u.atm_dev->signal = ATM_PHY_SIG_LOST;
-		dev_info(&instance->u.usb_dev->dev, "ADSL line: down\n");
+		atm_dev->signal = ATM_PHY_SIG_LOST;
+		dev_info(dev, "ADSL line: down\n");
 		break;
 
 	case 1:
-		instance->u.atm_dev->signal = ATM_PHY_SIG_LOST;
-		dev_info(&instance->u.usb_dev->dev, "ADSL line: attemtping to activate\n");
+		atm_dev->signal = ATM_PHY_SIG_LOST;
+		dev_info(dev, "ADSL line: attemtping to activate\n");
 		break;
 
 	case 2:
-		instance->u.atm_dev->signal = ATM_PHY_SIG_LOST;
-		dev_info(&instance->u.usb_dev->dev, "ADSL line: training\n");
+		atm_dev->signal = ATM_PHY_SIG_LOST;
+		dev_info(dev, "ADSL line: training\n");
 		break;
 
 	case 3:
-		instance->u.atm_dev->signal = ATM_PHY_SIG_LOST;
-		dev_info(&instance->u.usb_dev->dev, "ADSL line: channel analysis\n");
+		atm_dev->signal = ATM_PHY_SIG_LOST;
+		dev_info(dev, "ADSL line: channel analysis\n");
 		break;
 
 	case 4:
-		instance->u.atm_dev->signal = ATM_PHY_SIG_LOST;
-		dev_info(&instance->u.usb_dev->dev, "ADSL line: exchange\n");
+		atm_dev->signal = ATM_PHY_SIG_LOST;
+		dev_info(dev, "ADSL line: exchange\n");
 		break;
 
 	case 5:
-		instance->u.atm_dev->link_rate = buf[CXINF_DOWNSTREAM_RATE] * 1000 / 424;
-		instance->u.atm_dev->signal = ATM_PHY_SIG_FOUND;
+		atm_dev->link_rate = buf[CXINF_DOWNSTREAM_RATE] * 1000 / 424;
+		atm_dev->signal = ATM_PHY_SIG_FOUND;
 
-		dev_info(&instance->u.usb_dev->dev, "ADSL line: up (%d Kib/s down | %d Kib/s up)\n",
+		dev_info(dev, "ADSL line: up (%d Kib/s down | %d Kib/s up)\n",
 		     buf[CXINF_DOWNSTREAM_RATE], buf[CXINF_UPSTREAM_RATE]);
 		break;
 
 	case 6:
-		instance->u.atm_dev->signal = ATM_PHY_SIG_LOST;
-		dev_info(&instance->u.usb_dev->dev, "ADSL line: waiting\n");
+		atm_dev->signal = ATM_PHY_SIG_LOST;
+		dev_info(dev, "ADSL line: waiting\n");
 		break;
 
 	case 7:
-		instance->u.atm_dev->signal = ATM_PHY_SIG_LOST;
-		dev_info(&instance->u.usb_dev->dev, "ADSL line: initializing\n");
+		atm_dev->signal = ATM_PHY_SIG_LOST;
+		dev_info(dev, "ADSL line: initializing\n");
 		break;
 
 	default:
-		instance->u.atm_dev->signal = ATM_PHY_SIG_UNKNOWN;
-		dev_info(&instance->u.usb_dev->dev, "Unknown line state %02x\n",
-				instance->line_status);
+		atm_dev->signal = ATM_PHY_SIG_UNKNOWN;
+		dev_info(dev, "Unknown line state %02x\n", instance->line_status);
 		break;
 	}
 }
 
 #ifdef USE_FW_LOADER
-static int cxacru_fw(struct cxacru_instance_data *instance, enum cxacru_fw_request fw,
+static int cxacru_fw(struct usb_device *usb_dev, enum cxacru_fw_request fw,
 		     u8 code1, u8 code2, u32 addr, u8 *data, int size)
 {
 	int ret;
 	u8 *buf;
 	int offd, offb;
 	const int stride = CMD_PACKET_SIZE - 8;
-	struct usb_device *usb_dev = instance->u.usb_dev;
 
 	buf = (u8 *) __get_free_page(GFP_KERNEL);
 	if (!buf)
@@ -534,77 +531,78 @@
 	return ret;
 }
 
-static void cxacru_upload_firmware(struct cxacru_instance_data *instance,
+static void cxacru_upload_firmware(struct cxacru_data *instance,
 				   const struct firmware *fw,
 				   const struct firmware *br,
 				   const struct firmware *cf)
 {
 	int ret;
 	int off;
-	struct usb_device *dev = instance->u.usb_dev;
-	const u32 vid = dev->descriptor.idVendor;
-	const u32 pid = dev->descriptor.idProduct;
+	struct usb_device *usb_dev = instance->usbatm.usb_dev;
+	struct device *dev = &usb_dev->dev;
+	const u32 vid = usb_dev->descriptor.idVendor;
+	const u32 pid = usb_dev->descriptor.idProduct;
 	u32 val;
 
 	dbg("cxacru_upload_firmware");
 
 	/* FirmwarePllFClkValue */
 	val = br ? PLLFCLK_OLD : PLLFCLK_NEW;
-	ret = cxacru_fw(instance, FW_WRITE_MEM, 0x2, 0x0, PLLFCLK_ADDR, (u8 *) &val, 4);
+	ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, PLLFCLK_ADDR, (u8 *) &val, 4);
 	if (ret) {
-		err("FirmwarePllFClkValue failed: %d", ret);
+		dev_err(dev, "FirmwarePllFClkValue failed: %d\n", ret);
 		return;
 	}
 
 	/* FirmwarePllBClkValue */
 	val = br ? PLLBCLK_OLD : PLLBCLK_NEW;
-	ret = cxacru_fw(instance, FW_WRITE_MEM, 0x2, 0x0, PLLBCLK_ADDR, (u8 *) &val, 4);
+	ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, PLLBCLK_ADDR, (u8 *) &val, 4);
 	if (ret) {
-		err("FirmwarePllBClkValue failed: %d", ret);
+		dev_err(dev, "FirmwarePllBClkValue failed: %d\n", ret);
 		return;
 	}
 
 	/* Enable SDRAM */
 	val = SDRAM_ENA;
-	ret = cxacru_fw(instance, FW_WRITE_MEM, 0x2, 0x0, SDRAMEN_ADDR, (u8 *) &val, 4);
+	ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, SDRAMEN_ADDR, (u8 *) &val, 4);
 	if (ret) {
-		err("Enable SDRAM failed: %d", ret);
+		dev_err(dev, "Enable SDRAM failed: %d\n", ret);
 		return;
 	}
 
 	/* Firmware */
-	ret = cxacru_fw(instance, FW_WRITE_MEM, 0x2, 0x0, FW_ADDR, fw->data, fw->size);
+	ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, FW_ADDR, fw->data, fw->size);
 	if (ret) {
-		err("Firmware upload failed: %d", ret);
+		dev_err(dev, "Firmware upload failed: %d\n", ret);
 		return;
 	}
 
 	/* Boot ROM patch */
 	if (br) {
-		ret = cxacru_fw(instance, FW_WRITE_MEM, 0x2, 0x0, BR_ADDR, br->data, br->size);
+		ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, BR_ADDR, br->data, br->size);
 		if (ret) {
-			err("Boot ROM patching failed: %d", ret);
+			dev_err(dev, "Boot ROM patching failed: %d\n", ret);
 			return;
 		}
 	}
 
 	/* Signature */
 	val = (pid << 16) | (vid & 0xffff);
-	ret = cxacru_fw(instance, FW_WRITE_MEM, 0x2, 0x0, SIG_ADDR, (u8 *) &val, 4);
+	ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, SIG_ADDR, (u8 *) &val, 4);
 	if (ret) {
-		err("Signature storing failed: %d", ret);
+		dev_err(dev, "Signature storing failed: %d\n", ret);
 		return;
 	}
 
 	if (br) {
 		val = BR_ADDR;
-		ret = cxacru_fw(instance, FW_WRITE_MEM, 0x2, 0x0, BR_STACK_ADDR, (u8 *) &val, 4);
+		ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, BR_STACK_ADDR, (u8 *) &val, 4);
 	}
 	else {
-		ret = cxacru_fw(instance, FW_GOTO_MEM, 0x0, 0x0, FW_ADDR, NULL, 0);
+		ret = cxacru_fw(usb_dev, FW_GOTO_MEM, 0x0, 0x0, FW_ADDR, NULL, 0);
 	}
 	if (ret) {
-		err("Passing control to firmware failed: %d", ret);
+		dev_err(dev, "Passing control to firmware failed: %d\n", ret);
 		return;
 	}
 
@@ -612,14 +610,14 @@
 	   because we're in our own kernel thread anyway. */
 	msleep(1000);
 
-	usb_clear_halt(dev, usb_sndbulkpipe(dev, CXACRU_EP_CMD));
-	usb_clear_halt(dev, usb_rcvbulkpipe(dev, CXACRU_EP_CMD));
-	usb_clear_halt(dev, usb_sndbulkpipe(dev, CXACRU_EP_DATA));
-	usb_clear_halt(dev, usb_rcvbulkpipe(dev, CXACRU_EP_DATA));
+	usb_clear_halt(usb_dev, usb_sndbulkpipe(usb_dev, CXACRU_EP_CMD));
+	usb_clear_halt(usb_dev, usb_rcvbulkpipe(usb_dev, CXACRU_EP_CMD));
+	usb_clear_halt(usb_dev, usb_sndbulkpipe(usb_dev, CXACRU_EP_DATA));
+	usb_clear_halt(usb_dev, usb_rcvbulkpipe(usb_dev, CXACRU_EP_DATA));
 
 	ret = cxacru_cm(instance, CM_REQUEST_CARD_GET_STATUS, NULL, 0, NULL, 0);
 	if (ret < 0) {
-		err("modem failed to initialize: %d", ret);
+		dev_err(dev, "modem failed to initialize: %d\n", ret);
 		return;
 	}
 	
@@ -635,88 +633,81 @@
 		ret = cxacru_cm(instance, CM_REQUEST_CARD_DATA_SET,
 				(u8 *) buf, len, NULL, 0);
 		if (ret < 0) {
-			err("load config data failed: %d", ret);
+			dev_err(dev, "load config data failed: %d\n", ret);
 			return;
 		}
 	}
 
 	msleep(4000);
 
-	dbg("done setting up the modem");
-
-	cxacru_adsl_start(instance);
+	if (cxacru_is_up(instance)) {
+		dbg("done setting up the modem");
+		cxacru_adsl_start(instance);
+	}
+	else
+		dbg("modem initialisation failed");
 }
 
-static int cxacru_find_firmware(struct cxacru_instance_data *instance,
+static int cxacru_find_firmware(struct usbatm_data *instance,
 				char* phase, const struct firmware **fw_p)
 {
+	struct device *dev = &instance->usb_dev->dev;
 	char buf[16];
 
 	sprintf(buf, "cxacru-%s.bin", phase);
 	dbg("cxacru_find_firmware: looking for %s", buf);
 
-	if (request_firmware(fw_p, buf, &instance->u.usb_dev->dev)) {
-		dev_warn(&instance->u.usb_dev->dev, "no stage %s firmware found\n", phase);
+	if (request_firmware(fw_p, buf, dev)) {
+		dev_warn(dev, "no stage %s firmware found\n", phase);
 		return -ENOENT;
 	}
 
-	dev_info(&instance->u.usb_dev->dev, "found firmware %s\n", buf);
+	dev_info(dev, "found firmware %s\n", buf);
 
 	return 0;
 }
 
-static int cxacru_load_firmware(void *arg)
+static void cxacru_heavy_init(struct usbatm_data *usbatm_instance)
 {
 	const struct firmware *fw, *bp, *cf;
-	struct cxacru_instance_data *instance = arg;
-
-	BUG_ON(!instance);
 
-	daemonize("firmware/cxacru");
-
-	if (!cxacru_find_firmware(instance, "fw", &fw)) {
-		if (!cxacru_find_firmware(instance, "cf", &cf)) {
-			if (!cxacru_find_firmware(instance, "bp", &bp))
+	if (!cxacru_find_firmware(usbatm_instance, "fw", &fw)) {
+		if (!cxacru_find_firmware(usbatm_instance, "cf", &cf)) {
+			if (!cxacru_find_firmware(usbatm_instance, "bp", &bp))
 				/* ok, assume it's not needed */
 				bp = NULL;
-			cxacru_upload_firmware(instance, fw, bp, cf);
+			cxacru_upload_firmware(to_cxacru_data(usbatm_instance), fw, bp, cf);
 			release_firmware(cf);
 		}
 		release_firmware(fw);
 	}
-
-	module_put(THIS_MODULE);
-	return 0;
 }
+#endif /* USE_FW_LOADER */
 
-static void cxacru_firmware_start(struct cxacru_instance_data *instance)
+static void cxacru_cleanup(struct usbatm_data *usbatm_instance)
 {
-	int ret;
-
-	try_module_get(THIS_MODULE);
+	struct cxacru_data *instance = to_cxacru_data(usbatm_instance);
 
-	ret = kernel_thread(cxacru_load_firmware, instance,
-			    CLONE_FS | CLONE_FILES);
-
-	if (ret >= 0)
-		return;		/* OK */
+	dbg("cxacru_cleanup");
+	usb_kill_urb(instance->snd_urb);
+	usb_kill_urb(instance->rcv_urb);
+	usb_free_urb(instance->snd_urb);
+	usb_free_urb(instance->rcv_urb);
 
-	dbg("cxacru_firmware_start: kernel_thread failed (%d)!", ret);
+	free_page((unsigned long) instance->snd_buf);
+	free_page((unsigned long) instance->rcv_buf);
 
-	module_put(THIS_MODULE);
+	kfree(instance);
 }
-#endif /* USE_FW_LOADER */
 
 static int cxacru_usb_probe(struct usb_interface *intf,
-			      const struct usb_device_id *id)
+		const struct usb_device_id *id)
 {
-	struct usb_device *dev = interface_to_usbdev(intf);
-	struct cxacru_instance_data *instance;
+	struct cxacru_data *instance;
+	struct usb_device *usb_dev = interface_to_usbdev(intf);
 	int ret;
 
-	dbg("cxacru_usb_probe: trying device with vendor=0x%x, product=0x%x",
-			dev->descriptor.idVendor, dev->descriptor.idProduct);
-
+	dbg("probed device: %p", usb_dev);
 	/* instance init */
 	instance = kmalloc(sizeof(*instance), GFP_KERNEL);
 	if (!instance) {
@@ -724,7 +715,7 @@
 		return -ENOMEM;
 	}
 
-	memset(instance, 0, sizeof(struct cxacru_instance_data));
+	memset(instance, 0, sizeof(*instance));
 
 	instance->rcv_buf = (u8 *) __get_free_page(GFP_KERNEL);
 	if (!instance->rcv_buf) {
@@ -751,23 +742,24 @@
 		goto fail;
 	}
 
-	instance->u.data_endpoint = CXACRU_EP_DATA;
-	instance->u.snd_padding = 11;
-	instance->u.rcv_padding = 3;
-	instance->u.driver_name = cxacru_driver_name;
-	instance->u.usb_dev = dev;
-
-	usb_fill_int_urb(instance->rcv_urb, dev, usb_rcvintpipe(dev, CXACRU_EP_CMD),
-			 instance->rcv_buf, PAGE_SIZE,
-			 cxacru_blocking_completion, &instance->rcv_done, 1);
+	ret = usbatm_init(&instance->usbatm, &cxacru_driver, usb_dev);
+	if (ret < 0) {
+		dbg("cxacru_usb_probe: usbatm_init returned %d", ret);
+		goto fail;
+	}
+
+	usb_fill_int_urb(instance->rcv_urb,
+			usb_dev, usb_rcvintpipe(usb_dev, CXACRU_EP_CMD),
+			instance->rcv_buf, PAGE_SIZE,
+			cxacru_blocking_completion, &instance->rcv_done, 1);
 	instance->rcv_urb->transfer_flags |= URB_ASYNC_UNLINK;
 
-	usb_fill_int_urb(instance->snd_urb, dev, usb_sndintpipe(dev, CXACRU_EP_CMD),
-			 instance->snd_buf, PAGE_SIZE,
-			 cxacru_blocking_completion, &instance->snd_done, 4);
+	usb_fill_int_urb(instance->snd_urb,
+			usb_dev, usb_sndintpipe(usb_dev, CXACRU_EP_CMD),
+			instance->snd_buf, PAGE_SIZE,
+			cxacru_blocking_completion, &instance->snd_done, 4);
 	instance->snd_urb->transfer_flags |= URB_ASYNC_UNLINK;
 
-	init_MUTEX(&instance->start_serialize);
 	init_MUTEX(&instance->cm_serialize);
 
 	init_timer(&instance->poll_timer);
@@ -778,7 +770,12 @@
 
 	usb_set_intfdata(intf, instance);
 
-	cxacru_adsl_start(instance);
+	if (cxacru_is_up(instance))
+		cxacru_adsl_start(instance);
+#ifdef USE_FW_LOADER
+	else
+		usbatm_heavy_init(&instance->usbatm);
+#endif /* USE_FW_LOADER */
 
 	return 0;
 
@@ -798,7 +795,7 @@
 
 static void cxacru_usb_disconnect(struct usb_interface *intf)
 {
-	struct cxacru_instance_data *instance = usb_get_intfdata(intf);
+	struct cxacru_data *instance = usb_get_intfdata(intf);
 
 	dbg("cxacru_usb_disconnect entered");
 
@@ -811,20 +808,9 @@
 	wmb();
 	flush_scheduled_work();
 
-	usb_kill_urb(instance->snd_urb);
-	usb_kill_urb(instance->rcv_urb);
-	usb_free_urb(instance->snd_urb);
-	usb_free_urb(instance->rcv_urb);
-
-	free_page((unsigned long) instance->snd_buf);
-	free_page((unsigned long) instance->rcv_buf);
-
-	udsl_instance_disconnect(&instance->u);
+	usbatm_disconnect(&instance->usbatm);
 
-	/* clean up */
 	usb_set_intfdata(intf, NULL);
-	/* FIXME: do we need this refcount? */
-	udsl_put_instance(&instance->u);
 }
 
 static struct usb_device_id cxacru_usb_ids[] = {




More information about the Usbatm-commits mailing list