Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[safe/jmp/linux-2.6] / drivers / net / wireless / rtl818x / rtl8187_dev.c
index 180bc50..fd81884 100644 (file)
@@ -48,6 +48,10 @@ static struct usb_device_id rtl8187_table[] __devinitdata = {
        {USB_DEVICE(0x0bda, 0x8189), .driver_info = DEVICE_RTL8187B},
        {USB_DEVICE(0x0bda, 0x8197), .driver_info = DEVICE_RTL8187B},
        {USB_DEVICE(0x0bda, 0x8198), .driver_info = DEVICE_RTL8187B},
+       /* Surecom */
+       {USB_DEVICE(0x0769, 0x11F2), .driver_info = DEVICE_RTL8187},
+       /* Logitech */
+       {USB_DEVICE(0x0789, 0x010C), .driver_info = DEVICE_RTL8187},
        /* Netgear */
        {USB_DEVICE(0x0846, 0x6100), .driver_info = DEVICE_RTL8187},
        {USB_DEVICE(0x0846, 0x6a00), .driver_info = DEVICE_RTL8187},
@@ -57,8 +61,16 @@ static struct usb_device_id rtl8187_table[] __devinitdata = {
        /* Sitecom */
        {USB_DEVICE(0x0df6, 0x000d), .driver_info = DEVICE_RTL8187},
        {USB_DEVICE(0x0df6, 0x0028), .driver_info = DEVICE_RTL8187B},
+       /* Sphairon Access Systems GmbH */
+       {USB_DEVICE(0x114B, 0x0150), .driver_info = DEVICE_RTL8187},
+       /* Dick Smith Electronics */
+       {USB_DEVICE(0x1371, 0x9401), .driver_info = DEVICE_RTL8187},
        /* Abocom */
        {USB_DEVICE(0x13d1, 0xabe6), .driver_info = DEVICE_RTL8187},
+       /* Qcom */
+       {USB_DEVICE(0x18E8, 0x6232), .driver_info = DEVICE_RTL8187},
+       /* AirLive */
+       {USB_DEVICE(0x1b75, 0x8187), .driver_info = DEVICE_RTL8187},
        {}
 };
 
@@ -99,7 +111,6 @@ static const struct ieee80211_channel rtl818x_channels[] = {
 static void rtl8187_iowrite_async_cb(struct urb *urb)
 {
        kfree(urb->context);
-       usb_free_urb(urb);
 }
 
 static void rtl8187_iowrite_async(struct rtl8187_priv *priv, __le16 addr,
@@ -136,11 +147,13 @@ static void rtl8187_iowrite_async(struct rtl8187_priv *priv, __le16 addr,
        usb_fill_control_urb(urb, priv->udev, usb_sndctrlpipe(priv->udev, 0),
                             (unsigned char *)dr, buf, len,
                             rtl8187_iowrite_async_cb, buf);
+       usb_anchor_urb(urb, &priv->anchored);
        rc = usb_submit_urb(urb, GFP_ATOMIC);
        if (rc < 0) {
                kfree(buf);
-               usb_free_urb(urb);
+               usb_unanchor_urb(urb);
        }
+       usb_free_urb(urb);
 }
 
 static inline void rtl818x_iowrite32_async(struct rtl8187_priv *priv,
@@ -172,30 +185,37 @@ static void rtl8187_tx_cb(struct urb *urb)
        struct ieee80211_hw *hw = info->rate_driver_data[0];
        struct rtl8187_priv *priv = hw->priv;
 
-       usb_free_urb(info->rate_driver_data[1]);
        skb_pull(skb, priv->is_rtl8187b ? sizeof(struct rtl8187b_tx_hdr) :
                                          sizeof(struct rtl8187_tx_hdr));
        ieee80211_tx_info_clear_status(info);
 
-       if (!urb->status &&
-           !(info->flags & IEEE80211_TX_CTL_NO_ACK) &&
-           priv->is_rtl8187b) {
-               skb_queue_tail(&priv->b_tx_status.queue, skb);
+       if (!(urb->status) && !(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
+               if (priv->is_rtl8187b) {
+                       skb_queue_tail(&priv->b_tx_status.queue, skb);
 
-               /* queue is "full", discard last items */
-               while (skb_queue_len(&priv->b_tx_status.queue) > 5) {
-                       struct sk_buff *old_skb;
+                       /* queue is "full", discard last items */
+                       while (skb_queue_len(&priv->b_tx_status.queue) > 5) {
+                               struct sk_buff *old_skb;
 
-                       dev_dbg(&priv->udev->dev,
-                               "transmit status queue full\n");
+                               dev_dbg(&priv->udev->dev,
+                                       "transmit status queue full\n");
 
-                       old_skb = skb_dequeue(&priv->b_tx_status.queue);
-                       ieee80211_tx_status_irqsafe(hw, old_skb);
-               }
-       } else {
-               if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && !urb->status)
+                               old_skb = skb_dequeue(&priv->b_tx_status.queue);
+                               ieee80211_tx_status_irqsafe(hw, old_skb);
+                       }
+                       return;
+               } else {
                        info->flags |= IEEE80211_TX_STAT_ACK;
+               }
+       }
+       if (priv->is_rtl8187b)
                ieee80211_tx_status_irqsafe(hw, skb);
+       else {
+               /* Retry information for the RTI8187 is only available by
+                * reading a register in the device. We are in interrupt mode
+                * here, thus queue the skb and finish on a work queue. */
+               skb_queue_tail(&priv->b_tx_status.queue, skb);
+               queue_delayed_work(hw->workqueue, &priv->work, 0);
        }
 }
 
@@ -213,7 +233,7 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
        urb = usb_alloc_urb(0, GFP_ATOMIC);
        if (!urb) {
                kfree_skb(skb);
-               return 0;
+               return NETDEV_TX_OK;
        }
 
        flags = skb->len;
@@ -238,7 +258,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.rates[0].count << 8);
+               hdr->retry = cpu_to_le32((info->control.rates[0].count - 1) << 8);
                buf = hdr;
 
                ep = 2;
@@ -256,7 +276,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.rates[0].count << 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);
@@ -273,13 +293,16 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
 
        usb_fill_bulk_urb(urb, priv->udev, usb_sndbulkpipe(priv->udev, ep),
                          buf, skb->len, rtl8187_tx_cb, skb);
+       urb->transfer_flags |= URB_ZERO_PACKET;
+       usb_anchor_urb(urb, &priv->anchored);
        rc = usb_submit_urb(urb, GFP_ATOMIC);
        if (rc < 0) {
-               usb_free_urb(urb);
+               usb_unanchor_urb(urb);
                kfree_skb(skb);
        }
+       usb_free_urb(urb);
 
-       return 0;
+       return NETDEV_TX_OK;
 }
 
 static void rtl8187_rx_cb(struct urb *urb)
@@ -292,50 +315,35 @@ static void rtl8187_rx_cb(struct urb *urb)
        int rate, signal;
        u32 flags;
        u32 quality;
+       unsigned long f;
 
-       spin_lock(&priv->rx_queue.lock);
+       spin_lock_irqsave(&priv->rx_queue.lock, f);
        if (skb->next)
                __skb_unlink(skb, &priv->rx_queue);
        else {
-               spin_unlock(&priv->rx_queue.lock);
+               spin_unlock_irqrestore(&priv->rx_queue.lock, f);
                return;
        }
-       spin_unlock(&priv->rx_queue.lock);
+       spin_unlock_irqrestore(&priv->rx_queue.lock, f);
+       skb_put(skb, urb->actual_length);
 
        if (unlikely(urb->status)) {
-               usb_free_urb(urb);
                dev_kfree_skb_irq(skb);
                return;
        }
 
-       skb_put(skb, urb->actual_length);
        if (!priv->is_rtl8187b) {
                struct rtl8187_rx_hdr *hdr =
                        (typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr));
                flags = le32_to_cpu(hdr->flags);
-               signal = hdr->signal & 0x7f;
+               /* As with the RTL8187B below, the AGC is used to calculate
+                * signal strength and quality. In this case, the scaling
+                * constants are derived from the output of p54usb.
+                */
+               quality = 130 - ((41 * hdr->agc) >> 6);
+               signal = -4 - ((27 * hdr->agc) >> 6);
                rx_status.antenna = (hdr->signal >> 7) & 1;
-               rx_status.noise = hdr->noise;
                rx_status.mactime = le64_to_cpu(hdr->mac_time);
-               priv->quality = signal;
-               rx_status.qual = priv->quality;
-               priv->noise = hdr->noise;
-               rate = (flags >> 20) & 0xF;
-               if (rate > 3) { /* OFDM rate */
-                       if (signal > 90)
-                               signal = 90;
-                       else if (signal < 25)
-                               signal = 25;
-                       signal = 90 - signal;
-               } else {        /* CCK rate */
-                       if (signal > 95)
-                               signal = 95;
-                       else if (signal < 30)
-                               signal = 30;
-                       signal = 95 - signal;
-               }
-               rx_status.signal = signal;
-               priv->signal = signal;
        } else {
                struct rtl8187b_rx_hdr *hdr =
                        (typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr));
