@@ -321,6 +321,7 @@ static const struct ksz_dev_ops ksz9477_dev_ops = {
321321 .phylink_mac_link_up = ksz9477_phylink_mac_link_up ,
322322 .get_wol = ksz9477_get_wol ,
323323 .set_wol = ksz9477_set_wol ,
324+ .wol_pre_shutdown = ksz9477_wol_pre_shutdown ,
324325 .config_cpu_port = ksz9477_config_cpu_port ,
325326 .tc_cbs_set_cinc = ksz9477_tc_cbs_set_cinc ,
326327 .enable_stp_addr = ksz9477_enable_stp_addr ,
@@ -3569,6 +3570,7 @@ static int ksz_port_set_mac_address(struct dsa_switch *ds, int port,
35693570 const unsigned char * addr )
35703571{
35713572 struct dsa_port * dp = dsa_to_port (ds , port );
3573+ struct ethtool_wolinfo wol ;
35723574
35733575 if (dp -> hsr_dev ) {
35743576 dev_err (ds -> dev ,
@@ -3577,25 +3579,69 @@ static int ksz_port_set_mac_address(struct dsa_switch *ds, int port,
35773579 return - EBUSY ;
35783580 }
35793581
3582+ ksz_get_wol (ds , dp -> index , & wol );
3583+ if (wol .wolopts & WAKE_MAGIC ) {
3584+ dev_err (ds -> dev ,
3585+ "Cannot change MAC address on port %d with active Wake on Magic Packet\n" ,
3586+ port );
3587+ return - EBUSY ;
3588+ }
3589+
35803590 return 0 ;
35813591}
35823592
3583- /* Program the switch's MAC address register with the MAC address of the
3584- * requesting user port. This single address is used by the switch for multiple
3585- * features, like HSR self-address filtering and WoL. Other user ports are
3586- * allowed to share ownership of this address as long as their MAC address is
3587- * the same. The user ports' MAC addresses must not change while they have
3588- * ownership of the switch MAC address.
3593+ /**
3594+ * ksz_is_port_mac_global_usable - Check if the MAC address on a given port
3595+ * can be used as a global address.
3596+ * @ds: Pointer to the DSA switch structure.
3597+ * @port: The port number on which the MAC address is to be checked.
3598+ *
3599+ * This function examines the MAC address set on the specified port and
3600+ * determines if it can be used as a global address for the switch.
3601+ *
3602+ * Return: true if the port's MAC address can be used as a global address, false
3603+ * otherwise.
35893604 */
3590- static int ksz_switch_macaddr_get (struct dsa_switch * ds , int port ,
3591- struct netlink_ext_ack * extack )
3605+ bool ksz_is_port_mac_global_usable (struct dsa_switch * ds , int port )
3606+ {
3607+ struct net_device * user = dsa_to_port (ds , port )-> user ;
3608+ const unsigned char * addr = user -> dev_addr ;
3609+ struct ksz_switch_macaddr * switch_macaddr ;
3610+ struct ksz_device * dev = ds -> priv ;
3611+
3612+ ASSERT_RTNL ();
3613+
3614+ switch_macaddr = dev -> switch_macaddr ;
3615+ if (switch_macaddr && !ether_addr_equal (switch_macaddr -> addr , addr ))
3616+ return false;
3617+
3618+ return true;
3619+ }
3620+
3621+ /**
3622+ * ksz_switch_macaddr_get - Program the switch's MAC address register.
3623+ * @ds: DSA switch instance.
3624+ * @port: Port number.
3625+ * @extack: Netlink extended acknowledgment.
3626+ *
3627+ * This function programs the switch's MAC address register with the MAC address
3628+ * of the requesting user port. This single address is used by the switch for
3629+ * multiple features like HSR self-address filtering and WoL. Other user ports
3630+ * can share ownership of this address as long as their MAC address is the same.
3631+ * The MAC addresses of user ports must not change while they have ownership of
3632+ * the switch MAC address.
3633+ *
3634+ * Return: 0 on success, or other error codes on failure.
3635+ */
3636+ int ksz_switch_macaddr_get (struct dsa_switch * ds , int port ,
3637+ struct netlink_ext_ack * extack )
35923638{
35933639 struct net_device * user = dsa_to_port (ds , port )-> user ;
35943640 const unsigned char * addr = user -> dev_addr ;
35953641 struct ksz_switch_macaddr * switch_macaddr ;
35963642 struct ksz_device * dev = ds -> priv ;
35973643 const u16 * regs = dev -> info -> regs ;
3598- int i ;
3644+ int i , ret ;
35993645
36003646 /* Make sure concurrent MAC address changes are blocked */
36013647 ASSERT_RTNL ();
@@ -3622,13 +3668,23 @@ static int ksz_switch_macaddr_get(struct dsa_switch *ds, int port,
36223668 dev -> switch_macaddr = switch_macaddr ;
36233669
36243670 /* Program the switch MAC address to hardware */
3625- for (i = 0 ; i < ETH_ALEN ; i ++ )
3626- ksz_write8 (dev , regs [REG_SW_MAC_ADDR ] + i , addr [i ]);
3671+ for (i = 0 ; i < ETH_ALEN ; i ++ ) {
3672+ ret = ksz_write8 (dev , regs [REG_SW_MAC_ADDR ] + i , addr [i ]);
3673+ if (ret )
3674+ goto macaddr_drop ;
3675+ }
36273676
36283677 return 0 ;
3678+
3679+ macaddr_drop :
3680+ dev -> switch_macaddr = NULL ;
3681+ refcount_set (& switch_macaddr -> refcount , 0 );
3682+ kfree (switch_macaddr );
3683+
3684+ return ret ;
36293685}
36303686
3631- static void ksz_switch_macaddr_put (struct dsa_switch * ds )
3687+ void ksz_switch_macaddr_put (struct dsa_switch * ds )
36323688{
36333689 struct ksz_switch_macaddr * switch_macaddr ;
36343690 struct ksz_device * dev = ds -> priv ;
@@ -3790,6 +3846,30 @@ struct ksz_device *ksz_switch_alloc(struct device *base, void *priv)
37903846}
37913847EXPORT_SYMBOL (ksz_switch_alloc );
37923848
3849+ /**
3850+ * ksz_switch_shutdown - Shutdown routine for the switch device.
3851+ * @dev: The switch device structure.
3852+ *
3853+ * This function is responsible for initiating a shutdown sequence for the
3854+ * switch device. It invokes the reset operation defined in the device
3855+ * operations, if available, to reset the switch. Subsequently, it calls the
3856+ * DSA framework's shutdown function to ensure a proper shutdown of the DSA
3857+ * switch.
3858+ */
3859+ void ksz_switch_shutdown (struct ksz_device * dev )
3860+ {
3861+ bool wol_enabled = false;
3862+
3863+ if (dev -> dev_ops -> wol_pre_shutdown )
3864+ dev -> dev_ops -> wol_pre_shutdown (dev , & wol_enabled );
3865+
3866+ if (dev -> dev_ops -> reset && !wol_enabled )
3867+ dev -> dev_ops -> reset (dev );
3868+
3869+ dsa_switch_shutdown (dev -> ds );
3870+ }
3871+ EXPORT_SYMBOL (ksz_switch_shutdown );
3872+
37933873static void ksz_parse_rgmii_delay (struct ksz_device * dev , int port_num ,
37943874 struct device_node * port_dn )
37953875{
0 commit comments