blob: eb576937def74767389c254da25633a64ceeaf88 [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) {
Jack Phame8741502012-06-13 17:34:07 -0700102 dev_err(&iface->dev, "%s: ctrl device not found\n",
Hemant Kumar37c35e42011-09-14 23:44:19 -0700103 __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
Jack Phame8741502012-06-13 17:34:07 -0700121 dev_dbg(&iface->dev,
Hemant Kumar37c35e42011-09-14 23:44:19 -0700122 "%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) {
Jack Phame8741502012-06-13 17:34:07 -0700144 dev_err(&iface->dev, "%s: ctrl device not found\n", __func__);
Hemant Kumar37c35e42011-09-14 23:44:19 -0700145 retval = -ENODEV;
146 goto fail;
147 }
148 oldstate = iface->dev.power.power_state.event;
149 iface->dev.power.power_state.event = PM_EVENT_ON;
150
151 retval = usbnet_resume(iface);
152 if (!retval) {
Hemant Kumar37c35e42011-09-14 23:44:19 -0700153 if (oldstate & PM_EVENT_SUSPEND)
154 retval = rmnet_usb_ctrl_start(dev);
155 }
156fail:
157 return retval;
158}
159
160static int rmnet_usb_bind(struct usbnet *usbnet, struct usb_interface *iface)
161{
162 struct usb_host_endpoint *endpoint = NULL;
163 struct usb_host_endpoint *bulk_in = NULL;
164 struct usb_host_endpoint *bulk_out = NULL;
165 struct usb_host_endpoint *int_in = NULL;
Hemant Kumar37c35e42011-09-14 23:44:19 -0700166 int status = 0;
167 int i;
168 int numends;
169
Hemant Kumar37c35e42011-09-14 23:44:19 -0700170 numends = iface->cur_altsetting->desc.bNumEndpoints;
171 for (i = 0; i < numends; i++) {
172 endpoint = iface->cur_altsetting->endpoint + i;
173 if (!endpoint) {
Jack Phame8741502012-06-13 17:34:07 -0700174 dev_err(&iface->dev, "%s: invalid endpoint %u\n",
Hemant Kumar37c35e42011-09-14 23:44:19 -0700175 __func__, i);
176 status = -EINVAL;
177 goto out;
178 }
179 if (usb_endpoint_is_bulk_in(&endpoint->desc))
180 bulk_in = endpoint;
181 else if (usb_endpoint_is_bulk_out(&endpoint->desc))
182 bulk_out = endpoint;
183 else if (usb_endpoint_is_int_in(&endpoint->desc))
184 int_in = endpoint;
185 }
186
187 if (!bulk_in || !bulk_out || !int_in) {
Jack Phame8741502012-06-13 17:34:07 -0700188 dev_err(&iface->dev, "%s: invalid endpoints\n", __func__);
Hemant Kumar37c35e42011-09-14 23:44:19 -0700189 status = -EINVAL;
190 goto out;
191 }
192 usbnet->in = usb_rcvbulkpipe(usbnet->udev,
193 bulk_in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
194 usbnet->out = usb_sndbulkpipe(usbnet->udev,
195 bulk_out->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
196 usbnet->status = int_in;
197
198 /*change name of net device to rmnet_usbx here*/
199 strlcpy(usbnet->net->name, "rmnet_usb%d", IFNAMSIZ);
200
201 /*TBD: update rx_urb_size, curently set to eth frame len by usbnet*/
202out:
203 return status;
204}
205
206static struct sk_buff *rmnet_usb_tx_fixup(struct usbnet *dev,
207 struct sk_buff *skb, gfp_t flags)
208{
209 struct QMI_QOS_HDR_S *qmih;
210
211 if (test_bit(RMNET_MODE_QOS, &dev->data[0])) {
212 qmih = (struct QMI_QOS_HDR_S *)
213 skb_push(skb, sizeof(struct QMI_QOS_HDR_S));
214 qmih->version = 1;
215 qmih->flags = 0;
216 qmih->flow_id = skb->mark;
217 }
218
219 DBG1("[%s] Tx packet #%lu len=%d mark=0x%x\n",
220 dev->net->name, dev->net->stats.tx_packets, skb->len, skb->mark);
221
222 return skb;
223}
224
225static __be16 rmnet_ip_type_trans(struct sk_buff *skb,
226 struct net_device *dev)
227{
228 __be16 protocol = 0;
229
230 skb->dev = dev;
231
232 switch (skb->data[0] & 0xf0) {
233 case 0x40:
234 protocol = htons(ETH_P_IP);
235 break;
236 case 0x60:
237 protocol = htons(ETH_P_IPV6);
238 break;
239 default:
240 pr_err("[%s] rmnet_recv() L3 protocol decode error: 0x%02x",
241 dev->name, skb->data[0] & 0xf0);
242 }
243
244 return protocol;
245}
246
247static int rmnet_usb_rx_fixup(struct usbnet *dev,
248 struct sk_buff *skb)
249{
250
251 if (test_bit(RMNET_MODE_LLP_IP, &dev->data[0]))
252 skb->protocol = rmnet_ip_type_trans(skb, dev->net);
253 else /*set zero for eth mode*/
254 skb->protocol = 0;
255
256 DBG1("[%s] Rx packet #%lu len=%d\n",
257 dev->net->name, dev->net->stats.rx_packets, skb->len);
258
259 return 1;
260}
261
Jack Phamf77b9962012-02-23 18:45:43 -0800262static int rmnet_usb_manage_power(struct usbnet *dev, int on)
263{
264 dev->intf->needs_remote_wakeup = on;
265 return 0;
266}
267
Hemant Kumar37c35e42011-09-14 23:44:19 -0700268static int rmnet_change_mtu(struct net_device *dev, int new_mtu)
269{
270 if (0 > new_mtu || RMNET_DATA_LEN < new_mtu)
271 return -EINVAL;
272
273 DBG0("[%s] MTU change: old=%d new=%d\n", dev->name, dev->mtu, new_mtu);
274
275 dev->mtu = new_mtu;
276
277 return 0;
278}
279
280static struct net_device_stats *rmnet_get_stats(struct net_device *dev)
281{
282 return &dev->stats;
283}
284
285static const struct net_device_ops rmnet_usb_ops_ether = {
286 .ndo_open = usbnet_open,
287 .ndo_stop = usbnet_stop,
288 .ndo_start_xmit = usbnet_start_xmit,
289 .ndo_get_stats = rmnet_get_stats,
290 /*.ndo_set_multicast_list = rmnet_set_multicast_list,*/
291 .ndo_tx_timeout = usbnet_tx_timeout,
292 .ndo_do_ioctl = rmnet_ioctl,
293 .ndo_change_mtu = usbnet_change_mtu,
294 .ndo_set_mac_address = eth_mac_addr,
295 .ndo_validate_addr = eth_validate_addr,
296};
297
298static const struct net_device_ops rmnet_usb_ops_ip = {
299 .ndo_open = usbnet_open,
300 .ndo_stop = usbnet_stop,
301 .ndo_start_xmit = usbnet_start_xmit,
302 .ndo_get_stats = rmnet_get_stats,
303 /*.ndo_set_multicast_list = rmnet_set_multicast_list,*/
304 .ndo_tx_timeout = usbnet_tx_timeout,
305 .ndo_do_ioctl = rmnet_ioctl,
306 .ndo_change_mtu = rmnet_change_mtu,
307 .ndo_set_mac_address = 0,
308 .ndo_validate_addr = 0,
309};
310
311
312static int rmnet_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
313{
314 struct usbnet *unet = netdev_priv(dev);
315 u32 old_opmode;
316 int prev_mtu = dev->mtu;
317 int rc = 0;
318
319 old_opmode = unet->data[0]; /*data[0] saves operation mode*/
320 /* Process IOCTL command */
321 switch (cmd) {
322 case RMNET_IOCTL_SET_LLP_ETHERNET: /*Set Ethernet protocol*/
323 /* Perform Ethernet config only if in IP mode currently*/
324 if (test_bit(RMNET_MODE_LLP_IP, &unet->data[0])) {
325 ether_setup(dev);
326 random_ether_addr(dev->dev_addr);
327 dev->mtu = prev_mtu;
328 dev->netdev_ops = &rmnet_usb_ops_ether;
329 clear_bit(RMNET_MODE_LLP_IP, &unet->data[0]);
330 set_bit(RMNET_MODE_LLP_ETH, &unet->data[0]);
331 DBG0("[%s] rmnet_ioctl(): set Ethernet protocol mode\n",
332 dev->name);
333 }
334 break;
335
336 case RMNET_IOCTL_SET_LLP_IP: /* Set RAWIP protocol*/
337 /* Perform IP config only if in Ethernet mode currently*/
338 if (test_bit(RMNET_MODE_LLP_ETH, &unet->data[0])) {
339
340 /* Undo config done in ether_setup() */
341 dev->header_ops = 0; /* No header */
342 dev->type = ARPHRD_RAWIP;
343 dev->hard_header_len = 0;
344 dev->mtu = prev_mtu;
345 dev->addr_len = 0;
346 dev->flags &= ~(IFF_BROADCAST | IFF_MULTICAST);
347 dev->needed_headroom = HEADROOM_FOR_QOS;
348 dev->netdev_ops = &rmnet_usb_ops_ip;
349 clear_bit(RMNET_MODE_LLP_ETH, &unet->data[0]);
350 set_bit(RMNET_MODE_LLP_IP, &unet->data[0]);
351 DBG0("[%s] rmnet_ioctl(): set IP protocol mode\n",
352 dev->name);
353 }
354 break;
355
356 case RMNET_IOCTL_GET_LLP: /* Get link protocol state */
357 ifr->ifr_ifru.ifru_data = (void *)(unet->data[0]
358 & (RMNET_MODE_LLP_ETH
359 | RMNET_MODE_LLP_IP));
360 break;
361
362 case RMNET_IOCTL_SET_QOS_ENABLE: /* Set QoS header enabled*/
363 set_bit(RMNET_MODE_QOS, &unet->data[0]);
364 DBG0("[%s] rmnet_ioctl(): set QMI QOS header enable\n",
365 dev->name);
366 break;
367
368 case RMNET_IOCTL_SET_QOS_DISABLE: /* Set QoS header disabled */
369 clear_bit(RMNET_MODE_QOS, &unet->data[0]);
370 DBG0("[%s] rmnet_ioctl(): set QMI QOS header disable\n",
371 dev->name);
372 break;
373
374 case RMNET_IOCTL_GET_QOS: /* Get QoS header state */
375 ifr->ifr_ifru.ifru_data = (void *)(unet->data[0]
376 & RMNET_MODE_QOS);
377 break;
378
379 case RMNET_IOCTL_GET_OPMODE: /* Get operation mode*/
380 ifr->ifr_ifru.ifru_data = (void *)unet->data[0];
381 break;
382
383 case RMNET_IOCTL_OPEN: /* Open transport port */
384 rc = usbnet_open(dev);
385 DBG0("[%s] rmnet_ioctl(): open transport port\n", dev->name);
386 break;
387
388 case RMNET_IOCTL_CLOSE: /* Close transport port*/
389 rc = usbnet_stop(dev);
390 DBG0("[%s] rmnet_ioctl(): close transport port\n", dev->name);
391 break;
392
393 default:
Jack Phame8741502012-06-13 17:34:07 -0700394 dev_err(&unet->intf->dev, "[%s] error: "
Hemant Kumar37c35e42011-09-14 23:44:19 -0700395 "rmnet_ioct called for unsupported cmd[%d]",
396 dev->name, cmd);
397 return -EINVAL;
398 }
399
400 DBG2("[%s] %s: cmd=0x%x opmode old=0x%08x new=0x%08lx\n",
401 dev->name, __func__, cmd, old_opmode, unet->data[0]);
402
403 return rc;
404}
405
406static void rmnet_usb_setup(struct net_device *dev)
407{
408 /* Using Ethernet mode by default */
409 dev->netdev_ops = &rmnet_usb_ops_ether;
410
411 /* set this after calling ether_setup */
412 dev->mtu = RMNET_DATA_LEN;
413
414 dev->needed_headroom = HEADROOM_FOR_QOS;
415 random_ether_addr(dev->dev_addr);
416 dev->watchdog_timeo = 1000; /* 10 seconds? */
417}
418
Hemant Kumar7bf94262012-04-18 17:25:10 -0700419static int rmnet_usb_data_status(struct seq_file *s, void *unused)
420{
421 struct usbnet *unet = s->private;
422
423 seq_printf(s, "RMNET_MODE_LLP_IP: %d\n",
424 test_bit(RMNET_MODE_LLP_IP, &unet->data[0]));
425 seq_printf(s, "RMNET_MODE_LLP_ETH: %d\n",
426 test_bit(RMNET_MODE_LLP_ETH, &unet->data[0]));
427 seq_printf(s, "RMNET_MODE_QOS: %d\n",
428 test_bit(RMNET_MODE_QOS, &unet->data[0]));
429 seq_printf(s, "Net MTU: %u\n", unet->net->mtu);
430 seq_printf(s, "rx_urb_size: %u\n", unet->rx_urb_size);
431 seq_printf(s, "rx skb q len: %u\n", unet->rxq.qlen);
432 seq_printf(s, "rx skb done q len: %u\n", unet->done.qlen);
433 seq_printf(s, "rx errors: %lu\n", unet->net->stats.rx_errors);
434 seq_printf(s, "rx over errors: %lu\n",
435 unet->net->stats.rx_over_errors);
436 seq_printf(s, "rx length errors: %lu\n",
437 unet->net->stats.rx_length_errors);
438 seq_printf(s, "rx packets: %lu\n", unet->net->stats.rx_packets);
439 seq_printf(s, "rx bytes: %lu\n", unet->net->stats.rx_bytes);
440 seq_printf(s, "tx skb q len: %u\n", unet->txq.qlen);
441 seq_printf(s, "tx errors: %lu\n", unet->net->stats.tx_errors);
442 seq_printf(s, "tx packets: %lu\n", unet->net->stats.tx_packets);
443 seq_printf(s, "tx bytes: %lu\n", unet->net->stats.tx_bytes);
444 seq_printf(s, "suspend count: %d\n", unet->suspend_count);
445 seq_printf(s, "EVENT_DEV_OPEN: %d\n",
446 test_bit(EVENT_DEV_OPEN, &unet->flags));
447 seq_printf(s, "EVENT_TX_HALT: %d\n",
448 test_bit(EVENT_TX_HALT, &unet->flags));
449 seq_printf(s, "EVENT_RX_HALT: %d\n",
450 test_bit(EVENT_RX_HALT, &unet->flags));
451 seq_printf(s, "EVENT_RX_MEMORY: %d\n",
452 test_bit(EVENT_RX_MEMORY, &unet->flags));
453 seq_printf(s, "EVENT_DEV_ASLEEP: %d\n",
454 test_bit(EVENT_DEV_ASLEEP, &unet->flags));
455
456 return 0;
457}
458
459static int rmnet_usb_data_status_open(struct inode *inode, struct file *file)
460{
461 return single_open(file, rmnet_usb_data_status, inode->i_private);
462}
463
464const struct file_operations rmnet_usb_data_fops = {
465 .open = rmnet_usb_data_status_open,
466 .read = seq_read,
467 .llseek = seq_lseek,
468 .release = single_release,
469};
470
Hemant Kumar7bf94262012-04-18 17:25:10 -0700471static int rmnet_usb_data_debugfs_init(struct usbnet *unet)
472{
Hemant Kumar90b1a472012-04-26 19:59:56 -0700473 struct dentry *rmnet_usb_data_dbg_root;
Hemant Kumar7bf94262012-04-18 17:25:10 -0700474 struct dentry *rmnet_usb_data_dentry;
475
476 rmnet_usb_data_dbg_root = debugfs_create_dir(unet->net->name, NULL);
Hemant Kumar7bf94262012-04-18 17:25:10 -0700477 if (!rmnet_usb_data_dbg_root || IS_ERR(rmnet_usb_data_dbg_root))
478 return -ENODEV;
479
480 rmnet_usb_data_dentry = debugfs_create_file("status",
481 S_IRUGO | S_IWUSR,
482 rmnet_usb_data_dbg_root, unet,
483 &rmnet_usb_data_fops);
484
485 if (!rmnet_usb_data_dentry) {
486 debugfs_remove_recursive(rmnet_usb_data_dbg_root);
487 return -ENODEV;
488 }
489
Hemant Kumar90b1a472012-04-26 19:59:56 -0700490 unet->data[2] = (unsigned long)rmnet_usb_data_dbg_root;
491
Hemant Kumar7bf94262012-04-18 17:25:10 -0700492 return 0;
493}
494
Hemant Kumar90b1a472012-04-26 19:59:56 -0700495static void rmnet_usb_data_debugfs_cleanup(struct usbnet *unet)
Hemant Kumar7bf94262012-04-18 17:25:10 -0700496{
Hemant Kumar90b1a472012-04-26 19:59:56 -0700497 struct dentry *root = (struct dentry *)unet->data[2];
498
499 debugfs_remove_recursive(root);
500 unet->data[2] = 0;
Hemant Kumar7bf94262012-04-18 17:25:10 -0700501}
502
Hemant Kumar37c35e42011-09-14 23:44:19 -0700503static int rmnet_usb_probe(struct usb_interface *iface,
504 const struct usb_device_id *prod)
505{
506 struct usbnet *unet;
Hemant Kumar9d6016c2012-01-05 16:27:24 -0800507 struct driver_info *info;
Jack Pham9bc736e2012-06-19 17:52:51 -0700508 struct usb_device *udev;
Hemant Kumar9d6016c2012-01-05 16:27:24 -0800509 unsigned int iface_num;
510 static int first_rmnet_iface_num = -EINVAL;
511 int status = 0;
Hemant Kumar37c35e42011-09-14 23:44:19 -0700512
Hemant Kumar37c35e42011-09-14 23:44:19 -0700513 iface_num = iface->cur_altsetting->desc.bInterfaceNumber;
514 if (iface->num_altsetting != 1) {
Jack Phame8741502012-06-13 17:34:07 -0700515 dev_err(&iface->dev, "%s invalid num_altsetting %u\n",
Hemant Kumar37c35e42011-09-14 23:44:19 -0700516 __func__, iface->num_altsetting);
517 status = -EINVAL;
518 goto out;
519 }
520
Hemant Kumar9d6016c2012-01-05 16:27:24 -0800521 info = (struct driver_info *)prod->driver_info;
522 if (!test_bit(iface_num, &info->data))
523 return -ENODEV;
Hemant Kumar37c35e42011-09-14 23:44:19 -0700524
Hemant Kumar9d6016c2012-01-05 16:27:24 -0800525 status = usbnet_probe(iface, prod);
526 if (status < 0) {
Jack Phame8741502012-06-13 17:34:07 -0700527 dev_err(&iface->dev, "usbnet_probe failed %d\n", status);
Hemant Kumar9d6016c2012-01-05 16:27:24 -0800528 goto out;
Hemant Kumar37c35e42011-09-14 23:44:19 -0700529 }
Hemant Kumar9d6016c2012-01-05 16:27:24 -0800530 unet = usb_get_intfdata(iface);
531
532 /*set rmnet operation mode to eth by default*/
533 set_bit(RMNET_MODE_LLP_ETH, &unet->data[0]);
534
535 /*update net device*/
536 rmnet_usb_setup(unet->net);
537
538 /*create /sys/class/net/rmnet_usbx/dbg_mask*/
539 status = device_create_file(&unet->net->dev, &dev_attr_dbg_mask);
540 if (status)
541 goto out;
542
543 if (first_rmnet_iface_num == -EINVAL)
544 first_rmnet_iface_num = iface_num;
545
546 /*save control device intstance */
547 unet->data[1] = (unsigned long)ctrl_dev \
548 [iface_num - first_rmnet_iface_num];
549
550 status = rmnet_usb_ctrl_probe(iface, unet->status,
551 (struct rmnet_ctrl_dev *)unet->data[1]);
Jack Pham42346cf2012-03-13 12:49:07 -0700552 if (status)
553 goto out;
554
Hemant Kumar7bf94262012-04-18 17:25:10 -0700555 status = rmnet_usb_data_debugfs_init(unet);
556 if (status)
Jack Phame8741502012-06-13 17:34:07 -0700557 dev_dbg(&iface->dev, "mode debugfs file is not available\n");
Hemant Kumar7bf94262012-04-18 17:25:10 -0700558
Jack Pham9bc736e2012-06-19 17:52:51 -0700559 udev = unet->udev;
560
Jack Phambf42e602012-07-03 13:02:37 -0700561 usb_enable_autosuspend(udev);
562
Jack Pham42346cf2012-03-13 12:49:07 -0700563 /* allow modem to wake up suspended system */
Jack Pham9bc736e2012-06-19 17:52:51 -0700564 device_set_wakeup_enable(&udev->dev, 1);
565
566 /* set default autosuspend timeout for modem and roothub */
567 if (udev->parent && !udev->parent->parent) {
568 pm_runtime_set_autosuspend_delay(&udev->dev, 1000);
569 pm_runtime_set_autosuspend_delay(&udev->parent->dev, 200);
570 }
571
Hemant Kumar37c35e42011-09-14 23:44:19 -0700572out:
573 return status;
574}
575
576static void rmnet_usb_disconnect(struct usb_interface *intf)
577{
578 struct usbnet *unet;
Hemant Kumar37c35e42011-09-14 23:44:19 -0700579 struct rmnet_ctrl_dev *dev;
Hemant Kumar37c35e42011-09-14 23:44:19 -0700580
Hemant Kumar9d6016c2012-01-05 16:27:24 -0800581 unet = usb_get_intfdata(intf);
582 if (!unet) {
Jack Phame8741502012-06-13 17:34:07 -0700583 dev_err(&intf->dev, "%s:data device not found\n", __func__);
Hemant Kumar9d6016c2012-01-05 16:27:24 -0800584 return;
Hemant Kumar37c35e42011-09-14 23:44:19 -0700585 }
Hemant Kumar9d6016c2012-01-05 16:27:24 -0800586
Jack Phame8741502012-06-13 17:34:07 -0700587 device_set_wakeup_enable(&unet->udev->dev, 0);
Hemant Kumar90b1a472012-04-26 19:59:56 -0700588 rmnet_usb_data_debugfs_cleanup(unet);
589
Hemant Kumar9d6016c2012-01-05 16:27:24 -0800590 dev = (struct rmnet_ctrl_dev *)unet->data[1];
591 if (!dev) {
Jack Phame8741502012-06-13 17:34:07 -0700592 dev_err(&intf->dev, "%s:ctrl device not found\n", __func__);
Hemant Kumar9d6016c2012-01-05 16:27:24 -0800593 return;
594 }
595 unet->data[0] = 0;
596 unet->data[1] = 0;
597 rmnet_usb_ctrl_disconnect(dev);
598 device_remove_file(&unet->net->dev, &dev_attr_dbg_mask);
599 usbnet_disconnect(intf);
Hemant Kumar37c35e42011-09-14 23:44:19 -0700600}
601
Hemant Kumar9d6016c2012-01-05 16:27:24 -0800602/*bit position represents interface number*/
603#define PID9034_IFACE_MASK 0xF0
604#define PID9048_IFACE_MASK 0x1E0
Hemant Kumarbf024812012-02-24 12:58:56 -0800605#define PID904C_IFACE_MASK 0x1C0
Hemant Kumar9d6016c2012-01-05 16:27:24 -0800606
607static const struct driver_info rmnet_info_pid9034 = {
Hemant Kumar37c35e42011-09-14 23:44:19 -0700608 .description = "RmNET net device",
Jack Pham5a10c6f2012-06-26 11:41:28 -0700609 .flags = FLAG_SEND_ZLP,
Hemant Kumar37c35e42011-09-14 23:44:19 -0700610 .bind = rmnet_usb_bind,
611 .tx_fixup = rmnet_usb_tx_fixup,
612 .rx_fixup = rmnet_usb_rx_fixup,
Jack Phamf77b9962012-02-23 18:45:43 -0800613 .manage_power = rmnet_usb_manage_power,
Hemant Kumar9d6016c2012-01-05 16:27:24 -0800614 .data = PID9034_IFACE_MASK,
615};
616
617static const struct driver_info rmnet_info_pid9048 = {
618 .description = "RmNET net device",
Jack Pham5a10c6f2012-06-26 11:41:28 -0700619 .flags = FLAG_SEND_ZLP,
Hemant Kumar9d6016c2012-01-05 16:27:24 -0800620 .bind = rmnet_usb_bind,
621 .tx_fixup = rmnet_usb_tx_fixup,
622 .rx_fixup = rmnet_usb_rx_fixup,
Jack Phamf77b9962012-02-23 18:45:43 -0800623 .manage_power = rmnet_usb_manage_power,
Hemant Kumar9d6016c2012-01-05 16:27:24 -0800624 .data = PID9048_IFACE_MASK,
Hemant Kumar37c35e42011-09-14 23:44:19 -0700625};
626
Hemant Kumarbf024812012-02-24 12:58:56 -0800627static const struct driver_info rmnet_info_pid904c = {
628 .description = "RmNET net device",
Jack Pham5a10c6f2012-06-26 11:41:28 -0700629 .flags = FLAG_SEND_ZLP,
Hemant Kumarbf024812012-02-24 12:58:56 -0800630 .bind = rmnet_usb_bind,
631 .tx_fixup = rmnet_usb_tx_fixup,
632 .rx_fixup = rmnet_usb_rx_fixup,
Jack Phamf77b9962012-02-23 18:45:43 -0800633 .manage_power = rmnet_usb_manage_power,
Hemant Kumarbf024812012-02-24 12:58:56 -0800634 .data = PID904C_IFACE_MASK,
635};
636
Hemant Kumar37c35e42011-09-14 23:44:19 -0700637static const struct usb_device_id vidpids[] = {
638 {
Hemant Kumar9d6016c2012-01-05 16:27:24 -0800639 USB_DEVICE(0x05c6, 0x9034), /* MDM9x15*/
640 .driver_info = (unsigned long)&rmnet_info_pid9034,
Hemant Kumar37c35e42011-09-14 23:44:19 -0700641 },
Hemant Kumar9d6016c2012-01-05 16:27:24 -0800642 {
643 USB_DEVICE(0x05c6, 0x9048), /* MDM9x15*/
644 .driver_info = (unsigned long)&rmnet_info_pid9048,
645 },
Hemant Kumarbf024812012-02-24 12:58:56 -0800646 {
647 USB_DEVICE(0x05c6, 0x904c), /* MDM9x15*/
648 .driver_info = (unsigned long)&rmnet_info_pid904c,
649 },
Hemant Kumar9d6016c2012-01-05 16:27:24 -0800650
651 { }, /* Terminating entry */
Hemant Kumar37c35e42011-09-14 23:44:19 -0700652};
653
654MODULE_DEVICE_TABLE(usb, vidpids);
655
656static struct usb_driver rmnet_usb = {
657 .name = "rmnet_usb",
658 .id_table = vidpids,
659 .probe = rmnet_usb_probe,
660 .disconnect = rmnet_usb_disconnect,
661 .suspend = rmnet_usb_suspend,
662 .resume = rmnet_usb_resume,
663 .supports_autosuspend = true,
664};
665
666static int __init rmnet_usb_init(void)
667{
668 int retval;
669
670 retval = usb_register(&rmnet_usb);
671 if (retval) {
672 err("usb_register failed: %d", retval);
673 return retval;
674 }
675 /* initialize rmnet ctrl device here*/
676 retval = rmnet_usb_ctrl_init();
677 if (retval) {
678 usb_deregister(&rmnet_usb);
679 err("rmnet_usb_cmux_init failed: %d", retval);
680 return retval;
681 }
682
683 return 0;
684}
685module_init(rmnet_usb_init);
686
687static void __exit rmnet_usb_exit(void)
688{
689 rmnet_usb_ctrl_exit();
690 usb_deregister(&rmnet_usb);
691}
692module_exit(rmnet_usb_exit);
693
694MODULE_DESCRIPTION("msm rmnet usb device");
695MODULE_LICENSE("GPL v2");