2012-08-07 11:08:50

by Takuya Yoshikawa

[permalink] [raw]
Subject: [PATCH 0/5 - RESEND] Introduce generic set_bit_le()

This is against today's linux-next.

KVM is using test_and_set_bit_le() for this missing function; this patch
series corrects this usage.

As some drivers have their own definitions of set_bit_le(), a bit of
preparation is also needed.

Although these are differently implemented, especially for big-endian
case, than the generic __set_bit_le(), it should not be a problem to
use the latter since both maintainers prefer it.

Ben Hutchings (1):
sfc: Use standard __{clear,set}_bit_le() functions

Takuya Yoshikawa (4):
drivers/net/ethernet/dec/tulip: Use standard __set_bit_le() function
bitops: Introduce generic {clear,set}_bit_le()
powerpc: bitops: Introduce {clear,set}_bit_le()
KVM: Replace test_and_set_bit_le() in mark_page_dirty_in_slot() with set_bit_le()

arch/powerpc/include/asm/bitops.h | 10 ++++++++++
drivers/net/ethernet/dec/tulip/de2104x.c | 7 ++-----
drivers/net/ethernet/dec/tulip/tulip_core.c | 7 ++-----
drivers/net/ethernet/sfc/efx.c | 4 ++--
drivers/net/ethernet/sfc/net_driver.h | 12 ------------
drivers/net/ethernet/sfc/nic.c | 4 ++--
include/asm-generic/bitops/le.h | 10 ++++++++++
virt/kvm/kvm_main.c | 3 +--
8 files changed, 29 insertions(+), 28 deletions(-)

--
1.7.5.4


2012-08-07 11:09:50

by Takuya Yoshikawa

[permalink] [raw]
Subject: [PATCH 1/5] sfc: Use standard __{clear,set}_bit_le() functions

From: Ben Hutchings <[email protected]>

There are now standard functions for dealing with little-endian bit
arrays, so use them instead of our own implementations.

Signed-off-by: Ben Hutchings <[email protected]>
Signed-off-by: Takuya Yoshikawa <[email protected]>
---
drivers/net/ethernet/sfc/efx.c | 4 ++--
drivers/net/ethernet/sfc/net_driver.h | 12 ------------
drivers/net/ethernet/sfc/nic.c | 4 ++--
3 files changed, 4 insertions(+), 16 deletions(-)

diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index 65a8d49..7ceac47 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -1981,14 +1981,14 @@ static void efx_set_rx_mode(struct net_device *net_dev)
netdev_for_each_mc_addr(ha, net_dev) {
crc = ether_crc_le(ETH_ALEN, ha->addr);
bit = crc & (EFX_MCAST_HASH_ENTRIES - 1);
- set_bit_le(bit, mc_hash->byte);
+ __set_bit_le(bit, mc_hash);
}

/* Broadcast packets go through the multicast hash filter.
* ether_crc_le() of the broadcast address is 0xbe2612ff
* so we always add bit 0xff to the mask.
*/
- set_bit_le(0xff, mc_hash->byte);
+ __set_bit_le(0xff, mc_hash);
}

if (efx->port_enabled)
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index cd9c0a9..406ea85 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -1083,18 +1083,6 @@ static inline struct efx_rx_buffer *efx_rx_buffer(struct efx_rx_queue *rx_queue,
return &rx_queue->buffer[index];
}

-/* Set bit in a little-endian bitfield */
-static inline void set_bit_le(unsigned nr, unsigned char *addr)
-{
- addr[nr / 8] |= (1 << (nr % 8));
-}
-
-/* Clear bit in a little-endian bitfield */
-static inline void clear_bit_le(unsigned nr, unsigned char *addr)
-{
- addr[nr / 8] &= ~(1 << (nr % 8));
-}
-

/**
* EFX_MAX_FRAME_LEN - calculate maximum frame length
diff --git a/drivers/net/ethernet/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c
index 326d799..d358966 100644
--- a/drivers/net/ethernet/sfc/nic.c
+++ b/drivers/net/ethernet/sfc/nic.c
@@ -470,9 +470,9 @@ void efx_nic_init_tx(struct efx_tx_queue *tx_queue)

efx_reado(efx, &reg, FR_AA_TX_CHKSM_CFG);
if (tx_queue->queue & EFX_TXQ_TYPE_OFFLOAD)
- clear_bit_le(tx_queue->queue, (void *)&reg);
+ __clear_bit_le(tx_queue->queue, &reg);
else
- set_bit_le(tx_queue->queue, (void *)&reg);
+ __set_bit_le(tx_queue->queue, &reg);
efx_writeo(efx, &reg, FR_AA_TX_CHKSM_CFG);
}

--
1.7.5.4

2012-08-07 11:10:30

by Takuya Yoshikawa

[permalink] [raw]
Subject: [PATCH 2/5] drivers/net/ethernet/dec/tulip: Use standard __set_bit_le() function

From: Takuya Yoshikawa <[email protected]>

To introduce generic set_bit_le() later, we remove our own definition
and use a proper non-atomic bitops function: __set_bit_le().

Signed-off-by: Takuya Yoshikawa <[email protected]>
Acked-by: Grant Grundler <[email protected]>
---
drivers/net/ethernet/dec/tulip/de2104x.c | 7 ++-----
drivers/net/ethernet/dec/tulip/tulip_core.c | 7 ++-----
2 files changed, 4 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ethernet/dec/tulip/de2104x.c b/drivers/net/ethernet/dec/tulip/de2104x.c
index 61cc093..77335853 100644
--- a/drivers/net/ethernet/dec/tulip/de2104x.c
+++ b/drivers/net/ethernet/dec/tulip/de2104x.c
@@ -661,9 +661,6 @@ static netdev_tx_t de_start_xmit (struct sk_buff *skb,
new frame, not around filling de->setup_frame. This is non-deterministic
when re-entered but still correct. */

