diff options
Diffstat (limited to 'drivers/net/dsa/microchip/ksz8795.c')
| -rw-r--r-- | drivers/net/dsa/microchip/ksz8795.c | 75 | 
1 files changed, 63 insertions, 12 deletions
| diff --git a/drivers/net/dsa/microchip/ksz8795.c b/drivers/net/dsa/microchip/ksz8795.c index bd3b133e7085..003b0ac2854c 100644 --- a/drivers/net/dsa/microchip/ksz8795.c +++ b/drivers/net/dsa/microchip/ksz8795.c @@ -76,6 +76,57 @@ int ksz8_reset_switch(struct ksz_device *dev)  	return 0;  } +static int ksz8863_change_mtu(struct ksz_device *dev, int frame_size) +{ +	u8 ctrl2 = 0; + +	if (frame_size <= KSZ8_LEGAL_PACKET_SIZE) +		ctrl2 |= KSZ8863_LEGAL_PACKET_ENABLE; +	else if (frame_size > KSZ8863_NORMAL_PACKET_SIZE) +		ctrl2 |= KSZ8863_HUGE_PACKET_ENABLE; + +	return ksz_rmw8(dev, REG_SW_CTRL_2, KSZ8863_LEGAL_PACKET_ENABLE | +			KSZ8863_HUGE_PACKET_ENABLE, ctrl2); +} + +static int ksz8795_change_mtu(struct ksz_device *dev, int frame_size) +{ +	u8 ctrl1 = 0, ctrl2 = 0; +	int ret; + +	if (frame_size > KSZ8_LEGAL_PACKET_SIZE) +		ctrl2 |= SW_LEGAL_PACKET_DISABLE; +	else if (frame_size > KSZ8863_NORMAL_PACKET_SIZE) +		ctrl1 |= SW_HUGE_PACKET; + +	ret = ksz_rmw8(dev, REG_SW_CTRL_1, SW_HUGE_PACKET, ctrl1); +	if (ret) +		return ret; + +	return ksz_rmw8(dev, REG_SW_CTRL_2, SW_LEGAL_PACKET_DISABLE, ctrl2); +} + +int ksz8_change_mtu(struct ksz_device *dev, int port, int mtu) +{ +	u16 frame_size; + +	if (!dsa_is_cpu_port(dev->ds, port)) +		return 0; + +	frame_size = mtu + VLAN_ETH_HLEN + ETH_FCS_LEN; + +	switch (dev->chip_id) { +	case KSZ8795_CHIP_ID: +	case KSZ8794_CHIP_ID: +	case KSZ8765_CHIP_ID: +		return ksz8795_change_mtu(dev, frame_size); +	case KSZ8830_CHIP_ID: +		return ksz8863_change_mtu(dev, frame_size); +	} + +	return -EOPNOTSUPP; +} +  static void ksz8795_set_prio_queue(struct ksz_device *dev, int port, int queue)  {  	u8 hi, lo; @@ -1233,8 +1284,6 @@ void ksz8_config_cpu_port(struct dsa_switch *ds)  	masks = dev->info->masks;  	regs = dev->info->regs; -	/* Switch marks the maximum frame with extra byte as oversize. */ -	ksz_cfg(dev, REG_SW_CTRL_2, SW_LEGAL_PACKET_DISABLE, true);  	ksz_cfg(dev, regs[S_TAIL_TAG_CTRL], masks[SW_TAIL_TAG_ENABLE], true);  	p = &dev->ports[dev->cpu_port]; @@ -1308,6 +1357,18 @@ int ksz8_setup(struct dsa_switch *ds)  	struct ksz_device *dev = ds->priv;  	int i; +	ds->mtu_enforcement_ingress = true; + +	/* We rely on software untagging on the CPU port, so that we +	 * can support both tagged and untagged VLANs +	 */ +	ds->untag_bridge_pvid = true; + +	/* VLAN filtering is partly controlled by the global VLAN +	 * Enable flag +	 */ +	ds->vlan_filtering_is_global = true; +  	ksz_cfg(dev, S_REPLACE_VID_CTRL, SW_FLOW_CTRL, true);  	/* Enable automatic fast aging when link changed detected. */ @@ -1367,16 +1428,6 @@ int ksz8_switch_init(struct ksz_device *dev)  	dev->phy_port_cnt = dev->info->port_cnt - 1;  	dev->port_mask = (BIT(dev->phy_port_cnt) - 1) | dev->info->cpu_ports; -	/* We rely on software untagging on the CPU port, so that we -	 * can support both tagged and untagged VLANs -	 */ -	dev->ds->untag_bridge_pvid = true; - -	/* VLAN filtering is partly controlled by the global VLAN -	 * Enable flag -	 */ -	dev->ds->vlan_filtering_is_global = true; -  	return 0;  } |