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

Commit e2674c66 authored by Tzahi Sabo's avatar Tzahi Sabo Committed by Gerrit - the friendly Code Review server
Browse files

wil6210: send NL notifications on FW state change



Userspace needs to track FW state. Send NL notification to registered
userspace clients when FW state change.

Change-Id: I41b0607481b52a11676210d8cb353925cc4595fe
Signed-off-by: default avatarTzahi Sabo <stzahi@codeaurora.org>
parent 136a06e4
Loading
Loading
Loading
Loading
+72 −0
Original line number Diff line number Diff line
@@ -150,13 +150,28 @@ enum wil_nl_60g_evt_type {
	NL_60G_EVT_FW_WMI,
	NL_60G_EVT_DRIVER_SHUTOWN,
	NL_60G_EVT_DRIVER_DEBUG_EVENT,
	NL_60G_EVT_DRIVER_GENERIC,
};

enum wil_nl_60g_generic_evt {
	NL_60G_GEN_EVT_FW_STATE,
};

struct wil_nl_60g_generic_event { /* NL_60G_EVT_DRIVER_GENERIC */
	u32 evt_id; /* wil_nl_60g_generic_evt */
} __packed;

struct wil_nl_60g_fw_state_event {
	struct wil_nl_60g_generic_event hdr;
	u32 fw_state; /* wil_fw_state */
} __packed;

enum wil_nl_60g_debug_cmd {
	NL_60G_DBG_FORCE_WMI_SEND,
	NL_60G_GEN_RADAR_ALLOC_BUFFER,
	NL_60G_GEN_FW_RESET,
	NL_60G_GEN_GET_DRIVER_CAPA,
	NL_60G_GEN_GET_FW_STATE,
};

struct wil_nl_60g_send_receive_wmi {
@@ -3716,6 +3731,62 @@ static int wil_brp_set_ant_limit(struct wiphy *wiphy, struct wireless_dev *wdev,
					 antenna_num_limit);
}

static void wil_nl_60g_fw_state_evt(struct wil6210_priv *wil)
{
	struct sk_buff *vendor_event = NULL;
	struct wil_nl_60g_event *evt;
	struct wil_nl_60g_fw_state_event *fw_state_event;

	if (!wil->publish_nl_evt)
		return;

	wil_dbg_misc(wil, "report fw_state event to user-space (%d)\n",
		     wil->fw_state);

	evt = kzalloc(sizeof(*evt) + sizeof(*fw_state_event), GFP_KERNEL);
	if (!evt)
		return;

	evt->evt_type = NL_60G_EVT_DRIVER_GENERIC;
	evt->buf_len = sizeof(*fw_state_event);

	fw_state_event = (struct wil_nl_60g_fw_state_event *)evt->buf;
	fw_state_event->hdr.evt_id = NL_60G_GEN_EVT_FW_STATE;
	fw_state_event->fw_state = wil->fw_state;

	vendor_event = cfg80211_vendor_event_alloc(wil_to_wiphy(wil),
						   NULL,
						   4 + NLMSG_HDRLEN +
						   sizeof(*evt) +
						   sizeof(*fw_state_event),
						   QCA_EVENT_UNSPEC_INDEX,
						   GFP_KERNEL);
	if (!vendor_event) {
		wil_err(wil, "failed to allocate vendor_event\n");
		goto out;
	}

	if (nla_put(vendor_event, WIL_ATTR_60G_BUF,
		    sizeof(*evt) + sizeof(*fw_state_event), evt)) {
		wil_err(wil, "failed to fill WIL_ATTR_60G_BUF\n");
		kfree_skb(vendor_event);
		goto out;
	}

	cfg80211_vendor_event(vendor_event, GFP_KERNEL);

out:
	kfree(evt);
}

void wil_nl_60g_fw_state_change(struct wil6210_priv *wil,
				enum wil_fw_state fw_state)
{
	wil_dbg_misc(wil, "fw_state change:%d => %d", wil->fw_state, fw_state);
	wil->fw_state = fw_state;
	wil_nl_60g_fw_state_evt(wil);
}

