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

Commit 9437a248 authored by Larry Finger's avatar Larry Finger Committed by John W. Linville
Browse files

rtlwifi: rtl8192cu: Fix problem that prevents reassociation

The driver was failing to clear the BSSID when a disconnect happened. That
prevented a reconnection. This problem is reported at
https://bugzilla.redhat.com/show_bug.cgi?id=789605,
https://bugzilla.redhat.com/show_bug.cgi?id=866786,
https://bugzilla.redhat.com/show_bug.cgi?id=906734, and
https://bugzilla.kernel.org/show_bug.cgi?id=46171

.

Thanks to Jussi Kivilinna for making the critical observation
that led to the solution.

Reported-by: default avatarJussi Kivilinna <jussi.kivilinna@iki.fi>
Tested-by: default avatarJussi Kivilinna <jussi.kivilinna@iki.fi>
Tested-by: default avatarAlessandro Lannocca <alessandro.lannocca@gmail.com>
Signed-off-by: default avatarLarry Finger <Larry.Finger@lwfinger.net>
Cc: Stable <stable@vger.kernel.org>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 5818a46a
Loading
Loading
Loading
Loading
+35 −52
Original line number Diff line number Diff line
@@ -1376,75 +1376,58 @@ void rtl92cu_card_disable(struct ieee80211_hw *hw)
}

void rtl92cu_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid)
{
	/* dummy routine needed for callback from rtl_op_configure_filter() */
}

/*========================================================================== */

static void _rtl92cu_set_check_bssid(struct ieee80211_hw *hw,
			      enum nl80211_iftype type)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	u32 reg_rcr = rtl_read_dword(rtlpriv, REG_RCR);
	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
	struct rtl_phy *rtlphy = &(rtlpriv->phy);
	u8 filterout_non_associated_bssid = false;
	u32 reg_rcr = rtl_read_dword(rtlpriv, REG_RCR);

	switch (type) {
	case NL80211_IFTYPE_ADHOC:
	case NL80211_IFTYPE_STATION:
		filterout_non_associated_bssid = true;
		break;
	case NL80211_IFTYPE_UNSPECIFIED:
	case NL80211_IFTYPE_AP:
	default:
		break;
	}
	if (filterout_non_associated_bssid) {
	if (rtlpriv->psc.rfpwr_state != ERFON)
		return;

	if (check_bssid) {
		u8 tmp;
		if (IS_NORMAL_CHIP(rtlhal->version)) {
			switch (rtlphy->current_io_type) {
			case IO_CMD_RESUME_DM_BY_SCAN:
			reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN);
				rtlpriv->cfg->ops->set_hw_reg(hw,
						 HW_VAR_RCR, (u8 *)(&reg_rcr));
				/* enable update TSF */
				_rtl92cu_set_bcn_ctrl_reg(hw, 0, BIT(4));
				break;
			case IO_CMD_PAUSE_DM_BY_SCAN:
				reg_rcr &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);
				rtlpriv->cfg->ops->set_hw_reg(hw,
						 HW_VAR_RCR, (u8 *)(&reg_rcr));
				/* disable update TSF */
				_rtl92cu_set_bcn_ctrl_reg(hw, BIT(4), 0);
				break;
			}
			tmp = BIT(4);
		} else {
			reg_rcr |= (RCR_CBSSID);
			rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR,
						      (u8 *)(&reg_rcr));
			_rtl92cu_set_bcn_ctrl_reg(hw, 0, (BIT(4)|BIT(5)));
			reg_rcr |= RCR_CBSSID;
			tmp = BIT(4) | BIT(5);
		}
	} else if (filterout_non_associated_bssid == false) {
		if (IS_NORMAL_CHIP(rtlhal->version)) {
			reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN));
		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR,
					      (u8 *) (&reg_rcr));
			_rtl92cu_set_bcn_ctrl_reg(hw, BIT(4), 0);
		_rtl92cu_set_bcn_ctrl_reg(hw, 0, tmp);
	} else {
			reg_rcr &= (~RCR_CBSSID);
			rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR,
						      (u8 *)(&reg_rcr));
			_rtl92cu_set_bcn_ctrl_reg(hw, (BIT(4)|BIT(5)), 0);
		u8 tmp;
		if (IS_NORMAL_CHIP(rtlhal->version)) {
			reg_rcr &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);
			tmp = BIT(4);
		} else {
			reg_rcr &= ~RCR_CBSSID;
			tmp = BIT(4) | BIT(5);
		}
		reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN));
		rtlpriv->cfg->ops->set_hw_reg(hw,
					      HW_VAR_RCR, (u8 *) (&reg_rcr));
		_rtl92cu_set_bcn_ctrl_reg(hw, tmp, 0);
	}
}

/*========================================================================== */

int rtl92cu_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);

	if (_rtl92cu_set_media_status(hw, type))
		return -EOPNOTSUPP;
	_rtl92cu_set_check_bssid(hw, type);

	if (rtlpriv->mac80211.link_state == MAC80211_LINKED) {
		if (type != NL80211_IFTYPE_AP)
			rtl92cu_set_check_bssid(hw, true);
	} else {
		rtl92cu_set_check_bssid(hw, false);
	}

	return 0;
}