net: dlink: enable RMON MMIO access on supported devices
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>
This commit is contained in:
committed by
Jakub Kicinski
parent
34355b6712
commit
7fc18f9476
@@ -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);
|
||||
|
||||
@@ -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. */
|
||||
|
||||
Reference in New Issue
Block a user