* [PATCH 4/5] rsi: Added support for antenna selection
From: Prameela Rani Garnepudi @ 2016-11-14 12:17 UTC (permalink / raw)
To: linux-wireless
Cc: kvalo, johannes.berg, hofrat, xypron.glpk, prameela.garnepudi,
Prameela Rani Garnepudi
RSI 9113 device supports single antenna for tx and rx. Support for using
external is added. This can be configured from user space using iw.
Signed-off-by: Prameela Rani Garnepudi <prameela.j04cs@gmail.com>
---
drivers/net/wireless/rsi/rsi_91x_mac80211.c | 78 +++++++++++++++++++++++++++++
drivers/net/wireless/rsi/rsi_91x_mgmt.c | 33 ++++++++++++
drivers/net/wireless/rsi/rsi_main.h | 1 +
drivers/net/wireless/rsi/rsi_mgmt.h | 4 ++
4 files changed, 116 insertions(+)
diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
index ba21608..07314ea 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
@@ -1071,6 +1071,82 @@ static int rsi_mac80211_sta_remove(struct ieee80211_hw *hw,
return 0;
}
+/**
+ * rsi_mac80211_set_antenna() - This function is used to configure
+ * tx and rx antennas.
+ * @hw: Pointer to the ieee80211_hw structure.
+ * @tx_ant: Bitmap for tx antenna
+ * @rx_ant: Bitmap for rx antenna
+ *
+ * Return: 0 on success, -1 on failure.
+ */
+static int rsi_mac80211_set_antenna(struct ieee80211_hw *hw,
+ u32 tx_ant, u32 rx_ant)
+{
+ struct rsi_hw *adapter = hw->priv;
+ struct rsi_common *common = adapter->priv;
+ u32 antenna = 0;
+
+ if (tx_ant > 1 || rx_ant > 1) {
+ rsi_dbg(ERR_ZONE,
+ "Invalid antenna selection (tx: %d, rx:%d)\n",
+ tx_ant, rx_ant);
+ rsi_dbg(ERR_ZONE,
+ "Use 0 for int_ant, 1 for ext_ant\n");
+ return -EINVAL;
+ }
+
+ rsi_dbg(INFO_ZONE, "%s: Antenna map Tx %x Rx %d\n",
+ __func__, tx_ant, rx_ant);
+
+ mutex_lock(&common->mutex);
+
+ antenna = tx_ant ? ANTENNA_SEL_UFL : ANTENNA_SEL_INT;
+ if (common->ant_in_use != antenna)
+ if (rsi_set_antenna(common, antenna))
+ goto fail_set_antenna;
+
+ rsi_dbg(INFO_ZONE, "(%s) Antenna path configured successfully\n",
+ tx_ant ? "UFL" : "INT");
+
+ common->ant_in_use = antenna;
+
+ mutex_unlock(&common->mutex);
+
+ return 0;
+
+fail_set_antenna:
+ rsi_dbg(ERR_ZONE, "%s: Failed.\n", __func__);
+ mutex_unlock(&common->mutex);
+ return -EINVAL;
+}
+
+/**
+ * rsi_mac80211_get_antenna() - This function is used to configure
+ * tx and rx antennas.
+ *
+ * @hw: Pointer to the ieee80211_hw structure.
+ * @tx_ant: Bitmap for tx antenna
+ * @rx_ant: Bitmap for rx antenna
+ *
+ * Return: 0 on success, -1 on failure.
+ */
+static int rsi_mac80211_get_antenna(struct ieee80211_hw *hw,
+ u32 *tx_ant, u32 *rx_ant)
+{
+ struct rsi_hw *adapter = hw->priv;
+ struct rsi_common *common = adapter->priv;
+
+ mutex_lock(&common->mutex);
+
+ *tx_ant = (common->ant_in_use == ANTENNA_SEL_UFL) ? 1 : 0;
+ *rx_ant = 0;
+
+ mutex_unlock(&common->mutex);
+
+ return 0;
+}
+
static struct ieee80211_ops mac80211_ops = {
.tx = rsi_mac80211_tx,
.start = rsi_mac80211_start,
@@ -1087,6 +1163,8 @@ static struct ieee80211_ops mac80211_ops = {
.ampdu_action = rsi_mac80211_ampdu_action,
.sta_add = rsi_mac80211_sta_add,
.sta_remove = rsi_mac80211_sta_remove,
+ .set_antenna = rsi_mac80211_set_antenna,
+ .get_antenna = rsi_mac80211_get_antenna,
};
/**
diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
index 2e8e5dc..16dc3ac 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
@@ -1326,6 +1326,39 @@ int rsi_send_rx_filter_frame(struct rsi_common *common, u16 rx_filter_word)
}
/**
+ * rsi_set_antenna() - This fuction handles antenna selection functionality.
+ *
+ * @common: Pointer to the driver private structure.
+ * @antenna: bitmap for tx antenna selection
+ *
+ * Return: 0 on Success, < 0 on failure
+ */
+int rsi_set_antenna(struct rsi_common *common,
+ u8 antenna)
+{
+ struct rsi_mac_frame *mgmt_frame;
+ struct sk_buff *skb;
+
+ skb = dev_alloc_skb(FRAME_DESC_SZ);
+ if (!skb) {
+ rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ memset(skb->data, 0, FRAME_DESC_SZ);
+ mgmt_frame = (struct rsi_mac_frame *)skb->data;
+
+ mgmt_frame->desc_word[1] = cpu_to_le16(ANT_SEL_FRAME);
+ mgmt_frame->desc_word[3] = cpu_to_le16(antenna & 0x00ff);
+ mgmt_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12);
+
+ skb_put(skb, FRAME_DESC_SZ);
+
+ return rsi_send_internal_mgmt_frame(common, skb);
+}
+
+/**
* rsi_handle_ta_confirm_type() - This function handles the confirm frames.
* @common: Pointer to the driver private structure.
* @msg: Pointer to received packet.
diff --git a/drivers/net/wireless/rsi/rsi_main.h b/drivers/net/wireless/rsi/rsi_main.h
index 3938f13..2405b30 100644
--- a/drivers/net/wireless/rsi/rsi_main.h
+++ b/drivers/net/wireless/rsi/rsi_main.h
@@ -206,6 +206,7 @@ struct rsi_common {
bool hw_data_qs_blocked;
int tx_power;
+ u8 ant_in_use;
};
struct rsi_hw {
diff --git a/drivers/net/wireless/rsi/rsi_mgmt.h b/drivers/net/wireless/rsi/rsi_mgmt.h
index 6547ae7..1111c07 100644
--- a/drivers/net/wireless/rsi/rsi_mgmt.h
+++ b/drivers/net/wireless/rsi/rsi_mgmt.h
@@ -141,6 +141,9 @@
#define RSI_SUPP_FILTERS (FIF_ALLMULTI | FIF_PROBE_REQ |\
FIF_BCN_PRBRESP_PROMISC)
+#define ANTENNA_SEL_INT 0x02 /* RF_OUT_2 / Integerated */
+#define ANTENNA_SEL_UFL 0x03 /* RF_OUT_1 / U.FL */
+
/* Rx filter word definitions */
#define PROMISCOUS_MODE BIT(0)
#define ALLOW_DATA_ASSOC_PEER BIT(1)
@@ -337,4 +340,5 @@ int rsi_send_data_pkt(struct rsi_common *common, struct sk_buff *skb);
int rsi_band_check(struct rsi_common *common);
int rsi_send_rx_filter_frame(struct rsi_common *common, u16 rx_filter_word);
int rsi_send_radio_params_update(struct rsi_common *common);
+int rsi_set_antenna(struct rsi_common *common, u8 antenna);
#endif
--
2.4.11
^ permalink raw reply related
* [PATCH 2/5] rsi: Added rx filter frame
From: Prameela Rani Garnepudi @ 2016-11-14 12:16 UTC (permalink / raw)
To: linux-wireless
Cc: kvalo, johannes.berg, hofrat, xypron.glpk, prameela.garnepudi,
Prameela Rani Garnepudi
Filtering the rx frames in firmware after connection in station mode
avoids the overhead of processing un-necessary frames. Hence rx filter
frame is added which can be configured to device at suitable times.
Signed-off-by: Prameela Rani Garnepudi <prameela.j04cs@gmail.com>
---
drivers/net/wireless/rsi/rsi_91x_mac80211.c | 22 ++++++++++++++++++++
drivers/net/wireless/rsi/rsi_91x_mgmt.c | 32 +++++++++++++++++++++++++++++
drivers/net/wireless/rsi/rsi_mgmt.h | 11 ++++++++++
3 files changed, 65 insertions(+)
diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
index dbb2389..fa9498d 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
@@ -259,11 +259,14 @@ static int rsi_mac80211_start(struct ieee80211_hw *hw)
{
struct rsi_hw *adapter = hw->priv;
struct rsi_common *common = adapter->priv;
+ u16 rx_filter_word = 0;
mutex_lock(&common->mutex);
common->iface_down = false;
mutex_unlock(&common->mutex);
+ rsi_send_rx_filter_frame(common, rx_filter_word);
+
return 0;
}
@@ -456,11 +459,28 @@ static void rsi_mac80211_bss_info_changed(struct ieee80211_hw *hw,
{
struct rsi_hw *adapter = hw->priv;
struct rsi_common *common = adapter->priv;
+ struct ieee80211_bss_conf *bss = &adapter->vifs[0]->bss_conf;
+ u16 rx_filter_word = 0;
mutex_lock(&common->mutex);
if (changed & BSS_CHANGED_ASSOC) {
rsi_dbg(INFO_ZONE, "%s: Changed Association status: %d\n",
__func__, bss_conf->assoc);
+ bss->assoc = bss_conf->assoc;
+ if (bss_conf->assoc) {
+ /* Send the RX filter frame */
+ rx_filter_word = (ALLOW_DATA_ASSOC_PEER |
+ ALLOW_CTRL_ASSOC_PEER |
+ ALLOW_MGMT_ASSOC_PEER);
+ rsi_send_rx_filter_frame(common, rx_filter_word);
+ }
+ rsi_dbg(INFO_ZONE,
+ "assoc_status=%d, qos=%d, aid=%d\n",
+ bss->assoc, bss->qos, bss->aid);
+ rsi_dbg(INFO_ZONE,
+ "bssid=%02x:%02x:%02x:%02x:%02x:%02x",
+ bss->bssid[0], bss->bssid[1], bss->bssid[2],
+ bss->bssid[3], bss->bssid[4], bss->bssid[5]);
rsi_inform_bss_status(common,
bss_conf->assoc,
bss_conf->bssid,
@@ -1009,6 +1029,8 @@ static int rsi_mac80211_sta_remove(struct ieee80211_hw *hw,
common->secinfo.gtk_cipher = 0;
mutex_unlock(&common->mutex);
+ if (!common->iface_down)
+ rsi_send_rx_filter_frame(common, 0);
return 0;
}
diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
index 8db377b..ae4a814 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
@@ -1254,6 +1254,38 @@ int rsi_send_block_unblock_frame(struct rsi_common *common, bool block_event)
}
+/**
+ * This function sends a frame to filter the RX packets
+ *
+ * @param common Pointer to the driver private structure.
+ * @param rx_filter_word - Flags of filter packets
+ * @return 0 on success, -1 on failure.
+ */
+int rsi_send_rx_filter_frame(struct rsi_common *common, u16 rx_filter_word)
+{
+ struct rsi_mac_frame *mgmt_frame;
+ struct sk_buff *skb;
+
+ rsi_dbg(MGMT_TX_ZONE, "%s: Sending RX filter frame\n", __func__);
+
+ skb = dev_alloc_skb(FRAME_DESC_SZ);
+ if (!skb) {
+ rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ memset(skb->data, 0, FRAME_DESC_SZ);
+ mgmt_frame = (struct rsi_mac_frame *)skb->data;
+
+ mgmt_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12);
+ mgmt_frame->desc_word[1] = cpu_to_le16(SET_RX_FILTER);
+ mgmt_frame->desc_word[4] = cpu_to_le16(rx_filter_word);
+
+ skb_put(skb, FRAME_DESC_SZ);
+
+ return rsi_send_internal_mgmt_frame(common, skb);
+}
/**
* rsi_handle_ta_confirm_type() - This function handles the confirm frames.
diff --git a/drivers/net/wireless/rsi/rsi_mgmt.h b/drivers/net/wireless/rsi/rsi_mgmt.h
index 3741173..40e8f8e 100644
--- a/drivers/net/wireless/rsi/rsi_mgmt.h
+++ b/drivers/net/wireless/rsi/rsi_mgmt.h
@@ -140,6 +140,16 @@
#define RSI_SUPP_FILTERS (FIF_ALLMULTI | FIF_PROBE_REQ |\
FIF_BCN_PRBRESP_PROMISC)
+
+/* Rx filter word definitions */
+#define PROMISCOUS_MODE BIT(0)
+#define ALLOW_DATA_ASSOC_PEER BIT(1)
+#define ALLOW_MGMT_ASSOC_PEER BIT(2)
+#define ALLOW_CTRL_ASSOC_PEER BIT(3)
+#define DISALLOW_BEACONS BIT(4)
+#define ALLOW_CONN_PEER_MGMT_WHILE_BUF_FULL BIT(5)
+#define DISALLOW_BROADCAST_DATA BIT(6)
+
enum opmode {
STA_OPMODE = 1,
AP_OPMODE = 2
@@ -306,4 +316,5 @@ void rsi_core_xmit(struct rsi_common *common, struct sk_buff *skb);
int rsi_send_mgmt_pkt(struct rsi_common *common, struct sk_buff *skb);
int rsi_send_data_pkt(struct rsi_common *common, struct sk_buff *skb);
int rsi_band_check(struct rsi_common *common);
+int rsi_send_rx_filter_frame(struct rsi_common *common, u16 rx_filter_word);
#endif
--
2.4.11
^ permalink raw reply related
* [PATCH 5/5] rsi: Added support for 802.11d
From: Prameela Rani Garnepudi @ 2016-11-14 12:17 UTC (permalink / raw)
To: linux-wireless
Cc: kvalo, johannes.berg, hofrat, xypron.glpk, prameela.garnepudi,
Prameela Rani Garnepudi
Transmit power value in a channel are determined based on the dfs region
in firmware. To support regulatory rules dfs region should be configured
to device during set channel request. Also antenna gain values are taken
from the mac80211 channel parameters.
Signed-off-by: Prameela Rani Garnepudi <prameela.j04cs@gmail.com>
---
drivers/net/wireless/rsi/rsi_91x_mac80211.c | 30 ++++++++++++++++++++++++++++-
drivers/net/wireless/rsi/rsi_91x_mgmt.c | 26 ++++++++++++++++++++-----
drivers/net/wireless/rsi/rsi_main.h | 1 +
drivers/net/wireless/rsi/rsi_mgmt.h | 3 ++-
4 files changed, 53 insertions(+), 7 deletions(-)
diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
index 07314ea..064f38b 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
@@ -376,7 +376,7 @@ static int rsi_channel_change(struct ieee80211_hw *hw)
status = rsi_band_check(common);
if (!status)
- status = rsi_set_channel(adapter->priv, channel);
+ status = rsi_set_channel(adapter->priv, curchan);
if (bss->assoc) {
if (common->hw_data_qs_blocked &&
@@ -1147,6 +1147,32 @@ static int rsi_mac80211_get_antenna(struct ieee80211_hw *hw,
return 0;
}
+static void rsi_reg_notify(struct wiphy *wiphy,
+ struct regulatory_request *request)
+{
+ struct ieee80211_supported_band *sband;
+ struct ieee80211_channel *ch;
+ struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
+ struct rsi_hw * adapter = hw->priv;
+ int i;
+
+ sband = wiphy->bands[NL80211_BAND_5GHZ];
+
+ for (i = 0; i < sband->n_channels; i++) {
+ ch = &sband->channels[i];
+ if (ch->flags & IEEE80211_CHAN_DISABLED)
+ continue;
+
+ if (ch->flags & IEEE80211_CHAN_RADAR)
+ ch->flags |= IEEE80211_CHAN_NO_IR;
+ }
+
+ rsi_dbg(INFO_ZONE,
+ "country = %s dfs_region = %d\n",
+ request->alpha2, request->dfs_region);
+ adapter->dfs_region = request->dfs_region;
+}
+
static struct ieee80211_ops mac80211_ops = {
.tx = rsi_mac80211_tx,
.start = rsi_mac80211_start,
@@ -1229,6 +1255,8 @@ int rsi_mac80211_attach(struct rsi_common *common)
wiphy->bands[NL80211_BAND_5GHZ] =
&adapter->sbands[NL80211_BAND_5GHZ];
+ wiphy->reg_notifier = rsi_reg_notify;
+
status = ieee80211_register_hw(hw);
if (status)
return status;
diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
index 16dc3ac..a4d7bf9 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
@@ -924,7 +924,8 @@ int rsi_band_check(struct rsi_common *common)
*
* Return: 0 on success, corresponding error code on failure.
*/
-int rsi_set_channel(struct rsi_common *common, u16 channel)
+int rsi_set_channel(struct rsi_common *common,
+ struct ieee80211_channel *channel)
{
struct sk_buff *skb = NULL;
struct rsi_mac_frame *mgmt_frame;
@@ -939,24 +940,39 @@ int rsi_set_channel(struct rsi_common *common, u16 channel)
return -ENOMEM;
}
+ if (!channel) {
+ dev_kfree_skb(skb);
+ return 0;
+ }
memset(skb->data, 0, FRAME_DESC_SZ);
mgmt_frame = (struct rsi_mac_frame *)skb->data;
mgmt_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12);
mgmt_frame->desc_word[1] = cpu_to_le16(SCAN_REQUEST);
- mgmt_frame->desc_word[4] = cpu_to_le16(channel);
+ mgmt_frame->desc_word[4] = cpu_to_le16(channel->hw_value);
+
+ mgmt_frame->desc_word[4] |=
+ cpu_to_le16(((char)(channel->max_antenna_gain)) << 8);
+ mgmt_frame->desc_word[5] =
+ cpu_to_le16((char)(channel->max_antenna_gain));
mgmt_frame->desc_word[7] = cpu_to_le16(PUT_BBP_RESET |
BBP_REG_WRITE |
(RSI_RF_TYPE << 4));
- mgmt_frame->desc_word[5] = cpu_to_le16(0x01);
- mgmt_frame->desc_word[6] = cpu_to_le16(0x12);
+ if (!(channel->flags & IEEE80211_CHAN_NO_IR) &&
+ !(channel->flags & IEEE80211_CHAN_RADAR)) {
+ if (common->tx_power < channel->max_power)
+ mgmt_frame->desc_word[6] = cpu_to_le16(common->tx_power);
+ else
+ mgmt_frame->desc_word[6] = cpu_to_le16(channel->max_power);
+ }
+ mgmt_frame->desc_word[7] = cpu_to_le16(common->priv->dfs_region);
if (common->channel_width == BW_40MHZ)
mgmt_frame->desc_word[5] |= cpu_to_le16(0x1 << 8);
- common->channel = channel;
+ common->channel = channel->hw_value;
skb_put(skb, FRAME_DESC_SZ);
diff --git a/drivers/net/wireless/rsi/rsi_main.h b/drivers/net/wireless/rsi/rsi_main.h
index 2405b30..1d5904b 100644
--- a/drivers/net/wireless/rsi/rsi_main.h
+++ b/drivers/net/wireless/rsi/rsi_main.h
@@ -223,6 +223,7 @@ struct rsi_hw {
struct rsi_debugfs *dfsentry;
u8 num_debugfs_entries;
#endif
+ u8 dfs_region;
void *rsi_dev;
int (*host_intf_read_pkt)(struct rsi_hw *adapter, u8 *pkt, u32 len);
int (*host_intf_write_pkt)(struct rsi_hw *adapter, u8 *pkt, u32 len);
diff --git a/drivers/net/wireless/rsi/rsi_mgmt.h b/drivers/net/wireless/rsi/rsi_mgmt.h
index 1111c07..8e4c01d 100644
--- a/drivers/net/wireless/rsi/rsi_mgmt.h
+++ b/drivers/net/wireless/rsi/rsi_mgmt.h
@@ -324,7 +324,8 @@ int rsi_send_aggregation_params_frame(struct rsi_common *common, u16 tid,
u16 ssn, u8 buf_size, u8 event);
int rsi_hal_load_key(struct rsi_common *common, u8 *data, u16 key_len,
u8 key_type, u8 key_id, u32 cipher);
-int rsi_set_channel(struct rsi_common *common, u16 chno);
+int rsi_set_channel(struct rsi_common *common,
+ struct ieee80211_channel *channel);
int rsi_send_block_unblock_frame(struct rsi_common *common, bool event);
void rsi_inform_bss_status(struct rsi_common *common, u8 status,
const u8 *bssid, u8 qos_enable, u16 aid);
--
2.4.11
^ permalink raw reply related
* Re: [PATCH 05/10] rt2800: make ba_size depend on ampdu_factor
From: Stanislaw Gruszka @ 2016-11-14 12:43 UTC (permalink / raw)
To: Mathias Kresin; +Cc: linux-wireless, Helmut Schaa, Felix Fietkau
In-Reply-To: <20161114084536.GB12372@redhat.com>
On Mon, Nov 14, 2016 at 09:45:36AM +0100, Stanislaw Gruszka wrote:
> Could you check below patch and see if it helps? If it does not,
> could you printk sta->ht_cap.ampdu_density and ba_size values
> and provide them here.
Actually please print parameters from below patch. I think ba_size
should be based on per TID buf_size instead of ampdu_factor, in case
STA has buf size different for some TIDs.
Also adding Felix to cc since my orginal patch:
http://marc.info/?l=linux-wireless&m=147809595316289&w=2
was shamelessly stolen from mt76 driver. Perhaps Felix could provide
us some expertise.
Thanks
Stanislaw
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index 2515702..35bc38c 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -7950,6 +7950,8 @@ int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct rt2x00_sta *sta_priv = (struct rt2x00_sta *)sta->drv_priv;
int ret = 0;
+ printk("action %d sta %pM tid %u buf_size %u ampdu_factor %u\n", params->action, sta->addr, params->tid, params->buf_size, sta->ht_cap.ampdu_factor);
+
/*
* Don't allow aggregation for stations the hardware isn't aware
* of because tx status reports for frames to an unknown station
^ permalink raw reply related
* RE: [PATCH v2 3/3] mwifiex: Enable WoWLAN for both sdio and pcie
From: Amitkumar Karwar @ 2016-11-14 12:45 UTC (permalink / raw)
To: Brian Norris
Cc: linux-wireless@vger.kernel.org, Cathy Luo, Nishant Sarmukadam,
rajatja@google.com, dmitry.torokhov@gmail.com
In-Reply-To: <20161111204235.GB111624@google.com>
Hi Brian,
> From: Brian Norris [mailto:briannorris@chromium.org]
> Sent: Saturday, November 12, 2016 2:13 AM
> To: Amitkumar Karwar
> Cc: linux-wireless@vger.kernel.org; Cathy Luo; Nishant Sarmukadam;
> rajatja@google.com; dmitry.torokhov@gmail.com
> Subject: Re: [PATCH v2 3/3] mwifiex: Enable WoWLAN for both sdio and
> pcie
>
> On Fri, Nov 11, 2016 at 04:45:11PM +0530, Amitkumar Karwar wrote:
> > From: Rajat Jain <rajatja@google.com>
> >
> > Commit ce4f6f0c353b ("mwifiex: add platform specific wakeup interrupt
> > support") added WoWLAN feature only for sdio. This patch moves that
> > code to the common module so that all the interface drivers can use
> it
> > for free. It enables pcie and sdio for its use currently.
> >
> > Signed-off-by: Rajat Jain <rajatja@google.com>
> > ---
> > v2: v1 doesn't apply smoothly on latest code due to recently merged
> > patch "mwifiex: report error to PCIe for suspend failure". Minor
> > conflict is resolved in v2
> > ---
>
> In case you haven't noticed my comments elsewhere, I'll repeat them
> here: you're copy-and-pasting buggy code. That can be OK I suppose, but
> please fix these issues, possibly in a follow-up patch.
Thanks for pointing this. I will post separate follow-up patch which address this issue as per your suggestion.
Regards,
Amitkumar
^ permalink raw reply
* Re: [PATCH 05/10] rt2800: make ba_size depend on ampdu_factor
From: Stanislaw Gruszka @ 2016-11-14 12:45 UTC (permalink / raw)
To: linux-wireless; +Cc: Helmut Schaa, Kalle Valo
In-Reply-To: <1478095865-8651-6-git-send-email-sgruszka@redhat.com>
On Wed, Nov 02, 2016 at 03:11:00PM +0100, Stanislaw Gruszka wrote:
> We can calculate BA window size (max number of pending frames not
> yet block acked) of remote station using Maximum A-MPDU length factor
> for that station.
>
> Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
Kalle, please drop this patch from the set, it requires some rework.
Thanks
Stanislaw
> ---
> drivers/net/wireless/ralink/rt2x00/rt2x00queue.c | 15 ++++++++++-----
> 1 files changed, 10 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00queue.c b/drivers/net/wireless/ralink/rt2x00/rt2x00queue.c
> index 68b620b..9da89e3 100644
> --- a/drivers/net/wireless/ralink/rt2x00/rt2x00queue.c
> +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00queue.c
> @@ -305,14 +305,19 @@ static void rt2x00queue_create_tx_descriptor_ht(struct rt2x00_dev *rt2x00dev,
> struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
> struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0];
> struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
> - struct rt2x00_sta *sta_priv = NULL;
> + u8 ba_size = 0;
>
> if (sta) {
> - txdesc->u.ht.mpdu_density =
> - sta->ht_cap.ampdu_density;
> + struct rt2x00_sta *sta_priv = sta_to_rt2x00_sta(sta);
>
> - sta_priv = sta_to_rt2x00_sta(sta);
> + txdesc->u.ht.mpdu_density = sta->ht_cap.ampdu_density;
> txdesc->u.ht.wcid = sta_priv->wcid;
> +
> + if (!(tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)) {
> + ba_size = IEEE80211_MIN_AMPDU_BUF;
> + ba_size <<= sta->ht_cap.ampdu_factor;
> + ba_size = min_t(int, 63, ba_size - 1);
> + }
> }
>
> /*
> @@ -345,7 +350,7 @@ static void rt2x00queue_create_tx_descriptor_ht(struct rt2x00_dev *rt2x00dev,
> return;
> }
>
> - txdesc->u.ht.ba_size = 7; /* FIXME: What value is needed? */
> + txdesc->u.ht.ba_size = ba_size;
>
> /*
> * Only one STBC stream is supported for now.
> --
> 1.7.1
>
^ permalink raw reply
* RE: [PATCH v2 2/3] mwifiex: Introduce mwifiex_probe_of() to parse common properties
From: Amitkumar Karwar @ 2016-11-14 12:48 UTC (permalink / raw)
To: Brian Norris
Cc: linux-wireless@vger.kernel.org, Cathy Luo, Nishant Sarmukadam,
rajatja@google.com, dmitry.torokhov@gmail.com
In-Reply-To: <20161111204957.GC111624@google.com>
Hi Brian,
> From: Brian Norris [mailto:briannorris@chromium.org]
> Sent: Saturday, November 12, 2016 2:20 AM
> To: Amitkumar Karwar
> Cc: linux-wireless@vger.kernel.org; Cathy Luo; Nishant Sarmukadam;
> rajatja@google.com; dmitry.torokhov@gmail.com
> Subject: Re: [PATCH v2 2/3] mwifiex: Introduce mwifiex_probe_of() to
> parse common properties
>
> On Fri, Nov 11, 2016 at 04:45:10PM +0530, Amitkumar Karwar wrote:
> > From: Rajat Jain <rajatja@google.com>
> >
> > Introduce function mwifiex_probe_of() to parse common properties.
> > Since the interface drivers get to decide whether or not the device
> > tree node was a valid one (depending on the compatible property), let
> > the interface drivers pass a flag to indicate whether the device tree
> > node was a valid one.
>
> Wait, what? I don't understand why this is needed. The current of_node
> user (SDIO) always checks dev->of_node (if !NULL), and if it's not
> matching, it rejects the device and doesn't even try to register the
> card at all. That's a common pattern for DT-based drivers, and I don't
> see why we need to do differently for any other driver (e.g., PCIe).
>
> So...isn't 'dev->of_node != NULL' an equivalent test to
> 'of_node_valid'?
> Or put another way, mwifiex_add_card() should never see a 'struct
> device' whose of_node is not compatible. Do you agree?
I agree. 'of_node_valid' seems to be redundant here. I will remove it and post updated version.
Regards,
Amitkumar
^ permalink raw reply
* [PATCH v3 1/3] mwifiex: Allow mwifiex early access to device structure
From: Amitkumar Karwar @ 2016-11-14 12:49 UTC (permalink / raw)
To: linux-wireless
Cc: Cathy Luo, Nishant Sarmukadam, rajatja, briannorris,
dmitry.torokhov, Amitkumar Karwar
From: Rajat Jain <rajatja@google.com>
Today all the interface drivers (usb/pcie/sdio) assign the
adapter->dev in the register_dev() callback, although they
have this piece of info well before hand.
This patch makes the device structure available for mwifiex
right at the beginning, so that it can be used for early
initialization if needed.
This is needed for subsequent patches in this patchset that
intend to unify and consolidate some of the code that would
otherwise have to be duplicated among the interface drivers
(sdio, pcie, usb).
Signed-off-by: Rajat Jain <rajatja@google.com>
Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
---
v2: Same as v1
v3: Fixed checkpatch warnings
WARNING: function definition argument 'void *' should also have an identifier name
#59: FILE: drivers/net/wireless/marvell/mwifiex/main.h:1415:
+int mwifiex_add_card(void *, struct semaphore *, struct mwifiex_if_ops *, u8,
WARNING: function definition argument 'struct semaphore *' should also have an identifier name
#59: FILE: drivers/net/wireless/marvell/mwifiex/main.h:1415:
+int mwifiex_add_card(void *, struct semaphore *, struct mwifiex_if_ops *, u8,
WARNING: function definition argument 'struct mwifiex_if_ops *' should also have an identifier name
#59: FILE: drivers/net/wireless/marvell/mwifiex/main.h:1415:
+int mwifiex_add_card(void *, struct semaphore *, struct mwifiex_if_ops *, u8,
WARNING: function definition argument 'u8' should also have an identifier name
#59: FILE: drivers/net/wireless/marvell/mwifiex/main.h:1415:
+int mwifiex_add_card(void *, struct semaphore *, struct mwifiex_if_ops *, u8,
WARNING: function definition argument 'struct device *' should also have an identifier name
#59: FILE: drivers/net/wireless/marvell/mwifiex/main.h:1415:
+int mwifiex_add_card(void *, struct semaphore *, struct mwifiex_if_ops *, u8,
---
drivers/net/wireless/marvell/mwifiex/main.c | 4 +++-
drivers/net/wireless/marvell/mwifiex/main.h | 4 +++-
drivers/net/wireless/marvell/mwifiex/pcie.c | 4 +---
drivers/net/wireless/marvell/mwifiex/sdio.c | 5 +----
drivers/net/wireless/marvell/mwifiex/usb.c | 3 +--
5 files changed, 9 insertions(+), 11 deletions(-)
diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
index 2478ccd..dcceab2 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.c
+++ b/drivers/net/wireless/marvell/mwifiex/main.c
@@ -1567,7 +1567,8 @@ void mwifiex_do_flr(struct mwifiex_adapter *adapter, bool prepare)
*/
int
mwifiex_add_card(void *card, struct semaphore *sem,
- struct mwifiex_if_ops *if_ops, u8 iface_type)
+ struct mwifiex_if_ops *if_ops, u8 iface_type,
+ struct device *dev)
{
struct mwifiex_adapter *adapter;
@@ -1579,6 +1580,7 @@ void mwifiex_do_flr(struct mwifiex_adapter *adapter, bool prepare)
goto err_init_sw;
}
+ adapter->dev = dev;
adapter->iface_type = iface_type;
adapter->card_sem = sem;
diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h
index d61fe3a..549e1ba 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.h
+++ b/drivers/net/wireless/marvell/mwifiex/main.h
@@ -1412,7 +1412,9 @@ static inline u8 mwifiex_is_tdls_link_setup(u8 status)
int mwifiex_init_shutdown_fw(struct mwifiex_private *priv,
u32 func_init_shutdown);
-int mwifiex_add_card(void *, struct semaphore *, struct mwifiex_if_ops *, u8);
+int mwifiex_add_card(void *card, struct semaphore *sem,
+ struct mwifiex_if_ops *if_ops, u8 iface_type,
+ struct device *dev);
int mwifiex_remove_card(struct mwifiex_adapter *, struct semaphore *);
void mwifiex_get_version(struct mwifiex_adapter *adapter, char *version,
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
index fed6a1d..de6939c 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -231,7 +231,7 @@ static int mwifiex_pcie_probe(struct pci_dev *pdev,
}
ret = mwifiex_add_card(card, &add_remove_card_sem, &pcie_ops,
- MWIFIEX_PCIE);
+ MWIFIEX_PCIE, &pdev->dev);
if (ret) {
pr_err("%s failed\n", __func__);
goto err_free;
@@ -2999,11 +2999,9 @@ static void mwifiex_pcie_get_fw_name(struct mwifiex_adapter *adapter)
static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
{
struct pcie_service_card *card = adapter->card;
- struct pci_dev *pdev = card->dev;
/* save adapter pointer in card */
card->adapter = adapter;
- adapter->dev = &pdev->dev;
if (mwifiex_pcie_request_irq(adapter))
return -1;
diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c
index 807af13..c95f41f 100644
--- a/drivers/net/wireless/marvell/mwifiex/sdio.c
+++ b/drivers/net/wireless/marvell/mwifiex/sdio.c
@@ -206,7 +206,7 @@ static int mwifiex_sdio_probe_of(struct device *dev, struct sdio_mmc_card *card)
}
ret = mwifiex_add_card(card, &add_remove_card_sem, &sdio_ops,
- MWIFIEX_SDIO);
+ MWIFIEX_SDIO, &func->dev);
if (ret) {
dev_err(&func->dev, "add card failed\n");
goto err_disable;
@@ -2106,9 +2106,6 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
return ret;
}
-
- adapter->dev = &func->dev;
-
strcpy(adapter->fw_name, card->firmware);
if (card->fw_dump_enh) {
adapter->mem_type_mapping_tbl = generic_mem_type_map;
diff --git a/drivers/net/wireless/marvell/mwifiex/usb.c b/drivers/net/wireless/marvell/mwifiex/usb.c
index 73eb084..f847fff 100644
--- a/drivers/net/wireless/marvell/mwifiex/usb.c
+++ b/drivers/net/wireless/marvell/mwifiex/usb.c
@@ -476,7 +476,7 @@ static int mwifiex_usb_probe(struct usb_interface *intf,
usb_set_intfdata(intf, card);
ret = mwifiex_add_card(card, &add_remove_card_sem, &usb_ops,
- MWIFIEX_USB);
+ MWIFIEX_USB, &card->udev->dev);
if (ret) {
pr_err("%s: mwifiex_add_card failed: %d\n", __func__, ret);
usb_reset_device(udev);
@@ -932,7 +932,6 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
card->adapter = adapter;
- adapter->dev = &card->udev->dev;
switch (le16_to_cpu(card->udev->descriptor.idProduct)) {
case USB8997_PID_1:
--
1.9.1
^ permalink raw reply related
* [PATCH v3 2/3] mwifiex: Introduce mwifiex_probe_of() to parse common properties
From: Amitkumar Karwar @ 2016-11-14 12:49 UTC (permalink / raw)
To: linux-wireless
Cc: Cathy Luo, Nishant Sarmukadam, rajatja, briannorris,
dmitry.torokhov, Amitkumar Karwar
In-Reply-To: <1479127752-23745-1-git-send-email-akarwar@marvell.com>
From: Rajat Jain <rajatja@google.com>
Introduce function mwifiex_probe_of() to parse common properties.
Interface drivers get to decide whether or not the device tree node
was a valid one (depending on the compatible property),
Lets fill "adapter->dt_node" in mwifiex_add_card().
The function mwifiex_probe_of() is currently only a place holder with
the next patch adding content to it.
Signed-off-by: Rajat Jain <rajatja@google.com>
Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
---
v2: Same as v1
v3: Redundant flag "of_node_valid" is removed (Brian)
---
drivers/net/wireless/marvell/mwifiex/main.c | 12 ++++++++++++
drivers/net/wireless/marvell/mwifiex/sta_cmd.c | 5 +----
2 files changed, 13 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
index dcceab2..835d330 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.c
+++ b/drivers/net/wireless/marvell/mwifiex/main.c
@@ -1552,6 +1552,16 @@ void mwifiex_do_flr(struct mwifiex_adapter *adapter, bool prepare)
}
EXPORT_SYMBOL_GPL(mwifiex_do_flr);
+static void mwifiex_probe_of(struct mwifiex_adapter *adapter)
+{
+ struct device *dev = adapter->dev;
+
+ if (!dev->of_node)
+ return;
+
+ adapter->dt_node = dev->of_node;
+}
+
/*
* This function adds the card.
*
@@ -1581,6 +1591,8 @@ void mwifiex_do_flr(struct mwifiex_adapter *adapter, bool prepare)
}
adapter->dev = dev;
+ mwifiex_probe_of(adapter);
+
adapter->iface_type = iface_type;
adapter->card_sem = sem;
diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
index b697b61..bcd6408 100644
--- a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
+++ b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
@@ -2235,10 +2235,7 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init)
* The cal-data can be read from device tree and/or
* a configuration file and downloaded to firmware.
*/
- if ((priv->adapter->iface_type == MWIFIEX_SDIO ||
- priv->adapter->iface_type == MWIFIEX_PCIE) &&
- adapter->dev->of_node) {
- adapter->dt_node = adapter->dev->of_node;
+ if (adapter->dt_node) {
if (of_property_read_u32(adapter->dt_node,
"marvell,wakeup-pin",
&data) == 0) {
--
1.9.1
^ permalink raw reply related
* [PATCH v3 3/3] mwifiex: Enable WoWLAN for both sdio and pcie
From: Amitkumar Karwar @ 2016-11-14 12:49 UTC (permalink / raw)
To: linux-wireless
Cc: Cathy Luo, Nishant Sarmukadam, rajatja, briannorris,
dmitry.torokhov
In-Reply-To: <1479127752-23745-1-git-send-email-akarwar@marvell.com>
From: Rajat Jain <rajatja@google.com>
Commit ce4f6f0c353b ("mwifiex: add platform specific wakeup interrupt
support") added WoWLAN feature only for sdio. This patch moves that
code to the common module so that all the interface drivers can use
it for free. It enables pcie and sdio for its use currently.
Signed-off-by: Rajat Jain <rajatja@google.com>
---
v2: v1 doesn't apply smoothly on latest code due to recently merged
patch "mwifiex: report error to PCIe for suspend failure". Minor
conflict is resolved in v2
v3: Same as v2
---
drivers/net/wireless/marvell/mwifiex/main.c | 41 ++++++++++++++++
drivers/net/wireless/marvell/mwifiex/main.h | 25 ++++++++++
drivers/net/wireless/marvell/mwifiex/pcie.c | 2 +
drivers/net/wireless/marvell/mwifiex/sdio.c | 72 ++---------------------------
drivers/net/wireless/marvell/mwifiex/sdio.h | 8 ----
5 files changed, 73 insertions(+), 75 deletions(-)
diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
index 835d330..948f5c2 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.c
+++ b/drivers/net/wireless/marvell/mwifiex/main.c
@@ -1552,14 +1552,55 @@ void mwifiex_do_flr(struct mwifiex_adapter *adapter, bool prepare)
}
EXPORT_SYMBOL_GPL(mwifiex_do_flr);
+static irqreturn_t mwifiex_irq_wakeup_handler(int irq, void *priv)
+{
+ struct mwifiex_adapter *adapter = priv;
+
+ if (adapter->irq_wakeup >= 0) {
+ dev_dbg(adapter->dev, "%s: wake by wifi", __func__);
+ adapter->wake_by_wifi = true;
+ disable_irq_nosync(irq);
+ }
+
+ /* Notify PM core we are wakeup source */
+ pm_wakeup_event(adapter->dev, 0);
+
+ return IRQ_HANDLED;
+}
+
static void mwifiex_probe_of(struct mwifiex_adapter *adapter)
{
+ int ret;
struct device *dev = adapter->dev;
if (!dev->of_node)
return;
adapter->dt_node = dev->of_node;
+ adapter->irq_wakeup = irq_of_parse_and_map(adapter->dt_node, 0);
+ if (!adapter->irq_wakeup) {
+ dev_info(dev, "fail to parse irq_wakeup from device tree\n");
+ return;
+ }
+
+ ret = devm_request_irq(dev, adapter->irq_wakeup,
+ mwifiex_irq_wakeup_handler, IRQF_TRIGGER_LOW,
+ "wifi_wake", adapter);
+ if (ret) {
+ dev_err(dev, "Failed to request irq_wakeup %d (%d)\n",
+ adapter->irq_wakeup, ret);
+ goto err_exit;
+ }
+
+ disable_irq(adapter->irq_wakeup);
+ if (device_init_wakeup(dev, true)) {
+ dev_err(dev, "fail to init wakeup for mwifiex\n");
+ goto err_exit;
+ }
+ return;
+
+err_exit:
+ adapter->irq_wakeup = 0;
}
/*
diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h
index 549e1ba..ae5afe5 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.h
+++ b/drivers/net/wireless/marvell/mwifiex/main.h
@@ -1011,6 +1011,10 @@ struct mwifiex_adapter {
bool usb_mc_setup;
struct cfg80211_wowlan_nd_info *nd_info;
struct ieee80211_regdomain *regd;
+
+ /* Wake-on-WLAN (WoWLAN) */
+ int irq_wakeup;
+ bool wake_by_wifi;
};
void mwifiex_process_tx_queue(struct mwifiex_adapter *adapter);
@@ -1410,6 +1414,27 @@ static inline u8 mwifiex_is_tdls_link_setup(u8 status)
return false;
}
+/* Disable platform specific wakeup interrupt */
+static inline void mwifiex_disable_wake(struct mwifiex_adapter *adapter)
+{
+ if (adapter->irq_wakeup >= 0) {
+ disable_irq_wake(adapter->irq_wakeup);
+ if (!adapter->wake_by_wifi)
+ disable_irq(adapter->irq_wakeup);
+ }
+}
+
+/* Enable platform specific wakeup interrupt */
+static inline void mwifiex_enable_wake(struct mwifiex_adapter *adapter)
+{
+ /* Enable platform specific wakeup interrupt */
+ if (adapter->irq_wakeup >= 0) {
+ adapter->wake_by_wifi = false;
+ enable_irq(adapter->irq_wakeup);
+ enable_irq_wake(adapter->irq_wakeup);
+ }
+}
+
int mwifiex_init_shutdown_fw(struct mwifiex_private *priv,
u32 func_init_shutdown);
int mwifiex_add_card(void *card, struct semaphore *sem,
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
index de6939c..7942b28 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -131,6 +131,7 @@ static int mwifiex_pcie_suspend(struct device *dev)
}
adapter = card->adapter;
+ mwifiex_enable_wake(adapter);
/* Enable the Host Sleep */
if (!mwifiex_enable_hs(adapter)) {
@@ -186,6 +187,7 @@ static int mwifiex_pcie_resume(struct device *dev)
mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA),
MWIFIEX_ASYNC_CMD);
+ mwifiex_disable_wake(adapter);
return 0;
}
diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c
index c95f41f..7055282 100644
--- a/drivers/net/wireless/marvell/mwifiex/sdio.c
+++ b/drivers/net/wireless/marvell/mwifiex/sdio.c
@@ -79,67 +79,18 @@
{ }
};
-static irqreturn_t mwifiex_wake_irq_wifi(int irq, void *priv)
-{
- struct mwifiex_plt_wake_cfg *cfg = priv;
-
- if (cfg->irq_wifi >= 0) {
- pr_info("%s: wake by wifi", __func__);
- cfg->wake_by_wifi = true;
- disable_irq_nosync(irq);
- }
-
- /* Notify PM core we are wakeup source */
- pm_wakeup_event(cfg->dev, 0);
-
- return IRQ_HANDLED;
-}
-
/* This function parse device tree node using mmc subnode devicetree API.
* The device node is saved in card->plt_of_node.
* if the device tree node exist and include interrupts attributes, this
* function will also request platform specific wakeup interrupt.
*/
-static int mwifiex_sdio_probe_of(struct device *dev, struct sdio_mmc_card *card)
+static int mwifiex_sdio_probe_of(struct device *dev)
{
- struct mwifiex_plt_wake_cfg *cfg;
- int ret;
-
if (!of_match_node(mwifiex_sdio_of_match_table, dev->of_node)) {
dev_err(dev, "required compatible string missing\n");
return -EINVAL;
}
- card->plt_of_node = dev->of_node;
- card->plt_wake_cfg = devm_kzalloc(dev, sizeof(*card->plt_wake_cfg),
- GFP_KERNEL);
- cfg = card->plt_wake_cfg;
- if (cfg && card->plt_of_node) {
- cfg->dev = dev;
- cfg->irq_wifi = irq_of_parse_and_map(card->plt_of_node, 0);
- if (!cfg->irq_wifi) {
- dev_dbg(dev,
- "fail to parse irq_wifi from device tree\n");
- } else {
- ret = devm_request_irq(dev, cfg->irq_wifi,
- mwifiex_wake_irq_wifi,
- IRQF_TRIGGER_LOW,
- "wifi_wake", cfg);
- if (ret) {
- dev_dbg(dev,
- "Failed to request irq_wifi %d (%d)\n",
- cfg->irq_wifi, ret);
- card->plt_wake_cfg = NULL;
- return 0;
- }
- disable_irq(cfg->irq_wifi);
- }
- }
-
- ret = device_init_wakeup(dev, true);
- if (ret)
- dev_err(dev, "fail to init wakeup for mwifiex");
-
return 0;
}
@@ -198,11 +149,9 @@ static int mwifiex_sdio_probe_of(struct device *dev, struct sdio_mmc_card *card)
/* device tree node parsing and platform specific configuration*/
if (func->dev.of_node) {
- ret = mwifiex_sdio_probe_of(&func->dev, card);
- if (ret) {
- dev_err(&func->dev, "SDIO dt node parse failed\n");
+ ret = mwifiex_sdio_probe_of(&func->dev);
+ if (ret)
goto err_disable;
- }
}
ret = mwifiex_add_card(card, &add_remove_card_sem, &sdio_ops,
@@ -267,12 +216,7 @@ static int mwifiex_sdio_resume(struct device *dev)
mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA),
MWIFIEX_SYNC_CMD);
- /* Disable platform specific wakeup interrupt */
- if (card->plt_wake_cfg && card->plt_wake_cfg->irq_wifi >= 0) {
- disable_irq_wake(card->plt_wake_cfg->irq_wifi);
- if (!card->plt_wake_cfg->wake_by_wifi)
- disable_irq(card->plt_wake_cfg->irq_wifi);
- }
+ mwifiex_disable_wake(adapter);
return 0;
}
@@ -352,13 +296,7 @@ static int mwifiex_sdio_suspend(struct device *dev)
}
adapter = card->adapter;
-
- /* Enable platform specific wakeup interrupt */
- if (card->plt_wake_cfg && card->plt_wake_cfg->irq_wifi >= 0) {
- card->plt_wake_cfg->wake_by_wifi = false;
- enable_irq(card->plt_wake_cfg->irq_wifi);
- enable_irq_wake(card->plt_wake_cfg->irq_wifi);
- }
+ mwifiex_enable_wake(adapter);
/* Enable the Host Sleep */
if (!mwifiex_enable_hs(adapter)) {
diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.h b/drivers/net/wireless/marvell/mwifiex/sdio.h
index 07cdd23..b9fbc5c 100644
--- a/drivers/net/wireless/marvell/mwifiex/sdio.h
+++ b/drivers/net/wireless/marvell/mwifiex/sdio.h
@@ -154,12 +154,6 @@
a->mpa_rx.start_port = 0; \
} while (0)
-struct mwifiex_plt_wake_cfg {
- struct device *dev;
- int irq_wifi;
- bool wake_by_wifi;
-};
-
/* data structure for SDIO MPA TX */
struct mwifiex_sdio_mpa_tx {
/* multiport tx aggregation buffer pointer */
@@ -243,8 +237,6 @@ struct mwifiex_sdio_card_reg {
struct sdio_mmc_card {
struct sdio_func *func;
struct mwifiex_adapter *adapter;
- struct device_node *plt_of_node;
- struct mwifiex_plt_wake_cfg *plt_wake_cfg;
const char *firmware;
const struct mwifiex_sdio_card_reg *reg;
--
1.9.1
^ permalink raw reply related
* RE: [bug report] iwlwifi: mvm: use dev_coredumpsg()
From: Erenfeld, Aviya @ 2016-11-14 12:51 UTC (permalink / raw)
To: Dan Carpenter; +Cc: linux-wireless@vger.kernel.org, Berg, Johannes
In-Reply-To: <20161114112039.GA21931@mwanda>
Thanks,
Right, we already have a pending fix for that one.
Aviya
-----Original Message-----
From: Dan Carpenter [mailto:dan.carpenter@oracle.com]
Sent: Monday, November 14, 2016 13:21
To: Erenfeld, Aviya <aviya.erenfeld@intel.com>
Cc: linux-wireless@vger.kernel.org
Subject: [bug report] iwlwifi: mvm: use dev_coredumpsg()
Hello Aviya Erenfeld,
The patch 7e62a699aafb: "iwlwifi: mvm: use dev_coredumpsg()" from Sep 20, 2016, leads to the following static checker warning:
drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c:821 iwl_mvm_fw_error_dump()
error: we previously assumed 'fw_error_dump->trans_ptr' could be null (see line 809)
drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c
805 dump_trans_data:
806 fw_error_dump->trans_ptr = iwl_trans_dump_data(mvm->trans,
807 mvm->fw_dump_trig);
808 fw_error_dump->op_mode_len = file_len;
809 if (fw_error_dump->trans_ptr)
810 file_len += fw_error_dump->trans_ptr->len;
We assume ->trans_ptr can be NULL.
811 dump_file->file_len = cpu_to_le32(file_len);
812
813 sg_dump_data = alloc_sgtable(file_len);
That probably means file_len is zero? (didn't look). That means sg_dump_data is ZERO_SIZE_PTR (16).
814 if (sg_dump_data) {
815 sg_pcopy_from_buffer(sg_dump_data,
816 sg_nents(sg_dump_data),
817 fw_error_dump->op_mode_ptr,
818 fw_error_dump->op_mode_len, 0);
819 sg_pcopy_from_buffer(sg_dump_data,
820 sg_nents(sg_dump_data),
821 fw_error_dump->trans_ptr->data,
Leading to an oops.
822 fw_error_dump->trans_ptr->len,
823 fw_error_dump->op_mode_len);
824 dev_coredumpsg(mvm->trans->dev, sg_dump_data, file_len,
825 GFP_KERNEL);
826 }
827 vfree(fw_error_dump->op_mode_ptr);
828 vfree(fw_error_dump->trans_ptr);
829 kfree(fw_error_dump);
830
831 out:
832 iwl_mvm_free_fw_dump_desc(mvm);
833 mvm->fw_dump_trig = NULL;
834 clear_bit(IWL_MVM_STATUS_DUMPING_FW_LOG, &mvm->status);
835 }
regards,
dan carpenter
---------------------------------------------------------------------
A member of the Intel Corporation group of companies
This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.
^ permalink raw reply
* RE: [ath9k-devel] [NOT FOR MERGE] ath9k: work around key cache corruption
From: Stam, Michel [FINT] @ 2016-11-14 12:50 UTC (permalink / raw)
To: Johannes Berg, Sebastian Gottschall, Kalle Valo,
Antonio Quartulli
Cc: ath9k-devel@lists.ath9k.org, linux-wireless@vger.kernel.org,
Antonio Quartulli
In-Reply-To: <1477580802.4534.20.camel@sipsolutions.net>
Dear List,
After 2 weeks of Ferry Huberts and me trying to resolve this issue, this is the result:
The problem can be mitigated by resetting the chip and immediately replumbing the encryption keys. I wrote a patch for this, which unfortunately this seems to suffer from some locking issues, rtnl_lock and sc->mutex being the chief culprits.
Code snippet:
static void ath9k_plumb_key(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct ieee80211_key_conf *keyconf, void *data)
{
struct ath_common *common = (struct ath_common *)data;
int ret;
/* delete and re-install keys which were programmed into the hardware */
if (vif && test_bit(keyconf->hw_key_idx, common->keymap)) {
ath_key_delete(common, keyconf);
keyconf->hw_key_idx = 0;
ret = ath_key_config(common, vif, sta, keyconf);
if (ret >= 0)
keyconf->hw_key_idx = ret;
}
}
To reset and replumb, taken from ath_reset_internal():
ath9k_hw_kill_interrupts(sc->sc_ah);
set_bit(ATH_OP_HW_RESET, &common->op_flags);
ath9k_ps_wakeup(sc);
ath_reset_internal(sc, NULL);
rtnl_lock();
ieee80211_iter_keys(sc->hw, NULL, ath9k_plumb_key, common);
rtnl_unlock();
ath9k_ps_restore(sc);
In any case, the problem is only mitigated. It is not solved, as I see the error appearing still (less frequently though).
Looking at the OpenHAL has not yielded anything working either (there is a reference to KEY_PLUMB_WAR, but it is not a full implementation).
What I understand from previous attempts to tackle this issue is that Qualcomm is aware of the problem, and a workaround exists in at least the proprietary driver. I have tried to contact Qualcomm support about this, since it is not radio card specific, but I have not received any response so far.
I hope a Qualcomm employee reads this and is able to help obtain the information that is necessary to resolve this issue. Until then, I recommend using software encryption (nohwcrypt), or setting a very long rekeying time.
Kind regards,
Michel Stam
-----Original Message-----
From: ath9k-devel-bounces@lists.ath9k.org [mailto:ath9k-devel-bounces@lists.ath9k.org] On Behalf Of Johannes Berg
Sent: Thursday, October 27, 2016 17:07 PM
To: Sebastian Gottschall; Kalle Valo; Antonio Quartulli
Cc: ath9k-devel@lists.ath9k.org; linux-wireless@vger.kernel.org; Antonio Quartulli
Subject: Re: [ath9k-devel] [NOT FOR MERGE] ath9k: work around key cache corruption
On Thu, 2016-10-27 at 09:54 +0200, Sebastian Gottschall wrote:
> all patches have a unclear license since most patches are not comming
> with any licence declaration ;-)
You should read the DCO some time. Maybe you shouldn't be sending
patches if you think so.
johannes
_______________________________________________
ath9k-devel mailing list
ath9k-devel@lists.ath9k.org
https://lists.ath9k.org/mailman/listinfo/ath9k-devel
^ permalink raw reply
* [PATCH] ath10k: fix null deref on wmi-tlv when trying spectral scan
From: Michal Kazior @ 2016-11-14 13:25 UTC (permalink / raw)
To: ath10k; +Cc: linux-wireless, Michal Kazior
WMI ops wrappers did not properly check for null
function pointers for spectral scan. This caused
null dereference crash with WMI-TLV based firmware
which doesn't implement spectral scan.
The crash could be triggered with:
ip link set dev wlan0 up
echo background > /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan_ctl
The crash looked like this:
[ 168.031989] BUG: unable to handle kernel NULL pointer dereference at (null)
[ 168.037406] IP: [< (null)>] (null)
[ 168.040395] PGD cdd4067 PUD fa0f067 PMD 0
[ 168.043303] Oops: 0010 [#1] SMP
[ 168.045377] Modules linked in: ath10k_pci(O) ath10k_core(O) ath mac80211 cfg80211 [last unloaded: cfg80211]
[ 168.051560] CPU: 1 PID: 1380 Comm: bash Tainted: G W O 4.8.0 #78
[ 168.054336] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.7.5-20140531_083030-gandalf 04/01/2014
[ 168.059183] task: ffff88000c460c00 task.stack: ffff88000d4bc000
[ 168.061736] RIP: 0010:[<0000000000000000>] [< (null)>] (null)
...
[ 168.100620] Call Trace:
[ 168.101910] [<ffffffffa03b9566>] ? ath10k_spectral_scan_config+0x96/0x200 [ath10k_core]
[ 168.104871] [<ffffffff811386e2>] ? filemap_fault+0xb2/0x4a0
[ 168.106696] [<ffffffffa03b97e6>] write_file_spec_scan_ctl+0x116/0x280 [ath10k_core]
[ 168.109618] [<ffffffff812da3a1>] full_proxy_write+0x51/0x80
[ 168.111443] [<ffffffff811957b8>] __vfs_write+0x28/0x120
[ 168.113090] [<ffffffff812f1a2d>] ? security_file_permission+0x3d/0xc0
[ 168.114932] [<ffffffff8109b912>] ? percpu_down_read+0x12/0x60
[ 168.116680] [<ffffffff811965f8>] vfs_write+0xb8/0x1a0
[ 168.118293] [<ffffffff81197966>] SyS_write+0x46/0xa0
[ 168.119912] [<ffffffff818f2972>] entry_SYSCALL_64_fastpath+0x1a/0xa4
[ 168.121737] Code: Bad RIP value.
[ 168.123318] RIP [< (null)>] (null)
Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
---
drivers/net/wireless/ath/ath10k/wmi-ops.h | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/net/wireless/ath/ath10k/wmi-ops.h b/drivers/net/wireless/ath/ath10k/wmi-ops.h
index c9a8bb1186f2..c7956e181f80 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-ops.h
+++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h
@@ -660,6 +660,9 @@ ath10k_wmi_vdev_spectral_conf(struct ath10k *ar,
struct sk_buff *skb;
u32 cmd_id;
+ if (!ar->wmi.ops->gen_vdev_spectral_conf)
+ return -EOPNOTSUPP;
+
skb = ar->wmi.ops->gen_vdev_spectral_conf(ar, arg);
if (IS_ERR(skb))
return PTR_ERR(skb);
@@ -675,6 +678,9 @@ ath10k_wmi_vdev_spectral_enable(struct ath10k *ar, u32 vdev_id, u32 trigger,
struct sk_buff *skb;
u32 cmd_id;
+ if (!ar->wmi.ops->gen_vdev_spectral_enable)
+ return -EOPNOTSUPP;
+
skb = ar->wmi.ops->gen_vdev_spectral_enable(ar, vdev_id, trigger,
enable);
if (IS_ERR(skb))
--
2.1.4
^ permalink raw reply related
* Re: [PATCH] rtl8xxxu: Fix failure to reconnect to AP
From: Jes Sorensen @ 2016-11-14 13:24 UTC (permalink / raw)
To: Barry Day; +Cc: Kalle Valo, linux-wireless
In-Reply-To: <20161113111705.GA2393@box64.home.org>
Barry Day <briselec@gmail.com> writes:
> The rtl8192e and rtl8723 fail to reconnect to an AP after being
> disconnected. Ths patch fixes that without affecting the rtl8192cu.
> I don't have a rtl8723 to test but it has been tested on a rtl8192eu.
> After going through the orginal realtek code for the rtl8723, I am
> confident the patch is applicable to both.
>
> Signed-off-by: Barry Day <briselec@gmail.com>
> ---
> rtl8xxxu_core.c | 18 ++++++++++++++----
> 1 file changed, 14 insertions(+), 4 deletions(-)
Hi Barry,
Thank you for the patch. There are a couple of items which I am not
100% sure about the order of.
> diff --git a/rtl8xxxu_core.c b/rtl8xxxu_core.c
> index 04141e5..6ac10d2 100644
> --- a/rtl8xxxu_core.c
> +++ b/rtl8xxxu_core.c
> @@ -4372,17 +4372,25 @@ void rtl8xxxu_gen1_report_connect(struct rtl8xxxu_priv *priv,
> void rtl8xxxu_gen2_report_connect(struct rtl8xxxu_priv *priv,
> u8 macid, bool connect)
> {
> + u8 val8;
> struct h2c_cmd h2c;
>
> memset(&h2c, 0, sizeof(struct h2c_cmd));
>
> h2c.media_status_rpt.cmd = H2C_8723B_MEDIA_STATUS_RPT;
> - if (connect)
> + if (connect) {
> h2c.media_status_rpt.parm |= BIT(0);
> - else
> - h2c.media_status_rpt.parm &= ~BIT(0);
> + rtl8xxxu_gen2_h2c_cmd(priv, &h2c,
> + sizeof(h2c.media_status_rpt));
> + } else {
> + val8 = rtl8xxxu_read8(priv, REG_BEACON_CTRL);
> + val8 &= ~BEACON_FUNCTION_ENABLE;
> +
> + rtl8xxxu_write8(priv, REG_BEACON_CTRL, val8);
> + rtl8xxxu_write16(priv, REG_RXFLTMAP2, 0x00);
> + rtl8xxxu_write8(priv, REG_DUAL_TSF_RST, (BIT(0) | BIT(1)));
> + }
>
> - rtl8xxxu_gen2_h2c_cmd(priv, &h2c, sizeof(h2c.media_status_rpt));
> }
This only affects 8192eu and not 8192cu - we left RXFLTMAP2 out of here
on purpose for monitor mode, but you now disable it for 8192eu/8723bu.
> void rtl8xxxu_gen1_init_aggregation(struct rtl8xxxu_priv *priv)
> @@ -4515,6 +4523,8 @@ rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
> sgi = 1;
> rcu_read_unlock();
>
> + rtl8xxxu_write16(priv, REG_RXFLTMAP2, 0xffff);
> +
> priv->fops->update_rate_mask(priv, ramask, sgi);
>
> rtl8xxxu_write8(priv, REG_BCN_MAX_ERR, 0xff);
Here you enable RXFLTMAP2 for all devices - this doesn't balance with
the above.
I am not against the aproach, but I think we need to investigate a
little further what is going on.
Cheers,
Jes
^ permalink raw reply
* [PATCH] ath10k: add spectral scan support to wmi-tlv
From: Michal Kazior @ 2016-11-14 13:26 UTC (permalink / raw)
To: ath10k; +Cc: linux-wireless, Michal Kazior
Command structure and event flow doesn't seem to
be any different compared to existing
implementation for other firmware branches.
This patch effectively adds in-driver support for
spectral scanning on QCA61x4 and QCA9377.
Tested QCA9377 w/ WLAN.TF.1.0-00267-1.
Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
---
drivers/net/wireless/ath/ath10k/wmi-tlv.c | 72 +++++++++++++++++++++++++++++++
1 file changed, 72 insertions(+)
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
index e64f59300a7c..7f9b1185b549 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
@@ -3136,6 +3136,76 @@ ath10k_wmi_tlv_op_gen_echo(struct ath10k *ar, u32 value)
return skb;
}
+static struct sk_buff *
+ath10k_wmi_tlv_op_gen_vdev_spectral_conf(struct ath10k *ar,
+ const struct wmi_vdev_spectral_conf_arg *arg)
+{
+ struct wmi_vdev_spectral_conf_cmd *cmd;
+ struct sk_buff *skb;
+ struct wmi_tlv *tlv;
+ void *ptr;
+ size_t len;
+
+ len = sizeof(*tlv) + sizeof(*cmd);
+ skb = ath10k_wmi_alloc_skb(ar, len);
+ if (!skb)
+ return ERR_PTR(-ENOMEM);
+
+ ptr = (void *)skb->data;
+ tlv = ptr;
+ tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_SPECTRAL_CONFIGURE_CMD);
+ tlv->len = __cpu_to_le16(sizeof(*cmd));
+ cmd = (void *)tlv->value;
+ cmd->vdev_id = __cpu_to_le32(arg->vdev_id);
+ cmd->scan_count = __cpu_to_le32(arg->scan_count);
+ cmd->scan_period = __cpu_to_le32(arg->scan_period);
+ cmd->scan_priority = __cpu_to_le32(arg->scan_priority);
+ cmd->scan_fft_size = __cpu_to_le32(arg->scan_fft_size);
+ cmd->scan_gc_ena = __cpu_to_le32(arg->scan_gc_ena);
+ cmd->scan_restart_ena = __cpu_to_le32(arg->scan_restart_ena);
+ cmd->scan_noise_floor_ref = __cpu_to_le32(arg->scan_noise_floor_ref);
+ cmd->scan_init_delay = __cpu_to_le32(arg->scan_init_delay);
+ cmd->scan_nb_tone_thr = __cpu_to_le32(arg->scan_nb_tone_thr);
+ cmd->scan_str_bin_thr = __cpu_to_le32(arg->scan_str_bin_thr);
+ cmd->scan_wb_rpt_mode = __cpu_to_le32(arg->scan_wb_rpt_mode);
+ cmd->scan_rssi_rpt_mode = __cpu_to_le32(arg->scan_rssi_rpt_mode);
+ cmd->scan_rssi_thr = __cpu_to_le32(arg->scan_rssi_thr);
+ cmd->scan_pwr_format = __cpu_to_le32(arg->scan_pwr_format);
+ cmd->scan_rpt_mode = __cpu_to_le32(arg->scan_rpt_mode);
+ cmd->scan_bin_scale = __cpu_to_le32(arg->scan_bin_scale);
+ cmd->scan_dbm_adj = __cpu_to_le32(arg->scan_dbm_adj);
+ cmd->scan_chn_mask = __cpu_to_le32(arg->scan_chn_mask);
+
+ return skb;
+}
+
+static struct sk_buff *
+ath10k_wmi_tlv_op_gen_vdev_spectral_enable(struct ath10k *ar, u32 vdev_id,
+ u32 trigger, u32 enable)
+{
+ struct wmi_vdev_spectral_enable_cmd *cmd;
+ struct sk_buff *skb;
+ struct wmi_tlv *tlv;
+ void *ptr;
+ size_t len;
+
+ len = sizeof(*tlv) + sizeof(*cmd);
+ skb = ath10k_wmi_alloc_skb(ar, len);
+ if (!skb)
+ return ERR_PTR(-ENOMEM);
+
+ ptr = (void *)skb->data;
+ tlv = ptr;
+ tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_SPECTRAL_ENABLE_CMD);
+ tlv->len = __cpu_to_le16(sizeof(*cmd));
+ cmd = (void *)tlv->value;
+ cmd->vdev_id = __cpu_to_le32(vdev_id);
+ cmd->trigger_cmd = __cpu_to_le32(trigger);
+ cmd->enable_cmd = __cpu_to_le32(enable);
+
+ return skb;
+}
+
/****************/
/* TLV mappings */
/****************/
@@ -3542,6 +3612,8 @@ static const struct wmi_ops wmi_tlv_ops = {
.fw_stats_fill = ath10k_wmi_main_op_fw_stats_fill,
.get_vdev_subtype = ath10k_wmi_op_get_vdev_subtype,
.gen_echo = ath10k_wmi_tlv_op_gen_echo,
+ .gen_vdev_spectral_conf = ath10k_wmi_tlv_op_gen_vdev_spectral_conf,
+ .gen_vdev_spectral_enable = ath10k_wmi_tlv_op_gen_vdev_spectral_enable,
};
static const struct wmi_peer_flags_map wmi_tlv_peer_flags_map = {
--
2.1.4
^ permalink raw reply related
* Re: [RFC] change mac80211_hwsim tx_rates to ieee80211_tx_rate
From: Johannes Berg @ 2016-11-14 14:09 UTC (permalink / raw)
To: Benjamin Beichler, linux-wireless
In-Reply-To: <faf081ea-18c6-8ad5-e336-aac9a79a0ce3@uni-rostock.de>
> I agree with that, but there exist also other code in hwsim, which is
> tightly coupled with the mac80211 API, as e.g., the usage of
> IEEE80211_TX_MAX_RATES, which already broke older versions of
> wmediumd or similar implementations. Maybe a review regarding such
> things would be good to decouple the userspace daemon from the
> special kernel version.
Agree. It'd be better if that were using nested attributes etc.
Although then again, to really decouple this we should make hwsim
behave towards wmediumd more like real hardware would, and have it pass
just a single rate to userspace, with only success/fail indication
coming back - if it fails, it could walk down the chain of rates
itself. Right now we let wmediumd do this, which is why we have all
these API internals exposed to it.
> > > but I think that will break up the communication to e.g. bob
> > > copelands
> > > wmediumd and similar simulations. I would like to have our
> > > Implementation working with mainline kernels and therefore ask
> > > how we
> > > could achieve this easily.
> > >
> > > Obviously, we could define another field in the hwsim messages,
> > > but
> > > as bob copeland already stated, significantly more information
> > > within
> > > the netlink messages could intensify the timing overhead of
> > > hwsim.
> > I don't think we have any other choice but add the relevant fields
> > as
> > proper attributes.
>
> I'm totally fine with that. Nonetheless, I would suggest to add the
> flags to "struct hwsim_tx_rate", since the flags are also tightly
> coupled to the rates and tries of a frame. To not break up things, we
> could add the flags as a separate attribute in the struct and not as
> part of the bitfield like in the original. This would be possible,
> due
> to the "__packed" flag, but I'm also unsure, whether this is a really
> good idea for a userspace API/ABI.
Changing the struct size itself would break ABI though?
johannes
^ permalink raw reply
* [RFC 1/2] ath9k: work around AR_CFG 0xdeadbeef chip hang
From: Sven Eckelmann @ 2016-11-14 14:42 UTC (permalink / raw)
To: ath9k-devel; +Cc: linux-wireless, ath9k-devel, Simon Wunderlich, Sven Eckelmann
From: Simon Wunderlich <simon.wunderlich@open-mesh.com>
QCA 802.11n chips (especially AR9330/AR9340) sometimes end up in a state in
which a read of AR_CFG always returns 0xdeadbeef. This should not happen
when when the power_mode of the device is ATH9K_PM_AWAKE.
This problem is not yet detected by any other workaround in ath9k. No way
is known to reproduce the problem easily.
Signed-off-by: Simon Wunderlich <simon.wunderlich@open-mesh.com>
[sven.eckelmann@open-mesh.com: port to recent ath9k, add commit message]
Signed-off-by: Sven Eckelmann <sven.eckelmann@open-mesh.com>
---
This was discussed 4 years ago on the OpenWrt mailing list. The most
relevant post is
https://lists.openwrt.org/pipermail/openwrt-devel/2012-September/016708.html
---
drivers/net/wireless/ath/ath9k/ath9k.h | 3 +++
drivers/net/wireless/ath/ath9k/debug.c | 1 +
drivers/net/wireless/ath/ath9k/debug.h | 1 +
drivers/net/wireless/ath/ath9k/init.c | 1 +
drivers/net/wireless/ath/ath9k/link.c | 33 +++++++++++++++++++++++++++++++++
drivers/net/wireless/ath/ath9k/main.c | 4 ++++
6 files changed, 43 insertions(+)
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 26fc8ec..9c6fee7 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -710,11 +710,13 @@ void ath9k_csa_update(struct ath_softc *sc);
#define ATH_ANI_MAX_SKIP_COUNT 10
#define ATH_PAPRD_TIMEOUT 100 /* msecs */
#define ATH_PLL_WORK_INTERVAL 100
+#define ATH_HANG_WORK_INTERVAL 30000
void ath_tx_complete_poll_work(struct work_struct *work);
void ath_reset_work(struct work_struct *work);
bool ath_hw_check(struct ath_softc *sc);
void ath_hw_pll_work(struct work_struct *work);
+void ath_hw_hang_work(struct work_struct *work);
void ath_paprd_calibrate(struct work_struct *work);
void ath_ani_calibrate(unsigned long data);
void ath_start_ani(struct ath_softc *sc);
@@ -1014,6 +1016,7 @@ struct ath_softc {
#endif
struct delayed_work tx_complete_work;
struct delayed_work hw_pll_work;
+ struct delayed_work hw_hang_work;
struct timer_list sleep_timer;
#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index c56e40f..608b370 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -767,6 +767,7 @@ static int read_file_reset(struct seq_file *file, void *data)
[RESET_TYPE_CALIBRATION] = "Calibration error",
[RESET_TX_DMA_ERROR] = "Tx DMA stop error",
[RESET_RX_DMA_ERROR] = "Rx DMA stop error",
+ [RESET_TYPE_DEADBEEF] = "deadbeef hang",
};
int i;
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
index cd68c5f..0d77abbf6 100644
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -52,6 +52,7 @@ enum ath_reset_type {
RESET_TYPE_CALIBRATION,
RESET_TX_DMA_ERROR,
RESET_RX_DMA_ERROR,
+ RESET_TYPE_DEADBEEF,
__RESET_TYPE_MAX
};
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index 368d9b3..9bc7d1c 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -638,6 +638,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
INIT_WORK(&sc->hw_reset_work, ath_reset_work);
INIT_WORK(&sc->paprd_work, ath_paprd_calibrate);
INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work);
+ INIT_DELAYED_WORK(&sc->hw_hang_work, ath_hw_hang_work);
ath9k_init_channel_context(sc);
diff --git a/drivers/net/wireless/ath/ath9k/link.c b/drivers/net/wireless/ath/ath9k/link.c
index 5ad0fee..ff11d85 100644
--- a/drivers/net/wireless/ath/ath9k/link.c
+++ b/drivers/net/wireless/ath/ath9k/link.c
@@ -138,6 +138,39 @@ void ath_hw_pll_work(struct work_struct *work)
msecs_to_jiffies(ATH_PLL_WORK_INTERVAL));
}
+static bool ath_hw_hang_deadbeef(struct ath_softc *sc)
+{
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ u32 reg;
+
+ /* check for stucked MAC */
+ ath9k_ps_wakeup(sc);
+ reg = REG_READ(sc->sc_ah, AR_CFG);
+ ath9k_ps_restore(sc);
+
+ if (reg != 0xdeadbeef)
+ return false;
+
+ ath_dbg(common, RESET,
+ "0xdeadbeef hang is detected. Schedule chip reset\n");
+ ath9k_queue_reset(sc, RESET_TYPE_DEADBEEF);
+
+ return true;
+}
+
+void ath_hw_hang_work(struct work_struct *work)
+{
+ struct ath_softc *sc = container_of(work, struct ath_softc,
+ hw_hang_work.work);
+
+ if (ath_hw_hang_deadbeef(sc))
+ goto requeue_worker;
+
+requeue_worker:
+ ieee80211_queue_delayed_work(sc->hw, &sc->hw_hang_work,
+ msecs_to_jiffies(ATH_HANG_WORK_INTERVAL));
+}
+
/*
* PA Pre-distortion.
*/
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index e9f32b5..4d3e216 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -183,6 +183,7 @@ static void __ath_cancel_work(struct ath_softc *sc)
cancel_work_sync(&sc->paprd_work);
cancel_delayed_work_sync(&sc->tx_complete_work);
cancel_delayed_work_sync(&sc->hw_pll_work);
+ cancel_delayed_work_sync(&sc->hw_hang_work);
#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
if (ath9k_hw_mci_is_enabled(sc->sc_ah))
@@ -204,6 +205,9 @@ void ath_restart_work(struct ath_softc *sc)
ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work,
msecs_to_jiffies(ATH_PLL_WORK_INTERVAL));
+ ieee80211_queue_delayed_work(sc->hw, &sc->hw_hang_work,
+ msecs_to_jiffies(ATH_HANG_WORK_INTERVAL));
+
ath_start_ani(sc);
}
--
2.10.2
^ permalink raw reply related
* [RFC 2/2] ath9k: Reset chip on potential deaf state
From: Sven Eckelmann @ 2016-11-14 14:42 UTC (permalink / raw)
To: ath9k-devel; +Cc: linux-wireless, ath9k-devel, Simon Wunderlich, Sven Eckelmann
In-Reply-To: <20161114144226.15748-1-sven.eckelmann@open-mesh.com>
From: Simon Wunderlich <simon.wunderlich@open-mesh.com>
The chip is switching seemingly random into a state which can be described
as "deaf". No or nearly no interrupts are generated anymore for incoming
packets. Existing links either break down after a while and new links will
not be established.
The driver doesn't know if there is no other device available or if it
ended up in an "deaf" state. Resetting the chip proactively avoids
permanent problems in case the chip really was in its "deaf" state but
maybe causes unnecessary resets in case it wasn't "deaf".
Signed-off-by: Simon Wunderlich <simon.wunderlich@open-mesh.com>
[sven.eckelmann@open-mesh.com: port to recent ath9k, add commit message]
Signed-off-by: Sven Eckelmann <sven.eckelmann@open-mesh.com>
---
This problem was discovered in mesh setups. It was noticed that some nodes
were not able to see their neighbors (mostly after running for a while) -
even when those neighbors received data from them via IBSS. A simple `iw
dev wlan0 scan` fixed the problem for them. But the problem seems to
reappear after while(tm) in a large enough(tm) mesh.
This patch is a little bit obscure because it requires CONFIG_ATH9K_DEBUGFS
to actually work. But there still seems to be potential interest in
Freifunk communities or Freifunk meta-projects (e.g. freifunk-gluon). It is
currently not known if it helps them but publishing this to allow them to
test and play around with it will not hurt :)
---
drivers/net/wireless/ath/ath9k/ath9k.h | 3 +++
drivers/net/wireless/ath/ath9k/debug.c | 1 +
drivers/net/wireless/ath/ath9k/debug.h | 1 +
drivers/net/wireless/ath/ath9k/link.c | 45 ++++++++++++++++++++++++++++++++++
4 files changed, 50 insertions(+)
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 9c6fee7..3987ad5 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -996,6 +996,9 @@ struct ath_softc {
short nbcnvifs;
unsigned long ps_usecount;
+ unsigned long last_check_time;
+ u32 last_check_interrupts;
+
struct ath_rx rx;
struct ath_tx tx;
struct ath_beacon beacon;
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index 608b370..6d5c253 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -768,6 +768,7 @@ static int read_file_reset(struct seq_file *file, void *data)
[RESET_TX_DMA_ERROR] = "Tx DMA stop error",
[RESET_RX_DMA_ERROR] = "Rx DMA stop error",
[RESET_TYPE_DEADBEEF] = "deadbeef hang",
+ [RESET_TYPE_DEAF] = "deaf hang",
};
int i;
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
index 0d77abbf6..6f186bd 100644
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -53,6 +53,7 @@ enum ath_reset_type {
RESET_TX_DMA_ERROR,
RESET_RX_DMA_ERROR,
RESET_TYPE_DEADBEEF,
+ RESET_TYPE_DEAF,
__RESET_TYPE_MAX
};
diff --git a/drivers/net/wireless/ath/ath9k/link.c b/drivers/net/wireless/ath/ath9k/link.c
index ff11d85..f4b74b7 100644
--- a/drivers/net/wireless/ath/ath9k/link.c
+++ b/drivers/net/wireless/ath/ath9k/link.c
@@ -158,6 +158,48 @@ static bool ath_hw_hang_deadbeef(struct ath_softc *sc)
return true;
}
+static bool ath_hw_hang_deaf(struct ath_softc *sc)
+{
+#ifndef CONFIG_ATH9K_DEBUGFS
+ return false;
+#else
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ u32 interrupts, interrupt_per_s;
+ unsigned int interval;
+
+ /* get historic data */
+ interval = jiffies_to_msecs(jiffies - sc->last_check_time);
+ if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
+ interrupts = sc->debug.stats.istats.rxlp;
+ else
+ interrupts = sc->debug.stats.istats.rxok;
+
+ interrupts -= sc->last_check_interrupts;
+
+ /* save current data */
+ sc->last_check_time = jiffies;
+ if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
+ sc->last_check_interrupts = sc->debug.stats.istats.rxlp;
+ else
+ sc->last_check_interrupts = sc->debug.stats.istats.rxok;
+
+ /* sanity check, should be 30 seconds */
+ if (interval > 40000 || interval < 20000)
+ return false;
+
+ /* should be at least one interrupt per second */
+ interrupt_per_s = interrupts / (interval / 1000);
+ if (interrupt_per_s >= 1)
+ return false;
+
+ ath_dbg(common, RESET,
+ "RX deaf hang is detected. Schedule chip reset\n");
+ ath9k_queue_reset(sc, RESET_TYPE_DEAF);
+
+ return true;
+#endif
+}
+
void ath_hw_hang_work(struct work_struct *work)
{
struct ath_softc *sc = container_of(work, struct ath_softc,
@@ -166,6 +208,9 @@ void ath_hw_hang_work(struct work_struct *work)
if (ath_hw_hang_deadbeef(sc))
goto requeue_worker;
+ if (ath_hw_hang_deaf(sc))
+ goto requeue_worker;
+
requeue_worker:
ieee80211_queue_delayed_work(sc->hw, &sc->hw_hang_work,
msecs_to_jiffies(ATH_HANG_WORK_INTERVAL));
--
2.10.2
^ permalink raw reply related
* Re: [RFC] change mac80211_hwsim tx_rates to ieee80211_tx_rate
From: Benjamin Beichler @ 2016-11-14 14:48 UTC (permalink / raw)
To: Johannes Berg, linux-wireless
In-Reply-To: <1479132555.12007.6.camel@sipsolutions.net>
> I agree with that, but there exist also other code in hwsim, which is
>> tightly coupled with the mac80211 API, as e.g., the usage of
>> IEEE80211_TX_MAX_RATES, which already broke older versions of
>> wmediumd or similar implementations. Maybe a review regarding such
>> things would be good to decouple the userspace daemon from the
>> special kernel version.
> Agree. It'd be better if that were using nested attributes etc.
> Although then again, to really decouple this we should make hwsim
> behave towards wmediumd more like real hardware would, and have it pass
> just a single rate to userspace, with only success/fail indication
> coming back - if it fails, it could walk down the chain of rates
> itself. Right now we let wmediumd do this, which is why we have all
> these API internals exposed to it.
Mhh, I thought also some atheros drivers implement hardware multirate
retry changes, which maps to this struct. Only one rate per frame would
introduce a extreme additional communication overhead, which will make
testing with standard wmediumd impractical. I think we need to keep such
a structure, but we should align that with other mac80211 depended drivers.
>
>>>> but I think that will break up the communication to e.g. bob
>>>> copelands
>>>> wmediumd and similar simulations. I would like to have our
>>>> Implementation working with mainline kernels and therefore ask
>>>> how we
>>>> could achieve this easily.
>>>>
>>>> Obviously, we could define another field in the hwsim messages,
>>>> but
>>>> as bob copeland already stated, significantly more information
>>>> within
>>>> the netlink messages could intensify the timing overhead of
>>>> hwsim.
>>> I don't think we have any other choice but add the relevant fields
>>> as
>>> proper attributes.
>> I'm totally fine with that. Nonetheless, I would suggest to add the
>> flags to "struct hwsim_tx_rate", since the flags are also tightly
>> coupled to the rates and tries of a frame. To not break up things, we
>> could add the flags as a separate attribute in the struct and not as
>> part of the bitfield like in the original. This would be possible,
>> due
>> to the "__packed" flag, but I'm also unsure, whether this is a really
>> good idea for a userspace API/ABI.
> Changing the struct size itself would break ABI though?
You are totally right ... I was a bit absent. But the point is, without
the rates and tries, the flags are useless, so I think it is better to
put them together, but I'm also fine with another attribute ;-)
Benjamin
^ permalink raw reply
* Re: [RFC] change mac80211_hwsim tx_rates to ieee80211_tx_rate
From: Johannes Berg @ 2016-11-14 14:56 UTC (permalink / raw)
To: Benjamin Beichler, linux-wireless
In-Reply-To: <838c443a-f8aa-ab21-61b0-9352f24442b1@uni-rostock.de>
> Mhh, I thought also some atheros drivers implement hardware multirate
> retry changes, which maps to this struct. Only one rate per frame
> would introduce a extreme additional communication overhead, which
> will make testing with standard wmediumd impractical. I think we need
> to keep such a structure, but we should align that with other
> mac80211 depended drivers.
Yeah, I was being imprecise. The driver interface is usually similar to
the mac80211 struct in one way or another (though it might also be a
more global table, like other drivers implement).
I was more thinking of the actual air interface. I'm not too worried
about the efficiency of this (we can push quite a few gbps over hwsim
today iirc), but it actually doesn't make sense because an accurate
simulation would require NAV/TXOP simulation, and that wouldn't be
possible with "software retry".
So I think our best bet remains to map this to new attributes - better
with properly formatted ones etc. than with the struct (keeping that
only for compatibility)
If you're worried about the overhead, we could consider converting
hwsim to use the rate_table API - see struct ieee80211_sta -> rates,
and maybe adding a signal to update that in the driver, send that to
userspace directly and work with that, rather than "serializing" the
table for every frame?
johannes
^ permalink raw reply
* Re: [PATCH] rtl8xxxu: Fix failure to reconnect to AP
From: Barry Day @ 2016-11-14 16:05 UTC (permalink / raw)
To: Jes Sorensen; +Cc: Kalle Valo, linux-wireless
In-Reply-To: <wrfjoa1iyz1e.fsf@redhat.com>
On Mon, Nov 14, 2016 at 08:24:45AM -0500, Jes Sorensen wrote:
> Barry Day <briselec@gmail.com> writes:
> > The rtl8192e and rtl8723 fail to reconnect to an AP after being
> > disconnected. Ths patch fixes that without affecting the rtl8192cu.
> > I don't have a rtl8723 to test but it has been tested on a rtl8192eu.
> > After going through the orginal realtek code for the rtl8723, I am
> > confident the patch is applicable to both.
> >
> > Signed-off-by: Barry Day <briselec@gmail.com>
> > ---
> > rtl8xxxu_core.c | 18 ++++++++++++++----
> > 1 file changed, 14 insertions(+), 4 deletions(-)
>
> Hi Barry,
>
> Thank you for the patch. There are a couple of items which I am not
> 100% sure about the order of.
>
> > diff --git a/rtl8xxxu_core.c b/rtl8xxxu_core.c
> > index 04141e5..6ac10d2 100644
> > --- a/rtl8xxxu_core.c
> > +++ b/rtl8xxxu_core.c
> > @@ -4372,17 +4372,25 @@ void rtl8xxxu_gen1_report_connect(struct rtl8xxxu_priv *priv,
> > void rtl8xxxu_gen2_report_connect(struct rtl8xxxu_priv *priv,
> > u8 macid, bool connect)
> > {
> > + u8 val8;
> > struct h2c_cmd h2c;
> >
> > memset(&h2c, 0, sizeof(struct h2c_cmd));
> >
> > h2c.media_status_rpt.cmd = H2C_8723B_MEDIA_STATUS_RPT;
> > - if (connect)
> > + if (connect) {
> > h2c.media_status_rpt.parm |= BIT(0);
> > - else
> > - h2c.media_status_rpt.parm &= ~BIT(0);
> > + rtl8xxxu_gen2_h2c_cmd(priv, &h2c,
> > + sizeof(h2c.media_status_rpt));
> > + } else {
> > + val8 = rtl8xxxu_read8(priv, REG_BEACON_CTRL);
> > + val8 &= ~BEACON_FUNCTION_ENABLE;
> > +
> > + rtl8xxxu_write8(priv, REG_BEACON_CTRL, val8);
> > + rtl8xxxu_write16(priv, REG_RXFLTMAP2, 0x00);
> > + rtl8xxxu_write8(priv, REG_DUAL_TSF_RST, (BIT(0) | BIT(1)));
> > + }
> >
> > - rtl8xxxu_gen2_h2c_cmd(priv, &h2c, sizeof(h2c.media_status_rpt));
> > }
>
> This only affects 8192eu and not 8192cu - we left RXFLTMAP2 out of here
> on purpose for monitor mode, but you now disable it for 8192eu/8723bu.
>
Even in monitor mode the interface has to brought up to use it which invokes
rtl8xxxu_start which sets it back to accepting frames.
> > void rtl8xxxu_gen1_init_aggregation(struct rtl8xxxu_priv *priv)
> > @@ -4515,6 +4523,8 @@ rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
> > sgi = 1;
> > rcu_read_unlock();
> >
> > + rtl8xxxu_write16(priv, REG_RXFLTMAP2, 0xffff);
> > +
> > priv->fops->update_rate_mask(priv, ramask, sgi);
> >
> > rtl8xxxu_write8(priv, REG_BCN_MAX_ERR, 0xff);
>
> Here you enable RXFLTMAP2 for all devices - this doesn't balance with
> the above.
>
The original realtek code I have for the 8192cu does the disconnect the
same way as in this patch. I tested the 8192cu using the patched
gen2_report connect and it works. That would make things consistent across
all chipsets.
^ permalink raw reply
* Re: [PATCH] rtl8xxxu: Fix failure to reconnect to AP
From: Jes Sorensen @ 2016-11-14 16:32 UTC (permalink / raw)
To: Barry Day; +Cc: Kalle Valo, linux-wireless
In-Reply-To: <20161114160504.GA12996@testbox>
Barry Day <briselec@gmail.com> writes:
> On Mon, Nov 14, 2016 at 08:24:45AM -0500, Jes Sorensen wrote:
>> Barry Day <briselec@gmail.com> writes:
>> > The rtl8192e and rtl8723 fail to reconnect to an AP after being
>> > disconnected. Ths patch fixes that without affecting the rtl8192cu.
>> > I don't have a rtl8723 to test but it has been tested on a rtl8192eu.
>> > After going through the orginal realtek code for the rtl8723, I am
>> > confident the patch is applicable to both.
>> >
>> > Signed-off-by: Barry Day <briselec@gmail.com>
>> > ---
>> > rtl8xxxu_core.c | 18 ++++++++++++++----
>> > 1 file changed, 14 insertions(+), 4 deletions(-)
>>
>> Hi Barry,
>>
>> Thank you for the patch. There are a couple of items which I am not
>> 100% sure about the order of.
>>
>> > diff --git a/rtl8xxxu_core.c b/rtl8xxxu_core.c
>> > index 04141e5..6ac10d2 100644
>> > --- a/rtl8xxxu_core.c
>> > +++ b/rtl8xxxu_core.c
>> > @@ -4372,17 +4372,25 @@ void rtl8xxxu_gen1_report_connect(struct rtl8xxxu_priv *priv,
>> > void rtl8xxxu_gen2_report_connect(struct rtl8xxxu_priv *priv,
>> > u8 macid, bool connect)
>> > {
>> > + u8 val8;
>> > struct h2c_cmd h2c;
>> >
>> > memset(&h2c, 0, sizeof(struct h2c_cmd));
>> >
>> > h2c.media_status_rpt.cmd = H2C_8723B_MEDIA_STATUS_RPT;
>> > - if (connect)
>> > + if (connect) {
>> > h2c.media_status_rpt.parm |= BIT(0);
>> > - else
>> > - h2c.media_status_rpt.parm &= ~BIT(0);
>> > + rtl8xxxu_gen2_h2c_cmd(priv, &h2c,
>> > + sizeof(h2c.media_status_rpt));
>> > + } else {
>> > + val8 = rtl8xxxu_read8(priv, REG_BEACON_CTRL);
>> > + val8 &= ~BEACON_FUNCTION_ENABLE;
>> > +
>> > + rtl8xxxu_write8(priv, REG_BEACON_CTRL, val8);
>> > + rtl8xxxu_write16(priv, REG_RXFLTMAP2, 0x00);
>> > + rtl8xxxu_write8(priv, REG_DUAL_TSF_RST, (BIT(0) | BIT(1)));
>> > + }
>> >
>> > - rtl8xxxu_gen2_h2c_cmd(priv, &h2c, sizeof(h2c.media_status_rpt));
>> > }
>>
>> This only affects 8192eu and not 8192cu - we left RXFLTMAP2 out of here
>> on purpose for monitor mode, but you now disable it for 8192eu/8723bu.
>
> Even in monitor mode the interface has to brought up to use it which invokes
> rtl8xxxu_start which sets it back to accepting frames.
>
>
>> > void rtl8xxxu_gen1_init_aggregation(struct rtl8xxxu_priv *priv)
>> > @@ -4515,6 +4523,8 @@ rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
>> > sgi = 1;
>> > rcu_read_unlock();
>> >
>> > + rtl8xxxu_write16(priv, REG_RXFLTMAP2, 0xffff);
>> > +
>> > priv->fops->update_rate_mask(priv, ramask, sgi);
>> >
>> > rtl8xxxu_write8(priv, REG_BCN_MAX_ERR, 0xff);
>>
>> Here you enable RXFLTMAP2 for all devices - this doesn't balance with
>> the above.
>
> The original realtek code I have for the 8192cu does the disconnect the
> same way as in this patch. I tested the 8192cu using the patched
> gen2_report connect and it works. That would make things consistent across
> all chipsets.
My concern is that you only set FLATMAP and BEACON_CTRL for gen2
devices, which has zero impact on gen1 devices, such as the 8192cu. If
need to do this for gen2 (8723bu/8192eu) I assume we need to do it for
gen1 as well.
I'd like to see us do a little more investigating on this first.
Jes
^ permalink raw reply
* [RFC 00/12] ath10k sdio support
From: Erik Stromdahl @ 2016-11-14 16:33 UTC (permalink / raw)
To: kvalo, linux-wireless, ath10k; +Cc: Erik Stromdahl
This patch series adds sdio support to ath10k.
Some of the patches affect the existing pcie/ahb code as well.
Those are patches 3 and 4 in the series.
Overview:
A new HIF layer: sdio/mailbox.
The current HIF ops are unaltered even though some ops
are not applicable for sdio.
The HTC layer has only suffered minor modifications:
- A few new functions for handling the mailbox specific
RX trailers (lookahead reports)
- Some minor refactorization of the existing code
(patches 3 and 4)
This is not included in this patch series:
- HTT High latency RX and TX support
- Full integration in core.c
The following basic tests have been made so far:
BMI fw load and firmware startup (all the steps in ath10k_core_start).
This means:
- HTT service connect
- WMI control service connect
- WMI unified init
The above mentioned bullets where verified with a QCA6584 chipset.
I have not been able to test the patch series together with
ath10k pcie hardware, but I will do so as soon as I can get
my hands on some hardware.
The patches have been built and tested against the ath tree:
git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
branch/tag: master/ath-201611090123
Erik Stromdahl (12):
ath10k: htc: made static function public
ath10k: htc: rx trailer lookahead support
ath10k: htc: Changed order of wait target and ep connect
ath10k: htc: refactorization
ath10k: htc: Added ATH10K_HTC_FLAG_BUNDLE_LSB
ath10k: bmi: Added SOC reg read/write functions
ath10k: Added SDIO dbg masks
ath10k: Added ATH10K_BUS_SDIO enum
ath10k: Mailbox address definitions
ath10k: Added QCA65XX hw definition
ath10k: Added more host_interest members
ath10k: Added sdio support
drivers/net/wireless/ath/ath10k/Kconfig | 6 +
drivers/net/wireless/ath/ath10k/Makefile | 3 +
drivers/net/wireless/ath/ath10k/bmi.c | 79 +-
drivers/net/wireless/ath/ath10k/bmi.h | 4 +
drivers/net/wireless/ath/ath10k/core.h | 3 +
drivers/net/wireless/ath/ath10k/debug.h | 2 +
drivers/net/wireless/ath/ath10k/htc.c | 208 ++-
drivers/net/wireless/ath/ath10k/htc.h | 36 +-
drivers/net/wireless/ath/ath10k/hw.h | 54 +
drivers/net/wireless/ath/ath10k/sdio.c | 1855 +++++++++++++++++++++++++++
drivers/net/wireless/ath/ath10k/sdio.h | 276 ++++
drivers/net/wireless/ath/ath10k/targaddrs.h | 24 +
12 files changed, 2484 insertions(+), 66 deletions(-)
create mode 100644 drivers/net/wireless/ath/ath10k/sdio.c
create mode 100644 drivers/net/wireless/ath/ath10k/sdio.h
--
1.7.9.5
^ permalink raw reply
* [RFC 01/12] ath10k: htc: made static function public
From: Erik Stromdahl @ 2016-11-14 16:33 UTC (permalink / raw)
To: kvalo, linux-wireless, ath10k; +Cc: Erik Stromdahl
In-Reply-To: <1479141222-8493-1-git-send-email-erik.stromdahl@gmail.com>
Changed ath10k_htc_notify_tx_completion and
ath10k_htc_process_trailer from static to non static.
These functions are needed by SDIO/mbox.
Signed-off-by: Erik Stromdahl <erik.stromdahl@gmail.com>
---
drivers/net/wireless/ath/ath10k/htc.c | 14 ++++++++------
drivers/net/wireless/ath/ath10k/htc.h | 6 ++++++
2 files changed, 14 insertions(+), 6 deletions(-)
diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c
index 175aae3..26b1e15 100644
--- a/drivers/net/wireless/ath/ath10k/htc.c
+++ b/drivers/net/wireless/ath/ath10k/htc.c
@@ -57,8 +57,8 @@ static inline void ath10k_htc_restore_tx_skb(struct ath10k_htc *htc,
skb_pull(skb, sizeof(struct ath10k_htc_hdr));
}
-static void ath10k_htc_notify_tx_completion(struct ath10k_htc_ep *ep,
- struct sk_buff *skb)
+void ath10k_htc_notify_tx_completion(struct ath10k_htc_ep *ep,
+ struct sk_buff *skb)
{
struct ath10k *ar = ep->htc->ar;
@@ -75,6 +75,7 @@ static void ath10k_htc_notify_tx_completion(struct ath10k_htc_ep *ep,
ep->ep_ops.ep_tx_complete(ep->htc->ar, skb);
}
+EXPORT_SYMBOL(ath10k_htc_notify_tx_completion);
static void ath10k_htc_prepare_tx_skb(struct ath10k_htc_ep *ep,
struct sk_buff *skb)
@@ -227,10 +228,10 @@ void ath10k_htc_tx_completion_handler(struct ath10k *ar, struct sk_buff *skb)
spin_unlock_bh(&htc->tx_lock);
}
-static int ath10k_htc_process_trailer(struct ath10k_htc *htc,
- u8 *buffer,
- int length,
- enum ath10k_htc_ep_id src_eid)
+int ath10k_htc_process_trailer(struct ath10k_htc *htc,
+ u8 *buffer,
+ int length,
+ enum ath10k_htc_ep_id src_eid)
{
struct ath10k *ar = htc->ar;
int status = 0;
@@ -291,6 +292,7 @@ static int ath10k_htc_process_trailer(struct ath10k_htc *htc,
return status;
}
+EXPORT_SYMBOL(ath10k_htc_process_trailer);
void ath10k_htc_rx_completion_handler(struct ath10k *ar, struct sk_buff *skb)
{
diff --git a/drivers/net/wireless/ath/ath10k/htc.h b/drivers/net/wireless/ath/ath10k/htc.h
index 0c55cd9..858e19f 100644
--- a/drivers/net/wireless/ath/ath10k/htc.h
+++ b/drivers/net/wireless/ath/ath10k/htc.h
@@ -354,5 +354,11 @@ int ath10k_htc_send(struct ath10k_htc *htc, enum ath10k_htc_ep_id eid,
struct sk_buff *ath10k_htc_alloc_skb(struct ath10k *ar, int size);
void ath10k_htc_tx_completion_handler(struct ath10k *ar, struct sk_buff *skb);
void ath10k_htc_rx_completion_handler(struct ath10k *ar, struct sk_buff *skb);
+void ath10k_htc_notify_tx_completion(struct ath10k_htc_ep *ep,
+ struct sk_buff *skb);
+int ath10k_htc_process_trailer(struct ath10k_htc *htc,
+ u8 *buffer,
+ int length,
+ enum ath10k_htc_ep_id src_eid);
#endif
--
1.7.9.5
^ permalink raw reply related
* [RFC 02/12] ath10k: htc: rx trailer lookahead support
From: Erik Stromdahl @ 2016-11-14 16:33 UTC (permalink / raw)
To: kvalo, linux-wireless, ath10k; +Cc: Erik Stromdahl
In-Reply-To: <1479141222-8493-1-git-send-email-erik.stromdahl@gmail.com>
The RX trailer parsing is now capable of parsing lookahead reports.
This is needed by SDIO/mbox.
Signed-off-by: Erik Stromdahl <erik.stromdahl@gmail.com>
---
drivers/net/wireless/ath/ath10k/htc.c | 91 ++++++++++++++++++++++++++++++++-
drivers/net/wireless/ath/ath10k/htc.h | 30 +++++++++--
2 files changed, 116 insertions(+), 5 deletions(-)
diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c
index 26b1e15..e3f7bf4 100644
--- a/drivers/net/wireless/ath/ath10k/htc.c
+++ b/drivers/net/wireless/ath/ath10k/htc.c
@@ -228,10 +228,74 @@ void ath10k_htc_tx_completion_handler(struct ath10k *ar, struct sk_buff *skb)
spin_unlock_bh(&htc->tx_lock);
}
+static int
+ath10k_htc_process_lookahead(struct ath10k_htc *htc,
+ const struct ath10k_htc_lookahead_report *report,
+ int len,
+ enum ath10k_htc_ep_id eid,
+ u32 *next_lk_ahds,
+ int *next_lk_ahds_len)
+{
+ struct ath10k *ar = htc->ar;
+
+ if (report->pre_valid != ((~report->post_valid) & 0xFF))
+ /* Invalid lookahead flags are actually transmitted by
+ * the target in the HTC control message.
+ * Since this will happen at every boot we silently ignore
+ * the lookahead in this case
+ */
+ return 0;
+
+ if (next_lk_ahds && next_lk_ahds_len) {
+ ath10k_dbg(ar, ATH10K_DBG_HTC,
+ "htc rx lk_ahd found pre_valid 0x%x post_valid 0x%x\n",
+ report->pre_valid, report->post_valid);
+
+ /* look ahead bytes are valid, copy them over */
+ memcpy((u8 *)&next_lk_ahds[0], report->lk_ahd, 4);
+
+ *next_lk_ahds_len = 1;
+ }
+
+ return 0;
+}
+
+static int
+ath10k_htc_process_lookahead_bundle(struct ath10k_htc *htc,
+ const struct ath10k_htc_lookahead_report_bundle *report,
+ int len,
+ enum ath10k_htc_ep_id eid,
+ u32 *next_lk_ahds,
+ int *next_lk_ahds_len)
+{
+ int bundle_cnt = len / sizeof(*report);
+
+ if (!bundle_cnt || (bundle_cnt > HTC_HOST_MAX_MSG_PER_BUNDLE)) {
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
+ if (next_lk_ahds && next_lk_ahds_len) {
+ int i;
+
+ for (i = 0; i < bundle_cnt; i++) {
+ memcpy((u8 *)&next_lk_ahds[i], report->lk_ahd,
+ sizeof(u32));
+ report++;
+ }
+
+ *next_lk_ahds_len = bundle_cnt;
+ }
+
+ return 0;
+}
+
int ath10k_htc_process_trailer(struct ath10k_htc *htc,
u8 *buffer,
int length,
- enum ath10k_htc_ep_id src_eid)
+ enum ath10k_htc_ep_id src_eid,
+ u32 *next_lk_ahds,
+ int *next_lk_ahds_len)
{
struct ath10k *ar = htc->ar;
int status = 0;
@@ -272,6 +336,28 @@ int ath10k_htc_process_trailer(struct ath10k_htc *htc,
record->hdr.len,
src_eid);
break;
+ case ATH10K_HTC_RECORD_LOOKAHEAD:
+ len = sizeof(struct ath10k_htc_lookahead_report);
+ if (record->hdr.len < len) {
+ ath10k_warn(ar, "Lookahead report too long\n");
+ status = -EINVAL;
+ break;
+ }
+ status = ath10k_htc_process_lookahead(htc,
+ record->lkahd_report,
+ record->hdr.len,
+ src_eid,
+ next_lk_ahds,
+ next_lk_ahds_len);
+ break;
+ case ATH10K_HTC_RECORD_LOOKAHEAD_BUNDLE:
+ status = ath10k_htc_process_lookahead_bundle(htc,
+ record->lkahd_bundle,
+ record->hdr.len,
+ src_eid,
+ next_lk_ahds,
+ next_lk_ahds_len);
+ break;
default:
ath10k_warn(ar, "Unhandled record: id:%d length:%d\n",
record->hdr.id, record->hdr.len);
@@ -359,7 +445,8 @@ void ath10k_htc_rx_completion_handler(struct ath10k *ar, struct sk_buff *skb)
trailer += payload_len;
trailer -= trailer_len;
status = ath10k_htc_process_trailer(htc, trailer,
- trailer_len, hdr->eid);
+ trailer_len, hdr->eid,
+ NULL, NULL);
if (status)
goto out;
diff --git a/drivers/net/wireless/ath/ath10k/htc.h b/drivers/net/wireless/ath/ath10k/htc.h
index 858e19f..589800a 100644
--- a/drivers/net/wireless/ath/ath10k/htc.h
+++ b/drivers/net/wireless/ath/ath10k/htc.h
@@ -50,6 +50,8 @@
* 4-byte aligned.
*/
+#define HTC_HOST_MAX_MSG_PER_BUNDLE 8
+
enum ath10k_htc_tx_flags {
ATH10K_HTC_FLAG_NEED_CREDIT_UPDATE = 0x01,
ATH10K_HTC_FLAG_SEND_BUNDLE = 0x02
@@ -174,8 +176,10 @@ struct ath10k_htc_msg {
} __packed __aligned(4);
enum ath10k_ath10k_htc_record_id {
- ATH10K_HTC_RECORD_NULL = 0,
- ATH10K_HTC_RECORD_CREDITS = 1
+ ATH10K_HTC_RECORD_NULL = 0,
+ ATH10K_HTC_RECORD_CREDITS = 1,
+ ATH10K_HTC_RECORD_LOOKAHEAD = 2,
+ ATH10K_HTC_RECORD_LOOKAHEAD_BUNDLE = 3,
};
struct ath10k_ath10k_htc_record_hdr {
@@ -192,10 +196,28 @@ struct ath10k_htc_credit_report {
u8 pad1;
} __packed;
+struct ath10k_htc_lookahead_report {
+ u8 pre_valid;
+ u8 pad0;
+ u8 pad1;
+ u8 pad2;
+ u8 lk_ahd[4];
+ u8 post_valid;
+ u8 pad3;
+ u8 pad4;
+ u8 pad5;
+} __packed;
+
+struct ath10k_htc_lookahead_report_bundle {
+ u8 lk_ahd[4];
+} __packed;
+
struct ath10k_htc_record {
struct ath10k_ath10k_htc_record_hdr hdr;
union {
struct ath10k_htc_credit_report credit_report[0];
+ struct ath10k_htc_lookahead_report lkahd_report[0];
+ struct ath10k_htc_lookahead_report_bundle lkahd_bundle[0];
u8 pauload[0];
};
} __packed __aligned(4);
@@ -359,6 +381,8 @@ void ath10k_htc_notify_tx_completion(struct ath10k_htc_ep *ep,
int ath10k_htc_process_trailer(struct ath10k_htc *htc,
u8 *buffer,
int length,
- enum ath10k_htc_ep_id src_eid);
+ enum ath10k_htc_ep_id src_eid,
+ u32 *next_lk_ahds,
+ int *next_lk_ahds_len);
#endif
--
1.7.9.5
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox