Path: blob/master/ALFA-W1F1/RTL8814AU/os_dep/linux/usb_ops_linux.c
1307 views
/******************************************************************************1*2* Copyright(c) 2007 - 2017 Realtek Corporation.3*4* This program is free software; you can redistribute it and/or modify it5* under the terms of version 2 of the GNU General Public License as6* published by the Free Software Foundation.7*8* This program is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for11* more details.12*13*****************************************************************************/14#define _USB_OPS_LINUX_C_1516#include <drv_types.h>17#include <hal_data.h>18#include <rtw_sreset.h>1920struct rtw_async_write_data {21u8 data[VENDOR_CMD_MAX_DATA_LEN];22struct usb_ctrlrequest dr;23};2425int usbctrl_vendorreq(struct intf_hdl *pintfhdl, u8 request, u16 value, u16 index, void *pdata, u16 len, u8 requesttype)26{27_adapter *padapter = pintfhdl->padapter;28struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);29struct usb_device *udev = pdvobjpriv->pusbdev;3031unsigned int pipe;32int status = 0;33#ifdef CONFIG_USB_VENDOR_REQ_BUFFER_DYNAMIC_ALLOCATE34u32 tmp_buflen = 0;35#endif36u8 reqtype;37u8 *pIo_buf;38int vendorreq_times = 0;3940#if (defined(CONFIG_RTL8822B) || defined(CONFIG_RTL8821C)) || defined(CONFIG_RTL8822C)41#define REG_ON_SEC 0x0042#define REG_OFF_SEC 0x0143#define REG_LOCAL_SEC 0x0244u8 current_reg_sec = REG_LOCAL_SEC;45#endif4647#ifdef CONFIG_USB_VENDOR_REQ_BUFFER_DYNAMIC_ALLOCATE48u8 *tmp_buf;49#else /* use stack memory */50#ifndef CONFIG_USB_VENDOR_REQ_BUFFER_PREALLOC51u8 tmp_buf[MAX_USB_IO_CTL_SIZE];52#endif53#endif5455/* RTW_INFO("%s %s:%d\n",__FUNCTION__, current->comm, current->pid); */5657if (RTW_CANNOT_IO(padapter)) {58status = -EPERM;59goto exit;60}6162if (len > MAX_VENDOR_REQ_CMD_SIZE) {63RTW_INFO("[%s] Buffer len error ,vendor request failed\n", __FUNCTION__);64status = -EINVAL;65goto exit;66}6768#ifdef CONFIG_USB_VENDOR_REQ_MUTEX69_enter_critical_mutex_lock(&pdvobjpriv->usb_vendor_req_mutex, NULL);70#endif717273/* Acquire IO memory for vendorreq */74#ifdef CONFIG_USB_VENDOR_REQ_BUFFER_PREALLOC75pIo_buf = pdvobjpriv->usb_vendor_req_buf;76#else77#ifdef CONFIG_USB_VENDOR_REQ_BUFFER_DYNAMIC_ALLOCATE78tmp_buf = rtw_malloc((u32) len + ALIGNMENT_UNIT);79tmp_buflen = (u32)len + ALIGNMENT_UNIT;80#else /* use stack memory */81tmp_buflen = MAX_USB_IO_CTL_SIZE;82#endif8384/* Added by Albert 2010/02/09 */85/* For mstar platform, mstar suggests the address for USB IO should be 16 bytes alignment. */86/* Trying to fix it here. */87pIo_buf = (tmp_buf == NULL) ? NULL : tmp_buf + ALIGNMENT_UNIT - ((SIZE_PTR)(tmp_buf) & 0x0f);88#endif8990if (pIo_buf == NULL) {91RTW_INFO("[%s] pIo_buf == NULL\n", __FUNCTION__);92status = -ENOMEM;93goto release_mutex;94}9596while (++vendorreq_times <= MAX_USBCTRL_VENDORREQ_TIMES) {97_rtw_memset(pIo_buf, 0, len);9899if (requesttype == 0x01) {100pipe = usb_rcvctrlpipe(udev, 0);/* read_in */101reqtype = REALTEK_USB_VENQT_READ;102} else {103pipe = usb_sndctrlpipe(udev, 0);/* write_out */104reqtype = REALTEK_USB_VENQT_WRITE;105_rtw_memcpy(pIo_buf, pdata, len);106}107108status = rtw_usb_control_msg(udev, pipe, request, reqtype, value, index, pIo_buf, len, RTW_USB_CONTROL_MSG_TIMEOUT);109110if (status == len) { /* Success this control transfer. */111rtw_reset_continual_io_error(pdvobjpriv);112if (requesttype == 0x01) {113/* For Control read transfer, we have to copy the read data from pIo_buf to pdata. */114_rtw_memcpy(pdata, pIo_buf, len);115}116} else { /* error cases */117switch (len) {118case 1:119RTW_INFO("reg 0x%x, usb %s %u fail, status:%d value=0x%x, vendorreq_times:%d\n"120, value, (requesttype == 0x01) ? "read" : "write" , len, status, *(u8 *)pdata, vendorreq_times);121break;122case 2:123RTW_INFO("reg 0x%x, usb %s %u fail, status:%d value=0x%x, vendorreq_times:%d\n"124, value, (requesttype == 0x01) ? "read" : "write" , len, status, *(u16 *)pdata, vendorreq_times);125break;126case 4:127RTW_INFO("reg 0x%x, usb %s %u fail, status:%d value=0x%x, vendorreq_times:%d\n"128, value, (requesttype == 0x01) ? "read" : "write" , len, status, *(u32 *)pdata, vendorreq_times);129break;130default:131RTW_INFO("reg 0x%x, usb %s %u fail, status:%d, vendorreq_times:%d\n"132, value, (requesttype == 0x01) ? "read" : "write" , len, status, vendorreq_times);133break;134135}136137if (status < 0) {138if (status == (-ESHUTDOWN) || status == -ENODEV)139rtw_set_surprise_removed(padapter);140else {141#ifdef DBG_CONFIG_ERROR_DETECT142{143HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);144pHalData->srestpriv.Wifi_Error_Status = USB_VEN_REQ_CMD_FAIL;145}146#endif147}148} else { /* status != len && status >= 0 */149if (status > 0) {150if (requesttype == 0x01) {151/* For Control read transfer, we have to copy the read data from pIo_buf to pdata. */152_rtw_memcpy(pdata, pIo_buf, len);153}154}155}156157if (rtw_inc_and_chk_continual_io_error(pdvobjpriv) == _TRUE) {158rtw_set_surprise_removed(padapter);159break;160}161162}163164/* firmware download is checksumed, don't retry */165if ((value >= FW_START_ADDRESS) || status == len)166break;167168}169170#if (defined(CONFIG_RTL8822B) || defined(CONFIG_RTL8821C)) || defined(CONFIG_RTL8822C)171if (value < 0xFE00) {172if (value <= 0xff)173current_reg_sec = REG_ON_SEC;174else if (0x1000 <= value && value <= 0x10ff)175current_reg_sec = REG_ON_SEC;176else177current_reg_sec = REG_OFF_SEC;178} else {179current_reg_sec = REG_LOCAL_SEC;180}181182if (current_reg_sec == REG_ON_SEC) {183unsigned int t_pipe = usb_sndctrlpipe(udev, 0);/* write_out */184u8 t_reqtype = REALTEK_USB_VENQT_WRITE;185u8 t_len = 1;186u8 t_req = 0x05;187u16 t_reg = 0;188u16 t_index = 0;189190t_reg = 0x4e0;191192status = rtw_usb_control_msg(udev, t_pipe, t_req, t_reqtype, t_reg, t_index, pIo_buf, t_len, RTW_USB_CONTROL_MSG_TIMEOUT);193194if (status == t_len)195rtw_reset_continual_io_error(pdvobjpriv);196else197RTW_INFO("reg 0x%x, usb %s %u fail, status:%d\n", t_reg, "write" , t_len, status);198199}200#endif201202/* release IO memory used by vendorreq */203#ifdef CONFIG_USB_VENDOR_REQ_BUFFER_DYNAMIC_ALLOCATE204rtw_mfree(tmp_buf, tmp_buflen);205#endif206207release_mutex:208#ifdef CONFIG_USB_VENDOR_REQ_MUTEX209_exit_critical_mutex(&pdvobjpriv->usb_vendor_req_mutex, NULL);210#endif211exit:212return status;213214}215216#ifdef CONFIG_USB_SUPPORT_ASYNC_VDN_REQ217static void _usbctrl_vendorreq_async_callback(struct urb *urb, struct pt_regs *regs)218{219if (urb) {220if (urb->context)221rtw_mfree(urb->context, sizeof(struct rtw_async_write_data));222usb_free_urb(urb);223}224}225226int _usbctrl_vendorreq_async_write(struct usb_device *udev, u8 request,227u16 value, u16 index, void *pdata, u16 len, u8 requesttype)228{229int rc;230unsigned int pipe;231u8 reqtype;232struct usb_ctrlrequest *dr;233struct urb *urb;234struct rtw_async_write_data *buf;235236237if (requesttype == VENDOR_READ) {238pipe = usb_rcvctrlpipe(udev, 0);/* read_in */239reqtype = REALTEK_USB_VENQT_READ;240} else {241pipe = usb_sndctrlpipe(udev, 0);/* write_out */242reqtype = REALTEK_USB_VENQT_WRITE;243}244245buf = (struct rtl819x_async_write_data *)rtw_zmalloc(sizeof(*buf));246if (!buf) {247rc = -ENOMEM;248goto exit;249}250251urb = usb_alloc_urb(0, GFP_ATOMIC);252if (!urb) {253rtw_mfree((u8 *)buf, sizeof(*buf));254rc = -ENOMEM;255goto exit;256}257258dr = &buf->dr;259260dr->bRequestType = reqtype;261dr->bRequest = request;262dr->wValue = cpu_to_le16(value);263dr->wIndex = cpu_to_le16(index);264dr->wLength = cpu_to_le16(len);265266_rtw_memcpy(buf, pdata, len);267268usb_fill_control_urb(urb, udev, pipe, (unsigned char *)dr, buf, len,269_usbctrl_vendorreq_async_callback, buf);270271rc = usb_submit_urb(urb, GFP_ATOMIC);272if (rc < 0) {273rtw_mfree((u8 *)buf, sizeof(*buf));274usb_free_urb(urb);275}276277exit:278return rc;279}280281282#endif /* CONFIG_USB_SUPPORT_ASYNC_VDN_REQ */283284unsigned int ffaddr2pipehdl(struct dvobj_priv *pdvobj, u32 addr)285{286unsigned int pipe = 0, ep_num = 0;287struct usb_device *pusbd = pdvobj->pusbdev;288289if (addr == RECV_BULK_IN_ADDR)290pipe = usb_rcvbulkpipe(pusbd, pdvobj->RtInPipe[0]);291292else if (addr == RECV_INT_IN_ADDR)293pipe = usb_rcvintpipe(pusbd, pdvobj->RtInPipe[1]);294295#ifdef RTW_HALMAC296/* halmac already translate queue id to bulk out id (addr 0~3) */297/* 8814BU bulk out id range is 0~6 */298else if (addr < MAX_BULKOUT_NUM) {299ep_num = pdvobj->RtOutPipe[addr];300pipe = usb_sndbulkpipe(pusbd, ep_num);301}302#else303else if (addr < HW_QUEUE_ENTRY) {304ep_num = pdvobj->Queue2Pipe[addr];305pipe = usb_sndbulkpipe(pusbd, ep_num);306}307#endif308309310return pipe;311}312313struct zero_bulkout_context {314void *pbuf;315void *purb;316void *pirp;317void *padapter;318};319#if 0320static void usb_bulkout_zero_complete(struct urb *purb, struct pt_regs *regs)321{322struct zero_bulkout_context *pcontext = (struct zero_bulkout_context *)purb->context;323324/* RTW_INFO("+usb_bulkout_zero_complete\n"); */325326if (pcontext) {327if (pcontext->pbuf)328rtw_mfree(pcontext->pbuf, sizeof(int));329330if (pcontext->purb && (pcontext->purb == purb))331usb_free_urb(pcontext->purb);332333334rtw_mfree((u8 *)pcontext, sizeof(struct zero_bulkout_context));335}336337338}339340static u32 usb_bulkout_zero(struct intf_hdl *pintfhdl, u32 addr)341{342int pipe, status, len;343u32 ret;344unsigned char *pbuf;345struct zero_bulkout_context *pcontext;346PURB purb = NULL;347_adapter *padapter = (_adapter *)pintfhdl->padapter;348struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);349struct usb_device *pusbd = pdvobj->pusbdev;350351/* RTW_INFO("%s\n", __func__); */352353354if (RTW_CANNOT_TX(padapter))355return _FAIL;356357358pcontext = (struct zero_bulkout_context *)rtw_zmalloc(sizeof(struct zero_bulkout_context));359if (pcontext == NULL)360return _FAIL;361362pbuf = (unsigned char *)rtw_zmalloc(sizeof(int));363purb = usb_alloc_urb(0, GFP_ATOMIC);364365/* translate DMA FIFO addr to pipehandle */366pipe = ffaddr2pipehdl(pdvobj, addr);367368len = 0;369pcontext->pbuf = pbuf;370pcontext->purb = purb;371pcontext->pirp = NULL;372pcontext->padapter = padapter;373374375/* translate DMA FIFO addr to pipehandle */376/* pipe = ffaddr2pipehdl(pdvobj, addr); */377378usb_fill_bulk_urb(purb, pusbd, pipe,379pbuf,380len,381usb_bulkout_zero_complete,382pcontext);/* context is pcontext */383384status = usb_submit_urb(purb, GFP_ATOMIC);385386if (!status)387ret = _SUCCESS;388else389ret = _FAIL;390391392return _SUCCESS;393394}395#endif396void usb_read_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem)397{398399}400401void usb_write_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem)402{403404}405406407void usb_read_port_cancel(struct intf_hdl *pintfhdl)408{409int i;410struct recv_buf *precvbuf;411_adapter *padapter = pintfhdl->padapter;412precvbuf = (struct recv_buf *)padapter->recvpriv.precv_buf;413414RTW_INFO("%s\n", __func__);415416for (i = 0; i < NR_RECVBUFF ; i++) {417418if (precvbuf->purb) {419/* RTW_INFO("usb_read_port_cancel : usb_kill_urb\n"); */420usb_kill_urb(precvbuf->purb);421}422precvbuf++;423}424425#ifdef CONFIG_USB_INTERRUPT_IN_PIPE426usb_kill_urb(padapter->recvpriv.int_in_urb);427#endif428}429430static void usb_write_port_complete(struct urb *purb, struct pt_regs *regs)431{432_irqL irqL;433struct xmit_buf *pxmitbuf = (struct xmit_buf *)purb->context;434/* struct xmit_frame *pxmitframe = (struct xmit_frame *)pxmitbuf->priv_data; */435/* _adapter *padapter = pxmitframe->padapter; */436_adapter *padapter = pxmitbuf->padapter;437struct xmit_priv *pxmitpriv = &padapter->xmitpriv;438/* struct pkt_attrib *pattrib = &pxmitframe->attrib; */439440441switch (pxmitbuf->flags) {442case VO_QUEUE_INX:443pxmitpriv->voq_cnt--;444break;445case VI_QUEUE_INX:446pxmitpriv->viq_cnt--;447break;448case BE_QUEUE_INX:449pxmitpriv->beq_cnt--;450break;451case BK_QUEUE_INX:452pxmitpriv->bkq_cnt--;453break;454default:455break;456}457458459/*460_enter_critical(&pxmitpriv->lock, &irqL);461462pxmitpriv->txirp_cnt--;463464switch(pattrib->priority)465{466case 1:467case 2:468pxmitpriv->bkq_cnt--;469470break;471case 4:472case 5:473pxmitpriv->viq_cnt--;474475break;476case 6:477case 7:478pxmitpriv->voq_cnt--;479480break;481case 0:482case 3:483default:484pxmitpriv->beq_cnt--;485486break;487488}489490_exit_critical(&pxmitpriv->lock, &irqL);491492493if(pxmitpriv->txirp_cnt==0)494{495_rtw_up_sema(&(pxmitpriv->tx_retevt));496}497*/498/* rtw_free_xmitframe(pxmitpriv, pxmitframe); */499500if (RTW_CANNOT_TX(padapter)) {501RTW_INFO("%s(): TX Warning! bDriverStopped(%s) OR bSurpriseRemoved(%s) pxmitbuf->buf_tag(%x)\n"502, __func__503, rtw_is_drv_stopped(padapter) ? "True" : "False"504, rtw_is_surprise_removed(padapter) ? "True" : "False"505, pxmitbuf->buf_tag);506507goto check_completion;508}509510511if (purb->status == 0) {512513} else {514RTW_INFO("###=> urb_write_port_complete status(%d)\n", purb->status);515if ((purb->status == -EPIPE) || (purb->status == -EPROTO)) {516/* usb_clear_halt(pusbdev, purb->pipe); */517/* msleep(10); */518sreset_set_wifi_error_status(padapter, USB_WRITE_PORT_FAIL);519} else if (purb->status == -EINPROGRESS) {520goto check_completion;521522} else if (purb->status == -ENOENT) {523RTW_INFO("%s: -ENOENT\n", __func__);524goto check_completion;525526} else if (purb->status == -ECONNRESET) {527RTW_INFO("%s: -ECONNRESET\n", __func__);528goto check_completion;529530} else if (purb->status == -ESHUTDOWN) {531rtw_set_drv_stopped(padapter);532533goto check_completion;534} else {535rtw_set_surprise_removed(padapter);536RTW_INFO("bSurpriseRemoved=TRUE\n");537538goto check_completion;539}540}541542#ifdef DBG_CONFIG_ERROR_DETECT543{544HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);545pHalData->srestpriv.last_tx_complete_time = rtw_get_current_time();546}547#endif548549check_completion:550_enter_critical(&pxmitpriv->lock_sctx, &irqL);551rtw_sctx_done_err(&pxmitbuf->sctx,552purb->status ? RTW_SCTX_DONE_WRITE_PORT_ERR : RTW_SCTX_DONE_SUCCESS);553_exit_critical(&pxmitpriv->lock_sctx, &irqL);554555rtw_free_xmitbuf(pxmitpriv, pxmitbuf);556557/* if(rtw_txframes_pending(padapter)) */558{559tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);560}561562563}564565u32 usb_write_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem)566{567_irqL irqL;568unsigned int pipe;569int status;570u32 ret = _FAIL;571PURB purb = NULL;572_adapter *padapter = (_adapter *)pintfhdl->padapter;573struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);574struct xmit_priv *pxmitpriv = &padapter->xmitpriv;575struct xmit_buf *pxmitbuf = (struct xmit_buf *)wmem;576struct xmit_frame *pxmitframe = (struct xmit_frame *)pxmitbuf->priv_data;577struct usb_device *pusbd = pdvobj->pusbdev;578579if (RTW_CANNOT_TX(padapter)) {580#ifdef DBG_TX581RTW_INFO(" DBG_TX %s:%d bDriverStopped%s, bSurpriseRemoved:%s\n", __func__, __LINE__582, rtw_is_drv_stopped(padapter) ? "True" : "False"583, rtw_is_surprise_removed(padapter) ? "True" : "False");584#endif585rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_TX_DENY);586goto exit;587}588589_enter_critical(&pxmitpriv->lock, &irqL);590591switch (addr) {592case VO_QUEUE_INX:593pxmitpriv->voq_cnt++;594pxmitbuf->flags = VO_QUEUE_INX;595break;596case VI_QUEUE_INX:597pxmitpriv->viq_cnt++;598pxmitbuf->flags = VI_QUEUE_INX;599break;600case BE_QUEUE_INX:601pxmitpriv->beq_cnt++;602pxmitbuf->flags = BE_QUEUE_INX;603break;604case BK_QUEUE_INX:605pxmitpriv->bkq_cnt++;606pxmitbuf->flags = BK_QUEUE_INX;607break;608case HIGH_QUEUE_INX:609pxmitbuf->flags = HIGH_QUEUE_INX;610break;611default:612pxmitbuf->flags = MGT_QUEUE_INX;613break;614}615616_exit_critical(&pxmitpriv->lock, &irqL);617618purb = pxmitbuf->pxmit_urb[0];619620/* translate DMA FIFO addr to pipehandle */621#ifdef RTW_HALMAC622pipe = ffaddr2pipehdl(pdvobj, pxmitbuf->bulkout_id);623#else624pipe = ffaddr2pipehdl(pdvobj, addr);625#endif626627#ifdef CONFIG_REDUCE_USB_TX_INT628if ((pxmitpriv->free_xmitbuf_cnt % NR_XMITBUFF == 0)629|| (pxmitbuf->buf_tag > XMITBUF_DATA))630purb->transfer_flags &= (~URB_NO_INTERRUPT);631else {632purb->transfer_flags |= URB_NO_INTERRUPT;633/* RTW_INFO("URB_NO_INTERRUPT "); */634}635#endif636637638usb_fill_bulk_urb(purb, pusbd, pipe,639pxmitframe->buf_addr, /* = pxmitbuf->pbuf */640cnt,641usb_write_port_complete,642pxmitbuf);/* context is pxmitbuf */643644#ifdef CONFIG_USE_USB_BUFFER_ALLOC_TX645purb->transfer_dma = pxmitbuf->dma_transfer_addr;646purb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;647purb->transfer_flags |= URB_ZERO_PACKET;648#endif /* CONFIG_USE_USB_BUFFER_ALLOC_TX */649650#ifdef USB_PACKET_OFFSET_SZ651#if (USB_PACKET_OFFSET_SZ == 0)652purb->transfer_flags |= URB_ZERO_PACKET;653#endif654#endif655656#if 0657if (bwritezero)658purb->transfer_flags |= URB_ZERO_PACKET;659#endif660661status = usb_submit_urb(purb, GFP_ATOMIC);662if (!status) {663#ifdef DBG_CONFIG_ERROR_DETECT664{665HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);666pHalData->srestpriv.last_tx_time = rtw_get_current_time();667}668#endif669} else {670rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_WRITE_PORT_ERR);671RTW_INFO("usb_write_port, status=%d\n", status);672673switch (status) {674case -ENODEV:675rtw_set_drv_stopped(padapter);676break;677default:678break;679}680goto exit;681}682683ret = _SUCCESS;684685/* Commented by Albert 2009/10/13686* We add the URB_ZERO_PACKET flag to urb so that the host will send the zero packet automatically. */687/*688if(bwritezero == _TRUE)689{690usb_bulkout_zero(pintfhdl, addr);691}692*/693694695exit:696if (ret != _SUCCESS)697rtw_free_xmitbuf(pxmitpriv, pxmitbuf);698return ret;699700}701702void usb_write_port_cancel(struct intf_hdl *pintfhdl)703{704int i, j;705_adapter *padapter = pintfhdl->padapter;706struct xmit_buf *pxmitbuf = (struct xmit_buf *)padapter->xmitpriv.pxmitbuf;707708RTW_INFO("%s\n", __func__);709710for (i = 0; i < NR_XMITBUFF; i++) {711for (j = 0; j < 8; j++) {712if (pxmitbuf->pxmit_urb[j])713usb_kill_urb(pxmitbuf->pxmit_urb[j]);714}715pxmitbuf++;716}717718pxmitbuf = (struct xmit_buf *)padapter->xmitpriv.pxmit_extbuf;719for (i = 0; i < NR_XMIT_EXTBUFF ; i++) {720for (j = 0; j < 8; j++) {721if (pxmitbuf->pxmit_urb[j])722usb_kill_urb(pxmitbuf->pxmit_urb[j]);723}724pxmitbuf++;725}726}727728void usb_init_recvbuf(_adapter *padapter, struct recv_buf *precvbuf)729{730731precvbuf->transfer_len = 0;732733precvbuf->len = 0;734735precvbuf->ref_cnt = 0;736737if (precvbuf->pbuf) {738precvbuf->pdata = precvbuf->phead = precvbuf->ptail = precvbuf->pbuf;739precvbuf->pend = precvbuf->pdata + MAX_RECVBUF_SZ;740}741742}743744int recvbuf2recvframe(PADAPTER padapter, void *ptr);745746#ifdef CONFIG_USE_USB_BUFFER_ALLOC_RX747void usb_recv_tasklet(void *priv)748{749struct recv_buf *precvbuf = NULL;750_adapter *padapter = (_adapter *)priv;751struct recv_priv *precvpriv = &padapter->recvpriv;752753while (NULL != (precvbuf = rtw_dequeue_recvbuf(&precvpriv->recv_buf_pending_queue))) {754if (RTW_CANNOT_RUN(padapter)) {755RTW_INFO("recv_tasklet => bDriverStopped(%s) OR bSurpriseRemoved(%s)\n"756, rtw_is_drv_stopped(padapter)? "True" : "False"757, rtw_is_surprise_removed(padapter)? "True" : "False");758break;759}760761recvbuf2recvframe(padapter, precvbuf);762763rtw_read_port(padapter, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf);764}765}766767void usb_read_port_complete(struct urb *purb, struct pt_regs *regs)768{769struct recv_buf *precvbuf = (struct recv_buf *)purb->context;770_adapter *padapter = (_adapter *)precvbuf->adapter;771struct recv_priv *precvpriv = &padapter->recvpriv;772773ATOMIC_DEC(&(precvpriv->rx_pending_cnt));774775if (RTW_CANNOT_RX(padapter)) {776RTW_INFO("%s() RX Warning! bDriverStopped(%s) OR bSurpriseRemoved(%s)\n"777, __func__778, rtw_is_drv_stopped(padapter) ? "True" : "False"779, rtw_is_surprise_removed(padapter) ? "True" : "False");780return;781}782783if (purb->status == 0) {784785if ((purb->actual_length > MAX_RECVBUF_SZ) || (purb->actual_length < RXDESC_SIZE)) {786RTW_INFO("%s()-%d: urb->actual_length:%u, MAX_RECVBUF_SZ:%u, RXDESC_SIZE:%u\n"787, __FUNCTION__, __LINE__, purb->actual_length, MAX_RECVBUF_SZ, RXDESC_SIZE);788rtw_read_port(padapter, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf);789} else {790rtw_reset_continual_io_error(adapter_to_dvobj(padapter));791792precvbuf->transfer_len = purb->actual_length;793794rtw_enqueue_recvbuf(precvbuf, &precvpriv->recv_buf_pending_queue);795796tasklet_schedule(&precvpriv->recv_tasklet);797}798} else {799800RTW_INFO("###=> usb_read_port_complete => urb.status(%d)\n", purb->status);801802if (rtw_inc_and_chk_continual_io_error(adapter_to_dvobj(padapter)) == _TRUE)803rtw_set_surprise_removed(padapter);804805switch (purb->status) {806case -EINVAL:807case -EPIPE:808case -ENODEV:809case -ESHUTDOWN:810case -ENOENT:811rtw_set_drv_stopped(padapter);812break;813case -EPROTO:814case -EILSEQ:815case -ETIME:816case -ECOMM:817case -EOVERFLOW:818#ifdef DBG_CONFIG_ERROR_DETECT819{820HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);821pHalData->srestpriv.Wifi_Error_Status = USB_READ_PORT_FAIL;822}823#endif824rtw_read_port(padapter, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf);825break;826case -EINPROGRESS:827RTW_INFO("ERROR: URB IS IN PROGRESS!/n");828break;829default:830break;831}832}833834}835836u32 usb_read_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem)837{838int err;839unsigned int pipe;840u32 ret = _SUCCESS;841PURB purb = NULL;842struct recv_buf *precvbuf = (struct recv_buf *)rmem;843_adapter *adapter = pintfhdl->padapter;844struct dvobj_priv *pdvobj = adapter_to_dvobj(adapter);845struct pwrctrl_priv *pwrctl = dvobj_to_pwrctl(pdvobj);846struct recv_priv *precvpriv = &adapter->recvpriv;847struct usb_device *pusbd = pdvobj->pusbdev;848849850if (RTW_CANNOT_RX(adapter) || (precvbuf == NULL)) {851return _FAIL;852}853854usb_init_recvbuf(adapter, precvbuf);855856if (precvbuf->pbuf) {857ATOMIC_INC(&(precvpriv->rx_pending_cnt));858purb = precvbuf->purb;859860/* translate DMA FIFO addr to pipehandle */861pipe = ffaddr2pipehdl(pdvobj, addr);862863usb_fill_bulk_urb(purb, pusbd, pipe,864precvbuf->pbuf,865MAX_RECVBUF_SZ,866usb_read_port_complete,867precvbuf);/* context is precvbuf */868869purb->transfer_dma = precvbuf->dma_transfer_addr;870purb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;871872err = usb_submit_urb(purb, GFP_ATOMIC);873if ((err) && (err != (-EPERM))) {874RTW_INFO("cannot submit rx in-token(err = 0x%08x),urb_status = %d\n", err, purb->status);875ret = _FAIL;876}877878}879880881return ret;882}883#else /* CONFIG_USE_USB_BUFFER_ALLOC_RX */884885void usb_recv_tasklet(void *priv)886{887_pkt *pskb;888_adapter *padapter = (_adapter *)priv;889struct recv_priv *precvpriv = &padapter->recvpriv;890struct recv_buf *precvbuf = NULL;891892while (NULL != (pskb = skb_dequeue(&precvpriv->rx_skb_queue))) {893894if (RTW_CANNOT_RUN(padapter)) {895RTW_INFO("recv_tasklet => bDriverStopped(%s) OR bSurpriseRemoved(%s)\n"896, rtw_is_drv_stopped(padapter) ? "True" : "False"897, rtw_is_surprise_removed(padapter) ? "True" : "False");898#ifdef CONFIG_PREALLOC_RX_SKB_BUFFER899if (rtw_free_skb_premem(pskb) != 0)900#endif /* CONFIG_PREALLOC_RX_SKB_BUFFER */901rtw_skb_free(pskb);902break;903}904905recvbuf2recvframe(padapter, pskb);906907skb_reset_tail_pointer(pskb);908pskb->len = 0;909910skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb);911912precvbuf = rtw_dequeue_recvbuf(&precvpriv->recv_buf_pending_queue);913if (NULL != precvbuf) {914precvbuf->pskb = NULL;915rtw_read_port(padapter, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf);916}917}918}919920void usb_read_port_complete(struct urb *purb, struct pt_regs *regs)921{922struct recv_buf *precvbuf = (struct recv_buf *)purb->context;923_adapter *padapter = (_adapter *)precvbuf->adapter;924struct recv_priv *precvpriv = &padapter->recvpriv;925926ATOMIC_DEC(&(precvpriv->rx_pending_cnt));927928if (RTW_CANNOT_RX(padapter)) {929RTW_INFO("%s() RX Warning! bDriverStopped(%s) OR bSurpriseRemoved(%s)\n"930, __func__931, rtw_is_drv_stopped(padapter) ? "True" : "False"932, rtw_is_surprise_removed(padapter) ? "True" : "False");933goto exit;934}935936if (purb->status == 0) {937938if ((purb->actual_length > MAX_RECVBUF_SZ) || (purb->actual_length < RXDESC_SIZE)) {939RTW_INFO("%s()-%d: urb->actual_length:%u, MAX_RECVBUF_SZ:%u, RXDESC_SIZE:%u\n"940, __FUNCTION__, __LINE__, purb->actual_length, MAX_RECVBUF_SZ, RXDESC_SIZE);941rtw_read_port(padapter, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf);942} else {943rtw_reset_continual_io_error(adapter_to_dvobj(padapter));944945precvbuf->transfer_len = purb->actual_length;946skb_put(precvbuf->pskb, purb->actual_length);947skb_queue_tail(&precvpriv->rx_skb_queue, precvbuf->pskb);948949#ifndef CONFIG_FIX_NR_BULKIN_BUFFER950if (skb_queue_len(&precvpriv->rx_skb_queue) <= 1)951#endif952tasklet_schedule(&precvpriv->recv_tasklet);953954precvbuf->pskb = NULL;955rtw_read_port(padapter, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf);956}957} else {958959RTW_INFO("###=> usb_read_port_complete => urb.status(%d)\n", purb->status);960961if (rtw_inc_and_chk_continual_io_error(adapter_to_dvobj(padapter)) == _TRUE)962rtw_set_surprise_removed(padapter);963964switch (purb->status) {965case -EINVAL:966case -EPIPE:967case -ENODEV:968case -ESHUTDOWN:969case -ENOENT:970rtw_set_drv_stopped(padapter);971break;972case -EPROTO:973case -EILSEQ:974case -ETIME:975case -ECOMM:976case -EOVERFLOW:977#ifdef DBG_CONFIG_ERROR_DETECT978{979HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);980pHalData->srestpriv.Wifi_Error_Status = USB_READ_PORT_FAIL;981}982#endif983rtw_read_port(padapter, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf);984break;985case -EINPROGRESS:986RTW_INFO("ERROR: URB IS IN PROGRESS!/n");987break;988default:989break;990}991}992993exit:994return;995}996997u32 usb_read_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem)998{999int err;1000unsigned int pipe;1001u32 ret = _FAIL;1002PURB purb = NULL;1003struct recv_buf *precvbuf = (struct recv_buf *)rmem;1004_adapter *adapter = pintfhdl->padapter;1005struct dvobj_priv *pdvobj = adapter_to_dvobj(adapter);1006struct recv_priv *precvpriv = &adapter->recvpriv;1007struct usb_device *pusbd = pdvobj->pusbdev;100810091010if (RTW_CANNOT_RX(adapter) || (precvbuf == NULL)) {1011goto exit;1012}10131014usb_init_recvbuf(adapter, precvbuf);10151016if (precvbuf->pskb == NULL) {1017SIZE_PTR tmpaddr = 0;1018SIZE_PTR alignment = 0;10191020precvbuf->pskb = skb_dequeue(&precvpriv->free_recv_skb_queue);1021if (NULL != precvbuf->pskb)1022goto recv_buf_hook;10231024#ifndef CONFIG_FIX_NR_BULKIN_BUFFER1025precvbuf->pskb = rtw_skb_alloc(MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);1026#endif10271028if (precvbuf->pskb == NULL) {1029if (0)1030RTW_INFO("usb_read_port() enqueue precvbuf=%p\n", precvbuf);1031/* enqueue precvbuf and wait for free skb */1032rtw_enqueue_recvbuf(precvbuf, &precvpriv->recv_buf_pending_queue);1033goto exit;1034}10351036tmpaddr = (SIZE_PTR)precvbuf->pskb->data;1037alignment = tmpaddr & (RECVBUFF_ALIGN_SZ - 1);1038skb_reserve(precvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment));1039}10401041recv_buf_hook:1042precvbuf->phead = precvbuf->pskb->head;1043precvbuf->pdata = precvbuf->pskb->data;1044precvbuf->ptail = skb_tail_pointer(precvbuf->pskb);1045precvbuf->pend = skb_end_pointer(precvbuf->pskb);1046precvbuf->pbuf = precvbuf->pskb->data;10471048purb = precvbuf->purb;10491050/* translate DMA FIFO addr to pipehandle */1051pipe = ffaddr2pipehdl(pdvobj, addr);10521053usb_fill_bulk_urb(purb, pusbd, pipe,1054precvbuf->pbuf,1055MAX_RECVBUF_SZ,1056usb_read_port_complete,1057precvbuf);10581059err = usb_submit_urb(purb, GFP_ATOMIC);1060if (err && err != (-EPERM)) {1061RTW_INFO("cannot submit rx in-token(err = 0x%08x),urb_status = %d\n"1062, err, purb->status);1063goto exit;1064}10651066ATOMIC_INC(&(precvpriv->rx_pending_cnt));1067ret = _SUCCESS;10681069exit:107010711072return ret;1073}1074#endif /* CONFIG_USE_USB_BUFFER_ALLOC_RX */10751076#ifdef CONFIG_USB_INTERRUPT_IN_PIPE1077void usb_read_interrupt_complete(struct urb *purb, struct pt_regs *regs)1078{1079int err;1080_adapter *padapter = (_adapter *)purb->context;10811082if (RTW_CANNOT_RX(padapter)) {1083RTW_INFO("%s() RX Warning! bDriverStopped(%s) OR bSurpriseRemoved(%s)\n"1084, __func__1085, rtw_is_drv_stopped(padapter) ? "True" : "False"1086, rtw_is_surprise_removed(padapter) ? "True" : "False");10871088return;1089}10901091if (purb->status == 0) {/*SUCCESS*/1092if (purb->actual_length > INTERRUPT_MSG_FORMAT_LEN)1093RTW_INFO("usb_read_interrupt_complete: purb->actual_length > INTERRUPT_MSG_FORMAT_LEN(%d)\n", INTERRUPT_MSG_FORMAT_LEN);10941095rtw_hal_interrupt_handler(padapter, purb->actual_length, purb->transfer_buffer);10961097err = usb_submit_urb(purb, GFP_ATOMIC);1098if ((err) && (err != (-EPERM)))1099RTW_INFO("cannot submit interrupt in-token(err = 0x%08x),urb_status = %d\n", err, purb->status);1100} else {1101RTW_INFO("###=> usb_read_interrupt_complete => urb status(%d)\n", purb->status);11021103switch (purb->status) {1104case -EINVAL:1105case -EPIPE:1106case -ENODEV:1107case -ESHUTDOWN:1108case -ENOENT:1109rtw_set_drv_stopped(padapter);1110break;1111case -EPROTO:1112break;1113case -EINPROGRESS:1114RTW_INFO("ERROR: URB IS IN PROGRESS!/n");1115break;1116default:1117break;1118}1119}1120}11211122u32 usb_read_interrupt(struct intf_hdl *pintfhdl, u32 addr)1123{1124int err;1125unsigned int pipe;1126u32 ret = _SUCCESS;1127_adapter *adapter = pintfhdl->padapter;1128struct dvobj_priv *pdvobj = adapter_to_dvobj(adapter);1129struct recv_priv *precvpriv = &adapter->recvpriv;1130struct usb_device *pusbd = pdvobj->pusbdev;113111321133if (RTW_CANNOT_RX(adapter)) {1134return _FAIL;1135}11361137/*translate DMA FIFO addr to pipehandle*/1138pipe = ffaddr2pipehdl(pdvobj, addr);11391140usb_fill_int_urb(precvpriv->int_in_urb, pusbd, pipe,1141precvpriv->int_in_buf,1142INTERRUPT_MSG_FORMAT_LEN,1143usb_read_interrupt_complete,1144adapter,11451);11461147err = usb_submit_urb(precvpriv->int_in_urb, GFP_ATOMIC);1148if ((err) && (err != (-EPERM))) {1149RTW_INFO("cannot submit interrupt in-token(err = 0x%08x), urb_status = %d\n", err, precvpriv->int_in_urb->status);1150ret = _FAIL;1151}11521153return ret;1154}1155#endif /* CONFIG_USB_INTERRUPT_IN_PIPE */115611571158