Re: [PATCH 2/2] ipg: redundancy with mii.h

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Pekka Enberg <[email protected]> :
[...]
> My initial patches are here:
> 
> http://www.cs.helsinki.fi/u/penberg/linux/ip1000/

Nice. Thanks.

> I consider your tree the master now. Please let me know when you have
> recreated the history, so I can clone your tree. Thanks.

The new serie is available in branch 'netdev-ipg' at
git://electric-eye.fr.zoreil.com/home/romieu/linux-2.6.git

Former branch 'netdev-ipg' was moved to 'netdev-ipg.log'.

I have added a new patch (see (way) below).

$ git log master..

commit 17adeb85054a693224a2ab7787a224c722bdd4eb
Author: Francois Romieu <[email protected]>
Date:   Fri May 5 01:42:12 2006 +0200

    ip1000: ethtool {get/set}_settings support
    
    The patch shoehorns the driver into the usual mii/ethtool framework.
    mii_mutex will prove useful when the link management tasks issued in
    irq context are moved to user/workqueue context. Next step.
    
    At least the current code should not be _too_ broken.
    
    Signed-off-by: Francois Romieu <[email protected]>

commit 997a02f4c4b3cf2ec0177ba33ffda6d550396eb7
Author: Francois Romieu <[email protected]>
Date:   Thu May 4 00:29:59 2006 +0200

    ip1000: remove forward declarations
    
    It makes no sense in a new driver.
    
    Signed-off-by: Francois Romieu <[email protected]>

commit b141c4ec3572f3151b2eb037ef5e7aba8d190445
Author: Francois Romieu <[email protected]>
Date:   Thu May 4 00:04:57 2006 +0200

    ip1000: replace #define with enum
    
    Added some underscores to improve readability.
    
    Signed-off-by: Francois Romieu <[email protected]>

commit 9d27e1ab51b2295d72ea254bbc8de5b5797a4139
Author: Francois Romieu <[email protected]>
Date:   Wed May 3 22:51:16 2006 +0200

    ip1000: removal of useless #defines
    
    IPG_TX_NOTBUSY apart (one occurence in ipg.c), the #defines appear
    nowhere in the sources.
    
    Signed-off-by: Francois Romieu <[email protected]>

commit 42ad0c39990c1897ee56dfc34bb4a7b2de76ace0
Author: Francois Romieu <[email protected]>
Date:   Wed May 3 22:44:47 2006 +0200

    ip1000: redundancy with mii.h - take II
    
    Replace a bunch of #define with their counterpart from mii.h
    
    It is applied to the usual MII registers this time.
    
    Signed-off-by: Francois Romieu <[email protected]>

commit be97a643f5d955208c0be7aa9e16a05c7737a2be
Author: Romieu Francois <[email protected]>
Date:   Tue May 2 23:25:44 2006 +0200

    ip1000: redundancy with mii.h
    
    Replace a bunch of #define with their counterpart from mii.h
    
    Signed-off-by: Francois Romieu <[email protected]>

commit 273a5a5f0815a35cf06faeafea6fc47503d364cb
Author: Romieu Francois <[email protected]>
Date:   Tue May 2 22:15:34 2006 +0200

    ip1000: sanitize the pci device table
    
    - vendor id belong to include/linux/pci_id.h ;
    - the pci table does not include all the devices in nics_supported ;
    - qualify the pci table as __devinitdata ;
    - kill 50 LOC.
    
    Signed-off-by: Francois Romieu <[email protected]>

commit e1e773d79369783d68fd7f66fffbe154929df837
Author: Romieu Francois <[email protected]>
Date:   Tue May 2 01:07:48 2006 +0200

    ip1000: plug leaks in the error path of ipg_nic_open
    
    Added ipg_{rx/tx}_clear() to factor out some code.
    
    Signed-off-by: Francois Romieu <[email protected]>

