summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/staging/brcm80211/brcmsmac/wl_mac80211.c50
-rw-r--r--drivers/staging/brcm80211/brcmsmac/wlc_main.c11
-rw-r--r--drivers/staging/brcm80211/brcmsmac/wlc_pub.h5
-rw-r--r--drivers/staging/brcm80211/brcmsmac/wlc_rate.h8
4 files changed, 63 insertions, 11 deletions
diff --git a/drivers/staging/brcm80211/brcmsmac/wl_mac80211.c b/drivers/staging/brcm80211/brcmsmac/wl_mac80211.c
index 0faf1051a8c9..770ff933fbb6 100644
--- a/drivers/staging/brcm80211/brcmsmac/wl_mac80211.c
+++ b/drivers/staging/brcm80211/brcmsmac/wl_mac80211.c
@@ -83,6 +83,7 @@ static int __devinit wl_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *ent);
static void wl_remove(struct pci_dev *pdev);
static void wl_free(struct wl_info *wl);
+static void wl_set_basic_rate(struct wl_rateset *rs, u16 rate, bool is_br);
MODULE_AUTHOR("Broadcom Corporation");
MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN driver.");
@@ -367,9 +368,37 @@ wl_ops_bss_info_changed(struct ieee80211_hw *hw,
mode & IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT);
}
if (changed & BSS_CHANGED_BASIC_RATES) {
+ struct ieee80211_supported_band *bi;
+ u32 br_mask, i;
+ u16 rate;
+ struct wl_rateset rs;
+ int error;
+
/* Basic rateset changed */
- wiphy_err(wiphy, "%s: Need to change Basic Rates: 0x%x"
- " (implement)\n", __func__, (u32) info->basic_rates);
+ no_printk("%s: change basic rates: 0x%x\n",
+ __func__, (u32) info->basic_rates);
+
+ /* retrieve the current rates */
+ error = wlc_ioctl(wl->wlc, WLC_GET_CURR_RATESET,
+ &rs, sizeof(rs), NULL);
+ if (error) {
+ wiphy_err(wiphy, "%s: retrieve rateset failed: %d\n",
+ __func__, error);
+ return;
+ }
+ br_mask = info->basic_rates;
+ bi = hw->wiphy->bands[wlc_get_curband(wl->wlc)];
+ for (i = 0; i < bi->n_bitrates; i++) {
+ /* convert to internal rate value */
+ rate = (bi->bitrates[i].bitrate << 1) / 10;
+
+ /* set/clear basic rate flag */
+ wl_set_basic_rate(&rs, rate, br_mask & 1);
+ br_mask >>= 1;
+ }
+
+ /* update the rate set */
+ wlc_ioctl(wl->wlc, WLC_SET_RATESET, &rs, sizeof(rs), NULL);
}
if (changed & BSS_CHANGED_BEACON_INT) {
/* Beacon interval changed */
@@ -1355,6 +1384,23 @@ static void wl_free(struct wl_info *wl)
wl->regsva = NULL;
}
+/* flags the given rate in rateset as requested */
+static void wl_set_basic_rate(struct wl_rateset *rs, u16 rate, bool is_br)
+{
+ u32 i;
+
+ for (i = 0; i < rs->count; i++) {
+ if (rate != (rs->rates[i] & 0x7f))
+ continue;
+
+ if (is_br)
+ rs->rates[i] |= WLC_RATE_FLAG;
+ else
+ rs->rates[i] &= WLC_RATE_MASK;
+ return;
+ }
+}
+
/*
* precondition: perimeter lock has been acquired
*/
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_main.c b/drivers/staging/brcm80211/brcmsmac/wlc_main.c
index 05ce854d4bb3..aa0a23c2eabf 100644
--- a/drivers/staging/brcm80211/brcmsmac/wlc_main.c
+++ b/drivers/staging/brcm80211/brcmsmac/wlc_main.c
@@ -3006,8 +3006,8 @@ _wlc_ioctl(struct wlc_info *wlc, int cmd, void *arg, int len,
wlc_bss_info_t *current_bss;
/* update bsscfg pointer */
- bsscfg = NULL; /* XXX: Hack bsscfg to be size one and use this globally */
- current_bss = NULL;
+ bsscfg = wlc->cfg;
+ current_bss = bsscfg->current_bss;
/* initialize the following to get rid of compiler warning */
nextscb = NULL;
@@ -3582,7 +3582,7 @@ _wlc_ioctl(struct wlc_info *wlc, int cmd, void *arg, int len,
wl_rateset_t *ret_rs = (wl_rateset_t *) arg;
wlc_rateset_t *rs;
- if (bsscfg->associated)
+ if (wlc->pub->associated)
rs = &current_bss->rateset;
else
rs = &wlc->default_bss->rateset;
@@ -8451,3 +8451,8 @@ void wlc_inval_dma_pkts(struct wlc_hw_info *hw,
dma_walk_packets(dmah, dma_callback_fn, sta);
}
}
+
+int wlc_get_curband(struct wlc_info *wlc)
+{
+ return wlc->band->bandunit;
+}
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_pub.h b/drivers/staging/brcm80211/brcmsmac/wlc_pub.h
index 2b51440f886e..08e5fb5703d9 100644
--- a/drivers/staging/brcm80211/brcmsmac/wlc_pub.h
+++ b/drivers/staging/brcm80211/brcmsmac/wlc_pub.h
@@ -59,6 +59,10 @@
*/
#define WLC_TXPWR_MAX (127) /* ~32 dBm = 1,500 mW */
+/* rate related definitions */
+#define WLC_RATE_FLAG 0x80 /* Flag to indicate it is a basic rate */
+#define WLC_RATE_MASK 0x7f /* Rate value mask w/o basic rate flag */
+
/* legacy rx Antenna diversity for SISO rates */
#define ANT_RX_DIV_FORCE_0 0 /* Use antenna 0 */
#define ANT_RX_DIV_FORCE_1 1 /* Use antenna 1 */
@@ -564,6 +568,7 @@ extern void wlc_enable_mac(struct wlc_info *wlc);
extern void wlc_associate_upd(struct wlc_info *wlc, bool state);
extern void wlc_scan_start(struct wlc_info *wlc);
extern void wlc_scan_stop(struct wlc_info *wlc);
+extern int wlc_get_curband(struct wlc_info *wlc);
static inline int wlc_iovar_getuint(struct wlc_info *wlc, const char *name,
uint *arg)
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_rate.h b/drivers/staging/brcm80211/brcmsmac/wlc_rate.h
index f406a79cb55a..5575e83bdc69 100644
--- a/drivers/staging/brcm80211/brcmsmac/wlc_rate.h
+++ b/drivers/staging/brcm80211/brcmsmac/wlc_rate.h
@@ -54,12 +54,8 @@ extern const mcs_info_t mcs_table[];
(_is40 ? mcs_table[_mcs].phy_rate_40 : mcs_table[_mcs].phy_rate_20))
#define VALID_MCS(_mcs) ((_mcs < MCS_TABLE_SIZE))
-/* rate related definitions */
-#define WLC_RATE_FLAG 0x80 /* Rate flag to indicate it is a basic rate */
-#define WLC_RATE_MASK 0x7f /* Rate value mask w/o basic rate flag */
-
-/* Macro to use in the rate_info table */
-#define WLC_RATE_MASK_FULL 0xff /* Rate value mask with basic rate flag */
+/* Macro to use the rate_info table */
+#define WLC_RATE_MASK_FULL 0xff /* Rate value mask with basic rate flag */
#define WLC_RATE_500K_TO_BPS(rate) ((rate) * 500000) /* convert 500kbps to bps */