@@ -4919,6 +4919,37 @@ static const struct net_device_ops mtk_netdev_ops = {
49194919 .ndo_select_queue = mtk_select_queue ,
49204920};
49214921
4922+ static struct phylink * mtk_mux_create_phylink (struct mtk_mux * mux , unsigned int channel )
4923+ {
4924+ struct mtk_mux_data * data = mux -> data [channel ];
4925+ struct mtk_mac * mac = mux -> mac ;
4926+ struct mtk_eth * eth = mac -> hw ;
4927+ phy_interface_t phy_mode ;
4928+ struct phylink * pl ;
4929+ int err ;
4930+
4931+ if (!data || !data -> of_node )
4932+ return ERR_PTR (- EINVAL );
4933+
4934+ err = of_get_phy_mode (data -> of_node , & phy_mode );
4935+ if (err ) {
4936+ dev_err (eth -> dev , "invalid phy-mode for mux channel %u\n" , channel );
4937+ return ERR_PTR (err );
4938+ }
4939+
4940+ pl = phylink_create (& mac -> phylink_config ,
4941+ of_fwnode_handle (data -> of_node ),
4942+ phy_mode , & mtk_phylink_ops );
4943+ if (IS_ERR (pl )) {
4944+ dev_err (eth -> dev , "failed to create phylink for channel %u\n" , channel );
4945+ return pl ;
4946+ }
4947+
4948+ dev_info (eth -> dev , "Created phylink for channel %u\n" , channel );
4949+ data -> phylink = pl ;
4950+ return pl ;
4951+ }
4952+
49224953static void mux_poll (struct work_struct * work )
49234954{
49244955 struct mtk_mux * mux = container_of (work , struct mtk_mux , poll .work );
@@ -4939,25 +4970,50 @@ static void mux_poll(struct work_struct *work)
49394970 goto reschedule ;
49404971
49414972 dev_info (eth -> dev , "ethernet mux: line:%d new channel:%d,sfp:%d\n" ,__LINE__ , new_channel ,sfp_present );
4942- rtnl_lock ();
49434973
4974+ rtnl_lock ();
49444975 mtk_stop (dev );
49454976
4946- mac -> of_node = mux -> data [new_channel ]-> of_node ;
4947- mac -> phylink = mux -> data [new_channel ]-> phylink ;
4977+ /* Destroy old phylink if it exists */
4978+ if (mux -> data [mux -> channel ] && mux -> data [mux -> channel ]-> phylink ) {
4979+ dev_info (eth -> dev , "Destroying phylink for channel %u\n" , mux -> channel );
4980+ phylink_destroy (mux -> data [mux -> channel ]-> phylink );
4981+ phylink_stop (mux -> data [mux -> channel ]-> phylink );
4982+ phylink_disconnect_phy (mux -> data [mux -> channel ]-> phylink );
4983+ phylink_destroy (mux -> data [mux -> channel ]-> phylink );
4984+ mux -> data [mux -> channel ]-> phylink = NULL ;
4985+ }
4986+ rtnl_unlock ();
49484987
49494988 dev_info (eth -> dev , "ethernet mux: switch to channel%d\n" , new_channel );
49504989
49514990 gpiod_set_value_cansleep (mux -> chan_sel_gpio , new_channel );
49524991
49534992 usleep_range (100000 ,200000 );
49544993
4994+ /* Create new phylink if not yet present */
4995+ if (!mux -> data [new_channel ]-> phylink ) {
4996+ mux -> data [new_channel ]-> phylink = mtk_mux_create_phylink (mux , new_channel );
4997+ if (IS_ERR (mux -> data [new_channel ]-> phylink )) {
4998+ dev_err (eth -> dev , "Failed to create new phylink\n" );
4999+ mux -> data [new_channel ]-> phylink = NULL ;
5000+ goto out_unlock ;
5001+ }
5002+ }
5003+
5004+ mac -> of_node = mux -> data [new_channel ]-> of_node ;
5005+ mac -> phylink = mux -> data [new_channel ]-> phylink ;
5006+
5007+ rtnl_lock ();
49555008 mtk_open (dev );
49565009
49575010 rtnl_unlock ();
49585011
49595012 mux -> channel = new_channel ;
5013+ goto reschedule ;
49605014
5015+ out_unlock :
5016+ rtnl_unlock ();
49615017reschedule :
49625018 mod_delayed_work (system_wq , & mux -> poll , msecs_to_jiffies (100 ));
49635019}
@@ -4995,18 +5051,18 @@ static int mtk_add_mux_channel(struct mtk_mux *mux, struct device_node *np)
49955051 goto err_free_data ;
49965052 }
49975053
4998- phylink = phylink_create (& mux -> mac -> phylink_config ,
5054+ /* phylink = phylink_create(&mux->mac->phylink_config,
49995055 of_fwnode_handle(np),
50005056 phy_mode, &mtk_phylink_ops);
50015057 if (IS_ERR(phylink)) {
50025058 dev_err(eth->dev, "failed to create phylink structure\n");
50035059 err = PTR_ERR(phylink);
50045060 goto err_free_data;
5005- }
5061+ }*/
50065062
50075063 dev_info (eth -> dev , "ethernet mux: line:%d added new channel:%d\n" ,__LINE__ ,id );
50085064 data -> of_node = np ;
5009- data -> phylink = phylink ;
5065+ data -> phylink = NULL ; // phylink;
50105066 mux -> data [id ] = data ;
50115067
50125068 return 0 ;
0 commit comments