commit 9cb655fddfd2d169bc7574e849fa5eb179fef12c
Author: Romieu Francois <[email protected]>
Date:   Tue May 2 00:15:54 2006 +0200

    ip1000: leaks in ipg_probe
    
    The error paths are badly broken.
    
    Bonus:
    - remove duplicate initialization of sp;
    - remove useless NULL initialization of dev;
    - USE_IO_OPS is not used (and the driver does not seem to care about
      posted writes, rejoice).
    
    Signed-off-by: Francois Romieu <[email protected]>

commit 2b5d40c1c4cf795c31d2683bcdff646a8984115d
Author: Romieu Francois <[email protected]>
Date:   Mon May 1 23:52:37 2006 +0200

    ip1000: removal of unreachable code
    
    map/unmap is done in ipg_{probe/remove}
    
    Signed-off-by: Francois Romieu <[email protected]>

commit 5b8bde4d4c02e3d54672d0c431941d9357c35417
Author: Romieu Francois <[email protected]>
Date:   Mon May 1 22:40:29 2006 +0200

    ip1000: speed-up access to the PHY registers
    
    Reduce delays when reading/writing the PHY registers so we clock the
    MII management interface at 2.5 MHz (the maximum according to the
    datasheet) instead of 500 Hz.
    
    Signed-off-by: David Vrabel <[email protected]>

commit d4a621ceadb0e4ee83a644be4ffef8bdef687249
Author: David Vrabel <[email protected]>
Date:   Mon May 1 21:34:19 2006 +0200

    ip1000: root_dev removal and PHY initialization
    
    - Remove ether_crc_le() -- use crc32_le() instead.
    - No more nonsense with root_dev -- ipg_remove() now works.
    - Move PHY and MAC address initialization into the ipg_probe().
      It was previously filling in the MAC address on open which breaks
      some user space.
    - Folded ipg_nic_init into ipg_probe since it was broke otherwise.
    
    Signed-off-by: David Vrabel <[email protected]>

commit ae6f7b51bfb69a60062d390f10c83396c37f0301
Author: David Vrabel <[email protected]>
Date:   Mon May 1 13:20:49 2006 +0200

    ip1000: remove changelogs
    
    Signed-off-by: David Vrabel <[email protected]>

commit 7aeb86e2db5deac7d8357d6d794550999fd5e7c6
Author: Pekka Enberg <[email protected]>
Date:   Sun Apr 30 12:45:16 2006 +0300

    ip1000: alloc_etherdev already allocates memory for private data
    
    Signed-off-by: Pekka Enberg <[email protected]>

commit 49b94ecdf8124c988160585d460b1cc643ee07e0
Author: Pekka Enberg <[email protected]>
Date:   Sun Apr 30 12:42:02 2006 +0300

    ip1000: remove unused forward declarations
    
    Signed-off-by: Pekka Enberg <[email protected]>

commit e85531a2d8c23b6ff17b3a8cd6d14e6c09954240
Author: Pekka Enberg <[email protected]>
Date:   Sun Apr 30 12:16:58 2006 +0300

    ip1000: interrupt handler code cleanups
    
    Signed-off-by: Pekka Enberg <[email protected]>

commit 822b9f528c47df857514e33d1ad98a9a551a3b00
Author: Pekka Enberg <[email protected]>
Date:   Sun Apr 30 12:05:09 2006 +0300

    ip1000: rename baseaddr to ioaddr
    
    Signed-off-by: Pekka Enberg <[email protected]>

commit e8e5f8dece06429793074df6f956a8c4cb60c362
Author: Pekka Enberg <[email protected]>
Date:   Sun Apr 30 12:02:51 2006 +0300

    ip1000: remove device register write macros
    
    Signed-off-by: Pekka Enberg <[email protected]>

commit 8e1a207d9e0d355aa2949ef4e5710e8c8987b01b
Author: Pekka Enberg <[email protected]>
Date:   Sun Apr 30 11:41:01 2006 +0300

    ip1000: kill obfuscating register read macros
    
    Signed-off-by: Pekka Enberg <[email protected]>

