On Tue, Aug 01, 2006 at 04:12:15PM +0100, Steve Glendinning wrote:
> > > Attached is a driver patch for SMSC911x family of ethernet chips,
> > > generated against 2.6.18-rc1 sources. There's a similar driver in the
> > > tree; this one has been tested by SMSC on all flavors of the chip and
> > > claimed to be efficient.
> >
> > Updated after feedback from Stephen Hemminger.
> >
> > Driver updated to also support LAN921x family.  Workarounds added for
> > known hardware issues.
> 
> Many improvements following feedback from Stephen Hemminger and
> Francois Romieu:
>  - Tasklet removed, NAPI poll used instead
>  - Multiple device support
>  - style fixes & minor improvements

<snip>

> +/* waits for MAC not busy, with timeout.  Assumes MacPhyAccessLock has
> + * already been acquired */
> +static int smsc911x_mac_notbusy(struct smsc911x_data *pdata)
> +{
> +     int i;
> +
> +     for (i = 0; i < 40; i++) {
> +             if ((smsc911x_reg_read(pdata, MAC_CSR_CMD)
> +                  & MAC_CSR_CMD_CSR_BUSY_) == 0) {
> +                     return 1;
> +             }
> +     }
> +     SMSC_WARNING("Timed out waiting for MAC not BUSY. "
> +                  "MAC_CSR_CMD: 0x%08X", smsc911x_reg_read(pdata,
> +                                                           MAC_CSR_CMD));
> +     return 0;
> +}

How is the length of this timeout controlled?  IOW, what prevents
it from being too short when the Omegatron 128 running at 10GHz hits
the market?  Are you relying on the MII clock rate?

<snip>

