From: Jesse Huang <[EMAIL PROTECTED]>

ipg_config_autoneg rewrite

Change Logs:
    ipg_config_autoneg rewrite

---

 drivers/net/ipg.c |  307
++++++-----------------------------------------------
 1 files changed, 32 insertions(+), 275 deletions(-)

c3f6df15430f9c05e19f36b8485b31110d52a091
diff --git a/drivers/net/ipg.c b/drivers/net/ipg.c
index a996c45..f859107 100644
--- a/drivers/net/ipg.c
+++ b/drivers/net/ipg.c
@@ -484,26 +484,18 @@ static int ipg_config_autoneg(struct net
 {
        struct ipg_nic_private *sp = netdev_priv(dev);
        void __iomem *ioaddr = sp->ioaddr;
+       u8 phyctrl;
        u32 asicctrl;
-       u32 mac_ctl;
-       int phyaddr = 0;
-       u16 status = 0;
-       u16 advertisement;
-       u16 linkpartner_ability;
-       u16 gigadvertisement;
-       u16 giglinkpartner_ability;
-       u16 techabilities;
        int fiber;
        int gig;
        int fullduplex;
        int txflowcontrol;
        int rxflowcontrol;
-       u8 phyctrl;
 
        IPG_DEBUG_MSG("_config_autoneg\n");
 
        asicctrl = ioread32(ioaddr + ASIC_CTRL);
-       phyctrl = ioread8(ioaddr + PHY_CTRL);
+       phyctrl = ioread32(ioaddr + PHY_CTRL);
 
        /* Set flags for use in resolving auto-negotation, assuming
         * non-1000Mbps, half duplex, no flow control.
@@ -519,14 +511,13 @@ static int ipg_config_autoneg(struct net
         */
        sp->tenmbpsmode = 0;
 
-       printk("Link speed = ");
+       printk(KERN_INFO "Link speed = ");
 
        /* Determine actual speed of operation. */
        switch (phyctrl & IPG_PC_LINK_SPEED) {
        case IPG_PC_LINK_SPEED_10MBPS:
                printk("10Mbps.\n");
-               printk(KERN_INFO "%s: 10Mbps operational mode enabled.\n",
-                      dev->name);
+               printk("%s: 10Mbps operational mode enabled.\n",dev->name);
                sp->tenmbpsmode = 1;
                break;
        case IPG_PC_LINK_SPEED_100MBPS:
@@ -538,283 +529,49 @@ static int ipg_config_autoneg(struct net
                break;
        default:
                printk("undefined!\n");
-       }
-
-       fiber = ipg_sti_fiber_detect(dev);
-
-       /* Determine if auto-negotiation resolution is necessary.
-        * First check for fiber based media 10/100 media.
-        */
-       if ((fiber == 1) &&
-           (asicctrl & (IPG_AC_PHY_SPEED10 | IPG_AC_PHY_SPEED100))) {
-               printk(KERN_INFO
-                      "%s: Fiber based PHY, setting full duplex, no flow
control.\n",
-                      dev->name);
-
-               mac_ctl  = ioread32(ioaddr + MAC_CTRL);
-               mac_ctl |= IPG_MC_DUPLEX_SELECT_FD;
-               mac_ctl &= ~IPG_MC_TX_FLOW_CONTROL_ENABLE;
-               mac_ctl &= ~IPG_MC_RX_FLOW_CONTROL_ENABLE;
-
-               iowrite32(IPG_MC_RSVD_MASK & mac_ctl, ioaddr + MAC_CTRL);
-
                return 0;
        }
 
-       /* Determine if PHY is auto-negotiation capable. */
-       phyaddr = ipg_find_phyaddr(dev);
-
-       if (phyaddr == -1) {
-               printk(KERN_INFO
-                      "%s: Error on read to GMII/MII Status register.\n",
-                      dev->name);
-               return -EILSEQ;
-       }
-       sp->mii_if.phy_id = phyaddr;
-
-       IPG_DEBUG_MSG("GMII/MII PHY address = %x\n", phyaddr);
-
-       status = mdio_read(dev, phyaddr, MII_BMSR);
-
-       printk("PHYStatus = %x \n", status);
-       if ((status & BMSR_ANEGCAPABLE) == 0) {
-               printk(KERN_INFO
-                      "%s: Error PHY unable to perform auto-negotiation.\n",
-                      dev->name);
-               return -EILSEQ;
-       }
-
-       advertisement = mdio_read(dev, phyaddr, MII_ADVERTISE);
-       linkpartner_ability = mdio_read(dev, phyaddr, MII_LPA);
-
-       printk("PHYadvertisement=%x LinkPartner=%x \n", advertisement,
-              linkpartner_ability);
-       if ((advertisement == 0xFFFF) || (linkpartner_ability == 0xFFFF)) {
-               printk(KERN_INFO
-                      "%s: Error on read to GMII/MII registers 4 and/or 5.\n",
-                      dev->name);
-               return -EILSEQ;
+       if (phyctrl & IPG_PC_DUPLEX_STATUS) {
+               fullduplex = 1;
+               txflowcontrol = 1;
+               rxflowcontrol = 1;
+       } else {
+               fullduplex = 0;
+               txflowcontrol = 0;
+               rxflowcontrol = 0;
        }
 
-       fiber = ipg_tmi_fiber_detect(dev, phyaddr);
-
-       /* Resolve full/half duplex if 1000BASE-X. */
-       if ((gig == 1) && (fiber == 1)) {
-               int bmcr;
-               /*
-                * Compare the full duplex bits in the GMII registers
-                * for the local device, and the link partner. If these
-                * bits are logic 1 in both registers, configure the
-                * IPG for full duplex operation.
-                */
-               bmcr = mdio_read(dev, phyaddr, MII_BMCR);
+       /* Configure full duplex, and flow control. */
+       if (fullduplex == 1) {
+               /* Configure IPG for full duplex operation. */
+               printk(KERN_INFO "setting full duplex, ");
 
-               if ((advertisement & ADVERTISE_1000XFULL) ==
-                   (linkpartner_ability & ADVERTISE_1000XFULL)) {
-                       fullduplex = 1;
+               iowrite32(ioread32(ioaddr + MAC_CTRL) | IPG_MC_DUPLEX_SELECT_FD,
ioaddr + MAC_CTRL);
 
-                       /* In 1000BASE-X using IPG's internal PCS
-                        * layer, so write to the GMII duplex bit.
-                        */
-                       bmcr |= ADVERTISE_1000HALF; // Typo ?
+               if (txflowcontrol == 1) {
+                       printk("TX flow control");
+                       iowrite32(ioread32(ioaddr + MAC_CTRL) |
IPG_MC_TX_FLOW_CONTROL_ENABLE, ioaddr + MAC_CTRL);
                } else {
-                       fullduplex = 0;
-
-                       /* In 1000BASE-X using IPG's internal PCS
-                        * layer, so write to the GMII duplex bit.
-                        */
-                       bmcr &= ~ADVERTISE_1000HALF; // Typo ?
+                       printk("no TX flow control");
+                       iowrite32(ioread32(ioaddr + MAC_CTRL) &
~IPG_MC_TX_FLOW_CONTROL_ENABLE, ioaddr + MAC_CTRL);
                }
-               mdio_write(dev, phyaddr, MII_BMCR, bmcr);
-       }
 
-       /* Resolve full/half duplex if 1000BASE-T. */
-       if ((gig == 1) && (fiber == 0)) {
-               /* Read the 1000BASE-T "Control" and "Status"
-                * registers which represent the advertised and
-                * link partner abilities exchanged via next page
-                * transfers.
-                */
-               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.
-                * If these bits are logic 1 in both registers, configure
-                * the IPG for full duplex operation.
-                */
-               if ((gigadvertisement & ADVERTISE_1000FULL) &&
-                   (giglinkpartner_ability & ADVERTISE_1000FULL)) {
-                       fullduplex = 1;
+               if (rxflowcontrol == 1) {
+                       printk(", RX flow control.");
+                       iowrite32(ioread32(ioaddr+MAC_CTRL) | 
IPG_MC_RX_FLOW_CONTROL_ENABLE,
ioaddr + MAC_CTRL);
                } else {
-                       fullduplex = 0;
-               }
-       }
-
-       /* Resolve full/half duplex for 10/100BASE-T. */
-       if (gig == 0) {
-               /* Autonegotiation Priority Resolution algorithm, as defined in
-                * IEEE 802.3 Annex 28B.
-                */
-               if (((advertisement & ADVERTISE_SLCT) ==
-                    MII_PHY_SELECTOR_IEEE8023) &&
-                   ((linkpartner_ability & ADVERTISE_SLCT) ==
-                    MII_PHY_SELECTOR_IEEE8023)) {
-                       techabilities = (advertisement & linkpartner_ability &
-                                        MII_PHY_TECHABILITYFIELD);
-
-                       fullduplex = 0;
-
-                       /* 10BASE-TX half duplex is lowest priority. */
-                       if (techabilities & LPA_10HALF)
-                               fullduplex = 0;
-
-                       if (techabilities & LPA_10FULL)
-                               fullduplex = 1;
-
-                       if (techabilities & LPA_100HALF)
-                               fullduplex = 0;
-
-                       if (techabilities & LPA_100BASE4)
-                               fullduplex = 0;
-
-                       /* 100BASE-TX half duplex is highest priority. 
*///Sorbica full
duplex ?
-                       if (techabilities & LPA_100FULL)
-                               fullduplex = 1;
-
-                       if (fullduplex == 1) {
-                               /* If in full duplex mode, determine if PAUSE
-                                * functionality is supported by the local
-                                * device, and the link partner.
-                                */
-                               if (techabilities & LPA_PAUSE_CAP) {
-                                       txflowcontrol = 1;
-                                       rxflowcontrol = 1;
-                               } else {
-                                       txflowcontrol = 0;
-                                       rxflowcontrol = 0;
-                               }
-                       }
+                       printk(", no RX flow control.");
+                       iowrite32(ioread32(ioaddr+MAC_CTRL) &
~IPG_MC_RX_FLOW_CONTROL_ENABLE, ioaddr + MAC_CTRL);
                }
-       }
 
-       /* If in 1000Mbps, fiber, and full duplex mode, resolve
-        * 1000BASE-X PAUSE capabilities. */
-       if ((fullduplex == 1) && (fiber == 1) && (gig == 1)) {
-               /* In full duplex mode, resolve PAUSE
-                * functionality.
-                */
-               u8 flow_ctl;
-#define LPA_PAUSE_ANY  (LPA_1000XPAUSE_ASYM | LPA_1000XPAUSE)
-
-               flow_ctl  = (advertisement & LPA_PAUSE_ANY) >> 5;
-               flow_ctl |= (linkpartner_ability & LPA_PAUSE_ANY) >> 7;
-               switch (flow_ctl) {
-               case 0x7:
-                       txflowcontrol = 1;
-                       rxflowcontrol = 0;
-                       break;
-
-               case 0xA:
-               case 0xB:
-               case 0xE:
-               case 0xF:
-                       txflowcontrol = 1;
-                       rxflowcontrol = 1;
-                       break;
-
-               case 0xD:
-                       txflowcontrol = 0;
-                       rxflowcontrol = 1;
-                       break;
+               printk("\n");
+       } else {
+               /* Configure IPG for half duplex operation. */
+               printk(KERN_INFO "setting half duplex, no TX flow control, no
RX flow control.\n");
 
-               default:
-                       txflowcontrol = 0;
-                       rxflowcontrol = 0;
-               }
+               iowrite32(ioread32(ioaddr+MAC_CTRL) & ~IPG_MC_DUPLEX_SELECT_FD &
~IPG_MC_TX_FLOW_CONTROL_ENABLE & ~IPG_MC_RX_FLOW_CONTROL_ENABLE, ioaddr
+ MAC_CTRL);
        }
-
-       /*
-        * If in 1000Mbps, non-fiber, full duplex mode, resolve
-        * 1000BASE-T PAUSE capabilities.
-        */
-       if ((fullduplex == 1) && (fiber == 0) && (gig == 1)) {
-               /*
-                * Make sure the PHY is advertising we are PAUSE capable.
-                * Otherwise advertise PAUSE and restart auto-negotiation.
-                */
-#define ADVERTISE_PAUSE_ANY (ADVERTISE_PAUSE_CAP |
ADVERTISE_PAUSE_ASYM)
-
-               if (!(ADVERTISE_PAUSE_ANY & advertisement)) {
-                       advertisement |= ADVERTISE_PAUSE_ANY;
-                       mdio_write(dev, phyaddr, MII_ADVERTISE, advertisement);
-                       mdio_write(dev, phyaddr, MII_BMCR, BMCR_ANRESTART);
-
-                       return -EAGAIN;
-               }
-               /* In full duplex mode, resolve PAUSE functionality. */
-               switch (((ADVERTISE_PAUSE_ANY & advertisement) >> 0x8) |
-                       ((ADVERTISE_PAUSE_ANY & linkpartner_ability) >> 0xa)) {
-               case 0x7:
-                       txflowcontrol = 1;
-                       rxflowcontrol = 0;
-                       break;
-
-               case 0xA:
-               case 0xB:
-               case 0xE:
-               case 0xF:
-                       txflowcontrol = 1;
-                       rxflowcontrol = 1;
-                       break;
-
-               case 0xD:
-                       txflowcontrol = 0;
-                       rxflowcontrol = 1;
-                       break;
-
-               default:
-                       txflowcontrol = 0;
-                       rxflowcontrol = 0;
-               }
-       }
-
-       /*
-        * If in 10/100Mbps, non-fiber, full duplex mode, assure
-        * 10/100BASE-T PAUSE capabilities are advertised.
-        * Otherwise advertise PAUSE and restart auto-negotiation.
-        */
-       if ((fullduplex == 1) && (fiber == 0) && (gig == 0) &&
-           !(advertisement & ADVERTISE_PAUSE_CAP)) {
-               advertisement |= ADVERTISE_PAUSE_CAP;
-               mdio_write(dev, phyaddr, MII_ADVERTISE, advertisement);
-               mdio_write(dev, phyaddr, MII_BMCR, BMCR_ANRESTART);
-               return -EAGAIN;
-       }
-
-       printk(KERN_INFO "%s: %s based PHY, ", dev->name,
-               (fiber == 1) ? "fiber" : "copper");
-
-       /* Configure full duplex, and flow control. */
-
-       mac_ctl  = ioread32(ioaddr + MAC_CTRL);
-
-       mac_ctl &= ~IPG_MC_DUPLEX_SELECT_FD;
-       mac_ctl &= ~IPG_MC_TX_FLOW_CONTROL_ENABLE;
-       mac_ctl &= ~IPG_MC_RX_FLOW_CONTROL_ENABLE;
-
-       if (fullduplex == 1) {
-               mac_ctl |= IPG_MC_DUPLEX_SELECT_FD;
-
-               if (txflowcontrol == 1)
-                       mac_ctl |= IPG_MC_TX_FLOW_CONTROL_ENABLE;
-
-               if (rxflowcontrol == 1)
-                       mac_ctl |= IPG_MC_RX_FLOW_CONTROL_ENABLE;
-       }
-
-       iowrite32(IPG_MC_RSVD_MASK & mac_ctl, ioaddr + MAC_CTRL);
-
        return 0;
 }
 
-- 
1.3.2



-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to