mesh.c 29 KB

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