wlan: Use spinlock to synchronize SME request/response

Many of the APIs supported by HDD require a call to SME to perform an
action or to retrieve some data.  In most cases SME performs the
operation asynchronously, and will execute a provided callback
function when the request has completed.  In order to synchronize this
the HDD API allocates a context which is then passed to SME, and which
is then, in turn, passed back to the callback function when the
operation completes.  The callback function then sets a completion
variable inside the context which the HDD API is waiting on.  In an
ideal world the HDD API would wait forever (or at least for a long
time) for the response to be received and for the completion variable
to be set.  However in most cases these HDD APIs are being invoked in
the context of a userspace thread which has invoked either a cfg80211
API or a wireless extensions ioctl and which has taken the kernel
rtnl_lock.  Since this lock is used to synchronize many of the kernel
tasks, we do not want to hold it for a long time.  In addition we do
not want to block userspace threads (such as the wpa supplicant's main
thread) for an extended time.  Therefore we only block for a short
time waiting for the response before we timeout.  This means that it
is possible for the HDD API to timeout, and for the callback to be
invoked afterwards.  In order for the callback function to determine
if the HDD API is still waiting, a magic value is also stored in the
shared context.  Only if the context has a valid magic will the
callback routine do any work.

The original implementation of this logic included a well-documented
race condition where the HDD API timeout could coincide with the
callback being invoked.  In such a scenario the HDD API could be
invalidating the context immediately after the callback function had
validated it and was dereferencing it.  In order to mitigate the
effects of such a race condition, the HDD API would always msleep()
for a short amount of time when a timeout occurred so that if the
callback was executing concurrently, the callback could (hopefully)
complete its work before the HDD API exited.

Due to an customer-observed issue this logic was further scrutinized
and it was suggested that a spinlock could be used to properly
serialize the activities of the HDD API and the callback function when
they are running in parallel.  So introduce a spinlock that is used so
that if any HDD API timeout coincides with its callback, the
operations of the two threads will be serialized.

Change-Id: If0d84e535f6cf0818410e4210f5bfe8294919526
CRs-fixed: 592261
4 files changed
tree: ee1ba32cc3a42e523ea9e735e1b70e7b866cb2c3
  1. CORE/
  2. firmware_bin/
  3. prima/
  4. riva/
  5. Android.mk
  6. Kbuild
  7. Kconfig