xref: /openbmc/linux/drivers/net/wireless/marvell/libertas/mesh.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
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  
lbs_mesh_access(struct lbs_private * priv,uint16_t cmd_action,struct cmd_ds_mesh_access * cmd)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  
__lbs_mesh_config_send(struct lbs_private * priv,struct cmd_ds_mesh_config * cmd,uint16_t action,uint16_t type)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  
lbs_mesh_config_send(struct lbs_private * priv,struct cmd_ds_mesh_config * cmd,uint16_t action,uint16_t type)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   */
lbs_mesh_config(struct lbs_private * priv,uint16_t action,uint16_t chan)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  
lbs_mesh_set_channel(struct lbs_private * priv,u8 channel)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  
lbs_mesh_get_channel(struct lbs_private * priv)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   */
anycast_mask_show(struct device * dev,struct device_attribute * attr,char * buf)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   */
anycast_mask_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)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   */
prb_rsp_limit_show(struct device * dev,struct device_attribute * attr,char * buf)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   */
prb_rsp_limit_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)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   */
lbs_mesh_show(struct device * dev,struct device_attribute * attr,char * buf)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   */
lbs_mesh_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)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  
mesh_get_default_parameters(struct device * dev,struct mrvl_mesh_defaults * defs)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   */
bootflag_show(struct device * dev,struct device_attribute * attr,char * buf)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   */
bootflag_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)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   */
boottime_show(struct device * dev,struct device_attribute * attr,char * buf)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   */
boottime_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)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   */
channel_show(struct device * dev,struct device_attribute * attr,char * buf)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   */
channel_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)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   */
mesh_id_show(struct device * dev,struct device_attribute * attr,char * buf)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   */
mesh_id_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)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   */
protocol_id_show(struct device * dev,struct device_attribute * attr,char * buf)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   */
protocol_id_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)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   */
metric_id_show(struct device * dev,struct device_attribute * attr,char * buf)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   */
metric_id_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)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   */
capability_show(struct device * dev,struct device_attribute * attr,char * buf)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   */
capability_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)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   */
lbs_init_mesh(struct lbs_private * priv)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  
lbs_start_mesh(struct lbs_private * priv)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  
lbs_deinit_mesh(struct lbs_private * priv)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   */
lbs_mesh_stop(struct net_device * dev)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   */
lbs_mesh_dev_open(struct net_device * dev)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   */
lbs_add_mesh(struct lbs_private * priv)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  
lbs_remove_mesh(struct lbs_private * priv)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   */
lbs_mesh_set_dev(struct lbs_private * priv,struct net_device * dev,struct rxpd * rxpd)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  
lbs_mesh_set_txpd(struct lbs_private * priv,struct net_device * dev,struct txpd * txpd)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  
lbs_mesh_ethtool_get_stats(struct net_device * dev,struct ethtool_stats * stats,uint64_t * data)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  
lbs_mesh_ethtool_get_sset_count(struct net_device * dev,int sset)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  
lbs_mesh_ethtool_get_strings(struct net_device * dev,uint32_t stringset,uint8_t * s)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