summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFenghua Yu <fenghua.yu@intel.com>2020-01-02 13:27:06 -0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-02-01 09:37:08 +0000
commit6079715f2cc204bb381fbbcd7ae0d9b9ef6b32de (patch)
treee484c4a3077ae30d0e786946d3ed5380fdf8dab7
parent6fb12237c51e73e65899f9b1df69cd3999b4d90a (diff)
downloadlinux-stable-6079715f2cc204bb381fbbcd7ae0d9b9ef6b32de.tar.gz
linux-stable-6079715f2cc204bb381fbbcd7ae0d9b9ef6b32de.tar.bz2
linux-stable-6079715f2cc204bb381fbbcd7ae0d9b9ef6b32de.zip
drivers/net/b44: Change to non-atomic bit operations on pwol_mask
[ Upstream commit f11421ba4af706cb4f5703de34fa77fba8472776 ] Atomic operations that span cache lines are super-expensive on x86 (not just to the current processor, but also to other processes as all memory operations are blocked until the operation completes). Upcoming x86 processors have a switch to cause such operations to generate a #AC trap. It is expected that some real time systems will enable this mode in BIOS. In preparation for this, it is necessary to fix code that may execute atomic instructions with operands that cross cachelines because the #AC trap will crash the kernel. Since "pwol_mask" is local and never exposed to concurrency, there is no need to set bits in pwol_mask using atomic operations. Directly operate on the byte which contains the bit instead of using __set_bit() to avoid any big endian concern due to type cast to unsigned long in __set_bit(). Suggested-by: Peter Zijlstra <peterz@infradead.org> Signed-off-by: Fenghua Yu <fenghua.yu@intel.com> Signed-off-by: Tony Luck <tony.luck@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r--drivers/net/ethernet/broadcom/b44.c9
1 files changed, 6 insertions, 3 deletions
diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c
index e445ab724827..88f8d31e4c83 100644
--- a/drivers/net/ethernet/broadcom/b44.c
+++ b/drivers/net/ethernet/broadcom/b44.c
@@ -1519,8 +1519,10 @@ static int b44_magic_pattern(u8 *macaddr, u8 *ppattern, u8 *pmask, int offset)
int ethaddr_bytes = ETH_ALEN;
memset(ppattern + offset, 0xff, magicsync);
- for (j = 0; j < magicsync; j++)
- set_bit(len++, (unsigned long *) pmask);
+ for (j = 0; j < magicsync; j++) {
+ pmask[len >> 3] |= BIT(len & 7);
+ len++;
+ }
for (j = 0; j < B44_MAX_PATTERNS; j++) {
if ((B44_PATTERN_SIZE - len) >= ETH_ALEN)
@@ -1532,7 +1534,8 @@ static int b44_magic_pattern(u8 *macaddr, u8 *ppattern, u8 *pmask, int offset)
for (k = 0; k< ethaddr_bytes; k++) {
ppattern[offset + magicsync +
(j * ETH_ALEN) + k] = macaddr[k];
- set_bit(len++, (unsigned long *) pmask);
+ pmask[len >> 3] |= BIT(len & 7);
+ len++;
}
}
return len - 1;