aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrank Pavlic <fpavlic@de.ibm.com>2006-09-15 10:26:34 -0400
committerJeff Garzik <jeff@garzik.org>2006-09-17 01:03:07 -0400
commit09d2d38a152419467f764c0f730821e896766c1f (patch)
tree56001b9b3573a9a2fc05f74a4e2d0571607d0a19
parentf7b65d70a3e6f1c97eb614964270816992d0d4b4 (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/Kconfig9
-rw-r--r--drivers/s390/net/qeth.h10
-rw-r--r--drivers/s390/net/qeth_eddp.c5
-rw-r--r--drivers/s390/net/qeth_main.c147
-rw-r--r--drivers/s390/net/qeth_proc.c23
-rw-r--r--drivers/s390/net/qeth_sys.c42
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
95config 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
104config CCWGROUP 95config 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
180struct qeth_perf_stats { 179struct 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 */
218struct qeth_routing_info { 219struct 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
1053static inline int 1052static inline int
1054qeth_get_micros(void) 1053qeth_get_micros(void)
1055{ 1054{
1056 return (int) (get_clock() >> 12); 1055 return (int) (get_clock() >> 12);
1057} 1056}
1058#endif
1059 1057
1060static inline int 1058static inline int
1061qeth_get_qdio_q_format(struct qeth_card *card) 1059qeth_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
2777static inline int 2777static 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
3064static void 3061static 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"
174static struct proc_dir_entry *qeth_perf_procfile; 174static struct proc_dir_entry *qeth_perf_procfile;
175 175
176#ifdef CONFIG_QETH_PERF_STATS
177static int 176static int
178qeth_perf_procfile_seq_show(struct seq_file *s, void *it) 177qeth_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
283int __init 284int __init
284qeth_create_procfs_entries(void) 285qeth_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
745static ssize_t 745static ssize_t
746qeth_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
756static ssize_t
757qeth_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
783static DEVICE_ATTR(performance_stats, 0644, qeth_dev_performance_stats_show,
784 qeth_dev_performance_stats_store);
785
786static ssize_t
746qeth_dev_large_send_show(struct device *dev, struct device_attribute *attr, char *buf) 787qeth_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