aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--drivers/s390/cio/qdio.c37
-rw-r--r--drivers/s390/cio/qdio.h4
-rw-r--r--drivers/s390/net/qeth_main.c14
-rw-r--r--include/asm-s390/qdio.h1
4 files changed, 39 insertions, 17 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,
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index 032483513027..134f08c200d2 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -2816,6 +2816,7 @@ qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int,
2816 struct qeth_qdio_out_buffer *buf; 2816 struct qeth_qdio_out_buffer *buf;
2817 int rc; 2817 int rc;
2818 int i; 2818 int i;
2819 unsigned int qdio_flags;
2819 2820
2820 QETH_DBF_TEXT(trace, 6, "flushbuf"); 2821 QETH_DBF_TEXT(trace, 6, "flushbuf");
2821 2822
@@ -2859,13 +2860,13 @@ qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int,
2859 queue->card->perf_stats.outbound_do_qdio_start_time = 2860 queue->card->perf_stats.outbound_do_qdio_start_time =
2860 qeth_get_micros(); 2861 qeth_get_micros();
2861 } 2862 }
2863 qdio_flags = QDIO_FLAG_SYNC_OUTPUT;
2862 if (under_int) 2864 if (under_int)
2863 rc = do_QDIO(CARD_DDEV(queue->card), 2865 qdio_flags |= QDIO_FLAG_UNDER_INTERRUPT;
2864 QDIO_FLAG_SYNC_OUTPUT | QDIO_FLAG_UNDER_INTERRUPT, 2866 if (atomic_read(&queue->set_pci_flags_count))
2865 queue->queue_no, index, count, NULL); 2867 qdio_flags |= QDIO_FLAG_PCI_OUT;
2866 else 2868 rc = do_QDIO(CARD_DDEV(queue->card), qdio_flags,
2867 rc = do_QDIO(CARD_DDEV(queue->card), QDIO_FLAG_SYNC_OUTPUT, 2869 queue->queue_no, index, count, NULL);
2868 queue->queue_no, index, count, NULL);
2869 if (queue->card->options.performance_stats) 2870 if (queue->card->options.performance_stats)
2870 queue->card->perf_stats.outbound_do_qdio_time += 2871 queue->card->perf_stats.outbound_do_qdio_time +=
2871 qeth_get_micros() - 2872 qeth_get_micros() -
@@ -8498,6 +8499,7 @@ __qeth_reboot_event_card(struct device *dev, void *data)
8498 card = (struct qeth_card *) dev->driver_data; 8499 card = (struct qeth_card *) dev->driver_data;
8499 qeth_clear_ip_list(card, 0, 0); 8500 qeth_clear_ip_list(card, 0, 0);
8500 qeth_qdio_clear_card(card, 0); 8501 qeth_qdio_clear_card(card, 0);
8502 qeth_clear_qdio_buffers(card);
8501 return 0; 8503 return 0;
8502} 8504}
8503 8505
diff --git a/include/asm-s390/qdio.h b/include/asm-s390/qdio.h
index 127f72e77419..74db1dc10a7d 100644
--- a/include/asm-s390/qdio.h
+++ b/include/asm-s390/qdio.h
@@ -120,6 +120,7 @@ extern unsigned long qdio_get_status(int irq);
120#define QDIO_FLAG_NO_INPUT_INTERRUPT_CONTEXT 0x08 /* no effect on 120#define QDIO_FLAG_NO_INPUT_INTERRUPT_CONTEXT 0x08 /* no effect on
121 adapter interrupts */ 121 adapter interrupts */
122#define QDIO_FLAG_DONT_SIGA 0x10 122#define QDIO_FLAG_DONT_SIGA 0x10
123#define QDIO_FLAG_PCI_OUT 0x20
123 124
124extern int do_QDIO(struct ccw_device*, unsigned int flags, 125extern int do_QDIO(struct ccw_device*, unsigned int flags,
125 unsigned int queue_number, 126 unsigned int queue_number,