blob: 47b87b0a6e5758765f56a83f4d5169575383a593 [file] [log] [blame]
Chandana Kishori Chiluveruc8f81012017-11-02 16:41:20 +05301/*
Pratham Pratap2f5f9832018-02-19 17:22:10 +05302 * Copyright (c) 2011-2018, The Linux Foundation. All rights reserved.
Chandana Kishori Chiluveruc8f81012017-11-02 16:41:20 +05303 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#include <linux/slab.h>
15#include <linux/kernel.h>
16#include <linux/device.h>
17#include <linux/netdevice.h>
18#include <linux/spinlock.h>
19#include <linux/usb_bam.h>
20#include <linux/module.h>
21
Chandana Kishori Chiluveruc8f81012017-11-02 16:41:20 +053022#include "u_data_ipa.h"
23#include "configfs.h"
24
25#define RMNET_NOTIFY_INTERVAL 5
26#define RMNET_MAX_NOTIFY_SIZE sizeof(struct usb_cdc_notification)
27
28#define ACM_CTRL_DTR (1 << 0)
29
30struct f_rmnet {
31 struct usb_function func;
32 enum qti_port_type qti_port_type;
Ajay Agarwalb7f8e952017-12-27 23:25:26 +053033 enum bam_dmux_func_type bam_dmux_func_type;
34 enum data_xport_type xport_type;
35 enum ipa_func_type ipa_func_type;
Chandana Kishori Chiluveruc8f81012017-11-02 16:41:20 +053036 struct grmnet port;
37 int ifc_id;
38 atomic_t online;
39 atomic_t ctrl_online;
40 struct usb_composite_dev *cdev;
Ajay Agarwalb7f8e952017-12-27 23:25:26 +053041 struct data_port bam_port;
Chandana Kishori Chiluveruc8f81012017-11-02 16:41:20 +053042 spinlock_t lock;
43
44 /* usb eps*/
45 struct usb_ep *notify;
46 struct usb_request *notify_req;
47
48 /* control info */
49 struct list_head cpkt_resp_q;
50 unsigned long notify_count;
51};
52
53static struct usb_interface_descriptor rmnet_interface_desc = {
54 .bLength = USB_DT_INTERFACE_SIZE,
55 .bDescriptorType = USB_DT_INTERFACE,
56 .bNumEndpoints = 3,
57 .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
58 .bInterfaceSubClass = USB_CLASS_VENDOR_SPEC,
59 .bInterfaceProtocol = USB_CLASS_VENDOR_SPEC,
60 /* .iInterface = DYNAMIC */
61};
62
63/* Full speed support */
64static struct usb_endpoint_descriptor rmnet_fs_notify_desc = {
65 .bLength = USB_DT_ENDPOINT_SIZE,
66 .bDescriptorType = USB_DT_ENDPOINT,
67 .bEndpointAddress = USB_DIR_IN,
68 .bmAttributes = USB_ENDPOINT_XFER_INT,
69 .wMaxPacketSize = cpu_to_le16(RMNET_MAX_NOTIFY_SIZE),
70 .bInterval = 1 << RMNET_NOTIFY_INTERVAL,
71};
72
73static struct usb_endpoint_descriptor rmnet_fs_in_desc = {
74 .bLength = USB_DT_ENDPOINT_SIZE,
75 .bDescriptorType = USB_DT_ENDPOINT,
76 .bEndpointAddress = USB_DIR_IN,
77 .bmAttributes = USB_ENDPOINT_XFER_BULK,
78 .wMaxPacketSize = cpu_to_le16(64),
79};
80
81static struct usb_endpoint_descriptor rmnet_fs_out_desc = {
82 .bLength = USB_DT_ENDPOINT_SIZE,
83 .bDescriptorType = USB_DT_ENDPOINT,
84 .bEndpointAddress = USB_DIR_OUT,
85 .bmAttributes = USB_ENDPOINT_XFER_BULK,
86 .wMaxPacketSize = cpu_to_le16(64),
87};
88
89static struct usb_descriptor_header *rmnet_fs_function[] = {
90 (struct usb_descriptor_header *) &rmnet_interface_desc,
91 (struct usb_descriptor_header *) &rmnet_fs_notify_desc,
92 (struct usb_descriptor_header *) &rmnet_fs_in_desc,
93 (struct usb_descriptor_header *) &rmnet_fs_out_desc,
94 NULL,
95};
96
97/* High speed support */
98static struct usb_endpoint_descriptor rmnet_hs_notify_desc = {
99 .bLength = USB_DT_ENDPOINT_SIZE,
100 .bDescriptorType = USB_DT_ENDPOINT,
101 .bEndpointAddress = USB_DIR_IN,
102 .bmAttributes = USB_ENDPOINT_XFER_INT,
103 .wMaxPacketSize = cpu_to_le16(RMNET_MAX_NOTIFY_SIZE),
104 .bInterval = RMNET_NOTIFY_INTERVAL + 4,
105};
106
107static struct usb_endpoint_descriptor rmnet_hs_in_desc = {
108 .bLength = USB_DT_ENDPOINT_SIZE,
109 .bDescriptorType = USB_DT_ENDPOINT,
110 .bEndpointAddress = USB_DIR_IN,
111 .bmAttributes = USB_ENDPOINT_XFER_BULK,
112 .wMaxPacketSize = cpu_to_le16(512),
113};
114
115static struct usb_endpoint_descriptor rmnet_hs_out_desc = {
116 .bLength = USB_DT_ENDPOINT_SIZE,
117 .bDescriptorType = USB_DT_ENDPOINT,
118 .bEndpointAddress = USB_DIR_OUT,
119 .bmAttributes = USB_ENDPOINT_XFER_BULK,
120 .wMaxPacketSize = cpu_to_le16(512),
121};
122
123static struct usb_descriptor_header *rmnet_hs_function[] = {
124 (struct usb_descriptor_header *) &rmnet_interface_desc,
125 (struct usb_descriptor_header *) &rmnet_hs_notify_desc,
126 (struct usb_descriptor_header *) &rmnet_hs_in_desc,
127 (struct usb_descriptor_header *) &rmnet_hs_out_desc,
128 NULL,
129};
130
131/* Super speed support */
132static struct usb_endpoint_descriptor rmnet_ss_notify_desc = {
133 .bLength = USB_DT_ENDPOINT_SIZE,
134 .bDescriptorType = USB_DT_ENDPOINT,
135 .bEndpointAddress = USB_DIR_IN,
136 .bmAttributes = USB_ENDPOINT_XFER_INT,
137 .wMaxPacketSize = cpu_to_le16(RMNET_MAX_NOTIFY_SIZE),
138 .bInterval = RMNET_NOTIFY_INTERVAL + 4,
139};
140
141static struct usb_ss_ep_comp_descriptor rmnet_ss_notify_comp_desc = {
142 .bLength = sizeof(rmnet_ss_notify_comp_desc),
143 .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
144
145 /* the following 3 values can be tweaked if necessary */
146 /* .bMaxBurst = 0, */
147 /* .bmAttributes = 0, */
148 .wBytesPerInterval = cpu_to_le16(RMNET_MAX_NOTIFY_SIZE),
149};
150
151static struct usb_endpoint_descriptor rmnet_ss_in_desc = {
152 .bLength = USB_DT_ENDPOINT_SIZE,
153 .bDescriptorType = USB_DT_ENDPOINT,
154 .bEndpointAddress = USB_DIR_IN,
155 .bmAttributes = USB_ENDPOINT_XFER_BULK,
156 .wMaxPacketSize = cpu_to_le16(1024),
157};
158
159static struct usb_ss_ep_comp_descriptor rmnet_ss_in_comp_desc = {
160 .bLength = sizeof(rmnet_ss_in_comp_desc),
161 .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
162
163 /* the following 2 values can be tweaked if necessary */
164 /* .bMaxBurst = 0, */
165 /* .bmAttributes = 0, */
166};
167
168static struct usb_endpoint_descriptor rmnet_ss_out_desc = {
169 .bLength = USB_DT_ENDPOINT_SIZE,
170 .bDescriptorType = USB_DT_ENDPOINT,
171 .bEndpointAddress = USB_DIR_OUT,
172 .bmAttributes = USB_ENDPOINT_XFER_BULK,
173 .wMaxPacketSize = cpu_to_le16(1024),
174};
175
176static struct usb_ss_ep_comp_descriptor rmnet_ss_out_comp_desc = {
177 .bLength = sizeof(rmnet_ss_out_comp_desc),
178 .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
179
180 /* the following 2 values can be tweaked if necessary */
181 /* .bMaxBurst = 0, */
182 /* .bmAttributes = 0, */
183};
184
185static struct usb_descriptor_header *rmnet_ss_function[] = {
186 (struct usb_descriptor_header *) &rmnet_interface_desc,
187 (struct usb_descriptor_header *) &rmnet_ss_notify_desc,
188 (struct usb_descriptor_header *) &rmnet_ss_notify_comp_desc,
189 (struct usb_descriptor_header *) &rmnet_ss_in_desc,
190 (struct usb_descriptor_header *) &rmnet_ss_in_comp_desc,
191 (struct usb_descriptor_header *) &rmnet_ss_out_desc,
192 (struct usb_descriptor_header *) &rmnet_ss_out_comp_desc,
193 NULL,
194};
195
196/* String descriptors */
197
198static struct usb_string rmnet_string_defs[] = {
199 [0].s = "RmNet",
200 { } /* end of list */
201};
202
203static struct usb_gadget_strings rmnet_string_table = {
204 .language = 0x0409, /* en-us */
205 .strings = rmnet_string_defs,
206};
207
208static struct usb_gadget_strings *rmnet_strings[] = {
209 &rmnet_string_table,
210 NULL,
211};
212
213static struct usb_interface_descriptor dpl_data_intf_desc = {
214 .bLength = sizeof(dpl_data_intf_desc),
215 .bDescriptorType = USB_DT_INTERFACE,
216 .bAlternateSetting = 0,
217 .bNumEndpoints = 1,
218 .bInterfaceClass = 0xff,
219 .bInterfaceSubClass = 0xff,
220 .bInterfaceProtocol = 0xff,
221};
222
Pratham Pratap2f5f9832018-02-19 17:22:10 +0530223static struct usb_endpoint_descriptor dpl_fs_data_desc = {
224 .bLength = USB_DT_ENDPOINT_SIZE,
225 .bDescriptorType = USB_DT_ENDPOINT,
226 .bEndpointAddress = USB_DIR_IN,
227 .bmAttributes = USB_ENDPOINT_XFER_BULK,
228 .wMaxPacketSize = cpu_to_le16(64),
229};
230
Chandana Kishori Chiluveruc8f81012017-11-02 16:41:20 +0530231static struct usb_endpoint_descriptor dpl_hs_data_desc = {
232 .bLength = USB_DT_ENDPOINT_SIZE,
233 .bDescriptorType = USB_DT_ENDPOINT,
234 .bEndpointAddress = USB_DIR_IN,
235 .bmAttributes = USB_ENDPOINT_XFER_BULK,
236 .wMaxPacketSize = cpu_to_le16(512),
237};
238
239static struct usb_endpoint_descriptor dpl_ss_data_desc = {
240 .bLength = USB_DT_ENDPOINT_SIZE,
241 .bDescriptorType = USB_DT_ENDPOINT,
242 .bEndpointAddress = USB_DIR_IN,
243 .bmAttributes = USB_ENDPOINT_XFER_BULK,
244 .wMaxPacketSize = cpu_to_le16(1024),
245};
246
247static struct usb_ss_ep_comp_descriptor dpl_data_ep_comp_desc = {
248 .bLength = sizeof(dpl_data_ep_comp_desc),
249 .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
250 .bMaxBurst = 1,
251 .bmAttributes = 0,
252 .wBytesPerInterval = 0,
253};
254
Pratham Pratap2f5f9832018-02-19 17:22:10 +0530255static struct usb_descriptor_header *dpl_fs_data_only_desc[] = {
256 (struct usb_descriptor_header *) &dpl_data_intf_desc,
257 (struct usb_descriptor_header *) &dpl_fs_data_desc,
258 NULL,
259};
260
Chandana Kishori Chiluveruc8f81012017-11-02 16:41:20 +0530261static struct usb_descriptor_header *dpl_hs_data_only_desc[] = {
262 (struct usb_descriptor_header *) &dpl_data_intf_desc,
263 (struct usb_descriptor_header *) &dpl_hs_data_desc,
264 NULL,
265};
266
267static struct usb_descriptor_header *dpl_ss_data_only_desc[] = {
268 (struct usb_descriptor_header *) &dpl_data_intf_desc,
269 (struct usb_descriptor_header *) &dpl_ss_data_desc,
270 (struct usb_descriptor_header *) &dpl_data_ep_comp_desc,
271 NULL,
272};
273
274/* string descriptors: */
275
276static struct usb_string dpl_string_defs[] = {
277 [0].s = "QDSS DATA",
278 {}, /* end of list */
279};
280
281static struct usb_gadget_strings dpl_string_table = {
282 .language = 0x0409,
283 .strings = dpl_string_defs,
284};
285
286static struct usb_gadget_strings *dpl_strings[] = {
287 &dpl_string_table,
288 NULL,
289};
290
291static void frmnet_ctrl_response_available(struct f_rmnet *dev);
292
293/* ------- misc functions --------------------*/
294
295static inline struct f_rmnet *func_to_rmnet(struct usb_function *f)
296{
297 return container_of(f, struct f_rmnet, func);
298}
299
300static inline struct f_rmnet *port_to_rmnet(struct grmnet *r)
301{
302 return container_of(r, struct f_rmnet, port);
303}
304
305int name_to_prot(struct f_rmnet *dev, const char *name)
306{
307 if (!name)
308 goto error;
309
310 if (!strncasecmp("rmnet", name, MAX_INST_NAME_LEN)) {
311 dev->qti_port_type = QTI_PORT_RMNET;
Ajay Agarwalb7f8e952017-12-27 23:25:26 +0530312 dev->xport_type = BAM2BAM_IPA;
313 dev->ipa_func_type = USB_IPA_FUNC_RMNET;
Chandana Kishori Chiluveruc8f81012017-11-02 16:41:20 +0530314 } else if (!strncasecmp("dpl", name, MAX_INST_NAME_LEN)) {
315 dev->qti_port_type = QTI_PORT_DPL;
Ajay Agarwalb7f8e952017-12-27 23:25:26 +0530316 dev->xport_type = BAM2BAM_IPA;
317 dev->ipa_func_type = USB_IPA_FUNC_DPL;
318 } else if (!strncasecmp("rmnet_bam_dmux", name, MAX_INST_NAME_LEN)) {
319 dev->qti_port_type = QTI_PORT_RMNET;
320 dev->xport_type = BAM_DMUX;
321 dev->bam_dmux_func_type = BAM_DMUX_FUNC_RMNET;
322 } else if (!strncasecmp("dpl_bam_dmux", name, MAX_INST_NAME_LEN)) {
323 dev->qti_port_type = QTI_PORT_DPL;
324 dev->xport_type = BAM_DMUX;
325 dev->bam_dmux_func_type = BAM_DMUX_FUNC_DPL;
Chandana Kishori Chiluveruc8f81012017-11-02 16:41:20 +0530326 }
Ajay Agarwalb7f8e952017-12-27 23:25:26 +0530327
Chandana Kishori Chiluveruc8f81012017-11-02 16:41:20 +0530328 return 0;
329
330error:
331 return -EINVAL;
332}
333
334static struct usb_request *
335frmnet_alloc_req(struct usb_ep *ep, unsigned int len, gfp_t flags)
336{
337 struct usb_request *req;
338
339 req = usb_ep_alloc_request(ep, flags);
340 if (!req)
341 return ERR_PTR(-ENOMEM);
342
343 req->buf = kmalloc(len, flags);
344 if (!req->buf) {
345 usb_ep_free_request(ep, req);
346 return ERR_PTR(-ENOMEM);
347 }
348
349 req->length = len;
350
351 return req;
352}
353
354void frmnet_free_req(struct usb_ep *ep, struct usb_request *req)
355{
356 kfree(req->buf);
357 usb_ep_free_request(ep, req);
358}
359
360static struct
361rmnet_ctrl_pkt *rmnet_alloc_ctrl_pkt(unsigned int len, gfp_t flags)
362{
363 struct rmnet_ctrl_pkt *pkt;
364
365 pkt = kzalloc(sizeof(struct rmnet_ctrl_pkt), flags);
366 if (!pkt)
367 return ERR_PTR(-ENOMEM);
368
369 pkt->buf = kmalloc(len, flags);
370 if (!pkt->buf) {
371 kfree(pkt);
372 return ERR_PTR(-ENOMEM);
373 }
374 pkt->len = len;
375
376 return pkt;
377}
378
379static void rmnet_free_ctrl_pkt(struct rmnet_ctrl_pkt *pkt)
380{
381 kfree(pkt->buf);
382 kfree(pkt);
383}
384
385/* -------------------------------------------*/
386
387static int gport_rmnet_connect(struct f_rmnet *dev)
388{
389 int ret;
390 int src_connection_idx = 0, dst_connection_idx = 0;
391 struct usb_gadget *gadget = dev->cdev->gadget;
392 enum usb_ctrl usb_bam_type;
393 int bam_pipe_num = (dev->qti_port_type == QTI_PORT_DPL) ? 1 : 0;
394
Ajay Agarwalb7f8e952017-12-27 23:25:26 +0530395 ret = gqti_ctrl_connect(&dev->port, dev->qti_port_type, dev->ifc_id,
396 dev->xport_type);
Chandana Kishori Chiluveruc8f81012017-11-02 16:41:20 +0530397 if (ret) {
398 pr_err("%s: gqti_ctrl_connect failed: err:%d\n",
399 __func__, ret);
400 return ret;
401 }
402 if (dev->qti_port_type == QTI_PORT_DPL)
403 dev->port.send_encap_cmd(QTI_PORT_DPL, NULL, 0);
Ajay Agarwalb7f8e952017-12-27 23:25:26 +0530404 dev->bam_port.cdev = dev->cdev;
405 if (dev->xport_type == BAM_DMUX) {
406 ret = gbam_connect(&dev->bam_port, dev->bam_dmux_func_type);
407 if (ret)
408 pr_err("%s: gbam_connect failed: err:%d\n",
409 __func__, ret);
410 } else {
411 ipa_data_port_select(dev->ipa_func_type);
412 usb_bam_type = usb_bam_get_bam_type(gadget->name);
Chandana Kishori Chiluveruc8f81012017-11-02 16:41:20 +0530413
Ajay Agarwalb7f8e952017-12-27 23:25:26 +0530414 if (dev->bam_port.in) {
415 dst_connection_idx = usb_bam_get_connection_idx(
416 usb_bam_type, IPA_P_BAM,
417 PEER_PERIPHERAL_TO_USB,
418 USB_BAM_DEVICE, bam_pipe_num);
419 }
420 if (dev->bam_port.out) {
421 src_connection_idx = usb_bam_get_connection_idx(
422 usb_bam_type, IPA_P_BAM,
423 USB_TO_PEER_PERIPHERAL,
424 USB_BAM_DEVICE, bam_pipe_num);
425 }
426 if (dst_connection_idx < 0 || src_connection_idx < 0) {
427 pr_err("%s: usb_bam_get_connection_idx failed\n",
428 __func__);
429 gqti_ctrl_disconnect(&dev->port, dev->qti_port_type);
430 return -EINVAL;
431 }
432 ret = ipa_data_connect(&dev->bam_port, dev->ipa_func_type,
433 src_connection_idx, dst_connection_idx);
434 if (ret)
435 pr_err("%s: ipa_data_connect failed: err:%d\n",
436 __func__, ret);
Chandana Kishori Chiluveruc8f81012017-11-02 16:41:20 +0530437 }
Ajay Agarwalb7f8e952017-12-27 23:25:26 +0530438
Chandana Kishori Chiluveruc8f81012017-11-02 16:41:20 +0530439 if (ret) {
Chandana Kishori Chiluveruc8f81012017-11-02 16:41:20 +0530440 gqti_ctrl_disconnect(&dev->port, dev->qti_port_type);
441 return ret;
442 }
443 return 0;
444}
445
446static int gport_rmnet_disconnect(struct f_rmnet *dev)
447{
448 gqti_ctrl_disconnect(&dev->port, dev->qti_port_type);
Ajay Agarwalb7f8e952017-12-27 23:25:26 +0530449 if (dev->xport_type == BAM_DMUX)
450 gbam_disconnect(&dev->bam_port, dev->bam_dmux_func_type);
451 else
452 ipa_data_disconnect(&dev->bam_port, dev->ipa_func_type);
453
Chandana Kishori Chiluveruc8f81012017-11-02 16:41:20 +0530454 return 0;
455}
456
457static void frmnet_free(struct usb_function *f)
458{
459 struct f_rmnet_opts *opts;
460
461 opts = container_of(f->fi, struct f_rmnet_opts, func_inst);
462 opts->refcnt--;
463}
464
465static void frmnet_unbind(struct usb_configuration *c, struct usb_function *f)
466{
467 struct f_rmnet *dev = func_to_rmnet(f);
468 struct usb_gadget *gadget = c->cdev->gadget;
469
470 pr_debug("%s: start unbinding\nclear_desc\n", __func__);
471 if (gadget_is_superspeed(gadget) && f->ss_descriptors)
472 usb_free_descriptors(f->ss_descriptors);
473
474 if (gadget_is_dualspeed(gadget) && f->hs_descriptors)
475 usb_free_descriptors(f->hs_descriptors);
476
477 if (f->fs_descriptors)
478 usb_free_descriptors(f->fs_descriptors);
479
480 if (dev->notify_req)
481 frmnet_free_req(dev->notify, dev->notify_req);
482}
483
484static void frmnet_purge_responses(struct f_rmnet *dev)
485{
486 unsigned long flags;
487 struct rmnet_ctrl_pkt *cpkt;
488
489 pr_debug("%s: Purging responses\n", __func__);
490 spin_lock_irqsave(&dev->lock, flags);
491 while (!list_empty(&dev->cpkt_resp_q)) {
492 cpkt = list_first_entry(&dev->cpkt_resp_q,
493 struct rmnet_ctrl_pkt, list);
494
495 list_del(&cpkt->list);
496 rmnet_free_ctrl_pkt(cpkt);
497 }
498 dev->notify_count = 0;
499 spin_unlock_irqrestore(&dev->lock, flags);
500}
501
502static void frmnet_suspend(struct usb_function *f)
503{
504 struct f_rmnet *dev = func_to_rmnet(f);
505 bool remote_wakeup_allowed;
506
507 if (f->config->cdev->gadget->speed == USB_SPEED_SUPER)
508 remote_wakeup_allowed = f->func_wakeup_allowed;
509 else
510 remote_wakeup_allowed = f->config->cdev->gadget->remote_wakeup;
511
512 pr_debug("%s: dev: %pK remote_wakeup: %d\n", __func__, dev,
513 remote_wakeup_allowed);
514
515 if (dev->notify) {
516 usb_ep_fifo_flush(dev->notify);
517 frmnet_purge_responses(dev);
518 }
Ajay Agarwalb7f8e952017-12-27 23:25:26 +0530519
520 if (dev->xport_type == BAM2BAM_IPA)
521 ipa_data_suspend(&dev->bam_port, dev->ipa_func_type,
522 remote_wakeup_allowed);
Chandana Kishori Chiluveruc8f81012017-11-02 16:41:20 +0530523}
524
525static void frmnet_resume(struct usb_function *f)
526{
527 struct f_rmnet *dev = func_to_rmnet(f);
528 bool remote_wakeup_allowed;
529
530 if (f->config->cdev->gadget->speed == USB_SPEED_SUPER)
531 remote_wakeup_allowed = f->func_wakeup_allowed;
532 else
533 remote_wakeup_allowed = f->config->cdev->gadget->remote_wakeup;
534
535 pr_debug("%s: dev: %pK remote_wakeup: %d\n", __func__, dev,
536 remote_wakeup_allowed);
Ajay Agarwalb7f8e952017-12-27 23:25:26 +0530537 if (dev->xport_type == BAM2BAM_IPA)
538 ipa_data_resume(&dev->bam_port, dev->ipa_func_type,
539 remote_wakeup_allowed);
Chandana Kishori Chiluveruc8f81012017-11-02 16:41:20 +0530540}
541
542static void frmnet_disable(struct usb_function *f)
543{
544 struct f_rmnet *dev = func_to_rmnet(f);
545
546 pr_debug("%s: Disabling\n", __func__);
547 atomic_set(&dev->online, 0);
548 if (dev->notify) {
549 usb_ep_disable(dev->notify);
550 dev->notify->driver_data = NULL;
551 frmnet_purge_responses(dev);
552 }
553
554 gport_rmnet_disconnect(dev);
555}
556
557static int
558frmnet_set_alt(struct usb_function *f, unsigned int intf, unsigned int alt)
559{
560 struct f_rmnet *dev = func_to_rmnet(f);
561 struct usb_composite_dev *cdev = f->config->cdev;
562 int ret = 0;
563
564 pr_debug("%s:dev:%pK\n", __func__, dev);
565 dev->cdev = cdev;
566 if (dev->notify) {
567 if (dev->notify->driver_data) {
568 pr_debug("%s: reset port\n", __func__);
569 usb_ep_disable(dev->notify);
570 }
571
572 ret = config_ep_by_speed(cdev->gadget, f, dev->notify);
573 if (ret) {
574 dev->notify->desc = NULL;
575 ERROR(cdev,
576 "config_ep_by_speed failed for ep %s, result %d\n",
577 dev->notify->name, ret);
578 return ret;
579 }
580
581 ret = usb_ep_enable(dev->notify);
582 if (ret) {
583 pr_err("%s: usb ep#%s enable failed, err#%d\n",
584 __func__, dev->notify->name, ret);
585 dev->notify->desc = NULL;
586 return ret;
587 }
588
589 dev->notify->driver_data = dev;
590 }
591
Ajay Agarwalb7f8e952017-12-27 23:25:26 +0530592 if (dev->bam_port.in && !dev->bam_port.in->desc
593 && config_ep_by_speed(cdev->gadget, f, dev->bam_port.in)) {
Chandana Kishori Chiluveruc8f81012017-11-02 16:41:20 +0530594 pr_err("%s(): config_ep_by_speed failed.\n",
595 __func__);
Ajay Agarwalb7f8e952017-12-27 23:25:26 +0530596 dev->bam_port.in->desc = NULL;
Chandana Kishori Chiluveruc8f81012017-11-02 16:41:20 +0530597 ret = -EINVAL;
598 goto err_disable_ep;
599 }
600
Ajay Agarwalb7f8e952017-12-27 23:25:26 +0530601 if (dev->bam_port.out && !dev->bam_port.out->desc
602 && config_ep_by_speed(cdev->gadget, f, dev->bam_port.out)) {
Chandana Kishori Chiluveruc8f81012017-11-02 16:41:20 +0530603 pr_err("%s(): config_ep_by_speed failed.\n",
604 __func__);
Ajay Agarwalb7f8e952017-12-27 23:25:26 +0530605 dev->bam_port.out->desc = NULL;
Chandana Kishori Chiluveruc8f81012017-11-02 16:41:20 +0530606 ret = -EINVAL;
607 goto err_disable_ep;
608 }
609
610 ret = gport_rmnet_connect(dev);
611 if (ret) {
612 pr_err("%s(): gport_rmnet_connect fail with err:%d\n",
613 __func__, ret);
614 goto err_disable_ep;
615 }
616
617 atomic_set(&dev->online, 1);
618 /*
619 * In case notifications were aborted, but there are
620 * pending control packets in the response queue,
621 * re-add the notifications.
622 */
623 if (dev->qti_port_type == QTI_PORT_RMNET) {
624 struct list_head *cpkt;
625
626 list_for_each(cpkt, &dev->cpkt_resp_q)
627 frmnet_ctrl_response_available(dev);
628 }
629
630 return ret;
631err_disable_ep:
632 if (dev->notify && dev->notify->driver_data)
633 usb_ep_disable(dev->notify);
634
635 return ret;
636}
637
638static void frmnet_ctrl_response_available(struct f_rmnet *dev)
639{
640 struct usb_request *req = dev->notify_req;
641 struct usb_cdc_notification *event;
642 unsigned long flags;
643 int ret;
644 struct rmnet_ctrl_pkt *cpkt;
645
646 pr_debug("%s:dev:%pK\n", __func__, dev);
647 spin_lock_irqsave(&dev->lock, flags);
648 if (!atomic_read(&dev->online) || !req || !req->buf) {
649 spin_unlock_irqrestore(&dev->lock, flags);
650 return;
651 }
652
653 if (++dev->notify_count != 1) {
654 spin_unlock_irqrestore(&dev->lock, flags);
655 return;
656 }
657
658 event = req->buf;
659 event->bmRequestType = USB_DIR_IN | USB_TYPE_CLASS
660 | USB_RECIP_INTERFACE;
661 event->bNotificationType = USB_CDC_NOTIFY_RESPONSE_AVAILABLE;
662 event->wValue = cpu_to_le16(0);
663 event->wIndex = cpu_to_le16(dev->ifc_id);
664 event->wLength = cpu_to_le16(0);
665 spin_unlock_irqrestore(&dev->lock, flags);
666
667 ret = usb_ep_queue(dev->notify, dev->notify_req, GFP_ATOMIC);
668 if (ret) {
669 spin_lock_irqsave(&dev->lock, flags);
670 if (!list_empty(&dev->cpkt_resp_q)) {
671 if (dev->notify_count > 0)
672 dev->notify_count--;
673 else {
674 pr_debug("%s: Invalid notify_count=%lu to decrement\n",
675 __func__, dev->notify_count);
676 spin_unlock_irqrestore(&dev->lock, flags);
677 return;
678 }
679 cpkt = list_first_entry(&dev->cpkt_resp_q,
680 struct rmnet_ctrl_pkt, list);
681 list_del(&cpkt->list);
682 rmnet_free_ctrl_pkt(cpkt);
683 }
684 spin_unlock_irqrestore(&dev->lock, flags);
685 pr_debug("ep enqueue error %d\n", ret);
686 }
687}
688
689static void frmnet_connect(struct grmnet *gr)
690{
691 struct f_rmnet *dev;
692
693 if (!gr) {
694 pr_err("%s: Invalid grmnet:%pK\n", __func__, gr);
695 return;
696 }
697
698 dev = port_to_rmnet(gr);
699
700 atomic_set(&dev->ctrl_online, 1);
701}
702
703static void frmnet_disconnect(struct grmnet *gr)
704{
705 struct f_rmnet *dev;
706 struct usb_cdc_notification *event;
707 int status;
708
709 if (!gr) {
710 pr_err("%s: Invalid grmnet:%pK\n", __func__, gr);
711 return;
712 }
713
714 dev = port_to_rmnet(gr);
715
716 atomic_set(&dev->ctrl_online, 0);
717
718 if (!atomic_read(&dev->online)) {
719 pr_debug("%s: nothing to do\n", __func__);
720 return;
721 }
722
723 usb_ep_fifo_flush(dev->notify);
724
725 event = dev->notify_req->buf;
726 event->bmRequestType = USB_DIR_IN | USB_TYPE_CLASS
727 | USB_RECIP_INTERFACE;
728 event->bNotificationType = USB_CDC_NOTIFY_NETWORK_CONNECTION;
729 event->wValue = cpu_to_le16(0);
730 event->wIndex = cpu_to_le16(dev->ifc_id);
731 event->wLength = cpu_to_le16(0);
732
733 status = usb_ep_queue(dev->notify, dev->notify_req, GFP_ATOMIC);
734 if (status < 0) {
735 if (!atomic_read(&dev->online))
736 return;
737 pr_err("%s: rmnet notify ep enqueue error %d\n",
738 __func__, status);
739 }
740
741 frmnet_purge_responses(dev);
742}
743
744static int
745frmnet_send_cpkt_response(void *gr, void *buf, size_t len)
746{
747 struct f_rmnet *dev;
748 struct rmnet_ctrl_pkt *cpkt;
749 unsigned long flags;
750
751 if (!gr || !buf) {
752 pr_err("%s: Invalid grmnet/buf, grmnet:%pK buf:%pK\n",
753 __func__, gr, buf);
754 return -ENODEV;
755 }
756 cpkt = rmnet_alloc_ctrl_pkt(len, GFP_ATOMIC);
757 if (IS_ERR(cpkt)) {
758 pr_err("%s: Unable to allocate ctrl pkt\n", __func__);
759 return -ENOMEM;
760 }
761 memcpy(cpkt->buf, buf, len);
762 cpkt->len = len;
763
764 dev = port_to_rmnet(gr);
765
766 pr_debug("%s: dev: %pK\n", __func__, dev);
767 if (!atomic_read(&dev->online) || !atomic_read(&dev->ctrl_online)) {
768 rmnet_free_ctrl_pkt(cpkt);
769 return 0;
770 }
771
772 spin_lock_irqsave(&dev->lock, flags);
773 list_add_tail(&cpkt->list, &dev->cpkt_resp_q);
774 spin_unlock_irqrestore(&dev->lock, flags);
775
776 frmnet_ctrl_response_available(dev);
777
778 return 0;
779}
780
781static void
782frmnet_cmd_complete(struct usb_ep *ep, struct usb_request *req)
783{
784 struct f_rmnet *dev = req->context;
785 struct usb_composite_dev *cdev;
786
787 if (!dev) {
788 pr_err("%s: rmnet dev is null\n", __func__);
789 return;
790 }
791 pr_debug("%s: dev: %pK\n", __func__, dev);
792 cdev = dev->cdev;
793
794 if (dev->port.send_encap_cmd)
795 dev->port.send_encap_cmd(QTI_PORT_RMNET, req->buf, req->actual);
796}
797
798static void frmnet_notify_complete(struct usb_ep *ep, struct usb_request *req)
799{
800 struct f_rmnet *dev = req->context;
801 int status = req->status;
802 unsigned long flags;
803 struct rmnet_ctrl_pkt *cpkt;
804
805 pr_debug("%s: dev: %pK\n", __func__, dev);
806 switch (status) {
807 case -ECONNRESET:
808 case -ESHUTDOWN:
809 /* connection gone */
810 spin_lock_irqsave(&dev->lock, flags);
811 dev->notify_count = 0;
812 spin_unlock_irqrestore(&dev->lock, flags);
813 break;
814 default:
815 pr_err("rmnet notify ep error %d\n", status);
816 /* FALLTHROUGH */
817 case 0:
818 if (!atomic_read(&dev->ctrl_online))
819 break;
820
821 spin_lock_irqsave(&dev->lock, flags);
822 if (dev->notify_count > 0) {
823 dev->notify_count--;
824 if (dev->notify_count == 0) {
825 spin_unlock_irqrestore(&dev->lock, flags);
826 break;
827 }
828 } else {
829 pr_debug("%s: Invalid notify_count=%lu to decrement\n",
830 __func__, dev->notify_count);
831 spin_unlock_irqrestore(&dev->lock, flags);
832 break;
833 }
834 spin_unlock_irqrestore(&dev->lock, flags);
835
836 status = usb_ep_queue(dev->notify, req, GFP_ATOMIC);
837 if (status) {
838 spin_lock_irqsave(&dev->lock, flags);
839 if (!list_empty(&dev->cpkt_resp_q)) {
840 if (dev->notify_count > 0)
841 dev->notify_count--;
842 else {
843 pr_err("%s: Invalid notify_count=%lu to decrement\n",
844 __func__, dev->notify_count);
845 spin_unlock_irqrestore(&dev->lock,
846 flags);
847 break;
848 }
849 cpkt = list_first_entry(&dev->cpkt_resp_q,
850 struct rmnet_ctrl_pkt, list);
851 list_del(&cpkt->list);
852 rmnet_free_ctrl_pkt(cpkt);
853 }
854 spin_unlock_irqrestore(&dev->lock, flags);
855 pr_debug("ep enqueue error %d\n", status);
856 }
857 break;
858 }
859}
860
861static int
862frmnet_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
863{
864 struct f_rmnet *dev = func_to_rmnet(f);
865 struct usb_composite_dev *cdev = dev->cdev;
866 struct usb_request *req = cdev->req;
867 u16 w_index = le16_to_cpu(ctrl->wIndex);
868 u16 w_value = le16_to_cpu(ctrl->wValue);
869 u16 w_length = le16_to_cpu(ctrl->wLength);
870 int ret = -EOPNOTSUPP;
871
872 pr_debug("%s: dev: %pK\n", __func__, dev);
873 if (!atomic_read(&dev->online)) {
874 pr_warn("%s: usb cable is not connected\n", __func__);
875 return -ENOTCONN;
876 }
877
878 switch ((ctrl->bRequestType << 8) | ctrl->bRequest) {
879
880 case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
881 | USB_CDC_SEND_ENCAPSULATED_COMMAND:
882 pr_debug("%s: USB_CDC_SEND_ENCAPSULATED_COMMAND\n"
883 , __func__);
884 ret = w_length;
885 req->complete = frmnet_cmd_complete;
886 req->context = dev;
887 break;
888
889
890 case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
891 | USB_CDC_GET_ENCAPSULATED_RESPONSE:
892 pr_debug("%s: USB_CDC_GET_ENCAPSULATED_RESPONSE\n", __func__);
893 if (w_value) {
894 pr_err("%s: invalid w_value = %04x\n",
895 __func__, w_value);
896 goto invalid;
897 } else {
898 unsigned int len;
899 struct rmnet_ctrl_pkt *cpkt;
900
901 spin_lock(&dev->lock);
902 if (list_empty(&dev->cpkt_resp_q)) {
903 pr_err("ctrl resp queue empty: ");
904 pr_err("req%02x.%02x v%04x i%04x l%d\n",
905 ctrl->bRequestType, ctrl->bRequest,
906 w_value, w_index, w_length);
907 ret = 0;
908 spin_unlock(&dev->lock);
909 goto invalid;
910 }
911
912 cpkt = list_first_entry(&dev->cpkt_resp_q,
913 struct rmnet_ctrl_pkt, list);
914 list_del(&cpkt->list);
915 spin_unlock(&dev->lock);
916
917 len = min_t(unsigned int, w_length, cpkt->len);
918 memcpy(req->buf, cpkt->buf, len);
919 ret = len;
920
921 rmnet_free_ctrl_pkt(cpkt);
922 }
923 break;
924 case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
925 | USB_CDC_REQ_SET_CONTROL_LINE_STATE:
926 pr_debug("%s: USB_CDC_REQ_SET_CONTROL_LINE_STATE: DTR:%d\n",
927 __func__, w_value & ACM_CTRL_DTR ? 1 : 0);
928 if (dev->port.notify_modem) {
929 dev->port.notify_modem(&dev->port,
930 QTI_PORT_RMNET, w_value);
931 }
932 ret = 0;
933
934 break;
935 default:
936
937invalid:
938 DBG(cdev, "invalid control req%02x.%02x v%04x i%04x l%d\n",
939 ctrl->bRequestType, ctrl->bRequest,
940 w_value, w_index, w_length);
941 }
942
943 /* respond with data transfer or status phase? */
944 if (ret >= 0) {
945 VDBG(cdev, "rmnet req%02x.%02x v%04x i%04x l%d\n",
946 ctrl->bRequestType, ctrl->bRequest,
947 w_value, w_index, w_length);
948 req->zero = (ret < w_length);
949 req->length = ret;
950 ret = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
951 if (ret < 0)
952 ERROR(cdev, "rmnet ep0 enqueue err %d\n", ret);
953 }
954
955 return ret;
956}
957
958static int ipa_update_function_bind_params(struct f_rmnet *dev,
959 struct usb_composite_dev *cdev, struct ipa_function_bind_info *info)
960{
961 struct usb_ep *ep;
962 struct usb_function *f = &dev->func;
963 int status;
964
965 /* maybe allocate device-global string IDs */
966 if (info->string_defs[0].id != 0)
967 goto skip_string_id_alloc;
968
969 if (info->data_str_idx >= 0 && info->data_desc) {
970 /* data interface label */
971 status = usb_string_id(cdev);
972 if (status < 0)
973 return status;
974 info->string_defs[info->data_str_idx].id = status;
975 info->data_desc->iInterface = status;
976 }
977
978skip_string_id_alloc:
979 if (info->data_desc)
980 info->data_desc->bInterfaceNumber = dev->ifc_id;
981
982 if (info->fs_in_desc) {
983 ep = usb_ep_autoconfig(cdev->gadget, info->fs_in_desc);
984 if (!ep) {
985 pr_err("%s: usb epin autoconfig failed\n",
986 __func__);
987 return -ENODEV;
988 }
Ajay Agarwalb7f8e952017-12-27 23:25:26 +0530989 dev->bam_port.in = ep;
Chandana Kishori Chiluveruc8f81012017-11-02 16:41:20 +0530990 ep->driver_data = cdev;
991 }
992
993 if (info->fs_out_desc) {
994 ep = usb_ep_autoconfig(cdev->gadget, info->fs_out_desc);
995 if (!ep) {
996 pr_err("%s: usb epout autoconfig failed\n",
997 __func__);
998 status = -ENODEV;
999 goto ep_auto_out_fail;
1000 }
Ajay Agarwalb7f8e952017-12-27 23:25:26 +05301001 dev->bam_port.out = ep;
Chandana Kishori Chiluveruc8f81012017-11-02 16:41:20 +05301002 ep->driver_data = cdev;
1003 }
1004
1005 if (info->fs_notify_desc) {
1006 ep = usb_ep_autoconfig(cdev->gadget, info->fs_notify_desc);
1007 if (!ep) {
1008 pr_err("%s: usb epnotify autoconfig failed\n",
1009 __func__);
1010 status = -ENODEV;
1011 goto ep_auto_notify_fail;
1012 }
1013 dev->notify = ep;
1014 ep->driver_data = cdev;
1015 dev->notify_req = frmnet_alloc_req(ep,
1016 sizeof(struct usb_cdc_notification),
1017 GFP_KERNEL);
1018 if (IS_ERR(dev->notify_req)) {
1019 pr_err("%s: unable to allocate memory for notify req\n",
1020 __func__);
1021 status = -ENOMEM;
1022 goto ep_notify_alloc_fail;
1023 }
1024
1025 dev->notify_req->complete = frmnet_notify_complete;
1026 dev->notify_req->context = dev;
1027 }
1028
1029 status = -ENOMEM;
1030 f->fs_descriptors = usb_copy_descriptors(info->fs_desc_hdr);
1031 if (!f->fs_descriptors) {
1032 pr_err("%s: no descriptors, usb_copy descriptors(fs)failed\n",
1033 __func__);
1034 goto fail;
1035 }
1036
1037 if (gadget_is_dualspeed(cdev->gadget)) {
1038 if (info->fs_in_desc && info->hs_in_desc)
1039 info->hs_in_desc->bEndpointAddress =
1040 info->fs_in_desc->bEndpointAddress;
1041 if (info->fs_out_desc && info->hs_out_desc)
1042 info->hs_out_desc->bEndpointAddress =
1043 info->fs_out_desc->bEndpointAddress;
1044 if (info->fs_notify_desc && info->hs_notify_desc)
1045 info->hs_notify_desc->bEndpointAddress =
1046 info->fs_notify_desc->bEndpointAddress;
1047
1048 /* copy descriptors, and track endpoint copies */
1049 f->hs_descriptors = usb_copy_descriptors(info->hs_desc_hdr);
1050 if (!f->hs_descriptors) {
1051 pr_err("%s: no hs_descriptors, usb_copy descriptors(hs)failed\n",
1052 __func__);
1053 goto fail;
1054 }
1055 }
1056
1057 if (gadget_is_superspeed(cdev->gadget)) {
1058 if (info->fs_in_desc && info->ss_in_desc)
1059 info->ss_in_desc->bEndpointAddress =
1060 info->fs_in_desc->bEndpointAddress;
1061
1062 if (info->fs_out_desc && info->ss_out_desc)
1063 info->ss_out_desc->bEndpointAddress =
1064 info->fs_out_desc->bEndpointAddress;
1065 if (info->fs_notify_desc && info->ss_notify_desc)
1066 info->ss_notify_desc->bEndpointAddress =
1067 info->fs_notify_desc->bEndpointAddress;
1068
1069 /* copy descriptors, and track endpoint copies */
1070 f->ss_descriptors = usb_copy_descriptors(info->ss_desc_hdr);
1071 if (!f->ss_descriptors) {
1072 pr_err("%s: no ss_descriptors,usb_copy descriptors(ss)failed\n",
1073 __func__);
1074 goto fail;
1075 }
1076 }
1077
1078 return 0;
1079
1080fail:
1081 if (gadget_is_superspeed(cdev->gadget) && f->ss_descriptors)
1082 usb_free_descriptors(f->ss_descriptors);
1083 if (gadget_is_dualspeed(cdev->gadget) && f->hs_descriptors)
1084 usb_free_descriptors(f->hs_descriptors);
1085 if (f->fs_descriptors)
1086 usb_free_descriptors(f->fs_descriptors);
1087 if (dev->notify_req)
1088 frmnet_free_req(dev->notify, dev->notify_req);
1089ep_notify_alloc_fail:
1090 dev->notify->driver_data = NULL;
1091 dev->notify = NULL;
1092ep_auto_notify_fail:
Ajay Agarwalb7f8e952017-12-27 23:25:26 +05301093 dev->bam_port.out->driver_data = NULL;
1094 dev->bam_port.out = NULL;
Chandana Kishori Chiluveruc8f81012017-11-02 16:41:20 +05301095ep_auto_out_fail:
Ajay Agarwalb7f8e952017-12-27 23:25:26 +05301096 dev->bam_port.in->driver_data = NULL;
1097 dev->bam_port.in = NULL;
Chandana Kishori Chiluveruc8f81012017-11-02 16:41:20 +05301098
1099 return status;
1100}
1101
1102static int frmnet_bind(struct usb_configuration *c, struct usb_function *f)
1103{
1104 struct f_rmnet *dev = func_to_rmnet(f);
1105 struct usb_composite_dev *cdev = c->cdev;
1106 int ret = -ENODEV;
1107 struct ipa_function_bind_info info = {0};
1108
1109 pr_debug("%s: start binding\n", __func__);
1110 dev->ifc_id = usb_interface_id(c, f);
1111 if (dev->ifc_id < 0) {
1112 pr_err("%s: unable to allocate ifc id, err:%d\n",
1113 __func__, dev->ifc_id);
1114 return dev->ifc_id;
1115 }
1116
1117 info.data_str_idx = 0;
1118 if (dev->qti_port_type == QTI_PORT_RMNET) {
1119 info.string_defs = rmnet_string_defs;
1120 info.data_desc = &rmnet_interface_desc;
1121 info.fs_in_desc = &rmnet_fs_in_desc;
1122 info.fs_out_desc = &rmnet_fs_out_desc;
1123 info.fs_notify_desc = &rmnet_fs_notify_desc;
1124 info.hs_in_desc = &rmnet_hs_in_desc;
1125 info.hs_out_desc = &rmnet_hs_out_desc;
1126 info.hs_notify_desc = &rmnet_hs_notify_desc;
1127 info.ss_in_desc = &rmnet_ss_in_desc;
1128 info.ss_out_desc = &rmnet_ss_out_desc;
1129 info.ss_notify_desc = &rmnet_ss_notify_desc;
1130 info.fs_desc_hdr = rmnet_fs_function;
1131 info.hs_desc_hdr = rmnet_hs_function;
1132 info.ss_desc_hdr = rmnet_ss_function;
1133 } else {
1134 info.string_defs = dpl_string_defs;
1135 info.data_desc = &dpl_data_intf_desc;
Pratham Pratap2f5f9832018-02-19 17:22:10 +05301136 info.fs_in_desc = &dpl_fs_data_desc;
Chandana Kishori Chiluveruc8f81012017-11-02 16:41:20 +05301137 info.hs_in_desc = &dpl_hs_data_desc;
1138 info.ss_in_desc = &dpl_ss_data_desc;
Pratham Pratap2f5f9832018-02-19 17:22:10 +05301139 info.fs_desc_hdr = dpl_fs_data_only_desc;
Chandana Kishori Chiluveruc8f81012017-11-02 16:41:20 +05301140 info.hs_desc_hdr = dpl_hs_data_only_desc;
1141 info.ss_desc_hdr = dpl_ss_data_only_desc;
1142 }
1143
1144 ret = ipa_update_function_bind_params(dev, cdev, &info);
1145
1146 return ret;
1147}
1148
1149static struct usb_function *frmnet_bind_config(struct usb_function_instance *fi)
1150{
1151 struct f_rmnet_opts *opts;
1152 struct f_rmnet *dev;
1153 struct usb_function *f;
1154
1155 opts = container_of(fi, struct f_rmnet_opts, func_inst);
1156 opts->refcnt++;
1157 dev = opts->dev;
1158 f = &dev->func;
1159 if (dev->qti_port_type == QTI_PORT_RMNET) {
1160 f->name = "rmnet";
1161 f->strings = rmnet_strings;
1162 } else {
1163 f->name = "dpl";
1164 f->strings = dpl_strings;
1165 }
1166
1167 f->bind = frmnet_bind;
1168 f->unbind = frmnet_unbind;
1169 f->disable = frmnet_disable;
1170 f->set_alt = frmnet_set_alt;
1171 f->setup = frmnet_setup;
1172 f->suspend = frmnet_suspend;
1173 f->resume = frmnet_resume;
1174 f->free_func = frmnet_free;
1175 dev->port.send_cpkt_response = frmnet_send_cpkt_response;
1176 dev->port.disconnect = frmnet_disconnect;
1177 dev->port.connect = frmnet_connect;
1178
1179 pr_debug("%s: complete\n", __func__);
1180
1181 return f;
1182}
1183
1184static int rmnet_init(void)
1185{
1186 return gqti_ctrl_init();
1187}
1188
1189static void frmnet_cleanup(void)
1190{
1191 gqti_ctrl_cleanup();
1192}
1193
1194static void rmnet_free_inst(struct usb_function_instance *f)
1195{
1196 struct f_rmnet_opts *opts = container_of(f, struct f_rmnet_opts,
1197 func_inst);
Ajay Agarwalb7f8e952017-12-27 23:25:26 +05301198 if (opts->dev->xport_type == BAM_DMUX)
1199 gbam_cleanup(opts->dev->bam_dmux_func_type);
1200 else
1201 ipa_data_free(opts->dev->ipa_func_type);
1202
Chandana Kishori Chiluveruc8f81012017-11-02 16:41:20 +05301203 kfree(opts->dev);
1204 kfree(opts);
1205}
1206
1207static int rmnet_set_inst_name(struct usb_function_instance *fi,
1208 const char *name)
1209{
1210 int name_len, ret = 0;
1211 struct f_rmnet *dev;
1212 struct f_rmnet_opts *opts = container_of(fi,
1213 struct f_rmnet_opts, func_inst);
1214
1215 name_len = strlen(name) + 1;
1216 if (name_len > MAX_INST_NAME_LEN)
1217 return -ENAMETOOLONG;
1218
1219 dev = kzalloc(sizeof(struct f_rmnet), GFP_KERNEL);
1220 if (!dev)
1221 return -ENOMEM;
1222
1223 spin_lock_init(&dev->lock);
1224 /* Update qti->qti_port_type */
1225 ret = name_to_prot(dev, name);
1226 if (ret < 0) {
1227 pr_err("%s: failed to find prot for %s instance\n",
1228 __func__, name);
1229 goto fail;
1230 }
1231
1232 if (dev->qti_port_type >= QTI_NUM_PORTS ||
Ajay Agarwalb7f8e952017-12-27 23:25:26 +05301233 dev->xport_type >= NR_XPORT_TYPES ||
1234 dev->ipa_func_type >= USB_IPA_NUM_FUNCS ||
1235 dev->bam_dmux_func_type >= BAM_DMUX_NUM_FUNCS) {
Chandana Kishori Chiluveruc8f81012017-11-02 16:41:20 +05301236 pr_err("%s: invalid prot\n", __func__);
1237 ret = -EINVAL;
1238 goto fail;
1239 }
1240
1241 INIT_LIST_HEAD(&dev->cpkt_resp_q);
Ajay Agarwalb7f8e952017-12-27 23:25:26 +05301242 if (dev->xport_type == BAM_DMUX)
1243 ret = gbam_setup(dev->bam_dmux_func_type);
1244 else
1245 ret = ipa_data_setup(dev->ipa_func_type);
1246
Chandana Kishori Chiluveruc8f81012017-11-02 16:41:20 +05301247 if (ret)
1248 goto fail;
1249
1250 opts->dev = dev;
1251 return 0;
1252
1253fail:
1254 kfree(dev);
1255 return ret;
1256}
1257
1258static inline struct f_rmnet_opts *to_f_rmnet_opts(struct config_item *item)
1259{
1260 return container_of(to_config_group(item), struct f_rmnet_opts,
1261 func_inst.group);
1262}
1263
1264static void rmnet_opts_release(struct config_item *item)
1265{
1266 struct f_rmnet_opts *opts = to_f_rmnet_opts(item);
1267
1268 usb_put_function_instance(&opts->func_inst);
1269};
1270
1271static struct configfs_item_operations rmnet_item_ops = {
1272 .release = rmnet_opts_release,
1273};
1274
1275static struct config_item_type rmnet_func_type = {
1276 .ct_item_ops = &rmnet_item_ops,
1277 .ct_owner = THIS_MODULE,
1278};
1279
1280static struct usb_function_instance *rmnet_alloc_inst(void)
1281{
1282 struct f_rmnet_opts *opts;
1283
1284 opts = kzalloc(sizeof(*opts), GFP_KERNEL);
1285 if (!opts)
1286 return ERR_PTR(-ENOMEM);
1287
1288 opts->func_inst.set_inst_name = rmnet_set_inst_name;
1289 opts->func_inst.free_func_inst = rmnet_free_inst;
1290
1291 config_group_init_type_name(&opts->func_inst.group, "",
1292 &rmnet_func_type);
1293 return &opts->func_inst;
1294}
1295
1296static struct usb_function *rmnet_alloc(struct usb_function_instance *fi)
1297{
1298 return frmnet_bind_config(fi);
1299}
1300
1301DECLARE_USB_FUNCTION(rmnet_bam, rmnet_alloc_inst, rmnet_alloc);
1302
1303static int __init usb_rmnet_init(void)
1304{
1305 int ret;
1306
1307 ret = rmnet_init();
1308 if (!ret) {
1309 ret = usb_function_register(&rmnet_bamusb_func);
1310 if (ret) {
1311 pr_err("%s: failed to register rmnet %d\n",
1312 __func__, ret);
1313 return ret;
1314 }
1315 }
1316 return ret;
1317}
1318
1319static void __exit usb_rmnet_exit(void)
1320{
1321 usb_function_unregister(&rmnet_bamusb_func);
1322 frmnet_cleanup();
1323}
1324
1325module_init(usb_rmnet_init);
1326module_exit(usb_rmnet_exit);
1327MODULE_LICENSE("GPL v2");
1328MODULE_DESCRIPTION("USB RMNET Function Driver");