[PATCH] staging: brcm80211: implementation of RFKILL functionality

Arend van Spriel arend at broadcom.com
Wed Mar 9 18:58:19 UTC 2011


Resubmitted the patch to be included in the staging-linus branch.

Only hardware switch state needs to be handled by driver. RFKILL is
informed when hardware switch is activated. MAC80211 rfkill_poll
callback is used to check hardware switch deactivation.

Reviewed-by: Brett Rudley <brudley at broadcom.com>
Reviewed-by: Henry Ptasinski <henryp at broadcom.com>
Signed-off-by: Arend van Spriel <arend at broadcom.com>
---
 drivers/staging/brcm80211/sys/wl_export.h    |    1 +
 drivers/staging/brcm80211/sys/wl_mac80211.c  |   38 +++++++++++++++++++++++++-
 drivers/staging/brcm80211/sys/wlc_bmac.c     |    9 ++----
 drivers/staging/brcm80211/sys/wlc_mac80211.c |    9 ++++++
 drivers/staging/brcm80211/sys/wlc_pub.h      |    1 +
 5 files changed, 51 insertions(+), 7 deletions(-)

diff --git a/drivers/staging/brcm80211/sys/wl_export.h b/drivers/staging/brcm80211/sys/wl_export.h
index aa8b5a3..16c626a 100644
--- a/drivers/staging/brcm80211/sys/wl_export.h
+++ b/drivers/staging/brcm80211/sys/wl_export.h
@@ -34,6 +34,7 @@ extern void wl_down(struct wl_info *wl);
 extern void wl_txflowcontrol(struct wl_info *wl, struct wl_if *wlif, bool state,
 			     int prio);
 extern bool wl_alloc_dma_resources(struct wl_info *wl, uint dmaddrwidth);
+extern bool wl_rfkill_set_hw_state(struct wl_info *wl);
 
 /* timer functions */
 struct wl_timer;
diff --git a/drivers/staging/brcm80211/sys/wl_mac80211.c b/drivers/staging/brcm80211/sys/wl_mac80211.c
index cd8392b..cd5ef37 100644
--- a/drivers/staging/brcm80211/sys/wl_mac80211.c
+++ b/drivers/staging/brcm80211/sys/wl_mac80211.c
@@ -172,6 +172,7 @@ static int wl_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 static int wl_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 			   enum ieee80211_ampdu_mlme_action action,
 			   struct ieee80211_sta *sta, u16 tid, u16 *ssn);
+static void wl_ops_rfkill_poll(struct ieee80211_hw *hw);
 
 static int wl_ops_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
@@ -192,14 +193,18 @@ static int wl_ops_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 static int wl_ops_start(struct ieee80211_hw *hw)
 {
 	struct wl_info *wl = hw->priv;
+	bool blocked;
 	/*
 	  struct ieee80211_channel *curchan = hw->conf.channel;
 	  WL_NONE("%s : Initial channel: %d\n", __func__, curchan->hw_value);
 	*/
 
-	WL_LOCK(wl);
 	ieee80211_wake_queues(hw);
+	WL_LOCK(wl);
+	blocked = wl_rfkill_set_hw_state(wl);
 	WL_UNLOCK(wl);
+	if (!blocked)
+		wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
 
 	return 0;
 }
@@ -621,6 +626,19 @@ wl_ampdu_action(struct ieee80211_hw *hw,
 	return 0;
 }
 
+static void wl_ops_rfkill_poll(struct ieee80211_hw *hw)
+{
+	struct wl_info *wl = HW_TO_WL(hw);
+	bool blocked;
+
+	WL_LOCK(wl);
+	blocked = wlc_check_radio_disabled(wl->wlc);
+	WL_UNLOCK(wl);
+
+	WL_ERROR("wl: rfkill_poll: %d\n", blocked);
+	wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, blocked);
+}
+
 static const struct ieee80211_ops wl_ops = {
 	.tx = wl_ops_tx,
 	.start = wl_ops_start,
@@ -642,6 +660,7 @@ static const struct ieee80211_ops wl_ops = {
 	.sta_add = wl_sta_add,
 	.sta_remove = wl_sta_remove,
 	.ampdu_action = wl_ampdu_action,
+	.rfkill_poll = wl_ops_rfkill_poll,
 };
 
 static int wl_set_hint(struct wl_info *wl, char *abbrev)
@@ -1180,6 +1199,10 @@ static void wl_remove(struct pci_dev *pdev)
 		return;
 	}
 	if (wl->wlc) {
+		/* make sure rfkill is not using driver */
+		wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false);
+		wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
+
 		ieee80211_unregister_hw(hw);
 		WL_LOCK(wl);
 		wl_down(wl);
@@ -1853,3 +1876,16 @@ int wl_check_firmwares(struct wl_info *wl)
 	return rc;
 }
 
+bool wl_rfkill_set_hw_state(struct wl_info *wl)
+{
+	bool blocked = wlc_check_radio_disabled(wl->wlc);
+
+	WL_ERROR("%s: update hw state: blocked=%s\n", __func__,
+		 blocked ? "true" : "false");
+	WL_UNLOCK(wl);
+	wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, blocked);
+	if (blocked)
+		wiphy_rfkill_start_polling(wl->pub->ieee_hw->wiphy);
+	WL_LOCK(wl);
+	return blocked;
+}
diff --git a/drivers/staging/brcm80211/sys/wlc_bmac.c b/drivers/staging/brcm80211/sys/wlc_bmac.c
index 69f600a..e837b04 100644
--- a/drivers/staging/brcm80211/sys/wlc_bmac.c
+++ b/drivers/staging/brcm80211/sys/wlc_bmac.c
@@ -428,14 +428,11 @@ bool BCMFASTPATH wlc_dpc(struct wlc_info *wlc, bool bounded)
 	}
 
 	if (macintstatus & MI_RFDISABLE) {
-#if defined(BCMDBG)
-		u32 rfd = R_REG(wlc_hw->osh, &regs->phydebug) & PDBG_RFD;
-#endif
-
-		WL_ERROR("wl%d: MAC Detected a change on the RF Disable Input 0x%x\n",
-			 wlc_hw->unit, rfd);
+		WL_TRACE("wl%d: BMAC Detected change on RF Disable Input\n",
+			 wlc_hw->unit);
 
 		WLCNTINCR(wlc->pub->_cnt->rfdisable);
+		wl_rfkill_set_hw_state(wlc->wl);
 	}
 
 	/* send any enq'd tx packets. Just makes sure to jump start tx */
diff --git a/drivers/staging/brcm80211/sys/wlc_mac80211.c b/drivers/staging/brcm80211/sys/wlc_mac80211.c
index e37e805..73b5b06 100644
--- a/drivers/staging/brcm80211/sys/wlc_mac80211.c
+++ b/drivers/staging/brcm80211/sys/wlc_mac80211.c
@@ -2314,6 +2314,15 @@ static void wlc_down_led_upd(struct wlc_info *wlc)
 	}
 }
 
+/* update hwradio status and return it */
+bool wlc_check_radio_disabled(struct wlc_info *wlc)
+{
+	wlc_radio_hwdisable_upd(wlc);
+
+	return mboolisset(wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE)
+		? true : false;
+}
+
 void wlc_radio_disable(struct wlc_info *wlc)
 {
 	if (!wlc->pub->up) {
diff --git a/drivers/staging/brcm80211/sys/wlc_pub.h b/drivers/staging/brcm80211/sys/wlc_pub.h
index aff4130..5940dc4 100644
--- a/drivers/staging/brcm80211/sys/wlc_pub.h
+++ b/drivers/staging/brcm80211/sys/wlc_pub.h
@@ -604,6 +604,7 @@ extern void wlc_getrand(struct wlc_info *wlc, u8 *buf, int len);
 struct scb;
 extern void wlc_ps_on(struct wlc_info *wlc, struct scb *scb);
 extern void wlc_ps_off(struct wlc_info *wlc, struct scb *scb, bool discard);
+extern bool wlc_check_radio_disabled(struct wlc_info *wlc);
 extern bool wlc_radio_monitor_stop(struct wlc_info *wlc);
 
 #if defined(BCMDBG)
-- 
1.7.1





More information about the devel mailing list