mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-11-01 17:08:10 +00:00
[TG3]: Refine DMA boundary setting.
Extract DMA boundary bit selection into a seperate function, tg3_calc_dma_bndry(). Call this from tg3_test_dma(). Make DMA test more reliable by using no DMA boundry setting during the test. If the test passes, then use the setting we selected before the test. Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Michael Chan <mchan@broadcom.com>
This commit is contained in:
parent
15f9850d3c
commit
59e6b43432
1 changed files with 163 additions and 44 deletions
|
@ -8775,6 +8775,146 @@ static int __devinit tg3_get_device_address(struct tg3 *tp)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define BOUNDARY_SINGLE_CACHELINE 1
|
||||
#define BOUNDARY_MULTI_CACHELINE 2
|
||||
|
||||
static u32 __devinit tg3_calc_dma_bndry(struct tg3 *tp, u32 val)
|
||||
{
|
||||
int cacheline_size;
|
||||
u8 byte;
|
||||
int goal;
|
||||
|
||||
pci_read_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE, &byte);
|
||||
if (byte == 0)
|
||||
cacheline_size = 1024;
|
||||
else
|
||||
cacheline_size = (int) byte * 4;
|
||||
|
||||
/* On 5703 and later chips, the boundary bits have no
|
||||
* effect.
|
||||
*/
|
||||
if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 &&
|
||||
GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701 &&
|
||||
!(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS))
|
||||
goto out;
|
||||
|
||||
#if defined(CONFIG_PPC64) || defined(CONFIG_IA64) || defined(CONFIG_PARISC)
|
||||
goal = BOUNDARY_MULTI_CACHELINE;
|
||||
#else
|
||||
#if defined(CONFIG_SPARC64) || defined(CONFIG_ALPHA)
|
||||
goal = BOUNDARY_SINGLE_CACHELINE;
|
||||
#else
|
||||
goal = 0;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (!goal)
|
||||
goto out;
|
||||
|
||||
/* PCI controllers on most RISC systems tend to disconnect
|
||||
* when a device tries to burst across a cache-line boundary.
|
||||
* Therefore, letting tg3 do so just wastes PCI bandwidth.
|
||||
*
|
||||
* Unfortunately, for PCI-E there are only limited
|
||||
* write-side controls for this, and thus for reads
|
||||
* we will still get the disconnects. We'll also waste
|
||||
* these PCI cycles for both read and write for chips
|
||||
* other than 5700 and 5701 which do not implement the
|
||||
* boundary bits.
|
||||
*/
|
||||
if ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) &&
|
||||
!(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)) {
|
||||
switch (cacheline_size) {
|
||||
case 16:
|
||||
case 32:
|
||||
case 64:
|
||||
case 128:
|
||||
if (goal == BOUNDARY_SINGLE_CACHELINE) {
|
||||
val |= (DMA_RWCTRL_READ_BNDRY_128_PCIX |
|
||||
DMA_RWCTRL_WRITE_BNDRY_128_PCIX);
|
||||
} else {
|
||||
val |= (DMA_RWCTRL_READ_BNDRY_384_PCIX |
|
||||
DMA_RWCTRL_WRITE_BNDRY_384_PCIX);
|
||||
}
|
||||
break;
|
||||
|
||||
case 256:
|
||||
val |= (DMA_RWCTRL_READ_BNDRY_256_PCIX |
|
||||
DMA_RWCTRL_WRITE_BNDRY_256_PCIX);
|
||||
break;
|
||||
|
||||
default:
|
||||
val |= (DMA_RWCTRL_READ_BNDRY_384_PCIX |
|
||||
DMA_RWCTRL_WRITE_BNDRY_384_PCIX);
|
||||
break;
|
||||
};
|
||||
} else if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) {
|
||||
switch (cacheline_size) {
|
||||
case 16:
|
||||
case 32:
|
||||
case 64:
|
||||
if (goal == BOUNDARY_SINGLE_CACHELINE) {
|
||||
val &= ~DMA_RWCTRL_WRITE_BNDRY_DISAB_PCIE;
|
||||
val |= DMA_RWCTRL_WRITE_BNDRY_64_PCIE;
|
||||
break;
|
||||
}
|
||||
/* fallthrough */
|
||||
case 128:
|
||||
default:
|
||||
val &= ~DMA_RWCTRL_WRITE_BNDRY_DISAB_PCIE;
|
||||
val |= DMA_RWCTRL_WRITE_BNDRY_128_PCIE;
|
||||
break;
|
||||
};
|
||||
} else {
|
||||
switch (cacheline_size) {
|
||||
case 16:
|
||||
if (goal == BOUNDARY_SINGLE_CACHELINE) {
|
||||
val |= (DMA_RWCTRL_READ_BNDRY_16 |
|
||||
DMA_RWCTRL_WRITE_BNDRY_16);
|
||||
break;
|
||||
}
|
||||
/* fallthrough */
|
||||
case 32:
|
||||
if (goal == BOUNDARY_SINGLE_CACHELINE) {
|
||||
val |= (DMA_RWCTRL_READ_BNDRY_32 |
|
||||
DMA_RWCTRL_WRITE_BNDRY_32);
|
||||
break;
|
||||
}
|
||||
/* fallthrough */
|
||||
case 64:
|
||||
if (goal == BOUNDARY_SINGLE_CACHELINE) {
|
||||
val |= (DMA_RWCTRL_READ_BNDRY_64 |
|
||||
DMA_RWCTRL_WRITE_BNDRY_64);
|
||||
break;
|
||||
}
|
||||
/* fallthrough */
|
||||
case 128:
|
||||
if (goal == BOUNDARY_SINGLE_CACHELINE) {
|
||||
val |= (DMA_RWCTRL_READ_BNDRY_128 |
|
||||
DMA_RWCTRL_WRITE_BNDRY_128);
|
||||
break;
|
||||
}
|
||||
/* fallthrough */
|
||||
case 256:
|
||||
val |= (DMA_RWCTRL_READ_BNDRY_256 |
|
||||
DMA_RWCTRL_WRITE_BNDRY_256);
|
||||
break;
|
||||
case 512:
|
||||
val |= (DMA_RWCTRL_READ_BNDRY_512 |
|
||||
DMA_RWCTRL_WRITE_BNDRY_512);
|
||||
break;
|
||||
case 1024:
|
||||
default:
|
||||
val |= (DMA_RWCTRL_READ_BNDRY_1024 |
|
||||
DMA_RWCTRL_WRITE_BNDRY_1024);
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
out:
|
||||
return val;
|
||||
}
|
||||
|
||||
static int __devinit tg3_do_test_dma(struct tg3 *tp, u32 *buf, dma_addr_t buf_dma, int size, int to_device)
|
||||
{
|
||||
struct tg3_internal_buffer_desc test_desc;
|
||||
|
@ -8861,7 +9001,7 @@ static int __devinit tg3_do_test_dma(struct tg3 *tp, u32 *buf, dma_addr_t buf_dm
|
|||
static int __devinit tg3_test_dma(struct tg3 *tp)
|
||||
{
|
||||
dma_addr_t buf_dma;
|
||||
u32 *buf;
|
||||
u32 *buf, saved_dma_rwctrl;
|
||||
int ret;
|
||||
|
||||
buf = pci_alloc_consistent(tp->pdev, TEST_BUFFER_SIZE, &buf_dma);
|
||||
|
@ -8873,46 +9013,7 @@ static int __devinit tg3_test_dma(struct tg3 *tp)
|
|||
tp->dma_rwctrl = ((0x7 << DMA_RWCTRL_PCI_WRITE_CMD_SHIFT) |
|
||||
(0x6 << DMA_RWCTRL_PCI_READ_CMD_SHIFT));
|
||||
|
||||
#ifndef CONFIG_X86
|
||||
{
|
||||
u8 byte;
|
||||
int cacheline_size;
|
||||
pci_read_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE, &byte);
|
||||
|
||||
if (byte == 0)
|
||||
cacheline_size = 1024;
|
||||
else
|
||||
cacheline_size = (int) byte * 4;
|
||||
|
||||
switch (cacheline_size) {
|
||||
case 16:
|
||||
case 32:
|
||||
case 64:
|
||||
case 128:
|
||||
if ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) &&
|
||||
!(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)) {
|
||||
tp->dma_rwctrl |=
|
||||
DMA_RWCTRL_WRITE_BNDRY_384_PCIX;
|
||||
break;
|
||||
} else if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) {
|
||||
tp->dma_rwctrl &=
|
||||
~(DMA_RWCTRL_PCI_WRITE_CMD);
|
||||
tp->dma_rwctrl |=
|
||||
DMA_RWCTRL_WRITE_BNDRY_128_PCIE;
|
||||
break;
|
||||
}
|
||||
/* fallthrough */
|
||||
case 256:
|
||||
if (!(tp->tg3_flags & TG3_FLAG_PCIX_MODE) &&
|
||||
!(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS))
|
||||
tp->dma_rwctrl |=
|
||||
DMA_RWCTRL_WRITE_BNDRY_256;
|
||||
else if (!(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS))
|
||||
tp->dma_rwctrl |=
|
||||
DMA_RWCTRL_WRITE_BNDRY_256_PCIX;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
tp->dma_rwctrl = tg3_calc_dma_bndry(tp, tp->dma_rwctrl);
|
||||
|
||||
if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) {
|
||||
/* DMA read watermark not used on PCIE */
|
||||
|
@ -8931,7 +9032,7 @@ static int __devinit tg3_test_dma(struct tg3 *tp)
|
|||
if (ccval == 0x6 || ccval == 0x7)
|
||||
tp->dma_rwctrl |= DMA_RWCTRL_ONE_DMA;
|
||||
|
||||
/* Set bit 23 to renable PCIX hw bug fix */
|
||||
/* Set bit 23 to enable PCIX hw bug fix */
|
||||
tp->dma_rwctrl |= 0x009f0000;
|
||||
} else {
|
||||
tp->dma_rwctrl |= 0x001b000f;
|
||||
|
@ -8972,6 +9073,13 @@ static int __devinit tg3_test_dma(struct tg3 *tp)
|
|||
GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701)
|
||||
goto out;
|
||||
|
||||
/* It is best to perform DMA test with maximum write burst size
|
||||
* to expose the 5700/5701 write DMA bug.
|
||||
*/
|
||||
saved_dma_rwctrl = tp->dma_rwctrl;
|
||||
tp->dma_rwctrl &= ~DMA_RWCTRL_WRITE_BNDRY_MASK;
|
||||
tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl);
|
||||
|
||||
while (1) {
|
||||
u32 *p = buf, i;
|
||||
|
||||
|
@ -9010,8 +9118,9 @@ static int __devinit tg3_test_dma(struct tg3 *tp)
|
|||
if (p[i] == i)
|
||||
continue;
|
||||
|
||||
if ((tp->dma_rwctrl & DMA_RWCTRL_WRITE_BNDRY_MASK) ==
|
||||
DMA_RWCTRL_WRITE_BNDRY_DISAB) {
|
||||
if ((tp->dma_rwctrl & DMA_RWCTRL_WRITE_BNDRY_MASK) !=
|
||||
DMA_RWCTRL_WRITE_BNDRY_16) {
|
||||
tp->dma_rwctrl &= ~DMA_RWCTRL_WRITE_BNDRY_MASK;
|
||||
tp->dma_rwctrl |= DMA_RWCTRL_WRITE_BNDRY_16;
|
||||
tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl);
|
||||
break;
|
||||
|
@ -9028,6 +9137,14 @@ static int __devinit tg3_test_dma(struct tg3 *tp)
|
|||
break;
|
||||
}
|
||||
}
|
||||
if ((tp->dma_rwctrl & DMA_RWCTRL_WRITE_BNDRY_MASK) !=
|
||||
DMA_RWCTRL_WRITE_BNDRY_16) {
|
||||
/* DMA test passed without adjusting DMA boundary,
|
||||
* just restore the calculated DMA boundary
|
||||
*/
|
||||
tp->dma_rwctrl = saved_dma_rwctrl;
|
||||
tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl);
|
||||
}
|
||||
|
||||
out:
|
||||
pci_free_consistent(tp->pdev, TEST_BUFFER_SIZE, buf, buf_dma);
|
||||
|
@ -9429,6 +9546,8 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
|
|||
(tp->tg3_flags & TG3_FLAG_SPLIT_MODE) != 0,
|
||||
(tp->tg3_flags2 & TG3_FLG2_NO_ETH_WIRE_SPEED) == 0,
|
||||
(tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) != 0);
|
||||
printk(KERN_INFO "%s: dma_rwctrl[%08x]\n",
|
||||
dev->name, tp->dma_rwctrl);
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
Loading…
Reference in a new issue