* [PATCH v2 01/17] mwifiex: rename mwifiex_free_adapter() routine in init.c
2013-05-18 0:50 [PATCH v2 00/17] mwifiex updates for 3.11 Bing Zhao
@ 2013-05-18 0:50 ` Bing Zhao
2013-05-18 0:50 ` [PATCH v2 02/17] mwifiex: scan delay timer cleanup in unload path Bing Zhao
` (8 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Bing Zhao @ 2013-05-18 0:50 UTC (permalink / raw)
To: linux-wireless
Cc: John W. Linville, Amitkumar Karwar, Avinash Patil,
Yogesh Ashok Powar, Nishant Sarmukadam, Frank Huang, Bing Zhao
From: Amitkumar Karwar <akarwar@marvell.com>
We have two different static routines with name
mwifiex_free_adapter(). The routine in main.c actually frees the
adapter structure.
We will rename other routine in init.c to mwifiex_adapter_cleanup()
to avoid confusion.
Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
---
drivers/net/wireless/mwifiex/init.c | 18 ++++++++----------
1 file changed, 8 insertions(+), 10 deletions(-)
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c
index 9f44fda..58e151e 100644
--- a/drivers/net/wireless/mwifiex/init.c
+++ b/drivers/net/wireless/mwifiex/init.c
@@ -447,17 +447,16 @@ static void mwifiex_free_lock_list(struct mwifiex_adapter *adapter)
}
/*
- * This function frees the adapter structure.
+ * This function performs cleanup for adapter structure.
*
- * The freeing operation is done recursively, by canceling all
- * pending commands, freeing the member buffers previously
- * allocated (command buffers, scan table buffer, sleep confirm
- * command buffer), stopping the timers and calling the cleanup
- * routines for every interface, before the actual adapter
- * structure is freed.
+ * The cleanup is done recursively, by canceling all pending
+ * commands, freeing the member buffers previously allocated
+ * (command buffers, scan table buffer, sleep confirm command
+ * buffer), stopping the timers and calling the cleanup routines
+ * for every interface.
*/
static void
-mwifiex_free_adapter(struct mwifiex_adapter *adapter)
+mwifiex_adapter_cleanup(struct mwifiex_adapter *adapter)
{
if (!adapter) {
pr_err("%s: adapter is NULL\n", __func__);
@@ -733,8 +732,7 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter)
}
}
- /* Free adapter structure */
- mwifiex_free_adapter(adapter);
+ mwifiex_adapter_cleanup(adapter);
spin_unlock_irqrestore(&adapter->mwifiex_lock, flags);
--
1.8.2.3
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH v2 02/17] mwifiex: scan delay timer cleanup in unload path
2013-05-18 0:50 [PATCH v2 00/17] mwifiex updates for 3.11 Bing Zhao
2013-05-18 0:50 ` [PATCH v2 01/17] mwifiex: rename mwifiex_free_adapter() routine in init.c Bing Zhao
@ 2013-05-18 0:50 ` Bing Zhao
2013-05-18 0:50 ` [PATCH v2 03/17] mwifiex: remove global user_scan_cfg variable Bing Zhao
` (7 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Bing Zhao @ 2013-05-18 0:50 UTC (permalink / raw)
To: linux-wireless
Cc: John W. Linville, Amitkumar Karwar, Avinash Patil,
Yogesh Ashok Powar, Nishant Sarmukadam, Frank Huang, Bing Zhao
From: Amitkumar Karwar <akarwar@marvell.com>
Return from scan delay timer routine if surprise_removed flag
is true. Also, cancel the timer in unload path.
This fixes a crash when scan delay timer accesses structures
that have been freed already.
Tested with "iwlist mlan0 scan & sleep 1; rmmod mwifiex_sdio"
Reported-by: Daniel Drake <dsd@laptop.org>
Tested-by: Daniel Drake <dsd@laptop.org>
Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
---
drivers/net/wireless/mwifiex/init.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c
index 58e151e..71bbf12 100644
--- a/drivers/net/wireless/mwifiex/init.c
+++ b/drivers/net/wireless/mwifiex/init.c
@@ -59,6 +59,9 @@ static void scan_delay_timer_fn(unsigned long data)
struct cmd_ctrl_node *cmd_node, *tmp_node;
unsigned long flags;
+ if (adapter->surprise_removed)
+ return;
+
if (adapter->scan_delay_cnt == MWIFIEX_MAX_SCAN_DELAY_CNT) {
/*
* Abort scan operation by cancelling all pending scan
@@ -458,11 +461,18 @@ static void mwifiex_free_lock_list(struct mwifiex_adapter *adapter)
static void
mwifiex_adapter_cleanup(struct mwifiex_adapter *adapter)
{
+ int i;
+
if (!adapter) {
pr_err("%s: adapter is NULL\n", __func__);
return;
}
+ for (i = 0; i < adapter->priv_num; i++) {
+ if (adapter->priv[i])
+ del_timer_sync(&adapter->priv[i]->scan_delay_timer);
+ }
+
mwifiex_cancel_all_pending_cmd(adapter);
/* Free lock variables */
--
1.8.2.3
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH v2 03/17] mwifiex: remove global user_scan_cfg variable
2013-05-18 0:50 [PATCH v2 00/17] mwifiex updates for 3.11 Bing Zhao
2013-05-18 0:50 ` [PATCH v2 01/17] mwifiex: rename mwifiex_free_adapter() routine in init.c Bing Zhao
2013-05-18 0:50 ` [PATCH v2 02/17] mwifiex: scan delay timer cleanup in unload path Bing Zhao
@ 2013-05-18 0:50 ` Bing Zhao
2013-05-18 0:50 ` [PATCH v2 04/17] mwifiex: abort remaining scan commands when association started Bing Zhao
` (6 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Bing Zhao @ 2013-05-18 0:50 UTC (permalink / raw)
To: linux-wireless
Cc: John W. Linville, Amitkumar Karwar, Avinash Patil,
Yogesh Ashok Powar, Nishant Sarmukadam, Frank Huang, Bing Zhao
From: Amitkumar Karwar <akarwar@marvell.com>
As the variable is used only for preparation of internal scan
commands, we don't need to keep it allocated until the entire
scan completes. We will define it as a local variable and free
immediately after it's use.
New flag 'scan_aborting' is added to handle race between
mwifiex_close() and scan handler. Previously user_scan_cfg
pointer used to take care of this.
This patch fixes a memory leak in mwifiex_cfg80211_scan after
running "iwlist mlan0 scan & sleep 1; rmmod mwifiex_sdio".
Reported-by: Daniel Drake <dsd@laptop.org>
Tested-by: Daniel Drake <dsd@laptop.org>
Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
---
drivers/net/wireless/mwifiex/cfg80211.c | 31 +++++++++++++++++--------------
drivers/net/wireless/mwifiex/init.c | 20 +++++++-------------
drivers/net/wireless/mwifiex/main.c | 1 +
drivers/net/wireless/mwifiex/main.h | 2 +-
drivers/net/wireless/mwifiex/scan.c | 22 ++++++++--------------
5 files changed, 34 insertions(+), 42 deletions(-)
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index e42b266..e493f89 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -1859,6 +1859,7 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,
int i, offset, ret;
struct ieee80211_channel *chan;
struct ieee_types_header *ie;
+ struct mwifiex_user_scan_cfg *user_scan_cfg;
wiphy_dbg(wiphy, "info: received scan request on %s\n", dev->name);
@@ -1869,20 +1870,22 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,
return -EBUSY;
}
- if (priv->user_scan_cfg) {
+ /* Block scan request if scan operation or scan cleanup when interface
+ * is disabled is in process
+ */
+ if (priv->scan_request || priv->scan_aborting) {
dev_err(priv->adapter->dev, "cmd: Scan already in process..\n");
return -EBUSY;
}
- priv->user_scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg),
- GFP_KERNEL);
- if (!priv->user_scan_cfg)
+ user_scan_cfg = kzalloc(sizeof(*user_scan_cfg), GFP_KERNEL);
+ if (!user_scan_cfg)
return -ENOMEM;
priv->scan_request = request;
- priv->user_scan_cfg->num_ssids = request->n_ssids;
- priv->user_scan_cfg->ssid_list = request->ssids;
+ user_scan_cfg->num_ssids = request->n_ssids;
+ user_scan_cfg->ssid_list = request->ssids;
if (request->ie && request->ie_len) {
offset = 0;
@@ -1902,25 +1905,25 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,
for (i = 0; i < min_t(u32, request->n_channels,
MWIFIEX_USER_SCAN_CHAN_MAX); i++) {
chan = request->channels[i];
- priv->user_scan_cfg->chan_list[i].chan_number = chan->hw_value;
- priv->user_scan_cfg->chan_list[i].radio_type = chan->band;
+ user_scan_cfg->chan_list[i].chan_number = chan->hw_value;
+ user_scan_cfg->chan_list[i].radio_type = chan->band;
if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)
- priv->user_scan_cfg->chan_list[i].scan_type =
+ user_scan_cfg->chan_list[i].scan_type =
MWIFIEX_SCAN_TYPE_PASSIVE;
else
- priv->user_scan_cfg->chan_list[i].scan_type =
+ user_scan_cfg->chan_list[i].scan_type =
MWIFIEX_SCAN_TYPE_ACTIVE;
- priv->user_scan_cfg->chan_list[i].scan_time = 0;
+ user_scan_cfg->chan_list[i].scan_time = 0;
}
- ret = mwifiex_scan_networks(priv, priv->user_scan_cfg);
+ ret = mwifiex_scan_networks(priv, user_scan_cfg);
+ kfree(user_scan_cfg);
if (ret) {
dev_err(priv->adapter->dev, "scan failed: %d\n", ret);
+ priv->scan_aborting = false;
priv->scan_request = NULL;
- kfree(priv->user_scan_cfg);
- priv->user_scan_cfg = NULL;
return ret;
}
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c
index 71bbf12..1343725f 100644
--- a/drivers/net/wireless/mwifiex/init.c
+++ b/drivers/net/wireless/mwifiex/init.c
@@ -81,19 +81,13 @@ static void scan_delay_timer_fn(unsigned long data)
adapter->empty_tx_q_cnt = 0;
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
- if (priv->user_scan_cfg) {
- if (priv->scan_request) {
- dev_dbg(priv->adapter->dev,
- "info: aborting scan\n");
- cfg80211_scan_done(priv->scan_request, 1);
- priv->scan_request = NULL;
- } else {
- dev_dbg(priv->adapter->dev,
- "info: scan already aborted\n");
- }
-
- kfree(priv->user_scan_cfg);
- priv->user_scan_cfg = NULL;
+ if (priv->scan_request) {
+ dev_dbg(adapter->dev, "info: aborting scan\n");
+ cfg80211_scan_done(priv->scan_request, 1);
+ priv->scan_request = NULL;
+ } else {
+ priv->scan_aborting = false;
+ dev_dbg(adapter->dev, "info: scan already aborted\n");
}
goto done;
}
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c
index 2eb88ea..4e7270c 100644
--- a/drivers/net/wireless/mwifiex/main.c
+++ b/drivers/net/wireless/mwifiex/main.c
@@ -436,6 +436,7 @@ mwifiex_close(struct net_device *dev)
dev_dbg(priv->adapter->dev, "aborting scan on ndo_stop\n");
cfg80211_scan_done(priv->scan_request, 1);
priv->scan_request = NULL;
+ priv->scan_aborting = true;
}
return 0;
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index 4ef67fc..81251d9 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -492,7 +492,6 @@ struct mwifiex_private {
struct semaphore async_sem;
u8 report_scan_result;
struct cfg80211_scan_request *scan_request;
- struct mwifiex_user_scan_cfg *user_scan_cfg;
u8 cfg_bssid[6];
struct wps wps;
u8 scan_block;
@@ -510,6 +509,7 @@ struct mwifiex_private {
u8 ap_11ac_enabled;
u32 mgmt_frame_mask;
struct mwifiex_roc_cfg roc_cfg;
+ bool scan_aborting;
};
enum mwifiex_ba_status {
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c
index 9cf5d8f..7b2566b 100644
--- a/drivers/net/wireless/mwifiex/scan.c
+++ b/drivers/net/wireless/mwifiex/scan.c
@@ -1784,22 +1784,16 @@ check_next_scan:
if (priv->report_scan_result)
priv->report_scan_result = false;
- if (priv->user_scan_cfg) {
- if (priv->scan_request) {
- dev_dbg(priv->adapter->dev,
- "info: notifying scan done\n");
- cfg80211_scan_done(priv->scan_request, 0);
- priv->scan_request = NULL;
- } else {
- dev_dbg(priv->adapter->dev,
- "info: scan already aborted\n");
- }
-
- kfree(priv->user_scan_cfg);
- priv->user_scan_cfg = NULL;
+ if (priv->scan_request) {
+ dev_dbg(adapter->dev, "info: notifying scan done\n");
+ cfg80211_scan_done(priv->scan_request, 0);
+ priv->scan_request = NULL;
+ } else {
+ priv->scan_aborting = false;
+ dev_dbg(adapter->dev, "info: scan already aborted\n");
}
} else {
- if (priv->user_scan_cfg && !priv->scan_request) {
+ if (priv->scan_aborting && !priv->scan_request) {
spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
flags);
adapter->scan_delay_cnt = MWIFIEX_MAX_SCAN_DELAY_CNT;
--
1.8.2.3
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH v2 04/17] mwifiex: abort remaining scan commands when association started
2013-05-18 0:50 [PATCH v2 00/17] mwifiex updates for 3.11 Bing Zhao
` (2 preceding siblings ...)
2013-05-18 0:50 ` [PATCH v2 03/17] mwifiex: remove global user_scan_cfg variable Bing Zhao
@ 2013-05-18 0:50 ` Bing Zhao
2013-05-18 0:50 ` [PATCH v2 05/17] mwifiex: avoid deleting all stations during mwifiex_del_sta_entry() Bing Zhao
` (5 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Bing Zhao @ 2013-05-18 0:50 UTC (permalink / raw)
To: linux-wireless
Cc: John W. Linville, Amitkumar Karwar, Avinash Patil,
Yogesh Ashok Powar, Nishant Sarmukadam, Frank Huang, Bing Zhao
A full-channel scan is split to multiple scan commands in driver
before they are sent to firmware. When each scan result is back
the SSID entries are parsed and informed to cfg80211 directly.
It's observed that sometimes userspace may initiate association
as soon as the target AP is found. During the 4-way handshake
firmware may go off-channel to scan the remaining channels.
This causes the 4-way handshake to fail.
Fix it by checking 'scan_block' flag and aborting the remaining
scan in this case. 'scan_block' flag is set after association
and before 4-way handshake. It gets cleared after 4-way handshake
is completed.
Tested-by: Jason Abele <jabele@chromium.org>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
---
drivers/net/wireless/mwifiex/scan.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c
index 7b2566b..801b6b7 100644
--- a/drivers/net/wireless/mwifiex/scan.c
+++ b/drivers/net/wireless/mwifiex/scan.c
@@ -1793,7 +1793,8 @@ check_next_scan:
dev_dbg(adapter->dev, "info: scan already aborted\n");
}
} else {
- if (priv->scan_aborting && !priv->scan_request) {
+ if ((priv->scan_aborting && !priv->scan_request) ||
+ priv->scan_block) {
spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
flags);
adapter->scan_delay_cnt = MWIFIEX_MAX_SCAN_DELAY_CNT;
--
1.8.2.3
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH v2 05/17] mwifiex: avoid deleting all stations during mwifiex_del_sta_entry()
2013-05-18 0:50 [PATCH v2 00/17] mwifiex updates for 3.11 Bing Zhao
` (3 preceding siblings ...)
2013-05-18 0:50 ` [PATCH v2 04/17] mwifiex: abort remaining scan commands when association started Bing Zhao
@ 2013-05-18 0:50 ` Bing Zhao
2013-05-18 0:50 ` [PATCH v2 06/17] mwifiex: add del_station handler Bing Zhao
` (4 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Bing Zhao @ 2013-05-18 0:50 UTC (permalink / raw)
To: linux-wireless
Cc: John W. Linville, Amitkumar Karwar, Avinash Patil,
Yogesh Ashok Powar, Nishant Sarmukadam, Frank Huang, Bing Zhao
From: Avinash Patil <patila@marvell.com>
During deleting a station entry from associated sta_list, we are
supposed to delete entry only for this particular mac address.
This patch is a bug fix wherein we were deleting all entries from
list; fix this by removing list_for_each_entry_safe() call.
Signed-off-by: Avinash Patil <patila@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
---
drivers/net/wireless/mwifiex/uap_event.c | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/drivers/net/wireless/mwifiex/uap_event.c b/drivers/net/wireless/mwifiex/uap_event.c
index 21c640d..77fb533 100644
--- a/drivers/net/wireless/mwifiex/uap_event.c
+++ b/drivers/net/wireless/mwifiex/uap_event.c
@@ -107,18 +107,15 @@ mwifiex_set_sta_ht_cap(struct mwifiex_private *priv, const u8 *ies,
*/
static void mwifiex_del_sta_entry(struct mwifiex_private *priv, u8 *mac)
{
- struct mwifiex_sta_node *node, *tmp;
+ struct mwifiex_sta_node *node;
unsigned long flags;
spin_lock_irqsave(&priv->sta_list_spinlock, flags);
node = mwifiex_get_sta_entry(priv, mac);
if (node) {
- list_for_each_entry_safe(node, tmp, &priv->sta_list,
- list) {
- list_del(&node->list);
- kfree(node);
- }
+ list_del(&node->list);
+ kfree(node);
}
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
--
1.8.2.3
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH v2 06/17] mwifiex: add del_station handler
2013-05-18 0:50 [PATCH v2 00/17] mwifiex updates for 3.11 Bing Zhao
` (4 preceding siblings ...)
2013-05-18 0:50 ` [PATCH v2 05/17] mwifiex: avoid deleting all stations during mwifiex_del_sta_entry() Bing Zhao
@ 2013-05-18 0:50 ` Bing Zhao
2013-05-18 0:50 ` [PATCH v2 07/17] mwifiex: replace spin_lock_irqsave with spin_lock and fix warn_on Bing Zhao
` (3 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Bing Zhao @ 2013-05-18 0:50 UTC (permalink / raw)
To: linux-wireless
Cc: John W. Linville, Amitkumar Karwar, Avinash Patil,
Yogesh Ashok Powar, Nishant Sarmukadam, Frank Huang, Bing Zhao
From: Avinash Patil <patila@marvell.com>
This patch adds cfg80211 del_station handler for mwifiex.
If bss is not started or there are no stations in associated
stations list, no action is taken. If argument received is
null/broadcast mac, all stations in associated station list are
deauthenticated.
Patch also deletes related RxReorder stream and TxBA stream tables
for related station.
Signed-off-by: Avinash Patil <patila@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
---
drivers/net/wireless/mwifiex/cfg80211.c | 46 ++++++++++++++++++++++++++++++
drivers/net/wireless/mwifiex/cmdevt.c | 1 +
drivers/net/wireless/mwifiex/fw.h | 7 +++++
drivers/net/wireless/mwifiex/main.h | 2 ++
drivers/net/wireless/mwifiex/sta_cmdresp.c | 2 ++
drivers/net/wireless/mwifiex/uap_cmd.c | 21 ++++++++++++++
drivers/net/wireless/mwifiex/uap_event.c | 16 +++++++++++
7 files changed, 95 insertions(+)
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index e493f89..00a8281 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -1231,6 +1231,51 @@ static int mwifiex_cfg80211_change_beacon(struct wiphy *wiphy,
return 0;
}
+/* cfg80211 operation handler for del_station.
+ * Function deauthenticates station which value is provided in mac parameter.
+ * If mac is NULL/broadcast, all stations in associated station list are
+ * deauthenticated. If bss is not started or there are no stations in
+ * associated stations list, no action is taken.
+ */
+static int
+mwifiex_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev,
+ u8 *mac)
+{
+ struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+ struct mwifiex_sta_node *sta_node;
+ unsigned long flags;
+
+ if (list_empty(&priv->sta_list) || !priv->bss_started)
+ return 0;
+
+ if (!mac || is_broadcast_ether_addr(mac)) {
+ wiphy_dbg(wiphy, "%s: NULL/broadcast mac address\n", __func__);
+ list_for_each_entry(sta_node, &priv->sta_list, list) {
+ if (mwifiex_send_cmd_sync(priv,
+ HostCmd_CMD_UAP_STA_DEAUTH,
+ HostCmd_ACT_GEN_SET, 0,
+ sta_node->mac_addr))
+ return -1;
+ mwifiex_uap_del_sta_data(priv, sta_node);
+ }
+ } else {
+ wiphy_dbg(wiphy, "%s: mac address %pM\n", __func__, mac);
+ spin_lock_irqsave(&priv->sta_list_spinlock, flags);
+ sta_node = mwifiex_get_sta_entry(priv, mac);
+ spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
+ if (sta_node) {
+ if (mwifiex_send_cmd_sync(priv,
+ HostCmd_CMD_UAP_STA_DEAUTH,
+ HostCmd_ACT_GEN_SET, 0,
+ sta_node->mac_addr))
+ return -1;
+ mwifiex_uap_del_sta_data(priv, sta_node);
+ }
+ }
+
+ return 0;
+}
+
static int
mwifiex_cfg80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant)
{
@@ -2422,6 +2467,7 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = {
.change_beacon = mwifiex_cfg80211_change_beacon,
.set_cqm_rssi_config = mwifiex_cfg80211_set_cqm_rssi_config,
.set_antenna = mwifiex_cfg80211_set_antenna,
+ .del_station = mwifiex_cfg80211_del_station,
#ifdef CONFIG_PM
.suspend = mwifiex_cfg80211_suspend,
.resume = mwifiex_cfg80211_resume,
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c
index 26755d9..2d76147 100644
--- a/drivers/net/wireless/mwifiex/cmdevt.c
+++ b/drivers/net/wireless/mwifiex/cmdevt.c
@@ -570,6 +570,7 @@ int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no,
case HostCmd_CMD_UAP_SYS_CONFIG:
case HostCmd_CMD_UAP_BSS_START:
case HostCmd_CMD_UAP_BSS_STOP:
+ case HostCmd_CMD_UAP_STA_DEAUTH:
ret = mwifiex_uap_prepare_cmd(priv, cmd_no, cmd_action,
cmd_oid, data_buf,
cmd_ptr);
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h
index 1f7578d..d3c1e01 100644
--- a/drivers/net/wireless/mwifiex/fw.h
+++ b/drivers/net/wireless/mwifiex/fw.h
@@ -279,6 +279,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
#define HostCmd_CMD_UAP_SYS_CONFIG 0x00b0
#define HostCmd_CMD_UAP_BSS_START 0x00b1
#define HostCmd_CMD_UAP_BSS_STOP 0x00b2
+#define HostCmd_CMD_UAP_STA_DEAUTH 0x00b5
#define HostCmd_CMD_11N_CFG 0x00cd
#define HostCmd_CMD_11N_ADDBA_REQ 0x00ce
#define HostCmd_CMD_11N_ADDBA_RSP 0x00cf
@@ -1197,6 +1198,11 @@ struct host_cmd_ds_amsdu_aggr_ctrl {
__le16 curr_buf_size;
} __packed;
+struct host_cmd_ds_sta_deauth {
+ u8 mac[ETH_ALEN];
+ __le16 reason;
+} __packed;
+
struct mwifiex_ie_types_wmm_param_set {
struct mwifiex_ie_types_header header;
u8 wmm_ie[1];
@@ -1630,6 +1636,7 @@ struct host_cmd_ds_command {
struct host_cmd_ds_802_11_eeprom_access eeprom;
struct host_cmd_ds_802_11_subsc_evt subsc_evt;
struct host_cmd_ds_sys_config uap_sys_config;
+ struct host_cmd_ds_sta_deauth sta_deauth;
struct host_cmd_11ac_vht_cfg vht_cfg;
} params;
} __packed;
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index 81251d9..9cf6852 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -1115,6 +1115,8 @@ int mwifiex_set_mgmt_ies(struct mwifiex_private *priv,
struct cfg80211_beacon_data *data);
int mwifiex_del_mgmt_ies(struct mwifiex_private *priv);
u8 *mwifiex_11d_code_2_region(u8 code);
+void mwifiex_uap_del_sta_data(struct mwifiex_private *priv,
+ struct mwifiex_sta_node *node);
extern const struct ethtool_ops mwifiex_ethtool_ops;
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c
index 9f990e1..c710a1b 100644
--- a/drivers/net/wireless/mwifiex/sta_cmdresp.c
+++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c
@@ -978,6 +978,8 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
case HostCmd_CMD_UAP_BSS_STOP:
priv->bss_started = 0;
break;
+ case HostCmd_CMD_UAP_STA_DEAUTH:
+ break;
case HostCmd_CMD_MEF_CFG:
break;
default:
diff --git a/drivers/net/wireless/mwifiex/uap_cmd.c b/drivers/net/wireless/mwifiex/uap_cmd.c
index b04b1db..2de882d 100644
--- a/drivers/net/wireless/mwifiex/uap_cmd.c
+++ b/drivers/net/wireless/mwifiex/uap_cmd.c
@@ -689,6 +689,23 @@ mwifiex_cmd_uap_sys_config(struct host_cmd_ds_command *cmd, u16 cmd_action,
return 0;
}
+/* This function prepares AP specific deauth command with mac supplied in
+ * function parameter.
+ */
+static int mwifiex_cmd_uap_sta_deauth(struct mwifiex_private *priv,
+ struct host_cmd_ds_command *cmd, u8 *mac)
+{
+ struct host_cmd_ds_sta_deauth *sta_deauth = &cmd->params.sta_deauth;
+
+ cmd->command = cpu_to_le16(HostCmd_CMD_UAP_STA_DEAUTH);
+ memcpy(sta_deauth->mac, mac, ETH_ALEN);
+ sta_deauth->reason = cpu_to_le16(WLAN_REASON_DEAUTH_LEAVING);
+
+ cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_sta_deauth) +
+ S_DS_GEN);
+ return 0;
+}
+
/* This function prepares the AP specific commands before sending them
* to the firmware.
* This is a generic function which calls specific command preparation
@@ -710,6 +727,10 @@ int mwifiex_uap_prepare_cmd(struct mwifiex_private *priv, u16 cmd_no,
cmd->command = cpu_to_le16(cmd_no);
cmd->size = cpu_to_le16(S_DS_GEN);
break;
+ case HostCmd_CMD_UAP_STA_DEAUTH:
+ if (mwifiex_cmd_uap_sta_deauth(priv, cmd, data_buf))
+ return -1;
+ break;
default:
dev_err(priv->adapter->dev,
"PREP_CMD: unknown cmd %#x\n", cmd_no);
diff --git a/drivers/net/wireless/mwifiex/uap_event.c b/drivers/net/wireless/mwifiex/uap_event.c
index 77fb533..7180665 100644
--- a/drivers/net/wireless/mwifiex/uap_event.c
+++ b/drivers/net/wireless/mwifiex/uap_event.c
@@ -292,3 +292,19 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
return 0;
}
+
+/* This function deletes station entry from associated station list.
+ * Also if both AP and STA are 11n enabled, RxReorder tables and TxBA stream
+ * tables created for this station are deleted.
+ */
+void mwifiex_uap_del_sta_data(struct mwifiex_private *priv,
+ struct mwifiex_sta_node *node)
+{
+ if (priv->ap_11n_enabled && node->is_11n_enabled) {
+ mwifiex_11n_del_rx_reorder_tbl_by_ta(priv, node->mac_addr);
+ mwifiex_del_tx_ba_stream_tbl_by_ra(priv, node->mac_addr);
+ }
+ mwifiex_del_sta_entry(priv, node->mac_addr);
+
+ return;
+}
--
1.8.2.3
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH v2 07/17] mwifiex: replace spin_lock_irqsave with spin_lock and fix warn_on
2013-05-18 0:50 [PATCH v2 00/17] mwifiex updates for 3.11 Bing Zhao
` (5 preceding siblings ...)
2013-05-18 0:50 ` [PATCH v2 06/17] mwifiex: add del_station handler Bing Zhao
@ 2013-05-18 0:50 ` Bing Zhao
2013-05-18 0:50 ` [PATCH v2 08/17] mwifiex: add calibration data download feature Bing Zhao
` (2 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Bing Zhao @ 2013-05-18 0:50 UTC (permalink / raw)
To: linux-wireless
Cc: John W. Linville, Amitkumar Karwar, Avinash Patil,
Yogesh Ashok Powar, Nishant Sarmukadam, Frank Huang, Bing Zhao
From: Avinash Patil <patila@marvell.com>
We see this WARN_ON during PCIe unload:
WARNING: at kernel/smp.c:382 smp_call_function_many+0x66/0x1e1()
This happens because we are doing PCI iounmap operations while
holding spinlock via spin_lock_irqsave(). Holding spinlock this
way causes disabling IRQs and hence PCI iounmap shows warning on
irqs_disabled() check.
Use non-irq variant of spin_lock i.e. spin_lock() instead.
Signed-off-by: Avinash Patil <patila@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
---
drivers/net/wireless/mwifiex/init.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c
index 1343725f..c7f11c0 100644
--- a/drivers/net/wireless/mwifiex/init.c
+++ b/drivers/net/wireless/mwifiex/init.c
@@ -687,7 +687,6 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter)
int ret = -EINPROGRESS;
struct mwifiex_private *priv;
s32 i;
- unsigned long flags;
struct sk_buff *skb;
/* mwifiex already shutdown */
@@ -722,7 +721,7 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter)
}
}
- spin_lock_irqsave(&adapter->mwifiex_lock, flags);
+ spin_lock(&adapter->mwifiex_lock);
if (adapter->if_ops.data_complete) {
while ((skb = skb_dequeue(&adapter->usb_rx_data_q))) {
@@ -738,7 +737,7 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter)
mwifiex_adapter_cleanup(adapter);
- spin_unlock_irqrestore(&adapter->mwifiex_lock, flags);
+ spin_unlock(&adapter->mwifiex_lock);
/* Notify completion */
ret = mwifiex_shutdown_fw_complete(adapter);
--
1.8.2.3
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH v2 08/17] mwifiex: add calibration data download feature
2013-05-18 0:50 [PATCH v2 00/17] mwifiex updates for 3.11 Bing Zhao
` (6 preceding siblings ...)
2013-05-18 0:50 ` [PATCH v2 07/17] mwifiex: replace spin_lock_irqsave with spin_lock and fix warn_on Bing Zhao
@ 2013-05-18 0:50 ` Bing Zhao
2013-05-18 0:50 ` [PATCH v2 09/17] mwifiex: use u32 variables for SDIO read/write port bitmap Bing Zhao
2013-05-18 0:50 ` [PATCH v2 10/17] mwifiex: store SDIO chip specific information in separate structure Bing Zhao
9 siblings, 0 replies; 11+ messages in thread
From: Bing Zhao @ 2013-05-18 0:50 UTC (permalink / raw)
To: linux-wireless
Cc: John W. Linville, Amitkumar Karwar, Avinash Patil,
Yogesh Ashok Powar, Nishant Sarmukadam, Frank Huang, Bing Zhao
From: Amitkumar Karwar <akarwar@marvell.com>
User can provide a text file containing calibration data in hex
format while loading mwifiex module. It will be downloaded to
firmware.
eg. insmod mwifiex.ko cal_data_cfg=cal_data.conf
Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
---
drivers/net/wireless/mwifiex/fw.h | 10 +++++
drivers/net/wireless/mwifiex/main.c | 13 +++++++
drivers/net/wireless/mwifiex/main.h | 1 +
drivers/net/wireless/mwifiex/sta_cmd.c | 62 ++++++++++++++++++++++++++++++
drivers/net/wireless/mwifiex/sta_cmdresp.c | 15 ++++++++
5 files changed, 101 insertions(+)
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h
index d3c1e01..d6ada73 100644
--- a/drivers/net/wireless/mwifiex/fw.h
+++ b/drivers/net/wireless/mwifiex/fw.h
@@ -271,6 +271,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
#define HostCmd_CMD_802_11_SUBSCRIBE_EVENT 0x0075
#define HostCmd_CMD_802_11_TX_RATE_QUERY 0x007f
#define HostCmd_CMD_802_11_IBSS_COALESCING_STATUS 0x0083
+#define HostCmd_CMD_CFG_DATA 0x008f
#define HostCmd_CMD_VERSION_EXT 0x0097
#define HostCmd_CMD_MEF_CFG 0x009a
#define HostCmd_CMD_RSSI_INFO 0x00a4
@@ -465,6 +466,8 @@ enum P2P_MODES {
#define MWIFIEX_CRITERIA_UNICAST BIT(1)
#define MWIFIEX_CRITERIA_MULTICAST BIT(3)
+#define CFG_DATA_TYPE_CAL 2
+
struct mwifiex_ie_types_header {
__le16 type;
__le16 len;
@@ -1579,6 +1582,12 @@ struct mwifiex_ie_list {
struct mwifiex_ie ie_list[MAX_MGMT_IE_INDEX];
} __packed;
+struct host_cmd_ds_802_11_cfg_data {
+ __le16 action;
+ __le16 type;
+ __le16 data_len;
+} __packed;
+
struct host_cmd_ds_command {
__le16 command;
__le16 size;
@@ -1638,6 +1647,7 @@ struct host_cmd_ds_command {
struct host_cmd_ds_sys_config uap_sys_config;
struct host_cmd_ds_sta_deauth sta_deauth;
struct host_cmd_11ac_vht_cfg vht_cfg;
+ struct host_cmd_ds_802_11_cfg_data cfg_data;
} params;
} __packed;
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c
index 4e7270c..5bc7ef8 100644
--- a/drivers/net/wireless/mwifiex/main.c
+++ b/drivers/net/wireless/mwifiex/main.c
@@ -25,6 +25,8 @@
#define VERSION "1.0"
const char driver_version[] = "mwifiex " VERSION " (%s) ";
+static char *cal_data_cfg;
+module_param(cal_data_cfg, charp, 0);
/*
* This function registers the device and performs all the necessary
@@ -336,6 +338,13 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
dev_notice(adapter->dev, "WLAN FW is active\n");
+ if (cal_data_cfg) {
+ if ((request_firmware(&adapter->cal_data, cal_data_cfg,
+ adapter->dev)) < 0)
+ dev_err(adapter->dev,
+ "Cal data request_firmware() failed\n");
+ }
+
adapter->init_wait_q_woken = false;
ret = mwifiex_init_fw(adapter);
if (ret == -1) {
@@ -390,6 +399,10 @@ err_init_fw:
pr_debug("info: %s: unregister device\n", __func__);
adapter->if_ops.unregister_dev(adapter);
done:
+ if (adapter->cal_data) {
+ release_firmware(adapter->cal_data);
+ adapter->cal_data = NULL;
+ }
release_firmware(adapter->firmware);
complete(&adapter->fw_load);
return;
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index 9cf6852..0832c24 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -730,6 +730,7 @@ struct mwifiex_adapter {
u16 max_mgmt_ie_index;
u8 scan_delay_cnt;
u8 empty_tx_q_cnt;
+ const struct firmware *cal_data;
/* 11AC */
u32 is_hw_11ac_capable;
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c
index b193e25..8ece485 100644
--- a/drivers/net/wireless/mwifiex/sta_cmd.c
+++ b/drivers/net/wireless/mwifiex/sta_cmd.c
@@ -1134,6 +1134,55 @@ mwifiex_cmd_mef_cfg(struct mwifiex_private *priv,
return 0;
}
+/* This function parse cal data from ASCII to hex */
+static u32 mwifiex_parse_cal_cfg(u8 *src, size_t len, u8 *dst)
+{
+ u8 *s = src, *d = dst;
+
+ while (s - src < len) {
+ if (*s && (isspace(*s) || *s == '\t')) {
+ s++;
+ continue;
+ }
+ if (isxdigit(*s)) {
+ *d++ = simple_strtol(s, NULL, 16);
+ s += 2;
+ } else {
+ s++;
+ }
+ }
+
+ return d - dst;
+}
+
+/* This function prepares command of set_cfg_data. */
+static int mwifiex_cmd_cfg_data(struct mwifiex_private *priv,
+ struct host_cmd_ds_command *cmd,
+ u16 cmd_action)
+{
+ struct host_cmd_ds_802_11_cfg_data *cfg_data = &cmd->params.cfg_data;
+ struct mwifiex_adapter *adapter = priv->adapter;
+ u32 len, cal_data_offset;
+ u8 *tmp_cmd = (u8 *)cmd;
+
+ cal_data_offset = S_DS_GEN + sizeof(*cfg_data);
+ if ((adapter->cal_data->data) && (adapter->cal_data->size > 0))
+ len = mwifiex_parse_cal_cfg((u8 *)adapter->cal_data->data,
+ adapter->cal_data->size,
+ (u8 *)(tmp_cmd + cal_data_offset));
+ else
+ return -1;
+
+ cfg_data->action = cpu_to_le16(cmd_action);
+ cfg_data->type = cpu_to_le16(CFG_DATA_TYPE_CAL);
+ cfg_data->data_len = cpu_to_le16(len);
+
+ cmd->command = cpu_to_le16(HostCmd_CMD_CFG_DATA);
+ cmd->size = cpu_to_le16(S_DS_GEN + sizeof(*cfg_data) + len);
+
+ return 0;
+}
+
/*
* This function prepares the commands before sending them to the firmware.
*
@@ -1152,6 +1201,9 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
case HostCmd_CMD_GET_HW_SPEC:
ret = mwifiex_cmd_get_hw_spec(priv, cmd_ptr);
break;
+ case HostCmd_CMD_CFG_DATA:
+ ret = mwifiex_cmd_cfg_data(priv, cmd_ptr, cmd_action);
+ break;
case HostCmd_CMD_MAC_CONTROL:
ret = mwifiex_cmd_mac_control(priv, cmd_ptr, cmd_action,
data_buf);
@@ -1384,6 +1436,7 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
*/
int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta)
{
+ struct mwifiex_adapter *adapter = priv->adapter;
int ret;
u16 enable = true;
struct mwifiex_ds_11n_amsdu_aggr_ctrl amsdu_aggr_ctrl;
@@ -1404,6 +1457,15 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta)
HostCmd_ACT_GEN_SET, 0, NULL);
if (ret)
return -1;
+
+ /* Download calibration data to firmware */
+ if (adapter->cal_data) {
+ ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_CFG_DATA,
+ HostCmd_ACT_GEN_SET, 0, NULL);
+ if (ret)
+ return -1;
+ }
+
/* Read MAC address from HW */
ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_GET_HW_SPEC,
HostCmd_ACT_GEN_GET, 0, NULL);
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c
index c710a1b..d85df15 100644
--- a/drivers/net/wireless/mwifiex/sta_cmdresp.c
+++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c
@@ -818,6 +818,18 @@ static int mwifiex_ret_subsc_evt(struct mwifiex_private *priv,
return 0;
}
+/* This function handles the command response of set_cfg_data */
+static int mwifiex_ret_cfg_data(struct mwifiex_private *priv,
+ struct host_cmd_ds_command *resp)
+{
+ if (resp->result != HostCmd_RESULT_OK) {
+ dev_err(priv->adapter->dev, "Cal data cmd resp failed\n");
+ return -1;
+ }
+
+ return 0;
+}
+
/*
* This function handles the command responses.
*
@@ -841,6 +853,9 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
case HostCmd_CMD_GET_HW_SPEC:
ret = mwifiex_ret_get_hw_spec(priv, resp);
break;
+ case HostCmd_CMD_CFG_DATA:
+ ret = mwifiex_ret_cfg_data(priv, resp);
+ break;
case HostCmd_CMD_MAC_CONTROL:
break;
case HostCmd_CMD_802_11_MAC_ADDRESS:
--
1.8.2.3
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH v2 09/17] mwifiex: use u32 variables for SDIO read/write port bitmap
2013-05-18 0:50 [PATCH v2 00/17] mwifiex updates for 3.11 Bing Zhao
` (7 preceding siblings ...)
2013-05-18 0:50 ` [PATCH v2 08/17] mwifiex: add calibration data download feature Bing Zhao
@ 2013-05-18 0:50 ` Bing Zhao
2013-05-18 0:50 ` [PATCH v2 10/17] mwifiex: store SDIO chip specific information in separate structure Bing Zhao
9 siblings, 0 replies; 11+ messages in thread
From: Bing Zhao @ 2013-05-18 0:50 UTC (permalink / raw)
To: linux-wireless
Cc: John W. Linville, Amitkumar Karwar, Avinash Patil,
Yogesh Ashok Powar, Nishant Sarmukadam, Frank Huang, Bing Zhao
From: Amitkumar Karwar <akarwar@marvell.com>
Currently supported SDIO chipsets (SD87XX) have 16 ports.
This change is a prerequisite for new chipset.
Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
Signed-off-by: Yogesh Ashok Powar <yogeshp@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
---
drivers/net/wireless/mwifiex/sdio.c | 40 ++++++++++++++++++-------------------
drivers/net/wireless/mwifiex/sdio.h | 10 +++++-----
2 files changed, 25 insertions(+), 25 deletions(-)
diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c
index 363ba31..7368ee1 100644
--- a/drivers/net/wireless/mwifiex/sdio.c
+++ b/drivers/net/wireless/mwifiex/sdio.c
@@ -486,21 +486,21 @@ static int mwifiex_write_data_to_card(struct mwifiex_adapter *adapter,
static int mwifiex_get_rd_port(struct mwifiex_adapter *adapter, u8 *port)
{
struct sdio_mmc_card *card = adapter->card;
- u16 rd_bitmap = card->mp_rd_bitmap;
+ u32 rd_bitmap = card->mp_rd_bitmap;
- dev_dbg(adapter->dev, "data: mp_rd_bitmap=0x%04x\n", rd_bitmap);
+ dev_dbg(adapter->dev, "data: mp_rd_bitmap=0x%08x\n", rd_bitmap);
if (!(rd_bitmap & (CTRL_PORT_MASK | DATA_PORT_MASK)))
return -1;
if (card->mp_rd_bitmap & CTRL_PORT_MASK) {
- card->mp_rd_bitmap &= (u16) (~CTRL_PORT_MASK);
+ card->mp_rd_bitmap &= (u32) (~CTRL_PORT_MASK);
*port = CTRL_PORT;
- dev_dbg(adapter->dev, "data: port=%d mp_rd_bitmap=0x%04x\n",
+ dev_dbg(adapter->dev, "data: port=%d mp_rd_bitmap=0x%08x\n",
*port, card->mp_rd_bitmap);
} else {
if (card->mp_rd_bitmap & (1 << card->curr_rd_port)) {
- card->mp_rd_bitmap &= (u16)
+ card->mp_rd_bitmap &= (u32)
(~(1 << card->curr_rd_port));
*port = card->curr_rd_port;
@@ -511,7 +511,7 @@ static int mwifiex_get_rd_port(struct mwifiex_adapter *adapter, u8 *port)
}
dev_dbg(adapter->dev,
- "data: port=%d mp_rd_bitmap=0x%04x -> 0x%04x\n",
+ "data: port=%d mp_rd_bitmap=0x%08x -> 0x%08x\n",
*port, rd_bitmap, card->mp_rd_bitmap);
}
return 0;
@@ -527,15 +527,15 @@ static int mwifiex_get_rd_port(struct mwifiex_adapter *adapter, u8 *port)
static int mwifiex_get_wr_port_data(struct mwifiex_adapter *adapter, u8 *port)
{
struct sdio_mmc_card *card = adapter->card;
- u16 wr_bitmap = card->mp_wr_bitmap;
+ u32 wr_bitmap = card->mp_wr_bitmap;
- dev_dbg(adapter->dev, "data: mp_wr_bitmap=0x%04x\n", wr_bitmap);
+ dev_dbg(adapter->dev, "data: mp_wr_bitmap=0x%08x\n", wr_bitmap);
if (!(wr_bitmap & card->mp_data_port_mask))
return -1;
if (card->mp_wr_bitmap & (1 << card->curr_wr_port)) {
- card->mp_wr_bitmap &= (u16) (~(1 << card->curr_wr_port));
+ card->mp_wr_bitmap &= (u32) (~(1 << card->curr_wr_port));
*port = card->curr_wr_port;
if (++card->curr_wr_port == card->mp_end_port)
card->curr_wr_port = 1;
@@ -545,14 +545,14 @@ static int mwifiex_get_wr_port_data(struct mwifiex_adapter *adapter, u8 *port)
}
if (*port == CTRL_PORT) {
- dev_err(adapter->dev, "invalid data port=%d cur port=%d"
- " mp_wr_bitmap=0x%04x -> 0x%04x\n",
+ dev_err(adapter->dev,
+ "invalid data port=%d cur port=%d mp_wr_bitmap=0x%08x -> 0x%08x\n",
*port, card->curr_wr_port, wr_bitmap,
card->mp_wr_bitmap);
return -1;
}
- dev_dbg(adapter->dev, "data: port=%d mp_wr_bitmap=0x%04x -> 0x%04x\n",
+ dev_dbg(adapter->dev, "data: port=%d mp_wr_bitmap=0x%08x -> 0x%08x\n",
*port, wr_bitmap, card->mp_wr_bitmap);
return 0;
@@ -1024,7 +1024,7 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter,
goto rx_curr_single;
}
- if (card->mp_rd_bitmap & (~((u16) CTRL_PORT_MASK))) {
+ if (card->mp_rd_bitmap & (~((u32) CTRL_PORT_MASK))) {
/* Some more data RX pending */
dev_dbg(adapter->dev, "info: %s: not last packet\n", __func__);
@@ -1185,9 +1185,9 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
return ret;
if (sdio_ireg & DN_LD_HOST_INT_STATUS) {
- card->mp_wr_bitmap = ((u16) card->mp_regs[WR_BITMAP_U]) << 8;
- card->mp_wr_bitmap |= (u16) card->mp_regs[WR_BITMAP_L];
- dev_dbg(adapter->dev, "int: DNLD: wr_bitmap=0x%04x\n",
+ card->mp_wr_bitmap = ((u32) card->mp_regs[WR_BITMAP_U]) << 8;
+ card->mp_wr_bitmap |= (u32) card->mp_regs[WR_BITMAP_L];
+ dev_dbg(adapter->dev, "int: DNLD: wr_bitmap=0x%08x\n",
card->mp_wr_bitmap);
if (adapter->data_sent &&
(card->mp_wr_bitmap & card->mp_data_port_mask)) {
@@ -1204,7 +1204,7 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
/* Check if firmware has attach buffer at command port and
update just that in wr_bit_map. */
card->mp_wr_bitmap |=
- (u16) card->mp_regs[WR_BITMAP_L] & CTRL_PORT_MASK;
+ (u32) card->mp_regs[WR_BITMAP_L] & CTRL_PORT_MASK;
if (card->mp_wr_bitmap & CTRL_PORT_MASK)
adapter->cmd_sent = false;
}
@@ -1212,9 +1212,9 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
dev_dbg(adapter->dev, "info: cmd_sent=%d data_sent=%d\n",
adapter->cmd_sent, adapter->data_sent);
if (sdio_ireg & UP_LD_HOST_INT_STATUS) {
- card->mp_rd_bitmap = ((u16) card->mp_regs[RD_BITMAP_U]) << 8;
- card->mp_rd_bitmap |= (u16) card->mp_regs[RD_BITMAP_L];
- dev_dbg(adapter->dev, "int: UPLD: rd_bitmap=0x%04x\n",
+ card->mp_rd_bitmap = ((u32) card->mp_regs[RD_BITMAP_U]) << 8;
+ card->mp_rd_bitmap |= (u32) card->mp_regs[RD_BITMAP_L];
+ dev_dbg(adapter->dev, "int: UPLD: rd_bitmap=0x%08x\n",
card->mp_rd_bitmap);
while (true) {
diff --git a/drivers/net/wireless/mwifiex/sdio.h b/drivers/net/wireless/mwifiex/sdio.h
index 8cc5468..6588069 100644
--- a/drivers/net/wireless/mwifiex/sdio.h
+++ b/drivers/net/wireless/mwifiex/sdio.h
@@ -261,7 +261,7 @@ struct mwifiex_sdio_mpa_tx {
u8 *buf;
u32 buf_len;
u32 pkt_cnt;
- u16 ports;
+ u32 ports;
u16 start_port;
u8 enabled;
u32 buf_size;
@@ -272,7 +272,7 @@ struct mwifiex_sdio_mpa_rx {
u8 *buf;
u32 buf_len;
u32 pkt_cnt;
- u16 ports;
+ u32 ports;
u16 start_port;
struct sk_buff *skb_arr[SDIO_MP_AGGR_DEF_PKT_LIMIT];
@@ -290,11 +290,11 @@ struct sdio_mmc_card {
struct sdio_func *func;
struct mwifiex_adapter *adapter;
- u16 mp_rd_bitmap;
- u16 mp_wr_bitmap;
+ u32 mp_rd_bitmap;
+ u32 mp_wr_bitmap;
u16 mp_end_port;
- u16 mp_data_port_mask;
+ u32 mp_data_port_mask;
u8 curr_rd_port;
u8 curr_wr_port;
--
1.8.2.3
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH v2 10/17] mwifiex: store SDIO chip specific information in separate structure
2013-05-18 0:50 [PATCH v2 00/17] mwifiex updates for 3.11 Bing Zhao
` (8 preceding siblings ...)
2013-05-18 0:50 ` [PATCH v2 09/17] mwifiex: use u32 variables for SDIO read/write port bitmap Bing Zhao
@ 2013-05-18 0:50 ` Bing Zhao
9 siblings, 0 replies; 11+ messages in thread
From: Bing Zhao @ 2013-05-18 0:50 UTC (permalink / raw)
To: linux-wireless
Cc: John W. Linville, Amitkumar Karwar, Avinash Patil,
Yogesh Ashok Powar, Nishant Sarmukadam, Frank Huang, Bing Zhao
From: Amitkumar Karwar <akarwar@marvell.com>
Register addresses, firmware name and some macros are specific to
a chip. They are stored in a new structure.
Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
---
drivers/net/wireless/mwifiex/sdio.c | 116 +++++++++++++++++++++---------------
drivers/net/wireless/mwifiex/sdio.h | 114 +++++++++++++++++++++++++----------
2 files changed, 149 insertions(+), 81 deletions(-)
diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c
index 7368ee1..022e9fd 100644
--- a/drivers/net/wireless/mwifiex/sdio.c
+++ b/drivers/net/wireless/mwifiex/sdio.c
@@ -77,6 +77,15 @@ mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id)
func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE;
+ if (id->driver_data) {
+ struct mwifiex_sdio_device *data = (void *)id->driver_data;
+
+ card->firmware = data->firmware;
+ card->reg = data->reg;
+ card->max_ports = data->max_ports;
+ card->mp_agg_pkt_limit = data->mp_agg_pkt_limit;
+ }
+
sdio_claim_host(func);
ret = sdio_enable_func(func);
sdio_release_host(func);
@@ -254,9 +263,12 @@ static int mwifiex_sdio_resume(struct device *dev)
/* WLAN IDs */
static const struct sdio_device_id mwifiex_ids[] = {
- {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8786)},
- {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8787)},
- {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8797)},
+ {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8786),
+ .driver_data = (unsigned long) &mwifiex_sdio_sd8786},
+ {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8787),
+ .driver_data = (unsigned long) &mwifiex_sdio_sd8787},
+ {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8797),
+ .driver_data = (unsigned long) &mwifiex_sdio_sd8797},
{},
};
@@ -410,6 +422,7 @@ static int mwifiex_pm_wakeup_card_complete(struct mwifiex_adapter *adapter)
static int mwifiex_init_sdio_ioport(struct mwifiex_adapter *adapter)
{
u32 reg;
+ struct sdio_mmc_card *card = adapter->card;
adapter->ioport = 0;
@@ -434,13 +447,13 @@ static int mwifiex_init_sdio_ioport(struct mwifiex_adapter *adapter)
/* Set Host interrupt reset to read to clear */
if (!mwifiex_read_reg(adapter, HOST_INT_RSR_REG, ®))
mwifiex_write_reg(adapter, HOST_INT_RSR_REG,
- reg | SDIO_INT_MASK);
+ reg | card->reg->sdio_int_mask);
else
return -1;
/* Dnld/Upld ready set to auto reset */
- if (!mwifiex_read_reg(adapter, CARD_MISC_CFG_REG, ®))
- mwifiex_write_reg(adapter, CARD_MISC_CFG_REG,
+ if (!mwifiex_read_reg(adapter, card->reg->card_misc_cfg_reg, ®))
+ mwifiex_write_reg(adapter, card->reg->card_misc_cfg_reg,
reg | AUTO_RE_ENABLE_INT);
else
return -1;
@@ -486,11 +499,12 @@ static int mwifiex_write_data_to_card(struct mwifiex_adapter *adapter,
static int mwifiex_get_rd_port(struct mwifiex_adapter *adapter, u8 *port)
{
struct sdio_mmc_card *card = adapter->card;
+ const struct mwifiex_sdio_card_reg *reg = card->reg;
u32 rd_bitmap = card->mp_rd_bitmap;
dev_dbg(adapter->dev, "data: mp_rd_bitmap=0x%08x\n", rd_bitmap);
- if (!(rd_bitmap & (CTRL_PORT_MASK | DATA_PORT_MASK)))
+ if (!(rd_bitmap & (CTRL_PORT_MASK | reg->data_port_mask)))
return -1;
if (card->mp_rd_bitmap & CTRL_PORT_MASK) {
@@ -504,8 +518,8 @@ static int mwifiex_get_rd_port(struct mwifiex_adapter *adapter, u8 *port)
(~(1 << card->curr_rd_port));
*port = card->curr_rd_port;
- if (++card->curr_rd_port == MAX_PORT)
- card->curr_rd_port = 1;
+ if (++card->curr_rd_port == card->max_ports)
+ card->curr_rd_port = reg->start_rd_port;
} else {
return -1;
}
@@ -538,7 +552,7 @@ static int mwifiex_get_wr_port_data(struct mwifiex_adapter *adapter, u8 *port)
card->mp_wr_bitmap &= (u32) (~(1 << card->curr_wr_port));
*port = card->curr_wr_port;
if (++card->curr_wr_port == card->mp_end_port)
- card->curr_wr_port = 1;
+ card->curr_wr_port = card->reg->start_wr_port;
} else {
adapter->data_sent = true;
return -EBUSY;
@@ -564,11 +578,12 @@ static int mwifiex_get_wr_port_data(struct mwifiex_adapter *adapter, u8 *port)
static int
mwifiex_sdio_poll_card_status(struct mwifiex_adapter *adapter, u8 bits)
{
+ struct sdio_mmc_card *card = adapter->card;
u32 tries;
u32 cs;
for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
- if (mwifiex_read_reg(adapter, CARD_STATUS_REG, &cs))
+ if (mwifiex_read_reg(adapter, card->reg->poll_reg, &cs))
break;
else if ((cs & bits) == bits)
return 0;
@@ -587,12 +602,14 @@ mwifiex_sdio_poll_card_status(struct mwifiex_adapter *adapter, u8 bits)
static int
mwifiex_sdio_read_fw_status(struct mwifiex_adapter *adapter, u16 *dat)
{
+ struct sdio_mmc_card *card = adapter->card;
+ const struct mwifiex_sdio_card_reg *reg = card->reg;
u32 fws0, fws1;
- if (mwifiex_read_reg(adapter, CARD_FW_STATUS0_REG, &fws0))
+ if (mwifiex_read_reg(adapter, reg->status_reg_0, &fws0))
return -1;
- if (mwifiex_read_reg(adapter, CARD_FW_STATUS1_REG, &fws1))
+ if (mwifiex_read_reg(adapter, reg->status_reg_1, &fws1))
return -1;
*dat = (u16) ((fws1 << 8) | fws0);
@@ -633,8 +650,11 @@ static int mwifiex_sdio_disable_host_int(struct mwifiex_adapter *adapter)
*/
static int mwifiex_sdio_enable_host_int(struct mwifiex_adapter *adapter)
{
+ struct sdio_mmc_card *card = adapter->card;
+
/* Simply write the mask to the register */
- if (mwifiex_write_reg(adapter, HOST_INT_MASK_REG, HOST_INT_ENABLE)) {
+ if (mwifiex_write_reg(adapter, HOST_INT_MASK_REG,
+ card->reg->host_int_enable)) {
dev_err(adapter->dev, "enable host interrupt failed\n");
return -1;
}
@@ -686,6 +706,8 @@ static int mwifiex_sdio_card_to_host(struct mwifiex_adapter *adapter,
static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
struct mwifiex_fw_image *fw)
{
+ struct sdio_mmc_card *card = adapter->card;
+ const struct mwifiex_sdio_card_reg *reg = card->reg;
int ret;
u8 *firmware = fw->fw_buf;
u32 firmware_len = fw->fw_len;
@@ -727,7 +749,7 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
break;
for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
- ret = mwifiex_read_reg(adapter, HOST_F1_RD_BASE_0,
+ ret = mwifiex_read_reg(adapter, reg->base_0_reg,
&base0);
if (ret) {
dev_err(adapter->dev,
@@ -736,7 +758,7 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
base0, base0);
goto done;
}
- ret = mwifiex_read_reg(adapter, HOST_F1_RD_BASE_1,
+ ret = mwifiex_read_reg(adapter, reg->base_1_reg,
&base1);
if (ret) {
dev_err(adapter->dev,
@@ -828,6 +850,7 @@ done:
static int mwifiex_check_fw_status(struct mwifiex_adapter *adapter,
u32 poll_num)
{
+ struct sdio_mmc_card *card = adapter->card;
int ret = 0;
u16 firmware_stat;
u32 tries;
@@ -849,7 +872,7 @@ static int mwifiex_check_fw_status(struct mwifiex_adapter *adapter,
if (ret) {
if (mwifiex_read_reg
- (adapter, CARD_FW_STATUS0_REG, &winner_status))
+ (adapter, card->reg->status_reg_0, &winner_status))
winner_status = 0;
if (winner_status)
@@ -869,9 +892,9 @@ static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter)
u32 sdio_ireg;
unsigned long flags;
- if (mwifiex_read_data_sync(adapter, card->mp_regs, MAX_MP_REGS,
- REG_PORT | MWIFIEX_SDIO_BYTE_MODE_MASK,
- 0)) {
+ if (mwifiex_read_data_sync(adapter, card->mp_regs,
+ card->reg->max_mp_regs,
+ REG_PORT | MWIFIEX_SDIO_BYTE_MODE_MASK, 0)) {
dev_err(adapter->dev, "read mp_regs failed\n");
return;
}
@@ -1167,6 +1190,7 @@ error:
static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
{
struct sdio_mmc_card *card = adapter->card;
+ const struct mwifiex_sdio_card_reg *reg = card->reg;
int ret = 0;
u8 sdio_ireg;
struct sk_buff *skb;
@@ -1185,8 +1209,10 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
return ret;
if (sdio_ireg & DN_LD_HOST_INT_STATUS) {
- card->mp_wr_bitmap = ((u32) card->mp_regs[WR_BITMAP_U]) << 8;
- card->mp_wr_bitmap |= (u32) card->mp_regs[WR_BITMAP_L];
+ card->mp_wr_bitmap =
+ ((u32) card->mp_regs[reg->wr_bitmap_u]) << 8;
+ card->mp_wr_bitmap |=
+ (u32) card->mp_regs[reg->wr_bitmap_l];
dev_dbg(adapter->dev, "int: DNLD: wr_bitmap=0x%08x\n",
card->mp_wr_bitmap);
if (adapter->data_sent &&
@@ -1204,7 +1230,7 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
/* Check if firmware has attach buffer at command port and
update just that in wr_bit_map. */
card->mp_wr_bitmap |=
- (u32) card->mp_regs[WR_BITMAP_L] & CTRL_PORT_MASK;
+ (u32) card->mp_regs[reg->wr_bitmap_l] & CTRL_PORT_MASK;
if (card->mp_wr_bitmap & CTRL_PORT_MASK)
adapter->cmd_sent = false;
}
@@ -1212,8 +1238,9 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
dev_dbg(adapter->dev, "info: cmd_sent=%d data_sent=%d\n",
adapter->cmd_sent, adapter->data_sent);
if (sdio_ireg & UP_LD_HOST_INT_STATUS) {
- card->mp_rd_bitmap = ((u32) card->mp_regs[RD_BITMAP_U]) << 8;
- card->mp_rd_bitmap |= (u32) card->mp_regs[RD_BITMAP_L];
+ card->mp_rd_bitmap =
+ ((u32) card->mp_regs[reg->rd_bitmap_u]) << 8;
+ card->mp_rd_bitmap |= (u32) card->mp_regs[reg->rd_bitmap_l];
dev_dbg(adapter->dev, "int: UPLD: rd_bitmap=0x%08x\n",
card->mp_rd_bitmap);
@@ -1224,8 +1251,8 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
"info: no more rd_port available\n");
break;
}
- len_reg_l = RD_LEN_P0_L + (port << 1);
- len_reg_u = RD_LEN_P0_U + (port << 1);
+ len_reg_l = reg->rd_len_p0_l + (port << 1);
+ len_reg_u = reg->rd_len_p0_u + (port << 1);
rx_len = ((u16) card->mp_regs[len_reg_u]) << 8;
rx_len |= (u16) card->mp_regs[len_reg_l];
dev_dbg(adapter->dev, "info: RX: port=%d rx_len=%u\n",
@@ -1586,18 +1613,7 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
adapter->dev = &func->dev;
- switch (func->device) {
- case SDIO_DEVICE_ID_MARVELL_8786:
- strcpy(adapter->fw_name, SD8786_DEFAULT_FW_NAME);
- break;
- case SDIO_DEVICE_ID_MARVELL_8797:
- strcpy(adapter->fw_name, SD8797_DEFAULT_FW_NAME);
- break;
- case SDIO_DEVICE_ID_MARVELL_8787:
- default:
- strcpy(adapter->fw_name, SD8787_DEFAULT_FW_NAME);
- break;
- }
+ strcpy(adapter->fw_name, card->firmware);
return 0;
@@ -1626,6 +1642,7 @@ disable_func:
static int mwifiex_init_sdio(struct mwifiex_adapter *adapter)
{
struct sdio_mmc_card *card = adapter->card;
+ const struct mwifiex_sdio_card_reg *reg = card->reg;
int ret;
u32 sdio_ireg;
@@ -1645,27 +1662,27 @@ static int mwifiex_init_sdio(struct mwifiex_adapter *adapter)
/* Initialize SDIO variables in card */
card->mp_rd_bitmap = 0;
card->mp_wr_bitmap = 0;
- card->curr_rd_port = 1;
- card->curr_wr_port = 1;
+ card->curr_rd_port = reg->start_rd_port;
+ card->curr_wr_port = reg->start_wr_port;
- card->mp_data_port_mask = DATA_PORT_MASK;
+ card->mp_data_port_mask = reg->data_port_mask;
card->mpa_tx.buf_len = 0;
card->mpa_tx.pkt_cnt = 0;
card->mpa_tx.start_port = 0;
card->mpa_tx.enabled = 1;
- card->mpa_tx.pkt_aggr_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT;
+ card->mpa_tx.pkt_aggr_limit = card->mp_agg_pkt_limit;
card->mpa_rx.buf_len = 0;
card->mpa_rx.pkt_cnt = 0;
card->mpa_rx.start_port = 0;
card->mpa_rx.enabled = 1;
- card->mpa_rx.pkt_aggr_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT;
+ card->mpa_rx.pkt_aggr_limit = card->mp_agg_pkt_limit;
/* Allocate buffers for SDIO MP-A */
- card->mp_regs = kzalloc(MAX_MP_REGS, GFP_KERNEL);
+ card->mp_regs = kzalloc(reg->max_mp_regs, GFP_KERNEL);
if (!card->mp_regs)
return -ENOMEM;
@@ -1716,16 +1733,17 @@ static void
mwifiex_update_mp_end_port(struct mwifiex_adapter *adapter, u16 port)
{
struct sdio_mmc_card *card = adapter->card;
+ const struct mwifiex_sdio_card_reg *reg = card->reg;
int i;
card->mp_end_port = port;
- card->mp_data_port_mask = DATA_PORT_MASK;
+ card->mp_data_port_mask = reg->data_port_mask;
- for (i = 1; i <= MAX_PORT - card->mp_end_port; i++)
- card->mp_data_port_mask &= ~(1 << (MAX_PORT - i));
+ for (i = 1; i <= card->max_ports - card->mp_end_port; i++)
+ card->mp_data_port_mask &= ~(1 << (card->max_ports - i));
- card->curr_wr_port = 1;
+ card->curr_wr_port = reg->start_wr_port;
dev_dbg(adapter->dev, "cmd: mp_end_port %d, data port mask 0x%x\n",
port, card->mp_data_port_mask);
diff --git a/drivers/net/wireless/mwifiex/sdio.h b/drivers/net/wireless/mwifiex/sdio.h
index 6588069..0d931f7 100644
--- a/drivers/net/wireless/mwifiex/sdio.h
+++ b/drivers/net/wireless/mwifiex/sdio.h
@@ -37,12 +37,6 @@
#define BYTE_MODE 0
#define REG_PORT 0
-#define RD_BITMAP_L 0x04
-#define RD_BITMAP_U 0x05
-#define WR_BITMAP_L 0x06
-#define WR_BITMAP_U 0x07
-#define RD_LEN_P0_L 0x08
-#define RD_LEN_P0_U 0x09
#define MWIFIEX_SDIO_IO_PORT_MASK 0xfffff
@@ -50,12 +44,8 @@
#define CTRL_PORT 0
#define CTRL_PORT_MASK 0x0001
-#define DATA_PORT_MASK 0xfffe
-#define MAX_MP_REGS 64
-#define MAX_PORT 16
-
-#define SDIO_MP_AGGR_DEF_PKT_LIMIT 8
+#define SDIO_MP_AGGR_DEF_PKT_LIMIT 8
#define SDIO_MP_TX_AGGR_DEF_BUF_SIZE (8192) /* 8K */
@@ -90,8 +80,6 @@
#define UP_LD_HOST_INT_MASK (0x1U)
/* Host Control Registers : Download host interrupt mask */
#define DN_LD_HOST_INT_MASK (0x2U)
-/* Enable Host interrupt mask */
-#define HOST_INT_ENABLE (UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK)
/* Disable Host interrupt mask */
#define HOST_INT_DISABLE 0xff
@@ -106,7 +94,6 @@
#define HOST_INT_RSR_REG 0x01
/* Host Control Registers : Upload host interrupt RSR */
#define UP_LD_HOST_INT_RSR (0x1U)
-#define SDIO_INT_MASK 0x3F
/* Host Control Registers : Host interrupt status */
#define HOST_INT_STATUS_REG 0x28
@@ -117,8 +104,6 @@
/* Host Control Registers : Download restart */
#define DN_LD_RESTART (0x1U << 0)
-/* Card Control Registers : Card status register */
-#define CARD_STATUS_REG 0x30
/* Card Control Registers : Card I/O ready */
#define CARD_IO_READY (0x1U << 3)
/* Card Control Registers : CIS card ready */
@@ -153,20 +138,9 @@
/* Card Control Registers : Power down RSR */
#define POWER_DOWN_RSR (0x1U << 3)
-/* Card Control Registers : Miscellaneous Configuration Register */
-#define CARD_MISC_CFG_REG 0x6C
-
-/* Host F1 read base 0 */
-#define HOST_F1_RD_BASE_0 0x0040
-/* Host F1 read base 1 */
-#define HOST_F1_RD_BASE_1 0x0041
/* Host F1 card ready */
#define HOST_F1_CARD_RDY 0x0020
-/* Firmware status 0 register */
-#define CARD_FW_STATUS0_REG 0x60
-/* Firmware status 1 register */
-#define CARD_FW_STATUS1_REG 0x61
/* Rx length register */
#define CARD_RX_LEN_REG 0x62
/* Rx unit register */
@@ -192,7 +166,8 @@
if (a->mpa_tx.start_port <= port) \
a->mpa_tx.ports |= (1<<(a->mpa_tx.pkt_cnt)); \
else \
- a->mpa_tx.ports |= (1<<(a->mpa_tx.pkt_cnt+1+(MAX_PORT - \
+ a->mpa_tx.ports |= (1<<(a->mpa_tx.pkt_cnt+1+ \
+ (a->max_ports - \
a->mp_end_port))); \
a->mpa_tx.pkt_cnt++; \
} while (0)
@@ -203,9 +178,9 @@
/* SDIO Tx aggregation port limit ? */
#define MP_TX_AGGR_PORT_LIMIT_REACHED(a) ((a->curr_wr_port < \
- a->mpa_tx.start_port) && (((MAX_PORT - \
+ a->mpa_tx.start_port) && (((a->max_ports -\
a->mpa_tx.start_port) + a->curr_wr_port) >= \
- SDIO_MP_AGGR_DEF_PKT_LIMIT))
+ a->mp_agg_pkt_limit))
/* Reset SDIO Tx aggregation buffer parameters */
#define MP_TX_AGGR_BUF_RESET(a) do { \
@@ -221,9 +196,9 @@
/* SDIO Tx aggregation port limit ? */
#define MP_RX_AGGR_PORT_LIMIT_REACHED(a) ((a->curr_rd_port < \
- a->mpa_rx.start_port) && (((MAX_PORT - \
+ a->mpa_rx.start_port) && (((a->max_ports -\
a->mpa_rx.start_port) + a->curr_rd_port) >= \
- SDIO_MP_AGGR_DEF_PKT_LIMIT))
+ a->mp_agg_pkt_limit))
/* SDIO Rx aggregation in progress ? */
#define MP_RX_AGGR_IN_PROGRESS(a) (a->mpa_rx.pkt_cnt > 0)
@@ -286,10 +261,36 @@ struct mwifiex_sdio_mpa_rx {
int mwifiex_bus_register(void);
void mwifiex_bus_unregister(void);
+struct mwifiex_sdio_card_reg {
+ u8 start_rd_port;
+ u8 start_wr_port;
+ u8 base_0_reg;
+ u8 base_1_reg;
+ u8 poll_reg;
+ u8 host_int_enable;
+ u8 status_reg_0;
+ u8 status_reg_1;
+ u8 sdio_int_mask;
+ u32 data_port_mask;
+ u8 max_mp_regs;
+ u8 rd_bitmap_l;
+ u8 rd_bitmap_u;
+ u8 wr_bitmap_l;
+ u8 wr_bitmap_u;
+ u8 rd_len_p0_l;
+ u8 rd_len_p0_u;
+ u8 card_misc_cfg_reg;
+};
+
struct sdio_mmc_card {
struct sdio_func *func;
struct mwifiex_adapter *adapter;
+ const char *firmware;
+ const struct mwifiex_sdio_card_reg *reg;
+ u8 max_ports;
+ u8 mp_agg_pkt_limit;
+
u32 mp_rd_bitmap;
u32 mp_wr_bitmap;
@@ -305,6 +306,55 @@ struct sdio_mmc_card {
struct mwifiex_sdio_mpa_rx mpa_rx;
};
+struct mwifiex_sdio_device {
+ const char *firmware;
+ const struct mwifiex_sdio_card_reg *reg;
+ u8 max_ports;
+ u8 mp_agg_pkt_limit;
+};
+
+static const struct mwifiex_sdio_card_reg mwifiex_reg_sd87xx = {
+ .start_rd_port = 1,
+ .start_wr_port = 1,
+ .base_0_reg = 0x0040,
+ .base_1_reg = 0x0041,
+ .poll_reg = 0x30,
+ .host_int_enable = UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK,
+ .status_reg_0 = 0x60,
+ .status_reg_1 = 0x61,
+ .sdio_int_mask = 0x3f,
+ .data_port_mask = 0x0000fffe,
+ .max_mp_regs = 64,
+ .rd_bitmap_l = 0x04,
+ .rd_bitmap_u = 0x05,
+ .wr_bitmap_l = 0x06,
+ .wr_bitmap_u = 0x07,
+ .rd_len_p0_l = 0x08,
+ .rd_len_p0_u = 0x09,
+ .card_misc_cfg_reg = 0x6c,
+};
+
+static const struct mwifiex_sdio_device mwifiex_sdio_sd8786 = {
+ .firmware = SD8786_DEFAULT_FW_NAME,
+ .reg = &mwifiex_reg_sd87xx,
+ .max_ports = 16,
+ .mp_agg_pkt_limit = 8,
+};
+
+static const struct mwifiex_sdio_device mwifiex_sdio_sd8787 = {
+ .firmware = SD8787_DEFAULT_FW_NAME,
+ .reg = &mwifiex_reg_sd87xx,
+ .max_ports = 16,
+ .mp_agg_pkt_limit = 8,
+};
+
+static const struct mwifiex_sdio_device mwifiex_sdio_sd8797 = {
+ .firmware = SD8797_DEFAULT_FW_NAME,
+ .reg = &mwifiex_reg_sd87xx,
+ .max_ports = 16,
+ .mp_agg_pkt_limit = 8,
+};
+
/*
* .cmdrsp_complete handler
*/
--
1.8.2.3
^ permalink raw reply related [flat|nested] 11+ messages in thread