GNU Linux-libre 5.19-rc6-gnu
[releases.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                 rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_TX_DENY);
111                 goto exit;
112         }
113
114         spin_lock_irqsave(&pxmitpriv->lock, irqL);
115
116         switch (addr) {
117         case VO_QUEUE_INX:
118                 pxmitpriv->voq_cnt++;
119                 pxmitbuf->flags = VO_QUEUE_INX;
120                 break;
121         case VI_QUEUE_INX:
122                 pxmitpriv->viq_cnt++;
123                 pxmitbuf->flags = VI_QUEUE_INX;
124                 break;
125         case BE_QUEUE_INX:
126                 pxmitpriv->beq_cnt++;
127                 pxmitbuf->flags = BE_QUEUE_INX;
128                 break;
129         case BK_QUEUE_INX:
130                 pxmitpriv->bkq_cnt++;
131                 pxmitbuf->flags = BK_QUEUE_INX;
132                 break;
133         case HIGH_QUEUE_INX:
134                 pxmitbuf->flags = HIGH_QUEUE_INX;
135                 break;
136         default:
137                 pxmitbuf->flags = MGT_QUEUE_INX;
138                 break;
139         }
140
141         spin_unlock_irqrestore(&pxmitpriv->lock, irqL);
142
143         purb    = pxmitbuf->pxmit_urb;
144
145         /* translate DMA FIFO addr to pipehandle */
146         pipe = ffaddr2pipehdl(pdvobj, addr);
147
148         usb_fill_bulk_urb(purb, pusbd, pipe,
149                           pxmitframe->buf_addr, /*  pxmitbuf->pbuf */
150                           cnt,
151                           usb_write_port_complete,
152                           pxmitbuf);/* context is pxmitbuf */
153
154         status = usb_submit_urb(purb, GFP_ATOMIC);
155         if (status) {
156                 rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_WRITE_PORT_ERR);
157
158                 switch (status) {
159                 case -ENODEV:
160                         padapter->bDriverStopped = true;
161                         break;
162                 default:
163                         break;
164                 }
165                 goto exit;
166         }
167
168         ret = _SUCCESS;
169
170 /*    We add the URB_ZERO_PACKET flag to urb so that the host will send the zero packet automatically. */
171
172 exit:
173         if (ret != _SUCCESS)
174                 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
175
176         return ret;
177 }
178
179 void rtw_write_port_cancel(struct adapter *padapter)
180 {
181         int i;
182         struct xmit_buf *pxmitbuf = (struct xmit_buf *)padapter->xmitpriv.pxmitbuf;
183
184         padapter->bWritePortCancel = true;
185
186         for (i = 0; i < NR_XMITBUFF; i++) {
187                 if (pxmitbuf->pxmit_urb)
188                         usb_kill_urb(pxmitbuf->pxmit_urb);
189                 pxmitbuf++;
190         }
191
192         pxmitbuf = (struct xmit_buf *)padapter->xmitpriv.pxmit_extbuf;
193         for (i = 0; i < NR_XMIT_EXTBUFF; i++) {
194                 if (pxmitbuf->pxmit_urb)
195                         usb_kill_urb(pxmitbuf->pxmit_urb);
196                 pxmitbuf++;
197         }
198 }