persistcfg.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  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>
  8. #include "host.h"
  9. #include "decl.h"
  10. #include "dev.h"
  11. #include "wext.h"
  12. #include "debugfs.h"
  13. #include "scan.h"
  14. #include "assoc.h"
  15. #include "cmd.h"
  16. static int mesh_get_default_parameters(struct device *dev,
  17. struct mrvl_mesh_defaults *defs)
  18. {
  19. struct lbs_private *priv = to_net_dev(dev)->ml_priv;
  20. struct cmd_ds_mesh_config cmd;
  21. int ret;
  22. memset(&cmd, 0, sizeof(struct cmd_ds_mesh_config));
  23. ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_GET,
  24. CMD_TYPE_MESH_GET_DEFAULTS);
  25. if (ret)
  26. return -EOPNOTSUPP;
  27. memcpy(defs, &cmd.data[0], sizeof(struct mrvl_mesh_defaults));
  28. return 0;
  29. }
  30. /**
  31. * @brief Get function for sysfs attribute bootflag
  32. */
  33. static ssize_t bootflag_get(struct device *dev,
  34. struct device_attribute *attr, char *buf)
  35. {
  36. struct mrvl_mesh_defaults defs;
  37. int ret;
  38. ret = mesh_get_default_parameters(dev, &defs);
  39. if (ret)
  40. return ret;
  41. return snprintf(buf, 12, "%d\n", le32_to_cpu(defs.bootflag));
  42. }
  43. /**
  44. * @brief Set function for sysfs attribute bootflag
  45. */
  46. static ssize_t bootflag_set(struct device *dev, struct device_attribute *attr,
  47. const char *buf, size_t count)
  48. {
  49. struct lbs_private *priv = to_net_dev(dev)->ml_priv;
  50. struct cmd_ds_mesh_config cmd;
  51. uint32_t datum;
  52. int ret;
  53. memset(&cmd, 0, sizeof(cmd));
  54. ret = sscanf(buf, "%d", &datum);
  55. if ((ret != 1) || (datum > 1))
  56. return -EINVAL;
  57. *((__le32 *)&cmd.data[0]) = cpu_to_le32(!!datum);
  58. cmd.length = cpu_to_le16(sizeof(uint32_t));
  59. ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
  60. CMD_TYPE_MESH_SET_BOOTFLAG);
  61. if (ret)
  62. return ret;
  63. return strlen(buf);
  64. }
  65. /**
  66. * @brief Get function for sysfs attribute boottime
  67. */
  68. static ssize_t boottime_get(struct device *dev,
  69. struct device_attribute *attr, char *buf)
  70. {
  71. struct mrvl_mesh_defaults defs;
  72. int ret;
  73. ret = mesh_get_default_parameters(dev, &defs);
  74. if (ret)
  75. return ret;
  76. return snprintf(buf, 12, "%d\n", defs.boottime);
  77. }
  78. /**
  79. * @brief Set function for sysfs attribute boottime
  80. */
  81. static ssize_t boottime_set(struct device *dev,
  82. struct device_attribute *attr, const char *buf, size_t count)
  83. {
  84. struct lbs_private *priv = to_net_dev(dev)->ml_priv;
  85. struct cmd_ds_mesh_config cmd;
  86. uint32_t datum;
  87. int ret;
  88. memset(&cmd, 0, sizeof(cmd));
  89. ret = sscanf(buf, "%d", &datum);
  90. if ((ret != 1) || (datum > 255))
  91. return -EINVAL;
  92. /* A too small boot time will result in the device booting into
  93. * standalone (no-host) mode before the host can take control of it,
  94. * so the change will be hard to revert. This may be a desired
  95. * feature (e.g to configure a very fast boot time for devices that
  96. * will not be attached to a host), but dangerous. So I'm enforcing a
  97. * lower limit of 20 seconds: remove and recompile the driver if this
  98. * does not work for you.
  99. */
  100. datum = (datum < 20) ? 20 : datum;
  101. cmd.data[0] = datum;
  102. cmd.length = cpu_to_le16(sizeof(uint8_t));
  103. ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
  104. CMD_TYPE_MESH_SET_BOOTTIME);
  105. if (ret)
  106. return ret;
  107. return strlen(buf);
  108. }
  109. /**
  110. * @brief Get function for sysfs attribute channel
  111. */
  112. static ssize_t channel_get(struct device *dev,
  113. struct device_attribute *attr, char *buf)
  114. {
  115. struct mrvl_mesh_defaults defs;
  116. int ret;
  117. ret = mesh_get_default_parameters(dev, &defs);
  118. if (ret)
  119. return ret;
  120. return snprintf(buf, 12, "%d\n", le16_to_cpu(defs.channel));
  121. }
  122. /**
  123. * @brief Set function for sysfs attribute channel
  124. */
  125. static ssize_t channel_set(struct device *dev, struct device_attribute *attr,
  126. const char *buf, size_t count)
  127. {
  128. struct lbs_private *priv = to_net_dev(dev)->ml_priv;
  129. struct cmd_ds_mesh_config cmd;
  130. uint32_t datum;
  131. int ret;
  132. memset(&cmd, 0, sizeof(cmd));
  133. ret = sscanf(buf, "%d", &datum);
  134. if (ret != 1 || datum < 1 || datum > 11)
  135. return -EINVAL;
  136. *((__le16 *)&cmd.data[0]) = cpu_to_le16(datum);
  137. cmd.length = cpu_to_le16(sizeof(uint16_t));
  138. ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
  139. CMD_TYPE_MESH_SET_DEF_CHANNEL);
  140. if (ret)
  141. return ret;
  142. return strlen(buf);
  143. }
  144. /**
  145. * @brief Get function for sysfs attribute mesh_id
  146. */
  147. static ssize_t mesh_id_get(struct device *dev, struct device_attribute *attr,
  148. char *buf)
  149. {
  150. struct mrvl_mesh_defaults defs;
  151. int maxlen;
  152. int ret;
  153. ret = mesh_get_default_parameters(dev, &defs);
  154. if (ret)
  155. return ret;
  156. if (defs.meshie.val.mesh_id_len > IW_ESSID_MAX_SIZE) {
  157. lbs_pr_err("inconsistent mesh ID length");
  158. defs.meshie.val.mesh_id_len = IW_ESSID_MAX_SIZE;
  159. }
  160. /* SSID not null terminated: reserve room for \0 + \n */
  161. maxlen = defs.meshie.val.mesh_id_len + 2;
  162. maxlen = (PAGE_SIZE > maxlen) ? maxlen : PAGE_SIZE;
  163. defs.meshie.val.mesh_id[defs.meshie.val.mesh_id_len] = '\0';
  164. return snprintf(buf, maxlen, "%s\n", defs.meshie.val.mesh_id);
  165. }
  166. /**
  167. * @brief Set function for sysfs attribute mesh_id
  168. */
  169. static ssize_t mesh_id_set(struct device *dev, struct device_attribute *attr,
  170. const char *buf, size_t count)
  171. {
  172. struct cmd_ds_mesh_config cmd;
  173. struct mrvl_mesh_defaults defs;
  174. struct mrvl_meshie *ie;
  175. struct lbs_private *priv = to_net_dev(dev)->ml_priv;
  176. int len;
  177. int ret;
  178. if (count < 2 || count > IW_ESSID_MAX_SIZE + 1)
  179. return -EINVAL;
  180. memset(&cmd, 0, sizeof(struct cmd_ds_mesh_config));
  181. ie = (struct mrvl_meshie *) &cmd.data[0];
  182. /* fetch all other Information Element parameters */
  183. ret = mesh_get_default_parameters(dev, &defs);
  184. cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie));
  185. /* transfer IE elements */
  186. memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie));
  187. len = count - 1;
  188. memcpy(ie->val.mesh_id, buf, len);
  189. /* SSID len */
  190. ie->val.mesh_id_len = len;
  191. /* IE len */
  192. ie->len = sizeof(struct mrvl_meshie_val) - IW_ESSID_MAX_SIZE + len;
  193. ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
  194. CMD_TYPE_MESH_SET_MESH_IE);
  195. if (ret)
  196. return ret;
  197. return strlen(buf);
  198. }
  199. /**
  200. * @brief Get function for sysfs attribute protocol_id
  201. */
  202. static ssize_t protocol_id_get(struct device *dev,
  203. struct device_attribute *attr, char *buf)
  204. {
  205. struct mrvl_mesh_defaults defs;
  206. int ret;
  207. ret = mesh_get_default_parameters(dev, &defs);
  208. if (ret)
  209. return ret;
  210. return snprintf(buf, 5, "%d\n", defs.meshie.val.active_protocol_id);
  211. }
  212. /**
  213. * @brief Set function for sysfs attribute protocol_id
  214. */
  215. static ssize_t protocol_id_set(struct device *dev,
  216. struct device_attribute *attr, const char *buf, size_t count)
  217. {
  218. struct cmd_ds_mesh_config cmd;
  219. struct mrvl_mesh_defaults defs;
  220. struct mrvl_meshie *ie;
  221. struct lbs_private *priv = to_net_dev(dev)->ml_priv;
  222. uint32_t datum;
  223. int ret;
  224. memset(&cmd, 0, sizeof(cmd));
  225. ret = sscanf(buf, "%d", &datum);
  226. if ((ret != 1) || (datum > 255))
  227. return -EINVAL;
  228. /* fetch all other Information Element parameters */
  229. ret = mesh_get_default_parameters(dev, &defs);
  230. cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie));
  231. /* transfer IE elements */
  232. ie = (struct mrvl_meshie *) &cmd.data[0];
  233. memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie));
  234. /* update protocol id */
  235. ie->val.active_protocol_id = datum;
  236. ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
  237. CMD_TYPE_MESH_SET_MESH_IE);
  238. if (ret)
  239. return ret;
  240. return strlen(buf);
  241. }
  242. /**
  243. * @brief Get function for sysfs attribute metric_id
  244. */
  245. static ssize_t metric_id_get(struct device *dev,
  246. struct device_attribute *attr, char *buf)
  247. {
  248. struct mrvl_mesh_defaults defs;
  249. int ret;
  250. ret = mesh_get_default_parameters(dev, &defs);
  251. if (ret)
  252. return ret;
  253. return snprintf(buf, 5, "%d\n", defs.meshie.val.active_metric_id);
  254. }
  255. /**
  256. * @brief Set function for sysfs attribute metric_id
  257. */
  258. static ssize_t metric_id_set(struct device *dev, struct device_attribute *attr,
  259. const char *buf, size_t count)
  260. {
  261. struct cmd_ds_mesh_config cmd;
  262. struct mrvl_mesh_defaults defs;
  263. struct mrvl_meshie *ie;
  264. struct lbs_private *priv = to_net_dev(dev)->ml_priv;
  265. uint32_t datum;
  266. int ret;
  267. memset(&cmd, 0, sizeof(cmd));
  268. ret = sscanf(buf, "%d", &datum);
  269. if ((ret != 1) || (datum > 255))
  270. return -EINVAL;
  271. /* fetch all other Information Element parameters */
  272. ret = mesh_get_default_parameters(dev, &defs);
  273. cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie));
  274. /* transfer IE elements */
  275. ie = (struct mrvl_meshie *) &cmd.data[0];
  276. memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie));
  277. /* update metric id */
  278. ie->val.active_metric_id = datum;
  279. ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
  280. CMD_TYPE_MESH_SET_MESH_IE);
  281. if (ret)
  282. return ret;
  283. return strlen(buf);
  284. }
  285. /**
  286. * @brief Get function for sysfs attribute capability
  287. */
  288. static ssize_t capability_get(struct device *dev,
  289. struct device_attribute *attr, char *buf)
  290. {
  291. struct mrvl_mesh_defaults defs;
  292. int ret;
  293. ret = mesh_get_default_parameters(dev, &defs);
  294. if (ret)
  295. return ret;
  296. return snprintf(buf, 5, "%d\n", defs.meshie.val.mesh_capability);
  297. }
  298. /**
  299. * @brief Set function for sysfs attribute capability
  300. */
  301. static ssize_t capability_set(struct device *dev, struct device_attribute *attr,
  302. const char *buf, size_t count)
  303. {
  304. struct cmd_ds_mesh_config cmd;
  305. struct mrvl_mesh_defaults defs;
  306. struct mrvl_meshie *ie;
  307. struct lbs_private *priv = to_net_dev(dev)->ml_priv;
  308. uint32_t datum;
  309. int ret;
  310. memset(&cmd, 0, sizeof(cmd));
  311. ret = sscanf(buf, "%d", &datum);
  312. if ((ret != 1) || (datum > 255))
  313. return -EINVAL;
  314. /* fetch all other Information Element parameters */
  315. ret = mesh_get_default_parameters(dev, &defs);
  316. cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie));
  317. /* transfer IE elements */
  318. ie = (struct mrvl_meshie *) &cmd.data[0];
  319. memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie));
  320. /* update value */
  321. ie->val.mesh_capability = datum;
  322. ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
  323. CMD_TYPE_MESH_SET_MESH_IE);
  324. if (ret)
  325. return ret;
  326. return strlen(buf);
  327. }
  328. static DEVICE_ATTR(bootflag, 0644, bootflag_get, bootflag_set);
  329. static DEVICE_ATTR(boottime, 0644, boottime_get, boottime_set);
  330. static DEVICE_ATTR(channel, 0644, channel_get, channel_set);
  331. static DEVICE_ATTR(mesh_id, 0644, mesh_id_get, mesh_id_set);
  332. static DEVICE_ATTR(protocol_id, 0644, protocol_id_get, protocol_id_set);
  333. static DEVICE_ATTR(metric_id, 0644, metric_id_get, metric_id_set);
  334. static DEVICE_ATTR(capability, 0644, capability_get, capability_set);
  335. static struct attribute *boot_opts_attrs[] = {
  336. &dev_attr_bootflag.attr,
  337. &dev_attr_boottime.attr,
  338. &dev_attr_channel.attr,
  339. NULL
  340. };
  341. static struct attribute_group boot_opts_group = {
  342. .name = "boot_options",
  343. .attrs = boot_opts_attrs,
  344. };
  345. static struct attribute *mesh_ie_attrs[] = {
  346. &dev_attr_mesh_id.attr,
  347. &dev_attr_protocol_id.attr,
  348. &dev_attr_metric_id.attr,
  349. &dev_attr_capability.attr,
  350. NULL
  351. };
  352. static struct attribute_group mesh_ie_group = {
  353. .name = "mesh_ie",
  354. .attrs = mesh_ie_attrs,
  355. };
  356. void lbs_persist_config_init(struct net_device *dev)
  357. {
  358. int ret;
  359. ret = sysfs_create_group(&(dev->dev.kobj), &boot_opts_group);
  360. ret = sysfs_create_group(&(dev->dev.kobj), &mesh_ie_group);
  361. }
  362. void lbs_persist_config_remove(struct net_device *dev)
  363. {
  364. sysfs_remove_group(&(dev->dev.kobj), &boot_opts_group);
  365. sysfs_remove_group(&(dev->dev.kobj), &mesh_ie_group);
  366. }