diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/tg3.c | 190 | ||||
-rw-r--r-- | drivers/net/tg3.h | 1 |
2 files changed, 163 insertions, 28 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 8411e0f4cb69..3a7cfb81bf89 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
@@ -340,10 +340,12 @@ static struct { | |||
340 | 340 | ||
341 | static void tg3_write_indirect_reg32(struct tg3 *tp, u32 off, u32 val) | 341 | static void tg3_write_indirect_reg32(struct tg3 *tp, u32 off, u32 val) |
342 | { | 342 | { |
343 | spin_lock_bh(&tp->indirect_lock); | 343 | unsigned long flags; |
344 | |||
345 | spin_lock_irqsave(&tp->indirect_lock, flags); | ||
344 | pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off); | 346 | pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off); |
345 | pci_write_config_dword(tp->pdev, TG3PCI_REG_DATA, val); | 347 | pci_write_config_dword(tp->pdev, TG3PCI_REG_DATA, val); |
346 | spin_unlock_bh(&tp->indirect_lock); | 348 | spin_unlock_irqrestore(&tp->indirect_lock, flags); |
347 | } | 349 | } |
348 | 350 | ||
349 | static void tg3_write_flush_reg32(struct tg3 *tp, u32 off, u32 val) | 351 | static void tg3_write_flush_reg32(struct tg3 *tp, u32 off, u32 val) |
@@ -352,24 +354,75 @@ static void tg3_write_flush_reg32(struct tg3 *tp, u32 off, u32 val) | |||
352 | readl(tp->regs + off); | 354 | readl(tp->regs + off); |
353 | } | 355 | } |
354 | 356 | ||
355 | static void _tw32_flush(struct tg3 *tp, u32 off, u32 val) | 357 | static u32 tg3_read_indirect_reg32(struct tg3 *tp, u32 off) |
356 | { | 358 | { |
357 | if ((tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) != 0) { | 359 | unsigned long flags; |
358 | spin_lock_bh(&tp->indirect_lock); | 360 | u32 val; |
359 | pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off); | 361 | |
360 | pci_write_config_dword(tp->pdev, TG3PCI_REG_DATA, val); | 362 | spin_lock_irqsave(&tp->indirect_lock, flags); |
361 | spin_unlock_bh(&tp->indirect_lock); | 363 | pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off); |
362 | } else { | 364 | pci_read_config_dword(tp->pdev, TG3PCI_REG_DATA, &val); |
363 | void __iomem *dest = tp->regs + off; | 365 | spin_unlock_irqrestore(&tp->indirect_lock, flags); |
364 | writel(val, dest); | 366 | return val; |
365 | readl(dest); /* always flush PCI write */ | 367 | } |
368 | |||
369 | static void tg3_write_indirect_mbox(struct tg3 *tp, u32 off, u32 val) | ||
370 | { | ||
371 | unsigned long flags; | ||
372 | |||
373 | if (off == (MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW)) { | ||
374 | pci_write_config_dword(tp->pdev, TG3PCI_RCV_RET_RING_CON_IDX + | ||
375 | TG3_64BIT_REG_LOW, val); | ||
376 | return; | ||
377 | } | ||
378 | if (off == (MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW)) { | ||
379 | pci_write_config_dword(tp->pdev, TG3PCI_STD_RING_PROD_IDX + | ||
380 | TG3_64BIT_REG_LOW, val); | ||
381 | return; | ||
366 | } | 382 | } |
383 | |||
384 | spin_lock_irqsave(&tp->indirect_lock, flags); | ||
385 | pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off + 0x5600); | ||
386 | pci_write_config_dword(tp->pdev, TG3PCI_REG_DATA, val); | ||
387 | spin_unlock_irqrestore(&tp->indirect_lock, flags); | ||
388 | |||
389 | /* In indirect mode when disabling interrupts, we also need | ||
390 | * to clear the interrupt bit in the GRC local ctrl register. | ||
391 | */ | ||
392 | if ((off == (MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW)) && | ||
393 | (val == 0x1)) { | ||
394 | pci_write_config_dword(tp->pdev, TG3PCI_MISC_LOCAL_CTRL, | ||
395 | tp->grc_local_ctrl|GRC_LCLCTRL_CLEARINT); | ||
396 | } | ||
397 | } | ||
398 | |||
399 | static u32 tg3_read_indirect_mbox(struct tg3 *tp, u32 off) | ||
400 | { | ||
401 | unsigned long flags; | ||
402 | u32 val; | ||
403 | |||
404 | spin_lock_irqsave(&tp->indirect_lock, flags); | ||
405 | pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off + 0x5600); | ||
406 | pci_read_config_dword(tp->pdev, TG3PCI_REG_DATA, &val); | ||
407 | spin_unlock_irqrestore(&tp->indirect_lock, flags); | ||
408 | return val; | ||
409 | } | ||
410 | |||
411 | static void _tw32_flush(struct tg3 *tp, u32 off, u32 val) | ||
412 | { | ||
413 | tp->write32(tp, off, val); | ||
414 | if (!(tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) && | ||
415 | !(tp->tg3_flags & TG3_FLAG_5701_REG_WRITE_BUG) && | ||
416 | !(tp->tg3_flags2 & TG3_FLG2_ICH_WORKAROUND)) | ||
417 | tp->read32(tp, off); /* flush */ | ||
367 | } | 418 | } |
368 | 419 | ||
369 | static inline void tw32_mailbox_flush(struct tg3 *tp, u32 off, u32 val) | 420 | static inline void tw32_mailbox_flush(struct tg3 *tp, u32 off, u32 val) |
370 | { | 421 | { |
371 | tp->write32_mbox(tp, off, val); | 422 | tp->write32_mbox(tp, off, val); |
372 | tp->read32_mbox(tp, off); | 423 | if (!(tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) && |
424 | !(tp->tg3_flags2 & TG3_FLG2_ICH_WORKAROUND)) | ||
425 | tp->read32_mbox(tp, off); | ||
373 | } | 426 | } |
374 | 427 | ||
375 | static void tg3_write32_tx_mbox(struct tg3 *tp, u32 off, u32 val) | 428 | static void tg3_write32_tx_mbox(struct tg3 *tp, u32 off, u32 val) |
@@ -404,24 +457,28 @@ static u32 tg3_read32(struct tg3 *tp, u32 off) | |||
404 | 457 | ||
405 | static void tg3_write_mem(struct tg3 *tp, u32 off, u32 val) | 458 | static void tg3_write_mem(struct tg3 *tp, u32 off, u32 val) |
406 | { | 459 | { |
407 | spin_lock_bh(&tp->indirect_lock); | 460 | unsigned long flags; |
461 | |||
462 | spin_lock_irqsave(&tp->indirect_lock, flags); | ||
408 | pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off); | 463 | pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off); |
409 | pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val); | 464 | pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val); |
410 | 465 | ||
411 | /* Always leave this as zero. */ | 466 | /* Always leave this as zero. */ |
412 | pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0); | 467 | pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0); |
413 | spin_unlock_bh(&tp->indirect_lock); | 468 | spin_unlock_irqrestore(&tp->indirect_lock, flags); |
414 | } | 469 | } |
415 | 470 | ||
416 | static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val) | 471 | static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val) |
417 | { | 472 | { |
418 | spin_lock_bh(&tp->indirect_lock); | 473 | unsigned long flags; |
474 | |||
475 | spin_lock_irqsave(&tp->indirect_lock, flags); | ||
419 | pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off); | 476 | pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off); |
420 | pci_read_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val); | 477 | pci_read_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val); |
421 | 478 | ||
422 | /* Always leave this as zero. */ | 479 | /* Always leave this as zero. */ |
423 | pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0); | 480 | pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0); |
424 | spin_unlock_bh(&tp->indirect_lock); | 481 | spin_unlock_irqrestore(&tp->indirect_lock, flags); |
425 | } | 482 | } |
426 | 483 | ||
427 | static void tg3_disable_ints(struct tg3 *tp) | 484 | static void tg3_disable_ints(struct tg3 *tp) |
@@ -9149,14 +9206,6 @@ static int __devinit tg3_is_sun_570X(struct tg3 *tp) | |||
9149 | static int __devinit tg3_get_invariants(struct tg3 *tp) | 9206 | static int __devinit tg3_get_invariants(struct tg3 *tp) |
9150 | { | 9207 | { |
9151 | static struct pci_device_id write_reorder_chipsets[] = { | 9208 | static struct pci_device_id write_reorder_chipsets[] = { |
9152 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, | ||
9153 | PCI_DEVICE_ID_INTEL_82801AA_8) }, | ||
9154 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, | ||
9155 | PCI_DEVICE_ID_INTEL_82801AB_8) }, | ||
9156 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, | ||
9157 | PCI_DEVICE_ID_INTEL_82801BA_11) }, | ||
9158 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, | ||
9159 | PCI_DEVICE_ID_INTEL_82801BA_6) }, | ||
9160 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, | 9209 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, |
9161 | PCI_DEVICE_ID_AMD_FE_GATE_700C) }, | 9210 | PCI_DEVICE_ID_AMD_FE_GATE_700C) }, |
9162 | { }, | 9211 | { }, |
@@ -9173,7 +9222,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) | |||
9173 | tp->tg3_flags2 |= TG3_FLG2_SUN_570X; | 9222 | tp->tg3_flags2 |= TG3_FLG2_SUN_570X; |
9174 | #endif | 9223 | #endif |
9175 | 9224 | ||
9176 | /* If we have an AMD 762 or Intel ICH/ICH0/ICH2 chipset, write | 9225 | /* If we have an AMD 762 chipset, write |
9177 | * reordering to the mailbox registers done by the host | 9226 | * reordering to the mailbox registers done by the host |
9178 | * controller can cause major troubles. We read back from | 9227 | * controller can cause major troubles. We read back from |
9179 | * every mailbox register write to force the writes to be | 9228 | * every mailbox register write to force the writes to be |
@@ -9211,6 +9260,69 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) | |||
9211 | if (tp->pci_chip_rev_id == CHIPREV_ID_5752_A0_HW) | 9260 | if (tp->pci_chip_rev_id == CHIPREV_ID_5752_A0_HW) |
9212 | tp->pci_chip_rev_id = CHIPREV_ID_5752_A0; | 9261 | tp->pci_chip_rev_id = CHIPREV_ID_5752_A0; |
9213 | 9262 | ||
9263 | /* If we have 5702/03 A1 or A2 on certain ICH chipsets, | ||
9264 | * we need to disable memory and use config. cycles | ||
9265 | * only to access all registers. The 5702/03 chips | ||
9266 | * can mistakenly decode the special cycles from the | ||
9267 | * ICH chipsets as memory write cycles, causing corruption | ||
9268 | * of register and memory space. Only certain ICH bridges | ||
9269 | * will drive special cycles with non-zero data during the | ||
9270 | * address phase which can fall within the 5703's address | ||
9271 | * range. This is not an ICH bug as the PCI spec allows | ||
9272 | * non-zero address during special cycles. However, only | ||
9273 | * these ICH bridges are known to drive non-zero addresses | ||
9274 | * during special cycles. | ||
9275 | * | ||
9276 | * Since special cycles do not cross PCI bridges, we only | ||
9277 | * enable this workaround if the 5703 is on the secondary | ||
9278 | * bus of these ICH bridges. | ||
9279 | */ | ||
9280 | if ((tp->pci_chip_rev_id == CHIPREV_ID_5703_A1) || | ||
9281 | (tp->pci_chip_rev_id == CHIPREV_ID_5703_A2)) { | ||
9282 | static struct tg3_dev_id { | ||
9283 | u32 vendor; | ||
9284 | u32 device; | ||
9285 | u32 rev; | ||
9286 | } ich_chipsets[] = { | ||
9287 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_8, | ||
9288 | PCI_ANY_ID }, | ||
9289 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_8, | ||
9290 | PCI_ANY_ID }, | ||
9291 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_11, | ||
9292 | 0xa }, | ||
9293 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_6, | ||
9294 | PCI_ANY_ID }, | ||
9295 | { }, | ||
9296 | }; | ||
9297 | struct tg3_dev_id *pci_id = &ich_chipsets[0]; | ||
9298 | struct pci_dev *bridge = NULL; | ||
9299 | |||
9300 | while (pci_id->vendor != 0) { | ||
9301 | bridge = pci_get_device(pci_id->vendor, pci_id->device, | ||
9302 | bridge); | ||
9303 | if (!bridge) { | ||
9304 | pci_id++; | ||
9305 | continue; | ||
9306 | } | ||
9307 | if (pci_id->rev != PCI_ANY_ID) { | ||
9308 | u8 rev; | ||
9309 | |||
9310 | pci_read_config_byte(bridge, PCI_REVISION_ID, | ||
9311 | &rev); | ||
9312 | if (rev > pci_id->rev) | ||
9313 | continue; | ||
9314 | } | ||
9315 | if (bridge->subordinate && | ||
9316 | (bridge->subordinate->number == | ||
9317 | tp->pdev->bus->number)) { | ||
9318 | |||
9319 | tp->tg3_flags2 |= TG3_FLG2_ICH_WORKAROUND; | ||
9320 | pci_dev_put(bridge); | ||
9321 | break; | ||
9322 | } | ||
9323 | } | ||
9324 | } | ||
9325 | |||
9214 | /* Find msi capability. */ | 9326 | /* Find msi capability. */ |
9215 | if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780) | 9327 | if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780) |
9216 | tp->msi_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_MSI); | 9328 | tp->msi_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_MSI); |
@@ -9342,6 +9454,22 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) | |||
9342 | tp->write32_rx_mbox = tg3_write_flush_reg32; | 9454 | tp->write32_rx_mbox = tg3_write_flush_reg32; |
9343 | } | 9455 | } |
9344 | 9456 | ||
9457 | if (tp->tg3_flags2 & TG3_FLG2_ICH_WORKAROUND) { | ||
9458 | tp->read32 = tg3_read_indirect_reg32; | ||
9459 | tp->write32 = tg3_write_indirect_reg32; | ||
9460 | tp->read32_mbox = tg3_read_indirect_mbox; | ||
9461 | tp->write32_mbox = tg3_write_indirect_mbox; | ||
9462 | tp->write32_tx_mbox = tg3_write_indirect_mbox; | ||
9463 | tp->write32_rx_mbox = tg3_write_indirect_mbox; | ||
9464 | |||
9465 | iounmap(tp->regs); | ||
9466 | tp->regs = 0; | ||
9467 | |||
9468 | pci_read_config_word(tp->pdev, PCI_COMMAND, &pci_cmd); | ||
9469 | pci_cmd &= ~PCI_COMMAND_MEMORY; | ||
9470 | pci_write_config_word(tp->pdev, PCI_COMMAND, pci_cmd); | ||
9471 | } | ||
9472 | |||
9345 | /* Get eeprom hw config before calling tg3_set_power_state(). | 9473 | /* Get eeprom hw config before calling tg3_set_power_state(). |
9346 | * In particular, the TG3_FLAG_EEPROM_WRITE_PROT flag must be | 9474 | * In particular, the TG3_FLAG_EEPROM_WRITE_PROT flag must be |
9347 | * determined before calling tg3_set_power_state() so that | 9475 | * determined before calling tg3_set_power_state() so that |
@@ -10486,7 +10614,10 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, | |||
10486 | return 0; | 10614 | return 0; |
10487 | 10615 | ||
10488 | err_out_iounmap: | 10616 | err_out_iounmap: |
10489 | iounmap(tp->regs); | 10617 | if (tp->regs) { |
10618 | iounmap(tp->regs); | ||
10619 | tp->regs = 0; | ||
10620 | } | ||
10490 | 10621 | ||
10491 | err_out_free_dev: | 10622 | err_out_free_dev: |
10492 | free_netdev(dev); | 10623 | free_netdev(dev); |
@@ -10508,7 +10639,10 @@ static void __devexit tg3_remove_one(struct pci_dev *pdev) | |||
10508 | struct tg3 *tp = netdev_priv(dev); | 10639 | struct tg3 *tp = netdev_priv(dev); |
10509 | 10640 | ||
10510 | unregister_netdev(dev); | 10641 | unregister_netdev(dev); |
10511 | iounmap(tp->regs); | 10642 | if (tp->regs) { |
10643 | iounmap(tp->regs); | ||
10644 | tp->regs = 0; | ||
10645 | } | ||
10512 | free_netdev(dev); | 10646 | free_netdev(dev); |
10513 | pci_release_regions(pdev); | 10647 | pci_release_regions(pdev); |
10514 | pci_disable_device(pdev); | 10648 | pci_disable_device(pdev); |
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index c398b8478d62..c184b773e585 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h | |||
@@ -2174,6 +2174,7 @@ struct tg3 { | |||
2174 | #define TG3_FLG2_ANY_SERDES (TG3_FLG2_PHY_SERDES | \ | 2174 | #define TG3_FLG2_ANY_SERDES (TG3_FLG2_PHY_SERDES | \ |
2175 | TG3_FLG2_MII_SERDES) | 2175 | TG3_FLG2_MII_SERDES) |
2176 | #define TG3_FLG2_PARALLEL_DETECT 0x01000000 | 2176 | #define TG3_FLG2_PARALLEL_DETECT 0x01000000 |
2177 | #define TG3_FLG2_ICH_WORKAROUND 0x02000000 | ||
2177 | 2178 | ||
2178 | u32 split_mode_max_reqs; | 2179 | u32 split_mode_max_reqs; |
2179 | #define SPLIT_MODE_5704_MAX_REQ 3 | 2180 | #define SPLIT_MODE_5704_MAX_REQ 3 |