linux/drivers/s390/net/qeth_l2_sys.c
<<
>>
Prefs
   1/*
   2 *    Copyright IBM Corp. 2013
   3 *    Author(s): Eugene Crosser <eugene.crosser@ru.ibm.com>
   4 */
   5
   6#include <linux/slab.h>
   7#include <asm/ebcdic.h>
   8#include "qeth_core.h"
   9#include "qeth_l2.h"
  10
  11#define QETH_DEVICE_ATTR(_id, _name, _mode, _show, _store) \
  12struct device_attribute dev_attr_##_id = __ATTR(_name, _mode, _show, _store)
  13
  14static ssize_t qeth_bridge_port_role_state_show(struct device *dev,
  15                                struct device_attribute *attr, char *buf,
  16                                int show_state)
  17{
  18        struct qeth_card *card = dev_get_drvdata(dev);
  19        enum qeth_sbp_states state = QETH_SBP_STATE_INACTIVE;
  20        int rc = 0;
  21        char *word;
  22
  23        if (!card)
  24                return -EINVAL;
  25
  26        if (qeth_card_hw_is_reachable(card) &&
  27                                        card->options.sbp.supported_funcs)
  28                rc = qeth_bridgeport_query_ports(card,
  29                        &card->options.sbp.role, &state);
  30        if (!rc) {
  31                if (show_state)
  32                        switch (state) {
  33                        case QETH_SBP_STATE_INACTIVE:
  34                                word = "inactive"; break;
  35                        case QETH_SBP_STATE_STANDBY:
  36                                word = "standby"; break;
  37                        case QETH_SBP_STATE_ACTIVE:
  38                                word = "active"; break;
  39                        default:
  40                                rc = -EIO;
  41                        }
  42                else
  43                        switch (card->options.sbp.role) {
  44                        case QETH_SBP_ROLE_NONE:
  45                                word = "none"; break;
  46                        case QETH_SBP_ROLE_PRIMARY:
  47                                word = "primary"; break;
  48                        case QETH_SBP_ROLE_SECONDARY:
  49                                word = "secondary"; break;
  50                        default:
  51                                rc = -EIO;
  52                        }
  53                if (rc)
  54                        QETH_CARD_TEXT_(card, 2, "SBP%02x:%02x",
  55                                card->options.sbp.role, state);
  56                else
  57                        rc = sprintf(buf, "%s\n", word);
  58        }
  59
  60        return rc;
  61}
  62
  63static ssize_t qeth_bridge_port_role_show(struct device *dev,
  64                                struct device_attribute *attr, char *buf)
  65{
  66        return qeth_bridge_port_role_state_show(dev, attr, buf, 0);
  67}
  68
  69static ssize_t qeth_bridge_port_role_store(struct device *dev,
  70                struct device_attribute *attr, const char *buf, size_t count)
  71{
  72        struct qeth_card *card = dev_get_drvdata(dev);
  73        int rc = 0;
  74        enum qeth_sbp_roles role;
  75
  76        if (!card)
  77                return -EINVAL;
  78        if (sysfs_streq(buf, "primary"))
  79                role = QETH_SBP_ROLE_PRIMARY;
  80        else if (sysfs_streq(buf, "secondary"))
  81                role = QETH_SBP_ROLE_SECONDARY;
  82        else if (sysfs_streq(buf, "none"))
  83                role = QETH_SBP_ROLE_NONE;
  84        else
  85                return -EINVAL;
  86
  87        mutex_lock(&card->conf_mutex);
  88
  89        if (card->options.sbp.reflect_promisc) /* Forbid direct manipulation */
  90                rc = -EPERM;
  91        else if (qeth_card_hw_is_reachable(card)) {
  92                rc = qeth_bridgeport_setrole(card, role);
  93                if (!rc)
  94                        card->options.sbp.role = role;
  95        } else
  96                card->options.sbp.role = role;
  97
  98        mutex_unlock(&card->conf_mutex);
  99
 100        return rc ? rc : count;
 101}
 102
 103static DEVICE_ATTR(bridge_role, 0644, qeth_bridge_port_role_show,
 104                   qeth_bridge_port_role_store);
 105
 106static ssize_t qeth_bridge_port_state_show(struct device *dev,
 107                                struct device_attribute *attr, char *buf)
 108{
 109        return qeth_bridge_port_role_state_show(dev, attr, buf, 1);
 110}
 111
 112static DEVICE_ATTR(bridge_state, 0444, qeth_bridge_port_state_show,
 113                   NULL);
 114
 115static ssize_t qeth_bridgeport_hostnotification_show(struct device *dev,
 116                                struct device_attribute *attr, char *buf)
 117{
 118        struct qeth_card *card = dev_get_drvdata(dev);
 119        int enabled;
 120
 121        if (!card)
 122                return -EINVAL;
 123
 124        enabled = card->options.sbp.hostnotification;
 125
 126        return sprintf(buf, "%d\n", enabled);
 127}
 128
 129static ssize_t qeth_bridgeport_hostnotification_store(struct device *dev,
 130                struct device_attribute *attr, const char *buf, size_t count)
 131{
 132        struct qeth_card *card = dev_get_drvdata(dev);
 133        int rc = 0;
 134        int enable;
 135
 136        if (!card)
 137                return -EINVAL;
 138
 139        if (sysfs_streq(buf, "0"))
 140                enable = 0;
 141        else if (sysfs_streq(buf, "1"))
 142                enable = 1;
 143        else
 144                return -EINVAL;
 145
 146        mutex_lock(&card->conf_mutex);
 147
 148        if (qeth_card_hw_is_reachable(card)) {
 149                rc = qeth_bridgeport_an_set(card, enable);
 150                if (!rc)
 151                        card->options.sbp.hostnotification = enable;
 152        } else
 153                card->options.sbp.hostnotification = enable;
 154
 155        mutex_unlock(&card->conf_mutex);
 156
 157        return rc ? rc : count;
 158}
 159
 160static DEVICE_ATTR(bridge_hostnotify, 0644,
 161                        qeth_bridgeport_hostnotification_show,
 162                        qeth_bridgeport_hostnotification_store);
 163
 164static ssize_t qeth_bridgeport_reflect_show(struct device *dev,
 165                                struct device_attribute *attr, char *buf)
 166{
 167        struct qeth_card *card = dev_get_drvdata(dev);
 168        char *state;
 169
 170        if (!card)
 171                return -EINVAL;
 172
 173        if (card->options.sbp.reflect_promisc) {
 174                if (card->options.sbp.reflect_promisc_primary)
 175                        state = "primary";
 176                else
 177                        state = "secondary";
 178        } else
 179                state = "none";
 180
 181        return sprintf(buf, "%s\n", state);
 182}
 183
 184static ssize_t qeth_bridgeport_reflect_store(struct device *dev,
 185                struct device_attribute *attr, const char *buf, size_t count)
 186{
 187        struct qeth_card *card = dev_get_drvdata(dev);
 188        int enable, primary;
 189        int rc = 0;
 190
 191        if (!card)
 192                return -EINVAL;
 193
 194        if (sysfs_streq(buf, "none")) {
 195                enable = 0;
 196                primary = 0;
 197        } else if (sysfs_streq(buf, "primary")) {
 198                enable = 1;
 199                primary = 1;
 200        } else if (sysfs_streq(buf, "secondary")) {
 201                enable = 1;
 202                primary = 0;
 203        } else
 204                return -EINVAL;
 205
 206        mutex_lock(&card->conf_mutex);
 207
 208        if (card->options.sbp.role != QETH_SBP_ROLE_NONE)
 209                rc = -EPERM;
 210        else {
 211                card->options.sbp.reflect_promisc = enable;
 212                card->options.sbp.reflect_promisc_primary = primary;
 213                rc = 0;
 214        }
 215
 216        mutex_unlock(&card->conf_mutex);
 217
 218        return rc ? rc : count;
 219}
 220
 221static DEVICE_ATTR(bridge_reflect_promisc, 0644,
 222                        qeth_bridgeport_reflect_show,
 223                        qeth_bridgeport_reflect_store);
 224
 225static struct attribute *qeth_l2_bridgeport_attrs[] = {
 226        &dev_attr_bridge_role.attr,
 227        &dev_attr_bridge_state.attr,
 228        &dev_attr_bridge_hostnotify.attr,
 229        &dev_attr_bridge_reflect_promisc.attr,
 230        NULL,
 231};
 232
 233static struct attribute_group qeth_l2_bridgeport_attr_group = {
 234        .attrs = qeth_l2_bridgeport_attrs,
 235};
 236
 237int qeth_l2_create_device_attributes(struct device *dev)
 238{
 239        return sysfs_create_group(&dev->kobj, &qeth_l2_bridgeport_attr_group);
 240}
 241
 242void qeth_l2_remove_device_attributes(struct device *dev)
 243{
 244        sysfs_remove_group(&dev->kobj, &qeth_l2_bridgeport_attr_group);
 245}
 246
 247/**
 248 * qeth_l2_setup_bridgeport_attrs() - set/restore attrs when turning online.
 249 * @card:                             qeth_card structure pointer
 250 *
 251 * Note: this function is called with conf_mutex held by the caller
 252 */
 253void qeth_l2_setup_bridgeport_attrs(struct qeth_card *card)
 254{
 255        int rc;
 256
 257        if (!card)
 258                return;
 259        if (!card->options.sbp.supported_funcs)
 260                return;
 261        if (card->options.sbp.role != QETH_SBP_ROLE_NONE) {
 262                /* Conditional to avoid spurious error messages */
 263                qeth_bridgeport_setrole(card, card->options.sbp.role);
 264                /* Let the callback function refresh the stored role value. */
 265                qeth_bridgeport_query_ports(card,
 266                        &card->options.sbp.role, NULL);
 267        }
 268        if (card->options.sbp.hostnotification) {
 269                rc = qeth_bridgeport_an_set(card, 1);
 270                if (rc)
 271                        card->options.sbp.hostnotification = 0;
 272        } else
 273                qeth_bridgeport_an_set(card, 0);
 274}
 275