commit fd3e0c5b3599375024e1e7fc3ddb00f7f5bc0c53
Author: Pekka Enberg <[email protected]>
Date:   Sun Apr 30 00:03:23 2006 +0300

    ip1000: use iomap for pio/mmio
    
    Signed-off-by: Pekka Enberg <[email protected]>

commit 7ed56b01680978afc5db87f684de81398366bf84
Author: Pekka Enberg <[email protected]>
Date:   Sat Apr 29 14:02:34 2006 +0300

    ip1000: use static for private symbols
    
    Signed-off-by: Pekka Enberg <[email protected]>

commit b83bac329befd061bb66377d33b1efd4dd39a931
Author: Pekka Enberg <[email protected]>
Date:   Sat Apr 29 13:19:36 2006 +0300

    ip1000: sparse fixes
    
    Signed-off-by: Pekka Enberg <[email protected]>

commit 65229dd8a40d887364f3aa60277ac3f0e8c64041
Author: Pekka Enberg <[email protected]>
Date:   Sat Apr 29 13:06:27 2006 +0300

    ip1000: iomem annotations
    
    Signed-off-by: Pekka Enberg <[email protected]>

commit d79a8a846188eee278f5b490b7f15c070f1245d4
Author: Pekka Enberg <[email protected]>
Date:   Sat Apr 29 12:41:45 2006 +0300

    ip1000: new gigabit ethernet device driver
    
    Signed-off-by: Pekka Enberg <[email protected]>

----------------8<-----------------------------------------------------------

Patch of the day:

The patch shoehorns the driver into the usual mii/ethtool framework.
mii_mutex will prove useful when the link management tasks issued in
irq context are moved to user/workqueue context. Next step.

At least the current code should not be _too_ broken.

Signed-off-by: Francois Romieu <[email protected]>

---

 drivers/net/ipg.c |  344 ++++++++++++++++++++---------------------------------
 drivers/net/ipg.h |    3 
 2 files changed, 130 insertions(+), 217 deletions(-)

8e15d782fa4a0f483a71faec7ba17697d9397e76
diff --git a/drivers/net/ipg.c b/drivers/net/ipg.c
index 31cde6c..5d19269 100644
--- a/drivers/net/ipg.c
+++ b/drivers/net/ipg.c
@@ -15,7 +15,9 @@
  * [email protected]
  */
 #include <linux/crc32.h>
+#include <linux/ethtool.h>
 #include <linux/mii.h>
+#include <linux/mutex.h>
 
 #define IPG_RX_RING_BYTES	(sizeof(struct RFD) * IPG_RFDLIST_LENGTH)
 #define IPG_TX_RING_BYTES	(sizeof(struct TFD) * IPG_TFDLIST_LENGTH)
@@ -161,8 +163,7 @@ static u16 read_phy_bit(void __iomem * i
 	return bit_data;
 }
 
