summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArend van Spriel <arend@broadcom.com>2011-05-03 11:35:14 +0200
committerGreg Kroah-Hartman <gregkh@suse.de>2011-05-03 12:42:32 -0700
commit94da409ef37c66aba3e4639f49d3696b141a090e (patch)
treef15375b1056616ead93ff37481a07237e7cc8221
parent78e1914dc977e1a1c970be7d4afd110735c92882 (diff)
downloadlinux-94da409ef37c66aba3e4639f49d3696b141a090e.tar.gz
staging: brcm80211: honour basic rate configuration from mac80211
The basic rates to be used are provided by the wireless access point within the beacon information. The station should conform to those rates and this information is passed by mac80211 to the driver. The patch processes the information and applies the basic rates accor- dingly. This is required functionality for mac80211 drivers. Cc: devel@linuxdriverproject.org Cc: linux-wireless@vger.kernel.org Cc: Brett Rudley <brudley@broadcom.com> Cc: Henry Ptasinski <henryp@broadcom.com> Cc: Roland Vossen <rvossen@broadcom.com> Signed-off-by: Arend van Spriel <arend@broadcom.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-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 */