|
@@ -24,6 +24,7 @@
|
|
|
|
|
|
#include <asm/ebcdic.h>
|
|
|
#include <asm/io.h>
|
|
|
+#include <asm/sysinfo.h>
|
|
|
|
|
|
#include "qeth_core.h"
|
|
|
|
|
@@ -349,6 +350,8 @@ static struct qeth_ipa_cmd *qeth_check_ipa_data(struct qeth_card *card,
|
|
|
card->info.chpid);
|
|
|
netif_carrier_on(card->dev);
|
|
|
card->lan_online = 1;
|
|
|
+ if (card->info.hwtrap)
|
|
|
+ card->info.hwtrap = 2;
|
|
|
qeth_schedule_recovery(card);
|
|
|
return NULL;
|
|
|
case IPA_CMD_MODCCID:
|
|
@@ -2573,6 +2576,142 @@ int qeth_query_setadapterparms(struct qeth_card *card)
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(qeth_query_setadapterparms);
|
|
|
|
|
|
+static int qeth_query_ipassists_cb(struct qeth_card *card,
|
|
|
+ struct qeth_reply *reply, unsigned long data)
|
|
|
+{
|
|
|
+ struct qeth_ipa_cmd *cmd;
|
|
|
+
|
|
|
+ QETH_DBF_TEXT(SETUP, 2, "qipasscb");
|
|
|
+
|
|
|
+ cmd = (struct qeth_ipa_cmd *) data;
|
|
|
+ if (cmd->hdr.prot_version == QETH_PROT_IPV4) {
|
|
|
+ card->options.ipa4.supported_funcs = cmd->hdr.ipa_supported;
|
|
|
+ card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled;
|
|
|
+ } else {
|
|
|
+ card->options.ipa6.supported_funcs = cmd->hdr.ipa_supported;
|
|
|
+ card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled;
|
|
|
+ }
|
|
|
+ QETH_DBF_TEXT(SETUP, 2, "suppenbl");
|
|
|
+ QETH_DBF_TEXT_(SETUP, 2, "%x", cmd->hdr.ipa_supported);
|
|
|
+ QETH_DBF_TEXT_(SETUP, 2, "%x", cmd->hdr.ipa_enabled);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+int qeth_query_ipassists(struct qeth_card *card, enum qeth_prot_versions prot)
|
|
|
+{
|
|
|
+ int rc;
|
|
|
+ struct qeth_cmd_buffer *iob;
|
|
|
+
|
|
|
+ QETH_DBF_TEXT_(SETUP, 2, "qipassi%i", prot);
|
|
|
+ iob = qeth_get_ipacmd_buffer(card, IPA_CMD_QIPASSIST, prot);
|
|
|
+ rc = qeth_send_ipa_cmd(card, iob, qeth_query_ipassists_cb, NULL);
|
|
|
+ return rc;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(qeth_query_ipassists);
|
|
|
+
|
|
|
+static int qeth_query_setdiagass_cb(struct qeth_card *card,
|
|
|
+ struct qeth_reply *reply, unsigned long data)
|
|
|
+{
|
|
|
+ struct qeth_ipa_cmd *cmd;
|
|
|
+ __u16 rc;
|
|
|
+
|
|
|
+ cmd = (struct qeth_ipa_cmd *)data;
|
|
|
+ rc = cmd->hdr.return_code;
|
|
|
+ if (rc)
|
|
|
+ QETH_CARD_TEXT_(card, 2, "diagq:%x", rc);
|
|
|
+ else
|
|
|
+ card->info.diagass_support = cmd->data.diagass.ext;
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int qeth_query_setdiagass(struct qeth_card *card)
|
|
|
+{
|
|
|
+ struct qeth_cmd_buffer *iob;
|
|
|
+ struct qeth_ipa_cmd *cmd;
|
|
|
+
|
|
|
+ QETH_DBF_TEXT(SETUP, 2, "qdiagass");
|
|
|
+ iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SET_DIAG_ASS, 0);
|
|
|
+ cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
|
|
|
+ cmd->data.diagass.subcmd_len = 16;
|
|
|
+ cmd->data.diagass.subcmd = QETH_DIAGS_CMD_QUERY;
|
|
|
+ return qeth_send_ipa_cmd(card, iob, qeth_query_setdiagass_cb, NULL);
|
|
|
+}
|
|
|
+
|
|
|
+static void qeth_get_trap_id(struct qeth_card *card, struct qeth_trap_id *tid)
|
|
|
+{
|
|
|
+ unsigned long info = get_zeroed_page(GFP_KERNEL);
|
|
|
+ struct sysinfo_2_2_2 *info222 = (struct sysinfo_2_2_2 *)info;
|
|
|
+ struct sysinfo_3_2_2 *info322 = (struct sysinfo_3_2_2 *)info;
|
|
|
+ struct ccw_dev_id ccwid;
|
|
|
+ int level, rc;
|
|
|
+
|
|
|
+ tid->chpid = card->info.chpid;
|
|
|
+ ccw_device_get_id(CARD_RDEV(card), &ccwid);
|
|
|
+ tid->ssid = ccwid.ssid;
|
|
|
+ tid->devno = ccwid.devno;
|
|
|
+ if (!info)
|
|
|
+ return;
|
|
|
+
|
|
|
+ rc = stsi(NULL, 0, 0, 0);
|
|
|
+ if (rc == -ENOSYS)
|
|
|
+ level = rc;
|
|
|
+ else
|
|
|
+ level = (((unsigned int) rc) >> 28);
|
|
|
+
|
|
|
+ if ((level >= 2) && (stsi(info222, 2, 2, 2) != -ENOSYS))
|
|
|
+ tid->lparnr = info222->lpar_number;
|
|
|
+
|
|
|
+ if ((level >= 3) && (stsi(info322, 3, 2, 2) != -ENOSYS)) {
|
|
|
+ EBCASC(info322->vm[0].name, sizeof(info322->vm[0].name));
|
|
|
+ memcpy(tid->vmname, info322->vm[0].name, sizeof(tid->vmname));
|
|
|
+ }
|
|
|
+ free_page(info);
|
|
|
+ return;
|
|
|
+}
|
|
|
+
|
|
|
+static int qeth_hw_trap_cb(struct qeth_card *card,
|
|
|
+ struct qeth_reply *reply, unsigned long data)
|
|
|
+{
|
|
|
+ struct qeth_ipa_cmd *cmd;
|
|
|
+ __u16 rc;
|
|
|
+
|
|
|
+ cmd = (struct qeth_ipa_cmd *)data;
|
|
|
+ rc = cmd->hdr.return_code;
|
|
|
+ if (rc)
|
|
|
+ QETH_CARD_TEXT_(card, 2, "trapc:%x", rc);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+int qeth_hw_trap(struct qeth_card *card, enum qeth_diags_trap_action action)
|
|
|
+{
|
|
|
+ struct qeth_cmd_buffer *iob;
|
|
|
+ struct qeth_ipa_cmd *cmd;
|
|
|
+
|
|
|
+ QETH_DBF_TEXT(SETUP, 2, "diagtrap");
|
|
|
+ iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SET_DIAG_ASS, 0);
|
|
|
+ cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
|
|
|
+ cmd->data.diagass.subcmd_len = 80;
|
|
|
+ cmd->data.diagass.subcmd = QETH_DIAGS_CMD_TRAP;
|
|
|
+ cmd->data.diagass.type = 1;
|
|
|
+ cmd->data.diagass.action = action;
|
|
|
+ switch (action) {
|
|
|
+ case QETH_DIAGS_TRAP_ARM:
|
|
|
+ cmd->data.diagass.options = 0x0003;
|
|
|
+ cmd->data.diagass.ext = 0x00010000 +
|
|
|
+ sizeof(struct qeth_trap_id);
|
|
|
+ qeth_get_trap_id(card,
|
|
|
+ (struct qeth_trap_id *)cmd->data.diagass.cdata);
|
|
|
+ break;
|
|
|
+ case QETH_DIAGS_TRAP_DISARM:
|
|
|
+ cmd->data.diagass.options = 0x0001;
|
|
|
+ break;
|
|
|
+ case QETH_DIAGS_TRAP_CAPTURE:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ return qeth_send_ipa_cmd(card, iob, qeth_hw_trap_cb, NULL);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(qeth_hw_trap);
|
|
|
+
|
|
|
int qeth_check_qdio_errors(struct qeth_card *card, struct qdio_buffer *buf,
|
|
|
unsigned int qdio_error, const char *dbftext)
|
|
|
{
|
|
@@ -3983,6 +4122,15 @@ retriable:
|
|
|
QETH_DBF_TEXT_(SETUP, 2, "5err%d", rc);
|
|
|
goto out;
|
|
|
}
|
|
|
+
|
|
|
+ card->options.ipa4.supported_funcs = 0;
|
|
|
+ card->options.adp.supported_funcs = 0;
|
|
|
+ card->info.diagass_support = 0;
|
|
|
+ qeth_query_ipassists(card, QETH_PROT_IPV4);
|
|
|
+ if (qeth_is_supported(card, IPA_SETADAPTERPARMS))
|
|
|
+ qeth_query_setadapterparms(card);
|
|
|
+ if (qeth_adp_supported(card, IPA_SETADP_SET_DIAG_ASSIST))
|
|
|
+ qeth_query_setdiagass(card);
|
|
|
return 0;
|
|
|
out:
|
|
|
dev_warn(&card->gdev->dev, "The qeth device driver failed to recover "
|