1bfcc09ddSBjoern A. Zeeb /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ 2bfcc09ddSBjoern A. Zeeb /* 3*a4128aadSBjoern A. Zeeb * Copyright (C) 2005-2014, 2023 Intel Corporation 4bfcc09ddSBjoern A. Zeeb * Copyright (C) 2015-2017 Intel Deutschland GmbH 5bfcc09ddSBjoern A. Zeeb */ 6bfcc09ddSBjoern A. Zeeb #ifndef __iwl_notif_wait_h__ 7bfcc09ddSBjoern A. Zeeb #define __iwl_notif_wait_h__ 8bfcc09ddSBjoern A. Zeeb 9bfcc09ddSBjoern A. Zeeb #include <linux/wait.h> 10bfcc09ddSBjoern A. Zeeb 11bfcc09ddSBjoern A. Zeeb #include "iwl-trans.h" 12bfcc09ddSBjoern A. Zeeb 13bfcc09ddSBjoern A. Zeeb struct iwl_notif_wait_data { 14bfcc09ddSBjoern A. Zeeb struct list_head notif_waits; 15bfcc09ddSBjoern A. Zeeb spinlock_t notif_wait_lock; 16bfcc09ddSBjoern A. Zeeb wait_queue_head_t notif_waitq; 17bfcc09ddSBjoern A. Zeeb }; 18bfcc09ddSBjoern A. Zeeb 19bfcc09ddSBjoern A. Zeeb #define MAX_NOTIF_CMDS 5 20bfcc09ddSBjoern A. Zeeb 21bfcc09ddSBjoern A. Zeeb /** 22bfcc09ddSBjoern A. Zeeb * struct iwl_notification_wait - notification wait entry 23bfcc09ddSBjoern A. Zeeb * @list: list head for global list 24bfcc09ddSBjoern A. Zeeb * @fn: Function called with the notification. If the function 25bfcc09ddSBjoern A. Zeeb * returns true, the wait is over, if it returns false then 26bfcc09ddSBjoern A. Zeeb * the waiter stays blocked. If no function is given, any 27bfcc09ddSBjoern A. Zeeb * of the listed commands will unblock the waiter. 28*a4128aadSBjoern A. Zeeb * @fn_data: pointer to pass to the @fn's data argument 29bfcc09ddSBjoern A. Zeeb * @cmds: command IDs 30bfcc09ddSBjoern A. Zeeb * @n_cmds: number of command IDs 31bfcc09ddSBjoern A. Zeeb * @triggered: waiter should be woken up 32bfcc09ddSBjoern A. Zeeb * @aborted: wait was aborted 33bfcc09ddSBjoern A. Zeeb * 34bfcc09ddSBjoern A. Zeeb * This structure is not used directly, to wait for a 35bfcc09ddSBjoern A. Zeeb * notification declare it on the stack, and call 36bfcc09ddSBjoern A. Zeeb * iwl_init_notification_wait() with appropriate 37bfcc09ddSBjoern A. Zeeb * parameters. Then do whatever will cause the ucode 38bfcc09ddSBjoern A. Zeeb * to notify the driver, and to wait for that then 39bfcc09ddSBjoern A. Zeeb * call iwl_wait_notification(). 40bfcc09ddSBjoern A. Zeeb * 41bfcc09ddSBjoern A. Zeeb * Each notification is one-shot. If at some point we 42bfcc09ddSBjoern A. Zeeb * need to support multi-shot notifications (which 43bfcc09ddSBjoern A. Zeeb * can't be allocated on the stack) we need to modify 44bfcc09ddSBjoern A. Zeeb * the code for them. 45bfcc09ddSBjoern A. Zeeb */ 46bfcc09ddSBjoern A. Zeeb struct iwl_notification_wait { 47bfcc09ddSBjoern A. Zeeb struct list_head list; 48bfcc09ddSBjoern A. Zeeb 49bfcc09ddSBjoern A. Zeeb bool (*fn)(struct iwl_notif_wait_data *notif_data, 50bfcc09ddSBjoern A. Zeeb struct iwl_rx_packet *pkt, void *data); 51bfcc09ddSBjoern A. Zeeb void *fn_data; 52bfcc09ddSBjoern A. Zeeb 53bfcc09ddSBjoern A. Zeeb u16 cmds[MAX_NOTIF_CMDS]; 54bfcc09ddSBjoern A. Zeeb u8 n_cmds; 55bfcc09ddSBjoern A. Zeeb bool triggered, aborted; 56bfcc09ddSBjoern A. Zeeb }; 57bfcc09ddSBjoern A. Zeeb 58bfcc09ddSBjoern A. Zeeb 59bfcc09ddSBjoern A. Zeeb /* caller functions */ 60bfcc09ddSBjoern A. Zeeb void iwl_notification_wait_init(struct iwl_notif_wait_data *notif_data); 61bfcc09ddSBjoern A. Zeeb bool iwl_notification_wait(struct iwl_notif_wait_data *notif_data, 62bfcc09ddSBjoern A. Zeeb struct iwl_rx_packet *pkt); 63bfcc09ddSBjoern A. Zeeb void iwl_abort_notification_waits(struct iwl_notif_wait_data *notif_data); 64bfcc09ddSBjoern A. Zeeb 65bfcc09ddSBjoern A. Zeeb static inline void 66bfcc09ddSBjoern A. Zeeb iwl_notification_notify(struct iwl_notif_wait_data *notif_data) 67bfcc09ddSBjoern A. Zeeb { 68bfcc09ddSBjoern A. Zeeb wake_up_all(¬if_data->notif_waitq); 69bfcc09ddSBjoern A. Zeeb } 70bfcc09ddSBjoern A. Zeeb 71bfcc09ddSBjoern A. Zeeb static inline void 72bfcc09ddSBjoern A. Zeeb iwl_notification_wait_notify(struct iwl_notif_wait_data *notif_data, 73bfcc09ddSBjoern A. Zeeb struct iwl_rx_packet *pkt) 74bfcc09ddSBjoern A. Zeeb { 75bfcc09ddSBjoern A. Zeeb if (iwl_notification_wait(notif_data, pkt)) 76bfcc09ddSBjoern A. Zeeb iwl_notification_notify(notif_data); 77bfcc09ddSBjoern A. Zeeb } 78bfcc09ddSBjoern A. Zeeb 79bfcc09ddSBjoern A. Zeeb /* user functions */ 80bfcc09ddSBjoern A. Zeeb void __acquires(wait_entry) 81bfcc09ddSBjoern A. Zeeb iwl_init_notification_wait(struct iwl_notif_wait_data *notif_data, 82bfcc09ddSBjoern A. Zeeb struct iwl_notification_wait *wait_entry, 83bfcc09ddSBjoern A. Zeeb const u16 *cmds, int n_cmds, 84bfcc09ddSBjoern A. Zeeb bool (*fn)(struct iwl_notif_wait_data *notif_data, 85bfcc09ddSBjoern A. Zeeb struct iwl_rx_packet *pkt, void *data), 86bfcc09ddSBjoern A. Zeeb void *fn_data); 87bfcc09ddSBjoern A. Zeeb 88bfcc09ddSBjoern A. Zeeb int __must_check __releases(wait_entry) 89bfcc09ddSBjoern A. Zeeb iwl_wait_notification(struct iwl_notif_wait_data *notif_data, 90bfcc09ddSBjoern A. Zeeb struct iwl_notification_wait *wait_entry, 91bfcc09ddSBjoern A. Zeeb unsigned long timeout); 92bfcc09ddSBjoern A. Zeeb 93bfcc09ddSBjoern A. Zeeb void __releases(wait_entry) 94bfcc09ddSBjoern A. Zeeb iwl_remove_notification(struct iwl_notif_wait_data *notif_data, 95bfcc09ddSBjoern A. Zeeb struct iwl_notification_wait *wait_entry); 96bfcc09ddSBjoern A. Zeeb 97bfcc09ddSBjoern A. Zeeb #endif /* __iwl_notif_wait_h__ */ 98