Commit bd3a025d authored by Julian Wiedmann's avatar Julian Wiedmann Committed by Heiko Carstens

s390/qdio: improve handling of CIWs

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: default avatarJulian Wiedmann <jwi@linux.ibm.com>
Reviewed-by: default avatarBenjamin Block <bblock@linux.ibm.com>
Signed-off-by: default avatarHeiko Carstens <hca@linux.ibm.com>
parent 764fc318
...@@ -237,8 +237,6 @@ struct qdio_irq { ...@@ -237,8 +237,6 @@ struct qdio_irq {
int nr_output_qs; int nr_output_qs;
struct ccw1 ccw; struct ccw1 ccw;
struct ciw equeue;
struct ciw aqueue;
struct qdio_ssqd_desc ssqd_desc; struct qdio_ssqd_desc ssqd_desc;
void (*orig_handler) (struct ccw_device *, unsigned long, struct irb *); void (*orig_handler) (struct ccw_device *, unsigned long, struct irb *);
...@@ -338,7 +336,7 @@ void qdio_setup_ssqd_info(struct qdio_irq *irq_ptr); ...@@ -338,7 +336,7 @@ void qdio_setup_ssqd_info(struct qdio_irq *irq_ptr);
int qdio_setup_get_ssqd(struct qdio_irq *irq_ptr, int qdio_setup_get_ssqd(struct qdio_irq *irq_ptr,
struct subchannel_id *schid, struct subchannel_id *schid,
struct qdio_ssqd_desc *data); 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_shutdown_irq(struct qdio_irq *irq);
void qdio_print_subchannel_info(struct qdio_irq *irq_ptr); void qdio_print_subchannel_info(struct qdio_irq *irq_ptr);
void qdio_free_queues(struct qdio_irq *irq_ptr); void qdio_free_queues(struct qdio_irq *irq_ptr);
......
...@@ -972,6 +972,7 @@ int qdio_establish(struct ccw_device *cdev, ...@@ -972,6 +972,7 @@ int qdio_establish(struct ccw_device *cdev,
{ {
struct qdio_irq *irq_ptr = cdev->private->qdio_data; struct qdio_irq *irq_ptr = cdev->private->qdio_data;
struct subchannel_id schid; struct subchannel_id schid;
struct ciw *ciw;
long timeout; long timeout;
int rc; int rc;
...@@ -996,6 +997,12 @@ int qdio_establish(struct ccw_device *cdev, ...@@ -996,6 +997,12 @@ int qdio_establish(struct ccw_device *cdev,
if (!init_data->irq_poll) if (!init_data->irq_poll)
return -EINVAL; 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); mutex_lock(&irq_ptr->setup_mutex);
qdio_trace_init_data(irq_ptr, init_data); qdio_trace_init_data(irq_ptr, init_data);
qdio_setup_irq(irq_ptr, init_data); qdio_setup_irq(irq_ptr, init_data);
...@@ -1005,9 +1012,9 @@ int qdio_establish(struct ccw_device *cdev, ...@@ -1005,9 +1012,9 @@ int qdio_establish(struct ccw_device *cdev,
goto err_thinint; goto err_thinint;
/* establish q */ /* 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.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); irq_ptr->ccw.cda = (u32) virt_to_phys(irq_ptr->qdr);
spin_lock_irq(get_ccwdev_lock(cdev)); spin_lock_irq(get_ccwdev_lock(cdev));
...@@ -1065,6 +1072,7 @@ int qdio_activate(struct ccw_device *cdev) ...@@ -1065,6 +1072,7 @@ int qdio_activate(struct ccw_device *cdev)
{ {
struct qdio_irq *irq_ptr = cdev->private->qdio_data; struct qdio_irq *irq_ptr = cdev->private->qdio_data;
struct subchannel_id schid; struct subchannel_id schid;
struct ciw *ciw;
int rc; int rc;
ccw_device_get_schid(cdev, &schid); ccw_device_get_schid(cdev, &schid);
...@@ -1073,15 +1081,21 @@ int qdio_activate(struct ccw_device *cdev) ...@@ -1073,15 +1081,21 @@ int qdio_activate(struct ccw_device *cdev)
if (!irq_ptr) if (!irq_ptr)
return -ENODEV; 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); mutex_lock(&irq_ptr->setup_mutex);
if (irq_ptr->state == QDIO_IRQ_STATE_INACTIVE) { if (irq_ptr->state == QDIO_IRQ_STATE_INACTIVE) {
rc = -EBUSY; rc = -EBUSY;
goto out; 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.flags = CCW_FLAG_SLI;
irq_ptr->ccw.count = irq_ptr->aqueue.count; irq_ptr->ccw.count = ciw->count;
irq_ptr->ccw.cda = 0; irq_ptr->ccw.cda = 0;
spin_lock_irq(get_ccwdev_lock(cdev)); spin_lock_irq(get_ccwdev_lock(cdev));
......
...@@ -351,10 +351,9 @@ static void setup_qib(struct qdio_irq *irq_ptr, ...@@ -351,10 +351,9 @@ static void setup_qib(struct qdio_irq *irq_ptr,
sizeof(irq_ptr->qib.parm)); 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 ccw_device *cdev = irq_ptr->cdev;
struct ciw *ciw;
irq_ptr->qdioac1 = 0; irq_ptr->qdioac1 = 0;
memset(&irq_ptr->ccw, 0, sizeof(irq_ptr->ccw)); memset(&irq_ptr->ccw, 0, sizeof(irq_ptr->ccw));
...@@ -386,23 +385,6 @@ int qdio_setup_irq(struct qdio_irq *irq_ptr, struct qdio_initialize *init_data) ...@@ -386,23 +385,6 @@ int qdio_setup_irq(struct qdio_irq *irq_ptr, struct qdio_initialize *init_data)
irq_ptr->orig_handler = cdev->handler; irq_ptr->orig_handler = cdev->handler;
cdev->handler = qdio_int_handler; cdev->handler = qdio_int_handler;
spin_unlock_irq(get_ccwdev_lock(cdev)); 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) void qdio_shutdown_irq(struct qdio_irq *irq)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment