Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5e7dfd0f authored by Matt Carlson's avatar Matt Carlson Committed by David S. Miller
Browse files

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: default avatarMatt Carlson <mcarlson@broadcom.com>
Signed-off-by: default avatarMichael Chan <mchan@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 52f4490c
Loading
Loading
Loading
Loading
+63 −14
Original line number Original line Diff line number Diff line
@@ -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) {
			u16 lnkctl;

		pci_read_config_word(tp->pdev,
		pci_read_config_word(tp->pdev,
					     pcie_cap + PCI_EXP_LNKCTL,
				     tp->pcie_cap + PCI_EXP_LNKCTL,
				     &lnkctl);
				     &lnkctl);
			if (lnkctl & PCI_EXP_LNKCTL_CLKREQ_EN)
		if (lnkctl & PCI_EXP_LNKCTL_CLKREQ_EN) {
			if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
				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;
+4 −0
Original line number Original line Diff line number Diff line
@@ -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];