summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-ucode.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-03-15 21:26:44 +0100
committerJohn W. Linville <linville@tuxdriver.com>2012-04-09 22:37:15 +0200
commitdb662d478695a967b9d0a4c9893278e797b73f6c (patch)
tree3a5cf5c45c1bf241eb5dbf354c5122d53c55a14a /drivers/net/wireless/iwlwifi/iwl-ucode.c
parentiwlwifi: process multiple frames per RXB (diff)
downloadlinux-db662d478695a967b9d0a4c9893278e797b73f6c.tar.xz
linux-db662d478695a967b9d0a4c9893278e797b73f6c.zip
iwlwifi: extend notification wait
Sometimes, for example when we ask the uCode for calibration, we wait for the "complete" response while we also need the results that are sent in other, interim, notifications. Currently we handle this by installing an RX handler globally, but that isn't needed as this is the only time we want to use these notifications. So in order to be able to simplify at least future code that does the same, extend the notification wait framework to allow you to wait for multiple commands and decide based on the command whether the wait finished. While at it, also fix a race that can then become relevant -- if the wait function has returned true once it shouldn't be called again, today this can happen due to races between the triggering and the wakeup. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-ucode.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-ucode.c20
1 files changed, 13 insertions, 7 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.c b/drivers/net/wireless/iwlwifi/iwl-ucode.c
index 252828728837..44b0e72ca7fb 100644
--- a/drivers/net/wireless/iwlwifi/iwl-ucode.c
+++ b/drivers/net/wireless/iwlwifi/iwl-ucode.c
@@ -417,9 +417,8 @@ struct iwl_alive_data {
u8 subtype;
};
-static void iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
- struct iwl_rx_packet *pkt,
- void *data)
+static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
+ struct iwl_rx_packet *pkt, void *data)
{
struct iwl_priv *priv =
container_of(notif_wait, struct iwl_priv, notif_wait);
@@ -440,6 +439,8 @@ static void iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
alive_data->subtype = palive->ver_subtype;
alive_data->valid = palive->is_valid == UCODE_VALID_OK;
+
+ return true;
}
#define UCODE_ALIVE_TIMEOUT HZ
@@ -453,6 +454,7 @@ int iwl_load_ucode_wait_alive(struct iwl_priv *priv,
const struct fw_img *fw;
int ret;
enum iwl_ucode_type old_type;
+ static const u8 alive_cmd[] = { REPLY_ALIVE };
old_type = priv->shrd->ucode_type;
priv->shrd->ucode_type = ucode_type;
@@ -463,8 +465,9 @@ int iwl_load_ucode_wait_alive(struct iwl_priv *priv,
if (!fw)
return -EINVAL;
- iwl_init_notification_wait(&priv->notif_wait, &alive_wait, REPLY_ALIVE,
- iwl_alive_fn, &alive_data);
+ iwl_init_notification_wait(&priv->notif_wait, &alive_wait,
+ alive_cmd, ARRAY_SIZE(alive_cmd),
+ iwl_alive_fn, &alive_data);
ret = iwl_trans_start_fw(trans(priv), fw);
if (ret) {
@@ -522,6 +525,9 @@ int iwl_load_ucode_wait_alive(struct iwl_priv *priv,
int iwl_run_init_ucode(struct iwl_priv *priv)
{
struct iwl_notification_wait calib_wait;
+ static const u8 calib_complete[] = {
+ CALIBRATION_COMPLETE_NOTIFICATION
+ };
int ret;
lockdep_assert_held(&priv->mutex);
@@ -534,8 +540,8 @@ int iwl_run_init_ucode(struct iwl_priv *priv)
return 0;
iwl_init_notification_wait(&priv->notif_wait, &calib_wait,
- CALIBRATION_COMPLETE_NOTIFICATION,
- NULL, NULL);
+ calib_complete, ARRAY_SIZE(calib_complete),
+ NULL, NULL);
/* Will also start the device */
ret = iwl_load_ucode_wait_alive(priv, IWL_UCODE_INIT);