aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/net/qeth_l2_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/net/qeth_l2_main.c')
-rw-r--r--drivers/s390/net/qeth_l2_main.c173
1 files changed, 108 insertions, 65 deletions
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