aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/libertas/cmd.c7
-rw-r--r--drivers/net/wireless/libertas/cmdresp.c17
-rw-r--r--drivers/net/wireless/libertas/decl.h4
-rw-r--r--drivers/net/wireless/libertas/defs.h11
-rw-r--r--drivers/net/wireless/libertas/dev.h16
-rw-r--r--drivers/net/wireless/libertas/fw.c9
-rw-r--r--drivers/net/wireless/libertas/hostcmd.h8
-rw-r--r--drivers/net/wireless/libertas/join.c203
-rw-r--r--drivers/net/wireless/libertas/join.h2
-rw-r--r--drivers/net/wireless/libertas/main.c57
-rw-r--r--drivers/net/wireless/libertas/rx.c9
-rw-r--r--drivers/net/wireless/libertas/scan.c54
-rw-r--r--drivers/net/wireless/libertas/scan.h4
-rw-r--r--drivers/net/wireless/libertas/wext.c163
14 files changed, 241 insertions, 323 deletions
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
index c96ced963d6..c3fc074b6e3 100644
--- a/drivers/net/wireless/libertas/cmd.c
+++ b/drivers/net/wireless/libertas/cmd.c
@@ -607,17 +607,14 @@ static int wlan_cmd_802_11_data_rate(wlan_private * priv,
cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_data_rate) +
S_DS_GEN);
-
cmd->command = cpu_to_le16(CMD_802_11_DATA_RATE);
-
memset(pdatarate, 0, sizeof(struct cmd_ds_802_11_data_rate));
-
pdatarate->action = cpu_to_le16(cmd_action);
if (cmd_action == CMD_ACT_SET_TX_FIX_RATE) {
- pdatarate->datarate[0] = libertas_data_rate_to_index(adapter->datarate);
+ pdatarate->rates[0] = libertas_data_rate_to_fw_index(adapter->cur_rate);
lbs_deb_cmd("Setting FW for fixed rate 0x%02X\n",
- adapter->datarate);
+ adapter->cur_rate);
} else if (cmd_action == CMD_ACT_SET_TX_AUTO) {
lbs_deb_cmd("Setting FW for AUTO rate\n");
}
diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c
index d90279269e7..577c434089b 100644
--- a/drivers/net/wireless/libertas/cmdresp.c
+++ b/drivers/net/wireless/libertas/cmdresp.c
@@ -430,21 +430,18 @@ static int wlan_ret_802_11_data_rate(wlan_private * priv,
{
struct cmd_ds_802_11_data_rate *pdatarate = &resp->params.drate;
wlan_adapter *adapter = priv->adapter;
- u8 dot11datarate;
lbs_deb_enter(LBS_DEB_CMD);
- lbs_dbg_hex("DATA_RATE_RESP: data_rate- ",
- (u8 *) pdatarate, sizeof(struct cmd_ds_802_11_data_rate));
+ lbs_dbg_hex("DATA_RATE_RESP: data_rate- ", (u8 *) pdatarate,
+ sizeof(struct cmd_ds_802_11_data_rate));
- dot11datarate = pdatarate->datarate[0];
- if (pdatarate->action == cpu_to_le16(CMD_ACT_GET_TX_RATE)) {
- memcpy(adapter->libertas_supported_rates, pdatarate->datarate,
- sizeof(adapter->libertas_supported_rates));
- }
- adapter->datarate = libertas_index_to_data_rate(dot11datarate);
+ /* FIXME: get actual rates FW can do if this command actually returns
+ * all data rates supported.
+ */
+ adapter->cur_rate = libertas_fw_index_to_data_rate(pdatarate->rates[0]);
- lbs_deb_enter(LBS_DEB_CMD);
+ lbs_deb_leave(LBS_DEB_CMD);
return 0;
}
diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h
index 846e79a77f6..129b021d35f 100644
--- a/drivers/net/wireless/libertas/decl.h
+++ b/drivers/net/wireless/libertas/decl.h
@@ -44,8 +44,8 @@ int libertas_execute_next_command(wlan_private * priv);
int libertas_process_event(wlan_private * priv);
void libertas_interrupt(struct net_device *);
int libertas_set_radio_control(wlan_private * priv);
-u32 libertas_index_to_data_rate(u8 index);
-u8 libertas_data_rate_to_index(u32 rate);
+u32 libertas_fw_index_to_data_rate(u8 index);
+u8 libertas_data_rate_to_fw_index(u32 rate);
void libertas_get_fwversion(wlan_adapter * adapter, char *fwversion, int maxlen);
void libertas_upload_rx_packet(wlan_private * priv, struct sk_buff *skb);
diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h
index 862292913c2..a1c6dae1ba4 100644
--- a/drivers/net/wireless/libertas/defs.h
+++ b/drivers/net/wireless/libertas/defs.h
@@ -246,10 +246,7 @@ static inline void lbs_dbg_hex(char *prompt, u8 * buf, int len)
((((int)(AVG) * (N -1)) + ((u16)(SNRNF) * \
AVG_SCALE)) / N))
-#define B_SUPPORTED_RATES 8
-#define G_SUPPORTED_RATES 14
-
-#define WLAN_SUPPORTED_RATES 14
+#define MAX_RATES 14
#define MAX_LEDS 8
@@ -263,11 +260,7 @@ typedef struct _wlan_adapter wlan_adapter;
extern const char libertas_driver_version[];
extern u16 libertas_region_code_to_index[MRVDRV_MAX_REGION_CODE];
-extern u8 libertas_supported_rates[G_SUPPORTED_RATES];
-
-extern u8 libertas_adhoc_rates_g[G_SUPPORTED_RATES];
-
-extern u8 libertas_adhoc_rates_b[4];
+extern u8 libertas_bg_rates[MAX_RATES];
/** ENUM definition*/
/** SNRNF_TYPE */
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
index c6fb703f665..6acb8fb8733 100644
--- a/drivers/net/wireless/libertas/dev.h
+++ b/drivers/net/wireless/libertas/dev.h
@@ -72,10 +72,8 @@ struct current_bss_params {
u8 band;
/** channel */
u8 channel;
- /** number of rates supported */
- int numofrates;
- /** supported rates*/
- u8 datarates[WLAN_SUPPORTED_RATES];
+ /** zero-terminated array of supported data rates */
+ u8 rates[MAX_RATES + 1];
};
/** sleep_params */
@@ -296,9 +294,6 @@ struct _wlan_adapter {
u32 fragthsd;
u32 rtsthsd;
- u32 datarate;
- u8 is_datarate_auto;
-
u16 listeninterval;
u16 prescan;
u8 txretrycount;
@@ -364,10 +359,9 @@ struct _wlan_adapter {
u8 radioon;
u32 preamble;
- /** Multi bands Parameter*/
- u8 libertas_supported_rates[G_SUPPORTED_RATES];
-
- /** Blue Tooth Co-existence Arbitration */
+ /** data rate stuff */
+ u8 cur_rate;
+ u8 auto_rate;
/** sleep_params */
struct sleep_params sp;
diff --git a/drivers/net/wireless/libertas/fw.c b/drivers/net/wireless/libertas/fw.c
index d214692eb20..6c259878da9 100644
--- a/drivers/net/wireless/libertas/fw.c
+++ b/drivers/net/wireless/libertas/fw.c
@@ -214,7 +214,10 @@ static void wlan_init_adapter(wlan_private * priv)
adapter->txantenna = RF_ANTENNA_2;
adapter->rxantenna = RF_ANTENNA_AUTO;
- adapter->is_datarate_auto = 1;
+ adapter->auto_rate = 1;
+ adapter->cur_rate = 0;
+ adapter->adhoc_grate_enabled = 0;
+
adapter->beaconperiod = MRVDRV_BEACON_INTERVAL;
// set default capabilities
@@ -229,10 +232,6 @@ static void wlan_init_adapter(wlan_private * priv)
adapter->needtowakeup = 0;
adapter->locallisteninterval = 0; /* default value in firmware will be used */
- adapter->datarate = 0; // Initially indicate the rate as auto
-
- adapter->adhoc_grate_enabled = 0;
-
adapter->intcounter = 0;
adapter->currenttxskb = NULL;
diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h
index 76c5fdeb256..44cf39c8d1b 100644
--- a/drivers/net/wireless/libertas/hostcmd.h
+++ b/drivers/net/wireless/libertas/hostcmd.h
@@ -428,8 +428,8 @@ struct PS_CMD_ConfirmSleep {
struct cmd_ds_802_11_data_rate {
__le16 action;
- __le16 reserverd;
- u8 datarate[G_SUPPORTED_RATES];
+ __le16 reserved;
+ u8 rates[MAX_RATES];
};
struct cmd_ds_802_11_rate_adapt_rateset {
@@ -447,7 +447,7 @@ struct cmd_ds_802_11_ad_hoc_start {
union ieeetypes_phyparamset phyparamset;
__le16 probedelay;
__le16 capability;
- u8 datarate[G_SUPPORTED_RATES];
+ u8 rates[MAX_RATES];
u8 tlv_memory_size_pad[100];
} __attribute__ ((packed));
@@ -462,7 +462,7 @@ struct adhoc_bssdesc {
union ieeetypes_phyparamset phyparamset;
union IEEEtypes_ssparamset ssparamset;
__le16 capability;
- u8 datarates[G_SUPPORTED_RATES];
+ u8 rates[MAX_RATES];
/* DO NOT ADD ANY FIELDS TO THIS STRUCTURE. It is used below in the
* Adhoc join command and will cause a binary layout mismatch with
diff --git a/drivers/net/wireless/libertas/join.c b/drivers/net/wireless/libertas/join.c
index 381739d6ed9..78e398d6f5f 100644
--- a/drivers/net/wireless/libertas/join.c
+++ b/drivers/net/wireless/libertas/join.c
@@ -17,8 +17,12 @@
#include "dev.h"
#include "assoc.h"
+/* Supported rates for ad-hoc B mode */
+u8 adhoc_rates_b[5] = { 0x02, 0x04, 0x0b, 0x16, 0x00 };
+
+
/**
- * @brief This function finds out the common rates between rate1 and rate2.
+ * @brief This function finds common rates between rate1 and card rates.
*
* It will fill common rates in rate1 as output if found.
*
@@ -27,61 +31,87 @@
*
* @param adapter A pointer to wlan_adapter structure
* @param rate1 the buffer which keeps input and output
- * @param rate1_size the size of rate1 buffer
- * @param rate2 the buffer which keeps rate2
- * @param rate2_size the size of rate2 buffer.
+ * @param rate1_size the size of rate1 buffer; new size of buffer on return
*
* @return 0 or -1
*/
-static int get_common_rates(wlan_adapter * adapter, u8 * rate1,
- int rate1_size, u8 * rate2, int rate2_size)
+static int get_common_rates(wlan_adapter * adapter, u8 * rates, u16 *rates_size)
{
- u8 *ptr = rate1;
- int ret = 0;
+ u8 *card_rates = libertas_bg_rates;
+ size_t num_card_rates = sizeof(libertas_bg_rates);
+ int ret = 0, i, j;
u8 tmp[30];
- int i;
+ size_t tmp_size = 0;
- memset(&tmp, 0, sizeof(tmp));
- memcpy(&tmp, rate1, min_t(size_t, rate1_size, sizeof(tmp)));
- memset(rate1, 0, rate1_size);
-
- /* Mask the top bit of the original values */
- for (i = 0; tmp[i] && i < sizeof(tmp); i++)
- tmp[i] &= 0x7F;
-
- for (i = 0; rate2[i] && i < rate2_size; i++) {
- /* Check for Card Rate in tmp, excluding the top bit */
- if (strchr(tmp, rate2[i] & 0x7F)) {
- /* values match, so copy the Card Rate to rate1 */
- *rate1++ = rate2[i];
+ /* For each rate in card_rates that exists in rate1, copy to tmp */
+ for (i = 0; card_rates[i] && (i < num_card_rates); i++) {
+ for (j = 0; rates[j] && (j < *rates_size); j++) {
+ if (rates[j] == card_rates[i])
+ tmp[tmp_size++] = card_rates[i];
}
}
- lbs_dbg_hex("rate1 (AP) rates:", tmp, sizeof(tmp));
- lbs_dbg_hex("rate2 (Card) rates:", rate2, rate2_size);
- lbs_dbg_hex("Common rates:", ptr, rate1_size);
- lbs_deb_join("Tx datarate is set to 0x%X\n", adapter->datarate);
+ lbs_dbg_hex("rate1 (AP) rates:", rates, *rates_size);
+ lbs_dbg_hex("rate2 (Card) rates:", card_rates, num_card_rates);
+ lbs_dbg_hex("Common rates:", tmp, tmp_size);
+ lbs_deb_join("Tx datarate is currently 0x%X\n", adapter->cur_rate);
- if (!adapter->is_datarate_auto) {
- while (*ptr) {
- if ((*ptr & 0x7f) == adapter->datarate) {
- ret = 0;
+ if (!adapter->auto_rate) {
+ for (i = 0; i < tmp_size; i++) {
+ if (tmp[i] == adapter->cur_rate)
goto done;
- }
- ptr++;
}
- lbs_pr_alert( "Previously set fixed data rate %#x isn't "
- "compatible with the network.\n", adapter->datarate);
-
+ lbs_pr_alert("Previously set fixed data rate %#x isn't "
+ "compatible with the network.\n", adapter->cur_rate);
ret = -1;
goto done;
}
-
ret = 0;
+
done:
+ memset(rates, 0, *rates_size);
+ *rates_size = min_t(int, tmp_size, *rates_size);
+ memcpy(rates, tmp, *rates_size);
return ret;
}
+
+/**
+ * @brief Sets the MSB on basic rates as the firmware requires
+ *
+ * Scan through an array and set the MSB for basic data rates.
+ *
+ * @param rates buffer of data rates
+ * @param len size of buffer
+ */
+static void libertas_set_basic_rate_flags(u8 * rates, size_t len)
+{
+ int i;
+
+ for (i = 0; i < len; i++) {
+ if (rates[i] == 0x02 || rates[i] == 0x04 ||
+ rates[i] == 0x0b || rates[i] == 0x16)
+ rates[i] |= 0x80;
+ }
+}
+
+/**
+ * @brief Unsets the MSB on basic rates
+ *
+ * Scan through an array and unset the MSB for basic data rates.
+ *
+ * @param rates buffer of data rates
+ * @param len size of buffer
+ */
+void libertas_unset_basic_rate_flags(u8 * rates, size_t len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ rates[i] &= 0x7f;
+}
+
+
int libertas_send_deauth(wlan_private * priv)
{
wlan_adapter *adapter = priv->adapter;
@@ -330,9 +360,7 @@ int libertas_cmd_80211_associate(wlan_private * priv,
int ret = 0;
struct assoc_request * assoc_req = pdata_buf;
struct bss_descriptor * bss = &assoc_req->bss;
- u8 *card_rates;
u8 *pos;
- int card_rates_size;
u16 tmpcap, tmplen;
struct mrvlietypes_ssidparamset *ssid;
struct mrvlietypes_phyparamset *phy;
@@ -386,23 +414,24 @@ int libertas_cmd_80211_associate(wlan_private * priv,
rates = (struct mrvlietypes_ratesparamset *) pos;
rates->header.type = cpu_to_le16(TLV_TYPE_RATES);
-
- memcpy(&rates->rates, &bss->libertas_supported_rates, WLAN_SUPPORTED_RATES);
-
- card_rates = libertas_supported_rates;
- card_rates_size = sizeof(libertas_supported_rates);
-
- if (get_common_rates(adapter, rates->rates, WLAN_SUPPORTED_RATES,
- card_rates, card_rates_size)) {
+ memcpy(&rates->rates, &bss->rates, MAX_RATES);
+ tmplen = MAX_RATES;
+ if (get_common_rates(adapter, rates->rates, &tmplen)) {
ret = -1;
goto done;
}
-
- tmplen = min_t(size_t, strlen(rates->rates), WLAN_SUPPORTED_RATES);
- adapter->curbssparams.numofrates = tmplen;
-
pos += sizeof(rates->header) + tmplen;
rates->header.len = cpu_to_le16(tmplen);
+ lbs_deb_join("ASSOC_CMD: num rates = %u\n", tmplen);
+
+ /* Copy the infra. association rates into Current BSS state structure */
+ memset(&adapter->curbssparams.rates, 0, sizeof(adapter->curbssparams.rates));
+ memcpy(&adapter->curbssparams.rates, &rates->rates, tmplen);
+
+ /* Set MSB on basic rates as the firmware requires, but _after_
+ * copying to current bss rates.
+ */
+ libertas_set_basic_rate_flags(rates->rates, tmplen);
if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) {
rsn = (struct mrvlietypes_rsnparamset *) pos;
@@ -419,14 +448,6 @@ int libertas_cmd_80211_associate(wlan_private * priv,
/* update curbssparams */
adapter->curbssparams.channel = bss->phyparamset.dsparamset.currentchan;
- /* Copy the infra. association rates into Current BSS state structure */
- memcpy(&adapter->curbssparams.datarates, &rates->rates,
- min_t(size_t, sizeof(adapter->curbssparams.datarates),
- cpu_to_le16(rates->header.len)));
-
- lbs_deb_join("ASSOC_CMD: rates->header.len = %d\n",
- cpu_to_le16(rates->header.len));
-
if (libertas_parse_dnld_countryinfo_11d(priv, bss)) {
ret = -1;
goto done;
@@ -454,9 +475,9 @@ int libertas_cmd_80211_ad_hoc_start(wlan_private * priv,
struct cmd_ds_802_11_ad_hoc_start *adhs = &cmd->params.ads;
int ret = 0;
int cmdappendsize = 0;
- int i;
struct assoc_request * assoc_req = pdata_buf;
u16 tmpcap = 0;
+ size_t ratesize = 0;
lbs_deb_enter(LBS_DEB_JOIN);
@@ -526,28 +547,26 @@ int libertas_cmd_80211_ad_hoc_start(wlan_private * priv,
/* probedelay */
adhs->probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
- memset(adhs->datarate, 0, sizeof(adhs->datarate));
-
+ memset(adhs->rates, 0, sizeof(adhs->rates));
if (adapter->adhoc_grate_enabled) {
- memcpy(adhs->datarate, libertas_adhoc_rates_g,
- min(sizeof(adhs->datarate), sizeof(libertas_adhoc_rates_g)));
+ ratesize = min(sizeof(adhs->rates), sizeof(libertas_bg_rates));
+ memcpy(adhs->rates, libertas_bg_rates, ratesize);
} else {
- memcpy(adhs->datarate, libertas_adhoc_rates_b,
- min(sizeof(adhs->datarate), sizeof(libertas_adhoc_rates_b)));
+ ratesize = min(sizeof(adhs->rates), sizeof(adhoc_rates_b));
+ memcpy(adhs->rates, adhoc_rates_b, ratesize);
}
- /* Find the last non zero */
- for (i = 0; i < sizeof(adhs->datarate) && adhs->datarate[i]; i++) ;
-
- adapter->curbssparams.numofrates = i;
-
/* Copy the ad-hoc creating rates into Current BSS state structure */
- memcpy(&adapter->curbssparams.datarates,
- &adhs->datarate, adapter->curbssparams.numofrates);
+ memset(&adapter->curbssparams.rates, 0, sizeof(adapter->curbssparams.rates));
+ memcpy(&adapter->curbssparams.rates, &adhs->rates, ratesize);
+
+ /* Set MSB on basic rates as the firmware requires, but _after_
+ * copying to current bss rates.
+ */
+ libertas_set_basic_rate_flags(adhs->rates, ratesize);
lbs_deb_join("ADHOC_S_CMD: rates=%02x %02x %02x %02x \n",
- adhs->datarate[0], adhs->datarate[1],
- adhs->datarate[2], adhs->datarate[3]);
+ adhs->rates[0], adhs->rates[1], adhs->rates[2], adhs->rates[3]);
lbs_deb_join("ADHOC_S_CMD: AD HOC Start command is ready\n");
@@ -584,9 +603,7 @@ int libertas_cmd_80211_ad_hoc_join(wlan_private * priv,
struct bss_descriptor *bss = &assoc_req->bss;
int cmdappendsize = 0;
int ret = 0;
- u8 *card_rates;
- int card_rates_size;
- int i;
+ u16 ratesize = 0;
lbs_deb_enter(LBS_DEB_JOIN);
@@ -619,36 +636,26 @@ int libertas_cmd_80211_ad_hoc_join(wlan_private * priv,
/* probedelay */
join_cmd->probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
- /* Copy Data rates from the rates recorded in scan response */
- memset(join_cmd->bss.datarates, 0, sizeof(join_cmd->bss.datarates));
- memcpy(join_cmd->bss.datarates, bss->datarates,
- min(sizeof(join_cmd->bss.datarates), sizeof(bss->datarates)));
-
- card_rates = libertas_supported_rates;
- card_rates_size = sizeof(libertas_supported_rates);
-
adapter->curbssparams.channel = bss->channel;
- if (get_common_rates(adapter, join_cmd->bss.datarates,
- sizeof(join_cmd->bss.datarates),
- card_rates, card_rates_size)) {
+ /* Copy Data rates from the rates recorded in scan response */
+ memset(join_cmd->bss.rates, 0, sizeof(join_cmd->bss.rates));
+ ratesize = min_t(u16, sizeof(join_cmd->bss.rates), MAX_RATES);
+ memcpy(join_cmd->bss.rates, bss->rates, ratesize);
+ if (get_common_rates(adapter, join_cmd->bss.rates, &ratesize)) {
lbs_deb_join("ADHOC_J_CMD: get_common_rates returns error.\n");
ret = -1;
goto done;
}
- /* Find the last non zero */
- for (i = 0; i < sizeof(join_cmd->bss.datarates)
- && join_cmd->bss.datarates[i]; i++) ;
-
- adapter->curbssparams.numofrates = i;
+ /* Copy the ad-hoc creating rates into Current BSS state structure */
+ memset(&adapter->curbssparams.rates, 0, sizeof(adapter->curbssparams.rates));
+ memcpy(&adapter->curbssparams.rates, join_cmd->bss.rates, ratesize);
- /*
- * Copy the adhoc joining rates to Current BSS State structure
+ /* Set MSB on basic rates as the firmware requires, but _after_
+ * copying to current bss rates.
*/
- memcpy(adapter->curbssparams.datarates,
- join_cmd->bss.datarates,
- adapter->curbssparams.numofrates);
+ libertas_set_basic_rate_flags(join_cmd->bss.rates, ratesize);
join_cmd->bss.ssparamset.ibssparamset.atimwindow =
cpu_to_le16(bss->atimwindow);
diff --git a/drivers/net/wireless/libertas/join.h b/drivers/net/wireless/libertas/join.h
index d522630ff8c..8ea5ae30f4a 100644
--- a/drivers/net/wireless/libertas/join.h
+++ b/drivers/net/wireless/libertas/join.h
@@ -53,4 +53,6 @@ extern int libertas_do_adhocstop_ioctl(wlan_private * priv);
int wlan_associate(wlan_private * priv, struct assoc_request * assoc_req);
+void libertas_unset_basic_rate_flags(u8 * rates, size_t len);
+
#endif
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index 26948595d95..03217f5537a 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -150,29 +150,60 @@ static struct region_cfp_table region_cfp_table[] = {
};
/**
- * the rates supported
+ * the table to keep region code
*/
-u8 libertas_supported_rates[G_SUPPORTED_RATES] =
- { 0x82, 0x84, 0x8b, 0x96, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c,
-0 };
+u16 libertas_region_code_to_index[MRVDRV_MAX_REGION_CODE] =
+ { 0x10, 0x20, 0x30, 0x31, 0x32, 0x40 };
/**
- * the rates supported for ad-hoc G mode
+ * 802.11b/g supported bitrates (in 500Kb/s units)
*/
-u8 libertas_adhoc_rates_g[G_SUPPORTED_RATES] =
- { 0x82, 0x84, 0x8b, 0x96, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c,
-0 };
+u8 libertas_bg_rates[MAX_RATES] =
+ { 0x02, 0x04, 0x0b, 0x16, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c,
+0x00, 0x00 };
/**
- * the rates supported for ad-hoc B mode
+ * FW rate table. FW refers to rates by their index in this table, not by the
+ * rate value itself. Values of 0x00 are
+ * reserved positions.
*/
-u8 libertas_adhoc_rates_b[4] = { 0x82, 0x84, 0x8b, 0x96 };
+static u8 fw_data_rates[MAX_RATES] =
+ { 0x02, 0x04, 0x0B, 0x16, 0x00, 0x0C, 0x12,
+ 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C, 0x00
+};
/**
- * the table to keep region code
+ * @brief use index to get the data rate
+ *
+ * @param idx The index of data rate
+ * @return data rate or 0
*/
-u16 libertas_region_code_to_index[MRVDRV_MAX_REGION_CODE] =
- { 0x10, 0x20, 0x30, 0x31, 0x32, 0x40 };
+u32 libertas_fw_index_to_data_rate(u8 idx)
+{
+ if (idx >= sizeof(fw_data_rates))
+ idx = 0;
+ return fw_data_rates[idx];
+}
+
+/**
+ * @brief use rate to get the index
+ *
+ * @param rate data rate
+ * @return index or 0
+ */
+u8 libertas_data_rate_to_fw_index(u32 rate)
+{
+ u8 i;
+
+ if (!rate)
+ return 0;
+
+ for (i = 0; i < sizeof(fw_data_rates); i++) {
+ if (rate == fw_data_rates[i])
+ return i;
+ }
+ return 0;
+}
/**
* Attributes exported through sysfs
diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c
index 769c86fb950..e78636d6651 100644
--- a/drivers/net/wireless/libertas/rx.c
+++ b/drivers/net/wireless/libertas/rx.c
@@ -260,8 +260,8 @@ int libertas_process_rxed_packet(wlan_private * priv, struct sk_buff *skb)
/* Take the data rate from the rxpd structure
* only if the rate is auto
*/
- if (adapter->is_datarate_auto)
- adapter->datarate = libertas_index_to_data_rate(p_rx_pd->rx_rate);
+ if (adapter->auto_rate)
+ adapter->cur_rate = libertas_fw_index_to_data_rate(p_rx_pd->rx_rate);
wlan_compute_rssi(priv, p_rx_pd);
@@ -424,9 +424,8 @@ static int process_rxed_802_11_packet(wlan_private * priv, struct sk_buff *skb)
/* Take the data rate from the rxpd structure
* only if the rate is auto
*/
- if (adapter->is_datarate_auto) {
- adapter->datarate = libertas_index_to_data_rate(prxpd->rx_rate);
- }
+ if (adapter->auto_rate)
+ adapter->cur_rate = libertas_fw_index_to_data_rate(prxpd->rx_rate);
wlan_compute_rssi(priv, prxpd);
diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c
index 2cac47fc4cd..790e9888ea2 100644
--- a/drivers/net/wireless/libertas/scan.c
+++ b/drivers/net/wireless/libertas/scan.c
@@ -17,6 +17,7 @@
#include "decl.h"
#include "dev.h"
#include "scan.h"
+#include "join.h"
//! Approximate amount of data needed to pass a scan result back to iwlist
#define MAX_SCAN_CELL_SIZE (IW_EV_ADDR_LEN \
@@ -904,22 +905,14 @@ static int libertas_process_bss(struct bss_descriptor * bss,
struct ieeetypes_dsparamset *pDS;
struct ieeetypes_cfparamset *pCF;
struct ieeetypes_ibssparamset *pibss;
- u8 *pos, *end;
- u8 *pRate;
- u8 bytestocopy;
- u8 ratesize;
- u16 beaconsize;
- u8 founddatarateie;
- int ret;
-
struct ieeetypes_countryinfoset *pcountryinfo;
+ u8 *pos, *end, *p;
+ u8 n_ex_rates = 0, got_basic_rates = 0, n_basic_rates = 0;
+ u16 beaconsize = 0;
+ int ret;
lbs_deb_enter(LBS_DEB_ASSOC);
- founddatarateie = 0;
- ratesize = 0;
- beaconsize = 0;
-
if (*bytesleft >= sizeof(beaconsize)) {
/* Extract & convert beacon size from the command buffer */
beaconsize = le16_to_cpup((void *)*pbeaconinfo);
@@ -1005,11 +998,9 @@ static int libertas_process_bss(struct bss_descriptor * bss,
break;
case MFIE_TYPE_RATES:
- memcpy(bss->datarates, elem->data, elem->len);
- memmove(bss->libertas_supported_rates, elem->data,
- elem->len);
- ratesize = elem->len;
- founddatarateie = 1;
+ n_basic_rates = min_t(u8, MAX_RATES, elem->len);
+ memcpy(bss->rates, elem->data, n_basic_rates);
+ got_basic_rates = 1;
break;
case MFIE_TYPE_FH_SET:
@@ -1070,22 +1061,15 @@ static int libertas_process_bss(struct bss_descriptor * bss,
* already found. Data rate IE should come before
* extended supported rate IE
*/
- if (!founddatarateie)
+ if (!got_basic_rates)
break;
- if ((elem->len + ratesize) > WLAN_SUPPORTED_RATES) {
- bytestocopy =
- (WLAN_SUPPORTED_RATES - ratesize);
- } else {
- bytestocopy = elem->len;
- }
+ n_ex_rates = elem->len;
+ if (n_basic_rates + n_ex_rates > MAX_RATES)
+ n_ex_rates = MAX_RATES - n_basic_rates;
- pRate = (u8 *) bss->datarates;
- pRate += ratesize;
- memmove(pRate, elem->data, bytestocopy);
- pRate = (u8 *) bss->libertas_supported_rates;
- pRate += ratesize;
- memmove(pRate, elem->data, bytestocopy);
+ p = bss->rates + n_basic_rates;
+ memcpy(p, elem->data, n_ex_rates);
break;
case MFIE_TYPE_GENERIC:
@@ -1123,6 +1107,7 @@ static int libertas_process_bss(struct bss_descriptor * bss,
/* Timestamp */
bss->last_scanned = jiffies;
+ libertas_unset_basic_rate_flags(bss->rates, sizeof(bss->rates));
ret = 0;
@@ -1530,12 +1515,9 @@ static inline char *libertas_translate_scan(wlan_private *priv,
iwe.u.bitrate.disabled = 0;
iwe.u.bitrate.value = 0;
- for (j = 0; j < sizeof(bss->libertas_supported_rates); j++) {
- u8 rate = bss->libertas_supported_rates[j];
- if (rate == 0)
- break; /* no more rates */
- /* Bit rate given in 500 kb/s units (+ 0x80) */
- iwe.u.bitrate.value = (rate & 0x7f) * 500000;
+ for (j = 0; bss->rates[j] && (j < sizeof(bss->rates)); j++) {
+ /* Bit rate given in 500 kb/s units */
+ iwe.u.bitrate.value = bss->rates[j] * 500000;
current_val = iwe_stream_add_value(start, current_val,
stop, &iwe, IW_EV_PARAM_LEN);
}
diff --git a/drivers/net/wireless/libertas/scan.h b/drivers/net/wireless/libertas/scan.h
index 23c539c2263..8c3508b3257 100644
--- a/drivers/net/wireless/libertas/scan.h
+++ b/drivers/net/wireless/libertas/scan.h
@@ -152,14 +152,14 @@ struct bss_descriptor {
u32 atimwindow;
u8 mode;
- u8 libertas_supported_rates[WLAN_SUPPORTED_RATES];
+ /* zero-terminated array of supported data rates */
+ u8 rates[MAX_RATES + 1];
__le64 timestamp; //!< TSF value included in the beacon/probe response
unsigned long last_scanned;
union ieeetypes_phyparamset phyparamset;
union IEEEtypes_ssparamset ssparamset;
- u8 datarates[WLAN_SUPPORTED_RATES];
u64 networktsf; //!< TSF timestamp from the current firmware TSF
diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c
index 115f02c010a..0b805e32993 100644
--- a/drivers/net/wireless/libertas/wext.c
+++ b/drivers/net/wireless/libertas/wext.c
@@ -22,14 +22,6 @@
/**
- * the rates supported by the card
- */
-static u8 libertas_wlan_data_rates[WLAN_SUPPORTED_RATES] =
- { 0x02, 0x04, 0x0B, 0x16, 0x00, 0x0C, 0x12,
- 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C, 0x00
-};
-
-/**
* @brief Convert mw value to dbm value
*
* @param mw the value of mw
@@ -187,57 +179,21 @@ int wlan_radio_ioctl(wlan_private * priv, u8 option)
}
/**
- * @brief Copy rates
- *
- * @param dest A pointer to Dest Buf
- * @param src A pointer to Src Buf
- * @param len The len of Src Buf
- * @return Number of rates copyed
- */
-static inline int copyrates(u8 * dest, int pos, u8 * src, int len)
-{
- int i;
-
- for (i = 0; i < len && src[i]; i++, pos++) {
- if (pos >= sizeof(u8) * WLAN_SUPPORTED_RATES)
- break;
- dest[pos] = src[i];
- }
-
- return pos;
-}
-
-/**
- * @brief Get active data rates
+ * @brief Copy active data rates based on adapter mode and status
*
* @param adapter A pointer to wlan_adapter structure
* @param rate The buf to return the active rates
- * @return The number of rates
*/
-static int get_active_data_rates(wlan_adapter * adapter,
- u8* rates)
+static void copy_active_data_rates(wlan_adapter * adapter, u8 * rates)
{
- int k = 0;
-
lbs_deb_enter(LBS_DEB_WEXT);
- if (adapter->connect_status != LIBERTAS_CONNECTED) {
- if (adapter->mode == IW_MODE_INFRA) {
- lbs_deb_wext("infra\n");
- k = copyrates(rates, k, libertas_supported_rates,
- sizeof(libertas_supported_rates));
- } else {
- lbs_deb_wext("Adhoc G\n");
- k = copyrates(rates, k, libertas_adhoc_rates_g,
- sizeof(libertas_adhoc_rates_g));
- }
- } else {
- k = copyrates(rates, 0, adapter->curbssparams.datarates,
- adapter->curbssparams.numofrates);
- }
+ if (adapter->connect_status != LIBERTAS_CONNECTED)
+ memcpy(rates, libertas_bg_rates, MAX_RATES);
+ else
+ memcpy(rates, adapter->curbssparams.rates, MAX_RATES);
- lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", k);
- return k;
+ lbs_deb_leave(LBS_DEB_WEXT);
}
static int wlan_get_name(struct net_device *dev, struct iw_request_info *info,
@@ -673,7 +629,7 @@ static int wlan_get_range(struct net_device *dev, struct iw_request_info *info,
wlan_adapter *adapter = priv->adapter;
struct iw_range *range = (struct iw_range *)extra;
struct chan_freq_power *cfp;
- u8 rates[WLAN_SUPPORTED_RATES];
+ u8 rates[MAX_RATES + 1];
u8 flag = 0;
@@ -686,12 +642,10 @@ static int wlan_get_range(struct net_device *dev, struct iw_request_info *info,
range->max_nwid = 0;
memset(rates, 0, sizeof(rates));
- range->num_bitrates = get_active_data_rates(adapter, rates);
-
- for (i = 0; i < min_t(__u8, range->num_bitrates, IW_MAX_BITRATES) && rates[i];
- i++) {
- range->bitrate[i] = (rates[i] & 0x7f) * 500000;
- }
+ copy_active_data_rates(adapter, rates);
+ range->num_bitrates = strnlen(rates, IW_MAX_BITRATES);
+ for (i = 0; i < range->num_bitrates; i++)
+ range->bitrate[i] = rates[i] * 500000;
range->num_bitrates = i;
lbs_deb_wext("IW_MAX_BITRATES %d, num_bitrates %d\n", IW_MAX_BITRATES,
range->num_bitrates);
@@ -1080,88 +1034,46 @@ out:
return ret;
}
-/**
- * @brief use index to get the data rate
- *
- * @param index The index of data rate
- * @return data rate or 0
- */
-u32 libertas_index_to_data_rate(u8 index)
-{
- if (index >= sizeof(libertas_wlan_data_rates))
- index = 0;
-
- return libertas_wlan_data_rates[index];
-}
-
-/**
- * @brief use rate to get the index
- *
- * @param rate data rate
- * @return index or 0
- */
-u8 libertas_data_rate_to_index(u32 rate)
-{
- u8 *ptr;
-
- if (rate)
- if ((ptr = memchr(libertas_wlan_data_rates, (u8) rate,
- sizeof(libertas_wlan_data_rates))))
- return (ptr - libertas_wlan_data_rates);
-
- return 0;
-}
-
static int wlan_set_rate(struct net_device *dev, struct iw_request_info *info,
struct iw_param *vwrq, char *extra)
{
wlan_private *priv = dev->priv;
wlan_adapter *adapter = priv->adapter;
- u32 data_rate;
+ u32 new_rate;
u16 action;
- int ret = 0;
- u8 rates[WLAN_SUPPORTED_RATES];
- u8 *rate;
+ int ret = -EINVAL;
+ u8 rates[MAX_RATES + 1];
lbs_deb_enter(LBS_DEB_WEXT);
-
lbs_deb_wext("vwrq->value %d\n", vwrq->value);
+ /* Auto rate? */
if (vwrq->value == -1) {
- action = CMD_ACT_SET_TX_AUTO; // Auto
- adapter->is_datarate_auto = 1;
- adapter->datarate = 0;
+ action = CMD_ACT_SET_TX_AUTO;
+ adapter->auto_rate = 1;
+ adapter->cur_rate = 0;
} else {
- if (vwrq->value % 100000) {
- return -EINVAL;
- }
-
- data_rate = vwrq->value / 500000;
+ if (vwrq->value % 100000)
+ goto out;
memset(rates, 0, sizeof(rates));
- get_active_data_rates(adapter, rates);
- rate = rates;
- while (*rate) {
- lbs_deb_wext("rate=0x%X, wanted data_rate 0x%X\n", *rate,
- data_rate);
- if ((*rate & 0x7f) == (data_rate & 0x7f))
- break;
- rate++;
- }
- if (!*rate) {
- lbs_pr_alert("fixed data rate 0x%X out "
- "of range\n", data_rate);
- return -EINVAL;
+ copy_active_data_rates(adapter, rates);
+ new_rate = vwrq->value / 500000;
+ if (!memchr(rates, new_rate, sizeof(rates))) {
+ lbs_pr_alert("fixed data rate 0x%X out of range\n",
+ new_rate);
+ goto out;
}
- adapter->datarate = data_rate;
+ adapter->cur_rate = new_rate;
action = CMD_ACT_SET_TX_FIX_RATE;
- adapter->is_datarate_auto = 0;
+ adapter->auto_rate = 0;
}
ret = libertas_prepare_and_send_command(priv, CMD_802_11_DATA_RATE,
action, CMD_OPTION_WAITFORRSP, 0, NULL);
+out:
lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
return ret;
}
@@ -1174,14 +1086,19 @@ static int wlan_get_rate(struct net_device *dev, struct iw_request_info *info,
lbs_deb_enter(LBS_DEB_WEXT);
- if (adapter->is_datarate_auto) {
- vwrq->fixed = 0;
+ if (adapter->connect_status == LIBERTAS_CONNECTED) {
+ vwrq->value = adapter->cur_rate * 500000;
+
+ if (adapter->auto_rate)
+ vwrq->fixed = 0;
+ else
+ vwrq->fixed = 1;
+
} else {
- vwrq->fixed = 1;
+ vwrq->fixed = 0;
+ vwrq->value = 0;
}
- vwrq->value = adapter->datarate * 500000;
-
lbs_deb_leave(LBS_DEB_WEXT);
return 0;
}