atl1c_set_rxbufsize(adapter, adapter->netdev);
        atomic_set(&adapter->irq_sem, 1);
        spin_lock_init(&adapter->mdio_lock);
+       spin_lock_init(&adapter->hw.intr_mask_lock);
        set_bit(__AT_DOWN, &adapter->flags);
 
        return 0;
        spin_unlock(&adapter->mdio_lock);
 }
 
-static bool atl1c_clean_tx_irq(struct atl1c_adapter *adapter,
-                               enum atl1c_trans_queue type)
+static int atl1c_clean_tx(struct napi_struct *napi, int budget)
 {
-       struct atl1c_tpd_ring *tpd_ring = &adapter->tpd_ring[type];
+       struct atl1c_adapter *adapter =
+               container_of(napi, struct atl1c_adapter, tx_napi);
+       struct atl1c_tpd_ring *tpd_ring = &adapter->tpd_ring[atl1c_trans_normal];
        struct atl1c_buffer *buffer_info;
        struct pci_dev *pdev = adapter->pdev;
        u16 next_to_clean = atomic_read(&tpd_ring->next_to_clean);
        u16 hw_next_to_clean;
-       u16 reg;
        unsigned int total_bytes = 0, total_packets = 0;
+       unsigned long flags;
 
-       reg = type == atl1c_trans_high ? REG_TPD_PRI1_CIDX : REG_TPD_PRI0_CIDX;
-
-       AT_READ_REGW(&adapter->hw, reg, &hw_next_to_clean);
+       AT_READ_REGW(&adapter->hw, REG_TPD_PRI0_CIDX, &hw_next_to_clean);
 
        while (next_to_clean != hw_next_to_clean) {
                buffer_info = &tpd_ring->buffer_info[next_to_clean];
                netif_wake_queue(adapter->netdev);
        }
 
-       return true;
+       if (total_packets < budget) {
+               napi_complete_done(napi, total_packets);
+               spin_lock_irqsave(&adapter->hw.intr_mask_lock, flags);
+               adapter->hw.intr_mask |= ISR_TX_PKT;
+               AT_WRITE_REG(&adapter->hw, REG_IMR, adapter->hw.intr_mask);
+               spin_unlock_irqrestore(&adapter->hw.intr_mask_lock, flags);
+               return total_packets;
+       }
+       return budget;
 }
 
 /**
                AT_WRITE_REG(hw, REG_ISR, status | ISR_DIS_INT);
                if (status & ISR_RX_PKT) {
                        if (likely(napi_schedule_prep(&adapter->napi))) {
+                               spin_lock(&hw->intr_mask_lock);
                                hw->intr_mask &= ~ISR_RX_PKT;
                                AT_WRITE_REG(hw, REG_IMR, hw->intr_mask);
+                               spin_unlock(&hw->intr_mask_lock);
                                __napi_schedule(&adapter->napi);
                        }
                }
-               if (status & ISR_TX_PKT)
-                       atl1c_clean_tx_irq(adapter, atl1c_trans_normal);
+               if (status & ISR_TX_PKT) {
+                       if (napi_schedule_prep(&adapter->tx_napi)) {
+                               spin_lock(&hw->intr_mask_lock);
+                               hw->intr_mask &= ~ISR_TX_PKT;
+                               AT_WRITE_REG(hw, REG_IMR, hw->intr_mask);
+                               spin_unlock(&hw->intr_mask_lock);
+                               __napi_schedule(&adapter->tx_napi);
+                       }
+               }
 
                handled = IRQ_HANDLED;
                /* check if PCIE PHY Link down */
        struct atl1c_adapter *adapter =
                        container_of(napi, struct atl1c_adapter, napi);
        int work_done = 0;
+       unsigned long flags;
 
        /* Keep link state information with original netdev */
        if (!netif_carrier_ok(adapter->netdev))
        if (work_done < budget) {
 quit_polling:
                napi_complete_done(napi, work_done);
+               spin_lock_irqsave(&adapter->hw.intr_mask_lock, flags);
                adapter->hw.intr_mask |= ISR_RX_PKT;
                AT_WRITE_REG(&adapter->hw, REG_IMR, adapter->hw.intr_mask);
+               spin_unlock_irqrestore(&adapter->hw.intr_mask_lock, flags);
        }
        return work_done;
 }
        atl1c_check_link_status(adapter);
        clear_bit(__AT_DOWN, &adapter->flags);
        napi_enable(&adapter->napi);
+       napi_enable(&adapter->tx_napi);
        atl1c_irq_enable(adapter);
        netif_start_queue(netdev);
        return err;
        set_bit(__AT_DOWN, &adapter->flags);
        netif_carrier_off(netdev);
        napi_disable(&adapter->napi);
+       napi_disable(&adapter->tx_napi);
        atl1c_irq_disable(adapter);
        atl1c_free_irq(adapter);
        /* disable ASPM if device inactive */
        adapter->mii.mdio_write = atl1c_mdio_write;
        adapter->mii.phy_id_mask = 0x1f;
        adapter->mii.reg_num_mask = MDIO_CTRL_REG_MASK;
+       dev_set_threaded(netdev, true);
        netif_napi_add(netdev, &adapter->napi, atl1c_clean, 64);
+       netif_napi_add(netdev, &adapter->tx_napi, atl1c_clean_tx, 64);
        timer_setup(&adapter->phy_config_timer, atl1c_phy_config, 0);
        /* setup the private structure */
        err = atl1c_sw_init(adapter);