Re: [PATCH 10/21] e1000: force register write flushes to circumvent broken platforms
Jeff Garzik wrote: Kok, Auke wrote: A certain AMD64 bridge (8132) has an option to turn on write combining which breaks our adapter. To circumvent this we need to flush every write. Signed-off-by: Jesse Brandeburg [EMAIL PROTECTED] Signed-off-by: Auke Kok [EMAIL PROTECTED] --- drivers/net/e1000/e1000_hw.c | 24 ++-- drivers/net/e1000/e1000_main.c | 18 +++--- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c index 3959039..749d621 100644 --- a/drivers/net/e1000/e1000_hw.c +++ b/drivers/net/e1000/e1000_hw.c @@ -705,8 +705,12 @@ e1000_init_hw(struct e1000_hw *hw) /* Zero out the Multicast HASH table */ DEBUGOUT(Zeroing the MTA\n); mta_size = E1000_MC_TBL_SIZE; -for(i = 0; i mta_size; i++) +for(i = 0; i mta_size; i++) { E1000_WRITE_REG_ARRAY(hw, MTA, i, 0); +/* use write flush to prevent Memory Write Block (MWB) from + * occuring when accessing our register space */ +E1000_WRITE_FLUSH(hw); +} NAK. We can't crap up every driver just for one weird piece of hardware. If this problem falls outside the grounds of mmiowb() [see Documentation/memory-barriers.txt], then other solutions need to be looked into... ioremap_nocache() ? Tweaking the MTRR for this region? Chipset quirk? ... If there is an in-kernel fix for this that would make these flushes obsolete I would certainly prefer it too, unfortunately we can't fix already released kernels and our driver still needs to work there too, so that's why I queued it. It can be dropped from this series if that's preferred. Cheers, Auke - To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 10/21] e1000: force register write flushes to circumvent broken platforms
Auke Kok wrote: If there is an in-kernel fix for this that would make these flushes obsolete I would certainly prefer it too, unfortunately we can't fix already released kernels and our driver still needs to work there too, so that's why I queued it. It can be dropped from this series if that's preferred. Yes, definitely drop it from the series... Jeff - To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 10/21] e1000: force register write flushes to circumvent broken platforms
Auke Kok wrote: Jeff Garzik wrote: Kok, Auke wrote: A certain AMD64 bridge (8132) has an option to turn on write combining which breaks our adapter. To circumvent this we need to flush every write. Signed-off-by: Jesse Brandeburg [EMAIL PROTECTED] Signed-off-by: Auke Kok [EMAIL PROTECTED] --- drivers/net/e1000/e1000_hw.c | 24 ++-- drivers/net/e1000/e1000_main.c | 18 +++--- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c index 3959039..749d621 100644 --- a/drivers/net/e1000/e1000_hw.c +++ b/drivers/net/e1000/e1000_hw.c @@ -705,8 +705,12 @@ e1000_init_hw(struct e1000_hw *hw) /* Zero out the Multicast HASH table */ DEBUGOUT(Zeroing the MTA\n); mta_size = E1000_MC_TBL_SIZE; -for(i = 0; i mta_size; i++) +for(i = 0; i mta_size; i++) { E1000_WRITE_REG_ARRAY(hw, MTA, i, 0); +/* use write flush to prevent Memory Write Block (MWB) from + * occuring when accessing our register space */ +E1000_WRITE_FLUSH(hw); +} NAK. We can't crap up every driver just for one weird piece of hardware. If this problem falls outside the grounds of mmiowb() [see Documentation/memory-barriers.txt], then other solutions need to be looked into... ioremap_nocache() ? Tweaking the MTRR for this region? Chipset quirk? ... If there is an in-kernel fix for this that would make these flushes obsolete I would certainly prefer it too, unfortunately we can't fix already released kernels and our driver still needs to work there too, so that's why I queued it. It can be dropped from this series if that's preferred. I have to get back on that - it's not as simple as the platform is broken. e1000's don't support write-combining in hardware but the problem only shows itself during initialization. This patch makes it work on AMD platforms with write-combining enabled, the platform itself isn't broken - technically the NIC is (ixgb doesn't have this problem for instance). The added write flushes are at initialization only, and fix the problem for any other case. I don't see much harm in that. Auke - To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 10/21] e1000: force register write flushes to circumvent broken platforms
Kok, Auke wrote: A certain AMD64 bridge (8132) has an option to turn on write combining which breaks our adapter. To circumvent this we need to flush every write. Signed-off-by: Jesse Brandeburg [EMAIL PROTECTED] Signed-off-by: Auke Kok [EMAIL PROTECTED] --- drivers/net/e1000/e1000_hw.c | 24 ++-- drivers/net/e1000/e1000_main.c | 18 +++--- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c index 3959039..749d621 100644 --- a/drivers/net/e1000/e1000_hw.c +++ b/drivers/net/e1000/e1000_hw.c @@ -705,8 +705,12 @@ e1000_init_hw(struct e1000_hw *hw) /* Zero out the Multicast HASH table */ DEBUGOUT(Zeroing the MTA\n); mta_size = E1000_MC_TBL_SIZE; -for(i = 0; i mta_size; i++) +for(i = 0; i mta_size; i++) { E1000_WRITE_REG_ARRAY(hw, MTA, i, 0); +/* use write flush to prevent Memory Write Block (MWB) from + * occuring when accessing our register space */ +E1000_WRITE_FLUSH(hw); +} NAK. We can't crap up every driver just for one weird piece of hardware. If this problem falls outside the grounds of mmiowb() [see Documentation/memory-barriers.txt], then other solutions need to be looked into... ioremap_nocache() ? Tweaking the MTRR for this region? Chipset quirk? ... Jeff - To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 10/21] e1000: force register write flushes to circumvent broken platforms
A certain AMD64 bridge (8132) has an option to turn on write combining which breaks our adapter. To circumvent this we need to flush every write. Signed-off-by: Jesse Brandeburg [EMAIL PROTECTED] Signed-off-by: Auke Kok [EMAIL PROTECTED] --- drivers/net/e1000/e1000_hw.c | 24 ++-- drivers/net/e1000/e1000_main.c | 18 +++--- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c index 3959039..749d621 100644 --- a/drivers/net/e1000/e1000_hw.c +++ b/drivers/net/e1000/e1000_hw.c @@ -705,8 +705,12 @@ e1000_init_hw(struct e1000_hw *hw) /* Zero out the Multicast HASH table */ DEBUGOUT(Zeroing the MTA\n); mta_size = E1000_MC_TBL_SIZE; -for(i = 0; i mta_size; i++) +for(i = 0; i mta_size; i++) { E1000_WRITE_REG_ARRAY(hw, MTA, i, 0); +/* use write flush to prevent Memory Write Block (MWB) from + * occuring when accessing our register space */ +E1000_WRITE_FLUSH(hw); +} /* Set the PCI priority bit correctly in the CTRL register. This * determines if the adapter gives priority to receives, or if it @@ -5106,7 +5110,9 @@ e1000_init_rx_addrs(struct e1000_hw *hw) DEBUGOUT(Clearing RAR[1-15]\n); for(i = 1; i rar_num; i++) { E1000_WRITE_REG_ARRAY(hw, RA, (i 1), 0); +E1000_WRITE_FLUSH(hw); E1000_WRITE_REG_ARRAY(hw, RA, ((i 1) + 1), 0); +E1000_WRITE_FLUSH(hw); } } @@ -5153,7 +5159,9 @@ e1000_mc_addr_list_update(struct e1000_h for(i = rar_used_count; i num_rar_entry; i++) { E1000_WRITE_REG_ARRAY(hw, RA, (i 1), 0); +E1000_WRITE_FLUSH(hw); E1000_WRITE_REG_ARRAY(hw, RA, ((i 1) + 1), 0); +E1000_WRITE_FLUSH(hw); } /* Clear the MTA */ @@ -5161,6 +5169,7 @@ e1000_mc_addr_list_update(struct e1000_h num_mta_entry = E1000_NUM_MTA_REGISTERS; for(i = 0; i num_mta_entry; i++) { E1000_WRITE_REG_ARRAY(hw, MTA, i, 0); +E1000_WRITE_FLUSH(hw); } /* Add the new addresses */ @@ -5275,9 +5284,12 @@ e1000_mta_set(struct e1000_hw *hw, if((hw-mac_type == e1000_82544) ((hash_reg 0x1) == 1)) { temp = E1000_READ_REG_ARRAY(hw, MTA, (hash_reg - 1)); E1000_WRITE_REG_ARRAY(hw, MTA, hash_reg, mta); +E1000_WRITE_FLUSH(hw); E1000_WRITE_REG_ARRAY(hw, MTA, (hash_reg - 1), temp); +E1000_WRITE_FLUSH(hw); } else { E1000_WRITE_REG_ARRAY(hw, MTA, hash_reg, mta); +E1000_WRITE_FLUSH(hw); } } @@ -5334,7 +5346,9 @@ e1000_rar_set(struct e1000_hw *hw, } E1000_WRITE_REG_ARRAY(hw, RA, (index 1), rar_low); +E1000_WRITE_FLUSH(hw); E1000_WRITE_REG_ARRAY(hw, RA, ((index 1) + 1), rar_high); +E1000_WRITE_FLUSH(hw); } /** @@ -5354,9 +5368,12 @@ e1000_write_vfta(struct e1000_hw *hw, if((hw-mac_type == e1000_82544) ((offset 0x1) == 1)) { temp = E1000_READ_REG_ARRAY(hw, VFTA, (offset - 1)); E1000_WRITE_REG_ARRAY(hw, VFTA, offset, value); +E1000_WRITE_FLUSH(hw); E1000_WRITE_REG_ARRAY(hw, VFTA, (offset - 1), temp); +E1000_WRITE_FLUSH(hw); } else { E1000_WRITE_REG_ARRAY(hw, VFTA, offset, value); +E1000_WRITE_FLUSH(hw); } } @@ -5392,6 +5409,7 @@ e1000_clear_vfta(struct e1000_hw *hw) * manageability unit */ vfta_value = (offset == vfta_offset) ? vfta_bit_in_reg : 0; E1000_WRITE_REG_ARRAY(hw, VFTA, offset, vfta_value); +E1000_WRITE_FLUSH(hw); } } @@ -6928,8 +6946,10 @@ e1000_mng_write_cmd_header(struct e1000_ length = 2; /* The device driver writes the relevant command block into the ram area. */ -for (i = 0; i length; i++) +for (i = 0; i length; i++) { E1000_WRITE_REG_ARRAY_DWORD(hw, HOST_IF, i, *((uint32_t *) hdr + i)); +E1000_WRITE_FLUSH(hw); +} return E1000_SUCCESS; } diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index c58fafd..c44ed6f 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -1370,11 +1370,11 @@ e1000_configure_tx(struct e1000_adapter tdba = adapter-tx_ring[0].dma; tdlen = adapter-tx_ring[0].count * sizeof(struct e1000_tx_desc); - E1000_WRITE_REG(hw, TDBAL, (tdba 0xULL)); - E1000_WRITE_REG(hw, TDBAH, (tdba 32)); E1000_WRITE_REG(hw, TDLEN, tdlen); - E1000_WRITE_REG(hw, TDH, 0); + E1000_WRITE_REG(hw, TDBAH, (tdba 32)); + E1000_WRITE_REG(hw, TDBAL, (tdba 0xULL)); E1000_WRITE_REG(hw, TDT, 0); + E1000_WRITE_REG(hw, TDH, 0); adapter-tx_ring[0].tdh = E1000_TDH; adapter-tx_ring[0].tdt =