Merge tag 'pci-v5.18-changes-2' of git://git.kernel.org/pub/scm/linux/kernel/git...
[sfrench/cifs-2.6.git] / drivers / staging / r8188eu / os_dep / usb_ops_linux.c
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2007 - 2012 Realtek Corporation. */
3
4 #define _USB_OPS_LINUX_C_
5
6 #include "../include/drv_types.h"
7 #include "../include/usb_ops_linux.h"
8 #include "../include/rtl8188e_recv.h"
9
10 unsigned int ffaddr2pipehdl(struct dvobj_priv *pdvobj, u32 addr)
11 {
12         unsigned int pipe = 0, ep_num = 0;
13         struct usb_device *pusbd = pdvobj->pusbdev;
14
15         if (addr < HW_QUEUE_ENTRY) {
16                 ep_num = pdvobj->Queue2Pipe[addr];
17                 pipe = usb_sndbulkpipe(pusbd, ep_num);
18         }
19
20         return pipe;
21 }
22
23 void rtw_read_port_cancel(struct adapter *padapter)
24 {
25         int i;
26         struct recv_buf *precvbuf = (struct recv_buf *)padapter->recvpriv.precv_buf;
27
28         padapter->bReadPortCancel = true;
29
30         for (i = 0; i < NR_RECVBUFF; i++) {
31                 precvbuf->reuse = true;
32                 if (precvbuf->purb)
33                         usb_kill_urb(precvbuf->purb);
34                 precvbuf++;
35         }
36 }
37
38 static void usb_write_port_complete(struct urb *purb, struct pt_regs *regs)
39 {
40         struct xmit_buf *pxmitbuf = (struct xmit_buf *)purb->context;
41         struct adapter  *padapter = pxmitbuf->padapter;
42         struct xmit_priv        *pxmitpriv = &padapter->xmitpriv;
43
44         switch (pxmitbuf->flags) {
45         case VO_QUEUE_INX:
46                 pxmitpriv->voq_cnt--;
47                 break;
48         case VI_QUEUE_INX:
49                 pxmitpriv->viq_cnt--;
50                 break;
51         case BE_QUEUE_INX:
52                 pxmitpriv->beq_cnt--;
53                 break;
54         case BK_QUEUE_INX:
55                 pxmitpriv->bkq_cnt--;
56                 break;
57         case HIGH_QUEUE_INX:
58                 rtw_chk_hi_queue_cmd(padapter);
59                 break;
60         default:
61                 break;
62         }
63
64         if (padapter->bSurpriseRemoved || padapter->bDriverStopped ||
65             padapter->bWritePortCancel)
66                 goto check_completion;
67
68         if (purb->status) {
69                 if (purb->status == -EINPROGRESS) {
70                         goto check_completion;
71                 } else if (purb->status == -ENOENT) {
72                         goto check_completion;
73                 } else if (purb->status == -ECONNRESET) {
74                         goto check_completion;
75                 } else if (purb->status == -ESHUTDOWN) {
76                         padapter->bDriverStopped = true;
77                         goto check_completion;
78                 } else if ((purb->status != -EPIPE) && (purb->status != -EPROTO)) {
79                         padapter->bSurpriseRemoved = true;
80
81                         goto check_completion;
82                 }
83         }
84
85 check_completion:
86         rtw_sctx_done_err(&pxmitbuf->sctx,
87                           purb->status ? RTW_SCTX_DONE_WRITE_PORT_ERR :
88                           RTW_SCTX_DONE_SUCCESS);
89
90         rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
91
92         tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
93
94 }
95
96 u32 rtw_write_port(struct adapter *padapter, u32 addr, u32 cnt, u8 *wmem)
97 {
98         unsigned long irqL;
99         unsigned int pipe;
100         int status;
101         u32 ret = _FAIL;
102         struct urb *purb = NULL;
103         struct dvobj_priv       *pdvobj = adapter_to_dvobj(padapter);
104         struct xmit_priv        *pxmitpriv = &padapter->xmitpriv;
105         struct xmit_buf *pxmitbuf = (struct xmit_buf *)wmem;
106         struct xmit_frame *pxmitframe = (struct xmit_frame *)pxmitbuf->priv_data;
107         struct usb_device *pusbd = pdvobj->pusbdev;
108
109         if ((padapter->bDriverStopped) || (padapter->bSurpriseRemoved) ||
110             (padapter->pwrctrlpriv.pnp_bstop_trx)) {
111                 rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_TX_DENY);
112                 goto exit;
113         }
114
115         spin_lock_irqsave(&pxmitpriv->lock, irqL);
116
117         switch (addr) {
118         case VO_QUEUE_INX:
119                 pxmitpriv->voq_cnt++;
120                 pxmitbuf->flags = VO_QUEUE_INX;
121                 break;
122         case VI_QUEUE_INX:
123                 pxmitpriv->viq_cnt++;
124                 pxmitbuf->flags = VI_QUEUE_INX;
125                 break;
126         case BE_QUEUE_INX:
127                 pxmitpriv->beq_cnt++;
128                 pxmitbuf->flags = BE_QUEUE_INX;
129                 break;
130         case BK_QUEUE_INX:
131                 pxmitpriv->bkq_cnt++;
132                 pxmitbuf->flags = BK_QUEUE_INX;
133                 break;
134         case HIGH_QUEUE_INX:
135                 pxmitbuf->flags = HIGH_QUEUE_INX;
136                 break;
137         default:
138                 pxmitbuf->flags = MGT_QUEUE_INX;
139                 break;
140         }
141
142         spin_unlock_irqrestore(&pxmitpriv->lock, irqL);
143
144         purb    = pxmitbuf->pxmit_urb[0];
145
146         /* translate DMA FIFO addr to pipehandle */
147         pipe = ffaddr2pipehdl(pdvobj, addr);
148
149         usb_fill_bulk_urb(purb, pusbd, pipe,
150                           pxmitframe->buf_addr, /*  pxmitbuf->pbuf */
151                           cnt,
152                           usb_write_port_complete,
153                           pxmitbuf);/* context is pxmitbuf */
154
155         status = usb_submit_urb(purb, GFP_ATOMIC);
156         if (status) {
157                 rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_WRITE_PORT_ERR);
158
159                 switch (status) {
160                 case -ENODEV:
161                         padapter->bDriverStopped = true;
162                         break;
163                 default:
164                         break;
165                 }
166                 goto exit;
167         }
168
169         ret = _SUCCESS;
170
171 /*    We add the URB_ZERO_PACKET flag to urb so that the host will send the zero packet automatically. */
172
173 exit:
174         if (ret != _SUCCESS)
175                 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
176
177         return ret;
178 }
179
180 void rtw_write_port_cancel(struct adapter *padapter)
181 {
182         int i, j;
183         struct xmit_buf *pxmitbuf = (struct xmit_buf *)padapter->xmitpriv.pxmitbuf;
184
185         padapter->bWritePortCancel = true;
186
187         for (i = 0; i < NR_XMITBUFF; i++) {
188                 for (j = 0; j < 8; j++) {
189                         if (pxmitbuf->pxmit_urb[j])
190                                 usb_kill_urb(pxmitbuf->pxmit_urb[j]);
191                 }
192                 pxmitbuf++;
193         }
194
195         pxmitbuf = (struct xmit_buf *)padapter->xmitpriv.pxmit_extbuf;
196         for (i = 0; i < NR_XMIT_EXTBUFF; i++) {
197                 for (j = 0; j < 8; j++) {
198                         if (pxmitbuf->pxmit_urb[j])
199                                 usb_kill_urb(pxmitbuf->pxmit_urb[j]);
200                 }
201                 pxmitbuf++;
202         }
203 }