struct rteth_tx *tx_data;
};
+static void rteth_disable_all_irqs(struct rteth_ctrl *ctrl)
+{
+ int registers = ((ctrl->r->rx_rings * 2 + 7) / 32) + 1;
+
+ for (int reg = 0; reg < registers; reg++) {
+ sw_w32(0, ctrl->r->dma_if_intr_msk + reg * 4);
+ sw_w32(GENMASK(31, 0), ctrl->r->dma_if_intr_sts + reg * 4);
+ }
+}
+
+static void rteth_enable_all_rx_irqs(struct rteth_ctrl *ctrl)
+{
+ int mask, shift, reg;
+
+ /*
+ * The hardware has several types of interrupts. Basically for rx/tx completion and
+ * if hardware queues run out. For now the driver only needs notification about new
+ * incoming packets. Leave everything else disabled.
+ */
+ mask = GENMASK(ctrl->r->rx_rings - 1, 0);
+ shift = ctrl->r->rx_rings % 32;
+ reg = ctrl->r->rx_rings / 32;
+ sw_w32_mask(0, mask << shift, ctrl->r->dma_if_intr_msk + reg * 4);
+
+ /*
+ * RTL839x has additional L2 notification interrupts. Simply activate them. All other
+ * devices that do not have the feature have adequate reserved bit space and ignore it.
+ */
+ mask = GENMASK(2, 0);
+ shift = (ctrl->r->rx_rings * 2 + 4) % 32;
+ reg = (ctrl->r->rx_rings * 2 + 4) / 32;
+ sw_w32_mask(0, mask << shift, ctrl->r->dma_if_intr_msk + reg * 4);
+}
+
/* On the RTL93XX, the RTL93XX_DMA_IF_RX_RING_CNTR track the fill level of
* the rings. Writing x into these registers substracts x from its content.
* When the content reaches the ring size, the ASIC no longer adds
static void rteth_838x_hw_reset(struct rteth_ctrl *ctrl)
{
- /* Disable and clear interrupts */
- sw_w32(0x00000000, ctrl->r->dma_if_intr_msk);
- sw_w32(0xffffffff, ctrl->r->dma_if_intr_sts);
-
rteth_nic_reset(ctrl, 0xc);
/* Free floating rings without space tracking */
{
u32 int_saved, nbuf;
- /* Disable and clear interrupts */
- sw_w32(0x00000000, ctrl->r->dma_if_intr_msk);
- sw_w32(0xffffffff, ctrl->r->dma_if_intr_sts);
-
/* Preserve L2 notification and NBUF settings */
int_saved = sw_r32(ctrl->r->dma_if_intr_msk);
nbuf = sw_r32(RTL839X_DMA_IF_NBUF_BASE_DESC_ADDR_CTRL);
static void rteth_93xx_hw_reset(struct rteth_ctrl *ctrl)
{
- /* Disable and clear interrupts */
- sw_w32(0x00000000, ctrl->r->dma_if_intr_msk);
- sw_w32(0xffffffff, ctrl->r->dma_if_intr_sts);
- sw_w32(0x00000000, ctrl->r->dma_if_intr_rx_done_msk);
- sw_w32(0xffffffff, ctrl->r->dma_if_intr_rx_done_sts);
- sw_w32(0x00000000, ctrl->r->dma_if_intr_tx_done_msk);
- sw_w32(0x0000000f, ctrl->r->dma_if_intr_tx_done_sts);
-
rteth_nic_reset(ctrl, 0x6);
/* Setup Head of Line */
/* Truncate RX buffer to DEFAULT_MTU bytes, pad TX */
sw_w32((DEFAULT_MTU << 16) | RX_TRUNCATE_EN_83XX | TX_PAD_EN_838X, ctrl->r->dma_if_ctrl);
- /* Enable RX done and RX overflow, TX done interrupts not needed */
- sw_w32(0xffff, ctrl->r->dma_if_intr_msk);
+ rteth_enable_all_rx_irqs(ctrl);
/* Enable DMA, engine expects empty FCS field */
sw_w32_mask(0, RX_EN | TX_EN, ctrl->r->dma_if_ctrl);
/* Setup CPU-Port: RX Buffer */
sw_w32((DEFAULT_MTU << 5) | RX_TRUNCATE_EN_83XX, ctrl->r->dma_if_ctrl);
- /* Enable Notify, RX done and RX overflow, TX done interrupts not needed */
- sw_w32(0x0070ffff, ctrl->r->dma_if_intr_msk); /* Notify IRQ! */
+ rteth_enable_all_rx_irqs(ctrl);
/* Enable DMA */
sw_w32_mask(0, RX_EN | TX_EN, ctrl->r->dma_if_ctrl);
sw_w32_mask(0x3ff << pos, v, ctrl->r->dma_if_rx_ring_cntr(i));
}
- /* Enable Notify, RX done and RX overflow, TX done interrupts not needed */
- sw_w32(0xffffffff, ctrl->r->dma_if_intr_msk);
- sw_w32(0xffffffff, ctrl->r->dma_if_intr_rx_done_msk);
- sw_w32(0x00000000, ctrl->r->dma_if_intr_tx_done_msk);
+ rteth_enable_all_rx_irqs(ctrl);
/* Enable DMA */
sw_w32_mask(0, RX_EN_93XX | TX_EN_93XX, ctrl->r->dma_if_ctrl);
static void rtl838x_hw_stop(struct rteth_ctrl *ctrl)
{
u32 force_mac = ctrl->r->family_id == RTL8380_FAMILY_ID ? 0x6192C : 0x75;
- u32 clear_irq = ctrl->r->family_id == RTL8380_FAMILY_ID ? 0x000fffff : 0x007fffff;
/* Disable RX/TX from/to CPU-port */
sw_w32_mask(0x3, 0, ctrl->r->mac_l2_port_ctrl);
sw_w32_mask(BIT(0) | BIT(9), 0, ctrl->r->mac_force_mode_ctrl + ctrl->r->cpu_port * 4);
mdelay(100);
- /* Disable all TX/RX interrupts */
- if (ctrl->r->family_id == RTL9300_FAMILY_ID || ctrl->r->family_id == RTL9310_FAMILY_ID) {
- sw_w32(0x00000000, ctrl->r->dma_if_intr_msk);
- sw_w32(0xffffffff, ctrl->r->dma_if_intr_sts);
- sw_w32(0x00000000, ctrl->r->dma_if_intr_rx_done_msk);
- sw_w32(0xffffffff, ctrl->r->dma_if_intr_rx_done_sts);
- sw_w32(0x00000000, ctrl->r->dma_if_intr_tx_done_msk);
- sw_w32(0x0000000f, ctrl->r->dma_if_intr_tx_done_sts);
- } else {
- sw_w32(0x00000000, ctrl->r->dma_if_intr_msk);
- sw_w32(clear_irq, ctrl->r->dma_if_intr_sts);
- }
+ rteth_disable_all_irqs(ctrl);
/* Disable TX/RX DMA */
sw_w32(0x00000000, ctrl->r->dma_if_ctrl);
if (dev->irq < 0)
return -ENODEV;
+ rteth_disable_all_irqs(ctrl);
err = devm_request_irq(&pdev->dev, dev->irq, ctrl->r->net_irq,
IRQF_SHARED, dev->name, dev);
if (err) {