diff options
author | Taku Izumi <izumi.taku@jp.fujitsu.com> | 2015-08-21 04:29:32 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-08-24 17:06:36 -0400 |
commit | 8edb62a8131ca5b5ecbb29e45d812d9583585afb (patch) | |
tree | 6bbb849e4b377f358a6d1f1b660e1f4c129c4ad1 | |
parent | 3e3fedda31798cff2cb5358e15263b8799c1e72c (diff) |
fjes: interrupt_watch_task
This patch adds interrupt_watch_task.
This task is used to prevent delay of interrupts.
Signed-off-by: Taku Izumi <izumi.taku@jp.fujitsu.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/fjes/fjes.h | 5 | ||||
-rw-r--r-- | drivers/net/fjes/fjes_main.c | 40 |
2 files changed, 44 insertions, 1 deletions
diff --git a/drivers/net/fjes/fjes.h b/drivers/net/fjes/fjes.h index b04ea9dcab43..1743dbb83e5b 100644 --- a/drivers/net/fjes/fjes.h +++ b/drivers/net/fjes/fjes.h | |||
@@ -32,6 +32,7 @@ | |||
32 | #define FJES_TX_RETRY_TIMEOUT (100) | 32 | #define FJES_TX_RETRY_TIMEOUT (100) |
33 | #define FJES_TX_TX_STALL_TIMEOUT (FJES_TX_RETRY_INTERVAL / 2) | 33 | #define FJES_TX_TX_STALL_TIMEOUT (FJES_TX_RETRY_INTERVAL / 2) |
34 | #define FJES_OPEN_ZONE_UPDATE_WAIT (300) /* msec */ | 34 | #define FJES_OPEN_ZONE_UPDATE_WAIT (300) /* msec */ |
35 | #define FJES_IRQ_WATCH_DELAY (HZ) | ||
35 | 36 | ||
36 | /* board specific private data structure */ | 37 | /* board specific private data structure */ |
37 | struct fjes_adapter { | 38 | struct fjes_adapter { |
@@ -52,10 +53,14 @@ struct fjes_adapter { | |||
52 | bool irq_registered; | 53 | bool irq_registered; |
53 | 54 | ||
54 | struct workqueue_struct *txrx_wq; | 55 | struct workqueue_struct *txrx_wq; |
56 | struct workqueue_struct *control_wq; | ||
55 | 57 | ||
56 | struct work_struct tx_stall_task; | 58 | struct work_struct tx_stall_task; |
57 | struct work_struct raise_intr_rxdata_task; | 59 | struct work_struct raise_intr_rxdata_task; |
58 | 60 | ||
61 | struct delayed_work interrupt_watch_task; | ||
62 | bool interrupt_watch_enable; | ||
63 | |||
59 | struct fjes_hw hw; | 64 | struct fjes_hw hw; |
60 | }; | 65 | }; |
61 | 66 | ||
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c index 4a4ce8144023..5fce33dec820 100644 --- a/drivers/net/fjes/fjes_main.c +++ b/drivers/net/fjes/fjes_main.c | |||
@@ -71,7 +71,7 @@ static int fjes_remove(struct platform_device *); | |||
71 | 71 | ||
72 | static int fjes_sw_init(struct fjes_adapter *); | 72 | static int fjes_sw_init(struct fjes_adapter *); |
73 | static void fjes_netdev_setup(struct net_device *); | 73 | static void fjes_netdev_setup(struct net_device *); |
74 | 74 | static void fjes_irq_watch_task(struct work_struct *); | |
75 | static void fjes_rx_irq(struct fjes_adapter *, int); | 75 | static void fjes_rx_irq(struct fjes_adapter *, int); |
76 | static int fjes_poll(struct napi_struct *, int); | 76 | static int fjes_poll(struct napi_struct *, int); |
77 | 77 | ||
@@ -197,6 +197,13 @@ static int fjes_request_irq(struct fjes_adapter *adapter) | |||
197 | struct net_device *netdev = adapter->netdev; | 197 | struct net_device *netdev = adapter->netdev; |
198 | int result = -1; | 198 | int result = -1; |
199 | 199 | ||
200 | adapter->interrupt_watch_enable = true; | ||
201 | if (!delayed_work_pending(&adapter->interrupt_watch_task)) { | ||
202 | queue_delayed_work(adapter->control_wq, | ||
203 | &adapter->interrupt_watch_task, | ||
204 | FJES_IRQ_WATCH_DELAY); | ||
205 | } | ||
206 | |||
200 | if (!adapter->irq_registered) { | 207 | if (!adapter->irq_registered) { |
201 | result = request_irq(adapter->hw.hw_res.irq, fjes_intr, | 208 | result = request_irq(adapter->hw.hw_res.irq, fjes_intr, |
202 | IRQF_SHARED, netdev->name, adapter); | 209 | IRQF_SHARED, netdev->name, adapter); |
@@ -213,6 +220,9 @@ static void fjes_free_irq(struct fjes_adapter *adapter) | |||
213 | { | 220 | { |
214 | struct fjes_hw *hw = &adapter->hw; | 221 | struct fjes_hw *hw = &adapter->hw; |
215 | 222 | ||
223 | adapter->interrupt_watch_enable = false; | ||
224 | cancel_delayed_work_sync(&adapter->interrupt_watch_task); | ||
225 | |||
216 | fjes_hw_set_irqmask(hw, REG_ICTL_MASK_ALL, true); | 226 | fjes_hw_set_irqmask(hw, REG_ICTL_MASK_ALL, true); |
217 | 227 | ||
218 | if (adapter->irq_registered) { | 228 | if (adapter->irq_registered) { |
@@ -297,6 +307,7 @@ static int fjes_close(struct net_device *netdev) | |||
297 | 307 | ||
298 | fjes_free_irq(adapter); | 308 | fjes_free_irq(adapter); |
299 | 309 | ||
310 | cancel_delayed_work_sync(&adapter->interrupt_watch_task); | ||
300 | cancel_work_sync(&adapter->raise_intr_rxdata_task); | 311 | cancel_work_sync(&adapter->raise_intr_rxdata_task); |
301 | cancel_work_sync(&adapter->tx_stall_task); | 312 | cancel_work_sync(&adapter->tx_stall_task); |
302 | 313 | ||
@@ -996,11 +1007,15 @@ static int fjes_probe(struct platform_device *plat_dev) | |||
996 | adapter->open_guard = false; | 1007 | adapter->open_guard = false; |
997 | 1008 | ||
998 | adapter->txrx_wq = create_workqueue(DRV_NAME "/txrx"); | 1009 | adapter->txrx_wq = create_workqueue(DRV_NAME "/txrx"); |
1010 | adapter->control_wq = create_workqueue(DRV_NAME "/control"); | ||
999 | 1011 | ||
1000 | INIT_WORK(&adapter->tx_stall_task, fjes_tx_stall_task); | 1012 | INIT_WORK(&adapter->tx_stall_task, fjes_tx_stall_task); |
1001 | INIT_WORK(&adapter->raise_intr_rxdata_task, | 1013 | INIT_WORK(&adapter->raise_intr_rxdata_task, |
1002 | fjes_raise_intr_rxdata_task); | 1014 | fjes_raise_intr_rxdata_task); |
1003 | 1015 | ||
1016 | INIT_DELAYED_WORK(&adapter->interrupt_watch_task, fjes_irq_watch_task); | ||
1017 | adapter->interrupt_watch_enable = false; | ||
1018 | |||
1004 | res = platform_get_resource(plat_dev, IORESOURCE_MEM, 0); | 1019 | res = platform_get_resource(plat_dev, IORESOURCE_MEM, 0); |
1005 | hw->hw_res.start = res->start; | 1020 | hw->hw_res.start = res->start; |
1006 | hw->hw_res.size = res->end - res->start + 1; | 1021 | hw->hw_res.size = res->end - res->start + 1; |
@@ -1040,8 +1055,11 @@ static int fjes_remove(struct platform_device *plat_dev) | |||
1040 | struct fjes_adapter *adapter = netdev_priv(netdev); | 1055 | struct fjes_adapter *adapter = netdev_priv(netdev); |
1041 | struct fjes_hw *hw = &adapter->hw; | 1056 | struct fjes_hw *hw = &adapter->hw; |
1042 | 1057 | ||
1058 | cancel_delayed_work_sync(&adapter->interrupt_watch_task); | ||
1043 | cancel_work_sync(&adapter->raise_intr_rxdata_task); | 1059 | cancel_work_sync(&adapter->raise_intr_rxdata_task); |
1044 | cancel_work_sync(&adapter->tx_stall_task); | 1060 | cancel_work_sync(&adapter->tx_stall_task); |
1061 | if (adapter->control_wq) | ||
1062 | destroy_workqueue(adapter->control_wq); | ||
1045 | if (adapter->txrx_wq) | 1063 | if (adapter->txrx_wq) |
1046 | destroy_workqueue(adapter->txrx_wq); | 1064 | destroy_workqueue(adapter->txrx_wq); |
1047 | 1065 | ||
@@ -1077,6 +1095,26 @@ static void fjes_netdev_setup(struct net_device *netdev) | |||
1077 | netdev->features |= NETIF_F_HW_CSUM | NETIF_F_HW_VLAN_CTAG_FILTER; | 1095 | netdev->features |= NETIF_F_HW_CSUM | NETIF_F_HW_VLAN_CTAG_FILTER; |
1078 | } | 1096 | } |
1079 | 1097 | ||
1098 | static void fjes_irq_watch_task(struct work_struct *work) | ||
1099 | { | ||
1100 | struct fjes_adapter *adapter = container_of(to_delayed_work(work), | ||
1101 | struct fjes_adapter, interrupt_watch_task); | ||
1102 | |||
1103 | local_irq_disable(); | ||
1104 | fjes_intr(adapter->hw.hw_res.irq, adapter); | ||
1105 | local_irq_enable(); | ||
1106 | |||
1107 | if (fjes_rxframe_search_exist(adapter, 0) >= 0) | ||
1108 | napi_schedule(&adapter->napi); | ||
1109 | |||
1110 | if (adapter->interrupt_watch_enable) { | ||
1111 | if (!delayed_work_pending(&adapter->interrupt_watch_task)) | ||
1112 | queue_delayed_work(adapter->control_wq, | ||
1113 | &adapter->interrupt_watch_task, | ||
1114 | FJES_IRQ_WATCH_DELAY); | ||
1115 | } | ||
1116 | } | ||
1117 | |||
1080 | /* fjes_init_module - Driver Registration Routine */ | 1118 | /* fjes_init_module - Driver Registration Routine */ |
1081 | static int __init fjes_init_module(void) | 1119 | static int __init fjes_init_module(void) |
1082 | { | 1120 | { |