2003-07-01 18:38:50

by Martin Schwidefsky

[permalink] [raw]
Subject: [PATCH] s390 (5/6): thin interrupts.

Add thin interrupt support to qdio.

diffstat:
drivers/s390/cio/qdio.c | 738 ++++++++++++++++++++++++++----------------------
drivers/s390/cio/qdio.h | 19 -
2 files changed, 417 insertions(+), 340 deletions(-)

diff -urN linux-2.5/drivers/s390/cio/qdio.c linux-2.5-s390/drivers/s390/cio/qdio.c
--- linux-2.5/drivers/s390/cio/qdio.c Sun Jun 22 20:32:56 2003
+++ linux-2.5-s390/drivers/s390/cio/qdio.c Tue Jul 1 20:48:28 2003
@@ -55,7 +55,7 @@
#include "ioasm.h"
#include "chsc.h"

-#define VERSION_QDIO_C "$Revision: 1.49 $"
+#define VERSION_QDIO_C "$Revision: 1.51 $"

/****************** MODULE PARAMETER VARIABLES ********************/
MODULE_AUTHOR("Utz Bacher <[email protected]>");
@@ -74,6 +74,8 @@
static struct qdio_perf_stats perf_stats;
#endif /* QDIO_PERFORMANCE_STATS */

+static int hydra_thinints;
+
static int indicator_used[INDICATORS_PER_CACHELINE];
static __u32 * volatile indicators;
static __u32 volatile spare_indicator;
@@ -88,12 +90,12 @@
#endif /* QDIO_DBF_LIKE_HELL */

/* iQDIO stuff: */
-static volatile struct qdio_q *iq_list=NULL; /* volatile as it could change
- during a while loop */
-static spinlock_t iq_list_lock=SPIN_LOCK_UNLOCKED;
+static volatile struct qdio_q *tiq_list=NULL; /* volatile as it could change
+ during a while loop */
+static spinlock_t ttiq_list_lock=SPIN_LOCK_UNLOCKED;
static int register_thinint_result;
-static void iqdio_tl(unsigned long);
-static DECLARE_TASKLET(iqdio_tasklet,iqdio_tl,0);
+static void tiqdio_tl(unsigned long);
+static DECLARE_TASKLET(tiqdio_tasklet,tiqdio_tl,0);

/* not a macro, as one of the arguments is atomic_read */
static inline int
@@ -173,7 +175,7 @@
/*
* unfortunately, we can't just xchg the values; in do_QDIO we want to reserve
* the q in any case, so that we'll not be interrupted when we are in
- * qdio_mark_iq... shouldn't have a really bad impact, as reserving almost
+ * qdio_mark_tiq... shouldn't have a really bad impact, as reserving almost
* ever works (last famous words)
*/
static inline int
@@ -195,7 +197,8 @@
}

static inline int
-qdio_siga_sync(struct qdio_q *q)
+qdio_siga_sync(struct qdio_q *q, unsigned int gpr2,
+ unsigned int gpr3)
{
int cc;

@@ -206,17 +209,21 @@
perf_stats.siga_syncs++;
#endif /* QDIO_PERFORMANCE_STATS */

- if (q->is_input_q)
- cc = do_siga_sync(q->irq, 0, q->mask);
- else
- cc = do_siga_sync(q->irq, q->mask, 0);
-
+ cc = do_siga_sync(q->irq, gpr2, gpr3);
if (cc)
QDIO_DBF_HEX3(0,trace,&cc,sizeof(int*));

return cc;
}

+static inline int
+qdio_siga_sync_q(struct qdio_q *q)
+{
+ if (q->is_input_q)
+ return qdio_siga_sync(q, 0, q->mask);
+ return qdio_siga_sync(q, q->mask, 0);
+}
+
/*
* returns QDIO_SIGA_ERROR_ACCESS_EXCEPTION as cc, when SIGA returns
* an access exception
@@ -304,7 +311,7 @@
}

static inline volatile void
-iqdio_clear_summary_bit(__u32 *location)
+tiqdio_clear_summary_bit(__u32 *location)
{
QDIO_DBF_TEXT5(0,trace,"clrsummb");
QDIO_DBF_HEX5(0,trace,&location,sizeof(void*));
@@ -313,7 +320,7 @@
}

static inline volatile void
-iqdio_set_summary_bit(__u32 *location)
+tiqdio_set_summary_bit(__u32 *location)
{
QDIO_DBF_TEXT5(0,trace,"setsummb");
QDIO_DBF_HEX5(0,trace,&location,sizeof(void*));
@@ -322,21 +329,21 @@
}

static inline void
-iqdio_sched_tl(void)
+tiqdio_sched_tl(void)
{
- tasklet_hi_schedule(&iqdio_tasklet);
+ tasklet_hi_schedule(&tiqdio_tasklet);
}

static inline void
-qdio_mark_iq(struct qdio_q *q)
+qdio_mark_tiq(struct qdio_q *q)
{
unsigned long flags;

QDIO_DBF_TEXT4(0,trace,"mark iq");
QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));

- spin_lock_irqsave(&iq_list_lock,flags);
- if (atomic_read(&q->is_in_shutdown))
+ spin_lock_irqsave(&ttiq_list_lock,flags);
+ if (unlikely(atomic_read(&q->is_in_shutdown)))
goto out_unlock;

if (!q->is_input_q)
@@ -345,23 +352,23 @@
if ((q->list_prev) || (q->list_next))
goto out_unlock;

- if (!iq_list) {
- iq_list=q;
+ if (!tiq_list) {
+ tiq_list=q;
q->list_prev=q;
q->list_next=q;
} else {
- q->list_next=iq_list;
- q->list_prev=iq_list->list_prev;
- iq_list->list_prev->list_next=q;
- iq_list->list_prev=q;
+ q->list_next=tiq_list;
+ q->list_prev=tiq_list->list_prev;
+ tiq_list->list_prev->list_next=q;
+ tiq_list->list_prev=q;
}
- spin_unlock_irqrestore(&iq_list_lock,flags);
+ spin_unlock_irqrestore(&ttiq_list_lock,flags);

- iqdio_set_summary_bit((__u32*)q->dev_st_chg_ind);
- iqdio_sched_tl();
+ tiqdio_set_summary_bit((__u32*)q->dev_st_chg_ind);
+ tiqdio_sched_tl();
return;
out_unlock:
- spin_unlock_irqrestore(&iq_list_lock,flags);
+ spin_unlock_irqrestore(&ttiq_list_lock,flags);
return;
}

@@ -371,7 +378,7 @@
QDIO_DBF_TEXT4(0,trace,"mark q");
QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));

- if (atomic_read(&q->is_in_shutdown))
+ if (unlikely(atomic_read(&q->is_in_shutdown)))
return;

tasklet_schedule(&q->tasklet);
@@ -410,7 +417,7 @@
* checking for PRIMED state
*/
if (q->is_iqdio_q)
- iqdio_set_summary_bit((__u32*)q->dev_st_chg_ind);
+ tiqdio_set_summary_bit((__u32*)q->dev_st_chg_ind);
return 0;

#else /* QDIO_USE_PROCESSING_STATE */
@@ -434,27 +441,27 @@
if ((!q->list_prev)||(!q->list_next))
return;

- if ((q->is_iqdio_q)&&(q->is_input_q)) {
+ if ((q->is_thinint_q)&&(q->is_input_q)) {
/* iQDIO */
- spin_lock_irqsave(&iq_list_lock,flags);
+ spin_lock_irqsave(&ttiq_list_lock,flags);
if (q->list_next==q) {
/* q was the only interesting q */
- iq_list=NULL;
+ tiq_list=NULL;
q->list_next=NULL;
q->list_prev=NULL;
} else {
q->list_next->list_prev=q->list_prev;
q->list_prev->list_next=q->list_next;
- iq_list=q->list_next;
+ tiq_list=q->list_next;
q->list_next=NULL;
q->list_prev=NULL;
}
- spin_unlock_irqrestore(&iq_list_lock,flags);
+ spin_unlock_irqrestore(&ttiq_list_lock,flags);
}
}

static inline unsigned long
-iqdio_clear_global_summary(void)
+tiqdio_clear_global_summary(void)
{
unsigned long time;

@@ -467,6 +474,223 @@
return time;
}

+
+/************************* OUTBOUND ROUTINES *******************************/
+
+inline static int
+qdio_get_outbound_buffer_frontier(struct qdio_q *q)
+{
+ int f,f_mod_no;
+ volatile char *slsb;
+ int first_not_to_check;
+ char dbf_text[15];
+
+ QDIO_DBF_TEXT4(0,trace,"getobfro");
+ QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
+
+ slsb=&q->slsb.acc.val[0];
+ f_mod_no=f=q->first_to_check;
+ /*
+ * f points to already processed elements, so f+no_used is correct...
+ * ... but: we don't check 128 buffers, as otherwise
+ * qdio_has_outbound_q_moved would return 0
+ */
+ first_not_to_check=f+qdio_min(atomic_read(&q->number_of_buffers_used),
+ (QDIO_MAX_BUFFERS_PER_Q-1));
+
+ if ((!q->is_iqdio_q)&&(!q->hydra_gives_outbound_pcis))
+ SYNC_MEMORY;
+
+check_next:
+ if (f==first_not_to_check)
+ goto out;
+
+ switch(slsb[f_mod_no]) {
+
+ /* the hydra has not fetched the output yet */
+ case SLSB_CU_OUTPUT_PRIMED:
+ QDIO_DBF_TEXT5(0,trace,"outpprim");
+ break;
+
+ /* the hydra got it */
+ case SLSB_P_OUTPUT_EMPTY:
+ atomic_dec(&q->number_of_buffers_used);
+ f++;
+ f_mod_no=f&(QDIO_MAX_BUFFERS_PER_Q-1);
+ QDIO_DBF_TEXT5(0,trace,"outpempt");
+ goto check_next;
+
+ case SLSB_P_OUTPUT_ERROR:
+ QDIO_DBF_TEXT3(0,trace,"outperr");
+ sprintf(dbf_text,"%x-%x-%x",f_mod_no,
+ q->sbal[f_mod_no]->element[14].sbalf.value,
+ q->sbal[f_mod_no]->element[15].sbalf.value);
+ QDIO_DBF_TEXT3(1,trace,dbf_text);
+ QDIO_DBF_HEX2(1,sbal,q->sbal[f_mod_no],256);
+
+ /* kind of process the buffer */
+ set_slsb(&q->slsb.acc.val[f_mod_no], SLSB_P_OUTPUT_NOT_INIT);
+
+ /*
+ * we increment the frontier, as this buffer
+ * was processed obviously
+ */
+ atomic_dec(&q->number_of_buffers_used);
+ f_mod_no=(f_mod_no+1)&(QDIO_MAX_BUFFERS_PER_Q-1);
+
+ if (q->qdio_error)
+ q->error_status_flags|=
+ QDIO_STATUS_MORE_THAN_ONE_QDIO_ERROR;
+ q->qdio_error=SLSB_P_OUTPUT_ERROR;
+ q->error_status_flags|=QDIO_STATUS_LOOK_FOR_ERROR;
+
+ break;
+
+ /* no new buffers */
+ default:
+ QDIO_DBF_TEXT5(0,trace,"outpni");
+ }
+out:
+ return (q->first_to_check=f_mod_no);
+}
+
+/* all buffers are processed */
+inline static int
+qdio_is_outbound_q_done(struct qdio_q *q)
+{
+ int no_used;
+ char dbf_text[15];
+
+ no_used=atomic_read(&q->number_of_buffers_used);
+
+ if (no_used) {
+ sprintf(dbf_text,"oqisnt%02x",no_used);
+ QDIO_DBF_TEXT4(0,trace,dbf_text);
+ } else {
+ QDIO_DBF_TEXT4(0,trace,"oqisdone");
+ }
+ QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
+ return (no_used==0);
+}
+
+inline static int
+qdio_has_outbound_q_moved(struct qdio_q *q)
+{
+ int i;
+
+ i=qdio_get_outbound_buffer_frontier(q);
+
+ if ( (i!=GET_SAVED_FRONTIER(q)) ||
+ (q->error_status_flags&QDIO_STATUS_LOOK_FOR_ERROR) ) {
+ SAVE_FRONTIER(q,i);
+ SAVE_TIMESTAMP(q);
+ QDIO_DBF_TEXT4(0,trace,"oqhasmvd");
+ QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
+ return 1;
+ } else {
+ QDIO_DBF_TEXT4(0,trace,"oqhsntmv");
+ QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
+ return 0;
+ }
+}
+
+inline static void
+qdio_kick_outbound_q(struct qdio_q *q)
+{
+ int result;
+
+ QDIO_DBF_TEXT4(0,trace,"kickoutq");
+ QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
+
+ if (!q->siga_out)
+ return;
+
+ result=qdio_siga_output(q);
+
+ if (!result)
+ return;
+
+ if (q->siga_error)
+ q->error_status_flags|=QDIO_STATUS_MORE_THAN_ONE_SIGA_ERROR;
+ q->error_status_flags |= QDIO_STATUS_LOOK_FOR_ERROR;
+ q->siga_error=result;
+}
+
+inline static void
+qdio_kick_outbound_handler(struct qdio_q *q)
+{
+ int start, end, real_end, count;
+ char dbf_text[15];
+
+ start = q->first_element_to_kick;
+ /* last_move_ftc was just updated */
+ real_end = GET_SAVED_FRONTIER(q);
+ end = (real_end+QDIO_MAX_BUFFERS_PER_Q-1)&
+ (QDIO_MAX_BUFFERS_PER_Q-1);
+ count = (end+QDIO_MAX_BUFFERS_PER_Q+1-start)&
+ (QDIO_MAX_BUFFERS_PER_Q-1);
+
+ QDIO_DBF_TEXT4(0,trace,"kickouth");
+ QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
+
+ sprintf(dbf_text,"s=%2xc=%2x",start,count);
+ QDIO_DBF_TEXT4(0,trace,dbf_text);
+
+ if (q->state==QDIO_IRQ_STATE_ACTIVE)
+ q->handler(q->cdev,QDIO_STATUS_OUTBOUND_INT|
+ q->error_status_flags,
+ q->qdio_error,q->siga_error,q->q_no,start,count,
+ q->int_parm);
+
+ /* for the next time: */
+ q->first_element_to_kick=real_end;
+ q->qdio_error=0;
+ q->siga_error=0;
+ q->error_status_flags=0;
+}
+
+static void
+qdio_outbound_processing(struct qdio_q *q)
+{
+ QDIO_DBF_TEXT4(0,trace,"qoutproc");
+ QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
+
+ if (unlikely(qdio_reserve_q(q))) {
+ qdio_release_q(q);
+#ifdef QDIO_PERFORMANCE_STATS
+ o_p_c++;
+#endif /* QDIO_PERFORMANCE_STATS */
+ /* as we're sissies, we'll check next time */
+ if (likely(!atomic_read(&q->is_in_shutdown))) {
+ qdio_mark_q(q);
+ QDIO_DBF_TEXT4(0,trace,"busy,agn");
+ }
+ return;
+ }
+#ifdef QDIO_PERFORMANCE_STATS
+ o_p_nc++;
+ perf_stats.tl_runs++;
+#endif /* QDIO_PERFORMANCE_STATS */
+
+ if (qdio_has_outbound_q_moved(q))
+ qdio_kick_outbound_handler(q);
+
+ if (q->is_iqdio_q) {
+ /*
+ * for asynchronous queues, we better check, if the fill
+ * level is too high
+ */
+ if (atomic_read(&q->number_of_buffers_used)>
+ IQDIO_FILL_LEVEL_TO_POLL)
+ qdio_mark_q(q);
+
+ } else if (!q->hydra_gives_outbound_pcis)
+ if (!qdio_is_outbound_q_done(q))
+ qdio_mark_q(q);
+
+ qdio_release_q(q);
+}
+
/************************* INBOUND ROUTINES *******************************/


