aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/sierra.c
diff options
context:
space:
mode:
authorAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
committerAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
commitada47b5fe13d89735805b566185f4885f5a3f750 (patch)
tree644b88f8a71896307d71438e9b3af49126ffb22b /drivers/usb/serial/sierra.c
parent43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff)
parent3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff)
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/usb/serial/sierra.c')
-rw-r--r--drivers/usb/serial/sierra.c153
1 files changed, 116 insertions, 37 deletions
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
index 5019325ba25d..ef0bdb08d788 100644
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -16,8 +16,9 @@
16 Portions based on the option driver by Matthias Urlichs <smurf@smurf.noris.de> 16 Portions based on the option driver by Matthias Urlichs <smurf@smurf.noris.de>
17 Whom based his on the Keyspan driver by Hugh Blemings <hugh@blemings.org> 17 Whom based his on the Keyspan driver by Hugh Blemings <hugh@blemings.org>
18*/ 18*/
19 19/* Uncomment to log function calls */
20#define DRIVER_VERSION "v.1.3.8" 20/* #define DEBUG */
21#define DRIVER_VERSION "v.1.7.16"
21#define DRIVER_AUTHOR "Kevin Lloyd, Elina Pasheva, Matthew Safar, Rory Filer" 22#define DRIVER_AUTHOR "Kevin Lloyd, Elina Pasheva, Matthew Safar, Rory Filer"
22#define DRIVER_DESC "USB Driver for Sierra Wireless USB modems" 23#define DRIVER_DESC "USB Driver for Sierra Wireless USB modems"
23 24
@@ -25,6 +26,7 @@
25#include <linux/jiffies.h> 26#include <linux/jiffies.h>
26#include <linux/errno.h> 27#include <linux/errno.h>
27#include <linux/tty.h> 28#include <linux/tty.h>
29#include <linux/slab.h>
28#include <linux/tty_flip.h> 30#include <linux/tty_flip.h>
29#include <linux/module.h> 31#include <linux/module.h>
30#include <linux/usb.h> 32#include <linux/usb.h>
@@ -33,8 +35,10 @@
33#define SWIMS_USB_REQUEST_SetPower 0x00 35#define SWIMS_USB_REQUEST_SetPower 0x00
34#define SWIMS_USB_REQUEST_SetNmea 0x07 36#define SWIMS_USB_REQUEST_SetNmea 0x07
35 37
36#define N_IN_URB 8 38#define N_IN_URB_HM 8
37#define N_OUT_URB 64 39#define N_OUT_URB_HM 64
40#define N_IN_URB 4
41#define N_OUT_URB 4
38#define IN_BUFLEN 4096 42#define IN_BUFLEN 4096
39 43
40#define MAX_TRANSFER (PAGE_SIZE - 512) 44#define MAX_TRANSFER (PAGE_SIZE - 512)
@@ -124,6 +128,23 @@ static int is_blacklisted(const u8 ifnum,
124 return 0; 128 return 0;
125} 129}
126 130
131static int is_himemory(const u8 ifnum,
132 const struct sierra_iface_info *himemorylist)
133{
134 const u8 *info;
135 int i;
136
137 if (himemorylist) {
138 info = himemorylist->ifaceinfo;
139
140 for (i=0; i < himemorylist->infolen; i++) {
141 if (info[i] == ifnum)
142 return 1;
143 }
144 }
145 return 0;
146}
147
127static int sierra_calc_interface(struct usb_serial *serial) 148static int sierra_calc_interface(struct usb_serial *serial)
128{ 149{
129 int interface; 150 int interface;
@@ -186,15 +207,30 @@ static int sierra_probe(struct usb_serial *serial,
186 return result; 207 return result;
187} 208}
188 209
210/* interfaces with higher memory requirements */
211static const u8 hi_memory_typeA_ifaces[] = { 0, 2 };
212static const struct sierra_iface_info typeA_interface_list = {
213 .infolen = ARRAY_SIZE(hi_memory_typeA_ifaces),
214 .ifaceinfo = hi_memory_typeA_ifaces,
215};
216
217static const u8 hi_memory_typeB_ifaces[] = { 3, 4, 5, 6 };
218static const struct sierra_iface_info typeB_interface_list = {
219 .infolen = ARRAY_SIZE(hi_memory_typeB_ifaces),
220 .ifaceinfo = hi_memory_typeB_ifaces,
221};
222
223/* 'blacklist' of interfaces not served by this driver */
189static const u8 direct_ip_non_serial_ifaces[] = { 7, 8, 9, 10, 11 }; 224static const u8 direct_ip_non_serial_ifaces[] = { 7, 8, 9, 10, 11 };
190static const struct sierra_iface_info direct_ip_interface_blacklist = { 225static const struct sierra_iface_info direct_ip_interface_blacklist = {
191 .infolen = ARRAY_SIZE(direct_ip_non_serial_ifaces), 226 .infolen = ARRAY_SIZE(direct_ip_non_serial_ifaces),
192 .ifaceinfo = direct_ip_non_serial_ifaces, 227 .ifaceinfo = direct_ip_non_serial_ifaces,
193}; 228};
194 229
195static struct usb_device_id id_table [] = { 230static const struct usb_device_id id_table[] = {
196 { USB_DEVICE(0x0F3D, 0x0112) }, /* Airprime/Sierra PC 5220 */ 231 { USB_DEVICE(0x0F3D, 0x0112) }, /* Airprime/Sierra PC 5220 */
197 { USB_DEVICE(0x03F0, 0x1B1D) }, /* HP ev2200 a.k.a MC5720 */ 232 { USB_DEVICE(0x03F0, 0x1B1D) }, /* HP ev2200 a.k.a MC5720 */
233 { USB_DEVICE(0x03F0, 0x211D) }, /* HP ev2210 a.k.a MC5725 */
198 { USB_DEVICE(0x03F0, 0x1E1D) }, /* HP hs2300 a.k.a MC8775 */ 234 { USB_DEVICE(0x03F0, 0x1E1D) }, /* HP hs2300 a.k.a MC8775 */
199 235
200 { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */ 236 { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */
@@ -264,21 +300,12 @@ static struct usb_device_id id_table [] = {
264 { USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless Direct IP modems */ 300 { USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless Direct IP modems */
265 .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist 301 .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
266 }, 302 },
303 { USB_DEVICE(0x413C, 0x08133) }, /* Dell Computer Corp. Wireless 5720 VZW Mobile Broadband (EVDO Rev-A) Minicard GPS Port */
267 304
268 { } 305 { }
269}; 306};
270MODULE_DEVICE_TABLE(usb, id_table); 307MODULE_DEVICE_TABLE(usb, id_table);
271 308
272static struct usb_driver sierra_driver = {
273 .name = "sierra",
274 .probe = usb_serial_probe,
275 .disconnect = usb_serial_disconnect,
276 .suspend = usb_serial_suspend,
277 .resume = usb_serial_resume,
278 .id_table = id_table,
279 .no_dynamic_id = 1,
280 .supports_autosuspend = 1,
281};
282 309
283struct sierra_port_private { 310struct sierra_port_private {
284 spinlock_t lock; /* lock the structure */ 311 spinlock_t lock; /* lock the structure */
@@ -286,8 +313,10 @@ struct sierra_port_private {
286 struct usb_anchor active; 313 struct usb_anchor active;
287 struct usb_anchor delayed; 314 struct usb_anchor delayed;
288 315
316 int num_out_urbs;
317 int num_in_urbs;
289 /* Input endpoints and buffers for this port */ 318 /* Input endpoints and buffers for this port */
290 struct urb *in_urbs[N_IN_URB]; 319 struct urb *in_urbs[N_IN_URB_HM];
291 320
292 /* Settings for the port */ 321 /* Settings for the port */
293 int rts_state; /* Handshaking pins (outputs) */ 322 int rts_state; /* Handshaking pins (outputs) */
@@ -440,7 +469,7 @@ static void sierra_outdat_callback(struct urb *urb)
440static int sierra_write(struct tty_struct *tty, struct usb_serial_port *port, 469static int sierra_write(struct tty_struct *tty, struct usb_serial_port *port,
441 const unsigned char *buf, int count) 470 const unsigned char *buf, int count)
442{ 471{
443 struct sierra_port_private *portdata = usb_get_serial_port_data(port); 472 struct sierra_port_private *portdata;
444 struct sierra_intf_private *intfdata; 473 struct sierra_intf_private *intfdata;
445 struct usb_serial *serial = port->serial; 474 struct usb_serial *serial = port->serial;
446 unsigned long flags; 475 unsigned long flags;
@@ -460,7 +489,7 @@ static int sierra_write(struct tty_struct *tty, struct usb_serial_port *port,
460 spin_lock_irqsave(&portdata->lock, flags); 489 spin_lock_irqsave(&portdata->lock, flags);
461 dev_dbg(&port->dev, "%s - outstanding_urbs: %d\n", __func__, 490 dev_dbg(&port->dev, "%s - outstanding_urbs: %d\n", __func__,
462 portdata->outstanding_urbs); 491 portdata->outstanding_urbs);
463 if (portdata->outstanding_urbs > N_OUT_URB) { 492 if (portdata->outstanding_urbs > portdata->num_out_urbs) {
464 spin_unlock_irqrestore(&portdata->lock, flags); 493 spin_unlock_irqrestore(&portdata->lock, flags);
465 dev_dbg(&port->dev, "%s - write limit hit\n", __func__); 494 dev_dbg(&port->dev, "%s - write limit hit\n", __func__);
466 return 0; 495 return 0;
@@ -567,14 +596,15 @@ static void sierra_indat_callback(struct urb *urb)
567 } else { 596 } else {
568 if (urb->actual_length) { 597 if (urb->actual_length) {
569 tty = tty_port_tty_get(&port->port); 598 tty = tty_port_tty_get(&port->port);
570 599 if (tty) {
571 tty_buffer_request_room(tty, urb->actual_length); 600 tty_insert_flip_string(tty, data,
572 tty_insert_flip_string(tty, data, urb->actual_length); 601 urb->actual_length);
573 tty_flip_buffer_push(tty); 602 tty_flip_buffer_push(tty);
574 603
575 tty_kref_put(tty); 604 tty_kref_put(tty);
576 usb_serial_debug_data(debug, &port->dev, __func__, 605 usb_serial_debug_data(debug, &port->dev,
577 urb->actual_length, data); 606 __func__, urb->actual_length, data);
607 }
578 } else { 608 } else {
579 dev_dbg(&port->dev, "%s: empty read urb" 609 dev_dbg(&port->dev, "%s: empty read urb"
580 " received\n", __func__); 610 " received\n", __func__);
@@ -582,10 +612,10 @@ static void sierra_indat_callback(struct urb *urb)
582 } 612 }
583 613
584 /* Resubmit urb so we continue receiving */ 614 /* Resubmit urb so we continue receiving */
585 if (port->port.count && status != -ESHUTDOWN && status != -EPERM) { 615 if (status != -ESHUTDOWN && status != -EPERM) {
586 usb_mark_last_busy(port->serial->dev); 616 usb_mark_last_busy(port->serial->dev);
587 err = usb_submit_urb(urb, GFP_ATOMIC); 617 err = usb_submit_urb(urb, GFP_ATOMIC);
588 if (err) 618 if (err && err != -EPERM)
589 dev_err(&port->dev, "resubmit read urb failed." 619 dev_err(&port->dev, "resubmit read urb failed."
590 "(%d)\n", err); 620 "(%d)\n", err);
591 } 621 }
@@ -644,11 +674,11 @@ static void sierra_instat_callback(struct urb *urb)
644 dev_dbg(&port->dev, "%s: error %d\n", __func__, status); 674 dev_dbg(&port->dev, "%s: error %d\n", __func__, status);
645 675
646 /* Resubmit urb so we continue receiving IRQ data */ 676 /* Resubmit urb so we continue receiving IRQ data */
647 if (port->port.count && status != -ESHUTDOWN && status != -ENOENT) { 677 if (status != -ESHUTDOWN && status != -ENOENT) {
648 usb_mark_last_busy(serial->dev); 678 usb_mark_last_busy(serial->dev);
649 urb->dev = serial->dev; 679 urb->dev = serial->dev;
650 err = usb_submit_urb(urb, GFP_ATOMIC); 680 err = usb_submit_urb(urb, GFP_ATOMIC);
651 if (err) 681 if (err && err != -EPERM)
652 dev_err(&port->dev, "%s: resubmit intr urb " 682 dev_err(&port->dev, "%s: resubmit intr urb "
653 "failed. (%d)\n", __func__, err); 683 "failed. (%d)\n", __func__, err);
654 } 684 }
@@ -665,7 +695,7 @@ static int sierra_write_room(struct tty_struct *tty)
665 /* try to give a good number back based on if we have any free urbs at 695 /* try to give a good number back based on if we have any free urbs at
666 * this point in time */ 696 * this point in time */
667 spin_lock_irqsave(&portdata->lock, flags); 697 spin_lock_irqsave(&portdata->lock, flags);
668 if (portdata->outstanding_urbs > N_OUT_URB * 2 / 3) { 698 if (portdata->outstanding_urbs > (portdata->num_out_urbs * 2) / 3) {
669 spin_unlock_irqrestore(&portdata->lock, flags); 699 spin_unlock_irqrestore(&portdata->lock, flags);
670 dev_dbg(&port->dev, "%s - write limit hit\n", __func__); 700 dev_dbg(&port->dev, "%s - write limit hit\n", __func__);
671 return 0; 701 return 0;
@@ -680,7 +710,7 @@ static void sierra_stop_rx_urbs(struct usb_serial_port *port)
680 int i; 710 int i;
681 struct sierra_port_private *portdata = usb_get_serial_port_data(port); 711 struct sierra_port_private *portdata = usb_get_serial_port_data(port);
682 712
683 for (i = 0; i < ARRAY_SIZE(portdata->in_urbs); i++) 713 for (i = 0; i < portdata->num_in_urbs; i++)
684 usb_kill_urb(portdata->in_urbs[i]); 714 usb_kill_urb(portdata->in_urbs[i]);
685 715
686 usb_kill_urb(port->interrupt_in_urb); 716 usb_kill_urb(port->interrupt_in_urb);
@@ -695,7 +725,7 @@ static int sierra_submit_rx_urbs(struct usb_serial_port *port, gfp_t mem_flags)
695 struct sierra_port_private *portdata = usb_get_serial_port_data(port); 725 struct sierra_port_private *portdata = usb_get_serial_port_data(port);
696 726
697 ok_cnt = 0; 727 ok_cnt = 0;
698 for (i = 0; i < ARRAY_SIZE(portdata->in_urbs); i++) { 728 for (i = 0; i < portdata->num_in_urbs; i++) {
699 urb = portdata->in_urbs[i]; 729 urb = portdata->in_urbs[i];
700 if (!urb) 730 if (!urb)
701 continue; 731 continue;
@@ -791,7 +821,7 @@ static void sierra_close(struct usb_serial_port *port)
791 /* Stop reading urbs */ 821 /* Stop reading urbs */
792 sierra_stop_rx_urbs(port); 822 sierra_stop_rx_urbs(port);
793 /* .. and release them */ 823 /* .. and release them */
794 for (i = 0; i < N_IN_URB; i++) { 824 for (i = 0; i < portdata->num_in_urbs; i++) {
795 sierra_release_urb(portdata->in_urbs[i]); 825 sierra_release_urb(portdata->in_urbs[i]);
796 portdata->in_urbs[i] = NULL; 826 portdata->in_urbs[i] = NULL;
797 } 827 }
@@ -818,7 +848,7 @@ static int sierra_open(struct tty_struct *tty, struct usb_serial_port *port)
818 848
819 849
820 endpoint = port->bulk_in_endpointAddress; 850 endpoint = port->bulk_in_endpointAddress;
821 for (i = 0; i < ARRAY_SIZE(portdata->in_urbs); i++) { 851 for (i = 0; i < portdata->num_in_urbs; i++) {
822 urb = sierra_setup_urb(serial, endpoint, USB_DIR_IN, port, 852 urb = sierra_setup_urb(serial, endpoint, USB_DIR_IN, port,
823 IN_BUFLEN, GFP_KERNEL, 853 IN_BUFLEN, GFP_KERNEL,
824 sierra_indat_callback); 854 sierra_indat_callback);
@@ -869,7 +899,9 @@ static int sierra_startup(struct usb_serial *serial)
869{ 899{
870 struct usb_serial_port *port; 900 struct usb_serial_port *port;
871 struct sierra_port_private *portdata; 901 struct sierra_port_private *portdata;
902 struct sierra_iface_info *himemoryp = NULL;
872 int i; 903 int i;
904 u8 ifnum;
873 905
874 dev_dbg(&serial->dev->dev, "%s\n", __func__); 906 dev_dbg(&serial->dev->dev, "%s\n", __func__);
875 907
@@ -886,13 +918,40 @@ static int sierra_startup(struct usb_serial *serial)
886 portdata = kzalloc(sizeof(*portdata), GFP_KERNEL); 918 portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
887 if (!portdata) { 919 if (!portdata) {
888 dev_dbg(&port->dev, "%s: kmalloc for " 920 dev_dbg(&port->dev, "%s: kmalloc for "
889 "sierra_port_private (%d) failed!.\n", 921 "sierra_port_private (%d) failed!\n",
890 __func__, i); 922 __func__, i);
891 return -ENOMEM; 923 return -ENOMEM;
892 } 924 }
893 spin_lock_init(&portdata->lock); 925 spin_lock_init(&portdata->lock);
894 init_usb_anchor(&portdata->active); 926 init_usb_anchor(&portdata->active);
895 init_usb_anchor(&portdata->delayed); 927 init_usb_anchor(&portdata->delayed);
928 ifnum = i;
929 /* Assume low memory requirements */
930 portdata->num_out_urbs = N_OUT_URB;
931 portdata->num_in_urbs = N_IN_URB;
932
933 /* Determine actual memory requirements */
934 if (serial->num_ports == 1) {
935 /* Get interface number for composite device */
936 ifnum = sierra_calc_interface(serial);
937 himemoryp =
938 (struct sierra_iface_info *)&typeB_interface_list;
939 if (is_himemory(ifnum, himemoryp)) {
940 portdata->num_out_urbs = N_OUT_URB_HM;
941 portdata->num_in_urbs = N_IN_URB_HM;
942 }
943 }
944 else {
945 himemoryp =
946 (struct sierra_iface_info *)&typeA_interface_list;
947 if (is_himemory(i, himemoryp)) {
948 portdata->num_out_urbs = N_OUT_URB_HM;
949 portdata->num_in_urbs = N_IN_URB_HM;
950 }
951 }
952 dev_dbg(&serial->dev->dev,
953 "Memory usage (urbs) interface #%d, in=%d, out=%d\n",
954 ifnum,portdata->num_in_urbs, portdata->num_out_urbs );
896 /* Set the port private data pointer */ 955 /* Set the port private data pointer */
897 usb_set_serial_port_data(port, portdata); 956 usb_set_serial_port_data(port, portdata);
898 } 957 }
@@ -940,7 +999,7 @@ static int sierra_suspend(struct usb_serial *serial, pm_message_t message)
940 struct sierra_intf_private *intfdata; 999 struct sierra_intf_private *intfdata;
941 int b; 1000 int b;
942 1001
943 if (serial->dev->auto_pm) { 1002 if (message.event & PM_EVENT_AUTO) {
944 intfdata = serial->private; 1003 intfdata = serial->private;
945 spin_lock_irq(&intfdata->susp_lock); 1004 spin_lock_irq(&intfdata->susp_lock);
946 b = intfdata->in_flight; 1005 b = intfdata->in_flight;
@@ -995,11 +1054,31 @@ static int sierra_resume(struct usb_serial *serial)
995 1054
996 return ec ? -EIO : 0; 1055 return ec ? -EIO : 0;
997} 1056}
1057
1058static int sierra_reset_resume(struct usb_interface *intf)
1059{
1060 struct usb_serial *serial = usb_get_intfdata(intf);
1061 dev_err(&serial->dev->dev, "%s\n", __func__);
1062 return usb_serial_resume(intf);
1063}
998#else 1064#else
999#define sierra_suspend NULL 1065#define sierra_suspend NULL
1000#define sierra_resume NULL 1066#define sierra_resume NULL
1067#define sierra_reset_resume NULL
1001#endif 1068#endif
1002 1069
1070static struct usb_driver sierra_driver = {
1071 .name = "sierra",
1072 .probe = usb_serial_probe,
1073 .disconnect = usb_serial_disconnect,
1074 .suspend = usb_serial_suspend,
1075 .resume = usb_serial_resume,
1076 .reset_resume = sierra_reset_resume,
1077 .id_table = id_table,
1078 .no_dynamic_id = 1,
1079 .supports_autosuspend = 1,
1080};
1081
1003static struct usb_serial_driver sierra_device = { 1082static struct usb_serial_driver sierra_device = {
1004 .driver = { 1083 .driver = {
1005 .owner = THIS_MODULE, 1084 .owner = THIS_MODULE,