提交 1f8bdae9 编写于 作者: U Ursula Braun 提交者: Jeff Garzik

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: NUrsula Braun <braunu@de.ibm.com>
Signed-off-by: NFrank Pavlic <fpavlic@de.ibm.com>
Signed-off-by: NJeff Garzik <jeff@garzik.org>
上级 a4c48a26
...@@ -996,18 +996,25 @@ __qdio_outbound_processing(struct qdio_q *q) ...@@ -996,18 +996,25 @@ __qdio_outbound_processing(struct qdio_q *q)
if (qdio_has_outbound_q_moved(q)) if (qdio_has_outbound_q_moved(q))
qdio_kick_outbound_handler(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 * make sure buffer switch from PRIMED to EMPTY is noticed
* buffer is already switched from PRIMED to EMPTY. * and outbound_handler is called
*/ */
if ((q->queue_type == QDIO_IQDIO_QFMT_ASYNCH) && if (qdio_is_outbound_q_done(q)) {
!qdio_is_outbound_q_done(q)) del_timer(&q->timer);
qdio_mark_q(q); } else {
if (!timer_pending(&q->timer))
} else if (!q->hydra_gives_outbound_pcis) mod_timer(&q->timer, jiffies +
if (!qdio_is_outbound_q_done(q)) QDIO_FORCE_CHECK_TIMEOUT);
qdio_mark_q(q); }
}
qdio_release_q(q); qdio_release_q(q);
} }
...@@ -1826,6 +1833,7 @@ qdio_fill_qs(struct qdio_irq *irq_ptr, struct ccw_device *cdev, ...@@ -1826,6 +1833,7 @@ qdio_fill_qs(struct qdio_irq *irq_ptr, struct ccw_device *cdev,
q->queue_type = QDIO_IQDIO_QFMT_ASYNCH; q->queue_type = QDIO_IQDIO_QFMT_ASYNCH;
q->int_parm=int_parm; q->int_parm=int_parm;
q->is_input_q=0; q->is_input_q=0;
q->is_pci_out = 0;
q->schid = irq_ptr->schid; q->schid = irq_ptr->schid;
q->cdev = cdev; q->cdev = cdev;
q->irq_ptr = irq_ptr; q->irq_ptr = irq_ptr;
...@@ -1838,6 +1846,10 @@ qdio_fill_qs(struct qdio_irq *irq_ptr, struct ccw_device *cdev, ...@@ -1838,6 +1846,10 @@ qdio_fill_qs(struct qdio_irq *irq_ptr, struct ccw_device *cdev,
q->tasklet.data=(unsigned long)q; q->tasklet.data=(unsigned long)q;
q->tasklet.func=(void(*)(unsigned long)) q->tasklet.func=(void(*)(unsigned long))
&qdio_outbound_processing; &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); atomic_set(&q->busy_siga_counter,0);
q->timing.busy_start=0; q->timing.busy_start=0;
...@@ -2635,6 +2647,7 @@ qdio_shutdown(struct ccw_device *cdev, int how) ...@@ -2635,6 +2647,7 @@ qdio_shutdown(struct ccw_device *cdev, int how)
for (i=0;i<irq_ptr->no_output_qs;i++) { for (i=0;i<irq_ptr->no_output_qs;i++) {
tasklet_kill(&irq_ptr->output_qs[i]->tasklet); tasklet_kill(&irq_ptr->output_qs[i]->tasklet);
del_timer(&irq_ptr->output_qs[i]->timer);
wait_event_interruptible_timeout(cdev->private->wait_q, wait_event_interruptible_timeout(cdev->private->wait_q,
!atomic_read(&irq_ptr-> !atomic_read(&irq_ptr->
output_qs[i]-> output_qs[i]->
...@@ -3458,6 +3471,10 @@ do_qdio_handle_outbound(struct qdio_q *q, unsigned int callflags, ...@@ -3458,6 +3471,10 @@ do_qdio_handle_outbound(struct qdio_q *q, unsigned int callflags,
qdio_perf_stat_inc(&perf_stats.outbound_cnt); qdio_perf_stat_inc(&perf_stats.outbound_cnt);
return; return;
} }
if (callflags & QDIO_FLAG_PCI_OUT)
q->is_pci_out = 1;
else
q->is_pci_out = 0;
if (q->is_iqdio_q) { if (q->is_iqdio_q) {
/* one siga for every sbal */ /* one siga for every sbal */
while (count--) while (count--)
......
...@@ -60,6 +60,7 @@ ...@@ -60,6 +60,7 @@
#define QDIO_ACTIVATE_TIMEOUT ((5*HZ)>>10) #define QDIO_ACTIVATE_TIMEOUT ((5*HZ)>>10)
#define QDIO_CLEANUP_CLEAR_TIMEOUT (20*HZ) #define QDIO_CLEANUP_CLEAR_TIMEOUT (20*HZ)
#define QDIO_CLEANUP_HALT_TIMEOUT (10*HZ) #define QDIO_CLEANUP_HALT_TIMEOUT (10*HZ)
#define QDIO_FORCE_CHECK_TIMEOUT (10*HZ)
enum qdio_irq_states { enum qdio_irq_states {
QDIO_IRQ_STATE_INACTIVE, QDIO_IRQ_STATE_INACTIVE,
...@@ -511,8 +512,8 @@ struct qdio_q { ...@@ -511,8 +512,8 @@ struct qdio_q {
void *irq_ptr; void *irq_ptr;
#ifdef QDIO_USE_TIMERS_FOR_POLLING
struct timer_list timer; struct timer_list timer;
#ifdef QDIO_USE_TIMERS_FOR_POLLING
atomic_t timer_already_set; atomic_t timer_already_set;
spinlock_t timer_lock; spinlock_t timer_lock;
#else /* QDIO_USE_TIMERS_FOR_POLLING */ #else /* QDIO_USE_TIMERS_FOR_POLLING */
...@@ -558,6 +559,7 @@ struct qdio_q { ...@@ -558,6 +559,7 @@ struct qdio_q {
} timing; } timing;
atomic_t busy_siga_counter; atomic_t busy_siga_counter;
unsigned int queue_type; unsigned int queue_type;
unsigned int is_pci_out;
/* leave this member at the end. won't be cleared in qdio_fill_qs */ /* leave this member at the end. won't be cleared in qdio_fill_qs */
struct slib *slib; /* a page is allocated under this pointer, struct slib *slib; /* a page is allocated under this pointer,
......
...@@ -2816,6 +2816,7 @@ qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int, ...@@ -2816,6 +2816,7 @@ qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int,
struct qeth_qdio_out_buffer *buf; struct qeth_qdio_out_buffer *buf;
int rc; int rc;
int i; int i;
unsigned int qdio_flags;
QETH_DBF_TEXT(trace, 6, "flushbuf"); QETH_DBF_TEXT(trace, 6, "flushbuf");
...@@ -2859,12 +2860,12 @@ qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int, ...@@ -2859,12 +2860,12 @@ qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int,
queue->card->perf_stats.outbound_do_qdio_start_time = queue->card->perf_stats.outbound_do_qdio_start_time =
qeth_get_micros(); qeth_get_micros();
} }
qdio_flags = QDIO_FLAG_SYNC_OUTPUT;
if (under_int) if (under_int)
rc = do_QDIO(CARD_DDEV(queue->card), qdio_flags |= QDIO_FLAG_UNDER_INTERRUPT;
QDIO_FLAG_SYNC_OUTPUT | QDIO_FLAG_UNDER_INTERRUPT, if (atomic_read(&queue->set_pci_flags_count))
queue->queue_no, index, count, NULL); qdio_flags |= QDIO_FLAG_PCI_OUT;
else rc = do_QDIO(CARD_DDEV(queue->card), qdio_flags,
rc = do_QDIO(CARD_DDEV(queue->card), QDIO_FLAG_SYNC_OUTPUT,
queue->queue_no, index, count, NULL); queue->queue_no, index, count, NULL);
if (queue->card->options.performance_stats) if (queue->card->options.performance_stats)
queue->card->perf_stats.outbound_do_qdio_time += queue->card->perf_stats.outbound_do_qdio_time +=
...@@ -8498,6 +8499,7 @@ __qeth_reboot_event_card(struct device *dev, void *data) ...@@ -8498,6 +8499,7 @@ __qeth_reboot_event_card(struct device *dev, void *data)
card = (struct qeth_card *) dev->driver_data; card = (struct qeth_card *) dev->driver_data;
qeth_clear_ip_list(card, 0, 0); qeth_clear_ip_list(card, 0, 0);
qeth_qdio_clear_card(card, 0); qeth_qdio_clear_card(card, 0);
qeth_clear_qdio_buffers(card);
return 0; return 0;
} }
......
...@@ -120,6 +120,7 @@ extern unsigned long qdio_get_status(int irq); ...@@ -120,6 +120,7 @@ extern unsigned long qdio_get_status(int irq);
#define QDIO_FLAG_NO_INPUT_INTERRUPT_CONTEXT 0x08 /* no effect on #define QDIO_FLAG_NO_INPUT_INTERRUPT_CONTEXT 0x08 /* no effect on
adapter interrupts */ adapter interrupts */
#define QDIO_FLAG_DONT_SIGA 0x10 #define QDIO_FLAG_DONT_SIGA 0x10
#define QDIO_FLAG_PCI_OUT 0x20
extern int do_QDIO(struct ccw_device*, unsigned int flags, extern int do_QDIO(struct ccw_device*, unsigned int flags,
unsigned int queue_number, unsigned int queue_number,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册