diff options
-rw-r--r-- | drivers/net/ethernet/sfc/efx.c | 43 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/efx.h | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/ethtool.c | 6 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/mcdi_port.c | 158 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/net_driver.h | 2 |
5 files changed, 120 insertions, 93 deletions
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 3780161de5a1..12f0abc30cb1 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c | |||
@@ -953,31 +953,42 @@ void efx_link_status_changed(struct efx_nic *efx) | |||
953 | netif_info(efx, link, efx->net_dev, "link down\n"); | 953 | netif_info(efx, link, efx->net_dev, "link down\n"); |
954 | } | 954 | } |
955 | 955 | ||
956 | void efx_link_set_advertising(struct efx_nic *efx, u32 advertising) | 956 | void efx_link_set_advertising(struct efx_nic *efx, |
957 | const unsigned long *advertising) | ||
957 | { | 958 | { |
958 | efx->link_advertising = advertising; | 959 | memcpy(efx->link_advertising, advertising, |
959 | if (advertising) { | 960 | sizeof(__ETHTOOL_DECLARE_LINK_MODE_MASK())); |
960 | if (advertising & ADVERTISED_Pause) | 961 | |
961 | efx->wanted_fc |= (EFX_FC_TX | EFX_FC_RX); | 962 | efx->link_advertising[0] |= ADVERTISED_Autoneg; |
962 | else | 963 | if (advertising[0] & ADVERTISED_Pause) |
963 | efx->wanted_fc &= ~(EFX_FC_TX | EFX_FC_RX); | 964 | efx->wanted_fc |= (EFX_FC_TX | EFX_FC_RX); |
964 | if (advertising & ADVERTISED_Asym_Pause) | 965 | else |
965 | efx->wanted_fc ^= EFX_FC_TX; | 966 | efx->wanted_fc &= ~(EFX_FC_TX | EFX_FC_RX); |
966 | } | 967 | if (advertising[0] & ADVERTISED_Asym_Pause) |
968 | efx->wanted_fc ^= EFX_FC_TX; | ||
969 | } | ||
970 | |||
971 | /* Equivalent to efx_link_set_advertising with all-zeroes, except does not | ||
972 | * force the Autoneg bit on. | ||
973 | */ | ||
974 | void efx_link_clear_advertising(struct efx_nic *efx) | ||
975 | { | ||
976 | bitmap_zero(efx->link_advertising, __ETHTOOL_LINK_MODE_MASK_NBITS); | ||
977 | efx->wanted_fc &= ~(EFX_FC_TX | EFX_FC_RX); | ||
967 | } | 978 | } |
968 | 979 | ||
969 | void efx_link_set_wanted_fc(struct efx_nic *efx, u8 wanted_fc) | 980 | void efx_link_set_wanted_fc(struct efx_nic *efx, u8 wanted_fc) |
970 | { | 981 | { |
971 | efx->wanted_fc = wanted_fc; | 982 | efx->wanted_fc = wanted_fc; |
972 | if (efx->link_advertising) { | 983 | if (efx->link_advertising[0]) { |
973 | if (wanted_fc & EFX_FC_RX) | 984 | if (wanted_fc & EFX_FC_RX) |
974 | efx->link_advertising |= (ADVERTISED_Pause | | 985 | efx->link_advertising[0] |= (ADVERTISED_Pause | |
975 | ADVERTISED_Asym_Pause); | 986 | ADVERTISED_Asym_Pause); |
976 | else | 987 | else |
977 | efx->link_advertising &= ~(ADVERTISED_Pause | | 988 | efx->link_advertising[0] &= ~(ADVERTISED_Pause | |
978 | ADVERTISED_Asym_Pause); | 989 | ADVERTISED_Asym_Pause); |
979 | if (wanted_fc & EFX_FC_TX) | 990 | if (wanted_fc & EFX_FC_TX) |
980 | efx->link_advertising ^= ADVERTISED_Asym_Pause; | 991 | efx->link_advertising[0] ^= ADVERTISED_Asym_Pause; |
981 | } | 992 | } |
982 | } | 993 | } |
983 | 994 | ||
diff --git a/drivers/net/ethernet/sfc/efx.h b/drivers/net/ethernet/sfc/efx.h index 16da3e9a6000..0cddc5ad77b1 100644 --- a/drivers/net/ethernet/sfc/efx.h +++ b/drivers/net/ethernet/sfc/efx.h | |||
@@ -258,7 +258,9 @@ static inline void efx_schedule_channel_irq(struct efx_channel *channel) | |||
258 | } | 258 | } |
259 | 259 | ||
260 | void efx_link_status_changed(struct efx_nic *efx); | 260 | void efx_link_status_changed(struct efx_nic *efx); |
261 | void efx_link_set_advertising(struct efx_nic *efx, u32); | 261 | void efx_link_set_advertising(struct efx_nic *efx, |
262 | const unsigned long *advertising); | ||
263 | void efx_link_clear_advertising(struct efx_nic *efx); | ||
262 | void efx_link_set_wanted_fc(struct efx_nic *efx, u8); | 264 | void efx_link_set_wanted_fc(struct efx_nic *efx, u8); |
263 | 265 | ||
264 | static inline void efx_device_detach_sync(struct efx_nic *efx) | 266 | static inline void efx_device_detach_sync(struct efx_nic *efx) |
diff --git a/drivers/net/ethernet/sfc/ethtool.c b/drivers/net/ethernet/sfc/ethtool.c index 3747b5644110..4db2dc2bf52f 100644 --- a/drivers/net/ethernet/sfc/ethtool.c +++ b/drivers/net/ethernet/sfc/ethtool.c | |||
@@ -720,7 +720,7 @@ static int efx_ethtool_set_pauseparam(struct net_device *net_dev, | |||
720 | goto out; | 720 | goto out; |
721 | } | 721 | } |
722 | 722 | ||
723 | if ((wanted_fc & EFX_FC_AUTO) && !efx->link_advertising) { | 723 | if ((wanted_fc & EFX_FC_AUTO) && !efx->link_advertising[0]) { |
724 | netif_dbg(efx, drv, efx->net_dev, | 724 | netif_dbg(efx, drv, efx->net_dev, |
725 | "Autonegotiation is disabled\n"); | 725 | "Autonegotiation is disabled\n"); |
726 | rc = -EINVAL; | 726 | rc = -EINVAL; |
@@ -732,10 +732,10 @@ static int efx_ethtool_set_pauseparam(struct net_device *net_dev, | |||
732 | (wanted_fc & EFX_FC_TX) && !(efx->wanted_fc & EFX_FC_TX)) | 732 | (wanted_fc & EFX_FC_TX) && !(efx->wanted_fc & EFX_FC_TX)) |
733 | efx->type->prepare_enable_fc_tx(efx); | 733 | efx->type->prepare_enable_fc_tx(efx); |
734 | 734 | ||
735 | old_adv = efx->link_advertising; | 735 | old_adv = efx->link_advertising[0]; |
736 | old_fc = efx->wanted_fc; | 736 | old_fc = efx->wanted_fc; |
737 | efx_link_set_wanted_fc(efx, wanted_fc); | 737 | efx_link_set_wanted_fc(efx, wanted_fc); |
738 | if (efx->link_advertising != old_adv || | 738 | if (efx->link_advertising[0] != old_adv || |
739 | (efx->wanted_fc ^ old_fc) & EFX_FC_AUTO) { | 739 | (efx->wanted_fc ^ old_fc) & EFX_FC_AUTO) { |
740 | rc = efx->phy_op->reconfigure(efx); | 740 | rc = efx->phy_op->reconfigure(efx); |
741 | if (rc) { | 741 | if (rc) { |
diff --git a/drivers/net/ethernet/sfc/mcdi_port.c b/drivers/net/ethernet/sfc/mcdi_port.c index 65ee1a468170..ce8aabf9091e 100644 --- a/drivers/net/ethernet/sfc/mcdi_port.c +++ b/drivers/net/ethernet/sfc/mcdi_port.c | |||
@@ -171,89 +171,108 @@ static int efx_mcdi_mdio_write(struct net_device *net_dev, | |||
171 | return 0; | 171 | return 0; |
172 | } | 172 | } |
173 | 173 | ||
174 | static u32 mcdi_to_ethtool_cap(u32 media, u32 cap) | 174 | static void mcdi_to_ethtool_linkset(u32 media, u32 cap, unsigned long *linkset) |
175 | { | 175 | { |
176 | u32 result = 0; | 176 | #define SET_BIT(name) __set_bit(ETHTOOL_LINK_MODE_ ## name ## _BIT, \ |
177 | linkset) | ||
177 | 178 | ||
179 | bitmap_zero(linkset, __ETHTOOL_LINK_MODE_MASK_NBITS); | ||
178 | switch (media) { | 180 | switch (media) { |
179 | case MC_CMD_MEDIA_KX4: | 181 | case MC_CMD_MEDIA_KX4: |
180 | result |= SUPPORTED_Backplane; | 182 | SET_BIT(Backplane); |
181 | if (cap & (1 << MC_CMD_PHY_CAP_1000FDX_LBN)) | 183 | if (cap & (1 << MC_CMD_PHY_CAP_1000FDX_LBN)) |
182 | result |= SUPPORTED_1000baseKX_Full; | 184 | SET_BIT(1000baseKX_Full); |
183 | if (cap & (1 << MC_CMD_PHY_CAP_10000FDX_LBN)) | 185 | if (cap & (1 << MC_CMD_PHY_CAP_10000FDX_LBN)) |
184 | result |= SUPPORTED_10000baseKX4_Full; | 186 | SET_BIT(10000baseKX4_Full); |
185 | if (cap & (1 << MC_CMD_PHY_CAP_40000FDX_LBN)) | 187 | if (cap & (1 << MC_CMD_PHY_CAP_40000FDX_LBN)) |
186 | result |= SUPPORTED_40000baseKR4_Full; | 188 | SET_BIT(40000baseKR4_Full); |
187 | break; | 189 | break; |
188 | 190 | ||
189 | case MC_CMD_MEDIA_XFP: | 191 | case MC_CMD_MEDIA_XFP: |
190 | case MC_CMD_MEDIA_SFP_PLUS: | 192 | case MC_CMD_MEDIA_SFP_PLUS: |
191 | case MC_CMD_MEDIA_QSFP_PLUS: | 193 | case MC_CMD_MEDIA_QSFP_PLUS: |
192 | result |= SUPPORTED_FIBRE; | 194 | SET_BIT(FIBRE); |
193 | if (cap & (1 << MC_CMD_PHY_CAP_1000FDX_LBN)) | 195 | if (cap & (1 << MC_CMD_PHY_CAP_1000FDX_LBN)) |
194 | result |= SUPPORTED_1000baseT_Full; | 196 | SET_BIT(1000baseT_Full); |
195 | if (cap & (1 << MC_CMD_PHY_CAP_10000FDX_LBN)) | 197 | if (cap & (1 << MC_CMD_PHY_CAP_10000FDX_LBN)) |
196 | result |= SUPPORTED_10000baseT_Full; | 198 | SET_BIT(10000baseT_Full); |
197 | if (cap & (1 << MC_CMD_PHY_CAP_40000FDX_LBN)) | 199 | if (cap & (1 << MC_CMD_PHY_CAP_40000FDX_LBN)) |
198 | result |= SUPPORTED_40000baseCR4_Full; | 200 | SET_BIT(40000baseCR4_Full); |
201 | if (cap & (1 << MC_CMD_PHY_CAP_100000FDX_LBN)) | ||
202 | SET_BIT(100000baseCR4_Full); | ||
203 | if (cap & (1 << MC_CMD_PHY_CAP_25000FDX_LBN)) | ||
204 | SET_BIT(25000baseCR_Full); | ||
205 | if (cap & (1 << MC_CMD_PHY_CAP_50000FDX_LBN)) | ||
206 | SET_BIT(50000baseCR2_Full); | ||
199 | break; | 207 | break; |
200 | 208 | ||
201 | case MC_CMD_MEDIA_BASE_T: | 209 | case MC_CMD_MEDIA_BASE_T: |
202 | result |= SUPPORTED_TP; | 210 | SET_BIT(TP); |
203 | if (cap & (1 << MC_CMD_PHY_CAP_10HDX_LBN)) | 211 | if (cap & (1 << MC_CMD_PHY_CAP_10HDX_LBN)) |
204 | result |= SUPPORTED_10baseT_Half; | 212 | SET_BIT(10baseT_Half); |
205 | if (cap & (1 << MC_CMD_PHY_CAP_10FDX_LBN)) | 213 | if (cap & (1 << MC_CMD_PHY_CAP_10FDX_LBN)) |
206 | result |= SUPPORTED_10baseT_Full; | 214 | SET_BIT(10baseT_Full); |
207 | if (cap & (1 << MC_CMD_PHY_CAP_100HDX_LBN)) | 215 | if (cap & (1 << MC_CMD_PHY_CAP_100HDX_LBN)) |
208 | result |= SUPPORTED_100baseT_Half; | 216 | SET_BIT(100baseT_Half); |
209 | if (cap & (1 << MC_CMD_PHY_CAP_100FDX_LBN)) | 217 | if (cap & (1 << MC_CMD_PHY_CAP_100FDX_LBN)) |
210 | result |= SUPPORTED_100baseT_Full; | 218 | SET_BIT(100baseT_Full); |
211 | if (cap & (1 << MC_CMD_PHY_CAP_1000HDX_LBN)) | 219 | if (cap & (1 << MC_CMD_PHY_CAP_1000HDX_LBN)) |
212 | result |= SUPPORTED_1000baseT_Half; | 220 | SET_BIT(1000baseT_Half); |
213 | if (cap & (1 << MC_CMD_PHY_CAP_1000FDX_LBN)) | 221 | if (cap & (1 << MC_CMD_PHY_CAP_1000FDX_LBN)) |
214 | result |= SUPPORTED_1000baseT_Full; | 222 | SET_BIT(1000baseT_Full); |
215 | if (cap & (1 << MC_CMD_PHY_CAP_10000FDX_LBN)) | 223 | if (cap & (1 << MC_CMD_PHY_CAP_10000FDX_LBN)) |
216 | result |= SUPPORTED_10000baseT_Full; | 224 | SET_BIT(10000baseT_Full); |
217 | break; | 225 | break; |
218 | } | 226 | } |
219 | 227 | ||
220 | if (cap & (1 << MC_CMD_PHY_CAP_PAUSE_LBN)) | 228 | if (cap & (1 << MC_CMD_PHY_CAP_PAUSE_LBN)) |
221 | result |= SUPPORTED_Pause; | 229 | SET_BIT(Pause); |
222 | if (cap & (1 << MC_CMD_PHY_CAP_ASYM_LBN)) | 230 | if (cap & (1 << MC_CMD_PHY_CAP_ASYM_LBN)) |
223 | result |= SUPPORTED_Asym_Pause; | 231 | SET_BIT(Asym_Pause); |
224 | if (cap & (1 << MC_CMD_PHY_CAP_AN_LBN)) | 232 | if (cap & (1 << MC_CMD_PHY_CAP_AN_LBN)) |
225 | result |= SUPPORTED_Autoneg; | 233 | SET_BIT(Autoneg); |
226 | 234 | ||
227 | return result; | 235 | #undef SET_BIT |
228 | } | 236 | } |
229 | 237 | ||
230 | static u32 ethtool_to_mcdi_cap(u32 cap) | 238 | static u32 ethtool_linkset_to_mcdi_cap(const unsigned long *linkset) |
231 | { | 239 | { |
232 | u32 result = 0; | 240 | u32 result = 0; |
233 | 241 | ||
234 | if (cap & SUPPORTED_10baseT_Half) | 242 | #define TEST_BIT(name) test_bit(ETHTOOL_LINK_MODE_ ## name ## _BIT, \ |
243 | linkset) | ||
244 | |||
245 | if (TEST_BIT(10baseT_Half)) | ||
235 | result |= (1 << MC_CMD_PHY_CAP_10HDX_LBN); | 246 | result |= (1 << MC_CMD_PHY_CAP_10HDX_LBN); |
236 | if (cap & SUPPORTED_10baseT_Full) | 247 | if (TEST_BIT(10baseT_Full)) |
237 | result |= (1 << MC_CMD_PHY_CAP_10FDX_LBN); | 248 | result |= (1 << MC_CMD_PHY_CAP_10FDX_LBN); |
238 | if (cap & SUPPORTED_100baseT_Half) | 249 | if (TEST_BIT(100baseT_Half)) |
239 | result |= (1 << MC_CMD_PHY_CAP_100HDX_LBN); | 250 | result |= (1 << MC_CMD_PHY_CAP_100HDX_LBN); |
240 | if (cap & SUPPORTED_100baseT_Full) | 251 | if (TEST_BIT(100baseT_Full)) |
241 | result |= (1 << MC_CMD_PHY_CAP_100FDX_LBN); | 252 | result |= (1 << MC_CMD_PHY_CAP_100FDX_LBN); |
242 | if (cap & SUPPORTED_1000baseT_Half) | 253 | if (TEST_BIT(1000baseT_Half)) |
243 | result |= (1 << MC_CMD_PHY_CAP_1000HDX_LBN); | 254 | result |= (1 << MC_CMD_PHY_CAP_1000HDX_LBN); |
244 | if (cap & (SUPPORTED_1000baseT_Full | SUPPORTED_1000baseKX_Full)) | 255 | if (TEST_BIT(1000baseT_Full) || TEST_BIT(1000baseKX_Full)) |
245 | result |= (1 << MC_CMD_PHY_CAP_1000FDX_LBN); | 256 | result |= (1 << MC_CMD_PHY_CAP_1000FDX_LBN); |
246 | if (cap & (SUPPORTED_10000baseT_Full | SUPPORTED_10000baseKX4_Full)) | 257 | if (TEST_BIT(10000baseT_Full) || TEST_BIT(10000baseKX4_Full)) |
247 | result |= (1 << MC_CMD_PHY_CAP_10000FDX_LBN); | 258 | result |= (1 << MC_CMD_PHY_CAP_10000FDX_LBN); |
248 | if (cap & (SUPPORTED_40000baseCR4_Full | SUPPORTED_40000baseKR4_Full)) | 259 | if (TEST_BIT(40000baseCR4_Full) || TEST_BIT(40000baseKR4_Full)) |
249 | result |= (1 << MC_CMD_PHY_CAP_40000FDX_LBN); | 260 | result |= (1 << MC_CMD_PHY_CAP_40000FDX_LBN); |
250 | if (cap & SUPPORTED_Pause) | 261 | if (TEST_BIT(100000baseCR4_Full)) |
262 | result |= (1 << MC_CMD_PHY_CAP_100000FDX_LBN); | ||
263 | if (TEST_BIT(25000baseCR_Full)) | ||
264 | result |= (1 << MC_CMD_PHY_CAP_25000FDX_LBN); | ||
265 | if (TEST_BIT(50000baseCR2_Full)) | ||
266 | result |= (1 << MC_CMD_PHY_CAP_50000FDX_LBN); | ||
267 | if (TEST_BIT(Pause)) | ||
251 | result |= (1 << MC_CMD_PHY_CAP_PAUSE_LBN); | 268 | result |= (1 << MC_CMD_PHY_CAP_PAUSE_LBN); |
252 | if (cap & SUPPORTED_Asym_Pause) | 269 | if (TEST_BIT(Asym_Pause)) |
253 | result |= (1 << MC_CMD_PHY_CAP_ASYM_LBN); | 270 | result |= (1 << MC_CMD_PHY_CAP_ASYM_LBN); |
254 | if (cap & SUPPORTED_Autoneg) | 271 | if (TEST_BIT(Autoneg)) |
255 | result |= (1 << MC_CMD_PHY_CAP_AN_LBN); | 272 | result |= (1 << MC_CMD_PHY_CAP_AN_LBN); |
256 | 273 | ||
274 | #undef TEST_BIT | ||
275 | |||
257 | return result; | 276 | return result; |
258 | } | 277 | } |
259 | 278 | ||
@@ -285,7 +304,7 @@ static u32 efx_get_mcdi_phy_flags(struct efx_nic *efx) | |||
285 | return flags; | 304 | return flags; |
286 | } | 305 | } |
287 | 306 | ||
288 | static u32 mcdi_to_ethtool_media(u32 media) | 307 | static u8 mcdi_to_ethtool_media(u32 media) |
289 | { | 308 | { |
290 | switch (media) { | 309 | switch (media) { |
291 | case MC_CMD_MEDIA_XAUI: | 310 | case MC_CMD_MEDIA_XAUI: |
@@ -371,8 +390,8 @@ static int efx_mcdi_phy_probe(struct efx_nic *efx) | |||
371 | 390 | ||
372 | caps = MCDI_DWORD(outbuf, GET_LINK_OUT_CAP); | 391 | caps = MCDI_DWORD(outbuf, GET_LINK_OUT_CAP); |
373 | if (caps & (1 << MC_CMD_PHY_CAP_AN_LBN)) | 392 | if (caps & (1 << MC_CMD_PHY_CAP_AN_LBN)) |
374 | efx->link_advertising = | 393 | mcdi_to_ethtool_linkset(phy_data->media, caps, |
375 | mcdi_to_ethtool_cap(phy_data->media, caps); | 394 | efx->link_advertising); |
376 | else | 395 | else |
377 | phy_data->forced_cap = caps; | 396 | phy_data->forced_cap = caps; |
378 | 397 | ||
@@ -435,8 +454,8 @@ fail: | |||
435 | int efx_mcdi_port_reconfigure(struct efx_nic *efx) | 454 | int efx_mcdi_port_reconfigure(struct efx_nic *efx) |
436 | { | 455 | { |
437 | struct efx_mcdi_phy_data *phy_cfg = efx->phy_data; | 456 | struct efx_mcdi_phy_data *phy_cfg = efx->phy_data; |
438 | u32 caps = (efx->link_advertising ? | 457 | u32 caps = (efx->link_advertising[0] ? |
439 | ethtool_to_mcdi_cap(efx->link_advertising) : | 458 | ethtool_linkset_to_mcdi_cap(efx->link_advertising) : |
440 | phy_cfg->forced_cap); | 459 | phy_cfg->forced_cap); |
441 | 460 | ||
442 | return efx_mcdi_set_link(efx, caps, efx_get_mcdi_phy_flags(efx), | 461 | return efx_mcdi_set_link(efx, caps, efx_get_mcdi_phy_flags(efx), |
@@ -509,34 +528,28 @@ static void efx_mcdi_phy_get_link_ksettings(struct efx_nic *efx, | |||
509 | struct efx_mcdi_phy_data *phy_cfg = efx->phy_data; | 528 | struct efx_mcdi_phy_data *phy_cfg = efx->phy_data; |
510 | MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_LINK_OUT_LEN); | 529 | MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_LINK_OUT_LEN); |
511 | int rc; | 530 | int rc; |
512 | u32 supported, advertising, lp_advertising; | ||
513 | 531 | ||
514 | supported = mcdi_to_ethtool_cap(phy_cfg->media, phy_cfg->supported_cap); | ||
515 | advertising = efx->link_advertising; | ||
516 | cmd->base.speed = efx->link_state.speed; | 532 | cmd->base.speed = efx->link_state.speed; |
517 | cmd->base.duplex = efx->link_state.fd; | 533 | cmd->base.duplex = efx->link_state.fd; |
518 | cmd->base.port = mcdi_to_ethtool_media(phy_cfg->media); | 534 | cmd->base.port = mcdi_to_ethtool_media(phy_cfg->media); |
519 | cmd->base.phy_address = phy_cfg->port; | 535 | cmd->base.phy_address = phy_cfg->port; |
520 | cmd->base.autoneg = !!(efx->link_advertising & ADVERTISED_Autoneg); | 536 | cmd->base.autoneg = !!(efx->link_advertising[0] & ADVERTISED_Autoneg); |
521 | cmd->base.mdio_support = (efx->mdio.mode_support & | 537 | cmd->base.mdio_support = (efx->mdio.mode_support & |
522 | (MDIO_SUPPORTS_C45 | MDIO_SUPPORTS_C22)); | 538 | (MDIO_SUPPORTS_C45 | MDIO_SUPPORTS_C22)); |
523 | 539 | ||
524 | ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported, | 540 | mcdi_to_ethtool_linkset(phy_cfg->media, phy_cfg->supported_cap, |
525 | supported); | 541 | cmd->link_modes.supported); |
526 | ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising, | 542 | memcpy(cmd->link_modes.advertising, efx->link_advertising, |
527 | advertising); | 543 | sizeof(__ETHTOOL_DECLARE_LINK_MODE_MASK())); |
528 | 544 | ||
529 | BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN != 0); | 545 | BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN != 0); |
530 | rc = efx_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0, | 546 | rc = efx_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0, |
531 | outbuf, sizeof(outbuf), NULL); | 547 | outbuf, sizeof(outbuf), NULL); |
532 | if (rc) | 548 | if (rc) |
533 | return; | 549 | return; |
534 | lp_advertising = | 550 | mcdi_to_ethtool_linkset(phy_cfg->media, |
535 | mcdi_to_ethtool_cap(phy_cfg->media, | 551 | MCDI_DWORD(outbuf, GET_LINK_OUT_LP_CAP), |
536 | MCDI_DWORD(outbuf, GET_LINK_OUT_LP_CAP)); | 552 | cmd->link_modes.lp_advertising); |
537 | |||
538 | ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.lp_advertising, | ||
539 | lp_advertising); | ||
540 | } | 553 | } |
541 | 554 | ||
542 | static int | 555 | static int |
@@ -546,29 +559,28 @@ efx_mcdi_phy_set_link_ksettings(struct efx_nic *efx, | |||
546 | struct efx_mcdi_phy_data *phy_cfg = efx->phy_data; | 559 | struct efx_mcdi_phy_data *phy_cfg = efx->phy_data; |
547 | u32 caps; | 560 | u32 caps; |
548 | int rc; | 561 | int rc; |
549 | u32 advertising; | ||
550 | |||
551 | ethtool_convert_link_mode_to_legacy_u32(&advertising, | ||
552 | cmd->link_modes.advertising); | ||
553 | 562 | ||
554 | if (cmd->base.autoneg) { | 563 | if (cmd->base.autoneg) { |
555 | caps = (ethtool_to_mcdi_cap(advertising) | | 564 | caps = (ethtool_linkset_to_mcdi_cap(cmd->link_modes.advertising) | |
556 | 1 << MC_CMD_PHY_CAP_AN_LBN); | 565 | 1 << MC_CMD_PHY_CAP_AN_LBN); |
557 | } else if (cmd->base.duplex) { | 566 | } else if (cmd->base.duplex) { |
558 | switch (cmd->base.speed) { | 567 | switch (cmd->base.speed) { |
559 | case 10: caps = 1 << MC_CMD_PHY_CAP_10FDX_LBN; break; | 568 | case 10: caps = 1 << MC_CMD_PHY_CAP_10FDX_LBN; break; |
560 | case 100: caps = 1 << MC_CMD_PHY_CAP_100FDX_LBN; break; | 569 | case 100: caps = 1 << MC_CMD_PHY_CAP_100FDX_LBN; break; |
561 | case 1000: caps = 1 << MC_CMD_PHY_CAP_1000FDX_LBN; break; | 570 | case 1000: caps = 1 << MC_CMD_PHY_CAP_1000FDX_LBN; break; |
562 | case 10000: caps = 1 << MC_CMD_PHY_CAP_10000FDX_LBN; break; | 571 | case 10000: caps = 1 << MC_CMD_PHY_CAP_10000FDX_LBN; break; |
563 | case 40000: caps = 1 << MC_CMD_PHY_CAP_40000FDX_LBN; break; | 572 | case 40000: caps = 1 << MC_CMD_PHY_CAP_40000FDX_LBN; break; |
564 | default: return -EINVAL; | 573 | case 100000: caps = 1 << MC_CMD_PHY_CAP_100000FDX_LBN; break; |
574 | case 25000: caps = 1 << MC_CMD_PHY_CAP_25000FDX_LBN; break; | ||
575 | case 50000: caps = 1 << MC_CMD_PHY_CAP_50000FDX_LBN; break; | ||
576 | default: return -EINVAL; | ||
565 | } | 577 | } |
566 | } else { | 578 | } else { |
567 | switch (cmd->base.speed) { | 579 | switch (cmd->base.speed) { |
568 | case 10: caps = 1 << MC_CMD_PHY_CAP_10HDX_LBN; break; | 580 | case 10: caps = 1 << MC_CMD_PHY_CAP_10HDX_LBN; break; |
569 | case 100: caps = 1 << MC_CMD_PHY_CAP_100HDX_LBN; break; | 581 | case 100: caps = 1 << MC_CMD_PHY_CAP_100HDX_LBN; break; |
570 | case 1000: caps = 1 << MC_CMD_PHY_CAP_1000HDX_LBN; break; | 582 | case 1000: caps = 1 << MC_CMD_PHY_CAP_1000HDX_LBN; break; |
571 | default: return -EINVAL; | 583 | default: return -EINVAL; |
572 | } | 584 | } |
573 | } | 585 | } |
574 | 586 | ||
@@ -578,11 +590,10 @@ efx_mcdi_phy_set_link_ksettings(struct efx_nic *efx, | |||
578 | return rc; | 590 | return rc; |
579 | 591 | ||
580 | if (cmd->base.autoneg) { | 592 | if (cmd->base.autoneg) { |
581 | efx_link_set_advertising( | 593 | efx_link_set_advertising(efx, cmd->link_modes.advertising); |
582 | efx, advertising | ADVERTISED_Autoneg); | ||
583 | phy_cfg->forced_cap = 0; | 594 | phy_cfg->forced_cap = 0; |
584 | } else { | 595 | } else { |
585 | efx_link_set_advertising(efx, 0); | 596 | efx_link_clear_advertising(efx); |
586 | phy_cfg->forced_cap = caps; | 597 | phy_cfg->forced_cap = caps; |
587 | } | 598 | } |
588 | return 0; | 599 | return 0; |
@@ -985,6 +996,9 @@ static unsigned int efx_mcdi_event_link_speed[] = { | |||
985 | [MCDI_EVENT_LINKCHANGE_SPEED_1G] = 1000, | 996 | [MCDI_EVENT_LINKCHANGE_SPEED_1G] = 1000, |
986 | [MCDI_EVENT_LINKCHANGE_SPEED_10G] = 10000, | 997 | [MCDI_EVENT_LINKCHANGE_SPEED_10G] = 10000, |
987 | [MCDI_EVENT_LINKCHANGE_SPEED_40G] = 40000, | 998 | [MCDI_EVENT_LINKCHANGE_SPEED_40G] = 40000, |
999 | [MCDI_EVENT_LINKCHANGE_SPEED_25G] = 25000, | ||
1000 | [MCDI_EVENT_LINKCHANGE_SPEED_50G] = 50000, | ||
1001 | [MCDI_EVENT_LINKCHANGE_SPEED_100G] = 100000, | ||
988 | }; | 1002 | }; |
989 | 1003 | ||
990 | void efx_mcdi_process_link_change(struct efx_nic *efx, efx_qword_t *ev) | 1004 | void efx_mcdi_process_link_change(struct efx_nic *efx, efx_qword_t *ev) |
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index 4cedc5c4c6d9..3dd42f3136fe 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h | |||
@@ -937,7 +937,7 @@ struct efx_nic { | |||
937 | unsigned int mdio_bus; | 937 | unsigned int mdio_bus; |
938 | enum efx_phy_mode phy_mode; | 938 | enum efx_phy_mode phy_mode; |
939 | 939 | ||
940 | u32 link_advertising; | 940 | __ETHTOOL_DECLARE_LINK_MODE_MASK(link_advertising); |
941 | struct efx_link_state link_state; | 941 | struct efx_link_state link_state; |
942 | unsigned int n_link_state_changes; | 942 | unsigned int n_link_state_changes; |
943 | 943 | ||