linux/drivers/staging/bcm/InterfaceTx.c
<<
>>
Prefs
   1#include "headers.h"
   2
   3static void prepare_low_power_mode(struct urb *urb,
   4                                   struct bcm_interface_adapter *interface,
   5                                   struct bcm_mini_adapter *ps_adapter,
   6                                   struct bcm_mini_adapter *ad,
   7                                   struct bcm_link_request *p_control_msg,
   8                                   bool *b_power_down_msg)
   9{
  10        if (((p_control_msg->szData[0] == GO_TO_IDLE_MODE_PAYLOAD) &&
  11                (p_control_msg->szData[1] == TARGET_CAN_GO_TO_IDLE_MODE))) {
  12
  13                *b_power_down_msg = TRUE;
  14                /*
  15                 * This covers the bus err while Idle Request msg
  16                 * sent down.
  17                 */
  18                if (urb->status != STATUS_SUCCESS) {
  19                        ps_adapter->bPreparingForLowPowerMode = false;
  20                        BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, NEXT_SEND,
  21                                        DBG_LVL_ALL,
  22                                        "Idle Mode Request msg failed to reach to Modem");
  23                        /* Signalling the cntrl pkt path in Ioctl */
  24                        wake_up(&ps_adapter->lowpower_mode_wait_queue);
  25                        StartInterruptUrb(interface);
  26                        return;
  27                }
  28
  29                if (ps_adapter->bDoSuspend == false) {
  30                        ps_adapter->IdleMode = TRUE;
  31                        /* since going in Idle mode completed hence making this var false */
  32                        ps_adapter->bPreparingForLowPowerMode = false;
  33
  34                        BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, NEXT_SEND,
  35                                        DBG_LVL_ALL,
  36                                        "Host Entered in Idle Mode State...");
  37                        /* Signalling the cntrl pkt path in Ioctl*/
  38                        wake_up(&ps_adapter->lowpower_mode_wait_queue);
  39                }
  40
  41        } else if ((p_control_msg->Leader.Status == LINK_UP_CONTROL_REQ) &&
  42                (p_control_msg->szData[0] == LINK_UP_ACK) &&
  43                (p_control_msg->szData[1] == LINK_SHUTDOWN_REQ_FROM_FIRMWARE)  &&
  44                (p_control_msg->szData[2] == SHUTDOWN_ACK_FROM_DRIVER)) {
  45                /*
  46                 * This covers the bus err while shutdown Request
  47                 * msg sent down.
  48                 */
  49                if (urb->status != STATUS_SUCCESS) {
  50                        ps_adapter->bPreparingForLowPowerMode = false;
  51                        BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, NEXT_SEND,
  52                                        DBG_LVL_ALL,
  53                                        "Shutdown Request Msg failed to reach to Modem");
  54                        /* Signalling the cntrl pkt path in Ioctl */
  55                        wake_up(&ps_adapter->lowpower_mode_wait_queue);
  56                        StartInterruptUrb(interface);
  57                        return;
  58                }
  59
  60                *b_power_down_msg = TRUE;
  61                if (ps_adapter->bDoSuspend == false) {
  62                        ps_adapter->bShutStatus = TRUE;
  63                        /*
  64                         * since going in shutdown mode completed hence
  65                         * making this var false
  66                         */
  67                        ps_adapter->bPreparingForLowPowerMode = false;
  68                        BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, NEXT_SEND,
  69                                        DBG_LVL_ALL,
  70                                        "Host Entered in shutdown Mode State...");
  71                        /* Signalling the cntrl pkt path in Ioctl */
  72                        wake_up(&ps_adapter->lowpower_mode_wait_queue);
  73                }
  74        }
  75
  76        if (ps_adapter->bDoSuspend && *b_power_down_msg) {
  77                /* issuing bus suspend request */
  78                BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL,
  79                                "Issuing the Bus suspend request to USB stack");
  80                interface->bPreparingForBusSuspend = TRUE;
  81                schedule_work(&interface->usbSuspendWork);
  82        }
  83}
  84
  85/*this is transmit call-back(BULK OUT)*/
  86static void write_bulk_callback(struct urb *urb/*, struct pt_regs *regs*/)
  87{
  88        struct bcm_usb_tcb *pTcb = (struct bcm_usb_tcb *)urb->context;
  89        struct bcm_interface_adapter *psIntfAdapter = pTcb->psIntfAdapter;
  90        struct bcm_link_request *pControlMsg =
  91                (struct bcm_link_request *)urb->transfer_buffer;
  92        struct bcm_mini_adapter *psAdapter = psIntfAdapter->psAdapter;
  93        bool bpowerDownMsg = false;
  94        struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
  95
  96        if (unlikely(netif_msg_tx_done(Adapter)))
  97                pr_info(PFX "%s: transmit status %d\n", Adapter->dev->name,
  98                        urb->status);
  99
 100        if (urb->status != STATUS_SUCCESS) {
 101                if (urb->status == -EPIPE) {
 102                        psIntfAdapter->psAdapter->bEndPointHalted = TRUE;
 103                        wake_up(&psIntfAdapter->psAdapter->tx_packet_wait_queue);
 104                } else {
 105                        BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, NEXT_SEND,
 106                                        DBG_LVL_ALL,
 107                                        "Tx URB has got cancelled. status :%d",
 108                                        urb->status);
 109                }
 110        }
 111
 112        pTcb->bUsed = false;
 113        atomic_dec(&psIntfAdapter->uNumTcbUsed);
 114
 115        if (TRUE == psAdapter->bPreparingForLowPowerMode) {
 116                prepare_low_power_mode(urb, psIntfAdapter, psAdapter, Adapter,
 117                                       pControlMsg, &bpowerDownMsg);
 118        }
 119
 120        usb_free_coherent(urb->dev, urb->transfer_buffer_length,
 121                        urb->transfer_buffer, urb->transfer_dma);
 122}
 123
 124
 125static struct bcm_usb_tcb *GetBulkOutTcb(struct bcm_interface_adapter *psIntfAdapter)
 126{
 127        struct bcm_usb_tcb *pTcb = NULL;
 128        UINT index = 0;
 129
 130        if ((atomic_read(&psIntfAdapter->uNumTcbUsed) < MAXIMUM_USB_TCB) &&
 131                (psIntfAdapter->psAdapter->StopAllXaction == false)) {
 132                index = atomic_read(&psIntfAdapter->uCurrTcb);
 133                pTcb = &psIntfAdapter->asUsbTcb[index];
 134                pTcb->bUsed = TRUE;
 135                pTcb->psIntfAdapter = psIntfAdapter;
 136                BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_TX,
 137                                NEXT_SEND, DBG_LVL_ALL,
 138                                "Got Tx desc %d used %d",
 139                                index,
 140                                atomic_read(&psIntfAdapter->uNumTcbUsed));
 141                index = (index + 1) % MAXIMUM_USB_TCB;
 142                atomic_set(&psIntfAdapter->uCurrTcb, index);
 143                atomic_inc(&psIntfAdapter->uNumTcbUsed);
 144        }
 145        return pTcb;
 146}
 147
 148static int TransmitTcb(struct bcm_interface_adapter *psIntfAdapter,
 149                       struct bcm_usb_tcb *pTcb, PVOID data, int len)
 150{
 151
 152        struct urb *urb = pTcb->urb;
 153        int retval = 0;
 154
 155        urb->transfer_buffer = usb_alloc_coherent(psIntfAdapter->udev, len,
 156                                                GFP_ATOMIC, &urb->transfer_dma);
 157        if (!urb->transfer_buffer) {
 158                BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0,
 159                                "Error allocating memory\n");
 160                return  -ENOMEM;
 161        }
 162        memcpy(urb->transfer_buffer, data, len);
 163        urb->transfer_buffer_length = len;
 164
 165        BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_TX, NEXT_SEND,
 166                        DBG_LVL_ALL, "Sending Bulk out packet\n");
 167        /* For T3B,INT OUT end point will be used as bulk out end point */
 168        if ((psIntfAdapter->psAdapter->chip_id == T3B) &&
 169                        (psIntfAdapter->bHighSpeedDevice == TRUE)) {
 170                usb_fill_int_urb(urb, psIntfAdapter->udev,
 171                        psIntfAdapter->sBulkOut.bulk_out_pipe,
 172                        urb->transfer_buffer, len, write_bulk_callback, pTcb,
 173                        psIntfAdapter->sBulkOut.int_out_interval);
 174        } else {
 175        usb_fill_bulk_urb(urb, psIntfAdapter->udev,
 176                  psIntfAdapter->sBulkOut.bulk_out_pipe,
 177                  urb->transfer_buffer, len, write_bulk_callback, pTcb);
 178        }
 179        urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; /* For DMA transfer */
 180
 181        if (false == psIntfAdapter->psAdapter->device_removed &&
 182           false == psIntfAdapter->psAdapter->bEndPointHalted &&
 183           false == psIntfAdapter->bSuspended &&
 184           false == psIntfAdapter->bPreparingForBusSuspend) {
 185                retval = usb_submit_urb(urb, GFP_ATOMIC);
 186                if (retval) {
 187                        BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_TX,
 188                                        NEXT_SEND, DBG_LVL_ALL,
 189                                        "failed submitting write urb, error %d",
 190                                        retval);
 191                        if (retval == -EPIPE) {
 192                                psIntfAdapter->psAdapter->bEndPointHalted = TRUE;
 193                                wake_up(&psIntfAdapter->psAdapter->tx_packet_wait_queue);
 194                        }
 195                }
 196        }
 197        return retval;
 198}
 199
 200int InterfaceTransmitPacket(PVOID arg, PVOID data, UINT len)
 201{
 202        struct bcm_usb_tcb *pTcb = NULL;
 203        struct bcm_interface_adapter *psIntfAdapter = arg;
 204
 205        pTcb = GetBulkOutTcb(psIntfAdapter);
 206        if (pTcb == NULL) {
 207                BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0,
 208                                "No URB to transmit packet, dropping packet");
 209                return -EFAULT;
 210        }
 211        return TransmitTcb(psIntfAdapter, pTcb, data, len);
 212}
 213
 214