mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-15 01:24:33 +00:00
Merge branch 'net-iep-clock-module-fixes'
Meghana Malladi says: ==================== IEP clock module bug fixes This series has some bug fixes for IEP module needed by PPS and timesync operations. Patch 1/2 fixes firmware load sequence to run all the firmwares when either of the ethernet interfaces is up. Move all the code common for firmware bringup under common functions. Patch 2/2 fixes distorted PPS signal when the ethernet interfaces are brough down and up. This patch also fixes enabling PPS signal after bringing the interface up, without disabling PPS. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
ce21419b55
@ -215,6 +215,9 @@ static void icss_iep_enable_shadow_mode(struct icss_iep *iep)
|
||||
for (cmp = IEP_MIN_CMP; cmp < IEP_MAX_CMP; cmp++) {
|
||||
regmap_update_bits(iep->map, ICSS_IEP_CMP_STAT_REG,
|
||||
IEP_CMP_STATUS(cmp), IEP_CMP_STATUS(cmp));
|
||||
|
||||
regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG,
|
||||
IEP_CMP_CFG_CMP_EN(cmp), 0);
|
||||
}
|
||||
|
||||
/* enable reset counter on CMP0 event */
|
||||
@ -780,6 +783,11 @@ int icss_iep_exit(struct icss_iep *iep)
|
||||
}
|
||||
icss_iep_disable(iep);
|
||||
|
||||
if (iep->pps_enabled)
|
||||
icss_iep_pps_enable(iep, false);
|
||||
else if (iep->perout_enabled)
|
||||
icss_iep_perout_enable(iep, NULL, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(icss_iep_exit);
|
||||
|
@ -855,31 +855,6 @@ irqreturn_t prueth_rx_irq(int irq, void *dev_id)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(prueth_rx_irq);
|
||||
|
||||
void prueth_emac_stop(struct prueth_emac *emac)
|
||||
{
|
||||
struct prueth *prueth = emac->prueth;
|
||||
int slice;
|
||||
|
||||
switch (emac->port_id) {
|
||||
case PRUETH_PORT_MII0:
|
||||
slice = ICSS_SLICE0;
|
||||
break;
|
||||
case PRUETH_PORT_MII1:
|
||||
slice = ICSS_SLICE1;
|
||||
break;
|
||||
default:
|
||||
netdev_err(emac->ndev, "invalid port\n");
|
||||
return;
|
||||
}
|
||||
|
||||
emac->fw_running = 0;
|
||||
if (!emac->is_sr1)
|
||||
rproc_shutdown(prueth->txpru[slice]);
|
||||
rproc_shutdown(prueth->rtu[slice]);
|
||||
rproc_shutdown(prueth->pru[slice]);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(prueth_emac_stop);
|
||||
|
||||
void prueth_cleanup_tx_ts(struct prueth_emac *emac)
|
||||
{
|
||||
int i;
|
||||
|
@ -397,7 +397,7 @@ static int prueth_emac_buffer_setup(struct prueth_emac *emac)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void icssg_init_emac_mode(struct prueth *prueth)
|
||||
void icssg_init_emac_mode(struct prueth *prueth)
|
||||
{
|
||||
/* When the device is configured as a bridge and it is being brought
|
||||
* back to the emac mode, the host mac address has to be set as 0.
|
||||
@ -406,9 +406,6 @@ static void icssg_init_emac_mode(struct prueth *prueth)
|
||||
int i;
|
||||
u8 mac[ETH_ALEN] = { 0 };
|
||||
|
||||
if (prueth->emacs_initialized)
|
||||
return;
|
||||
|
||||
/* Set VLAN TABLE address base */
|
||||
regmap_update_bits(prueth->miig_rt, FDB_GEN_CFG1, SMEM_VLAN_OFFSET_MASK,
|
||||
addr << SMEM_VLAN_OFFSET);
|
||||
@ -423,15 +420,13 @@ static void icssg_init_emac_mode(struct prueth *prueth)
|
||||
/* Clear host MAC address */
|
||||
icssg_class_set_host_mac_addr(prueth->miig_rt, mac);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(icssg_init_emac_mode);
|
||||
|
||||
static void icssg_init_fw_offload_mode(struct prueth *prueth)
|
||||
void icssg_init_fw_offload_mode(struct prueth *prueth)
|
||||
{
|
||||
u32 addr = prueth->shram.pa + EMAC_ICSSG_SWITCH_DEFAULT_VLAN_TABLE_OFFSET;
|
||||
int i;
|
||||
|
||||
if (prueth->emacs_initialized)
|
||||
return;
|
||||
|
||||
/* Set VLAN TABLE address base */
|
||||
regmap_update_bits(prueth->miig_rt, FDB_GEN_CFG1, SMEM_VLAN_OFFSET_MASK,
|
||||
addr << SMEM_VLAN_OFFSET);
|
||||
@ -448,6 +443,7 @@ static void icssg_init_fw_offload_mode(struct prueth *prueth)
|
||||
icssg_class_set_host_mac_addr(prueth->miig_rt, prueth->hw_bridge_dev->dev_addr);
|
||||
icssg_set_pvid(prueth, prueth->default_vlan, PRUETH_PORT_HOST);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(icssg_init_fw_offload_mode);
|
||||
|
||||
int icssg_config(struct prueth *prueth, struct prueth_emac *emac, int slice)
|
||||
{
|
||||
@ -455,11 +451,6 @@ int icssg_config(struct prueth *prueth, struct prueth_emac *emac, int slice)
|
||||
struct icssg_flow_cfg __iomem *flow_cfg;
|
||||
int ret;
|
||||
|
||||
if (prueth->is_switch_mode || prueth->is_hsr_offload_mode)
|
||||
icssg_init_fw_offload_mode(prueth);
|
||||
else
|
||||
icssg_init_emac_mode(prueth);
|
||||
|
||||
memset_io(config, 0, TAS_GATE_MASK_LIST0);
|
||||
icssg_miig_queues_init(prueth, slice);
|
||||
|
||||
@ -786,3 +777,27 @@ void icssg_set_pvid(struct prueth *prueth, u8 vid, u8 port)
|
||||
writel(pvid, prueth->shram.va + EMAC_ICSSG_SWITCH_PORT0_DEFAULT_VLAN_OFFSET);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(icssg_set_pvid);
|
||||
|
||||
int emac_fdb_flow_id_updated(struct prueth_emac *emac)
|
||||
{
|
||||
struct mgmt_cmd_rsp fdb_cmd_rsp = { 0 };
|
||||
int slice = prueth_emac_slice(emac);
|
||||
struct mgmt_cmd fdb_cmd = { 0 };
|
||||
int ret;
|
||||
|
||||
fdb_cmd.header = ICSSG_FW_MGMT_CMD_HEADER;
|
||||
fdb_cmd.type = ICSSG_FW_MGMT_FDB_CMD_TYPE_RX_FLOW;
|
||||
fdb_cmd.seqnum = ++(emac->prueth->icssg_hwcmdseq);
|
||||
fdb_cmd.param = 0;
|
||||
|
||||
fdb_cmd.param |= (slice << 4);
|
||||
fdb_cmd.cmd_args[0] = 0;
|
||||
|
||||
ret = icssg_send_fdb_msg(emac, &fdb_cmd, &fdb_cmd_rsp);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
WARN_ON(fdb_cmd.seqnum != fdb_cmd_rsp.seqnum);
|
||||
return fdb_cmd_rsp.status == 1 ? 0 : -EINVAL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(emac_fdb_flow_id_updated);
|
||||
|
@ -55,6 +55,7 @@ struct icssg_rxq_ctx {
|
||||
#define ICSSG_FW_MGMT_FDB_CMD_TYPE 0x03
|
||||
#define ICSSG_FW_MGMT_CMD_TYPE 0x04
|
||||
#define ICSSG_FW_MGMT_PKT 0x80000000
|
||||
#define ICSSG_FW_MGMT_FDB_CMD_TYPE_RX_FLOW 0x05
|
||||
|
||||
struct icssg_r30_cmd {
|
||||
u32 cmd[4];
|
||||
|
@ -164,11 +164,26 @@ static struct icssg_firmwares icssg_emac_firmwares[] = {
|
||||
}
|
||||
};
|
||||
|
||||
static int prueth_emac_start(struct prueth *prueth, struct prueth_emac *emac)
|
||||
static int prueth_start(struct rproc *rproc, const char *fw_name)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = rproc_set_firmware(rproc, fw_name);
|
||||
if (ret)
|
||||
return ret;
|
||||
return rproc_boot(rproc);
|
||||
}
|
||||
|
||||
static void prueth_shutdown(struct rproc *rproc)
|
||||
{
|
||||
rproc_shutdown(rproc);
|
||||
}
|
||||
|
||||
static int prueth_emac_start(struct prueth *prueth)
|
||||
{
|
||||
struct icssg_firmwares *firmwares;
|
||||
struct device *dev = prueth->dev;
|
||||
int slice, ret;
|
||||
int ret, slice;
|
||||
|
||||
if (prueth->is_switch_mode)
|
||||
firmwares = icssg_switch_firmwares;
|
||||
@ -177,49 +192,126 @@ static int prueth_emac_start(struct prueth *prueth, struct prueth_emac *emac)
|
||||
else
|
||||
firmwares = icssg_emac_firmwares;
|
||||
|
||||
slice = prueth_emac_slice(emac);
|
||||
if (slice < 0) {
|
||||
netdev_err(emac->ndev, "invalid port\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = icssg_config(prueth, emac, slice);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = rproc_set_firmware(prueth->pru[slice], firmwares[slice].pru);
|
||||
ret = rproc_boot(prueth->pru[slice]);
|
||||
for (slice = 0; slice < PRUETH_NUM_MACS; slice++) {
|
||||
ret = prueth_start(prueth->pru[slice], firmwares[slice].pru);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to boot PRU%d: %d\n", slice, ret);
|
||||
return -EINVAL;
|
||||
goto unwind_slices;
|
||||
}
|
||||
|
||||
ret = rproc_set_firmware(prueth->rtu[slice], firmwares[slice].rtu);
|
||||
ret = rproc_boot(prueth->rtu[slice]);
|
||||
ret = prueth_start(prueth->rtu[slice], firmwares[slice].rtu);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to boot RTU%d: %d\n", slice, ret);
|
||||
goto halt_pru;
|
||||
rproc_shutdown(prueth->pru[slice]);
|
||||
goto unwind_slices;
|
||||
}
|
||||
|
||||
ret = rproc_set_firmware(prueth->txpru[slice], firmwares[slice].txpru);
|
||||
ret = rproc_boot(prueth->txpru[slice]);
|
||||
ret = prueth_start(prueth->txpru[slice], firmwares[slice].txpru);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to boot TX_PRU%d: %d\n", slice, ret);
|
||||
goto halt_rtu;
|
||||
rproc_shutdown(prueth->rtu[slice]);
|
||||
rproc_shutdown(prueth->pru[slice]);
|
||||
goto unwind_slices;
|
||||
}
|
||||
}
|
||||
|
||||
emac->fw_running = 1;
|
||||
return 0;
|
||||
|
||||
halt_rtu:
|
||||
rproc_shutdown(prueth->rtu[slice]);
|
||||
|
||||
halt_pru:
|
||||
rproc_shutdown(prueth->pru[slice]);
|
||||
unwind_slices:
|
||||
while (--slice >= 0) {
|
||||
prueth_shutdown(prueth->txpru[slice]);
|
||||
prueth_shutdown(prueth->rtu[slice]);
|
||||
prueth_shutdown(prueth->pru[slice]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void prueth_emac_stop(struct prueth *prueth)
|
||||
{
|
||||
int slice;
|
||||
|
||||
for (slice = 0; slice < PRUETH_NUM_MACS; slice++) {
|
||||
prueth_shutdown(prueth->txpru[slice]);
|
||||
prueth_shutdown(prueth->rtu[slice]);
|
||||
prueth_shutdown(prueth->pru[slice]);
|
||||
}
|
||||
}
|
||||
|
||||
static int prueth_emac_common_start(struct prueth *prueth)
|
||||
{
|
||||
struct prueth_emac *emac;
|
||||
int ret = 0;
|
||||
int slice;
|
||||
|
||||
if (!prueth->emac[ICSS_SLICE0] && !prueth->emac[ICSS_SLICE1])
|
||||
return -EINVAL;
|
||||
|
||||
/* clear SMEM and MSMC settings for all slices */
|
||||
memset_io(prueth->msmcram.va, 0, prueth->msmcram.size);
|
||||
memset_io(prueth->shram.va, 0, ICSSG_CONFIG_OFFSET_SLICE1 * PRUETH_NUM_MACS);
|
||||
|
||||
icssg_class_default(prueth->miig_rt, ICSS_SLICE0, 0, false);
|
||||
icssg_class_default(prueth->miig_rt, ICSS_SLICE1, 0, false);
|
||||
|
||||
if (prueth->is_switch_mode || prueth->is_hsr_offload_mode)
|
||||
icssg_init_fw_offload_mode(prueth);
|
||||
else
|
||||
icssg_init_emac_mode(prueth);
|
||||
|
||||
for (slice = 0; slice < PRUETH_NUM_MACS; slice++) {
|
||||
emac = prueth->emac[slice];
|
||||
if (!emac)
|
||||
continue;
|
||||
ret = icssg_config(prueth, emac, slice);
|
||||
if (ret)
|
||||
goto disable_class;
|
||||
}
|
||||
|
||||
ret = prueth_emac_start(prueth);
|
||||
if (ret)
|
||||
goto disable_class;
|
||||
|
||||
emac = prueth->emac[ICSS_SLICE0] ? prueth->emac[ICSS_SLICE0] :
|
||||
prueth->emac[ICSS_SLICE1];
|
||||
ret = icss_iep_init(emac->iep, &prueth_iep_clockops,
|
||||
emac, IEP_DEFAULT_CYCLE_TIME_NS);
|
||||
if (ret) {
|
||||
dev_err(prueth->dev, "Failed to initialize IEP module\n");
|
||||
goto stop_pruss;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
stop_pruss:
|
||||
prueth_emac_stop(prueth);
|
||||
|
||||
disable_class:
|
||||
icssg_class_disable(prueth->miig_rt, ICSS_SLICE0);
|
||||
icssg_class_disable(prueth->miig_rt, ICSS_SLICE1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int prueth_emac_common_stop(struct prueth *prueth)
|
||||
{
|
||||
struct prueth_emac *emac;
|
||||
|
||||
if (!prueth->emac[ICSS_SLICE0] && !prueth->emac[ICSS_SLICE1])
|
||||
return -EINVAL;
|
||||
|
||||
icssg_class_disable(prueth->miig_rt, ICSS_SLICE0);
|
||||
icssg_class_disable(prueth->miig_rt, ICSS_SLICE1);
|
||||
|
||||
prueth_emac_stop(prueth);
|
||||
|
||||
emac = prueth->emac[ICSS_SLICE0] ? prueth->emac[ICSS_SLICE0] :
|
||||
prueth->emac[ICSS_SLICE1];
|
||||
icss_iep_exit(emac->iep);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* called back by PHY layer if there is change in link state of hw port*/
|
||||
static void emac_adjust_link(struct net_device *ndev)
|
||||
{
|
||||
@ -374,9 +466,6 @@ static void prueth_iep_settime(void *clockops_data, u64 ns)
|
||||
u32 cycletime;
|
||||
int timeout;
|
||||
|
||||
if (!emac->fw_running)
|
||||
return;
|
||||
|
||||
sc_descp = emac->prueth->shram.va + TIMESYNC_FW_WC_SETCLOCK_DESC_OFFSET;
|
||||
|
||||
cycletime = IEP_DEFAULT_CYCLE_TIME_NS;
|
||||
@ -543,23 +632,17 @@ static int emac_ndo_open(struct net_device *ndev)
|
||||
{
|
||||
struct prueth_emac *emac = netdev_priv(ndev);
|
||||
int ret, i, num_data_chn = emac->tx_ch_num;
|
||||
struct icssg_flow_cfg __iomem *flow_cfg;
|
||||
struct prueth *prueth = emac->prueth;
|
||||
int slice = prueth_emac_slice(emac);
|
||||
struct device *dev = prueth->dev;
|
||||
int max_rx_flows;
|
||||
int rx_flow;
|
||||
|
||||
/* clear SMEM and MSMC settings for all slices */
|
||||
if (!prueth->emacs_initialized) {
|
||||
memset_io(prueth->msmcram.va, 0, prueth->msmcram.size);
|
||||
memset_io(prueth->shram.va, 0, ICSSG_CONFIG_OFFSET_SLICE1 * PRUETH_NUM_MACS);
|
||||
}
|
||||
|
||||
/* set h/w MAC as user might have re-configured */
|
||||
ether_addr_copy(emac->mac_addr, ndev->dev_addr);
|
||||
|
||||
icssg_class_set_mac_addr(prueth->miig_rt, slice, emac->mac_addr);
|
||||
icssg_class_default(prueth->miig_rt, slice, 0, false);
|
||||
icssg_ft1_set_mac_addr(prueth->miig_rt, slice, emac->mac_addr);
|
||||
|
||||
/* Notify the stack of the actual queue counts. */
|
||||
@ -597,18 +680,23 @@ static int emac_ndo_open(struct net_device *ndev)
|
||||
goto cleanup_napi;
|
||||
}
|
||||
|
||||
/* reset and start PRU firmware */
|
||||
ret = prueth_emac_start(prueth, emac);
|
||||
if (!prueth->emacs_initialized) {
|
||||
ret = prueth_emac_common_start(prueth);
|
||||
if (ret)
|
||||
goto free_rx_irq;
|
||||
}
|
||||
|
||||
flow_cfg = emac->dram.va + ICSSG_CONFIG_OFFSET + PSI_L_REGULAR_FLOW_ID_BASE_OFFSET;
|
||||
writew(emac->rx_flow_id_base, &flow_cfg->rx_base_flow);
|
||||
ret = emac_fdb_flow_id_updated(emac);
|
||||
|
||||
if (ret) {
|
||||
netdev_err(ndev, "Failed to update Rx Flow ID %d", ret);
|
||||
goto stop;
|
||||
}
|
||||
|
||||
icssg_mii_update_mtu(prueth->mii_rt, slice, ndev->max_mtu);
|
||||
|
||||
if (!prueth->emacs_initialized) {
|
||||
ret = icss_iep_init(emac->iep, &prueth_iep_clockops,
|
||||
emac, IEP_DEFAULT_CYCLE_TIME_NS);
|
||||
}
|
||||
|
||||
ret = request_threaded_irq(emac->tx_ts_irq, NULL, prueth_tx_ts_irq,
|
||||
IRQF_ONESHOT, dev_name(dev), emac);
|
||||
if (ret)
|
||||
@ -653,7 +741,8 @@ reset_rx_chn:
|
||||
free_tx_ts_irq:
|
||||
free_irq(emac->tx_ts_irq, emac);
|
||||
stop:
|
||||
prueth_emac_stop(emac);
|
||||
if (!prueth->emacs_initialized)
|
||||
prueth_emac_common_stop(prueth);
|
||||
free_rx_irq:
|
||||
free_irq(emac->rx_chns.irq[rx_flow], emac);
|
||||
cleanup_napi:
|
||||
@ -689,8 +778,6 @@ static int emac_ndo_stop(struct net_device *ndev)
|
||||
if (ndev->phydev)
|
||||
phy_stop(ndev->phydev);
|
||||
|
||||
icssg_class_disable(prueth->miig_rt, prueth_emac_slice(emac));
|
||||
|
||||
if (emac->prueth->is_hsr_offload_mode)
|
||||
__dev_mc_unsync(ndev, icssg_prueth_hsr_del_mcast);
|
||||
else
|
||||
@ -728,11 +815,9 @@ static int emac_ndo_stop(struct net_device *ndev)
|
||||
/* Destroying the queued work in ndo_stop() */
|
||||
cancel_delayed_work_sync(&emac->stats_work);
|
||||
|
||||
if (prueth->emacs_initialized == 1)
|
||||
icss_iep_exit(emac->iep);
|
||||
|
||||
/* stop PRUs */
|
||||
prueth_emac_stop(emac);
|
||||
if (prueth->emacs_initialized == 1)
|
||||
prueth_emac_common_stop(prueth);
|
||||
|
||||
free_irq(emac->tx_ts_irq, emac);
|
||||
|
||||
@ -1053,10 +1138,11 @@ static void prueth_offload_fwd_mark_update(struct prueth *prueth)
|
||||
}
|
||||
}
|
||||
|
||||
static void prueth_emac_restart(struct prueth *prueth)
|
||||
static int prueth_emac_restart(struct prueth *prueth)
|
||||
{
|
||||
struct prueth_emac *emac0 = prueth->emac[PRUETH_MAC0];
|
||||
struct prueth_emac *emac1 = prueth->emac[PRUETH_MAC1];
|
||||
int ret;
|
||||
|
||||
/* Detach the net_device for both PRUeth ports*/
|
||||
if (netif_running(emac0->ndev))
|
||||
@ -1065,36 +1151,46 @@ static void prueth_emac_restart(struct prueth *prueth)
|
||||
netif_device_detach(emac1->ndev);
|
||||
|
||||
/* Disable both PRUeth ports */
|
||||
icssg_set_port_state(emac0, ICSSG_EMAC_PORT_DISABLE);
|
||||
icssg_set_port_state(emac1, ICSSG_EMAC_PORT_DISABLE);
|
||||
ret = icssg_set_port_state(emac0, ICSSG_EMAC_PORT_DISABLE);
|
||||
ret |= icssg_set_port_state(emac1, ICSSG_EMAC_PORT_DISABLE);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Stop both pru cores for both PRUeth ports*/
|
||||
prueth_emac_stop(emac0);
|
||||
prueth->emacs_initialized--;
|
||||
prueth_emac_stop(emac1);
|
||||
prueth->emacs_initialized--;
|
||||
ret = prueth_emac_common_stop(prueth);
|
||||
if (ret) {
|
||||
dev_err(prueth->dev, "Failed to stop the firmwares");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Start both pru cores for both PRUeth ports */
|
||||
prueth_emac_start(prueth, emac0);
|
||||
prueth->emacs_initialized++;
|
||||
prueth_emac_start(prueth, emac1);
|
||||
prueth->emacs_initialized++;
|
||||
ret = prueth_emac_common_start(prueth);
|
||||
if (ret) {
|
||||
dev_err(prueth->dev, "Failed to start the firmwares");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Enable forwarding for both PRUeth ports */
|
||||
icssg_set_port_state(emac0, ICSSG_EMAC_PORT_FORWARD);
|
||||
icssg_set_port_state(emac1, ICSSG_EMAC_PORT_FORWARD);
|
||||
ret = icssg_set_port_state(emac0, ICSSG_EMAC_PORT_FORWARD);
|
||||
ret |= icssg_set_port_state(emac1, ICSSG_EMAC_PORT_FORWARD);
|
||||
|
||||
/* Attache net_device for both PRUeth ports */
|
||||
netif_device_attach(emac0->ndev);
|
||||
netif_device_attach(emac1->ndev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void icssg_change_mode(struct prueth *prueth)
|
||||
{
|
||||
struct prueth_emac *emac;
|
||||
int mac;
|
||||
int mac, ret;
|
||||
|
||||
prueth_emac_restart(prueth);
|
||||
ret = prueth_emac_restart(prueth);
|
||||
if (ret) {
|
||||
dev_err(prueth->dev, "Failed to restart the firmwares, aborting the process");
|
||||
return;
|
||||
}
|
||||
|
||||
for (mac = PRUETH_MAC0; mac < PRUETH_NUM_MACS; mac++) {
|
||||
emac = prueth->emac[mac];
|
||||
@ -1173,13 +1269,18 @@ static void prueth_netdevice_port_unlink(struct net_device *ndev)
|
||||
{
|
||||
struct prueth_emac *emac = netdev_priv(ndev);
|
||||
struct prueth *prueth = emac->prueth;
|
||||
int ret;
|
||||
|
||||
prueth->br_members &= ~BIT(emac->port_id);
|
||||
|
||||
if (prueth->is_switch_mode) {
|
||||
prueth->is_switch_mode = false;
|
||||
emac->port_vlan = 0;
|
||||
prueth_emac_restart(prueth);
|
||||
ret = prueth_emac_restart(prueth);
|
||||
if (ret) {
|
||||
dev_err(prueth->dev, "Failed to restart the firmwares, aborting the process");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
prueth_offload_fwd_mark_update(prueth);
|
||||
@ -1228,6 +1329,7 @@ static void prueth_hsr_port_unlink(struct net_device *ndev)
|
||||
struct prueth *prueth = emac->prueth;
|
||||
struct prueth_emac *emac0;
|
||||
struct prueth_emac *emac1;
|
||||
int ret;
|
||||
|
||||
emac0 = prueth->emac[PRUETH_MAC0];
|
||||
emac1 = prueth->emac[PRUETH_MAC1];
|
||||
@ -1238,7 +1340,11 @@ static void prueth_hsr_port_unlink(struct net_device *ndev)
|
||||
emac0->port_vlan = 0;
|
||||
emac1->port_vlan = 0;
|
||||
prueth->hsr_dev = NULL;
|
||||
prueth_emac_restart(prueth);
|
||||
ret = prueth_emac_restart(prueth);
|
||||
if (ret) {
|
||||
dev_err(prueth->dev, "Failed to restart the firmwares, aborting the process");
|
||||
return;
|
||||
}
|
||||
netdev_dbg(ndev, "Disabling HSR Offload mode\n");
|
||||
}
|
||||
}
|
||||
@ -1413,13 +1519,10 @@ static int prueth_probe(struct platform_device *pdev)
|
||||
prueth->pa_stats = NULL;
|
||||
}
|
||||
|
||||
if (eth0_node) {
|
||||
if (eth0_node || eth1_node) {
|
||||
ret = prueth_get_cores(prueth, ICSS_SLICE0, false);
|
||||
if (ret)
|
||||
goto put_cores;
|
||||
}
|
||||
|
||||
if (eth1_node) {
|
||||
ret = prueth_get_cores(prueth, ICSS_SLICE1, false);
|
||||
if (ret)
|
||||
goto put_cores;
|
||||
@ -1618,14 +1721,12 @@ put_pruss:
|
||||
pruss_put(prueth->pruss);
|
||||
|
||||
put_cores:
|
||||
if (eth1_node) {
|
||||
prueth_put_cores(prueth, ICSS_SLICE1);
|
||||
of_node_put(eth1_node);
|
||||
}
|
||||
|
||||
if (eth0_node) {
|
||||
if (eth0_node || eth1_node) {
|
||||
prueth_put_cores(prueth, ICSS_SLICE0);
|
||||
of_node_put(eth0_node);
|
||||
|
||||
prueth_put_cores(prueth, ICSS_SLICE1);
|
||||
of_node_put(eth1_node);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -140,7 +140,6 @@ struct prueth_rx_chn {
|
||||
/* data for each emac port */
|
||||
struct prueth_emac {
|
||||
bool is_sr1;
|
||||
bool fw_running;
|
||||
struct prueth *prueth;
|
||||
struct net_device *ndev;
|
||||
u8 mac_addr[6];
|
||||
@ -361,6 +360,8 @@ int icssg_set_port_state(struct prueth_emac *emac,
|
||||
enum icssg_port_state_cmd state);
|
||||
void icssg_config_set_speed(struct prueth_emac *emac);
|
||||
void icssg_config_half_duplex(struct prueth_emac *emac);
|
||||
void icssg_init_emac_mode(struct prueth *prueth);
|
||||
void icssg_init_fw_offload_mode(struct prueth *prueth);
|
||||
|
||||
/* Buffer queue helpers */
|
||||
int icssg_queue_pop(struct prueth *prueth, u8 queue);
|
||||
@ -377,6 +378,7 @@ void icssg_vtbl_modify(struct prueth_emac *emac, u8 vid, u8 port_mask,
|
||||
u8 untag_mask, bool add);
|
||||
u16 icssg_get_pvid(struct prueth_emac *emac);
|
||||
void icssg_set_pvid(struct prueth *prueth, u8 vid, u8 port);
|
||||
int emac_fdb_flow_id_updated(struct prueth_emac *emac);
|
||||
#define prueth_napi_to_tx_chn(pnapi) \
|
||||
container_of(pnapi, struct prueth_tx_chn, napi_tx)
|
||||
|
||||
@ -407,7 +409,6 @@ void emac_rx_timestamp(struct prueth_emac *emac,
|
||||
struct sk_buff *skb, u32 *psdata);
|
||||
enum netdev_tx icssg_ndo_start_xmit(struct sk_buff *skb, struct net_device *ndev);
|
||||
irqreturn_t prueth_rx_irq(int irq, void *dev_id);
|
||||
void prueth_emac_stop(struct prueth_emac *emac);
|
||||
void prueth_cleanup_tx_ts(struct prueth_emac *emac);
|
||||
int icssg_napi_rx_poll(struct napi_struct *napi_rx, int budget);
|
||||
int prueth_prepare_rx_chan(struct prueth_emac *emac,
|
||||
|
@ -440,7 +440,6 @@ static int prueth_emac_start(struct prueth *prueth, struct prueth_emac *emac)
|
||||
goto halt_pru;
|
||||
}
|
||||
|
||||
emac->fw_running = 1;
|
||||
return 0;
|
||||
|
||||
halt_pru:
|
||||
@ -449,6 +448,29 @@ halt_pru:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void prueth_emac_stop(struct prueth_emac *emac)
|
||||
{
|
||||
struct prueth *prueth = emac->prueth;
|
||||
int slice;
|
||||
|
||||
switch (emac->port_id) {
|
||||
case PRUETH_PORT_MII0:
|
||||
slice = ICSS_SLICE0;
|
||||
break;
|
||||
case PRUETH_PORT_MII1:
|
||||
slice = ICSS_SLICE1;
|
||||
break;
|
||||
default:
|
||||
netdev_err(emac->ndev, "invalid port\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!emac->is_sr1)
|
||||
rproc_shutdown(prueth->txpru[slice]);
|
||||
rproc_shutdown(prueth->rtu[slice]);
|
||||
rproc_shutdown(prueth->pru[slice]);
|
||||
}
|
||||
|
||||
/**
|
||||
* emac_ndo_open - EMAC device open
|
||||
* @ndev: network adapter device
|
||||
|
Loading…
x
Reference in New Issue
Block a user