/** * @brief This function initialize the rx URBs and submit them * * @param handle Pointer to moal_handle structure * * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ mlan_status woal_usb_rx_init(moal_handle * handle) { struct usb_card_rec *cardp = (struct usb_card_rec *) handle->card; int i; mlan_status ret = MLAN_STATUS_SUCCESS; ENTER(); cardp->rx_cmd.handle = handle; cardp->rx_cmd.ep = cardp->rx_cmd_ep; /* Allocate URB for command/event */ if (!(cardp->rx_cmd.urb = usb_alloc_urb(0, GFP_ATOMIC))) { PRINTM(ERROR, "Rx command URB allocation failed\n"); ret = MLAN_STATUS_FAILURE; goto init_exit; } if ((cardp->rx_cmd.pmbuf = woal_alloc_mlan_buffer(MLAN_RX_CMD_BUF_SIZE))) { /* Submit Rx command URB */ if (woal_usb_submit_rx_urb(&cardp->rx_cmd, MLAN_RX_CMD_BUF_SIZE) < 0) { ret = MLAN_STATUS_FAILURE; goto init_exit; } } for (i = 0; i < MVUSB_RX_DATA_URB; i++) { cardp->rx_data_list[i].handle = handle; cardp->rx_data_list[i].ep = cardp->rx_data_ep; /* Allocate URB for data */ if (!(cardp->rx_data_list[i].urb = usb_alloc_urb(0, GFP_ATOMIC))) { PRINTM(ERROR, "Rx data URB allocation failed\n"); ret = MLAN_STATUS_FAILURE; goto init_exit; } /* Submit Rx data URB */ if (woal_usb_submit_rx_urb (&cardp->rx_data_list[i], MLAN_RX_DATA_BUF_SIZE) < 0) { ret = MLAN_STATUS_FAILURE; goto init_exit; } } init_exit: LEAVE(); return ret; }
/** * @brief This function will submit rx urb. * * @param handle Pointer to moal_handle * @param ep Endpoint to re-submit urb * * @return N/A */ void woal_submit_rx_urb(moal_handle * handle, t_u8 ep) { struct usb_card_rec *cardp = (struct usb_card_rec *) handle->card; ENTER(); if ((ep == cardp->rx_cmd_ep) && (!atomic_read(&cardp->rx_cmd_urb_pending))) { woal_usb_submit_rx_urb(&cardp->rx_cmd, MLAN_RX_CMD_BUF_SIZE); } LEAVE(); return; }
/** * @brief This function submits the rx data URBs * * @param handle Pointer to moal_handle structure * * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ mlan_status woal_usb_submit_rx_data_urbs(moal_handle * handle) { struct usb_card_rec *cardp = (struct usb_card_rec *) handle->card; int i; mlan_status ret = MLAN_STATUS_FAILURE; ENTER(); for (i = 0; i < MVUSB_RX_DATA_URB; i++) { /* Submit Rx data URB */ if (!cardp->rx_data_list[i].pmbuf) { if (woal_usb_submit_rx_urb (&cardp->rx_data_list[i], MLAN_RX_DATA_BUF_SIZE)) continue; } ret = MLAN_STATUS_SUCCESS; } LEAVE(); return ret; }
/** * @brief Handle resume * * @param intf Pointer to usb_interface * * @return MLAN_STATUS_SUCCESS */ static int woal_usb_resume(struct usb_interface *intf) { struct usb_card_rec *cardp = usb_get_intfdata(intf); moal_handle *handle = NULL; int i; ENTER(); if (!cardp || !cardp->phandle) { PRINTM(MERROR, "Card or adapter structure is not valid\n"); LEAVE(); return MLAN_STATUS_SUCCESS; } handle = cardp->phandle; if (handle->is_suspended == MFALSE) { PRINTM(MWARN, "Device already resumed\n"); LEAVE(); return MLAN_STATUS_SUCCESS; } /* Indicate device resumed. The netdev queue will be resumed only after the urbs have been resubmitted */ handle->is_suspended = MFALSE; if (!atomic_read(&cardp->rx_data_urb_pending)) { /* Submit multiple Rx data URBs */ woal_usb_submit_rx_data_urbs(handle); } if (!atomic_read(&cardp->rx_cmd_urb_pending)) { if ((cardp->rx_cmd.pmbuf = woal_alloc_mlan_buffer(handle, MLAN_RX_CMD_BUF_SIZE))) woal_usb_submit_rx_urb(&cardp->rx_cmd, MLAN_RX_CMD_BUF_SIZE); } for (i = 0; i < handle->priv_num; i++) if (handle->priv[i]->media_connected == MTRUE) netif_carrier_on(handle->priv[i]->netdev); /* Disable Host Sleep */ if (handle->hs_activated) woal_cancel_hs(woal_get_priv(handle, MLAN_BSS_ROLE_ANY), MOAL_NO_WAIT); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) #ifdef CONFIG_PM /* Resume handler may be called due to remote wakeup, force to exit suspend anyway */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) cardp->udev->autosuspend_disabled = 1; #else cardp->udev->dev.power.runtime_auto = 0; #endif /* < 2.6.35 */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) cardp->udev->autoresume_disabled = 0; #endif /* < 2.6.33 */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34) atomic_inc(&(cardp->udev)->dev.power.usage_count); #endif /* >= 2.6.34 */ #endif /* CONFIG_PM */ #endif /* >= 2.6.24 */ LEAVE(); return MLAN_STATUS_SUCCESS; }
/** * @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; }