]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
net: dlink: enable RMON MMIO access on supported devices
authorMoon Yeounsu <yyyynoom@gmail.com>
Tue, 10 Jun 2025 00:01:30 +0000 (09:01 +0900)
committerJakub Kicinski <kuba@kernel.org>
Wed, 11 Jun 2025 00:47:13 +0000 (17:47 -0700)
Enable memory-mapped I/O access to RMON statistics registers for devices
known to work correctly. Currently, only the D-Link DGE-550T (`0x4000`)
with PCI revision A3 (`0x0c`) is allowed.

To avoid issues on other hardware, a runtime check was added to restrict
MMIO usage. The `MEM_MAPPING` macro was removed in favor of runtime
detection.

To access RMON registers, the code `dw32(RmonStatMask, 0x0007ffff);`
must also be skipped, so this patch conditionally disables it as well.

Tested-on: D-Link DGE-550T Rev-A3
Signed-off-by: Moon Yeounsu <yyyynoom@gmail.com>
Link: https://patch.msgid.link/20250610000130.49065-2-yyyynoom@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/dlink/dl2k.c
drivers/net/ethernet/dlink/dl2k.h

index 038a0400c1f956a5fceaa639d2895122d5e96dc4..ea8361ba6cad0dc147c3d3fd6c493ee27c510885 100644 (file)
@@ -99,6 +99,13 @@ static const struct net_device_ops netdev_ops = {
        .ndo_tx_timeout         = rio_tx_timeout,
 };
 
+static bool is_support_rmon_mmio(struct pci_dev *pdev)
+{
+       return pdev->vendor == PCI_VENDOR_ID_DLINK &&
+              pdev->device == 0x4000 &&
+              pdev->revision == 0x0c;
+}
+
 static int
 rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
 {
@@ -131,18 +138,22 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
 
        np = netdev_priv(dev);
 
+       if (is_support_rmon_mmio(pdev))
+               np->rmon_enable = true;
+
        /* IO registers range. */
        ioaddr = pci_iomap(pdev, 0, 0);
        if (!ioaddr)
                goto err_out_dev;
        np->eeprom_addr = ioaddr;
 
-#ifdef MEM_MAPPING
-       /* MM registers range. */
-       ioaddr = pci_iomap(pdev, 1, 0);
-       if (!ioaddr)
-               goto err_out_iounmap;
-#endif
+       if (np->rmon_enable) {
+               /* MM registers range. */
+               ioaddr = pci_iomap(pdev, 1, 0);
+               if (!ioaddr)
+                       goto err_out_iounmap;
+       }
+
        np->ioaddr = ioaddr;
        np->chip_id = chip_idx;
        np->pdev = pdev;
@@ -289,9 +300,8 @@ err_out_unmap_tx:
        dma_free_coherent(&pdev->dev, TX_TOTAL_SIZE, np->tx_ring,
                          np->tx_ring_dma);
 err_out_iounmap:
-#ifdef MEM_MAPPING
-       pci_iounmap(pdev, np->ioaddr);
-#endif
+       if (np->rmon_enable)
+               pci_iounmap(pdev, np->ioaddr);
        pci_iounmap(pdev, np->eeprom_addr);
 err_out_dev:
        free_netdev (dev);
@@ -578,7 +588,8 @@ static void rio_hw_init(struct net_device *dev)
        dw8(TxDMAPollPeriod, 0xff);
        dw8(RxDMABurstThresh, 0x30);
        dw8(RxDMAUrgentThresh, 0x30);
-       dw32(RmonStatMask, 0x0007ffff);
+       if (!np->rmon_enable)
+               dw32(RmonStatMask, 0x0007ffff);
        /* clear statistics */
        clear_stats (dev);
 
@@ -1076,9 +1087,6 @@ get_stats (struct net_device *dev)
 {
        struct netdev_private *np = netdev_priv(dev);
        void __iomem *ioaddr = np->ioaddr;
-#ifdef MEM_MAPPING
-       int i;
-#endif
        unsigned int stat_reg;
        unsigned long flags;
 
@@ -1123,10 +1131,10 @@ get_stats (struct net_device *dev)
        dr16(MacControlFramesXmtd);
        dr16(FramesWEXDeferal);
 
-#ifdef MEM_MAPPING
-       for (i = 0x100; i <= 0x150; i += 4)
-               dr32(i);
-#endif
+       if (np->rmon_enable)
+               for (int i = 0x100; i <= 0x150; i += 4)
+                       dr32(i);
+
        dr16(TxJumboFrames);
        dr16(RxJumboFrames);
        dr16(TCPCheckSumErrors);
@@ -1143,9 +1151,6 @@ clear_stats (struct net_device *dev)
 {
        struct netdev_private *np = netdev_priv(dev);
        void __iomem *ioaddr = np->ioaddr;
-#ifdef MEM_MAPPING
-       int i;
-#endif
 
        /* All statistics registers need to be acknowledged,
           else statistic overflow could cause problems */
@@ -1181,10 +1186,9 @@ clear_stats (struct net_device *dev)
        dr16(BcstFramesXmtdOk);
        dr16(MacControlFramesXmtd);
        dr16(FramesWEXDeferal);
-#ifdef MEM_MAPPING
-       for (i = 0x100; i <= 0x150; i += 4)
-               dr32(i);
-#endif
+       if (np->rmon_enable)
+               for (int i = 0x100; i <= 0x150; i += 4)
+                       dr32(i);
        dr16(TxJumboFrames);
        dr16(RxJumboFrames);
        dr16(TCPCheckSumErrors);
@@ -1810,9 +1814,8 @@ rio_remove1 (struct pci_dev *pdev)
                                  np->rx_ring_dma);
                dma_free_coherent(&pdev->dev, TX_TOTAL_SIZE, np->tx_ring,
                                  np->tx_ring_dma);
-#ifdef MEM_MAPPING
-               pci_iounmap(pdev, np->ioaddr);
-#endif
+               if (np->rmon_enable)
+                       pci_iounmap(pdev, np->ioaddr);
                pci_iounmap(pdev, np->eeprom_addr);
                free_netdev (dev);
                pci_release_regions (pdev);
index ba679025e86674fd382690c89686069f06456830..4788cc94639d1d7a40356138bd5414299476f73d 100644 (file)
@@ -403,6 +403,8 @@ struct netdev_private {
        u16 negotiate;          /* Negotiated media */
        int phy_addr;           /* PHY addresses. */
        u16 led_mode;           /* LED mode read from EEPROM (IP1000A only) */
+
+       bool rmon_enable;
 };
 
 /* The station address location in the EEPROM. */