bf038a5991b44c7e2cb65dec7bc3082ddcb8ec34
[librecmc/librecmc.git] /
1 From 175c2548332b45b144af673e70fdbb1a947d7aba Mon Sep 17 00:00:00 2001
2 From: Stanislaw Gruszka <sgruszka@redhat.com>
3 Date: Sat, 9 Feb 2019 12:08:35 +0100
4 X-Patchwork-Submitter: Stanislaw Gruszka <sgruszka@redhat.com>
5 X-Patchwork-Id: 10804445
6 X-Patchwork-Delegate: kvalo@adurom.com
7 Subject: [PATCH 25/28] rt2800mmio: use timer and work for handling tx statuses
8  timeouts
9
10 Sometimes we can get into situation when there are pending statuses,
11 but we do not get INT_SOURCE_CSR_TX_FIFO_STATUS. Handle this situation
12 by arming timeout timer and read statuses (it will fix case when
13 we just do not have irq) and queue work to handle case we missed
14 statues from hardware FIFO.
15
16 Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
17 ---
18  .../net/wireless/ralink/rt2x00/rt2800mmio.c   | 81 +++++++++++++++++--
19  .../net/wireless/ralink/rt2x00/rt2800mmio.h   |  1 +
20  .../net/wireless/ralink/rt2x00/rt2800pci.c    |  2 +-
21  .../net/wireless/ralink/rt2x00/rt2800soc.c    |  2 +-
22  .../net/wireless/ralink/rt2x00/rt2x00dev.c    |  4 +
23  5 files changed, 82 insertions(+), 8 deletions(-)
24
25 --- a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
26 +++ b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
27 @@ -426,6 +426,9 @@ void rt2800mmio_start_queue(struct data_
28  }
29  EXPORT_SYMBOL_GPL(rt2800mmio_start_queue);
30  
31 +/* 200 ms */
32 +#define TXSTATUS_TIMEOUT 200000000
33 +
34  void rt2800mmio_kick_queue(struct data_queue *queue)
35  {
36         struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
37 @@ -440,6 +443,8 @@ void rt2800mmio_kick_queue(struct data_q
38                 entry = rt2x00queue_get_entry(queue, Q_INDEX);
39                 rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX(queue->qid),
40                                           entry->entry_idx);
41 +               hrtimer_start(&rt2x00dev->txstatus_timer,
42 +                             TXSTATUS_TIMEOUT, HRTIMER_MODE_REL);
43                 break;
44         case QID_MGMT:
45                 entry = rt2x00queue_get_entry(queue, Q_INDEX);
46 @@ -484,12 +489,8 @@ void rt2800mmio_flush_queue(struct data_
47                  * For TX queues schedule completion tasklet to catch
48                  * tx status timeouts, othewise just wait.
49                  */
50 -               if (tx_queue) {
51 -                       tasklet_disable(&rt2x00dev->txstatus_tasklet);
52 -                       rt2800_txdone(rt2x00dev, UINT_MAX);
53 -                       rt2800_txdone_nostatus(rt2x00dev);
54 -                       tasklet_enable(&rt2x00dev->txstatus_tasklet);
55 -               }
56 +               if (tx_queue)
57 +                       queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
58  
59                 /*
60                  * Wait for a little while to give the driver
61 @@ -627,6 +628,10 @@ void rt2800mmio_clear_entry(struct queue
62                 word = rt2x00_desc_read(entry_priv->desc, 1);
63                 rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 1);
64                 rt2x00_desc_write(entry_priv->desc, 1, word);
65 +
66 +               /* If last entry stop txstatus timer */
67 +               if (entry->queue->length == 1)
68 +                       hrtimer_cancel(&rt2x00dev->txstatus_timer);
69         }
70  }
71  EXPORT_SYMBOL_GPL(rt2800mmio_clear_entry);
72 @@ -759,6 +764,70 @@ int rt2800mmio_enable_radio(struct rt2x0
73  }
74  EXPORT_SYMBOL_GPL(rt2800mmio_enable_radio);
75  
76 +static void rt2800mmio_work_txdone(struct work_struct *work)
77 +{
78 +       struct rt2x00_dev *rt2x00dev =
79 +           container_of(work, struct rt2x00_dev, txdone_work);
80 +
81 +       if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
82 +               return;
83 +
84 +       while (!kfifo_is_empty(&rt2x00dev->txstatus_fifo) ||
85 +              rt2800_txstatus_timeout(rt2x00dev)) {
86 +
87 +               tasklet_disable(&rt2x00dev->txstatus_tasklet);
88 +               rt2800_txdone(rt2x00dev, UINT_MAX);
89 +               rt2800_txdone_nostatus(rt2x00dev);
90 +               tasklet_enable(&rt2x00dev->txstatus_tasklet);
91 +       }
92 +
93 +       if (rt2800_txstatus_pending(rt2x00dev))
94 +               hrtimer_start(&rt2x00dev->txstatus_timer,
95 +                             TXSTATUS_TIMEOUT, HRTIMER_MODE_REL);
96 +}
97 +
98 +static enum hrtimer_restart rt2800mmio_tx_sta_fifo_timeout(struct hrtimer *timer)
99 +{
100 +       struct rt2x00_dev *rt2x00dev =
101 +           container_of(timer, struct rt2x00_dev, txstatus_timer);
102 +
103 +       if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
104 +               goto out;
105 +
106 +       if (!rt2800_txstatus_pending(rt2x00dev))
107 +               goto out;
108 +
109 +       rt2800mmio_fetch_txstatus(rt2x00dev);
110 +       if (!kfifo_is_empty(&rt2x00dev->txstatus_fifo))
111 +               tasklet_schedule(&rt2x00dev->txstatus_tasklet);
112 +       else
113 +               queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
114 +out:
115 +       return HRTIMER_NORESTART;
116 +}
117 +
118 +int rt2800mmio_probe_hw(struct rt2x00_dev *rt2x00dev)
119 +{
120 +       int retval;
121 +
122 +       retval = rt2800_probe_hw(rt2x00dev);
123 +       if (retval)
124 +               return retval;
125 +
126 +       /*
127 +        * Set txstatus timer function.
128 +        */
129 +       rt2x00dev->txstatus_timer.function = rt2800mmio_tx_sta_fifo_timeout;
130 +
131 +       /*
132 +        * Overwrite TX done handler
133 +        */
134 +       INIT_WORK(&rt2x00dev->txdone_work, rt2800mmio_work_txdone);
135 +
136 +       return 0;
137 +}
138 +EXPORT_SYMBOL_GPL(rt2800mmio_probe_hw);
139 +
140  MODULE_AUTHOR(DRV_PROJECT);
141  MODULE_VERSION(DRV_VERSION);
142  MODULE_DESCRIPTION("rt2800 MMIO library");
143 --- a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.h
144 +++ b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.h
145 @@ -153,6 +153,7 @@ void rt2800mmio_stop_queue(struct data_q
146  void rt2800mmio_queue_init(struct data_queue *queue);
147  
148  /* Initialization functions */
149 +int rt2800mmio_probe_hw(struct rt2x00_dev *rt2x00dev);
150  bool rt2800mmio_get_entry_state(struct queue_entry *entry);
151  void rt2800mmio_clear_entry(struct queue_entry *entry);
152  int rt2800mmio_init_queues(struct rt2x00_dev *rt2x00dev);
153 --- a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
154 +++ b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
155 @@ -346,7 +346,7 @@ static const struct rt2x00lib_ops rt2800
156         .tbtt_tasklet           = rt2800mmio_tbtt_tasklet,
157         .rxdone_tasklet         = rt2800mmio_rxdone_tasklet,
158         .autowake_tasklet       = rt2800mmio_autowake_tasklet,
159 -       .probe_hw               = rt2800_probe_hw,
160 +       .probe_hw               = rt2800mmio_probe_hw,
161         .get_firmware_name      = rt2800pci_get_firmware_name,
162         .check_firmware         = rt2800_check_firmware,
163         .load_firmware          = rt2800_load_firmware,
164 --- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
165 +++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
166 @@ -185,7 +185,7 @@ static const struct rt2x00lib_ops rt2800
167         .tbtt_tasklet           = rt2800mmio_tbtt_tasklet,
168         .rxdone_tasklet         = rt2800mmio_rxdone_tasklet,
169         .autowake_tasklet       = rt2800mmio_autowake_tasklet,
170 -       .probe_hw               = rt2800_probe_hw,
171 +       .probe_hw               = rt2800mmio_probe_hw,
172         .get_firmware_name      = rt2800soc_get_firmware_name,
173         .check_firmware         = rt2800soc_check_firmware,
174         .load_firmware          = rt2800soc_load_firmware,
175 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
176 +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
177 @@ -1391,6 +1391,8 @@ int rt2x00lib_probe_dev(struct rt2x00_de
178         mutex_init(&rt2x00dev->conf_mutex);
179         INIT_LIST_HEAD(&rt2x00dev->bar_list);
180         spin_lock_init(&rt2x00dev->bar_list_lock);
181 +       hrtimer_init(&rt2x00dev->txstatus_timer, CLOCK_MONOTONIC,
182 +                    HRTIMER_MODE_REL);
183  
184         set_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
185  
186 @@ -1515,6 +1517,8 @@ void rt2x00lib_remove_dev(struct rt2x00_
187         cancel_delayed_work_sync(&rt2x00dev->autowakeup_work);
188         cancel_work_sync(&rt2x00dev->sleep_work);
189  
190 +       hrtimer_cancel(&rt2x00dev->txstatus_timer);
191 +
192         /*
193          * Kill the tx status tasklet.
194          */