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)->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, "0x%x\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)->priv;
61 struct cmd_ds_mesh_config cmd;
65 memset(&cmd, 0, sizeof(cmd));
66 ret = sscanf(buf, "%x", &datum);
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, "0x%x\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)->priv;
104 struct cmd_ds_mesh_config cmd;
108 memset(&cmd, 0, sizeof(cmd));
109 ret = sscanf(buf, "%x", &datum);
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 mesh_id
135 static ssize_t mesh_id_get(struct device *dev, struct device_attribute *attr,
138 struct mrvl_mesh_defaults defs;
142 ret = mesh_get_default_parameters(dev, &defs);
147 if (defs.meshie.val.mesh_id_len > IW_ESSID_MAX_SIZE) {
148 printk(KERN_ERR "Inconsistent mesh ID length");
149 defs.meshie.val.mesh_id_len = IW_ESSID_MAX_SIZE;
152 /* SSID not null terminated: reserve room for \0 + \n */
153 maxlen = defs.meshie.val.mesh_id_len + 2;
154 maxlen = (PAGE_SIZE > maxlen) ? maxlen : PAGE_SIZE;
156 defs.meshie.val.mesh_id[defs.meshie.val.mesh_id_len] = '\0';
158 return snprintf(buf, maxlen, "%s\n", defs.meshie.val.mesh_id);
162 * @brief Set function for sysfs attribute mesh_id
164 static ssize_t mesh_id_set(struct device *dev, struct device_attribute *attr,
165 const char *buf, size_t count)
167 struct cmd_ds_mesh_config cmd;
168 struct mrvl_mesh_defaults defs;
169 struct mrvl_meshie *ie;
170 struct lbs_private *priv = to_net_dev(dev)->priv;
174 if (count < 2 || count > IW_ESSID_MAX_SIZE + 1)
177 memset(&cmd, 0, sizeof(struct cmd_ds_mesh_config));
178 ie = (struct mrvl_meshie *) &cmd.data[0];
180 /* fetch all other Information Element parameters */
181 ret = mesh_get_default_parameters(dev, &defs);
183 cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie));
185 /* transfer IE elements */
186 memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie));
189 memcpy(ie->val.mesh_id, buf, len);
191 ie->val.mesh_id_len = len;
193 ie->hdr.len = sizeof(struct mrvl_meshie_val) - IW_ESSID_MAX_SIZE + len;
195 ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
196 CMD_TYPE_MESH_SET_MESH_IE);
204 * @brief Get function for sysfs attribute protocol_id
206 static ssize_t protocol_id_get(struct device *dev,
207 struct device_attribute *attr, char *buf)
209 struct mrvl_mesh_defaults defs;
212 ret = mesh_get_default_parameters(dev, &defs);
217 return snprintf(buf, 5, "%d\n", defs.meshie.val.active_protocol_id);
221 * @brief Set function for sysfs attribute protocol_id
223 static ssize_t protocol_id_set(struct device *dev,
224 struct device_attribute *attr, const char *buf, size_t count)
226 struct cmd_ds_mesh_config cmd;
227 struct mrvl_mesh_defaults defs;
228 struct mrvl_meshie *ie;
229 struct lbs_private *priv = to_net_dev(dev)->priv;
233 memset(&cmd, 0, sizeof(cmd));
234 ret = sscanf(buf, "%x", &datum);
238 /* fetch all other Information Element parameters */
239 ret = mesh_get_default_parameters(dev, &defs);
241 cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie));
243 /* transfer IE elements */
244 ie = (struct mrvl_meshie *) &cmd.data[0];
245 memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie));
246 /* update protocol id */
247 ie->val.active_protocol_id = datum;
249 ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
250 CMD_TYPE_MESH_SET_MESH_IE);
258 * @brief Get function for sysfs attribute metric_id
260 static ssize_t metric_id_get(struct device *dev,
261 struct device_attribute *attr, char *buf)
263 struct mrvl_mesh_defaults defs;
266 ret = mesh_get_default_parameters(dev, &defs);
271 return snprintf(buf, 5, "%d\n", defs.meshie.val.active_metric_id);
275 * @brief Set function for sysfs attribute metric_id
277 static ssize_t metric_id_set(struct device *dev, struct device_attribute *attr,
278 const char *buf, size_t count)
280 struct cmd_ds_mesh_config cmd;
281 struct mrvl_mesh_defaults defs;
282 struct mrvl_meshie *ie;
283 struct lbs_private *priv = to_net_dev(dev)->priv;
287 memset(&cmd, 0, sizeof(cmd));
288 ret = sscanf(buf, "%x", &datum);
292 /* fetch all other Information Element parameters */
293 ret = mesh_get_default_parameters(dev, &defs);
295 cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie));
297 /* transfer IE elements */
298 ie = (struct mrvl_meshie *) &cmd.data[0];
299 memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie));
300 /* update metric id */
301 ie->val.active_metric_id = datum;
303 ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
304 CMD_TYPE_MESH_SET_MESH_IE);
312 * @brief Get function for sysfs attribute capability
314 static ssize_t capability_get(struct device *dev,
315 struct device_attribute *attr, char *buf)
317 struct mrvl_mesh_defaults defs;
320 ret = mesh_get_default_parameters(dev, &defs);
325 return snprintf(buf, 5, "%d\n", defs.meshie.val.mesh_capability);
329 * @brief Set function for sysfs attribute capability
331 static ssize_t capability_set(struct device *dev, struct device_attribute *attr,
332 const char *buf, size_t count)
334 struct cmd_ds_mesh_config cmd;
335 struct mrvl_mesh_defaults defs;
336 struct mrvl_meshie *ie;
337 struct lbs_private *priv = to_net_dev(dev)->priv;
341 memset(&cmd, 0, sizeof(cmd));
342 ret = sscanf(buf, "%x", &datum);
346 /* fetch all other Information Element parameters */
347 ret = mesh_get_default_parameters(dev, &defs);
349 cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie));
351 /* transfer IE elements */
352 ie = (struct mrvl_meshie *) &cmd.data[0];
353 memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie));
355 ie->val.mesh_capability = datum;
357 ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
358 CMD_TYPE_MESH_SET_MESH_IE);
366 static DEVICE_ATTR(bootflag, 0644, bootflag_get, bootflag_set);
367 static DEVICE_ATTR(boottime, 0644, boottime_get, boottime_set);
368 static DEVICE_ATTR(mesh_id, 0644, mesh_id_get, mesh_id_set);
369 static DEVICE_ATTR(protocol_id, 0644, protocol_id_get, protocol_id_set);
370 static DEVICE_ATTR(metric_id, 0644, metric_id_get, metric_id_set);
371 static DEVICE_ATTR(capability, 0644, capability_get, capability_set);
373 static struct attribute *boot_opts_attrs[] = {
374 &dev_attr_bootflag.attr,
375 &dev_attr_boottime.attr,
379 static struct attribute_group boot_opts_group = {
380 .name = "boot_options",
381 .attrs = boot_opts_attrs,
384 static struct attribute *mesh_ie_attrs[] = {
385 &dev_attr_mesh_id.attr,
386 &dev_attr_protocol_id.attr,
387 &dev_attr_metric_id.attr,
388 &dev_attr_capability.attr,
392 static struct attribute_group mesh_ie_group = {
394 .attrs = mesh_ie_attrs,
397 void lbs_persist_config_init(struct net_device *dev)
400 ret = sysfs_create_group(&(dev->dev.kobj), &boot_opts_group);
401 ret = sysfs_create_group(&(dev->dev.kobj), &mesh_ie_group);
404 void lbs_persist_config_remove(struct net_device *dev)
406 sysfs_remove_group(&(dev->dev.kobj), &boot_opts_group);
407 sysfs_remove_group(&(dev->dev.kobj), &mesh_ie_group);