chelsio: Use generic MDIO definitions and mdio_mii_ioctl()
authorBen Hutchings <bhutchings@solarflare.com>
Wed, 29 Apr 2009 08:06:34 +0000 (08:06 +0000)
committerDavid S. Miller <davem@davemloft.net>
Thu, 30 Apr 2009 00:32:31 +0000 (17:32 -0700)
Compile-tested only.

Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/Kconfig
drivers/net/chelsio/common.h
drivers/net/chelsio/cphy.h
drivers/net/chelsio/cxgb2.c
drivers/net/chelsio/mv88x201x.c
drivers/net/chelsio/my3126.c
drivers/net/chelsio/subr.c

index 2f81db51b45d8dd8f5ef3b45f7f7af843be59d3d..1ccd54714c4c69dfa91197f01019419859198f0e 100644 (file)
@@ -2450,6 +2450,7 @@ config CHELSIO_T1
         tristate "Chelsio 10Gb Ethernet support"
         depends on PCI
        select CRC32
+       select MDIO
         help
           This driver supports Chelsio gigabit and 10-gigabit
           Ethernet cards. More information about adapter features and
index 4bd2455b0fe31b50bc20fba8f6a35e90ccc323fd..699d22c5fe094f03919aefd7e2672a412955ab19 100644 (file)
@@ -46,7 +46,7 @@
 #include <linux/pci.h>
 #include <linux/ethtool.h>
 #include <linux/if_vlan.h>
-#include <linux/mii.h>
+#include <linux/mdio.h>
 #include <linux/crc32.h>
 #include <linux/init.h>
 #include <asm/io.h>
index 79d855e267e0238a5d314d3c72098529f1df5a90..8b5165a5af3fbef3323ca48d3df26ecc866875d1 100644 (file)
 
 struct mdio_ops {
        void (*init)(adapter_t *adapter, const struct board_info *bi);
-       int  (*read)(adapter_t *adapter, int phy_addr, int mmd_addr,
-                    int reg_addr, unsigned int *val);
-       int  (*write)(adapter_t *adapter, int phy_addr, int mmd_addr,
-                     int reg_addr, unsigned int val);
+       int  (*read)(struct net_device *dev, int phy_addr, int mmd_addr,
+                    u16 reg_addr);
+       int  (*write)(struct net_device *dev, int phy_addr, int mmd_addr,
+                     u16 reg_addr, u16 val);
+       unsigned mode_support;
 };
 
 /* PHY interrupt types */