-u16 read_phy_register(struct net_device * dev,
-		      int phy_address, int phy_register)
+static int mdio_read(struct net_device * dev, int phy_address, int phy_register)
 {
 	/* Read a register from the Physical Layer device located
 	 * on the IPG NIC, using the IPG PHYCTRL register.
@@ -176,7 +177,7 @@ u16 read_phy_register(struct net_device 
 	u8 databit;
 	u8 phyctrlpolarity;
 
-	IPG_DEBUG_MSG("read_phy_register\n");
+	IPG_DEBUG_MSG("mdio_read\n");
 
 	/* The GMII mangement frame structure for a read is as follows:
 	 *
@@ -274,8 +275,8 @@ u16 read_phy_register(struct net_device 
 	return field[6];
 }
 
-static void write_phy_register(struct net_device *dev,
-			       int phy_address, int phy_register, u16 writeval)
+static void mdio_write(struct net_device *dev,
+		       int phy_address, int phy_register, int val)
 {
 	/* Write to a register from the Physical Layer device located
 	 * on the IPG NIC, using the IPG PHYCTRL register.
@@ -289,7 +290,7 @@ static void write_phy_register(struct ne
 	u8 databit;
 	u8 phyctrlpolarity;
 
-	IPG_DEBUG_MSG("write_phy_register\n");
+	IPG_DEBUG_MSG("mdio_write\n");
 
 	/* The GMII mangement frame structure for a read is as follows:
 	 *
@@ -318,7 +319,7 @@ static void write_phy_register(struct ne
 	fieldlen[4] = 5;	/* REGAD */
 	field[5] = 0x0002;
 	fieldlen[5] = 2;	/* TA */
-	field[6] = writeval;
+	field[6] = val & 0xffff;
 	fieldlen[6] = 16;	/* DATA */
 	field[7] = 0x0000;
 	fieldlen[7] = 1;	/* IDLE */
@@ -486,7 +487,7 @@ static int ipg_tmi_fiber_detect(struct n
 
 	IPG_DEBUG_MSG("_tmi_fiber_detect\n");
 
-	phyid = read_phy_register(dev, phyaddr, MII_PHYSID1);
+	phyid = mdio_read(dev, phyaddr, MII_PHYSID1);
 
 	IPG_DEBUG_MSG("PHY ID = %x\n", phyid);
 
@@ -497,15 +498,14 @@ static int ipg_tmi_fiber_detect(struct n
 }
 #endif
 
+/* Find the GMII PHY address. */
 static int ipg_find_phyaddr(struct net_device *dev)
 {
-	/* Find the GMII PHY address. */
-
-	int i;
-	int phyaddr;
-	u32 status;
+	int phyaddr, i;
 
 	for (i = 0; i < 32; i++) {
+		u32 status;
+
 		/* Search for the correct PHY address among 32 possible. */
 		phyaddr = (IPG_NIC_PHY_ADDRESS + i) % 32;
 
@@ -513,13 +513,13 @@ static int ipg_find_phyaddr(struct net_d
 		   GMII_PHY_ID1
 		 */
 
-		status = read_phy_register(dev, phyaddr, MII_BMSR);
+		status = mdio_read(dev, phyaddr, MII_BMSR);
 
 		if ((status != 0xFFFF) && (status != 0))
 			return phyaddr;
 	}
 
-	return -1;
+	return 0x1f;
 }
 
 #ifdef NOTGRACE
@@ -618,10 +618,11 @@ #endif
 		       dev->name);
 		return -EILSEQ;
 	}
+	sp->mii_if.phy_id = phyaddr;
 
 	IPG_DEBUG_MSG("GMII/MII PHY address = %x\n", phyaddr);
 
-	status = read_phy_register(dev, phyaddr, MII_BMSR);
+	status = mdio_read(dev, phyaddr, MII_BMSR);
 
 	printk("PHYStatus = %x \n", status);
 	if ((status & BMSR_ANEGCAPABLE) == 0) {
@@ -631,8 +632,8 @@ #endif
 		return -EILSEQ;
 	}
 
-	advertisement = read_phy_register(dev, phyaddr, MII_ADVERTISE);
-	linkpartner_ability = read_phy_register(dev, phyaddr, MII_LPA);
+	advertisement = mdio_read(dev, phyaddr, MII_ADVERTISE);
+	linkpartner_ability = mdio_read(dev, phyaddr, MII_LPA);
 
 	printk("PHYadvertisement=%x LinkPartner=%x \n", advertisement,
 	       linkpartner_ability);
@@ -660,8 +661,8 @@ #endif
 			/* In 1000BASE-X using IPG's internal PCS
 			 * layer, so write to the GMII duplex bit.
 			 */
-			write_phy_register(dev, phyaddr, MII_BMCR,
-				read_phy_register(dev, phyaddr, MII_BMCR) |
+			mdio_write(dev, phyaddr, MII_BMCR,
+				mdio_read(dev, phyaddr, MII_BMCR) |
 					   ADVERTISE_1000HALF); // Typo ?
 
 		} else {
@@ -670,8 +671,8 @@ #endif
 			/* In 1000BASE-X using IPG's internal PCS
 			 * layer, so write to the GMII duplex bit.
 			 */
-			write_phy_register(dev, phyaddr, MII_BMCR,
-				read_phy_register(dev, phyaddr, MII_BMCR) &
+			mdio_write(dev, phyaddr, MII_BMCR,
+				mdio_read(dev, phyaddr, MII_BMCR) &
 					   ~ADVERTISE_1000HALF); // Typo ?
 		}
 	}
@@ -683,10 +684,8 @@ #endif
 		 * link partner abilities exchanged via next page
 		 * transfers.
 		 */
-		gigadvertisement =
-			read_phy_register(dev, phyaddr, MII_CTRL1000);
-		giglinkpartner_ability =
-			read_phy_register(dev, phyaddr, MII_STAT1000);
+		gigadvertisement = mdio_read(dev, phyaddr, MII_CTRL1000);
+		giglinkpartner_ability = mdio_read(dev, phyaddr, MII_STAT1000);
 
 		/* Compare the full duplex bits in the 1000BASE-T GMII
 		 * registers for the local device, and the link partner.
@@ -795,11 +794,10 @@ #define LPA_PAUSE_ANY	(LPA_1000XPAUSE_AS
 			/* PAUSE is not being advertised. Advertise
 			 * PAUSE and restart auto-negotiation.
 			 */
-			write_phy_register(dev, phyaddr, MII_ADVERTISE,
+			mdio_write(dev, phyaddr, MII_ADVERTISE,
 				(advertisement |
 				 ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM));
-			write_phy_register(dev, phyaddr, MII_BMCR,
-					   BMCR_ANRESTART);
+			mdio_write(dev, phyaddr, MII_BMCR, BMCR_ANRESTART);
 
 			return -EAGAIN;
 		}
@@ -845,10 +843,9 @@ #define LPA_PAUSE_ANY	(LPA_1000XPAUSE_AS
 			/* PAUSE is not being advertised. Advertise
 			 * PAUSE and restart auto-negotiation.
 			 */
-			write_phy_register(dev, phyaddr, MII_ADVERTISE,
-					   advertisement | ADVERTISE_PAUSE_CAP);
-			write_phy_register(dev, phyaddr, MII_BMCR,
-					   BMCR_ANRESTART);
+			mdio_write(dev, phyaddr, MII_ADVERTISE,
+				   advertisement | ADVERTISE_PAUSE_CAP);
+			mdio_write(dev, phyaddr, MII_BMCR, BMCR_ANRESTART);
 			return -EAGAIN;
 		}
 
