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_l2.h"
   9
  10#define QETH_DEVICE_ATTR(_id, _name, _mode, _show, _store) \
  11struct device_attribute dev_attr_##_id = __ATTR(_name, _mode, _show, _store)
  12
  13static int qeth_card_hw_is_reachable(struct qeth_card *card)
  14{
  15        return (card->state == CARD_STATE_SOFTSETUP) ||
  16                (card->state == CARD_STATE_UP);
  17}
  18
  19static ssize_t qeth_bridge_port_role_state_show(struct device *dev,
  20                                struct device_attribute *attr, char *buf,
  21                                int show_state)
  22{
  23        struct qeth_card *card = dev_get_drvdata(dev);
  24        enum qeth_sbp_states state = QETH_SBP_STATE_INACTIVE;
  25        int rc = 0;
  26        char *word;
  27
  28        if (!card)
  29                return -EINVAL;
  30
  31        mutex_lock(&card->conf_mutex);
  32
  33        if (qeth_card_hw_is_reachable(card) &&
  34                                        card->options.sbp.supported_funcs)
  35                rc = qeth_bridgeport_query_ports(card,
  36                        &card->options.sbp.role, &state);
  37        if (!rc) {
  38                if (show_state)
  39                        switch (state) {
  40                        case QETH_SBP_STATE_INACTIVE:
  41                                word = "inactive"; break;
  42                        case QETH_SBP_STATE_STANDBY:
  43                                word = "standby"; break;
  44                        case QETH_SBP_STATE_ACTIVE:
  45                                word = "active"; break;
  46                        default:
  47                                rc = -EIO;
  48                        }
  49                else
  50                        switch (card->options.sbp.role) {
  51                        case QETH_SBP_ROLE_NONE:
  52                                word = "none"; break;
  53                        case QETH_SBP_ROLE_PRIMARY:
  54                                word = "primary"; break;
  55                        case QETH_SBP_ROLE_SECONDARY:
  56                                word = "secondary"; break;
  57                        default:
  58                                rc = -EIO;
  59                        }
  60                if (rc)
  61                        QETH_CARD_TEXT_(card, 2, "SBP%02x:%02x",
  62                                card->options.sbp.role, state);
  63                else
  64                        rc = sprintf(buf, "%s\n", word);
  65        }
  66
  67        mutex_unlock(&card->conf_mutex);
  68
  69        return rc;
  70}
  71
  72static ssize_t qeth_bridge_port_role_show(struct device *dev,
  73                                struct device_attribute *attr, char *buf)
  74{
  75        return qeth_bridge_port_role_state_show(dev, attr, buf, 0);
  76}
  77
  78static ssize_t qeth_bridge_port_role_store(struct device *dev,
  79                struct device_attribute *attr, const char *buf, size_t count)
  80{
  81        struct qeth_card *card = dev_get_drvdata(dev);
  82        int rc = 0;
  83        enum qeth_sbp_roles role;
  84
  85        if (!card)
  86                return -EINVAL;
  87        if (sysfs_streq(buf, "primary"))
  88                role = QETH_SBP_ROLE_PRIMARY;
  89        else if (sysfs_streq(buf, "secondary"))
  90                role = QETH_SBP_ROLE_SECONDARY;
  91        else if (sysfs_streq(buf, "none"))
  92                role = QETH_SBP_ROLE_NONE;
  93        else
  94                return -EINVAL;
  95
  96        mutex_lock(&card->conf_mutex);
  97
  98        if (qeth_card_hw_is_reachable(card)) {
  99                rc = qeth_bridgeport_setrole(card, role);
 100                if (!rc)
 101                        card->options.sbp.role = role;
 102        } else
 103                card->options.sbp.role = role;
 104
 105        mutex_unlock(&card->conf_mutex);
 106
 107        return rc ? rc : count;
 108}
 109
 110static DEVICE_ATTR(bridge_role, 0644, qeth_bridge_port_role_show,
 111                   qeth_bridge_port_role_store);
 112
 113static ssize_t qeth_bridge_port_state_show(struct device *dev,
 114                                struct device_attribute *attr, char *buf)
 115{
 116        return qeth_bridge_port_role_state_show(dev, attr, buf, 1);
 117}
 118
 119static DEVICE_ATTR(bridge_state, 0644, qeth_bridge_port_state_show,
 120                   NULL);
 121
 122static ssize_t qeth_bridgeport_hostnotification_show(struct device *dev,
 123                                struct device_attribute *attr, char *buf)
 124{
 125        struct qeth_card *card = dev_get_drvdata(dev);
 126        int enabled;
 127
 128        if (!card)
 129                return -EINVAL;
 130
 131        mutex_lock(&card->conf_mutex);
 132
 133        enabled = card->options.sbp.hostnotification;
 134
 135        mutex_unlock(&card->conf_mutex);
 136
 137        return sprintf(buf, "%d\n", enabled);
 138}
 139
 140static ssize_t qeth_bridgeport_hostnotification_store(struct device *dev,
 141                struct device_attribute *attr, const char *buf, size_t count)
 142{
 143        struct qeth_card *card = dev_get_drvdata(dev);
 144        int rc = 0;
 145        int enable;
 146
 147        if (!card)
 148                return -EINVAL;
 149
 150        if (sysfs_streq(buf, "0"))
 151                enable = 0;
 152        else if (sysfs_streq(buf, "1"))
 153                enable = 1;
 154        else
 155                return -EINVAL;
 156
 157        mutex_lock(&card->conf_mutex);
 158
 159        if (qeth_card_hw_is_reachable(card)) {
 160                rc = qeth_bridgeport_an_set(card, enable);
 161                if (!rc)
 162                        card->options.sbp.hostnotification = enable;
 163        } else
 164                card->options.sbp.hostnotification = enable;
 165
 166        mutex_unlock(&card->conf_mutex);
 167
 168        return rc ? rc : count;
 169}
 170
 171static DEVICE_ATTR(bridge_hostnotify, 0644,
 172                        qeth_bridgeport_hostnotification_show,
 173                        qeth_bridgeport_hostnotification_store);
 174
 175static struct attribute *qeth_l2_bridgeport_attrs[] = {
 176        &dev_attr_bridge_role.attr,
 177        &dev_attr_bridge_state.attr,
 178        &dev_attr_bridge_hostnotify.attr,
 179        NULL,
 180};
 181
 182static struct attribute_group qeth_l2_bridgeport_attr_group = {
 183        .attrs = qeth_l2_bridgeport_attrs,
 184};
 185
 186int qeth_l2_create_device_attributes(struct device *dev)
 187{
 188        return sysfs_create_group(&dev->kobj, &qeth_l2_bridgeport_attr_group);
 189}
 190
 191void qeth_l2_remove_device_attributes(struct device *dev)
 192{
 193        sysfs_remove_group(&dev->kobj, &qeth_l2_bridgeport_attr_group);
 194}
 195
 196/**
 197 * qeth_l2_setup_bridgeport_attrs() - set/restore attrs when turning online.
 198 * @card:                             qeth_card structure pointer
 199 *
 200 * Note: this function is called with conf_mutex held by the caller
 201 */
 202void qeth_l2_setup_bridgeport_attrs(struct qeth_card *card)
 203{
 204        int rc;
 205
 206        if (!card)
 207                return;
 208        if (!card->options.sbp.supported_funcs)
 209                return;
 210        if (card->options.sbp.role != QETH_SBP_ROLE_NONE) {
 211                /* Conditional to avoid spurious error messages */
 212                qeth_bridgeport_setrole(card, card->options.sbp.role);
 213                /* Let the callback function refresh the stored role value. */
 214                qeth_bridgeport_query_ports(card,
 215                        &card->options.sbp.role, NULL);
 216        }
 217        if (card->options.sbp.hostnotification) {
 218                rc = qeth_bridgeport_an_set(card, 1);
 219                if (rc)
 220                        card->options.sbp.hostnotification = 0;
 221        } else
 222                qeth_bridgeport_an_set(card, 0);
 223}
 224