diff options
author | David S. Miller <davem@davemloft.net> | 2011-07-14 11:43:32 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-07-14 11:43:32 -0400 |
commit | 10d1e8ca8d7136111641472e9800775205ef5a0f (patch) | |
tree | 2b156935a6783944f39176cf7502cececdb0202c /drivers/net/sfc | |
parent | cd0d7228b4f0279f219bc555fa0192dc072d79cd (diff) | |
parent | ff79c8ac40a115adf5d94e1349f4a379ae156f55 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/bwh/sfc-next
Diffstat (limited to 'drivers/net/sfc')
-rw-r--r-- | drivers/net/sfc/Kconfig | 7 | ||||
-rw-r--r-- | drivers/net/sfc/efx.c | 60 | ||||
-rw-r--r-- | drivers/net/sfc/enum.h | 3 | ||||
-rw-r--r-- | drivers/net/sfc/ethtool.c | 27 | ||||
-rw-r--r-- | drivers/net/sfc/falcon.c | 51 | ||||
-rw-r--r-- | drivers/net/sfc/filter.c | 45 | ||||
-rw-r--r-- | drivers/net/sfc/net_driver.h | 11 | ||||
-rw-r--r-- | drivers/net/sfc/siena.c | 47 |
8 files changed, 152 insertions, 99 deletions
diff --git a/drivers/net/sfc/Kconfig b/drivers/net/sfc/Kconfig index a65c98638398..a3d5bb9e39dc 100644 --- a/drivers/net/sfc/Kconfig +++ b/drivers/net/sfc/Kconfig | |||
@@ -1,5 +1,5 @@ | |||
1 | config SFC | 1 | config SFC |
2 | tristate "Solarflare Solarstorm SFC4000/SFC9000-family support" | 2 | tristate "Solarflare SFC4000/SFC9000-family support" |
3 | depends on PCI && INET | 3 | depends on PCI && INET |
4 | select MDIO | 4 | select MDIO |
5 | select CRC32 | 5 | select CRC32 |
@@ -7,13 +7,12 @@ config SFC | |||
7 | select I2C_ALGOBIT | 7 | select I2C_ALGOBIT |
8 | help | 8 | help |
9 | This driver supports 10-gigabit Ethernet cards based on | 9 | This driver supports 10-gigabit Ethernet cards based on |
10 | the Solarflare Communications Solarstorm SFC4000 and | 10 | the Solarflare SFC4000 and SFC9000-family controllers. |
11 | SFC9000-family controllers. | ||
12 | 11 | ||
13 | To compile this driver as a module, choose M here. The module | 12 | To compile this driver as a module, choose M here. The module |
14 | will be called sfc. | 13 | will be called sfc. |
15 | config SFC_MTD | 14 | config SFC_MTD |
16 | bool "Solarflare Solarstorm SFC4000/SFC9000-family MTD support" | 15 | bool "Solarflare SFC4000/SFC9000-family MTD support" |
17 | depends on SFC && MTD && !(SFC=y && MTD=m) | 16 | depends on SFC && MTD && !(SFC=y && MTD=m) |
18 | default y | 17 | default y |
19 | help | 18 | help |
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index c914729f9554..faca764aa21b 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c | |||
@@ -229,8 +229,7 @@ static int efx_process_channel(struct efx_channel *channel, int budget) | |||
229 | struct efx_nic *efx = channel->efx; | 229 | struct efx_nic *efx = channel->efx; |
230 | int spent; | 230 | int spent; |
231 | 231 | ||
232 | if (unlikely(efx->reset_pending != RESET_TYPE_NONE || | 232 | if (unlikely(efx->reset_pending || !channel->enabled)) |
233 | !channel->enabled)) | ||
234 | return 0; | 233 | return 0; |
235 | 234 | ||
236 | spent = efx_nic_process_eventq(channel, budget); | 235 | spent = efx_nic_process_eventq(channel, budget); |
@@ -1461,7 +1460,7 @@ static void efx_start_all(struct efx_nic *efx) | |||
1461 | * reset_pending [modified from an atomic context], we instead guarantee | 1460 | * reset_pending [modified from an atomic context], we instead guarantee |
1462 | * that efx_mcdi_mode_poll() isn't reverted erroneously */ | 1461 | * that efx_mcdi_mode_poll() isn't reverted erroneously */ |
1463 | efx_mcdi_mode_event(efx); | 1462 | efx_mcdi_mode_event(efx); |
1464 | if (efx->reset_pending != RESET_TYPE_NONE) | 1463 | if (efx->reset_pending) |
1465 | efx_mcdi_mode_poll(efx); | 1464 | efx_mcdi_mode_poll(efx); |
1466 | 1465 | ||
1467 | /* Start the hardware monitor if there is one. Otherwise (we're link | 1466 | /* Start the hardware monitor if there is one. Otherwise (we're link |
@@ -2118,8 +2117,10 @@ int efx_reset(struct efx_nic *efx, enum reset_type method) | |||
2118 | goto out; | 2117 | goto out; |
2119 | } | 2118 | } |
2120 | 2119 | ||
2121 | /* Allow resets to be rescheduled. */ | 2120 | /* Clear flags for the scopes we covered. We assume the NIC and |
2122 | efx->reset_pending = RESET_TYPE_NONE; | 2121 | * driver are now quiescent so that there is no race here. |
2122 | */ | ||
2123 | efx->reset_pending &= -(1 << (method + 1)); | ||
2123 | 2124 | ||
2124 | /* Reinitialise bus-mastering, which may have been turned off before | 2125 | /* Reinitialise bus-mastering, which may have been turned off before |
2125 | * the reset was scheduled. This is still appropriate, even in the | 2126 | * the reset was scheduled. This is still appropriate, even in the |
@@ -2154,12 +2155,13 @@ out: | |||
2154 | static void efx_reset_work(struct work_struct *data) | 2155 | static void efx_reset_work(struct work_struct *data) |
2155 | { | 2156 | { |
2156 | struct efx_nic *efx = container_of(data, struct efx_nic, reset_work); | 2157 | struct efx_nic *efx = container_of(data, struct efx_nic, reset_work); |
2158 | unsigned long pending = ACCESS_ONCE(efx->reset_pending); | ||
2157 | 2159 | ||
2158 | if (efx->reset_pending == RESET_TYPE_NONE) | 2160 | if (!pending) |
2159 | return; | 2161 | return; |
2160 | 2162 | ||
2161 | /* If we're not RUNNING then don't reset. Leave the reset_pending | 2163 | /* If we're not RUNNING then don't reset. Leave the reset_pending |
2162 | * flag set so that efx_pci_probe_main will be retried */ | 2164 | * flags set so that efx_pci_probe_main will be retried */ |
2163 | if (efx->state != STATE_RUNNING) { | 2165 | if (efx->state != STATE_RUNNING) { |
2164 | netif_info(efx, drv, efx->net_dev, | 2166 | netif_info(efx, drv, efx->net_dev, |
2165 | "scheduled reset quenched. NIC not RUNNING\n"); | 2167 | "scheduled reset quenched. NIC not RUNNING\n"); |
@@ -2167,7 +2169,7 @@ static void efx_reset_work(struct work_struct *data) | |||
2167 | } | 2169 | } |
2168 | 2170 | ||
2169 | rtnl_lock(); | 2171 | rtnl_lock(); |
2170 | (void)efx_reset(efx, efx->reset_pending); | 2172 | (void)efx_reset(efx, fls(pending) - 1); |
2171 | rtnl_unlock(); | 2173 | rtnl_unlock(); |
2172 | } | 2174 | } |
2173 | 2175 | ||
@@ -2175,40 +2177,24 @@ void efx_schedule_reset(struct efx_nic *efx, enum reset_type type) | |||
2175 | { | 2177 | { |
2176 | enum reset_type method; | 2178 | enum reset_type method; |
2177 | 2179 | ||
2178 | if (efx->reset_pending != RESET_TYPE_NONE) { | ||
2179 | netif_info(efx, drv, efx->net_dev, | ||
2180 | "quenching already scheduled reset\n"); | ||
2181 | return; | ||
2182 | } | ||
2183 | |||
2184 | switch (type) { | 2180 | switch (type) { |
2185 | case RESET_TYPE_INVISIBLE: | 2181 | case RESET_TYPE_INVISIBLE: |
2186 | case RESET_TYPE_ALL: | 2182 | case RESET_TYPE_ALL: |
2187 | case RESET_TYPE_WORLD: | 2183 | case RESET_TYPE_WORLD: |
2188 | case RESET_TYPE_DISABLE: | 2184 | case RESET_TYPE_DISABLE: |
2189 | method = type; | 2185 | method = type; |
2186 | netif_dbg(efx, drv, efx->net_dev, "scheduling %s reset\n", | ||
2187 | RESET_TYPE(method)); | ||
2190 | break; | 2188 | break; |
2191 | case RESET_TYPE_RX_RECOVERY: | ||
2192 | case RESET_TYPE_RX_DESC_FETCH: | ||
2193 | case RESET_TYPE_TX_DESC_FETCH: | ||
2194 | case RESET_TYPE_TX_SKIP: | ||
2195 | method = RESET_TYPE_INVISIBLE; | ||
2196 | break; | ||
2197 | case RESET_TYPE_MC_FAILURE: | ||
2198 | default: | 2189 | default: |
2199 | method = RESET_TYPE_ALL; | 2190 | method = efx->type->map_reset_reason(type); |
2200 | break; | ||
2201 | } | ||
2202 | |||
2203 | if (method != type) | ||
2204 | netif_dbg(efx, drv, efx->net_dev, | 2191 | netif_dbg(efx, drv, efx->net_dev, |
2205 | "scheduling %s reset for %s\n", | 2192 | "scheduling %s reset for %s\n", |
2206 | RESET_TYPE(method), RESET_TYPE(type)); | 2193 | RESET_TYPE(method), RESET_TYPE(type)); |
2207 | else | 2194 | break; |
2208 | netif_dbg(efx, drv, efx->net_dev, "scheduling %s reset\n", | 2195 | } |
2209 | RESET_TYPE(method)); | ||
2210 | 2196 | ||
2211 | efx->reset_pending = method; | 2197 | set_bit(method, &efx->reset_pending); |
2212 | 2198 | ||
2213 | /* efx_process_channel() will no longer read events once a | 2199 | /* efx_process_channel() will no longer read events once a |
2214 | * reset is scheduled. So switch back to poll'd MCDI completions. */ | 2200 | * reset is scheduled. So switch back to poll'd MCDI completions. */ |
@@ -2288,7 +2274,6 @@ static int efx_init_struct(struct efx_nic *efx, const struct efx_nic_type *type, | |||
2288 | efx->pci_dev = pci_dev; | 2274 | efx->pci_dev = pci_dev; |
2289 | efx->msg_enable = debug; | 2275 | efx->msg_enable = debug; |
2290 | efx->state = STATE_INIT; | 2276 | efx->state = STATE_INIT; |
2291 | efx->reset_pending = RESET_TYPE_NONE; | ||
2292 | strlcpy(efx->name, pci_name(pci_dev), sizeof(efx->name)); | 2277 | strlcpy(efx->name, pci_name(pci_dev), sizeof(efx->name)); |
2293 | 2278 | ||
2294 | efx->net_dev = net_dev; | 2279 | efx->net_dev = net_dev; |
@@ -2491,7 +2476,7 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev, | |||
2491 | goto fail1; | 2476 | goto fail1; |
2492 | 2477 | ||
2493 | netif_info(efx, probe, efx->net_dev, | 2478 | netif_info(efx, probe, efx->net_dev, |
2494 | "Solarflare Communications NIC detected\n"); | 2479 | "Solarflare NIC detected\n"); |
2495 | 2480 | ||
2496 | /* Set up basic I/O (BAR mappings etc) */ | 2481 | /* Set up basic I/O (BAR mappings etc) */ |
2497 | rc = efx_init_io(efx); | 2482 | rc = efx_init_io(efx); |
@@ -2510,7 +2495,7 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev, | |||
2510 | cancel_work_sync(&efx->reset_work); | 2495 | cancel_work_sync(&efx->reset_work); |
2511 | 2496 | ||
2512 | if (rc == 0) { | 2497 | if (rc == 0) { |
2513 | if (efx->reset_pending != RESET_TYPE_NONE) { | 2498 | if (efx->reset_pending) { |
2514 | /* If there was a scheduled reset during | 2499 | /* If there was a scheduled reset during |
2515 | * probe, the NIC is probably hosed anyway */ | 2500 | * probe, the NIC is probably hosed anyway */ |
2516 | efx_pci_remove_main(efx); | 2501 | efx_pci_remove_main(efx); |
@@ -2521,11 +2506,12 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev, | |||
2521 | } | 2506 | } |
2522 | 2507 | ||
2523 | /* Retry if a recoverably reset event has been scheduled */ | 2508 | /* Retry if a recoverably reset event has been scheduled */ |
2524 | if ((efx->reset_pending != RESET_TYPE_INVISIBLE) && | 2509 | if (efx->reset_pending & |
2525 | (efx->reset_pending != RESET_TYPE_ALL)) | 2510 | ~(1 << RESET_TYPE_INVISIBLE | 1 << RESET_TYPE_ALL) || |
2511 | !efx->reset_pending) | ||
2526 | goto fail3; | 2512 | goto fail3; |
2527 | 2513 | ||
2528 | efx->reset_pending = RESET_TYPE_NONE; | 2514 | efx->reset_pending = 0; |
2529 | } | 2515 | } |
2530 | 2516 | ||
2531 | if (rc) { | 2517 | if (rc) { |
@@ -2609,7 +2595,7 @@ static int efx_pm_poweroff(struct device *dev) | |||
2609 | 2595 | ||
2610 | efx->type->fini(efx); | 2596 | efx->type->fini(efx); |
2611 | 2597 | ||
2612 | efx->reset_pending = RESET_TYPE_NONE; | 2598 | efx->reset_pending = 0; |
2613 | 2599 | ||
2614 | pci_save_state(pci_dev); | 2600 | pci_save_state(pci_dev); |
2615 | return pci_set_power_state(pci_dev, PCI_D3hot); | 2601 | return pci_set_power_state(pci_dev, PCI_D3hot); |
diff --git a/drivers/net/sfc/enum.h b/drivers/net/sfc/enum.h index 384cfe3b1be1..d725a8fbe1a6 100644 --- a/drivers/net/sfc/enum.h +++ b/drivers/net/sfc/enum.h | |||
@@ -134,6 +134,8 @@ enum efx_loopback_mode { | |||
134 | * other valuesspecify reasons, which efx_schedule_reset() will choose | 134 | * other valuesspecify reasons, which efx_schedule_reset() will choose |
135 | * a method for. | 135 | * a method for. |
136 | * | 136 | * |
137 | * Reset methods are numbered in order of increasing scope. | ||
138 | * | ||
137 | * @RESET_TYPE_INVISIBLE: don't reset the PHYs or interrupts | 139 | * @RESET_TYPE_INVISIBLE: don't reset the PHYs or interrupts |
138 | * @RESET_TYPE_ALL: reset everything but PCI core blocks | 140 | * @RESET_TYPE_ALL: reset everything but PCI core blocks |
139 | * @RESET_TYPE_WORLD: reset everything, save & restore PCI config | 141 | * @RESET_TYPE_WORLD: reset everything, save & restore PCI config |
@@ -147,7 +149,6 @@ enum efx_loopback_mode { | |||
147 | * @RESET_TYPE_MC_FAILURE: MC reboot/assertion | 149 | * @RESET_TYPE_MC_FAILURE: MC reboot/assertion |
148 | */ | 150 | */ |
149 | enum reset_type { | 151 | enum reset_type { |
150 | RESET_TYPE_NONE = -1, | ||
151 | RESET_TYPE_INVISIBLE = 0, | 152 | RESET_TYPE_INVISIBLE = 0, |
152 | RESET_TYPE_ALL = 1, | 153 | RESET_TYPE_ALL = 1, |
153 | RESET_TYPE_WORLD = 2, | 154 | RESET_TYPE_WORLD = 2, |
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 60176e873d62..94bf4aaf984d 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c | |||
@@ -536,7 +536,7 @@ void falcon_reconfigure_mac_wrapper(struct efx_nic *efx) | |||
536 | efx_oword_t reg; | 536 | efx_oword_t reg; |
537 | int link_speed, isolate; | 537 | int link_speed, isolate; |
538 | 538 | ||
539 | isolate = (efx->reset_pending != RESET_TYPE_NONE); | 539 | isolate = !!ACCESS_ONCE(efx->reset_pending); |
540 | 540 | ||
541 | switch (link_state->speed) { | 541 | switch (link_state->speed) { |
542 | case 10000: link_speed = 3; break; | 542 | case 10000: link_speed = 3; break; |
@@ -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/filter.c b/drivers/net/sfc/filter.c index f2fc2587c09d..2b9636f96e05 100644 --- a/drivers/net/sfc/filter.c +++ b/drivers/net/sfc/filter.c | |||
@@ -335,28 +335,35 @@ static int efx_filter_search(struct efx_filter_table *table, | |||
335 | bool for_insert, int *depth_required) | 335 | bool for_insert, int *depth_required) |
336 | { | 336 | { |
337 | unsigned hash, incr, filter_idx, depth, depth_max; | 337 | unsigned hash, incr, filter_idx, depth, depth_max; |
338 | struct efx_filter_spec *cmp; | ||
339 | 338 | ||
340 | hash = efx_filter_hash(key); | 339 | hash = efx_filter_hash(key); |
341 | incr = efx_filter_increment(key); | 340 | incr = efx_filter_increment(key); |
342 | depth_max = (spec->priority <= EFX_FILTER_PRI_HINT ? | 341 | |
343 | FILTER_CTL_SRCH_HINT_MAX : FILTER_CTL_SRCH_MAX); | 342 | filter_idx = hash & (table->size - 1); |
344 | 343 | depth = 1; | |
345 | for (depth = 1, filter_idx = hash & (table->size - 1); | 344 | depth_max = (for_insert ? |
346 | depth <= depth_max && test_bit(filter_idx, table->used_bitmap); | 345 | (spec->priority <= EFX_FILTER_PRI_HINT ? |
347 | ++depth) { | 346 | FILTER_CTL_SRCH_HINT_MAX : FILTER_CTL_SRCH_MAX) : |
348 | cmp = &table->spec[filter_idx]; | 347 | table->search_depth[spec->type]); |
349 | if (efx_filter_equal(spec, cmp)) | 348 | |
350 | goto found; | 349 | for (;;) { |
350 | /* Return success if entry is used and matches this spec | ||
351 | * or entry is unused and we are trying to insert. | ||
352 | */ | ||
353 | if (test_bit(filter_idx, table->used_bitmap) ? | ||
354 | efx_filter_equal(spec, &table->spec[filter_idx]) : | ||
355 | for_insert) { | ||
356 | *depth_required = depth; | ||
357 | return filter_idx; | ||
358 | } | ||
359 | |||
360 | /* Return failure if we reached the maximum search depth */ | ||
361 | if (depth == depth_max) | ||
362 | return for_insert ? -EBUSY : -ENOENT; | ||
363 | |||
351 | filter_idx = (filter_idx + incr) & (table->size - 1); | 364 | filter_idx = (filter_idx + incr) & (table->size - 1); |
365 | ++depth; | ||
352 | } | 366 | } |
353 | if (!for_insert) | ||
354 | return -ENOENT; | ||
355 | if (depth > depth_max) | ||
356 | return -EBUSY; | ||
357 | found: | ||
358 | *depth_required = depth; | ||
359 | return filter_idx; | ||
360 | } | 367 | } |
361 | 368 | ||
362 | /* Construct/deconstruct external filter IDs */ | 369 | /* Construct/deconstruct external filter IDs */ |
@@ -650,11 +657,11 @@ int efx_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb, | |||
650 | return -EPROTONOSUPPORT; | 657 | return -EPROTONOSUPPORT; |
651 | 658 | ||
652 | /* RFS must validate the IP header length before calling us */ | 659 | /* RFS must validate the IP header length before calling us */ |
653 | EFX_BUG_ON_PARANOID(!pskb_may_pull(skb, nhoff + sizeof(*ip))); | 660 | EFX_BUG_ON_PARANOID(skb_headlen(skb) < nhoff + sizeof(*ip)); |
654 | ip = (const struct iphdr *)(skb->data + nhoff); | 661 | ip = (const struct iphdr *)(skb->data + nhoff); |
655 | if (ip_is_fragment(ip)) | 662 | if (ip_is_fragment(ip)) |
656 | return -EPROTONOSUPPORT; | 663 | return -EPROTONOSUPPORT; |
657 | EFX_BUG_ON_PARANOID(!pskb_may_pull(skb, nhoff + 4 * ip->ihl + 4)); | 664 | EFX_BUG_ON_PARANOID(skb_headlen(skb) < nhoff + 4 * ip->ihl + 4); |
658 | ports = (const __be16 *)(skb->data + nhoff + 4 * ip->ihl); | 665 | ports = (const __be16 *)(skb->data + nhoff + 4 * ip->ihl); |
659 | 666 | ||
660 | efx_filter_init_rx(&spec, EFX_FILTER_PRI_HINT, 0, rxq_index); | 667 | efx_filter_init_rx(&spec, EFX_FILTER_PRI_HINT, 0, rxq_index); |
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index 1affbf4d7083..b8e251a1ee48 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h | |||
@@ -644,7 +644,7 @@ struct efx_filter_state; | |||
644 | * @irq_rx_moderation: IRQ moderation time for RX event queues | 644 | * @irq_rx_moderation: IRQ moderation time for RX event queues |
645 | * @msg_enable: Log message enable flags | 645 | * @msg_enable: Log message enable flags |
646 | * @state: Device state flag. Serialised by the rtnl_lock. | 646 | * @state: Device state flag. Serialised by the rtnl_lock. |
647 | * @reset_pending: Pending reset method (normally RESET_TYPE_NONE) | 647 | * @reset_pending: Bitmask for pending resets |
648 | * @tx_queue: TX DMA queues | 648 | * @tx_queue: TX DMA queues |
649 | * @rx_queue: RX DMA queues | 649 | * @rx_queue: RX DMA queues |
650 | * @channel: Channels | 650 | * @channel: Channels |
@@ -727,7 +727,7 @@ struct efx_nic { | |||
727 | u32 msg_enable; | 727 | u32 msg_enable; |
728 | 728 | ||
729 | enum nic_state state; | 729 | enum nic_state state; |
730 | enum reset_type reset_pending; | 730 | unsigned long reset_pending; |
731 | 731 | ||
732 | struct efx_channel *channel[EFX_MAX_CHANNELS]; | 732 | struct efx_channel *channel[EFX_MAX_CHANNELS]; |
733 | char channel_name[EFX_MAX_CHANNELS][IFNAMSIZ + 6]; | 733 | char channel_name[EFX_MAX_CHANNELS][IFNAMSIZ + 6]; |
@@ -827,6 +827,8 @@ static inline unsigned int efx_port_num(struct efx_nic *efx) | |||
827 | * @init: Initialise the controller | 827 | * @init: Initialise the controller |
828 | * @fini: Shut down the controller | 828 | * @fini: Shut down the controller |
829 | * @monitor: Periodic function for polling link state and hardware monitor | 829 | * @monitor: Periodic function for polling link state and hardware monitor |
830 | * @map_reset_reason: Map ethtool reset reason to a reset method | ||
831 | * @map_reset_flags: Map ethtool reset flags to a reset method, if possible | ||
830 | * @reset: Reset the controller hardware and possibly the PHY. This will | 832 | * @reset: Reset the controller hardware and possibly the PHY. This will |
831 | * be called while the controller is uninitialised. | 833 | * be called while the controller is uninitialised. |
832 | * @probe_port: Probe the MAC and PHY | 834 | * @probe_port: Probe the MAC and PHY |
@@ -864,8 +866,6 @@ static inline unsigned int efx_port_num(struct efx_nic *efx) | |||
864 | * @rx_dc_base: Base address in SRAM of RX queue descriptor caches | 866 | * @rx_dc_base: Base address in SRAM of RX queue descriptor caches |
865 | * @offload_features: net_device feature flags for protocol offload | 867 | * @offload_features: net_device feature flags for protocol offload |
866 | * features implemented in hardware | 868 | * features implemented in hardware |
867 | * @reset_world_flags: Flags for additional components covered by | ||
868 | * reset method RESET_TYPE_WORLD | ||
869 | */ | 869 | */ |
870 | struct efx_nic_type { | 870 | struct efx_nic_type { |
871 | int (*probe)(struct efx_nic *efx); | 871 | int (*probe)(struct efx_nic *efx); |
@@ -873,6 +873,8 @@ struct efx_nic_type { | |||
873 | int (*init)(struct efx_nic *efx); | 873 | int (*init)(struct efx_nic *efx); |
874 | void (*fini)(struct efx_nic *efx); | 874 | void (*fini)(struct efx_nic *efx); |
875 | void (*monitor)(struct efx_nic *efx); | 875 | void (*monitor)(struct efx_nic *efx); |
876 | enum reset_type (*map_reset_reason)(enum reset_type reason); | ||
877 | int (*map_reset_flags)(u32 *flags); | ||
876 | int (*reset)(struct efx_nic *efx, enum reset_type method); | 878 | int (*reset)(struct efx_nic *efx, enum reset_type method); |
877 | int (*probe_port)(struct efx_nic *efx); | 879 | int (*probe_port)(struct efx_nic *efx); |
878 | void (*remove_port)(struct efx_nic *efx); | 880 | void (*remove_port)(struct efx_nic *efx); |
@@ -907,7 +909,6 @@ struct efx_nic_type { | |||
907 | unsigned int tx_dc_base; | 909 | unsigned int tx_dc_base; |
908 | unsigned int rx_dc_base; | 910 | unsigned int rx_dc_base; |
909 | u32 offload_features; | 911 | u32 offload_features; |
910 | u32 reset_world_flags; | ||
911 | }; | 912 | }; |
912 | 913 | ||
913 | /************************************************************************** | 914 | /************************************************************************** |
diff --git a/drivers/net/sfc/siena.c b/drivers/net/sfc/siena.c index a66818ed4011..5735e84c69de 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; |
@@ -390,14 +420,13 @@ static void siena_remove_nic(struct efx_nic *efx) | |||
390 | efx->nic_data = NULL; | 420 | efx->nic_data = NULL; |
391 | } | 421 | } |
392 | 422 | ||
393 | #define STATS_GENERATION_INVALID ((u64)(-1)) | 423 | #define STATS_GENERATION_INVALID ((__force __le64)(-1)) |
394 | 424 | ||
395 | static int siena_try_update_nic_stats(struct efx_nic *efx) | 425 | static int siena_try_update_nic_stats(struct efx_nic *efx) |
396 | { | 426 | { |
397 | u64 *dma_stats; | 427 | __le64 *dma_stats; |
398 | struct efx_mac_stats *mac_stats; | 428 | struct efx_mac_stats *mac_stats; |
399 | u64 generation_start; | 429 | __le64 generation_start, generation_end; |
400 | u64 generation_end; | ||
401 | 430 | ||
402 | mac_stats = &efx->mac_stats; | 431 | mac_stats = &efx->mac_stats; |
403 | dma_stats = efx->stats_buffer.addr; | 432 | dma_stats = efx->stats_buffer.addr; |
@@ -408,7 +437,7 @@ static int siena_try_update_nic_stats(struct efx_nic *efx) | |||
408 | rmb(); | 437 | rmb(); |
409 | 438 | ||
410 | #define MAC_STAT(M, D) \ | 439 | #define MAC_STAT(M, D) \ |
411 | mac_stats->M = dma_stats[MC_CMD_MAC_ ## D] | 440 | mac_stats->M = le64_to_cpu(dma_stats[MC_CMD_MAC_ ## D]) |
412 | 441 | ||
413 | MAC_STAT(tx_bytes, TX_BYTES); | 442 | MAC_STAT(tx_bytes, TX_BYTES); |
414 | MAC_STAT(tx_bad_bytes, TX_BAD_BYTES); | 443 | MAC_STAT(tx_bad_bytes, TX_BAD_BYTES); |
@@ -478,7 +507,8 @@ static int siena_try_update_nic_stats(struct efx_nic *efx) | |||
478 | MAC_STAT(rx_internal_error, RX_INTERNAL_ERROR_PKTS); | 507 | MAC_STAT(rx_internal_error, RX_INTERNAL_ERROR_PKTS); |
479 | mac_stats->rx_good_lt64 = 0; | 508 | mac_stats->rx_good_lt64 = 0; |
480 | 509 | ||
481 | efx->n_rx_nodesc_drop_cnt = dma_stats[MC_CMD_MAC_RX_NODESC_DROPS]; | 510 | efx->n_rx_nodesc_drop_cnt = |
511 | le64_to_cpu(dma_stats[MC_CMD_MAC_RX_NODESC_DROPS]); | ||
482 | 512 | ||
483 | #undef MAC_STAT | 513 | #undef MAC_STAT |
484 | 514 | ||
@@ -507,7 +537,7 @@ static void siena_update_nic_stats(struct efx_nic *efx) | |||
507 | 537 | ||
508 | static void siena_start_nic_stats(struct efx_nic *efx) | 538 | static void siena_start_nic_stats(struct efx_nic *efx) |
509 | { | 539 | { |
510 | u64 *dma_stats = (u64 *)efx->stats_buffer.addr; | 540 | __le64 *dma_stats = efx->stats_buffer.addr; |
511 | 541 | ||
512 | dma_stats[MC_CMD_MAC_GENERATION_END] = STATS_GENERATION_INVALID; | 542 | dma_stats[MC_CMD_MAC_GENERATION_END] = STATS_GENERATION_INVALID; |
513 | 543 | ||
@@ -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 | }; |