[PATCH v7 4/7] scsi: mvumi: walk the hotplug event bitmap a byte at a time
From: Yehyeong Lee
Date: Wed Oct 14 2026 - 20:58:22 EST
mvumi_proc_msg() casts param->bitmap to unsigned long * and hands it to
find_next_zero_bit(). bitmap sits four bytes into struct
mvumi_hotplug_event, so on a 64-bit host the pointer is four-byte aligned
where the bitmap API expects long alignment. On an architecture that
traps unaligned loads that faults, and the second bitmap, which starts at
an arbitrary byte offset derived from size, can be misaligned on any host.
Walk the bitmap bytes instead. The driver reads every other
firmware-supplied field natively, so bit n of the bitmap is already byte
n / 8 bit n % 8 in practice; writing that out keeps the device numbering
this driver has always used, needs no alignment from the buffer, and drops
the long-at-a-time reads the earlier bound had to allow for. That bound
stays as it is, which is now more conservative than the walk needs.
Fixes: bd756ddea18e ("[SCSI] mvumi: Add support for Marvell SAS/SATA RAID-on-Chip(ROC) 88RC9580")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Yehyeong Lee <yhlee@xxxxxxxxxxxxxxxxxx>
---
drivers/scsi/mvumi.c | 41 +++++++++++++++++------------------------
1 file changed, 17 insertions(+), 24 deletions(-)
diff --git a/drivers/scsi/mvumi.c b/drivers/scsi/mvumi.c
index 9a3dde53dea97..18964e860ac8e 100644
--- a/drivers/scsi/mvumi.c
+++ b/drivers/scsi/mvumi.c
@@ -1653,16 +1653,15 @@ static void mvumi_proc_msg(struct mvumi_hba *mhba,
struct mvumi_hotplug_event *param)
{
u16 size = READ_ONCE(param->size);
- const unsigned long *ar_bitmap;
- const unsigned long *re_bitmap;
+ const u8 *ar_bitmap;
+ const u8 *re_bitmap;
int index;
/*
- * The second bitmap starts size bits into the event buffer and
- * find_next_zero_bit() reads it a long at a time, so that is the
- * furthest the two scans reach. Bound it by the length the firmware
- * was told it may write, not by the buffer: the bytes past that are
- * still zero, and a zero bit here means a device is present.
+ * The second bitmap starts size bits into the event buffer, so that
+ * is the furthest the two walks reach. Bound it by the length the
+ * firmware was told it may write, not by the buffer: the bytes past
+ * that are still zero, and a zero bit here means a device is present.
*/
if (sizeof(*param) + (size >> 3) + BITS_TO_LONGS(size) * sizeof(long) >
sizeof(struct mvumi_event_req)) {
@@ -1672,25 +1671,19 @@ static void mvumi_proc_msg(struct mvumi_hba *mhba,
}
if (mhba->fw_flag & MVUMI_FW_ATTACH) {
- index = -1;
- ar_bitmap = (const unsigned long *) param->bitmap;
- re_bitmap = (const unsigned long *) ¶m->bitmap[size >> 3];
+ ar_bitmap = param->bitmap;
+ re_bitmap = ¶m->bitmap[size >> 3];
mutex_lock(&mhba->sas_discovery_mutex);
- do {
- index = find_next_zero_bit(ar_bitmap, size, index + 1);
- if (index >= size)
- break;
- mvumi_handle_hotplug(mhba, index, DEVICE_ONLINE);
- } while (1);
-
- index = -1;
- do {
- index = find_next_zero_bit(re_bitmap, size, index + 1);
- if (index >= size)
- break;
- mvumi_handle_hotplug(mhba, index, DEVICE_OFFLINE);
- } while (1);
+ for (index = 0; index < size; index++)
+ if (!(ar_bitmap[index >> 3] & (1 << (index & 7))))
+ mvumi_handle_hotplug(mhba, index,
+ DEVICE_ONLINE);
+
+ for (index = 0; index < size; index++)
+ if (!(re_bitmap[index >> 3] & (1 << (index & 7))))
+ mvumi_handle_hotplug(mhba, index,
+ DEVICE_OFFLINE);
mutex_unlock(&mhba->sas_discovery_mutex);
}
}
--
2.43.0