rtl8180: don't write MAR registers for rtl8187se
[deliverable/linux.git] / drivers / net / wireless / rtl818x / rtl8180 / dev.c
index 767e1048f3368e18bd2ef6934377d6afc30d9c60..cce972d289ef3c20b9f97cf522e8b12fd454551d 100644 (file)
@@ -129,14 +129,30 @@ void rtl8180_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data)
 static void rtl8180_handle_rx(struct ieee80211_hw *dev)
 {
        struct rtl8180_priv *priv = dev->priv;
+       struct rtl818x_rx_cmd_desc *cmd_desc;
        unsigned int count = 32;
        u8 signal, agc, sq;
        dma_addr_t mapping;
 
        while (count--) {
-               struct rtl8180_rx_desc *entry = &priv->rx_ring[priv->rx_idx];
+               void *entry = priv->rx_ring + priv->rx_idx * priv->rx_ring_sz;
                struct sk_buff *skb = priv->rx_buf[priv->rx_idx];
-               u32 flags = le32_to_cpu(entry->flags);
+               u32 flags, flags2;
+               u64 tsft;
+
+               if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) {
+                       struct rtl8187se_rx_desc *desc = entry;
+
+                       flags = le32_to_cpu(desc->flags);
+                       flags2 = le32_to_cpu(desc->flags2);
+                       tsft = le64_to_cpu(desc->tsft);
+               } else {
+                       struct rtl8180_rx_desc *desc = entry;
+
+                       flags = le32_to_cpu(desc->flags);
+                       flags2 = le32_to_cpu(desc->flags2);
+                       tsft = le64_to_cpu(desc->tsft);
+               }
 
                if (flags & RTL818X_RX_DESC_FLAG_OWN)
                        return;
@@ -146,7 +162,6 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev)
                                      RTL818X_RX_DESC_FLAG_RX_ERR)))
                        goto done;
                else {
-                       u32 flags2 = le32_to_cpu(entry->flags2);
                        struct ieee80211_rx_status rx_status = {0};
                        struct sk_buff *new_skb = dev_alloc_skb(MAX_RX_SIZE);
 
@@ -178,14 +193,18 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev)
                                        signal = 90 - clamp_t(u8, agc, 25, 90);
                                else
                                        signal = 95 - clamp_t(u8, agc, 30, 95);
-                       } else {
+                       } else if (priv->chip_family ==
+                                  RTL818X_CHIP_FAMILY_RTL8180) {
                                sq = flags2 & 0xff;
                                signal = priv->rf->calc_rssi(agc, sq);
+                       } else {
+                               /* TODO: rtl8187se rssi */
+                               signal = 10;
                        }
                        rx_status.signal = signal;
                        rx_status.freq = dev->conf.chandef.chan->center_freq;
                        rx_status.band = dev->conf.chandef.chan->band;
-                       rx_status.mactime = le64_to_cpu(entry->tsft);
+                       rx_status.mactime = tsft;
                        rx_status.flag |= RX_FLAG_MACTIME_START;
                        if (flags & RTL818X_RX_DESC_FLAG_CRC32_ERR)
                                rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;
@@ -199,11 +218,13 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev)
                }
 
        done:
-               entry->rx_buf = cpu_to_le32(*((dma_addr_t *)skb->cb));
-               entry->flags = cpu_to_le32(RTL818X_RX_DESC_FLAG_OWN |
+               cmd_desc = entry;
+               cmd_desc->rx_buf = cpu_to_le32(*((dma_addr_t *)skb->cb));
+               cmd_desc->flags = cpu_to_le32(RTL818X_RX_DESC_FLAG_OWN |
                                           MAX_RX_SIZE);
                if (priv->rx_idx == 31)
-                       entry->flags |= cpu_to_le32(RTL818X_RX_DESC_FLAG_EOR);
+                       cmd_desc->flags |=
+                               cpu_to_le32(RTL818X_RX_DESC_FLAG_EOR);
                priv->rx_idx = (priv->rx_idx + 1) % 32;
        }
 }
@@ -243,6 +264,55 @@ static void rtl8180_handle_tx(struct ieee80211_hw *dev, unsigned int prio)
        }
 }
 
