diff options
-rw-r--r-- | drivers/net/sfc/efx.c | 20 | ||||
-rw-r--r-- | drivers/net/sfc/ethtool.c | 27 | ||||
-rw-r--r-- | drivers/net/sfc/falcon.c | 49 | ||||
-rw-r--r-- | drivers/net/sfc/net_driver.h | 7 | ||||
-rw-r--r-- | drivers/net/sfc/siena.c | 33 |
5 files changed, 93 insertions, 43 deletions
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index 9b4cfdb09516..ff162df06bd0 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c | |||
@@ -2183,26 +2183,16 @@ void efx_schedule_reset(struct efx_nic *efx, enum reset_type type) | |||
2183 | case RESET_TYPE_WORLD: | 2183 | case RESET_TYPE_WORLD: |
2184 | case RESET_TYPE_DISABLE: | 2184 | case RESET_TYPE_DISABLE: |
2185 | method = type; | 2185 | method = type; |
2186 | netif_dbg(efx, drv, efx->net_dev, "scheduling %s reset\n", | ||
2187 | RESET_TYPE(method)); | ||
2186 | break; | 2188 | break; |
2187 | case RESET_TYPE_RX_RECOVERY: | ||
2188 | case RESET_TYPE_RX_DESC_FETCH: | ||
2189 | case RESET_TYPE_TX_DESC_FETCH: | ||
2190 | case RESET_TYPE_TX_SKIP: | ||
2191 | method = RESET_TYPE_INVISIBLE; | ||
2192 | break; | ||
2193 | case RESET_TYPE_MC_FAILURE: | ||
2194 | default: | 2189 | default: |
2195 | method = RESET_TYPE_ALL; | 2190 | method = efx->type->map_reset_reason(type); |
2196 | break; | ||
2197 | } | ||
2198 | |||
2199 | if (method != type) | ||
2200 | netif_dbg(efx, drv, efx->net_dev, | 2191 | netif_dbg(efx, drv, efx->net_dev, |
2201 | "scheduling %s reset for %s\n", | 2192 | "scheduling %s reset for %s\n", |
2202 | RESET_TYPE(method), RESET_TYPE(type)); | 2193 | RESET_TYPE(method), RESET_TYPE(type)); |
2203 | else | 2194 | break; |
2204 | netif_dbg(efx, drv, efx->net_dev, "scheduling %s reset\n", | 2195 | } |
2205 | RESET_TYPE(method)); | ||
2206 | 2196 | ||
2207 | set_bit(method, &efx->reset_pending); | 2197 | set_bit(method, &efx->reset_pending); |
2208 | 2198 | ||
diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c index d229027dc363..bc4643af6dd1 100644 --- a/drivers/net/sfc/ethtool.c +++ b/drivers/net/sfc/ethtool.c | |||
@@ -796,30 +796,13 @@ static int efx_ethtool_set_wol(struct net_device *net_dev, | |||
796 | static int efx_ethtool_reset(struct net_device *net_dev, u32 *flags) | 796 | static int efx_ethtool_reset(struct net_device *net_dev, u32 *flags) |
797 | { | 797 | { |
798 | struct efx_nic *efx = netdev_priv(net_dev); | 798 | struct efx_nic *efx = netdev_priv(net_dev); |
799 | enum reset_type method; | 799 | int rc; |
800 | enum { | ||
801 | ETH_RESET_EFX_INVISIBLE = (ETH_RESET_DMA | ETH_RESET_FILTER | | ||
802 | ETH_RESET_OFFLOAD | ETH_RESET_MAC) | ||
803 | }; | ||
804 | |||
805 | /* Check for minimal reset flags */ | ||
806 | if ((*flags & ETH_RESET_EFX_INVISIBLE) != ETH_RESET_EFX_INVISIBLE) | ||
807 | return -EINVAL; | ||
808 | *flags ^= ETH_RESET_EFX_INVISIBLE; | ||
809 | method = RESET_TYPE_INVISIBLE; | ||
810 | |||
811 | if (*flags & ETH_RESET_PHY) { | ||
812 | *flags ^= ETH_RESET_PHY; | ||
813 | method = RESET_TYPE_ALL; | ||
814 | } | ||
815 | 800 | ||
816 | if ((*flags & efx->type->reset_world_flags) == | 801 | rc = efx->type->map_reset_flags(flags); |
817 | efx->type->reset_world_flags) { | 802 | if (rc < 0) |
818 | *flags ^= efx->type->reset_world_flags; | 803 | return rc; |
819 | method = RESET_TYPE_WORLD; | ||
820 | } | ||
821 | 804 | ||
822 | return efx_reset(efx, method); | 805 | return efx_reset(efx, rc); |
823 | } | 806 | } |
824 | 807 | ||
825 | static int | 808 | static int |
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index a4c7830ec9b0..94bf4aaf984d 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c | |||
@@ -1051,6 +1051,49 @@ static int falcon_b0_test_registers(struct efx_nic *efx) | |||
1051 | ************************************************************************** | 1051 | ************************************************************************** |
1052 | */ | 1052 | */ |
1053 | 1053 | ||
1054 | static enum reset_type falcon_map_reset_reason(enum reset_type reason) | ||
1055 | { | ||
1056 | switch (reason) { | ||
1057 | case RESET_TYPE_RX_RECOVERY: | ||
1058 | case RESET_TYPE_RX_DESC_FETCH: | ||
1059 | case RESET_TYPE_TX_DESC_FETCH: | ||
1060 | case RESET_TYPE_TX_SKIP: | ||
1061 | /* These can occasionally occur due to hardware bugs. | ||
1062 | * We try to reset without disrupting the link. | ||
1063 | */ | ||
1064 | return RESET_TYPE_INVISIBLE; | ||
1065 | default: | ||
1066 | return RESET_TYPE_ALL; | ||
1067 | } | ||
1068 | } | ||
1069 | |||
1070 | static int falcon_map_reset_flags(u32 *flags) | ||
1071 | { | ||
1072 | enum { | ||
1073 | FALCON_RESET_INVISIBLE = (ETH_RESET_DMA | ETH_RESET_FILTER | | ||
1074 | ETH_RESET_OFFLOAD | ETH_RESET_MAC), | ||
1075 | FALCON_RESET_ALL = FALCON_RESET_INVISIBLE | ETH_RESET_PHY, | ||
1076 | FALCON_RESET_WORLD = FALCON_RESET_ALL | ETH_RESET_IRQ, | ||
1077 | }; | ||
1078 | |||
1079 | if ((*flags & FALCON_RESET_WORLD) == FALCON_RESET_WORLD) { | ||
1080 | *flags &= ~FALCON_RESET_WORLD; | ||
1081 | return RESET_TYPE_WORLD; | ||
1082 | } | ||
1083 | |||
1084 | if ((*flags & FALCON_RESET_ALL) == FALCON_RESET_ALL) { | ||
1085 | *flags &= ~FALCON_RESET_ALL; | ||
1086 | return RESET_TYPE_ALL; | ||
1087 | } | ||
1088 | |||
1089 | if ((*flags & FALCON_RESET_INVISIBLE) == FALCON_RESET_INVISIBLE) { | ||
1090 | *flags &= ~FALCON_RESET_INVISIBLE; | ||
1091 | return RESET_TYPE_INVISIBLE; | ||
1092 | } | ||
1093 | |||
1094 | return -EINVAL; | ||
1095 | } | ||
1096 | |||
1054 | /* Resets NIC to known state. This routine must be called in process | 1097 | /* Resets NIC to known state. This routine must be called in process |
1055 | * context and is allowed to sleep. */ | 1098 | * context and is allowed to sleep. */ |
1056 | static int __falcon_reset_hw(struct efx_nic *efx, enum reset_type method) | 1099 | static int __falcon_reset_hw(struct efx_nic *efx, enum reset_type method) |
@@ -1709,6 +1752,8 @@ const struct efx_nic_type falcon_a1_nic_type = { | |||
1709 | .init = falcon_init_nic, | 1752 | .init = falcon_init_nic, |
1710 | .fini = efx_port_dummy_op_void, | 1753 | .fini = efx_port_dummy_op_void, |
1711 | .monitor = falcon_monitor, | 1754 | .monitor = falcon_monitor, |
1755 | .map_reset_reason = falcon_map_reset_reason, | ||
1756 | .map_reset_flags = falcon_map_reset_flags, | ||
1712 | .reset = falcon_reset_hw, | 1757 | .reset = falcon_reset_hw, |
1713 | .probe_port = falcon_probe_port, | 1758 | .probe_port = falcon_probe_port, |
1714 | .remove_port = falcon_remove_port, | 1759 | .remove_port = falcon_remove_port, |
@@ -1741,7 +1786,6 @@ const struct efx_nic_type falcon_a1_nic_type = { | |||
1741 | .tx_dc_base = 0x130000, | 1786 | .tx_dc_base = 0x130000, |
1742 | .rx_dc_base = 0x100000, | 1787 | .rx_dc_base = 0x100000, |
1743 | .offload_features = NETIF_F_IP_CSUM, | 1788 | .offload_features = NETIF_F_IP_CSUM, |
1744 | .reset_world_flags = ETH_RESET_IRQ, | ||
1745 | }; | 1789 | }; |
1746 | 1790 | ||
1747 | const struct efx_nic_type falcon_b0_nic_type = { | 1791 | const struct efx_nic_type falcon_b0_nic_type = { |
@@ -1750,6 +1794,8 @@ const struct efx_nic_type falcon_b0_nic_type = { | |||
1750 | .init = falcon_init_nic, | 1794 | .init = falcon_init_nic, |
1751 | .fini = efx_port_dummy_op_void, | 1795 | .fini = efx_port_dummy_op_void, |
1752 | .monitor = falcon_monitor, | 1796 | .monitor = falcon_monitor, |
1797 | .map_reset_reason = falcon_map_reset_reason, | ||
1798 | .map_reset_flags = falcon_map_reset_flags, | ||
1753 | .reset = falcon_reset_hw, | 1799 | .reset = falcon_reset_hw, |
1754 | .probe_port = falcon_probe_port, | 1800 | .probe_port = falcon_probe_port, |
1755 | .remove_port = falcon_remove_port, | 1801 | .remove_port = falcon_remove_port, |
@@ -1791,6 +1837,5 @@ const struct efx_nic_type falcon_b0_nic_type = { | |||
1791 | .tx_dc_base = 0x130000, | 1837 | .tx_dc_base = 0x130000, |
1792 | .rx_dc_base = 0x100000, | 1838 | .rx_dc_base = 0x100000, |
1793 | .offload_features = NETIF_F_IP_CSUM | NETIF_F_RXHASH | NETIF_F_NTUPLE, | 1839 | .offload_features = NETIF_F_IP_CSUM | NETIF_F_RXHASH | NETIF_F_NTUPLE, |
1794 | .reset_world_flags = ETH_RESET_IRQ, | ||
1795 | }; | 1840 | }; |
1796 | 1841 | ||
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index c422eb2ce60a..4597066741f1 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h | |||
@@ -828,6 +828,8 @@ static inline unsigned int efx_port_num(struct efx_nic *efx) | |||
828 | * @init: Initialise the controller | 828 | * @init: Initialise the controller |
829 | * @fini: Shut down the controller | 829 | * @fini: Shut down the controller |
830 | * @monitor: Periodic function for polling link state and hardware monitor | 830 | * @monitor: Periodic function for polling link state and hardware monitor |
831 | * @map_reset_reason: Map ethtool reset reason to a reset method | ||
832 | * @map_reset_flags: Map ethtool reset flags to a reset method, if possible | ||
831 | * @reset: Reset the controller hardware and possibly the PHY. This will | 833 | * @reset: Reset the controller hardware and possibly the PHY. This will |
832 | * be called while the controller is uninitialised. | 834 | * be called while the controller is uninitialised. |
833 | * @probe_port: Probe the MAC and PHY | 835 | * @probe_port: Probe the MAC and PHY |
@@ -865,8 +867,6 @@ static inline unsigned int efx_port_num(struct efx_nic *efx) | |||
865 | * @rx_dc_base: Base address in SRAM of RX queue descriptor caches | 867 | * @rx_dc_base: Base address in SRAM of RX queue descriptor caches |
866 | * @offload_features: net_device feature flags for protocol offload | 868 | * @offload_features: net_device feature flags for protocol offload |
867 | * features implemented in hardware | 869 | * features implemented in hardware |
868 | * @reset_world_flags: Flags for additional components covered by | ||
869 | * reset method RESET_TYPE_WORLD | ||
870 | */ | 870 | */ |
871 | struct efx_nic_type { | 871 | struct efx_nic_type { |
872 | int (*probe)(struct efx_nic *efx); | 872 | int (*probe)(struct efx_nic *efx); |
@@ -874,6 +874,8 @@ struct efx_nic_type { | |||
874 | int (*init)(struct efx_nic *efx); | 874 | int (*init)(struct efx_nic *efx); |
875 | void (*fini)(struct efx_nic *efx); | 875 | void (*fini)(struct efx_nic *efx); |
876 | void (*monitor)(struct efx_nic *efx); | 876 | void (*monitor)(struct efx_nic *efx); |
877 | enum reset_type (*map_reset_reason)(enum reset_type reason); | ||
878 | int (*map_reset_flags)(u32 *flags); | ||
877 | int (*reset)(struct efx_nic *efx, enum reset_type method); | 879 | int (*reset)(struct efx_nic *efx, enum reset_type method); |
878 | int (*probe_port)(struct efx_nic *efx); | 880 | int (*probe_port)(struct efx_nic *efx); |
879 | void (*remove_port)(struct efx_nic *efx); | 881 | void (*remove_port)(struct efx_nic *efx); |
@@ -908,7 +910,6 @@ struct efx_nic_type { | |||
908 | unsigned int tx_dc_base; | 910 | unsigned int tx_dc_base; |
909 | unsigned int rx_dc_base; | 911 | unsigned int rx_dc_base; |
910 | u32 offload_features; | 912 | u32 offload_features; |
911 | u32 reset_world_flags; | ||
912 | }; | 913 | }; |
913 | 914 | ||
914 | /************************************************************************** | 915 | /************************************************************************** |
diff --git a/drivers/net/sfc/siena.c b/drivers/net/sfc/siena.c index a66818ed4011..442897b14270 100644 --- a/drivers/net/sfc/siena.c +++ b/drivers/net/sfc/siena.c | |||
@@ -177,6 +177,36 @@ static int siena_test_registers(struct efx_nic *efx) | |||
177 | ************************************************************************** | 177 | ************************************************************************** |
178 | */ | 178 | */ |
179 | 179 | ||
180 | static enum reset_type siena_map_reset_reason(enum reset_type reason) | ||
181 | { | ||
182 | return RESET_TYPE_ALL; | ||
183 | } | ||
184 | |||
185 | static int siena_map_reset_flags(u32 *flags) | ||
186 | { | ||
187 | enum { | ||
188 | SIENA_RESET_PORT = (ETH_RESET_DMA | ETH_RESET_FILTER | | ||
189 | ETH_RESET_OFFLOAD | ETH_RESET_MAC | | ||
190 | ETH_RESET_PHY), | ||
191 | SIENA_RESET_MC = (SIENA_RESET_PORT | | ||
192 | ETH_RESET_MGMT << ETH_RESET_SHARED_SHIFT), | ||
193 | }; | ||
194 | |||
195 | if ((*flags & SIENA_RESET_MC) == SIENA_RESET_MC) { | ||
196 | *flags &= ~SIENA_RESET_MC; | ||
197 | return RESET_TYPE_WORLD; | ||
198 | } | ||
199 | |||
200 | if ((*flags & SIENA_RESET_PORT) == SIENA_RESET_PORT) { | ||
201 | *flags &= ~SIENA_RESET_PORT; | ||
202 | return RESET_TYPE_ALL; | ||
203 | } | ||
204 | |||
205 | /* no invisible reset implemented */ | ||
206 | |||
207 | return -EINVAL; | ||
208 | } | ||
209 | |||
180 | static int siena_reset_hw(struct efx_nic *efx, enum reset_type method) | 210 | static int siena_reset_hw(struct efx_nic *efx, enum reset_type method) |
181 | { | 211 | { |
182 | int rc; | 212 | int rc; |
@@ -605,6 +635,8 @@ const struct efx_nic_type siena_a0_nic_type = { | |||
605 | .init = siena_init_nic, | 635 | .init = siena_init_nic, |
606 | .fini = efx_port_dummy_op_void, | 636 | .fini = efx_port_dummy_op_void, |
607 | .monitor = NULL, | 637 | .monitor = NULL, |
638 | .map_reset_reason = siena_map_reset_reason, | ||
639 | .map_reset_flags = siena_map_reset_flags, | ||
608 | .reset = siena_reset_hw, | 640 | .reset = siena_reset_hw, |
609 | .probe_port = siena_probe_port, | 641 | .probe_port = siena_probe_port, |
610 | .remove_port = siena_remove_port, | 642 | .remove_port = siena_remove_port, |
@@ -641,5 +673,4 @@ const struct efx_nic_type siena_a0_nic_type = { | |||
641 | .rx_dc_base = 0x68000, | 673 | .rx_dc_base = 0x68000, |
642 | .offload_features = (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | | 674 | .offload_features = (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | |
643 | NETIF_F_RXHASH | NETIF_F_NTUPLE), | 675 | NETIF_F_RXHASH | NETIF_F_NTUPLE), |
644 | .reset_world_flags = ETH_RESET_MGMT << ETH_RESET_SHARED_SHIFT, | ||
645 | }; | 676 | }; |