https://blog.csdn.net/hz5034/article/details/79794478
static irqreturn_t ixgbe_msix_clean_many(int irq, void *data) { struct ixgbe_q_vector *q_vector = data; struct ixgbe_adapter *adapter = q_vector->adapter; struct ixgbe_ring *ring; int r_idx; int i; // 若发送/接收队列数都为零 if (!q_vector->txr_count && !q_vector->rxr_count) return IRQ_HANDLED; r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues); for (i = 0; i < q_vector->txr_count; i++) { // 遍历中断对应的发送队列(一般一个中断只对应一个发送队列) ring = &(adapter->tx_ring[r_idx]); // 清零total_bytes和total_packets ring->total_bytes = 0; ring->total_packets = 0; r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues, r_idx + 1); } r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); for (i = 0; i < q_vector->rxr_count; i++) { // 遍历中断对应的接收队列(一般一个中断只对应一个接收队列) ring = &(adapter->rx_ring[r_idx]); // 清零total_bytes和total_packets ring->total_bytes = 0; ring->total_packets = 0; r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues, r_idx + 1); } /* disable interrupts on this vector only */ ixgbe_irq_disable_queues(adapter, ((u64)1 << q_vector->v_idx)); napi_schedule(&q_vector->napi); // NAPI调度 return IRQ_HANDLED; }
static inline void ixgbe_irq_disable_queues(struct ixgbe_adapter *adapter, u64 qmask) { u32 mask; struct ixgbe_hw *hw = &adapter->hw; switch (hw->mac.type) { case ixgbe_mac_82598EB: mask = (IXGBE_EIMS_RTX_QUEUE & qmask); IXGBE_WRITE_REG(hw, IXGBE_EIMC, mask); break; case ixgbe_mac_82599EB: case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: case ixgbe_mac_x550em_a: mask = (qmask & 0xFFFFFFFF); if (mask) IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(0), mask); mask = (qmask >> 32); if (mask) IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(1), mask); break; default: break; } /* skip the flush */ }
static irqreturn_t e100_intr(int irq, void *dev_id) { struct net_device *netdev = dev_id; struct nic *nic = netdev_priv(netdev); u8 stat_ack = ioread8(&nic->csr->scb.stat_ack); netif_printk(nic, intr, KERN_DEBUG, nic->netdev, "stat_ack = 0x%02X ", stat_ack); if (stat_ack == stat_ack_not_ours || /* Not our interrupt */ stat_ack == stat_ack_not_present) /* Hardware is ejected */ return IRQ_NONE; /* Ack interrupt(s) */ iowrite8(stat_ack, &nic->csr->scb.stat_ack); /* We hit Receive No Resource (RNR); restart RU after cleaning */ if (stat_ack & stat_ack_rnr) nic->ru_running = RU_SUSPENDED; if (likely(napi_schedule_prep(&nic->napi))) { e100_disable_irq(nic); //将该网络设备加入到sd的poll_list中 __napi_schedule(&nic->napi); } return IRQ_HANDLED; }
static void e100_enable_irq(struct nic *nic) { unsigned long flags; spin_lock_irqsave(&nic->cmd_lock, flags); iowrite8(irq_mask_none, &nic->csr->scb.cmd_hi); e100_write_flush(nic); spin_unlock_irqrestore(&nic->cmd_lock, flags); } static void e100_disable_irq(struct nic *nic) { unsigned long flags; spin_lock_irqsave(&nic->cmd_lock, flags); iowrite8(irq_mask_all, &nic->csr->scb.cmd_hi); e100_write_flush(nic); spin_unlock_irqrestore(&nic->cmd_lock, flags); }