@@ -650,8 +874,8 @@
* we will return 0 below, as there is nothing to do, except scheduling
* ourselves for the next time.
*/
- iqdio_set_summary_bit((__u32*)q->dev_st_chg_ind);
- iqdio_sched_tl();
+ tiqdio_set_summary_bit((__u32*)q->dev_st_chg_ind);
+ tiqdio_sched_tl();
return 0;
}

@@ -725,14 +949,15 @@
count=0;
while (1) {
count++;
- if (i==end) break;
+ if (i==end)
+ break;
i=(i+1)&(QDIO_MAX_BUFFERS_PER_Q-1);
}

sprintf(dbf_text,"s=%2xc=%2x",start,count);
QDIO_DBF_TEXT4(0,trace,dbf_text);

- if (q->state==QDIO_IRQ_STATE_ACTIVE)
+ if (likely(q->state==QDIO_IRQ_STATE_ACTIVE))
q->handler(q->cdev,
QDIO_STATUS_INBOUND_INT|q->error_status_flags,
q->qdio_error,q->siga_error,q->q_no,start,count,
@@ -751,8 +976,12 @@
}

static inline void
-iqdio_inbound_processing(struct qdio_q *q)
+tiqdio_inbound_processing(struct qdio_q *q)
{
+ struct qdio_irq *irq_ptr;
+ struct qdio_q *oq;
+ int i;
+
QDIO_DBF_TEXT4(0,trace,"iqinproc");
QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));

