brintos

brintos / linux-shallow public Read only

0
0
Text · 10.0 KiB · 7f592f9 Raw
384 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 *    Copyright IBM Corp. 20134 *    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 12static 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_bridgeport_allowed(card))22		return sysfs_emit(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		else42			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		else56			rc = sysfs_emit(buf, "%s\n", word);57	}58	mutex_unlock(&card->sbp_lock);59 60	return rc;61}62 63static 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_bridgeport_allowed(card))69		return sysfs_emit(buf, "n/a (VNIC characteristics)\n");70 71	return qeth_bridge_port_role_state_show(dev, attr, buf, 0);72}73 74static 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	else88		return -EINVAL;89 90	mutex_lock(&card->conf_mutex);91	mutex_lock(&card->sbp_lock);92 93	if (!qeth_bridgeport_allowed(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	} else103		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 111static DEVICE_ATTR(bridge_role, 0644, qeth_bridge_port_role_show,112		   qeth_bridge_port_role_store);113 114static 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_bridgeport_allowed(card))120		return sysfs_emit(buf, "n/a (VNIC characteristics)\n");121 122	return qeth_bridge_port_role_state_show(dev, attr, buf, 1);123}124 125static DEVICE_ATTR(bridge_state, 0444, qeth_bridge_port_state_show,126		   NULL);127 128static 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_bridgeport_allowed(card))135		return sysfs_emit(buf, "n/a (VNIC characteristics)\n");136 137	enabled = card->options.sbp.hostnotification;138 139	return sysfs_emit(buf, "%d\n", enabled);140}141 142static 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_bridgeport_allowed(card))157		rc = -EBUSY;158	else if (qeth_card_hw_is_reachable(card)) {159		rc = qeth_bridgeport_an_set(card, enable);160		/* sbp_lock ensures ordering vs notifications-stopped events */161		if (!rc)162			card->options.sbp.hostnotification = enable;163	} else164		card->options.sbp.hostnotification = enable;165 166	mutex_unlock(&card->sbp_lock);167	mutex_unlock(&card->conf_mutex);168 169	return rc ? rc : count;170}171 172static DEVICE_ATTR(bridge_hostnotify, 0644,173			qeth_bridgeport_hostnotification_show,174			qeth_bridgeport_hostnotification_store);175 176static ssize_t qeth_bridgeport_reflect_show(struct device *dev,177				struct device_attribute *attr, char *buf)178{179	struct qeth_card *card = dev_get_drvdata(dev);180	char *state;181 182	if (!qeth_bridgeport_allowed(card))183		return sysfs_emit(buf, "n/a (VNIC characteristics)\n");184 185	if (card->options.sbp.reflect_promisc) {186		if (card->options.sbp.reflect_promisc_primary)187			state = "primary";188		else189			state = "secondary";190	} else191		state = "none";192 193	return sysfs_emit(buf, "%s\n", state);194}195 196static ssize_t qeth_bridgeport_reflect_store(struct device *dev,197		struct device_attribute *attr, const char *buf, size_t count)198{199	struct qeth_card *card = dev_get_drvdata(dev);200	int enable, primary;201	int rc = 0;202 203	if (sysfs_streq(buf, "none")) {204		enable = 0;205		primary = 0;206	} else if (sysfs_streq(buf, "primary")) {207		enable = 1;208		primary = 1;209	} else if (sysfs_streq(buf, "secondary")) {210		enable = 1;211		primary = 0;212	} else213		return -EINVAL;214 215	mutex_lock(&card->conf_mutex);216	mutex_lock(&card->sbp_lock);217 218	if (!qeth_bridgeport_allowed(card))219		rc = -EBUSY;220	else if (card->options.sbp.role != QETH_SBP_ROLE_NONE)221		rc = -EPERM;222	else {223		card->options.sbp.reflect_promisc = enable;224		card->options.sbp.reflect_promisc_primary = primary;225		rc = 0;226	}227 228	mutex_unlock(&card->sbp_lock);229	mutex_unlock(&card->conf_mutex);230 231	return rc ? rc : count;232}233 234static DEVICE_ATTR(bridge_reflect_promisc, 0644,235			qeth_bridgeport_reflect_show,236			qeth_bridgeport_reflect_store);237 238static struct attribute *qeth_l2_bridgeport_attrs[] = {239	&dev_attr_bridge_role.attr,240	&dev_attr_bridge_state.attr,241	&dev_attr_bridge_hostnotify.attr,242	&dev_attr_bridge_reflect_promisc.attr,243	NULL,244};245 246static struct attribute_group qeth_l2_bridgeport_attr_group = {247	.attrs = qeth_l2_bridgeport_attrs,248};249 250/* VNIC CHARS support */251 252/* convert sysfs attr name to VNIC characteristic */253static u32 qeth_l2_vnicc_sysfs_attr_to_char(const char *attr_name)254{255	if (sysfs_streq(attr_name, "flooding"))256		return QETH_VNICC_FLOODING;257	else if (sysfs_streq(attr_name, "mcast_flooding"))258		return QETH_VNICC_MCAST_FLOODING;259	else if (sysfs_streq(attr_name, "learning"))260		return QETH_VNICC_LEARNING;261	else if (sysfs_streq(attr_name, "takeover_setvmac"))262		return QETH_VNICC_TAKEOVER_SETVMAC;263	else if (sysfs_streq(attr_name, "takeover_learning"))264		return QETH_VNICC_TAKEOVER_LEARNING;265	else if (sysfs_streq(attr_name, "bridge_invisible"))266		return QETH_VNICC_BRIDGE_INVISIBLE;267	else if (sysfs_streq(attr_name, "rx_bcast"))268		return QETH_VNICC_RX_BCAST;269 270	return 0;271}272 273/* get current timeout setting */274static ssize_t qeth_vnicc_timeout_show(struct device *dev,275				       struct device_attribute *attr, char *buf)276{277	struct qeth_card *card = dev_get_drvdata(dev);278	u32 timeout;279	int rc;280 281	rc = qeth_l2_vnicc_get_timeout(card, &timeout);282	if (rc == -EBUSY)283		return sysfs_emit(buf, "n/a (BridgePort)\n");284	if (rc == -EOPNOTSUPP)285		return sysfs_emit(buf, "n/a\n");286	return rc ? rc : sysfs_emit(buf, "%d\n", timeout);287}288 289/* change timeout setting */290static ssize_t qeth_vnicc_timeout_store(struct device *dev,291					struct device_attribute *attr,292					const char *buf, size_t count)293{294	struct qeth_card *card = dev_get_drvdata(dev);295	u32 timeout;296	int rc;297 298	rc = kstrtou32(buf, 10, &timeout);299	if (rc)300		return rc;301 302	mutex_lock(&card->conf_mutex);303	rc = qeth_l2_vnicc_set_timeout(card, timeout);304	mutex_unlock(&card->conf_mutex);305	return rc ? rc : count;306}307 308/* get current setting of characteristic */309static ssize_t qeth_vnicc_char_show(struct device *dev,310				    struct device_attribute *attr, char *buf)311{312	struct qeth_card *card = dev_get_drvdata(dev);313	bool state;314	u32 vnicc;315	int rc;316 317	vnicc = qeth_l2_vnicc_sysfs_attr_to_char(attr->attr.name);318	rc = qeth_l2_vnicc_get_state(card, vnicc, &state);319 320	if (rc == -EBUSY)321		return sysfs_emit(buf, "n/a (BridgePort)\n");322	if (rc == -EOPNOTSUPP)323		return sysfs_emit(buf, "n/a\n");324	return rc ? rc : sysfs_emit(buf, "%d\n", state);325}326 327/* change setting of characteristic */328static ssize_t qeth_vnicc_char_store(struct device *dev,329				     struct device_attribute *attr,330				     const char *buf, size_t count)331{332	struct qeth_card *card = dev_get_drvdata(dev);333	bool state;334	u32 vnicc;335	int rc;336 337	if (kstrtobool(buf, &state))338		return -EINVAL;339 340	vnicc = qeth_l2_vnicc_sysfs_attr_to_char(attr->attr.name);341	mutex_lock(&card->conf_mutex);342	rc = qeth_l2_vnicc_set_state(card, vnicc, state);343	mutex_unlock(&card->conf_mutex);344 345	return rc ? rc : count;346}347 348static DEVICE_ATTR(flooding, 0644, qeth_vnicc_char_show, qeth_vnicc_char_store);349static DEVICE_ATTR(mcast_flooding, 0644, qeth_vnicc_char_show,350		   qeth_vnicc_char_store);351static DEVICE_ATTR(learning, 0644, qeth_vnicc_char_show, qeth_vnicc_char_store);352static DEVICE_ATTR(learning_timeout, 0644, qeth_vnicc_timeout_show,353		   qeth_vnicc_timeout_store);354static DEVICE_ATTR(takeover_setvmac, 0644, qeth_vnicc_char_show,355		   qeth_vnicc_char_store);356static DEVICE_ATTR(takeover_learning, 0644, qeth_vnicc_char_show,357		   qeth_vnicc_char_store);358static DEVICE_ATTR(bridge_invisible, 0644, qeth_vnicc_char_show,359		   qeth_vnicc_char_store);360static DEVICE_ATTR(rx_bcast, 0644, qeth_vnicc_char_show, qeth_vnicc_char_store);361 362static struct attribute *qeth_l2_vnicc_attrs[] = {363	&dev_attr_flooding.attr,364	&dev_attr_mcast_flooding.attr,365	&dev_attr_learning.attr,366	&dev_attr_learning_timeout.attr,367	&dev_attr_takeover_setvmac.attr,368	&dev_attr_takeover_learning.attr,369	&dev_attr_bridge_invisible.attr,370	&dev_attr_rx_bcast.attr,371	NULL,372};373 374static struct attribute_group qeth_l2_vnicc_attr_group = {375	.attrs = qeth_l2_vnicc_attrs,376	.name = "vnicc",377};378 379const struct attribute_group *qeth_l2_attr_groups[] = {380	&qeth_l2_bridgeport_attr_group,381	&qeth_l2_vnicc_attr_group,382	NULL,383};384