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

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
Loading
Loading
Loading
Loading
+3 −5
Original line number Diff line number Diff line
@@ -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);
+3 −2
Original line number Diff line number Diff line
@@ -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);
+0 −2
Original line number Diff line number Diff line
@@ -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,
+7 −17
Original line number Diff line number Diff line
@@ -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;