Skip to contentSkip to conversation

bitmap: optimize bitmap_weight() usage

PATCH Applied Yury Norov 20 participants 98 messages Feb 10, 2022 – Jun 11, 2022 1 message not in the archive

Subsystems (57)
lore
Share & tools
lore

Yury Norov

author maintainer
#0 lore raw

v4 cover bitmap: optimize bitmap_weight() usage

In many cases people use bitmap_weight()-based functions to compare the result against a number of expression:

if (cpumask_weight(mask) > 1)
do_something();

This may take considerable amount of time on many-cpus machines because cpumask_weight() will traverse every word of underlying cpumask unconditionally.

We can significantly improve on it for many real cases if stop traversing the mask as soon as we count cpus to any number greater than 1:

        if (cpumask_weight_gt(mask, 1))
                do_something();

The first part of the series is a cleanup and rework where bitmap_weight API is used wrongly.

Second part converts cpumask_weight() to cpumask_empty() if the number to compare with is 0. Ditto for bitmap_weight() and nodes_weight().

In the 3nd part of the series bitmap_weight_cmp() is added together with bitmap_weight_{eq,gt,ge,lt,le} wrappers on top of it. Corresponding wrappers for cpumask and nodemask are added as well.

The rough numbers of new functions usage, as counted by grep:

	{bitmap,cpumask,nodes}_weight_eq	26
	{bitmap,cpumask,nodes}_weight_ge	25
	{bitmap,cpumask,nodes}_weight_gt	19
	{bitmap,cpumask,nodes}_weight_le	18
	{bitmap,cpumask,nodes}_weight_lt	14

v1: https://lkml.org/lkml/2021/11/27/339
v2: https://lkml.org/lkml/2021/12/18/241
v3: https://lkml.org/lkml/2022/1/27/913
v4:
- rebase on next-20220209;
- exclude patches that already in next-20220209;
- drop patches 41, 43, 47, 48 from v3 as they are not performance critical;
- deeply rework iio_simple_dummy_trigger_h (patch #4) and qed_rdma_bmap_free (#10), instead of replacing bitmap_weight;
- use more standard tags.

Yury Norov (49):
net: dsa: don't use bitmap_weight() in b53_arl_read()
net: systemport: don't use bitmap_weight() in bcm_sysport_rule_set()
net: mellanox: fix open-coded for_each_set_bit()
iio: fix opencoded for_each_set_bit()
qed: rework qed_rdma_bmap_free()
nds32: perf: replace bitmap_weight with bitmap_empty where appropriate
KVM: x86: replace bitmap_weight with bitmap_empty where appropriate
drm: replace bitmap_weight with bitmap_empty where appropriate
ice: replace bitmap_weight with bitmap_empty for intel
octeontx2-pf: replace bitmap_weight with bitmap_empty for Marvell
qed: replace bitmap_weight with bitmap_empty in qed_roce_stop() perf/arm-cci: replace bitmap_weight with bitmap_empty where
appropriate
perf tools: replace bitmap_weight with bitmap_empty where appropriate arch/alpha: replace cpumask_weight with cpumask_empty where
appropriate
arch/ia64: replace cpumask_weight with cpumask_empty where appropriate arch/x86: replace cpumask_weight with cpumask_empty where appropriate
cpufreq: replace cpumask_weight with cpumask_empty where appropriate
gpu: drm: replace cpumask_weight with cpumask_empty where appropriate RDMA/hfi: replace cpumask_weight with cpumask_empty where appropriate
irq: mips: replace cpumask_weight with cpumask_empty where appropriate genirq/affinity: replace cpumask_weight with cpumask_empty where
appropriate
sched: replace cpumask_weight with cpumask_empty where appropriate
clocksource: replace cpumask_weight with cpumask_empty in
clocksource.c
mm/vmstat: replace cpumask_weight with cpumask_empty where appropriate arch/x86: replace nodes_weight with nodes_empty where appropriate
bitmap: add bitmap_weight_{cmp, eq, gt, ge, lt, le} functions arch/x86: replace bitmap_weight with bitmap_weight_{eq,gt,ge,lt,le}
where appropriate
iio: replace bitmap_weight() with bitmap_weight_{eq,gt} where
appropriate
memstick: replace bitmap_weight with bitmap_weight_eq where
appropriate
ixgbe: replace bitmap_weight with bitmap_weight_eq for intel
octeontx2-pf: replace bitmap_weight with bitmap_weight_{eq,gt} for
OcteonTX2
mlx4: replace bitmap_weight with bitmap_weight_{eq,gt,ge,lt,le} for
mellanox
perf: replace bitmap_weight with bitmap_weight_eq for ThunderX2
media: tegra-video:: replace bitmap_weight with bitmap_weight_le
cpumask: add cpumask_weight_{eq,gt,ge,lt,le}
arch/ia64: replace cpumask_weight with cpumask_weight_eq in mm/tlb.c arch/mips: replace cpumask_weight with cpumask_weight_{eq, ...} where
appropriate
arch/powerpc: replace cpumask_weight with cpumask_weight_{eq, ...}
where appropriate
arch/s390: replace cpumask_weight with cpumask_weight_eq where
appropriate
firmware: pcsi: replace cpumask_weight with cpumask_weight_eq RDMA/hfi1: replace cpumask_weight with cpumask_weight_{eq, ...} where
appropriate
scsi: lpfc: replace cpumask_weight with cpumask_weight_gt soc/qman: replace cpumask_weight with cpumask_weight_lt
nodemask: add nodemask_weight_{eq,gt,ge,lt,le}
ACPI: replace nodes__weight with nodes_weight_ge for numa mm/mempolicy: replace nodes_weight with nodes_weight_eq
nodemask: add num_node_state_eq()
tools: bitmap: sync bitmap_weight
MAINTAINERS: add cpumask and nodemask files to BITMAP_API

 MAINTAINERS                                   |  4 +
 arch/alpha/kernel/process.c                   |  2 +-
 arch/ia64/kernel/setup.c                      |  2 +-
 arch/ia64/mm/tlb.c                            |  2 +-
 arch/mips/cavium-octeon/octeon-irq.c          |  4 +-
 arch/mips/kernel/crash.c                      |  2 +-
 arch/nds32/kernel/perf_event_cpu.c            |  2 +-
 arch/powerpc/kernel/smp.c                     |  2 +-
 arch/powerpc/kernel/watchdog.c                |  2 +-
 arch/powerpc/xmon/xmon.c                      |  4 +-
 arch/s390/kernel/perf_cpum_cf.c               |  2 +-
 arch/x86/kernel/cpu/resctrl/rdtgroup.c        | 16 ++--
 arch/x86/kvm/hyperv.c                         |  8 +-
 arch/x86/mm/amdtopology.c                     |  2 +-
 arch/x86/mm/mmio-mod.c                        |  2 +-
 arch/x86/mm/numa_emulation.c                  |  4 +-
 arch/x86/platform/uv/uv_nmi.c                 |  2 +-
 drivers/acpi/numa/srat.c                      |  2 +-
 drivers/cpufreq/qcom-cpufreq-hw.c             |  2 +-
 drivers/cpufreq/scmi-cpufreq.c                |  2 +-
 drivers/firmware/psci/psci_checker.c          |  2 +-
 drivers/gpu/drm/i915/i915_pmu.c               |  2 +-
 drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c      |  2 +-
 drivers/iio/dummy/iio_simple_dummy_buffer.c   | 48 +++++-------
 drivers/iio/industrialio-trigger.c            |  2 +-
 drivers/infiniband/hw/hfi1/affinity.c         | 13 ++--
 drivers/infiniband/hw/qib/qib_file_ops.c      |  2 +-
 drivers/infiniband/hw/qib/qib_iba7322.c       |  2 +-
 drivers/irqchip/irq-bcm6345-l1.c              |  2 +-
 drivers/memstick/core/ms_block.c              |  4 +-
 drivers/net/dsa/b53/b53_common.c              |  6 +-
 drivers/net/ethernet/broadcom/bcmsysport.c    |  6 +-
 .../net/ethernet/intel/ice/ice_virtchnl_pf.c  |  4 +-
 .../net/ethernet/intel/ixgbe/ixgbe_sriov.c    |  2 +-
 .../marvell/octeontx2/nic/otx2_ethtool.c      |  2 +-
 .../marvell/octeontx2/nic/otx2_flows.c        |  8 +-
 .../ethernet/marvell/octeontx2/nic/otx2_pf.c  |  2 +-
 drivers/net/ethernet/mellanox/mlx4/cmd.c      | 33 +++-----
 drivers/net/ethernet/mellanox/mlx4/eq.c       |  4 +-
 drivers/net/ethernet/mellanox/mlx4/fw.c       |  4 +-
 drivers/net/ethernet/mellanox/mlx4/main.c     |  2 +-
 drivers/net/ethernet/qlogic/qed/qed_rdma.c    | 45 ++++-------
 drivers/net/ethernet/qlogic/qed/qed_roce.c    |  2 +-
 drivers/perf/arm-cci.c                        |  2 +-
 drivers/perf/arm_pmu.c                        |  4 +-
 drivers/perf/hisilicon/hisi_uncore_pmu.c      |  2 +-
 drivers/perf/thunderx2_pmu.c                  |  4 +-
 drivers/perf/xgene_pmu.c                      |  2 +-
 drivers/scsi/lpfc/lpfc_init.c                 |  2 +-
 drivers/soc/fsl/qbman/qman_test_stash.c       |  2 +-
 drivers/staging/media/tegra-video/vi.c        |  2 +-
 include/linux/bitmap.h                        | 78 +++++++++++++++++++
 include/linux/cpumask.h                       | 50 ++++++++++++
 include/linux/nodemask.h                      | 40 ++++++++++
 kernel/irq/affinity.c                         |  2 +-
 kernel/sched/core.c                           |  2 +-
 kernel/sched/topology.c                       |  2 +-
 kernel/time/clocksource.c                     |  2 +-
 lib/bitmap.c                                  | 21 +++++
 mm/mempolicy.c                                |  2 +-
 mm/page_alloc.c                               |  2 +-
 mm/vmstat.c                                   |  4 +-
 tools/include/linux/bitmap.h                  | 44 +++++++++++
 tools/lib/bitmap.c                            | 20 +++++
 tools/perf/builtin-c2c.c                      |  4 +-
 tools/perf/util/pmu.c                         |  2 +-
 66 files changed, 384 insertions(+), 178 deletions(-)
Signature · 1 line
2.32.0
author maintainer
#1 lore raw

PATCH v4 1/49 net: dsa: don't use bitmap_weight() in b53_arl_read()

Don't call bitmap_weight() if the following code can get by without it.

---
 drivers/net/dsa/b53/b53_common.c | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)
drivers/net/dsa/b53/b53_common.c +1 -5
index a3b98992f180..d99813bf3cdd 100644
@@ -1620,12 +1620,8 @@ static int b53_arl_read(struct b53_device *dev, u64 mac,
 		return 0;
 	}
 
-	if (bitmap_weight(free_bins, dev->num_arl_bins) == 0)
-		return -ENOSPC;
-
 	*idx = find_first_bit(free_bins, dev->num_arl_bins);
-
-	return -ENOENT;
+	return *idx >= dev->num_arl_bins ? -ENOSPC : -ENOENT;
 }
 
 static int b53_arl_op(struct b53_device *dev, int op, int port,
Signature · 1 line
2.32.0
author maintainer
#2 lore raw

PATCH v4 2/49 net: systemport: don't use bitmap_weight() in bcm_sysport_rule_set()

In reply to Yury Norov

Don't call bitmap_weight() if the following code can get by without it.

---
 drivers/net/ethernet/broadcom/bcmsysport.c | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)
drivers/net/ethernet/broadcom/bcmsysport.c +1 -5
index 60dde29974bf..5284a5c961db 100644
@@ -2180,13 +2180,9 @@ static int bcm_sysport_rule_set(struct bcm_sysport_priv *priv,
 	if (nfc->fs.ring_cookie != RX_CLS_FLOW_WAKE)
 		return -EOPNOTSUPP;
 
-	/* All filters are already in use, we cannot match more rules */
-	if (bitmap_weight(priv->filters, RXCHK_BRCM_TAG_MAX) ==
-	    RXCHK_BRCM_TAG_MAX)
-		return -ENOSPC;
-
 	index = find_first_zero_bit(priv->filters, RXCHK_BRCM_TAG_MAX);
 	if (index >= RXCHK_BRCM_TAG_MAX)
+		/* All filters are already in use, we cannot match more rules */
 		return -ENOSPC;
 
 	/* Location is the classification ID, and index is the position
Signature · 1 line
2.32.0
author maintainer
#3 lore raw

PATCH v4 3/49 net: mellanox: fix open-coded for_each_set_bit()

In reply to Yury Norov

Mellanox driver has an open-coded for_each_set_bit(). Fix it.

---
 drivers/net/ethernet/mellanox/mlx4/cmd.c | 23 ++++++-----------------
 1 file changed, 6 insertions(+), 17 deletions(-)
drivers/net/ethernet/mellanox/mlx4/cmd.c +6 -17
index e10b7b04b894..c56d2194cbfc 100644
@@ -1994,21 +1994,16 @@ static void mlx4_allocate_port_vpps(struct mlx4_dev *dev, int port)
 
 static int mlx4_master_activate_admin_state(struct mlx4_priv *priv, int slave)
 {
-	int port, err;
+	int p, port, err;
 	struct mlx4_vport_state *vp_admin;
 	struct mlx4_vport_oper_state *vp_oper;
 	struct mlx4_slave_state *slave_state =
 		&priv->mfunc.master.slave_state[slave];
 	struct mlx4_active_ports actv_ports = mlx4_get_active_ports(
 			&priv->dev, slave);
-	int min_port = find_first_bit(actv_ports.ports,
-				      priv->dev.caps.num_ports) + 1;
-	int max_port = min_port - 1 +
-		bitmap_weight(actv_ports.ports, priv->dev.caps.num_ports);
 
-	for (port = min_port; port <= max_port; port++) {
-		if (!test_bit(port - 1, actv_ports.ports))
-			continue;
+	for_each_set_bit(p, actv_ports.ports, priv->dev.caps.num_ports) {
+		port = p + 1;
 		priv->mfunc.master.vf_oper[slave].smi_enabled[port] =
 			priv->mfunc.master.vf_admin[slave].enable_smi[port];
 		vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port];
@@ -2063,19 +2058,13 @@ static int mlx4_master_activate_admin_state(struct mlx4_priv *priv, int slave)
 
 static void mlx4_master_deactivate_admin_state(struct mlx4_priv *priv, int slave)
 {
-	int port;
+	int p, port;
 	struct mlx4_vport_oper_state *vp_oper;
 	struct mlx4_active_ports actv_ports = mlx4_get_active_ports(
 			&priv->dev, slave);
-	int min_port = find_first_bit(actv_ports.ports,
-				      priv->dev.caps.num_ports) + 1;
-	int max_port = min_port - 1 +
-		bitmap_weight(actv_ports.ports, priv->dev.caps.num_ports);
 
-
-	for (port = min_port; port <= max_port; port++) {
-		if (!test_bit(port - 1, actv_ports.ports))
-			continue;
+	for_each_set_bit(p, actv_ports.ports, priv->dev.caps.num_ports) {
+		port = p + 1;
 		priv->mfunc.master.vf_oper[slave].smi_enabled[port] =
 			MLX4_VF_SMI_DISABLED;
 		vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port];
Signature · 1 line
2.32.0
#4 lore raw

RE: [PATCH 03/49] net: mellanox: fix open-coded for_each_set_bit()

From: Yury Norov

Quoted 26 lines

Sent: 10 February 2022 22:49

Mellanox driver has an open-coded for_each_set_bit(). Fix it.

---
 drivers/net/ethernet/mellanox/mlx4/cmd.c | 23 ++++++-----------------
 1 file changed, 6 insertions(+), 17 deletions(-)
drivers/net/ethernet/mellanox/mlx4/cmd.c +1 -1
index e10b7b04b894..c56d2194cbfc 100644
@@ -1994,21 +1994,16 @@ static void mlx4_allocate_port_vpps(struct mlx4_dev *dev, int port)
 
 static int mlx4_master_activate_admin_state(struct mlx4_priv *priv, int slave)
 {
-	int port, err;
+	int p, port, err;
 	struct mlx4_vport_state *vp_admin;
 	struct mlx4_vport_oper_state *vp_oper;
 	struct mlx4_slave_state *slave_state =
 		&priv->mfunc.master.slave_state[slave];
 	struct mlx4_active_ports actv_ports = mlx4_get_active_ports(
 			&priv->dev, slave);

drivers/net/ethernet/mellanox/mlx4/cmd.c static void mlx4_allocate_port_vpps(struct mlx4_dev *dev, int port) · line 2006

Quoted 10 lines
drivers/net/ethernet/mellanox/mlx4/cmd.c +2 -7
-	int min_port = find_first_bit(actv_ports.ports,
-				      priv->dev.caps.num_ports) + 1;
-	int max_port = min_port - 1 +
-		bitmap_weight(actv_ports.ports, priv->dev.caps.num_ports);
 
-	for (port = min_port; port <= max_port; port++) {
-		if (!test_bit(port - 1, actv_ports.ports))
-			continue;
+	for_each_set_bit(p, actv_ports.ports, priv->dev.caps.num_ports) {
+		port = p + 1;

This is an 'interesting' change in behaviour, and looks like a bug fix. Did anyone actually test the old code?

David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK Registration No: 1397386 (Wales)

author maintainer
#5 lore raw

PATCH v4 4/49 iio: fix opencoded for_each_set_bit()

In reply to Yury Norov

iio_simple_dummy_trigger_h() is mostly an opencoded for_each_set_bit(). Using for_each_set_bit() make code much cleaner, and more effective.

---
 drivers/iio/dummy/iio_simple_dummy_buffer.c | 48 ++++++++-------------
 1 file changed, 19 insertions(+), 29 deletions(-)
drivers/iio/dummy/iio_simple_dummy_buffer.c +19 -29
index d81c2b2dad82..3bc1b7529e2a 100644
@@ -45,41 +45,31 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p)
 {
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->indio_dev;
+	int i = 0, j;
 	u16 *data;
 
 	data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
 	if (!data)
 		goto done;
 
-	if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)) {
-		/*
-		 * Three common options here:
-		 * hardware scans: certain combinations of channels make
-		 *   up a fast read.  The capture will consist of all of them.
-		 *   Hence we just call the grab data function and fill the
-		 *   buffer without processing.
-		 * software scans: can be considered to be random access
-		 *   so efficient reading is just a case of minimal bus
-		 *   transactions.
-		 * software culled hardware scans:
-		 *   occasionally a driver may process the nearest hardware
-		 *   scan to avoid storing elements that are not desired. This
-		 *   is the fiddliest option by far.
-		 * Here let's pretend we have random access. And the values are
-		 * in the constant table fakedata.
-		 */
-		int i, j;
-
-		for (i = 0, j = 0;
-		     i < bitmap_weight(indio_dev->active_scan_mask,
-				       indio_dev->masklength);
-		     i++, j++) {
-			j = find_next_bit(indio_dev->active_scan_mask,
-					  indio_dev->masklength, j);
-			/* random access read from the 'device' */
-			data[i] = fakedata[j];
-		}
-	}
+	/*
+	 * Three common options here:
+	 * hardware scans: certain combinations of channels make
+	 *   up a fast read.  The capture will consist of all of them.
+	 *   Hence we just call the grab data function and fill the
+	 *   buffer without processing.
+	 * software scans: can be considered to be random access
+	 *   so efficient reading is just a case of minimal bus
+	 *   transactions.
+	 * software culled hardware scans:
+	 *   occasionally a driver may process the nearest hardware
+	 *   scan to avoid storing elements that are not desired. This
+	 *   is the fiddliest option by far.
+	 * Here let's pretend we have random access. And the values are
+	 * in the constant table fakedata.
+	 */
+	for_each_set_bit(j, indio_dev->active_scan_mask, indio_dev->masklength)
+		data[i++] = fakedata[j];
 
 	iio_push_to_buffers_with_timestamp(indio_dev, data,
 					   iio_get_time_ns(indio_dev));
Signature · 1 line
2.32.0
Reviewed-by on v4 4/49
#6 lore raw

Re: [PATCH 04/49] iio: fix opencoded for_each_set_bit()

Quoted 2 lines · Yury Norov

iio_simple_dummy_trigger_h() is mostly an opencoded for_each_set_bit(). Using for_each_set_bit() make code much cleaner, and more effective.

I would wait for some testing, but from code perspective looks good.

Quoted 73 lines
---
 drivers/iio/dummy/iio_simple_dummy_buffer.c | 48 ++++++++-------------
 1 file changed, 19 insertions(+), 29 deletions(-)
drivers/iio/dummy/iio_simple_dummy_buffer.c +19 -29
index d81c2b2dad82..3bc1b7529e2a 100644
@@ -45,41 +45,31 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p)
 {
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->indio_dev;
+	int i = 0, j;
 	u16 *data;
 
 	data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
 	if (!data)
 		goto done;
 
-	if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)) {
-		/*
-		 * Three common options here:
-		 * hardware scans: certain combinations of channels make
-		 *   up a fast read.  The capture will consist of all of them.
-		 *   Hence we just call the grab data function and fill the
-		 *   buffer without processing.
-		 * software scans: can be considered to be random access
-		 *   so efficient reading is just a case of minimal bus
-		 *   transactions.
-		 * software culled hardware scans:
-		 *   occasionally a driver may process the nearest hardware
-		 *   scan to avoid storing elements that are not desired. This
-		 *   is the fiddliest option by far.
-		 * Here let's pretend we have random access. And the values are
-		 * in the constant table fakedata.
-		 */
-		int i, j;
-
-		for (i = 0, j = 0;
-		     i < bitmap_weight(indio_dev->active_scan_mask,
-				       indio_dev->masklength);
-		     i++, j++) {
-			j = find_next_bit(indio_dev->active_scan_mask,
-					  indio_dev->masklength, j);
-			/* random access read from the 'device' */
-			data[i] = fakedata[j];
-		}
-	}
+	/*
+	 * Three common options here:
+	 * hardware scans: certain combinations of channels make
+	 *   up a fast read.  The capture will consist of all of them.
+	 *   Hence we just call the grab data function and fill the
+	 *   buffer without processing.
+	 * software scans: can be considered to be random access
+	 *   so efficient reading is just a case of minimal bus
+	 *   transactions.
+	 * software culled hardware scans:
+	 *   occasionally a driver may process the nearest hardware
+	 *   scan to avoid storing elements that are not desired. This
+	 *   is the fiddliest option by far.
+	 * Here let's pretend we have random access. And the values are
+	 * in the constant table fakedata.
+	 */
+	for_each_set_bit(j, indio_dev->active_scan_mask, indio_dev->masklength)
+		data[i++] = fakedata[j];
 
 	iio_push_to_buffers_with_timestamp(indio_dev, data,
 					   iio_get_time_ns(indio_dev));
Signature · 1 line
2.32.0
Signature · 2 lines
With Best Regards,
Andy Shevchenko
#7 lore raw

Re: [PATCH 04/49] iio: fix opencoded for_each_set_bit()

In reply to Yury Norov

Le 10/02/2022 à 23:48, Yury Norov a écrit :

Quoted 58 lines

iio_simple_dummy_trigger_h() is mostly an opencoded for_each_set_bit(). Using for_each_set_bit() make code much cleaner, and more effective.

---
  drivers/iio/dummy/iio_simple_dummy_buffer.c | 48 ++++++++-------------
  1 file changed, 19 insertions(+), 29 deletions(-)
drivers/iio/dummy/iio_simple_dummy_buffer.c +7 -29
index d81c2b2dad82..3bc1b7529e2a 100644
@@ -45,41 +45,31 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p)
  {
  	struct iio_poll_func *pf = p;
  	struct iio_dev *indio_dev = pf->indio_dev;
+	int i = 0, j;
  	u16 *data;
 
  	data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
  	if (!data)
  		goto done;
 
-	if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)) {
-		/*
-		 * Three common options here:
-		 * hardware scans: certain combinations of channels make
-		 *   up a fast read.  The capture will consist of all of them.
-		 *   Hence we just call the grab data function and fill the
-		 *   buffer without processing.
-		 * software scans: can be considered to be random access
-		 *   so efficient reading is just a case of minimal bus
-		 *   transactions.
-		 * software culled hardware scans:
-		 *   occasionally a driver may process the nearest hardware
-		 *   scan to avoid storing elements that are not desired. This
-		 *   is the fiddliest option by far.
-		 * Here let's pretend we have random access. And the values are
-		 * in the constant table fakedata.
-		 */
-		int i, j;
-
-		for (i = 0, j = 0;
-		     i < bitmap_weight(indio_dev->active_scan_mask,
-				       indio_dev->masklength);
-		     i++, j++) {
-			j = find_next_bit(indio_dev->active_scan_mask,
-					  indio_dev->masklength, j);
-			/* random access read from the 'device' */
-			data[i] = fakedata[j];
-		}
-	}
+	/*
+	 * Three common options here:
+	 * hardware scans: certain combinations of channels make
+	 *   up a fast read.  The capture will consist of all of them.
+	 *   Hence we just call the grab data function and fill the
+	 *   buffer without processing.

drivers/iio/dummy/iio_simple_dummy_buffer.c static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p) · line 70

Quoted 10 lines
drivers/iio/dummy/iio_simple_dummy_buffer.c +10 -0
+	 * software scans: can be considered to be random access
+	 *   so efficient reading is just a case of minimal bus
+	 *   transactions.
+	 * software culled hardware scans:
+	 *   occasionally a driver may process the nearest hardware
+	 *   scan to avoid storing elements that are not desired. This
+	 *   is the fiddliest option by far.
+	 * Here let's pretend we have random access. And the values are
+	 * in the constant table fakedata.
+	 */

Nitpicking: you could take advantage of the tab you save to use the full width of the line and save some lines of code.

Just my 2c.

CJ

Quoted 5 lines
drivers/iio/dummy/iio_simple_dummy_buffer.c +2 -0
+	for_each_set_bit(j, indio_dev->active_scan_mask, indio_dev->masklength)
+		data[i++] = fakedata[j];
 
  	iio_push_to_buffers_with_timestamp(indio_dev, data,
  					   iio_get_time_ns(indio_dev));
maintainer
#8 lore raw

Re: [PATCH 04/49] iio: fix opencoded for_each_set_bit()

Quoted 64 lines · On Fri, 11 Feb 2022 18:17:37 +0100 Christophe JAILLET…

Le 10/02/2022 à 23:48, Yury Norov a écrit :

Quoted 63 lines

iio_simple_dummy_trigger_h() is mostly an opencoded for_each_set_bit(). Using for_each_set_bit() make code much cleaner, and more effective.

---
  drivers/iio/dummy/iio_simple_dummy_buffer.c | 48 ++++++++-------------
  1 file changed, 19 insertions(+), 29 deletions(-)
drivers/iio/dummy/iio_simple_dummy_buffer.c +12 -29
index d81c2b2dad82..3bc1b7529e2a 100644
@@ -45,41 +45,31 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p)
  {
  	struct iio_poll_func *pf = p;
  	struct iio_dev *indio_dev = pf->indio_dev;
+	int i = 0, j;
  	u16 *data;
 
  	data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
  	if (!data)
  		goto done;
 
-	if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)) {
-		/*
-		 * Three common options here:
-		 * hardware scans: certain combinations of channels make
-		 *   up a fast read.  The capture will consist of all of them.
-		 *   Hence we just call the grab data function and fill the
-		 *   buffer without processing.
-		 * software scans: can be considered to be random access
-		 *   so efficient reading is just a case of minimal bus
-		 *   transactions.
-		 * software culled hardware scans:
-		 *   occasionally a driver may process the nearest hardware
-		 *   scan to avoid storing elements that are not desired. This
-		 *   is the fiddliest option by far.
-		 * Here let's pretend we have random access. And the values are
-		 * in the constant table fakedata.
-		 */
-		int i, j;
-
-		for (i = 0, j = 0;
-		     i < bitmap_weight(indio_dev->active_scan_mask,
-				       indio_dev->masklength);
-		     i++, j++) {
-			j = find_next_bit(indio_dev->active_scan_mask,
-					  indio_dev->masklength, j);
-			/* random access read from the 'device' */
-			data[i] = fakedata[j];
-		}
-	}
+	/*
+	 * Three common options here:
+	 * hardware scans: certain combinations of channels make
+	 *   up a fast read.  The capture will consist of all of them.
+	 *   Hence we just call the grab data function and fill the
+	 *   buffer without processing.
+	 * software scans: can be considered to be random access
+	 *   so efficient reading is just a case of minimal bus
+	 *   transactions.
+	 * software culled hardware scans:
+	 *   occasionally a driver may process the nearest hardware
Quoted 8 lines

drivers/iio/dummy/iio_simple_dummy_buffer.c static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p) · line 70

Quoted 5 lines
drivers/iio/dummy/iio_simple_dummy_buffer.c +5 -0
+	 *   scan to avoid storing elements that are not desired. This
+	 *   is the fiddliest option by far.
+	 * Here let's pretend we have random access. And the values are
+	 * in the constant table fakedata.
+	 */  

Nitpicking: you could take advantage of the tab you save to use the full width of the line and save some lines of code.

Tweaked whilst applying.

Sorry this one took so long. I marked it as a patch that I'd revisit if and tidy up if there was no v2 sent, but then managed to forget about it until I came to do a clean out of patchwork today.

Anyhow, now applied to the togreg branch of iio.git - initially pushed out as testing for 0-day to see if we missed anything.

Thanks,

Jonathan

Quoted 12 lines

Just my 2c.

CJ

Quoted 5 lines
drivers/iio/dummy/iio_simple_dummy_buffer.c +2 -0
+	for_each_set_bit(j, indio_dev->active_scan_mask, indio_dev->masklength)
+		data[i++] = fakedata[j];
 
  	iio_push_to_buffers_with_timestamp(indio_dev, data,
  					   iio_get_time_ns(indio_dev));  
maintainer
#9 lore raw

Re: [PATCH 04/49] iio: fix opencoded for_each_set_bit()

Quoted 76 lines · On Sat, 4 Jun 2022 16:41:13 +0100 Jonathan Cameron <[email protected]> wrote:
Quoted 64 lines · On Fri, 11 Feb 2022 18:17:37 +0100 Christophe JAILLET…

Le 10/02/2022 à 23:48, Yury Norov a écrit :

Quoted 63 lines

iio_simple_dummy_trigger_h() is mostly an opencoded for_each_set_bit(). Using for_each_set_bit() make code much cleaner, and more effective.

---
  drivers/iio/dummy/iio_simple_dummy_buffer.c | 48 ++++++++-------------
  1 file changed, 19 insertions(+), 29 deletions(-)
drivers/iio/dummy/iio_simple_dummy_buffer.c +12 -29
index d81c2b2dad82..3bc1b7529e2a 100644
@@ -45,41 +45,31 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p)
  {
  	struct iio_poll_func *pf = p;
  	struct iio_dev *indio_dev = pf->indio_dev;
+	int i = 0, j;
  	u16 *data;
 
  	data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
  	if (!data)
  		goto done;
 
-	if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)) {
-		/*
-		 * Three common options here:
-		 * hardware scans: certain combinations of channels make
-		 *   up a fast read.  The capture will consist of all of them.
-		 *   Hence we just call the grab data function and fill the
-		 *   buffer without processing.
-		 * software scans: can be considered to be random access
-		 *   so efficient reading is just a case of minimal bus
-		 *   transactions.
-		 * software culled hardware scans:
-		 *   occasionally a driver may process the nearest hardware
-		 *   scan to avoid storing elements that are not desired. This
-		 *   is the fiddliest option by far.
-		 * Here let's pretend we have random access. And the values are
-		 * in the constant table fakedata.
-		 */
-		int i, j;
-
-		for (i = 0, j = 0;
-		     i < bitmap_weight(indio_dev->active_scan_mask,
-				       indio_dev->masklength);
-		     i++, j++) {
-			j = find_next_bit(indio_dev->active_scan_mask,
-					  indio_dev->masklength, j);
-			/* random access read from the 'device' */
-			data[i] = fakedata[j];
-		}
-	}
+	/*
+	 * Three common options here:
+	 * hardware scans: certain combinations of channels make
+	 *   up a fast read.  The capture will consist of all of them.
+	 *   Hence we just call the grab data function and fill the
+	 *   buffer without processing.
+	 * software scans: can be considered to be random access
+	 *   so efficient reading is just a case of minimal bus
+	 *   transactions.
+	 * software culled hardware scans:
+	 *   occasionally a driver may process the nearest hardware
Quoted 8 lines

drivers/iio/dummy/iio_simple_dummy_buffer.c static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p) · line 70

Quoted 5 lines
drivers/iio/dummy/iio_simple_dummy_buffer.c +5 -0
+	 *   scan to avoid storing elements that are not desired. This
+	 *   is the fiddliest option by far.
+	 * Here let's pretend we have random access. And the values are
+	 * in the constant table fakedata.
+	 */    

Nitpicking: you could take advantage of the tab you save to use the full width of the line and save some lines of code.

Quoted 8 lines

Tweaked whilst applying.

Sorry this one took so long. I marked it as a patch that I'd revisit if and tidy up if there was no v2 sent, but then managed to forget about it until I came to do a clean out of patchwork today.

Anyhow, now applied to the togreg branch of iio.git - initially pushed out as testing for 0-day to see if we missed anything.

And dropped again during a rebase as a different version has gone upstream through a pull request to Linus.

Whilst I have no strong opinion on that in general, I am a little grumpy that a version was merged that was never posted to the mailing lists (that I can find on lore.kernel.org.) Sure the changes were minor and easy to verify as harmless, but none the less they should have been posted.

Jonathan

Quoted 18 lines

Thanks,

Jonathan

Quoted 12 lines

Just my 2c.

CJ

Quoted 5 lines
drivers/iio/dummy/iio_simple_dummy_buffer.c +2 -0
+	for_each_set_bit(j, indio_dev->active_scan_mask, indio_dev->masklength)
+		data[i++] = fakedata[j];
 
  	iio_push_to_buffers_with_timestamp(indio_dev, data,
  					   iio_get_time_ns(indio_dev));    
author maintainer
#10 lore raw

RFC PATCH v4 5/49 qed: rework qed_rdma_bmap_free()

In reply to Yury Norov

qed_rdma_bmap_free() is mostly an opencoded version of printk("%*pb"). Using %*pb format simplifies the code, and helps to avoid inefficient usage of bitmap_weight().

While here, reorganize logic to avoid calculating bmap weight if check is false.

---

This is RFC because it changes lines printing format to bitmap %*pb. If it hurts userspace, it's better to drop the patch.

 drivers/net/ethernet/qlogic/qed/qed_rdma.c | 45 +++++++---------------
 1 file changed, 14 insertions(+), 31 deletions(-)
