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.reflect_promisc && 266 card->options.sbp.role != QETH_SBP_ROLE_NONE) { 267 /* Conditional to avoid spurious error messages */ 268 qeth_bridgeport_setrole(card, card->options.sbp.role); 269 /* Let the callback function refresh the stored role value. */ 270 qeth_bridgeport_query_ports(card, 271 &card->options.sbp.role, NULL); 272 } 273 if (card->options.sbp.hostnotification) { 274 rc = qeth_bridgeport_an_set(card, 1); 275 if (rc) 276 card->options.sbp.hostnotification = 0; 277 } else { 278 qeth_bridgeport_an_set(card, 0); 279 } 280 mutex_unlock(&card->sbp_lock); 281 } 282 283 /* VNIC CHARS support */ 284 285 /* convert sysfs attr name to VNIC characteristic */ 286 static u32 qeth_l2_vnicc_sysfs_attr_to_char(const char *attr_name) 287 { 288 if (sysfs_streq(attr_name, "flooding")) 289 return QETH_VNICC_FLOODING; 290 else if (sysfs_streq(attr_name, "mcast_flooding")) 291 return QETH_VNICC_MCAST_FLOODING; 292 else if (sysfs_streq(attr_name, "learning")) 293 return QETH_VNICC_LEARNING; 294 else if (sysfs_streq(attr_name, "takeover_setvmac")) 295 return QETH_VNICC_TAKEOVER_SETVMAC; 296 else if (sysfs_streq(attr_name, "takeover_learning")) 297 return QETH_VNICC_TAKEOVER_LEARNING; 298 else if (sysfs_streq(attr_name, "bridge_invisible")) 299 return QETH_VNICC_BRIDGE_INVISIBLE; 300 else if (sysfs_streq(attr_name, "rx_bcast")) 301 return QETH_VNICC_RX_BCAST; 302 303 return 0; 304 } 305 306 /* get current timeout setting */ 307 static ssize_t qeth_vnicc_timeout_show(struct device *dev, 308 struct device_attribute *attr, char *buf) 309 { 310 struct qeth_card *card = dev_get_drvdata(dev); 311 u32 timeout; 312 int rc; 313 314 rc = qeth_l2_vnicc_get_timeout(card, &timeout); 315 if (rc == -EBUSY) 316 return sprintf(buf, "n/a (BridgePort)\n"); 317 if (rc == -EOPNOTSUPP) 318 return sprintf(buf, "n/a\n"); 319 return rc ? rc : sprintf(buf, "%d\n", timeout); 320 } 321 322 /* change timeout setting */ 323 static ssize_t qeth_vnicc_timeout_store(struct device *dev, 324 struct device_attribute *attr, 325 const char *buf, size_t count) 326 { 327 struct qeth_card *card = dev_get_drvdata(dev); 328 u32 timeout; 329 int rc; 330 331 rc = kstrtou32(buf, 10, &timeout); 332 if (rc) 333 return rc; 334 335 mutex_lock(&card->conf_mutex); 336 rc = qeth_l2_vnicc_set_timeout(card, timeout); 337 mutex_unlock(&card->conf_mutex); 338 return rc ? rc : count; 339 } 340 341 /* get current setting of characteristic */ 342 static ssize_t qeth_vnicc_char_show(struct device *dev, 343 struct device_attribute *attr, char *buf) 344 { 345 struct qeth_card *card = dev_get_drvdata(dev); 346 bool state; 347 u32 vnicc; 348 int rc; 349 350 vnicc = qeth_l2_vnicc_sysfs_attr_to_char(attr->attr.name); 351 rc = qeth_l2_vnicc_get_state(card, vnicc, &state); 352 353 if (rc == -EBUSY) 354 return sprintf(buf, "n/a (BridgePort)\n"); 355 if (rc == -EOPNOTSUPP) 356 return sprintf(buf, "n/a\n"); 357 return rc ? rc : sprintf(buf, "%d\n", state); 358 } 359 360 /* change setting of characteristic */ 361 static ssize_t qeth_vnicc_char_store(struct device *dev, 362 struct device_attribute *attr, 363 const char *buf, size_t count) 364 { 365 struct qeth_card *card = dev_get_drvdata(dev); 366 bool state; 367 u32 vnicc; 368 int rc; 369 370 if (kstrtobool(buf, &state)) 371 return -EINVAL; 372 373 vnicc = qeth_l2_vnicc_sysfs_attr_to_char(attr->attr.name); 374 mutex_lock(&card->conf_mutex); 375 rc = qeth_l2_vnicc_set_state(card, vnicc, state); 376 mutex_unlock(&card->conf_mutex); 377 378 return rc ? rc : count; 379 } 380 381 static DEVICE_ATTR(flooding, 0644, qeth_vnicc_char_show, qeth_vnicc_char_store); 382 static DEVICE_ATTR(mcast_flooding, 0644, qeth_vnicc_char_show, 383 qeth_vnicc_char_store); 384 static DEVICE_ATTR(learning, 0644, qeth_vnicc_char_show, qeth_vnicc_char_store); 385 static DEVICE_ATTR(learning_timeout, 0644, qeth_vnicc_timeout_show, 386 qeth_vnicc_timeout_store); 387 static DEVICE_ATTR(takeover_setvmac, 0644, qeth_vnicc_char_show, 388 qeth_vnicc_char_store); 389 static DEVICE_ATTR(takeover_learning, 0644, qeth_vnicc_char_show, 390 qeth_vnicc_char_store); 391 static DEVICE_ATTR(bridge_invisible, 0644, qeth_vnicc_char_show, 392 qeth_vnicc_char_store); 393 static DEVICE_ATTR(rx_bcast, 0644, qeth_vnicc_char_show, qeth_vnicc_char_store); 394 395 static struct attribute *qeth_l2_vnicc_attrs[] = { 396 &dev_attr_flooding.attr, 397 &dev_attr_mcast_flooding.attr, 398 &dev_attr_learning.attr, 399 &dev_attr_learning_timeout.attr, 400 &dev_attr_takeover_setvmac.attr, 401 &dev_attr_takeover_learning.attr, 402 &dev_attr_bridge_invisible.attr, 403 &dev_attr_rx_bcast.attr, 404 NULL, 405 }; 406 407 static struct attribute_group qeth_l2_vnicc_attr_group = { 408 .attrs = qeth_l2_vnicc_attrs, 409 .name = "vnicc", 410 }; 411 412 static const struct attribute_group *qeth_l2_only_attr_groups[] = { 413 &qeth_l2_bridgeport_attr_group, 414 &qeth_l2_vnicc_attr_group, 415 NULL, 416 }; 417 418 int qeth_l2_create_device_attributes(struct device *dev) 419 { 420 return sysfs_create_groups(&dev->kobj, qeth_l2_only_attr_groups); 421 } 422 423 void qeth_l2_remove_device_attributes(struct device *dev) 424 { 425 sysfs_remove_groups(&dev->kobj, qeth_l2_only_attr_groups); 426 } 427 428 const struct attribute_group *qeth_l2_attr_groups[] = { 429 &qeth_device_attr_group, 430 &qeth_device_blkt_group, 431 /* l2 specific, see qeth_l2_only_attr_groups: */ 432 &qeth_l2_bridgeport_attr_group, 433 &qeth_l2_vnicc_attr_group, 434 NULL, 435 }; 436