diff options
author | Frank Pavlic <fpavlic@de.ibm.com> | 2006-09-15 10:26:34 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-09-17 01:03:07 -0400 |
commit | 09d2d38a152419467f764c0f730821e896766c1f (patch) | |
tree | 56001b9b3573a9a2fc05f74a4e2d0571607d0a19 | |
parent | f7b65d70a3e6f1c97eb614964270816992d0d4b4 (diff) |
[PATCH] s390: qeth driver fixes [4/6]
[PATCH 7/9] s390: qeth driver fixes [4/6]
From: Frank Pavlic <fpavlic@de.ibm.com>
- fix kernel crash due to race,
set card->state to SOFTSETUP after
card and card->dev are initialized properly.
- remove CONFIG_QETH_PERF_STATS, use sysfs attribute instead,
as we want to have the ability to turn on/off the
statistics at runtime.
Signed-off-by: Frank Pavlic <fpavlic@de.ibm.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r-- | drivers/s390/net/Kconfig | 9 | ||||
-rw-r--r-- | drivers/s390/net/qeth.h | 10 | ||||
-rw-r--r-- | drivers/s390/net/qeth_eddp.c | 5 | ||||
-rw-r--r-- | drivers/s390/net/qeth_main.c | 147 | ||||
-rw-r--r-- | drivers/s390/net/qeth_proc.c | 23 | ||||
-rw-r--r-- | drivers/s390/net/qeth_sys.c | 42 |
6 files changed, 128 insertions, 108 deletions
diff --git a/drivers/s390/net/Kconfig b/drivers/s390/net/Kconfig index 548854754921..1a93fa684e9f 100644 --- a/drivers/s390/net/Kconfig +++ b/drivers/s390/net/Kconfig | |||
@@ -92,15 +92,6 @@ config QETH_VLAN | |||
92 | If CONFIG_QETH is switched on, this option will include IEEE | 92 | If CONFIG_QETH is switched on, this option will include IEEE |
93 | 802.1q VLAN support in the qeth device driver. | 93 | 802.1q VLAN support in the qeth device driver. |
94 | 94 | ||
95 | config QETH_PERF_STATS | ||
96 | bool "Performance statistics in /proc" | ||
97 | depends on QETH | ||
98 | help | ||
99 | When switched on, this option will add a file in the proc-fs | ||
100 | (/proc/qeth_perf_stats) containing performance statistics. It | ||
101 | may slightly impact performance, so this is only recommended for | ||
102 | internal tuning of the device driver. | ||
103 | |||
104 | config CCWGROUP | 95 | config CCWGROUP |
105 | tristate | 96 | tristate |
106 | default (LCS || CTC || QETH) | 97 | default (LCS || CTC || QETH) |
diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h index c04ee915dc1b..22a7ffbcaa42 100644 --- a/drivers/s390/net/qeth.h +++ b/drivers/s390/net/qeth.h | |||
@@ -176,7 +176,6 @@ extern struct ccwgroup_driver qeth_ccwgroup_driver; | |||
176 | /** | 176 | /** |
177 | * card stuff | 177 | * card stuff |
178 | */ | 178 | */ |
179 | #ifdef CONFIG_QETH_PERF_STATS | ||
180 | struct qeth_perf_stats { | 179 | struct qeth_perf_stats { |
181 | unsigned int bufs_rec; | 180 | unsigned int bufs_rec; |
182 | unsigned int bufs_sent; | 181 | unsigned int bufs_sent; |
@@ -211,8 +210,10 @@ struct qeth_perf_stats { | |||
211 | unsigned int large_send_cnt; | 210 | unsigned int large_send_cnt; |
212 | unsigned int sg_skbs_sent; | 211 | unsigned int sg_skbs_sent; |
213 | unsigned int sg_frags_sent; | 212 | unsigned int sg_frags_sent; |
213 | /* initial values when measuring starts */ | ||
214 | unsigned long initial_rx_packets; | ||
215 | unsigned long initial_tx_packets; | ||
214 | }; | 216 | }; |
215 | #endif /* CONFIG_QETH_PERF_STATS */ | ||
216 | 217 | ||
217 | /* Routing stuff */ | 218 | /* Routing stuff */ |
218 | struct qeth_routing_info { | 219 | struct qeth_routing_info { |
@@ -767,6 +768,7 @@ struct qeth_card_options { | |||
767 | int fake_ll; | 768 | int fake_ll; |
768 | int layer2; | 769 | int layer2; |
769 | enum qeth_large_send_types large_send; | 770 | enum qeth_large_send_types large_send; |
771 | int performance_stats; | ||
770 | }; | 772 | }; |
771 | 773 | ||
772 | /* | 774 | /* |
@@ -819,9 +821,7 @@ struct qeth_card { | |||
819 | struct list_head cmd_waiter_list; | 821 | struct list_head cmd_waiter_list; |
820 | /* QDIO buffer handling */ | 822 | /* QDIO buffer handling */ |
821 | struct qeth_qdio_info qdio; | 823 | struct qeth_qdio_info qdio; |
822 | #ifdef CONFIG_QETH_PERF_STATS | ||
823 | struct qeth_perf_stats perf_stats; | 824 | struct qeth_perf_stats perf_stats; |
824 | #endif /* CONFIG_QETH_PERF_STATS */ | ||
825 | int use_hard_stop; | 825 | int use_hard_stop; |
826 | int (*orig_hard_header)(struct sk_buff *,struct net_device *, | 826 | int (*orig_hard_header)(struct sk_buff *,struct net_device *, |
827 | unsigned short,void *,void *,unsigned); | 827 | unsigned short,void *,void *,unsigned); |
@@ -1049,13 +1049,11 @@ qeth_get_arphdr_type(int cardtype, int linktype) | |||
1049 | } | 1049 | } |
1050 | } | 1050 | } |
1051 | 1051 | ||
1052 | #ifdef CONFIG_QETH_PERF_STATS | ||
1053 | static inline int | 1052 | static inline int |
1054 | qeth_get_micros(void) | 1053 | qeth_get_micros(void) |
1055 | { | 1054 | { |
1056 | return (int) (get_clock() >> 12); | 1055 | return (int) (get_clock() >> 12); |
1057 | } | 1056 | } |
1058 | #endif | ||
1059 | 1057 | ||
1060 | static inline int | 1058 | static inline int |
1061 | qeth_get_qdio_q_format(struct qeth_card *card) | 1059 | qeth_get_qdio_q_format(struct qeth_card *card) |
diff --git a/drivers/s390/net/qeth_eddp.c b/drivers/s390/net/qeth_eddp.c index 8491598f9149..a363721cf28d 100644 --- a/drivers/s390/net/qeth_eddp.c +++ b/drivers/s390/net/qeth_eddp.c | |||
@@ -179,9 +179,8 @@ out_check: | |||
179 | flush_cnt++; | 179 | flush_cnt++; |
180 | } | 180 | } |
181 | } else { | 181 | } else { |
182 | #ifdef CONFIG_QETH_PERF_STATS | 182 | if (queue->card->options.performance_stats) |
183 | queue->card->perf_stats.skbs_sent_pack++; | 183 | queue->card->perf_stats.skbs_sent_pack++; |
184 | #endif | ||
185 | QETH_DBF_TEXT(trace, 6, "fillbfpa"); | 184 | QETH_DBF_TEXT(trace, 6, "fillbfpa"); |
186 | if (buf->next_element_to_fill >= | 185 | if (buf->next_element_to_fill >= |
187 | QETH_MAX_BUFFER_ELEMENTS(queue->card)) { | 186 | QETH_MAX_BUFFER_ELEMENTS(queue->card)) { |
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index 522fb9dd551e..0bc55a327907 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c | |||
@@ -1073,6 +1073,7 @@ qeth_set_intial_options(struct qeth_card *card) | |||
1073 | card->options.layer2 = 1; | 1073 | card->options.layer2 = 1; |
1074 | else | 1074 | else |
1075 | card->options.layer2 = 0; | 1075 | card->options.layer2 = 0; |
1076 | card->options.performance_stats = 1; | ||
1076 | } | 1077 | } |
1077 | 1078 | ||
1078 | /** | 1079 | /** |
@@ -2564,9 +2565,8 @@ qeth_process_inbound_buffer(struct qeth_card *card, | |||
2564 | /* get first element of current buffer */ | 2565 | /* get first element of current buffer */ |
2565 | element = (struct qdio_buffer_element *)&buf->buffer->element[0]; | 2566 | element = (struct qdio_buffer_element *)&buf->buffer->element[0]; |
2566 | offset = 0; | 2567 | offset = 0; |
2567 | #ifdef CONFIG_QETH_PERF_STATS | 2568 | if (card->options.performance_stats) |
2568 | card->perf_stats.bufs_rec++; | 2569 | card->perf_stats.bufs_rec++; |
2569 | #endif | ||
2570 | while((skb = qeth_get_next_skb(card, buf->buffer, &element, | 2570 | while((skb = qeth_get_next_skb(card, buf->buffer, &element, |
2571 | &offset, &hdr))) { | 2571 | &offset, &hdr))) { |
2572 | skb->dev = card->dev; | 2572 | skb->dev = card->dev; |
@@ -2623,7 +2623,7 @@ qeth_init_input_buffer(struct qeth_card *card, struct qeth_qdio_buffer *buf) | |||
2623 | { | 2623 | { |
2624 | struct qeth_buffer_pool_entry *pool_entry; | 2624 | struct qeth_buffer_pool_entry *pool_entry; |
2625 | int i; | 2625 | int i; |
2626 | 2626 | ||
2627 | pool_entry = qeth_get_buffer_pool_entry(card); | 2627 | pool_entry = qeth_get_buffer_pool_entry(card); |
2628 | /* | 2628 | /* |
2629 | * since the buffer is accessed only from the input_tasklet | 2629 | * since the buffer is accessed only from the input_tasklet |
@@ -2697,17 +2697,18 @@ qeth_queue_input_buffer(struct qeth_card *card, int index) | |||
2697 | * 'index') un-requeued -> this buffer is the first buffer that | 2697 | * 'index') un-requeued -> this buffer is the first buffer that |
2698 | * will be requeued the next time | 2698 | * will be requeued the next time |
2699 | */ | 2699 | */ |
2700 | #ifdef CONFIG_QETH_PERF_STATS | 2700 | if (card->options.performance_stats) { |
2701 | card->perf_stats.inbound_do_qdio_cnt++; | 2701 | card->perf_stats.inbound_do_qdio_cnt++; |
2702 | card->perf_stats.inbound_do_qdio_start_time = qeth_get_micros(); | 2702 | card->perf_stats.inbound_do_qdio_start_time = |
2703 | #endif | 2703 | qeth_get_micros(); |
2704 | } | ||
2704 | rc = do_QDIO(CARD_DDEV(card), | 2705 | rc = do_QDIO(CARD_DDEV(card), |
2705 | QDIO_FLAG_SYNC_INPUT | QDIO_FLAG_UNDER_INTERRUPT, | 2706 | QDIO_FLAG_SYNC_INPUT | QDIO_FLAG_UNDER_INTERRUPT, |
2706 | 0, queue->next_buf_to_init, count, NULL); | 2707 | 0, queue->next_buf_to_init, count, NULL); |
2707 | #ifdef CONFIG_QETH_PERF_STATS | 2708 | if (card->options.performance_stats) |
2708 | card->perf_stats.inbound_do_qdio_time += qeth_get_micros() - | 2709 | card->perf_stats.inbound_do_qdio_time += |
2709 | card->perf_stats.inbound_do_qdio_start_time; | 2710 | qeth_get_micros() - |
2710 | #endif | 2711 | card->perf_stats.inbound_do_qdio_start_time; |
2711 | if (rc){ | 2712 | if (rc){ |
2712 | PRINT_WARN("qeth_queue_input_buffer's do_QDIO " | 2713 | PRINT_WARN("qeth_queue_input_buffer's do_QDIO " |
2713 | "return %i (device %s).\n", | 2714 | "return %i (device %s).\n", |
@@ -2743,10 +2744,10 @@ qeth_qdio_input_handler(struct ccw_device * ccwdev, unsigned int status, | |||
2743 | QETH_DBF_TEXT(trace, 6, "qdinput"); | 2744 | QETH_DBF_TEXT(trace, 6, "qdinput"); |
2744 | card = (struct qeth_card *) card_ptr; | 2745 | card = (struct qeth_card *) card_ptr; |
2745 | net_dev = card->dev; | 2746 | net_dev = card->dev; |
2746 | #ifdef CONFIG_QETH_PERF_STATS | 2747 | if (card->options.performance_stats) { |
2747 | card->perf_stats.inbound_cnt++; | 2748 | card->perf_stats.inbound_cnt++; |
2748 | card->perf_stats.inbound_start_time = qeth_get_micros(); | 2749 | card->perf_stats.inbound_start_time = qeth_get_micros(); |
2749 | #endif | 2750 | } |
2750 | if (status & QDIO_STATUS_LOOK_FOR_ERROR) { | 2751 | if (status & QDIO_STATUS_LOOK_FOR_ERROR) { |
2751 | if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION){ | 2752 | if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION){ |
2752 | QETH_DBF_TEXT(trace, 1,"qdinchk"); | 2753 | QETH_DBF_TEXT(trace, 1,"qdinchk"); |
@@ -2768,10 +2769,9 @@ qeth_qdio_input_handler(struct ccw_device * ccwdev, unsigned int status, | |||
2768 | qeth_put_buffer_pool_entry(card, buffer->pool_entry); | 2769 | qeth_put_buffer_pool_entry(card, buffer->pool_entry); |
2769 | qeth_queue_input_buffer(card, index); | 2770 | qeth_queue_input_buffer(card, index); |
2770 | } | 2771 | } |
2771 | #ifdef CONFIG_QETH_PERF_STATS | 2772 | if (card->options.performance_stats) |
2772 | card->perf_stats.inbound_time += qeth_get_micros() - | 2773 | card->perf_stats.inbound_time += qeth_get_micros() - |
2773 | card->perf_stats.inbound_start_time; | 2774 | card->perf_stats.inbound_start_time; |
2774 | #endif | ||
2775 | } | 2775 | } |
2776 | 2776 | ||
2777 | static inline int | 2777 | static inline int |
@@ -2861,10 +2861,11 @@ qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int, | |||
2861 | } | 2861 | } |
2862 | 2862 | ||
2863 | queue->card->dev->trans_start = jiffies; | 2863 | queue->card->dev->trans_start = jiffies; |
2864 | #ifdef CONFIG_QETH_PERF_STATS | 2864 | if (queue->card->options.performance_stats) { |
2865 | queue->card->perf_stats.outbound_do_qdio_cnt++; | 2865 | queue->card->perf_stats.outbound_do_qdio_cnt++; |
2866 | queue->card->perf_stats.outbound_do_qdio_start_time = qeth_get_micros(); | 2866 | queue->card->perf_stats.outbound_do_qdio_start_time = |
2867 | #endif | 2867 | qeth_get_micros(); |
2868 | } | ||
2868 | if (under_int) | 2869 | if (under_int) |
2869 | rc = do_QDIO(CARD_DDEV(queue->card), | 2870 | rc = do_QDIO(CARD_DDEV(queue->card), |
2870 | QDIO_FLAG_SYNC_OUTPUT | QDIO_FLAG_UNDER_INTERRUPT, | 2871 | QDIO_FLAG_SYNC_OUTPUT | QDIO_FLAG_UNDER_INTERRUPT, |
@@ -2872,10 +2873,10 @@ qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int, | |||
2872 | else | 2873 | else |
2873 | rc = do_QDIO(CARD_DDEV(queue->card), QDIO_FLAG_SYNC_OUTPUT, | 2874 | rc = do_QDIO(CARD_DDEV(queue->card), QDIO_FLAG_SYNC_OUTPUT, |
2874 | queue->queue_no, index, count, NULL); | 2875 | queue->queue_no, index, count, NULL); |
2875 | #ifdef CONFIG_QETH_PERF_STATS | 2876 | if (queue->card->options.performance_stats) |
2876 | queue->card->perf_stats.outbound_do_qdio_time += qeth_get_micros() - | 2877 | queue->card->perf_stats.outbound_do_qdio_time += |
2877 | queue->card->perf_stats.outbound_do_qdio_start_time; | 2878 | qeth_get_micros() - |
2878 | #endif | 2879 | queue->card->perf_stats.outbound_do_qdio_start_time; |
2879 | if (rc){ | 2880 | if (rc){ |
2880 | QETH_DBF_TEXT(trace, 2, "flushbuf"); | 2881 | QETH_DBF_TEXT(trace, 2, "flushbuf"); |
2881 | QETH_DBF_TEXT_(trace, 2, " err%d", rc); | 2882 | QETH_DBF_TEXT_(trace, 2, " err%d", rc); |
@@ -2887,9 +2888,8 @@ qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int, | |||
2887 | return; | 2888 | return; |
2888 | } | 2889 | } |
2889 | atomic_add(count, &queue->used_buffers); | 2890 | atomic_add(count, &queue->used_buffers); |
2890 | #ifdef CONFIG_QETH_PERF_STATS | 2891 | if (queue->card->options.performance_stats) |
2891 | queue->card->perf_stats.bufs_sent += count; | 2892 | queue->card->perf_stats.bufs_sent += count; |
2892 | #endif | ||
2893 | } | 2893 | } |
2894 | 2894 | ||
2895 | /* | 2895 | /* |
@@ -2904,9 +2904,8 @@ qeth_switch_to_packing_if_needed(struct qeth_qdio_out_q *queue) | |||
2904 | >= QETH_HIGH_WATERMARK_PACK){ | 2904 | >= QETH_HIGH_WATERMARK_PACK){ |
2905 | /* switch non-PACKING -> PACKING */ | 2905 | /* switch non-PACKING -> PACKING */ |
2906 | QETH_DBF_TEXT(trace, 6, "np->pack"); | 2906 | QETH_DBF_TEXT(trace, 6, "np->pack"); |
2907 | #ifdef CONFIG_QETH_PERF_STATS | 2907 | if (queue->card->options.performance_stats) |
2908 | queue->card->perf_stats.sc_dp_p++; | 2908 | queue->card->perf_stats.sc_dp_p++; |
2909 | #endif | ||
2910 | queue->do_pack = 1; | 2909 | queue->do_pack = 1; |
2911 | } | 2910 | } |
2912 | } | 2911 | } |
@@ -2929,9 +2928,8 @@ qeth_switch_to_nonpacking_if_needed(struct qeth_qdio_out_q *queue) | |||
2929 | <= QETH_LOW_WATERMARK_PACK) { | 2928 | <= QETH_LOW_WATERMARK_PACK) { |
2930 | /* switch PACKING -> non-PACKING */ | 2929 | /* switch PACKING -> non-PACKING */ |
2931 | QETH_DBF_TEXT(trace, 6, "pack->np"); | 2930 | QETH_DBF_TEXT(trace, 6, "pack->np"); |
2932 | #ifdef CONFIG_QETH_PERF_STATS | 2931 | if (queue->card->options.performance_stats) |
2933 | queue->card->perf_stats.sc_p_dp++; | 2932 | queue->card->perf_stats.sc_p_dp++; |
2934 | #endif | ||
2935 | queue->do_pack = 0; | 2933 | queue->do_pack = 0; |
2936 | /* flush packing buffers */ | 2934 | /* flush packing buffers */ |
2937 | buffer = &queue->bufs[queue->next_buf_to_fill]; | 2935 | buffer = &queue->bufs[queue->next_buf_to_fill]; |
@@ -2943,7 +2941,7 @@ qeth_switch_to_nonpacking_if_needed(struct qeth_qdio_out_q *queue) | |||
2943 | queue->next_buf_to_fill = | 2941 | queue->next_buf_to_fill = |
2944 | (queue->next_buf_to_fill + 1) % | 2942 | (queue->next_buf_to_fill + 1) % |
2945 | QDIO_MAX_BUFFERS_PER_Q; | 2943 | QDIO_MAX_BUFFERS_PER_Q; |
2946 | } | 2944 | } |
2947 | } | 2945 | } |
2948 | } | 2946 | } |
2949 | return flush_count; | 2947 | return flush_count; |
@@ -2999,11 +2997,10 @@ qeth_check_outbound_queue(struct qeth_qdio_out_q *queue) | |||
2999 | !atomic_read(&queue->set_pci_flags_count)) | 2997 | !atomic_read(&queue->set_pci_flags_count)) |
3000 | flush_cnt += | 2998 | flush_cnt += |
3001 | qeth_flush_buffers_on_no_pci(queue); | 2999 | qeth_flush_buffers_on_no_pci(queue); |
3002 | #ifdef CONFIG_QETH_PERF_STATS | 3000 | if (queue->card->options.performance_stats && |
3003 | if (q_was_packing) | 3001 | q_was_packing) |
3004 | queue->card->perf_stats.bufs_sent_pack += | 3002 | queue->card->perf_stats.bufs_sent_pack += |
3005 | flush_cnt; | 3003 | flush_cnt; |
3006 | #endif | ||
3007 | if (flush_cnt) | 3004 | if (flush_cnt) |
3008 | qeth_flush_buffers(queue, 1, index, flush_cnt); | 3005 | qeth_flush_buffers(queue, 1, index, flush_cnt); |
3009 | atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); | 3006 | atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); |
@@ -3033,10 +3030,11 @@ qeth_qdio_output_handler(struct ccw_device * ccwdev, unsigned int status, | |||
3033 | return; | 3030 | return; |
3034 | } | 3031 | } |
3035 | } | 3032 | } |
3036 | #ifdef CONFIG_QETH_PERF_STATS | 3033 | if (card->options.performance_stats) { |
3037 | card->perf_stats.outbound_handler_cnt++; | 3034 | card->perf_stats.outbound_handler_cnt++; |
3038 | card->perf_stats.outbound_handler_start_time = qeth_get_micros(); | 3035 | card->perf_stats.outbound_handler_start_time = |
3039 | #endif | 3036 | qeth_get_micros(); |
3037 | } | ||
3040 | for(i = first_element; i < (first_element + count); ++i){ | 3038 | for(i = first_element; i < (first_element + count); ++i){ |
3041 | buffer = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q]; | 3039 | buffer = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q]; |
3042 | /*we only handle the KICK_IT error by doing a recovery */ | 3040 | /*we only handle the KICK_IT error by doing a recovery */ |
@@ -3055,10 +3053,9 @@ qeth_qdio_output_handler(struct ccw_device * ccwdev, unsigned int status, | |||
3055 | qeth_check_outbound_queue(queue); | 3053 | qeth_check_outbound_queue(queue); |
3056 | 3054 | ||
3057 | netif_wake_queue(queue->card->dev); | 3055 | netif_wake_queue(queue->card->dev); |
3058 | #ifdef CONFIG_QETH_PERF_STATS | 3056 | if (card->options.performance_stats) |
3059 | card->perf_stats.outbound_handler_time += qeth_get_micros() - | 3057 | card->perf_stats.outbound_handler_time += qeth_get_micros() - |
3060 | card->perf_stats.outbound_handler_start_time; | 3058 | card->perf_stats.outbound_handler_start_time; |
3061 | #endif | ||
3062 | } | 3059 | } |
3063 | 3060 | ||
3064 | static void | 3061 | static void |
@@ -3684,10 +3681,10 @@ qeth_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
3684 | /* return OK; otherwise ksoftirqd goes to 100% */ | 3681 | /* return OK; otherwise ksoftirqd goes to 100% */ |
3685 | return NETDEV_TX_OK; | 3682 | return NETDEV_TX_OK; |
3686 | } | 3683 | } |
3687 | #ifdef CONFIG_QETH_PERF_STATS | 3684 | if (card->options.performance_stats) { |
3688 | card->perf_stats.outbound_cnt++; | 3685 | card->perf_stats.outbound_cnt++; |
3689 | card->perf_stats.outbound_start_time = qeth_get_micros(); | 3686 | card->perf_stats.outbound_start_time = qeth_get_micros(); |
3690 | #endif | 3687 | } |
3691 | netif_stop_queue(dev); | 3688 | netif_stop_queue(dev); |
3692 | if ((rc = qeth_send_packet(card, skb))) { | 3689 | if ((rc = qeth_send_packet(card, skb))) { |
3693 | if (rc == -EBUSY) { | 3690 | if (rc == -EBUSY) { |
@@ -3701,10 +3698,9 @@ qeth_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
3701 | } | 3698 | } |
3702 | } | 3699 | } |
3703 | netif_wake_queue(dev); | 3700 | netif_wake_queue(dev); |
3704 | #ifdef CONFIG_QETH_PERF_STATS | 3701 | if (card->options.performance_stats) |
3705 | card->perf_stats.outbound_time += qeth_get_micros() - | 3702 | card->perf_stats.outbound_time += qeth_get_micros() - |
3706 | card->perf_stats.outbound_start_time; | 3703 | card->perf_stats.outbound_start_time; |
3707 | #endif | ||
3708 | return rc; | 3704 | return rc; |
3709 | } | 3705 | } |
3710 | 3706 | ||
@@ -4213,9 +4209,8 @@ qeth_fill_buffer(struct qeth_qdio_out_q *queue, | |||
4213 | flush_cnt = 1; | 4209 | flush_cnt = 1; |
4214 | } else { | 4210 | } else { |
4215 | QETH_DBF_TEXT(trace, 6, "fillbfpa"); | 4211 | QETH_DBF_TEXT(trace, 6, "fillbfpa"); |
4216 | #ifdef CONFIG_QETH_PERF_STATS | 4212 | if (queue->card->options.performance_stats) |
4217 | queue->card->perf_stats.skbs_sent_pack++; | 4213 | queue->card->perf_stats.skbs_sent_pack++; |
4218 | #endif | ||
4219 | if (buf->next_element_to_fill >= | 4214 | if (buf->next_element_to_fill >= |
4220 | QETH_MAX_BUFFER_ELEMENTS(queue->card)) { | 4215 | QETH_MAX_BUFFER_ELEMENTS(queue->card)) { |
4221 | /* | 4216 | /* |
@@ -4380,10 +4375,8 @@ out: | |||
4380 | qeth_flush_buffers(queue, 0, start_index, flush_count); | 4375 | qeth_flush_buffers(queue, 0, start_index, flush_count); |
4381 | } | 4376 | } |
4382 | /* at this point the queue is UNLOCKED again */ | 4377 | /* at this point the queue is UNLOCKED again */ |
4383 | #ifdef CONFIG_QETH_PERF_STATS | 4378 | if (queue->card->options.performance_stats && do_pack) |
4384 | if (do_pack) | ||
4385 | queue->card->perf_stats.bufs_sent_pack += flush_count; | 4379 | queue->card->perf_stats.bufs_sent_pack += flush_count; |
4386 | #endif /* CONFIG_QETH_PERF_STATS */ | ||
4387 | 4380 | ||
4388 | return rc; | 4381 | return rc; |
4389 | } | 4382 | } |
@@ -4420,10 +4413,8 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) | |||
4420 | enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO; | 4413 | enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO; |
4421 | struct qeth_eddp_context *ctx = NULL; | 4414 | struct qeth_eddp_context *ctx = NULL; |
4422 | int tx_bytes = skb->len; | 4415 | int tx_bytes = skb->len; |
4423 | #ifdef CONFIG_QETH_PERF_STATS | ||
4424 | unsigned short nr_frags = skb_shinfo(skb)->nr_frags; | 4416 | unsigned short nr_frags = skb_shinfo(skb)->nr_frags; |
4425 | unsigned short tso_size = skb_shinfo(skb)->gso_size; | 4417 | unsigned short tso_size = skb_shinfo(skb)->gso_size; |
4426 | #endif | ||
4427 | struct sk_buff *new_skb, *new_skb2; | 4418 | struct sk_buff *new_skb, *new_skb2; |
4428 | int rc; | 4419 | int rc; |
4429 | 4420 | ||
@@ -4505,19 +4496,19 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) | |||
4505 | card->stats.tx_bytes += tx_bytes; | 4496 | card->stats.tx_bytes += tx_bytes; |
4506 | if (new_skb != skb) | 4497 | if (new_skb != skb) |
4507 | dev_kfree_skb_any(skb); | 4498 | dev_kfree_skb_any(skb); |
4508 | #ifdef CONFIG_QETH_PERF_STATS | 4499 | if (card->options.performance_stats) { |
4509 | if (tso_size && | 4500 | if (tso_size && |
4510 | !(large_send == QETH_LARGE_SEND_NO)) { | 4501 | !(large_send == QETH_LARGE_SEND_NO)) { |
4511 | card->perf_stats.large_send_bytes += tx_bytes; | 4502 | card->perf_stats.large_send_bytes += tx_bytes; |
4512 | card->perf_stats.large_send_cnt++; | 4503 | card->perf_stats.large_send_cnt++; |
4513 | } | 4504 | } |
4514 | if (nr_frags > 0) { | 4505 | if (nr_frags > 0) { |
4515 | card->perf_stats.sg_skbs_sent++; | 4506 | card->perf_stats.sg_skbs_sent++; |
4516 | /* nr_frags + skb->data */ | 4507 | /* nr_frags + skb->data */ |
4517 | card->perf_stats.sg_frags_sent += | 4508 | card->perf_stats.sg_frags_sent += |
4518 | nr_frags + 1; | 4509 | nr_frags + 1; |
4510 | } | ||
4519 | } | 4511 | } |
4520 | #endif /* CONFIG_QETH_PERF_STATS */ | ||
4521 | } else { | 4512 | } else { |
4522 | card->stats.tx_dropped++; | 4513 | card->stats.tx_dropped++; |
4523 | __qeth_free_new_skb(skb, new_skb); | 4514 | __qeth_free_new_skb(skb, new_skb); |
@@ -7878,12 +7869,12 @@ __qeth_set_online(struct ccwgroup_device *gdev, int recovery_mode) | |||
7878 | QETH_DBF_TEXT_(setup, 2, "5err%d", rc); | 7869 | QETH_DBF_TEXT_(setup, 2, "5err%d", rc); |
7879 | goto out_remove; | 7870 | goto out_remove; |
7880 | } | 7871 | } |
7881 | card->state = CARD_STATE_SOFTSETUP; | ||
7882 | 7872 | ||
7883 | if ((rc = qeth_init_qdio_queues(card))){ | 7873 | if ((rc = qeth_init_qdio_queues(card))){ |
7884 | QETH_DBF_TEXT_(setup, 2, "6err%d", rc); | 7874 | QETH_DBF_TEXT_(setup, 2, "6err%d", rc); |
7885 | goto out_remove; | 7875 | goto out_remove; |
7886 | } | 7876 | } |
7877 | card->state = CARD_STATE_SOFTSETUP; | ||
7887 | netif_carrier_on(card->dev); | 7878 | netif_carrier_on(card->dev); |
7888 | 7879 | ||
7889 | qeth_set_allowed_threads(card, 0xffffffff, 0); | 7880 | qeth_set_allowed_threads(card, 0xffffffff, 0); |
diff --git a/drivers/s390/net/qeth_proc.c b/drivers/s390/net/qeth_proc.c index 66f2da14e6e3..faa768e59257 100644 --- a/drivers/s390/net/qeth_proc.c +++ b/drivers/s390/net/qeth_proc.c | |||
@@ -173,7 +173,6 @@ static struct file_operations qeth_procfile_fops = { | |||
173 | #define QETH_PERF_PROCFILE_NAME "qeth_perf" | 173 | #define QETH_PERF_PROCFILE_NAME "qeth_perf" |
174 | static struct proc_dir_entry *qeth_perf_procfile; | 174 | static struct proc_dir_entry *qeth_perf_procfile; |
175 | 175 | ||
176 | #ifdef CONFIG_QETH_PERF_STATS | ||
177 | static int | 176 | static int |
178 | qeth_perf_procfile_seq_show(struct seq_file *s, void *it) | 177 | qeth_perf_procfile_seq_show(struct seq_file *s, void *it) |
179 | { | 178 | { |
@@ -192,14 +191,21 @@ qeth_perf_procfile_seq_show(struct seq_file *s, void *it) | |||
192 | CARD_DDEV_ID(card), | 191 | CARD_DDEV_ID(card), |
193 | QETH_CARD_IFNAME(card) | 192 | QETH_CARD_IFNAME(card) |
194 | ); | 193 | ); |
194 | if (!card->options.performance_stats) | ||
195 | seq_printf(s, "Performance statistics are deactivated.\n"); | ||
195 | seq_printf(s, " Skb's/buffers received : %lu/%u\n" | 196 | seq_printf(s, " Skb's/buffers received : %lu/%u\n" |
196 | " Skb's/buffers sent : %lu/%u\n\n", | 197 | " Skb's/buffers sent : %lu/%u\n\n", |
197 | card->stats.rx_packets, card->perf_stats.bufs_rec, | 198 | card->stats.rx_packets - |
198 | card->stats.tx_packets, card->perf_stats.bufs_sent | 199 | card->perf_stats.initial_rx_packets, |
200 | card->perf_stats.bufs_rec, | ||
201 | card->stats.tx_packets - | ||
202 | card->perf_stats.initial_tx_packets, | ||
203 | card->perf_stats.bufs_sent | ||
199 | ); | 204 | ); |
200 | seq_printf(s, " Skb's/buffers sent without packing : %lu/%u\n" | 205 | seq_printf(s, " Skb's/buffers sent without packing : %lu/%u\n" |
201 | " Skb's/buffers sent with packing : %u/%u\n\n", | 206 | " Skb's/buffers sent with packing : %u/%u\n\n", |
202 | card->stats.tx_packets - card->perf_stats.skbs_sent_pack, | 207 | card->stats.tx_packets - card->perf_stats.initial_tx_packets |
208 | - card->perf_stats.skbs_sent_pack, | ||
203 | card->perf_stats.bufs_sent - card->perf_stats.bufs_sent_pack, | 209 | card->perf_stats.bufs_sent - card->perf_stats.bufs_sent_pack, |
204 | card->perf_stats.skbs_sent_pack, | 210 | card->perf_stats.skbs_sent_pack, |
205 | card->perf_stats.bufs_sent_pack | 211 | card->perf_stats.bufs_sent_pack |
@@ -275,11 +281,6 @@ static struct file_operations qeth_perf_procfile_fops = { | |||
275 | .release = seq_release, | 281 | .release = seq_release, |
276 | }; | 282 | }; |
277 | 283 | ||
278 | #define qeth_perf_procfile_created qeth_perf_procfile | ||
279 | #else | ||
280 | #define qeth_perf_procfile_created 1 | ||
281 | #endif /* CONFIG_QETH_PERF_STATS */ | ||
282 | |||
283 | int __init | 284 | int __init |
284 | qeth_create_procfs_entries(void) | 285 | qeth_create_procfs_entries(void) |
285 | { | 286 | { |
@@ -288,15 +289,13 @@ qeth_create_procfs_entries(void) | |||
288 | if (qeth_procfile) | 289 | if (qeth_procfile) |
289 | qeth_procfile->proc_fops = &qeth_procfile_fops; | 290 | qeth_procfile->proc_fops = &qeth_procfile_fops; |
290 | 291 | ||
291 | #ifdef CONFIG_QETH_PERF_STATS | ||
292 | qeth_perf_procfile = create_proc_entry(QETH_PERF_PROCFILE_NAME, | 292 | qeth_perf_procfile = create_proc_entry(QETH_PERF_PROCFILE_NAME, |
293 | S_IFREG | 0444, NULL); | 293 | S_IFREG | 0444, NULL); |
294 | if (qeth_perf_procfile) | 294 | if (qeth_perf_procfile) |
295 | qeth_perf_procfile->proc_fops = &qeth_perf_procfile_fops; | 295 | qeth_perf_procfile->proc_fops = &qeth_perf_procfile_fops; |
296 | #endif /* CONFIG_QETH_PERF_STATS */ | ||
297 | 296 | ||
298 | if (qeth_procfile && | 297 | if (qeth_procfile && |
299 | qeth_perf_procfile_created) | 298 | qeth_perf_procfile) |
300 | return 0; | 299 | return 0; |
301 | else | 300 | else |
302 | return -ENOMEM; | 301 | return -ENOMEM; |
diff --git a/drivers/s390/net/qeth_sys.c b/drivers/s390/net/qeth_sys.c index c1f3187f37ea..5836737ac58f 100644 --- a/drivers/s390/net/qeth_sys.c +++ b/drivers/s390/net/qeth_sys.c | |||
@@ -743,6 +743,47 @@ static DEVICE_ATTR(layer2, 0644, qeth_dev_layer2_show, | |||
743 | qeth_dev_layer2_store); | 743 | qeth_dev_layer2_store); |
744 | 744 | ||
745 | static ssize_t | 745 | static ssize_t |
746 | qeth_dev_performance_stats_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
747 | { | ||
748 | struct qeth_card *card = dev->driver_data; | ||
749 | |||
750 | if (!card) | ||
751 | return -EINVAL; | ||
752 | |||
753 | return sprintf(buf, "%i\n", card->options.performance_stats ? 1:0); | ||
754 | } | ||
755 | |||
756 | static ssize_t | ||
757 | qeth_dev_performance_stats_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
758 | { | ||
759 | struct qeth_card *card = dev->driver_data; | ||
760 | char *tmp; | ||
761 | int i; | ||
762 | |||
763 | if (!card) | ||
764 | return -EINVAL; | ||
765 | |||
766 | i = simple_strtoul(buf, &tmp, 16); | ||
767 | if ((i == 0) || (i == 1)) { | ||
768 | if (i == card->options.performance_stats) | ||
769 | return count; | ||
770 | card->options.performance_stats = i; | ||
771 | if (i == 0) | ||
772 | memset(&card->perf_stats, 0, | ||
773 | sizeof(struct qeth_perf_stats)); | ||
774 | card->perf_stats.initial_rx_packets = card->stats.rx_packets; | ||
775 | card->perf_stats.initial_tx_packets = card->stats.tx_packets; | ||
776 | } else { | ||
777 | PRINT_WARN("performance_stats: write 0 or 1 to this file!\n"); | ||
778 | return -EINVAL; | ||
779 | } | ||
780 | return count; | ||
781 | } | ||
782 | |||
783 | static DEVICE_ATTR(performance_stats, 0644, qeth_dev_performance_stats_show, | ||
784 | qeth_dev_performance_stats_store); | ||
785 | |||
786 | static ssize_t | ||
746 | qeth_dev_large_send_show(struct device *dev, struct device_attribute *attr, char *buf) | 787 | qeth_dev_large_send_show(struct device *dev, struct device_attribute *attr, char *buf) |
747 | { | 788 | { |
748 | struct qeth_card *card = dev->driver_data; | 789 | struct qeth_card *card = dev->driver_data; |
@@ -928,6 +969,7 @@ static struct device_attribute * qeth_device_attrs[] = { | |||
928 | &dev_attr_canonical_macaddr, | 969 | &dev_attr_canonical_macaddr, |
929 | &dev_attr_layer2, | 970 | &dev_attr_layer2, |
930 | &dev_attr_large_send, | 971 | &dev_attr_large_send, |
972 | &dev_attr_performance_stats, | ||
931 | NULL, | 973 | NULL, |
932 | }; | 974 | }; |
933 | 975 | ||