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 12 static 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_l2_vnicc_is_in_use(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 63 static 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_l2_vnicc_is_in_use(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 74 static 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_l2_vnicc_is_in_use(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 111 static DEVICE_ATTR(bridge_role, 0644, qeth_bridge_port_role_show, 112 qeth_bridge_port_role_store); 113 114 static 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_l2_vnicc_is_in_use(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 125 static DEVICE_ATTR(bridge_state, 0444, qeth_bridge_port_state_show, 126 NULL); 127 128 static 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_l2_vnicc_is_in_use(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 142 static 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_l2_vnicc_is_in_use(card)) 157 rc = -EBUSY; 158 else if (qeth_card_hw_is_reachable(card)) { 159 rc = qeth_bridgeport_an_set(card, enable); 160 if (!rc) 161 card->options.sbp.hostnotification = enable; 162 } else 163 card->options.sbp.hostnotification = enable; 164 165 mutex_unlock(&card->sbp_lock); 166 mutex_unlock(&card->conf_mutex); 167 168 return rc ? rc : count; 169 } 170 171 static DEVICE_ATTR(bridge_hostnotify, 0644, 172 qeth_bridgeport_hostnotification_show, 173 qeth_bridgeport_hostnotification_store); 174 175 static ssize_t qeth_bridgeport_reflect_show(struct device *dev, 176 struct device_attribute *attr, char *buf) 177 { 178 struct qeth_card *card = dev_get_drvdata(dev); 179 char *state; 180 181 if (qeth_l2_vnicc_is_in_use(card)) 182 return sprintf(buf, "n/a (VNIC characteristics)\n"); 183 184 if (card->options.sbp.reflect_promisc) { 185 if (card->options.sbp.reflect_promisc_primary) 186 state = "primary"; 187 else 188 state = "secondary"; 189 } else 190 state = "none"; 191 192 return sprintf(buf, "%s\n", state); 193 } 194 195 static ssize_t qeth_bridgeport_reflect_store(struct device *dev, 196 struct device_attribute *attr, const char *buf, size_t count) 197 { 198 struct qeth_card *card = dev_get_drvdata(dev); 199 int enable, primary; 200 int rc = 0; 201 202 if (sysfs_streq(buf, "none")) { 203 enable = 0; 204 primary = 0; 205 } else if (sysfs_streq(buf, "primary")) { 206 enable = 1; 207 primary = 1; 208 } else if (sysfs_streq(buf, "secondary")) { 209 enable = 1; 210 primary = 0; 211 } else 212 return -EINVAL; 213 214 mutex_lock(&card->conf_mutex); 215 mutex_lock(&card->sbp_lock); 216 217 if (qeth_l2_vnicc_is_in_use(card)) 218 rc = -EBUSY; 219 else if (card->options.sbp.role != QETH_SBP_ROLE_NONE) 220 rc = -EPERM; 221 else { 222 card->options.sbp.reflect_promisc = enable; 223 card->options.sbp.reflect_promisc_primary = primary; 224 rc = 0; 225 } 226 227 mutex_unlock(&card->sbp_lock); 228 mutex_unlock(&card->conf_mutex); 229 230 return rc ? rc : count; 231 } 232 233 static DEVICE_ATTR(bridge_reflect_promisc, 0644, 234 qeth_bridgeport_reflect_show, 235 qeth_bridgeport_reflect_store); 236 237 static struct attribute *qeth_l2_bridgeport_attrs[] = { 238 &dev_attr_bridge_role.attr, 239 &dev_attr_bridge_state.attr, 240 &dev_attr_bridge_hostnotify.attr, 241 &dev_attr_bridge_reflect_promisc.attr, 242 NULL, 243 }; 244 245 static struct attribute_group qeth_l2_bridgeport_attr_group = { 246 .attrs = qeth_l2_bridgeport_attrs, 247 }; 248 249 /** 250 * qeth_l2_setup_bridgeport_attrs() - set/restore attrs when turning online. 251 * @card: qeth_card structure pointer 252 * 253 * Note: this function is called with conf_mutex held by the caller 254 */ 255 void qeth_l2_setup_bridgeport_attrs(struct qeth_card *card) 256 { 257 int rc; 258 259 if (!card) 260 return; 261 if (!card->options.sbp.supported_funcs) 262 return; 263 264 mutex_lock(&card->sbp_lock); 265 if (card->options.sbp.role != QETH_SBP_ROLE_NONE) { 266 /* Conditional to avoid spurious error messages */ 267 qeth_bridgeport_setrole(card, card->options.sbp.role); 268 /* Let the callback function refresh the stored role value. */ 269 qeth_bridgeport_query_ports(card, 270 &card->options.sbp.role, NULL); 271 } 272 if (card->options.sbp.hostnotification) { 273 rc = qeth_bridgeport_an_set(card, 1); 274 if (rc) 275 card->options.sbp.hostnotification = 0; 276 } else { 277 qeth_bridgeport_an_set(card, 0); 278 } 279 mutex_unlock(&card->sbp_lock); 280 } 281 282 /* VNIC CHARS support */ 283 284 /* convert sysfs attr name to VNIC characteristic */ 285 static u32 qeth_l2_vnicc_sysfs_attr_to_char(const char *attr_name) 286 { 287 if (sysfs_streq(attr_name, "flooding")) 288 return QETH_VNICC_FLOODING; 289 else if (sysfs_streq(attr_name, "mcast_flooding")) 290 return QETH_VNICC_MCAST_FLOODING; 291 else if (sysfs_streq(attr_name, "learning")) 292 return QETH_VNICC_LEARNING; 293 else if (sysfs_streq(attr_name, "takeover_setvmac")) 294 return QETH_VNICC_TAKEOVER_SETVMAC; 295 else if (sysfs_streq(attr_name, "takeover_learning")) 296 return QETH_VNICC_TAKEOVER_LEARNING; 297 else if (sysfs_streq(attr_name, "bridge_invisible")) 298 return QETH_VNICC_BRIDGE_INVISIBLE; 299 else if (sysfs_streq(attr_name, "rx_bcast")) 300 return QETH_VNICC_RX_BCAST; 301 302 return 0; 303 } 304 305 /* get current timeout setting */ 306 static ssize_t qeth_vnicc_timeout_show(struct device *dev, 307 struct device_attribute *attr, char *buf) 308 { 309 struct qeth_card *card = dev_get_drvdata(dev); 310 u32 timeout; 311 int rc; 312 313 rc = qeth_l2_vnicc_get_timeout(card, &timeout); 314 if (rc == -EBUSY) 315 return sprintf(buf, "n/a (BridgePort)\n"); 316 if (rc == -EOPNOTSUPP) 317 return sprintf(buf, "n/a\n"); 318 return rc ? rc : sprintf(buf, "%d\n", timeout); 319 } 320 321 /* change timeout setting */ 322 static ssize_t qeth_vnicc_timeout_store(struct device *dev, 323 struct device_attribute *attr, 324 const char *buf, size_t count) 325 { 326 struct qeth_card *card = dev_get_drvdata(dev); 327 u32 timeout; 328 int rc; 329 330 rc = kstrtou32(buf, 10, &timeout); 331 if (rc) 332 return rc; 333 334 mutex_lock(&card->conf_mutex); 335 rc = qeth_l2_vnicc_set_timeout(card, timeout); 336 mutex_unlock(&card->conf_mutex); 337 return rc ? rc : count; 338 } 339 340 /* get current setting of characteristic */ 341 static ssize_t qeth_vnicc_char_show(struct device *dev, 342 struct device_attribute *attr, char *buf) 343 { 344 struct qeth_card *card = dev_get_drvdata(dev); 345 bool state; 346 u32 vnicc; 347 int rc; 348 349 vnicc = qeth_l2_vnicc_sysfs_attr_to_char(attr->attr.name); 350 rc = qeth_l2_vnicc_get_state(card, vnicc, &state); 351 352 if (rc == -EBUSY) 353 return sprintf(buf, "n/a (BridgePort)\n"); 354 if (rc == -EOPNOTSUPP) 355 return sprintf(buf, "n/a\n"); 356 return rc ? rc : sprintf(buf, "%d\n", state); 357 } 358 359 /* change setting of characteristic */ 360 static ssize_t qeth_vnicc_char_store(struct device *dev, 361 struct device_attribute *attr, 362 const char *buf, size_t count) 363 { 364 struct qeth_card *card = dev_get_drvdata(dev); 365 bool state; 366 u32 vnicc; 367 int rc; 368 369 if (kstrtobool(buf, &state)) 370 return -EINVAL; 371 372 vnicc = qeth_l2_vnicc_sysfs_attr_to_char(attr->attr.name); 373 mutex_lock(&card->conf_mutex); 374 rc = qeth_l2_vnicc_set_state(card, vnicc, state); 375 mutex_unlock(&card->conf_mutex); 376 377 return rc ? rc : count; 378 } 379 380 static DEVICE_ATTR(flooding, 0644, qeth_vnicc_char_show, qeth_vnicc_char_store); 381 static DEVICE_ATTR(mcast_flooding, 0644, qeth_vnicc_char_show, 382 qeth_vnicc_char_store); 383 static DEVICE_ATTR(learning, 0644, qeth_vnicc_char_show, qeth_vnicc_char_store); 384 static DEVICE_ATTR(learning_timeout, 0644, qeth_vnicc_timeout_show, 385 qeth_vnicc_timeout_store); 386 static DEVICE_ATTR(takeover_setvmac, 0644, qeth_vnicc_char_show, 387 qeth_vnicc_char_store); 388 static DEVICE_ATTR(takeover_learning, 0644, qeth_vnicc_char_show, 389 qeth_vnicc_char_store); 390 static DEVICE_ATTR(bridge_invisible, 0644, qeth_vnicc_char_show, 391 qeth_vnicc_char_store); 392 static DEVICE_ATTR(rx_bcast, 0644, qeth_vnicc_char_show, qeth_vnicc_char_store); 393 394 static struct attribute *qeth_l2_vnicc_attrs[] = { 395 &dev_attr_flooding.attr, 396 &dev_attr_mcast_flooding.attr, 397 &dev_attr_learning.attr, 398 &dev_attr_learning_timeout.attr, 399 &dev_attr_takeover_setvmac.attr, 400 &dev_attr_takeover_learning.attr, 401 &dev_attr_bridge_invisible.attr, 402 &dev_attr_rx_bcast.attr, 403 NULL, 404 }; 405 406 static struct attribute_group qeth_l2_vnicc_attr_group = { 407 .attrs = qeth_l2_vnicc_attrs, 408 .name = "vnicc", 409 }; 410 411 static const struct attribute_group *qeth_l2_only_attr_groups[] = { 412 &qeth_l2_bridgeport_attr_group, 413 &qeth_l2_vnicc_attr_group, 414 NULL, 415 }; 416 417 int qeth_l2_create_device_attributes(struct device *dev) 418 { 419 return sysfs_create_groups(&dev->kobj, qeth_l2_only_attr_groups); 420 } 421 422 void qeth_l2_remove_device_attributes(struct device *dev) 423 { 424 sysfs_remove_groups(&dev->kobj, qeth_l2_only_attr_groups); 425 } 426 427 const struct attribute_group *qeth_l2_attr_groups[] = { 428 &qeth_device_attr_group, 429 &qeth_device_blkt_group, 430 /* l2 specific, see qeth_l2_only_attr_groups: */ 431 &qeth_l2_bridgeport_attr_group, 432 &qeth_l2_vnicc_attr_group, 433 NULL, 434 }; 435