summaryrefslogtreecommitdiff
path: root/drivers/s390/cio/qdio_main.c
diff options
context:
space:
mode:
authorGrant Likely <grant.likely@secretlab.ca>2011-05-20 10:43:00 +0400
committerGrant Likely <grant.likely@secretlab.ca>2011-05-20 10:43:00 +0400
commit78fab4c04c76b8c9327541bd270f82b85b42bbf7 (patch)
treeb43006348a1ac15c28e6791d08646809761a2a4a /drivers/s390/cio/qdio_main.c
parent3b8a4dd3ebfcc647260ad5c39ef4f73eb3a6b155 (diff)
parent61c4f2c81c61f73549928dfd9f3e8f26aa36a8cf (diff)
downloadlinux-78fab4c04c76b8c9327541bd270f82b85b42bbf7.tar.xz
Merge commit 'v2.6.39' into spi/next
Diffstat (limited to 'drivers/s390/cio/qdio_main.c')
-rw-r--r--drivers/s390/cio/qdio_main.c33
1 files changed, 20 insertions, 13 deletions
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c
index 479c665e9e7c..e8f267eb8887 100644
--- a/drivers/s390/cio/qdio_main.c
+++ b/drivers/s390/cio/qdio_main.c
@@ -407,8 +407,11 @@ static inline void account_sbals(struct qdio_q *q, int count)
q->q_stats.nr_sbals[pos]++;
}
-static void announce_buffer_error(struct qdio_q *q, int count)
+static void process_buffer_error(struct qdio_q *q, int count)
{
+ unsigned char state = (q->is_input_q) ? SLSB_P_INPUT_NOT_INIT :
+ SLSB_P_OUTPUT_NOT_INIT;
+
q->qdio_error |= QDIO_ERROR_SLSB_STATE;
/* special handling for no target buffer empty */
@@ -426,6 +429,12 @@ static void announce_buffer_error(struct qdio_q *q, int count)
DBF_ERROR("F14:%2x F15:%2x",
q->sbal[q->first_to_check]->element[14].flags & 0xff,
q->sbal[q->first_to_check]->element[15].flags & 0xff);
+
+ /*
+ * Interrupts may be avoided as long as the error is present
+ * so change the buffer state immediately to avoid starvation.
+ */
+ set_buf_states(q, q->first_to_check, state, count);
}
static inline void inbound_primed(struct qdio_q *q, int count)
@@ -506,8 +515,7 @@ static int get_inbound_buffer_frontier(struct qdio_q *q)
account_sbals(q, count);
break;
case SLSB_P_INPUT_ERROR:
- announce_buffer_error(q, count);
- /* process the buffer, the upper layer will take care of it */
+ process_buffer_error(q, count);
q->first_to_check = add_buf(q->first_to_check, count);
atomic_sub(count, &q->nr_buf_used);
if (q->irq_ptr->perf_stat_enabled)
@@ -677,8 +685,7 @@ static int get_outbound_buffer_frontier(struct qdio_q *q)
account_sbals(q, count);
break;
case SLSB_P_OUTPUT_ERROR:
- announce_buffer_error(q, count);
- /* process the buffer, the upper layer will take care of it */
+ process_buffer_error(q, count);
q->first_to_check = add_buf(q->first_to_check, count);
atomic_sub(count, &q->nr_buf_used);
if (q->irq_ptr->perf_stat_enabled)
@@ -1649,26 +1656,26 @@ static int __init init_QDIO(void)
{
int rc;
- rc = qdio_setup_init();
+ rc = qdio_debug_init();
if (rc)
return rc;
+ rc = qdio_setup_init();
+ if (rc)
+ goto out_debug;
rc = tiqdio_allocate_memory();
if (rc)
goto out_cache;
- rc = qdio_debug_init();
- if (rc)
- goto out_ti;
rc = tiqdio_register_thinints();
if (rc)
- goto out_debug;
+ goto out_ti;
return 0;
-out_debug:
- qdio_debug_exit();
out_ti:
tiqdio_free_memory();
out_cache:
qdio_setup_exit();
+out_debug:
+ qdio_debug_exit();
return rc;
}
@@ -1676,8 +1683,8 @@ static void __exit exit_QDIO(void)
{
tiqdio_unregister_thinints();
tiqdio_free_memory();
- qdio_debug_exit();
qdio_setup_exit();
+ qdio_debug_exit();
}
module_init(init_QDIO);