rtl8180: don't write MAR registers for rtl8187se
[deliverable/linux.git] / drivers / net / wireless / rtl818x / rtl8180 / dev.c
index 0b405b8c8d70c131198e55aced94f4e4313e6bf6..cce972d289ef3c20b9f97cf522e8b12fd454551d 100644 (file)
@@ -85,6 +85,30 @@ static const struct ieee80211_channel rtl818x_channels[] = {
        { .center_freq = 2484 },
 };
 
+/* Queues for rtl8180/rtl8185 cards
+ *
+ * name | reg  |  prio
+ *  BC  |  7   |   3
+ *  HI  |  6   |   0
+ *  NO  |  5   |   1
+ *  LO  |  4   |   2
+ *
+ * The complete map for DMA kick reg using all queue is:
+ * static const int rtl8180_queues_map[RTL8180_NR_TX_QUEUES] = {6, 5, 4, 7};
+ *
+ * .. but .. Because the mac80211 needs at least 4 queues for QoS or
+ * otherwise QoS can't be done, we use just one.
+ * Beacon queue could be used, but this is not finished yet.
+ * Actual map is:
+ *
+ * name | reg  |  prio
+ *  BC  |  7   |   1  <- currently not used yet.
+ *  HI  |  6   |   x  <- not used
+ *  NO  |  5   |   x  <- not used
+ *  LO  |  4   |   0  <- used
+ */
+
+static const int rtl8180_queues_map[RTL8180_NR_TX_QUEUES] = {4, 7};
 
 void rtl8180_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data)
 {
@@ -105,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;
@@ -122,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);
 
@@ -154,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;
@@ -175,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;
        }
 }
@@ -219,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;
@@ -235,12 +329,6 @@ static irqreturn_t rtl8180_interrupt(int irq, void *dev_id)
        rtl818x_iowrite16(priv, &priv->map->INT_STATUS, reg);
 
        if (reg & (RTL818X_INT_TXB_OK | RTL818X_INT_TXB_ERR))
-               rtl8180_handle_tx(dev, 3);
-
-       if (reg & (RTL818X_INT_TXH_OK | RTL818X_INT_TXH_ERR))
-               rtl8180_handle_tx(dev, 2);
-
-       if (reg & (RTL818X_INT_TXN_OK | RTL818X_INT_TXN_ERR))
                rtl8180_handle_tx(dev, 1);
 
        if (reg & (RTL818X_INT_TXL_OK | RTL818X_INT_TXL_ERR))
@@ -264,7 +352,7 @@ static void rtl8180_tx(struct ieee80211_hw *dev,
        struct rtl8180_tx_ring *ring;
        struct rtl8180_tx_desc *entry;
        unsigned long flags;
-       unsigned int idx, prio;
+       unsigned int idx, prio, hw_prio;
        dma_addr_t mapping;
        u32 tx_flags;
        u8 rc_flags;
@@ -354,7 +442,11 @@ static void rtl8180_tx(struct ieee80211_hw *dev,
 
        spin_unlock_irqrestore(&priv->lock, flags);
 
-       rtl818x_iowrite8(priv, &priv->map->TX_DMA_POLLING, (1 << (prio + 4)));
+       hw_prio = rtl8180_queues_map[prio];
+
+       rtl818x_iowrite8(priv, &priv->map->TX_DMA_POLLING,
+                        (1 << hw_prio) | /* ring to poll  */
+                        (1<<1) | (1<<2));/* stopped rings */
 }
 
 void rtl8180_set_anaparam(struct rtl8180_priv *priv, u32 anaparam)
@@ -371,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)
 {
@@ -390,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:
@@ -398,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;
        }
 }
 
@@ -411,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);
@@ -447,9 +573,7 @@ static int rtl8180_init_hw(struct ieee80211_hw *dev)
                rtl8180_set_anaparam(priv, priv->anaparam);
 
        rtl818x_iowrite32(priv, &priv->map->RDSAR, priv->rx_ring_dma);
