diff options
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/net/lcs.c | 2 | ||||
-rw-r--r-- | drivers/s390/net/qeth_core.h | 2 | ||||
-rw-r--r-- | drivers/s390/net/qeth_core_main.c | 3 | ||||
-rw-r--r-- | drivers/s390/net/qeth_core_mpc.c | 3 | ||||
-rw-r--r-- | drivers/s390/net/qeth_core_mpc.h | 3 | ||||
-rw-r--r-- | drivers/s390/net/qeth_l2_main.c | 124 | ||||
-rw-r--r-- | drivers/s390/net/qeth_l2_sys.c | 74 | ||||
-rw-r--r-- | drivers/s390/net/qeth_l3_main.c | 9 |
8 files changed, 163 insertions, 57 deletions
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index 00b7d9c9fe48..2f5b518b0e78 100644 --- a/drivers/s390/net/lcs.c +++ b/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/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index 3abac028899f..ba974a2e409f 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -175,6 +175,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, diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 3466d3cb7647..5e20fba37bff 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/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)) diff --git a/drivers/s390/net/qeth_core_mpc.c b/drivers/s390/net/qeth_core_mpc.c index 7b55768a9592..beb4bdc26de5 100644 --- a/drivers/s390/net/qeth_core_mpc.c +++ b/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/drivers/s390/net/qeth_core_mpc.h b/drivers/s390/net/qeth_core_mpc.h index 1558be1af72d..6cccc9a49ede 100644 --- a/drivers/s390/net/qeth_core_mpc.h +++ b/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/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 0ea0869120cf..2e65b989a9ea 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -137,7 +137,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; @@ -683,6 +683,39 @@ static int qeth_l2_set_mac_address(struct net_device *dev, void *p) return rc ? -EINVAL : 0; } +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; + } +} + static void qeth_l2_set_multicast_list(struct net_device *dev) { struct qeth_card *card = dev->ml_priv; @@ -704,9 +737,10 @@ static void qeth_l2_set_multicast_list(struct net_device *dev) qeth_l2_add_mc(card, ha->addr, 1); 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) @@ -994,7 +1028,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)) { @@ -1247,7 +1281,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); @@ -1533,7 +1568,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 +1652,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 +1733,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 +1771,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 +1848,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 +1860,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 +1915,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 +1925,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 +1948,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/drivers/s390/net/qeth_l2_sys.c b/drivers/s390/net/qeth_l2_sys.c index 59e3aa538b4d..52673cd1db99 100644 --- a/drivers/s390/net/qeth_l2_sys.c +++ b/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; @@ -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/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 04e42c649134..70eb2f61bb92 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -3198,8 +3198,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 +3207,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_l3_set_rx_csum(card, features & NETIF_F_RXCSUM ? 1 : 0); } static const struct ethtool_ops qeth_l3_ethtool_ops = { |