@@ -353,18 +361,18 @@ static void rtl8187_rx_cb(struct urb *urb)
                 */
                flags = le32_to_cpu(hdr->flags);
                quality = 170 - hdr->agc;
-               if (quality > 100)
-                       quality = 100;
                signal = 14 - hdr->agc / 2;
-               rx_status.qual = quality;
-               priv->quality = quality;
-               rx_status.signal = signal;
-               priv->signal = signal;
                rx_status.antenna = (hdr->rssi >> 7) & 1;
                rx_status.mactime = le64_to_cpu(hdr->mac_time);
-               rate = (flags >> 20) & 0xF;
        }
 
+       if (quality > 100)
+               quality = 100;
+       rx_status.qual = quality;
+       priv->quality = quality;
+       rx_status.signal = signal;
+       priv->signal = signal;
+       rate = (flags >> 20) & 0xF;
        skb_trim(skb, flags & 0x0FFF);
        rx_status.rate_idx = rate;
        rx_status.freq = dev->conf.channel->center_freq;
@@ -376,7 +384,6 @@ static void rtl8187_rx_cb(struct urb *urb)
 
        skb = dev_alloc_skb(RTL8187_MAX_RX);
        if (unlikely(!skb)) {
-               usb_free_urb(urb);
                /* TODO check rx queue length and refill *somewhere* */
                return;
        }
