speedtch speedtch.c,1.51,1.52

Duncan Sands duncan at infradead.org
Sun Apr 24 17:07:27 EDT 2005


Update of /home/cvs/speedtch
In directory phoenix.infradead.org:/tmp/cvs-serv18723

Modified Files:
	speedtch.c 
Log Message:
Restore the interrupt endpoint stuff.  I made the completion handler more
conservative about when it resubmits the urb - I want to avoid getting into
tight loops (something the corresponding user-space driver used to do from
time to time).  The interaction with polling and reading the status registers
could be done better I reckon, but this will do fine for the moment.


Index: speedtch.c
===================================================================
RCS file: /home/cvs/speedtch/speedtch.c,v
retrieving revision 1.51
retrieving revision 1.52
diff -u -r1.51 -r1.52
--- speedtch.c	22 Apr 2005 08:12:36 -0000	1.51
+++ speedtch.c	24 Apr 2005 21:07:24 -0000	1.52
@@ -169,63 +169,6 @@
 		usb_warn(usbatm, "%s failed on URB150: %d\n", __func__, ret);
 }
 
-//static void speedtch_handle_int(struct urb *urb, struct pt_regs *regs)
-//{
-//	struct speedtch_instance_data *instance = urb->context;
-//	unsigned int count = urb->actual_length;
-//	int ret;
-//
-//	/* The magic interrupt for "up state" */
-//	const static unsigned char up_int[6]   = { 0xa1, 0x00, 0x01, 0x00, 0x00, 0x00 };
-//	/* The magic interrupt for "down state" */
-//	const static unsigned char down_int[6] = { 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00 };
-//
-//	switch (urb->status) {
-//	case 0:
-//		/* success */
-//		break;
-//	case -ECONNRESET:
-//	case -ENOENT:
-//	case -ESHUTDOWN:
-//		/* this urb is terminated; clean up */
-//		dbg("%s - urb shutting down with status: %d", __func__, urb->status);
-//		return;
-//	default:
-//		dbg("%s - nonzero urb status received: %d", __func__, urb->status);
-//		goto exit;
-//	}
-//
-//	if (count < 6) {
-//		dbg("%s - int packet too short", __func__);
-//		goto exit;
-//	}
-//
-//	if (!memcmp(up_int, instance->int_data, 6)) {
-//		del_timer(&instance->poll_timer);
-//		printk(KERN_NOTICE "DSL line goes up\n");
-//	} else if (!memcmp(down_int, instance->int_data, 6)) {
-//		printk(KERN_NOTICE "DSL line goes down\n");
-//	} else {
-//		int i;
-//
-//		printk(KERN_DEBUG "Unknown interrupt packet of %d bytes:", count);
-//		for (i = 0; i < count; i++)
-//			printk(" %02x", instance->int_data[i]);
-//		printk("\n");
-//	}
-//	schedule_work(&instance->check_status);
-//
-// exit:
-//	rmb();
-//	if (!instance->int_urb)
-//		return;
-//
-//	ret = usb_submit_urb(urb, GFP_ATOMIC);
-//	if (ret)
-//		err("%s - usb_submit_urb failed with result %d", __func__, ret);
-//}
-//
-
 static int speedtch_upload_firmware(struct speedtch_instance_data *instance,
 				     const struct firmware *fw1,
 				     const struct firmware *fw2)
@@ -562,6 +505,44 @@
 		atm_warn(instance->usbatm, "Too many failures - disabling line status polling\n");
 }
 
