aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sfc
diff options
context:
space:
mode:
authorSteve Hodgson <shodgson@solarflare.com>2009-11-28 00:34:05 -0500
committerDavid S. Miller <davem@davemloft.net>2009-11-29 02:58:50 -0500
commitfdaa9aed21c8c8b529f3c94a5ffa138bf3360b75 (patch)
tree6db7fd76481b3f87f0f4e94e1bd55c0624fba296 /drivers/net/sfc
parent5e7565930524410f097f5b04f8aba663089a6ffc (diff)
sfc: Simplify PHY polling
Falcon can generate events for LASI interrupts from the PHY, but in practice we have never implemented this in reference designs. Instead we have polled, inserted the appropriate events, and then handled the events later. This is a waste of time and code. Instead, make PHY poll functions update the link state synchronously and report whether it changed. We can still make use of the LASI registers as a shortcut on the SFT9001. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/sfc')
-rw-r--r--drivers/net/sfc/efx.c35
-rw-r--r--drivers/net/sfc/efx.h3
-rw-r--r--drivers/net/sfc/falcon.c69
-rw-r--r--drivers/net/sfc/falcon.h1
-rw-r--r--drivers/net/sfc/net_driver.h24
-rw-r--r--drivers/net/sfc/qt202x_phy.c26
-rw-r--r--drivers/net/sfc/tenxpress.c69
7 files changed, 103 insertions, 124 deletions
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index 1009d1eeba82..b5a7e91590dc 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -583,7 +583,7 @@ void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue, int delay)
583 * netif_carrier_on/off) of the link status, and also maintains the 583 * netif_carrier_on/off) of the link status, and also maintains the
584 * link status's stop on the port's TX queue. 584 * link status's stop on the port's TX queue.
585 */ 585 */
586static void efx_link_status_changed(struct efx_nic *efx) 586void efx_link_status_changed(struct efx_nic *efx)
587{ 587{
588 struct efx_link_state *link_state = &efx->link_state; 588 struct efx_link_state *link_state = &efx->link_state;
589 589
@@ -675,19 +675,6 @@ void efx_reconfigure_port(struct efx_nic *efx)
675 mutex_unlock(&efx->mac_lock); 675 mutex_unlock(&efx->mac_lock);
676} 676}
677 677
678/* Asynchronous efx_reconfigure_port work item. To speed up efx_flush_all()
679 * we don't efx_reconfigure_port() if the port is disabled. Care is taken
680 * in efx_stop_all() and efx_start_port() to prevent PHY events being lost */
681static void efx_phy_work(struct work_struct *data)
682{
683 struct efx_nic *efx = container_of(data, struct efx_nic, phy_work);
684
685 mutex_lock(&efx->mac_lock);
686 if (efx->port_enabled)
687 __efx_reconfigure_port(efx);
688 mutex_unlock(&efx->mac_lock);
689}
690
691/* Asynchronous work item for changing MAC promiscuity and multicast 678/* Asynchronous work item for changing MAC promiscuity and multicast
692 * hash. Avoid a drain/rx_ingress enable by reconfiguring the current 679 * hash. Avoid a drain/rx_ingress enable by reconfiguring the current
693 * MAC directly. */ 680 * MAC directly. */
@@ -768,9 +755,6 @@ fail1:
768 return rc; 755 return rc;
769} 756}
770 757
771/* Allow efx_reconfigure_port() to be scheduled, and close the window
772 * between efx_stop_port and efx_flush_all whereby a previously scheduled
773 * efx_phy_work()/efx_mac_work() may have been cancelled */
774static void efx_start_port(struct efx_nic *efx) 758static void efx_start_port(struct efx_nic *efx)
775{ 759{
776 EFX_LOG(efx, "start port\n"); 760 EFX_LOG(efx, "start port\n");
@@ -787,10 +771,7 @@ static void efx_start_port(struct efx_nic *efx)
787 mutex_unlock(&efx->mac_lock); 771 mutex_unlock(&efx->mac_lock);
788} 772}
789 773
790/* Prevent efx_phy_work, efx_mac_work, and efx_monitor() from executing, 774/* Prevent efx_mac_work() and efx_monitor() from working */
791 * and efx_set_multicast_list() from scheduling efx_phy_work. efx_phy_work
792 * and efx_mac_work may still be scheduled via NAPI processing until
793 * efx_flush_all() is called */
794static void efx_stop_port(struct efx_nic *efx) 775static void efx_stop_port(struct efx_nic *efx)
795{ 776{
796 EFX_LOG(efx, "stop port\n"); 777 EFX_LOG(efx, "stop port\n");
@@ -1188,8 +1169,6 @@ static void efx_flush_all(struct efx_nic *efx)
1188 1169
1189 /* Stop scheduled port reconfigurations */ 1170 /* Stop scheduled port reconfigurations */
1190 cancel_work_sync(&efx->mac_work); 1171 cancel_work_sync(&efx->mac_work);
1191 cancel_work_sync(&efx->phy_work);
1192
1193} 1172}
1194 1173
1195/* Quiesce hardware and software without bringing the link down. 1174/* Quiesce hardware and software without bringing the link down.
@@ -1227,7 +1206,7 @@ static void efx_stop_all(struct efx_nic *efx)
1227 * window to loose phy events */ 1206 * window to loose phy events */
1228 efx_stop_port(efx); 1207 efx_stop_port(efx);
1229 1208
1230 /* Flush efx_phy_work, efx_mac_work, refill_workqueue, monitor_work */ 1209 /* Flush efx_mac_work(), refill_workqueue, monitor_work */
1231 efx_flush_all(efx); 1210 efx_flush_all(efx);
1232 1211
1233 /* Isolate the MAC from the TX and RX engines, so that queue 1212 /* Isolate the MAC from the TX and RX engines, so that queue
@@ -1907,6 +1886,10 @@ void efx_port_dummy_op_void(struct efx_nic *efx) {}
1907void efx_port_dummy_op_set_id_led(struct efx_nic *efx, enum efx_led_mode mode) 1886void efx_port_dummy_op_set_id_led(struct efx_nic *efx, enum efx_led_mode mode)
1908{ 1887{
1909} 1888}
1889bool efx_port_dummy_op_poll(struct efx_nic *efx)
1890{
1891 return false;
1892}
1910 1893
1911static struct efx_mac_operations efx_dummy_mac_operations = { 1894static struct efx_mac_operations efx_dummy_mac_operations = {
1912 .reconfigure = efx_port_dummy_op_void, 1895 .reconfigure = efx_port_dummy_op_void,
@@ -1915,9 +1898,8 @@ static struct efx_mac_operations efx_dummy_mac_operations = {
1915static struct efx_phy_operations efx_dummy_phy_operations = { 1898static struct efx_phy_operations efx_dummy_phy_operations = {
1916 .init = efx_port_dummy_op_int, 1899 .init = efx_port_dummy_op_int,
1917 .reconfigure = efx_port_dummy_op_void, 1900 .reconfigure = efx_port_dummy_op_void,
1918 .poll = efx_port_dummy_op_void, 1901 .poll = efx_port_dummy_op_poll,
1919 .fini = efx_port_dummy_op_void, 1902 .fini = efx_port_dummy_op_void,
1920 .clear_interrupt = efx_port_dummy_op_void,
1921}; 1903};
1922 1904
1923/************************************************************************** 1905/**************************************************************************
@@ -1957,7 +1939,6 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,
1957 efx->mac_op = &efx_dummy_mac_operations; 1939 efx->mac_op = &efx_dummy_mac_operations;
1958 efx->phy_op = &efx_dummy_phy_operations; 1940 efx->phy_op = &efx_dummy_phy_operations;
1959 efx->mdio.dev = net_dev; 1941 efx->mdio.dev = net_dev;
1960 INIT_WORK(&efx->phy_work, efx_phy_work);
1961 INIT_WORK(&efx->mac_work, efx_mac_work); 1942 INIT_WORK(&efx->mac_work, efx_mac_work);
1962 atomic_set(&efx->netif_stop_count, 1); 1943 atomic_set(&efx->netif_stop_count, 1);
1963 1944
diff --git a/drivers/net/sfc/efx.h b/drivers/net/sfc/efx.h
index 01b93f93d316..15edda2a2242 100644
--- a/drivers/net/sfc/efx.h
+++ b/drivers/net/sfc/efx.h
@@ -90,6 +90,7 @@ extern int efx_port_dummy_op_int(struct efx_nic *efx);
90extern void efx_port_dummy_op_void(struct efx_nic *efx); 90extern void efx_port_dummy_op_void(struct efx_nic *efx);
91extern void 91extern void
92efx_port_dummy_op_set_id_led(struct efx_nic *efx, enum efx_led_mode mode); 92efx_port_dummy_op_set_id_led(struct efx_nic *efx, enum efx_led_mode mode);
93extern bool efx_port_dummy_op_poll(struct efx_nic *efx);
93 94
94/* MTD */ 95/* MTD */
95#ifdef CONFIG_SFC_MTD 96#ifdef CONFIG_SFC_MTD
@@ -113,4 +114,6 @@ static inline void efx_schedule_channel(struct efx_channel *channel)
113 napi_schedule(&channel->napi_str); 114 napi_schedule(&channel->napi_str);
114} 115}
115 116
117extern void efx_link_status_changed(struct efx_nic *efx);
118
116#endif /* EFX_EFX_H */ 119#endif /* EFX_EFX_H */
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c
index e26043eb01b5..e16faad70283 100644
--- a/drivers/net/sfc/falcon.c
+++ b/drivers/net/sfc/falcon.c
@@ -893,8 +893,7 @@ static void falcon_handle_global_event(struct efx_channel *channel,
893 if (EFX_QWORD_FIELD(*event, FSF_AB_GLB_EV_G_PHY0_INTR) || 893 if (EFX_QWORD_FIELD(*event, FSF_AB_GLB_EV_G_PHY0_INTR) ||
894 EFX_QWORD_FIELD(*event, FSF_AB_GLB_EV_XG_PHY0_INTR) || 894 EFX_QWORD_FIELD(*event, FSF_AB_GLB_EV_XG_PHY0_INTR) ||
895 EFX_QWORD_FIELD(*event, FSF_AB_GLB_EV_XFP_PHY0_INTR)) { 895 EFX_QWORD_FIELD(*event, FSF_AB_GLB_EV_XFP_PHY0_INTR)) {
896 efx->phy_op->clear_interrupt(efx); 896 /* Ignored */
897 queue_work(efx->workqueue, &efx->phy_work);
898 handled = true; 897 handled = true;
899 } 898 }
900 899
@@ -1140,20 +1139,6 @@ void falcon_generate_test_event(struct efx_channel *channel, unsigned int magic)
1140 falcon_generate_event(channel, &test_event); 1139 falcon_generate_event(channel, &test_event);
1141} 1140}
1142 1141
1143void falcon_sim_phy_event(struct efx_nic *efx)
1144{
1145 efx_qword_t phy_event;
1146
1147 EFX_POPULATE_QWORD_1(phy_event, FSF_AZ_EV_CODE,
1148 FSE_AZ_EV_CODE_GLOBAL_EV);
1149 if (EFX_IS10G(efx))
1150 EFX_SET_QWORD_FIELD(phy_event, FSF_AB_GLB_EV_XG_PHY0_INTR, 1);
1151 else
1152 EFX_SET_QWORD_FIELD(phy_event, FSF_AB_GLB_EV_G_PHY0_INTR, 1);
1153
1154 falcon_generate_event(&efx->channel[0], &phy_event);
1155}
1156
1157/************************************************************************** 1142/**************************************************************************
1158 * 1143 *
1159 * Flush handling 1144 * Flush handling
@@ -2063,6 +2048,25 @@ static void falcon_stats_timer_func(unsigned long context)
2063 spin_unlock(&efx->stats_lock); 2048 spin_unlock(&efx->stats_lock);
2064} 2049}
2065 2050
2051static bool falcon_loopback_link_poll(struct efx_nic *efx)
2052{
2053 struct efx_link_state old_state = efx->link_state;
2054
2055 WARN_ON(!mutex_is_locked(&efx->mac_lock));
2056 WARN_ON(!LOOPBACK_INTERNAL(efx));
2057
2058 efx->link_state.fd = true;
2059 efx->link_state.fc = efx->wanted_fc;
2060 efx->link_state.up = true;
2061
2062 if (efx->loopback_mode == LOOPBACK_GMAC)
2063 efx->link_state.speed = 1000;
2064 else
2065 efx->link_state.speed = 10000;
2066
2067 return !efx_link_state_equal(&efx->link_state, &old_state);
2068}
2069
2066/************************************************************************** 2070/**************************************************************************
2067 * 2071 *
2068 * PHY access via GMII 2072 * PHY access via GMII
@@ -2225,15 +2229,6 @@ int falcon_switch_mac(struct efx_nic *efx)
2225 /* Don't try to fetch MAC stats while we're switching MACs */ 2229 /* Don't try to fetch MAC stats while we're switching MACs */
2226 falcon_stop_nic_stats(efx); 2230 falcon_stop_nic_stats(efx);
2227 2231
2228 /* Internal loopbacks override the phy speed setting */
2229 if (efx->loopback_mode == LOOPBACK_GMAC) {
2230 efx->link_state.speed = 1000;
2231 efx->link_state.fd = true;
2232 } else if (LOOPBACK_INTERNAL(efx)) {
2233 efx->link_state.speed = 10000;
2234 efx->link_state.fd = true;
2235 }
2236
2237 WARN_ON(!mutex_is_locked(&efx->mac_lock)); 2232 WARN_ON(!mutex_is_locked(&efx->mac_lock));
2238 efx->mac_op = (EFX_IS10G(efx) ? 2233 efx->mac_op = (EFX_IS10G(efx) ?
2239 &falcon_xmac_operations : &falcon_gmac_operations); 2234 &falcon_xmac_operations : &falcon_gmac_operations);
@@ -2610,16 +2605,36 @@ fail5:
2610 2605
2611void falcon_monitor(struct efx_nic *efx) 2606void falcon_monitor(struct efx_nic *efx)
2612{ 2607{
2608 bool link_changed;
2613 int rc; 2609 int rc;
2614 2610
2611 BUG_ON(!mutex_is_locked(&efx->mac_lock));
2612
2615 rc = falcon_board(efx)->type->monitor(efx); 2613 rc = falcon_board(efx)->type->monitor(efx);
2616 if (rc) { 2614 if (rc) {
2617 EFX_ERR(efx, "Board sensor %s; shutting down PHY\n", 2615 EFX_ERR(efx, "Board sensor %s; shutting down PHY\n",
2618 (rc == -ERANGE) ? "reported fault" : "failed"); 2616 (rc == -ERANGE) ? "reported fault" : "failed");
2619 efx->phy_mode |= PHY_MODE_LOW_POWER; 2617 efx->phy_mode |= PHY_MODE_LOW_POWER;
2620 falcon_sim_phy_event(efx); 2618 __efx_reconfigure_port(efx);
2621 } 2619 }
2622 efx->phy_op->poll(efx); 2620
2621 if (LOOPBACK_INTERNAL(efx))
2622 link_changed = falcon_loopback_link_poll(efx);
2623 else
2624 link_changed = efx->phy_op->poll(efx);
2625
2626 if (link_changed) {
2627 falcon_stop_nic_stats(efx);
2628 falcon_deconfigure_mac_wrapper(efx);
2629
2630 falcon_switch_mac(efx);
2631 efx->mac_op->reconfigure(efx);
2632
2633 falcon_start_nic_stats(efx);
2634
2635 efx_link_status_changed(efx);
2636 }
2637
2623 if (EFX_IS10G(efx)) 2638 if (EFX_IS10G(efx))
2624 falcon_poll_xmac(efx); 2639 falcon_poll_xmac(efx);
2625} 2640}
diff --git a/drivers/net/sfc/falcon.h b/drivers/net/sfc/falcon.h
index c70bb084216f..a561f6758bc6 100644
--- a/drivers/net/sfc/falcon.h
+++ b/drivers/net/sfc/falcon.h
@@ -145,7 +145,6 @@ extern int falcon_init_interrupt(struct efx_nic *efx);
145extern void falcon_enable_interrupts(struct efx_nic *efx); 145extern void falcon_enable_interrupts(struct efx_nic *efx);
146extern void falcon_generate_test_event(struct efx_channel *channel, 146extern void falcon_generate_test_event(struct efx_channel *channel,
147 unsigned int magic); 147 unsigned int magic);
148extern void falcon_sim_phy_event(struct efx_nic *efx);
149extern void falcon_generate_interrupt(struct efx_nic *efx); 148extern void falcon_generate_interrupt(struct efx_nic *efx);
150extern void falcon_set_int_moderation(struct efx_channel *channel); 149extern void falcon_set_int_moderation(struct efx_channel *channel);
151extern void falcon_disable_interrupts(struct efx_nic *efx); 150extern void falcon_disable_interrupts(struct efx_nic *efx);
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h
index ead1c982365b..fb9327c5ea57 100644
--- a/drivers/net/sfc/net_driver.h
+++ b/drivers/net/sfc/net_driver.h
@@ -503,6 +503,13 @@ struct efx_link_state {
503 unsigned int speed; 503 unsigned int speed;
504}; 504};
505 505
506static inline bool efx_link_state_equal(const struct efx_link_state *left,
507 const struct efx_link_state *right)
508{
509 return left->up == right->up && left->fd == right->fd &&
510 left->fc == right->fc && left->speed == right->speed;
511}
512
506/** 513/**
507 * struct efx_mac_operations - Efx MAC operations table 514 * struct efx_mac_operations - Efx MAC operations table
508 * @reconfigure: Reconfigure MAC. Serialised by the mac_lock 515 * @reconfigure: Reconfigure MAC. Serialised by the mac_lock
@@ -520,8 +527,8 @@ struct efx_mac_operations {
520 * @init: Initialise PHY 527 * @init: Initialise PHY
521 * @fini: Shut down PHY 528 * @fini: Shut down PHY
522 * @reconfigure: Reconfigure PHY (e.g. for new link parameters) 529 * @reconfigure: Reconfigure PHY (e.g. for new link parameters)
523 * @clear_interrupt: Clear down interrupt 530 * @poll: Update @link_state and report whether it changed.
524 * @poll: Poll for hardware state. Serialised by the mac_lock. 531 * Serialised by the mac_lock.
525 * @get_settings: Get ethtool settings. Serialised by the mac_lock. 532 * @get_settings: Get ethtool settings. Serialised by the mac_lock.
526 * @set_settings: Set ethtool settings. Serialised by the mac_lock. 533 * @set_settings: Set ethtool settings. Serialised by the mac_lock.
527 * @set_npage_adv: Set abilities advertised in (Extended) Next Page 534 * @set_npage_adv: Set abilities advertised in (Extended) Next Page
@@ -538,8 +545,7 @@ struct efx_phy_operations {
538 int (*init) (struct efx_nic *efx); 545 int (*init) (struct efx_nic *efx);
539 void (*fini) (struct efx_nic *efx); 546 void (*fini) (struct efx_nic *efx);
540 void (*reconfigure) (struct efx_nic *efx); 547 void (*reconfigure) (struct efx_nic *efx);
541 void (*clear_interrupt) (struct efx_nic *efx); 548 bool (*poll) (struct efx_nic *efx);
542 void (*poll) (struct efx_nic *efx);
543 void (*get_settings) (struct efx_nic *efx, 549 void (*get_settings) (struct efx_nic *efx,
544 struct ethtool_cmd *ecmd); 550 struct ethtool_cmd *ecmd);
545 int (*set_settings) (struct efx_nic *efx, 551 int (*set_settings) (struct efx_nic *efx,
@@ -700,10 +706,10 @@ union efx_multicast_hash {
700 * @mac_lock: MAC access lock. Protects @port_enabled, @phy_mode, 706 * @mac_lock: MAC access lock. Protects @port_enabled, @phy_mode,
701 * @port_inhibited, efx_monitor() and efx_reconfigure_port() 707 * @port_inhibited, efx_monitor() and efx_reconfigure_port()
702 * @port_enabled: Port enabled indicator. 708 * @port_enabled: Port enabled indicator.
703 * Serialises efx_stop_all(), efx_start_all(), efx_monitor(), 709 * Serialises efx_stop_all(), efx_start_all(), efx_monitor() and
704 * efx_phy_work(), and efx_mac_work() with kernel interfaces. Safe to read 710 * efx_mac_work() with kernel interfaces. Safe to read under any
705 * under any one of the rtnl_lock, mac_lock, or netif_tx_lock, but all 711 * one of the rtnl_lock, mac_lock, or netif_tx_lock, but all three must
706 * three must be held to modify it. 712 * be held to modify it.
707 * @port_inhibited: If set, the netif_carrier is always off. Hold the mac_lock 713 * @port_inhibited: If set, the netif_carrier is always off. Hold the mac_lock
708 * @port_initialized: Port initialized? 714 * @port_initialized: Port initialized?
709 * @net_dev: Operating system network device. Consider holding the rtnl lock 715 * @net_dev: Operating system network device. Consider holding the rtnl lock
@@ -729,7 +735,6 @@ union efx_multicast_hash {
729 * @promiscuous: Promiscuous flag. Protected by netif_tx_lock. 735 * @promiscuous: Promiscuous flag. Protected by netif_tx_lock.
730 * @multicast_hash: Multicast hash table 736 * @multicast_hash: Multicast hash table
731 * @wanted_fc: Wanted flow control flags 737 * @wanted_fc: Wanted flow control flags
732 * @phy_work: work item for dealing with PHY events
733 * @mac_work: Work item for changing MAC promiscuity and multicast hash 738 * @mac_work: Work item for changing MAC promiscuity and multicast hash
734 * @loopback_mode: Loopback status 739 * @loopback_mode: Loopback status
735 * @loopback_modes: Supported loopback mode bitmask 740 * @loopback_modes: Supported loopback mode bitmask
@@ -802,7 +807,6 @@ struct efx_nic {
802 807
803 enum phy_type phy_type; 808 enum phy_type phy_type;
804 spinlock_t phy_lock; 809 spinlock_t phy_lock;
805 struct work_struct phy_work;
806 struct efx_phy_operations *phy_op; 810 struct efx_phy_operations *phy_op;
807 void *phy_data; 811 void *phy_data;
808 struct mdio_if_info mdio; 812 struct mdio_if_info mdio;
diff --git a/drivers/net/sfc/qt202x_phy.c b/drivers/net/sfc/qt202x_phy.c
index f9c354e9fc3c..1b174c3e6c12 100644
--- a/drivers/net/sfc/qt202x_phy.c
+++ b/drivers/net/sfc/qt202x_phy.c
@@ -167,29 +167,26 @@ static int qt202x_phy_init(struct efx_nic *efx)
167 return rc; 167 return rc;
168} 168}
169 169
170static void qt202x_phy_clear_interrupt(struct efx_nic *efx)
171{
172 /* Read to clear link status alarm */
173 efx_mdio_read(efx, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_STAT);
174}
175
176static int qt202x_link_ok(struct efx_nic *efx) 170static int qt202x_link_ok(struct efx_nic *efx)
177{ 171{
178 return efx_mdio_links_ok(efx, QT202X_REQUIRED_DEVS); 172 return efx_mdio_links_ok(efx, QT202X_REQUIRED_DEVS);
179} 173}
180 174
181static void qt202x_phy_poll(struct efx_nic *efx) 175static bool qt202x_phy_poll(struct efx_nic *efx)
182{ 176{
183 int link_up = qt202x_link_ok(efx); 177 bool was_up = efx->link_state.up;
184 /* Simulate a PHY event if link state has changed */ 178
185 if (link_up != efx->link_state.up) 179 efx->link_state.up = qt202x_link_ok(efx);
186 falcon_sim_phy_event(efx); 180 efx->link_state.speed = 10000;
181 efx->link_state.fd = true;
182 efx->link_state.fc = efx->wanted_fc;
183
184 return efx->link_state.up != was_up;
187} 185}
188 186
189static void qt202x_phy_reconfigure(struct efx_nic *efx) 187static void qt202x_phy_reconfigure(struct efx_nic *efx)
190{ 188{
191 struct qt202x_phy_data *phy_data = efx->phy_data; 189 struct qt202x_phy_data *phy_data = efx->phy_data;
192 struct efx_link_state *link_state = &efx->link_state;
193 190
194 if (efx->phy_type == PHY_TYPE_QT2025C) { 191 if (efx->phy_type == PHY_TYPE_QT2025C) {
195 /* There are several different register bits which can 192 /* There are several different register bits which can
@@ -216,10 +213,6 @@ static void qt202x_phy_reconfigure(struct efx_nic *efx)
216 efx_mdio_phy_reconfigure(efx); 213 efx_mdio_phy_reconfigure(efx);
217 214
218 phy_data->phy_mode = efx->phy_mode; 215 phy_data->phy_mode = efx->phy_mode;
219 link_state->up = qt202x_link_ok(efx);
220 link_state->speed = 10000;
221 link_state->fd = true;
222 link_state->fc = efx->wanted_fc;
223} 216}
224 217
225static void qt202x_phy_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) 218static void qt202x_phy_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
@@ -240,7 +233,6 @@ struct efx_phy_operations falcon_qt202x_phy_ops = {
240 .reconfigure = qt202x_phy_reconfigure, 233 .reconfigure = qt202x_phy_reconfigure,
241 .poll = qt202x_phy_poll, 234 .poll = qt202x_phy_poll,
242 .fini = qt202x_phy_fini, 235 .fini = qt202x_phy_fini,
243 .clear_interrupt = qt202x_phy_clear_interrupt,
244 .get_settings = qt202x_phy_get_settings, 236 .get_settings = qt202x_phy_get_settings,
245 .set_settings = efx_mdio_set_settings, 237 .set_settings = efx_mdio_set_settings,
246 .mmds = QT202X_REQUIRED_DEVS, 238 .mmds = QT202X_REQUIRED_DEVS,
diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c
index e6232fe26072..1bd79650a00f 100644
--- a/drivers/net/sfc/tenxpress.c
+++ b/drivers/net/sfc/tenxpress.c
@@ -503,7 +503,6 @@ static void tenxpress_low_power(struct efx_nic *efx)
503static void tenxpress_phy_reconfigure(struct efx_nic *efx) 503static void tenxpress_phy_reconfigure(struct efx_nic *efx)
504{ 504{
505 struct tenxpress_phy_data *phy_data = efx->phy_data; 505 struct tenxpress_phy_data *phy_data = efx->phy_data;
506 struct efx_link_state *link_state = &efx->link_state;
507 struct ethtool_cmd ecmd; 506 struct ethtool_cmd ecmd;
508 bool phy_mode_change, loop_reset; 507 bool phy_mode_change, loop_reset;
509 508
@@ -544,53 +543,41 @@ static void tenxpress_phy_reconfigure(struct efx_nic *efx)
544 543
545 phy_data->loopback_mode = efx->loopback_mode; 544 phy_data->loopback_mode = efx->loopback_mode;
546 phy_data->phy_mode = efx->phy_mode; 545 phy_data->phy_mode = efx->phy_mode;
547
548 if (efx->phy_type == PHY_TYPE_SFX7101) {
549 link_state->speed = 10000;
550 link_state->fd = true;
551 link_state->up = sfx7101_link_ok(efx);
552 } else {
553 efx->phy_op->get_settings(efx, &ecmd);
554 link_state->speed = ecmd.speed;
555 link_state->fd = ecmd.duplex == DUPLEX_FULL;
556 link_state->up = sft9001_link_ok(efx, &ecmd);
557 }
558 link_state->fc = efx_mdio_get_pause(efx);
559} 546}
560 547
561/* Poll PHY for interrupt */ 548static void
562static void tenxpress_phy_poll(struct efx_nic *efx) 549tenxpress_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd);
550
551/* Poll for link state changes */
552static bool tenxpress_phy_poll(struct efx_nic *efx)
563{ 553{
564 struct tenxpress_phy_data *phy_data = efx->phy_data; 554 struct efx_link_state old_state = efx->link_state;
565 struct efx_link_state *link_state = &efx->link_state;
566 bool change = false;
567 555
568 if (efx->phy_type == PHY_TYPE_SFX7101) { 556 if (efx->phy_type == PHY_TYPE_SFX7101) {
569 bool link_ok = sfx7101_link_ok(efx); 557 efx->link_state.up = sfx7101_link_ok(efx);
570 if (link_ok != link_state->up) { 558 efx->link_state.speed = 10000;
571 change = true; 559 efx->link_state.fd = true;
572 } else { 560 efx->link_state.fc = efx_mdio_get_pause(efx);
573 unsigned int link_fc = efx_mdio_get_pause(efx); 561
574 if (link_fc != link_state->fc) 562 sfx7101_check_bad_lp(efx, efx->link_state.up);
575 change = true;
576 }
577 sfx7101_check_bad_lp(efx, link_ok);
578 } else if (efx->loopback_mode) {
579 bool link_ok = sft9001_link_ok(efx, NULL);
580 if (link_ok != link_state->up)
581 change = true;
582 } else { 563 } else {
583 int status = efx_mdio_read(efx, MDIO_MMD_PMAPMD, 564 struct ethtool_cmd ecmd;
584 MDIO_PMA_LASI_STAT);
585 if (status & MDIO_PMA_LASI_LSALARM)
586 change = true;
587 }
588 565
589 if (change) 566 /* Check the LASI alarm first */
590 falcon_sim_phy_event(efx); 567 if (efx->loopback_mode == LOOPBACK_NONE &&
568 !(efx_mdio_read(efx, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_STAT) &
569 MDIO_PMA_LASI_LSALARM))
570 return false;
591 571
592 if (phy_data->phy_mode != PHY_MODE_NORMAL) 572 tenxpress_get_settings(efx, &ecmd);
593 return; 573
574 efx->link_state.up = sft9001_link_ok(efx, &ecmd);
575 efx->link_state.speed = ecmd.speed;
576 efx->link_state.fd = (ecmd.duplex == DUPLEX_FULL);
577 efx->link_state.fc = efx_mdio_get_pause(efx);
578 }
579
580 return !efx_link_state_equal(&efx->link_state, &old_state);
594} 581}
595 582
596static void tenxpress_phy_fini(struct efx_nic *efx) 583static void tenxpress_phy_fini(struct efx_nic *efx)
@@ -818,7 +805,6 @@ struct efx_phy_operations falcon_sfx7101_phy_ops = {
818 .reconfigure = tenxpress_phy_reconfigure, 805 .reconfigure = tenxpress_phy_reconfigure,
819 .poll = tenxpress_phy_poll, 806 .poll = tenxpress_phy_poll,
820 .fini = tenxpress_phy_fini, 807 .fini = tenxpress_phy_fini,
821 .clear_interrupt = efx_port_dummy_op_void,
822 .get_settings = tenxpress_get_settings, 808 .get_settings = tenxpress_get_settings,
823 .set_settings = tenxpress_set_settings, 809 .set_settings = tenxpress_set_settings,
824 .set_npage_adv = sfx7101_set_npage_adv, 810 .set_npage_adv = sfx7101_set_npage_adv,
@@ -835,7 +821,6 @@ struct efx_phy_operations falcon_sft9001_phy_ops = {
835 .reconfigure = tenxpress_phy_reconfigure, 821 .reconfigure = tenxpress_phy_reconfigure,
836 .poll = tenxpress_phy_poll, 822 .poll = tenxpress_phy_poll,
837 .fini = tenxpress_phy_fini, 823 .fini = tenxpress_phy_fini,
838 .clear_interrupt = efx_port_dummy_op_void,
839 .get_settings = tenxpress_get_settings, 824 .get_settings = tenxpress_get_settings,
840 .set_settings = tenxpress_set_settings, 825 .set_settings = tenxpress_set_settings,
841 .set_npage_adv = sft9001_set_npage_adv, 826 .set_npage_adv = sft9001_set_npage_adv,