diff options
author | Don Fry <donald.h.fry@intel.com> | 2011-12-02 11:48:40 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-12-06 16:07:07 -0500 |
commit | 79e3b16b7123018610f2754ce1bd219c5dd844f5 (patch) | |
tree | 74a35b533d32b6ae3f61f8bb21311f2cc27cb234 /drivers | |
parent | a96b724d5ad7d44184d6a871bc1d35b005f2d53e (diff) |
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>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 51 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-rx.c | 16 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.h | 16 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.c | 15 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-dev.h | 33 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-shared.h | 56 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-testmode.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-ucode.c | 78 |
9 files changed, 143 insertions, 134 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 0bc962217351..575d1bb8e8cc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c | |||
@@ -934,57 +934,6 @@ u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant, u8 valid) | |||
934 | return ant; | 934 | return ant; |
935 | } | 935 | } |
936 | 936 | ||
937 | /* notification wait support */ | ||
938 | void iwlagn_init_notification_wait(struct iwl_priv *priv, | ||
939 | struct iwl_notification_wait *wait_entry, | ||
940 | u8 cmd, | ||
941 | void (*fn)(struct iwl_priv *priv, | ||
942 | struct iwl_rx_packet *pkt, | ||
943 | void *data), | ||
944 | void *fn_data) | ||
945 | { | ||
946 | wait_entry->fn = fn; | ||
947 | wait_entry->fn_data = fn_data; | ||
948 | wait_entry->cmd = cmd; | ||
949 | wait_entry->triggered = false; | ||
950 | wait_entry->aborted = false; | ||
951 | |||
952 | spin_lock_bh(&priv->notif_wait_lock); | ||
953 | list_add(&wait_entry->list, &priv->notif_waits); | ||
954 | spin_unlock_bh(&priv->notif_wait_lock); | ||
955 | } | ||
956 | |||
957 | int iwlagn_wait_notification(struct iwl_priv *priv, | ||
958 | struct iwl_notification_wait *wait_entry, | ||
959 | unsigned long timeout) | ||
960 | { | ||
961 | int ret; | ||
962 | |||
963 | ret = wait_event_timeout(priv->notif_waitq, | ||
964 | wait_entry->triggered || wait_entry->aborted, | ||
965 | timeout); | ||
966 | |||
967 | spin_lock_bh(&priv->notif_wait_lock); | ||
968 | list_del(&wait_entry->list); | ||
969 | spin_unlock_bh(&priv->notif_wait_lock); | ||
970 | |||
971 | if (wait_entry->aborted) | ||
972 | return -EIO; | ||
973 | |||
974 | /* return value is always >= 0 */ | ||
975 | if (ret <= 0) | ||
976 | return -ETIMEDOUT; | ||
977 | return 0; | ||
978 | } | ||
979 | |||
980 | void iwlagn_remove_notification(struct iwl_priv *priv, | ||
981 | struct iwl_notification_wait *wait_entry) | ||
982 | { | ||
983 | spin_lock_bh(&priv->notif_wait_lock); | ||
984 | list_del(&wait_entry->list); | ||
985 | spin_unlock_bh(&priv->notif_wait_lock); | ||
986 | } | ||
987 | |||
988 | #ifdef CONFIG_PM_SLEEP | 937 | #ifdef CONFIG_PM_SLEEP |
989 | static void iwlagn_convert_p1k(u16 *p1k, __le16 *out) | 938 | static void iwlagn_convert_p1k(u16 *p1k, __le16 *out) |
990 | { | 939 | { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c index 087fd52e5727..90c55ea4cc39 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c | |||
@@ -1131,9 +1131,9 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv) | |||
1131 | priv->rx_handlers[REPLY_TX] = iwlagn_rx_reply_tx; | 1131 | priv->rx_handlers[REPLY_TX] = iwlagn_rx_reply_tx; |
1132 | 1132 | ||
1133 | /* set up notification wait support */ | 1133 | /* set up notification wait support */ |
1134 | spin_lock_init(&priv->notif_wait_lock); | 1134 | spin_lock_init(&priv->shrd->notif_wait_lock); |
1135 | INIT_LIST_HEAD(&priv->notif_waits); | 1135 | INIT_LIST_HEAD(&priv->shrd->notif_waits); |
1136 | init_waitqueue_head(&priv->notif_waitq); | 1136 | init_waitqueue_head(&priv->shrd->notif_waitq); |
1137 | 1137 | ||
1138 | /* Set up BT Rx handlers */ | 1138 | /* Set up BT Rx handlers */ |
1139 | if (priv->cfg->lib->bt_rx_handler_setup) | 1139 | if (priv->cfg->lib->bt_rx_handler_setup) |
@@ -1152,11 +1152,11 @@ int iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, | |||
1152 | * even if the RX handler consumes the RXB we have | 1152 | * even if the RX handler consumes the RXB we have |
1153 | * access to it in the notification wait entry. | 1153 | * access to it in the notification wait entry. |
1154 | */ | 1154 | */ |
1155 | if (!list_empty(&priv->notif_waits)) { | 1155 | if (!list_empty(&priv->shrd->notif_waits)) { |
1156 | struct iwl_notification_wait *w; | 1156 | struct iwl_notification_wait *w; |
1157 | 1157 | ||
1158 | spin_lock(&priv->notif_wait_lock); | 1158 | spin_lock(&priv->shrd->notif_wait_lock); |
1159 | list_for_each_entry(w, &priv->notif_waits, list) { | 1159 | list_for_each_entry(w, &priv->shrd->notif_waits, list) { |
1160 | if (w->cmd != pkt->hdr.cmd) | 1160 | if (w->cmd != pkt->hdr.cmd) |
1161 | continue; | 1161 | continue; |
1162 | IWL_DEBUG_RX(priv, | 1162 | IWL_DEBUG_RX(priv, |
@@ -1167,9 +1167,9 @@ int iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, | |||
1167 | if (w->fn) | 1167 | if (w->fn) |
1168 | w->fn(priv, pkt, w->fn_data); | 1168 | w->fn(priv, pkt, w->fn_data); |
1169 | } | 1169 | } |
1170 | spin_unlock(&priv->notif_wait_lock); | 1170 | spin_unlock(&priv->shrd->notif_wait_lock); |
1171 | 1171 | ||
1172 | wake_up_all(&priv->notif_waitq); | 1172 | wake_up_all(&priv->shrd->notif_waitq); |
1173 | } | 1173 | } |
1174 | 1174 | ||
1175 | if (priv->pre_rx_handler) | 1175 | if (priv->pre_rx_handler) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index 00b38711c15d..466e4ab544f7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | |||
@@ -60,7 +60,7 @@ static int iwlagn_disable_pan(struct iwl_priv *priv, | |||
60 | u8 old_dev_type = send->dev_type; | 60 | u8 old_dev_type = send->dev_type; |
61 | int ret; | 61 | int ret; |
62 | 62 | ||
63 | iwlagn_init_notification_wait(priv, &disable_wait, | 63 | iwl_init_notification_wait(priv->shrd, &disable_wait, |
64 | REPLY_WIPAN_DEACTIVATION_COMPLETE, | 64 | REPLY_WIPAN_DEACTIVATION_COMPLETE, |
65 | NULL, NULL); | 65 | NULL, NULL); |
66 | 66 | ||
@@ -74,9 +74,9 @@ static int iwlagn_disable_pan(struct iwl_priv *priv, | |||
74 | 74 | ||
75 | if (ret) { | 75 | if (ret) { |
76 | IWL_ERR(priv, "Error disabling PAN (%d)\n", ret); | 76 | IWL_ERR(priv, "Error disabling PAN (%d)\n", ret); |
77 | iwlagn_remove_notification(priv, &disable_wait); | 77 | iwl_remove_notification(priv->shrd, &disable_wait); |
78 | } else { | 78 | } else { |
79 | ret = iwlagn_wait_notification(priv, &disable_wait, HZ); | 79 | ret = iwl_wait_notification(priv->shrd, &disable_wait, HZ); |
80 | if (ret) | 80 | if (ret) |
81 | IWL_ERR(priv, "Timed out waiting for PAN disable\n"); | 81 | IWL_ERR(priv, "Timed out waiting for PAN disable\n"); |
82 | } | 82 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 0db0a8fb5679..f2f10702754d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h | |||
@@ -356,22 +356,6 @@ static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags) | |||
356 | void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv); | 356 | void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv); |
357 | void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac); | 357 | void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac); |
358 | 358 | ||
359 | /* notification wait support */ | ||
360 | void __acquires(wait_entry) | ||
361 | iwlagn_init_notification_wait(struct iwl_priv *priv, | ||
362 | struct iwl_notification_wait *wait_entry, | ||
363 | u8 cmd, | ||
364 | void (*fn)(struct iwl_priv *priv, | ||
365 | struct iwl_rx_packet *pkt, | ||
366 | void *data), | ||
367 | void *fn_data); | ||
368 | int __must_check __releases(wait_entry) | ||
369 | iwlagn_wait_notification(struct iwl_priv *priv, | ||
370 | struct iwl_notification_wait *wait_entry, | ||
371 | unsigned long timeout); | ||
372 | void __releases(wait_entry) | ||
373 | iwlagn_remove_notification(struct iwl_priv *priv, | ||
374 | struct iwl_notification_wait *wait_entry); | ||
375 | extern int iwlagn_init_alive_start(struct iwl_priv *priv); | 359 | extern int iwlagn_init_alive_start(struct iwl_priv *priv); |
376 | extern int iwl_alive_start(struct iwl_priv *priv); | 360 | extern int iwl_alive_start(struct iwl_priv *priv); |
377 | /* svtool */ | 361 | /* svtool */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index b24623b3bdb3..3b6f48bfe0e3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -836,19 +836,6 @@ void iwl_print_rx_config_cmd(struct iwl_priv *priv, | |||
836 | } | 836 | } |
837 | #endif | 837 | #endif |
838 | 838 | ||
839 | static void iwlagn_abort_notification_waits(struct iwl_priv *priv) | ||
840 | { | ||
841 | unsigned long flags; | ||
842 | struct iwl_notification_wait *wait_entry; | ||
843 | |||
844 | spin_lock_irqsave(&priv->notif_wait_lock, flags); | ||
845 | list_for_each_entry(wait_entry, &priv->notif_waits, list) | ||
846 | wait_entry->aborted = true; | ||
847 | spin_unlock_irqrestore(&priv->notif_wait_lock, flags); | ||
848 | |||
849 | wake_up_all(&priv->notif_waitq); | ||
850 | } | ||
851 | |||
852 | void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) | 839 | void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) |
853 | { | 840 | { |
854 | unsigned int reload_msec; | 841 | unsigned int reload_msec; |
@@ -860,7 +847,7 @@ void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) | |||
860 | /* Cancel currently queued command. */ | 847 | /* Cancel currently queued command. */ |
861 | clear_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status); | 848 | clear_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status); |
862 | 849 | ||
863 | iwlagn_abort_notification_waits(priv); | 850 | iwl_abort_notification_waits(priv->shrd); |
864 | 851 | ||
865 | /* Keep the restart process from trying to send host | 852 | /* Keep the restart process from trying to send host |
866 | * commands by clearing the ready bit */ | 853 | * commands by clearing the ready bit */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 0019a23d6d49..6f6a647d34f6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -689,35 +689,6 @@ struct iwl_force_reset { | |||
689 | */ | 689 | */ |
690 | #define IWLAGN_EXT_BEACON_TIME_POS 22 | 690 | #define IWLAGN_EXT_BEACON_TIME_POS 22 |
691 | 691 | ||
692 | /** | ||
693 | * struct iwl_notification_wait - notification wait entry | ||
694 | * @list: list head for global list | ||
695 | * @fn: function called with the notification | ||
696 | * @cmd: command ID | ||
697 | * | ||
698 | * This structure is not used directly, to wait for a | ||
699 | * notification declare it on the stack, and call | ||
700 | * iwlagn_init_notification_wait() with appropriate | ||
701 | * parameters. Then do whatever will cause the ucode | ||
702 | * to notify the driver, and to wait for that then | ||
703 | * call iwlagn_wait_notification(). | ||
704 | * | ||
705 | * Each notification is one-shot. If at some point we | ||
706 | * need to support multi-shot notifications (which | ||
707 | * can't be allocated on the stack) we need to modify | ||
708 | * the code for them. | ||
709 | */ | ||
710 | struct iwl_notification_wait { | ||
711 | struct list_head list; | ||
712 | |||
713 | void (*fn)(struct iwl_priv *priv, struct iwl_rx_packet *pkt, | ||
714 | void *data); | ||
715 | void *fn_data; | ||
716 | |||
717 | u8 cmd; | ||
718 | bool triggered, aborted; | ||
719 | }; | ||
720 | |||
721 | struct iwl_rxon_context { | 692 | struct iwl_rxon_context { |
722 | struct ieee80211_vif *vif; | 693 | struct ieee80211_vif *vif; |
723 | 694 | ||
@@ -992,10 +963,6 @@ struct iwl_priv { | |||
992 | /* counts reply_tx error */ | 963 | /* counts reply_tx error */ |
993 | struct reply_tx_error_statistics reply_tx_stats; | 964 | struct reply_tx_error_statistics reply_tx_stats; |
994 | struct reply_agg_tx_error_statistics reply_agg_tx_stats; | 965 | struct reply_agg_tx_error_statistics reply_agg_tx_stats; |
995 | /* notification wait support */ | ||
996 | struct list_head notif_waits; | ||
997 | spinlock_t notif_wait_lock; | ||
998 | wait_queue_head_t notif_waitq; | ||
999 | 966 | ||
1000 | /* remain-on-channel offload support */ | 967 | /* remain-on-channel offload support */ |
1001 | struct ieee80211_channel *hw_roc_channel; | 968 | struct ieee80211_channel *hw_roc_channel; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index aa4905a2e794..39aa9cf5b847 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h | |||
@@ -274,6 +274,35 @@ enum iwl_ucode_type { | |||
274 | }; | 274 | }; |
275 | 275 | ||
276 | /** | 276 | /** |
277 | * struct iwl_notification_wait - notification wait entry | ||
278 | * @list: list head for global list | ||
279 | * @fn: function called with the notification | ||
280 | * @cmd: command ID | ||
281 | * | ||
282 | * This structure is not used directly, to wait for a | ||
283 | * notification declare it on the stack, and call | ||
284 | * iwlagn_init_notification_wait() with appropriate | ||
285 | * parameters. Then do whatever will cause the ucode | ||
286 | * to notify the driver, and to wait for that then | ||
287 | * call iwlagn_wait_notification(). | ||
288 | * | ||
289 | * Each notification is one-shot. If at some point we | ||
290 | * need to support multi-shot notifications (which | ||
291 | * can't be allocated on the stack) we need to modify | ||
292 | * the code for them. | ||
293 | */ | ||
294 | struct iwl_notification_wait { | ||
295 | struct list_head list; | ||
296 | |||
297 | void (*fn)(struct iwl_priv *priv, struct iwl_rx_packet *pkt, | ||
298 | void *data); | ||
299 | void *fn_data; | ||
300 | |||
301 | u8 cmd; | ||
302 | bool triggered, aborted; | ||
303 | }; | ||
304 | |||
305 | /** | ||
277 | * struct iwl_shared - shared fields for all the layers of the driver | 306 | * struct iwl_shared - shared fields for all the layers of the driver |
278 | * | 307 | * |
279 | * @dbg_level_dev: dbg level set per device. Prevails on | 308 | * @dbg_level_dev: dbg level set per device. Prevails on |
@@ -290,6 +319,10 @@ enum iwl_ucode_type { | |||
290 | * @sta_lock: protects the station table. | 319 | * @sta_lock: protects the station table. |
291 | * If lock and sta_lock are needed, lock must be acquired first. | 320 | * If lock and sta_lock are needed, lock must be acquired first. |
292 | * @mutex: | 321 | * @mutex: |
322 | * @ucode_type: indicator of loaded ucode image | ||
323 | * @notif_waits: things waiting for notification | ||
324 | * @notif_wait_lock: lock protecting notification | ||
325 | * @notif_waitq: head of notification wait queue | ||
293 | */ | 326 | */ |
294 | struct iwl_shared { | 327 | struct iwl_shared { |
295 | #ifdef CONFIG_IWLWIFI_DEBUG | 328 | #ifdef CONFIG_IWLWIFI_DEBUG |
@@ -320,6 +353,11 @@ struct iwl_shared { | |||
320 | 353 | ||
321 | /* ucode related variables */ | 354 | /* ucode related variables */ |
322 | enum iwl_ucode_type ucode_type; | 355 | enum iwl_ucode_type ucode_type; |
356 | |||
357 | /* notification wait support */ | ||
358 | struct list_head notif_waits; | ||
359 | spinlock_t notif_wait_lock; | ||
360 | wait_queue_head_t notif_waitq; | ||
323 | }; | 361 | }; |
324 | 362 | ||
325 | /*Whatever _m is (iwl_trans, iwl_priv, iwl_bus, these macros will work */ | 363 | /*Whatever _m is (iwl_trans, iwl_priv, iwl_bus, these macros will work */ |
@@ -463,6 +501,24 @@ bool iwl_check_for_ct_kill(struct iwl_priv *priv); | |||
463 | void iwl_stop_sw_queue(struct iwl_priv *priv, u8 ac); | 501 | void iwl_stop_sw_queue(struct iwl_priv *priv, u8 ac); |
464 | void iwl_wake_sw_queue(struct iwl_priv *priv, u8 ac); | 502 | void iwl_wake_sw_queue(struct iwl_priv *priv, u8 ac); |
465 | 503 | ||
504 | /* notification wait support */ | ||
505 | void iwl_abort_notification_waits(struct iwl_shared *shrd); | ||
506 | void __acquires(wait_entry) | ||
507 | iwl_init_notification_wait(struct iwl_shared *shrd, | ||
508 | struct iwl_notification_wait *wait_entry, | ||
509 | u8 cmd, | ||
510 | void (*fn)(struct iwl_priv *priv, | ||
511 | struct iwl_rx_packet *pkt, | ||
512 | void *data), | ||
513 | void *fn_data); | ||
514 | int __must_check __releases(wait_entry) | ||
515 | iwl_wait_notification(struct iwl_shared *shrd, | ||
516 | struct iwl_notification_wait *wait_entry, | ||
517 | unsigned long timeout); | ||
518 | void __releases(wait_entry) | ||
519 | iwl_remove_notification(struct iwl_shared *shrd, | ||
520 | struct iwl_notification_wait *wait_entry); | ||
521 | |||
466 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 522 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
467 | void iwl_reset_traffic_log(struct iwl_priv *priv); | 523 | void iwl_reset_traffic_log(struct iwl_priv *priv); |
468 | #endif /* CONFIG_IWLWIFI_DEBUGFS */ | 524 | #endif /* CONFIG_IWLWIFI_DEBUGFS */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.c b/drivers/net/wireless/iwlwifi/iwl-testmode.c index ed2a3d749b1b..ff72dbcfd52d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.c +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.c | |||
@@ -373,7 +373,7 @@ static int iwl_testmode_cfg_init_calib(struct iwl_priv *priv) | |||
373 | struct iwl_notification_wait calib_wait; | 373 | struct iwl_notification_wait calib_wait; |
374 | int ret; | 374 | int ret; |
375 | 375 | ||
376 | iwlagn_init_notification_wait(priv, &calib_wait, | 376 | iwl_init_notification_wait(priv->shrd, &calib_wait, |
377 | CALIBRATION_COMPLETE_NOTIFICATION, | 377 | CALIBRATION_COMPLETE_NOTIFICATION, |
378 | NULL, NULL); | 378 | NULL, NULL); |
379 | ret = iwlagn_init_alive_start(priv); | 379 | ret = iwlagn_init_alive_start(priv); |
@@ -383,14 +383,14 @@ static int iwl_testmode_cfg_init_calib(struct iwl_priv *priv) | |||
383 | goto cfg_init_calib_error; | 383 | goto cfg_init_calib_error; |
384 | } | 384 | } |
385 | 385 | ||
386 | ret = iwlagn_wait_notification(priv, &calib_wait, 2 * HZ); | 386 | ret = iwl_wait_notification(priv->shrd, &calib_wait, 2 * HZ); |
387 | if (ret) | 387 | if (ret) |
388 | IWL_DEBUG_INFO(priv, "Error detecting" | 388 | IWL_DEBUG_INFO(priv, "Error detecting" |
389 | " CALIBRATION_COMPLETE_NOTIFICATION: %d\n", ret); | 389 | " CALIBRATION_COMPLETE_NOTIFICATION: %d\n", ret); |
390 | return ret; | 390 | return ret; |
391 | 391 | ||
392 | cfg_init_calib_error: | 392 | cfg_init_calib_error: |
393 | iwlagn_remove_notification(priv, &calib_wait); | 393 | iwl_remove_notification(priv->shrd, &calib_wait); |
394 | return ret; | 394 | return ret; |
395 | } | 395 | } |
396 | 396 | ||
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, | |||
571 | alive_data->valid = palive->is_valid == UCODE_VALID_OK; | 571 | alive_data->valid = palive->is_valid == UCODE_VALID_OK; |
572 | } | 572 | } |
573 | 573 | ||
574 | /* notification wait support */ | ||
575 | void iwl_init_notification_wait(struct iwl_shared *shrd, | ||
576 | struct iwl_notification_wait *wait_entry, | ||
577 | u8 cmd, | ||
578 | void (*fn)(struct iwl_priv *priv, | ||
579 | struct iwl_rx_packet *pkt, | ||
580 | void *data), | ||
581 | void *fn_data) | ||
582 | { | ||
583 | wait_entry->fn = fn; | ||
584 | wait_entry->fn_data = fn_data; | ||
585 | wait_entry->cmd = cmd; | ||
586 | wait_entry->triggered = false; | ||
587 | wait_entry->aborted = false; | ||
588 | |||
589 | spin_lock_bh(&shrd->notif_wait_lock); | ||
590 | list_add(&wait_entry->list, &shrd->notif_waits); | ||
591 | spin_unlock_bh(&shrd->notif_wait_lock); | ||
592 | } | ||
593 | |||
594 | int iwl_wait_notification(struct iwl_shared *shrd, | ||
595 | struct iwl_notification_wait *wait_entry, | ||
596 | unsigned long timeout) | ||
597 | { | ||
598 | int ret; | ||
599 | |||
600 | ret = wait_event_timeout(shrd->notif_waitq, | ||
601 | wait_entry->triggered || wait_entry->aborted, | ||
602 | timeout); | ||
603 | |||
604 | spin_lock_bh(&shrd->notif_wait_lock); | ||
605 | list_del(&wait_entry->list); | ||
606 | spin_unlock_bh(&shrd->notif_wait_lock); | ||
607 | |||
608 | if (wait_entry->aborted) | ||
609 | return -EIO; | ||
610 | |||
611 | /* return value is always >= 0 */ | ||
612 | if (ret <= 0) | ||
613 | return -ETIMEDOUT; | ||
614 | return 0; | ||
615 | } | ||
616 | |||
617 | void iwl_remove_notification(struct iwl_shared *shrd, | ||
618 | struct iwl_notification_wait *wait_entry) | ||
619 | { | ||
620 | spin_lock_bh(&shrd->notif_wait_lock); | ||
621 | list_del(&wait_entry->list); | ||
622 | spin_unlock_bh(&shrd->notif_wait_lock); | ||
623 | } | ||
624 | |||
625 | void iwl_abort_notification_waits(struct iwl_shared *shrd) | ||
626 | { | ||
627 | unsigned long flags; | ||
628 | struct iwl_notification_wait *wait_entry; | ||
629 | |||
630 | spin_lock_irqsave(&shrd->notif_wait_lock, flags); | ||
631 | list_for_each_entry(wait_entry, &shrd->notif_waits, list) | ||
632 | wait_entry->aborted = true; | ||
633 | spin_unlock_irqrestore(&shrd->notif_wait_lock, flags); | ||
634 | |||
635 | wake_up_all(&shrd->notif_waitq); | ||
636 | } | ||
637 | |||
574 | #define UCODE_ALIVE_TIMEOUT HZ | 638 | #define UCODE_ALIVE_TIMEOUT HZ |
575 | #define UCODE_CALIB_TIMEOUT (2*HZ) | 639 | #define UCODE_CALIB_TIMEOUT (2*HZ) |
576 | 640 | ||
@@ -587,7 +651,7 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, | |||
587 | if (ret) | 651 | if (ret) |
588 | return ret; | 652 | return ret; |
589 | 653 | ||
590 | iwlagn_init_notification_wait(priv, &alive_wait, REPLY_ALIVE, | 654 | iwl_init_notification_wait(trans->shrd, &alive_wait, REPLY_ALIVE, |
591 | iwl_alive_fn, &alive_data); | 655 | iwl_alive_fn, &alive_data); |
592 | 656 | ||
593 | old_type = trans->shrd->ucode_type; | 657 | old_type = trans->shrd->ucode_type; |
@@ -596,7 +660,7 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, | |||
596 | ret = iwl_load_given_ucode(trans, ucode_type); | 660 | ret = iwl_load_given_ucode(trans, ucode_type); |
597 | if (ret) { | 661 | if (ret) { |
598 | trans->shrd->ucode_type = old_type; | 662 | trans->shrd->ucode_type = old_type; |
599 | iwlagn_remove_notification(priv, &alive_wait); | 663 | iwl_remove_notification(trans->shrd, &alive_wait); |
600 | return ret; | 664 | return ret; |
601 | } | 665 | } |
602 | 666 | ||
@@ -606,7 +670,8 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, | |||
606 | * Some things may run in the background now, but we | 670 | * Some things may run in the background now, but we |
607 | * just wait for the ALIVE notification here. | 671 | * just wait for the ALIVE notification here. |
608 | */ | 672 | */ |
609 | ret = iwlagn_wait_notification(priv, &alive_wait, UCODE_ALIVE_TIMEOUT); | 673 | ret = iwl_wait_notification(trans->shrd, &alive_wait, |
674 | UCODE_ALIVE_TIMEOUT); | ||
610 | if (ret) { | 675 | if (ret) { |
611 | trans->shrd->ucode_type = old_type; | 676 | trans->shrd->ucode_type = old_type; |
612 | return ret; | 677 | return ret; |
@@ -659,7 +724,7 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv) | |||
659 | if (priv->shrd->ucode_type != IWL_UCODE_NONE) | 724 | if (priv->shrd->ucode_type != IWL_UCODE_NONE) |
660 | return 0; | 725 | return 0; |
661 | 726 | ||
662 | iwlagn_init_notification_wait(priv, &calib_wait, | 727 | iwl_init_notification_wait(priv->shrd, &calib_wait, |
663 | CALIBRATION_COMPLETE_NOTIFICATION, | 728 | CALIBRATION_COMPLETE_NOTIFICATION, |
664 | NULL, NULL); | 729 | NULL, NULL); |
665 | 730 | ||
@@ -676,12 +741,13 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv) | |||
676 | * Some things may run in the background now, but we | 741 | * Some things may run in the background now, but we |
677 | * just wait for the calibration complete notification. | 742 | * just wait for the calibration complete notification. |
678 | */ | 743 | */ |
679 | ret = iwlagn_wait_notification(priv, &calib_wait, UCODE_CALIB_TIMEOUT); | 744 | ret = iwl_wait_notification(priv->shrd, &calib_wait, |
745 | UCODE_CALIB_TIMEOUT); | ||
680 | 746 | ||
681 | goto out; | 747 | goto out; |
682 | 748 | ||
683 | error: | 749 | error: |
684 | iwlagn_remove_notification(priv, &calib_wait); | 750 | iwl_remove_notification(priv->shrd, &calib_wait); |
685 | out: | 751 | out: |
686 | /* Whatever happened, stop the device */ | 752 | /* Whatever happened, stop the device */ |
687 | iwl_trans_stop_device(trans(priv)); | 753 | iwl_trans_stop_device(trans(priv)); |