aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFlorian Fainelli <f.fainelli@gmail.com>2018-05-15 19:01:24 -0400
committerDavid S. Miller <davem@davemloft.net>2018-05-16 14:11:22 -0400
commit6c05561c541843b2bec2189f680bed6d20afc25b (patch)
tree894df56cec85e31331ae9d327571f0756f804eb6
parent43a5e00f38fe8933a1c716bfe5b30e97f749d94b (diff)
net: dsa: bcm_sf2: Fix IPv6 rules and chain ID
We had several issues that would make the programming of IPv6 rules both inconsistent and error prone: - the chain ID that we would be asking the hardware to put in the packet's Broadcom tag would be off by one, it would return one of the two indexes, but not the one user-space specified - when an user specified a particular location to insert a CFP rule at, we would not be returning the same index, which would be confusing if nothing else - finally, like IPv4, it would be possible to overflow the last entry by re-programming it Fix this by swapping the usage of rule_index[0] and rule_index[1] where relevant in order to return a consistent and correct user-space experience. Fixes: ba0696c22e7c ("net: dsa: bcm_sf2: Add support for IPv6 CFP rules") Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/dsa/bcm_sf2_cfp.c20
1 files changed, 11 insertions, 9 deletions
diff --git a/drivers/net/dsa/bcm_sf2_cfp.c b/drivers/net/dsa/bcm_sf2_cfp.c
index 9e04786e3139..6fd0f8a12cc2 100644
--- a/drivers/net/dsa/bcm_sf2_cfp.c
+++ b/drivers/net/dsa/bcm_sf2_cfp.c
@@ -565,19 +565,21 @@ static int bcm_sf2_cfp_ipv6_rule_set(struct bcm_sf2_priv *priv, int port,
565 * first half because the HW search is by incrementing addresses. 565 * first half because the HW search is by incrementing addresses.
566 */ 566 */
567 if (fs->location == RX_CLS_LOC_ANY) 567 if (fs->location == RX_CLS_LOC_ANY)
568 rule_index[0] = find_first_zero_bit(priv->cfp.used, 568 rule_index[1] = find_first_zero_bit(priv->cfp.used,
569 bcm_sf2_cfp_rule_size(priv)); 569 priv->num_cfp_rules);
570 else 570 else
571 rule_index[0] = fs->location; 571 rule_index[1] = fs->location;
572 if (rule_index[1] > bcm_sf2_cfp_rule_size(priv))
573 return -ENOSPC;
572 574
573 /* Flag it as used (cleared on error path) such that we can immediately 575 /* Flag it as used (cleared on error path) such that we can immediately
574 * obtain a second one to chain from. 576 * obtain a second one to chain from.
575 */ 577 */
576 set_bit(rule_index[0], priv->cfp.used); 578 set_bit(rule_index[1], priv->cfp.used);
577 579
578 rule_index[1] = find_first_zero_bit(priv->cfp.used, 580 rule_index[0] = find_first_zero_bit(priv->cfp.used,
579 bcm_sf2_cfp_rule_size(priv)); 581 priv->num_cfp_rules);
580 if (rule_index[1] > bcm_sf2_cfp_rule_size(priv)) { 582 if (rule_index[0] > bcm_sf2_cfp_rule_size(priv)) {
581 ret = -ENOSPC; 583 ret = -ENOSPC;
582 goto out_err; 584 goto out_err;
583 } 585 }
@@ -715,14 +717,14 @@ static int bcm_sf2_cfp_ipv6_rule_set(struct bcm_sf2_priv *priv, int port,
715 /* Flag the second half rule as being used now, return it as the 717 /* Flag the second half rule as being used now, return it as the
716 * location, and flag it as unique while dumping rules 718 * location, and flag it as unique while dumping rules
717 */ 719 */
718 set_bit(rule_index[1], priv->cfp.used); 720 set_bit(rule_index[0], priv->cfp.used);
719 set_bit(rule_index[1], priv->cfp.unique); 721 set_bit(rule_index[1], priv->cfp.unique);
720 fs->location = rule_index[1]; 722 fs->location = rule_index[1];
721 723
722 return ret; 724 return ret;
723 725
724out_err: 726out_err:
725 clear_bit(rule_index[0], priv->cfp.used); 727 clear_bit(rule_index[1], priv->cfp.used);
726 return ret; 728 return ret;
727} 729}
728 730