/* * low_level_output(): * * Should do the actual transmission of the packet. The packet is * contained in the pbuf that is passed to the function. This pbuf * might be chained. * */ static err_t low_level_output(struct netif *netif, struct pbuf *p) { SYS_ARCH_DECL_PROTECT(lev); struct xemac_s *xemac = (struct xemac_s *)(netif->state); xemacliteif_s *xemacliteif = (xemacliteif_s *)(xemac->state); XEmacLite *instance = xemacliteif->instance; struct pbuf *q; SYS_ARCH_PROTECT(lev); /* check if space is available to send */ if (XEmacLite_TxBufferAvailable(instance) == TRUE) { if (pq_qlength(xemacliteif->send_q)) { /* send backlog */ _unbuffered_low_level_output(instance, (struct pbuf *)pq_dequeue(xemacliteif->send_q)); } else { /* send current */ _unbuffered_low_level_output(instance, p); SYS_ARCH_UNPROTECT(lev); return ERR_OK; } } /* if we cannot send the packet immediately, then make a copy of the whole packet * into a separate pbuf and store it in send_q. We cannot enqueue the pbuf as is * since parts of the pbuf may be modified inside lwIP. */ q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_POOL); if (!q) { #if LINK_STATS lwip_stats.link.drop++; #endif SYS_ARCH_UNPROTECT(lev); return ERR_MEM; } for (q->len = 0; p; p = p->next) { memcpy(q->payload + q->len, p->payload, p->len); q->len += p->len; } if (pq_enqueue(xemacliteif->send_q, (void *)q) < 0) { #if LINK_STATS lwip_stats.link.drop++; #endif SYS_ARCH_UNPROTECT(lev); return ERR_MEM; } SYS_ARCH_UNPROTECT(lev); return ERR_OK; }
static err_t low_level_output(struct netif *netif, struct pbuf *p) { SYS_ARCH_DECL_PROTECT(lev); err_t err; struct xemac_s *xemac = (struct xemac_s *)(netif->state); xlltemacif_s *xlltemacif = (xlltemacif_s *)(xemac->state); SYS_ARCH_PROTECT(lev); /* check if space is available to send */ if (is_tx_space_available(xlltemacif)) { _unbuffered_low_level_output(xlltemacif, p); err = ERR_OK; } else { #if LINK_STATS lwip_stats.link.drop++; #endif print("pack dropped, no space\r\n"); err = ERR_MEM; } SYS_ARCH_UNPROTECT(lev); return err; }
static void xemacif_send_handler(void *arg) { struct xemac_s *xemac = (struct xemac_s *)(arg); xemacliteif_s *xemacliteif = (xemacliteif_s *)(xemac->state); XEmacLite *instance = xemacliteif->instance; struct xtopology_t *xtopologyp = &xtopology[xemac->topology_index]; XIntc_AckIntr(xtopologyp->intc_baseaddr, 1 << xtopologyp->intc_emac_intr); if (pq_qlength(xemacliteif->send_q) && (XEmacLite_TxBufferAvailable(instance) == XTRUE)) { struct pbuf *p = pq_dequeue(xemacliteif->send_q); _unbuffered_low_level_output(instance, p); pbuf_free(p); } }
static err_t low_level_output(struct netif *netif, struct pbuf *p) { SYS_ARCH_DECL_PROTECT(lev); err_t err; struct xemac_s *xemac = (struct xemac_s *)(netif->state); xaxiemacif_s *xaxiemacif = (xaxiemacif_s *)(xemac->state); /* * With AXI Ethernet on Zynq, we observed unexplained delays for * BD Status update. As a result, we are hitting a condition where * there are no BDs free to transmit packets. So, we have added * this logic where we look for the status update in a definite * loop. */ XAxiDma_BdRing *txring = XAxiDma_GetTxRing(&xaxiemacif->axidma); int count = 100; SYS_ARCH_PROTECT(lev); while (count) { /* check if space is available to send */ if (is_tx_space_available(xaxiemacif)) { _unbuffered_low_level_output(xaxiemacif, p); err = ERR_OK; break; } else { #if LINK_STATS lwip_stats.link.drop++; #endif process_sent_bds(txring); count--; } } if (count == 0) { print("pack dropped, no space\r\n"); err = ERR_MEM; } SYS_ARCH_UNPROTECT(lev); return err; }