Skip to content

Commit

Permalink
[S390] qdio: cleanup SIGA sync
Browse files Browse the repository at this point in the history
Simplify the SIGA sync code and add unlikely annotations. In polling mode
SBALs may be accessed without interrupt, so call SIGA sync before every scan.

Signed-off-by: Jan Glauber <jang@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
  • Loading branch information
Jan Glauber authored and Martin Schwidefsky committed Jan 5, 2011
1 parent 110da31 commit 90adac5
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 55 deletions.
16 changes: 8 additions & 8 deletions drivers/s390/cio/qdio.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,10 +148,9 @@ struct siga_flag {
u8 input:1;
u8 output:1;
u8 sync:1;
u8 no_sync_ti:1;
u8 no_sync_out_ti:1;
u8 no_sync_out_pci:1;
u8:2;
u8 sync_after_ai:1;
u8 sync_out_after_pci:1;
u8:3;
} __attribute__ ((packed));

struct chsc_ssqd_area {
Expand Down Expand Up @@ -390,12 +389,13 @@ static inline int multicast_outbound(struct qdio_q *q)
(q->irq_ptr->qib.ac & QIB_AC_OUTBOUND_PCI_SUPPORTED)
#define is_qebsm(q) (q->irq_ptr->sch_token != 0)

#define need_siga_sync_thinint(q) (!q->irq_ptr->siga_flag.no_sync_ti)
#define need_siga_sync_out_thinint(q) (!q->irq_ptr->siga_flag.no_sync_out_ti)
#define need_siga_in(q) (q->irq_ptr->siga_flag.input)
#define need_siga_out(q) (q->irq_ptr->siga_flag.output)
#define need_siga_sync(q) (q->irq_ptr->siga_flag.sync)
#define siga_syncs_out_pci(q) (q->irq_ptr->siga_flag.no_sync_out_pci)
#define need_siga_sync(q) (unlikely(q->irq_ptr->siga_flag.sync))
#define need_siga_sync_after_ai(q) \
(unlikely(q->irq_ptr->siga_flag.sync_after_ai))
#define need_siga_sync_out_after_pci(q) \
(unlikely(q->irq_ptr->siga_flag.sync_out_after_pci))

#define for_each_input_queue(irq_ptr, q, i) \
for (i = 0, q = irq_ptr->input_qs[0]; \
Expand Down
64 changes: 29 additions & 35 deletions drivers/s390/cio/qdio_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -286,9 +286,6 @@ static inline int qdio_siga_sync(struct qdio_q *q, unsigned int output,
unsigned int fc = QDIO_SIGA_SYNC;
int cc;

if (!need_siga_sync(q))
return 0;

DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-s:%1d", q->nr);
qperf_inc(q, siga_sync);

Expand All @@ -311,16 +308,6 @@ static inline int qdio_siga_sync_q(struct qdio_q *q)
return qdio_siga_sync(q, q->mask, 0);
}

static inline int qdio_siga_sync_out(struct qdio_q *q)
{
return qdio_siga_sync(q, ~0U, 0);
}

static inline int qdio_siga_sync_all(struct qdio_q *q)
{
return qdio_siga_sync(q, ~0U, ~0U);
}

static int qdio_siga_output(struct qdio_q *q, unsigned int *busy_bit)
{
unsigned long schid = *((u32 *) &q->irq_ptr->schid);
Expand Down Expand Up @@ -369,21 +356,23 @@ static inline int qdio_siga_input(struct qdio_q *q)
return cc;
}

static inline void qdio_sync_after_thinint(struct qdio_q *q)
#define qdio_siga_sync_out(q) qdio_siga_sync(q, ~0U, 0)
#define qdio_siga_sync_all(q) qdio_siga_sync(q, ~0U, ~0U)

static inline void qdio_sync_queues(struct qdio_q *q)
{
if (pci_out_supported(q)) {
if (need_siga_sync_thinint(q))
qdio_siga_sync_all(q);
else if (need_siga_sync_out_thinint(q))
qdio_siga_sync_out(q);
} else
/* PCI capable outbound queues will also be scanned so sync them too */
if (pci_out_supported(q))
qdio_siga_sync_all(q);
else
qdio_siga_sync_q(q);
}

int debug_get_buf_state(struct qdio_q *q, unsigned int bufnr,
unsigned char *state)
{
qdio_siga_sync_q(q);
if (need_siga_sync(q))
qdio_siga_sync_q(q);
return get_buf_states(q, bufnr, state, 1, 0);
}

Expand Down Expand Up @@ -560,7 +549,8 @@ static inline int qdio_inbound_q_done(struct qdio_q *q)
if (!atomic_read(&q->nr_buf_used))
return 1;

qdio_siga_sync_q(q);
if (need_siga_sync(q))
qdio_siga_sync_q(q);
get_buf_state(q, q->first_to_check, &state, 0);

if (state == SLSB_P_INPUT_PRIMED || state == SLSB_P_INPUT_ERROR)
Expand Down Expand Up @@ -655,9 +645,12 @@ static int get_outbound_buffer_frontier(struct qdio_q *q)
int count, stop;
unsigned char state;

if (((queue_type(q) != QDIO_IQDIO_QFMT) && !pci_out_supported(q)) ||
(queue_type(q) == QDIO_IQDIO_QFMT && multicast_outbound(q)))
qdio_siga_sync_q(q);
if (need_siga_sync(q))
if (((queue_type(q) != QDIO_IQDIO_QFMT) &&
!pci_out_supported(q)) ||
(queue_type(q) == QDIO_IQDIO_QFMT &&
multicast_outbound(q)))
qdio_siga_sync_q(q);

/*
* Don't check 128 buffers, as otherwise qdio_inbound_q_moved
Expand Down Expand Up @@ -829,7 +822,8 @@ static inline void qdio_check_outbound_after_thinint(struct qdio_q *q)
static void __tiqdio_inbound_processing(struct qdio_q *q)
{
qperf_inc(q, tasklet_inbound);
qdio_sync_after_thinint(q);
if (need_siga_sync(q) && need_siga_sync_after_ai(q))
qdio_sync_queues(q);

/*
* The interrupt could be caused by a PCI request. Check the
Expand Down Expand Up @@ -909,16 +903,14 @@ static void qdio_int_handler_pci(struct qdio_irq *irq_ptr)
tasklet_schedule(&q->tasklet);
}

if (!(irq_ptr->qib.ac & QIB_AC_OUTBOUND_PCI_SUPPORTED))
if (!pci_out_supported(q))
return;

for_each_output_queue(irq_ptr, q, i) {
if (qdio_outbound_q_done(q))
continue;

if (!siga_syncs_out_pci(q))
if (need_siga_sync(q) && need_siga_sync_out_after_pci(q))
qdio_siga_sync_q(q);

tasklet_schedule(&q->tasklet);
}
}
Expand Down Expand Up @@ -1470,7 +1462,7 @@ static int handle_outbound(struct qdio_q *q, unsigned int callflags,
WARN_ON_ONCE(count > 1 && !multicast_outbound(q));

rc = qdio_kick_outbound_q(q);
} else if (unlikely(need_siga_sync(q))) {
} else if (need_siga_sync(q)) {
rc = qdio_siga_sync_q(q);
} else {
/* try to fast requeue buffers */
Expand Down Expand Up @@ -1597,12 +1589,14 @@ int qdio_get_next_buffers(struct ccw_device *cdev, int nr, int *bufnr,
q = irq_ptr->input_qs[nr];
WARN_ON(queue_irqs_enabled(q));

qdio_sync_after_thinint(q);

/*
* The interrupt could be caused by a PCI request. Check the
* PCI capable outbound queues.
* Cannot rely on automatic sync after interrupt since queues may
* also be examined without interrupt.
*/
if (need_siga_sync(q))
qdio_sync_queues(q);

/* check the PCI capable outbound queues. */
qdio_check_outbound_after_thinint(q);

if (!qdio_inbound_q_moved(q))
Expand Down
19 changes: 7 additions & 12 deletions drivers/s390/cio/qdio_setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,14 +197,10 @@ static void process_ac_flags(struct qdio_irq *irq_ptr, unsigned char qdioac)
irq_ptr->siga_flag.output = 1;
if (qdioac & AC1_SIGA_SYNC_NEEDED)
irq_ptr->siga_flag.sync = 1;
if (qdioac & AC1_AUTOMATIC_SYNC_ON_THININT)
irq_ptr->siga_flag.no_sync_ti = 1;
if (qdioac & AC1_AUTOMATIC_SYNC_ON_OUT_PCI)
irq_ptr->siga_flag.no_sync_out_pci = 1;

if (irq_ptr->siga_flag.no_sync_out_pci &&
irq_ptr->siga_flag.no_sync_ti)
irq_ptr->siga_flag.no_sync_out_ti = 1;
if (!(qdioac & AC1_AUTOMATIC_SYNC_ON_THININT))
irq_ptr->siga_flag.sync_after_ai = 1;
if (!(qdioac & AC1_AUTOMATIC_SYNC_ON_OUT_PCI))
irq_ptr->siga_flag.sync_out_after_pci = 1;
}

static void check_and_setup_qebsm(struct qdio_irq *irq_ptr,
Expand Down Expand Up @@ -452,7 +448,7 @@ void qdio_print_subchannel_info(struct qdio_irq *irq_ptr,
char s[80];

snprintf(s, 80, "qdio: %s %s on SC %x using "
"AI:%d QEBSM:%d PCI:%d TDD:%d SIGA:%s%s%s%s%s%s\n",
"AI:%d QEBSM:%d PCI:%d TDD:%d SIGA:%s%s%s%s%s\n",
dev_name(&cdev->dev),
(irq_ptr->qib.qfmt == QDIO_QETH_QFMT) ? "OSA" :
((irq_ptr->qib.qfmt == QDIO_ZFCP_QFMT) ? "ZFCP" : "HS"),
Expand All @@ -464,9 +460,8 @@ void qdio_print_subchannel_info(struct qdio_irq *irq_ptr,
(irq_ptr->siga_flag.input) ? "R" : " ",
(irq_ptr->siga_flag.output) ? "W" : " ",
(irq_ptr->siga_flag.sync) ? "S" : " ",
(!irq_ptr->siga_flag.no_sync_ti) ? "A" : " ",
(!irq_ptr->siga_flag.no_sync_out_ti) ? "O" : " ",
(!irq_ptr->siga_flag.no_sync_out_pci) ? "P" : " ");
(irq_ptr->siga_flag.sync_after_ai) ? "A" : " ",
(irq_ptr->siga_flag.sync_out_after_pci) ? "P" : " ");
printk(KERN_INFO "%s", s);
}

Expand Down

0 comments on commit 90adac5

Please sign in to comment.