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