mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 12:17:12 +09:00
net: dsa: microchip: Fix KSZ9477 set_ageing_time function
[ Upstream commit 262bfba8ab820641c8cfbbf03b86d6c00242c078 ]
The aging count is not a simple 11-bit value but comprises a 3-bit
multiplier and an 8-bit second count. The code tries to use the
original multiplier which is 4 as the second count is still 300 seconds
by default.
Fixes: 2c119d9982 ("net: dsa: microchip: add the support for set_ageing_time")
Signed-off-by: Tristram Ha <tristram.ha@microchip.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://patch.msgid.link/20241218020224.70590-2-Tristram.Ha@microchip.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
2478960146
commit
f7954e8575
@@ -2,7 +2,7 @@
|
|||||||
/*
|
/*
|
||||||
* Microchip KSZ9477 switch driver main logic
|
* Microchip KSZ9477 switch driver main logic
|
||||||
*
|
*
|
||||||
* Copyright (C) 2017-2019 Microchip Technology Inc.
|
* Copyright (C) 2017-2024 Microchip Technology Inc.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
@@ -964,26 +964,51 @@ void ksz9477_get_caps(struct ksz_device *dev, int port,
|
|||||||
int ksz9477_set_ageing_time(struct ksz_device *dev, unsigned int msecs)
|
int ksz9477_set_ageing_time(struct ksz_device *dev, unsigned int msecs)
|
||||||
{
|
{
|
||||||
u32 secs = msecs / 1000;
|
u32 secs = msecs / 1000;
|
||||||
u8 value;
|
u8 data, mult, value;
|
||||||
u8 data;
|
u32 max_val;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
value = FIELD_GET(SW_AGE_PERIOD_7_0_M, secs);
|
#define MAX_TIMER_VAL ((1 << 8) - 1)
|
||||||
|
|
||||||
ret = ksz_write8(dev, REG_SW_LUE_CTRL_3, value);
|
/* The aging timer comprises a 3-bit multiplier and an 8-bit second
|
||||||
if (ret < 0)
|
* value. Either of them cannot be zero. The maximum timer is then
|
||||||
return ret;
|
* 7 * 255 = 1785 seconds.
|
||||||
|
*/
|
||||||
|
if (!secs)
|
||||||
|
secs = 1;
|
||||||
|
|
||||||
data = FIELD_GET(SW_AGE_PERIOD_10_8_M, secs);
|
/* Return error if too large. */
|
||||||
|
else if (secs > 7 * MAX_TIMER_VAL)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
ret = ksz_read8(dev, REG_SW_LUE_CTRL_0, &value);
|
ret = ksz_read8(dev, REG_SW_LUE_CTRL_0, &value);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
value &= ~SW_AGE_CNT_M;
|
/* Check whether there is need to update the multiplier. */
|
||||||
value |= FIELD_PREP(SW_AGE_CNT_M, data);
|
mult = FIELD_GET(SW_AGE_CNT_M, value);
|
||||||
|
max_val = MAX_TIMER_VAL;
|
||||||
|
if (mult > 0) {
|
||||||
|
/* Try to use the same multiplier already in the register as
|
||||||
|
* the hardware default uses multiplier 4 and 75 seconds for
|
||||||
|
* 300 seconds.
|
||||||
|
*/
|
||||||
|
max_val = DIV_ROUND_UP(secs, mult);
|
||||||
|
if (max_val > MAX_TIMER_VAL || max_val * mult != secs)
|
||||||
|
max_val = MAX_TIMER_VAL;
|
||||||
|
}
|
||||||
|
|
||||||
return ksz_write8(dev, REG_SW_LUE_CTRL_0, value);
|
data = DIV_ROUND_UP(secs, max_val);
|
||||||
|
if (mult != data) {
|
||||||
|
value &= ~SW_AGE_CNT_M;
|
||||||
|
value |= FIELD_PREP(SW_AGE_CNT_M, data);
|
||||||
|
ret = ksz_write8(dev, REG_SW_LUE_CTRL_0, value);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = DIV_ROUND_UP(secs, data);
|
||||||
|
return ksz_write8(dev, REG_SW_LUE_CTRL_3, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port)
|
void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
/*
|
/*
|
||||||
* Microchip KSZ9477 register definitions
|
* Microchip KSZ9477 register definitions
|
||||||
*
|
*
|
||||||
* Copyright (C) 2017-2018 Microchip Technology Inc.
|
* Copyright (C) 2017-2024 Microchip Technology Inc.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __KSZ9477_REGS_H
|
#ifndef __KSZ9477_REGS_H
|
||||||
@@ -190,8 +190,6 @@
|
|||||||
#define SW_VLAN_ENABLE BIT(7)
|
#define SW_VLAN_ENABLE BIT(7)
|
||||||
#define SW_DROP_INVALID_VID BIT(6)
|
#define SW_DROP_INVALID_VID BIT(6)
|
||||||
#define SW_AGE_CNT_M GENMASK(5, 3)
|
#define SW_AGE_CNT_M GENMASK(5, 3)
|
||||||
#define SW_AGE_CNT_S 3
|
|
||||||
#define SW_AGE_PERIOD_10_8_M GENMASK(10, 8)
|
|
||||||
#define SW_RESV_MCAST_ENABLE BIT(2)
|
#define SW_RESV_MCAST_ENABLE BIT(2)
|
||||||
#define SW_HASH_OPTION_M 0x03
|
#define SW_HASH_OPTION_M 0x03
|
||||||
#define SW_HASH_OPTION_CRC 1
|
#define SW_HASH_OPTION_CRC 1
|
||||||
|
|||||||
Reference in New Issue
Block a user