11146ee4aSGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
2ad9bd58cSGreg Kroah-Hartman /* Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. */
361e12104SWon Kang 
40ec473b5SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
50ec473b5SJoe Perches 
661e12104SWon Kang #include <linux/module.h>
761e12104SWon Kang #include <linux/kernel.h>
861e12104SWon Kang #include <linux/usb.h>
961e12104SWon Kang #include <linux/sched.h>
1061e12104SWon Kang #include <linux/kthread.h>
1161e12104SWon Kang #include <linux/usb/cdc.h>
1261e12104SWon Kang #include <linux/wait.h>
1361e12104SWon Kang #include <linux/if_ether.h>
1461e12104SWon Kang #include <linux/pm_runtime.h>
1561e12104SWon Kang 
1661e12104SWon Kang #include "gdm_usb.h"
1761e12104SWon Kang #include "gdm_lte.h"
1861e12104SWon Kang #include "hci.h"
1961e12104SWon Kang #include "hci_packet.h"
2061e12104SWon Kang #include "gdm_endian.h"
2161e12104SWon Kang 
2261e12104SWon Kang #define USB_DEVICE_CDC_DATA(vid, pid) \
2335db0350SAybuke Ozdemir 	.match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
2435db0350SAybuke Ozdemir 		USB_DEVICE_ID_MATCH_INT_CLASS | \
2535db0350SAybuke Ozdemir 		USB_DEVICE_ID_MATCH_INT_SUBCLASS,\
2661e12104SWon Kang 	.idVendor = vid,\
2761e12104SWon Kang 	.idProduct = pid,\
2861e12104SWon Kang 	.bInterfaceClass = USB_CLASS_COMM,\
2961e12104SWon Kang 	.bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET
3061e12104SWon Kang 
3161e12104SWon Kang #define USB_DEVICE_MASS_DATA(vid, pid) \
3235db0350SAybuke Ozdemir 	.match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
3335db0350SAybuke Ozdemir 		USB_DEVICE_ID_MATCH_INT_INFO,\
3461e12104SWon Kang 	.idVendor = vid,\
3561e12104SWon Kang 	.idProduct = pid,\
3661e12104SWon Kang 	.bInterfaceSubClass = USB_SC_SCSI, \
3761e12104SWon Kang 	.bInterfaceClass = USB_CLASS_MASS_STORAGE,\
3861e12104SWon Kang 	.bInterfaceProtocol = USB_PR_BULK
3961e12104SWon Kang 
4061e12104SWon Kang static const struct usb_device_id id_table[] = {
4161e12104SWon Kang 	{ USB_DEVICE_CDC_DATA(VID_GCT, PID_GDM7240) }, /* GCT GDM7240 */
4261e12104SWon Kang 	{ USB_DEVICE_CDC_DATA(VID_GCT, PID_GDM7243) }, /* GCT GDM7243 */
4361e12104SWon Kang 	{ }
4461e12104SWon Kang };
4561e12104SWon Kang 
4661e12104SWon Kang MODULE_DEVICE_TABLE(usb, id_table);
4761e12104SWon Kang 
4861e12104SWon Kang static void do_tx(struct work_struct *work);
4961e12104SWon Kang static void do_rx(struct work_struct *work);
5061e12104SWon Kang 
5161e12104SWon Kang static int gdm_usb_recv(void *priv_dev,
5235db0350SAybuke Ozdemir 			int (*cb)(void *cb_data,
5335db0350SAybuke Ozdemir 				  void *data, int len, int context),
5461e12104SWon Kang 			void *cb_data,
5561e12104SWon Kang 			int context);
5661e12104SWon Kang 
request_mac_address(struct lte_udev * udev)5761e12104SWon Kang static int request_mac_address(struct lte_udev *udev)
5861e12104SWon Kang {
59*7c3a0635SAmey Narkhede 	struct hci_packet *hci;
6061e12104SWon Kang 	struct usb_device *usbdev = udev->usbdev;
6161e12104SWon Kang 	int actual;
6261e12104SWon Kang 	int ret = -1;
6361e12104SWon Kang 
64*7c3a0635SAmey Narkhede 	hci = kmalloc(struct_size(hci, data, 1), GFP_KERNEL);
65*7c3a0635SAmey Narkhede 	if (!hci)
66*7c3a0635SAmey Narkhede 		return -ENOMEM;
67*7c3a0635SAmey Narkhede 
681b5e56ecSQuytelda Kahja 	hci->cmd_evt = gdm_cpu_to_dev16(udev->gdm_ed, LTE_GET_INFORMATION);
691b5e56ecSQuytelda Kahja 	hci->len = gdm_cpu_to_dev16(udev->gdm_ed, 1);
7061e12104SWon Kang 	hci->data[0] = MAC_ADDRESS;
7161e12104SWon Kang 
72*7c3a0635SAmey Narkhede 	ret = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 2), hci, 5,
7361e12104SWon Kang 			   &actual, 1000);
7461e12104SWon Kang 
7561e12104SWon Kang 	udev->request_mac_addr = 1;
76*7c3a0635SAmey Narkhede 	kfree(hci);
7761e12104SWon Kang 
7861e12104SWon Kang 	return ret;
7961e12104SWon Kang }
8061e12104SWon Kang 
alloc_tx_struct(int len)8161e12104SWon Kang static struct usb_tx *alloc_tx_struct(int len)
8261e12104SWon Kang {
8361e12104SWon Kang 	struct usb_tx *t = NULL;
8461e12104SWon Kang 	int ret = 0;
8561e12104SWon Kang 
867b7df122SIoana Ciornei 	t = kzalloc(sizeof(*t), GFP_ATOMIC);
8761e12104SWon Kang 	if (!t) {
8861e12104SWon Kang 		ret = -ENOMEM;
8961e12104SWon Kang 		goto out;
9061e12104SWon Kang 	}
9161e12104SWon Kang 
9261e12104SWon Kang 	t->urb = usb_alloc_urb(0, GFP_ATOMIC);
9361e12104SWon Kang 	if (!(len % 512))
9461e12104SWon Kang 		len++;
9561e12104SWon Kang 
9661e12104SWon Kang 	t->buf = kmalloc(len, GFP_ATOMIC);
9761e12104SWon Kang 	if (!t->urb || !t->buf) {
9861e12104SWon Kang 		ret = -ENOMEM;
9961e12104SWon Kang 		goto out;
10061e12104SWon Kang 	}
10161e12104SWon Kang 
10261e12104SWon Kang out:
10361e12104SWon Kang 	if (ret < 0) {
10461e12104SWon Kang 		if (t) {
10561e12104SWon Kang 			usb_free_urb(t->urb);
10661e12104SWon Kang 			kfree(t->buf);
10761e12104SWon Kang 			kfree(t);
10861e12104SWon Kang 		}
10961e12104SWon Kang 		return NULL;
11061e12104SWon Kang 	}
11161e12104SWon Kang 
11261e12104SWon Kang 	return t;
11361e12104SWon Kang }
11461e12104SWon Kang 
alloc_tx_sdu_struct(void)11561e12104SWon Kang static struct usb_tx_sdu *alloc_tx_sdu_struct(void)
11661e12104SWon Kang {
11775bc5fadSDan Carpenter 	struct usb_tx_sdu *t_sdu;
11861e12104SWon Kang 
1197b7df122SIoana Ciornei 	t_sdu = kzalloc(sizeof(*t_sdu), GFP_KERNEL);
12075bc5fadSDan Carpenter 	if (!t_sdu)
12175bc5fadSDan Carpenter 		return NULL;
12261e12104SWon Kang 
12322505b25SAlexey Khoroshilov 	t_sdu->buf = kmalloc(SDU_BUF_SIZE, GFP_KERNEL);
12461e12104SWon Kang 	if (!t_sdu->buf) {
12561e12104SWon Kang 		kfree(t_sdu);
12661e12104SWon Kang 		return NULL;
12761e12104SWon Kang 	}
12861e12104SWon Kang 
12961e12104SWon Kang 	return t_sdu;
13061e12104SWon Kang }
13161e12104SWon Kang 
free_tx_struct(struct usb_tx * t)13261e12104SWon Kang static void free_tx_struct(struct usb_tx *t)
13361e12104SWon Kang {
13461e12104SWon Kang 	if (t) {
13561e12104SWon Kang 		usb_free_urb(t->urb);
13661e12104SWon Kang 		kfree(t->buf);
13761e12104SWon Kang 		kfree(t);
13861e12104SWon Kang 	}
13961e12104SWon Kang }
14061e12104SWon Kang 
free_tx_sdu_struct(struct usb_tx_sdu * t_sdu)14161e12104SWon Kang static void free_tx_sdu_struct(struct usb_tx_sdu *t_sdu)
14261e12104SWon Kang {
14361e12104SWon Kang 	if (t_sdu) {
14461e12104SWon Kang 		kfree(t_sdu->buf);
14561e12104SWon Kang 		kfree(t_sdu);
14661e12104SWon Kang 	}
14761e12104SWon Kang }
14861e12104SWon Kang 
get_tx_sdu_struct(struct tx_cxt * tx,int * no_spc)14961e12104SWon Kang static struct usb_tx_sdu *get_tx_sdu_struct(struct tx_cxt *tx, int *no_spc)
15061e12104SWon Kang {
15161e12104SWon Kang 	struct usb_tx_sdu *t_sdu;
15261e12104SWon Kang 
15361e12104SWon Kang 	if (list_empty(&tx->free_list))
15461e12104SWon Kang 		return NULL;
15561e12104SWon Kang 
15661e12104SWon Kang 	t_sdu = list_entry(tx->free_list.next, struct usb_tx_sdu, list);
15761e12104SWon Kang 	list_del(&t_sdu->list);
15861e12104SWon Kang 
15961e12104SWon Kang 	tx->avail_count--;
16061e12104SWon Kang 
16161e12104SWon Kang 	*no_spc = list_empty(&tx->free_list) ? 1 : 0;
16261e12104SWon Kang 
16361e12104SWon Kang 	return t_sdu;
16461e12104SWon Kang }
16561e12104SWon Kang 
put_tx_struct(struct tx_cxt * tx,struct usb_tx_sdu * t_sdu)16661e12104SWon Kang static void put_tx_struct(struct tx_cxt *tx, struct usb_tx_sdu *t_sdu)
16761e12104SWon Kang {
16861e12104SWon Kang 	list_add_tail(&t_sdu->list, &tx->free_list);
16961e12104SWon Kang 	tx->avail_count++;
17061e12104SWon Kang }
17161e12104SWon Kang 
alloc_rx_struct(void)17261e12104SWon Kang static struct usb_rx *alloc_rx_struct(void)
17361e12104SWon Kang {
17461e12104SWon Kang 	struct usb_rx *r = NULL;
17561e12104SWon Kang 	int ret = 0;
17661e12104SWon Kang 
1777b7df122SIoana Ciornei 	r = kmalloc(sizeof(*r), GFP_KERNEL);
17861e12104SWon Kang 	if (!r) {
17961e12104SWon Kang 		ret = -ENOMEM;
18061e12104SWon Kang 		goto out;
18161e12104SWon Kang 	}
18261e12104SWon Kang 
18322505b25SAlexey Khoroshilov 	r->urb = usb_alloc_urb(0, GFP_KERNEL);
18422505b25SAlexey Khoroshilov 	r->buf = kmalloc(RX_BUF_SIZE, GFP_KERNEL);
18561e12104SWon Kang 	if (!r->urb || !r->buf) {
18661e12104SWon Kang 		ret = -ENOMEM;
18761e12104SWon Kang 		goto out;
18861e12104SWon Kang 	}
18961e12104SWon Kang out:
19061e12104SWon Kang 
19161e12104SWon Kang 	if (ret < 0) {
19261e12104SWon Kang 		if (r) {
19361e12104SWon Kang 			usb_free_urb(r->urb);
19461e12104SWon Kang 			kfree(r->buf);
19561e12104SWon Kang 			kfree(r);
19661e12104SWon Kang 		}
19761e12104SWon Kang 		return NULL;
19861e12104SWon Kang 	}
19961e12104SWon Kang 
20061e12104SWon Kang 	return r;
20161e12104SWon Kang }
20261e12104SWon Kang 
free_rx_struct(struct usb_rx * r)20361e12104SWon Kang static void free_rx_struct(struct usb_rx *r)
20461e12104SWon Kang {
20561e12104SWon Kang 	if (r) {
20661e12104SWon Kang 		usb_free_urb(r->urb);
20761e12104SWon Kang 		kfree(r->buf);
20861e12104SWon Kang 		kfree(r);
20961e12104SWon Kang 	}
21061e12104SWon Kang }
21161e12104SWon Kang 
get_rx_struct(struct rx_cxt * rx,int * no_spc)21261e12104SWon Kang static struct usb_rx *get_rx_struct(struct rx_cxt *rx, int *no_spc)
21361e12104SWon Kang {
21461e12104SWon Kang 	struct usb_rx *r;
21561e12104SWon Kang 	unsigned long flags;
21661e12104SWon Kang 
21761e12104SWon Kang 	spin_lock_irqsave(&rx->rx_lock, flags);
21861e12104SWon Kang 
21961e12104SWon Kang 	if (list_empty(&rx->free_list)) {
22061e12104SWon Kang 		spin_unlock_irqrestore(&rx->rx_lock, flags);
22161e12104SWon Kang 		return NULL;
22261e12104SWon Kang 	}
22361e12104SWon Kang 
22461e12104SWon Kang 	r = list_entry(rx->free_list.next, struct usb_rx, free_list);
22561e12104SWon Kang 	list_del(&r->free_list);
22661e12104SWon Kang 
22761e12104SWon Kang 	rx->avail_count--;
22861e12104SWon Kang 
22961e12104SWon Kang 	*no_spc = list_empty(&rx->free_list) ? 1 : 0;
23061e12104SWon Kang 
23161e12104SWon Kang 	spin_unlock_irqrestore(&rx->rx_lock, flags);
23261e12104SWon Kang 
23361e12104SWon Kang 	return r;
23461e12104SWon Kang }
23561e12104SWon Kang 
put_rx_struct(struct rx_cxt * rx,struct usb_rx * r)23661e12104SWon Kang static void put_rx_struct(struct rx_cxt *rx, struct usb_rx *r)
23761e12104SWon Kang {
23861e12104SWon Kang 	unsigned long flags;
23961e12104SWon Kang 
24061e12104SWon Kang 	spin_lock_irqsave(&rx->rx_lock, flags);
24161e12104SWon Kang 
24261e12104SWon Kang 	list_add_tail(&r->free_list, &rx->free_list);
24361e12104SWon Kang 	rx->avail_count++;
24461e12104SWon Kang 
24561e12104SWon Kang 	spin_unlock_irqrestore(&rx->rx_lock, flags);
24661e12104SWon Kang }
24761e12104SWon Kang 
release_usb(struct lte_udev * udev)24861e12104SWon Kang static void release_usb(struct lte_udev *udev)
24961e12104SWon Kang {
25061e12104SWon Kang 	struct rx_cxt	*rx = &udev->rx;
25161e12104SWon Kang 	struct tx_cxt	*tx = &udev->tx;
25261e12104SWon Kang 	struct usb_tx	*t, *t_next;
25361e12104SWon Kang 	struct usb_rx	*r, *r_next;
25461e12104SWon Kang 	struct usb_tx_sdu	*t_sdu, *t_sdu_next;
25561e12104SWon Kang 	unsigned long flags;
25661e12104SWon Kang 
25761e12104SWon Kang 	spin_lock_irqsave(&tx->lock, flags);
258e010a2a0SCihangir Akturk 	list_for_each_entry_safe(t_sdu, t_sdu_next, &tx->sdu_list, list) {
25961e12104SWon Kang 		list_del(&t_sdu->list);
26061e12104SWon Kang 		free_tx_sdu_struct(t_sdu);
26161e12104SWon Kang 	}
26261e12104SWon Kang 
263e010a2a0SCihangir Akturk 	list_for_each_entry_safe(t, t_next, &tx->hci_list, list) {
26461e12104SWon Kang 		list_del(&t->list);
26561e12104SWon Kang 		free_tx_struct(t);
26661e12104SWon Kang 	}
26761e12104SWon Kang 
268e010a2a0SCihangir Akturk 	list_for_each_entry_safe(t_sdu, t_sdu_next, &tx->free_list, list) {
26961e12104SWon Kang 		list_del(&t_sdu->list);
27061e12104SWon Kang 		free_tx_sdu_struct(t_sdu);
27161e12104SWon Kang 	}
27261e12104SWon Kang 	spin_unlock_irqrestore(&tx->lock, flags);
27361e12104SWon Kang 
27461e12104SWon Kang 	spin_lock_irqsave(&rx->submit_lock, flags);
275e010a2a0SCihangir Akturk 	list_for_each_entry_safe(r, r_next, &rx->rx_submit_list,
276e010a2a0SCihangir Akturk 				 rx_submit_list) {
27761e12104SWon Kang 		spin_unlock_irqrestore(&rx->submit_lock, flags);
27861e12104SWon Kang 		usb_kill_urb(r->urb);
27961e12104SWon Kang 		spin_lock_irqsave(&rx->submit_lock, flags);
28061e12104SWon Kang 	}
28161e12104SWon Kang 	spin_unlock_irqrestore(&rx->submit_lock, flags);
28261e12104SWon Kang 
28361e12104SWon Kang 	spin_lock_irqsave(&rx->rx_lock, flags);
284e010a2a0SCihangir Akturk 	list_for_each_entry_safe(r, r_next, &rx->free_list, free_list) {
28561e12104SWon Kang 		list_del(&r->free_list);
28661e12104SWon Kang 		free_rx_struct(r);
28761e12104SWon Kang 	}
28861e12104SWon Kang 	spin_unlock_irqrestore(&rx->rx_lock, flags);
28961e12104SWon Kang 
29061e12104SWon Kang 	spin_lock_irqsave(&rx->to_host_lock, flags);
291e010a2a0SCihangir Akturk 	list_for_each_entry_safe(r, r_next, &rx->to_host_list, to_host_list) {
29261e12104SWon Kang 		if (r->index == (void *)udev) {
29361e12104SWon Kang 			list_del(&r->to_host_list);
29461e12104SWon Kang 			free_rx_struct(r);
29561e12104SWon Kang 		}
29661e12104SWon Kang 	}
29761e12104SWon Kang 	spin_unlock_irqrestore(&rx->to_host_lock, flags);
29861e12104SWon Kang }
29961e12104SWon Kang 
init_usb(struct lte_udev * udev)30061e12104SWon Kang static int init_usb(struct lte_udev *udev)
30161e12104SWon Kang {
30261e12104SWon Kang 	int ret = 0;
30361e12104SWon Kang 	int i;
30461e12104SWon Kang 	struct tx_cxt *tx = &udev->tx;
30561e12104SWon Kang 	struct rx_cxt *rx = &udev->rx;
30661e12104SWon Kang 	struct usb_tx_sdu *t_sdu = NULL;
30761e12104SWon Kang 	struct usb_rx *r = NULL;
30861e12104SWon Kang 
30961e12104SWon Kang 	udev->send_complete = 1;
31061e12104SWon Kang 	udev->tx_stop = 0;
31161e12104SWon Kang 	udev->request_mac_addr = 0;
31261e12104SWon Kang 	udev->usb_state = PM_NORMAL;
31361e12104SWon Kang 
31461e12104SWon Kang 	INIT_LIST_HEAD(&tx->sdu_list);
31561e12104SWon Kang 	INIT_LIST_HEAD(&tx->hci_list);
31661e12104SWon Kang 	INIT_LIST_HEAD(&tx->free_list);
31761e12104SWon Kang 	INIT_LIST_HEAD(&rx->rx_submit_list);
31861e12104SWon Kang 	INIT_LIST_HEAD(&rx->free_list);
31961e12104SWon Kang 	INIT_LIST_HEAD(&rx->to_host_list);
32061e12104SWon Kang 	spin_lock_init(&tx->lock);
32161e12104SWon Kang 	spin_lock_init(&rx->rx_lock);
32261e12104SWon Kang 	spin_lock_init(&rx->submit_lock);
32361e12104SWon Kang 	spin_lock_init(&rx->to_host_lock);
32461e12104SWon Kang 
32561e12104SWon Kang 	tx->avail_count = 0;
32661e12104SWon Kang 	rx->avail_count = 0;
32761e12104SWon Kang 
32861e12104SWon Kang 	udev->rx_cb = NULL;
32961e12104SWon Kang 
33061e12104SWon Kang 	for (i = 0; i < MAX_NUM_SDU_BUF; i++) {
33161e12104SWon Kang 		t_sdu = alloc_tx_sdu_struct();
332b6f6fd8aSIoana Ciornei 		if (!t_sdu) {
33361e12104SWon Kang 			ret = -ENOMEM;
33461e12104SWon Kang 			goto fail;
33561e12104SWon Kang 		}
33661e12104SWon Kang 
33761e12104SWon Kang 		list_add(&t_sdu->list, &tx->free_list);
33861e12104SWon Kang 		tx->avail_count++;
33961e12104SWon Kang 	}
34061e12104SWon Kang 
34161e12104SWon Kang 	for (i = 0; i < MAX_RX_SUBMIT_COUNT * 2; i++) {
34261e12104SWon Kang 		r = alloc_rx_struct();
343b6f6fd8aSIoana Ciornei 		if (!r) {
34461e12104SWon Kang 			ret = -ENOMEM;
34561e12104SWon Kang 			goto fail;
34661e12104SWon Kang 		}
34761e12104SWon Kang 
34861e12104SWon Kang 		list_add(&r->free_list, &rx->free_list);
34961e12104SWon Kang 		rx->avail_count++;
35061e12104SWon Kang 	}
35161e12104SWon Kang 	INIT_DELAYED_WORK(&udev->work_tx, do_tx);
35261e12104SWon Kang 	INIT_DELAYED_WORK(&udev->work_rx, do_rx);
35361e12104SWon Kang 	return 0;
35461e12104SWon Kang fail:
35522505b25SAlexey Khoroshilov 	release_usb(udev);
35661e12104SWon Kang 	return ret;
35761e12104SWon Kang }
35861e12104SWon Kang 
set_mac_address(u8 * data,void * arg)35961e12104SWon Kang static int set_mac_address(u8 *data, void *arg)
36061e12104SWon Kang {
3612594ca30SShraddha Barke 	struct phy_dev *phy_dev = arg;
36261e12104SWon Kang 	struct lte_udev *udev = phy_dev->priv_dev;
36361e12104SWon Kang 	struct tlv *tlv = (struct tlv *)data;
36461e12104SWon Kang 	u8 mac_address[ETH_ALEN] = {0, };
36561e12104SWon Kang 
36661e12104SWon Kang 	if (tlv->type == MAC_ADDRESS && udev->request_mac_addr) {
36761e12104SWon Kang 		memcpy(mac_address, tlv->data, tlv->len);
36861e12104SWon Kang 
36935db0350SAybuke Ozdemir 		if (register_lte_device(phy_dev,
37035db0350SAybuke Ozdemir 					&udev->intf->dev, mac_address) < 0)
3710ec473b5SJoe Perches 			pr_err("register lte device failed\n");
37261e12104SWon Kang 
37361e12104SWon Kang 		udev->request_mac_addr = 0;
37461e12104SWon Kang 
37561e12104SWon Kang 		return 1;
37661e12104SWon Kang 	}
37761e12104SWon Kang 
37861e12104SWon Kang 	return 0;
37961e12104SWon Kang }
38061e12104SWon Kang 
do_rx(struct work_struct * work)38161e12104SWon Kang static void do_rx(struct work_struct *work)
38261e12104SWon Kang {
38335db0350SAybuke Ozdemir 	struct lte_udev *udev =
38435db0350SAybuke Ozdemir 		container_of(work, struct lte_udev, work_rx.work);
38561e12104SWon Kang 	struct rx_cxt *rx = &udev->rx;
38661e12104SWon Kang 	struct usb_rx *r;
38761e12104SWon Kang 	struct hci_packet *hci;
38861e12104SWon Kang 	struct phy_dev *phy_dev;
38961e12104SWon Kang 	u16 cmd_evt;
39061e12104SWon Kang 	int ret;
39161e12104SWon Kang 	unsigned long flags;
39261e12104SWon Kang 
39361e12104SWon Kang 	while (1) {
39461e12104SWon Kang 		spin_lock_irqsave(&rx->to_host_lock, flags);
39561e12104SWon Kang 		if (list_empty(&rx->to_host_list)) {
39661e12104SWon Kang 			spin_unlock_irqrestore(&rx->to_host_lock, flags);
39761e12104SWon Kang 			break;
39861e12104SWon Kang 		}
39935db0350SAybuke Ozdemir 		r = list_entry(rx->to_host_list.next,
40035db0350SAybuke Ozdemir 			       struct usb_rx, to_host_list);
40161e12104SWon Kang 		list_del(&r->to_host_list);
40261e12104SWon Kang 		spin_unlock_irqrestore(&rx->to_host_lock, flags);
40361e12104SWon Kang 
4042594ca30SShraddha Barke 		phy_dev = r->cb_data;
4052594ca30SShraddha Barke 		udev = phy_dev->priv_dev;
40661e12104SWon Kang 		hci = (struct hci_packet *)r->buf;
4071b5e56ecSQuytelda Kahja 		cmd_evt = gdm_dev16_to_cpu(udev->gdm_ed, hci->cmd_evt);
40861e12104SWon Kang 
40961e12104SWon Kang 		switch (cmd_evt) {
41061e12104SWon Kang 		case LTE_GET_INFORMATION_RESULT:
41161e12104SWon Kang 			if (set_mac_address(hci->data, r->cb_data) == 0) {
41249bb9af0SLuis de Bethencourt 				r->callback(r->cb_data,
41361e12104SWon Kang 					    r->buf,
41461e12104SWon Kang 					    r->urb->actual_length,
41561e12104SWon Kang 					    KERNEL_THREAD);
41661e12104SWon Kang 			}
41761e12104SWon Kang 			break;
41861e12104SWon Kang 
41961e12104SWon Kang 		default:
42061e12104SWon Kang 			if (r->callback) {
42161e12104SWon Kang 				ret = r->callback(r->cb_data,
42261e12104SWon Kang 						  r->buf,
42361e12104SWon Kang 						  r->urb->actual_length,
42461e12104SWon Kang 						  KERNEL_THREAD);
42561e12104SWon Kang 
42661e12104SWon Kang 				if (ret == -EAGAIN)
4270ec473b5SJoe Perches 					pr_err("failed to send received data\n");
42861e12104SWon Kang 			}
42961e12104SWon Kang 			break;
43061e12104SWon Kang 		}
43161e12104SWon Kang 
43261e12104SWon Kang 		put_rx_struct(rx, r);
43361e12104SWon Kang 
43461e12104SWon Kang 		gdm_usb_recv(udev,
43561e12104SWon Kang 			     r->callback,
43661e12104SWon Kang 			     r->cb_data,
43761e12104SWon Kang 			     USB_COMPLETE);
43861e12104SWon Kang 	}
43961e12104SWon Kang }
44061e12104SWon Kang 
remove_rx_submit_list(struct usb_rx * r,struct rx_cxt * rx)44161e12104SWon Kang static void remove_rx_submit_list(struct usb_rx *r, struct rx_cxt *rx)
44261e12104SWon Kang {
44361e12104SWon Kang 	unsigned long flags;
44461e12104SWon Kang 	struct usb_rx	*r_remove, *r_remove_next;
44561e12104SWon Kang 
44661e12104SWon Kang 	spin_lock_irqsave(&rx->submit_lock, flags);
447e010a2a0SCihangir Akturk 	list_for_each_entry_safe(r_remove, r_remove_next,
448e010a2a0SCihangir Akturk 				 &rx->rx_submit_list, rx_submit_list) {
44961e12104SWon Kang 		if (r == r_remove) {
45061e12104SWon Kang 			list_del(&r->rx_submit_list);
45161e12104SWon Kang 			break;
45261e12104SWon Kang 		}
45361e12104SWon Kang 	}
45461e12104SWon Kang 	spin_unlock_irqrestore(&rx->submit_lock, flags);
45561e12104SWon Kang }
45661e12104SWon Kang 
gdm_usb_rcv_complete(struct urb * urb)45761e12104SWon Kang static void gdm_usb_rcv_complete(struct urb *urb)
45861e12104SWon Kang {
45961e12104SWon Kang 	struct usb_rx *r = urb->context;
46061e12104SWon Kang 	struct rx_cxt *rx = r->rx;
46161e12104SWon Kang 	unsigned long flags;
46261e12104SWon Kang 	struct lte_udev *udev = container_of(r->rx, struct lte_udev, rx);
46361e12104SWon Kang 	struct usb_device *usbdev = udev->usbdev;
46461e12104SWon Kang 
46561e12104SWon Kang 	remove_rx_submit_list(r, rx);
46661e12104SWon Kang 
46761e12104SWon Kang 	if (!urb->status && r->callback) {
46861e12104SWon Kang 		spin_lock_irqsave(&rx->to_host_lock, flags);
46961e12104SWon Kang 		list_add_tail(&r->to_host_list, &rx->to_host_list);
470bd743442SAmitoj Kaur Chawla 		schedule_work(&udev->work_rx.work);
47161e12104SWon Kang 		spin_unlock_irqrestore(&rx->to_host_lock, flags);
47261e12104SWon Kang 	} else {
47361e12104SWon Kang 		if (urb->status && udev->usb_state == PM_NORMAL)
4743d719423SHaneen Mohammed 			dev_err(&urb->dev->dev, "%s: urb status error %d\n",
4750ec473b5SJoe Perches 				__func__, urb->status);
47661e12104SWon Kang 
47761e12104SWon Kang 		put_rx_struct(rx, r);
47861e12104SWon Kang 	}
47961e12104SWon Kang 
48061e12104SWon Kang 	usb_mark_last_busy(usbdev);
48161e12104SWon Kang }
48261e12104SWon Kang 
gdm_usb_recv(void * priv_dev,int (* cb)(void * cb_data,void * data,int len,int context),void * cb_data,int context)48361e12104SWon Kang static int gdm_usb_recv(void *priv_dev,
48435db0350SAybuke Ozdemir 			int (*cb)(void *cb_data,
48535db0350SAybuke Ozdemir 				  void *data, int len, int context),
48661e12104SWon Kang 			void *cb_data,
48761e12104SWon Kang 			int context)
48861e12104SWon Kang {
48961e12104SWon Kang 	struct lte_udev *udev = priv_dev;
49061e12104SWon Kang 	struct usb_device *usbdev = udev->usbdev;
49161e12104SWon Kang 	struct rx_cxt *rx = &udev->rx;
49261e12104SWon Kang 	struct usb_rx *r;
49361e12104SWon Kang 	int no_spc;
49461e12104SWon Kang 	int ret;
49561e12104SWon Kang 	unsigned long flags;
49661e12104SWon Kang 
49761e12104SWon Kang 	if (!udev->usbdev) {
4980ec473b5SJoe Perches 		pr_err("invalid device\n");
49961e12104SWon Kang 		return -ENODEV;
50061e12104SWon Kang 	}
50161e12104SWon Kang 
50261e12104SWon Kang 	r = get_rx_struct(rx, &no_spc);
50361e12104SWon Kang 	if (!r) {
5040ec473b5SJoe Perches 		pr_err("Out of Memory\n");
50561e12104SWon Kang 		return -ENOMEM;
50661e12104SWon Kang 	}
50761e12104SWon Kang 
50861e12104SWon Kang 	udev->rx_cb = cb;
50961e12104SWon Kang 	r->callback = cb;
51061e12104SWon Kang 	r->cb_data = cb_data;
51161e12104SWon Kang 	r->index = (void *)udev;
51261e12104SWon Kang 	r->rx = rx;
51361e12104SWon Kang 
51461e12104SWon Kang 	usb_fill_bulk_urb(r->urb,
51561e12104SWon Kang 			  usbdev,
51661e12104SWon Kang 			  usb_rcvbulkpipe(usbdev, 0x83),
51761e12104SWon Kang 			  r->buf,
51861e12104SWon Kang 			  RX_BUF_SIZE,
51961e12104SWon Kang 			  gdm_usb_rcv_complete,
52061e12104SWon Kang 			  r);
52161e12104SWon Kang 
52261e12104SWon Kang 	spin_lock_irqsave(&rx->submit_lock, flags);
52361e12104SWon Kang 	list_add_tail(&r->rx_submit_list, &rx->rx_submit_list);
52461e12104SWon Kang 	spin_unlock_irqrestore(&rx->submit_lock, flags);
52561e12104SWon Kang 
52661e12104SWon Kang 	if (context == KERNEL_THREAD)
52761e12104SWon Kang 		ret = usb_submit_urb(r->urb, GFP_KERNEL);
52861e12104SWon Kang 	else
52961e12104SWon Kang 		ret = usb_submit_urb(r->urb, GFP_ATOMIC);
53061e12104SWon Kang 
53161e12104SWon Kang 	if (ret) {
53261e12104SWon Kang 		spin_lock_irqsave(&rx->submit_lock, flags);
53361e12104SWon Kang 		list_del(&r->rx_submit_list);
53461e12104SWon Kang 		spin_unlock_irqrestore(&rx->submit_lock, flags);
53561e12104SWon Kang 
5360ec473b5SJoe Perches 		pr_err("usb_submit_urb failed (%p)\n", r);
53761e12104SWon Kang 		put_rx_struct(rx, r);
53861e12104SWon Kang 	}
53961e12104SWon Kang 
54061e12104SWon Kang 	return ret;
54161e12104SWon Kang }
54261e12104SWon Kang 
gdm_usb_send_complete(struct urb * urb)54361e12104SWon Kang static void gdm_usb_send_complete(struct urb *urb)
54461e12104SWon Kang {
54561e12104SWon Kang 	struct usb_tx *t = urb->context;
54661e12104SWon Kang 	struct tx_cxt *tx = t->tx;
54761e12104SWon Kang 	struct lte_udev *udev = container_of(tx, struct lte_udev, tx);
54861e12104SWon Kang 	unsigned long flags;
54961e12104SWon Kang 
55061e12104SWon Kang 	if (urb->status == -ECONNRESET) {
5513d719423SHaneen Mohammed 		dev_info(&urb->dev->dev, "CONNRESET\n");
55261e12104SWon Kang 		return;
55361e12104SWon Kang 	}
55461e12104SWon Kang 
55561e12104SWon Kang 	if (t->callback)
55661e12104SWon Kang 		t->callback(t->cb_data);
55761e12104SWon Kang 
55861e12104SWon Kang 	free_tx_struct(t);
55961e12104SWon Kang 
56061e12104SWon Kang 	spin_lock_irqsave(&tx->lock, flags);
56161e12104SWon Kang 	udev->send_complete = 1;
562bd743442SAmitoj Kaur Chawla 	schedule_work(&udev->work_tx.work);
56361e12104SWon Kang 	spin_unlock_irqrestore(&tx->lock, flags);
56461e12104SWon Kang }
56561e12104SWon Kang 
send_tx_packet(struct usb_device * usbdev,struct usb_tx * t,u32 len)56661e12104SWon Kang static int send_tx_packet(struct usb_device *usbdev, struct usb_tx *t, u32 len)
56761e12104SWon Kang {
56861e12104SWon Kang 	int ret = 0;
56961e12104SWon Kang 
57061e12104SWon Kang 	if (!(len % 512))
57161e12104SWon Kang 		len++;
57261e12104SWon Kang 
57361e12104SWon Kang 	usb_fill_bulk_urb(t->urb,
57461e12104SWon Kang 			  usbdev,
57561e12104SWon Kang 			  usb_sndbulkpipe(usbdev, 2),
57661e12104SWon Kang 			  t->buf,
57761e12104SWon Kang 			  len,
57861e12104SWon Kang 			  gdm_usb_send_complete,
57961e12104SWon Kang 			  t);
58061e12104SWon Kang 
58161e12104SWon Kang 	ret = usb_submit_urb(t->urb, GFP_ATOMIC);
58261e12104SWon Kang 
58361e12104SWon Kang 	if (ret)
5843d719423SHaneen Mohammed 		dev_err(&usbdev->dev, "usb_submit_urb failed: %d\n",
5853d719423SHaneen Mohammed 			ret);
58661e12104SWon Kang 
58761e12104SWon Kang 	usb_mark_last_busy(usbdev);
58861e12104SWon Kang 
58961e12104SWon Kang 	return ret;
59061e12104SWon Kang }
59161e12104SWon Kang 
packet_aggregation(struct lte_udev * udev,u8 * send_buf)59261e12104SWon Kang static u32 packet_aggregation(struct lte_udev *udev, u8 *send_buf)
59361e12104SWon Kang {
59461e12104SWon Kang 	struct tx_cxt *tx = &udev->tx;
59561e12104SWon Kang 	struct usb_tx_sdu *t_sdu = NULL;
59661e12104SWon Kang 	struct multi_sdu *multi_sdu = (struct multi_sdu *)send_buf;
59761e12104SWon Kang 	u16 send_len = 0;
59861e12104SWon Kang 	u16 num_packet = 0;
59961e12104SWon Kang 	unsigned long flags;
60061e12104SWon Kang 
6011b5e56ecSQuytelda Kahja 	multi_sdu->cmd_evt = gdm_cpu_to_dev16(udev->gdm_ed, LTE_TX_MULTI_SDU);
60261e12104SWon Kang 
60361e12104SWon Kang 	while (num_packet < MAX_PACKET_IN_MULTI_SDU) {
60461e12104SWon Kang 		spin_lock_irqsave(&tx->lock, flags);
60561e12104SWon Kang 		if (list_empty(&tx->sdu_list)) {
60661e12104SWon Kang 			spin_unlock_irqrestore(&tx->lock, flags);
60761e12104SWon Kang 			break;
60861e12104SWon Kang 		}
60961e12104SWon Kang 
61061e12104SWon Kang 		t_sdu = list_entry(tx->sdu_list.next, struct usb_tx_sdu, list);
61161e12104SWon Kang 		if (send_len + t_sdu->len > MAX_SDU_SIZE) {
61261e12104SWon Kang 			spin_unlock_irqrestore(&tx->lock, flags);
61361e12104SWon Kang 			break;
61461e12104SWon Kang 		}
61561e12104SWon Kang 
61661e12104SWon Kang 		list_del(&t_sdu->list);
61761e12104SWon Kang 		spin_unlock_irqrestore(&tx->lock, flags);
61861e12104SWon Kang 
61961e12104SWon Kang 		memcpy(multi_sdu->data + send_len, t_sdu->buf, t_sdu->len);
62061e12104SWon Kang 
62161e12104SWon Kang 		send_len += (t_sdu->len + 3) & 0xfffc;
62261e12104SWon Kang 		num_packet++;
62361e12104SWon Kang 
62461e12104SWon Kang 		if (tx->avail_count > 10)
62561e12104SWon Kang 			t_sdu->callback(t_sdu->cb_data);
62661e12104SWon Kang 
62761e12104SWon Kang 		spin_lock_irqsave(&tx->lock, flags);
62861e12104SWon Kang 		put_tx_struct(tx, t_sdu);
62961e12104SWon Kang 		spin_unlock_irqrestore(&tx->lock, flags);
63061e12104SWon Kang 	}
63161e12104SWon Kang 
6321b5e56ecSQuytelda Kahja 	multi_sdu->len = gdm_cpu_to_dev16(udev->gdm_ed, send_len);
6331b5e56ecSQuytelda Kahja 	multi_sdu->num_packet = gdm_cpu_to_dev16(udev->gdm_ed, num_packet);
63461e12104SWon Kang 
63561e12104SWon Kang 	return send_len + offsetof(struct multi_sdu, data);
63661e12104SWon Kang }
63761e12104SWon Kang 
do_tx(struct work_struct * work)63861e12104SWon Kang static void do_tx(struct work_struct *work)
63961e12104SWon Kang {
64035db0350SAybuke Ozdemir 	struct lte_udev *udev =
64135db0350SAybuke Ozdemir 		container_of(work, struct lte_udev, work_tx.work);
64261e12104SWon Kang 	struct usb_device *usbdev = udev->usbdev;
64361e12104SWon Kang 	struct tx_cxt *tx = &udev->tx;
64461e12104SWon Kang 	struct usb_tx *t = NULL;
64561e12104SWon Kang 	int is_send = 0;
64661e12104SWon Kang 	u32 len = 0;
64761e12104SWon Kang 	unsigned long flags;
64861e12104SWon Kang 
64961e12104SWon Kang 	if (!usb_autopm_get_interface(udev->intf))
65061e12104SWon Kang 		usb_autopm_put_interface(udev->intf);
65161e12104SWon Kang 
65261e12104SWon Kang 	if (udev->usb_state == PM_SUSPEND)
65361e12104SWon Kang 		return;
65461e12104SWon Kang 
65561e12104SWon Kang 	spin_lock_irqsave(&tx->lock, flags);
65661e12104SWon Kang 	if (!udev->send_complete) {
65761e12104SWon Kang 		spin_unlock_irqrestore(&tx->lock, flags);
65861e12104SWon Kang 		return;
65961e12104SWon Kang 	}
660d1fed028SGulsah Kose 	udev->send_complete = 0;
66161e12104SWon Kang 
66261e12104SWon Kang 	if (!list_empty(&tx->hci_list)) {
66361e12104SWon Kang 		t = list_entry(tx->hci_list.next, struct usb_tx, list);
66461e12104SWon Kang 		list_del(&t->list);
66561e12104SWon Kang 		len = t->len;
66661e12104SWon Kang 		t->is_sdu = 0;
66761e12104SWon Kang 		is_send = 1;
66861e12104SWon Kang 	} else if (!list_empty(&tx->sdu_list)) {
66961e12104SWon Kang 		if (udev->tx_stop) {
67061e12104SWon Kang 			udev->send_complete = 1;
67161e12104SWon Kang 			spin_unlock_irqrestore(&tx->lock, flags);
67261e12104SWon Kang 			return;
67361e12104SWon Kang 		}
67461e12104SWon Kang 
67561e12104SWon Kang 		t = alloc_tx_struct(TX_BUF_SIZE);
676b6f6fd8aSIoana Ciornei 		if (!t) {
677a600f458SAbel Moyo 			spin_unlock_irqrestore(&tx->lock, flags);
678a600f458SAbel Moyo 			return;
679a600f458SAbel Moyo 		}
68061e12104SWon Kang 		t->callback = NULL;
68161e12104SWon Kang 		t->tx = tx;
68261e12104SWon Kang 		t->is_sdu = 1;
68361e12104SWon Kang 		is_send = 1;
68461e12104SWon Kang 	}
68561e12104SWon Kang 
68661e12104SWon Kang 	if (!is_send) {
68761e12104SWon Kang 		udev->send_complete = 1;
68861e12104SWon Kang 		spin_unlock_irqrestore(&tx->lock, flags);
68961e12104SWon Kang 		return;
69061e12104SWon Kang 	}
69161e12104SWon Kang 	spin_unlock_irqrestore(&tx->lock, flags);
69261e12104SWon Kang 
69361e12104SWon Kang 	if (t->is_sdu)
69461e12104SWon Kang 		len = packet_aggregation(udev, t->buf);
69561e12104SWon Kang 
69661e12104SWon Kang 	if (send_tx_packet(usbdev, t, len)) {
6970ec473b5SJoe Perches 		pr_err("send_tx_packet failed\n");
69861e12104SWon Kang 		t->callback = NULL;
69961e12104SWon Kang 		gdm_usb_send_complete(t->urb);
70061e12104SWon Kang 	}
70161e12104SWon Kang }
70261e12104SWon Kang 
70361e12104SWon Kang #define SDU_PARAM_LEN 12
gdm_usb_sdu_send(void * priv_dev,void * data,int len,unsigned int dft_eps_ID,unsigned int eps_ID,void (* cb)(void * data),void * cb_data,int dev_idx,int nic_type)70461e12104SWon Kang static int gdm_usb_sdu_send(void *priv_dev, void *data, int len,
7053cbe6a1cSBruno Carvalho 			    unsigned int dft_eps_ID, unsigned int eps_ID,
70661e12104SWon Kang 			    void (*cb)(void *data), void *cb_data,
70761e12104SWon Kang 			    int dev_idx, int nic_type)
70861e12104SWon Kang {
70961e12104SWon Kang 	struct lte_udev *udev = priv_dev;
71061e12104SWon Kang 	struct tx_cxt *tx = &udev->tx;
71161e12104SWon Kang 	struct usb_tx_sdu *t_sdu;
71261e12104SWon Kang 	struct sdu *sdu = NULL;
71361e12104SWon Kang 	unsigned long flags;
71461e12104SWon Kang 	int no_spc = 0;
71561e12104SWon Kang 	u16 send_len;
71661e12104SWon Kang 
71761e12104SWon Kang 	if (!udev->usbdev) {
7180ec473b5SJoe Perches 		pr_err("sdu send - invalid device\n");
71961e12104SWon Kang 		return TX_NO_DEV;
72061e12104SWon Kang 	}
72161e12104SWon Kang 
72261e12104SWon Kang 	spin_lock_irqsave(&tx->lock, flags);
72361e12104SWon Kang 	t_sdu = get_tx_sdu_struct(tx, &no_spc);
72461e12104SWon Kang 	spin_unlock_irqrestore(&tx->lock, flags);
72561e12104SWon Kang 
726b6f6fd8aSIoana Ciornei 	if (!t_sdu) {
7270ec473b5SJoe Perches 		pr_err("sdu send - free list empty\n");
72861e12104SWon Kang 		return TX_NO_SPC;
72961e12104SWon Kang 	}
73061e12104SWon Kang 
73161e12104SWon Kang 	sdu = (struct sdu *)t_sdu->buf;
7321b5e56ecSQuytelda Kahja 	sdu->cmd_evt = gdm_cpu_to_dev16(udev->gdm_ed, LTE_TX_SDU);
73361e12104SWon Kang 	if (nic_type == NIC_TYPE_ARP) {
73461e12104SWon Kang 		send_len = len + SDU_PARAM_LEN;
73561e12104SWon Kang 		memcpy(sdu->data, data, len);
73661e12104SWon Kang 	} else {
73761e12104SWon Kang 		send_len = len - ETH_HLEN;
73861e12104SWon Kang 		send_len += SDU_PARAM_LEN;
73961e12104SWon Kang 		memcpy(sdu->data, data + ETH_HLEN, len - ETH_HLEN);
74061e12104SWon Kang 	}
74161e12104SWon Kang 
7421b5e56ecSQuytelda Kahja 	sdu->len = gdm_cpu_to_dev16(udev->gdm_ed, send_len);
7431b5e56ecSQuytelda Kahja 	sdu->dft_eps_ID = gdm_cpu_to_dev32(udev->gdm_ed, dft_eps_ID);
7441b5e56ecSQuytelda Kahja 	sdu->bearer_ID = gdm_cpu_to_dev32(udev->gdm_ed, eps_ID);
7451b5e56ecSQuytelda Kahja 	sdu->nic_type = gdm_cpu_to_dev32(udev->gdm_ed, nic_type);
74661e12104SWon Kang 
74761e12104SWon Kang 	t_sdu->len = send_len + HCI_HEADER_SIZE;
74861e12104SWon Kang 	t_sdu->callback = cb;
74961e12104SWon Kang 	t_sdu->cb_data = cb_data;
75061e12104SWon Kang 
75161e12104SWon Kang 	spin_lock_irqsave(&tx->lock, flags);
75261e12104SWon Kang 	list_add_tail(&t_sdu->list, &tx->sdu_list);
753bd743442SAmitoj Kaur Chawla 	schedule_work(&udev->work_tx.work);
75461e12104SWon Kang 	spin_unlock_irqrestore(&tx->lock, flags);
75561e12104SWon Kang 
75661e12104SWon Kang 	if (no_spc)
75761e12104SWon Kang 		return TX_NO_BUFFER;
75861e12104SWon Kang 
75961e12104SWon Kang 	return 0;
76061e12104SWon Kang }
76161e12104SWon Kang 
gdm_usb_hci_send(void * priv_dev,void * data,int len,void (* cb)(void * data),void * cb_data)76261e12104SWon Kang static int gdm_usb_hci_send(void *priv_dev, void *data, int len,
76361e12104SWon Kang 			    void (*cb)(void *data), void *cb_data)
76461e12104SWon Kang {
76561e12104SWon Kang 	struct lte_udev *udev = priv_dev;
76661e12104SWon Kang 	struct tx_cxt *tx = &udev->tx;
76761e12104SWon Kang 	struct usb_tx *t;
76861e12104SWon Kang 	unsigned long flags;
76961e12104SWon Kang 
77061e12104SWon Kang 	if (!udev->usbdev) {
7710ec473b5SJoe Perches 		pr_err("hci send - invalid device\n");
77261e12104SWon Kang 		return -ENODEV;
77361e12104SWon Kang 	}
77461e12104SWon Kang 
77561e12104SWon Kang 	t = alloc_tx_struct(len);
776b6f6fd8aSIoana Ciornei 	if (!t) {
7770ec473b5SJoe Perches 		pr_err("hci_send - out of memory\n");
77861e12104SWon Kang 		return -ENOMEM;
77961e12104SWon Kang 	}
78061e12104SWon Kang 
78161e12104SWon Kang 	memcpy(t->buf, data, len);
78261e12104SWon Kang 	t->callback = cb;
78361e12104SWon Kang 	t->cb_data = cb_data;
78461e12104SWon Kang 	t->len = len;
78561e12104SWon Kang 	t->tx = tx;
78661e12104SWon Kang 	t->is_sdu = 0;
78761e12104SWon Kang 
78861e12104SWon Kang 	spin_lock_irqsave(&tx->lock, flags);
78961e12104SWon Kang 	list_add_tail(&t->list, &tx->hci_list);
790bd743442SAmitoj Kaur Chawla 	schedule_work(&udev->work_tx.work);
79161e12104SWon Kang 	spin_unlock_irqrestore(&tx->lock, flags);
79261e12104SWon Kang 
79361e12104SWon Kang 	return 0;
79461e12104SWon Kang }
79561e12104SWon Kang 
gdm_usb_get_endian(void * priv_dev)7961b5e56ecSQuytelda Kahja static u8 gdm_usb_get_endian(void *priv_dev)
79761e12104SWon Kang {
79861e12104SWon Kang 	struct lte_udev *udev = priv_dev;
79961e12104SWon Kang 
8001b5e56ecSQuytelda Kahja 	return udev->gdm_ed;
80161e12104SWon Kang }
80261e12104SWon Kang 
gdm_usb_probe(struct usb_interface * intf,const struct usb_device_id * id)80335db0350SAybuke Ozdemir static int gdm_usb_probe(struct usb_interface *intf,
80435db0350SAybuke Ozdemir 			 const struct usb_device_id *id)
80561e12104SWon Kang {
80661e12104SWon Kang 	int ret = 0;
80761e12104SWon Kang 	struct phy_dev *phy_dev = NULL;
80861e12104SWon Kang 	struct lte_udev *udev = NULL;
80961e12104SWon Kang 	u16 idVendor, idProduct;
81061e12104SWon Kang 	int bInterfaceNumber;
81161e12104SWon Kang 	struct usb_device *usbdev = interface_to_usbdev(intf);
81261e12104SWon Kang 
81361e12104SWon Kang 	bInterfaceNumber = intf->cur_altsetting->desc.bInterfaceNumber;
81461e12104SWon Kang 	idVendor = __le16_to_cpu(usbdev->descriptor.idVendor);
81561e12104SWon Kang 	idProduct = __le16_to_cpu(usbdev->descriptor.idProduct);
81661e12104SWon Kang 
8170ec473b5SJoe Perches 	pr_info("net vid = 0x%04x pid = 0x%04x\n", idVendor, idProduct);
81861e12104SWon Kang 
81961e12104SWon Kang 	if (bInterfaceNumber > NETWORK_INTERFACE) {
8200ec473b5SJoe Perches 		pr_info("not a network device\n");
821a34c72b3SAlexey Khoroshilov 		return -ENODEV;
82261e12104SWon Kang 	}
82361e12104SWon Kang 
8247b7df122SIoana Ciornei 	phy_dev = kzalloc(sizeof(*phy_dev), GFP_KERNEL);
825a34c72b3SAlexey Khoroshilov 	if (!phy_dev)
826a34c72b3SAlexey Khoroshilov 		return -ENOMEM;
82761e12104SWon Kang 
8287b7df122SIoana Ciornei 	udev = kzalloc(sizeof(*udev), GFP_KERNEL);
82961e12104SWon Kang 	if (!udev) {
83061e12104SWon Kang 		ret = -ENOMEM;
831a34c72b3SAlexey Khoroshilov 		goto err_udev;
83261e12104SWon Kang 	}
83361e12104SWon Kang 
83461e12104SWon Kang 	phy_dev->priv_dev = (void *)udev;
83561e12104SWon Kang 	phy_dev->send_hci_func = gdm_usb_hci_send;
83661e12104SWon Kang 	phy_dev->send_sdu_func = gdm_usb_sdu_send;
83761e12104SWon Kang 	phy_dev->rcv_func = gdm_usb_recv;
83861e12104SWon Kang 	phy_dev->get_endian = gdm_usb_get_endian;
83961e12104SWon Kang 
84061e12104SWon Kang 	udev->usbdev = usbdev;
84161e12104SWon Kang 	ret = init_usb(udev);
84261e12104SWon Kang 	if (ret < 0) {
843df02b50aSHaneen Mohammed 		dev_err(intf->usb_dev, "init_usb func failed\n");
844a34c72b3SAlexey Khoroshilov 		goto err_init_usb;
84561e12104SWon Kang 	}
84661e12104SWon Kang 	udev->intf = intf;
84761e12104SWon Kang 
84861e12104SWon Kang 	intf->needs_remote_wakeup = 1;
84961e12104SWon Kang 	usb_enable_autosuspend(usbdev);
85061e12104SWon Kang 	pm_runtime_set_autosuspend_delay(&usbdev->dev, AUTO_SUSPEND_TIMER);
85161e12104SWon Kang 
85235db0350SAybuke Ozdemir 	/* List up hosts with big endians, otherwise,
85335db0350SAybuke Ozdemir 	 * defaults to little endian
85435db0350SAybuke Ozdemir 	 */
85561e12104SWon Kang 	if (idProduct == PID_GDM7243)
8561b5e56ecSQuytelda Kahja 		udev->gdm_ed = ENDIANNESS_BIG;
85761e12104SWon Kang 	else
8581b5e56ecSQuytelda Kahja 		udev->gdm_ed = ENDIANNESS_LITTLE;
85961e12104SWon Kang 
86061e12104SWon Kang 	ret = request_mac_address(udev);
86161e12104SWon Kang 	if (ret < 0) {
862df02b50aSHaneen Mohammed 		dev_err(intf->usb_dev, "request Mac address failed\n");
863a34c72b3SAlexey Khoroshilov 		goto err_mac_address;
86461e12104SWon Kang 	}
86561e12104SWon Kang 
86661e12104SWon Kang 	start_rx_proc(phy_dev);
86761e12104SWon Kang 	usb_get_dev(usbdev);
86861e12104SWon Kang 	usb_set_intfdata(intf, phy_dev);
86961e12104SWon Kang 
870a34c72b3SAlexey Khoroshilov 	return 0;
871a34c72b3SAlexey Khoroshilov 
872a34c72b3SAlexey Khoroshilov err_mac_address:
873a34c72b3SAlexey Khoroshilov 	release_usb(udev);
874a34c72b3SAlexey Khoroshilov err_init_usb:
875a34c72b3SAlexey Khoroshilov 	kfree(udev);
876a34c72b3SAlexey Khoroshilov err_udev:
877a34c72b3SAlexey Khoroshilov 	kfree(phy_dev);
878a34c72b3SAlexey Khoroshilov 
87961e12104SWon Kang 	return ret;
88061e12104SWon Kang }
88161e12104SWon Kang 
gdm_usb_disconnect(struct usb_interface * intf)88261e12104SWon Kang static void gdm_usb_disconnect(struct usb_interface *intf)
88361e12104SWon Kang {
88461e12104SWon Kang 	struct phy_dev *phy_dev;
88561e12104SWon Kang 	struct lte_udev *udev;
88661e12104SWon Kang 	struct usb_device *usbdev;
887aa920159SKiran Padwal 
88861e12104SWon Kang 	usbdev = interface_to_usbdev(intf);
88961e12104SWon Kang 	phy_dev = usb_get_intfdata(intf);
89061e12104SWon Kang 
89161e12104SWon Kang 	udev = phy_dev->priv_dev;
89261e12104SWon Kang 	unregister_lte_device(phy_dev);
89361e12104SWon Kang 
89461e12104SWon Kang 	release_usb(udev);
89561e12104SWon Kang 
89661e12104SWon Kang 	kfree(udev);
89761e12104SWon Kang 	udev = NULL;
89861e12104SWon Kang 
89961e12104SWon Kang 	kfree(phy_dev);
90061e12104SWon Kang 	phy_dev = NULL;
90161e12104SWon Kang 
90261e12104SWon Kang 	usb_put_dev(usbdev);
90361e12104SWon Kang }
90461e12104SWon Kang 
gdm_usb_suspend(struct usb_interface * intf,pm_message_t pm_msg)90561e12104SWon Kang static int gdm_usb_suspend(struct usb_interface *intf, pm_message_t pm_msg)
90661e12104SWon Kang {
90761e12104SWon Kang 	struct phy_dev *phy_dev;
90861e12104SWon Kang 	struct lte_udev *udev;
90961e12104SWon Kang 	struct rx_cxt *rx;
91061e12104SWon Kang 	struct usb_rx *r;
91161e12104SWon Kang 	struct usb_rx *r_next;
91261e12104SWon Kang 	unsigned long flags;
91361e12104SWon Kang 
91461e12104SWon Kang 	phy_dev = usb_get_intfdata(intf);
91561e12104SWon Kang 	udev = phy_dev->priv_dev;
91661e12104SWon Kang 	rx = &udev->rx;
91761e12104SWon Kang 	if (udev->usb_state != PM_NORMAL) {
918df02b50aSHaneen Mohammed 		dev_err(intf->usb_dev, "usb suspend - invalid state\n");
91961e12104SWon Kang 		return -1;
92061e12104SWon Kang 	}
92161e12104SWon Kang 
92261e12104SWon Kang 	udev->usb_state = PM_SUSPEND;
92361e12104SWon Kang 
92461e12104SWon Kang 	spin_lock_irqsave(&rx->submit_lock, flags);
925e010a2a0SCihangir Akturk 	list_for_each_entry_safe(r, r_next, &rx->rx_submit_list,
926e010a2a0SCihangir Akturk 				 rx_submit_list) {
92761e12104SWon Kang 		spin_unlock_irqrestore(&rx->submit_lock, flags);
92861e12104SWon Kang 		usb_kill_urb(r->urb);
92961e12104SWon Kang 		spin_lock_irqsave(&rx->submit_lock, flags);
93061e12104SWon Kang 	}
93161e12104SWon Kang 	spin_unlock_irqrestore(&rx->submit_lock, flags);
93261e12104SWon Kang 
933bd743442SAmitoj Kaur Chawla 	cancel_work_sync(&udev->work_tx.work);
934bd743442SAmitoj Kaur Chawla 	cancel_work_sync(&udev->work_rx.work);
935bd743442SAmitoj Kaur Chawla 
93661e12104SWon Kang 	return 0;
93761e12104SWon Kang }
93861e12104SWon Kang 
gdm_usb_resume(struct usb_interface * intf)93961e12104SWon Kang static int gdm_usb_resume(struct usb_interface *intf)
94061e12104SWon Kang {
94161e12104SWon Kang 	struct phy_dev *phy_dev;
94261e12104SWon Kang 	struct lte_udev *udev;
94361e12104SWon Kang 	struct tx_cxt *tx;
94461e12104SWon Kang 	struct rx_cxt *rx;
94561e12104SWon Kang 	unsigned long flags;
94661e12104SWon Kang 	int issue_count;
94761e12104SWon Kang 	int i;
94861e12104SWon Kang 
94961e12104SWon Kang 	phy_dev = usb_get_intfdata(intf);
95061e12104SWon Kang 	udev = phy_dev->priv_dev;
95161e12104SWon Kang 	rx = &udev->rx;
95261e12104SWon Kang 
95361e12104SWon Kang 	if (udev->usb_state != PM_SUSPEND) {
954df02b50aSHaneen Mohammed 		dev_err(intf->usb_dev, "usb resume - invalid state\n");
95561e12104SWon Kang 		return -1;
95661e12104SWon Kang 	}
95761e12104SWon Kang 	udev->usb_state = PM_NORMAL;
95861e12104SWon Kang 
95961e12104SWon Kang 	spin_lock_irqsave(&rx->rx_lock, flags);
96061e12104SWon Kang 	issue_count = rx->avail_count - MAX_RX_SUBMIT_COUNT;
96161e12104SWon Kang 	spin_unlock_irqrestore(&rx->rx_lock, flags);
96261e12104SWon Kang 
96361e12104SWon Kang 	if (issue_count >= 0) {
96461e12104SWon Kang 		for (i = 0; i < issue_count; i++)
96561e12104SWon Kang 			gdm_usb_recv(phy_dev->priv_dev,
96661e12104SWon Kang 				     udev->rx_cb,
96761e12104SWon Kang 				     phy_dev,
96861e12104SWon Kang 				     USB_COMPLETE);
96961e12104SWon Kang 	}
97061e12104SWon Kang 
97161e12104SWon Kang 	tx = &udev->tx;
97261e12104SWon Kang 	spin_lock_irqsave(&tx->lock, flags);
973bd743442SAmitoj Kaur Chawla 	schedule_work(&udev->work_tx.work);
97461e12104SWon Kang 	spin_unlock_irqrestore(&tx->lock, flags);
97561e12104SWon Kang 
97661e12104SWon Kang 	return 0;
97761e12104SWon Kang }
97861e12104SWon Kang 
97961e12104SWon Kang static struct usb_driver gdm_usb_lte_driver = {
98061e12104SWon Kang 	.name = "gdm_lte",
98161e12104SWon Kang 	.probe = gdm_usb_probe,
98261e12104SWon Kang 	.disconnect = gdm_usb_disconnect,
98361e12104SWon Kang 	.id_table = id_table,
98461e12104SWon Kang 	.supports_autosuspend = 1,
98561e12104SWon Kang 	.suspend = gdm_usb_suspend,
98661e12104SWon Kang 	.resume = gdm_usb_resume,
98761e12104SWon Kang 	.reset_resume = gdm_usb_resume,
98861e12104SWon Kang };
98961e12104SWon Kang 
gdm_usb_lte_init(void)99061e12104SWon Kang static int __init gdm_usb_lte_init(void)
99161e12104SWon Kang {
99261e12104SWon Kang 	if (gdm_lte_event_init() < 0) {
9930ec473b5SJoe Perches 		pr_err("error creating event\n");
99461e12104SWon Kang 		return -1;
99561e12104SWon Kang 	}
99661e12104SWon Kang 
99761e12104SWon Kang 	return usb_register(&gdm_usb_lte_driver);
99861e12104SWon Kang }
99961e12104SWon Kang 
gdm_usb_lte_exit(void)100061e12104SWon Kang static void __exit gdm_usb_lte_exit(void)
100161e12104SWon Kang {
100261e12104SWon Kang 	gdm_lte_event_exit();
100361e12104SWon Kang 
100461e12104SWon Kang 	usb_deregister(&gdm_usb_lte_driver);
100561e12104SWon Kang }
100661e12104SWon Kang 
100761e12104SWon Kang module_init(gdm_usb_lte_init);
100861e12104SWon Kang module_exit(gdm_usb_lte_exit);
100961e12104SWon Kang 
101061e12104SWon Kang MODULE_VERSION(DRIVER_VERSION);
101161e12104SWon Kang MODULE_DESCRIPTION("GCT LTE USB Device Driver");
101261e12104SWon Kang MODULE_LICENSE("GPL");
1013