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