@@ -137,6 +137,22 @@ MODULE_DESCRIPTION("Marvell PHY driver");
137137MODULE_AUTHOR ("Andy Fleming" );
138138MODULE_LICENSE ("GPL" );
139139
140+ struct marvell_hw_stat {
141+ const char * string ;
142+ u8 page ;
143+ u8 reg ;
144+ u8 bits ;
145+ };
146+
147+ static struct marvell_hw_stat marvell_hw_stats [] = {
148+ { "phy_receive_errors" , 0 , 21 , 16 },
149+ { "phy_idle_errors" , 0 , 10 , 8 },
150+ };
151+
152+ struct marvell_priv {
153+ u64 stats [ARRAY_SIZE (marvell_hw_stats )];
154+ };
155+
140156static int marvell_ack_interrupt (struct phy_device * phydev )
141157{
142158 int err ;
@@ -986,19 +1002,90 @@ static int m88e1318_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *w
9861002 return 0 ;
9871003}
9881004
1005+ static int marvell_get_sset_count (struct phy_device * phydev )
1006+ {
1007+ return ARRAY_SIZE (marvell_hw_stats );
1008+ }
1009+
1010+ static void marvell_get_strings (struct phy_device * phydev , u8 * data )
1011+ {
1012+ int i ;
1013+
1014+ for (i = 0 ; i < ARRAY_SIZE (marvell_hw_stats ); i ++ ) {
1015+ memcpy (data + i * ETH_GSTRING_LEN ,
1016+ marvell_hw_stats [i ].string , ETH_GSTRING_LEN );
1017+ }
1018+ }
1019+
1020+ #ifndef UINT64_MAX
1021+ #define UINT64_MAX (u64)(~((u64)0))
1022+ #endif
1023+ static u64 marvell_get_stat (struct phy_device * phydev , int i )
1024+ {
1025+ struct marvell_hw_stat stat = marvell_hw_stats [i ];
1026+ struct marvell_priv * priv = phydev -> priv ;
1027+ int err , oldpage ;
1028+ u64 val ;
1029+
1030+ oldpage = phy_read (phydev , MII_MARVELL_PHY_PAGE );
1031+ err = phy_write (phydev , MII_MARVELL_PHY_PAGE ,
1032+ stat .page );
1033+ if (err < 0 )
1034+ return UINT64_MAX ;
1035+
1036+ val = phy_read (phydev , stat .reg );
1037+ if (val < 0 ) {
1038+ val = UINT64_MAX ;
1039+ } else {
1040+ val = val & ((1 << stat .bits ) - 1 );
1041+ priv -> stats [i ] += val ;
1042+ val = priv -> stats [i ];
1043+ }
1044+
1045+ phy_write (phydev , MII_MARVELL_PHY_PAGE , oldpage );
1046+
1047+ return val ;
1048+ }
1049+
1050+ static void marvell_get_stats (struct phy_device * phydev ,
1051+ struct ethtool_stats * stats , u64 * data )
1052+ {
1053+ int i ;
1054+
1055+ for (i = 0 ; i < ARRAY_SIZE (marvell_hw_stats ); i ++ )
1056+ data [i ] = marvell_get_stat (phydev , i );
1057+ }
1058+
1059+ static int marvell_probe (struct phy_device * phydev )
1060+ {
1061+ struct marvell_priv * priv ;
1062+
1063+ priv = devm_kzalloc (& phydev -> dev , sizeof (* priv ), GFP_KERNEL );
1064+ if (!priv )
1065+ return - ENOMEM ;
1066+
1067+ phydev -> priv = priv ;
1068+
1069+ return 0 ;
1070+ }
1071+
9891072static struct phy_driver marvell_drivers [] = {
9901073 {
9911074 .phy_id = MARVELL_PHY_ID_88E1101 ,
9921075 .phy_id_mask = MARVELL_PHY_ID_MASK ,
9931076 .name = "Marvell 88E1101" ,
9941077 .features = PHY_GBIT_FEATURES ,
1078+ .probe = marvell_probe ,
9951079 .flags = PHY_HAS_INTERRUPT ,
9961080 .config_aneg = & marvell_config_aneg ,
9971081 .read_status = & genphy_read_status ,
9981082 .ack_interrupt = & marvell_ack_interrupt ,
9991083 .config_intr = & marvell_config_intr ,
10001084 .resume = & genphy_resume ,
10011085 .suspend = & genphy_suspend ,
1086+ .get_sset_count = marvell_get_sset_count ,
1087+ .get_strings = marvell_get_strings ,
1088+ .get_stats = marvell_get_stats ,
10021089 .driver = { .owner = THIS_MODULE },
10031090 },
10041091 {
@@ -1007,13 +1094,17 @@ static struct phy_driver marvell_drivers[] = {
10071094 .name = "Marvell 88E1112" ,
10081095 .features = PHY_GBIT_FEATURES ,
10091096 .flags = PHY_HAS_INTERRUPT ,
1097+ .probe = marvell_probe ,
10101098 .config_init = & m88e1111_config_init ,
10111099 .config_aneg = & marvell_config_aneg ,
10121100 .read_status = & genphy_read_status ,
10131101 .ack_interrupt = & marvell_ack_interrupt ,
10141102 .config_intr = & marvell_config_intr ,
10151103 .resume = & genphy_resume ,
10161104 .suspend = & genphy_suspend ,
1105+ .get_sset_count = marvell_get_sset_count ,
1106+ .get_strings = marvell_get_strings ,
1107+ .get_stats = marvell_get_stats ,
10171108 .driver = { .owner = THIS_MODULE },
10181109 },
10191110 {
@@ -1022,13 +1113,17 @@ static struct phy_driver marvell_drivers[] = {
10221113 .name = "Marvell 88E1111" ,
10231114 .features = PHY_GBIT_FEATURES ,
10241115 .flags = PHY_HAS_INTERRUPT ,
1116+ .probe = marvell_probe ,
10251117 .config_init = & m88e1111_config_init ,
10261118 .config_aneg = & marvell_config_aneg ,
10271119 .read_status = & marvell_read_status ,
10281120 .ack_interrupt = & marvell_ack_interrupt ,
10291121 .config_intr = & marvell_config_intr ,
10301122 .resume = & genphy_resume ,
10311123 .suspend = & genphy_suspend ,
1124+ .get_sset_count = marvell_get_sset_count ,
1125+ .get_strings = marvell_get_strings ,
1126+ .get_stats = marvell_get_stats ,
10321127 .driver = { .owner = THIS_MODULE },
10331128 },
10341129 {
@@ -1037,13 +1132,17 @@ static struct phy_driver marvell_drivers[] = {
10371132 .name = "Marvell 88E1118" ,
10381133 .features = PHY_GBIT_FEATURES ,
10391134 .flags = PHY_HAS_INTERRUPT ,
1135+ .probe = marvell_probe ,
10401136 .config_init = & m88e1118_config_init ,
10411137 .config_aneg = & m88e1118_config_aneg ,
10421138 .read_status = & genphy_read_status ,
10431139 .ack_interrupt = & marvell_ack_interrupt ,
10441140 .config_intr = & marvell_config_intr ,
10451141 .resume = & genphy_resume ,
10461142 .suspend = & genphy_suspend ,
1143+ .get_sset_count = marvell_get_sset_count ,
1144+ .get_strings = marvell_get_strings ,
1145+ .get_stats = marvell_get_stats ,
10471146 .driver = {.owner = THIS_MODULE ,},
10481147 },
10491148 {
@@ -1052,13 +1151,17 @@ static struct phy_driver marvell_drivers[] = {
10521151 .name = "Marvell 88E1121R" ,
10531152 .features = PHY_GBIT_FEATURES ,
10541153 .flags = PHY_HAS_INTERRUPT ,
1154+ .probe = marvell_probe ,
10551155 .config_aneg = & m88e1121_config_aneg ,
10561156 .read_status = & marvell_read_status ,
10571157 .ack_interrupt = & marvell_ack_interrupt ,
10581158 .config_intr = & marvell_config_intr ,
10591159 .did_interrupt = & m88e1121_did_interrupt ,
10601160 .resume = & genphy_resume ,
10611161 .suspend = & genphy_suspend ,
1162+ .get_sset_count = marvell_get_sset_count ,
1163+ .get_strings = marvell_get_strings ,
1164+ .get_stats = marvell_get_stats ,
10621165 .driver = { .owner = THIS_MODULE },
10631166 },
10641167 {
@@ -1067,6 +1170,7 @@ static struct phy_driver marvell_drivers[] = {
10671170 .name = "Marvell 88E1318S" ,
10681171 .features = PHY_GBIT_FEATURES ,
10691172 .flags = PHY_HAS_INTERRUPT ,
1173+ .probe = marvell_probe ,
10701174 .config_aneg = & m88e1318_config_aneg ,
10711175 .read_status = & marvell_read_status ,
10721176 .ack_interrupt = & marvell_ack_interrupt ,
@@ -1076,6 +1180,9 @@ static struct phy_driver marvell_drivers[] = {
10761180 .set_wol = & m88e1318_set_wol ,
10771181 .resume = & genphy_resume ,
10781182 .suspend = & genphy_suspend ,
1183+ .get_sset_count = marvell_get_sset_count ,
1184+ .get_strings = marvell_get_strings ,
1185+ .get_stats = marvell_get_stats ,
10791186 .driver = { .owner = THIS_MODULE },
10801187 },
10811188 {
@@ -1084,13 +1191,17 @@ static struct phy_driver marvell_drivers[] = {
10841191 .name = "Marvell 88E1145" ,
10851192 .features = PHY_GBIT_FEATURES ,
10861193 .flags = PHY_HAS_INTERRUPT ,
1194+ .probe = marvell_probe ,
10871195 .config_init = & m88e1145_config_init ,
10881196 .config_aneg = & marvell_config_aneg ,
10891197 .read_status = & genphy_read_status ,
10901198 .ack_interrupt = & marvell_ack_interrupt ,
10911199 .config_intr = & marvell_config_intr ,
10921200 .resume = & genphy_resume ,
10931201 .suspend = & genphy_suspend ,
1202+ .get_sset_count = marvell_get_sset_count ,
1203+ .get_strings = marvell_get_strings ,
1204+ .get_stats = marvell_get_stats ,
10941205 .driver = { .owner = THIS_MODULE },
10951206 },
10961207 {
@@ -1099,13 +1210,17 @@ static struct phy_driver marvell_drivers[] = {
10991210 .name = "Marvell 88E1149R" ,
11001211 .features = PHY_GBIT_FEATURES ,
11011212 .flags = PHY_HAS_INTERRUPT ,
1213+ .probe = marvell_probe ,
11021214 .config_init = & m88e1149_config_init ,
11031215 .config_aneg = & m88e1118_config_aneg ,
11041216 .read_status = & genphy_read_status ,
11051217 .ack_interrupt = & marvell_ack_interrupt ,
11061218 .config_intr = & marvell_config_intr ,
11071219 .resume = & genphy_resume ,
11081220 .suspend = & genphy_suspend ,
1221+ .get_sset_count = marvell_get_sset_count ,
1222+ .get_strings = marvell_get_strings ,
1223+ .get_stats = marvell_get_stats ,
11091224 .driver = { .owner = THIS_MODULE },
11101225 },
11111226 {
@@ -1114,13 +1229,17 @@ static struct phy_driver marvell_drivers[] = {
11141229 .name = "Marvell 88E1240" ,
11151230 .features = PHY_GBIT_FEATURES ,
11161231 .flags = PHY_HAS_INTERRUPT ,
1232+ .probe = marvell_probe ,
11171233 .config_init = & m88e1111_config_init ,
11181234 .config_aneg = & marvell_config_aneg ,
11191235 .read_status = & genphy_read_status ,
11201236 .ack_interrupt = & marvell_ack_interrupt ,
11211237 .config_intr = & marvell_config_intr ,
11221238 .resume = & genphy_resume ,
11231239 .suspend = & genphy_suspend ,
1240+ .get_sset_count = marvell_get_sset_count ,
1241+ .get_strings = marvell_get_strings ,
1242+ .get_stats = marvell_get_stats ,
11241243 .driver = { .owner = THIS_MODULE },
11251244 },
11261245 {
@@ -1129,13 +1248,17 @@ static struct phy_driver marvell_drivers[] = {
11291248 .name = "Marvell 88E1116R" ,
11301249 .features = PHY_GBIT_FEATURES ,
11311250 .flags = PHY_HAS_INTERRUPT ,
1251+ .probe = marvell_probe ,
11321252 .config_init = & m88e1116r_config_init ,
11331253 .config_aneg = & genphy_config_aneg ,
11341254 .read_status = & genphy_read_status ,
11351255 .ack_interrupt = & marvell_ack_interrupt ,
11361256 .config_intr = & marvell_config_intr ,
11371257 .resume = & genphy_resume ,
11381258 .suspend = & genphy_suspend ,
1259+ .get_sset_count = marvell_get_sset_count ,
1260+ .get_strings = marvell_get_strings ,
1261+ .get_stats = marvell_get_stats ,
11391262 .driver = { .owner = THIS_MODULE },
11401263 },
11411264 {
@@ -1144,13 +1267,17 @@ static struct phy_driver marvell_drivers[] = {
11441267 .name = "Marvell 88E1510" ,
11451268 .features = PHY_GBIT_FEATURES ,
11461269 .flags = PHY_HAS_INTERRUPT ,
1270+ .probe = marvell_probe ,
11471271 .config_aneg = & m88e1510_config_aneg ,
11481272 .read_status = & marvell_read_status ,
11491273 .ack_interrupt = & marvell_ack_interrupt ,
11501274 .config_intr = & marvell_config_intr ,
11511275 .did_interrupt = & m88e1121_did_interrupt ,
11521276 .resume = & genphy_resume ,
11531277 .suspend = & genphy_suspend ,
1278+ .get_sset_count = marvell_get_sset_count ,
1279+ .get_strings = marvell_get_strings ,
1280+ .get_stats = marvell_get_stats ,
11541281 .driver = { .owner = THIS_MODULE },
11551282 },
11561283 {
@@ -1159,13 +1286,17 @@ static struct phy_driver marvell_drivers[] = {
11591286 .name = "Marvell 88E1540" ,
11601287 .features = PHY_GBIT_FEATURES ,
11611288 .flags = PHY_HAS_INTERRUPT ,
1289+ .probe = marvell_probe ,
11621290 .config_aneg = & m88e1510_config_aneg ,
11631291 .read_status = & marvell_read_status ,
11641292 .ack_interrupt = & marvell_ack_interrupt ,
11651293 .config_intr = & marvell_config_intr ,
11661294 .did_interrupt = & m88e1121_did_interrupt ,
11671295 .resume = & genphy_resume ,
11681296 .suspend = & genphy_suspend ,
1297+ .get_sset_count = marvell_get_sset_count ,
1298+ .get_strings = marvell_get_strings ,
1299+ .get_stats = marvell_get_stats ,
11691300 .driver = { .owner = THIS_MODULE },
11701301 },
11711302 {
@@ -1174,6 +1305,7 @@ static struct phy_driver marvell_drivers[] = {
11741305 .name = "Marvell 88E3016" ,
11751306 .features = PHY_BASIC_FEATURES ,
11761307 .flags = PHY_HAS_INTERRUPT ,
1308+ .probe = marvell_probe ,
11771309 .config_aneg = & genphy_config_aneg ,
11781310 .config_init = & m88e3016_config_init ,
11791311 .aneg_done = & marvell_aneg_done ,
@@ -1183,6 +1315,9 @@ static struct phy_driver marvell_drivers[] = {
11831315 .did_interrupt = & m88e1121_did_interrupt ,
11841316 .resume = & genphy_resume ,
11851317 .suspend = & genphy_suspend ,
1318+ .get_sset_count = marvell_get_sset_count ,
1319+ .get_strings = marvell_get_strings ,
1320+ .get_stats = marvell_get_stats ,
11861321 .driver = { .owner = THIS_MODULE },
11871322 },
11881323};
0 commit comments