162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2005-2014 Intel Corporation 462306a36Sopenharmony_ci * Copyright (C) 2015-2017 Intel Deutschland GmbH 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci#ifndef __iwl_notif_wait_h__ 762306a36Sopenharmony_ci#define __iwl_notif_wait_h__ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/wait.h> 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include "iwl-trans.h" 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_cistruct iwl_notif_wait_data { 1462306a36Sopenharmony_ci struct list_head notif_waits; 1562306a36Sopenharmony_ci spinlock_t notif_wait_lock; 1662306a36Sopenharmony_ci wait_queue_head_t notif_waitq; 1762306a36Sopenharmony_ci}; 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#define MAX_NOTIF_CMDS 5 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci/** 2262306a36Sopenharmony_ci * struct iwl_notification_wait - notification wait entry 2362306a36Sopenharmony_ci * @list: list head for global list 2462306a36Sopenharmony_ci * @fn: Function called with the notification. If the function 2562306a36Sopenharmony_ci * returns true, the wait is over, if it returns false then 2662306a36Sopenharmony_ci * the waiter stays blocked. If no function is given, any 2762306a36Sopenharmony_ci * of the listed commands will unblock the waiter. 2862306a36Sopenharmony_ci * @cmds: command IDs 2962306a36Sopenharmony_ci * @n_cmds: number of command IDs 3062306a36Sopenharmony_ci * @triggered: waiter should be woken up 3162306a36Sopenharmony_ci * @aborted: wait was aborted 3262306a36Sopenharmony_ci * 3362306a36Sopenharmony_ci * This structure is not used directly, to wait for a 3462306a36Sopenharmony_ci * notification declare it on the stack, and call 3562306a36Sopenharmony_ci * iwl_init_notification_wait() with appropriate 3662306a36Sopenharmony_ci * parameters. Then do whatever will cause the ucode 3762306a36Sopenharmony_ci * to notify the driver, and to wait for that then 3862306a36Sopenharmony_ci * call iwl_wait_notification(). 3962306a36Sopenharmony_ci * 4062306a36Sopenharmony_ci * Each notification is one-shot. If at some point we 4162306a36Sopenharmony_ci * need to support multi-shot notifications (which 4262306a36Sopenharmony_ci * can't be allocated on the stack) we need to modify 4362306a36Sopenharmony_ci * the code for them. 4462306a36Sopenharmony_ci */ 4562306a36Sopenharmony_cistruct iwl_notification_wait { 4662306a36Sopenharmony_ci struct list_head list; 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci bool (*fn)(struct iwl_notif_wait_data *notif_data, 4962306a36Sopenharmony_ci struct iwl_rx_packet *pkt, void *data); 5062306a36Sopenharmony_ci void *fn_data; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci u16 cmds[MAX_NOTIF_CMDS]; 5362306a36Sopenharmony_ci u8 n_cmds; 5462306a36Sopenharmony_ci bool triggered, aborted; 5562306a36Sopenharmony_ci}; 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci/* caller functions */ 5962306a36Sopenharmony_civoid iwl_notification_wait_init(struct iwl_notif_wait_data *notif_data); 6062306a36Sopenharmony_cibool iwl_notification_wait(struct iwl_notif_wait_data *notif_data, 6162306a36Sopenharmony_ci struct iwl_rx_packet *pkt); 6262306a36Sopenharmony_civoid iwl_abort_notification_waits(struct iwl_notif_wait_data *notif_data); 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_cistatic inline void 6562306a36Sopenharmony_ciiwl_notification_notify(struct iwl_notif_wait_data *notif_data) 6662306a36Sopenharmony_ci{ 6762306a36Sopenharmony_ci wake_up_all(¬if_data->notif_waitq); 6862306a36Sopenharmony_ci} 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_cistatic inline void 7162306a36Sopenharmony_ciiwl_notification_wait_notify(struct iwl_notif_wait_data *notif_data, 7262306a36Sopenharmony_ci struct iwl_rx_packet *pkt) 7362306a36Sopenharmony_ci{ 7462306a36Sopenharmony_ci if (iwl_notification_wait(notif_data, pkt)) 7562306a36Sopenharmony_ci iwl_notification_notify(notif_data); 7662306a36Sopenharmony_ci} 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci/* user functions */ 7962306a36Sopenharmony_civoid __acquires(wait_entry) 8062306a36Sopenharmony_ciiwl_init_notification_wait(struct iwl_notif_wait_data *notif_data, 8162306a36Sopenharmony_ci struct iwl_notification_wait *wait_entry, 8262306a36Sopenharmony_ci const u16 *cmds, int n_cmds, 8362306a36Sopenharmony_ci bool (*fn)(struct iwl_notif_wait_data *notif_data, 8462306a36Sopenharmony_ci struct iwl_rx_packet *pkt, void *data), 8562306a36Sopenharmony_ci void *fn_data); 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ciint __must_check __releases(wait_entry) 8862306a36Sopenharmony_ciiwl_wait_notification(struct iwl_notif_wait_data *notif_data, 8962306a36Sopenharmony_ci struct iwl_notification_wait *wait_entry, 9062306a36Sopenharmony_ci unsigned long timeout); 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_civoid __releases(wait_entry) 9362306a36Sopenharmony_ciiwl_remove_notification(struct iwl_notif_wait_data *notif_data, 9462306a36Sopenharmony_ci struct iwl_notification_wait *wait_entry); 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci#endif /* __iwl_notif_wait_h__ */ 97