aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/net
diff options
context:
space:
mode:
authorFrank Blaschka <frank.blaschka@de.ibm.com>2011-05-12 14:45:02 -0400
committerDavid S. Miller <davem@davemloft.net>2011-05-13 14:55:20 -0400
commit1da74b1c10062eff5f67accb3bcb27fa329a55d6 (patch)
tree3d26997561114d152b23e8c5be3fb0df4b356a50 /drivers/s390/net
parentc5e631a8d4e305a68465b7334efe9875be8b7033 (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>
Diffstat (limited to 'drivers/s390/net')
-rw-r--r--drivers/s390/net/qeth_core.h18
-rw-r--r--drivers/s390/net/qeth_core_main.c148
-rw-r--r--drivers/s390/net/qeth_core_mpc.h9
-rw-r--r--drivers/s390/net/qeth_core_sys.c61
-rw-r--r--drivers/s390/net/qeth_l2_main.c16
-rw-r--r--drivers/s390/net/qeth_l3_main.c53
6 files changed, 268 insertions, 37 deletions
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h
index a2e67558a31..55c6aa1c970 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
636struct qeth_card_options { 638struct qeth_card_options {
@@ -752,6 +754,14 @@ struct qeth_card_list_struct {
752 rwlock_t rwlock; 754 rwlock_t rwlock;
753}; 755};
754 756
757struct 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
799static 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
789extern struct ccwgroup_driver qeth_l2_ccwgroup_driver; 805extern struct ccwgroup_driver qeth_l2_ccwgroup_driver;
790extern struct ccwgroup_driver qeth_l3_ccwgroup_driver; 806extern struct ccwgroup_driver qeth_l3_ccwgroup_driver;
791const char *qeth_get_cardname_short(struct qeth_card *); 807const char *qeth_get_cardname_short(struct qeth_card *);
@@ -871,6 +887,8 @@ void qeth_dbf_longtext(debug_info_t *id, int level, char *text, ...);
871int qeth_core_ethtool_get_settings(struct net_device *, struct ethtool_cmd *); 887int qeth_core_ethtool_get_settings(struct net_device *, struct ethtool_cmd *);
872int qeth_set_access_ctrl_online(struct qeth_card *card); 888int qeth_set_access_ctrl_online(struct qeth_card *card);
873int qeth_hdr_chk_and_bounce(struct sk_buff *, int); 889int qeth_hdr_chk_and_bounce(struct sk_buff *, int);
890int qeth_hw_trap(struct qeth_card *, enum qeth_diags_trap_action);
891int qeth_query_ipassists(struct qeth_card *, enum qeth_prot_versions prot);
874 892
875/* exports for OSN */ 893/* exports for OSN */
876int qeth_osn_assist(struct net_device *, void *, int); 894int 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 4dffdbe9a67..92e37f728e5 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}
2574EXPORT_SYMBOL_GPL(qeth_query_setadapterparms); 2577EXPORT_SYMBOL_GPL(qeth_query_setadapterparms);
2575 2578
2579static 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
2600int 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}
2610EXPORT_SYMBOL_GPL(qeth_query_ipassists);
2611
2612static 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
2627static 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
2640static 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
2672static 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
2685int 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}
2713EXPORT_SYMBOL_GPL(qeth_hw_trap);
2714
2576int qeth_check_qdio_errors(struct qeth_card *card, struct qdio_buffer *buf, 2715int 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;
3987out: 4135out:
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 d8988dca812..e5a9d1c0383 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
451enum qeth_diags_trap_action {
452 QETH_DIAGS_TRAP_ARM = 0x01,
453 QETH_DIAGS_TRAP_DISARM = 0x02,
454 QETH_DIAGS_TRAP_CAPTURE = 0x04,
455};
456
451struct qeth_ipacmd_diagass { 457struct 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 b5e967cf7e2..0a8e86c1b0e 100644
--- a/drivers/s390/net/qeth_core_sys.c
+++ b/drivers/s390/net/qeth_core_sys.c
@@ -530,6 +530,66 @@ out:
530static DEVICE_ATTR(isolation, 0644, qeth_dev_isolation_show, 530static DEVICE_ATTR(isolation, 0644, qeth_dev_isolation_show,
531 qeth_dev_isolation_store); 531 qeth_dev_isolation_store);
532 532
533static 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
546static 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
590static DEVICE_ATTR(hw_trap, 0644, qeth_hw_trap_show,
591 qeth_hw_trap_store);
592
533static ssize_t qeth_dev_blkt_show(char *buf, struct qeth_card *card, int value) 593static 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 8ba4c7e1ee3..b70b47fbd6c 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)
1157static void qeth_l2_shutdown(struct ccwgroup_device *gdev) 1169static 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 18484b586a3..bbe7e1c058a 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
1280static 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
1301static 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
1314static int qeth_l3_softsetup_ipv6(struct qeth_card *card) 1281static 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)
3585static void qeth_l3_shutdown(struct ccwgroup_device *gdev) 3562static 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);