drivers/net/ethernet/qlogic/qed/qed_rdma.c +14 -31
index 23b668de4640..f4c04af9d4dd 100644
@@ -319,44 +319,27 @@ static int qed_rdma_alloc(struct qed_hwfn *p_hwfn)
 void qed_rdma_bmap_free(struct qed_hwfn *p_hwfn,
 			struct qed_bmap *bmap, bool check)
 {
-	int weight = bitmap_weight(bmap->bitmap, bmap->max_count);
-	int last_line = bmap->max_count / (64 * 8);
-	int last_item = last_line * 8 +
-	    DIV_ROUND_UP(bmap->max_count % (64 * 8), 64);
-	u64 *pmap = (u64 *)bmap->bitmap;
-	int line, item, offset;
-	u8 str_last_line[200] = { 0 };
-
-	if (!weight || !check)
+	unsigned int bit, weight, nbits;
+	unsigned long *b;
+
+	if (!check)
+		goto end;
+
+	weight = bitmap_weight(bmap->bitmap, bmap->max_count);
+	if (!weight)
 		goto end;
 
 	DP_NOTICE(p_hwfn,
 		  "%s bitmap not free - size=%d, weight=%d, 512 bits per line\n",
 		  bmap->name, bmap->max_count, weight);
 
-	/* print aligned non-zero lines, if any */
-	for (item = 0, line = 0; line < last_line; line++, item += 8)
-		if (bitmap_weight((unsigned long *)&pmap[item], 64 * 8))
+	for (bit = 0; bit < bmap->max_count; bit += 512) {
+		b =  bmap->bitmap + BITS_TO_LONGS(bit);
+		nbits = min(bmap->max_count - bit, 512);
+
+		if (!bitmap_empty(b, nbits))
 			DP_NOTICE(p_hwfn,
-				  "line 0x%04x: 0x%016llx 0x%016llx 0x%016llx 0x%016llx 0x%016llx 0x%016llx 0x%016llx 0x%016llx\n",
-				  line,
-				  pmap[item],
-				  pmap[item + 1],
-				  pmap[item + 2],
-				  pmap[item + 3],
-				  pmap[item + 4],
-				  pmap[item + 5],
-				  pmap[item + 6], pmap[item + 7]);
-
-	/* print last unaligned non-zero line, if any */
-	if ((bmap->max_count % (64 * 8)) &&
-	    (bitmap_weight((unsigned long *)&pmap[item],
-			   bmap->max_count - item * 64))) {
-		offset = sprintf(str_last_line, "line 0x%04x: ", line);
-		for (; item < last_item; item++)
-			offset += sprintf(str_last_line + offset,
-					  "0x%016llx ", pmap[item]);
-		DP_NOTICE(p_hwfn, "%s\n", str_last_line);
+				  "line 0x%04x: %*pb\n", bit / 512, nbits, b);
 	}
 
 end:
Signature · 1 line
2.32.0
Reviewed-by on v4 5/49
#11 lore raw

Re: [RFC PATCH 05/49] qed: rework qed_rdma_bmap_free()

Quoted 6 lines · Yury Norov

qed_rdma_bmap_free() is mostly an opencoded version of printk("%*pb"). Using %*pb format simplifies the code, and helps to avoid inefficient usage of bitmap_weight().

While here, reorganize logic to avoid calculating bmap weight if check is false.

I like this kind of patches,

Quoted 5 lines

---

This is RFC because it changes lines printing format to bitmap %*pb. If it hurts userspace, it's better to drop the patch.

How? The only way is some strange script that parses dmesg, but dmesg almost never was an ABI, moreover, with printk() indexing feature (recently introduced) the one who parses such messages can actually find the (new) format as well.

Quoted 69 lines
 drivers/net/ethernet/qlogic/qed/qed_rdma.c | 45 +++++++---------------
 1 file changed, 14 insertions(+), 31 deletions(-)
drivers/net/ethernet/qlogic/qed/qed_rdma.c +14 -31
index 23b668de4640..f4c04af9d4dd 100644
@@ -319,44 +319,27 @@ static int qed_rdma_alloc(struct qed_hwfn *p_hwfn)
 void qed_rdma_bmap_free(struct qed_hwfn *p_hwfn,
 			struct qed_bmap *bmap, bool check)
 {
-	int weight = bitmap_weight(bmap->bitmap, bmap->max_count);
-	int last_line = bmap->max_count / (64 * 8);
-	int last_item = last_line * 8 +
-	    DIV_ROUND_UP(bmap->max_count % (64 * 8), 64);
-	u64 *pmap = (u64 *)bmap->bitmap;
-	int line, item, offset;
-	u8 str_last_line[200] = { 0 };
-
-	if (!weight || !check)
+	unsigned int bit, weight, nbits;
+	unsigned long *b;
+
+	if (!check)
+		goto end;
+
+	weight = bitmap_weight(bmap->bitmap, bmap->max_count);
+	if (!weight)
 		goto end;
 
 	DP_NOTICE(p_hwfn,
 		  "%s bitmap not free - size=%d, weight=%d, 512 bits per line\n",
 		  bmap->name, bmap->max_count, weight);
 
-	/* print aligned non-zero lines, if any */
-	for (item = 0, line = 0; line < last_line; line++, item += 8)
-		if (bitmap_weight((unsigned long *)&pmap[item], 64 * 8))
+	for (bit = 0; bit < bmap->max_count; bit += 512) {
+		b =  bmap->bitmap + BITS_TO_LONGS(bit);
+		nbits = min(bmap->max_count - bit, 512);
+
+		if (!bitmap_empty(b, nbits))
 			DP_NOTICE(p_hwfn,
-				  "line 0x%04x: 0x%016llx 0x%016llx 0x%016llx 0x%016llx 0x%016llx 0x%016llx 0x%016llx 0x%016llx\n",
-				  line,
-				  pmap[item],
-				  pmap[item + 1],
-				  pmap[item + 2],
-				  pmap[item + 3],
-				  pmap[item + 4],
-				  pmap[item + 5],
-				  pmap[item + 6], pmap[item + 7]);
-
-	/* print last unaligned non-zero line, if any */
-	if ((bmap->max_count % (64 * 8)) &&
-	    (bitmap_weight((unsigned long *)&pmap[item],
-			   bmap->max_count - item * 64))) {
-		offset = sprintf(str_last_line, "line 0x%04x: ", line);
-		for (; item < last_item; item++)
-			offset += sprintf(str_last_line + offset,
-					  "0x%016llx ", pmap[item]);
-		DP_NOTICE(p_hwfn, "%s\n", str_last_line);
+				  "line 0x%04x: %*pb\n", bit / 512, nbits, b);
 	}
 
 end:
Signature · 1 line
2.32.0
Signature · 2 lines
With Best Regards,
Andy Shevchenko
author maintainer
#12 lore raw

PATCH v4 6/49 nds32: perf: replace bitmap_weight with bitmap_empty where appropriate

In reply to Yury Norov

nds32_pmu_enable calls bitmap_weight() to check if any bit of a given bitmap is set. It's better to use bitmap_empty() in that case because bitmap_empty() stops traversing the bitmap as soon as it finds first set bit, while bitmap_weight() counts all bits unconditionally.

---
 arch/nds32/kernel/perf_event_cpu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/nds32/kernel/perf_event_cpu.c +1 -1
index a78a879e7ef1..ea44e9ecb5c7 100644
@@ -695,7 +695,7 @@ static void nds32_pmu_enable(struct pmu *pmu)
 {
 	struct nds32_pmu *nds32_pmu = to_nds32_pmu(pmu);
 	struct pmu_hw_events *hw_events = nds32_pmu->get_hw_events();
-	int enabled = bitmap_weight(hw_events->used_mask,
+	bool enabled = !bitmap_empty(hw_events->used_mask,
 				    nds32_pmu->num_events);
 
 	if (enabled)
Signature · 1 line
2.32.0
author maintainer
#13 lore raw

PATCH v4 7/49 KVM: x86: replace bitmap_weight with bitmap_empty where appropriate

In reply to Yury Norov

In some places kvm/hyperv.c code calls bitmap_weight() to check if any bit of a given bitmap is set. It's better to use bitmap_empty() in that case because bitmap_empty() stops traversing the bitmap as soon as it finds first set bit, while bitmap_weight() counts all bits unconditionally.

---
 arch/x86/kvm/hyperv.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
arch/x86/kvm/hyperv.c +4 -4
index 6e38a7d22e97..06c2a5603123 100644
@@ -90,7 +90,7 @@ static void synic_update_vector(struct kvm_vcpu_hv_synic *synic,
 {
 	struct kvm_vcpu *vcpu = hv_synic_to_vcpu(synic);
 	struct kvm_hv *hv = to_kvm_hv(vcpu->kvm);
-	int auto_eoi_old, auto_eoi_new;
+	bool auto_eoi_old, auto_eoi_new;
 
 	if (vector < HV_SYNIC_FIRST_VALID_VECTOR)
 		return;
@@ -100,16 +100,16 @@ static void synic_update_vector(struct kvm_vcpu_hv_synic *synic,
 	else
 		__clear_bit(vector, synic->vec_bitmap);
 
-	auto_eoi_old = bitmap_weight(synic->auto_eoi_bitmap, 256);
+	auto_eoi_old = !bitmap_empty(synic->auto_eoi_bitmap, 256);
 
 	if (synic_has_vector_auto_eoi(synic, vector))
 		__set_bit(vector, synic->auto_eoi_bitmap);
 	else
 		__clear_bit(vector, synic->auto_eoi_bitmap);
 
-	auto_eoi_new = bitmap_weight(synic->auto_eoi_bitmap, 256);
+	auto_eoi_new = !bitmap_empty(synic->auto_eoi_bitmap, 256);
 
-	if (!!auto_eoi_old == !!auto_eoi_new)
+	if (auto_eoi_old == auto_eoi_new)
 		return;
 
 	down_write(&vcpu->kvm->arch.apicv_update_lock);
Signature · 1 line
2.32.0
maintainer Reviewed-by on v4 7/49
#14 lore raw

Re: [PATCH 07/49] KVM: x86: replace bitmap_weight with bitmap_empty where appropriate

Quoted 8 lines · Yury Norov

In some places kvm/hyperv.c code calls bitmap_weight() to check if any bit of a given bitmap is set. It's better to use bitmap_empty() in that case because bitmap_empty() stops traversing the bitmap as soon as it finds first set bit, while bitmap_weight() counts all bits unconditionally.

---

#15 lore raw

Re: [PATCH 07/49] KVM: x86: replace bitmap_weight with bitmap_empty where appropriate

In reply to Yury Norov

Le 10/02/2022 à 23:48, Yury Norov a écrit :

Quoted 25 lines

In some places kvm/hyperv.c code calls bitmap_weight() to check if any bit of a given bitmap is set. It's better to use bitmap_empty() in that case because bitmap_empty() stops traversing the bitmap as soon as it finds first set bit, while bitmap_weight() counts all bits unconditionally.

---
  arch/x86/kvm/hyperv.c | 8 ++++----
  1 file changed, 4 insertions(+), 4 deletions(-)
arch/x86/kvm/hyperv.c +1 -1
index 6e38a7d22e97..06c2a5603123 100644
@@ -90,7 +90,7 @@ static void synic_update_vector(struct kvm_vcpu_hv_synic *synic,
  {
  	struct kvm_vcpu *vcpu = hv_synic_to_vcpu(synic);
  	struct kvm_hv *hv = to_kvm_hv(vcpu->kvm);
-	int auto_eoi_old, auto_eoi_new;
+	bool auto_eoi_old, auto_eoi_new;
 
  	if (vector < HV_SYNIC_FIRST_VALID_VECTOR)
  		return;

arch/x86/kvm/hyperv.c static void synic_update_vector(struct kvm_vcpu_hv_synic *synic, · line 103

Quoted 5 lines
arch/x86/kvm/hyperv.c +1 -1
@@ -100,16 +100,16 @@ static void synic_update_vector(struct kvm_vcpu_hv_synic *synic,
  	else
  		__clear_bit(vector, synic->vec_bitmap);
 
-	auto_eoi_old = bitmap_weight(synic->auto_eoi_bitmap, 256);
+	auto_eoi_old = !bitmap_empty(synic->auto_eoi_bitmap, 256);

I think that you can also remove the "!" here, ...

arch/x86/kvm/hyperv.c static void synic_update_vector(struct kvm_vcpu_hv_synic *synic, · line 110

Quoted 8 lines
arch/x86/kvm/hyperv.c +1 -1
  	if (synic_has_vector_auto_eoi(synic, vector))
  		__set_bit(vector, synic->auto_eoi_bitmap);
  	else
  		__clear_bit(vector, synic->auto_eoi_bitmap);
 
-	auto_eoi_new = bitmap_weight(synic->auto_eoi_bitmap, 256);
+	auto_eoi_new = !bitmap_empty(synic->auto_eoi_bitmap, 256);

... and there...

arch/x86/kvm/hyperv.c static void synic_update_vector(struct kvm_vcpu_hv_synic *synic, · line 112

Quoted 3 lines
arch/x86/kvm/hyperv.c +1 -1
-	if (!!auto_eoi_old == !!auto_eoi_new)
+	if (auto_eoi_old == auto_eoi_new)

... because this test would still give the same result.

Just my 2c,
CJ

Quoted 3 lines
arch/x86/kvm/hyperv.c +0 -0
  		return;
 
  	down_write(&vcpu->kvm->arch.apicv_update_lock);
#16 lore raw

Re: [PATCH 07/49] KVM: x86: replace bitmap_weight with bitmap_empty where appropriate

Quoted 41 lines · Christophe JAILLET

Le 10/02/2022 à 23:48, Yury Norov a écrit :

Quoted 24 lines

In some places kvm/hyperv.c code calls bitmap_weight() to check if any bit of a given bitmap is set. It's better to use bitmap_empty() in that case because bitmap_empty() stops traversing the bitmap as soon as it finds first set bit, while bitmap_weight() counts all bits unconditionally.

---
  arch/x86/kvm/hyperv.c | 8 ++++----
  1 file changed, 4 insertions(+), 4 deletions(-)
arch/x86/kvm/hyperv.c +1 -1
index 6e38a7d22e97..06c2a5603123 100644
@@ -90,7 +90,7 @@ static void synic_update_vector(struct kvm_vcpu_hv_synic *synic,
  {
  	struct kvm_vcpu *vcpu = hv_synic_to_vcpu(synic);
  	struct kvm_hv *hv = to_kvm_hv(vcpu->kvm);
-	int auto_eoi_old, auto_eoi_new;
+	bool auto_eoi_old, auto_eoi_new;
  	if (vector < HV_SYNIC_FIRST_VALID_VECTOR)
  		return;

arch/x86/kvm/hyperv.c static void synic_update_vector(struct kvm_vcpu_hv_synic *synic, · line 102

Quoted 4 lines
arch/x86/kvm/hyperv.c +1 -1
@@ -100,16 +100,16 @@ static void synic_update_vector(struct kvm_vcpu_hv_synic *synic,
  	else
  		__clear_bit(vector, synic->vec_bitmap);
-	auto_eoi_old = bitmap_weight(synic->auto_eoi_bitmap, 256);
+	auto_eoi_old = !bitmap_empty(synic->auto_eoi_bitmap, 256);

I think that you can also remove the "!" here, ...

arch/x86/kvm/hyperv.c static void synic_update_vector(struct kvm_vcpu_hv_synic *synic, · line 110

Quoted 6 lines
arch/x86/kvm/hyperv.c +1 -1
  	if (synic_has_vector_auto_eoi(synic, vector))
  		__set_bit(vector, synic->auto_eoi_bitmap);
  	else
  		__clear_bit(vector, synic->auto_eoi_bitmap);
-	auto_eoi_new = bitmap_weight(synic->auto_eoi_bitmap, 256);
+	auto_eoi_new = !bitmap_empty(synic->auto_eoi_bitmap, 256);

... and there...

Quoted 4 lines

arch/x86/kvm/hyperv.c static void synic_update_vector(struct kvm_vcpu_hv_synic *synic, · line 112

Quoted 2 lines
arch/x86/kvm/hyperv.c +1 -1
-	if (!!auto_eoi_old == !!auto_eoi_new)
+	if (auto_eoi_old == auto_eoi_new)

... because this test would still give the same result.

It would give the same result, but the variable names would be inverted as they track if "auto EOI" is being used. So yes, it's technically unnecessary, but also very deliberate.

author maintainer
#17 lore raw

Re: [PATCH 07/49] KVM: x86: replace bitmap_weight with bitmap_empty where appropriate

Quoted 42 lines · Sean Christopherson
Quoted 41 lines · Christophe JAILLET

Le 10/02/2022 à 23:48, Yury Norov a écrit :

Quoted 24 lines

In some places kvm/hyperv.c code calls bitmap_weight() to check if any bit of a given bitmap is set. It's better to use bitmap_empty() in that case because bitmap_empty() stops traversing the bitmap as soon as it finds first set bit, while bitmap_weight() counts all bits unconditionally.

---
  arch/x86/kvm/hyperv.c | 8 ++++----
  1 file changed, 4 insertions(+), 4 deletions(-)
arch/x86/kvm/hyperv.c +1 -1
index 6e38a7d22e97..06c2a5603123 100644
@@ -90,7 +90,7 @@ static void synic_update_vector(struct kvm_vcpu_hv_synic *synic,
  {
  	struct kvm_vcpu *vcpu = hv_synic_to_vcpu(synic);
  	struct kvm_hv *hv = to_kvm_hv(vcpu->kvm);
-	int auto_eoi_old, auto_eoi_new;
+	bool auto_eoi_old, auto_eoi_new;
  	if (vector < HV_SYNIC_FIRST_VALID_VECTOR)
  		return;

arch/x86/kvm/hyperv.c static void synic_update_vector(struct kvm_vcpu_hv_synic *synic, · line 102

Quoted 4 lines
arch/x86/kvm/hyperv.c +1 -1
@@ -100,16 +100,16 @@ static void synic_update_vector(struct kvm_vcpu_hv_synic *synic,
  	else
  		__clear_bit(vector, synic->vec_bitmap);
-	auto_eoi_old = bitmap_weight(synic->auto_eoi_bitmap, 256);
+	auto_eoi_old = !bitmap_empty(synic->auto_eoi_bitmap, 256);

I think that you can also remove the "!" here, ...

arch/x86/kvm/hyperv.c static void synic_update_vector(struct kvm_vcpu_hv_synic *synic, · line 110

Quoted 6 lines
arch/x86/kvm/hyperv.c +1 -1
  	if (synic_has_vector_auto_eoi(synic, vector))
  		__set_bit(vector, synic->auto_eoi_bitmap);
  	else
  		__clear_bit(vector, synic->auto_eoi_bitmap);
-	auto_eoi_new = bitmap_weight(synic->auto_eoi_bitmap, 256);
+	auto_eoi_new = !bitmap_empty(synic->auto_eoi_bitmap, 256);

... and there...

Quoted 4 lines
Quoted 4 lines

arch/x86/kvm/hyperv.c static void synic_update_vector(struct kvm_vcpu_hv_synic *synic, · line 112

Quoted 2 lines
arch/x86/kvm/hyperv.c +1 -1
-	if (!!auto_eoi_old == !!auto_eoi_new)
+	if (auto_eoi_old == auto_eoi_new)

... because this test would still give the same result.

This is how it was in v3. Vitaly asked to add '!' to keep variables names correct.
https://lore.kernel.org/lkml/CAAH8bW_u6oNOkMsA_jRyWFHkzjMi0CB7gXmvLYAdjNMSqrrY7w@mail.gmail.com/t/#m51d28c03eafed5754a69f95f24c7d0a0510cc5c0

Quoted 4 lines

It would give the same result, but the variable names would be inverted as they track if "auto EOI" is being used. So yes, it's technically unnecessary, but also very deliberate.

auto_eoi_old_not_used = bitmap_empty() is worse to me than auto_eoi_old = !bitmap_empty().

Thanks,
Yury

author maintainer
#18 lore raw

PATCH v4 8/49 drm: replace bitmap_weight with bitmap_empty where appropriate

In reply to Yury Norov

smp_request_block() in drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c calls bitmap_weight() to check if any bit of a given bitmap is set. It's better to use bitmap_empty() in that case because bitmap_empty() stops traversing the bitmap as soon as it finds first set bit, while bitmap_weight() counts all bits unconditionally.

---
 drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c +1 -1
index d7fa2c49e741..56a3063545ec 100644
@@ -68,7 +68,7 @@ static int smp_request_block(struct mdp5_smp *smp,
 	uint8_t reserved;
 
 	/* we shouldn't be requesting blocks for an in-use client: */
-	WARN_ON(bitmap_weight(cs, cnt) > 0);
+	WARN_ON(!bitmap_empty(cs, cnt));
 
 	reserved = smp->reserved[cid];
 
Signature · 1 line
2.32.0
Reviewed-by on v4 8/49
#19 lore raw

Re: [PATCH 08/49] drm: replace bitmap_weight with bitmap_empty where appropriate

Quoted 17 lines · Yury Norov

smp_request_block() in drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c calls bitmap_weight() to check if any bit of a given bitmap is set. It's better to use bitmap_empty() in that case because bitmap_empty() stops traversing the bitmap as soon as it finds first set bit, while bitmap_weight() counts all bits unconditionally.

---
 drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c +0 -0
index d7fa2c49e741..56a3063545ec 100644

drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c static int smp_request_block(struct mdp5_smp *smp, · line 71

Quoted 5 lines
drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c +1 -1
@@ -68,7 +68,7 @@ static int smp_request_block(struct mdp5_smp *smp,
        uint8_t reserved;
 
        /* we shouldn't be requesting blocks for an in-use client: */
-       WARN_ON(bitmap_weight(cs, cnt) > 0);
+       WARN_ON(!bitmap_empty(cs, cnt));
Quoted 6 lines
drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c +0 -1
        reserved = smp->reserved[cid];
 
--

2.32.0

Signature · 2 lines
With best wishes
Dmitry
author maintainer
#20 lore raw

PATCH v4 9/49 ice: replace bitmap_weight with bitmap_empty

In reply to Yury Norov

The ice_vf_has_no_qs_ena() calls bitmap_weight() to check if any bit of a given bitmap is set. It's better to use bitmap_empty() in that case because bitmap_empty() stops traversing the bitmap as soon as it finds first set bit, while bitmap_weight() counts all bits unconditionally.

---
 drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c +2 -2
index 39b80124d282..9a86eeb6e3f2 100644
@@ -267,8 +267,8 @@ ice_set_pfe_link(struct ice_vf *vf, struct virtchnl_pf_event *pfe,
  */
 static bool ice_vf_has_no_qs_ena(struct ice_vf *vf)
 {
-	return (!bitmap_weight(vf->rxq_ena, ICE_MAX_RSS_QS_PER_VF) &&
-		!bitmap_weight(vf->txq_ena, ICE_MAX_RSS_QS_PER_VF));
+	return bitmap_empty(vf->rxq_ena, ICE_MAX_RSS_QS_PER_VF) &&
+		bitmap_empty(vf->txq_ena, ICE_MAX_RSS_QS_PER_VF);
 }
 
 /**
Signature · 1 line
2.32.0
author maintainer
#21 lore raw

PATCH v4 10/49 octeontx2-pf: replace bitmap_weight with bitmap_empty where appropriate

In reply to Yury Norov

In some places, octeontx2 code calls bitmap_weight() to check if any bit of a given bitmap is set. It's better to use bitmap_empty() in that case because bitmap_empty() stops traversing the bitmap as soon as it finds first set bit, while bitmap_weight() counts all bits unconditionally.

---
 drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c | 4 ++--
 drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c    | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)
drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c +2 -2
index 77a13fb555fb..80b2d64b4136 100644
@@ -353,7 +353,7 @@ int otx2_add_macfilter(struct net_device *netdev, const u8 *mac)
 {
 	struct otx2_nic *pf = netdev_priv(netdev);
 
-	if (bitmap_weight(&pf->flow_cfg->dmacflt_bmap,
+	if (!bitmap_empty(&pf->flow_cfg->dmacflt_bmap,
 			  pf->flow_cfg->dmacflt_max_flows))
 		netdev_warn(netdev,
 			    "Add %pM to CGX/RPM DMAC filters list as well\n",
@@ -436,7 +436,7 @@ int otx2_get_maxflows(struct otx2_flow_config *flow_cfg)
 		return 0;
 
 	if (flow_cfg->nr_flows == flow_cfg->max_flows ||
-	    bitmap_weight(&flow_cfg->dmacflt_bmap,
+	    !bitmap_empty(&flow_cfg->dmacflt_bmap,
 			  flow_cfg->dmacflt_max_flows))
 		return flow_cfg->max_flows + flow_cfg->dmacflt_max_flows;
 	else
drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c +1 -1
index 86c1c2f77bd7..0f671df46694 100644
@@ -1120,7 +1120,7 @@ static int otx2_cgx_config_loopback(struct otx2_nic *pf, bool enable)
 	struct msg_req *msg;
 	int err;
 
-	if (enable && bitmap_weight(&pf->flow_cfg->dmacflt_bmap,
+	if (enable && !bitmap_empty(&pf->flow_cfg->dmacflt_bmap,
 				    pf->flow_cfg->dmacflt_max_flows))
 		netdev_warn(pf->netdev,
 			    "CGX/RPM internal loopback might not work as DMAC filters are active\n");
Signature · 1 line
2.32.0
author maintainer
#22 lore raw

PATCH v4 11/49 qed: replace bitmap_weight with bitmap_empty in qed_roce_stop()

In reply to Yury Norov

qed_roce_stop() calls bitmap_weight() to check if any bit of a given bitmap is set. We can do it more efficiently with bitmap_empty() because bitmap_empty() stops traversing the bitmap as soon as it finds first set bit, while bitmap_weight() counts all bits unconditionally.

---
 drivers/net/ethernet/qlogic/qed/qed_roce.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/qlogic/qed/qed_roce.c +1 -1
index 071b4aeaddf2..134ecfca96a3 100644
@@ -76,7 +76,7 @@ void qed_roce_stop(struct qed_hwfn *p_hwfn)
 	 * We delay for a short while if an async destroy QP is still expected.
 	 * Beyond the added delay we clear the bitmap anyway.
 	 */
-	while (bitmap_weight(rcid_map->bitmap, rcid_map->max_count)) {
+	while (!bitmap_empty(rcid_map->bitmap, rcid_map->max_count)) {
 		/* If the HW device is during recovery, all resources are
 		 * immediately reset without receiving a per-cid indication
 		 * from HW. In this case we don't expect the cid bitmap to be
Signature · 1 line
2.32.0
author maintainer
#23 lore raw

PATCH v4 12/49 perf: replace bitmap_weight with bitmap_empty where appropriate

In reply to Yury Norov

In some places, drivers/perf code calls bitmap_weight() to check if any bit of a given bitmap is set. It's better to use bitmap_empty() in that case because bitmap_empty() stops traversing the bitmap as soon as it finds first set bit, while bitmap_weight() counts all bits unconditionally.

---
 drivers/perf/arm-cci.c                   | 2 +-
 drivers/perf/arm_pmu.c                   | 4 ++--
 drivers/perf/hisilicon/hisi_uncore_pmu.c | 2 +-
 drivers/perf/xgene_pmu.c                 | 2 +-
 4 files changed, 5 insertions(+), 5 deletions(-)
drivers/perf/arm-cci.c +1 -1
index 54aca3a62814..96e09fa40909 100644
@@ -1096,7 +1096,7 @@ static void cci_pmu_enable(struct pmu *pmu)
 {
 	struct cci_pmu *cci_pmu = to_cci_pmu(pmu);
 	struct cci_pmu_hw_events *hw_events = &cci_pmu->hw_events;
-	int enabled = bitmap_weight(hw_events->used_mask, cci_pmu->num_cntrs);
+	bool enabled = !bitmap_empty(hw_events->used_mask, cci_pmu->num_cntrs);
 	unsigned long flags;
 
 	if (!enabled)
drivers/perf/arm_pmu.c +2 -2
index 295cc7952d0e..a31b302b0ade 100644
@@ -524,7 +524,7 @@ static void armpmu_enable(struct pmu *pmu)
 {
 	struct arm_pmu *armpmu = to_arm_pmu(pmu);
 	struct pmu_hw_events *hw_events = this_cpu_ptr(armpmu->hw_events);
-	int enabled = bitmap_weight(hw_events->used_mask, armpmu->num_events);
+	bool enabled = !bitmap_empty(hw_events->used_mask, armpmu->num_events);
 
 	/* For task-bound events we may be called on other CPUs */
 	if (!cpumask_test_cpu(smp_processor_id(), &armpmu->supported_cpus))
@@ -785,7 +785,7 @@ static int cpu_pm_pmu_notify(struct notifier_block *b, unsigned long cmd,
 {
 	struct arm_pmu *armpmu = container_of(b, struct arm_pmu, cpu_pm_nb);
 	struct pmu_hw_events *hw_events = this_cpu_ptr(armpmu->hw_events);
-	int enabled = bitmap_weight(hw_events->used_mask, armpmu->num_events);
+	bool enabled = !bitmap_empty(hw_events->used_mask, armpmu->num_events);
 
 	if (!cpumask_test_cpu(smp_processor_id(), &armpmu->supported_cpus))
 		return NOTIFY_DONE;
drivers/perf/hisilicon/hisi_uncore_pmu.c +1 -1
index a738aeab5c04..358e4e284a62 100644
@@ -393,7 +393,7 @@ EXPORT_SYMBOL_GPL(hisi_uncore_pmu_read);
 void hisi_uncore_pmu_enable(struct pmu *pmu)
 {
 	struct hisi_pmu *hisi_pmu = to_hisi_pmu(pmu);
-	int enabled = bitmap_weight(hisi_pmu->pmu_events.used_mask,
+	bool enabled = !bitmap_empty(hisi_pmu->pmu_events.used_mask,
 				    hisi_pmu->num_counters);
 
 	if (!enabled)
drivers/perf/xgene_pmu.c +1 -1
index 5283608dc055..0c32dffc7ede 100644
@@ -867,7 +867,7 @@ static void xgene_perf_pmu_enable(struct pmu *pmu)
 {
 	struct xgene_pmu_dev *pmu_dev = to_pmu_dev(pmu);
 	struct xgene_pmu *xgene_pmu = pmu_dev->parent;
-	int enabled = bitmap_weight(pmu_dev->cntr_assign_mask,
+	bool enabled = !bitmap_empty(pmu_dev->cntr_assign_mask,
 			pmu_dev->max_counters);
 
 	if (!enabled)
Signature · 1 line
2.32.0
maintainer Acked-by on v4 12/49
#24 lore raw

Re: [PATCH 12/49] perf: replace bitmap_weight with bitmap_empty where appropriate

Hi Yury,

Quoted 6 lines · Yury Norov

In some places, drivers/perf code calls bitmap_weight() to check if any bit of a given bitmap is set. It's better to use bitmap_empty() in that case because bitmap_empty() stops traversing the bitmap as soon as it finds first set bit, while bitmap_weight() counts all bits unconditionally.

This looks like a nice semantic cleanup to me, so FWIW:

How are you expecting to queue all of this? Should Will and I pick this patch?

Thanks,
Mark.

Quoted 71 lines
---
 drivers/perf/arm-cci.c                   | 2 +-
 drivers/perf/arm_pmu.c                   | 4 ++--
 drivers/perf/hisilicon/hisi_uncore_pmu.c | 2 +-
 drivers/perf/xgene_pmu.c                 | 2 +-
 4 files changed, 5 insertions(+), 5 deletions(-)
drivers/perf/arm-cci.c +1 -1
index 54aca3a62814..96e09fa40909 100644
@@ -1096,7 +1096,7 @@ static void cci_pmu_enable(struct pmu *pmu)
 {
 	struct cci_pmu *cci_pmu = to_cci_pmu(pmu);
 	struct cci_pmu_hw_events *hw_events = &cci_pmu->hw_events;
-	int enabled = bitmap_weight(hw_events->used_mask, cci_pmu->num_cntrs);
+	bool enabled = !bitmap_empty(hw_events->used_mask, cci_pmu->num_cntrs);
 	unsigned long flags;
 
 	if (!enabled)
drivers/perf/arm_pmu.c +2 -2
index 295cc7952d0e..a31b302b0ade 100644
@@ -524,7 +524,7 @@ static void armpmu_enable(struct pmu *pmu)
 {
 	struct arm_pmu *armpmu = to_arm_pmu(pmu);
 	struct pmu_hw_events *hw_events = this_cpu_ptr(armpmu->hw_events);
-	int enabled = bitmap_weight(hw_events->used_mask, armpmu->num_events);
+	bool enabled = !bitmap_empty(hw_events->used_mask, armpmu->num_events);
 
 	/* For task-bound events we may be called on other CPUs */
 	if (!cpumask_test_cpu(smp_processor_id(), &armpmu->supported_cpus))
@@ -785,7 +785,7 @@ static int cpu_pm_pmu_notify(struct notifier_block *b, unsigned long cmd,
 {
 	struct arm_pmu *armpmu = container_of(b, struct arm_pmu, cpu_pm_nb);
 	struct pmu_hw_events *hw_events = this_cpu_ptr(armpmu->hw_events);
-	int enabled = bitmap_weight(hw_events->used_mask, armpmu->num_events);
+	bool enabled = !bitmap_empty(hw_events->used_mask, armpmu->num_events);
 
 	if (!cpumask_test_cpu(smp_processor_id(), &armpmu->supported_cpus))
 		return NOTIFY_DONE;
drivers/perf/hisilicon/hisi_uncore_pmu.c +1 -1
index a738aeab5c04..358e4e284a62 100644
@@ -393,7 +393,7 @@ EXPORT_SYMBOL_GPL(hisi_uncore_pmu_read);
 void hisi_uncore_pmu_enable(struct pmu *pmu)
 {
 	struct hisi_pmu *hisi_pmu = to_hisi_pmu(pmu);
-	int enabled = bitmap_weight(hisi_pmu->pmu_events.used_mask,
+	bool enabled = !bitmap_empty(hisi_pmu->pmu_events.used_mask,
 				    hisi_pmu->num_counters);
 
 	if (!enabled)
drivers/perf/xgene_pmu.c +1 -1
index 5283608dc055..0c32dffc7ede 100644
@@ -867,7 +867,7 @@ static void xgene_perf_pmu_enable(struct pmu *pmu)
 {
 	struct xgene_pmu_dev *pmu_dev = to_pmu_dev(pmu);
 	struct xgene_pmu *xgene_pmu = pmu_dev->parent;
-	int enabled = bitmap_weight(pmu_dev->cntr_assign_mask,
+	bool enabled = !bitmap_empty(pmu_dev->cntr_assign_mask,
 			pmu_dev->max_counters);
 
 	if (!enabled)
Signature · 1 line
2.32.0
author maintainer
#25 lore raw

Re: [PATCH 12/49] perf: replace bitmap_weight with bitmap_empty where appropriate

Quoted 11 lines · Mark Rutland

Hi Yury,

Quoted 6 lines · Yury Norov

In some places, drivers/perf code calls bitmap_weight() to check if any bit of a given bitmap is set. It's better to use bitmap_empty() in that case because bitmap_empty() stops traversing the bitmap as soon as it finds first set bit, while bitmap_weight() counts all bits unconditionally.

This looks like a nice semantic cleanup to me, so FWIW:

Thanks :)

Quoted 3 lines

How are you expecting to queue all of this?

I expect maintainers of corresponding subsystems will pick most of the material. For the rest, I have my own bitmap branch.

Quoted 1 line

Should Will and I pick this patch?

Yes please.

Quoted 74 lines

Thanks,
Mark.

Quoted 71 lines
---
 drivers/perf/arm-cci.c                   | 2 +-
 drivers/perf/arm_pmu.c                   | 4 ++--
 drivers/perf/hisilicon/hisi_uncore_pmu.c | 2 +-
 drivers/perf/xgene_pmu.c                 | 2 +-
 4 files changed, 5 insertions(+), 5 deletions(-)
drivers/perf/arm-cci.c +1 -1
index 54aca3a62814..96e09fa40909 100644
@@ -1096,7 +1096,7 @@ static void cci_pmu_enable(struct pmu *pmu)
 {
 	struct cci_pmu *cci_pmu = to_cci_pmu(pmu);
 	struct cci_pmu_hw_events *hw_events = &cci_pmu->hw_events;
-	int enabled = bitmap_weight(hw_events->used_mask, cci_pmu->num_cntrs);
+	bool enabled = !bitmap_empty(hw_events->used_mask, cci_pmu->num_cntrs);
 	unsigned long flags;
 
 	if (!enabled)
drivers/perf/arm_pmu.c +2 -2
index 295cc7952d0e..a31b302b0ade 100644
@@ -524,7 +524,7 @@ static void armpmu_enable(struct pmu *pmu)
 {
 	struct arm_pmu *armpmu = to_arm_pmu(pmu);
 	struct pmu_hw_events *hw_events = this_cpu_ptr(armpmu->hw_events);
-	int enabled = bitmap_weight(hw_events->used_mask, armpmu->num_events);
+	bool enabled = !bitmap_empty(hw_events->used_mask, armpmu->num_events);
 
 	/* For task-bound events we may be called on other CPUs */
 	if (!cpumask_test_cpu(smp_processor_id(), &armpmu->supported_cpus))
@@ -785,7 +785,7 @@ static int cpu_pm_pmu_notify(struct notifier_block *b, unsigned long cmd,
 {
 	struct arm_pmu *armpmu = container_of(b, struct arm_pmu, cpu_pm_nb);
 	struct pmu_hw_events *hw_events = this_cpu_ptr(armpmu->hw_events);
-	int enabled = bitmap_weight(hw_events->used_mask, armpmu->num_events);
+	bool enabled = !bitmap_empty(hw_events->used_mask, armpmu->num_events);
 
 	if (!cpumask_test_cpu(smp_processor_id(), &armpmu->supported_cpus))
 		return NOTIFY_DONE;
drivers/perf/hisilicon/hisi_uncore_pmu.c +1 -1
index a738aeab5c04..358e4e284a62 100644
@@ -393,7 +393,7 @@ EXPORT_SYMBOL_GPL(hisi_uncore_pmu_read);
 void hisi_uncore_pmu_enable(struct pmu *pmu)
 {
 	struct hisi_pmu *hisi_pmu = to_hisi_pmu(pmu);
-	int enabled = bitmap_weight(hisi_pmu->pmu_events.used_mask,
+	bool enabled = !bitmap_empty(hisi_pmu->pmu_events.used_mask,
 				    hisi_pmu->num_counters);
 
 	if (!enabled)
drivers/perf/xgene_pmu.c +1 -1
index 5283608dc055..0c32dffc7ede 100644
@@ -867,7 +867,7 @@ static void xgene_perf_pmu_enable(struct pmu *pmu)
 {
 	struct xgene_pmu_dev *pmu_dev = to_pmu_dev(pmu);
 	struct xgene_pmu *xgene_pmu = pmu_dev->parent;
-	int enabled = bitmap_weight(pmu_dev->cntr_assign_mask,
+	bool enabled = !bitmap_empty(pmu_dev->cntr_assign_mask,
 			pmu_dev->max_counters);
 
 	if (!enabled)
Signature · 1 line
2.32.0
#26 lore raw

Re: [PATCH 12/49] perf: replace bitmap_weight with bitmap_empty where appropriate

In reply to Yury Norov

Le 10/02/2022 à 23:48, Yury Norov a écrit :

Quoted 66 lines

In some places, drivers/perf code calls bitmap_weight() to check if any bit of a given bitmap is set. It's better to use bitmap_empty() in that case because bitmap_empty() stops traversing the bitmap as soon as it finds first set bit, while bitmap_weight() counts all bits unconditionally.

---
  drivers/perf/arm-cci.c                   | 2 +-
  drivers/perf/arm_pmu.c                   | 4 ++--
  drivers/perf/hisilicon/hisi_uncore_pmu.c | 2 +-
  drivers/perf/xgene_pmu.c                 | 2 +-
  4 files changed, 5 insertions(+), 5 deletions(-)
drivers/perf/arm-cci.c +1 -1
index 54aca3a62814..96e09fa40909 100644
@@ -1096,7 +1096,7 @@ static void cci_pmu_enable(struct pmu *pmu)
  {
  	struct cci_pmu *cci_pmu = to_cci_pmu(pmu);
  	struct cci_pmu_hw_events *hw_events = &cci_pmu->hw_events;
-	int enabled = bitmap_weight(hw_events->used_mask, cci_pmu->num_cntrs);
+	bool enabled = !bitmap_empty(hw_events->used_mask, cci_pmu->num_cntrs);
  	unsigned long flags;
 
  	if (!enabled)
drivers/perf/arm_pmu.c +2 -2
index 295cc7952d0e..a31b302b0ade 100644
@@ -524,7 +524,7 @@ static void armpmu_enable(struct pmu *pmu)
  {
  	struct arm_pmu *armpmu = to_arm_pmu(pmu);
  	struct pmu_hw_events *hw_events = this_cpu_ptr(armpmu->hw_events);
-	int enabled = bitmap_weight(hw_events->used_mask, armpmu->num_events);
+	bool enabled = !bitmap_empty(hw_events->used_mask, armpmu->num_events);
 
  	/* For task-bound events we may be called on other CPUs */
  	if (!cpumask_test_cpu(smp_processor_id(), &armpmu->supported_cpus))
@@ -785,7 +785,7 @@ static int cpu_pm_pmu_notify(struct notifier_block *b, unsigned long cmd,
  {
  	struct arm_pmu *armpmu = container_of(b, struct arm_pmu, cpu_pm_nb);
  	struct pmu_hw_events *hw_events = this_cpu_ptr(armpmu->hw_events);
-	int enabled = bitmap_weight(hw_events->used_mask, armpmu->num_events);
+	bool enabled = !bitmap_empty(hw_events->used_mask, armpmu->num_events);
 
  	if (!cpumask_test_cpu(smp_processor_id(), &armpmu->supported_cpus))
  		return NOTIFY_DONE;
drivers/perf/hisilicon/hisi_uncore_pmu.c +1 -1
index a738aeab5c04..358e4e284a62 100644
@@ -393,7 +393,7 @@ EXPORT_SYMBOL_GPL(hisi_uncore_pmu_read);
  void hisi_uncore_pmu_enable(struct pmu *pmu)
  {
  	struct hisi_pmu *hisi_pmu = to_hisi_pmu(pmu);
-	int enabled = bitmap_weight(hisi_pmu->pmu_events.used_mask,
+	bool enabled = !bitmap_empty(hisi_pmu->pmu_events.used_mask,
  				    hisi_pmu->num_counters);
 
  	if (!enabled)
drivers/perf/xgene_pmu.c +0 -0
index 5283608dc055..0c32dffc7ede 100644

drivers/perf/xgene_pmu.c static void xgene_perf_pmu_enable(struct pmu *pmu) · line 871

Quoted 6 lines
drivers/perf/xgene_pmu.c +1 -1
@@ -867,7 +867,7 @@ static void xgene_perf_pmu_enable(struct pmu *pmu)
  {
  	struct xgene_pmu_dev *pmu_dev = to_pmu_dev(pmu);
  	struct xgene_pmu *xgene_pmu = pmu_dev->parent;
-	int enabled = bitmap_weight(pmu_dev->cntr_assign_mask,
+	bool enabled = !bitmap_empty(pmu_dev->cntr_assign_mask,
  			pmu_dev->max_counters);

Would it make sense to call it 'disabled', remove the "!"...

drivers/perf/xgene_pmu.c static void xgene_perf_pmu_enable(struct pmu *pmu) · line 872

Quoted 2 lines
drivers/perf/xgene_pmu.c +0 -0
  	if (!enabled)

... and 'if (disabled)' here?

Just my 2c,

CJ

author maintainer
#27 lore raw

Re: [PATCH 12/49] perf: replace bitmap_weight with bitmap_empty where appropriate

Quoted 72 lines · Christophe JAILLET

Le 10/02/2022 à 23:48, Yury Norov a écrit :

Quoted 62 lines

In some places, drivers/perf code calls bitmap_weight() to check if any bit of a given bitmap is set. It's better to use bitmap_empty() in that case because bitmap_empty() stops traversing the bitmap as soon as it finds first set bit, while bitmap_weight() counts all bits unconditionally.

---
  drivers/perf/arm-cci.c                   | 2 +-
  drivers/perf/arm_pmu.c                   | 4 ++--
  drivers/perf/hisilicon/hisi_uncore_pmu.c | 2 +-
  drivers/perf/xgene_pmu.c                 | 2 +-
  4 files changed, 5 insertions(+), 5 deletions(-)
drivers/perf/arm-cci.c +1 -1
index 54aca3a62814..96e09fa40909 100644
@@ -1096,7 +1096,7 @@ static void cci_pmu_enable(struct pmu *pmu)
  {
  	struct cci_pmu *cci_pmu = to_cci_pmu(pmu);
  	struct cci_pmu_hw_events *hw_events = &cci_pmu->hw_events;
-	int enabled = bitmap_weight(hw_events->used_mask, cci_pmu->num_cntrs);
+	bool enabled = !bitmap_empty(hw_events->used_mask, cci_pmu->num_cntrs);
  	unsigned long flags;
  	if (!enabled)
drivers/perf/arm_pmu.c +2 -2
index 295cc7952d0e..a31b302b0ade 100644
@@ -524,7 +524,7 @@ static void armpmu_enable(struct pmu *pmu)
  {
  	struct arm_pmu *armpmu = to_arm_pmu(pmu);
  	struct pmu_hw_events *hw_events = this_cpu_ptr(armpmu->hw_events);
-	int enabled = bitmap_weight(hw_events->used_mask, armpmu->num_events);
+	bool enabled = !bitmap_empty(hw_events->used_mask, armpmu->num_events);
  	/* For task-bound events we may be called on other CPUs */
  	if (!cpumask_test_cpu(smp_processor_id(), &armpmu->supported_cpus))
@@ -785,7 +785,7 @@ static int cpu_pm_pmu_notify(struct notifier_block *b, unsigned long cmd,
  {
  	struct arm_pmu *armpmu = container_of(b, struct arm_pmu, cpu_pm_nb);
  	struct pmu_hw_events *hw_events = this_cpu_ptr(armpmu->hw_events);
-	int enabled = bitmap_weight(hw_events->used_mask, armpmu->num_events);
+	bool enabled = !bitmap_empty(hw_events->used_mask, armpmu->num_events);
  	if (!cpumask_test_cpu(smp_processor_id(), &armpmu->supported_cpus))
  		return NOTIFY_DONE;
drivers/perf/hisilicon/hisi_uncore_pmu.c +1 -1
index a738aeab5c04..358e4e284a62 100644
@@ -393,7 +393,7 @@ EXPORT_SYMBOL_GPL(hisi_uncore_pmu_read);
  void hisi_uncore_pmu_enable(struct pmu *pmu)
  {
  	struct hisi_pmu *hisi_pmu = to_hisi_pmu(pmu);
-	int enabled = bitmap_weight(hisi_pmu->pmu_events.used_mask,
+	bool enabled = !bitmap_empty(hisi_pmu->pmu_events.used_mask,
  				    hisi_pmu->num_counters);
  	if (!enabled)
drivers/perf/xgene_pmu.c +0 -0
index 5283608dc055..0c32dffc7ede 100644

drivers/perf/xgene_pmu.c static void xgene_perf_pmu_enable(struct pmu *pmu) · line 871

Quoted 6 lines
drivers/perf/xgene_pmu.c +1 -1
@@ -867,7 +867,7 @@ static void xgene_perf_pmu_enable(struct pmu *pmu)
  {
  	struct xgene_pmu_dev *pmu_dev = to_pmu_dev(pmu);
  	struct xgene_pmu *xgene_pmu = pmu_dev->parent;
-	int enabled = bitmap_weight(pmu_dev->cntr_assign_mask,
+	bool enabled = !bitmap_empty(pmu_dev->cntr_assign_mask,
  			pmu_dev->max_counters);

Would it make sense to call it 'disabled', remove the "!"...

Quoted 2 lines

drivers/perf/xgene_pmu.c static void xgene_perf_pmu_enable(struct pmu *pmu) · line 872

Quoted 1 line
drivers/perf/xgene_pmu.c +0 -0
  	if (!enabled)

... and 'if (disabled)' here?

People like positive names (as I do):

        $ git grep bool | grep "= \!" | grep -v "= \!\!" | wc -l
        334

And probably authors chose positive name in this case for a reason.

Replacing 'enabled' with 'disabled' just to avoid negation will add absolutely nothing to performance, neither to readability. But noise level of this and other patches will increase - just for nothing.

For me it sounds like total negative commitment.

Thanks,
Yury

author maintainer
#28 lore raw

PATCH v4 13/49 perf tools: replace bitmap_weight with bitmap_empty where appropriate

In reply to Yury Norov

Some code in builtin-c2c.c calls bitmap_weight() to check if any bit of a given bitmap is set. It's better to use bitmap_empty() in that case because bitmap_empty() stops traversing the bitmap as soon as it finds first set bit, while bitmap_weight() counts all bits unconditionally.

---
 tools/perf/builtin-c2c.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
tools/perf/builtin-c2c.c +2 -2
index 77dd4afacca4..14f787c67140 100644
@@ -1080,7 +1080,7 @@ node_entry(struct perf_hpp_fmt *fmt __maybe_unused, struct perf_hpp *hpp,
 		bitmap_zero(set, c2c.cpus_cnt);
 		bitmap_and(set, c2c_he->cpuset, c2c.nodes[node], c2c.cpus_cnt);
 
-		if (!bitmap_weight(set, c2c.cpus_cnt)) {
+		if (bitmap_empty(set, c2c.cpus_cnt)) {
 			if (c2c.node_info == 1) {
 				ret = scnprintf(hpp->buf, hpp->size, "%21s", " ");
 				advance_hpp(hpp, ret);
@@ -1944,7 +1944,7 @@ static int set_nodestr(struct c2c_hist_entry *c2c_he)
 	if (c2c_he->nodestr)
 		return 0;
 
-	if (bitmap_weight(c2c_he->nodeset, c2c.nodes_cnt)) {
+	if (!bitmap_empty(c2c_he->nodeset, c2c.nodes_cnt)) {
 		len = bitmap_scnprintf(c2c_he->nodeset, c2c.nodes_cnt,
 				      buf, sizeof(buf));
 	} else {
Signature · 1 line
2.32.0
author maintainer
#29 lore raw

PATCH v4 14/49 arch/alpha: replace cpumask_weight with cpumask_empty where appropriate

In reply to Yury Norov

common_shutdown_1() calls cpumask_weight() to check if any bit of a given cpumask is set. We can do it more efficiently with cpumask_empty() because cpumask_empty() stops traversing the cpumask as soon as it finds first set bit, while cpumask_weight() counts all bits unconditionally.

---
 arch/alpha/kernel/process.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/alpha/kernel/process.c +1 -1
index 5f8527081da9..0d4bc60828bf 100644
@@ -125,7 +125,7 @@ common_shutdown_1(void *generic_ptr)
 	/* Wait for the secondaries to halt. */
 	set_cpu_present(boot_cpuid, false);
 	set_cpu_possible(boot_cpuid, false);
-	while (cpumask_weight(cpu_present_mask))
+	while (!cpumask_empty(cpu_present_mask))
 		barrier();
 #endif
 
Signature · 1 line
2.32.0
author maintainer
#30 lore raw

PATCH v4 15/49 arch/ia64: replace cpumask_weight with cpumask_empty where appropriate

In reply to Yury Norov

setup_arch() calls cpumask_weight() to check if any bit of a given cpumask is set. We can do it more efficiently with cpumask_empty() because cpumask_empty() stops traversing the cpumask as soon as it finds first set bit, while cpumask_weight() counts all bits unconditionally.

---
 arch/ia64/kernel/setup.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/ia64/kernel/setup.c +1 -1
index 5010348fa21b..fd6301eafa9d 100644
@@ -572,7 +572,7 @@ setup_arch (char **cmdline_p)
 #ifdef CONFIG_ACPI_HOTPLUG_CPU
 	prefill_possible_map();
 #endif
-	per_cpu_scan_finalize((cpumask_weight(&early_cpu_possible_map) = 0 ?
+	per_cpu_scan_finalize((cpumask_empty(&early_cpu_possible_map) ?
 		32 : cpumask_weight(&early_cpu_possible_map)),
 		additional_cpus > 0 ? additional_cpus : 0);
 #endif /* CONFIG_ACPI_NUMA */
Signature · 1 line
2.32.0
author maintainer
#31 lore raw

PATCH v4 16/49 arch/x86: replace cpumask_weight with cpumask_empty where appropriate

In reply to Yury Norov

In some cases, arch/x86 code calls cpumask_weight() to check if any bit of a given cpumask is set. We can do it more efficiently with cpumask_empty() because cpumask_empty() stops traversing the cpumask as soon as it finds first set bit, while cpumask_weight() counts all bits unconditionally.

---
 arch/x86/kernel/cpu/resctrl/rdtgroup.c | 14 +++++++-------
 arch/x86/mm/mmio-mod.c                 |  2 +-
 arch/x86/platform/uv/uv_nmi.c          |  2 +-
 3 files changed, 9 insertions(+), 9 deletions(-)
arch/x86/kernel/cpu/resctrl/rdtgroup.c +7 -7
index b57b3db9a6a7..e23ff03290b8 100644
@@ -341,14 +341,14 @@ static int cpus_mon_write(struct rdtgroup *rdtgrp, cpumask_var_t newmask,
 
 	/* Check whether cpus belong to parent ctrl group */
 	cpumask_andnot(tmpmask, newmask, &prgrp->cpu_mask);
-	if (cpumask_weight(tmpmask)) {
+	if (!cpumask_empty(tmpmask)) {
 		rdt_last_cmd_puts("Can only add CPUs to mongroup that belong to parent\n");
 		return -EINVAL;
 	}
 
 	/* Check whether cpus are dropped from this group */
 	cpumask_andnot(tmpmask, &rdtgrp->cpu_mask, newmask);
-	if (cpumask_weight(tmpmask)) {
+	if (!cpumask_empty(tmpmask)) {
 		/* Give any dropped cpus to parent rdtgroup */
 		cpumask_or(&prgrp->cpu_mask, &prgrp->cpu_mask, tmpmask);
 		update_closid_rmid(tmpmask, prgrp);
@@ -359,7 +359,7 @@ static int cpus_mon_write(struct rdtgroup *rdtgrp, cpumask_var_t newmask,
 	 * and update per-cpu rmid
 	 */
 	cpumask_andnot(tmpmask, newmask, &rdtgrp->cpu_mask);
-	if (cpumask_weight(tmpmask)) {
+	if (!cpumask_empty(tmpmask)) {
 		head = &prgrp->mon.crdtgrp_list;
 		list_for_each_entry(crgrp, head, mon.crdtgrp_list) {
 			if (crgrp == rdtgrp)
@@ -394,7 +394,7 @@ static int cpus_ctrl_write(struct rdtgroup *rdtgrp, cpumask_var_t newmask,
 
 	/* Check whether cpus are dropped from this group */
 	cpumask_andnot(tmpmask, &rdtgrp->cpu_mask, newmask);
-	if (cpumask_weight(tmpmask)) {
+	if (!cpumask_empty(tmpmask)) {
 		/* Can't drop from default group */
 		if (rdtgrp == &rdtgroup_default) {
 			rdt_last_cmd_puts("Can't drop CPUs from default group\n");
@@ -413,12 +413,12 @@ static int cpus_ctrl_write(struct rdtgroup *rdtgrp, cpumask_var_t newmask,
 	 * and update per-cpu closid/rmid.
 	 */
 	cpumask_andnot(tmpmask, newmask, &rdtgrp->cpu_mask);
-	if (cpumask_weight(tmpmask)) {
+	if (!cpumask_empty(tmpmask)) {
 		list_for_each_entry(r, &rdt_all_groups, rdtgroup_list) {
 			if (r == rdtgrp)
 				continue;
 			cpumask_and(tmpmask1, &r->cpu_mask, tmpmask);
-			if (cpumask_weight(tmpmask1))
+			if (!cpumask_empty(tmpmask1))
 				cpumask_rdtgrp_clear(r, tmpmask1);
 		}
 		update_closid_rmid(tmpmask, rdtgrp);
@@ -488,7 +488,7 @@ static ssize_t rdtgroup_cpus_write(struct kernfs_open_file *of,
 
 	/* check that user didn't specify any offline cpus */
 	cpumask_andnot(tmpmask, newmask, cpu_online_mask);
-	if (cpumask_weight(tmpmask)) {
+	if (!cpumask_empty(tmpmask)) {
 		ret = -EINVAL;
 		rdt_last_cmd_puts("Can only assign online CPUs\n");
 		goto unlock;
arch/x86/mm/mmio-mod.c +1 -1
index 933a2ebad471..c3317f0650d8 100644
@@ -400,7 +400,7 @@ static void leave_uniprocessor(void)
 	int cpu;
 	int err;
 
-	if (!cpumask_available(downed_cpus) || cpumask_weight(downed_cpus) == 0)
+	if (!cpumask_available(downed_cpus) || cpumask_empty(downed_cpus))
 		return;
 	pr_notice("Re-enabling CPUs...\n");
 	for_each_cpu(cpu, downed_cpus) {
arch/x86/platform/uv/uv_nmi.c +1 -1
index 1e9ff28bc2e0..ea277fc08357 100644
@@ -985,7 +985,7 @@ static int uv_handle_nmi(unsigned int reason, struct pt_regs *regs)
 
 	/* Clear global flags */
 	if (master) {
-		if (cpumask_weight(uv_nmi_cpu_mask))
+		if (!cpumask_empty(uv_nmi_cpu_mask))
 			uv_nmi_cleanup_mask();
 		atomic_set(&uv_nmi_cpus_in_nmi, -1);
 		atomic_set(&uv_nmi_cpu, -1);
Signature · 1 line
2.32.0
merge bot Applied
#32 lore raw

[tip: x86/cleanups] x86: Replace cpumask_weight() with cpumask_empty() where appropriate

The following commit has been merged into the x86/cleanups branch of tip:

The following commit has been merged into the x86/cleanups branch of tip:

Commit-ID:     3a5ff1f6dd50f5e1c2aa87491910dd6d275af24b
Gitweb:        https://git.kernel.org/tip/3a5ff1f6dd50f5e1c2aa87491910dd6d275af24b
Author:        Yury Norov <[email protected]>
AuthorDate:    Thu, 10 Feb 2022 14:49:00 -08:00
Committer:     Thomas Gleixner <[email protected]>
CommitterDate: Sun, 10 Apr 2022 22:35:38 +02:00

x86: Replace cpumask_weight() with cpumask_empty() where appropriate

In some cases, x86 code calls cpumask_weight() to check if any bit of a given cpumask is set.

This can be done more efficiently with cpumask_empty() because cpumask_empty() stops traversing the cpumask as soon as it finds first set bit, while cpumask_weight() counts all bits unconditionally.

---
 arch/x86/kernel/cpu/resctrl/rdtgroup.c | 14 +++++++-------
 arch/x86/mm/mmio-mod.c                 |  2 +-
 arch/x86/platform/uv/uv_nmi.c          |  2 +-
 3 files changed, 9 insertions(+), 9 deletions(-)
arch/x86/kernel/cpu/resctrl/rdtgroup.c +7 -7
index 83f901e..f276aff 100644
@@ -341,14 +341,14 @@ static int cpus_mon_write(struct rdtgroup *rdtgrp, cpumask_var_t newmask,
 
 	/* Check whether cpus belong to parent ctrl group */
 	cpumask_andnot(tmpmask, newmask, &prgrp->cpu_mask);
-	if (cpumask_weight(tmpmask)) {
+	if (!cpumask_empty(tmpmask)) {
 		rdt_last_cmd_puts("Can only add CPUs to mongroup that belong to parent\n");
 		return -EINVAL;
 	}
 
 	/* Check whether cpus are dropped from this group */
 	cpumask_andnot(tmpmask, &rdtgrp->cpu_mask, newmask);
-	if (cpumask_weight(tmpmask)) {
+	if (!cpumask_empty(tmpmask)) {
 		/* Give any dropped cpus to parent rdtgroup */
 		cpumask_or(&prgrp->cpu_mask, &prgrp->cpu_mask, tmpmask);
 		update_closid_rmid(tmpmask, prgrp);
@@ -359,7 +359,7 @@ static int cpus_mon_write(struct rdtgroup *rdtgrp, cpumask_var_t newmask,
 	 * and update per-cpu rmid
 	 */
 	cpumask_andnot(tmpmask, newmask, &rdtgrp->cpu_mask);
-	if (cpumask_weight(tmpmask)) {
+	if (!cpumask_empty(tmpmask)) {
 		head = &prgrp->mon.crdtgrp_list;
 		list_for_each_entry(crgrp, head, mon.crdtgrp_list) {
 			if (crgrp == rdtgrp)
@@ -394,7 +394,7 @@ static int cpus_ctrl_write(struct rdtgroup *rdtgrp, cpumask_var_t newmask,
 
 	/* Check whether cpus are dropped from this group */
 	cpumask_andnot(tmpmask, &rdtgrp->cpu_mask, newmask);
-	if (cpumask_weight(tmpmask)) {
+	if (!cpumask_empty(tmpmask)) {
 		/* Can't drop from default group */
 		if (rdtgrp == &rdtgroup_default) {
 			rdt_last_cmd_puts("Can't drop CPUs from default group\n");
@@ -413,12 +413,12 @@ static int cpus_ctrl_write(struct rdtgroup *rdtgrp, cpumask_var_t newmask,
 	 * and update per-cpu closid/rmid.
 	 */
 	cpumask_andnot(tmpmask, newmask, &rdtgrp->cpu_mask);
-	if (cpumask_weight(tmpmask)) {
+	if (!cpumask_empty(tmpmask)) {
 		list_for_each_entry(r, &rdt_all_groups, rdtgroup_list) {
 			if (r == rdtgrp)
 				continue;
 			cpumask_and(tmpmask1, &r->cpu_mask, tmpmask);
-			if (cpumask_weight(tmpmask1))
+			if (!cpumask_empty(tmpmask1))
 				cpumask_rdtgrp_clear(r, tmpmask1);
 		}
 		update_closid_rmid(tmpmask, rdtgrp);
@@ -488,7 +488,7 @@ static ssize_t rdtgroup_cpus_write(struct kernfs_open_file *of,
 
 	/* check that user didn't specify any offline cpus */
 	cpumask_andnot(tmpmask, newmask, cpu_online_mask);
-	if (cpumask_weight(tmpmask)) {
+	if (!cpumask_empty(tmpmask)) {
 		ret = -EINVAL;
 		rdt_last_cmd_puts("Can only assign online CPUs\n");
 		goto unlock;
arch/x86/mm/mmio-mod.c +1 -1
index 933a2eb..c3317f0 100644
@@ -400,7 +400,7 @@ static void leave_uniprocessor(void)
 	int cpu;
 	int err;
 
-	if (!cpumask_available(downed_cpus) || cpumask_weight(downed_cpus) == 0)
+	if (!cpumask_available(downed_cpus) || cpumask_empty(downed_cpus))
 		return;
 	pr_notice("Re-enabling CPUs...\n");
 	for_each_cpu(cpu, downed_cpus) {
arch/x86/platform/uv/uv_nmi.c +1 -1
index 1e9ff28..ea277fc 100644
@@ -985,7 +985,7 @@ static int uv_handle_nmi(unsigned int reason, struct pt_regs *regs)
 
 	/* Clear global flags */
 	if (master) {
-		if (cpumask_weight(uv_nmi_cpu_mask))
+		if (!cpumask_empty(uv_nmi_cpu_mask))
 			uv_nmi_cleanup_mask();
 		atomic_set(&uv_nmi_cpus_in_nmi, -1);
 		atomic_set(&uv_nmi_cpu, -1);
author maintainer
#33 lore raw

PATCH v4 17/49 cpufreq: replace cpumask_weight with cpumask_empty where appropriate

In reply to Yury Norov

drivers/cpufreq calls cpumask_weight() to check if any bit of a given cpumask is set. We can do it more efficiently with cpumask_empty() because cpumask_empty() stops traversing the cpumask as soon as it finds first set bit, while cpumask_weight() counts all bits unconditionally.

---
 drivers/cpufreq/qcom-cpufreq-hw.c | 2 +-
 drivers/cpufreq/scmi-cpufreq.c    | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
drivers/cpufreq/qcom-cpufreq-hw.c +1 -1
index 05f3d7876e44..95a0c57ab5bb 100644
@@ -482,7 +482,7 @@ static int qcom_cpufreq_hw_cpu_init(struct cpufreq_policy *policy)
 	}
 
 	qcom_get_related_cpus(index, policy->cpus);
-	if (!cpumask_weight(policy->cpus)) {
+	if (cpumask_empty(policy->cpus)) {
 		dev_err(dev, "Domain-%d failed to get related CPUs\n", index);
 		ret = -ENOENT;
 		goto error;
drivers/cpufreq/scmi-cpufreq.c +1 -1
index 1e0cd4d165f0..919fa6e3f462 100644
@@ -154,7 +154,7 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
 	 * table and opp-shared.
 	 */
 	ret = dev_pm_opp_of_get_sharing_cpus(cpu_dev, priv->opp_shared_cpus);
-	if (ret || !cpumask_weight(priv->opp_shared_cpus)) {
+	if (ret || cpumask_empty(priv->opp_shared_cpus)) {
 		/*
 		 * Either opp-table is not set or no opp-shared was found.
 		 * Use the CPU mask from SCMI to designate CPUs sharing an OPP
Signature · 1 line
2.32.0
maintainer
#34 lore raw

Re: [PATCH 17/49] cpufreq: replace cpumask_weight with cpumask_empty where appropriate

Quoted 11 lines · Yury Norov

drivers/cpufreq calls cpumask_weight() to check if any bit of a given cpumask is set. We can do it more efficiently with cpumask_empty() because cpumask_empty() stops traversing the cpumask as soon as it finds first set bit, while cpumask_weight() counts all bits unconditionally.

---
 drivers/cpufreq/qcom-cpufreq-hw.c | 2 +-
 drivers/cpufreq/scmi-cpufreq.c    | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

I already applied it yesterday and replied to you as well. Did I miss something ?

Signature · 1 line
viresh
author maintainer
#35 lore raw

Re: [PATCH 17/49] cpufreq: replace cpumask_weight with cpumask_empty where appropriate

Quoted 13 lines · Viresh Kumar
Quoted 11 lines · Yury Norov

drivers/cpufreq calls cpumask_weight() to check if any bit of a given cpumask is set. We can do it more efficiently with cpumask_empty() because cpumask_empty() stops traversing the cpumask as soon as it finds first set bit, while cpumask_weight() counts all bits unconditionally.

---
 drivers/cpufreq/qcom-cpufreq-hw.c | 2 +-
 drivers/cpufreq/scmi-cpufreq.c    | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
Quoted 2 lines

I already applied it yesterday and replied to you as well. Did I miss something ?

It appeared in next today after I prepared this series, that's why it slipped through. Sorry for that. Please ignore this patch.

Thanks,
Yury

author maintainer
#36 lore raw

PATCH v4 18/49 drm/i915/pmu: replace cpumask_weight with cpumask_empty where appropriate

In reply to Yury Norov

i915_pmu_cpu_online() calls cpumask_weight() to check if any bit of a given cpumask is set. We can do it more efficiently with cpumask_empty() because cpumask_empty() stops traversing the cpumask as soon as it finds first set bit, while cpumask_weight() counts all bits unconditionally.

---
 drivers/gpu/drm/i915/i915_pmu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/i915/i915_pmu.c +1 -1
index cfc21042499d..7299ed9937dd 100644
@@ -1050,7 +1050,7 @@ static int i915_pmu_cpu_online(unsigned int cpu, struct hlist_node *node)
 	GEM_BUG_ON(!pmu->base.event_init);
 
 	/* Select the first online CPU as a designated reader. */
-	if (!cpumask_weight(&i915_pmu_cpumask))
+	if (cpumask_empty(&i915_pmu_cpumask))
 		cpumask_set_cpu(cpu, &i915_pmu_cpumask);
 
 	return 0;
Signature · 1 line
2.32.0
author maintainer
#37 lore raw

PATCH v4 19/49 RDMA/hfi: replace cpumask_weight with cpumask_empty where appropriate

In reply to Yury Norov

drivers/infiniband/hw/hfi1/affinity.c code calls cpumask_weight() to check if any bit of a given cpumask is set. We can do it more efficiently with cpumask_empty() because cpumask_empty() stops traversing the cpumask as soon as it finds first set bit, while cpumask_weight() counts all bits unconditionally.

---
 drivers/infiniband/hw/hfi1/affinity.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/infiniband/hw/hfi1/affinity.c +2 -2
index 706b3b659713..877f8e84a672 100644
@@ -666,7 +666,7 @@ int hfi1_dev_affinity_init(struct hfi1_devdata *dd)
 			 * engines, use the same CPU cores as general/control
 			 * context.
 			 */
-			if (cpumask_weight(&entry->def_intr.mask) == 0)
+			if (cpumask_empty(&entry->def_intr.mask))
 				cpumask_copy(&entry->def_intr.mask,
 					     &entry->general_intr_mask);
 		}
@@ -686,7 +686,7 @@ int hfi1_dev_affinity_init(struct hfi1_devdata *dd)
 		 * vectors, use the same CPU core as the general/control
 		 * context.
 		 */
-		if (cpumask_weight(&entry->comp_vect_mask) == 0)
+		if (cpumask_empty(&entry->comp_vect_mask))
 			cpumask_copy(&entry->comp_vect_mask,
 				     &entry->general_intr_mask);
 	}
Signature · 1 line
2.32.0
maintainer Applied
#38 lore raw

Re: [PATCH 19/49] RDMA/hfi: replace cpumask_weight with cpumask_empty where appropriate

Quoted 11 lines · Yury Norov

drivers/infiniband/hw/hfi1/affinity.c code calls cpumask_weight() to check if any bit of a given cpumask is set. We can do it more efficiently with cpumask_empty() because cpumask_empty() stops traversing the cpumask as soon as it finds first set bit, while cpumask_weight() counts all bits unconditionally.

---
 drivers/infiniband/hw/hfi1/affinity.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

Applied to the rdma tree

Thanks,
Jason

author maintainer
#39 lore raw

PATCH v4 20/49 irq: mips: replace cpumask_weight with cpumask_empty where appropriate

In reply to Yury Norov

bcm6345_l1_of_init() calls cpumask_weight() to check if any bit of a given cpumask is set. We can do it more efficiently with cpumask_empty() because cpumask_empty() stops traversing the cpumask as soon as it finds first set bit, while cpumask_weight() counts all bits unconditionally.

---
 drivers/irqchip/irq-bcm6345-l1.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/irqchip/irq-bcm6345-l1.c +1 -1
index fd079215c17f..142a7431745f 100644
@@ -315,7 +315,7 @@ static int __init bcm6345_l1_of_init(struct device_node *dn,
 			cpumask_set_cpu(idx, &intc->cpumask);
 	}
 
-	if (!cpumask_weight(&intc->cpumask)) {
+	if (cpumask_empty(&intc->cpumask)) {
 		ret = -ENODEV;
 		goto out_free;
 	}
Signature · 1 line
2.32.0
merge bot Applied
#40 lore raw

[tip: irq/core] irqchip/bmips: Replace cpumask_weight() with cpumask_empty()

The following commit has been merged into the irq/core branch of tip:

The following commit has been merged into the irq/core branch of tip:

Commit-ID:     0de61d739c21003201a0adb1f5c403f89a7c2441
Gitweb:        https://git.kernel.org/tip/0de61d739c21003201a0adb1f5c403f89a7c2441
Author:        Yury Norov <[email protected]>
AuthorDate:    Thu, 10 Feb 2022 14:49:04 -08:00
Committer:     Thomas Gleixner <[email protected]>
CommitterDate: Sun, 10 Apr 2022 22:28:28 +02:00

irqchip/bmips: Replace cpumask_weight() with cpumask_empty()

bcm6345_l1_of_init() calls cpumask_weight() to check if any bit of a given cpumask is set.

This can be done more efficiently with cpumask_empty() because cpumask_empty() stops traversing the cpumask as soon as it finds first set bit, while cpumask_weight() counts all bits unconditionally.

---
 drivers/irqchip/irq-bcm6345-l1.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/irqchip/irq-bcm6345-l1.c +1 -1
index fd07921..142a743 100644
@@ -315,7 +315,7 @@ static int __init bcm6345_l1_of_init(struct device_node *dn,
 			cpumask_set_cpu(idx, &intc->cpumask);
 	}
 
-	if (!cpumask_weight(&intc->cpumask)) {
+	if (cpumask_empty(&intc->cpumask)) {
 		ret = -ENODEV;
 		goto out_free;
 	}
author maintainer
#41 lore raw

PATCH v4 21/49 genirq/affinity: replace cpumask_weight with cpumask_empty where appropriate

In reply to Yury Norov

__irq_build_affinity_masks() calls cpumask_weight() to check if any bit of a given cpumask is set. We can do it more efficiently with cpumask_empty() because cpumask_empty() stops traversing the cpumask as soon as it finds first set bit, while cpumask_weight() counts all bits unconditionally.

---
 kernel/irq/affinity.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/irq/affinity.c +1 -1
index f7ff8919dc9b..18740faf0eb1 100644
@@ -258,7 +258,7 @@ static int __irq_build_affinity_masks(unsigned int startvec,
 	nodemask_t nodemsk = NODE_MASK_NONE;
 	struct node_vectors *node_vectors;
 
-	if (!cpumask_weight(cpu_mask))
+	if (cpumask_empty(cpu_mask))
 		return 0;
 
 	nodes = get_nodes_in_cpumask(node_to_cpumask, cpu_mask, &nodemsk);
Signature · 1 line
2.32.0
merge bot Applied
#42 lore raw

[tip: irq/core] genirq/affinity: Replace cpumask_weight() with cpumask_empty() where appropriate

The following commit has been merged into the irq/core branch of tip:

The following commit has been merged into the irq/core branch of tip:

Commit-ID:     911488de0565f1d53bd36174d20917ebc4b44c0e
Gitweb:        https://git.kernel.org/tip/911488de0565f1d53bd36174d20917ebc4b44c0e
Author:        Yury Norov <[email protected]>
AuthorDate:    Thu, 10 Feb 2022 14:49:05 -08:00
Committer:     Thomas Gleixner <[email protected]>
CommitterDate: Sun, 10 Apr 2022 22:20:28 +02:00

genirq/affinity: Replace cpumask_weight() with cpumask_empty() where appropriate

__irq_build_affinity_masks() calls cpumask_weight() to check if any bit of a given cpumask is set.

This can be done more efficiently with cpumask_empty() because cpumask_empty() stops traversing the cpumask as soon as it finds first set bit, while cpumask_weight() counts all bits unconditionally.

---
 kernel/irq/affinity.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/irq/affinity.c +1 -1
index f7ff891..18740fa 100644
@@ -258,7 +258,7 @@ static int __irq_build_affinity_masks(unsigned int startvec,
 	nodemask_t nodemsk = NODE_MASK_NONE;
 	struct node_vectors *node_vectors;
 
-	if (!cpumask_weight(cpu_mask))
+	if (cpumask_empty(cpu_mask))
 		return 0;
 
 	nodes = get_nodes_in_cpumask(node_to_cpumask, cpu_mask, &nodemsk);

A message that is not in the archive (sent off-list or not yet received): [email protected]

author maintainer
#44 lore raw

Re: [tip: irq/core] genirq/affinity: Replace cpumask_weight() with cpumask_empty() where appropriate

Quoted 19 lines · Ozgur

10.04.2022, 23:27, "tip-bot2 for Yury Norov" <[email protected]>:

The following commit has been merged into the irq/core branch of tip:

Commit-ID: 911488de0565f1d53bd36174d20917ebc4b44c0e
Gitweb: https://git.kernel.org/tip/911488de0565f1d53bd36174d20917ebc4b44c0e
Author: Yury Norov <[email protected]>
AuthorDate: Thu, 10 Feb 2022 14:49:05 -08:00
Committer: Thomas Gleixner <[email protected]>
CommitterDate: Sun, 10 Apr 2022 22:20:28 +02:00

genirq/affinity: Replace cpumask_weight() with cpumask_empty() where appropriate

__irq_build_affinity_masks() calls cpumask_weight() to check if any bit of a given cpumask is set.

Quoted 7 lines

This can be done more efficiently with cpumask_empty() because cpumask_empty() stops traversing the cpumask as soon as it finds first set bit, while cpumask_weight() counts all bits unconditionally.

Hello,
in this patch, struct cpumask *nmsk will also be affected because is called ncpus = cpumask_weight(nmsk); right?

Sorry, I don't understand that. The line that you mentioned can't modify nmsk neither before
nor after this patch. Can you clarify your concern in greater details?

Thanks,
Yury

Quoted 24 lines
---
 kernel/irq/affinity.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/irq/affinity.c +1 -1
index f7ff891..18740fa 100644
@@ -258,7 +258,7 @@ static int __irq_build_affinity_masks(unsigned int startvec,
         nodemask_t nodemsk = NODE_MASK_NONE;
         struct node_vectors *node_vectors;
 
- if (!cpumask_weight(cpu_mask))
+ if (cpumask_empty(cpu_mask))
                 return 0;
 
         nodes = get_nodes_in_cpumask(node_to_cpumask, cpu_mask, &nodemsk);

Ozgur

author maintainer
#45 lore raw

PATCH v4 22/49 sched: replace cpumask_weight with cpumask_empty where appropriate

In reply to Yury Norov

In some places, kernel/sched code calls cpumask_weight() to check if any bit of a given cpumask is set. We can do it more efficiently with cpumask_empty() because cpumask_empty() stops traversing the cpumask as soon as it finds first set bit, while cpumask_weight() counts all bits unconditionally.

---
 kernel/sched/core.c     | 2 +-
 kernel/sched/topology.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
kernel/sched/core.c +1 -1
index 28d1b7af03dc..ed7b392945b7 100644
@@ -8711,7 +8711,7 @@ int cpuset_cpumask_can_shrink(const struct cpumask *cur,
 {
 	int ret = 1;
 
-	if (!cpumask_weight(cur))
+	if (cpumask_empty(cur))
 		return ret;
 
 	ret = dl_cpuset_cpumask_can_shrink(cur, trial);
kernel/sched/topology.c +1 -1
index d201a7052a29..8478e2a8cd65 100644
@@ -74,7 +74,7 @@ static int sched_domain_debug_one(struct sched_domain *sd, int cpu, int level,
 			break;
 		}
 
-		if (!cpumask_weight(sched_group_span(group))) {
+		if (cpumask_empty(sched_group_span(group))) {
 			printk(KERN_CONT "\n");
 			printk(KERN_ERR "ERROR: empty group\n");
 			break;
Signature · 1 line
2.32.0
maintainer Acked-by on v4 22/49
#46 lore raw

Re: [PATCH 22/49] sched: replace cpumask_weight with cpumask_empty where appropriate

Quoted 7 lines · Yury Norov

In some places, kernel/sched code calls cpumask_weight() to check if any bit of a given cpumask is set. We can do it more efficiently with cpumask_empty() because cpumask_empty() stops traversing the cpumask as soon as it finds first set bit, while cpumask_weight() counts all bits unconditionally.

Neither of these paths are really performance sentitive, but whatever.

Do you want me to take this now, or do you want to merge the whole series somewere else? In which case:

Quoted 34 lines
---
 kernel/sched/core.c     | 2 +-
 kernel/sched/topology.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
kernel/sched/core.c +1 -1
index 28d1b7af03dc..ed7b392945b7 100644
@@ -8711,7 +8711,7 @@ int cpuset_cpumask_can_shrink(const struct cpumask *cur,
 {
 	int ret = 1;
 
-	if (!cpumask_weight(cur))
+	if (cpumask_empty(cur))
 		return ret;
 
 	ret = dl_cpuset_cpumask_can_shrink(cur, trial);
kernel/sched/topology.c +1 -1
index d201a7052a29..8478e2a8cd65 100644
@@ -74,7 +74,7 @@ static int sched_domain_debug_one(struct sched_domain *sd, int cpu, int level,
 			break;
 		}
 
-		if (!cpumask_weight(sched_group_span(group))) {
+		if (cpumask_empty(sched_group_span(group))) {
 			printk(KERN_CONT "\n");
 			printk(KERN_ERR "ERROR: empty group\n");
 			break;
Signature · 1 line
2.32.0
author maintainer
#47 lore raw

Re: [PATCH 22/49] sched: replace cpumask_weight with cpumask_empty where appropriate

Quoted 7 lines · Peter Zijlstra
Quoted 6 lines · Yury Norov

In some places, kernel/sched code calls cpumask_weight() to check if any bit of a given cpumask is set. We can do it more efficiently with cpumask_empty() because cpumask_empty() stops traversing the cpumask as soon as it finds first set bit, while cpumask_weight() counts all bits unconditionally.

Quoted 5 lines
Quoted 1 line

Neither of these paths are really performance sentitive, but whatever.

Do you want me to take this now,

Yes please. Many patches from this series already merged this way.

Quoted 39 lines

or do you want to merge the whole
series somewere else? In which case:

Quoted 34 lines
---
 kernel/sched/core.c     | 2 +-
 kernel/sched/topology.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
kernel/sched/core.c +1 -1
index 28d1b7af03dc..ed7b392945b7 100644
@@ -8711,7 +8711,7 @@ int cpuset_cpumask_can_shrink(const struct cpumask *cur,
 {
 	int ret = 1;
 
-	if (!cpumask_weight(cur))
+	if (cpumask_empty(cur))
 		return ret;
 
 	ret = dl_cpuset_cpumask_can_shrink(cur, trial);
kernel/sched/topology.c +1 -1
index d201a7052a29..8478e2a8cd65 100644
@@ -74,7 +74,7 @@ static int sched_domain_debug_one(struct sched_domain *sd, int cpu, int level,
 			break;
 		}
 
-		if (!cpumask_weight(sched_group_span(group))) {
+		if (cpumask_empty(sched_group_span(group))) {
 			printk(KERN_CONT "\n");
 			printk(KERN_ERR "ERROR: empty group\n");
 			break;
Signature · 1 line
2.32.0
merge bot Applied
#48 lore raw

[tip: sched/core] sched: replace cpumask_weight with cpumask_empty where appropriate

In reply to Yury Norov
The following commit has been merged into the sched/core branch of tip:

The following commit has been merged into the sched/core branch of tip:

Commit-ID:     1087ad4e3f88c474b8134a482720782922bf3fdf
Gitweb:        https://git.kernel.org/tip/1087ad4e3f88c474b8134a482720782922bf3fdf
Author:        Yury Norov <[email protected]>
AuthorDate:    Thu, 10 Feb 2022 14:49:06 -08:00
Committer:     Peter Zijlstra <[email protected]>
CommitterDate: Wed, 16 Feb 2022 15:57:53 +01:00

sched: replace cpumask_weight with cpumask_empty where appropriate

In some places, kernel/sched code calls cpumask_weight() to check if any bit of a given cpumask is set. We can do it more efficiently with cpumask_empty() because cpumask_empty() stops traversing the cpumask as soon as it finds first set bit, while cpumask_weight() counts all bits unconditionally.

---
 kernel/sched/core.c     | 2 +-
 kernel/sched/topology.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
kernel/sched/core.c +1 -1
index 1d863d7..c620aab 100644
@@ -8708,7 +8708,7 @@ int cpuset_cpumask_can_shrink(const struct cpumask *cur,
 {
 	int ret = 1;
 
-	if (!cpumask_weight(cur))
+	if (cpumask_empty(cur))
 		return ret;
 
 	ret = dl_cpuset_cpumask_can_shrink(cur, trial);
kernel/sched/topology.c +1 -1
index e6cd559..1c84b48 100644
@@ -74,7 +74,7 @@ static int sched_domain_debug_one(struct sched_domain *sd, int cpu, int level,
 			break;
 		}
 
-		if (!cpumask_weight(sched_group_span(group))) {
+		if (cpumask_empty(sched_group_span(group))) {
 			printk(KERN_CONT "\n");
 			printk(KERN_ERR "ERROR: empty group\n");
 			break;
author maintainer
#49 lore raw

PATCH v4 23/49 clocksource: replace cpumask_weight with cpumask_empty in clocksource.c

In reply to Yury Norov

clocksource_verify_percpu() calls cpumask_weight() to check if any bit of a given cpumask is set. We can do it more efficiently with cpumask_empty() because cpumask_empty() stops traversing the cpumask as soon as it finds first set bit, while cpumask_weight() counts all bits unconditionally.

---
 kernel/time/clocksource.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/time/clocksource.c +1 -1
index 95d7ca35bdf2..cee5da1e54c4 100644
@@ -343,7 +343,7 @@ void clocksource_verify_percpu(struct clocksource *cs)
 	cpus_read_lock();
 	preempt_disable();
 	clocksource_verify_choose_cpus();
-	if (cpumask_weight(&cpus_chosen) == 0) {
+	if (cpumask_empty(&cpus_chosen)) {
 		preempt_enable();
 		cpus_read_unlock();
 		pr_warn("Not enough CPUs to check clocksource '%s'.\n", cs->name);
Signature · 1 line
2.32.0
merge bot Applied
#50 lore raw

[tip: timers/core] clocksource: Replace cpumask_weight() with cpumask_empty()

The following commit has been merged into the timers/core branch of tip:

The following commit has been merged into the timers/core branch of tip:

Commit-ID:     8afbcaf8690dac19ebf570a4e4fef9c59c75bf8e
Gitweb:        https://git.kernel.org/tip/8afbcaf8690dac19ebf570a4e4fef9c59c75bf8e
Author:        Yury Norov <[email protected]>
AuthorDate:    Thu, 10 Feb 2022 14:49:07 -08:00
Committer:     Thomas Gleixner <[email protected]>
CommitterDate: Sun, 10 Apr 2022 22:30:04 +02:00

clocksource: Replace cpumask_weight() with cpumask_empty()

clocksource_verify_percpu() calls cpumask_weight() to check if any bit of a given cpumask is set.

This can be done more efficiently with cpumask_empty() because cpumask_empty() stops traversing the cpumask as soon as it finds first set bit, while cpumask_weight() counts all bits unconditionally.

---
 kernel/time/clocksource.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/time/clocksource.c +1 -1
index 95d7ca3..cee5da1 100644
@@ -343,7 +343,7 @@ void clocksource_verify_percpu(struct clocksource *cs)
 	cpus_read_lock();
 	preempt_disable();
 	clocksource_verify_choose_cpus();
-	if (cpumask_weight(&cpus_chosen) == 0) {
+	if (cpumask_empty(&cpus_chosen)) {
 		preempt_enable();
 		cpus_read_unlock();
 		pr_warn("Not enough CPUs to check clocksource '%s'.\n", cs->name);
author maintainer
#51 lore raw

PATCH v4 24/49 mm/vmstat: replace cpumask_weight with cpumask_empty where appropriate

In reply to Yury Norov

mm/vmstat.c code calls cpumask_weight() to check if any bit of a given cpumask is set. We can do it more efficiently with cpumask_empty() because cpumask_empty() stops traversing the cpumask as soon as it finds first set bit, while cpumask_weight() counts all bits unconditionally.

---
 mm/vmstat.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
mm/vmstat.c +2 -2
index d5cc8d739fac..27a94afd4ee5 100644
@@ -2041,7 +2041,7 @@ static void __init init_cpu_node_state(void)
 	int node;
 
 	for_each_online_node(node) {
-		if (cpumask_weight(cpumask_of_node(node)) > 0)
+		if (!cpumask_empty(cpumask_of_node(node)))
 			node_set_state(node, N_CPU);
 	}
 }
@@ -2068,7 +2068,7 @@ static int vmstat_cpu_dead(unsigned int cpu)
 
 	refresh_zone_stat_thresholds();
 	node_cpus = cpumask_of_node(node);
-	if (cpumask_weight(node_cpus) > 0)
+	if (!cpumask_empty(node_cpus))
 		return 0;
 
 	node_clear_state(node, N_CPU);
Signature · 1 line
2.32.0
reviewer Acked-by on v4 24/49
#52 lore raw

Re: [PATCH 24/49] mm/vmstat: replace cpumask_weight with cpumask_empty where appropriate

Quoted 6 lines · Yury Norov

mm/vmstat.c code calls cpumask_weight() to check if any bit of a given cpumask is set. We can do it more efficiently with cpumask_empty() because cpumask_empty() stops traversing the cpumask as soon as it finds first set bit, while cpumask_weight() counts all bits unconditionally.

Quoted 30 lines
---
 mm/vmstat.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
mm/vmstat.c +2 -2
index d5cc8d739fac..27a94afd4ee5 100644
@@ -2041,7 +2041,7 @@ static void __init init_cpu_node_state(void)
 	int node;
 
 	for_each_online_node(node) {
-		if (cpumask_weight(cpumask_of_node(node)) > 0)
+		if (!cpumask_empty(cpumask_of_node(node)))
 			node_set_state(node, N_CPU);
 	}
 }
@@ -2068,7 +2068,7 @@ static int vmstat_cpu_dead(unsigned int cpu)
 
 	refresh_zone_stat_thresholds();
 	node_cpus = cpumask_of_node(node);
-	if (cpumask_weight(node_cpus) > 0)
+	if (!cpumask_empty(node_cpus))
 		return 0;
 
 	node_clear_state(node, N_CPU);
Signature · 1 line
2.32.0
Signature · 2 lines
Sincerely yours,
Mike.
author maintainer
#53 lore raw

PATCH v4 25/49 arch/x86: replace nodes_weight with nodes_empty where appropriate

In reply to Yury Norov

mm code calls nodes_weight() to check if any bit of a given nodemask is set. We can do it more efficiently with nodes_empty() because nodes_empty() stops traversing the nodemask as soon as it finds first set bit, while nodes_weight() counts all bits unconditionally.

---
 arch/x86/mm/amdtopology.c    | 2 +-
 arch/x86/mm/numa_emulation.c | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)
arch/x86/mm/amdtopology.c +1 -1
index 058b2f36b3a6..b3ca7d23e4b0 100644
@@ -154,7 +154,7 @@ int __init amd_numa_init(void)
 		node_set(nodeid, numa_nodes_parsed);
 	}
 
-	if (!nodes_weight(numa_nodes_parsed))
+	if (nodes_empty(numa_nodes_parsed))
 		return -ENOENT;
 
 	/*
arch/x86/mm/numa_emulation.c +2 -2
index 1a02b791d273..9a9305367fdd 100644
@@ -123,7 +123,7 @@ static int __init split_nodes_interleave(struct numa_meminfo *ei,
 	 * Continue to fill physical nodes with fake nodes until there is no
 	 * memory left on any of them.
 	 */
-	while (nodes_weight(physnode_mask)) {
+	while (!nodes_empty(physnode_mask)) {
 		for_each_node_mask(i, physnode_mask) {
 			u64 dma32_end = PFN_PHYS(MAX_DMA32_PFN);
 			u64 start, limit, end;
@@ -270,7 +270,7 @@ static int __init split_nodes_size_interleave_uniform(struct numa_meminfo *ei,
 	 * Fill physical nodes with fake nodes of size until there is no memory
 	 * left on any of them.
 	 */
-	while (nodes_weight(physnode_mask)) {
+	while (!nodes_empty(physnode_mask)) {
 		for_each_node_mask(i, physnode_mask) {
 			u64 dma32_end = PFN_PHYS(MAX_DMA32_PFN);
 			u64 start, limit, end;
Signature · 1 line
2.32.0
merge bot Applied
#54 lore raw

[tip: x86/cleanups] x86/mm: Replace nodes_weight() with nodes_empty() where appropriate

The following commit has been merged into the x86/cleanups branch of tip:

The following commit has been merged into the x86/cleanups branch of tip:

Commit-ID:     c2a911d302b0d014a4d0d732a2bfc319e643eb62
Gitweb:        https://git.kernel.org/tip/c2a911d302b0d014a4d0d732a2bfc319e643eb62
Author:        Yury Norov <[email protected]>
AuthorDate:    Thu, 10 Feb 2022 14:49:09 -08:00
Committer:     Thomas Gleixner <[email protected]>
CommitterDate: Sun, 10 Apr 2022 22:35:38 +02:00

x86/mm: Replace nodes_weight() with nodes_empty() where appropriate

Various mm code calls nodes_weight() to check if any bit of a given nodemask is set.

This can be done more efficiently with nodes_empty() because nodes_empty() stops traversing the nodemask as soon as it finds first set bit, while nodes_weight() counts all bits unconditionally.

---
 arch/x86/mm/amdtopology.c    | 2 +-
 arch/x86/mm/numa_emulation.c | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)
arch/x86/mm/amdtopology.c +1 -1
index 058b2f3..b3ca7d2 100644
@@ -154,7 +154,7 @@ int __init amd_numa_init(void)
 		node_set(nodeid, numa_nodes_parsed);
 	}
 
-	if (!nodes_weight(numa_nodes_parsed))
+	if (nodes_empty(numa_nodes_parsed))
 		return -ENOENT;
 
 	/*
arch/x86/mm/numa_emulation.c +2 -2
index 1a02b79..9a93053 100644
@@ -123,7 +123,7 @@ static int __init split_nodes_interleave(struct numa_meminfo *ei,
 	 * Continue to fill physical nodes with fake nodes until there is no
 	 * memory left on any of them.
 	 */
-	while (nodes_weight(physnode_mask)) {
+	while (!nodes_empty(physnode_mask)) {
 		for_each_node_mask(i, physnode_mask) {
 			u64 dma32_end = PFN_PHYS(MAX_DMA32_PFN);
 			u64 start, limit, end;
@@ -270,7 +270,7 @@ static int __init split_nodes_size_interleave_uniform(struct numa_meminfo *ei,
 	 * Fill physical nodes with fake nodes of size until there is no memory
 	 * left on any of them.
 	 */
-	while (nodes_weight(physnode_mask)) {
+	while (!nodes_empty(physnode_mask)) {
 		for_each_node_mask(i, physnode_mask) {
 			u64 dma32_end = PFN_PHYS(MAX_DMA32_PFN);
 			u64 start, limit, end;
author maintainer
#55 lore raw

PATCH v4 26/49 bitmap: add bitmap_weight_{cmp, eq, gt, ge, lt, le} functions

In reply to Yury Norov

Many kernel users use bitmap_weight() to compare the result against some number or expression:

	if (bitmap_weight(...) > 1)
		do_something();

It works OK, but may be significantly improved for large bitmaps: if first few words count set bits to a number greater than given, we can stop counting and immediately return.

The same idea would work in other direction: if we know that the number of set bits that we counted so far is small enough, so that it would be smaller than required number even if all bits of the rest of the bitmap are set, we can stop counting earlier.

This patch adds new bitmap_weight_cmp() as suggested by Michał Mirosław and a family of eq, gt, ge, lt, and le wrappers to allow this optimization. The following patches apply new functions where appropriate.

---
 include/linux/bitmap.h | 78 ++++++++++++++++++++++++++++++++++++++++++
 lib/bitmap.c           | 21 ++++++++++++
 2 files changed, 99 insertions(+)
include/linux/bitmap.h +78 -0
index 7dba0847510c..a89b626d0fbe 100644
@@ -51,6 +51,12 @@ struct device;
  *  bitmap_empty(src, nbits)                    Are all bits zero in *src?
  *  bitmap_full(src, nbits)                     Are all bits set in *src?
  *  bitmap_weight(src, nbits)                   Hamming Weight: number set bits
+ *  bitmap_weight_cmp(src, nbits)               compare Hamming Weight with a number
+ *  bitmap_weight_eq(src, nbits, num)           Hamming Weight == num
+ *  bitmap_weight_gt(src, nbits, num)           Hamming Weight >  num
+ *  bitmap_weight_ge(src, nbits, num)           Hamming Weight >= num
+ *  bitmap_weight_lt(src, nbits, num)           Hamming Weight <  num
+ *  bitmap_weight_le(src, nbits, num)           Hamming Weight <= num
  *  bitmap_set(dst, pos, nbits)                 Set specified bit area
  *  bitmap_clear(dst, pos, nbits)               Clear specified bit area
  *  bitmap_find_next_zero_area(buf, len, pos, n, mask)  Find bit free area
@@ -162,6 +168,7 @@ int __bitmap_intersects(const unsigned long *bitmap1,
 int __bitmap_subset(const unsigned long *bitmap1,
 		    const unsigned long *bitmap2, unsigned int nbits);
 int __bitmap_weight(const unsigned long *bitmap, unsigned int nbits);
+int __bitmap_weight_cmp(const unsigned long *bitmap, unsigned int bits, int num);
 void __bitmap_set(unsigned long *map, unsigned int start, int len);
 void __bitmap_clear(unsigned long *map, unsigned int start, int len);
 
@@ -403,6 +410,77 @@ static __always_inline int bitmap_weight(const unsigned long *src, unsigned int
 	return __bitmap_weight(src, nbits);
 }
 
+/**
+ * bitmap_weight_cmp - compares number of set bits in @src with @num.
+ * @src:   source bitmap
+ * @nbits: length of bitmap in bits
+ * @num:   number to compare with
+ *
+ * As opposite to bitmap_weight() this function doesn't necessarily
+ * traverse full bitmap and may return earlier.
+ *
+ * Because number of set bits cannot decrease while counting, when user
+ * wants to know if the number of set bits in the bitmap is less than
+ * @num, calling
+ *	bitmap_weight_cmp(..., @num) < 0
+ * is potentially less effective than
+ *	bitmap_weight_cmp(..., @num - 1) <= 0
+ *
+ * Consider an example:
+ * bitmap_weight_cmp(1000 0000 0000 0000, 1) < 0
+ *				    ^
+ *				    stop here
+ *
+ * bitmap_weight_cmp(1000 0000 0000 0000, 0) <= 0
+ *		     ^
+ *		     stop here
+ *
+ * Returns: zero if weight of @src is equal to @num;
+ *	   negative number if weight of @src is less than @num;
+ *	   positive number if weight of @src is greater than @num.
+ */
+static __always_inline
+int bitmap_weight_cmp(const unsigned long *src, unsigned int nbits, int num)
+{
+	if ((unsigned int)num > nbits)
+		return -num;
+
+	if (small_const_nbits(nbits))
+		return hweight_long(*src & BITMAP_LAST_WORD_MASK(nbits)) - num;
+
+	return __bitmap_weight_cmp(src, nbits, num);
+}
+
+static __always_inline
+bool bitmap_weight_eq(const unsigned long *src, unsigned int nbits, int num)
+{
+	return bitmap_weight_cmp(src, nbits, num) == 0;
+}
+
+static __always_inline
+bool bitmap_weight_gt(const unsigned long *src, unsigned int nbits, int num)
+{
+	return bitmap_weight_cmp(src, nbits, num) > 0;
+}
+
+static __always_inline
+bool bitmap_weight_ge(const unsigned long *src, unsigned int nbits, int num)
+{
+	return bitmap_weight_cmp(src, nbits, num - 1) > 0;
+}
+
+static __always_inline
+bool bitmap_weight_lt(const unsigned long *src, unsigned int nbits, int num)
+{
+	return bitmap_weight_cmp(src, nbits, num - 1) <= 0;
+}
+
+static __always_inline
+bool bitmap_weight_le(const unsigned long *src, unsigned int nbits, int num)
+{
+	return bitmap_weight_cmp(src, nbits, num) <= 0;
+}
+
 static __always_inline void bitmap_set(unsigned long *map, unsigned int start,
 		unsigned int nbits)
 {
lib/bitmap.c +21 -0
index 926408883456..fb84ca70c5d9 100644
@@ -348,6 +348,27 @@ int __bitmap_weight(const unsigned long *bitmap, unsigned int bits)
 }
 EXPORT_SYMBOL(__bitmap_weight);
 
+int __bitmap_weight_cmp(const unsigned long *bitmap, unsigned int bits, int num)
+{
+	unsigned int k, w, lim = bits / BITS_PER_LONG;
+
+	for (k = 0, w = 0; k < lim; k++) {
+		if (w + bits - k * BITS_PER_LONG < num)
+			goto out;
+
+		w += hweight_long(bitmap[k]);
+
+		if (w > num)
+			goto out;
+	}
+
+	if (bits % BITS_PER_LONG)
+		w += hweight_long(bitmap[k] & BITMAP_LAST_WORD_MASK(bits));
+out:
+	return w - num;
+}
+EXPORT_SYMBOL(__bitmap_weight_cmp);
+
 void __bitmap_set(unsigned long *map, unsigned int start, int len)
 {
 	unsigned long *p = map + BIT_WORD(start);
Signature · 1 line
2.32.0
author maintainer
#56 lore raw

PATCH v4 27/49 arch/x86: replace bitmap_weight with bitmap_weight_{eq,gt,ge,lt,le} where appropriate

In reply to Yury Norov

__init_one_rdt_domain in rdtgroup.c code calls bitmap_weight() to compare the weight of bitmap with a given number. We can do it more efficiently with bitmap_weight_lt because conditional bitmap_weight() may stop traversing the bitmap earlier, as soon as condition is (or can't be) met.

---
 arch/x86/kernel/cpu/resctrl/rdtgroup.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/kernel/cpu/resctrl/rdtgroup.c +1 -1
index e23ff03290b8..9d42e592c1cf 100644
@@ -2752,7 +2752,7 @@ static int __init_one_rdt_domain(struct rdt_domain *d, struct resctrl_schema *s,
 	 * bitmap_weight() does not access out-of-bound memory.
 	 */
 	tmp_cbm = cfg->new_ctrl;
-	if (bitmap_weight(&tmp_cbm, r->cache.cbm_len) < r->cache.min_cbm_bits) {
+	if (bitmap_weight_lt(&tmp_cbm, r->cache.cbm_len, r->cache.min_cbm_bits)) {
 		rdt_last_cmd_printf("No space on %s:%d\n", s->name, d->id);
 		return -ENOSPC;
 	}
Signature · 1 line
2.32.0
author maintainer
#57 lore raw

PATCH v4 28/49 iio: replace bitmap_weight() with bitmap_weight_{eq,gt} where appropriate

In reply to Yury Norov

drivers/iio calls bitmap_weight() to compare the weight of bitmap with a given number. We can do it more efficiently with bitmap_weight_eq because conditional bitmap_weight may stop traversing the bitmap earlier, as soon as condition is (or can't be) met.

---
 drivers/iio/industrialio-trigger.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/iio/industrialio-trigger.c +1 -1
index f504ed351b3e..98c54022fecf 100644
@@ -331,7 +331,7 @@ int iio_trigger_detach_poll_func(struct iio_trigger *trig,
 {
 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(pf->indio_dev);
 	bool no_other_users =
-		bitmap_weight(trig->pool, CONFIG_IIO_CONSUMERS_PER_TRIGGER) == 1;
+		bitmap_weight_eq(trig->pool, CONFIG_IIO_CONSUMERS_PER_TRIGGER, 1);
 	int ret = 0;
 
 	if (trig->ops && trig->ops->set_trigger_state && no_other_users) {
Signature · 1 line
2.32.0
author maintainer
#58 lore raw

PATCH v4 29/49 memstick: replace bitmap_weight with bitmap_weight_eq where appropriate

In reply to Yury Norov

msb_validate_used_block_bitmap() calls bitmap_weight() to compare the weight of bitmap with a given number. We can do it more efficiently with bitmap_weight_eq because conditional bitmap_weight may stop traversing the bitmap earlier, as soon as condition is (or can't be) met.

---
 drivers/memstick/core/ms_block.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/memstick/core/ms_block.c +2 -2
index 0cda6c6baefc..5cdd987e78f7 100644
@@ -155,8 +155,8 @@ static int msb_validate_used_block_bitmap(struct msb_data *msb)
 	for (i = 0; i < msb->zone_count; i++)
 		total_free_blocks += msb->free_block_count[i];
 
-	if (msb->block_count - bitmap_weight(msb->used_blocks_bitmap,
-					msb->block_count) == total_free_blocks)
+	if (bitmap_weight_eq(msb->used_blocks_bitmap, msb->block_count,
+				msb->block_count - total_free_blocks))
 		return 0;
 
 	pr_err("BUG: free block counts don't match the bitmap");
Signature · 1 line
2.32.0
#59 lore raw

Re: [PATCH 29/49] memstick: replace bitmap_weight with bitmap_weight_eq where appropriate

Quoted 9 lines · Yury Norov

msb_validate_used_block_bitmap() calls bitmap_weight() to compare the weight of bitmap with a given number. We can do it more efficiently with bitmap_weight_eq because conditional bitmap_weight may stop traversing the bitmap earlier, as soon as condition is (or can't be) met.

Applied for next, thanks!

Kind regards
Uffe

Quoted 22 lines
---
 drivers/memstick/core/ms_block.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/memstick/core/ms_block.c +2 -3
index 0cda6c6baefc..5cdd987e78f7 100644
@@ -155,8 +155,8 @@ static int msb_validate_used_block_bitmap(struct msb_data *msb)
        for (i = 0; i < msb->zone_count; i++)
                total_free_blocks += msb->free_block_count[i];
 
-       if (msb->block_count - bitmap_weight(msb->used_blocks_bitmap,
-                                       msb->block_count) == total_free_blocks)
+       if (bitmap_weight_eq(msb->used_blocks_bitmap, msb->block_count,
+                               msb->block_count - total_free_blocks))
                return 0;
 
        pr_err("BUG: free block counts don't match the bitmap");
--

2.32.0

author maintainer
#60 lore raw

Re: [PATCH 29/49] memstick: replace bitmap_weight with bitmap_weight_eq where appropriate

Quoted 8 lines · Ulf Hansson
Quoted 6 lines · Yury Norov

msb_validate_used_block_bitmap() calls bitmap_weight() to compare the weight of bitmap with a given number. We can do it more efficiently with bitmap_weight_eq because conditional bitmap_weight may stop traversing the bitmap earlier, as soon as condition is (or can't be) met.

Quoted 5 lines
Quoted 3 lines

Applied for next, thanks!

Hi Ulf,

This patch depends on patch 26/49 "bitmap: add bitmap_weight_{cmp, eq, gt, ge, lt, le} functions"
from this series. Can you make sure you applied them together? Or I can apply it later.

Thanks,
Yury

#61 lore raw

Re: [PATCH 29/49] memstick: replace bitmap_weight with bitmap_weight_eq where appropriate

Quoted 14 lines · Yury Norov
Quoted 12 lines · Ulf Hansson
Quoted 9 lines · Yury Norov

msb_validate_used_block_bitmap() calls bitmap_weight() to compare the weight of bitmap with a given number. We can do it more efficiently with bitmap_weight_eq because conditional bitmap_weight may stop traversing the bitmap earlier, as soon as condition is (or can't be) met.

Quoted 8 lines
Quoted 1 line

Applied for next, thanks!

Hi Ulf,

This patch depends on patch 26/49 "bitmap: add bitmap_weight_{cmp, eq, gt, ge, lt, le} functions"
from this series. Can you make sure you applied them together? Or I can apply it later.

I can't apply them, unless there is an immutable branch being shared between the different trees.

Therefore I have dropped the patch for now.

Kind regards
Uffe

author maintainer
#62 lore raw

PATCH v4 30/49 ixgbe: replace bitmap_weight with bitmap_weight_eq

In reply to Yury Norov

ixgbe_disable_sriov calls bitmap_weight() to compare the weight of bitmap with a given number. We can do it more efficiently with bitmap_weight_eq because conditional bitmap_weight may stop traversing the bitmap earlier, as soon as condition is (or can't be) met.

---
 drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c +1 -1
index 214a38de3f41..35297d8a488b 100644
@@ -246,7 +246,7 @@ int ixgbe_disable_sriov(struct ixgbe_adapter *adapter)
 #endif
 
 	/* Disable VMDq flag so device will be set in VM mode */
-	if (bitmap_weight(adapter->fwd_bitmask, adapter->num_rx_pools) == 1) {
+	if (bitmap_weight_eq(adapter->fwd_bitmask, adapter->num_rx_pools, 1)) {
 		adapter->flags &= ~IXGBE_FLAG_VMDQ_ENABLED;
 		adapter->flags &= ~IXGBE_FLAG_SRIOV_ENABLED;
 		rss = min_t(int, ixgbe_max_rss_indices(adapter),
Signature · 1 line
2.32.0
author maintainer
#63 lore raw

PATCH v4 31/49 octeontx2-pf: replace bitmap_weight with bitmap_weight_{eq,gt}

In reply to Yury Norov

OcteonTX2 code calls bitmap_weight() to compare the weight of bitmap with a given number. We can do it more efficiently with bitmap_weight_{eq,gt} because conditional bitmap_weight may stop traversing the bitmap earlier, as soon as condition is (or can't be) met.

---
 drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c | 2 +-
 drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c   | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)
drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c +1 -1
index abe5267210ef..152890066c2a 100644
@@ -287,7 +287,7 @@ static int otx2_set_channels(struct net_device *dev,
 	if (!channel->rx_count || !channel->tx_count)
 		return -EINVAL;
 
-	if (bitmap_weight(&pfvf->rq_bmap, pfvf->hw.rx_queues) > 1) {
+	if (bitmap_weight_gt(&pfvf->rq_bmap, pfvf->hw.rx_queues, 1)) {
 		netdev_err(dev,
 			   "Receive queues are in use by TC police action\n");
 		return -EINVAL;
drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c +2 -2
index 80b2d64b4136..55c899a6fcdd 100644
@@ -1170,8 +1170,8 @@ int otx2_remove_flow(struct otx2_nic *pfvf, u32 location)
 		 * interface mac address and configure CGX/RPM block in
 		 * promiscuous mode
 		 */
-		if (bitmap_weight(&flow_cfg->dmacflt_bmap,
-				  flow_cfg->dmacflt_max_flows) == 1)
+		if (bitmap_weight_eq(&flow_cfg->dmacflt_bmap,
+				     flow_cfg->dmacflt_max_flows, 1))
 			otx2_update_rem_pfmac(pfvf, DMAC_ADDR_DEL);
 	} else {
 		err = otx2_remove_flow_msg(pfvf, flow->entry, false);
Signature · 1 line
2.32.0
author maintainer
#64 lore raw

PATCH v4 32/49 mlx4: replace bitmap_weight with bitmap_weight_{eq,gt,ge,lt,le}

In reply to Yury Norov

Mellanox code uses bitmap_weight() to compare the weight of bitmap with a given number. We can do it more efficiently with bitmap_weight_{eq, ...} because conditional bitmap_weight may stop traversing the bitmap earlier, as soon as condition is (or can't be) met.

---
 drivers/net/ethernet/mellanox/mlx4/cmd.c  | 10 +++-------
 drivers/net/ethernet/mellanox/mlx4/eq.c   |  4 ++--
 drivers/net/ethernet/mellanox/mlx4/fw.c   |  4 ++--
 drivers/net/ethernet/mellanox/mlx4/main.c |  2 +-
 4 files changed, 8 insertions(+), 12 deletions(-)
drivers/net/ethernet/mellanox/mlx4/cmd.c +3 -7
index c56d2194cbfc..5bca0c68f00a 100644
@@ -2792,9 +2792,8 @@ int mlx4_slave_convert_port(struct mlx4_dev *dev, int slave, int port)
 {
 	unsigned n;
 	struct mlx4_active_ports actv_ports = mlx4_get_active_ports(dev, slave);
-	unsigned m = bitmap_weight(actv_ports.ports, dev->caps.num_ports);
 
-	if (port <= 0 || port > m)
+	if (port <= 0 || bitmap_weight_lt(actv_ports.ports, dev->caps.num_ports, port))
 		return -EINVAL;
 
 	n = find_first_bit(actv_ports.ports, dev->caps.num_ports);
@@ -3404,10 +3403,6 @@ int mlx4_vf_set_enable_smi_admin(struct mlx4_dev *dev, int slave, int port,
 	struct mlx4_priv *priv = mlx4_priv(dev);
 	struct mlx4_active_ports actv_ports = mlx4_get_active_ports(
 			&priv->dev, slave);
-	int min_port = find_first_bit(actv_ports.ports,
-				      priv->dev.caps.num_ports) + 1;
-	int max_port = min_port - 1 +
-		bitmap_weight(actv_ports.ports, priv->dev.caps.num_ports);
 
 	if (slave == mlx4_master_func_num(dev))
 		return 0;
@@ -3417,7 +3412,8 @@ int mlx4_vf_set_enable_smi_admin(struct mlx4_dev *dev, int slave, int port,
 	    enabled < 0 || enabled > 1)
 		return -EINVAL;
 
-	if (min_port == max_port && dev->caps.num_ports > 1) {
+	if (dev->caps.num_ports > 1 &&
+	    bitmap_weight_eq(actv_ports.ports, priv->dev.caps.num_ports, 1)) {
 		mlx4_info(dev, "SMI access disallowed for single ported VFs\n");
 		return -EPROTONOSUPPORT;
 	}
drivers/net/ethernet/mellanox/mlx4/eq.c +2 -2
index 414e390e6b48..0c09432ff389 100644
@@ -1435,8 +1435,8 @@ int mlx4_is_eq_shared(struct mlx4_dev *dev, int vector)
 	if (vector <= 0 || (vector >= dev->caps.num_comp_vectors + 1))
 		return -EINVAL;
 
-	return !!(bitmap_weight(priv->eq_table.eq[vector].actv_ports.ports,
-				dev->caps.num_ports) > 1);
+	return bitmap_weight_gt(priv->eq_table.eq[vector].actv_ports.ports,
+				dev->caps.num_ports, 1);
 }
 EXPORT_SYMBOL(mlx4_is_eq_shared);
 
drivers/net/ethernet/mellanox/mlx4/fw.c +2 -2
index 42c96c9d7fb1..855aae326ccb 100644
@@ -1300,8 +1300,8 @@ int mlx4_QUERY_DEV_CAP_wrapper(struct mlx4_dev *dev, int slave,
 	actv_ports = mlx4_get_active_ports(dev, slave);
 	first_port = find_first_bit(actv_ports.ports, dev->caps.num_ports);
 	for (slave_port = 0, real_port = first_port;
-	     real_port < first_port +
-	     bitmap_weight(actv_ports.ports, dev->caps.num_ports);
+	     bitmap_weight_gt(actv_ports.ports, dev->caps.num_ports,
+			      real_port - first_port);
 	     ++real_port, ++slave_port) {
 		if (flags & (MLX4_DEV_CAP_FLAG_WOL_PORT1 << real_port))
 			flags |= MLX4_DEV_CAP_FLAG_WOL_PORT1 << slave_port;
drivers/net/ethernet/mellanox/mlx4/main.c +1 -1
index b187c210d4d6..cfbaa7ac712f 100644
@@ -1383,7 +1383,7 @@ static int mlx4_mf_bond(struct mlx4_dev *dev)
 		   dev->persist->num_vfs + 1);
 
 	/* only single port vfs are allowed */
-	if (bitmap_weight(slaves_port_1_2, dev->persist->num_vfs + 1) > 1) {
+	if (bitmap_weight_gt(slaves_port_1_2, dev->persist->num_vfs + 1, 1)) {
 		mlx4_warn(dev, "HA mode unsupported for dual ported VFs\n");
 		return -EINVAL;
 	}
Signature · 1 line
2.32.0
author maintainer
#65 lore raw

PATCH v4 33/49 perf: replace bitmap_weight with bitmap_weight_eq for ThunderX2

In reply to Yury Norov

tx2_uncore_event_start() calls bitmap_weight() to compare the weight of bitmap with a given number. We can do it more efficiently with bitmap_weight_eq because conditional bitmap_weight may stop traversing the bitmap earlier, as soon as condition is (or can't be) met.

---
 drivers/perf/thunderx2_pmu.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/perf/thunderx2_pmu.c +2 -2
index 1edb9c03704f..97d5b39778fa 100644
@@ -623,8 +623,8 @@ static void tx2_uncore_event_start(struct perf_event *event, int flags)
 		return;
 
 	/* Start timer for first event */
-	if (bitmap_weight(tx2_pmu->active_counters,
-				tx2_pmu->max_counters) == 1) {
+	if (bitmap_weight_eq(tx2_pmu->active_counters,
+				tx2_pmu->max_counters, 1)) {
 		hrtimer_start(&tx2_pmu->hrtimer,
 			ns_to_ktime(tx2_pmu->hrtimer_interval),
 			HRTIMER_MODE_REL_PINNED);
Signature · 1 line
2.32.0
maintainer Acked-by on v4 33/49
#66 lore raw

Re: [PATCH 33/49] perf: replace bitmap_weight with bitmap_weight_eq for ThunderX2

Quoted 6 lines · Yury Norov

tx2_uncore_event_start() calls bitmap_weight() to compare the weight of bitmap with a given number. We can do it more efficiently with bitmap_weight_eq because conditional bitmap_weight may stop traversing the bitmap earlier, as soon as condition is (or can't be) met.

Given the max counters value is either 4 or 8 I doubt this should matter, but for consistenct this is fine, so:

I now see bitmap_weight_eq() is introduced within this series, so I assume you need to queue that and its users together, and will want to take the prior drivers/perf/ bit together with that.

Thanks,
Mark.

Quoted 22 lines
---
 drivers/perf/thunderx2_pmu.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/perf/thunderx2_pmu.c +2 -2
index 1edb9c03704f..97d5b39778fa 100644
@@ -623,8 +623,8 @@ static void tx2_uncore_event_start(struct perf_event *event, int flags)
 		return;
 
 	/* Start timer for first event */
-	if (bitmap_weight(tx2_pmu->active_counters,
-				tx2_pmu->max_counters) == 1) {
+	if (bitmap_weight_eq(tx2_pmu->active_counters,
+				tx2_pmu->max_counters, 1)) {
 		hrtimer_start(&tx2_pmu->hrtimer,
 			ns_to_ktime(tx2_pmu->hrtimer_interval),
 			HRTIMER_MODE_REL_PINNED);
Signature · 1 line
2.32.0
author maintainer
#67 lore raw

PATCH v4 34/49 media: tegra-video: replace bitmap_weight with bitmap_weight_le

In reply to Yury Norov

tegra_channel_enum_format() calls bitmap_weight() to compare the weight of bitmap with a given number. We can do it more efficiently with bitmap_weight_le() because conditional bitmap_weight may stop traversing the bitmap earlier, as soon as condition is (or can't be) met.

---
 drivers/staging/media/tegra-video/vi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/staging/media/tegra-video/vi.c +1 -1
index d1f43f465c22..4e79a80e9307 100644
@@ -436,7 +436,7 @@ static int tegra_channel_enum_format(struct file *file, void *fh,
 	if (!IS_ENABLED(CONFIG_VIDEO_TEGRA_TPG))
 		fmts_bitmap = chan->fmts_bitmap;
 
-	if (f->index >= bitmap_weight(fmts_bitmap, MAX_FORMAT_NUM))
+	if (bitmap_weight_le(fmts_bitmap, MAX_FORMAT_NUM, f->index))
 		return -EINVAL;
 
 	for (i = 0; i < f->index + 1; i++, index++)
Signature · 1 line
2.32.0
Acked-by on v4 34/49
#68 lore raw

Re: [PATCH 34/49] media: tegra-video: replace bitmap_weight with bitmap_weight_le

Quoted 6 lines · Yury Norov

tegra_channel_enum_format() calls bitmap_weight() to compare the weight of bitmap with a given number. We can do it more efficiently with bitmap_weight_le() because conditional bitmap_weight may stop traversing the bitmap earlier, as soon as condition is (or can't be) met.

Regards,

Hans

Quoted 17 lines
---
 drivers/staging/media/tegra-video/vi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/staging/media/tegra-video/vi.c +1 -1
index d1f43f465c22..4e79a80e9307 100644
@@ -436,7 +436,7 @@ static int tegra_channel_enum_format(struct file *file, void *fh,
 	if (!IS_ENABLED(CONFIG_VIDEO_TEGRA_TPG))
 		fmts_bitmap = chan->fmts_bitmap;
 
-	if (f->index >= bitmap_weight(fmts_bitmap, MAX_FORMAT_NUM))
+	if (bitmap_weight_le(fmts_bitmap, MAX_FORMAT_NUM, f->index))
 		return -EINVAL;
 
 	for (i = 0; i < f->index + 1; i++, index++)
author maintainer
#69 lore raw

PATCH v4 35/49 cpumask: add cpumask_weight_{eq,gt,ge,lt,le}

In reply to Yury Norov

In many cases people use cpumask_weight() to compare the result against some number or expression:

	if (cpumask_weight(...) > 1)
		do_something();

It may be significantly improved for large cpumasks: if first few words count set bits to a number greater than given, we can stop counting and immediately return.

The same idea would work in other direction: if we know that the number of set bits that we counted so far is small enough, so that it would be smaller than required number even if all bits of the rest of the cpumask are set, we can stop counting earlier.

This patch adds cpumask_weight_{eq, gt, ge, lt, le} helpers based on corresponding bitmap functions. The following patches apply new functions where appropriate.

---
 include/linux/cpumask.h | 50 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 50 insertions(+)
include/linux/cpumask.h +50 -0
index 6b06c698cd2a..0037297c542a 100644
@@ -575,6 +575,56 @@ static inline unsigned int cpumask_weight(const struct cpumask *srcp)
 	return bitmap_weight(cpumask_bits(srcp), nr_cpumask_bits);
 }
 
+/**
+ * cpumask_weight_eq - Check if # of bits in *srcp is equal to a given number
+ * @srcp: the cpumask to count bits (< nr_cpu_ids) in.
+ * @num: the number to check.
+ */
+static inline bool cpumask_weight_eq(const struct cpumask *srcp, unsigned int num)
+{
+	return bitmap_weight_eq(cpumask_bits(srcp), nr_cpumask_bits, num);
+}
+
+/**
+ * cpumask_weight_gt - Check if # of bits in *srcp is greater than a given number
+ * @srcp: the cpumask to count bits (< nr_cpu_ids) in.
+ * @num: the number to check.
+ */
+static inline bool cpumask_weight_gt(const struct cpumask *srcp, int num)
+{
+	return bitmap_weight_gt(cpumask_bits(srcp), nr_cpumask_bits, num);
+}
+
+/**
+ * cpumask_weight_ge - Check if # of bits in *srcp is greater than or equal to a given number
+ * @srcp: the cpumask to count bits (< nr_cpu_ids) in.
+ * @num: the number to check.
+ */
+static inline bool cpumask_weight_ge(const struct cpumask *srcp, int num)
+{
+	return bitmap_weight_ge(cpumask_bits(srcp), nr_cpumask_bits, num);
+}
+
+/**
+ * cpumask_weight_lt - Check if # of bits in *srcp is less than a given number
+ * @srcp: the cpumask to count bits (< nr_cpu_ids) in.
+ * @num: the number to check.
+ */
+static inline bool cpumask_weight_lt(const struct cpumask *srcp, int num)
+{
+	return bitmap_weight_lt(cpumask_bits(srcp), nr_cpumask_bits, num);
+}
+
+/**
+ * cpumask_weight_le - Check if # of bits in *srcp is less than or equal to a given number
+ * @srcp: the cpumask to count bits (< nr_cpu_ids) in.
+ * @num: the number to check.
+ */
+static inline bool cpumask_weight_le(const struct cpumask *srcp, int num)
+{
+	return bitmap_weight_le(cpumask_bits(srcp), nr_cpumask_bits, num);
+}
+
 /**
  * cpumask_shift_right - *dstp = *srcp >> n
  * @dstp: the cpumask result
Signature · 1 line
2.32.0
author maintainer
#70 lore raw

PATCH v4 36/49 arch/ia64: replace cpumask_weight with cpumask_weight_eq in mm/tlb.c

In reply to Yury Norov

__flush_tlb_range() code calls cpumask_weight() to compare the weight of cpumask with a given number. We can do it more efficiently with cpumask_weight_eq because conditional cpumask_weight may stop traversing the cpumask earlier, as soon as condition is (or can't be) met.

---
 arch/ia64/mm/tlb.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/ia64/mm/tlb.c +1 -1
index 135b5135cace..a5bce13ab047 100644
@@ -332,7 +332,7 @@ __flush_tlb_range (struct vm_area_struct *vma, unsigned long start,
 
 	preempt_disable();
 #ifdef CONFIG_SMP
-	if (mm != current->active_mm || cpumask_weight(mm_cpumask(mm)) != 1) {
+	if (mm != current->active_mm || !cpumask_weight_eq(mm_cpumask(mm), 1)) {
 		ia64_global_tlb_purge(mm, start, end, nbits);
 		preempt_enable();
 		return;
Signature · 1 line
2.32.0
author maintainer
#71 lore raw

PATCH v4 37/49 arch/mips: replace cpumask_weight with cpumask_weight_{eq, ...} where appropriate

In reply to Yury Norov

Mips code uses calls cpumask_weight() to compare the weight of cpumask with a given number. We can do it more efficiently with cpumask_weight_{eq, ...} because conditional cpumask_weight may stop traversing the cpumask earlier, as soon as condition is (or can't be) met.

---
 arch/mips/cavium-octeon/octeon-irq.c | 4 ++--
 arch/mips/kernel/crash.c             | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)
arch/mips/cavium-octeon/octeon-irq.c +2 -2
index 844f882096e6..914871f15fb7 100644
@@ -763,7 +763,7 @@ static void octeon_irq_cpu_offline_ciu(struct irq_data *data)
 	if (!cpumask_test_cpu(cpu, mask))
 		return;
 
-	if (cpumask_weight(mask) > 1) {
+	if (cpumask_weight_gt(mask, 1)) {
 		/*
 		 * It has multi CPU affinity, just remove this CPU
 		 * from the affinity set.
@@ -795,7 +795,7 @@ static int octeon_irq_ciu_set_affinity(struct irq_data *data,
 	 * This removes the need to do locking in the .ack/.eoi
 	 * functions.
 	 */
-	if (cpumask_weight(dest) != 1)
+	if (!cpumask_weight_eq(dest, 1))
 		return -EINVAL;
 
 	if (!enable_one)
arch/mips/kernel/crash.c +1 -1
index 81845ba04835..5b690d52491f 100644
@@ -72,7 +72,7 @@ static void crash_kexec_prepare_cpus(void)
 	 */
 	pr_emerg("Sending IPI to other cpus...\n");
 	msecs = 10000;
-	while ((cpumask_weight(&cpus_in_crash) < ncpus) && (--msecs > 0)) {
+	while (cpumask_weight_lt(&cpus_in_crash, ncpus) && (--msecs > 0)) {
 		cpu_relax();
 		mdelay(1);
 	}
Signature · 1 line
2.32.0
author maintainer
#72 lore raw

PATCH v4 38/49 arch/powerpc: replace cpumask_weight with cpumask_weight_{eq, ...} where appropriate

In reply to Yury Norov

PowerPC code uses cpumask_weight() to compare the weight of cpumask with a given number. We can do it more efficiently with cpumask_weight_{eq, ...} because conditional cpumask_weight may stop traversing the cpumask earlier, as soon as condition is (or can't be) met.

---
 arch/powerpc/kernel/smp.c      | 2 +-
 arch/powerpc/kernel/watchdog.c | 2 +-
 arch/powerpc/xmon/xmon.c       | 4 ++--
 3 files changed, 4 insertions(+), 4 deletions(-)
arch/powerpc/kernel/smp.c +1 -1
index b7fd6a72aa76..8bff748df402 100644
@@ -1656,7 +1656,7 @@ void start_secondary(void *unused)
 		if (has_big_cores)
 			sibling_mask = cpu_smallcore_mask;
 
-		if (cpumask_weight(mask) > cpumask_weight(sibling_mask(cpu)))
+		if (cpumask_weight_gt(mask, cpumask_weight(sibling_mask(cpu))))
 			shared_caches = true;
 	}
 
arch/powerpc/kernel/watchdog.c +1 -1
index bfc27496fe7e..62937a077de7 100644
@@ -483,7 +483,7 @@ static void start_watchdog(void *arg)
 
 	wd_smp_lock(&flags);
 	cpumask_set_cpu(cpu, &wd_cpus_enabled);
-	if (cpumask_weight(&wd_cpus_enabled) == 1) {
+	if (cpumask_weight_eq(&wd_cpus_enabled, 1)) {
 		cpumask_set_cpu(cpu, &wd_smp_cpus_pending);
 		wd_smp_last_reset_tb = get_tb();
 	}
arch/powerpc/xmon/xmon.c +2 -2
index fd72753e8ad5..b423812e94e0 100644
@@ -469,7 +469,7 @@ static bool wait_for_other_cpus(int ncpus)
 
 	/* We wait for 2s, which is a metric "little while" */
 	for (timeout = 20000; timeout != 0; --timeout) {
-		if (cpumask_weight(&cpus_in_xmon) >= ncpus)
+		if (cpumask_weight_ge(&cpus_in_xmon, ncpus))
 			return true;
 		udelay(100);
 		barrier();
@@ -1338,7 +1338,7 @@ static int cpu_cmd(void)
 			case 'S':
 			case 't':
 				cpumask_copy(&xmon_batch_cpus, &cpus_in_xmon);
-				if (cpumask_weight(&xmon_batch_cpus) <= 1) {
+				if (cpumask_weight_le(&xmon_batch_cpus, 1)) {
 					printf("There are no other cpus in xmon\n");
 					break;
 				}
Signature · 1 line
2.32.0
reviewer Acked-by on v4 38/49
#73 lore raw

Re: [PATCH 38/49] arch/powerpc: replace cpumask_weight with cpumask_weight_{eq, ...} where appropriate

Quoted 11 lines · Yury Norov

PowerPC code uses cpumask_weight() to compare the weight of cpumask with a given number. We can do it more efficiently with cpumask_weight_{eq, ...} because conditional cpumask_weight may stop traversing the cpumask earlier, as soon as condition is (or can't be) met.

---
 arch/powerpc/kernel/smp.c      | 2 +-
 arch/powerpc/kernel/watchdog.c | 2 +-
 arch/powerpc/xmon/xmon.c       | 4 ++--
 3 files changed, 4 insertions(+), 4 deletions(-)

cheers

author maintainer
#74 lore raw

PATCH v4 39/49 arch/s390: replace cpumask_weight with cpumask_weight_eq where appropriate

In reply to Yury Norov

cfset_all_start() calls cpumask_weight() to compare the weight of cpumask with a given number. We can do it more efficiently with cpumask_weight_{eq, ...} because conditional cpumask_weight may stop traversing the cpumask earlier, as soon as condition is (or can't be) met.

---
 arch/s390/kernel/perf_cpum_cf.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/s390/kernel/perf_cpum_cf.c +1 -1
index ee8707abdb6a..4d217f7f5ccf 100644
@@ -975,7 +975,7 @@ static int cfset_all_start(struct cfset_request *req)
 		return -ENOMEM;
 	cpumask_and(mask, &req->mask, cpu_online_mask);
 	on_each_cpu_mask(mask, cfset_ioctl_on, &p, 1);
-	if (atomic_read(&p.cpus_ack) != cpumask_weight(mask)) {
+	if (!cpumask_weight_eq(mask, atomic_read(&p.cpus_ack))) {
 		on_each_cpu_mask(mask, cfset_ioctl_off, &p, 1);
 		rc = -EIO;
 		debug_sprintf_event(cf_dbg, 4, "%s CPUs missing", __func__);
Signature · 1 line
2.32.0
reviewer
#75 lore raw

Re: [PATCH 39/49] arch/s390: replace cpumask_weight with cpumask_weight_eq where appropriate

Hi Yury,

Quoted 15 lines · Yury Norov

cfset_all_start() calls cpumask_weight() to compare the weight of cpumask with a given number. We can do it more efficiently with cpumask_weight_{eq, ...} because conditional cpumask_weight may stop traversing the cpumask earlier, as soon as condition is (or can't be) met.

---
 arch/s390/kernel/perf_cpum_cf.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/s390/kernel/perf_cpum_cf.c +0 -0
index ee8707abdb6a..4d217f7f5ccf 100644

arch/s390/kernel/perf_cpum_cf.c static int cfset_all_start(struct cfset_request *req) · line 981

Quoted 8 lines
arch/s390/kernel/perf_cpum_cf.c +1 -1
@@ -975,7 +975,7 @@ static int cfset_all_start(struct cfset_request *req)
 		return -ENOMEM;
 	cpumask_and(mask, &req->mask, cpu_online_mask);
 	on_each_cpu_mask(mask, cfset_ioctl_on, &p, 1);
-	if (atomic_read(&p.cpus_ack) != cpumask_weight(mask)) {
+	if (!cpumask_weight_eq(mask, atomic_read(&p.cpus_ack))) {
 		on_each_cpu_mask(mask, cfset_ioctl_off, &p, 1);
 		rc = -EIO;
 		debug_sprintf_event(cf_dbg, 4, "%s CPUs missing", __func__);

given that you're adding a bunch of these functions - gt,lt,eq and others, i wonder whether it makes sense to also add cpumask_weight_ne(), so one could just write:

if (cpumask_weight_ne(mask, atomic_read(&p.cpus_ack))) {
	...
}

?

/Sven

author maintainer
#76 lore raw

Re: [PATCH 39/49] arch/s390: replace cpumask_weight with cpumask_weight_eq where appropriate

Quoted 32 lines · Sven Schnelle

Hi Yury,

Quoted 15 lines · Yury Norov

cfset_all_start() calls cpumask_weight() to compare the weight of cpumask with a given number. We can do it more efficiently with cpumask_weight_{eq, ...} because conditional cpumask_weight may stop traversing the cpumask earlier, as soon as condition is (or can't be) met.

---
 arch/s390/kernel/perf_cpum_cf.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/s390/kernel/perf_cpum_cf.c +0 -0
index ee8707abdb6a..4d217f7f5ccf 100644

arch/s390/kernel/perf_cpum_cf.c static int cfset_all_start(struct cfset_request *req) · line 981

Quoted 8 lines
arch/s390/kernel/perf_cpum_cf.c +1 -1
@@ -975,7 +975,7 @@ static int cfset_all_start(struct cfset_request *req)
 		return -ENOMEM;
 	cpumask_and(mask, &req->mask, cpu_online_mask);
 	on_each_cpu_mask(mask, cfset_ioctl_on, &p, 1);
-	if (atomic_read(&p.cpus_ack) != cpumask_weight(mask)) {
+	if (!cpumask_weight_eq(mask, atomic_read(&p.cpus_ack))) {
 		on_each_cpu_mask(mask, cfset_ioctl_off, &p, 1);
 		rc = -EIO;
 		debug_sprintf_event(cf_dbg, 4, "%s CPUs missing", __func__);

given that you're adding a bunch of these functions - gt,lt,eq and others, i wonder whether it makes sense to also add cpumask_weight_ne(), so one could just write:

Quoted 5 lines
if (cpumask_weight_ne(mask, atomic_read(&p.cpus_ack))) {
	...
}

?

It will have 3 users in cpumask + 1 in nodemask. I have no strong opinion whether we need it or not. Let's see what people say.

Thanks,
Yury

author maintainer
#77 lore raw

PATCH v4 40/49 firmware: pcsi: replace cpumask_weight with cpumask_weight_eq

In reply to Yury Norov

down_and_up_cpus() calls cpumask_weight() to compare the weight of cpumask with a given number. We can do it more efficiently with cpumask_weight_{eq, ...} because conditional cpumask_weight may stop traversing the cpumask earlier, as soon as condition is (or can't be) met.

---
 drivers/firmware/psci/psci_checker.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/firmware/psci/psci_checker.c +1 -1
index 116eb465cdb4..90c9473832a9 100644
@@ -90,7 +90,7 @@ static unsigned int down_and_up_cpus(const struct cpumask *cpus,
 		 * cpu_down() checks the number of online CPUs before the TOS
 		 * resident CPU.
 		 */
-		if (cpumask_weight(offlined_cpus) + 1 == nb_available_cpus) {
+		if (cpumask_weight_eq(offlined_cpus, nb_available_cpus - 1)) {
 			if (ret != -EBUSY) {
 				pr_err("Unexpected return code %d while trying "
 				       "to power down last online CPU %d\n",
Signature · 1 line
2.32.0
Reviewed-by on v4 40/49
#78 lore raw

Re: [PATCH 40/49] firmware: pcsi: replace cpumask_weight with cpumask_weight_eq

Quoted 5 lines · Yury Norov

down_and_up_cpus() calls cpumask_weight() to compare the weight of cpumask with a given number. We can do it more efficiently with cpumask_weight_{eq, ...} because conditional cpumask_weight may stop traversing the cpumask earlier, as soon as condition is (or can't be) met.

Nit: s/pcsi/psci/ in $subject. With that fixed,

Signature · 2 lines
Regards,
Sudeep
maintainer Acked-by on v4 40/49
#79 lore raw

Re: [PATCH 40/49] firmware: pcsi: replace cpumask_weight with cpumask_weight_eq

In reply to Yury Norov
Quoted 6 lines · Yury Norov

down_and_up_cpus() calls cpumask_weight() to compare the weight of cpumask with a given number. We can do it more efficiently with cpumask_weight_{eq, ...} because conditional cpumask_weight may stop traversing the cpumask earlier, as soon as condition is (or can't be) met.

With the 'pcsi' typo fixed:

Mark.

Quoted 20 lines
---
 drivers/firmware/psci/psci_checker.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/firmware/psci/psci_checker.c +1 -1
index 116eb465cdb4..90c9473832a9 100644
@@ -90,7 +90,7 @@ static unsigned int down_and_up_cpus(const struct cpumask *cpus,
 		 * cpu_down() checks the number of online CPUs before the TOS
 		 * resident CPU.
 		 */
-		if (cpumask_weight(offlined_cpus) + 1 == nb_available_cpus) {
+		if (cpumask_weight_eq(offlined_cpus, nb_available_cpus - 1)) {
 			if (ret != -EBUSY) {
 				pr_err("Unexpected return code %d while trying "
 				       "to power down last online CPU %d\n",
Signature · 1 line
2.32.0
author maintainer
#80 lore raw

PATCH v4 41/49 RDMA/hfi1: replace cpumask_weight with cpumask_weight_{eq, ...} where appropriate

In reply to Yury Norov

Infiniband code uses cpumask_weight() to compare the weight of cpumask with a given number. We can do it more efficiently with cpumask_weight_{eq, ...} because conditional cpumask_weight may stop traversing the cpumask earlier, as soon as condition is (or can't be) met.

---
 drivers/infiniband/hw/hfi1/affinity.c    | 9 ++++-----
 drivers/infiniband/hw/qib/qib_file_ops.c | 2 +-
 drivers/infiniband/hw/qib/qib_iba7322.c  | 2 +-
 3 files changed, 6 insertions(+), 7 deletions(-)
drivers/infiniband/hw/hfi1/affinity.c +4 -5
index 877f8e84a672..a9ad07808dea 100644
@@ -506,7 +506,7 @@ static int _dev_comp_vect_cpu_mask_init(struct hfi1_devdata *dd,
 	 * available CPUs divide it by the number of devices in the
 	 * local NUMA node.
 	 */
-	if (cpumask_weight(&entry->comp_vect_mask) == 1) {
+	if (cpumask_weight_eq(&entry->comp_vect_mask, 1)) {
 		possible_cpus_comp_vect = 1;
 		dd_dev_warn(dd,
 			    "Number of kernel receive queues is too large for completion vector affinity to be effective\n");
@@ -592,7 +592,7 @@ int hfi1_dev_affinity_init(struct hfi1_devdata *dd)
 {
 	struct hfi1_affinity_node *entry;
 	const struct cpumask *local_mask;
-	int curr_cpu, possible, i, ret;
+	int curr_cpu, i, ret;
 	bool new_entry = false;
 
 	local_mask = cpumask_of_node(dd->node);
@@ -625,10 +625,9 @@ int hfi1_dev_affinity_init(struct hfi1_devdata *dd)
 			    local_mask);
 
 		/* fill in the receive list */
-		possible = cpumask_weight(&entry->def_intr.mask);
 		curr_cpu = cpumask_first(&entry->def_intr.mask);
 
-		if (possible == 1) {
+		if (cpumask_weight_eq(&entry->def_intr.mask, 1)) {
 			/* only one CPU, everyone will use it */
 			cpumask_set_cpu(curr_cpu, &entry->rcv_intr.mask);
 			cpumask_set_cpu(curr_cpu, &entry->general_intr_mask);
@@ -1016,7 +1015,7 @@ int hfi1_get_proc_affinity(int node)
 		cpu = cpumask_first(proc_mask);
 		cpumask_set_cpu(cpu, &set->used);
 		goto done;
-	} else if (current->nr_cpus_allowed < cpumask_weight(&set->mask)) {
+	} else if (cpumask_weight_gt(&set->mask, current->nr_cpus_allowed)) {
 		hfi1_cdbg(PROC, "PID %u %s affinity set to CPU set(s) %*pbl",
 			  current->pid, current->comm,
 			  cpumask_pr_args(proc_mask));
drivers/infiniband/hw/qib/qib_file_ops.c +1 -1
index aa290928cf96..add89bc21b0a 100644
@@ -1151,7 +1151,7 @@ static void assign_ctxt_affinity(struct file *fp, struct qib_devdata *dd)
 	 * reserve a processor for it on the local NUMA node.
 	 */
 	if ((weight >= qib_cpulist_count) &&
-		(cpumask_weight(local_mask) <= qib_cpulist_count)) {
+		(cpumask_weight_le(local_mask, qib_cpulist_count))) {
 		for_each_cpu(local_cpu, local_mask)
 			if (!test_and_set_bit(local_cpu, qib_cpulist)) {
 				fd->rec_cpu_num = local_cpu;
drivers/infiniband/hw/qib/qib_iba7322.c +1 -1
index ceed302cf6a0..b17f96509d2c 100644
@@ -3405,7 +3405,7 @@ static void qib_setup_7322_interrupt(struct qib_devdata *dd, int clearpend)
 	local_mask = cpumask_of_pcibus(dd->pcidev->bus);
 	firstcpu = cpumask_first(local_mask);
 	if (firstcpu >= nr_cpu_ids ||
-			cpumask_weight(local_mask) == num_online_cpus()) {
+			cpumask_weight_eq(local_mask, num_online_cpus())) {
 		local_mask = topology_core_cpumask(0);
 		firstcpu = cpumask_first(local_mask);
 	}
Signature · 1 line
2.32.0
maintainer Acked-by on v4 41/49
#81 lore raw

Re: [PATCH 41/49] RDMA/hfi1: replace cpumask_weight with cpumask_weight_{eq, ...} where appropriate

Quoted 11 lines · Yury Norov

Infiniband code uses cpumask_weight() to compare the weight of cpumask with a given number. We can do it more efficiently with cpumask_weight_{eq, ...} because conditional cpumask_weight may stop traversing the cpumask earlier, as soon as condition is (or can't be) met.

---
 drivers/infiniband/hw/hfi1/affinity.c    | 9 ++++-----
 drivers/infiniband/hw/qib/qib_file_ops.c | 2 +-
 drivers/infiniband/hw/qib/qib_iba7322.c  | 2 +-
 3 files changed, 6 insertions(+), 7 deletions(-)

I suppose you'll send this with the prior patch adding the functions in which case

Jason

author maintainer
#82 lore raw

PATCH v4 42/49 scsi: lpfc: replace cpumask_weight with cpumask_weight_gt

In reply to Yury Norov

lpfc_cpuhp_get_eq() calls cpumask_weight() to compare the weight of cpumask with a given number. We can do it more efficiently with cpumask_weight_gt because conditional cpumask_weight may stop traversing the cpumask earlier, as soon as condition is (or can't be) met.

---
 drivers/scsi/lpfc/lpfc_init.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/scsi/lpfc/lpfc_init.c +1 -1
index f5c363f663f6..35688427cb7f 100644
@@ -12642,7 +12642,7 @@ lpfc_cpuhp_get_eq(struct lpfc_hba *phba, unsigned int cpu,
 		 * gone offline yet, we need >1.
 		 */
 		cpumask_and(tmp, maskp, cpu_online_mask);
-		if (cpumask_weight(tmp) > 1)
+		if (cpumask_weight_gt(tmp, 1))
 			continue;
 
 		/* Now that we have an irq to shutdown, get the eq
Signature · 1 line
2.32.0
author maintainer
#83 lore raw

PATCH v4 43/49 soc/qman: replace cpumask_weight with cpumask_weight_lt

In reply to Yury Norov

qman_test_stash() calls cpumask_weight() to compare the weight of cpumask with a given number. We can do it more efficiently with cpumask_weight_lt because conditional cpumask_weight may stop traversing the cpumask earlier, as soon as condition is (or can't be) met.

---
 drivers/soc/fsl/qbman/qman_test_stash.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/soc/fsl/qbman/qman_test_stash.c +1 -1
index b7e8e5ec884c..28b08568a349 100644
@@ -561,7 +561,7 @@ int qman_test_stash(void)
 {
 	int err;
 
-	if (cpumask_weight(cpu_online_mask) < 2) {
+	if (cpumask_weight_lt(cpu_online_mask, 2)) {
 		pr_info("%s(): skip - only 1 CPU\n", __func__);
 		return 0;
 	}
Signature · 1 line
2.32.0
author maintainer
#84 lore raw

PATCH v4 44/49 nodemask: add nodemask_weight_{eq,gt,ge,lt,le}

In reply to Yury Norov

In many cases kernel code uses nodemask_weight() to compare the result against some number or expression:

	if (nodes_weight(...) > 1)
		do_something();

It may be significantly improved for large nodemasks: if first few words count set bits to a number greater than given, we can stop counting and immediately return.

The same idea would work in other direction: if we know that the number of set bits that we counted so far is small enough, so that it would be smaller than required number even if all bits of the rest of the nodemask are set, we can stop counting earlier.

This patch adds nodes_weight{eq, gt, ge, lt, le} helpers based on corresponding bitmap functions. The following patches apply new functions where appropriate.

---
 include/linux/nodemask.h | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)
include/linux/nodemask.h +35 -0
index 567c3ddba2c4..197598e075e9 100644
@@ -38,6 +38,11 @@
  * int nodes_empty(mask)		Is mask empty (no bits sets)?
  * int nodes_full(mask)			Is mask full (all bits sets)?
  * int nodes_weight(mask)		Hamming weight - number of set bits
+ * bool nodes_weight_eq(src, nbits, num) Hamming Weight is equal to num
+ * bool nodes_weight_gt(src, nbits, num) Hamming Weight is greater than num
+ * bool nodes_weight_ge(src, nbits, num) Hamming Weight is greater than or equal to num
+ * bool nodes_weight_lt(src, nbits, num) Hamming Weight is less than num
+ * bool nodes_weight_le(src, nbits, num) Hamming Weight is less than or equal to num
  *
  * void nodes_shift_right(dst, src, n)	Shift right
  * void nodes_shift_left(dst, src, n)	Shift left
@@ -240,6 +245,36 @@ static inline int __nodes_weight(const nodemask_t *srcp, unsigned int nbits)
 	return bitmap_weight(srcp->bits, nbits);
 }
 
+#define nodes_weight_eq(nodemask, num) __nodes_weight_eq(&(nodemask), MAX_NUMNODES, (num))
+static inline int __nodes_weight_eq(const nodemask_t *srcp, unsigned int nbits, int num)
+{
+	return bitmap_weight_eq(srcp->bits, nbits, num);
+}
+
+#define nodes_weight_gt(nodemask, num) __nodes_weight_gt(&(nodemask), MAX_NUMNODES, (num))
+static inline int __nodes_weight_gt(const nodemask_t *srcp, unsigned int nbits, int num)
+{
+	return bitmap_weight_gt(srcp->bits, nbits, num);
+}
+
+#define nodes_weight_ge(nodemask, num) __nodes_weight_ge(&(nodemask), MAX_NUMNODES, (num))
+static inline int __nodes_weight_ge(const nodemask_t *srcp, unsigned int nbits, int num)
+{
+	return bitmap_weight_ge(srcp->bits, nbits, num);
+}
+
+#define nodes_weight_lt(nodemask, num) __nodes_weight_lt(&(nodemask), MAX_NUMNODES, (num))
+static inline int __nodes_weight_lt(const nodemask_t *srcp, unsigned int nbits, int num)
+{
+	return bitmap_weight_lt(srcp->bits, nbits, num);
+}
+
+#define nodes_weight_le(nodemask, num) __nodes_weight_le(&(nodemask), MAX_NUMNODES, (num))
+static inline int __nodes_weight_le(const nodemask_t *srcp, unsigned int nbits, int num)
+{
+	return bitmap_weight_le(srcp->bits, nbits, num);
+}
+
 #define nodes_shift_right(dst, src, n) \
 			__nodes_shift_right(&(dst), &(src), (n), MAX_NUMNODES)
 static inline void __nodes_shift_right(nodemask_t *dstp,
Signature · 1 line
2.32.0
author maintainer
#85 lore raw

PATCH v4 45/49 ACPI: replace nodes__weight with nodes_weight_ge for numa

In reply to Yury Norov

acpi_map_pxm_to_node() calls nodes_weight() to compare the weight of nodemask with a given number. We can do it more efficiently with nodes_weight_eq() because conditional nodes_weight may stop traversing the nodemask earlier, as soon as condition is (or is not) met.

---
 drivers/acpi/numa/srat.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/acpi/numa/srat.c +1 -1
index 3b818ab186be..fe7a7996f553 100644
@@ -67,7 +67,7 @@ int acpi_map_pxm_to_node(int pxm)
 	node = pxm_to_node_map[pxm];
 
 	if (node == NUMA_NO_NODE) {
-		if (nodes_weight(nodes_found_map) >= MAX_NUMNODES)
+		if (nodes_weight_ge(nodes_found_map, MAX_NUMNODES))
 			return NUMA_NO_NODE;
 		node = first_unset_node(nodes_found_map);
 		__acpi_map_pxm_to_node(pxm, node);
Signature · 1 line
2.32.0
maintainer Applied
#86 lore raw

Re: [PATCH 45/49] ACPI: replace nodes__weight with nodes_weight_ge for numa

Quoted 17 lines · Yury Norov

acpi_map_pxm_to_node() calls nodes_weight() to compare the weight of nodemask with a given number. We can do it more efficiently with nodes_weight_eq() because conditional nodes_weight may stop traversing the nodemask earlier, as soon as condition is (or is not) met.

---
 drivers/acpi/numa/srat.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/acpi/numa/srat.c +0 -0
index 3b818ab186be..fe7a7996f553 100644

drivers/acpi/numa/srat.c int acpi_map_pxm_to_node(int pxm)

Quoted 9 lines
drivers/acpi/numa/srat.c +1 -2
@@ -67,7 +67,7 @@ int acpi_map_pxm_to_node(int pxm)
        node = pxm_to_node_map[pxm];
 
        if (node == NUMA_NO_NODE) {
-               if (nodes_weight(nodes_found_map) >= MAX_NUMNODES)
+               if (nodes_weight_ge(nodes_found_map, MAX_NUMNODES))
                        return NUMA_NO_NODE;
                node = first_unset_node(nodes_found_map);
                __acpi_map_pxm_to_node(pxm, node);
--

Applied as 5.18 material, thanks!

author maintainer
#87 lore raw

Re: [PATCH 45/49] ACPI: replace nodes__weight with nodes_weight_ge for numa

Quoted 20 lines · Rafael J. Wysocki
Quoted 19 lines · Yury Norov

acpi_map_pxm_to_node() calls nodes_weight() to compare the weight of nodemask with a given number. We can do it more efficiently with nodes_weight_eq() because conditional nodes_weight may stop traversing the nodemask earlier, as soon as condition is (or is not) met.

---
 drivers/acpi/numa/srat.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/acpi/numa/srat.c +0 -0
index 3b818ab186be..fe7a7996f553 100644
@@ -67,7 +67,7 @@ int acpi_map_pxm_to_node(int pxm)
        node = pxm_to_node_map[pxm];
 
Quoted 9 lines

drivers/acpi/numa/srat.c int acpi_map_pxm_to_node(int pxm)

Quoted 7 lines
drivers/acpi/numa/srat.c +1 -2
        if (node == NUMA_NO_NODE) {
-               if (nodes_weight(nodes_found_map) >= MAX_NUMNODES)
+               if (nodes_weight_ge(nodes_found_map, MAX_NUMNODES))
                        return NUMA_NO_NODE;
                node = first_unset_node(nodes_found_map);
                __acpi_map_pxm_to_node(pxm, node);
--

Applied as 5.18 material, thanks!

It depends on patches 44 and 26. Are you applying them too?

#88 lore raw

Re: [PATCH 45/49] ACPI: replace nodes__weight with nodes_weight_ge for numa

Quoted 32 lines · Yury Norov
Quoted 20 lines · Rafael J. Wysocki
Quoted 19 lines · Yury Norov

acpi_map_pxm_to_node() calls nodes_weight() to compare the weight of nodemask with a given number. We can do it more efficiently with nodes_weight_eq() because conditional nodes_weight may stop traversing the nodemask earlier, as soon as condition is (or is not) met.

---
 drivers/acpi/numa/srat.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/acpi/numa/srat.c +0 -0
index 3b818ab186be..fe7a7996f553 100644
@@ -67,7 +67,7 @@ int acpi_map_pxm_to_node(int pxm)
        node = pxm_to_node_map[pxm];
 
Quoted 9 lines

drivers/acpi/numa/srat.c int acpi_map_pxm_to_node(int pxm)

Quoted 7 lines
drivers/acpi/numa/srat.c +1 -2
        if (node == NUMA_NO_NODE) {
-               if (nodes_weight(nodes_found_map) >= MAX_NUMNODES)
+               if (nodes_weight_ge(nodes_found_map, MAX_NUMNODES))
                        return NUMA_NO_NODE;
                node = first_unset_node(nodes_found_map);
                __acpi_map_pxm_to_node(pxm, node);
--

Applied as 5.18 material, thanks!

Quoted 1 line

It depends on patches 44 and 26. Are you applying them too?

No, I'm not (I've only received this one directly).

I'll drop this patch now and please feel free to add my ACK to it.

Thanks!

author maintainer
#89 lore raw

Re: [PATCH 45/49] ACPI: replace nodes__weight with nodes_weight_ge for numa

Quoted 34 lines · Rafael J. Wysocki
Quoted 32 lines · Yury Norov
Quoted 29 lines · Rafael J. Wysocki
Quoted 17 lines · Yury Norov

acpi_map_pxm_to_node() calls nodes_weight() to compare the weight of nodemask with a given number. We can do it more efficiently with nodes_weight_eq() because conditional nodes_weight may stop traversing the nodemask earlier, as soon as condition is (or is not) met.

---
 drivers/acpi/numa/srat.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/acpi/numa/srat.c +0 -0
index 3b818ab186be..fe7a7996f553 100644

drivers/acpi/numa/srat.c int acpi_map_pxm_to_node(int pxm)

Quoted 9 lines
drivers/acpi/numa/srat.c +1 -2
@@ -67,7 +67,7 @@ int acpi_map_pxm_to_node(int pxm)
        node = pxm_to_node_map[pxm];
 
        if (node == NUMA_NO_NODE) {
-               if (nodes_weight(nodes_found_map) >= MAX_NUMNODES)
+               if (nodes_weight_ge(nodes_found_map, MAX_NUMNODES))
                        return NUMA_NO_NODE;
                node = first_unset_node(nodes_found_map);
                __acpi_map_pxm_to_node(pxm, node);
--

Applied as 5.18 material, thanks!

Quoted 5 lines
Quoted 1 line

It depends on patches 44 and 26. Are you applying them too?

No, I'm not (I've only received this one directly).

I'll drop this patch now and please feel free to add my ACK to it.

OK, thanks.

author maintainer
#90 lore raw

PATCH v4 46/49 mm/mempolicy: replace nodes_weight with nodes_weight_eq

In reply to Yury Norov

do_migrate_pages() calls nodes_weight() to compare the weight of nodemask with a given number. We can do it more efficiently with nodes_weight_eq() because conditional nodes_weight() may stop traversing the nodemask earlier, as soon as condition is (or is not) met.

---
 mm/mempolicy.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
mm/mempolicy.c +1 -1
index 7c852793d9e8..56efd00b1b6e 100644
@@ -1154,7 +1154,7 @@ int do_migrate_pages(struct mm_struct *mm, const nodemask_t *from,
 			 *          [0-7] - > [3,4,5] moves only 0,1,2,6,7.
 			 */
 
-			if ((nodes_weight(*from) != nodes_weight(*to)) &&
+			if (!nodes_weight_eq(*from, nodes_weight(*to)) &&
 						(node_isset(s, *to)))
 				continue;
 
Signature · 1 line
2.32.0
reviewer Acked-by on v4 46/49
#91 lore raw

Re: [PATCH 46/49] mm/mempolicy: replace nodes_weight with nodes_weight_eq

Quoted 7 lines · Yury Norov

do_migrate_pages() calls nodes_weight() to compare the weight of nodemask with a given number. We can do it more efficiently with nodes_weight_eq() because conditional nodes_weight() may stop traversing the nodemask earlier, as soon as condition is (or is not) met.

Quoted 21 lines
---
 mm/mempolicy.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
mm/mempolicy.c +1 -1
index 7c852793d9e8..56efd00b1b6e 100644
@@ -1154,7 +1154,7 @@ int do_migrate_pages(struct mm_struct *mm, const nodemask_t *from,
 			 *          [0-7] - > [3,4,5] moves only 0,1,2,6,7.
 			 */
 
-			if ((nodes_weight(*from) != nodes_weight(*to)) &&
+			if (!nodes_weight_eq(*from, nodes_weight(*to)) &&
 						(node_isset(s, *to)))
 				continue;
 
Signature · 1 line
2.32.0
Signature · 2 lines
Sincerely yours,
Mike.
#92 lore raw

Re: [PATCH 46/49] mm/mempolicy: replace nodes_weight with nodes_weight_eq

In reply to Yury Norov

Le 10/02/2022 à 23:49, Yury Norov a écrit :

Quoted 16 lines

do_migrate_pages() calls nodes_weight() to compare the weight of nodemask with a given number. We can do it more efficiently with nodes_weight_eq() because conditional nodes_weight() may stop traversing the nodemask earlier, as soon as condition is (or is not) met.

---
  mm/mempolicy.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)
mm/mempolicy.c +0 -0
index 7c852793d9e8..56efd00b1b6e 100644

mm/mempolicy.c int do_migrate_pages(struct mm_struct *mm, const nodemask_t *from, · line 1158

Quoted 6 lines
mm/mempolicy.c +1 -1
@@ -1154,7 +1154,7 @@ int do_migrate_pages(struct mm_struct *mm, const nodemask_t *from,
  			 *          [0-7] - > [3,4,5] moves only 0,1,2,6,7.
  			 */
 
-			if ((nodes_weight(*from) != nodes_weight(*to)) &&
+			if (!nodes_weight_eq(*from, nodes_weight(*to)) &&
  						(node_isset(s, *to)))

Hi,

I've not looked in details, but would it make sense to hoist the "(nodes_weight(*from) != nodes_weight(*to))" test out of the for_each_node_mask() to compute it only once?

'from' and 'to' look unmodified in the loop.

Just my 2c,
CJ

Quoted 2 lines
mm/mempolicy.c +0 -0
  				continue;
 
author maintainer
#93 lore raw

Re: [PATCH 46/49] mm/mempolicy: replace nodes_weight with nodes_weight_eq

+ Larry Woodman <[email protected]>

Quoted 25 lines · Christophe JAILLET

Le 10/02/2022 à 23:49, Yury Norov a écrit :

Quoted 16 lines

do_migrate_pages() calls nodes_weight() to compare the weight of nodemask with a given number. We can do it more efficiently with nodes_weight_eq() because conditional nodes_weight() may stop traversing the nodemask earlier, as soon as condition is (or is not) met.

---
  mm/mempolicy.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)
mm/mempolicy.c +0 -0
index 7c852793d9e8..56efd00b1b6e 100644

mm/mempolicy.c int do_migrate_pages(struct mm_struct *mm, const nodemask_t *from, · line 1157

Quoted 5 lines
mm/mempolicy.c +1 -1
@@ -1154,7 +1154,7 @@ int do_migrate_pages(struct mm_struct *mm, const nodemask_t *from,
  			 *          [0-7] - > [3,4,5] moves only 0,1,2,6,7.
  			 */
-			if ((nodes_weight(*from) != nodes_weight(*to)) &&
+			if (!nodes_weight_eq(*from, nodes_weight(*to)) &&
  						(node_isset(s, *to)))

Hi,

Quoted 5 lines

I've not looked in details, but would it make sense to hoist the "(nodes_weight(*from) != nodes_weight(*to))" test out of the for_each_node_mask() to compute it only once?

'from' and 'to' look unmodified in the loop.

It seems that 'from' and 'to' are untouched in the outer while() loop as well, so we can compare weights of nodemaps only once at the beginning.

Larry, can you please comment on that?

Thanks,
Yury

author maintainer
#94 lore raw

PATCH v4 47/49 nodemask: add num_node_state_eq()

In reply to Yury Norov

Page allocator uses num_node_state() to compare number of nodes with a given number. The underlying code calls bitmap_weight(), and we can do it more efficiently with num_node_state_eq because conditional nodes_weight may stop traversing the nodemask earlier, as soon as condition is (or is not) met.

---
 include/linux/nodemask.h | 5 +++++
 mm/page_alloc.c          | 2 +-
 2 files changed, 6 insertions(+), 1 deletion(-)
include/linux/nodemask.h +5 -0
index 197598e075e9..c5014dbf3cce 100644
@@ -466,6 +466,11 @@ static inline int num_node_state(enum node_states state)
 	return nodes_weight(node_states[state]);
 }
 
+static inline int num_node_state_eq(enum node_states state, int num)
+{
+	return nodes_weight_eq(node_states[state], num);
+}
+
 #define for_each_node_state(__node, __state) \
 	for_each_node_mask((__node), node_states[__state])
 
mm/page_alloc.c +1 -1
index cface1d38093..897e64b66ca4 100644
@@ -8434,7 +8434,7 @@ void __init page_alloc_init(void)
 	int ret;
 
 #ifdef CONFIG_NUMA
-	if (num_node_state(N_MEMORY) == 1)
+	if (num_node_state_eq(N_MEMORY, 1))
 		hashdist = 0;
 #endif
 
Signature · 1 line
2.32.0
reviewer Acked-by on v4 47/49
#95 lore raw

Re: [PATCH 47/49] nodemask: add num_node_state_eq()

Quoted 7 lines · Yury Norov

Page allocator uses num_node_state() to compare number of nodes with a given number. The underlying code calls bitmap_weight(), and we can do it more efficiently with num_node_state_eq because conditional nodes_weight may stop traversing the nodemask earlier, as soon as condition is (or is not) met.

Quoted 38 lines
---
 include/linux/nodemask.h | 5 +++++
 mm/page_alloc.c          | 2 +-
 2 files changed, 6 insertions(+), 1 deletion(-)
include/linux/nodemask.h +5 -0
index 197598e075e9..c5014dbf3cce 100644
@@ -466,6 +466,11 @@ static inline int num_node_state(enum node_states state)
 	return nodes_weight(node_states[state]);
 }
 
+static inline int num_node_state_eq(enum node_states state, int num)
+{
+	return nodes_weight_eq(node_states[state], num);
+}
+
 #define for_each_node_state(__node, __state) \
 	for_each_node_mask((__node), node_states[__state])
 
mm/page_alloc.c +1 -1
index cface1d38093..897e64b66ca4 100644
@@ -8434,7 +8434,7 @@ void __init page_alloc_init(void)
 	int ret;
 
 #ifdef CONFIG_NUMA
-	if (num_node_state(N_MEMORY) == 1)
+	if (num_node_state_eq(N_MEMORY, 1))
 		hashdist = 0;
 #endif
 
Signature · 1 line
2.32.0
Signature · 2 lines
Sincerely yours,
Mike.
author maintainer
#96 lore raw

PATCH v4 48/49 tools: bitmap: sync bitmap_weight

In reply to Yury Norov

Pull bitmap_weight_{cmp,eq,gt,ge,lt,le} from mother kernel and use where applicable.

---
 tools/include/linux/bitmap.h | 44 ++++++++++++++++++++++++++++++++++++
 tools/lib/bitmap.c           | 20 ++++++++++++++++
 tools/perf/util/pmu.c        |  2 +-
 3 files changed, 65 insertions(+), 1 deletion(-)
tools/include/linux/bitmap.h +44 -0
index ea97804d04d4..29bf54996a84 100644
@@ -12,6 +12,8 @@
 	unsigned long name[BITS_TO_LONGS(bits)]
 
 int __bitmap_weight(const unsigned long *bitmap, int bits);
+int __bitmap_weight_cmp(const unsigned long *bitmap, unsigned int bits,
+			 unsigned int num);
 void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
 		 const unsigned long *bitmap2, int bits);
 int __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
@@ -68,6 +70,48 @@ static inline int bitmap_weight(const unsigned long *src, unsigned int nbits)
 	return __bitmap_weight(src, nbits);
 }
 
+static __always_inline
+int bitmap_weight_cmp(const unsigned long *src, unsigned int nbits, int num)
+{
+	if ((unsigned int)num > nbits)
+		return -num;
+
+	if (small_const_nbits(nbits))
+		return hweight_long(*src & BITMAP_LAST_WORD_MASK(nbits)) - num;
+
+	return __bitmap_weight_cmp(src, nbits, num);
+}
+
+static __always_inline
+bool bitmap_weight_eq(const unsigned long *src, unsigned int nbits, int num)
+{
+	return bitmap_weight_cmp(src, nbits, num) == 0;
+}
+
+static __always_inline
+bool bitmap_weight_gt(const unsigned long *src, unsigned int nbits, int num)
+{
+	return bitmap_weight_cmp(src, nbits, num) > 0;
+}
+
+static __always_inline
+bool bitmap_weight_ge(const unsigned long *src, unsigned int nbits, int num)
+{
+	return bitmap_weight_cmp(src, nbits, num - 1) > 0;
+}
+
+static __always_inline
+bool bitmap_weight_lt(const unsigned long *src, unsigned int nbits, int num)
+{
+	return bitmap_weight_cmp(src, nbits, num - 1) <= 0;
+}
+
+static __always_inline
+bool bitmap_weight_le(const unsigned long *src, unsigned int nbits, int num)
+{
+	return bitmap_weight_cmp(src, nbits, num) <= 0;
+}
+
 static inline void bitmap_or(unsigned long *dst, const unsigned long *src1,
 			     const unsigned long *src2, unsigned int nbits)
 {
tools/lib/bitmap.c +20 -0
index db466ef7be9d..06e58fee8523 100644
@@ -18,6 +18,26 @@ int __bitmap_weight(const unsigned long *bitmap, int bits)
 	return w;
 }
 
+int __bitmap_weight_cmp(const unsigned long *bitmap, unsigned int bits, int num)
+{
+	unsigned int k, w, lim = bits / BITS_PER_LONG;
+
+	for (k = 0, w = 0; k < lim; k++) {
+		if (w + bits - k * BITS_PER_LONG < num)
+			goto out;
+
+		w += hweight_long(bitmap[k]);
+
+		if (w > num)
+			goto out;
+	}
+
+	if (bits % BITS_PER_LONG)
+		w += hweight_long(bitmap[k] & BITMAP_LAST_WORD_MASK(bits));
+out:
+	return w - num;
+}
+
 void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
 		 const unsigned long *bitmap2, int bits)
 {
tools/perf/util/pmu.c +1 -1
index 8dfbba15aeb8..2c26cdd7f9b0 100644
@@ -1314,7 +1314,7 @@ static int pmu_config_term(const char *pmu_name,
 	 */
 	if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) {
 		if (term->no_value &&
-		    bitmap_weight(format->bits, PERF_PMU_FORMAT_BITS) > 1) {
+		    bitmap_weight_gt(format->bits, PERF_PMU_FORMAT_BITS, 1)) {
 			if (err) {
 				parse_events_error__handle(err, term->err_val,
 					   strdup("no value assigned for term"),
Signature · 1 line
2.32.0
author maintainer
#97 lore raw

PATCH v4 49/49 MAINTAINERS: add cpumask and nodemask files to BITMAP_API

In reply to Yury Norov

cpumask and nodemask APIs are thin wrappers around basic bitmap API, and corresponding files are not formally maintained. This patch adds them to BITMAP_API section, so that bitmap folks would have closer look at it.

---
 MAINTAINERS | 4 ++++
 1 file changed, 4 insertions(+)
MAINTAINERS +4 -0
index bc32519e5c02..718ed3b81c8e 100644
@@ -3434,10 +3434,14 @@ R:	Andy Shevchenko <[email protected]>
 R:	Rasmus Villemoes <[email protected]>
 S:	Maintained
 F:	include/linux/bitmap.h
+F:	include/linux/cpumask.h
 F:	include/linux/find.h
+F:	include/linux/nodemask.h
 F:	lib/bitmap.c
+F:	lib/cpumask.c
 F:	lib/find_bit.c
 F:	lib/find_bit_benchmark.c
+F:	lib/nodemask.c
 F:	lib/test_bitmap.c
 F:	tools/include/linux/bitmap.h
 F:	tools/include/linux/find.h
Signature · 1 line
2.32.0
maintainer Applied
#98 lore raw
In reply to Yury Norov
Quoted 11 lines · Yury Norov

In many cases people use bitmap_weight()-based functions to compare the result against a number of expression:

if (cpumask_weight(mask) > 1)
do_something();

This may take considerable amount of time on many-cpus machines because cpumask_weight() will traverse every word of underlying cpumask unconditionally.

[...]

Applied to will (for-next/perf), thanks!

[12/49] perf: replace bitmap_weight with bitmap_empty where appropriate

        https://git.kernel.org/will/c/95ed57c73bbc

Cheers,

Signature · 5 lines
Will

https://fixes.arm64.dev
https://next.arm64.dev
https://will.arm64.dev