This patch adds tx_stall_task. When receiver's buffer is full, sender stops its tx queue. This task is used to monitor receiver's status and when receiver's buffer is avairable, it resumes tx queue. Signed-off-by: Taku Izumi <izumi.taku@xxxxxxxxxxxxxx> --- drivers/net/fjes/fjes.h | 2 ++ drivers/net/fjes/fjes_main.c | 63 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/drivers/net/fjes/fjes.h b/drivers/net/fjes/fjes.h index 8e9899e..b04ea9d 100644 --- a/drivers/net/fjes/fjes.h +++ b/drivers/net/fjes/fjes.h @@ -30,6 +30,7 @@ #define FJES_MAX_QUEUES 1 #define FJES_TX_RETRY_INTERVAL (20 * HZ) #define FJES_TX_RETRY_TIMEOUT (100) +#define FJES_TX_TX_STALL_TIMEOUT (FJES_TX_RETRY_INTERVAL / 2) #define FJES_OPEN_ZONE_UPDATE_WAIT (300) /* msec */ /* board specific private data structure */ @@ -52,6 +53,7 @@ struct fjes_adapter { struct workqueue_struct *txrx_wq; + struct work_struct tx_stall_task; struct work_struct raise_intr_rxdata_task; struct fjes_hw hw; diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c index 735aa5e..f4c2445 100644 --- a/drivers/net/fjes/fjes_main.c +++ b/drivers/net/fjes/fjes_main.c @@ -53,6 +53,7 @@ static int fjes_setup_resources(struct fjes_adapter *); static void fjes_free_resources(struct fjes_adapter *); static netdev_tx_t fjes_xmit_frame(struct sk_buff *, struct net_device *); static void fjes_raise_intr_rxdata_task(struct work_struct *); +static void fjes_tx_stall_task(struct work_struct *); static irqreturn_t fjes_intr(int, void*); static int fjes_acpi_add(struct acpi_device *); @@ -281,6 +282,7 @@ static int fjes_close(struct net_device *netdev) fjes_free_irq(adapter); cancel_work_sync(&adapter->raise_intr_rxdata_task); + cancel_work_sync(&adapter->tx_stall_task); fjes_hw_wait_epstop(hw); @@ -410,6 +412,61 @@ static void fjes_free_resources(struct fjes_adapter *adapter) } } +static void fjes_tx_stall_task(struct work_struct *work) +{ + struct fjes_adapter *adapter = container_of(work, + struct fjes_adapter, tx_stall_task); + struct fjes_hw *hw = &adapter->hw; + struct net_device *netdev = adapter->netdev; + enum ep_partner_status pstatus; + int epid; + int max_epid, my_epid; + union ep_buffer_info *info; + int all_queue_available; + int i; + int sendable; + + if (((long)jiffies - + (long)(netdev->trans_start)) > 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 (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); +} + static void fjes_raise_intr_rxdata_task(struct work_struct *work) { struct fjes_adapter *adapter = container_of(work, @@ -606,6 +663,10 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev) netdev->trans_start = jiffies; netif_tx_stop_queue(cur_queue); + if (!work_pending(&adapter->tx_stall_task)) + queue_work(adapter->txrx_wq, + &adapter->tx_stall_task); + ret = NETDEV_TX_BUSY; } } else { @@ -690,6 +751,7 @@ static int fjes_probe(struct platform_device *plat_dev) adapter->txrx_wq = create_workqueue(DRV_NAME "/txrx"); + INIT_WORK(&adapter->tx_stall_task, fjes_tx_stall_task); INIT_WORK(&adapter->raise_intr_rxdata_task, fjes_raise_intr_rxdata_task); @@ -734,6 +796,7 @@ static int fjes_remove(struct platform_device *plat_dev) struct fjes_hw *hw = &adapter->hw; cancel_work_sync(&adapter->raise_intr_rxdata_task); + cancel_work_sync(&adapter->tx_stall_task); if (adapter->txrx_wq) destroy_workqueue(adapter->txrx_wq); -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html