Commit 988cf07b authored by Jérôme Pouiller's avatar Jérôme Pouiller Committed by Greg Kroah-Hartman
Browse files

staging: wfx: handle firmware events synchronously



Currently, events from firmware are handled in a work queue with a
complex event queue mechanism. It is probably overkill since there is
only two events to handle: bss_loss and CQM events. Handling these
events synchronously is sufficient.

Signed-off-by: default avatarJérôme Pouiller <jerome.pouiller@silabs.com>
Link: https://lore.kernel.org/r/20200420160311.57323-5-Jerome.Pouiller@silabs.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 5c442b6a
Loading
Loading
Loading
Loading
+22 −17
Original line number Diff line number Diff line
@@ -158,26 +158,31 @@ static int hif_event_indication(struct wfx_dev *wdev,
{
	struct wfx_vif *wvif = wdev_to_wvif(wdev, hif->interface);
	const struct hif_ind_event *body = buf;
	struct wfx_hif_event *event;
	int first;

	WARN_ON(!wvif);
	if (!wvif)
	if (!wvif) {
		dev_warn(wdev->dev, "received event for non-existent vif\n");
		return 0;
	}

	event = kzalloc(sizeof(*event), GFP_KERNEL);
	if (!event)
		return -ENOMEM;

	memcpy(&event->evt, body, sizeof(struct hif_ind_event));
	spin_lock(&wvif->event_queue_lock);
	first = list_empty(&wvif->event_queue);
	list_add_tail(&event->link, &wvif->event_queue);
	spin_unlock(&wvif->event_queue_lock);

	if (first)
		schedule_work(&wvif->event_handler_work);

	switch (body->event_id) {
	case HIF_EVENT_IND_RCPI_RSSI:
		wfx_event_report_rssi(wvif, body->event_data.rcpi_rssi);
		break;
	case HIF_EVENT_IND_BSSLOST:
		schedule_delayed_work(&wvif->beacon_loss_work, 0);
		break;
	case HIF_EVENT_IND_BSSREGAINED:
		cancel_delayed_work(&wvif->beacon_loss_work);
		dev_dbg(wdev->dev, "ignore BSSREGAINED indication\n");
		break;
	case HIF_EVENT_IND_PS_MODE_ERROR:
		dev_warn(wdev->dev, "error while processing power save request\n");
		break;
	default:
		dev_warn(wdev->dev, "unhandled event indication: %.2x\n",
			 body->event_id);
		break;
	}
	return 0;
}

+1 −69
Original line number Diff line number Diff line
@@ -38,27 +38,6 @@ u32 wfx_rate_mask_to_hw(struct wfx_dev *wdev, u32 rates)
	return ret;
}

static void __wfx_free_event_queue(struct list_head *list)
{
	struct wfx_hif_event *event, *tmp;

	list_for_each_entry_safe(event, tmp, list, link) {
		list_del(&event->link);
		kfree(event);
	}
}

static void wfx_free_event_queue(struct wfx_vif *wvif)
{
	LIST_HEAD(list);

	spin_lock(&wvif->event_queue_lock);
	list_splice_init(&wvif->event_queue, &list);
	spin_unlock(&wvif->event_queue_lock);

	__wfx_free_event_queue(&list);
}