+static irqreturn_t rtl8187se_interrupt(int irq, void *dev_id)
+{
+       struct ieee80211_hw *dev = dev_id;
+       struct rtl8180_priv *priv = dev->priv;
+       u32 reg;
+       unsigned long flags;
+       static int desc_err;
+
+       spin_lock_irqsave(&priv->lock, flags);
+       /* Note: 32-bit interrupt status */
+       reg = rtl818x_ioread32(priv, &priv->map->INT_STATUS_SE);
+       if (unlikely(reg == 0xFFFFFFFF)) {
+               spin_unlock_irqrestore(&priv->lock, flags);
+               return IRQ_HANDLED;
+       }
+
+       rtl818x_iowrite32(priv, &priv->map->INT_STATUS_SE, reg);
+
+       if (reg & IMR_TIMEOUT1)
+               rtl818x_iowrite32(priv, &priv->map->INT_TIMEOUT, 0);
+
+       if (reg & (IMR_TBDOK | IMR_TBDER))
+               rtl8180_handle_tx(dev, 4);
+
+       if (reg & (IMR_TVODOK | IMR_TVODER))
+               rtl8180_handle_tx(dev, 0);
+
+       if (reg & (IMR_TVIDOK | IMR_TVIDER))
+               rtl8180_handle_tx(dev, 1);
+
+       if (reg & (IMR_TBEDOK | IMR_TBEDER))
+               rtl8180_handle_tx(dev, 2);
+
+       if (reg & (IMR_TBKDOK | IMR_TBKDER))
+               rtl8180_handle_tx(dev, 3);
+
+       if (reg & (IMR_ROK | IMR_RER | RTL818X_INT_SE_RX_DU | IMR_RQOSOK))
+               rtl8180_handle_rx(dev);
+       /* The interface sometimes generates several RX DMA descriptor errors
+        * at startup. Do not report these.
+        */
+       if ((reg & RTL818X_INT_SE_RX_DU) && desc_err++ > 2)
+               if (net_ratelimit())
+                       wiphy_err(dev->wiphy, "No RX DMA Descriptor avail\n");
+
+       spin_unlock_irqrestore(&priv->lock, flags);
+       return IRQ_HANDLED;
+}
+
 static irqreturn_t rtl8180_interrupt(int irq, void *dev_id)
 {
        struct ieee80211_hw *dev = dev_id;
@@ -393,6 +463,36 @@ void rtl8180_set_anaparam(struct rtl8180_priv *priv, u32 anaparam)
        rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
 }
 
+static void rtl8180_int_enable(struct ieee80211_hw *dev)
+{
+       struct rtl8180_priv *priv = dev->priv;
+
+       if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) {
+               rtl818x_iowrite32(priv, &priv->map->IMR, IMR_TMGDOK |
+                         IMR_TBDER | IMR_THPDER |
+                         IMR_THPDER | IMR_THPDOK |
+                         IMR_TVODER | IMR_TVODOK |
+                         IMR_TVIDER | IMR_TVIDOK |
+                         IMR_TBEDER | IMR_TBEDOK |
+                         IMR_TBKDER | IMR_TBKDOK |
+                         IMR_RDU | IMR_RER |
+                         IMR_ROK | IMR_RQOSOK);
+       } else {
+               rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0xFFFF);
+       }
+}
+
+static void rtl8180_int_disable(struct ieee80211_hw *dev)
+{
+       struct rtl8180_priv *priv = dev->priv;
+
+       if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) {
+               rtl818x_iowrite32(priv, &priv->map->IMR, 0);
+       } else {
+               rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0);
+       }
+}
+
 static void rtl8180_conf_basic_rates(struct ieee80211_hw *dev,
                            u32 rates_mask)
 {
@@ -412,7 +512,6 @@ static void rtl8180_conf_basic_rates(struct ieee80211_hw *dev,
                reg &= ~3;
                reg |= max;
                rtl818x_iowrite16(priv, &priv->map->BRSR, reg);
-
                break;
 
        case RTL818X_CHIP_FAMILY_RTL8185:
@@ -420,6 +519,11 @@ static void rtl8180_conf_basic_rates(struct ieee80211_hw *dev,
                rtl818x_iowrite16(priv, &priv->map->BRSR, rates_mask);
                rtl818x_iowrite8(priv, &priv->map->RESP_RATE, (max << 4) | min);
                break;
+
+       case RTL818X_CHIP_FAMILY_RTL8187SE:
+               /* in 8187se this is a BITMAP */
+               rtl818x_iowrite16(priv, &priv->map->BRSR_8187SE, rates_mask);
+               break;
        }
 }
 
@@ -433,7 +537,7 @@ static int rtl8180_init_hw(struct ieee80211_hw *dev)
        msleep(10);
 
        /* reset */
-       rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0);
+       rtl8180_int_disable(dev);
        rtl818x_ioread8(priv, &priv->map->CMD);
 
        reg = rtl818x_ioread8(priv, &priv->map->CMD);
