summaryrefslogtreecommitdiffstats
path: root/kernel/drivers/s390/net
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/drivers/s390/net')
-rw-r--r--kernel/drivers/s390/net/lcs.c2
-rw-r--r--kernel/drivers/s390/net/netiucv.c21
-rw-r--r--kernel/drivers/s390/net/qeth_core.h32
-rw-r--r--kernel/drivers/s390/net/qeth_core_main.c244
-rw-r--r--kernel/drivers/s390/net/qeth_core_mpc.c3
-rw-r--r--kernel/drivers/s390/net/qeth_core_mpc.h3
-rw-r--r--kernel/drivers/s390/net/qeth_core_sys.c43
-rw-r--r--kernel/drivers/s390/net/qeth_l2_main.c355
-rw-r--r--kernel/drivers/s390/net/qeth_l2_sys.c76
-rw-r--r--kernel/drivers/s390/net/qeth_l3_main.c170
-rw-r--r--kernel/drivers/s390/net/smsgiucv.c5
11 files changed, 585 insertions, 369 deletions
diff --git a/kernel/drivers/s390/net/lcs.c b/kernel/drivers/s390/net/lcs.c
index 00b7d9c9f..2f5b518b0 100644
--- a/kernel/drivers/s390/net/lcs.c
+++ b/kernel/drivers/s390/net/lcs.c
@@ -2150,7 +2150,7 @@ lcs_new_device(struct ccwgroup_device *ccwgdev)
rc = lcs_detect(card);
if (rc) {
LCS_DBF_TEXT(2, setup, "dtctfail");
- dev_err(&card->dev->dev,
+ dev_err(&ccwgdev->dev,
"Detecting a network adapter for LCS devices"
" failed with rc=%d (0x%x)\n", rc, rc);
lcs_stopcard(card);
diff --git a/kernel/drivers/s390/net/netiucv.c b/kernel/drivers/s390/net/netiucv.c
index 33f7040d7..0ba3a2f81 100644
--- a/kernel/drivers/s390/net/netiucv.c
+++ b/kernel/drivers/s390/net/netiucv.c
@@ -149,12 +149,11 @@ static struct device_driver netiucv_driver = {
.pm = &netiucv_pm_ops,
};
-static int netiucv_callback_connreq(struct iucv_path *,
- u8 ipvmid[8], u8 ipuser[16]);
-static void netiucv_callback_connack(struct iucv_path *, u8 ipuser[16]);
-static void netiucv_callback_connrej(struct iucv_path *, u8 ipuser[16]);
-static void netiucv_callback_connsusp(struct iucv_path *, u8 ipuser[16]);
-static void netiucv_callback_connres(struct iucv_path *, u8 ipuser[16]);
+static int netiucv_callback_connreq(struct iucv_path *, u8 *, u8 *);
+static void netiucv_callback_connack(struct iucv_path *, u8 *);
+static void netiucv_callback_connrej(struct iucv_path *, u8 *);
+static void netiucv_callback_connsusp(struct iucv_path *, u8 *);
+static void netiucv_callback_connres(struct iucv_path *, u8 *);
static void netiucv_callback_rx(struct iucv_path *, struct iucv_message *);
static void netiucv_callback_txdone(struct iucv_path *, struct iucv_message *);
@@ -556,8 +555,8 @@ static void netiucv_callback_connack(struct iucv_path *path, u8 ipuser[16])
fsm_event(conn->fsm, CONN_EVENT_CONN_ACK, conn);
}
-static int netiucv_callback_connreq(struct iucv_path *path,
- u8 ipvmid[8], u8 ipuser[16])
+static int netiucv_callback_connreq(struct iucv_path *path, u8 *ipvmid,
+ u8 *ipuser)
{
struct iucv_connection *conn = path->private;
struct iucv_event ev;
@@ -587,21 +586,21 @@ static int netiucv_callback_connreq(struct iucv_path *path,
return rc;
}
-static void netiucv_callback_connrej(struct iucv_path *path, u8 ipuser[16])
+static void netiucv_callback_connrej(struct iucv_path *path, u8 *ipuser)
{
struct iucv_connection *conn = path->private;
fsm_event(conn->fsm, CONN_EVENT_CONN_REJ, conn);
}
-static void netiucv_callback_connsusp(struct iucv_path *path, u8 ipuser[16])
+static void netiucv_callback_connsusp(struct iucv_path *path, u8 *ipuser)
{
struct iucv_connection *conn = path->private;
fsm_event(conn->fsm, CONN_EVENT_CONN_SUS, conn);
}
-static void netiucv_callback_connres(struct iucv_path *path, u8 ipuser[16])
+static void netiucv_callback_connres(struct iucv_path *path, u8 *ipuser)
{
struct iucv_connection *conn = path->private;
diff --git a/kernel/drivers/s390/net/qeth_core.h b/kernel/drivers/s390/net/qeth_core.h
index 3abac0288..1766a20eb 100644
--- a/kernel/drivers/s390/net/qeth_core.h
+++ b/kernel/drivers/s390/net/qeth_core.h
@@ -18,6 +18,7 @@
#include <linux/bitops.h>
#include <linux/seq_file.h>
#include <linux/ethtool.h>
+#include <linux/hashtable.h>
#include <net/ipv6.h>
#include <net/if_inet6.h>
@@ -175,6 +176,8 @@ struct qeth_sbp_info {
__u32 supported_funcs;
enum qeth_sbp_roles role;
__u32 hostnotification:1;
+ __u32 reflect_promisc:1;
+ __u32 reflect_promisc_primary:1;
};
static inline int qeth_is_ipa_supported(struct qeth_ipa_info *ipa,
@@ -661,9 +664,7 @@ struct qeth_card_info {
char mcl_level[QETH_MCL_LENGTH + 1];
int guestlan;
int mac_bits;
- int portname_required;
int portno;
- char portname[9];
enum qeth_card_types type;
enum qeth_link_types link_type;
int is_multicast_different;
@@ -739,11 +740,17 @@ struct qeth_vlan_vid {
unsigned short vid;
};
-struct qeth_mc_mac {
- struct list_head list;
- __u8 mc_addr[MAX_ADDR_LEN];
- unsigned char mc_addrlen;
- int is_vmac;
+enum qeth_mac_disposition {
+ QETH_DISP_MAC_DELETE = 0,
+ QETH_DISP_MAC_DO_NOTHING = 1,
+ QETH_DISP_MAC_ADD = 2,
+};
+
+struct qeth_mac {
+ u8 mac_addr[OSA_ADDR_LEN];
+ u8 is_uc:1;
+ u8 disp_flag:2;
+ struct hlist_node hnode;
};
struct qeth_rx {
@@ -790,7 +797,7 @@ struct qeth_card {
spinlock_t mclock;
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
struct list_head vid_list;
- struct list_head mc_list;
+ DECLARE_HASHTABLE(mac_htable, 4);
struct work_struct kernel_thread_starter;
spinlock_t thread_mask_lock;
unsigned long thread_start_mask;
@@ -967,6 +974,15 @@ int qeth_hw_trap(struct qeth_card *, enum qeth_diags_trap_action);
int qeth_query_ipassists(struct qeth_card *, enum qeth_prot_versions prot);
void qeth_trace_features(struct qeth_card *);
void qeth_close_dev(struct qeth_card *);
+int qeth_send_simple_setassparms(struct qeth_card *, enum qeth_ipa_funcs,
+ __u16, long);
+int qeth_send_setassparms(struct qeth_card *, struct qeth_cmd_buffer *, __u16,
+ long,
+ int (*reply_cb)(struct qeth_card *,
+ struct qeth_reply *, unsigned long),
+ void *);
+int qeth_start_ipa_tx_checksum(struct qeth_card *);
+int qeth_set_rx_csum(struct qeth_card *, int);
/* exports for OSN */
int qeth_osn_assist(struct net_device *, void *, int);
diff --git a/kernel/drivers/s390/net/qeth_core_main.c b/kernel/drivers/s390/net/qeth_core_main.c
index 3466d3cb7..31ac53fa5 100644
--- a/kernel/drivers/s390/net/qeth_core_main.c
+++ b/kernel/drivers/s390/net/qeth_core_main.c
@@ -645,7 +645,8 @@ static struct qeth_ipa_cmd *qeth_check_ipa_data(struct qeth_card *card,
card->info.hwtrap = 2;
qeth_schedule_recovery(card);
return NULL;
- case IPA_CMD_SETBRIDGEPORT:
+ case IPA_CMD_SETBRIDGEPORT_IQD:
+ case IPA_CMD_SETBRIDGEPORT_OSA:
case IPA_CMD_ADDRESS_CHANGE_NOTIF:
if (card->discipline->control_event_handler
(card, cmd))
@@ -1981,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 "
@@ -2359,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;
@@ -2679,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) {
@@ -2757,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);
@@ -5026,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);
@@ -5131,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;
@@ -5316,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;
@@ -6002,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;
diff --git a/kernel/drivers/s390/net/qeth_core_mpc.c b/kernel/drivers/s390/net/qeth_core_mpc.c
index 7b55768a9..beb4bdc26 100644
--- a/kernel/drivers/s390/net/qeth_core_mpc.c
+++ b/kernel/drivers/s390/net/qeth_core_mpc.c
@@ -237,6 +237,7 @@ static struct ipa_cmd_names qeth_ipa_cmd_names[] = {
{IPA_CMD_DELGMAC, "delgmac"},
{IPA_CMD_SETVLAN, "setvlan"},
{IPA_CMD_DELVLAN, "delvlan"},
+ {IPA_CMD_SETBRIDGEPORT_OSA, "set_bridge_port(osa)"},
{IPA_CMD_SETCCID, "setccid"},
{IPA_CMD_DELCCID, "delccid"},
{IPA_CMD_MODCCID, "modccid"},
@@ -249,7 +250,7 @@ static struct ipa_cmd_names qeth_ipa_cmd_names[] = {
{IPA_CMD_DELIP, "delip"},
{IPA_CMD_SETADAPTERPARMS, "setadapterparms"},
{IPA_CMD_SET_DIAG_ASS, "set_diag_ass"},
- {IPA_CMD_SETBRIDGEPORT, "set_bridge_port"},
+ {IPA_CMD_SETBRIDGEPORT_IQD, "set_bridge_port(hs)"},
{IPA_CMD_CREATE_ADDR, "create_addr"},
{IPA_CMD_DESTROY_ADDR, "destroy_addr"},
{IPA_CMD_REGISTER_LOCAL_ADDR, "register_local_addr"},
diff --git a/kernel/drivers/s390/net/qeth_core_mpc.h b/kernel/drivers/s390/net/qeth_core_mpc.h
index 1558be1af..6cccc9a49 100644
--- a/kernel/drivers/s390/net/qeth_core_mpc.h
+++ b/kernel/drivers/s390/net/qeth_core_mpc.h
@@ -92,6 +92,7 @@ enum qeth_ipa_cmds {
IPA_CMD_DELGMAC = 0x24,
IPA_CMD_SETVLAN = 0x25,
IPA_CMD_DELVLAN = 0x26,
+ IPA_CMD_SETBRIDGEPORT_OSA = 0x2b,
IPA_CMD_SETCCID = 0x41,
IPA_CMD_DELCCID = 0x42,
IPA_CMD_MODCCID = 0x43,
@@ -104,7 +105,7 @@ enum qeth_ipa_cmds {
IPA_CMD_DELIP = 0xb7,
IPA_CMD_SETADAPTERPARMS = 0xb8,
IPA_CMD_SET_DIAG_ASS = 0xb9,
- IPA_CMD_SETBRIDGEPORT = 0xbe,
+ IPA_CMD_SETBRIDGEPORT_IQD = 0xbe,
IPA_CMD_CREATE_ADDR = 0xc3,
IPA_CMD_DESTROY_ADDR = 0xc4,
IPA_CMD_REGISTER_LOCAL_ADDR = 0xd1,
diff --git a/kernel/drivers/s390/net/qeth_core_sys.c b/kernel/drivers/s390/net/qeth_core_sys.c
index 423bec56c..e6e5b9671 100644
--- a/kernel/drivers/s390/net/qeth_core_sys.c
+++ b/kernel/drivers/s390/net/qeth_core_sys.c
@@ -153,52 +153,17 @@ static DEVICE_ATTR(portno, 0644, qeth_dev_portno_show, qeth_dev_portno_store);
static ssize_t qeth_dev_portname_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct qeth_card *card = dev_get_drvdata(dev);
- char portname[9] = {0, };
-
- if (!card)
- return -EINVAL;
-
- if (card->info.portname_required) {
- memcpy(portname, card->info.portname + 1, 8);
- EBCASC(portname, 8);
- return sprintf(buf, "%s\n", portname);
- } else
- return sprintf(buf, "no portname required\n");
+ return sprintf(buf, "no portname required\n");
}
static ssize_t qeth_dev_portname_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev_get_drvdata(dev);
- char *tmp;
- int i, rc = 0;
-
- if (!card)
- return -EINVAL;
-
- mutex_lock(&card->conf_mutex);
- if ((card->state != CARD_STATE_DOWN) &&
- (card->state != CARD_STATE_RECOVER)) {
- rc = -EPERM;
- goto out;
- }
- tmp = strsep((char **) &buf, "\n");
- if ((strlen(tmp) > 8) || (strlen(tmp) == 0)) {
- rc = -EINVAL;
- goto out;
- }
-
- card->info.portname[0] = strlen(tmp);
- /* for beauty reasons */
- for (i = 1; i < 9; i++)
- card->info.portname[i] = ' ';
- strcpy(card->info.portname + 1, tmp);
- ASCEBC(card->info.portname + 1, 8);
-out:
- mutex_unlock(&card->conf_mutex);
- return rc ? rc : count;
+ dev_warn_once(&card->gdev->dev,
+ "portname is deprecated and is ignored\n");
+ return count;
}
static DEVICE_ATTR(portname, 0644, qeth_dev_portname_show,
diff --git a/kernel/drivers/s390/net/qeth_l2_main.c b/kernel/drivers/s390/net/qeth_l2_main.c
index 0ea086912..8f1b091e1 100644
--- a/kernel/drivers/s390/net/qeth_l2_main.c
+++ b/kernel/drivers/s390/net/qeth_l2_main.c
@@ -19,7 +19,9 @@
#include <linux/mii.h>
#include <linux/ip.h>
#include <linux/list.h>
-
+#include <linux/hash.h>
+#include <linux/hashtable.h>
+#include <linux/string.h>
#include "qeth_core.h"
#include "qeth_l2.h"
@@ -28,7 +30,7 @@ static int qeth_l2_stop(struct net_device *);
static int qeth_l2_send_delmac(struct qeth_card *, __u8 *);
static int qeth_l2_send_setdelmac(struct qeth_card *, __u8 *,
enum qeth_ipa_cmds);
-static void qeth_l2_set_multicast_list(struct net_device *);
+static void qeth_l2_set_rx_mode(struct net_device *);
static int qeth_l2_recover(void *);
static void qeth_bridgeport_query_support(struct qeth_card *card);
static void qeth_bridge_state_change(struct qeth_card *card,
@@ -137,7 +139,7 @@ static int qeth_setdel_makerc(struct qeth_card *card, int retcode)
rc = 0;
break;
case IPA_RC_L2_UNSUPPORTED_CMD:
- rc = -ENOSYS;
+ rc = -EOPNOTSUPP;
break;
case IPA_RC_L2_ADDR_TABLE_FULL:
rc = -ENOSPC;
@@ -193,49 +195,44 @@ static int qeth_l2_send_delgroupmac(struct qeth_card *card, __u8 *mac)
return rc;
}
-static void qeth_l2_add_mc(struct qeth_card *card, __u8 *mac, int vmac)
+static inline u32 qeth_l2_mac_hash(const u8 *addr)
{
- struct qeth_mc_mac *mc;
- int rc;
-
- mc = kmalloc(sizeof(struct qeth_mc_mac), GFP_ATOMIC);
+ return get_unaligned((u32 *)(&addr[2]));
+}
- if (!mc)
- return;
+static int qeth_l2_write_mac(struct qeth_card *card, struct qeth_mac *mac)
+{
- memcpy(mc->mc_addr, mac, OSA_ADDR_LEN);
- mc->mc_addrlen = OSA_ADDR_LEN;
- mc->is_vmac = vmac;
+ int rc;
- if (vmac) {
+ if (mac->is_uc) {
rc = qeth_setdel_makerc(card,
- qeth_l2_send_setdelmac(card, mac, IPA_CMD_SETVMAC));
+ qeth_l2_send_setdelmac(card, mac->mac_addr,
+ IPA_CMD_SETVMAC));
} else {
rc = qeth_setdel_makerc(card,
- qeth_l2_send_setgroupmac(card, mac));
+ qeth_l2_send_setgroupmac(card, mac->mac_addr));
}
-
- if (!rc)
- list_add_tail(&mc->list, &card->mc_list);
- else
- kfree(mc);
+ return rc;
}
-static void qeth_l2_del_all_mc(struct qeth_card *card, int del)
+static void qeth_l2_del_all_macs(struct qeth_card *card, int del)
{
- struct qeth_mc_mac *mc, *tmp;
+ struct qeth_mac *mac;
+ struct hlist_node *tmp;
+ int i;
spin_lock_bh(&card->mclock);
- list_for_each_entry_safe(mc, tmp, &card->mc_list, list) {
+ hash_for_each_safe(card->mac_htable, i, tmp, mac, hnode) {
if (del) {
- if (mc->is_vmac)
- qeth_l2_send_setdelmac(card, mc->mc_addr,
- IPA_CMD_DELVMAC);
+ if (mac->is_uc)
+ qeth_l2_send_setdelmac(card, mac->mac_addr,
+ IPA_CMD_DELVMAC);
else
- qeth_l2_send_delgroupmac(card, mc->mc_addr);
+ qeth_l2_send_delgroupmac(card, mac->mac_addr);
}
- list_del(&mc->list);
- kfree(mc);
+ hash_del(&mac->hnode);
+ kfree(mac);
}
spin_unlock_bh(&card->mclock);
}
@@ -252,6 +249,23 @@ static inline int qeth_l2_get_cast_type(struct qeth_card *card,
return RTN_UNSPEC;
}
+static inline void qeth_l2_hdr_csum(struct qeth_card *card,
+ struct qeth_hdr *hdr, struct sk_buff *skb)
+{
+ struct iphdr *iph = ip_hdr(skb);
+
+ /* tcph->check contains already the pseudo hdr checksum
+ * so just set the header flags
+ */
+ if (iph->protocol == IPPROTO_UDP)
+ hdr->hdr.l2.flags[1] |= QETH_HDR_EXT_UDP;
+ hdr->hdr.l2.flags[1] |= QETH_HDR_EXT_CSUM_TRANSP_REQ |
+ QETH_HDR_EXT_CSUM_HDR_REQ;
+ iph->check = 0;
+ if (card->options.performance_stats)
+ card->perf_stats.tx_csum++;
+}
+
static void qeth_l2_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
struct sk_buff *skb, int cast_type)
{
@@ -386,14 +400,44 @@ static int qeth_l2_vlan_rx_kill_vid(struct net_device *dev,
rc = qeth_l2_send_setdelvlan(card, vid, IPA_CMD_DELVLAN);
kfree(tmpid);
}
- qeth_l2_set_multicast_list(card->dev);
+ qeth_l2_set_rx_mode(card->dev);
return rc;
}
-static int qeth_l2_stop_card(struct qeth_card *card, int recovery_mode)
+static netdev_features_t qeth_l2_fix_features(struct net_device *dev,
+ netdev_features_t features)
{
- int rc = 0;
+ struct qeth_card *card = dev->ml_priv;
+
+ QETH_DBF_TEXT(SETUP, 2, "fixfeat");
+ if (!qeth_is_supported(card, IPA_OUTBOUND_CHECKSUM))
+ features &= ~NETIF_F_IP_CSUM;
+ if (!qeth_is_supported(card, IPA_INBOUND_CHECKSUM))
+ features &= ~NETIF_F_RXCSUM;
+ QETH_DBF_HEX(SETUP, 2, &features, sizeof(features));
+ return features;
+}
+
+static int qeth_l2_set_features(struct net_device *dev,
+ netdev_features_t features)
+{
+ struct qeth_card *card = dev->ml_priv;
+ netdev_features_t changed = dev->features ^ features;
+
+ QETH_DBF_TEXT(SETUP, 2, "setfeat");
+ QETH_DBF_HEX(SETUP, 2, &features, sizeof(features));
+ if (card->state == CARD_STATE_DOWN ||
+ card->state == CARD_STATE_RECOVER)
+ return 0;
+
+ if (!(changed & NETIF_F_RXCSUM))
+ return 0;
+ return qeth_set_rx_csum(card, features & NETIF_F_RXCSUM ? 1 : 0);
+}
+
+static void qeth_l2_stop_card(struct qeth_card *card, int recovery_mode)
+{
QETH_DBF_TEXT(SETUP , 2, "stopcard");
QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
@@ -413,7 +457,7 @@ static int qeth_l2_stop_card(struct qeth_card *card, int recovery_mode)
card->state = CARD_STATE_SOFTSETUP;
}
if (card->state == CARD_STATE_SOFTSETUP) {
- qeth_l2_del_all_mc(card, 0);
+ qeth_l2_del_all_macs(card, 0);
qeth_clear_ipacmd_list(card);
card->state = CARD_STATE_HARDSETUP;
}
@@ -427,7 +471,6 @@ static int qeth_l2_stop_card(struct qeth_card *card, int recovery_mode)
qeth_clear_cmd_buffers(&card->read);
qeth_clear_cmd_buffers(&card->write);
}
- return rc;
}
static int qeth_l2_process_inbound_buffer(struct qeth_card *card,
@@ -453,11 +496,19 @@ static int qeth_l2_process_inbound_buffer(struct qeth_card *card,
case QETH_HEADER_TYPE_LAYER2:
skb->pkt_type = PACKET_HOST;
skb->protocol = eth_type_trans(skb, skb->dev);
- skb->ip_summed = CHECKSUM_NONE;
+ if ((card->dev->features & NETIF_F_RXCSUM)
+ && ((hdr->hdr.l2.flags[1] &
+ (QETH_HDR_EXT_CSUM_HDR_REQ |
+ QETH_HDR_EXT_CSUM_TRANSP_REQ)) ==
+ (QETH_HDR_EXT_CSUM_HDR_REQ |
+ QETH_HDR_EXT_CSUM_TRANSP_REQ)))
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ else
+ skb->ip_summed = CHECKSUM_NONE;
if (skb->protocol == htons(ETH_P_802_2))
*((__u32 *)skb->cb) = ++card->seqno.pkt_seqno;
len = skb->len;
- netif_receive_skb(skb);
+ napi_gro_receive(&card->napi, skb);
break;
case QETH_HEADER_TYPE_OSN:
if (card->info.type == QETH_CARD_TYPE_OSN) {
@@ -683,30 +734,126 @@ static int qeth_l2_set_mac_address(struct net_device *dev, void *p)
return rc ? -EINVAL : 0;
}
-static void qeth_l2_set_multicast_list(struct net_device *dev)
+static void qeth_promisc_to_bridge(struct qeth_card *card)
+{
+ struct net_device *dev = card->dev;
+ enum qeth_ipa_promisc_modes promisc_mode;
+ int role;
+ int rc;
+
+ QETH_CARD_TEXT(card, 3, "pmisc2br");
+
+ if (!card->options.sbp.reflect_promisc)
+ return;
+ promisc_mode = (dev->flags & IFF_PROMISC) ? SET_PROMISC_MODE_ON
+ : SET_PROMISC_MODE_OFF;
+ if (promisc_mode == card->info.promisc_mode)
+ return;
+
+ if (promisc_mode == SET_PROMISC_MODE_ON) {
+ if (card->options.sbp.reflect_promisc_primary)
+ role = QETH_SBP_ROLE_PRIMARY;
+ else
+ role = QETH_SBP_ROLE_SECONDARY;
+ } else
+ role = QETH_SBP_ROLE_NONE;
+
+ rc = qeth_bridgeport_setrole(card, role);
+ QETH_DBF_TEXT_(SETUP, 2, "bpm%c%04x",
+ (promisc_mode == SET_PROMISC_MODE_ON) ? '+' : '-', rc);
+ if (!rc) {
+ card->options.sbp.role = role;
+ card->info.promisc_mode = promisc_mode;
+ }
+
+}
+/* New MAC address is added to the hash table and marked to be written on card
+ * only if there is not in the hash table storage already
+ *
+*/
+static void
+qeth_l2_add_mac(struct qeth_card *card, struct netdev_hw_addr *ha, u8 is_uc)
+{
+ struct qeth_mac *mac;
+
+ hash_for_each_possible(card->mac_htable, mac, hnode,
+ qeth_l2_mac_hash(ha->addr)) {
+ if (is_uc == mac->is_uc &&
+ !memcmp(ha->addr, mac->mac_addr, OSA_ADDR_LEN)) {
+ mac->disp_flag = QETH_DISP_MAC_DO_NOTHING;
+ return;
+ }
+ }
+
+ mac = kzalloc(sizeof(struct qeth_mac), GFP_ATOMIC);
+
+ if (!mac)
+ return;
+
+ memcpy(mac->mac_addr, ha->addr, OSA_ADDR_LEN);
+ mac->is_uc = is_uc;
+ mac->disp_flag = QETH_DISP_MAC_ADD;
+
+ hash_add(card->mac_htable, &mac->hnode,
+ qeth_l2_mac_hash(mac->mac_addr));
+
+}
+
+static void qeth_l2_set_rx_mode(struct net_device *dev)
{
struct qeth_card *card = dev->ml_priv;
struct netdev_hw_addr *ha;
+ struct qeth_mac *mac;
+ struct hlist_node *tmp;
+ int i;
+ int rc;
if (card->info.type == QETH_CARD_TYPE_OSN)
- return ;
+ return;
QETH_CARD_TEXT(card, 3, "setmulti");
if (qeth_threads_running(card, QETH_RECOVER_THREAD) &&
(card->state != CARD_STATE_UP))
return;
- qeth_l2_del_all_mc(card, 1);
+
spin_lock_bh(&card->mclock);
+
netdev_for_each_mc_addr(ha, dev)
- qeth_l2_add_mc(card, ha->addr, 0);
+ qeth_l2_add_mac(card, ha, 0);
netdev_for_each_uc_addr(ha, dev)
- qeth_l2_add_mc(card, ha->addr, 1);
+ qeth_l2_add_mac(card, ha, 1);
+
+ hash_for_each_safe(card->mac_htable, i, tmp, mac, hnode) {
+ if (mac->disp_flag == QETH_DISP_MAC_DELETE) {
+ if (!mac->is_uc)
+ rc = qeth_l2_send_delgroupmac(card,
+ mac->mac_addr);
+ else {
+ rc = qeth_l2_send_setdelmac(card, mac->mac_addr,
+ IPA_CMD_DELVMAC);
+ }
+
+ hash_del(&mac->hnode);
+ kfree(mac);
+
+ } else if (mac->disp_flag == QETH_DISP_MAC_ADD) {
+ rc = qeth_l2_write_mac(card, mac);
+ if (rc) {
+ hash_del(&mac->hnode);
+ kfree(mac);
+ } else
+ mac->disp_flag = QETH_DISP_MAC_DELETE;
+ } else
+ mac->disp_flag = QETH_DISP_MAC_DELETE;
+ }
spin_unlock_bh(&card->mclock);
- if (!qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE))
- return;
- qeth_setadp_promisc_mode(card);
+
+ if (qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE))
+ qeth_setadp_promisc_mode(card);
+ else
+ qeth_promisc_to_bridge(card);
}
static int qeth_l2_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -772,6 +919,8 @@ static int qeth_l2_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
sizeof(struct qeth_hdr));
skb_set_mac_header(new_skb, sizeof(struct qeth_hdr));
qeth_l2_fill_header(card, hdr, new_skb, cast_type);
+ if (new_skb->ip_summed == CHECKSUM_PARTIAL)
+ qeth_l2_hdr_csum(card, hdr, new_skb);
}
}
@@ -884,7 +1033,7 @@ static int qeth_l2_probe_device(struct ccwgroup_device *gdev)
qeth_l2_create_device_attributes(&gdev->dev);
INIT_LIST_HEAD(&card->vid_list);
- INIT_LIST_HEAD(&card->mc_list);
+ hash_init(card->mac_htable);
card->options.layer2 = 1;
card->info.hwtrap = 0;
return 0;
@@ -930,13 +1079,15 @@ static const struct net_device_ops qeth_l2_netdev_ops = {
.ndo_get_stats = qeth_get_stats,
.ndo_start_xmit = qeth_l2_hard_start_xmit,
.ndo_validate_addr = eth_validate_addr,
- .ndo_set_rx_mode = qeth_l2_set_multicast_list,
+ .ndo_set_rx_mode = qeth_l2_set_rx_mode,
.ndo_do_ioctl = qeth_l2_do_ioctl,
.ndo_set_mac_address = qeth_l2_set_mac_address,
.ndo_change_mtu = qeth_change_mtu,
.ndo_vlan_rx_add_vid = qeth_l2_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = qeth_l2_vlan_rx_kill_vid,
.ndo_tx_timeout = qeth_tx_timeout,
+ .ndo_fix_features = qeth_l2_fix_features,
+ .ndo_set_features = qeth_l2_set_features
};
static int qeth_l2_setup_netdev(struct qeth_card *card)
@@ -966,6 +1117,11 @@ static int qeth_l2_setup_netdev(struct qeth_card *card)
(card->info.type != QETH_CARD_TYPE_OSN) ?
&qeth_l2_ethtool_ops : &qeth_l2_osn_ops;
card->dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+ if (card->info.type == QETH_CARD_TYPE_OSD && !card->info.guestlan) {
+ card->dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM;
+ /* Turn on RX offloading per default */
+ card->dev->features |= NETIF_F_RXCSUM;
+ }
card->info.broadcast_capable = 1;
qeth_l2_request_initial_mac(card);
SET_NETDEV_DEV(card->dev, &card->gdev->dev);
@@ -973,6 +1129,17 @@ static int qeth_l2_setup_netdev(struct qeth_card *card)
return register_netdev(card->dev);
}
+static int qeth_l2_start_ipassists(struct qeth_card *card)
+{
+ /* configure isolation level */
+ if (qeth_set_access_ctrl_online(card, 0))
+ return -ENODEV;
+ if (qeth_is_supported(card, IPA_INBOUND_CHECKSUM))
+ qeth_set_rx_csum(card, 1);
+ qeth_start_ipa_tx_checksum(card);
+ return 0;
+}
+
static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
{
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
@@ -994,7 +1161,7 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
qeth_bridgeport_query_support(card);
if (card->options.sbp.supported_funcs)
dev_info(&card->gdev->dev,
- "The device represents a HiperSockets Bridge Capable Port\n");
+ "The device represents a Bridge Capable Port\n");
qeth_trace_features(card);
if (!card->dev && qeth_l2_setup_netdev(card)) {
@@ -1038,12 +1205,8 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
contin:
if ((card->info.type == QETH_CARD_TYPE_OSD) ||
(card->info.type == QETH_CARD_TYPE_OSX)) {
- /* configure isolation level */
- rc = qeth_set_access_ctrl_online(card, 0);
- if (rc) {
- rc = -ENODEV;
+ if (qeth_l2_start_ipassists(card))
goto out_remove;
- }
}
if (card->info.type != QETH_CARD_TYPE_OSN &&
@@ -1075,7 +1238,7 @@ contin:
rtnl_unlock();
}
/* this also sets saved unicast addresses */
- qeth_l2_set_multicast_list(card->dev);
+ qeth_l2_set_rx_mode(card->dev);
}
/* let user_space know that device is online */
kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE);
@@ -1247,7 +1410,8 @@ static int qeth_l2_control_event(struct qeth_card *card,
struct qeth_ipa_cmd *cmd)
{
switch (cmd->hdr.command) {
- case IPA_CMD_SETBRIDGEPORT:
+ case IPA_CMD_SETBRIDGEPORT_OSA:
+ case IPA_CMD_SETBRIDGEPORT_IQD:
if (cmd->data.sbp.hdr.command_code ==
IPA_SBP_BRIDGE_PORT_STATE_CHANGE) {
qeth_bridge_state_change(card, cmd);
@@ -1420,8 +1584,8 @@ static void qeth_bridge_emit_host_event(struct qeth_card *card,
env[i] = str[i]; i++;
}
if (code & IPA_ADDR_CHANGE_CODE_MACADDR) {
- snprintf(str[i], sizeof(str[i]), "MAC=%pM6",
- &addr_lnid->mac);
+ snprintf(str[i], sizeof(str[i]), "MAC=%pM",
+ addr_lnid->mac);
env[i] = str[i]; i++;
}
snprintf(str[i], sizeof(str[i]), "NTOK_BUSID=%x.%x.%04x",
@@ -1533,7 +1697,7 @@ static void qeth_bridge_host_event_worker(struct work_struct *work)
if (data->hostevs.lost_event_mask) {
dev_info(&data->card->gdev->dev,
-"Address notification from the HiperSockets Bridge Port stopped %s (%s)\n",
+"Address notification from the Bridge Port stopped %s (%s)\n",
data->card->dev->name,
(data->hostevs.lost_event_mask == 0x01)
? "Overflow"
@@ -1617,70 +1781,80 @@ static int qeth_bridgeport_makerc(struct qeth_card *card,
struct _qeth_sbp_cbctl *cbctl, enum qeth_ipa_sbp_cmd setcmd)
{
int rc;
+ int is_iqd = (card->info.type == QETH_CARD_TYPE_IQD);
- switch (cbctl->ipa_rc) {
- case IPA_RC_SUCCESS:
+ if ((is_iqd && (cbctl->ipa_rc == IPA_RC_SUCCESS)) ||
+ (!is_iqd && (cbctl->ipa_rc == cbctl->cmd_rc)))
switch (cbctl->cmd_rc) {
case 0x0000:
rc = 0;
break;
+ case 0x2B04:
case 0x0004:
- rc = -ENOSYS;
+ rc = -EOPNOTSUPP;
break;
+ case 0x2B0C:
case 0x000C: /* Not configured as bridge Port */
rc = -ENODEV; /* maybe not the best code here? */
dev_err(&card->gdev->dev,
- "The HiperSockets device is not configured as a Bridge Port\n");
+ "The device is not configured as a Bridge Port\n");
break;
+ case 0x2B14:
case 0x0014: /* Another device is Primary */
switch (setcmd) {
case IPA_SBP_SET_PRIMARY_BRIDGE_PORT:
rc = -EEXIST;
dev_err(&card->gdev->dev,
- "The HiperSockets LAN already has a primary Bridge Port\n");
+ "The LAN already has a primary Bridge Port\n");
break;
case IPA_SBP_SET_SECONDARY_BRIDGE_PORT:
rc = -EBUSY;
dev_err(&card->gdev->dev,
- "The HiperSockets device is already a primary Bridge Port\n");
+ "The device is already a primary Bridge Port\n");
break;
default:
rc = -EIO;
}
break;
+ case 0x2B18:
case 0x0018: /* This device is currently Secondary */
rc = -EBUSY;
dev_err(&card->gdev->dev,
- "The HiperSockets device is already a secondary Bridge Port\n");
+ "The device is already a secondary Bridge Port\n");
break;
+ case 0x2B1C:
case 0x001C: /* Limit for Secondary devices reached */
rc = -EEXIST;
dev_err(&card->gdev->dev,
- "The HiperSockets LAN cannot have more secondary Bridge Ports\n");
+ "The LAN cannot have more secondary Bridge Ports\n");
break;
+ case 0x2B24:
case 0x0024: /* This device is currently Primary */
rc = -EBUSY;
dev_err(&card->gdev->dev,
- "The HiperSockets device is already a primary Bridge Port\n");
+ "The device is already a primary Bridge Port\n");
break;
+ case 0x2B20:
case 0x0020: /* Not authorized by zManager */
rc = -EACCES;
dev_err(&card->gdev->dev,
- "The HiperSockets device is not authorized to be a Bridge Port\n");
+ "The device is not authorized to be a Bridge Port\n");
break;
default:
rc = -EIO;
}
- break;
- case IPA_RC_NOTSUPP:
- rc = -ENOSYS;
- break;
- case IPA_RC_UNSUPPORTED_COMMAND:
- rc = -ENOSYS;
- break;
- default:
- rc = -EIO;
- }
+ else
+ switch (cbctl->ipa_rc) {
+ case IPA_RC_NOTSUPP:
+ rc = -EOPNOTSUPP;
+ break;
+ case IPA_RC_UNSUPPORTED_COMMAND:
+ rc = -EOPNOTSUPP;
+ break;
+ default:
+ rc = -EIO;
+ }
+
if (rc) {
QETH_CARD_TEXT_(card, 2, "SBPi%04x", cbctl->ipa_rc);
QETH_CARD_TEXT_(card, 2, "SBPc%04x", cbctl->cmd_rc);
@@ -1688,6 +1862,13 @@ static int qeth_bridgeport_makerc(struct qeth_card *card,
return rc;
}
+static inline int ipa_cmd_sbp(struct qeth_card *card)
+{
+ return (card->info.type == QETH_CARD_TYPE_IQD) ?
+ IPA_CMD_SETBRIDGEPORT_IQD :
+ IPA_CMD_SETBRIDGEPORT_OSA;
+}
+
static int qeth_bridgeport_query_support_cb(struct qeth_card *card,
struct qeth_reply *reply, unsigned long data)
{
@@ -1719,7 +1900,7 @@ static void qeth_bridgeport_query_support(struct qeth_card *card)
struct _qeth_sbp_cbctl cbctl;
QETH_CARD_TEXT(card, 2, "brqsuppo");
- iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SETBRIDGEPORT, 0);
+ iob = qeth_get_ipacmd_buffer(card, ipa_cmd_sbp(card), 0);
if (!iob)
return;
cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
@@ -1796,7 +1977,7 @@ int qeth_bridgeport_query_ports(struct qeth_card *card,
QETH_CARD_TEXT(card, 2, "brqports");
if (!(card->options.sbp.supported_funcs & IPA_SBP_QUERY_BRIDGE_PORTS))
return -EOPNOTSUPP;
- iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SETBRIDGEPORT, 0);
+ iob = qeth_get_ipacmd_buffer(card, ipa_cmd_sbp(card), 0);
if (!iob)
return -ENOMEM;
cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
@@ -1808,10 +1989,9 @@ int qeth_bridgeport_query_ports(struct qeth_card *card,
cmd->data.sbp.hdr.seq_no = 1;
rc = qeth_send_ipa_cmd(card, iob, qeth_bridgeport_query_ports_cb,
(void *)&cbctl);
- if (rc)
+ if (rc < 0)
return rc;
- rc = qeth_bridgeport_makerc(card, &cbctl, IPA_SBP_QUERY_BRIDGE_PORTS);
- return rc;
+ return qeth_bridgeport_makerc(card, &cbctl, IPA_SBP_QUERY_BRIDGE_PORTS);
}
EXPORT_SYMBOL_GPL(qeth_bridgeport_query_ports);
@@ -1864,7 +2044,7 @@ int qeth_bridgeport_setrole(struct qeth_card *card, enum qeth_sbp_roles role)
}
if (!(card->options.sbp.supported_funcs & setcmd))
return -EOPNOTSUPP;
- iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SETBRIDGEPORT, 0);
+ iob = qeth_get_ipacmd_buffer(card, ipa_cmd_sbp(card), 0);
if (!iob)
return -ENOMEM;
cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
@@ -1874,10 +2054,9 @@ int qeth_bridgeport_setrole(struct qeth_card *card, enum qeth_sbp_roles role)
cmd->data.sbp.hdr.seq_no = 1;
rc = qeth_send_ipa_cmd(card, iob, qeth_bridgeport_set_cb,
(void *)&cbctl);
- if (rc)
+ if (rc < 0)
return rc;
- rc = qeth_bridgeport_makerc(card, &cbctl, setcmd);
- return rc;
+ return qeth_bridgeport_makerc(card, &cbctl, setcmd);
}
/**
@@ -1898,7 +2077,7 @@ static int qeth_anset_makerc(struct qeth_card *card, int pnso_rc, u16 response)
case 0x0004:
case 0x0100:
case 0x0106:
- rc = -ENOSYS;
+ rc = -EOPNOTSUPP;
dev_err(&card->gdev->dev,
"Setting address notification failed\n");
break;
diff --git a/kernel/drivers/s390/net/qeth_l2_sys.c b/kernel/drivers/s390/net/qeth_l2_sys.c
index 59e3aa538..692db49e3 100644
--- a/kernel/drivers/s390/net/qeth_l2_sys.c
+++ b/kernel/drivers/s390/net/qeth_l2_sys.c
@@ -23,8 +23,6 @@ static ssize_t qeth_bridge_port_role_state_show(struct device *dev,
if (!card)
return -EINVAL;
- mutex_lock(&card->conf_mutex);
-
if (qeth_card_hw_is_reachable(card) &&
card->options.sbp.supported_funcs)
rc = qeth_bridgeport_query_ports(card,
@@ -59,8 +57,6 @@ static ssize_t qeth_bridge_port_role_state_show(struct device *dev,
rc = sprintf(buf, "%s\n", word);
}
- mutex_unlock(&card->conf_mutex);
-
return rc;
}
@@ -90,7 +86,9 @@ static ssize_t qeth_bridge_port_role_store(struct device *dev,
mutex_lock(&card->conf_mutex);
- if (qeth_card_hw_is_reachable(card)) {
+ if (card->options.sbp.reflect_promisc) /* Forbid direct manipulation */
+ rc = -EPERM;
+ else if (qeth_card_hw_is_reachable(card)) {
rc = qeth_bridgeport_setrole(card, role);
if (!rc)
card->options.sbp.role = role;
@@ -111,7 +109,7 @@ static ssize_t qeth_bridge_port_state_show(struct device *dev,
return qeth_bridge_port_role_state_show(dev, attr, buf, 1);
}
-static DEVICE_ATTR(bridge_state, 0644, qeth_bridge_port_state_show,
+static DEVICE_ATTR(bridge_state, 0444, qeth_bridge_port_state_show,
NULL);
static ssize_t qeth_bridgeport_hostnotification_show(struct device *dev,
@@ -123,12 +121,8 @@ static ssize_t qeth_bridgeport_hostnotification_show(struct device *dev,
if (!card)
return -EINVAL;
- mutex_lock(&card->conf_mutex);
-
enabled = card->options.sbp.hostnotification;
- mutex_unlock(&card->conf_mutex);
-
return sprintf(buf, "%d\n", enabled);
}
@@ -167,10 +161,72 @@ static DEVICE_ATTR(bridge_hostnotify, 0644,
qeth_bridgeport_hostnotification_show,
qeth_bridgeport_hostnotification_store);
+static ssize_t qeth_bridgeport_reflect_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct qeth_card *card = dev_get_drvdata(dev);
+ char *state;
+
+ if (!card)
+ return -EINVAL;
+
+ if (card->options.sbp.reflect_promisc) {
+ if (card->options.sbp.reflect_promisc_primary)
+ state = "primary";
+ else
+ state = "secondary";
+ } else
+ state = "none";
+
+ return sprintf(buf, "%s\n", state);
+}
+
+static ssize_t qeth_bridgeport_reflect_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct qeth_card *card = dev_get_drvdata(dev);
+ int enable, primary;
+ int rc = 0;
+
+ if (!card)
+ return -EINVAL;
+
+ if (sysfs_streq(buf, "none")) {
+ enable = 0;
+ primary = 0;
+ } else if (sysfs_streq(buf, "primary")) {
+ enable = 1;
+ primary = 1;
+ } else if (sysfs_streq(buf, "secondary")) {
+ enable = 1;
+ primary = 0;
+ } else
+ return -EINVAL;
+
+ mutex_lock(&card->conf_mutex);
+
+ if (card->options.sbp.role != QETH_SBP_ROLE_NONE)
+ rc = -EPERM;
+ else {
+ card->options.sbp.reflect_promisc = enable;
+ card->options.sbp.reflect_promisc_primary = primary;
+ rc = 0;
+ }
+
+ mutex_unlock(&card->conf_mutex);
+
+ return rc ? rc : count;
+}
+
+static DEVICE_ATTR(bridge_reflect_promisc, 0644,
+ qeth_bridgeport_reflect_show,
+ qeth_bridgeport_reflect_store);
+
static struct attribute *qeth_l2_bridgeport_attrs[] = {
&dev_attr_bridge_role.attr,
&dev_attr_bridge_state.attr,
&dev_attr_bridge_hostnotify.attr,
+ &dev_attr_bridge_reflect_promisc.attr,
NULL,
};
diff --git a/kernel/drivers/s390/net/qeth_l3_main.c b/kernel/drivers/s390/net/qeth_l3_main.c
index 04e42c649..543960e96 100644
--- a/kernel/drivers/s390/net/qeth_l3_main.c
+++ b/kernel/drivers/s390/net/qeth_l3_main.c
@@ -1065,27 +1065,6 @@ static struct qeth_cmd_buffer *qeth_l3_get_setassparms_cmd(
return iob;
}
-static int qeth_l3_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;
-}
-
#ifdef CONFIG_QETH_IPV6
static int qeth_l3_send_simple_setassparms_ipv6(struct qeth_card *card,
enum qeth_ipa_funcs ipa_func, __u16 cmd_code)
@@ -1098,31 +1077,12 @@ static int qeth_l3_send_simple_setassparms_ipv6(struct qeth_card *card,
0, QETH_PROT_IPV6);
if (!iob)
return -ENOMEM;
- rc = qeth_l3_send_setassparms(card, iob, 0, 0,
+ rc = qeth_send_setassparms(card, iob, 0, 0,
qeth_l3_default_setassparms_cb, NULL);
return rc;
}
#endif
-static int qeth_l3_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_l3_get_setassparms_cmd(card, ipa_func, cmd_code,
- length, QETH_PROT_IPV4);
- if (!iob)
- return -ENOMEM;
- rc = qeth_l3_send_setassparms(card, iob, length, data,
- qeth_l3_default_setassparms_cb, NULL);
- return rc;
-}
-
static int qeth_l3_start_ipa_arp_processing(struct qeth_card *card)
{
int rc;
@@ -1135,8 +1095,8 @@ static int qeth_l3_start_ipa_arp_processing(struct qeth_card *card)
QETH_CARD_IFNAME(card));
return 0;
}
- rc = qeth_l3_send_simple_setassparms(card, IPA_ARP_PROCESSING,
- IPA_CMD_ASS_START, 0);
+ rc = qeth_send_simple_setassparms(card, IPA_ARP_PROCESSING,
+ IPA_CMD_ASS_START, 0);
if (rc) {
dev_warn(&card->gdev->dev,
"Starting ARP processing support for %s failed\n",
@@ -1158,7 +1118,7 @@ static int qeth_l3_start_ipa_ip_fragmentation(struct qeth_card *card)
return -EOPNOTSUPP;
}
- rc = qeth_l3_send_simple_setassparms(card, IPA_IP_FRAGMENTATION,
+ rc = qeth_send_simple_setassparms(card, IPA_IP_FRAGMENTATION,
IPA_CMD_ASS_START, 0);
if (rc) {
dev_warn(&card->gdev->dev,
@@ -1183,7 +1143,7 @@ static int qeth_l3_start_ipa_source_mac(struct qeth_card *card)
return -EOPNOTSUPP;
}
- rc = qeth_l3_send_simple_setassparms(card, IPA_SOURCE_MAC,
+ rc = qeth_send_simple_setassparms(card, IPA_SOURCE_MAC,
IPA_CMD_ASS_START, 0);
if (rc)
dev_warn(&card->gdev->dev,
@@ -1204,7 +1164,7 @@ static int qeth_l3_start_ipa_vlan(struct qeth_card *card)
return -EOPNOTSUPP;
}
- rc = qeth_l3_send_simple_setassparms(card, IPA_VLAN_PRIO,
+ rc = qeth_send_simple_setassparms(card, IPA_VLAN_PRIO,
IPA_CMD_ASS_START, 0);
if (rc) {
dev_warn(&card->gdev->dev,
@@ -1229,7 +1189,7 @@ static int qeth_l3_start_ipa_multicast(struct qeth_card *card)
return -EOPNOTSUPP;
}
- rc = qeth_l3_send_simple_setassparms(card, IPA_MULTICASTING,
+ rc = qeth_send_simple_setassparms(card, IPA_MULTICASTING,
IPA_CMD_ASS_START, 0);
if (rc) {
dev_warn(&card->gdev->dev,
@@ -1259,7 +1219,7 @@ static int qeth_l3_softsetup_ipv6(struct qeth_card *card)
QETH_CARD_IFNAME(card));
return rc;
}
- rc = qeth_l3_send_simple_setassparms(card, IPA_IPV6,
+ rc = qeth_send_simple_setassparms(card, IPA_IPV6,
IPA_CMD_ASS_START, 3);
if (rc) {
dev_err(&card->gdev->dev,
@@ -1319,7 +1279,7 @@ static int qeth_l3_start_ipa_broadcast(struct qeth_card *card)
rc = -EOPNOTSUPP;
goto out;
}
- rc = qeth_l3_send_simple_setassparms(card, IPA_FILTERING,
+ rc = qeth_send_simple_setassparms(card, IPA_FILTERING,
IPA_CMD_ASS_START, 0);
if (rc) {
dev_warn(&card->gdev->dev, "Enabling broadcast filtering for "
@@ -1327,7 +1287,7 @@ static int qeth_l3_start_ipa_broadcast(struct qeth_card *card)
goto out;
}
- rc = qeth_l3_send_simple_setassparms(card, IPA_FILTERING,
+ rc = qeth_send_simple_setassparms(card, IPA_FILTERING,
IPA_CMD_ASS_CONFIGURE, 1);
if (rc) {
dev_warn(&card->gdev->dev,
@@ -1337,7 +1297,7 @@ static int qeth_l3_start_ipa_broadcast(struct qeth_card *card)
}
card->info.broadcast_capable = QETH_BROADCAST_WITH_ECHO;
dev_info(&card->gdev->dev, "Broadcast enabled\n");
- rc = qeth_l3_send_simple_setassparms(card, IPA_FILTERING,
+ rc = qeth_send_simple_setassparms(card, IPA_FILTERING,
IPA_CMD_ASS_ENABLE, 1);
if (rc) {
dev_warn(&card->gdev->dev, "Setting up broadcast echo "
@@ -1353,84 +1313,18 @@ out:
return rc;
}
-static int qeth_l3_send_checksum_command(struct qeth_card *card)
-{
- int rc;
-
- rc = qeth_l3_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_l3_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;
-}
-
-static int qeth_l3_set_rx_csum(struct qeth_card *card, int on)
-{
- int rc = 0;
-
- if (on) {
- rc = qeth_l3_send_checksum_command(card);
- if (rc)
- return -EIO;
- dev_info(&card->gdev->dev,
- "HW Checksumming (inbound) enabled\n");
- } else {
- rc = qeth_l3_send_simple_setassparms(card,
- IPA_INBOUND_CHECKSUM, IPA_CMD_ASS_STOP, 0);
- if (rc)
- return -EIO;
- }
-
- return 0;
-}
-
-static int qeth_l3_start_ipa_checksum(struct qeth_card *card)
+static void qeth_l3_start_ipa_checksum(struct qeth_card *card)
{
QETH_CARD_TEXT(card, 3, "strtcsum");
-
- if (card->dev->features & NETIF_F_RXCSUM) {
- rtnl_lock();
- /* force set_features call */
- card->dev->features &= ~NETIF_F_RXCSUM;
- netdev_update_features(card->dev);
- rtnl_unlock();
- }
- return 0;
+ if (qeth_is_supported(card, IPA_INBOUND_CHECKSUM)
+ && (card->dev->features & NETIF_F_RXCSUM))
+ qeth_set_rx_csum(card, 1);
}
-static int qeth_l3_start_ipa_tx_checksum(struct qeth_card *card)
+static void qeth_l3_start_ipa_tx_checksum(struct qeth_card *card)
{
- int rc = 0;
-
- if (!qeth_is_supported(card, IPA_OUTBOUND_CHECKSUM))
- return rc;
- rc = qeth_l3_send_simple_setassparms(card, IPA_OUTBOUND_CHECKSUM,
- IPA_CMD_ASS_START, 0);
- if (rc)
- goto err_out;
- rc = qeth_l3_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;
+ QETH_CARD_TEXT(card, 3, "strttxcs");
+ qeth_start_ipa_tx_checksum(card);
}
static int qeth_l3_start_ipa_tso(struct qeth_card *card)
@@ -1445,8 +1339,8 @@ static int qeth_l3_start_ipa_tso(struct qeth_card *card)
QETH_CARD_IFNAME(card));
rc = -EOPNOTSUPP;
} else {
- rc = qeth_l3_send_simple_setassparms(card, IPA_OUTBOUND_TSO,
- IPA_CMD_ASS_START, 0);
+ rc = qeth_send_simple_setassparms(card, IPA_OUTBOUND_TSO,
+ IPA_CMD_ASS_START, 0);
if (rc)
dev_warn(&card->gdev->dev, "Starting outbound TCP "
"segmentation offload for %s failed\n",
@@ -1950,7 +1844,6 @@ static inline int qeth_l3_rebuild_skb(struct qeth_card *card,
skb->ip_summed = CHECKSUM_NONE;
} else
skb->ip_summed = CHECKSUM_NONE;
-
return is_vlan;
}
@@ -2158,10 +2051,8 @@ static struct qeth_card *qeth_l3_get_card_from_dev(struct net_device *dev)
return card ;
}
-static int qeth_l3_stop_card(struct qeth_card *card, int recovery_mode)
+static void qeth_l3_stop_card(struct qeth_card *card, int recovery_mode)
{
- int rc = 0;
-
QETH_DBF_TEXT(SETUP, 2, "stopcard");
QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
@@ -2196,7 +2087,6 @@ static int qeth_l3_stop_card(struct qeth_card *card, int recovery_mode)
qeth_clear_cmd_buffers(&card->read);
qeth_clear_cmd_buffers(&card->write);
}
- return rc;
}
/*
@@ -2290,7 +2180,7 @@ static int qeth_l3_arp_set_no_entries(struct qeth_card *card, int no_entries)
if (!qeth_is_supported(card, IPA_ARP_PROCESSING)) {
return -EOPNOTSUPP;
}
- rc = qeth_l3_send_simple_setassparms(card, IPA_ARP_PROCESSING,
+ rc = qeth_send_simple_setassparms(card, IPA_ARP_PROCESSING,
IPA_CMD_ASS_ARP_SET_NO_ENTRIES,
no_entries);
if (rc) {
@@ -2555,7 +2445,7 @@ static int qeth_l3_arp_add_entry(struct qeth_card *card,
QETH_PROT_IPV4);
if (!iob)
return -ENOMEM;
- rc = qeth_l3_send_setassparms(card, iob,
+ rc = qeth_send_setassparms(card, iob,
sizeof(struct qeth_arp_cache_entry),
(unsigned long) entry,
qeth_l3_default_setassparms_cb, NULL);
@@ -2596,7 +2486,7 @@ static int qeth_l3_arp_remove_entry(struct qeth_card *card,
QETH_PROT_IPV4);
if (!iob)
return -ENOMEM;
- rc = qeth_l3_send_setassparms(card, iob,
+ rc = qeth_send_setassparms(card, iob,
12, (unsigned long)buf,
qeth_l3_default_setassparms_cb, NULL);
if (rc) {
@@ -2627,7 +2517,7 @@ static int qeth_l3_arp_flush_cache(struct qeth_card *card)
if (!qeth_is_supported(card, IPA_ARP_PROCESSING)) {
return -EOPNOTSUPP;
}
- rc = qeth_l3_send_simple_setassparms(card, IPA_ARP_PROCESSING,
+ rc = qeth_send_simple_setassparms(card, IPA_ARP_PROCESSING,
IPA_CMD_ASS_ARP_FLUSH_CACHE, 0);
if (rc) {
tmp = rc;
@@ -3190,7 +3080,6 @@ static netdev_features_t qeth_l3_fix_features(struct net_device *dev,
features &= ~NETIF_F_TSO;
if (!qeth_is_supported(card, IPA_INBOUND_CHECKSUM))
features &= ~NETIF_F_RXCSUM;
-
return features;
}
@@ -3198,8 +3087,7 @@ static int qeth_l3_set_features(struct net_device *dev,
netdev_features_t features)
{
struct qeth_card *card = dev->ml_priv;
- u32 changed = dev->features ^ features;
- int err;
+ netdev_features_t changed = dev->features ^ features;
if (!(changed & NETIF_F_RXCSUM))
return 0;
@@ -3208,11 +3096,7 @@ static int qeth_l3_set_features(struct net_device *dev,
card->state == CARD_STATE_RECOVER)
return 0;
- err = qeth_l3_set_rx_csum(card, features & NETIF_F_RXCSUM);
- if (err)
- dev->features = features ^ NETIF_F_RXCSUM;
-
- return err;
+ return qeth_set_rx_csum(card, features & NETIF_F_RXCSUM ? 1 : 0);
}
static const struct ethtool_ops qeth_l3_ethtool_ops = {
diff --git a/kernel/drivers/s390/net/smsgiucv.c b/kernel/drivers/s390/net/smsgiucv.c
index d8f990b6b..a851d34c6 100644
--- a/kernel/drivers/s390/net/smsgiucv.c
+++ b/kernel/drivers/s390/net/smsgiucv.c
@@ -49,7 +49,7 @@ static DEFINE_SPINLOCK(smsg_list_lock);
static LIST_HEAD(smsg_list);
static int iucv_path_connected;
-static int smsg_path_pending(struct iucv_path *, u8 ipvmid[8], u8 ipuser[16]);
+static int smsg_path_pending(struct iucv_path *, u8 *, u8 *);
static void smsg_message_pending(struct iucv_path *, struct iucv_message *);
static struct iucv_handler smsg_handler = {
@@ -57,8 +57,7 @@ static struct iucv_handler smsg_handler = {
.message_pending = smsg_message_pending,
};
-static int smsg_path_pending(struct iucv_path *path, u8 ipvmid[8],
- u8 ipuser[16])
+static int smsg_path_pending(struct iucv_path *path, u8 *ipvmid, u8 *ipuser)
{
if (strncmp(ipvmid, "*MSG ", 8) != 0)
return -EINVAL;