> +/* Gets a phy register, phy_lock must be acquired before calling */
> +static unsigned int
> +smsc911x_phy_read(struct smsc911x_data *pdata, unsigned int index)
> +{
> +     unsigned int addr;
> +     unsigned int result = 0xFFFF;
> +     int i;
> +
> +     /* Confirm MII not busy */
> +     if (unlikely
> +         ((smsc911x_mac_read(pdata, MII_ACC) & MII_ACC_MII_BUSY_) != 0)) {
> +             SMSC_WARNING("MII is busy in smsc911x_phy_read???");
> +             return 0;
> +     }
> +
> +     /* Set the address, index & direction (read from PHY) */
> +     addr = (((pdata->phy_address) & 0x1F) << 11)
> +         | ((index & 0x1F) << 6);
> +     smsc911x_mac_write(pdata, MII_ACC, addr);
> +
> +     /* Wait for read to complete w/ timeout */
> +     for (i = 0; i < 100; i++) {
> +             /* See if MII is finished yet */
> +             if ((smsc911x_mac_read(pdata, MII_ACC)
> +                  & MII_ACC_MII_BUSY_) == 0) {
> +                     result = smsc911x_mac_read(pdata, MII_DATA);
> +                     return result;
> +             }
> +     }
> +     SMSC_WARNING("Timed out waiting for MII write to finish");

Ditto?

<snip>

> +/* Sets a phy register, phy_lock must be acquired before calling */
> +static void smsc911x_phy_write(struct smsc911x_data *pdata,
> +                            unsigned int index, unsigned int val)
> +{
> +     unsigned int addr;
> +     int i;
> +
> +     /* Confirm MII not busy */
> +     if (unlikely
> +         ((smsc911x_mac_read(pdata, MII_ACC) & MII_ACC_MII_BUSY_) != 0)) {
> +             SMSC_WARNING("MII is busy in smsc911x_write_phy???");
> +             return;
> +     }
> +
> +     /* Put the data to write in the MAC */
> +     smsc911x_mac_write(pdata, MII_DATA, val);
> +
> +     /* Set the address, index & direction (write to PHY) */
> +     addr = (((pdata->phy_address) & 0x1F) << 11) |
> +         ((index & 0x1F) << 6) | MII_ACC_MII_WRITE_;
> +     smsc911x_mac_write(pdata, MII_ACC, addr);
> +
> +     /* Wait for write to complete w/ timeout */
> +     for (i = 0; i < 100; i++) {
> +             /* See if MII is finished yet */
> +             if ((smsc911x_mac_read(pdata, MII_ACC)
> +                  & MII_ACC_MII_BUSY_) == 0)
> +                     return;
> +     }
> +     SMSC_WARNING("Timed out waiting for MII write to finish");
> +}

Ditto?

> +/* Autodetects and initialises external phy for SMSC9115 and SMSC9117 
> flavors.
> + * If something goes wrong, returns -ENODEV to revert back to internal phy.
> + * Performed at initialisation only, phy_lock already acquired. */
> +static int smsc911x_phy_initialise_external(struct smsc911x_data *pdata)
> +{
> +     unsigned int address;
> +     unsigned int hwcfg;
> +     unsigned int phyid1;
> +     unsigned int phyid2;
> +
> +     hwcfg = smsc911x_reg_read(pdata, HW_CFG);
> +
> +     /* External phy is requested, supported, and detected */
> +     if (hwcfg & HW_CFG_EXT_PHY_DET_) {
> +
> +             /* Attempt to switch to external phy for auto-detecting
> +              * its address. Assuming tx and rx are stopped because
> +              * smsc911x_phy_initialise is called before
> +              * smsc911x_rx_initialise and tx_initialise.
> +              */
> +
> +             /* Disable phy clocks to the MAC */
> +             hwcfg &= (~HW_CFG_PHY_CLK_SEL_);
> +             hwcfg |= HW_CFG_PHY_CLK_SEL_CLK_DIS_;
> +             smsc911x_reg_write(hwcfg, pdata, HW_CFG);
> +             udelay(10);     /* Enough time for clocks to stop */
> +
> +             /* Switch to external phy */
> +             hwcfg |= HW_CFG_EXT_PHY_EN_;
> +             smsc911x_reg_write(hwcfg, pdata, HW_CFG);
> +
> +             /* Enable phy clocks to the MAC */
> +             hwcfg &= (~HW_CFG_PHY_CLK_SEL_);
> +             hwcfg |= HW_CFG_PHY_CLK_SEL_EXT_PHY_;
> +             smsc911x_reg_write(hwcfg, pdata, HW_CFG);
> +             udelay(10);     /* Enough time for clocks to restart */
> +
> +             hwcfg |= HW_CFG_SMI_SEL_;
> +             smsc911x_reg_write(hwcfg, pdata, HW_CFG);
> +
> +             /* Auto-detect PHY */
> +             for (address = 0; address <= 31; address++) {
> +                     pdata->phy_address = address;
> +                     phyid1 = smsc911x_phy_read(pdata, MII_PHYSID1);
> +                     phyid2 = smsc911x_phy_read(pdata, MII_PHYSID2);
> +                     if ((phyid1 != 0xFFFFU) || (phyid2 != 0xFFFFU)) {
> +                             SMSC_TRACE("Detected PHY at address = "
> +                                        "0x%02X = %d", address, address);
> +                             break;
> +                     }
> +             }

Does this need the magic "for (addr=1; addr <=32; addr++)" trick that
has become idiomatic for PHY discovery in our drivers?

<snip>

> --- /dev/null
> +++ b/drivers/net/smsc911x.h

<snip>

> +/* SMSC911x registers and bitfields */
> +#define RX_DATA_FIFO                                 0x00
> +
> +#define TX_DATA_FIFO                                 0x20
> +#define TX_CMD_A_ON_COMP_                            0x80000000
> +#define TX_CMD_A_BUF_END_ALGN_                               0x03000000
> +#define TX_CMD_A_4_BYTE_ALGN_                                0x00000000
> +#define TX_CMD_A_16_BYTE_ALGN_                               0x01000000
> +#define TX_CMD_A_32_BYTE_ALGN_                               0x02000000
> +#define TX_CMD_A_DATA_OFFSET_                                0x001F0000
> +#define TX_CMD_A_FIRST_SEG_                          0x00002000
> +#define TX_CMD_A_LAST_SEG_                           0x00001000
> +#define TX_CMD_A_BUF_SIZE_                           0x000007FF
> +#define TX_CMD_B_PKT_TAG_                            0xFFFF0000
> +#define TX_CMD_B_ADD_CRC_DISABLE_                    0x00002000
> +#define TX_CMD_B_DISABLE_PADDING_                    0x00001000
> +#define TX_CMD_B_PKT_BYTE_LENGTH_                    0x000007FF

Looks like something went haywire w/ your tabbing in this file...?

Your style overall is very nice and easy to read.

Thanks,

John
-- 
John W. Linville
[EMAIL PROTECTED]
-
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