Skip to content

Commit b240fc5

Browse files
committed
Merge branch 'net-dsa-vsc73xx-convert-to-phylink-and-do-some-cleanup'
Pawel Dembicki says: ==================== net: dsa: vsc73xx: convert to PHYLINK and do some cleanup This patch series is a result of splitting a larger patch series [0], where some parts needed to be refactored. The first patch switches from a poll loop to read_poll_timeout. The second patch is a simple conversion to phylink because adjust_link won't work anymore. The third patch is preparation for future use. Using the "phy_interface_mode_is_rgmii" macro allows for the proper recognition of all RGMII modes. Patches 4-5 involve some cleanup: The fourth patch introduces a definition with the maximum number of ports to avoid using magic numbers. The next one fills in documentation. [0] https://patchwork.kernel.org/project/netdevbpf/list/?series=841034&state=%2A&archive=both ==================== Link: https://lore.kernel.org/r/20240417205048.3542839-1-paweldembicki@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2 parents c51db4a + 96944aa commit b240fc5

File tree

2 files changed

+144
-138
lines changed

2 files changed

+144
-138
lines changed

drivers/net/dsa/vitesse-vsc73xx-core.c

Lines changed: 118 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <linux/kernel.h>
1818
#include <linux/module.h>
1919
#include <linux/device.h>
20+
#include <linux/iopoll.h>
2021
#include <linux/of.h>
2122
#include <linux/of_mdio.h>
2223
#include <linux/bitops.h>
@@ -268,6 +269,9 @@
268269
#define IS_7398(a) ((a)->chipid == VSC73XX_CHIPID_ID_7398)
269270
#define IS_739X(a) (IS_7395(a) || IS_7398(a))
270271

272+
#define VSC73XX_POLL_SLEEP_US 1000
273+
#define VSC73XX_POLL_TIMEOUT_US 10000
274+
271275
struct vsc73xx_counter {
272276
u8 counter;
273277
const char *name;
@@ -713,51 +717,44 @@ static void vsc73xx_init_port(struct vsc73xx *vsc, int port)
713717
port, VSC73XX_C_RX0, 0);
714718
}
715719

716-
static void vsc73xx_adjust_enable_port(struct vsc73xx *vsc,
717-
int port, struct phy_device *phydev,
718-
u32 initval)
720+
static void vsc73xx_reset_port(struct vsc73xx *vsc, int port, u32 initval)
719721
{
720-
u32 val = initval;
721-
u8 seed;
722-
723-
/* Reset this port FIXME: break out subroutine */
724-
val |= VSC73XX_MAC_CFG_RESET;
725-
vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, port, VSC73XX_MAC_CFG, val);
726-
727-
/* Seed the port randomness with randomness */
728-
get_random_bytes(&seed, 1);
729-
val |= seed << VSC73XX_MAC_CFG_SEED_OFFSET;
730-
val |= VSC73XX_MAC_CFG_SEED_LOAD;
731-
val |= VSC73XX_MAC_CFG_WEXC_DIS;
732-
vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, port, VSC73XX_MAC_CFG, val);
722+
int ret, err;
723+
u32 val;
733724

734-
/* Flow control for the PHY facing ports:
735-
* Use a zero delay pause frame when pause condition is left
736-
* Obey pause control frames
737-
* When generating pause frames, use 0xff as pause value
738-
*/
739-
vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, port, VSC73XX_FCCONF,
740-
VSC73XX_FCCONF_ZERO_PAUSE_EN |
741-
VSC73XX_FCCONF_FLOW_CTRL_OBEY |
742-
0xff);
725+
/* Disable RX on this port */
726+
vsc73xx_update_bits(vsc, VSC73XX_BLOCK_MAC, port,
727+
VSC73XX_MAC_CFG,
728+
VSC73XX_MAC_CFG_RX_EN, 0);
743729

744-
/* Disallow backward dropping of frames from this port */
730+
/* Discard packets */
745731
vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ARBITER, 0,
746-
VSC73XX_SBACKWDROP, BIT(port), 0);
732+
VSC73XX_ARBDISC, BIT(port), BIT(port));
733+
734+
/* Wait until queue is empty */
735+
ret = read_poll_timeout(vsc73xx_read, err,
736+
err < 0 || (val & BIT(port)),
737+
VSC73XX_POLL_SLEEP_US,
738+
VSC73XX_POLL_TIMEOUT_US, false,
739+
vsc, VSC73XX_BLOCK_ARBITER, 0,
740+
VSC73XX_ARBEMPTY, &val);
741+
if (ret)
742+
dev_err(vsc->dev,
743+
"timeout waiting for block arbiter\n");
744+
else if (err < 0)
745+
dev_err(vsc->dev, "error reading arbiter\n");
747746