static int wil_nl_60g_handle_cmd(struct wiphy *wiphy, struct wireless_dev *wdev,
				 const void *data, int data_len)
{
@@ -3757,6 +3828,7 @@ static int wil_nl_60g_handle_cmd(struct wiphy *wiphy, struct wireless_dev *wdev,

		wil_dbg_wmi(wil, "Publish wmi event %s\n",
			    publish ? "enabled" : "disabled");
		wil_nl_60g_fw_state_evt(wil);
		break;
	case NL_60G_CMD_DEBUG:
		if (!tb[WIL_ATTR_60G_BUF]) {
+10 −0
Original line number Diff line number Diff line
@@ -621,6 +621,12 @@ static void wil_fw_error_worker(struct work_struct *work)
	struct net_device *ndev = wil->main_ndev;

	wil_dbg_misc(wil, "fw error worker\n");
	if (wil->fw_state == WIL_FW_STATE_READY)
		wil_nl_60g_fw_state_change(wil,
					   WIL_FW_STATE_ERROR);
	else
		wil_nl_60g_fw_state_change(wil,
					   WIL_FW_STATE_ERROR_BEFORE_READY);

	if (!ndev || !(ndev->flags & IFF_UP)) {
		wil_info(wil, "No recovery - interface is down\n");
@@ -798,6 +804,7 @@ int wil_priv_init(struct wil6210_priv *wil)
	wil->rx_buff_id_count = WIL_RX_BUFF_ARR_SIZE_DEFAULT;

	wil->amsdu_en = 1;
	wil->fw_state = WIL_FW_STATE_DOWN;

	return 0;

@@ -1508,6 +1515,7 @@ static int wil_wait_for_fw_ready(struct wil6210_priv *wil)
	} else {
		wil_info(wil, "FW ready after %d ms. HW version 0x%08x\n",
			 jiffies_to_msecs(to-left), wil->hw_version);
		wil_nl_60g_fw_state_change(wil, WIL_FW_STATE_READY);
	}
	return 0;
}
@@ -1703,6 +1711,7 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)

		ether_addr_copy(ndev->perm_addr, mac);
		ether_addr_copy(ndev->dev_addr, ndev->perm_addr);
		wil->fw_state = WIL_FW_STATE_UNKNOWN;
		return 0;
	}

@@ -1737,6 +1746,7 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
				rc);
	}

	wil_nl_60g_fw_state_change(wil, WIL_FW_STATE_DOWN);
	set_bit(wil_status_resetting, wil->status);
	mutex_lock(&wil->vif_mutex);
	wil_abort_scan_all_vifs(wil, false);
+7 −0
Original line number Diff line number Diff line
@@ -387,6 +387,13 @@ static int wil_platform_rop_notify(void *wil_handle,
		set_bit(wil_status_resetting, wil->status);
		set_bit(wil_status_pci_linkdown, wil->status);

		if (wil->fw_state == WIL_FW_STATE_READY)
			wil_nl_60g_fw_state_change(wil,
						   WIL_FW_STATE_ERROR);
		else
			wil_nl_60g_fw_state_change(wil,
					WIL_FW_STATE_ERROR_BEFORE_READY);

		schedule_work(&wil->pci_linkdown_recovery_worker);
		break;
	default:
+15 −0
Original line number Diff line number Diff line
@@ -960,6 +960,17 @@ struct wil_ftm_offsets {
	unsigned int rx_offset;
};

enum wil_fw_state {
	/* When driver loaded with debug_fw the FW state is unknown */
	WIL_FW_STATE_UNKNOWN,
	WIL_FW_STATE_DOWN, /* FW not loaded or not ready yet */
	WIL_FW_STATE_READY,/* FW is ready*/
	/* Detected FW error before FW sent ready indication */
	WIL_FW_STATE_ERROR_BEFORE_READY,
	/* Detected FW error after FW sent ready indication */
	WIL_FW_STATE_ERROR,
};

struct wil6210_priv {
	struct pci_dev *pdev;
	u32 bar_size;
@@ -1124,6 +1135,7 @@ struct wil6210_priv {
	u32 max_agg_wsize;
	u32 max_ampdu_size;

	enum wil_fw_state fw_state;
	struct work_struct pci_linkdown_recovery_worker;
	void *ipa_handle;

@@ -1387,6 +1399,9 @@ int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
			 struct cfg80211_mgmt_tx_params *params,
			 u64 *cookie);
void wil_cfg80211_ap_recovery(struct wil6210_priv *wil);

void wil_nl_60g_fw_state_change(struct wil6210_priv *wil,
				enum wil_fw_state fw_state);
int wil_cfg80211_iface_combinations_from_fw(
	struct wil6210_priv *wil,
	const struct wil_fw_record_concurrency *conc);