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

Commit 1d70e214 authored by Dedy Lansky's avatar Dedy Lansky
Browse files

wil6210: add support for set_cqm_rssi_config



set_cqm_rssi_config() is used by the kernel to configure connection
quality monitor RSSI threshold.
wil6210 uses WMI_SET_LINK_MONITOR_CMDID to set the RSSI threshold to
FW which in turn reports RSSI threshold changes with
WMI_LINK_MONITOR_EVENTID.

Change-Id: Id979652ada39922e701e94079d24269e09f89ddb
Signed-off-by: default avatarDedy Lansky <dlansky@codeaurora.org>
parent 78a63621
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -2996,6 +2996,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,
@@ -3027,6 +3044,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,
+3 −0
Original line number Diff line number Diff line
@@ -1140,6 +1140,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)
@@ -1572,4 +1573,6 @@ 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);
#endif /* __WIL6210_H__ */
+76 −0
Original line number Diff line number Diff line
@@ -483,6 +483,8 @@ 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_LINK_MONITOR_CMDID:
		return "WMI_SET_LINK_MONITOR_CMD";
	default:
		return "Untracked CMD";
	}
@@ -635,6 +637,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_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 +1914,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 +1980,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 +4384,46 @@ 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;
}
+33 −0
Original line number Diff line number Diff line
@@ -195,6 +195,7 @@ 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_SET_LINK_MONITOR_CMDID			= 0x845,
	WMI_SET_SECTORS_CMDID				= 0x849,
	WMI_MAINTAIN_PAUSE_CMDID			= 0x850,
	WMI_MAINTAIN_RESUME_CMDID			= 0x851,
@@ -1989,6 +1990,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 +2043,7 @@ 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_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 +3333,36 @@ struct wmi_link_maintain_cfg_read_cmd {
	__le32 cid;
} __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_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 */