diff options
| author | Vivien Didelot <vivien.didelot@savoirfairelinux.com> | 2017-11-03 19:05:27 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2017-11-05 08:31:39 -0500 |
| commit | 975e6e32215e6cbc09b65d762865b1a46e8e9103 (patch) | |
| tree | 93a36b4df42a92294714cbdf8a70e4b23c427be8 /net/dsa | |
| parent | 0eefe2c1730020c6207bc9695fd466e558301dbb (diff) | |
net: dsa: rework switch parsing
When parsing a switch, we have to identify to which tree it belongs and
parse its ports. Provide two functions to separate the OF and platform
data specific paths.
Also use the of_property_read_variable_u32_array function to parse the
OF member array instead of calling of_property_read_u32_index twice.
Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/dsa')
| -rw-r--r-- | net/dsa/dsa2.c | 117 |
1 files changed, 58 insertions, 59 deletions
diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c index 5918fbddb0ab..dfcb6247f2f2 100644 --- a/net/dsa/dsa2.c +++ b/net/dsa/dsa2.c | |||
| @@ -617,7 +617,8 @@ static int dsa_port_parse_of(struct dsa_port *dp, struct device_node *dn) | |||
| 617 | return 0; | 617 | return 0; |
| 618 | } | 618 | } |
| 619 | 619 | ||
| 620 | static int dsa_parse_ports_of(struct device_node *dn, struct dsa_switch *ds) | 620 | static int dsa_switch_parse_ports_of(struct dsa_switch *ds, |
| 621 | struct device_node *dn) | ||
| 621 | { | 622 | { |
| 622 | struct device_node *ports, *port; | 623 | struct device_node *ports, *port; |
| 623 | struct dsa_port *dp; | 624 | struct dsa_port *dp; |
| @@ -648,6 +649,39 @@ static int dsa_parse_ports_of(struct device_node *dn, struct dsa_switch *ds) | |||
| 648 | return 0; | 649 | return 0; |
| 649 | } | 650 | } |
| 650 | 651 | ||
| 652 | static int dsa_switch_parse_member_of(struct dsa_switch *ds, | ||
| 653 | struct device_node *dn) | ||
| 654 | { | ||
| 655 | u32 m[2] = { 0, 0 }; | ||
| 656 | int sz; | ||
| 657 | |||
| 658 | /* Don't error out if this optional property isn't found */ | ||
| 659 | sz = of_property_read_variable_u32_array(dn, "dsa,member", m, 2, 2); | ||
| 660 | if (sz < 0 && sz != -EINVAL) | ||
| 661 | return sz; | ||
| 662 | |||
| 663 | ds->index = m[1]; | ||
| 664 | if (ds->index >= DSA_MAX_SWITCHES) | ||
| 665 | return -EINVAL; | ||
| 666 | |||
| 667 | ds->dst = dsa_tree_touch(m[0]); | ||
| 668 | if (!ds->dst) | ||
| 669 | return -ENOMEM; | ||
| 670 | |||
| 671 | return 0; | ||
| 672 | } | ||
| 673 | |||
| 674 | static int dsa_switch_parse_of(struct dsa_switch *ds, struct device_node *dn) | ||
| 675 | { | ||
| 676 | int err; | ||
| 677 | |||
| 678 | err = dsa_switch_parse_member_of(ds, dn); | ||
| 679 | if (err) | ||
| 680 | return err; | ||
| 681 | |||
| 682 | return dsa_switch_parse_ports_of(ds, dn); | ||
| 683 | } | ||
| 684 | |||
| 651 | static int dsa_port_parse(struct dsa_port *dp, const char *name, | 685 | static int dsa_port_parse(struct dsa_port *dp, const char *name, |
| 652 | struct device *dev) | 686 | struct device *dev) |
| 653 | { | 687 | { |
| @@ -673,7 +707,8 @@ static int dsa_port_parse(struct dsa_port *dp, const char *name, | |||
| 673 | return 0; | 707 | return 0; |
| 674 | } | 708 | } |
| 675 | 709 | ||
| 676 | static int dsa_parse_ports(struct dsa_chip_data *cd, struct dsa_switch *ds) | 710 | static int dsa_switch_parse_ports(struct dsa_switch *ds, |
| 711 | struct dsa_chip_data *cd) | ||
| 677 | { | 712 | { |
| 678 | bool valid_name_found = false; | 713 | bool valid_name_found = false; |
| 679 | struct dsa_port *dp; | 714 | struct dsa_port *dp; |
| @@ -703,40 +738,19 @@ static int dsa_parse_ports(struct dsa_chip_data *cd, struct dsa_switch *ds) | |||
| 703 | return 0; | 738 | return 0; |
| 704 | } | 739 | } |
| 705 | 740 | ||
| 706 | static int dsa_parse_member_dn(struct device_node *np, u32 *tree, u32 *index) | 741 | static int dsa_switch_parse(struct dsa_switch *ds, struct dsa_chip_data *cd) |
| 707 | { | ||
| 708 | int err; | ||
| 709 | |||
| 710 | *tree = *index = 0; | ||
| 711 | |||
| 712 | err = of_property_read_u32_index(np, "dsa,member", 0, tree); | ||
| 713 | if (err) { | ||
| 714 | /* Does not exist, but it is optional */ | ||
| 715 | if (err == -EINVAL) | ||
| 716 | return 0; | ||
| 717 | return err; | ||
| 718 | } | ||
| 719 | |||
| 720 | err = of_property_read_u32_index(np, "dsa,member", 1, index); | ||
| 721 | if (err) | ||
| 722 | return err; | ||
| 723 | |||
| 724 | if (*index >= DSA_MAX_SWITCHES) | ||
| 725 | return -EINVAL; | ||
| 726 | |||
| 727 | return 0; | ||
| 728 | } | ||
| 729 | |||
| 730 | static int dsa_parse_member(struct dsa_chip_data *pd, u32 *tree, u32 *index) | ||
| 731 | { | 742 | { |
| 732 | if (!pd) | 743 | ds->cd = cd; |
| 733 | return -ENODEV; | ||
| 734 | 744 | ||
| 735 | /* We do not support complex trees with dsa_chip_data */ | 745 | /* We don't support interconnected switches nor multiple trees via |
| 736 | *tree = 0; | 746 | * platform data, so this is the unique switch of the tree. |
| 737 | *index = 0; | 747 | */ |
| 748 | ds->index = 0; | ||
| 749 | ds->dst = dsa_tree_touch(0); | ||
| 750 | if (!ds->dst) | ||
| 751 | return -ENOMEM; | ||
| 738 | 752 | ||
| 739 | return 0; | 753 | return dsa_switch_parse_ports(ds, cd); |
| 740 | } | 754 | } |
| 741 | 755 | ||
| 742 | static int _dsa_register_switch(struct dsa_switch *ds) | 756 | static int _dsa_register_switch(struct dsa_switch *ds) |
| @@ -744,36 +758,21 @@ static int _dsa_register_switch(struct dsa_switch *ds) | |||
| 744 | struct dsa_chip_data *pdata = ds->dev->platform_data; | 758 | struct dsa_chip_data *pdata = ds->dev->platform_data; |
| 745 | struct device_node *np = ds->dev->of_node; | 759 | struct device_node *np = ds->dev->of_node; |
| 746 | struct dsa_switch_tree *dst; | 760 | struct dsa_switch_tree *dst; |
| 747 | u32 tree, index; | 761 | unsigned int index; |
| 748 | int i, err; | 762 | int i, err; |
| 749 | 763 | ||
| 750 | if (np) { | 764 | if (np) |
| 751 | err = dsa_parse_member_dn(np, &tree, &index); | 765 | err = dsa_switch_parse_of(ds, np); |
| 752 | if (err) | 766 | else if (pdata) |
| 753 | return err; | 767 | err = dsa_switch_parse(ds, pdata); |
| 754 | } else { | 768 | else |
| 755 | err = dsa_parse_member(pdata, &tree, &index); | 769 | err = -ENODEV; |
| 756 | if (err) | ||
| 757 | return err; | ||
| 758 | } | ||
| 759 | 770 | ||
| 760 | dst = dsa_tree_touch(tree); | 771 | if (err) |
| 761 | if (!dst) | 772 | return err; |
| 762 | return -ENOMEM; | ||
| 763 | |||
| 764 | ds->dst = dst; | ||
| 765 | ds->index = index; | ||
| 766 | ds->cd = pdata; | ||
| 767 | 773 | ||
| 768 | if (np) { | 774 | index = ds->index; |
| 769 | err = dsa_parse_ports_of(np, ds); | 775 | dst = ds->dst; |
| 770 | if (err) | ||
| 771 | return err; | ||
| 772 | } else { | ||
| 773 | err = dsa_parse_ports(pdata, ds); | ||
| 774 | if (err) | ||
| 775 | return err; | ||
| 776 | } | ||
| 777 | 776 | ||
| 778 | /* Initialize the routing table */ | 777 | /* Initialize the routing table */ |
| 779 | for (i = 0; i < DSA_MAX_SWITCHES; ++i) | 778 | for (i = 0; i < DSA_MAX_SWITCHES; ++i) |
