On 7. 10. 24 06:13, Suravee Suthikulpanit wrote:
+
/****************************************************************************
*
* Helper functions
*
****************************************************************************/
+static void write_dte_upper128(struct dev_table_entry *ptr, struct dev_table_entry *new)
+{
+ struct dev_table_entry old = {};
+
+ do {
+ old.data128[1] = ptr->data128[1];
+ new->data[2] &= ~DTE_DATA2_INTR_MASK;
+ new->data[2] |= old.data[2] & (DTE_DATA2_INTR_MASK | DTE_DATA2_RESV_MASK);
+ } while (!try_cmpxchg128(&ptr->data128[1], &old.data128[1], new->data128[1]));
Please note that try_cmpxchg inherently updates &old.data128[1] above on failure. There is no need to update value again in the loop.
Please also note that the value from ptr->data128[1] should be read using READ_ONCE() to prevent compiler from merging, refetching or reordering the read. Currently, there is no READ_ONCE() implemented for __int128, so something like the attached patch should be used.
Based on the above, the loop should be rewritten as:
old.data128[1] = READ_ONCE(ptr->data128[1]);
do {
new->data[2] &= ~DTE_DATA2_INTR_MASK;
new->data[2] |= old.data[2] & (DTE_DATA2_INTR_MASK | DTE_DATA2_RESV_MASK);
} while (!try_cmpxchg128(&ptr->data128[1], &old.data128[1], new->data128[1]));
+}
+
+static void write_dte_lower128(struct dev_table_entry *ptr, struct dev_table_entry *new)
+{
+ struct dev_table_entry old = {};
+
+ /*
+ * Need to preserve DTE[96:106], which can be set by information in IVRS table.
+ * See set_dev_entry_from_acpi().
+ */
+ new->data[1] |= ptr->data[1] & DTE_FLAG_MASK;
+
+ do {
+ old.data128[0] = ptr->data128[0];
+ } while (!try_cmpxchg128(&ptr->data128[0], &old.data128[0], new->data128[0]));
And this one as:
old.data128[0] = READ_ONCE(ptr->data128[0]);
do {
} while (!try_cmpxchg128(&ptr->data128[0], &old.data128[0], new->data128[0]));
Best regards,
Uros.