forked from Minki/linux
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:
parent
d6f8aa8586
commit
ccdffb9a88
@ -370,8 +370,9 @@ struct ring_info {
|
||||
};
|
||||
|
||||
enum features {
|
||||
RTL_FEATURE_WOL = (1 << 0),
|
||||
RTL_FEATURE_MSI = (1 << 1),
|
||||
RTL_FEATURE_WOL = (1 << 0),
|
||||
RTL_FEATURE_MSI = (1 << 1),
|
||||
RTL_FEATURE_GMII = (1 << 2),
|
||||
};
|
||||
|
||||
struct rtl8169_private {
|
||||
@ -406,13 +407,15 @@ struct rtl8169_private {
|
||||
struct vlan_group *vlgrp;
|
||||
#endif
|
||||
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 (*hw_start)(struct net_device *);
|
||||
unsigned int (*phy_reset_pending)(void __iomem *);
|
||||
unsigned int (*link_ok)(void __iomem *);
|
||||
struct delayed_work task;
|
||||
unsigned features;
|
||||
|
||||
struct mii_if_info mii;
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
RTL_W16(IntrMask, 0x0000);
|
||||
@ -850,7 +870,7 @@ static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc,
|
||||
|
||||
#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);
|
||||
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->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);
|
||||
void __iomem *ioaddr = tp->mmio_addr;
|
||||
u8 status;
|
||||
|
||||
cmd->supported = SUPPORTED_10baseT_Half |
|
||||
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;
|
||||
return mii_ethtool_gset(&tp->mii, cmd);
|
||||
}
|
||||
|
||||
static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
|
||||
{
|
||||
struct rtl8169_private *tp = netdev_priv(dev);
|
||||
unsigned long flags;
|
||||
int rc;
|
||||
|
||||
spin_lock_irqsave(&tp->lock, flags);
|
||||
|
||||
tp->get_settings(dev, cmd);
|
||||
rc = tp->get_settings(dev, cmd);
|
||||
|
||||
spin_unlock_irqrestore(&tp->lock, flags);
|
||||
return 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
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;
|
||||
u16 intr_event;
|
||||
u16 napi_event;
|
||||
unsigned msi;
|
||||
unsigned features;
|
||||
} rtl_cfg_infos [] = {
|
||||
[RTL_CFG_0] = {
|
||||
.hw_start = rtl_hw_start_8169,
|
||||
@ -1522,7 +1506,7 @@ static const struct rtl_cfg_info {
|
||||
.intr_event = SYSErr | LinkChg | RxOverflow |
|
||||
RxFIFOOver | TxErr | TxOK | RxOK | RxErr,
|
||||
.napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow,
|
||||
.msi = 0
|
||||
.features = RTL_FEATURE_GMII
|
||||
},
|
||||
[RTL_CFG_1] = {
|
||||
.hw_start = rtl_hw_start_8168,
|
||||
@ -1531,7 +1515,7 @@ static const struct rtl_cfg_info {
|
||||
.intr_event = SYSErr | LinkChg | RxOverflow |
|
||||
TxErr | TxOK | RxOK | RxErr,
|
||||
.napi_event = TxErr | TxOK | RxOK | RxOverflow,
|
||||
.msi = RTL_FEATURE_MSI
|
||||
.features = RTL_FEATURE_GMII | RTL_FEATURE_MSI
|
||||
},
|
||||
[RTL_CFG_2] = {
|
||||
.hw_start = rtl_hw_start_8101,
|
||||
@ -1540,7 +1524,7 @@ static const struct rtl_cfg_info {
|
||||
.intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout |
|
||||
RxFIFOOver | TxErr | TxOK | RxOK | RxErr,
|
||||
.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;
|
||||
|
||||
cfg2 = RTL_R8(Config2) & ~MSIEnable;
|
||||
if (cfg->msi) {
|
||||
if (cfg->features & RTL_FEATURE_MSI) {
|
||||
if (pci_enable_msi(pdev)) {
|
||||
dev_info(&pdev->dev, "no MSI. Back to INTx.\n");
|
||||
} 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 unsigned int region = cfg->region;
|
||||
struct rtl8169_private *tp;
|
||||
struct mii_if_info *mii;
|
||||
struct net_device *dev;
|
||||
void __iomem *ioaddr;
|
||||
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->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) */
|
||||
rc = pci_enable_device(pdev);
|
||||
if (rc < 0) {
|
||||
|
Loading…
Reference in New Issue
Block a user