static void fjes_tx_stall_task(struct work_struct *work) { struct fjes_adapter *adapter = container_of(work, struct fjes_adapter, tx_stall_task); struct net_device *netdev = adapter->netdev; struct fjes_hw *hw = &adapter->hw; int all_queue_available, sendable; enum ep_partner_status pstatus; int max_epid, my_epid, epid; union ep_buffer_info *info; int i; if (((long)jiffies - dev_trans_start(netdev)) > FJES_TX_TX_STALL_TIMEOUT) { netif_wake_queue(netdev); return; } my_epid = hw->my_epid; max_epid = hw->max_epid; for (i = 0; i < 5; i++) { all_queue_available = 1; for (epid = 0; epid < max_epid; epid++) { if (my_epid == epid) continue; pstatus = fjes_hw_get_partner_ep_status(hw, epid); sendable = (pstatus == EP_PARTNER_SHARED); if (!sendable) continue; info = adapter->hw.ep_shm_info[epid].tx.info; if (!(info->v1i.rx_status & FJES_RX_MTU_CHANGING_DONE)) return; if (EP_RING_FULL(info->v1i.head, info->v1i.tail, info->v1i.count_max)) { all_queue_available = 0; break; } } if (all_queue_available) { netif_wake_queue(netdev); return; } } usleep_range(50, 100); queue_work(adapter->txrx_wq, &adapter->tx_stall_task); }
int fjes_hw_epbuf_tx_pkt_send(struct epbuf_handler *epbh, void *frame, size_t size) { union ep_buffer_info *info = epbh->info; struct esmem_frame *ring_frame; if (EP_RING_FULL(info->v1i.head, info->v1i.tail, info->v1i.count_max)) return -ENOBUFS; ring_frame = (struct esmem_frame *)&(epbh->ring[EP_RING_INDEX (info->v1i.tail - 1, info->v1i.count_max) * info->v1i.frame_max]); ring_frame->frame_size = size; memcpy((void *)(ring_frame->frame_data), (void *)frame, size); EP_RING_INDEX_INC(epbh->info->v1i.tail, info->v1i.count_max); return 0; }