@@ -388,24 +395,32 @@ static void rtl8187_rx_cb(struct urb *urb)
        urb->context = skb;
        skb_queue_tail(&priv->rx_queue, skb);
 
-       usb_submit_urb(urb, GFP_ATOMIC);
+       usb_anchor_urb(urb, &priv->anchored);
+       if (usb_submit_urb(urb, GFP_ATOMIC)) {
+               usb_unanchor_urb(urb);
+               skb_unlink(skb, &priv->rx_queue);
+               dev_kfree_skb_irq(skb);
+       }
 }
 
 static int rtl8187_init_urbs(struct ieee80211_hw *dev)
 {
        struct rtl8187_priv *priv = dev->priv;
-       struct urb *entry;
+       struct urb *entry = NULL;
        struct sk_buff *skb;
        struct rtl8187_rx_info *info;
+       int ret = 0;
 
-       while (skb_queue_len(&priv->rx_queue) < 8) {
+       while (skb_queue_len(&priv->rx_queue) < 16) {
                skb = __dev_alloc_skb(RTL8187_MAX_RX, GFP_KERNEL);
-               if (!skb)
-                       break;
+               if (!skb) {
+                       ret = -ENOMEM;
+                       goto err;
+               }
                entry = usb_alloc_urb(0, GFP_KERNEL);
                if (!entry) {
-                       kfree_skb(skb);
-                       break;
+                       ret = -ENOMEM;
+                       goto err;
                }
                usb_fill_bulk_urb(entry, priv->udev,
                                  usb_rcvbulkpipe(priv->udev,
@@ -416,10 +431,22 @@ static int rtl8187_init_urbs(struct ieee80211_hw *dev)
                info->urb = entry;
                info->dev = dev;
                skb_queue_tail(&priv->rx_queue, skb);
-               usb_submit_urb(entry, GFP_KERNEL);
+               usb_anchor_urb(entry, &priv->anchored);
+               ret = usb_submit_urb(entry, GFP_KERNEL);
+               if (ret) {
+                       skb_unlink(skb, &priv->rx_queue);
+                       usb_unanchor_urb(entry);
+                       goto err;
+               }
+               usb_free_urb(entry);
        }
+       return ret;
 
-       return 0;
+err:
+       usb_free_urb(entry);
+       kfree_skb(skb);
+       usb_kill_anchored_urbs(&priv->anchored);
+       return ret;
 }
 
 static void rtl8187b_status_cb(struct urb *urb)
@@ -429,10 +456,8 @@ static void rtl8187b_status_cb(struct urb *urb)
        u64 val;
        unsigned int cmd_type;
 
-       if (unlikely(urb->status)) {
-               usb_free_urb(urb);
+       if (unlikely(urb->status))
                return;
-       }
 
        /*
         * Read from status buffer:
@@ -496,33 +521,39 @@ static void rtl8187b_status_cb(struct urb *urb)
                        __skb_unlink(skb, &priv->b_tx_status.queue);
                        if (tok)
                                info->flags |= IEEE80211_TX_STAT_ACK;
-                       info->status.rates[0].count = pkt_rc;
+                       info->status.rates[0].count = pkt_rc + 1;
 
                        ieee80211_tx_status_irqsafe(hw, skb);
                }
                spin_unlock_irqrestore(&priv->b_tx_status.queue.lock, flags);
        }
 
-       usb_submit_urb(urb, GFP_ATOMIC);
+       usb_anchor_urb(urb, &priv->anchored);
+       if (usb_submit_urb(urb, GFP_ATOMIC))
+               usb_unanchor_urb(urb);
 }
 
 static int rtl8187b_init_status_urb(struct ieee80211_hw *dev)
 {
        struct rtl8187_priv *priv = dev->priv;
        struct urb *entry;
+       int ret = 0;
 
        entry = usb_alloc_urb(0, GFP_KERNEL);
        if (!entry)
                return -ENOMEM;
-       priv->b_tx_status.urb = entry;
 
        usb_fill_bulk_urb(entry, priv->udev, usb_rcvbulkpipe(priv->udev, 9),
                          &priv->b_tx_status.buf, sizeof(priv->b_tx_status.buf),
                          rtl8187b_status_cb, dev);
 
-       usb_submit_urb(entry, GFP_KERNEL);
+       usb_anchor_urb(entry, &priv->anchored);
+       ret = usb_submit_urb(entry, GFP_KERNEL);
+       if (ret)
+               usb_unanchor_urb(entry);
+       usb_free_urb(entry);
 
-       return 0;
+       return ret;
 }
 
 static int rtl8187_cmd_reset(struct ieee80211_hw *dev)
@@ -634,7 +665,7 @@ static int rtl8187_init_hw(struct ieee80211_hw *dev)
 
        rtl818x_iowrite32(priv, &priv->map->INT_TIMEOUT, 0);
        rtl818x_iowrite8(priv, &priv->map->WPA_CONF, 0);
-       rtl818x_iowrite8(priv, &priv->map->RATE_FALLBACK, 0x81);
+       rtl818x_iowrite8(priv, &priv->map->RATE_FALLBACK, 0);
 
        // TODO: set RESP_RATE and BRSR properly
        rtl818x_iowrite8(priv, &priv->map->RESP_RATE, (8 << 4) | 0);
@@ -754,9 +785,6 @@ static int rtl8187b_init_hw(struct ieee80211_hw *dev)
        rtl818x_iowrite8(priv, &priv->map->TX_AGC_CTL, reg);
 
        rtl818x_iowrite16_idx(priv, (__le16 *)0xFFE0, 0x0FFF, 1);
-       reg = rtl818x_ioread8(priv, &priv->map->RATE_FALLBACK);
-       reg |= RTL818X_RATE_FALLBACK_ENABLE;
-       rtl818x_iowrite8(priv, &priv->map->RATE_FALLBACK, reg);
 
        rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL, 100);
        rtl818x_iowrite16(priv, &priv->map->ATIM_WND, 2);
@@ -844,6 +872,34 @@ static int rtl8187b_init_hw(struct ieee80211_hw *dev)
        return 0;
 }
 
+static void rtl8187_work(struct work_struct *work)
+{
+       /* The RTL8187 returns the retry count through register 0xFFFA. In
+        * addition, it appears to be a cumulative retry count, not the
+        * value for the current TX packet. When multiple TX entries are
+        * queued, the retry count will be valid for the last one in the queue.
+        * The "error" should not matter for purposes of rate setting. */
+       struct rtl8187_priv *priv = container_of(work, struct rtl8187_priv,
+                                   work.work);
+       struct ieee80211_tx_info *info;
+       struct ieee80211_hw *dev = priv->dev;
+       static u16 retry;
+       u16 tmp;
+
+       mutex_lock(&priv->conf_mutex);
+       tmp = rtl818x_ioread16(priv, (__le16 *)0xFFFA);
+       while (skb_queue_len(&priv->b_tx_status.queue) > 0) {
+               struct sk_buff *old_skb;
+
+               old_skb = skb_dequeue(&priv->b_tx_status.queue);
+               info = IEEE80211_SKB_CB(old_skb);
+               info->status.rates[0].count = tmp - retry + 1;
+               ieee80211_tx_status_irqsafe(dev, old_skb);
+       }
+       retry = tmp;
+       mutex_unlock(&priv->conf_mutex);
+}
+
 static int rtl8187_start(struct ieee80211_hw *dev)
 {
        struct rtl8187_priv *priv = dev->priv;
@@ -856,6 +912,10 @@ static int rtl8187_start(struct ieee80211_hw *dev)
                return ret;
 
        mutex_lock(&priv->conf_mutex);
+
+       init_usb_anchor(&priv->anchored);
+       priv->dev = dev;
+
        if (priv->is_rtl8187b) {
                reg = RTL818X_RX_CONF_MGMT |
                      RTL818X_RX_CONF_DATA |
@@ -922,6 +982,7 @@ static int rtl8187_start(struct ieee80211_hw *dev)
        reg |= RTL818X_CMD_TX_ENABLE;
        reg |= RTL818X_CMD_RX_ENABLE;
        rtl818x_iowrite8(priv, &priv->map->CMD, reg);
+       INIT_DELAYED_WORK(&priv->work, rtl8187_work);
        mutex_unlock(&priv->conf_mutex);
 
        return 0;
@@ -930,7 +991,6 @@ static int rtl8187_start(struct ieee80211_hw *dev)
 static void rtl8187_stop(struct ieee80211_hw *dev)
 {
        struct rtl8187_priv *priv = dev->priv;
-       struct rtl8187_rx_info *info;
        struct sk_buff *skb;
        u32 reg;
 
@@ -949,14 +1009,12 @@ static void rtl8187_stop(struct ieee80211_hw *dev)
        rtl818x_iowrite8(priv, &priv->map->CONFIG4, reg | RTL818X_CONFIG4_VCOOFF);
        rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
 
-       while ((skb = skb_dequeue(&priv->rx_queue))) {
-               info = (struct rtl8187_rx_info *)skb->cb;
-               usb_kill_urb(info->urb);
-               kfree_skb(skb);
-       }
        while ((skb = skb_dequeue(&priv->b_tx_status.queue)))
                dev_kfree_skb_any(skb);
-       usb_kill_urb(priv->b_tx_status.urb);
+
+       usb_kill_anchored_urbs(&priv->anchored);
+       if (!priv->is_rtl8187b)
+               cancel_delayed_work_sync(&priv->work);
        mutex_unlock(&priv->conf_mutex);
 }
 
@@ -965,19 +1023,21 @@ static int rtl8187_add_interface(struct ieee80211_hw *dev,
 {
        struct rtl8187_priv *priv = dev->priv;
        int i;
+       int ret = -EOPNOTSUPP;
 
+       mutex_lock(&priv->conf_mutex);
        if (priv->mode != NL80211_IFTYPE_MONITOR)
-               return -EOPNOTSUPP;
+               goto exit;
 
        switch (conf->type) {
        case NL80211_IFTYPE_STATION:
                priv->mode = conf->type;
                break;
        default:
-               return -EOPNOTSUPP;
+               goto exit;
        }
 
-       mutex_lock(&priv->conf_mutex);
+       ret = 0;
        priv->vif = conf->vif;
 
        rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
@@ -986,8 +1046,9 @@ static int rtl8187_add_interface(struct ieee80211_hw *dev,
                                 ((u8 *)conf->mac_addr)[i]);
        rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
 
+exit:
        mutex_unlock(&priv->conf_mutex);
-       return 0;
+       return ret;
 }
 
 static void rtl8187_remove_interface(struct ieee80211_hw *dev,
@@ -1293,6 +1354,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
 
        priv->mode = NL80211_IFTYPE_MONITOR;
        dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
+                    IEEE80211_HW_SIGNAL_DBM |
                     IEEE80211_HW_RX_INCLUDES_FCS;
 
        eeprom.data = dev;
@@ -1408,13 +1470,8 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
                (*channel++).hw_value = txpwr >> 8;
        }
 
-       if (priv->is_rtl8187b) {
+       if (priv->is_rtl8187b)
                printk(KERN_WARNING "rtl8187: 8187B chip detected.\n");
-               dev->flags |= IEEE80211_HW_SIGNAL_DBM;
-       } else {
-               dev->flags |= IEEE80211_HW_SIGNAL_UNSPEC;
-               dev->max_signal = 65;
-       }
 
        /*
         * XXX: Once this driver supports anything that requires
@@ -1467,6 +1524,7 @@ static void __devexit rtl8187_disconnect(struct usb_interface *intf)
        ieee80211_unregister_hw(dev);
 
        priv = dev->priv;
+       usb_reset_device(priv->udev);
        usb_put_dev(interface_to_usbdev(intf));
        ieee80211_free_hw(dev);
 }