/** * ieee80211_set_qos_hdr - Fill in the QoS header if there is one. * * @sdata: local subif * @skb: packet to be updated */ void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) { struct ieee80211_hdr *hdr = (void *)skb->data; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); u8 *p; u8 ack_policy, tid; if (!ieee80211_is_data_qos(hdr->frame_control)) return; p = ieee80211_get_qos_ctl(hdr); tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; /* preserve EOSP bit */ ack_policy = *p & IEEE80211_QOS_CTL_EOSP; if (is_multicast_ether_addr(hdr->addr1) || sdata->noack_map & BIT(tid)) { ack_policy |= IEEE80211_QOS_CTL_ACK_POLICY_NOACK; info->flags |= IEEE80211_TX_CTL_NO_ACK; } /* qos header is 2 bytes */ *p++ = ack_policy | tid; if (ieee80211_vif_is_mesh(&sdata->vif)) { /* preserve RSPI and Mesh PS Level bit */ *p &= ((IEEE80211_QOS_CTL_RSPI | IEEE80211_QOS_CTL_MESH_PS_LEVEL) >> 8); /* Nulls don't have a mesh header (frame body) */ if (!ieee80211_is_qos_nullfunc(hdr->frame_control)) *p |= (IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT >> 8); } else {
/** * ieee80211_set_qos_hdr - Fill in the QoS header if there is one. * * @sdata: local subif * @skb: packet to be updated */ void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) { struct ieee80211_hdr *hdr = (void *)skb->data; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); u8 tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; u8 flags; u8 *p; if (!ieee80211_is_data_qos(hdr->frame_control)) return; p = ieee80211_get_qos_ctl(hdr); /* set up the first byte */ /* * preserve everything but the TID and ACK policy * (which we both write here) */ flags = *p & ~(IEEE80211_QOS_CTL_TID_MASK | IEEE80211_QOS_CTL_ACK_POLICY_MASK); if (is_multicast_ether_addr(hdr->addr1) || sdata->noack_map & BIT(tid)) { flags |= IEEE80211_QOS_CTL_ACK_POLICY_NOACK; info->flags |= IEEE80211_TX_CTL_NO_ACK; } *p = flags | tid; /* set up the second byte */ p++; if (ieee80211_vif_is_mesh(&sdata->vif)) { /* preserve RSPI and Mesh PS Level bit */ *p &= ((IEEE80211_QOS_CTL_RSPI | IEEE80211_QOS_CTL_MESH_PS_LEVEL) >> 8); /* Nulls don't have a mesh header (frame body) */ if (!ieee80211_is_qos_nullfunc(hdr->frame_control)) *p |= (IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT >> 8); } else {
void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, u32 changed) { struct ieee80211_local *local = sdata->local; static const u8 zero[ETH_ALEN] = { 0 }; if (!changed) return; if (sdata->vif.type == NL80211_IFTYPE_STATION) { /* * While not associated, claim a BSSID of all-zeroes * so that drivers don't do any weird things with the * BSSID at that time. */ if (sdata->vif.bss_conf.assoc) sdata->vif.bss_conf.bssid = sdata->u.mgd.bssid; else sdata->vif.bss_conf.bssid = zero; } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) sdata->vif.bss_conf.bssid = sdata->u.ibss.bssid; else if (sdata->vif.type == NL80211_IFTYPE_AP) sdata->vif.bss_conf.bssid = sdata->vif.addr; else if (sdata->vif.type == NL80211_IFTYPE_WDS) sdata->vif.bss_conf.bssid = NULL; else if (ieee80211_vif_is_mesh(&sdata->vif)) { sdata->vif.bss_conf.bssid = zero; } else { WARN_ON(1); return; } switch (sdata->vif.type) { case NL80211_IFTYPE_AP: case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_WDS: case NL80211_IFTYPE_MESH_POINT: break; default: /* do not warn to simplify caller in scan.c */ changed &= ~BSS_CHANGED_BEACON_ENABLED; if (WARN_ON(changed & BSS_CHANGED_BEACON)) return; break; } if (changed & BSS_CHANGED_BEACON_ENABLED) { if (local->quiescing || !ieee80211_sdata_running(sdata) || test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state)) { sdata->vif.bss_conf.enable_beacon = false; } else { /* * Beacon should be enabled, but AP mode must * check whether there is a beacon configured. */ switch (sdata->vif.type) { case NL80211_IFTYPE_AP: sdata->vif.bss_conf.enable_beacon = !!sdata->u.ap.beacon; break; case NL80211_IFTYPE_ADHOC: sdata->vif.bss_conf.enable_beacon = !!sdata->u.ibss.presp; break; #ifdef CONFIG_MAC80211_MESH case NL80211_IFTYPE_MESH_POINT: sdata->vif.bss_conf.enable_beacon = !!sdata->u.mesh.mesh_id_len; break; #endif default: /* not reached */ WARN_ON(1); break; } } } drv_bss_info_changed(local, sdata, &sdata->vif.bss_conf, changed); }
static void rate_control_pid_sample(struct rc_pid_info *pinfo, struct ieee80211_supported_band *sband, struct ieee80211_sta *sta, struct rc_pid_sta_info *spinfo) { struct rc_pid_rateinfo *rinfo = pinfo->rinfo; u32 pf; s32 err_avg; u32 err_prop; u32 err_int; u32 err_der; int adj, i, j, tmp; unsigned long period; /* In case nothing happened during the previous control interval, turn * the sharpening factor on. */ period = (HZ * pinfo->sampling_period + 500) / 1000; if (!period) period = 1; if (jiffies - spinfo->last_sample > 2 * period) spinfo->sharp_cnt = pinfo->sharpen_duration; spinfo->last_sample = jiffies; /* This should never happen, but in case, we assume the old sample is * still a good measurement and copy it. */ if (unlikely(spinfo->tx_num_xmit == 0)) pf = spinfo->last_pf; else { /* XXX: BAD HACK!!! */ struct sta_info *si = container_of(sta, struct sta_info, sta); pf = spinfo->tx_num_failed * 100 / spinfo->tx_num_xmit; if (ieee80211_vif_is_mesh(&si->sdata->vif) && pf == 100) mesh_plink_broken(si); pf <<= RC_PID_ARITH_SHIFT; si->fail_avg = ((pf + (spinfo->last_pf << 3)) / 9) >> RC_PID_ARITH_SHIFT; } spinfo->tx_num_xmit = 0; spinfo->tx_num_failed = 0; /* If we just switched rate, update the rate behaviour info. */ if (pinfo->oldrate != spinfo->txrate_idx) { i = rinfo[pinfo->oldrate].rev_index; j = rinfo[spinfo->txrate_idx].rev_index; tmp = (pf - spinfo->last_pf); tmp = RC_PID_DO_ARITH_RIGHT_SHIFT(tmp, RC_PID_ARITH_SHIFT); rinfo[j].diff = rinfo[i].diff + tmp; pinfo->oldrate = spinfo->txrate_idx; } rate_control_pid_normalize(pinfo, sband->n_bitrates); /* Compute the proportional, integral and derivative errors. */ err_prop = (pinfo->target << RC_PID_ARITH_SHIFT) - pf; err_avg = spinfo->err_avg_sc >> pinfo->smoothing_shift; spinfo->err_avg_sc = spinfo->err_avg_sc - err_avg + err_prop; err_int = spinfo->err_avg_sc >> pinfo->smoothing_shift; err_der = (pf - spinfo->last_pf) * (1 + pinfo->sharpen_factor * spinfo->sharp_cnt); spinfo->last_pf = pf; if (spinfo->sharp_cnt) spinfo->sharp_cnt--; #ifdef CONFIG_MAC80211_DEBUGFS rate_control_pid_event_pf_sample(&spinfo->events, pf, err_prop, err_int, err_der); #endif /* Compute the controller output. */ adj = (err_prop * pinfo->coeff_p + err_int * pinfo->coeff_i + err_der * pinfo->coeff_d); adj = RC_PID_DO_ARITH_RIGHT_SHIFT(adj, 2 * RC_PID_ARITH_SHIFT); /* Change rate. */ if (adj) rate_control_pid_adjust_rate(sband, sta, spinfo, adj, rinfo); }