Commit 4a29cc2e authored by Michael Chan's avatar Michael Chan Committed by David S. Miller

[TG3]: 40-bit DMA workaround part 2

The 40-bit DMA workaround recently implemented for 5714, 5715, and
5780 needs to be expanded because there may be other tg3 devices
behind the EPB Express to PCIX bridge in the 5780 class device.

For example, some 4-port card or mother board designs have 5704 behind
the 5714.

All devices behind the EPB require the 40-bit DMA workaround.

Thanks to Chris Elmquist again for reporting the problem and testing
the patch.
Signed-off-by: default avatarMichael Chan <mchan@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c7c694d1
...@@ -9552,12 +9552,36 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) ...@@ -9552,12 +9552,36 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
} }
} }
/* Find msi capability. */ /* The EPB bridge inside 5714, 5715, and 5780 cannot support
* DMA addresses > 40-bit. This bridge may have other additional
* 57xx devices behind it in some 4-port NIC designs for example.
* Any tg3 device found behind the bridge will also need the 40-bit
* DMA workaround.
*/
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780 || if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) { GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) {
tp->tg3_flags2 |= TG3_FLG2_5780_CLASS; tp->tg3_flags2 |= TG3_FLG2_5780_CLASS;
tp->tg3_flags |= TG3_FLAG_40BIT_DMA_BUG;
tp->msi_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_MSI); tp->msi_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_MSI);
} }
else {
struct pci_dev *bridge = NULL;
do {
bridge = pci_get_device(PCI_VENDOR_ID_SERVERWORKS,
PCI_DEVICE_ID_SERVERWORKS_EPB,
bridge);
if (bridge && bridge->subordinate &&
(bridge->subordinate->number <=
tp->pdev->bus->number) &&
(bridge->subordinate->subordinate >=
tp->pdev->bus->number)) {
tp->tg3_flags |= TG3_FLAG_40BIT_DMA_BUG;
pci_dev_put(bridge);
break;
}
} while (bridge);
}
/* Initialize misc host control in PCI block. */ /* Initialize misc host control in PCI block. */
tp->misc_host_ctrl |= (misc_ctrl_reg & tp->misc_host_ctrl |= (misc_ctrl_reg &
...@@ -10303,7 +10327,14 @@ static int __devinit tg3_test_dma(struct tg3 *tp) ...@@ -10303,7 +10327,14 @@ static int __devinit tg3_test_dma(struct tg3 *tp)
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) { GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
u32 ccval = (tr32(TG3PCI_CLOCK_CTRL) & 0x1f); u32 ccval = (tr32(TG3PCI_CLOCK_CTRL) & 0x1f);
if (ccval == 0x6 || ccval == 0x7) /* If the 5704 is behind the EPB bridge, we can
* do the less restrictive ONE_DMA workaround for
* better performance.
*/
if ((tp->tg3_flags & TG3_FLAG_40BIT_DMA_BUG) &&
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704)
tp->dma_rwctrl |= 0x8000;
else if (ccval == 0x6 || ccval == 0x7)
tp->dma_rwctrl |= DMA_RWCTRL_ONE_DMA; tp->dma_rwctrl |= DMA_RWCTRL_ONE_DMA;
/* Set bit 23 to enable PCIX hw bug fix */ /* Set bit 23 to enable PCIX hw bug fix */
...@@ -10759,19 +10790,20 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, ...@@ -10759,19 +10790,20 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
goto err_out_iounmap; goto err_out_iounmap;
} }
/* 5714, 5715 and 5780 cannot support DMA addresses > 40-bit. /* The EPB bridge inside 5714, 5715, and 5780 and any
* device behind the EPB cannot support DMA addresses > 40-bit.
* On 64-bit systems with IOMMU, use 40-bit dma_mask. * On 64-bit systems with IOMMU, use 40-bit dma_mask.
* On 64-bit systems without IOMMU, use 64-bit dma_mask and * On 64-bit systems without IOMMU, use 64-bit dma_mask and
* do DMA address check in tg3_start_xmit(). * do DMA address check in tg3_start_xmit().
*/ */
if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) { if (tp->tg3_flags2 & TG3_FLG2_IS_5788)
persist_dma_mask = dma_mask = DMA_32BIT_MASK;
else if (tp->tg3_flags & TG3_FLAG_40BIT_DMA_BUG) {
persist_dma_mask = dma_mask = DMA_40BIT_MASK; persist_dma_mask = dma_mask = DMA_40BIT_MASK;
#ifdef CONFIG_HIGHMEM #ifdef CONFIG_HIGHMEM
dma_mask = DMA_64BIT_MASK; dma_mask = DMA_64BIT_MASK;
#endif #endif
} else if (tp->tg3_flags2 & TG3_FLG2_IS_5788) } else
persist_dma_mask = dma_mask = DMA_32BIT_MASK;
else
persist_dma_mask = dma_mask = DMA_64BIT_MASK; persist_dma_mask = dma_mask = DMA_64BIT_MASK;
/* Configure DMA attributes. */ /* Configure DMA attributes. */
...@@ -10908,8 +10940,10 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, ...@@ -10908,8 +10940,10 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
(tp->tg3_flags & TG3_FLAG_SPLIT_MODE) != 0, (tp->tg3_flags & TG3_FLAG_SPLIT_MODE) != 0,
(tp->tg3_flags2 & TG3_FLG2_NO_ETH_WIRE_SPEED) == 0, (tp->tg3_flags2 & TG3_FLG2_NO_ETH_WIRE_SPEED) == 0,
(tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) != 0); (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) != 0);
printk(KERN_INFO "%s: dma_rwctrl[%08x]\n", printk(KERN_INFO "%s: dma_rwctrl[%08x] dma_mask[%d-bit]\n",
dev->name, tp->dma_rwctrl); dev->name, tp->dma_rwctrl,
(pdev->dma_mask == DMA_32BIT_MASK) ? 32 :
(((u64) pdev->dma_mask == DMA_40BIT_MASK) ? 40 : 64));
return 0; return 0;
......
...@@ -2163,6 +2163,7 @@ struct tg3 { ...@@ -2163,6 +2163,7 @@ struct tg3 {
#define TG3_FLAG_10_100_ONLY 0x01000000 #define TG3_FLAG_10_100_ONLY 0x01000000
#define TG3_FLAG_PAUSE_AUTONEG 0x02000000 #define TG3_FLAG_PAUSE_AUTONEG 0x02000000
#define TG3_FLAG_IN_RESET_TASK 0x04000000 #define TG3_FLAG_IN_RESET_TASK 0x04000000
#define TG3_FLAG_40BIT_DMA_BUG 0x08000000
#define TG3_FLAG_BROKEN_CHECKSUMS 0x10000000 #define TG3_FLAG_BROKEN_CHECKSUMS 0x10000000
#define TG3_FLAG_GOT_SERDES_FLOWCTL 0x20000000 #define TG3_FLAG_GOT_SERDES_FLOWCTL 0x20000000
#define TG3_FLAG_SPLIT_MODE 0x40000000 #define TG3_FLAG_SPLIT_MODE 0x40000000
......
...@@ -1365,6 +1365,7 @@ ...@@ -1365,6 +1365,7 @@
#define PCI_DEVICE_ID_SERVERWORKS_HE 0x0008 #define PCI_DEVICE_ID_SERVERWORKS_HE 0x0008
#define PCI_DEVICE_ID_SERVERWORKS_LE 0x0009 #define PCI_DEVICE_ID_SERVERWORKS_LE 0x0009
#define PCI_DEVICE_ID_SERVERWORKS_GCNB_LE 0x0017 #define PCI_DEVICE_ID_SERVERWORKS_GCNB_LE 0x0017
#define PCI_DEVICE_ID_SERVERWORKS_EPB 0x0103
#define PCI_DEVICE_ID_SERVERWORKS_OSB4 0x0200 #define PCI_DEVICE_ID_SERVERWORKS_OSB4 0x0200
#define PCI_DEVICE_ID_SERVERWORKS_CSB5 0x0201 #define PCI_DEVICE_ID_SERVERWORKS_CSB5 0x0201
#define PCI_DEVICE_ID_SERVERWORKS_CSB6 0x0203 #define PCI_DEVICE_ID_SERVERWORKS_CSB6 0x0203
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment