1219820Sjeff/* SPDX-License-Identifier: GPL-2.0 */ 2219820Sjeff#ifndef _X86_POSTED_INTR_H 3219820Sjeff#define _X86_POSTED_INTR_H 4272027Shselasky#include <asm/irq_vectors.h> 5219820Sjeff 6219820Sjeff#define POSTED_INTR_ON 0 7219820Sjeff#define POSTED_INTR_SN 1 8219820Sjeff 9219820Sjeff#define PID_TABLE_ENTRY_VALID 1 10219820Sjeff 11219820Sjeff/* Posted-Interrupt Descriptor */ 12219820Sjeffstruct pi_desc { 13219820Sjeff union { 14219820Sjeff u32 pir[8]; /* Posted interrupt requested */ 15219820Sjeff u64 pir64[4]; 16219820Sjeff }; 17219820Sjeff union { 18219820Sjeff struct { 19219820Sjeff u16 notifications; /* Suppress and outstanding bits */ 20219820Sjeff u8 nv; 21219820Sjeff u8 rsvd_2; 22219820Sjeff u32 ndst; 23219820Sjeff }; 24219820Sjeff u64 control; 25219820Sjeff }; 26219820Sjeff u32 rsvd[6]; 27219820Sjeff} __aligned(64); 28219820Sjeff 29219820Sjeffstatic inline bool pi_test_and_set_on(struct pi_desc *pi_desc) 30219820Sjeff{ 31219820Sjeff return test_and_set_bit(POSTED_INTR_ON, (unsigned long *)&pi_desc->control); 32219820Sjeff} 33219820Sjeff 34219820Sjeffstatic inline bool pi_test_and_clear_on(struct pi_desc *pi_desc) 35219820Sjeff{ 36272027Shselasky return test_and_clear_bit(POSTED_INTR_ON, (unsigned long *)&pi_desc->control); 37272027Shselasky} 38272027Shselasky 39272027Shselaskystatic inline bool pi_test_and_clear_sn(struct pi_desc *pi_desc) 40306486Shselasky{ 41306486Shselasky return test_and_clear_bit(POSTED_INTR_SN, (unsigned long *)&pi_desc->control); 42219820Sjeff} 43219820Sjeff 44219820Sjeffstatic inline bool pi_test_and_set_pir(int vector, struct pi_desc *pi_desc) 45219820Sjeff{ 46255932Salfred return test_and_set_bit(vector, (unsigned long *)pi_desc->pir); 47255932Salfred} 48255932Salfred 49255932Salfredstatic inline bool pi_is_pir_empty(struct pi_desc *pi_desc) 50255932Salfred{ 51255932Salfred return bitmap_empty((unsigned long *)pi_desc->pir, NR_VECTORS); 52219820Sjeff} 53219820Sjeff 54219820Sjeffstatic inline void pi_set_sn(struct pi_desc *pi_desc) 55219820Sjeff{ 56219820Sjeff set_bit(POSTED_INTR_SN, (unsigned long *)&pi_desc->control); 57219820Sjeff} 58219820Sjeff 59219820Sjeffstatic inline void pi_set_on(struct pi_desc *pi_desc) 60219820Sjeff{ 61219820Sjeff set_bit(POSTED_INTR_ON, (unsigned long *)&pi_desc->control); 62219820Sjeff} 63219820Sjeff 64219820Sjeffstatic inline void pi_clear_on(struct pi_desc *pi_desc) 65219820Sjeff{ 66255932Salfred clear_bit(POSTED_INTR_ON, (unsigned long *)&pi_desc->control); 67219820Sjeff} 68219820Sjeff 69219820Sjeffstatic inline void pi_clear_sn(struct pi_desc *pi_desc) 70219820Sjeff{ 71219820Sjeff clear_bit(POSTED_INTR_SN, (unsigned long *)&pi_desc->control); 72219820Sjeff} 73219820Sjeff 74219820Sjeffstatic inline bool pi_test_on(struct pi_desc *pi_desc) 75219820Sjeff{ 76255932Salfred return test_bit(POSTED_INTR_ON, (unsigned long *)&pi_desc->control); 77255932Salfred} 78219820Sjeff 79255932Salfredstatic inline bool pi_test_sn(struct pi_desc *pi_desc) 80255932Salfred{ 81255932Salfred return test_bit(POSTED_INTR_SN, (unsigned long *)&pi_desc->control); 82255932Salfred} 83255932Salfred 84255932Salfred/* Non-atomic helpers */ 85255932Salfredstatic inline void __pi_set_sn(struct pi_desc *pi_desc) 86255932Salfred{ 87255932Salfred pi_desc->notifications |= BIT(POSTED_INTR_SN); 88255932Salfred} 89255932Salfred 90255932Salfredstatic inline void __pi_clear_sn(struct pi_desc *pi_desc) 91255932Salfred{ 92255932Salfred pi_desc->notifications &= ~BIT(POSTED_INTR_SN); 93255932Salfred} 94255932Salfred 95255932Salfred#ifdef CONFIG_X86_POSTED_MSI 96219820Sjeff/* 97219820Sjeff * Not all external vectors are subject to interrupt remapping, e.g. IOMMU's 98219820Sjeff * own interrupts. Here we do not distinguish them since those vector bits in 99219820Sjeff * PIR will always be zero. 100219820Sjeff */ 101219820Sjeffstatic inline bool pi_pending_this_cpu(unsigned int vector) 102219820Sjeff{ 103219820Sjeff struct pi_desc *pid = this_cpu_ptr(&posted_msi_pi_desc); 104219820Sjeff 105219820Sjeff if (WARN_ON_ONCE(vector > NR_VECTORS || vector < FIRST_EXTERNAL_VECTOR)) 106219820Sjeff return false; 107219820Sjeff 108219820Sjeff return test_bit(vector, (unsigned long *)pid->pir); 109219820Sjeff} 110219820Sjeff 111219820Sjeffextern void intel_posted_msi_init(void); 112219820Sjeff#else 113219820Sjeffstatic inline bool pi_pending_this_cpu(unsigned int vector) { return false; } 114219820Sjeff 115219820Sjeffstatic inline void intel_posted_msi_init(void) {}; 116219820Sjeff#endif /* X86_POSTED_MSI */ 117219820Sjeff 118219820Sjeff#endif /* _X86_POSTED_INTR_H */ 119219820Sjeff