Since nobody with a working PCI_PRODUCT_ATTANSIC_L2C seems interested,
and the devices newly added in this diff are showing up more often
in submitted dmesg than the L2C version matched by the current driver,
I intend to commit this tomorrow unless there are objections.


On 2011/05/16 11:16, Stuart Henderson wrote:
> So far, only had reports from L1C and the new devices (which is
> not the point of sending out this sort of diff). This is a fairly
> large diff and changes behaviour for existing devices.
> 
> Has anyone with a currently-working L2C tested this to make sure
> it doesn't break their nic?
> 
> 
> On 2011/05/01 20:10, Stuart Henderson wrote:
> > On 2011/05/01 18:35, Edd Barrett wrote:
> > > I have acquired a netboot (packard bell dot s), which I think uses this 
> > > NIC. Is
> > > there an updated diff?
> > 
> > Yes I just took the 2 minutes it took to apply it and fix
> > the minor conflicts and linewrapping issue with the diff.
> > Untested beyond "it builds".
> > 
> > Test reports and dmesg lines from existing working alc(4) L1C and
> > L2C wanted. If it makes new chips work that's a bonus, but the
> > important thing is making sure it doesn't break something that
> > already works.
> > 
> > Doesn't seem any point disabling interrupts in the ISR though.
> > I haven't touched that in this diff but that should probably be
> > done too.
> 
> Index: share/man/man4/alc.4
> ===================================================================
> RCS file: /cvs/src/share/man/man4/alc.4,v
> retrieving revision 1.2
> diff -u -p -r1.2 alc.4
> --- share/man/man4/alc.4      8 Aug 2009 14:12:41 -0000       1.2
> +++ share/man/man4/alc.4      1 May 2011 18:55:25 -0000
> @@ -19,7 +19,7 @@
>  .Os
>  .Sh NAME
>  .Nm alc
> -.Nd Atheros AR8131/AR8132 10/100/Gigabit Ethernet device
> +.Nd Atheros AR813x/AR815x 10/100/Gigabit Ethernet device
>  .Sh SYNOPSIS
>  .Cd "alc* at pci?"
>  .Cd "atphy* at mii?"
> @@ -27,8 +27,7 @@
>  The
>  .Nm
>  driver provides support for Ethernet interfaces based on the
> -Atheros AR8131/AR8132 Ethernet chipset, also known as
> -the Attansic L1C/L2C respectively.
> +Atheros AR813x/AR815x Ethernet chipset.
>  .Pp
>  The
>  .Nm
> Index: sys/arch/amd64/conf/GENERIC
> ===================================================================
> RCS file: /cvs/src/sys/arch/amd64/conf/GENERIC,v
> retrieving revision 1.316
> diff -u -p -r1.316 GENERIC
> --- sys/arch/amd64/conf/GENERIC       10 Apr 2011 20:27:02 -0000      1.316
> +++ sys/arch/amd64/conf/GENERIC       1 May 2011 18:55:25 -0000
> @@ -472,7 +472,7 @@ bce*      at pci?                         # Broadcom 
> BCM4401
>  vic* at pci?                         # VMware VMXnet virtual interface
>  et*  at pci?                         # Agere/LSI ET1310
>  age* at pci?                         # Attansic L1 Ethernet
> -alc* at pci?                         # Attansic L1C/L2C Ethernet
> +alc* at pci?                         # Attansic L1C/L1D/L2C Ethernet
>  ale* at pci?                         # Attansic L1E Ethernet
>  lii* at pci?                         # Attansic L2 Ethernet
>  jme* at pci?                         # JMicron JMC250/JMC260 Ethernet
> Index: sys/arch/amd64/conf/RAMDISK_CD
> ===================================================================
> RCS file: /cvs/src/sys/arch/amd64/conf/RAMDISK_CD,v
> retrieving revision 1.116
> diff -u -p -r1.116 RAMDISK_CD
> --- sys/arch/amd64/conf/RAMDISK_CD    3 Apr 2011 12:32:05 -0000       1.116
> +++ sys/arch/amd64/conf/RAMDISK_CD    1 May 2011 18:55:25 -0000
> @@ -291,7 +291,7 @@ bce*      at pci?                 # Broadcom BCM4401
>  vic* at pci?                 # VMware VMXnet virtual interface
>  et*  at pci?                 # Agere/LSI ET1310
>  age* at pci?                 # Attansic L1 Ethernet
> -alc* at pci?                 # Attansic L1C/L2C Ethernet
> +alc* at pci?                 # Attansic L1C/L1D/L2C Ethernet
>  ale* at pci?                 # Attansic L1E Ethernet
>  lii* at pci?                 # Attansic L2 Ethernet
>  jme* at pci?                 # JMicron JMC250/JMC260 Ethernet
> Index: sys/arch/i386/conf/GENERIC
> ===================================================================
> RCS file: /cvs/src/sys/arch/i386/conf/GENERIC,v
> retrieving revision 1.713
> diff -u -p -r1.713 GENERIC
> --- sys/arch/i386/conf/GENERIC        10 Apr 2011 20:27:02 -0000      1.713
> +++ sys/arch/i386/conf/GENERIC        1 May 2011 18:55:25 -0000
> @@ -632,7 +632,7 @@ gem*      at pci?                         # Sun 'gem' 
> ethernet
>  vic* at pci?                         # VMware VMXnet virtual interface
>  et*  at pci?                         # Agere/LSI ET1310
>  age* at pci?                         # Attansic L1 Ethernet
> -alc* at pci?                         # Attansic L1C/L2C Ethernet
> +alc* at pci?                         # Attansic L1C/L1D/L2C Ethernet
>  ale* at pci?                         # Attansic L1E Ethernet
>  lii* at pci?                         # Attansic L2 Ethernet
>  jme* at pci?                         # JMicron JMC250/JMC260 Ethernet
> Index: sys/arch/i386/conf/RAMDISK_CD
> ===================================================================
> RCS file: /cvs/src/sys/arch/i386/conf/RAMDISK_CD,v
> retrieving revision 1.185
> diff -u -p -r1.185 RAMDISK_CD
> --- sys/arch/i386/conf/RAMDISK_CD     3 Apr 2011 12:32:05 -0000       1.185
> +++ sys/arch/i386/conf/RAMDISK_CD     1 May 2011 18:55:25 -0000
> @@ -372,7 +372,7 @@ xge*      at pci?                         # Neterion 
> Xframe-I/II 1
>  vic* at pci?                         # VMware VMXnet virtual interface
>  et*  at pci?                         # Agere/LSI ET1310
>  age* at pci?                         # Attansic L1 Ethernet
> -alc* at pci?                         # Attansic L1C/L2C Ethernet
> +alc* at pci?                         # Attansic L1C/L1D/L2C Ethernet
>  ale* at pci?                         # Attansic L1E Ethernet
>  lii* at pci?                         # Attansic L2 Ethernet
>  jme* at pci?                         # JMicron JMC250/JMC260 Ethernet
> Index: sys/dev/pci/files.pci
> ===================================================================
> RCS file: /cvs/src/sys/dev/pci/files.pci,v
> retrieving revision 1.278
> diff -u -p -r1.278 files.pci
> --- sys/dev/pci/files.pci     10 Apr 2011 20:27:02 -0000      1.278
> +++ sys/dev/pci/files.pci     1 May 2011 18:55:25 -0000
> @@ -643,7 +643,7 @@ device    age: ether, ifnet, mii, ifmedia, 
>  attach       age at pci
>  file dev/pci/if_age.c                age
>  
> -# Attansic/Atheros L1C/L2C Gigabit Ethernet
> +# Attansic/Atheros L1C/L1D/L2C Gigabit Ethernet
>  device       alc: ether, ifnet, mii, ifmedia, mii_phy
>  attach       alc at pci
>  file dev/pci/if_alc.c                alc
> Index: sys/dev/pci/if_alc.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/pci/if_alc.c,v
> retrieving revision 1.11
> diff -u -p -r1.11 if_alc.c
> --- sys/dev/pci/if_alc.c      5 Apr 2011 18:01:21 -0000       1.11
> +++ sys/dev/pci/if_alc.c      1 May 2011 18:55:25 -0000
> @@ -88,7 +88,7 @@ void        alc_watchdog(struct ifnet *);
>  int  alc_mediachange(struct ifnet *);
>  void alc_mediastatus(struct ifnet *, struct ifmediareq *);
>  
> -void alc_aspm(struct alc_softc *);
> +void alc_aspm(struct alc_softc *, int);
>  void alc_disable_l0s_l1(struct alc_softc *);
>  int  alc_dma_alloc(struct alc_softc *);
>  void alc_dma_free(struct alc_softc *);
> @@ -109,7 +109,7 @@ void      alc_phy_down(struct alc_softc *);
>  void alc_phy_reset(struct alc_softc *);
>  void alc_reset(struct alc_softc *);
>  void alc_rxeof(struct alc_softc *, struct rx_rdesc *);
> -int  alc_rxintr(struct alc_softc *);
> +void alc_rxintr(struct alc_softc *);
>  void alc_iff(struct alc_softc *);
>  void alc_rxvlan(struct alc_softc *);
>  void alc_start_queue(struct alc_softc *);
> @@ -125,7 +125,11 @@ uint32_t alc_dma_burst[] = { 128, 256, 5
>  
>  const struct pci_matchid alc_devices[] = {
>       { PCI_VENDOR_ATTANSIC, PCI_PRODUCT_ATTANSIC_L1C },
> -     { PCI_VENDOR_ATTANSIC, PCI_PRODUCT_ATTANSIC_L2C }
> +     { PCI_VENDOR_ATTANSIC, PCI_PRODUCT_ATTANSIC_L2C },
> +     { PCI_VENDOR_ATTANSIC, PCI_PRODUCT_ATTANSIC_L1D },
> +     { PCI_VENDOR_ATTANSIC, PCI_PRODUCT_ATTANSIC_L1D_1 },
> +     { PCI_VENDOR_ATTANSIC, PCI_PRODUCT_ATTANSIC_L2C_1 },
> +     { PCI_VENDOR_ATTANSIC, PCI_PRODUCT_ATTANSIC_L2C_2 }
>  };
>  
>  struct cfattach alc_ca = {
> @@ -236,8 +240,8 @@ alc_miibus_statchg(struct device *dev)
>               reg = CSR_READ_4(sc, ALC_MAC_CFG);
>               reg |= MAC_CFG_TX_ENB | MAC_CFG_RX_ENB;
>               CSR_WRITE_4(sc, ALC_MAC_CFG, reg);
> +             alc_aspm(sc, IFM_SUBTYPE(mii->mii_media_active));
>       }
> -     alc_aspm(sc);
>  }
>  
>  void
> @@ -280,20 +284,53 @@ void
>  alc_get_macaddr(struct alc_softc *sc)
>  {
>       uint32_t ea[2], opt;
> -     int i;
> +     uint16_t val;
> +     int eeprom, i;
>  
> +     eeprom = 0;
>       opt = CSR_READ_4(sc, ALC_OPT_CFG);
> -     if ((CSR_READ_4(sc, ALC_TWSI_DEBUG) & TWSI_DEBUG_DEV_EXIST) != 0) {
> +     if ((CSR_READ_4(sc, ALC_MASTER_CFG) & MASTER_OTP_SEL) != 0 &&
> +         (CSR_READ_4(sc, ALC_TWSI_DEBUG) & TWSI_DEBUG_DEV_EXIST) != 0) {
>               /*
>                * EEPROM found, let TWSI reload EEPROM configuration.
>                * This will set ethernet address of controller.
>                */
> -             if ((opt & OPT_CFG_CLK_ENB) == 0) {
> -                     opt |= OPT_CFG_CLK_ENB;
> -                     CSR_WRITE_4(sc, ALC_OPT_CFG, opt);
> -                     CSR_READ_4(sc, ALC_OPT_CFG);
> -                     DELAY(1000);
> +             eeprom++;
> +             switch (sc->sc_product) {
> +             case PCI_PRODUCT_ATTANSIC_L1C:
> +             case PCI_PRODUCT_ATTANSIC_L2C:
> +                     if ((opt & OPT_CFG_CLK_ENB) == 0) {
> +                             opt |= OPT_CFG_CLK_ENB;
> +                             CSR_WRITE_4(sc, ALC_OPT_CFG, opt);
> +                             CSR_READ_4(sc, ALC_OPT_CFG);
> +                             DELAY(1000);
> +                     }
> +                     break;
> +             case PCI_PRODUCT_ATTANSIC_L1D:
> +             case PCI_PRODUCT_ATTANSIC_L1D_1:
> +             case PCI_PRODUCT_ATTANSIC_L2C_1:
> +             case PCI_PRODUCT_ATTANSIC_L2C_2:
> +                     alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
> +                         ALC_MII_DBG_ADDR, 0x00);
> +                     val = alc_miibus_readreg(&sc->sc_dev, sc->alc_phyaddr,
> +                         ALC_MII_DBG_DATA);
> +                     alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
> +                         ALC_MII_DBG_DATA, val & 0xFF7F);
> +                     alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
> +                         ALC_MII_DBG_ADDR, 0x3B);
> +                     val = alc_miibus_readreg(&sc->sc_dev, sc->alc_phyaddr,
> +                         ALC_MII_DBG_DATA);
> +                     alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
> +                         ALC_MII_DBG_DATA, val | 0x0008);
> +                     DELAY(20);
> +                     break;
>               }
> +
> +             CSR_WRITE_4(sc, ALC_LTSSM_ID_CFG,
> +                 CSR_READ_4(sc, ALC_LTSSM_ID_CFG) & ~LTSSM_ID_WRO_ENB);
> +             CSR_WRITE_4(sc, ALC_WOL_CFG, 0);
> +             CSR_READ_4(sc, ALC_WOL_CFG);
> +
>               CSR_WRITE_4(sc, ALC_TWSI_CFG, CSR_READ_4(sc, ALC_TWSI_CFG) |
>                   TWSI_CFG_SW_LD_START);
>               for (i = 100; i > 0; i--) {
> @@ -309,11 +346,36 @@ alc_get_macaddr(struct alc_softc *sc)
>               if (alcdebug)
>                       printf("%s: EEPROM not found!\n", sc->sc_dev.dv_xname);
>       }
> -     if ((opt & OPT_CFG_CLK_ENB) != 0) {
> -             opt &= ~OPT_CFG_CLK_ENB;
> -             CSR_WRITE_4(sc, ALC_OPT_CFG, opt);
> -             CSR_READ_4(sc, ALC_OPT_CFG);
> -             DELAY(1000);
> +     if (eeprom != 0) {
> +             switch (sc->sc_product) {
> +             case PCI_PRODUCT_ATTANSIC_L1C:
> +             case PCI_PRODUCT_ATTANSIC_L2C:
> +                     if ((opt & OPT_CFG_CLK_ENB) != 0) {
> +                             opt &= ~OPT_CFG_CLK_ENB;
> +                             CSR_WRITE_4(sc, ALC_OPT_CFG, opt);
> +                             CSR_READ_4(sc, ALC_OPT_CFG);
> +                             DELAY(1000);
> +                     }
> +                     break;
> +             case PCI_PRODUCT_ATTANSIC_L1D:
> +             case PCI_PRODUCT_ATTANSIC_L1D_1:
> +             case PCI_PRODUCT_ATTANSIC_L2C_1:
> +             case PCI_PRODUCT_ATTANSIC_L2C_2:
> +                     alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
> +                         ALC_MII_DBG_ADDR, 0x00);
> +                     val = alc_miibus_readreg(&sc->sc_dev, sc->alc_phyaddr,
> +                         ALC_MII_DBG_DATA);
> +                     alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
> +                         ALC_MII_DBG_DATA, val | 0x0080);
> +                     alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
> +                         ALC_MII_DBG_ADDR, 0x3B);
> +                     val = alc_miibus_readreg(&sc->sc_dev, sc->alc_phyaddr,
> +                         ALC_MII_DBG_DATA);
> +                     alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
> +                         ALC_MII_DBG_DATA, val & 0xFFF7);
> +                     DELAY(20);
> +                     break;
> +             }
>       }
>  
>       ea[0] = CSR_READ_4(sc, ALC_PAR0);
> @@ -358,6 +420,43 @@ alc_phy_reset(struct alc_softc *sc)
>       CSR_READ_2(sc, ALC_GPHY_CFG);
>       DELAY(10 * 1000);
>  
> +     /* DSP fixup, Vendor magic. */
> +     if (sc->sc_product == PCI_PRODUCT_ATTANSIC_L2C_1) {
> +             alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
> +                 ALC_MII_DBG_ADDR, 0x000A);
> +             data = alc_miibus_readreg(&sc->sc_dev, sc->alc_phyaddr,
> +                 ALC_MII_DBG_DATA);
> +             alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
> +                 ALC_MII_DBG_DATA, data & 0xDFFF);
> +     }
> +     if (sc->sc_product == PCI_PRODUCT_ATTANSIC_L1D ||
> +         sc->sc_product == PCI_PRODUCT_ATTANSIC_L1D_1 ||
> +         sc->sc_product == PCI_PRODUCT_ATTANSIC_L2C_1 ||
> +         sc->sc_product == PCI_PRODUCT_ATTANSIC_L2C_2) {
> +             alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
> +                 ALC_MII_DBG_ADDR, 0x003B);
> +             data = alc_miibus_readreg(&sc->sc_dev, sc->alc_phyaddr,
> +                 ALC_MII_DBG_DATA);
> +             alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
> +                 ALC_MII_DBG_DATA, data & 0xFFF7);
> +             DELAY(20 * 1000);
> +     }
> +     if (sc->sc_product == PCI_PRODUCT_ATTANSIC_L1D) {
> +             alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
> +                 ALC_MII_DBG_ADDR, 0x0029);
> +             alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
> +                 ALC_MII_DBG_DATA, 0x929D);
> +     }
> +     if (sc->sc_product == PCI_PRODUCT_ATTANSIC_L1C ||
> +         sc->sc_product == PCI_PRODUCT_ATTANSIC_L2C ||
> +         sc->sc_product == PCI_PRODUCT_ATTANSIC_L1D_1 ||
> +         sc->sc_product == PCI_PRODUCT_ATTANSIC_L2C_2) {
> +             alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
> +                 ALC_MII_DBG_ADDR, 0x0029);
> +             alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
> +                 ALC_MII_DBG_DATA, 0xB6DD);
> +     }
> +
>       /* Load DSP codes, vendor magic. */
>       data = ANA_LOOP_SEL_10BT | ANA_EN_MASK_TB | ANA_EN_10BT_IDLE |
>           ((1 << ANA_INTERVAL_SEL_TIMER_SHIFT) & ANA_INTERVAL_SEL_TIMER_MASK);
> @@ -406,35 +505,114 @@ alc_phy_reset(struct alc_softc *sc)
>  void
>  alc_phy_down(struct alc_softc *sc)
>  {
> -
> -     /* Force PHY down. */
> -     CSR_WRITE_2(sc, ALC_GPHY_CFG,
> -         GPHY_CFG_EXT_RESET | GPHY_CFG_HIB_EN | GPHY_CFG_HIB_PULSE |
> -         GPHY_CFG_SEL_ANA_RESET | GPHY_CFG_PHY_IDDQ | GPHY_CFG_PWDOWN_HW);
> -     DELAY(1000);
> +     switch (sc->sc_product) {
> +     case PCI_PRODUCT_ATTANSIC_L1D:
> +     case PCI_PRODUCT_ATTANSIC_L1D_1:
> +             /*
> +              * GPHY power down caused more problems on AR8151 v2.0.
> +              * When driver is reloaded after GPHY power down,
> +              * accesses to PHY/MAC registers hung the system. Only
> +              * cold boot recovered from it.  I'm not sure whether
> +              * AR8151 v1.0 also requires this one though.  I don't
> +              * have AR8151 v1.0 controller in hand.
> +              * The only option left is to isolate the PHY and
> +              * initiates power down the PHY which in turn saves
> +              * more power when driver is unloaded.
> +              */
> +             alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
> +                 MII_BMCR, BMCR_ISO | BMCR_PDOWN);
> +             break;
> +     default:
> +             /* Force PHY down. */
> +             CSR_WRITE_2(sc, ALC_GPHY_CFG,
> +                 GPHY_CFG_EXT_RESET | GPHY_CFG_HIB_EN | GPHY_CFG_HIB_PULSE |
> +                 GPHY_CFG_SEL_ANA_RESET | GPHY_CFG_PHY_IDDQ | 
> +                 GPHY_CFG_PWDOWN_HW);
> +             DELAY(1000);
> +             break;
> +     }
>  }
>  
>  void
> -alc_aspm(struct alc_softc *sc)
> +alc_aspm(struct alc_softc *sc, int media)
>  {
>       uint32_t pmcfg;
> +     uint16_t linkcfg;
>  
>       pmcfg = CSR_READ_4(sc, ALC_PM_CFG);
> +     if ((sc->alc_flags & (ALC_FLAG_APS | ALC_FLAG_PCIE)) ==
> +         (ALC_FLAG_APS | ALC_FLAG_PCIE))
> +             linkcfg = CSR_READ_2(sc, sc->alc_expcap +
> +                 PCI_PCIE_LCSR);
> +     else
> +             linkcfg = 0;
>       pmcfg &= ~PM_CFG_SERDES_PD_EX_L1;
> -     pmcfg |= PM_CFG_SERDES_BUDS_RX_L1_ENB;
> -     pmcfg |= PM_CFG_SERDES_L1_ENB;
> -     pmcfg &= ~PM_CFG_L1_ENTRY_TIMER_MASK;
> +     pmcfg &= ~(PM_CFG_L1_ENTRY_TIMER_MASK | PM_CFG_LCKDET_TIMER_MASK);
>       pmcfg |= PM_CFG_MAC_ASPM_CHK;
> +     pmcfg |= (PM_CFG_LCKDET_TIMER_DEFAULT << PM_CFG_LCKDET_TIMER_SHIFT);
> +     pmcfg &= ~(PM_CFG_ASPM_L1_ENB | PM_CFG_ASPM_L0S_ENB);
> +
> +     if ((sc->alc_flags & ALC_FLAG_APS) != 0) {
> +             /* Disable extended sync except AR8152 B v1.0 */
> +             linkcfg &= ~0x80;
> +             if (sc->sc_product == PCI_PRODUCT_ATTANSIC_L2C_1 &&
> +                 sc->alc_rev == ATHEROS_AR8152_B_V10)
> +                     linkcfg |= 0x80;
> +             CSR_WRITE_2(sc, sc->alc_expcap + PCI_PCIE_LCSR,
> +                 linkcfg);
> +             pmcfg &= ~(PM_CFG_EN_BUFS_RX_L0S | PM_CFG_SA_DLY_ENB |
> +                 PM_CFG_HOTRST);
> +             pmcfg |= (PM_CFG_L1_ENTRY_TIMER_DEFAULT <<
> +                 PM_CFG_L1_ENTRY_TIMER_SHIFT);
> +             pmcfg &= ~PM_CFG_PM_REQ_TIMER_MASK;
> +             pmcfg |= (PM_CFG_PM_REQ_TIMER_DEFAULT <<
> +                 PM_CFG_PM_REQ_TIMER_SHIFT);
> +             pmcfg |= PM_CFG_SERDES_PD_EX_L1 | PM_CFG_PCIE_RECV;
> +     }
> +
>       if ((sc->alc_flags & ALC_FLAG_LINK) != 0) {
> -             pmcfg |= PM_CFG_SERDES_PLL_L1_ENB;
> -             pmcfg &= ~PM_CFG_CLK_SWH_L1;
> -             pmcfg &= ~PM_CFG_ASPM_L1_ENB;
> -             pmcfg &= ~PM_CFG_ASPM_L0S_ENB;
> +             if ((sc->alc_flags & ALC_FLAG_L0S) != 0)
> +                     pmcfg |= PM_CFG_ASPM_L0S_ENB;
> +             if ((sc->alc_flags & ALC_FLAG_L1S) != 0)
> +                     pmcfg |= PM_CFG_ASPM_L1_ENB;
> +             if ((sc->alc_flags & ALC_FLAG_APS) != 0) {
> +                     if (sc->sc_product == PCI_PRODUCT_ATTANSIC_L2C_1)
> +                             pmcfg &= ~PM_CFG_ASPM_L0S_ENB;
> +                     pmcfg &= ~(PM_CFG_SERDES_L1_ENB |
> +                         PM_CFG_SERDES_PLL_L1_ENB |
> +                         PM_CFG_SERDES_BUDS_RX_L1_ENB);
> +                     pmcfg |= PM_CFG_CLK_SWH_L1;
> +                     if (media == IFM_100_TX || media == IFM_1000_T) {
> +                             pmcfg &= ~PM_CFG_L1_ENTRY_TIMER_MASK;
> +                             switch (sc->sc_product) {
> +                             case PCI_PRODUCT_ATTANSIC_L2C_1:
> +                                     pmcfg |= (7 <<
> +                                         PM_CFG_L1_ENTRY_TIMER_SHIFT);
> +                                     break;
> +                             case PCI_PRODUCT_ATTANSIC_L1D_1:
> +                             case PCI_PRODUCT_ATTANSIC_L2C_2:
> +                                     pmcfg |= (4 <<
> +                                         PM_CFG_L1_ENTRY_TIMER_SHIFT);
> +                                     break;
> +                             default:
> +                                     pmcfg |= (15 <<
> +                                         PM_CFG_L1_ENTRY_TIMER_SHIFT);
> +                                     break;
> +                             }
> +                     }
> +             } else {
> +                     pmcfg |= PM_CFG_SERDES_L1_ENB |
> +                         PM_CFG_SERDES_PLL_L1_ENB |
> +                         PM_CFG_SERDES_BUDS_RX_L1_ENB;
> +                     pmcfg &= ~(PM_CFG_CLK_SWH_L1 |
> +                         PM_CFG_ASPM_L1_ENB | PM_CFG_ASPM_L0S_ENB);
> +             }
>       } else {
> -             pmcfg &= ~PM_CFG_SERDES_PLL_L1_ENB;
> +             pmcfg &= ~(PM_CFG_SERDES_BUDS_RX_L1_ENB | PM_CFG_SERDES_L1_ENB |
> +                 PM_CFG_SERDES_PLL_L1_ENB);
>               pmcfg |= PM_CFG_CLK_SWH_L1;
> -             pmcfg &= ~PM_CFG_ASPM_L1_ENB;
> -             pmcfg &= ~PM_CFG_ASPM_L0S_ENB;
> +             if ((sc->alc_flags & ALC_FLAG_L1S) != 0)
> +                     pmcfg |= PM_CFG_ASPM_L1_ENB;
>       }
>       CSR_WRITE_4(sc, ALC_PM_CFG, pmcfg);
>  }
> @@ -450,9 +628,9 @@ alc_attach(struct device *parent, struct
>       const char *intrstr;
>       struct ifnet *ifp;
>       pcireg_t memtype;
> -     char *aspm_state[] = { "L0s/L1", "L0s", "L1", "L0s/l1" };
> +     char *aspm_state[] = { "L0s/L1", "L0s", "L1", "L0s/L1" };
>       uint16_t burst;
> -     int base, mii_flags, state, error = 0;
> +     int base, state, error = 0;
>       uint32_t cap, ctl, val;
>  
>       /*
> @@ -499,6 +677,7 @@ alc_attach(struct device *parent, struct
>       if (pci_get_capability(pc, pa->pa_tag, PCI_CAP_PCIEXPRESS,
>           &base, NULL)) {
>               sc->alc_flags |= ALC_FLAG_PCIE;
> +             sc->alc_expcap = base;
>               burst = pci_conf_read(sc->sc_pct, sc->sc_pcitag,
>                   base + PCI_PCIE_DCSR) >> 16;
>               sc->alc_dma_rd_burst = (burst & 0x7000) >> 12;
> @@ -515,6 +694,20 @@ alc_attach(struct device *parent, struct
>               val = CSR_READ_4(sc, ALC_PEX_UNC_ERR_SEV);
>               val &= ~(PEX_UNC_ERR_SEV_DLP | PEX_UNC_ERR_SEV_FCP);
>               CSR_WRITE_4(sc, ALC_PEX_UNC_ERR_SEV, val);
> +             CSR_WRITE_4(sc, ALC_LTSSM_ID_CFG,
> +                 CSR_READ_4(sc, ALC_LTSSM_ID_CFG) & ~LTSSM_ID_WRO_ENB);
> +             CSR_WRITE_4(sc, ALC_PCIE_PHYMISC,
> +                 CSR_READ_4(sc, ALC_PCIE_PHYMISC) |
> +                 PCIE_PHYMISC_FORCE_RCV_DET);
> +             if (sc->sc_product == PCI_PRODUCT_ATTANSIC_L2C_1 &&
> +                 sc->alc_rev == ATHEROS_AR8152_B_V10) {
> +                     val = CSR_READ_4(sc, ALC_PCIE_PHYMISC2);
> +                     val &= ~(PCIE_PHYMISC2_SERDES_CDR_MASK |
> +                         PCIE_PHYMISC2_SERDES_TH_MASK);
> +                     val |= 3 << PCIE_PHYMISC2_SERDES_CDR_SHIFT;
> +                     val |= 3 << PCIE_PHYMISC2_SERDES_TH_SHIFT;
> +                     CSR_WRITE_4(sc, ALC_PCIE_PHYMISC2, val);
> +             }
>               /* Disable ASPM L0S and L1. */
>               cap = pci_conf_read(sc->sc_pct, sc->sc_pcitag,
>                   base + PCI_PCIE_LCAP) >> 16;
> @@ -528,13 +721,16 @@ alc_attach(struct device *parent, struct
>                                   sc->sc_dev.dv_xname,
>                                   sc->alc_rcb == DMA_CFG_RCB_64 ? 64 : 128);
>                       state = ctl & 0x03;
> +                     if (state & 0x01)
> +                             sc->alc_flags |= ALC_FLAG_L0S;
> +                     if (state & 0x02)
> +                             sc->alc_flags |= ALC_FLAG_L1S;
>                       if (alcdebug)
>                               printf("%s: ASPM %s %s\n",
>                                   sc->sc_dev.dv_xname,
>                                   aspm_state[state],
>                                   state == 0 ? "disabled" : "enabled");
> -                     if (state != 0)
> -                             alc_disable_l0s_l1(sc);
> +                     alc_disable_l0s_l1(sc);
>               }
>       }
>  
> @@ -551,12 +747,39 @@ alc_attach(struct device *parent, struct
>        * used in AR8132 can't establish gigabit link even if it
>        * shows the same PHY model/revision number of AR8131.
>        */
> -     if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ATTANSIC_L2C)
> -             sc->alc_flags |= ALC_FLAG_FASTETHER | ALC_FLAG_JUMBO;
> -     else
> -             sc->alc_flags |= ALC_FLAG_JUMBO | ALC_FLAG_ASPM_MON;
> +     sc->sc_product = PCI_PRODUCT(pa->pa_id);
> +     switch (sc->sc_product) {
> +     case PCI_PRODUCT_ATTANSIC_L2C_1:
> +     case PCI_PRODUCT_ATTANSIC_L2C_2:
> +             sc->alc_flags |= ALC_FLAG_APS;
> +             /* FALLTHROUGH */
> +     case PCI_PRODUCT_ATTANSIC_L2C:
> +             sc->alc_flags |= ALC_FLAG_FASTETHER;
> +             break;
> +     case PCI_PRODUCT_ATTANSIC_L1D:
> +     case PCI_PRODUCT_ATTANSIC_L1D_1:
> +             sc->alc_flags |= ALC_FLAG_APS;
> +             /* FALLTHROUGH */
> +     default:
> +             break;
> +     }
> +     sc->alc_flags |= ALC_FLAG_ASPM_MON | ALC_FLAG_JUMBO;
> +
> +     switch (sc->sc_product) {
> +     case PCI_PRODUCT_ATTANSIC_L1C:
> +     case PCI_PRODUCT_ATTANSIC_L2C:
> +             sc->alc_max_framelen = 9 * 1024;
> +             break;
> +     case PCI_PRODUCT_ATTANSIC_L1D:
> +     case PCI_PRODUCT_ATTANSIC_L1D_1:
> +     case PCI_PRODUCT_ATTANSIC_L2C_1:
> +     case PCI_PRODUCT_ATTANSIC_L2C_2:
> +             sc->alc_max_framelen = 6 * 1024;
> +             break;
> +     }
> +
>       /*
> -      * It seems that AR8131/AR8132 has silicon bug for SMB. In
> +      * It seems that AR813x/AR815x has silicon bug for SMB. In
>        * addition, Atheros said that enabling SMB wouldn't improve
>        * performance. However I think it's bad to access lots of
>        * registers to extract MAC statistics.
> @@ -619,11 +842,8 @@ alc_attach(struct device *parent, struct
>  
>       ifmedia_init(&sc->sc_miibus.mii_media, 0, alc_mediachange,
>           alc_mediastatus);
> -     mii_flags = 0;
> -     if ((sc->alc_flags & ALC_FLAG_JUMBO) != 0)
> -             mii_flags |= MIIF_DOPAUSE;
>       mii_attach(self, &sc->sc_miibus, 0xffffffff, MII_PHY_ANY,
> -             MII_OFFSET_ANY, mii_flags);
> +             MII_OFFSET_ANY, MIIF_DOPAUSE);
>  
>       if (LIST_FIRST(&sc->sc_miibus.mii_phys) == NULL) {
>               printf("%s: no PHY found!\n", sc->sc_dev.dv_xname);
> @@ -1136,16 +1356,15 @@ alc_start(struct ifnet *ifp)
>  {
>       struct alc_softc *sc = ifp->if_softc;
>       struct mbuf *m_head;
> -     int enq;
> -
> -     if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
> -             return;
> +     int enq = 0;
>  
>       /* Reclaim transmitted frames. */
>       if (sc->alc_cdata.alc_tx_cnt >= ALC_TX_DESC_HIWAT)
>               alc_txeof(sc);
>  
> -     enq = 0;
> +     if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
> +             return;
> +
>       for (;;) {
>               IFQ_DEQUEUE(&ifp->if_snd, m_head);
>               if (m_head == NULL)
> @@ -1162,7 +1381,7 @@ alc_start(struct ifnet *ifp)
>                       ifp->if_flags |= IFF_OACTIVE;
>                       break;
>               }
> -             enq = 1;
> +             enq++;
>               
>  #if NBPFILTER > 0
>               /*
> @@ -1174,7 +1393,7 @@ alc_start(struct ifnet *ifp)
>  #endif
>       }
>  
> -     if (enq) {
> +     if (enq > 0) {
>               /* Sync descriptors. */
>               bus_dmamap_sync(sc->sc_dmat, sc->alc_cdata.alc_tx_ring_map, 0,
>                   sc->alc_cdata.alc_tx_ring_map->dm_mapsize, 
> @@ -1274,6 +1493,10 @@ alc_mac_config(struct alc_softc *sc)
>       reg = CSR_READ_4(sc, ALC_MAC_CFG);
>       reg &= ~(MAC_CFG_FULL_DUPLEX | MAC_CFG_TX_FC | MAC_CFG_RX_FC |
>           MAC_CFG_SPEED_MASK);
> +     if (sc->sc_product == PCI_PRODUCT_ATTANSIC_L1D ||
> +         sc->sc_product == PCI_PRODUCT_ATTANSIC_L1D_1 ||
> +         sc->sc_product == PCI_PRODUCT_ATTANSIC_L2C_2)
> +             reg |= MAC_CFG_HASH_ALG_CRC32 | MAC_CFG_SPEED_MODE_SW;
>       /* Reprogram MAC with resolved speed/duplex. */
>       switch (IFM_SUBTYPE(mii->mii_media_active)) {
>       case IFM_10_T:
> @@ -1451,24 +1674,25 @@ alc_intr(void *arg)
>       struct alc_softc *sc = arg;
>       struct ifnet *ifp = &sc->sc_arpcom.ac_if;
>       uint32_t status;
> +     int claimed = 0;
>  
>       status = CSR_READ_4(sc, ALC_INTR_STATUS);
>       if ((status & ALC_INTRS) == 0)
>               return (0);
>  
> +     /* Disable interrupts. */
> +     CSR_WRITE_4(sc, ALC_INTR_STATUS, INTR_DIS_INT);
> +
> +     status = CSR_READ_4(sc, ALC_INTR_STATUS);
> +     if ((status & ALC_INTRS) == 0)
> +             goto back;
> +
>       /* Acknowledge and disable interrupts. */
>       CSR_WRITE_4(sc, ALC_INTR_STATUS, status | INTR_DIS_INT);
>  
>       if (ifp->if_flags & IFF_RUNNING) {
> -             if (status & INTR_RX_PKT) {
> -                     int error;
> -
> -                     error = alc_rxintr(sc);
> -                     if (error) {
> -                             alc_init(ifp);
> -                             return (0);
> -                     }
> -             }
> +             if (status & INTR_RX_PKT)
> +                     alc_rxintr(sc);
>  
>               if (status & (INTR_DMA_RD_TO_RST | INTR_DMA_WR_TO_RST |
>                   INTR_TXQ_TO_RST)) {
> @@ -1485,14 +1709,17 @@ alc_intr(void *arg)
>                       return (0);
>               }
>  
> -             alc_txeof(sc);
> -             if (!IFQ_IS_EMPTY(&ifp->if_snd))
> +             if (status & INTR_TX_PKT) {
> +                     alc_txeof(sc);
> +                 if (!IFQ_IS_EMPTY(&ifp->if_snd))
>                       alc_start(ifp);
> +             }
>       }
> -
> +     claimed = 1;
> +back:
>       /* Re-enable interrupts. */
>       CSR_WRITE_4(sc, ALC_INTR_STATUS, 0x7FFFFFFF);
> -     return (1);
> +     return (claimed);
>  }
>  
>  void
> @@ -1507,7 +1734,7 @@ alc_txeof(struct alc_softc *sc)
>               return;
>       bus_dmamap_sync(sc->sc_dmat, sc->alc_cdata.alc_tx_ring_map, 0,
>           sc->alc_cdata.alc_tx_ring_map->dm_mapsize,
> -         BUS_DMASYNC_POSTREAD);
> +         BUS_DMASYNC_POSTWRITE);
>       if ((sc->alc_flags & ALC_FLAG_CMB_BUG) == 0) {
>               bus_dmamap_sync(sc->sc_dmat, sc->alc_cdata.alc_cmb_map, 0,
>                   sc->alc_cdata.alc_cmb_map->dm_mapsize, 
> @@ -1591,7 +1818,7 @@ alc_newbuf(struct alc_softc *sc, struct 
>       return (0);
>  }
>  
> -int
> +void
>  alc_rxintr(struct alc_softc *sc)
>  {
>       struct ifnet *ifp = &sc->sc_arpcom.ac_if;
> @@ -1615,7 +1842,7 @@ alc_rxintr(struct alc_softc *sc)
>                       if (alcdebug)
>                               printf("%s: unexpected segment count -- "
>                                   "resetting\n", sc->sc_dev.dv_xname);
> -                     return (EIO);
> +                     break;
>               }
>               alc_rxeof(sc, rrd);
>               /* Clear Rx return status. */
> @@ -1653,8 +1880,6 @@ alc_rxintr(struct alc_softc *sc)
>               CSR_WRITE_4(sc, ALC_MBOX_RD0_PROD_IDX,
>                   sc->alc_cdata.alc_rx_cons);
>       }
> -
> -     return (0);
>  }
>  
>  /* Receive a frame. */
> @@ -1686,9 +1911,8 @@ alc_rxeof(struct alc_softc *sc, struct r
>                *  Force network stack compute checksum for
>                *  errored frames.
>                */
> -             status |= RRD_TCP_UDPCSUM_NOK | RRD_IPCSUM_NOK;
> -             if ((RRD_ERR_CRC | RRD_ERR_ALIGN | RRD_ERR_TRUNC |
> -                 RRD_ERR_RUNT) != 0)
> +             if ((status & (RRD_ERR_CRC | RRD_ERR_ALIGN |
> +                 RRD_ERR_TRUNC | RRD_ERR_RUNT)) != 0)
>                       return;
>       }
>  
> @@ -1801,7 +2025,9 @@ alc_reset(struct alc_softc *sc)
>       uint32_t reg;
>       int i;
>  
> -     CSR_WRITE_4(sc, ALC_MASTER_CFG, MASTER_RESET);
> +     reg = CSR_READ_4(sc, ALC_MASTER_CFG) & 0xFFFF;
> +     reg |= MASTER_OOB_DIS_OFF | MASTER_RESET;
> +     CSR_WRITE_4(sc, ALC_MASTER_CFG, reg);
>       for (i = ALC_RESET_TIMEOUT; i > 0; i--) {
>               DELAY(10);
>               if ((CSR_READ_4(sc, ALC_MASTER_CFG) & MASTER_RESET) == 0)
> @@ -1852,6 +2078,9 @@ alc_init(struct ifnet *ifp)
>       alc_init_cmb(sc);
>       alc_init_smb(sc);
>  
> +     /* Enable all clocks. */
> +     CSR_WRITE_4(sc, ALC_CLK_GATING_CFG, 0);
> +
>       /* Reprogram the station address. */
>       bcopy(LLADDR(ifp->if_sadl), eaddr, ETHER_ADDR_LEN);
>       CSR_WRITE_4(sc, ALC_PAR0,
> @@ -1913,6 +2142,18 @@ alc_init(struct ifnet *ifp)
>       CSR_WRITE_4(sc, ALC_SMB_BASE_ADDR_HI, ALC_ADDR_HI(paddr));
>       CSR_WRITE_4(sc, ALC_SMB_BASE_ADDR_LO, ALC_ADDR_LO(paddr));
>  
> +     if (sc->sc_product == PCI_PRODUCT_ATTANSIC_L2C_1) {
> +             /* Reconfigure SRAM - Vendor magic. */ 
> +             CSR_WRITE_4(sc, ALC_SRAM_RX_FIFO_LEN, 0x000002A0); 
> +             CSR_WRITE_4(sc, ALC_SRAM_TX_FIFO_LEN, 0x00000100);
> +             CSR_WRITE_4(sc, ALC_SRAM_RX_FIFO_ADDR, 0x029F0000);
> +             CSR_WRITE_4(sc, ALC_SRAM_RD0_ADDR, 0x02BF02A0);
> +             CSR_WRITE_4(sc, ALC_SRAM_TX_FIFO_ADDR, 0x03BF02C0);
> +             CSR_WRITE_4(sc, ALC_SRAM_TD_ADDR, 0x03DF03C0);
> +             CSR_WRITE_4(sc, ALC_TXF_WATER_MARK, 0x00000000);
> +             CSR_WRITE_4(sc, ALC_RD_DMA_CFG, 0x00000000);
> +     }
> +
>       /* Tell hardware that we're ready to load DMA blocks. */
>       CSR_WRITE_4(sc, ALC_DMA_BLOCK, DMA_BLOCK_LOAD);
>  
> @@ -1922,14 +2163,11 @@ alc_init(struct ifnet *ifp)
>       reg = ALC_USECS(sc->alc_int_rx_mod) << IM_TIMER_RX_SHIFT;
>       reg |= ALC_USECS(sc->alc_int_tx_mod) << IM_TIMER_TX_SHIFT;
>       CSR_WRITE_4(sc, ALC_IM_TIMER, reg);
> -     reg = CSR_READ_4(sc, ALC_MASTER_CFG);
> -     reg &= ~(MASTER_CHIP_REV_MASK | MASTER_CHIP_ID_MASK);
>       /*
>        * We don't want to automatic interrupt clear as task queue
>        * for the interrupt should know interrupt status.
>        */
> -     reg &= ~MASTER_INTR_RD_CLR;
> -     reg &= ~(MASTER_IM_RX_TIMER_ENB | MASTER_IM_TX_TIMER_ENB);
> +     reg = MASTER_SA_TIMER_ENB;
>       if (ALC_USECS(sc->alc_int_rx_mod) != 0)
>               reg |= MASTER_IM_RX_TIMER_ENB;
>       if (ALC_USECS(sc->alc_int_tx_mod) != 0)
> @@ -1970,7 +2208,7 @@ alc_init(struct ifnet *ifp)
>        * Be conservative in what you do, be liberal in what you
>        * accept from others - RFC 793.
>        */
> -     CSR_WRITE_4(sc, ALC_FRAME_SIZE, ALC_JUMBO_FRAMELEN);
> +     CSR_WRITE_4(sc, ALC_FRAME_SIZE, sc->alc_max_framelen);
>  
>       /* Disable header split(?) */
>       CSR_WRITE_4(sc, ALC_HDS_CFG, 0);
> @@ -1997,11 +2235,14 @@ alc_init(struct ifnet *ifp)
>        * TSO/checksum offloading.
>        */
>       CSR_WRITE_4(sc, ALC_TSO_OFFLOAD_THRESH,
> -         (ALC_JUMBO_FRAMELEN >> TSO_OFFLOAD_THRESH_UNIT_SHIFT) &
> +         (sc->alc_max_framelen >> TSO_OFFLOAD_THRESH_UNIT_SHIFT) &
>           TSO_OFFLOAD_THRESH_MASK);
>       /* Configure TxQ. */
>       reg = (alc_dma_burst[sc->alc_dma_rd_burst] <<
>           TXQ_CFG_TX_FIFO_BURST_SHIFT) & TXQ_CFG_TX_FIFO_BURST_MASK;
> +     if (sc->sc_product == PCI_PRODUCT_ATTANSIC_L2C_1 ||
> +         sc->sc_product == PCI_PRODUCT_ATTANSIC_L2C_2)
> +             reg >>= 1;
>       reg |= (TXQ_CFG_TD_BURST_DEFAULT << TXQ_CFG_TD_BURST_SHIFT) &
>           TXQ_CFG_TD_BURST_MASK;
>       CSR_WRITE_4(sc, ALC_TXQ_CFG, reg | TXQ_CFG_ENHANCED_MODE);
> @@ -2018,14 +2259,22 @@ alc_init(struct ifnet *ifp)
>        * XON  : 80% of Rx FIFO
>        * XOFF : 30% of Rx FIFO
>        */
> -     reg = CSR_READ_4(sc, ALC_SRAM_RX_FIFO_LEN);
> -     rxf_hi = (reg * 8) / 10;
> -     rxf_lo = (reg * 3)/ 10;
> -     CSR_WRITE_4(sc, ALC_RX_FIFO_PAUSE_THRESH,
> -         ((rxf_lo << RX_FIFO_PAUSE_THRESH_LO_SHIFT) &
> -         RX_FIFO_PAUSE_THRESH_LO_MASK) |
> -         ((rxf_hi << RX_FIFO_PAUSE_THRESH_HI_SHIFT) &
> -          RX_FIFO_PAUSE_THRESH_HI_MASK));
> +     if (sc->sc_product == PCI_PRODUCT_ATTANSIC_L1C ||
> +         sc->sc_product == PCI_PRODUCT_ATTANSIC_L2C) {
> +             reg = CSR_READ_4(sc, ALC_SRAM_RX_FIFO_LEN);
> +             rxf_hi = (reg * 8) / 10;
> +             rxf_lo = (reg * 3) / 10;
> +             CSR_WRITE_4(sc, ALC_RX_FIFO_PAUSE_THRESH,
> +                 ((rxf_lo << RX_FIFO_PAUSE_THRESH_LO_SHIFT) &
> +                 RX_FIFO_PAUSE_THRESH_LO_MASK) |
> +                 ((rxf_hi << RX_FIFO_PAUSE_THRESH_HI_SHIFT) &
> +                 RX_FIFO_PAUSE_THRESH_HI_MASK));
> +     }
> +     if (sc->sc_product == PCI_PRODUCT_ATTANSIC_L1D_1 ||
> +         sc->sc_product == PCI_PRODUCT_ATTANSIC_L2C_1)
> +             CSR_WRITE_4(sc, ALC_SERDES_LOCK,
> +                 CSR_READ_4(sc, ALC_SERDES_LOCK) | SERDES_MAC_CLK_SLOWDOWN |
> +                 SERDES_PHY_CLK_SLOWDOWN);
>  
>       /* Disable RSS until I understand L1C/L2C's RSS logic. */
>       CSR_WRITE_4(sc, ALC_RSS_IDT_TABLE0, 0);
> @@ -2036,15 +2285,9 @@ alc_init(struct ifnet *ifp)
>           RXQ_CFG_RD_BURST_MASK;
>       reg |= RXQ_CFG_RSS_MODE_DIS;
>       if ((sc->alc_flags & ALC_FLAG_ASPM_MON) != 0)
> -             reg |= RXQ_CFG_ASPM_THROUGHPUT_LIMIT_100M;
> +             reg |= RXQ_CFG_ASPM_THROUGHPUT_LIMIT_1M;
>       CSR_WRITE_4(sc, ALC_RXQ_CFG, reg);
>  
> -     /* Configure Rx DMAW request thresold. */
> -     CSR_WRITE_4(sc, ALC_RD_DMA_CFG,
> -         ((RD_DMA_CFG_THRESH_DEFAULT << RD_DMA_CFG_THRESH_SHIFT) &
> -         RD_DMA_CFG_THRESH_MASK) |
> -         ((ALC_RD_DMA_CFG_USECS(0) << RD_DMA_CFG_TIMER_SHIFT) &
> -         RD_DMA_CFG_TIMER_MASK));
>       /* Configure DMA parameters. */
>       reg = DMA_CFG_OUT_ORDER | DMA_CFG_RD_REQ_PRI;
>       reg |= sc->alc_rcb;
> @@ -2070,7 +2313,7 @@ alc_init(struct ifnet *ifp)
>        *  - Enable CRC generation.
>        *  Actual reconfiguration of MAC for resolved speed/duplex
>        *  is followed after detection of link establishment.
> -      *  AR8131/AR8132 always does checksum computation regardless
> +      *  AR813x/AR815x always does checksum computation regardless
>        *  of MAC_CFG_RXCSUM_ENB bit. Also the controller is known to
>        *  have bug in protocol field in Rx return structure so
>        *  these controllers can't handle fragmented frames. Disable
> @@ -2080,6 +2323,10 @@ alc_init(struct ifnet *ifp)
>       reg = MAC_CFG_TX_CRC_ENB | MAC_CFG_TX_AUTO_PAD | MAC_CFG_FULL_DUPLEX |
>           ((MAC_CFG_PREAMBLE_DEFAULT << MAC_CFG_PREAMBLE_SHIFT) &
>           MAC_CFG_PREAMBLE_MASK);
> +     if (sc->sc_product == PCI_PRODUCT_ATTANSIC_L1D ||
> +         sc->sc_product == PCI_PRODUCT_ATTANSIC_L1D_1 ||
> +         sc->sc_product == PCI_PRODUCT_ATTANSIC_L2C_2)
> +             reg |= MAC_CFG_HASH_ALG_CRC32 | MAC_CFG_SPEED_MODE_SW;
>       if ((sc->alc_flags & ALC_FLAG_FASTETHER) != 0)
>               reg |= MAC_CFG_SPEED_10_100;
>       else
> Index: sys/dev/pci/if_alcreg.h
> ===================================================================
> RCS file: /cvs/src/sys/dev/pci/if_alcreg.h,v
> retrieving revision 1.1
> diff -u -p -r1.1 if_alcreg.h
> --- sys/dev/pci/if_alcreg.h   8 Aug 2009 09:31:13 -0000       1.1
> +++ sys/dev/pci/if_alcreg.h   1 May 2011 18:55:25 -0000
> @@ -31,7 +31,10 @@
>  #ifndef      _IF_ALCREG_H
>  #define      _IF_ALCREG_H
>  
> -#define ALC_PCIR_BAR                 0x10
> +#define      ALC_PCIR_BAR                    0x10
> +
> +#define      ATHEROS_AR8152_B_V10            0xC0
> +#define      ATHEROS_AR8152_B_V11            0xC1
>  
>  /* 0x0000 - 0x02FF : PCIe configuration space */
>  
> @@ -56,6 +59,12 @@
>  #define      ALC_PCIE_PHYMISC                0x1000
>  #define      PCIE_PHYMISC_FORCE_RCV_DET      0x00000004
>  
> +#define      ALC_PCIE_PHYMISC2               0x1004
> +#define      PCIE_PHYMISC2_SERDES_CDR_MASK   0x00030000
> +#define      PCIE_PHYMISC2_SERDES_TH_MASK    0x000C0000
> +#define      PCIE_PHYMISC2_SERDES_CDR_SHIFT  16
> +#define      PCIE_PHYMISC2_SERDES_TH_SHIFT   18
> +
>  #define      ALC_TWSI_DEBUG                  0x1108
>  #define      TWSI_DEBUG_DEV_EXIST            0x20000000
>  
> @@ -88,7 +97,9 @@
>  #define      PM_CFG_PCIE_RECV                0x00008000
>  #define      PM_CFG_L1_ENTRY_TIMER_MASK      0x000F0000
>  #define      PM_CFG_PM_REQ_TIMER_MASK        0x00F00000
> -#define      PM_CFG_LCKDET_TIMER_MASK        0x3F000000
> +#define      PM_CFG_LCKDET_TIMER_MASK        0x0F000000
> +#define      PM_CFG_EN_BUFS_RX_L0S           0x10000000
> +#define      PM_CFG_SA_DLY_ENB               0x20000000
>  #define      PM_CFG_MAC_ASPM_CHK             0x40000000
>  #define      PM_CFG_HOTRST                   0x80000000
>  #define      PM_CFG_L0S_ENTRY_TIMER_SHIFT    8
> @@ -96,10 +107,20 @@
>  #define      PM_CFG_PM_REQ_TIMER_SHIFT       20
>  #define      PM_CFG_LCKDET_TIMER_SHIFT       24
>  
> +#define      PM_CFG_L0S_ENTRY_TIMER_DEFAULT  6
> +#define      PM_CFG_L1_ENTRY_TIMER_DEFAULT   1
> +#define      PM_CFG_LCKDET_TIMER_DEFAULT     12
> +#define      PM_CFG_PM_REQ_TIMER_DEFAULT     12
> +
> +#define      ALC_LTSSM_ID_CFG                0x12FC
> +#define      LTSSM_ID_WRO_ENB                0x00001000
> +
>  #define      ALC_MASTER_CFG                  0x1400
>  #define      MASTER_RESET                    0x00000001
> +#define      MASTER_TEST_MODE_MASK           0x0000000C
>  #define      MASTER_BERT_START               0x00000010
> -#define      MASTER_TEST_MODE_MASK           0x000000C0
> +#define      MASTER_OOB_DIS_OFF              0x00000040
> +#define      MASTER_SA_TIMER_ENB             0x00000080
>  #define      MASTER_MTIMER_ENB               0x00000100
>  #define      MASTER_MANUAL_INTR_ENB          0x00000200
>  #define      MASTER_IM_TX_TIMER_ENB          0x00000400
> @@ -114,7 +135,7 @@
>  #define      MASTER_CHIP_REV_SHIFT           16
>  #define      MASTER_CHIP_ID_SHIFT            24
>  
> -/* Number of ticks per usec for AR8131/AR8132. */
> +/* Number of ticks per usec for AR813x/AR815x. */
>  #define      ALC_TICK_USECS                  2
>  #define      ALC_USECS(x)                    ((x) / ALC_TICK_USECS)
>  
> @@ -136,7 +157,7 @@
>   * alc(4) does not rely on Tx completion interrupts, so set it
>   * somewhat large value to reduce Tx completion interrupts.
>   */
> -#define      ALC_IM_TX_TIMER_DEFAULT         50000   /* 50ms */
> +#define      ALC_IM_TX_TIMER_DEFAULT         1000    /* 1ms */
>  
>  #define      ALC_GPHY_CFG                    0x140C  /* 16bits */
>  #define      GPHY_CFG_EXT_RESET              0x0001
> @@ -212,6 +233,8 @@
>  #define      ALC_SERDES_LOCK                 0x1424
>  #define      SERDES_LOCK_DET                 0x00000001
>  #define      SERDES_LOCK_DET_ENB             0x00000002
> +#define      SERDES_MAC_CLK_SLOWDOWN         0x00020000
> +#define      SERDES_PHY_CLK_SLOWDOWN         0x00040000
>  
>  #define      ALC_MAC_CFG                     0x1480
>  #define      MAC_CFG_TX_ENB                  0x00000001
> @@ -241,6 +264,8 @@
>  #define      MAC_CFG_BCAST                   0x04000000
>  #define      MAC_CFG_DBG                     0x08000000
>  #define      MAC_CFG_SINGLE_PAUSE_ENB        0x10000000
> +#define      MAC_CFG_HASH_ALG_CRC32          0x20000000
> +#define      MAC_CFG_SPEED_MODE_SW           0x40000000
>  #define      MAC_CFG_PREAMBLE_SHIFT          10
>  #define      MAC_CFG_PREAMBLE_DEFAULT        7
>  
> @@ -683,11 +708,19 @@
>  #define      HDS_CFG_BACKFILLSIZE_SHIFT      8
>  #define      HDS_CFG_MAX_HDRSIZE_SHIFT       20
>  
> -/* AR8131/AR8132 registers for MAC statistics */
> +/* AR813x/AR815x registers for MAC statistics */
>  #define      ALC_RX_MIB_BASE                 0x1700
>  
>  #define      ALC_TX_MIB_BASE                 0x1760
>  
> +#define      ALC_CLK_GATING_CFG              0x1814
> +#define      CLK_GATING_DMAW_ENB             0x0001
> +#define      CLK_GATING_DMAR_ENB             0x0002
> +#define      CLK_GATING_TXQ_ENB              0x0004
> +#define      CLK_GATING_RXQ_ENB              0x0008
> +#define      CLK_GATING_TXMAC_ENB            0x0010
> +#define      CLK_GATING_RXMAC_ENB            0x0020
> +
>  #define      ALC_DEBUG_DATA0                 0x1900
>  
>  #define      ALC_DEBUG_DATA1                 0x1904
> @@ -1112,6 +1145,7 @@ struct alc_softc {
>       bus_dma_tag_t           sc_dmat;
>       pci_chipset_tag_t       sc_pct;
>       pcitag_t                sc_pcitag;
> +     pci_vendor_id_t         sc_product;
>  
>       void                    *sc_irq_handle;
>  
> @@ -1120,19 +1154,23 @@ struct alc_softc {
>       int                     alc_chip_rev;
>       int                     alc_phyaddr;
>       uint8_t                 alc_eaddr[ETHER_ADDR_LEN];
> +     uint32_t                alc_max_framelen;
>       uint32_t                alc_dma_rd_burst;
>       uint32_t                alc_dma_wr_burst;
>       uint32_t                alc_rcb;
> +     int                     alc_expcap;
>       int                     alc_flags;
>  #define      ALC_FLAG_PCIE           0x0001
>  #define      ALC_FLAG_PCIX           0x0002
> -#define      ALC_FLAG_MSI            0x0004
> -#define      ALC_FLAG_MSIX           0x0008
> +#define      ALC_FLAG_PM             0x0010
>  #define      ALC_FLAG_FASTETHER      0x0020
>  #define      ALC_FLAG_JUMBO          0x0040
>  #define      ALC_FLAG_ASPM_MON       0x0080
>  #define      ALC_FLAG_CMB_BUG        0x0100
>  #define      ALC_FLAG_SMB_BUG        0x0200
> +#define      ALC_FLAG_L0S            0x0400
> +#define      ALC_FLAG_L1S            0x0800
> +#define      ALC_FLAG_APS            0x1000
>  #define      ALC_FLAG_DETACH         0x4000
>  #define      ALC_FLAG_LINK           0x8000

Reply via email to