[PATCH] ibm_emac: fix graceful stop timeout handling

This patch fixes graceful stop timeout handling in PPC4xx EMAC driver.

Currently, when we stop TX/RX channels we just do some number of loops
without relying on actual spent time. This has finally bitten me on
one of our systems (heavy network traffic during start up, RX channel
is stopped several times to configure multicast list).

Graceful channel stop can take up to 1 frame time, so I've added
device specific timeout counter which depends on current link speed
and calls to udelay() to really wait required amount of time before
giving up.

Signed-off-by: Eugene Surovegin <ebs@ebshome.net>
Signed-off-by: Jeff Garzik <jgarzik@pobox.com>

authored by Eugene Surovegin and committed by Jeff Garzik 8169bd91 be0df20c

+31 -9
+29 -9
drivers/net/ibm_emac/ibm_emac_core.c
··· 65 */ 66 67 #define DRV_NAME "emac" 68 - #define DRV_VERSION "3.53" 69 #define DRV_DESC "PPC 4xx OCP EMAC driver" 70 71 MODULE_DESCRIPTION(DRV_DESC); ··· 158 #define PHY_POLL_LINK_ON HZ 159 #define PHY_POLL_LINK_OFF (HZ / 5) 160 161 /* Please, keep in sync with struct ibm_emac_stats/ibm_emac_error_stats */ 162 static const char emac_stats_keys[EMAC_ETHTOOL_STATS_COUNT][ETH_GSTRING_LEN] = { 163 "rx_packets", "rx_bytes", "tx_packets", "tx_bytes", "rx_packets_csum", ··· 230 231 r = in_be32(&p->mr0); 232 if (r & EMAC_MR0_TXE) { 233 - int n = 300; 234 out_be32(&p->mr0, r & ~EMAC_MR0_TXE); 235 - while (!(in_be32(&p->mr0) & EMAC_MR0_TXI) && n) 236 --n; 237 if (unlikely(!n)) 238 emac_report_timeout_error(dev, "TX disable timeout"); 239 } ··· 258 if (!(r & EMAC_MR0_RXE)) { 259 if (unlikely(!(r & EMAC_MR0_RXI))) { 260 /* Wait if previous async disable is still in progress */ 261 - int n = 100; 262 - while (!(r = in_be32(&p->mr0) & EMAC_MR0_RXI) && n) 263 --n; 264 if (unlikely(!n)) 265 emac_report_timeout_error(dev, 266 "RX disable timeout"); ··· 285 286 r = in_be32(&p->mr0); 287 if (r & EMAC_MR0_RXE) { 288 - int n = 300; 289 out_be32(&p->mr0, r & ~EMAC_MR0_RXE); 290 - while (!(in_be32(&p->mr0) & EMAC_MR0_RXI) && n) 291 --n; 292 if (unlikely(!n)) 293 emac_report_timeout_error(dev, "RX disable timeout"); 294 } ··· 409 r = EMAC_MR1_BASE(emac_opb_mhz()) | EMAC_MR1_VLE | EMAC_MR1_IST; 410 if (dev->phy.duplex == DUPLEX_FULL) 411 r |= EMAC_MR1_FDE; 412 switch (dev->phy.speed) { 413 case SPEED_1000: 414 if (emac_phy_gpcs(dev->phy.mode)) { ··· 424 r |= EMAC_MR1_MF_1000; 425 r |= EMAC_MR1_RFS_16K; 426 gige = 1; 427 - 428 - if (dev->ndev->mtu > ETH_DATA_LEN) 429 r |= EMAC_MR1_JPSM; 430 break; 431 case SPEED_100: 432 r |= EMAC_MR1_MF_100; 433 /* Fall through */ 434 default: 435 r |= EMAC_MR1_RFS_4K; ··· 2067 dev->phy.duplex = DUPLEX_FULL; 2068 dev->phy.autoneg = AUTONEG_DISABLE; 2069 dev->phy.pause = dev->phy.asym_pause = 0; 2070 init_timer(&dev->link_timer); 2071 dev->link_timer.function = emac_link_timer; 2072 dev->link_timer.data = (unsigned long)dev;
··· 65 */ 66 67 #define DRV_NAME "emac" 68 + #define DRV_VERSION "3.54" 69 #define DRV_DESC "PPC 4xx OCP EMAC driver" 70 71 MODULE_DESCRIPTION(DRV_DESC); ··· 158 #define PHY_POLL_LINK_ON HZ 159 #define PHY_POLL_LINK_OFF (HZ / 5) 160 161 + /* Graceful stop timeouts in us. 162 + * We should allow up to 1 frame time (full-duplex, ignoring collisions) 163 + */ 164 + #define STOP_TIMEOUT_10 1230 165 + #define STOP_TIMEOUT_100 124 166 + #define STOP_TIMEOUT_1000 13 167 + #define STOP_TIMEOUT_1000_JUMBO 73 168 + 169 /* Please, keep in sync with struct ibm_emac_stats/ibm_emac_error_stats */ 170 static const char emac_stats_keys[EMAC_ETHTOOL_STATS_COUNT][ETH_GSTRING_LEN] = { 171 "rx_packets", "rx_bytes", "tx_packets", "tx_bytes", "rx_packets_csum", ··· 222 223 r = in_be32(&p->mr0); 224 if (r & EMAC_MR0_TXE) { 225 + int n = dev->stop_timeout; 226 out_be32(&p->mr0, r & ~EMAC_MR0_TXE); 227 + while (!(in_be32(&p->mr0) & EMAC_MR0_TXI) && n) { 228 + udelay(1); 229 --n; 230 + } 231 if (unlikely(!n)) 232 emac_report_timeout_error(dev, "TX disable timeout"); 233 } ··· 248 if (!(r & EMAC_MR0_RXE)) { 249 if (unlikely(!(r & EMAC_MR0_RXI))) { 250 /* Wait if previous async disable is still in progress */ 251 + int n = dev->stop_timeout; 252 + while (!(r = in_be32(&p->mr0) & EMAC_MR0_RXI) && n) { 253 + udelay(1); 254 --n; 255 + } 256 if (unlikely(!n)) 257 emac_report_timeout_error(dev, 258 "RX disable timeout"); ··· 273 274 r = in_be32(&p->mr0); 275 if (r & EMAC_MR0_RXE) { 276 + int n = dev->stop_timeout; 277 out_be32(&p->mr0, r & ~EMAC_MR0_RXE); 278 + while (!(in_be32(&p->mr0) & EMAC_MR0_RXI) && n) { 279 + udelay(1); 280 --n; 281 + } 282 if (unlikely(!n)) 283 emac_report_timeout_error(dev, "RX disable timeout"); 284 } ··· 395 r = EMAC_MR1_BASE(emac_opb_mhz()) | EMAC_MR1_VLE | EMAC_MR1_IST; 396 if (dev->phy.duplex == DUPLEX_FULL) 397 r |= EMAC_MR1_FDE; 398 + dev->stop_timeout = STOP_TIMEOUT_10; 399 switch (dev->phy.speed) { 400 case SPEED_1000: 401 if (emac_phy_gpcs(dev->phy.mode)) { ··· 409 r |= EMAC_MR1_MF_1000; 410 r |= EMAC_MR1_RFS_16K; 411 gige = 1; 412 + 413 + if (dev->ndev->mtu > ETH_DATA_LEN) { 414 r |= EMAC_MR1_JPSM; 415 + dev->stop_timeout = STOP_TIMEOUT_1000_JUMBO; 416 + } else 417 + dev->stop_timeout = STOP_TIMEOUT_1000; 418 break; 419 case SPEED_100: 420 r |= EMAC_MR1_MF_100; 421 + dev->stop_timeout = STOP_TIMEOUT_100; 422 /* Fall through */ 423 default: 424 r |= EMAC_MR1_RFS_4K; ··· 2048 dev->phy.duplex = DUPLEX_FULL; 2049 dev->phy.autoneg = AUTONEG_DISABLE; 2050 dev->phy.pause = dev->phy.asym_pause = 0; 2051 + dev->stop_timeout = STOP_TIMEOUT_100; 2052 init_timer(&dev->link_timer); 2053 dev->link_timer.function = emac_link_timer; 2054 dev->link_timer.data = (unsigned long)dev;
+2
drivers/net/ibm_emac/ibm_emac_core.h
··· 189 struct timer_list link_timer; 190 int reset_failed; 191 192 struct ibm_emac_error_stats estats; 193 struct net_device_stats nstats; 194
··· 189 struct timer_list link_timer; 190 int reset_failed; 191 192 + int stop_timeout; /* in us */ 193 + 194 struct ibm_emac_error_stats estats; 195 struct net_device_stats nstats; 196