@@ -761,7 +990,7 @@
* interrupt ourselves and call qdio_unmark_q, as is_in_shutdown might
* be set
*/
- if (qdio_reserve_q(q)) {
+ if (unlikely(qdio_reserve_q(q))) {
qdio_release_q(q);
#ifdef QDIO_PERFORMANCE_STATS
ii_p_c++;
@@ -770,13 +999,13 @@
* as we might just be about to stop polling, we make
* sure that we check again at least once more
*/
- iqdio_sched_tl();
+ tiqdio_sched_tl();
return;
}
#ifdef QDIO_PERFORMANCE_STATS
ii_p_nc++;
#endif /* QDIO_PERFORMANCE_STATS */
- if (atomic_read(&q->is_in_shutdown)) {
+ if (unlikely(atomic_read(&q->is_in_shutdown))) {
qdio_unmark_q(q);
goto out;
}
@@ -784,10 +1013,34 @@
if (!(*(q->dev_st_chg_ind)))
goto out;

- iqdio_clear_summary_bit((__u32*)q->dev_st_chg_ind);
+ tiqdio_clear_summary_bit((__u32*)q->dev_st_chg_ind);

- if (!q->siga_sync_done_on_thinints)
- SYNC_MEMORY;
+ if (q->hydra_gives_outbound_pcis) {
+ if (!q->siga_sync_done_on_thinints) {
+ SYNC_MEMORY_ALL;
+ } else if ((!q->siga_sync_done_on_outb_tis)&&
+ (q->hydra_gives_outbound_pcis)) {
+ SYNC_MEMORY_ALL_OUTB;
+ }
+ } else {
+ SYNC_MEMORY;
+ }
+ /*
+ * maybe we have to do work on our outbound queues... at least
+ * we have to check Hydra outbound-int-capable thinint-capable
+ * queues
+ */
+ if (q->hydra_gives_outbound_pcis) {
+ irq_ptr = (struct qdio_irq*)q->irq_ptr;
+ for (i=0;i<irq_ptr->no_output_qs;i++) {
+ oq = irq_ptr->output_qs[i];
+#ifdef QDIO_PERFORMANCE_STATS
+ perf_stats.tl_runs--;
+#endif /* QDIO_PERFORMANCE_STATS */
+ if (!qdio_is_outbound_q_done(oq))
+ qdio_outbound_processing(oq);
+ }
+ }

if (!qdio_has_inbound_q_moved(q))
goto out;
@@ -799,8 +1052,8 @@
* we set the flags to get into the stuff next time,
* see also comment in qdio_stop_polling
*/
- iqdio_set_summary_bit((__u32*)q->dev_st_chg_ind);
- iqdio_sched_tl();
+ tiqdio_set_summary_bit((__u32*)q->dev_st_chg_ind);
+ tiqdio_sched_tl();
}
out:
qdio_release_q(q);
@@ -814,13 +1067,13 @@
QDIO_DBF_TEXT4(0,trace,"qinproc");
QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));

