s390/ap: rework to use irq info from ap queue status
authorHarald Freudenberger <freude@linux.ibm.com>
Mon, 23 Oct 2023 12:50:11 +0000 (14:50 +0200)
committerVasily Gorbik <gor@linux.ibm.com>
Sun, 5 Nov 2023 21:34:57 +0000 (22:34 +0100)
This patch reworks the irq handling and reporting code
for the AP queue interrupt handling to always use the
irq info from the queue status.

Until now the interrupt status of an AP queue was stored
into a bool variable within the ap_queue struct. This
variable was set on a successful interrupt enablement
and cleared with kicking a reset. However, it may be
that the interrupt state is manipulated outband for
example by a hypervisor. This patch removes this variable
and instead the irq bit from the AP queue status which is
always reflecting the current irq state is used.

Reviewed-by: Tony Krowiak <akrowiak@linux.ibm.com>
Reviewed-by: Holger Dengler <dengler@linux.ibm.com>
Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
drivers/s390/crypto/ap_bus.h
drivers/s390/crypto/ap_queue.c

index 359a35f894d5189bc8ec2142a532a9d0b72684c7..b0771ca0849b99dec76ac84c07b85e28d5809312 100644 (file)
@@ -206,7 +206,6 @@ struct ap_queue {
        bool config;                    /* configured state */
        bool chkstop;                   /* checkstop state */
        ap_qid_t qid;                   /* AP queue id. */
-       bool interrupt;                 /* indicate if interrupts are enabled */
        bool se_bound;                  /* SE bound state */
        unsigned int assoc_idx;         /* SE association index */
        int queue_count;                /* # messages currently on AP queue. */
index 993240370ecf7c478639849d12716bb388b5815f..f1abd21661dc393755134bd2c133ea9fe9301f4f 100644 (file)
@@ -203,7 +203,7 @@ static enum ap_sm_wait ap_sm_read(struct ap_queue *aq)
                return AP_SM_WAIT_NONE;
        case AP_RESPONSE_NO_PENDING_REPLY:
                if (aq->queue_count > 0)
-                       return aq->interrupt ?
+                       return status.irq_enabled ?
                                AP_SM_WAIT_INTERRUPT : AP_SM_WAIT_HIGH_TIMEOUT;
                aq->sm_state = AP_SM_STATE_IDLE;
                return AP_SM_WAIT_NONE;
@@ -254,7 +254,7 @@ static enum ap_sm_wait ap_sm_write(struct ap_queue *aq)
                fallthrough;
        case AP_RESPONSE_Q_FULL:
                aq->sm_state = AP_SM_STATE_QUEUE_FULL;
-               return aq->interrupt ?
+               return status.irq_enabled ?
                        AP_SM_WAIT_INTERRUPT : AP_SM_WAIT_HIGH_TIMEOUT;
        case AP_RESPONSE_RESET_IN_PROGRESS:
                aq->sm_state = AP_SM_STATE_RESET_WAIT;
@@ -307,7 +307,6 @@ static enum ap_sm_wait ap_sm_reset(struct ap_queue *aq)
        case AP_RESPONSE_NORMAL:
        case AP_RESPONSE_RESET_IN_PROGRESS:
                aq->sm_state = AP_SM_STATE_RESET_WAIT;
-               aq->interrupt = false;
                aq->rapq_fbit = 0;
                aq->se_bound = false;
                return AP_SM_WAIT_LOW_TIMEOUT;
@@ -383,7 +382,6 @@ static enum ap_sm_wait ap_sm_setirq_wait(struct ap_queue *aq)
 
        if (status.irq_enabled == 1) {
                /* Irqs are now enabled */
-               aq->interrupt = true;
                aq->sm_state = (aq->queue_count > 0) ?
                        AP_SM_STATE_WORKING : AP_SM_STATE_IDLE;
        }
@@ -626,16 +624,21 @@ static ssize_t interrupt_show(struct device *dev,
                              struct device_attribute *attr, char *buf)
 {
        struct ap_queue *aq = to_ap_queue(dev);
+       struct ap_queue_status status;
        int rc = 0;
 
        spin_lock_bh(&aq->lock);
-       if (aq->sm_state == AP_SM_STATE_SETIRQ_WAIT)
+       if (aq->sm_state == AP_SM_STATE_SETIRQ_WAIT) {
                rc = sysfs_emit(buf, "Enable Interrupt pending.\n");
-       else if (aq->interrupt)
-               rc = sysfs_emit(buf, "Interrupts enabled.\n");
-       else
-               rc = sysfs_emit(buf, "Interrupts disabled.\n");
+       } else {
+               status = ap_tapq(aq->qid, NULL);
+               if (status.irq_enabled)
+                       rc = sysfs_emit(buf, "Interrupts enabled.\n");
+               else
+                       rc = sysfs_emit(buf, "Interrupts disabled.\n");
+       }
        spin_unlock_bh(&aq->lock);
+
        return rc;
 }
 
@@ -1032,7 +1035,6 @@ struct ap_queue *ap_queue_create(ap_qid_t qid, int device_type)
        if (ap_sb_available() && is_prot_virt_guest())
                aq->ap_dev.device.groups = ap_queue_dev_sb_attr_groups;
        aq->qid = qid;
-       aq->interrupt = false;
        spin_lock_init(&aq->lock);
        INIT_LIST_HEAD(&aq->pendingq);
        INIT_LIST_HEAD(&aq->requestq);