diff options
author | Ursula Braun <braunu@de.ibm.com> | 2007-05-02 15:18:07 +0200 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-05-08 01:16:23 -0400 |
commit | 1f8bdae9ef8e1ed2b208cdbaadb91061ede30212 (patch) | |
tree | 4b2da76796701c4142878ea189e2fad2adcc897c /drivers/s390/cio/qdio.c | |
parent | a4c48a2691189cec0359ac13b41726d3005ef2f5 (diff) | |
download | op-kernel-dev-1f8bdae9ef8e1ed2b208cdbaadb91061ede30212.zip op-kernel-dev-1f8bdae9ef8e1ed2b208cdbaadb91061ede30212.tar.gz |
s390: free skbs in finite amount of time in qeth
Free sent skbs in some finite amount of time. Affected are
asynchronous queue of Hipersockets devices and the output
queues of all eth-devices respectively.
Signed-off-by: Ursula Braun <braunu@de.ibm.com>
Signed-off-by: Frank Pavlic <fpavlic@de.ibm.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/s390/cio/qdio.c')
-rw-r--r-- | drivers/s390/cio/qdio.c | 37 |
1 files changed, 27 insertions, 10 deletions
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c index cba64e4..f770018 100644 --- a/drivers/s390/cio/qdio.c +++ b/drivers/s390/cio/qdio.c @@ -996,18 +996,25 @@ __qdio_outbound_processing(struct qdio_q *q) if (qdio_has_outbound_q_moved(q)) qdio_kick_outbound_handler(q); - if (q->is_iqdio_q) { + if (q->queue_type == QDIO_ZFCP_QFMT) { + if ((!q->hydra_gives_outbound_pcis) && + (!qdio_is_outbound_q_done(q))) + qdio_mark_q(q); + } + else if (((!q->is_iqdio_q) && (!q->is_pci_out)) || + (q->queue_type == QDIO_IQDIO_QFMT_ASYNCH)) { /* - * for asynchronous queues, we better check, if the sent - * buffer is already switched from PRIMED to EMPTY. + * make sure buffer switch from PRIMED to EMPTY is noticed + * and outbound_handler is called */ - if ((q->queue_type == QDIO_IQDIO_QFMT_ASYNCH) && - !qdio_is_outbound_q_done(q)) - qdio_mark_q(q); - - } else if (!q->hydra_gives_outbound_pcis) - if (!qdio_is_outbound_q_done(q)) - qdio_mark_q(q); + if (qdio_is_outbound_q_done(q)) { + del_timer(&q->timer); + } else { + if (!timer_pending(&q->timer)) + mod_timer(&q->timer, jiffies + + QDIO_FORCE_CHECK_TIMEOUT); + } + } qdio_release_q(q); } @@ -1826,6 +1833,7 @@ qdio_fill_qs(struct qdio_irq *irq_ptr, struct ccw_device *cdev, q->queue_type = QDIO_IQDIO_QFMT_ASYNCH; q->int_parm=int_parm; q->is_input_q=0; + q->is_pci_out = 0; q->schid = irq_ptr->schid; q->cdev = cdev; q->irq_ptr = irq_ptr; @@ -1838,6 +1846,10 @@ qdio_fill_qs(struct qdio_irq *irq_ptr, struct ccw_device *cdev, q->tasklet.data=(unsigned long)q; q->tasklet.func=(void(*)(unsigned long)) &qdio_outbound_processing; + q->timer.function=(void(*)(unsigned long)) + &qdio_outbound_processing; + q->timer.data = (long)q; + init_timer(&q->timer); atomic_set(&q->busy_siga_counter,0); q->timing.busy_start=0; @@ -2635,6 +2647,7 @@ qdio_shutdown(struct ccw_device *cdev, int how) for (i=0;i<irq_ptr->no_output_qs;i++) { tasklet_kill(&irq_ptr->output_qs[i]->tasklet); + del_timer(&irq_ptr->output_qs[i]->timer); wait_event_interruptible_timeout(cdev->private->wait_q, !atomic_read(&irq_ptr-> output_qs[i]-> @@ -3458,6 +3471,10 @@ do_qdio_handle_outbound(struct qdio_q *q, unsigned int callflags, qdio_perf_stat_inc(&perf_stats.outbound_cnt); return; } + if (callflags & QDIO_FLAG_PCI_OUT) + q->is_pci_out = 1; + else + q->is_pci_out = 0; if (q->is_iqdio_q) { /* one siga for every sbal */ while (count--) |