pos = (u8 *)mgmt->u.beacon.variable;
end = skb->data + skb->len; while (pos < end) { if (pos + 2 + pos[1] > end) return NULL;
if (pos[0] == ie) return pos;
pos += 2 + pos[1];
} return NULL;
}
staticint p54_beacon_format_ie_tim(struct sk_buff *skb)
{ /* * the good excuse for this mess is ... the firmware. * The dummy TIM MUST be at the end of the beacon frame, * because it'll be overwritten!
*/
u8 *tim;
u8 dtim_len;
u8 dtim_period;
u8 *next;
tim = p54_find_ie(skb, WLAN_EID_TIM); if (!tim) return 0;
dtim_len = tim[1];
dtim_period = tim[3];
next = tim + 2 + dtim_len;
/* add the dummy at the end */
tim[0] = WLAN_EID_TIM;
tim[1] = 3;
tim[2] = 0;
tim[3] = dtim_period;
tim[4] = 0;
if (dtim_len > 3)
skb_trim(skb, skb->len - (dtim_len - 3));
return 0;
}
staticint p54_beacon_update(struct p54_common *priv, struct ieee80211_vif *vif)
{ struct ieee80211_tx_control control = { }; struct sk_buff *beacon; int ret;
beacon = ieee80211_beacon_get(priv->hw, vif, 0); if (!beacon) return -ENOMEM;
ret = p54_beacon_format_ie_tim(beacon); if (ret) return ret;
/* * During operation, the firmware takes care of beaconing. * The driver only needs to upload a new beacon template, once * the template was changed by the stack or userspace. * * LMAC API 3.2.2 also specifies that the driver does not need * to cancel the old beacon template by hand, instead the firmware * will release the previous one through the feedback mechanism.
*/
p54_tx_80211(priv->hw, &control, beacon);
priv->tsf_high32 = 0;
priv->tsf_low32 = 0;
mutex_lock(&priv->conf_mutex); if (priv->mode != NL80211_IFTYPE_MONITOR) {
mutex_unlock(&priv->conf_mutex); return -EOPNOTSUPP;
}
priv->vif = vif;
switch (vif->type) { case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_AP: case NL80211_IFTYPE_MESH_POINT:
priv->mode = vif->type; break; default:
mutex_unlock(&priv->conf_mutex); return -EOPNOTSUPP;
}
/* * LMAC API 3.2.2 states that any active beacon template must be * canceled by the driver before attempting a mode transition.
*/ if (le32_to_cpu(priv->beacon_req_id) != 0) {
p54_tx_cancel(priv, priv->beacon_req_id);
wait_for_completion_interruptible_timeout(&priv->beacon_comp, HZ);
}
priv->mode = NL80211_IFTYPE_MONITOR;
eth_zero_addr(priv->mac_addr);
eth_zero_addr(priv->bssid);
p54_setup_mac(priv);
mutex_unlock(&priv->conf_mutex);
}
BUILD_BUG_ON(ARRAY_SIZE(priv->mc_maclist) !=
ARRAY_SIZE(((struct p54_group_address_table *)NULL)->mac_list)); /* * The first entry is reserved for the global broadcast MAC. * Otherwise the firmware will drop it and ARP will no longer work.
*/
i = 1;
priv->mc_maclist_num = netdev_hw_addr_list_count(mc_list) + i;
netdev_hw_addr_list_for_each(ha, mc_list) {
memcpy(&priv->mc_maclist[i], ha->addr, ETH_ALEN);
i++; if (i >= ARRAY_SIZE(priv->mc_maclist)) break;
}
if (key->flags & IEEE80211_KEY_FLAG_RX_MGMT) { /* * Unfortunately most/all firmwares are trying to decrypt * incoming management frames if a suitable key can be found. * However, in doing so the data in these frames gets * corrupted. So, we can't have firmware supported crypto * offload in this case.
*/ return -EOPNOTSUPP;
}
mutex_lock(&priv->conf_mutex); if (cmd == SET_KEY) { switch (key->cipher) { case WLAN_CIPHER_SUITE_TKIP: if (!(priv->privacy_caps & (BR_DESC_PRIV_CAP_MICHAEL |
BR_DESC_PRIV_CAP_TKIP))) {
ret = -EOPNOTSUPP; goto out_unlock;
}
key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
algo = P54_CRYPTO_TKIPMICHAEL; break; case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP104: if (!(priv->privacy_caps & BR_DESC_PRIV_CAP_WEP)) {
ret = -EOPNOTSUPP; goto out_unlock;
}
key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
algo = P54_CRYPTO_WEP; break; case WLAN_CIPHER_SUITE_CCMP: if (!(priv->privacy_caps & BR_DESC_PRIV_CAP_AESCCMP)) {
ret = -EOPNOTSUPP; goto out_unlock;
}
key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
algo = P54_CRYPTO_AESCCMP; break; default:
ret = -EOPNOTSUPP; goto out_unlock;
}
slot = bitmap_find_free_region(priv->used_rxkeys,
priv->rx_keycache_size, 0);
if (slot < 0) { /* * The device supports the chosen algorithm, but the * firmware does not provide enough key slots to store * all of them. * But encryption offload for outgoing frames is always * possible, so we just pretend that the upload was * successful and do the decryption in software.
*/
/* mark the key as invalid. */
key->hw_key_idx = 0xff; goto out_unlock;
}
if (in_use) { /* test if the reported statistics are valid. */ if (survey->time != 0) {
survey->filled |= SURVEY_INFO_IN_USE;
} else { /* * hw/fw has not accumulated enough sample sets. * Wait for 100ms, this ought to be enough to * get at least one non-null set of channel * usage statistics.
*/
msleep(100); continue;
}
} return 0;
} return -ETIMEDOUT; #undef MAX_TRIES
}
staticunsignedint p54_flush_count(struct p54_common *priv)
{ unsignedint total = 0, i;
/* * Because the firmware has the sole control over any frames * in the P54_QUEUE_BEACON or P54_QUEUE_SCAN queues, they * don't really count as pending or active.
*/ for (i = P54_QUEUE_MGMT; i < P54_QUEUE_NUM; i++)
total += priv->tx_stats[i].len; return total;
}
/* * Currently, it wouldn't really matter if we wait for one second * or 15 minutes. But once someone gets around and completes the * TODOs [ancel stuck frames / reset device] in p54_work, it will * suddenly make sense to wait that long.
*/
i = P54_STATISTICS_UPDATE * 2 / 20;
/* * In this case no locking is required because as we speak the * queues have already been stopped and no new frames can sneak * up from behind.
*/ while ((total = p54_flush_count(priv)) && i--) { /* waste time */
msleep(20);
}
mutex_lock(&priv->conf_mutex); /* support all coverage class values as in 802.11-2007 Table 7-27 */
priv->coverage_class = clamp_t(u8, coverage_class, 0, 31);
p54_set_edcf(priv);
mutex_unlock(&priv->conf_mutex);
}
priv->beacon_req_id = cpu_to_le32(0);
priv->tx_stats[P54_QUEUE_BEACON].limit = 1;
priv->tx_stats[P54_QUEUE_FWSCAN].limit = 1;
priv->tx_stats[P54_QUEUE_MGMT].limit = 3;
priv->tx_stats[P54_QUEUE_CAB].limit = 3;
priv->tx_stats[P54_QUEUE_DATA].limit = 5;
dev->queues = 1;
priv->noise = -94; /* * We support at most 8 tries no matter which rate they're at, * we cannot support max_rates * max_rate_tries as we set it * here, but setting it correctly to 4/2 or so would limit us * artificially if the RC algorithm wants just two rates, so * let's say 4/7, we'll redistribute it at TX time, see the * comments there.
*/
dev->max_rates = 4;
dev->max_rate_tries = 7;
dev->extra_tx_headroom = sizeof(struct p54_hdr) + 4 + sizeof(struct p54_tx_data);
/* * For now, disable PS by default because it affects * link stability significantly.
*/
dev->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
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.