summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rtl8187_dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/rtl8187_dev.c')
-rw-r--r--drivers/net/wireless/rtl8187_dev.c133
1 files changed, 85 insertions, 48 deletions
diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c
index 431e3c7..66add5e 100644
--- a/drivers/net/wireless/rtl8187_dev.c
+++ b/drivers/net/wireless/rtl8187_dev.c
@@ -152,21 +152,19 @@ void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data)
rtl818x_iowrite8(priv, &priv->map->PHY[2], (data >> 16) & 0xFF);
rtl818x_iowrite8(priv, &priv->map->PHY[1], (data >> 8) & 0xFF);
rtl818x_iowrite8(priv, &priv->map->PHY[0], data & 0xFF);
-
- msleep(1);
}
static void rtl8187_tx_cb(struct urb *urb)
{
struct sk_buff *skb = (struct sk_buff *)urb->context;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- struct ieee80211_hw *hw = info->driver_data[0];
+ struct ieee80211_hw *hw = info->rate_driver_data[0];
struct rtl8187_priv *priv = hw->priv;
- usb_free_urb(info->driver_data[1]);
+ usb_free_urb(info->rate_driver_data[1]);
skb_pull(skb, priv->is_rtl8187b ? sizeof(struct rtl8187b_tx_hdr) :
sizeof(struct rtl8187_tx_hdr));
- memset(&info->status, 0, sizeof(info->status));
+ ieee80211_tx_info_clear_status(info);
info->flags |= IEEE80211_TX_STAT_ACK;
ieee80211_tx_status_irqsafe(hw, skb);
}
@@ -175,7 +173,6 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
{
struct rtl8187_priv *priv = dev->priv;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data;
unsigned int ep;
void *buf;
struct urb *urb;
@@ -195,12 +192,12 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
flags |= ieee80211_get_tx_rate(dev, info)->hw_value << 24;
if (ieee80211_has_morefrags(((struct ieee80211_hdr *)skb->data)->frame_control))
flags |= RTL818X_TX_DESC_FLAG_MOREFRAG;
- if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) {
+ if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) {
flags |= RTL818X_TX_DESC_FLAG_RTS;
flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19;
rts_dur = ieee80211_rts_duration(dev, priv->vif,
skb->len, info);
- } else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) {
+ } else if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
flags |= RTL818X_TX_DESC_FLAG_CTS;
flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19;
}
@@ -211,7 +208,7 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
hdr->flags = cpu_to_le32(flags);
hdr->len = 0;
hdr->rts_duration = rts_dur;
- hdr->retry = cpu_to_le32(info->control.retry_limit << 8);
+ hdr->retry = cpu_to_le32((info->control.rates[0].count - 1) << 8);
buf = hdr;
ep = 2;
@@ -229,7 +226,7 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
memset(hdr, 0, sizeof(*hdr));
hdr->flags = cpu_to_le32(flags);
hdr->rts_duration = rts_dur;
- hdr->retry = cpu_to_le32(info->control.retry_limit << 8);
+ hdr->retry = cpu_to_le32((info->control.rates[0].count - 1) << 8);
hdr->tx_duration =
ieee80211_generic_frame_duration(dev, priv->vif,
skb->len, txrate);
@@ -241,22 +238,8 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
ep = epmap[skb_get_queue_mapping(skb)];
}
- /* FIXME: The sequence that follows is needed for this driver to
- * work with mac80211 since "mac80211: fix TX sequence numbers".
- * As with the temporary code in rt2x00, changes will be needed
- * to get proper sequence numbers on beacons. In addition, this
- * patch places the sequence number in the hardware state, which
- * limits us to a single virtual state.
- */
- if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
- if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
- priv->seqno += 0x10;
- ieee80211hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
- ieee80211hdr->seq_ctrl |= cpu_to_le16(priv->seqno);
- }
-
- info->driver_data[0] = dev;
- info->driver_data[1] = urb;
+ info->rate_driver_data[0] = dev;
+ info->rate_driver_data[1] = urb;
usb_fill_bulk_urb(urb, priv->udev, usb_sndbulkpipe(priv->udev, ep),
buf, skb->len, rtl8187_tx_cb, skb);
@@ -684,7 +667,7 @@ static int rtl8187b_init_hw(struct ieee80211_hw *dev)
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480);
rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x2488);
rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
- msleep(1100);
+ msleep(100);
priv->rf->init(dev);
@@ -873,9 +856,10 @@ static void rtl8187_remove_interface(struct ieee80211_hw *dev,
mutex_unlock(&priv->conf_mutex);
}
-static int rtl8187_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
+static int rtl8187_config(struct ieee80211_hw *dev, u32 changed)
{
struct rtl8187_priv *priv = dev->priv;
+ struct ieee80211_conf *conf = &dev->conf;
u32 reg;
mutex_lock(&priv->conf_mutex);
@@ -886,27 +870,10 @@ static int rtl8187_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
*/
rtl818x_iowrite32(priv, &priv->map->TX_CONF,
reg | RTL818X_TX_CONF_LOOPBACK_MAC);
- msleep(10);
priv->rf->set_chan(dev, conf);
msleep(10);
rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg);
- if (!priv->is_rtl8187b) {
- rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22);
-
- if (conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) {
- rtl818x_iowrite8(priv, &priv->map->SLOT, 0x9);
- rtl818x_iowrite8(priv, &priv->map->DIFS, 0x14);
- rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x14);
- rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0x73);
- } else {
- rtl818x_iowrite8(priv, &priv->map->SLOT, 0x14);
- rtl818x_iowrite8(priv, &priv->map->DIFS, 0x24);
- rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x24);
- rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0xa5);
- }
- }
-
rtl818x_iowrite16(priv, &priv->map->ATIM_WND, 2);
rtl818x_iowrite16(priv, &priv->map->ATIMTR_INTERVAL, 100);
rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL, 100);
@@ -941,6 +908,72 @@ static int rtl8187_config_interface(struct ieee80211_hw *dev,
return 0;
}
+static void rtl8187_conf_erp(struct rtl8187_priv *priv, bool use_short_slot,
+ bool use_short_preamble)
+{
+ if (priv->is_rtl8187b) {
+ u8 difs, eifs, slot_time;
+ u16 ack_timeout;
+
+ if (use_short_slot) {
+ slot_time = 0x9;
+ difs = 0x1c;
+ eifs = 0x53;
+ } else {
+ slot_time = 0x14;
+ difs = 0x32;
+ eifs = 0x5b;
+ }
+ rtl818x_iowrite8(priv, &priv->map->SIFS, 0xa);
+ rtl818x_iowrite8(priv, &priv->map->SLOT, slot_time);
+ rtl818x_iowrite8(priv, &priv->map->DIFS, difs);
+
+ /*
+ * BRSR+1 on 8187B is in fact EIFS register
+ * Value in units of 4 us
+ */
+ rtl818x_iowrite8(priv, (u8 *)&priv->map->BRSR + 1, eifs);
+
+ /*
+ * For 8187B, CARRIER_SENSE_COUNTER is in fact ack timeout
+ * register. In units of 4 us like eifs register
+ * ack_timeout = ack duration + plcp + difs + preamble
+ */
+ ack_timeout = 112 + 48 + difs;
+ if (use_short_preamble)
+ ack_timeout += 72;
+ else
+ ack_timeout += 144;
+ rtl818x_iowrite8(priv, &priv->map->CARRIER_SENSE_COUNTER,
+ DIV_ROUND_UP(ack_timeout, 4));
+ } else {
+ rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22);
+ if (use_short_slot) {
+ rtl818x_iowrite8(priv, &priv->map->SLOT, 0x9);
+ rtl818x_iowrite8(priv, &priv->map->DIFS, 0x14);
+ rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x14);
+ rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0x73);
+ } else {
+ rtl818x_iowrite8(priv, &priv->map->SLOT, 0x14);
+ rtl818x_iowrite8(priv, &priv->map->DIFS, 0x24);
+ rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x24);
+ rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0xa5);
+ }
+ }
+}
+
+static void rtl8187_bss_info_changed(struct ieee80211_hw *dev,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *info,
+ u32 changed)
+{
+ struct rtl8187_priv *priv = dev->priv;
+
+ if (changed & (BSS_CHANGED_ERP_SLOT | BSS_CHANGED_ERP_PREAMBLE))
+ rtl8187_conf_erp(priv, info->use_short_slot,
+ info->use_short_preamble);
+}
+
static void rtl8187_configure_filter(struct ieee80211_hw *dev,
unsigned int changed_flags,
unsigned int *total_flags,
@@ -981,6 +1014,7 @@ static const struct ieee80211_ops rtl8187_ops = {
.remove_interface = rtl8187_remove_interface,
.config = rtl8187_config,
.config_interface = rtl8187_config_interface,
+ .bss_info_changed = rtl8187_bss_info_changed,
.configure_filter = rtl8187_configure_filter,
};
@@ -1026,7 +1060,6 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
const char *chip_name;
u16 txpwr, reg;
int err, i;
- DECLARE_MAC_BUF(mac);
dev = ieee80211_alloc_hw(sizeof(*priv), &rtl8187_ops);
if (!dev) {
@@ -1187,6 +1220,10 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
dev->max_signal = 65;
}
+ /*
+ * XXX: Once this driver supports anything that requires
+ * beacons it must implement IEEE80211_TX_CTL_ASSIGN_SEQ.
+ */
dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
if ((id->driver_info == DEVICE_RTL8187) && priv->is_rtl8187b)
@@ -1209,8 +1246,8 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
}
mutex_init(&priv->conf_mutex);
- printk(KERN_INFO "%s: hwaddr %s, %s V%d + %s\n",
- wiphy_name(dev->wiphy), print_mac(mac, dev->wiphy->perm_addr),
+ printk(KERN_INFO "%s: hwaddr %pM, %s V%d + %s\n",
+ wiphy_name(dev->wiphy), dev->wiphy->perm_addr,
chip_name, priv->asic_rev, priv->rf->name);
return 0;
OpenPOWER on IntegriCloud