blob: a6b64228ead25367197daf39b289afb11e796182 [file] [log] [blame]
Greg Kroah-Hartmanb2441312017-11-01 15:07:57 +01001// SPDX-License-Identifier: GPL-2.0
Frank Blaschka4a71df52008-02-15 09:19:42 +01002/*
Frank Blaschka4a71df52008-02-15 09:19:42 +01003 * Copyright IBM Corp. 2007
4 * Author(s): Utz Bacher <utz.bacher@de.ibm.com>,
5 * Frank Pavlic <fpavlic@de.ibm.com>,
6 * Thomas Spatzier <tspat@de.ibm.com>,
7 * Frank Blaschka <frank.blaschka@de.ibm.com>
8 */
9
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090010#include <linux/slab.h>
Frank Blaschkab3332932011-08-08 01:33:59 +000011#include <asm/ebcdic.h>
Lakhvich Dmitriy5f78e292016-06-16 16:18:58 +020012#include <linux/hashtable.h>
Julian Wiedmann556fd272017-12-20 20:11:09 +010013#include <linux/inet.h>
Frank Blaschka4a71df52008-02-15 09:19:42 +010014#include "qeth_l3.h"
15
16#define QETH_DEVICE_ATTR(_id, _name, _mode, _show, _store) \
17struct device_attribute dev_attr_##_id = __ATTR(_name, _mode, _show, _store)
18
Julian Wiedmann556fd272017-12-20 20:11:09 +010019static int qeth_l3_string_to_ipaddr(const char *buf,
20 enum qeth_prot_versions proto, u8 *addr)
21{
22 const char *end;
23
24 if ((proto == QETH_PROT_IPV4 && !in4_pton(buf, -1, addr, -1, &end)) ||
25 (proto == QETH_PROT_IPV6 && !in6_pton(buf, -1, addr, -1, &end)))
26 return -EINVAL;
27 return 0;
28}
29
Frank Blaschka4a71df52008-02-15 09:19:42 +010030static ssize_t qeth_l3_dev_route_show(struct qeth_card *card,
31 struct qeth_routing_info *route, char *buf)
32{
33 switch (route->type) {
34 case PRIMARY_ROUTER:
Thorsten Winklerdde87692023-02-09 12:04:23 +010035 return sysfs_emit(buf, "%s\n", "primary router");
Frank Blaschka4a71df52008-02-15 09:19:42 +010036 case SECONDARY_ROUTER:
Thorsten Winklerdde87692023-02-09 12:04:23 +010037 return sysfs_emit(buf, "%s\n", "secondary router");
Frank Blaschka4a71df52008-02-15 09:19:42 +010038 case MULTICAST_ROUTER:
39 if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
Thorsten Winklerdde87692023-02-09 12:04:23 +010040 return sysfs_emit(buf, "%s\n", "multicast router+");
Frank Blaschka4a71df52008-02-15 09:19:42 +010041 else
Thorsten Winklerdde87692023-02-09 12:04:23 +010042 return sysfs_emit(buf, "%s\n", "multicast router");
Frank Blaschka4a71df52008-02-15 09:19:42 +010043 case PRIMARY_CONNECTOR:
44 if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
Thorsten Winklerdde87692023-02-09 12:04:23 +010045 return sysfs_emit(buf, "%s\n", "primary connector+");
Frank Blaschka4a71df52008-02-15 09:19:42 +010046 else
Thorsten Winklerdde87692023-02-09 12:04:23 +010047 return sysfs_emit(buf, "%s\n", "primary connector");
Frank Blaschka4a71df52008-02-15 09:19:42 +010048 case SECONDARY_CONNECTOR:
49 if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
Thorsten Winklerdde87692023-02-09 12:04:23 +010050 return sysfs_emit(buf, "%s\n", "secondary connector+");
Frank Blaschka4a71df52008-02-15 09:19:42 +010051 else
Thorsten Winklerdde87692023-02-09 12:04:23 +010052 return sysfs_emit(buf, "%s\n", "secondary connector");
Frank Blaschka4a71df52008-02-15 09:19:42 +010053 default:
Thorsten Winklerdde87692023-02-09 12:04:23 +010054 return sysfs_emit(buf, "%s\n", "no");
Frank Blaschka4a71df52008-02-15 09:19:42 +010055 }
56}
57
58static ssize_t qeth_l3_dev_route4_show(struct device *dev,
59 struct device_attribute *attr, char *buf)
60{
61 struct qeth_card *card = dev_get_drvdata(dev);
62
Frank Blaschka4a71df52008-02-15 09:19:42 +010063 return qeth_l3_dev_route_show(card, &card->options.route4, buf);
64}
65
66static ssize_t qeth_l3_dev_route_store(struct qeth_card *card,
67 struct qeth_routing_info *route, enum qeth_prot_versions prot,
68 const char *buf, size_t count)
69{
70 enum qeth_routing_types old_route_type = route->type;
Frank Blaschkac4949f02010-05-11 19:34:47 +000071 int rc = 0;
Frank Blaschka4a71df52008-02-15 09:19:42 +010072
Frank Blaschkac4949f02010-05-11 19:34:47 +000073 mutex_lock(&card->conf_mutex);
Eugene Crosser7e846d6b2015-01-16 14:05:48 +010074 if (sysfs_streq(buf, "no_router")) {
Frank Blaschka4a71df52008-02-15 09:19:42 +010075 route->type = NO_ROUTER;
Eugene Crosser7e846d6b2015-01-16 14:05:48 +010076 } else if (sysfs_streq(buf, "primary_connector")) {
Frank Blaschka4a71df52008-02-15 09:19:42 +010077 route->type = PRIMARY_CONNECTOR;
Eugene Crosser7e846d6b2015-01-16 14:05:48 +010078 } else if (sysfs_streq(buf, "secondary_connector")) {
Frank Blaschka4a71df52008-02-15 09:19:42 +010079 route->type = SECONDARY_CONNECTOR;
Eugene Crosser7e846d6b2015-01-16 14:05:48 +010080 } else if (sysfs_streq(buf, "primary_router")) {
Frank Blaschka4a71df52008-02-15 09:19:42 +010081 route->type = PRIMARY_ROUTER;
Eugene Crosser7e846d6b2015-01-16 14:05:48 +010082 } else if (sysfs_streq(buf, "secondary_router")) {
Frank Blaschka4a71df52008-02-15 09:19:42 +010083 route->type = SECONDARY_ROUTER;
Eugene Crosser7e846d6b2015-01-16 14:05:48 +010084 } else if (sysfs_streq(buf, "multicast_router")) {
Frank Blaschka4a71df52008-02-15 09:19:42 +010085 route->type = MULTICAST_ROUTER;
86 } else {
Frank Blaschkac4949f02010-05-11 19:34:47 +000087 rc = -EINVAL;
88 goto out;
Frank Blaschka4a71df52008-02-15 09:19:42 +010089 }
Eugene Crosserc3521252015-01-16 14:05:47 +010090 if (qeth_card_hw_is_reachable(card) &&
Frank Blaschka4a71df52008-02-15 09:19:42 +010091 (old_route_type != route->type)) {
92 if (prot == QETH_PROT_IPV4)
93 rc = qeth_l3_setrouting_v4(card);
94 else if (prot == QETH_PROT_IPV6)
95 rc = qeth_l3_setrouting_v6(card);
96 }
Frank Blaschkac4949f02010-05-11 19:34:47 +000097out:
Stefan Raspl82e2e782013-03-18 20:04:43 +000098 if (rc)
99 route->type = old_route_type;
Frank Blaschkac4949f02010-05-11 19:34:47 +0000100 mutex_unlock(&card->conf_mutex);
101 return rc ? rc : count;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100102}
103
104static ssize_t qeth_l3_dev_route4_store(struct device *dev,
105 struct device_attribute *attr, const char *buf, size_t count)
106{
107 struct qeth_card *card = dev_get_drvdata(dev);
108
Frank Blaschka4a71df52008-02-15 09:19:42 +0100109 return qeth_l3_dev_route_store(card, &card->options.route4,
110 QETH_PROT_IPV4, buf, count);
111}
112
113static DEVICE_ATTR(route4, 0644, qeth_l3_dev_route4_show,
114 qeth_l3_dev_route4_store);
115
116static ssize_t qeth_l3_dev_route6_show(struct device *dev,
117 struct device_attribute *attr, char *buf)
118{
119 struct qeth_card *card = dev_get_drvdata(dev);
120
Frank Blaschka4a71df52008-02-15 09:19:42 +0100121 return qeth_l3_dev_route_show(card, &card->options.route6, buf);
122}
123
124static ssize_t qeth_l3_dev_route6_store(struct device *dev,
125 struct device_attribute *attr, const char *buf, size_t count)
126{
127 struct qeth_card *card = dev_get_drvdata(dev);
128
Frank Blaschka4a71df52008-02-15 09:19:42 +0100129 return qeth_l3_dev_route_store(card, &card->options.route6,
130 QETH_PROT_IPV6, buf, count);
131}
132
133static DEVICE_ATTR(route6, 0644, qeth_l3_dev_route6_show,
134 qeth_l3_dev_route6_store);
135
Ursula Braun76b11f82010-01-11 02:50:50 +0000136static ssize_t qeth_l3_dev_sniffer_show(struct device *dev,
137 struct device_attribute *attr, char *buf)
138{
139 struct qeth_card *card = dev_get_drvdata(dev);
140
Thorsten Winklerdde87692023-02-09 12:04:23 +0100141 return sysfs_emit(buf, "%i\n", card->options.sniffer ? 1 : 0);
Ursula Braun76b11f82010-01-11 02:50:50 +0000142}
143
144static ssize_t qeth_l3_dev_sniffer_store(struct device *dev,
145 struct device_attribute *attr, const char *buf, size_t count)
146{
147 struct qeth_card *card = dev_get_drvdata(dev);
Frank Blaschkac4949f02010-05-11 19:34:47 +0000148 int rc = 0;
Ursula Braun76b11f82010-01-11 02:50:50 +0000149 unsigned long i;
150
Julian Wiedmann379ac992019-04-25 18:25:57 +0200151 if (!IS_IQD(card))
Ursula Braun76b11f82010-01-11 02:50:50 +0000152 return -EPERM;
Frank Blaschkab3332932011-08-08 01:33:59 +0000153 if (card->options.cq == QETH_CQ_ENABLED)
154 return -EPERM;
Ursula Braun76b11f82010-01-11 02:50:50 +0000155
Frank Blaschkac4949f02010-05-11 19:34:47 +0000156 mutex_lock(&card->conf_mutex);
Julian Wiedmannd7d543f2019-02-28 18:59:36 +0100157 if (card->state != CARD_STATE_DOWN) {
Frank Blaschkac4949f02010-05-11 19:34:47 +0000158 rc = -EPERM;
159 goto out;
160 }
Ursula Braun76b11f82010-01-11 02:50:50 +0000161
Jingoo Han01787222013-07-22 10:18:15 +0900162 rc = kstrtoul(buf, 16, &i);
Frank Blaschkac4949f02010-05-11 19:34:47 +0000163 if (rc) {
164 rc = -EINVAL;
165 goto out;
166 }
Ursula Braun76b11f82010-01-11 02:50:50 +0000167 switch (i) {
168 case 0:
169 card->options.sniffer = i;
170 break;
171 case 1:
Frank Blaschkac4949f02010-05-11 19:34:47 +0000172 qdio_get_ssqd_desc(CARD_DDEV(card), &card->ssqd);
Julian Wiedmann1917b472019-10-23 10:03:23 +0200173 if (card->ssqd.qdioac2 & CHSC_AC2_SNIFFER_AVAILABLE) {
Ursula Braun76b11f82010-01-11 02:50:50 +0000174 card->options.sniffer = i;
Julian Wiedmann5d4f7852020-03-11 18:07:11 +0100175 qeth_resize_buffer_pool(card, QETH_IN_BUF_COUNT_MAX);
176 } else {
Frank Blaschkac4949f02010-05-11 19:34:47 +0000177 rc = -EPERM;
Julian Wiedmann5d4f7852020-03-11 18:07:11 +0100178 }
179
Ursula Braun6cc31d02011-11-15 02:31:12 +0000180 break;
181 default:
Frank Blaschkac4949f02010-05-11 19:34:47 +0000182 rc = -EINVAL;
Ursula Braun76b11f82010-01-11 02:50:50 +0000183 }
Frank Blaschkac4949f02010-05-11 19:34:47 +0000184out:
185 mutex_unlock(&card->conf_mutex);
186 return rc ? rc : count;
Ursula Braun76b11f82010-01-11 02:50:50 +0000187}
188
189static DEVICE_ATTR(sniffer, 0644, qeth_l3_dev_sniffer_show,
190 qeth_l3_dev_sniffer_store);
191
Frank Blaschkab3332932011-08-08 01:33:59 +0000192static ssize_t qeth_l3_dev_hsuid_show(struct device *dev,
193 struct device_attribute *attr, char *buf)
194{
195 struct qeth_card *card = dev_get_drvdata(dev);
196 char tmp_hsuid[9];
197
Julian Wiedmann379ac992019-04-25 18:25:57 +0200198 if (!IS_IQD(card))
Frank Blaschkab3332932011-08-08 01:33:59 +0000199 return -EPERM;
200
Frank Blaschkab3332932011-08-08 01:33:59 +0000201 memcpy(tmp_hsuid, card->options.hsuid, sizeof(tmp_hsuid));
202 EBCASC(tmp_hsuid, 8);
Thorsten Winklerdde87692023-02-09 12:04:23 +0100203 return sysfs_emit(buf, "%s\n", tmp_hsuid);
Frank Blaschkab3332932011-08-08 01:33:59 +0000204}
205
206static ssize_t qeth_l3_dev_hsuid_store(struct device *dev,
207 struct device_attribute *attr, const char *buf, size_t count)
208{
209 struct qeth_card *card = dev_get_drvdata(dev);
Julian Wiedmann5b6c7b52019-12-23 15:03:22 +0100210 int rc = 0;
Frank Blaschkab3332932011-08-08 01:33:59 +0000211 char *tmp;
Frank Blaschkab3332932011-08-08 01:33:59 +0000212
Julian Wiedmann379ac992019-04-25 18:25:57 +0200213 if (!IS_IQD(card))
Frank Blaschkab3332932011-08-08 01:33:59 +0000214 return -EPERM;
Julian Wiedmann5b6c7b52019-12-23 15:03:22 +0100215
216 mutex_lock(&card->conf_mutex);
217 if (card->state != CARD_STATE_DOWN) {
218 rc = -EPERM;
219 goto out;
220 }
221
222 if (card->options.sniffer) {
223 rc = -EPERM;
224 goto out;
225 }
226
227 if (card->options.cq == QETH_CQ_NOTAVAILABLE) {
228 rc = -EPERM;
229 goto out;
230 }
Frank Blaschkab3332932011-08-08 01:33:59 +0000231
232 tmp = strsep((char **)&buf, "\n");
Julian Wiedmann5b6c7b52019-12-23 15:03:22 +0100233 if (strlen(tmp) > 8) {
234 rc = -EINVAL;
235 goto out;
236 }
Frank Blaschkab3332932011-08-08 01:33:59 +0000237
Julian Wiedmann1617dae2018-03-09 18:13:02 +0100238 if (card->options.hsuid[0])
Frank Blaschkab3332932011-08-08 01:33:59 +0000239 /* delete old ip address */
Julian Wiedmann1617dae2018-03-09 18:13:02 +0100240 qeth_l3_modify_hsuid(card, false);
Frank Blaschkab3332932011-08-08 01:33:59 +0000241
242 if (strlen(tmp) == 0) {
243 /* delete ip address only */
244 card->options.hsuid[0] = '\0';
Julian Wiedmannd3d1b202018-07-19 12:43:51 +0200245 memcpy(card->dev->perm_addr, card->options.hsuid, 9);
Frank Blaschkab3332932011-08-08 01:33:59 +0000246 qeth_configure_cq(card, QETH_CQ_DISABLED);
Julian Wiedmann5b6c7b52019-12-23 15:03:22 +0100247 goto out;
Frank Blaschkab3332932011-08-08 01:33:59 +0000248 }
249
Julian Wiedmann5b6c7b52019-12-23 15:03:22 +0100250 if (qeth_configure_cq(card, QETH_CQ_ENABLED)) {
251 rc = -EPERM;
252 goto out;
253 }
Frank Blaschkab3332932011-08-08 01:33:59 +0000254
Thorsten Winkler74c05a382023-02-09 12:04:24 +0100255 scnprintf(card->options.hsuid, sizeof(card->options.hsuid),
256 "%-8s", tmp);
Frank Blaschkab3332932011-08-08 01:33:59 +0000257 ASCEBC(card->options.hsuid, 8);
Julian Wiedmannd3d1b202018-07-19 12:43:51 +0200258 memcpy(card->dev->perm_addr, card->options.hsuid, 9);
Frank Blaschkab3332932011-08-08 01:33:59 +0000259
Julian Wiedmann1617dae2018-03-09 18:13:02 +0100260 rc = qeth_l3_modify_hsuid(card, true);
Frank Blaschkab3332932011-08-08 01:33:59 +0000261
Julian Wiedmann5b6c7b52019-12-23 15:03:22 +0100262out:
263 mutex_unlock(&card->conf_mutex);
Julian Wiedmannb9ea5252017-12-27 17:44:28 +0100264 return rc ? rc : count;
Frank Blaschkab3332932011-08-08 01:33:59 +0000265}
266
267static DEVICE_ATTR(hsuid, 0644, qeth_l3_dev_hsuid_show,
268 qeth_l3_dev_hsuid_store);
269
270
Frank Blaschka4a71df52008-02-15 09:19:42 +0100271static struct attribute *qeth_l3_device_attrs[] = {
272 &dev_attr_route4.attr,
273 &dev_attr_route6.attr,
Ursula Braun76b11f82010-01-11 02:50:50 +0000274 &dev_attr_sniffer.attr,
Frank Blaschkab3332932011-08-08 01:33:59 +0000275 &dev_attr_hsuid.attr,
Frank Blaschka4a71df52008-02-15 09:19:42 +0100276 NULL,
277};
278
Arvind Yadavcfe9a042017-07-19 12:39:14 +0530279static const struct attribute_group qeth_l3_device_attr_group = {
Frank Blaschka4a71df52008-02-15 09:19:42 +0100280 .attrs = qeth_l3_device_attrs,
281};
282
283static ssize_t qeth_l3_dev_ipato_enable_show(struct device *dev,
284 struct device_attribute *attr, char *buf)
285{
286 struct qeth_card *card = dev_get_drvdata(dev);
287
Thorsten Winklerdde87692023-02-09 12:04:23 +0100288 return sysfs_emit(buf, "%u\n", card->ipato.enabled ? 1 : 0);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100289}
290
291static ssize_t qeth_l3_dev_ipato_enable_store(struct device *dev,
292 struct device_attribute *attr, const char *buf, size_t count)
293{
294 struct qeth_card *card = dev_get_drvdata(dev);
Julian Wiedmann7fbd9492017-12-13 18:56:29 +0100295 bool enable;
Julian Wiedmann02f510f2017-12-13 18:56:32 +0100296 int rc = 0;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100297
Frank Blaschkac4949f02010-05-11 19:34:47 +0000298 mutex_lock(&card->conf_mutex);
Julian Wiedmannd7d543f2019-02-28 18:59:36 +0100299 if (card->state != CARD_STATE_DOWN) {
Frank Blaschkac4949f02010-05-11 19:34:47 +0000300 rc = -EPERM;
301 goto out;
302 }
Frank Blaschka4a71df52008-02-15 09:19:42 +0100303
Julian Wiedmannd6e64262020-09-23 10:36:53 +0200304 mutex_lock(&card->ip_lock);
Eugene Crosser7e846d6b2015-01-16 14:05:48 +0100305 if (sysfs_streq(buf, "toggle")) {
Julian Wiedmann7fbd9492017-12-13 18:56:29 +0100306 enable = !card->ipato.enabled;
307 } else if (kstrtobool(buf, &enable)) {
Frank Blaschkac4949f02010-05-11 19:34:47 +0000308 rc = -EINVAL;
Julian Wiedmannd6e64262020-09-23 10:36:53 +0200309 goto unlock_ip;
Julian Wiedmann7fbd9492017-12-13 18:56:29 +0100310 }
311
Julian Wiedmann02f510f2017-12-13 18:56:32 +0100312 if (card->ipato.enabled != enable) {
313 card->ipato.enabled = enable;
Julian Wiedmann02f510f2017-12-13 18:56:32 +0100314 qeth_l3_update_ipato(card);
Julian Wiedmann7fbd9492017-12-13 18:56:29 +0100315 }
Julian Wiedmannd6e64262020-09-23 10:36:53 +0200316
317unlock_ip:
318 mutex_unlock(&card->ip_lock);
Frank Blaschkac4949f02010-05-11 19:34:47 +0000319out:
320 mutex_unlock(&card->conf_mutex);
321 return rc ? rc : count;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100322}
323
324static QETH_DEVICE_ATTR(ipato_enable, enable, 0644,
325 qeth_l3_dev_ipato_enable_show,
326 qeth_l3_dev_ipato_enable_store);
327
328static ssize_t qeth_l3_dev_ipato_invert4_show(struct device *dev,
329 struct device_attribute *attr, char *buf)
330{
331 struct qeth_card *card = dev_get_drvdata(dev);
332
Thorsten Winklerdde87692023-02-09 12:04:23 +0100333 return sysfs_emit(buf, "%u\n", card->ipato.invert4 ? 1 : 0);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100334}
335
336static ssize_t qeth_l3_dev_ipato_invert4_store(struct device *dev,
337 struct device_attribute *attr,
338 const char *buf, size_t count)
339{
340 struct qeth_card *card = dev_get_drvdata(dev);
Julian Wiedmann02f510f2017-12-13 18:56:32 +0100341 bool invert;
Frank Blaschkac4949f02010-05-11 19:34:47 +0000342 int rc = 0;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100343
Julian Wiedmannd6e64262020-09-23 10:36:53 +0200344 mutex_lock(&card->ip_lock);
Julian Wiedmann02f510f2017-12-13 18:56:32 +0100345 if (sysfs_streq(buf, "toggle")) {
346 invert = !card->ipato.invert4;
347 } else if (kstrtobool(buf, &invert)) {
Frank Blaschkac4949f02010-05-11 19:34:47 +0000348 rc = -EINVAL;
Julian Wiedmann02f510f2017-12-13 18:56:32 +0100349 goto out;
350 }
351
352 if (card->ipato.invert4 != invert) {
353 card->ipato.invert4 = invert;
Julian Wiedmann02f510f2017-12-13 18:56:32 +0100354 qeth_l3_update_ipato(card);
Julian Wiedmann02f510f2017-12-13 18:56:32 +0100355 }
Julian Wiedmannd6e64262020-09-23 10:36:53 +0200356
Julian Wiedmann02f510f2017-12-13 18:56:32 +0100357out:
Julian Wiedmannd6e64262020-09-23 10:36:53 +0200358 mutex_unlock(&card->ip_lock);
Frank Blaschkac4949f02010-05-11 19:34:47 +0000359 return rc ? rc : count;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100360}
361
362static QETH_DEVICE_ATTR(ipato_invert4, invert4, 0644,
363 qeth_l3_dev_ipato_invert4_show,
364 qeth_l3_dev_ipato_invert4_store);
365
366static ssize_t qeth_l3_dev_ipato_add_show(char *buf, struct qeth_card *card,
367 enum qeth_prot_versions proto)
368{
369 struct qeth_ipato_entry *ipatoe;
Thorsten Winklerdde87692023-02-09 12:04:23 +0100370 char addr_str[INET6_ADDRSTRLEN];
371 int offset = 0;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100372
Julian Wiedmanndf2a2a52019-03-28 16:39:23 +0100373 mutex_lock(&card->ip_lock);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100374 list_for_each_entry(ipatoe, &card->ipato.entries, entry) {
375 if (ipatoe->proto != proto)
376 continue;
Julian Wiedmanne6b1b7d2019-12-18 17:34:44 +0100377
Thorsten Winklerdde87692023-02-09 12:04:23 +0100378 qeth_l3_ipaddr_to_string(proto, ipatoe->addr, addr_str);
379 offset += sysfs_emit_at(buf, offset, "%s/%i\n",
380 addr_str, ipatoe->mask_bits);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100381 }
Julian Wiedmanndf2a2a52019-03-28 16:39:23 +0100382 mutex_unlock(&card->ip_lock);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100383
Thorsten Winklerdde87692023-02-09 12:04:23 +0100384 return offset ? offset : sysfs_emit(buf, "\n");
Frank Blaschka4a71df52008-02-15 09:19:42 +0100385}
386
387static ssize_t qeth_l3_dev_ipato_add4_show(struct device *dev,
388 struct device_attribute *attr, char *buf)
389{
390 struct qeth_card *card = dev_get_drvdata(dev);
391
Frank Blaschka4a71df52008-02-15 09:19:42 +0100392 return qeth_l3_dev_ipato_add_show(buf, card, QETH_PROT_IPV4);
393}
394
395static int qeth_l3_parse_ipatoe(const char *buf, enum qeth_prot_versions proto,
Julian Wiedmannab29c482020-09-23 10:36:55 +0200396 u8 *addr, unsigned int *mask_bits)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100397{
Julian Wiedmannab29c482020-09-23 10:36:55 +0200398 char *sep;
Julian Wiedmannbcdfdf02020-09-23 10:36:54 +0200399 int rc;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100400
Julian Wiedmannbcdfdf02020-09-23 10:36:54 +0200401 /* Expected input pattern: %addr/%mask */
Thorsten Winkler180f5132023-02-09 12:04:22 +0100402 sep = strnchr(buf, INET6_ADDRSTRLEN, '/');
Julian Wiedmannbcdfdf02020-09-23 10:36:54 +0200403 if (!sep)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100404 return -EINVAL;
Julian Wiedmannbcdfdf02020-09-23 10:36:54 +0200405
406 /* Terminate the %addr sub-string, and parse it: */
407 *sep = '\0';
408 rc = qeth_l3_string_to_ipaddr(buf, proto, addr);
409 if (rc)
410 return rc;
411
Julian Wiedmannab29c482020-09-23 10:36:55 +0200412 rc = kstrtouint(sep + 1, 10, mask_bits);
413 if (rc)
414 return rc;
415
416 if (*mask_bits > ((proto == QETH_PROT_IPV4) ? 32 : 128))
Frank Blaschka4a71df52008-02-15 09:19:42 +0100417 return -EINVAL;
Julian Wiedmannab29c482020-09-23 10:36:55 +0200418
Frank Blaschka4a71df52008-02-15 09:19:42 +0100419 return 0;
420}
421
422static ssize_t qeth_l3_dev_ipato_add_store(const char *buf, size_t count,
423 struct qeth_card *card, enum qeth_prot_versions proto)
424{
425 struct qeth_ipato_entry *ipatoe;
Julian Wiedmannab29c482020-09-23 10:36:55 +0200426 unsigned int mask_bits;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100427 u8 addr[16];
Frank Blaschkac4949f02010-05-11 19:34:47 +0000428 int rc = 0;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100429
430 rc = qeth_l3_parse_ipatoe(buf, proto, addr, &mask_bits);
431 if (rc)
Julian Wiedmann23901662019-12-18 17:34:45 +0100432 return rc;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100433
434 ipatoe = kzalloc(sizeof(struct qeth_ipato_entry), GFP_KERNEL);
Julian Wiedmann23901662019-12-18 17:34:45 +0100435 if (!ipatoe)
436 return -ENOMEM;
437
Frank Blaschka4a71df52008-02-15 09:19:42 +0100438 ipatoe->proto = proto;
Julian Wiedmann378ac802020-10-01 19:11:35 +0200439 memcpy(ipatoe->addr, addr, (proto == QETH_PROT_IPV4) ? 4 : 16);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100440 ipatoe->mask_bits = mask_bits;
441
442 rc = qeth_l3_add_ipato_entry(card, ipatoe);
Frank Blaschkac4949f02010-05-11 19:34:47 +0000443 if (rc)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100444 kfree(ipatoe);
Julian Wiedmann23901662019-12-18 17:34:45 +0100445
Frank Blaschkac4949f02010-05-11 19:34:47 +0000446 return rc ? rc : count;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100447}
448
449static ssize_t qeth_l3_dev_ipato_add4_store(struct device *dev,
450 struct device_attribute *attr, const char *buf, size_t count)
451{
452 struct qeth_card *card = dev_get_drvdata(dev);
453
Frank Blaschka4a71df52008-02-15 09:19:42 +0100454 return qeth_l3_dev_ipato_add_store(buf, count, card, QETH_PROT_IPV4);
455}
456
457static QETH_DEVICE_ATTR(ipato_add4, add4, 0644,
458 qeth_l3_dev_ipato_add4_show,
459 qeth_l3_dev_ipato_add4_store);
460
461static ssize_t qeth_l3_dev_ipato_del_store(const char *buf, size_t count,
462 struct qeth_card *card, enum qeth_prot_versions proto)
463{
Julian Wiedmannab29c482020-09-23 10:36:55 +0200464 unsigned int mask_bits;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100465 u8 addr[16];
Frank Blaschkac4949f02010-05-11 19:34:47 +0000466 int rc = 0;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100467
468 rc = qeth_l3_parse_ipatoe(buf, proto, addr, &mask_bits);
Frank Blaschkac4949f02010-05-11 19:34:47 +0000469 if (!rc)
Julian Wiedmannb9ea5252017-12-27 17:44:28 +0100470 rc = qeth_l3_del_ipato_entry(card, proto, addr, mask_bits);
Frank Blaschkac4949f02010-05-11 19:34:47 +0000471 return rc ? rc : count;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100472}
473
474static ssize_t qeth_l3_dev_ipato_del4_store(struct device *dev,
475 struct device_attribute *attr, const char *buf, size_t count)
476{
477 struct qeth_card *card = dev_get_drvdata(dev);
478
Frank Blaschka4a71df52008-02-15 09:19:42 +0100479 return qeth_l3_dev_ipato_del_store(buf, count, card, QETH_PROT_IPV4);
480}
481
482static QETH_DEVICE_ATTR(ipato_del4, del4, 0200, NULL,
483 qeth_l3_dev_ipato_del4_store);
484
485static ssize_t qeth_l3_dev_ipato_invert6_show(struct device *dev,
486 struct device_attribute *attr, char *buf)
487{
488 struct qeth_card *card = dev_get_drvdata(dev);
489
Thorsten Winklerdde87692023-02-09 12:04:23 +0100490 return sysfs_emit(buf, "%u\n", card->ipato.invert6 ? 1 : 0);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100491}
492
493static ssize_t qeth_l3_dev_ipato_invert6_store(struct device *dev,
494 struct device_attribute *attr, const char *buf, size_t count)
495{
496 struct qeth_card *card = dev_get_drvdata(dev);
Julian Wiedmann02f510f2017-12-13 18:56:32 +0100497 bool invert;
Frank Blaschkac4949f02010-05-11 19:34:47 +0000498 int rc = 0;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100499
Julian Wiedmannd6e64262020-09-23 10:36:53 +0200500 mutex_lock(&card->ip_lock);
Julian Wiedmann02f510f2017-12-13 18:56:32 +0100501 if (sysfs_streq(buf, "toggle")) {
502 invert = !card->ipato.invert6;
503 } else if (kstrtobool(buf, &invert)) {
Frank Blaschkac4949f02010-05-11 19:34:47 +0000504 rc = -EINVAL;
Julian Wiedmann02f510f2017-12-13 18:56:32 +0100505 goto out;
506 }
507
508 if (card->ipato.invert6 != invert) {
509 card->ipato.invert6 = invert;
Julian Wiedmann02f510f2017-12-13 18:56:32 +0100510 qeth_l3_update_ipato(card);
Julian Wiedmann02f510f2017-12-13 18:56:32 +0100511 }
Julian Wiedmannd6e64262020-09-23 10:36:53 +0200512
Julian Wiedmann02f510f2017-12-13 18:56:32 +0100513out:
Julian Wiedmannd6e64262020-09-23 10:36:53 +0200514 mutex_unlock(&card->ip_lock);
Frank Blaschkac4949f02010-05-11 19:34:47 +0000515 return rc ? rc : count;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100516}
517
518static QETH_DEVICE_ATTR(ipato_invert6, invert6, 0644,
519 qeth_l3_dev_ipato_invert6_show,
520 qeth_l3_dev_ipato_invert6_store);
521
522
523static ssize_t qeth_l3_dev_ipato_add6_show(struct device *dev,
524 struct device_attribute *attr, char *buf)
525{
526 struct qeth_card *card = dev_get_drvdata(dev);
527
Frank Blaschka4a71df52008-02-15 09:19:42 +0100528 return qeth_l3_dev_ipato_add_show(buf, card, QETH_PROT_IPV6);
529}
530
531static ssize_t qeth_l3_dev_ipato_add6_store(struct device *dev,
532 struct device_attribute *attr, const char *buf, size_t count)
533{
534 struct qeth_card *card = dev_get_drvdata(dev);
535
Frank Blaschka4a71df52008-02-15 09:19:42 +0100536 return qeth_l3_dev_ipato_add_store(buf, count, card, QETH_PROT_IPV6);
537}
538
539static QETH_DEVICE_ATTR(ipato_add6, add6, 0644,
540 qeth_l3_dev_ipato_add6_show,
541 qeth_l3_dev_ipato_add6_store);
542
543static ssize_t qeth_l3_dev_ipato_del6_store(struct device *dev,
544 struct device_attribute *attr, const char *buf, size_t count)
545{
546 struct qeth_card *card = dev_get_drvdata(dev);
547
Frank Blaschka4a71df52008-02-15 09:19:42 +0100548 return qeth_l3_dev_ipato_del_store(buf, count, card, QETH_PROT_IPV6);
549}
550
551static QETH_DEVICE_ATTR(ipato_del6, del6, 0200, NULL,
552 qeth_l3_dev_ipato_del6_store);
553
554static struct attribute *qeth_ipato_device_attrs[] = {
555 &dev_attr_ipato_enable.attr,
556 &dev_attr_ipato_invert4.attr,
557 &dev_attr_ipato_add4.attr,
558 &dev_attr_ipato_del4.attr,
559 &dev_attr_ipato_invert6.attr,
560 &dev_attr_ipato_add6.attr,
561 &dev_attr_ipato_del6.attr,
562 NULL,
563};
564
Arvind Yadavcfe9a042017-07-19 12:39:14 +0530565static const struct attribute_group qeth_device_ipato_group = {
Frank Blaschka4a71df52008-02-15 09:19:42 +0100566 .name = "ipa_takeover",
567 .attrs = qeth_ipato_device_attrs,
568};
569
Julian Wiedmannd2073ef2017-12-27 17:44:29 +0100570static ssize_t qeth_l3_dev_ip_add_show(struct device *dev, char *buf,
571 enum qeth_prot_versions proto,
572 enum qeth_ip_types type)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100573{
Julian Wiedmannd2073ef2017-12-27 17:44:29 +0100574 struct qeth_card *card = dev_get_drvdata(dev);
Thorsten Winklerdde87692023-02-09 12:04:23 +0100575 char addr_str[INET6_ADDRSTRLEN];
Frank Blaschka4a71df52008-02-15 09:19:42 +0100576 struct qeth_ipaddr *ipaddr;
Thorsten Winklerdde87692023-02-09 12:04:23 +0100577 int offset = 0;
Ursula Braune48b9ea2017-01-12 15:48:43 +0100578 int i;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100579
Julian Wiedmanndf2a2a52019-03-28 16:39:23 +0100580 mutex_lock(&card->ip_lock);
Ursula Braune48b9ea2017-01-12 15:48:43 +0100581 hash_for_each(card->ip_htable, i, ipaddr, hnode) {
Julian Wiedmannd2073ef2017-12-27 17:44:29 +0100582 if (ipaddr->proto != proto || ipaddr->type != type)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100583 continue;
Julian Wiedmanne6b1b7d2019-12-18 17:34:44 +0100584
Thorsten Winklerdde87692023-02-09 12:04:23 +0100585 qeth_l3_ipaddr_to_string(proto, (u8 *)&ipaddr->u, addr_str);
586 offset += sysfs_emit_at(buf, offset, "%s\n", addr_str);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100587 }
Julian Wiedmanndf2a2a52019-03-28 16:39:23 +0100588 mutex_unlock(&card->ip_lock);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100589
Thorsten Winklerdde87692023-02-09 12:04:23 +0100590 return offset ? offset : sysfs_emit(buf, "\n");
Frank Blaschka4a71df52008-02-15 09:19:42 +0100591}
592
593static ssize_t qeth_l3_dev_vipa_add4_show(struct device *dev,
Julian Wiedmannd2073ef2017-12-27 17:44:29 +0100594 struct device_attribute *attr,
595 char *buf)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100596{
Julian Wiedmannd2073ef2017-12-27 17:44:29 +0100597 return qeth_l3_dev_ip_add_show(dev, buf, QETH_PROT_IPV4,
598 QETH_IP_TYPE_VIPA);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100599}
600
Julian Wiedmann23901662019-12-18 17:34:45 +0100601static ssize_t qeth_l3_vipa_store(struct device *dev, const char *buf, bool add,
602 size_t count, enum qeth_prot_versions proto)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100603{
Julian Wiedmann23901662019-12-18 17:34:45 +0100604 struct qeth_card *card = dev_get_drvdata(dev);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100605 u8 addr[16] = {0, };
606 int rc;
607
Julian Wiedmann23901662019-12-18 17:34:45 +0100608 rc = qeth_l3_string_to_ipaddr(buf, proto, addr);
Frank Blaschkac4949f02010-05-11 19:34:47 +0000609 if (!rc)
Julian Wiedmann23901662019-12-18 17:34:45 +0100610 rc = qeth_l3_modify_rxip_vipa(card, add, addr,
Julian Wiedmann1617dae2018-03-09 18:13:02 +0100611 QETH_IP_TYPE_VIPA, proto);
Frank Blaschkac4949f02010-05-11 19:34:47 +0000612 return rc ? rc : count;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100613}
614
615static ssize_t qeth_l3_dev_vipa_add4_store(struct device *dev,
616 struct device_attribute *attr, const char *buf, size_t count)
617{
Julian Wiedmann23901662019-12-18 17:34:45 +0100618 return qeth_l3_vipa_store(dev, buf, true, count, QETH_PROT_IPV4);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100619}
620
621static QETH_DEVICE_ATTR(vipa_add4, add4, 0644,
622 qeth_l3_dev_vipa_add4_show,
623 qeth_l3_dev_vipa_add4_store);
624
Frank Blaschka4a71df52008-02-15 09:19:42 +0100625static ssize_t qeth_l3_dev_vipa_del4_store(struct device *dev,
626 struct device_attribute *attr, const char *buf, size_t count)
627{
Thorsten Winkler80de8092023-07-04 16:41:21 +0200628 return qeth_l3_vipa_store(dev, buf, false, count, QETH_PROT_IPV4);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100629}
630
631static QETH_DEVICE_ATTR(vipa_del4, del4, 0200, NULL,
632 qeth_l3_dev_vipa_del4_store);
633
634static ssize_t qeth_l3_dev_vipa_add6_show(struct device *dev,
Julian Wiedmannd2073ef2017-12-27 17:44:29 +0100635 struct device_attribute *attr,
636 char *buf)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100637{
Julian Wiedmannd2073ef2017-12-27 17:44:29 +0100638 return qeth_l3_dev_ip_add_show(dev, buf, QETH_PROT_IPV6,
639 QETH_IP_TYPE_VIPA);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100640}
641
642static ssize_t qeth_l3_dev_vipa_add6_store(struct device *dev,
643 struct device_attribute *attr, const char *buf, size_t count)
644{
Julian Wiedmann23901662019-12-18 17:34:45 +0100645 return qeth_l3_vipa_store(dev, buf, true, count, QETH_PROT_IPV6);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100646}
647
648static QETH_DEVICE_ATTR(vipa_add6, add6, 0644,
649 qeth_l3_dev_vipa_add6_show,
650 qeth_l3_dev_vipa_add6_store);
651
652static ssize_t qeth_l3_dev_vipa_del6_store(struct device *dev,
653 struct device_attribute *attr, const char *buf, size_t count)
654{
Julian Wiedmann23901662019-12-18 17:34:45 +0100655 return qeth_l3_vipa_store(dev, buf, false, count, QETH_PROT_IPV6);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100656}
657
658static QETH_DEVICE_ATTR(vipa_del6, del6, 0200, NULL,
659 qeth_l3_dev_vipa_del6_store);
660
661static struct attribute *qeth_vipa_device_attrs[] = {
662 &dev_attr_vipa_add4.attr,
663 &dev_attr_vipa_del4.attr,
664 &dev_attr_vipa_add6.attr,
665 &dev_attr_vipa_del6.attr,
666 NULL,
667};
668
Arvind Yadavcfe9a042017-07-19 12:39:14 +0530669static const struct attribute_group qeth_device_vipa_group = {
Frank Blaschka4a71df52008-02-15 09:19:42 +0100670 .name = "vipa",
671 .attrs = qeth_vipa_device_attrs,
672};
673
Frank Blaschka4a71df52008-02-15 09:19:42 +0100674static ssize_t qeth_l3_dev_rxip_add4_show(struct device *dev,
Julian Wiedmannd2073ef2017-12-27 17:44:29 +0100675 struct device_attribute *attr,
676 char *buf)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100677{
Julian Wiedmannd2073ef2017-12-27 17:44:29 +0100678 return qeth_l3_dev_ip_add_show(dev, buf, QETH_PROT_IPV4,
679 QETH_IP_TYPE_RXIP);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100680}
681
682static int qeth_l3_parse_rxipe(const char *buf, enum qeth_prot_versions proto,
683 u8 *addr)
684{
Kittipon Meesompopaa9bea02017-08-15 17:02:48 +0200685 __be32 ipv4_addr;
686 struct in6_addr ipv6_addr;
687
Frank Blaschka4a71df52008-02-15 09:19:42 +0100688 if (qeth_l3_string_to_ipaddr(buf, proto, addr)) {
Frank Blaschka4a71df52008-02-15 09:19:42 +0100689 return -EINVAL;
690 }
Kittipon Meesompopaa9bea02017-08-15 17:02:48 +0200691 if (proto == QETH_PROT_IPV4) {
692 memcpy(&ipv4_addr, addr, sizeof(ipv4_addr));
693 if (ipv4_is_multicast(ipv4_addr)) {
694 QETH_DBF_MESSAGE(2, "multicast rxip not supported.\n");
695 return -EINVAL;
696 }
697 } else if (proto == QETH_PROT_IPV6) {
698 memcpy(&ipv6_addr, addr, sizeof(ipv6_addr));
699 if (ipv6_addr_is_multicast(&ipv6_addr)) {
700 QETH_DBF_MESSAGE(2, "multicast rxip not supported.\n");
701 return -EINVAL;
702 }
703 }
704
Frank Blaschka4a71df52008-02-15 09:19:42 +0100705 return 0;
706}
707
Julian Wiedmann23901662019-12-18 17:34:45 +0100708static ssize_t qeth_l3_rxip_store(struct device *dev, const char *buf, bool add,
709 size_t count, enum qeth_prot_versions proto)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100710{
Julian Wiedmann23901662019-12-18 17:34:45 +0100711 struct qeth_card *card = dev_get_drvdata(dev);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100712 u8 addr[16] = {0, };
713 int rc;
714
715 rc = qeth_l3_parse_rxipe(buf, proto, addr);
Frank Blaschkac4949f02010-05-11 19:34:47 +0000716 if (!rc)
Julian Wiedmann23901662019-12-18 17:34:45 +0100717 rc = qeth_l3_modify_rxip_vipa(card, add, addr,
Julian Wiedmann1617dae2018-03-09 18:13:02 +0100718 QETH_IP_TYPE_RXIP, proto);
Frank Blaschkac4949f02010-05-11 19:34:47 +0000719 return rc ? rc : count;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100720}
721
722static ssize_t qeth_l3_dev_rxip_add4_store(struct device *dev,
723 struct device_attribute *attr, const char *buf, size_t count)
724{
Julian Wiedmann23901662019-12-18 17:34:45 +0100725 return qeth_l3_rxip_store(dev, buf, true, count, QETH_PROT_IPV4);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100726}
727
728static QETH_DEVICE_ATTR(rxip_add4, add4, 0644,
729 qeth_l3_dev_rxip_add4_show,
730 qeth_l3_dev_rxip_add4_store);
731
Frank Blaschka4a71df52008-02-15 09:19:42 +0100732static ssize_t qeth_l3_dev_rxip_del4_store(struct device *dev,
733 struct device_attribute *attr, const char *buf, size_t count)
734{
Julian Wiedmann23901662019-12-18 17:34:45 +0100735 return qeth_l3_rxip_store(dev, buf, false, count, QETH_PROT_IPV4);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100736}
737
738static QETH_DEVICE_ATTR(rxip_del4, del4, 0200, NULL,
739 qeth_l3_dev_rxip_del4_store);
740
741static ssize_t qeth_l3_dev_rxip_add6_show(struct device *dev,
Julian Wiedmannd2073ef2017-12-27 17:44:29 +0100742 struct device_attribute *attr,
743 char *buf)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100744{
Julian Wiedmannd2073ef2017-12-27 17:44:29 +0100745 return qeth_l3_dev_ip_add_show(dev, buf, QETH_PROT_IPV6,
746 QETH_IP_TYPE_RXIP);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100747}
748
749static ssize_t qeth_l3_dev_rxip_add6_store(struct device *dev,
750 struct device_attribute *attr, const char *buf, size_t count)
751{
Julian Wiedmann23901662019-12-18 17:34:45 +0100752 return qeth_l3_rxip_store(dev, buf, true, count, QETH_PROT_IPV6);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100753}
754
755static QETH_DEVICE_ATTR(rxip_add6, add6, 0644,
756 qeth_l3_dev_rxip_add6_show,
757 qeth_l3_dev_rxip_add6_store);
758
759static ssize_t qeth_l3_dev_rxip_del6_store(struct device *dev,
760 struct device_attribute *attr, const char *buf, size_t count)
761{
Julian Wiedmann23901662019-12-18 17:34:45 +0100762 return qeth_l3_rxip_store(dev, buf, false, count, QETH_PROT_IPV6);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100763}
764
765static QETH_DEVICE_ATTR(rxip_del6, del6, 0200, NULL,
766 qeth_l3_dev_rxip_del6_store);
767
768static struct attribute *qeth_rxip_device_attrs[] = {
769 &dev_attr_rxip_add4.attr,
770 &dev_attr_rxip_del4.attr,
771 &dev_attr_rxip_add6.attr,
772 &dev_attr_rxip_del6.attr,
773 NULL,
774};
775
Arvind Yadavcfe9a042017-07-19 12:39:14 +0530776static const struct attribute_group qeth_device_rxip_group = {
Frank Blaschka4a71df52008-02-15 09:19:42 +0100777 .name = "rxip",
778 .attrs = qeth_rxip_device_attrs,
779};
780
Ursula Braun79a04e42017-06-06 14:33:49 +0200781const struct attribute_group *qeth_l3_attr_groups[] = {
Ursula Braun79a04e42017-06-06 14:33:49 +0200782 &qeth_l3_device_attr_group,
783 &qeth_device_ipato_group,
784 &qeth_device_vipa_group,
785 &qeth_device_rxip_group,
Julian Wiedmannab25a502017-09-18 21:18:19 +0200786 NULL,
Ursula Braun79a04e42017-06-06 14:33:49 +0200787};