aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/net
diff options
context:
space:
mode:
authorFrank Blaschka <frank.blaschka@de.ibm.com>2010-09-07 17:14:42 -0400
committerDavid S. Miller <davem@davemloft.net>2010-09-08 17:31:02 -0400
commita1c3ed4c9ca01dded8d511a1d1daf271fbae8d89 (patch)
tree1ff0b2887e550f127fe844222b6833b831a4b036 /drivers/s390/net
parent81d53749416995538f830c8e4d3fbaf1769b9375 (diff)
qeth: NAPI support for l2 and l3 discipline
This patch adds NAPI support to the qeth layer 2 and layer 3 discipline. It is important to understand that we can not enable/disable IRQs as usual, we have to use the corresponding new QDIO interface. Also to not overdraw the budget we have to stop and restart buffer processing at any point during processing a bulk of QDIO buffers. Having the driver NAPI enabled it is possible to turn on GRO for the layer 3 discipline. Signed-off-by: Frank Blaschka <frank.blaschka@de.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/s390/net')
-rw-r--r--drivers/s390/net/qeth_core.h17
-rw-r--r--drivers/s390/net/qeth_core_main.c26
-rw-r--r--drivers/s390/net/qeth_l2_main.c173
-rw-r--r--drivers/s390/net/qeth_l3_main.c182
4 files changed, 260 insertions, 138 deletions
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h
index d1257768be90..6be43eb126b4 100644
--- a/drivers/s390/net/qeth_core.h
+++ b/drivers/s390/net/qeth_core.h
@@ -676,6 +676,7 @@ enum qeth_discipline_id {
676}; 676};
677 677
678struct qeth_discipline { 678struct qeth_discipline {
679 void (*start_poll)(struct ccw_device *, int, unsigned long);
679 qdio_handler_t *input_handler; 680 qdio_handler_t *input_handler;
680 qdio_handler_t *output_handler; 681 qdio_handler_t *output_handler;
681 int (*recover)(void *ptr); 682 int (*recover)(void *ptr);
@@ -702,6 +703,16 @@ struct qeth_skb_data {
702#define QETH_SKB_MAGIC 0x71657468 703#define QETH_SKB_MAGIC 0x71657468
703#define QETH_SIGA_CC2_RETRIES 3 704#define QETH_SIGA_CC2_RETRIES 3
704 705
706struct qeth_rx {
707 int b_count;
708 int b_index;
709 struct qdio_buffer_element *b_element;
710 int e_offset;
711 int qdio_err;
712};
713
714#define QETH_NAPI_WEIGHT 128
715
705struct qeth_card { 716struct qeth_card {
706 struct list_head list; 717 struct list_head list;
707 enum qeth_card_states state; 718 enum qeth_card_states state;
@@ -749,6 +760,8 @@ struct qeth_card {
749 debug_info_t *debug; 760 debug_info_t *debug;
750 struct mutex conf_mutex; 761 struct mutex conf_mutex;
751 struct mutex discipline_mutex; 762 struct mutex discipline_mutex;
763 struct napi_struct napi;
764 struct qeth_rx rx;
752}; 765};
753 766
754struct qeth_card_list_struct { 767struct qeth_card_list_struct {
@@ -831,6 +844,10 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *,
831 struct qdio_buffer *, struct qdio_buffer_element **, int *, 844 struct qdio_buffer *, struct qdio_buffer_element **, int *,
832 struct qeth_hdr **); 845 struct qeth_hdr **);
833void qeth_schedule_recovery(struct qeth_card *); 846void qeth_schedule_recovery(struct qeth_card *);
847void qeth_qdio_start_poll(struct ccw_device *, int, unsigned long);
848void qeth_qdio_input_handler(struct ccw_device *,
849 unsigned int, unsigned int, int,
850 int, unsigned long);
834void qeth_qdio_output_handler(struct ccw_device *, unsigned int, 851void qeth_qdio_output_handler(struct ccw_device *, unsigned int,
835 int, int, int, unsigned long); 852 int, int, int, unsigned long);
836void qeth_clear_ipacmd_list(struct qeth_card *); 853void qeth_clear_ipacmd_list(struct qeth_card *);
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 3a5a18a0fc28..764267062601 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -2911,6 +2911,27 @@ static void qeth_check_outbound_queue(struct qeth_qdio_out_q *queue)
2911 } 2911 }
2912} 2912}
2913 2913
2914void qeth_qdio_start_poll(struct ccw_device *ccwdev, int queue,
2915 unsigned long card_ptr)
2916{
2917 struct qeth_card *card = (struct qeth_card *)card_ptr;
2918
2919 if (card->dev)
2920 napi_schedule(&card->napi);
2921}
2922EXPORT_SYMBOL_GPL(qeth_qdio_start_poll);
2923
2924void qeth_qdio_input_handler(struct ccw_device *ccwdev, unsigned int qdio_err,
2925 unsigned int queue, int first_element, int count,
2926 unsigned long card_ptr)
2927{
2928 struct qeth_card *card = (struct qeth_card *)card_ptr;
2929
2930 if (qdio_err)
2931 qeth_schedule_recovery(card);
2932}
2933EXPORT_SYMBOL_GPL(qeth_qdio_input_handler);
2934
2914void qeth_qdio_output_handler(struct ccw_device *ccwdev, 2935void qeth_qdio_output_handler(struct ccw_device *ccwdev,
2915 unsigned int qdio_error, int __queue, int first_element, 2936 unsigned int qdio_error, int __queue, int first_element,
2916 int count, unsigned long card_ptr) 2937 int count, unsigned long card_ptr)
@@ -3843,6 +3864,7 @@ static int qeth_qdio_establish(struct qeth_card *card)
3843 init_data.no_output_qs = card->qdio.no_out_queues; 3864 init_data.no_output_qs = card->qdio.no_out_queues;
3844 init_data.input_handler = card->discipline.input_handler; 3865 init_data.input_handler = card->discipline.input_handler;
3845 init_data.output_handler = card->discipline.output_handler; 3866 init_data.output_handler = card->discipline.output_handler;
3867 init_data.queue_start_poll = card->discipline.start_poll;
3846 init_data.int_parm = (unsigned long) card; 3868 init_data.int_parm = (unsigned long) card;
3847 init_data.input_sbal_addr_array = (void **) in_sbal_ptrs; 3869 init_data.input_sbal_addr_array = (void **) in_sbal_ptrs;
3848 init_data.output_sbal_addr_array = (void **) out_sbal_ptrs; 3870 init_data.output_sbal_addr_array = (void **) out_sbal_ptrs;
@@ -4513,8 +4535,8 @@ static struct {
4513/* 20 */{"queue 1 buffer usage"}, 4535/* 20 */{"queue 1 buffer usage"},
4514 {"queue 2 buffer usage"}, 4536 {"queue 2 buffer usage"},
4515 {"queue 3 buffer usage"}, 4537 {"queue 3 buffer usage"},
4516 {"rx handler time"}, 4538 {"rx poll time"},
4517 {"rx handler count"}, 4539 {"rx poll count"},
4518 {"rx do_QDIO time"}, 4540 {"rx do_QDIO time"},
4519 {"rx do_QDIO count"}, 4541 {"rx do_QDIO count"},
4520 {"tx handler time"}, 4542 {"tx handler time"},
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
index 830d63524d61..01c3c1f77879 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -407,29 +407,25 @@ static int qeth_l2_stop_card(struct qeth_card *card, int recovery_mode)
407 return rc; 407 return rc;
408} 408}
409 409
410static void qeth_l2_process_inbound_buffer(struct qeth_card *card, 410static int qeth_l2_process_inbound_buffer(struct qeth_card *card,
411 struct qeth_qdio_buffer *buf, int index) 411 int budget, int *done)
412{ 412{
413 struct qdio_buffer_element *element; 413 int work_done = 0;
414 struct sk_buff *skb; 414 struct sk_buff *skb;
415 struct qeth_hdr *hdr; 415 struct qeth_hdr *hdr;
416 int offset;
417 unsigned int len; 416 unsigned int len;
418 417
419 /* get first element of current buffer */ 418 *done = 0;
420 element = (struct qdio_buffer_element *)&buf->buffer->element[0]; 419 BUG_ON(!budget);
421 offset = 0; 420 while (budget) {
422 if (card->options.performance_stats) 421 skb = qeth_core_get_next_skb(card,
423 card->perf_stats.bufs_rec++; 422 card->qdio.in_q->bufs[card->rx.b_index].buffer,
424 while ((skb = qeth_core_get_next_skb(card, buf->buffer, &element, 423 &card->rx.b_element, &card->rx.e_offset, &hdr);
425 &offset, &hdr))) { 424 if (!skb) {
426 skb->dev = card->dev; 425 *done = 1;
427 /* is device UP ? */ 426 break;
428 if (!(card->dev->flags & IFF_UP)) {
429 dev_kfree_skb_any(skb);
430 continue;
431 } 427 }
432 428 skb->dev = card->dev;
433 switch (hdr->hdr.l2.id) { 429 switch (hdr->hdr.l2.id) {
434 case QETH_HEADER_TYPE_LAYER2: 430 case QETH_HEADER_TYPE_LAYER2:
435 skb->pkt_type = PACKET_HOST; 431 skb->pkt_type = PACKET_HOST;
@@ -441,7 +437,7 @@ static void qeth_l2_process_inbound_buffer(struct qeth_card *card,
441 if (skb->protocol == htons(ETH_P_802_2)) 437 if (skb->protocol == htons(ETH_P_802_2))
442 *((__u32 *)skb->cb) = ++card->seqno.pkt_seqno; 438 *((__u32 *)skb->cb) = ++card->seqno.pkt_seqno;
443 len = skb->len; 439 len = skb->len;
444 netif_rx(skb); 440 netif_receive_skb(skb);
445 break; 441 break;
446 case QETH_HEADER_TYPE_OSN: 442 case QETH_HEADER_TYPE_OSN:
447 if (card->info.type == QETH_CARD_TYPE_OSN) { 443 if (card->info.type == QETH_CARD_TYPE_OSN) {
@@ -459,9 +455,87 @@ static void qeth_l2_process_inbound_buffer(struct qeth_card *card,
459 QETH_DBF_HEX(CTRL, 3, hdr, QETH_DBF_CTRL_LEN); 455 QETH_DBF_HEX(CTRL, 3, hdr, QETH_DBF_CTRL_LEN);
460 continue; 456 continue;
461 } 457 }
458 work_done++;
459 budget--;
462 card->stats.rx_packets++; 460 card->stats.rx_packets++;
463 card->stats.rx_bytes += len; 461 card->stats.rx_bytes += len;
464 } 462 }
463 return work_done;
464}
465
466static int qeth_l2_poll(struct napi_struct *napi, int budget)
467{
468 struct qeth_card *card = container_of(napi, struct qeth_card, napi);
469 int work_done = 0;
470 struct qeth_qdio_buffer *buffer;
471 int done;
472 int new_budget = budget;
473
474 if (card->options.performance_stats) {
475 card->perf_stats.inbound_cnt++;
476 card->perf_stats.inbound_start_time = qeth_get_micros();
477 }
478
479 while (1) {
480 if (!card->rx.b_count) {
481 card->rx.qdio_err = 0;
482 card->rx.b_count = qdio_get_next_buffers(
483 card->data.ccwdev, 0, &card->rx.b_index,
484 &card->rx.qdio_err);
485 if (card->rx.b_count <= 0) {
486 card->rx.b_count = 0;
487 break;
488 }
489 card->rx.b_element =
490 &card->qdio.in_q->bufs[card->rx.b_index]
491 .buffer->element[0];
492 card->rx.e_offset = 0;
493 }
494
495 while (card->rx.b_count) {
496 buffer = &card->qdio.in_q->bufs[card->rx.b_index];
497 if (!(card->rx.qdio_err &&
498 qeth_check_qdio_errors(card, buffer->buffer,
499 card->rx.qdio_err, "qinerr")))
500 work_done += qeth_l2_process_inbound_buffer(
501 card, new_budget, &done);
502 else
503 done = 1;
504
505 if (done) {
506 if (card->options.performance_stats)
507 card->perf_stats.bufs_rec++;
508 qeth_put_buffer_pool_entry(card,
509 buffer->pool_entry);
510 qeth_queue_input_buffer(card, card->rx.b_index);
511 card->rx.b_count--;
512 if (card->rx.b_count) {
513 card->rx.b_index =
514 (card->rx.b_index + 1) %
515 QDIO_MAX_BUFFERS_PER_Q;
516 card->rx.b_element =
517 &card->qdio.in_q
518 ->bufs[card->rx.b_index]
519 .buffer->element[0];
520 card->rx.e_offset = 0;
521 }
522 }
523
524 if (work_done >= budget)
525 goto out;
526 else
527 new_budget = budget - work_done;
528 }
529 }
530
531 napi_complete(napi);
532 if (qdio_start_irq(card->data.ccwdev, 0))
533 napi_schedule(&card->napi);
534out:
535 if (card->options.performance_stats)
536 card->perf_stats.inbound_time += qeth_get_micros() -
537 card->perf_stats.inbound_start_time;
538 return work_done;
465} 539}
466 540
467static int qeth_l2_send_setdelmac(struct qeth_card *card, __u8 *mac, 541static int qeth_l2_send_setdelmac(struct qeth_card *card, __u8 *mac,
@@ -755,49 +829,10 @@ tx_drop:
755 return NETDEV_TX_OK; 829 return NETDEV_TX_OK;
756} 830}
757 831
758static void qeth_l2_qdio_input_handler(struct ccw_device *ccwdev,
759 unsigned int qdio_err, unsigned int queue,
760 int first_element, int count, unsigned long card_ptr)
761{
762 struct net_device *net_dev;
763 struct qeth_card *card;
764 struct qeth_qdio_buffer *buffer;
765 int index;
766 int i;
767
768 card = (struct qeth_card *) card_ptr;
769 net_dev = card->dev;
770 if (card->options.performance_stats) {
771 card->perf_stats.inbound_cnt++;
772 card->perf_stats.inbound_start_time = qeth_get_micros();
773 }
774 if (qdio_err & QDIO_ERROR_ACTIVATE_CHECK_CONDITION) {
775 QETH_CARD_TEXT(card, 1, "qdinchk");
776 QETH_CARD_TEXT_(card, 1, "%04X%04X", first_element,
777 count);
778 QETH_CARD_TEXT_(card, 1, "%04X", queue);
779 qeth_schedule_recovery(card);
780 return;
781 }
782 for (i = first_element; i < (first_element + count); ++i) {
783 index = i % QDIO_MAX_BUFFERS_PER_Q;
784 buffer = &card->qdio.in_q->bufs[index];
785 if (!(qdio_err &&
786 qeth_check_qdio_errors(card, buffer->buffer, qdio_err,
787 "qinerr")))
788 qeth_l2_process_inbound_buffer(card, buffer, index);
789 /* clear buffer and give back to hardware */
790 qeth_put_buffer_pool_entry(card, buffer->pool_entry);
791 qeth_queue_input_buffer(card, index);
792 }
793 if (card->options.performance_stats)
794 card->perf_stats.inbound_time += qeth_get_micros() -
795 card->perf_stats.inbound_start_time;
796}
797
798static int qeth_l2_open(struct net_device *dev) 832static int qeth_l2_open(struct net_device *dev)
799{ 833{
800 struct qeth_card *card = dev->ml_priv; 834 struct qeth_card *card = dev->ml_priv;
835 int rc = 0;
801 836
802 QETH_CARD_TEXT(card, 4, "qethopen"); 837 QETH_CARD_TEXT(card, 4, "qethopen");
803 if (card->state != CARD_STATE_SOFTSETUP) 838 if (card->state != CARD_STATE_SOFTSETUP)
@@ -814,18 +849,24 @@ static int qeth_l2_open(struct net_device *dev)
814 849
815 if (!card->lan_online && netif_carrier_ok(dev)) 850 if (!card->lan_online && netif_carrier_ok(dev))
816 netif_carrier_off(dev); 851 netif_carrier_off(dev);
817 return 0; 852 if (qdio_stop_irq(card->data.ccwdev, 0) >= 0) {
853 napi_enable(&card->napi);
854 napi_schedule(&card->napi);
855 } else
856 rc = -EIO;
857 return rc;
818} 858}
819 859
820
821static int qeth_l2_stop(struct net_device *dev) 860static int qeth_l2_stop(struct net_device *dev)
822{ 861{
823 struct qeth_card *card = dev->ml_priv; 862 struct qeth_card *card = dev->ml_priv;
824 863
825 QETH_CARD_TEXT(card, 4, "qethstop"); 864 QETH_CARD_TEXT(card, 4, "qethstop");
826 netif_tx_disable(dev); 865 netif_tx_disable(dev);
827 if (card->state == CARD_STATE_UP) 866 if (card->state == CARD_STATE_UP) {
828 card->state = CARD_STATE_SOFTSETUP; 867 card->state = CARD_STATE_SOFTSETUP;
868 napi_disable(&card->napi);
869 }
829 return 0; 870 return 0;
830} 871}
831 872
@@ -836,8 +877,9 @@ static int qeth_l2_probe_device(struct ccwgroup_device *gdev)
836 INIT_LIST_HEAD(&card->vid_list); 877 INIT_LIST_HEAD(&card->vid_list);
837 INIT_LIST_HEAD(&card->mc_list); 878 INIT_LIST_HEAD(&card->mc_list);
838 card->options.layer2 = 1; 879 card->options.layer2 = 1;
880 card->discipline.start_poll = qeth_qdio_start_poll;
839 card->discipline.input_handler = (qdio_handler_t *) 881 card->discipline.input_handler = (qdio_handler_t *)
840 qeth_l2_qdio_input_handler; 882 qeth_qdio_input_handler;
841 card->discipline.output_handler = (qdio_handler_t *) 883 card->discipline.output_handler = (qdio_handler_t *)
842 qeth_qdio_output_handler; 884 qeth_qdio_output_handler;
843 card->discipline.recover = qeth_l2_recover; 885 card->discipline.recover = qeth_l2_recover;
@@ -923,6 +965,7 @@ static int qeth_l2_setup_netdev(struct qeth_card *card)
923 card->info.broadcast_capable = 1; 965 card->info.broadcast_capable = 1;
924 qeth_l2_request_initial_mac(card); 966 qeth_l2_request_initial_mac(card);
925 SET_NETDEV_DEV(card->dev, &card->gdev->dev); 967 SET_NETDEV_DEV(card->dev, &card->gdev->dev);
968 netif_napi_add(card->dev, &card->napi, qeth_l2_poll, QETH_NAPI_WEIGHT);
926 return register_netdev(card->dev); 969 return register_netdev(card->dev);
927} 970}
928 971
@@ -955,6 +998,7 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
955 qeth_l2_send_setmac(card, &card->dev->dev_addr[0]); 998 qeth_l2_send_setmac(card, &card->dev->dev_addr[0]);
956 999
957 card->state = CARD_STATE_HARDSETUP; 1000 card->state = CARD_STATE_HARDSETUP;
1001 memset(&card->rx, 0, sizeof(struct qeth_rx));
958 qeth_print_status_message(card); 1002 qeth_print_status_message(card);
959 1003
960 /* softsetup */ 1004 /* softsetup */
@@ -1086,9 +1130,6 @@ static int qeth_l2_recover(void *ptr)
1086 card->use_hard_stop = 1; 1130 card->use_hard_stop = 1;
1087 __qeth_l2_set_offline(card->gdev, 1); 1131 __qeth_l2_set_offline(card->gdev, 1);
1088 rc = __qeth_l2_set_online(card->gdev, 1); 1132 rc = __qeth_l2_set_online(card->gdev, 1);
1089 /* don't run another scheduled recovery */
1090 qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
1091 qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
1092 if (!rc) 1133 if (!rc)
1093 dev_info(&card->gdev->dev, 1134 dev_info(&card->gdev->dev,
1094 "Device successfully recovered!\n"); 1135 "Device successfully recovered!\n");
@@ -1099,6 +1140,8 @@ static int qeth_l2_recover(void *ptr)
1099 dev_warn(&card->gdev->dev, "The qeth device driver " 1140 dev_warn(&card->gdev->dev, "The qeth device driver "
1100 "failed to recover an error on the device\n"); 1141 "failed to recover an error on the device\n");
1101 } 1142 }
1143 qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
1144 qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
1102 return 0; 1145 return 0;
1103} 1146}
1104 1147
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index 561bdc881e92..5b79f573bd93 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -2107,51 +2107,44 @@ static inline __u16 qeth_l3_rebuild_skb(struct qeth_card *card,
2107 return vlan_id; 2107 return vlan_id;
2108} 2108}
2109 2109
2110static void qeth_l3_process_inbound_buffer(struct qeth_card *card, 2110static int qeth_l3_process_inbound_buffer(struct qeth_card *card,
2111 struct qeth_qdio_buffer *buf, int index) 2111 int budget, int *done)
2112{ 2112{
2113 struct qdio_buffer_element *element; 2113 int work_done = 0;
2114 struct sk_buff *skb; 2114 struct sk_buff *skb;
2115 struct qeth_hdr *hdr; 2115 struct qeth_hdr *hdr;
2116 int offset;
2117 __u16 vlan_tag = 0; 2116 __u16 vlan_tag = 0;
2118 unsigned int len; 2117 unsigned int len;
2119 /* get first element of current buffer */
2120 element = (struct qdio_buffer_element *)&buf->buffer->element[0];
2121 offset = 0;
2122 if (card->options.performance_stats)
2123 card->perf_stats.bufs_rec++;
2124 while ((skb = qeth_core_get_next_skb(card, buf->buffer, &element,
2125 &offset, &hdr))) {
2126 skb->dev = card->dev;
2127 /* is device UP ? */
2128 if (!(card->dev->flags & IFF_UP)) {
2129 dev_kfree_skb_any(skb);
2130 continue;
2131 }
2132 2118
2119 *done = 0;
2120 BUG_ON(!budget);
2121 while (budget) {
2122 skb = qeth_core_get_next_skb(card,
2123 card->qdio.in_q->bufs[card->rx.b_index].buffer,
2124 &card->rx.b_element, &card->rx.e_offset, &hdr);
2125 if (!skb) {
2126 *done = 1;
2127 break;
2128 }
2129 skb->dev = card->dev;
2133 switch (hdr->hdr.l3.id) { 2130 switch (hdr->hdr.l3.id) {
2134 case QETH_HEADER_TYPE_LAYER3: 2131 case QETH_HEADER_TYPE_LAYER3:
2135 vlan_tag = qeth_l3_rebuild_skb(card, skb, hdr); 2132 vlan_tag = qeth_l3_rebuild_skb(card, skb, hdr);
2136 len = skb->len; 2133 len = skb->len;
2137 if (vlan_tag && !card->options.sniffer) 2134 if (vlan_tag && !card->options.sniffer)
2138 if (card->vlangrp) 2135 if (card->vlangrp)
2139 vlan_hwaccel_rx(skb, card->vlangrp, 2136 vlan_gro_receive(&card->napi,
2140 vlan_tag); 2137 card->vlangrp, vlan_tag, skb);
2141 else { 2138 else {
2142 dev_kfree_skb_any(skb); 2139 dev_kfree_skb_any(skb);
2143 continue; 2140 continue;
2144 } 2141 }
2145 else 2142 else
2146 netif_rx(skb); 2143 napi_gro_receive(&card->napi, skb);
2147 break; 2144 break;
2148 case QETH_HEADER_TYPE_LAYER2: /* for HiperSockets sniffer */ 2145 case QETH_HEADER_TYPE_LAYER2: /* for HiperSockets sniffer */
2149 skb->pkt_type = PACKET_HOST; 2146 skb->pkt_type = PACKET_HOST;
2150 skb->protocol = eth_type_trans(skb, skb->dev); 2147 skb->protocol = eth_type_trans(skb, skb->dev);
2151 if (card->options.checksum_type == NO_CHECKSUMMING)
2152 skb->ip_summed = CHECKSUM_UNNECESSARY;
2153 else
2154 skb->ip_summed = CHECKSUM_NONE;
2155 len = skb->len; 2148 len = skb->len;
2156 netif_receive_skb(skb); 2149 netif_receive_skb(skb);
2157 break; 2150 break;
@@ -2161,10 +2154,87 @@ static void qeth_l3_process_inbound_buffer(struct qeth_card *card,
2161 QETH_DBF_HEX(CTRL, 3, hdr, QETH_DBF_CTRL_LEN); 2154 QETH_DBF_HEX(CTRL, 3, hdr, QETH_DBF_CTRL_LEN);
2162 continue; 2155 continue;
2163 } 2156 }
2164 2157 work_done++;
2158 budget--;
2165 card->stats.rx_packets++; 2159 card->stats.rx_packets++;
2166 card->stats.rx_bytes += len; 2160 card->stats.rx_bytes += len;
2167 } 2161 }
2162 return work_done;
2163}
2164
2165static int qeth_l3_poll(struct napi_struct *napi, int budget)
2166{
2167 struct qeth_card *card = container_of(napi, struct qeth_card, napi);
2168 int work_done = 0;
2169 struct qeth_qdio_buffer *buffer;
2170 int done;
2171 int new_budget = budget;
2172
2173 if (card->options.performance_stats) {
2174 card->perf_stats.inbound_cnt++;
2175 card->perf_stats.inbound_start_time = qeth_get_micros();
2176 }
2177
2178 while (1) {
2179 if (!card->rx.b_count) {
2180 card->rx.qdio_err = 0;
2181 card->rx.b_count = qdio_get_next_buffers(
2182 card->data.ccwdev, 0, &card->rx.b_index,
2183 &card->rx.qdio_err);
2184 if (card->rx.b_count <= 0) {
2185 card->rx.b_count = 0;
2186 break;
2187 }
2188 card->rx.b_element =
2189 &card->qdio.in_q->bufs[card->rx.b_index]
2190 .buffer->element[0];
2191 card->rx.e_offset = 0;
2192 }
2193
2194 while (card->rx.b_count) {
2195 buffer = &card->qdio.in_q->bufs[card->rx.b_index];
2196 if (!(card->rx.qdio_err &&
2197 qeth_check_qdio_errors(card, buffer->buffer,
2198 card->rx.qdio_err, "qinerr")))
2199 work_done += qeth_l3_process_inbound_buffer(
2200 card, new_budget, &done);
2201 else
2202 done = 1;
2203
2204 if (done) {
2205 if (card->options.performance_stats)
2206 card->perf_stats.bufs_rec++;
2207 qeth_put_buffer_pool_entry(card,
2208 buffer->pool_entry);
2209 qeth_queue_input_buffer(card, card->rx.b_index);
2210 card->rx.b_count--;
2211 if (card->rx.b_count) {
2212 card->rx.b_index =
2213 (card->rx.b_index + 1) %
2214 QDIO_MAX_BUFFERS_PER_Q;
2215 card->rx.b_element =
2216 &card->qdio.in_q
2217 ->bufs[card->rx.b_index]
2218 .buffer->element[0];
2219 card->rx.e_offset = 0;
2220 }
2221 }
2222
2223 if (work_done >= budget)
2224 goto out;
2225 else
2226 new_budget = budget - work_done;
2227 }
2228 }
2229
2230 napi_complete(napi);
2231 if (qdio_start_irq(card->data.ccwdev, 0))
2232 napi_schedule(&card->napi);
2233out:
2234 if (card->options.performance_stats)
2235 card->perf_stats.inbound_time += qeth_get_micros() -
2236 card->perf_stats.inbound_start_time;
2237 return work_done;
2168} 2238}
2169 2239
2170static int qeth_l3_verify_vlan_dev(struct net_device *dev, 2240static int qeth_l3_verify_vlan_dev(struct net_device *dev,
@@ -3098,6 +3168,7 @@ tx_drop:
3098static int qeth_l3_open(struct net_device *dev) 3168static int qeth_l3_open(struct net_device *dev)
3099{ 3169{
3100 struct qeth_card *card = dev->ml_priv; 3170 struct qeth_card *card = dev->ml_priv;
3171 int rc = 0;
3101 3172
3102 QETH_CARD_TEXT(card, 4, "qethopen"); 3173 QETH_CARD_TEXT(card, 4, "qethopen");
3103 if (card->state != CARD_STATE_SOFTSETUP) 3174 if (card->state != CARD_STATE_SOFTSETUP)
@@ -3108,7 +3179,12 @@ static int qeth_l3_open(struct net_device *dev)
3108 3179
3109 if (!card->lan_online && netif_carrier_ok(dev)) 3180 if (!card->lan_online && netif_carrier_ok(dev))
3110 netif_carrier_off(dev); 3181 netif_carrier_off(dev);
3111 return 0; 3182 if (qdio_stop_irq(card->data.ccwdev, 0) >= 0) {
3183 napi_enable(&card->napi);
3184 napi_schedule(&card->napi);
3185 } else
3186 rc = -EIO;
3187 return rc;
3112} 3188}
3113 3189
3114static int qeth_l3_stop(struct net_device *dev) 3190static int qeth_l3_stop(struct net_device *dev)
@@ -3117,8 +3193,10 @@ static int qeth_l3_stop(struct net_device *dev)
3117 3193
3118 QETH_CARD_TEXT(card, 4, "qethstop"); 3194 QETH_CARD_TEXT(card, 4, "qethstop");
3119 netif_tx_disable(dev); 3195 netif_tx_disable(dev);
3120 if (card->state == CARD_STATE_UP) 3196 if (card->state == CARD_STATE_UP) {
3121 card->state = CARD_STATE_SOFTSETUP; 3197 card->state = CARD_STATE_SOFTSETUP;
3198 napi_disable(&card->napi);
3199 }
3122 return 0; 3200 return 0;
3123} 3201}
3124 3202
@@ -3288,57 +3366,19 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
3288 card->dev->gso_max_size = 15 * PAGE_SIZE; 3366 card->dev->gso_max_size = 15 * PAGE_SIZE;
3289 3367
3290 SET_NETDEV_DEV(card->dev, &card->gdev->dev); 3368 SET_NETDEV_DEV(card->dev, &card->gdev->dev);
3369 netif_napi_add(card->dev, &card->napi, qeth_l3_poll, QETH_NAPI_WEIGHT);
3291 return register_netdev(card->dev); 3370 return register_netdev(card->dev);
3292} 3371}
3293 3372
3294static void qeth_l3_qdio_input_handler(struct ccw_device *ccwdev,
3295 unsigned int qdio_err, unsigned int queue, int first_element,
3296 int count, unsigned long card_ptr)
3297{
3298 struct net_device *net_dev;
3299 struct qeth_card *card;
3300 struct qeth_qdio_buffer *buffer;
3301 int index;
3302 int i;
3303
3304 card = (struct qeth_card *) card_ptr;
3305 net_dev = card->dev;
3306 if (card->options.performance_stats) {
3307 card->perf_stats.inbound_cnt++;
3308 card->perf_stats.inbound_start_time = qeth_get_micros();
3309 }
3310 if (qdio_err & QDIO_ERROR_ACTIVATE_CHECK_CONDITION) {
3311 QETH_CARD_TEXT(card, 1, "qdinchk");
3312 QETH_CARD_TEXT_(card, 1, "%04X%04X",
3313 first_element, count);
3314 QETH_CARD_TEXT_(card, 1, "%04X", queue);
3315 qeth_schedule_recovery(card);
3316 return;
3317 }
3318 for (i = first_element; i < (first_element + count); ++i) {
3319 index = i % QDIO_MAX_BUFFERS_PER_Q;
3320 buffer = &card->qdio.in_q->bufs[index];
3321 if (!(qdio_err &&
3322 qeth_check_qdio_errors(card, buffer->buffer,
3323 qdio_err, "qinerr")))
3324 qeth_l3_process_inbound_buffer(card, buffer, index);
3325 /* clear buffer and give back to hardware */
3326 qeth_put_buffer_pool_entry(card, buffer->pool_entry);
3327 qeth_queue_input_buffer(card, index);
3328 }
3329 if (card->options.performance_stats)
3330 card->perf_stats.inbound_time += qeth_get_micros() -
3331 card->perf_stats.inbound_start_time;
3332}
3333
3334static int qeth_l3_probe_device(struct ccwgroup_device *gdev) 3373static int qeth_l3_probe_device(struct ccwgroup_device *gdev)
3335{ 3374{
3336 struct qeth_card *card = dev_get_drvdata(&gdev->dev); 3375 struct qeth_card *card = dev_get_drvdata(&gdev->dev);
3337 3376
3338 qeth_l3_create_device_attributes(&gdev->dev); 3377 qeth_l3_create_device_attributes(&gdev->dev);
3339 card->options.layer2 = 0; 3378 card->options.layer2 = 0;
3379 card->discipline.start_poll = qeth_qdio_start_poll;
3340 card->discipline.input_handler = (qdio_handler_t *) 3380 card->discipline.input_handler = (qdio_handler_t *)
3341 qeth_l3_qdio_input_handler; 3381 qeth_qdio_input_handler;
3342 card->discipline.output_handler = (qdio_handler_t *) 3382 card->discipline.output_handler = (qdio_handler_t *)
3343 qeth_qdio_output_handler; 3383 qeth_qdio_output_handler;
3344 card->discipline.recover = qeth_l3_recover; 3384 card->discipline.recover = qeth_l3_recover;
@@ -3397,6 +3437,7 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
3397 } 3437 }
3398 3438
3399 card->state = CARD_STATE_HARDSETUP; 3439 card->state = CARD_STATE_HARDSETUP;
3440 memset(&card->rx, 0, sizeof(struct qeth_rx));
3400 qeth_print_status_message(card); 3441 qeth_print_status_message(card);
3401 3442
3402 /* softsetup */ 3443 /* softsetup */
@@ -3533,9 +3574,6 @@ static int qeth_l3_recover(void *ptr)
3533 card->use_hard_stop = 1; 3574 card->use_hard_stop = 1;
3534 __qeth_l3_set_offline(card->gdev, 1); 3575 __qeth_l3_set_offline(card->gdev, 1);
3535 rc = __qeth_l3_set_online(card->gdev, 1); 3576 rc = __qeth_l3_set_online(card->gdev, 1);
3536 /* don't run another scheduled recovery */
3537 qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
3538 qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
3539 if (!rc) 3577 if (!rc)
3540 dev_info(&card->gdev->dev, 3578 dev_info(&card->gdev->dev,
3541 "Device successfully recovered!\n"); 3579 "Device successfully recovered!\n");
@@ -3546,6 +3584,8 @@ static int qeth_l3_recover(void *ptr)
3546 dev_warn(&card->gdev->dev, "The qeth device driver " 3584 dev_warn(&card->gdev->dev, "The qeth device driver "
3547 "failed to recover an error on the device\n"); 3585 "failed to recover an error on the device\n");
3548 } 3586 }
3587 qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
3588 qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
3549 return 0; 3589 return 0;
3550} 3590}
3551 3591