drivers: net: cpsw: ale: add broadcast/multicast rate limit support
The CPSW ALE supports feature to rate limit number ingress broadcast(BC)/multicast(MC) packets per/sec which main purpose is BC/MC storm prevention. The ALE BC/MC packet rate limit configuration consist of two parts: - global ALE_CONTROL.ENABLE_RATE_LIMIT bit 0 which enables rate limiting globally ALE_PRESCALE.PRESCALE specifies rate limiting interval - per-port ALE_PORTCTLx.BCASTMCAST/_LIMIT specifies number of BC/MC packets allowed per rate limiting interval. When port.BCASTMCAST/_LIMIT is 0 rate limiting is disabled for Port. When BC/MC packet rate limiting is enabled the number of allowed packets per/sec is defined as: number_of_packets/sec = (Fclk / ALE_PRESCALE) * port.BCASTMCAST/_LIMIT Hence, the ALE_PRESCALE configuration is common for all ports the 1ms interval is selected and configured during ALE initialization while port.BCAST/MCAST_LIMIT are configured per-port. This allows to achieve: - min number_of_packets = 1000 when port.BCAST/MCAST_LIMIT = 1 - max number_of_packets = 1000 * 255 = 255000 when port.BCAST/MCAST_LIMIT = 0xFF The ALE_CONTROL.ENABLE_RATE_LIMIT can also be enabled once during ALE initialization as rate limiting enabled by non zero port.BCASTMCAST/_LIMIT values. This patch implements above logic in ALE and adds new ALE APIs cpsw_ale_rx_ratelimit_bc(); cpsw_ale_rx_ratelimit_mc(); Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Родитель
1a95e04e29
Коммит
e3a5e33fae
|
@ -50,6 +50,8 @@
|
|||
/* ALE_AGING_TIMER */
|
||||
#define ALE_AGING_TIMER_MASK GENMASK(23, 0)
|
||||
|
||||
#define ALE_RATE_LIMIT_MIN_PPS 1000
|
||||
|
||||
/**
|
||||
* struct ale_entry_fld - The ALE tbl entry field description
|
||||
* @start_bit: field start bit
|
||||
|
@ -1136,6 +1138,50 @@ int cpsw_ale_control_get(struct cpsw_ale *ale, int port, int control)
|
|||
return tmp & BITMASK(info->bits);
|
||||
}
|
||||
|
||||
int cpsw_ale_rx_ratelimit_mc(struct cpsw_ale *ale, int port, unsigned int ratelimit_pps)
|
||||
|
||||
{
|
||||
int val = ratelimit_pps / ALE_RATE_LIMIT_MIN_PPS;
|
||||
u32 remainder = ratelimit_pps % ALE_RATE_LIMIT_MIN_PPS;
|
||||
|
||||
if (ratelimit_pps && !val) {
|
||||
dev_err(ale->params.dev, "ALE MC port:%d ratelimit min value 1000pps\n", port);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (remainder)
|
||||
dev_info(ale->params.dev, "ALE port:%d MC ratelimit set to %dpps (requested %d)\n",
|
||||
port, ratelimit_pps - remainder, ratelimit_pps);
|
||||
|
||||
cpsw_ale_control_set(ale, port, ALE_PORT_MCAST_LIMIT, val);
|
||||
|
||||
dev_dbg(ale->params.dev, "ALE port:%d MC ratelimit set %d\n",
|
||||
port, val * ALE_RATE_LIMIT_MIN_PPS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cpsw_ale_rx_ratelimit_bc(struct cpsw_ale *ale, int port, unsigned int ratelimit_pps)
|
||||
|
||||
{
|
||||
int val = ratelimit_pps / ALE_RATE_LIMIT_MIN_PPS;
|
||||
u32 remainder = ratelimit_pps % ALE_RATE_LIMIT_MIN_PPS;
|
||||
|
||||
if (ratelimit_pps && !val) {
|
||||
dev_err(ale->params.dev, "ALE port:%d BC ratelimit min value 1000pps\n", port);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (remainder)
|
||||
dev_info(ale->params.dev, "ALE port:%d BC ratelimit set to %dpps (requested %d)\n",
|
||||
port, ratelimit_pps - remainder, ratelimit_pps);
|
||||
|
||||
cpsw_ale_control_set(ale, port, ALE_PORT_BCAST_LIMIT, val);
|
||||
|
||||
dev_dbg(ale->params.dev, "ALE port:%d BC ratelimit set %d\n",
|
||||
port, val * ALE_RATE_LIMIT_MIN_PPS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cpsw_ale_timer(struct timer_list *t)
|
||||
{
|
||||
struct cpsw_ale *ale = from_timer(ale, t, timer);
|
||||
|
@ -1199,6 +1245,26 @@ static void cpsw_ale_aging_stop(struct cpsw_ale *ale)
|
|||
|
||||
void cpsw_ale_start(struct cpsw_ale *ale)
|
||||
{
|
||||
unsigned long ale_prescale;
|
||||
|
||||
/* configure Broadcast and Multicast Rate Limit
|
||||
* number_of_packets = (Fclk / ALE_PRESCALE) * port.BCAST/MCAST_LIMIT
|
||||
* ALE_PRESCALE width is 19bit and min value 0x10
|
||||
* port.BCAST/MCAST_LIMIT is 8bit
|
||||
*
|
||||
* For multi port configuration support the ALE_PRESCALE is configured to 1ms interval,
|
||||
* which allows to configure port.BCAST/MCAST_LIMIT per port and achieve:
|
||||
* min number_of_packets = 1000 when port.BCAST/MCAST_LIMIT = 1
|
||||
* max number_of_packets = 1000 * 255 = 255000 when port.BCAST/MCAST_LIMIT = 0xFF
|
||||
*/
|
||||
ale_prescale = ale->params.bus_freq / ALE_RATE_LIMIT_MIN_PPS;
|
||||
writel((u32)ale_prescale, ale->params.ale_regs + ALE_PRESCALE);
|
||||
|
||||
/* Allow MC/BC rate limiting globally.
|
||||
* The actual Rate Limit cfg enabled per-port by port.BCAST/MCAST_LIMIT
|
||||
*/
|
||||
cpsw_ale_control_set(ale, 0, ALE_RATE_LIMIT, 1);
|
||||
|
||||
cpsw_ale_control_set(ale, 0, ALE_ENABLE, 1);
|
||||
cpsw_ale_control_set(ale, 0, ALE_CLEAR, 1);
|
||||
|
||||
|
|
|
@ -120,6 +120,8 @@ int cpsw_ale_add_vlan(struct cpsw_ale *ale, u16 vid, int port, int untag,
|
|||
int reg_mcast, int unreg_mcast);
|
||||
int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port);
|
||||
void cpsw_ale_set_allmulti(struct cpsw_ale *ale, int allmulti, int port);
|
||||
int cpsw_ale_rx_ratelimit_bc(struct cpsw_ale *ale, int port, unsigned int ratelimit_pps);
|
||||
int cpsw_ale_rx_ratelimit_mc(struct cpsw_ale *ale, int port, unsigned int ratelimit_pps);
|
||||
|
||||
int cpsw_ale_control_get(struct cpsw_ale *ale, int port, int control);
|
||||
int cpsw_ale_control_set(struct cpsw_ale *ale, int port,
|
||||
|
|
Загрузка…
Ссылка в новой задаче