Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 45a1c634 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "wil6210: add fst_config sysfs"

parents 2f15888a 5d660bdc
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -3001,6 +3001,23 @@ wil_cfg80211_update_ft_ies(struct wiphy *wiphy, struct net_device *dev,
	return rc;
}

static int wil_cfg80211_set_cqm_rssi_config(struct wiphy *wiphy,
					    struct net_device *dev,
					    s32 rssi_thold, u32 rssi_hyst)
{
	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
	int rc;

	wil->cqm_rssi_thold = rssi_thold;

	rc = wmi_set_cqm_rssi_config(wil, rssi_thold, rssi_hyst);
	if (rc)
		/* reset stored value upon failure */
		wil->cqm_rssi_thold = 0;

	return rc;
}

static const struct cfg80211_ops wil_cfg80211_ops = {
	.add_virtual_intf = wil_cfg80211_add_iface,
	.del_virtual_intf = wil_cfg80211_del_iface,
@@ -3032,6 +3049,7 @@ static const struct cfg80211_ops wil_cfg80211_ops = {
	.start_p2p_device = wil_cfg80211_start_p2p_device,
	.stop_p2p_device = wil_cfg80211_stop_p2p_device,
	.set_power_mgmt = wil_cfg80211_set_power_mgmt,
	.set_cqm_rssi_config = wil_cfg80211_set_cqm_rssi_config,
	.suspend = wil_cfg80211_suspend,
	.resume = wil_cfg80211_resume,
	.sched_scan_start = wil_cfg80211_sched_scan_start,
+38 −0
Original line number Diff line number Diff line
@@ -317,6 +317,43 @@ fst_link_loss_store(struct device *dev, struct device_attribute *attr,

static DEVICE_ATTR_RW(fst_link_loss);

static ssize_t
fst_config_store(struct device *dev, struct device_attribute *attr,
		 const char *buf, size_t count)
{
	struct wil6210_priv *wil = dev_get_drvdata(dev);
	u8 addr[ETH_ALEN];
	int rc;
	u8 enabled, entry_mcs, exit_mcs, slevel;

	/* <ap_bssid> <enabled> <entry_mcs> <exit_mcs> <sensitivity_level> */
	if (sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx %hhu %hhu %hhu %hhu",
		   &addr[0], &addr[1], &addr[2],
		   &addr[3], &addr[4], &addr[5],
		   &enabled, &entry_mcs, &exit_mcs, &slevel) != 10)
		return -EINVAL;

	if (entry_mcs > WIL_MCS_MAX || exit_mcs > WIL_MCS_MAX ||
	    entry_mcs < exit_mcs || slevel > WMI_FST_SWITCH_SENSITIVITY_HIGH)
		return -EINVAL;

	wil_dbg_misc(wil,
		     "fst_config %sabled for [%pM] with entry/exit MCS %d/%d, sensitivity %s\n",
		     enabled ? "en" : "dis", addr, entry_mcs, exit_mcs,
		     (slevel == WMI_FST_SWITCH_SENSITIVITY_LOW) ?
			"LOW" : (slevel == WMI_FST_SWITCH_SENSITIVITY_HIGH) ?
					"HIGH" : "MED");

	rc = wmi_set_fst_config(wil, addr, enabled, entry_mcs, exit_mcs,
				slevel);
	if (!rc)
		rc = count;

	return rc;
}

static DEVICE_ATTR_WO(fst_config);

static ssize_t
vr_profile_show(struct device *dev, struct device_attribute *attr,
		char *buf)
@@ -427,6 +464,7 @@ static struct attribute *wil6210_sysfs_entries[] = {
	&dev_attr_fst_link_loss.attr,
	&dev_attr_snr_thresh.attr,
	&dev_attr_vr_profile.attr,
	&dev_attr_fst_config.attr,
	NULL
};

+5 −0
Original line number Diff line number Diff line
@@ -1141,6 +1141,7 @@ struct wil6210_priv {
	void *ipa_handle;

	u32 tx_reserved_entries; /* Used only in Talyn code-path */
	s32 cqm_rssi_thold;
};

#define wil_to_wiphy(i) (i->wiphy)
@@ -1573,4 +1574,8 @@ 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);
int wmi_set_cqm_rssi_config(struct wil6210_priv *wil,
			    s32 rssi_thold, u32 rssi_hyst);
int wmi_set_fst_config(struct wil6210_priv *wil, const u8 *bssid, u8 enabled,
		       u8 entry_mcs, u8 exit_mcs, u8 slevel);
#endif /* __WIL6210_H__ */
+118 −0
Original line number Diff line number Diff line
@@ -483,6 +483,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_FST_CONFIG_CMDID:
		return "WMI_FST_CONFIG_CMD";
	case WMI_SET_LINK_MONITOR_CMDID:
		return "WMI_SET_LINK_MONITOR_CMD";
	default:
		return "Untracked CMD";
	}
@@ -635,6 +639,12 @@ 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_FST_CONFIG_EVENTID:
		return "WMI_FST_CONFIG_EVENT";
	case WMI_SET_LINK_MONITOR_EVENTID:
		return "WMI_SET_LINK_MONITOR_EVENT";
	case WMI_LINK_MONITOR_EVENTID:
		return "WMI_LINK_MONITOR_EVENT";
	default:
		return "Untracked EVENT";
	}
@@ -1908,6 +1918,32 @@ wmi_evt_reassoc_status(struct wil6210_vif *vif, int id, void *d, int len)
	wil6210_disconnect(vif, NULL, WLAN_REASON_PREV_AUTH_NOT_VALID);
}

static void
wmi_evt_link_monitor(struct wil6210_vif *vif, int id, void *d, int len)
{
	struct wil6210_priv *wil = vif_to_wil(vif);
	struct net_device *ndev = vif_to_ndev(vif);
	struct wmi_link_monitor_event *evt = d;
	enum nl80211_cqm_rssi_threshold_event event_type;

	if (len < sizeof(*evt)) {
		wil_err(wil, "link monitor event too short %d\n", len);
		return;
	}

	wil_dbg_wmi(wil, "link monitor event, type %d rssi %d (stored %d)\n",
		    evt->type, evt->rssi_level, wil->cqm_rssi_thold);

	if (evt->type != WMI_LINK_MONITOR_NOTIF_RSSI_THRESHOLD_EVT)
		/* ignore */
		return;

	event_type = (evt->rssi_level > wil->cqm_rssi_thold ?
		      NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH :
		      NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW);
	cfg80211_cqm_rssi_notify(ndev, event_type, evt->rssi_level, GFP_KERNEL);
}

/**
 * Some events are ignored for purpose; and need not be interpreted as
 * "unhandled events"
@@ -1948,6 +1984,7 @@ static const struct {
	{WMI_LINK_STATS_EVENTID,		wmi_evt_link_stats},
	{WMI_FT_AUTH_STATUS_EVENTID,		wmi_evt_auth_status},
	{WMI_FT_REASSOC_STATUS_EVENTID,		wmi_evt_reassoc_status},
	{WMI_LINK_MONITOR_EVENTID,		wmi_evt_link_monitor},
};

/*
@@ -4351,3 +4388,84 @@ int wmi_reset_spi_slave(struct wil6210_priv *wil)

	return 0;
}

int wmi_set_cqm_rssi_config(struct wil6210_priv *wil,
			    s32 rssi_thold, u32 rssi_hyst)
{
	struct net_device *ndev = wil->main_ndev;
	struct wil6210_vif *vif = ndev_to_vif(ndev);
	int rc;
	struct {
		struct wmi_set_link_monitor_cmd cmd;
		s8 rssi_thold;
	} __packed cmd = {
		.cmd = {
			.rssi_hyst = rssi_hyst,
			.rssi_thresholds_list_size = 1,
		},
		.rssi_thold = rssi_thold,
	};
	struct {
		struct wmi_cmd_hdr hdr;
		struct wmi_set_link_monitor_event evt;
	} __packed reply = {
		.evt = {.status = WMI_FW_STATUS_FAILURE},
	};

	if (rssi_thold > S8_MAX || rssi_thold < S8_MIN || rssi_hyst > U8_MAX)
		return -EINVAL;

	rc = wmi_call(wil, WMI_SET_LINK_MONITOR_CMDID, vif->mid, &cmd,
		      sizeof(cmd), WMI_SET_LINK_MONITOR_EVENTID,
		      &reply, sizeof(reply), WIL_WMI_CALL_GENERAL_TO_MS);
	if (rc) {
		wil_err(wil, "WMI_SET_LINK_MONITOR_CMDID failed, rc %d\n", rc);
		return rc;
	}

	if (reply.evt.status != WMI_FW_STATUS_SUCCESS) {
		wil_err(wil, "WMI_SET_LINK_MONITOR_CMDID failed, status %d\n",
			reply.evt.status);
		return -EINVAL;
	}

	return 0;
}

int wmi_set_fst_config(struct wil6210_priv *wil, const u8 *bssid, u8 enabled,
		       u8 entry_mcs, u8 exit_mcs, u8 slevel)
{
	struct net_device *ndev = wil->main_ndev;
	struct wil6210_vif *vif = ndev_to_vif(ndev);
	int rc;
	struct wmi_fst_config_cmd cmd = {
		.fst_en = enabled,
		.fst_entry_mcs = entry_mcs,
		.fst_exit_mcs = exit_mcs,
		.sensitivity_level = slevel,
	};
	struct {
		struct wmi_cmd_hdr hdr;
		struct wmi_fst_config_event evt;
	} __packed reply = {
		.evt = {.status = WMI_FW_STATUS_FAILURE},
	};

	ether_addr_copy(cmd.fst_ap_bssid, bssid);

	rc = wmi_call(wil, WMI_FST_CONFIG_CMDID, vif->mid, &cmd,
		      sizeof(cmd), WMI_FST_CONFIG_EVENTID,
		      &reply, sizeof(reply), WIL_WMI_CALL_GENERAL_TO_MS);
	if (rc) {
		wil_err(wil, "WMI_FST_CONFIG_CMDID failed, rc %d\n", rc);
		return rc;
	}

	if (reply.evt.status != WMI_FW_STATUS_SUCCESS) {
		wil_err(wil, "WMI_FST_CONFIG_CMDID failed, status %d\n",
			reply.evt.status);
		return -EINVAL;
	}

	return 0;
}
+60 −0
Original line number Diff line number Diff line
@@ -195,6 +195,8 @@ enum wmi_command_id {
	WMI_RCP_ADDBA_RESP_EDMA_CMDID			= 0x83B,
	WMI_LINK_MAINTAIN_CFG_WRITE_CMDID		= 0x842,
	WMI_LINK_MAINTAIN_CFG_READ_CMDID		= 0x843,
	WMI_FST_CONFIG_CMDID				= 0x844,
	WMI_SET_LINK_MONITOR_CMDID			= 0x845,
	WMI_SET_SECTORS_CMDID				= 0x849,
	WMI_MAINTAIN_PAUSE_CMDID			= 0x850,
	WMI_MAINTAIN_RESUME_CMDID			= 0x851,
@@ -1989,6 +1991,7 @@ enum wmi_event_id {
	WMI_REPORT_STATISTICS_EVENTID			= 0x100B,
	WMI_FT_AUTH_STATUS_EVENTID			= 0x100C,
	WMI_FT_REASSOC_STATUS_EVENTID			= 0x100D,
	WMI_LINK_MONITOR_EVENTID			= 0x100E,
	WMI_RADAR_GENERAL_CONFIG_EVENTID		= 0x1100,
	WMI_RADAR_CONFIG_SELECT_EVENTID			= 0x1101,
	WMI_RADAR_PARAMS_CONFIG_EVENTID			= 0x1102,
@@ -2041,6 +2044,8 @@ enum wmi_event_id {
	WMI_TX_MGMT_PACKET_EVENTID			= 0x1841,
	WMI_LINK_MAINTAIN_CFG_WRITE_DONE_EVENTID	= 0x1842,
	WMI_LINK_MAINTAIN_CFG_READ_DONE_EVENTID		= 0x1843,
	WMI_FST_CONFIG_EVENTID				= 0x1844,
	WMI_SET_LINK_MONITOR_EVENTID			= 0x1845,
	WMI_RF_XPM_READ_RESULT_EVENTID			= 0x1856,
	WMI_RF_XPM_WRITE_RESULT_EVENTID			= 0x1857,
	WMI_LED_CFG_DONE_EVENTID			= 0x1858,
@@ -3330,6 +3335,61 @@ struct wmi_link_maintain_cfg_read_cmd {
	__le32 cid;
} __packed;

/* switch sensitivity levels for WMI_FST_CONFIG_CMDID command */
enum wmi_fst_switch_sensitivity_level {
	WMI_FST_SWITCH_SENSITIVITY_LOW	= 0x00,
	WMI_FST_SWITCH_SENSITIVITY_MED	= 0x01,
	WMI_FST_SWITCH_SENSITIVITY_HIGH	= 0x02,
};

