On Tuesday 02 June 2009, Andreas Mohr wrote:
> Hi,
>
> On Sun, Mar 01, 2009 at 10:24:12PM +0100, Andreas Mohr wrote:
> > The whole thing has been somewhat low-priority indeed
> > given the probable age of some non-MII contenders. OTOH it would be quite
> > sad (and locally problematic) to see support for those non-MII cards
> > vanish come 2.6.29.
> > Subsequently it would then be nice to devise non-MII support
> > in some structured way that enables us to support them without
> > much burden (code-wise) on proper standards-supporting MII cards.
>
> OK, so.......
>
> Frankly, I didn't want to see my card slowly and painfully getting
> unsupported (which, conversely, results in a PC cut off from ANY kernel
> upgrades...). Thus I decided to clean up my previous still-too-messy patch
> by removing all dirty "are we MII?" - noooo - skip it! barriers.
>
> ChangeLog:
> Restore support for cards with MII-lacking PHYs as compared to
> removed pre-2.6.29 eepro100 driver:
> use full low-level MII I/O access abstraction by providing clean
> PHY-specific mdio_ctrl() functions for either standard MII-compliant cards,
> slightly special ones or non-MII PHY ones.
>
>
>
> We now have another netdev_priv member for mdio_ctrl(),
> thus we have some array indirection, but we save some additional opcodes
> for specific phy_82552_v handling in the common case.
>
>
> Patch tested on 2.6.30-rc7 (cold boot results in working network
> access - this mail typed.....), checkpatch.pl'ed.
>
> Obviously this patch needs quite some testing (-mmotm?),
> since it also touches phy_82552_v functionality.
>
> Oh, and this will be my very ultimately last attempt at this,
> if there's no serious inclusion of something similar to this,
> then I'll just give up.
> [and install my nice WGA'd DRM'd and billed/invaded-by-the-minute
> Windows...]
>
> Thanks!
>
> Signed-off-by: Andreas Mohr <a...@lisas.de>
>
> --- linux-2.6.30-rc7/drivers/net/e100.c.orig  2009-06-02 19:27:19.000000000
> +0200 +++ linux-2.6.30-rc7/drivers/net/e100.c 2009-06-02 23:31:25.000000000
> +0200 @@ -143,6 +143,8 @@
>   *   FIXES:
>   * 2005/12/02 - Michael O'Donnell <Michael.ODonnell at stratus dot com>
>   *   - Stratus87247: protect MDI control register manipulations
> + * 2009/06/01 - Andreas Mohr <andi at lisas dot de>
> + *      - add clean lowlevel I/O emulation for cards with MII-lacking PHYs
>   */
>
>  #include <linux/module.h>
> @@ -372,6 +374,7 @@
>
>  enum eeprom_offsets {
>       eeprom_cnfg_mdix  = 0x03,
> +     eeprom_phy_iface  = 0x06,
>       eeprom_id         = 0x0A,
>       eeprom_config_asf = 0x0D,
>       eeprom_smbus_addr = 0x90,
> @@ -381,6 +384,18 @@
>       eeprom_mdix_enabled = 0x0080,
>  };
>
> +enum eeprom_phy_iface {
> +     NonSuchPhy = 0,
> +     I82553AB,
> +     I82553C,
> +     I82503,
> +     DP83840,
> +     S80C240,
> +     S80C24,
> +     I82555,
> +     DP83840A = 10,
> +};
> +
>  enum eeprom_id {
>       eeprom_id_wol = 0x0020,
>  };
> @@ -545,6 +560,7 @@
>       u32 msg_enable                          ____cacheline_aligned;
>       struct net_device *netdev;
>       struct pci_dev *pdev;
> +     u16 (*mdio_ctrl)(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data);
>
>       struct rx *rxs                          ____cacheline_aligned;
>       struct rx *rx_to_use;
> @@ -899,7 +915,21 @@
>       return err;
>  }
>
> -static u16 mdio_ctrl(struct nic *nic, u32 addr, u32 dir, u32 reg, u16
> data) +static int mdio_read(struct net_device *netdev, int addr, int reg)
> +{
> +     struct nic *nic = netdev_priv(netdev);
> +     return nic->mdio_ctrl(nic, addr, mdi_read, reg, 0);
> +}
> +
> +static void mdio_write(struct net_device *netdev, int addr, int reg, int
> data) +{
> +     struct nic *nic = netdev_priv(netdev);
> +
> +     nic->mdio_ctrl(nic, addr, mdi_write, reg, data);
> +}
> +
> +/* the standard mdio_ctrl() function for usual MII-compliant hardware */
> +static u16 mdio_ctrl_hw(struct nic *nic, u32 addr, u32 dir, u32 reg, u16
> data) {
>       u32 data_out = 0;
>       unsigned int i;
> @@ -938,30 +968,83 @@
>       return (u16)data_out;
>  }
>
> -static int mdio_read(struct net_device *netdev, int addr, int reg)
> -{
> -     return mdio_ctrl(netdev_priv(netdev), addr, mdi_read, reg, 0);
> +/* slightly tweaked mdio_ctrl() function for phy_82552_v specifics */
> +static u16 mdio_ctrl_phy_82552_v(struct nic *nic,
> +                              u32 addr,
> +                              u32 dir,
> +                              u32 reg,
> +                              u16 data)
> +{
> +     if ((reg == MII_BMCR) && (dir == mdi_write)) {
> +             if (data & (BMCR_ANRESTART | BMCR_ANENABLE)) {
> +                     u16 advert = mdio_read(nic->netdev, nic->mii.phy_id,
> +                                                     MII_ADVERTISE);
> +
> +                     /*
> +                      * Workaround Si issue where sometimes the part will not
> +                      * autoneg to 100Mbps even when advertised.
> +                      */
> +                     if (advert & ADVERTISE_100FULL)
> +                             data |= BMCR_SPEED100 | BMCR_FULLDPLX;
> +                     else if (advert & ADVERTISE_100HALF)
> +                             data |= BMCR_SPEED100;
> +             }
> +     }
> +     return mdio_ctrl_hw(nic, addr, dir, reg, data);
>  }
>
> -static void mdio_write(struct net_device *netdev, int addr, int reg, int
> data) -{
> -     struct nic *nic = netdev_priv(netdev);
> -
> -     if  ((nic->phy == phy_82552_v) && (reg == MII_BMCR) &&
> -          (data & (BMCR_ANRESTART | BMCR_ANENABLE))) {
> -             u16 advert = mdio_read(netdev, nic->mii.phy_id, MII_ADVERTISE);
> -
> -             /*
> -              * Workaround Si issue where sometimes the part will not
> -              * autoneg to 100Mbps even when advertised.
> -              */
> -             if (advert & ADVERTISE_100FULL)
> -                     data |= BMCR_SPEED100 | BMCR_FULLDPLX;
> -             else if (advert & ADVERTISE_100HALF)
> -                     data |= BMCR_SPEED100;
> +/* Fully software-emulated mdio_ctrl() function for cards without
> + * MII-compliant PHYs.
> + * For now, this is mainly geared towards 80c24 support; in case of
> further + * requirements for other types (i82503, ...?) either extend this
> mechanism + * or split it, whichever is cleaner.
> + */
> +static u16 mdio_ctrl_phy_mii_emulated(struct nic *nic,
> +                                   u32 addr,
> +                                   u32 dir,
> +                                   u32 reg,
> +                                   u16 data)
> +{
> +     /* might need to allocate a netdev_priv'ed register array eventually
> +      * to be able to record state changes, but for now
> +      * some fully hardcoded register handling ought to be ok I guess. */
> +
> +     if (dir == mdi_read) {
> +             switch (reg) {
> +             case MII_BMCR:
> +                     /* Auto-negotiation, right? */
> +                     return  BMCR_ANENABLE |
> +                             BMCR_FULLDPLX;
> +             case MII_BMSR:
> +                     return  BMSR_LSTATUS /* for mii_link_ok() */ |
> +                             BMSR_ANEGCAPABLE |
> +                             BMSR_10FULL;
> +             case MII_ADVERTISE:
> +                     /* 80c24 is a "combo card" PHY, right? */
> +                     return  ADVERTISE_10HALF |
> +                             ADVERTISE_10FULL;
> +             default:
> +                     DPRINTK(HW, DEBUG,
> +             "%s:addr=%d, reg=%d, data=0x%04X: unimplemented emulation!\n",
> +             dir == mdi_read ? "READ" : "WRITE", addr, reg, data);
> +                     return 0xFFFF;
> +             }
> +     } else {
> +             switch (reg) {
> +             default:
> +                     DPRINTK(HW, DEBUG,
> +             "%s:addr=%d, reg=%d, data=0x%04X: unimplemented emulation!\n",
> +             dir == mdi_read ? "READ" : "WRITE", addr, reg, data);
> +                     return 0xFFFF;
> +             }
>       }
> -
> -     mdio_ctrl(netdev_priv(netdev), addr, mdi_write, reg, data);
> +}
> +static inline int e100_phy_supports_mii(struct nic *nic)
> +{
> +     /* for now, just check it by comparing whether we
> +        are using MII software emulation.
> +     */
> +     return (nic->mdio_ctrl != mdio_ctrl_phy_mii_emulated);
>  }
>
>  static void e100_get_defaults(struct nic *nic)
> @@ -1013,7 +1096,8 @@
>       config->standard_stat_counter = 0x1;    /* 1=standard, 0=extended */
>       config->rx_discard_short_frames = 0x1;  /* 1=discard, 0=pass */
>       config->tx_underrun_retry = 0x3;        /* # of underrun retries */
> -     config->mii_mode = 0x1;                 /* 1=MII mode, 0=503 mode */
> +     if (e100_phy_supports_mii(nic))
> +             config->mii_mode = 1;           /* 1=MII mode, 0=i82503 mode */
>       config->pad10 = 0x6;
>       config->no_source_addr_insertion = 0x1; /* 1=no, 0=yes */
>       config->preamble_length = 0x2;          /* 0=1, 1=3, 2=7, 3=15 bytes */
> @@ -1270,6 +1354,44 @@
>               offsetof(struct mem, dump_buf));
>  }
>
> +static int e100_phy_check_without_mii(struct nic *nic)
> +{
> +     u8 phy_type;
> +     int without_mii;
> +
> +     phy_type = (nic->eeprom[eeprom_phy_iface] >> 8) & 0x0f;
> +
> +     switch (phy_type) {
> +     case NonSuchPhy: /* Non-MII PHY; UNTESTED! */
> +     case I82503: /* Non-MII PHY; UNTESTED! */
> +     case S80C24: /* Non-MII PHY; tested and working */
> +     {
> +             /* paragraph from the FreeBSD driver, "FXP_PHY_80C24":
> +              * The Seeq 80c24 AutoDUPLEX(tm) Ethernet Interface Adapter
> +              * doesn't have a programming interface of any sort.  The
> +              * media is sensed automatically based on how the link partner
> +              * is configured.  This is, in essence, manual configuration.
> +              */
> +             DPRINTK(PROBE, INFO,
> +                      "found MII-less i82503 or 80c24 or other PHY\n");
> +
> +             nic->mdio_ctrl = mdio_ctrl_phy_mii_emulated;
> +             nic->mii.phy_id = 0; /* is this ok for an MII-less PHY? */
> +
> +             /* these might be needed for certain MII-less cards...
> +              * nic->flags |= ich;
> +              * nic->flags |= ich_10h_workaround; */
> +
> +             without_mii = 1;
> +     }
> +     break;
> +     default:
> +             without_mii = 0;
> +             break;
> +     }
> +     return without_mii;
> +}
> +
>  #define NCONFIG_AUTO_SWITCH  0x0080
>  #define MII_NSC_CONG         MII_RESV1
>  #define NSC_CONG_ENABLE              0x0100
> @@ -1290,9 +1412,21 @@
>               if (!((bmcr == 0xFFFF) || ((stat == 0) && (bmcr == 0))))
>                       break;
>       }
> -     DPRINTK(HW, DEBUG, "phy_addr = %d\n", nic->mii.phy_id);
> -     if (addr == 32)
> -             return -EAGAIN;
> +     if (addr == 32) {
> +             /* uhoh, no PHY detected: check whether we seem to be some
> +              * weird, rare variant which is *known* to not have any MII.
> +              * But do this AFTER MII checking only, since this does
> +              * lookup of EEPROM values which may easily be unreliable. */
> +             if (e100_phy_check_without_mii(nic))
> +                     return 0; /* simply return and hope for the best */
> +             else {
> +                     /* for unknown cases log a fatal error */
> +                     DPRINTK(HW, ERR,
> +                             "Failed to locate any known PHY, aborting.\n");
> +                     return -EAGAIN;
> +             }
> +     } else
> +             DPRINTK(HW, DEBUG, "phy_addr = %d\n", nic->mii.phy_id);
>
>       /* Isolate all the PHY ids */
>       for (addr = 0; addr < 32; addr++)
> @@ -1320,6 +1454,9 @@
>       if (nic->phy == phy_82552_v) {
>               u16 advert = mdio_read(netdev, nic->mii.phy_id, MII_ADVERTISE);
>
> +             /* assign special tweaked mdio_ctrl() function */
> +             nic->mdio_ctrl = mdio_ctrl_phy_82552_v;
> +
>               /* Workaround Si not advertising flow-control during autoneg */
>               advert |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
>               mdio_write(netdev, nic->mii.phy_id, MII_ADVERTISE, advert);
> @@ -2585,6 +2722,7 @@
>       nic->netdev = netdev;
>       nic->pdev = pdev;
>       nic->msg_enable = (1 << debug) - 1;
> +     nic->mdio_ctrl = mdio_ctrl_hw;
>       pci_set_drvdata(pdev, netdev);
>
>       if ((err = pci_enable_device(pdev))) {
>
> ---------------------------------------------------------------------------
>--- OpenSolaris 2009.06 is a cutting edge operating system for enterprises
> looking to deploy the next generation of Solaris that includes the latest
> innovations from Sun and the OpenSource community. Download a copy and
> enjoy capabilities such as Networking, Storage and Virtualization. Go to:
> http://p.sf.net/sfu/opensolaris-get
> _______________________________________________
> E1000-devel mailing list
> E1000-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/e1000-devel


I am having trouble applying this patch.  I am trying to apply it to the
OpenWrt build system, which is driven by quilt (I have no experience of
quilt to know if this makes a difference).  One thing I did have to do was to
unwrap some of the lines, and it is possible that I have not done that 
correctly, and I have some places where the original source file seems to
have a tab in it and the patch has a space (or is it the other way around
I got myself confused).  I get a rather bald malformed patch message from
quilt.

Anyway, is there somewhere I can download a vanilla form of this patch?
Is it in a VCS somewhere that I can fetch?

Regards

David

------------------------------------------------------------------------------
OpenSolaris 2009.06 is a cutting edge operating system for enterprises 
looking to deploy the next generation of Solaris that includes the latest 
innovations from Sun and the OpenSource community. Download a copy and 
enjoy capabilities such as Networking, Storage and Virtualization. 
Go to: http://p.sf.net/sfu/opensolaris-get
_______________________________________________
E1000-devel mailing list
E1000-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/e1000-devel

Reply via email to