|
@@ -571,6 +571,70 @@ static void iwl_alive_fn(struct iwl_priv *priv,
|
|
alive_data->valid = palive->is_valid == UCODE_VALID_OK;
|
|
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_ALIVE_TIMEOUT HZ
|
|
#define UCODE_CALIB_TIMEOUT (2*HZ)
|
|
#define UCODE_CALIB_TIMEOUT (2*HZ)
|
|
|
|
|
|
@@ -587,7 +651,7 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
|
|
if (ret)
|
|
if (ret)
|
|
return 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);
|
|
iwl_alive_fn, &alive_data);
|
|
|
|
|
|
old_type = trans->shrd->ucode_type;
|
|
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);
|
|
ret = iwl_load_given_ucode(trans, ucode_type);
|
|
if (ret) {
|
|
if (ret) {
|
|
trans->shrd->ucode_type = old_type;
|
|
trans->shrd->ucode_type = old_type;
|
|
- iwlagn_remove_notification(priv, &alive_wait);
|
|
|
|
|
|
+ iwl_remove_notification(trans->shrd, &alive_wait);
|
|
return ret;
|
|
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
|
|
* Some things may run in the background now, but we
|
|
* just wait for the ALIVE notification here.
|
|
* 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) {
|
|
if (ret) {
|
|
trans->shrd->ucode_type = old_type;
|
|
trans->shrd->ucode_type = old_type;
|
|
return ret;
|
|
return ret;
|
|
@@ -659,7 +724,7 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv)
|
|
if (priv->shrd->ucode_type != IWL_UCODE_NONE)
|
|
if (priv->shrd->ucode_type != IWL_UCODE_NONE)
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
- iwlagn_init_notification_wait(priv, &calib_wait,
|
|
|
|
|
|
+ iwl_init_notification_wait(priv->shrd, &calib_wait,
|
|
CALIBRATION_COMPLETE_NOTIFICATION,
|
|
CALIBRATION_COMPLETE_NOTIFICATION,
|
|
NULL, NULL);
|
|
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
|
|
* Some things may run in the background now, but we
|
|
* just wait for the calibration complete notification.
|
|
* 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;
|
|
goto out;
|
|
|
|
|
|
error:
|
|
error:
|
|
- iwlagn_remove_notification(priv, &calib_wait);
|
|
|
|
|
|
+ iwl_remove_notification(priv->shrd, &calib_wait);
|
|
out:
|
|
out:
|
|
/* Whatever happened, stop the device */
|
|
/* Whatever happened, stop the device */
|
|
iwl_trans_stop_device(trans(priv));
|
|
iwl_trans_stop_device(trans(priv));
|