123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283 |
- /*
- * Copyright IBM Corp. 2013
- * Author(s): Eugene Crosser <eugene.crosser@ru.ibm.com>
- */
- #include <linux/slab.h>
- #include <asm/ebcdic.h>
- #include "qeth_core.h"
- #include "qeth_l2.h"
- #define QETH_DEVICE_ATTR(_id, _name, _mode, _show, _store) \
- struct device_attribute dev_attr_##_id = __ATTR(_name, _mode, _show, _store)
- 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 (!card)
- return -EINVAL;
- 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);
- }
- return rc;
- }
- static ssize_t qeth_bridge_port_role_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- 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 (!card)
- return -EINVAL;
- 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);
- 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->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)
- {
- 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 (!card)
- return -EINVAL;
- 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);
- int rc = 0;
- int enable;
- if (!card)
- return -EINVAL;
- if (sysfs_streq(buf, "0"))
- enable = 0;
- else if (sysfs_streq(buf, "1"))
- enable = 1;
- else
- return -EINVAL;
- mutex_lock(&card->conf_mutex);
- if (qeth_card_hw_is_reachable(card)) {
- rc = qeth_bridgeport_an_set(card, enable);
- if (!rc)
- card->options.sbp.hostnotification = enable;
- } else
- card->options.sbp.hostnotification = enable;
- 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 (!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,
- };
- static struct attribute_group qeth_l2_bridgeport_attr_group = {
- .attrs = qeth_l2_bridgeport_attrs,
- };
- int qeth_l2_create_device_attributes(struct device *dev)
- {
- return sysfs_create_group(&dev->kobj, &qeth_l2_bridgeport_attr_group);
- }
- void qeth_l2_remove_device_attributes(struct device *dev)
- {
- sysfs_remove_group(&dev->kobj, &qeth_l2_bridgeport_attr_group);
- }
- /**
- * qeth_l2_setup_bridgeport_attrs() - set/restore attrs when turning online.
- * @card: qeth_card structure pointer
- *
- * Note: this function is called with conf_mutex held by the caller
- */
- void qeth_l2_setup_bridgeport_attrs(struct qeth_card *card)
- {
- int rc;
- if (!card)
- return;
- if (!card->options.sbp.supported_funcs)
- return;
- if (card->options.sbp.role != QETH_SBP_ROLE_NONE) {
- /* Conditional to avoid spurious error messages */
- qeth_bridgeport_setrole(card, card->options.sbp.role);
- /* Let the callback function refresh the stored role value. */
- qeth_bridgeport_query_ports(card,
- &card->options.sbp.role, NULL);
- }
- if (card->options.sbp.hostnotification) {
- rc = qeth_bridgeport_an_set(card, 1);
- if (rc)
- card->options.sbp.hostnotification = 0;
- } else
- qeth_bridgeport_an_set(card, 0);
- }
- const struct attribute_group *qeth_l2_attr_groups[] = {
- &qeth_device_attr_group,
- &qeth_device_blkt_group,
- /* l2 specific, see l2_{create,remove}_device_attributes(): */
- &qeth_l2_bridgeport_attr_group,
- NULL,
- };
|