dpaa2-switch: integrate the MAC endpoint support
Integrate the common MAC endpoint management support into the dpaa2-switch driver as well. Nothing special happens here, just that the already available dpaa2-mac functions are also called from dpaa2-switch. Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
27cfdadd68
commit
84cba72956
@ -11,7 +11,7 @@ fsl-dpaa2-eth-objs := dpaa2-eth.o dpaa2-ethtool.o dpni.o dpaa2-mac.o dpmac.o dpa
|
|||||||
fsl-dpaa2-eth-${CONFIG_FSL_DPAA2_ETH_DCB} += dpaa2-eth-dcb.o
|
fsl-dpaa2-eth-${CONFIG_FSL_DPAA2_ETH_DCB} += dpaa2-eth-dcb.o
|
||||||
fsl-dpaa2-eth-${CONFIG_DEBUG_FS} += dpaa2-eth-debugfs.o
|
fsl-dpaa2-eth-${CONFIG_DEBUG_FS} += dpaa2-eth-debugfs.o
|
||||||
fsl-dpaa2-ptp-objs := dpaa2-ptp.o dprtc.o
|
fsl-dpaa2-ptp-objs := dpaa2-ptp.o dprtc.o
|
||||||
fsl-dpaa2-switch-objs := dpaa2-switch.o dpaa2-switch-ethtool.o dpsw.o dpaa2-switch-flower.o
|
fsl-dpaa2-switch-objs := dpaa2-switch.o dpaa2-switch-ethtool.o dpsw.o dpaa2-switch-flower.o dpaa2-mac.o dpmac.o
|
||||||
|
|
||||||
# Needed by the tracing framework
|
# Needed by the tracing framework
|
||||||
CFLAGS_dpaa2-eth.o := -I$(src)
|
CFLAGS_dpaa2-eth.o := -I$(src)
|
||||||
|
@ -62,6 +62,10 @@ dpaa2_switch_get_link_ksettings(struct net_device *netdev,
|
|||||||
struct dpsw_link_state state = {0};
|
struct dpsw_link_state state = {0};
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
|
if (dpaa2_switch_port_is_type_phy(port_priv))
|
||||||
|
return phylink_ethtool_ksettings_get(port_priv->mac->phylink,
|
||||||
|
link_ksettings);
|
||||||
|
|
||||||
err = dpsw_if_get_link_state(port_priv->ethsw_data->mc_io, 0,
|
err = dpsw_if_get_link_state(port_priv->ethsw_data->mc_io, 0,
|
||||||
port_priv->ethsw_data->dpsw_handle,
|
port_priv->ethsw_data->dpsw_handle,
|
||||||
port_priv->idx,
|
port_priv->idx,
|
||||||
@ -95,6 +99,10 @@ dpaa2_switch_set_link_ksettings(struct net_device *netdev,
|
|||||||
bool if_running;
|
bool if_running;
|
||||||
int err = 0, ret;
|
int err = 0, ret;
|
||||||
|
|
||||||
|
if (dpaa2_switch_port_is_type_phy(port_priv))
|
||||||
|
return phylink_ethtool_ksettings_set(port_priv->mac->phylink,
|
||||||
|
link_ksettings);
|
||||||
|
|
||||||
/* Interface needs to be down to change link settings */
|
/* Interface needs to be down to change link settings */
|
||||||
if_running = netif_running(netdev);
|
if_running = netif_running(netdev);
|
||||||
if (if_running) {
|
if (if_running) {
|
||||||
|
@ -600,6 +600,12 @@ static int dpaa2_switch_port_link_state_update(struct net_device *netdev)
|
|||||||
struct dpsw_link_state state;
|
struct dpsw_link_state state;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
/* When we manage the MAC/PHY using phylink there is no need
|
||||||
|
* to manually update the netif_carrier.
|
||||||
|
*/
|
||||||
|
if (dpaa2_switch_port_is_type_phy(port_priv))
|
||||||
|
return 0;
|
||||||
|
|
||||||
/* Interrupts are received even though no one issued an 'ifconfig up'
|
/* Interrupts are received even though no one issued an 'ifconfig up'
|
||||||
* on the switch interface. Ignore these link state update interrupts
|
* on the switch interface. Ignore these link state update interrupts
|
||||||
*/
|
*/
|
||||||
@ -677,12 +683,14 @@ static int dpaa2_switch_port_open(struct net_device *netdev)
|
|||||||
struct ethsw_core *ethsw = port_priv->ethsw_data;
|
struct ethsw_core *ethsw = port_priv->ethsw_data;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
/* Explicitly set carrier off, otherwise
|
if (!dpaa2_switch_port_is_type_phy(port_priv)) {
|
||||||
* netif_carrier_ok() will return true and cause 'ip link show'
|
/* Explicitly set carrier off, otherwise
|
||||||
* to report the LOWER_UP flag, even though the link
|
* netif_carrier_ok() will return true and cause 'ip link show'
|
||||||
* notification wasn't even received.
|
* to report the LOWER_UP flag, even though the link
|
||||||
*/
|
* notification wasn't even received.
|
||||||
netif_carrier_off(netdev);
|
*/
|
||||||
|
netif_carrier_off(netdev);
|
||||||
|
}
|
||||||
|
|
||||||
err = dpsw_if_enable(port_priv->ethsw_data->mc_io, 0,
|
err = dpsw_if_enable(port_priv->ethsw_data->mc_io, 0,
|
||||||
port_priv->ethsw_data->dpsw_handle,
|
port_priv->ethsw_data->dpsw_handle,
|
||||||
@ -694,6 +702,9 @@ static int dpaa2_switch_port_open(struct net_device *netdev)
|
|||||||
|
|
||||||
dpaa2_switch_enable_ctrl_if_napi(ethsw);
|
dpaa2_switch_enable_ctrl_if_napi(ethsw);
|
||||||
|
|
||||||
|
if (dpaa2_switch_port_is_type_phy(port_priv))
|
||||||
|
phylink_start(port_priv->mac->phylink);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -703,6 +714,13 @@ static int dpaa2_switch_port_stop(struct net_device *netdev)
|
|||||||
struct ethsw_core *ethsw = port_priv->ethsw_data;
|
struct ethsw_core *ethsw = port_priv->ethsw_data;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
if (dpaa2_switch_port_is_type_phy(port_priv)) {
|
||||||
|
phylink_stop(port_priv->mac->phylink);
|
||||||
|
} else {
|
||||||
|
netif_tx_stop_all_queues(netdev);
|
||||||
|
netif_carrier_off(netdev);
|
||||||
|
}
|
||||||
|
|
||||||
err = dpsw_if_disable(port_priv->ethsw_data->mc_io, 0,
|
err = dpsw_if_disable(port_priv->ethsw_data->mc_io, 0,
|
||||||
port_priv->ethsw_data->dpsw_handle,
|
port_priv->ethsw_data->dpsw_handle,
|
||||||
port_priv->idx);
|
port_priv->idx);
|
||||||
@ -1405,6 +1423,67 @@ bool dpaa2_switch_port_dev_check(const struct net_device *netdev)
|
|||||||
return netdev->netdev_ops == &dpaa2_switch_port_ops;
|
return netdev->netdev_ops == &dpaa2_switch_port_ops;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int dpaa2_switch_port_connect_mac(struct ethsw_port_priv *port_priv)
|
||||||
|
{
|
||||||
|
struct fsl_mc_device *dpsw_port_dev, *dpmac_dev;
|
||||||
|
struct dpaa2_mac *mac;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
dpsw_port_dev = to_fsl_mc_device(port_priv->netdev->dev.parent);
|
||||||
|
dpmac_dev = fsl_mc_get_endpoint(dpsw_port_dev, port_priv->idx);
|
||||||
|
|
||||||
|
if (PTR_ERR(dpmac_dev) == -EPROBE_DEFER)
|
||||||
|
return PTR_ERR(dpmac_dev);
|
||||||
|
|
||||||
|
if (IS_ERR(dpmac_dev) || dpmac_dev->dev.type != &fsl_mc_bus_dpmac_type)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
mac = kzalloc(sizeof(*mac), GFP_KERNEL);
|
||||||
|
if (!mac)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
mac->mc_dev = dpmac_dev;
|
||||||
|
mac->mc_io = port_priv->ethsw_data->mc_io;
|
||||||
|
mac->net_dev = port_priv->netdev;
|
||||||
|
|
||||||
|
err = dpaa2_mac_open(mac);
|
||||||
|
if (err)
|
||||||
|
goto err_free_mac;
|
||||||
|
port_priv->mac = mac;
|
||||||
|
|
||||||
|
if (dpaa2_switch_port_is_type_phy(port_priv)) {
|
||||||
|
err = dpaa2_mac_connect(mac);
|
||||||
|
if (err) {
|
||||||
|
netdev_err(port_priv->netdev,
|
||||||
|
"Error connecting to the MAC endpoint %pe\n",
|
||||||
|
ERR_PTR(err));
|
||||||
|
goto err_close_mac;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_close_mac:
|
||||||
|
dpaa2_mac_close(mac);
|
||||||
|
port_priv->mac = NULL;
|
||||||
|
err_free_mac:
|
||||||
|
kfree(mac);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dpaa2_switch_port_disconnect_mac(struct ethsw_port_priv *port_priv)
|
||||||
|
{
|
||||||
|
if (dpaa2_switch_port_is_type_phy(port_priv))
|
||||||
|
dpaa2_mac_disconnect(port_priv->mac);
|
||||||
|
|
||||||
|
if (!dpaa2_switch_port_has_mac(port_priv))
|
||||||
|
return;
|
||||||
|
|
||||||
|
dpaa2_mac_close(port_priv->mac);
|
||||||
|
kfree(port_priv->mac);
|
||||||
|
port_priv->mac = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static irqreturn_t dpaa2_switch_irq0_handler_thread(int irq_num, void *arg)
|
static irqreturn_t dpaa2_switch_irq0_handler_thread(int irq_num, void *arg)
|
||||||
{
|
{
|
||||||
struct device *dev = (struct device *)arg;
|
struct device *dev = (struct device *)arg;
|
||||||
@ -1427,6 +1506,14 @@ static irqreturn_t dpaa2_switch_irq0_handler_thread(int irq_num, void *arg)
|
|||||||
dpaa2_switch_port_link_state_update(port_priv->netdev);
|
dpaa2_switch_port_link_state_update(port_priv->netdev);
|
||||||
dpaa2_switch_port_set_mac_addr(port_priv);
|
dpaa2_switch_port_set_mac_addr(port_priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (status & DPSW_IRQ_EVENT_ENDPOINT_CHANGED) {
|
||||||
|
if (dpaa2_switch_port_has_mac(port_priv))
|
||||||
|
dpaa2_switch_port_disconnect_mac(port_priv);
|
||||||
|
else
|
||||||
|
dpaa2_switch_port_connect_mac(port_priv);
|
||||||
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
err = dpsw_clear_irq_status(ethsw->mc_io, 0, ethsw->dpsw_handle,
|
err = dpsw_clear_irq_status(ethsw->mc_io, 0, ethsw->dpsw_handle,
|
||||||
DPSW_IRQ_INDEX_IF, status);
|
DPSW_IRQ_INDEX_IF, status);
|
||||||
@ -3112,6 +3199,7 @@ static int dpaa2_switch_remove(struct fsl_mc_device *sw_dev)
|
|||||||
for (i = 0; i < ethsw->sw_attr.num_ifs; i++) {
|
for (i = 0; i < ethsw->sw_attr.num_ifs; i++) {
|
||||||
port_priv = ethsw->ports[i];
|
port_priv = ethsw->ports[i];
|
||||||
unregister_netdev(port_priv->netdev);
|
unregister_netdev(port_priv->netdev);
|
||||||
|
dpaa2_switch_port_disconnect_mac(port_priv);
|
||||||
free_netdev(port_priv->netdev);
|
free_netdev(port_priv->netdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3191,6 +3279,10 @@ static int dpaa2_switch_probe_port(struct ethsw_core *ethsw,
|
|||||||
goto err_port_probe;
|
goto err_port_probe;
|
||||||
port_priv->learn_ena = false;
|
port_priv->learn_ena = false;
|
||||||
|
|
||||||
|
err = dpaa2_switch_port_connect_mac(port_priv);
|
||||||
|
if (err)
|
||||||
|
goto err_port_probe;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_port_probe:
|
err_port_probe:
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include <net/pkt_cls.h>
|
#include <net/pkt_cls.h>
|
||||||
#include <soc/fsl/dpaa2-io.h>
|
#include <soc/fsl/dpaa2-io.h>
|
||||||
|
|
||||||
|
#include "dpaa2-mac.h"
|
||||||
#include "dpsw.h"
|
#include "dpsw.h"
|
||||||
|
|
||||||
/* Number of IRQs supported */
|
/* Number of IRQs supported */
|
||||||
@ -159,6 +160,7 @@ struct ethsw_port_priv {
|
|||||||
bool learn_ena;
|
bool learn_ena;
|
||||||
|
|
||||||
struct dpaa2_switch_filter_block *filter_block;
|
struct dpaa2_switch_filter_block *filter_block;
|
||||||
|
struct dpaa2_mac *mac;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Switch data */
|
/* Switch data */
|
||||||
@ -225,6 +227,22 @@ static inline bool dpaa2_switch_supports_cpu_traffic(struct ethsw_core *ethsw)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
dpaa2_switch_port_is_type_phy(struct ethsw_port_priv *port_priv)
|
||||||
|
{
|
||||||
|
if (port_priv->mac &&
|
||||||
|
(port_priv->mac->attr.link_type == DPMAC_LINK_TYPE_PHY ||
|
||||||
|
port_priv->mac->attr.link_type == DPMAC_LINK_TYPE_BACKPLANE))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool dpaa2_switch_port_has_mac(struct ethsw_port_priv *port_priv)
|
||||||
|
{
|
||||||
|
return port_priv->mac ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
bool dpaa2_switch_port_dev_check(const struct net_device *netdev);
|
bool dpaa2_switch_port_dev_check(const struct net_device *netdev);
|
||||||
|
|
||||||
int dpaa2_switch_port_vlans_add(struct net_device *netdev,
|
int dpaa2_switch_port_vlans_add(struct net_device *netdev,
|
||||||
|
@ -98,6 +98,11 @@ int dpsw_reset(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token);
|
|||||||
*/
|
*/
|
||||||
#define DPSW_IRQ_EVENT_LINK_CHANGED 0x0001
|
#define DPSW_IRQ_EVENT_LINK_CHANGED 0x0001
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DPSW_IRQ_EVENT_ENDPOINT_CHANGED - Indicates a change in endpoint
|
||||||
|
*/
|
||||||
|
#define DPSW_IRQ_EVENT_ENDPOINT_CHANGED 0x0002
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct dpsw_irq_cfg - IRQ configuration
|
* struct dpsw_irq_cfg - IRQ configuration
|
||||||
* @addr: Address that must be written to signal a message-based interrupt
|
* @addr: Address that must be written to signal a message-based interrupt
|
||||||
|
Loading…
x
Reference in New Issue
Block a user