Commit 85319f93 authored by Javier Cardona's avatar Javier Cardona Committed by John W. Linville

libertas: rate adaptation configuration via iwconfig.

Implemented rate adaptation support via 'iwconfig rate' API.  It is now
possible to specify a bit-rate value and append 'auto'.  That will configure
rate adaptation to use all bit-rates equal or lower than than selected value.

Made lbs_cmd_802_11_rate_adapt_rateset a direct command.
Signed-off-by: default avatarJavier Cardona <javier@cozybit.com>
Signed-off-by: default avatarDavid Woodhouse <dwmw2@infradead.org>
Acked-by: default avatarDan Williams <dcbw@redhat.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 553381c4
...@@ -1250,7 +1250,7 @@ static int get_common_rates(struct lbs_private *priv, ...@@ -1250,7 +1250,7 @@ static int get_common_rates(struct lbs_private *priv,
lbs_deb_hex(LBS_DEB_JOIN, "common rates", tmp, tmp_size); lbs_deb_hex(LBS_DEB_JOIN, "common rates", tmp, tmp_size);
lbs_deb_join("TX data rate 0x%02x\n", priv->cur_rate); lbs_deb_join("TX data rate 0x%02x\n", priv->cur_rate);
if (!priv->auto_rate) { if (!priv->enablehwauto) {
for (i = 0; i < tmp_size; i++) { for (i = 0; i < tmp_size; i++) {
if (tmp[i] == priv->cur_rate) if (tmp[i] == priv->cur_rate)
goto done; goto done;
......
...@@ -676,26 +676,60 @@ static int lbs_cmd_802_11_monitor_mode(struct cmd_ds_command *cmd, ...@@ -676,26 +676,60 @@ static int lbs_cmd_802_11_monitor_mode(struct cmd_ds_command *cmd,
return 0; return 0;
} }
static int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv, static __le16 lbs_rate_to_fw_bitmap(int rate, int lower_rates_ok)
struct cmd_ds_command *cmd,
u16 cmd_action)
{ {
struct cmd_ds_802_11_rate_adapt_rateset /* Bit Rate
*rateadapt = &cmd->params.rateset; * 15:13 Reserved
* 12 54 Mbps
* 11 48 Mbps
* 10 36 Mbps
* 9 24 Mbps
* 8 18 Mbps
* 7 12 Mbps
* 6 9 Mbps
* 5 6 Mbps
* 4 Reserved
* 3 11 Mbps
* 2 5.5 Mbps
* 1 2 Mbps
* 0 1 Mbps
**/
uint16_t ratemask;
int i = lbs_data_rate_to_fw_index(rate);
if (lower_rates_ok)
ratemask = (0x1fef >> (12 - i));
else
ratemask = (1 << i);
return cpu_to_le16(ratemask);
}
int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv,
uint16_t cmd_action)
{
struct cmd_ds_802_11_rate_adapt_rateset cmd;
int ret;
lbs_deb_enter(LBS_DEB_CMD); lbs_deb_enter(LBS_DEB_CMD);
cmd->size =
cpu_to_le16(sizeof(struct cmd_ds_802_11_rate_adapt_rateset)
+ S_DS_GEN);
cmd->command = cpu_to_le16(CMD_802_11_RATE_ADAPT_RATESET);
rateadapt->action = cpu_to_le16(cmd_action); if (!priv->cur_rate && !priv->enablehwauto)
rateadapt->enablehwauto = cpu_to_le16(priv->enablehwauto); return -EINVAL;
rateadapt->bitmap = cpu_to_le16(priv->ratebitmap);
lbs_deb_leave(LBS_DEB_CMD); cmd.hdr.size = cpu_to_le16(sizeof(cmd));
return 0;
cmd.action = cpu_to_le16(cmd_action);
cmd.enablehwauto = cpu_to_le16(priv->enablehwauto);
cmd.bitmap = lbs_rate_to_fw_bitmap(priv->cur_rate, priv->enablehwauto);
ret = lbs_cmd_with_response(priv, CMD_802_11_RATE_ADAPT_RATESET, &cmd);
if (!ret && cmd_action == CMD_ACT_GET) {
priv->ratebitmap = le16_to_cpu(cmd.bitmap);
priv->enablehwauto = le16_to_cpu(cmd.enablehwauto);
}
lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
return ret;
} }
EXPORT_SYMBOL_GPL(lbs_cmd_802_11_rate_adapt_rateset);
/** /**
* @brief Set the data rate * @brief Set the data rate
...@@ -1378,11 +1412,6 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, ...@@ -1378,11 +1412,6 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
cmd_action, pdata_buf); cmd_action, pdata_buf);
break; break;
case CMD_802_11_RATE_ADAPT_RATESET:
ret = lbs_cmd_802_11_rate_adapt_rateset(priv,
cmdptr, cmd_action);
break;
case CMD_802_11_MONITOR_MODE: case CMD_802_11_MONITOR_MODE:
ret = lbs_cmd_802_11_monitor_mode(cmdptr, ret = lbs_cmd_802_11_monitor_mode(cmdptr,
cmd_action, pdata_buf); cmd_action, pdata_buf);
......
...@@ -48,6 +48,8 @@ int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria); ...@@ -48,6 +48,8 @@ int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria);
int lbs_suspend(struct lbs_private *priv); int lbs_suspend(struct lbs_private *priv);
void lbs_resume(struct lbs_private *priv); void lbs_resume(struct lbs_private *priv);
int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv,
uint16_t cmd_action);
int lbs_cmd_802_11_inactivity_timeout(struct lbs_private *priv, int lbs_cmd_802_11_inactivity_timeout(struct lbs_private *priv,
uint16_t cmd_action, uint16_t *timeout); uint16_t cmd_action, uint16_t *timeout);
int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action, int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action,
......
...@@ -203,22 +203,6 @@ static int lbs_ret_802_11_rf_tx_power(struct lbs_private *priv, ...@@ -203,22 +203,6 @@ static int lbs_ret_802_11_rf_tx_power(struct lbs_private *priv,
return 0; return 0;
} }
static int lbs_ret_802_11_rate_adapt_rateset(struct lbs_private *priv,
struct cmd_ds_command *resp)
{
struct cmd_ds_802_11_rate_adapt_rateset *rates = &resp->params.rateset;
lbs_deb_enter(LBS_DEB_CMD);
if (rates->action == CMD_ACT_GET) {
priv->enablehwauto = le16_to_cpu(rates->enablehwauto);
priv->ratebitmap = le16_to_cpu(rates->bitmap);
}
lbs_deb_leave(LBS_DEB_CMD);
return 0;
}
static int lbs_ret_802_11_rssi(struct lbs_private *priv, static int lbs_ret_802_11_rssi(struct lbs_private *priv,
struct cmd_ds_command *resp) struct cmd_ds_command *resp)
{ {
...@@ -321,10 +305,6 @@ static inline int handle_cmd_response(struct lbs_private *priv, ...@@ -321,10 +305,6 @@ static inline int handle_cmd_response(struct lbs_private *priv,
case CMD_RET(CMD_802_11_BEACON_STOP): case CMD_RET(CMD_802_11_BEACON_STOP):
break; break;
case CMD_RET(CMD_802_11_RATE_ADAPT_RATESET):
ret = lbs_ret_802_11_rate_adapt_rateset(priv, resp);
break;
case CMD_RET(CMD_802_11_RSSI): case CMD_RET(CMD_802_11_RSSI):
ret = lbs_ret_802_11_rssi(priv, resp); ret = lbs_ret_802_11_rssi(priv, resp);
break; break;
......
...@@ -237,8 +237,8 @@ struct lbs_private { ...@@ -237,8 +237,8 @@ struct lbs_private {
/** 802.11 statistics */ /** 802.11 statistics */
// struct cmd_DS_802_11_GET_STAT wlan802_11Stat; // struct cmd_DS_802_11_GET_STAT wlan802_11Stat;
u16 enablehwauto; uint16_t enablehwauto;
u16 ratebitmap; uint16_t ratebitmap;
u32 fragthsd; u32 fragthsd;
u32 rtsthsd; u32 rtsthsd;
...@@ -296,7 +296,6 @@ struct lbs_private { ...@@ -296,7 +296,6 @@ struct lbs_private {
/** data rate stuff */ /** data rate stuff */
u8 cur_rate; u8 cur_rate;
u8 auto_rate;
/** RF calibration data */ /** RF calibration data */
......
...@@ -500,6 +500,7 @@ struct cmd_ds_802_11_data_rate { ...@@ -500,6 +500,7 @@ struct cmd_ds_802_11_data_rate {
}; };
struct cmd_ds_802_11_rate_adapt_rateset { struct cmd_ds_802_11_rate_adapt_rateset {
struct cmd_header hdr;
__le16 action; __le16 action;
__le16 enablehwauto; __le16 enablehwauto;
__le16 bitmap; __le16 bitmap;
...@@ -703,7 +704,6 @@ struct cmd_ds_command { ...@@ -703,7 +704,6 @@ struct cmd_ds_command {
struct cmd_ds_802_11_rf_tx_power txp; struct cmd_ds_802_11_rf_tx_power txp;
struct cmd_ds_802_11_rf_antenna rant; struct cmd_ds_802_11_rf_antenna rant;
struct cmd_ds_802_11_monitor_mode monitor; struct cmd_ds_802_11_monitor_mode monitor;
struct cmd_ds_802_11_rate_adapt_rateset rateset;
struct cmd_ds_802_11_ad_hoc_join adj; struct cmd_ds_802_11_ad_hoc_join adj;
struct cmd_ds_802_11_rssi rssi; struct cmd_ds_802_11_rssi rssi;
struct cmd_ds_802_11_rssi_rsp rssirsp; struct cmd_ds_802_11_rssi_rsp rssirsp;
......
...@@ -1044,7 +1044,7 @@ static int lbs_init_adapter(struct lbs_private *priv) ...@@ -1044,7 +1044,7 @@ static int lbs_init_adapter(struct lbs_private *priv)
priv->curbssparams.channel = DEFAULT_AD_HOC_CHANNEL; priv->curbssparams.channel = DEFAULT_AD_HOC_CHANNEL;
priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON; priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON;
priv->radioon = RADIO_ON; priv->radioon = RADIO_ON;
priv->auto_rate = 1; priv->enablehwauto = 1;
priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE; priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE;
priv->psmode = LBS802_11POWERMODECAM; priv->psmode = LBS802_11POWERMODECAM;
priv->psstate = PS_STATE_FULL_POWER; priv->psstate = PS_STATE_FULL_POWER;
......
...@@ -237,7 +237,7 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) ...@@ -237,7 +237,7 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb)
/* Take the data rate from the rxpd structure /* Take the data rate from the rxpd structure
* only if the rate is auto * only if the rate is auto
*/ */
if (priv->auto_rate) if (priv->enablehwauto)
priv->cur_rate = lbs_fw_index_to_data_rate(p_rx_pd->rx_rate); priv->cur_rate = lbs_fw_index_to_data_rate(p_rx_pd->rx_rate);
lbs_compute_rssi(priv, p_rx_pd); lbs_compute_rssi(priv, p_rx_pd);
...@@ -383,7 +383,7 @@ static int process_rxed_802_11_packet(struct lbs_private *priv, ...@@ -383,7 +383,7 @@ static int process_rxed_802_11_packet(struct lbs_private *priv,
/* Take the data rate from the rxpd structure /* Take the data rate from the rxpd structure
* only if the rate is auto * only if the rate is auto
*/ */
if (priv->auto_rate) if (priv->enablehwauto)
priv->cur_rate = lbs_fw_index_to_data_rate(prxpd->rx_rate); priv->cur_rate = lbs_fw_index_to_data_rate(prxpd->rx_rate);
lbs_compute_rssi(priv, prxpd); lbs_compute_rssi(priv, prxpd);
......
...@@ -1021,28 +1021,37 @@ static int lbs_set_rate(struct net_device *dev, struct iw_request_info *info, ...@@ -1021,28 +1021,37 @@ static int lbs_set_rate(struct net_device *dev, struct iw_request_info *info,
lbs_deb_enter(LBS_DEB_WEXT); lbs_deb_enter(LBS_DEB_WEXT);
lbs_deb_wext("vwrq->value %d\n", vwrq->value); lbs_deb_wext("vwrq->value %d\n", vwrq->value);
lbs_deb_wext("vwrq->fixed %d\n", vwrq->fixed);
if (vwrq->fixed && vwrq->value == -1)
goto out;
/* Auto rate? */ /* Auto rate? */
if (vwrq->value == -1) { priv->enablehwauto = !vwrq->fixed;
priv->auto_rate = 1;
if (vwrq->value == -1)
priv->cur_rate = 0; priv->cur_rate = 0;
} else { else {
if (vwrq->value % 100000) if (vwrq->value % 100000)
goto out; goto out;
new_rate = vwrq->value / 500000;
priv->cur_rate = new_rate;
/* the rest is only needed for lbs_set_data_rate() */
memset(rates, 0, sizeof(rates)); memset(rates, 0, sizeof(rates));
copy_active_data_rates(priv, rates); copy_active_data_rates(priv, rates);
new_rate = vwrq->value / 500000;
if (!memchr(rates, new_rate, sizeof(rates))) { if (!memchr(rates, new_rate, sizeof(rates))) {
lbs_pr_alert("fixed data rate 0x%X out of range\n", lbs_pr_alert("fixed data rate 0x%X out of range\n",
new_rate); new_rate);
goto out; goto out;
} }
priv->cur_rate = new_rate;
priv->auto_rate = 0;
} }
/* Try the newer command first (Firmware Spec 5.1 and above) */
ret = lbs_cmd_802_11_rate_adapt_rateset(priv, CMD_ACT_SET);
/* Fallback to older version */
if (ret)
ret = lbs_set_data_rate(priv, new_rate); ret = lbs_set_data_rate(priv, new_rate);
out: out:
...@@ -1060,7 +1069,7 @@ static int lbs_get_rate(struct net_device *dev, struct iw_request_info *info, ...@@ -1060,7 +1069,7 @@ static int lbs_get_rate(struct net_device *dev, struct iw_request_info *info,
if (priv->connect_status == LBS_CONNECTED) { if (priv->connect_status == LBS_CONNECTED) {
vwrq->value = priv->cur_rate * 500000; vwrq->value = priv->cur_rate * 500000;
if (priv->auto_rate) if (priv->enablehwauto)
vwrq->fixed = 0; vwrq->fixed = 0;
else else
vwrq->fixed = 1; vwrq->fixed = 1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment