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.");
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 */
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
*/
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;
wl_rateset_t *ret_rs = (wl_rateset_t *) arg;
wlc_rateset_t *rs;
- if (bsscfg->associated)
+ if (wlc->pub->associated)
rs = ¤t_bss->rateset;
else
rs = &wlc->default_bss->rateset;
dma_walk_packets(dmah, dma_callback_fn, sta);
}
}
+
+int wlc_get_curband(struct wlc_info *wlc)
+{
+ return wlc->band->bandunit;
+}
*/
#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 */
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)
(_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 */