748-
/* Enable TX, RX, deassert reset, stop loading seed */
749-
vsc73xx_update_bits(vsc, VSC73XX_BLOCK_MAC, port,
750-
VSC73XX_MAC_CFG,
751-
VSC73XX_MAC_CFG_RESET | VSC73XX_MAC_CFG_SEED_LOAD |
752-
VSC73XX_MAC_CFG_TX_EN | VSC73XX_MAC_CFG_RX_EN,
753-
VSC73XX_MAC_CFG_TX_EN | VSC73XX_MAC_CFG_RX_EN);
747+
/* Put this port into reset */
748+
vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, port, VSC73XX_MAC_CFG,
749+
VSC73XX_MAC_CFG_RESET | initval);
754750
}
755751

756-
static void vsc73xx_adjust_link(struct dsa_switch *ds, int port,
757-
struct phy_device *phydev)
752+
static void vsc73xx_mac_config(struct phylink_config *config, unsigned int mode,
753+
const struct phylink_link_state *state)
758754
{
759-
struct vsc73xx *vsc = ds->priv;
760-
u32 val;
755+
struct dsa_port *dp = dsa_phylink_to_port(config);
756+
struct vsc73xx *vsc = dp->ds->priv;
757+
int port = dp->index;
761758

762759
/* Special handling of the CPU-facing port */
763760
if (port == CPU_PORT) {
@@ -774,104 +771,93 @@ static void vsc73xx_adjust_link(struct dsa_switch *ds, int port,
774771
VSC73XX_ADVPORTM_ENA_GTX |
775772
VSC73XX_ADVPORTM_DDR_MODE);
776773
}
774+
}
775+
776+
static void vsc73xx_mac_link_down(struct phylink_config *config,
777+
unsigned int mode, phy_interface_t interface)
778+
{
779+
struct dsa_port *dp = dsa_phylink_to_port(config);
780+
struct vsc73xx *vsc = dp->ds->priv;
781+
int port = dp->index;
777782

778-
/* This is the MAC confiuration that always need to happen
779-
* after a PHY or the CPU port comes up or down.
783+
/* This routine is described in the datasheet (below ARBDISC register
784+
* description)
780785
*/
781-
if (!phydev->link) {
782-
int maxloop = 10;
783-
784-
dev_dbg(vsc->dev, "port %d: went down\n",
785-
port);
786-
787-
/* Disable RX on this port */
788-
vsc73xx_update_bits(vsc, VSC73XX_BLOCK_MAC, port,
789-
VSC73XX_MAC_CFG,
790-
VSC73XX_MAC_CFG_RX_EN, 0);
791-
792-
/* Discard packets */
793-
vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ARBITER, 0,
794-
VSC73XX_ARBDISC, BIT(port), BIT(port));
795-
796-
/* Wait until queue is empty */
797-
vsc73xx_read(vsc, VSC73XX_BLOCK_ARBITER, 0,
798-
VSC73XX_ARBEMPTY, &val);
799-
while (!(val & BIT(port))) {
800-
msleep(1);
801-
vsc73xx_read(vsc, VSC73XX_BLOCK_ARBITER, 0,
802-
VSC73XX_ARBEMPTY, &val);
803-
if (--maxloop == 0) {
804-
dev_err(vsc->dev,
805-
"timeout waiting for block arbiter\n");
806-
/* Continue anyway */
807-
break;
808-
}
809-
}
786+
vsc73xx_reset_port(vsc, port, 0);
787+
788+
/* Allow backward dropping of frames from this port */
789+
vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ARBITER, 0,
790+
VSC73XX_SBACKWDROP, BIT(port), BIT(port));
791+
792+
/* Receive mask (disable forwarding) */
793+
vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ANALYZER, 0,
794+
VSC73XX_RECVMASK, BIT(port), 0);
795+
}
796+
797+
static void vsc73xx_mac_link_up(struct phylink_config *config,
798+
struct phy_device *phy, unsigned int mode,
799+
phy_interface_t interface, int speed,
800+
int duplex, bool tx_pause, bool rx_pause)
801+
{
802+
struct dsa_port *dp = dsa_phylink_to_port(config);
803+
struct vsc73xx *vsc = dp->ds->priv;
804+
int port = dp->index;
805+
u32 val;
806+
u8 seed;
810807

811-
/* Put this port into reset */
812-
vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, port, VSC73XX_MAC_CFG,
813-
VSC73XX_MAC_CFG_RESET);
808+
if (speed == SPEED_1000)
809+
val = VSC73XX_MAC_CFG_GIGA_MODE | VSC73XX_MAC_CFG_TX_IPG_1000M;
810+
else
811+
val = VSC73XX_MAC_CFG_TX_IPG_100_10M;
814812

