/** * @brief This function sets up the data to receive * * @param ctx Pointer to urb_context structure * @param size Skb size * * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ static mlan_status woal_usb_submit_rx_urb(urb_context * ctx, int size) { moal_handle *handle = ctx->handle; struct usb_card_rec *cardp = (struct usb_card_rec *) handle->card; mlan_status ret = MLAN_STATUS_FAILURE; ENTER(); if (cardp->rx_cmd_ep != ctx->ep) { if (!(ctx->pmbuf = woal_alloc_mlan_buffer(handle, size))) { PRINTM(MERROR, "Fail to submit Rx URB due to no memory/skb\n"); goto rx_ret; } } ctx->pmbuf->data_offset = MLAN_NET_IP_ALIGN + MLAN_RX_HEADER_LEN; usb_fill_bulk_urb(ctx->urb, cardp->udev, usb_rcvbulkpipe(cardp->udev, ctx->ep), ctx->pmbuf->pbuf + ctx->pmbuf->data_offset, size - ctx->pmbuf->data_offset, woal_usb_receive, (void *) ctx); if (cardp->rx_cmd_ep == ctx->ep) atomic_inc(&cardp->rx_cmd_urb_pending); else atomic_inc(&cardp->rx_data_urb_pending); if (usb_submit_urb(ctx->urb, GFP_ATOMIC)) { /* Submit URB failure */ PRINTM(MERROR, "Submit Rx URB failed: %d\n", ret); woal_free_mlan_buffer(handle, ctx->pmbuf); if (cardp->rx_cmd_ep == ctx->ep) atomic_dec(&cardp->rx_cmd_urb_pending); else atomic_dec(&cardp->rx_data_urb_pending); ctx->pmbuf = NULL; ret = MLAN_STATUS_FAILURE; } else { ret = MLAN_STATUS_SUCCESS; } rx_ret: LEAVE(); return ret; }
/** * @brief This function sets up the data to receive * * @param ctx Pointer to urb_context structure * @param size Skb size * * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ static mlan_status woal_usb_submit_rx_urb(urb_context * ctx, int size) { moal_handle *handle = ctx->handle; struct usb_card_rec *cardp = (struct usb_card_rec *) handle->card; struct sk_buff *skb = NULL; mlan_status ret = MLAN_STATUS_FAILURE; ENTER(); if (cardp->rx_cmd_ep != ctx->ep) { if (!(ctx->pmbuf = woal_alloc_mlan_buffer(size))) { PRINTM(ERROR, "No free skb\n"); goto rx_ret; } } skb = (struct sk_buff *) ctx->pmbuf->pdesc; ctx->pmbuf->data_offset = MLAN_NET_IP_ALIGN; usb_fill_bulk_urb(ctx->urb, cardp->udev, usb_rcvbulkpipe(cardp->udev, ctx->ep), skb->tail + MLAN_NET_IP_ALIGN, size - MLAN_NET_IP_ALIGN, woal_usb_receive, (void *) ctx); if (cardp->rx_cmd_ep == ctx->ep) atomic_inc(&cardp->rx_cmd_urb_pending); else atomic_inc(&cardp->rx_data_urb_pending); if ((ret = usb_submit_urb(ctx->urb, GFP_ATOMIC))) { /* Submit URB failure */ PRINTM(ERROR, "Submit Rx URB failed: %d\n", ret); woal_free_mlan_buffer(ctx->pmbuf); if (cardp->rx_cmd_ep == ctx->ep) atomic_dec(&cardp->rx_cmd_urb_pending); else atomic_dec(&cardp->rx_data_urb_pending); ctx->pmbuf = NULL; } else { ret = MLAN_STATUS_SUCCESS; } rx_ret: LEAVE(); return ret; }
/** * @brief This function receive packet of the data/cmd/event packet * and pass to MLAN * * @param urb Pointer to struct urb * * @return N/A */ static void woal_usb_receive(struct urb *urb) #endif { urb_context *context = (urb_context *) urb->context; moal_handle *handle = context->handle; mlan_buffer *pmbuf = context->pmbuf; struct usb_card_rec *cardp = NULL; int recv_length = urb->actual_length; int size; mlan_status status; ENTER(); if (!handle || !handle->card) { PRINTM(MERROR, "moal handle or card structure is not valid\n"); LEAVE(); return; } cardp = (struct usb_card_rec *) handle->card; if (cardp->rx_cmd_ep == context->ep) atomic_dec(&cardp->rx_cmd_urb_pending); else atomic_dec(&cardp->rx_data_urb_pending); if (recv_length) { if (urb->status || (handle->surprise_removed == MTRUE)) { PRINTM(MERROR, "URB status is failed: %d\n", urb->status); /* Do not free mlan_buffer in case of command ep */ if (cardp->rx_cmd_ep != context->ep) woal_free_mlan_buffer(handle, pmbuf); goto setup_for_next; } /* Send packet to MLAN */ pmbuf->data_len = recv_length; atomic_inc(&handle->rx_pending); status = mlan_recv(handle->pmlan_adapter, pmbuf, context->ep); PRINTM(MINFO, "Receive length = 0x%x, status=%d\n", recv_length, status); if (status == MLAN_STATUS_PENDING) { queue_work(handle->workqueue, &handle->main_work); /* urb for data_ep is re-submitted now */ /* urb for cmd_ep will be re-submitted in callback moal_recv_complete */ if (cardp->rx_cmd_ep == context->ep) goto rx_exit; } else { atomic_dec(&handle->rx_pending); if (status == MLAN_STATUS_FAILURE) PRINTM(MERROR, "MLAN fail to process the receive data\n"); /* Do not free mlan_buffer in case of command ep */ if (cardp->rx_cmd_ep != context->ep) woal_free_mlan_buffer(handle, pmbuf); } } else if (urb->status) { if (!handle->is_suspended) { PRINTM(MMSG, "Card is removed: %d\n", urb->status); handle->surprise_removed = MTRUE; } woal_free_mlan_buffer(handle, pmbuf); context->pmbuf = NULL; goto rx_exit; } else { /* Do not free mlan_buffer in case of command ep */ if (cardp->rx_cmd_ep != context->ep) woal_free_mlan_buffer(handle, pmbuf); goto setup_for_next; } setup_for_next: if (cardp->rx_cmd_ep == context->ep) size = MLAN_RX_CMD_BUF_SIZE; else size = MLAN_RX_DATA_BUF_SIZE; woal_usb_submit_rx_urb(context, size); rx_exit: LEAVE(); return; }