mirror of https://gitee.com/openkylin/linux.git
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>
This commit is contained in:
commit
2b33b202dc
|
@ -585,7 +585,10 @@ static int felix_setup(struct dsa_switch *ds)
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
ocelot_init(ocelot);
|
err = ocelot_init(ocelot);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
if (ocelot->ptp) {
|
if (ocelot->ptp) {
|
||||||
err = ocelot_init_timestamp(ocelot, &ocelot_ptp_clock_info);
|
err = ocelot_init_timestamp(ocelot, &ocelot_ptp_clock_info);
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -640,10 +643,13 @@ static void felix_teardown(struct dsa_switch *ds)
|
||||||
{
|
{
|
||||||
struct ocelot *ocelot = ds->priv;
|
struct ocelot *ocelot = ds->priv;
|
||||||
struct felix *felix = ocelot_to_felix(ocelot);
|
struct felix *felix = ocelot_to_felix(ocelot);
|
||||||
|
int port;
|
||||||
|
|
||||||
if (felix->info->mdio_bus_free)
|
if (felix->info->mdio_bus_free)
|
||||||
felix->info->mdio_bus_free(ocelot);
|
felix->info->mdio_bus_free(ocelot);
|
||||||
|
|
||||||
|
for (port = 0; port < ocelot->num_phys_ports; port++)
|
||||||
|
ocelot_deinit_port(ocelot, port);
|
||||||
ocelot_deinit_timestamp(ocelot);
|
ocelot_deinit_timestamp(ocelot);
|
||||||
/* stop workqueue thread */
|
/* stop workqueue thread */
|
||||||
ocelot_deinit(ocelot);
|
ocelot_deinit(ocelot);
|
||||||
|
|
|
@ -1008,7 +1008,7 @@ static const struct felix_info seville_info_vsc9953 = {
|
||||||
.vcap_is2_keys = vsc9953_vcap_is2_keys,
|
.vcap_is2_keys = vsc9953_vcap_is2_keys,
|
||||||
.vcap_is2_actions = vsc9953_vcap_is2_actions,
|
.vcap_is2_actions = vsc9953_vcap_is2_actions,
|
||||||
.vcap = vsc9953_vcap_props,
|
.vcap = vsc9953_vcap_props,
|
||||||
.shared_queue_sz = 128 * 1024,
|
.shared_queue_sz = 2048 * 1024,
|
||||||
.num_mact_rows = 2048,
|
.num_mact_rows = 2048,
|
||||||
.num_ports = 10,
|
.num_ports = 10,
|
||||||
.mdio_bus_alloc = vsc9953_mdio_bus_alloc,
|
.mdio_bus_alloc = vsc9953_mdio_bus_alloc,
|
||||||
|
|
|
@ -421,10 +421,15 @@ int ocelot_port_add_txtstamp_skb(struct ocelot_port *ocelot_port,
|
||||||
|
|
||||||
if (ocelot->ptp && shinfo->tx_flags & SKBTX_HW_TSTAMP &&
|
if (ocelot->ptp && shinfo->tx_flags & SKBTX_HW_TSTAMP &&
|
||||||
ocelot_port->ptp_cmd == IFH_REW_OP_TWO_STEP_PTP) {
|
ocelot_port->ptp_cmd == IFH_REW_OP_TWO_STEP_PTP) {
|
||||||
|
spin_lock(&ocelot_port->ts_id_lock);
|
||||||
|
|
||||||
shinfo->tx_flags |= SKBTX_IN_PROGRESS;
|
shinfo->tx_flags |= SKBTX_IN_PROGRESS;
|
||||||
/* Store timestamp ID in cb[0] of sk_buff */
|
/* Store timestamp ID in cb[0] of sk_buff */
|
||||||
skb->cb[0] = ocelot_port->ts_id % 4;
|
skb->cb[0] = ocelot_port->ts_id;
|
||||||
|
ocelot_port->ts_id = (ocelot_port->ts_id + 1) % 4;
|
||||||
skb_queue_tail(&ocelot_port->tx_skbs, skb);
|
skb_queue_tail(&ocelot_port->tx_skbs, skb);
|
||||||
|
|
||||||
|
spin_unlock(&ocelot_port->ts_id_lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return -ENODATA;
|
return -ENODATA;
|
||||||
|
@ -1300,6 +1305,7 @@ void ocelot_init_port(struct ocelot *ocelot, int port)
|
||||||
struct ocelot_port *ocelot_port = ocelot->ports[port];
|
struct ocelot_port *ocelot_port = ocelot->ports[port];
|
||||||
|
|
||||||
skb_queue_head_init(&ocelot_port->tx_skbs);
|
skb_queue_head_init(&ocelot_port->tx_skbs);
|
||||||
|
spin_lock_init(&ocelot_port->ts_id_lock);
|
||||||
|
|
||||||
/* Basic L2 initialization */
|
/* Basic L2 initialization */
|
||||||
|
|
||||||
|
@ -1544,18 +1550,18 @@ EXPORT_SYMBOL(ocelot_init);
|
||||||
|
|
||||||
void ocelot_deinit(struct ocelot *ocelot)
|
void ocelot_deinit(struct ocelot *ocelot)
|
||||||
{
|
{
|
||||||
struct ocelot_port *port;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
cancel_delayed_work(&ocelot->stats_work);
|
cancel_delayed_work(&ocelot->stats_work);
|
||||||
destroy_workqueue(ocelot->stats_queue);
|
destroy_workqueue(ocelot->stats_queue);
|
||||||
mutex_destroy(&ocelot->stats_lock);
|
mutex_destroy(&ocelot->stats_lock);
|
||||||
|
|
||||||
for (i = 0; i < ocelot->num_phys_ports; i++) {
|
|
||||||
port = ocelot->ports[i];
|
|
||||||
skb_queue_purge(&port->tx_skbs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(ocelot_deinit);
|
EXPORT_SYMBOL(ocelot_deinit);
|
||||||
|
|
||||||
|
void ocelot_deinit_port(struct ocelot *ocelot, int port)
|
||||||
|
{
|
||||||
|
struct ocelot_port *ocelot_port = ocelot->ports[port];
|
||||||
|
|
||||||
|
skb_queue_purge(&ocelot_port->tx_skbs);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(ocelot_deinit_port);
|
||||||
|
|
||||||
MODULE_LICENSE("Dual MIT/GPL");
|
MODULE_LICENSE("Dual MIT/GPL");
|
||||||
|
|
|
@ -330,6 +330,7 @@ static int ocelot_port_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||||
u8 grp = 0; /* Send everything on CPU group 0 */
|
u8 grp = 0; /* Send everything on CPU group 0 */
|
||||||
unsigned int i, count, last;
|
unsigned int i, count, last;
|
||||||
int port = priv->chip_port;
|
int port = priv->chip_port;
|
||||||
|
bool do_tstamp;
|
||||||
|
|
||||||
val = ocelot_read(ocelot, QS_INJ_STATUS);
|
val = ocelot_read(ocelot, QS_INJ_STATUS);
|
||||||
if (!(val & QS_INJ_STATUS_FIFO_RDY(BIT(grp))) ||
|
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)
|
||||||
info.vid = skb_vlan_tag_get(skb);
|
info.vid = skb_vlan_tag_get(skb);
|
||||||
|
|
||||||
/* Check if timestamping is needed */
|
/* Check if timestamping is needed */
|
||||||
|
do_tstamp = (ocelot_port_add_txtstamp_skb(ocelot_port, skb) == 0);
|
||||||
|
|
||||||
if (ocelot->ptp && shinfo->tx_flags & SKBTX_HW_TSTAMP) {
|
if (ocelot->ptp && shinfo->tx_flags & SKBTX_HW_TSTAMP) {
|
||||||
info.rew_op = ocelot_port->ptp_cmd;
|
info.rew_op = ocelot_port->ptp_cmd;
|
||||||
if (ocelot_port->ptp_cmd == IFH_REW_OP_TWO_STEP_PTP)
|
if (ocelot_port->ptp_cmd == IFH_REW_OP_TWO_STEP_PTP)
|
||||||
info.rew_op |= (ocelot_port->ts_id % 4) << 3;
|
info.rew_op |= skb->cb[0] << 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
ocelot_gen_ifh(ifh, &info);
|
ocelot_gen_ifh(ifh, &info);
|
||||||
|
@ -380,12 +383,9 @@ static int ocelot_port_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||||
dev->stats.tx_packets++;
|
dev->stats.tx_packets++;
|
||||||
dev->stats.tx_bytes += skb->len;
|
dev->stats.tx_bytes += skb->len;
|
||||||
|
|
||||||
if (!ocelot_port_add_txtstamp_skb(ocelot_port, skb)) {
|
if (!do_tstamp)
|
||||||
ocelot_port->ts_id++;
|
dev_kfree_skb_any(skb);
|
||||||
return NETDEV_TX_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
dev_kfree_skb_any(skb);
|
|
||||||
return NETDEV_TX_OK;
|
return NETDEV_TX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -896,11 +896,137 @@ static struct ptp_clock_info ocelot_ptp_clock_info = {
|
||||||
.enable = ocelot_ptp_enable,
|
.enable = ocelot_ptp_enable,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void mscc_ocelot_release_ports(struct ocelot *ocelot)
|
||||||
|
{
|
||||||
|
int port;
|
||||||
|
|
||||||
|
for (port = 0; port < ocelot->num_phys_ports; port++) {
|
||||||
|
struct ocelot_port_private *priv;
|
||||||
|
struct ocelot_port *ocelot_port;
|
||||||
|
|
||||||
|
ocelot_port = ocelot->ports[port];
|
||||||
|
if (!ocelot_port)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ocelot_deinit_port(ocelot, port);
|
||||||
|
|
||||||
|
priv = container_of(ocelot_port, struct ocelot_port_private,
|
||||||
|
port);
|
||||||
|
|
||||||
|
unregister_netdev(priv->dev);
|
||||||
|
free_netdev(priv->dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mscc_ocelot_init_ports(struct platform_device *pdev,
|
||||||
|
struct device_node *ports)
|
||||||
|
{
|
||||||
|
struct ocelot *ocelot = platform_get_drvdata(pdev);
|
||||||
|
struct device_node *portnp;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
ocelot->ports = devm_kcalloc(ocelot->dev, ocelot->num_phys_ports,
|
||||||
|
sizeof(struct ocelot_port *), GFP_KERNEL);
|
||||||
|
if (!ocelot->ports)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
/* No NPI port */
|
||||||
|
ocelot_configure_cpu(ocelot, -1, OCELOT_TAG_PREFIX_NONE,
|
||||||
|
OCELOT_TAG_PREFIX_NONE);
|
||||||
|
|
||||||
|
for_each_available_child_of_node(ports, portnp) {
|
||||||
|
struct ocelot_port_private *priv;
|
||||||
|
struct ocelot_port *ocelot_port;
|
||||||
|
struct device_node *phy_node;
|
||||||
|
phy_interface_t phy_mode;
|
||||||
|
struct phy_device *phy;
|
||||||
|
struct regmap *target;
|
||||||
|
struct resource *res;
|
||||||
|
struct phy *serdes;
|
||||||
|
char res_name[8];
|
||||||
|
u32 port;
|
||||||
|
|
||||||
|
if (of_property_read_u32(portnp, "reg", &port))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
snprintf(res_name, sizeof(res_name), "port%d", port);
|
||||||
|
|
||||||
|
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
|
||||||
|
res_name);
|
||||||
|
target = ocelot_regmap_init(ocelot, res);
|
||||||
|
if (IS_ERR(target))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
phy_node = of_parse_phandle(portnp, "phy-handle", 0);
|
||||||
|
if (!phy_node)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
phy = of_phy_find_device(phy_node);
|
||||||
|
of_node_put(phy_node);
|
||||||
|
if (!phy)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
err = ocelot_probe_port(ocelot, port, target, phy);
|
||||||
|
if (err) {
|
||||||
|
of_node_put(portnp);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
ocelot_port = ocelot->ports[port];
|
||||||
|
priv = container_of(ocelot_port, struct ocelot_port_private,
|
||||||
|
port);
|
||||||
|
|
||||||
|
of_get_phy_mode(portnp, &phy_mode);
|
||||||
|
|
||||||
|
ocelot_port->phy_mode = phy_mode;
|
||||||
|
|
||||||
|
switch (ocelot_port->phy_mode) {
|
||||||
|
case PHY_INTERFACE_MODE_NA:
|
||||||
|
continue;
|
||||||
|
case PHY_INTERFACE_MODE_SGMII:
|
||||||
|
break;
|
||||||
|
case PHY_INTERFACE_MODE_QSGMII:
|
||||||
|
/* Ensure clock signals and speed is set on all
|
||||||
|
* QSGMII links
|
||||||
|
*/
|
||||||
|
ocelot_port_writel(ocelot_port,
|
||||||
|
DEV_CLOCK_CFG_LINK_SPEED
|
||||||
|
(OCELOT_SPEED_1000),
|
||||||
|
DEV_CLOCK_CFG);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dev_err(ocelot->dev,
|
||||||
|
"invalid phy mode for port%d, (Q)SGMII only\n",
|
||||||
|
port);
|
||||||
|
of_node_put(portnp);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
serdes = devm_of_phy_get(ocelot->dev, portnp, NULL);
|
||||||
|
if (IS_ERR(serdes)) {
|
||||||
|
err = PTR_ERR(serdes);
|
||||||
|
if (err == -EPROBE_DEFER)
|
||||||
|
dev_dbg(ocelot->dev, "deferring probe\n");
|
||||||
|
else
|
||||||
|
dev_err(ocelot->dev,
|
||||||
|
"missing SerDes phys for port%d\n",
|
||||||
|
port);
|
||||||
|
|
||||||
|
of_node_put(portnp);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->serdes = serdes;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int mscc_ocelot_probe(struct platform_device *pdev)
|
static int mscc_ocelot_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct device_node *np = pdev->dev.of_node;
|
struct device_node *np = pdev->dev.of_node;
|
||||||
struct device_node *ports, *portnp;
|
|
||||||
int err, irq_xtr, irq_ptp_rdy;
|
int err, irq_xtr, irq_ptp_rdy;
|
||||||
|
struct device_node *ports;
|
||||||
struct ocelot *ocelot;
|
struct ocelot *ocelot;
|
||||||
struct regmap *hsio;
|
struct regmap *hsio;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
@ -985,20 +1111,24 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
ports = of_get_child_by_name(np, "ethernet-ports");
|
ports = of_get_child_by_name(np, "ethernet-ports");
|
||||||
if (!ports) {
|
if (!ports) {
|
||||||
dev_err(&pdev->dev, "no ethernet-ports child node found\n");
|
dev_err(ocelot->dev, "no ethernet-ports child node found\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
ocelot->num_phys_ports = of_get_child_count(ports);
|
ocelot->num_phys_ports = of_get_child_count(ports);
|
||||||
|
|
||||||
ocelot->ports = devm_kcalloc(&pdev->dev, ocelot->num_phys_ports,
|
|
||||||
sizeof(struct ocelot_port *), GFP_KERNEL);
|
|
||||||
|
|
||||||
ocelot->vcap_is2_keys = vsc7514_vcap_is2_keys;
|
ocelot->vcap_is2_keys = vsc7514_vcap_is2_keys;
|
||||||
ocelot->vcap_is2_actions = vsc7514_vcap_is2_actions;
|
ocelot->vcap_is2_actions = vsc7514_vcap_is2_actions;
|
||||||
ocelot->vcap = vsc7514_vcap_props;
|
ocelot->vcap = vsc7514_vcap_props;
|
||||||
|
|
||||||
ocelot_init(ocelot);
|
err = ocelot_init(ocelot);
|
||||||
|
if (err)
|
||||||
|
goto out_put_ports;
|
||||||
|
|
||||||
|
err = mscc_ocelot_init_ports(pdev, ports);
|
||||||
|
if (err)
|
||||||
|
goto out_put_ports;
|
||||||
|
|
||||||
if (ocelot->ptp) {
|
if (ocelot->ptp) {
|
||||||
err = ocelot_init_timestamp(ocelot, &ocelot_ptp_clock_info);
|
err = ocelot_init_timestamp(ocelot, &ocelot_ptp_clock_info);
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -1008,96 +1138,6 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* No NPI port */
|
|
||||||
ocelot_configure_cpu(ocelot, -1, OCELOT_TAG_PREFIX_NONE,
|
|
||||||
OCELOT_TAG_PREFIX_NONE);
|
|
||||||
|
|
||||||
for_each_available_child_of_node(ports, portnp) {
|
|
||||||
struct ocelot_port_private *priv;
|
|
||||||
struct ocelot_port *ocelot_port;
|
|
||||||
struct device_node *phy_node;
|
|
||||||
phy_interface_t phy_mode;
|
|
||||||
struct phy_device *phy;
|
|
||||||
struct regmap *target;
|
|
||||||
struct resource *res;
|
|
||||||
struct phy *serdes;
|
|
||||||
char res_name[8];
|
|
||||||
u32 port;
|
|
||||||
|
|
||||||
if (of_property_read_u32(portnp, "reg", &port))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
snprintf(res_name, sizeof(res_name), "port%d", port);
|
|
||||||
|
|
||||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
|
|
||||||
res_name);
|
|
||||||
target = ocelot_regmap_init(ocelot, res);
|
|
||||||
if (IS_ERR(target))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
phy_node = of_parse_phandle(portnp, "phy-handle", 0);
|
|
||||||
if (!phy_node)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
phy = of_phy_find_device(phy_node);
|
|
||||||
of_node_put(phy_node);
|
|
||||||
if (!phy)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
err = ocelot_probe_port(ocelot, port, target, phy);
|
|
||||||
if (err) {
|
|
||||||
of_node_put(portnp);
|
|
||||||
goto out_put_ports;
|
|
||||||
}
|
|
||||||
|
|
||||||
ocelot_port = ocelot->ports[port];
|
|
||||||
priv = container_of(ocelot_port, struct ocelot_port_private,
|
|
||||||
port);
|
|
||||||
|
|
||||||
of_get_phy_mode(portnp, &phy_mode);
|
|
||||||
|
|
||||||
ocelot_port->phy_mode = phy_mode;
|
|
||||||
|
|
||||||
switch (ocelot_port->phy_mode) {
|
|
||||||
case PHY_INTERFACE_MODE_NA:
|
|
||||||
continue;
|
|
||||||
case PHY_INTERFACE_MODE_SGMII:
|
|
||||||
break;
|
|
||||||
case PHY_INTERFACE_MODE_QSGMII:
|
|
||||||
/* Ensure clock signals and speed is set on all
|
|
||||||
* QSGMII links
|
|
||||||
*/
|
|
||||||
ocelot_port_writel(ocelot_port,
|
|
||||||
DEV_CLOCK_CFG_LINK_SPEED
|
|
||||||
(OCELOT_SPEED_1000),
|
|
||||||
DEV_CLOCK_CFG);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
dev_err(ocelot->dev,
|
|
||||||
"invalid phy mode for port%d, (Q)SGMII only\n",
|
|
||||||
port);
|
|
||||||
of_node_put(portnp);
|
|
||||||
err = -EINVAL;
|
|
||||||
goto out_put_ports;
|
|
||||||
}
|
|
||||||
|
|
||||||
serdes = devm_of_phy_get(ocelot->dev, portnp, NULL);
|
|
||||||
if (IS_ERR(serdes)) {
|
|
||||||
err = PTR_ERR(serdes);
|
|
||||||
if (err == -EPROBE_DEFER)
|
|
||||||
dev_dbg(ocelot->dev, "deferring probe\n");
|
|
||||||
else
|
|
||||||
dev_err(ocelot->dev,
|
|
||||||
"missing SerDes phys for port%d\n",
|
|
||||||
port);
|
|
||||||
|
|
||||||
of_node_put(portnp);
|
|
||||||
goto out_put_ports;
|
|
||||||
}
|
|
||||||
|
|
||||||
priv->serdes = serdes;
|
|
||||||
}
|
|
||||||
|
|
||||||
register_netdevice_notifier(&ocelot_netdevice_nb);
|
register_netdevice_notifier(&ocelot_netdevice_nb);
|
||||||
register_switchdev_notifier(&ocelot_switchdev_nb);
|
register_switchdev_notifier(&ocelot_switchdev_nb);
|
||||||
register_switchdev_blocking_notifier(&ocelot_switchdev_blocking_nb);
|
register_switchdev_blocking_notifier(&ocelot_switchdev_blocking_nb);
|
||||||
|
@ -1114,6 +1154,7 @@ static int mscc_ocelot_remove(struct platform_device *pdev)
|
||||||
struct ocelot *ocelot = platform_get_drvdata(pdev);
|
struct ocelot *ocelot = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
ocelot_deinit_timestamp(ocelot);
|
ocelot_deinit_timestamp(ocelot);
|
||||||
|
mscc_ocelot_release_ports(ocelot);
|
||||||
ocelot_deinit(ocelot);
|
ocelot_deinit(ocelot);
|
||||||
unregister_switchdev_blocking_notifier(&ocelot_switchdev_blocking_nb);
|
unregister_switchdev_blocking_notifier(&ocelot_switchdev_blocking_nb);
|
||||||
unregister_switchdev_notifier(&ocelot_switchdev_nb);
|
unregister_switchdev_notifier(&ocelot_switchdev_nb);
|
||||||
|
|
|
@ -566,6 +566,7 @@ struct ocelot_port {
|
||||||
u8 ptp_cmd;
|
u8 ptp_cmd;
|
||||||
struct sk_buff_head tx_skbs;
|
struct sk_buff_head tx_skbs;
|
||||||
u8 ts_id;
|
u8 ts_id;
|
||||||
|
spinlock_t ts_id_lock;
|
||||||
|
|
||||||
phy_interface_t phy_mode;
|
phy_interface_t phy_mode;
|
||||||
|
|
||||||
|
@ -677,6 +678,7 @@ void ocelot_configure_cpu(struct ocelot *ocelot, int npi,
|
||||||
int ocelot_init(struct ocelot *ocelot);
|
int ocelot_init(struct ocelot *ocelot);
|
||||||
void ocelot_deinit(struct ocelot *ocelot);
|
void ocelot_deinit(struct ocelot *ocelot);
|
||||||
void ocelot_init_port(struct ocelot *ocelot, int port);
|
void ocelot_init_port(struct ocelot *ocelot, int port);
|
||||||
|
void ocelot_deinit_port(struct ocelot *ocelot, int port);
|
||||||
|
|
||||||
/* DSA callbacks */
|
/* DSA callbacks */
|
||||||
void ocelot_port_enable(struct ocelot *ocelot, int port,
|
void ocelot_port_enable(struct ocelot *ocelot, int port,
|
||||||
|
|
|
@ -160,11 +160,14 @@ static struct sk_buff *ocelot_xmit(struct sk_buff *skb,
|
||||||
packing(injection, &qos_class, 19, 17, OCELOT_TAG_LEN, PACK, 0);
|
packing(injection, &qos_class, 19, 17, OCELOT_TAG_LEN, PACK, 0);
|
||||||
|
|
||||||
if (ocelot->ptp && (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
|
if (ocelot->ptp && (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
|
||||||
|
struct sk_buff *clone = DSA_SKB_CB(skb)->clone;
|
||||||
|
|
||||||
rew_op = ocelot_port->ptp_cmd;
|
rew_op = ocelot_port->ptp_cmd;
|
||||||
if (ocelot_port->ptp_cmd == IFH_REW_OP_TWO_STEP_PTP) {
|
/* Retrieve timestamp ID populated inside skb->cb[0] of the
|
||||||
rew_op |= (ocelot_port->ts_id % 4) << 3;
|
* clone by ocelot_port_add_txtstamp_skb
|
||||||
ocelot_port->ts_id++;
|
*/
|
||||||
}
|
if (ocelot_port->ptp_cmd == IFH_REW_OP_TWO_STEP_PTP)
|
||||||
|
rew_op |= clone->cb[0] << 3;
|
||||||
|
|
||||||
packing(injection, &rew_op, 125, 117, OCELOT_TAG_LEN, PACK, 0);
|
packing(injection, &rew_op, 125, 117, OCELOT_TAG_LEN, PACK, 0);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue