xref: /linux/drivers/net/wireless/marvell/libertas/mesh.c (revision e7d759f31ca295d589f7420719c311870bb3166f)
1 // SPDX-License-Identifier: GPL-2.0
2 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
3 
4 #include <linux/delay.h>
5 #include <linux/etherdevice.h>
6 #include <linux/hardirq.h>
7 #include <linux/netdevice.h>
8 #include <linux/if_ether.h>
9 #include <linux/if_arp.h>
10 #include <linux/kthread.h>
11 #include <linux/kfifo.h>
12 #include <net/cfg80211.h>
13 
14 #include "mesh.h"
15 #include "decl.h"
16 #include "cmd.h"
17 
18 
19 static int lbs_add_mesh(struct lbs_private *priv);
20 
21 /***************************************************************************
22  * Mesh command handling
23  */
24 
25 static int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action,
26 		    struct cmd_ds_mesh_access *cmd)
27 {
28 	int ret;
29 
30 	cmd->hdr.command = cpu_to_le16(CMD_MESH_ACCESS);
31 	cmd->hdr.size = cpu_to_le16(sizeof(*cmd));
32 	cmd->hdr.result = 0;
33 
34 	cmd->action = cpu_to_le16(cmd_action);
35 
36 	ret = lbs_cmd_with_response(priv, CMD_MESH_ACCESS, cmd);
37 
38 	return ret;
39 }
40 
41 static int __lbs_mesh_config_send(struct lbs_private *priv,
42 				  struct cmd_ds_mesh_config *cmd,
43 				  uint16_t action, uint16_t type)
44 {
45 	int ret;
46 	u16 command = CMD_MESH_CONFIG_OLD;
47 
48 	/*
49 	 * Command id is 0xac for v10 FW along with mesh interface
50 	 * id in bits 14-13-12.
51 	 */
52 	if (priv->mesh_tlv == TLV_TYPE_MESH_ID)
53 		command = CMD_MESH_CONFIG |
54 			  (MESH_IFACE_ID << MESH_IFACE_BIT_OFFSET);
55 
56 	cmd->hdr.command = cpu_to_le16(command);
57 	cmd->hdr.size = cpu_to_le16(sizeof(struct cmd_ds_mesh_config));
58 	cmd->hdr.result = 0;
59 
60 	cmd->type = cpu_to_le16(type);
61 	cmd->action = cpu_to_le16(action);
62 
63 	ret = lbs_cmd_with_response(priv, command, cmd);
64 
65 	return ret;
66 }
67 
68 static int lbs_mesh_config_send(struct lbs_private *priv,
69 			 struct cmd_ds_mesh_config *cmd,
70 			 uint16_t action, uint16_t type)
71 {
72 	int ret;
73 
74 	if (!(priv->fwcapinfo & FW_CAPINFO_PERSISTENT_CONFIG))
75 		return -EOPNOTSUPP;
76 
77 	ret = __lbs_mesh_config_send(priv, cmd, action, type);
78 	return ret;
79 }
80 
81 /* This function is the CMD_MESH_CONFIG legacy function.  It only handles the
82  * START and STOP actions.  The extended actions supported by CMD_MESH_CONFIG
83  * are all handled by preparing a struct cmd_ds_mesh_config and passing it to
84  * lbs_mesh_config_send.
85  */
86 static int lbs_mesh_config(struct lbs_private *priv, uint16_t action,
87 		uint16_t chan)
88 {
89 	struct wireless_dev *mesh_wdev;
90 	struct cmd_ds_mesh_config cmd;
91 	struct mrvl_meshie *ie;
92 
93 	memset(&cmd, 0, sizeof(cmd));
94 	cmd.channel = cpu_to_le16(chan);
95 	ie = (struct mrvl_meshie *)cmd.data;
96 
97 	switch (action) {
98 	case CMD_ACT_MESH_CONFIG_START:
99 		ie->id = WLAN_EID_VENDOR_SPECIFIC;
100 		ie->val.oui[0] = 0x00;
101 		ie->val.oui[1] = 0x50;
102 		ie->val.oui[2] = 0x43;
103 		ie->val.type = MARVELL_MESH_IE_TYPE;
104 		ie->val.subtype = MARVELL_MESH_IE_SUBTYPE;
105 		ie->val.version = MARVELL_MESH_IE_VERSION;
106 		ie->val.active_protocol_id = MARVELL_MESH_PROTO_ID_HWMP;
107 		ie->val.active_metric_id = MARVELL_MESH_METRIC_ID;
108 		ie->val.mesh_capability = MARVELL_MESH_CAPABILITY;
109 
110 		if (priv->mesh_dev) {
111 			mesh_wdev = priv->mesh_dev->ieee80211_ptr;
112 			ie->val.mesh_id_len = mesh_wdev->u.mesh.id_up_len;
113 			memcpy(ie->val.mesh_id, mesh_wdev->u.mesh.id,
114 						mesh_wdev->u.mesh.id_up_len);
115 		}
116 
117 		ie->len = sizeof(struct mrvl_meshie_val) -
118 			IEEE80211_MAX_SSID_LEN + ie->val.mesh_id_len;
119 
120 		cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie_val));
121 		break;
122 	case CMD_ACT_MESH_CONFIG_STOP:
123 		break;
124 	default:
125 		return -1;
126 	}
127 	lbs_deb_cmd("mesh config action %d type %x channel %d SSID %*pE\n",
128 		    action, priv->mesh_tlv, chan, ie->val.mesh_id_len,
129 		    ie->val.mesh_id);
130 
131 	return __lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv);
132 }
133 
134 int lbs_mesh_set_channel(struct lbs_private *priv, u8 channel)
135 {
136 	priv->mesh_channel = channel;
137 	return lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, channel);
138 }
139 
140 static uint16_t lbs_mesh_get_channel(struct lbs_private *priv)
141 {
142 	return priv->mesh_channel ?: 1;
143 }
144 
145 /***************************************************************************
146  * Mesh sysfs support
147  */
148 
149 /*
150  * Attributes exported through sysfs
151  */
152 
153 /**
154  * anycast_mask_show - Get function for sysfs attribute anycast_mask
155  * @dev: the &struct device
156  * @attr: device attributes
157  * @buf: buffer where data will be returned
158  */
159 static ssize_t anycast_mask_show(struct device *dev,
160 				 struct device_attribute *attr, char *buf)
161 {
162 	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
163 	struct cmd_ds_mesh_access mesh_access;
164 	int ret;
165 
166 	memset(&mesh_access, 0, sizeof(mesh_access));
167 
168 	ret = lbs_mesh_access(priv, CMD_ACT_MESH_GET_ANYCAST, &mesh_access);
169 	if (ret)
170 		return ret;
171 
172 	return sysfs_emit(buf, "0x%X\n", le32_to_cpu(mesh_access.data[0]));
173 }
174 
175 /**
176  * anycast_mask_store - Set function for sysfs attribute anycast_mask
177  * @dev: the &struct device
178  * @attr: device attributes
179  * @buf: buffer that contains new attribute value
180  * @count: size of buffer
181  */
182 static ssize_t anycast_mask_store(struct device *dev,
183 				  struct device_attribute *attr,
184 				  const char *buf, size_t count)
185 {
186 	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
187 	struct cmd_ds_mesh_access mesh_access;
188 	uint32_t datum;
189 	int ret;
190 
191 	ret = kstrtouint(buf, 16, &datum);
192 	if (ret)
193 		return ret;
194 
195 	memset(&mesh_access, 0, sizeof(mesh_access));
196 	mesh_access.data[0] = cpu_to_le32(datum);
197 
198 	ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_ANYCAST, &mesh_access);
199 	if (ret)
200 		return ret;
201 
202 	return strlen(buf);
203 }
204 
205 /**
206  * prb_rsp_limit_show - Get function for sysfs attribute prb_rsp_limit
207  * @dev: the &struct device
208  * @attr: device attributes
209  * @buf: buffer where data will be returned
210  */
211 static ssize_t prb_rsp_limit_show(struct device *dev,
212 				  struct device_attribute *attr, char *buf)
213 {
214 	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
215 	struct cmd_ds_mesh_access mesh_access;
216 	int ret;
217 	u32 retry_limit;
218 
219 	memset(&mesh_access, 0, sizeof(mesh_access));
220 	mesh_access.data[0] = cpu_to_le32(CMD_ACT_GET);
221 
222 	ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_GET_PRB_RSP_LIMIT,
223 			&mesh_access);
224 	if (ret)
225 		return ret;
226 
227 	retry_limit = le32_to_cpu(mesh_access.data[1]);
228 	return sysfs_emit(buf, "%d\n", retry_limit);
229 }
230 
231 /**
232  * prb_rsp_limit_store - Set function for sysfs attribute prb_rsp_limit
233  * @dev: the &struct device
234  * @attr: device attributes
235  * @buf: buffer that contains new attribute value
236  * @count: size of buffer
237  */
238 static ssize_t prb_rsp_limit_store(struct device *dev,
239 				   struct device_attribute *attr,
240 				   const char *buf, size_t count)
241 {
242 	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
243 	struct cmd_ds_mesh_access mesh_access;
244 	int ret;
245 	unsigned long retry_limit;
246 
247 	ret = kstrtoul(buf, 10, &retry_limit);
248 	if (ret)
249 		return ret;
250 	if (retry_limit > 15)
251 		return -ENOTSUPP;
252 
253 	memset(&mesh_access, 0, sizeof(mesh_access));
254 	mesh_access.data[0] = cpu_to_le32(CMD_ACT_SET);
255 	mesh_access.data[1] = cpu_to_le32(retry_limit);
256 
257 	ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_GET_PRB_RSP_LIMIT,
258 			&mesh_access);
259 	if (ret)
260 		return ret;
261 
262 	return strlen(buf);
263 }
264 
265 /**
266  * lbs_mesh_show - Get function for sysfs attribute mesh
267  * @dev: the &struct device
268  * @attr: device attributes
269  * @buf: buffer where data will be returned
270  */
271 static ssize_t lbs_mesh_show(struct device *dev,
272 			     struct device_attribute *attr, char *buf)
273 {
274 	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
275 	return sysfs_emit(buf, "0x%X\n", !!priv->mesh_dev);
276 }
277 
278 /**
279  * lbs_mesh_store - Set function for sysfs attribute mesh
280  * @dev: the &struct device
281  * @attr: device attributes
282  * @buf: buffer that contains new attribute value
283  * @count: size of buffer
284  */
285 static ssize_t lbs_mesh_store(struct device *dev,
286 			      struct device_attribute *attr,
287 			      const char *buf, size_t count)
288 {
289 	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
290 	int ret, enable;
291 
292 	ret = kstrtoint(buf, 16, &enable);
293 	if (ret)
294 		return ret;
295 
296 	enable = !!enable;
297 	if (enable == !!priv->mesh_dev)
298 		return count;
299 
300 	if (enable)
301 		lbs_add_mesh(priv);
302 	else
303 		lbs_remove_mesh(priv);
304 
305 	return count;
306 }
307 
308 /*
309  * lbs_mesh attribute to be exported per ethX interface
310  * through sysfs (/sys/class/net/ethX/lbs_mesh)
311  */
312 static DEVICE_ATTR_RW(lbs_mesh);
313 
314 /*
315  * anycast_mask attribute to be exported per mshX interface
316  * through sysfs (/sys/class/net/mshX/anycast_mask)
317  */
318 static DEVICE_ATTR_RW(anycast_mask);
319 
320 /*
321  * prb_rsp_limit attribute to be exported per mshX interface
322  * through sysfs (/sys/class/net/mshX/prb_rsp_limit)
323  */
324 static DEVICE_ATTR_RW(prb_rsp_limit);
325 
326 static struct attribute *lbs_mesh_sysfs_entries[] = {
327 	&dev_attr_anycast_mask.attr,
328 	&dev_attr_prb_rsp_limit.attr,
329 	NULL,
330 };
331 
332 static const struct attribute_group lbs_mesh_attr_group = {
333 	.attrs = lbs_mesh_sysfs_entries,
334 };
335 
336 
337 /***************************************************************************
338  * Persistent configuration support
339  */
340 
341 static int mesh_get_default_parameters(struct device *dev,
342 				       struct mrvl_mesh_defaults *defs)
343 {
344 	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
345 	struct cmd_ds_mesh_config cmd;
346 	int ret;
347 
348 	memset(&cmd, 0, sizeof(struct cmd_ds_mesh_config));
349 	ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_GET,
350 				   CMD_TYPE_MESH_GET_DEFAULTS);
351 
352 	if (ret)
353 		return -EOPNOTSUPP;
354 
355 	memcpy(defs, &cmd.data[0], sizeof(struct mrvl_mesh_defaults));
356 
357 	return 0;
358 }
359 
360 /**
361  * bootflag_show - Get function for sysfs attribute bootflag
362  * @dev: the &struct device
363  * @attr: device attributes
364  * @buf: buffer where data will be returned
365  */
366 static ssize_t bootflag_show(struct device *dev,
367 			     struct device_attribute *attr, char *buf)
368 {
369 	struct mrvl_mesh_defaults defs;
370 	int ret;
371 
372 	ret = mesh_get_default_parameters(dev, &defs);
373 
374 	if (ret)
375 		return ret;
376 
377 	return sysfs_emit(buf, "%d\n", le32_to_cpu(defs.bootflag));
378 }
379 
380 /**
381  * bootflag_store - Set function for sysfs attribute bootflag
382  * @dev: the &struct device
383  * @attr: device attributes
384  * @buf: buffer that contains new attribute value
385  * @count: size of buffer
386  */
387 static ssize_t bootflag_store(struct device *dev, struct device_attribute *attr,
388 			      const char *buf, size_t count)
389 {
390 	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
391 	struct cmd_ds_mesh_config cmd;
392 	uint32_t datum;
393 	int ret;
394 
395 	ret = kstrtouint(buf, 10, &datum);
396 	if (ret)
397 		return ret;
398 	if (datum > 1)
399 		return -EINVAL;
400 
401 	memset(&cmd, 0, sizeof(cmd));
402 	*((__le32 *)&cmd.data[0]) = cpu_to_le32(!!datum);
403 	cmd.length = cpu_to_le16(sizeof(uint32_t));
404 	ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
405 				   CMD_TYPE_MESH_SET_BOOTFLAG);
406 	if (ret)
407 		return ret;
408 
409 	return strlen(buf);
410 }
411 
412 /**
413  * boottime_show - Get function for sysfs attribute boottime
414  * @dev: the &struct device
415  * @attr: device attributes
416  * @buf: buffer where data will be returned
417  */
418 static ssize_t boottime_show(struct device *dev,
419 			     struct device_attribute *attr, char *buf)
420 {
421 	struct mrvl_mesh_defaults defs;
422 	int ret;
423 
424 	ret = mesh_get_default_parameters(dev, &defs);
425 
426 	if (ret)
427 		return ret;
428 
429 	return sysfs_emit(buf, "%d\n", defs.boottime);
430 }
431 
432 /**
433  * boottime_store - Set function for sysfs attribute boottime
434  * @dev: the &struct device
435  * @attr: device attributes
436  * @buf: buffer that contains new attribute value
437  * @count: size of buffer
438  */
439 static ssize_t boottime_store(struct device *dev,
440 			      struct device_attribute *attr,
441 			      const char *buf, size_t count)
442 {
443 	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
444 	struct cmd_ds_mesh_config cmd;
445 	uint32_t datum;
446 	int ret;
447 
448 	ret = kstrtouint(buf, 10, &datum);
449 	if (ret)
450 		return ret;
451 	if (datum > 255)
452 		return -EINVAL;
453 
454 	memset(&cmd, 0, sizeof(cmd));
455 
456 	/* A too small boot time will result in the device booting into
457 	 * standalone (no-host) mode before the host can take control of it,
458 	 * so the change will be hard to revert.  This may be a desired
459 	 * feature (e.g to configure a very fast boot time for devices that
460 	 * will not be attached to a host), but dangerous.  So I'm enforcing a
461 	 * lower limit of 20 seconds:  remove and recompile the driver if this
462 	 * does not work for you.
463 	 */
464 	datum = (datum < 20) ? 20 : datum;
465 	cmd.data[0] = datum;
466 	cmd.length = cpu_to_le16(sizeof(uint8_t));
467 	ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
468 				   CMD_TYPE_MESH_SET_BOOTTIME);
469 	if (ret)
470 		return ret;
471 
472 	return strlen(buf);
473 }
474 
475 /**
476  * channel_show - Get function for sysfs attribute channel
477  * @dev: the &struct device
478  * @attr: device attributes
479  * @buf: buffer where data will be returned
480  */
481 static ssize_t channel_show(struct device *dev,
482 			    struct device_attribute *attr, char *buf)
483 {
484 	struct mrvl_mesh_defaults defs;
485 	int ret;
486 
487 	ret = mesh_get_default_parameters(dev, &defs);
488 
489 	if (ret)
490 		return ret;
491 
492 	return sysfs_emit(buf, "%d\n", le16_to_cpu(defs.channel));
493 }
494 
495 /**
496  * channel_store - Set function for sysfs attribute channel
497  * @dev: the &struct device
498  * @attr: device attributes
499  * @buf: buffer that contains new attribute value
500  * @count: size of buffer
501  */
502 static ssize_t channel_store(struct device *dev, struct device_attribute *attr,
503 			     const char *buf, size_t count)
504 {
505 	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
506 	struct cmd_ds_mesh_config cmd;
507 	uint32_t datum;
508 	int ret;
509 
510 	ret = kstrtouint(buf, 10, &datum);
511 	if (ret)
512 		return ret;
513 	if (datum < 1 || datum > 11)
514 		return -EINVAL;
515 
516 	memset(&cmd, 0, sizeof(cmd));
517 	*((__le16 *)&cmd.data[0]) = cpu_to_le16(datum);
518 	cmd.length = cpu_to_le16(sizeof(uint16_t));
519 	ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
520 				   CMD_TYPE_MESH_SET_DEF_CHANNEL);
521 	if (ret)
522 		return ret;
523 
524 	return strlen(buf);
525 }
526 
527 /**
528  * mesh_id_show - Get function for sysfs attribute mesh_id
529  * @dev: the &struct device
530  * @attr: device attributes
531  * @buf: buffer where data will be returned
532  */
533 static ssize_t mesh_id_show(struct device *dev, struct device_attribute *attr,
534 			    char *buf)
535 {
536 	struct mrvl_mesh_defaults defs;
537 	int ret;
538 
539 	ret = mesh_get_default_parameters(dev, &defs);
540 
541 	if (ret)
542 		return ret;
543 
544 	if (defs.meshie.val.mesh_id_len > IEEE80211_MAX_SSID_LEN) {
545 		dev_err(dev, "inconsistent mesh ID length\n");
546 		defs.meshie.val.mesh_id_len = IEEE80211_MAX_SSID_LEN;
547 	}
548 
549 	memcpy(buf, defs.meshie.val.mesh_id, defs.meshie.val.mesh_id_len);
550 	buf[defs.meshie.val.mesh_id_len] = '\n';
551 	buf[defs.meshie.val.mesh_id_len + 1] = '\0';
552 
553 	return defs.meshie.val.mesh_id_len + 1;
554 }
555 
556 /**
557  * mesh_id_store - Set function for sysfs attribute mesh_id
558  * @dev: the &struct device
559  * @attr: device attributes
560  * @buf: buffer that contains new attribute value
561  * @count: size of buffer
562  */
563 static ssize_t mesh_id_store(struct device *dev, struct device_attribute *attr,
564 			     const char *buf, size_t count)
565 {
566 	struct cmd_ds_mesh_config cmd;
567 	struct mrvl_mesh_defaults defs;
568 	struct mrvl_meshie *ie;
569 	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
570 	int len;
571 	int ret;
572 
573 	if (count < 2 || count > IEEE80211_MAX_SSID_LEN + 1)
574 		return -EINVAL;
575 
576 	memset(&cmd, 0, sizeof(struct cmd_ds_mesh_config));
577 	ie = (struct mrvl_meshie *) &cmd.data[0];
578 
579 	/* fetch all other Information Element parameters */
580 	ret = mesh_get_default_parameters(dev, &defs);
581 
582 	cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie));
583 
584 	/* transfer IE elements */
585 	memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie));
586 
587 	len = count - 1;
588 	memcpy(ie->val.mesh_id, buf, len);
589 	/* SSID len */
590 	ie->val.mesh_id_len = len;
591 	/* IE len */
592 	ie->len = sizeof(struct mrvl_meshie_val) - IEEE80211_MAX_SSID_LEN + len;
593 
594 	ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
595 				   CMD_TYPE_MESH_SET_MESH_IE);
596 	if (ret)
597 		return ret;
598 
599 	return strlen(buf);
600 }
601 
602 /**
603  * protocol_id_show - Get function for sysfs attribute protocol_id
604  * @dev: the &struct device
605  * @attr: device attributes
606  * @buf: buffer where data will be returned
607  */
608 static ssize_t protocol_id_show(struct device *dev,
609 				struct device_attribute *attr,
610 				char *buf)
611 {
612 	struct mrvl_mesh_defaults defs;
613 	int ret;
614 
615 	ret = mesh_get_default_parameters(dev, &defs);
616 
617 	if (ret)
618 		return ret;
619 
620 	return sysfs_emit(buf, "%d\n", defs.meshie.val.active_protocol_id);
621 }
622 
623 /**
624  * protocol_id_store - Set function for sysfs attribute protocol_id
625  * @dev: the &struct device
626  * @attr: device attributes
627  * @buf: buffer that contains new attribute value
628  * @count: size of buffer
629  */
630 static ssize_t protocol_id_store(struct device *dev,
631 				 struct device_attribute *attr,
632 				 const char *buf, size_t count)
633 {
634 	struct cmd_ds_mesh_config cmd;
635 	struct mrvl_mesh_defaults defs;
636 	struct mrvl_meshie *ie;
637 	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
638 	uint32_t datum;
639 	int ret;
640 
641 	ret = kstrtouint(buf, 10, &datum);
642 	if (ret)
643 		return ret;
644 	if (datum > 255)
645 		return -EINVAL;
646 
647 	memset(&cmd, 0, sizeof(cmd));
648 
649 	/* fetch all other Information Element parameters */
650 	ret = mesh_get_default_parameters(dev, &defs);
651 
652 	cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie));
653 
654 	/* transfer IE elements */
655 	ie = (struct mrvl_meshie *) &cmd.data[0];
656 	memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie));
657 	/* update protocol id */
658 	ie->val.active_protocol_id = datum;
659 
660 	ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
661 				   CMD_TYPE_MESH_SET_MESH_IE);
662 	if (ret)
663 		return ret;
664 
665 	return strlen(buf);
666 }
667 
668 /**
669  * metric_id_show - Get function for sysfs attribute metric_id
670  * @dev: the &struct device
671  * @attr: device attributes
672  * @buf: buffer where data will be returned
673  */
674 static ssize_t metric_id_show(struct device *dev,
675 			      struct device_attribute *attr, char *buf)
676 {
677 	struct mrvl_mesh_defaults defs;
678 	int ret;
679 
680 	ret = mesh_get_default_parameters(dev, &defs);
681 
682 	if (ret)
683 		return ret;
684 
685 	return sysfs_emit(buf, "%d\n", defs.meshie.val.active_metric_id);
686 }
687 
688 /**
689  * metric_id_store - Set function for sysfs attribute metric_id
690  * @dev: the &struct device
691  * @attr: device attributes
692  * @buf: buffer that contains new attribute value
693  * @count: size of buffer
694  */
695 static ssize_t metric_id_store(struct device *dev,
696 			       struct device_attribute *attr,
697 			       const char *buf, size_t count)
698 {
699 	struct cmd_ds_mesh_config cmd;
700 	struct mrvl_mesh_defaults defs;
701 	struct mrvl_meshie *ie;
702 	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
703 	uint32_t datum;
704 	int ret;
705 
706 	memset(&cmd, 0, sizeof(cmd));
707 	ret = sscanf(buf, "%d", &datum);
708 	if ((ret != 1) || (datum > 255))
709 		return -EINVAL;
710 
711 	/* fetch all other Information Element parameters */
712 	ret = mesh_get_default_parameters(dev, &defs);
713 
714 	cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie));
715 
716 	/* transfer IE elements */
717 	ie = (struct mrvl_meshie *) &cmd.data[0];
718 	memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie));
719 	/* update metric id */
720 	ie->val.active_metric_id = datum;
721 
722 	ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
723 				   CMD_TYPE_MESH_SET_MESH_IE);
724 	if (ret)
725 		return ret;
726 
727 	return strlen(buf);
728 }
729 
730 /**
731  * capability_show - Get function for sysfs attribute capability
732  * @dev: the &struct device
733  * @attr: device attributes
734  * @buf: buffer where data will be returned
735  */
736 static ssize_t capability_show(struct device *dev,
737 			       struct device_attribute *attr, char *buf)
738 {
739 	struct mrvl_mesh_defaults defs;
740 	int ret;
741 
742 	ret = mesh_get_default_parameters(dev, &defs);
743 
744 	if (ret)
745 		return ret;
746 
747 	return sysfs_emit(buf, "%d\n", defs.meshie.val.mesh_capability);
748 }
749 
750 /**
751  * capability_store - Set function for sysfs attribute capability
752  * @dev: the &struct device
753  * @attr: device attributes
754  * @buf: buffer that contains new attribute value
755  * @count: size of buffer
756  */
757 static ssize_t capability_store(struct device *dev,
758 				struct device_attribute *attr,
759 				const char *buf, size_t count)
760 {
761 	struct cmd_ds_mesh_config cmd;
762 	struct mrvl_mesh_defaults defs;
763 	struct mrvl_meshie *ie;
764 	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
765 	uint32_t datum;
766 	int ret;
767 
768 	memset(&cmd, 0, sizeof(cmd));
769 	ret = sscanf(buf, "%d", &datum);
770 	if ((ret != 1) || (datum > 255))
771 		return -EINVAL;
772 
773 	/* fetch all other Information Element parameters */
774 	ret = mesh_get_default_parameters(dev, &defs);
775 
776 	cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie));
777 
778 	/* transfer IE elements */
779 	ie = (struct mrvl_meshie *) &cmd.data[0];
780 	memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie));
781 	/* update value */
782 	ie->val.mesh_capability = datum;
783 
784 	ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
785 				   CMD_TYPE_MESH_SET_MESH_IE);
786 	if (ret)
787 		return ret;
788 
789 	return strlen(buf);
790 }
791 
792 
793 static DEVICE_ATTR_RW(bootflag);
794 static DEVICE_ATTR_RW(boottime);
795 static DEVICE_ATTR_RW(channel);
796 static DEVICE_ATTR_RW(mesh_id);
797 static DEVICE_ATTR_RW(protocol_id);
798 static DEVICE_ATTR_RW(metric_id);
799 static DEVICE_ATTR_RW(capability);
800 
801 static struct attribute *boot_opts_attrs[] = {
802 	&dev_attr_bootflag.attr,
803 	&dev_attr_boottime.attr,
804 	&dev_attr_channel.attr,
805 	NULL
806 };
807 
808 static const struct attribute_group boot_opts_group = {
809 	.name = "boot_options",
810 	.attrs = boot_opts_attrs,
811 };
812 
813 static struct attribute *mesh_ie_attrs[] = {
814 	&dev_attr_mesh_id.attr,
815 	&dev_attr_protocol_id.attr,
816 	&dev_attr_metric_id.attr,
817 	&dev_attr_capability.attr,
818 	NULL
819 };
820 
821 static const struct attribute_group mesh_ie_group = {
822 	.name = "mesh_ie",
823 	.attrs = mesh_ie_attrs,
824 };
825 
826 
827 /***************************************************************************
828  * Initializing and starting, stopping mesh
829  */
830 
831 /*
832  * Check mesh FW version and appropriately send the mesh start
833  * command
834  */
835 void lbs_init_mesh(struct lbs_private *priv)
836 {
837 	/* Determine mesh_fw_ver from fwrelease and fwcapinfo */
838 	/* 5.0.16p0 9.0.0.p0 is known to NOT support any mesh */
839 	/* 5.110.22 have mesh command with 0xa3 command id */
840 	/* 10.0.0.p0 FW brings in mesh config command with different id */
841 	/* Check FW version MSB and initialize mesh_fw_ver */
842 	if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5) {
843 		/* Enable mesh, if supported, and work out which TLV it uses.
844 		   0x100 + 291 is an unofficial value used in 5.110.20.pXX
845 		   0x100 + 37 is the official value used in 5.110.21.pXX
846 		   but we check them in that order because 20.pXX doesn't
847 		   give an error -- it just silently fails. */
848 
849 		/* 5.110.20.pXX firmware will fail the command if the channel
850 		   doesn't match the existing channel. But only if the TLV
851 		   is correct. If the channel is wrong, _BOTH_ versions will
852 		   give an error to 0x100+291, and allow 0x100+37 to succeed.
853 		   It's just that 5.110.20.pXX will not have done anything
854 		   useful */
855 
856 		priv->mesh_tlv = TLV_TYPE_OLD_MESH_ID;
857 		if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, 1)) {
858 			priv->mesh_tlv = TLV_TYPE_MESH_ID;
859 			if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, 1))
860 				priv->mesh_tlv = 0;
861 		}
862 	} else
863 	if ((MRVL_FW_MAJOR_REV(priv->fwrelease) >= MRVL_FW_V10) &&
864 		(priv->fwcapinfo & MESH_CAPINFO_ENABLE_MASK)) {
865 		/* 10.0.0.pXX new firmwares should succeed with TLV
866 		 * 0x100+37; Do not invoke command with old TLV.
867 		 */
868 		priv->mesh_tlv = TLV_TYPE_MESH_ID;
869 		if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, 1))
870 			priv->mesh_tlv = 0;
871 	}
872 
873 	/* Stop meshing until interface is brought up */
874 	lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_STOP, 1);
875 }
876 
877 void lbs_start_mesh(struct lbs_private *priv)
878 {
879 	lbs_add_mesh(priv);
880 
881 	if (device_create_file(&priv->dev->dev, &dev_attr_lbs_mesh))
882 		netdev_err(priv->dev, "cannot register lbs_mesh attribute\n");
883 }
884 
885 int lbs_deinit_mesh(struct lbs_private *priv)
886 {
887 	struct net_device *dev = priv->dev;
888 	int ret = 0;
889 
890 	if (priv->mesh_tlv) {
891 		device_remove_file(&dev->dev, &dev_attr_lbs_mesh);
892 		ret = 1;
893 	}
894 
895 	return ret;
896 }
897 
898 
899 /**
900  * lbs_mesh_stop - close the mshX interface
901  *
902  * @dev:	A pointer to &net_device structure
903  * returns:	0
904  */
905 static int lbs_mesh_stop(struct net_device *dev)
906 {
907 	struct lbs_private *priv = dev->ml_priv;
908 
909 	lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_STOP,
910 		lbs_mesh_get_channel(priv));
911 
912 	spin_lock_irq(&priv->driver_lock);
913 
914 	netif_stop_queue(dev);
915 	netif_carrier_off(dev);
916 
917 	spin_unlock_irq(&priv->driver_lock);
918 
919 	lbs_update_mcast(priv);
920 	if (!lbs_iface_active(priv))
921 		lbs_stop_iface(priv);
922 
923 	return 0;
924 }
925 
926 /**
927  * lbs_mesh_dev_open - open the mshX interface
928  *
929  * @dev:	A pointer to &net_device structure
930  * returns:	0 or -EBUSY if monitor mode active
931  */
932 static int lbs_mesh_dev_open(struct net_device *dev)
933 {
934 	struct lbs_private *priv = dev->ml_priv;
935 	int ret = 0;
936 
937 	if (!priv->iface_running) {
938 		ret = lbs_start_iface(priv);
939 		if (ret)
940 			goto out;
941 	}
942 
943 	spin_lock_irq(&priv->driver_lock);
944 
945 	if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) {
946 		ret = -EBUSY;
947 		spin_unlock_irq(&priv->driver_lock);
948 		goto out;
949 	}
950 
951 	netif_carrier_on(dev);
952 
953 	if (!priv->tx_pending_len)
954 		netif_wake_queue(dev);
955 
956 	spin_unlock_irq(&priv->driver_lock);
957 
958 	ret = lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
959 		lbs_mesh_get_channel(priv));
960 
961 out:
962 	return ret;
963 }
964 
965 static const struct net_device_ops mesh_netdev_ops = {
966 	.ndo_open		= lbs_mesh_dev_open,
967 	.ndo_stop 		= lbs_mesh_stop,
968 	.ndo_start_xmit		= lbs_hard_start_xmit,
969 	.ndo_set_mac_address	= lbs_set_mac_address,
970 	.ndo_set_rx_mode	= lbs_set_multicast_list,
971 };
972 
973 /**
974  * lbs_add_mesh - add mshX interface
975  *
976  * @priv:	A pointer to the &struct lbs_private structure
977  * returns:	0 if successful, -X otherwise
978  */
979 static int lbs_add_mesh(struct lbs_private *priv)
980 {
981 	struct net_device *mesh_dev = NULL;
982 	struct wireless_dev *mesh_wdev;
983 	int ret = 0;
984 
985 	/* Allocate a virtual mesh device */
986 	mesh_wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
987 	if (!mesh_wdev) {
988 		lbs_deb_mesh("init mshX wireless device failed\n");
989 		ret = -ENOMEM;
990 		goto done;
991 	}
992 
993 	mesh_dev = alloc_netdev(0, "msh%d", NET_NAME_UNKNOWN, ether_setup);
994 	if (!mesh_dev) {
995 		lbs_deb_mesh("init mshX device failed\n");
996 		ret = -ENOMEM;
997 		goto err_free_wdev;
998 	}
999 
1000 	mesh_wdev->iftype = NL80211_IFTYPE_MESH_POINT;
1001 	mesh_wdev->wiphy = priv->wdev->wiphy;
1002 
1003 	if (priv->mesh_tlv) {
1004 		sprintf(mesh_wdev->u.mesh.id, "mesh");
1005 		mesh_wdev->u.mesh.id_up_len = 4;
1006 	}
1007 
1008 	mesh_wdev->netdev = mesh_dev;
1009 
1010 	mesh_dev->ml_priv = priv;
1011 	mesh_dev->ieee80211_ptr = mesh_wdev;
1012 	priv->mesh_dev = mesh_dev;
1013 
1014 	mesh_dev->netdev_ops = &mesh_netdev_ops;
1015 	mesh_dev->ethtool_ops = &lbs_ethtool_ops;
1016 	eth_hw_addr_inherit(mesh_dev, priv->dev);
1017 
1018 	SET_NETDEV_DEV(priv->mesh_dev, priv->dev->dev.parent);
1019 
1020 	mesh_dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
1021 	mesh_dev->sysfs_groups[0] = &lbs_mesh_attr_group;
1022 	mesh_dev->sysfs_groups[1] = &boot_opts_group;
1023 	mesh_dev->sysfs_groups[2] = &mesh_ie_group;
1024 
1025 	/* Register virtual mesh interface */
1026 	ret = register_netdev(mesh_dev);
1027 	if (ret) {
1028 		pr_err("cannot register mshX virtual interface\n");
1029 		goto err_free_netdev;
1030 	}
1031 
1032 	/* Everything successful */
1033 	ret = 0;
1034 	goto done;
1035 
1036 err_free_netdev:
1037 	free_netdev(mesh_dev);
1038 
1039 err_free_wdev:
1040 	kfree(mesh_wdev);
1041 
1042 done:
1043 	return ret;
1044 }
1045 
1046 void lbs_remove_mesh(struct lbs_private *priv)
1047 {
1048 	struct net_device *mesh_dev;
1049 
1050 	mesh_dev = priv->mesh_dev;
1051 	if (!mesh_dev)
1052 		return;
1053 
1054 	netif_stop_queue(mesh_dev);
1055 	netif_carrier_off(mesh_dev);
1056 	unregister_netdev(mesh_dev);
1057 	priv->mesh_dev = NULL;
1058 	kfree(mesh_dev->ieee80211_ptr);
1059 	free_netdev(mesh_dev);
1060 }
1061 
1062 
1063 /***************************************************************************
1064  * Sending and receiving
1065  */
1066 struct net_device *lbs_mesh_set_dev(struct lbs_private *priv,
1067 	struct net_device *dev, struct rxpd *rxpd)
1068 {
1069 	if (priv->mesh_dev) {
1070 		if (priv->mesh_tlv == TLV_TYPE_OLD_MESH_ID) {
1071 			if (rxpd->rx_control & RxPD_MESH_FRAME)
1072 				dev = priv->mesh_dev;
1073 		} else if (priv->mesh_tlv == TLV_TYPE_MESH_ID) {
1074 			if (rxpd->u.bss.bss_num == MESH_IFACE_ID)
1075 				dev = priv->mesh_dev;
1076 		}
1077 	}
1078 	return dev;
1079 }
1080 
1081 
1082 void lbs_mesh_set_txpd(struct lbs_private *priv,
1083 	struct net_device *dev, struct txpd *txpd)
1084 {
1085 	if (dev == priv->mesh_dev) {
1086 		if (priv->mesh_tlv == TLV_TYPE_OLD_MESH_ID)
1087 			txpd->tx_control |= cpu_to_le32(TxPD_MESH_FRAME);
1088 		else if (priv->mesh_tlv == TLV_TYPE_MESH_ID)
1089 			txpd->u.bss.bss_num = MESH_IFACE_ID;
1090 	}
1091 }
1092 
1093 
1094 /***************************************************************************
1095  * Ethtool related
1096  */
1097 
1098 static const char mesh_stat_strings[MESH_STATS_NUM][ETH_GSTRING_LEN] = {
1099 	"drop_duplicate_bcast",
1100 	"drop_ttl_zero",
1101 	"drop_no_fwd_route",
1102 	"drop_no_buffers",
1103 	"fwded_unicast_cnt",
1104 	"fwded_bcast_cnt",
1105 	"drop_blind_table",
1106 	"tx_failed_cnt"
1107 };
1108 
1109 void lbs_mesh_ethtool_get_stats(struct net_device *dev,
1110 	struct ethtool_stats *stats, uint64_t *data)
1111 {
1112 	struct lbs_private *priv = dev->ml_priv;
1113 	struct cmd_ds_mesh_access mesh_access;
1114 	int ret;
1115 
1116 	/* Get Mesh Statistics */
1117 	ret = lbs_mesh_access(priv, CMD_ACT_MESH_GET_STATS, &mesh_access);
1118 
1119 	if (ret) {
1120 		memset(data, 0, MESH_STATS_NUM*(sizeof(uint64_t)));
1121 		return;
1122 	}
1123 
1124 	priv->mstats.fwd_drop_rbt = le32_to_cpu(mesh_access.data[0]);
1125 	priv->mstats.fwd_drop_ttl = le32_to_cpu(mesh_access.data[1]);
1126 	priv->mstats.fwd_drop_noroute = le32_to_cpu(mesh_access.data[2]);
1127 	priv->mstats.fwd_drop_nobuf = le32_to_cpu(mesh_access.data[3]);
1128 	priv->mstats.fwd_unicast_cnt = le32_to_cpu(mesh_access.data[4]);
1129 	priv->mstats.fwd_bcast_cnt = le32_to_cpu(mesh_access.data[5]);
1130 	priv->mstats.drop_blind = le32_to_cpu(mesh_access.data[6]);
1131 	priv->mstats.tx_failed_cnt = le32_to_cpu(mesh_access.data[7]);
1132 
1133 	data[0] = priv->mstats.fwd_drop_rbt;
1134 	data[1] = priv->mstats.fwd_drop_ttl;
1135 	data[2] = priv->mstats.fwd_drop_noroute;
1136 	data[3] = priv->mstats.fwd_drop_nobuf;
1137 	data[4] = priv->mstats.fwd_unicast_cnt;
1138 	data[5] = priv->mstats.fwd_bcast_cnt;
1139 	data[6] = priv->mstats.drop_blind;
1140 	data[7] = priv->mstats.tx_failed_cnt;
1141 }
1142 
1143 int lbs_mesh_ethtool_get_sset_count(struct net_device *dev, int sset)
1144 {
1145 	struct lbs_private *priv = dev->ml_priv;
1146 
1147 	if (sset == ETH_SS_STATS && dev == priv->mesh_dev)
1148 		return MESH_STATS_NUM;
1149 
1150 	return -EOPNOTSUPP;
1151 }
1152 
1153 void lbs_mesh_ethtool_get_strings(struct net_device *dev,
1154 	uint32_t stringset, uint8_t *s)
1155 {
1156 	switch (stringset) {
1157 	case ETH_SS_STATS:
1158 		memcpy(s, mesh_stat_strings, sizeof(mesh_stat_strings));
1159 		break;
1160 	}
1161 }
1162