summaryrefslogtreecommitdiffstats
path: root/src/drivers/net/rtl818x
diff options
context:
space:
mode:
authorJoshua Oreman2009-08-07 10:38:23 +0200
committerMichael Brown2009-08-09 01:11:26 +0200
commitf128a6db21339964c52fb7bcfc6c8a3ffa96387b (patch)
tree72f88f3acbcf7219685f16e60e3b1729c636d1c7 /src/drivers/net/rtl818x
parent[geniso] Emit proper error message for incorrect location of ISOLINUX_BIN (diff)
downloadipxe-f128a6db21339964c52fb7bcfc6c8a3ffa96387b.tar.gz
ipxe-f128a6db21339964c52fb7bcfc6c8a3ffa96387b.tar.xz
ipxe-f128a6db21339964c52fb7bcfc6c8a3ffa96387b.zip
[802.11] Enhance support for driver PHY differences
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>
Diffstat (limited to 'src/drivers/net/rtl818x')
-rw-r--r--src/drivers/net/rtl818x/rtl818x.c56
1 files changed, 32 insertions, 24 deletions
diff --git a/src/drivers/net/rtl818x/rtl818x.c b/src/drivers/net/rtl818x/rtl818x.c
index 8ffe1135..672ff9c2 100644
--- a/src/drivers/net/rtl818x/rtl818x.c
+++ b/src/drivers/net/rtl818x/rtl818x.c
@@ -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;
@@ -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);
@@ -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 */
@@ -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,
@@ -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);
@@ -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;
@@ -755,6 +758,7 @@ 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",
@@ -762,6 +766,7 @@ static int rtl818x_probe(struct pci_device *pdev,
else
DBG("rtl818x: RF frontend #%d not recognized!\n",
eeprom_val);
+#endif
err = -ENOSYS;
goto err_free_dev;
@@ -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) {
@@ -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));
@@ -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;
}