-       rtl818x_iowrite32(priv, &priv->map->TBDA, priv->tx_ring[3].dma);
-       rtl818x_iowrite32(priv, &priv->map->THPDA, priv->tx_ring[2].dma);
-       rtl818x_iowrite32(priv, &priv->map->TNPDA, priv->tx_ring[1].dma);
+       rtl818x_iowrite32(priv, &priv->map->TBDA, priv->tx_ring[1].dma);
        rtl818x_iowrite32(priv, &priv->map->TLPDA, priv->tx_ring[0].dma);
 
        /* TODO: necessary? specs indicate not */
@@ -505,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) {
@@ -517,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;
@@ -563,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;
 }
@@ -627,7 +756,7 @@ static int rtl8180_start(struct ieee80211_hw *dev)
        if (ret)
                return ret;
 
-       for (i = 0; i < 4; i++)
+       for (i = 0; i < (dev->queues + 1); i++)
                if ((ret = rtl8180_init_tx_ring(dev, i, 16)))
                        goto err_free_rings;
 
@@ -635,23 +764,28 @@ static int rtl8180_start(struct ieee80211_hw *dev)
        if (ret)
                goto err_free_rings;
 
-       rtl818x_iowrite32(priv, &priv->map->RDSAR, priv->rx_ring_dma);
-       rtl818x_iowrite32(priv, &priv->map->TBDA, priv->tx_ring[3].dma);
-       rtl818x_iowrite32(priv, &priv->map->THPDA, priv->tx_ring[2].dma);
-       rtl818x_iowrite32(priv, &priv->map->TNPDA, priv->tx_ring[1].dma);
-       rtl818x_iowrite32(priv, &priv->map->TLPDA, priv->tx_ring[0].dma);
-
-       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 |
@@ -728,7 +862,7 @@ static int rtl8180_start(struct ieee80211_hw *dev)
 
  err_free_rings:
        rtl8180_free_rx_ring(dev);
-       for (i = 0; i < 4; i++)
+       for (i = 0; i < (dev->queues + 1); i++)
                if (priv->tx_ring[i].desc)
                        rtl8180_free_tx_ring(dev, i);
 
@@ -741,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;
@@ -758,7 +892,7 @@ static void rtl8180_stop(struct ieee80211_hw *dev)
        free_irq(priv->pdev->irq, dev);
 
        rtl8180_free_rx_ring(dev);
-       for (i = 0; i < 4; i++)
+       for (i = 0; i < (dev->queues + 1); i++)
                rtl8180_free_tx_ring(dev, i);
 }
 
@@ -1221,7 +1355,6 @@ static int rtl8180_probe(struct pci_dev *pdev,
        dev->vif_data_size = sizeof(struct rtl8180_vif);
        dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
                                        BIT(NL80211_IFTYPE_ADHOC);
-       dev->queues = 1;
        dev->max_signal = 65;
 
        reg = rtl818x_ioread32(priv, &priv->map->TX_CONF);
@@ -1252,6 +1385,15 @@ static int rtl8180_probe(struct pci_dev *pdev,
                goto err_iounmap;
        }
 
+       /* we declare to MAC80211 all the queues except for beacon queue
+        * that will be eventually handled by DRV.
+        * TX rings are arranged in such a way that lower is the IDX,
+        * higher is the priority, in order to achieve direct mapping
+        * with mac80211, however the beacon queue is an exception and it
+        * is mapped on the highst tx ring IDX.
+        */
+       dev->queues = RTL8180_NR_TX_QUEUES - 1;
+
        if (priv->chip_family != RTL818X_CHIP_FAMILY_RTL8180) {
                priv->band.n_bitrates = ARRAY_SIZE(rtl818x_rates);
                pci_try_set_mwi(pdev);
This page took 0.048029 seconds and 5 git commands to generate.