18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright IBM Corp. 2013 48c2ecf20Sopenharmony_ci * Author(s): Eugene Crosser <eugene.crosser@ru.ibm.com> 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include <linux/slab.h> 88c2ecf20Sopenharmony_ci#include <asm/ebcdic.h> 98c2ecf20Sopenharmony_ci#include "qeth_core.h" 108c2ecf20Sopenharmony_ci#include "qeth_l2.h" 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_cistatic ssize_t qeth_bridge_port_role_state_show(struct device *dev, 138c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf, 148c2ecf20Sopenharmony_ci int show_state) 158c2ecf20Sopenharmony_ci{ 168c2ecf20Sopenharmony_ci struct qeth_card *card = dev_get_drvdata(dev); 178c2ecf20Sopenharmony_ci enum qeth_sbp_states state = QETH_SBP_STATE_INACTIVE; 188c2ecf20Sopenharmony_ci int rc = 0; 198c2ecf20Sopenharmony_ci char *word; 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci if (!qeth_bridgeport_allowed(card)) 228c2ecf20Sopenharmony_ci return sprintf(buf, "n/a (VNIC characteristics)\n"); 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci mutex_lock(&card->sbp_lock); 258c2ecf20Sopenharmony_ci if (qeth_card_hw_is_reachable(card) && 268c2ecf20Sopenharmony_ci card->options.sbp.supported_funcs) 278c2ecf20Sopenharmony_ci rc = qeth_bridgeport_query_ports(card, 288c2ecf20Sopenharmony_ci &card->options.sbp.role, &state); 298c2ecf20Sopenharmony_ci if (!rc) { 308c2ecf20Sopenharmony_ci if (show_state) 318c2ecf20Sopenharmony_ci switch (state) { 328c2ecf20Sopenharmony_ci case QETH_SBP_STATE_INACTIVE: 338c2ecf20Sopenharmony_ci word = "inactive"; break; 348c2ecf20Sopenharmony_ci case QETH_SBP_STATE_STANDBY: 358c2ecf20Sopenharmony_ci word = "standby"; break; 368c2ecf20Sopenharmony_ci case QETH_SBP_STATE_ACTIVE: 378c2ecf20Sopenharmony_ci word = "active"; break; 388c2ecf20Sopenharmony_ci default: 398c2ecf20Sopenharmony_ci rc = -EIO; 408c2ecf20Sopenharmony_ci } 418c2ecf20Sopenharmony_ci else 428c2ecf20Sopenharmony_ci switch (card->options.sbp.role) { 438c2ecf20Sopenharmony_ci case QETH_SBP_ROLE_NONE: 448c2ecf20Sopenharmony_ci word = "none"; break; 458c2ecf20Sopenharmony_ci case QETH_SBP_ROLE_PRIMARY: 468c2ecf20Sopenharmony_ci word = "primary"; break; 478c2ecf20Sopenharmony_ci case QETH_SBP_ROLE_SECONDARY: 488c2ecf20Sopenharmony_ci word = "secondary"; break; 498c2ecf20Sopenharmony_ci default: 508c2ecf20Sopenharmony_ci rc = -EIO; 518c2ecf20Sopenharmony_ci } 528c2ecf20Sopenharmony_ci if (rc) 538c2ecf20Sopenharmony_ci QETH_CARD_TEXT_(card, 2, "SBP%02x:%02x", 548c2ecf20Sopenharmony_ci card->options.sbp.role, state); 558c2ecf20Sopenharmony_ci else 568c2ecf20Sopenharmony_ci rc = sprintf(buf, "%s\n", word); 578c2ecf20Sopenharmony_ci } 588c2ecf20Sopenharmony_ci mutex_unlock(&card->sbp_lock); 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci return rc; 618c2ecf20Sopenharmony_ci} 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_cistatic ssize_t qeth_bridge_port_role_show(struct device *dev, 648c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 658c2ecf20Sopenharmony_ci{ 668c2ecf20Sopenharmony_ci struct qeth_card *card = dev_get_drvdata(dev); 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci if (!qeth_bridgeport_allowed(card)) 698c2ecf20Sopenharmony_ci return sprintf(buf, "n/a (VNIC characteristics)\n"); 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci return qeth_bridge_port_role_state_show(dev, attr, buf, 0); 728c2ecf20Sopenharmony_ci} 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_cistatic ssize_t qeth_bridge_port_role_store(struct device *dev, 758c2ecf20Sopenharmony_ci struct device_attribute *attr, const char *buf, size_t count) 768c2ecf20Sopenharmony_ci{ 778c2ecf20Sopenharmony_ci struct qeth_card *card = dev_get_drvdata(dev); 788c2ecf20Sopenharmony_ci int rc = 0; 798c2ecf20Sopenharmony_ci enum qeth_sbp_roles role; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci if (sysfs_streq(buf, "primary")) 828c2ecf20Sopenharmony_ci role = QETH_SBP_ROLE_PRIMARY; 838c2ecf20Sopenharmony_ci else if (sysfs_streq(buf, "secondary")) 848c2ecf20Sopenharmony_ci role = QETH_SBP_ROLE_SECONDARY; 858c2ecf20Sopenharmony_ci else if (sysfs_streq(buf, "none")) 868c2ecf20Sopenharmony_ci role = QETH_SBP_ROLE_NONE; 878c2ecf20Sopenharmony_ci else 888c2ecf20Sopenharmony_ci return -EINVAL; 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci mutex_lock(&card->conf_mutex); 918c2ecf20Sopenharmony_ci mutex_lock(&card->sbp_lock); 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci if (!qeth_bridgeport_allowed(card)) 948c2ecf20Sopenharmony_ci rc = -EBUSY; 958c2ecf20Sopenharmony_ci else if (card->options.sbp.reflect_promisc) 968c2ecf20Sopenharmony_ci /* Forbid direct manipulation */ 978c2ecf20Sopenharmony_ci rc = -EPERM; 988c2ecf20Sopenharmony_ci else if (qeth_card_hw_is_reachable(card)) { 998c2ecf20Sopenharmony_ci rc = qeth_bridgeport_setrole(card, role); 1008c2ecf20Sopenharmony_ci if (!rc) 1018c2ecf20Sopenharmony_ci card->options.sbp.role = role; 1028c2ecf20Sopenharmony_ci } else 1038c2ecf20Sopenharmony_ci card->options.sbp.role = role; 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci mutex_unlock(&card->sbp_lock); 1068c2ecf20Sopenharmony_ci mutex_unlock(&card->conf_mutex); 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci return rc ? rc : count; 1098c2ecf20Sopenharmony_ci} 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_cistatic DEVICE_ATTR(bridge_role, 0644, qeth_bridge_port_role_show, 1128c2ecf20Sopenharmony_ci qeth_bridge_port_role_store); 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_cistatic ssize_t qeth_bridge_port_state_show(struct device *dev, 1158c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 1168c2ecf20Sopenharmony_ci{ 1178c2ecf20Sopenharmony_ci struct qeth_card *card = dev_get_drvdata(dev); 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci if (!qeth_bridgeport_allowed(card)) 1208c2ecf20Sopenharmony_ci return sprintf(buf, "n/a (VNIC characteristics)\n"); 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci return qeth_bridge_port_role_state_show(dev, attr, buf, 1); 1238c2ecf20Sopenharmony_ci} 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_cistatic DEVICE_ATTR(bridge_state, 0444, qeth_bridge_port_state_show, 1268c2ecf20Sopenharmony_ci NULL); 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_cistatic ssize_t qeth_bridgeport_hostnotification_show(struct device *dev, 1298c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 1308c2ecf20Sopenharmony_ci{ 1318c2ecf20Sopenharmony_ci struct qeth_card *card = dev_get_drvdata(dev); 1328c2ecf20Sopenharmony_ci int enabled; 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci if (!qeth_bridgeport_allowed(card)) 1358c2ecf20Sopenharmony_ci return sprintf(buf, "n/a (VNIC characteristics)\n"); 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci enabled = card->options.sbp.hostnotification; 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci return sprintf(buf, "%d\n", enabled); 1408c2ecf20Sopenharmony_ci} 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_cistatic ssize_t qeth_bridgeport_hostnotification_store(struct device *dev, 1438c2ecf20Sopenharmony_ci struct device_attribute *attr, const char *buf, size_t count) 1448c2ecf20Sopenharmony_ci{ 1458c2ecf20Sopenharmony_ci struct qeth_card *card = dev_get_drvdata(dev); 1468c2ecf20Sopenharmony_ci bool enable; 1478c2ecf20Sopenharmony_ci int rc; 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci rc = kstrtobool(buf, &enable); 1508c2ecf20Sopenharmony_ci if (rc) 1518c2ecf20Sopenharmony_ci return rc; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci mutex_lock(&card->conf_mutex); 1548c2ecf20Sopenharmony_ci mutex_lock(&card->sbp_lock); 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci if (!qeth_bridgeport_allowed(card)) 1578c2ecf20Sopenharmony_ci rc = -EBUSY; 1588c2ecf20Sopenharmony_ci else if (qeth_card_hw_is_reachable(card)) { 1598c2ecf20Sopenharmony_ci rc = qeth_bridgeport_an_set(card, enable); 1608c2ecf20Sopenharmony_ci /* sbp_lock ensures ordering vs notifications-stopped events */ 1618c2ecf20Sopenharmony_ci if (!rc) 1628c2ecf20Sopenharmony_ci card->options.sbp.hostnotification = enable; 1638c2ecf20Sopenharmony_ci } else 1648c2ecf20Sopenharmony_ci card->options.sbp.hostnotification = enable; 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci mutex_unlock(&card->sbp_lock); 1678c2ecf20Sopenharmony_ci mutex_unlock(&card->conf_mutex); 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci return rc ? rc : count; 1708c2ecf20Sopenharmony_ci} 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_cistatic DEVICE_ATTR(bridge_hostnotify, 0644, 1738c2ecf20Sopenharmony_ci qeth_bridgeport_hostnotification_show, 1748c2ecf20Sopenharmony_ci qeth_bridgeport_hostnotification_store); 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_cistatic ssize_t qeth_bridgeport_reflect_show(struct device *dev, 1778c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 1788c2ecf20Sopenharmony_ci{ 1798c2ecf20Sopenharmony_ci struct qeth_card *card = dev_get_drvdata(dev); 1808c2ecf20Sopenharmony_ci char *state; 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci if (!qeth_bridgeport_allowed(card)) 1838c2ecf20Sopenharmony_ci return sprintf(buf, "n/a (VNIC characteristics)\n"); 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci if (card->options.sbp.reflect_promisc) { 1868c2ecf20Sopenharmony_ci if (card->options.sbp.reflect_promisc_primary) 1878c2ecf20Sopenharmony_ci state = "primary"; 1888c2ecf20Sopenharmony_ci else 1898c2ecf20Sopenharmony_ci state = "secondary"; 1908c2ecf20Sopenharmony_ci } else 1918c2ecf20Sopenharmony_ci state = "none"; 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci return sprintf(buf, "%s\n", state); 1948c2ecf20Sopenharmony_ci} 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_cistatic ssize_t qeth_bridgeport_reflect_store(struct device *dev, 1978c2ecf20Sopenharmony_ci struct device_attribute *attr, const char *buf, size_t count) 1988c2ecf20Sopenharmony_ci{ 1998c2ecf20Sopenharmony_ci struct qeth_card *card = dev_get_drvdata(dev); 2008c2ecf20Sopenharmony_ci int enable, primary; 2018c2ecf20Sopenharmony_ci int rc = 0; 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci if (sysfs_streq(buf, "none")) { 2048c2ecf20Sopenharmony_ci enable = 0; 2058c2ecf20Sopenharmony_ci primary = 0; 2068c2ecf20Sopenharmony_ci } else if (sysfs_streq(buf, "primary")) { 2078c2ecf20Sopenharmony_ci enable = 1; 2088c2ecf20Sopenharmony_ci primary = 1; 2098c2ecf20Sopenharmony_ci } else if (sysfs_streq(buf, "secondary")) { 2108c2ecf20Sopenharmony_ci enable = 1; 2118c2ecf20Sopenharmony_ci primary = 0; 2128c2ecf20Sopenharmony_ci } else 2138c2ecf20Sopenharmony_ci return -EINVAL; 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci mutex_lock(&card->conf_mutex); 2168c2ecf20Sopenharmony_ci mutex_lock(&card->sbp_lock); 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci if (!qeth_bridgeport_allowed(card)) 2198c2ecf20Sopenharmony_ci rc = -EBUSY; 2208c2ecf20Sopenharmony_ci else if (card->options.sbp.role != QETH_SBP_ROLE_NONE) 2218c2ecf20Sopenharmony_ci rc = -EPERM; 2228c2ecf20Sopenharmony_ci else { 2238c2ecf20Sopenharmony_ci card->options.sbp.reflect_promisc = enable; 2248c2ecf20Sopenharmony_ci card->options.sbp.reflect_promisc_primary = primary; 2258c2ecf20Sopenharmony_ci rc = 0; 2268c2ecf20Sopenharmony_ci } 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci mutex_unlock(&card->sbp_lock); 2298c2ecf20Sopenharmony_ci mutex_unlock(&card->conf_mutex); 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci return rc ? rc : count; 2328c2ecf20Sopenharmony_ci} 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_cistatic DEVICE_ATTR(bridge_reflect_promisc, 0644, 2358c2ecf20Sopenharmony_ci qeth_bridgeport_reflect_show, 2368c2ecf20Sopenharmony_ci qeth_bridgeport_reflect_store); 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_cistatic struct attribute *qeth_l2_bridgeport_attrs[] = { 2398c2ecf20Sopenharmony_ci &dev_attr_bridge_role.attr, 2408c2ecf20Sopenharmony_ci &dev_attr_bridge_state.attr, 2418c2ecf20Sopenharmony_ci &dev_attr_bridge_hostnotify.attr, 2428c2ecf20Sopenharmony_ci &dev_attr_bridge_reflect_promisc.attr, 2438c2ecf20Sopenharmony_ci NULL, 2448c2ecf20Sopenharmony_ci}; 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_cistatic struct attribute_group qeth_l2_bridgeport_attr_group = { 2478c2ecf20Sopenharmony_ci .attrs = qeth_l2_bridgeport_attrs, 2488c2ecf20Sopenharmony_ci}; 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci/* VNIC CHARS support */ 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci/* convert sysfs attr name to VNIC characteristic */ 2538c2ecf20Sopenharmony_cistatic u32 qeth_l2_vnicc_sysfs_attr_to_char(const char *attr_name) 2548c2ecf20Sopenharmony_ci{ 2558c2ecf20Sopenharmony_ci if (sysfs_streq(attr_name, "flooding")) 2568c2ecf20Sopenharmony_ci return QETH_VNICC_FLOODING; 2578c2ecf20Sopenharmony_ci else if (sysfs_streq(attr_name, "mcast_flooding")) 2588c2ecf20Sopenharmony_ci return QETH_VNICC_MCAST_FLOODING; 2598c2ecf20Sopenharmony_ci else if (sysfs_streq(attr_name, "learning")) 2608c2ecf20Sopenharmony_ci return QETH_VNICC_LEARNING; 2618c2ecf20Sopenharmony_ci else if (sysfs_streq(attr_name, "takeover_setvmac")) 2628c2ecf20Sopenharmony_ci return QETH_VNICC_TAKEOVER_SETVMAC; 2638c2ecf20Sopenharmony_ci else if (sysfs_streq(attr_name, "takeover_learning")) 2648c2ecf20Sopenharmony_ci return QETH_VNICC_TAKEOVER_LEARNING; 2658c2ecf20Sopenharmony_ci else if (sysfs_streq(attr_name, "bridge_invisible")) 2668c2ecf20Sopenharmony_ci return QETH_VNICC_BRIDGE_INVISIBLE; 2678c2ecf20Sopenharmony_ci else if (sysfs_streq(attr_name, "rx_bcast")) 2688c2ecf20Sopenharmony_ci return QETH_VNICC_RX_BCAST; 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci return 0; 2718c2ecf20Sopenharmony_ci} 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci/* get current timeout setting */ 2748c2ecf20Sopenharmony_cistatic ssize_t qeth_vnicc_timeout_show(struct device *dev, 2758c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 2768c2ecf20Sopenharmony_ci{ 2778c2ecf20Sopenharmony_ci struct qeth_card *card = dev_get_drvdata(dev); 2788c2ecf20Sopenharmony_ci u32 timeout; 2798c2ecf20Sopenharmony_ci int rc; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci rc = qeth_l2_vnicc_get_timeout(card, &timeout); 2828c2ecf20Sopenharmony_ci if (rc == -EBUSY) 2838c2ecf20Sopenharmony_ci return sprintf(buf, "n/a (BridgePort)\n"); 2848c2ecf20Sopenharmony_ci if (rc == -EOPNOTSUPP) 2858c2ecf20Sopenharmony_ci return sprintf(buf, "n/a\n"); 2868c2ecf20Sopenharmony_ci return rc ? rc : sprintf(buf, "%d\n", timeout); 2878c2ecf20Sopenharmony_ci} 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci/* change timeout setting */ 2908c2ecf20Sopenharmony_cistatic ssize_t qeth_vnicc_timeout_store(struct device *dev, 2918c2ecf20Sopenharmony_ci struct device_attribute *attr, 2928c2ecf20Sopenharmony_ci const char *buf, size_t count) 2938c2ecf20Sopenharmony_ci{ 2948c2ecf20Sopenharmony_ci struct qeth_card *card = dev_get_drvdata(dev); 2958c2ecf20Sopenharmony_ci u32 timeout; 2968c2ecf20Sopenharmony_ci int rc; 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci rc = kstrtou32(buf, 10, &timeout); 2998c2ecf20Sopenharmony_ci if (rc) 3008c2ecf20Sopenharmony_ci return rc; 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci mutex_lock(&card->conf_mutex); 3038c2ecf20Sopenharmony_ci rc = qeth_l2_vnicc_set_timeout(card, timeout); 3048c2ecf20Sopenharmony_ci mutex_unlock(&card->conf_mutex); 3058c2ecf20Sopenharmony_ci return rc ? rc : count; 3068c2ecf20Sopenharmony_ci} 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci/* get current setting of characteristic */ 3098c2ecf20Sopenharmony_cistatic ssize_t qeth_vnicc_char_show(struct device *dev, 3108c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 3118c2ecf20Sopenharmony_ci{ 3128c2ecf20Sopenharmony_ci struct qeth_card *card = dev_get_drvdata(dev); 3138c2ecf20Sopenharmony_ci bool state; 3148c2ecf20Sopenharmony_ci u32 vnicc; 3158c2ecf20Sopenharmony_ci int rc; 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci vnicc = qeth_l2_vnicc_sysfs_attr_to_char(attr->attr.name); 3188c2ecf20Sopenharmony_ci rc = qeth_l2_vnicc_get_state(card, vnicc, &state); 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_ci if (rc == -EBUSY) 3218c2ecf20Sopenharmony_ci return sprintf(buf, "n/a (BridgePort)\n"); 3228c2ecf20Sopenharmony_ci if (rc == -EOPNOTSUPP) 3238c2ecf20Sopenharmony_ci return sprintf(buf, "n/a\n"); 3248c2ecf20Sopenharmony_ci return rc ? rc : sprintf(buf, "%d\n", state); 3258c2ecf20Sopenharmony_ci} 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci/* change setting of characteristic */ 3288c2ecf20Sopenharmony_cistatic ssize_t qeth_vnicc_char_store(struct device *dev, 3298c2ecf20Sopenharmony_ci struct device_attribute *attr, 3308c2ecf20Sopenharmony_ci const char *buf, size_t count) 3318c2ecf20Sopenharmony_ci{ 3328c2ecf20Sopenharmony_ci struct qeth_card *card = dev_get_drvdata(dev); 3338c2ecf20Sopenharmony_ci bool state; 3348c2ecf20Sopenharmony_ci u32 vnicc; 3358c2ecf20Sopenharmony_ci int rc; 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci if (kstrtobool(buf, &state)) 3388c2ecf20Sopenharmony_ci return -EINVAL; 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci vnicc = qeth_l2_vnicc_sysfs_attr_to_char(attr->attr.name); 3418c2ecf20Sopenharmony_ci mutex_lock(&card->conf_mutex); 3428c2ecf20Sopenharmony_ci rc = qeth_l2_vnicc_set_state(card, vnicc, state); 3438c2ecf20Sopenharmony_ci mutex_unlock(&card->conf_mutex); 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci return rc ? rc : count; 3468c2ecf20Sopenharmony_ci} 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_cistatic DEVICE_ATTR(flooding, 0644, qeth_vnicc_char_show, qeth_vnicc_char_store); 3498c2ecf20Sopenharmony_cistatic DEVICE_ATTR(mcast_flooding, 0644, qeth_vnicc_char_show, 3508c2ecf20Sopenharmony_ci qeth_vnicc_char_store); 3518c2ecf20Sopenharmony_cistatic DEVICE_ATTR(learning, 0644, qeth_vnicc_char_show, qeth_vnicc_char_store); 3528c2ecf20Sopenharmony_cistatic DEVICE_ATTR(learning_timeout, 0644, qeth_vnicc_timeout_show, 3538c2ecf20Sopenharmony_ci qeth_vnicc_timeout_store); 3548c2ecf20Sopenharmony_cistatic DEVICE_ATTR(takeover_setvmac, 0644, qeth_vnicc_char_show, 3558c2ecf20Sopenharmony_ci qeth_vnicc_char_store); 3568c2ecf20Sopenharmony_cistatic DEVICE_ATTR(takeover_learning, 0644, qeth_vnicc_char_show, 3578c2ecf20Sopenharmony_ci qeth_vnicc_char_store); 3588c2ecf20Sopenharmony_cistatic DEVICE_ATTR(bridge_invisible, 0644, qeth_vnicc_char_show, 3598c2ecf20Sopenharmony_ci qeth_vnicc_char_store); 3608c2ecf20Sopenharmony_cistatic DEVICE_ATTR(rx_bcast, 0644, qeth_vnicc_char_show, qeth_vnicc_char_store); 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_cistatic struct attribute *qeth_l2_vnicc_attrs[] = { 3638c2ecf20Sopenharmony_ci &dev_attr_flooding.attr, 3648c2ecf20Sopenharmony_ci &dev_attr_mcast_flooding.attr, 3658c2ecf20Sopenharmony_ci &dev_attr_learning.attr, 3668c2ecf20Sopenharmony_ci &dev_attr_learning_timeout.attr, 3678c2ecf20Sopenharmony_ci &dev_attr_takeover_setvmac.attr, 3688c2ecf20Sopenharmony_ci &dev_attr_takeover_learning.attr, 3698c2ecf20Sopenharmony_ci &dev_attr_bridge_invisible.attr, 3708c2ecf20Sopenharmony_ci &dev_attr_rx_bcast.attr, 3718c2ecf20Sopenharmony_ci NULL, 3728c2ecf20Sopenharmony_ci}; 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_cistatic struct attribute_group qeth_l2_vnicc_attr_group = { 3758c2ecf20Sopenharmony_ci .attrs = qeth_l2_vnicc_attrs, 3768c2ecf20Sopenharmony_ci .name = "vnicc", 3778c2ecf20Sopenharmony_ci}; 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_cistatic const struct attribute_group *qeth_l2_only_attr_groups[] = { 3808c2ecf20Sopenharmony_ci &qeth_l2_bridgeport_attr_group, 3818c2ecf20Sopenharmony_ci &qeth_l2_vnicc_attr_group, 3828c2ecf20Sopenharmony_ci NULL, 3838c2ecf20Sopenharmony_ci}; 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ciint qeth_l2_create_device_attributes(struct device *dev) 3868c2ecf20Sopenharmony_ci{ 3878c2ecf20Sopenharmony_ci return sysfs_create_groups(&dev->kobj, qeth_l2_only_attr_groups); 3888c2ecf20Sopenharmony_ci} 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_civoid qeth_l2_remove_device_attributes(struct device *dev) 3918c2ecf20Sopenharmony_ci{ 3928c2ecf20Sopenharmony_ci sysfs_remove_groups(&dev->kobj, qeth_l2_only_attr_groups); 3938c2ecf20Sopenharmony_ci} 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ciconst struct attribute_group *qeth_l2_attr_groups[] = { 3968c2ecf20Sopenharmony_ci &qeth_device_attr_group, 3978c2ecf20Sopenharmony_ci &qeth_device_blkt_group, 3988c2ecf20Sopenharmony_ci /* l2 specific, see qeth_l2_only_attr_groups: */ 3998c2ecf20Sopenharmony_ci &qeth_l2_bridgeport_attr_group, 4008c2ecf20Sopenharmony_ci &qeth_l2_vnicc_attr_group, 4018c2ecf20Sopenharmony_ci NULL, 4028c2ecf20Sopenharmony_ci}; 403