|
@@ -243,8 +243,10 @@ struct cxl *cxl_alloc_adapter(void)
|
|
|
if (dev_set_name(&adapter->dev, "card%i", adapter->adapter_num))
|
|
|
goto err2;
|
|
|
|
|
|
- return adapter;
|
|
|
+ /* start with context lock taken */
|
|
|
+ atomic_set(&adapter->contexts_num, -1);
|
|
|
|
|
|
+ return adapter;
|
|
|
err2:
|
|
|
cxl_remove_adapter_nr(adapter);
|
|
|
err1:
|
|
@@ -286,6 +288,44 @@ int cxl_afu_select_best_mode(struct cxl_afu *afu)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+int cxl_adapter_context_get(struct cxl *adapter)
|
|
|
+{
|
|
|
+ int rc;
|
|
|
+
|
|
|
+ rc = atomic_inc_unless_negative(&adapter->contexts_num);
|
|
|
+ return rc >= 0 ? 0 : -EBUSY;
|
|
|
+}
|
|
|
+
|
|
|
+void cxl_adapter_context_put(struct cxl *adapter)
|
|
|
+{
|
|
|
+ atomic_dec_if_positive(&adapter->contexts_num);
|
|
|
+}
|
|
|
+
|
|
|
+int cxl_adapter_context_lock(struct cxl *adapter)
|
|
|
+{
|
|
|
+ int rc;
|
|
|
+ /* no active contexts -> contexts_num == 0 */
|
|
|
+ rc = atomic_cmpxchg(&adapter->contexts_num, 0, -1);
|
|
|
+ return rc ? -EBUSY : 0;
|
|
|
+}
|
|
|
+
|
|
|
+void cxl_adapter_context_unlock(struct cxl *adapter)
|
|
|
+{
|
|
|
+ int val = atomic_cmpxchg(&adapter->contexts_num, -1, 0);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * contexts lock taken -> contexts_num == -1
|
|
|
+ * If not true then show a warning and force reset the lock.
|
|
|
+ * This will happen when context_unlock was requested without
|
|
|
+ * doing a context_lock.
|
|
|
+ */
|
|
|
+ if (val != -1) {
|
|
|
+ atomic_set(&adapter->contexts_num, 0);
|
|
|
+ WARN(1, "Adapter context unlocked with %d active contexts",
|
|
|
+ val);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
static int __init init_cxl(void)
|
|
|
{
|
|
|
int rc = 0;
|