mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	tg3: Prevent corruption at 10 / 100Mbps w CLKREQ
This patch disables CLKREQ at 10Mbps and 100Mbps to workaround a TX BD corruption issue. This problem only affects the 5784 and 5761 (and 57780 AX) ASIC revisions. Signed-off-by: Matt Carlson <mcarlson@broadcom.com> Signed-off-by: Michael Chan <mchan@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									52f4490c3b
								
							
						
					
					
						commit
						5e7dfd0fb9
					
				
					 2 changed files with 67 additions and 14 deletions
				
			
		| 
						 | 
					@ -2154,6 +2154,20 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
 | 
				
			||||||
			tp->dev->name, state);
 | 
								tp->dev->name, state);
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Restore the CLKREQ setting. */
 | 
				
			||||||
 | 
						if (tp->tg3_flags3 & TG3_FLG3_CLKREQ_BUG) {
 | 
				
			||||||
 | 
							u16 lnkctl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							pci_read_config_word(tp->pdev,
 | 
				
			||||||
 | 
									     tp->pcie_cap + PCI_EXP_LNKCTL,
 | 
				
			||||||
 | 
									     &lnkctl);
 | 
				
			||||||
 | 
							lnkctl |= PCI_EXP_LNKCTL_CLKREQ_EN;
 | 
				
			||||||
 | 
							pci_write_config_word(tp->pdev,
 | 
				
			||||||
 | 
									      tp->pcie_cap + PCI_EXP_LNKCTL,
 | 
				
			||||||
 | 
									      lnkctl);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	misc_host_ctrl = tr32(TG3PCI_MISC_HOST_CTRL);
 | 
						misc_host_ctrl = tr32(TG3PCI_MISC_HOST_CTRL);
 | 
				
			||||||
	tw32(TG3PCI_MISC_HOST_CTRL,
 | 
						tw32(TG3PCI_MISC_HOST_CTRL,
 | 
				
			||||||
	     misc_host_ctrl | MISC_HOST_CTRL_MASK_PCI_INT);
 | 
						     misc_host_ctrl | MISC_HOST_CTRL_MASK_PCI_INT);
 | 
				
			||||||
| 
						 | 
					@ -2923,6 +2937,24 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
 | 
				
			||||||
			      NIC_SRAM_FIRMWARE_MBOX_MAGIC2);
 | 
								      NIC_SRAM_FIRMWARE_MBOX_MAGIC2);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Prevent send BD corruption. */
 | 
				
			||||||
 | 
						if (tp->tg3_flags3 & TG3_FLG3_CLKREQ_BUG) {
 | 
				
			||||||
 | 
							u16 oldlnkctl, newlnkctl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							pci_read_config_word(tp->pdev,
 | 
				
			||||||
 | 
									     tp->pcie_cap + PCI_EXP_LNKCTL,
 | 
				
			||||||
 | 
									     &oldlnkctl);
 | 
				
			||||||
 | 
							if (tp->link_config.active_speed == SPEED_100 ||
 | 
				
			||||||
 | 
							    tp->link_config.active_speed == SPEED_10)
 | 
				
			||||||
 | 
								newlnkctl = oldlnkctl & ~PCI_EXP_LNKCTL_CLKREQ_EN;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								newlnkctl = oldlnkctl | PCI_EXP_LNKCTL_CLKREQ_EN;
 | 
				
			||||||
 | 
							if (newlnkctl != oldlnkctl)
 | 
				
			||||||
 | 
								pci_write_config_word(tp->pdev,
 | 
				
			||||||
 | 
										      tp->pcie_cap + PCI_EXP_LNKCTL,
 | 
				
			||||||
 | 
										      newlnkctl);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (current_link_up != netif_carrier_ok(tp->dev)) {
 | 
						if (current_link_up != netif_carrier_ok(tp->dev)) {
 | 
				
			||||||
		if (current_link_up)
 | 
							if (current_link_up)
 | 
				
			||||||
			netif_carrier_on(tp->dev);
 | 
								netif_carrier_on(tp->dev);
 | 
				
			||||||
| 
						 | 
					@ -6016,7 +6048,7 @@ static int tg3_chip_reset(struct tg3 *tp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	udelay(120);
 | 
						udelay(120);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) {
 | 
						if ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) && tp->pcie_cap) {
 | 
				
			||||||
		if (tp->pci_chip_rev_id == CHIPREV_ID_5750_A0) {
 | 
							if (tp->pci_chip_rev_id == CHIPREV_ID_5750_A0) {
 | 
				
			||||||
			int i;
 | 
								int i;
 | 
				
			||||||
			u32 cfg_val;
 | 
								u32 cfg_val;
 | 
				
			||||||
| 
						 | 
					@ -6029,9 +6061,23 @@ static int tg3_chip_reset(struct tg3 *tp)
 | 
				
			||||||
			pci_write_config_dword(tp->pdev, 0xc4,
 | 
								pci_write_config_dword(tp->pdev, 0xc4,
 | 
				
			||||||
					       cfg_val | (1 << 15));
 | 
										       cfg_val | (1 << 15));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785)
 | 
					
 | 
				
			||||||
			/* Set PCIE max payload size and clear error status.  */
 | 
							/* Set PCIE max payload size to 128 bytes and
 | 
				
			||||||
			pci_write_config_dword(tp->pdev, 0xd8, 0xf5000);
 | 
							 * clear the "no snoop" and "relaxed ordering" bits.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							pci_write_config_word(tp->pdev,
 | 
				
			||||||
 | 
									      tp->pcie_cap + PCI_EXP_DEVCTL,
 | 
				
			||||||
 | 
									      0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							pcie_set_readrq(tp->pdev, 4096);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Clear error status */
 | 
				
			||||||
 | 
							pci_write_config_word(tp->pdev,
 | 
				
			||||||
 | 
									      tp->pcie_cap + PCI_EXP_DEVSTA,
 | 
				
			||||||
 | 
									      PCI_EXP_DEVSTA_CED |
 | 
				
			||||||
 | 
									      PCI_EXP_DEVSTA_NFED |
 | 
				
			||||||
 | 
									      PCI_EXP_DEVSTA_FED |
 | 
				
			||||||
 | 
									      PCI_EXP_DEVSTA_URD);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tg3_restore_pci_state(tp);
 | 
						tg3_restore_pci_state(tp);
 | 
				
			||||||
| 
						 | 
					@ -11967,7 +12013,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 | 
				
			||||||
	u32 pci_state_reg, grc_misc_cfg;
 | 
						u32 pci_state_reg, grc_misc_cfg;
 | 
				
			||||||
	u32 val;
 | 
						u32 val;
 | 
				
			||||||
	u16 pci_cmd;
 | 
						u16 pci_cmd;
 | 
				
			||||||
	int err, pcie_cap;
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Force memory write invalidate off.  If we leave it on,
 | 
						/* Force memory write invalidate off.  If we leave it on,
 | 
				
			||||||
	 * then on 5700_BX chips we have to enable a workaround.
 | 
						 * then on 5700_BX chips we have to enable a workaround.
 | 
				
			||||||
| 
						 | 
					@ -12193,20 +12239,23 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 | 
				
			||||||
	pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE,
 | 
						pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE,
 | 
				
			||||||
			      &pci_state_reg);
 | 
								      &pci_state_reg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pcie_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_EXP);
 | 
						tp->pcie_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_EXP);
 | 
				
			||||||
	if (pcie_cap != 0) {
 | 
						if (tp->pcie_cap != 0) {
 | 
				
			||||||
 | 
							u16 lnkctl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		tp->tg3_flags2 |= TG3_FLG2_PCI_EXPRESS;
 | 
							tp->tg3_flags2 |= TG3_FLG2_PCI_EXPRESS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		pcie_set_readrq(tp->pdev, 4096);
 | 
							pcie_set_readrq(tp->pdev, 4096);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
 | 
							pci_read_config_word(tp->pdev,
 | 
				
			||||||
			u16 lnkctl;
 | 
									     tp->pcie_cap + PCI_EXP_LNKCTL,
 | 
				
			||||||
 | 
									     &lnkctl);
 | 
				
			||||||
			pci_read_config_word(tp->pdev,
 | 
							if (lnkctl & PCI_EXP_LNKCTL_CLKREQ_EN) {
 | 
				
			||||||
					     pcie_cap + PCI_EXP_LNKCTL,
 | 
								if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
 | 
				
			||||||
					     &lnkctl);
 | 
					 | 
				
			||||||
			if (lnkctl & PCI_EXP_LNKCTL_CLKREQ_EN)
 | 
					 | 
				
			||||||
				tp->tg3_flags2 &= ~TG3_FLG2_HW_TSO_2;
 | 
									tp->tg3_flags2 &= ~TG3_FLG2_HW_TSO_2;
 | 
				
			||||||
 | 
								if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
 | 
				
			||||||
 | 
								    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
 | 
				
			||||||
 | 
									tp->tg3_flags3 |= TG3_FLG3_CLKREQ_BUG;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) {
 | 
						} else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) {
 | 
				
			||||||
		tp->tg3_flags2 |= TG3_FLG2_PCI_EXPRESS;
 | 
							tp->tg3_flags2 |= TG3_FLG2_PCI_EXPRESS;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2618,6 +2618,7 @@ struct tg3 {
 | 
				
			||||||
#define TG3_FLG3_RGMII_STD_IBND_DISABLE	0x00000100
 | 
					#define TG3_FLG3_RGMII_STD_IBND_DISABLE	0x00000100
 | 
				
			||||||
#define TG3_FLG3_RGMII_EXT_IBND_RX_EN	0x00000200
 | 
					#define TG3_FLG3_RGMII_EXT_IBND_RX_EN	0x00000200
 | 
				
			||||||
#define TG3_FLG3_RGMII_EXT_IBND_TX_EN	0x00000400
 | 
					#define TG3_FLG3_RGMII_EXT_IBND_TX_EN	0x00000400
 | 
				
			||||||
 | 
					#define TG3_FLG3_CLKREQ_BUG		0x00000800
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct timer_list		timer;
 | 
						struct timer_list		timer;
 | 
				
			||||||
	u16				timer_counter;
 | 
						u16				timer_counter;
 | 
				
			||||||
| 
						 | 
					@ -2656,7 +2657,10 @@ struct tg3 {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int				pm_cap;
 | 
						int				pm_cap;
 | 
				
			||||||
	int				msi_cap;
 | 
						int				msi_cap;
 | 
				
			||||||
 | 
						union {
 | 
				
			||||||
	int				pcix_cap;
 | 
						int				pcix_cap;
 | 
				
			||||||
 | 
						int				pcie_cap;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct mii_bus			*mdio_bus;
 | 
						struct mii_bus			*mdio_bus;
 | 
				
			||||||
	int				mdio_irq[PHY_MAX_ADDR];
 | 
						int				mdio_irq[PHY_MAX_ADDR];
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue