Skip to content

Commit

Permalink
rt2x00: Rate structure overhaul
Browse files Browse the repository at this point in the history
Recent changes to the rate structure registration broke rt2x00,
the hw_value was reduced from 32bits to 16bits while rt2x00 used
the full 32bits. However the way rt2x00 used the value was inflexible
and needed to be changed anyway.

This patch creates a array containing information for each rate,
the hw_value passed to mac80211 is the index value for that array
including a field to indicate if short preamble should be enabled.

Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Ivo van Doorn authored and John W. Linville committed Feb 29, 2008
1 parent e71c9fa commit 70e2fed
Show file tree
Hide file tree
Showing 4 changed files with 153 additions and 140 deletions.
4 changes: 1 addition & 3 deletions drivers/net/wireless/rt2x00/rt2x00config.c
Original file line number Diff line number Diff line change
Expand Up @@ -246,9 +246,7 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,

band = &rt2x00dev->bands[conf->channel->band];
rate = &band->bitrates[band->n_bitrates - 1];

libconf.basic_rates =
DEVICE_GET_RATE_FIELD(rate->hw_value, RATEMASK) & DEV_BASIC_RATEMASK;
libconf.basic_rates = rt2x00_get_rate(rate->hw_value)->ratemask;
}

if (flags & CONFIG_UPDATE_CHANNEL) {
Expand Down
173 changes: 107 additions & 66 deletions drivers/net/wireless/rt2x00/rt2x00dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -551,30 +551,26 @@ void rt2x00lib_rxdone(struct queue_entry *entry,
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status;
struct ieee80211_supported_band *sband;
struct ieee80211_rate *rate;
struct ieee80211_hdr *hdr;
const struct rt2x00_rate *rate;
unsigned int i;
int val = 0, idx = -1;
int idx = -1;
u16 fc;

/*
* Update RX statistics.
*/
sband = &rt2x00dev->bands[rt2x00dev->curr_band];
for (i = 0; i < sband->n_bitrates; i++) {
rate = &sband->bitrates[i];
rate = rt2x00_get_rate(sband->bitrates[i].hw_value);

/*
* When frame was received with an OFDM bitrate,
* the signal is the PLCP value. If it was received with
* a CCK bitrate the signal is the rate in 0.5kbit/s.
* a CCK bitrate the signal is the rate in 100kbit/s.
*/
if (!rxdesc->ofdm)
val = DEVICE_GET_RATE_FIELD(rate->hw_value, RATE);
else
val = DEVICE_GET_RATE_FIELD(rate->hw_value, PLCP);

if (val == rxdesc->signal) {
if ((rxdesc->ofdm && rate->plcp == rxdesc->signal) ||
(!rxdesc->ofdm && rate->bitrate == rxdesc->signal)) {
idx = i;
break;
}
Expand All @@ -583,7 +579,7 @@ void rt2x00lib_rxdone(struct queue_entry *entry,
/*
* Only update link status if this is a beacon frame carrying our bssid.
*/
hdr = (struct ieee80211_hdr*)entry->skb->data;
hdr = (struct ieee80211_hdr *)entry->skb->data;
fc = le16_to_cpu(hdr->frame_control);
if (is_beacon(fc) && rxdesc->my_bss)
rt2x00lib_update_link_stats(&rt2x00dev->link, rxdesc->rssi);
Expand Down Expand Up @@ -617,9 +613,9 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev,
{
struct txentry_desc txdesc;
struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
const struct rt2x00_rate *rate;
int tx_rate;
int bitrate;
int length;
int duration;
int residual;
Expand All @@ -636,8 +632,8 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev,
/*
* Read required fields from ieee80211 header.
*/
frame_control = le16_to_cpu(ieee80211hdr->frame_control);
seq_ctrl = le16_to_cpu(ieee80211hdr->seq_ctrl);
frame_control = le16_to_cpu(hdr->frame_control);
seq_ctrl = le16_to_cpu(hdr->seq_ctrl);

tx_rate = control->tx_rate->hw_value;

Expand All @@ -661,16 +657,12 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev,
tx_rate = control->rts_cts_rate->hw_value;
}

/*
* Check for OFDM
*/
if (DEVICE_GET_RATE_FIELD(tx_rate, RATEMASK) & DEV_OFDM_RATEMASK)
__set_bit(ENTRY_TXD_OFDM_RATE, &txdesc.flags);
rate = rt2x00_get_rate(tx_rate);

/*
* Check if more fragments are pending
*/
if (ieee80211_get_morefrag(ieee80211hdr)) {
if (ieee80211_get_morefrag(hdr)) {
__set_bit(ENTRY_TXD_BURST, &txdesc.flags);
__set_bit(ENTRY_TXD_MORE_FRAG, &txdesc.flags);
}
Expand Down Expand Up @@ -698,29 +690,29 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev,
* PLCP setup
* Length calculation depends on OFDM/CCK rate.
*/
txdesc.signal = DEVICE_GET_RATE_FIELD(tx_rate, PLCP);
txdesc.signal = rate->plcp;
txdesc.service = 0x04;

length = skb->len + FCS_LEN;
if (test_bit(ENTRY_TXD_OFDM_RATE, &txdesc.flags)) {
if (rate->flags & DEV_RATE_OFDM) {
__set_bit(ENTRY_TXD_OFDM_RATE, &txdesc.flags);

txdesc.length_high = (length >> 6) & 0x3f;
txdesc.length_low = length & 0x3f;
} else {
bitrate = DEVICE_GET_RATE_FIELD(tx_rate, RATE);

/*
* Convert length to microseconds.
*/
residual = get_duration_res(length, bitrate);
duration = get_duration(length, bitrate);
residual = get_duration_res(length, rate->bitrate);
duration = get_duration(length, rate->bitrate);

if (residual != 0) {
duration++;

/*
* Check if we need to set the Length Extension
*/
if (bitrate == 110 && residual <= 30)
if (rate->bitrate == 110 && residual <= 30)
txdesc.service |= 0x80;
}

Expand All @@ -731,7 +723,7 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev,
* When preamble is enabled we should set the
* preamble bit for the signal.
*/
if (DEVICE_GET_RATE_FIELD(tx_rate, PREAMBLE))
if (rt2x00_get_rate_preamble(tx_rate))
txdesc.signal |= 0x08;
}

Expand All @@ -756,6 +748,81 @@ EXPORT_SYMBOL_GPL(rt2x00lib_write_tx_desc);
/*
* Driver initialization handlers.
*/
const struct rt2x00_rate rt2x00_supported_rates[12] = {
{
.flags = 0,
.bitrate = 10,
.ratemask = DEV_RATEMASK_1MB,
.plcp = 0x00,
},
{
.flags = DEV_RATE_SHORT_PREAMBLE,
.bitrate = 20,
.ratemask = DEV_RATEMASK_2MB,
.plcp = 0x01,
},
{
.flags = DEV_RATE_SHORT_PREAMBLE,
.bitrate = 55,
.ratemask = DEV_RATEMASK_5_5MB,
.plcp = 0x02,
},
{
.flags = DEV_RATE_SHORT_PREAMBLE,
.bitrate = 110,
.ratemask = DEV_RATEMASK_11MB,
.plcp = 0x03,
},
{
.flags = DEV_RATE_OFDM,
.bitrate = 60,
.ratemask = DEV_RATEMASK_6MB,
.plcp = 0x0b,
},
{
.flags = DEV_RATE_OFDM,
.bitrate = 90,
.ratemask = DEV_RATEMASK_9MB,
.plcp = 0x0f,
},
{
.flags = DEV_RATE_OFDM,
.bitrate = 120,
.ratemask = DEV_RATEMASK_12MB,
.plcp = 0x0a,
},
{
.flags = DEV_RATE_OFDM,
.bitrate = 180,
.ratemask = DEV_RATEMASK_18MB,
.plcp = 0x0e,
},
{
.flags = DEV_RATE_OFDM,
.bitrate = 240,
.ratemask = DEV_RATEMASK_24MB,
.plcp = 0x09,
},
{
.flags = DEV_RATE_OFDM,
.bitrate = 360,
.ratemask = DEV_RATEMASK_36MB,
.plcp = 0x0d,
},
{
.flags = DEV_RATE_OFDM,
.bitrate = 480,
.ratemask = DEV_RATEMASK_48MB,
.plcp = 0x08,
},
{
.flags = DEV_RATE_OFDM,
.bitrate = 540,
.ratemask = DEV_RATEMASK_54MB,
.plcp = 0x0c,
},
};

static void rt2x00lib_channel(struct ieee80211_channel *entry,
const int channel, const int tx_power,
const int value)
Expand All @@ -770,18 +837,17 @@ static void rt2x00lib_channel(struct ieee80211_channel *entry,
}

static void rt2x00lib_rate(struct ieee80211_rate *entry,
const int rate, const int mask,
const int plcp, const int flags)
const u16 index, const struct rt2x00_rate *rate)
{
entry->bitrate = rate;
entry->hw_value =
DEVICE_SET_RATE_FIELD(rate, RATE) |
DEVICE_SET_RATE_FIELD(mask, RATEMASK) |
DEVICE_SET_RATE_FIELD(plcp, PLCP);
entry->flags = flags;
entry->flags = 0;
entry->bitrate = rate->bitrate;
entry->hw_value = rt2x00_create_rate_hw_value(index, 0);
entry->hw_value_short = entry->hw_value;
if (entry->flags & IEEE80211_RATE_SHORT_PREAMBLE)
entry->hw_value_short |= DEVICE_SET_RATE_FIELD(1, PREAMBLE);

if (rate->flags & DEV_RATE_SHORT_PREAMBLE) {
entry->flags |= IEEE80211_RATE_SHORT_PREAMBLE;
entry->hw_value_short |= rt2x00_create_rate_hw_value(index, 1);
}
}

static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev,
Expand All @@ -807,33 +873,8 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev,
/*
* Initialize Rate list.
*/
rt2x00lib_rate(&rates[0], 10, DEV_RATEMASK_1MB,
0x00, 0);
rt2x00lib_rate(&rates[1], 20, DEV_RATEMASK_2MB,
0x01, IEEE80211_RATE_SHORT_PREAMBLE);
rt2x00lib_rate(&rates[2], 55, DEV_RATEMASK_5_5MB,
0x02, IEEE80211_RATE_SHORT_PREAMBLE);
rt2x00lib_rate(&rates[3], 110, DEV_RATEMASK_11MB,
0x03, IEEE80211_RATE_SHORT_PREAMBLE);

if (spec->num_rates > 4) {
rt2x00lib_rate(&rates[4], 60, DEV_RATEMASK_6MB,
0x0b, 0);
rt2x00lib_rate(&rates[5], 90, DEV_RATEMASK_9MB,
0x0f, 0);
rt2x00lib_rate(&rates[6], 120, DEV_RATEMASK_12MB,
0x0a, 0);
rt2x00lib_rate(&rates[7], 180, DEV_RATEMASK_18MB,
0x0e, 0);
rt2x00lib_rate(&rates[8], 240, DEV_RATEMASK_24MB,
0x09, 0);
rt2x00lib_rate(&rates[9], 360, DEV_RATEMASK_36MB,
0x0d, 0);
rt2x00lib_rate(&rates[10], 480, DEV_RATEMASK_48MB,
0x08, 0);
rt2x00lib_rate(&rates[11], 540, DEV_RATEMASK_54MB,
0x0c, 0);
}
for (i = 0; i < spec->num_rates; i++)
rt2x00lib_rate(&rates[0], i, rt2x00_get_rate(i));

/*
* Initialize Channel list.
Expand Down
45 changes: 45 additions & 0 deletions drivers/net/wireless/rt2x00/rt2x00lib.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,51 @@
#define LINK_TUNE_INTERVAL ( round_jiffies_relative(HZ) )
#define RFKILL_POLL_INTERVAL ( 1000 )

/*
* rt2x00_rate: Per rate device information
*/
struct rt2x00_rate {
unsigned short flags;
#define DEV_RATE_OFDM 0x0001
#define DEV_RATE_SHORT_PREAMBLE 0x0002

unsigned short bitrate; /* In 100kbit/s */

unsigned short ratemask;
#define DEV_RATEMASK_1MB ( (1 << 1) - 1 )
#define DEV_RATEMASK_2MB ( (1 << 2) - 1 )
#define DEV_RATEMASK_5_5MB ( (1 << 3) - 1 )
#define DEV_RATEMASK_11MB ( (1 << 4) - 1 )
#define DEV_RATEMASK_6MB ( (1 << 5) - 1 )
#define DEV_RATEMASK_9MB ( (1 << 6) - 1 )
#define DEV_RATEMASK_12MB ( (1 << 7) - 1 )
#define DEV_RATEMASK_18MB ( (1 << 8) - 1 )
#define DEV_RATEMASK_24MB ( (1 << 9) - 1 )
#define DEV_RATEMASK_36MB ( (1 << 10) - 1 )
#define DEV_RATEMASK_48MB ( (1 << 11) - 1 )
#define DEV_RATEMASK_54MB ( (1 << 12) - 1 )

unsigned short plcp;
};

extern const struct rt2x00_rate rt2x00_supported_rates[12];

static inline u16 rt2x00_create_rate_hw_value(const u16 index,
const u16 short_preamble)
{
return (short_preamble << 8) | (index & 0xff);
}

static inline const struct rt2x00_rate *rt2x00_get_rate(const u16 hw_value)
{
return &rt2x00_supported_rates[hw_value & 0xff];
}

static inline int rt2x00_get_rate_preamble(const u16 hw_value)
{
return (hw_value & 0xff00);
}

/*
* Radio control handlers.
*/
Expand Down
Loading

0 comments on commit 70e2fed

Please sign in to comment.