Merge tag 'wireless-drivers-next-for-davem-2015-06-18' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next
Kalle Valo says: ==================== Major changes: mwifiex: * enhancements for AP mode: support verbose information in station dump command and also information about AP link. * enable power save by default brcmfmac: * fix module reload issue for PCIe * improving msgbuf protocol for PCIe devices * rework .get_station() cfg80211 callback operation * determine interface combinations upon device feature support ath9k: * ath9k_htc: add support of channel switch wil6210: * add modparam for bcast ring size * support hidden SSID * add per-MCS Rx stats ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
@@ -988,6 +988,7 @@ static void brcmf_sdiod_freezer_detach(struct brcmf_sdio_dev *sdiodev)
|
||||
|
||||
static int brcmf_sdiod_remove(struct brcmf_sdio_dev *sdiodev)
|
||||
{
|
||||
sdiodev->state = BRCMF_SDIOD_DOWN;
|
||||
if (sdiodev->bus) {
|
||||
brcmf_sdio_remove(sdiodev->bus);
|
||||
sdiodev->bus = NULL;
|
||||
|
@@ -52,8 +52,6 @@
|
||||
#define BRCMF_PNO_SCAN_COMPLETE 1
|
||||
#define BRCMF_PNO_SCAN_INCOMPLETE 0
|
||||
|
||||
#define BRCMF_IFACE_MAX_CNT 3
|
||||
|
||||
#define WPA_OUI "\x00\x50\xF2" /* WPA OUI */
|
||||
#define WPA_OUI_TYPE 1
|
||||
#define RSN_OUI "\x00\x0F\xAC" /* RSN OUI */
|
||||
@@ -2398,27 +2396,80 @@ brcmf_cfg80211_reconfigure_wep(struct brcmf_if *ifp)
|
||||
brcmf_err("set wsec error (%d)\n", err);
|
||||
}
|
||||
|
||||
static void brcmf_convert_sta_flags(u32 fw_sta_flags, struct station_info *si)
|
||||
{
|
||||
struct nl80211_sta_flag_update *sfu;
|
||||
|
||||
brcmf_dbg(TRACE, "flags %08x\n", fw_sta_flags);
|
||||
si->filled |= BIT(NL80211_STA_INFO_STA_FLAGS);
|
||||
sfu = &si->sta_flags;
|
||||
sfu->mask = BIT(NL80211_STA_FLAG_WME) |
|
||||
BIT(NL80211_STA_FLAG_AUTHENTICATED) |
|
||||
BIT(NL80211_STA_FLAG_ASSOCIATED) |
|
||||
BIT(NL80211_STA_FLAG_AUTHORIZED);
|
||||
if (fw_sta_flags & BRCMF_STA_WME)
|
||||
sfu->set |= BIT(NL80211_STA_FLAG_WME);
|
||||
if (fw_sta_flags & BRCMF_STA_AUTHE)
|
||||
sfu->set |= BIT(NL80211_STA_FLAG_AUTHENTICATED);
|
||||
if (fw_sta_flags & BRCMF_STA_ASSOC)
|
||||
sfu->set |= BIT(NL80211_STA_FLAG_ASSOCIATED);
|
||||
if (fw_sta_flags & BRCMF_STA_AUTHO)
|
||||
sfu->set |= BIT(NL80211_STA_FLAG_AUTHORIZED);
|
||||
}
|
||||
|
||||
static void brcmf_fill_bss_param(struct brcmf_if *ifp, struct station_info *si)
|
||||
{
|
||||
struct {
|
||||
__le32 len;
|
||||
struct brcmf_bss_info_le bss_le;
|
||||
} *buf;
|
||||
u16 capability;
|
||||
int err;
|
||||
|
||||
buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return;
|
||||
|
||||
buf->len = cpu_to_le32(WL_BSS_INFO_MAX);
|
||||
err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSS_INFO, buf,
|
||||
WL_BSS_INFO_MAX);
|
||||
if (err) {
|
||||
brcmf_err("Failed to get bss info (%d)\n", err);
|
||||
return;
|
||||
}
|
||||
si->filled |= BIT(NL80211_STA_INFO_BSS_PARAM);
|
||||
si->bss_param.beacon_interval = le16_to_cpu(buf->bss_le.beacon_period);
|
||||
si->bss_param.dtim_period = buf->bss_le.dtim_period;
|
||||
capability = le16_to_cpu(buf->bss_le.capability);
|
||||
if (capability & IEEE80211_HT_STBC_PARAM_DUAL_CTS_PROT)
|
||||
si->bss_param.flags |= BSS_PARAM_FLAGS_CTS_PROT;
|
||||
if (capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
|
||||
si->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_PREAMBLE;
|
||||
if (capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)
|
||||
si->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME;
|
||||
}
|
||||
|
||||
static s32
|
||||
brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
|
||||
const u8 *mac, struct station_info *sinfo)
|
||||
{
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
|
||||
struct brcmf_scb_val_le scb_val;
|
||||
int rssi;
|
||||
s32 rate;
|
||||
s32 err = 0;
|
||||
u8 *bssid = profile->bssid;
|
||||
struct brcmf_sta_info_le sta_info_le;
|
||||
u32 beacon_period;
|
||||
u32 dtim_period;
|
||||
u32 sta_flags;
|
||||
u32 is_tdls_peer;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter, MAC %pM\n", mac);
|
||||
if (!check_vif_up(ifp->vif))
|
||||
return -EIO;
|
||||
|
||||
if (brcmf_is_apmode(ifp->vif)) {
|
||||
memcpy(&sta_info_le, mac, ETH_ALEN);
|
||||
memset(&sta_info_le, 0, sizeof(sta_info_le));
|
||||
memcpy(&sta_info_le, mac, ETH_ALEN);
|
||||
err = brcmf_fil_iovar_data_get(ifp, "tdls_sta_info",
|
||||
&sta_info_le,
|
||||
sizeof(sta_info_le));
|
||||
is_tdls_peer = !err;
|
||||
if (err) {
|
||||
err = brcmf_fil_iovar_data_get(ifp, "sta_info",
|
||||
&sta_info_le,
|
||||
sizeof(sta_info_le));
|
||||
@@ -2426,73 +2477,48 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
|
||||
brcmf_err("GET STA INFO failed, %d\n", err);
|
||||
goto done;
|
||||
}
|
||||
sinfo->filled = BIT(NL80211_STA_INFO_INACTIVE_TIME);
|
||||
sinfo->inactive_time = le32_to_cpu(sta_info_le.idle) * 1000;
|
||||
if (le32_to_cpu(sta_info_le.flags) & BRCMF_STA_ASSOC) {
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_CONNECTED_TIME);
|
||||
sinfo->connected_time = le32_to_cpu(sta_info_le.in);
|
||||
}
|
||||
brcmf_dbg(TRACE, "STA idle time : %d ms, connected time :%d sec\n",
|
||||
sinfo->inactive_time, sinfo->connected_time);
|
||||
} else if (ifp->vif->wdev.iftype == NL80211_IFTYPE_STATION) {
|
||||
if (memcmp(mac, bssid, ETH_ALEN)) {
|
||||
brcmf_err("Wrong Mac address cfg_mac-%pM wl_bssid-%pM\n",
|
||||
mac, bssid);
|
||||
err = -ENOENT;
|
||||
goto done;
|
||||
}
|
||||
/* Report the current tx rate */
|
||||
err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_RATE, &rate);
|
||||
if (err) {
|
||||
brcmf_err("Could not get rate (%d)\n", err);
|
||||
goto done;
|
||||
} else {
|
||||
}
|
||||
brcmf_dbg(TRACE, "version %d\n", le16_to_cpu(sta_info_le.ver));
|
||||
sinfo->filled = BIT(NL80211_STA_INFO_INACTIVE_TIME);
|
||||
sinfo->inactive_time = le32_to_cpu(sta_info_le.idle) * 1000;
|
||||
sta_flags = le32_to_cpu(sta_info_le.flags);
|
||||
brcmf_convert_sta_flags(sta_flags, sinfo);
|
||||
sinfo->sta_flags.mask |= BIT(NL80211_STA_FLAG_TDLS_PEER);
|
||||
if (is_tdls_peer)
|
||||
sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER);
|
||||
else
|
||||
sinfo->sta_flags.set &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
|
||||
if (sta_flags & BRCMF_STA_ASSOC) {
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_CONNECTED_TIME);
|
||||
sinfo->connected_time = le32_to_cpu(sta_info_le.in);
|
||||
brcmf_fill_bss_param(ifp, sinfo);
|
||||
}
|
||||
if (sta_flags & BRCMF_STA_SCBSTATS) {
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_TX_FAILED);
|
||||
sinfo->tx_failed = le32_to_cpu(sta_info_le.tx_failures);
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_TX_PACKETS);
|
||||
sinfo->tx_packets = le32_to_cpu(sta_info_le.tx_pkts);
|
||||
sinfo->tx_packets += le32_to_cpu(sta_info_le.tx_mcast_pkts);
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_RX_PACKETS);
|
||||
sinfo->rx_packets = le32_to_cpu(sta_info_le.rx_ucast_pkts);
|
||||
sinfo->rx_packets += le32_to_cpu(sta_info_le.rx_mcast_pkts);
|
||||
if (sinfo->tx_packets) {
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE);
|
||||
sinfo->txrate.legacy = rate * 5;
|
||||
brcmf_dbg(CONN, "Rate %d Mbps\n", rate / 2);
|
||||
sinfo->txrate.legacy = le32_to_cpu(sta_info_le.tx_rate);
|
||||
sinfo->txrate.legacy /= 100;
|
||||
}
|
||||
|
||||
if (test_bit(BRCMF_VIF_STATUS_CONNECTED,
|
||||
&ifp->vif->sme_state)) {
|
||||
memset(&scb_val, 0, sizeof(scb_val));
|
||||
err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_RSSI,
|
||||
&scb_val, sizeof(scb_val));
|
||||
if (err) {
|
||||
brcmf_err("Could not get rssi (%d)\n", err);
|
||||
goto done;
|
||||
} else {
|
||||
rssi = le32_to_cpu(scb_val.val);
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
|
||||
sinfo->signal = rssi;
|
||||
brcmf_dbg(CONN, "RSSI %d dBm\n", rssi);
|
||||
}
|
||||
err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_BCNPRD,
|
||||
&beacon_period);
|
||||
if (err) {
|
||||
brcmf_err("Could not get beacon period (%d)\n",
|
||||
err);
|
||||
goto done;
|
||||
} else {
|
||||
sinfo->bss_param.beacon_interval =
|
||||
beacon_period;
|
||||
brcmf_dbg(CONN, "Beacon peroid %d\n",
|
||||
beacon_period);
|
||||
}
|
||||
err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_DTIMPRD,
|
||||
&dtim_period);
|
||||
if (err) {
|
||||
brcmf_err("Could not get DTIM period (%d)\n",
|
||||
err);
|
||||
goto done;
|
||||
} else {
|
||||
sinfo->bss_param.dtim_period = dtim_period;
|
||||
brcmf_dbg(CONN, "DTIM peroid %d\n",
|
||||
dtim_period);
|
||||
}
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_BSS_PARAM);
|
||||
if (sinfo->rx_packets) {
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_RX_BITRATE);
|
||||
sinfo->rxrate.legacy = le32_to_cpu(sta_info_le.rx_rate);
|
||||
sinfo->rxrate.legacy /= 100;
|
||||
}
|
||||
} else
|
||||
err = -EPERM;
|
||||
if (le16_to_cpu(sta_info_le.ver) >= 4) {
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_TX_BYTES);
|
||||
sinfo->tx_bytes = le64_to_cpu(sta_info_le.tx_tot_bytes);
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_RX_BYTES);
|
||||
sinfo->rx_bytes = le64_to_cpu(sta_info_le.rx_tot_bytes);
|
||||
}
|
||||
}
|
||||
done:
|
||||
brcmf_dbg(TRACE, "Exit\n");
|
||||
return err;
|
||||
@@ -5640,53 +5666,6 @@ static int brcmf_setup_wiphybands(struct wiphy *wiphy)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ieee80211_iface_limit brcmf_iface_limits_mbss[] = {
|
||||
{
|
||||
.max = 1,
|
||||
.types = BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_ADHOC)
|
||||
},
|
||||
{
|
||||
.max = 4,
|
||||
.types = BIT(NL80211_IFTYPE_AP)
|
||||
},
|
||||
{
|
||||
.max = 1,
|
||||
.types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
|
||||
BIT(NL80211_IFTYPE_P2P_GO)
|
||||
},
|
||||
{
|
||||
.max = 1,
|
||||
.types = BIT(NL80211_IFTYPE_P2P_DEVICE)
|
||||
}
|
||||
};
|
||||
|
||||
static const struct ieee80211_iface_limit brcmf_iface_limits_sbss[] = {
|
||||
{
|
||||
.max = 2,
|
||||
.types = BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_ADHOC) |
|
||||
BIT(NL80211_IFTYPE_AP)
|
||||
},
|
||||
{
|
||||
.max = 1,
|
||||
.types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
|
||||
BIT(NL80211_IFTYPE_P2P_GO)
|
||||
},
|
||||
{
|
||||
.max = 1,
|
||||
.types = BIT(NL80211_IFTYPE_P2P_DEVICE)
|
||||
}
|
||||
};
|
||||
static struct ieee80211_iface_combination brcmf_iface_combos[] = {
|
||||
{
|
||||
.max_interfaces = BRCMF_IFACE_MAX_CNT,
|
||||
.num_different_channels = 1,
|
||||
.n_limits = ARRAY_SIZE(brcmf_iface_limits_sbss),
|
||||
.limits = brcmf_iface_limits_sbss,
|
||||
}
|
||||
};
|
||||
|
||||
static const struct ieee80211_txrx_stypes
|
||||
brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = {
|
||||
[NL80211_IFTYPE_STATION] = {
|
||||
@@ -5716,6 +5695,67 @@ brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = {
|
||||
}
|
||||
};
|
||||
|
||||
static int brcmf_setup_ifmodes(struct wiphy *wiphy, struct brcmf_if *ifp)
|
||||
{
|
||||
struct ieee80211_iface_combination *combo = NULL;
|
||||
struct ieee80211_iface_limit *limits = NULL;
|
||||
int i = 0, max_iface_cnt;
|
||||
|
||||
combo = kzalloc(sizeof(*combo), GFP_KERNEL);
|
||||
if (!combo)
|
||||
goto err;
|
||||
|
||||
limits = kzalloc(sizeof(*limits) * 4, GFP_KERNEL);
|
||||
if (!limits)
|
||||
goto err;
|
||||
|
||||
wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_ADHOC) |
|
||||
BIT(NL80211_IFTYPE_AP);
|
||||
|
||||
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN))
|
||||
combo->num_different_channels = 2;
|
||||
else
|
||||
combo->num_different_channels = 1;
|
||||
|
||||
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) {
|
||||
limits[i].max = 1;
|
||||
limits[i++].types = BIT(NL80211_IFTYPE_STATION);
|
||||
limits[i].max = 4;
|
||||
limits[i++].types = BIT(NL80211_IFTYPE_AP);
|
||||
max_iface_cnt = 5;
|
||||
} else {
|
||||
limits[i].max = 2;
|
||||
limits[i++].types = BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_AP);
|
||||
max_iface_cnt = 2;
|
||||
}
|
||||
|
||||
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_P2P)) {
|
||||
wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_CLIENT) |
|
||||
BIT(NL80211_IFTYPE_P2P_GO) |
|
||||
BIT(NL80211_IFTYPE_P2P_DEVICE);
|
||||
limits[i].max = 1;
|
||||
limits[i++].types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
|
||||
BIT(NL80211_IFTYPE_P2P_GO);
|
||||
limits[i].max = 1;
|
||||
limits[i++].types = BIT(NL80211_IFTYPE_P2P_DEVICE);
|
||||
max_iface_cnt += 2;
|
||||
}
|
||||
combo->max_interfaces = max_iface_cnt;
|
||||
combo->limits = limits;
|
||||
combo->n_limits = i;
|
||||
|
||||
wiphy->iface_combinations = combo;
|
||||
wiphy->n_iface_combinations = 1;
|
||||
return 0;
|
||||
|
||||
err:
|
||||
kfree(limits);
|
||||
kfree(combo);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static void brcmf_wiphy_pno_params(struct wiphy *wiphy)
|
||||
{
|
||||
/* scheduled scan settings */
|
||||
@@ -5746,7 +5786,6 @@ static void brcmf_wiphy_wowl_params(struct wiphy *wiphy)
|
||||
static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
|
||||
{
|
||||
struct ieee80211_supported_band *band;
|
||||
struct ieee80211_iface_combination ifc_combo;
|
||||
__le32 bandlist[3];
|
||||
u32 n_bands;
|
||||
int err, i;
|
||||
@@ -5754,24 +5793,11 @@ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
|
||||
wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;
|
||||
wiphy->max_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX;
|
||||
wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
|
||||
wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_ADHOC) |
|
||||
BIT(NL80211_IFTYPE_AP) |
|
||||
BIT(NL80211_IFTYPE_P2P_CLIENT) |
|
||||
BIT(NL80211_IFTYPE_P2P_GO) |
|
||||
BIT(NL80211_IFTYPE_P2P_DEVICE);
|
||||
/* need VSDB firmware feature for concurrent channels */
|
||||
ifc_combo = brcmf_iface_combos[0];
|
||||
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN))
|
||||
ifc_combo.num_different_channels = 2;
|
||||
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) {
|
||||
ifc_combo.n_limits = ARRAY_SIZE(brcmf_iface_limits_mbss),
|
||||
ifc_combo.limits = brcmf_iface_limits_mbss;
|
||||
}
|
||||
wiphy->iface_combinations = kmemdup(&ifc_combo,
|
||||
sizeof(ifc_combo),
|
||||
GFP_KERNEL);
|
||||
wiphy->n_iface_combinations = ARRAY_SIZE(brcmf_iface_combos);
|
||||
|
||||
err = brcmf_setup_ifmodes(wiphy, ifp);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
|
||||
wiphy->cipher_suites = __wl_cipher_suites;
|
||||
wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
|
||||
@@ -6036,6 +6062,8 @@ static void brcmf_free_wiphy(struct wiphy *wiphy)
|
||||
if (!wiphy)
|
||||
return;
|
||||
|
||||
if (wiphy->iface_combinations)
|
||||
kfree(wiphy->iface_combinations->limits);
|
||||
kfree(wiphy->iface_combinations);
|
||||
if (wiphy->bands[IEEE80211_BAND_2GHZ]) {
|
||||
kfree(wiphy->bands[IEEE80211_BAND_2GHZ]->channels);
|
||||
@@ -6071,6 +6099,7 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
|
||||
brcmf_err("Could not allocate wiphy device\n");
|
||||
return NULL;
|
||||
}
|
||||
memcpy(wiphy->perm_addr, drvr->mac, ETH_ALEN);
|
||||
set_wiphy_dev(wiphy, busdev);
|
||||
|
||||
cfg = wiphy_priv(wiphy);
|
||||
@@ -6178,10 +6207,8 @@ void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg)
|
||||
if (!cfg)
|
||||
return;
|
||||
|
||||
WARN_ON(!list_empty(&cfg->vif_list));
|
||||
wiphy_unregister(cfg->wiphy);
|
||||
brcmf_btcoex_detach(cfg);
|
||||
brcmf_p2p_detach(&cfg->p2p);
|
||||
wiphy_unregister(cfg->wiphy);
|
||||
wl_deinit_priv(cfg);
|
||||
brcmf_free_wiphy(cfg->wiphy);
|
||||
}
|
||||
|
@@ -223,8 +223,6 @@ void brcmf_commonring_write_cancel(struct brcmf_commonring *commonring,
|
||||
void *brcmf_commonring_get_read_ptr(struct brcmf_commonring *commonring,
|
||||
u16 *n_items)
|
||||
{
|
||||
void *ret_addr;
|
||||
|
||||
if (commonring->cr_update_wptr)
|
||||
commonring->cr_update_wptr(commonring->cr_ctx);
|
||||
|
||||
@@ -235,19 +233,18 @@ void *brcmf_commonring_get_read_ptr(struct brcmf_commonring *commonring,
|
||||
if (*n_items == 0)
|
||||
return NULL;
|
||||
|
||||
ret_addr = commonring->buf_addr +
|
||||
(commonring->r_ptr * commonring->item_len);
|
||||
|
||||
commonring->r_ptr += *n_items;
|
||||
if (commonring->r_ptr == commonring->depth)
|
||||
commonring->r_ptr = 0;
|
||||
|
||||
return ret_addr;
|
||||
return commonring->buf_addr +
|
||||
(commonring->r_ptr * commonring->item_len);
|
||||
}
|
||||
|
||||
|
||||
int brcmf_commonring_read_complete(struct brcmf_commonring *commonring)
|
||||
int brcmf_commonring_read_complete(struct brcmf_commonring *commonring,
|
||||
u16 n_items)
|
||||
{
|
||||
commonring->r_ptr += n_items;
|
||||
if (commonring->r_ptr == commonring->depth)
|
||||
commonring->r_ptr = 0;
|
||||
|
||||
if (commonring->cr_write_rptr)
|
||||
return commonring->cr_write_rptr(commonring->cr_ctx);
|
||||
|
||||
|
@@ -62,7 +62,8 @@ void brcmf_commonring_write_cancel(struct brcmf_commonring *commonring,
|
||||
u16 n_items);
|
||||
void *brcmf_commonring_get_read_ptr(struct brcmf_commonring *commonring,
|
||||
u16 *n_items);
|
||||
int brcmf_commonring_read_complete(struct brcmf_commonring *commonring);
|
||||
int brcmf_commonring_read_complete(struct brcmf_commonring *commonring,
|
||||
u16 n_items);
|
||||
|
||||
#define brcmf_commonring_n_items(commonring) (commonring->depth)
|
||||
#define brcmf_commonring_len_item(commonring) (commonring->item_len)
|
||||
|
@@ -867,8 +867,6 @@ static void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx)
|
||||
}
|
||||
/* unregister will take care of freeing it */
|
||||
unregister_netdev(ifp->ndev);
|
||||
} else {
|
||||
kfree(ifp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1100,6 +1098,8 @@ void brcmf_detach(struct device *dev)
|
||||
|
||||
/* stop firmware event handling */
|
||||
brcmf_fweh_detach(drvr);
|
||||
if (drvr->config)
|
||||
brcmf_p2p_detach(&drvr->config->p2p);
|
||||
|
||||
brcmf_bus_change_state(bus_if, BRCMF_BUS_DOWN);
|
||||
|
||||
|
@@ -41,15 +41,6 @@ void brcmf_debugfs_exit(void)
|
||||
root_folder = NULL;
|
||||
}
|
||||
|
||||
static int brcmf_debugfs_chipinfo_read(struct seq_file *seq, void *data)
|
||||
{
|
||||
struct brcmf_bus *bus = dev_get_drvdata(seq->private);
|
||||
|
||||
seq_printf(seq, "chip: %x(%u) rev %u\n",
|
||||
bus->chip, bus->chip, bus->chiprev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int brcmf_debugfs_attach(struct brcmf_pub *drvr)
|
||||
{
|
||||
struct device *dev = drvr->bus_if->dev;
|
||||
@@ -58,7 +49,6 @@ int brcmf_debugfs_attach(struct brcmf_pub *drvr)
|
||||
return -ENODEV;
|
||||
|
||||
drvr->dbgfs_dir = debugfs_create_dir(dev_name(dev), root_folder);
|
||||
brcmf_debugfs_add_entry(drvr, "chipinfo", brcmf_debugfs_chipinfo_read);
|
||||
|
||||
return PTR_ERR_OR_ZERO(drvr->dbgfs_dir);
|
||||
}
|
||||
@@ -74,44 +64,12 @@ struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr)
|
||||
return drvr->dbgfs_dir;
|
||||
}
|
||||
|
||||
struct brcmf_debugfs_entry {
|
||||
int (*read)(struct seq_file *seq, void *data);
|
||||
struct brcmf_pub *drvr;
|
||||
};
|
||||
|
||||
static int brcmf_debugfs_entry_open(struct inode *inode, struct file *f)
|
||||
{
|
||||
struct brcmf_debugfs_entry *entry = inode->i_private;
|
||||
|
||||
return single_open(f, entry->read, entry->drvr->bus_if->dev);
|
||||
}
|
||||
|
||||
static const struct file_operations brcmf_debugfs_def_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = brcmf_debugfs_entry_open,
|
||||
.release = single_release,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek
|
||||
};
|
||||
|
||||
int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn,
|
||||
int (*read_fn)(struct seq_file *seq, void *data))
|
||||
{
|
||||
struct dentry *dentry = drvr->dbgfs_dir;
|
||||
struct brcmf_debugfs_entry *entry;
|
||||
struct dentry *e;
|
||||
|
||||
if (IS_ERR_OR_NULL(dentry))
|
||||
return -ENOENT;
|
||||
|
||||
entry = devm_kzalloc(drvr->bus_if->dev, sizeof(*entry), GFP_KERNEL);
|
||||
if (!entry)
|
||||
return -ENOMEM;
|
||||
|
||||
entry->read = read_fn;
|
||||
entry->drvr = drvr;
|
||||
|
||||
dentry = debugfs_create_file(fn, S_IRUGO, dentry, entry,
|
||||
&brcmf_debugfs_def_ops);
|
||||
|
||||
return PTR_ERR_OR_ZERO(dentry);
|
||||
e = debugfs_create_devm_seqfile(drvr->bus_if->dev, fn,
|
||||
drvr->dbgfs_dir, read_fn);
|
||||
return PTR_ERR_OR_ZERO(e);
|
||||
}
|
||||
|
@@ -129,6 +129,7 @@ void brcmf_feat_attach(struct brcmf_pub *drvr)
|
||||
brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_WOWL, "wowl");
|
||||
if (drvr->bus_if->chip != BRCM_CC_43362_CHIP_ID)
|
||||
brcmf_feat_iovar_int_set(ifp, BRCMF_FEAT_MBSS, "mbss", 0);
|
||||
brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_P2P, "p2p");
|
||||
|
||||
/* set chip related quirks */
|
||||
switch (drvr->bus_if->chip) {
|
||||
|
@@ -23,12 +23,14 @@
|
||||
* MCHAN: multi-channel for concurrent P2P.
|
||||
* PNO: preferred network offload.
|
||||
* WOWL: Wake-On-WLAN.
|
||||
* P2P: peer-to-peer
|
||||
*/
|
||||
#define BRCMF_FEAT_LIST \
|
||||
BRCMF_FEAT_DEF(MBSS) \
|
||||
BRCMF_FEAT_DEF(MCHAN) \
|
||||
BRCMF_FEAT_DEF(PNO) \
|
||||
BRCMF_FEAT_DEF(WOWL)
|
||||
BRCMF_FEAT_DEF(WOWL) \
|
||||
BRCMF_FEAT_DEF(P2P)
|
||||
/*
|
||||
* Quirks:
|
||||
*
|
||||
|
@@ -43,7 +43,7 @@ enum nvram_parser_state {
|
||||
* struct nvram_parser - internal info for parser.
|
||||
*
|
||||
* @state: current parser state.
|
||||
* @fwnv: input buffer being parsed.
|
||||
* @data: input buffer being parsed.
|
||||
* @nvram: output buffer with parse result.
|
||||
* @nvram_len: lenght of parse result.
|
||||
* @line: current line.
|
||||
@@ -55,7 +55,7 @@ enum nvram_parser_state {
|
||||
*/
|
||||
struct nvram_parser {
|
||||
enum nvram_parser_state state;
|
||||
const struct firmware *fwnv;
|
||||
const u8 *data;
|
||||
u8 *nvram;
|
||||
u32 nvram_len;
|
||||
u32 line;
|
||||
@@ -91,7 +91,7 @@ static enum nvram_parser_state brcmf_nvram_handle_idle(struct nvram_parser *nvp)
|
||||
{
|
||||
char c;
|
||||
|
||||
c = nvp->fwnv->data[nvp->pos];
|
||||
c = nvp->data[nvp->pos];
|
||||
if (c == '\n')
|
||||
return COMMENT;
|
||||
if (is_whitespace(c))
|
||||
@@ -115,16 +115,16 @@ static enum nvram_parser_state brcmf_nvram_handle_key(struct nvram_parser *nvp)
|
||||
enum nvram_parser_state st = nvp->state;
|
||||
char c;
|
||||
|
||||
c = nvp->fwnv->data[nvp->pos];
|
||||
c = nvp->data[nvp->pos];
|
||||
if (c == '=') {
|
||||
/* ignore RAW1 by treating as comment */
|
||||
if (strncmp(&nvp->fwnv->data[nvp->entry], "RAW1", 4) == 0)
|
||||
if (strncmp(&nvp->data[nvp->entry], "RAW1", 4) == 0)
|
||||
st = COMMENT;
|
||||
else
|
||||
st = VALUE;
|
||||
if (strncmp(&nvp->fwnv->data[nvp->entry], "devpath", 7) == 0)
|
||||
if (strncmp(&nvp->data[nvp->entry], "devpath", 7) == 0)
|
||||
nvp->multi_dev_v1 = true;
|
||||
if (strncmp(&nvp->fwnv->data[nvp->entry], "pcie/", 5) == 0)
|
||||
if (strncmp(&nvp->data[nvp->entry], "pcie/", 5) == 0)
|
||||
nvp->multi_dev_v2 = true;
|
||||
} else if (!is_nvram_char(c) || c == ' ') {
|
||||
brcmf_dbg(INFO, "warning: ln=%d:col=%d: '=' expected, skip invalid key entry\n",
|
||||
@@ -145,11 +145,11 @@ brcmf_nvram_handle_value(struct nvram_parser *nvp)
|
||||
char *ekv;
|
||||
u32 cplen;
|
||||
|
||||
c = nvp->fwnv->data[nvp->pos];
|
||||
c = nvp->data[nvp->pos];
|
||||
if (!is_nvram_char(c)) {
|
||||
/* key,value pair complete */
|
||||
ekv = (u8 *)&nvp->fwnv->data[nvp->pos];
|
||||
skv = (u8 *)&nvp->fwnv->data[nvp->entry];
|
||||
ekv = (u8 *)&nvp->data[nvp->pos];
|
||||
skv = (u8 *)&nvp->data[nvp->entry];
|
||||
cplen = ekv - skv;
|
||||
if (nvp->nvram_len + cplen + 1 >= BRCMF_FW_MAX_NVRAM_SIZE)
|
||||
return END;
|
||||
@@ -170,7 +170,7 @@ brcmf_nvram_handle_comment(struct nvram_parser *nvp)
|
||||
{
|
||||
char *eoc, *sol;
|
||||
|
||||
sol = (char *)&nvp->fwnv->data[nvp->pos];
|
||||
sol = (char *)&nvp->data[nvp->pos];
|
||||
eoc = strchr(sol, '\n');
|
||||
if (!eoc) {
|
||||
eoc = strchr(sol, '\0');
|
||||
@@ -201,17 +201,17 @@ static enum nvram_parser_state
|
||||
};
|
||||
|
||||
static int brcmf_init_nvram_parser(struct nvram_parser *nvp,
|
||||
const struct firmware *nv)
|
||||
const u8 *data, size_t data_len)
|
||||
{
|
||||
size_t size;
|
||||
|
||||
memset(nvp, 0, sizeof(*nvp));
|
||||
nvp->fwnv = nv;
|
||||
nvp->data = data;
|
||||
/* Limit size to MAX_NVRAM_SIZE, some files contain lot of comment */
|
||||
if (nv->size > BRCMF_FW_MAX_NVRAM_SIZE)
|
||||
if (data_len > BRCMF_FW_MAX_NVRAM_SIZE)
|
||||
size = BRCMF_FW_MAX_NVRAM_SIZE;
|
||||
else
|
||||
size = nv->size;
|
||||
size = data_len;
|
||||
/* Alloc for extra 0 byte + roundup by 4 + length field */
|
||||
size += 1 + 3 + sizeof(u32);
|
||||
nvp->nvram = kzalloc(size, GFP_KERNEL);
|
||||
@@ -232,6 +232,8 @@ static void brcmf_fw_strip_multi_v1(struct nvram_parser *nvp, u16 domain_nr,
|
||||
u16 bus_nr)
|
||||
{
|
||||
/* Device path with a leading '=' key-value separator */
|
||||
char pci_path[] = "=pci/?/?";
|
||||
size_t pci_len;
|
||||
char pcie_path[] = "=pcie/?/?";
|
||||
size_t pcie_len;
|
||||
|
||||
@@ -251,6 +253,9 @@ static void brcmf_fw_strip_multi_v1(struct nvram_parser *nvp, u16 domain_nr,
|
||||
/* First search for the devpathX and see if it is the configuration
|
||||
* for domain_nr/bus_nr. Search complete nvp
|
||||
*/
|
||||
snprintf(pci_path, sizeof(pci_path), "=pci/%d/%d", domain_nr,
|
||||
bus_nr);
|
||||
pci_len = strlen(pci_path);
|
||||
snprintf(pcie_path, sizeof(pcie_path), "=pcie/%d/%d", domain_nr,
|
||||
bus_nr);
|
||||
pcie_len = strlen(pcie_path);
|
||||
@@ -260,8 +265,9 @@ static void brcmf_fw_strip_multi_v1(struct nvram_parser *nvp, u16 domain_nr,
|
||||
/* Format: devpathX=pcie/Y/Z/
|
||||
* Y = domain_nr, Z = bus_nr, X = virtual ID
|
||||
*/
|
||||
if ((strncmp(&nvp->nvram[i], "devpath", 7) == 0) &&
|
||||
(strncmp(&nvp->nvram[i + 8], pcie_path, pcie_len) == 0)) {
|
||||
if (strncmp(&nvp->nvram[i], "devpath", 7) == 0 &&
|
||||
(!strncmp(&nvp->nvram[i + 8], pci_path, pci_len) ||
|
||||
!strncmp(&nvp->nvram[i + 8], pcie_path, pcie_len))) {
|
||||
id = nvp->nvram[i + 7] - '0';
|
||||
found = true;
|
||||
break;
|
||||
@@ -356,18 +362,18 @@ fail:
|
||||
* and converts newlines to NULs. Shortens buffer as needed and pads with NULs.
|
||||
* End of buffer is completed with token identifying length of buffer.
|
||||
*/
|
||||
static void *brcmf_fw_nvram_strip(const struct firmware *nv, u32 *new_length,
|
||||
u16 domain_nr, u16 bus_nr)
|
||||
static void *brcmf_fw_nvram_strip(const u8 *data, size_t data_len,
|
||||
u32 *new_length, u16 domain_nr, u16 bus_nr)
|
||||
{
|
||||
struct nvram_parser nvp;
|
||||
u32 pad;
|
||||
u32 token;
|
||||
__le32 token_le;
|
||||
|
||||
if (brcmf_init_nvram_parser(&nvp, nv) < 0)
|
||||
if (brcmf_init_nvram_parser(&nvp, data, data_len) < 0)
|
||||
return NULL;
|
||||
|
||||
while (nvp.pos < nv->size) {
|
||||
while (nvp.pos < data_len) {
|
||||
nvp.state = nv_parser_states[nvp.state](&nvp);
|
||||
if (nvp.state == END)
|
||||
break;
|
||||
@@ -426,7 +432,7 @@ static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
|
||||
goto fail;
|
||||
|
||||
if (fw) {
|
||||
nvram = brcmf_fw_nvram_strip(fw, &nvram_length,
|
||||
nvram = brcmf_fw_nvram_strip(fw->data, fw->size, &nvram_length,
|
||||
fwctx->domain_nr, fwctx->bus_nr);
|
||||
release_firmware(fw);
|
||||
if (!nvram && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL))
|
||||
|
@@ -32,7 +32,11 @@
|
||||
#define BRCMF_BSS_INFO_VERSION 109 /* curr ver of brcmf_bss_info_le struct */
|
||||
#define BRCMF_BSS_RSSI_ON_CHANNEL 0x0002
|
||||
|
||||
#define BRCMF_STA_ASSOC 0x10 /* Associated */
|
||||
#define BRCMF_STA_WME 0x00000002 /* WMM association */
|
||||
#define BRCMF_STA_AUTHE 0x00000008 /* Authenticated */
|
||||
#define BRCMF_STA_ASSOC 0x00000010 /* Associated */
|
||||
#define BRCMF_STA_AUTHO 0x00000020 /* Authorized */
|
||||
#define BRCMF_STA_SCBSTATS 0x00004000 /* Per STA debug stats */
|
||||
|
||||
/* size of brcmf_scan_params not including variable length array */
|
||||
#define BRCMF_SCAN_PARAMS_FIXED_SIZE 64
|
||||
@@ -113,6 +117,7 @@
|
||||
#define BRCMF_WOWL_MAXPATTERNSIZE 128
|
||||
|
||||
#define BRCMF_COUNTRY_BUF_SZ 4
|
||||
#define BRCMF_ANT_MAX 4
|
||||
|
||||
/* join preference types for join_pref iovar */
|
||||
enum brcmf_join_pref_types {
|
||||
@@ -456,25 +461,61 @@ struct brcmf_channel_info_le {
|
||||
};
|
||||
|
||||
struct brcmf_sta_info_le {
|
||||
__le16 ver; /* version of this struct */
|
||||
__le16 len; /* length in bytes of this structure */
|
||||
__le16 cap; /* sta's advertised capabilities */
|
||||
__le32 flags; /* flags defined below */
|
||||
__le32 idle; /* time since data pkt rx'd from sta */
|
||||
u8 ea[ETH_ALEN]; /* Station address */
|
||||
__le32 count; /* # rates in this set */
|
||||
u8 rates[BRCMF_MAXRATES_IN_SET]; /* rates in 500kbps units */
|
||||
__le16 ver; /* version of this struct */
|
||||
__le16 len; /* length in bytes of this structure */
|
||||
__le16 cap; /* sta's advertised capabilities */
|
||||
__le32 flags; /* flags defined below */
|
||||
__le32 idle; /* time since data pkt rx'd from sta */
|
||||
u8 ea[ETH_ALEN]; /* Station address */
|
||||
__le32 count; /* # rates in this set */
|
||||
u8 rates[BRCMF_MAXRATES_IN_SET]; /* rates in 500kbps units */
|
||||
/* w/hi bit set if basic */
|
||||
__le32 in; /* seconds elapsed since associated */
|
||||
__le32 listen_interval_inms; /* Min Listen interval in ms for STA */
|
||||
__le32 tx_pkts; /* # of packets transmitted */
|
||||
__le32 tx_failures; /* # of packets failed */
|
||||
__le32 rx_ucast_pkts; /* # of unicast packets received */
|
||||
__le32 rx_mcast_pkts; /* # of multicast packets received */
|
||||
__le32 tx_rate; /* Rate of last successful tx frame */
|
||||
__le32 rx_rate; /* Rate of last successful rx frame */
|
||||
__le32 rx_decrypt_succeeds; /* # of packet decrypted successfully */
|
||||
__le32 rx_decrypt_failures; /* # of packet decrypted failed */
|
||||
__le32 in; /* seconds elapsed since associated */
|
||||
__le32 listen_interval_inms; /* Min Listen interval in ms for STA */
|
||||
__le32 tx_pkts; /* # of packets transmitted */
|
||||
__le32 tx_failures; /* # of packets failed */
|
||||
__le32 rx_ucast_pkts; /* # of unicast packets received */
|
||||
__le32 rx_mcast_pkts; /* # of multicast packets received */
|
||||
__le32 tx_rate; /* Rate of last successful tx frame */
|
||||
__le32 rx_rate; /* Rate of last successful rx frame */
|
||||
__le32 rx_decrypt_succeeds; /* # of packet decrypted successfully */
|
||||
__le32 rx_decrypt_failures; /* # of packet decrypted failed */
|
||||
__le32 tx_tot_pkts; /* # of tx pkts (ucast + mcast) */
|
||||
__le32 rx_tot_pkts; /* # of data packets recvd (uni + mcast) */
|
||||
__le32 tx_mcast_pkts; /* # of mcast pkts txed */
|
||||
__le64 tx_tot_bytes; /* data bytes txed (ucast + mcast) */
|
||||
__le64 rx_tot_bytes; /* data bytes recvd (ucast + mcast) */
|
||||
__le64 tx_ucast_bytes; /* data bytes txed (ucast) */
|
||||
__le64 tx_mcast_bytes; /* # data bytes txed (mcast) */
|
||||
__le64 rx_ucast_bytes; /* data bytes recvd (ucast) */
|
||||
__le64 rx_mcast_bytes; /* data bytes recvd (mcast) */
|
||||
s8 rssi[BRCMF_ANT_MAX]; /* per antenna rssi */
|
||||
s8 nf[BRCMF_ANT_MAX]; /* per antenna noise floor */
|
||||
__le16 aid; /* association ID */
|
||||
__le16 ht_capabilities; /* advertised ht caps */
|
||||
__le16 vht_flags; /* converted vht flags */
|
||||
__le32 tx_pkts_retry_cnt; /* # of frames where a retry was
|
||||
* exhausted.
|
||||
*/
|
||||
__le32 tx_pkts_retry_exhausted; /* # of user frames where a retry
|
||||
* was exhausted
|
||||
*/
|
||||
s8 rx_lastpkt_rssi[BRCMF_ANT_MAX]; /* Per antenna RSSI of last
|
||||
* received data frame.
|
||||
*/
|
||||
/* TX WLAN retry/failure statistics:
|
||||
* Separated for host requested frames and locally generated frames.
|
||||
* Include unicast frame only where the retries/failures can be counted.
|
||||
*/
|
||||
__le32 tx_pkts_total; /* # user frames sent successfully */
|
||||
__le32 tx_pkts_retries; /* # user frames retries */
|
||||
__le32 tx_pkts_fw_total; /* # FW generated sent successfully */
|
||||
__le32 tx_pkts_fw_retries; /* # retries for FW generated frames */
|
||||
__le32 tx_pkts_fw_retry_exhausted; /* # FW generated where a retry
|
||||
* was exhausted
|
||||
*/
|
||||
__le32 rx_pkts_retried; /* # rx with retry bit set */
|
||||
__le32 tx_rate_fallback; /* lowest fallback TX rate */
|
||||
};
|
||||
|
||||
struct brcmf_chanspec_list {
|
||||
|
@@ -75,6 +75,8 @@
|
||||
|
||||
#define BRCMF_MSGBUF_DELAY_TXWORKER_THRS 96
|
||||
#define BRCMF_MSGBUF_TRICKLE_TXWORKER_THRS 32
|
||||
#define BRCMF_MSGBUF_UPDATE_RX_PTR_THRS 48
|
||||
|
||||
|
||||
struct msgbuf_common_hdr {
|
||||
u8 msgtype;
|
||||
@@ -1257,19 +1259,27 @@ static void brcmf_msgbuf_process_rx(struct brcmf_msgbuf *msgbuf,
|
||||
{
|
||||
void *buf;
|
||||
u16 count;
|
||||
u16 processed;
|
||||
|
||||
again:
|
||||
buf = brcmf_commonring_get_read_ptr(commonring, &count);
|
||||
if (buf == NULL)
|
||||
return;
|
||||
|
||||
processed = 0;
|
||||
while (count) {
|
||||
brcmf_msgbuf_process_msgtype(msgbuf,
|
||||
buf + msgbuf->rx_dataoffset);
|
||||
buf += brcmf_commonring_len_item(commonring);
|
||||
processed++;
|
||||
if (processed == BRCMF_MSGBUF_UPDATE_RX_PTR_THRS) {
|
||||
brcmf_commonring_read_complete(commonring, processed);
|
||||
processed = 0;
|
||||
}
|
||||
count--;
|
||||
}
|
||||
brcmf_commonring_read_complete(commonring);
|
||||
if (processed)
|
||||
brcmf_commonring_read_complete(commonring, processed);
|
||||
|
||||
if (commonring->r_ptr == 0)
|
||||
goto again;
|
||||
|
@@ -16,6 +16,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <net/cfg80211.h>
|
||||
|
||||
#include <brcmu_wifi.h>
|
||||
@@ -1907,105 +1908,6 @@ s32 brcmf_p2p_notify_rx_mgmt_p2p_probereq(struct brcmf_if *ifp,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* brcmf_p2p_attach() - attach for P2P.
|
||||
*
|
||||
* @cfg: driver private data for cfg80211 interface.
|
||||
*/
|
||||
s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg)
|
||||
{
|
||||
struct brcmf_if *pri_ifp;
|
||||
struct brcmf_if *p2p_ifp;
|
||||
struct brcmf_cfg80211_vif *p2p_vif;
|
||||
struct brcmf_p2p_info *p2p;
|
||||
struct brcmf_pub *drvr;
|
||||
s32 bssidx;
|
||||
s32 err = 0;
|
||||
|
||||
p2p = &cfg->p2p;
|
||||
p2p->cfg = cfg;
|
||||
|
||||
drvr = cfg->pub;
|
||||
|
||||
pri_ifp = drvr->iflist[0];
|
||||
p2p_ifp = drvr->iflist[1];
|
||||
|
||||
p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif = pri_ifp->vif;
|
||||
|
||||
if (p2p_ifp) {
|
||||
p2p_vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_P2P_DEVICE,
|
||||
false);
|
||||
if (IS_ERR(p2p_vif)) {
|
||||
brcmf_err("could not create discovery vif\n");
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
p2p_vif->ifp = p2p_ifp;
|
||||
p2p_ifp->vif = p2p_vif;
|
||||
p2p_vif->wdev.netdev = p2p_ifp->ndev;
|
||||
p2p_ifp->ndev->ieee80211_ptr = &p2p_vif->wdev;
|
||||
SET_NETDEV_DEV(p2p_ifp->ndev, wiphy_dev(cfg->wiphy));
|
||||
|
||||
p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = p2p_vif;
|
||||
|
||||
brcmf_p2p_generate_bss_mac(p2p, NULL);
|
||||
memcpy(p2p_ifp->mac_addr, p2p->dev_addr, ETH_ALEN);
|
||||
brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr);
|
||||
|
||||
/* Initialize P2P Discovery in the firmware */
|
||||
err = brcmf_fil_iovar_int_set(pri_ifp, "p2p_disc", 1);
|
||||
if (err < 0) {
|
||||
brcmf_err("set p2p_disc error\n");
|
||||
brcmf_free_vif(p2p_vif);
|
||||
goto exit;
|
||||
}
|
||||
/* obtain bsscfg index for P2P discovery */
|
||||
err = brcmf_fil_iovar_int_get(pri_ifp, "p2p_dev", &bssidx);
|
||||
if (err < 0) {
|
||||
brcmf_err("retrieving discover bsscfg index failed\n");
|
||||
brcmf_free_vif(p2p_vif);
|
||||
goto exit;
|
||||
}
|
||||
/* Verify that firmware uses same bssidx as driver !! */
|
||||
if (p2p_ifp->bssidx != bssidx) {
|
||||
brcmf_err("Incorrect bssidx=%d, compared to p2p_ifp->bssidx=%d\n",
|
||||
bssidx, p2p_ifp->bssidx);
|
||||
brcmf_free_vif(p2p_vif);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
init_completion(&p2p->send_af_done);
|
||||
INIT_WORK(&p2p->afx_hdl.afx_work, brcmf_p2p_afx_handler);
|
||||
init_completion(&p2p->afx_hdl.act_frm_scan);
|
||||
init_completion(&p2p->wait_next_af);
|
||||
}
|
||||
exit:
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* brcmf_p2p_detach() - detach P2P.
|
||||
*
|
||||
* @p2p: P2P specific data.
|
||||
*/
|
||||
void brcmf_p2p_detach(struct brcmf_p2p_info *p2p)
|
||||
{
|
||||
struct brcmf_cfg80211_vif *vif;
|
||||
|
||||
vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
|
||||
if (vif != NULL) {
|
||||
brcmf_p2p_cancel_remain_on_channel(vif->ifp);
|
||||
brcmf_p2p_deinit_discovery(p2p);
|
||||
/* remove discovery interface */
|
||||
brcmf_free_vif(vif);
|
||||
p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL;
|
||||
}
|
||||
/* just set it all to zero */
|
||||
memset(p2p, 0, sizeof(*p2p));
|
||||
}
|
||||
|
||||
/**
|
||||
* brcmf_p2p_get_current_chanspec() - Get current operation channel.
|
||||
*
|
||||
@@ -2238,6 +2140,7 @@ static void brcmf_p2p_delete_p2pdev(struct brcmf_p2p_info *p2p,
|
||||
{
|
||||
cfg80211_unregister_wdev(&vif->wdev);
|
||||
p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL;
|
||||
brcmf_remove_interface(vif->ifp->drvr, vif->ifp->bssidx);
|
||||
brcmf_free_vif(vif);
|
||||
}
|
||||
|
||||
@@ -2364,6 +2267,8 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev)
|
||||
break;
|
||||
|
||||
case NL80211_IFTYPE_P2P_DEVICE:
|
||||
brcmf_p2p_cancel_remain_on_channel(vif->ifp);
|
||||
brcmf_p2p_deinit_discovery(p2p);
|
||||
brcmf_p2p_delete_p2pdev(p2p, vif);
|
||||
return 0;
|
||||
default:
|
||||
@@ -2425,3 +2330,103 @@ void brcmf_p2p_stop_device(struct wiphy *wiphy, struct wireless_dev *wdev)
|
||||
clear_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state);
|
||||
mutex_unlock(&cfg->usr_sync);
|
||||
}
|
||||
|
||||
/**
|
||||
* brcmf_p2p_attach() - attach for P2P.
|
||||
*
|
||||
* @cfg: driver private data for cfg80211 interface.
|
||||
*/
|
||||
s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg)
|
||||
{
|
||||
struct brcmf_if *pri_ifp;
|
||||
struct brcmf_if *p2p_ifp;
|
||||
struct brcmf_cfg80211_vif *p2p_vif;
|
||||
struct brcmf_p2p_info *p2p;
|
||||
struct brcmf_pub *drvr;
|
||||
s32 bssidx;
|
||||
s32 err = 0;
|
||||
|
||||
p2p = &cfg->p2p;
|
||||
p2p->cfg = cfg;
|
||||
|
||||
drvr = cfg->pub;
|
||||
|
||||
pri_ifp = drvr->iflist[0];
|
||||
p2p_ifp = drvr->iflist[1];
|
||||
|
||||
p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif = pri_ifp->vif;
|
||||
|
||||
if (p2p_ifp) {
|
||||
p2p_vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_P2P_DEVICE,
|
||||
false);
|
||||
if (IS_ERR(p2p_vif)) {
|
||||
brcmf_err("could not create discovery vif\n");
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
p2p_vif->ifp = p2p_ifp;
|
||||
p2p_ifp->vif = p2p_vif;
|
||||
p2p_vif->wdev.netdev = p2p_ifp->ndev;
|
||||
p2p_ifp->ndev->ieee80211_ptr = &p2p_vif->wdev;
|
||||
SET_NETDEV_DEV(p2p_ifp->ndev, wiphy_dev(cfg->wiphy));
|
||||
|
||||
p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = p2p_vif;
|
||||
|
||||
brcmf_p2p_generate_bss_mac(p2p, NULL);
|
||||
memcpy(p2p_ifp->mac_addr, p2p->dev_addr, ETH_ALEN);
|
||||
brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr);
|
||||
|
||||
/* Initialize P2P Discovery in the firmware */
|
||||
err = brcmf_fil_iovar_int_set(pri_ifp, "p2p_disc", 1);
|
||||
if (err < 0) {
|
||||
brcmf_err("set p2p_disc error\n");
|
||||
brcmf_free_vif(p2p_vif);
|
||||
goto exit;
|
||||
}
|
||||
/* obtain bsscfg index for P2P discovery */
|
||||
err = brcmf_fil_iovar_int_get(pri_ifp, "p2p_dev", &bssidx);
|
||||
if (err < 0) {
|
||||
brcmf_err("retrieving discover bsscfg index failed\n");
|
||||
brcmf_free_vif(p2p_vif);
|
||||
goto exit;
|
||||
}
|
||||
/* Verify that firmware uses same bssidx as driver !! */
|
||||
if (p2p_ifp->bssidx != bssidx) {
|
||||
brcmf_err("Incorrect bssidx=%d, compared to p2p_ifp->bssidx=%d\n",
|
||||
bssidx, p2p_ifp->bssidx);
|
||||
brcmf_free_vif(p2p_vif);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
init_completion(&p2p->send_af_done);
|
||||
INIT_WORK(&p2p->afx_hdl.afx_work, brcmf_p2p_afx_handler);
|
||||
init_completion(&p2p->afx_hdl.act_frm_scan);
|
||||
init_completion(&p2p->wait_next_af);
|
||||
}
|
||||
exit:
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* brcmf_p2p_detach() - detach P2P.
|
||||
*
|
||||
* @p2p: P2P specific data.
|
||||
*/
|
||||
void brcmf_p2p_detach(struct brcmf_p2p_info *p2p)
|
||||
{
|
||||
struct brcmf_cfg80211_vif *vif;
|
||||
|
||||
vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
|
||||
if (vif != NULL) {
|
||||
brcmf_p2p_cancel_remain_on_channel(vif->ifp);
|
||||
brcmf_p2p_deinit_discovery(p2p);
|
||||
/* remove discovery interface */
|
||||
rtnl_lock();
|
||||
brcmf_p2p_delete_p2pdev(p2p, vif);
|
||||
rtnl_unlock();
|
||||
}
|
||||
/* just set it all to zero */
|
||||
memset(p2p, 0, sizeof(*p2p));
|
||||
}
|
||||
|
||||
|
@@ -1629,20 +1629,7 @@ static void brcmf_pcie_buscore_write32(void *ctx, u32 addr, u32 value)
|
||||
|
||||
static int brcmf_pcie_buscoreprep(void *ctx)
|
||||
{
|
||||
struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx;
|
||||
int err;
|
||||
|
||||
err = brcmf_pcie_get_resource(devinfo);
|
||||
if (err == 0) {
|
||||
/* Set CC watchdog to reset all the cores on the chip to bring
|
||||
* back dongle to a sane state.
|
||||
*/
|
||||
brcmf_pcie_buscore_write32(ctx, CORE_CC_REG(SI_ENUM_BASE,
|
||||
watchdog), 4);
|
||||
msleep(100);
|
||||
}
|
||||
|
||||
return err;
|
||||
return brcmf_pcie_get_resource(ctx);
|
||||
}
|
||||
|
||||
|
||||
@@ -1824,6 +1811,7 @@ brcmf_pcie_remove(struct pci_dev *pdev)
|
||||
brcmf_pcie_intr_disable(devinfo);
|
||||
|
||||
brcmf_detach(&pdev->dev);
|
||||
brcmf_pcie_reset_device(devinfo);
|
||||
|
||||
kfree(bus->bus_priv.pcie);
|
||||
kfree(bus->msgbuf->flowrings);
|
||||
|
@@ -2820,6 +2820,8 @@ static int brcmf_sdio_bus_txdata(struct device *dev, struct sk_buff *pkt)
|
||||
struct brcmf_sdio *bus = sdiodev->bus;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter: pkt: data %p len %d\n", pkt->data, pkt->len);
|
||||
if (sdiodev->state != BRCMF_SDIOD_DATA)
|
||||
return -EIO;
|
||||
|
||||
/* Add space for the header */
|
||||
skb_push(pkt, bus->tx_hdrlen);
|
||||
@@ -2948,6 +2950,8 @@ brcmf_sdio_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
|
||||
int ret;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
if (sdiodev->state != BRCMF_SDIOD_DATA)
|
||||
return -EIO;
|
||||
|
||||
/* Send from dpc */
|
||||
bus->ctrl_frame_buf = msg;
|
||||
@@ -3238,6 +3242,8 @@ brcmf_sdio_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen)
|
||||
struct brcmf_sdio *bus = sdiodev->bus;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
if (sdiodev->state != BRCMF_SDIOD_DATA)
|
||||
return -EIO;
|
||||
|
||||
/* Wait until control frame is available */
|
||||
timeleft = brcmf_sdio_dcmd_resp_wait(bus, &bus->rxlen, &pending);
|
||||
|
Reference in New Issue
Block a user