summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-ucode.c
diff options
context:
space:
mode:
authorDon Fry <donald.h.fry@intel.com>2011-11-28 16:13:19 -0800
committerWey-Yi Guy <wey-yi.w.guy@intel.com>2011-12-02 08:23:28 -0800
commitdd5fe1046cb07d2a6665b6dbbfc6989b39ae063b (patch)
tree83d8f9c06d870847a6f817581416c915092a89f1 /drivers/net/wireless/iwlwifi/iwl-ucode.c
parent3d6acefc0a24bf90746c1f259e9d65d1ed7ea5e2 (diff)
downloadlinux-stable-dd5fe1046cb07d2a6665b6dbbfc6989b39ae063b.tar.gz
linux-stable-dd5fe1046cb07d2a6665b6dbbfc6989b39ae063b.tar.bz2
linux-stable-dd5fe1046cb07d2a6665b6dbbfc6989b39ae063b.zip
iwlwifi: move ucode notification from iwl_priv to iwl_shared
Move the notification structures for ucode operations from the iwl_priv structure to the iwl_shared structure, with associated code changes. Signed-off-by: Don Fry <donald.h.fry@intel.com> Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-ucode.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-ucode.c78
1 files changed, 72 insertions, 6 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.c b/drivers/net/wireless/iwlwifi/iwl-ucode.c
index 1b23b99c474c..b365de457b1b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-ucode.c
+++ b/drivers/net/wireless/iwlwifi/iwl-ucode.c
@@ -571,6 +571,70 @@ static void iwl_alive_fn(struct iwl_priv *priv,
alive_data->valid = palive->is_valid == UCODE_VALID_OK;
}
+/* notification wait support */
+void iwl_init_notification_wait(struct iwl_shared *shrd,
+ struct iwl_notification_wait *wait_entry,
+ u8 cmd,
+ void (*fn)(struct iwl_priv *priv,
+ struct iwl_rx_packet *pkt,
+ void *data),
+ void *fn_data)
+{
+ wait_entry->fn = fn;
+ wait_entry->fn_data = fn_data;
+ wait_entry->cmd = cmd;
+ wait_entry->triggered = false;
+ wait_entry->aborted = false;
+
+ spin_lock_bh(&shrd->notif_wait_lock);
+ list_add(&wait_entry->list, &shrd->notif_waits);
+ spin_unlock_bh(&shrd->notif_wait_lock);
+}
+
+int iwl_wait_notification(struct iwl_shared *shrd,
+ struct iwl_notification_wait *wait_entry,
+ unsigned long timeout)
+{
+ int ret;
+
+ ret = wait_event_timeout(shrd->notif_waitq,
+ wait_entry->triggered || wait_entry->aborted,
+ timeout);
+
+ spin_lock_bh(&shrd->notif_wait_lock);
+ list_del(&wait_entry->list);
+ spin_unlock_bh(&shrd->notif_wait_lock);
+
+ if (wait_entry->aborted)
+ return -EIO;
+
+ /* return value is always >= 0 */
+ if (ret <= 0)
+ return -ETIMEDOUT;
+ return 0;
+}
+
+void iwl_remove_notification(struct iwl_shared *shrd,
+ struct iwl_notification_wait *wait_entry)
+{
+ spin_lock_bh(&shrd->notif_wait_lock);
+ list_del(&wait_entry->list);
+ spin_unlock_bh(&shrd->notif_wait_lock);
+}
+
+void iwl_abort_notification_waits(struct iwl_shared *shrd)
+{
+ unsigned long flags;
+ struct iwl_notification_wait *wait_entry;
+
+ spin_lock_irqsave(&shrd->notif_wait_lock, flags);
+ list_for_each_entry(wait_entry, &shrd->notif_waits, list)
+ wait_entry->aborted = true;
+ spin_unlock_irqrestore(&shrd->notif_wait_lock, flags);
+
+ wake_up_all(&shrd->notif_waitq);
+}
+
#define UCODE_ALIVE_TIMEOUT HZ
#define UCODE_CALIB_TIMEOUT (2*HZ)
@@ -587,7 +651,7 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
if (ret)
return ret;
- iwlagn_init_notification_wait(priv, &alive_wait, REPLY_ALIVE,
+ iwl_init_notification_wait(trans->shrd, &alive_wait, REPLY_ALIVE,
iwl_alive_fn, &alive_data);
old_type = trans->shrd->ucode_type;
@@ -596,7 +660,7 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
ret = iwl_load_given_ucode(trans, ucode_type);
if (ret) {
trans->shrd->ucode_type = old_type;
- iwlagn_remove_notification(priv, &alive_wait);
+ iwl_remove_notification(trans->shrd, &alive_wait);
return ret;
}
@@ -606,7 +670,8 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
* Some things may run in the background now, but we
* just wait for the ALIVE notification here.
*/
- ret = iwlagn_wait_notification(priv, &alive_wait, UCODE_ALIVE_TIMEOUT);
+ ret = iwl_wait_notification(trans->shrd, &alive_wait,
+ UCODE_ALIVE_TIMEOUT);
if (ret) {
trans->shrd->ucode_type = old_type;
return ret;
@@ -659,7 +724,7 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv)
if (priv->shrd->ucode_type != IWL_UCODE_NONE)
return 0;
- iwlagn_init_notification_wait(priv, &calib_wait,
+ iwl_init_notification_wait(priv->shrd, &calib_wait,
CALIBRATION_COMPLETE_NOTIFICATION,
NULL, NULL);
@@ -676,12 +741,13 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv)
* Some things may run in the background now, but we
* just wait for the calibration complete notification.
*/
- ret = iwlagn_wait_notification(priv, &calib_wait, UCODE_CALIB_TIMEOUT);
+ ret = iwl_wait_notification(priv->shrd, &calib_wait,
+ UCODE_CALIB_TIMEOUT);
goto out;
error:
- iwlagn_remove_notification(priv, &calib_wait);
+ iwl_remove_notification(priv->shrd, &calib_wait);
out:
/* Whatever happened, stop the device */
iwl_trans_stop_device(trans(priv));