aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sfc/xfp_phy.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/sfc/xfp_phy.c')
-rw-r--r--drivers/net/sfc/xfp_phy.c36
1 files changed, 36 insertions, 0 deletions
diff --git a/drivers/net/sfc/xfp_phy.c b/drivers/net/sfc/xfp_phy.c
index 66dd5bf1eaa9..3b9f9ddbc372 100644
--- a/drivers/net/sfc/xfp_phy.c
+++ b/drivers/net/sfc/xfp_phy.c
@@ -24,6 +24,10 @@
24 MDIO_MMDREG_DEVS0_PMAPMD | \ 24 MDIO_MMDREG_DEVS0_PMAPMD | \
25 MDIO_MMDREG_DEVS0_PHYXS) 25 MDIO_MMDREG_DEVS0_PHYXS)
26 26
27#define XFP_LOOPBACKS ((1 << LOOPBACK_PCS) | \
28 (1 << LOOPBACK_PMAPMD) | \
29 (1 << LOOPBACK_NETWORK))
30
27/****************************************************************************/ 31/****************************************************************************/
28/* Quake-specific MDIO registers */ 32/* Quake-specific MDIO registers */
29#define MDIO_QUAKE_LED0_REG (0xD006) 33#define MDIO_QUAKE_LED0_REG (0xD006)
@@ -35,6 +39,10 @@ void xfp_set_led(struct efx_nic *p, int led, int mode)
35 mode); 39 mode);
36} 40}
37 41
42struct xfp_phy_data {
43 int tx_disabled;
44};
45
38#define XFP_MAX_RESET_TIME 500 46#define XFP_MAX_RESET_TIME 500
39#define XFP_RESET_WAIT 10 47#define XFP_RESET_WAIT 10
40 48
@@ -72,18 +80,31 @@ static int xfp_reset_phy(struct efx_nic *efx)
72 80
73static int xfp_phy_init(struct efx_nic *efx) 81static int xfp_phy_init(struct efx_nic *efx)
74{ 82{
83 struct xfp_phy_data *phy_data;
75 u32 devid = mdio_clause45_read_id(efx, MDIO_MMD_PHYXS); 84 u32 devid = mdio_clause45_read_id(efx, MDIO_MMD_PHYXS);
76 int rc; 85 int rc;
77 86
87 phy_data = kzalloc(sizeof(struct xfp_phy_data), GFP_KERNEL);
88 efx->phy_data = (void *) phy_data;
89
78 EFX_INFO(efx, "XFP: PHY ID reg %x (OUI %x model %x revision" 90 EFX_INFO(efx, "XFP: PHY ID reg %x (OUI %x model %x revision"
79 " %x)\n", devid, MDIO_ID_OUI(devid), MDIO_ID_MODEL(devid), 91 " %x)\n", devid, MDIO_ID_OUI(devid), MDIO_ID_MODEL(devid),
80 MDIO_ID_REV(devid)); 92 MDIO_ID_REV(devid));
81 93
94 phy_data->tx_disabled = efx->tx_disabled;
95
82 rc = xfp_reset_phy(efx); 96 rc = xfp_reset_phy(efx);
83 97
84 EFX_INFO(efx, "XFP: PHY init %s.\n", 98 EFX_INFO(efx, "XFP: PHY init %s.\n",
85 rc ? "failed" : "successful"); 99 rc ? "failed" : "successful");
100 if (rc < 0)
101 goto fail;
86 102
103 return 0;
104
105 fail:
106 kfree(efx->phy_data);
107 efx->phy_data = NULL;
87 return rc; 108 return rc;
88} 109}
89 110
@@ -110,6 +131,16 @@ static int xfp_phy_check_hw(struct efx_nic *efx)
110 131
111static void xfp_phy_reconfigure(struct efx_nic *efx) 132static void xfp_phy_reconfigure(struct efx_nic *efx)
112{ 133{
134 struct xfp_phy_data *phy_data = efx->phy_data;
135
136 /* Reset the PHY when moving from tx off to tx on */
137 if (phy_data->tx_disabled && !efx->tx_disabled)
138 xfp_reset_phy(efx);
139
140 mdio_clause45_transmit_disable(efx);
141 mdio_clause45_phy_reconfigure(efx);
142
143 phy_data->tx_disabled = efx->tx_disabled;
113 efx->link_up = xfp_link_ok(efx); 144 efx->link_up = xfp_link_ok(efx);
114 efx->link_options = GM_LPA_10000FULL; 145 efx->link_options = GM_LPA_10000FULL;
115} 146}
@@ -119,6 +150,10 @@ static void xfp_phy_fini(struct efx_nic *efx)
119{ 150{
120 /* Clobber the LED if it was blinking */ 151 /* Clobber the LED if it was blinking */
121 efx->board_info.blink(efx, 0); 152 efx->board_info.blink(efx, 0);
153
154 /* Free the context block */
155 kfree(efx->phy_data);
156 efx->phy_data = NULL;
122} 157}
123 158
124struct efx_phy_operations falcon_xfp_phy_ops = { 159struct efx_phy_operations falcon_xfp_phy_ops = {
@@ -129,4 +164,5 @@ struct efx_phy_operations falcon_xfp_phy_ops = {
129 .clear_interrupt = xfp_phy_clear_interrupt, 164 .clear_interrupt = xfp_phy_clear_interrupt,
130 .reset_xaui = efx_port_dummy_op_void, 165 .reset_xaui = efx_port_dummy_op_void,
131 .mmds = XFP_REQUIRED_DEVS, 166 .mmds = XFP_REQUIRED_DEVS,
167 .loopbacks = XFP_LOOPBACKS,
132}; 168};