Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0f07c4ee authored by Ben Hutchings's avatar Ben Hutchings Committed by David S. Miller
Browse files

cxgb3: Use generic MDIO definitions and mdio_mii_ioctl()



Compile-tested only.

Signed-off-by: default avatarBen Hutchings <bhutchings@solarflare.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 23c3320c
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -2483,6 +2483,7 @@ config CHELSIO_T3
	tristate "Chelsio Communications T3 10Gb Ethernet support"
	depends on CHELSIO_T3_DEPENDS
	select FW_LOADER
	select MDIO
	help
	  This driver supports Chelsio T3-based gigabit and 10Gb Ethernet
	  adapters.
+76 −70
Original line number Diff line number Diff line
@@ -33,14 +33,6 @@
#include "regs.h"

enum {
	PMD_RSD     = 10,   /* PMA/PMD receive signal detect register */
	PCS_STAT1_X = 24,   /* 10GBASE-X PCS status 1 register */
	PCS_STAT1_R = 32,   /* 10GBASE-R PCS status 1 register */
	XS_LN_STAT  = 24    /* XS lane status register */
};

enum {
	AEL100X_TX_DISABLE = 9,
	AEL100X_TX_CONFIG1 = 0xc002,
	AEL1002_PWR_DOWN_HI = 0xc011,
	AEL1002_PWR_DOWN_LO = 0xc012,
@@ -74,7 +66,7 @@ static int set_phy_regs(struct cphy *phy, const struct reg_val *rv)

	for (err = 0; rv->mmd_addr && !err; rv++) {
		if (rv->clear_bits == 0xffff)
			err = mdio_write(phy, rv->mmd_addr, rv->reg_addr,
			err = t3_mdio_write(phy, rv->mmd_addr, rv->reg_addr,
					    rv->set_bits);
		else
			err = t3_mdio_change_bits(phy, rv->mmd_addr,
@@ -86,7 +78,8 @@ static int set_phy_regs(struct cphy *phy, const struct reg_val *rv)

static void ael100x_txon(struct cphy *phy)
{
	int tx_on_gpio = phy->addr == 0 ? F_GPIO7_OUT_VAL : F_GPIO2_OUT_VAL;
	int tx_on_gpio =
		phy->mdio.prtad == 0 ? F_GPIO7_OUT_VAL : F_GPIO2_OUT_VAL;

	msleep(100);
	t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN, 0, tx_on_gpio);
@@ -97,10 +90,11 @@ static int ael1002_power_down(struct cphy *phy, int enable)
{
	int err;

	err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL100X_TX_DISABLE, !!enable);
	err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, MDIO_PMA_TXDIS, !!enable);
	if (!err)
		err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR,
					  BMCR_PDOWN, enable ? BMCR_PDOWN : 0);
		err = mdio_set_flag(&phy->mdio, phy->mdio.prtad,
				    MDIO_MMD_PMAPMD, MDIO_CTRL1,
				    MDIO_CTRL1_LPOWER, enable);
	return err;
}

@@ -109,11 +103,11 @@ static int ael1002_reset(struct cphy *phy, int wait)
	int err;

	if ((err = ael1002_power_down(phy, 0)) ||
	    (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL100X_TX_CONFIG1, 1)) ||
	    (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_PWR_DOWN_HI, 0)) ||
	    (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_PWR_DOWN_LO, 0)) ||
	    (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_XFI_EQL, 0x18)) ||
	    (err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, AEL1002_LB_EN,
	    (err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL100X_TX_CONFIG1, 1)) ||
	    (err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL1002_PWR_DOWN_HI, 0)) ||
	    (err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL1002_PWR_DOWN_LO, 0)) ||
	    (err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL1002_XFI_EQL, 0x18)) ||
	    (err = t3_mdio_change_bits(phy, MDIO_MMD_PMAPMD, AEL1002_LB_EN,
				       0, 1 << 5)))
		return err;
	return 0;
@@ -132,12 +126,15 @@ static int get_link_status_r(struct cphy *phy, int *link_ok, int *speed,
{
	if (link_ok) {
		unsigned int stat0, stat1, stat2;
		int err = mdio_read(phy, MDIO_DEV_PMA_PMD, PMD_RSD, &stat0);
		int err = t3_mdio_read(phy, MDIO_MMD_PMAPMD,
				       MDIO_PMA_RXDET, &stat0);

		if (!err)
			err = mdio_read(phy, MDIO_DEV_PCS, PCS_STAT1_R, &stat1);
			err = t3_mdio_read(phy, MDIO_MMD_PCS,
					   MDIO_PCS_10GBRT_STAT1, &stat1);
		if (!err)
			err = mdio_read(phy, MDIO_DEV_XGXS, XS_LN_STAT, &stat2);
			err = t3_mdio_read(phy, MDIO_MMD_PHYXS,
					   MDIO_PHYXS_LNSTAT, &stat2);
		if (err)
			return err;
		*link_ok = (stat0 & stat1 & (stat2 >> 12)) & 1;
@@ -157,6 +154,7 @@ static struct cphy_ops ael1002_ops = {
	.intr_handler = ael1002_intr_noop,
	.get_link_status = get_link_status_r,
	.power_down = ael1002_power_down,
	.mmds = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS,
};

int t3_ael1002_phy_prep(struct cphy *phy, struct adapter *adapter,
@@ -171,13 +169,13 @@ int t3_ael1002_phy_prep(struct cphy *phy, struct adapter *adapter,

static int ael1006_reset(struct cphy *phy, int wait)
{
	return t3_phy_reset(phy, MDIO_DEV_PMA_PMD, wait);
	return t3_phy_reset(phy, MDIO_MMD_PMAPMD, wait);
}

static int ael1006_power_down(struct cphy *phy, int enable)
{
	return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR,
				   BMCR_PDOWN, enable ? BMCR_PDOWN : 0);
	return mdio_set_flag(&phy->mdio, phy->mdio.prtad, MDIO_MMD_PMAPMD,
			     MDIO_CTRL1, MDIO_CTRL1_LPOWER, enable);
}

static struct cphy_ops ael1006_ops = {
@@ -188,6 +186,7 @@ static struct cphy_ops ael1006_ops = {
	.intr_handler = t3_phy_lasi_intr_handler,
	.get_link_status = get_link_status_r,
	.power_down = ael1006_power_down,
	.mmds = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS,
};

int t3_ael1006_phy_prep(struct cphy *phy, struct adapter *adapter,
@@ -203,9 +202,9 @@ int t3_ael1006_phy_prep(struct cphy *phy, struct adapter *adapter,
static int ael2005_setup_sr_edc(struct cphy *phy)
{
	static struct reg_val regs[] = {
		{ MDIO_DEV_PMA_PMD, 0xc003, 0xffff, 0x181 },
		{ MDIO_DEV_PMA_PMD, 0xc010, 0xffff, 0x448a },
		{ MDIO_DEV_PMA_PMD, 0xc04a, 0xffff, 0x5200 },
		{ MDIO_MMD_PMAPMD, 0xc003, 0xffff, 0x181 },
		{ MDIO_MMD_PMAPMD, 0xc010, 0xffff, 0x448a },
		{ MDIO_MMD_PMAPMD, 0xc04a, 0xffff, 0x5200 },
		{ 0, 0, 0, 0 }
	};
	static u16 sr_edc[] = {
@@ -490,7 +489,7 @@ static int ael2005_setup_sr_edc(struct cphy *phy)
	msleep(50);

	for (i = 0; i < ARRAY_SIZE(sr_edc) && !err; i += 2)
		err = mdio_write(phy, MDIO_DEV_PMA_PMD, sr_edc[i],
		err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, sr_edc[i],
				    sr_edc[i + 1]);
	if (!err)
		phy->priv = edc_sr;
@@ -500,12 +499,12 @@ static int ael2005_setup_sr_edc(struct cphy *phy)
static int ael2005_setup_twinax_edc(struct cphy *phy, int modtype)
{
	static struct reg_val regs[] = {
		{ MDIO_DEV_PMA_PMD, 0xc04a, 0xffff, 0x5a00 },
		{ MDIO_MMD_PMAPMD, 0xc04a, 0xffff, 0x5a00 },
		{ 0, 0, 0, 0 }
	};
	static struct reg_val preemphasis[] = {
		{ MDIO_DEV_PMA_PMD, 0xc014, 0xffff, 0xfe16 },
		{ MDIO_DEV_PMA_PMD, 0xc015, 0xffff, 0xa000 },
		{ MDIO_MMD_PMAPMD, 0xc014, 0xffff, 0xfe16 },
		{ MDIO_MMD_PMAPMD, 0xc015, 0xffff, 0xa000 },
		{ 0, 0, 0, 0 }
	};
	static u16 twinax_edc[] = {
@@ -887,7 +886,7 @@ static int ael2005_setup_twinax_edc(struct cphy *phy, int modtype)
	msleep(50);

	for (i = 0; i < ARRAY_SIZE(twinax_edc) && !err; i += 2)
		err = mdio_write(phy, MDIO_DEV_PMA_PMD, twinax_edc[i],
		err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, twinax_edc[i],
				    twinax_edc[i + 1]);
	if (!err)
		phy->priv = edc_twinax;
@@ -899,18 +898,18 @@ static int ael2005_i2c_rd(struct cphy *phy, int dev_addr, int word_addr)
	int i, err;
	unsigned int stat, data;

	err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL_I2C_CTRL,
	err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL_I2C_CTRL,
			    (dev_addr << 8) | (1 << 8) | word_addr);
	if (err)
		return err;

	for (i = 0; i < 5; i++) {
		msleep(1);
		err = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL_I2C_STAT, &stat);
		err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL_I2C_STAT, &stat);
		if (err)
			return err;
		if ((stat & 3) == 1) {
			err = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL_I2C_DATA,
			err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL_I2C_DATA,
					   &data);
			if (err)
				return err;
@@ -918,7 +917,7 @@ static int ael2005_i2c_rd(struct cphy *phy, int dev_addr, int word_addr)
		}
	}
	CH_WARN(phy->adapter, "PHY %u I2C read of addr %u timed out\n",
		phy->addr, word_addr);
		phy->mdio.prtad, word_addr);
	return -ETIMEDOUT;
}

@@ -927,7 +926,7 @@ static int get_module_type(struct cphy *phy, int delay_ms)
	int v;
	unsigned int stat;

	v = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, &stat);
	v = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_CTRL, &stat);
	if (v)
		return v;

@@ -971,48 +970,48 @@ static int get_module_type(struct cphy *phy, int delay_ms)

static int ael2005_intr_enable(struct cphy *phy)
{
	int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0x200);
	int err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_CTRL, 0x200);
	return err ? err : t3_phy_lasi_intr_enable(phy);
}

static int ael2005_intr_disable(struct cphy *phy)
{
	int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0x100);
	int err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_CTRL, 0x100);
	return err ? err : t3_phy_lasi_intr_disable(phy);
}

static int ael2005_intr_clear(struct cphy *phy)
{
	int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0xd00);
	int err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_CTRL, 0xd00);
	return err ? err : t3_phy_lasi_intr_clear(phy);
}

static int ael2005_reset(struct cphy *phy, int wait)
{
	static struct reg_val regs0[] = {
		{ MDIO_DEV_PMA_PMD, 0xc001, 0, 1 << 5 },
		{ MDIO_DEV_PMA_PMD, 0xc017, 0, 1 << 5 },
		{ MDIO_DEV_PMA_PMD, 0xc013, 0xffff, 0xf341 },
		{ MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8000 },
		{ MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8100 },
		{ MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8000 },
		{ MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0 },
		{ MDIO_MMD_PMAPMD, 0xc001, 0, 1 << 5 },
		{ MDIO_MMD_PMAPMD, 0xc017, 0, 1 << 5 },
		{ MDIO_MMD_PMAPMD, 0xc013, 0xffff, 0xf341 },
		{ MDIO_MMD_PMAPMD, 0xc210, 0xffff, 0x8000 },
		{ MDIO_MMD_PMAPMD, 0xc210, 0xffff, 0x8100 },
		{ MDIO_MMD_PMAPMD, 0xc210, 0xffff, 0x8000 },
		{ MDIO_MMD_PMAPMD, 0xc210, 0xffff, 0 },
		{ 0, 0, 0, 0 }
	};
	static struct reg_val regs1[] = {
		{ MDIO_DEV_PMA_PMD, 0xca00, 0xffff, 0x0080 },
		{ MDIO_DEV_PMA_PMD, 0xca12, 0xffff, 0 },
		{ MDIO_MMD_PMAPMD, 0xca00, 0xffff, 0x0080 },
		{ MDIO_MMD_PMAPMD, 0xca12, 0xffff, 0 },
		{ 0, 0, 0, 0 }
	};

	int err;
	unsigned int lasi_ctrl;

	err = mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, &lasi_ctrl);
	err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, LASI_CTRL, &lasi_ctrl);
	if (err)
		return err;

	err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, 0);
	err = t3_phy_reset(phy, MDIO_MMD_PMAPMD, 0);
	if (err)
		return err;

@@ -1051,12 +1050,12 @@ static int ael2005_intr_handler(struct cphy *phy)
	unsigned int stat;
	int ret, edc_needed, cause = 0;

	ret = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_STAT, &stat);
	ret = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_STAT, &stat);
	if (ret)
		return ret;

	if (stat & AEL2005_MODDET_IRQ) {
		ret = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL,
		ret = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_CTRL,
				    0xd00);
		if (ret)
			return ret;
@@ -1098,6 +1097,7 @@ static struct cphy_ops ael2005_ops = {
	.intr_handler    = ael2005_intr_handler,
	.get_link_status = get_link_status_r,
	.power_down      = ael1002_power_down,
	.mmds            = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS,
};

int t3_ael2005_phy_prep(struct cphy *phy, struct adapter *adapter,
@@ -1107,7 +1107,7 @@ int t3_ael2005_phy_prep(struct cphy *phy, struct adapter *adapter,
		  SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE |
		  SUPPORTED_IRQ, "10GBASE-R");
	msleep(125);
	return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, AEL_OPT_SETTINGS, 0,
	return t3_mdio_change_bits(phy, MDIO_MMD_PMAPMD, AEL_OPT_SETTINGS, 0,
				   1 << 5);
}

@@ -1119,12 +1119,15 @@ static int get_link_status_x(struct cphy *phy, int *link_ok, int *speed,
{
	if (link_ok) {
		unsigned int stat0, stat1, stat2;
		int err = mdio_read(phy, MDIO_DEV_PMA_PMD, PMD_RSD, &stat0);
		int err = t3_mdio_read(phy, MDIO_MMD_PMAPMD,
				       MDIO_PMA_RXDET, &stat0);

		if (!err)
			err = mdio_read(phy, MDIO_DEV_PCS, PCS_STAT1_X, &stat1);
			err = t3_mdio_read(phy, MDIO_MMD_PCS,
					   MDIO_PCS_10GBX_STAT1, &stat1);
		if (!err)
			err = mdio_read(phy, MDIO_DEV_XGXS, XS_LN_STAT, &stat2);
			err = t3_mdio_read(phy, MDIO_MMD_PHYXS,
					   MDIO_PHYXS_LNSTAT, &stat2);
		if (err)
			return err;
		*link_ok = (stat0 & (stat1 >> 12) & (stat2 >> 12)) & 1;
@@ -1144,6 +1147,7 @@ static struct cphy_ops qt2045_ops = {
	.intr_handler = t3_phy_lasi_intr_handler,
	.get_link_status = get_link_status_x,
	.power_down = ael1006_power_down,
	.mmds = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS,
};

int t3_qt2045_phy_prep(struct cphy *phy, struct adapter *adapter,
@@ -1159,9 +1163,10 @@ int t3_qt2045_phy_prep(struct cphy *phy, struct adapter *adapter,
	 * Some cards where the PHY is supposed to be at address 0 actually
	 * have it at 1.
	 */
	if (!phy_addr && !mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR, &stat) &&
	if (!phy_addr &&
	    !t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_STAT1, &stat) &&
	    stat == 0xffff)
		phy->addr = 1;
		phy->mdio.prtad = 1;
	return 0;
}

@@ -1175,15 +1180,16 @@ static int xaui_direct_get_link_status(struct cphy *phy, int *link_ok,
{
	if (link_ok) {
		unsigned int status;
		int prtad = phy->mdio.prtad;

		status = t3_read_reg(phy->adapter,
				     XGM_REG(A_XGM_SERDES_STAT0, phy->addr)) |
				     XGM_REG(A_XGM_SERDES_STAT0, prtad)) |
		    t3_read_reg(phy->adapter,
				XGM_REG(A_XGM_SERDES_STAT1, phy->addr)) |
				    XGM_REG(A_XGM_SERDES_STAT1, prtad)) |
		    t3_read_reg(phy->adapter,
				XGM_REG(A_XGM_SERDES_STAT2, phy->addr)) |
				XGM_REG(A_XGM_SERDES_STAT2, prtad)) |
		    t3_read_reg(phy->adapter,
				XGM_REG(A_XGM_SERDES_STAT3, phy->addr));
				XGM_REG(A_XGM_SERDES_STAT3, prtad));
		*link_ok = !(status & F_LOWSIG0);
	}
	if (speed)
@@ -1211,7 +1217,7 @@ static struct cphy_ops xaui_direct_ops = {
int t3_xaui_direct_phy_prep(struct cphy *phy, struct adapter *adapter,
			    int phy_addr, const struct mdio_ops *mdio_ops)
{
	cphy_init(phy, adapter, phy_addr, &xaui_direct_ops, mdio_ops,
	cphy_init(phy, adapter, MDIO_PRTAD_NONE, &xaui_direct_ops, mdio_ops,
		  SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP,
		  "10GBASE-CX4");
	return 0;
+23 −30
Original line number Diff line number Diff line
@@ -39,7 +39,7 @@
#include <linux/init.h>
#include <linux/netdevice.h>
#include <linux/ethtool.h>
#include <linux/mii.h>
#include <linux/mdio.h>
#include "version.h"

#define CH_ERR(adap, fmt, ...)   dev_err(&adap->pdev->dev, fmt, ## __VA_ARGS__)
@@ -184,10 +184,11 @@ struct cphy;
struct adapter;

struct mdio_ops {
	int (*read)(struct adapter *adapter, int phy_addr, int mmd_addr,
		    int reg_addr, unsigned int *val);
	int (*write)(struct adapter *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;
};

struct adapter_info {
@@ -520,17 +521,6 @@ enum {
	MAC_RXFIFO_SIZE = 32768
};

/* IEEE 802.3 specified MDIO devices */
enum {
	MDIO_DEV_PMA_PMD = 1,
	MDIO_DEV_WIS = 2,
	MDIO_DEV_PCS = 3,
	MDIO_DEV_XGXS = 4,
	MDIO_DEV_ANEG = 7,
	MDIO_DEV_VEND1 = 30,
	MDIO_DEV_VEND2 = 31
};

/* LASI control and status registers */
enum {
	RX_ALARM_CTRL = 0x9000,
@@ -583,11 +573,12 @@ struct cphy_ops {
	int (*get_link_status)(struct cphy *phy, int *link_ok, int *speed,
			       int *duplex, int *fc);
	int (*power_down)(struct cphy *phy, int enable);

	u32 mmds;
};

/* A PHY instance */
struct cphy {
	u8 addr;			/* PHY address */
	u8 modtype;			/* PHY module type */
	short priv;			/* scratch pad */
	unsigned int caps;		/* PHY capabilities */
@@ -595,23 +586,23 @@ struct cphy {
	const char *desc;		/* PHY description */
	unsigned long fifo_errors;	/* FIFO over/under-flows */
	const struct cphy_ops *ops;	/* PHY operations */
	int (*mdio_read)(struct adapter *adapter, int phy_addr, int mmd_addr,
			 int reg_addr, unsigned int *val);
	int (*mdio_write)(struct adapter *adapter, int phy_addr, int mmd_addr,
			  int reg_addr, unsigned int val);
	struct mdio_if_info mdio;
};

/* Convenience MDIO read/write wrappers */
static inline int mdio_read(struct cphy *phy, int mmd, int reg,
static inline int t3_mdio_read(struct cphy *phy, int mmd, int reg,
			       unsigned int *valp)
{
	return phy->mdio_read(phy->adapter, phy->addr, mmd, reg, valp);
	int rc = phy->mdio.mdio_read(phy->mdio.dev, phy->mdio.prtad, mmd, reg);
	*valp = (rc >= 0) ? rc : -1;
	return (rc >= 0) ? 0 : rc;
}

static inline int mdio_write(struct cphy *phy, int mmd, int reg,
static inline int t3_mdio_write(struct cphy *phy, int mmd, int reg,
				unsigned int val)
{
	return phy->mdio_write(phy->adapter, phy->addr, mmd, reg, val);
	return phy->mdio.mdio_write(phy->mdio.dev, phy->mdio.prtad, mmd,
				    reg, val);
}

/* Convenience initializer */
@@ -620,14 +611,16 @@ static inline void cphy_init(struct cphy *phy, struct adapter *adapter,
			     const struct mdio_ops *mdio_ops,
			      unsigned int caps, const char *desc)
{
	phy->addr = phy_addr;
	phy->caps = caps;
	phy->adapter = adapter;
	phy->desc = desc;
	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;
	}
}

+13 −58
Original line number Diff line number Diff line
@@ -37,7 +37,7 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/if_vlan.h>
#include <linux/mii.h>
#include <linux/mdio.h>
#include <linux/sockios.h>
#include <linux/workqueue.h>
#include <linux/proc_fs.h>
@@ -1593,7 +1593,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;
@@ -2308,70 +2308,25 @@ static int cxgb_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
	struct mii_ioctl_data *data = if_mii(req);
	struct port_info *pi = netdev_priv(dev);
	struct adapter *adapter = pi->adapter;
	int ret, mmd;

	switch (cmd) {
	case SIOCGMIIPHY:
		data->phy_id = pi->phy.addr;
	case SIOCGMIIREG:
	case SIOCSMIIREG:
		/* Convert phy_id from older PRTAD/DEVAD format */
		if (is_10G(adapter) &&
		    !mdio_phy_id_is_c45(data->phy_id) &&
		    (data->phy_id & 0x1f00) &&
		    !(data->phy_id & 0xe0e0))
			data->phy_id = mdio_phy_id_c45(data->phy_id >> 8,
						       data->phy_id & 0x1f);
		/* FALLTHRU */
	case SIOCGMIIREG:{
		u32 val;
		struct cphy *phy = &pi->phy;

		if (!phy->mdio_read)
			return -EOPNOTSUPP;
		if (is_10G(adapter)) {
			mmd = data->phy_id >> 8;
			if (!mmd)
				mmd = MDIO_DEV_PCS;
			else if (mmd > MDIO_DEV_VEND2)
				return -EINVAL;

			ret =
				phy->mdio_read(adapter, data->phy_id & 0x1f,
						mmd, data->reg_num, &val);
		} else
			ret =
				phy->mdio_read(adapter, data->phy_id & 0x1f,
						0, data->reg_num & 0x1f,
						&val);
		if (!ret)
			data->val_out = val;
		break;
	}
	case SIOCSMIIREG:{
		struct cphy *phy = &pi->phy;

		if (!capable(CAP_NET_ADMIN))
			return -EPERM;
		if (!phy->mdio_write)
			return -EOPNOTSUPP;
		if (is_10G(adapter)) {
			mmd = data->phy_id >> 8;
			if (!mmd)
				mmd = MDIO_DEV_PCS;
			else if (mmd > MDIO_DEV_VEND2)
				return -EINVAL;

			ret =
				phy->mdio_write(adapter,
						data->phy_id & 0x1f, mmd,
						data->reg_num,
						data->val_in);
		} else
			ret =
				phy->mdio_write(adapter,
						data->phy_id & 0x1f, 0,
						data->reg_num & 0x1f,
						data->val_in);
		break;
	}
	case SIOCGMIIPHY:
		return mdio_mii_ioctl(&pi->phy.mdio, data, cmd);
	case SIOCCHIOCTL:
		return cxgb_extension_ioctl(dev, req->ifr_data);
	default:
		return -EOPNOTSUPP;
	}
	return ret;
}

static int cxgb_change_mtu(struct net_device *dev, int new_mtu)
+42 −36
Original line number Diff line number Diff line
@@ -204,35 +204,33 @@ static void mi1_init(struct adapter *adap, const struct adapter_info *ai)
/*
 * MI1 read/write operations for clause 22 PHYs.
 */
static int t3_mi1_read(struct adapter *adapter, int phy_addr, int mmd_addr,
		       int reg_addr, unsigned int *valp)
static int t3_mi1_read(struct net_device *dev, int phy_addr, int mmd_addr,
		       u16 reg_addr)
{
	struct port_info *pi = netdev_priv(dev);
	struct adapter *adapter = pi->adapter;
	int ret;
	u32 addr = V_REGADDR(reg_addr) | V_PHYADDR(phy_addr);

	if (mmd_addr)
		return -EINVAL;

	mutex_lock(&adapter->mdio_lock);
	t3_set_reg_field(adapter, A_MI1_CFG, V_ST(M_ST), V_ST(1));
	t3_write_reg(adapter, A_MI1_ADDR, addr);
	t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(2));
	ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, MDIO_ATTEMPTS, 10);
	if (!ret)
		*valp = t3_read_reg(adapter, A_MI1_DATA);
		ret = t3_read_reg(adapter, A_MI1_DATA);
	mutex_unlock(&adapter->mdio_lock);
	return ret;
}

static int t3_mi1_write(struct adapter *adapter, int phy_addr, int mmd_addr,
		     int reg_addr, unsigned int val)
static int t3_mi1_write(struct net_device *dev, int phy_addr, int mmd_addr,
			u16 reg_addr, u16 val)
{
	struct port_info *pi = netdev_priv(dev);
	struct adapter *adapter = pi->adapter;
	int ret;
	u32 addr = V_REGADDR(reg_addr) | V_PHYADDR(phy_addr);

	if (mmd_addr)
		return -EINVAL;

	mutex_lock(&adapter->mdio_lock);
	t3_set_reg_field(adapter, A_MI1_CFG, V_ST(M_ST), V_ST(1));
	t3_write_reg(adapter, A_MI1_ADDR, addr);
@@ -244,8 +242,9 @@ static int t3_mi1_write(struct adapter *adapter, int phy_addr, int mmd_addr,
}

static const struct mdio_ops mi1_mdio_ops = {
	t3_mi1_read,
	t3_mi1_write
	.read = t3_mi1_read,
	.write = t3_mi1_write,
	.mode_support = MDIO_SUPPORTS_C22
};

/*
@@ -268,9 +267,11 @@ static int mi1_wr_addr(struct adapter *adapter, int phy_addr, int mmd_addr,
/*
 * MI1 read/write operations for indirect-addressed PHYs.
 */
static int mi1_ext_read(struct adapter *adapter, int phy_addr, int mmd_addr,
			int reg_addr, unsigned int *valp)
static int mi1_ext_read(struct net_device *dev, int phy_addr, int mmd_addr,
			u16 reg_addr)
{
	struct port_info *pi = netdev_priv(dev);
	struct adapter *adapter = pi->adapter;
	int ret;

	mutex_lock(&adapter->mdio_lock);
@@ -280,15 +281,17 @@ static int mi1_ext_read(struct adapter *adapter, int phy_addr, int mmd_addr,
		ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0,
				      MDIO_ATTEMPTS, 10);
		if (!ret)
			*valp = t3_read_reg(adapter, A_MI1_DATA);
			ret = t3_read_reg(adapter, A_MI1_DATA);
	}
	mutex_unlock(&adapter->mdio_lock);
	return ret;
}

static int mi1_ext_write(struct adapter *adapter, int phy_addr, int mmd_addr,
			 int reg_addr, unsigned int val)
static int mi1_ext_write(struct net_device *dev, int phy_addr, int mmd_addr,
			 u16 reg_addr, u16 val)
{
	struct port_info *pi = netdev_priv(dev);
	struct adapter *adapter = pi->adapter;
	int ret;

	mutex_lock(&adapter->mdio_lock);
@@ -304,8 +307,9 @@ static int mi1_ext_write(struct adapter *adapter, int phy_addr, int mmd_addr,
}

static const struct mdio_ops mi1_mdio_ext_ops = {
	mi1_ext_read,
	mi1_ext_write
	.read = mi1_ext_read,
	.write = mi1_ext_write,
	.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22
};

/**
@@ -325,10 +329,10 @@ int t3_mdio_change_bits(struct cphy *phy, int mmd, int reg, unsigned int clear,
	int ret;
	unsigned int val;

	ret = mdio_read(phy, mmd, reg, &val);
	ret = t3_mdio_read(phy, mmd, reg, &val);
	if (!ret) {
		val &= ~clear;
		ret = mdio_write(phy, mmd, reg, val | set);
		ret = t3_mdio_write(phy, mmd, reg, val | set);
	}
	return ret;
}
@@ -348,15 +352,16 @@ int t3_phy_reset(struct cphy *phy, int mmd, int wait)
	int err;
	unsigned int ctl;

	err = t3_mdio_change_bits(phy, mmd, MII_BMCR, BMCR_PDOWN, BMCR_RESET);
	err = t3_mdio_change_bits(phy, mmd, MDIO_CTRL1, MDIO_CTRL1_LPOWER,
				  MDIO_CTRL1_RESET);
	if (err || !wait)
		return err;

	do {
		err = mdio_read(phy, mmd, MII_BMCR, &ctl);
		err = t3_mdio_read(phy, mmd, MDIO_CTRL1, &ctl);
		if (err)
			return err;
		ctl &= BMCR_RESET;
		ctl &= MDIO_CTRL1_RESET;
		if (ctl)
			msleep(1);
	} while (ctl && --wait);
@@ -377,7 +382,7 @@ int t3_phy_advertise(struct cphy *phy, unsigned int advert)
	int err;
	unsigned int val = 0;

	err = mdio_read(phy, 0, MII_CTRL1000, &val);
	err = t3_mdio_read(phy, MDIO_DEVAD_NONE, MII_CTRL1000, &val);
	if (err)
		return err;

@@ -387,7 +392,7 @@ int t3_phy_advertise(struct cphy *phy, unsigned int advert)
	if (advert & ADVERTISED_1000baseT_Full)
		val |= ADVERTISE_1000FULL;

	err = mdio_write(phy, 0, MII_CTRL1000, val);
	err = t3_mdio_write(phy, MDIO_DEVAD_NONE, MII_CTRL1000, val);
	if (err)
		return err;

@@ -404,7 +409,7 @@ int t3_phy_advertise(struct cphy *phy, unsigned int advert)
		val |= ADVERTISE_PAUSE_CAP;
	if (advert & ADVERTISED_Asym_Pause)
		val |= ADVERTISE_PAUSE_ASYM;
	return mdio_write(phy, 0, MII_ADVERTISE, val);
	return t3_mdio_write(phy, MDIO_DEVAD_NONE, MII_ADVERTISE, val);
}

/**
@@ -427,7 +432,7 @@ int t3_phy_advertise_fiber(struct cphy *phy, unsigned int advert)
		val |= ADVERTISE_1000XPAUSE;
	if (advert & ADVERTISED_Asym_Pause)
		val |= ADVERTISE_1000XPSE_ASYM;
	return mdio_write(phy, 0, MII_ADVERTISE, val);
	return t3_mdio_write(phy, MDIO_DEVAD_NONE, MII_ADVERTISE, val);
}

/**
@@ -444,7 +449,7 @@ int t3_set_phy_speed_duplex(struct cphy *phy, int speed, int duplex)
	int err;
	unsigned int ctl;

	err = mdio_read(phy, 0, MII_BMCR, &ctl);
	err = t3_mdio_read(phy, MDIO_DEVAD_NONE, MII_BMCR, &ctl);
	if (err)
		return err;

@@ -462,30 +467,30 @@ int t3_set_phy_speed_duplex(struct cphy *phy, int speed, int duplex)
	}
	if (ctl & BMCR_SPEED1000) /* auto-negotiation required for GigE */
		ctl |= BMCR_ANENABLE;
	return mdio_write(phy, 0, MII_BMCR, ctl);
	return t3_mdio_write(phy, MDIO_DEVAD_NONE, MII_BMCR, ctl);
}

int t3_phy_lasi_intr_enable(struct cphy *phy)
{
	return mdio_write(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, 1);
	return t3_mdio_write(phy, MDIO_MMD_PMAPMD, LASI_CTRL, 1);
}

int t3_phy_lasi_intr_disable(struct cphy *phy)
{
	return mdio_write(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, 0);
	return t3_mdio_write(phy, MDIO_MMD_PMAPMD, LASI_CTRL, 0);
}

int t3_phy_lasi_intr_clear(struct cphy *phy)
{
	u32 val;

	return mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_STAT, &val);
	return t3_mdio_read(phy, MDIO_MMD_PMAPMD, LASI_STAT, &val);
}

int t3_phy_lasi_intr_handler(struct cphy *phy)
{
	unsigned int status;
	int err = mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_STAT, &status);
	int err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, LASI_STAT, &status);

	if (err)
		return err;
@@ -3863,6 +3868,7 @@ int t3_prep_adapter(struct adapter *adapter, const struct adapter_info *ai,
				    ai->mdio_ops);
		if (ret)
			return ret;
		p->phy.mdio.dev = adapter->port[i];
		mac_prep(&p->mac, adapter, j);

		/*
@@ -3918,7 +3924,7 @@ int t3_replay_prep_adapter(struct adapter *adapter)
			;

		pti = &port_types[adapter->params.vpd.port_type[j]];
		ret = pti->phy_prep(&p->phy, adapter, p->phy.addr, NULL);
		ret = pti->phy_prep(&p->phy, adapter, p->phy.mdio.prtad, NULL);
		if (ret)
			return ret;
		p->phy.ops->power_down(&p->phy, 1);
Loading