@@ -2671,8 +2668,7 @@ static void ipg_set_phy_default_param(un
 				address = *phy_param;
 				value = *(phy_param + 1);
 				phy_param += 2;
-				write_phy_register(dev,
-						   phy_address, address, value);
+				mdio_write(dev, phy_address, address, value);
 				length -= 4;
 			}
 
@@ -2710,14 +2706,47 @@ static int read_eeprom(struct net_device
 	return ret;
 }
 
+static void ipg_init_mii(struct net_device *dev)
+{
+	struct ipg_nic_private *sp = netdev_priv(dev);
+	struct mii_if_info *mii_if = &sp->mii_if;
+	int phyaddr;
+
+	mii_if->dev          = dev;
+	mii_if->mdio_read    = mdio_read;
+	mii_if->mdio_write   = mdio_write;
+	mii_if->phy_id_mask  = 0x1f;
+	mii_if->reg_num_mask = 0x1f;
+
+	mii_if->phy_id = phyaddr = ipg_find_phyaddr(dev);
+
+	if (phyaddr != 0x1f) {
+		u16 mii_phyctrl, mii_1000cr;
+		u8 revisionid = 0;
+
+		mii_1000cr  = mdio_read(dev, phyaddr, MII_CTRL1000);
+		mii_1000cr |= ADVERTISE_1000FULL | ADVERTISE_1000HALF |
+			GMII_PHY_1000BASETCONTROL_PreferMaster;
+		mdio_write(dev, phyaddr, MII_CTRL1000, mii_1000cr);
+
+		mii_phyctrl = mdio_read(dev, phyaddr, MII_BMCR);
+
+		/* Set default phyparam */
+		pci_read_config_byte(sp->pdev, PCI_REVISION_ID, &revisionid);
+		ipg_set_phy_default_param(revisionid, dev, phyaddr);
+
+		/* Reset PHY */
+		mii_phyctrl |= BMCR_RESET | BMCR_ANRESTART;
+		mdio_write(dev, phyaddr, MII_BMCR, mii_phyctrl);
+
+	}
+}
+
 static int ipg_hw_init(struct net_device *dev)
 {
-	int phyaddr = 0;
-	int error = 0;
-	int i;
-	void __iomem *ioaddr = ipg_ioaddr(dev);
-	u8 revisionid = 0;
 	struct ipg_nic_private *sp = netdev_priv(dev);
+	void __iomem *ioaddr = sp->ioaddr;
+	int i, rc;
 
 	/* Reset all functions within the IPG. Do not assert
 	 * RST_OUT as not compatible with some PHYs.
@@ -2729,34 +2758,11 @@ static int ipg_hw_init(struct net_device
 	/* Read LED Mode Configuration from EEPROM */
 	sp->LED_Mode = read_eeprom(dev, 6);
 
-	error = ipg_reset(dev, i);
-	if (error < 0) {
-		return error;
-	}
-
-	ioaddr = ipg_ioaddr(dev);
-
-	/* Reset PHY. */
-	phyaddr = ipg_find_phyaddr(dev);
-
-	if (phyaddr != -1) {
-		u16 mii_phyctrl, mii_1000cr;
-		mii_1000cr =
-			read_phy_register(dev, phyaddr, MII_CTRL1000);
-		write_phy_register(dev, phyaddr, MII_CTRL1000,
-			mii_1000cr | ADVERTISE_1000FULL | ADVERTISE_1000HALF |
-				   GMII_PHY_1000BASETCONTROL_PreferMaster);
-
-		mii_phyctrl = read_phy_register(dev, phyaddr, MII_BMCR);
-		/* Set default phyparam */
-		pci_read_config_byte(sp->pdev, PCI_REVISION_ID, &revisionid);
-		ipg_set_phy_default_param(revisionid, dev, phyaddr);
-
-		/* reset Phy */
-		write_phy_register(dev, phyaddr, MII_BMCR,
-			(mii_phyctrl | BMCR_RESET | BMCR_ANRESTART));
+	rc = ipg_reset(dev, i);
+	if (rc < 0)
+		goto out;
 
-	}
+	ipg_init_mii(dev);
 
 	/* Read MAC Address from EERPOM Jesse20040128EEPROM_VALUE */
 	sp->StationAddr0 = read_eeprom(dev, 16);
@@ -2774,161 +2780,21 @@ static int ipg_hw_init(struct net_device
 	dev->dev_addr[3] = (ioread16(ioaddr + STATION_ADDRESS_1) & 0xff00) >> 8;
 	dev->dev_addr[4] =  ioread16(ioaddr + STATION_ADDRESS_2) & 0x00ff;
 	dev->dev_addr[5] = (ioread16(ioaddr + STATION_ADDRESS_2) & 0xff00) >> 8;
-
-	return 0;
+out:
+	return rc;
 }
 
-static int ipg_nic_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
+static int ipg_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
-	/* IOCTL commands for IPG NIC.
-	 *
-	 * SIOCDEVPRIVATE       nothing
-	 * SIOCDEVPRIVATE+1     register read
-	 *                      ifr_data[0] = 0x08, 0x10, 0x20
-	 *                      ifr_data[1] = register offset
-	 *                      ifr_data[2] = value read
-	 * SIOCDEVPRIVATE+2     register write
-	 *                      ifr_data[0] = 0x08, 0x10, 0x20
-	 *                      ifr_data[1] = register offset
-	 *                      ifr_data[2] = value to write
-	 * SIOCDEVPRIVATE+3     GMII register read
-	 *                      ifr_data[1] = register offset
-	 * SIOCDEVPRIVATE+4     GMII register write
-	 *                      ifr_data[1] = register offset
-	 *                      ifr_data[2] = value to write
-	 * SIOCDEVPRIVATE+5     PCI register read
-	 *                      ifr_data[0] = 0x08, 0x10, 0x20
-	 *                      ifr_data[1] = register offset
-	 *                      ifr_data[2] = value read
-	 * SIOCDEVPRIVATE+6     PCI register write
-	 *                      ifr_data[0] = 0x08, 0x10, 0x20
-	 *                      ifr_data[1] = register offset
-	 *                      ifr_data[2] = value to write
-	 *
-	 */
-
-	u8 val8;
-	u16 val16;
-	u32 val32;
-	unsigned int *data;
-	int phyaddr = 0;
-	void __iomem *ioaddr = ipg_ioaddr(dev);
 	struct ipg_nic_private *sp = netdev_priv(dev);
+	struct mii_ioctl_data *data = if_mii(ifr);
+	int rc;
 
-	IPG_DEBUG_MSG("_nic_do_ioctl\n");
-
-	data = (unsigned int *)&req->ifr_data;
-
-	switch (cmd) {
-	case SIOCDEVPRIVATE:
-		return 0;
-
-	case SIOCDEVPRIVATE + 1:
-		switch (data[0]) {
-		case 0x08:
-			data[2] = ioread8(ioaddr + data[1]);
-			return 0;
-
-		case 0x10:
-			data[2] = ioread16(ioaddr + data[1]);
-			return 0;
-
-		case 0x20:
-			data[2] = ioread32(ioaddr + data[1]);
-			return 0;
-
-		default:
-			data[2] = 0x00;
-			return -EINVAL;
-		}
-
-	case SIOCDEVPRIVATE + 2:
-		switch (data[0]) {
-		case 0x08:
-			iowrite8(data[2], ioaddr + data[1]);
-			return 0;
-
-		case 0x10:
-			iowrite16(data[2], ioaddr + data[1]);
-			return 0;
-
-		case 0x20:
-			iowrite32(data[2], ioaddr + data[1]);
-			return 0;
-
-		default:
-			return -EINVAL;
-		}
-
-	case SIOCDEVPRIVATE + 3:
-		phyaddr = ipg_find_phyaddr(dev);
-
-		if (phyaddr == -1)
-			return -EINVAL;
-
-		data[2] = read_phy_register(dev, phyaddr, data[1]);
-
-		return 0;
-
-	case SIOCDEVPRIVATE + 4:
-		phyaddr = ipg_find_phyaddr(dev);
-
-		if (phyaddr == -1)
-			return -EINVAL;
-
-		write_phy_register(dev, phyaddr, data[1], (u16) data[2]);
-
-		return 0;
-
-	case SIOCDEVPRIVATE + 5:
-		switch (data[0]) {
-		case 0x08:
-			pci_read_config_byte(sp->pdev, data[1], &val8);
-			data[2] = (unsigned int)val8;
-			return 0;
-
-		case 0x10:
-			pci_read_config_word(sp->pdev, data[1], &val16);
-			data[2] = (unsigned int)val16;
-			return 0;
-
-		case 0x20:
-			pci_read_config_dword(sp->pdev, data[1], &val32);
-			data[2] = (unsigned int)val32;
-			return 0;
-
-		default:
-			data[2] = 0x00;
-			return -EINVAL;
-		}
-
-	case SIOCDEVPRIVATE + 6:
-		switch (data[0]) {
-		case 0x08:
-			pci_write_config_byte(sp->pdev, data[1], (u8) data[2]);
-			return 0;
-
-		case 0x10:
-			pci_write_config_word(sp->pdev, data[1], (u16) data[2]);
-			return 0;
-
-		case 0x20:
-			pci_write_config_dword(sp->pdev, data[1],
-					       (u32) data[2]);
-			return 0;
+	mutex_lock(&sp->mii_mutex);
+	rc = generic_mii_ioctl(&sp->mii_if, data, cmd, NULL);
+	mutex_unlock(&sp->mii_mutex);
 
-		default:
-			return -EINVAL;
-		}
-
-	case SIOCSIFMTU:
-		{
-			return 0;
-		}
-
-	default:
-		return -EOPNOTSUPP;
-	}
+	return rc;
 }
 
 static int ipg_nic_change_mtu(struct net_device *dev, int new_mtu)
