aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/net/qeth_main.c
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 /drivers/s390/net/qeth_main.c
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>
Diffstat (limited to 'drivers/s390/net/qeth_main.c')
-rw-r--r--drivers/s390/net/qeth_main.c147
1 files changed, 69 insertions, 78 deletions
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);