+static void speedtch_handle_int(struct urb *urb, struct pt_regs *regs)
+{
+	struct speedtch_instance_data *instance = urb->context;
+	struct usbatm_data *usbatm = instance->usbatm;
+	unsigned int count = urb->actual_length;
+	int ret;
+
+	/* The magic interrupt for "up state" */
+	const static unsigned char up_int[6]   = { 0xa1, 0x00, 0x01, 0x00, 0x00, 0x00 };
+	/* The magic interrupt for "down state" */
+	const static unsigned char down_int[6] = { 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+	if (urb->status) {
+		atm_dbg(usbatm, "%s: nonzero urb status %d!\n", __func__, urb->status);
+		return;
+	}
+
+	if ((count == 6) && !memcmp(up_int, instance->int_data, 6)) {
+		del_timer(&instance->poll_timer);
+		atm_info(usbatm, "DSL line goes up\n");
+	} else if ((count == 6) && !memcmp(down_int, instance->int_data, 6)) {
+		atm_info(usbatm, "DSL line goes down\n");
+	} else {
+		int i;
+
+		atm_dbg(usbatm, "%s: unknown interrupt packet of length %d:", __func__, count);
+		for (i = 0; i < count; i++)
+			printk(" %02x", instance->int_data[i]);
+		printk("\n");
+	}
+
+	schedule_work(&instance->check_status);
+
+	ret = usb_submit_urb(urb, GFP_ATOMIC);
+	if (ret < 0)
+		atm_dbg(usbatm, "%s: usb_submit_urb failed with result %d\n", __func__, ret);
+}
+
 static int speedtch_atm_start(struct usbatm_data *usbatm, struct atm_dev *atm_dev)
 {
 	struct usb_device *usb_dev = usbatm->usb_dev;
@@ -583,36 +564,24 @@
 			atm_dev->esi[i] = (hex2int(mac_str[i * 2]) * 16) + (hex2int(mac_str[i * 2 + 1]));
 	}
 
-//	/* Set up interrupt endpoint */
-//	intf = usb_ifnum_to_if(instance->u.usb_dev, 0);
-//	if (intf && !usb_driver_claim_interface(&speedtch_usb_driver, intf, NULL)) {
-//
-//		instance->int_urb = usb_alloc_urb(0, GFP_KERNEL);
-//		if (instance->int_urb) {
-//
-//			usb_fill_int_urb(instance->int_urb, instance->u.usb_dev,
-//					 usb_rcvintpipe(instance->u.usb_dev, SPEEDTCH_ENDPOINT_INT),
-//					 instance->int_data,
-//					 sizeof(instance->int_data),
-//					 speedtch_handle_int, instance, 50);
-//			err = usb_submit_urb(instance->int_urb, GFP_KERNEL);
-//			if (err) {
-//				/* Doesn't matter; we'll poll anyway */
-//				dbg("speedtch_got_firmware: Submission of interrupt URB failed %d", err);
-//				usb_free_urb(instance->int_urb);
-//				instance->int_urb = NULL;
-//				usb_driver_release_interface(&speedtch_usb_driver, intf);
-//			}
-//		}
-//	}
-
 	/* Start modem synchronisation */
 	ret = speedtch_start_synchro(instance);
 
 	/* Start status polling */
 	mod_timer(&instance->poll_timer, jiffies + (1 * HZ));
 
-	return ret;
+	/* Set up interrupt endpoint */
+	if (instance->int_urb) {
+		ret = usb_submit_urb(instance->int_urb, GFP_KERNEL);
+		if (ret < 0) {
+			/* Doesn't matter; we'll poll anyway */
+			atm_dbg(usbatm, "%s: submission of interrupt URB failed (%d)!\n", __func__, ret);
+			usb_free_urb(instance->int_urb);
+			instance->int_urb = NULL;
+		}
+	}
+
+	return 0;
 }
 
 static void speedtch_atm_stop(struct usbatm_data *usbatm, struct atm_dev *atm_dev)
@@ -622,6 +591,7 @@
 	atm_dbg(usbatm, "%s entered\n", __func__);
 
 	del_timer_sync(&instance->poll_timer);
+	usb_kill_urb(instance->int_urb);
 	wmb();
 	flush_scheduled_work();
 }
@@ -707,11 +677,22 @@
 	instance->usbatm = usbatm;
 
 	INIT_WORK(&instance->check_status, (void *)speedtch_check_status, instance);
+
 	init_timer(&instance->poll_timer);
 	instance->poll_timer.function = speedtch_status_poll;
 	instance->poll_timer.data = (unsigned long)instance;
 	instance->poll_delay = SPEEDTCH_MIN_POLL_DELAY;
 
+	instance->int_urb = usb_alloc_urb(0, GFP_KERNEL);
+
+	if (instance->int_urb)
+		usb_fill_int_urb(instance->int_urb, usb_dev,
+				 usb_rcvintpipe(usb_dev, SPEEDTCH_ENDPOINT_INT),
+				 instance->int_data, sizeof(instance->int_data),
+				 speedtch_handle_int, instance, 50);
+	else
+		usb_dbg(usbatm, "%s: no memory for interrupt urb!\n", __func__);
+
 	/* check whether the modem already seems to be alive */
 	ret = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
 			      0x12, 0xc0, 0x07, 0x00,
@@ -730,6 +711,7 @@
 	return 0;
 
 fail_free:
+	usb_free_urb(instance->int_urb);
 	kfree(instance);
 fail_release:
 	speedtch_release_interfaces(usb_dev, num_interfaces);
@@ -744,6 +726,7 @@
 	usb_dbg(usbatm, "%s entered\n", __func__);
 	
 	speedtch_release_interfaces(usb_dev, usb_dev->actconfig->desc.bNumInterfaces);
+	usb_free_urb(instance->int_urb);
 	kfree(instance);
 }
 




More information about the Usbatm-commits mailing list