qeth_l2_sys.c (10156B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright IBM Corp. 2013 4 * Author(s): Eugene Crosser <eugene.crosser@ru.ibm.com> 5 */ 6 7#include <linux/slab.h> 8#include <asm/ebcdic.h> 9#include "qeth_core.h" 10#include "qeth_l2.h" 11 12static ssize_t qeth_bridge_port_role_state_show(struct device *dev, 13 struct device_attribute *attr, char *buf, 14 int show_state) 15{ 16 struct qeth_card *card = dev_get_drvdata(dev); 17 enum qeth_sbp_states state = QETH_SBP_STATE_INACTIVE; 18 int rc = 0; 19 char *word; 20 21 if (!qeth_bridgeport_allowed(card)) 22 return sprintf(buf, "n/a (VNIC characteristics)\n"); 23 24 mutex_lock(&card->sbp_lock); 25 if (qeth_card_hw_is_reachable(card) && 26 card->options.sbp.supported_funcs) 27 rc = qeth_bridgeport_query_ports(card, 28 &card->options.sbp.role, &state); 29 if (!rc) { 30 if (show_state) 31 switch (state) { 32 case QETH_SBP_STATE_INACTIVE: 33 word = "inactive"; break; 34 case QETH_SBP_STATE_STANDBY: 35 word = "standby"; break; 36 case QETH_SBP_STATE_ACTIVE: 37 word = "active"; break; 38 default: 39 rc = -EIO; 40 } 41 else 42 switch (card->options.sbp.role) { 43 case QETH_SBP_ROLE_NONE: 44 word = "none"; break; 45 case QETH_SBP_ROLE_PRIMARY: 46 word = "primary"; break; 47 case QETH_SBP_ROLE_SECONDARY: 48 word = "secondary"; break; 49 default: 50 rc = -EIO; 51 } 52 if (rc) 53 QETH_CARD_TEXT_(card, 2, "SBP%02x:%02x", 54 card->options.sbp.role, state); 55 else 56 rc = sprintf(buf, "%s\n", word); 57 } 58 mutex_unlock(&card->sbp_lock); 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 struct qeth_card *card = dev_get_drvdata(dev); 67 68 if (!qeth_bridgeport_allowed(card)) 69 return sprintf(buf, "n/a (VNIC characteristics)\n"); 70 71 return qeth_bridge_port_role_state_show(dev, attr, buf, 0); 72} 73 74static ssize_t qeth_bridge_port_role_store(struct device *dev, 75 struct device_attribute *attr, const char *buf, size_t count) 76{ 77 struct qeth_card *card = dev_get_drvdata(dev); 78 int rc = 0; 79 enum qeth_sbp_roles role; 80 81 if (sysfs_streq(buf, "primary")) 82 role = QETH_SBP_ROLE_PRIMARY; 83 else if (sysfs_streq(buf, "secondary")) 84 role = QETH_SBP_ROLE_SECONDARY; 85 else if (sysfs_streq(buf, "none")) 86 role = QETH_SBP_ROLE_NONE; 87 else 88 return -EINVAL; 89 90 mutex_lock(&card->conf_mutex); 91 mutex_lock(&card->sbp_lock); 92 93 if (!qeth_bridgeport_allowed(card)) 94 rc = -EBUSY; 95 else if (card->options.sbp.reflect_promisc) 96 /* Forbid direct manipulation */ 97 rc = -EPERM; 98 else 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->sbp_lock); 106 mutex_unlock(&card->conf_mutex); 107 108 return rc ? rc : count; 109} 110 111static DEVICE_ATTR(bridge_role, 0644, qeth_bridge_port_role_show, 112 qeth_bridge_port_role_store); 113 114static ssize_t qeth_bridge_port_state_show(struct device *dev, 115 struct device_attribute *attr, char *buf) 116{ 117 struct qeth_card *card = dev_get_drvdata(dev); 118 119 if (!qeth_bridgeport_allowed(card)) 120 return sprintf(buf, "n/a (VNIC characteristics)\n"); 121 122 return qeth_bridge_port_role_state_show(dev, attr, buf, 1); 123} 124 125static DEVICE_ATTR(bridge_state, 0444, qeth_bridge_port_state_show, 126 NULL); 127 128static ssize_t qeth_bridgeport_hostnotification_show(struct device *dev, 129 struct device_attribute *attr, char *buf) 130{ 131 struct qeth_card *card = dev_get_drvdata(dev); 132 int enabled; 133 134 if (!qeth_bridgeport_allowed(card)) 135 return sprintf(buf, "n/a (VNIC characteristics)\n"); 136 137 enabled = card->options.sbp.hostnotification; 138 139 return sprintf(buf, "%d\n", enabled); 140} 141 142static ssize_t qeth_bridgeport_hostnotification_store(struct device *dev, 143 struct device_attribute *attr, const char *buf, size_t count) 144{ 145 struct qeth_card *card = dev_get_drvdata(dev); 146 bool enable; 147 int rc; 148 149 rc = kstrtobool(buf, &enable); 150 if (rc) 151 return rc; 152 153 mutex_lock(&card->conf_mutex); 154 mutex_lock(&card->sbp_lock); 155 156 if (!qeth_bridgeport_allowed(card)) 157 rc = -EBUSY; 158 else if (qeth_card_hw_is_reachable(card)) { 159 rc = qeth_bridgeport_an_set(card, enable); 160 /* sbp_lock ensures ordering vs notifications-stopped events */ 161 if (!rc) 162 card->options.sbp.hostnotification = enable; 163 } else 164 card->options.sbp.hostnotification = enable; 165 166 mutex_unlock(&card->sbp_lock); 167 mutex_unlock(&card->conf_mutex); 168 169 return rc ? rc : count; 170} 171 172static DEVICE_ATTR(bridge_hostnotify, 0644, 173 qeth_bridgeport_hostnotification_show, 174 qeth_bridgeport_hostnotification_store); 175 176static ssize_t qeth_bridgeport_reflect_show(struct device *dev, 177 struct device_attribute *attr, char *buf) 178{ 179 struct qeth_card *card = dev_get_drvdata(dev); 180 char *state; 181 182 if (!qeth_bridgeport_allowed(card)) 183 return sprintf(buf, "n/a (VNIC characteristics)\n"); 184 185 if (card->options.sbp.reflect_promisc) { 186 if (card->options.sbp.reflect_promisc_primary) 187 state = "primary"; 188 else 189 state = "secondary"; 190 } else 191 state = "none"; 192 193 return sprintf(buf, "%s\n", state); 194} 195 196static ssize_t qeth_bridgeport_reflect_store(struct device *dev, 197 struct device_attribute *attr, const char *buf, size_t count) 198{ 199 struct qeth_card *card = dev_get_drvdata(dev); 200 int enable, primary; 201 int rc = 0; 202 203 if (sysfs_streq(buf, "none")) { 204 enable = 0; 205 primary = 0; 206 } else if (sysfs_streq(buf, "primary")) { 207 enable = 1; 208 primary = 1; 209 } else if (sysfs_streq(buf, "secondary")) { 210 enable = 1; 211 primary = 0; 212 } else 213 return -EINVAL; 214 215 mutex_lock(&card->conf_mutex); 216 mutex_lock(&card->sbp_lock); 217 218 if (!qeth_bridgeport_allowed(card)) 219 rc = -EBUSY; 220 else if (card->options.sbp.role != QETH_SBP_ROLE_NONE) 221 rc = -EPERM; 222 else { 223 card->options.sbp.reflect_promisc = enable; 224 card->options.sbp.reflect_promisc_primary = primary; 225 rc = 0; 226 } 227 228 mutex_unlock(&card->sbp_lock); 229 mutex_unlock(&card->conf_mutex); 230 231 return rc ? rc : count; 232} 233 234static DEVICE_ATTR(bridge_reflect_promisc, 0644, 235 qeth_bridgeport_reflect_show, 236 qeth_bridgeport_reflect_store); 237 238static struct attribute *qeth_l2_bridgeport_attrs[] = { 239 &dev_attr_bridge_role.attr, 240 &dev_attr_bridge_state.attr, 241 &dev_attr_bridge_hostnotify.attr, 242 &dev_attr_bridge_reflect_promisc.attr, 243 NULL, 244}; 245 246static struct attribute_group qeth_l2_bridgeport_attr_group = { 247 .attrs = qeth_l2_bridgeport_attrs, 248}; 249 250/* VNIC CHARS support */ 251 252/* convert sysfs attr name to VNIC characteristic */ 253static u32 qeth_l2_vnicc_sysfs_attr_to_char(const char *attr_name) 254{ 255 if (sysfs_streq(attr_name, "flooding")) 256 return QETH_VNICC_FLOODING; 257 else if (sysfs_streq(attr_name, "mcast_flooding")) 258 return QETH_VNICC_MCAST_FLOODING; 259 else if (sysfs_streq(attr_name, "learning")) 260 return QETH_VNICC_LEARNING; 261 else if (sysfs_streq(attr_name, "takeover_setvmac")) 262 return QETH_VNICC_TAKEOVER_SETVMAC; 263 else if (sysfs_streq(attr_name, "takeover_learning")) 264 return QETH_VNICC_TAKEOVER_LEARNING; 265 else if (sysfs_streq(attr_name, "bridge_invisible")) 266 return QETH_VNICC_BRIDGE_INVISIBLE; 267 else if (sysfs_streq(attr_name, "rx_bcast")) 268 return QETH_VNICC_RX_BCAST; 269 270 return 0; 271} 272 273/* get current timeout setting */ 274static ssize_t qeth_vnicc_timeout_show(struct device *dev, 275 struct device_attribute *attr, char *buf) 276{ 277 struct qeth_card *card = dev_get_drvdata(dev); 278 u32 timeout; 279 int rc; 280 281 rc = qeth_l2_vnicc_get_timeout(card, &timeout); 282 if (rc == -EBUSY) 283 return sprintf(buf, "n/a (BridgePort)\n"); 284 if (rc == -EOPNOTSUPP) 285 return sprintf(buf, "n/a\n"); 286 return rc ? rc : sprintf(buf, "%d\n", timeout); 287} 288 289/* change timeout setting */ 290static ssize_t qeth_vnicc_timeout_store(struct device *dev, 291 struct device_attribute *attr, 292 const char *buf, size_t count) 293{ 294 struct qeth_card *card = dev_get_drvdata(dev); 295 u32 timeout; 296 int rc; 297 298 rc = kstrtou32(buf, 10, &timeout); 299 if (rc) 300 return rc; 301 302 mutex_lock(&card->conf_mutex); 303 rc = qeth_l2_vnicc_set_timeout(card, timeout); 304 mutex_unlock(&card->conf_mutex); 305 return rc ? rc : count; 306} 307 308/* get current setting of characteristic */ 309static ssize_t qeth_vnicc_char_show(struct device *dev, 310 struct device_attribute *attr, char *buf) 311{ 312 struct qeth_card *card = dev_get_drvdata(dev); 313 bool state; 314 u32 vnicc; 315 int rc; 316 317 vnicc = qeth_l2_vnicc_sysfs_attr_to_char(attr->attr.name); 318 rc = qeth_l2_vnicc_get_state(card, vnicc, &state); 319 320 if (rc == -EBUSY) 321 return sprintf(buf, "n/a (BridgePort)\n"); 322 if (rc == -EOPNOTSUPP) 323 return sprintf(buf, "n/a\n"); 324 return rc ? rc : sprintf(buf, "%d\n", state); 325} 326 327/* change setting of characteristic */ 328static ssize_t qeth_vnicc_char_store(struct device *dev, 329 struct device_attribute *attr, 330 const char *buf, size_t count) 331{ 332 struct qeth_card *card = dev_get_drvdata(dev); 333 bool state; 334 u32 vnicc; 335 int rc; 336 337 if (kstrtobool(buf, &state)) 338 return -EINVAL; 339 340 vnicc = qeth_l2_vnicc_sysfs_attr_to_char(attr->attr.name); 341 mutex_lock(&card->conf_mutex); 342 rc = qeth_l2_vnicc_set_state(card, vnicc, state); 343 mutex_unlock(&card->conf_mutex); 344 345 return rc ? rc : count; 346} 347 348static DEVICE_ATTR(flooding, 0644, qeth_vnicc_char_show, qeth_vnicc_char_store); 349static DEVICE_ATTR(mcast_flooding, 0644, qeth_vnicc_char_show, 350 qeth_vnicc_char_store); 351static DEVICE_ATTR(learning, 0644, qeth_vnicc_char_show, qeth_vnicc_char_store); 352static DEVICE_ATTR(learning_timeout, 0644, qeth_vnicc_timeout_show, 353 qeth_vnicc_timeout_store); 354static DEVICE_ATTR(takeover_setvmac, 0644, qeth_vnicc_char_show, 355 qeth_vnicc_char_store); 356static DEVICE_ATTR(takeover_learning, 0644, qeth_vnicc_char_show, 357 qeth_vnicc_char_store); 358static DEVICE_ATTR(bridge_invisible, 0644, qeth_vnicc_char_show, 359 qeth_vnicc_char_store); 360static DEVICE_ATTR(rx_bcast, 0644, qeth_vnicc_char_show, qeth_vnicc_char_store); 361 362static struct attribute *qeth_l2_vnicc_attrs[] = { 363 &dev_attr_flooding.attr, 364 &dev_attr_mcast_flooding.attr, 365 &dev_attr_learning.attr, 366 &dev_attr_learning_timeout.attr, 367 &dev_attr_takeover_setvmac.attr, 368 &dev_attr_takeover_learning.attr, 369 &dev_attr_bridge_invisible.attr, 370 &dev_attr_rx_bcast.attr, 371 NULL, 372}; 373 374static struct attribute_group qeth_l2_vnicc_attr_group = { 375 .attrs = qeth_l2_vnicc_attrs, 376 .name = "vnicc", 377}; 378 379const struct attribute_group *qeth_l2_attr_groups[] = { 380 &qeth_l2_bridgeport_attr_group, 381 &qeth_l2_vnicc_attr_group, 382 NULL, 383};