diff options
author | Matthew Garrett <mjg@redhat.com> | 2010-04-01 12:31:08 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-05-20 16:21:37 -0400 |
commit | 8b4c6a3ab596961b784659c71dc24b341f938a1a (patch) | |
tree | 7968134c21713297f1daba2e43eefba986c1d8b5 /drivers/usb/serial/option.c | |
parent | 0d4561947b8ddd5d944bdbbdc1ea1d6fd9a06041 (diff) |
USB: option: Use generic USB wwan code
As this code was simply factored out of option, this is a simple
conversion.
Signed-off-by: Matthew Garrett <mjg@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/serial/option.c')
-rw-r--r-- | drivers/usb/serial/option.c | 672 |
1 files changed, 26 insertions, 646 deletions
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 6d0dfd7da98c..1775e4554659 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c | |||
@@ -42,35 +42,14 @@ | |||
42 | #include <linux/bitops.h> | 42 | #include <linux/bitops.h> |
43 | #include <linux/usb.h> | 43 | #include <linux/usb.h> |
44 | #include <linux/usb/serial.h> | 44 | #include <linux/usb/serial.h> |
45 | #include "usb-wwan.h" | ||
45 | 46 | ||
46 | /* Function prototypes */ | 47 | /* Function prototypes */ |
47 | static int option_probe(struct usb_serial *serial, | 48 | static int option_probe(struct usb_serial *serial, |
48 | const struct usb_device_id *id); | 49 | const struct usb_device_id *id); |
49 | static int option_open(struct tty_struct *tty, struct usb_serial_port *port); | 50 | static int option_send_setup(struct usb_serial_port *port); |
50 | static void option_close(struct usb_serial_port *port); | ||
51 | static void option_dtr_rts(struct usb_serial_port *port, int on); | ||
52 | |||
53 | static int option_startup(struct usb_serial *serial); | ||
54 | static void option_disconnect(struct usb_serial *serial); | ||
55 | static void option_release(struct usb_serial *serial); | ||
56 | static int option_write_room(struct tty_struct *tty); | ||
57 | |||
58 | static void option_instat_callback(struct urb *urb); | 51 | static void option_instat_callback(struct urb *urb); |
59 | 52 | ||
60 | static int option_write(struct tty_struct *tty, struct usb_serial_port *port, | ||
61 | const unsigned char *buf, int count); | ||
62 | static int option_chars_in_buffer(struct tty_struct *tty); | ||
63 | static void option_set_termios(struct tty_struct *tty, | ||
64 | struct usb_serial_port *port, struct ktermios *old); | ||
65 | static int option_tiocmget(struct tty_struct *tty, struct file *file); | ||
66 | static int option_tiocmset(struct tty_struct *tty, struct file *file, | ||
67 | unsigned int set, unsigned int clear); | ||
68 | static int option_send_setup(struct usb_serial_port *port); | ||
69 | #ifdef CONFIG_PM | ||
70 | static int option_suspend(struct usb_serial *serial, pm_message_t message); | ||
71 | static int option_resume(struct usb_serial *serial); | ||
72 | #endif | ||
73 | |||
74 | /* Vendor and product IDs */ | 53 | /* Vendor and product IDs */ |
75 | #define OPTION_VENDOR_ID 0x0AF0 | 54 | #define OPTION_VENDOR_ID 0x0AF0 |
76 | #define OPTION_PRODUCT_COLT 0x5000 | 55 | #define OPTION_PRODUCT_COLT 0x5000 |
@@ -757,22 +736,22 @@ static struct usb_serial_driver option_1port_device = { | |||
757 | .id_table = option_ids, | 736 | .id_table = option_ids, |
758 | .num_ports = 1, | 737 | .num_ports = 1, |
759 | .probe = option_probe, | 738 | .probe = option_probe, |
760 | .open = option_open, | 739 | .open = usb_wwan_open, |
761 | .close = option_close, | 740 | .close = usb_wwan_close, |
762 | .dtr_rts = option_dtr_rts, | 741 | .dtr_rts = usb_wwan_dtr_rts, |
763 | .write = option_write, | 742 | .write = usb_wwan_write, |
764 | .write_room = option_write_room, | 743 | .write_room = usb_wwan_write_room, |
765 | .chars_in_buffer = option_chars_in_buffer, | 744 | .chars_in_buffer = usb_wwan_chars_in_buffer, |
766 | .set_termios = option_set_termios, | 745 | .set_termios = usb_wwan_set_termios, |
767 | .tiocmget = option_tiocmget, | 746 | .tiocmget = usb_wwan_tiocmget, |
768 | .tiocmset = option_tiocmset, | 747 | .tiocmset = usb_wwan_tiocmset, |
769 | .attach = option_startup, | 748 | .attach = usb_wwan_startup, |
770 | .disconnect = option_disconnect, | 749 | .disconnect = usb_wwan_disconnect, |
771 | .release = option_release, | 750 | .release = usb_wwan_release, |
772 | .read_int_callback = option_instat_callback, | 751 | .read_int_callback = option_instat_callback, |
773 | #ifdef CONFIG_PM | 752 | #ifdef CONFIG_PM |
774 | .suspend = option_suspend, | 753 | .suspend = usb_wwan_suspend, |
775 | .resume = option_resume, | 754 | .resume = usb_wwan_resume, |
776 | #endif | 755 | #endif |
777 | }; | 756 | }; |
778 | 757 | ||
@@ -785,13 +764,6 @@ static int debug; | |||
785 | #define IN_BUFLEN 4096 | 764 | #define IN_BUFLEN 4096 |
786 | #define OUT_BUFLEN 4096 | 765 | #define OUT_BUFLEN 4096 |
787 | 766 | ||
788 | struct option_intf_private { | ||
789 | spinlock_t susp_lock; | ||
790 | unsigned int suspended:1; | ||
791 | int in_flight; | ||
792 | struct option_blacklist_info *blacklist_info; | ||
793 | }; | ||
794 | |||
795 | struct option_port_private { | 767 | struct option_port_private { |
796 | /* Input endpoints and buffer for this port */ | 768 | /* Input endpoints and buffer for this port */ |
797 | struct urb *in_urbs[N_IN_URB]; | 769 | struct urb *in_urbs[N_IN_URB]; |
@@ -848,8 +820,7 @@ module_exit(option_exit); | |||
848 | static int option_probe(struct usb_serial *serial, | 820 | static int option_probe(struct usb_serial *serial, |
849 | const struct usb_device_id *id) | 821 | const struct usb_device_id *id) |
850 | { | 822 | { |
851 | struct option_intf_private *data; | 823 | struct usb_wwan_intf_private *data; |
852 | |||
853 | /* D-Link DWM 652 still exposes CD-Rom emulation interface in modem mode */ | 824 | /* D-Link DWM 652 still exposes CD-Rom emulation interface in modem mode */ |
854 | if (serial->dev->descriptor.idVendor == DLINK_VENDOR_ID && | 825 | if (serial->dev->descriptor.idVendor == DLINK_VENDOR_ID && |
855 | serial->dev->descriptor.idProduct == DLINK_PRODUCT_DWM_652 && | 826 | serial->dev->descriptor.idProduct == DLINK_PRODUCT_DWM_652 && |
@@ -862,11 +833,13 @@ static int option_probe(struct usb_serial *serial, | |||
862 | serial->interface->cur_altsetting->desc.bInterfaceClass != 0xff) | 833 | serial->interface->cur_altsetting->desc.bInterfaceClass != 0xff) |
863 | return -ENODEV; | 834 | return -ENODEV; |
864 | 835 | ||
865 | data = serial->private = kzalloc(sizeof(struct option_intf_private), GFP_KERNEL); | 836 | data = serial->private = kzalloc(sizeof(struct usb_wwan_intf_private), GFP_KERNEL); |
837 | |||
866 | if (!data) | 838 | if (!data) |
867 | return -ENOMEM; | 839 | return -ENOMEM; |
840 | data->send_setup = option_send_setup; | ||
868 | spin_lock_init(&data->susp_lock); | 841 | spin_lock_init(&data->susp_lock); |
869 | data->blacklist_info = (struct option_blacklist_info*) id->driver_info; | 842 | data->private = (void *)id->driver_info; |
870 | return 0; | 843 | return 0; |
871 | } | 844 | } |
872 | 845 | ||
@@ -887,205 +860,6 @@ static enum option_blacklist_reason is_blacklisted(const u8 ifnum, | |||
887 | return OPTION_BLACKLIST_NONE; | 860 | return OPTION_BLACKLIST_NONE; |
888 | } | 861 | } |
889 | 862 | ||
890 | static void option_set_termios(struct tty_struct *tty, | ||
891 | struct usb_serial_port *port, struct ktermios *old_termios) | ||
892 | { | ||
893 | dbg("%s", __func__); | ||
894 | /* Doesn't support option setting */ | ||
895 | tty_termios_copy_hw(tty->termios, old_termios); | ||
896 | option_send_setup(port); | ||
897 | } | ||
898 | |||
899 | static int option_tiocmget(struct tty_struct *tty, struct file *file) | ||
900 | { | ||
901 | struct usb_serial_port *port = tty->driver_data; | ||
902 | unsigned int value; | ||
903 | struct option_port_private *portdata; | ||
904 | |||
905 | portdata = usb_get_serial_port_data(port); | ||
906 | |||
907 | value = ((portdata->rts_state) ? TIOCM_RTS : 0) | | ||
908 | ((portdata->dtr_state) ? TIOCM_DTR : 0) | | ||
909 | ((portdata->cts_state) ? TIOCM_CTS : 0) | | ||
910 | ((portdata->dsr_state) ? TIOCM_DSR : 0) | | ||
911 | ((portdata->dcd_state) ? TIOCM_CAR : 0) | | ||
912 | ((portdata->ri_state) ? TIOCM_RNG : 0); | ||
913 | |||
914 | return value; | ||
915 | } | ||
916 | |||
917 | static int option_tiocmset(struct tty_struct *tty, struct file *file, | ||
918 | unsigned int set, unsigned int clear) | ||
919 | { | ||
920 | struct usb_serial_port *port = tty->driver_data; | ||
921 | struct option_port_private *portdata; | ||
922 | |||
923 | portdata = usb_get_serial_port_data(port); | ||
924 | |||
925 | /* FIXME: what locks portdata fields ? */ | ||
926 | if (set & TIOCM_RTS) | ||
927 | portdata->rts_state = 1; | ||
928 | if (set & TIOCM_DTR) | ||
929 | portdata->dtr_state = 1; | ||
930 | |||
931 | if (clear & TIOCM_RTS) | ||
932 | portdata->rts_state = 0; | ||
933 | if (clear & TIOCM_DTR) | ||
934 | portdata->dtr_state = 0; | ||
935 | return option_send_setup(port); | ||
936 | } | ||
937 | |||
938 | /* Write */ | ||
939 | static int option_write(struct tty_struct *tty, struct usb_serial_port *port, | ||
940 | const unsigned char *buf, int count) | ||
941 | { | ||
942 | struct option_port_private *portdata; | ||
943 | struct option_intf_private *intfdata; | ||
944 | int i; | ||
945 | int left, todo; | ||
946 | struct urb *this_urb = NULL; /* spurious */ | ||
947 | int err; | ||
948 | unsigned long flags; | ||
949 | |||
950 | portdata = usb_get_serial_port_data(port); | ||
951 | intfdata = port->serial->private; | ||
952 | |||
953 | dbg("%s: write (%d chars)", __func__, count); | ||
954 | |||
955 | i = 0; | ||
956 | left = count; | ||
957 | for (i = 0; left > 0 && i < N_OUT_URB; i++) { | ||
958 | todo = left; | ||
959 | if (todo > OUT_BUFLEN) | ||
960 | todo = OUT_BUFLEN; | ||
961 | |||
962 | this_urb = portdata->out_urbs[i]; | ||
963 | if (test_and_set_bit(i, &portdata->out_busy)) { | ||
964 | if (time_before(jiffies, | ||
965 | portdata->tx_start_time[i] + 10 * HZ)) | ||
966 | continue; | ||
967 | usb_unlink_urb(this_urb); | ||
968 | continue; | ||
969 | } | ||
970 | dbg("%s: endpoint %d buf %d", __func__, | ||
971 | usb_pipeendpoint(this_urb->pipe), i); | ||
972 | |||
973 | err = usb_autopm_get_interface_async(port->serial->interface); | ||
974 | if (err < 0) | ||
975 | break; | ||
976 | |||
977 | /* send the data */ | ||
978 | memcpy(this_urb->transfer_buffer, buf, todo); | ||
979 | this_urb->transfer_buffer_length = todo; | ||
980 | |||
981 | spin_lock_irqsave(&intfdata->susp_lock, flags); | ||
982 | if (intfdata->suspended) { | ||
983 | usb_anchor_urb(this_urb, &portdata->delayed); | ||
984 | spin_unlock_irqrestore(&intfdata->susp_lock, flags); | ||
985 | } else { | ||
986 | intfdata->in_flight++; | ||
987 | spin_unlock_irqrestore(&intfdata->susp_lock, flags); | ||
988 | err = usb_submit_urb(this_urb, GFP_ATOMIC); | ||
989 | if (err) { | ||
990 | dbg("usb_submit_urb %p (write bulk) failed " | ||
991 | "(%d)", this_urb, err); | ||
992 | clear_bit(i, &portdata->out_busy); | ||
993 | spin_lock_irqsave(&intfdata->susp_lock, flags); | ||
994 | intfdata->in_flight--; | ||
995 | spin_unlock_irqrestore(&intfdata->susp_lock, flags); | ||
996 | continue; | ||
997 | } | ||
998 | } | ||
999 | |||
1000 | portdata->tx_start_time[i] = jiffies; | ||
1001 | buf += todo; | ||
1002 | left -= todo; | ||
1003 | } | ||
1004 | |||
1005 | count -= left; | ||
1006 | dbg("%s: wrote (did %d)", __func__, count); | ||
1007 | return count; | ||
1008 | } | ||
1009 | |||
1010 | static void option_indat_callback(struct urb *urb) | ||
1011 | { | ||
1012 | int err; | ||
1013 | int endpoint; | ||
1014 | struct usb_serial_port *port; | ||
1015 | struct tty_struct *tty; | ||
1016 | unsigned char *data = urb->transfer_buffer; | ||
1017 | int status = urb->status; | ||
1018 | |||
1019 | dbg("%s: %p", __func__, urb); | ||
1020 | |||
1021 | endpoint = usb_pipeendpoint(urb->pipe); | ||
1022 | port = urb->context; | ||
1023 | |||
1024 | switch (status) { | ||
1025 | case 0: | ||
1026 | /* success */ | ||
1027 | break; | ||
1028 | case -ECONNRESET: | ||
1029 | case -ENOENT: | ||
1030 | case -ESHUTDOWN: | ||
1031 | /* this urb is terminated, clean up */ | ||
1032 | dbg("%s: urb shutting down with status: %d on endpoint %02x.", | ||
1033 | __func__, status, endpoint); | ||
1034 | return; | ||
1035 | default: | ||
1036 | dbg("%s: nonzero status: %d on endpoint %02x.", | ||
1037 | __func__, status, endpoint); | ||
1038 | goto exit; | ||
1039 | } | ||
1040 | |||
1041 | if (urb->actual_length) { | ||
1042 | tty = tty_port_tty_get(&port->port); | ||
1043 | tty_insert_flip_string(tty, data, urb->actual_length); | ||
1044 | tty_flip_buffer_push(tty); | ||
1045 | tty_kref_put(tty); | ||
1046 | } else | ||
1047 | dbg("%s: empty read urb received", __func__); | ||
1048 | |||
1049 | exit: | ||
1050 | /* Resubmit urb so we continue receiving */ | ||
1051 | err = usb_submit_urb(urb, GFP_ATOMIC); | ||
1052 | if (err && err != -EPERM) | ||
1053 | printk(KERN_ERR "%s: resubmit read urb failed. " | ||
1054 | "(%d)", __func__, err); | ||
1055 | else | ||
1056 | usb_mark_last_busy(port->serial->dev); | ||
1057 | |||
1058 | return; | ||
1059 | } | ||
1060 | |||
1061 | static void option_outdat_callback(struct urb *urb) | ||
1062 | { | ||
1063 | struct usb_serial_port *port; | ||
1064 | struct option_port_private *portdata; | ||
1065 | struct option_intf_private *intfdata; | ||
1066 | int i; | ||
1067 | |||
1068 | dbg("%s", __func__); | ||
1069 | |||
1070 | port = urb->context; | ||
1071 | intfdata = port->serial->private; | ||
1072 | |||
1073 | usb_serial_port_softint(port); | ||
1074 | usb_autopm_put_interface_async(port->serial->interface); | ||
1075 | portdata = usb_get_serial_port_data(port); | ||
1076 | spin_lock(&intfdata->susp_lock); | ||
1077 | intfdata->in_flight--; | ||
1078 | spin_unlock(&intfdata->susp_lock); | ||
1079 | |||
1080 | for (i = 0; i < N_OUT_URB; ++i) { | ||
1081 | if (portdata->out_urbs[i] == urb) { | ||
1082 | smp_mb__before_clear_bit(); | ||
1083 | clear_bit(i, &portdata->out_busy); | ||
1084 | break; | ||
1085 | } | ||
1086 | } | ||
1087 | } | ||
1088 | |||
1089 | static void option_instat_callback(struct urb *urb) | 863 | static void option_instat_callback(struct urb *urb) |
1090 | { | 864 | { |
1091 | int err; | 865 | int err; |
@@ -1142,183 +916,6 @@ static void option_instat_callback(struct urb *urb) | |||
1142 | } | 916 | } |
1143 | } | 917 | } |
1144 | 918 | ||
1145 | static int option_write_room(struct tty_struct *tty) | ||
1146 | { | ||
1147 | struct usb_serial_port *port = tty->driver_data; | ||
1148 | struct option_port_private *portdata; | ||
1149 | int i; | ||
1150 | int data_len = 0; | ||
1151 | struct urb *this_urb; | ||
1152 | |||
1153 | portdata = usb_get_serial_port_data(port); | ||
1154 | |||
1155 | for (i = 0; i < N_OUT_URB; i++) { | ||
1156 | this_urb = portdata->out_urbs[i]; | ||
1157 | if (this_urb && !test_bit(i, &portdata->out_busy)) | ||
1158 | data_len += OUT_BUFLEN; | ||
1159 | } | ||
1160 | |||
1161 | dbg("%s: %d", __func__, data_len); | ||
1162 | return data_len; | ||
1163 | } | ||
1164 | |||
1165 | static int option_chars_in_buffer(struct tty_struct *tty) | ||
1166 | { | ||
1167 | struct usb_serial_port *port = tty->driver_data; | ||
1168 | struct option_port_private *portdata; | ||
1169 | int i; | ||
1170 | int data_len = 0; | ||
1171 | struct urb *this_urb; | ||
1172 | |||
1173 | portdata = usb_get_serial_port_data(port); | ||
1174 | |||
1175 | for (i = 0; i < N_OUT_URB; i++) { | ||
1176 | this_urb = portdata->out_urbs[i]; | ||
1177 | /* FIXME: This locking is insufficient as this_urb may | ||
1178 | go unused during the test */ | ||
1179 | if (this_urb && test_bit(i, &portdata->out_busy)) | ||
1180 | data_len += this_urb->transfer_buffer_length; | ||
1181 | } | ||
1182 | dbg("%s: %d", __func__, data_len); | ||
1183 | return data_len; | ||
1184 | } | ||
1185 | |||
1186 | static int option_open(struct tty_struct *tty, struct usb_serial_port *port) | ||
1187 | { | ||
1188 | struct option_port_private *portdata; | ||
1189 | struct option_intf_private *intfdata; | ||
1190 | struct usb_serial *serial = port->serial; | ||
1191 | int i, err; | ||
1192 | struct urb *urb; | ||
1193 | |||
1194 | portdata = usb_get_serial_port_data(port); | ||
1195 | intfdata = serial->private; | ||
1196 | |||
1197 | dbg("%s", __func__); | ||
1198 | |||
1199 | /* Start reading from the IN endpoint */ | ||
1200 | for (i = 0; i < N_IN_URB; i++) { | ||
1201 | urb = portdata->in_urbs[i]; | ||
1202 | if (!urb) | ||
1203 | continue; | ||
1204 | err = usb_submit_urb(urb, GFP_KERNEL); | ||
1205 | if (err) { | ||
1206 | dbg("%s: submit urb %d failed (%d) %d", | ||
1207 | __func__, i, err, | ||
1208 | urb->transfer_buffer_length); | ||
1209 | } | ||
1210 | } | ||
1211 | |||
1212 | option_send_setup(port); | ||
1213 | |||
1214 | serial->interface->needs_remote_wakeup = 1; | ||
1215 | spin_lock_irq(&intfdata->susp_lock); | ||
1216 | portdata->opened = 1; | ||
1217 | spin_unlock_irq(&intfdata->susp_lock); | ||
1218 | usb_autopm_put_interface(serial->interface); | ||
1219 | |||
1220 | return 0; | ||
1221 | } | ||
1222 | |||
1223 | static void option_dtr_rts(struct usb_serial_port *port, int on) | ||
1224 | { | ||
1225 | struct usb_serial *serial = port->serial; | ||
1226 | struct option_port_private *portdata; | ||
1227 | |||
1228 | dbg("%s", __func__); | ||
1229 | portdata = usb_get_serial_port_data(port); | ||
1230 | mutex_lock(&serial->disc_mutex); | ||
1231 | portdata->rts_state = on; | ||
1232 | portdata->dtr_state = on; | ||
1233 | if (serial->dev) | ||
1234 | option_send_setup(port); | ||
1235 | mutex_unlock(&serial->disc_mutex); | ||
1236 | } | ||
1237 | |||
1238 | |||
1239 | static void option_close(struct usb_serial_port *port) | ||
1240 | { | ||
1241 | int i; | ||
1242 | struct usb_serial *serial = port->serial; | ||
1243 | struct option_port_private *portdata; | ||
1244 | struct option_intf_private *intfdata = port->serial->private; | ||
1245 | |||
1246 | dbg("%s", __func__); | ||
1247 | portdata = usb_get_serial_port_data(port); | ||
1248 | |||
1249 | if (serial->dev) { | ||
1250 | /* Stop reading/writing urbs */ | ||
1251 | spin_lock_irq(&intfdata->susp_lock); | ||
1252 | portdata->opened = 0; | ||
1253 | spin_unlock_irq(&intfdata->susp_lock); | ||
1254 | |||
1255 | for (i = 0; i < N_IN_URB; i++) | ||
1256 | usb_kill_urb(portdata->in_urbs[i]); | ||
1257 | for (i = 0; i < N_OUT_URB; i++) | ||
1258 | usb_kill_urb(portdata->out_urbs[i]); | ||
1259 | usb_autopm_get_interface(serial->interface); | ||
1260 | serial->interface->needs_remote_wakeup = 0; | ||
1261 | } | ||
1262 | } | ||
1263 | |||
1264 | /* Helper functions used by option_setup_urbs */ | ||
1265 | static struct urb *option_setup_urb(struct usb_serial *serial, int endpoint, | ||
1266 | int dir, void *ctx, char *buf, int len, | ||
1267 | void (*callback)(struct urb *)) | ||
1268 | { | ||
1269 | struct urb *urb; | ||
1270 | |||
1271 | if (endpoint == -1) | ||
1272 | return NULL; /* endpoint not needed */ | ||
1273 | |||
1274 | urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */ | ||
1275 | if (urb == NULL) { | ||
1276 | dbg("%s: alloc for endpoint %d failed.", __func__, endpoint); | ||
1277 | return NULL; | ||
1278 | } | ||
1279 | |||
1280 | /* Fill URB using supplied data. */ | ||
1281 | usb_fill_bulk_urb(urb, serial->dev, | ||
1282 | usb_sndbulkpipe(serial->dev, endpoint) | dir, | ||
1283 | buf, len, callback, ctx); | ||
1284 | |||
1285 | return urb; | ||
1286 | } | ||
1287 | |||
1288 | /* Setup urbs */ | ||
1289 | static void option_setup_urbs(struct usb_serial *serial) | ||
1290 | { | ||
1291 | int i, j; | ||
1292 | struct usb_serial_port *port; | ||
1293 | struct option_port_private *portdata; | ||
1294 | |||
1295 | dbg("%s", __func__); | ||
1296 | |||
1297 | for (i = 0; i < serial->num_ports; i++) { | ||
1298 | port = serial->port[i]; | ||
1299 | portdata = usb_get_serial_port_data(port); | ||
1300 | |||
1301 | /* Do indat endpoints first */ | ||
1302 | for (j = 0; j < N_IN_URB; ++j) { | ||
1303 | portdata->in_urbs[j] = option_setup_urb(serial, | ||
1304 | port->bulk_in_endpointAddress, | ||
1305 | USB_DIR_IN, port, | ||
1306 | portdata->in_buffer[j], | ||
1307 | IN_BUFLEN, option_indat_callback); | ||
1308 | } | ||
1309 | |||
1310 | /* outdat endpoints */ | ||
1311 | for (j = 0; j < N_OUT_URB; ++j) { | ||
1312 | portdata->out_urbs[j] = option_setup_urb(serial, | ||
1313 | port->bulk_out_endpointAddress, | ||
1314 | USB_DIR_OUT, port, | ||
1315 | portdata->out_buffer[j], | ||
1316 | OUT_BUFLEN, option_outdat_callback); | ||
1317 | } | ||
1318 | } | ||
1319 | } | ||
1320 | |||
1321 | |||
1322 | /** send RTS/DTR state to the port. | 919 | /** send RTS/DTR state to the port. |
1323 | * | 920 | * |
1324 | * This is exactly the same as SET_CONTROL_LINE_STATE from the PSTN | 921 | * This is exactly the same as SET_CONTROL_LINE_STATE from the PSTN |
@@ -1327,15 +924,16 @@ static void option_setup_urbs(struct usb_serial *serial) | |||
1327 | static int option_send_setup(struct usb_serial_port *port) | 924 | static int option_send_setup(struct usb_serial_port *port) |
1328 | { | 925 | { |
1329 | struct usb_serial *serial = port->serial; | 926 | struct usb_serial *serial = port->serial; |
1330 | struct option_intf_private *intfdata = | 927 | struct usb_wwan_intf_private *intfdata = |
1331 | (struct option_intf_private *) serial->private; | 928 | (struct usb_wwan_intf_private *) serial->private; |
1332 | struct option_port_private *portdata; | 929 | struct option_port_private *portdata; |
1333 | int ifNum = serial->interface->cur_altsetting->desc.bInterfaceNumber; | 930 | int ifNum = serial->interface->cur_altsetting->desc.bInterfaceNumber; |
1334 | int val = 0; | 931 | int val = 0; |
1335 | dbg("%s", __func__); | 932 | dbg("%s", __func__); |
1336 | 933 | ||
1337 | if (is_blacklisted(ifNum, intfdata->blacklist_info) == | 934 | if (is_blacklisted(ifNum, |
1338 | OPTION_BLACKLIST_SENDSETUP) { | 935 | (struct option_blacklist_info *) intfdata->private) |
936 | == OPTION_BLACKLIST_SENDSETUP) { | ||
1339 | dbg("No send_setup on blacklisted interface #%d\n", ifNum); | 937 | dbg("No send_setup on blacklisted interface #%d\n", ifNum); |
1340 | return -EIO; | 938 | return -EIO; |
1341 | } | 939 | } |
@@ -1352,224 +950,6 @@ static int option_send_setup(struct usb_serial_port *port) | |||
1352 | 0x22, 0x21, val, ifNum, NULL, 0, USB_CTRL_SET_TIMEOUT); | 950 | 0x22, 0x21, val, ifNum, NULL, 0, USB_CTRL_SET_TIMEOUT); |
1353 | } | 951 | } |
1354 | 952 | ||
1355 | static int option_startup(struct usb_serial *serial) | ||
1356 | { | ||
1357 | int i, j, err; | ||
1358 | struct usb_serial_port *port; | ||
1359 | struct option_port_private *portdata; | ||
1360 | u8 *buffer; | ||
1361 | |||
1362 | dbg("%s", __func__); | ||
1363 | |||
1364 | /* Now setup per port private data */ | ||
1365 | for (i = 0; i < serial->num_ports; i++) { | ||
1366 | port = serial->port[i]; | ||
1367 | portdata = kzalloc(sizeof(*portdata), GFP_KERNEL); | ||
1368 | if (!portdata) { | ||
1369 | dbg("%s: kmalloc for option_port_private (%d) failed!.", | ||
1370 | __func__, i); | ||
1371 | return 1; | ||
1372 | } | ||
1373 | init_usb_anchor(&portdata->delayed); | ||
1374 | |||
1375 | for (j = 0; j < N_IN_URB; j++) { | ||
1376 | buffer = (u8 *)__get_free_page(GFP_KERNEL); | ||
1377 | if (!buffer) | ||
1378 | goto bail_out_error; | ||
1379 | portdata->in_buffer[j] = buffer; | ||
1380 | } | ||
1381 | |||
1382 | for (j = 0; j < N_OUT_URB; j++) { | ||
1383 | buffer = kmalloc(OUT_BUFLEN, GFP_KERNEL); | ||
1384 | if (!buffer) | ||
1385 | goto bail_out_error2; | ||
1386 | portdata->out_buffer[j] = buffer; | ||
1387 | } | ||
1388 | |||
1389 | usb_set_serial_port_data(port, portdata); | ||
1390 | |||
1391 | if (!port->interrupt_in_urb) | ||
1392 | continue; | ||
1393 | err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); | ||
1394 | if (err) | ||
1395 | dbg("%s: submit irq_in urb failed %d", | ||
1396 | __func__, err); | ||
1397 | } | ||
1398 | option_setup_urbs(serial); | ||
1399 | return 0; | ||
1400 | |||
1401 | bail_out_error2: | ||
1402 | for (j = 0; j < N_OUT_URB; j++) | ||
1403 | kfree(portdata->out_buffer[j]); | ||
1404 | bail_out_error: | ||
1405 | for (j = 0; j < N_IN_URB; j++) | ||
1406 | if (portdata->in_buffer[j]) | ||
1407 | free_page((unsigned long)portdata->in_buffer[j]); | ||
1408 | kfree(portdata); | ||
1409 | return 1; | ||
1410 | } | ||
1411 | |||
1412 | static void stop_read_write_urbs(struct usb_serial *serial) | ||
1413 | { | ||
1414 | int i, j; | ||
1415 | struct usb_serial_port *port; | ||
1416 | struct option_port_private *portdata; | ||
1417 | |||
1418 | /* Stop reading/writing urbs */ | ||
1419 | for (i = 0; i < serial->num_ports; ++i) { | ||
1420 | port = serial->port[i]; | ||
1421 | portdata = usb_get_serial_port_data(port); | ||
1422 | for (j = 0; j < N_IN_URB; j++) | ||
1423 | usb_kill_urb(portdata->in_urbs[j]); | ||
1424 | for (j = 0; j < N_OUT_URB; j++) | ||
1425 | usb_kill_urb(portdata->out_urbs[j]); | ||
1426 | } | ||
1427 | } | ||
1428 | |||
1429 | static void option_disconnect(struct usb_serial *serial) | ||
1430 | { | ||
1431 | dbg("%s", __func__); | ||
1432 | |||
1433 | stop_read_write_urbs(serial); | ||
1434 | } | ||
1435 | |||
1436 | static void option_release(struct usb_serial *serial) | ||
1437 | { | ||
1438 | int i, j; | ||
1439 | struct usb_serial_port *port; | ||
1440 | struct option_port_private *portdata; | ||
1441 | |||
1442 | dbg("%s", __func__); | ||
1443 | |||
1444 | /* Now free them */ | ||
1445 | for (i = 0; i < serial->num_ports; ++i) { | ||
1446 | port = serial->port[i]; | ||
1447 | portdata = usb_get_serial_port_data(port); | ||
1448 | |||
1449 | for (j = 0; j < N_IN_URB; j++) { | ||
1450 | if (portdata->in_urbs[j]) { | ||
1451 | usb_free_urb(portdata->in_urbs[j]); | ||
1452 | free_page((unsigned long) | ||
1453 | portdata->in_buffer[j]); | ||
1454 | portdata->in_urbs[j] = NULL; | ||
1455 | } | ||
1456 | } | ||
1457 | for (j = 0; j < N_OUT_URB; j++) { | ||
1458 | if (portdata->out_urbs[j]) { | ||
1459 | usb_free_urb(portdata->out_urbs[j]); | ||
1460 | kfree(portdata->out_buffer[j]); | ||
1461 | portdata->out_urbs[j] = NULL; | ||
1462 | } | ||
1463 | } | ||
1464 | } | ||
1465 | |||
1466 | /* Now free per port private data */ | ||
1467 | for (i = 0; i < serial->num_ports; i++) { | ||
1468 | port = serial->port[i]; | ||
1469 | kfree(usb_get_serial_port_data(port)); | ||
1470 | } | ||
1471 | } | ||
1472 | |||
1473 | #ifdef CONFIG_PM | ||
1474 | static int option_suspend(struct usb_serial *serial, pm_message_t message) | ||
1475 | { | ||
1476 | struct option_intf_private *intfdata = serial->private; | ||
1477 | int b; | ||
1478 | |||
1479 | dbg("%s entered", __func__); | ||
1480 | |||
1481 | if (message.event & PM_EVENT_AUTO) { | ||
1482 | spin_lock_irq(&intfdata->susp_lock); | ||
1483 | b = intfdata->in_flight; | ||
1484 | spin_unlock_irq(&intfdata->susp_lock); | ||
1485 | |||
1486 | if (b) | ||
1487 | return -EBUSY; | ||
1488 | } | ||
1489 | |||
1490 | spin_lock_irq(&intfdata->susp_lock); | ||
1491 | intfdata->suspended = 1; | ||
1492 | spin_unlock_irq(&intfdata->susp_lock); | ||
1493 | stop_read_write_urbs(serial); | ||
1494 | |||
1495 | return 0; | ||
1496 | } | ||
1497 | |||
1498 | static void play_delayed(struct usb_serial_port *port) | ||
1499 | { | ||
1500 | struct option_intf_private *data; | ||
1501 | struct option_port_private *portdata; | ||
1502 | struct urb *urb; | ||
1503 | int err; | ||
1504 | |||
1505 | portdata = usb_get_serial_port_data(port); | ||
1506 | data = port->serial->private; | ||
1507 | while ((urb = usb_get_from_anchor(&portdata->delayed))) { | ||
1508 | err = usb_submit_urb(urb, GFP_ATOMIC); | ||
1509 | if (!err) | ||
1510 | data->in_flight++; | ||
1511 | } | ||
1512 | } | ||
1513 | |||
1514 | static int option_resume(struct usb_serial *serial) | ||
1515 | { | ||
1516 | int i, j; | ||
1517 | struct usb_serial_port *port; | ||
1518 | struct option_intf_private *intfdata = serial->private; | ||
1519 | struct option_port_private *portdata; | ||
1520 | struct urb *urb; | ||
1521 | int err = 0; | ||
1522 | |||
1523 | dbg("%s entered", __func__); | ||
1524 | /* get the interrupt URBs resubmitted unconditionally */ | ||
1525 | for (i = 0; i < serial->num_ports; i++) { | ||
1526 | port = serial->port[i]; | ||
1527 | if (!port->interrupt_in_urb) { | ||
1528 | dbg("%s: No interrupt URB for port %d", __func__, i); | ||
1529 | continue; | ||
1530 | } | ||
1531 | err = usb_submit_urb(port->interrupt_in_urb, GFP_NOIO); | ||
1532 | dbg("Submitted interrupt URB for port %d (result %d)", i, err); | ||
1533 | if (err < 0) { | ||
1534 | err("%s: Error %d for interrupt URB of port%d", | ||
1535 | __func__, err, i); | ||
1536 | goto err_out; | ||
1537 | } | ||
1538 | } | ||
1539 | |||
1540 | for (i = 0; i < serial->num_ports; i++) { | ||
1541 | /* walk all ports */ | ||
1542 | port = serial->port[i]; | ||
1543 | portdata = usb_get_serial_port_data(port); | ||
1544 | |||
1545 | /* skip closed ports */ | ||
1546 | spin_lock_irq(&intfdata->susp_lock); | ||
1547 | if (!portdata->opened) { | ||
1548 | spin_unlock_irq(&intfdata->susp_lock); | ||
1549 | continue; | ||
1550 | } | ||
1551 | |||
1552 | for (j = 0; j < N_IN_URB; j++) { | ||
1553 | urb = portdata->in_urbs[j]; | ||
1554 | err = usb_submit_urb(urb, GFP_ATOMIC); | ||
1555 | if (err < 0) { | ||
1556 | err("%s: Error %d for bulk URB %d", | ||
1557 | __func__, err, i); | ||
1558 | spin_unlock_irq(&intfdata->susp_lock); | ||
1559 | goto err_out; | ||
1560 | } | ||
1561 | } | ||
1562 | play_delayed(port); | ||
1563 | spin_unlock_irq(&intfdata->susp_lock); | ||
1564 | } | ||
1565 | spin_lock_irq(&intfdata->susp_lock); | ||
1566 | intfdata->suspended = 0; | ||
1567 | spin_unlock_irq(&intfdata->susp_lock); | ||
1568 | err_out: | ||
1569 | return err; | ||
1570 | } | ||
1571 | #endif | ||
1572 | |||
1573 | MODULE_AUTHOR(DRIVER_AUTHOR); | 953 | MODULE_AUTHOR(DRIVER_AUTHOR); |
1574 | MODULE_DESCRIPTION(DRIVER_DESC); | 954 | MODULE_DESCRIPTION(DRIVER_DESC); |
1575 | MODULE_VERSION(DRIVER_VERSION); | 955 | MODULE_VERSION(DRIVER_VERSION); |