blob: 2183ee6ebec439ecf8f279ac7ef5c404a67a2520 [file] [log] [blame]
Hemant Kumar9d6016c2012-01-05 16:27:24 -08001/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
Hemant Kumar37c35e42011-09-14 23:44:19 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
Steve Mucklef132c6c2012-06-06 18:30:57 -070013#include <linux/module.h>
Hemant Kumar37c35e42011-09-14 23:44:19 -070014#include <linux/mii.h>
15#include <linux/if_arp.h>
16#include <linux/etherdevice.h>
Hemant Kumar7bf94262012-04-18 17:25:10 -070017#include <linux/debugfs.h>
18#include <linux/seq_file.h>
Hemant Kumar37c35e42011-09-14 23:44:19 -070019#include <linux/usb.h>
20#include <linux/usb/usbnet.h>
21#include <linux/msm_rmnet.h>
22
23#include "rmnet_usb_ctrl.h"
24
25#define RMNET_DATA_LEN 2000
26#define HEADROOM_FOR_QOS 8
27
Hemant Kumar37c35e42011-09-14 23:44:19 -070028static int data_msg_dbg_mask;
29
30enum {
31 DEBUG_MASK_LVL0 = 1U << 0,
32 DEBUG_MASK_LVL1 = 1U << 1,
33 DEBUG_MASK_LVL2 = 1U << 2,
34};
35
36#define DBG(m, x...) do { \
37 if (data_msg_dbg_mask & m) \
38 pr_info(x); \
39} while (0)
40
41/*echo dbg_mask > /sys/class/net/rmnet_usbx/dbg_mask*/
42static ssize_t dbg_mask_store(struct device *d,
43 struct device_attribute *attr,
44 const char *buf, size_t n)
45{
46 unsigned int dbg_mask;
47 struct net_device *dev = to_net_dev(d);
48 struct usbnet *unet = netdev_priv(dev);
49
50 if (!dev)
51 return -ENODEV;
52
53 sscanf(buf, "%u", &dbg_mask);
54 /*enable dbg msgs for data driver*/
55 data_msg_dbg_mask = dbg_mask;
56
57 /*set default msg level*/
58 unet->msg_enable = NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK;
59
60 /*enable netif_xxx msgs*/
61 if (dbg_mask & DEBUG_MASK_LVL0)
62 unet->msg_enable |= NETIF_MSG_IFUP | NETIF_MSG_IFDOWN;
63 if (dbg_mask & DEBUG_MASK_LVL1)
64 unet->msg_enable |= NETIF_MSG_TX_ERR | NETIF_MSG_RX_ERR
65 | NETIF_MSG_TX_QUEUED | NETIF_MSG_TX_DONE
66 | NETIF_MSG_RX_STATUS;
67
68 return n;
69}
70
71static ssize_t dbg_mask_show(struct device *d,
72 struct device_attribute *attr, char *buf)
73{
74 return snprintf(buf, PAGE_SIZE, "%d\n", data_msg_dbg_mask);
75}
76
77static DEVICE_ATTR(dbg_mask, 0644, dbg_mask_show, dbg_mask_store);
78
79#define DBG0(x...) DBG(DEBUG_MASK_LVL0, x)
80#define DBG1(x...) DBG(DEBUG_MASK_LVL1, x)
81#define DBG2(x...) DBG(DEBUG_MASK_LVL2, x)
82
83static void rmnet_usb_setup(struct net_device *);
84static int rmnet_ioctl(struct net_device *, struct ifreq *, int);
85
86static int rmnet_usb_suspend(struct usb_interface *iface, pm_message_t message)
87{
88 struct usbnet *unet;
89 struct rmnet_ctrl_dev *dev;
90 int time = 0;
91 int retval = 0;
92
93 unet = usb_get_intfdata(iface);
94 if (!unet) {
95 pr_err("%s:data device not found\n", __func__);
96 retval = -ENODEV;
97 goto fail;
98 }
99
100 dev = (struct rmnet_ctrl_dev *)unet->data[1];
101 if (!dev) {
102 dev_err(&unet->udev->dev, "%s: ctrl device not found\n",
103 __func__);
104 retval = -ENODEV;
105 goto fail;
106 }
107
108 retval = usbnet_suspend(iface, message);
109 if (!retval) {
110 if (message.event & PM_EVENT_SUSPEND) {
111 time = usb_wait_anchor_empty_timeout(&dev->tx_submitted,
112 1000);
113 if (!time)
114 usb_kill_anchored_urbs(&dev->tx_submitted);
115
116 retval = rmnet_usb_ctrl_stop_rx(dev);
117 iface->dev.power.power_state.event = message.event;
118 }
119 /* TBD : do we need to set/clear usbnet->udev->reset_resume*/
120 } else
121 dev_dbg(&unet->udev->dev,
122 "%s: device is busy can not suspend\n", __func__);
123
124fail:
125 return retval;
126}
127
128static int rmnet_usb_resume(struct usb_interface *iface)
129{
130 int retval = 0;
131 int oldstate;
132 struct usbnet *unet;
133 struct rmnet_ctrl_dev *dev;
134
135 unet = usb_get_intfdata(iface);
136 if (!unet) {
137 pr_err("%s:data device not found\n", __func__);
138 retval = -ENODEV;
139 goto fail;
140 }
141
142 dev = (struct rmnet_ctrl_dev *)unet->data[1];
143 if (!dev) {
144 dev_err(&unet->udev->dev, "%s: ctrl device not found\n",
145 __func__);
146 retval = -ENODEV;
147 goto fail;
148 }
149 oldstate = iface->dev.power.power_state.event;
150 iface->dev.power.power_state.event = PM_EVENT_ON;
151
152 retval = usbnet_resume(iface);
153 if (!retval) {
Hemant Kumar37c35e42011-09-14 23:44:19 -0700154 if (oldstate & PM_EVENT_SUSPEND)
155 retval = rmnet_usb_ctrl_start(dev);
156 }
157fail:
158 return retval;
159}
160
161static int rmnet_usb_bind(struct usbnet *usbnet, struct usb_interface *iface)
162{
163 struct usb_host_endpoint *endpoint = NULL;
164 struct usb_host_endpoint *bulk_in = NULL;
165 struct usb_host_endpoint *bulk_out = NULL;
166 struct usb_host_endpoint *int_in = NULL;
167 struct usb_device *udev;
168 int status = 0;
169 int i;
170 int numends;
171
172 udev = interface_to_usbdev(iface);
173 numends = iface->cur_altsetting->desc.bNumEndpoints;
174 for (i = 0; i < numends; i++) {
175 endpoint = iface->cur_altsetting->endpoint + i;
176 if (!endpoint) {
177 dev_err(&udev->dev, "%s: invalid endpoint %u\n",
178 __func__, i);
179 status = -EINVAL;
180 goto out;
181 }
182 if (usb_endpoint_is_bulk_in(&endpoint->desc))
183 bulk_in = endpoint;
184 else if (usb_endpoint_is_bulk_out(&endpoint->desc))
185 bulk_out = endpoint;
186 else if (usb_endpoint_is_int_in(&endpoint->desc))
187 int_in = endpoint;
188 }
189
190 if (!bulk_in || !bulk_out || !int_in) {
191 dev_err(&udev->dev, "%s: invalid endpoints\n", __func__);
192 status = -EINVAL;
193 goto out;
194 }
195 usbnet->in = usb_rcvbulkpipe(usbnet->udev,
196 bulk_in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
197 usbnet->out = usb_sndbulkpipe(usbnet->udev,
198 bulk_out->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
199 usbnet->status = int_in;
200
201 /*change name of net device to rmnet_usbx here*/
202 strlcpy(usbnet->net->name, "rmnet_usb%d", IFNAMSIZ);
203
204 /*TBD: update rx_urb_size, curently set to eth frame len by usbnet*/
205out:
206 return status;
207}
208
209static struct sk_buff *rmnet_usb_tx_fixup(struct usbnet *dev,
210 struct sk_buff *skb, gfp_t flags)
211{
212 struct QMI_QOS_HDR_S *qmih;
213
214 if (test_bit(RMNET_MODE_QOS, &dev->data[0])) {
215 qmih = (struct QMI_QOS_HDR_S *)
216 skb_push(skb, sizeof(struct QMI_QOS_HDR_S));
217 qmih->version = 1;
218 qmih->flags = 0;
219 qmih->flow_id = skb->mark;
220 }
221
222 DBG1("[%s] Tx packet #%lu len=%d mark=0x%x\n",
223 dev->net->name, dev->net->stats.tx_packets, skb->len, skb->mark);
224
225 return skb;
226}
227
228static __be16 rmnet_ip_type_trans(struct sk_buff *skb,
229 struct net_device *dev)
230{
231 __be16 protocol = 0;
232
233 skb->dev = dev;
234
235 switch (skb->data[0] & 0xf0) {
236 case 0x40:
237 protocol = htons(ETH_P_IP);
238 break;
239 case 0x60:
240 protocol = htons(ETH_P_IPV6);
241 break;
242 default:
243 pr_err("[%s] rmnet_recv() L3 protocol decode error: 0x%02x",
244 dev->name, skb->data[0] & 0xf0);
245 }
246
247 return protocol;
248}
249
250static int rmnet_usb_rx_fixup(struct usbnet *dev,
251 struct sk_buff *skb)
252{
253
254 if (test_bit(RMNET_MODE_LLP_IP, &dev->data[0]))
255 skb->protocol = rmnet_ip_type_trans(skb, dev->net);
256 else /*set zero for eth mode*/
257 skb->protocol = 0;
258
259 DBG1("[%s] Rx packet #%lu len=%d\n",
260 dev->net->name, dev->net->stats.rx_packets, skb->len);
261
262 return 1;
263}
264
Jack Phamf77b9962012-02-23 18:45:43 -0800265static int rmnet_usb_manage_power(struct usbnet *dev, int on)
266{
267 dev->intf->needs_remote_wakeup = on;
268 return 0;
269}
270
Hemant Kumar37c35e42011-09-14 23:44:19 -0700271static int rmnet_change_mtu(struct net_device *dev, int new_mtu)
272{
273 if (0 > new_mtu || RMNET_DATA_LEN < new_mtu)
274 return -EINVAL;
275
276 DBG0("[%s] MTU change: old=%d new=%d\n", dev->name, dev->mtu, new_mtu);
277
278 dev->mtu = new_mtu;
279
280 return 0;
281}
282
283static struct net_device_stats *rmnet_get_stats(struct net_device *dev)
284{
285 return &dev->stats;
286}
287
288static const struct net_device_ops rmnet_usb_ops_ether = {
289 .ndo_open = usbnet_open,
290 .ndo_stop = usbnet_stop,
291 .ndo_start_xmit = usbnet_start_xmit,
292 .ndo_get_stats = rmnet_get_stats,
293 /*.ndo_set_multicast_list = rmnet_set_multicast_list,*/
294 .ndo_tx_timeout = usbnet_tx_timeout,
295 .ndo_do_ioctl = rmnet_ioctl,
296 .ndo_change_mtu = usbnet_change_mtu,
297 .ndo_set_mac_address = eth_mac_addr,
298 .ndo_validate_addr = eth_validate_addr,
299};
300
301static const struct net_device_ops rmnet_usb_ops_ip = {
302 .ndo_open = usbnet_open,
303 .ndo_stop = usbnet_stop,
304 .ndo_start_xmit = usbnet_start_xmit,
305 .ndo_get_stats = rmnet_get_stats,
306 /*.ndo_set_multicast_list = rmnet_set_multicast_list,*/
307 .ndo_tx_timeout = usbnet_tx_timeout,
308 .ndo_do_ioctl = rmnet_ioctl,
309 .ndo_change_mtu = rmnet_change_mtu,
310 .ndo_set_mac_address = 0,
311 .ndo_validate_addr = 0,
312};
313
314
315static int rmnet_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
316{
317 struct usbnet *unet = netdev_priv(dev);
318 u32 old_opmode;
319 int prev_mtu = dev->mtu;
320 int rc = 0;
321
322 old_opmode = unet->data[0]; /*data[0] saves operation mode*/
323 /* Process IOCTL command */
324 switch (cmd) {
325 case RMNET_IOCTL_SET_LLP_ETHERNET: /*Set Ethernet protocol*/
326 /* Perform Ethernet config only if in IP mode currently*/
327 if (test_bit(RMNET_MODE_LLP_IP, &unet->data[0])) {
328 ether_setup(dev);
329 random_ether_addr(dev->dev_addr);
330 dev->mtu = prev_mtu;
331 dev->netdev_ops = &rmnet_usb_ops_ether;
332 clear_bit(RMNET_MODE_LLP_IP, &unet->data[0]);
333 set_bit(RMNET_MODE_LLP_ETH, &unet->data[0]);
334 DBG0("[%s] rmnet_ioctl(): set Ethernet protocol mode\n",
335 dev->name);
336 }
337 break;
338
339 case RMNET_IOCTL_SET_LLP_IP: /* Set RAWIP protocol*/
340 /* Perform IP config only if in Ethernet mode currently*/
341 if (test_bit(RMNET_MODE_LLP_ETH, &unet->data[0])) {
342
343 /* Undo config done in ether_setup() */
344 dev->header_ops = 0; /* No header */
345 dev->type = ARPHRD_RAWIP;
346 dev->hard_header_len = 0;
347 dev->mtu = prev_mtu;
348 dev->addr_len = 0;
349 dev->flags &= ~(IFF_BROADCAST | IFF_MULTICAST);
350 dev->needed_headroom = HEADROOM_FOR_QOS;
351 dev->netdev_ops = &rmnet_usb_ops_ip;
352 clear_bit(RMNET_MODE_LLP_ETH, &unet->data[0]);
353 set_bit(RMNET_MODE_LLP_IP, &unet->data[0]);
354 DBG0("[%s] rmnet_ioctl(): set IP protocol mode\n",
355 dev->name);
356 }
357 break;
358
359 case RMNET_IOCTL_GET_LLP: /* Get link protocol state */
360 ifr->ifr_ifru.ifru_data = (void *)(unet->data[0]
361 & (RMNET_MODE_LLP_ETH
362 | RMNET_MODE_LLP_IP));
363 break;
364
365 case RMNET_IOCTL_SET_QOS_ENABLE: /* Set QoS header enabled*/
366 set_bit(RMNET_MODE_QOS, &unet->data[0]);
367 DBG0("[%s] rmnet_ioctl(): set QMI QOS header enable\n",
368 dev->name);
369 break;
370
371 case RMNET_IOCTL_SET_QOS_DISABLE: /* Set QoS header disabled */
372 clear_bit(RMNET_MODE_QOS, &unet->data[0]);
373 DBG0("[%s] rmnet_ioctl(): set QMI QOS header disable\n",
374 dev->name);
375 break;
376
377 case RMNET_IOCTL_GET_QOS: /* Get QoS header state */
378 ifr->ifr_ifru.ifru_data = (void *)(unet->data[0]
379 & RMNET_MODE_QOS);
380 break;
381
382 case RMNET_IOCTL_GET_OPMODE: /* Get operation mode*/
383 ifr->ifr_ifru.ifru_data = (void *)unet->data[0];
384 break;
385
386 case RMNET_IOCTL_OPEN: /* Open transport port */
387 rc = usbnet_open(dev);
388 DBG0("[%s] rmnet_ioctl(): open transport port\n", dev->name);
389 break;
390
391 case RMNET_IOCTL_CLOSE: /* Close transport port*/
392 rc = usbnet_stop(dev);
393 DBG0("[%s] rmnet_ioctl(): close transport port\n", dev->name);
394 break;
395
396 default:
397 dev_err(&unet->udev->dev, "[%s] error: "
398 "rmnet_ioct called for unsupported cmd[%d]",
399 dev->name, cmd);
400 return -EINVAL;
401 }
402
403 DBG2("[%s] %s: cmd=0x%x opmode old=0x%08x new=0x%08lx\n",
404 dev->name, __func__, cmd, old_opmode, unet->data[0]);
405
406 return rc;
407}
408
409static void rmnet_usb_setup(struct net_device *dev)
410{
411 /* Using Ethernet mode by default */
412 dev->netdev_ops = &rmnet_usb_ops_ether;
413
414 /* set this after calling ether_setup */
415 dev->mtu = RMNET_DATA_LEN;
416
417 dev->needed_headroom = HEADROOM_FOR_QOS;
418 random_ether_addr(dev->dev_addr);
419 dev->watchdog_timeo = 1000; /* 10 seconds? */
420}
421
Hemant Kumar7bf94262012-04-18 17:25:10 -0700422static int rmnet_usb_data_status(struct seq_file *s, void *unused)
423{
424 struct usbnet *unet = s->private;
425
426 seq_printf(s, "RMNET_MODE_LLP_IP: %d\n",
427 test_bit(RMNET_MODE_LLP_IP, &unet->data[0]));
428 seq_printf(s, "RMNET_MODE_LLP_ETH: %d\n",
429 test_bit(RMNET_MODE_LLP_ETH, &unet->data[0]));
430 seq_printf(s, "RMNET_MODE_QOS: %d\n",
431 test_bit(RMNET_MODE_QOS, &unet->data[0]));
432 seq_printf(s, "Net MTU: %u\n", unet->net->mtu);
433 seq_printf(s, "rx_urb_size: %u\n", unet->rx_urb_size);
434 seq_printf(s, "rx skb q len: %u\n", unet->rxq.qlen);
435 seq_printf(s, "rx skb done q len: %u\n", unet->done.qlen);
436 seq_printf(s, "rx errors: %lu\n", unet->net->stats.rx_errors);
437 seq_printf(s, "rx over errors: %lu\n",
438 unet->net->stats.rx_over_errors);
439 seq_printf(s, "rx length errors: %lu\n",
440 unet->net->stats.rx_length_errors);
441 seq_printf(s, "rx packets: %lu\n", unet->net->stats.rx_packets);
442 seq_printf(s, "rx bytes: %lu\n", unet->net->stats.rx_bytes);
443 seq_printf(s, "tx skb q len: %u\n", unet->txq.qlen);
444 seq_printf(s, "tx errors: %lu\n", unet->net->stats.tx_errors);
445 seq_printf(s, "tx packets: %lu\n", unet->net->stats.tx_packets);
446 seq_printf(s, "tx bytes: %lu\n", unet->net->stats.tx_bytes);
447 seq_printf(s, "suspend count: %d\n", unet->suspend_count);
448 seq_printf(s, "EVENT_DEV_OPEN: %d\n",
449 test_bit(EVENT_DEV_OPEN, &unet->flags));
450 seq_printf(s, "EVENT_TX_HALT: %d\n",
451 test_bit(EVENT_TX_HALT, &unet->flags));
452 seq_printf(s, "EVENT_RX_HALT: %d\n",
453 test_bit(EVENT_RX_HALT, &unet->flags));
454 seq_printf(s, "EVENT_RX_MEMORY: %d\n",
455 test_bit(EVENT_RX_MEMORY, &unet->flags));
456 seq_printf(s, "EVENT_DEV_ASLEEP: %d\n",
457 test_bit(EVENT_DEV_ASLEEP, &unet->flags));
458
459 return 0;
460}
461
462static int rmnet_usb_data_status_open(struct inode *inode, struct file *file)
463{
464 return single_open(file, rmnet_usb_data_status, inode->i_private);
465}
466
467const struct file_operations rmnet_usb_data_fops = {
468 .open = rmnet_usb_data_status_open,
469 .read = seq_read,
470 .llseek = seq_lseek,
471 .release = single_release,
472};
473
Hemant Kumar7bf94262012-04-18 17:25:10 -0700474static int rmnet_usb_data_debugfs_init(struct usbnet *unet)
475{
Hemant Kumar90b1a472012-04-26 19:59:56 -0700476 struct dentry *rmnet_usb_data_dbg_root;
Hemant Kumar7bf94262012-04-18 17:25:10 -0700477 struct dentry *rmnet_usb_data_dentry;
478
479 rmnet_usb_data_dbg_root = debugfs_create_dir(unet->net->name, NULL);
Hemant Kumar7bf94262012-04-18 17:25:10 -0700480 if (!rmnet_usb_data_dbg_root || IS_ERR(rmnet_usb_data_dbg_root))
481 return -ENODEV;
482
483 rmnet_usb_data_dentry = debugfs_create_file("status",
484 S_IRUGO | S_IWUSR,
485 rmnet_usb_data_dbg_root, unet,
486 &rmnet_usb_data_fops);
487
488 if (!rmnet_usb_data_dentry) {
489 debugfs_remove_recursive(rmnet_usb_data_dbg_root);
490 return -ENODEV;
491 }
492
Hemant Kumar90b1a472012-04-26 19:59:56 -0700493 unet->data[2] = (unsigned long)rmnet_usb_data_dbg_root;
494
Hemant Kumar7bf94262012-04-18 17:25:10 -0700495 return 0;
496}
497
Hemant Kumar90b1a472012-04-26 19:59:56 -0700498static void rmnet_usb_data_debugfs_cleanup(struct usbnet *unet)
Hemant Kumar7bf94262012-04-18 17:25:10 -0700499{
Hemant Kumar90b1a472012-04-26 19:59:56 -0700500 struct dentry *root = (struct dentry *)unet->data[2];
501
502 debugfs_remove_recursive(root);
503 unet->data[2] = 0;
Hemant Kumar7bf94262012-04-18 17:25:10 -0700504}
505
Hemant Kumar37c35e42011-09-14 23:44:19 -0700506static int rmnet_usb_probe(struct usb_interface *iface,
507 const struct usb_device_id *prod)
508{
509 struct usbnet *unet;
510 struct usb_device *udev;
Hemant Kumar9d6016c2012-01-05 16:27:24 -0800511 struct driver_info *info;
512 unsigned int iface_num;
513 static int first_rmnet_iface_num = -EINVAL;
514 int status = 0;
Hemant Kumar37c35e42011-09-14 23:44:19 -0700515
516 udev = interface_to_usbdev(iface);
517 iface_num = iface->cur_altsetting->desc.bInterfaceNumber;
518 if (iface->num_altsetting != 1) {
519 dev_err(&udev->dev, "%s invalid num_altsetting %u\n",
520 __func__, iface->num_altsetting);
521 status = -EINVAL;
522 goto out;
523 }
524
Hemant Kumar9d6016c2012-01-05 16:27:24 -0800525 info = (struct driver_info *)prod->driver_info;
526 if (!test_bit(iface_num, &info->data))
527 return -ENODEV;
Hemant Kumar37c35e42011-09-14 23:44:19 -0700528
Hemant Kumar9d6016c2012-01-05 16:27:24 -0800529 status = usbnet_probe(iface, prod);
530 if (status < 0) {
531 dev_err(&udev->dev, "usbnet_probe failed %d\n", status);
532 goto out;
Hemant Kumar37c35e42011-09-14 23:44:19 -0700533 }
Hemant Kumar9d6016c2012-01-05 16:27:24 -0800534 unet = usb_get_intfdata(iface);
535
536 /*set rmnet operation mode to eth by default*/
537 set_bit(RMNET_MODE_LLP_ETH, &unet->data[0]);
538
539 /*update net device*/
540 rmnet_usb_setup(unet->net);
541
542 /*create /sys/class/net/rmnet_usbx/dbg_mask*/
543 status = device_create_file(&unet->net->dev, &dev_attr_dbg_mask);
544 if (status)
545 goto out;
546
547 if (first_rmnet_iface_num == -EINVAL)
548 first_rmnet_iface_num = iface_num;
549
550 /*save control device intstance */
551 unet->data[1] = (unsigned long)ctrl_dev \
552 [iface_num - first_rmnet_iface_num];
553
554 status = rmnet_usb_ctrl_probe(iface, unet->status,
555 (struct rmnet_ctrl_dev *)unet->data[1]);
Jack Pham42346cf2012-03-13 12:49:07 -0700556 if (status)
557 goto out;
558
Hemant Kumar7bf94262012-04-18 17:25:10 -0700559 status = rmnet_usb_data_debugfs_init(unet);
560 if (status)
561 dev_dbg(&udev->dev, "mode debugfs file is not available\n");
562
Jack Pham42346cf2012-03-13 12:49:07 -0700563 /* allow modem to wake up suspended system */
564 device_set_wakeup_enable(&udev->dev, 1);
Hemant Kumar37c35e42011-09-14 23:44:19 -0700565out:
566 return status;
567}
568
569static void rmnet_usb_disconnect(struct usb_interface *intf)
570{
571 struct usbnet *unet;
572 struct usb_device *udev;
573 struct rmnet_ctrl_dev *dev;
Hemant Kumar37c35e42011-09-14 23:44:19 -0700574
575 udev = interface_to_usbdev(intf);
Jack Pham42346cf2012-03-13 12:49:07 -0700576 device_set_wakeup_enable(&udev->dev, 0);
Hemant Kumar37c35e42011-09-14 23:44:19 -0700577
Hemant Kumar9d6016c2012-01-05 16:27:24 -0800578 unet = usb_get_intfdata(intf);
579 if (!unet) {
580 dev_err(&udev->dev, "%s:data device not found\n", __func__);
581 return;
Hemant Kumar37c35e42011-09-14 23:44:19 -0700582 }
Hemant Kumar9d6016c2012-01-05 16:27:24 -0800583
Hemant Kumar90b1a472012-04-26 19:59:56 -0700584 rmnet_usb_data_debugfs_cleanup(unet);
585
Hemant Kumar9d6016c2012-01-05 16:27:24 -0800586 dev = (struct rmnet_ctrl_dev *)unet->data[1];
587 if (!dev) {
588 dev_err(&udev->dev, "%s:ctrl device not found\n", __func__);
589 return;
590 }
591 unet->data[0] = 0;
592 unet->data[1] = 0;
593 rmnet_usb_ctrl_disconnect(dev);
594 device_remove_file(&unet->net->dev, &dev_attr_dbg_mask);
595 usbnet_disconnect(intf);
Hemant Kumar37c35e42011-09-14 23:44:19 -0700596}
597
Hemant Kumar9d6016c2012-01-05 16:27:24 -0800598/*bit position represents interface number*/
599#define PID9034_IFACE_MASK 0xF0
600#define PID9048_IFACE_MASK 0x1E0
Hemant Kumarbf024812012-02-24 12:58:56 -0800601#define PID904C_IFACE_MASK 0x1C0
Hemant Kumar9d6016c2012-01-05 16:27:24 -0800602
603static const struct driver_info rmnet_info_pid9034 = {
Hemant Kumar37c35e42011-09-14 23:44:19 -0700604 .description = "RmNET net device",
605 .bind = rmnet_usb_bind,
606 .tx_fixup = rmnet_usb_tx_fixup,
607 .rx_fixup = rmnet_usb_rx_fixup,
Jack Phamf77b9962012-02-23 18:45:43 -0800608 .manage_power = rmnet_usb_manage_power,
Hemant Kumar9d6016c2012-01-05 16:27:24 -0800609 .data = PID9034_IFACE_MASK,
610};
611
612static const struct driver_info rmnet_info_pid9048 = {
613 .description = "RmNET net device",
614 .bind = rmnet_usb_bind,
615 .tx_fixup = rmnet_usb_tx_fixup,
616 .rx_fixup = rmnet_usb_rx_fixup,
Jack Phamf77b9962012-02-23 18:45:43 -0800617 .manage_power = rmnet_usb_manage_power,
Hemant Kumar9d6016c2012-01-05 16:27:24 -0800618 .data = PID9048_IFACE_MASK,
Hemant Kumar37c35e42011-09-14 23:44:19 -0700619};
620
Hemant Kumarbf024812012-02-24 12:58:56 -0800621static const struct driver_info rmnet_info_pid904c = {
622 .description = "RmNET net device",
623 .bind = rmnet_usb_bind,
624 .tx_fixup = rmnet_usb_tx_fixup,
625 .rx_fixup = rmnet_usb_rx_fixup,
Jack Phamf77b9962012-02-23 18:45:43 -0800626 .manage_power = rmnet_usb_manage_power,
Hemant Kumarbf024812012-02-24 12:58:56 -0800627 .data = PID904C_IFACE_MASK,
628};
629
Hemant Kumar37c35e42011-09-14 23:44:19 -0700630static const struct usb_device_id vidpids[] = {
631 {
Hemant Kumar9d6016c2012-01-05 16:27:24 -0800632 USB_DEVICE(0x05c6, 0x9034), /* MDM9x15*/
633 .driver_info = (unsigned long)&rmnet_info_pid9034,
Hemant Kumar37c35e42011-09-14 23:44:19 -0700634 },
Hemant Kumar9d6016c2012-01-05 16:27:24 -0800635 {
636 USB_DEVICE(0x05c6, 0x9048), /* MDM9x15*/
637 .driver_info = (unsigned long)&rmnet_info_pid9048,
638 },
Hemant Kumarbf024812012-02-24 12:58:56 -0800639 {
640 USB_DEVICE(0x05c6, 0x904c), /* MDM9x15*/
641 .driver_info = (unsigned long)&rmnet_info_pid904c,
642 },
Hemant Kumar9d6016c2012-01-05 16:27:24 -0800643
644 { }, /* Terminating entry */
Hemant Kumar37c35e42011-09-14 23:44:19 -0700645};
646
647MODULE_DEVICE_TABLE(usb, vidpids);
648
649static struct usb_driver rmnet_usb = {
650 .name = "rmnet_usb",
651 .id_table = vidpids,
652 .probe = rmnet_usb_probe,
653 .disconnect = rmnet_usb_disconnect,
654 .suspend = rmnet_usb_suspend,
655 .resume = rmnet_usb_resume,
656 .supports_autosuspend = true,
657};
658
659static int __init rmnet_usb_init(void)
660{
661 int retval;
662
663 retval = usb_register(&rmnet_usb);
664 if (retval) {
665 err("usb_register failed: %d", retval);
666 return retval;
667 }
668 /* initialize rmnet ctrl device here*/
669 retval = rmnet_usb_ctrl_init();
670 if (retval) {
671 usb_deregister(&rmnet_usb);
672 err("rmnet_usb_cmux_init failed: %d", retval);
673 return retval;
674 }
675
676 return 0;
677}
678module_init(rmnet_usb_init);
679
680static void __exit rmnet_usb_exit(void)
681{
682 rmnet_usb_ctrl_exit();
683 usb_deregister(&rmnet_usb);
684}
685module_exit(rmnet_usb_exit);
686
687MODULE_DESCRIPTION("msm rmnet usb device");
688MODULE_LICENSE("GPL v2");