Loading drivers/net/wireless/ath/wil6210/cfg80211.c +325 −0 Original line number Diff line number Diff line Loading @@ -53,6 +53,49 @@ static struct ieee80211_channel wil_60ghz_channels[] = { /* channel 4 not supported yet */ }; enum wil_nl_60g_cmd_type { NL_60G_CMD_FW_WMI, NL_60G_CMD_DEBUG, NL_60G_CMD_STATISTICS, NL_60G_CMD_REGISTER, }; enum wil_nl_60g_evt_type { NL_60G_EVT_DRIVER_ERROR, NL_60G_EVT_FW_ERROR, NL_60G_EVT_FW_WMI, NL_60G_EVT_DRIVER_SHUTOWN, NL_60G_EVT_DRIVER_DEBUG_EVENT, }; enum wil_nl_60g_debug_cmd { NL_60G_DBG_FORCE_WMI_SEND, }; struct wil_nl_60g_send_receive_wmi { u32 cmd_id; /* enum wmi_command_id or enum wmi_event_id */ u8 reserved[2]; u8 dev_id; /* mid */ u16 buf_len; u8 buf[0]; } __packed; struct wil_nl_60g_event { u32 evt_type; /* wil_nl_60g_evt_type */ u32 buf_len; u8 reserved[9]; u8 buf[0]; } __packed; struct wil_nl_60g_debug { /* NL_60G_CMD_DEBUG */ u32 cmd_id; /* wil_nl_60g_debug_cmd */ } __packed; struct wil_nl_60g_debug_force_wmi { struct wil_nl_60g_debug hdr; u32 enable; } __packed; /* Vendor id to be used in vendor specific command and events * to user space. * NOTE: The authoritative place for definition of QCA_NL80211_VENDOR_ID, Loading @@ -68,6 +111,8 @@ static struct ieee80211_channel wil_60ghz_channels[] = { enum qca_wlan_vendor_attr_wil { QCA_ATTR_MAC_ADDR = 6, QCA_ATTR_FEATURE_FLAGS = 7, QCA_ATTR_TEST = 8, QCA_ATTR_PAD = 13, QCA_ATTR_TSF = 29, QCA_ATTR_DMG_RF_SECTOR_INDEX = 30, Loading @@ -79,6 +124,9 @@ enum qca_wlan_vendor_attr_wil { QCA_ATTR_WIL_MAX, }; #define WIL_ATTR_60G_CMD_TYPE QCA_ATTR_FEATURE_FLAGS #define WIL_ATTR_60G_BUF QCA_ATTR_TEST enum qca_wlan_vendor_attr_dmg_rf_sector_type { QCA_ATTR_DMG_RF_SECTOR_TYPE_RX, QCA_ATTR_DMG_RF_SECTOR_TYPE_TX, Loading Loading @@ -135,7 +183,14 @@ nla_policy wil_rf_sector_cfg_policy[QCA_ATTR_DMG_RF_SECTOR_CFG_MAX + 1] = { [QCA_ATTR_DMG_RF_SECTOR_CFG_DTYPE_X16] = { .type = NLA_U32 }, }; static const struct nla_policy wil_nl_60g_policy[QCA_ATTR_WIL_MAX + 1] = { [WIL_ATTR_60G_CMD_TYPE] = { .type = NLA_U32 }, [WIL_ATTR_60G_BUF] = { .type = NLA_BINARY }, }; enum qca_nl80211_vendor_subcmds { QCA_NL80211_VENDOR_SUBCMD_UNSPEC = 0, QCA_NL80211_VENDOR_SUBCMD_LOC_GET_CAPA = 128, QCA_NL80211_VENDOR_SUBCMD_FTM_START_SESSION = 129, QCA_NL80211_VENDOR_SUBCMD_FTM_ABORT_SESSION = 130, Loading Loading @@ -167,6 +222,8 @@ static int wil_rf_sector_set_selected(struct wiphy *wiphy, static int wil_brp_set_ant_limit(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len); static int wil_nl_60g_handle_cmd(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len); /* vendor specific commands */ static const struct wiphy_vendor_command wil_nl80211_vendor_commands[] = { { Loading Loading @@ -248,6 +305,13 @@ static const struct wiphy_vendor_command wil_nl80211_vendor_commands[] = { WIPHY_VENDOR_CMD_NEED_RUNNING, .doit = wil_brp_set_ant_limit }, { .info.vendor_id = QCA_NL80211_VENDOR_ID, .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_UNSPEC, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, .doit = wil_nl_60g_handle_cmd }, }; /* vendor specific events */ Loading @@ -264,6 +328,10 @@ static const struct nl80211_vendor_cmd_info wil_nl80211_vendor_events[] = { .vendor_id = QCA_NL80211_VENDOR_ID, .subcmd = QCA_NL80211_VENDOR_SUBCMD_AOA_MEAS_RESULT }, [QCA_EVENT_UNSPEC_INDEX] = { .vendor_id = QCA_NL80211_VENDOR_ID, .subcmd = QCA_NL80211_VENDOR_SUBCMD_UNSPEC }, }; static struct ieee80211_supported_band wil_band_60ghz = { Loading Loading @@ -356,6 +424,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) { Loading Loading @@ -1103,6 +1251,16 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, } conn.channel = ch - 1; if (test_bit(WMI_FW_CAPABILITY_CHANNEL_BONDING, wil->fw_capabilities)) if (wil->force_edmg_channel) { rc = wil_spec2wmi_ch(wil->force_edmg_channel, &conn.edmg_channel); if (rc) wil_err(wil, "wmi channel for channel %d not found", wil->force_edmg_channel); } ether_addr_copy(conn.bssid, bss->bssid); ether_addr_copy(conn.dst_mac, bss->bssid); Loading Loading @@ -2965,3 +3123,170 @@ static int wil_brp_set_ant_limit(struct wiphy *wiphy, struct wireless_dev *wdev, return wil_brp_wmi_set_ant_limit(wil, vif->mid, cid, limit_mode, antenna_num_limit); } static int wil_nl_60g_handle_cmd(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len) { struct wil6210_priv *wil = wdev_to_wil(wdev); struct nlattr *tb[QCA_ATTR_WIL_MAX + 1]; struct wil_nl_60g_send_receive_wmi *cmd; struct wil_nl_60g_debug_force_wmi debug_force_wmi; int rc, len; u32 wil_nl_60g_cmd_type, publish; rc = nla_parse(tb, QCA_ATTR_WIL_MAX, data, data_len, wil_nl_60g_policy, NULL); if (rc) { wil_err(wil, "Invalid nl_60g_cmd ATTR\n"); return rc; } if (!tb[WIL_ATTR_60G_CMD_TYPE]) { wil_err(wil, "Invalid nl_60g_cmd type\n"); return -EINVAL; } wil_nl_60g_cmd_type = nla_get_u32(tb[WIL_ATTR_60G_CMD_TYPE]); switch (wil_nl_60g_cmd_type) { case NL_60G_CMD_REGISTER: if (!tb[WIL_ATTR_60G_BUF]) { wil_err(wil, "Invalid nl_60g_cmd spec\n"); return -EINVAL; } len = nla_len(tb[WIL_ATTR_60G_BUF]); if (len != sizeof(publish)) { wil_err(wil, "cmd buffer wrong len %d\n", len); return -EINVAL; } memcpy(&publish, nla_data(tb[WIL_ATTR_60G_BUF]), len); wil->publish_nl_evt = publish; wil_dbg_wmi(wil, "Publish wmi event %s\n", publish ? "enabled" : "disabled"); break; case NL_60G_CMD_DEBUG: if (!tb[WIL_ATTR_60G_BUF]) { wil_err(wil, "Invalid nl_60g_cmd spec\n"); return -EINVAL; } len = nla_len(tb[WIL_ATTR_60G_BUF]); if (len < sizeof(struct wil_nl_60g_debug)) { wil_err(wil, "cmd buffer too short %d\n", len); return -EINVAL; } memcpy(&debug_force_wmi, nla_data(tb[WIL_ATTR_60G_BUF]), sizeof(struct wil_nl_60g_debug)); switch (debug_force_wmi.hdr.cmd_id) { case NL_60G_DBG_FORCE_WMI_SEND: if (len != sizeof(debug_force_wmi)) { wil_err(wil, "cmd buffer wrong len %d\n", len); return -EINVAL; } memcpy(&debug_force_wmi, nla_data(tb[WIL_ATTR_60G_BUF]), sizeof(debug_force_wmi)); wil->force_wmi_send = debug_force_wmi.enable; wil_dbg_wmi(wil, "force sending wmi commands %d\n", wil->force_wmi_send); break; default: rc = -EINVAL; wil_err(wil, "invalid debug_cmd id %d", debug_force_wmi.hdr.cmd_id); } break; case NL_60G_CMD_FW_WMI: if (!tb[WIL_ATTR_60G_BUF]) { wil_err(wil, "Invalid nl_60g_cmd spec\n"); return -EINVAL; } len = nla_len(tb[WIL_ATTR_60G_BUF]); if (len < offsetof(struct wil_nl_60g_send_receive_wmi, buf)) { wil_err(wil, "wmi cmd buffer too small\n"); return -EINVAL; } cmd = kmalloc(len, GFP_KERNEL); if (!cmd) return -ENOMEM; memcpy(cmd, nla_data(tb[WIL_ATTR_60G_BUF]), (unsigned int)len); wil_dbg_wmi(wil, "sending user-space command (0x%04x) [%d]\n", cmd->cmd_id, cmd->buf_len); if (wil->force_wmi_send) rc = wmi_force_send(wil, cmd->cmd_id, cmd->dev_id, cmd->buf, cmd->buf_len); else rc = wmi_send(wil, cmd->cmd_id, cmd->dev_id, cmd->buf, cmd->buf_len); kfree(cmd); break; default: rc = -EINVAL; wil_err(wil, "invalid nl_60g_cmd type %d", wil_nl_60g_cmd_type); } return rc; } void wil_nl_60g_receive_wmi_evt(struct wil6210_priv *wil, u8 *cmd, int len) { struct sk_buff *vendor_event = NULL; struct wil_nl_60g_event *evt; struct wil_nl_60g_send_receive_wmi *wmi_buf; struct wmi_cmd_hdr *wmi_hdr = (struct wmi_cmd_hdr *)cmd; int data_len; if (!wil->publish_nl_evt) return; wil_dbg_wmi(wil, "report wmi event to user-space (0x%04x) [%d]\n", le16_to_cpu(wmi_hdr->command_id), len); data_len = len - sizeof(struct wmi_cmd_hdr); evt = kzalloc(sizeof(*evt) + sizeof(*wmi_buf) + data_len, GFP_KERNEL); if (!evt) return; evt->evt_type = NL_60G_EVT_FW_WMI; evt->buf_len = sizeof(*wmi_buf) + data_len; wmi_buf = (struct wil_nl_60g_send_receive_wmi *)evt->buf; wmi_buf->cmd_id = le16_to_cpu(wmi_hdr->command_id); wmi_buf->dev_id = wmi_hdr->mid; wmi_buf->buf_len = data_len; memcpy(wmi_buf->buf, cmd + sizeof(struct wmi_cmd_hdr), data_len); vendor_event = cfg80211_vendor_event_alloc(wil_to_wiphy(wil), NULL, data_len + 4 + NLMSG_HDRLEN + sizeof(*evt) + sizeof(*wmi_buf), QCA_EVENT_UNSPEC_INDEX, GFP_KERNEL); if (!vendor_event) goto out; if (nla_put(vendor_event, WIL_ATTR_60G_BUF, sizeof(*evt) + sizeof(*wmi_buf) + data_len, evt)) { wil_err(wil, "failed to fill WIL_ATTR_60G_BUF\n"); goto out; } cfg80211_vendor_event(vendor_event, GFP_KERNEL); out: kfree(evt); } drivers/net/wireless/ath/wil6210/debugfs.c +6 −16 Original line number Diff line number Diff line // SPDX-License-Identifier: ISC /* * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. * Copyright (c) 2018, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. */ #include <linux/module.h> Loading Loading @@ -954,7 +943,7 @@ static ssize_t wil_read_pmccfg(struct file *file, char __user *user_buf, " - \"alloc <num descriptors> <descriptor_size>\" to allocate pmc\n" " - \"free\" to free memory allocated for pmc\n"; sprintf(text, "Last command status: %d\n\n%s", snprintf(text, sizeof(text), "Last command status: %d\n\n%s", wil_pmc_last_cmd_status(wil), help); Loading Loading @@ -2526,6 +2515,7 @@ static const struct dbg_off dbg_wil_off[] = { WIL_FIELD(tx_status_ring_order, 0644, doff_u32), WIL_FIELD(rx_buff_id_count, 0644, doff_u32), WIL_FIELD(amsdu_en, 0644, doff_u8), WIL_FIELD(force_edmg_channel, 0644, doff_u8), {}, }; Loading drivers/net/wireless/ath/wil6210/ftm.h +1 −0 Original line number Diff line number Diff line Loading @@ -401,6 +401,7 @@ enum qca_events_index { QCA_EVENT_FTM_MEAS_RESULT_INDEX, QCA_EVENT_FTM_SESSION_DONE_INDEX, QCA_EVENT_AOA_MEAS_RESULT_INDEX, QCA_EVENT_UNSPEC_INDEX, }; /* measurement parameters. Specified for each peer as part Loading drivers/net/wireless/ath/wil6210/main.c +7 −4 Original line number Diff line number Diff line Loading @@ -212,6 +212,7 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) struct net_device *ndev = vif_to_ndev(vif); struct wireless_dev *wdev = vif_to_wdev(vif); struct wil_sta_info *sta = &wil->sta[cid]; int min_ring_id = wil_get_min_tx_ring_id(wil); might_sleep(); wil_dbg_misc(wil, "disconnect_cid: CID %d, MID %d, status %d\n", Loading Loading @@ -263,7 +264,7 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) memset(sta->tid_crypto_rx, 0, sizeof(sta->tid_crypto_rx)); memset(&sta->group_crypto_rx, 0, sizeof(sta->group_crypto_rx)); /* release vrings */ for (i = 0; i < ARRAY_SIZE(wil->ring_tx); i++) { for (i = min_ring_id; i < ARRAY_SIZE(wil->ring_tx); i++) { if (wil->ring2cid_tid[i][0] == cid) wil_ring_fini_tx(wil, i); } Loading Loading @@ -594,8 +595,10 @@ int wil_priv_init(struct wil6210_priv *wil) wil->sta[i].mid = U8_MAX; } for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) { spin_lock_init(&wil->ring_tx_data[i].lock); wil->ring2cid_tid[i][0] = WIL6210_MAX_CID; } mutex_init(&wil->mutex); mutex_init(&wil->vif_mutex); Loading Loading @@ -643,8 +646,6 @@ int wil_priv_init(struct wil6210_priv *wil) /* edma configuration can be updated via debugfs before allocation */ wil->num_rx_status_rings = WIL_DEFAULT_NUM_RX_STATUS_RINGS; wil->use_compressed_rx_status = true; wil->use_rx_hw_reordering = true; wil->tx_status_ring_order = WIL_TX_SRING_SIZE_ORDER_DEFAULT; /* Rx status ring size should be bigger than the number of RX buffers Loading Loading @@ -1540,6 +1541,8 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) wmi_event_flush(wil); wil->force_wmi_send = false; flush_workqueue(wil->wq_service); flush_workqueue(wil->wmi_wq); Loading drivers/net/wireless/ath/wil6210/pcie_bus.c +1 −0 Original line number Diff line number Diff line Loading @@ -97,6 +97,7 @@ int wil_set_capabilities(struct wil6210_priv *wil) set_bit(hw_capa_no_flash, wil->hw_capa); wil->use_enhanced_dma_hw = true; wil->use_rx_hw_reordering = true; wil->use_compressed_rx_status = true; wil_fw_name = ftm_mode ? WIL_FW_NAME_FTM_TALYN : WIL_FW_NAME_TALYN; if (wil_fw_verify_file_exists(wil, wil_fw_name)) Loading Loading
drivers/net/wireless/ath/wil6210/cfg80211.c +325 −0 Original line number Diff line number Diff line Loading @@ -53,6 +53,49 @@ static struct ieee80211_channel wil_60ghz_channels[] = { /* channel 4 not supported yet */ }; enum wil_nl_60g_cmd_type { NL_60G_CMD_FW_WMI, NL_60G_CMD_DEBUG, NL_60G_CMD_STATISTICS, NL_60G_CMD_REGISTER, }; enum wil_nl_60g_evt_type { NL_60G_EVT_DRIVER_ERROR, NL_60G_EVT_FW_ERROR, NL_60G_EVT_FW_WMI, NL_60G_EVT_DRIVER_SHUTOWN, NL_60G_EVT_DRIVER_DEBUG_EVENT, }; enum wil_nl_60g_debug_cmd { NL_60G_DBG_FORCE_WMI_SEND, }; struct wil_nl_60g_send_receive_wmi { u32 cmd_id; /* enum wmi_command_id or enum wmi_event_id */ u8 reserved[2]; u8 dev_id; /* mid */ u16 buf_len; u8 buf[0]; } __packed; struct wil_nl_60g_event { u32 evt_type; /* wil_nl_60g_evt_type */ u32 buf_len; u8 reserved[9]; u8 buf[0]; } __packed; struct wil_nl_60g_debug { /* NL_60G_CMD_DEBUG */ u32 cmd_id; /* wil_nl_60g_debug_cmd */ } __packed; struct wil_nl_60g_debug_force_wmi { struct wil_nl_60g_debug hdr; u32 enable; } __packed; /* Vendor id to be used in vendor specific command and events * to user space. * NOTE: The authoritative place for definition of QCA_NL80211_VENDOR_ID, Loading @@ -68,6 +111,8 @@ static struct ieee80211_channel wil_60ghz_channels[] = { enum qca_wlan_vendor_attr_wil { QCA_ATTR_MAC_ADDR = 6, QCA_ATTR_FEATURE_FLAGS = 7, QCA_ATTR_TEST = 8, QCA_ATTR_PAD = 13, QCA_ATTR_TSF = 29, QCA_ATTR_DMG_RF_SECTOR_INDEX = 30, Loading @@ -79,6 +124,9 @@ enum qca_wlan_vendor_attr_wil { QCA_ATTR_WIL_MAX, }; #define WIL_ATTR_60G_CMD_TYPE QCA_ATTR_FEATURE_FLAGS #define WIL_ATTR_60G_BUF QCA_ATTR_TEST enum qca_wlan_vendor_attr_dmg_rf_sector_type { QCA_ATTR_DMG_RF_SECTOR_TYPE_RX, QCA_ATTR_DMG_RF_SECTOR_TYPE_TX, Loading Loading @@ -135,7 +183,14 @@ nla_policy wil_rf_sector_cfg_policy[QCA_ATTR_DMG_RF_SECTOR_CFG_MAX + 1] = { [QCA_ATTR_DMG_RF_SECTOR_CFG_DTYPE_X16] = { .type = NLA_U32 }, }; static const struct nla_policy wil_nl_60g_policy[QCA_ATTR_WIL_MAX + 1] = { [WIL_ATTR_60G_CMD_TYPE] = { .type = NLA_U32 }, [WIL_ATTR_60G_BUF] = { .type = NLA_BINARY }, }; enum qca_nl80211_vendor_subcmds { QCA_NL80211_VENDOR_SUBCMD_UNSPEC = 0, QCA_NL80211_VENDOR_SUBCMD_LOC_GET_CAPA = 128, QCA_NL80211_VENDOR_SUBCMD_FTM_START_SESSION = 129, QCA_NL80211_VENDOR_SUBCMD_FTM_ABORT_SESSION = 130, Loading Loading @@ -167,6 +222,8 @@ static int wil_rf_sector_set_selected(struct wiphy *wiphy, static int wil_brp_set_ant_limit(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len); static int wil_nl_60g_handle_cmd(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len); /* vendor specific commands */ static const struct wiphy_vendor_command wil_nl80211_vendor_commands[] = { { Loading Loading @@ -248,6 +305,13 @@ static const struct wiphy_vendor_command wil_nl80211_vendor_commands[] = { WIPHY_VENDOR_CMD_NEED_RUNNING, .doit = wil_brp_set_ant_limit }, { .info.vendor_id = QCA_NL80211_VENDOR_ID, .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_UNSPEC, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, .doit = wil_nl_60g_handle_cmd }, }; /* vendor specific events */ Loading @@ -264,6 +328,10 @@ static const struct nl80211_vendor_cmd_info wil_nl80211_vendor_events[] = { .vendor_id = QCA_NL80211_VENDOR_ID, .subcmd = QCA_NL80211_VENDOR_SUBCMD_AOA_MEAS_RESULT }, [QCA_EVENT_UNSPEC_INDEX] = { .vendor_id = QCA_NL80211_VENDOR_ID, .subcmd = QCA_NL80211_VENDOR_SUBCMD_UNSPEC }, }; static struct ieee80211_supported_band wil_band_60ghz = { Loading Loading @@ -356,6 +424,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) { Loading Loading @@ -1103,6 +1251,16 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, } conn.channel = ch - 1; if (test_bit(WMI_FW_CAPABILITY_CHANNEL_BONDING, wil->fw_capabilities)) if (wil->force_edmg_channel) { rc = wil_spec2wmi_ch(wil->force_edmg_channel, &conn.edmg_channel); if (rc) wil_err(wil, "wmi channel for channel %d not found", wil->force_edmg_channel); } ether_addr_copy(conn.bssid, bss->bssid); ether_addr_copy(conn.dst_mac, bss->bssid); Loading Loading @@ -2965,3 +3123,170 @@ static int wil_brp_set_ant_limit(struct wiphy *wiphy, struct wireless_dev *wdev, return wil_brp_wmi_set_ant_limit(wil, vif->mid, cid, limit_mode, antenna_num_limit); } static int wil_nl_60g_handle_cmd(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len) { struct wil6210_priv *wil = wdev_to_wil(wdev); struct nlattr *tb[QCA_ATTR_WIL_MAX + 1]; struct wil_nl_60g_send_receive_wmi *cmd; struct wil_nl_60g_debug_force_wmi debug_force_wmi; int rc, len; u32 wil_nl_60g_cmd_type, publish; rc = nla_parse(tb, QCA_ATTR_WIL_MAX, data, data_len, wil_nl_60g_policy, NULL); if (rc) { wil_err(wil, "Invalid nl_60g_cmd ATTR\n"); return rc; } if (!tb[WIL_ATTR_60G_CMD_TYPE]) { wil_err(wil, "Invalid nl_60g_cmd type\n"); return -EINVAL; } wil_nl_60g_cmd_type = nla_get_u32(tb[WIL_ATTR_60G_CMD_TYPE]); switch (wil_nl_60g_cmd_type) { case NL_60G_CMD_REGISTER: if (!tb[WIL_ATTR_60G_BUF]) { wil_err(wil, "Invalid nl_60g_cmd spec\n"); return -EINVAL; } len = nla_len(tb[WIL_ATTR_60G_BUF]); if (len != sizeof(publish)) { wil_err(wil, "cmd buffer wrong len %d\n", len); return -EINVAL; } memcpy(&publish, nla_data(tb[WIL_ATTR_60G_BUF]), len); wil->publish_nl_evt = publish; wil_dbg_wmi(wil, "Publish wmi event %s\n", publish ? "enabled" : "disabled"); break; case NL_60G_CMD_DEBUG: if (!tb[WIL_ATTR_60G_BUF]) { wil_err(wil, "Invalid nl_60g_cmd spec\n"); return -EINVAL; } len = nla_len(tb[WIL_ATTR_60G_BUF]); if (len < sizeof(struct wil_nl_60g_debug)) { wil_err(wil, "cmd buffer too short %d\n", len); return -EINVAL; } memcpy(&debug_force_wmi, nla_data(tb[WIL_ATTR_60G_BUF]), sizeof(struct wil_nl_60g_debug)); switch (debug_force_wmi.hdr.cmd_id) { case NL_60G_DBG_FORCE_WMI_SEND: if (len != sizeof(debug_force_wmi)) { wil_err(wil, "cmd buffer wrong len %d\n", len); return -EINVAL; } memcpy(&debug_force_wmi, nla_data(tb[WIL_ATTR_60G_BUF]), sizeof(debug_force_wmi)); wil->force_wmi_send = debug_force_wmi.enable; wil_dbg_wmi(wil, "force sending wmi commands %d\n", wil->force_wmi_send); break; default: rc = -EINVAL; wil_err(wil, "invalid debug_cmd id %d", debug_force_wmi.hdr.cmd_id); } break; case NL_60G_CMD_FW_WMI: if (!tb[WIL_ATTR_60G_BUF]) { wil_err(wil, "Invalid nl_60g_cmd spec\n"); return -EINVAL; } len = nla_len(tb[WIL_ATTR_60G_BUF]); if (len < offsetof(struct wil_nl_60g_send_receive_wmi, buf)) { wil_err(wil, "wmi cmd buffer too small\n"); return -EINVAL; } cmd = kmalloc(len, GFP_KERNEL); if (!cmd) return -ENOMEM; memcpy(cmd, nla_data(tb[WIL_ATTR_60G_BUF]), (unsigned int)len); wil_dbg_wmi(wil, "sending user-space command (0x%04x) [%d]\n", cmd->cmd_id, cmd->buf_len); if (wil->force_wmi_send) rc = wmi_force_send(wil, cmd->cmd_id, cmd->dev_id, cmd->buf, cmd->buf_len); else rc = wmi_send(wil, cmd->cmd_id, cmd->dev_id, cmd->buf, cmd->buf_len); kfree(cmd); break; default: rc = -EINVAL; wil_err(wil, "invalid nl_60g_cmd type %d", wil_nl_60g_cmd_type); } return rc; } void wil_nl_60g_receive_wmi_evt(struct wil6210_priv *wil, u8 *cmd, int len) { struct sk_buff *vendor_event = NULL; struct wil_nl_60g_event *evt; struct wil_nl_60g_send_receive_wmi *wmi_buf; struct wmi_cmd_hdr *wmi_hdr = (struct wmi_cmd_hdr *)cmd; int data_len; if (!wil->publish_nl_evt) return; wil_dbg_wmi(wil, "report wmi event to user-space (0x%04x) [%d]\n", le16_to_cpu(wmi_hdr->command_id), len); data_len = len - sizeof(struct wmi_cmd_hdr); evt = kzalloc(sizeof(*evt) + sizeof(*wmi_buf) + data_len, GFP_KERNEL); if (!evt) return; evt->evt_type = NL_60G_EVT_FW_WMI; evt->buf_len = sizeof(*wmi_buf) + data_len; wmi_buf = (struct wil_nl_60g_send_receive_wmi *)evt->buf; wmi_buf->cmd_id = le16_to_cpu(wmi_hdr->command_id); wmi_buf->dev_id = wmi_hdr->mid; wmi_buf->buf_len = data_len; memcpy(wmi_buf->buf, cmd + sizeof(struct wmi_cmd_hdr), data_len); vendor_event = cfg80211_vendor_event_alloc(wil_to_wiphy(wil), NULL, data_len + 4 + NLMSG_HDRLEN + sizeof(*evt) + sizeof(*wmi_buf), QCA_EVENT_UNSPEC_INDEX, GFP_KERNEL); if (!vendor_event) goto out; if (nla_put(vendor_event, WIL_ATTR_60G_BUF, sizeof(*evt) + sizeof(*wmi_buf) + data_len, evt)) { wil_err(wil, "failed to fill WIL_ATTR_60G_BUF\n"); goto out; } cfg80211_vendor_event(vendor_event, GFP_KERNEL); out: kfree(evt); }
drivers/net/wireless/ath/wil6210/debugfs.c +6 −16 Original line number Diff line number Diff line // SPDX-License-Identifier: ISC /* * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. * Copyright (c) 2018, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. */ #include <linux/module.h> Loading Loading @@ -954,7 +943,7 @@ static ssize_t wil_read_pmccfg(struct file *file, char __user *user_buf, " - \"alloc <num descriptors> <descriptor_size>\" to allocate pmc\n" " - \"free\" to free memory allocated for pmc\n"; sprintf(text, "Last command status: %d\n\n%s", snprintf(text, sizeof(text), "Last command status: %d\n\n%s", wil_pmc_last_cmd_status(wil), help); Loading Loading @@ -2526,6 +2515,7 @@ static const struct dbg_off dbg_wil_off[] = { WIL_FIELD(tx_status_ring_order, 0644, doff_u32), WIL_FIELD(rx_buff_id_count, 0644, doff_u32), WIL_FIELD(amsdu_en, 0644, doff_u8), WIL_FIELD(force_edmg_channel, 0644, doff_u8), {}, }; Loading
drivers/net/wireless/ath/wil6210/ftm.h +1 −0 Original line number Diff line number Diff line Loading @@ -401,6 +401,7 @@ enum qca_events_index { QCA_EVENT_FTM_MEAS_RESULT_INDEX, QCA_EVENT_FTM_SESSION_DONE_INDEX, QCA_EVENT_AOA_MEAS_RESULT_INDEX, QCA_EVENT_UNSPEC_INDEX, }; /* measurement parameters. Specified for each peer as part Loading
drivers/net/wireless/ath/wil6210/main.c +7 −4 Original line number Diff line number Diff line Loading @@ -212,6 +212,7 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) struct net_device *ndev = vif_to_ndev(vif); struct wireless_dev *wdev = vif_to_wdev(vif); struct wil_sta_info *sta = &wil->sta[cid]; int min_ring_id = wil_get_min_tx_ring_id(wil); might_sleep(); wil_dbg_misc(wil, "disconnect_cid: CID %d, MID %d, status %d\n", Loading Loading @@ -263,7 +264,7 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) memset(sta->tid_crypto_rx, 0, sizeof(sta->tid_crypto_rx)); memset(&sta->group_crypto_rx, 0, sizeof(sta->group_crypto_rx)); /* release vrings */ for (i = 0; i < ARRAY_SIZE(wil->ring_tx); i++) { for (i = min_ring_id; i < ARRAY_SIZE(wil->ring_tx); i++) { if (wil->ring2cid_tid[i][0] == cid) wil_ring_fini_tx(wil, i); } Loading Loading @@ -594,8 +595,10 @@ int wil_priv_init(struct wil6210_priv *wil) wil->sta[i].mid = U8_MAX; } for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) { spin_lock_init(&wil->ring_tx_data[i].lock); wil->ring2cid_tid[i][0] = WIL6210_MAX_CID; } mutex_init(&wil->mutex); mutex_init(&wil->vif_mutex); Loading Loading @@ -643,8 +646,6 @@ int wil_priv_init(struct wil6210_priv *wil) /* edma configuration can be updated via debugfs before allocation */ wil->num_rx_status_rings = WIL_DEFAULT_NUM_RX_STATUS_RINGS; wil->use_compressed_rx_status = true; wil->use_rx_hw_reordering = true; wil->tx_status_ring_order = WIL_TX_SRING_SIZE_ORDER_DEFAULT; /* Rx status ring size should be bigger than the number of RX buffers Loading Loading @@ -1540,6 +1541,8 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) wmi_event_flush(wil); wil->force_wmi_send = false; flush_workqueue(wil->wq_service); flush_workqueue(wil->wmi_wq); Loading
drivers/net/wireless/ath/wil6210/pcie_bus.c +1 −0 Original line number Diff line number Diff line Loading @@ -97,6 +97,7 @@ int wil_set_capabilities(struct wil6210_priv *wil) set_bit(hw_capa_no_flash, wil->hw_capa); wil->use_enhanced_dma_hw = true; wil->use_rx_hw_reordering = true; wil->use_compressed_rx_status = true; wil_fw_name = ftm_mode ? WIL_FW_NAME_FTM_TALYN : WIL_FW_NAME_TALYN; if (wil_fw_verify_file_exists(wil, wil_fw_name)) Loading