diff options
Diffstat (limited to 'drivers/net/tg3.c')
-rw-r--r-- | drivers/net/tg3.c | 232 |
1 files changed, 228 insertions, 4 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 3200c9c5ff5e..5b6c1b286e92 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
@@ -314,6 +314,16 @@ static u32 tg3_read32(struct tg3 *tp, u32 off) | |||
314 | return (readl(tp->regs + off)); | 314 | return (readl(tp->regs + off)); |
315 | } | 315 | } |
316 | 316 | ||
317 | static void tg3_ape_write32(struct tg3 *tp, u32 off, u32 val) | ||
318 | { | ||
319 | writel(val, tp->aperegs + off); | ||
320 | } | ||
321 | |||
322 | static u32 tg3_ape_read32(struct tg3 *tp, u32 off) | ||
323 | { | ||
324 | return (readl(tp->aperegs + off)); | ||
325 | } | ||
326 | |||
317 | static void tg3_write_indirect_reg32(struct tg3 *tp, u32 off, u32 val) | 327 | static void tg3_write_indirect_reg32(struct tg3 *tp, u32 off, u32 val) |
318 | { | 328 | { |
319 | unsigned long flags; | 329 | unsigned long flags; |
@@ -500,6 +510,73 @@ static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val) | |||
500 | spin_unlock_irqrestore(&tp->indirect_lock, flags); | 510 | spin_unlock_irqrestore(&tp->indirect_lock, flags); |
501 | } | 511 | } |
502 | 512 | ||
513 | static void tg3_ape_lock_init(struct tg3 *tp) | ||
514 | { | ||
515 | int i; | ||
516 | |||
517 | /* Make sure the driver hasn't any stale locks. */ | ||
518 | for (i = 0; i < 8; i++) | ||
519 | tg3_ape_write32(tp, TG3_APE_LOCK_GRANT + 4 * i, | ||
520 | APE_LOCK_GRANT_DRIVER); | ||
521 | } | ||
522 | |||
523 | static int tg3_ape_lock(struct tg3 *tp, int locknum) | ||
524 | { | ||
525 | int i, off; | ||
526 | int ret = 0; | ||
527 | u32 status; | ||
528 | |||
529 | if (!(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) | ||
530 | return 0; | ||
531 | |||
532 | switch (locknum) { | ||
533 | case TG3_APE_LOCK_MEM: | ||
534 | break; | ||
535 | default: | ||
536 | return -EINVAL; | ||
537 | } | ||
538 | |||
539 | off = 4 * locknum; | ||
540 | |||
541 | tg3_ape_write32(tp, TG3_APE_LOCK_REQ + off, APE_LOCK_REQ_DRIVER); | ||
542 | |||
543 | /* Wait for up to 1 millisecond to acquire lock. */ | ||
544 | for (i = 0; i < 100; i++) { | ||
545 | status = tg3_ape_read32(tp, TG3_APE_LOCK_GRANT + off); | ||
546 | if (status == APE_LOCK_GRANT_DRIVER) | ||
547 | break; | ||
548 | udelay(10); | ||
549 | } | ||
550 | |||
551 | if (status != APE_LOCK_GRANT_DRIVER) { | ||
552 | /* Revoke the lock request. */ | ||
553 | tg3_ape_write32(tp, TG3_APE_LOCK_GRANT + off, | ||
554 | APE_LOCK_GRANT_DRIVER); | ||
555 | |||
556 | ret = -EBUSY; | ||
557 | } | ||
558 | |||
559 | return ret; | ||
560 | } | ||
561 | |||
562 | static void tg3_ape_unlock(struct tg3 *tp, int locknum) | ||
563 | { | ||
564 | int off; | ||
565 | |||
566 | if (!(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) | ||
567 | return; | ||
568 | |||
569 | switch (locknum) { | ||
570 | case TG3_APE_LOCK_MEM: | ||
571 | break; | ||
572 | default: | ||
573 | return; | ||
574 | } | ||
575 | |||
576 | off = 4 * locknum; | ||
577 | tg3_ape_write32(tp, TG3_APE_LOCK_GRANT + off, APE_LOCK_GRANT_DRIVER); | ||
578 | } | ||
579 | |||
503 | static void tg3_disable_ints(struct tg3 *tp) | 580 | static void tg3_disable_ints(struct tg3 *tp) |
504 | { | 581 | { |
505 | tw32(TG3PCI_MISC_HOST_CTRL, | 582 | tw32(TG3PCI_MISC_HOST_CTRL, |
@@ -1448,7 +1525,8 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) | |||
1448 | } | 1525 | } |
1449 | 1526 | ||
1450 | if (!(tp->tg3_flags & TG3_FLAG_WOL_ENABLE) && | 1527 | if (!(tp->tg3_flags & TG3_FLAG_WOL_ENABLE) && |
1451 | !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) | 1528 | !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF) && |
1529 | !(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) | ||
1452 | tg3_power_down_phy(tp); | 1530 | tg3_power_down_phy(tp); |
1453 | 1531 | ||
1454 | tg3_frob_aux_power(tp); | 1532 | tg3_frob_aux_power(tp); |
@@ -4726,6 +4804,80 @@ static void tg3_disable_nvram_access(struct tg3 *tp) | |||
4726 | } | 4804 | } |
4727 | } | 4805 | } |
4728 | 4806 | ||
4807 | static void tg3_ape_send_event(struct tg3 *tp, u32 event) | ||
4808 | { | ||
4809 | int i; | ||
4810 | u32 apedata; | ||
4811 | |||
4812 | apedata = tg3_ape_read32(tp, TG3_APE_SEG_SIG); | ||
4813 | if (apedata != APE_SEG_SIG_MAGIC) | ||
4814 | return; | ||
4815 | |||
4816 | apedata = tg3_ape_read32(tp, TG3_APE_FW_STATUS); | ||
4817 | if (apedata != APE_FW_STATUS_READY) | ||
4818 | return; | ||
4819 | |||
4820 | /* Wait for up to 1 millisecond for APE to service previous event. */ | ||
4821 | for (i = 0; i < 10; i++) { | ||
4822 | if (tg3_ape_lock(tp, TG3_APE_LOCK_MEM)) | ||
4823 | return; | ||
4824 | |||
4825 | apedata = tg3_ape_read32(tp, TG3_APE_EVENT_STATUS); | ||
4826 | |||
4827 | if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING)) | ||
4828 | tg3_ape_write32(tp, TG3_APE_EVENT_STATUS, | ||
4829 | event | APE_EVENT_STATUS_EVENT_PENDING); | ||
4830 | |||
4831 | tg3_ape_unlock(tp, TG3_APE_LOCK_MEM); | ||
4832 | |||
4833 | if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING)) | ||
4834 | break; | ||
4835 | |||
4836 | udelay(100); | ||
4837 | } | ||
4838 | |||
4839 | if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING)) | ||
4840 | tg3_ape_write32(tp, TG3_APE_EVENT, APE_EVENT_1); | ||
4841 | } | ||
4842 | |||
4843 | static void tg3_ape_driver_state_change(struct tg3 *tp, int kind) | ||
4844 | { | ||
4845 | u32 event; | ||
4846 | u32 apedata; | ||
4847 | |||
4848 | if (!(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) | ||
4849 | return; | ||
4850 | |||
4851 | switch (kind) { | ||
4852 | case RESET_KIND_INIT: | ||
4853 | tg3_ape_write32(tp, TG3_APE_HOST_SEG_SIG, | ||
4854 | APE_HOST_SEG_SIG_MAGIC); | ||
4855 | tg3_ape_write32(tp, TG3_APE_HOST_SEG_LEN, | ||
4856 | APE_HOST_SEG_LEN_MAGIC); | ||
4857 | apedata = tg3_ape_read32(tp, TG3_APE_HOST_INIT_COUNT); | ||
4858 | tg3_ape_write32(tp, TG3_APE_HOST_INIT_COUNT, ++apedata); | ||
4859 | tg3_ape_write32(tp, TG3_APE_HOST_DRIVER_ID, | ||
4860 | APE_HOST_DRIVER_ID_MAGIC); | ||
4861 | tg3_ape_write32(tp, TG3_APE_HOST_BEHAVIOR, | ||
4862 | APE_HOST_BEHAV_NO_PHYLOCK); | ||
4863 | |||
4864 | event = APE_EVENT_STATUS_STATE_START; | ||
4865 | break; | ||
4866 | case RESET_KIND_SHUTDOWN: | ||
4867 | event = APE_EVENT_STATUS_STATE_UNLOAD; | ||
4868 | break; | ||
4869 | case RESET_KIND_SUSPEND: | ||
4870 | event = APE_EVENT_STATUS_STATE_SUSPEND; | ||
4871 | break; | ||
4872 | default: | ||
4873 | return; | ||
4874 | } | ||
4875 | |||
4876 | event |= APE_EVENT_STATUS_DRIVER_EVNT | APE_EVENT_STATUS_STATE_CHNGE; | ||
4877 | |||
4878 | tg3_ape_send_event(tp, event); | ||
4879 | } | ||
4880 | |||
4729 | /* tp->lock is held. */ | 4881 | /* tp->lock is held. */ |
4730 | static void tg3_write_sig_pre_reset(struct tg3 *tp, int kind) | 4882 | static void tg3_write_sig_pre_reset(struct tg3 *tp, int kind) |
4731 | { | 4883 | { |
@@ -4753,6 +4905,10 @@ static void tg3_write_sig_pre_reset(struct tg3 *tp, int kind) | |||
4753 | break; | 4905 | break; |
4754 | }; | 4906 | }; |
4755 | } | 4907 | } |
4908 | |||
4909 | if (kind == RESET_KIND_INIT || | ||
4910 | kind == RESET_KIND_SUSPEND) | ||
4911 | tg3_ape_driver_state_change(tp, kind); | ||
4756 | } | 4912 | } |
4757 | 4913 | ||
4758 | /* tp->lock is held. */ | 4914 | /* tp->lock is held. */ |
@@ -4774,6 +4930,9 @@ static void tg3_write_sig_post_reset(struct tg3 *tp, int kind) | |||
4774 | break; | 4930 | break; |
4775 | }; | 4931 | }; |
4776 | } | 4932 | } |
4933 | |||
4934 | if (kind == RESET_KIND_SHUTDOWN) | ||
4935 | tg3_ape_driver_state_change(tp, kind); | ||
4777 | } | 4936 | } |
4778 | 4937 | ||
4779 | /* tp->lock is held. */ | 4938 | /* tp->lock is held. */ |
@@ -4864,6 +5023,10 @@ static void tg3_restore_pci_state(struct tg3 *tp) | |||
4864 | if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 && | 5023 | if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 && |
4865 | (tp->tg3_flags & TG3_FLAG_PCIX_MODE)) | 5024 | (tp->tg3_flags & TG3_FLAG_PCIX_MODE)) |
4866 | val |= PCISTATE_RETRY_SAME_DMA; | 5025 | val |= PCISTATE_RETRY_SAME_DMA; |
5026 | /* Allow reads and writes to the APE register and memory space. */ | ||
5027 | if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) | ||
5028 | val |= PCISTATE_ALLOW_APE_CTLSPC_WR | | ||
5029 | PCISTATE_ALLOW_APE_SHMEM_WR; | ||
4867 | pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, val); | 5030 | pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, val); |
4868 | 5031 | ||
4869 | pci_write_config_dword(tp->pdev, TG3PCI_COMMAND, tp->pci_cmd); | 5032 | pci_write_config_dword(tp->pdev, TG3PCI_COMMAND, tp->pci_cmd); |
@@ -5092,7 +5255,8 @@ static int tg3_chip_reset(struct tg3 *tp) | |||
5092 | /* tp->lock is held. */ | 5255 | /* tp->lock is held. */ |
5093 | static void tg3_stop_fw(struct tg3 *tp) | 5256 | static void tg3_stop_fw(struct tg3 *tp) |
5094 | { | 5257 | { |
5095 | if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) { | 5258 | if ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) && |
5259 | !(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) { | ||
5096 | u32 val; | 5260 | u32 val; |
5097 | int i; | 5261 | int i; |
5098 | 5262 | ||
@@ -6173,6 +6337,16 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) | |||
6173 | tw32(TG3PCI_PCISTATE, val); | 6337 | tw32(TG3PCI_PCISTATE, val); |
6174 | } | 6338 | } |
6175 | 6339 | ||
6340 | if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) { | ||
6341 | /* Allow reads and writes to the | ||
6342 | * APE register and memory space. | ||
6343 | */ | ||
6344 | val = tr32(TG3PCI_PCISTATE); | ||
6345 | val |= PCISTATE_ALLOW_APE_CTLSPC_WR | | ||
6346 | PCISTATE_ALLOW_APE_SHMEM_WR; | ||
6347 | tw32(TG3PCI_PCISTATE, val); | ||
6348 | } | ||
6349 | |||
6176 | if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5704_BX) { | 6350 | if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5704_BX) { |
6177 | /* Enable some hw fixes. */ | 6351 | /* Enable some hw fixes. */ |
6178 | val = tr32(TG3PCI_MSI_DATA); | 6352 | val = tr32(TG3PCI_MSI_DATA); |
@@ -6780,6 +6954,10 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) | |||
6780 | break; | 6954 | break; |
6781 | }; | 6955 | }; |
6782 | 6956 | ||
6957 | /* Write our heartbeat update interval to APE. */ | ||
6958 | tg3_ape_write32(tp, TG3_APE_HOST_HEARTBEAT_INT_MS, | ||
6959 | APE_HOST_HEARTBEAT_INT_DISABLE); | ||
6960 | |||
6783 | tg3_write_sig_post_reset(tp, RESET_KIND_INIT); | 6961 | tg3_write_sig_post_reset(tp, RESET_KIND_INIT); |
6784 | 6962 | ||
6785 | return 0; | 6963 | return 0; |
@@ -10302,6 +10480,8 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) | |||
10302 | if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) | 10480 | if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) |
10303 | tp->tg3_flags2 |= TG3_FLG2_ASF_NEW_HANDSHAKE; | 10481 | tp->tg3_flags2 |= TG3_FLG2_ASF_NEW_HANDSHAKE; |
10304 | } | 10482 | } |
10483 | if (nic_cfg & NIC_SRAM_DATA_CFG_APE_ENABLE) | ||
10484 | tp->tg3_flags3 |= TG3_FLG3_ENABLE_APE; | ||
10305 | if (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES && | 10485 | if (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES && |
10306 | !(nic_cfg & NIC_SRAM_DATA_CFG_FIBER_WOL)) | 10486 | !(nic_cfg & NIC_SRAM_DATA_CFG_FIBER_WOL)) |
10307 | tp->tg3_flags &= ~TG3_FLAG_WOL_CAP; | 10487 | tp->tg3_flags &= ~TG3_FLAG_WOL_CAP; |
@@ -10334,7 +10514,8 @@ static int __devinit tg3_phy_probe(struct tg3 *tp) | |||
10334 | * firwmare access to the PHY hardware. | 10514 | * firwmare access to the PHY hardware. |
10335 | */ | 10515 | */ |
10336 | err = 0; | 10516 | err = 0; |
10337 | if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) { | 10517 | if ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) || |
10518 | (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) { | ||
10338 | hw_phy_id = hw_phy_id_masked = PHY_ID_INVALID; | 10519 | hw_phy_id = hw_phy_id_masked = PHY_ID_INVALID; |
10339 | } else { | 10520 | } else { |
10340 | /* Now read the physical PHY_ID from the chip and verify | 10521 | /* Now read the physical PHY_ID from the chip and verify |
@@ -10381,6 +10562,7 @@ static int __devinit tg3_phy_probe(struct tg3 *tp) | |||
10381 | } | 10562 | } |
10382 | 10563 | ||
10383 | if (!(tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) && | 10564 | if (!(tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) && |
10565 | !(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) && | ||
10384 | !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) { | 10566 | !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) { |
10385 | u32 bmsr, adv_reg, tg3_ctrl, mask; | 10567 | u32 bmsr, adv_reg, tg3_ctrl, mask; |
10386 | 10568 | ||
@@ -10972,6 +11154,16 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) | |||
10972 | */ | 11154 | */ |
10973 | tg3_get_eeprom_hw_cfg(tp); | 11155 | tg3_get_eeprom_hw_cfg(tp); |
10974 | 11156 | ||
11157 | if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) { | ||
11158 | /* Allow reads and writes to the | ||
11159 | * APE register and memory space. | ||
11160 | */ | ||
11161 | pci_state_reg |= PCISTATE_ALLOW_APE_CTLSPC_WR | | ||
11162 | PCISTATE_ALLOW_APE_SHMEM_WR; | ||
11163 | pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, | ||
11164 | pci_state_reg); | ||
11165 | } | ||
11166 | |||
10975 | if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784) | 11167 | if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784) |
10976 | tp->tg3_flags |= TG3_FLAG_CPMU_PRESENT; | 11168 | tp->tg3_flags |= TG3_FLAG_CPMU_PRESENT; |
10977 | 11169 | ||
@@ -12165,13 +12357,35 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, | |||
12165 | 12357 | ||
12166 | tg3_init_coal(tp); | 12358 | tg3_init_coal(tp); |
12167 | 12359 | ||
12360 | if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) { | ||
12361 | if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) { | ||
12362 | printk(KERN_ERR PFX "Cannot find proper PCI device " | ||
12363 | "base address for APE, aborting.\n"); | ||
12364 | err = -ENODEV; | ||
12365 | goto err_out_iounmap; | ||
12366 | } | ||
12367 | |||
12368 | tg3reg_base = pci_resource_start(pdev, 2); | ||
12369 | tg3reg_len = pci_resource_len(pdev, 2); | ||
12370 | |||
12371 | tp->aperegs = ioremap_nocache(tg3reg_base, tg3reg_len); | ||
12372 | if (tp->aperegs == 0UL) { | ||
12373 | printk(KERN_ERR PFX "Cannot map APE registers, " | ||
12374 | "aborting.\n"); | ||
12375 | err = -ENOMEM; | ||
12376 | goto err_out_iounmap; | ||
12377 | } | ||
12378 | |||
12379 | tg3_ape_lock_init(tp); | ||
12380 | } | ||
12381 | |||
12168 | pci_set_drvdata(pdev, dev); | 12382 | pci_set_drvdata(pdev, dev); |
12169 | 12383 | ||
12170 | err = register_netdev(dev); | 12384 | err = register_netdev(dev); |
12171 | if (err) { | 12385 | if (err) { |
12172 | printk(KERN_ERR PFX "Cannot register net device, " | 12386 | printk(KERN_ERR PFX "Cannot register net device, " |
12173 | "aborting.\n"); | 12387 | "aborting.\n"); |
12174 | goto err_out_iounmap; | 12388 | goto err_out_apeunmap; |
12175 | } | 12389 | } |
12176 | 12390 | ||
12177 | printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] (%s) %s Ethernet ", | 12391 | printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] (%s) %s Ethernet ", |
@@ -12204,6 +12418,12 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, | |||
12204 | 12418 | ||
12205 | return 0; | 12419 | return 0; |
12206 | 12420 | ||
12421 | err_out_apeunmap: | ||
12422 | if (tp->aperegs) { | ||
12423 | iounmap(tp->aperegs); | ||
12424 | tp->aperegs = NULL; | ||
12425 | } | ||
12426 | |||
12207 | err_out_iounmap: | 12427 | err_out_iounmap: |
12208 | if (tp->regs) { | 12428 | if (tp->regs) { |
12209 | iounmap(tp->regs); | 12429 | iounmap(tp->regs); |
@@ -12231,6 +12451,10 @@ static void __devexit tg3_remove_one(struct pci_dev *pdev) | |||
12231 | 12451 | ||
12232 | flush_scheduled_work(); | 12452 | flush_scheduled_work(); |
12233 | unregister_netdev(dev); | 12453 | unregister_netdev(dev); |
12454 | if (tp->aperegs) { | ||
12455 | iounmap(tp->aperegs); | ||
12456 | tp->aperegs = NULL; | ||
12457 | } | ||
12234 | if (tp->regs) { | 12458 | if (tp->regs) { |
12235 | iounmap(tp->regs); | 12459 | iounmap(tp->regs); |
12236 | tp->regs = NULL; | 12460 | tp->regs = NULL; |