@@ -2953,6 +2819,48 @@ static int ipg_nic_change_mtu(struct net
 	return 0;
 }
 
+static int ipg_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct ipg_nic_private *sp = netdev_priv(dev);
+	int rc;
+
+	mutex_lock(&sp->mii_mutex);
+	rc = mii_ethtool_gset(&sp->mii_if, cmd);
+	mutex_unlock(&sp->mii_mutex);
+
+	return rc;
+}
+
+static int ipg_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct ipg_nic_private *sp = netdev_priv(dev);
+	int rc;
+
+	mutex_lock(&sp->mii_mutex);
+	rc = mii_ethtool_sset(&sp->mii_if, cmd);
+	mutex_unlock(&sp->mii_mutex);
+
+	return rc;
+}
+
+static int ipg_nway_reset(struct net_device *dev)
+{
+	struct ipg_nic_private *sp = netdev_priv(dev);
+	int rc;
+
+	mutex_lock(&sp->mii_mutex);
+	rc = mii_nway_restart(&sp->mii_if);
+	mutex_unlock(&sp->mii_mutex);
+
+	return rc;
+}
+
+static struct ethtool_ops ipg_ethtool_ops = {
+	.get_settings = ipg_get_settings,
+	.set_settings = ipg_set_settings,
+	.nway_reset   = ipg_nway_reset,
+};
+
 static void ipg_remove(struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
@@ -3011,6 +2919,7 @@ static int __devinit ipg_probe(struct pc
 
 	sp = netdev_priv(dev);
 	spin_lock_init(&sp->lock);
+	mutex_init(&sp->mii_mutex);
 
 	/* Declare IPG NIC functions for Ethernet device methods.
 	 */
@@ -3019,11 +2928,12 @@ static int __devinit ipg_probe(struct pc
 	dev->hard_start_xmit = &ipg_nic_hard_start_xmit;
 	dev->get_stats = &ipg_nic_get_stats;
 	dev->set_multicast_list = &ipg_nic_set_multicast_list;
-	dev->do_ioctl = &ipg_nic_do_ioctl;
+	dev->do_ioctl = ipg_ioctl;
 	dev->change_mtu = &ipg_nic_change_mtu;
 
 	SET_MODULE_OWNER(dev);
 	SET_NETDEV_DEV(dev, &pdev->dev);
+	SET_ETHTOOL_OPS(dev, &ipg_ethtool_ops);
 
 	rc = pci_request_regions(pdev, DRV_NAME);
 	if (rc)
diff --git a/drivers/net/ipg.h b/drivers/net/ipg.h
index 6c55b0b..58b1417 100644
--- a/drivers/net/ipg.h
+++ b/drivers/net/ipg.h
@@ -870,6 +870,9 @@ #endif
 	u16 StationAddr1;	/* Station Address in EEPROM Reg 0x11 */
 	u16 StationAddr2;	/* Station Address in EEPROM Reg 0x12 */
 
+	struct mutex		mii_mutex;
+	struct mii_if_info	mii_if;
+
 #ifdef IPG_DEBUG
 	int TFDunavailCount;
 	int RFDlistendCount;
-- 
1.3.1

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux