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