static int p54_config(struct ieee80211_hw *dev, u32 changed) { int ret = 0; struct p54_common *priv = dev->priv; struct ieee80211_conf *conf = &dev->conf; mutex_lock(&priv->conf_mutex); if (changed & IEEE80211_CONF_CHANGE_POWER) priv->output_power = conf->power_level << 2; if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { struct ieee80211_channel *oldchan; WARN_ON(p54_wait_for_stats(dev)); oldchan = priv->curchan; priv->curchan = NULL; ret = p54_scan(priv, P54_SCAN_EXIT, 0); if (ret) { priv->curchan = oldchan; goto out; } /* * TODO: Use the LM_SCAN_TRAP to determine the current * operating channel. */ priv->curchan = priv->hw->conf.chandef.chan; p54_reset_stats(priv); WARN_ON(p54_fetch_statistics(priv)); } if (changed & IEEE80211_CONF_CHANGE_PS) { WARN_ON(p54_wait_for_stats(dev)); ret = p54_set_ps(priv); if (ret) goto out; WARN_ON(p54_wait_for_stats(dev)); } if (changed & IEEE80211_CONF_CHANGE_IDLE) { WARN_ON(p54_wait_for_stats(dev)); ret = p54_setup_mac(priv); if (ret) goto out; WARN_ON(p54_wait_for_stats(dev)); } out: mutex_unlock(&priv->conf_mutex); return ret; }
struct ieee80211_hw *p54_init_common(size_t priv_data_len) { struct ieee80211_hw *dev; struct p54_common *priv; dev = ieee80211_alloc_hw(priv_data_len, &p54_ops); if (!dev) return NULL; priv = dev->priv; priv->hw = dev; priv->mode = NL80211_IFTYPE_UNSPECIFIED; priv->basic_rate_mask = 0x15f; spin_lock_init(&priv->tx_stats_lock); skb_queue_head_init(&priv->tx_queue); skb_queue_head_init(&priv->tx_pending); dev->flags = IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_PS_NULLFUNC_STACK | IEEE80211_HW_MFP_CAPABLE | IEEE80211_HW_REPORTS_TX_ACK_STATUS; dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_MESH_POINT); dev->channel_change_time = 1000; /* TODO: find actual value */ 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; mutex_init(&priv->conf_mutex); mutex_init(&priv->eeprom_mutex); init_completion(&priv->stat_comp); init_completion(&priv->eeprom_comp); init_completion(&priv->beacon_comp); INIT_DELAYED_WORK(&priv->work, p54_work); memset(&priv->mc_maclist[0], ~0, ETH_ALEN); priv->curchan = NULL; p54_reset_stats(priv); return dev; }