aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrancois Romieu <romieu@fr.zoreil.com>2005-07-30 07:10:21 -0400
committerJeff Garzik <jgarzik@pobox.com>2005-07-30 18:20:59 -0400
commit43afb949a955a7d88f4baf43d5c676bf4c31ff6c (patch)
treee179f7694439d8668c6f0691a8b468d20746ede3
parent4405d3b5ef0a870e8d70ee4a3d050c89fcc40a86 (diff)
[PATCH] sis190: ethtool/mii support.
ethtool/mii support Bug: disabling autonegotiation and setting the link parameters at the same time does not provide the expected result. More investigation is needed. Note: past the initial probe/open time, the link is managed from user-space or accessed through sis190_phy_task, i.e. in a usermode context. Whence the very limited locking needs. Signed-off-by: Francois Romieu <romieu@fr.zoreil.com> Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
-rw-r--r--drivers/net/sis190.c60
1 files changed, 60 insertions, 0 deletions
diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c
index e374cf43fed0..ff4f24e5f59c 100644
--- a/drivers/net/sis190.c
+++ b/drivers/net/sis190.c
@@ -21,6 +21,7 @@
21#include <linux/module.h> 21#include <linux/module.h>
22#include <linux/moduleparam.h> 22#include <linux/moduleparam.h>
23#include <linux/netdevice.h> 23#include <linux/netdevice.h>
24#include <linux/rtnetlink.h>
24#include <linux/etherdevice.h> 25#include <linux/etherdevice.h>
25#include <linux/ethtool.h> 26#include <linux/ethtool.h>
26#include <linux/pci.h> 27#include <linux/pci.h>
@@ -230,6 +231,7 @@ struct sis190_private {
230 struct work_struct phy_task; 231 struct work_struct phy_task;
231 struct timer_list timer; 232 struct timer_list timer;
232 u32 msg_enable; 233 u32 msg_enable;
234 struct mii_if_info mii_if;
233}; 235};
234 236
235const static struct { 237const static struct {
@@ -308,6 +310,20 @@ static int mdio_read(void __iomem *ioaddr, int reg)
308 return (u16) (SIS_R32(GMIIControl) >> EhnMIIdataShift); 310 return (u16) (SIS_R32(GMIIControl) >> EhnMIIdataShift);
309} 311}
310 312
313static void __mdio_write(struct net_device *dev, int phy_id, int reg, int val)
314{
315 struct sis190_private *tp = netdev_priv(dev);
316
317 mdio_write(tp->mmio_addr, reg, val);
318}
319
320static int __mdio_read(struct net_device *dev, int phy_id, int reg)
321{
322 struct sis190_private *tp = netdev_priv(dev);
323
324 return mdio_read(tp->mmio_addr, reg);
325}
326
311static int sis190_read_eeprom(void __iomem *ioaddr, u32 reg) 327static int sis190_read_eeprom(void __iomem *ioaddr, u32 reg)
312{ 328{
313 unsigned int i; 329 unsigned int i;
@@ -790,6 +806,8 @@ static void sis190_phy_task(void * data)
790 void __iomem *ioaddr = tp->mmio_addr; 806 void __iomem *ioaddr = tp->mmio_addr;
791 u16 val; 807 u16 val;
792 808
809 rtnl_lock();
810
793 val = mdio_read(ioaddr, MII_BMCR); 811 val = mdio_read(ioaddr, MII_BMCR);
794 if (val & BMCR_RESET) { 812 if (val & BMCR_RESET) {
795 // FIXME: needlessly high ? -- FR 02/07/2005 813 // FIXME: needlessly high ? -- FR 02/07/2005
@@ -843,6 +861,8 @@ static void sis190_phy_task(void * data)
843 p->msg); 861 p->msg);
844 netif_carrier_on(dev); 862 netif_carrier_on(dev);
845 } 863 }
864
865 rtnl_unlock();
846} 866}
847 867
848static void sis190_phy_timer(unsigned long __opaque) 868static void sis190_phy_timer(unsigned long __opaque)
@@ -1150,6 +1170,13 @@ static struct net_device * __devinit sis190_init_board(struct pci_dev *pdev)
1150 tp->pci_dev = pdev; 1170 tp->pci_dev = pdev;
1151 tp->mmio_addr = ioaddr; 1171 tp->mmio_addr = ioaddr;
1152 1172
1173 tp->mii_if.dev = dev;
1174 tp->mii_if.mdio_read = __mdio_read;
1175 tp->mii_if.mdio_write = __mdio_write;
1176 // tp->mii_if.phy_id = XXX;
1177 tp->mii_if.phy_id_mask = 0x1f;
1178 tp->mii_if.reg_num_mask = 0x1f;
1179
1153 sis190_irq_mask_and_ack(ioaddr); 1180 sis190_irq_mask_and_ack(ioaddr);
1154 1181
1155 sis190_soft_reset(ioaddr); 1182 sis190_soft_reset(ioaddr);
@@ -1216,6 +1243,20 @@ static void sis190_set_speed_auto(struct net_device *dev)
1216 BMCR_ANENABLE | BMCR_ANRESTART | BMCR_RESET); 1243 BMCR_ANENABLE | BMCR_ANRESTART | BMCR_RESET);
1217} 1244}
1218 1245
1246static int sis190_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
1247{
1248 struct sis190_private *tp = netdev_priv(dev);
1249
1250 return mii_ethtool_gset(&tp->mii_if, cmd);
1251}
1252
1253static int sis190_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
1254{
1255 struct sis190_private *tp = netdev_priv(dev);
1256
1257 return mii_ethtool_sset(&tp->mii_if, cmd);
1258}
1259
1219static void sis190_get_drvinfo(struct net_device *dev, 1260static void sis190_get_drvinfo(struct net_device *dev,
1220 struct ethtool_drvinfo *info) 1261 struct ethtool_drvinfo *info)
1221{ 1262{
@@ -1245,6 +1286,13 @@ static void sis190_get_regs(struct net_device *dev, struct ethtool_regs *regs,
1245 spin_unlock_irqrestore(&tp->lock, flags); 1286 spin_unlock_irqrestore(&tp->lock, flags);
1246} 1287}
1247 1288
1289static int sis190_nway_reset(struct net_device *dev)
1290{
1291 struct sis190_private *tp = netdev_priv(dev);
1292
1293 return mii_nway_restart(&tp->mii_if);
1294}
1295
1248static u32 sis190_get_msglevel(struct net_device *dev) 1296static u32 sis190_get_msglevel(struct net_device *dev)
1249{ 1297{
1250 struct sis190_private *tp = netdev_priv(dev); 1298 struct sis190_private *tp = netdev_priv(dev);
@@ -1260,14 +1308,25 @@ static void sis190_set_msglevel(struct net_device *dev, u32 value)
1260} 1308}
1261 1309
1262static struct ethtool_ops sis190_ethtool_ops = { 1310static struct ethtool_ops sis190_ethtool_ops = {
1311 .get_settings = sis190_get_settings,
1312 .set_settings = sis190_set_settings,
1263 .get_drvinfo = sis190_get_drvinfo, 1313 .get_drvinfo = sis190_get_drvinfo,
1264 .get_regs_len = sis190_get_regs_len, 1314 .get_regs_len = sis190_get_regs_len,
1265 .get_regs = sis190_get_regs, 1315 .get_regs = sis190_get_regs,
1266 .get_link = ethtool_op_get_link, 1316 .get_link = ethtool_op_get_link,
1267 .get_msglevel = sis190_get_msglevel, 1317 .get_msglevel = sis190_get_msglevel,
1268 .set_msglevel = sis190_set_msglevel, 1318 .set_msglevel = sis190_set_msglevel,
1319 .nway_reset = sis190_nway_reset,
1269}; 1320};
1270 1321
1322static int sis190_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1323{
1324 struct sis190_private *tp = netdev_priv(dev);
1325
1326 return !netif_running(dev) ? -EINVAL :
1327 generic_mii_ioctl(&tp->mii_if, if_mii(ifr), cmd, NULL);
1328}
1329
1271static int __devinit sis190_init_one(struct pci_dev *pdev, 1330static int __devinit sis190_init_one(struct pci_dev *pdev,
1272 const struct pci_device_id *ent) 1331 const struct pci_device_id *ent)
1273{ 1332{
@@ -1308,6 +1367,7 @@ static int __devinit sis190_init_one(struct pci_dev *pdev,
1308 1367
1309 dev->open = sis190_open; 1368 dev->open = sis190_open;
1310 dev->stop = sis190_close; 1369 dev->stop = sis190_close;
1370 dev->do_ioctl = sis190_ioctl;
1311 dev->get_stats = sis190_get_stats; 1371 dev->get_stats = sis190_get_stats;
1312 dev->tx_timeout = sis190_tx_timeout; 1372 dev->tx_timeout = sis190_tx_timeout;
1313 dev->watchdog_timeo = SIS190_TX_TIMEOUT; 1373 dev->watchdog_timeo = SIS190_TX_TIMEOUT;