diff options
Diffstat (limited to 'drivers/s390/net/qeth_main.c')
-rw-r--r-- | drivers/s390/net/qeth_main.c | 517 |
1 files changed, 271 insertions, 246 deletions
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index e1327b8fce00..5613b4564fa2 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 | /** |
@@ -1708,6 +1709,7 @@ qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob) | |||
1708 | "IP address reset.\n", | 1709 | "IP address reset.\n", |
1709 | QETH_CARD_IFNAME(card), | 1710 | QETH_CARD_IFNAME(card), |
1710 | card->info.chpid); | 1711 | card->info.chpid); |
1712 | netif_carrier_on(card->dev); | ||
1711 | qeth_schedule_recovery(card); | 1713 | qeth_schedule_recovery(card); |
1712 | return NULL; | 1714 | return NULL; |
1713 | case IPA_CMD_MODCCID: | 1715 | case IPA_CMD_MODCCID: |
@@ -2464,24 +2466,6 @@ qeth_rebuild_skb_fake_ll(struct qeth_card *card, struct sk_buff *skb, | |||
2464 | qeth_rebuild_skb_fake_ll_eth(card, skb, hdr); | 2466 | qeth_rebuild_skb_fake_ll_eth(card, skb, hdr); |
2465 | } | 2467 | } |
2466 | 2468 | ||
2467 | static inline void | ||
2468 | qeth_rebuild_skb_vlan(struct qeth_card *card, struct sk_buff *skb, | ||
2469 | struct qeth_hdr *hdr) | ||
2470 | { | ||
2471 | #ifdef CONFIG_QETH_VLAN | ||
2472 | u16 *vlan_tag; | ||
2473 | |||
2474 | if (hdr->hdr.l3.ext_flags & | ||
2475 | (QETH_HDR_EXT_VLAN_FRAME | QETH_HDR_EXT_INCLUDE_VLAN_TAG)) { | ||
2476 | vlan_tag = (u16 *) skb_push(skb, VLAN_HLEN); | ||
2477 | *vlan_tag = (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_VLAN_FRAME)? | ||
2478 | hdr->hdr.l3.vlan_id : *((u16 *)&hdr->hdr.l3.dest_addr[12]); | ||
2479 | *(vlan_tag + 1) = skb->protocol; | ||
2480 | skb->protocol = __constant_htons(ETH_P_8021Q); | ||
2481 | } | ||
2482 | #endif /* CONFIG_QETH_VLAN */ | ||
2483 | } | ||
2484 | |||
2485 | static inline __u16 | 2469 | static inline __u16 |
2486 | qeth_layer2_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, | 2470 | qeth_layer2_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, |
2487 | struct qeth_hdr *hdr) | 2471 | struct qeth_hdr *hdr) |
@@ -2510,15 +2494,16 @@ qeth_layer2_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, | |||
2510 | return vlan_id; | 2494 | return vlan_id; |
2511 | } | 2495 | } |
2512 | 2496 | ||
2513 | static inline void | 2497 | static inline __u16 |
2514 | qeth_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, | 2498 | qeth_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, |
2515 | struct qeth_hdr *hdr) | 2499 | struct qeth_hdr *hdr) |
2516 | { | 2500 | { |
2501 | unsigned short vlan_id = 0; | ||
2517 | #ifdef CONFIG_QETH_IPV6 | 2502 | #ifdef CONFIG_QETH_IPV6 |
2518 | if (hdr->hdr.l3.flags & QETH_HDR_PASSTHRU) { | 2503 | if (hdr->hdr.l3.flags & QETH_HDR_PASSTHRU) { |
2519 | skb->pkt_type = PACKET_HOST; | 2504 | skb->pkt_type = PACKET_HOST; |
2520 | skb->protocol = qeth_type_trans(skb, card->dev); | 2505 | skb->protocol = qeth_type_trans(skb, card->dev); |
2521 | return; | 2506 | return 0; |
2522 | } | 2507 | } |
2523 | #endif /* CONFIG_QETH_IPV6 */ | 2508 | #endif /* CONFIG_QETH_IPV6 */ |
2524 | skb->protocol = htons((hdr->hdr.l3.flags & QETH_HDR_IPV6)? ETH_P_IPV6 : | 2509 | skb->protocol = htons((hdr->hdr.l3.flags & QETH_HDR_IPV6)? ETH_P_IPV6 : |
@@ -2540,7 +2525,13 @@ qeth_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, | |||
2540 | default: | 2525 | default: |
2541 | skb->pkt_type = PACKET_HOST; | 2526 | skb->pkt_type = PACKET_HOST; |
2542 | } | 2527 | } |
2543 | qeth_rebuild_skb_vlan(card, skb, hdr); | 2528 | |
2529 | if (hdr->hdr.l3.ext_flags & | ||
2530 | (QETH_HDR_EXT_VLAN_FRAME | QETH_HDR_EXT_INCLUDE_VLAN_TAG)) { | ||
2531 | vlan_id = (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_VLAN_FRAME)? | ||
2532 | hdr->hdr.l3.vlan_id : *((u16 *)&hdr->hdr.l3.dest_addr[12]); | ||
2533 | } | ||
2534 | |||
2544 | if (card->options.fake_ll) | 2535 | if (card->options.fake_ll) |
2545 | qeth_rebuild_skb_fake_ll(card, skb, hdr); | 2536 | qeth_rebuild_skb_fake_ll(card, skb, hdr); |
2546 | else | 2537 | else |
@@ -2556,6 +2547,7 @@ qeth_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, | |||
2556 | else | 2547 | else |
2557 | skb->ip_summed = SW_CHECKSUMMING; | 2548 | skb->ip_summed = SW_CHECKSUMMING; |
2558 | } | 2549 | } |
2550 | return vlan_id; | ||
2559 | } | 2551 | } |
2560 | 2552 | ||
2561 | static inline void | 2553 | static inline void |
@@ -2568,20 +2560,20 @@ qeth_process_inbound_buffer(struct qeth_card *card, | |||
2568 | int offset; | 2560 | int offset; |
2569 | int rxrc; | 2561 | int rxrc; |
2570 | __u16 vlan_tag = 0; | 2562 | __u16 vlan_tag = 0; |
2563 | __u16 *vlan_addr; | ||
2571 | 2564 | ||
2572 | /* get first element of current buffer */ | 2565 | /* get first element of current buffer */ |
2573 | element = (struct qdio_buffer_element *)&buf->buffer->element[0]; | 2566 | element = (struct qdio_buffer_element *)&buf->buffer->element[0]; |
2574 | offset = 0; | 2567 | offset = 0; |
2575 | #ifdef CONFIG_QETH_PERF_STATS | 2568 | if (card->options.performance_stats) |
2576 | card->perf_stats.bufs_rec++; | 2569 | card->perf_stats.bufs_rec++; |
2577 | #endif | ||
2578 | while((skb = qeth_get_next_skb(card, buf->buffer, &element, | 2570 | while((skb = qeth_get_next_skb(card, buf->buffer, &element, |
2579 | &offset, &hdr))) { | 2571 | &offset, &hdr))) { |
2580 | skb->dev = card->dev; | 2572 | skb->dev = card->dev; |
2581 | if (hdr->hdr.l2.id == QETH_HEADER_TYPE_LAYER2) | 2573 | if (hdr->hdr.l2.id == QETH_HEADER_TYPE_LAYER2) |
2582 | vlan_tag = qeth_layer2_rebuild_skb(card, skb, hdr); | 2574 | vlan_tag = qeth_layer2_rebuild_skb(card, skb, hdr); |
2583 | else if (hdr->hdr.l3.id == QETH_HEADER_TYPE_LAYER3) | 2575 | else if (hdr->hdr.l3.id == QETH_HEADER_TYPE_LAYER3) |
2584 | qeth_rebuild_skb(card, skb, hdr); | 2576 | vlan_tag = qeth_rebuild_skb(card, skb, hdr); |
2585 | else { /*in case of OSN*/ | 2577 | else { /*in case of OSN*/ |
2586 | skb_push(skb, sizeof(struct qeth_hdr)); | 2578 | skb_push(skb, sizeof(struct qeth_hdr)); |
2587 | memcpy(skb->data, hdr, sizeof(struct qeth_hdr)); | 2579 | memcpy(skb->data, hdr, sizeof(struct qeth_hdr)); |
@@ -2591,14 +2583,19 @@ qeth_process_inbound_buffer(struct qeth_card *card, | |||
2591 | dev_kfree_skb_any(skb); | 2583 | dev_kfree_skb_any(skb); |
2592 | continue; | 2584 | continue; |
2593 | } | 2585 | } |
2586 | if (card->info.type == QETH_CARD_TYPE_OSN) | ||
2587 | rxrc = card->osn_info.data_cb(skb); | ||
2588 | else | ||
2594 | #ifdef CONFIG_QETH_VLAN | 2589 | #ifdef CONFIG_QETH_VLAN |
2595 | if (vlan_tag) | 2590 | if (vlan_tag) |
2596 | vlan_hwaccel_rx(skb, card->vlangrp, vlan_tag); | 2591 | if (card->vlangrp) |
2592 | vlan_hwaccel_rx(skb, card->vlangrp, vlan_tag); | ||
2593 | else { | ||
2594 | dev_kfree_skb_any(skb); | ||
2595 | continue; | ||
2596 | } | ||
2597 | else | 2597 | else |
2598 | #endif | 2598 | #endif |
2599 | if (card->info.type == QETH_CARD_TYPE_OSN) | ||
2600 | rxrc = card->osn_info.data_cb(skb); | ||
2601 | else | ||
2602 | rxrc = netif_rx(skb); | 2599 | rxrc = netif_rx(skb); |
2603 | card->dev->last_rx = jiffies; | 2600 | card->dev->last_rx = jiffies; |
2604 | card->stats.rx_packets++; | 2601 | card->stats.rx_packets++; |
@@ -2626,7 +2623,7 @@ qeth_init_input_buffer(struct qeth_card *card, struct qeth_qdio_buffer *buf) | |||
2626 | { | 2623 | { |
2627 | struct qeth_buffer_pool_entry *pool_entry; | 2624 | struct qeth_buffer_pool_entry *pool_entry; |
2628 | int i; | 2625 | int i; |
2629 | 2626 | ||
2630 | pool_entry = qeth_get_buffer_pool_entry(card); | 2627 | pool_entry = qeth_get_buffer_pool_entry(card); |
2631 | /* | 2628 | /* |
2632 | * since the buffer is accessed only from the input_tasklet | 2629 | * since the buffer is accessed only from the input_tasklet |
@@ -2700,17 +2697,18 @@ qeth_queue_input_buffer(struct qeth_card *card, int index) | |||
2700 | * 'index') un-requeued -> this buffer is the first buffer that | 2697 | * 'index') un-requeued -> this buffer is the first buffer that |
2701 | * will be requeued the next time | 2698 | * will be requeued the next time |
2702 | */ | 2699 | */ |
2703 | #ifdef CONFIG_QETH_PERF_STATS | 2700 | if (card->options.performance_stats) { |
2704 | card->perf_stats.inbound_do_qdio_cnt++; | 2701 | card->perf_stats.inbound_do_qdio_cnt++; |
2705 | card->perf_stats.inbound_do_qdio_start_time = qeth_get_micros(); | 2702 | card->perf_stats.inbound_do_qdio_start_time = |
2706 | #endif | 2703 | qeth_get_micros(); |
2704 | } | ||
2707 | rc = do_QDIO(CARD_DDEV(card), | 2705 | rc = do_QDIO(CARD_DDEV(card), |
2708 | QDIO_FLAG_SYNC_INPUT | QDIO_FLAG_UNDER_INTERRUPT, | 2706 | QDIO_FLAG_SYNC_INPUT | QDIO_FLAG_UNDER_INTERRUPT, |
2709 | 0, queue->next_buf_to_init, count, NULL); | 2707 | 0, queue->next_buf_to_init, count, NULL); |
2710 | #ifdef CONFIG_QETH_PERF_STATS | 2708 | if (card->options.performance_stats) |
2711 | card->perf_stats.inbound_do_qdio_time += qeth_get_micros() - | 2709 | card->perf_stats.inbound_do_qdio_time += |
2712 | card->perf_stats.inbound_do_qdio_start_time; | 2710 | qeth_get_micros() - |
2713 | #endif | 2711 | card->perf_stats.inbound_do_qdio_start_time; |
2714 | if (rc){ | 2712 | if (rc){ |
2715 | PRINT_WARN("qeth_queue_input_buffer's do_QDIO " | 2713 | PRINT_WARN("qeth_queue_input_buffer's do_QDIO " |
2716 | "return %i (device %s).\n", | 2714 | "return %i (device %s).\n", |
@@ -2746,10 +2744,10 @@ qeth_qdio_input_handler(struct ccw_device * ccwdev, unsigned int status, | |||
2746 | QETH_DBF_TEXT(trace, 6, "qdinput"); | 2744 | QETH_DBF_TEXT(trace, 6, "qdinput"); |
2747 | card = (struct qeth_card *) card_ptr; | 2745 | card = (struct qeth_card *) card_ptr; |
2748 | net_dev = card->dev; | 2746 | net_dev = card->dev; |
2749 | #ifdef CONFIG_QETH_PERF_STATS | 2747 | if (card->options.performance_stats) { |
2750 | card->perf_stats.inbound_cnt++; | 2748 | card->perf_stats.inbound_cnt++; |
2751 | card->perf_stats.inbound_start_time = qeth_get_micros(); | 2749 | card->perf_stats.inbound_start_time = qeth_get_micros(); |
2752 | #endif | 2750 | } |
2753 | if (status & QDIO_STATUS_LOOK_FOR_ERROR) { | 2751 | if (status & QDIO_STATUS_LOOK_FOR_ERROR) { |
2754 | if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION){ | 2752 | if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION){ |
2755 | QETH_DBF_TEXT(trace, 1,"qdinchk"); | 2753 | QETH_DBF_TEXT(trace, 1,"qdinchk"); |
@@ -2771,10 +2769,9 @@ qeth_qdio_input_handler(struct ccw_device * ccwdev, unsigned int status, | |||
2771 | qeth_put_buffer_pool_entry(card, buffer->pool_entry); | 2769 | qeth_put_buffer_pool_entry(card, buffer->pool_entry); |
2772 | qeth_queue_input_buffer(card, index); | 2770 | qeth_queue_input_buffer(card, index); |
2773 | } | 2771 | } |
2774 | #ifdef CONFIG_QETH_PERF_STATS | 2772 | if (card->options.performance_stats) |
2775 | card->perf_stats.inbound_time += qeth_get_micros() - | 2773 | card->perf_stats.inbound_time += qeth_get_micros() - |
2776 | card->perf_stats.inbound_start_time; | 2774 | card->perf_stats.inbound_start_time; |
2777 | #endif | ||
2778 | } | 2775 | } |
2779 | 2776 | ||
2780 | static inline int | 2777 | static inline int |
@@ -2864,10 +2861,11 @@ qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int, | |||
2864 | } | 2861 | } |
2865 | 2862 | ||
2866 | queue->card->dev->trans_start = jiffies; | 2863 | queue->card->dev->trans_start = jiffies; |
2867 | #ifdef CONFIG_QETH_PERF_STATS | 2864 | if (queue->card->options.performance_stats) { |
2868 | queue->card->perf_stats.outbound_do_qdio_cnt++; | 2865 | queue->card->perf_stats.outbound_do_qdio_cnt++; |
2869 | queue->card->perf_stats.outbound_do_qdio_start_time = qeth_get_micros(); | 2866 | queue->card->perf_stats.outbound_do_qdio_start_time = |
2870 | #endif | 2867 | qeth_get_micros(); |
2868 | } | ||
2871 | if (under_int) | 2869 | if (under_int) |
2872 | rc = do_QDIO(CARD_DDEV(queue->card), | 2870 | rc = do_QDIO(CARD_DDEV(queue->card), |
2873 | QDIO_FLAG_SYNC_OUTPUT | QDIO_FLAG_UNDER_INTERRUPT, | 2871 | QDIO_FLAG_SYNC_OUTPUT | QDIO_FLAG_UNDER_INTERRUPT, |
@@ -2875,10 +2873,10 @@ qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int, | |||
2875 | else | 2873 | else |
2876 | rc = do_QDIO(CARD_DDEV(queue->card), QDIO_FLAG_SYNC_OUTPUT, | 2874 | rc = do_QDIO(CARD_DDEV(queue->card), QDIO_FLAG_SYNC_OUTPUT, |
2877 | queue->queue_no, index, count, NULL); | 2875 | queue->queue_no, index, count, NULL); |
2878 | #ifdef CONFIG_QETH_PERF_STATS | 2876 | if (queue->card->options.performance_stats) |
2879 | queue->card->perf_stats.outbound_do_qdio_time += qeth_get_micros() - | 2877 | queue->card->perf_stats.outbound_do_qdio_time += |
2880 | queue->card->perf_stats.outbound_do_qdio_start_time; | 2878 | qeth_get_micros() - |
2881 | #endif | 2879 | queue->card->perf_stats.outbound_do_qdio_start_time; |
2882 | if (rc){ | 2880 | if (rc){ |
2883 | QETH_DBF_TEXT(trace, 2, "flushbuf"); | 2881 | QETH_DBF_TEXT(trace, 2, "flushbuf"); |
2884 | QETH_DBF_TEXT_(trace, 2, " err%d", rc); | 2882 | QETH_DBF_TEXT_(trace, 2, " err%d", rc); |
@@ -2890,9 +2888,8 @@ qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int, | |||
2890 | return; | 2888 | return; |
2891 | } | 2889 | } |
2892 | atomic_add(count, &queue->used_buffers); | 2890 | atomic_add(count, &queue->used_buffers); |
2893 | #ifdef CONFIG_QETH_PERF_STATS | 2891 | if (queue->card->options.performance_stats) |
2894 | queue->card->perf_stats.bufs_sent += count; | 2892 | queue->card->perf_stats.bufs_sent += count; |
2895 | #endif | ||
2896 | } | 2893 | } |
2897 | 2894 | ||
2898 | /* | 2895 | /* |
@@ -2907,9 +2904,8 @@ qeth_switch_to_packing_if_needed(struct qeth_qdio_out_q *queue) | |||
2907 | >= QETH_HIGH_WATERMARK_PACK){ | 2904 | >= QETH_HIGH_WATERMARK_PACK){ |
2908 | /* switch non-PACKING -> PACKING */ | 2905 | /* switch non-PACKING -> PACKING */ |
2909 | QETH_DBF_TEXT(trace, 6, "np->pack"); | 2906 | QETH_DBF_TEXT(trace, 6, "np->pack"); |
2910 | #ifdef CONFIG_QETH_PERF_STATS | 2907 | if (queue->card->options.performance_stats) |
2911 | queue->card->perf_stats.sc_dp_p++; | 2908 | queue->card->perf_stats.sc_dp_p++; |
2912 | #endif | ||
2913 | queue->do_pack = 1; | 2909 | queue->do_pack = 1; |
2914 | } | 2910 | } |
2915 | } | 2911 | } |
@@ -2932,9 +2928,8 @@ qeth_switch_to_nonpacking_if_needed(struct qeth_qdio_out_q *queue) | |||
2932 | <= QETH_LOW_WATERMARK_PACK) { | 2928 | <= QETH_LOW_WATERMARK_PACK) { |
2933 | /* switch PACKING -> non-PACKING */ | 2929 | /* switch PACKING -> non-PACKING */ |
2934 | QETH_DBF_TEXT(trace, 6, "pack->np"); | 2930 | QETH_DBF_TEXT(trace, 6, "pack->np"); |
2935 | #ifdef CONFIG_QETH_PERF_STATS | 2931 | if (queue->card->options.performance_stats) |
2936 | queue->card->perf_stats.sc_p_dp++; | 2932 | queue->card->perf_stats.sc_p_dp++; |
2937 | #endif | ||
2938 | queue->do_pack = 0; | 2933 | queue->do_pack = 0; |
2939 | /* flush packing buffers */ | 2934 | /* flush packing buffers */ |
2940 | buffer = &queue->bufs[queue->next_buf_to_fill]; | 2935 | buffer = &queue->bufs[queue->next_buf_to_fill]; |
@@ -2946,7 +2941,7 @@ qeth_switch_to_nonpacking_if_needed(struct qeth_qdio_out_q *queue) | |||
2946 | queue->next_buf_to_fill = | 2941 | queue->next_buf_to_fill = |
2947 | (queue->next_buf_to_fill + 1) % | 2942 | (queue->next_buf_to_fill + 1) % |
2948 | QDIO_MAX_BUFFERS_PER_Q; | 2943 | QDIO_MAX_BUFFERS_PER_Q; |
2949 | } | 2944 | } |
2950 | } | 2945 | } |
2951 | } | 2946 | } |
2952 | return flush_count; | 2947 | return flush_count; |
@@ -3002,11 +2997,10 @@ qeth_check_outbound_queue(struct qeth_qdio_out_q *queue) | |||
3002 | !atomic_read(&queue->set_pci_flags_count)) | 2997 | !atomic_read(&queue->set_pci_flags_count)) |
3003 | flush_cnt += | 2998 | flush_cnt += |
3004 | qeth_flush_buffers_on_no_pci(queue); | 2999 | qeth_flush_buffers_on_no_pci(queue); |
3005 | #ifdef CONFIG_QETH_PERF_STATS | 3000 | if (queue->card->options.performance_stats && |
3006 | if (q_was_packing) | 3001 | q_was_packing) |
3007 | queue->card->perf_stats.bufs_sent_pack += | 3002 | queue->card->perf_stats.bufs_sent_pack += |
3008 | flush_cnt; | 3003 | flush_cnt; |
3009 | #endif | ||
3010 | if (flush_cnt) | 3004 | if (flush_cnt) |
3011 | qeth_flush_buffers(queue, 1, index, flush_cnt); | 3005 | qeth_flush_buffers(queue, 1, index, flush_cnt); |
3012 | atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); | 3006 | atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); |
@@ -3036,10 +3030,11 @@ qeth_qdio_output_handler(struct ccw_device * ccwdev, unsigned int status, | |||
3036 | return; | 3030 | return; |
3037 | } | 3031 | } |
3038 | } | 3032 | } |
3039 | #ifdef CONFIG_QETH_PERF_STATS | 3033 | if (card->options.performance_stats) { |
3040 | card->perf_stats.outbound_handler_cnt++; | 3034 | card->perf_stats.outbound_handler_cnt++; |
3041 | card->perf_stats.outbound_handler_start_time = qeth_get_micros(); | 3035 | card->perf_stats.outbound_handler_start_time = |
3042 | #endif | 3036 | qeth_get_micros(); |
3037 | } | ||
3043 | for(i = first_element; i < (first_element + count); ++i){ | 3038 | for(i = first_element; i < (first_element + count); ++i){ |
3044 | buffer = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q]; | 3039 | buffer = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q]; |
3045 | /*we only handle the KICK_IT error by doing a recovery */ | 3040 | /*we only handle the KICK_IT error by doing a recovery */ |
@@ -3058,10 +3053,9 @@ qeth_qdio_output_handler(struct ccw_device * ccwdev, unsigned int status, | |||
3058 | qeth_check_outbound_queue(queue); | 3053 | qeth_check_outbound_queue(queue); |
3059 | 3054 | ||
3060 | netif_wake_queue(queue->card->dev); | 3055 | netif_wake_queue(queue->card->dev); |
3061 | #ifdef CONFIG_QETH_PERF_STATS | 3056 | if (card->options.performance_stats) |
3062 | card->perf_stats.outbound_handler_time += qeth_get_micros() - | 3057 | card->perf_stats.outbound_handler_time += qeth_get_micros() - |
3063 | card->perf_stats.outbound_handler_start_time; | 3058 | card->perf_stats.outbound_handler_start_time; |
3064 | #endif | ||
3065 | } | 3059 | } |
3066 | 3060 | ||
3067 | static void | 3061 | static void |
@@ -3185,13 +3179,14 @@ qeth_alloc_qdio_buffers(struct qeth_card *card) | |||
3185 | 3179 | ||
3186 | QETH_DBF_TEXT(setup, 2, "allcqdbf"); | 3180 | QETH_DBF_TEXT(setup, 2, "allcqdbf"); |
3187 | 3181 | ||
3188 | if (card->qdio.state == QETH_QDIO_ALLOCATED) | 3182 | if (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_UNINITIALIZED, |
3183 | QETH_QDIO_ALLOCATED) != QETH_QDIO_UNINITIALIZED) | ||
3189 | return 0; | 3184 | return 0; |
3190 | 3185 | ||
3191 | card->qdio.in_q = kmalloc(sizeof(struct qeth_qdio_q), | 3186 | card->qdio.in_q = kmalloc(sizeof(struct qeth_qdio_q), |
3192 | GFP_KERNEL|GFP_DMA); | 3187 | GFP_KERNEL|GFP_DMA); |
3193 | if (!card->qdio.in_q) | 3188 | if (!card->qdio.in_q) |
3194 | return - ENOMEM; | 3189 | goto out_nomem; |
3195 | QETH_DBF_TEXT(setup, 2, "inq"); | 3190 | QETH_DBF_TEXT(setup, 2, "inq"); |
3196 | QETH_DBF_HEX(setup, 2, &card->qdio.in_q, sizeof(void *)); | 3191 | QETH_DBF_HEX(setup, 2, &card->qdio.in_q, sizeof(void *)); |
3197 | memset(card->qdio.in_q, 0, sizeof(struct qeth_qdio_q)); | 3192 | memset(card->qdio.in_q, 0, sizeof(struct qeth_qdio_q)); |
@@ -3200,27 +3195,19 @@ qeth_alloc_qdio_buffers(struct qeth_card *card) | |||
3200 | card->qdio.in_q->bufs[i].buffer = | 3195 | card->qdio.in_q->bufs[i].buffer = |
3201 | &card->qdio.in_q->qdio_bufs[i]; | 3196 | &card->qdio.in_q->qdio_bufs[i]; |
3202 | /* inbound buffer pool */ | 3197 | /* inbound buffer pool */ |
3203 | if (qeth_alloc_buffer_pool(card)){ | 3198 | if (qeth_alloc_buffer_pool(card)) |
3204 | kfree(card->qdio.in_q); | 3199 | goto out_freeinq; |
3205 | return -ENOMEM; | ||
3206 | } | ||
3207 | /* outbound */ | 3200 | /* outbound */ |
3208 | card->qdio.out_qs = | 3201 | card->qdio.out_qs = |
3209 | kmalloc(card->qdio.no_out_queues * | 3202 | kmalloc(card->qdio.no_out_queues * |
3210 | sizeof(struct qeth_qdio_out_q *), GFP_KERNEL); | 3203 | sizeof(struct qeth_qdio_out_q *), GFP_KERNEL); |
3211 | if (!card->qdio.out_qs){ | 3204 | if (!card->qdio.out_qs) |
3212 | qeth_free_buffer_pool(card); | 3205 | goto out_freepool; |
3213 | return -ENOMEM; | 3206 | for (i = 0; i < card->qdio.no_out_queues; ++i) { |
3214 | } | ||
3215 | for (i = 0; i < card->qdio.no_out_queues; ++i){ | ||
3216 | card->qdio.out_qs[i] = kmalloc(sizeof(struct qeth_qdio_out_q), | 3207 | card->qdio.out_qs[i] = kmalloc(sizeof(struct qeth_qdio_out_q), |
3217 | GFP_KERNEL|GFP_DMA); | 3208 | GFP_KERNEL|GFP_DMA); |
3218 | if (!card->qdio.out_qs[i]){ | 3209 | if (!card->qdio.out_qs[i]) |
3219 | while (i > 0) | 3210 | goto out_freeoutq; |
3220 | kfree(card->qdio.out_qs[--i]); | ||
3221 | kfree(card->qdio.out_qs); | ||
3222 | return -ENOMEM; | ||
3223 | } | ||
3224 | QETH_DBF_TEXT_(setup, 2, "outq %i", i); | 3211 | QETH_DBF_TEXT_(setup, 2, "outq %i", i); |
3225 | QETH_DBF_HEX(setup, 2, &card->qdio.out_qs[i], sizeof(void *)); | 3212 | QETH_DBF_HEX(setup, 2, &card->qdio.out_qs[i], sizeof(void *)); |
3226 | memset(card->qdio.out_qs[i], 0, sizeof(struct qeth_qdio_out_q)); | 3213 | memset(card->qdio.out_qs[i], 0, sizeof(struct qeth_qdio_out_q)); |
@@ -3237,8 +3224,19 @@ qeth_alloc_qdio_buffers(struct qeth_card *card) | |||
3237 | INIT_LIST_HEAD(&card->qdio.out_qs[i]->bufs[j].ctx_list); | 3224 | INIT_LIST_HEAD(&card->qdio.out_qs[i]->bufs[j].ctx_list); |
3238 | } | 3225 | } |
3239 | } | 3226 | } |
3240 | card->qdio.state = QETH_QDIO_ALLOCATED; | ||
3241 | return 0; | 3227 | return 0; |
3228 | |||
3229 | out_freeoutq: | ||
3230 | while (i > 0) | ||
3231 | kfree(card->qdio.out_qs[--i]); | ||
3232 | kfree(card->qdio.out_qs); | ||
3233 | out_freepool: | ||
3234 | qeth_free_buffer_pool(card); | ||
3235 | out_freeinq: | ||
3236 | kfree(card->qdio.in_q); | ||
3237 | out_nomem: | ||
3238 | atomic_set(&card->qdio.state, QETH_QDIO_UNINITIALIZED); | ||
3239 | return -ENOMEM; | ||
3242 | } | 3240 | } |
3243 | 3241 | ||
3244 | static void | 3242 | static void |
@@ -3247,7 +3245,8 @@ qeth_free_qdio_buffers(struct qeth_card *card) | |||
3247 | int i, j; | 3245 | int i, j; |
3248 | 3246 | ||
3249 | QETH_DBF_TEXT(trace, 2, "freeqdbf"); | 3247 | QETH_DBF_TEXT(trace, 2, "freeqdbf"); |
3250 | if (card->qdio.state == QETH_QDIO_UNINITIALIZED) | 3248 | if (atomic_swap(&card->qdio.state, QETH_QDIO_UNINITIALIZED) == |
3249 | QETH_QDIO_UNINITIALIZED) | ||
3251 | return; | 3250 | return; |
3252 | kfree(card->qdio.in_q); | 3251 | kfree(card->qdio.in_q); |
3253 | /* inbound buffer pool */ | 3252 | /* inbound buffer pool */ |
@@ -3260,7 +3259,6 @@ qeth_free_qdio_buffers(struct qeth_card *card) | |||
3260 | kfree(card->qdio.out_qs[i]); | 3259 | kfree(card->qdio.out_qs[i]); |
3261 | } | 3260 | } |
3262 | kfree(card->qdio.out_qs); | 3261 | kfree(card->qdio.out_qs); |
3263 | card->qdio.state = QETH_QDIO_UNINITIALIZED; | ||
3264 | } | 3262 | } |
3265 | 3263 | ||
3266 | static void | 3264 | static void |
@@ -3282,7 +3280,7 @@ static void | |||
3282 | qeth_init_qdio_info(struct qeth_card *card) | 3280 | qeth_init_qdio_info(struct qeth_card *card) |
3283 | { | 3281 | { |
3284 | QETH_DBF_TEXT(setup, 4, "intqdinf"); | 3282 | QETH_DBF_TEXT(setup, 4, "intqdinf"); |
3285 | card->qdio.state = QETH_QDIO_UNINITIALIZED; | 3283 | atomic_set(&card->qdio.state, QETH_QDIO_UNINITIALIZED); |
3286 | /* inbound */ | 3284 | /* inbound */ |
3287 | card->qdio.in_buf_size = QETH_IN_BUF_SIZE_DEFAULT; | 3285 | card->qdio.in_buf_size = QETH_IN_BUF_SIZE_DEFAULT; |
3288 | card->qdio.init_pool.buf_count = QETH_IN_BUF_COUNT_DEFAULT; | 3286 | card->qdio.init_pool.buf_count = QETH_IN_BUF_COUNT_DEFAULT; |
@@ -3345,7 +3343,7 @@ qeth_qdio_establish(struct qeth_card *card) | |||
3345 | struct qdio_buffer **in_sbal_ptrs; | 3343 | struct qdio_buffer **in_sbal_ptrs; |
3346 | struct qdio_buffer **out_sbal_ptrs; | 3344 | struct qdio_buffer **out_sbal_ptrs; |
3347 | int i, j, k; | 3345 | int i, j, k; |
3348 | int rc; | 3346 | int rc = 0; |
3349 | 3347 | ||
3350 | QETH_DBF_TEXT(setup, 2, "qdioest"); | 3348 | QETH_DBF_TEXT(setup, 2, "qdioest"); |
3351 | 3349 | ||
@@ -3404,8 +3402,10 @@ qeth_qdio_establish(struct qeth_card *card) | |||
3404 | init_data.input_sbal_addr_array = (void **) in_sbal_ptrs; | 3402 | init_data.input_sbal_addr_array = (void **) in_sbal_ptrs; |
3405 | init_data.output_sbal_addr_array = (void **) out_sbal_ptrs; | 3403 | init_data.output_sbal_addr_array = (void **) out_sbal_ptrs; |
3406 | 3404 | ||
3407 | if (!(rc = qdio_initialize(&init_data))) | 3405 | if (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_ALLOCATED, |
3408 | card->qdio.state = QETH_QDIO_ESTABLISHED; | 3406 | QETH_QDIO_ESTABLISHED) == QETH_QDIO_ALLOCATED) |
3407 | if ((rc = qdio_initialize(&init_data))) | ||
3408 | atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED); | ||
3409 | 3409 | ||
3410 | kfree(out_sbal_ptrs); | 3410 | kfree(out_sbal_ptrs); |
3411 | kfree(in_sbal_ptrs); | 3411 | kfree(in_sbal_ptrs); |
@@ -3521,13 +3521,20 @@ qeth_qdio_clear_card(struct qeth_card *card, int use_halt) | |||
3521 | int rc = 0; | 3521 | int rc = 0; |
3522 | 3522 | ||
3523 | QETH_DBF_TEXT(trace,3,"qdioclr"); | 3523 | QETH_DBF_TEXT(trace,3,"qdioclr"); |
3524 | if (card->qdio.state == QETH_QDIO_ESTABLISHED){ | 3524 | switch (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_ESTABLISHED, |
3525 | QETH_QDIO_CLEANING)) { | ||
3526 | case QETH_QDIO_ESTABLISHED: | ||
3525 | if ((rc = qdio_cleanup(CARD_DDEV(card), | 3527 | if ((rc = qdio_cleanup(CARD_DDEV(card), |
3526 | (card->info.type == QETH_CARD_TYPE_IQD) ? | 3528 | (card->info.type == QETH_CARD_TYPE_IQD) ? |
3527 | QDIO_FLAG_CLEANUP_USING_HALT : | 3529 | QDIO_FLAG_CLEANUP_USING_HALT : |
3528 | QDIO_FLAG_CLEANUP_USING_CLEAR))) | 3530 | QDIO_FLAG_CLEANUP_USING_CLEAR))) |
3529 | QETH_DBF_TEXT_(trace, 3, "1err%d", rc); | 3531 | QETH_DBF_TEXT_(trace, 3, "1err%d", rc); |
3530 | card->qdio.state = QETH_QDIO_ALLOCATED; | 3532 | atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED); |
3533 | break; | ||
3534 | case QETH_QDIO_CLEANING: | ||
3535 | return rc; | ||
3536 | default: | ||
3537 | break; | ||
3531 | } | 3538 | } |
3532 | if ((rc = qeth_clear_halt_card(card, use_halt))) | 3539 | if ((rc = qeth_clear_halt_card(card, use_halt))) |
3533 | QETH_DBF_TEXT_(trace, 3, "2err%d", rc); | 3540 | QETH_DBF_TEXT_(trace, 3, "2err%d", rc); |
@@ -3687,10 +3694,10 @@ qeth_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
3687 | /* return OK; otherwise ksoftirqd goes to 100% */ | 3694 | /* return OK; otherwise ksoftirqd goes to 100% */ |
3688 | return NETDEV_TX_OK; | 3695 | return NETDEV_TX_OK; |
3689 | } | 3696 | } |
3690 | #ifdef CONFIG_QETH_PERF_STATS | 3697 | if (card->options.performance_stats) { |
3691 | card->perf_stats.outbound_cnt++; | 3698 | card->perf_stats.outbound_cnt++; |
3692 | card->perf_stats.outbound_start_time = qeth_get_micros(); | 3699 | card->perf_stats.outbound_start_time = qeth_get_micros(); |
3693 | #endif | 3700 | } |
3694 | netif_stop_queue(dev); | 3701 | netif_stop_queue(dev); |
3695 | if ((rc = qeth_send_packet(card, skb))) { | 3702 | if ((rc = qeth_send_packet(card, skb))) { |
3696 | if (rc == -EBUSY) { | 3703 | if (rc == -EBUSY) { |
@@ -3704,10 +3711,9 @@ qeth_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
3704 | } | 3711 | } |
3705 | } | 3712 | } |
3706 | netif_wake_queue(dev); | 3713 | netif_wake_queue(dev); |
3707 | #ifdef CONFIG_QETH_PERF_STATS | 3714 | if (card->options.performance_stats) |
3708 | card->perf_stats.outbound_time += qeth_get_micros() - | 3715 | card->perf_stats.outbound_time += qeth_get_micros() - |
3709 | card->perf_stats.outbound_start_time; | 3716 | card->perf_stats.outbound_start_time; |
3710 | #endif | ||
3711 | return rc; | 3717 | return rc; |
3712 | } | 3718 | } |
3713 | 3719 | ||
@@ -3922,49 +3928,59 @@ qeth_get_ip_version(struct sk_buff *skb) | |||
3922 | } | 3928 | } |
3923 | } | 3929 | } |
3924 | 3930 | ||
3925 | static inline int | 3931 | static inline struct qeth_hdr * |
3926 | qeth_prepare_skb(struct qeth_card *card, struct sk_buff **skb, | 3932 | __qeth_prepare_skb(struct qeth_card *card, struct sk_buff *skb, int ipv) |
3927 | struct qeth_hdr **hdr, int ipv) | ||
3928 | { | 3933 | { |
3929 | int rc = 0; | ||
3930 | #ifdef CONFIG_QETH_VLAN | 3934 | #ifdef CONFIG_QETH_VLAN |
3931 | u16 *tag; | 3935 | u16 *tag; |
3932 | #endif | 3936 | if (card->vlangrp && vlan_tx_tag_present(skb) && |
3933 | |||
3934 | QETH_DBF_TEXT(trace, 6, "prepskb"); | ||
3935 | if (card->info.type == QETH_CARD_TYPE_OSN) { | ||
3936 | *hdr = (struct qeth_hdr *)(*skb)->data; | ||
3937 | return rc; | ||
3938 | } | ||
3939 | rc = qeth_realloc_headroom(card, skb, sizeof(struct qeth_hdr)); | ||
3940 | if (rc) | ||
3941 | return rc; | ||
3942 | #ifdef CONFIG_QETH_VLAN | ||
3943 | if (card->vlangrp && vlan_tx_tag_present(*skb) && | ||
3944 | ((ipv == 6) || card->options.layer2) ) { | 3937 | ((ipv == 6) || card->options.layer2) ) { |
3945 | /* | 3938 | /* |
3946 | * Move the mac addresses (6 bytes src, 6 bytes dest) | 3939 | * Move the mac addresses (6 bytes src, 6 bytes dest) |
3947 | * to the beginning of the new header. We are using three | 3940 | * to the beginning of the new header. We are using three |
3948 | * memcpys instead of one memmove to save cycles. | 3941 | * memcpys instead of one memmove to save cycles. |
3949 | */ | 3942 | */ |
3950 | skb_push(*skb, VLAN_HLEN); | 3943 | skb_push(skb, VLAN_HLEN); |
3951 | memcpy((*skb)->data, (*skb)->data + 4, 4); | 3944 | memcpy(skb->data, skb->data + 4, 4); |
3952 | memcpy((*skb)->data + 4, (*skb)->data + 8, 4); | 3945 | memcpy(skb->data + 4, skb->data + 8, 4); |
3953 | memcpy((*skb)->data + 8, (*skb)->data + 12, 4); | 3946 | memcpy(skb->data + 8, skb->data + 12, 4); |
3954 | tag = (u16 *)((*skb)->data + 12); | 3947 | tag = (u16 *)(skb->data + 12); |
3955 | /* | 3948 | /* |
3956 | * first two bytes = ETH_P_8021Q (0x8100) | 3949 | * first two bytes = ETH_P_8021Q (0x8100) |
3957 | * second two bytes = VLANID | 3950 | * second two bytes = VLANID |
3958 | */ | 3951 | */ |
3959 | *tag = __constant_htons(ETH_P_8021Q); | 3952 | *tag = __constant_htons(ETH_P_8021Q); |
3960 | *(tag + 1) = htons(vlan_tx_tag_get(*skb)); | 3953 | *(tag + 1) = htons(vlan_tx_tag_get(skb)); |
3961 | } | 3954 | } |
3962 | #endif | 3955 | #endif |
3963 | *hdr = (struct qeth_hdr *) | 3956 | return ((struct qeth_hdr *) |
3964 | qeth_push_skb(card, skb, sizeof(struct qeth_hdr)); | 3957 | qeth_push_skb(card, skb, sizeof(struct qeth_hdr))); |
3965 | if (*hdr == NULL) | 3958 | } |
3966 | return -EINVAL; | 3959 | |
3967 | return 0; | 3960 | static inline void |
3961 | __qeth_free_new_skb(struct sk_buff *orig_skb, struct sk_buff *new_skb) | ||
3962 | { | ||
3963 | if (orig_skb != new_skb) | ||
3964 | dev_kfree_skb_any(new_skb); | ||
3965 | } | ||
3966 | |||
3967 | static inline struct sk_buff * | ||
3968 | qeth_prepare_skb(struct qeth_card *card, struct sk_buff *skb, | ||
3969 | struct qeth_hdr **hdr, int ipv) | ||
3970 | { | ||
3971 | struct sk_buff *new_skb; | ||
3972 | |||
3973 | QETH_DBF_TEXT(trace, 6, "prepskb"); | ||
3974 | |||
3975 | new_skb = qeth_realloc_headroom(card, skb, sizeof(struct qeth_hdr)); | ||
3976 | if (new_skb == NULL) | ||
3977 | return NULL; | ||
3978 | *hdr = __qeth_prepare_skb(card, new_skb, ipv); | ||
3979 | if (*hdr == NULL) { | ||
3980 | __qeth_free_new_skb(skb, new_skb); | ||
3981 | return NULL; | ||
3982 | } | ||
3983 | return new_skb; | ||
3968 | } | 3984 | } |
3969 | 3985 | ||
3970 | static inline u8 | 3986 | static inline u8 |
@@ -4206,9 +4222,8 @@ qeth_fill_buffer(struct qeth_qdio_out_q *queue, | |||
4206 | flush_cnt = 1; | 4222 | flush_cnt = 1; |
4207 | } else { | 4223 | } else { |
4208 | QETH_DBF_TEXT(trace, 6, "fillbfpa"); | 4224 | QETH_DBF_TEXT(trace, 6, "fillbfpa"); |
4209 | #ifdef CONFIG_QETH_PERF_STATS | 4225 | if (queue->card->options.performance_stats) |
4210 | queue->card->perf_stats.skbs_sent_pack++; | 4226 | queue->card->perf_stats.skbs_sent_pack++; |
4211 | #endif | ||
4212 | if (buf->next_element_to_fill >= | 4227 | if (buf->next_element_to_fill >= |
4213 | QETH_MAX_BUFFER_ELEMENTS(queue->card)) { | 4228 | QETH_MAX_BUFFER_ELEMENTS(queue->card)) { |
4214 | /* | 4229 | /* |
@@ -4245,21 +4260,15 @@ qeth_do_send_packet_fast(struct qeth_card *card, struct qeth_qdio_out_q *queue, | |||
4245 | * check if buffer is empty to make sure that we do not 'overtake' | 4260 | * check if buffer is empty to make sure that we do not 'overtake' |
4246 | * ourselves and try to fill a buffer that is already primed | 4261 | * ourselves and try to fill a buffer that is already primed |
4247 | */ | 4262 | */ |
4248 | if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY) { | 4263 | if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY) |
4249 | card->stats.tx_dropped++; | 4264 | goto out; |
4250 | atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); | ||
4251 | return -EBUSY; | ||
4252 | } | ||
4253 | if (ctx == NULL) | 4265 | if (ctx == NULL) |
4254 | queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) % | 4266 | queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) % |
4255 | QDIO_MAX_BUFFERS_PER_Q; | 4267 | QDIO_MAX_BUFFERS_PER_Q; |
4256 | else { | 4268 | else { |
4257 | buffers_needed = qeth_eddp_check_buffers_for_context(queue,ctx); | 4269 | buffers_needed = qeth_eddp_check_buffers_for_context(queue,ctx); |
4258 | if (buffers_needed < 0) { | 4270 | if (buffers_needed < 0) |
4259 | card->stats.tx_dropped++; | 4271 | goto out; |
4260 | atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); | ||
4261 | return -EBUSY; | ||
4262 | } | ||
4263 | queue->next_buf_to_fill = | 4272 | queue->next_buf_to_fill = |
4264 | (queue->next_buf_to_fill + buffers_needed) % | 4273 | (queue->next_buf_to_fill + buffers_needed) % |
4265 | QDIO_MAX_BUFFERS_PER_Q; | 4274 | QDIO_MAX_BUFFERS_PER_Q; |
@@ -4274,6 +4283,9 @@ qeth_do_send_packet_fast(struct qeth_card *card, struct qeth_qdio_out_q *queue, | |||
4274 | qeth_flush_buffers(queue, 0, index, flush_cnt); | 4283 | qeth_flush_buffers(queue, 0, index, flush_cnt); |
4275 | } | 4284 | } |
4276 | return 0; | 4285 | return 0; |
4286 | out: | ||
4287 | atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); | ||
4288 | return -EBUSY; | ||
4277 | } | 4289 | } |
4278 | 4290 | ||
4279 | static inline int | 4291 | static inline int |
@@ -4299,8 +4311,7 @@ qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, | |||
4299 | * check if buffer is empty to make sure that we do not 'overtake' | 4311 | * check if buffer is empty to make sure that we do not 'overtake' |
4300 | * ourselves and try to fill a buffer that is already primed | 4312 | * ourselves and try to fill a buffer that is already primed |
4301 | */ | 4313 | */ |
4302 | if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY){ | 4314 | if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY) { |
4303 | card->stats.tx_dropped++; | ||
4304 | atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); | 4315 | atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); |
4305 | return -EBUSY; | 4316 | return -EBUSY; |
4306 | } | 4317 | } |
@@ -4323,7 +4334,6 @@ qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, | |||
4323 | * again */ | 4334 | * again */ |
4324 | if (atomic_read(&buffer->state) != | 4335 | if (atomic_read(&buffer->state) != |
4325 | QETH_QDIO_BUF_EMPTY){ | 4336 | QETH_QDIO_BUF_EMPTY){ |
4326 | card->stats.tx_dropped++; | ||
4327 | qeth_flush_buffers(queue, 0, start_index, flush_count); | 4337 | qeth_flush_buffers(queue, 0, start_index, flush_count); |
4328 | atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); | 4338 | atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); |
4329 | return -EBUSY; | 4339 | return -EBUSY; |
@@ -4334,7 +4344,6 @@ qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, | |||
4334 | * free buffers) to handle eddp context */ | 4344 | * free buffers) to handle eddp context */ |
4335 | if (qeth_eddp_check_buffers_for_context(queue,ctx) < 0){ | 4345 | if (qeth_eddp_check_buffers_for_context(queue,ctx) < 0){ |
4336 | printk("eddp tx_dropped 1\n"); | 4346 | printk("eddp tx_dropped 1\n"); |
4337 | card->stats.tx_dropped++; | ||
4338 | rc = -EBUSY; | 4347 | rc = -EBUSY; |
4339 | goto out; | 4348 | goto out; |
4340 | } | 4349 | } |
@@ -4346,7 +4355,6 @@ qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, | |||
4346 | tmp = qeth_eddp_fill_buffer(queue,ctx,queue->next_buf_to_fill); | 4355 | tmp = qeth_eddp_fill_buffer(queue,ctx,queue->next_buf_to_fill); |
4347 | if (tmp < 0) { | 4356 | if (tmp < 0) { |
4348 | printk("eddp tx_dropped 2\n"); | 4357 | printk("eddp tx_dropped 2\n"); |
4349 | card->stats.tx_dropped++; | ||
4350 | rc = - EBUSY; | 4358 | rc = - EBUSY; |
4351 | goto out; | 4359 | goto out; |
4352 | } | 4360 | } |
@@ -4380,10 +4388,8 @@ out: | |||
4380 | qeth_flush_buffers(queue, 0, start_index, flush_count); | 4388 | qeth_flush_buffers(queue, 0, start_index, flush_count); |
4381 | } | 4389 | } |
4382 | /* at this point the queue is UNLOCKED again */ | 4390 | /* at this point the queue is UNLOCKED again */ |
4383 | #ifdef CONFIG_QETH_PERF_STATS | 4391 | if (queue->card->options.performance_stats && do_pack) |
4384 | if (do_pack) | ||
4385 | queue->card->perf_stats.bufs_sent_pack += flush_count; | 4392 | queue->card->perf_stats.bufs_sent_pack += flush_count; |
4386 | #endif /* CONFIG_QETH_PERF_STATS */ | ||
4387 | 4393 | ||
4388 | return rc; | 4394 | return rc; |
4389 | } | 4395 | } |
@@ -4394,21 +4400,21 @@ qeth_get_elements_no(struct qeth_card *card, void *hdr, | |||
4394 | { | 4400 | { |
4395 | int elements_needed = 0; | 4401 | int elements_needed = 0; |
4396 | 4402 | ||
4397 | if (skb_shinfo(skb)->nr_frags > 0) { | 4403 | if (skb_shinfo(skb)->nr_frags > 0) |
4398 | elements_needed = (skb_shinfo(skb)->nr_frags + 1); | 4404 | elements_needed = (skb_shinfo(skb)->nr_frags + 1); |
4399 | } | 4405 | if (elements_needed == 0) |
4400 | if (elements_needed == 0 ) | ||
4401 | elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE) | 4406 | elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE) |
4402 | + skb->len) >> PAGE_SHIFT); | 4407 | + skb->len) >> PAGE_SHIFT); |
4403 | if ((elements_needed + elems) > QETH_MAX_BUFFER_ELEMENTS(card)){ | 4408 | if ((elements_needed + elems) > QETH_MAX_BUFFER_ELEMENTS(card)){ |
4404 | PRINT_ERR("qeth_do_send_packet: invalid size of " | 4409 | PRINT_ERR("Invalid size of IP packet " |
4405 | "IP packet (Number=%d / Length=%d). Discarded.\n", | 4410 | "(Number=%d / Length=%d). Discarded.\n", |
4406 | (elements_needed+elems), skb->len); | 4411 | (elements_needed+elems), skb->len); |
4407 | return 0; | 4412 | return 0; |
4408 | } | 4413 | } |
4409 | return elements_needed; | 4414 | return elements_needed; |
4410 | } | 4415 | } |
4411 | 4416 | ||
4417 | |||
4412 | static inline int | 4418 | static inline int |
4413 | qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) | 4419 | qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) |
4414 | { | 4420 | { |
@@ -4420,112 +4426,112 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) | |||
4420 | enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO; | 4426 | enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO; |
4421 | struct qeth_eddp_context *ctx = NULL; | 4427 | struct qeth_eddp_context *ctx = NULL; |
4422 | int tx_bytes = skb->len; | 4428 | int tx_bytes = skb->len; |
4423 | #ifdef CONFIG_QETH_PERF_STATS | ||
4424 | unsigned short nr_frags = skb_shinfo(skb)->nr_frags; | 4429 | unsigned short nr_frags = skb_shinfo(skb)->nr_frags; |
4425 | unsigned short tso_size = skb_shinfo(skb)->gso_size; | 4430 | unsigned short tso_size = skb_shinfo(skb)->gso_size; |
4426 | #endif | 4431 | struct sk_buff *new_skb, *new_skb2; |
4427 | int rc; | 4432 | int rc; |
4428 | 4433 | ||
4429 | QETH_DBF_TEXT(trace, 6, "sendpkt"); | 4434 | QETH_DBF_TEXT(trace, 6, "sendpkt"); |
4430 | 4435 | ||
4436 | new_skb = skb; | ||
4437 | if ((card->info.type == QETH_CARD_TYPE_OSN) && | ||
4438 | (skb->protocol == htons(ETH_P_IPV6))) | ||
4439 | return -EPERM; | ||
4440 | cast_type = qeth_get_cast_type(card, skb); | ||
4441 | if ((cast_type == RTN_BROADCAST) && | ||
4442 | (card->info.broadcast_capable == 0)) | ||
4443 | return -EPERM; | ||
4444 | queue = card->qdio.out_qs | ||
4445 | [qeth_get_priority_queue(card, skb, ipv, cast_type)]; | ||
4431 | if (!card->options.layer2) { | 4446 | if (!card->options.layer2) { |
4432 | ipv = qeth_get_ip_version(skb); | 4447 | ipv = qeth_get_ip_version(skb); |
4433 | if ((card->dev->hard_header == qeth_fake_header) && ipv) { | 4448 | if ((card->dev->hard_header == qeth_fake_header) && ipv) { |
4434 | if ((skb = qeth_pskb_unshare(skb,GFP_ATOMIC)) == NULL) { | 4449 | new_skb = qeth_pskb_unshare(skb, GFP_ATOMIC); |
4435 | card->stats.tx_dropped++; | 4450 | if (!new_skb) |
4436 | dev_kfree_skb_irq(skb); | 4451 | return -ENOMEM; |
4437 | return 0; | ||
4438 | } | ||
4439 | if(card->dev->type == ARPHRD_IEEE802_TR){ | 4452 | if(card->dev->type == ARPHRD_IEEE802_TR){ |
4440 | skb_pull(skb, QETH_FAKE_LL_LEN_TR); | 4453 | skb_pull(new_skb, QETH_FAKE_LL_LEN_TR); |
4441 | } else { | 4454 | } else { |
4442 | skb_pull(skb, QETH_FAKE_LL_LEN_ETH); | 4455 | skb_pull(new_skb, QETH_FAKE_LL_LEN_ETH); |
4443 | } | 4456 | } |
4444 | } | 4457 | } |
4445 | } | 4458 | } |
4446 | if ((card->info.type == QETH_CARD_TYPE_OSN) && | ||
4447 | (skb->protocol == htons(ETH_P_IPV6))) { | ||
4448 | dev_kfree_skb_any(skb); | ||
4449 | return 0; | ||
4450 | } | ||
4451 | cast_type = qeth_get_cast_type(card, skb); | ||
4452 | if ((cast_type == RTN_BROADCAST) && | ||
4453 | (card->info.broadcast_capable == 0)){ | ||
4454 | card->stats.tx_dropped++; | ||
4455 | card->stats.tx_errors++; | ||
4456 | dev_kfree_skb_any(skb); | ||
4457 | return NETDEV_TX_OK; | ||
4458 | } | ||
4459 | queue = card->qdio.out_qs | ||
4460 | [qeth_get_priority_queue(card, skb, ipv, cast_type)]; | ||
4461 | |||
4462 | if (skb_is_gso(skb)) | 4459 | if (skb_is_gso(skb)) |
4463 | large_send = card->options.large_send; | 4460 | large_send = card->options.large_send; |
4464 | 4461 | /* check on OSN device*/ | |
4465 | /*are we able to do TSO ? If so ,prepare and send it from here */ | 4462 | if (card->info.type == QETH_CARD_TYPE_OSN) |
4463 | hdr = (struct qeth_hdr *)new_skb->data; | ||
4464 | /*are we able to do TSO ? */ | ||
4466 | if ((large_send == QETH_LARGE_SEND_TSO) && | 4465 | if ((large_send == QETH_LARGE_SEND_TSO) && |
4467 | (cast_type == RTN_UNSPEC)) { | 4466 | (cast_type == RTN_UNSPEC)) { |
4468 | rc = qeth_tso_prepare_packet(card, skb, ipv, cast_type); | 4467 | rc = qeth_tso_prepare_packet(card, new_skb, ipv, cast_type); |
4469 | if (rc) { | 4468 | if (rc) { |
4470 | card->stats.tx_dropped++; | 4469 | __qeth_free_new_skb(skb, new_skb); |
4471 | card->stats.tx_errors++; | 4470 | return rc; |
4472 | dev_kfree_skb_any(skb); | ||
4473 | return NETDEV_TX_OK; | ||
4474 | } | 4471 | } |
4475 | elements_needed++; | 4472 | elements_needed++; |
4476 | } else { | 4473 | } else if (card->info.type != QETH_CARD_TYPE_OSN) { |
4477 | if ((rc = qeth_prepare_skb(card, &skb, &hdr, ipv))) { | 4474 | new_skb2 = qeth_prepare_skb(card, new_skb, &hdr, ipv); |
4478 | QETH_DBF_TEXT_(trace, 4, "pskbe%d", rc); | 4475 | if (!new_skb2) { |
4479 | return rc; | 4476 | __qeth_free_new_skb(skb, new_skb); |
4477 | return -EINVAL; | ||
4480 | } | 4478 | } |
4481 | if (card->info.type != QETH_CARD_TYPE_OSN) | 4479 | if (new_skb != skb) |
4482 | qeth_fill_header(card, hdr, skb, ipv, cast_type); | 4480 | __qeth_free_new_skb(new_skb2, new_skb); |
4481 | new_skb = new_skb2; | ||
4482 | qeth_fill_header(card, hdr, new_skb, ipv, cast_type); | ||
4483 | } | 4483 | } |
4484 | |||
4485 | if (large_send == QETH_LARGE_SEND_EDDP) { | 4484 | if (large_send == QETH_LARGE_SEND_EDDP) { |
4486 | ctx = qeth_eddp_create_context(card, skb, hdr); | 4485 | ctx = qeth_eddp_create_context(card, new_skb, hdr); |
4487 | if (ctx == NULL) { | 4486 | if (ctx == NULL) { |
4487 | __qeth_free_new_skb(skb, new_skb); | ||
4488 | PRINT_WARN("could not create eddp context\n"); | 4488 | PRINT_WARN("could not create eddp context\n"); |
4489 | return -EINVAL; | 4489 | return -EINVAL; |
4490 | } | 4490 | } |
4491 | } else { | 4491 | } else { |
4492 | int elems = qeth_get_elements_no(card,(void*) hdr, skb, | 4492 | int elems = qeth_get_elements_no(card,(void*) hdr, new_skb, |
4493 | elements_needed); | 4493 | elements_needed); |
4494 | if (!elems) | 4494 | if (!elems) { |
4495 | __qeth_free_new_skb(skb, new_skb); | ||
4495 | return -EINVAL; | 4496 | return -EINVAL; |
4497 | } | ||
4496 | elements_needed += elems; | 4498 | elements_needed += elems; |
4497 | } | 4499 | } |
4498 | 4500 | ||
4499 | if (card->info.type != QETH_CARD_TYPE_IQD) | 4501 | if (card->info.type != QETH_CARD_TYPE_IQD) |
4500 | rc = qeth_do_send_packet(card, queue, skb, hdr, | 4502 | rc = qeth_do_send_packet(card, queue, new_skb, hdr, |
4501 | elements_needed, ctx); | 4503 | elements_needed, ctx); |
4502 | else | 4504 | else |
4503 | rc = qeth_do_send_packet_fast(card, queue, skb, hdr, | 4505 | rc = qeth_do_send_packet_fast(card, queue, new_skb, hdr, |
4504 | elements_needed, ctx); | 4506 | elements_needed, ctx); |
4505 | if (!rc){ | 4507 | if (!rc) { |
4506 | card->stats.tx_packets++; | 4508 | card->stats.tx_packets++; |
4507 | card->stats.tx_bytes += tx_bytes; | 4509 | card->stats.tx_bytes += tx_bytes; |
4508 | #ifdef CONFIG_QETH_PERF_STATS | 4510 | if (new_skb != skb) |
4509 | if (tso_size && | 4511 | dev_kfree_skb_any(skb); |
4510 | !(large_send == QETH_LARGE_SEND_NO)) { | 4512 | if (card->options.performance_stats) { |
4511 | card->perf_stats.large_send_bytes += tx_bytes; | 4513 | if (tso_size && |
4512 | card->perf_stats.large_send_cnt++; | 4514 | !(large_send == QETH_LARGE_SEND_NO)) { |
4513 | } | 4515 | card->perf_stats.large_send_bytes += tx_bytes; |
4514 | if (nr_frags > 0){ | 4516 | card->perf_stats.large_send_cnt++; |
4515 | card->perf_stats.sg_skbs_sent++; | 4517 | } |
4516 | /* nr_frags + skb->data */ | 4518 | if (nr_frags > 0) { |
4517 | card->perf_stats.sg_frags_sent += | 4519 | card->perf_stats.sg_skbs_sent++; |
4518 | nr_frags + 1; | 4520 | /* nr_frags + skb->data */ |
4521 | card->perf_stats.sg_frags_sent += | ||
4522 | nr_frags + 1; | ||
4523 | } | ||
4519 | } | 4524 | } |
4520 | #endif /* CONFIG_QETH_PERF_STATS */ | 4525 | } else { |
4526 | card->stats.tx_dropped++; | ||
4527 | __qeth_free_new_skb(skb, new_skb); | ||
4521 | } | 4528 | } |
4522 | if (ctx != NULL) { | 4529 | if (ctx != NULL) { |
4523 | /* drop creator's reference */ | 4530 | /* drop creator's reference */ |
4524 | qeth_eddp_put_context(ctx); | 4531 | qeth_eddp_put_context(ctx); |
4525 | /* free skb; it's not referenced by a buffer */ | 4532 | /* free skb; it's not referenced by a buffer */ |
4526 | if (rc == 0) | 4533 | if (!rc) |
4527 | dev_kfree_skb_any(skb); | 4534 | dev_kfree_skb_any(new_skb); |
4528 | |||
4529 | } | 4535 | } |
4530 | return rc; | 4536 | return rc; |
4531 | } | 4537 | } |
@@ -7338,6 +7344,8 @@ qeth_setrouting_v6(struct qeth_card *card) | |||
7338 | QETH_DBF_TEXT(trace,3,"setrtg6"); | 7344 | QETH_DBF_TEXT(trace,3,"setrtg6"); |
7339 | #ifdef CONFIG_QETH_IPV6 | 7345 | #ifdef CONFIG_QETH_IPV6 |
7340 | 7346 | ||
7347 | if (!qeth_is_supported(card, IPA_IPV6)) | ||
7348 | return 0; | ||
7341 | qeth_correct_routing_type(card, &card->options.route6.type, | 7349 | qeth_correct_routing_type(card, &card->options.route6.type, |
7342 | QETH_PROT_IPV6); | 7350 | QETH_PROT_IPV6); |
7343 | 7351 | ||
@@ -7876,12 +7884,12 @@ __qeth_set_online(struct ccwgroup_device *gdev, int recovery_mode) | |||
7876 | QETH_DBF_TEXT_(setup, 2, "5err%d", rc); | 7884 | QETH_DBF_TEXT_(setup, 2, "5err%d", rc); |
7877 | goto out_remove; | 7885 | goto out_remove; |
7878 | } | 7886 | } |
7879 | card->state = CARD_STATE_SOFTSETUP; | ||
7880 | 7887 | ||
7881 | if ((rc = qeth_init_qdio_queues(card))){ | 7888 | if ((rc = qeth_init_qdio_queues(card))){ |
7882 | QETH_DBF_TEXT_(setup, 2, "6err%d", rc); | 7889 | QETH_DBF_TEXT_(setup, 2, "6err%d", rc); |
7883 | goto out_remove; | 7890 | goto out_remove; |
7884 | } | 7891 | } |
7892 | card->state = CARD_STATE_SOFTSETUP; | ||
7885 | netif_carrier_on(card->dev); | 7893 | netif_carrier_on(card->dev); |
7886 | 7894 | ||
7887 | qeth_set_allowed_threads(card, 0xffffffff, 0); | 7895 | qeth_set_allowed_threads(card, 0xffffffff, 0); |
@@ -8538,34 +8546,44 @@ qeth_ipv6_uninit(void) | |||
8538 | static void | 8546 | static void |
8539 | qeth_sysfs_unregister(void) | 8547 | qeth_sysfs_unregister(void) |
8540 | { | 8548 | { |
8549 | s390_root_dev_unregister(qeth_root_dev); | ||
8541 | qeth_remove_driver_attributes(); | 8550 | qeth_remove_driver_attributes(); |
8542 | ccw_driver_unregister(&qeth_ccw_driver); | 8551 | ccw_driver_unregister(&qeth_ccw_driver); |
8543 | ccwgroup_driver_unregister(&qeth_ccwgroup_driver); | 8552 | ccwgroup_driver_unregister(&qeth_ccwgroup_driver); |
8544 | s390_root_dev_unregister(qeth_root_dev); | ||
8545 | } | 8553 | } |
8554 | |||
8546 | /** | 8555 | /** |
8547 | * register qeth at sysfs | 8556 | * register qeth at sysfs |
8548 | */ | 8557 | */ |
8549 | static int | 8558 | static int |
8550 | qeth_sysfs_register(void) | 8559 | qeth_sysfs_register(void) |
8551 | { | 8560 | { |
8552 | int rc=0; | 8561 | int rc; |
8553 | 8562 | ||
8554 | rc = ccwgroup_driver_register(&qeth_ccwgroup_driver); | 8563 | rc = ccwgroup_driver_register(&qeth_ccwgroup_driver); |
8555 | if (rc) | 8564 | if (rc) |
8556 | return rc; | 8565 | goto out; |
8566 | |||
8557 | rc = ccw_driver_register(&qeth_ccw_driver); | 8567 | rc = ccw_driver_register(&qeth_ccw_driver); |
8558 | if (rc) | 8568 | if (rc) |
8559 | return rc; | 8569 | goto out_ccw_driver; |
8570 | |||
8560 | rc = qeth_create_driver_attributes(); | 8571 | rc = qeth_create_driver_attributes(); |
8561 | if (rc) | 8572 | if (rc) |
8562 | return rc; | 8573 | goto out_qeth_attr; |
8574 | |||
8563 | qeth_root_dev = s390_root_dev_register("qeth"); | 8575 | qeth_root_dev = s390_root_dev_register("qeth"); |
8564 | if (IS_ERR(qeth_root_dev)) { | 8576 | rc = IS_ERR(qeth_root_dev) ? PTR_ERR(qeth_root_dev) : 0; |
8565 | rc = PTR_ERR(qeth_root_dev); | 8577 | if (!rc) |
8566 | return rc; | 8578 | goto out; |
8567 | } | 8579 | |
8568 | return 0; | 8580 | qeth_remove_driver_attributes(); |
8581 | out_qeth_attr: | ||
8582 | ccw_driver_unregister(&qeth_ccw_driver); | ||
8583 | out_ccw_driver: | ||
8584 | ccwgroup_driver_unregister(&qeth_ccwgroup_driver); | ||
8585 | out: | ||
8586 | return rc; | ||
8569 | } | 8587 | } |
8570 | 8588 | ||
8571 | /*** | 8589 | /*** |
@@ -8574,7 +8592,7 @@ qeth_sysfs_register(void) | |||
8574 | static int __init | 8592 | static int __init |
8575 | qeth_init(void) | 8593 | qeth_init(void) |
8576 | { | 8594 | { |
8577 | int rc=0; | 8595 | int rc; |
8578 | 8596 | ||
8579 | PRINT_INFO("loading %s\n", version); | 8597 | PRINT_INFO("loading %s\n", version); |
8580 | 8598 | ||
@@ -8583,20 +8601,26 @@ qeth_init(void) | |||
8583 | spin_lock_init(&qeth_notify_lock); | 8601 | spin_lock_init(&qeth_notify_lock); |
8584 | rwlock_init(&qeth_card_list.rwlock); | 8602 | rwlock_init(&qeth_card_list.rwlock); |
8585 | 8603 | ||
8586 | if (qeth_register_dbf_views()) | 8604 | rc = qeth_register_dbf_views(); |
8605 | if (rc) | ||
8587 | goto out_err; | 8606 | goto out_err; |
8588 | if (qeth_sysfs_register()) | 8607 | |
8589 | goto out_sysfs; | 8608 | rc = qeth_sysfs_register(); |
8609 | if (rc) | ||
8610 | goto out_dbf; | ||
8590 | 8611 | ||
8591 | #ifdef CONFIG_QETH_IPV6 | 8612 | #ifdef CONFIG_QETH_IPV6 |
8592 | if (qeth_ipv6_init()) { | 8613 | rc = qeth_ipv6_init(); |
8593 | PRINT_ERR("Out of memory during ipv6 init.\n"); | 8614 | if (rc) { |
8615 | PRINT_ERR("Out of memory during ipv6 init code = %d\n", rc); | ||
8594 | goto out_sysfs; | 8616 | goto out_sysfs; |
8595 | } | 8617 | } |
8596 | #endif /* QETH_IPV6 */ | 8618 | #endif /* QETH_IPV6 */ |
8597 | if (qeth_register_notifiers()) | 8619 | rc = qeth_register_notifiers(); |
8620 | if (rc) | ||
8598 | goto out_ipv6; | 8621 | goto out_ipv6; |
8599 | if (qeth_create_procfs_entries()) | 8622 | rc = qeth_create_procfs_entries(); |
8623 | if (rc) | ||
8600 | goto out_notifiers; | 8624 | goto out_notifiers; |
8601 | 8625 | ||
8602 | return rc; | 8626 | return rc; |
@@ -8606,12 +8630,13 @@ out_notifiers: | |||
8606 | out_ipv6: | 8630 | out_ipv6: |
8607 | #ifdef CONFIG_QETH_IPV6 | 8631 | #ifdef CONFIG_QETH_IPV6 |
8608 | qeth_ipv6_uninit(); | 8632 | qeth_ipv6_uninit(); |
8609 | #endif /* QETH_IPV6 */ | ||
8610 | out_sysfs: | 8633 | out_sysfs: |
8634 | #endif /* QETH_IPV6 */ | ||
8611 | qeth_sysfs_unregister(); | 8635 | qeth_sysfs_unregister(); |
8636 | out_dbf: | ||
8612 | qeth_unregister_dbf_views(); | 8637 | qeth_unregister_dbf_views(); |
8613 | out_err: | 8638 | out_err: |
8614 | PRINT_ERR("Initialization failed"); | 8639 | PRINT_ERR("Initialization failed with code %d\n", rc); |
8615 | return rc; | 8640 | return rc; |
8616 | } | 8641 | } |
8617 | 8642 | ||