* [PATCH 1/5] iwlagn: make iwl_rx_handle static
2011-01-05 0:21 [PATCH 0/5] update for 2.6.38 Wey-Yi Guy
@ 2011-01-05 0:21 ` Wey-Yi Guy
2011-01-05 0:22 ` [PATCH 2/5] iwlagn: add support for waiting for notifications Wey-Yi Guy
` (3 subsequent siblings)
4 siblings, 0 replies; 10+ messages in thread
From: Wey-Yi Guy @ 2011-01-05 0:21 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, ipw3945-devel, Johannes Berg, Wey-Yi Guy
From: Johannes Berg <johannes.berg@intel.com>
It's not used or likely to be needed from other
files, so it can be static.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
---
drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +-
drivers/net/wireless/iwlwifi/iwl-agn.h | 1 -
2 files changed, 1 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 5f11dc2..bd7ae27 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -846,7 +846,7 @@ static void iwl_setup_rx_handlers(struct iwl_priv *priv)
* the appropriate handlers, including command responses,
* frame-received notifications, and other notifications.
*/
-void iwl_rx_handle(struct iwl_priv *priv)
+static void iwl_rx_handle(struct iwl_priv *priv)
{
struct iwl_rx_mem_buffer *rxb;
struct iwl_rx_packet *pkt;
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h
index da30358..e725784 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.h
@@ -185,7 +185,6 @@ void iwlagn_rx_reply_rx(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb);
void iwlagn_rx_reply_rx_phy(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb);
-void iwl_rx_handle(struct iwl_priv *priv);
/* tx */
void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq);
--
1.7.0.4
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH 2/5] iwlagn: add support for waiting for notifications
2011-01-05 0:21 [PATCH 0/5] update for 2.6.38 Wey-Yi Guy
2011-01-05 0:21 ` [PATCH 1/5] iwlagn: make iwl_rx_handle static Wey-Yi Guy
@ 2011-01-05 0:22 ` Wey-Yi Guy
2011-01-05 0:22 ` [PATCH 3/5] iwlagn: properly wait for PAN disable Wey-Yi Guy
` (2 subsequent siblings)
4 siblings, 0 replies; 10+ messages in thread
From: Wey-Yi Guy @ 2011-01-05 0:22 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, ipw3945-devel, Johannes Berg, Wey-Yi Guy
From: Johannes Berg <johannes.berg@intel.com>
In order to implement waiting for notifications,
add a structure that captures the information,
and a list of such structures that will be
traversed when a command is received from the
ucode.
Use sparse checking to make sure calls to the
prepare/wait/cancel functions are always nested
correctly.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
---
drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 46 ++++++++++++++++++++++++++++
drivers/net/wireless/iwlwifi/iwl-agn.c | 21 +++++++++++++
drivers/net/wireless/iwlwifi/iwl-agn.h | 15 +++++++++
drivers/net/wireless/iwlwifi/iwl-dev.h | 33 ++++++++++++++++++++
4 files changed, 115 insertions(+), 0 deletions(-)
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
index 3dee87e..29dcda0 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
@@ -473,6 +473,11 @@ void iwlagn_rx_handler_setup(struct iwl_priv *priv)
priv->rx_handlers[CALIBRATION_COMPLETE_NOTIFICATION] =
iwlagn_rx_calib_complete;
priv->rx_handlers[REPLY_TX] = iwlagn_rx_reply_tx;
+
+ /* set up notification wait support */
+ spin_lock_init(&priv->_agn.notif_wait_lock);
+ INIT_LIST_HEAD(&priv->_agn.notif_waits);
+ init_waitqueue_head(&priv->_agn.notif_waitq);
}
void iwlagn_setup_deferred_work(struct iwl_priv *priv)
@@ -2389,3 +2394,44 @@ int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display)
}
return 0;
}
+
+/* notification wait support */
+void iwlagn_init_notification_wait(struct iwl_priv *priv,
+ struct iwl_notification_wait *wait_entry,
+ void (*fn)(struct iwl_priv *priv,
+ struct iwl_rx_packet *pkt),
+ u8 cmd)
+{
+ wait_entry->fn = fn;
+ wait_entry->cmd = cmd;
+ wait_entry->triggered = false;
+
+ spin_lock_bh(&priv->_agn.notif_wait_lock);
+ list_add(&wait_entry->list, &priv->_agn.notif_waits);
+ spin_unlock_bh(&priv->_agn.notif_wait_lock);
+}
+
+signed long iwlagn_wait_notification(struct iwl_priv *priv,
+ struct iwl_notification_wait *wait_entry,
+ unsigned long timeout)
+{
+ int ret;
+
+ ret = wait_event_timeout(priv->_agn.notif_waitq,
+ &wait_entry->triggered,
+ timeout);
+
+ spin_lock_bh(&priv->_agn.notif_wait_lock);
+ list_del(&wait_entry->list);
+ spin_unlock_bh(&priv->_agn.notif_wait_lock);
+
+ return ret;
+}
+
+void iwlagn_remove_notification(struct iwl_priv *priv,
+ struct iwl_notification_wait *wait_entry)
+{
+ spin_lock_bh(&priv->_agn.notif_wait_lock);
+ list_del(&wait_entry->list);
+ spin_unlock_bh(&priv->_agn.notif_wait_lock);
+}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index bd7ae27..9ac87da 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -910,6 +910,27 @@ static void iwl_rx_handle(struct iwl_priv *priv)
(pkt->hdr.cmd != STATISTICS_NOTIFICATION) &&
(pkt->hdr.cmd != REPLY_TX);
+ /*
+ * Do the notification wait before RX handlers so
+ * even if the RX handler consumes the RXB we have
+ * access to it in the notification wait entry.
+ */
+ if (!list_empty(&priv->_agn.notif_waits)) {
+ struct iwl_notification_wait *w;
+
+ spin_lock(&priv->_agn.notif_wait_lock);
+ list_for_each_entry(w, &priv->_agn.notif_waits, list) {
+ if (w->cmd == pkt->hdr.cmd) {
+ w->triggered = true;
+ if (w->fn)
+ w->fn(priv, pkt);
+ }
+ }
+ spin_unlock(&priv->_agn.notif_wait_lock);
+
+ wake_up_all(&priv->_agn.notif_waitq);
+ }
+
/* Based on type of command response or notification,
* handle those that need handling via function in
* rx_handlers table. See iwl_setup_rx_handlers() */
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h
index e725784..7b6cb83 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.h
@@ -329,6 +329,21 @@ void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac);
int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv);
void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv);
+/* notification wait support */
+void __acquires(wait_entry)
+iwlagn_init_notification_wait(struct iwl_priv *priv,
+ struct iwl_notification_wait *wait_entry,
+ void (*fn)(struct iwl_priv *priv,
+ struct iwl_rx_packet *pkt),
+ u8 cmd);
+signed long __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);
+
/* mac80211 handlers (for 4965) */
int iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
int iwlagn_mac_start(struct ieee80211_hw *hw);
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 8dda678..2ec680b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -34,6 +34,7 @@
#include <linux/pci.h> /* for struct pci_device_id */
#include <linux/kernel.h>
+#include <linux/wait.h>
#include <net/ieee80211_radiotap.h>
#include "iwl-eeprom.h"
@@ -1139,6 +1140,33 @@ struct iwl_force_reset {
*/
#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);
+
+ u8 cmd;
+ bool triggered;
+};
+
enum iwl_rxon_context_id {
IWL_RXON_CTX_BSS,
IWL_RXON_CTX_PAN,
@@ -1463,6 +1491,11 @@ struct iwl_priv {
struct iwl_bt_notif_statistics delta_statistics_bt;
struct iwl_bt_notif_statistics max_delta_bt;
#endif
+
+ /* notification wait support */
+ struct list_head notif_waits;
+ spinlock_t notif_wait_lock;
+ wait_queue_head_t notif_waitq;
} _agn;
#endif
};
--
1.7.0.4
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH 3/5] iwlagn: properly wait for PAN disable
2011-01-05 0:21 [PATCH 0/5] update for 2.6.38 Wey-Yi Guy
2011-01-05 0:21 ` [PATCH 1/5] iwlagn: make iwl_rx_handle static Wey-Yi Guy
2011-01-05 0:22 ` [PATCH 2/5] iwlagn: add support for waiting for notifications Wey-Yi Guy
@ 2011-01-05 0:22 ` Wey-Yi Guy
2011-01-05 0:22 ` [PATCH 4/5] iwlagn: return error if PAN disable timeout Wey-Yi Guy
2011-01-05 0:22 ` [PATCH 5/5] iwlwifi: fix 4965 notification wait setup Wey-Yi Guy
4 siblings, 0 replies; 10+ messages in thread
From: Wey-Yi Guy @ 2011-01-05 0:22 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, ipw3945-devel, Johannes Berg, Wey-Yi Guy
From: Johannes Berg <johannes.berg@intel.com>
Previously I hacked this with an msleep(300)
which was fine since we never had longer PAN
time slots, but now that we will have them I
need to fix that. Use the new notification
wait support to properly wait for the WIPAN
deactivation complete signal from the ucode.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
---
drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 15 ++++++++++++---
drivers/net/wireless/iwlwifi/iwl-commands.h | 1 +
drivers/net/wireless/iwlwifi/iwl-hcmd.c | 1 +
3 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
index 6d140bd..99e9650 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
@@ -52,10 +52,14 @@ static int iwlagn_disable_pan(struct iwl_priv *priv,
struct iwl_rxon_context *ctx,
struct iwl_rxon_cmd *send)
{
+ struct iwl_notification_wait disable_wait;
__le32 old_filter = send->filter_flags;
u8 old_dev_type = send->dev_type;
int ret;
+ iwlagn_init_notification_wait(priv, &disable_wait, NULL,
+ REPLY_WIPAN_DEACTIVATION_COMPLETE);
+
send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
send->dev_type = RXON_DEV_TYPE_P2P;
ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, sizeof(*send), send);
@@ -63,11 +67,16 @@ static int iwlagn_disable_pan(struct iwl_priv *priv,
send->filter_flags = old_filter;
send->dev_type = old_dev_type;
- if (ret)
+ if (ret) {
IWL_ERR(priv, "Error disabling PAN (%d)\n", ret);
+ iwlagn_remove_notification(priv, &disable_wait);
+ } else {
+ signed long wait_res;
- /* FIXME: WAIT FOR PAN DISABLE */
- msleep(300);
+ wait_res = iwlagn_wait_notification(priv, &disable_wait, HZ);
+ if (wait_res == 0)
+ IWL_ERR(priv, "Timed out waiting for PAN disable\n");
+ }
return ret;
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index f893d4a..abe2479 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -189,6 +189,7 @@ enum {
REPLY_WIPAN_WEPKEY = 0xb8, /* use REPLY_WEPKEY structure */
REPLY_WIPAN_P2P_CHANNEL_SWITCH = 0xb9,
REPLY_WIPAN_NOA_NOTIFICATION = 0xbc,
+ REPLY_WIPAN_DEACTIVATION_COMPLETE = 0xbd,
REPLY_MAX = 0xff
};
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
index c373b53..e4b953d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c
+++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
@@ -108,6 +108,7 @@ const char *get_cmd_string(u8 cmd)
IWL_CMD(REPLY_WIPAN_WEPKEY);
IWL_CMD(REPLY_WIPAN_P2P_CHANNEL_SWITCH);
IWL_CMD(REPLY_WIPAN_NOA_NOTIFICATION);
+ IWL_CMD(REPLY_WIPAN_DEACTIVATION_COMPLETE);
default:
return "UNKNOWN";
--
1.7.0.4
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH 4/5] iwlagn: return error if PAN disable timeout
2011-01-05 0:21 [PATCH 0/5] update for 2.6.38 Wey-Yi Guy
` (2 preceding siblings ...)
2011-01-05 0:22 ` [PATCH 3/5] iwlagn: properly wait for PAN disable Wey-Yi Guy
@ 2011-01-05 0:22 ` Wey-Yi Guy
2011-01-05 0:22 ` [PATCH 5/5] iwlwifi: fix 4965 notification wait setup Wey-Yi Guy
4 siblings, 0 replies; 10+ messages in thread
From: Wey-Yi Guy @ 2011-01-05 0:22 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, ipw3945-devel, Johannes Berg, Wey-Yi Guy
From: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
---
drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 4 +++-
1 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
index 99e9650..6e80f10 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
@@ -74,8 +74,10 @@ static int iwlagn_disable_pan(struct iwl_priv *priv,
signed long wait_res;
wait_res = iwlagn_wait_notification(priv, &disable_wait, HZ);
- if (wait_res == 0)
+ if (wait_res == 0) {
IWL_ERR(priv, "Timed out waiting for PAN disable\n");
+ ret = -EIO;
+ }
}
return ret;
--
1.7.0.4
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH 5/5] iwlwifi: fix 4965 notification wait setup
2011-01-05 0:21 [PATCH 0/5] update for 2.6.38 Wey-Yi Guy
` (3 preceding siblings ...)
2011-01-05 0:22 ` [PATCH 4/5] iwlagn: return error if PAN disable timeout Wey-Yi Guy
@ 2011-01-05 0:22 ` Wey-Yi Guy
4 siblings, 0 replies; 10+ messages in thread
From: Wey-Yi Guy @ 2011-01-05 0:22 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, ipw3945-devel, Johannes Berg, Wey-Yi Guy
From: Johannes Berg <johannes.berg@intel.com>
The notification wait support code is shared
between 4965 and other AGN devices, so 4965
also has to initialize the data structures
for it, otherwise it crashes.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
---
drivers/net/wireless/iwlwifi/iwl-4965.c | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 3f1e5f1..d9a7d93 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -2316,6 +2316,11 @@ static void iwl4965_rx_handler_setup(struct iwl_priv *priv)
priv->rx_handlers[REPLY_RX] = iwlagn_rx_reply_rx;
/* Tx response */
priv->rx_handlers[REPLY_TX] = iwl4965_rx_reply_tx;
+
+ /* set up notification wait support */
+ spin_lock_init(&priv->_agn.notif_wait_lock);
+ INIT_LIST_HEAD(&priv->_agn.notif_waits);
+ init_waitqueue_head(&priv->_agn.notif_waitq);
}
static void iwl4965_setup_deferred_work(struct iwl_priv *priv)
--
1.7.0.4
^ permalink raw reply related [flat|nested] 10+ messages in thread