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