Skip to content

Commit

Permalink
[802.11] Enhance support for driver PHY differences
Browse files Browse the repository at this point in the history
The prior net80211 model of physical-layer behavior for drivers was
overly simplistic and limited the drivers that could be written.  To
be more flexible, split the driver-provided list of supported rates by
band, and add a means for specifying a list of supported channels.
Allow drivers to specify a hardware channel value that will be tied to
uses of the channel.

Expose net80211_duration() to drivers, and make the rate it uses in
its computations configurable, so that it can be used in calculating
durations that must be set in hardware for ACK and CTS packets. Add
net80211_cts_duration() for the common case of calculating the
duration for a CTS packet.

Signed-off-by: Michael Brown <mcb30@etherboot.org>
  • Loading branch information
rwcr authored and Michael Brown committed Aug 8, 2009
1 parent e6e3061 commit f128a6d
Show file tree
Hide file tree
Showing 3 changed files with 147 additions and 44 deletions.
56 changes: 32 additions & 24 deletions src/drivers/net/rtl818x/rtl818x.c
Expand Up @@ -186,13 +186,16 @@ static int rtl818x_tx(struct net80211_device *dev, struct io_buffer *iob)
plcp_len |= 1 << 15;
}

entry = &priv->tx_ring[priv->tx_prod];

if (dev->phy_flags & NET80211_PHY_USE_PROTECTION) {
tx_flags |= RTL818X_TX_DESC_FLAG_CTS;
tx_flags |= priv->hw_rtscts_rate << 19;
entry->rts_duration = net80211_cts_duration(dev, len);
} else {
entry->rts_duration = 0;
}

entry = &priv->tx_ring[priv->tx_prod];

