#include "ioasm.h"
#include "chsc.h"
-#define VERSION_QDIO_C "$Revision: 1.80 $"
+#define VERSION_QDIO_C "$Revision: 1.84 $"
/****************** MODULE PARAMETER VARIABLES ********************/
MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>");
static debug_info_t *qdio_dbf_sbal;
static debug_info_t *qdio_dbf_trace;
static debug_info_t *qdio_dbf_sense;
-#ifdef QDIO_DBF_LIKE_HELL
+#ifdef CONFIG_QDIO_DEBUG
static debug_info_t *qdio_dbf_slsb_out;
static debug_info_t *qdio_dbf_slsb_in;
-#endif /* QDIO_DBF_LIKE_HELL */
+#endif /* CONFIG_QDIO_DEBUG */
/* iQDIO stuff: */
static volatile struct qdio_q *tiq_list=NULL; /* volatile as it could change
SLSB_P_INPUT_NOT_INIT);
/*
* we don't issue this SYNC_MEMORY, as we trust Rick T and
- * moreover will not use the PROCESSING state, so q->polling was 0
+ * moreover will not use the PROCESSING state under VM, so
+ * q->polling was 0 anyway
*/
/*SYNC_MEMORY;*/
if (q->slsb.acc.val[gsf]!=SLSB_P_INPUT_PRIMED)
qdio_is_outbound_q_done(struct qdio_q *q)
{
int no_used;
+#ifdef CONFIG_QDIO_DEBUG
char dbf_text[15];
+#endif
no_used=atomic_read(&q->number_of_buffers_used);
+#ifdef CONFIG_QDIO_DEBUG
if (no_used) {
sprintf(dbf_text,"oqisnt%02x",no_used);
QDIO_DBF_TEXT4(0,trace,dbf_text);
QDIO_DBF_TEXT4(0,trace,"oqisdone");
}
QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
+#endif /* CONFIG_QDIO_DEBUG */
return (no_used==0);
}
qdio_kick_outbound_q(struct qdio_q *q)
{
int result;
+#ifdef CONFIG_QDIO_DEBUG
char dbf_text[15];
QDIO_DBF_TEXT4(0,trace,"kickoutq");
QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
+#endif /* CONFIG_QDIO_DEBUG */
if (!q->siga_out)
return;
switch (result) {
case 0:
- /* went smooth this time, reset timestamp */
+ /* went smooth this time, reset timestamp */
+#ifdef CONFIG_QDIO_DEBUG
QDIO_DBF_TEXT3(0,trace,"cc2reslv");
sprintf(dbf_text,"%4x%2x%2x",q->irq,q->q_no,
atomic_read(&q->busy_siga_counter));
QDIO_DBF_TEXT3(0,trace,dbf_text);
q->timing.busy_start=0;
+#endif /* CONFIG_QDIO_DEBUG */
break;
case (2|QDIO_SIGA_ERROR_B_BIT_SET):
/* cc=2 and busy bit: */
- atomic_inc(&q->busy_siga_counter);
+ atomic_inc(&q->busy_siga_counter);
/* if the last siga was successful, save
* timestamp here */
break;
}
QDIO_DBF_TEXT2(0,trace,"cc2REPRT");
+#ifdef CONFIG_QDIO_DEBUG
sprintf(dbf_text,"%4x%2x%2x",q->irq,q->q_no,
atomic_read(&q->busy_siga_counter));
QDIO_DBF_TEXT3(0,trace,dbf_text);
+#endif /* CONFIG_QDIO_DEBUG */
/* else fallthrough and report error */
default:
/* for plain cc=1, 2 or 3: */
qdio_kick_outbound_handler(struct qdio_q *q)
{
int start, end, real_end, count;
+#ifdef CONFIG_QDIO_DEBUG
char dbf_text[15];
+#endif
start = q->first_element_to_kick;
/* last_move_ftc was just updated */
count = (end+QDIO_MAX_BUFFERS_PER_Q+1-start)&
(QDIO_MAX_BUFFERS_PER_Q-1);
+#ifdef CONFIG_QDIO_DEBUG
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);
+#endif /* CONFIG_QDIO_DEBUG */
if (q->state==QDIO_IRQ_STATE_ACTIVE)
q->handler(q->cdev,QDIO_STATUS_OUTBOUND_INT|
int f,f_mod_no;
volatile char *slsb;
int first_not_to_check;
+#ifdef CONFIG_QDIO_DEBUG
char dbf_text[15];
+#endif /* CONFIG_QDIO_DEBUG */
+#ifdef QDIO_USE_PROCESSING_STATE
+ int last_position=-1;
+#endif /* QDIO_USE_PROCESSING_STATE */
QDIO_DBF_TEXT4(0,trace,"getibfro");
QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
if (q->siga_sync) {
set_slsb(&slsb[f_mod_no],SLSB_P_INPUT_NOT_INIT);
} else {
- set_slsb(&slsb[f_mod_no],SLSB_P_INPUT_PROCESSING);
+ /* set the previous buffer to NOT_INIT. The current
+ * buffer will be set to PROCESSING at the end of
+ * this function to avoid further interrupts. */
+ if (last_position>=0)
+ set_slsb(&slsb[last_position],
+ SLSB_P_INPUT_NOT_INIT);
atomic_set(&q->polling,1);
+ last_position=f_mod_no;
}
#else /* QDIO_USE_PROCESSING_STATE */
set_slsb(&slsb[f_mod_no],SLSB_P_INPUT_NOT_INIT);
/* P_ERROR means frontier is reached, break and report error */
case SLSB_P_INPUT_ERROR:
+#ifdef CONFIG_QDIO_DEBUG
sprintf(dbf_text,"inperr%2x",f_mod_no);
QDIO_DBF_TEXT3(1,trace,dbf_text);
+#endif /* CONFIG_QDIO_DEBUG */
QDIO_DBF_HEX2(1,sbal,q->sbal[f_mod_no],256);
/* kind of process the buffer */
f_mod_no=(f_mod_no+1)&(QDIO_MAX_BUFFERS_PER_Q-1);
atomic_dec(&q->number_of_buffers_used);
+#ifdef QDIO_USE_PROCESSING_STATE
+ last_position=-1;
+#endif /* QDIO_USE_PROCESSING_STATE */
+
break;
/* everything else means frontier not changed (HALTED or so) */
out:
q->first_to_check=f_mod_no;
+#ifdef QDIO_USE_PROCESSING_STATE
+ if (last_position>=0)
+ set_slsb(&slsb[last_position],SLSB_P_INPUT_PROCESSING);
+#endif /* QDIO_USE_PROCESSING_STATE */
+
QDIO_DBF_HEX4(0,trace,&q->first_to_check,sizeof(int));
return q->first_to_check;
iqdio_is_inbound_q_done(struct qdio_q *q)
{
int no_used;
+#ifdef CONFIG_QDIO_DEBUG
char dbf_text[15];
+#endif
no_used=atomic_read(&q->number_of_buffers_used);
/* propagate the change from 82 to 80 through VM */
SYNC_MEMORY;
+#ifdef CONFIG_QDIO_DEBUG
if (no_used) {
sprintf(dbf_text,"iqisnt%02x",no_used);
QDIO_DBF_TEXT4(0,trace,dbf_text);
QDIO_DBF_TEXT4(0,trace,"iniqisdo");
}
QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
+#endif /* CONFIG_QDIO_DEBUG */
if (!no_used)
return 1;
qdio_is_inbound_q_done(struct qdio_q *q)
{
int no_used;
+#ifdef CONFIG_QDIO_DEBUG
char dbf_text[15];
+#endif
no_used=atomic_read(&q->number_of_buffers_used);
* has (probably) not moved (see qdio_inbound_processing)
*/
if (NOW>GET_SAVED_TIMESTAMP(q)+q->timing.threshold) {
+#ifdef CONFIG_QDIO_DEBUG
QDIO_DBF_TEXT4(0,trace,"inqisdon");
QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
sprintf(dbf_text,"pf%02xcn%02x",q->first_to_check,no_used);
QDIO_DBF_TEXT4(0,trace,dbf_text);
+#endif /* CONFIG_QDIO_DEBUG */
return 1;
} else {
+#ifdef CONFIG_QDIO_DEBUG
QDIO_DBF_TEXT4(0,trace,"inqisntd");
QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
sprintf(dbf_text,"pf%02xcn%02x",q->first_to_check,no_used);
QDIO_DBF_TEXT4(0,trace,dbf_text);
+#endif /* CONFIG_QDIO_DEBUG */
return 0;
}
}
qdio_kick_inbound_handler(struct qdio_q *q)
{
int count, start, end, real_end, i;
+#ifdef CONFIG_QDIO_DEBUG
char dbf_text[15];
+#endif
QDIO_DBF_TEXT4(0,trace,"kickinh");
QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
i=(i+1)&(QDIO_MAX_BUFFERS_PER_Q-1);
}
+#ifdef CONFIG_QDIO_DEBUG
sprintf(dbf_text,"s=%2xc=%2x",start,count);
QDIO_DBF_TEXT4(0,trace,dbf_text);
+#endif /* CONFIG_QDIO_DEBUG */
if (likely(q->state==QDIO_IRQ_STATE_ACTIVE))
q->handler(q->cdev,
#ifdef QDIO_USE_PROCESSING_STATE
static inline int
-tiqdio_do_inbound_checks(struct qdio_q *q, int q_laps)
+tiqdio_reset_processing_state(struct qdio_q *q, int q_laps)
{
if (!q) {
tiqdio_sched_tl();
do {
int ret;
- ret = tiqdio_do_inbound_checks(q, q_laps);
+ ret = tiqdio_reset_processing_state(q, q_laps);
switch (ret) {
case 0:
return;
qdio_set_state(struct qdio_irq *irq_ptr, enum qdio_irq_states state)
{
int i;
+#ifdef CONFIG_QDIO_DEBUG
char dbf_text[15];
QDIO_DBF_TEXT5(0,trace,"newstate");
sprintf(dbf_text,"%4x%4x",irq_ptr->irq,state);
QDIO_DBF_TEXT5(0,trace,dbf_text);
+#endif /* CONFIG_QDIO_DEBUG */
irq_ptr->state=state;
for (i=0;i<irq_ptr->no_input_qs;i++)
int cstat,dstat;
char dbf_text[15];
+#ifdef CONFIG_QDIO_DEBUG
QDIO_DBF_TEXT4(0, trace, "qint");
sprintf(dbf_text, "%s", cdev->dev.bus_id);
QDIO_DBF_TEXT4(0, trace, dbf_text);
+#endif /* CONFIG_QDIO_DEBUG */
if (!intparm) {
QDIO_PRINT_ERR("got unsolicited interrupt in qdio " \
qdio_irq_check_sense(irq_ptr->irq, irb);
+#ifdef CONFIG_QDIO_DEBUG
sprintf(dbf_text, "state:%d", irq_ptr->state);
QDIO_DBF_TEXT4(0, trace, dbf_text);
+#endif /* CONFIG_QDIO_DEBUG */
cstat = irb->scsw.cstat;
dstat = irb->scsw.dstat;
int cc;
struct qdio_q *q;
struct qdio_irq *irq_ptr;
- char dbf_text[15]="SyncXXXX";
void *ptr;
+#ifdef CONFIG_QDIO_DEBUG
+ char dbf_text[15]="SyncXXXX";
+#endif
irq_ptr = cdev->private->qdio_data;
if (!irq_ptr)
return -ENODEV;
+#ifdef CONFIG_QDIO_DEBUG
*((int*)(&dbf_text[4])) = irq_ptr->irq;
QDIO_DBF_HEX4(0,trace,dbf_text,QDIO_DBF_TRACE_LEN);
*((int*)(&dbf_text[0]))=flags;
*((int*)(&dbf_text[4]))=queue_number;
QDIO_DBF_HEX4(0,trace,dbf_text,QDIO_DBF_TRACE_LEN);
+#endif /* CONFIG_QDIO_DEBUG */
if (flags&QDIO_FLAG_SYNC_INPUT) {
q=irq_ptr->input_qs[queue_number];
static unsigned int
tiqdio_check_chsc_availability(void)
{
- int result;
char dbf_text[15];
- struct {
- struct chsc_header request;
- u32 reserved1;
- u32 reserved2;
- u32 reserved3;
- struct chsc_header response;
- u32 reserved4;
- u32 general_char[510];
- u32 chsc_char[518];
- } *scsc_area;
-
- scsc_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
- if (!scsc_area) {
- QDIO_PRINT_WARN("Was not able to determine available" \
- "CHSCs due to no memory.\n");
- return -ENOMEM;
- }
-
- scsc_area->request = (struct chsc_header) {
- .length = 0x0010,
- .code = 0x0010,
- };
-
- result=chsc(scsc_area);
- if (result) {
- QDIO_PRINT_WARN("Was not able to determine " \
- "available CHSCs, cc=%i.\n",
- result);
- result=-EIO;
- goto exit;
- }
+ if (!css_characteristics_avail)
+ return -EIO;
- if (scsc_area->response.code != 1) {
- QDIO_PRINT_WARN("Was not able to determine " \
- "available CHSCs.\n");
- result=-EIO;
- goto exit;
- }
/* Check for bit 41. */
- if ((scsc_area->general_char[1] & 0x00400000) != 0x00400000) {
+ if (!css_general_characteristics.aif) {
QDIO_PRINT_WARN("Adapter interruption facility not " \
"installed.\n");
- result=-ENOENT;
- goto exit;
+ return -ENOENT;
}
/* Check for bits 107 and 108. */
- if ((scsc_area->chsc_char[3] & 0x00180000) != 0x00180000) {
+ if (!css_chsc_characteristics.scssc ||
+ !css_chsc_characteristics.scsscf) {
QDIO_PRINT_WARN("Set Chan Subsys. Char. & Fast-CHSCs " \
"not available.\n");
- result=-ENOENT;
- goto exit;
+ return -ENOENT;
}
/* Check for OSA/FCP thin interrupts (bit 67). */
- hydra_thinints = ((scsc_area->general_char[2] & 0x10000000)
- == 0x10000000);
+ hydra_thinints = css_general_characteristics.aif_osa;
sprintf(dbf_text,"hydrati%1x", hydra_thinints);
QDIO_DBF_TEXT0(0,setup,dbf_text);
/* Check for aif time delay disablement fac (bit 56). If installed,
* omit svs even under lpar (good point by rick again) */
- omit_svs = ((scsc_area->general_char[1] & 0x00000080)
- == 0x00000080);
+ omit_svs = css_general_characteristics.aif_tdd;
sprintf(dbf_text,"omitsvs%1x", omit_svs);
QDIO_DBF_TEXT0(0,setup,dbf_text);
-exit:
- free_page ((unsigned long) scsc_area);
- return result;
+ return 0;
}
unsigned int count,struct qdio_buffer *buffers)
{
struct qdio_irq *irq_ptr;
-
+#ifdef CONFIG_QDIO_DEBUG
char dbf_text[20];
sprintf(dbf_text,"doQD%04x",cdev->private->irq);
- QDIO_DBF_TEXT3(0,trace,dbf_text);
+ QDIO_DBF_TEXT3(0,trace,dbf_text);
+#endif /* CONFIG_QDIO_DEBUG */
if ( (qidx>QDIO_MAX_BUFFERS_PER_Q) ||
(count>QDIO_MAX_BUFFERS_PER_Q) ||
if (!irq_ptr)
return -ENODEV;
+#ifdef CONFIG_QDIO_DEBUG
if (callflags&QDIO_FLAG_SYNC_INPUT)
QDIO_DBF_HEX3(0,trace,&irq_ptr->input_qs[queue_number],
sizeof(void*));
QDIO_DBF_TEXT3(0,trace,dbf_text);
sprintf(dbf_text,"qi%02xct%02x",qidx,count);
QDIO_DBF_TEXT3(0,trace,dbf_text);
+#endif /* CONFIG_QDIO_DEBUG */
if (irq_ptr->state!=QDIO_IRQ_STATE_ACTIVE)
return -EBUSY;
debug_unregister(qdio_dbf_sense);
if (qdio_dbf_trace)
debug_unregister(qdio_dbf_trace);
-#ifdef QDIO_DBF_LIKE_HELL
+#ifdef CONFIG_QDIO_DEBUG
if (qdio_dbf_slsb_out)
debug_unregister(qdio_dbf_slsb_out);
if (qdio_dbf_slsb_in)
debug_unregister(qdio_dbf_slsb_in);
-#endif /* QDIO_DBF_LIKE_HELL */
+#endif /* CONFIG_QDIO_DEBUG */
}
static int
debug_register_view(qdio_dbf_trace,&debug_hex_ascii_view);
debug_set_level(qdio_dbf_trace,QDIO_DBF_TRACE_LEVEL);
-#ifdef QDIO_DBF_LIKE_HELL
+#ifdef CONFIG_QDIO_DEBUG
qdio_dbf_slsb_out=debug_register(QDIO_DBF_SLSB_OUT_NAME,
QDIO_DBF_SLSB_OUT_INDEX,
QDIO_DBF_SLSB_OUT_NR_AREAS,
goto oom;
debug_register_view(qdio_dbf_slsb_in,&debug_hex_ascii_view);
debug_set_level(qdio_dbf_slsb_in,QDIO_DBF_SLSB_IN_LEVEL);
-#endif /* QDIO_DBF_LIKE_HELL */
+#endif /* CONFIG_QDIO_DEBUG */
return 0;
oom:
QDIO_PRINT_ERR("not enough memory for dbf.\n");