diff options
Diffstat (limited to 'drivers/s390/net/qeth_l2_main.c')
-rw-r--r-- | drivers/s390/net/qeth_l2_main.c | 272 |
1 files changed, 164 insertions, 108 deletions
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 830d63524d61..b70b47fbd6cd 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c | |||
@@ -202,17 +202,19 @@ static void qeth_l2_add_mc(struct qeth_card *card, __u8 *mac, int vmac) | |||
202 | kfree(mc); | 202 | kfree(mc); |
203 | } | 203 | } |
204 | 204 | ||
205 | static void qeth_l2_del_all_mc(struct qeth_card *card) | 205 | static void qeth_l2_del_all_mc(struct qeth_card *card, int del) |
206 | { | 206 | { |
207 | struct qeth_mc_mac *mc, *tmp; | 207 | struct qeth_mc_mac *mc, *tmp; |
208 | 208 | ||
209 | spin_lock_bh(&card->mclock); | 209 | spin_lock_bh(&card->mclock); |
210 | list_for_each_entry_safe(mc, tmp, &card->mc_list, list) { | 210 | list_for_each_entry_safe(mc, tmp, &card->mc_list, list) { |
211 | if (mc->is_vmac) | 211 | if (del) { |
212 | qeth_l2_send_setdelmac(card, mc->mc_addr, | 212 | if (mc->is_vmac) |
213 | qeth_l2_send_setdelmac(card, mc->mc_addr, | ||
213 | IPA_CMD_DELVMAC, NULL); | 214 | IPA_CMD_DELVMAC, NULL); |
214 | else | 215 | else |
215 | qeth_l2_send_delgroupmac(card, mc->mc_addr); | 216 | qeth_l2_send_delgroupmac(card, mc->mc_addr); |
217 | } | ||
216 | list_del(&mc->list); | 218 | list_del(&mc->list); |
217 | kfree(mc); | 219 | kfree(mc); |
218 | } | 220 | } |
@@ -288,18 +290,13 @@ static int qeth_l2_send_setdelvlan(struct qeth_card *card, __u16 i, | |||
288 | qeth_l2_send_setdelvlan_cb, NULL); | 290 | qeth_l2_send_setdelvlan_cb, NULL); |
289 | } | 291 | } |
290 | 292 | ||
291 | static void qeth_l2_process_vlans(struct qeth_card *card, int clear) | 293 | static void qeth_l2_process_vlans(struct qeth_card *card) |
292 | { | 294 | { |
293 | struct qeth_vlan_vid *id; | 295 | struct qeth_vlan_vid *id; |
294 | QETH_CARD_TEXT(card, 3, "L2prcvln"); | 296 | QETH_CARD_TEXT(card, 3, "L2prcvln"); |
295 | spin_lock_bh(&card->vlanlock); | 297 | spin_lock_bh(&card->vlanlock); |
296 | list_for_each_entry(id, &card->vid_list, list) { | 298 | list_for_each_entry(id, &card->vid_list, list) { |
297 | if (clear) | 299 | qeth_l2_send_setdelvlan(card, id->vid, IPA_CMD_SETVLAN); |
298 | qeth_l2_send_setdelvlan(card, id->vid, | ||
299 | IPA_CMD_DELVLAN); | ||
300 | else | ||
301 | qeth_l2_send_setdelvlan(card, id->vid, | ||
302 | IPA_CMD_SETVLAN); | ||
303 | } | 300 | } |
304 | spin_unlock_bh(&card->vlanlock); | 301 | spin_unlock_bh(&card->vlanlock); |
305 | } | 302 | } |
@@ -310,6 +307,8 @@ static void qeth_l2_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) | |||
310 | struct qeth_vlan_vid *id; | 307 | struct qeth_vlan_vid *id; |
311 | 308 | ||
312 | QETH_CARD_TEXT_(card, 4, "aid:%d", vid); | 309 | QETH_CARD_TEXT_(card, 4, "aid:%d", vid); |
310 | if (!vid) | ||
311 | return; | ||
313 | if (card->info.type == QETH_CARD_TYPE_OSM) { | 312 | if (card->info.type == QETH_CARD_TYPE_OSM) { |
314 | QETH_CARD_TEXT(card, 3, "aidOSM"); | 313 | QETH_CARD_TEXT(card, 3, "aidOSM"); |
315 | return; | 314 | return; |
@@ -377,19 +376,11 @@ static int qeth_l2_stop_card(struct qeth_card *card, int recovery_mode) | |||
377 | dev_close(card->dev); | 376 | dev_close(card->dev); |
378 | rtnl_unlock(); | 377 | rtnl_unlock(); |
379 | } | 378 | } |
380 | if (!card->use_hard_stop || | 379 | card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED; |
381 | recovery_mode) { | ||
382 | __u8 *mac = &card->dev->dev_addr[0]; | ||
383 | rc = qeth_l2_send_delmac(card, mac); | ||
384 | QETH_DBF_TEXT_(SETUP, 2, "Lerr%d", rc); | ||
385 | } | ||
386 | card->state = CARD_STATE_SOFTSETUP; | 380 | card->state = CARD_STATE_SOFTSETUP; |
387 | } | 381 | } |
388 | if (card->state == CARD_STATE_SOFTSETUP) { | 382 | if (card->state == CARD_STATE_SOFTSETUP) { |
389 | qeth_l2_process_vlans(card, 1); | 383 | qeth_l2_del_all_mc(card, 0); |
390 | if (!card->use_hard_stop || | ||
391 | recovery_mode) | ||
392 | qeth_l2_del_all_mc(card); | ||
393 | qeth_clear_ipacmd_list(card); | 384 | qeth_clear_ipacmd_list(card); |
394 | card->state = CARD_STATE_HARDSETUP; | 385 | card->state = CARD_STATE_HARDSETUP; |
395 | } | 386 | } |
@@ -403,45 +394,37 @@ static int qeth_l2_stop_card(struct qeth_card *card, int recovery_mode) | |||
403 | qeth_clear_cmd_buffers(&card->read); | 394 | qeth_clear_cmd_buffers(&card->read); |
404 | qeth_clear_cmd_buffers(&card->write); | 395 | qeth_clear_cmd_buffers(&card->write); |
405 | } | 396 | } |
406 | card->use_hard_stop = 0; | ||
407 | return rc; | 397 | return rc; |
408 | } | 398 | } |
409 | 399 | ||
410 | static void qeth_l2_process_inbound_buffer(struct qeth_card *card, | 400 | static int qeth_l2_process_inbound_buffer(struct qeth_card *card, |
411 | struct qeth_qdio_buffer *buf, int index) | 401 | int budget, int *done) |
412 | { | 402 | { |
413 | struct qdio_buffer_element *element; | 403 | int work_done = 0; |
414 | struct sk_buff *skb; | 404 | struct sk_buff *skb; |
415 | struct qeth_hdr *hdr; | 405 | struct qeth_hdr *hdr; |
416 | int offset; | ||
417 | unsigned int len; | 406 | unsigned int len; |
418 | 407 | ||
419 | /* get first element of current buffer */ | 408 | *done = 0; |
420 | element = (struct qdio_buffer_element *)&buf->buffer->element[0]; | 409 | BUG_ON(!budget); |
421 | offset = 0; | 410 | while (budget) { |
422 | if (card->options.performance_stats) | 411 | skb = qeth_core_get_next_skb(card, |
423 | card->perf_stats.bufs_rec++; | 412 | card->qdio.in_q->bufs[card->rx.b_index].buffer, |
424 | while ((skb = qeth_core_get_next_skb(card, buf->buffer, &element, | 413 | &card->rx.b_element, &card->rx.e_offset, &hdr); |
425 | &offset, &hdr))) { | 414 | if (!skb) { |
426 | skb->dev = card->dev; | 415 | *done = 1; |
427 | /* is device UP ? */ | 416 | break; |
428 | if (!(card->dev->flags & IFF_UP)) { | ||
429 | dev_kfree_skb_any(skb); | ||
430 | continue; | ||
431 | } | 417 | } |
432 | 418 | skb->dev = card->dev; | |
433 | switch (hdr->hdr.l2.id) { | 419 | switch (hdr->hdr.l2.id) { |
434 | case QETH_HEADER_TYPE_LAYER2: | 420 | case QETH_HEADER_TYPE_LAYER2: |
435 | skb->pkt_type = PACKET_HOST; | 421 | skb->pkt_type = PACKET_HOST; |
436 | skb->protocol = eth_type_trans(skb, skb->dev); | 422 | skb->protocol = eth_type_trans(skb, skb->dev); |
437 | if (card->options.checksum_type == NO_CHECKSUMMING) | 423 | skb->ip_summed = CHECKSUM_NONE; |
438 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
439 | else | ||
440 | skb->ip_summed = CHECKSUM_NONE; | ||
441 | if (skb->protocol == htons(ETH_P_802_2)) | 424 | if (skb->protocol == htons(ETH_P_802_2)) |
442 | *((__u32 *)skb->cb) = ++card->seqno.pkt_seqno; | 425 | *((__u32 *)skb->cb) = ++card->seqno.pkt_seqno; |
443 | len = skb->len; | 426 | len = skb->len; |
444 | netif_rx(skb); | 427 | netif_receive_skb(skb); |
445 | break; | 428 | break; |
446 | case QETH_HEADER_TYPE_OSN: | 429 | case QETH_HEADER_TYPE_OSN: |
447 | if (card->info.type == QETH_CARD_TYPE_OSN) { | 430 | if (card->info.type == QETH_CARD_TYPE_OSN) { |
@@ -459,9 +442,87 @@ static void qeth_l2_process_inbound_buffer(struct qeth_card *card, | |||
459 | QETH_DBF_HEX(CTRL, 3, hdr, QETH_DBF_CTRL_LEN); | 442 | QETH_DBF_HEX(CTRL, 3, hdr, QETH_DBF_CTRL_LEN); |
460 | continue; | 443 | continue; |
461 | } | 444 | } |
445 | work_done++; | ||
446 | budget--; | ||
462 | card->stats.rx_packets++; | 447 | card->stats.rx_packets++; |
463 | card->stats.rx_bytes += len; | 448 | card->stats.rx_bytes += len; |
464 | } | 449 | } |
450 | return work_done; | ||
451 | } | ||
452 | |||
453 | static int qeth_l2_poll(struct napi_struct *napi, int budget) | ||
454 | { | ||
455 | struct qeth_card *card = container_of(napi, struct qeth_card, napi); | ||
456 | int work_done = 0; | ||
457 | struct qeth_qdio_buffer *buffer; | ||
458 | int done; | ||
459 | int new_budget = budget; | ||
460 | |||
461 | if (card->options.performance_stats) { | ||
462 | card->perf_stats.inbound_cnt++; | ||
463 | card->perf_stats.inbound_start_time = qeth_get_micros(); | ||
464 | } | ||
465 | |||
466 | while (1) { | ||
467 | if (!card->rx.b_count) { | ||
468 | card->rx.qdio_err = 0; | ||
469 | card->rx.b_count = qdio_get_next_buffers( | ||
470 | card->data.ccwdev, 0, &card->rx.b_index, | ||
471 | &card->rx.qdio_err); | ||
472 | if (card->rx.b_count <= 0) { | ||
473 | card->rx.b_count = 0; | ||
474 | break; | ||
475 | } | ||
476 | card->rx.b_element = | ||
477 | &card->qdio.in_q->bufs[card->rx.b_index] | ||
478 | .buffer->element[0]; | ||
479 | card->rx.e_offset = 0; | ||
480 | } | ||
481 | |||
482 | while (card->rx.b_count) { | ||
483 | buffer = &card->qdio.in_q->bufs[card->rx.b_index]; | ||
484 | if (!(card->rx.qdio_err && | ||
485 | qeth_check_qdio_errors(card, buffer->buffer, | ||
486 | card->rx.qdio_err, "qinerr"))) | ||
487 | work_done += qeth_l2_process_inbound_buffer( | ||
488 | card, new_budget, &done); | ||
489 | else | ||
490 | done = 1; | ||
491 | |||
492 | if (done) { | ||
493 | if (card->options.performance_stats) | ||
494 | card->perf_stats.bufs_rec++; | ||
495 | qeth_put_buffer_pool_entry(card, | ||
496 | buffer->pool_entry); | ||
497 | qeth_queue_input_buffer(card, card->rx.b_index); | ||
498 | card->rx.b_count--; | ||
499 | if (card->rx.b_count) { | ||
500 | card->rx.b_index = | ||
501 | (card->rx.b_index + 1) % | ||
502 | QDIO_MAX_BUFFERS_PER_Q; | ||
503 | card->rx.b_element = | ||
504 | &card->qdio.in_q | ||
505 | ->bufs[card->rx.b_index] | ||
506 | .buffer->element[0]; | ||
507 | card->rx.e_offset = 0; | ||
508 | } | ||
509 | } | ||
510 | |||
511 | if (work_done >= budget) | ||
512 | goto out; | ||
513 | else | ||
514 | new_budget = budget - work_done; | ||
515 | } | ||
516 | } | ||
517 | |||
518 | napi_complete(napi); | ||
519 | if (qdio_start_irq(card->data.ccwdev, 0)) | ||
520 | napi_schedule(&card->napi); | ||
521 | out: | ||
522 | if (card->options.performance_stats) | ||
523 | card->perf_stats.inbound_time += qeth_get_micros() - | ||
524 | card->perf_stats.inbound_start_time; | ||
525 | return work_done; | ||
465 | } | 526 | } |
466 | 527 | ||
467 | static int qeth_l2_send_setdelmac(struct qeth_card *card, __u8 *mac, | 528 | static int qeth_l2_send_setdelmac(struct qeth_card *card, __u8 *mac, |
@@ -497,13 +558,13 @@ static int qeth_l2_send_setmac_cb(struct qeth_card *card, | |||
497 | case IPA_RC_L2_DUP_LAYER3_MAC: | 558 | case IPA_RC_L2_DUP_LAYER3_MAC: |
498 | dev_warn(&card->gdev->dev, | 559 | dev_warn(&card->gdev->dev, |
499 | "MAC address %pM already exists\n", | 560 | "MAC address %pM already exists\n", |
500 | card->dev->dev_addr); | 561 | cmd->data.setdelmac.mac); |
501 | break; | 562 | break; |
502 | case IPA_RC_L2_MAC_NOT_AUTH_BY_HYP: | 563 | case IPA_RC_L2_MAC_NOT_AUTH_BY_HYP: |
503 | case IPA_RC_L2_MAC_NOT_AUTH_BY_ADP: | 564 | case IPA_RC_L2_MAC_NOT_AUTH_BY_ADP: |
504 | dev_warn(&card->gdev->dev, | 565 | dev_warn(&card->gdev->dev, |
505 | "MAC address %pM is not authorized\n", | 566 | "MAC address %pM is not authorized\n", |
506 | card->dev->dev_addr); | 567 | cmd->data.setdelmac.mac); |
507 | break; | 568 | break; |
508 | default: | 569 | default: |
509 | break; | 570 | break; |
@@ -629,7 +690,7 @@ static void qeth_l2_set_multicast_list(struct net_device *dev) | |||
629 | if (qeth_threads_running(card, QETH_RECOVER_THREAD) && | 690 | if (qeth_threads_running(card, QETH_RECOVER_THREAD) && |
630 | (card->state != CARD_STATE_UP)) | 691 | (card->state != CARD_STATE_UP)) |
631 | return; | 692 | return; |
632 | qeth_l2_del_all_mc(card); | 693 | qeth_l2_del_all_mc(card, 1); |
633 | spin_lock_bh(&card->mclock); | 694 | spin_lock_bh(&card->mclock); |
634 | netdev_for_each_mc_addr(ha, dev) | 695 | netdev_for_each_mc_addr(ha, dev) |
635 | qeth_l2_add_mc(card, ha->addr, 0); | 696 | qeth_l2_add_mc(card, ha->addr, 0); |
@@ -755,51 +816,14 @@ tx_drop: | |||
755 | return NETDEV_TX_OK; | 816 | return NETDEV_TX_OK; |
756 | } | 817 | } |
757 | 818 | ||
758 | static void qeth_l2_qdio_input_handler(struct ccw_device *ccwdev, | 819 | static int __qeth_l2_open(struct net_device *dev) |
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 | |||
798 | static int qeth_l2_open(struct net_device *dev) | ||
799 | { | 820 | { |
800 | struct qeth_card *card = dev->ml_priv; | 821 | struct qeth_card *card = dev->ml_priv; |
822 | int rc = 0; | ||
801 | 823 | ||
802 | QETH_CARD_TEXT(card, 4, "qethopen"); | 824 | QETH_CARD_TEXT(card, 4, "qethopen"); |
825 | if (card->state == CARD_STATE_UP) | ||
826 | return rc; | ||
803 | if (card->state != CARD_STATE_SOFTSETUP) | 827 | if (card->state != CARD_STATE_SOFTSETUP) |
804 | return -ENODEV; | 828 | return -ENODEV; |
805 | 829 | ||
@@ -812,11 +836,25 @@ static int qeth_l2_open(struct net_device *dev) | |||
812 | card->state = CARD_STATE_UP; | 836 | card->state = CARD_STATE_UP; |
813 | netif_start_queue(dev); | 837 | netif_start_queue(dev); |
814 | 838 | ||
815 | if (!card->lan_online && netif_carrier_ok(dev)) | 839 | if (qdio_stop_irq(card->data.ccwdev, 0) >= 0) { |
816 | netif_carrier_off(dev); | 840 | napi_enable(&card->napi); |
817 | return 0; | 841 | napi_schedule(&card->napi); |
842 | } else | ||
843 | rc = -EIO; | ||
844 | return rc; | ||
818 | } | 845 | } |
819 | 846 | ||
847 | static int qeth_l2_open(struct net_device *dev) | ||
848 | { | ||
849 | struct qeth_card *card = dev->ml_priv; | ||
850 | |||
851 | QETH_CARD_TEXT(card, 5, "qethope_"); | ||
852 | if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) { | ||
853 | QETH_CARD_TEXT(card, 3, "openREC"); | ||
854 | return -ERESTARTSYS; | ||
855 | } | ||
856 | return __qeth_l2_open(dev); | ||
857 | } | ||
820 | 858 | ||
821 | static int qeth_l2_stop(struct net_device *dev) | 859 | static int qeth_l2_stop(struct net_device *dev) |
822 | { | 860 | { |
@@ -824,8 +862,10 @@ static int qeth_l2_stop(struct net_device *dev) | |||
824 | 862 | ||
825 | QETH_CARD_TEXT(card, 4, "qethstop"); | 863 | QETH_CARD_TEXT(card, 4, "qethstop"); |
826 | netif_tx_disable(dev); | 864 | netif_tx_disable(dev); |
827 | if (card->state == CARD_STATE_UP) | 865 | if (card->state == CARD_STATE_UP) { |
828 | card->state = CARD_STATE_SOFTSETUP; | 866 | card->state = CARD_STATE_SOFTSETUP; |
867 | napi_disable(&card->napi); | ||
868 | } | ||
829 | return 0; | 869 | return 0; |
830 | } | 870 | } |
831 | 871 | ||
@@ -836,8 +876,10 @@ static int qeth_l2_probe_device(struct ccwgroup_device *gdev) | |||
836 | INIT_LIST_HEAD(&card->vid_list); | 876 | INIT_LIST_HEAD(&card->vid_list); |
837 | INIT_LIST_HEAD(&card->mc_list); | 877 | INIT_LIST_HEAD(&card->mc_list); |
838 | card->options.layer2 = 1; | 878 | card->options.layer2 = 1; |
879 | card->info.hwtrap = 0; | ||
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; |
@@ -851,10 +893,8 @@ static void qeth_l2_remove_device(struct ccwgroup_device *cgdev) | |||
851 | qeth_set_allowed_threads(card, 0, 1); | 893 | qeth_set_allowed_threads(card, 0, 1); |
852 | wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0); | 894 | wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0); |
853 | 895 | ||
854 | if (cgdev->state == CCWGROUP_ONLINE) { | 896 | if (cgdev->state == CCWGROUP_ONLINE) |
855 | card->use_hard_stop = 1; | ||
856 | qeth_l2_set_offline(cgdev); | 897 | qeth_l2_set_offline(cgdev); |
857 | } | ||
858 | 898 | ||
859 | if (card->dev) { | 899 | if (card->dev) { |
860 | unregister_netdev(card->dev); | 900 | unregister_netdev(card->dev); |
@@ -923,6 +963,7 @@ static int qeth_l2_setup_netdev(struct qeth_card *card) | |||
923 | card->info.broadcast_capable = 1; | 963 | card->info.broadcast_capable = 1; |
924 | qeth_l2_request_initial_mac(card); | 964 | qeth_l2_request_initial_mac(card); |
925 | SET_NETDEV_DEV(card->dev, &card->gdev->dev); | 965 | SET_NETDEV_DEV(card->dev, &card->gdev->dev); |
966 | netif_napi_add(card->dev, &card->napi, qeth_l2_poll, QETH_NAPI_WEIGHT); | ||
926 | return register_netdev(card->dev); | 967 | return register_netdev(card->dev); |
927 | } | 968 | } |
928 | 969 | ||
@@ -954,7 +995,15 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) | |||
954 | if (card->info.type != QETH_CARD_TYPE_OSN) | 995 | if (card->info.type != QETH_CARD_TYPE_OSN) |
955 | qeth_l2_send_setmac(card, &card->dev->dev_addr[0]); | 996 | qeth_l2_send_setmac(card, &card->dev->dev_addr[0]); |
956 | 997 | ||
998 | if (qeth_is_diagass_supported(card, QETH_DIAGS_CMD_TRAP)) { | ||
999 | if (card->info.hwtrap && | ||
1000 | qeth_hw_trap(card, QETH_DIAGS_TRAP_ARM)) | ||
1001 | card->info.hwtrap = 0; | ||
1002 | } else | ||
1003 | card->info.hwtrap = 0; | ||
1004 | |||
957 | card->state = CARD_STATE_HARDSETUP; | 1005 | card->state = CARD_STATE_HARDSETUP; |
1006 | memset(&card->rx, 0, sizeof(struct qeth_rx)); | ||
958 | qeth_print_status_message(card); | 1007 | qeth_print_status_message(card); |
959 | 1008 | ||
960 | /* softsetup */ | 1009 | /* softsetup */ |
@@ -967,13 +1016,14 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) | |||
967 | dev_warn(&card->gdev->dev, | 1016 | dev_warn(&card->gdev->dev, |
968 | "The LAN is offline\n"); | 1017 | "The LAN is offline\n"); |
969 | card->lan_online = 0; | 1018 | card->lan_online = 0; |
970 | goto out; | 1019 | goto contin; |
971 | } | 1020 | } |
972 | rc = -ENODEV; | 1021 | rc = -ENODEV; |
973 | goto out_remove; | 1022 | goto out_remove; |
974 | } else | 1023 | } else |
975 | card->lan_online = 1; | 1024 | card->lan_online = 1; |
976 | 1025 | ||
1026 | contin: | ||
977 | if ((card->info.type == QETH_CARD_TYPE_OSD) || | 1027 | if ((card->info.type == QETH_CARD_TYPE_OSD) || |
978 | (card->info.type == QETH_CARD_TYPE_OSX)) | 1028 | (card->info.type == QETH_CARD_TYPE_OSX)) |
979 | /* configure isolation level */ | 1029 | /* configure isolation level */ |
@@ -981,7 +1031,7 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) | |||
981 | 1031 | ||
982 | if (card->info.type != QETH_CARD_TYPE_OSN && | 1032 | if (card->info.type != QETH_CARD_TYPE_OSN && |
983 | card->info.type != QETH_CARD_TYPE_OSM) | 1033 | card->info.type != QETH_CARD_TYPE_OSM) |
984 | qeth_l2_process_vlans(card, 0); | 1034 | qeth_l2_process_vlans(card); |
985 | 1035 | ||
986 | netif_tx_disable(card->dev); | 1036 | netif_tx_disable(card->dev); |
987 | 1037 | ||
@@ -992,13 +1042,16 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) | |||
992 | goto out_remove; | 1042 | goto out_remove; |
993 | } | 1043 | } |
994 | card->state = CARD_STATE_SOFTSETUP; | 1044 | card->state = CARD_STATE_SOFTSETUP; |
995 | netif_carrier_on(card->dev); | 1045 | if (card->lan_online) |
1046 | netif_carrier_on(card->dev); | ||
1047 | else | ||
1048 | netif_carrier_off(card->dev); | ||
996 | 1049 | ||
997 | qeth_set_allowed_threads(card, 0xffffffff, 0); | 1050 | qeth_set_allowed_threads(card, 0xffffffff, 0); |
998 | if (recover_flag == CARD_STATE_RECOVER) { | 1051 | if (recover_flag == CARD_STATE_RECOVER) { |
999 | if (recovery_mode && | 1052 | if (recovery_mode && |
1000 | card->info.type != QETH_CARD_TYPE_OSN) { | 1053 | card->info.type != QETH_CARD_TYPE_OSN) { |
1001 | qeth_l2_open(card->dev); | 1054 | __qeth_l2_open(card->dev); |
1002 | } else { | 1055 | } else { |
1003 | rtnl_lock(); | 1056 | rtnl_lock(); |
1004 | dev_open(card->dev); | 1057 | dev_open(card->dev); |
@@ -1009,13 +1062,11 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) | |||
1009 | } | 1062 | } |
1010 | /* let user_space know that device is online */ | 1063 | /* let user_space know that device is online */ |
1011 | kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE); | 1064 | kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE); |
1012 | out: | ||
1013 | mutex_unlock(&card->conf_mutex); | 1065 | mutex_unlock(&card->conf_mutex); |
1014 | mutex_unlock(&card->discipline_mutex); | 1066 | mutex_unlock(&card->discipline_mutex); |
1015 | return 0; | 1067 | return 0; |
1016 | 1068 | ||
1017 | out_remove: | 1069 | out_remove: |
1018 | card->use_hard_stop = 1; | ||
1019 | qeth_l2_stop_card(card, 0); | 1070 | qeth_l2_stop_card(card, 0); |
1020 | ccw_device_set_offline(CARD_DDEV(card)); | 1071 | ccw_device_set_offline(CARD_DDEV(card)); |
1021 | ccw_device_set_offline(CARD_WDEV(card)); | 1072 | ccw_device_set_offline(CARD_WDEV(card)); |
@@ -1049,6 +1100,10 @@ static int __qeth_l2_set_offline(struct ccwgroup_device *cgdev, | |||
1049 | if (card->dev && netif_carrier_ok(card->dev)) | 1100 | if (card->dev && netif_carrier_ok(card->dev)) |
1050 | netif_carrier_off(card->dev); | 1101 | netif_carrier_off(card->dev); |
1051 | recover_flag = card->state; | 1102 | recover_flag = card->state; |
1103 | if ((!recovery_mode && card->info.hwtrap) || card->info.hwtrap == 2) { | ||
1104 | qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM); | ||
1105 | card->info.hwtrap = 1; | ||
1106 | } | ||
1052 | qeth_l2_stop_card(card, recovery_mode); | 1107 | qeth_l2_stop_card(card, recovery_mode); |
1053 | rc = ccw_device_set_offline(CARD_DDEV(card)); | 1108 | rc = ccw_device_set_offline(CARD_DDEV(card)); |
1054 | rc2 = ccw_device_set_offline(CARD_WDEV(card)); | 1109 | rc2 = ccw_device_set_offline(CARD_WDEV(card)); |
@@ -1083,12 +1138,8 @@ static int qeth_l2_recover(void *ptr) | |||
1083 | QETH_CARD_TEXT(card, 2, "recover2"); | 1138 | QETH_CARD_TEXT(card, 2, "recover2"); |
1084 | dev_warn(&card->gdev->dev, | 1139 | dev_warn(&card->gdev->dev, |
1085 | "A recovery process has been started for the device\n"); | 1140 | "A recovery process has been started for the device\n"); |
1086 | card->use_hard_stop = 1; | ||
1087 | __qeth_l2_set_offline(card->gdev, 1); | 1141 | __qeth_l2_set_offline(card->gdev, 1); |
1088 | rc = __qeth_l2_set_online(card->gdev, 1); | 1142 | 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) | 1143 | if (!rc) |
1093 | dev_info(&card->gdev->dev, | 1144 | dev_info(&card->gdev->dev, |
1094 | "Device successfully recovered!\n"); | 1145 | "Device successfully recovered!\n"); |
@@ -1099,6 +1150,8 @@ static int qeth_l2_recover(void *ptr) | |||
1099 | dev_warn(&card->gdev->dev, "The qeth device driver " | 1150 | dev_warn(&card->gdev->dev, "The qeth device driver " |
1100 | "failed to recover an error on the device\n"); | 1151 | "failed to recover an error on the device\n"); |
1101 | } | 1152 | } |
1153 | qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD); | ||
1154 | qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD); | ||
1102 | return 0; | 1155 | return 0; |
1103 | } | 1156 | } |
1104 | 1157 | ||
@@ -1116,6 +1169,8 @@ static void __exit qeth_l2_exit(void) | |||
1116 | static void qeth_l2_shutdown(struct ccwgroup_device *gdev) | 1169 | static void qeth_l2_shutdown(struct ccwgroup_device *gdev) |
1117 | { | 1170 | { |
1118 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); | 1171 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); |
1172 | if ((gdev->state == CCWGROUP_ONLINE) && card->info.hwtrap) | ||
1173 | qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM); | ||
1119 | qeth_qdio_clear_card(card, 0); | 1174 | qeth_qdio_clear_card(card, 0); |
1120 | qeth_clear_qdio_buffers(card); | 1175 | qeth_clear_qdio_buffers(card); |
1121 | } | 1176 | } |
@@ -1131,7 +1186,8 @@ static int qeth_l2_pm_suspend(struct ccwgroup_device *gdev) | |||
1131 | if (gdev->state == CCWGROUP_OFFLINE) | 1186 | if (gdev->state == CCWGROUP_OFFLINE) |
1132 | return 0; | 1187 | return 0; |
1133 | if (card->state == CARD_STATE_UP) { | 1188 | if (card->state == CARD_STATE_UP) { |
1134 | card->use_hard_stop = 1; | 1189 | if (card->info.hwtrap) |
1190 | qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM); | ||
1135 | __qeth_l2_set_offline(card->gdev, 1); | 1191 | __qeth_l2_set_offline(card->gdev, 1); |
1136 | } else | 1192 | } else |
1137 | __qeth_l2_set_offline(card->gdev, 0); | 1193 | __qeth_l2_set_offline(card->gdev, 0); |