123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383 |
- // SPDX-License-Identifier: GPL-2.0
- /*
- * Copyright IBM Corp. 2013
- * Author(s): Eugene Crosser <[email protected]>
- */
- #include <linux/slab.h>
- #include <asm/ebcdic.h>
- #include "qeth_core.h"
- #include "qeth_l2.h"
- static ssize_t qeth_bridge_port_role_state_show(struct device *dev,
- struct device_attribute *attr, char *buf,
- int show_state)
- {
- struct qeth_card *card = dev_get_drvdata(dev);
- enum qeth_sbp_states state = QETH_SBP_STATE_INACTIVE;
- int rc = 0;
- char *word;
- if (!qeth_bridgeport_allowed(card))
- return sprintf(buf, "n/a (VNIC characteristics)\n");
- mutex_lock(&card->sbp_lock);
- if (qeth_card_hw_is_reachable(card) &&
- card->options.sbp.supported_funcs)
- rc = qeth_bridgeport_query_ports(card,
- &card->options.sbp.role, &state);
- if (!rc) {
- if (show_state)
- switch (state) {
- case QETH_SBP_STATE_INACTIVE:
- word = "inactive"; break;
- case QETH_SBP_STATE_STANDBY:
- word = "standby"; break;
- case QETH_SBP_STATE_ACTIVE:
- word = "active"; break;
- default:
- rc = -EIO;
- }
- else
- switch (card->options.sbp.role) {
- case QETH_SBP_ROLE_NONE:
- word = "none"; break;
- case QETH_SBP_ROLE_PRIMARY:
- word = "primary"; break;
- case QETH_SBP_ROLE_SECONDARY:
- word = "secondary"; break;
- default:
- rc = -EIO;
- }
- if (rc)
- QETH_CARD_TEXT_(card, 2, "SBP%02x:%02x",
- card->options.sbp.role, state);
- else
- rc = sprintf(buf, "%s\n", word);
- }
- mutex_unlock(&card->sbp_lock);
- return rc;
- }
- static ssize_t qeth_bridge_port_role_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- struct qeth_card *card = dev_get_drvdata(dev);
- if (!qeth_bridgeport_allowed(card))
- return sprintf(buf, "n/a (VNIC characteristics)\n");
- return qeth_bridge_port_role_state_show(dev, attr, buf, 0);
- }
- static ssize_t qeth_bridge_port_role_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
- {
- struct qeth_card *card = dev_get_drvdata(dev);
- int rc = 0;
- enum qeth_sbp_roles role;
- if (sysfs_streq(buf, "primary"))
- role = QETH_SBP_ROLE_PRIMARY;
- else if (sysfs_streq(buf, "secondary"))
- role = QETH_SBP_ROLE_SECONDARY;
- else if (sysfs_streq(buf, "none"))
- role = QETH_SBP_ROLE_NONE;
- else
- return -EINVAL;
- mutex_lock(&card->conf_mutex);
- mutex_lock(&card->sbp_lock);
- if (!qeth_bridgeport_allowed(card))
- rc = -EBUSY;
- else 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;
- } else
- card->options.sbp.role = role;
- mutex_unlock(&card->sbp_lock);
- mutex_unlock(&card->conf_mutex);
- return rc ? rc : count;
- }
- static DEVICE_ATTR(bridge_role, 0644, qeth_bridge_port_role_show,
- qeth_bridge_port_role_store);
- static ssize_t qeth_bridge_port_state_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- struct qeth_card *card = dev_get_drvdata(dev);
- if (!qeth_bridgeport_allowed(card))
- return sprintf(buf, "n/a (VNIC characteristics)\n");
- return qeth_bridge_port_role_state_show(dev, attr, buf, 1);
- }
- static DEVICE_ATTR(bridge_state, 0444, qeth_bridge_port_state_show,
- NULL);
- static ssize_t qeth_bridgeport_hostnotification_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- struct qeth_card *card = dev_get_drvdata(dev);
- int enabled;
- if (!qeth_bridgeport_allowed(card))
- return sprintf(buf, "n/a (VNIC characteristics)\n");
- enabled = card->options.sbp.hostnotification;
- return sprintf(buf, "%d\n", enabled);
- }
- static ssize_t qeth_bridgeport_hostnotification_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
- {
- struct qeth_card *card = dev_get_drvdata(dev);
- bool enable;
- int rc;
- rc = kstrtobool(buf, &enable);
- if (rc)
- return rc;
- mutex_lock(&card->conf_mutex);
- mutex_lock(&card->sbp_lock);
- if (!qeth_bridgeport_allowed(card))
- rc = -EBUSY;
- else if (qeth_card_hw_is_reachable(card)) {
- rc = qeth_bridgeport_an_set(card, enable);
- /* sbp_lock ensures ordering vs notifications-stopped events */
- if (!rc)
- card->options.sbp.hostnotification = enable;
- } else
- card->options.sbp.hostnotification = enable;
- mutex_unlock(&card->sbp_lock);
- mutex_unlock(&card->conf_mutex);
- return rc ? rc : count;
- }
- 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 (!qeth_bridgeport_allowed(card))
- return sprintf(buf, "n/a (VNIC characteristics)\n");
- 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 (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);
- mutex_lock(&card->sbp_lock);
- if (!qeth_bridgeport_allowed(card))
- rc = -EBUSY;
- else 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->sbp_lock);
- 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,
- };
- static struct attribute_group qeth_l2_bridgeport_attr_group = {
- .attrs = qeth_l2_bridgeport_attrs,
- };
- /* VNIC CHARS support */
- /* convert sysfs attr name to VNIC characteristic */
- static u32 qeth_l2_vnicc_sysfs_attr_to_char(const char *attr_name)
- {
- if (sysfs_streq(attr_name, "flooding"))
- return QETH_VNICC_FLOODING;
- else if (sysfs_streq(attr_name, "mcast_flooding"))
- return QETH_VNICC_MCAST_FLOODING;
- else if (sysfs_streq(attr_name, "learning"))
- return QETH_VNICC_LEARNING;
- else if (sysfs_streq(attr_name, "takeover_setvmac"))
- return QETH_VNICC_TAKEOVER_SETVMAC;
- else if (sysfs_streq(attr_name, "takeover_learning"))
- return QETH_VNICC_TAKEOVER_LEARNING;
- else if (sysfs_streq(attr_name, "bridge_invisible"))
- return QETH_VNICC_BRIDGE_INVISIBLE;
- else if (sysfs_streq(attr_name, "rx_bcast"))
- return QETH_VNICC_RX_BCAST;
- return 0;
- }
- /* get current timeout setting */
- static ssize_t qeth_vnicc_timeout_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- struct qeth_card *card = dev_get_drvdata(dev);
- u32 timeout;
- int rc;
- rc = qeth_l2_vnicc_get_timeout(card, &timeout);
- if (rc == -EBUSY)
- return sprintf(buf, "n/a (BridgePort)\n");
- if (rc == -EOPNOTSUPP)
- return sprintf(buf, "n/a\n");
- return rc ? rc : sprintf(buf, "%d\n", timeout);
- }
- /* change timeout setting */
- static ssize_t qeth_vnicc_timeout_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
- {
- struct qeth_card *card = dev_get_drvdata(dev);
- u32 timeout;
- int rc;
- rc = kstrtou32(buf, 10, &timeout);
- if (rc)
- return rc;
- mutex_lock(&card->conf_mutex);
- rc = qeth_l2_vnicc_set_timeout(card, timeout);
- mutex_unlock(&card->conf_mutex);
- return rc ? rc : count;
- }
- /* get current setting of characteristic */
- static ssize_t qeth_vnicc_char_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- struct qeth_card *card = dev_get_drvdata(dev);
- bool state;
- u32 vnicc;
- int rc;
- vnicc = qeth_l2_vnicc_sysfs_attr_to_char(attr->attr.name);
- rc = qeth_l2_vnicc_get_state(card, vnicc, &state);
- if (rc == -EBUSY)
- return sprintf(buf, "n/a (BridgePort)\n");
- if (rc == -EOPNOTSUPP)
- return sprintf(buf, "n/a\n");
- return rc ? rc : sprintf(buf, "%d\n", state);
- }
- /* change setting of characteristic */
- static ssize_t qeth_vnicc_char_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
- {
- struct qeth_card *card = dev_get_drvdata(dev);
- bool state;
- u32 vnicc;
- int rc;
- if (kstrtobool(buf, &state))
- return -EINVAL;
- vnicc = qeth_l2_vnicc_sysfs_attr_to_char(attr->attr.name);
- mutex_lock(&card->conf_mutex);
- rc = qeth_l2_vnicc_set_state(card, vnicc, state);
- mutex_unlock(&card->conf_mutex);
- return rc ? rc : count;
- }
- static DEVICE_ATTR(flooding, 0644, qeth_vnicc_char_show, qeth_vnicc_char_store);
- static DEVICE_ATTR(mcast_flooding, 0644, qeth_vnicc_char_show,
- qeth_vnicc_char_store);
- static DEVICE_ATTR(learning, 0644, qeth_vnicc_char_show, qeth_vnicc_char_store);
- static DEVICE_ATTR(learning_timeout, 0644, qeth_vnicc_timeout_show,
- qeth_vnicc_timeout_store);
- static DEVICE_ATTR(takeover_setvmac, 0644, qeth_vnicc_char_show,
- qeth_vnicc_char_store);
- static DEVICE_ATTR(takeover_learning, 0644, qeth_vnicc_char_show,
- qeth_vnicc_char_store);
- static DEVICE_ATTR(bridge_invisible, 0644, qeth_vnicc_char_show,
- qeth_vnicc_char_store);
- static DEVICE_ATTR(rx_bcast, 0644, qeth_vnicc_char_show, qeth_vnicc_char_store);
- static struct attribute *qeth_l2_vnicc_attrs[] = {
- &dev_attr_flooding.attr,
- &dev_attr_mcast_flooding.attr,
- &dev_attr_learning.attr,
- &dev_attr_learning_timeout.attr,
- &dev_attr_takeover_setvmac.attr,
- &dev_attr_takeover_learning.attr,
- &dev_attr_bridge_invisible.attr,
- &dev_attr_rx_bcast.attr,
- NULL,
- };
- static struct attribute_group qeth_l2_vnicc_attr_group = {
- .attrs = qeth_l2_vnicc_attrs,
- .name = "vnicc",
- };
- const struct attribute_group *qeth_l2_attr_groups[] = {
- &qeth_l2_bridgeport_attr_group,
- &qeth_l2_vnicc_attr_group,
- NULL,
- };
|