INT SendControlPacket(PMINI_ADAPTER Adapter, char *pControlPacket) { PLEADER PLeader = (PLEADER)pControlPacket; BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Tx"); if(!pControlPacket || !Adapter) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Got NULL Control Packet or Adapter"); return STATUS_FAILURE; } if((atomic_read( &Adapter->CurrNumFreeTxDesc ) < ((PLeader->PLength-1)/MAX_DEVICE_DESC_SIZE)+1)) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "NO FREE DESCRIPTORS TO SEND CONTROL PACKET"); return STATUS_FAILURE; } BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader Status: %x", PLeader->Status); BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader VCID: %x",PLeader->Vcid); BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader Length: %x",PLeader->PLength); if(Adapter->device_removed) return 0; if (netif_msg_pktdata(Adapter)) print_hex_dump(KERN_DEBUG, PFX "tx control: ", DUMP_PREFIX_NONE, 16, 1, pControlPacket, PLeader->PLength + LEADER_SIZE, 0); Adapter->interface_transmit(Adapter->pvInterfaceAdapter, pControlPacket, (PLeader->PLength + LEADER_SIZE)); atomic_dec(&Adapter->CurrNumFreeTxDesc); BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "<========="); return STATUS_SUCCESS; }
INT SetupNextSend(PMINI_ADAPTER Adapter, struct sk_buff *Packet, USHORT Vcid) { int status=0; BOOLEAN bHeaderSupressionEnabled = FALSE; B_UINT16 uiClassifierRuleID; u16 QueueIndex = skb_get_queue_mapping(Packet); LEADER Leader={0}; if(Packet->len > MAX_DEVICE_DESC_SIZE) { status = STATUS_FAILURE; goto errExit; } uiClassifierRuleID = *((UINT32*) (Packet->cb)+SKB_CB_CLASSIFICATION_OFFSET); bHeaderSupressionEnabled = Adapter->PackInfo[QueueIndex].bHeaderSuppressionEnabled & Adapter->bPHSEnabled; if(Adapter->device_removed) { status = STATUS_FAILURE; goto errExit; } status = PHSTransmit(Adapter, &Packet, Vcid, uiClassifierRuleID, bHeaderSupressionEnabled, (UINT *)&Packet->len, Adapter->PackInfo[QueueIndex].bEthCSSupport); if(status != STATUS_SUCCESS) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "PHS Transmit failed..\n"); goto errExit; } Leader.Vcid = Vcid; if(TCP_ACK == *((UINT32*) (Packet->cb) + SKB_CB_TCPACK_OFFSET )) Leader.Status = LEADER_STATUS_TCP_ACK; else Leader.Status = LEADER_STATUS; if(Adapter->PackInfo[QueueIndex].bEthCSSupport) { Leader.PLength = Packet->len; if(skb_headroom(Packet) < LEADER_SIZE) { if((status = skb_cow(Packet,LEADER_SIZE))) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL,"bcm_transmit : Failed To Increase headRoom\n"); goto errExit; } } skb_push(Packet, LEADER_SIZE); memcpy(Packet->data, &Leader, LEADER_SIZE); } else { Leader.PLength = Packet->len - ETH_HLEN; memcpy((LEADER*)skb_pull(Packet, (ETH_HLEN - LEADER_SIZE)), &Leader, LEADER_SIZE); } status = Adapter->interface_transmit(Adapter->pvInterfaceAdapter, Packet->data, (Leader.PLength + LEADER_SIZE)); if(status) { ++Adapter->dev->stats.tx_errors; if (netif_msg_tx_err(Adapter)) pr_info(PFX "%s: transmit error %d\n", Adapter->dev->name, status); } else { struct net_device_stats *netstats = &Adapter->dev->stats; Adapter->PackInfo[QueueIndex].uiTotalTxBytes += Leader.PLength; netstats->tx_bytes += Leader.PLength; ++netstats->tx_packets; Adapter->PackInfo[QueueIndex].uiCurrentTokenCount -= Leader.PLength << 3; Adapter->PackInfo[QueueIndex].uiSentBytes += (Packet->len); Adapter->PackInfo[QueueIndex].uiSentPackets++; Adapter->PackInfo[QueueIndex].NumOfPacketsSent++; atomic_dec(&Adapter->PackInfo[QueueIndex].uiPerSFTxResourceCount); Adapter->PackInfo[QueueIndex].uiThisPeriodSentBytes += Leader.PLength; } atomic_dec(&Adapter->CurrNumFreeTxDesc); errExit: dev_kfree_skb(Packet); return status; }
/** @ingroup tx_functions This function despatches the IP packets with the given vcid to the target via the host h/w interface. @return zero(success) or -ve value(failure) */ INT SetupNextSend(PMINI_ADAPTER Adapter, /**<Logical Adapter*/ struct sk_buff *Packet, /**<data buffer*/ USHORT Vcid) /**<VCID for this packet*/ { int status=0; #ifdef GDMA_INTERFACE int dontfree = 0; #endif BOOLEAN bHeaderSupressionEnabled = FALSE; B_UINT16 uiClassifierRuleID; int QueueIndex = NO_OF_QUEUES + 1; B_UINT32 time_spent_on_host = 0 ; if(!Adapter || !Packet) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Got NULL Adapter or Packet"); return -EINVAL; } if(Packet->len > MAX_DEVICE_DESC_SIZE) { status = STATUS_FAILURE; goto errExit; } /* Get the Classifier Rule ID */ uiClassifierRuleID = *((UINT32*) (Packet->cb)+SKB_CB_CLASSIFICATION_OFFSET); QueueIndex = SearchVcid( Adapter,Vcid); if(QueueIndex < NO_OF_QUEUES) { bHeaderSupressionEnabled = Adapter->PackInfo[QueueIndex].bHeaderSuppressionEnabled; bHeaderSupressionEnabled = bHeaderSupressionEnabled & Adapter->bPHSEnabled; } if(Adapter->device_removed) { status = STATUS_FAILURE; goto errExit; } status = PHSTransmit(Adapter, &Packet, Vcid, uiClassifierRuleID, bHeaderSupressionEnabled, (UINT *)&Packet->len, Adapter->PackInfo[QueueIndex].bEthCSSupport); if(status != STATUS_SUCCESS) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "PHS Transmit failed..\n"); goto errExit; } Leader.Vcid = Vcid; if(TCP_ACK == *((UINT32*) (Packet->cb) + SKB_CB_TCPACK_OFFSET )) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Sending TCP ACK\n"); Leader.Status = LEADER_STATUS_TCP_ACK; } else { Leader.Status = LEADER_STATUS; } if(Adapter->PackInfo[QueueIndex].bEthCSSupport) { Leader.PLength = Packet->len; if(skb_headroom(Packet) < LEADER_SIZE) { if((status = skb_cow(Packet,LEADER_SIZE))) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL,"bcm_transmit : Failed To Increase headRoom\n"); goto errExit; } } skb_push(Packet, LEADER_SIZE); memcpy(Packet->data, &Leader, LEADER_SIZE); } else { Leader.PLength = Packet->len - ETH_HLEN; memcpy((LEADER*)skb_pull(Packet, (ETH_HLEN - LEADER_SIZE)), &Leader, LEADER_SIZE); } BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Packet->len = %d", Packet->len); BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Vcid = %d", Vcid); #ifndef BCM_SHM_INTERFACE status = Adapter->interface_transmit(Adapter->pvInterfaceAdapter, Packet->data, (Leader.PLength + LEADER_SIZE)); #else status = tx_pkts_to_firmware(Packet,Packet->len,0); #endif if(status) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Tx Failed..\n"); } else { Adapter->PackInfo[QueueIndex].uiTotalTxBytes += Leader.PLength; atomic_add(Leader.PLength, &Adapter->GoodTxByteCount); atomic_inc(&Adapter->TxTotalPacketCount); #ifdef GDMA_INTERFACE dontfree = 1; #endif } time_spent_on_host = jiffies - *((UINT32*) (Packet->cb) + SKB_CB_LATENCY_OFFSET); BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_TIME_SPENT_IN_HOST, DBG_LVL_ALL, "TIME SPENT ON HOST :%#X \n",time_spent_on_host); atomic_dec(&Adapter->CurrNumFreeTxDesc); errExit: if(STATUS_SUCCESS == status) { Adapter->PackInfo[QueueIndex].uiCurrentTokenCount -= Leader.PLength << 3; Adapter->PackInfo[QueueIndex].uiSentBytes += (Packet->len); Adapter->PackInfo[QueueIndex].uiSentPackets++; Adapter->PackInfo[QueueIndex].NumOfPacketsSent++; atomic_dec(&Adapter->PackInfo[QueueIndex].uiPerSFTxResourceCount); #ifdef BCM_SHM_INTERFACE if(atomic_read(&Adapter->PackInfo[QueueIndex].uiPerSFTxResourceCount) < 0) { atomic_set(&Adapter->PackInfo[QueueIndex].uiPerSFTxResourceCount, 0); } #endif Adapter->PackInfo[QueueIndex].uiThisPeriodSentBytes += Leader.PLength; } #ifdef GDMA_INTERFACE if(!dontfree){ bcm_kfree_skb(Packet); } #else bcm_kfree_skb(Packet); #endif return status; }
/** @ingroup ctrl_pkt_functions This function dispatches control packet to the h/w interface @return zero(success) or -ve value(failure) */ INT SendControlPacket(PMINI_ADAPTER Adapter, /**<Logical Adapter*/ char *pControlPacket/**<Control Packet*/ ) { PLEADER PLeader = NULL; struct timeval tv; memset(&tv, 0, sizeof(tv)); BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "========>"); PLeader=(PLEADER)pControlPacket; BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Tx"); if(!pControlPacket || !Adapter) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Got NULL Control Packet or Adapter"); return STATUS_FAILURE; } if((atomic_read( &Adapter->CurrNumFreeTxDesc ) < ((PLeader->PLength-1)/MAX_DEVICE_DESC_SIZE)+1)) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "NO FREE DESCRIPTORS TO SEND CONTROL PACKET"); if(Adapter->bcm_jiffies == 0) { Adapter->bcm_jiffies = jiffies; BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "UPDATED TIME(hex): %u", Adapter->bcm_jiffies); } return STATUS_FAILURE; } /* Update the netdevice statistics */ /* Dump Packet */ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader Status: %x", PLeader->Status); BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader VCID: %x",PLeader->Vcid); BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader Length: %x",PLeader->PLength); if(Adapter->device_removed) return 0; #ifndef BCM_SHM_INTERFACE Adapter->interface_transmit(Adapter->pvInterfaceAdapter, pControlPacket, (PLeader->PLength + LEADER_SIZE)); #else tx_pkts_to_firmware(pControlPacket,(PLeader->PLength + LEADER_SIZE),1); if(PLeader->Status==IDLE_MESSAGE) { if(((CONTROL_MESSAGE*)PLeader)->szData[0] == GO_TO_IDLE_MODE_PAYLOAD && ((CONTROL_MESSAGE*)PLeader)->szData[1] == TARGET_CAN_GO_TO_IDLE_MODE) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Idle Mode Ack Sent to the Device\n"); BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Host Entering into Idle Mode\n"); do_gettimeofday(&tv); BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "IdleMode Msg sent to f/w at time :%ld ms", tv.tv_sec *1000 + tv.tv_usec /1000); if(Adapter->bDoSuspend != TRUE) { Adapter->IdleMode = TRUE; Adapter->bPreparingForLowPowerMode = FALSE ; } } } if((PLeader->Status == LINK_UP_CONTROL_REQ) && ((PUCHAR)pControlPacket)[sizeof(LEADER)] == LINK_UP_ACK && ((PUCHAR)pControlPacket)[sizeof(LEADER)+1] == LINK_SHUTDOWN_REQ_FROM_FIRMWARE && ((PUCHAR)pControlPacket)[sizeof(LEADER)+2] == SHUTDOWN_ACK_FROM_DRIVER) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Shut Down ACK Sent and Host entering Shut State \n"); if(Adapter->bDoSuspend != TRUE) { Adapter->bShutStatus = TRUE; Adapter->bPreparingForLowPowerMode = FALSE; Adapter->bTriedToWakeUpFromlowPowerMode = FALSE; } } #endif ((PLINUX_DEP_DATA)Adapter->pvOsDepData)->netstats.tx_packets++; ((PLINUX_DEP_DATA)Adapter->pvOsDepData)->netstats.tx_bytes+= PLeader->PLength; atomic_dec(&Adapter->CurrNumFreeTxDesc); BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "<========="); return STATUS_SUCCESS; }