Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: asix: ax88772: migrate to phylink

There are some exotic ax88772 based devices which may require
functionality provide by the phylink framework. For example:
- US100A20SFP, USB 2.0 auf LWL Converter with SFP Cage
- AX88772B USB to 100Base-TX Ethernet (with RMII) demo board, where it
is possible to switch between internal PHY and external RMII based
connection.

So, convert this driver to phylink as soon as possible.

Tested with:
- AX88772A + internal PHY
- AX88772B + external DP83TD510E T1L PHY

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Oleksij Rempel and committed by
David S. Miller
e0bffe3e 057062ad

+116 -11
+1 -1
drivers/net/usb/Kconfig
··· 168 168 tristate "ASIX AX88xxx Based USB 2.0 Ethernet Adapters" 169 169 depends on USB_USBNET 170 170 select CRC32 171 - select PHYLIB 171 + select PHYLINK 172 172 select AX88796B_PHY 173 173 imply NET_SELFTESTS 174 174 default y
+3
drivers/net/usb/asix.h
··· 27 27 #include <linux/if_vlan.h> 28 28 #include <linux/phy.h> 29 29 #include <net/selftests.h> 30 + #include <linux/phylink.h> 30 31 31 32 #define DRIVER_VERSION "22-Dec-2011" 32 33 #define DRIVER_NAME "asix" ··· 186 185 struct mii_bus *mdio; 187 186 struct phy_device *phydev; 188 187 struct phy_device *phydev_int; 188 + struct phylink *phylink; 189 + struct phylink_config phylink_config; 189 190 u16 phy_addr; 190 191 bool embd_phy; 191 192 u8 chipcode;
+112 -10
drivers/net/usb/asix_devices.c
··· 343 343 if (ret < 0) 344 344 goto out; 345 345 346 - phy_start(priv->phydev); 346 + phylink_start(priv->phylink); 347 347 348 348 return 0; 349 349 ··· 590 590 struct asix_common_private *priv = dev->driver_priv; 591 591 u16 medium; 592 592 593 - if (netif_running(dev->net)) 594 - phy_stop(priv->phydev); 593 + if (netif_running(dev->net)) { 594 + rtnl_lock(); 595 + phylink_suspend(priv->phylink, false); 596 + rtnl_unlock(); 597 + } 595 598 596 599 /* Stop MAC operation */ 597 600 medium = asix_read_medium_status(dev, 1); ··· 625 622 if (!priv->reset(dev, 1)) 626 623 break; 627 624 628 - if (netif_running(dev->net)) 629 - phy_start(priv->phydev); 625 + if (netif_running(dev->net)) { 626 + rtnl_lock(); 627 + phylink_resume(priv->phylink); 628 + rtnl_unlock(); 629 + } 630 630 } 631 631 632 632 static int asix_resume(struct usb_interface *intf) ··· 673 667 return -ENODEV; 674 668 } 675 669 676 - ret = phy_connect_direct(dev->net, priv->phydev, &asix_adjust_link, 677 - PHY_INTERFACE_MODE_INTERNAL); 670 + ret = phylink_connect_phy(priv->phylink, priv->phydev); 678 671 if (ret) { 679 672 netdev_err(dev->net, "Could not connect PHY\n"); 680 673 return ret; ··· 693 688 */ 694 689 priv->phydev_int = mdiobus_get_phy(priv->mdio, AX_EMBD_PHY_ADDR); 695 690 if (!priv->phydev_int) { 691 + rtnl_lock(); 692 + phylink_disconnect_phy(priv->phylink); 693 + rtnl_unlock(); 696 694 netdev_err(dev->net, "Could not find internal PHY\n"); 697 695 return -ENODEV; 698 696 } ··· 703 695 priv->phydev_int->mac_managed_pm = 1; 704 696 phy_suspend(priv->phydev_int); 705 697 698 + return 0; 699 + } 700 + 701 + static void ax88772_mac_config(struct phylink_config *config, unsigned int mode, 702 + const struct phylink_link_state *state) 703 + { 704 + /* Nothing to do */ 705 + } 706 + 707 + static void ax88772_mac_link_down(struct phylink_config *config, 708 + unsigned int mode, phy_interface_t interface) 709 + { 710 + struct usbnet *dev = netdev_priv(to_net_dev(config->dev)); 711 + 712 + asix_write_medium_mode(dev, 0, 0); 713 + usbnet_link_change(dev, false, false); 714 + } 715 + 716 + static void ax88772_mac_link_up(struct phylink_config *config, 717 + struct phy_device *phy, 718 + unsigned int mode, phy_interface_t interface, 719 + int speed, int duplex, 720 + bool tx_pause, bool rx_pause) 721 + { 722 + struct usbnet *dev = netdev_priv(to_net_dev(config->dev)); 723 + u16 m = AX_MEDIUM_AC | AX_MEDIUM_RE; 724 + 725 + m |= duplex ? AX_MEDIUM_FD : 0; 726 + 727 + switch (speed) { 728 + case SPEED_100: 729 + m |= AX_MEDIUM_PS; 730 + break; 731 + case SPEED_10: 732 + break; 733 + default: 734 + return; 735 + } 736 + 737 + if (tx_pause) 738 + m |= AX_MEDIUM_TFC; 739 + 740 + if (rx_pause) 741 + m |= AX_MEDIUM_RFC; 742 + 743 + asix_write_medium_mode(dev, m, 0); 744 + usbnet_link_change(dev, true, false); 745 + } 746 + 747 + static const struct phylink_mac_ops ax88772_phylink_mac_ops = { 748 + .validate = phylink_generic_validate, 749 + .mac_config = ax88772_mac_config, 750 + .mac_link_down = ax88772_mac_link_down, 751 + .mac_link_up = ax88772_mac_link_up, 752 + }; 753 + 754 + static int ax88772_phylink_setup(struct usbnet *dev) 755 + { 756 + struct asix_common_private *priv = dev->driver_priv; 757 + phy_interface_t phy_if_mode; 758 + struct phylink *phylink; 759 + 760 + priv->phylink_config.dev = &dev->net->dev; 761 + priv->phylink_config.type = PHYLINK_NETDEV; 762 + priv->phylink_config.mac_capabilities = MAC_SYM_PAUSE | MAC_ASYM_PAUSE | 763 + MAC_10 | MAC_100; 764 + 765 + __set_bit(PHY_INTERFACE_MODE_INTERNAL, 766 + priv->phylink_config.supported_interfaces); 767 + __set_bit(PHY_INTERFACE_MODE_RMII, 768 + priv->phylink_config.supported_interfaces); 769 + 770 + if (priv->embd_phy) 771 + phy_if_mode = PHY_INTERFACE_MODE_INTERNAL; 772 + else 773 + phy_if_mode = PHY_INTERFACE_MODE_RMII; 774 + 775 + phylink = phylink_create(&priv->phylink_config, dev->net->dev.fwnode, 776 + phy_if_mode, &ax88772_phylink_mac_ops); 777 + if (IS_ERR(phylink)) 778 + return PTR_ERR(phylink); 779 + 780 + priv->phylink = phylink; 706 781 return 0; 707 782 } 708 783 ··· 879 788 if (ret) 880 789 return ret; 881 790 882 - return ax88772_init_phy(dev); 791 + ret = ax88772_phylink_setup(dev); 792 + if (ret) 793 + return ret; 794 + 795 + ret = ax88772_init_phy(dev); 796 + if (ret) 797 + phylink_destroy(priv->phylink); 798 + 799 + return ret; 883 800 } 884 801 885 802 static int ax88772_stop(struct usbnet *dev) 886 803 { 887 804 struct asix_common_private *priv = dev->driver_priv; 888 805 889 - phy_stop(priv->phydev); 806 + phylink_stop(priv->phylink); 890 807 891 808 return 0; 892 809 } ··· 903 804 { 904 805 struct asix_common_private *priv = dev->driver_priv; 905 806 906 - phy_disconnect(priv->phydev); 807 + rtnl_lock(); 808 + phylink_disconnect_phy(priv->phylink); 809 + rtnl_unlock(); 810 + phylink_destroy(priv->phylink); 907 811 asix_rx_fixup_common_free(dev->driver_priv); 908 812 } 909 813