aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/sfc/efx.c20
-rw-r--r--drivers/net/sfc/ethtool.c27
-rw-r--r--drivers/net/sfc/falcon.c49
-rw-r--r--drivers/net/sfc/net_driver.h7
-rw-r--r--drivers/net/sfc/siena.c33
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,
796static int efx_ethtool_reset(struct net_device *net_dev, u32 *flags) 796static 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
825static int 808static 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
1054static 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
1070static 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. */
1056static int __falcon_reset_hw(struct efx_nic *efx, enum reset_type method) 1099static 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
1747const struct efx_nic_type falcon_b0_nic_type = { 1791const 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 */
871struct efx_nic_type { 871struct 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
180static enum reset_type siena_map_reset_reason(enum reset_type reason)
181{
182 return RESET_TYPE_ALL;
183}
184
185static 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
180static int siena_reset_hw(struct efx_nic *efx, enum reset_type method) 210static 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};