1 #include <linux/moduleparam.h>
2 #include <linux/delay.h>
3 #include <linux/etherdevice.h>
4 #include <linux/netdevice.h>
5 #include <linux/if_arp.h>
6 #include <linux/kthread.h>
7 #include <linux/kfifo.h>
18 static int mesh_get_default_parameters(struct device
*dev
,
19 struct mrvl_mesh_defaults
*defs
)
21 struct lbs_private
*priv
= to_net_dev(dev
)->ml_priv
;
22 struct cmd_ds_mesh_config cmd
;
25 memset(&cmd
, 0, sizeof(struct cmd_ds_mesh_config
));
26 ret
= lbs_mesh_config_send(priv
, &cmd
, CMD_ACT_MESH_CONFIG_GET
,
27 CMD_TYPE_MESH_GET_DEFAULTS
);
32 memcpy(defs
, &cmd
.data
[0], sizeof(struct mrvl_mesh_defaults
));
38 * @brief Get function for sysfs attribute bootflag
40 static ssize_t
bootflag_get(struct device
*dev
,
41 struct device_attribute
*attr
, char *buf
)
43 struct mrvl_mesh_defaults defs
;
46 ret
= mesh_get_default_parameters(dev
, &defs
);
51 return snprintf(buf
, 12, "%d\n", le32_to_cpu(defs
.bootflag
));
55 * @brief Set function for sysfs attribute bootflag
57 static ssize_t
bootflag_set(struct device
*dev
, struct device_attribute
*attr
,
58 const char *buf
, size_t count
)
60 struct lbs_private
*priv
= to_net_dev(dev
)->ml_priv
;
61 struct cmd_ds_mesh_config cmd
;
65 memset(&cmd
, 0, sizeof(cmd
));
66 ret
= sscanf(buf
, "%d", &datum
);
67 if ((ret
!= 1) || (datum
> 1))
70 *((__le32
*)&cmd
.data
[0]) = cpu_to_le32(!!datum
);
71 cmd
.length
= cpu_to_le16(sizeof(uint32_t));
72 ret
= lbs_mesh_config_send(priv
, &cmd
, CMD_ACT_MESH_CONFIG_SET
,
73 CMD_TYPE_MESH_SET_BOOTFLAG
);
81 * @brief Get function for sysfs attribute boottime
83 static ssize_t
boottime_get(struct device
*dev
,
84 struct device_attribute
*attr
, char *buf
)
86 struct mrvl_mesh_defaults defs
;
89 ret
= mesh_get_default_parameters(dev
, &defs
);
94 return snprintf(buf
, 12, "%d\n", defs
.boottime
);
98 * @brief Set function for sysfs attribute boottime
100 static ssize_t
boottime_set(struct device
*dev
,
101 struct device_attribute
*attr
, const char *buf
, size_t count
)
103 struct lbs_private
*priv
= to_net_dev(dev
)->ml_priv
;
104 struct cmd_ds_mesh_config cmd
;
108 memset(&cmd
, 0, sizeof(cmd
));
109 ret
= sscanf(buf
, "%d", &datum
);
110 if ((ret
!= 1) || (datum
> 255))
113 /* A too small boot time will result in the device booting into
114 * standalone (no-host) mode before the host can take control of it,
115 * so the change will be hard to revert. This may be a desired
116 * feature (e.g to configure a very fast boot time for devices that
117 * will not be attached to a host), but dangerous. So I'm enforcing a
118 * lower limit of 20 seconds: remove and recompile the driver if this
119 * does not work for you.
121 datum
= (datum
< 20) ? 20 : datum
;
123 cmd
.length
= cpu_to_le16(sizeof(uint8_t));
124 ret
= lbs_mesh_config_send(priv
, &cmd
, CMD_ACT_MESH_CONFIG_SET
,
125 CMD_TYPE_MESH_SET_BOOTTIME
);
133 * @brief Get function for sysfs attribute channel
135 static ssize_t
channel_get(struct device
*dev
,
136 struct device_attribute
*attr
, char *buf
)
138 struct mrvl_mesh_defaults defs
;
141 ret
= mesh_get_default_parameters(dev
, &defs
);
146 return snprintf(buf
, 12, "%d\n", le16_to_cpu(defs
.channel
));
150 * @brief Set function for sysfs attribute channel
152 static ssize_t
channel_set(struct device
*dev
, struct device_attribute
*attr
,
153 const char *buf
, size_t count
)
155 struct lbs_private
*priv
= to_net_dev(dev
)->ml_priv
;
156 struct cmd_ds_mesh_config cmd
;
160 memset(&cmd
, 0, sizeof(cmd
));
161 ret
= sscanf(buf
, "%d", &datum
);
162 if (ret
!= 1 || datum
< 1 || datum
> 11)
165 *((__le16
*)&cmd
.data
[0]) = cpu_to_le16(datum
);
166 cmd
.length
= cpu_to_le16(sizeof(uint16_t));
167 ret
= lbs_mesh_config_send(priv
, &cmd
, CMD_ACT_MESH_CONFIG_SET
,
168 CMD_TYPE_MESH_SET_DEF_CHANNEL
);
176 * @brief Get function for sysfs attribute mesh_id
178 static ssize_t
mesh_id_get(struct device
*dev
, struct device_attribute
*attr
,
181 struct mrvl_mesh_defaults defs
;
185 ret
= mesh_get_default_parameters(dev
, &defs
);
190 if (defs
.meshie
.val
.mesh_id_len
> IW_ESSID_MAX_SIZE
) {
191 lbs_pr_err("inconsistent mesh ID length");
192 defs
.meshie
.val
.mesh_id_len
= IW_ESSID_MAX_SIZE
;
195 /* SSID not null terminated: reserve room for \0 + \n */
196 maxlen
= defs
.meshie
.val
.mesh_id_len
+ 2;
197 maxlen
= (PAGE_SIZE
> maxlen
) ? maxlen
: PAGE_SIZE
;
199 defs
.meshie
.val
.mesh_id
[defs
.meshie
.val
.mesh_id_len
] = '\0';
201 return snprintf(buf
, maxlen
, "%s\n", defs
.meshie
.val
.mesh_id
);
205 * @brief Set function for sysfs attribute mesh_id
207 static ssize_t
mesh_id_set(struct device
*dev
, struct device_attribute
*attr
,
208 const char *buf
, size_t count
)
210 struct cmd_ds_mesh_config cmd
;
211 struct mrvl_mesh_defaults defs
;
212 struct mrvl_meshie
*ie
;
213 struct lbs_private
*priv
= to_net_dev(dev
)->ml_priv
;
217 if (count
< 2 || count
> IW_ESSID_MAX_SIZE
+ 1)
220 memset(&cmd
, 0, sizeof(struct cmd_ds_mesh_config
));
221 ie
= (struct mrvl_meshie
*) &cmd
.data
[0];
223 /* fetch all other Information Element parameters */
224 ret
= mesh_get_default_parameters(dev
, &defs
);
226 cmd
.length
= cpu_to_le16(sizeof(struct mrvl_meshie
));
228 /* transfer IE elements */
229 memcpy(ie
, &defs
.meshie
, sizeof(struct mrvl_meshie
));
232 memcpy(ie
->val
.mesh_id
, buf
, len
);
234 ie
->val
.mesh_id_len
= len
;
236 ie
->len
= sizeof(struct mrvl_meshie_val
) - IW_ESSID_MAX_SIZE
+ len
;
238 ret
= lbs_mesh_config_send(priv
, &cmd
, CMD_ACT_MESH_CONFIG_SET
,
239 CMD_TYPE_MESH_SET_MESH_IE
);
247 * @brief Get function for sysfs attribute protocol_id
249 static ssize_t
protocol_id_get(struct device
*dev
,
250 struct device_attribute
*attr
, char *buf
)
252 struct mrvl_mesh_defaults defs
;
255 ret
= mesh_get_default_parameters(dev
, &defs
);
260 return snprintf(buf
, 5, "%d\n", defs
.meshie
.val
.active_protocol_id
);
264 * @brief Set function for sysfs attribute protocol_id
266 static ssize_t
protocol_id_set(struct device
*dev
,
267 struct device_attribute
*attr
, const char *buf
, size_t count
)
269 struct cmd_ds_mesh_config cmd
;
270 struct mrvl_mesh_defaults defs
;
271 struct mrvl_meshie
*ie
;
272 struct lbs_private
*priv
= to_net_dev(dev
)->ml_priv
;
276 memset(&cmd
, 0, sizeof(cmd
));
277 ret
= sscanf(buf
, "%d", &datum
);
278 if ((ret
!= 1) || (datum
> 255))
281 /* fetch all other Information Element parameters */
282 ret
= mesh_get_default_parameters(dev
, &defs
);
284 cmd
.length
= cpu_to_le16(sizeof(struct mrvl_meshie
));
286 /* transfer IE elements */
287 ie
= (struct mrvl_meshie
*) &cmd
.data
[0];
288 memcpy(ie
, &defs
.meshie
, sizeof(struct mrvl_meshie
));
289 /* update protocol id */
290 ie
->val
.active_protocol_id
= datum
;
292 ret
= lbs_mesh_config_send(priv
, &cmd
, CMD_ACT_MESH_CONFIG_SET
,
293 CMD_TYPE_MESH_SET_MESH_IE
);
301 * @brief Get function for sysfs attribute metric_id
303 static ssize_t
metric_id_get(struct device
*dev
,
304 struct device_attribute
*attr
, char *buf
)
306 struct mrvl_mesh_defaults defs
;
309 ret
= mesh_get_default_parameters(dev
, &defs
);
314 return snprintf(buf
, 5, "%d\n", defs
.meshie
.val
.active_metric_id
);
318 * @brief Set function for sysfs attribute metric_id
320 static ssize_t
metric_id_set(struct device
*dev
, struct device_attribute
*attr
,
321 const char *buf
, size_t count
)
323 struct cmd_ds_mesh_config cmd
;
324 struct mrvl_mesh_defaults defs
;
325 struct mrvl_meshie
*ie
;
326 struct lbs_private
*priv
= to_net_dev(dev
)->ml_priv
;
330 memset(&cmd
, 0, sizeof(cmd
));
331 ret
= sscanf(buf
, "%d", &datum
);
332 if ((ret
!= 1) || (datum
> 255))
335 /* fetch all other Information Element parameters */
336 ret
= mesh_get_default_parameters(dev
, &defs
);
338 cmd
.length
= cpu_to_le16(sizeof(struct mrvl_meshie
));
340 /* transfer IE elements */
341 ie
= (struct mrvl_meshie
*) &cmd
.data
[0];
342 memcpy(ie
, &defs
.meshie
, sizeof(struct mrvl_meshie
));
343 /* update metric id */
344 ie
->val
.active_metric_id
= datum
;
346 ret
= lbs_mesh_config_send(priv
, &cmd
, CMD_ACT_MESH_CONFIG_SET
,
347 CMD_TYPE_MESH_SET_MESH_IE
);
355 * @brief Get function for sysfs attribute capability
357 static ssize_t
capability_get(struct device
*dev
,
358 struct device_attribute
*attr
, char *buf
)
360 struct mrvl_mesh_defaults defs
;
363 ret
= mesh_get_default_parameters(dev
, &defs
);
368 return snprintf(buf
, 5, "%d\n", defs
.meshie
.val
.mesh_capability
);
372 * @brief Set function for sysfs attribute capability
374 static ssize_t
capability_set(struct device
*dev
, struct device_attribute
*attr
,
375 const char *buf
, size_t count
)
377 struct cmd_ds_mesh_config cmd
;
378 struct mrvl_mesh_defaults defs
;
379 struct mrvl_meshie
*ie
;
380 struct lbs_private
*priv
= to_net_dev(dev
)->ml_priv
;
384 memset(&cmd
, 0, sizeof(cmd
));
385 ret
= sscanf(buf
, "%d", &datum
);
386 if ((ret
!= 1) || (datum
> 255))
389 /* fetch all other Information Element parameters */
390 ret
= mesh_get_default_parameters(dev
, &defs
);
392 cmd
.length
= cpu_to_le16(sizeof(struct mrvl_meshie
));
394 /* transfer IE elements */
395 ie
= (struct mrvl_meshie
*) &cmd
.data
[0];
396 memcpy(ie
, &defs
.meshie
, sizeof(struct mrvl_meshie
));
398 ie
->val
.mesh_capability
= datum
;
400 ret
= lbs_mesh_config_send(priv
, &cmd
, CMD_ACT_MESH_CONFIG_SET
,
401 CMD_TYPE_MESH_SET_MESH_IE
);
409 static DEVICE_ATTR(bootflag
, 0644, bootflag_get
, bootflag_set
);
410 static DEVICE_ATTR(boottime
, 0644, boottime_get
, boottime_set
);
411 static DEVICE_ATTR(channel
, 0644, channel_get
, channel_set
);
412 static DEVICE_ATTR(mesh_id
, 0644, mesh_id_get
, mesh_id_set
);
413 static DEVICE_ATTR(protocol_id
, 0644, protocol_id_get
, protocol_id_set
);
414 static DEVICE_ATTR(metric_id
, 0644, metric_id_get
, metric_id_set
);
415 static DEVICE_ATTR(capability
, 0644, capability_get
, capability_set
);
417 static struct attribute
*boot_opts_attrs
[] = {
418 &dev_attr_bootflag
.attr
,
419 &dev_attr_boottime
.attr
,
420 &dev_attr_channel
.attr
,
424 static struct attribute_group boot_opts_group
= {
425 .name
= "boot_options",
426 .attrs
= boot_opts_attrs
,
429 static struct attribute
*mesh_ie_attrs
[] = {
430 &dev_attr_mesh_id
.attr
,
431 &dev_attr_protocol_id
.attr
,
432 &dev_attr_metric_id
.attr
,
433 &dev_attr_capability
.attr
,
437 static struct attribute_group mesh_ie_group
= {
439 .attrs
= mesh_ie_attrs
,
442 void lbs_persist_config_init(struct net_device
*dev
)
445 ret
= sysfs_create_group(&(dev
->dev
.kobj
), &boot_opts_group
);
446 ret
= sysfs_create_group(&(dev
->dev
.kobj
), &mesh_ie_group
);
449 void lbs_persist_config_remove(struct net_device
*dev
)
451 sysfs_remove_group(&(dev
->dev
.kobj
), &boot_opts_group
);
452 sysfs_remove_group(&(dev
->dev
.kobj
), &mesh_ie_group
);