815-
/* Accept packets again */
816-
vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ARBITER, 0,
817-
VSC73XX_ARBDISC, BIT(port), 0);
813+
if (phy_interface_mode_is_rgmii(interface))
814+
val |= VSC73XX_MAC_CFG_CLK_SEL_1000M;
815+
else
816+
val |= VSC73XX_MAC_CFG_CLK_SEL_EXT;
818817

819-
/* Allow backward dropping of frames from this port */
820-
vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ARBITER, 0,
821-
VSC73XX_SBACKWDROP, BIT(port), BIT(port));
818+
if (duplex == DUPLEX_FULL)
819+
val |= VSC73XX_MAC_CFG_FDX;
822820

823-
/* Receive mask (disable forwarding) */
824-
vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ANALYZER, 0,
825-
VSC73XX_RECVMASK, BIT(port), 0);
821+
/* This routine is described in the datasheet (below ARBDISC register
822+
* description)
823+
*/
824+
vsc73xx_reset_port(vsc, port, val);
826825

827-
return;
828-
}
826+
/* Seed the port randomness with randomness */
827+
get_random_bytes(&seed, 1);
828+
val |= seed << VSC73XX_MAC_CFG_SEED_OFFSET;
829+
val |= VSC73XX_MAC_CFG_SEED_LOAD;
830+
val |= VSC73XX_MAC_CFG_WEXC_DIS;
831+
vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, port, VSC73XX_MAC_CFG, val);
829832

830-
/* Figure out what speed was negotiated */
831-
if (phydev->speed == SPEED_1000) {
832-
dev_dbg(vsc->dev, "port %d: 1000 Mbit mode full duplex\n",
833-
port);
834-
835-
/* Set up default for internal port or external RGMII */
836-
if (phydev->interface == PHY_INTERFACE_MODE_RGMII)
837-
val = VSC73XX_MAC_CFG_1000M_F_RGMII;
838-
else
839-
val = VSC73XX_MAC_CFG_1000M_F_PHY;
840-
vsc73xx_adjust_enable_port(vsc, port, phydev, val);
841-
} else if (phydev->speed == SPEED_100) {
842-
if (phydev->duplex == DUPLEX_FULL) {
843-
val = VSC73XX_MAC_CFG_100_10M_F_PHY;
844-
dev_dbg(vsc->dev,
845-
"port %d: 100 Mbit full duplex mode\n",
846-
port);
847-
} else {
848-
val = VSC73XX_MAC_CFG_100_10M_H_PHY;
849-
dev_dbg(vsc->dev,
850-
"port %d: 100 Mbit half duplex mode\n",
851-
port);
852-
}
853-
vsc73xx_adjust_enable_port(vsc, port, phydev, val);
854-
} else if (phydev->speed == SPEED_10) {
855-
if (phydev->duplex == DUPLEX_FULL) {
856-
val = VSC73XX_MAC_CFG_100_10M_F_PHY;
857-
dev_dbg(vsc->dev,
858-
"port %d: 10 Mbit full duplex mode\n",
859-
port);
860-
} else {
861-
val = VSC73XX_MAC_CFG_100_10M_H_PHY;
862-
dev_dbg(vsc->dev,
863-
"port %d: 10 Mbit half duplex mode\n",
864-
port);
865-
}
866-
vsc73xx_adjust_enable_port(vsc, port, phydev, val);
867-
} else {
868-
dev_err(vsc->dev,
869-
"could not adjust link: unknown speed\n");
870-
}
833+
/* Flow control for the PHY facing ports:
834+
* Use a zero delay pause frame when pause condition is left
835+
* Obey pause control frames
836+
* When generating pause frames, use 0xff as pause value
837+
*/
838+
vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, port, VSC73XX_FCCONF,
839+
VSC73XX_FCCONF_ZERO_PAUSE_EN |
840+
VSC73XX_FCCONF_FLOW_CTRL_OBEY |
841+
0xff);
871842

872-
/* Enable port (forwarding) in the receieve mask */
843+
/* Accept packets again */
844+
vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ARBITER, 0,
845+
VSC73XX_ARBDISC, BIT(port), 0);
846+
847+
/* Enable port (forwarding) in the receive mask */
873848
vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ANALYZER, 0,
874849
VSC73XX_RECVMASK, BIT(port), BIT(port));
850+
851+
/* Disallow backward dropping of frames from this port */
852+
vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ARBITER, 0,
853+
VSC73XX_SBACKWDROP, BIT(port), 0);
854+
855+
/* Enable TX, RX, deassert reset, stop loading seed */
856+
vsc73xx_update_bits(vsc, VSC73XX_BLOCK_MAC, port,
857+
VSC73XX_MAC_CFG,
858+
VSC73XX_MAC_CFG_RESET | VSC73XX_MAC_CFG_SEED_LOAD |
859+
VSC73XX_MAC_CFG_TX_EN | VSC73XX_MAC_CFG_RX_EN,
860+
VSC73XX_MAC_CFG_TX_EN | VSC73XX_MAC_CFG_RX_EN);
875861
}
876862

