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

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'net-stmmac-qcom-ethqos-cleanups-and-re-organise-serdes-handling'

Russell King says:

====================
net: stmmac: qcom-ethqos: cleanups and re-organise SerDes handling

As the last series had issues with stability, I've changed the approach
in this series to concentrate on keeping much of the SerDes related
code within the qcom-ethqos driver rather than trying to move it out at
this stage. This means it should be possible to bisect these patches and
pinpoint exactly the code movement that causes any instability.

This series starts with various cleanups to qcom-ethqos (the first four
patches) before beginning to move code, passing phylink's phy interface
(which will change) to the fix_mac_speed() method, and then using that
to configure the serdes and inband setting before moving the SerDes
code.

This patch set has been tested.
====================

Link: https://patch.msgid.link/aZwfAFJQcp9f0niI@shell.armlinux.org.uk
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+101 -71
+2 -1
drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c
··· 112 112 #define AUTO_CAL_STATUS 0x880c 113 113 #define AUTO_CAL_STATUS_ACTIVE BIT(31) 114 114 115 - static void tegra_eqos_fix_speed(void *bsp_priv, int speed, unsigned int mode) 115 + static void tegra_eqos_fix_speed(void *bsp_priv, phy_interface_t interface, 116 + int speed, unsigned int mode) 116 117 { 117 118 struct tegra_eqos *eqos = bsp_priv; 118 119 bool needs_calibration = false;
+7 -4
drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c
··· 48 48 49 49 int (*fix_soc_reset)(struct stmmac_priv *priv); 50 50 int (*set_intf_mode)(struct imx_priv_data *dwmac, u8 phy_intf_sel); 51 - void (*fix_mac_speed)(void *priv, int speed, unsigned int mode); 51 + void (*fix_mac_speed)(void *priv, phy_interface_t interface, 52 + int speed, unsigned int mode); 52 53 }; 53 54 54 55 struct imx_priv_data { ··· 161 160 return stmmac_set_clk_tx_rate(bsp_priv, clk_tx_i, interface, speed); 162 161 } 163 162 164 - static void imx_dwmac_fix_speed(void *priv, int speed, unsigned int mode) 163 + static void imx_dwmac_fix_speed(void *priv, phy_interface_t interface, 164 + int speed, unsigned int mode) 165 165 { 166 166 struct plat_stmmacenet_data *plat_dat; 167 167 struct imx_priv_data *dwmac = priv; ··· 187 185 dev_err(dwmac->dev, "failed to set tx rate %lu\n", rate); 188 186 } 189 187 190 - static void imx93_dwmac_fix_speed(void *priv, int speed, unsigned int mode) 188 + static void imx93_dwmac_fix_speed(void *priv, phy_interface_t interface, 189 + int speed, unsigned int mode) 191 190 { 192 191 struct imx_priv_data *dwmac = priv; 193 192 unsigned int iface; 194 193 int ctrl, old_ctrl; 195 194 196 - imx_dwmac_fix_speed(priv, speed, mode); 195 + imx_dwmac_fix_speed(priv, interface, speed, mode); 197 196 198 197 if (!dwmac || mode != MLO_AN_FIXED) 199 198 return;
+2 -1
drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
··· 143 143 .setup = loongson_gmac_data, 144 144 }; 145 145 146 - static void loongson_gnet_fix_speed(void *priv, int speed, unsigned int mode) 146 + static void loongson_gnet_fix_speed(void *priv, phy_interface_t interface, 147 + int speed, unsigned int mode) 147 148 { 148 149 struct loongson_data *ld = (struct loongson_data *)priv; 149 150 struct net_device *ndev = dev_get_drvdata(ld->dev);
+77 -58
drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
··· 87 87 }; 88 88 89 89 struct ethqos_emac_driver_data { 90 - const struct ethqos_emac_por *por; 91 - unsigned int num_por; 90 + const struct ethqos_emac_por *rgmii_por; 91 + unsigned int num_rgmii_por; 92 92 bool rgmii_config_loopback_en; 93 93 bool has_emac_ge_3; 94 94 const char *link_clk_name; ··· 100 100 struct qcom_ethqos { 101 101 struct platform_device *pdev; 102 102 void __iomem *rgmii_base; 103 - int (*configure_func)(struct qcom_ethqos *ethqos, int speed); 103 + void (*configure_func)(struct qcom_ethqos *ethqos, 104 + phy_interface_t interface, int speed); 104 105 105 - unsigned int link_clk_rate; 106 106 struct clk *link_clk; 107 107 struct phy *serdes_phy; 108 108 int serdes_speed; 109 109 phy_interface_t phy_mode; 110 110 111 - const struct ethqos_emac_por *por; 112 - unsigned int num_por; 111 + const struct ethqos_emac_por *rgmii_por; 112 + unsigned int num_rgmii_por; 113 113 bool rgmii_config_loopback_en; 114 114 bool has_emac_ge_3; 115 115 bool needs_sgmii_loopback; ··· 174 174 rgmii_readl(ethqos, EMAC_SYSTEM_LOW_POWER_DEBUG)); 175 175 } 176 176 177 - static void 178 - ethqos_update_link_clk(struct qcom_ethqos *ethqos, int speed) 177 + static int ethqos_set_clk_tx_rate(void *bsp_priv, struct clk *clk_tx_i, 178 + phy_interface_t interface, int speed) 179 179 { 180 + struct qcom_ethqos *ethqos = bsp_priv; 180 181 long rate; 181 182 182 - if (!phy_interface_mode_is_rgmii(ethqos->phy_mode)) 183 - return; 183 + if (!phy_interface_mode_is_rgmii(interface)) 184 + return 0; 184 185 185 186 rate = rgmii_clock(speed); 186 - if (rate > 0) 187 - ethqos->link_clk_rate = rate * 2; 187 + if (rate < 0) 188 + return rate; 188 189 189 - clk_set_rate(ethqos->link_clk, ethqos->link_clk_rate); 190 + return clk_set_rate(ethqos->link_clk, rate * 2); 190 191 } 191 192 192 193 static void ··· 205 204 206 205 static void ethqos_set_func_clk_en(struct qcom_ethqos *ethqos) 207 206 { 208 - qcom_ethqos_set_sgmii_loopback(ethqos, true); 209 207 rgmii_setmask(ethqos, RGMII_CONFIG_FUNC_CLK_EN, RGMII_IO_MACRO_CONFIG); 210 208 } 211 209 ··· 218 218 }; 219 219 220 220 static const struct ethqos_emac_driver_data emac_v2_3_0_data = { 221 - .por = emac_v2_3_0_por, 222 - .num_por = ARRAY_SIZE(emac_v2_3_0_por), 221 + .rgmii_por = emac_v2_3_0_por, 222 + .num_rgmii_por = ARRAY_SIZE(emac_v2_3_0_por), 223 223 .rgmii_config_loopback_en = true, 224 224 .has_emac_ge_3 = false, 225 225 }; ··· 234 234 }; 235 235 236 236 static const struct ethqos_emac_driver_data emac_v2_1_0_data = { 237 - .por = emac_v2_1_0_por, 238 - .num_por = ARRAY_SIZE(emac_v2_1_0_por), 237 + .rgmii_por = emac_v2_1_0_por, 238 + .num_rgmii_por = ARRAY_SIZE(emac_v2_1_0_por), 239 239 .rgmii_config_loopback_en = false, 240 240 .has_emac_ge_3 = false, 241 241 }; ··· 250 250 }; 251 251 252 252 static const struct ethqos_emac_driver_data emac_v3_0_0_data = { 253 - .por = emac_v3_0_0_por, 254 - .num_por = ARRAY_SIZE(emac_v3_0_0_por), 253 + .rgmii_por = emac_v3_0_0_por, 254 + .num_rgmii_por = ARRAY_SIZE(emac_v3_0_0_por), 255 255 .rgmii_config_loopback_en = false, 256 256 .has_emac_ge_3 = true, 257 257 .dwmac4_addrs = { ··· 282 282 }; 283 283 284 284 static const struct ethqos_emac_driver_data emac_v4_0_0_data = { 285 - .por = emac_v4_0_0_por, 286 - .num_por = ARRAY_SIZE(emac_v4_0_0_por), 285 + .rgmii_por = emac_v4_0_0_por, 286 + .num_rgmii_por = ARRAY_SIZE(emac_v4_0_0_por), 287 287 .rgmii_config_loopback_en = false, 288 288 .has_emac_ge_3 = true, 289 289 .link_clk_name = "phyaux", ··· 361 361 SDCC_HC_REG_DLL_CONFIG2); 362 362 363 363 rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_MCLK_FREQ_CALC, 364 - 0x1A << 10, SDCC_HC_REG_DLL_CONFIG2); 364 + FIELD_PREP(SDCC_DLL_CONFIG2_MCLK_FREQ_CALC, 26), 365 + SDCC_HC_REG_DLL_CONFIG2); 365 366 366 367 rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SEL, 367 - BIT(2), SDCC_HC_REG_DLL_CONFIG2); 368 + FIELD_PREP(SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SEL, 369 + 1), SDCC_HC_REG_DLL_CONFIG2); 368 370 369 371 rgmii_setmask(ethqos, SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SW, 370 372 SDCC_HC_REG_DLL_CONFIG2); ··· 427 425 if (ethqos->has_emac_ge_3) { 428 426 /* 0.9 ns */ 429 427 rgmii_updatel(ethqos, SDCC_DDR_CONFIG_PRG_RCLK_DLY, 430 - 115, SDCC_HC_REG_DDR_CONFIG); 428 + FIELD_PREP(SDCC_DDR_CONFIG_PRG_RCLK_DLY, 429 + 115), SDCC_HC_REG_DDR_CONFIG); 431 430 } else { 432 431 /* 1.8 ns */ 433 432 rgmii_updatel(ethqos, SDCC_DDR_CONFIG_PRG_RCLK_DLY, 434 - 57, SDCC_HC_REG_DDR_CONFIG); 433 + FIELD_PREP(SDCC_DDR_CONFIG_PRG_RCLK_DLY, 434 + 57), SDCC_HC_REG_DDR_CONFIG); 435 435 } 436 436 rgmii_setmask(ethqos, SDCC_DDR_CONFIG_PRG_DLY_EN, 437 437 SDCC_HC_REG_DDR_CONFIG); ··· 455 451 rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, 456 452 phase_shift, RGMII_IO_MACRO_CONFIG2); 457 453 rgmii_updatel(ethqos, RGMII_CONFIG_MAX_SPD_PRG_2, 458 - BIT(6), RGMII_IO_MACRO_CONFIG); 454 + FIELD_PREP(RGMII_CONFIG_MAX_SPD_PRG_2, 1), 455 + RGMII_IO_MACRO_CONFIG); 459 456 rgmii_clrmask(ethqos, RGMII_CONFIG2_RSVD_CONFIG15, 460 457 RGMII_IO_MACRO_CONFIG2); 461 458 ··· 469 464 470 465 /* Write 0x5 to PRG_RCLK_DLY_CODE */ 471 466 rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE, 472 - (BIT(29) | BIT(27)), SDCC_HC_REG_DDR_CONFIG); 467 + FIELD_PREP(SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE, 468 + 5), SDCC_HC_REG_DDR_CONFIG); 473 469 rgmii_setmask(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY, 474 470 SDCC_HC_REG_DDR_CONFIG); 475 471 rgmii_setmask(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN, ··· 493 487 rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, 494 488 phase_shift, RGMII_IO_MACRO_CONFIG2); 495 489 rgmii_updatel(ethqos, RGMII_CONFIG_MAX_SPD_PRG_9, 496 - BIT(12) | GENMASK(9, 8), 490 + FIELD_PREP(RGMII_CONFIG_MAX_SPD_PRG_9, 19), 497 491 RGMII_IO_MACRO_CONFIG); 498 492 rgmii_clrmask(ethqos, RGMII_CONFIG2_RSVD_CONFIG15, 499 493 RGMII_IO_MACRO_CONFIG2); ··· 505 499 RGMII_IO_MACRO_CONFIG2); 506 500 /* Write 0x5 to PRG_RCLK_DLY_CODE */ 507 501 rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE, 508 - (BIT(29) | BIT(27)), SDCC_HC_REG_DDR_CONFIG); 502 + FIELD_PREP(SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE, 503 + 5), SDCC_HC_REG_DDR_CONFIG); 509 504 rgmii_setmask(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY, 510 505 SDCC_HC_REG_DDR_CONFIG); 511 506 rgmii_setmask(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN, ··· 522 515 return 0; 523 516 } 524 517 525 - static int ethqos_configure_rgmii(struct qcom_ethqos *ethqos, int speed) 518 + static void ethqos_configure_rgmii(struct qcom_ethqos *ethqos, 519 + phy_interface_t interface, int speed) 526 520 { 527 521 struct device *dev = &ethqos->pdev->dev; 528 522 unsigned int i; 529 523 u32 val; 530 524 531 525 /* Reset to POR values and enable clk */ 532 - for (i = 0; i < ethqos->num_por; i++) 533 - rgmii_writel(ethqos, ethqos->por[i].value, 534 - ethqos->por[i].offset); 526 + for (i = 0; i < ethqos->num_rgmii_por; i++) 527 + rgmii_writel(ethqos, ethqos->rgmii_por[i].value, 528 + ethqos->rgmii_por[i].offset); 529 + 535 530 ethqos_set_func_clk_en(ethqos); 536 531 537 532 /* Initialize the DLL first */ ··· 589 580 ethqos_dll_configure(ethqos); 590 581 591 582 ethqos_rgmii_macro_init(ethqos, speed); 592 - 593 - return 0; 594 583 } 595 584 596 585 static void ethqos_set_serdes_speed(struct qcom_ethqos *ethqos, int speed) ··· 607 600 /* On interface toggle MAC registers gets reset. 608 601 * Configure MAC block for SGMII on ethernet phy link up 609 602 */ 610 - static int ethqos_configure_sgmii(struct qcom_ethqos *ethqos, int speed) 603 + static void ethqos_configure_sgmii(struct qcom_ethqos *ethqos, 604 + phy_interface_t interface, int speed) 611 605 { 612 606 struct net_device *dev = platform_get_drvdata(ethqos->pdev); 613 607 struct stmmac_priv *priv = netdev_priv(dev); 614 608 615 609 switch (speed) { 616 610 case SPEED_2500: 617 - rgmii_setmask(ethqos, RGMII_CONFIG2_RGMII_CLK_SEL_CFG, 618 - RGMII_IO_MACRO_CONFIG2); 619 - ethqos_set_serdes_speed(ethqos, SPEED_2500); 620 - ethqos_pcs_set_inband(priv, false); 621 - break; 622 611 case SPEED_1000: 623 612 rgmii_setmask(ethqos, RGMII_CONFIG2_RGMII_CLK_SEL_CFG, 624 613 RGMII_IO_MACRO_CONFIG2); 625 - ethqos_set_serdes_speed(ethqos, SPEED_1000); 626 - ethqos_pcs_set_inband(priv, true); 627 614 break; 628 615 case SPEED_100: 629 - ethqos_set_serdes_speed(ethqos, SPEED_1000); 630 - ethqos_pcs_set_inband(priv, true); 631 616 break; 632 617 case SPEED_10: 633 618 rgmii_updatel(ethqos, RGMII_CONFIG_SGMII_CLK_DVDR, 634 619 FIELD_PREP(RGMII_CONFIG_SGMII_CLK_DVDR, 635 620 SGMII_10M_RX_CLK_DVDR), 636 621 RGMII_IO_MACRO_CONFIG); 637 - ethqos_set_serdes_speed(ethqos, SPEED_1000); 638 - ethqos_pcs_set_inband(priv, true); 639 622 break; 640 623 } 641 624 642 - return 0; 625 + ethqos_pcs_set_inband(priv, interface == PHY_INTERFACE_MODE_SGMII); 643 626 } 644 627 645 - static int ethqos_configure(struct qcom_ethqos *ethqos, int speed) 628 + static void ethqos_configure(struct qcom_ethqos *ethqos, 629 + phy_interface_t interface, int speed) 646 630 { 647 - return ethqos->configure_func(ethqos, speed); 631 + return ethqos->configure_func(ethqos, interface, speed); 648 632 } 649 633 650 - static void ethqos_fix_mac_speed(void *priv, int speed, unsigned int mode) 634 + static void ethqos_fix_mac_speed(void *priv, phy_interface_t interface, 635 + int speed, unsigned int mode) 651 636 { 652 637 struct qcom_ethqos *ethqos = priv; 653 638 654 - qcom_ethqos_set_sgmii_loopback(ethqos, false); 655 - ethqos_update_link_clk(ethqos, speed); 656 - ethqos_configure(ethqos, speed); 639 + ethqos_configure(ethqos, interface, speed); 657 640 } 658 641 659 642 static int qcom_ethqos_serdes_powerup(struct net_device *ndev, void *priv) ··· 678 681 phy_exit(ethqos->serdes_phy); 679 682 } 680 683 684 + static int ethqos_mac_finish_serdes(struct net_device *ndev, void *priv, 685 + unsigned int mode, 686 + phy_interface_t interface) 687 + { 688 + struct qcom_ethqos *ethqos = priv; 689 + 690 + qcom_ethqos_set_sgmii_loopback(ethqos, false); 691 + 692 + if (interface == PHY_INTERFACE_MODE_SGMII) 693 + ethqos_set_serdes_speed(ethqos, SPEED_1000); 694 + else if (interface == PHY_INTERFACE_MODE_2500BASEX) 695 + ethqos_set_serdes_speed(ethqos, SPEED_2500); 696 + 697 + return 0; 698 + } 699 + 681 700 static int ethqos_clks_config(void *priv, bool enabled) 682 701 { 683 702 struct qcom_ethqos *ethqos = priv; ··· 711 698 * cycled. The actual configuration will be adjusted once 712 699 * ethqos_fix_mac_speed() is invoked. 713 700 */ 701 + qcom_ethqos_set_sgmii_loopback(ethqos, true); 714 702 ethqos_set_func_clk_en(ethqos); 715 703 } else { 716 704 clk_disable_unprepare(ethqos->link_clk); ··· 780 766 case PHY_INTERFACE_MODE_2500BASEX: 781 767 case PHY_INTERFACE_MODE_SGMII: 782 768 ethqos->configure_func = ethqos_configure_sgmii; 769 + plat_dat->mac_finish = ethqos_mac_finish_serdes; 783 770 break; 784 771 default: 785 772 dev_err(dev, "Unsupported phy mode %s\n", ··· 795 780 "Failed to map rgmii resource\n"); 796 781 797 782 data = of_device_get_match_data(dev); 798 - ethqos->por = data->por; 799 - ethqos->num_por = data->num_por; 783 + ethqos->rgmii_por = data->rgmii_por; 784 + ethqos->num_rgmii_por = data->num_rgmii_por; 800 785 ethqos->rgmii_config_loopback_en = data->rgmii_config_loopback_en; 801 786 ethqos->has_emac_ge_3 = data->has_emac_ge_3; 802 787 ethqos->needs_sgmii_loopback = data->needs_sgmii_loopback; ··· 820 805 "Failed to get serdes phy\n"); 821 806 822 807 ethqos->serdes_speed = SPEED_1000; 823 - ethqos_update_link_clk(ethqos, SPEED_1000); 808 + ethqos_set_clk_tx_rate(ethqos, NULL, plat_dat->phy_interface, 809 + SPEED_1000); 810 + 811 + qcom_ethqos_set_sgmii_loopback(ethqos, true); 824 812 ethqos_set_func_clk_en(ethqos); 825 813 826 814 plat_dat->bsp_priv = ethqos; 815 + plat_dat->set_clk_tx_rate = ethqos_set_clk_tx_rate; 827 816 plat_dat->fix_mac_speed = ethqos_fix_mac_speed; 828 817 plat_dat->dump_debug_regs = rgmii_dump; 829 818 plat_dat->ptp_clk_freq_config = ethqos_ptp_clk_freq_config;
+2 -1
drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
··· 72 72 const struct socfpga_dwmac_ops *ops; 73 73 }; 74 74 75 - static void socfpga_dwmac_fix_mac_speed(void *bsp_priv, int speed, 75 + static void socfpga_dwmac_fix_mac_speed(void *bsp_priv, 76 + phy_interface_t interface, int speed, 76 77 unsigned int mode) 77 78 { 78 79 struct socfpga_dwmac *dwmac = (struct socfpga_dwmac *)bsp_priv;
+7 -4
drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c
··· 91 91 struct regmap *regmap; 92 92 bool gmac_en; 93 93 int speed; 94 - void (*fix_retime_src)(void *priv, int speed, unsigned int mode); 94 + void (*fix_retime_src)(void *priv, phy_interface_t interface, 95 + int speed, unsigned int mode); 95 96 }; 96 97 97 98 struct sti_dwmac_of_data { 98 - void (*fix_retime_src)(void *priv, int speed, unsigned int mode); 99 + void (*fix_retime_src)(void *priv, phy_interface_t interface, 100 + int speed, unsigned int mode); 99 101 }; 100 102 101 103 enum { ··· 116 114 | STIH4XX_ETH_SEL_INTERNAL_NOTEXT_PHYCLK, 117 115 }; 118 116 119 - static void stih4xx_fix_retime_src(void *priv, int spd, unsigned int mode) 117 + static void stih4xx_fix_retime_src(void *priv, phy_interface_t interface, 118 + int spd, unsigned int mode) 120 119 { 121 120 struct sti_dwmac *dwmac = priv; 122 121 u32 src = dwmac->tx_retime_src; ··· 173 170 val = (dwmac->interface == PHY_INTERFACE_MODE_REVMII) ? 0 : ENMII; 174 171 regmap_update_bits(regmap, reg, ENMII_MASK, val); 175 172 176 - dwmac->fix_retime_src(dwmac, dwmac->speed, 0); 173 + dwmac->fix_retime_src(dwmac, dwmac->interface, dwmac->speed, 0); 177 174 178 175 return 0; 179 176 }
+2 -1
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
··· 1071 1071 } 1072 1072 1073 1073 if (priv->plat->fix_mac_speed) 1074 - priv->plat->fix_mac_speed(priv->plat->bsp_priv, speed, mode); 1074 + priv->plat->fix_mac_speed(priv->plat->bsp_priv, interface, 1075 + speed, mode); 1075 1076 1076 1077 if (!duplex) 1077 1078 ctrl &= ~priv->hw->link.duplex;
+2 -1
include/linux/stmmac.h
··· 256 256 int (*set_phy_intf_sel)(void *priv, u8 phy_intf_sel); 257 257 int (*set_clk_tx_rate)(void *priv, struct clk *clk_tx_i, 258 258 phy_interface_t interface, int speed); 259 - void (*fix_mac_speed)(void *priv, int speed, unsigned int mode); 259 + void (*fix_mac_speed)(void *priv, phy_interface_t interface, 260 + int speed, unsigned int mode); 260 261 int (*fix_soc_reset)(struct stmmac_priv *priv); 261 262 int (*serdes_powerup)(struct net_device *ndev, void *priv); 262 263 void (*serdes_powerdown)(struct net_device *ndev, void *priv);