if (entry->flags & RTL818X_TX_DESC_FLAG_OWN) {
/* card hasn't processed the old packet yet! */
return -EBUSY;
Expand All @@ -201,7 +204,6 @@ static int rtl818x_tx(struct net80211_device *dev, struct io_buffer *iob)
priv->tx_buf[priv->tx_prod] = iob;
priv->tx_prod = (priv->tx_prod + 1) % RTL818X_TX_RING_SIZE;

entry->rts_duration = 0;
entry->plcp_len = cpu_to_le16(plcp_len);
entry->tx_buf = cpu_to_le32(virt_to_bus(iob->data));
entry->frame_len = cpu_to_le32(len);
Expand Down Expand Up @@ -626,20 +628,7 @@ static struct bit_basher_operations rtl818x_basher_ops = {
.write = rtl818x_spi_write_bit,
};

/* The net80211 code makes a copy of this, so we're OK modifying the
static version as we initialize the card, as long as we don't
depend on possibly-modified values in case there are multiple cards. */
static struct net80211_hw_info rtl818x_hwinfo = {
/* MAC address filled in at runtime */
/* modes filled in at runtime */
.bands = NET80211_BAND_2GHZ,
.flags = NET80211_HW_RX_HAS_FCS,
.signal_type = NET80211_SIGNAL_ARBITRARY,
/* supported rates filled in at runtime */
.signal_max = 65,
.channel_change_time = 1000, /* no idea what the actual value is */
};

#if DBGLVL_MAX
static const char *rtl818x_rf_names[] = {
NULL, /* no 0 */
"Intersil", "RFMD", /* unsupported 1-2 */
Expand All @@ -649,6 +638,7 @@ static const char *rtl818x_rf_names[] = {
"RTL8255", /* unsupported 10 */
};
#define RTL818X_NR_RF_NAMES 11
#endif

struct net80211_device_operations rtl818x_operations = {
.open = rtl818x_start,
Expand All @@ -669,6 +659,13 @@ static int rtl818x_probe(struct pci_device *pdev,
const char *chip_name;
u32 reg;
u16 eeprom_val;
struct net80211_hw_info *hwinfo;

hwinfo = zalloc(sizeof(*hwinfo));
if (!hwinfo) {
DBG("rtl818x: hwinfo alloc failed\n");
return -ENOMEM;
}

adjust_pci_device(pdev);

Expand Down Expand Up @@ -715,15 +712,21 @@ static int rtl818x_probe(struct pci_device *pdev,

priv->r8185 = reg & RTL818X_TX_CONF_R8185_ABC;

memcpy(rtl818x_hwinfo.supported_rates, rtl818x_rates,
hwinfo->bands = NET80211_BAND_BIT_2GHZ;
hwinfo->flags = NET80211_HW_RX_HAS_FCS;
hwinfo->signal_type = NET80211_SIGNAL_ARBITRARY;
hwinfo->signal_max = 65;
hwinfo->channel_change_time = 1000;

memcpy(hwinfo->rates[NET80211_BAND_2GHZ], rtl818x_rates,
sizeof(*rtl818x_rates) * RTL818X_NR_RATES);

if (priv->r8185) {
rtl818x_hwinfo.modes = NET80211_MODE_B | NET80211_MODE_G;
rtl818x_hwinfo.nr_supported_rates = RTL818X_NR_RATES;
hwinfo->modes = NET80211_MODE_B | NET80211_MODE_G;
hwinfo->nr_rates[NET80211_BAND_2GHZ] = RTL818X_NR_RATES;
} else {
rtl818x_hwinfo.modes = NET80211_MODE_B;
rtl818x_hwinfo.nr_supported_rates = RTL818X_NR_B_RATES;
hwinfo->modes = NET80211_MODE_B;
hwinfo->nr_rates[NET80211_BAND_2GHZ] = RTL818X_NR_B_RATES;
}

priv->spibit.basher.op = &rtl818x_basher_ops;
Expand Down Expand Up @@ -755,13 +758,15 @@ static int rtl818x_probe(struct pci_device *pdev,
}

if (!priv->rf) {
#if DBGLVL_MAX
if (eeprom_val < RTL818X_NR_RF_NAMES &&
rtl818x_rf_names[eeprom_val] != NULL)
DBG("rtl818x: %s RF frontend not supported!\n",
rtl818x_rf_names[eeprom_val]);
else
DBG("rtl818x: RF frontend #%d not recognized!\n",
eeprom_val);
#endif

err = -ENOSYS;
goto err_free_dev;
Expand All @@ -777,7 +782,7 @@ static int rtl818x_probe(struct pci_device *pdev,
}

/* read the MAC address */
nvs_read(&priv->eeprom.nvs, 0x7, rtl818x_hwinfo.hwaddr, 6);
nvs_read(&priv->eeprom.nvs, 0x7, hwinfo->hwaddr, 6);

/* CCK TX power */
for (i = 0; i < 14; i += 2) {
Expand All @@ -799,12 +804,14 @@ static int rtl818x_probe(struct pci_device *pdev,

rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);

err = net80211_register(dev, &rtl818x_operations, &rtl818x_hwinfo);
err = net80211_register(dev, &rtl818x_operations, hwinfo);
if (err) {
DBG("rtl818x: cannot register device\n");
goto err_free_dev;
}

free(hwinfo);

DBG("rtl818x: Realtek RTL818%s (RF chip %s) with address %s\n",
chip_name, priv->rf->name, netdev_hwaddr(dev->netdev));

Expand All @@ -813,6 +820,7 @@ static int rtl818x_probe(struct pci_device *pdev,
err_free_dev:
pci_set_drvdata(pdev, NULL);
net80211_free(dev);
free(hwinfo);
return err;
}

Expand Down
45 changes: 39 additions & 6 deletions src/include/gpxe/net80211.h
Expand Up @@ -42,9 +42,16 @@ FILE_LICENCE ( GPL2_OR_LATER );
/** @{ */

/** The 2.4 GHz ISM band, unlicensed in most countries */
#define NET80211_BAND_2GHZ (1 << 0)
#define NET80211_BAND_2GHZ 0
/** The band from 4.9 GHz to 5.7 GHz, which tends to be more restricted */
#define NET80211_BAND_5GHZ (1 << 1)
#define NET80211_BAND_5GHZ 1
/** Number of RF bands */
#define NET80211_NR_BANDS 2

/** Bitmask for the 2GHz band */
#define NET80211_BAND_BIT_2GHZ (1 << 0)
/** Bitmask for the 5GHz band */
#define NET80211_BAND_BIT_5GHZ (1 << 1)

/** @} */

Expand Down Expand Up @@ -397,6 +404,9 @@ struct net80211_channel
*/
u16 center_freq;

/** Hardware channel value */
u16 hw_value;

/** Maximum allowable transmit power, in dBm
*
* This should be interpreted as EIRP, the power supplied to
Expand Down Expand Up @@ -478,15 +488,21 @@ struct net80211_hw_info
*/
unsigned signal_max;

/** List of transmission rates supported by the card
/** List of RF channels supported by the card */
struct net80211_channel channels[NET80211_MAX_CHANNELS];

/** Number of supported channels */
int nr_channels;

/** List of transmission rates supported by the card, indexed by band
*
* Rates should be in 100kbps increments (e.g. 11 Mbps would
* be represented as the number 110).
*/
u16 supported_rates[NET80211_MAX_RATES];
u16 rates[NET80211_NR_BANDS][NET80211_MAX_RATES];

/** Number of supported rates */
int nr_supported_rates;
/** Number of supported rates, indexed by band */
int nr_rates[NET80211_NR_BANDS];

/** Estimate of the time required to change channels, in microseconds
*
Expand Down Expand Up @@ -969,6 +985,7 @@ struct net80211_device *net80211_alloc ( size_t priv_size );
int net80211_register ( struct net80211_device *dev,
struct net80211_device_operations *ops,
struct net80211_hw_info *hw );
u16 net80211_duration ( struct net80211_device *dev, int bytes, u16 rate );
void net80211_rx ( struct net80211_device *dev, struct io_buffer *iob,
int signal, u16 rate );
void net80211_rx_err ( struct net80211_device *dev,
Expand All @@ -979,5 +996,21 @@ void net80211_unregister ( struct net80211_device *dev );
void net80211_free ( struct net80211_device *dev );
/** @} */

/**
* Calculate duration field for a CTS control frame
*
* @v dev 802.11 device
* @v size Size of the packet being cleared to send
*
* A CTS control frame's duration field captures the frame being
* protected and its 10-byte ACK.
*/
static inline u16 net80211_cts_duration ( struct net80211_device *dev,
int size )
{
return ( net80211_duration ( dev, 10,
dev->rates[dev->rtscts_rate] ) +
net80211_duration ( dev, size, dev->rates[dev->rate] ) );
}

#endif

0 comments on commit f128a6d

Please sign in to comment.