Blob Blame History Raw
From: Julian Wiedmann <jwi@linux.ibm.com>
Date: Thu, 8 Jul 2021 08:49:28 +0200
Subject: s390/qdio: improve handling of CIWs
Git-commit: bd3a025dd22c500d33960b0a1fcf92e27514332c
Patch-mainline: v5.17-rc1
References: jsc#PED-588 bsc#1203836 LTC#198623

Fetch the individual CIWs when we actually need them, rather than
fetching both of them in qdio_setup_irq() and then needing to cache
them inside the qdio_irq.

Also deal with the error when a CIW is not available, instead of
silently dropping this error condition in qdio_setup_irq()'s caller.

Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com>
Reviewed-by: Benjamin Block <bblock@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
Acked-by: Petr Tesarik <ptesarik@suse.com>
---
 drivers/s390/cio/qdio.h       |    4 +---
 drivers/s390/cio/qdio_main.c  |   22 ++++++++++++++++++----
 drivers/s390/cio/qdio_setup.c |   20 +-------------------
 3 files changed, 20 insertions(+), 26 deletions(-)

--- a/drivers/s390/cio/qdio.h
+++ b/drivers/s390/cio/qdio.h
@@ -237,8 +237,6 @@ struct qdio_irq {
 	int nr_output_qs;
 
 	struct ccw1 ccw;
-	struct ciw equeue;
-	struct ciw aqueue;
 
 	struct qdio_ssqd_desc ssqd_desc;
 	void (*orig_handler) (struct ccw_device *, unsigned long, struct irb *);
@@ -338,7 +336,7 @@ void qdio_setup_ssqd_info(struct qdio_ir
 int qdio_setup_get_ssqd(struct qdio_irq *irq_ptr,
 			struct subchannel_id *schid,
 			struct qdio_ssqd_desc *data);
-int qdio_setup_irq(struct qdio_irq *irq_ptr, struct qdio_initialize *init_data);
+void qdio_setup_irq(struct qdio_irq *irq_ptr, struct qdio_initialize *init_data);
 void qdio_shutdown_irq(struct qdio_irq *irq);
 void qdio_print_subchannel_info(struct qdio_irq *irq_ptr);
 void qdio_free_queues(struct qdio_irq *irq_ptr);
--- a/drivers/s390/cio/qdio_main.c
+++ b/drivers/s390/cio/qdio_main.c
@@ -972,6 +972,7 @@ int qdio_establish(struct ccw_device *cd
 {
 	struct qdio_irq *irq_ptr = cdev->private->qdio_data;
 	struct subchannel_id schid;
+	struct ciw *ciw;
 	long timeout;
 	int rc;
 
@@ -996,6 +997,12 @@ int qdio_establish(struct ccw_device *cd
 	if (!init_data->irq_poll)
 		return -EINVAL;
 
+	ciw = ccw_device_get_ciw(cdev, CIW_TYPE_EQUEUE);
+	if (!ciw) {
+		DBF_ERROR("%4x NO EQ", schid.sch_no);
+		return -EIO;
+	}
+
 	mutex_lock(&irq_ptr->setup_mutex);
 	qdio_trace_init_data(irq_ptr, init_data);
 	qdio_setup_irq(irq_ptr, init_data);
@@ -1005,9 +1012,9 @@ int qdio_establish(struct ccw_device *cd
 		goto err_thinint;
 
 	/* establish q */
-	irq_ptr->ccw.cmd_code = irq_ptr->equeue.cmd;
+	irq_ptr->ccw.cmd_code = ciw->cmd;
 	irq_ptr->ccw.flags = CCW_FLAG_SLI;
-	irq_ptr->ccw.count = irq_ptr->equeue.count;
+	irq_ptr->ccw.count = ciw->count;
 	irq_ptr->ccw.cda = (u32) virt_to_phys(irq_ptr->qdr);
 
 	spin_lock_irq(get_ccwdev_lock(cdev));
@@ -1065,6 +1072,7 @@ int qdio_activate(struct ccw_device *cde
 {
 	struct qdio_irq *irq_ptr = cdev->private->qdio_data;
 	struct subchannel_id schid;
+	struct ciw *ciw;
 	int rc;
 
 	ccw_device_get_schid(cdev, &schid);
@@ -1073,15 +1081,21 @@ int qdio_activate(struct ccw_device *cde
 	if (!irq_ptr)
 		return -ENODEV;
 
+	ciw = ccw_device_get_ciw(cdev, CIW_TYPE_AQUEUE);
+	if (!ciw) {
+		DBF_ERROR("%4x NO AQ", schid.sch_no);
+		return -EIO;
+	}
+
 	mutex_lock(&irq_ptr->setup_mutex);
 	if (irq_ptr->state == QDIO_IRQ_STATE_INACTIVE) {
 		rc = -EBUSY;
 		goto out;
 	}
 
-	irq_ptr->ccw.cmd_code = irq_ptr->aqueue.cmd;
+	irq_ptr->ccw.cmd_code = ciw->cmd;
 	irq_ptr->ccw.flags = CCW_FLAG_SLI;
-	irq_ptr->ccw.count = irq_ptr->aqueue.count;
+	irq_ptr->ccw.count = ciw->count;
 	irq_ptr->ccw.cda = 0;
 
 	spin_lock_irq(get_ccwdev_lock(cdev));
--- a/drivers/s390/cio/qdio_setup.c
+++ b/drivers/s390/cio/qdio_setup.c
@@ -364,10 +364,9 @@ static void setup_qib(struct qdio_irq *i
 		       sizeof(irq_ptr->qib.parm));
 }
 
-int qdio_setup_irq(struct qdio_irq *irq_ptr, struct qdio_initialize *init_data)
+void qdio_setup_irq(struct qdio_irq *irq_ptr, struct qdio_initialize *init_data)
 {
 	struct ccw_device *cdev = irq_ptr->cdev;
-	struct ciw *ciw;
 
 	irq_ptr->qdioac1 = 0;
 	memset(&irq_ptr->ccw, 0, sizeof(irq_ptr->ccw));
@@ -399,23 +398,6 @@ int qdio_setup_irq(struct qdio_irq *irq_
 	irq_ptr->orig_handler = cdev->handler;
 	cdev->handler = qdio_int_handler;
 	spin_unlock_irq(get_ccwdev_lock(cdev));
-
-	/* get qdio commands */
-	ciw = ccw_device_get_ciw(cdev, CIW_TYPE_EQUEUE);
-	if (!ciw) {
-		DBF_ERROR("%4x NO EQ", irq_ptr->schid.sch_no);
-		return -EINVAL;
-	}
-	irq_ptr->equeue = *ciw;
-
-	ciw = ccw_device_get_ciw(cdev, CIW_TYPE_AQUEUE);
-	if (!ciw) {
-		DBF_ERROR("%4x NO AQ", irq_ptr->schid.sch_no);
-		return -EINVAL;
-	}
-	irq_ptr->aqueue = *ciw;
-
-	return 0;
 }
 
 void qdio_shutdown_irq(struct qdio_irq *irq)