{ .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)
{
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;
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);
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;
}
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;
}
}
}
}
+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;
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))
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;
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)
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)
{
reg &= ~3;
reg |= max;
rtl818x_iowrite16(priv, &priv->map->BRSR, reg);
-
break;
case RTL818X_CHIP_FAMILY_RTL8185:
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;
}
}
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);
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 */
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) {
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;
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;
}
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;
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 |
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);
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;
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);
}
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);
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);