int epping_tx_send(adf_nbuf_t skb, epping_adapter_t *pAdapter) { adf_nbuf_t nodrop_skb; EPPING_HEADER *eppingHdr; A_UINT8 ac = 0; eppingHdr = (EPPING_HEADER *)adf_nbuf_data(skb); if (!IS_EPPING_PACKET(eppingHdr)) { EPPING_LOG(VOS_TRACE_LEVEL_FATAL, "%s: Recived non endpoint ping packets\n", __func__); /* no packet to send, cleanup */ adf_nbuf_free(skb); return -ENOMEM; } /* the stream ID is mapped to an access class */ ac = eppingHdr->StreamNo_h; /* hard coded two ep ids */ if (ac != 0 && ac != 1) { EPPING_LOG(VOS_TRACE_LEVEL_FATAL, "%s: ac %d is not mapped to mboxping service\n", __func__, ac); adf_nbuf_free(skb); return -ENOMEM; } /* * some EPPING packets cannot be dropped no matter what access class * it was sent on. A special care has been taken: * 1. when there is no TX resource, queue the control packets to * a special queue * 2. when there is TX resource, send the queued control packets first * and then other packets * 3. a timer launches to check if there is queued control packets and * flush them */ /* check the nodrop queue first */ while ((nodrop_skb = adf_nbuf_queue_remove(&pAdapter->nodrop_queue))) { HTCSetNodropPkt(pAdapter->pEpping_ctx->HTCHandle, TRUE); if (epping_tx_send_int(nodrop_skb, pAdapter)) { EPPING_LOG(VOS_TRACE_LEVEL_FATAL, "%s: nodrop: %p xmit fail\n", __func__, nodrop_skb); /* fail to xmit so put the nodrop packet to the nodrop queue */ adf_nbuf_queue_insert_head(&pAdapter->nodrop_queue, nodrop_skb); /* no cookie so free the current skb */ goto tx_fail; } else { HTCSetNodropPkt(pAdapter->pEpping_ctx->HTCHandle, FALSE); EPPING_LOG(VOS_TRACE_LEVEL_INFO, "%s: nodrop: %p xmit ok\n", __func__, nodrop_skb); } } /* send the original packet */ if (epping_tx_send_int(skb, pAdapter)) goto tx_fail; return 0; tx_fail: if (!IS_EPING_PACKET_NO_DROP(eppingHdr)) { /* allow to drop the skb so drop it */ adf_nbuf_free(skb); ++pAdapter->stats.tx_dropped; EPPING_LOG(VOS_TRACE_LEVEL_FATAL, "%s: Tx skb %p dropped, stats.tx_dropped = %ld\n", __func__, skb, pAdapter->stats.tx_dropped); return -ENOMEM; } else { EPPING_LOG(VOS_TRACE_LEVEL_FATAL, "%s: nodrop: %p queued\n", __func__, skb); adf_nbuf_queue_add(&pAdapter->nodrop_queue, skb); adf_os_spin_lock_bh(&pAdapter->data_lock); if (pAdapter->epping_timer_state != EPPING_TX_TIMER_RUNNING) { pAdapter->epping_timer_state = EPPING_TX_TIMER_RUNNING; adf_os_timer_mod(&pAdapter->epping_timer, TX_RETRY_TIMEOUT_IN_MS); } adf_os_spin_unlock_bh(&pAdapter->data_lock); } return 0; }
A_STATUS hci_test_send(AR_SOFTC_T *ar, struct sk_buff *skb) #endif { int status = A_OK; int length; EPPING_HEADER *pHeader; HTC_PACKET *pPacket; HTC_TX_TAG htc_tag = AR6K_DATA_PKT_TAG; #ifdef EXPORT_HCI_BRIDGE_INTERFACE AR6K_HCI_BRIDGE_INFO *pHcidevInfo = g_pHcidevInfo; #else AR6K_HCI_BRIDGE_INFO *pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)ar->hcidev_info; #endif do { if (NULL == pHcidevInfo) { status = A_ERROR; break; } if (NULL == pHcidevInfo->pHCIDev) { status = A_ERROR; break; } if (pHcidevInfo->HciNormalMode) { /* this interface cannot run when normal WMI is running */ status = A_ERROR; break; } pHeader = (EPPING_HEADER *)A_NETBUF_DATA(skb); if (!IS_EPPING_PACKET(pHeader)) { status = A_EINVAL; break; } if (IS_EPING_PACKET_NO_DROP(pHeader)) { htc_tag = AR6K_CONTROL_PKT_TAG; } length = sizeof(EPPING_HEADER) + pHeader->DataLength; pPacket = AllocHTCStruct(pHcidevInfo); if (NULL == pPacket) { status = A_NO_MEMORY; break; } SET_HTC_PACKET_INFO_TX(pPacket, skb, A_NETBUF_DATA(skb), length, HCI_ACL_TYPE, /* send every thing out as ACL */ htc_tag); HCI_TransportSendPkt(pHcidevInfo->pHCIDev,pPacket,FALSE); pPacket = NULL; } while (FALSE); return status; }