@@ -83,11 +84,12 @@ struct cphy_ops {
        int (*set_speed_duplex)(struct cphy *phy, int speed, int duplex);
        int (*get_link_status)(struct cphy *phy, int *link_ok, int *speed,
                               int *duplex, int *fc);
+
+       u32 mmds;
 };
 
 /* A PHY instance */
 struct cphy {
-       int addr;                            /* PHY address */
        int state;      /* Link status state machine */
        adapter_t *adapter;                  /* associated adapter */
 
@@ -101,36 +103,37 @@ struct cphy {
        u32 elmer_gpo;
 
        const struct cphy_ops *ops;            /* PHY operations */
-       int (*mdio_read)(adapter_t *adapter, int phy_addr, int mmd_addr,
-                        int reg_addr, unsigned int *val);
-       int (*mdio_write)(adapter_t *adapter, int phy_addr, int mmd_addr,
-                         int reg_addr, unsigned int val);
+       struct mdio_if_info mdio;
        struct cphy_instance *instance;
 };
 
 /* Convenience MDIO read/write wrappers */
-static inline int mdio_read(struct cphy *cphy, int mmd, int reg,
-                           unsigned int *valp)
+static inline int cphy_mdio_read(struct cphy *cphy, int mmd, int reg,
+                                unsigned int *valp)
 {
-       return cphy->mdio_read(cphy->adapter, cphy->addr, mmd, reg, valp);
+       int rc = cphy->mdio.mdio_read(cphy->mdio.dev, cphy->mdio.prtad, mmd,
+                                     reg);
+       *valp = (rc >= 0) ? rc : -1;
+       return (rc >= 0) ? 0 : rc;
 }
 
-static inline int mdio_write(struct cphy *cphy, int mmd, int reg,
-                            unsigned int val)
+static inline int cphy_mdio_write(struct cphy *cphy, int mmd, int reg,
+                                 unsigned int val)
 {
-       return cphy->mdio_write(cphy->adapter, cphy->addr, mmd, reg, val);
+       return cphy->mdio.mdio_write(cphy->mdio.dev, cphy->mdio.prtad, mmd,
+                                    reg, val);
 }
 
 static inline int simple_mdio_read(struct cphy *cphy, int reg,
                                   unsigned int *valp)
 {
-       return mdio_read(cphy, 0, reg, valp);
+       return cphy_mdio_read(cphy, MDIO_DEVAD_NONE, reg, valp);
 }
 
 static inline int simple_mdio_write(struct cphy *cphy, int reg,
                                    unsigned int val)
 {
-       return mdio_write(cphy, 0, reg, val);
+       return cphy_mdio_write(cphy, MDIO_DEVAD_NONE, reg, val);
 }
 
 /* Convenience initializer */
@@ -139,11 +142,13 @@ static inline void cphy_init(struct cphy *phy, adapter_t *adapter,
                             const struct mdio_ops *mdio_ops)
 {
        phy->adapter = adapter;
-       phy->addr    = phy_addr;
        phy->ops     = phy_ops;
        if (mdio_ops) {
-               phy->mdio_read  = mdio_ops->read;
-               phy->mdio_write = mdio_ops->write;
+               phy->mdio.prtad = phy_addr;
+               phy->mdio.mmds = phy_ops->mmds;
+               phy->mdio.mode_support = mdio_ops->mode_support;
+               phy->mdio.mdio_read = mdio_ops->read;
+               phy->mdio.mdio_write = mdio_ops->write;
        }
 }
 
index fa06994f973770e4f46c27d902e8fc0c7a28ed10..082cdb28b5101fd4bfc1cf0d1f174170da3dfbbd 100644 (file)
@@ -589,7 +589,7 @@ static int get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
        }
 
        cmd->port = (cmd->supported & SUPPORTED_TP) ? PORT_TP : PORT_FIBRE;
-       cmd->phy_address = p->phy->addr;
+       cmd->phy_address = p->phy->mdio.prtad;
        cmd->transceiver = XCVR_EXTERNAL;
        cmd->autoneg = p->link_config.autoneg;
        cmd->maxtxpkt = 0;
@@ -849,39 +849,9 @@ static const struct ethtool_ops t1_ethtool_ops = {
 static int t1_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
 {
        struct adapter *adapter = dev->ml_priv;
-       struct mii_ioctl_data *data = if_mii(req);
-
-       switch (cmd) {
-       case SIOCGMIIPHY:
-               data->phy_id = adapter->port[dev->if_port].phy->addr;
-               /* FALLTHRU */
-       case SIOCGMIIREG: {
-               struct cphy *phy = adapter->port[dev->if_port].phy;
-               u32 val;
-
-               if (!phy->mdio_read)
-                       return -EOPNOTSUPP;
-               phy->mdio_read(adapter, data->phy_id, 0, data->reg_num & 0x1f,
-                              &val);
-               data->val_out = val;
-               break;
-       }
-       case SIOCSMIIREG: {
-               struct cphy *phy = adapter->port[dev->if_port].phy;
-
-               if (!capable(CAP_NET_ADMIN))
-                   return -EPERM;
-               if (!phy->mdio_write)
-                       return -EOPNOTSUPP;
-               phy->mdio_write(adapter, data->phy_id, 0, data->reg_num & 0x1f,
-                               data->val_in);
-               break;
-       }
+       struct mdio_if_info *mdio = &adapter->port[dev->if_port].phy->mdio;
 
-       default:
-               return -EOPNOTSUPP;
-       }
-       return 0;
+       return mdio_mii_ioctl(mdio, if_mii(req), cmd);
 }
 
 static int t1_change_mtu(struct net_device *dev, int new_mtu)
index cd856041af34dfe861c54be45e84ce630102d6c8..29e0cba48d534cb620977d7278b08c5c1ae1aa32 100644 (file)
@@ -53,7 +53,7 @@ static int led_init(struct cphy *cphy)
         * Writing these bits maps control to another
         * register. mmd(0x1) addr(0x7)
         */
-       mdio_write(cphy, 0x3, 0x8304, 0xdddd);
+       cphy_mdio_write(cphy, MDIO_MMD_PCS, 0x8304, 0xdddd);
        return 0;
 }
 
@@ -62,14 +62,14 @@ static int led_link(struct cphy *cphy, u32 do_enable)
        u32 led = 0;
 #define LINK_ENABLE_BIT 0x1
 
-       mdio_read(cphy, 0x1, 0x7, &led);
+       cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_CTRL2, &led);
 
        if (do_enable & LINK_ENABLE_BIT) {
                led |= LINK_ENABLE_BIT;
-               mdio_write(cphy, 0x1, 0x7, led);
+               cphy_mdio_write(cphy, MDIO_MMD_PMAPMD, MDIO_CTRL2, led);
        } else {
                led &= ~LINK_ENABLE_BIT;
-               mdio_write(cphy, 0x1, 0x7, led);
+               cphy_mdio_write(cphy, MDIO_MMD_PMAPMD, MDIO_CTRL2, led);
        }
        return 0;
 }
@@ -86,7 +86,7 @@ static int mv88x201x_reset(struct cphy *cphy, int wait)
 static int mv88x201x_interrupt_enable(struct cphy *cphy)
 {
        /* Enable PHY LASI interrupts. */
-       mdio_write(cphy, 0x1, 0x9002, 0x1);
+       cphy_mdio_write(cphy, MDIO_MMD_PMAPMD, 0x9002, 0x1);
 
        /* Enable Marvell interrupts through Elmer0. */
        if (t1_is_asic(cphy->adapter)) {
@@ -102,7 +102,7 @@ static int mv88x201x_interrupt_enable(struct cphy *cphy)
 static int mv88x201x_interrupt_disable(struct cphy *cphy)
 {
        /* Disable PHY LASI interrupts. */
-       mdio_write(cphy, 0x1, 0x9002, 0x0);
+       cphy_mdio_write(cphy, MDIO_MMD_PMAPMD, 0x9002, 0x0);
 
        /* Disable Marvell interrupts through Elmer0. */
        if (t1_is_asic(cphy->adapter)) {
@@ -122,25 +122,25 @@ static int mv88x201x_interrupt_clear(struct cphy *cphy)
 
 #ifdef MV88x2010_LINK_STATUS_BUGS
        /* Required to read twice before clear takes affect. */
-       mdio_read(cphy, 0x1, 0x9003, &val);
-       mdio_read(cphy, 0x1, 0x9004, &val);
-       mdio_read(cphy, 0x1, 0x9005, &val);
+       cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, 0x9003, &val);
+       cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, 0x9004, &val);
+       cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, 0x9005, &val);
 
        /* Read this register after the others above it else
         * the register doesn't clear correctly.
         */
-       mdio_read(cphy, 0x1, 0x1, &val);
+       cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val);
 #endif
 
        /* Clear link status. */
-       mdio_read(cphy, 0x1, 0x1, &val);
+       cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val);
        /* Clear PHY LASI interrupts. */
-       mdio_read(cphy, 0x1, 0x9005, &val);
+       cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, 0x9005, &val);
 
 #ifdef MV88x2010_LINK_STATUS_BUGS
        /* Do it again. */
-       mdio_read(cphy, 0x1, 0x9003, &val);
-       mdio_read(cphy, 0x1, 0x9004, &val);
+       cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, 0x9003, &val);
+       cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, 0x9004, &val);
 #endif
 
        /* Clear Marvell interrupts through Elmer0. */
@@ -172,13 +172,12 @@ static int mv88x201x_get_link_status(struct cphy *cphy, int *link_ok,
                                     int *speed, int *duplex, int *fc)
 {
        u32 val = 0;
-#define LINK_STATUS_BIT 0x4
 
        if (link_ok) {
                /* Read link status. */
-               mdio_read(cphy, 0x1, 0x1, &val);
-               val &= LINK_STATUS_BIT;
-               *link_ok = (val == LINK_STATUS_BIT);
+               cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val);
+               val &= MDIO_STAT1_LSTATUS;
+               *link_ok = (val == MDIO_STAT1_LSTATUS);
                /* Turn on/off Link LED */
                led_link(cphy, *link_ok);
        }
@@ -205,6 +204,8 @@ static struct cphy_ops mv88x201x_ops = {
        .interrupt_handler = mv88x201x_interrupt_handler,
        .get_link_status   = mv88x201x_get_link_status,
        .set_loopback      = mv88x201x_set_loopback,
+       .mmds              = (MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS |
+                             MDIO_DEVS_PHYXS | MDIO_DEVS_WIS),
 };
 
 static struct cphy *mv88x201x_phy_create(adapter_t *adapter, int phy_addr,
@@ -219,12 +220,12 @@ static struct cphy *mv88x201x_phy_create(adapter_t *adapter, int phy_addr,
        cphy_init(cphy, adapter, phy_addr, &mv88x201x_ops, mdio_ops);
 
        /* Commands the PHY to enable XFP's clock. */
-       mdio_read(cphy, 0x3, 0x8300, &val);
-       mdio_write(cphy, 0x3, 0x8300, val | 1);
+       cphy_mdio_read(cphy, MDIO_MMD_PCS, 0x8300, &val);
+       cphy_mdio_write(cphy, MDIO_MMD_PCS, 0x8300, val | 1);
 
        /* Clear link status. Required because of a bug in the PHY.  */
-       mdio_read(cphy, 0x1, 0x8, &val);
-       mdio_read(cphy, 0x3, 0x8, &val);
+       cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT2, &val);
+       cphy_mdio_read(cphy, MDIO_MMD_PCS, MDIO_STAT2, &val);
 
        /* Allows for Link,Ack LED turn on/off */
        led_init(cphy);
index 040acd29995a2c5681f2816c620b43e64e0d17f0..977c7e08b0e0b9f304ab2b1af55cd94747c9eb6c 100644 (file)
@@ -43,11 +43,11 @@ static int my3126_interrupt_handler(struct cphy *cphy)
        adapter = cphy->adapter;
 
        if (cphy->count == 50) {
-               mdio_read(cphy, 0x1, 0x1, &val);
+               cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val);
                val16 = (u16) val;
                status = cphy->bmsr ^ val16;
 
-               if (status & BMSR_LSTATUS)
+               if (status & MDIO_STAT1_LSTATUS)
                        t1_link_changed(adapter, 0);
                cphy->bmsr = val16;
 
@@ -114,14 +114,14 @@ static int my3126_get_link_status(struct cphy *cphy,
        adapter_t *adapter;
 
        adapter = cphy->adapter;
-       mdio_read(cphy, 0x1, 0x1, &val);
+       cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val);
        val16 = (u16) val;
 
        /* Populate elmer_gpo with the register value */
        t1_tpi_read(adapter, A_ELMER0_GPO, &val);
        cphy->elmer_gpo = val;
 
-       *link_ok = (val16 & BMSR_LSTATUS);
+       *link_ok = (val16 & MDIO_STAT1_LSTATUS);
 
        if (*link_ok) {
                /* Turn on the LED. */
@@ -163,6 +163,8 @@ static struct cphy_ops my3126_ops = {
        .interrupt_handler      = my3126_interrupt_handler,
        .get_link_status        = my3126_get_link_status,
        .set_loopback           = my3126_set_loopback,
+       .mmds                   = (MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS |
+                                  MDIO_DEVS_PHYXS),
 };
 
 static struct cphy *my3126_phy_create(adapter_t *adapter,
index 7adf30230c4f7123d03d91e2f9c500f26d4a49f8..2564312b3056c68bdbf50216c56882ed3c2da24b 100644 (file)
@@ -284,32 +284,29 @@ static void mi1_mdio_init(adapter_t *adapter, const struct board_info *bi)
 /*
  * Elmer MI1 MDIO read/write operations.
  */
-static int mi1_mdio_read(adapter_t *adapter, int phy_addr, int mmd_addr,
-                        int reg_addr, unsigned int *valp)
+static int mi1_mdio_read(struct net_device *dev, int phy_addr, int mmd_addr,
+                        u16 reg_addr)
 {
+       struct adapter *adapter = dev->ml_priv;
        u32 addr = V_MI1_REG_ADDR(reg_addr) | V_MI1_PHY_ADDR(phy_addr);
-
-       if (mmd_addr)
-               return -EINVAL;
+       unsigned int val;
 
        spin_lock(&adapter->tpi_lock);
        __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr);
        __t1_tpi_write(adapter,
                        A_ELMER0_PORT0_MI1_OP, MI1_OP_DIRECT_READ);
        mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
-       __t1_tpi_read(adapter, A_ELMER0_PORT0_MI1_DATA, valp);
+       __t1_tpi_read(adapter, A_ELMER0_PORT0_MI1_DATA, &val);
        spin_unlock(&adapter->tpi_lock);
-       return 0;
+       return val;
 }
 
-static int mi1_mdio_write(adapter_t *adapter, int phy_addr, int mmd_addr,
-                         int reg_addr, unsigned int val)
+static int mi1_mdio_write(struct net_device *dev, int phy_addr, int mmd_addr,
+                         u16 reg_addr, u16 val)
 {
+       struct adapter *adapter = dev->ml_priv;
        u32 addr = V_MI1_REG_ADDR(reg_addr) | V_MI1_PHY_ADDR(phy_addr);
 
-       if (mmd_addr)
-               return -EINVAL;
-
        spin_lock(&adapter->tpi_lock);
        __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr);
        __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_DATA, val);
@@ -324,16 +321,19 @@ static int mi1_mdio_write(adapter_t *adapter, int phy_addr, int mmd_addr,
 static const struct mdio_ops mi1_mdio_ops = {
        .init = mi1_mdio_init,
        .read = mi1_mdio_read,
-       .write = mi1_mdio_write
+       .write = mi1_mdio_write,
+       .mode_support = MDIO_SUPPORTS_C22
 };
 #endif
 
 #endif
 
-static int mi1_mdio_ext_read(adapter_t *adapter, int phy_addr, int mmd_addr,
-                            int reg_addr, unsigned int *valp)
+static int mi1_mdio_ext_read(struct net_device *dev, int phy_addr, int mmd_addr,
+                            u16 reg_addr)
 {
+       struct adapter *adapter = dev->ml_priv;
        u32 addr = V_MI1_REG_ADDR(mmd_addr) | V_MI1_PHY_ADDR(phy_addr);
+       unsigned int val;
 
        spin_lock(&adapter->tpi_lock);
 
@@ -350,14 +350,15 @@ static int mi1_mdio_ext_read(adapter_t *adapter, int phy_addr, int mmd_addr,
        mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
 
        /* Read the data. */
-       __t1_tpi_read(adapter, A_ELMER0_PORT0_MI1_DATA, valp);
+       __t1_tpi_read(adapter, A_ELMER0_PORT0_MI1_DATA, &val);
        spin_unlock(&adapter->tpi_lock);
-       return 0;
+       return val;
 }
 
-static int mi1_mdio_ext_write(adapter_t *adapter, int phy_addr, int mmd_addr,
-                             int reg_addr, unsigned int val)
+static int mi1_mdio_ext_write(struct net_device *dev, int phy_addr,
+                             int mmd_addr, u16 reg_addr, u16 val)
 {
+       struct adapter *adapter = dev->ml_priv;
        u32 addr = V_MI1_REG_ADDR(mmd_addr) | V_MI1_PHY_ADDR(phy_addr);
 
        spin_lock(&adapter->tpi_lock);
@@ -380,7 +381,8 @@ static int mi1_mdio_ext_write(adapter_t *adapter, int phy_addr, int mmd_addr,
 static const struct mdio_ops mi1_mdio_ext_ops = {
        .init = mi1_mdio_init,
        .read = mi1_mdio_ext_read,
-       .write = mi1_mdio_ext_write
+       .write = mi1_mdio_ext_write,
+       .mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22
 };
 
 enum {
@@ -1140,6 +1142,7 @@ int __devinit t1_init_sw_modules(adapter_t *adapter,
                               adapter->name, i);
                        goto error;
                }
+               adapter->port[i].phy->mdio.dev = adapter->port[i].dev;
 
                adapter->port[i].mac = mac = bi->gmac->create(adapter, i);
                if (!mac) {