Commit 79e3b16b authored by Don Fry's avatar Don Fry Committed by John W. Linville

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: default avatarDon Fry <donald.h.fry@intel.com>
Signed-off-by: default avatarWey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent a96b724d
...@@ -934,57 +934,6 @@ u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant, u8 valid) ...@@ -934,57 +934,6 @@ u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant, u8 valid)
return ant; return ant;
} }
/* notification wait support */
void iwlagn_init_notification_wait(struct iwl_priv *priv,
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(&priv->notif_wait_lock);
list_add(&wait_entry->list, &priv->notif_waits);
spin_unlock_bh(&priv->notif_wait_lock);
}
int iwlagn_wait_notification(struct iwl_priv *priv,
struct iwl_notification_wait *wait_entry,
unsigned long timeout)
{
int ret;
ret = wait_event_timeout(priv->notif_waitq,
wait_entry->triggered || wait_entry->aborted,
timeout);
spin_lock_bh(&priv->notif_wait_lock);
list_del(&wait_entry->list);
spin_unlock_bh(&priv->notif_wait_lock);
if (wait_entry->aborted)
return -EIO;
/* return value is always >= 0 */
if (ret <= 0)
return -ETIMEDOUT;
return 0;
}
void iwlagn_remove_notification(struct iwl_priv *priv,
struct iwl_notification_wait *wait_entry)
{
spin_lock_bh(&priv->notif_wait_lock);
list_del(&wait_entry->list);
spin_unlock_bh(&priv->notif_wait_lock);
}
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
static void iwlagn_convert_p1k(u16 *p1k, __le16 *out) static void iwlagn_convert_p1k(u16 *p1k, __le16 *out)
{ {
......
...@@ -1131,9 +1131,9 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv) ...@@ -1131,9 +1131,9 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv)
priv->rx_handlers[REPLY_TX] = iwlagn_rx_reply_tx; priv->rx_handlers[REPLY_TX] = iwlagn_rx_reply_tx;
/* set up notification wait support */ /* set up notification wait support */
spin_lock_init(&priv->notif_wait_lock); spin_lock_init(&priv->shrd->notif_wait_lock);
INIT_LIST_HEAD(&priv->notif_waits); INIT_LIST_HEAD(&priv->shrd->notif_waits);
init_waitqueue_head(&priv->notif_waitq); init_waitqueue_head(&priv->shrd->notif_waitq);
/* Set up BT Rx handlers */ /* Set up BT Rx handlers */
if (priv->cfg->lib->bt_rx_handler_setup) 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,11 +1152,11 @@ int iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
* even if the RX handler consumes the RXB we have * even if the RX handler consumes the RXB we have
* access to it in the notification wait entry. * access to it in the notification wait entry.
*/ */
if (!list_empty(&priv->notif_waits)) { if (!list_empty(&priv->shrd->notif_waits)) {
struct iwl_notification_wait *w; struct iwl_notification_wait *w;
spin_lock(&priv->notif_wait_lock); spin_lock(&priv->shrd->notif_wait_lock);
list_for_each_entry(w, &priv->notif_waits, list) { list_for_each_entry(w, &priv->shrd->notif_waits, list) {
if (w->cmd != pkt->hdr.cmd) if (w->cmd != pkt->hdr.cmd)
continue; continue;
IWL_DEBUG_RX(priv, IWL_DEBUG_RX(priv,
...@@ -1167,9 +1167,9 @@ int iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, ...@@ -1167,9 +1167,9 @@ int iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
if (w->fn) if (w->fn)
w->fn(priv, pkt, w->fn_data); w->fn(priv, pkt, w->fn_data);
} }
spin_unlock(&priv->notif_wait_lock); spin_unlock(&priv->shrd->notif_wait_lock);
wake_up_all(&priv->notif_waitq); wake_up_all(&priv->shrd->notif_waitq);
} }
if (priv->pre_rx_handler) if (priv->pre_rx_handler)
......
...@@ -60,7 +60,7 @@ static int iwlagn_disable_pan(struct iwl_priv *priv, ...@@ -60,7 +60,7 @@ static int iwlagn_disable_pan(struct iwl_priv *priv,
u8 old_dev_type = send->dev_type; u8 old_dev_type = send->dev_type;
int ret; int ret;
iwlagn_init_notification_wait(priv, &disable_wait, iwl_init_notification_wait(priv->shrd, &disable_wait,
REPLY_WIPAN_DEACTIVATION_COMPLETE, REPLY_WIPAN_DEACTIVATION_COMPLETE,
NULL, NULL); NULL, NULL);
...@@ -74,9 +74,9 @@ static int iwlagn_disable_pan(struct iwl_priv *priv, ...@@ -74,9 +74,9 @@ static int iwlagn_disable_pan(struct iwl_priv *priv,
if (ret) { if (ret) {
IWL_ERR(priv, "Error disabling PAN (%d)\n", ret); IWL_ERR(priv, "Error disabling PAN (%d)\n", ret);
iwlagn_remove_notification(priv, &disable_wait); iwl_remove_notification(priv->shrd, &disable_wait);
} else { } else {
ret = iwlagn_wait_notification(priv, &disable_wait, HZ); ret = iwl_wait_notification(priv->shrd, &disable_wait, HZ);
if (ret) if (ret)
IWL_ERR(priv, "Timed out waiting for PAN disable\n"); IWL_ERR(priv, "Timed out waiting for PAN disable\n");
} }
......
...@@ -356,22 +356,6 @@ static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags) ...@@ -356,22 +356,6 @@ static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags)
void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv); void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv);
void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac); void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac);
/* notification wait support */
void __acquires(wait_entry)
iwlagn_init_notification_wait(struct iwl_priv *priv,
struct iwl_notification_wait *wait_entry,
u8 cmd,
void (*fn)(struct iwl_priv *priv,
struct iwl_rx_packet *pkt,
void *data),
void *fn_data);
int __must_check __releases(wait_entry)
iwlagn_wait_notification(struct iwl_priv *priv,
struct iwl_notification_wait *wait_entry,
unsigned long timeout);
void __releases(wait_entry)
iwlagn_remove_notification(struct iwl_priv *priv,
struct iwl_notification_wait *wait_entry);
extern int iwlagn_init_alive_start(struct iwl_priv *priv); extern int iwlagn_init_alive_start(struct iwl_priv *priv);
extern int iwl_alive_start(struct iwl_priv *priv); extern int iwl_alive_start(struct iwl_priv *priv);
/* svtool */ /* svtool */
......
...@@ -836,19 +836,6 @@ void iwl_print_rx_config_cmd(struct iwl_priv *priv, ...@@ -836,19 +836,6 @@ void iwl_print_rx_config_cmd(struct iwl_priv *priv,
} }
#endif #endif
static void iwlagn_abort_notification_waits(struct iwl_priv *priv)
{
unsigned long flags;
struct iwl_notification_wait *wait_entry;
spin_lock_irqsave(&priv->notif_wait_lock, flags);
list_for_each_entry(wait_entry, &priv->notif_waits, list)
wait_entry->aborted = true;
spin_unlock_irqrestore(&priv->notif_wait_lock, flags);
wake_up_all(&priv->notif_waitq);
}
void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
{ {
unsigned int reload_msec; unsigned int reload_msec;
...@@ -860,7 +847,7 @@ void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) ...@@ -860,7 +847,7 @@ void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
/* Cancel currently queued command. */ /* Cancel currently queued command. */
clear_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status); clear_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status);
iwlagn_abort_notification_waits(priv); iwl_abort_notification_waits(priv->shrd);
/* Keep the restart process from trying to send host /* Keep the restart process from trying to send host
* commands by clearing the ready bit */ * commands by clearing the ready bit */
......
...@@ -689,35 +689,6 @@ struct iwl_force_reset { ...@@ -689,35 +689,6 @@ struct iwl_force_reset {
*/ */
#define IWLAGN_EXT_BEACON_TIME_POS 22 #define IWLAGN_EXT_BEACON_TIME_POS 22
/**
* struct iwl_notification_wait - notification wait entry
* @list: list head for global list
* @fn: function called with the notification
* @cmd: command ID
*
* This structure is not used directly, to wait for a
* notification declare it on the stack, and call
* iwlagn_init_notification_wait() with appropriate
* parameters. Then do whatever will cause the ucode
* to notify the driver, and to wait for that then
* call iwlagn_wait_notification().
*
* Each notification is one-shot. If at some point we
* need to support multi-shot notifications (which
* can't be allocated on the stack) we need to modify
* the code for them.
*/
struct iwl_notification_wait {
struct list_head list;
void (*fn)(struct iwl_priv *priv, struct iwl_rx_packet *pkt,
void *data);
void *fn_data;
u8 cmd;
bool triggered, aborted;
};
struct iwl_rxon_context { struct iwl_rxon_context {
struct ieee80211_vif *vif; struct ieee80211_vif *vif;
...@@ -992,10 +963,6 @@ struct iwl_priv { ...@@ -992,10 +963,6 @@ struct iwl_priv {
/* counts reply_tx error */ /* counts reply_tx error */
struct reply_tx_error_statistics reply_tx_stats; struct reply_tx_error_statistics reply_tx_stats;
struct reply_agg_tx_error_statistics reply_agg_tx_stats; struct reply_agg_tx_error_statistics reply_agg_tx_stats;
/* notification wait support */
struct list_head notif_waits;
spinlock_t notif_wait_lock;
wait_queue_head_t notif_waitq;
/* remain-on-channel offload support */ /* remain-on-channel offload support */
struct ieee80211_channel *hw_roc_channel; struct ieee80211_channel *hw_roc_channel;
......
...@@ -273,6 +273,35 @@ enum iwl_ucode_type { ...@@ -273,6 +273,35 @@ enum iwl_ucode_type {
IWL_UCODE_WOWLAN, IWL_UCODE_WOWLAN,
}; };
/**
* struct iwl_notification_wait - notification wait entry
* @list: list head for global list
* @fn: function called with the notification
* @cmd: command ID
*
* This structure is not used directly, to wait for a
* notification declare it on the stack, and call
* iwlagn_init_notification_wait() with appropriate
* parameters. Then do whatever will cause the ucode
* to notify the driver, and to wait for that then
* call iwlagn_wait_notification().
*
* Each notification is one-shot. If at some point we
* need to support multi-shot notifications (which
* can't be allocated on the stack) we need to modify
* the code for them.
*/
struct iwl_notification_wait {
struct list_head list;
void (*fn)(struct iwl_priv *priv, struct iwl_rx_packet *pkt,
void *data);
void *fn_data;
u8 cmd;
bool triggered, aborted;
};
/** /**
* struct iwl_shared - shared fields for all the layers of the driver * struct iwl_shared - shared fields for all the layers of the driver
* *
...@@ -290,6 +319,10 @@ enum iwl_ucode_type { ...@@ -290,6 +319,10 @@ enum iwl_ucode_type {
* @sta_lock: protects the station table. * @sta_lock: protects the station table.
* If lock and sta_lock are needed, lock must be acquired first. * If lock and sta_lock are needed, lock must be acquired first.
* @mutex: * @mutex:
* @ucode_type: indicator of loaded ucode image
* @notif_waits: things waiting for notification
* @notif_wait_lock: lock protecting notification
* @notif_waitq: head of notification wait queue
*/ */
struct iwl_shared { struct iwl_shared {
#ifdef CONFIG_IWLWIFI_DEBUG #ifdef CONFIG_IWLWIFI_DEBUG
...@@ -320,6 +353,11 @@ struct iwl_shared { ...@@ -320,6 +353,11 @@ struct iwl_shared {
/* ucode related variables */ /* ucode related variables */
enum iwl_ucode_type ucode_type; enum iwl_ucode_type ucode_type;
/* notification wait support */
struct list_head notif_waits;
spinlock_t notif_wait_lock;
wait_queue_head_t notif_waitq;
}; };
/*Whatever _m is (iwl_trans, iwl_priv, iwl_bus, these macros will work */ /*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,6 +501,24 @@ bool iwl_check_for_ct_kill(struct iwl_priv *priv);
void iwl_stop_sw_queue(struct iwl_priv *priv, u8 ac); void iwl_stop_sw_queue(struct iwl_priv *priv, u8 ac);
void iwl_wake_sw_queue(struct iwl_priv *priv, u8 ac); void iwl_wake_sw_queue(struct iwl_priv *priv, u8 ac);
/* notification wait support */
void iwl_abort_notification_waits(struct iwl_shared *shrd);
void __acquires(wait_entry)
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);
int __must_check __releases(wait_entry)
iwl_wait_notification(struct iwl_shared *shrd,
struct iwl_notification_wait *wait_entry,
unsigned long timeout);
void __releases(wait_entry)
iwl_remove_notification(struct iwl_shared *shrd,
struct iwl_notification_wait *wait_entry);
#ifdef CONFIG_IWLWIFI_DEBUGFS #ifdef CONFIG_IWLWIFI_DEBUGFS
void iwl_reset_traffic_log(struct iwl_priv *priv); void iwl_reset_traffic_log(struct iwl_priv *priv);
#endif /* CONFIG_IWLWIFI_DEBUGFS */ #endif /* CONFIG_IWLWIFI_DEBUGFS */
......
...@@ -373,7 +373,7 @@ static int iwl_testmode_cfg_init_calib(struct iwl_priv *priv) ...@@ -373,7 +373,7 @@ static int iwl_testmode_cfg_init_calib(struct iwl_priv *priv)
struct iwl_notification_wait calib_wait; struct iwl_notification_wait calib_wait;
int ret; int ret;
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);
ret = iwlagn_init_alive_start(priv); ret = iwlagn_init_alive_start(priv);
...@@ -383,14 +383,14 @@ static int iwl_testmode_cfg_init_calib(struct iwl_priv *priv) ...@@ -383,14 +383,14 @@ static int iwl_testmode_cfg_init_calib(struct iwl_priv *priv)
goto cfg_init_calib_error; goto cfg_init_calib_error;
} }
ret = iwlagn_wait_notification(priv, &calib_wait, 2 * HZ); ret = iwl_wait_notification(priv->shrd, &calib_wait, 2 * HZ);
if (ret) if (ret)
IWL_DEBUG_INFO(priv, "Error detecting" IWL_DEBUG_INFO(priv, "Error detecting"
" CALIBRATION_COMPLETE_NOTIFICATION: %d\n", ret); " CALIBRATION_COMPLETE_NOTIFICATION: %d\n", ret);
return ret; return ret;
cfg_init_calib_error: cfg_init_calib_error:
iwlagn_remove_notification(priv, &calib_wait); iwl_remove_notification(priv->shrd, &calib_wait);
return ret; return ret;
} }
......
...@@ -571,6 +571,70 @@ static void iwl_alive_fn(struct iwl_priv *priv, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment