Skip to content

Commit

Permalink
Merge branch 'net-dsa-microchip-error-hndling-reg-access-validation'
Browse files Browse the repository at this point in the history
Oleksij Rempel says:

====================
net: dsa: microchip: add error handling and register access validation

changes v4:
- add Reviewed-by: Vladimir Oltean <olteanv@gmail.com> to all patches
- fix checkpatch warnings.

changes v3:
- fix build error in the middle of the patch stack.

changes v2:
- add regmap_ranges for KSZ9477
- drop output clock devicetree in driver validation patches. DTs need
  some more refactoring and can be done in a separate patch set.
- remove some unused variables.

This patch series adds error handling for the PHY read/write path and optional
register access validation.
After adding regmap_ranges for KSZ8563 some bugs was detected, so
critical bug fixes are sorted before ragmap_range patch.

Potentially this bug fixes can be ported to stable kernels, but need to be
reworked.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Aug 31, 2022
2 parents 21cb860 + 32cbac2 commit 2d919d3
Show file tree
Hide file tree
Showing 10 changed files with 652 additions and 123 deletions.
4 changes: 2 additions & 2 deletions drivers/net/dsa/microchip/ksz8.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ u32 ksz8_get_port_addr(int port, int offset);
void ksz8_cfg_port_member(struct ksz_device *dev, int port, u8 member);
void ksz8_flush_dyn_mac_table(struct ksz_device *dev, int port);
void ksz8_port_setup(struct ksz_device *dev, int port, bool cpu_port);
void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val);
void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val);
int ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val);
int ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val);
int ksz8_r_dyn_mac_table(struct ksz_device *dev, u16 addr, u8 *mac_addr,
u8 *fid, u8 *src_port, u8 *timestamp, u16 *entries);
int ksz8_r_sta_mac_table(struct ksz_device *dev, u16 addr,
Expand Down
111 changes: 87 additions & 24 deletions drivers/net/dsa/microchip/ksz8795.c
Original file line number Diff line number Diff line change
Expand Up @@ -552,22 +552,32 @@ static void ksz8_w_vlan_table(struct ksz_device *dev, u16 vid, u16 vlan)
ksz8_w_table(dev, TABLE_VLAN, addr, buf);
}

void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
int ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
{
u8 restart, speed, ctrl, link;
int processed = true;
const u16 *regs;
u8 val1, val2;
u16 data = 0;
u8 p = phy;
int ret;

regs = dev->info->regs;

switch (reg) {
case MII_BMCR:
ksz_pread8(dev, p, regs[P_NEG_RESTART_CTRL], &restart);
ksz_pread8(dev, p, regs[P_SPEED_STATUS], &speed);
ksz_pread8(dev, p, regs[P_FORCE_CTRL], &ctrl);
ret = ksz_pread8(dev, p, regs[P_NEG_RESTART_CTRL], &restart);
if (ret)
return ret;

ret = ksz_pread8(dev, p, regs[P_SPEED_STATUS], &speed);
if (ret)
return ret;

ret = ksz_pread8(dev, p, regs[P_FORCE_CTRL], &ctrl);
if (ret)
return ret;

if (restart & PORT_PHY_LOOPBACK)
data |= BMCR_LOOPBACK;
if (ctrl & PORT_FORCE_100_MBIT)
Expand Down Expand Up @@ -597,7 +607,10 @@ void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
data |= KSZ886X_BMCR_DISABLE_LED;
break;
case MII_BMSR:
ksz_pread8(dev, p, regs[P_LINK_STATUS], &link);
ret = ksz_pread8(dev, p, regs[P_LINK_STATUS], &link);
if (ret)
return ret;

data = BMSR_100FULL |
BMSR_100HALF |
BMSR_10FULL |
Expand All @@ -618,7 +631,10 @@ void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
data = KSZ8795_ID_LO;
break;
case MII_ADVERTISE:
ksz_pread8(dev, p, regs[P_LOCAL_CTRL], &ctrl);
ret = ksz_pread8(dev, p, regs[P_LOCAL_CTRL], &ctrl);
if (ret)
return ret;

data = ADVERTISE_CSMA;
if (ctrl & PORT_AUTO_NEG_SYM_PAUSE)
data |= ADVERTISE_PAUSE_CAP;
Expand All @@ -632,7 +648,10 @@ void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
data |= ADVERTISE_10HALF;
break;
case MII_LPA:
ksz_pread8(dev, p, regs[P_REMOTE_STATUS], &link);
ret = ksz_pread8(dev, p, regs[P_REMOTE_STATUS], &link);
if (ret)
return ret;

data = LPA_SLCT;
if (link & PORT_REMOTE_SYM_PAUSE)
data |= LPA_PAUSE_CAP;
Expand All @@ -648,8 +667,14 @@ void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
data |= LPA_LPACK;
break;
case PHY_REG_LINK_MD:
ksz_pread8(dev, p, REG_PORT_LINK_MD_CTRL, &val1);
ksz_pread8(dev, p, REG_PORT_LINK_MD_RESULT, &val2);
ret = ksz_pread8(dev, p, REG_PORT_LINK_MD_CTRL, &val1);
if (ret)
return ret;

ret = ksz_pread8(dev, p, REG_PORT_LINK_MD_RESULT, &val2);
if (ret)
return ret;

if (val1 & PORT_START_CABLE_DIAG)
data |= PHY_START_CABLE_DIAG;

Expand All @@ -664,7 +689,10 @@ void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
FIELD_GET(PORT_CABLE_FAULT_COUNTER_L, val2));
break;
case PHY_REG_PHY_CTRL:
ksz_pread8(dev, p, regs[P_LINK_STATUS], &link);
ret = ksz_pread8(dev, p, regs[P_LINK_STATUS], &link);
if (ret)
return ret;

if (link & PORT_MDIX_STATUS)
data |= KSZ886X_CTRL_MDIX_STAT;
break;
Expand All @@ -674,13 +702,16 @@ void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
}
if (processed)
*val = data;

return 0;
}

void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
int ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
{
u8 restart, speed, ctrl, data;
const u16 *regs;
u8 p = phy;
int ret;

regs = dev->info->regs;

Expand All @@ -690,15 +721,26 @@ void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
/* Do not support PHY reset function. */
if (val & BMCR_RESET)
break;
ksz_pread8(dev, p, regs[P_SPEED_STATUS], &speed);
ret = ksz_pread8(dev, p, regs[P_SPEED_STATUS], &speed);
if (ret)
return ret;

data = speed;
if (val & KSZ886X_BMCR_HP_MDIX)
data |= PORT_HP_MDIX;
else
data &= ~PORT_HP_MDIX;
if (data != speed)
ksz_pwrite8(dev, p, regs[P_SPEED_STATUS], data);
ksz_pread8(dev, p, regs[P_FORCE_CTRL], &ctrl);

if (data != speed) {
ret = ksz_pwrite8(dev, p, regs[P_SPEED_STATUS], data);
if (ret)
return ret;
}

ret = ksz_pread8(dev, p, regs[P_FORCE_CTRL], &ctrl);
if (ret)
return ret;

data = ctrl;
if (ksz_is_ksz88x3(dev)) {
if ((val & BMCR_ANENABLE))
Expand All @@ -724,9 +766,17 @@ void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
data |= PORT_FORCE_FULL_DUPLEX;
else
data &= ~PORT_FORCE_FULL_DUPLEX;
if (data != ctrl)
ksz_pwrite8(dev, p, regs[P_FORCE_CTRL], data);
ksz_pread8(dev, p, regs[P_NEG_RESTART_CTRL], &restart);

if (data != ctrl) {
ret = ksz_pwrite8(dev, p, regs[P_FORCE_CTRL], data);
if (ret)
return ret;
}

ret = ksz_pread8(dev, p, regs[P_NEG_RESTART_CTRL], &restart);
if (ret)
return ret;

data = restart;
if (val & KSZ886X_BMCR_DISABLE_LED)
data |= PORT_LED_OFF;
Expand Down Expand Up @@ -756,11 +806,19 @@ void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
data |= PORT_PHY_LOOPBACK;
else
data &= ~PORT_PHY_LOOPBACK;
if (data != restart)
ksz_pwrite8(dev, p, regs[P_NEG_RESTART_CTRL], data);

if (data != restart) {
ret = ksz_pwrite8(dev, p, regs[P_NEG_RESTART_CTRL],
data);
if (ret)
return ret;
}
break;
case MII_ADVERTISE:
ksz_pread8(dev, p, regs[P_LOCAL_CTRL], &ctrl);
ret = ksz_pread8(dev, p, regs[P_LOCAL_CTRL], &ctrl);
if (ret)
return ret;

data = ctrl;
data &= ~(PORT_AUTO_NEG_SYM_PAUSE |
PORT_AUTO_NEG_100BTX_FD |
Expand All @@ -777,8 +835,12 @@ void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
data |= PORT_AUTO_NEG_10BT_FD;
if (val & ADVERTISE_10HALF)
data |= PORT_AUTO_NEG_10BT;
if (data != ctrl)
ksz_pwrite8(dev, p, regs[P_LOCAL_CTRL], data);

if (data != ctrl) {
ret = ksz_pwrite8(dev, p, regs[P_LOCAL_CTRL], data);
if (ret)
return ret;
}
break;
case PHY_REG_LINK_MD:
if (val & PHY_START_CABLE_DIAG)
Expand All @@ -787,6 +849,8 @@ void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
default:
break;
}

return 0;
}

void ksz8_cfg_port_member(struct ksz_device *dev, int port, u8 member)
Expand Down Expand Up @@ -1187,7 +1251,6 @@ void ksz8_config_cpu_port(struct dsa_switch *ds)
if (i == dev->phy_port_cnt)
break;
p->on = 1;
p->phy = 1;
}
for (i = 0; i < dev->phy_port_cnt; i++) {
p = &dev->ports[i];
Expand Down
Loading

0 comments on commit 2d919d3

Please sign in to comment.