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 (!card) 22 return -EINVAL; 23 24 if (qeth_card_hw_is_reachable(card) && 25 card->options.sbp.supported_funcs) 26 rc = qeth_bridgeport_query_ports(card, 27 &card->options.sbp.role, &state); 28 if (!rc) { 29 if (show_state) 30 switch (state) { 31 case QETH_SBP_STATE_INACTIVE: 32 word = "inactive"; break; 33 case QETH_SBP_STATE_STANDBY: 34 word = "standby"; break; 35 case QETH_SBP_STATE_ACTIVE: 36 word = "active"; break; 37 default: 38 rc = -EIO; 39 } 40 else 41 switch (card->options.sbp.role) { 42 case QETH_SBP_ROLE_NONE: 43 word = "none"; break; 44 case QETH_SBP_ROLE_PRIMARY: 45 word = "primary"; break; 46 case QETH_SBP_ROLE_SECONDARY: 47 word = "secondary"; break; 48 default: 49 rc = -EIO; 50 } 51 if (rc) 52 QETH_CARD_TEXT_(card, 2, "SBP%02x:%02x", 53 card->options.sbp.role, state); 54 else 55 rc = sprintf(buf, "%s\n", word); 56 } 57 58 return rc; 59 } 60 61 static ssize_t qeth_bridge_port_role_show(struct device *dev, 62 struct device_attribute *attr, char *buf) 63 { 64 return qeth_bridge_port_role_state_show(dev, attr, buf, 0); 65 } 66 67 static ssize_t qeth_bridge_port_role_store(struct device *dev, 68 struct device_attribute *attr, const char *buf, size_t count) 69 { 70 struct qeth_card *card = dev_get_drvdata(dev); 71 int rc = 0; 72 enum qeth_sbp_roles role; 73 74 if (!card) 75 return -EINVAL; 76 if (sysfs_streq(buf, "primary")) 77 role = QETH_SBP_ROLE_PRIMARY; 78 else if (sysfs_streq(buf, "secondary")) 79 role = QETH_SBP_ROLE_SECONDARY; 80 else if (sysfs_streq(buf, "none")) 81 role = QETH_SBP_ROLE_NONE; 82 else 83 return -EINVAL; 84 85 mutex_lock(&card->conf_mutex); 86 87 if (card->options.sbp.reflect_promisc) /* Forbid direct manipulation */ 88 rc = -EPERM; 89 else if (qeth_card_hw_is_reachable(card)) { 90 rc = qeth_bridgeport_setrole(card, role); 91 if (!rc) 92 card->options.sbp.role = role; 93 } else 94 card->options.sbp.role = role; 95 96 mutex_unlock(&card->conf_mutex); 97 98 return rc ? rc : count; 99 } 100 101 static DEVICE_ATTR(bridge_role, 0644, qeth_bridge_port_role_show, 102 qeth_bridge_port_role_store); 103 104 static ssize_t qeth_bridge_port_state_show(struct device *dev, 105 struct device_attribute *attr, char *buf) 106 { 107 return qeth_bridge_port_role_state_show(dev, attr, buf, 1); 108 } 109 110 static DEVICE_ATTR(bridge_state, 0444, qeth_bridge_port_state_show, 111 NULL); 112 113 static ssize_t qeth_bridgeport_hostnotification_show(struct device *dev, 114 struct device_attribute *attr, char *buf) 115 { 116 struct qeth_card *card = dev_get_drvdata(dev); 117 int enabled; 118 119 if (!card) 120 return -EINVAL; 121 122 enabled = card->options.sbp.hostnotification; 123 124 return sprintf(buf, "%d\n", enabled); 125 } 126 127 static ssize_t qeth_bridgeport_hostnotification_store(struct device *dev, 128 struct device_attribute *attr, const char *buf, size_t count) 129 { 130 struct qeth_card *card = dev_get_drvdata(dev); 131 int rc = 0; 132 int enable; 133 134 if (!card) 135 return -EINVAL; 136 137 if (sysfs_streq(buf, "0")) 138 enable = 0; 139 else if (sysfs_streq(buf, "1")) 140 enable = 1; 141 else 142 return -EINVAL; 143 144 mutex_lock(&card->conf_mutex); 145 146 if (qeth_card_hw_is_reachable(card)) { 147 rc = qeth_bridgeport_an_set(card, enable); 148 if (!rc) 149 card->options.sbp.hostnotification = enable; 150 } else 151 card->options.sbp.hostnotification = enable; 152 153 mutex_unlock(&card->conf_mutex); 154 155 return rc ? rc : count; 156 } 157 158 static DEVICE_ATTR(bridge_hostnotify, 0644, 159 qeth_bridgeport_hostnotification_show, 160 qeth_bridgeport_hostnotification_store); 161 162 static ssize_t qeth_bridgeport_reflect_show(struct device *dev, 163 struct device_attribute *attr, char *buf) 164 { 165 struct qeth_card *card = dev_get_drvdata(dev); 166 char *state; 167 168 if (!card) 169 return -EINVAL; 170 171 if (card->options.sbp.reflect_promisc) { 172 if (card->options.sbp.reflect_promisc_primary) 173 state = "primary"; 174 else 175 state = "secondary"; 176 } else 177 state = "none"; 178 179 return sprintf(buf, "%s\n", state); 180 } 181 182 static ssize_t qeth_bridgeport_reflect_store(struct device *dev, 183 struct device_attribute *attr, const char *buf, size_t count) 184 { 185 struct qeth_card *card = dev_get_drvdata(dev); 186 int enable, primary; 187 int rc = 0; 188 189 if (!card) 190 return -EINVAL; 191 192 if (sysfs_streq(buf, "none")) { 193 enable = 0; 194 primary = 0; 195 } else if (sysfs_streq(buf, "primary")) { 196 enable = 1; 197 primary = 1; 198 } else if (sysfs_streq(buf, "secondary")) { 199 enable = 1; 200 primary = 0; 201 } else 202 return -EINVAL; 203 204 mutex_lock(&card->conf_mutex); 205 206 if (card->options.sbp.role != QETH_SBP_ROLE_NONE) 207 rc = -EPERM; 208 else { 209 card->options.sbp.reflect_promisc = enable; 210 card->options.sbp.reflect_promisc_primary = primary; 211 rc = 0; 212 } 213 214 mutex_unlock(&card->conf_mutex); 215 216 return rc ? rc : count; 217 } 218 219 static DEVICE_ATTR(bridge_reflect_promisc, 0644, 220 qeth_bridgeport_reflect_show, 221 qeth_bridgeport_reflect_store); 222 223 static struct attribute *qeth_l2_bridgeport_attrs[] = { 224 &dev_attr_bridge_role.attr, 225 &dev_attr_bridge_state.attr, 226 &dev_attr_bridge_hostnotify.attr, 227 &dev_attr_bridge_reflect_promisc.attr, 228 NULL, 229 }; 230 231 static struct attribute_group qeth_l2_bridgeport_attr_group = { 232 .attrs = qeth_l2_bridgeport_attrs, 233 }; 234 235 int qeth_l2_create_device_attributes(struct device *dev) 236 { 237 return sysfs_create_group(&dev->kobj, &qeth_l2_bridgeport_attr_group); 238 } 239 240 void qeth_l2_remove_device_attributes(struct device *dev) 241 { 242 sysfs_remove_group(&dev->kobj, &qeth_l2_bridgeport_attr_group); 243 } 244 245 /** 246 * qeth_l2_setup_bridgeport_attrs() - set/restore attrs when turning online. 247 * @card: qeth_card structure pointer 248 * 249 * Note: this function is called with conf_mutex held by the caller 250 */ 251 void qeth_l2_setup_bridgeport_attrs(struct qeth_card *card) 252 { 253 int rc; 254 255 if (!card) 256 return; 257 if (!card->options.sbp.supported_funcs) 258 return; 259 if (card->options.sbp.role != QETH_SBP_ROLE_NONE) { 260 /* Conditional to avoid spurious error messages */ 261 qeth_bridgeport_setrole(card, card->options.sbp.role); 262 /* Let the callback function refresh the stored role value. */ 263 qeth_bridgeport_query_ports(card, 264 &card->options.sbp.role, NULL); 265 } 266 if (card->options.sbp.hostnotification) { 267 rc = qeth_bridgeport_an_set(card, 1); 268 if (rc) 269 card->options.sbp.hostnotification = 0; 270 } else 271 qeth_bridgeport_an_set(card, 0); 272 } 273 274 const struct attribute_group *qeth_l2_attr_groups[] = { 275 &qeth_device_attr_group, 276 &qeth_device_blkt_group, 277 /* l2 specific, see l2_{create,remove}_device_attributes(): */ 278 &qeth_l2_bridgeport_attr_group, 279 NULL, 280 }; 281