-#undef set_bit_le
-#define set_bit_le(i,p) do { ((char *)(p))[(i)/8] |= (1<<((i)%8)); } while(0)
-
static void build_setup_frame_hash(u16 *setup_frm, struct net_device *dev)
{
struct de_private *de = netdev_priv(dev);
@@ -673,12 +670,12 @@ static void build_setup_frame_hash(u16 *setup_frm, struct net_device *dev)
u16 *eaddrs;

memset(hash_table, 0, sizeof(hash_table));
- set_bit_le(255, hash_table); /* Broadcast entry */
+ __set_bit_le(255, hash_table); /* Broadcast entry */
/* This should work on big-endian machines as well. */
netdev_for_each_mc_addr(ha, dev) {
int index = ether_crc_le(ETH_ALEN, ha->addr) & 0x1ff;

- set_bit_le(index, hash_table);
+ __set_bit_le(index, hash_table);
}

for (i = 0; i < 32; i++) {
diff --git a/drivers/net/ethernet/dec/tulip/tulip_core.c b/drivers/net/ethernet/dec/tulip/tulip_core.c
index c4f37ac..885700a 100644
--- a/drivers/net/ethernet/dec/tulip/tulip_core.c
+++ b/drivers/net/ethernet/dec/tulip/tulip_core.c
@@ -1010,9 +1010,6 @@ static int private_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
new frame, not around filling tp->setup_frame. This is non-deterministic
when re-entered but still correct. */

-#undef set_bit_le
-#define set_bit_le(i,p) do { ((char *)(p))[(i)/8] |= (1<<((i)%8)); } while(0)
-
static void build_setup_frame_hash(u16 *setup_frm, struct net_device *dev)
{
struct tulip_private *tp = netdev_priv(dev);
@@ -1022,12 +1019,12 @@ static void build_setup_frame_hash(u16 *setup_frm, struct net_device *dev)
u16 *eaddrs;

memset(hash_table, 0, sizeof(hash_table));
- set_bit_le(255, hash_table); /* Broadcast entry */
+ __set_bit_le(255, hash_table); /* Broadcast entry */
/* This should work on big-endian machines as well. */
netdev_for_each_mc_addr(ha, dev) {
int index = ether_crc_le(ETH_ALEN, ha->addr) & 0x1ff;

- set_bit_le(index, hash_table);
+ __set_bit_le(index, hash_table);
}
for (i = 0; i < 32; i++) {
*setup_frm++ = hash_table[i];
--
1.7.5.4

2012-08-07 11:11:38

by Takuya Yoshikawa

[permalink] [raw]
Subject: [PATCH 3/5] bitops: Introduce generic {clear,set}_bit_le()

From: Takuya Yoshikawa <[email protected]>

Needed to replace test_and_set_bit_le() in virt/kvm/kvm_main.c which is
being used for this missing function.

Signed-off-by: Takuya Yoshikawa <[email protected]>
Acked-by: Arnd Bergmann <[email protected]>
---
include/asm-generic/bitops/le.h | 10 ++++++++++
1 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/include/asm-generic/bitops/le.h b/include/asm-generic/bitops/le.h
index f95c663..6173154 100644
--- a/include/asm-generic/bitops/le.h
+++ b/include/asm-generic/bitops/le.h
@@ -54,6 +54,16 @@ static inline int test_bit_le(int nr, const void *addr)
return test_bit(nr ^ BITOP_LE_SWIZZLE, addr);
}

+static inline void set_bit_le(int nr, void *addr)
+{
+ set_bit(nr ^ BITOP_LE_SWIZZLE, addr);
+}
+
+static inline void clear_bit_le(int nr, void *addr)
+{
+ clear_bit(nr ^ BITOP_LE_SWIZZLE, addr);
+}
+
static inline void __set_bit_le(int nr, void *addr)
{
__set_bit(nr ^ BITOP_LE_SWIZZLE, addr);
--
1.7.5.4

2012-08-07 11:12:25

by Takuya Yoshikawa

[permalink] [raw]
Subject: [PATCH 4/5] powerpc: bitops: Introduce {clear,set}_bit_le()

From: Takuya Yoshikawa <[email protected]>

Needed to replace test_and_set_bit_le() in virt/kvm/kvm_main.c which is
being used for this missing function.

Signed-off-by: Takuya Yoshikawa <[email protected]>
Acked-by: Benjamin Herrenschmidt <[email protected]>
---
arch/powerpc/include/asm/bitops.h | 10 ++++++++++
1 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/include/asm/bitops.h b/arch/powerpc/include/asm/bitops.h
index efdc926..dc2cf9c 100644
--- a/arch/powerpc/include/asm/bitops.h
+++ b/arch/powerpc/include/asm/bitops.h
@@ -288,6 +288,16 @@ static __inline__ int test_bit_le(unsigned long nr,
return (tmp[nr >> 3] >> (nr & 7)) & 1;
}

+static inline void set_bit_le(int nr, void *addr)
+{
+ set_bit(nr ^ BITOP_LE_SWIZZLE, addr);
+}
+
+static inline void clear_bit_le(int nr, void *addr)
+{
+ clear_bit(nr ^ BITOP_LE_SWIZZLE, addr);
+}
+
static inline void __set_bit_le(int nr, void *addr)
{
__set_bit(nr ^ BITOP_LE_SWIZZLE, addr);
--
1.7.5.4

2012-08-07 11:13:08

by Takuya Yoshikawa

[permalink] [raw]
Subject: [PATCH 5/5] KVM: Replace test_and_set_bit_le() in mark_page_dirty_in_slot() with set_bit_le()

From: Takuya Yoshikawa <[email protected]>

Now that we have defined generic set_bit_le() we do not need to use
test_and_set_bit_le() for atomically setting a bit.

Signed-off-by: Takuya Yoshikawa <[email protected]>
Cc: Avi Kivity <[email protected]>
Cc: Marcelo Tosatti <[email protected]>
---
virt/kvm/kvm_main.c | 3 +--
1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index a2e85af..b983f23 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -1440,8 +1440,7 @@ void mark_page_dirty_in_slot(struct kvm *kvm, struct kvm_memory_slot *memslot,
if (memslot && memslot->dirty_bitmap) {
unsigned long rel_gfn = gfn - memslot->base_gfn;

- /* TODO: introduce set_bit_le() and use it */
- test_and_set_bit_le(rel_gfn, memslot->dirty_bitmap);
+ set_bit_le(rel_gfn, memslot->dirty_bitmap);
}
}

--
1.7.5.4