aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEgil Hjelmeland <privat@egil-hjelmeland.no>2017-12-07 13:56:04 -0500
committerDavid S. Miller <davem@davemloft.net>2017-12-08 14:12:33 -0500
commit2e8d243e887c8802b373338ddff684aa0578be3b (patch)
treea954e778e154c3c6fe325cc51c54e4c5c8cd96c0
parentdf45bf84e4f5a48f23d4b1a07d21d566e8b587b2 (diff)
net: dsa: lan9303: Protect ALR operations with mutex
ALR table operations are a sequence of related register operations which should be protected from concurrent access. The alr_cache should also be protected. Add alr_mutex doing that. Signed-off-by: Egil Hjelmeland <privat@egil-hjelmeland.no> Reviewed-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/dsa/lan9303-core.c14
-rw-r--r--include/linux/dsa/lan9303.h1
2 files changed, 13 insertions, 2 deletions
diff --git a/drivers/net/dsa/lan9303-core.c b/drivers/net/dsa/lan9303-core.c
index ea59dadefb33..c1b004fa64d9 100644
--- a/drivers/net/dsa/lan9303-core.c
+++ b/drivers/net/dsa/lan9303-core.c
@@ -583,6 +583,7 @@ static void lan9303_alr_loop(struct lan9303 *chip, alr_loop_cb_t *cb, void *ctx)
583{ 583{
584 int i; 584 int i;
585 585
586 mutex_lock(&chip->alr_mutex);
586 lan9303_write_switch_reg(chip, LAN9303_SWE_ALR_CMD, 587 lan9303_write_switch_reg(chip, LAN9303_SWE_ALR_CMD,
587 LAN9303_ALR_CMD_GET_FIRST); 588 LAN9303_ALR_CMD_GET_FIRST);
588 lan9303_write_switch_reg(chip, LAN9303_SWE_ALR_CMD, 0); 589 lan9303_write_switch_reg(chip, LAN9303_SWE_ALR_CMD, 0);
@@ -606,6 +607,7 @@ static void lan9303_alr_loop(struct lan9303 *chip, alr_loop_cb_t *cb, void *ctx)
606 LAN9303_ALR_CMD_GET_NEXT); 607 LAN9303_ALR_CMD_GET_NEXT);
607 lan9303_write_switch_reg(chip, LAN9303_SWE_ALR_CMD, 0); 608 lan9303_write_switch_reg(chip, LAN9303_SWE_ALR_CMD, 0);
608 } 609 }
610 mutex_unlock(&chip->alr_mutex);
609} 611}
610 612
611static void alr_reg_to_mac(u32 dat0, u32 dat1, u8 mac[6]) 613static void alr_reg_to_mac(u32 dat0, u32 dat1, u8 mac[6])
@@ -694,16 +696,20 @@ static int lan9303_alr_add_port(struct lan9303 *chip, const u8 *mac, int port,
694{ 696{
695 struct lan9303_alr_cache_entry *entr; 697 struct lan9303_alr_cache_entry *entr;
696 698
699 mutex_lock(&chip->alr_mutex);
697 entr = lan9303_alr_cache_find_mac(chip, mac); 700 entr = lan9303_alr_cache_find_mac(chip, mac);
698 if (!entr) { /*New entry */ 701 if (!entr) { /*New entry */
699 entr = lan9303_alr_cache_find_free(chip); 702 entr = lan9303_alr_cache_find_free(chip);
700 if (!entr) 703 if (!entr) {
704 mutex_unlock(&chip->alr_mutex);
701 return -ENOSPC; 705 return -ENOSPC;
706 }
702 ether_addr_copy(entr->mac_addr, mac); 707 ether_addr_copy(entr->mac_addr, mac);
703 } 708 }
704 entr->port_map |= BIT(port); 709 entr->port_map |= BIT(port);
705 entr->stp_override = stp_override; 710 entr->stp_override = stp_override;
706 lan9303_alr_set_entry(chip, mac, entr->port_map, stp_override); 711 lan9303_alr_set_entry(chip, mac, entr->port_map, stp_override);
712 mutex_unlock(&chip->alr_mutex);
707 713
708 return 0; 714 return 0;
709} 715}
@@ -713,15 +719,18 @@ static int lan9303_alr_del_port(struct lan9303 *chip, const u8 *mac, int port)
713{ 719{
714 struct lan9303_alr_cache_entry *entr; 720 struct lan9303_alr_cache_entry *entr;
715 721
722 mutex_lock(&chip->alr_mutex);
716 entr = lan9303_alr_cache_find_mac(chip, mac); 723 entr = lan9303_alr_cache_find_mac(chip, mac);
717 if (!entr) 724 if (!entr)
718 return 0; /* no static entry found */ 725 goto out; /* no static entry found */
719 726
720 entr->port_map &= ~BIT(port); 727 entr->port_map &= ~BIT(port);
721 if (entr->port_map == 0) /* zero means its free again */ 728 if (entr->port_map == 0) /* zero means its free again */
722 eth_zero_addr(entr->mac_addr); 729 eth_zero_addr(entr->mac_addr);
723 lan9303_alr_set_entry(chip, mac, entr->port_map, entr->stp_override); 730 lan9303_alr_set_entry(chip, mac, entr->port_map, entr->stp_override);
724 731
732out:
733 mutex_unlock(&chip->alr_mutex);
725 return 0; 734 return 0;
726} 735}
727 736
@@ -1323,6 +1332,7 @@ int lan9303_probe(struct lan9303 *chip, struct device_node *np)
1323 int ret; 1332 int ret;
1324 1333
1325 mutex_init(&chip->indirect_mutex); 1334 mutex_init(&chip->indirect_mutex);
1335 mutex_init(&chip->alr_mutex);
1326 1336
1327 lan9303_probe_reset_gpio(chip, np); 1337 lan9303_probe_reset_gpio(chip, np);
1328 1338
diff --git a/include/linux/dsa/lan9303.h b/include/linux/dsa/lan9303.h
index f48a85c377de..b6514c29563f 100644
--- a/include/linux/dsa/lan9303.h
+++ b/include/linux/dsa/lan9303.h
@@ -26,6 +26,7 @@ struct lan9303 {
26 bool phy_addr_sel_strap; 26 bool phy_addr_sel_strap;
27 struct dsa_switch *ds; 27 struct dsa_switch *ds;
28 struct mutex indirect_mutex; /* protect indexed register access */ 28 struct mutex indirect_mutex; /* protect indexed register access */
29 struct mutex alr_mutex; /* protect ALR access */
29 const struct lan9303_phy_ops *ops; 30 const struct lan9303_phy_ops *ops;
30 bool is_bridged; /* true if port 1 and 2 are bridged */ 31 bool is_bridged; /* true if port 1 and 2 are bridged */
31 32