@ -101,6 +101,9 @@ struct ar8216_priv {
int mib_next_port ;
int mib_next_port ;
u64 * mib_stats ;
u64 * mib_stats ;
struct list_head list ;
unsigned int use_count ;
/* all fields below are cleared on reset */
/* all fields below are cleared on reset */
bool vlan ;
bool vlan ;
u16 vlan_id [ AR8X16_MAX_VLANS ] ;
u16 vlan_id [ AR8X16_MAX_VLANS ] ;
@ -198,6 +201,9 @@ static const struct ar8xxx_mib_desc ar8236_mibs[] = {
MIB_DESC ( 1 , AR8236_STATS_TXLATECOL , " TxLateCol " ) ,
MIB_DESC ( 1 , AR8236_STATS_TXLATECOL , " TxLateCol " ) ,
} ;
} ;
static DEFINE_MUTEX ( ar8xxx_dev_list_lock ) ;
static LIST_HEAD ( ar8xxx_dev_list ) ;
static inline struct ar8216_priv *
static inline struct ar8216_priv *
swdev_to_ar8216 ( struct switch_dev * swdev )
swdev_to_ar8216 ( struct switch_dev * swdev )
{
{
@ -1848,15 +1854,8 @@ ar8216_config_init(struct phy_device *phydev)
struct switch_dev * swdev ;
struct switch_dev * swdev ;
int ret ;
int ret ;
if ( ! priv ) {
if ( WARN_ON ( ! priv ) )
priv = ar8xxx_create_mii ( phydev - > bus ) ;
return - ENODEV ;
if ( priv = = NULL )
return - ENOMEM ;
ret = ar8xxx_probe_switch ( priv ) ;
if ( ret )
goto err_free_priv ;
}
priv - > phy = phydev ;
priv - > phy = phydev ;
@ -1864,23 +1863,17 @@ ar8216_config_init(struct phy_device *phydev)
if ( chip_is_ar8316 ( priv ) ) {
if ( chip_is_ar8316 ( priv ) ) {
/* check if we're attaching to the switch twice */
/* check if we're attaching to the switch twice */
phydev = phydev - > bus - > phy_map [ 0 ] ;
phydev = phydev - > bus - > phy_map [ 0 ] ;
if ( ! phydev ) {
if ( ! phydev )
ar8xxx_free ( priv ) ;
return 0 ;
return 0 ;
}
/* switch device has not been initialized, reuse priv */
/* switch device has not been initialized, reuse priv */
if ( ! phydev - > priv ) {
if ( ! phydev - > priv ) {
priv - > port4_phy = true ;
priv - > port4_phy = true ;
priv - > dev . ports = ( AR8216_NUM_PORTS - 1 ) ;
priv - > dev . ports = ( AR8216_NUM_PORTS - 1 ) ;
phydev - > priv = priv ;
return 0 ;
return 0 ;
}
}
ar8xxx_free ( priv ) ;
/* switch device has been initialized, reinit */
/* switch device has been initialized, reinit */
priv = phydev - > priv ;
priv - > dev . ports = ( AR8216_NUM_PORTS - 1 ) ;
priv - > dev . ports = ( AR8216_NUM_PORTS - 1 ) ;
priv - > initialized = false ;
priv - > initialized = false ;
priv - > port4_phy = true ;
priv - > port4_phy = true ;
@ -1888,16 +1881,13 @@ ar8216_config_init(struct phy_device *phydev)
return 0 ;
return 0 ;
}
}
ar8xxx_free ( priv ) ;
return 0 ;
return 0 ;
}
}
phydev - > priv = priv ;
swdev = & priv - > dev ;
swdev = & priv - > dev ;
ret = register_switch ( swdev , phydev - > attached_dev ) ;
ret = register_switch ( swdev , phydev - > attached_dev ) ;
if ( ret )
if ( ret )
goto err_free_priv ;
goto err ;
pr_info ( " %s: %s switch driver attached. \n " ,
pr_info ( " %s: %s switch driver attached. \n " ,
phydev - > attached_dev - > name , swdev - > name ) ;
phydev - > attached_dev - > name , swdev - > name ) ;
@ -1928,9 +1918,7 @@ ar8216_config_init(struct phy_device *phydev)
err_unregister_switch :
err_unregister_switch :
unregister_switch ( & priv - > dev ) ;
unregister_switch ( & priv - > dev ) ;
err_free_priv :
err :
ar8xxx_free ( priv ) ;
phydev - > priv = NULL ;
return ret ;
return ret ;
}
}
@ -2036,16 +2024,22 @@ ar8216_probe(struct phy_device *phydev)
if ( ! ar8xxx_is_possible ( phydev - > bus ) )
if ( ! ar8xxx_is_possible ( phydev - > bus ) )
return - ENODEV ;
return - ENODEV ;
priv = ar8xxx_create_mii ( phydev - > bus ) ;
mutex_lock ( & ar8xxx_dev_list_lock ) ;
if ( priv = = NULL )
list_for_each_entry ( priv , & ar8xxx_dev_list , list )
return - ENOMEM ;
if ( priv - > mii_bus = = phydev - > bus )
goto found ;
priv - > phy = phydev ;
priv = ar8xxx_create_mii ( phydev - > bus ) ;
if ( priv = = NULL ) {
ret = - ENOMEM ;
goto unlock ;
}
ret = ar8xxx_probe_switch ( priv ) ;
ret = ar8xxx_probe_switch ( priv ) ;
if ( ret )
if ( ret )
goto out ;
goto free_priv ;
found :
if ( phydev - > addr = = 0 ) {
if ( phydev - > addr = = 0 ) {
if ( ar8xxx_has_gige ( priv ) ) {
if ( ar8xxx_has_gige ( priv ) ) {
phydev - > supported = SUPPORTED_1000baseT_Full ;
phydev - > supported = SUPPORTED_1000baseT_Full ;
@ -2061,10 +2055,19 @@ ar8216_probe(struct phy_device *phydev)
}
}
}
}
ret = 0 ;
phydev - > priv = priv ;
priv - > use_count + + ;
out :
list_add ( & priv - > list , & ar8xxx_dev_list ) ;
mutex_unlock ( & ar8xxx_dev_list_lock ) ;
return 0 ;
free_priv :
ar8xxx_free ( priv ) ;
ar8xxx_free ( priv ) ;
unlock :
mutex_unlock ( & ar8xxx_dev_list_lock ) ;
return ret ;
return ret ;
}
}
@ -2087,14 +2090,18 @@ ar8216_remove(struct phy_device *phydev)
{
{
struct ar8216_priv * priv = phydev - > priv ;
struct ar8216_priv * priv = phydev - > priv ;
if ( ! priv )
if ( WARN_ON ( ! priv ) )
return ;
return ;
phydev - > priv = NULL ;
phydev - > priv = NULL ;
if ( - - priv - > use_count > 0 )
return ;
if ( phydev - > addr = = 0 )
mutex_lock ( & ar8xxx_dev_list_lock ) ;
unregister_switch ( & priv - > dev ) ;
list_del ( & priv - > list ) ;
mutex_unlock ( & ar8xxx_dev_list_lock ) ;
unregister_switch ( & priv - > dev ) ;
ar8xxx_mib_stop ( priv ) ;
ar8xxx_mib_stop ( priv ) ;
ar8xxx_free ( priv ) ;
ar8xxx_free ( priv ) ;
}
}