/* WMI_FST_CONFIG_CMDID */
struct wmi_fst_config_cmd {
	u8 fst_en;
	u8 fst_ap_bssid[WMI_MAC_LEN];
	u8 fst_entry_mcs;
	u8 fst_exit_mcs;
	/* wmi_fst_switch_sensitivity_level */
	u8 sensitivity_level;
	u8 reserved[2];
} __packed;

/* WMI_SET_LINK_MONITOR_CMDID */
struct wmi_set_link_monitor_cmd {
	u8 rssi_hyst;
	u8 reserved[12];
	u8 rssi_thresholds_list_size;
	s8 rssi_thresholds_list[0];
} __packed;

/* WMI_FST_CONFIG_EVENTID */
struct wmi_fst_config_event {
	/* wmi_fw_status */
	u8 status;
	u8 reserved[3];
} __packed;

/* wmi_link_monitor_event_type */
enum wmi_link_monitor_event_type {
	WMI_LINK_MONITOR_NOTIF_RSSI_THRESHOLD_EVT	= 0x00,
	WMI_LINK_MONITOR_NOTIF_TX_ERR_EVT		= 0x01,
	WMI_LINK_MONITOR_NOTIF_THERMAL_EVT		= 0x02,
};

/* WMI_SET_LINK_MONITOR_EVENTID */
struct wmi_set_link_monitor_event {
	/* wmi_fw_status */
	u8 status;
	u8 reserved[3];
} __packed;

/* WMI_LINK_MONITOR_EVENTID */
struct wmi_link_monitor_event {
	/* link_monitor_event_type */
	u8 type;
	s8 rssi_level;
	u8 reserved[2];
} __packed;

/* WMI_LINK_MAINTAIN_CFG_WRITE_DONE_EVENTID */
struct wmi_link_maintain_cfg_write_done_event {
	/* requested connection ID */