2 * ---------------------------------------------------------------------------
6 * Provides an implementation for the driver bottom-half.
7 * It is part of the porting exercise in Linux.
9 * Copyright (C) 2005-2009 by Cambridge Silicon Radio Ltd.
11 * Refer to LICENSE.txt included with this source code for details on
14 * ---------------------------------------------------------------------------
16 #include "csr_wifi_hip_unifi.h"
17 #include "unifi_priv.h"
21 * ---------------------------------------------------------------------------
24 * Helper function to start a new thread.
27 * priv Pointer to OS driver structure for the device.
28 * thread Pointer to the thread object
29 * func The thread function
32 * 0 on success or else a Linux error code.
33 * ---------------------------------------------------------------------------
35 int uf_start_thread(unifi_priv_t
*priv
,
36 struct uf_thread
*thread
, int (*func
)(void *))
38 if (thread
->thread_task
!= NULL
) {
39 unifi_error(priv
, "%s thread already started\n", thread
->name
);
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
);
48 /* Module parameter overides the thread priority */
49 if (bh_priority
!= -1) {
50 if (bh_priority
>= 0 && bh_priority
<= MAX_RT_PRIO
) {
51 struct sched_param param
;
52 priv
->bh_thread
.prio
= bh_priority
;
53 unifi_trace(priv
, UDBG1
,
54 "%s thread (RT) priority = %d\n",
55 thread
->name
, bh_priority
);
56 param
.sched_priority
= bh_priority
;
57 sched_setscheduler(thread
->thread_task
,
59 } else if (bh_priority
> MAX_RT_PRIO
&&
60 bh_priority
<= MAX_PRIO
) {
61 priv
->bh_thread
.prio
= bh_priority
;
62 unifi_trace(priv
, UDBG1
, "%s thread priority = %d\n",
64 PRIO_TO_NICE(bh_priority
));
65 set_user_nice(thread
->thread_task
,
66 PRIO_TO_NICE(bh_priority
));
68 priv
->bh_thread
.prio
= DEFAULT_PRIO
;
70 "%s thread unsupported (%d) priority\n",
71 thread
->name
, bh_priority
);
74 priv
->bh_thread
.prio
= DEFAULT_PRIO
;
75 unifi_trace(priv
, UDBG2
, "Started %s thread\n", thread
->name
);
78 } /* uf_start_thread() */
82 * ---------------------------------------------------------------------------
85 * Helper function to stop a thread.
88 * priv Pointer to OS driver structure for the device.
89 * thread Pointer to the thread object
93 * ---------------------------------------------------------------------------
95 void uf_stop_thread(unifi_priv_t
*priv
, struct uf_thread
*thread
)
97 if (!thread
->thread_task
) {
98 unifi_notice(priv
, "%s thread is already stopped\n",
103 unifi_trace(priv
, UDBG2
, "Stopping %s thread\n", thread
->name
);
105 kthread_stop(thread
->thread_task
);
106 thread
->thread_task
= NULL
;
108 } /* uf_stop_thread() */
113 * ---------------------------------------------------------------------------
114 * uf_wait_for_thread_to_stop
116 * Helper function to wait until a thread is stopped.
119 * priv Pointer to OS driver structure for the device.
123 * ---------------------------------------------------------------------------
126 uf_wait_for_thread_to_stop(unifi_priv_t
*priv
, struct uf_thread
*thread
)
129 * kthread_stop() cannot handle the thread exiting while
130 * kthread_should_stop() is false, so sleep until kthread_stop()
133 unifi_trace(priv
, UDBG2
, "%s waiting for the stop signal.\n",
135 set_current_state(TASK_INTERRUPTIBLE
);
136 if (!kthread_should_stop()) {
137 unifi_trace(priv
, UDBG2
, "%s schedule....\n", thread
->name
);
141 thread
->thread_task
= NULL
;
142 unifi_trace(priv
, UDBG2
, "%s exiting....\n", thread
->name
);
143 } /* uf_wait_for_thread_to_stop() */
147 * ---------------------------------------------------------------------------
150 * This function reports an error returned from the HIP core bottom-half.
151 * Normally, implemented during the porting exercise, passing the error
152 * to the SME using unifi_sys_wifi_off_ind().
153 * The SME will try to reset the device and go through
154 * the initialisation of the UniFi.
157 * priv Pointer to OS driver structure for the device.
161 * ---------------------------------------------------------------------------
164 handle_bh_error(unifi_priv_t
*priv
)
166 netInterface_priv_t
*interfacePriv
;
167 u8 conf_param
= CONFIG_IND_ERROR
;
171 /* Block unifi_run_bh() until the error has been handled. */
172 priv
->bh_thread
.block_thread
= 1;
174 /* Consider UniFi to be uninitialised */
175 priv
->init_progress
= UNIFI_INIT_NONE
;
177 /* Stop the network traffic */
178 for (interfaceTag
= 0;
179 interfaceTag
< CSR_WIFI_NUM_INTERFACES
; interfaceTag
++) {
180 interfacePriv
= priv
->interfacePriv
[interfaceTag
];
181 if (interfacePriv
->netdev_registered
)
182 netif_carrier_off(priv
->netdev
[interfaceTag
]);
185 #ifdef CSR_NATIVE_LINUX
186 /* Force any client waiting on an mlme_wait_for_reply() to abort. */
189 /* Cancel any pending workqueue tasks */
190 flush_workqueue(priv
->unifi_workqueue
);
192 #endif /* CSR_NATIVE_LINUX */
195 "handle_bh_error: fatal error is reported to the SME.\n");
196 /* Notify the clients (SME or unifi_manager) for the error. */
197 ul_log_config_ind(priv
, &conf_param
, sizeof(u8
));
199 } /* handle_bh_error() */
204 * ---------------------------------------------------------------------------
207 * All hardware access happens in this thread.
208 * This means there is no need for locks on the hardware and we don't need
209 * to worry about reentrancy with the SDIO library.
210 * Provides and example implementation on how to call unifi_bh(), which
211 * is part of the HIP core API.
213 * It processes the events generated by unifi_run_bh() to serialise calls
214 * to unifi_bh(). It also demonstrates how the timeout parameter passed in
215 * and returned from unifi_bh() needs to be handled.
218 * arg Pointer to OS driver structure for the device.
224 * When the bottom half of the driver needs to process signals, events,
225 * or simply the host status (i.e sleep mode), it invokes unifi_run_bh().
226 * Since we need all SDIO transaction to be in a single thread, the
227 * unifi_run_bh() will wake up this thread to process it.
229 * ---------------------------------------------------------------------------
231 static int bh_thread_function(void *arg
)
233 unifi_priv_t
*priv
= (unifi_priv_t
*)arg
;
237 struct uf_thread
*this_thread
;
239 unifi_trace(priv
, UDBG2
, "bh_thread_function starting\n");
241 this_thread
= &priv
->bh_thread
;
244 while (!kthread_should_stop()) {
245 /* wait until an error occurs, or we need to process something. */
246 unifi_trace(priv
, UDBG3
, "bh_thread goes to sleep.\n");
249 /* Convert t in ms to jiffies */
250 t
= msecs_to_jiffies(timeout
);
251 ret
= wait_event_interruptible_timeout(this_thread
->wakeup_q
,
252 (this_thread
->wakeup_flag
&& !this_thread
->block_thread
) ||
253 kthread_should_stop(),
255 timeout
= (ret
> 0) ? jiffies_to_msecs(ret
) : 0;
257 ret
= wait_event_interruptible(this_thread
->wakeup_q
,
258 (this_thread
->wakeup_flag
&& !this_thread
->block_thread
) ||
259 kthread_should_stop());
262 if (kthread_should_stop()) {
263 unifi_trace(priv
, UDBG2
, "bh_thread: signalled to exit\n");
269 "bh_thread: wait_event returned %d, thread will exit\n",
271 uf_wait_for_thread_to_stop(priv
, this_thread
);
275 this_thread
->wakeup_flag
= 0;
277 unifi_trace(priv
, UDBG3
, "bh_thread calls unifi_bh().\n");
279 CsrSdioClaim(priv
->sdio
);
280 csrResult
= unifi_bh(priv
->card
, &timeout
);
281 if(csrResult
!= CSR_RESULT_SUCCESS
) {
282 if (csrResult
== CSR_WIFI_HIP_RESULT_NO_DEVICE
) {
283 CsrSdioRelease(priv
->sdio
);
284 uf_wait_for_thread_to_stop(priv
, this_thread
);
287 /* Errors must be delivered to the error task */
288 handle_bh_error(priv
);
290 CsrSdioRelease(priv
->sdio
);
294 * I would normally try to call csr_sdio_remove_irq() here to make sure
295 * that we do not get any interrupts while this thread is not running.
296 * However, the MMC/SDIO driver tries to kill its' interrupt thread.
297 * The kernel threads implementation does not allow to kill threads
298 * from a signalled to stop thread.
299 * So, instead call csr_sdio_linux_remove_irq() always after calling
300 * uf_stop_thread() to kill this thread.
303 unifi_trace(priv
, UDBG2
, "bh_thread exiting....\n");
305 } /* bh_thread_function() */
309 * ---------------------------------------------------------------------------
312 * Helper function to start the bottom half of the driver.
313 * All we need to do here is start the I/O bh thread.
316 * priv Pointer to OS driver structure for the device.
319 * 0 on success or else a Linux error code.
320 * ---------------------------------------------------------------------------
323 uf_init_bh(unifi_priv_t
*priv
)
327 /* Enable mlme interface. */
328 priv
->io_aborted
= 0;
331 /* Start the BH thread */
332 r
= uf_start_thread(priv
, &priv
->bh_thread
, bh_thread_function
);
335 "uf_init_bh: failed to start the BH thread.\n");
339 /* Allow interrupts */
340 r
= csr_sdio_linux_install_irq(priv
->sdio
);
343 "uf_init_bh: failed to install the IRQ.\n");
345 uf_stop_thread(priv
, &priv
->bh_thread
);
353 * ---------------------------------------------------------------------------
356 * Part of the HIP core lib API, implemented in the porting exercise.
357 * The bottom half of the driver calls this function when
358 * it wants to process anything that requires access to unifi.
359 * We need to call unifi_bh() which in this implementation is done
360 * by waking up the I/O thread.
363 * ospriv Pointer to OS driver structure for the device.
366 * 0 on success or else a Linux error code.
369 * ---------------------------------------------------------------------------
371 CsrResult
unifi_run_bh(void *ospriv
)
373 unifi_priv_t
*priv
= ospriv
;
376 * If an error has occured, we discard silently all messages from the bh
377 * until the error has been processed and the unifi has been reinitialised.
379 if (priv
->bh_thread
.block_thread
== 1) {
380 unifi_trace(priv
, UDBG3
, "unifi_run_bh: discard message.\n");
382 * Do not try to acknowledge a pending interrupt here.
383 * This function is called by unifi_send_signal() which in turn can be
384 * running in an atomic or 'disabled irq' level if a signal is sent
385 * from a workqueue task (i.e multicass addresses set).
386 * We can not hold the SDIO lock because it might sleep.
388 return CSR_RESULT_FAILURE
;
391 priv
->bh_thread
.wakeup_flag
= 1;
392 /* wake up I/O thread */
393 wake_up_interruptible(&priv
->bh_thread
.wakeup_q
);
395 return CSR_RESULT_SUCCESS
;
396 } /* unifi_run_bh() */