r8169: get ethtool settings through the generic mii helper

It avoids to report unsupported link capabilities with
the fast-ethernet only 8101/8102.

Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
Tested-by: Martin Capitanio <martin@capitanio.org>
Fixed-by: Ivan Vecera <ivecera@redhat.com>
Cc: Edward Hsu <edward_hsu@realtek.com.tw>
This commit is contained in:
Francois Romieu 2008-07-26 14:26:06 +02:00
parent d6f8aa8586
commit ccdffb9a88

View File

@ -370,8 +370,9 @@ struct ring_info {
}; };
enum features { enum features {
RTL_FEATURE_WOL = (1 << 0), RTL_FEATURE_WOL = (1 << 0),
RTL_FEATURE_MSI = (1 << 1), RTL_FEATURE_MSI = (1 << 1),
RTL_FEATURE_GMII = (1 << 2),
}; };
struct rtl8169_private { struct rtl8169_private {
@ -406,13 +407,15 @@ struct rtl8169_private {
struct vlan_group *vlgrp; struct vlan_group *vlgrp;
#endif #endif
int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex); int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex);
void (*get_settings)(struct net_device *, struct ethtool_cmd *); int (*get_settings)(struct net_device *, struct ethtool_cmd *);
void (*phy_reset_enable)(void __iomem *); void (*phy_reset_enable)(void __iomem *);
void (*hw_start)(struct net_device *); void (*hw_start)(struct net_device *);
unsigned int (*phy_reset_pending)(void __iomem *); unsigned int (*phy_reset_pending)(void __iomem *);
unsigned int (*link_ok)(void __iomem *); unsigned int (*link_ok)(void __iomem *);
struct delayed_work task; struct delayed_work task;
unsigned features; unsigned features;
struct mii_if_info mii;
}; };
MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>"); MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
@ -482,6 +485,23 @@ static int mdio_read(void __iomem *ioaddr, int reg_addr)
return value; return value;
} }
static void rtl_mdio_write(struct net_device *dev, int phy_id, int location,
int val)
{
struct rtl8169_private *tp = netdev_priv(dev);
void __iomem *ioaddr = tp->mmio_addr;
mdio_write(ioaddr, location, val);
}
static int rtl_mdio_read(struct net_device *dev, int phy_id, int location)
{
struct rtl8169_private *tp = netdev_priv(dev);
void __iomem *ioaddr = tp->mmio_addr;
return mdio_read(ioaddr, location);
}
static void rtl8169_irq_mask_and_ack(void __iomem *ioaddr) static void rtl8169_irq_mask_and_ack(void __iomem *ioaddr)
{ {
RTL_W16(IntrMask, 0x0000); RTL_W16(IntrMask, 0x0000);
@ -850,7 +870,7 @@ static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc,
#endif #endif
static void rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd)
{ {
struct rtl8169_private *tp = netdev_priv(dev); struct rtl8169_private *tp = netdev_priv(dev);
void __iomem *ioaddr = tp->mmio_addr; void __iomem *ioaddr = tp->mmio_addr;
@ -867,65 +887,29 @@ static void rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd)
cmd->speed = SPEED_1000; cmd->speed = SPEED_1000;
cmd->duplex = DUPLEX_FULL; /* Always set */ cmd->duplex = DUPLEX_FULL; /* Always set */
return 0;
} }
static void rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd) static int rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd)
{ {
struct rtl8169_private *tp = netdev_priv(dev); struct rtl8169_private *tp = netdev_priv(dev);
void __iomem *ioaddr = tp->mmio_addr;
u8 status;
cmd->supported = SUPPORTED_10baseT_Half | return mii_ethtool_gset(&tp->mii, cmd);
SUPPORTED_10baseT_Full |
SUPPORTED_100baseT_Half |
SUPPORTED_100baseT_Full |
SUPPORTED_1000baseT_Full |
SUPPORTED_Autoneg |
SUPPORTED_TP;
cmd->autoneg = 1;
cmd->advertising = ADVERTISED_TP | ADVERTISED_Autoneg;
if (tp->phy_auto_nego_reg & ADVERTISE_10HALF)
cmd->advertising |= ADVERTISED_10baseT_Half;
if (tp->phy_auto_nego_reg & ADVERTISE_10FULL)
cmd->advertising |= ADVERTISED_10baseT_Full;
if (tp->phy_auto_nego_reg & ADVERTISE_100HALF)
cmd->advertising |= ADVERTISED_100baseT_Half;
if (tp->phy_auto_nego_reg & ADVERTISE_100FULL)
cmd->advertising |= ADVERTISED_100baseT_Full;
if (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)
cmd->advertising |= ADVERTISED_1000baseT_Full;
status = RTL_R8(PHYstatus);
if (status & _1000bpsF)
cmd->speed = SPEED_1000;
else if (status & _100bps)
cmd->speed = SPEED_100;
else if (status & _10bps)
cmd->speed = SPEED_10;
if (status & TxFlowCtrl)
cmd->advertising |= ADVERTISED_Asym_Pause;
if (status & RxFlowCtrl)
cmd->advertising |= ADVERTISED_Pause;
cmd->duplex = ((status & _1000bpsF) || (status & FullDup)) ?
DUPLEX_FULL : DUPLEX_HALF;
} }
static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{ {
struct rtl8169_private *tp = netdev_priv(dev); struct rtl8169_private *tp = netdev_priv(dev);
unsigned long flags; unsigned long flags;
int rc;
spin_lock_irqsave(&tp->lock, flags); spin_lock_irqsave(&tp->lock, flags);
tp->get_settings(dev, cmd); rc = tp->get_settings(dev, cmd);
spin_unlock_irqrestore(&tp->lock, flags); spin_unlock_irqrestore(&tp->lock, flags);
return 0; return rc;
} }
static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs, static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs,
@ -1513,7 +1497,7 @@ static const struct rtl_cfg_info {
unsigned int align; unsigned int align;
u16 intr_event; u16 intr_event;
u16 napi_event; u16 napi_event;
unsigned msi; unsigned features;
} rtl_cfg_infos [] = { } rtl_cfg_infos [] = {
[RTL_CFG_0] = { [RTL_CFG_0] = {
.hw_start = rtl_hw_start_8169, .hw_start = rtl_hw_start_8169,
@ -1522,7 +1506,7 @@ static const struct rtl_cfg_info {
.intr_event = SYSErr | LinkChg | RxOverflow | .intr_event = SYSErr | LinkChg | RxOverflow |
RxFIFOOver | TxErr | TxOK | RxOK | RxErr, RxFIFOOver | TxErr | TxOK | RxOK | RxErr,
.napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow,
.msi = 0 .features = RTL_FEATURE_GMII
}, },
[RTL_CFG_1] = { [RTL_CFG_1] = {
.hw_start = rtl_hw_start_8168, .hw_start = rtl_hw_start_8168,
@ -1531,7 +1515,7 @@ static const struct rtl_cfg_info {
.intr_event = SYSErr | LinkChg | RxOverflow | .intr_event = SYSErr | LinkChg | RxOverflow |
TxErr | TxOK | RxOK | RxErr, TxErr | TxOK | RxOK | RxErr,
.napi_event = TxErr | TxOK | RxOK | RxOverflow, .napi_event = TxErr | TxOK | RxOK | RxOverflow,
.msi = RTL_FEATURE_MSI .features = RTL_FEATURE_GMII | RTL_FEATURE_MSI
}, },
[RTL_CFG_2] = { [RTL_CFG_2] = {
.hw_start = rtl_hw_start_8101, .hw_start = rtl_hw_start_8101,
@ -1540,7 +1524,7 @@ static const struct rtl_cfg_info {
.intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout | .intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout |
RxFIFOOver | TxErr | TxOK | RxOK | RxErr, RxFIFOOver | TxErr | TxOK | RxOK | RxErr,
.napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow,
.msi = RTL_FEATURE_MSI .features = RTL_FEATURE_MSI
} }
}; };
@ -1552,7 +1536,7 @@ static unsigned rtl_try_msi(struct pci_dev *pdev, void __iomem *ioaddr,
u8 cfg2; u8 cfg2;
cfg2 = RTL_R8(Config2) & ~MSIEnable; cfg2 = RTL_R8(Config2) & ~MSIEnable;
if (cfg->msi) { if (cfg->features & RTL_FEATURE_MSI) {
if (pci_enable_msi(pdev)) { if (pci_enable_msi(pdev)) {
dev_info(&pdev->dev, "no MSI. Back to INTx.\n"); dev_info(&pdev->dev, "no MSI. Back to INTx.\n");
} else { } else {
@ -1578,6 +1562,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data; const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data;
const unsigned int region = cfg->region; const unsigned int region = cfg->region;
struct rtl8169_private *tp; struct rtl8169_private *tp;
struct mii_if_info *mii;
struct net_device *dev; struct net_device *dev;
void __iomem *ioaddr; void __iomem *ioaddr;
unsigned int i; unsigned int i;
@ -1602,6 +1587,14 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
tp->pci_dev = pdev; tp->pci_dev = pdev;
tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT); tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT);
mii = &tp->mii;
mii->dev = dev;
mii->mdio_read = rtl_mdio_read;
mii->mdio_write = rtl_mdio_write;
mii->phy_id_mask = 0x1f;
mii->reg_num_mask = 0x1f;
mii->supports_gmii = !!(cfg->features & RTL_FEATURE_GMII);
/* enable device (incl. PCI PM wakeup and hotplug setup) */ /* enable device (incl. PCI PM wakeup and hotplug setup) */
rc = pci_enable_device(pdev); rc = pci_enable_device(pdev);
if (rc < 0) { if (rc < 0) {