diff options
Diffstat (limited to 'drivers/net/sfc')
-rw-r--r-- | drivers/net/sfc/efx.c | 35 | ||||
-rw-r--r-- | drivers/net/sfc/efx.h | 3 | ||||
-rw-r--r-- | drivers/net/sfc/falcon.c | 69 | ||||
-rw-r--r-- | drivers/net/sfc/falcon.h | 1 | ||||
-rw-r--r-- | drivers/net/sfc/net_driver.h | 24 | ||||
-rw-r--r-- | drivers/net/sfc/qt202x_phy.c | 26 | ||||
-rw-r--r-- | drivers/net/sfc/tenxpress.c | 69 |
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 | */ |
586 | static void efx_link_status_changed(struct efx_nic *efx) | 586 | void 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 */ | ||
681 | static 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 */ | ||
774 | static void efx_start_port(struct efx_nic *efx) | 758 | static 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 */ | ||
794 | static void efx_stop_port(struct efx_nic *efx) | 775 | static 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) {} | |||
1907 | void efx_port_dummy_op_set_id_led(struct efx_nic *efx, enum efx_led_mode mode) | 1886 | void efx_port_dummy_op_set_id_led(struct efx_nic *efx, enum efx_led_mode mode) |
1908 | { | 1887 | { |
1909 | } | 1888 | } |
1889 | bool efx_port_dummy_op_poll(struct efx_nic *efx) | ||
1890 | { | ||
1891 | return false; | ||
1892 | } | ||
1910 | 1893 | ||
1911 | static struct efx_mac_operations efx_dummy_mac_operations = { | 1894 | static 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 = { | |||
1915 | static struct efx_phy_operations efx_dummy_phy_operations = { | 1898 | static 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); | |||
90 | extern void efx_port_dummy_op_void(struct efx_nic *efx); | 90 | extern void efx_port_dummy_op_void(struct efx_nic *efx); |
91 | extern void | 91 | extern void |
92 | efx_port_dummy_op_set_id_led(struct efx_nic *efx, enum efx_led_mode mode); | 92 | efx_port_dummy_op_set_id_led(struct efx_nic *efx, enum efx_led_mode mode); |
93 | extern 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 | ||
117 | extern 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 | ||
1143 | void 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 | ||
2051 | static 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 | ||
2611 | void falcon_monitor(struct efx_nic *efx) | 2606 | void 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); | |||
145 | extern void falcon_enable_interrupts(struct efx_nic *efx); | 145 | extern void falcon_enable_interrupts(struct efx_nic *efx); |
146 | extern void falcon_generate_test_event(struct efx_channel *channel, | 146 | extern void falcon_generate_test_event(struct efx_channel *channel, |
147 | unsigned int magic); | 147 | unsigned int magic); |
148 | extern void falcon_sim_phy_event(struct efx_nic *efx); | ||
149 | extern void falcon_generate_interrupt(struct efx_nic *efx); | 148 | extern void falcon_generate_interrupt(struct efx_nic *efx); |
150 | extern void falcon_set_int_moderation(struct efx_channel *channel); | 149 | extern void falcon_set_int_moderation(struct efx_channel *channel); |
151 | extern void falcon_disable_interrupts(struct efx_nic *efx); | 150 | extern 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 | ||
506 | static 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 | ||
170 | static 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 | |||
176 | static int qt202x_link_ok(struct efx_nic *efx) | 170 | static 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 | ||
181 | static void qt202x_phy_poll(struct efx_nic *efx) | 175 | static 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 | ||
189 | static void qt202x_phy_reconfigure(struct efx_nic *efx) | 187 | static 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 | ||
225 | static void qt202x_phy_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) | 218 | static 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) | |||
503 | static void tenxpress_phy_reconfigure(struct efx_nic *efx) | 503 | static 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 */ | 548 | static void |
562 | static void tenxpress_phy_poll(struct efx_nic *efx) | 549 | tenxpress_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd); |
550 | |||
551 | /* Poll for link state changes */ | ||
552 | static 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 | ||
596 | static void tenxpress_phy_fini(struct efx_nic *efx) | 583 | static 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, |