* [PATCH v4 0/2] Add support for new channels on 60GHz band
From: Alexei Avshalom Lazar @ 2019-07-07 14:12 UTC (permalink / raw)
To: Johannes Berg; +Cc: Alexei Avshalom Lazar, linux-wireless, wil6210
The following set of patches add support for new channels on
60GHz band and EDMG channels:
Changelog:
V4:
- Addressed to comments from the community
- Updated comments and variable name
V3:
- Addressed to comments from the community
- Added 60G check for verifying some EDMG cases are relevant
- Used the ieee80211_sta_edmg_cap struct as the edmg channel configuration
- Updated nla_policy to NLA_POLICY_RANGE()
V2
- Addressed to comments from the community
- Align to latest Spec release
Alexei Avshalom Lazar (2):
nl80211: Add support for EDMG channels
wil6210: Add EDMG channel support
drivers/net/wireless/ath/wil6210/cfg80211.c | 205 +++++++++++++++++++++++++--
drivers/net/wireless/ath/wil6210/txrx_edma.c | 2 +
drivers/net/wireless/ath/wil6210/txrx_edma.h | 6 +
drivers/net/wireless/ath/wil6210/wil6210.h | 8 +-
drivers/net/wireless/ath/wil6210/wmi.c | 5 +-
drivers/net/wireless/ath/wil6210/wmi.h | 30 +++-
include/net/cfg80211.h | 37 ++++-
include/uapi/linux/nl80211.h | 22 +++
net/wireless/chan.c | 158 ++++++++++++++++++++-
net/wireless/nl80211.c | 35 +++++
net/wireless/util.c | 42 +++++-
11 files changed, 530 insertions(+), 20 deletions(-)
--
1.9.1
^ permalink raw reply
* [PATCH v4 2/2] wil6210: Add EDMG channel support
From: Alexei Avshalom Lazar @ 2019-07-07 14:12 UTC (permalink / raw)
To: Johannes Berg; +Cc: Alexei Avshalom Lazar, linux-wireless, wil6210
In-Reply-To: <1562508727-17082-1-git-send-email-ailizaro@codeaurora.org>
Add support for Enhanced Directional Multi-Gigabit (EDMG) channels 9-11.
wil6210 reports it's EDMG capabilities (that are also based on FW
capability) to cfg80211 by filling
wiphy->bands[NL80211_BAND_60GHZ]->edmg_cap.
wil6210 handles edmg.channels and edmg.bw_config requested in connect
and start_ap operations.
---
drivers/net/wireless/ath/wil6210/cfg80211.c | 205 +++++++++++++++++++++++++--
drivers/net/wireless/ath/wil6210/txrx_edma.c | 2 +
drivers/net/wireless/ath/wil6210/txrx_edma.h | 6 +
drivers/net/wireless/ath/wil6210/wil6210.h | 8 +-
drivers/net/wireless/ath/wil6210/wmi.c | 5 +-
drivers/net/wireless/ath/wil6210/wmi.h | 30 +++-
6 files changed, 242 insertions(+), 14 deletions(-)
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c
index ce68fbc..a68f148 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -25,6 +25,22 @@
#define WIL_MAX_ROC_DURATION_MS 5000
+#define WIL_EDMG_CHANNEL_9_SUBCHANNELS (BIT(0) | BIT(1))
+#define WIL_EDMG_CHANNEL_10_SUBCHANNELS (BIT(1) | BIT(2))
+#define WIL_EDMG_CHANNEL_11_SUBCHANNELS (BIT(2) | BIT(3))
+
+/* WIL_EDMG_BW_CONFIGURATION define the allowed channel bandwidth
+ * configurations as defined by IEEE 802.11 section 9.4.2.251, Table 13.
+ * The value 5 allowing CB1 and CB2 of adjacent channels.
+ */
+#define WIL_EDMG_BW_CONFIGURATION 5
+
+/* WIL_EDMG_CHANNELS is a bitmap that indicates the 2.16 GHz channel(s) that
+ * are allowed to be used for EDMG transmissions in the BSS as defined by
+ * IEEE 802.11 section 9.4.2.251.
+ */
+#define WIL_EDMG_CHANNELS (BIT(0) | BIT(1) | BIT(2) | BIT(3))
+
bool disable_ap_sme;
module_param(disable_ap_sme, bool, 0444);
MODULE_PARM_DESC(disable_ap_sme, " let user space handle AP mode SME");
@@ -51,6 +67,39 @@
CHAN60G(4, 0),
};
+/* Rx channel bonding mode */
+enum wil_rx_cb_mode {
+ WIL_RX_CB_MODE_DMG,
+ WIL_RX_CB_MODE_EDMG,
+ WIL_RX_CB_MODE_WIDE,
+};
+
+static int wil_rx_cb_mode_to_n_bonded(u8 cb_mode)
+{
+ switch (cb_mode) {
+ case WIL_RX_CB_MODE_DMG:
+ case WIL_RX_CB_MODE_EDMG:
+ return 1;
+ case WIL_RX_CB_MODE_WIDE:
+ return 2;
+ default:
+ return 1;
+ }
+}
+
+static int wil_tx_cb_mode_to_n_bonded(u8 cb_mode)
+{
+ switch (cb_mode) {
+ case WMI_TX_MODE_DMG:
+ case WMI_TX_MODE_EDMG_CB1:
+ return 1;
+ case WMI_TX_MODE_EDMG_CB2:
+ return 2;
+ default:
+ return 1;
+ }
+}
+
static void
wil_memdup_ie(u8 **pdst, size_t *pdst_len, const u8 *src, size_t src_len)
{
@@ -82,6 +131,12 @@ void update_supported_bands(struct wil6210_priv *wil)
wiphy->bands[NL80211_BAND_60GHZ]->n_channels =
wil_num_supported_channels(wil);
+
+ if (test_bit(WMI_FW_CAPABILITY_CHANNEL_BONDING, wil->fw_capabilities))
+ wiphy->bands[NL80211_BAND_60GHZ]->edmg_cap.channels =
+ WIL_EDMG_CHANNELS;
+ wiphy->bands[NL80211_BAND_60GHZ]->edmg_cap.bw_config =
+ WIL_EDMG_BW_CONFIGURATION;
}
/* Vendor id to be used in vendor specific command and events
@@ -296,6 +351,86 @@ int wil_iftype_nl2wmi(enum nl80211_iftype type)
return -EOPNOTSUPP;
}
+int wil_spec2wmi_ch(u8 spec_ch, u8 *wmi_ch)
+{
+ switch (spec_ch) {
+ case 1:
+ *wmi_ch = WMI_CHANNEL_1;
+ break;
+ case 2:
+ *wmi_ch = WMI_CHANNEL_2;
+ break;
+ case 3:
+ *wmi_ch = WMI_CHANNEL_3;
+ break;
+ case 4:
+ *wmi_ch = WMI_CHANNEL_4;
+ break;
+ case 5:
+ *wmi_ch = WMI_CHANNEL_5;
+ break;
+ case 6:
+ *wmi_ch = WMI_CHANNEL_6;
+ break;
+ case 9:
+ *wmi_ch = WMI_CHANNEL_9;
+ break;
+ case 10:
+ *wmi_ch = WMI_CHANNEL_10;
+ break;
+ case 11:
+ *wmi_ch = WMI_CHANNEL_11;
+ break;
+ case 12:
+ *wmi_ch = WMI_CHANNEL_12;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int wil_wmi2spec_ch(u8 wmi_ch, u8 *spec_ch)
+{
+ switch (wmi_ch) {
+ case WMI_CHANNEL_1:
+ *spec_ch = 1;
+ break;
+ case WMI_CHANNEL_2:
+ *spec_ch = 2;
+ break;
+ case WMI_CHANNEL_3:
+ *spec_ch = 3;
+ break;
+ case WMI_CHANNEL_4:
+ *spec_ch = 4;
+ break;
+ case WMI_CHANNEL_5:
+ *spec_ch = 5;
+ break;
+ case WMI_CHANNEL_6:
+ *spec_ch = 6;
+ break;
+ case WMI_CHANNEL_9:
+ *spec_ch = 9;
+ break;
+ case WMI_CHANNEL_10:
+ *spec_ch = 10;
+ break;
+ case WMI_CHANNEL_11:
+ *spec_ch = 11;
+ break;
+ case WMI_CHANNEL_12:
+ *spec_ch = 12;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
int wil_cid_fill_sinfo(struct wil6210_vif *vif, int cid,
struct station_info *sinfo)
{
@@ -310,6 +445,7 @@ int wil_cid_fill_sinfo(struct wil6210_vif *vif, int cid,
} __packed reply;
struct wil_net_stats *stats = &wil->sta[cid].stats;
int rc;
+ u8 txflag = RATE_INFO_FLAGS_DMG;
memset(&reply, 0, sizeof(reply));
@@ -322,7 +458,8 @@ int wil_cid_fill_sinfo(struct wil6210_vif *vif, int cid,
" MCS %d TSF 0x%016llx\n"
" BF status 0x%08x RSSI %d SQI %d%%\n"
" Tx Tpt %d goodput %d Rx goodput %d\n"
- " Sectors(rx:tx) my %d:%d peer %d:%d\n""}\n",
+ " Sectors(rx:tx) my %d:%d peer %d:%d\n"
+ " Tx mode %d}\n",
cid, vif->mid, le16_to_cpu(reply.evt.bf_mcs),
le64_to_cpu(reply.evt.tsf), reply.evt.status,
reply.evt.rssi,
@@ -333,7 +470,8 @@ int wil_cid_fill_sinfo(struct wil6210_vif *vif, int cid,
le16_to_cpu(reply.evt.my_rx_sector),
le16_to_cpu(reply.evt.my_tx_sector),
le16_to_cpu(reply.evt.other_rx_sector),
- le16_to_cpu(reply.evt.other_tx_sector));
+ le16_to_cpu(reply.evt.other_tx_sector),
+ reply.evt.tx_mode);
sinfo->generation = wil->sinfo_gen;
@@ -346,9 +484,16 @@ int wil_cid_fill_sinfo(struct wil6210_vif *vif, int cid,
BIT_ULL(NL80211_STA_INFO_RX_DROP_MISC) |
BIT_ULL(NL80211_STA_INFO_TX_FAILED);
- sinfo->txrate.flags = RATE_INFO_FLAGS_DMG;
+ if (wil->use_enhanced_dma_hw && reply.evt.tx_mode != WMI_TX_MODE_DMG)
+ txflag = RATE_INFO_FLAGS_EDMG;
+
+ sinfo->txrate.flags = txflag;
sinfo->txrate.mcs = le16_to_cpu(reply.evt.bf_mcs);
sinfo->rxrate.mcs = stats->last_mcs_rx;
+ sinfo->txrate.n_bonded_ch =
+ wil_tx_cb_mode_to_n_bonded(reply.evt.tx_mode);
+ sinfo->rxrate.n_bonded_ch =
+ wil_rx_cb_mode_to_n_bonded(stats->last_cb_mode_rx);
sinfo->rx_bytes = stats->rx_bytes;
sinfo->rx_packets = stats->rx_packets;
sinfo->rx_dropped_misc = stats->rx_dropped;
@@ -1006,6 +1151,33 @@ static int wil_ft_connect(struct wiphy *wiphy,
return rc;
}
+static int wil_get_wmi_edmg_channel(struct wil6210_priv *wil, u8 edmg_bw_config,
+ u8 edmg_channels, u8 *wmi_ch)
+{
+ if (!edmg_bw_config) {
+ *wmi_ch = 0;
+ return 0;
+ } else if (edmg_bw_config == WIL_EDMG_BW_CONFIGURATION) {
+ /* convert from edmg channel bitmap into edmg channel number */
+ switch (edmg_channels) {
+ case WIL_EDMG_CHANNEL_9_SUBCHANNELS:
+ return wil_spec2wmi_ch(9, wmi_ch);
+ case WIL_EDMG_CHANNEL_10_SUBCHANNELS:
+ return wil_spec2wmi_ch(10, wmi_ch);
+ case WIL_EDMG_CHANNEL_11_SUBCHANNELS:
+ return wil_spec2wmi_ch(11, wmi_ch);
+ default:
+ wil_err(wil, "Unsupported edmg channel bitmap 0x%x\n",
+ edmg_channels);
+ return -EINVAL;
+ }
+ } else {
+ wil_err(wil, "Unsupported EDMG BW configuration %d\n",
+ edmg_bw_config);
+ return -EINVAL;
+ }
+}
+
static int wil_cfg80211_connect(struct wiphy *wiphy,
struct net_device *ndev,
struct cfg80211_connect_params *sme)
@@ -1151,6 +1323,11 @@ static int wil_cfg80211_connect(struct wiphy *wiphy,
memcpy(conn.ssid, ssid_eid+2, conn.ssid_len);
conn.channel = ch - 1;
+ rc = wil_get_wmi_edmg_channel(wil, sme->edmg.bw_config,
+ sme->edmg.channels, &conn.edmg_channel);
+ if (rc < 0)
+ return rc;
+
ether_addr_copy(conn.bssid, bss->bssid);
ether_addr_copy(conn.dst_mac, bss->bssid);
@@ -1707,7 +1884,7 @@ static int _wil_cfg80211_set_ies(struct wil6210_vif *vif,
static int _wil_cfg80211_start_ap(struct wiphy *wiphy,
struct net_device *ndev,
const u8 *ssid, size_t ssid_len, u32 privacy,
- int bi, u8 chan,
+ int bi, u8 chan, u8 wmi_edmg_channel,
struct cfg80211_beacon_data *bcon,
u8 hidden_ssid, u32 pbss)
{
@@ -1770,6 +1947,7 @@ static int _wil_cfg80211_start_ap(struct wiphy *wiphy,
vif->privacy = privacy;
vif->channel = chan;
+ vif->wmi_edmg_channel = wmi_edmg_channel;
vif->hidden_ssid = hidden_ssid;
vif->pbss = pbss;
vif->bi = bi;
@@ -1780,7 +1958,8 @@ static int _wil_cfg80211_start_ap(struct wiphy *wiphy,
if (!wil_has_other_active_ifaces(wil, ndev, false, true))
wil6210_bus_request(wil, WIL_MAX_BUS_REQUEST_KBPS);
- rc = wmi_pcp_start(vif, bi, wmi_nettype, chan, hidden_ssid, is_go);
+ rc = wmi_pcp_start(vif, bi, wmi_nettype, chan, wmi_edmg_channel,
+ hidden_ssid, is_go);
if (rc)
goto err_pcp_start;
@@ -1832,7 +2011,8 @@ void wil_cfg80211_ap_recovery(struct wil6210_priv *wil)
rc = _wil_cfg80211_start_ap(wiphy, ndev,
vif->ssid, vif->ssid_len,
vif->privacy, vif->bi,
- vif->channel, &bcon,
+ vif->channel,
+ vif->wmi_edmg_channel, &bcon,
vif->hidden_ssid, vif->pbss);
if (rc) {
wil_err(wil, "vif %d recovery failed (%d)\n", i, rc);
@@ -1882,7 +2062,8 @@ static int wil_cfg80211_change_beacon(struct wiphy *wiphy,
rc = _wil_cfg80211_start_ap(wiphy, ndev, vif->ssid,
vif->ssid_len, privacy,
wdev->beacon_interval,
- vif->channel, bcon,
+ vif->channel,
+ vif->wmi_edmg_channel, bcon,
vif->hidden_ssid,
vif->pbss);
} else {
@@ -1901,10 +2082,17 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy,
struct ieee80211_channel *channel = info->chandef.chan;
struct cfg80211_beacon_data *bcon = &info->beacon;
struct cfg80211_crypto_settings *crypto = &info->crypto;
+ u8 wmi_edmg_channel;
u8 hidden_ssid;
wil_dbg_misc(wil, "start_ap\n");
+ rc = wil_get_wmi_edmg_channel(wil, info->chandef.edmg.bw_config,
+ info->chandef.edmg.channels,
+ &wmi_edmg_channel);
+ if (rc < 0)
+ return rc;
+
if (!channel) {
wil_err(wil, "AP: No channel???\n");
return -EINVAL;
@@ -1944,7 +2132,8 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy,
rc = _wil_cfg80211_start_ap(wiphy, ndev,
info->ssid, info->ssid_len, info->privacy,
info->beacon_interval, channel->hw_value,
- bcon, hidden_ssid, info->pbss);
+ wmi_edmg_channel, bcon, hidden_ssid,
+ info->pbss);
return rc;
}
diff --git a/drivers/net/wireless/ath/wil6210/txrx_edma.c b/drivers/net/wireless/ath/wil6210/txrx_edma.c
index c387738..0c9bb2c 100644
--- a/drivers/net/wireless/ath/wil6210/txrx_edma.c
+++ b/drivers/net/wireless/ath/wil6210/txrx_edma.c
@@ -1006,6 +1006,8 @@ static struct sk_buff *wil_sring_reap_rx_edma(struct wil6210_priv *wil,
stats->rx_per_mcs[stats->last_mcs_rx]++;
}
+ stats->last_cb_mode_rx = wil_rx_status_get_cb_mode(msg);
+
if (!wil->use_rx_hw_reordering && !wil->use_compressed_rx_status &&
wil_check_bar(wil, msg, cid, skb, stats) == -EAGAIN) {
kfree_skb(skb);
diff --git a/drivers/net/wireless/ath/wil6210/txrx_edma.h b/drivers/net/wireless/ath/wil6210/txrx_edma.h
index 343516a..2680ffc 100644
--- a/drivers/net/wireless/ath/wil6210/txrx_edma.h
+++ b/drivers/net/wireless/ath/wil6210/txrx_edma.h
@@ -366,6 +366,12 @@ static inline u8 wil_rx_status_get_mcs(void *msg)
16, 21);
}
+static inline u8 wil_rx_status_get_cb_mode(void *msg)
+{
+ return WIL_GET_BITS(((struct wil_rx_status_compressed *)msg)->d1,
+ 22, 23);
+}
+
static inline u16 wil_rx_status_get_flow_id(void *msg)
{
return WIL_GET_BITS(((struct wil_rx_status_compressed *)msg)->d0,
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
index e1b1039b..d32c0bf 100644
--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -590,6 +590,7 @@ struct wil_net_stats {
unsigned long rx_amsdu_error; /* eDMA specific */
unsigned long rx_csum_err;
u16 last_mcs_rx;
+ u8 last_cb_mode_rx;
u64 rx_per_mcs[WIL_MCS_MAX + 1];
u32 ft_roams; /* relevant in STA mode */
};
@@ -851,6 +852,7 @@ struct wil6210_vif {
DECLARE_BITMAP(status, wil_vif_status_last);
u32 privacy; /* secure connection? */
u16 channel; /* relevant in AP mode */
+ u8 wmi_edmg_channel; /* relevant in AP mode */
u8 hidden_ssid; /* relevant in AP mode */
u32 ap_isolate; /* no intra-BSS communication */
bool pbss;
@@ -1313,7 +1315,7 @@ int wil_cid_fill_sinfo(struct wil6210_vif *vif, int cid,
int wmi_set_mac_address(struct wil6210_priv *wil, void *addr);
int wmi_pcp_start(struct wil6210_vif *vif, int bi, u8 wmi_nettype, u8 chan,
- u8 hidden_ssid, u8 is_go);
+ u8 edmg_chan, u8 hidden_ssid, u8 is_go);
int wmi_pcp_stop(struct wil6210_vif *vif);
int wmi_led_cfg(struct wil6210_priv *wil, bool enable);
int wmi_abort_scan(struct wil6210_vif *vif);
@@ -1389,6 +1391,10 @@ int wmi_start_sched_scan(struct wil6210_priv *wil,
int wmi_mgmt_tx_ext(struct wil6210_vif *vif, const u8 *buf, size_t len,
u8 channel, u16 duration_ms);
+int wil_wmi2spec_ch(u8 wmi_ch, u8 *spec_ch);
+int wil_spec2wmi_ch(u8 spec_ch, u8 *wmi_ch);
+void wil_update_supported_bands(struct wil6210_priv *wil);
+
int reverse_memcmp(const void *cs, const void *ct, size_t count);
/* WMI for enhanced DMA */
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c
index bda4a97..fe8530d 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.c
+++ b/drivers/net/wireless/ath/wil6210/wmi.c
@@ -2123,8 +2123,8 @@ int wmi_led_cfg(struct wil6210_priv *wil, bool enable)
return rc;
}
-int wmi_pcp_start(struct wil6210_vif *vif,
- int bi, u8 wmi_nettype, u8 chan, u8 hidden_ssid, u8 is_go)
+int wmi_pcp_start(struct wil6210_vif *vif, int bi, u8 wmi_nettype,
+ u8 chan, u8 wmi_edmg_chan, u8 hidden_ssid, u8 is_go)
{
struct wil6210_priv *wil = vif_to_wil(vif);
int rc;
@@ -2134,6 +2134,7 @@ int wmi_pcp_start(struct wil6210_vif *vif,
.network_type = wmi_nettype,
.disable_sec_offload = 1,
.channel = chan - 1,
+ .edmg_channel = wmi_edmg_chan,
.pcp_max_assoc_sta = max_assoc_sta,
.hidden_ssid = hidden_ssid,
.is_go = is_go,
diff --git a/drivers/net/wireless/ath/wil6210/wmi.h b/drivers/net/wireless/ath/wil6210/wmi.h
index b668758..1b39aeb 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.h
+++ b/drivers/net/wireless/ath/wil6210/wmi.h
@@ -95,6 +95,7 @@ enum wmi_fw_capability {
WMI_FW_CAPABILITY_SET_SILENT_RSSI_TABLE = 13,
WMI_FW_CAPABILITY_LO_POWER_CALIB_FROM_OTP = 14,
WMI_FW_CAPABILITY_PNO = 15,
+ WMI_FW_CAPABILITY_CHANNEL_BONDING = 17,
WMI_FW_CAPABILITY_REF_CLOCK_CONTROL = 18,
WMI_FW_CAPABILITY_AP_SME_OFFLOAD_NONE = 19,
WMI_FW_CAPABILITY_MULTI_VIFS = 20,
@@ -355,6 +356,19 @@ enum wmi_connect_ctrl_flag_bits {
#define WMI_MAX_SSID_LEN (32)
+enum wmi_channel {
+ WMI_CHANNEL_1 = 0x00,
+ WMI_CHANNEL_2 = 0x01,
+ WMI_CHANNEL_3 = 0x02,
+ WMI_CHANNEL_4 = 0x03,
+ WMI_CHANNEL_5 = 0x04,
+ WMI_CHANNEL_6 = 0x05,
+ WMI_CHANNEL_9 = 0x06,
+ WMI_CHANNEL_10 = 0x07,
+ WMI_CHANNEL_11 = 0x08,
+ WMI_CHANNEL_12 = 0x09,
+};
+
/* WMI_CONNECT_CMDID */
struct wmi_connect_cmd {
u8 network_type;
@@ -366,8 +380,12 @@ struct wmi_connect_cmd {
u8 group_crypto_len;
u8 ssid_len;
u8 ssid[WMI_MAX_SSID_LEN];
+ /* enum wmi_channel WMI_CHANNEL_1..WMI_CHANNEL_6; for EDMG this is
+ * the primary channel number
+ */
u8 channel;
- u8 reserved0;
+ /* enum wmi_channel WMI_CHANNEL_9..WMI_CHANNEL_12 */
+ u8 edmg_channel;
u8 bssid[WMI_MAC_LEN];
__le32 ctrl_flags;
u8 dst_mac[WMI_MAC_LEN];
@@ -2267,7 +2285,9 @@ struct wmi_notify_req_done_event {
__le32 status;
__le64 tsf;
s8 rssi;
- u8 reserved0[3];
+ /* enum wmi_edmg_tx_mode */
+ u8 tx_mode;
+ u8 reserved0[2];
__le32 tx_tpt;
__le32 tx_goodput;
__le32 rx_goodput;
@@ -2283,8 +2303,12 @@ struct wmi_notify_req_done_event {
/* WMI_CONNECT_EVENTID */
struct wmi_connect_event {
+ /* enum wmi_channel WMI_CHANNEL_1..WMI_CHANNEL_6; for EDMG this is
+ * the primary channel number
+ */
u8 channel;
- u8 reserved0;
+ /* enum wmi_channel WMI_CHANNEL_9..WMI_CHANNEL_12 */
+ u8 edmg_channel;
u8 bssid[WMI_MAC_LEN];
__le16 listen_interval;
__le16 beacon_interval;
--
1.9.1
^ permalink raw reply related
* [PATCH v4 1/2] nl80211: Add support for EDMG channels
From: Alexei Avshalom Lazar @ 2019-07-07 14:12 UTC (permalink / raw)
To: Johannes Berg; +Cc: Alexei Avshalom Lazar, linux-wireless, wil6210
In-Reply-To: <1562508727-17082-1-git-send-email-ailizaro@codeaurora.org>
802.11ay specification defines Enhanced Directional Multi-Gigabit
(EDMG) STA and AP which allow channel bonding of 2 channels and more.
Introduce NL80211_ATTR_WIPHY_EDMG_CHANNELS,
NL80211_ATTR_WIPHY_EDMG_BW_CONFIG, NL80211_BAND_ATTR_EDMG_CHANNELS,
NL80211_BAND_ATTR_EDMG_BW_CONFIG and RATE_INFO_FLAGS_EDMG
that needed for enabling and configuring EDMG support.
Driver is expected to report its EDMG capabilities: whether EDMG
is supported and the supported EDMG channels.
Bitrate calculation is enhanced to take into account EDMG support
according to the 802.11ay specification.
The kernel uses NL80211_BAND_ATTR_EDMG_CHANNELS and
NL80211_BAND_ATTR_EDMG_BW_CONFIG attributes in order to publish
the EDMG capabilities to the userspace.
NL80211_BAND_ATTR_EDMG_CHANNELS is a bitmap field that indicates
the 2.16 GHz channel(s) that are allowed to be used.
If NL80211_BAND_ATTR_EDMG_CHANNELS is not set then EDMG not
supported. NL80211_BAND_ATTR_EDMG_BW_CONFIG represent the allowed
channel bandwidth configurations.
NL80211_ATTR_WIPHY_EDMG_CHANNELS and NL80211_ATTR_WIPHY_EDMG_BW_CONFIG
will be used by the userspace for AP configuration and connect command.
---
drivers/net/wireless/ath/wil6210/cfg80211.c | 2 +-
include/net/cfg80211.h | 37 ++++++-
include/uapi/linux/nl80211.h | 22 ++++
net/wireless/chan.c | 158 +++++++++++++++++++++++++++-
net/wireless/nl80211.c | 35 ++++++
net/wireless/util.c | 42 +++++++-
6 files changed, 289 insertions(+), 7 deletions(-)
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c
index a1e226652..ce68fbc 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -346,7 +346,7 @@ int wil_cid_fill_sinfo(struct wil6210_vif *vif, int cid,
BIT_ULL(NL80211_STA_INFO_RX_DROP_MISC) |
BIT_ULL(NL80211_STA_INFO_TX_FAILED);
- sinfo->txrate.flags = RATE_INFO_FLAGS_60G;
+ sinfo->txrate.flags = RATE_INFO_FLAGS_DMG;
sinfo->txrate.mcs = le16_to_cpu(reply.evt.bf_mcs);
sinfo->rxrate.mcs = stats->last_mcs_rx;
sinfo->rx_bytes = stats->rx_bytes;
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 117691f..98f663e 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -321,6 +321,24 @@ struct ieee80211_sband_iftype_data {
};
/**
+ * struct ieee80211_edmg - EDMG configuration
+ *
+ * This structure describes most essential parameters needed
+ * to describe 802.11ay EDMG configuration
+ *
+ * @channels: bitmap that indicates the 2.16 GHz channel(s)
+ * that are allowed to be used for transmissions.
+ * Bit 0 indicates channel 1, bit 1 indicates channel 2, etc.
+ * Set to 0 indicate EDMG not supported.
+ * @bw_config: Channel BW Configuration subfield encodes
+ * the allowed channel bandwidth configurations
+ */
+struct ieee80211_edmg {
+ u8 channels;
+ u8 bw_config;
+};
+
+/**
* struct ieee80211_supported_band - frequency band definition
*
* This structure describes a frequency band a wiphy
@@ -336,6 +354,7 @@ struct ieee80211_sband_iftype_data {
* @n_bitrates: Number of bitrates in @bitrates
* @ht_cap: HT capabilities in this band
* @vht_cap: VHT capabilities in this band
+ * @edmg_cap: EDMG capabilities in this band
* @n_iftype_data: number of iftype data entries
* @iftype_data: interface type data entries. Note that the bits in
* @types_mask inside this structure cannot overlap (i.e. only
@@ -350,6 +369,7 @@ struct ieee80211_supported_band {
int n_bitrates;
struct ieee80211_sta_ht_cap ht_cap;
struct ieee80211_sta_vht_cap vht_cap;
+ struct ieee80211_edmg edmg_cap;
u16 n_iftype_data;
const struct ieee80211_sband_iftype_data *iftype_data;
};
@@ -503,12 +523,17 @@ struct key_params {
* @center_freq1: center frequency of first segment
* @center_freq2: center frequency of second segment
* (only with 80+80 MHz)
+ * @edmg: define the EDMG channels configuration.
+ * If edmg is requested (i.e. the .channels member is non-zero),
+ * chan will define the primary channel and all other
+ * parameters are ignored.
*/
struct cfg80211_chan_def {
struct ieee80211_channel *chan;
enum nl80211_chan_width width;
u32 center_freq1;
u32 center_freq2;
+ struct ieee80211_edmg edmg;
};
/**
@@ -1144,15 +1169,17 @@ int cfg80211_check_station_change(struct wiphy *wiphy,
* @RATE_INFO_FLAGS_MCS: mcs field filled with HT MCS
* @RATE_INFO_FLAGS_VHT_MCS: mcs field filled with VHT MCS
* @RATE_INFO_FLAGS_SHORT_GI: 400ns guard interval
- * @RATE_INFO_FLAGS_60G: 60GHz MCS
+ * @RATE_INFO_FLAGS_DMG: 60GHz MCS
* @RATE_INFO_FLAGS_HE_MCS: HE MCS information
+ * @RATE_INFO_FLAGS_EDMG: 60GHz MCS in EDMG mode
*/
enum rate_info_flags {
RATE_INFO_FLAGS_MCS = BIT(0),
RATE_INFO_FLAGS_VHT_MCS = BIT(1),
RATE_INFO_FLAGS_SHORT_GI = BIT(2),
- RATE_INFO_FLAGS_60G = BIT(3),
+ RATE_INFO_FLAGS_DMG = BIT(3),
RATE_INFO_FLAGS_HE_MCS = BIT(4),
+ RATE_INFO_FLAGS_EDMG = BIT(5),
};
/**
@@ -1192,6 +1219,7 @@ enum rate_info_bw {
* @he_dcm: HE DCM value
* @he_ru_alloc: HE RU allocation (from &enum nl80211_he_ru_alloc,
* only valid if bw is %RATE_INFO_BW_HE_RU)
+ * @n_bonded_ch: In case of EDMG the number of bonded channels (1-4)
*/
struct rate_info {
u8 flags;
@@ -1202,6 +1230,7 @@ struct rate_info {
u8 he_gi;
u8 he_dcm;
u8 he_ru_alloc;
+ u8 n_bonded_ch;
};
/**
@@ -2403,6 +2432,9 @@ struct cfg80211_bss_selection {
* @fils_erp_rrk_len: Length of @fils_erp_rrk in octets.
* @want_1x: indicates user-space supports and wants to use 802.1X driver
* offload of 4-way handshake.
+ * @edmg: define the EDMG channels.
+ * This may specify multiple channels and bonding options for the driver
+ * to choose from, based on BSS configuration.
*/
struct cfg80211_connect_params {
struct ieee80211_channel *channel;
@@ -2436,6 +2468,7 @@ struct cfg80211_connect_params {
const u8 *fils_erp_rrk;
size_t fils_erp_rrk_len;
bool want_1x;
+ struct ieee80211_edmg edmg;
};
/**
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 25f70dd..106381c 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -52,6 +52,9 @@
#define NL80211_MULTICAST_GROUP_NAN "nan"
#define NL80211_MULTICAST_GROUP_TESTMODE "testmode"
+#define NL80211_EDMG_BW_CONFIG_MIN 4
+#define NL80211_EDMG_BW_CONFIG_MAX 15
+
/**
* DOC: Station handling
*
@@ -2324,6 +2327,13 @@ enum nl80211_commands {
* should be picking up the lowest tx power, either tx power per-interface
* or per-station.
*
+ * @NL80211_ATTR_WIPHY_EDMG_CHANNELS: bitmap that indicates the 2.16 GHz
+ * channel(s) that are allowed to be used for EDMG transmissions.
+ * Defined by IEEE P802.11ay/D4.0 section 9.4.2.251.
+ * @NL80211_ATTR_WIPHY_EDMG_BW_CONFIG: Channel BW Configuration subfield encodes
+ * the allowed channel bandwidth configurations.
+ * Defined by IEEE P802.11ay/D4.0 section 9.4.2.251, Table 13.
+ *
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
@@ -2777,6 +2787,9 @@ enum nl80211_attrs {
NL80211_ATTR_STA_TX_POWER_SETTING,
NL80211_ATTR_STA_TX_POWER,
+ NL80211_ATTR_WIPHY_EDMG_CHANNELS,
+ NL80211_ATTR_WIPHY_EDMG_BW_CONFIG,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
@@ -3385,6 +3398,12 @@ enum nl80211_band_iftype_attr {
* @NL80211_BAND_ATTR_VHT_CAPA: VHT capabilities, as in the HT information IE
* @NL80211_BAND_ATTR_IFTYPE_DATA: nested array attribute, with each entry using
* attributes from &enum nl80211_band_iftype_attr
+ * @NL80211_BAND_ATTR_EDMG_CHANNELS: bitmap that indicates the 2.16 GHz
+ * channel(s) that are allowed to be used for EDMG transmissions.
+ * Defined by IEEE P802.11ay/D4.0 section 9.4.2.251.
+ * @NL80211_BAND_ATTR_EDMG_BW_CONFIG: Channel BW Configuration subfield encodes
+ * the allowed channel bandwidth configurations.
+ * Defined by IEEE P802.11ay/D4.0 section 9.4.2.251, Table 13.
* @NL80211_BAND_ATTR_MAX: highest band attribute currently defined
* @__NL80211_BAND_ATTR_AFTER_LAST: internal use
*/
@@ -3402,6 +3421,9 @@ enum nl80211_band_attr {
NL80211_BAND_ATTR_VHT_CAPA,
NL80211_BAND_ATTR_IFTYPE_DATA,
+ NL80211_BAND_ATTR_EDMG_CHANNELS,
+ NL80211_BAND_ATTR_EDMG_BW_CONFIG,
+
/* keep last */
__NL80211_BAND_ATTR_AFTER_LAST,
NL80211_BAND_ATTR_MAX = __NL80211_BAND_ATTR_AFTER_LAST - 1
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index 7dc1bbd..0e6d3c3 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -14,6 +14,11 @@
#include "core.h"
#include "rdev-ops.h"
+static bool cfg80211_valid_60g_freq(u32 freq)
+{
+ return (freq >= 58320 && freq <= 70200);
+}
+
void cfg80211_chandef_create(struct cfg80211_chan_def *chandef,
struct ieee80211_channel *chan,
enum nl80211_channel_type chan_type)
@@ -23,6 +28,8 @@ void cfg80211_chandef_create(struct cfg80211_chan_def *chandef,
chandef->chan = chan;
chandef->center_freq2 = 0;
+ chandef->edmg.bw_config = 0;
+ chandef->edmg.channels = 0;
switch (chan_type) {
case NL80211_CHAN_NO_HT:
@@ -47,6 +54,93 @@ void cfg80211_chandef_create(struct cfg80211_chan_def *chandef,
}
EXPORT_SYMBOL(cfg80211_chandef_create);
+static bool cfg80211_edmg_chandef_valid(const struct cfg80211_chan_def *chandef)
+{
+ int max_contiguous = 0;
+ int num_of_enabled = 0;
+ int contiguous = 0;
+ int i;
+
+ if (!chandef->edmg.channels && !chandef->edmg.bw_config)
+ return true;
+
+ if ((!chandef->edmg.channels && chandef->edmg.bw_config) ||
+ (chandef->edmg.channels && !chandef->edmg.bw_config) ||
+ !cfg80211_valid_60g_freq(chandef->chan->center_freq))
+ return false;
+
+ for (i = 0; i < 6; i++) {
+ if (chandef->edmg.channels & BIT(i)) {
+ contiguous++;
+ num_of_enabled++;
+ } else {
+ contiguous = 0;
+ }
+
+ max_contiguous = max(contiguous, max_contiguous);
+ }
+ /* basic verification of edmg configuration according to
+ * IEEE P802.11ay/D4.0 section 9.4.2.251
+ */
+ /* check bw_config against contiguous edmg channels */
+ switch (chandef->edmg.bw_config) {
+ case 4:
+ case 8:
+ case 12:
+ if (max_contiguous < 1)
+ return false;
+ break;
+ case 5:
+ case 9:
+ case 13:
+ if (max_contiguous < 2)
+ return false;
+ break;
+ case 6:
+ case 10:
+ case 14:
+ if (max_contiguous < 3)
+ return false;
+ break;
+ case 7:
+ case 11:
+ case 15:
+ if (max_contiguous < 4)
+ return false;
+ break;
+
+ default:
+ return false;
+ }
+
+ /* check bw_config against aggregated (non contiguous) edmg channels */
+ switch (chandef->edmg.bw_config) {
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ break;
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ if (num_of_enabled < 2)
+ return false;
+ break;
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ if (num_of_enabled < 4 || max_contiguous < 2)
+ return false;
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef)
{
u32 control_freq;
@@ -112,7 +206,7 @@ bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef)
return false;
}
- return true;
+ return cfg80211_edmg_chandef_valid(chandef);
}
EXPORT_SYMBOL(cfg80211_chandef_valid);
@@ -721,12 +815,65 @@ static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
return true;
}
+/* check if the operating channels are valid and supported */
+static bool cfg80211_edmg_usable(struct wiphy *wiphy, u8 edmg_channels,
+ u8 edmg_bw_config, int primary_channel,
+ struct ieee80211_edmg *edmg_cap)
+{
+ struct ieee80211_channel *chan;
+ int i, freq;
+ int channels_counter = 0;
+
+ if (!edmg_channels && !edmg_bw_config)
+ return true;
+
+ if ((!edmg_channels && edmg_bw_config) ||
+ (edmg_channels && !edmg_bw_config))
+ return false;
+
+ if (!(edmg_channels & BIT(primary_channel - 1)))
+ return false;
+
+ /* 60GHz channels 1..6 */
+ for (i = 0; i < 6; i++) {
+ if (!(edmg_channels & BIT(i)))
+ continue;
+
+ if (!(edmg_cap->channels & BIT(i)))
+ return false;
+
+ channels_counter++;
+
+ freq = ieee80211_channel_to_frequency(i + 1,
+ NL80211_BAND_60GHZ);
+ chan = ieee80211_get_channel(wiphy, freq);
+ if (!chan || chan->flags & IEEE80211_CHAN_DISABLED)
+ return false;
+ }
+
+ /* IEEE802.11 allows max 4 channels */
+ if (channels_counter > 4)
+ return false;
+
+ /* check bw_config is a subset of what driver supports
+ * (see IEEE P802.11ay/D4.0 section 9.4.2.251, Table 13)
+ */
+ if ((edmg_bw_config % 4) > (edmg_cap->bw_config % 4))
+ return false;
+
+ if (edmg_bw_config > edmg_cap->bw_config)
+ return false;
+
+ return true;
+}
+
bool cfg80211_chandef_usable(struct wiphy *wiphy,
const struct cfg80211_chan_def *chandef,
u32 prohibited_flags)
{
struct ieee80211_sta_ht_cap *ht_cap;
struct ieee80211_sta_vht_cap *vht_cap;
+ struct ieee80211_edmg *edmg_cap;
u32 width, control_freq, cap;
if (WARN_ON(!cfg80211_chandef_valid(chandef)))
@@ -734,6 +881,15 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
ht_cap = &wiphy->bands[chandef->chan->band]->ht_cap;
vht_cap = &wiphy->bands[chandef->chan->band]->vht_cap;
+ edmg_cap = &wiphy->bands[chandef->chan->band]->edmg_cap;
+
+ if (edmg_cap->channels &&
+ !cfg80211_edmg_usable(wiphy,
+ chandef->edmg.channels,
+ chandef->edmg.bw_config,
+ chandef->chan->hw_value,
+ edmg_cap))
+ return false;
control_freq = chandef->chan->center_freq;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index da3843a..ce6dc73 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -288,6 +288,11 @@ static int validate_ie_attr(const struct nlattr *attr,
[NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 },
[NL80211_ATTR_WIPHY_CHANNEL_TYPE] = { .type = NLA_U32 },
+ [NL80211_ATTR_WIPHY_EDMG_CHANNELS] = { .type = NLA_U8 },
+ [NL80211_ATTR_WIPHY_EDMG_BW_CONFIG] = NLA_POLICY_RANGE(NLA_U8,
+ NL80211_EDMG_BW_CONFIG_MIN,
+ NL80211_EDMG_BW_CONFIG_MAX),
+
[NL80211_ATTR_CHANNEL_WIDTH] = { .type = NLA_U32 },
[NL80211_ATTR_CENTER_FREQ1] = { .type = NLA_U32 },
[NL80211_ATTR_CENTER_FREQ2] = { .type = NLA_U32 },
@@ -1501,6 +1506,15 @@ static int nl80211_send_band_rateinfo(struct sk_buff *msg,
nla_nest_end(msg, nl_iftype_data);
}
+ /* add EDMG info */
+ if (sband->edmg_cap.channels &&
+ (nla_put_u8(msg, NL80211_BAND_ATTR_EDMG_CHANNELS,
+ sband->edmg_cap.channels) ||
+ nla_put_u8(msg, NL80211_BAND_ATTR_EDMG_BW_CONFIG,
+ sband->edmg_cap.bw_config)))
+
+ return -ENOBUFS;
+
/* add bitrates */
nl_rates = nla_nest_start(msg, NL80211_BAND_ATTR_RATES);
if (!nl_rates)
@@ -2560,6 +2574,18 @@ int nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ2]);
}
+ if (info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]) {
+ chandef->edmg.channels =
+ nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]);
+
+ if (info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG])
+ chandef->edmg.bw_config =
+ nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG]);
+ } else {
+ chandef->edmg.bw_config = 0;
+ chandef->edmg.channels = 0;
+ }
+
if (!cfg80211_chandef_valid(chandef)) {
NL_SET_ERR_MSG(extack, "invalid channel definition");
return -EINVAL;
@@ -9699,6 +9725,15 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
return -EINVAL;
}
+ if (info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]) {
+ connect.edmg.channels =
+ nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]);
+
+ if (info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG])
+ connect.edmg.bw_config =
+ nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG]);
+ }
+
if (connect.privacy && info->attrs[NL80211_ATTR_KEYS]) {
connkeys = nl80211_parse_connkeys(rdev, info, NULL);
if (IS_ERR(connkeys))
diff --git a/net/wireless/util.c b/net/wireless/util.c
index cf63b63..7d06dd6 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -1034,7 +1034,7 @@ static u32 cfg80211_calculate_bitrate_ht(struct rate_info *rate)
return (bitrate + 50000) / 100000;
}
-static u32 cfg80211_calculate_bitrate_60g(struct rate_info *rate)
+static u32 cfg80211_calculate_bitrate_dmg(struct rate_info *rate)
{
static const u32 __mcs2bitrate[] = {
/* control PHY */
@@ -1081,6 +1081,40 @@ static u32 cfg80211_calculate_bitrate_60g(struct rate_info *rate)
return __mcs2bitrate[rate->mcs];
}
+static u32 cfg80211_calculate_bitrate_edmg(struct rate_info *rate)
+{
+ static const u32 __mcs2bitrate[] = {
+ /* control PHY */
+ [0] = 275,
+ /* SC PHY */
+ [1] = 3850,
+ [2] = 7700,
+ [3] = 9625,
+ [4] = 11550,
+ [5] = 12512, /* 1251.25 mbps */
+ [6] = 13475,
+ [7] = 15400,
+ [8] = 19250,
+ [9] = 23100,
+ [10] = 25025,
+ [11] = 26950,
+ [12] = 30800,
+ [13] = 38500,
+ [14] = 46200,
+ [15] = 50050,
+ [16] = 53900,
+ [17] = 57750,
+ [18] = 69300,
+ [19] = 75075,
+ [20] = 80850,
+ };
+
+ if (WARN_ON_ONCE(rate->mcs >= ARRAY_SIZE(__mcs2bitrate)))
+ return 0;
+
+ return __mcs2bitrate[rate->mcs] * rate->n_bonded_ch;
+}
+
static u32 cfg80211_calculate_bitrate_vht(struct rate_info *rate)
{
static const u32 base[4][10] = {
@@ -1253,8 +1287,10 @@ u32 cfg80211_calculate_bitrate(struct rate_info *rate)
{
if (rate->flags & RATE_INFO_FLAGS_MCS)
return cfg80211_calculate_bitrate_ht(rate);
- if (rate->flags & RATE_INFO_FLAGS_60G)
- return cfg80211_calculate_bitrate_60g(rate);
+ if (rate->flags & RATE_INFO_FLAGS_DMG)
+ return cfg80211_calculate_bitrate_dmg(rate);
+ if (rate->flags & RATE_INFO_FLAGS_EDMG)
+ return cfg80211_calculate_bitrate_edmg(rate);
if (rate->flags & RATE_INFO_FLAGS_VHT_MCS)
return cfg80211_calculate_bitrate_vht(rate);
if (rate->flags & RATE_INFO_FLAGS_HE_MCS)
--
1.9.1
^ permalink raw reply related
* [PATCH] rtw88/pci: Rearrange the memory usage for skb in RX ISR
From: Jian-Hong Pan @ 2019-07-08 6:32 UTC (permalink / raw)
To: Yan-Hsuan Chuang, Kalle Valo, David S . Miller
Cc: linux-wireless, netdev, linux-kernel, linux, Jian-Hong Pan,
Daniel Drake, stable
Testing with RTL8822BE hardware, when available memory is low, we
frequently see a kernel panic and system freeze.
First, rtw_pci_rx_isr encounters a memory allocation failure (trimmed):
rx routine starvation
WARNING: CPU: 7 PID: 9871 at drivers/net/wireless/realtek/rtw88/pci.c:822 rtw_pci_rx_isr.constprop.25+0x35a/0x370 [rtwpci]
[ 2356.580313] RIP: 0010:rtw_pci_rx_isr.constprop.25+0x35a/0x370 [rtwpci]
Then we see a variety of different error conditions and kernel panics,
such as this one (trimmed):
rtw_pci 0000:02:00.0: pci bus timeout, check dma status
skbuff: skb_over_panic: text:00000000091b6e66 len:415 put:415 head:00000000d2880c6f data:000000007a02b1ea tail:0x1df end:0xc0 dev:<NULL>
------------[ cut here ]------------
kernel BUG at net/core/skbuff.c:105!
invalid opcode: 0000 [#1] SMP NOPTI
RIP: 0010:skb_panic+0x43/0x45
When skb allocation fails and the "rx routine starvation" is hit, the
function returns immediately without updating the RX ring. At this
point, the RX ring may continue referencing an old skb which was already
handed off to ieee80211_rx_irqsafe(). When it comes to be used again,
bad things happen.
This patch allocates a new skb first in RX ISR. If we don't have memory
available, we discard the current frame, allowing the existing skb to be
reused in the ring. Otherwise, we simplify the code flow and just hand
over the RX-populated skb over to mac80211.
In addition, to fixing the kernel crash, the RX routine should now
generally behave better under low memory conditions.
Buglink: https://bugzilla.kernel.org/show_bug.cgi?id=204053
Signed-off-by: Jian-Hong Pan <jian-hong@endlessm.com>
Reviewed-by: Daniel Drake <drake@endlessm.com>
Cc: <stable@vger.kernel.org>
---
drivers/net/wireless/realtek/rtw88/pci.c | 28 +++++++++++-------------
1 file changed, 13 insertions(+), 15 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c
index cfe05ba7280d..1bfc99ae6b84 100644
--- a/drivers/net/wireless/realtek/rtw88/pci.c
+++ b/drivers/net/wireless/realtek/rtw88/pci.c
@@ -786,6 +786,15 @@ static void rtw_pci_rx_isr(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci,
rx_desc = skb->data;
chip->ops->query_rx_desc(rtwdev, rx_desc, &pkt_stat, &rx_status);
+ /* discard current skb if the new skb cannot be allocated as a
+ * new one in rx ring later
+ * */
+ new = dev_alloc_skb(RTK_PCI_RX_BUF_SIZE);
+ if (WARN(!new, "rx routine starvation\n")) {
+ new = skb;
+ goto next_rp;
+ }
+
/* offset from rx_desc to payload */
pkt_offset = pkt_desc_sz + pkt_stat.drv_info_sz +
pkt_stat.shift;
@@ -803,25 +812,14 @@ static void rtw_pci_rx_isr(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci,
skb_put(skb, pkt_stat.pkt_len);
skb_reserve(skb, pkt_offset);
- /* alloc a smaller skb to mac80211 */
- new = dev_alloc_skb(pkt_stat.pkt_len);
- if (!new) {
- new = skb;
- } else {
- skb_put_data(new, skb->data, skb->len);
- dev_kfree_skb_any(skb);
- }
/* TODO: merge into rx.c */
rtw_rx_stats(rtwdev, pkt_stat.vif, skb);
- memcpy(new->cb, &rx_status, sizeof(rx_status));
- ieee80211_rx_irqsafe(rtwdev->hw, new);
+ memcpy(skb->cb, &rx_status, sizeof(rx_status));
+ ieee80211_rx_irqsafe(rtwdev->hw, skb);
}
- /* skb delivered to mac80211, alloc a new one in rx ring */
- new = dev_alloc_skb(RTK_PCI_RX_BUF_SIZE);
- if (WARN(!new, "rx routine starvation\n"))
- return;
-
+next_rp:
+ /* skb delivered to mac80211, attach the new one into rx ring */
ring->buf[cur_rp] = new;
rtw_pci_reset_rx_desc(rtwdev, new, ring, cur_rp, buf_desc_sz);
--
2.22.0
^ permalink raw reply related
* RE: [PATCH] rtw88/pci: Rearrange the memory usage for skb in RX ISR
From: Tony Chuang @ 2019-07-08 7:23 UTC (permalink / raw)
To: Jian-Hong Pan, Kalle Valo, David S . Miller
Cc: linux-wireless@vger.kernel.org, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org, linux@endlessm.com, Daniel Drake,
stable@vger.kernel.org
In-Reply-To: <20190708063252.4756-1-jian-hong@endlessm.com>
> Subject: [PATCH] rtw88/pci: Rearrange the memory usage for skb in RX ISR
nit, "rtw88: pci:" would be better.
>
>
> When skb allocation fails and the "rx routine starvation" is hit, the
> function returns immediately without updating the RX ring. At this
> point, the RX ring may continue referencing an old skb which was already
> handed off to ieee80211_rx_irqsafe(). When it comes to be used again,
> bad things happen.
>
> This patch allocates a new skb first in RX ISR. If we don't have memory
> available, we discard the current frame, allowing the existing skb to be
> reused in the ring. Otherwise, we simplify the code flow and just hand
> over the RX-populated skb over to mac80211.
>
> In addition, to fixing the kernel crash, the RX routine should now
> generally behave better under low memory conditions.
>
> Buglink: https://bugzilla.kernel.org/show_bug.cgi?id=204053
> Signed-off-by: Jian-Hong Pan <jian-hong@endlessm.com>
> Reviewed-by: Daniel Drake <drake@endlessm.com>
> Cc: <stable@vger.kernel.org>
> ---
> drivers/net/wireless/realtek/rtw88/pci.c | 28 +++++++++++-------------
> 1 file changed, 13 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/net/wireless/realtek/rtw88/pci.c
> b/drivers/net/wireless/realtek/rtw88/pci.c
> index cfe05ba7280d..1bfc99ae6b84 100644
> --- a/drivers/net/wireless/realtek/rtw88/pci.c
> +++ b/drivers/net/wireless/realtek/rtw88/pci.c
> @@ -786,6 +786,15 @@ static void rtw_pci_rx_isr(struct rtw_dev *rtwdev,
> struct rtw_pci *rtwpci,
> rx_desc = skb->data;
> chip->ops->query_rx_desc(rtwdev, rx_desc, &pkt_stat, &rx_status);
>
> + /* discard current skb if the new skb cannot be allocated as a
> + * new one in rx ring later
> + * */
nit, comment indentation.
> + new = dev_alloc_skb(RTK_PCI_RX_BUF_SIZE);
> + if (WARN(!new, "rx routine starvation\n")) {
> + new = skb;
> + goto next_rp;
> + }
> +
> /* offset from rx_desc to payload */
> pkt_offset = pkt_desc_sz + pkt_stat.drv_info_sz +
> pkt_stat.shift;
> @@ -803,25 +812,14 @@ static void rtw_pci_rx_isr(struct rtw_dev *rtwdev,
> struct rtw_pci *rtwpci,
> skb_put(skb, pkt_stat.pkt_len);
> skb_reserve(skb, pkt_offset);
>
> - /* alloc a smaller skb to mac80211 */
> - new = dev_alloc_skb(pkt_stat.pkt_len);
> - if (!new) {
> - new = skb;
> - } else {
> - skb_put_data(new, skb->data, skb->len);
> - dev_kfree_skb_any(skb);
> - }
I am not sure if it's fine to deliver every huge SKB to mac80211.
Because it will then be delivered to TCP/IP stack.
Hence I think either it should be tested to know if the performance
would be impacted or find out a more efficient way to send
smaller SKB to mac80211 stack.
> /* TODO: merge into rx.c */
> rtw_rx_stats(rtwdev, pkt_stat.vif, skb);
> - memcpy(new->cb, &rx_status, sizeof(rx_status));
> - ieee80211_rx_irqsafe(rtwdev->hw, new);
> + memcpy(skb->cb, &rx_status, sizeof(rx_status));
> + ieee80211_rx_irqsafe(rtwdev->hw, skb);
> }
>
> - /* skb delivered to mac80211, alloc a new one in rx ring */
> - new = dev_alloc_skb(RTK_PCI_RX_BUF_SIZE);
> - if (WARN(!new, "rx routine starvation\n"))
> - return;
> -
> +next_rp:
> + /* skb delivered to mac80211, attach the new one into rx ring */
> ring->buf[cur_rp] = new;
> rtw_pci_reset_rx_desc(rtwdev, new, ring, cur_rp, buf_desc_sz);
>
--
Yan-Hsuan
^ permalink raw reply
* Re: [PATCH] rtw88/pci: Rearrange the memory usage for skb in RX ISR
From: Jian-Hong Pan @ 2019-07-08 8:07 UTC (permalink / raw)
To: Tony Chuang
Cc: Kalle Valo, David S . Miller, linux-wireless@vger.kernel.org,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
linux@endlessm.com, Daniel Drake, stable@vger.kernel.org
In-Reply-To: <F7CD281DE3E379468C6D07993EA72F84D1861A6D@RTITMBSVM04.realtek.com.tw>
Tony Chuang <yhchuang@realtek.com> 於 2019年7月8日 週一 下午3:23寫道:
>
> > Subject: [PATCH] rtw88/pci: Rearrange the memory usage for skb in RX ISR
>
> nit, "rtw88: pci:" would be better.
Ok.
> >
> > When skb allocation fails and the "rx routine starvation" is hit, the
> > function returns immediately without updating the RX ring. At this
> > point, the RX ring may continue referencing an old skb which was already
> > handed off to ieee80211_rx_irqsafe(). When it comes to be used again,
> > bad things happen.
> >
> > This patch allocates a new skb first in RX ISR. If we don't have memory
> > available, we discard the current frame, allowing the existing skb to be
> > reused in the ring. Otherwise, we simplify the code flow and just hand
> > over the RX-populated skb over to mac80211.
> >
> > In addition, to fixing the kernel crash, the RX routine should now
> > generally behave better under low memory conditions.
> >
> > Buglink: https://bugzilla.kernel.org/show_bug.cgi?id=204053
> > Signed-off-by: Jian-Hong Pan <jian-hong@endlessm.com>
> > Reviewed-by: Daniel Drake <drake@endlessm.com>
> > Cc: <stable@vger.kernel.org>
> > ---
> > drivers/net/wireless/realtek/rtw88/pci.c | 28 +++++++++++-------------
> > 1 file changed, 13 insertions(+), 15 deletions(-)
> >
> > diff --git a/drivers/net/wireless/realtek/rtw88/pci.c
> > b/drivers/net/wireless/realtek/rtw88/pci.c
> > index cfe05ba7280d..1bfc99ae6b84 100644
> > --- a/drivers/net/wireless/realtek/rtw88/pci.c
> > +++ b/drivers/net/wireless/realtek/rtw88/pci.c
> > @@ -786,6 +786,15 @@ static void rtw_pci_rx_isr(struct rtw_dev *rtwdev,
> > struct rtw_pci *rtwpci,
> > rx_desc = skb->data;
> > chip->ops->query_rx_desc(rtwdev, rx_desc, &pkt_stat, &rx_status);
> >
> > + /* discard current skb if the new skb cannot be allocated as a
> > + * new one in rx ring later
> > + * */
>
> nit, comment indentation.
Thanks. I will fix this.
> > + new = dev_alloc_skb(RTK_PCI_RX_BUF_SIZE);
> > + if (WARN(!new, "rx routine starvation\n")) {
> > + new = skb;
> > + goto next_rp;
> > + }
> > +
> > /* offset from rx_desc to payload */
> > pkt_offset = pkt_desc_sz + pkt_stat.drv_info_sz +
> > pkt_stat.shift;
> > @@ -803,25 +812,14 @@ static void rtw_pci_rx_isr(struct rtw_dev *rtwdev,
> > struct rtw_pci *rtwpci,
> > skb_put(skb, pkt_stat.pkt_len);
> > skb_reserve(skb, pkt_offset);
> >
> > - /* alloc a smaller skb to mac80211 */
> > - new = dev_alloc_skb(pkt_stat.pkt_len);
> > - if (!new) {
> > - new = skb;
> > - } else {
> > - skb_put_data(new, skb->data, skb->len);
> > - dev_kfree_skb_any(skb);
> > - }
>
> I am not sure if it's fine to deliver every huge SKB to mac80211.
> Because it will then be delivered to TCP/IP stack.
> Hence I think either it should be tested to know if the performance
> would be impacted or find out a more efficient way to send
> smaller SKB to mac80211 stack.
I remember network stack only processes the skb with(in) pointers
(skb->data) and the skb->len for data part. It also checks real
buffer boundary (head and end) of the skb to prevent memory overflow.
Therefore, I think using the original skb is the most efficient way.
If I misunderstand something, please point out.
> > /* TODO: merge into rx.c */
> > rtw_rx_stats(rtwdev, pkt_stat.vif, skb);
> > - memcpy(new->cb, &rx_status, sizeof(rx_status));
> > - ieee80211_rx_irqsafe(rtwdev->hw, new);
> > + memcpy(skb->cb, &rx_status, sizeof(rx_status));
> > + ieee80211_rx_irqsafe(rtwdev->hw, skb);
> > }
> >
> > - /* skb delivered to mac80211, alloc a new one in rx ring */
> > - new = dev_alloc_skb(RTK_PCI_RX_BUF_SIZE);
> > - if (WARN(!new, "rx routine starvation\n"))
> > - return;
> > -
> > +next_rp:
> > + /* skb delivered to mac80211, attach the new one into rx ring */
> > ring->buf[cur_rp] = new;
> > rtw_pci_reset_rx_desc(rtwdev, new, ring, cur_rp, buf_desc_sz);
> >
>
> --
>
> Yan-Hsuan
^ permalink raw reply
* RE: [PATCH] rtw88/pci: Rearrange the memory usage for skb in RX ISR
From: David Laight @ 2019-07-08 8:36 UTC (permalink / raw)
To: 'Jian-Hong Pan', Yan-Hsuan Chuang, Kalle Valo,
David S . Miller
Cc: linux-wireless@vger.kernel.org, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org, linux@endlessm.com, Daniel Drake,
stable@vger.kernel.org
In-Reply-To: <20190708063252.4756-1-jian-hong@endlessm.com>
From: Jian-Hong Pan
> Sent: 08 July 2019 07:33
> To: Yan-Hsuan Chuang; Kalle Valo; David S . Miller
>
> Testing with RTL8822BE hardware, when available memory is low, we
> frequently see a kernel panic and system freeze.
>
> First, rtw_pci_rx_isr encounters a memory allocation failure (trimmed):
>
> rx routine starvation
> WARNING: CPU: 7 PID: 9871 at drivers/net/wireless/realtek/rtw88/pci.c:822
> rtw_pci_rx_isr.constprop.25+0x35a/0x370 [rtwpci]
> [ 2356.580313] RIP: 0010:rtw_pci_rx_isr.constprop.25+0x35a/0x370 [rtwpci]
>
> Then we see a variety of different error conditions and kernel panics,
> such as this one (trimmed):
>
> rtw_pci 0000:02:00.0: pci bus timeout, check dma status
> skbuff: skb_over_panic: text:00000000091b6e66 len:415 put:415 head:00000000d2880c6f
> data:000000007a02b1ea tail:0x1df end:0xc0 dev:<NULL>
> ------------[ cut here ]------------
> kernel BUG at net/core/skbuff.c:105!
> invalid opcode: 0000 [#1] SMP NOPTI
> RIP: 0010:skb_panic+0x43/0x45
>
> When skb allocation fails and the "rx routine starvation" is hit, the
> function returns immediately without updating the RX ring. At this
> point, the RX ring may continue referencing an old skb which was already
> handed off to ieee80211_rx_irqsafe(). When it comes to be used again,
> bad things happen.
>
> This patch allocates a new skb first in RX ISR. If we don't have memory
> available, we discard the current frame, allowing the existing skb to be
> reused in the ring. Otherwise, we simplify the code flow and just hand
> over the RX-populated skb over to mac80211.
>
> In addition, to fixing the kernel crash, the RX routine should now
> generally behave better under low memory conditions.
Under low memory conditions it may be preferable to limit the amount
of memory assigned to the receive ring.
I also thought it was preferable (DM may correct me here) to do the
skb allocates from the 'bh' of the driver rather than from the hardware
interrupt.
It is also almost certainly preferable (especially on IOMMU systems)
to copy small frames into a new skb (of the right size) and then
reuse the skb (with its dma-mapped buffer) for a later frame.
Allocating a new skb before ay px processing just seems wrong...
David
> Buglink: https://bugzilla.kernel.org/show_bug.cgi?id=204053
> Signed-off-by: Jian-Hong Pan <jian-hong@endlessm.com>
> Reviewed-by: Daniel Drake <drake@endlessm.com>
> Cc: <stable@vger.kernel.org>
> ---
> drivers/net/wireless/realtek/rtw88/pci.c | 28 +++++++++++-------------
> 1 file changed, 13 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c
> index cfe05ba7280d..1bfc99ae6b84 100644
> --- a/drivers/net/wireless/realtek/rtw88/pci.c
> +++ b/drivers/net/wireless/realtek/rtw88/pci.c
> @@ -786,6 +786,15 @@ static void rtw_pci_rx_isr(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci,
> rx_desc = skb->data;
> chip->ops->query_rx_desc(rtwdev, rx_desc, &pkt_stat, &rx_status);
>
> + /* discard current skb if the new skb cannot be allocated as a
> + * new one in rx ring later
> + * */
> + new = dev_alloc_skb(RTK_PCI_RX_BUF_SIZE);
> + if (WARN(!new, "rx routine starvation\n")) {
> + new = skb;
> + goto next_rp;
> + }
> +
> /* offset from rx_desc to payload */
> pkt_offset = pkt_desc_sz + pkt_stat.drv_info_sz +
> pkt_stat.shift;
> @@ -803,25 +812,14 @@ static void rtw_pci_rx_isr(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci,
> skb_put(skb, pkt_stat.pkt_len);
> skb_reserve(skb, pkt_offset);
>
> - /* alloc a smaller skb to mac80211 */
> - new = dev_alloc_skb(pkt_stat.pkt_len);
> - if (!new) {
> - new = skb;
> - } else {
> - skb_put_data(new, skb->data, skb->len);
> - dev_kfree_skb_any(skb);
> - }
> /* TODO: merge into rx.c */
> rtw_rx_stats(rtwdev, pkt_stat.vif, skb);
> - memcpy(new->cb, &rx_status, sizeof(rx_status));
> - ieee80211_rx_irqsafe(rtwdev->hw, new);
> + memcpy(skb->cb, &rx_status, sizeof(rx_status));
> + ieee80211_rx_irqsafe(rtwdev->hw, skb);
> }
>
> - /* skb delivered to mac80211, alloc a new one in rx ring */
> - new = dev_alloc_skb(RTK_PCI_RX_BUF_SIZE);
> - if (WARN(!new, "rx routine starvation\n"))
> - return;
> -
> +next_rp:
> + /* skb delivered to mac80211, attach the new one into rx ring */
> ring->buf[cur_rp] = new;
> rtw_pci_reset_rx_desc(rtwdev, new, ring, cur_rp, buf_desc_sz);
>
> --
> 2.22.0
-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)
^ permalink raw reply
* RE: [PATCH] rtw88/pci: Rearrange the memory usage for skb in RX ISR
From: Tony Chuang @ 2019-07-08 9:00 UTC (permalink / raw)
To: Jian-Hong Pan
Cc: Kalle Valo, David S . Miller, linux-wireless@vger.kernel.org,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
linux@endlessm.com, Daniel Drake, stable@vger.kernel.org
In-Reply-To: <CAPpJ_eebQtL0y_j98J2T7m9g77A61SVtvD8qnNN42bV0dm4MLA@mail.gmail.com>
> > > @@ -803,25 +812,14 @@ static void rtw_pci_rx_isr(struct rtw_dev
> *rtwdev,
> > > struct rtw_pci *rtwpci,
> > > skb_put(skb, pkt_stat.pkt_len);
> > > skb_reserve(skb, pkt_offset);
> > >
> > > - /* alloc a smaller skb to mac80211 */
> > > - new = dev_alloc_skb(pkt_stat.pkt_len);
> > > - if (!new) {
> > > - new = skb;
> > > - } else {
> > > - skb_put_data(new, skb->data,
> skb->len);
> > > - dev_kfree_skb_any(skb);
> > > - }
> >
> > I am not sure if it's fine to deliver every huge SKB to mac80211.
> > Because it will then be delivered to TCP/IP stack.
> > Hence I think either it should be tested to know if the performance
> > would be impacted or find out a more efficient way to send
> > smaller SKB to mac80211 stack.
>
> I remember network stack only processes the skb with(in) pointers
> (skb->data) and the skb->len for data part. It also checks real
> buffer boundary (head and end) of the skb to prevent memory overflow.
> Therefore, I think using the original skb is the most efficient way.
>
> If I misunderstand something, please point out.
>
It means if we still use a huge SKB (~8K) for every RX packet (~1.5K).
There is about 6.5K not used. And even more if we ping with large packet
size "eg. $ ping -s 65536", I am not sure if those huge SKBs will eat all of
the SKB mem pool, and then ping fails.
BTW, the original design of RTK_PCI_RX_BUF_SIZE to be (8192 + 24) is to
receive AMSDU packet in one SKB.
(Could probably enlarge it to RX VHT AMSDU ~11K)
Yan-Hsuan
^ permalink raw reply
* RE: [PATCH] rtw88/pci: Rearrange the memory usage for skb in RX ISR
From: David Laight @ 2019-07-08 9:18 UTC (permalink / raw)
To: 'Tony Chuang', Jian-Hong Pan
Cc: Kalle Valo, David S . Miller, linux-wireless@vger.kernel.org,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
linux@endlessm.com, Daniel Drake, stable@vger.kernel.org
In-Reply-To: <F7CD281DE3E379468C6D07993EA72F84D1861B71@RTITMBSVM04.realtek.com.tw>
From: Tony Chuang
> Sent: 08 July 2019 10:00
> > > > @@ -803,25 +812,14 @@ static void rtw_pci_rx_isr(struct rtw_dev
> > *rtwdev,
> > > > struct rtw_pci *rtwpci,
> > > > skb_put(skb, pkt_stat.pkt_len);
> > > > skb_reserve(skb, pkt_offset);
> > > >
> > > > - /* alloc a smaller skb to mac80211 */
> > > > - new = dev_alloc_skb(pkt_stat.pkt_len);
> > > > - if (!new) {
> > > > - new = skb;
> > > > - } else {
> > > > - skb_put_data(new, skb->data,
> > skb->len);
> > > > - dev_kfree_skb_any(skb);
> > > > - }
> > >
> > > I am not sure if it's fine to deliver every huge SKB to mac80211.
> > > Because it will then be delivered to TCP/IP stack.
> > > Hence I think either it should be tested to know if the performance
> > > would be impacted or find out a more efficient way to send
> > > smaller SKB to mac80211 stack.
> >
> > I remember network stack only processes the skb with(in) pointers
> > (skb->data) and the skb->len for data part. It also checks real
> > buffer boundary (head and end) of the skb to prevent memory overflow.
> > Therefore, I think using the original skb is the most efficient way.
> >
> > If I misunderstand something, please point out.
> >
>
> It means if we still use a huge SKB (~8K) for every RX packet (~1.5K).
> There is about 6.5K not used. And even more if we ping with large packet
> size "eg. $ ping -s 65536", I am not sure if those huge SKBs will eat all of
> the SKB mem pool, and then ping fails.
>
> BTW, the original design of RTK_PCI_RX_BUF_SIZE to be (8192 + 24) is to
> receive AMSDU packet in one SKB.
> (Could probably enlarge it to RX VHT AMSDU ~11K)
If you allocate 8192+24 the memory allocated will be either 12k or 16k
and the skb truesize set appropriately.
(Probably 16k if dma memory.)
If this is fed into IP it is quite likely that a single byte of data
will end up queued on the socket in 16k of dma-able memory.
The 'truesize' stops this using all the system memory, but it isn't
good for memory usage.
David
-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)
^ permalink raw reply
* Re: [PATCH 3/7] brcmsmac: switch source files to using SPDX license identifier
From: Arend Van Spriel @ 2019-07-08 10:07 UTC (permalink / raw)
To: Rafał Miłecki
Cc: Greg Kroah-Hartman, Kalle Valo, linux-wireless@vger.kernel.org,
Thomas Gleixner, alan
In-Reply-To: <CACna6rxuSFWN8eib7FpJiVQqLwdD5GOTaAFr7msJa01rBSTLKA@mail.gmail.com>
+ Alan
On 5/17/2019 8:07 PM, Rafał Miłecki wrote:
>>>> Another option could be MIT license which is in the preferred folder.
>>>> Will have to consult our legal department about it though.
>>> Hey, if your legal department is going to get asked this, why not just
>>> switch it to GPLv2? That would make everything much simpler.
>> Hah. Because I already know the answer to that.;-)
> It's not that obvious to me, sorry. Does your legal department require
> something more permissive than GPLv2? Is that worth asking them about
> dual-licensing? Something like
> GPL-2.0 OR MIT
> ? That assures driver is compatible with Linux, no matter what's the
> current lawyers interpretation of MIT vs. GPL 2.0. I believe Alan Cox
> once told/suggested that dual-licensing is safer for legal reasons.
Hi Alan,
Rafał mentioned your name a while ago when I was struggling with the
SPDX identifiers. The drivers sources I want to modify for this
originally had a license text in the header that matches ISC. However,
one of the files did not have that and it was marked in bulk to GPLv2.
So now the question is whether I can change it to ISC like the rest or
should I make it dual like Rafał suggested.
Can you elaborate the pros and cons of dual license?
Regards,
Arend
^ permalink raw reply
* Re: [PATCH 3/7] brcmsmac: switch source files to using SPDX license identifier
From: Greg Kroah-Hartman @ 2019-07-08 10:41 UTC (permalink / raw)
To: Arend Van Spriel
Cc: Rafał Miłecki, Kalle Valo,
linux-wireless@vger.kernel.org, Thomas Gleixner, alan
In-Reply-To: <34aa04e4-9ddd-b6aa-721f-a20398f7740d@broadcom.com>
On Mon, Jul 08, 2019 at 12:07:43PM +0200, Arend Van Spriel wrote:
> + Alan
>
> On 5/17/2019 8:07 PM, Rafał Miłecki wrote:
> > > > > Another option could be MIT license which is in the preferred folder.
> > > > > Will have to consult our legal department about it though.
> > > > Hey, if your legal department is going to get asked this, why not just
> > > > switch it to GPLv2? That would make everything much simpler.
> > > Hah. Because I already know the answer to that.;-)
> > It's not that obvious to me, sorry. Does your legal department require
> > something more permissive than GPLv2? Is that worth asking them about
> > dual-licensing? Something like
> > GPL-2.0 OR MIT
> > ? That assures driver is compatible with Linux, no matter what's the
> > current lawyers interpretation of MIT vs. GPL 2.0. I believe Alan Cox
> > once told/suggested that dual-licensing is safer for legal reasons.
>
> Hi Alan,
>
> Rafał mentioned your name a while ago when I was struggling with the SPDX
> identifiers. The drivers sources I want to modify for this originally had a
> license text in the header that matches ISC. However,
> one of the files did not have that and it was marked in bulk to GPLv2. So
> now the question is whether I can change it to ISC like the rest or should I
> make it dual like Rafał suggested.
>
> Can you elaborate the pros and cons of dual license?
You need to talk to your lawyers about that. Please ask this of them.
thanks,
greg k-h
^ permalink raw reply
* Re: [PATCH 4/7] mmc: sdio: Drop powered-on re-init at runtime resume and HW reset
From: Ulf Hansson @ 2019-07-08 10:53 UTC (permalink / raw)
To: Doug Anderson
Cc: Linux MMC List, Adrian Hunter, Brian Norris, Shawn Lin,
Guenter Roeck, Heiko Stuebner, Kalle Valo, Arend Van Spriel,
linux-wireless
In-Reply-To: <CAD=FV=X7P2F1k_zwHc0mbtfk55-rucTz_GoDH=PL6zWqKYcpuw@mail.gmail.com>
On Thu, 4 Jul 2019 at 02:02, Doug Anderson <dianders@chromium.org> wrote:
>
> Hi,
>
> On Tue, Jun 18, 2019 at 8:35 AM Ulf Hansson <ulf.hansson@linaro.org> wrote:
> >
> > To use the so called powered-on re-initialization of an SDIO card, the
> > power to the card must obviously have stayed on. If not, the initialization
> > will simply fail.
> >
> > In the runtime suspend case, the card is always powered off. Hence, let's
> > drop the support for powered-on re-initialization during runtime resume, as
> > it doesn't make sense.
> >
> > Moreover, during a HW reset, the point is to cut the power to the card and
> > then do fresh re-initialization. Therefore drop the support for powered-on
> > re-initialization during HW reset.
> >
> > Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> > ---
> > drivers/mmc/core/sdio.c | 8 +-------
> > 1 file changed, 1 insertion(+), 7 deletions(-)
>
> This has been on my list of things to test for a while but I never
> quite got to it...
>
> ...and then, today, I spent time bisecting why the "reset"
> functionality of miwfiex is broken on my 4.19 kernel [1]. AKA, this
> is broken:
>
> cd /sys/kernel/debug/mwifiex/mlan0
> echo 1 > reset
>
> I finally bisected the problem and tracked it down to commit
> ca8971ca5753 ("mmc: dw_mmc: Prevent runtime PM suspend when SDIO IRQs
> are enabled"), which embarrassingly has my Tested-by on it. I guess I
> never tested the Marvell reset call. :-/
>
> I dug a little and found that when the Marvell code did its reset we
> ended up getting a call to dw_mci_enable_sdio_irq(enb=0) and never saw
> a dw_mci_enable_sdio_irq(enb=1) after. I tracked it down further and
> found that specifically it was the call to mmc_signal_sdio_irq() in
> mmc_sdio_power_restore() that was making the call. The call stack
> shown for the "enb=0" call:
>
> [<c071a290>] (dw_mci_enable_sdio_irq) from [<c070a960>]
> (mmc_sdio_power_restore+0x98/0xc0)
> [<c070a960>] (mmc_sdio_power_restore) from [<c070a9b4>]
> (mmc_sdio_reset+0x2c/0x30)
> [<c070a9b4>] (mmc_signal_sdio_irq) from [<c06ff160>] (mmc_hw_reset+0xbc/0x138)
> [<c06ff160>] (mmc_hw_reset) from [<bf1bbad8>]
> (mwifiex_sdio_work+0x5d4/0x678 [mwifiex_sdio])
> [<bf1bbad8>] (mwifiex_sdio_work [mwifiex_sdio]) from [<c0247cd0>]
> (process_one_work+0x290/0x4b4)
>
> I picked your patch here (which gets rid of the call to
> mmc_signal_sdio_irq()) and magically the problem went away because
> there is no more call to mmc_signal_sdio_irq().
>
> I personally don't have lots of history about the whole
> "powered_resume" code path. I checked and mmc_card_keep_power() was 0
> in my test case of getting called from hw_reset, so the rest of this
> patch doesn't affect me at all. This surprised me a little since I
> saw "MMC_PM_KEEP_POWER" being set in mwifiex but then I realized that
> it was only set for the duration of suspend and then cleared by the
> core. ;-)
>
> I will also say that I don't have any test case or knowledge of how
> SDIO runtime suspend/resume is supposed to work since on dw_mmc SDIO
> cards are currently not allowed to runtime suspend anyway. ;-)
>
>
> So I guess the result of all that long-winded reply is that for on
> rk3288-veyron-jerry:
>
> Fixes: ca8971ca5753 ("mmc: dw_mmc: Prevent runtime PM suspend when
> SDIO IRQs are enabled")
> Tested-by: Douglas Anderson <dianders@chromium.org>
Thanks a lot for testing and for your detailed feedback. I have
amended the patch by adding your tags above.
Moreover, we seems to need this for stable as well, but I am leaving
that to be managed as a separate task. We may even consider the hole
series for stable, but that requires more testing first.
>
>
> One last note is that, though Marvell WiFi works after a reset after
> this commit, Marvell Bluetooth (on the same SDIO module) doesn't. I
> guess next week it'll be another bisect...
Is the Bluetooth connected to the same SDIO interface, thus the
Bluetooth driver is an SDIO func driver?
>
> [1] https://crbug.com/981113
>
>
>
> -Doug
Kind regards
Uffe
^ permalink raw reply
* [PATCH] ath10k: work around uninitialized vht_pfr variable
From: Arnd Bergmann @ 2019-07-08 12:50 UTC (permalink / raw)
To: Kalle Valo
Cc: Arnd Bergmann, Miaoqing Pan, David S. Miller, Rakesh Pillai,
Brian Norris, Balaji Pothunoori, Wen Gong, Pradeep kumar Chitrapu,
Sriram R, ath10k, linux-wireless, netdev, linux-kernel,
clang-built-linux
As clang points out, the vht_pfr is assigned to a struct member
without being initialized in one case:
drivers/net/wireless/ath/ath10k/mac.c:7528:7: error: variable 'vht_pfr' is used uninitialized whenever 'if' condition
is false [-Werror,-Wsometimes-uninitialized]
if (!ath10k_mac_can_set_bitrate_mask(ar, band, mask,
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/net/wireless/ath/ath10k/mac.c:7551:20: note: uninitialized use occurs here
arvif->vht_pfr = vht_pfr;
^~~~~~~
drivers/net/wireless/ath/ath10k/mac.c:7528:3: note: remove the 'if' if its condition is always true
if (!ath10k_mac_can_set_bitrate_mask(ar, band, mask,
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/net/wireless/ath/ath10k/mac.c:7483:12: note: initialize the variable 'vht_pfr' to silence this warning
u8 vht_pfr;
Add an explicit but probably incorrect initialization here.
I suspect we want a better fix here, but chose this approach to
illustrate the issue.
Fixes: 8b97b055dc9d ("ath10k: fix failure to set multiple fixed rate")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
drivers/net/wireless/ath/ath10k/mac.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index e43a566eef77..0606416dc971 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -7541,6 +7541,8 @@ static int ath10k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
&vht_nss,
true);
update_bitrate_mask = false;
+ } else {
+ vht_pfr = 0;
}
mutex_lock(&ar->conf_mutex);
--
2.20.0
^ permalink raw reply related
* Re: [PATCH] ath10k: work around uninitialized vht_pfr variable
From: Nathan Chancellor @ 2019-07-08 14:46 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Kalle Valo, Miaoqing Pan, David S. Miller, Rakesh Pillai,
Brian Norris, Balaji Pothunoori, Wen Gong, Pradeep kumar Chitrapu,
Sriram R, ath10k, linux-wireless, netdev, linux-kernel,
clang-built-linux
In-Reply-To: <20190708125050.3689133-1-arnd@arndb.de>
On Mon, Jul 08, 2019 at 02:50:06PM +0200, Arnd Bergmann wrote:
> As clang points out, the vht_pfr is assigned to a struct member
> without being initialized in one case:
>
> drivers/net/wireless/ath/ath10k/mac.c:7528:7: error: variable 'vht_pfr' is used uninitialized whenever 'if' condition
> is false [-Werror,-Wsometimes-uninitialized]
> if (!ath10k_mac_can_set_bitrate_mask(ar, band, mask,
> ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> drivers/net/wireless/ath/ath10k/mac.c:7551:20: note: uninitialized use occurs here
> arvif->vht_pfr = vht_pfr;
> ^~~~~~~
> drivers/net/wireless/ath/ath10k/mac.c:7528:3: note: remove the 'if' if its condition is always true
> if (!ath10k_mac_can_set_bitrate_mask(ar, band, mask,
> ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> drivers/net/wireless/ath/ath10k/mac.c:7483:12: note: initialize the variable 'vht_pfr' to silence this warning
> u8 vht_pfr;
>
> Add an explicit but probably incorrect initialization here.
> I suspect we want a better fix here, but chose this approach to
> illustrate the issue.
Yup, I reached out to the maintainers when this issue first cropped up,
should have taken your approach though.
https://lore.kernel.org/lkml/20190702181837.GA118849@archlinux-epyc/
Initializing to zero is better than uninitialized.
>
> Fixes: 8b97b055dc9d ("ath10k: fix failure to set multiple fixed rate")
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Reviewed-by: Nathan Chancellor <natechancellor@gmail.com>
^ permalink raw reply
* [PATCH 0/2] iwlwifi: fixes intended for 5.3 2019-07-08
From: Luca Coelho @ 2019-07-08 15:55 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, Luca Coelho
From: Luca Coelho <luciano.coelho@intel.com>
Hi,
This is the first patchset with fixes for v5.3.
The changes are:
* A few new PCI IDs for 9000 and 22000 series;
* Support for C-step 22000 devices;
As usual, I'm pushing this to a pending branch, for kbuild bot. And
as we agreed, I'll delegate these patches to you in patchwork for you
to apply them directly. There's no hurry with this, I know we're
still in the merge window, I just wanted to send them out for people
who have these devices and are having problems. It's your call:
either send them during the merge window, if you send a new pull-req;
or take it when the merge window closes, for v5.3-rc1.
Note: all this area will probably have some conflicts when merging
with -next, because I've been sending new PCI IDs and such things for
fixes, while some other changes are being made for -next. Let me know
if you need any help merging, when time comes.
Cheers,
Luca.
Ihab Zhaika (1):
iwlwifi: add new cards for 9000 and 20000 series
Luca Coelho (1):
iwlwifi: pcie: add support for qu c-step devices
.../net/wireless/intel/iwlwifi/cfg/22000.c | 53 +++++++++++++++++++
.../net/wireless/intel/iwlwifi/iwl-config.h | 7 +++
drivers/net/wireless/intel/iwlwifi/iwl-csr.h | 2 +
drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 23 ++++++++
4 files changed, 85 insertions(+)
--
2.20.1
^ permalink raw reply
* [PATCH 1/2] iwlwifi: add new cards for 9000 and 20000 series
From: Luca Coelho @ 2019-07-08 15:55 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, Ihab Zhaika, stable, Luca Coelho
In-Reply-To: <20190708155534.18241-1-luca@coelho.fi>
From: Ihab Zhaika <ihab.zhaika@intel.com>
add two new PCI ID's for 9000 and 20000 series
Cc: stable@vger.kernel.org
Signed-off-by: Ihab Zhaika <ihab.zhaika@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
index ccc83fd74649..fe645380bd2f 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
@@ -604,6 +604,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
{IWL_PCI_DEVICE(0x2526, 0x40A4, iwl9460_2ac_cfg)},
{IWL_PCI_DEVICE(0x2526, 0x4234, iwl9560_2ac_cfg_soc)},
{IWL_PCI_DEVICE(0x2526, 0x42A4, iwl9462_2ac_cfg_soc)},
+ {IWL_PCI_DEVICE(0x2526, 0x6014, iwl9260_2ac_160_cfg)},
{IWL_PCI_DEVICE(0x2526, 0x8014, iwl9260_2ac_160_cfg)},
{IWL_PCI_DEVICE(0x2526, 0x8010, iwl9260_2ac_160_cfg)},
{IWL_PCI_DEVICE(0x2526, 0xA014, iwl9260_2ac_160_cfg)},
@@ -971,6 +972,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
{IWL_PCI_DEVICE(0x7A70, 0x0310, iwlax211_2ax_cfg_so_gf_a0)},
{IWL_PCI_DEVICE(0x7A70, 0x0510, iwlax211_2ax_cfg_so_gf_a0)},
{IWL_PCI_DEVICE(0x7A70, 0x0A10, iwlax211_2ax_cfg_so_gf_a0)},
+ {IWL_PCI_DEVICE(0x7AF0, 0x0090, iwlax211_2ax_cfg_so_gf_a0)},
{IWL_PCI_DEVICE(0x7AF0, 0x0310, iwlax211_2ax_cfg_so_gf_a0)},
{IWL_PCI_DEVICE(0x7AF0, 0x0510, iwlax211_2ax_cfg_so_gf_a0)},
{IWL_PCI_DEVICE(0x7AF0, 0x0A10, iwlax211_2ax_cfg_so_gf_a0)},
--
2.20.1
^ permalink raw reply related
* [PATCH 2/2] iwlwifi: pcie: add support for qu c-step devices
From: Luca Coelho @ 2019-07-08 15:55 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, Luca Coelho, stable
In-Reply-To: <20190708155534.18241-1-luca@coelho.fi>
From: Luca Coelho <luciano.coelho@intel.com>
Add support for C-step devices. Currently we don't have a nice way of
matching the step and choosing the proper configuration, so we need to
switch the config structs one by one.
Cc: stable@vger.kernel.org
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
.../net/wireless/intel/iwlwifi/cfg/22000.c | 53 +++++++++++++++++++
.../net/wireless/intel/iwlwifi/iwl-config.h | 7 +++
drivers/net/wireless/intel/iwlwifi/iwl-csr.h | 2 +
drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 21 ++++++++
4 files changed, 83 insertions(+)
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c
index 93526dfaf791..1f500cddb3a7 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c
@@ -80,7 +80,9 @@
#define IWL_22000_QU_B_HR_B_FW_PRE "iwlwifi-Qu-b0-hr-b0-"
#define IWL_22000_HR_B_FW_PRE "iwlwifi-QuQnj-b0-hr-b0-"
#define IWL_22000_HR_A0_FW_PRE "iwlwifi-QuQnj-a0-hr-a0-"
+#define IWL_QU_C_HR_B_FW_PRE "iwlwifi-Qu-c0-hr-b0-"
#define IWL_QU_B_JF_B_FW_PRE "iwlwifi-Qu-b0-jf-b0-"
+#define IWL_QU_C_JF_B_FW_PRE "iwlwifi-Qu-c0-jf-b0-"
#define IWL_QUZ_A_HR_B_FW_PRE "iwlwifi-QuZ-a0-hr-b0-"
#define IWL_QUZ_A_JF_B_FW_PRE "iwlwifi-QuZ-a0-jf-b0-"
#define IWL_QNJ_B_JF_B_FW_PRE "iwlwifi-QuQnj-b0-jf-b0-"
@@ -109,6 +111,8 @@
IWL_QUZ_A_HR_B_FW_PRE __stringify(api) ".ucode"
#define IWL_QUZ_A_JF_B_MODULE_FIRMWARE(api) \
IWL_QUZ_A_JF_B_FW_PRE __stringify(api) ".ucode"
+#define IWL_QU_C_HR_B_MODULE_FIRMWARE(api) \
+ IWL_QU_C_HR_B_FW_PRE __stringify(api) ".ucode"
#define IWL_QU_B_JF_B_MODULE_FIRMWARE(api) \
IWL_QU_B_JF_B_FW_PRE __stringify(api) ".ucode"
#define IWL_QNJ_B_JF_B_MODULE_FIRMWARE(api) \
@@ -256,6 +260,30 @@ const struct iwl_cfg iwl_ax201_cfg_qu_hr = {
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
};
+const struct iwl_cfg iwl_ax101_cfg_qu_c0_hr_b0 = {
+ .name = "Intel(R) Wi-Fi 6 AX101",
+ .fw_name_pre = IWL_QU_C_HR_B_FW_PRE,
+ IWL_DEVICE_22500,
+ /*
+ * This device doesn't support receiving BlockAck with a large bitmap
+ * so we need to restrict the size of transmitted aggregation to the
+ * HT size; mac80211 would otherwise pick the HE max (256) by default.
+ */
+ .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
+};
+
+const struct iwl_cfg iwl_ax201_cfg_qu_c0_hr_b0 = {
+ .name = "Intel(R) Wi-Fi 6 AX201 160MHz",
+ .fw_name_pre = IWL_QU_C_HR_B_FW_PRE,
+ IWL_DEVICE_22500,
+ /*
+ * This device doesn't support receiving BlockAck with a large bitmap
+ * so we need to restrict the size of transmitted aggregation to the
+ * HT size; mac80211 would otherwise pick the HE max (256) by default.
+ */
+ .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
+};
+
const struct iwl_cfg iwl_ax101_cfg_quz_hr = {
.name = "Intel(R) Wi-Fi 6 AX101",
.fw_name_pre = IWL_QUZ_A_HR_B_FW_PRE,
@@ -372,6 +400,30 @@ const struct iwl_cfg iwl9560_2ac_160_cfg_qu_b0_jf_b0 = {
IWL_DEVICE_22500,
};
+const struct iwl_cfg iwl9461_2ac_cfg_qu_c0_jf_b0 = {
+ .name = "Intel(R) Wireless-AC 9461",
+ .fw_name_pre = IWL_QU_C_JF_B_FW_PRE,
+ IWL_DEVICE_22500,
+};
+
+const struct iwl_cfg iwl9462_2ac_cfg_qu_c0_jf_b0 = {
+ .name = "Intel(R) Wireless-AC 9462",
+ .fw_name_pre = IWL_QU_C_JF_B_FW_PRE,
+ IWL_DEVICE_22500,
+};
+
+const struct iwl_cfg iwl9560_2ac_cfg_qu_c0_jf_b0 = {
+ .name = "Intel(R) Wireless-AC 9560",
+ .fw_name_pre = IWL_QU_C_JF_B_FW_PRE,
+ IWL_DEVICE_22500,
+};
+
+const struct iwl_cfg iwl9560_2ac_160_cfg_qu_c0_jf_b0 = {
+ .name = "Intel(R) Wireless-AC 9560 160MHz",
+ .fw_name_pre = IWL_QU_C_JF_B_FW_PRE,
+ IWL_DEVICE_22500,
+};
+
const struct iwl_cfg iwl9560_2ac_cfg_qnj_jf_b0 = {
.name = "Intel(R) Wireless-AC 9560 160MHz",
.fw_name_pre = IWL_QNJ_B_JF_B_FW_PRE,
@@ -590,6 +642,7 @@ MODULE_FIRMWARE(IWL_22000_HR_A_F0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_22000_HR_B_F0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_22000_HR_B_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_22000_HR_A0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_QU_C_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_QU_B_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_QUZ_A_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_QUZ_A_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h
index bc267bd2c3b0..1c1bf1b281cd 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h
@@ -565,10 +565,13 @@ extern const struct iwl_cfg iwl22000_2ac_cfg_hr;
extern const struct iwl_cfg iwl22000_2ac_cfg_hr_cdb;
extern const struct iwl_cfg iwl22000_2ac_cfg_jf;
extern const struct iwl_cfg iwl_ax101_cfg_qu_hr;
+extern const struct iwl_cfg iwl_ax101_cfg_qu_c0_hr_b0;
extern const struct iwl_cfg iwl_ax101_cfg_quz_hr;
extern const struct iwl_cfg iwl22000_2ax_cfg_hr;
extern const struct iwl_cfg iwl_ax200_cfg_cc;
extern const struct iwl_cfg iwl_ax201_cfg_qu_hr;
+extern const struct iwl_cfg iwl_ax201_cfg_qu_hr;
+extern const struct iwl_cfg iwl_ax201_cfg_qu_c0_hr_b0;
extern const struct iwl_cfg iwl_ax201_cfg_quz_hr;
extern const struct iwl_cfg iwl_ax1650i_cfg_quz_hr;
extern const struct iwl_cfg iwl_ax1650s_cfg_quz_hr;
@@ -580,6 +583,10 @@ extern const struct iwl_cfg iwl9461_2ac_cfg_qu_b0_jf_b0;
extern const struct iwl_cfg iwl9462_2ac_cfg_qu_b0_jf_b0;
extern const struct iwl_cfg iwl9560_2ac_cfg_qu_b0_jf_b0;
extern const struct iwl_cfg iwl9560_2ac_160_cfg_qu_b0_jf_b0;
+extern const struct iwl_cfg iwl9461_2ac_cfg_qu_c0_jf_b0;
+extern const struct iwl_cfg iwl9462_2ac_cfg_qu_c0_jf_b0;
+extern const struct iwl_cfg iwl9560_2ac_cfg_qu_c0_jf_b0;
+extern const struct iwl_cfg iwl9560_2ac_160_cfg_qu_c0_jf_b0;
extern const struct iwl_cfg killer1550i_2ac_cfg_qu_b0_jf_b0;
extern const struct iwl_cfg killer1550s_2ac_cfg_qu_b0_jf_b0;
extern const struct iwl_cfg iwl22000_2ax_cfg_jf;
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h
index 93da96a7247c..cb4c5514a556 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h
@@ -328,6 +328,8 @@ enum {
#define CSR_HW_REV_TYPE_NONE (0x00001F0)
#define CSR_HW_REV_TYPE_QNJ (0x0000360)
#define CSR_HW_REV_TYPE_QNJ_B0 (0x0000364)
+#define CSR_HW_REV_TYPE_QU_B0 (0x0000334)
+#define CSR_HW_REV_TYPE_QU_C0 (0x0000338)
#define CSR_HW_REV_TYPE_QUZ (0x0000354)
#define CSR_HW_REV_TYPE_HR_CDB (0x0000340)
#define CSR_HW_REV_TYPE_SO (0x0000370)
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
index fe645380bd2f..ea2a03d4bf55 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
@@ -1039,6 +1039,27 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
}
iwl_trans->cfg = cfg;
}
+
+ /*
+ * This is a hack to switch from Qu B0 to Qu C0. We need to
+ * do this for all cfgs that use Qu B0. All this code is in
+ * urgent need for a refactor, but for now this is the easiest
+ * thing to do to support Qu C-step.
+ */
+ if (iwl_trans->hw_rev == CSR_HW_REV_TYPE_QU_C0) {
+ if (iwl_trans->cfg == &iwl_ax101_cfg_qu_hr)
+ iwl_trans->cfg = &iwl_ax101_cfg_qu_c0_hr_b0;
+ else if (iwl_trans->cfg == &iwl_ax201_cfg_qu_hr)
+ iwl_trans->cfg = &iwl_ax201_cfg_qu_c0_hr_b0;
+ else if (iwl_trans->cfg == &iwl9461_2ac_cfg_qu_b0_jf_b0)
+ iwl_trans->cfg = &iwl9461_2ac_cfg_qu_c0_jf_b0;
+ else if (iwl_trans->cfg == &iwl9462_2ac_cfg_qu_b0_jf_b0)
+ iwl_trans->cfg = &iwl9462_2ac_cfg_qu_c0_jf_b0;
+ else if (iwl_trans->cfg == &iwl9560_2ac_cfg_qu_b0_jf_b0)
+ iwl_trans->cfg = &iwl9560_2ac_cfg_qu_c0_jf_b0;
+ else if (iwl_trans->cfg == &iwl9560_2ac_160_cfg_qu_b0_jf_b0)
+ iwl_trans->cfg = &iwl9560_2ac_160_cfg_qu_c0_jf_b0;
+ }
#endif
pci_set_drvdata(pdev, iwl_trans);
--
2.20.1
^ permalink raw reply related
* Re: [PATCH] rtw88/pci: Rearrange the memory usage for skb in RX ISR
From: Larry Finger @ 2019-07-08 18:01 UTC (permalink / raw)
To: Jian-Hong Pan, Yan-Hsuan Chuang, Kalle Valo, David S . Miller
Cc: linux-wireless, netdev, linux-kernel, linux, Daniel Drake, stable
In-Reply-To: <20190708063252.4756-1-jian-hong@endlessm.com>
On 7/8/19 1:32 AM, Jian-Hong Pan wrote:
> diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c
> index cfe05ba7280d..1bfc99ae6b84 100644
> --- a/drivers/net/wireless/realtek/rtw88/pci.c
> +++ b/drivers/net/wireless/realtek/rtw88/pci.c
> @@ -786,6 +786,15 @@ static void rtw_pci_rx_isr(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci,
> rx_desc = skb->data;
> chip->ops->query_rx_desc(rtwdev, rx_desc, &pkt_stat, &rx_status);
>
> + /* discard current skb if the new skb cannot be allocated as a
> + * new one in rx ring later
> + * */
> + new = dev_alloc_skb(RTK_PCI_RX_BUF_SIZE);
> + if (WARN(!new, "rx routine starvation\n")) {
> + new = skb;
> + goto next_rp;
This should probably be a WARN_ONCE() rather than WARN(), otherwise the logs
will be flooded once this condition triggers.
Larry
^ permalink raw reply
* Re: use exact allocation for dma coherent memory
From: Christoph Hellwig @ 2019-07-08 18:43 UTC (permalink / raw)
To: Arend Van Spriel
Cc: Christoph Hellwig, Maarten Lankhorst, Maxime Ripard, Sean Paul,
David Airlie, Daniel Vetter, Jani Nikula, Joonas Lahtinen,
Rodrigo Vivi, Ian Abbott, H Hartley Sweeten, devel, linux-s390,
Intel Linux Wireless, linux-rdma, netdev, intel-gfx,
linux-wireless, linux-kernel, dri-devel, linux-mm, iommu,
moderated list:ARM PORT, linux-media
In-Reply-To: <74eb9d99-6aa6-d1ad-e66d-6cc9c496b2f3@broadcom.com>
On Tue, Jul 02, 2019 at 11:48:44AM +0200, Arend Van Spriel wrote:
> You made me look ;-) Actually not touching my drivers so I'm off the hook.
> However, I was wondering if drivers could know so I decided to look into
> the DMA-API.txt documentation which currently states:
>
> """
> The flag parameter (dma_alloc_coherent() only) allows the caller to
> specify the ``GFP_`` flags (see kmalloc()) for the allocation (the
> implementation may choose to ignore flags that affect the location of
> the returned memory, like GFP_DMA).
> """
>
> I do expect you are going to change that description as well now that you
> are going to issue a warning on __GFP_COMP. Maybe include that in patch
> 15/16 where you introduce that warning.
Yes, that description needs an updated, even without this series.
I'll make sure it is more clear.
^ permalink raw reply
* Re: [PATCH] ath10k: work around uninitialized vht_pfr variable
From: Brian Norris @ 2019-07-08 20:34 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Kalle Valo, Miaoqing Pan, David S. Miller, Rakesh Pillai,
Balaji Pothunoori, Wen Gong, Pradeep kumar Chitrapu, Sriram R,
ath10k, linux-wireless, <netdev@vger.kernel.org>,
Linux Kernel, clang-built-linux
In-Reply-To: <20190708125050.3689133-1-arnd@arndb.de>
Hi Arnd,
On Mon, Jul 8, 2019 at 5:50 AM Arnd Bergmann <arnd@arndb.de> wrote:
>
> As clang points out, the vht_pfr is assigned to a struct member
> without being initialized in one case:
>
> drivers/net/wireless/ath/ath10k/mac.c:7528:7: error: variable 'vht_pfr' is used uninitialized whenever 'if' condition
> is false [-Werror,-Wsometimes-uninitialized]
> if (!ath10k_mac_can_set_bitrate_mask(ar, band, mask,
> ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> drivers/net/wireless/ath/ath10k/mac.c:7551:20: note: uninitialized use occurs here
> arvif->vht_pfr = vht_pfr;
> ^~~~~~~
> drivers/net/wireless/ath/ath10k/mac.c:7528:3: note: remove the 'if' if its condition is always true
> if (!ath10k_mac_can_set_bitrate_mask(ar, band, mask,
> ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> drivers/net/wireless/ath/ath10k/mac.c:7483:12: note: initialize the variable 'vht_pfr' to silence this warning
> u8 vht_pfr;
>
> Add an explicit but probably incorrect initialization here.
> I suspect we want a better fix here, but chose this approach to
> illustrate the issue.
>
> Fixes: 8b97b055dc9d ("ath10k: fix failure to set multiple fixed rate")
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---
> drivers/net/wireless/ath/ath10k/mac.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
> index e43a566eef77..0606416dc971 100644
> --- a/drivers/net/wireless/ath/ath10k/mac.c
> +++ b/drivers/net/wireless/ath/ath10k/mac.c
> @@ -7541,6 +7541,8 @@ static int ath10k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
> &vht_nss,
> true);
^^ Technically, this call to ath10k_mac_bitrate_mask_get_single_rate()
can fail to assign 'vht_pfr' as well. I can't immediately tell whether
it provably will never hit the -EINVAL case, but if we do, then you'd
have another uninitialized case.
I *believe* it shouldn't fail, since we already pre-checked the VHT
MCS lists for "exactly 1" rate. But it still seems like better code to
pre-initialize and/or add error-handling, so we don't rely on that
implicit proof.
I'm not quite sure yet what the "better" answer should be for
resolving this, but at a minimum, I think the above could be improved.
Brian
> update_bitrate_mask = false;
> + } else {
> + vht_pfr = 0;
> }
>
> mutex_lock(&ar->conf_mutex);
> --
> 2.20.0
>
^ permalink raw reply
* Re: [PATCH 4/7] mmc: sdio: Drop powered-on re-init at runtime resume and HW reset
From: Doug Anderson @ 2019-07-08 21:12 UTC (permalink / raw)
To: Ulf Hansson
Cc: Linux MMC List, Adrian Hunter, Brian Norris, Shawn Lin,
Guenter Roeck, Heiko Stuebner, Kalle Valo, Arend Van Spriel,
linux-wireless
In-Reply-To: <CAPDyKFoHzCmobCtyy-j+-4xjW0Bt1_vA5-s4vHLVN78jXJ4X-w@mail.gmail.com>
Hi,
On Mon, Jul 8, 2019 at 3:54 AM Ulf Hansson <ulf.hansson@linaro.org> wrote:
>
> On Thu, 4 Jul 2019 at 02:02, Doug Anderson <dianders@chromium.org> wrote:
> >
> > Hi,
> >
> > On Tue, Jun 18, 2019 at 8:35 AM Ulf Hansson <ulf.hansson@linaro.org> wrote:
> > >
> > > To use the so called powered-on re-initialization of an SDIO card, the
> > > power to the card must obviously have stayed on. If not, the initialization
> > > will simply fail.
> > >
> > > In the runtime suspend case, the card is always powered off. Hence, let's
> > > drop the support for powered-on re-initialization during runtime resume, as
> > > it doesn't make sense.
> > >
> > > Moreover, during a HW reset, the point is to cut the power to the card and
> > > then do fresh re-initialization. Therefore drop the support for powered-on
> > > re-initialization during HW reset.
> > >
> > > Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> > > ---
> > > drivers/mmc/core/sdio.c | 8 +-------
> > > 1 file changed, 1 insertion(+), 7 deletions(-)
> >
> > This has been on my list of things to test for a while but I never
> > quite got to it...
> >
> > ...and then, today, I spent time bisecting why the "reset"
> > functionality of miwfiex is broken on my 4.19 kernel [1]. AKA, this
> > is broken:
> >
> > cd /sys/kernel/debug/mwifiex/mlan0
> > echo 1 > reset
> >
> > I finally bisected the problem and tracked it down to commit
> > ca8971ca5753 ("mmc: dw_mmc: Prevent runtime PM suspend when SDIO IRQs
> > are enabled"), which embarrassingly has my Tested-by on it. I guess I
> > never tested the Marvell reset call. :-/
> >
> > I dug a little and found that when the Marvell code did its reset we
> > ended up getting a call to dw_mci_enable_sdio_irq(enb=0) and never saw
> > a dw_mci_enable_sdio_irq(enb=1) after. I tracked it down further and
> > found that specifically it was the call to mmc_signal_sdio_irq() in
> > mmc_sdio_power_restore() that was making the call. The call stack
> > shown for the "enb=0" call:
> >
> > [<c071a290>] (dw_mci_enable_sdio_irq) from [<c070a960>]
> > (mmc_sdio_power_restore+0x98/0xc0)
> > [<c070a960>] (mmc_sdio_power_restore) from [<c070a9b4>]
> > (mmc_sdio_reset+0x2c/0x30)
> > [<c070a9b4>] (mmc_signal_sdio_irq) from [<c06ff160>] (mmc_hw_reset+0xbc/0x138)
> > [<c06ff160>] (mmc_hw_reset) from [<bf1bbad8>]
> > (mwifiex_sdio_work+0x5d4/0x678 [mwifiex_sdio])
> > [<bf1bbad8>] (mwifiex_sdio_work [mwifiex_sdio]) from [<c0247cd0>]
> > (process_one_work+0x290/0x4b4)
> >
> > I picked your patch here (which gets rid of the call to
> > mmc_signal_sdio_irq()) and magically the problem went away because
> > there is no more call to mmc_signal_sdio_irq().
> >
> > I personally don't have lots of history about the whole
> > "powered_resume" code path. I checked and mmc_card_keep_power() was 0
> > in my test case of getting called from hw_reset, so the rest of this
> > patch doesn't affect me at all. This surprised me a little since I
> > saw "MMC_PM_KEEP_POWER" being set in mwifiex but then I realized that
> > it was only set for the duration of suspend and then cleared by the
> > core. ;-)
> >
> > I will also say that I don't have any test case or knowledge of how
> > SDIO runtime suspend/resume is supposed to work since on dw_mmc SDIO
> > cards are currently not allowed to runtime suspend anyway. ;-)
> >
> >
> > So I guess the result of all that long-winded reply is that for on
> > rk3288-veyron-jerry:
> >
> > Fixes: ca8971ca5753 ("mmc: dw_mmc: Prevent runtime PM suspend when
> > SDIO IRQs are enabled")
> > Tested-by: Douglas Anderson <dianders@chromium.org>
>
> Thanks a lot for testing and for your detailed feedback. I have
> amended the patch by adding your tags above.
Sure! I'm going to try to do some detailed testing on the next patch
too to confirm it's OK, but I have a few other tasks to get to first.
;-)
> Moreover, we seems to need this for stable as well, but I am leaving
> that to be managed as a separate task. We may even consider the hole
> series for stable, but that requires more testing first.
Sure, makes sense. We'll pick it to the Chrome OS 4.19 kernel
directly but it's usually nice to get fixes like this into stable so
everyone can benefit.
> > One last note is that, though Marvell WiFi works after a reset after
> > this commit, Marvell Bluetooth (on the same SDIO module) doesn't. I
> > guess next week it'll be another bisect...
>
> Is the Bluetooth connected to the same SDIO interface, thus the
> Bluetooth driver is an SDIO func driver?
Yes, it's a SDIO func driver connected to the same interface. So far
I've managed to confirm the problem on:
v4.4 (plus 76ae3e26ea43 mwifiex: add debugfs file for testing reset of card)
v4.9
next-20190708
...so it seems like it's not a "regression", it's just never worked.
:-P I guess I'll have to see if I can figure out what's different in
our chromeos-3.14 kernel. Ah, I see. In 3.14 we had this solution:
pr_err("Resetting card...\n");
mmc_remove_host(reset_host);
/* 200ms delay is based on experiment with sdhci controller */
mdelay(200);
reset_host->rescan_entered = 0;
mmc_add_host(reset_host);
...I think that didn't fly upstream. ...but I can confirm that this works fine:
cd /sys/bus/platform/drivers/dwmmc_rockchip
echo ff0d0000.dwmmc > unbind
sleep .5
echo ff0d0000.dwmmc > bind
...so I guess this boils down to: how does the mwifiex reset code not
behave like a full removal and re-insertion of the card? Oh, but
maybe that's obvious. We're doing all the reset / re-init from the
WiFi side of things (mwifiex_sdio_card_reset_work) but I don't think
anything is communicated to the Bluetooth side of things. Presumably
this is just totally broken for everyone? ...or am I confused?
-Doug
-Doug
^ permalink raw reply
* Re: linux-next: build failure after merge of the tip tree
From: Stephen Rothwell @ 2019-07-09 0:09 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, H. Peter Anvin, Peter Zijlstra,
Kalle Valo, Wireless
Cc: Linux Next Mailing List, Linux Kernel Mailing List,
Christian Lamparter, Jason A. Donenfeld
In-Reply-To: <20190625160432.533aa140@canb.auug.org.au>
[-- Attachment #1: Type: text/plain, Size: 2123 bytes --]
Hi all,
On Tue, 25 Jun 2019 16:04:32 +1000 Stephen Rothwell <sfr@canb.auug.org.au> wrote:
>
> After merging the tip tree, today's linux-next build (x86_64 allmodconfig)
> failed like this:
>
> drivers/net/wireless/intersil/p54/txrx.c: In function 'p54_rx_data':
> drivers/net/wireless/intersil/p54/txrx.c:386:28: error: implicit declaration of function 'ktime_get_boot_ns'; did you mean 'ktime_get_raw_ns'? [-Werror=implicit-function-declaration]
> rx_status->boottime_ns = ktime_get_boot_ns();
> ^~~~~~~~~~~~~~~~~
> ktime_get_raw_ns
>
> Caused by commit
>
> c11c75ec784e ("p54: Support boottime in scan results")
>
> from the wireless-drivers-next tree interacting with commit
>
> 9285ec4c8b61 ("timekeeping: Use proper clock specifier names in functions")
>
> from the tip tree.
>
> I have added the following merge fix patch:
>
> From: Stephen Rothwell <sfr@canb.auug.org.au>
> Date: Tue, 25 Jun 2019 15:55:36 +1000
> Subject: [PATCH] p54: fix up for ktime_get_boot_ns() name change
>
> Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
> ---
> drivers/net/wireless/intersil/p54/txrx.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/net/wireless/intersil/p54/txrx.c b/drivers/net/wireless/intersil/p54/txrx.c
> index be6968454282..873fea59894f 100644
> --- a/drivers/net/wireless/intersil/p54/txrx.c
> +++ b/drivers/net/wireless/intersil/p54/txrx.c
> @@ -383,7 +383,7 @@ static int p54_rx_data(struct p54_common *priv, struct sk_buff *skb)
>
> fc = ((struct ieee80211_hdr *)skb->data)->frame_control;
> if (ieee80211_is_probe_resp(fc) || ieee80211_is_beacon(fc))
> - rx_status->boottime_ns = ktime_get_boot_ns();
> + rx_status->boottime_ns = ktime_get_boottime_ns();
>
> if (unlikely(priv->hw->conf.flags & IEEE80211_CONF_PS))
> p54_pspoll_workaround(priv, skb);
> --
> 2.20.1
I am still getting this conflict (the commit ids may have changed).
Just a reminder in case you think Linus may need to know.
--
Cheers,
Stephen Rothwell
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* Re: linux-next: build failure after merge of the tip tree
From: Stephen Rothwell @ 2019-07-09 3:46 UTC (permalink / raw)
To: Kalle Valo, Wireless
Cc: Thomas Gleixner, Ingo Molnar, H. Peter Anvin, Peter Zijlstra,
Linux Next Mailing List, Linux Kernel Mailing List,
Christian Lamparter, Jason A. Donenfeld, David Miller, Networking
In-Reply-To: <20190625160432.533aa140@canb.auug.org.au>
[-- Attachment #1: Type: text/plain, Size: 2061 bytes --]
Hi all,
On Tue, 25 Jun 2019 16:04:32 +1000 Stephen Rothwell <sfr@canb.auug.org.au> wrote:
>
> After merging the tip tree, today's linux-next build (x86_64 allmodconfig)
> failed like this:
>
> drivers/net/wireless/intersil/p54/txrx.c: In function 'p54_rx_data':
> drivers/net/wireless/intersil/p54/txrx.c:386:28: error: implicit declaration of function 'ktime_get_boot_ns'; did you mean 'ktime_get_raw_ns'? [-Werror=implicit-function-declaration]
> rx_status->boottime_ns = ktime_get_boot_ns();
> ^~~~~~~~~~~~~~~~~
> ktime_get_raw_ns
>
> Caused by commit
>
> c11c75ec784e ("p54: Support boottime in scan results")
>
> from the wireless-drivers-next tree interacting with commit
>
> 9285ec4c8b61 ("timekeeping: Use proper clock specifier names in functions")
>
> from the tip tree.
>
> I have added the following merge fix patch:
>
> From: Stephen Rothwell <sfr@canb.auug.org.au>
> Date: Tue, 25 Jun 2019 15:55:36 +1000
> Subject: [PATCH] p54: fix up for ktime_get_boot_ns() name change
>
> Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
> ---
> drivers/net/wireless/intersil/p54/txrx.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/net/wireless/intersil/p54/txrx.c b/drivers/net/wireless/intersil/p54/txrx.c
> index be6968454282..873fea59894f 100644
> --- a/drivers/net/wireless/intersil/p54/txrx.c
> +++ b/drivers/net/wireless/intersil/p54/txrx.c
> @@ -383,7 +383,7 @@ static int p54_rx_data(struct p54_common *priv, struct sk_buff *skb)
>
> fc = ((struct ieee80211_hdr *)skb->data)->frame_control;
> if (ieee80211_is_probe_resp(fc) || ieee80211_is_beacon(fc))
> - rx_status->boottime_ns = ktime_get_boot_ns();
> + rx_status->boottime_ns = ktime_get_boottime_ns();
>
> if (unlikely(priv->hw->conf.flags & IEEE80211_CONF_PS))
> p54_pspoll_workaround(priv, skb);
This patch is now needed in the merge between the net-next tree and
Linus' tree.
--
Cheers,
Stephen Rothwell
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* [PATCH v4] ath10k: Enable MSA region dump support for WCN3990
From: Govind Singh @ 2019-07-09 5:36 UTC (permalink / raw)
To: ath10k; +Cc: linux-wireless, Govind Singh
MSA memory region caries the hw descriptors information.
Dump MSA region in core dump as this is very helpful in debugging
hw issues.
Testing: Tested on WCN3990 HW
Tested FW: WLAN.HL.3.1-00959-QCAHLSWMTPLZ-1
Signed-off-by: Govind Singh <govinds@codeaurora.org>
---
Changes from v3:
- Fixed error reported in v2.
Changes from v2:
- Rebased on top of 38faed150438 ath10k: perform crash dump collection in workqueue.
- Removed redundant msa permission call.
---
drivers/net/wireless/ath/ath10k/coredump.c | 21 +++++++
drivers/net/wireless/ath/ath10k/coredump.h | 1 +
drivers/net/wireless/ath/ath10k/qmi.c | 4 ++
drivers/net/wireless/ath/ath10k/snoc.c | 66 ++++++++++++++++++++++
drivers/net/wireless/ath/ath10k/snoc.h | 1 +
5 files changed, 93 insertions(+)
diff --git a/drivers/net/wireless/ath/ath10k/coredump.c b/drivers/net/wireless/ath/ath10k/coredump.c
index aa04fbf146e0..0ec690b49fb1 100644
--- a/drivers/net/wireless/ath/ath10k/coredump.c
+++ b/drivers/net/wireless/ath/ath10k/coredump.c
@@ -962,6 +962,19 @@ static const struct ath10k_mem_region qca4019_hw10_mem_regions[] = {
},
};
+static const struct ath10k_mem_region wcn399x_hw10_mem_regions[] = {
+ {
+ /* MSA region start is not fixed, hence it is assigned at runtime */
+ .type = ATH10K_MEM_REGION_TYPE_MSA,
+ .len = 0x100000,
+ .name = "DRAM",
+ .section_table = {
+ .sections = NULL,
+ .size = 0,
+ },
+ },
+};
+
static const struct ath10k_hw_mem_layout hw_mem_layouts[] = {
{
.hw_id = QCA6174_HW_1_0_VERSION,
@@ -1059,6 +1072,14 @@ static const struct ath10k_hw_mem_layout hw_mem_layouts[] = {
.size = ARRAY_SIZE(qca4019_hw10_mem_regions),
},
},
+ {
+ .hw_id = WCN3990_HW_1_0_DEV_VERSION,
+ .hw_rev = ATH10K_HW_WCN3990,
+ .region_table = {
+ .regions = wcn399x_hw10_mem_regions,
+ .size = ARRAY_SIZE(wcn399x_hw10_mem_regions),
+ },
+ },
};
static u32 ath10k_coredump_get_ramdump_size(struct ath10k *ar)
diff --git a/drivers/net/wireless/ath/ath10k/coredump.h b/drivers/net/wireless/ath/ath10k/coredump.h
index 5dac653e1649..9802e90483f4 100644
--- a/drivers/net/wireless/ath/ath10k/coredump.h
+++ b/drivers/net/wireless/ath/ath10k/coredump.h
@@ -126,6 +126,7 @@ enum ath10k_mem_region_type {
ATH10K_MEM_REGION_TYPE_IRAM2 = 5,
ATH10K_MEM_REGION_TYPE_IOSRAM = 6,
ATH10K_MEM_REGION_TYPE_IOREG = 7,
+ ATH10K_MEM_REGION_TYPE_MSA = 8,
};
/* Define a section of the region which should be copied. As not all parts
diff --git a/drivers/net/wireless/ath/ath10k/qmi.c b/drivers/net/wireless/ath/ath10k/qmi.c
index ba8f5a8f83d1..8eb0f0f0d3a7 100644
--- a/drivers/net/wireless/ath/ath10k/qmi.c
+++ b/drivers/net/wireless/ath/ath10k/qmi.c
@@ -817,9 +817,13 @@ ath10k_qmi_driver_event_post(struct ath10k_qmi *qmi,
static void ath10k_qmi_event_server_exit(struct ath10k_qmi *qmi)
{
struct ath10k *ar = qmi->ar;
+ struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
ath10k_qmi_remove_msa_permission(qmi);
ath10k_core_free_board_files(ar);
+ if (!test_bit(ATH10K_SNOC_FLAG_UNREGISTERING, &ar_snoc->flags))
+ ath10k_snoc_fw_crashed_dump(ar);
+
ath10k_snoc_fw_indication(ar, ATH10K_QMI_EVENT_FW_DOWN_IND);
ath10k_dbg(ar, ATH10K_DBG_QMI, "wifi fw qmi service disconnected\n");
}
diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c
index 0be12996beba..6c362c928e4e 100644
--- a/drivers/net/wireless/ath/ath10k/snoc.c
+++ b/drivers/net/wireless/ath/ath10k/snoc.c
@@ -24,6 +24,7 @@
#include <linux/regulator/consumer.h>
#include "ce.h"
+#include "coredump.h"
#include "debug.h"
#include "hif.h"
#include "htc.h"
@@ -1586,6 +1587,71 @@ static int ath10k_hw_power_off(struct ath10k *ar)
return ret;
}
+static void ath10k_msa_dump_memory(struct ath10k *ar,
+ struct ath10k_fw_crash_data *crash_data)
+{
+ struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
+ const struct ath10k_hw_mem_layout *mem_layout;
+ const struct ath10k_mem_region *current_region;
+ struct ath10k_dump_ram_data_hdr *hdr;
+ size_t buf_len;
+ u8 *buf;
+
+ if (!crash_data && !crash_data->ramdump_buf)
+ return;
+
+ mem_layout = ath10k_coredump_get_mem_layout(ar);
+ if (!mem_layout)
+ return;
+
+ current_region = &mem_layout->region_table.regions[0];
+
+ buf = crash_data->ramdump_buf;
+ buf_len = crash_data->ramdump_buf_len;
+ memset(buf, 0, buf_len);
+
+ /* Reserve space for the header. */
+ hdr = (void *)buf;
+ buf += sizeof(*hdr);
+ buf_len -= sizeof(*hdr);
+
+ hdr->region_type = cpu_to_le32(current_region->type);
+ hdr->start = cpu_to_le32((unsigned long)ar_snoc->qmi->msa_va);
+ hdr->length = cpu_to_le32(ar_snoc->qmi->msa_mem_size);
+
+ if (current_region->len < ar_snoc->qmi->msa_mem_size) {
+ memcpy(buf, ar_snoc->qmi->msa_va, current_region->len);
+ ath10k_warn(ar, "msa dump length is less than msa size %x, %x\n",
+ current_region->len, ar_snoc->qmi->msa_mem_size);
+ } else {
+ memcpy(buf, ar_snoc->qmi->msa_va, ar_snoc->qmi->msa_mem_size);
+ }
+}
+
+void ath10k_snoc_fw_crashed_dump(struct ath10k *ar)
+{
+ struct ath10k_fw_crash_data *crash_data;
+ char guid[UUID_STRING_LEN + 1];
+
+ mutex_lock(&ar->dump_mutex);
+
+ spin_lock_bh(&ar->data_lock);
+ ar->stats.fw_crash_counter++;
+ spin_unlock_bh(&ar->data_lock);
+
+ crash_data = ath10k_coredump_new(ar);
+
+ if (crash_data)
+ scnprintf(guid, sizeof(guid), "%pUl", &crash_data->guid);
+ else
+ scnprintf(guid, sizeof(guid), "n/a");
+
+ ath10k_err(ar, "firmware crashed! (guid %s)\n", guid);
+ ath10k_print_driver_info(ar);
+ ath10k_msa_dump_memory(ar, crash_data);
+ mutex_unlock(&ar->dump_mutex);
+}
+
static const struct of_device_id ath10k_snoc_dt_match[] = {
{ .compatible = "qcom,wcn3990-wifi",
.data = &drv_priv,
diff --git a/drivers/net/wireless/ath/ath10k/snoc.h b/drivers/net/wireless/ath/ath10k/snoc.h
index 25383de8f17d..6d28a6290a94 100644
--- a/drivers/net/wireless/ath/ath10k/snoc.h
+++ b/drivers/net/wireless/ath/ath10k/snoc.h
@@ -101,5 +101,6 @@ static inline struct ath10k_snoc *ath10k_snoc_priv(struct ath10k *ar)
}
int ath10k_snoc_fw_indication(struct ath10k *ar, u64 type);
+void ath10k_snoc_fw_crashed_dump(struct ath10k *ar);
#endif /* _SNOC_H_ */
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply related
* Re: [PATCH 1/3] mt76: usb: fix endian in mt76u_copy
From: Stanislaw Gruszka @ 2019-07-09 10:06 UTC (permalink / raw)
To: linux-wireless; +Cc: Felix Fietkau, Lorenzo Bianconi
In-Reply-To: <1562079961-15527-2-git-send-email-sgruszka@redhat.com>
On Tue, Jul 02, 2019 at 05:05:59PM +0200, Stanislaw Gruszka wrote:
> In contrast to mt76_wr() which we use to program registers,
> on mt76_wr_copy() we should not change endian of the data.
>
> Fixes: b40b15e1521f ("mt76: add usb support to mt76 layer")
> Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
> ---
> drivers/net/wireless/mediatek/mt76/usb.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c
> index 87ecbe290f99..db90ec6b8775 100644
> --- a/drivers/net/wireless/mediatek/mt76/usb.c
> +++ b/drivers/net/wireless/mediatek/mt76/usb.c
> @@ -165,11 +165,11 @@ static void mt76u_copy(struct mt76_dev *dev, u32 offset,
>
> mutex_lock(&usb->usb_ctrl_mtx);
> for (i = 0; i < DIV_ROUND_UP(len, 4); i++) {
> - put_unaligned_le32(val[i], usb->data);
> + put_unaligned(val[i], usb->data);
This is bug as put_unaligned() use size based second argument
pointer type, correct version should looks like this:
put_unaligned(val[i], (u32 *) usb->data);
Stanislaw
^ permalink raw reply
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