Commit c3d41503 authored by David Kilroy's avatar David Kilroy Committed by John W. Linville

orinoco: implement set_wiphy_params

... to set fragmentation and RTS thresholds. Also report RTS retry
settings during wiphy init.

Note that the existing semantics for enabling microwave robustness are
preserved on firmwares that have it.
Signed-off-by: default avatarDavid Kilroy <kilroyd@googlemail.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 3393a608
...@@ -88,7 +88,9 @@ int orinoco_wiphy_register(struct wiphy *wiphy) ...@@ -88,7 +88,9 @@ int orinoco_wiphy_register(struct wiphy *wiphy)
wiphy->rts_threshold = priv->rts_thresh; wiphy->rts_threshold = priv->rts_thresh;
if (!priv->has_mwo) if (!priv->has_mwo)
wiphy->frag_threshold = priv->frag_thresh; wiphy->frag_threshold = priv->frag_thresh + 1;
wiphy->retry_short = priv->short_retry_limit;
wiphy->retry_long = priv->long_retry_limit;
return wiphy_register(wiphy); return wiphy_register(wiphy);
} }
...@@ -196,8 +198,92 @@ static int orinoco_set_channel(struct wiphy *wiphy, ...@@ -196,8 +198,92 @@ static int orinoco_set_channel(struct wiphy *wiphy,
return err; return err;
} }
static int orinoco_set_wiphy_params(struct wiphy *wiphy, u32 changed)
{
struct orinoco_private *priv = wiphy_priv(wiphy);
int frag_value = -1;
int rts_value = -1;
int err = 0;
if (changed & WIPHY_PARAM_RETRY_SHORT) {
/* Setting short retry not supported */
err = -EINVAL;
}
if (changed & WIPHY_PARAM_RETRY_LONG) {
/* Setting long retry not supported */
err = -EINVAL;
}
if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
/* Set fragmentation */
if (priv->has_mwo) {
if (wiphy->frag_threshold < 0)
frag_value = 0;
else {
printk(KERN_WARNING "%s: Fixed fragmentation "
"is not supported on this firmware. "
"Using MWO robust instead.\n",
priv->ndev->name);
frag_value = 1;
}
} else {
if (wiphy->frag_threshold < 0)
frag_value = 2346;
else if ((wiphy->frag_threshold < 257) ||
(wiphy->frag_threshold > 2347))
err = -EINVAL;
else
/* cfg80211 value is 257-2347 (odd only)
* orinoco rid has range 256-2346 (even only) */
frag_value = wiphy->frag_threshold & ~0x1;
}
}
if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
/* Set RTS.
*
* Prism documentation suggests default of 2432,
* and a range of 0-3000.
*
* Current implementation uses 2347 as the default and
* the upper limit.
*/
if (wiphy->rts_threshold < 0)
rts_value = 2347;
else if (wiphy->rts_threshold > 2347)
err = -EINVAL;
else
rts_value = wiphy->rts_threshold;
}
if (!err) {
unsigned long flags;
if (orinoco_lock(priv, &flags) != 0)
return -EBUSY;
if (frag_value >= 0) {
if (priv->has_mwo)
priv->mwo_robust = frag_value;
else
priv->frag_thresh = frag_value;
}
if (rts_value >= 0)
priv->rts_thresh = rts_value;
err = orinoco_commit(priv);
orinoco_unlock(priv, &flags);
}
return err;
}
const struct cfg80211_ops orinoco_cfg_ops = { const struct cfg80211_ops orinoco_cfg_ops = {
.change_virtual_intf = orinoco_change_vif, .change_virtual_intf = orinoco_change_vif,
.set_channel = orinoco_set_channel, .set_channel = orinoco_set_channel,
.scan = orinoco_scan, .scan = orinoco_scan,
.set_wiphy_params = orinoco_set_wiphy_params,
}; };
...@@ -374,6 +374,32 @@ int orinoco_hw_read_card_settings(struct orinoco_private *priv, u8 *dev_addr) ...@@ -374,6 +374,32 @@ int orinoco_hw_read_card_settings(struct orinoco_private *priv, u8 *dev_addr)
err = hermes_read_wordrec(hw, USER_BAP, err = hermes_read_wordrec(hw, USER_BAP,
HERMES_RID_CNFPREAMBLE_SYMBOL, HERMES_RID_CNFPREAMBLE_SYMBOL,
&priv->preamble); &priv->preamble);
if (err) {
dev_err(dev, "Failed to read preamble setup\n");
goto out;
}
}
/* Retry settings */
err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_SHORTRETRYLIMIT,
&priv->short_retry_limit);
if (err) {
dev_err(dev, "Failed to read short retry limit\n");
goto out;
}
err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_LONGRETRYLIMIT,
&priv->long_retry_limit);
if (err) {
dev_err(dev, "Failed to read long retry limit\n");
goto out;
}
err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_MAXTRANSMITLIFETIME,
&priv->retry_lifetime);
if (err) {
dev_err(dev, "Failed to read max retry lifetime\n");
goto out;
} }
out: out:
......
...@@ -131,6 +131,8 @@ struct orinoco_private { ...@@ -131,6 +131,8 @@ struct orinoco_private {
u16 ap_density, rts_thresh; u16 ap_density, rts_thresh;
u16 pm_on, pm_mcast, pm_period, pm_timeout; u16 pm_on, pm_mcast, pm_period, pm_timeout;
u16 preamble; u16 preamble;
u16 short_retry_limit, long_retry_limit;
u16 retry_lifetime;
#ifdef WIRELESS_SPY #ifdef WIRELESS_SPY
struct iw_spy_data spy_data; /* iwspy support */ struct iw_spy_data spy_data; /* iwspy support */
struct iw_public_data wireless_data; struct iw_public_data wireless_data;
......
...@@ -537,125 +537,6 @@ static int orinoco_ioctl_setsens(struct net_device *dev, ...@@ -537,125 +537,6 @@ static int orinoco_ioctl_setsens(struct net_device *dev,
return -EINPROGRESS; /* Call commit handler */ return -EINPROGRESS; /* Call commit handler */
} }
static int orinoco_ioctl_setrts(struct net_device *dev,
struct iw_request_info *info,
struct iw_param *rrq,
char *extra)
{
struct orinoco_private *priv = ndev_priv(dev);
int val = rrq->value;
unsigned long flags;
if (rrq->disabled)
val = 2347;
if ((val < 0) || (val > 2347))
return -EINVAL;
if (orinoco_lock(priv, &flags) != 0)
return -EBUSY;
priv->rts_thresh = val;
orinoco_unlock(priv, &flags);
return -EINPROGRESS; /* Call commit handler */
}
static int orinoco_ioctl_getrts(struct net_device *dev,
struct iw_request_info *info,
struct iw_param *rrq,
char *extra)
{
struct orinoco_private *priv = ndev_priv(dev);
rrq->value = priv->rts_thresh;
rrq->disabled = (rrq->value == 2347);
rrq->fixed = 1;
return 0;
}
static int orinoco_ioctl_setfrag(struct net_device *dev,
struct iw_request_info *info,
struct iw_param *frq,
char *extra)
{
struct orinoco_private *priv = ndev_priv(dev);
int err = -EINPROGRESS; /* Call commit handler */
unsigned long flags;
if (orinoco_lock(priv, &flags) != 0)
return -EBUSY;
if (priv->has_mwo) {
if (frq->disabled)
priv->mwo_robust = 0;
else {
if (frq->fixed)
printk(KERN_WARNING "%s: Fixed fragmentation "
"is not supported on this firmware. "
"Using MWO robust instead.\n",
dev->name);
priv->mwo_robust = 1;
}
} else {
if (frq->disabled)
priv->frag_thresh = 2346;
else {
if ((frq->value < 256) || (frq->value > 2346))
err = -EINVAL;
else
/* must be even */
priv->frag_thresh = frq->value & ~0x1;
}
}
orinoco_unlock(priv, &flags);
return err;
}
static int orinoco_ioctl_getfrag(struct net_device *dev,
struct iw_request_info *info,
struct iw_param *frq,
char *extra)
{
struct orinoco_private *priv = ndev_priv(dev);
hermes_t *hw = &priv->hw;
int err;
u16 val;
unsigned long flags;
if (orinoco_lock(priv, &flags) != 0)
return -EBUSY;
if (priv->has_mwo) {
err = hermes_read_wordrec(hw, USER_BAP,
HERMES_RID_CNFMWOROBUST_AGERE,
&val);
if (err)
val = 0;
frq->value = val ? 2347 : 0;
frq->disabled = !val;
frq->fixed = 0;
} else {
err = hermes_read_wordrec(hw, USER_BAP,
HERMES_RID_CNFFRAGMENTATIONTHRESHOLD,
&val);
if (err)
val = 0;
frq->value = val;
frq->disabled = (val >= 2346);
frq->fixed = 1;
}
orinoco_unlock(priv, &flags);
return err;
}
static int orinoco_ioctl_setrate(struct net_device *dev, static int orinoco_ioctl_setrate(struct net_device *dev,
struct iw_request_info *info, struct iw_request_info *info,
struct iw_param *rrq, struct iw_param *rrq,
...@@ -1200,60 +1081,6 @@ static int orinoco_ioctl_set_mlme(struct net_device *dev, ...@@ -1200,60 +1081,6 @@ static int orinoco_ioctl_set_mlme(struct net_device *dev,
return ret; return ret;
} }
static int orinoco_ioctl_getretry(struct net_device *dev,
struct iw_request_info *info,
struct iw_param *rrq,
char *extra)
{
struct orinoco_private *priv = ndev_priv(dev);
hermes_t *hw = &priv->hw;
int err = 0;
u16 short_limit, long_limit, lifetime;
unsigned long flags;
if (orinoco_lock(priv, &flags) != 0)
return -EBUSY;
err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_SHORTRETRYLIMIT,
&short_limit);
if (err)
goto out;
err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_LONGRETRYLIMIT,
&long_limit);
if (err)
goto out;
err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_MAXTRANSMITLIFETIME,
&lifetime);
if (err)
goto out;
rrq->disabled = 0; /* Can't be disabled */
/* Note : by default, display the retry number */
if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
rrq->flags = IW_RETRY_LIFETIME;
rrq->value = lifetime * 1000; /* ??? */
} else {
/* By default, display the min number */
if ((rrq->flags & IW_RETRY_LONG)) {
rrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
rrq->value = long_limit;
} else {
rrq->flags = IW_RETRY_LIMIT;
rrq->value = short_limit;
if (short_limit != long_limit)
rrq->flags |= IW_RETRY_SHORT;
}
}
out:
orinoco_unlock(priv, &flags);
return err;
}
static int orinoco_ioctl_reset(struct net_device *dev, static int orinoco_ioctl_reset(struct net_device *dev,
struct iw_request_info *info, struct iw_request_info *info,
void *wrqu, void *wrqu,
...@@ -1527,11 +1354,11 @@ static const iw_handler orinoco_handler[] = { ...@@ -1527,11 +1354,11 @@ static const iw_handler orinoco_handler[] = {
IW_HANDLER(SIOCGIWESSID, (iw_handler)orinoco_ioctl_getessid), IW_HANDLER(SIOCGIWESSID, (iw_handler)orinoco_ioctl_getessid),
IW_HANDLER(SIOCSIWRATE, (iw_handler)orinoco_ioctl_setrate), IW_HANDLER(SIOCSIWRATE, (iw_handler)orinoco_ioctl_setrate),
IW_HANDLER(SIOCGIWRATE, (iw_handler)orinoco_ioctl_getrate), IW_HANDLER(SIOCGIWRATE, (iw_handler)orinoco_ioctl_getrate),
IW_HANDLER(SIOCSIWRTS, (iw_handler)orinoco_ioctl_setrts), IW_HANDLER(SIOCSIWRTS, (iw_handler)cfg80211_wext_siwrts),
IW_HANDLER(SIOCGIWRTS, (iw_handler)orinoco_ioctl_getrts), IW_HANDLER(SIOCGIWRTS, (iw_handler)cfg80211_wext_giwrts),
IW_HANDLER(SIOCSIWFRAG, (iw_handler)orinoco_ioctl_setfrag), IW_HANDLER(SIOCSIWFRAG, (iw_handler)cfg80211_wext_siwfrag),
IW_HANDLER(SIOCGIWFRAG, (iw_handler)orinoco_ioctl_getfrag), IW_HANDLER(SIOCGIWFRAG, (iw_handler)cfg80211_wext_giwfrag),
IW_HANDLER(SIOCGIWRETRY, (iw_handler)orinoco_ioctl_getretry), IW_HANDLER(SIOCGIWRETRY, (iw_handler)cfg80211_wext_giwretry),
IW_HANDLER(SIOCSIWENCODE, (iw_handler)orinoco_ioctl_setiwencode), IW_HANDLER(SIOCSIWENCODE, (iw_handler)orinoco_ioctl_setiwencode),
IW_HANDLER(SIOCGIWENCODE, (iw_handler)orinoco_ioctl_getiwencode), IW_HANDLER(SIOCGIWENCODE, (iw_handler)orinoco_ioctl_getiwencode),
IW_HANDLER(SIOCSIWPOWER, (iw_handler)orinoco_ioctl_setpower), IW_HANDLER(SIOCSIWPOWER, (iw_handler)orinoco_ioctl_setpower),
......
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