Skip to content

Commit 2b33b20

Browse files
committed
Merge branch 'Bugfixes-in-Microsemi-Ocelot-switch-driver'
Vladimir Oltean says: ==================== Bugfixes in Microsemi Ocelot switch driver This is a series of 8 assorted patches for "net", on the drivers for the VSC7514 MIPS switch (Ocelot-1), the VSC9953 PowerPC (Seville), and a few more that are common to all supported devices since they are in the common library portion. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
2 parents 5f6857e + e5fb512 commit 2b33b20

File tree

7 files changed

+175
-117
lines changed

7 files changed

+175
-117
lines changed

drivers/net/dsa/ocelot/felix.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -585,7 +585,10 @@ static int felix_setup(struct dsa_switch *ds)
585585
if (err)
586586
return err;
587587

588-
ocelot_init(ocelot);
588+
err = ocelot_init(ocelot);
589+
if (err)
590+
return err;
591+
589592
if (ocelot->ptp) {
590593
err = ocelot_init_timestamp(ocelot, &ocelot_ptp_clock_info);
591594
if (err) {
@@ -640,10 +643,13 @@ static void felix_teardown(struct dsa_switch *ds)
640643
{
641644
struct ocelot *ocelot = ds->priv;
642645
struct felix *felix = ocelot_to_felix(ocelot);
646+
int port;
643647

644648
if (felix->info->mdio_bus_free)
645649
felix->info->mdio_bus_free(ocelot);
646650

651+
for (port = 0; port < ocelot->num_phys_ports; port++)
652+
ocelot_deinit_port(ocelot, port);
647653
ocelot_deinit_timestamp(ocelot);
648654
/* stop workqueue thread */
649655
ocelot_deinit(ocelot);

drivers/net/dsa/ocelot/seville_vsc9953.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1008,7 +1008,7 @@ static const struct felix_info seville_info_vsc9953 = {
10081008
.vcap_is2_keys = vsc9953_vcap_is2_keys,
10091009
.vcap_is2_actions = vsc9953_vcap_is2_actions,
10101010
.vcap = vsc9953_vcap_props,
1011-
.shared_queue_sz = 128 * 1024,
1011+
.shared_queue_sz = 2048 * 1024,
10121012
.num_mact_rows = 2048,
10131013
.num_ports = 10,
10141014
.mdio_bus_alloc = vsc9953_mdio_bus_alloc,

drivers/net/ethernet/mscc/ocelot.c

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -421,10 +421,15 @@ int ocelot_port_add_txtstamp_skb(struct ocelot_port *ocelot_port,
421421

422422
if (ocelot->ptp && shinfo->tx_flags & SKBTX_HW_TSTAMP &&
423423
ocelot_port->ptp_cmd == IFH_REW_OP_TWO_STEP_PTP) {
424+
spin_lock(&ocelot_port->ts_id_lock);
425+
424426
shinfo->tx_flags |= SKBTX_IN_PROGRESS;
425427
/* Store timestamp ID in cb[0] of sk_buff */
426-
skb->cb[0] = ocelot_port->ts_id % 4;
428+
skb->cb[0] = ocelot_port->ts_id;
429+
ocelot_port->ts_id = (ocelot_port->ts_id + 1) % 4;
427430
skb_queue_tail(&ocelot_port->tx_skbs, skb);
431+
432+
spin_unlock(&ocelot_port->ts_id_lock);
428433
return 0;
429434
}
430435
return -ENODATA;
@@ -1300,6 +1305,7 @@ void ocelot_init_port(struct ocelot *ocelot, int port)
13001305
struct ocelot_port *ocelot_port = ocelot->ports[port];
13011306

13021307
skb_queue_head_init(&ocelot_port->tx_skbs);
1308+
spin_lock_init(&ocelot_port->ts_id_lock);
13031309

13041310
/* Basic L2 initialization */
13051311

@@ -1544,18 +1550,18 @@ EXPORT_SYMBOL(ocelot_init);
15441550

15451551
void ocelot_deinit(struct ocelot *ocelot)
15461552
{
1547-
struct ocelot_port *port;
1548-
int i;
1549-
15501553
cancel_delayed_work(&ocelot->stats_work);
15511554
destroy_workqueue(ocelot->stats_queue);
15521555
mutex_destroy(&ocelot->stats_lock);
1553-
1554-
for (i = 0; i < ocelot->num_phys_ports; i++) {
1555-
port = ocelot->ports[i];
1556-
skb_queue_purge(&port->tx_skbs);
1557-
}
15581556
}
15591557
EXPORT_SYMBOL(ocelot_deinit);
15601558

1559+
void ocelot_deinit_port(struct ocelot *ocelot, int port)
1560+
{
1561+
struct ocelot_port *ocelot_port = ocelot->ports[port];
1562+
1563+
skb_queue_purge(&ocelot_port->tx_skbs);
1564+
}
1565+
EXPORT_SYMBOL(ocelot_deinit_port);
1566+
15611567
MODULE_LICENSE("Dual MIT/GPL");

drivers/net/ethernet/mscc/ocelot_net.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,7 @@ static int ocelot_port_xmit(struct sk_buff *skb, struct net_device *dev)
330330
u8 grp = 0; /* Send everything on CPU group 0 */
331331
unsigned int i, count, last;
332332
int port = priv->chip_port;
333+
bool do_tstamp;
333334

334335
val = ocelot_read(ocelot, QS_INJ_STATUS);
335336
if (!(val & QS_INJ_STATUS_FIFO_RDY(BIT(grp))) ||
@@ -344,10 +345,12 @@ static int ocelot_port_xmit(struct sk_buff *skb, struct net_device *dev)
344345
info.vid = skb_vlan_tag_get(skb);
345346

346347
/* Check if timestamping is needed */
348+
do_tstamp = (ocelot_port_add_txtstamp_skb(ocelot_port, skb) == 0);
349+
347350
if (ocelot->ptp && shinfo->tx_flags & SKBTX_HW_TSTAMP) {
348351
info.rew_op = ocelot_port->ptp_cmd;
349352
if (ocelot_port->ptp_cmd == IFH_REW_OP_TWO_STEP_PTP)
350-
info.rew_op |= (ocelot_port->ts_id % 4) << 3;
353+
info.rew_op |= skb->cb[0] << 3;
351354
}
352355

353356
ocelot_gen_ifh(ifh, &info);
@@ -380,12 +383,9 @@ static int ocelot_port_xmit(struct sk_buff *skb, struct net_device *dev)
380383
dev->stats.tx_packets++;
381384
dev->stats.tx_bytes += skb->len;
382385

383-
if (!ocelot_port_add_txtstamp_skb(ocelot_port, skb)) {
384-
ocelot_port->ts_id++;
385-
return NETDEV_TX_OK;
386-
}
386+
if (!do_tstamp)
387+
dev_kfree_skb_any(skb);
387388

388-
dev_kfree_skb_any(skb);
389389
return NETDEV_TX_OK;
390390
}
391391

drivers/net/ethernet/mscc/ocelot_vsc7514.c

Lines changed: 137 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -896,11 +896,137 @@ static struct ptp_clock_info ocelot_ptp_clock_info = {
896896
.enable = ocelot_ptp_enable,
897897
};
898898

899+
static void mscc_ocelot_release_ports(struct ocelot *ocelot)
900+
{
901+
int port;
902+
903+
for (port = 0; port < ocelot->num_phys_ports; port++) {
904+
struct ocelot_port_private *priv;
905+
struct ocelot_port *ocelot_port;
906+
907+
ocelot_port = ocelot->ports[port];
908+
if (!ocelot_port)
909+
continue;
910+
911+
ocelot_deinit_port(ocelot, port);
912+
913+
priv = container_of(ocelot_port, struct ocelot_port_private,
914+
port);
915+
916+
unregister_netdev(priv->dev);
917+
free_netdev(priv->dev);
918+
}
919+
}
920+
921+
static int mscc_ocelot_init_ports(struct platform_device *pdev,
922+
struct device_node *ports)
923+
{
924+
struct ocelot *ocelot = platform_get_drvdata(pdev);
925+
struct device_node *portnp;
926+
int err;
927+
928+
ocelot->ports = devm_kcalloc(ocelot->dev, ocelot->num_phys_ports,
929+
sizeof(struct ocelot_port *), GFP_KERNEL);
930+
if (!ocelot->ports)
931+
return -ENOMEM;
932+
933+
/* No NPI port */
934+
ocelot_configure_cpu(ocelot, -1, OCELOT_TAG_PREFIX_NONE,
935+
OCELOT_TAG_PREFIX_NONE);
936+
937+
for_each_available_child_of_node(ports, portnp) {
938+
struct ocelot_port_private *priv;
939+
struct ocelot_port *ocelot_port;
940+
struct device_node *phy_node;
941+
phy_interface_t phy_mode;
942+
struct phy_device *phy;
943+
struct regmap *target;
944+
struct resource *res;
945+
struct phy *serdes;
946+
char res_name[8];
947+
u32 port;
948+
949+
if (of_property_read_u32(portnp, "reg", &port))
950+
continue;
951+
952+
snprintf(res_name, sizeof(res_name), "port%d", port);
953+
954+
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
955+
res_name);
956+
target = ocelot_regmap_init(ocelot, res);
957+
if (IS_ERR(target))
958+
continue;
959+
960+
phy_node = of_parse_phandle(portnp, "phy-handle", 0);
961+
if (!phy_node)
962+
continue;
963+
964+
phy = of_phy_find_device(phy_node);
965+
of_node_put(phy_node);
966+
if (!phy)
967+
continue;
968+
969+
err = ocelot_probe_port(ocelot, port, target, phy);
970+
if (err) {
971+
of_node_put(portnp);
972+
return err;
973+
}
974+
975+
ocelot_port = ocelot->ports[port];
976+
priv = container_of(ocelot_port, struct ocelot_port_private,
977+
port);
978+
979+
of_get_phy_mode(portnp, &phy_mode);
980+
981+
ocelot_port->phy_mode = phy_mode;
982+
983+
switch (ocelot_port->phy_mode) {
984+
case PHY_INTERFACE_MODE_NA:
985+
continue;
986+
case PHY_INTERFACE_MODE_SGMII:
987+
break;
988+
case PHY_INTERFACE_MODE_QSGMII:
989+
/* Ensure clock signals and speed is set on all
990+
* QSGMII links
991+
*/
992+
ocelot_port_writel(ocelot_port,
993+
DEV_CLOCK_CFG_LINK_SPEED
994+
(OCELOT_SPEED_1000),
995+
DEV_CLOCK_CFG);
996+
break;
997+
default:
998+
dev_err(ocelot->dev,
999+
"invalid phy mode for port%d, (Q)SGMII only\n",
1000+
port);
1001+
of_node_put(portnp);
1002+
return -EINVAL;
1003+
}
1004+
1005+
serdes = devm_of_phy_get(ocelot->dev, portnp, NULL);
1006+
if (IS_ERR(serdes)) {
1007+
err = PTR_ERR(serdes);
1008+
if (err == -EPROBE_DEFER)
1009+
dev_dbg(ocelot->dev, "deferring probe\n");
1010+
else
1011+
dev_err(ocelot->dev,
1012+
"missing SerDes phys for port%d\n",
1013+
port);
1014+
1015+
of_node_put(portnp);
1016+
return err;
1017+
}
1018+
1019+
priv->serdes = serdes;
1020+
}
1021+
1022+
return 0;
1023+
}
1024+
8991025
static int mscc_ocelot_probe(struct platform_device *pdev)
9001026
{
9011027
struct device_node *np = pdev->dev.of_node;
902-
struct device_node *ports, *portnp;
9031028
int err, irq_xtr, irq_ptp_rdy;
1029+
struct device_node *ports;
9041030
struct ocelot *ocelot;
9051031
struct regmap *hsio;
9061032
unsigned int i;
@@ -985,20 +1111,24 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
9851111

9861112
ports = of_get_child_by_name(np, "ethernet-ports");
9871113
if (!ports) {
988-
dev_err(&pdev->dev, "no ethernet-ports child node found\n");
1114+
dev_err(ocelot->dev, "no ethernet-ports child node found\n");
9891115
return -ENODEV;
9901116
}
9911117

9921118
ocelot->num_phys_ports = of_get_child_count(ports);
9931119

994-
ocelot->ports = devm_kcalloc(&pdev->dev, ocelot->num_phys_ports,
995-
sizeof(struct ocelot_port *), GFP_KERNEL);
996-
9971120
ocelot->vcap_is2_keys = vsc7514_vcap_is2_keys;
9981121
ocelot->vcap_is2_actions = vsc7514_vcap_is2_actions;
9991122
ocelot->vcap = vsc7514_vcap_props;
10001123

1001-
ocelot_init(ocelot);
1124+
err = ocelot_init(ocelot);
1125+
if (err)
1126+
goto out_put_ports;
1127+
1128+
err = mscc_ocelot_init_ports(pdev, ports);
1129+
if (err)
1130+
goto out_put_ports;
1131+
10021132
if (ocelot->ptp) {
10031133
err = ocelot_init_timestamp(ocelot, &ocelot_ptp_clock_info);
10041134
if (err) {
@@ -1008,96 +1138,6 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
10081138
}
10091139
}
10101140

1011-
/* No NPI port */
1012-
ocelot_configure_cpu(ocelot, -1, OCELOT_TAG_PREFIX_NONE,
1013-
OCELOT_TAG_PREFIX_NONE);
1014-
1015-
for_each_available_child_of_node(ports, portnp) {
1016-
struct ocelot_port_private *priv;
1017-
struct ocelot_port *ocelot_port;
1018-
struct device_node *phy_node;
1019-
phy_interface_t phy_mode;
1020-
struct phy_device *phy;
1021-
struct regmap *target;
1022-
struct resource *res;
1023-
struct phy *serdes;
1024-
char res_name[8];
1025-
u32 port;
1026-
1027-
if (of_property_read_u32(portnp, "reg", &port))
1028-
continue;
1029-
1030-
snprintf(res_name, sizeof(res_name), "port%d", port);
1031-
1032-
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
1033-
res_name);
1034-
target = ocelot_regmap_init(ocelot, res);
1035-
if (IS_ERR(target))
1036-
continue;
1037-
1038-
phy_node = of_parse_phandle(portnp, "phy-handle", 0);
1039-
if (!phy_node)
1040-
continue;
1041-
1042-
phy = of_phy_find_device(phy_node);
1043-
of_node_put(phy_node);
1044-
if (!phy)
1045-
continue;
1046-
1047-
err = ocelot_probe_port(ocelot, port, target, phy);
1048-
if (err) {
1049-
of_node_put(portnp);
1050-
goto out_put_ports;
1051-
}
1052-
1053-
ocelot_port = ocelot->ports[port];
1054-
priv = container_of(ocelot_port, struct ocelot_port_private,
1055-
port);
1056-
1057-
of_get_phy_mode(portnp, &phy_mode);
1058-
1059-
ocelot_port->phy_mode = phy_mode;
1060-
1061-
switch (ocelot_port->phy_mode) {
1062-
case PHY_INTERFACE_MODE_NA:
1063-
continue;
1064-
case PHY_INTERFACE_MODE_SGMII:
1065-
break;
1066-
case PHY_INTERFACE_MODE_QSGMII:
1067-
/* Ensure clock signals and speed is set on all
1068-
* QSGMII links
1069-
*/
1070-
ocelot_port_writel(ocelot_port,
1071-
DEV_CLOCK_CFG_LINK_SPEED
1072-
(OCELOT_SPEED_1000),
1073-
DEV_CLOCK_CFG);
1074-
break;
1075-
default:
1076-
dev_err(ocelot->dev,
1077-
"invalid phy mode for port%d, (Q)SGMII only\n",
1078-
port);
1079-
of_node_put(portnp);
1080-
err = -EINVAL;
1081-
goto out_put_ports;
1082-
}
1083-
1084-
serdes = devm_of_phy_get(ocelot->dev, portnp, NULL);
1085-
if (IS_ERR(serdes)) {
1086-
err = PTR_ERR(serdes);
1087-
if (err == -EPROBE_DEFER)
1088-
dev_dbg(ocelot->dev, "deferring probe\n");
1089-
else
1090-
dev_err(ocelot->dev,
1091-
"missing SerDes phys for port%d\n",
1092-
port);
1093-
1094-
of_node_put(portnp);
1095-
goto out_put_ports;
1096-
}
1097-
1098-
priv->serdes = serdes;
1099-
}
1100-
11011141
register_netdevice_notifier(&ocelot_netdevice_nb);
11021142
register_switchdev_notifier(&ocelot_switchdev_nb);
11031143
register_switchdev_blocking_notifier(&ocelot_switchdev_blocking_nb);
@@ -1114,6 +1154,7 @@ static int mscc_ocelot_remove(struct platform_device *pdev)
11141154
struct ocelot *ocelot = platform_get_drvdata(pdev);
11151155

11161156
ocelot_deinit_timestamp(ocelot);
1157+
mscc_ocelot_release_ports(ocelot);
11171158
ocelot_deinit(ocelot);
11181159
unregister_switchdev_blocking_notifier(&ocelot_switchdev_blocking_nb);
11191160
unregister_switchdev_notifier(&ocelot_switchdev_nb);

0 commit comments

Comments
 (0)