aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/net/qeth_core_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/net/qeth_core_main.c')
-rw-r--r--drivers/s390/net/qeth_core_main.c241
1 files changed, 178 insertions, 63 deletions
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 5e20fba37bff..31ac53fa5cee 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -1982,14 +1982,6 @@ static void qeth_idx_read_cb(struct qeth_channel *channel,
goto out;
}
-/**
- * * temporary fix for microcode bug
- * * to revert it,replace OR by AND
- * */
- if ((!QETH_IDX_NO_PORTNAME_REQUIRED(iob->data)) ||
- (card->info.type == QETH_CARD_TYPE_OSD))
- card->info.portname_required = 1;
-
memcpy(&temp, QETH_IDX_ACT_FUNC_LEVEL(iob->data), 2);
if (temp != qeth_peer_func_level(card->info.func_level)) {
QETH_DBF_MESSAGE(2, "%s IDX_ACTIVATE on read channel: function "
@@ -2360,8 +2352,6 @@ static int qeth_ulp_enable(struct qeth_card *card)
&card->token.cm_connection_r, QETH_MPC_TOKEN_LENGTH);
memcpy(QETH_ULP_ENABLE_FILTER_TOKEN(iob->data),
&card->token.ulp_filter_w, QETH_MPC_TOKEN_LENGTH);
- memcpy(QETH_ULP_ENABLE_PORTNAME_AND_LL(iob->data),
- card->info.portname, 9);
rc = qeth_send_control_data(card, ULP_ENABLE_SIZE, iob,
qeth_ulp_enable_cb, NULL);
return rc;
@@ -2680,48 +2670,6 @@ out_qdio:
return rc;
}
-static void qeth_print_status_with_portname(struct qeth_card *card)
-{
- char dbf_text[15];
- int i;
-
- sprintf(dbf_text, "%s", card->info.portname + 1);
- for (i = 0; i < 8; i++)
- dbf_text[i] =
- (char) _ebcasc[(__u8) dbf_text[i]];
- dbf_text[8] = 0;
- dev_info(&card->gdev->dev, "Device is a%s card%s%s%s\n"
- "with link type %s (portname: %s)\n",
- qeth_get_cardname(card),
- (card->info.mcl_level[0]) ? " (level: " : "",
- (card->info.mcl_level[0]) ? card->info.mcl_level : "",
- (card->info.mcl_level[0]) ? ")" : "",
- qeth_get_cardname_short(card),
- dbf_text);
-
-}
-
-static void qeth_print_status_no_portname(struct qeth_card *card)
-{
- if (card->info.portname[0])
- dev_info(&card->gdev->dev, "Device is a%s "
- "card%s%s%s\nwith link type %s "
- "(no portname needed by interface).\n",
- qeth_get_cardname(card),
- (card->info.mcl_level[0]) ? " (level: " : "",
- (card->info.mcl_level[0]) ? card->info.mcl_level : "",
- (card->info.mcl_level[0]) ? ")" : "",
- qeth_get_cardname_short(card));
- else
- dev_info(&card->gdev->dev, "Device is a%s "
- "card%s%s%s\nwith link type %s.\n",
- qeth_get_cardname(card),
- (card->info.mcl_level[0]) ? " (level: " : "",
- (card->info.mcl_level[0]) ? card->info.mcl_level : "",
- (card->info.mcl_level[0]) ? ")" : "",
- qeth_get_cardname_short(card));
-}
-
void qeth_print_status_message(struct qeth_card *card)
{
switch (card->info.type) {
@@ -2758,10 +2706,13 @@ void qeth_print_status_message(struct qeth_card *card)
default:
memset(&card->info.mcl_level[0], 0, QETH_MCL_LENGTH + 1);
}
- if (card->info.portname_required)
- qeth_print_status_with_portname(card);
- else
- qeth_print_status_no_portname(card);
+ dev_info(&card->gdev->dev,
+ "Device is a%s card%s%s%s\nwith link type %s.\n",
+ qeth_get_cardname(card),
+ (card->info.mcl_level[0]) ? " (level: " : "",
+ (card->info.mcl_level[0]) ? card->info.mcl_level : "",
+ (card->info.mcl_level[0]) ? ")" : "",
+ qeth_get_cardname_short(card));
}
EXPORT_SYMBOL_GPL(qeth_print_status_message);
@@ -5027,13 +4978,11 @@ static void qeth_core_free_card(struct qeth_card *card)
void qeth_trace_features(struct qeth_card *card)
{
QETH_CARD_TEXT(card, 2, "features");
- QETH_CARD_TEXT_(card, 2, "%x", card->options.ipa4.supported_funcs);
- QETH_CARD_TEXT_(card, 2, "%x", card->options.ipa4.enabled_funcs);
- QETH_CARD_TEXT_(card, 2, "%x", card->options.ipa6.supported_funcs);
- QETH_CARD_TEXT_(card, 2, "%x", card->options.ipa6.enabled_funcs);
- QETH_CARD_TEXT_(card, 2, "%x", card->options.adp.supported_funcs);
- QETH_CARD_TEXT_(card, 2, "%x", card->options.adp.enabled_funcs);
- QETH_CARD_TEXT_(card, 2, "%x", card->info.diagass_support);
+ QETH_CARD_HEX(card, 2, &card->options.ipa4, sizeof(card->options.ipa4));
+ QETH_CARD_HEX(card, 2, &card->options.ipa6, sizeof(card->options.ipa6));
+ QETH_CARD_HEX(card, 2, &card->options.adp, sizeof(card->options.adp));
+ QETH_CARD_HEX(card, 2, &card->info.diagass_support,
+ sizeof(card->info.diagass_support));
}
EXPORT_SYMBOL_GPL(qeth_trace_features);
@@ -5132,6 +5081,7 @@ retriable:
}
card->options.ipa4.supported_funcs = 0;
+ card->options.ipa6.supported_funcs = 0;
card->options.adp.supported_funcs = 0;
card->options.sbp.supported_funcs = 0;
card->info.diagass_support = 0;
@@ -5317,6 +5267,102 @@ no_mem:
}
EXPORT_SYMBOL_GPL(qeth_core_get_next_skb);
+static int qeth_setassparms_cb(struct qeth_card *card,
+ struct qeth_reply *reply, unsigned long data)
+{
+ struct qeth_ipa_cmd *cmd;
+
+ QETH_CARD_TEXT(card, 4, "defadpcb");
+
+ cmd = (struct qeth_ipa_cmd *) data;
+ if (cmd->hdr.return_code == 0) {
+ cmd->hdr.return_code = cmd->data.setassparms.hdr.return_code;
+ if (cmd->hdr.prot_version == QETH_PROT_IPV4)
+ card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled;
+ if (cmd->hdr.prot_version == QETH_PROT_IPV6)
+ card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled;
+ }
+ if (cmd->data.setassparms.hdr.assist_no == IPA_INBOUND_CHECKSUM &&
+ cmd->data.setassparms.hdr.command_code == IPA_CMD_ASS_START) {
+ card->info.csum_mask = cmd->data.setassparms.data.flags_32bit;
+ QETH_CARD_TEXT_(card, 3, "csum:%d", card->info.csum_mask);
+ }
+ if (cmd->data.setassparms.hdr.assist_no == IPA_OUTBOUND_CHECKSUM &&
+ cmd->data.setassparms.hdr.command_code == IPA_CMD_ASS_START) {
+ card->info.tx_csum_mask =
+ cmd->data.setassparms.data.flags_32bit;
+ QETH_CARD_TEXT_(card, 3, "tcsu:%d", card->info.tx_csum_mask);
+ }
+
+ return 0;
+}
+
+static struct qeth_cmd_buffer *qeth_get_setassparms_cmd(struct qeth_card *card,
+ enum qeth_ipa_funcs ipa_func,
+ __u16 cmd_code, __u16 len,
+ enum qeth_prot_versions prot)
+{
+ struct qeth_cmd_buffer *iob;
+ struct qeth_ipa_cmd *cmd;
+
+ QETH_CARD_TEXT(card, 4, "getasscm");
+ iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SETASSPARMS, prot);
+
+ if (iob) {
+ cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+ cmd->data.setassparms.hdr.assist_no = ipa_func;
+ cmd->data.setassparms.hdr.length = 8 + len;
+ cmd->data.setassparms.hdr.command_code = cmd_code;
+ cmd->data.setassparms.hdr.return_code = 0;
+ cmd->data.setassparms.hdr.seq_no = 0;
+ }
+
+ return iob;
+}
+
+int qeth_send_setassparms(struct qeth_card *card,
+ struct qeth_cmd_buffer *iob, __u16 len, long data,
+ int (*reply_cb)(struct qeth_card *,
+ struct qeth_reply *, unsigned long),
+ void *reply_param)
+{
+ int rc;
+ struct qeth_ipa_cmd *cmd;
+
+ QETH_CARD_TEXT(card, 4, "sendassp");
+
+ cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+ if (len <= sizeof(__u32))
+ cmd->data.setassparms.data.flags_32bit = (__u32) data;
+ else /* (len > sizeof(__u32)) */
+ memcpy(&cmd->data.setassparms.data, (void *) data, len);
+
+ rc = qeth_send_ipa_cmd(card, iob, reply_cb, reply_param);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(qeth_send_setassparms);
+
+int qeth_send_simple_setassparms(struct qeth_card *card,
+ enum qeth_ipa_funcs ipa_func,
+ __u16 cmd_code, long data)
+{
+ int rc;
+ int length = 0;
+ struct qeth_cmd_buffer *iob;
+
+ QETH_CARD_TEXT(card, 4, "simassp4");
+ if (data)
+ length = sizeof(__u32);
+ iob = qeth_get_setassparms_cmd(card, ipa_func, cmd_code,
+ length, QETH_PROT_IPV4);
+ if (!iob)
+ return -ENOMEM;
+ rc = qeth_send_setassparms(card, iob, length, data,
+ qeth_setassparms_cb, NULL);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(qeth_send_simple_setassparms);
+
static void qeth_unregister_dbf_views(void)
{
int x;
@@ -6003,6 +6049,75 @@ int qeth_core_ethtool_get_settings(struct net_device *netdev,
}
EXPORT_SYMBOL_GPL(qeth_core_ethtool_get_settings);
+static int qeth_send_checksum_command(struct qeth_card *card)
+{
+ int rc;
+
+ rc = qeth_send_simple_setassparms(card, IPA_INBOUND_CHECKSUM,
+ IPA_CMD_ASS_START, 0);
+ if (rc) {
+ dev_warn(&card->gdev->dev, "Starting HW checksumming for %s "
+ "failed, using SW checksumming\n",
+ QETH_CARD_IFNAME(card));
+ return rc;
+ }
+ rc = qeth_send_simple_setassparms(card, IPA_INBOUND_CHECKSUM,
+ IPA_CMD_ASS_ENABLE,
+ card->info.csum_mask);
+ if (rc) {
+ dev_warn(&card->gdev->dev, "Enabling HW checksumming for %s "
+ "failed, using SW checksumming\n",
+ QETH_CARD_IFNAME(card));
+ return rc;
+ }
+ return 0;
+}
+
+int qeth_set_rx_csum(struct qeth_card *card, int on)
+{
+ int rc;
+
+ if (on) {
+ rc = qeth_send_checksum_command(card);
+ if (rc)
+ return -EIO;
+ dev_info(&card->gdev->dev,
+ "HW Checksumming (inbound) enabled\n");
+ } else {
+ rc = qeth_send_simple_setassparms(card,
+ IPA_INBOUND_CHECKSUM, IPA_CMD_ASS_STOP, 0);
+ if (rc)
+ return -EIO;
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(qeth_set_rx_csum);
+
+int qeth_start_ipa_tx_checksum(struct qeth_card *card)
+{
+ int rc = 0;
+
+ if (!qeth_is_supported(card, IPA_OUTBOUND_CHECKSUM))
+ return rc;
+ rc = qeth_send_simple_setassparms(card, IPA_OUTBOUND_CHECKSUM,
+ IPA_CMD_ASS_START, 0);
+ if (rc)
+ goto err_out;
+ rc = qeth_send_simple_setassparms(card, IPA_OUTBOUND_CHECKSUM,
+ IPA_CMD_ASS_ENABLE,
+ card->info.tx_csum_mask);
+ if (rc)
+ goto err_out;
+
+ dev_info(&card->gdev->dev, "HW TX Checksumming enabled\n");
+ return rc;
+err_out:
+ dev_warn(&card->gdev->dev, "Enabling HW TX checksumming for %s "
+ "failed, using SW TX checksumming\n", QETH_CARD_IFNAME(card));
+ return rc;
+}
+EXPORT_SYMBOL_GPL(qeth_start_ipa_tx_checksum);
+
static int __init qeth_core_init(void)
{
int rc;