[S390] qdio: cleanup SIGA sync
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>
This commit is contained in:
parent
110da31709
commit
90adac58d1
|
@ -148,10 +148,9 @@ struct siga_flag {
|
||||||
u8 input:1;
|
u8 input:1;
|
||||||
u8 output:1;
|
u8 output:1;
|
||||||
u8 sync:1;
|
u8 sync:1;
|
||||||
u8 no_sync_ti:1;
|
u8 sync_after_ai:1;
|
||||||
u8 no_sync_out_ti:1;
|
u8 sync_out_after_pci:1;
|
||||||
u8 no_sync_out_pci:1;
|
u8:3;
|
||||||
u8:2;
|
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
struct chsc_ssqd_area {
|
struct chsc_ssqd_area {
|
||||||
|
@ -390,12 +389,13 @@ static inline int multicast_outbound(struct qdio_q *q)
|
||||||
(q->irq_ptr->qib.ac & QIB_AC_OUTBOUND_PCI_SUPPORTED)
|
(q->irq_ptr->qib.ac & QIB_AC_OUTBOUND_PCI_SUPPORTED)
|
||||||
#define is_qebsm(q) (q->irq_ptr->sch_token != 0)
|
#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_in(q) (q->irq_ptr->siga_flag.input)
|
||||||
#define need_siga_out(q) (q->irq_ptr->siga_flag.output)
|
#define need_siga_out(q) (q->irq_ptr->siga_flag.output)
|
||||||
#define need_siga_sync(q) (q->irq_ptr->siga_flag.sync)
|
#define need_siga_sync(q) (unlikely(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_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) \
|
#define for_each_input_queue(irq_ptr, q, i) \
|
||||||
for (i = 0, q = irq_ptr->input_qs[0]; \
|
for (i = 0, q = irq_ptr->input_qs[0]; \
|
||||||
|
|
|
@ -286,9 +286,6 @@ static inline int qdio_siga_sync(struct qdio_q *q, unsigned int output,
|
||||||
unsigned int fc = QDIO_SIGA_SYNC;
|
unsigned int fc = QDIO_SIGA_SYNC;
|
||||||
int cc;
|
int cc;
|
||||||
|
|
||||||
if (!need_siga_sync(q))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-s:%1d", q->nr);
|
DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-s:%1d", q->nr);
|
||||||
qperf_inc(q, siga_sync);
|
qperf_inc(q, siga_sync);
|
||||||
|
|
||||||
|
@ -311,16 +308,6 @@ static inline int qdio_siga_sync_q(struct qdio_q *q)
|
||||||
return qdio_siga_sync(q, q->mask, 0);
|
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)
|
static int qdio_siga_output(struct qdio_q *q, unsigned int *busy_bit)
|
||||||
{
|
{
|
||||||
unsigned long schid = *((u32 *) &q->irq_ptr->schid);
|
unsigned long schid = *((u32 *) &q->irq_ptr->schid);
|
||||||
|
@ -369,20 +356,22 @@ static inline int qdio_siga_input(struct qdio_q *q)
|
||||||
return cc;
|
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)) {
|
/* PCI capable outbound queues will also be scanned so sync them too */
|
||||||
if (need_siga_sync_thinint(q))
|
if (pci_out_supported(q))
|
||||||
qdio_siga_sync_all(q);
|
qdio_siga_sync_all(q);
|
||||||
else if (need_siga_sync_out_thinint(q))
|
else
|
||||||
qdio_siga_sync_out(q);
|
|
||||||
} else
|
|
||||||
qdio_siga_sync_q(q);
|
qdio_siga_sync_q(q);
|
||||||
}
|
}
|
||||||
|
|
||||||
int debug_get_buf_state(struct qdio_q *q, unsigned int bufnr,
|
int debug_get_buf_state(struct qdio_q *q, unsigned int bufnr,
|
||||||
unsigned char *state)
|
unsigned char *state)
|
||||||
{
|
{
|
||||||
|
if (need_siga_sync(q))
|
||||||
qdio_siga_sync_q(q);
|
qdio_siga_sync_q(q);
|
||||||
return get_buf_states(q, bufnr, state, 1, 0);
|
return get_buf_states(q, bufnr, state, 1, 0);
|
||||||
}
|
}
|
||||||
|
@ -560,6 +549,7 @@ static inline int qdio_inbound_q_done(struct qdio_q *q)
|
||||||
if (!atomic_read(&q->nr_buf_used))
|
if (!atomic_read(&q->nr_buf_used))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
if (need_siga_sync(q))
|
||||||
qdio_siga_sync_q(q);
|
qdio_siga_sync_q(q);
|
||||||
get_buf_state(q, q->first_to_check, &state, 0);
|
get_buf_state(q, q->first_to_check, &state, 0);
|
||||||
|
|
||||||
|
@ -655,8 +645,11 @@ static int get_outbound_buffer_frontier(struct qdio_q *q)
|
||||||
int count, stop;
|
int count, stop;
|
||||||
unsigned char state;
|
unsigned char state;
|
||||||
|
|
||||||
if (((queue_type(q) != QDIO_IQDIO_QFMT) && !pci_out_supported(q)) ||
|
if (need_siga_sync(q))
|
||||||
(queue_type(q) == QDIO_IQDIO_QFMT && multicast_outbound(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);
|
qdio_siga_sync_q(q);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -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)
|
static void __tiqdio_inbound_processing(struct qdio_q *q)
|
||||||
{
|
{
|
||||||
qperf_inc(q, tasklet_inbound);
|
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
|
* The interrupt could be caused by a PCI request. Check the
|
||||||
|
@ -909,16 +903,14 @@ static void qdio_int_handler_pci(struct qdio_irq *irq_ptr)
|
||||||
tasklet_schedule(&q->tasklet);
|
tasklet_schedule(&q->tasklet);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(irq_ptr->qib.ac & QIB_AC_OUTBOUND_PCI_SUPPORTED))
|
if (!pci_out_supported(q))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for_each_output_queue(irq_ptr, q, i) {
|
for_each_output_queue(irq_ptr, q, i) {
|
||||||
if (qdio_outbound_q_done(q))
|
if (qdio_outbound_q_done(q))
|
||||||
continue;
|
continue;
|
||||||
|
if (need_siga_sync(q) && need_siga_sync_out_after_pci(q))
|
||||||
if (!siga_syncs_out_pci(q))
|
|
||||||
qdio_siga_sync_q(q);
|
qdio_siga_sync_q(q);
|
||||||
|
|
||||||
tasklet_schedule(&q->tasklet);
|
tasklet_schedule(&q->tasklet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1470,7 +1462,7 @@ static int handle_outbound(struct qdio_q *q, unsigned int callflags,
|
||||||
WARN_ON_ONCE(count > 1 && !multicast_outbound(q));
|
WARN_ON_ONCE(count > 1 && !multicast_outbound(q));
|
||||||
|
|
||||||
rc = qdio_kick_outbound_q(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);
|
rc = qdio_siga_sync_q(q);
|
||||||
} else {
|
} else {
|
||||||
/* try to fast requeue buffers */
|
/* try to fast requeue buffers */
|
||||||
|
@ -1597,12 +1589,14 @@ int qdio_get_next_buffers(struct ccw_device *cdev, int nr, int *bufnr,
|
||||||
q = irq_ptr->input_qs[nr];
|
q = irq_ptr->input_qs[nr];
|
||||||
WARN_ON(queue_irqs_enabled(q));
|
WARN_ON(queue_irqs_enabled(q));
|
||||||
|
|
||||||
qdio_sync_after_thinint(q);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The interrupt could be caused by a PCI request. Check the
|
* Cannot rely on automatic sync after interrupt since queues may
|
||||||
* PCI capable outbound queues.
|
* 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);
|
qdio_check_outbound_after_thinint(q);
|
||||||
|
|
||||||
if (!qdio_inbound_q_moved(q))
|
if (!qdio_inbound_q_moved(q))
|
||||||
|
|
|
@ -197,14 +197,10 @@ static void process_ac_flags(struct qdio_irq *irq_ptr, unsigned char qdioac)
|
||||||
irq_ptr->siga_flag.output = 1;
|
irq_ptr->siga_flag.output = 1;
|
||||||
if (qdioac & AC1_SIGA_SYNC_NEEDED)
|
if (qdioac & AC1_SIGA_SYNC_NEEDED)
|
||||||
irq_ptr->siga_flag.sync = 1;
|
irq_ptr->siga_flag.sync = 1;
|
||||||
if (qdioac & AC1_AUTOMATIC_SYNC_ON_THININT)
|
if (!(qdioac & AC1_AUTOMATIC_SYNC_ON_THININT))
|
||||||
irq_ptr->siga_flag.no_sync_ti = 1;
|
irq_ptr->siga_flag.sync_after_ai = 1;
|
||||||
if (qdioac & AC1_AUTOMATIC_SYNC_ON_OUT_PCI)
|
if (!(qdioac & AC1_AUTOMATIC_SYNC_ON_OUT_PCI))
|
||||||
irq_ptr->siga_flag.no_sync_out_pci = 1;
|
irq_ptr->siga_flag.sync_out_after_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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void check_and_setup_qebsm(struct qdio_irq *irq_ptr,
|
static void check_and_setup_qebsm(struct qdio_irq *irq_ptr,
|
||||||
|
@ -452,7 +448,7 @@ void qdio_print_subchannel_info(struct qdio_irq *irq_ptr,
|
||||||
char s[80];
|
char s[80];
|
||||||
|
|
||||||
snprintf(s, 80, "qdio: %s %s on SC %x using "
|
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),
|
dev_name(&cdev->dev),
|
||||||
(irq_ptr->qib.qfmt == QDIO_QETH_QFMT) ? "OSA" :
|
(irq_ptr->qib.qfmt == QDIO_QETH_QFMT) ? "OSA" :
|
||||||
((irq_ptr->qib.qfmt == QDIO_ZFCP_QFMT) ? "ZFCP" : "HS"),
|
((irq_ptr->qib.qfmt == QDIO_ZFCP_QFMT) ? "ZFCP" : "HS"),
|
||||||
|
@ -464,9 +460,8 @@ void qdio_print_subchannel_info(struct qdio_irq *irq_ptr,
|
||||||
(irq_ptr->siga_flag.input) ? "R" : " ",
|
(irq_ptr->siga_flag.input) ? "R" : " ",
|
||||||
(irq_ptr->siga_flag.output) ? "W" : " ",
|
(irq_ptr->siga_flag.output) ? "W" : " ",
|
||||||
(irq_ptr->siga_flag.sync) ? "S" : " ",
|
(irq_ptr->siga_flag.sync) ? "S" : " ",
|
||||||
(!irq_ptr->siga_flag.no_sync_ti) ? "A" : " ",
|
(irq_ptr->siga_flag.sync_after_ai) ? "A" : " ",
|
||||||
(!irq_ptr->siga_flag.no_sync_out_ti) ? "O" : " ",
|
(irq_ptr->siga_flag.sync_out_after_pci) ? "P" : " ");
|
||||||
(!irq_ptr->siga_flag.no_sync_out_pci) ? "P" : " ");
|
|
||||||
printk(KERN_INFO "%s", s);
|
printk(KERN_INFO "%s", s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue