rtlpriv->cfg->ops->get_hw_reg(hw, HAL_DEF_WOWLAN,
(u8 *)(&support_remote_wakeup)); /* here is must, because adhoc do stop and start, * but stop with RFOFF may cause something wrong, * like adhoc TP
*/ if (unlikely(ppsc->rfpwr_state == ERFOFF))
rtl_ips_nic_on(hw);
mutex_lock(&rtlpriv->locks.conf_mutex); /* if wowlan supported, DON'T clear connected info */ if (!(support_remote_wakeup &&
rtlhal->enter_pnp_sleep)) {
mac->link_state = MAC80211_NOLINK;
eth_zero_addr(mac->bssid);
mac->vendor = PEER_UNKNOWN;
* Therefore, we need translate mask_from_OS to mask_to_hw. * We should left-shift mask by 6 bits, then set the new bit[0~5] = 0, * because new mask[0~5] means 'SA', but our HW packet begins from LLC, * bit[0~5] corresponds to first 6 Bytes in LLC, they just don't match.
******************************************************************************/
/* Shift 6 bits */ for (j = 0; j < mask_len - 1; j++) {
mask[j] = mask_os[j] >> 6;
mask[j] |= (mask_os[j + 1] & 0x3F) << 2;
}
mask[j] = (mask_os[j] >> 6) & 0x3F; /* Set bit 0-5 to zero */
mask[0] &= 0xC0;
/* To get the wake up pattern from the mask. * We do not count first 12 bits which means * DA[6] and SA[6] in the pattern to match HW design.
*/
len = 0; for (j = 12; j < patterns[i].pattern_len; j++) { if ((mask_os[j / 8] >> (j % 8)) & 0x01) {
content[len] = pattern_os[j];
len++;
}
}
/*For IPS */ if (changed & IEEE80211_CONF_CHANGE_IDLE) { if (hw->conf.flags & IEEE80211_CONF_IDLE)
rtl_ips_nic_off(hw); else
rtl_ips_nic_on(hw);
} else { /* *although rfoff may not cause by ips, but we will *check the reason in set_rf_power_state function
*/ if (unlikely(ppsc->rfpwr_state == ERFOFF))
rtl_ips_nic_on(hw);
}
/*For LPS */ if ((changed & IEEE80211_CONF_CHANGE_PS) &&
rtlpriv->psc.swctrl_lps && !rtlpriv->psc.fwctrl_lps) {
cancel_delayed_work(&rtlpriv->works.ps_work);
cancel_delayed_work(&rtlpriv->works.ps_rfon_wq); if (conf->flags & IEEE80211_CONF_PS) {
rtlpriv->psc.sw_ps_enabled = true; /* sleep here is must, or we may recv the beacon and * cause mac80211 into wrong ps state, this will cause * power save nullfunc send fail, and further cause * pkt loss, So sleep must quickly but not immediatly * because that will cause nullfunc send by mac80211 * fail, and cause pkt loss, we have tested that 5mA
* is worked very well */ if (!rtlpriv->psc.multi_buffered)
queue_delayed_work(rtlpriv->works.rtl_wq,
&rtlpriv->works.ps_work,
MSECS(5));
} else {
rtl_swlps_rf_awake(hw);
rtlpriv->psc.sw_ps_enabled = false;
}
}
/* channel_type is for 20&40M */ if (width < NL80211_CHAN_WIDTH_80)
channel_type =
cfg80211_get_chandef_type(&hw->conf.chandef); if (mac->act_scanning)
mac->n_channels++;
/* *because we should back channel to *current_network.chan in scanning, *So if set_chan == current_network.chan *we should set it. *because mac80211 tell us wrong bw40 *info for cisco1253 bw20, so we modify *it here based on UPPER & LOWER
*/
if (width >= NL80211_CHAN_WIDTH_80) { if (width == NL80211_CHAN_WIDTH_80) {
u32 center = hw->conf.chandef.center_freq1;
u32 primary =
(u32)hw->conf.chandef.chan->center_freq;
break; default:
mac->bw_40 = false;
mac->bw_80 = false;
pr_err("switch case %#x not processed\n",
channel_type); break;
}
}
if (wide_chan <= 0)
wide_chan = 1;
/* In scanning, when before we offchannel we may send a ps=1 * null to AP, and then we may send a ps = 0 null to AP quickly, * but first null may have caused AP to put lots of packet to * hw tx buffer. These packets must be tx'd before we go off * channel so we must delay more time to let AP flush these * packets before going offchannel, or dis-association or * delete BA will be caused by AP
*/ if (rtlpriv->mac80211.offchan_delay) {
rtlpriv->mac80211.offchan_delay = false;
mdelay(50);
}
/* if ssid not set to hw don't check bssid * here just used for linked scanning, & linked * and nolink check bssid is set in set network_type
*/ if (changed_flags & FIF_BCN_PRBRESP_PROMISC &&
mac->link_state >= MAC80211_LINKED) { if (mac->opmode != NL80211_IFTYPE_AP &&
mac->opmode != NL80211_IFTYPE_MESH_POINT) { if (*new_flags & FIF_BCN_PRBRESP_PROMISC)
rtlpriv->cfg->ops->set_chk_bssid(hw, false); else
rtlpriv->cfg->ops->set_chk_bssid(hw, true); if (update_rcr)
update_rcr = false;
}
}
if (changed_flags & FIF_CONTROL) { if (*new_flags & FIF_CONTROL) {
mac->rx_conf |= rtlpriv->cfg->maps[MAC_RCR_ACF];
rtl_dbg(rtlpriv, COMP_MAC80211, DBG_LOUD, "Enable receive control frame.\n");
} else {
mac->rx_conf &= ~rtlpriv->cfg->maps[MAC_RCR_ACF];
rtl_dbg(rtlpriv, COMP_MAC80211, DBG_LOUD, "Disable receive control frame.\n");
} if (!update_rcr)
update_rcr = true;
}
if (changed_flags & FIF_OTHER_BSS) { if (*new_flags & FIF_OTHER_BSS) {
mac->rx_conf |= rtlpriv->cfg->maps[MAC_RCR_AAP];
rtl_dbg(rtlpriv, COMP_MAC80211, DBG_LOUD, "Enable receive other BSS's frame.\n");
} else {
mac->rx_conf &= ~rtlpriv->cfg->maps[MAC_RCR_AAP];
rtl_dbg(rtlpriv, COMP_MAC80211, DBG_LOUD, "Disable receive other BSS's frame.\n");
} if (!update_rcr)
update_rcr = true;
}
if (update_rcr)
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR,
(u8 *)(&mac->rx_conf));
}
mstatus = RT_MEDIA_CONNECT; /* we should reset all sec info & cam * before set cam after linked, we should not * reset in disassoc, that will cause tkip->wep
* fail because some flag will be wrong */ /* reset sec info */
rtl_cam_reset_sec_info(hw); /* reset cam to fix wep fail issue
* when change from wpa to wep */
rtl_cam_reset_all_entry(hw);
if (changed & BSS_CHANGED_ERP_PREAMBLE) {
rtl_dbg(rtlpriv, COMP_MAC80211, DBG_LOUD, "BSS_CHANGED_ERP_PREAMBLE use short preamble:%x\n",
bss_conf->use_short_preamble);
if (sta->deflink.ht_cap.ht_supported) { if (rtlhal->current_bandtype == BAND_ON_2_4G)
mac->mode = WIRELESS_MODE_N_24G; else
mac->mode = WIRELESS_MODE_N_5G;
}
if (sta->deflink.vht_cap.vht_supported) { if (rtlhal->current_bandtype == BAND_ON_5G)
mac->mode = WIRELESS_MODE_AC_5G; else
mac->mode = WIRELESS_MODE_AC_24G;
}
/* just station need it, because ibss & ap mode will
* set in sta_add, and will be NULL here */ if (vif->type == NL80211_IFTYPE_STATION) { struct rtl_sta_info *sta_entry;
if (sta->deflink.vht_cap.vht_supported)
mac->vht_enable = true;
if (changed & BSS_CHANGED_BASIC_RATES) { /* for 5G must << RATE_6M_INDEX = 4,
* because 5G have no cck rate*/ if (rtlhal->current_bandtype == BAND_ON_5G)
basic_rates = sta->deflink.supp_rates[1] << 4; else
basic_rates = sta->deflink.supp_rates[0];
if (rtlpriv->link_info.higher_busytraffic) return;
/* p2p will use 1/6/11 to scan */ if (mac->n_channels == 3)
mac->p2p_in_use = true; else
mac->p2p_in_use = false;
mac->n_channels = 0; /* Dul mac */
rtlpriv->rtlhal.load_imrandiqk_setting_for2g = false;
/* <2> get key_idx */
key_idx = (u8) (key->keyidx); if (key_idx > 3) goto out_unlock; /* <3> if pairwise key enable_hw_sec */
group_key = !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE);
/* wep always be group key, but there are two conditions: * 1) wep only: is just for wep enc, in this condition * rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION * will be true & enable_hw_sec will be set when wep * ke setting. * 2) wep(group) + AES(pairwise): some AP like cisco * may use it, in this condition enable_hw_sec will not
* be set when wep key setting */ /* we must reset sec_info after lingked before set key,
* or some flag will be wrong*/ if (vif->type == NL80211_IFTYPE_AP ||
vif->type == NL80211_IFTYPE_MESH_POINT) { if (!group_key || key_type == WEP40_ENCRYPTION ||
key_type == WEP104_ENCRYPTION) { if (group_key)
wep_only = true;
rtlpriv->cfg->ops->enable_hw_sec(hw);
}
} else { if (!group_key || vif->type == NL80211_IFTYPE_ADHOC ||
rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION) { if (rtlpriv->sec.pairwise_enc_algorithm ==
NO_ENCRYPTION &&
(key_type == WEP40_ENCRYPTION ||
key_type == WEP104_ENCRYPTION))
wep_only = true;
rtlpriv->sec.pairwise_enc_algorithm = key_type;
rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG, "set enable_hw_sec, key_type:%x(OPEN:0 WEP40:1 TKIP:2 AES:4 WEP104:5)\n",
key_type);
rtlpriv->cfg->ops->enable_hw_sec(hw);
}
} /* <4> set key based on cmd */ switch (cmd) { case SET_KEY: if (wep_only) {
rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG, "set WEP(group/pairwise) key\n"); /* Pairwise key with an assigned MAC address. */
rtlpriv->sec.pairwise_enc_algorithm = key_type;
rtlpriv->sec.group_enc_algorithm = key_type; /*set local buf about wep key. */
memcpy(rtlpriv->sec.key_buf[key_idx],
key->key, key->keylen);
rtlpriv->sec.key_len[key_idx] = key->keylen;
eth_zero_addr(mac_addr);
} elseif (group_key) { /* group key */
rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG, "set group key\n"); /* group key */
rtlpriv->sec.group_enc_algorithm = key_type; /*set local buf about group key. */
memcpy(rtlpriv->sec.key_buf[key_idx],
key->key, key->keylen);
rtlpriv->sec.key_len[key_idx] = key->keylen;
eth_broadcast_addr(mac_addr);
} else { /* pairwise key */
rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG, "set pairwise key\n"); if (!sta) {
WARN_ONCE(true, "rtlwifi: pairwise key without mac_addr\n");
err = -EOPNOTSUPP; goto out_unlock;
} /* Pairwise key with an assigned MAC address. */
rtlpriv->sec.pairwise_enc_algorithm = key_type; /*set local buf about pairwise key. */
memcpy(rtlpriv->sec.key_buf[PAIRWISE_KEYIDX],
key->key, key->keylen);
rtlpriv->sec.key_len[PAIRWISE_KEYIDX] = key->keylen;
rtlpriv->sec.pairwise_key =
rtlpriv->sec.key_buf[PAIRWISE_KEYIDX];
memcpy(mac_addr, sta->addr, ETH_ALEN);
}
rtlpriv->cfg->ops->set_key(hw, key_idx, mac_addr,
group_key, key_type, wep_only, false); /* <5> tell mac80211 do something: */ /*must use sw generate IV, or can not work !!!!. */
key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
key->hw_key_idx = key_idx; if (key_type == TKIP_ENCRYPTION)
key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; /*use software CCMP encryption for management frames (MFP) */ if (key_type == AESCCMP_ENCRYPTION)
key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; break; case DISABLE_KEY:
rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG, "disable key delete one entry\n"); /*set local buf about wep key. */ if (vif->type == NL80211_IFTYPE_AP ||
vif->type == NL80211_IFTYPE_MESH_POINT) { if (sta)
rtl_cam_del_entry(hw, sta->addr);
}
memset(rtlpriv->sec.key_buf[key_idx], 0, key->keylen);
rtlpriv->sec.key_len[key_idx] = 0;
eth_zero_addr(mac_addr); /* *mac80211 will delete entries one by one, *so don't use rtl_cam_reset_all_entry *or clear all entry here.
*/
rtl_wait_tx_report_acked(hw, 500); /* wait 500ms for TX ack */
/* this function is called by mac80211 to flush tx buffer * before switch channle or power save, or tx buffer packet * maybe send after offchannel or rf sleep, this may cause
* dis-association by AP */ staticvoid rtl_op_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
u32 queues, bool drop)
{ struct rtl_priv *rtlpriv = rtl_priv(hw);
if (rtlpriv->intf_ops->flush)
rtlpriv->intf_ops->flush(hw, queues, drop);
}
if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CU)
schedule_work(&rtlpriv->works.update_beacon_work);
return 0;
}
/* Description: * This routine deals with the Power Configuration CMD * parsing for RTL8723/RTL8188E Series IC. * Assumption: * We should follow specific format that was released from HW SD.
*/ bool rtl_hal_pwrseqcmdparsing(struct rtl_priv *rtlpriv, u8 cut_version,
u8 faversion, u8 interface_type, struct wlan_pwr_cfg pwrcfgcmd[])
{ struct wlan_pwr_cfg cfg_cmd; bool polling_bit = false;
u32 ary_idx = 0;
u8 value = 0;
u32 offset = 0;
u32 polling_count = 0;
u32 max_polling_cnt = 5000;
if ((GET_PWR_CFG_FAB_MASK(cfg_cmd)&faversion) &&
(GET_PWR_CFG_CUT_MASK(cfg_cmd)&cut_version) &&
(GET_PWR_CFG_INTF_MASK(cfg_cmd)&interface_type)) { switch (GET_PWR_CFG_CMD(cfg_cmd)) { case PWR_CMD_READ:
rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE, "rtl_hal_pwrseqcmdparsing(): PWR_CMD_READ\n"); break; case PWR_CMD_WRITE:
rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE, "%s(): PWR_CMD_WRITE\n", __func__);
offset = GET_PWR_CFG_OFFSET(cfg_cmd);
/*Read the value from system register*/
value = rtl_read_byte(rtlpriv, offset);
value &= (~(GET_PWR_CFG_MASK(cfg_cmd)));
value |= (GET_PWR_CFG_VALUE(cfg_cmd) &
GET_PWR_CFG_MASK(cfg_cmd));
/*Write the value back to system register*/
rtl_write_byte(rtlpriv, offset, value); break; case PWR_CMD_POLLING:
rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE, "rtl_hal_pwrseqcmdparsing(): PWR_CMD_POLLING\n");
polling_bit = false;
offset = GET_PWR_CFG_OFFSET(cfg_cmd);
do {
value = rtl_read_byte(rtlpriv, offset);
value &= GET_PWR_CFG_MASK(cfg_cmd); if (value ==
(GET_PWR_CFG_VALUE(cfg_cmd) &
GET_PWR_CFG_MASK(cfg_cmd)))
polling_bit = true; else
udelay(10);
if (polling_count++ > max_polling_cnt) returnfalse;
} while (!polling_bit); break; case PWR_CMD_DELAY:
rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE, "%s: PWR_CMD_DELAY\n", __func__); if (GET_PWR_CFG_VALUE(cfg_cmd) ==
PWRSEQ_DELAY_US)
udelay(GET_PWR_CFG_OFFSET(cfg_cmd)); else
mdelay(GET_PWR_CFG_OFFSET(cfg_cmd)); break; case PWR_CMD_END:
rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE, "%s: PWR_CMD_END\n", __func__); returntrue; default:
WARN_ONCE(true, "rtlwifi: rtl_hal_pwrseqcmdparsing(): Unknown CMD!!\n"); break;
}
}
ary_idx++;
} while (1);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.