@@ -525,11 +629,16 @@ static int rtl8180_init_hw(struct ieee80211_hw *dev)
 static int rtl8180_init_rx_ring(struct ieee80211_hw *dev)
 {
        struct rtl8180_priv *priv = dev->priv;
-       struct rtl8180_rx_desc *entry;
+       struct rtl818x_rx_cmd_desc *entry;
        int i;
 
+       if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE)
+               priv->rx_ring_sz = sizeof(struct rtl8187se_rx_desc);
+       else
+               priv->rx_ring_sz = sizeof(struct rtl8180_rx_desc);
+
        priv->rx_ring = pci_alloc_consistent(priv->pdev,
-                                            sizeof(*priv->rx_ring) * 32,
+                                            priv->rx_ring_sz * 32,
                                             &priv->rx_ring_dma);
 
        if (!priv->rx_ring || (unsigned long)priv->rx_ring & 0xFF) {
@@ -537,13 +646,13 @@ static int rtl8180_init_rx_ring(struct ieee80211_hw *dev)
                return -ENOMEM;
        }
 
-       memset(priv->rx_ring, 0, sizeof(*priv->rx_ring) * 32);
+       memset(priv->rx_ring, 0, priv->rx_ring_sz * 32);
        priv->rx_idx = 0;
 
        for (i = 0; i < 32; i++) {
                struct sk_buff *skb = dev_alloc_skb(MAX_RX_SIZE);
                dma_addr_t *mapping;
-               entry = &priv->rx_ring[i];
+               entry = priv->rx_ring + priv->rx_ring_sz*i;
                if (!skb) {
                        wiphy_err(dev->wiphy, "Cannot allocate RX skb\n");
                        return -ENOMEM;
@@ -583,7 +692,7 @@ static void rtl8180_free_rx_ring(struct ieee80211_hw *dev)
                kfree_skb(skb);
        }
 
-       pci_free_consistent(priv->pdev, sizeof(*priv->rx_ring) * 32,
+       pci_free_consistent(priv->pdev, priv->rx_ring_sz * 32,
                            priv->rx_ring, priv->rx_ring_dma);
        priv->rx_ring = NULL;
 }
@@ -655,17 +764,28 @@ static int rtl8180_start(struct ieee80211_hw *dev)
        if (ret)
                goto err_free_rings;
 
-       ret = request_irq(priv->pdev->irq, rtl8180_interrupt,
+       if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) {
+               ret = request_irq(priv->pdev->irq, rtl8187se_interrupt,
+                         IRQF_SHARED, KBUILD_MODNAME, dev);
+       } else {
+               ret = request_irq(priv->pdev->irq, rtl8180_interrupt,
                          IRQF_SHARED, KBUILD_MODNAME, dev);
+       }
+
        if (ret) {
                wiphy_err(dev->wiphy, "failed to register IRQ handler\n");
                goto err_free_rings;
        }
 
-       rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0xFFFF);
+       rtl8180_int_enable(dev);
 
-       rtl818x_iowrite32(priv, &priv->map->MAR[0], ~0);
-       rtl818x_iowrite32(priv, &priv->map->MAR[1], ~0);
+       /* in rtl8187se at MAR regs offset there is the management
+        * TX descriptor DMA addres..
+        */
+       if (priv->chip_family != RTL818X_CHIP_FAMILY_RTL8187SE) {
+               rtl818x_iowrite32(priv, &priv->map->MAR[0], ~0);
+               rtl818x_iowrite32(priv, &priv->map->MAR[1], ~0);
+       }
 
        reg = RTL818X_RX_CONF_ONLYERLPKT |
              RTL818X_RX_CONF_RX_AUTORESETPHY |
@@ -755,7 +875,7 @@ static void rtl8180_stop(struct ieee80211_hw *dev)
        u8 reg;
        int i;
 
-       rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0);
+       rtl8180_int_disable(dev);
 
        reg = rtl818x_ioread8(priv, &priv->map->CMD);
        reg &= ~RTL818X_CMD_TX_ENABLE;
This page took 0.032206 seconds and 5 git commands to generate.