Merge "wil6210: extend bus voting support for wider bandwidth"

This commit is contained in:
qctecmdr 2019-12-17 18:50:53 -08:00 • committed by Gerrit - the friendly Code Review server
commit ba31e4ed26
7 changed files with 287 additions and 7 deletions

View file

@ -1551,8 +1551,14 @@ static int wil_cfg80211_connect(struct wiphy *wiphy,
rc = wmi_send(wil, WMI_CONNECT_CMDID, vif->mid, &conn, sizeof(conn));
if (rc == 0) {
netif_carrier_on(ndev);
if (!wil_has_other_active_ifaces(wil, ndev, false, true))
wil6210_bus_request(wil, WIL_MAX_BUS_REQUEST_KBPS);
if (!wil_has_other_active_ifaces(wil, ndev, false, true)) {
if (wil->force_edmg_channel)
wil6210_bus_request(wil,
WIL_11AY_BUS_REQUEST_KBPS);
else
wil6210_bus_request(wil,
WIL_11AD_BUS_REQUEST_KBPS);
}
vif->bss = bss;
/* Connect can take lots of time */
mod_timer(&vif->connect_timer,
@ -2207,8 +2213,13 @@ static int _wil_cfg80211_start_ap(struct wiphy *wiphy,
}
netif_carrier_on(ndev);
if (!wil_has_other_active_ifaces(wil, ndev, false, true))
wil6210_bus_request(wil, WIL_MAX_BUS_REQUEST_KBPS);
if (!wil_has_other_active_ifaces(wil, ndev, false, true)) {
if (wil->force_edmg_channel)
wil6210_bus_request(wil, WIL_11AY_BUS_REQUEST_KBPS);
else
wil6210_bus_request(wil, WIL_11AD_BUS_REQUEST_KBPS);
}
rc = wmi_pcp_start(vif, bi, wmi_nettype, chan, wmi_edmg_channel,
hidden_ssid, is_go);
@ -2646,6 +2657,10 @@ static int wil_cfg80211_set_power_mgmt(struct wiphy *wiphy,
struct wil6210_priv *wil = wiphy_to_wil(wiphy);
enum wmi_ps_profile_type ps_profile;
if (wil->vr_profile != WMI_VR_PROFILE_DISABLED)
/* disallow in VR mode */
return -EINVAL;
wil_dbg_misc(wil, "enabled=%d, timeout=%d\n",
enabled, timeout);

View file

@ -20,6 +20,8 @@
#define WAIT_FOR_SCAN_ABORT_MS 1000
#define WIL_DEFAULT_NUM_RX_STATUS_RINGS 1
#define WIL_BOARD_FILE_MAX_NAMELEN 128
#define WIL6210_ITR_VR_RX_MAX_BURST_DURATION (5) /* usec */
#define WIL6210_VR_TX_RING_ORDER 10
bool debug_fw; /* = false; */
module_param(debug_fw, bool, 0444);
@ -104,6 +106,11 @@ MODULE_PARM_DESC(tx_ring_order, " Tx ring order; size = 1 << order");
module_param_cb(bcast_ring_order, &ring_order_ops, &bcast_ring_order, 0444);
MODULE_PARM_DESC(bcast_ring_order, " Bcast ring order; size = 1 << order");
static u8 support_sensing_over_spi;
module_param(support_sensing_over_spi, byte, 0444);
MODULE_PARM_DESC(support_sensing_over_spi,
" notify FW to enable SPI for sensing");
enum {
WIL_BOOT_ERR,
WIL_BOOT_VANILLA,
@ -1560,6 +1567,38 @@ int wil_ps_update(struct wil6210_priv *wil, enum wmi_ps_profile_type ps_profile)
return rc;
}
int wil_vr_update_profile(struct wil6210_priv *wil, u8 profile)
{
int rc;
if (profile == WMI_VR_PROFILE_DISABLED) {
/* Switch from VR mode to normal (non-VR) mode is not
* supported at runtime - it requires FW re-loading.
* It is assumed here that FW is not running when VR disable
* is requested
*/
wil->ps_profile = WMI_PS_PROFILE_TYPE_DEFAULT;
tx_ring_order = WIL_TX_RING_SIZE_ORDER_DEFAULT;
drop_if_ring_full = false;
wil->rx_max_burst_duration =
WIL6210_ITR_RX_MAX_BURST_DURATION_DEFAULT;
return 0;
}
rc = wmi_set_vr_profile(wil, profile);
if (rc)
return rc;
/* VR default configuration */
wil->ps_profile = WMI_PS_PROFILE_TYPE_PS_DISABLED;
tx_ring_order = WIL6210_VR_TX_RING_ORDER;
drop_if_ring_full = true;
wil->rx_max_burst_duration = WIL6210_ITR_VR_RX_MAX_BURST_DURATION;
return 0;
}
static void wil_pre_fw_config(struct wil6210_priv *wil)
{
wil_clear_fw_log_addr(wil);
@ -1675,6 +1714,15 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
wil_s(wil, RGF_USER_USAGE_8, BIT_USER_EXT_CLK);
}
if (support_sensing_over_spi) {
wil_dbg_misc(wil, "notify FW to enable SPI for sensing\n");
wil_s(wil, RGF_USER_USAGE_6, BIT_SPI_SENSING_SUPPORT);
wmi_reset_spi_slave(wil);
} else {
wil_dbg_misc(wil, "notify FW to disable SPI for sensing\n");
wil_c(wil, RGF_USER_USAGE_6, BIT_SPI_SENSING_SUPPORT);
}
if (wil->platform_ops.notify) {
rc = wil->platform_ops.notify(wil->platform_handle,
WIL_PLATFORM_EVT_PRE_RESET);
@ -1802,6 +1850,10 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
return rc;
}
/* Update VR mode before configuring interrupt moderation */
if (wil->vr_profile != WMI_VR_PROFILE_DISABLED)
wil_vr_update_profile(wil, wil->vr_profile);
wil->txrx_ops.configure_interrupt_moderation(wil);
/* Enable OFU rdy valid bug fix, to prevent hang in oful34_rx

View file

@ -51,6 +51,13 @@ wil_can_suspend_vif(struct wil6210_priv *wil, struct wil6210_vif *vif,
/* for STA-like interface, don't runtime suspend */
case NL80211_IFTYPE_STATION:
if (test_bit(wil_vif_fwconnected, vif->status) &&
wil->vr_profile != WMI_VR_PROFILE_DISABLED) {
wil_dbg_pm(wil,
"Reject suspend in VR mode when connected\n");
return false;
}
/* fallthrough */
case NL80211_IFTYPE_P2P_CLIENT:
if (test_bit(wil_vif_fwconnecting, vif->status)) {
wil_dbg_pm(wil, "Delay suspend when connecting\n");

View file

@ -297,6 +297,59 @@ out:
static DEVICE_ATTR_RW(fst_link_loss);
static ssize_t
vr_profile_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct wil6210_priv *wil = dev_get_drvdata(dev);
ssize_t len;
len = snprintf(buf, PAGE_SIZE, "%s\n",
wil_get_vr_profile_name(wil->vr_profile));
return len;
}
static ssize_t
vr_profile_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct wil6210_priv *wil = dev_get_drvdata(dev);
u8 profile;
int rc = 0;
if (kstrtou8(buf, 0, &profile))
return -EINVAL;
if (test_bit(wil_status_fwready, wil->status)) {
wil_err(wil, "Cannot set VR while interface is up\n");
return -EIO;
}
if (profile == wil->vr_profile) {
wil_info(wil, "Ignore same VR profile %s\n",
wil_get_vr_profile_name(wil->vr_profile));
return count;
}
wil_info(wil, "Sysfs: set VR profile to %s\n",
wil_get_vr_profile_name(profile));
/* Enabling of VR mode is done from wil_reset after FW is ready.
* Disabling is done from here.
*/
if (profile == WMI_VR_PROFILE_DISABLED) {
rc = wil_vr_update_profile(wil, profile);
if (rc)
return rc;
}
wil->vr_profile = profile;
return count;
}
static DEVICE_ATTR_RW(vr_profile);
static ssize_t
snr_thresh_show(struct device *dev, struct device_attribute *attr,
char *buf)
@ -339,6 +392,7 @@ static struct attribute *wil6210_sysfs_entries[] = {
&dev_attr_thermal_throttling.attr,
&dev_attr_fst_link_loss.attr,
&dev_attr_snr_thresh.attr,
&dev_attr_vr_profile.attr,
NULL
};

View file

@ -52,6 +52,8 @@ union wil_tx_desc;
#define WIL_DEFAULT_BUS_REQUEST_KBPS 128000 /* ~1Gbps */
#define WIL_MAX_BUS_REQUEST_KBPS 800000 /* ~6.1Gbps */
#define WIL_11AD_BUS_REQUEST_KBPS 600000 /* ~4.6Gbps */
#define WIL_11AY_BUS_REQUEST_KBPS 1300000 /* ~10.1Gbps */
#define WIL_NUM_LATENCY_BINS 200
@ -181,6 +183,7 @@ struct RGF_ICR {
#define RGF_USER_USAGE_1 (0x880004)
#define RGF_USER_USAGE_2 (0x880008)
#define RGF_USER_USAGE_6 (0x880018)
#define BIT_SPI_SENSING_SUPPORT BIT(28)
#define BIT_USER_OOB_MODE BIT(31)
#define BIT_USER_OOB_R2_MODE BIT(30)
#define RGF_USER_USAGE_8 (0x880020)
@ -1051,6 +1054,9 @@ struct wil6210_priv {
short direct;
} snr_thresh;
/* VR profile, VR is disabled on profile 0 */
u8 vr_profile;
/* current reg domain configured in kernel */
char regdomain[3]; /* alpha2 */
@ -1254,6 +1260,7 @@ void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r);
int wil_find_cid(struct wil6210_priv *wil, u8 mid, const u8 *mac);
int wil_find_cid_by_idx(struct wil6210_priv *wil, u8 mid, int idx);
void wil_set_ethtoolops(struct net_device *ndev);
int wil_vr_update_profile(struct wil6210_priv *wil, u8 profile);
struct fw_map *wil_find_fw_mapping(const char *section);
void __iomem *wmi_buffer_block(struct wil6210_priv *wil, __le32 ptr, u32 size);
@ -1449,6 +1456,10 @@ void wil_halp_unvote(struct wil6210_priv *wil);
void wil6210_set_halp(struct wil6210_priv *wil);
void wil6210_clear_halp(struct wil6210_priv *wil);
int wmi_set_vr_profile(struct wil6210_priv *wil, u8 profile);
const char *
wil_get_vr_profile_name(enum wmi_vr_profile profile);
void wil_ftm_init(struct wil6210_vif *vif);
void wil_ftm_deinit(struct wil6210_vif *vif);
void wil_ftm_stop_operations(struct wil6210_priv *wil);
@ -1502,6 +1513,7 @@ int wmi_addba_rx_resp_edma(struct wil6210_priv *wil, u8 mid, u8 cid,
u16 agg_wsize, u16 timeout);
void update_supported_bands(struct wil6210_priv *wil);
int wmi_reset_spi_slave(struct wil6210_priv *wil);
void wil_clear_fw_log_addr(struct wil6210_priv *wil);
#endif /* __WIL6210_H__ */

View file

@ -32,6 +32,7 @@ MODULE_PARM_DESC(led_id,
#define WIL_WAIT_FOR_SUSPEND_RESUME_COMP 200
#define WIL_WMI_PCP_STOP_TO_MS 5000
#define WIL_WMI_SPI_SLAVE_RESET_TO_MS 500
/**
* WMI event receiving - theory of operations
@ -478,6 +479,10 @@ static const char *cmdid2name(u16 cmdid)
return "WMI_RBUFCAP_CFG_CMD";
case WMI_TEMP_SENSE_ALL_CMDID:
return "WMI_TEMP_SENSE_ALL_CMDID";
case WMI_SET_VR_PROFILE_CMDID:
return "WMI_SET_VR_PROFILE_CMD";
case WMI_RESET_SPI_SLAVE_CMDID:
return "WMI_RESET_SPI_SLAVE_CMD";
default:
return "Untracked CMD";
}
@ -626,6 +631,10 @@ static const char *eventid2name(u16 eventid)
return "WMI_RBUFCAP_CFG_EVENT";
case WMI_TEMP_SENSE_ALL_DONE_EVENTID:
return "WMI_TEMP_SENSE_ALL_DONE_EVENTID";
case WMI_SET_VR_PROFILE_EVENTID:
return "WMI_SET_VR_PROFILE_EVENT";
case WMI_RESET_SPI_SLAVE_EVENTID:
return "WMI_RESET_SPI_SLAVE_EVENT";
default:
return "Untracked EVENT";
}
@ -2070,8 +2079,9 @@ void wmi_recv_cmd(struct wil6210_priv *wil)
n - num_immed_reply, num_immed_reply);
}
int wmi_call(struct wil6210_priv *wil, u16 cmdid, u8 mid, void *buf, u16 len,
u16 reply_id, void *reply, u16 reply_size, int to_msec)
static int __wmi_call(struct wil6210_priv *wil, u16 cmdid, u8 mid, void *buf,
u16 len, u16 reply_id, void *reply, u16 reply_size,
int to_msec, bool force_send)
{
int rc;
unsigned long remain;
@ -2087,7 +2097,7 @@ int wmi_call(struct wil6210_priv *wil, u16 cmdid, u8 mid, void *buf, u16 len,
reinit_completion(&wil->wmi_call);
spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
rc = __wmi_send(wil, cmdid, mid, buf, len, false);
rc = __wmi_send(wil, cmdid, mid, buf, len, force_send);
if (rc)
goto out;
@ -2117,6 +2127,13 @@ out:
return rc;
}
int wmi_call(struct wil6210_priv *wil, u16 cmdid, u8 mid, void *buf, u16 len,
u16 reply_id, void *reply, u16 reply_size, int to_msec)
{
return __wmi_call(wil, cmdid, mid, buf, len, reply_id, reply,
reply_size, to_msec, false);
}
int wmi_echo(struct wil6210_priv *wil)
{
struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
@ -4211,3 +4228,84 @@ int wmi_link_stats_cfg(struct wil6210_vif *vif, u32 type, u8 cid, u32 interval)
return 0;
}
const char *
wil_get_vr_profile_name(enum wmi_vr_profile profile)
{
switch (profile) {
case WMI_VR_PROFILE_DISABLED:
return "DISABLED";
case WMI_VR_PROFILE_COMMON_AP:
return "COMMON_AP";
case WMI_VR_PROFILE_COMMON_STA:
return "COMMON_STA";
default:
return "unknown";
}
}
int wmi_set_vr_profile(struct wil6210_priv *wil, u8 profile)
{
int rc;
struct net_device *ndev = wil->main_ndev;
struct wil6210_vif *vif = ndev_to_vif(ndev);
struct wmi_set_vr_profile_cmd cmd = {0};
struct {
struct wmi_cmd_hdr hdr;
struct wmi_set_vr_profile_event evt;
} __packed reply = {
.evt = {.status = WMI_FW_STATUS_FAILURE},
};
cmd.profile = profile;
wil_info(wil, "sending set vr config command, profile=%d\n", profile);
rc = wmi_call(wil, WMI_SET_VR_PROFILE_CMDID, vif->mid, &cmd,
sizeof(cmd), WMI_SET_VR_PROFILE_EVENTID,
&reply, sizeof(reply), WIL_WMI_CALL_GENERAL_TO_MS);
if (rc) {
wil_err(wil, "WMI_SET_VR_PROFILE_CMDID failed, rc %d\n", rc);
return rc;
}
if (reply.evt.status != WMI_FW_STATUS_SUCCESS) {
wil_err(wil, "set vr profile failed, status %d\n",
reply.evt.status);
return -EINVAL;
}
return 0;
}
int wmi_reset_spi_slave(struct wil6210_priv *wil)
{
struct net_device *ndev = wil->main_ndev;
struct wil6210_vif *vif = ndev_to_vif(ndev);
struct wmi_reset_spi_slave_cmd cmd = { {0} };
struct {
struct wmi_cmd_hdr wmi;
struct wmi_reset_spi_slave_event evt;
} __packed reply = {
.evt = {.status = WMI_FW_STATUS_FAILURE},
};
int rc;
if (!(ndev->flags & IFF_UP))
return 0;
/* Force sending SPI slave reset to guarantee safe SPI reset */
rc = __wmi_call(wil, WMI_RESET_SPI_SLAVE_CMDID, vif->mid, &cmd,
sizeof(cmd), WMI_RESET_SPI_SLAVE_EVENTID, &reply,
sizeof(reply), WIL_WMI_SPI_SLAVE_RESET_TO_MS, true);
if (rc) {
wil_err(wil, "WMI_RESET_SPI_SLAVE_CMDID failed, rc %d\n", rc);
return rc;
}
if (reply.evt.status != WMI_FW_STATUS_SUCCESS) {
wil_err(wil, "spi slave reset failed, status %d\n",
reply.evt.status);
return -EINVAL;
}
return 0;
}

View file

@ -140,6 +140,7 @@ enum wmi_command_id {
WMI_RADAR_SET_MODE_CMDID = 0x103,
WMI_RADAR_CONTROL_CMDID = 0x104,
WMI_RADAR_PCI_CONTROL_CMDID = 0x105,
WMI_RESET_SPI_SLAVE_CMDID = 0x106,
WMI_MEM_READ_CMDID = 0x800,
WMI_MEM_WR_CMDID = 0x801,
WMI_ECHO_CMDID = 0x803,
@ -284,6 +285,7 @@ enum wmi_command_id {
WMI_GET_ASSOC_LIST_CMDID = 0xA06,
WMI_GET_CCA_INDICATIONS_CMDID = 0xA07,
WMI_SET_CCA_INDICATIONS_BI_AVG_NUM_CMDID = 0xA08,
WMI_SET_VR_PROFILE_CMDID = 0xA09,
WMI_INTERNAL_FW_IOCTL_CMDID = 0xA0B,
WMI_LINK_STATS_CMDID = 0xA0C,
WMI_SET_GRANT_MCS_CMDID = 0xA0E,
@ -692,6 +694,11 @@ struct wmi_radar_pci_control_cmd {
__le32 reserved;
} __packed;
/* WMI_RESET_SPI_SLAVE_CMDID */
struct wmi_reset_spi_slave_cmd {
u8 reserved[4];
} __packed;
/* WMI_RF_MGMT_CMDID */
enum wmi_rf_mgmt_type {
WMI_RF_MGMT_W_DISABLE = 0x00,
@ -1734,6 +1741,13 @@ struct wmi_radar_pci_control_event {
u8 reserved[3];
} __packed;
/* WMI_RESET_SPI_SLAVE_EVENTID */
struct wmi_reset_spi_slave_event {
/* wmi_fw_status */
u8 status;
u8 reserved[3];
} __packed;
/* WMI_SET_LONG_RANGE_CONFIG_CMDID */
struct wmi_set_long_range_config_cmd {
__le32 reserved;
@ -1980,6 +1994,7 @@ enum wmi_event_id {
WMI_RADAR_SET_MODE_EVENTID = 0x1103,
WMI_RADAR_CONTROL_EVENTID = 0x1104,
WMI_RADAR_PCI_CONTROL_EVENTID = 0x1105,
WMI_RESET_SPI_SLAVE_EVENTID = 0x1106,
WMI_RD_MEM_RSP_EVENTID = 0x1800,
WMI_FW_READY_EVENTID = 0x1801,
WMI_EXIT_FAST_MEM_ACC_MODE_EVENTID = 0x200,
@ -2110,6 +2125,7 @@ enum wmi_event_id {
WMI_GET_ASSOC_LIST_RES_EVENTID = 0x1A06,
WMI_GET_CCA_INDICATIONS_EVENTID = 0x1A07,
WMI_SET_CCA_INDICATIONS_BI_AVG_NUM_EVENTID = 0x1A08,
WMI_SET_VR_PROFILE_EVENTID = 0x1A09,
WMI_INTERNAL_FW_EVENT_EVENTID = 0x1A0A,
WMI_INTERNAL_FW_IOCTL_EVENTID = 0x1A0B,
WMI_LINK_STATS_CONFIG_DONE_EVENTID = 0x1A0C,
@ -4158,6 +4174,32 @@ struct wmi_rbufcap_cfg_cmd {
__le16 rx_desc_threshold;
} __packed;
enum wmi_vr_profile {
WMI_VR_PROFILE_DISABLED = 0,
WMI_VR_PROFILE_COMMON_AP = 1,
WMI_VR_PROFILE_COMMON_STA = 2,
WMI_VR_PROFILE_RESERVED0 = 250,
WMI_VR_PROFILE_RESERVED1 = 251,
WMI_VR_PROFILE_RESERVED2 = 252,
WMI_VR_PROFILE_RESERVED3 = 253,
WMI_VR_PROFILE_RESERVED4 = 254,
WMI_VR_PROFILE_RESERVED5 = 255,
};
/* WMI_SET_VR_PROFILE_CMDID */
struct wmi_set_vr_profile_cmd {
/* enum wmi_vr_profile */
u8 profile;
u8 reserved[3];
} __packed;
/* WMI_SET_VR_PROFILE_EVENTID */
struct wmi_set_vr_profile_event {
/* enum wmi_fw_status */
u8 status;
u8 reserved[3];
} __packed;
/* WMI_RBUFCAP_CFG_EVENTID */
struct wmi_rbufcap_cfg_event {
/* enum wmi_fw_status */