Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a5d7a7b3 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "haven: dbl: Make hh_dbl_ functions wait for capid availability"

parents 846ffba2 23f7911b
Loading
Loading
Loading
Loading
+61 −19
Original line number Diff line number Diff line
@@ -10,7 +10,6 @@
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/haven/hh_common.h>
#include <linux/haven/hh_rm_drv.h>

#include <soc/qcom/subsystem_notif.h>
@@ -31,12 +30,13 @@ static struct kobj_type guestvm_kobj_type = {
};

struct guestvm_loader_private {
	struct work_struct vm_loader_work;
	struct notifier_block guestvm_nb;
	struct kobject vm_loader_kobj;
	struct device *dev;
	char vm_name[MAX_LEN];
	void *vm_loaded;
	int vmid;
	u8 vm_status;
};

static inline enum hh_vm_names get_hh_vm_name(const char *str)
@@ -50,24 +50,50 @@ static inline enum hh_vm_names get_hh_vm_name(const char *str)
	return HH_VM_MAX;
}

static void guestvm_loader_rm_notifier(struct work_struct *vm_loader_work)
static int guestvm_loader_nb_handler(struct notifier_block *this,
					unsigned long cmd, void *data)
{
	struct guestvm_loader_private *priv;
	int ret = 0;
	struct hh_rm_notif_vm_status_payload *vm_status_payload = data;
	u8 vm_status = vm_status_payload->vm_status;
	int ret;

	priv = container_of(vm_loader_work, struct guestvm_loader_private,
				vm_loader_work);
	priv->vmid = hh_rm_vm_alloc_vmid(get_hh_vm_name(priv->vm_name));
	if (priv->vmid == HH_VM_MAX) {
		dev_err(priv->dev, "Couldn't get vmid.\n");
		return;
	priv = container_of(this, struct guestvm_loader_private, guestvm_nb);

	if (cmd != HH_RM_NOTIF_VM_STATUS)
		return NOTIFY_DONE;

	if (priv->vmid != vm_status_payload->vmid)
		dev_warn(priv->dev, "Expected a notification from vmid = %d, but received one from vmid = %d\n",
				priv->vmid, vm_status_payload->vmid);

	/*
	 * Listen to STATUS_READY or STATUS_RUNNING notifications from RM.
	 * These notifications come from RM after PIL loading the VM images.
	 * Query GET_HYP_RESOURCES to populate other entities such as MessageQ
	 * and DBL.
	 */
	switch (vm_status) {
	case HH_RM_VM_STATUS_READY:
		priv->vm_status = HH_RM_VM_STATUS_READY;
		ret = hh_rm_populate_hyp_res(vm_status_payload->vmid);
		if (ret < 0) {
			dev_err(priv->dev, "Failed to get hyp resources for vmid = %d ret = %d\n",
				vm_status_payload->vmid, ret);
			return NOTIFY_DONE;
		}
	ret = hh_rm_vm_start(priv->vmid);
	if (ret)
		dev_err(priv->dev, "VM start has failed with %d.\n", ret);
		break;
	case HH_RM_VM_STATUS_RUNNING:
		break;
	default:
		dev_err(priv->dev, "Unknown notification receieved for vmid = %d vm_status = %d\n",
				vm_status_payload->vmid, vm_status);
	}

	return NOTIFY_DONE;
}

static ssize_t guestvm_load_start(struct kobject *kobj,
static ssize_t guestvm_loader_start(struct kobject *kobj,
	struct kobj_attribute *attr,
	const char *buf,
	size_t count)
@@ -88,6 +114,13 @@ static ssize_t guestvm_load_start(struct kobject *kobj,
	}

	if (boot) {
		priv->vm_status = HH_RM_VM_STATUS_INIT;
		priv->vmid = hh_rm_vm_alloc_vmid(get_hh_vm_name(priv->vm_name));
		if (priv->vmid < 0) {
			dev_err(priv->dev, "Couldn't allocate VMID.\n");
			return count;
		}

		priv->vm_loaded = subsystem_get(priv->vm_name);
		if (IS_ERR(priv->vm_loaded)) {
			ret = (int)(PTR_ERR(priv->vm_loaded));
@@ -96,13 +129,18 @@ static ssize_t guestvm_load_start(struct kobject *kobj,
			priv->vm_loaded = NULL;
			return ret;
		}
		schedule_work(&priv->vm_loader_work);

		priv->vm_status = HH_RM_VM_STATUS_RUNNING;
		ret = hh_rm_vm_start(priv->vmid);
		if (ret)
			dev_err(priv->dev, "VM start has failed for vmid = %d ret = %d\n",
				priv->vmid, ret);
	}

	return count;
}
static struct kobj_attribute guestvm_loader_attribute =
__ATTR(boot_guestvm, 0220, NULL, guestvm_load_start);
__ATTR(boot_guestvm, 0220, NULL, guestvm_loader_start);

static struct attribute *attrs[] = {
	&guestvm_loader_attribute.attr,
@@ -132,8 +170,6 @@ static int guestvm_loader_probe(struct platform_device *pdev)
		return -EINVAL;
	strlcpy(priv->vm_name, sub_sys, sizeof(priv->vm_name));

	INIT_WORK(&priv->vm_loader_work, guestvm_loader_rm_notifier);

	ret = kobject_init_and_add(&priv->vm_loader_kobj, &guestvm_kobj_type,
				   kernel_kobj, "load_guestvm");
	if (ret) {
@@ -148,6 +184,12 @@ static int guestvm_loader_probe(struct platform_device *pdev)
		goto error_return;
	}

	priv->guestvm_nb.notifier_call = guestvm_loader_nb_handler;
	ret = hh_rm_register_notifier(&priv->guestvm_nb);
	if (ret)
		return ret;

	priv->vm_status = HH_RM_VM_STATUS_NO_STATE;
	return 0;

error_return:
+79 −40
Original line number Diff line number Diff line
@@ -34,19 +34,21 @@ struct hh_dbl_cap_table {
	const char *rx_irq_name;
	dbl_rx_cb_t rx_callback;
	void *rx_priv_data;
	wait_queue_head_t cap_wq;
};

static bool hh_dbl_initialized;
static struct hh_dbl_cap_table hh_dbl_cap_table[HH_DBL_LABEL_MAX];

/**
 * hh_dbl_validate_params - Validate doorbell common parameters
 */
static int hh_dbl_validate_params(struct hh_dbl_desc *client_desc,
				  enum hh_dbl_dir dir)
			enum hh_dbl_dir dir, const unsigned long flags)
{
	struct hh_dbl_cap_table *cap_table_entry;

	if (!client_desc)
	if (IS_ERR_OR_NULL(client_desc))
		return -EINVAL;

	/* Check if the client has manipulated the label */
@@ -67,23 +69,35 @@ static int hh_dbl_validate_params(struct hh_dbl_desc *client_desc,
	 * There are no doorbell setup for Tx or Rx
	 */
	if (dir == HH_DBL_DIRECTION_RX) {
		if (!cap_table_entry->rx_cap_id ||
		    !cap_table_entry->rx_reg_done) {
			pr_err("%s: label: %d; rx_cap_id: %llu; dir: %d rx_done: %d\n",
				__func__, client_desc->label,
				cap_table_entry->rx_cap_id,
				dir, cap_table_entry->rx_reg_done);
		if (!cap_table_entry->rx_reg_done)
			return -EINVAL;

		if (cap_table_entry->rx_cap_id != HH_CAPID_INVAL)
			return 0;

		if (flags & HH_DBL_NONBLOCK)
			return -EAGAIN;
		}

		if (wait_event_interruptible(cap_table_entry->cap_wq,
				cap_table_entry->rx_cap_id != HH_CAPID_INVAL))
			return -ERESTARTSYS;

		return 0;
	} else {
		if (!cap_table_entry->tx_cap_id ||
		    !cap_table_entry->tx_reg_done) {
			pr_err("%s: label: %d; tx_cap_id: %llu; dir: %d tx_done: %d\n",
				__func__, client_desc->label,
				cap_table_entry->tx_cap_id,
				dir, cap_table_entry->tx_reg_done);
		if (!cap_table_entry->tx_reg_done)
			return -EINVAL;

		if (cap_table_entry->tx_cap_id != HH_CAPID_INVAL)
			return 0;

		if (flags & HH_DBL_NONBLOCK)
			return -EAGAIN;
		}

		if (wait_event_interruptible(cap_table_entry->cap_wq,
				cap_table_entry->tx_cap_id != HH_CAPID_INVAL))
			return -ERESTARTSYS;

		return 0;
	}

	return 0;
@@ -93,6 +107,8 @@ static int hh_dbl_validate_params(struct hh_dbl_desc *client_desc,
 * hh_dbl_read_and_clean - Automatically read and clear the flags in doorbell
 * @client_desc: client handle to indetify the doorbell object
 * @clear_flags: clear the bits mentioned in the clear_flags
 * @flags: Optional flags to pass to send the data. For the list of flags,
 *         see linux/haven/hh_dbl.h
 *
 * Reads and clears the flags of the Doorbell object. If there is a pending
 * bound virtual interrupt, it will be de-asserted
@@ -101,7 +117,8 @@ static int hh_dbl_validate_params(struct hh_dbl_desc *client_desc,
 * 0 on success, @clear_flags contains the doorbell’s previous unmasked flags
 * before the @clear_flags were removed.
 */
int hh_dbl_read_and_clean(void *dbl_client_desc, hh_dbl_flags_t *clear_flags)
int hh_dbl_read_and_clean(void *dbl_client_desc, hh_dbl_flags_t *clear_flags,
			  const unsigned long flags)
{
	struct hh_dbl_cap_table *cap_table_entry;
	struct hh_hcall_dbl_recv_resp recv_resp;
@@ -111,7 +128,7 @@ int hh_dbl_read_and_clean(void *dbl_client_desc, hh_dbl_flags_t *clear_flags)
	if (!clear_flags)
		return -EINVAL;

	ret = hh_dbl_validate_params(client_desc, HH_DBL_DIRECTION_RX);
	ret = hh_dbl_validate_params(client_desc, HH_DBL_DIRECTION_RX, flags);
	if (ret)
		return ret;

@@ -137,6 +154,8 @@ EXPORT_SYMBOL(hh_dbl_read_and_clean);
 *				 the doorbell's bound virtual interrupt
 * @ack_mask: Controls which flags should be automatically cleared
 *			  when the interrupt is asserted
 * @flags: Optional flags to pass to send the data. For the list of flags,
 *         see linux/haven/hh_dbl.h
 *
 * Sets the Doorbell object’s masks. A doorbell object has two masks
 * which are configured by the receiver to control which flags it is
@@ -146,13 +165,13 @@ EXPORT_SYMBOL(hh_dbl_read_and_clean);
 * 0 on success
 */
int hh_dbl_set_mask(void *dbl_client_desc, hh_dbl_flags_t enable_mask,
						hh_dbl_flags_t ack_mask)
		    hh_dbl_flags_t ack_mask, const unsigned long flags)
{
	struct hh_dbl_cap_table *cap_table_entry;
	struct hh_dbl_desc *client_desc = dbl_client_desc;
	int ret, hh_ret;

	ret = hh_dbl_validate_params(client_desc, HH_DBL_DIRECTION_RX);
	ret = hh_dbl_validate_params(client_desc, HH_DBL_DIRECTION_RX, flags);
	if (ret)
		return ret;

@@ -176,6 +195,8 @@ EXPORT_SYMBOL(hh_dbl_set_mask);
 * @client_desc: client handle to indetify the doorbell object
 * @newflags: flags to set in the doorbell. This flag along with enable_mask
 *			  in the doorbell decide whehter to raise vIRQ are not.
 * @flags: Optional flags to pass to send the data. For the list of flags,
 *         see linux/haven/hh_dbl.h
 *
 * Set flags in the doorbell. If following the send, the set of enabled flags
 * as defined by the bitwise-AND of the doorbell flags with the EnableMask,
@@ -185,7 +206,8 @@ EXPORT_SYMBOL(hh_dbl_set_mask);
 * 0 on success, @newflags contains the doorbell’s previous unmasked flags
 * before the @newflags were added.
 */
int hh_dbl_send(void *dbl_client_desc, hh_dbl_flags_t *newflags)
int hh_dbl_send(void *dbl_client_desc, hh_dbl_flags_t *newflags,
		unsigned long flags)
{
	struct hh_dbl_cap_table *cap_table_entry;
	struct hh_hcall_dbl_send_resp send_resp;
@@ -195,7 +217,7 @@ int hh_dbl_send(void *dbl_client_desc, hh_dbl_flags_t *newflags)
	if (!newflags)
		return -EINVAL;

	ret = hh_dbl_validate_params(client_desc, HH_DBL_DIRECTION_TX);
	ret = hh_dbl_validate_params(client_desc, HH_DBL_DIRECTION_TX, flags);
	if (ret)
		return ret;

@@ -218,6 +240,8 @@ EXPORT_SYMBOL(hh_dbl_send);
 * hh_dbl_reset - clear all the flags of the doorbell and sets all bits in
 *				  the Doorbell’s mask.
 * @client_desc: client handle to indetify the doorbell object
 * @flags: Optional flags to pass to send the data. For the list of flags,
 *         see linux/haven/hh_dbl.h
 *
 * Clears all the flags of the doorbell and sets all bits in the doorbell’s
 * mask. If there is a pending bound virtual interrupt, it will be de-asserted.
@@ -225,13 +249,13 @@ EXPORT_SYMBOL(hh_dbl_send);
 * Returns:
 * 0 on success
 */
int hh_dbl_reset(void *dbl_client_desc)
int hh_dbl_reset(void *dbl_client_desc, const unsigned long flags)
{
	struct hh_dbl_cap_table *cap_table_entry;
	struct hh_dbl_desc *client_desc = dbl_client_desc;
	int ret, hh_ret;

	ret = hh_dbl_validate_params(client_desc, HH_DBL_DIRECTION_RX);
	ret = hh_dbl_validate_params(client_desc, HH_DBL_DIRECTION_RX, flags);
	if (ret)
		return ret;

@@ -278,6 +302,9 @@ void *hh_dbl_tx_register(enum hh_dbl_label label)
	if (label < 0 || label >= HH_DBL_LABEL_MAX)
		return ERR_PTR(-EINVAL);

	if (!hh_dbl_initialized)
		return ERR_PTR(-EPROBE_DEFER);

	cap_table_entry = &hh_dbl_cap_table[label];

	if (mutex_lock_interruptible(&cap_table_entry->cap_entry_lock))
@@ -338,6 +365,9 @@ void *hh_dbl_rx_register(enum hh_dbl_label label, dbl_rx_cb_t rx_cb, void *priv)
	if (label < 0 || label >= HH_DBL_LABEL_MAX)
		return ERR_PTR(-EINVAL);

	if (!hh_dbl_initialized)
		return ERR_PTR(-EPROBE_DEFER);

	cap_table_entry = &hh_dbl_cap_table[label];

	if (mutex_lock_interruptible(&cap_table_entry->cap_entry_lock))
@@ -365,20 +395,6 @@ void *hh_dbl_rx_register(enum hh_dbl_label label, dbl_rx_cb_t rx_cb, void *priv)
	cap_table_entry->rx_callback = rx_cb;
	cap_table_entry->rx_priv_data = priv;

	ret = request_threaded_irq(cap_table_entry->rx_irq,
				   NULL,
				   hh_dbl_rx_callback_thread,
				   IRQF_ONESHOT,
				   cap_table_entry->rx_irq_name,
				   cap_table_entry);

	if (ret < 0) {
		pr_err("%s: IRQ registration failed\n", __func__);
		cap_table_entry->rx_callback = NULL;
		cap_table_entry->rx_priv_data = NULL;
		goto err;
	}

	cap_table_entry->rx_reg_done = 1;

	pr_debug("%s: Registered Rx client for label: %d\n", __func__, label);
@@ -407,7 +423,7 @@ int hh_dbl_tx_unregister(void *dbl_client_desc)
	struct hh_dbl_desc *client_desc = dbl_client_desc;
	struct hh_dbl_cap_table *cap_table_entry;

	if (!client_desc)
	if (IS_ERR_OR_NULL(client_desc))
		return -EINVAL;

	/* Check if the client has manipulated the label */
@@ -458,7 +474,7 @@ int hh_dbl_rx_unregister(void *dbl_client_desc)
	struct hh_dbl_desc *client_desc = dbl_client_desc;
	struct hh_dbl_cap_table *cap_table_entry;

	if (!client_desc)
	if (IS_ERR_OR_NULL(client_desc))
		return -EINVAL;

	/* Check if the client has manipulated the label */
@@ -525,6 +541,9 @@ int hh_dbl_populate_cap_info(enum hh_dbl_label label, u64 cap_id,
			goto err;
		}
		cap_table_entry->tx_cap_id = cap_id;

		wake_up_interruptible(&cap_table_entry->cap_wq);

		pr_debug("%s: label: %d; tx_cap_id: %llu; dir: %d; rx_irq: %d\n",
			__func__, label, cap_id, direction, rx_irq);
		break;
@@ -537,6 +556,21 @@ int hh_dbl_populate_cap_info(enum hh_dbl_label label, u64 cap_id,
		}
		cap_table_entry->rx_cap_id = cap_id;
		cap_table_entry->rx_irq = rx_irq;

		ret = request_threaded_irq(cap_table_entry->rx_irq,
				   NULL,
				   hh_dbl_rx_callback_thread,
				   IRQF_ONESHOT | IRQF_TRIGGER_RISING,
				   cap_table_entry->rx_irq_name,
				   cap_table_entry);

		if (ret < 0) {
			pr_err("%s: IRQ registration failed\n", __func__);
			goto err;
		}

		wake_up_interruptible(&cap_table_entry->cap_wq);

		pr_debug("%s: label: %d; rx_cap_id: %llu; dir: %d; rx_irq: %d\n",
			__func__, label, cap_id, direction, rx_irq);
		break;
@@ -575,6 +609,9 @@ static int __init hh_dbl_init(void)
	for (i = 0; i < HH_DBL_LABEL_MAX; i++) {
		entry = &hh_dbl_cap_table[i];
		mutex_init(&entry->cap_entry_lock);
		init_waitqueue_head(&entry->cap_wq);
		entry->tx_cap_id = HH_CAPID_INVAL;
		entry->rx_cap_id = HH_CAPID_INVAL;
		entry->rx_irq_name = kasprintf(GFP_KERNEL, "hh_dbl_rx_%d", i);
		if (!entry->rx_irq_name) {
			ret = -ENOMEM;
@@ -582,6 +619,8 @@ static int __init hh_dbl_init(void)
		}
	}

	hh_dbl_initialized = true;

	return 0;

err:
+10 −20
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include <linux/haven/hh_msgq.h>
#include <linux/haven/hh_errno.h>
#include <linux/haven/hh_common.h>
#include <linux/haven/hh_rm_drv.h>

#include "hh_rm_drv_private.h"

@@ -66,8 +67,6 @@ SRCU_NOTIFIER_HEAD_STATIC(hh_rm_notifier);
static void hh_rm_get_svm_res_work_fn(struct work_struct *work);
static DECLARE_WORK(hh_rm_get_svm_res_work, hh_rm_get_svm_res_work_fn);

static int hh_rm_populate_hyp_res(hh_vmid_t vmid);

static struct hh_rm_connection *hh_rm_alloc_connection(u32 msg_id)
{
	struct hh_rm_connection *connection;
@@ -124,21 +123,6 @@ int hh_rm_unregister_notifier(struct notifier_block *nb)
}
EXPORT_SYMBOL(hh_rm_unregister_notifier);

static int hh_rm_process_notif_vm_status(void *recv_buff, size_t recv_buff_size)
{
	struct hh_rm_notif_vm_status_payload *vm_status_payload;

	vm_status_payload = recv_buff + sizeof(struct hh_rm_rpc_hdr);

	/* The VM is now booting. Collect it's info and
	 * populate to other entities such as MessageQ and DBL
	 */
	if (vm_status_payload->vm_status == HH_RM_OS_STATUS_BOOT)
		return hh_rm_populate_hyp_res(vm_status_payload->vmid);

	return 0;
}

static struct hh_rm_connection *
hh_rm_wait_for_notif_fragments(void *recv_buff, size_t recv_buff_size)
{
@@ -214,8 +198,6 @@ static int hh_rm_process_notif(void *recv_buff, size_t recv_buff_size)
			ret = -EINVAL;
			goto err;
		}

		ret = hh_rm_process_notif_vm_status(recv_buff, recv_buff_size);
		break;
	case HH_RM_NOTIF_VM_IRQ_LENT:
		if (recv_buff_size != sizeof(*hdr) +
@@ -699,7 +681,14 @@ static int hh_rm_get_irq(struct hh_vm_get_hyp_res_resp_entry *res_entry)
	return ret;
}

static int hh_rm_populate_hyp_res(hh_vmid_t vmid)
/**
 * hh_rm_populate_hyp_res: Query Resource Manager VM to get hyp resources.
 * @vmid: The vmid of resources to be queried.
 *
 * The function encodes the error codes via ERR_PTR. Hence, the caller is
 * responsible to check it with IS_ERR_OR_NULL().
 */
int hh_rm_populate_hyp_res(hh_vmid_t vmid)
{
	struct hh_vm_get_hyp_res_resp_entry *res_entries = NULL;
	int linux_irq, ret = 0;
@@ -769,6 +758,7 @@ static int hh_rm_populate_hyp_res(hh_vmid_t vmid)
	kfree(res_entries);
	return ret;
}
EXPORT_SYMBOL(hh_rm_populate_hyp_res);

static void hh_rm_get_svm_res_work_fn(struct work_struct *work)
{
+2 −2
Original line number Diff line number Diff line
@@ -506,13 +506,13 @@ int hh_rm_vm_start(int vmid)
				&resp_payload_size, &reply_err_code);
	if (reply_err_code || IS_ERR_OR_NULL(resp_payload)) {
		err = PTR_ERR(resp_payload);
		pr_err("%s: VM_ALLOCATE failed with err: %d\n",
		pr_err("%s: VM_START failed with err: %d\n",
			__func__, err);
		return err;
	}

	if (resp_payload_size != sizeof(*resp_payload)) {
		pr_err("%s: Invalid size received for VM_IRQ_ACCEPT: %u\n",
		pr_err("%s: Invalid size received for VM_START: %u\n",
			__func__, resp_payload_size);
		kfree(resp_payload);
		return -EINVAL;
+16 −8
Original line number Diff line number Diff line
@@ -19,6 +19,9 @@ enum hh_dbl_label {
	HH_DBL_LABEL_MAX
};

/* Possible flags to pass for send, set_mask, read, reset */
#define HH_DBL_NONBLOCK		BIT(32)

#if IS_ENABLED(CONFIG_HH_DBL)
void *hh_dbl_tx_register(enum hh_dbl_label label);
void *hh_dbl_rx_register(enum hh_dbl_label label, dbl_rx_cb_t rx_cb,
@@ -27,11 +30,13 @@ void *hh_dbl_rx_register(enum hh_dbl_label label, dbl_rx_cb_t rx_cb,
int hh_dbl_tx_unregister(void *dbl_client_desc);
int hh_dbl_rx_unregister(void *dbl_client_desc);

int hh_dbl_send(void *dbl_client_desc, uint64_t *newflags);
int hh_dbl_send(void *dbl_client_desc, uint64_t *newflags,
		const unsigned long flags);
int hh_dbl_set_mask(void *dbl_client_desc, hh_dbl_flags_t enable_mask,
		    hh_dbl_flags_t ack_mask);
int hh_dbl_read_and_clean(void *dbl_client_desc, hh_dbl_flags_t *clear_flags);
int hh_dbl_reset(void *dbl_client_desc);
		    hh_dbl_flags_t ack_mask, const unsigned long flags);
int hh_dbl_read_and_clean(void *dbl_client_desc, hh_dbl_flags_t *clear_flags,
			  const unsigned long flags);
int hh_dbl_reset(void *dbl_client_desc, const unsigned long flags);
int hh_dbl_populate_cap_info(enum hh_dbl_label label, u64 cap_id,
						int direction, int rx_irq);
#else
@@ -57,25 +62,28 @@ static inline int hh_dbl_rx_unregister(void *dbl_client_desc)
	return ERR_PTR(-ENODEV);
}

static inline int hh_dbl_send(void *dbl_client_desc, uint64_t *newflags)
static inline int hh_dbl_send(void *dbl_client_desc, uint64_t *newflags,
			      const unsigned long flags)
{
	return -EINVAL;
}

static inline int hh_dbl_set_mask(void *dbl_client_desc,
		    hh_dbl_flags_t enable_mask,
		    hh_dbl_flags_t ack_mask)
		    hh_dbl_flags_t ack_mask,
		    const unsigned long flags)
{
	return -EINVAL;
}

static inline int hh_dbl_read_and_clean(void *dbl_client_desc,
					hh_dbl_flags_t *clear_flags)
					hh_dbl_flags_t *clear_flags,
					const unsigned long flags)
{
	return -EINVAL;
}

static inline int hh_dbl_reset(void *dbl_client_desc)
static inline int hh_dbl_reset(void *dbl_client_desc, const unsigned long flags)
{
	return -EINVAL;
}
Loading