Message ID | 1435114554-7151-11-git-send-email-izumi.taku@jp.fujitsu.com (mailing list archive) |
---|---|
State | Not Applicable, archived |
Headers | show |
Hi Izum-san, On Wed, 24 Jun 2015 11:55:42 +0900 Taku Izumi <izumi.taku@jp.fujitsu.com> wrote: > 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@jp.fujitsu.com> > --- > 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++) { Why do you loop 5 times? Thanks, Yasuaki Ishimatsu > + 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@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
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);
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@jp.fujitsu.com> --- drivers/net/fjes/fjes.h | 2 ++ drivers/net/fjes/fjes_main.c | 63 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+)