static void RefillRecvBuffers(struct ar6k_hci_bridge_info *pHcidevInfo, HCI_TRANSPORT_PACKET_TYPE Type, int NumBuffers) { int length, i; void *osBuf = NULL; struct htc_packet_queue queue; struct htc_packet *pPacket; INIT_HTC_PACKET_QUEUE(&queue); if (Type == HCI_ACL_TYPE) { if (pHcidevInfo->HciNormalMode) { length = HCI_MAX_FRAME_SIZE; } else { length = MAX_ACL_RECV_LENGTH; } } else { length = MAX_EVT_RECV_LENGTH; } /* add on transport head and tail room */ length += pHcidevInfo->HCIProps.HeadRoom + pHcidevInfo->HCIProps.TailRoom; /* round up to the required I/O padding */ length = BLOCK_ROUND_UP_PWR2(length,pHcidevInfo->HCIProps.IOBlockPad); for (i = 0; i < NumBuffers; i++) { if (pHcidevInfo->HciNormalMode) { osBuf = bt_alloc_buffer(pHcidevInfo,length); } else { osBuf = A_NETBUF_ALLOC(length); } if (NULL == osBuf) { break; } pPacket = AllocHTCStruct(pHcidevInfo); if (NULL == pPacket) { FreeBtOsBuf(pHcidevInfo,osBuf); AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to alloc HTC struct \n")); break; } SET_HTC_PACKET_INFO_RX_REFILL(pPacket,osBuf,A_NETBUF_DATA(osBuf),length,Type); /* add to queue */ HTC_PACKET_ENQUEUE(&queue,pPacket); } if (i > 0) { HCI_TransportAddReceivePkts(pHcidevInfo->pHCIDev, &queue); } }
static void ar6000_hci_send_complete(void *pContext, HTC_PACKET *pPacket) { AR6K_HCI_BRIDGE_INFO *pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)pContext; void *osbuf = pPacket->pPktContext; A_ASSERT(osbuf != NULL); A_ASSERT(pHcidevInfo != NULL); if (A_FAILED(pPacket->Status)) { if ((pPacket->Status != A_ECANCELED) && (pPacket->Status != A_NO_RESOURCE)) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: Send Packet Failed: %d \n",pPacket->Status)); } } FreeHTCStruct(pHcidevInfo,pPacket); FreeBtOsBuf(pHcidevInfo,osbuf); }
static void ar6000_hci_pkt_recv(void *pContext, HTC_PACKET *pPacket) { AR6K_HCI_BRIDGE_INFO *pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)pContext; struct sk_buff *skb; AR_SOFTC_DEV_T *arDev = pHcidevInfo->ar->arDev[0]; A_ASSERT(pHcidevInfo != NULL); skb = (struct sk_buff *)pPacket->pPktContext; A_ASSERT(skb != NULL); do { if (A_FAILED(pPacket->Status)) { break; } AR_DEBUG_PRINTF(ATH_DEBUG_HCI_RECV, ("HCI Bridge, packet received type : %d len:%d \n", HCI_GET_PACKET_TYPE(pPacket),pPacket->ActualLength)); /* set the actual buffer position in the os buffer, HTC recv buffers posted to HCI are set * to fill the front of the buffer */ A_NETBUF_PUT(skb,pPacket->ActualLength + pHcidevInfo->HCIProps.HeadRoom); A_NETBUF_PULL(skb,pHcidevInfo->HCIProps.HeadRoom); if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_HCI_DUMP)) { AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("<<< Recv HCI %s packet len:%d \n", (HCI_GET_PACKET_TYPE(pPacket) == HCI_EVENT_TYPE) ? "EVENT" : "ACL", skb->len)); AR_DEBUG_PRINTBUF(skb->data, skb->len,"BT HCI RECV Packet Dump"); } if (pHcidevInfo->HciNormalMode) { /* indicate the packet */ if (bt_indicate_recv(pHcidevInfo,HCI_GET_PACKET_TYPE(pPacket),skb)) { /* bt stack accepted the packet */ skb = NULL; } break; } /* for testing, indicate packet to the network stack */ #ifdef EXPORT_HCI_BRIDGE_INTERFACE skb->dev = (struct net_device *)(pHcidevInfo->HCITransHdl.netDevice); if ((((struct net_device *)pHcidevInfo->HCITransHdl.netDevice)->flags & IFF_UP) == IFF_UP) { skb->protocol = eth_type_trans(skb, (struct net_device *)(pHcidevInfo->HCITransHdl.netDevice)); #else skb->dev = arDev->arNetDev; if ((arDev->arNetDev->flags & IFF_UP) == IFF_UP) { skb->protocol = eth_type_trans(skb, arDev->arNetDev); #endif netif_rx(skb); skb = NULL; } } while (FALSE); FreeHTCStruct(pHcidevInfo,pPacket); if (skb != NULL) { /* packet was not accepted, free it */ FreeBtOsBuf(pHcidevInfo,skb); } } static void ar6000_hci_pkt_refill(void *pContext, HCI_TRANSPORT_PACKET_TYPE Type, int BuffersAvailable) { AR6K_HCI_BRIDGE_INFO *pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)pContext; int refillCount; if (Type == HCI_ACL_TYPE) { refillCount = MAX_ACL_RECV_BUFS - BuffersAvailable; } else { refillCount = MAX_EVT_RECV_BUFS - BuffersAvailable; } if (refillCount > 0) { RefillRecvBuffers(pHcidevInfo,Type,refillCount); } }