static void wfx_filter_beacon(struct wfx_vif *wvif, bool filter_beacon)
{
	const struct hif_ie_table_entry filter_ies[] = {
@@ -269,7 +248,7 @@ int wfx_set_rts_threshold(struct ieee80211_hw *hw, u32 value)

/* WSM callbacks */

static void wfx_event_report_rssi(struct wfx_vif *wvif, u8 raw_rcpi_rssi)
void wfx_event_report_rssi(struct wfx_vif *wvif, u8 raw_rcpi_rssi)
{
	/* RSSI: signed Q8.0, RCPI: unsigned Q7.1
	 * RSSI = RCPI / 2 - 110
@@ -296,44 +275,6 @@ static void wfx_beacon_loss_work(struct work_struct *work)
			      msecs_to_jiffies(bss_conf->beacon_int));
}

static void wfx_event_handler_work(struct work_struct *work)
{
	struct wfx_vif *wvif =
		container_of(work, struct wfx_vif, event_handler_work);
	struct wfx_hif_event *event;

	LIST_HEAD(list);

	spin_lock(&wvif->event_queue_lock);
	list_splice_init(&wvif->event_queue, &list);
	spin_unlock(&wvif->event_queue_lock);

	list_for_each_entry(event, &list, link) {
		switch (event->evt.event_id) {
		case HIF_EVENT_IND_BSSLOST:
			schedule_delayed_work(&wvif->beacon_loss_work, 0);
			break;
		case HIF_EVENT_IND_BSSREGAINED:
			cancel_delayed_work(&wvif->beacon_loss_work);
			break;
		case HIF_EVENT_IND_RCPI_RSSI:
			wfx_event_report_rssi(wvif,
					      event->evt.event_data.rcpi_rssi);
			break;
		case HIF_EVENT_IND_PS_MODE_ERROR:
			dev_warn(wvif->wdev->dev,
				 "error while processing power save request\n");
			break;
		default:
			dev_warn(wvif->wdev->dev,
				 "unhandled event indication: %.2x\n",
				 event->evt.event_id);
			break;
		}
	}
	__wfx_free_event_queue(&list);
}

// Call it with wdev->conf_mutex locked
static void wfx_do_unjoin(struct wfx_vif *wvif)
{
@@ -351,9 +292,6 @@ static void wfx_do_unjoin(struct wfx_vif *wvif)
	wfx_tx_policy_init(wvif);
	if (wvif_count(wvif->wdev) <= 1)
		hif_set_block_ack_policy(wvif, 0xFF, 0xFF);
	wfx_free_event_queue(wvif);
	cancel_work_sync(&wvif->event_handler_work);

	wfx_tx_unlock(wvif->wdev);
	cancel_delayed_work_sync(&wvif->beacon_loss_work);
}
@@ -844,10 +782,6 @@ int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
	wvif->wep_default_key_id = -1;
	INIT_WORK(&wvif->wep_key_work, wfx_wep_key_work);

	spin_lock_init(&wvif->event_queue_lock);
	INIT_LIST_HEAD(&wvif->event_queue);
	INIT_WORK(&wvif->event_handler_work, wfx_event_handler_work);

	init_completion(&wvif->set_pm_mode_complete);
	complete(&wvif->set_pm_mode_complete);
	INIT_WORK(&wvif->tx_policy_upload_work, wfx_tx_policy_upload_work);
@@ -904,9 +838,7 @@ void wfx_remove_interface(struct ieee80211_hw *hw,
	/* FIXME: In add to reset MAC address, try to reset interface */
	hif_set_macaddr(wvif, NULL);

	wfx_free_event_queue(wvif);
	cancel_delayed_work_sync(&wvif->beacon_loss_work);

	wdev->vif[wvif->id] = NULL;
	wvif->vif = NULL;

+1 −5
Original line number Diff line number Diff line
@@ -23,11 +23,6 @@ enum wfx_state {
	WFX_STATE_AP,
};

struct wfx_hif_event {
	struct list_head link;
	struct hif_ind_event evt;
};

struct wfx_sta_priv {
	int link_id;
	int vif_id;
@@ -79,6 +74,7 @@ void wfx_unassign_vif_chanctx(struct ieee80211_hw *hw,

// WSM Callbacks
void wfx_suspend_resume_mc(struct wfx_vif *wvif, enum sta_notify_cmd cmd);
void wfx_event_report_rssi(struct wfx_vif *wvif, u8 raw_rcpi_rssi);

// Other Helpers
u32 wfx_rate_mask_to_hw(struct wfx_dev *wdev, u32 rates);
+0 −4
Original line number Diff line number Diff line
@@ -98,10 +98,6 @@ struct wfx_vif {
	struct ieee80211_scan_request *scan_req;

	struct completion	set_pm_mode_complete;

	struct list_head	event_queue;
	spinlock_t		event_queue_lock;
	struct work_struct	event_handler_work;
};

static inline struct wfx_vif *wdev_to_wvif(struct wfx_dev *wdev, int vif_id)