diff options
| author | Frank Blaschka <frank.blaschka@de.ibm.com> | 2011-05-12 14:45:02 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2011-05-13 14:55:20 -0400 |
| commit | 1da74b1c10062eff5f67accb3bcb27fa329a55d6 (patch) | |
| tree | 3d26997561114d152b23e8c5be3fb0df4b356a50 | |
| parent | c5e631a8d4e305a68465b7334efe9875be8b7033 (diff) | |
qeth: add OSA concurrent hardware trap
This patch improves FFDC (first failure data capture) by requesting
a hardware trace in case the device driver, the hardware or a user
detects an error.
Signed-off-by: Frank Blaschka <frank.blaschka@de.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | drivers/s390/net/qeth_core.h | 18 | ||||
| -rw-r--r-- | drivers/s390/net/qeth_core_main.c | 148 | ||||
| -rw-r--r-- | drivers/s390/net/qeth_core_mpc.h | 9 | ||||
| -rw-r--r-- | drivers/s390/net/qeth_core_sys.c | 61 | ||||
| -rw-r--r-- | drivers/s390/net/qeth_l2_main.c | 16 | ||||
| -rw-r--r-- | drivers/s390/net/qeth_l3_main.c | 53 |
6 files changed, 268 insertions, 37 deletions
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index a2e67558a313..55c6aa1c9704 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h | |||
| @@ -631,6 +631,8 @@ struct qeth_card_info { | |||
| 631 | __u32 csum_mask; | 631 | __u32 csum_mask; |
| 632 | __u32 tx_csum_mask; | 632 | __u32 tx_csum_mask; |
| 633 | enum qeth_ipa_promisc_modes promisc_mode; | 633 | enum qeth_ipa_promisc_modes promisc_mode; |
| 634 | __u32 diagass_support; | ||
| 635 | __u32 hwtrap; | ||
| 634 | }; | 636 | }; |
| 635 | 637 | ||
| 636 | struct qeth_card_options { | 638 | struct qeth_card_options { |
| @@ -752,6 +754,14 @@ struct qeth_card_list_struct { | |||
| 752 | rwlock_t rwlock; | 754 | rwlock_t rwlock; |
| 753 | }; | 755 | }; |
| 754 | 756 | ||
| 757 | struct qeth_trap_id { | ||
| 758 | __u16 lparnr; | ||
| 759 | char vmname[8]; | ||
| 760 | __u8 chpid; | ||
| 761 | __u8 ssid; | ||
| 762 | __u16 devno; | ||
| 763 | } __packed; | ||
| 764 | |||
| 755 | /*some helper functions*/ | 765 | /*some helper functions*/ |
| 756 | #define QETH_CARD_IFNAME(card) (((card)->dev)? (card)->dev->name : "") | 766 | #define QETH_CARD_IFNAME(card) (((card)->dev)? (card)->dev->name : "") |
| 757 | 767 | ||
| @@ -786,6 +796,12 @@ static inline void qeth_put_buffer_pool_entry(struct qeth_card *card, | |||
| 786 | list_add_tail(&entry->list, &card->qdio.in_buf_pool.entry_list); | 796 | list_add_tail(&entry->list, &card->qdio.in_buf_pool.entry_list); |
| 787 | } | 797 | } |
| 788 | 798 | ||
| 799 | static inline int qeth_is_diagass_supported(struct qeth_card *card, | ||
| 800 | enum qeth_diags_cmds cmd) | ||
| 801 | { | ||
| 802 | return card->info.diagass_support & (__u32)cmd; | ||
| 803 | } | ||
| 804 | |||
| 789 | extern struct ccwgroup_driver qeth_l2_ccwgroup_driver; | 805 | extern struct ccwgroup_driver qeth_l2_ccwgroup_driver; |
| 790 | extern struct ccwgroup_driver qeth_l3_ccwgroup_driver; | 806 | extern struct ccwgroup_driver qeth_l3_ccwgroup_driver; |
| 791 | const char *qeth_get_cardname_short(struct qeth_card *); | 807 | const char *qeth_get_cardname_short(struct qeth_card *); |
| @@ -871,6 +887,8 @@ void qeth_dbf_longtext(debug_info_t *id, int level, char *text, ...); | |||
| 871 | int qeth_core_ethtool_get_settings(struct net_device *, struct ethtool_cmd *); | 887 | int qeth_core_ethtool_get_settings(struct net_device *, struct ethtool_cmd *); |
| 872 | int qeth_set_access_ctrl_online(struct qeth_card *card); | 888 | int qeth_set_access_ctrl_online(struct qeth_card *card); |
| 873 | int qeth_hdr_chk_and_bounce(struct sk_buff *, int); | 889 | int qeth_hdr_chk_and_bounce(struct sk_buff *, int); |
| 890 | int qeth_hw_trap(struct qeth_card *, enum qeth_diags_trap_action); | ||
| 891 | int qeth_query_ipassists(struct qeth_card *, enum qeth_prot_versions prot); | ||
| 874 | 892 | ||
| 875 | /* exports for OSN */ | 893 | /* exports for OSN */ |
| 876 | int qeth_osn_assist(struct net_device *, void *, int); | 894 | int qeth_osn_assist(struct net_device *, void *, int); |
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 4dffdbe9a674..92e37f728e54 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | 24 | ||
| 25 | #include <asm/ebcdic.h> | 25 | #include <asm/ebcdic.h> |
| 26 | #include <asm/io.h> | 26 | #include <asm/io.h> |
| 27 | #include <asm/sysinfo.h> | ||
| 27 | 28 | ||
| 28 | #include "qeth_core.h" | 29 | #include "qeth_core.h" |
| 29 | 30 | ||
| @@ -349,6 +350,8 @@ static struct qeth_ipa_cmd *qeth_check_ipa_data(struct qeth_card *card, | |||
| 349 | card->info.chpid); | 350 | card->info.chpid); |
| 350 | netif_carrier_on(card->dev); | 351 | netif_carrier_on(card->dev); |
| 351 | card->lan_online = 1; | 352 | card->lan_online = 1; |
| 353 | if (card->info.hwtrap) | ||
| 354 | card->info.hwtrap = 2; | ||
| 352 | qeth_schedule_recovery(card); | 355 | qeth_schedule_recovery(card); |
| 353 | return NULL; | 356 | return NULL; |
| 354 | case IPA_CMD_MODCCID: | 357 | case IPA_CMD_MODCCID: |
| @@ -2573,6 +2576,142 @@ int qeth_query_setadapterparms(struct qeth_card *card) | |||
| 2573 | } | 2576 | } |
| 2574 | EXPORT_SYMBOL_GPL(qeth_query_setadapterparms); | 2577 | EXPORT_SYMBOL_GPL(qeth_query_setadapterparms); |
| 2575 | 2578 | ||
| 2579 | static int qeth_query_ipassists_cb(struct qeth_card *card, | ||
| 2580 | struct qeth_reply *reply, unsigned long data) | ||
| 2581 | { | ||
| 2582 | struct qeth_ipa_cmd *cmd; | ||
| 2583 | |||
| 2584 | QETH_DBF_TEXT(SETUP, 2, "qipasscb"); | ||
| 2585 | |||
| 2586 | cmd = (struct qeth_ipa_cmd *) data; | ||
| 2587 | if (cmd->hdr.prot_version == QETH_PROT_IPV4) { | ||
| 2588 | card->options.ipa4.supported_funcs = cmd->hdr.ipa_supported; | ||
| 2589 | card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled; | ||
| 2590 | } else { | ||
| 2591 | card->options.ipa6.supported_funcs = cmd->hdr.ipa_supported; | ||
| 2592 | card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled; | ||
| 2593 | } | ||
| 2594 | QETH_DBF_TEXT(SETUP, 2, "suppenbl"); | ||
| 2595 | QETH_DBF_TEXT_(SETUP, 2, "%x", cmd->hdr.ipa_supported); | ||
| 2596 | QETH_DBF_TEXT_(SETUP, 2, "%x", cmd->hdr.ipa_enabled); | ||
| 2597 | return 0; | ||
| 2598 | } | ||
| 2599 | |||
| 2600 | int qeth_query_ipassists(struct qeth_card *card, enum qeth_prot_versions prot) | ||
| 2601 | { | ||
| 2602 | int rc; | ||
| 2603 | struct qeth_cmd_buffer *iob; | ||
| 2604 | |||
| 2605 | QETH_DBF_TEXT_(SETUP, 2, "qipassi%i", prot); | ||
| 2606 | iob = qeth_get_ipacmd_buffer(card, IPA_CMD_QIPASSIST, prot); | ||
| 2607 | rc = qeth_send_ipa_cmd(card, iob, qeth_query_ipassists_cb, NULL); | ||
| 2608 | return rc; | ||
| 2609 | } | ||
| 2610 | EXPORT_SYMBOL_GPL(qeth_query_ipassists); | ||
| 2611 | |||
| 2612 | static int qeth_query_setdiagass_cb(struct qeth_card *card, | ||
| 2613 | struct qeth_reply *reply, unsigned long data) | ||
| 2614 | { | ||
| 2615 | struct qeth_ipa_cmd *cmd; | ||
| 2616 | __u16 rc; | ||
| 2617 | |||
| 2618 | cmd = (struct qeth_ipa_cmd *)data; | ||
| 2619 | rc = cmd->hdr.return_code; | ||
| 2620 | if (rc) | ||
| 2621 | QETH_CARD_TEXT_(card, 2, "diagq:%x", rc); | ||
| 2622 | else | ||
| 2623 | card->info.diagass_support = cmd->data.diagass.ext; | ||
| 2624 | return 0; | ||
| 2625 | } | ||
| 2626 | |||
| 2627 | static int qeth_query_setdiagass(struct qeth_card *card) | ||
| 2628 | { | ||
| 2629 | struct qeth_cmd_buffer *iob; | ||
| 2630 | struct qeth_ipa_cmd *cmd; | ||
| 2631 | |||
| 2632 | QETH_DBF_TEXT(SETUP, 2, "qdiagass"); | ||
| 2633 | iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SET_DIAG_ASS, 0); | ||
| 2634 | cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); | ||
| 2635 | cmd->data.diagass.subcmd_len = 16; | ||
| 2636 | cmd->data.diagass.subcmd = QETH_DIAGS_CMD_QUERY; | ||
| 2637 | return qeth_send_ipa_cmd(card, iob, qeth_query_setdiagass_cb, NULL); | ||
| 2638 | } | ||
| 2639 | |||
| 2640 | static void qeth_get_trap_id(struct qeth_card *card, struct qeth_trap_id *tid) | ||
| 2641 | { | ||
| 2642 | unsigned long info = get_zeroed_page(GFP_KERNEL); | ||
| 2643 | struct sysinfo_2_2_2 *info222 = (struct sysinfo_2_2_2 *)info; | ||
| 2644 | struct sysinfo_3_2_2 *info322 = (struct sysinfo_3_2_2 *)info; | ||
| 2645 | struct ccw_dev_id ccwid; | ||
| 2646 | int level, rc; | ||
| 2647 | |||
| 2648 | tid->chpid = card->info.chpid; | ||
| 2649 | ccw_device_get_id(CARD_RDEV(card), &ccwid); | ||
| 2650 | tid->ssid = ccwid.ssid; | ||
| 2651 | tid->devno = ccwid.devno; | ||
| 2652 | if (!info) | ||
| 2653 | return; | ||
| 2654 | |||
| 2655 | rc = stsi(NULL, 0, 0, 0); | ||
| 2656 | if (rc == -ENOSYS) | ||
| 2657 | level = rc; | ||
| 2658 | else | ||
| 2659 | level = (((unsigned int) rc) >> 28); | ||
| 2660 | |||
| 2661 | if ((level >= 2) && (stsi(info222, 2, 2, 2) != -ENOSYS)) | ||
| 2662 | tid->lparnr = info222->lpar_number; | ||
| 2663 | |||
| 2664 | if ((level >= 3) && (stsi(info322, 3, 2, 2) != -ENOSYS)) { | ||
| 2665 | EBCASC(info322->vm[0].name, sizeof(info322->vm[0].name)); | ||
| 2666 | memcpy(tid->vmname, info322->vm[0].name, sizeof(tid->vmname)); | ||
| 2667 | } | ||
| 2668 | free_page(info); | ||
| 2669 | return; | ||
| 2670 | } | ||
| 2671 | |||
| 2672 | static int qeth_hw_trap_cb(struct qeth_card *card, | ||
| 2673 | struct qeth_reply *reply, unsigned long data) | ||
| 2674 | { | ||
| 2675 | struct qeth_ipa_cmd *cmd; | ||
| 2676 | __u16 rc; | ||
| 2677 | |||
| 2678 | cmd = (struct qeth_ipa_cmd *)data; | ||
| 2679 | rc = cmd->hdr.return_code; | ||
| 2680 | if (rc) | ||
| 2681 | QETH_CARD_TEXT_(card, 2, "trapc:%x", rc); | ||
| 2682 | return 0; | ||
| 2683 | } | ||
| 2684 | |||
| 2685 | int qeth_hw_trap(struct qeth_card *card, enum qeth_diags_trap_action action) | ||
| 2686 | { | ||
| 2687 | struct qeth_cmd_buffer *iob; | ||
| 2688 | struct qeth_ipa_cmd *cmd; | ||
| 2689 | |||
| 2690 | QETH_DBF_TEXT(SETUP, 2, "diagtrap"); | ||
| 2691 | iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SET_DIAG_ASS, 0); | ||
| 2692 | cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); | ||
| 2693 | cmd->data.diagass.subcmd_len = 80; | ||
| 2694 | cmd->data.diagass.subcmd = QETH_DIAGS_CMD_TRAP; | ||
| 2695 | cmd->data.diagass.type = 1; | ||
| 2696 | cmd->data.diagass.action = action; | ||
| 2697 | switch (action) { | ||
| 2698 | case QETH_DIAGS_TRAP_ARM: | ||
| 2699 | cmd->data.diagass.options = 0x0003; | ||
| 2700 | cmd->data.diagass.ext = 0x00010000 + | ||
| 2701 | sizeof(struct qeth_trap_id); | ||
| 2702 | qeth_get_trap_id(card, | ||
| 2703 | (struct qeth_trap_id *)cmd->data.diagass.cdata); | ||
| 2704 | break; | ||
| 2705 | case QETH_DIAGS_TRAP_DISARM: | ||
| 2706 | cmd->data.diagass.options = 0x0001; | ||
| 2707 | break; | ||
| 2708 | case QETH_DIAGS_TRAP_CAPTURE: | ||
| 2709 | break; | ||
| 2710 | } | ||
| 2711 | return qeth_send_ipa_cmd(card, iob, qeth_hw_trap_cb, NULL); | ||
| 2712 | } | ||
| 2713 | EXPORT_SYMBOL_GPL(qeth_hw_trap); | ||
| 2714 | |||
| 2576 | int qeth_check_qdio_errors(struct qeth_card *card, struct qdio_buffer *buf, | 2715 | int qeth_check_qdio_errors(struct qeth_card *card, struct qdio_buffer *buf, |
| 2577 | unsigned int qdio_error, const char *dbftext) | 2716 | unsigned int qdio_error, const char *dbftext) |
| 2578 | { | 2717 | { |
| @@ -3983,6 +4122,15 @@ retriable: | |||
| 3983 | QETH_DBF_TEXT_(SETUP, 2, "5err%d", rc); | 4122 | QETH_DBF_TEXT_(SETUP, 2, "5err%d", rc); |
| 3984 | goto out; | 4123 | goto out; |
| 3985 | } | 4124 | } |
| 4125 | |||
| 4126 | card->options.ipa4.supported_funcs = 0; | ||
| 4127 | card->options.adp.supported_funcs = 0; | ||
| 4128 | card->info.diagass_support = 0; | ||
| 4129 | qeth_query_ipassists(card, QETH_PROT_IPV4); | ||
| 4130 | if (qeth_is_supported(card, IPA_SETADAPTERPARMS)) | ||
| 4131 | qeth_query_setadapterparms(card); | ||
| 4132 | if (qeth_adp_supported(card, IPA_SETADP_SET_DIAG_ASSIST)) | ||
| 4133 | qeth_query_setdiagass(card); | ||
| 3986 | return 0; | 4134 | return 0; |
| 3987 | out: | 4135 | out: |
| 3988 | dev_warn(&card->gdev->dev, "The qeth device driver failed to recover " | 4136 | dev_warn(&card->gdev->dev, "The qeth device driver failed to recover " |
diff --git a/drivers/s390/net/qeth_core_mpc.h b/drivers/s390/net/qeth_core_mpc.h index d8988dca8129..e5a9d1c03839 100644 --- a/drivers/s390/net/qeth_core_mpc.h +++ b/drivers/s390/net/qeth_core_mpc.h | |||
| @@ -448,6 +448,12 @@ enum qeth_diags_trace_cmds { | |||
| 448 | QETH_DIAGS_CMD_TRACE_QUERY = 0x0010, | 448 | QETH_DIAGS_CMD_TRACE_QUERY = 0x0010, |
| 449 | }; | 449 | }; |
| 450 | 450 | ||
| 451 | enum qeth_diags_trap_action { | ||
| 452 | QETH_DIAGS_TRAP_ARM = 0x01, | ||
| 453 | QETH_DIAGS_TRAP_DISARM = 0x02, | ||
| 454 | QETH_DIAGS_TRAP_CAPTURE = 0x04, | ||
| 455 | }; | ||
| 456 | |||
| 451 | struct qeth_ipacmd_diagass { | 457 | struct qeth_ipacmd_diagass { |
| 452 | __u32 host_tod2; | 458 | __u32 host_tod2; |
| 453 | __u32:32; | 459 | __u32:32; |
| @@ -457,7 +463,8 @@ struct qeth_ipacmd_diagass { | |||
| 457 | __u8 type; | 463 | __u8 type; |
| 458 | __u8 action; | 464 | __u8 action; |
| 459 | __u16 options; | 465 | __u16 options; |
| 460 | __u32:32; | 466 | __u32 ext; |
| 467 | __u8 cdata[64]; | ||
| 461 | } __attribute__ ((packed)); | 468 | } __attribute__ ((packed)); |
| 462 | 469 | ||
| 463 | /* Header for each IPA command */ | 470 | /* Header for each IPA command */ |
diff --git a/drivers/s390/net/qeth_core_sys.c b/drivers/s390/net/qeth_core_sys.c index b5e967cf7e2d..0a8e86c1b0ea 100644 --- a/drivers/s390/net/qeth_core_sys.c +++ b/drivers/s390/net/qeth_core_sys.c | |||
| @@ -530,6 +530,66 @@ out: | |||
| 530 | static DEVICE_ATTR(isolation, 0644, qeth_dev_isolation_show, | 530 | static DEVICE_ATTR(isolation, 0644, qeth_dev_isolation_show, |
| 531 | qeth_dev_isolation_store); | 531 | qeth_dev_isolation_store); |
| 532 | 532 | ||
| 533 | static ssize_t qeth_hw_trap_show(struct device *dev, | ||
| 534 | struct device_attribute *attr, char *buf) | ||
| 535 | { | ||
| 536 | struct qeth_card *card = dev_get_drvdata(dev); | ||
| 537 | |||
| 538 | if (!card) | ||
| 539 | return -EINVAL; | ||
| 540 | if (card->info.hwtrap) | ||
| 541 | return snprintf(buf, 5, "arm\n"); | ||
| 542 | else | ||
| 543 | return snprintf(buf, 8, "disarm\n"); | ||
| 544 | } | ||
| 545 | |||
| 546 | static ssize_t qeth_hw_trap_store(struct device *dev, | ||
| 547 | struct device_attribute *attr, const char *buf, size_t count) | ||
| 548 | { | ||
| 549 | struct qeth_card *card = dev_get_drvdata(dev); | ||
| 550 | int rc = 0; | ||
| 551 | char *tmp, *curtoken; | ||
| 552 | int state = 0; | ||
| 553 | curtoken = (char *)buf; | ||
| 554 | |||
| 555 | if (!card) | ||
| 556 | return -EINVAL; | ||
| 557 | |||
| 558 | mutex_lock(&card->conf_mutex); | ||
| 559 | if (card->state == CARD_STATE_SOFTSETUP || card->state == CARD_STATE_UP) | ||
| 560 | state = 1; | ||
| 561 | tmp = strsep(&curtoken, "\n"); | ||
| 562 | |||
| 563 | if (!strcmp(tmp, "arm") && !card->info.hwtrap) { | ||
| 564 | if (state) { | ||
| 565 | if (qeth_is_diagass_supported(card, | ||
| 566 | QETH_DIAGS_CMD_TRAP)) { | ||
| 567 | rc = qeth_hw_trap(card, QETH_DIAGS_TRAP_ARM); | ||
| 568 | if (!rc) | ||
| 569 | card->info.hwtrap = 1; | ||
| 570 | } else | ||
| 571 | rc = -EINVAL; | ||
| 572 | } else | ||
| 573 | card->info.hwtrap = 1; | ||
| 574 | } else if (!strcmp(tmp, "disarm") && card->info.hwtrap) { | ||
| 575 | if (state) { | ||
| 576 | rc = qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM); | ||
| 577 | if (!rc) | ||
| 578 | card->info.hwtrap = 0; | ||
| 579 | } else | ||
| 580 | card->info.hwtrap = 0; | ||
| 581 | } else if (!strcmp(tmp, "trap") && state && card->info.hwtrap) | ||
| 582 | rc = qeth_hw_trap(card, QETH_DIAGS_TRAP_CAPTURE); | ||
| 583 | else | ||
| 584 | rc = -EINVAL; | ||
| 585 | |||
| 586 | mutex_unlock(&card->conf_mutex); | ||
| 587 | return rc ? rc : count; | ||
| 588 | } | ||
| 589 | |||
| 590 | static DEVICE_ATTR(hw_trap, 0644, qeth_hw_trap_show, | ||
| 591 | qeth_hw_trap_store); | ||
| 592 | |||
| 533 | static ssize_t qeth_dev_blkt_show(char *buf, struct qeth_card *card, int value) | 593 | static ssize_t qeth_dev_blkt_show(char *buf, struct qeth_card *card, int value) |
| 534 | { | 594 | { |
| 535 | 595 | ||
| @@ -653,6 +713,7 @@ static struct attribute *qeth_device_attrs[] = { | |||
| 653 | &dev_attr_performance_stats.attr, | 713 | &dev_attr_performance_stats.attr, |
| 654 | &dev_attr_layer2.attr, | 714 | &dev_attr_layer2.attr, |
| 655 | &dev_attr_isolation.attr, | 715 | &dev_attr_isolation.attr, |
| 716 | &dev_attr_hw_trap.attr, | ||
| 656 | NULL, | 717 | NULL, |
| 657 | }; | 718 | }; |
| 658 | 719 | ||
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 8ba4c7e1ee3a..b70b47fbd6cd 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c | |||
| @@ -876,6 +876,7 @@ static int qeth_l2_probe_device(struct ccwgroup_device *gdev) | |||
| 876 | INIT_LIST_HEAD(&card->vid_list); | 876 | INIT_LIST_HEAD(&card->vid_list); |
| 877 | INIT_LIST_HEAD(&card->mc_list); | 877 | INIT_LIST_HEAD(&card->mc_list); |
| 878 | card->options.layer2 = 1; | 878 | card->options.layer2 = 1; |
| 879 | card->info.hwtrap = 0; | ||
| 879 | card->discipline.start_poll = qeth_qdio_start_poll; | 880 | card->discipline.start_poll = qeth_qdio_start_poll; |
| 880 | card->discipline.input_handler = (qdio_handler_t *) | 881 | card->discipline.input_handler = (qdio_handler_t *) |
| 881 | qeth_qdio_input_handler; | 882 | qeth_qdio_input_handler; |
| @@ -994,6 +995,13 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) | |||
| 994 | if (card->info.type != QETH_CARD_TYPE_OSN) | 995 | if (card->info.type != QETH_CARD_TYPE_OSN) |
| 995 | qeth_l2_send_setmac(card, &card->dev->dev_addr[0]); | 996 | qeth_l2_send_setmac(card, &card->dev->dev_addr[0]); |
| 996 | 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 | |||
| 997 | card->state = CARD_STATE_HARDSETUP; | 1005 | card->state = CARD_STATE_HARDSETUP; |
| 998 | memset(&card->rx, 0, sizeof(struct qeth_rx)); | 1006 | memset(&card->rx, 0, sizeof(struct qeth_rx)); |
| 999 | qeth_print_status_message(card); | 1007 | qeth_print_status_message(card); |
| @@ -1092,6 +1100,10 @@ static int __qeth_l2_set_offline(struct ccwgroup_device *cgdev, | |||
| 1092 | if (card->dev && netif_carrier_ok(card->dev)) | 1100 | if (card->dev && netif_carrier_ok(card->dev)) |
| 1093 | netif_carrier_off(card->dev); | 1101 | netif_carrier_off(card->dev); |
| 1094 | 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 | } | ||
| 1095 | qeth_l2_stop_card(card, recovery_mode); | 1107 | qeth_l2_stop_card(card, recovery_mode); |
| 1096 | rc = ccw_device_set_offline(CARD_DDEV(card)); | 1108 | rc = ccw_device_set_offline(CARD_DDEV(card)); |
| 1097 | rc2 = ccw_device_set_offline(CARD_WDEV(card)); | 1109 | rc2 = ccw_device_set_offline(CARD_WDEV(card)); |
| @@ -1157,6 +1169,8 @@ static void __exit qeth_l2_exit(void) | |||
| 1157 | static void qeth_l2_shutdown(struct ccwgroup_device *gdev) | 1169 | static void qeth_l2_shutdown(struct ccwgroup_device *gdev) |
| 1158 | { | 1170 | { |
| 1159 | 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); | ||
| 1160 | qeth_qdio_clear_card(card, 0); | 1174 | qeth_qdio_clear_card(card, 0); |
| 1161 | qeth_clear_qdio_buffers(card); | 1175 | qeth_clear_qdio_buffers(card); |
| 1162 | } | 1176 | } |
| @@ -1172,6 +1186,8 @@ static int qeth_l2_pm_suspend(struct ccwgroup_device *gdev) | |||
| 1172 | if (gdev->state == CCWGROUP_OFFLINE) | 1186 | if (gdev->state == CCWGROUP_OFFLINE) |
| 1173 | return 0; | 1187 | return 0; |
| 1174 | if (card->state == CARD_STATE_UP) { | 1188 | if (card->state == CARD_STATE_UP) { |
| 1189 | if (card->info.hwtrap) | ||
| 1190 | qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM); | ||
| 1175 | __qeth_l2_set_offline(card->gdev, 1); | 1191 | __qeth_l2_set_offline(card->gdev, 1); |
| 1176 | } else | 1192 | } else |
| 1177 | __qeth_l2_set_offline(card->gdev, 0); | 1193 | __qeth_l2_set_offline(card->gdev, 0); |
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 18484b586a3e..bbe7e1c058ab 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c | |||
| @@ -1277,39 +1277,6 @@ static int qeth_l3_start_ipa_multicast(struct qeth_card *card) | |||
| 1277 | return rc; | 1277 | return rc; |
| 1278 | } | 1278 | } |
| 1279 | 1279 | ||
| 1280 | static int qeth_l3_query_ipassists_cb(struct qeth_card *card, | ||
| 1281 | struct qeth_reply *reply, unsigned long data) | ||
| 1282 | { | ||
| 1283 | struct qeth_ipa_cmd *cmd; | ||
| 1284 | |||
| 1285 | QETH_DBF_TEXT(SETUP, 2, "qipasscb"); | ||
| 1286 | |||
| 1287 | cmd = (struct qeth_ipa_cmd *) data; | ||
| 1288 | if (cmd->hdr.prot_version == QETH_PROT_IPV4) { | ||
| 1289 | card->options.ipa4.supported_funcs = cmd->hdr.ipa_supported; | ||
| 1290 | card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled; | ||
| 1291 | } else { | ||
| 1292 | card->options.ipa6.supported_funcs = cmd->hdr.ipa_supported; | ||
| 1293 | card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled; | ||
| 1294 | } | ||
| 1295 | QETH_DBF_TEXT(SETUP, 2, "suppenbl"); | ||
| 1296 | QETH_DBF_TEXT_(SETUP, 2, "%x", cmd->hdr.ipa_supported); | ||
| 1297 | QETH_DBF_TEXT_(SETUP, 2, "%x", cmd->hdr.ipa_enabled); | ||
| 1298 | return 0; | ||
| 1299 | } | ||
| 1300 | |||
| 1301 | static int qeth_l3_query_ipassists(struct qeth_card *card, | ||
| 1302 | enum qeth_prot_versions prot) | ||
| 1303 | { | ||
| 1304 | int rc; | ||
| 1305 | struct qeth_cmd_buffer *iob; | ||
| 1306 | |||
| 1307 | QETH_DBF_TEXT_(SETUP, 2, "qipassi%i", prot); | ||
| 1308 | iob = qeth_get_ipacmd_buffer(card, IPA_CMD_QIPASSIST, prot); | ||
| 1309 | rc = qeth_send_ipa_cmd(card, iob, qeth_l3_query_ipassists_cb, NULL); | ||
| 1310 | return rc; | ||
| 1311 | } | ||
| 1312 | |||
| 1313 | #ifdef CONFIG_QETH_IPV6 | 1280 | #ifdef CONFIG_QETH_IPV6 |
| 1314 | static int qeth_l3_softsetup_ipv6(struct qeth_card *card) | 1281 | static int qeth_l3_softsetup_ipv6(struct qeth_card *card) |
| 1315 | { | 1282 | { |
| @@ -1320,7 +1287,7 @@ static int qeth_l3_softsetup_ipv6(struct qeth_card *card) | |||
| 1320 | if (card->info.type == QETH_CARD_TYPE_IQD) | 1287 | if (card->info.type == QETH_CARD_TYPE_IQD) |
| 1321 | goto out; | 1288 | goto out; |
| 1322 | 1289 | ||
| 1323 | rc = qeth_l3_query_ipassists(card, QETH_PROT_IPV6); | 1290 | rc = qeth_query_ipassists(card, QETH_PROT_IPV6); |
| 1324 | if (rc) { | 1291 | if (rc) { |
| 1325 | dev_err(&card->gdev->dev, | 1292 | dev_err(&card->gdev->dev, |
| 1326 | "Activating IPv6 support for %s failed\n", | 1293 | "Activating IPv6 support for %s failed\n", |
| @@ -3371,6 +3338,7 @@ static int qeth_l3_probe_device(struct ccwgroup_device *gdev) | |||
| 3371 | 3338 | ||
| 3372 | qeth_l3_create_device_attributes(&gdev->dev); | 3339 | qeth_l3_create_device_attributes(&gdev->dev); |
| 3373 | card->options.layer2 = 0; | 3340 | card->options.layer2 = 0; |
| 3341 | card->info.hwtrap = 0; | ||
| 3374 | card->discipline.start_poll = qeth_qdio_start_poll; | 3342 | card->discipline.start_poll = qeth_qdio_start_poll; |
| 3375 | card->discipline.input_handler = (qdio_handler_t *) | 3343 | card->discipline.input_handler = (qdio_handler_t *) |
| 3376 | qeth_qdio_input_handler; | 3344 | qeth_qdio_input_handler; |
| @@ -3422,13 +3390,18 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) | |||
| 3422 | goto out_remove; | 3390 | goto out_remove; |
| 3423 | } | 3391 | } |
| 3424 | 3392 | ||
| 3425 | qeth_l3_query_ipassists(card, QETH_PROT_IPV4); | ||
| 3426 | |||
| 3427 | if (!card->dev && qeth_l3_setup_netdev(card)) { | 3393 | if (!card->dev && qeth_l3_setup_netdev(card)) { |
| 3428 | rc = -ENODEV; | 3394 | rc = -ENODEV; |
| 3429 | goto out_remove; | 3395 | goto out_remove; |
| 3430 | } | 3396 | } |
| 3431 | 3397 | ||
| 3398 | if (qeth_is_diagass_supported(card, QETH_DIAGS_CMD_TRAP)) { | ||
| 3399 | if (card->info.hwtrap && | ||
| 3400 | qeth_hw_trap(card, QETH_DIAGS_TRAP_ARM)) | ||
| 3401 | card->info.hwtrap = 0; | ||
| 3402 | } else | ||
| 3403 | card->info.hwtrap = 0; | ||
| 3404 | |||
| 3432 | card->state = CARD_STATE_HARDSETUP; | 3405 | card->state = CARD_STATE_HARDSETUP; |
| 3433 | memset(&card->rx, 0, sizeof(struct qeth_rx)); | 3406 | memset(&card->rx, 0, sizeof(struct qeth_rx)); |
| 3434 | qeth_print_status_message(card); | 3407 | qeth_print_status_message(card); |
| @@ -3530,6 +3503,10 @@ static int __qeth_l3_set_offline(struct ccwgroup_device *cgdev, | |||
| 3530 | if (card->dev && netif_carrier_ok(card->dev)) | 3503 | if (card->dev && netif_carrier_ok(card->dev)) |
| 3531 | netif_carrier_off(card->dev); | 3504 | netif_carrier_off(card->dev); |
| 3532 | recover_flag = card->state; | 3505 | recover_flag = card->state; |
| 3506 | if ((!recovery_mode && card->info.hwtrap) || card->info.hwtrap == 2) { | ||
| 3507 | qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM); | ||
| 3508 | card->info.hwtrap = 1; | ||
| 3509 | } | ||
| 3533 | qeth_l3_stop_card(card, recovery_mode); | 3510 | qeth_l3_stop_card(card, recovery_mode); |
| 3534 | rc = ccw_device_set_offline(CARD_DDEV(card)); | 3511 | rc = ccw_device_set_offline(CARD_DDEV(card)); |
| 3535 | rc2 = ccw_device_set_offline(CARD_WDEV(card)); | 3512 | rc2 = ccw_device_set_offline(CARD_WDEV(card)); |
| @@ -3585,6 +3562,8 @@ static int qeth_l3_recover(void *ptr) | |||
| 3585 | static void qeth_l3_shutdown(struct ccwgroup_device *gdev) | 3562 | static void qeth_l3_shutdown(struct ccwgroup_device *gdev) |
| 3586 | { | 3563 | { |
| 3587 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); | 3564 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); |
| 3565 | if ((gdev->state == CCWGROUP_ONLINE) && card->info.hwtrap) | ||
| 3566 | qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM); | ||
| 3588 | qeth_qdio_clear_card(card, 0); | 3567 | qeth_qdio_clear_card(card, 0); |
| 3589 | qeth_clear_qdio_buffers(card); | 3568 | qeth_clear_qdio_buffers(card); |
| 3590 | } | 3569 | } |
| @@ -3600,6 +3579,8 @@ static int qeth_l3_pm_suspend(struct ccwgroup_device *gdev) | |||
| 3600 | if (gdev->state == CCWGROUP_OFFLINE) | 3579 | if (gdev->state == CCWGROUP_OFFLINE) |
| 3601 | return 0; | 3580 | return 0; |
| 3602 | if (card->state == CARD_STATE_UP) { | 3581 | if (card->state == CARD_STATE_UP) { |
| 3582 | if (card->info.hwtrap) | ||
| 3583 | qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM); | ||
| 3603 | __qeth_l3_set_offline(card->gdev, 1); | 3584 | __qeth_l3_set_offline(card->gdev, 1); |
| 3604 | } else | 3585 | } else |
| 3605 | __qeth_l3_set_offline(card->gdev, 0); | 3586 | __qeth_l3_set_offline(card->gdev, 0); |
