aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio
diff options
context:
space:
mode:
authorUrsula Braun <braunu@de.ibm.com>2007-05-02 09:18:07 -0400
committerJeff Garzik <jeff@garzik.org>2007-05-08 01:16:23 -0400
commit1f8bdae9ef8e1ed2b208cdbaadb91061ede30212 (patch)
tree4b2da76796701c4142878ea189e2fad2adcc897c /drivers/s390/cio
parenta4c48a2691189cec0359ac13b41726d3005ef2f5 (diff)
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')
-rw-r--r--drivers/s390/cio/qdio.c37
-rw-r--r--drivers/s390/cio/qdio.h4
2 files changed, 30 insertions, 11 deletions
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
index cba64e4cfcd4..f770018fe1d5 100644
--- a/drivers/s390/cio/qdio.c
+++ b/drivers/s390/cio/qdio.c
@@ -996,18 +996,25 @@ __qdio_outbound_processing(struct qdio_q *q)
996 if (qdio_has_outbound_q_moved(q)) 996 if (qdio_has_outbound_q_moved(q))
997 qdio_kick_outbound_handler(q); 997 qdio_kick_outbound_handler(q);
998 998
999 if (q->is_iqdio_q) { 999 if (q->queue_type == QDIO_ZFCP_QFMT) {
1000 if ((!q->hydra_gives_outbound_pcis) &&
1001 (!qdio_is_outbound_q_done(q)))
1002 qdio_mark_q(q);
1003 }
1004 else if (((!q->is_iqdio_q) && (!q->is_pci_out)) ||
1005 (q->queue_type == QDIO_IQDIO_QFMT_ASYNCH)) {
1000 /* 1006 /*
1001 * for asynchronous queues, we better check, if the sent 1007 * make sure buffer switch from PRIMED to EMPTY is noticed
1002 * buffer is already switched from PRIMED to EMPTY. 1008 * and outbound_handler is called
1003 */ 1009 */
1004 if ((q->queue_type == QDIO_IQDIO_QFMT_ASYNCH) && 1010 if (qdio_is_outbound_q_done(q)) {
1005 !qdio_is_outbound_q_done(q)) 1011 del_timer(&q->timer);
1006 qdio_mark_q(q); 1012 } else {
1007 1013 if (!timer_pending(&q->timer))
1008 } else if (!q->hydra_gives_outbound_pcis) 1014 mod_timer(&q->timer, jiffies +
1009 if (!qdio_is_outbound_q_done(q)) 1015 QDIO_FORCE_CHECK_TIMEOUT);
1010 qdio_mark_q(q); 1016 }
1017 }
1011 1018
1012 qdio_release_q(q); 1019 qdio_release_q(q);
1013} 1020}
@@ -1826,6 +1833,7 @@ qdio_fill_qs(struct qdio_irq *irq_ptr, struct ccw_device *cdev,
1826 q->queue_type = QDIO_IQDIO_QFMT_ASYNCH; 1833 q->queue_type = QDIO_IQDIO_QFMT_ASYNCH;
1827 q->int_parm=int_parm; 1834 q->int_parm=int_parm;
1828 q->is_input_q=0; 1835 q->is_input_q=0;
1836 q->is_pci_out = 0;
1829 q->schid = irq_ptr->schid; 1837 q->schid = irq_ptr->schid;
1830 q->cdev = cdev; 1838 q->cdev = cdev;
1831 q->irq_ptr = irq_ptr; 1839 q->irq_ptr = irq_ptr;
@@ -1838,6 +1846,10 @@ qdio_fill_qs(struct qdio_irq *irq_ptr, struct ccw_device *cdev,
1838 q->tasklet.data=(unsigned long)q; 1846 q->tasklet.data=(unsigned long)q;
1839 q->tasklet.func=(void(*)(unsigned long)) 1847 q->tasklet.func=(void(*)(unsigned long))
1840 &qdio_outbound_processing; 1848 &qdio_outbound_processing;
1849 q->timer.function=(void(*)(unsigned long))
1850 &qdio_outbound_processing;
1851 q->timer.data = (long)q;
1852 init_timer(&q->timer);
1841 1853
1842 atomic_set(&q->busy_siga_counter,0); 1854 atomic_set(&q->busy_siga_counter,0);
1843 q->timing.busy_start=0; 1855 q->timing.busy_start=0;
@@ -2635,6 +2647,7 @@ qdio_shutdown(struct ccw_device *cdev, int how)
2635 2647
2636 for (i=0;i<irq_ptr->no_output_qs;i++) { 2648 for (i=0;i<irq_ptr->no_output_qs;i++) {
2637 tasklet_kill(&irq_ptr->output_qs[i]->tasklet); 2649 tasklet_kill(&irq_ptr->output_qs[i]->tasklet);
2650 del_timer(&irq_ptr->output_qs[i]->timer);
2638 wait_event_interruptible_timeout(cdev->private->wait_q, 2651 wait_event_interruptible_timeout(cdev->private->wait_q,
2639 !atomic_read(&irq_ptr-> 2652 !atomic_read(&irq_ptr->
2640 output_qs[i]-> 2653 output_qs[i]->
@@ -3458,6 +3471,10 @@ do_qdio_handle_outbound(struct qdio_q *q, unsigned int callflags,
3458 qdio_perf_stat_inc(&perf_stats.outbound_cnt); 3471 qdio_perf_stat_inc(&perf_stats.outbound_cnt);
3459 return; 3472 return;
3460 } 3473 }
3474 if (callflags & QDIO_FLAG_PCI_OUT)
3475 q->is_pci_out = 1;
3476 else
3477 q->is_pci_out = 0;
3461 if (q->is_iqdio_q) { 3478 if (q->is_iqdio_q) {
3462 /* one siga for every sbal */ 3479 /* one siga for every sbal */
3463 while (count--) 3480 while (count--)
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h
index 2895392eaae4..6d7aad18f6f0 100644
--- a/drivers/s390/cio/qdio.h
+++ b/drivers/s390/cio/qdio.h
@@ -60,6 +60,7 @@
60#define QDIO_ACTIVATE_TIMEOUT ((5*HZ)>>10) 60#define QDIO_ACTIVATE_TIMEOUT ((5*HZ)>>10)
61#define QDIO_CLEANUP_CLEAR_TIMEOUT (20*HZ) 61#define QDIO_CLEANUP_CLEAR_TIMEOUT (20*HZ)
62#define QDIO_CLEANUP_HALT_TIMEOUT (10*HZ) 62#define QDIO_CLEANUP_HALT_TIMEOUT (10*HZ)
63#define QDIO_FORCE_CHECK_TIMEOUT (10*HZ)
63 64
64enum qdio_irq_states { 65enum qdio_irq_states {
65 QDIO_IRQ_STATE_INACTIVE, 66 QDIO_IRQ_STATE_INACTIVE,
@@ -511,8 +512,8 @@ struct qdio_q {
511 512
512 void *irq_ptr; 513 void *irq_ptr;
513 514
514#ifdef QDIO_USE_TIMERS_FOR_POLLING
515 struct timer_list timer; 515 struct timer_list timer;
516#ifdef QDIO_USE_TIMERS_FOR_POLLING
516 atomic_t timer_already_set; 517 atomic_t timer_already_set;
517 spinlock_t timer_lock; 518 spinlock_t timer_lock;
518#else /* QDIO_USE_TIMERS_FOR_POLLING */ 519#else /* QDIO_USE_TIMERS_FOR_POLLING */
@@ -558,6 +559,7 @@ struct qdio_q {
558 } timing; 559 } timing;
559 atomic_t busy_siga_counter; 560 atomic_t busy_siga_counter;
560 unsigned int queue_type; 561 unsigned int queue_type;
562 unsigned int is_pci_out;
561 563
562 /* leave this member at the end. won't be cleared in qdio_fill_qs */ 564 /* leave this member at the end. won't be cleared in qdio_fill_qs */
563 struct slib *slib; /* a page is allocated under this pointer, 565 struct slib *slib; /* a page is allocated under this pointer,