Commit 5f561f68 authored by Bartosz.Markowski@tieto.com's avatar Bartosz.Markowski@tieto.com Committed by John W. Linville
Browse files

wlcore/wl12xx: implement better beacon loss handling



Make use of REGAINED_BSS_EVENT and instead of reporting connection
loss immediately on each BEACON_LOSE event, try if not regained
in reasonable period of time.

Signed-off-by: default avatarbartosz.markowski <bartosz.markowski@tieto.com>
Signed-off-by: default avatarLuciano Coelho <coelho@ti.com>
parent 161f17b5
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -413,6 +413,7 @@ int wlcore_boot_run_firmware(struct wl1271 *wl)

	/* unmask required mbox events  */
	wl->event_mask = BSS_LOSE_EVENT_ID |
		REGAINED_BSS_EVENT_ID |
		SCAN_COMPLETE_EVENT_ID |
		ROLE_STOP_COMPLETE_EVENT_ID |
		RSSI_SNR_TRIGGER_0_EVENT_ID |
+12 −17
Original line number Diff line number Diff line
@@ -103,7 +103,6 @@ static int wl1271_event_process(struct wl1271 *wl)
	struct ieee80211_vif *vif;
	struct wl12xx_vif *wlvif;
	u32 vector;
	bool beacon_loss = false;
	bool disconnect_sta = false;
	unsigned long sta_bitmap = 0;

@@ -141,20 +140,23 @@ static int wl1271_event_process(struct wl1271 *wl)
					       mbox->soft_gemini_sense_info);

	/*
	 * The BSS_LOSE_EVENT_ID is only needed while psm (and hence beacon
	 * filtering) is enabled. Without PSM, the stack will receive all
	 * beacons and can detect beacon loss by itself.
	 *
	 * As there's possibility that the driver disables PSM before receiving
	 * BSS_LOSE_EVENT, beacon loss has to be reported to the stack.
	 *
	 * We are HW_MONITOR device. On beacon loss - queue
	 * connection loss work. Cancel it on REGAINED event.
	 */
	if (vector & BSS_LOSE_EVENT_ID) {
		/* TODO: check for multi-role */
		int delay = wl->conf.conn.synch_fail_thold *
					wl->conf.conn.bss_lose_timeout;
		wl1271_info("Beacon loss detected.");
		cancel_delayed_work_sync(&wl->connection_loss_work);
		ieee80211_queue_delayed_work(wl->hw, &wl->connection_loss_work,
		      msecs_to_jiffies(delay));
	}

		/* indicate to the stack, that beacons have been lost */
		beacon_loss = true;
	if (vector & REGAINED_BSS_EVENT_ID) {
		/* TODO: check for multi-role */
		wl1271_info("Beacon regained.");
		cancel_delayed_work_sync(&wl->connection_loss_work);
	}

	if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) {
@@ -257,13 +259,6 @@ static int wl1271_event_process(struct wl1271 *wl)
			rcu_read_unlock();
		}
	}

	if (beacon_loss)
		wl12xx_for_each_wlvif_sta(wl, wlvif) {
			vif = wl12xx_wlvif_to_vif(wlvif);
			ieee80211_connection_loss(vif);
		}

	return 0;
}

+35 −0
Original line number Diff line number Diff line
@@ -1120,6 +1120,7 @@ int wl1271_plt_stop(struct wl1271 *wl)
	cancel_work_sync(&wl->recovery_work);
	cancel_delayed_work_sync(&wl->elp_work);
	cancel_delayed_work_sync(&wl->tx_watchdog_work);
	cancel_delayed_work_sync(&wl->connection_loss_work);

	mutex_lock(&wl->mutex);
	wl1271_power_off(wl);
@@ -1753,6 +1754,7 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
	cancel_work_sync(&wl->tx_work);
	cancel_delayed_work_sync(&wl->elp_work);
	cancel_delayed_work_sync(&wl->tx_watchdog_work);
	cancel_delayed_work_sync(&wl->connection_loss_work);

	/* let's notify MAC80211 about the remaining pending TX frames */
	wl12xx_tx_reset(wl, true);
@@ -3705,6 +3707,9 @@ sta_not_found:
			do_join = true;
			set_assoc = true;

			/* Cancel connection_loss_work */
			cancel_delayed_work_sync(&wl->connection_loss_work);

			/*
			 * use basic rates from AP, and determine lowest rate
			 * to use with control frames.
@@ -4815,6 +4820,34 @@ static struct bin_attribute fwlog_attr = {
	.read = wl1271_sysfs_read_fwlog,
};

void wl1271_connection_loss_work(struct work_struct *work)
{
	struct delayed_work *dwork;
	struct wl1271 *wl;
	struct ieee80211_vif *vif;
	struct wl12xx_vif *wlvif;

	dwork = container_of(work, struct delayed_work, work);
	wl = container_of(dwork, struct wl1271, connection_loss_work);

	wl1271_info("Connection loss work.");

	mutex_lock(&wl->mutex);

	if (unlikely(wl->state == WL1271_STATE_OFF))
		goto out;

	/* Call mac80211 connection loss */
	wl12xx_for_each_wlvif_sta(wl, wlvif) {
		if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
			goto out;
		vif = wl12xx_wlvif_to_vif(wlvif);
		ieee80211_connection_loss(vif);
	}
out:
	mutex_unlock(&wl->mutex);
}

static void wl12xx_derive_mac_addresses(struct wl1271 *wl,
					u32 oui, u32 nic, int n)
{
@@ -5070,6 +5103,8 @@ struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size)
	INIT_WORK(&wl->recovery_work, wl1271_recovery_work);
	INIT_DELAYED_WORK(&wl->scan_complete_work, wl1271_scan_complete_work);
	INIT_DELAYED_WORK(&wl->tx_watchdog_work, wl12xx_tx_watchdog_work);
	INIT_DELAYED_WORK(&wl->connection_loss_work,
			  wl1271_connection_loss_work);

	wl->freezable_wq = create_freezable_workqueue("wl12xx_wq");
	if (!wl->freezable_wq) {
+3 −0
Original line number Diff line number Diff line
@@ -243,6 +243,9 @@ struct wl1271 {
	struct wl1271_scan scan;
	struct delayed_work scan_complete_work;

	/* Connection loss work */
	struct delayed_work connection_loss_work;

	bool sched_scanning;

	/* The current band */