diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-23 14:47:02 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-23 14:47:02 -0400 |
commit | 5f05647dd81c11a6a165ccc8f0c1370b16f3bcb0 (patch) | |
tree | 7851ef1c93aa1aba7ef327ca4b75fd35e6d10f29 /drivers/s390 | |
parent | 02f36038c568111ad4fc433f6fa760ff5e38fab4 (diff) | |
parent | ec37a48d1d16c30b655ac5280209edf52a6775d4 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6: (1699 commits)
bnx2/bnx2x: Unsupported Ethtool operations should return -EINVAL.
vlan: Calling vlan_hwaccel_do_receive() is always valid.
tproxy: use the interface primary IP address as a default value for --on-ip
tproxy: added IPv6 support to the socket match
cxgb3: function namespace cleanup
tproxy: added IPv6 support to the TPROXY target
tproxy: added IPv6 socket lookup function to nf_tproxy_core
be2net: Changes to use only priority codes allowed by f/w
tproxy: allow non-local binds of IPv6 sockets if IP_TRANSPARENT is enabled
tproxy: added tproxy sockopt interface in the IPV6 layer
tproxy: added udp6_lib_lookup function
tproxy: added const specifiers to udp lookup functions
tproxy: split off ipv6 defragmentation to a separate module
l2tp: small cleanup
nf_nat: restrict ICMP translation for embedded header
can: mcp251x: fix generation of error frames
can: mcp251x: fix endless loop in interrupt handler if CANINTF_MERRF is set
can-raw: add msg_flags to distinguish local traffic
9p: client code cleanup
rds: make local functions/variables static
...
Fix up conflicts in net/core/dev.c, drivers/net/pcmcia/smc91c92_cs.c and
drivers/net/wireless/ath/ath9k/debug.c as per David
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/cio/qdio.h | 29 | ||||
-rw-r--r-- | drivers/s390/cio/qdio_debug.c | 33 | ||||
-rw-r--r-- | drivers/s390/cio/qdio_main.c | 138 | ||||
-rw-r--r-- | drivers/s390/cio/qdio_setup.c | 1 | ||||
-rw-r--r-- | drivers/s390/cio/qdio_thinint.c | 66 | ||||
-rw-r--r-- | drivers/s390/net/Kconfig | 2 | ||||
-rw-r--r-- | drivers/s390/net/ctcm_mpc.c | 2 | ||||
-rw-r--r-- | drivers/s390/net/qeth_core.h | 17 | ||||
-rw-r--r-- | drivers/s390/net/qeth_core_main.c | 26 | ||||
-rw-r--r-- | drivers/s390/net/qeth_l2_main.c | 175 | ||||
-rw-r--r-- | drivers/s390/net/qeth_l3_main.c | 218 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_qdio.c | 6 |
12 files changed, 496 insertions, 217 deletions
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h index f0037eefd44e..0f4ef8769a3d 100644 --- a/drivers/s390/cio/qdio.h +++ b/drivers/s390/cio/qdio.h | |||
@@ -208,6 +208,7 @@ struct qdio_dev_perf_stat { | |||
208 | unsigned int eqbs_partial; | 208 | unsigned int eqbs_partial; |
209 | unsigned int sqbs; | 209 | unsigned int sqbs; |
210 | unsigned int sqbs_partial; | 210 | unsigned int sqbs_partial; |
211 | unsigned int int_discarded; | ||
211 | } ____cacheline_aligned; | 212 | } ____cacheline_aligned; |
212 | 213 | ||
213 | struct qdio_queue_perf_stat { | 214 | struct qdio_queue_perf_stat { |
@@ -222,6 +223,10 @@ struct qdio_queue_perf_stat { | |||
222 | unsigned int nr_sbal_total; | 223 | unsigned int nr_sbal_total; |
223 | }; | 224 | }; |
224 | 225 | ||
226 | enum qdio_queue_irq_states { | ||
227 | QDIO_QUEUE_IRQS_DISABLED, | ||
228 | }; | ||
229 | |||
225 | struct qdio_input_q { | 230 | struct qdio_input_q { |
226 | /* input buffer acknowledgement flag */ | 231 | /* input buffer acknowledgement flag */ |
227 | int polling; | 232 | int polling; |
@@ -231,6 +236,10 @@ struct qdio_input_q { | |||
231 | int ack_count; | 236 | int ack_count; |
232 | /* last time of noticing incoming data */ | 237 | /* last time of noticing incoming data */ |
233 | u64 timestamp; | 238 | u64 timestamp; |
239 | /* upper-layer polling flag */ | ||
240 | unsigned long queue_irq_state; | ||
241 | /* callback to start upper-layer polling */ | ||
242 | void (*queue_start_poll) (struct ccw_device *, int, unsigned long); | ||
234 | }; | 243 | }; |
235 | 244 | ||
236 | struct qdio_output_q { | 245 | struct qdio_output_q { |
@@ -399,6 +408,26 @@ static inline int multicast_outbound(struct qdio_q *q) | |||
399 | #define sub_buf(bufnr, dec) \ | 408 | #define sub_buf(bufnr, dec) \ |
400 | ((bufnr - dec) & QDIO_MAX_BUFFERS_MASK) | 409 | ((bufnr - dec) & QDIO_MAX_BUFFERS_MASK) |
401 | 410 | ||
411 | #define queue_irqs_enabled(q) \ | ||
412 | (test_bit(QDIO_QUEUE_IRQS_DISABLED, &q->u.in.queue_irq_state) == 0) | ||
413 | #define queue_irqs_disabled(q) \ | ||
414 | (test_bit(QDIO_QUEUE_IRQS_DISABLED, &q->u.in.queue_irq_state) != 0) | ||
415 | |||
416 | #define TIQDIO_SHARED_IND 63 | ||
417 | |||
418 | /* device state change indicators */ | ||
419 | struct indicator_t { | ||
420 | u32 ind; /* u32 because of compare-and-swap performance */ | ||
421 | atomic_t count; /* use count, 0 or 1 for non-shared indicators */ | ||
422 | }; | ||
423 | |||
424 | extern struct indicator_t *q_indicators; | ||
425 | |||
426 | static inline int shared_ind(struct qdio_irq *irq_ptr) | ||
427 | { | ||
428 | return irq_ptr->dsci == &q_indicators[TIQDIO_SHARED_IND].ind; | ||
429 | } | ||
430 | |||
402 | /* prototypes for thin interrupt */ | 431 | /* prototypes for thin interrupt */ |
403 | void qdio_setup_thinint(struct qdio_irq *irq_ptr); | 432 | void qdio_setup_thinint(struct qdio_irq *irq_ptr); |
404 | int qdio_establish_thinint(struct qdio_irq *irq_ptr); | 433 | int qdio_establish_thinint(struct qdio_irq *irq_ptr); |
diff --git a/drivers/s390/cio/qdio_debug.c b/drivers/s390/cio/qdio_debug.c index 6ce83f56d537..28868e7471a5 100644 --- a/drivers/s390/cio/qdio_debug.c +++ b/drivers/s390/cio/qdio_debug.c | |||
@@ -56,9 +56,16 @@ static int qstat_show(struct seq_file *m, void *v) | |||
56 | 56 | ||
57 | seq_printf(m, "DSCI: %d nr_used: %d\n", | 57 | seq_printf(m, "DSCI: %d nr_used: %d\n", |
58 | *(u32 *)q->irq_ptr->dsci, atomic_read(&q->nr_buf_used)); | 58 | *(u32 *)q->irq_ptr->dsci, atomic_read(&q->nr_buf_used)); |
59 | seq_printf(m, "ftc: %d last_move: %d\n", q->first_to_check, q->last_move); | 59 | seq_printf(m, "ftc: %d last_move: %d\n", |
60 | seq_printf(m, "polling: %d ack start: %d ack count: %d\n", | 60 | q->first_to_check, q->last_move); |
61 | q->u.in.polling, q->u.in.ack_start, q->u.in.ack_count); | 61 | if (q->is_input_q) { |
62 | seq_printf(m, "polling: %d ack start: %d ack count: %d\n", | ||
63 | q->u.in.polling, q->u.in.ack_start, | ||
64 | q->u.in.ack_count); | ||
65 | seq_printf(m, "IRQs disabled: %u\n", | ||
66 | test_bit(QDIO_QUEUE_IRQS_DISABLED, | ||
67 | &q->u.in.queue_irq_state)); | ||
68 | } | ||
62 | seq_printf(m, "SBAL states:\n"); | 69 | seq_printf(m, "SBAL states:\n"); |
63 | seq_printf(m, "|0 |8 |16 |24 |32 |40 |48 |56 63|\n"); | 70 | seq_printf(m, "|0 |8 |16 |24 |32 |40 |48 |56 63|\n"); |
64 | 71 | ||
@@ -113,22 +120,6 @@ static int qstat_show(struct seq_file *m, void *v) | |||
113 | return 0; | 120 | return 0; |
114 | } | 121 | } |
115 | 122 | ||
116 | static ssize_t qstat_seq_write(struct file *file, const char __user *buf, | ||
117 | size_t count, loff_t *off) | ||
118 | { | ||
119 | struct seq_file *seq = file->private_data; | ||
120 | struct qdio_q *q = seq->private; | ||
121 | |||
122 | if (!q) | ||
123 | return 0; | ||
124 | if (q->is_input_q) | ||
125 | xchg(q->irq_ptr->dsci, 1); | ||
126 | local_bh_disable(); | ||
127 | tasklet_schedule(&q->tasklet); | ||
128 | local_bh_enable(); | ||
129 | return count; | ||
130 | } | ||
131 | |||
132 | static int qstat_seq_open(struct inode *inode, struct file *filp) | 123 | static int qstat_seq_open(struct inode *inode, struct file *filp) |
133 | { | 124 | { |
134 | return single_open(filp, qstat_show, | 125 | return single_open(filp, qstat_show, |
@@ -139,7 +130,6 @@ static const struct file_operations debugfs_fops = { | |||
139 | .owner = THIS_MODULE, | 130 | .owner = THIS_MODULE, |
140 | .open = qstat_seq_open, | 131 | .open = qstat_seq_open, |
141 | .read = seq_read, | 132 | .read = seq_read, |
142 | .write = qstat_seq_write, | ||
143 | .llseek = seq_lseek, | 133 | .llseek = seq_lseek, |
144 | .release = single_release, | 134 | .release = single_release, |
145 | }; | 135 | }; |
@@ -166,7 +156,8 @@ static char *qperf_names[] = { | |||
166 | "QEBSM eqbs", | 156 | "QEBSM eqbs", |
167 | "QEBSM eqbs partial", | 157 | "QEBSM eqbs partial", |
168 | "QEBSM sqbs", | 158 | "QEBSM sqbs", |
169 | "QEBSM sqbs partial" | 159 | "QEBSM sqbs partial", |
160 | "Discarded interrupts" | ||
170 | }; | 161 | }; |
171 | 162 | ||
172 | static int qperf_show(struct seq_file *m, void *v) | 163 | static int qperf_show(struct seq_file *m, void *v) |
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 00520f9a7a8e..5fcfa7f9e9ef 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c | |||
@@ -884,8 +884,19 @@ static void qdio_int_handler_pci(struct qdio_irq *irq_ptr) | |||
884 | if (unlikely(irq_ptr->state == QDIO_IRQ_STATE_STOPPED)) | 884 | if (unlikely(irq_ptr->state == QDIO_IRQ_STATE_STOPPED)) |
885 | return; | 885 | return; |
886 | 886 | ||
887 | for_each_input_queue(irq_ptr, q, i) | 887 | for_each_input_queue(irq_ptr, q, i) { |
888 | tasklet_schedule(&q->tasklet); | 888 | if (q->u.in.queue_start_poll) { |
889 | /* skip if polling is enabled or already in work */ | ||
890 | if (test_and_set_bit(QDIO_QUEUE_IRQS_DISABLED, | ||
891 | &q->u.in.queue_irq_state)) { | ||
892 | qperf_inc(q, int_discarded); | ||
893 | continue; | ||
894 | } | ||
895 | q->u.in.queue_start_poll(q->irq_ptr->cdev, q->nr, | ||
896 | q->irq_ptr->int_parm); | ||
897 | } else | ||
898 | tasklet_schedule(&q->tasklet); | ||
899 | } | ||
889 | 900 | ||
890 | if (!(irq_ptr->qib.ac & QIB_AC_OUTBOUND_PCI_SUPPORTED)) | 901 | if (!(irq_ptr->qib.ac & QIB_AC_OUTBOUND_PCI_SUPPORTED)) |
891 | return; | 902 | return; |
@@ -1519,6 +1530,129 @@ int do_QDIO(struct ccw_device *cdev, unsigned int callflags, | |||
1519 | } | 1530 | } |
1520 | EXPORT_SYMBOL_GPL(do_QDIO); | 1531 | EXPORT_SYMBOL_GPL(do_QDIO); |
1521 | 1532 | ||
1533 | /** | ||
1534 | * qdio_start_irq - process input buffers | ||
1535 | * @cdev: associated ccw_device for the qdio subchannel | ||
1536 | * @nr: input queue number | ||
1537 | * | ||
1538 | * Return codes | ||
1539 | * 0 - success | ||
1540 | * 1 - irqs not started since new data is available | ||
1541 | */ | ||
1542 | int qdio_start_irq(struct ccw_device *cdev, int nr) | ||
1543 | { | ||
1544 | struct qdio_q *q; | ||
1545 | struct qdio_irq *irq_ptr = cdev->private->qdio_data; | ||
1546 | |||
1547 | if (!irq_ptr) | ||
1548 | return -ENODEV; | ||
1549 | q = irq_ptr->input_qs[nr]; | ||
1550 | |||
1551 | WARN_ON(queue_irqs_enabled(q)); | ||
1552 | |||
1553 | if (!shared_ind(q->irq_ptr)) | ||
1554 | xchg(q->irq_ptr->dsci, 0); | ||
1555 | |||
1556 | qdio_stop_polling(q); | ||
1557 | clear_bit(QDIO_QUEUE_IRQS_DISABLED, &q->u.in.queue_irq_state); | ||
1558 | |||
1559 | /* | ||
1560 | * We need to check again to not lose initiative after | ||
1561 | * resetting the ACK state. | ||
1562 | */ | ||
1563 | if (!shared_ind(q->irq_ptr) && *q->irq_ptr->dsci) | ||
1564 | goto rescan; | ||
1565 | if (!qdio_inbound_q_done(q)) | ||
1566 | goto rescan; | ||
1567 | return 0; | ||
1568 | |||
1569 | rescan: | ||
1570 | if (test_and_set_bit(QDIO_QUEUE_IRQS_DISABLED, | ||
1571 | &q->u.in.queue_irq_state)) | ||
1572 | return 0; | ||
1573 | else | ||
1574 | return 1; | ||
1575 | |||
1576 | } | ||
1577 | EXPORT_SYMBOL(qdio_start_irq); | ||
1578 | |||
1579 | /** | ||
1580 | * qdio_get_next_buffers - process input buffers | ||
1581 | * @cdev: associated ccw_device for the qdio subchannel | ||
1582 | * @nr: input queue number | ||
1583 | * @bufnr: first filled buffer number | ||
1584 | * @error: buffers are in error state | ||
1585 | * | ||
1586 | * Return codes | ||
1587 | * < 0 - error | ||
1588 | * = 0 - no new buffers found | ||
1589 | * > 0 - number of processed buffers | ||
1590 | */ | ||
1591 | int qdio_get_next_buffers(struct ccw_device *cdev, int nr, int *bufnr, | ||
1592 | int *error) | ||
1593 | { | ||
1594 | struct qdio_q *q; | ||
1595 | int start, end; | ||
1596 | struct qdio_irq *irq_ptr = cdev->private->qdio_data; | ||
1597 | |||
1598 | if (!irq_ptr) | ||
1599 | return -ENODEV; | ||
1600 | q = irq_ptr->input_qs[nr]; | ||
1601 | WARN_ON(queue_irqs_enabled(q)); | ||
1602 | |||
1603 | qdio_sync_after_thinint(q); | ||
1604 | |||
1605 | /* | ||
1606 | * The interrupt could be caused by a PCI request. Check the | ||
1607 | * PCI capable outbound queues. | ||
1608 | */ | ||
1609 | qdio_check_outbound_after_thinint(q); | ||
1610 | |||
1611 | if (!qdio_inbound_q_moved(q)) | ||
1612 | return 0; | ||
1613 | |||
1614 | /* Note: upper-layer MUST stop processing immediately here ... */ | ||
1615 | if (unlikely(q->irq_ptr->state != QDIO_IRQ_STATE_ACTIVE)) | ||
1616 | return -EIO; | ||
1617 | |||
1618 | start = q->first_to_kick; | ||
1619 | end = q->first_to_check; | ||
1620 | *bufnr = start; | ||
1621 | *error = q->qdio_error; | ||
1622 | |||
1623 | /* for the next time */ | ||
1624 | q->first_to_kick = end; | ||
1625 | q->qdio_error = 0; | ||
1626 | return sub_buf(end, start); | ||
1627 | } | ||
1628 | EXPORT_SYMBOL(qdio_get_next_buffers); | ||
1629 | |||
1630 | /** | ||
1631 | * qdio_stop_irq - disable interrupt processing for the device | ||
1632 | * @cdev: associated ccw_device for the qdio subchannel | ||
1633 | * @nr: input queue number | ||
1634 | * | ||
1635 | * Return codes | ||
1636 | * 0 - interrupts were already disabled | ||
1637 | * 1 - interrupts successfully disabled | ||
1638 | */ | ||
1639 | int qdio_stop_irq(struct ccw_device *cdev, int nr) | ||
1640 | { | ||
1641 | struct qdio_q *q; | ||
1642 | struct qdio_irq *irq_ptr = cdev->private->qdio_data; | ||
1643 | |||
1644 | if (!irq_ptr) | ||
1645 | return -ENODEV; | ||
1646 | q = irq_ptr->input_qs[nr]; | ||
1647 | |||
1648 | if (test_and_set_bit(QDIO_QUEUE_IRQS_DISABLED, | ||
1649 | &q->u.in.queue_irq_state)) | ||
1650 | return 0; | ||
1651 | else | ||
1652 | return 1; | ||
1653 | } | ||
1654 | EXPORT_SYMBOL(qdio_stop_irq); | ||
1655 | |||
1522 | static int __init init_QDIO(void) | 1656 | static int __init init_QDIO(void) |
1523 | { | 1657 | { |
1524 | int rc; | 1658 | int rc; |
diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c index 34c7e4046df4..a13cf7ec64b2 100644 --- a/drivers/s390/cio/qdio_setup.c +++ b/drivers/s390/cio/qdio_setup.c | |||
@@ -161,6 +161,7 @@ static void setup_queues(struct qdio_irq *irq_ptr, | |||
161 | setup_queues_misc(q, irq_ptr, qdio_init->input_handler, i); | 161 | setup_queues_misc(q, irq_ptr, qdio_init->input_handler, i); |
162 | 162 | ||
163 | q->is_input_q = 1; | 163 | q->is_input_q = 1; |
164 | q->u.in.queue_start_poll = qdio_init->queue_start_poll; | ||
164 | setup_storage_lists(q, irq_ptr, input_sbal_array, i); | 165 | setup_storage_lists(q, irq_ptr, input_sbal_array, i); |
165 | input_sbal_array += QDIO_MAX_BUFFERS_PER_Q; | 166 | input_sbal_array += QDIO_MAX_BUFFERS_PER_Q; |
166 | 167 | ||
diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c index 8daf1b99f153..752dbee06af5 100644 --- a/drivers/s390/cio/qdio_thinint.c +++ b/drivers/s390/cio/qdio_thinint.c | |||
@@ -25,24 +25,20 @@ | |||
25 | */ | 25 | */ |
26 | #define TIQDIO_NR_NONSHARED_IND 63 | 26 | #define TIQDIO_NR_NONSHARED_IND 63 |
27 | #define TIQDIO_NR_INDICATORS (TIQDIO_NR_NONSHARED_IND + 1) | 27 | #define TIQDIO_NR_INDICATORS (TIQDIO_NR_NONSHARED_IND + 1) |
28 | #define TIQDIO_SHARED_IND 63 | ||
29 | 28 | ||
30 | /* list of thin interrupt input queues */ | 29 | /* list of thin interrupt input queues */ |
31 | static LIST_HEAD(tiq_list); | 30 | static LIST_HEAD(tiq_list); |
32 | DEFINE_MUTEX(tiq_list_lock); | 31 | DEFINE_MUTEX(tiq_list_lock); |
33 | 32 | ||
34 | /* adapter local summary indicator */ | 33 | /* adapter local summary indicator */ |
35 | static unsigned char *tiqdio_alsi; | 34 | static u8 *tiqdio_alsi; |
36 | 35 | ||
37 | /* device state change indicators */ | 36 | struct indicator_t *q_indicators; |
38 | struct indicator_t { | ||
39 | u32 ind; /* u32 because of compare-and-swap performance */ | ||
40 | atomic_t count; /* use count, 0 or 1 for non-shared indicators */ | ||
41 | }; | ||
42 | static struct indicator_t *q_indicators; | ||
43 | 37 | ||
44 | static int css_qdio_omit_svs; | 38 | static int css_qdio_omit_svs; |
45 | 39 | ||
40 | static u64 last_ai_time; | ||
41 | |||
46 | static inline unsigned long do_clear_global_summary(void) | 42 | static inline unsigned long do_clear_global_summary(void) |
47 | { | 43 | { |
48 | register unsigned long __fn asm("1") = 3; | 44 | register unsigned long __fn asm("1") = 3; |
@@ -116,59 +112,73 @@ void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr) | |||
116 | } | 112 | } |
117 | } | 113 | } |
118 | 114 | ||
119 | static inline int shared_ind(struct qdio_irq *irq_ptr) | 115 | static inline int shared_ind_used(void) |
120 | { | 116 | { |
121 | return irq_ptr->dsci == &q_indicators[TIQDIO_SHARED_IND].ind; | 117 | return atomic_read(&q_indicators[TIQDIO_SHARED_IND].count); |
122 | } | 118 | } |
123 | 119 | ||
124 | /** | 120 | /** |
125 | * tiqdio_thinint_handler - thin interrupt handler for qdio | 121 | * tiqdio_thinint_handler - thin interrupt handler for qdio |
126 | * @ind: pointer to adapter local summary indicator | 122 | * @alsi: pointer to adapter local summary indicator |
127 | * @drv_data: NULL | 123 | * @data: NULL |
128 | */ | 124 | */ |
129 | static void tiqdio_thinint_handler(void *ind, void *drv_data) | 125 | static void tiqdio_thinint_handler(void *alsi, void *data) |
130 | { | 126 | { |
131 | struct qdio_q *q; | 127 | struct qdio_q *q; |
132 | 128 | ||
129 | last_ai_time = S390_lowcore.int_clock; | ||
130 | |||
133 | /* | 131 | /* |
134 | * SVS only when needed: issue SVS to benefit from iqdio interrupt | 132 | * SVS only when needed: issue SVS to benefit from iqdio interrupt |
135 | * avoidance (SVS clears adapter interrupt suppression overwrite) | 133 | * avoidance (SVS clears adapter interrupt suppression overwrite). |
136 | */ | 134 | */ |
137 | if (!css_qdio_omit_svs) | 135 | if (!css_qdio_omit_svs) |
138 | do_clear_global_summary(); | 136 | do_clear_global_summary(); |
139 | 137 | ||
140 | /* | 138 | /* reset local summary indicator */ |
141 | * reset local summary indicator (tiqdio_alsi) to stop adapter | 139 | if (shared_ind_used()) |
142 | * interrupts for now | 140 | xchg(tiqdio_alsi, 0); |
143 | */ | ||
144 | xchg((u8 *)ind, 0); | ||
145 | 141 | ||
146 | /* protect tiq_list entries, only changed in activate or shutdown */ | 142 | /* protect tiq_list entries, only changed in activate or shutdown */ |
147 | rcu_read_lock(); | 143 | rcu_read_lock(); |
148 | 144 | ||
149 | /* check for work on all inbound thinint queues */ | 145 | /* check for work on all inbound thinint queues */ |
150 | list_for_each_entry_rcu(q, &tiq_list, entry) | 146 | list_for_each_entry_rcu(q, &tiq_list, entry) { |
147 | |||
151 | /* only process queues from changed sets */ | 148 | /* only process queues from changed sets */ |
152 | if (*q->irq_ptr->dsci) { | 149 | if (!*q->irq_ptr->dsci) |
153 | qperf_inc(q, adapter_int); | 150 | continue; |
154 | 151 | ||
152 | if (q->u.in.queue_start_poll) { | ||
153 | /* skip if polling is enabled or already in work */ | ||
154 | if (test_and_set_bit(QDIO_QUEUE_IRQS_DISABLED, | ||
155 | &q->u.in.queue_irq_state)) { | ||
156 | qperf_inc(q, int_discarded); | ||
157 | continue; | ||
158 | } | ||
159 | |||
160 | /* avoid dsci clear here, done after processing */ | ||
161 | q->u.in.queue_start_poll(q->irq_ptr->cdev, q->nr, | ||
162 | q->irq_ptr->int_parm); | ||
163 | } else { | ||
155 | /* only clear it if the indicator is non-shared */ | 164 | /* only clear it if the indicator is non-shared */ |
156 | if (!shared_ind(q->irq_ptr)) | 165 | if (!shared_ind(q->irq_ptr)) |
157 | xchg(q->irq_ptr->dsci, 0); | 166 | xchg(q->irq_ptr->dsci, 0); |
158 | /* | 167 | /* |
159 | * don't call inbound processing directly since | 168 | * Call inbound processing but not directly |
160 | * that could starve other thinint queues | 169 | * since that could starve other thinint queues. |
161 | */ | 170 | */ |
162 | tasklet_schedule(&q->tasklet); | 171 | tasklet_schedule(&q->tasklet); |
163 | } | 172 | } |
164 | 173 | qperf_inc(q, adapter_int); | |
174 | } | ||
165 | rcu_read_unlock(); | 175 | rcu_read_unlock(); |
166 | 176 | ||
167 | /* | 177 | /* |
168 | * if we used the shared indicator clear it now after all queues | 178 | * If the shared indicator was used clear it now after all queues |
169 | * were processed | 179 | * were processed. |
170 | */ | 180 | */ |
171 | if (atomic_read(&q_indicators[TIQDIO_SHARED_IND].count)) { | 181 | if (shared_ind_used()) { |
172 | xchg(&q_indicators[TIQDIO_SHARED_IND].ind, 0); | 182 | xchg(&q_indicators[TIQDIO_SHARED_IND].ind, 0); |
173 | 183 | ||
174 | /* prevent racing */ | 184 | /* prevent racing */ |
diff --git a/drivers/s390/net/Kconfig b/drivers/s390/net/Kconfig index 977bb4d4ed15..456b18743397 100644 --- a/drivers/s390/net/Kconfig +++ b/drivers/s390/net/Kconfig | |||
@@ -100,6 +100,6 @@ config QETH_IPV6 | |||
100 | 100 | ||
101 | config CCWGROUP | 101 | config CCWGROUP |
102 | tristate | 102 | tristate |
103 | default (LCS || CTCM || QETH) | 103 | default (LCS || CTCM || QETH || CLAW) |
104 | 104 | ||
105 | endmenu | 105 | endmenu |
diff --git a/drivers/s390/net/ctcm_mpc.c b/drivers/s390/net/ctcm_mpc.c index 2861e78773cb..b64881f33f23 100644 --- a/drivers/s390/net/ctcm_mpc.c +++ b/drivers/s390/net/ctcm_mpc.c | |||
@@ -540,7 +540,7 @@ void ctc_mpc_dealloc_ch(int port_num) | |||
540 | 540 | ||
541 | CTCM_DBF_TEXT_(MPC_SETUP, CTC_DBF_DEBUG, | 541 | CTCM_DBF_TEXT_(MPC_SETUP, CTC_DBF_DEBUG, |
542 | "%s: %s: refcount = %d\n", | 542 | "%s: %s: refcount = %d\n", |
543 | CTCM_FUNTAIL, dev->name, atomic_read(&dev->refcnt)); | 543 | CTCM_FUNTAIL, dev->name, netdev_refcnt_read(dev)); |
544 | 544 | ||
545 | fsm_deltimer(&priv->restart_timer); | 545 | fsm_deltimer(&priv->restart_timer); |
546 | grp->channels_terminating = 0; | 546 | grp->channels_terminating = 0; |
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index d1257768be90..6be43eb126b4 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h | |||
@@ -676,6 +676,7 @@ enum qeth_discipline_id { | |||
676 | }; | 676 | }; |
677 | 677 | ||
678 | struct qeth_discipline { | 678 | struct qeth_discipline { |
679 | void (*start_poll)(struct ccw_device *, int, unsigned long); | ||
679 | qdio_handler_t *input_handler; | 680 | qdio_handler_t *input_handler; |
680 | qdio_handler_t *output_handler; | 681 | qdio_handler_t *output_handler; |
681 | int (*recover)(void *ptr); | 682 | int (*recover)(void *ptr); |
@@ -702,6 +703,16 @@ struct qeth_skb_data { | |||
702 | #define QETH_SKB_MAGIC 0x71657468 | 703 | #define QETH_SKB_MAGIC 0x71657468 |
703 | #define QETH_SIGA_CC2_RETRIES 3 | 704 | #define QETH_SIGA_CC2_RETRIES 3 |
704 | 705 | ||
706 | struct qeth_rx { | ||
707 | int b_count; | ||
708 | int b_index; | ||
709 | struct qdio_buffer_element *b_element; | ||
710 | int e_offset; | ||
711 | int qdio_err; | ||
712 | }; | ||
713 | |||
714 | #define QETH_NAPI_WEIGHT 128 | ||
715 | |||
705 | struct qeth_card { | 716 | struct qeth_card { |
706 | struct list_head list; | 717 | struct list_head list; |
707 | enum qeth_card_states state; | 718 | enum qeth_card_states state; |
@@ -749,6 +760,8 @@ struct qeth_card { | |||
749 | debug_info_t *debug; | 760 | debug_info_t *debug; |
750 | struct mutex conf_mutex; | 761 | struct mutex conf_mutex; |
751 | struct mutex discipline_mutex; | 762 | struct mutex discipline_mutex; |
763 | struct napi_struct napi; | ||
764 | struct qeth_rx rx; | ||
752 | }; | 765 | }; |
753 | 766 | ||
754 | struct qeth_card_list_struct { | 767 | struct qeth_card_list_struct { |
@@ -831,6 +844,10 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *, | |||
831 | struct qdio_buffer *, struct qdio_buffer_element **, int *, | 844 | struct qdio_buffer *, struct qdio_buffer_element **, int *, |
832 | struct qeth_hdr **); | 845 | struct qeth_hdr **); |
833 | void qeth_schedule_recovery(struct qeth_card *); | 846 | void qeth_schedule_recovery(struct qeth_card *); |
847 | void qeth_qdio_start_poll(struct ccw_device *, int, unsigned long); | ||
848 | void qeth_qdio_input_handler(struct ccw_device *, | ||
849 | unsigned int, unsigned int, int, | ||
850 | int, unsigned long); | ||
834 | void qeth_qdio_output_handler(struct ccw_device *, unsigned int, | 851 | void qeth_qdio_output_handler(struct ccw_device *, unsigned int, |
835 | int, int, int, unsigned long); | 852 | int, int, int, unsigned long); |
836 | void qeth_clear_ipacmd_list(struct qeth_card *); | 853 | void qeth_clear_ipacmd_list(struct qeth_card *); |
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 3a5a18a0fc28..764267062601 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c | |||
@@ -2911,6 +2911,27 @@ static void qeth_check_outbound_queue(struct qeth_qdio_out_q *queue) | |||
2911 | } | 2911 | } |
2912 | } | 2912 | } |
2913 | 2913 | ||
2914 | void qeth_qdio_start_poll(struct ccw_device *ccwdev, int queue, | ||
2915 | unsigned long card_ptr) | ||
2916 | { | ||
2917 | struct qeth_card *card = (struct qeth_card *)card_ptr; | ||
2918 | |||
2919 | if (card->dev) | ||
2920 | napi_schedule(&card->napi); | ||
2921 | } | ||
2922 | EXPORT_SYMBOL_GPL(qeth_qdio_start_poll); | ||
2923 | |||
2924 | void qeth_qdio_input_handler(struct ccw_device *ccwdev, unsigned int qdio_err, | ||
2925 | unsigned int queue, int first_element, int count, | ||
2926 | unsigned long card_ptr) | ||
2927 | { | ||
2928 | struct qeth_card *card = (struct qeth_card *)card_ptr; | ||
2929 | |||
2930 | if (qdio_err) | ||
2931 | qeth_schedule_recovery(card); | ||
2932 | } | ||
2933 | EXPORT_SYMBOL_GPL(qeth_qdio_input_handler); | ||
2934 | |||
2914 | void qeth_qdio_output_handler(struct ccw_device *ccwdev, | 2935 | void qeth_qdio_output_handler(struct ccw_device *ccwdev, |
2915 | unsigned int qdio_error, int __queue, int first_element, | 2936 | unsigned int qdio_error, int __queue, int first_element, |
2916 | int count, unsigned long card_ptr) | 2937 | int count, unsigned long card_ptr) |
@@ -3843,6 +3864,7 @@ static int qeth_qdio_establish(struct qeth_card *card) | |||
3843 | init_data.no_output_qs = card->qdio.no_out_queues; | 3864 | init_data.no_output_qs = card->qdio.no_out_queues; |
3844 | init_data.input_handler = card->discipline.input_handler; | 3865 | init_data.input_handler = card->discipline.input_handler; |
3845 | init_data.output_handler = card->discipline.output_handler; | 3866 | init_data.output_handler = card->discipline.output_handler; |
3867 | init_data.queue_start_poll = card->discipline.start_poll; | ||
3846 | init_data.int_parm = (unsigned long) card; | 3868 | init_data.int_parm = (unsigned long) card; |
3847 | init_data.input_sbal_addr_array = (void **) in_sbal_ptrs; | 3869 | init_data.input_sbal_addr_array = (void **) in_sbal_ptrs; |
3848 | init_data.output_sbal_addr_array = (void **) out_sbal_ptrs; | 3870 | init_data.output_sbal_addr_array = (void **) out_sbal_ptrs; |
@@ -4513,8 +4535,8 @@ static struct { | |||
4513 | /* 20 */{"queue 1 buffer usage"}, | 4535 | /* 20 */{"queue 1 buffer usage"}, |
4514 | {"queue 2 buffer usage"}, | 4536 | {"queue 2 buffer usage"}, |
4515 | {"queue 3 buffer usage"}, | 4537 | {"queue 3 buffer usage"}, |
4516 | {"rx handler time"}, | 4538 | {"rx poll time"}, |
4517 | {"rx handler count"}, | 4539 | {"rx poll count"}, |
4518 | {"rx do_QDIO time"}, | 4540 | {"rx do_QDIO time"}, |
4519 | {"rx do_QDIO count"}, | 4541 | {"rx do_QDIO count"}, |
4520 | {"tx handler time"}, | 4542 | {"tx handler time"}, |
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 830d63524d61..847e8797073c 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c | |||
@@ -310,6 +310,8 @@ static void qeth_l2_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) | |||
310 | struct qeth_vlan_vid *id; | 310 | struct qeth_vlan_vid *id; |
311 | 311 | ||
312 | QETH_CARD_TEXT_(card, 4, "aid:%d", vid); | 312 | QETH_CARD_TEXT_(card, 4, "aid:%d", vid); |
313 | if (!vid) | ||
314 | return; | ||
313 | if (card->info.type == QETH_CARD_TYPE_OSM) { | 315 | if (card->info.type == QETH_CARD_TYPE_OSM) { |
314 | QETH_CARD_TEXT(card, 3, "aidOSM"); | 316 | QETH_CARD_TEXT(card, 3, "aidOSM"); |
315 | return; | 317 | return; |
@@ -407,29 +409,25 @@ static int qeth_l2_stop_card(struct qeth_card *card, int recovery_mode) | |||
407 | return rc; | 409 | return rc; |
408 | } | 410 | } |
409 | 411 | ||
410 | static void qeth_l2_process_inbound_buffer(struct qeth_card *card, | 412 | static int qeth_l2_process_inbound_buffer(struct qeth_card *card, |
411 | struct qeth_qdio_buffer *buf, int index) | 413 | int budget, int *done) |
412 | { | 414 | { |
413 | struct qdio_buffer_element *element; | 415 | int work_done = 0; |
414 | struct sk_buff *skb; | 416 | struct sk_buff *skb; |
415 | struct qeth_hdr *hdr; | 417 | struct qeth_hdr *hdr; |
416 | int offset; | ||
417 | unsigned int len; | 418 | unsigned int len; |
418 | 419 | ||
419 | /* get first element of current buffer */ | 420 | *done = 0; |
420 | element = (struct qdio_buffer_element *)&buf->buffer->element[0]; | 421 | BUG_ON(!budget); |
421 | offset = 0; | 422 | while (budget) { |
422 | if (card->options.performance_stats) | 423 | skb = qeth_core_get_next_skb(card, |
423 | card->perf_stats.bufs_rec++; | 424 | card->qdio.in_q->bufs[card->rx.b_index].buffer, |
424 | while ((skb = qeth_core_get_next_skb(card, buf->buffer, &element, | 425 | &card->rx.b_element, &card->rx.e_offset, &hdr); |
425 | &offset, &hdr))) { | 426 | if (!skb) { |
426 | skb->dev = card->dev; | 427 | *done = 1; |
427 | /* is device UP ? */ | 428 | break; |
428 | if (!(card->dev->flags & IFF_UP)) { | ||
429 | dev_kfree_skb_any(skb); | ||
430 | continue; | ||
431 | } | 429 | } |
432 | 430 | skb->dev = card->dev; | |
433 | switch (hdr->hdr.l2.id) { | 431 | switch (hdr->hdr.l2.id) { |
434 | case QETH_HEADER_TYPE_LAYER2: | 432 | case QETH_HEADER_TYPE_LAYER2: |
435 | skb->pkt_type = PACKET_HOST; | 433 | skb->pkt_type = PACKET_HOST; |
@@ -441,7 +439,7 @@ static void qeth_l2_process_inbound_buffer(struct qeth_card *card, | |||
441 | if (skb->protocol == htons(ETH_P_802_2)) | 439 | if (skb->protocol == htons(ETH_P_802_2)) |
442 | *((__u32 *)skb->cb) = ++card->seqno.pkt_seqno; | 440 | *((__u32 *)skb->cb) = ++card->seqno.pkt_seqno; |
443 | len = skb->len; | 441 | len = skb->len; |
444 | netif_rx(skb); | 442 | netif_receive_skb(skb); |
445 | break; | 443 | break; |
446 | case QETH_HEADER_TYPE_OSN: | 444 | case QETH_HEADER_TYPE_OSN: |
447 | if (card->info.type == QETH_CARD_TYPE_OSN) { | 445 | if (card->info.type == QETH_CARD_TYPE_OSN) { |
@@ -459,9 +457,87 @@ static void qeth_l2_process_inbound_buffer(struct qeth_card *card, | |||
459 | QETH_DBF_HEX(CTRL, 3, hdr, QETH_DBF_CTRL_LEN); | 457 | QETH_DBF_HEX(CTRL, 3, hdr, QETH_DBF_CTRL_LEN); |
460 | continue; | 458 | continue; |
461 | } | 459 | } |
460 | work_done++; | ||
461 | budget--; | ||
462 | card->stats.rx_packets++; | 462 | card->stats.rx_packets++; |
463 | card->stats.rx_bytes += len; | 463 | card->stats.rx_bytes += len; |
464 | } | 464 | } |
465 | return work_done; | ||
466 | } | ||
467 | |||
468 | static int qeth_l2_poll(struct napi_struct *napi, int budget) | ||
469 | { | ||
470 | struct qeth_card *card = container_of(napi, struct qeth_card, napi); | ||
471 | int work_done = 0; | ||
472 | struct qeth_qdio_buffer *buffer; | ||
473 | int done; | ||
474 | int new_budget = budget; | ||
475 | |||
476 | if (card->options.performance_stats) { | ||
477 | card->perf_stats.inbound_cnt++; | ||
478 | card->perf_stats.inbound_start_time = qeth_get_micros(); | ||
479 | } | ||
480 | |||
481 | while (1) { | ||
482 | if (!card->rx.b_count) { | ||
483 | card->rx.qdio_err = 0; | ||
484 | card->rx.b_count = qdio_get_next_buffers( | ||
485 | card->data.ccwdev, 0, &card->rx.b_index, | ||
486 | &card->rx.qdio_err); | ||
487 | if (card->rx.b_count <= 0) { | ||
488 | card->rx.b_count = 0; | ||
489 | break; | ||
490 | } | ||
491 | card->rx.b_element = | ||
492 | &card->qdio.in_q->bufs[card->rx.b_index] | ||
493 | .buffer->element[0]; | ||
494 | card->rx.e_offset = 0; | ||
495 | } | ||
496 | |||
497 | while (card->rx.b_count) { | ||
498 | buffer = &card->qdio.in_q->bufs[card->rx.b_index]; | ||
499 | if (!(card->rx.qdio_err && | ||
500 | qeth_check_qdio_errors(card, buffer->buffer, | ||
501 | card->rx.qdio_err, "qinerr"))) | ||
502 | work_done += qeth_l2_process_inbound_buffer( | ||
503 | card, new_budget, &done); | ||
504 | else | ||
505 | done = 1; | ||
506 | |||
507 | if (done) { | ||
508 | if (card->options.performance_stats) | ||
509 | card->perf_stats.bufs_rec++; | ||
510 | qeth_put_buffer_pool_entry(card, | ||
511 | buffer->pool_entry); | ||
512 | qeth_queue_input_buffer(card, card->rx.b_index); | ||
513 | card->rx.b_count--; | ||
514 | if (card->rx.b_count) { | ||
515 | card->rx.b_index = | ||
516 | (card->rx.b_index + 1) % | ||
517 | QDIO_MAX_BUFFERS_PER_Q; | ||
518 | card->rx.b_element = | ||
519 | &card->qdio.in_q | ||
520 | ->bufs[card->rx.b_index] | ||
521 | .buffer->element[0]; | ||
522 | card->rx.e_offset = 0; | ||
523 | } | ||
524 | } | ||
525 | |||
526 | if (work_done >= budget) | ||
527 | goto out; | ||
528 | else | ||
529 | new_budget = budget - work_done; | ||
530 | } | ||
531 | } | ||
532 | |||
533 | napi_complete(napi); | ||
534 | if (qdio_start_irq(card->data.ccwdev, 0)) | ||
535 | napi_schedule(&card->napi); | ||
536 | out: | ||
537 | if (card->options.performance_stats) | ||
538 | card->perf_stats.inbound_time += qeth_get_micros() - | ||
539 | card->perf_stats.inbound_start_time; | ||
540 | return work_done; | ||
465 | } | 541 | } |
466 | 542 | ||
467 | static int qeth_l2_send_setdelmac(struct qeth_card *card, __u8 *mac, | 543 | static int qeth_l2_send_setdelmac(struct qeth_card *card, __u8 *mac, |
@@ -755,49 +831,10 @@ tx_drop: | |||
755 | return NETDEV_TX_OK; | 831 | return NETDEV_TX_OK; |
756 | } | 832 | } |
757 | 833 | ||
758 | static void qeth_l2_qdio_input_handler(struct ccw_device *ccwdev, | ||
759 | unsigned int qdio_err, unsigned int queue, | ||
760 | int first_element, int count, unsigned long card_ptr) | ||
761 | { | ||
762 | struct net_device *net_dev; | ||
763 | struct qeth_card *card; | ||
764 | struct qeth_qdio_buffer *buffer; | ||
765 | int index; | ||
766 | int i; | ||
767 | |||
768 | card = (struct qeth_card *) card_ptr; | ||
769 | net_dev = card->dev; | ||
770 | if (card->options.performance_stats) { | ||
771 | card->perf_stats.inbound_cnt++; | ||
772 | card->perf_stats.inbound_start_time = qeth_get_micros(); | ||
773 | } | ||
774 | if (qdio_err & QDIO_ERROR_ACTIVATE_CHECK_CONDITION) { | ||
775 | QETH_CARD_TEXT(card, 1, "qdinchk"); | ||
776 | QETH_CARD_TEXT_(card, 1, "%04X%04X", first_element, | ||
777 | count); | ||
778 | QETH_CARD_TEXT_(card, 1, "%04X", queue); | ||
779 | qeth_schedule_recovery(card); | ||
780 | return; | ||
781 | } | ||
782 | for (i = first_element; i < (first_element + count); ++i) { | ||
783 | index = i % QDIO_MAX_BUFFERS_PER_Q; | ||
784 | buffer = &card->qdio.in_q->bufs[index]; | ||
785 | if (!(qdio_err && | ||
786 | qeth_check_qdio_errors(card, buffer->buffer, qdio_err, | ||
787 | "qinerr"))) | ||
788 | qeth_l2_process_inbound_buffer(card, buffer, index); | ||
789 | /* clear buffer and give back to hardware */ | ||
790 | qeth_put_buffer_pool_entry(card, buffer->pool_entry); | ||
791 | qeth_queue_input_buffer(card, index); | ||
792 | } | ||
793 | if (card->options.performance_stats) | ||
794 | card->perf_stats.inbound_time += qeth_get_micros() - | ||
795 | card->perf_stats.inbound_start_time; | ||
796 | } | ||
797 | |||
798 | static int qeth_l2_open(struct net_device *dev) | 834 | static int qeth_l2_open(struct net_device *dev) |
799 | { | 835 | { |
800 | struct qeth_card *card = dev->ml_priv; | 836 | struct qeth_card *card = dev->ml_priv; |
837 | int rc = 0; | ||
801 | 838 | ||
802 | QETH_CARD_TEXT(card, 4, "qethopen"); | 839 | QETH_CARD_TEXT(card, 4, "qethopen"); |
803 | if (card->state != CARD_STATE_SOFTSETUP) | 840 | if (card->state != CARD_STATE_SOFTSETUP) |
@@ -814,18 +851,24 @@ static int qeth_l2_open(struct net_device *dev) | |||
814 | 851 | ||
815 | if (!card->lan_online && netif_carrier_ok(dev)) | 852 | if (!card->lan_online && netif_carrier_ok(dev)) |
816 | netif_carrier_off(dev); | 853 | netif_carrier_off(dev); |
817 | return 0; | 854 | if (qdio_stop_irq(card->data.ccwdev, 0) >= 0) { |
855 | napi_enable(&card->napi); | ||
856 | napi_schedule(&card->napi); | ||
857 | } else | ||
858 | rc = -EIO; | ||
859 | return rc; | ||
818 | } | 860 | } |
819 | 861 | ||
820 | |||
821 | static int qeth_l2_stop(struct net_device *dev) | 862 | static int qeth_l2_stop(struct net_device *dev) |
822 | { | 863 | { |
823 | struct qeth_card *card = dev->ml_priv; | 864 | struct qeth_card *card = dev->ml_priv; |
824 | 865 | ||
825 | QETH_CARD_TEXT(card, 4, "qethstop"); | 866 | QETH_CARD_TEXT(card, 4, "qethstop"); |
826 | netif_tx_disable(dev); | 867 | netif_tx_disable(dev); |
827 | if (card->state == CARD_STATE_UP) | 868 | if (card->state == CARD_STATE_UP) { |
828 | card->state = CARD_STATE_SOFTSETUP; | 869 | card->state = CARD_STATE_SOFTSETUP; |
870 | napi_disable(&card->napi); | ||
871 | } | ||
829 | return 0; | 872 | return 0; |
830 | } | 873 | } |
831 | 874 | ||
@@ -836,8 +879,9 @@ static int qeth_l2_probe_device(struct ccwgroup_device *gdev) | |||
836 | INIT_LIST_HEAD(&card->vid_list); | 879 | INIT_LIST_HEAD(&card->vid_list); |
837 | INIT_LIST_HEAD(&card->mc_list); | 880 | INIT_LIST_HEAD(&card->mc_list); |
838 | card->options.layer2 = 1; | 881 | card->options.layer2 = 1; |
882 | card->discipline.start_poll = qeth_qdio_start_poll; | ||
839 | card->discipline.input_handler = (qdio_handler_t *) | 883 | card->discipline.input_handler = (qdio_handler_t *) |
840 | qeth_l2_qdio_input_handler; | 884 | qeth_qdio_input_handler; |
841 | card->discipline.output_handler = (qdio_handler_t *) | 885 | card->discipline.output_handler = (qdio_handler_t *) |
842 | qeth_qdio_output_handler; | 886 | qeth_qdio_output_handler; |
843 | card->discipline.recover = qeth_l2_recover; | 887 | card->discipline.recover = qeth_l2_recover; |
@@ -923,6 +967,7 @@ static int qeth_l2_setup_netdev(struct qeth_card *card) | |||
923 | card->info.broadcast_capable = 1; | 967 | card->info.broadcast_capable = 1; |
924 | qeth_l2_request_initial_mac(card); | 968 | qeth_l2_request_initial_mac(card); |
925 | SET_NETDEV_DEV(card->dev, &card->gdev->dev); | 969 | SET_NETDEV_DEV(card->dev, &card->gdev->dev); |
970 | netif_napi_add(card->dev, &card->napi, qeth_l2_poll, QETH_NAPI_WEIGHT); | ||
926 | return register_netdev(card->dev); | 971 | return register_netdev(card->dev); |
927 | } | 972 | } |
928 | 973 | ||
@@ -955,6 +1000,7 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) | |||
955 | qeth_l2_send_setmac(card, &card->dev->dev_addr[0]); | 1000 | qeth_l2_send_setmac(card, &card->dev->dev_addr[0]); |
956 | 1001 | ||
957 | card->state = CARD_STATE_HARDSETUP; | 1002 | card->state = CARD_STATE_HARDSETUP; |
1003 | memset(&card->rx, 0, sizeof(struct qeth_rx)); | ||
958 | qeth_print_status_message(card); | 1004 | qeth_print_status_message(card); |
959 | 1005 | ||
960 | /* softsetup */ | 1006 | /* softsetup */ |
@@ -1086,9 +1132,6 @@ static int qeth_l2_recover(void *ptr) | |||
1086 | card->use_hard_stop = 1; | 1132 | card->use_hard_stop = 1; |
1087 | __qeth_l2_set_offline(card->gdev, 1); | 1133 | __qeth_l2_set_offline(card->gdev, 1); |
1088 | rc = __qeth_l2_set_online(card->gdev, 1); | 1134 | rc = __qeth_l2_set_online(card->gdev, 1); |
1089 | /* don't run another scheduled recovery */ | ||
1090 | qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD); | ||
1091 | qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD); | ||
1092 | if (!rc) | 1135 | if (!rc) |
1093 | dev_info(&card->gdev->dev, | 1136 | dev_info(&card->gdev->dev, |
1094 | "Device successfully recovered!\n"); | 1137 | "Device successfully recovered!\n"); |
@@ -1099,6 +1142,8 @@ static int qeth_l2_recover(void *ptr) | |||
1099 | dev_warn(&card->gdev->dev, "The qeth device driver " | 1142 | dev_warn(&card->gdev->dev, "The qeth device driver " |
1100 | "failed to recover an error on the device\n"); | 1143 | "failed to recover an error on the device\n"); |
1101 | } | 1144 | } |
1145 | qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD); | ||
1146 | qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD); | ||
1102 | return 0; | 1147 | return 0; |
1103 | } | 1148 | } |
1104 | 1149 | ||
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index e22ae248f613..74d1401a5d5e 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c | |||
@@ -103,12 +103,7 @@ int qeth_l3_string_to_ipaddr4(const char *buf, __u8 *addr) | |||
103 | 103 | ||
104 | void qeth_l3_ipaddr6_to_string(const __u8 *addr, char *buf) | 104 | void qeth_l3_ipaddr6_to_string(const __u8 *addr, char *buf) |
105 | { | 105 | { |
106 | sprintf(buf, "%02x%02x:%02x%02x:%02x%02x:%02x%02x" | 106 | sprintf(buf, "%pI6", addr); |
107 | ":%02x%02x:%02x%02x:%02x%02x:%02x%02x", | ||
108 | addr[0], addr[1], addr[2], addr[3], | ||
109 | addr[4], addr[5], addr[6], addr[7], | ||
110 | addr[8], addr[9], addr[10], addr[11], | ||
111 | addr[12], addr[13], addr[14], addr[15]); | ||
112 | } | 107 | } |
113 | 108 | ||
114 | int qeth_l3_string_to_ipaddr6(const char *buf, __u8 *addr) | 109 | int qeth_l3_string_to_ipaddr6(const char *buf, __u8 *addr) |
@@ -1825,7 +1820,7 @@ static void qeth_l3_add_vlan_mc(struct qeth_card *card) | |||
1825 | return; | 1820 | return; |
1826 | 1821 | ||
1827 | vg = card->vlangrp; | 1822 | vg = card->vlangrp; |
1828 | for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { | 1823 | for (i = 0; i < VLAN_N_VID; i++) { |
1829 | struct net_device *netdev = vlan_group_get_device(vg, i); | 1824 | struct net_device *netdev = vlan_group_get_device(vg, i); |
1830 | if (netdev == NULL || | 1825 | if (netdev == NULL || |
1831 | !(netdev->flags & IFF_UP)) | 1826 | !(netdev->flags & IFF_UP)) |
@@ -1888,7 +1883,7 @@ static void qeth_l3_add_vlan_mc6(struct qeth_card *card) | |||
1888 | return; | 1883 | return; |
1889 | 1884 | ||
1890 | vg = card->vlangrp; | 1885 | vg = card->vlangrp; |
1891 | for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { | 1886 | for (i = 0; i < VLAN_N_VID; i++) { |
1892 | struct net_device *netdev = vlan_group_get_device(vg, i); | 1887 | struct net_device *netdev = vlan_group_get_device(vg, i); |
1893 | if (netdev == NULL || | 1888 | if (netdev == NULL || |
1894 | !(netdev->flags & IFF_UP)) | 1889 | !(netdev->flags & IFF_UP)) |
@@ -2018,13 +2013,14 @@ static void qeth_l3_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) | |||
2018 | qeth_l3_set_multicast_list(card->dev); | 2013 | qeth_l3_set_multicast_list(card->dev); |
2019 | } | 2014 | } |
2020 | 2015 | ||
2021 | static inline __u16 qeth_l3_rebuild_skb(struct qeth_card *card, | 2016 | static inline int qeth_l3_rebuild_skb(struct qeth_card *card, |
2022 | struct sk_buff *skb, struct qeth_hdr *hdr) | 2017 | struct sk_buff *skb, struct qeth_hdr *hdr, |
2018 | unsigned short *vlan_id) | ||
2023 | { | 2019 | { |
2024 | unsigned short vlan_id = 0; | ||
2025 | __be16 prot; | 2020 | __be16 prot; |
2026 | struct iphdr *ip_hdr; | 2021 | struct iphdr *ip_hdr; |
2027 | unsigned char tg_addr[MAX_ADDR_LEN]; | 2022 | unsigned char tg_addr[MAX_ADDR_LEN]; |
2023 | int is_vlan = 0; | ||
2028 | 2024 | ||
2029 | if (!(hdr->hdr.l3.flags & QETH_HDR_PASSTHRU)) { | 2025 | if (!(hdr->hdr.l3.flags & QETH_HDR_PASSTHRU)) { |
2030 | prot = htons((hdr->hdr.l3.flags & QETH_HDR_IPV6)? ETH_P_IPV6 : | 2026 | prot = htons((hdr->hdr.l3.flags & QETH_HDR_IPV6)? ETH_P_IPV6 : |
@@ -2087,8 +2083,9 @@ static inline __u16 qeth_l3_rebuild_skb(struct qeth_card *card, | |||
2087 | 2083 | ||
2088 | if (hdr->hdr.l3.ext_flags & | 2084 | if (hdr->hdr.l3.ext_flags & |
2089 | (QETH_HDR_EXT_VLAN_FRAME | QETH_HDR_EXT_INCLUDE_VLAN_TAG)) { | 2085 | (QETH_HDR_EXT_VLAN_FRAME | QETH_HDR_EXT_INCLUDE_VLAN_TAG)) { |
2090 | vlan_id = (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_VLAN_FRAME)? | 2086 | *vlan_id = (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_VLAN_FRAME) ? |
2091 | hdr->hdr.l3.vlan_id : *((u16 *)&hdr->hdr.l3.dest_addr[12]); | 2087 | hdr->hdr.l3.vlan_id : *((u16 *)&hdr->hdr.l3.dest_addr[12]); |
2088 | is_vlan = 1; | ||
2092 | } | 2089 | } |
2093 | 2090 | ||
2094 | switch (card->options.checksum_type) { | 2091 | switch (card->options.checksum_type) { |
@@ -2109,54 +2106,44 @@ static inline __u16 qeth_l3_rebuild_skb(struct qeth_card *card, | |||
2109 | skb->ip_summed = CHECKSUM_NONE; | 2106 | skb->ip_summed = CHECKSUM_NONE; |
2110 | } | 2107 | } |
2111 | 2108 | ||
2112 | return vlan_id; | 2109 | return is_vlan; |
2113 | } | 2110 | } |
2114 | 2111 | ||
2115 | static void qeth_l3_process_inbound_buffer(struct qeth_card *card, | 2112 | static int qeth_l3_process_inbound_buffer(struct qeth_card *card, |
2116 | struct qeth_qdio_buffer *buf, int index) | 2113 | int budget, int *done) |
2117 | { | 2114 | { |
2118 | struct qdio_buffer_element *element; | 2115 | int work_done = 0; |
2119 | struct sk_buff *skb; | 2116 | struct sk_buff *skb; |
2120 | struct qeth_hdr *hdr; | 2117 | struct qeth_hdr *hdr; |
2121 | int offset; | ||
2122 | __u16 vlan_tag = 0; | 2118 | __u16 vlan_tag = 0; |
2119 | int is_vlan; | ||
2123 | unsigned int len; | 2120 | unsigned int len; |
2124 | /* get first element of current buffer */ | ||
2125 | element = (struct qdio_buffer_element *)&buf->buffer->element[0]; | ||
2126 | offset = 0; | ||
2127 | if (card->options.performance_stats) | ||
2128 | card->perf_stats.bufs_rec++; | ||
2129 | while ((skb = qeth_core_get_next_skb(card, buf->buffer, &element, | ||
2130 | &offset, &hdr))) { | ||
2131 | skb->dev = card->dev; | ||
2132 | /* is device UP ? */ | ||
2133 | if (!(card->dev->flags & IFF_UP)) { | ||
2134 | dev_kfree_skb_any(skb); | ||
2135 | continue; | ||
2136 | } | ||
2137 | 2121 | ||
2122 | *done = 0; | ||
2123 | BUG_ON(!budget); | ||
2124 | while (budget) { | ||
2125 | skb = qeth_core_get_next_skb(card, | ||
2126 | card->qdio.in_q->bufs[card->rx.b_index].buffer, | ||
2127 | &card->rx.b_element, &card->rx.e_offset, &hdr); | ||
2128 | if (!skb) { | ||
2129 | *done = 1; | ||
2130 | break; | ||
2131 | } | ||
2132 | skb->dev = card->dev; | ||
2138 | switch (hdr->hdr.l3.id) { | 2133 | switch (hdr->hdr.l3.id) { |
2139 | case QETH_HEADER_TYPE_LAYER3: | 2134 | case QETH_HEADER_TYPE_LAYER3: |
2140 | vlan_tag = qeth_l3_rebuild_skb(card, skb, hdr); | 2135 | is_vlan = qeth_l3_rebuild_skb(card, skb, hdr, |
2136 | &vlan_tag); | ||
2141 | len = skb->len; | 2137 | len = skb->len; |
2142 | if (vlan_tag && !card->options.sniffer) | 2138 | if (is_vlan && !card->options.sniffer) |
2143 | if (card->vlangrp) | 2139 | vlan_gro_receive(&card->napi, card->vlangrp, |
2144 | vlan_hwaccel_rx(skb, card->vlangrp, | 2140 | vlan_tag, skb); |
2145 | vlan_tag); | ||
2146 | else { | ||
2147 | dev_kfree_skb_any(skb); | ||
2148 | continue; | ||
2149 | } | ||
2150 | else | 2141 | else |
2151 | netif_rx(skb); | 2142 | napi_gro_receive(&card->napi, skb); |
2152 | break; | 2143 | break; |
2153 | case QETH_HEADER_TYPE_LAYER2: /* for HiperSockets sniffer */ | 2144 | case QETH_HEADER_TYPE_LAYER2: /* for HiperSockets sniffer */ |
2154 | skb->pkt_type = PACKET_HOST; | 2145 | skb->pkt_type = PACKET_HOST; |
2155 | skb->protocol = eth_type_trans(skb, skb->dev); | 2146 | skb->protocol = eth_type_trans(skb, skb->dev); |
2156 | if (card->options.checksum_type == NO_CHECKSUMMING) | ||
2157 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
2158 | else | ||
2159 | skb->ip_summed = CHECKSUM_NONE; | ||
2160 | len = skb->len; | 2147 | len = skb->len; |
2161 | netif_receive_skb(skb); | 2148 | netif_receive_skb(skb); |
2162 | break; | 2149 | break; |
@@ -2166,10 +2153,87 @@ static void qeth_l3_process_inbound_buffer(struct qeth_card *card, | |||
2166 | QETH_DBF_HEX(CTRL, 3, hdr, QETH_DBF_CTRL_LEN); | 2153 | QETH_DBF_HEX(CTRL, 3, hdr, QETH_DBF_CTRL_LEN); |
2167 | continue; | 2154 | continue; |
2168 | } | 2155 | } |
2169 | 2156 | work_done++; | |
2157 | budget--; | ||
2170 | card->stats.rx_packets++; | 2158 | card->stats.rx_packets++; |
2171 | card->stats.rx_bytes += len; | 2159 | card->stats.rx_bytes += len; |
2172 | } | 2160 | } |
2161 | return work_done; | ||
2162 | } | ||
2163 | |||
2164 | static int qeth_l3_poll(struct napi_struct *napi, int budget) | ||
2165 | { | ||
2166 | struct qeth_card *card = container_of(napi, struct qeth_card, napi); | ||
2167 | int work_done = 0; | ||
2168 | struct qeth_qdio_buffer *buffer; | ||
2169 | int done; | ||
2170 | int new_budget = budget; | ||
2171 | |||
2172 | if (card->options.performance_stats) { | ||
2173 | card->perf_stats.inbound_cnt++; | ||
2174 | card->perf_stats.inbound_start_time = qeth_get_micros(); | ||
2175 | } | ||
2176 | |||
2177 | while (1) { | ||
2178 | if (!card->rx.b_count) { | ||
2179 | card->rx.qdio_err = 0; | ||
2180 | card->rx.b_count = qdio_get_next_buffers( | ||
2181 | card->data.ccwdev, 0, &card->rx.b_index, | ||
2182 | &card->rx.qdio_err); | ||
2183 | if (card->rx.b_count <= 0) { | ||
2184 | card->rx.b_count = 0; | ||
2185 | break; | ||
2186 | } | ||
2187 | card->rx.b_element = | ||
2188 | &card->qdio.in_q->bufs[card->rx.b_index] | ||
2189 | .buffer->element[0]; | ||
2190 | card->rx.e_offset = 0; | ||
2191 | } | ||
2192 | |||
2193 | while (card->rx.b_count) { | ||
2194 | buffer = &card->qdio.in_q->bufs[card->rx.b_index]; | ||
2195 | if (!(card->rx.qdio_err && | ||
2196 | qeth_check_qdio_errors(card, buffer->buffer, | ||
2197 | card->rx.qdio_err, "qinerr"))) | ||
2198 | work_done += qeth_l3_process_inbound_buffer( | ||
2199 | card, new_budget, &done); | ||
2200 | else | ||
2201 | done = 1; | ||
2202 | |||
2203 | if (done) { | ||
2204 | if (card->options.performance_stats) | ||
2205 | card->perf_stats.bufs_rec++; | ||
2206 | qeth_put_buffer_pool_entry(card, | ||
2207 | buffer->pool_entry); | ||
2208 | qeth_queue_input_buffer(card, card->rx.b_index); | ||
2209 | card->rx.b_count--; | ||
2210 | if (card->rx.b_count) { | ||
2211 | card->rx.b_index = | ||
2212 | (card->rx.b_index + 1) % | ||
2213 | QDIO_MAX_BUFFERS_PER_Q; | ||
2214 | card->rx.b_element = | ||
2215 | &card->qdio.in_q | ||
2216 | ->bufs[card->rx.b_index] | ||
2217 | .buffer->element[0]; | ||
2218 | card->rx.e_offset = 0; | ||
2219 | } | ||
2220 | } | ||
2221 | |||
2222 | if (work_done >= budget) | ||
2223 | goto out; | ||
2224 | else | ||
2225 | new_budget = budget - work_done; | ||
2226 | } | ||
2227 | } | ||
2228 | |||
2229 | napi_complete(napi); | ||
2230 | if (qdio_start_irq(card->data.ccwdev, 0)) | ||
2231 | napi_schedule(&card->napi); | ||
2232 | out: | ||
2233 | if (card->options.performance_stats) | ||
2234 | card->perf_stats.inbound_time += qeth_get_micros() - | ||
2235 | card->perf_stats.inbound_start_time; | ||
2236 | return work_done; | ||
2173 | } | 2237 | } |
2174 | 2238 | ||
2175 | static int qeth_l3_verify_vlan_dev(struct net_device *dev, | 2239 | static int qeth_l3_verify_vlan_dev(struct net_device *dev, |
@@ -2183,7 +2247,7 @@ static int qeth_l3_verify_vlan_dev(struct net_device *dev, | |||
2183 | if (!vg) | 2247 | if (!vg) |
2184 | return rc; | 2248 | return rc; |
2185 | 2249 | ||
2186 | for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { | 2250 | for (i = 0; i < VLAN_N_VID; i++) { |
2187 | if (vlan_group_get_device(vg, i) == dev) { | 2251 | if (vlan_group_get_device(vg, i) == dev) { |
2188 | rc = QETH_VLAN_CARD; | 2252 | rc = QETH_VLAN_CARD; |
2189 | break; | 2253 | break; |
@@ -3103,6 +3167,7 @@ tx_drop: | |||
3103 | static int qeth_l3_open(struct net_device *dev) | 3167 | static int qeth_l3_open(struct net_device *dev) |
3104 | { | 3168 | { |
3105 | struct qeth_card *card = dev->ml_priv; | 3169 | struct qeth_card *card = dev->ml_priv; |
3170 | int rc = 0; | ||
3106 | 3171 | ||
3107 | QETH_CARD_TEXT(card, 4, "qethopen"); | 3172 | QETH_CARD_TEXT(card, 4, "qethopen"); |
3108 | if (card->state != CARD_STATE_SOFTSETUP) | 3173 | if (card->state != CARD_STATE_SOFTSETUP) |
@@ -3113,7 +3178,12 @@ static int qeth_l3_open(struct net_device *dev) | |||
3113 | 3178 | ||
3114 | if (!card->lan_online && netif_carrier_ok(dev)) | 3179 | if (!card->lan_online && netif_carrier_ok(dev)) |
3115 | netif_carrier_off(dev); | 3180 | netif_carrier_off(dev); |
3116 | return 0; | 3181 | if (qdio_stop_irq(card->data.ccwdev, 0) >= 0) { |
3182 | napi_enable(&card->napi); | ||
3183 | napi_schedule(&card->napi); | ||
3184 | } else | ||
3185 | rc = -EIO; | ||
3186 | return rc; | ||
3117 | } | 3187 | } |
3118 | 3188 | ||
3119 | static int qeth_l3_stop(struct net_device *dev) | 3189 | static int qeth_l3_stop(struct net_device *dev) |
@@ -3122,8 +3192,10 @@ static int qeth_l3_stop(struct net_device *dev) | |||
3122 | 3192 | ||
3123 | QETH_CARD_TEXT(card, 4, "qethstop"); | 3193 | QETH_CARD_TEXT(card, 4, "qethstop"); |
3124 | netif_tx_disable(dev); | 3194 | netif_tx_disable(dev); |
3125 | if (card->state == CARD_STATE_UP) | 3195 | if (card->state == CARD_STATE_UP) { |
3126 | card->state = CARD_STATE_SOFTSETUP; | 3196 | card->state = CARD_STATE_SOFTSETUP; |
3197 | napi_disable(&card->napi); | ||
3198 | } | ||
3127 | return 0; | 3199 | return 0; |
3128 | } | 3200 | } |
3129 | 3201 | ||
@@ -3293,57 +3365,19 @@ static int qeth_l3_setup_netdev(struct qeth_card *card) | |||
3293 | card->dev->gso_max_size = 15 * PAGE_SIZE; | 3365 | card->dev->gso_max_size = 15 * PAGE_SIZE; |
3294 | 3366 | ||
3295 | SET_NETDEV_DEV(card->dev, &card->gdev->dev); | 3367 | SET_NETDEV_DEV(card->dev, &card->gdev->dev); |
3368 | netif_napi_add(card->dev, &card->napi, qeth_l3_poll, QETH_NAPI_WEIGHT); | ||
3296 | return register_netdev(card->dev); | 3369 | return register_netdev(card->dev); |
3297 | } | 3370 | } |
3298 | 3371 | ||
3299 | static void qeth_l3_qdio_input_handler(struct ccw_device *ccwdev, | ||
3300 | unsigned int qdio_err, unsigned int queue, int first_element, | ||
3301 | int count, unsigned long card_ptr) | ||
3302 | { | ||
3303 | struct net_device *net_dev; | ||
3304 | struct qeth_card *card; | ||
3305 | struct qeth_qdio_buffer *buffer; | ||
3306 | int index; | ||
3307 | int i; | ||
3308 | |||
3309 | card = (struct qeth_card *) card_ptr; | ||
3310 | net_dev = card->dev; | ||
3311 | if (card->options.performance_stats) { | ||
3312 | card->perf_stats.inbound_cnt++; | ||
3313 | card->perf_stats.inbound_start_time = qeth_get_micros(); | ||
3314 | } | ||
3315 | if (qdio_err & QDIO_ERROR_ACTIVATE_CHECK_CONDITION) { | ||
3316 | QETH_CARD_TEXT(card, 1, "qdinchk"); | ||
3317 | QETH_CARD_TEXT_(card, 1, "%04X%04X", | ||
3318 | first_element, count); | ||
3319 | QETH_CARD_TEXT_(card, 1, "%04X", queue); | ||
3320 | qeth_schedule_recovery(card); | ||
3321 | return; | ||
3322 | } | ||
3323 | for (i = first_element; i < (first_element + count); ++i) { | ||
3324 | index = i % QDIO_MAX_BUFFERS_PER_Q; | ||
3325 | buffer = &card->qdio.in_q->bufs[index]; | ||
3326 | if (!(qdio_err && | ||
3327 | qeth_check_qdio_errors(card, buffer->buffer, | ||
3328 | qdio_err, "qinerr"))) | ||
3329 | qeth_l3_process_inbound_buffer(card, buffer, index); | ||
3330 | /* clear buffer and give back to hardware */ | ||
3331 | qeth_put_buffer_pool_entry(card, buffer->pool_entry); | ||
3332 | qeth_queue_input_buffer(card, index); | ||
3333 | } | ||
3334 | if (card->options.performance_stats) | ||
3335 | card->perf_stats.inbound_time += qeth_get_micros() - | ||
3336 | card->perf_stats.inbound_start_time; | ||
3337 | } | ||
3338 | |||
3339 | static int qeth_l3_probe_device(struct ccwgroup_device *gdev) | 3372 | static int qeth_l3_probe_device(struct ccwgroup_device *gdev) |
3340 | { | 3373 | { |
3341 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); | 3374 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); |
3342 | 3375 | ||
3343 | qeth_l3_create_device_attributes(&gdev->dev); | 3376 | qeth_l3_create_device_attributes(&gdev->dev); |
3344 | card->options.layer2 = 0; | 3377 | card->options.layer2 = 0; |
3378 | card->discipline.start_poll = qeth_qdio_start_poll; | ||
3345 | card->discipline.input_handler = (qdio_handler_t *) | 3379 | card->discipline.input_handler = (qdio_handler_t *) |
3346 | qeth_l3_qdio_input_handler; | 3380 | qeth_qdio_input_handler; |
3347 | card->discipline.output_handler = (qdio_handler_t *) | 3381 | card->discipline.output_handler = (qdio_handler_t *) |
3348 | qeth_qdio_output_handler; | 3382 | qeth_qdio_output_handler; |
3349 | card->discipline.recover = qeth_l3_recover; | 3383 | card->discipline.recover = qeth_l3_recover; |
@@ -3402,6 +3436,7 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) | |||
3402 | } | 3436 | } |
3403 | 3437 | ||
3404 | card->state = CARD_STATE_HARDSETUP; | 3438 | card->state = CARD_STATE_HARDSETUP; |
3439 | memset(&card->rx, 0, sizeof(struct qeth_rx)); | ||
3405 | qeth_print_status_message(card); | 3440 | qeth_print_status_message(card); |
3406 | 3441 | ||
3407 | /* softsetup */ | 3442 | /* softsetup */ |
@@ -3538,9 +3573,6 @@ static int qeth_l3_recover(void *ptr) | |||
3538 | card->use_hard_stop = 1; | 3573 | card->use_hard_stop = 1; |
3539 | __qeth_l3_set_offline(card->gdev, 1); | 3574 | __qeth_l3_set_offline(card->gdev, 1); |
3540 | rc = __qeth_l3_set_online(card->gdev, 1); | 3575 | rc = __qeth_l3_set_online(card->gdev, 1); |
3541 | /* don't run another scheduled recovery */ | ||
3542 | qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD); | ||
3543 | qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD); | ||
3544 | if (!rc) | 3576 | if (!rc) |
3545 | dev_info(&card->gdev->dev, | 3577 | dev_info(&card->gdev->dev, |
3546 | "Device successfully recovered!\n"); | 3578 | "Device successfully recovered!\n"); |
@@ -3551,6 +3583,8 @@ static int qeth_l3_recover(void *ptr) | |||
3551 | dev_warn(&card->gdev->dev, "The qeth device driver " | 3583 | dev_warn(&card->gdev->dev, "The qeth device driver " |
3552 | "failed to recover an error on the device\n"); | 3584 | "failed to recover an error on the device\n"); |
3553 | } | 3585 | } |
3586 | qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD); | ||
3587 | qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD); | ||
3554 | return 0; | 3588 | return 0; |
3555 | } | 3589 | } |
3556 | 3590 | ||
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index 60e6e5714eb9..a0554beb4179 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c | |||
@@ -279,16 +279,12 @@ int zfcp_qdio_send(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req) | |||
279 | static void zfcp_qdio_setup_init_data(struct qdio_initialize *id, | 279 | static void zfcp_qdio_setup_init_data(struct qdio_initialize *id, |
280 | struct zfcp_qdio *qdio) | 280 | struct zfcp_qdio *qdio) |
281 | { | 281 | { |
282 | 282 | memset(id, 0, sizeof(*id)); | |
283 | id->cdev = qdio->adapter->ccw_device; | 283 | id->cdev = qdio->adapter->ccw_device; |
284 | id->q_format = QDIO_ZFCP_QFMT; | 284 | id->q_format = QDIO_ZFCP_QFMT; |
285 | memcpy(id->adapter_name, dev_name(&id->cdev->dev), 8); | 285 | memcpy(id->adapter_name, dev_name(&id->cdev->dev), 8); |
286 | ASCEBC(id->adapter_name, 8); | 286 | ASCEBC(id->adapter_name, 8); |
287 | id->qib_rflags = QIB_RFLAGS_ENABLE_DATA_DIV; | 287 | id->qib_rflags = QIB_RFLAGS_ENABLE_DATA_DIV; |
288 | id->qib_param_field_format = 0; | ||
289 | id->qib_param_field = NULL; | ||
290 | id->input_slib_elements = NULL; | ||
291 | id->output_slib_elements = NULL; | ||
292 | id->no_input_qs = 1; | 288 | id->no_input_qs = 1; |
293 | id->no_output_qs = 1; | 289 | id->no_output_qs = 1; |
294 | id->input_handler = zfcp_qdio_int_resp; | 290 | id->input_handler = zfcp_qdio_int_resp; |