linux/drivers/staging/bcm/InterfaceRx.c
<<
>>
Prefs
   1#include "headers.h"
   2
   3static int SearchVcid(PMINI_ADAPTER Adapter,unsigned short usVcid)
   4{
   5        int iIndex=0;
   6
   7        for(iIndex=(NO_OF_QUEUES-1);iIndex>=0;iIndex--)
   8                if(Adapter->PackInfo[iIndex].usVCID_Value == usVcid)
   9                        return iIndex;
  10        return NO_OF_QUEUES+1;
  11
  12}
  13
  14
  15static PUSB_RCB
  16GetBulkInRcb(PS_INTERFACE_ADAPTER psIntfAdapter)
  17{
  18        PUSB_RCB pRcb = NULL;
  19        UINT index = 0;
  20
  21        if((atomic_read(&psIntfAdapter->uNumRcbUsed) < MAXIMUM_USB_RCB) &&
  22                (psIntfAdapter->psAdapter->StopAllXaction == FALSE))
  23        {
  24                index = atomic_read(&psIntfAdapter->uCurrRcb);
  25                pRcb = &psIntfAdapter->asUsbRcb[index];
  26                pRcb->bUsed = TRUE;
  27                pRcb->psIntfAdapter= psIntfAdapter;
  28                BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "Got Rx desc %d used %d",
  29                        index, atomic_read(&psIntfAdapter->uNumRcbUsed));
  30                index = (index + 1) % MAXIMUM_USB_RCB;
  31                atomic_set(&psIntfAdapter->uCurrRcb, index);
  32                atomic_inc(&psIntfAdapter->uNumRcbUsed);
  33        }
  34        return pRcb;
  35}
  36
  37/*this is receive call back - when pkt avilable for receive (BULK IN- end point)*/
  38static void read_bulk_callback(struct urb *urb)
  39{
  40        struct sk_buff *skb = NULL;
  41        BOOLEAN bHeaderSupressionEnabled = FALSE;
  42        int QueueIndex = NO_OF_QUEUES + 1;
  43        UINT uiIndex=0;
  44        int process_done = 1;
  45        //int idleflag = 0 ;
  46        PUSB_RCB pRcb = (PUSB_RCB)urb->context;
  47        PS_INTERFACE_ADAPTER psIntfAdapter = pRcb->psIntfAdapter;
  48        PMINI_ADAPTER Adapter = psIntfAdapter->psAdapter;
  49        PLEADER pLeader = urb->transfer_buffer;
  50
  51        if (unlikely(netif_msg_rx_status(Adapter)))
  52                pr_info(PFX "%s: rx urb status %d length %d\n",
  53                        Adapter->dev->name, urb->status, urb->actual_length);
  54
  55        if((Adapter->device_removed == TRUE)  ||
  56                (TRUE == Adapter->bEndPointHalted) ||
  57                (0 == urb->actual_length)
  58                )
  59        {
  60                pRcb->bUsed = FALSE;
  61                atomic_dec(&psIntfAdapter->uNumRcbUsed);
  62                return;
  63        }
  64
  65        if(urb->status != STATUS_SUCCESS)
  66        {
  67                if(urb->status == -EPIPE)
  68                {
  69                        Adapter->bEndPointHalted = TRUE ;
  70                        wake_up(&Adapter->tx_packet_wait_queue);
  71                }
  72                else
  73                {
  74                        BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL,"Rx URB has got cancelled. status :%d", urb->status);
  75                }
  76                pRcb->bUsed = FALSE;
  77                atomic_dec(&psIntfAdapter->uNumRcbUsed);
  78                urb->status = STATUS_SUCCESS ;
  79                return ;
  80        }
  81
  82        if(Adapter->bDoSuspend && (Adapter->bPreparingForLowPowerMode))
  83        {
  84                BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL,"device is going in low power mode while PMU option selected..hence rx packet should not be process");
  85                return ;
  86        }
  87
  88        BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "Read back done len %d\n", pLeader->PLength);
  89        if(!pLeader->PLength)
  90        {
  91                BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "Leader Length 0");
  92                atomic_dec(&psIntfAdapter->uNumRcbUsed);
  93                return;
  94        }
  95        BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "Leader Status:0x%hX, Length:0x%hX, VCID:0x%hX", pLeader->Status,pLeader->PLength,pLeader->Vcid);
  96        if(MAX_CNTL_PKT_SIZE < pLeader->PLength)
  97        {
  98                if (netif_msg_rx_err(Adapter))
  99                        pr_info(PFX "%s: corrupted leader length...%d\n",
 100                                Adapter->dev->name, pLeader->PLength);
 101                ++Adapter->dev->stats.rx_dropped;
 102                atomic_dec(&psIntfAdapter->uNumRcbUsed);
 103                return;
 104        }
 105
 106        QueueIndex = SearchVcid( Adapter,pLeader->Vcid);
 107        if(QueueIndex < NO_OF_QUEUES)
 108        {
 109                bHeaderSupressionEnabled =
 110                        Adapter->PackInfo[QueueIndex].bHeaderSuppressionEnabled;
 111                bHeaderSupressionEnabled =
 112                        bHeaderSupressionEnabled & Adapter->bPHSEnabled;
 113        }
 114
 115        skb = dev_alloc_skb (pLeader->PLength + SKB_RESERVE_PHS_BYTES + SKB_RESERVE_ETHERNET_HEADER);//2   //2 for allignment
 116        if(!skb)
 117        {
 118                BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "NO SKBUFF!!! Dropping the Packet");
 119                atomic_dec(&psIntfAdapter->uNumRcbUsed);
 120                return;
 121        }
 122    /* If it is a control Packet, then call handle_bcm_packet ()*/
 123        if((ntohs(pLeader->Vcid) == VCID_CONTROL_PACKET) ||
 124            (!(pLeader->Status >= 0x20  &&  pLeader->Status <= 0x3F)))
 125        {
 126            BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_RX, RX_CTRL, DBG_LVL_ALL, "Recived control pkt...");
 127                *(PUSHORT)skb->data = pLeader->Status;
 128        memcpy(skb->data+sizeof(USHORT), urb->transfer_buffer +
 129                        (sizeof(LEADER)), pLeader->PLength);
 130                skb->len = pLeader->PLength + sizeof(USHORT);
 131
 132                spin_lock(&Adapter->control_queue_lock);
 133                ENQUEUEPACKET(Adapter->RxControlHead,Adapter->RxControlTail,skb);
 134                spin_unlock(&Adapter->control_queue_lock);
 135
 136                atomic_inc(&Adapter->cntrlpktCnt);
 137                wake_up(&Adapter->process_rx_cntrlpkt);
 138        }
 139        else
 140        {
 141                /*
 142                  * Data Packet, Format a proper Ethernet Header
 143                  * and give it to the stack
 144                  */
 145        BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_RX, RX_DATA, DBG_LVL_ALL, "Recived Data pkt...");
 146                skb_reserve(skb, 2 + SKB_RESERVE_PHS_BYTES);
 147                memcpy(skb->data+ETH_HLEN, (PUCHAR)urb->transfer_buffer + sizeof(LEADER), pLeader->PLength);
 148                skb->dev = Adapter->dev;
 149
 150                /* currently skb->len has extra ETH_HLEN bytes in the beginning */
 151                skb_put (skb, pLeader->PLength + ETH_HLEN);
 152                Adapter->PackInfo[QueueIndex].uiTotalRxBytes+=pLeader->PLength;
 153                Adapter->PackInfo[QueueIndex].uiThisPeriodRxBytes+= pLeader->PLength;
 154        BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_RX, RX_DATA, DBG_LVL_ALL, "Recived Data pkt of len :0x%X", pLeader->PLength);
 155
 156                if(netif_running(Adapter->dev))
 157                {
 158                        /* Moving ahead by ETH_HLEN to the data ptr as received from FW */
 159                        skb_pull(skb, ETH_HLEN);
 160                        PHSRecieve(Adapter, pLeader->Vcid, skb, &skb->len,
 161                                        NULL,bHeaderSupressionEnabled);
 162
 163                        if(!Adapter->PackInfo[QueueIndex].bEthCSSupport)
 164                        {
 165                                skb_push(skb, ETH_HLEN);
 166
 167                                memcpy(skb->data, skb->dev->dev_addr, 6);
 168                                memcpy(skb->data+6, skb->dev->dev_addr, 6);
 169                                (*(skb->data+11))++;
 170                                *(skb->data+12) = 0x08;
 171                                *(skb->data+13) = 0x00;
 172                                pLeader->PLength+=ETH_HLEN;
 173                        }
 174
 175                        skb->protocol = eth_type_trans(skb, Adapter->dev);
 176                        process_done = netif_rx(skb);
 177                }
 178                else
 179                {
 180                    BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_RX, RX_DATA, DBG_LVL_ALL, "i/f not up hance freeing SKB...");
 181                        dev_kfree_skb(skb);
 182                }
 183
 184                ++Adapter->dev->stats.rx_packets;
 185                Adapter->dev->stats.rx_bytes += pLeader->PLength;
 186
 187                for(uiIndex = 0 ; uiIndex < MIBS_MAX_HIST_ENTRIES ; uiIndex++)
 188                {
 189                        if((pLeader->PLength <= MIBS_PKTSIZEHIST_RANGE*(uiIndex+1))
 190                                && (pLeader->PLength > MIBS_PKTSIZEHIST_RANGE*(uiIndex)))
 191                                Adapter->aRxPktSizeHist[uiIndex]++;
 192                }
 193        }
 194        Adapter->PrevNumRecvDescs++;
 195        pRcb->bUsed = FALSE;
 196        atomic_dec(&psIntfAdapter->uNumRcbUsed);
 197}
 198
 199static int ReceiveRcb(PS_INTERFACE_ADAPTER psIntfAdapter, PUSB_RCB pRcb)
 200{
 201        struct urb *urb = pRcb->urb;
 202        int retval = 0;
 203
 204        usb_fill_bulk_urb(urb, psIntfAdapter->udev, usb_rcvbulkpipe(
 205                        psIntfAdapter->udev, psIntfAdapter->sBulkIn.bulk_in_endpointAddr),
 206                        urb->transfer_buffer, BCM_USB_MAX_READ_LENGTH, read_bulk_callback,
 207                        pRcb);
 208        if(FALSE == psIntfAdapter->psAdapter->device_removed &&
 209           FALSE == psIntfAdapter->psAdapter->bEndPointHalted &&
 210           FALSE == psIntfAdapter->bSuspended &&
 211           FALSE == psIntfAdapter->bPreparingForBusSuspend)
 212        {
 213                retval = usb_submit_urb(urb, GFP_ATOMIC);
 214                if (retval)
 215                {
 216                        BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "failed submitting read urb, error %d", retval);
 217                        //if this return value is because of pipe halt. need to clear this.
 218                        if(retval == -EPIPE)
 219                        {
 220                                psIntfAdapter->psAdapter->bEndPointHalted = TRUE ;
 221                                wake_up(&psIntfAdapter->psAdapter->tx_packet_wait_queue);
 222                        }
 223
 224                }
 225        }
 226        return retval;
 227}
 228
 229/*
 230Function:                               InterfaceRx
 231
 232Description:                    This is the hardware specific Function for Recieveing
 233                                                data packet/control packets from the device.
 234
 235Input parameters:               IN PMINI_ADAPTER Adapter   - Miniport Adapter Context
 236
 237
 238
 239Return:                         TRUE  - If Rx was successful.
 240                                        Other - If an error occured.
 241*/
 242
 243BOOLEAN InterfaceRx (PS_INTERFACE_ADAPTER psIntfAdapter)
 244{
 245        USHORT RxDescCount = NUM_RX_DESC - atomic_read(&psIntfAdapter->uNumRcbUsed);
 246        PUSB_RCB pRcb = NULL;
 247
 248//      RxDescCount = psIntfAdapter->psAdapter->CurrNumRecvDescs -
 249//                              psIntfAdapter->psAdapter->PrevNumRecvDescs;
 250        while(RxDescCount)
 251        {
 252                pRcb = GetBulkInRcb(psIntfAdapter);
 253                if(pRcb == NULL)
 254                {
 255                        BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Unable to get Rcb pointer");
 256                        return FALSE;
 257                }
 258                //atomic_inc(&psIntfAdapter->uNumRcbUsed);
 259                ReceiveRcb(psIntfAdapter, pRcb);
 260                RxDescCount--;
 261    }
 262        return TRUE;
 263}
 264
 265