- if (qdio_reserve_q(q)) {
+ if (unlikely(qdio_reserve_q(q))) {
qdio_release_q(q);
#ifdef QDIO_PERFORMANCE_STATS
i_p_c++;
#endif /* QDIO_PERFORMANCE_STATS */
/* as we're sissies, we'll check next time */
- if (!atomic_read(&q->is_in_shutdown)) {
+ if (likely(!atomic_read(&q->is_in_shutdown))) {
qdio_mark_q(q);
QDIO_DBF_TEXT4(0,trace,"busy,agn");
}
@@ -849,229 +1102,14 @@
qdio_release_q(q);
}

-/************************* OUTBOUND ROUTINES *******************************/
-
-inline static int
-qdio_get_outbound_buffer_frontier(struct qdio_q *q)
-{
- int f,f_mod_no;
- volatile char *slsb;
- int first_not_to_check;
- char dbf_text[15];
-
- QDIO_DBF_TEXT4(0,trace,"getobfro");
- QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
-
- slsb=&q->slsb.acc.val[0];
- f_mod_no=f=q->first_to_check;
- /*
- * f points to already processed elements, so f+no_used is correct...
- * ... but: we don't check 128 buffers, as otherwise
- * qdio_has_outbound_q_moved would return 0
- */
- first_not_to_check=f+qdio_min(atomic_read(&q->number_of_buffers_used),
- (QDIO_MAX_BUFFERS_PER_Q-1));
-
- if ((!q->is_iqdio_q)&&(!q->hydra_gives_outbound_pcis))
- SYNC_MEMORY;
-
-check_next:
- if (f==first_not_to_check)
- goto out;
-
- switch(slsb[f_mod_no]) {
-
- /* the hydra has not fetched the output yet */
- case SLSB_CU_OUTPUT_PRIMED:
- QDIO_DBF_TEXT5(0,trace,"outpprim");
- break;
-
- /* the hydra got it */
- case SLSB_P_OUTPUT_EMPTY:
- atomic_dec(&q->number_of_buffers_used);
- f++;
- f_mod_no=f&(QDIO_MAX_BUFFERS_PER_Q-1);
- QDIO_DBF_TEXT5(0,trace,"outpempt");
- goto check_next;
-
- case SLSB_P_OUTPUT_ERROR:
- QDIO_DBF_TEXT3(0,trace,"outperr");
- sprintf(dbf_text,"%x-%x-%x",f_mod_no,
- q->sbal[f_mod_no]->element[14].sbalf.value,
- q->sbal[f_mod_no]->element[15].sbalf.value);
- QDIO_DBF_TEXT3(1,trace,dbf_text);
- QDIO_DBF_HEX2(1,sbal,q->sbal[f_mod_no],256);
-
- /* kind of process the buffer */
- set_slsb(&q->slsb.acc.val[f_mod_no], SLSB_P_OUTPUT_NOT_INIT);
-
- /*
- * we increment the frontier, as this buffer
- * was processed obviously
- */
- atomic_dec(&q->number_of_buffers_used);
- f_mod_no=(f_mod_no+1)&(QDIO_MAX_BUFFERS_PER_Q-1);
-
- if (q->qdio_error)
- q->error_status_flags|=
- QDIO_STATUS_MORE_THAN_ONE_QDIO_ERROR;
- q->qdio_error=SLSB_P_OUTPUT_ERROR;
- q->error_status_flags|=QDIO_STATUS_LOOK_FOR_ERROR;
-
- break;
-
- /* no new buffers */
- default:
- QDIO_DBF_TEXT5(0,trace,"outpni");
- }
-out:
- return (q->first_to_check=f_mod_no);
-}
-
-/* all buffers are processed */
-inline static int
-qdio_is_outbound_q_done(struct qdio_q *q)
-{
- int no_used;
- char dbf_text[15];
-
- no_used=atomic_read(&q->number_of_buffers_used);
-
- if (no_used) {
- sprintf(dbf_text,"oqisnt%02x",no_used);
- QDIO_DBF_TEXT4(0,trace,dbf_text);
- } else {
- QDIO_DBF_TEXT4(0,trace,"oqisdone");
- }
- QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
- return (no_used==0);
-}
-
-inline static int
-qdio_has_outbound_q_moved(struct qdio_q *q)
-{
- int i;
-
- i=qdio_get_outbound_buffer_frontier(q);
-
- if ( (i!=GET_SAVED_FRONTIER(q)) ||
- (q->error_status_flags&QDIO_STATUS_LOOK_FOR_ERROR) ) {
- SAVE_FRONTIER(q,i);
- SAVE_TIMESTAMP(q);
- QDIO_DBF_TEXT4(0,trace,"oqhasmvd");
- QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
- return 1;
- } else {
- QDIO_DBF_TEXT4(0,trace,"oqhsntmv");
- QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
- return 0;
- }
-}
-
-inline static void
-qdio_kick_outbound_q(struct qdio_q *q)
-{
- int result;
-
- QDIO_DBF_TEXT4(0,trace,"kickoutq");
- QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
-
- if (!q->siga_out)
- return;
-
- result=qdio_siga_output(q);
-
- if (!result)
- return;
-
- if (q->siga_error)
- q->error_status_flags|=QDIO_STATUS_MORE_THAN_ONE_SIGA_ERROR;
- q->error_status_flags |= QDIO_STATUS_LOOK_FOR_ERROR;
- q->siga_error=result;
-}
-
-inline static void
-qdio_kick_outbound_handler(struct qdio_q *q)
-{
- int start, end, real_end, count;
- char dbf_text[15];
-
- start = q->first_element_to_kick;
- /* last_move_ftc was just updated */
- real_end = GET_SAVED_FRONTIER(q);
- end = (real_end+QDIO_MAX_BUFFERS_PER_Q-1)&
- (QDIO_MAX_BUFFERS_PER_Q-1);
- count = (end+QDIO_MAX_BUFFERS_PER_Q+1-start)&
- (QDIO_MAX_BUFFERS_PER_Q-1);
-
- QDIO_DBF_TEXT4(0,trace,"kickouth");
- QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
-
- sprintf(dbf_text,"s=%2xc=%2x",start,count);
- QDIO_DBF_TEXT4(0,trace,dbf_text);
-
- if (q->state==QDIO_IRQ_STATE_ACTIVE)
- q->handler(q->cdev,QDIO_STATUS_OUTBOUND_INT|
- q->error_status_flags,
- q->qdio_error,q->siga_error,q->q_no,start,count,
- q->int_parm);
-
- /* for the next time: */
- q->first_element_to_kick=real_end;
- q->qdio_error=0;
- q->siga_error=0;
- q->error_status_flags=0;
-}
-
-static void qdio_outbound_processing(struct qdio_q *q)
-{
- QDIO_DBF_TEXT4(0,trace,"qoutproc");
- QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
-
- if (qdio_reserve_q(q)) {
- qdio_release_q(q);
-#ifdef QDIO_PERFORMANCE_STATS
- o_p_c++;
-#endif /* QDIO_PERFORMANCE_STATS */
- /* as we're sissies, we'll check next time */
- if (!atomic_read(&q->is_in_shutdown)) {
- qdio_mark_q(q);
- QDIO_DBF_TEXT4(0,trace,"busy,agn");
- }
- return;
- }
-#ifdef QDIO_PERFORMANCE_STATS
- o_p_nc++;
- perf_stats.tl_runs++;
-#endif /* QDIO_PERFORMANCE_STATS */
-
- if (qdio_has_outbound_q_moved(q))
- qdio_kick_outbound_handler(q);
-
- if (q->is_iqdio_q) {
- /*
- * for asynchronous queues, we better check, if the fill
- * level is too high
- */
- if (atomic_read(&q->number_of_buffers_used)>
- IQDIO_FILL_LEVEL_TO_POLL)
- qdio_mark_q(q);
-
- } else if (!q->hydra_gives_outbound_pcis)
- if (!qdio_is_outbound_q_done(q))
- qdio_mark_q(q);
-
- qdio_release_q(q);
-}
-
/************************* MAIN ROUTINES *******************************/

#ifdef QDIO_USE_PROCESSING_STATE
static inline int
-iqdio_do_inbound_checks(struct qdio_q *q, int q_laps)
+tiqdio_do_inbound_checks(struct qdio_q *q, int q_laps)
{
if (!q) {
- iqdio_sched_tl();
+ tiqdio_sched_tl();
return 0;
}

@@ -1082,7 +1120,7 @@
if (q->siga_sync)
return 2;

- if (qdio_reserve_q(q)) {
+ if (unlikely(qdio_reserve_q(q))) {
qdio_release_q(q);
#ifdef QDIO_PERFORMANCE_STATS
ii_p_c++;
@@ -1096,8 +1134,8 @@
* sanity -- we'd get here without setting the
* dev st chg ind
*/
- iqdio_set_summary_bit((__u32*)q->dev_st_chg_ind);
- iqdio_sched_tl();
+ tiqdio_set_summary_bit((__u32*)q->dev_st_chg_ind);
+ tiqdio_sched_tl();
return 0;
}
if (qdio_stop_polling(q)) {
@@ -1112,8 +1150,8 @@
* we set the flags to get into the stuff
* next time, see also comment in qdio_stop_polling
*/
- iqdio_set_summary_bit((__u32*)q->dev_st_chg_ind);
- iqdio_sched_tl();
+ tiqdio_set_summary_bit((__u32*)q->dev_st_chg_ind);
+ tiqdio_sched_tl();
qdio_release_q(q);
return 1;

@@ -1121,7 +1159,7 @@
#endif /* QDIO_USE_PROCESSING_STATE */

static inline void
-iqdio_inbound_checks(void)
+tiqdio_inbound_checks(void)
{
struct qdio_q *q;
#ifdef QDIO_USE_PROCESSING_STATE
@@ -1135,20 +1173,20 @@
again:
#endif /* QDIO_USE_PROCESSING_STATE */

- q=(struct qdio_q*)iq_list;
+ q=(struct qdio_q*)tiq_list;
do {
if (!q)
break;
- iqdio_inbound_processing(q);
+ tiqdio_inbound_processing(q);
q=(struct qdio_q*)q->list_next;
- } while (q!=(struct qdio_q*)iq_list);
+ } while (q!=(struct qdio_q*)tiq_list);

#ifdef QDIO_USE_PROCESSING_STATE
- q=(struct qdio_q*)iq_list;
+ q=(struct qdio_q*)tiq_list;
do {
int ret;

- ret = iqdio_do_inbound_checks(q, q_laps);
+ ret = tiqdio_do_inbound_checks(q, q_laps);
switch (ret) {
case 0:
return;
@@ -1161,17 +1199,12 @@
q_laps++;
goto again;
}
- } while (q!=(struct qdio_q*)iq_list);
+ } while (q!=(struct qdio_q*)tiq_list);
#endif /* QDIO_USE_PROCESSING_STATE */
}

static void
-iqdio_check_for_polling(void)
-{
-}
-
-static void
-iqdio_tl(unsigned long data)
+tiqdio_tl(unsigned long data)
{
QDIO_DBF_TEXT4(0,trace,"iqdio_tl");

@@ -1179,8 +1212,7 @@
perf_stats.tl_runs++;
#endif /* QDIO_PERFORMANCE_STATS */

- iqdio_inbound_checks();
- iqdio_check_for_polling();
+ tiqdio_inbound_checks();
}

/********************* GENERAL HELPER_ROUTINES ***********************/
@@ -1298,6 +1330,7 @@
q->int_parm=int_parm;
irq_ptr->input_qs[i]=q;
q->irq=irq_ptr->irq;
+ q->irq_ptr = irq_ptr;
q->cdev = cdev;
q->mask=1<<(31-i);
q->q_no=i;
@@ -1308,10 +1341,11 @@
q->dev_st_chg_ind=irq_ptr->dev_st_chg_ind;

q->tasklet.data=(unsigned long)q;
+ /* q->is_thinint_q isn't valid at this time, but
+ * irq_ptr->is_thinint_irq is */
q->tasklet.func=(void(*)(unsigned long))
- (
- (q_format==QDIO_IQDIO_QFMT)?&iqdio_inbound_processing:
- &qdio_inbound_processing);
+ ((irq_ptr->is_thinint_irq)?&tiqdio_inbound_processing:
+ &qdio_inbound_processing);

/* for (j=0;j<QDIO_STATS_NUMBER;j++)
q->timing.last_transfer_times[j]=(qdio_get_micros()/
@@ -1376,6 +1410,7 @@
q->is_input_q=0;
q->irq=irq_ptr->irq;
q->cdev = cdev;
+ q->irq_ptr = irq_ptr;
q->mask=1<<(31-i);
q->q_no=i;
q->first_to_check=0;
@@ -1454,7 +1489,7 @@
}

static int
-iqdio_thinint_handler(void)
+tiqdio_thinint_handler(void)
{
QDIO_DBF_TEXT4(0,trace,"thin_int");

@@ -1464,10 +1499,9 @@
#endif /* QDIO_PERFORMANCE_STATS */
/* VM will do the SVS for us */
if (!MACHINE_IS_VM)
- iqdio_clear_global_summary();
+ tiqdio_clear_global_summary();

- iqdio_inbound_checks();
- iqdio_check_for_polling();
+ tiqdio_inbound_checks();
return 0;
}

@@ -1814,9 +1848,10 @@
}

static unsigned int
-iqdio_check_chsc_availability(void)
+tiqdio_check_chsc_availability(void)
{
int result;
+ char dbf_text[15];

struct {
struct chsc_header request;
@@ -1871,6 +1906,12 @@
result=-ENOENT;
goto exit;
}
+
+ /* Check for hydra thin interrupts. */
+ hydra_thinints = ((scsc_area->general_char[2] & 0x10000000)
+ == 0x10000000);
+ sprintf(dbf_text,"hydra_ti%1x", hydra_thinints);
+ QDIO_DBF_TEXT0(0,setup,dbf_text);
exit:
free_page ((unsigned long) scsc_area);
return result;
@@ -1878,7 +1919,7 @@


static unsigned int
-iqdio_set_subchannel_ind(struct qdio_irq *irq_ptr, int reset_to_zero)
+tiqdio_set_subchannel_ind(struct qdio_irq *irq_ptr, int reset_to_zero)
{
unsigned long real_addr_local_summary_bit;
unsigned long real_addr_dev_st_chg_ind;
@@ -1907,7 +1948,7 @@
u32 reserved7;
} *scssc_area;

- if (!irq_ptr->is_iqdio_irq)
+ if (!irq_ptr->is_thinint_irq)
return -ENODEV;

if (reset_to_zero) {
@@ -1936,7 +1977,7 @@
scssc_area->subchannel_indicator_addr = real_addr_dev_st_chg_ind;
scssc_area->ks = QDIO_STORAGE_KEY;
scssc_area->kc = QDIO_STORAGE_KEY;
- scssc_area->isc = IQDIO_THININT_ISC;
+ scssc_area->isc = TIQDIO_THININT_ISC;
scssc_area->subsystem_id = (1<<16) + irq_ptr->irq;

result = chsc(scssc_area);
@@ -1972,7 +2013,7 @@
}

static unsigned int
-iqdio_set_delay_target(struct qdio_irq *irq_ptr, unsigned long delay_target)
+tiqdio_set_delay_target(struct qdio_irq *irq_ptr, unsigned long delay_target)
{
unsigned int resp_code;
int result;
@@ -1992,7 +2033,7 @@
u32 reserved6;
} *scsscf_area;

- if (!irq_ptr->is_iqdio_irq)
+ if (!irq_ptr->is_thinint_irq)
return -ENODEV;

scsscf_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
@@ -2082,7 +2123,7 @@
for (i=0;i<irq_ptr->no_output_qs;i++)
atomic_set(&irq_ptr->output_qs[i]->is_in_shutdown,1);

- tasklet_kill(&iqdio_tasklet);
+ tasklet_kill(&tiqdio_tasklet);

for (i=0;i<irq_ptr->no_input_qs;i++) {
qdio_unmark_q(irq_ptr->input_qs[i]);
@@ -2145,9 +2186,9 @@
static inline void
qdio_cleanup_finish(struct ccw_device *cdev, struct qdio_irq *irq_ptr)
{
- if (irq_ptr->is_iqdio_irq) {
+ if (irq_ptr->is_thinint_irq) {
qdio_put_indicator((__u32*)irq_ptr->dev_st_chg_ind);
- iqdio_set_subchannel_ind(irq_ptr,1);
+ tiqdio_set_subchannel_ind(irq_ptr,1);
/* reset adapter interrupt indicators */
}

@@ -2156,6 +2197,7 @@
cdev->handler=irq_ptr->original_int_handler;

qdio_set_state(irq_ptr,QDIO_IRQ_STATE_INACTIVE);
+
}

int
@@ -2228,13 +2270,14 @@
qdio_allocate_fill_input_desc(struct qdio_irq *irq_ptr, int i, int iqfmt)
{
irq_ptr->input_qs[i]->is_iqdio_q = iqfmt;
+ irq_ptr->input_qs[i]->is_thinint_q = irq_ptr->is_thinint_irq;

irq_ptr->qdr->qdf0[i].sliba=(unsigned long)(irq_ptr->input_qs[i]->slib);

irq_ptr->qdr->qdf0[i].sla=(unsigned long)(irq_ptr->input_qs[i]->sl);

irq_ptr->qdr->qdf0[i].slsba=
- (unsigned long)(&irq_ptr->input_qs[i]->slsb.acc.val[0]);
+ (unsigned long)(&irq_ptr->input_qs[i]->slsb.acc.val[0]);

irq_ptr->qdr->qdf0[i].akey=QDIO_STORAGE_KEY;
irq_ptr->qdr->qdf0[i].bkey=QDIO_STORAGE_KEY;
@@ -2247,9 +2290,9 @@
int j, int iqfmt)
{
irq_ptr->output_qs[i]->is_iqdio_q = iqfmt;
+ irq_ptr->output_qs[i]->is_thinint_q = irq_ptr->is_thinint_irq;

- irq_ptr->qdr->qdf0[i+j].sliba=
- (unsigned long)(irq_ptr->output_qs[i]->slib);
+ irq_ptr->qdr->qdf0[i+j].sliba=(unsigned long)(irq_ptr->output_qs[i]->slib);

irq_ptr->qdr->qdf0[i+j].sla=(unsigned long)(irq_ptr->output_qs[i]->sl);

@@ -2279,6 +2322,13 @@
irq_ptr->qdioac&CHSC_FLAG_SIGA_SYNC_DONE_ON_THININTS;
irq_ptr->input_qs[i]->hydra_gives_outbound_pcis=
irq_ptr->hydra_gives_outbound_pcis;
+ irq_ptr->input_qs[i]->siga_sync_done_on_outb_tis=
+ ((irq_ptr->qdioac&
+ (CHSC_FLAG_SIGA_SYNC_DONE_ON_OUTB_PCIS|
+ CHSC_FLAG_SIGA_SYNC_DONE_ON_THININTS))==
+ (CHSC_FLAG_SIGA_SYNC_DONE_ON_OUTB_PCIS|
+ CHSC_FLAG_SIGA_SYNC_DONE_ON_THININTS));
+
}
}

@@ -2298,6 +2348,13 @@
irq_ptr->qdioac&CHSC_FLAG_SIGA_SYNC_DONE_ON_THININTS;
irq_ptr->output_qs[i]->hydra_gives_outbound_pcis=
irq_ptr->hydra_gives_outbound_pcis;
+ irq_ptr->output_qs[i]->siga_sync_done_on_outb_tis=
+ ((irq_ptr->qdioac&
+ (CHSC_FLAG_SIGA_SYNC_DONE_ON_OUTB_PCIS|
+ CHSC_FLAG_SIGA_SYNC_DONE_ON_THININTS))==
+ (CHSC_FLAG_SIGA_SYNC_DONE_ON_OUTB_PCIS|
+ CHSC_FLAG_SIGA_SYNC_DONE_ON_THININTS));
+
}
}

@@ -2414,6 +2471,7 @@
struct ciw *ciw;
int result;
int is_iqdio;
+ char dbf_text[15];

if ( (init_data->no_input_qs>QDIO_MAX_QUEUES_PER_IRQ) ||
(init_data->no_output_qs>QDIO_MAX_QUEUES_PER_IRQ) ||
@@ -2460,9 +2518,18 @@
irq_ptr->no_input_qs=init_data->no_input_qs;
irq_ptr->no_output_qs=init_data->no_output_qs;

- irq_ptr->is_iqdio_irq=(init_data->q_format==QDIO_IQDIO_QFMT)?1:0;
+ if (init_data->q_format==QDIO_IQDIO_QFMT) {
+ irq_ptr->is_iqdio_irq=1;
+ irq_ptr->is_thinint_irq=1;
+ } else {
+ irq_ptr->is_iqdio_irq=0;
+ irq_ptr->is_thinint_irq=hydra_thinints;
+ }
+ sprintf(dbf_text,"is_i_t%1x%1x",
+ irq_ptr->is_iqdio_irq,irq_ptr->is_thinint_irq);
+ QDIO_DBF_TEXT2(0,setup,dbf_text);

- if (irq_ptr->is_iqdio_irq) {
+ if (irq_ptr->is_thinint_irq) {
irq_ptr->dev_st_chg_ind=qdio_get_indicator();
QDIO_DBF_HEX1(0,setup,&irq_ptr->dev_st_chg_ind,sizeof(void*));
if (!irq_ptr->dev_st_chg_ind) {
@@ -2522,10 +2589,10 @@

/* fill in qib */
irq_ptr->qib.qfmt=init_data->q_format;
- if (init_data->no_input_qs) irq_ptr->qib.isliba=
- (unsigned long)(irq_ptr->input_qs[0]->slib);
- if (init_data->no_output_qs) irq_ptr->qib.osliba=(unsigned long)
- (irq_ptr->output_qs[0]->slib);
+ if (init_data->no_input_qs)
+ irq_ptr->qib.isliba=(unsigned long)(irq_ptr->input_qs[0]->slib);
+ if (init_data->no_output_qs)
+ irq_ptr->qib.osliba=(unsigned long)(irq_ptr->output_qs[0]->slib);
memcpy(irq_ptr->qib.ebcnam,init_data->adapter_name,8);

qdio_set_impl_params(irq_ptr,init_data->qib_param_field_format,
@@ -2567,21 +2634,16 @@
irq_ptr->original_int_handler = init_data->cdev->handler;
init_data->cdev->handler = qdio_handler;

- /* the iqdio CHSC stuff */
- if (irq_ptr->is_iqdio_irq) {
-/* iqdio_enable_adapter_int_facility(irq_ptr);*/
-
- if (iqdio_check_chsc_availability()) {
- QDIO_PRINT_ERR("Not all CHSCs supported. " \
- "Continuing.\n");
- }
- result=iqdio_set_subchannel_ind(irq_ptr,0);
+ /* the thinint CHSC stuff */
+ if (irq_ptr->is_thinint_irq) {
+
+ result = tiqdio_set_subchannel_ind(irq_ptr,0);
if (result) {
up(&irq_ptr->setting_up_sema);
qdio_cleanup(init_data->cdev, QDIO_FLAG_CLEANUP_USING_CLEAR);
return result;
}
- iqdio_set_delay_target(irq_ptr,IQDIO_DELAY_TARGET);
+ tiqdio_set_delay_target(irq_ptr,TIQDIO_DELAY_TARGET);
}

up(&irq_ptr->setting_up_sema);
@@ -2620,7 +2682,7 @@

ccw_device_set_options(cdev, 0);
result=ccw_device_start_timeout(cdev,&irq_ptr->ccw,
- QDIO_DOING_ESTABLISH,0,0,
+ QDIO_DOING_ESTABLISH,0, 0,
QDIO_ESTABLISH_TIMEOUT);
if (result) {
result2=ccw_device_start_timeout(cdev,&irq_ptr->ccw,
@@ -2721,14 +2783,14 @@
goto out;

for (i=0;i<irq_ptr->no_input_qs;i++) {
- if (irq_ptr->is_iqdio_irq) {
+ if (irq_ptr->is_thinint_irq) {
/*
* that way we know, that, if we will get interrupted
- * by iqdio_inbound_processing, qdio_unmark_q will
+ * by tiqdio_inbound_processing, qdio_unmark_q will
* not be called
*/
qdio_reserve_q(irq_ptr->input_qs[i]);
- qdio_mark_iq(irq_ptr->input_qs[i]);
+ qdio_mark_tiq(irq_ptr->input_qs[i]);
qdio_release_q(irq_ptr->input_qs[i]);
}
}
@@ -2958,7 +3020,7 @@
perf_stats.siga_ins);
_OUTP_IT("Number of SIGA out's issued : %u\n",
perf_stats.siga_outs);
- _OUTP_IT("Number of PCI's caught : %u\n",
+ _OUTP_IT("Number of PCIs caught : %u\n",
perf_stats.pcis);
_OUTP_IT("Number of adapter interrupts caught : %u\n",
perf_stats.thinints);
@@ -3032,11 +3094,11 @@
}

static void
-iqdio_register_thinints(void)
+tiqdio_register_thinints(void)
{
char dbf_text[20];
register_thinint_result=
- s390_register_adapter_interrupt(&iqdio_thinint_handler);
+ s390_register_adapter_interrupt(&tiqdio_thinint_handler);
if (register_thinint_result) {
sprintf(dbf_text,"regthn%x",(register_thinint_result&0xff));
QDIO_DBF_TEXT0(0,setup,dbf_text);
@@ -3048,10 +3110,10 @@
}

static void
-iqdio_unregister_thinints(void)
+tiqdio_unregister_thinints(void)
{
if (!register_thinint_result)
- s390_unregister_adapter_interrupt(&iqdio_thinint_handler);
+ s390_unregister_adapter_interrupt(&tiqdio_thinint_handler);
}

static int
@@ -3191,7 +3253,11 @@
#endif /* QDIO_PERFORMANCE_STATS */

qdio_add_procfs_entry();
- iqdio_register_thinints();
+
+ if (tiqdio_check_chsc_availability())
+ QDIO_PRINT_ERR("Not all CHSCs supported. Continuing.\n");
+
+ tiqdio_register_thinints();

return 0;
}
@@ -3199,7 +3265,7 @@
static void __exit
cleanup_QDIO(void)
{
- iqdio_unregister_thinints();
+ tiqdio_unregister_thinints();
qdio_remove_procfs_entry();
qdio_release_qdio_memory();
qdio_unregister_dbf_views();
diff -urN linux-2.5/drivers/s390/cio/qdio.h linux-2.5-s390/drivers/s390/cio/qdio.h
--- linux-2.5/drivers/s390/cio/qdio.h Tue Jul 1 20:48:10 2003
+++ linux-2.5-s390/drivers/s390/cio/qdio.h Tue Jul 1 20:48:28 2003
@@ -1,7 +1,7 @@
#ifndef _CIO_QDIO_H
#define _CIO_QDIO_H

-#define VERSION_CIO_QDIO_H "$Revision: 1.17 $"
+#define VERSION_CIO_QDIO_H "$Revision: 1.18 $"

//#define QDIO_DBF_LIKE_HELL

@@ -31,8 +31,8 @@
*/
#define IQDIO_FILL_LEVEL_TO_POLL 4

-#define IQDIO_THININT_ISC 3
-#define IQDIO_DELAY_TARGET 0
+#define TIQDIO_THININT_ISC 3
+#define TIQDIO_DELAY_TARGET 0
#define QDIO_BUSY_BIT_PATIENCE 2000 /* in microsecs */
#define IQDIO_GLOBAL_LAPS 2 /* GLOBAL_LAPS are not used as we */
#define IQDIO_GLOBAL_LAPS_INT 1 /* don't global summary */
@@ -473,7 +473,13 @@

#define atomic_swap(a,b) xchg((int*)a.counter,b)

-#define SYNC_MEMORY if (q->siga_sync) qdio_siga_sync(q)
+/* unlikely as the later the better */
+#define SYNC_MEMORY if (unlikely(q->siga_sync)) qdio_siga_sync_q(q)
+#define SYNC_MEMORY_ALL if (unlikely(q->siga_sync)) \
+ qdio_siga_sync(q,~0U,~0U)
+#define SYNC_MEMORY_ALL_OUTB if (unlikely(q->siga_sync)) \
+ qdio_siga_sync(q,~0U,0)
+
#define NOW qdio_get_micros()
#define SAVE_TIMESTAMP(q) q->timing.last_transfer_time=NOW
#define GET_SAVED_TIMESTAMP(q) (q->timing.last_transfer_time)
@@ -519,6 +525,7 @@
struct ccw_device *cdev;

unsigned int is_iqdio_q;
+ unsigned int is_thinint_q;

/* bit 0 means queue 0, bit 1 means queue 1, ... */
unsigned int mask;
@@ -540,6 +547,7 @@
unsigned int siga_out;
unsigned int siga_sync;
unsigned int siga_sync_done_on_thinints;
+ unsigned int siga_sync_done_on_outb_tis;
unsigned int hydra_gives_outbound_pcis;

/* used to save beginning position when calling dd_handlers */
@@ -548,6 +556,8 @@
atomic_t use_count;
atomic_t is_in_shutdown;

+ void *irq_ptr;
+
#ifdef QDIO_USE_TIMERS_FOR_POLLING
struct timer_list timer;
atomic_t timer_already_set;
@@ -604,6 +614,7 @@
int irq;

unsigned int is_iqdio_irq;
+ unsigned int is_thinint_irq;
unsigned int hydra_gives_outbound_pcis;
unsigned int sync_done_on_outb_pcis;