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); } }
/* Custom_Api_Send - Entry point for MQX driver interface to send a packet. * This is specific to MQX. This function is NOT called from within the * driver. * QCA_CONTEXT_STRUCT_PTR qca_ptr - the MQX driver context. * PCB_PTR pcb_ptr - the MQX packet object. * uint32_t size - the length in bytes of pcb_ptr. * uint32_t frags - the number of fragments in pcb_ptr. * uint32_t flags - optional flags for transmit. *****************************************************************************/ uint32_t Custom_Api_Send(QCA_CONTEXT_STRUCT_PTR qca_ptr, /* [IN] the Ethernet state structure */ PCB_PTR pcb_ptr, /* [IN] the packet to send */ uint32_t size, /* [IN] total size of the packet */ uint32_t frags, /* [IN] total fragments in the packet */ uint32_t flags /* [IN] optional flags, zero = default */ ) { uint32_t error = QCA_OK; A_NETBUF *a_netbuf_ptr; UNUSED_ARGUMENT(flags); UNUSED_ARGUMENT(size); #if 0 if(g_sampleTotAlloc != g_totAlloc){ A_PRINTF("send alloc: %d\n", g_totAlloc); g_sampleTotAlloc = g_totAlloc; } #endif /* create an atheros pcb and continue or fail. */ do { /* provide enough space in the top buffer to store the 14 byte * header which will be copied from its position in the original * buffer. this will allow wmi_dix_2_dot3() to function properly. */ if ((a_netbuf_ptr = (A_NETBUF *)A_NETBUF_ALLOC(sizeof(ATH_MAC_HDR))) == NULL) { error = ENETERR_ALLOC_PCB; break; } a_netbuf_ptr->num_frags = (uint8_t)frags; /* HACK: copy the first part of the fragment to the new buf in order to allow * wmi_dix_2_dot3() to function properly. */ A_ASSERT(pcb_ptr->FRAG[0].LENGTH >= sizeof(ATH_MAC_HDR)); A_NETBUF_PUT_DATA(a_netbuf_ptr, (uint8_t *)pcb_ptr->FRAG[0].FRAGMENT, sizeof(ATH_MAC_HDR)); /*(char*)pcb_ptr->FRAG[0].FRAGMENT += sizeof(ATH_MAC_HDR);*/ pcb_ptr->FRAG[0].FRAGMENT = (uint8_t *)((uint32_t)pcb_ptr->FRAG[0].FRAGMENT + sizeof(ATH_MAC_HDR)); pcb_ptr->FRAG[0].LENGTH -= sizeof(ATH_MAC_HDR); // ensure there is enough headroom to complete the tx operation if (A_NETBUF_HEADROOM(a_netbuf_ptr) < sizeof(ATH_MAC_HDR) + sizeof(ATH_LLC_SNAP_HDR) + sizeof(WMI_DATA_HDR) + HTC_HDR_LENGTH + WMI_MAX_TX_META_SZ) { error = ENETERR_ALLOC_PCB; break; } // carry the original around until completion. // it is freed by A_NETBUF_FREE a_netbuf_ptr->native_orig = pcb_ptr; if (A_OK != Api_DataTxStart((void *)qca_ptr->MAC_CONTEXT_PTR, (void *)a_netbuf_ptr)) { error = QCA_ERROR; break; } } while (0); if (error != QCA_OK) { /* in the event of api failure, the original pcb should be returned to the caller un-touched * and the a_netbuf_ptr should be freed */ a_netbuf_ptr->native_orig = NULL; A_NETBUF_FREE((void *)a_netbuf_ptr); } return error; }