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

net: phy: nxp-c45-tja11xx: add MACsec statistics

Add MACsec statistics callbacks.
The statistic registers must be set to 0 if the SC/SA is
deleted to read relevant values next time when the SC/SA is used.

Signed-off-by: Radu Pirea (NXP OSS) <radu-nicolae.pirea@oss.nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Radu Pirea (NXP OSS) and committed by
David S. Miller
31a99fc0 a868b486

+345
+345
drivers/net/phy/nxp-c45-tja11xx-macsec.c
··· 137 137 #define ADAPTER_EN BIT(6) 138 138 #define MACSEC_EN BIT(5) 139 139 140 + #define MACSEC_INOV1HS 0x0140 141 + #define MACSEC_INOV2HS 0x0144 142 + #define MACSEC_INOD1HS 0x0148 143 + #define MACSEC_INOD2HS 0x014C 144 + #define MACSEC_RXSCIPUS 0x0150 145 + #define MACSEC_RXSCIPDS 0x0154 146 + #define MACSEC_RXSCIPLS 0x0158 147 + #define MACSEC_RXAN0INUSS 0x0160 148 + #define MACSEC_RXAN0IPUSS 0x0170 149 + #define MACSEC_RXSA_A_IPOS 0x0194 150 + #define MACSEC_RXSA_A_IPIS 0x01B0 151 + #define MACSEC_RXSA_A_IPNVS 0x01B4 152 + #define MACSEC_RXSA_B_IPOS 0x01D4 153 + #define MACSEC_RXSA_B_IPIS 0x01F0 154 + #define MACSEC_RXSA_B_IPNVS 0x01F4 155 + #define MACSEC_OPUS 0x021C 156 + #define MACSEC_OPTLS 0x022C 157 + #define MACSEC_OOP1HS 0x0240 158 + #define MACSEC_OOP2HS 0x0244 159 + #define MACSEC_OOE1HS 0x0248 160 + #define MACSEC_OOE2HS 0x024C 161 + #define MACSEC_TXSA_A_OPPS 0x028C 162 + #define MACSEC_TXSA_A_OPES 0x0290 163 + #define MACSEC_TXSA_B_OPPS 0x02CC 164 + #define MACSEC_TXSA_B_OPES 0x02D0 165 + #define MACSEC_INPWTS 0x0630 166 + #define MACSEC_INPBTS 0x0638 167 + #define MACSEC_IPSNFS 0x063C 168 + 140 169 enum nxp_c45_sa_type { 141 170 TX_SA, 142 171 RX_SA, ··· 204 175 u16 ka; 205 176 u16 ssci; 206 177 u16 salt; 178 + u16 ipis; 179 + u16 ipnvs; 180 + u16 ipos; 181 + u16 opps; 182 + u16 opes; 207 183 }; 208 184 209 185 static const struct nxp_c45_sa_regs rx_sa_a_regs = { ··· 220 186 .ka = MACSEC_RXSA_A_KA, 221 187 .ssci = MACSEC_RXSA_A_SSCI, 222 188 .salt = MACSEC_RXSA_A_SALT, 189 + .ipis = MACSEC_RXSA_A_IPIS, 190 + .ipnvs = MACSEC_RXSA_A_IPNVS, 191 + .ipos = MACSEC_RXSA_A_IPOS, 223 192 }; 224 193 225 194 static const struct nxp_c45_sa_regs rx_sa_b_regs = { ··· 234 197 .ka = MACSEC_RXSA_B_KA, 235 198 .ssci = MACSEC_RXSA_B_SSCI, 236 199 .salt = MACSEC_RXSA_B_SALT, 200 + .ipis = MACSEC_RXSA_B_IPIS, 201 + .ipnvs = MACSEC_RXSA_B_IPNVS, 202 + .ipos = MACSEC_RXSA_B_IPOS, 237 203 }; 238 204 239 205 static const struct nxp_c45_sa_regs tx_sa_a_regs = { ··· 246 206 .ka = MACSEC_TXSA_A_KA, 247 207 .ssci = MACSEC_TXSA_A_SSCI, 248 208 .salt = MACSEC_TXSA_A_SALT, 209 + .opps = MACSEC_TXSA_A_OPPS, 210 + .opes = MACSEC_TXSA_A_OPES, 249 211 }; 250 212 251 213 static const struct nxp_c45_sa_regs tx_sa_b_regs = { ··· 257 215 .ka = MACSEC_TXSA_B_KA, 258 216 .ssci = MACSEC_TXSA_B_SSCI, 259 217 .salt = MACSEC_TXSA_B_SALT, 218 + .opps = MACSEC_TXSA_B_OPPS, 219 + .opes = MACSEC_TXSA_B_OPES, 260 220 }; 261 221 262 222 static const ··· 326 282 phydev_dbg(phydev, "read addr 0x%x value 0x%x\n", addr, *value); 327 283 328 284 return 0; 285 + } 286 + 287 + static void nxp_c45_macsec_read32_64(struct phy_device *phydev, u16 addr, 288 + u64 *value) 289 + { 290 + u32 lvalue; 291 + 292 + nxp_c45_macsec_read(phydev, addr, &lvalue); 293 + *value = lvalue; 294 + } 295 + 296 + static void nxp_c45_macsec_read64(struct phy_device *phydev, u16 addr, 297 + u64 *value) 298 + { 299 + u32 lvalue; 300 + 301 + nxp_c45_macsec_read(phydev, addr, &lvalue); 302 + *value = (u64)lvalue << 32; 303 + nxp_c45_macsec_read(phydev, addr + 4, &lvalue); 304 + *value |= lvalue; 329 305 } 330 306 331 307 static void nxp_c45_secy_irq_en(struct phy_device *phydev, ··· 507 443 } 508 444 509 445 nxp_c45_macsec_write(phydev, sa_regs->cs, MACSEC_SA_CS_A); 446 + } 447 + 448 + static void nxp_c45_rx_sa_clear_stats(struct phy_device *phydev, 449 + struct nxp_c45_sa *sa) 450 + { 451 + nxp_c45_macsec_write(phydev, sa->regs->ipis, 0); 452 + nxp_c45_macsec_write(phydev, sa->regs->ipnvs, 0); 453 + nxp_c45_macsec_write(phydev, sa->regs->ipos, 0); 454 + 455 + nxp_c45_macsec_write(phydev, MACSEC_RXAN0INUSS + sa->an * 4, 0); 456 + nxp_c45_macsec_write(phydev, MACSEC_RXAN0IPUSS + sa->an * 4, 0); 457 + } 458 + 459 + static void nxp_c45_rx_sa_read_stats(struct phy_device *phydev, 460 + struct nxp_c45_sa *sa, 461 + struct macsec_rx_sa_stats *stats) 462 + { 463 + nxp_c45_macsec_read(phydev, sa->regs->ipis, &stats->InPktsInvalid); 464 + nxp_c45_macsec_read(phydev, sa->regs->ipnvs, &stats->InPktsNotValid); 465 + nxp_c45_macsec_read(phydev, sa->regs->ipos, &stats->InPktsOK); 466 + } 467 + 468 + static void nxp_c45_tx_sa_clear_stats(struct phy_device *phydev, 469 + struct nxp_c45_sa *sa) 470 + { 471 + nxp_c45_macsec_write(phydev, sa->regs->opps, 0); 472 + nxp_c45_macsec_write(phydev, sa->regs->opes, 0); 473 + } 474 + 475 + static void nxp_c45_tx_sa_read_stats(struct phy_device *phydev, 476 + struct nxp_c45_sa *sa, 477 + struct macsec_tx_sa_stats *stats) 478 + { 479 + nxp_c45_macsec_read(phydev, sa->regs->opps, &stats->OutPktsProtected); 480 + nxp_c45_macsec_read(phydev, sa->regs->opes, &stats->OutPktsEncrypted); 510 481 } 511 482 512 483 static void nxp_c45_rx_sa_update(struct phy_device *phydev, ··· 748 649 nxp_c45_macsec_write(phydev, MACSEC_TXSC_CFG, cfg); 749 650 } 750 651 652 + static void nxp_c45_tx_sc_clear_stats(struct phy_device *phydev, 653 + struct nxp_c45_secy *phy_secy) 654 + { 655 + struct nxp_c45_sa *pos, *tmp; 656 + 657 + list_for_each_entry_safe(pos, tmp, &phy_secy->sa_list, list) 658 + if (pos->type == TX_SA) 659 + nxp_c45_tx_sa_clear_stats(phydev, pos); 660 + 661 + nxp_c45_macsec_write(phydev, MACSEC_OPUS, 0); 662 + nxp_c45_macsec_write(phydev, MACSEC_OPTLS, 0); 663 + nxp_c45_macsec_write(phydev, MACSEC_OOP1HS, 0); 664 + nxp_c45_macsec_write(phydev, MACSEC_OOP2HS, 0); 665 + nxp_c45_macsec_write(phydev, MACSEC_OOE1HS, 0); 666 + nxp_c45_macsec_write(phydev, MACSEC_OOE2HS, 0); 667 + } 668 + 751 669 static void nxp_c45_set_rx_sc0_impl(struct phy_device *phydev, 752 670 bool enable) 753 671 { ··· 849 733 nxp_c45_macsec_write(phydev, MACSEC_RXSC_CFG, cfg); 850 734 } 851 735 736 + static void nxp_c45_rx_sc_clear_stats(struct phy_device *phydev, 737 + struct nxp_c45_secy *phy_secy) 738 + { 739 + struct nxp_c45_sa *pos, *tmp; 740 + int i; 741 + 742 + list_for_each_entry_safe(pos, tmp, &phy_secy->sa_list, list) 743 + if (pos->type == RX_SA) 744 + nxp_c45_rx_sa_clear_stats(phydev, pos); 745 + 746 + nxp_c45_macsec_write(phydev, MACSEC_INOD1HS, 0); 747 + nxp_c45_macsec_write(phydev, MACSEC_INOD2HS, 0); 748 + 749 + nxp_c45_macsec_write(phydev, MACSEC_INOV1HS, 0); 750 + nxp_c45_macsec_write(phydev, MACSEC_INOV2HS, 0); 751 + 752 + nxp_c45_macsec_write(phydev, MACSEC_RXSCIPDS, 0); 753 + nxp_c45_macsec_write(phydev, MACSEC_RXSCIPLS, 0); 754 + nxp_c45_macsec_write(phydev, MACSEC_RXSCIPUS, 0); 755 + 756 + for (i = 0; i < MACSEC_NUM_AN; i++) { 757 + nxp_c45_macsec_write(phydev, MACSEC_RXAN0INUSS + i * 4, 0); 758 + nxp_c45_macsec_write(phydev, MACSEC_RXAN0IPUSS + i * 4, 0); 759 + } 760 + } 761 + 852 762 static void nxp_c45_rx_sc_del(struct phy_device *phydev, 853 763 struct nxp_c45_secy *phy_secy) 854 764 { ··· 884 742 nxp_c45_macsec_write(phydev, MACSEC_RPW, 0); 885 743 nxp_c45_set_sci(phydev, MACSEC_RXSC_SCI_1H, 0); 886 744 745 + nxp_c45_rx_sc_clear_stats(phydev, phy_secy); 746 + 887 747 list_for_each_entry_safe(pos, tmp, &phy_secy->sa_list, list) { 888 748 if (pos->type == RX_SA) { 889 749 nxp_c45_rx_sa_update(phydev, pos, false); 890 750 nxp_c45_sa_free(pos); 891 751 } 892 752 } 753 + } 754 + 755 + static void nxp_c45_clear_global_stats(struct phy_device *phydev) 756 + { 757 + nxp_c45_macsec_write(phydev, MACSEC_INPBTS, 0); 758 + nxp_c45_macsec_write(phydev, MACSEC_INPWTS, 0); 759 + nxp_c45_macsec_write(phydev, MACSEC_IPSNFS, 0); 893 760 } 894 761 895 762 static void nxp_c45_macsec_en(struct phy_device *phydev, bool en) ··· 1092 941 nxp_c45_mdo_dev_stop(ctx); 1093 942 nxp_c45_tx_sa_next(phy_secy, &next_sa, encoding_sa); 1094 943 nxp_c45_tx_sa_update(phydev, &next_sa, false); 944 + nxp_c45_tx_sc_clear_stats(phydev, phy_secy); 1095 945 if (phy_secy->rx_sc) 1096 946 nxp_c45_rx_sc_del(phydev, phy_secy); 1097 947 ··· 1102 950 1103 951 clear_bit(phy_secy->secy_id, priv->macsec->tx_sc_bitmap); 1104 952 nxp_c45_secy_free(phy_secy); 953 + 954 + if (list_empty(&priv->macsec->secy_list)) 955 + nxp_c45_clear_global_stats(phydev); 1105 956 1106 957 return 0; 1107 958 } ··· 1263 1108 1264 1109 nxp_c45_select_secy(phydev, phy_secy->secy_id); 1265 1110 nxp_c45_rx_sa_update(phydev, sa, false); 1111 + nxp_c45_rx_sa_clear_stats(phydev, sa); 1266 1112 1267 1113 nxp_c45_sa_free(sa); 1268 1114 ··· 1353 1197 nxp_c45_select_secy(phydev, phy_secy->secy_id); 1354 1198 if (ctx->secy->tx_sc.encoding_sa == sa->an) 1355 1199 nxp_c45_tx_sa_update(phydev, sa, false); 1200 + nxp_c45_tx_sa_clear_stats(phydev, sa); 1356 1201 1357 1202 nxp_c45_sa_free(sa); 1203 + 1204 + return 0; 1205 + } 1206 + 1207 + static int nxp_c45_mdo_get_dev_stats(struct macsec_context *ctx) 1208 + { 1209 + struct phy_device *phydev = ctx->phydev; 1210 + struct nxp_c45_phy *priv = phydev->priv; 1211 + struct macsec_dev_stats *dev_stats; 1212 + struct nxp_c45_secy *phy_secy; 1213 + 1214 + phy_secy = nxp_c45_find_secy(&priv->macsec->secy_list, ctx->secy->sci); 1215 + if (IS_ERR(phy_secy)) 1216 + return PTR_ERR(phy_secy); 1217 + 1218 + dev_stats = ctx->stats.dev_stats; 1219 + nxp_c45_select_secy(phydev, phy_secy->secy_id); 1220 + 1221 + nxp_c45_macsec_read32_64(phydev, MACSEC_OPUS, 1222 + &dev_stats->OutPktsUntagged); 1223 + nxp_c45_macsec_read32_64(phydev, MACSEC_OPTLS, 1224 + &dev_stats->OutPktsTooLong); 1225 + nxp_c45_macsec_read32_64(phydev, MACSEC_INPBTS, 1226 + &dev_stats->InPktsBadTag); 1227 + 1228 + if (phy_secy->secy->validate_frames == MACSEC_VALIDATE_STRICT) 1229 + nxp_c45_macsec_read32_64(phydev, MACSEC_INPWTS, 1230 + &dev_stats->InPktsNoTag); 1231 + else 1232 + nxp_c45_macsec_read32_64(phydev, MACSEC_INPWTS, 1233 + &dev_stats->InPktsUntagged); 1234 + 1235 + if (phy_secy->secy->validate_frames == MACSEC_VALIDATE_STRICT) 1236 + nxp_c45_macsec_read32_64(phydev, MACSEC_IPSNFS, 1237 + &dev_stats->InPktsNoSCI); 1238 + else 1239 + nxp_c45_macsec_read32_64(phydev, MACSEC_IPSNFS, 1240 + &dev_stats->InPktsUnknownSCI); 1241 + 1242 + /* Always 0. */ 1243 + dev_stats->InPktsOverrun = 0; 1244 + 1245 + return 0; 1246 + } 1247 + 1248 + static int nxp_c45_mdo_get_tx_sc_stats(struct macsec_context *ctx) 1249 + { 1250 + struct phy_device *phydev = ctx->phydev; 1251 + struct nxp_c45_phy *priv = phydev->priv; 1252 + struct macsec_tx_sa_stats tx_sa_stats; 1253 + struct macsec_tx_sc_stats *stats; 1254 + struct nxp_c45_secy *phy_secy; 1255 + struct nxp_c45_sa *pos, *tmp; 1256 + 1257 + phy_secy = nxp_c45_find_secy(&priv->macsec->secy_list, ctx->secy->sci); 1258 + if (IS_ERR(phy_secy)) 1259 + return PTR_ERR(phy_secy); 1260 + 1261 + stats = ctx->stats.tx_sc_stats; 1262 + nxp_c45_select_secy(phydev, phy_secy->secy_id); 1263 + 1264 + nxp_c45_macsec_read64(phydev, MACSEC_OOE1HS, 1265 + &stats->OutOctetsEncrypted); 1266 + nxp_c45_macsec_read64(phydev, MACSEC_OOP1HS, 1267 + &stats->OutOctetsProtected); 1268 + list_for_each_entry_safe(pos, tmp, &phy_secy->sa_list, list) { 1269 + if (pos->type != TX_SA) 1270 + continue; 1271 + 1272 + memset(&tx_sa_stats, 0, sizeof(tx_sa_stats)); 1273 + nxp_c45_tx_sa_read_stats(phydev, pos, &tx_sa_stats); 1274 + 1275 + stats->OutPktsEncrypted += tx_sa_stats.OutPktsEncrypted; 1276 + stats->OutPktsProtected += tx_sa_stats.OutPktsProtected; 1277 + } 1278 + 1279 + return 0; 1280 + } 1281 + 1282 + static int nxp_c45_mdo_get_tx_sa_stats(struct macsec_context *ctx) 1283 + { 1284 + struct phy_device *phydev = ctx->phydev; 1285 + struct nxp_c45_phy *priv = phydev->priv; 1286 + struct macsec_tx_sa_stats *stats; 1287 + struct nxp_c45_secy *phy_secy; 1288 + u8 an = ctx->sa.assoc_num; 1289 + struct nxp_c45_sa *sa; 1290 + 1291 + phy_secy = nxp_c45_find_secy(&priv->macsec->secy_list, ctx->secy->sci); 1292 + if (IS_ERR(phy_secy)) 1293 + return PTR_ERR(phy_secy); 1294 + 1295 + sa = nxp_c45_find_sa(&phy_secy->sa_list, TX_SA, an); 1296 + if (IS_ERR(sa)) 1297 + return PTR_ERR(sa); 1298 + 1299 + stats = ctx->stats.tx_sa_stats; 1300 + nxp_c45_select_secy(phydev, phy_secy->secy_id); 1301 + nxp_c45_tx_sa_read_stats(phydev, sa, stats); 1302 + 1303 + return 0; 1304 + } 1305 + 1306 + static int nxp_c45_mdo_get_rx_sc_stats(struct macsec_context *ctx) 1307 + { 1308 + struct phy_device *phydev = ctx->phydev; 1309 + struct nxp_c45_phy *priv = phydev->priv; 1310 + struct macsec_rx_sa_stats rx_sa_stats; 1311 + struct macsec_rx_sc_stats *stats; 1312 + struct nxp_c45_secy *phy_secy; 1313 + struct nxp_c45_sa *pos, *tmp; 1314 + u32 reg = 0; 1315 + int i; 1316 + 1317 + phy_secy = nxp_c45_find_secy(&priv->macsec->secy_list, ctx->secy->sci); 1318 + if (IS_ERR(phy_secy)) 1319 + return PTR_ERR(phy_secy); 1320 + 1321 + if (phy_secy->rx_sc != ctx->rx_sc) 1322 + return -EINVAL; 1323 + 1324 + stats = ctx->stats.rx_sc_stats; 1325 + nxp_c45_select_secy(phydev, phy_secy->secy_id); 1326 + 1327 + list_for_each_entry_safe(pos, tmp, &phy_secy->sa_list, list) { 1328 + if (pos->type != RX_SA) 1329 + continue; 1330 + 1331 + memset(&rx_sa_stats, 0, sizeof(rx_sa_stats)); 1332 + nxp_c45_rx_sa_read_stats(phydev, pos, &rx_sa_stats); 1333 + 1334 + stats->InPktsInvalid += rx_sa_stats.InPktsInvalid; 1335 + stats->InPktsNotValid += rx_sa_stats.InPktsNotValid; 1336 + stats->InPktsOK += rx_sa_stats.InPktsOK; 1337 + } 1338 + 1339 + for (i = 0; i < MACSEC_NUM_AN; i++) { 1340 + nxp_c45_macsec_read(phydev, MACSEC_RXAN0INUSS + i * 4, &reg); 1341 + stats->InPktsNotUsingSA += reg; 1342 + nxp_c45_macsec_read(phydev, MACSEC_RXAN0IPUSS + i * 4, &reg); 1343 + stats->InPktsUnusedSA += reg; 1344 + } 1345 + 1346 + nxp_c45_macsec_read64(phydev, MACSEC_INOD1HS, 1347 + &stats->InOctetsDecrypted); 1348 + nxp_c45_macsec_read64(phydev, MACSEC_INOV1HS, 1349 + &stats->InOctetsValidated); 1350 + 1351 + nxp_c45_macsec_read32_64(phydev, MACSEC_RXSCIPDS, 1352 + &stats->InPktsDelayed); 1353 + nxp_c45_macsec_read32_64(phydev, MACSEC_RXSCIPLS, 1354 + &stats->InPktsLate); 1355 + nxp_c45_macsec_read32_64(phydev, MACSEC_RXSCIPUS, 1356 + &stats->InPktsUnchecked); 1357 + 1358 + return 0; 1359 + } 1360 + 1361 + static int nxp_c45_mdo_get_rx_sa_stats(struct macsec_context *ctx) 1362 + { 1363 + struct phy_device *phydev = ctx->phydev; 1364 + struct nxp_c45_phy *priv = phydev->priv; 1365 + struct macsec_rx_sa_stats *stats; 1366 + struct nxp_c45_secy *phy_secy; 1367 + u8 an = ctx->sa.assoc_num; 1368 + struct nxp_c45_sa *sa; 1369 + 1370 + phy_secy = nxp_c45_find_secy(&priv->macsec->secy_list, ctx->secy->sci); 1371 + if (IS_ERR(phy_secy)) 1372 + return PTR_ERR(phy_secy); 1373 + 1374 + sa = nxp_c45_find_sa(&phy_secy->sa_list, RX_SA, an); 1375 + if (IS_ERR(sa)) 1376 + return PTR_ERR(sa); 1377 + 1378 + stats = ctx->stats.rx_sa_stats; 1379 + nxp_c45_select_secy(phydev, phy_secy->secy_id); 1380 + 1381 + nxp_c45_rx_sa_read_stats(phydev, sa, stats); 1382 + nxp_c45_macsec_read(phydev, MACSEC_RXAN0INUSS + an * 4, 1383 + &stats->InPktsNotUsingSA); 1384 + nxp_c45_macsec_read(phydev, MACSEC_RXAN0IPUSS + an * 4, 1385 + &stats->InPktsUnusedSA); 1358 1386 1359 1387 return 0; 1360 1388 } ··· 1558 1218 .mdo_add_txsa = nxp_c45_mdo_add_txsa, 1559 1219 .mdo_upd_txsa = nxp_c45_mdo_upd_txsa, 1560 1220 .mdo_del_txsa = nxp_c45_mdo_del_txsa, 1221 + .mdo_get_dev_stats = nxp_c45_mdo_get_dev_stats, 1222 + .mdo_get_tx_sc_stats = nxp_c45_mdo_get_tx_sc_stats, 1223 + .mdo_get_tx_sa_stats = nxp_c45_mdo_get_tx_sa_stats, 1224 + .mdo_get_rx_sc_stats = nxp_c45_mdo_get_rx_sc_stats, 1225 + .mdo_get_rx_sa_stats = nxp_c45_mdo_get_rx_sa_stats, 1561 1226 }; 1562 1227 1563 1228 int nxp_c45_macsec_config_init(struct phy_device *phydev)