Commit 94c43bda authored by Julian Wiedmann's avatar Julian Wiedmann Committed by Vasily Gorbik

s390/qdio: simplify thinint device registration

On an interrupt, tiqdio_thinint_handler() walks a list of all objects
that might require attention, and checks their DSCI. This list is
awkwardly built from Input Queues, even though the IRQs are per-device
and the queue is then only used to dereference its qdio_irq parent.

To simplify the logic, change the code so that tiq_list contains
qdio_irq entries.
Signed-off-by: default avatarJulian Wiedmann <jwi@linux.ibm.com>
Reviewed-by: default avatarBenjamin Block <bblock@linux.ibm.com>
Signed-off-by: default avatarVasily Gorbik <gor@linux.ibm.com>
parent 46112810
......@@ -252,9 +252,6 @@ struct qdio_q {
/* input or output queue */
int is_input_q;
/* list of thinint input queues */
struct list_head entry;
/* upper-layer program handler */
qdio_handler_t (*handler);
......@@ -272,6 +269,7 @@ struct qdio_irq {
struct qib qib;
u32 *dsci; /* address of device state change indicator */
struct ccw_device *cdev;
struct list_head entry; /* list of thinint devices */
struct dentry *debugfs_dev;
struct dentry *debugfs_perf;
......@@ -373,8 +371,8 @@ extern u64 last_ai_time;
void qdio_setup_thinint(struct qdio_irq *irq_ptr);
int qdio_establish_thinint(struct qdio_irq *irq_ptr);
void qdio_shutdown_thinint(struct qdio_irq *irq_ptr);
void tiqdio_add_input_queues(struct qdio_irq *irq_ptr);
void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr);
void tiqdio_add_device(struct qdio_irq *irq_ptr);
void tiqdio_remove_device(struct qdio_irq *irq_ptr);
void tiqdio_inbound_processing(unsigned long q);
int tiqdio_allocate_memory(void);
void tiqdio_free_memory(void);
......
......@@ -1162,7 +1162,7 @@ int qdio_shutdown(struct ccw_device *cdev, int how)
*/
qdio_set_state(irq_ptr, QDIO_IRQ_STATE_STOPPED);
tiqdio_remove_input_queues(irq_ptr);
tiqdio_remove_device(irq_ptr);
qdio_shutdown_queues(cdev);
qdio_shutdown_debug_entries(irq_ptr);
......@@ -1284,6 +1284,7 @@ int qdio_allocate(struct qdio_initialize *init_data)
init_data->no_output_qs))
goto out_rel;
INIT_LIST_HEAD(&irq_ptr->entry);
init_data->cdev->private->qdio_data = irq_ptr;
qdio_set_state(irq_ptr, QDIO_IRQ_STATE_INACTIVE);
return 0;
......@@ -1428,7 +1429,7 @@ int qdio_activate(struct ccw_device *cdev)
}
if (is_thinint_irq(irq_ptr))
tiqdio_add_input_queues(irq_ptr);
tiqdio_add_device(irq_ptr);
/* wait for subchannel to become active */
msleep(5);
......
......@@ -150,7 +150,6 @@ static int __qdio_allocate_qs(struct qdio_q **irq_ptr_qs, int nr_queues)
return -ENOMEM;
}
irq_ptr_qs[i] = q;
INIT_LIST_HEAD(&q->entry);
}
return 0;
}
......@@ -179,7 +178,6 @@ static void setup_queues_misc(struct qdio_q *q, struct qdio_irq *irq_ptr,
q->mask = 1 << (31 - i);
q->nr = i;
q->handler = handler;
INIT_LIST_HEAD(&q->entry);
}
static void setup_storage_lists(struct qdio_q *q, struct qdio_irq *irq_ptr,
......
......@@ -66,26 +66,20 @@ static void put_indicator(u32 *addr)
atomic_dec(&ind->count);
}
void tiqdio_add_input_queues(struct qdio_irq *irq_ptr)
void tiqdio_add_device(struct qdio_irq *irq_ptr)
{
mutex_lock(&tiq_list_lock);
list_add_rcu(&irq_ptr->input_qs[0]->entry, &tiq_list);
list_add_rcu(&irq_ptr->entry, &tiq_list);
mutex_unlock(&tiq_list_lock);
}
void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr)
void tiqdio_remove_device(struct qdio_irq *irq_ptr)
{
struct qdio_q *q;
q = irq_ptr->input_qs[0];
if (!q)
return;
mutex_lock(&tiq_list_lock);
list_del_rcu(&q->entry);
list_del_rcu(&irq_ptr->entry);
mutex_unlock(&tiq_list_lock);
synchronize_rcu();
INIT_LIST_HEAD(&q->entry);
INIT_LIST_HEAD(&irq_ptr->entry);
}
static inline int has_multiple_inq_on_dsci(struct qdio_irq *irq_ptr)
......@@ -174,7 +168,7 @@ static inline void tiqdio_call_inq_handlers(struct qdio_irq *irq)
static void tiqdio_thinint_handler(struct airq_struct *airq, bool floating)
{
u32 si_used = clear_shared_ind();
struct qdio_q *q;
struct qdio_irq *irq;
last_ai_time = S390_lowcore.int_clock;
inc_irq_stat(IRQIO_QAI);
......@@ -182,12 +176,8 @@ static void tiqdio_thinint_handler(struct airq_struct *airq, bool floating)
/* protect tiq_list entries, only changed in activate or shutdown */
rcu_read_lock();
/* check for work on all inbound thinint queues */
list_for_each_entry_rcu(q, &tiq_list, entry) {
struct qdio_irq *irq;
list_for_each_entry_rcu(irq, &tiq_list, entry) {
/* only process queues from changed sets */
irq = q->irq_ptr;
if (unlikely(references_shared_dsci(irq))) {
if (!si_used)
continue;
......
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