rtl8180: use NAPI for bottom-half processing
Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
4e6cbfd09c
commit
030725d2c7
1 changed files with 69 additions and 59 deletions
|
@ -99,19 +99,66 @@ void rtl8180_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data)
|
|||
}
|
||||
}
|
||||
|
||||
static void rtl8180_handle_rx(struct ieee80211_hw *dev)
|
||||
static void rtl8180_handle_tx(struct ieee80211_hw *dev)
|
||||
{
|
||||
struct rtl8180_priv *priv = dev->priv;
|
||||
unsigned int count = 32;
|
||||
struct rtl8180_tx_ring *ring;
|
||||
int prio;
|
||||
|
||||
spin_lock(&priv->lock);
|
||||
|
||||
for (prio = 3; prio >= 0; prio--) {
|
||||
ring = &priv->tx_ring[prio];
|
||||
|
||||
while (skb_queue_len(&ring->queue)) {
|
||||
struct rtl8180_tx_desc *entry = &ring->desc[ring->idx];
|
||||
struct sk_buff *skb;
|
||||
struct ieee80211_tx_info *info;
|
||||
u32 flags = le32_to_cpu(entry->flags);
|
||||
|
||||
if (flags & RTL818X_TX_DESC_FLAG_OWN)
|
||||
break;
|
||||
|
||||
ring->idx = (ring->idx + 1) % ring->entries;
|
||||
skb = __skb_dequeue(&ring->queue);
|
||||
pci_unmap_single(priv->pdev, le32_to_cpu(entry->tx_buf),
|
||||
skb->len, PCI_DMA_TODEVICE);
|
||||
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
ieee80211_tx_info_clear_status(info);
|
||||
|
||||
if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) &&
|
||||
(flags & RTL818X_TX_DESC_FLAG_TX_OK))
|
||||
info->flags |= IEEE80211_TX_STAT_ACK;
|
||||
|
||||
info->status.rates[0].count = (flags & 0xFF) + 1;
|
||||
info->status.rates[1].idx = -1;
|
||||
|
||||
ieee80211_tx_status(dev, skb);
|
||||
if (ring->entries - skb_queue_len(&ring->queue) == 2)
|
||||
ieee80211_wake_queue(dev, prio);
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock(&priv->lock);
|
||||
}
|
||||
|
||||
static int rtl8180_poll(struct ieee80211_hw *dev, int budget)
|
||||
{
|
||||
struct rtl8180_priv *priv = dev->priv;
|
||||
unsigned int count = 0;
|
||||
u8 signal, agc, sq;
|
||||
|
||||
while (count--) {
|
||||
/* handle pending Tx queue cleanup */
|
||||
rtl8180_handle_tx(dev);
|
||||
|
||||
while (count++ < budget) {
|
||||
struct rtl8180_rx_desc *entry = &priv->rx_ring[priv->rx_idx];
|
||||
struct sk_buff *skb = priv->rx_buf[priv->rx_idx];
|
||||
u32 flags = le32_to_cpu(entry->flags);
|
||||
|
||||
if (flags & RTL818X_RX_DESC_FLAG_OWN)
|
||||
return;
|
||||
break;
|
||||
|
||||
if (unlikely(flags & (RTL818X_RX_DESC_FLAG_DMA_FAIL |
|
||||
RTL818X_RX_DESC_FLAG_FOF |
|
||||
|
@ -151,7 +198,7 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev)
|
|||
rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;
|
||||
|
||||
memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
|
||||
ieee80211_rx_irqsafe(dev, skb);
|
||||
ieee80211_rx(dev, skb);
|
||||
|
||||
skb = new_skb;
|
||||
priv->rx_buf[priv->rx_idx] = skb;
|
||||
|
@ -168,41 +215,16 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev)
|
|||
entry->flags |= cpu_to_le32(RTL818X_RX_DESC_FLAG_EOR);
|
||||
priv->rx_idx = (priv->rx_idx + 1) % 32;
|
||||
}
|
||||
}
|
||||
|
||||
static void rtl8180_handle_tx(struct ieee80211_hw *dev, unsigned int prio)
|
||||
{
|
||||
struct rtl8180_priv *priv = dev->priv;
|
||||
struct rtl8180_tx_ring *ring = &priv->tx_ring[prio];
|
||||
if (count < budget) {
|
||||
/* disable polling */
|
||||
ieee80211_napi_complete(dev);
|
||||
|
||||
while (skb_queue_len(&ring->queue)) {
|
||||
struct rtl8180_tx_desc *entry = &ring->desc[ring->idx];
|
||||
struct sk_buff *skb;
|
||||
struct ieee80211_tx_info *info;
|
||||
u32 flags = le32_to_cpu(entry->flags);
|
||||
|
||||
if (flags & RTL818X_TX_DESC_FLAG_OWN)
|
||||
return;
|
||||
|
||||
ring->idx = (ring->idx + 1) % ring->entries;
|
||||
skb = __skb_dequeue(&ring->queue);
|
||||
pci_unmap_single(priv->pdev, le32_to_cpu(entry->tx_buf),
|
||||
skb->len, PCI_DMA_TODEVICE);
|
||||
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
ieee80211_tx_info_clear_status(info);
|
||||
|
||||
if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) &&
|
||||
(flags & RTL818X_TX_DESC_FLAG_TX_OK))
|
||||
info->flags |= IEEE80211_TX_STAT_ACK;
|
||||
|
||||
info->status.rates[0].count = (flags & 0xFF) + 1;
|
||||
info->status.rates[1].idx = -1;
|
||||
|
||||
ieee80211_tx_status_irqsafe(dev, skb);
|
||||
if (ring->entries - skb_queue_len(&ring->queue) == 2)
|
||||
ieee80211_wake_queue(dev, prio);
|
||||
/* enable interrupts */
|
||||
rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0xFFFF);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static irqreturn_t rtl8180_interrupt(int irq, void *dev_id)
|
||||
|
@ -211,31 +233,17 @@ static irqreturn_t rtl8180_interrupt(int irq, void *dev_id)
|
|||
struct rtl8180_priv *priv = dev->priv;
|
||||
u16 reg;
|
||||
|
||||
spin_lock(&priv->lock);
|
||||
reg = rtl818x_ioread16(priv, &priv->map->INT_STATUS);
|
||||
if (unlikely(reg == 0xFFFF)) {
|
||||
spin_unlock(&priv->lock);
|
||||
if (unlikely(reg == 0xFFFF))
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
rtl818x_iowrite16(priv, &priv->map->INT_STATUS, reg);
|
||||
|
||||
if (reg & (RTL818X_INT_TXB_OK | RTL818X_INT_TXB_ERR))
|
||||
rtl8180_handle_tx(dev, 3);
|
||||
/* disable interrupts */
|
||||
rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0);
|
||||
|
||||
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))
|
||||
rtl8180_handle_tx(dev, 0);
|
||||
|
||||
if (reg & (RTL818X_INT_RX_OK | RTL818X_INT_RX_ERR))
|
||||
rtl8180_handle_rx(dev);
|
||||
|
||||
spin_unlock(&priv->lock);
|
||||
/* enable polling */
|
||||
ieee80211_napi_schedule(dev);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
@ -247,7 +255,6 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
|
|||
struct rtl8180_priv *priv = dev->priv;
|
||||
struct rtl8180_tx_ring *ring;
|
||||
struct rtl8180_tx_desc *entry;
|
||||
unsigned long flags;
|
||||
unsigned int idx, prio;
|
||||
dma_addr_t mapping;
|
||||
u32 tx_flags;
|
||||
|
@ -294,7 +301,7 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
|
|||
plcp_len |= 1 << 15;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
spin_lock(&priv->lock);
|
||||
|
||||
if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
|
||||
if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
|
||||
|
@ -318,7 +325,7 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
|
|||
if (ring->entries - skb_queue_len(&ring->queue) < 2)
|
||||
ieee80211_stop_queue(dev, prio);
|
||||
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
spin_unlock(&priv->lock);
|
||||
|
||||
rtl818x_iowrite8(priv, &priv->map->TX_DMA_POLLING, (1 << (prio + 4)));
|
||||
|
||||
|
@ -861,6 +868,7 @@ static const struct ieee80211_ops rtl8180_ops = {
|
|||
.prepare_multicast = rtl8180_prepare_multicast,
|
||||
.configure_filter = rtl8180_configure_filter,
|
||||
.get_tsf = rtl8180_get_tsf,
|
||||
.napi_poll = rtl8180_poll,
|
||||
};
|
||||
|
||||
static void rtl8180_eeprom_register_read(struct eeprom_93cx6 *eeprom)
|
||||
|
@ -992,6 +1000,8 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev,
|
|||
dev->queues = 1;
|
||||
dev->max_signal = 65;
|
||||
|
||||
dev->napi_weight = 64;
|
||||
|
||||
reg = rtl818x_ioread32(priv, &priv->map->TX_CONF);
|
||||
reg &= RTL818X_TX_CONF_HWVER_MASK;
|
||||
switch (reg) {
|
||||
|
|
Loading…
Reference in a new issue