#include <linux/bitfield.h>
#include <linux/bitmap.h>
-#include <linux/bits.h>
+#include <linux/bitops.h>
#include <linux/cleanup.h>
#include <linux/container_of.h>
#include <linux/delay.h>
acpm_get_saved_rx(achan, xfer, seqnum);
/* Relinquish ownership of the sequence slot */
- clear_bit(seqnum - 1, achan->bitmap_seqnum);
+ clear_bit_unlock(seqnum - 1, achan->bitmap_seqnum);
return 0;
}
struct acpm_rx_data *rx_data;
u32 *txd = (u32 *)xfer->txd;
- /* Prevent chan->seqnum from being re-used */
+ /*
+ * Prevent chan->seqnum from being re-used.
+ * test_and_set_bit_lock() provides formal LKMM Acquire semantics.
+ * It pairs with the RX thread's clear_bit_unlock() to ensure the CPU
+ * does not speculatively execute the rx_data buffer wipe (memset)
+ * before the sequence number is safely claimed.
+ */
do {
if (++achan->seqnum == ACPM_SEQNUM_MAX)
achan->seqnum = 1;
- } while (test_bit(achan->seqnum - 1, achan->bitmap_seqnum));
+ /* Flag the index based on seqnum. (seqnum: 1~63, bitmap: 0~62) */
+ } while (test_and_set_bit_lock(achan->seqnum - 1, achan->bitmap_seqnum));
txd[0] |= FIELD_PREP(ACPM_PROTOCOL_SEQNUM, achan->seqnum);
memset(rx_data->cmd, 0, sizeof(*rx_data->cmd) * rx_data->n_cmd);
/* zero means no response expected */
rx_data->rxcnt = xfer->rxcnt;
-
- /* Flag the index based on seqnum. (seqnum: 1~63, bitmap: 0~62) */
- set_bit(achan->seqnum - 1, achan->bitmap_seqnum);
}
/**