877863
static int vsc73xx_port_enable(struct dsa_switch *ds, int port,
@@ -1053,12 +1039,17 @@ static void vsc73xx_phylink_get_caps(struct dsa_switch *dsa, int port,
10531039
config->mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100 | MAC_1000;
10541040
}
10551041

1042+
static const struct phylink_mac_ops vsc73xx_phylink_mac_ops = {
1043+
.mac_config = vsc73xx_mac_config,
1044+
.mac_link_down = vsc73xx_mac_link_down,
1045+
.mac_link_up = vsc73xx_mac_link_up,
1046+
};
1047+
10561048
static const struct dsa_switch_ops vsc73xx_ds_ops = {
10571049
.get_tag_protocol = vsc73xx_get_tag_protocol,
10581050
.setup = vsc73xx_setup,
10591051
.phy_read = vsc73xx_phy_read,
10601052
.phy_write = vsc73xx_phy_write,
1061-
.adjust_link = vsc73xx_adjust_link,
10621053
.get_strings = vsc73xx_get_strings,
10631054
.get_ethtool_stats = vsc73xx_get_ethtool_stats,
10641055
.get_sset_count = vsc73xx_get_sset_count,
@@ -1195,26 +1186,16 @@ int vsc73xx_probe(struct vsc73xx *vsc)
11951186
vsc->addr[0], vsc->addr[1], vsc->addr[2],
11961187
vsc->addr[3], vsc->addr[4], vsc->addr[5]);
11971188

1198-
/* The VSC7395 switch chips have 5+1 ports which means 5
1199-
* ordinary ports and a sixth CPU port facing the processor
1200-
* with an RGMII interface. These ports are numbered 0..4
1201-
* and 6, so they leave a "hole" in the port map for port 5,
1202-
* which is invalid.
1203-
*
1204-
* The VSC7398 has 8 ports, port 7 is again the CPU port.
1205-
*
1206-
* We allocate 8 ports and avoid access to the nonexistant
1207-
* ports.
1208-
*/
12091189
vsc->ds = devm_kzalloc(dev, sizeof(*vsc->ds), GFP_KERNEL);
12101190
if (!vsc->ds)
12111191
return -ENOMEM;
12121192

12131193
vsc->ds->dev = dev;
1214-
vsc->ds->num_ports = 8;
1194+
vsc->ds->num_ports = VSC73XX_MAX_NUM_PORTS;
12151195
vsc->ds->priv = vsc;
12161196

12171197
vsc->ds->ops = &vsc73xx_ds_ops;
1198+
vsc->ds->phylink_mac_ops = &vsc73xx_phylink_mac_ops;
12181199
ret = dsa_register_switch(vsc->ds);
12191200
if (ret) {
12201201
dev_err(dev, "unable to register switch (%d)\n", ret);

drivers/net/dsa/vitesse-vsc73xx.h

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,28 @@
33
#include <linux/etherdevice.h>
44
#include <linux/gpio/driver.h>
55

6+
/* The VSC7395 switch chips have 5+1 ports which means 5 ordinary ports and
7+
* a sixth CPU port facing the processor with an RGMII interface. These ports
8+
* are numbered 0..4 and 6, so they leave a "hole" in the port map for port 5,
9+
* which is invalid.
10+
*
11+
* The VSC7398 has 8 ports, port 7 is again the CPU port.
12+
*
13+
* We allocate 8 ports and avoid access to the nonexistent ports.
14+
*/
15+
#define VSC73XX_MAX_NUM_PORTS 8
16+
617
/**
7-
* struct vsc73xx - VSC73xx state container
18+
* struct vsc73xx - VSC73xx state container: main data structure
19+
* @dev: The device pointer
20+
* @reset: The descriptor for the GPIO line tied to the reset pin
21+
* @ds: Pointer to the DSA core structure
22+
* @gc: Main structure of the GPIO controller
23+
* @chipid: Storage for the Chip ID value read from the CHIPID register of the
24+
* switch
25+
* @addr: MAC address used in flow control frames
26+
* @ops: Structure with hardware-dependent operations
27+
* @priv: Pointer to the configuration interface structure
828
*/
929
struct vsc73xx {
1030
struct device *dev;
@@ -17,6 +37,11 @@ struct vsc73xx {
1737
void *priv;
1838
};
1939

40+
/**
41+
* struct vsc73xx_ops - VSC73xx methods container
42+
* @read: Method for register reading over the hardware-dependent interface
43+
* @write: Method for register writing over the hardware-dependent interface
44+
*/
2045
struct vsc73xx_ops {
2146
int (*read)(struct vsc73xx *vsc, u8 block, u8 subblock, u8 reg,
2247
u32 *val);

0 commit comments

Comments
 (0)