Merge remote-tracking branch 'upstream' into next
[cascardo/linux.git] / drivers / staging / csr / bh.c
1 /*
2  * ---------------------------------------------------------------------------
3  * FILE:     bh.c
4  *
5  * PURPOSE:
6  *      Provides an implementation for the driver bottom-half.
7  *      It is part of the porting exercise in Linux.
8  *
9  * Copyright (C) 2005-2009 by Cambridge Silicon Radio Ltd.
10  *
11  * Refer to LICENSE.txt included with this source code for details on
12  * the license terms.
13  *
14  * ---------------------------------------------------------------------------
15  */
16 #include "csr_wifi_hip_unifi.h"
17 #include "unifi_priv.h"
18
19
20 /*
21  * ---------------------------------------------------------------------------
22  *  uf_start_thread
23  *
24  *      Helper function to start a new thread.
25  *
26  *  Arguments:
27  *      priv            Pointer to OS driver structure for the device.
28  *      thread          Pointer to the thread object
29  *      func            The thread function
30  *
31  *  Returns:
32  *      0 on success or else a Linux error code.
33  * ---------------------------------------------------------------------------
34  */
35 int
36 uf_start_thread(unifi_priv_t *priv, struct uf_thread *thread, int (*func)(void *))
37 {
38     if (thread->thread_task != NULL) {
39         unifi_error(priv, "%s thread already started\n", thread->name);
40         return 0;
41     }
42
43     /* Start the kernel thread that handles all h/w accesses. */
44     thread->thread_task = kthread_run(func, priv, "%s", thread->name);
45     if (IS_ERR(thread->thread_task)) {
46         return PTR_ERR(thread->thread_task);
47     }
48
49     /* Module parameter overides the thread priority */
50     if (bh_priority != -1) {
51         if (bh_priority >= 0 && bh_priority <= MAX_RT_PRIO) {
52             struct sched_param param;
53             priv->bh_thread.prio = bh_priority;
54             unifi_trace(priv, UDBG1, "%s thread (RT) priority = %d\n",
55                         thread->name, bh_priority);
56             param.sched_priority = bh_priority;
57             sched_setscheduler(thread->thread_task, SCHED_FIFO, &param);
58         } else if (bh_priority > MAX_RT_PRIO && bh_priority <= MAX_PRIO) {
59             priv->bh_thread.prio = bh_priority;
60             unifi_trace(priv, UDBG1, "%s thread priority = %d\n",
61                         thread->name, PRIO_TO_NICE(bh_priority));
62             set_user_nice(thread->thread_task, PRIO_TO_NICE(bh_priority));
63         } else {
64             priv->bh_thread.prio = DEFAULT_PRIO;
65             unifi_warning(priv, "%s thread unsupported (%d) priority\n",
66                           thread->name, bh_priority);
67         }
68     } else {
69         priv->bh_thread.prio = DEFAULT_PRIO;
70     }
71     unifi_trace(priv, UDBG2, "Started %s thread\n", thread->name);
72
73     return 0;
74 } /* uf_start_thread() */
75
76
77 /*
78  * ---------------------------------------------------------------------------
79  *  uf_stop_thread
80  *
81  *      Helper function to stop a thread.
82  *
83  *  Arguments:
84  *      priv            Pointer to OS driver structure for the device.
85  *      thread          Pointer to the thread object
86  *
87  *  Returns:
88  *
89  * ---------------------------------------------------------------------------
90  */
91     void
92 uf_stop_thread(unifi_priv_t *priv, struct uf_thread *thread)
93 {
94     if (!thread->thread_task) {
95         unifi_notice(priv, "%s thread is already stopped\n", thread->name);
96         return;
97     }
98
99     unifi_trace(priv, UDBG2, "Stopping %s thread\n", thread->name);
100
101     kthread_stop(thread->thread_task);
102     thread->thread_task = NULL;
103
104 } /* uf_stop_thread() */
105
106
107
108 /*
109  * ---------------------------------------------------------------------------
110  *  uf_wait_for_thread_to_stop
111  *
112  *      Helper function to wait until a thread is stopped.
113  *
114  *  Arguments:
115  *      priv    Pointer to OS driver structure for the device.
116  *
117  *  Returns:
118  *
119  * ---------------------------------------------------------------------------
120  */
121     void
122 uf_wait_for_thread_to_stop(unifi_priv_t *priv, struct uf_thread *thread)
123 {
124     /*
125      * kthread_stop() cannot handle the thread exiting while
126      * kthread_should_stop() is false, so sleep until kthread_stop()
127      * wakes us up.
128      */
129     unifi_trace(priv, UDBG2, "%s waiting for the stop signal.\n", thread->name);
130     set_current_state(TASK_INTERRUPTIBLE);
131     if (!kthread_should_stop()) {
132         unifi_trace(priv, UDBG2, "%s schedule....\n", thread->name);
133         schedule();
134     }
135
136     thread->thread_task = NULL;
137     unifi_trace(priv, UDBG2, "%s exiting....\n", thread->name);
138 } /* uf_wait_for_thread_to_stop() */
139
140
141 /*
142  * ---------------------------------------------------------------------------
143  *  handle_bh_error
144  *
145  *      This function reports an error returned from the HIP core bottom-half.
146  *      Normally, implemented during the porting exercise, passing the error
147  *      to the SME using unifi_sys_wifi_off_ind().
148  *      The SME will try to reset the device and go through
149  *      the initialisation of the UniFi.
150  *
151  *  Arguments:
152  *      priv            Pointer to OS driver structure for the device.
153  *
154  *  Returns:
155  *      None.
156  * ---------------------------------------------------------------------------
157  */
158     static void
159 handle_bh_error(unifi_priv_t *priv)
160 {
161     u8 conf_param = CONFIG_IND_ERROR;
162     u8 interfaceTag = 0; /* used as a loop counter */
163
164
165     /* Block unifi_run_bh() until the error has been handled. */
166     priv->bh_thread.block_thread = 1;
167
168     /* Consider UniFi to be uninitialised */
169     priv->init_progress = UNIFI_INIT_NONE;
170
171     /* Stop the network traffic */
172     for( interfaceTag =0; interfaceTag <CSR_WIFI_NUM_INTERFACES;interfaceTag ++) {
173         netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag];
174         if (interfacePriv->netdev_registered == 1) {
175             netif_carrier_off(priv->netdev[interfaceTag]);
176         }
177     }
178
179 #ifdef CSR_NATIVE_LINUX
180     /* Force any client waiting on an mlme_wait_for_reply() to abort. */
181     uf_abort_mlme(priv);
182
183     /* Cancel any pending workqueue tasks */
184     flush_workqueue(priv->unifi_workqueue);
185
186 #endif /* CSR_NATIVE_LINUX */
187
188     unifi_error(priv, "handle_bh_error: fatal error is reported to the SME.\n");
189     /* Notify the clients (SME or unifi_manager) for the error. */
190     ul_log_config_ind(priv, &conf_param, sizeof(u8));
191
192 } /* handle_bh_error() */
193
194
195
196 /*
197  * ---------------------------------------------------------------------------
198  *  bh_thread_function
199  *
200  *      All hardware access happens in this thread.
201  *      This means there is no need for locks on the hardware and we don't need
202  *      to worry about reentrancy with the SDIO library.
203  *      Provides and example implementation on how to call unifi_bh(), which
204  *      is part of the HIP core API.
205  *
206  *      It processes the events generated by unifi_run_bh() to serialise calls
207  *      to unifi_bh(). It also demonstrates how the timeout parameter passed in
208  *      and returned from unifi_bh() needs to be handled.
209  *
210  *  Arguments:
211  *      arg             Pointer to OS driver structure for the device.
212  *
213  *  Returns:
214  *      None.
215  *
216  *  Notes:
217  *      When the bottom half of the driver needs to process signals, events,
218  *      or simply the host status (i.e sleep mode), it invokes unifi_run_bh().
219  *      Since we need all SDIO transaction to be in a single thread, the
220  *      unifi_run_bh() will wake up this thread to process it.
221  *
222  * ---------------------------------------------------------------------------
223  */
224 static int
225 bh_thread_function(void *arg)
226 {
227     unifi_priv_t *priv = (unifi_priv_t*)arg;
228     CsrResult csrResult;
229     long ret;
230     u32 timeout, t;
231     struct uf_thread *this_thread;
232
233     unifi_trace(priv, UDBG2, "bh_thread_function starting\n");
234
235     this_thread = &priv->bh_thread;
236
237     t = timeout = 0;
238     while (!kthread_should_stop()) {
239         /* wait until an error occurs, or we need to process something. */
240         unifi_trace(priv, UDBG3, "bh_thread goes to sleep.\n");
241
242         if (timeout > 0) {
243             /* Convert t in ms to jiffies */
244             t = msecs_to_jiffies(timeout);
245             ret = wait_event_interruptible_timeout(this_thread->wakeup_q,
246                     (this_thread->wakeup_flag && !this_thread->block_thread) ||
247                     kthread_should_stop(),
248                     t);
249             timeout = (ret > 0) ? jiffies_to_msecs(ret) : 0;
250         } else {
251             ret = wait_event_interruptible(this_thread->wakeup_q,
252                     (this_thread->wakeup_flag && !this_thread->block_thread) ||
253                     kthread_should_stop());
254         }
255
256         if (kthread_should_stop()) {
257             unifi_trace(priv, UDBG2, "bh_thread: signalled to exit\n");
258             break;
259         }
260
261         if (ret < 0) {
262             unifi_notice(priv,
263                     "bh_thread: wait_event returned %d, thread will exit\n",
264                     ret);
265             uf_wait_for_thread_to_stop(priv, this_thread);
266             break;
267         }
268
269         this_thread->wakeup_flag = 0;
270
271         unifi_trace(priv, UDBG3, "bh_thread calls unifi_bh().\n");
272
273         CsrSdioClaim(priv->sdio);
274         csrResult = unifi_bh(priv->card, &timeout);
275         if(csrResult != CSR_RESULT_SUCCESS) {
276             if (csrResult == CSR_WIFI_HIP_RESULT_NO_DEVICE) {
277                 CsrSdioRelease(priv->sdio);
278                 uf_wait_for_thread_to_stop(priv, this_thread);
279                 break;
280             }
281             /* Errors must be delivered to the error task */
282             handle_bh_error(priv);
283         }
284         CsrSdioRelease(priv->sdio);
285     }
286
287     /*
288      * I would normally try to call csr_sdio_remove_irq() here to make sure
289      * that we do not get any interrupts while this thread is not running.
290      * However, the MMC/SDIO driver tries to kill its' interrupt thread.
291      * The kernel threads implementation does not allow to kill threads
292      * from a signalled to stop thread.
293      * So, instead call csr_sdio_linux_remove_irq() always after calling
294      * uf_stop_thread() to kill this thread.
295      */
296
297     unifi_trace(priv, UDBG2, "bh_thread exiting....\n");
298     return 0;
299 } /* bh_thread_function() */
300
301
302 /*
303  * ---------------------------------------------------------------------------
304  *  uf_init_bh
305  *
306  *      Helper function to start the bottom half of the driver.
307  *      All we need to do here is start the I/O bh thread.
308  *
309  *  Arguments:
310  *      priv            Pointer to OS driver structure for the device.
311  *
312  *  Returns:
313  *      0 on success or else a Linux error code.
314  * ---------------------------------------------------------------------------
315  */
316     int
317 uf_init_bh(unifi_priv_t *priv)
318 {
319     int r;
320
321     /* Enable mlme interface. */
322     priv->io_aborted = 0;
323
324
325     /* Start the BH thread */
326     r = uf_start_thread(priv, &priv->bh_thread, bh_thread_function);
327     if (r) {
328         unifi_error(priv,
329                 "uf_init_bh: failed to start the BH thread.\n");
330         return r;
331     }
332
333     /* Allow interrupts */
334     r = csr_sdio_linux_install_irq(priv->sdio);
335     if (r) {
336         unifi_error(priv,
337                 "uf_init_bh: failed to install the IRQ.\n");
338
339         uf_stop_thread(priv, &priv->bh_thread);
340     }
341
342     return r;
343 } /* uf_init_bh() */
344
345
346 /*
347  * ---------------------------------------------------------------------------
348  *  unifi_run_bh
349  *
350  *      Part of the HIP core lib API, implemented in the porting exercise.
351  *      The bottom half of the driver calls this function when
352  *      it wants to process anything that requires access to unifi.
353  *      We need to call unifi_bh() which in this implementation is done
354  *      by waking up the I/O thread.
355  *
356  *  Arguments:
357  *      ospriv          Pointer to OS driver structure for the device.
358  *
359  *  Returns:
360  *      0 on success or else a Linux error code.
361  *
362  *  Notes:
363  * ---------------------------------------------------------------------------
364  */
365 CsrResult unifi_run_bh(void *ospriv)
366 {
367     unifi_priv_t *priv = ospriv;
368
369     /*
370      * If an error has occured, we discard silently all messages from the bh
371      * until the error has been processed and the unifi has been reinitialised.
372      */
373     if (priv->bh_thread.block_thread == 1) {
374         unifi_trace(priv, UDBG3, "unifi_run_bh: discard message.\n");
375         /*
376          * Do not try to acknowledge a pending interrupt here.
377          * This function is called by unifi_send_signal() which in turn can be
378          * running in an atomic or 'disabled irq' level if a signal is sent
379          * from a workqueue task (i.e multicass addresses set).
380          * We can not hold the SDIO lock because it might sleep.
381          */
382         return CSR_RESULT_FAILURE;
383     }
384
385     priv->bh_thread.wakeup_flag = 1;
386     /* wake up I/O thread */
387     wake_up_interruptible(&priv->bh_thread.wakeup_q);
388
389     return CSR_RESULT_SUCCESS;
390 } /* unifi_run_bh() */
391