aboutsummaryrefslogtreecommitdiffstats
path: root/net/dsa/dsa.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/dsa/dsa.c')
-rw-r--r--net/dsa/dsa.c41
1 files changed, 34 insertions, 7 deletions
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 76e3800765f8..c59fa5d9c22c 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -634,6 +634,10 @@ static void dsa_of_free_platform_data(struct dsa_platform_data *pd)
634 port_index++; 634 port_index++;
635 } 635 }
636 kfree(pd->chip[i].rtable); 636 kfree(pd->chip[i].rtable);
637
638 /* Drop our reference to the MDIO bus device */
639 if (pd->chip[i].host_dev)
640 put_device(pd->chip[i].host_dev);
637 } 641 }
638 kfree(pd->chip); 642 kfree(pd->chip);
639} 643}
@@ -661,16 +665,22 @@ static int dsa_of_probe(struct device *dev)
661 return -EPROBE_DEFER; 665 return -EPROBE_DEFER;
662 666
663 ethernet = of_parse_phandle(np, "dsa,ethernet", 0); 667 ethernet = of_parse_phandle(np, "dsa,ethernet", 0);
664 if (!ethernet) 668 if (!ethernet) {
665 return -EINVAL; 669 ret = -EINVAL;
670 goto out_put_mdio;
671 }
666 672
667 ethernet_dev = of_find_net_device_by_node(ethernet); 673 ethernet_dev = of_find_net_device_by_node(ethernet);
668 if (!ethernet_dev) 674 if (!ethernet_dev) {
669 return -EPROBE_DEFER; 675 ret = -EPROBE_DEFER;
676 goto out_put_mdio;
677 }
670 678
671 pd = kzalloc(sizeof(*pd), GFP_KERNEL); 679 pd = kzalloc(sizeof(*pd), GFP_KERNEL);
672 if (!pd) 680 if (!pd) {
673 return -ENOMEM; 681 ret = -ENOMEM;
682 goto out_put_ethernet;
683 }
674 684
675 dev->platform_data = pd; 685 dev->platform_data = pd;
676 pd->of_netdev = ethernet_dev; 686 pd->of_netdev = ethernet_dev;
@@ -691,7 +701,9 @@ static int dsa_of_probe(struct device *dev)
691 cd = &pd->chip[chip_index]; 701 cd = &pd->chip[chip_index];
692 702
693 cd->of_node = child; 703 cd->of_node = child;
694 cd->host_dev = &mdio_bus->dev; 704
705 /* When assigning the host device, increment its refcount */
706 cd->host_dev = get_device(&mdio_bus->dev);
695 707
696 sw_addr = of_get_property(child, "reg", NULL); 708 sw_addr = of_get_property(child, "reg", NULL);
697 if (!sw_addr) 709 if (!sw_addr)
@@ -711,6 +723,12 @@ static int dsa_of_probe(struct device *dev)
711 ret = -EPROBE_DEFER; 723 ret = -EPROBE_DEFER;
712 goto out_free_chip; 724 goto out_free_chip;
713 } 725 }
726
727 /* Drop the mdio_bus device ref, replacing the host
728 * device with the mdio_bus_switch device, keeping
729 * the refcount from of_mdio_find_bus() above.
730 */
731 put_device(cd->host_dev);
714 cd->host_dev = &mdio_bus_switch->dev; 732 cd->host_dev = &mdio_bus_switch->dev;
715 } 733 }
716 734
@@ -744,6 +762,10 @@ static int dsa_of_probe(struct device *dev)
744 } 762 }
745 } 763 }
746 764
765 /* The individual chips hold their own refcount on the mdio bus,
766 * so drop ours */
767 put_device(&mdio_bus->dev);
768
747 return 0; 769 return 0;
748 770
749out_free_chip: 771out_free_chip:
@@ -751,6 +773,10 @@ out_free_chip:
751out_free: 773out_free:
752 kfree(pd); 774 kfree(pd);
753 dev->platform_data = NULL; 775 dev->platform_data = NULL;
776out_put_ethernet:
777 put_device(&ethernet_dev->dev);
778out_put_mdio:
779 put_device(&mdio_bus->dev);
754 return ret; 780 return ret;
755} 781}
756 782
@@ -762,6 +788,7 @@ static void dsa_of_remove(struct device *dev)
762 return; 788 return;
763 789
764 dsa_of_free_platform_data(pd); 790 dsa_of_free_platform_data(pd);
791 put_device(&pd->of_netdev->dev);
765 kfree(pd); 792 kfree(pd);
766} 793}
767#else 794#else