sysfs.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  1. /*
  2. * WUSB Wire Adapter: WLP interface
  3. * Sysfs interfaces
  4. *
  5. * Copyright (C) 2005-2006 Intel Corporation
  6. * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License version
  10. * 2 as published by the Free Software Foundation.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  20. * 02110-1301, USA.
  21. *
  22. *
  23. * FIXME: docs
  24. */
  25. #include <linux/netdevice.h>
  26. #include <linux/etherdevice.h>
  27. #include <linux/device.h>
  28. #include "i1480u-wlp.h"
  29. /**
  30. *
  31. * @dev: Class device from the net_device; assumed refcnted.
  32. *
  33. * Yes, I don't lock--we assume it is refcounted and I am getting a
  34. * single byte value that is kind of atomic to read.
  35. */
  36. ssize_t uwb_phy_rate_show(const struct wlp_options *options, char *buf)
  37. {
  38. return sprintf(buf, "%u\n",
  39. wlp_tx_hdr_phy_rate(&options->def_tx_hdr));
  40. }
  41. EXPORT_SYMBOL_GPL(uwb_phy_rate_show);
  42. ssize_t uwb_phy_rate_store(struct wlp_options *options,
  43. const char *buf, size_t size)
  44. {
  45. ssize_t result;
  46. unsigned rate;
  47. result = sscanf(buf, "%u\n", &rate);
  48. if (result != 1) {
  49. result = -EINVAL;
  50. goto out;
  51. }
  52. result = -EINVAL;
  53. if (rate >= UWB_PHY_RATE_INVALID)
  54. goto out;
  55. wlp_tx_hdr_set_phy_rate(&options->def_tx_hdr, rate);
  56. result = 0;
  57. out:
  58. return result < 0 ? result : size;
  59. }
  60. EXPORT_SYMBOL_GPL(uwb_phy_rate_store);
  61. ssize_t uwb_rts_cts_show(const struct wlp_options *options, char *buf)
  62. {
  63. return sprintf(buf, "%u\n",
  64. wlp_tx_hdr_rts_cts(&options->def_tx_hdr));
  65. }
  66. EXPORT_SYMBOL_GPL(uwb_rts_cts_show);
  67. ssize_t uwb_rts_cts_store(struct wlp_options *options,
  68. const char *buf, size_t size)
  69. {
  70. ssize_t result;
  71. unsigned value;
  72. result = sscanf(buf, "%u\n", &value);
  73. if (result != 1) {
  74. result = -EINVAL;
  75. goto out;
  76. }
  77. result = -EINVAL;
  78. wlp_tx_hdr_set_rts_cts(&options->def_tx_hdr, !!value);
  79. result = 0;
  80. out:
  81. return result < 0 ? result : size;
  82. }
  83. EXPORT_SYMBOL_GPL(uwb_rts_cts_store);
  84. ssize_t uwb_ack_policy_show(const struct wlp_options *options, char *buf)
  85. {
  86. return sprintf(buf, "%u\n",
  87. wlp_tx_hdr_ack_policy(&options->def_tx_hdr));
  88. }
  89. EXPORT_SYMBOL_GPL(uwb_ack_policy_show);
  90. ssize_t uwb_ack_policy_store(struct wlp_options *options,
  91. const char *buf, size_t size)
  92. {
  93. ssize_t result;
  94. unsigned value;
  95. result = sscanf(buf, "%u\n", &value);
  96. if (result != 1 || value > UWB_ACK_B_REQ) {
  97. result = -EINVAL;
  98. goto out;
  99. }
  100. wlp_tx_hdr_set_ack_policy(&options->def_tx_hdr, value);
  101. result = 0;
  102. out:
  103. return result < 0 ? result : size;
  104. }
  105. EXPORT_SYMBOL_GPL(uwb_ack_policy_store);
  106. /**
  107. * Show the PCA base priority.
  108. *
  109. * We can access without locking, as the value is (for now) orthogonal
  110. * to other values.
  111. */
  112. ssize_t uwb_pca_base_priority_show(const struct wlp_options *options,
  113. char *buf)
  114. {
  115. return sprintf(buf, "%u\n",
  116. options->pca_base_priority);
  117. }
  118. EXPORT_SYMBOL_GPL(uwb_pca_base_priority_show);
  119. /**
  120. * Set the PCA base priority.
  121. *
  122. * We can access without locking, as the value is (for now) orthogonal
  123. * to other values.
  124. */
  125. ssize_t uwb_pca_base_priority_store(struct wlp_options *options,
  126. const char *buf, size_t size)
  127. {
  128. ssize_t result = -EINVAL;
  129. u8 pca_base_priority;
  130. result = sscanf(buf, "%hhu\n", &pca_base_priority);
  131. if (result != 1) {
  132. result = -EINVAL;
  133. goto out;
  134. }
  135. result = -EINVAL;
  136. if (pca_base_priority >= 8)
  137. goto out;
  138. options->pca_base_priority = pca_base_priority;
  139. /* Update TX header if we are currently using PCA. */
  140. if (result >= 0 && (wlp_tx_hdr_delivery_id_type(&options->def_tx_hdr) & WLP_DRP) == 0)
  141. wlp_tx_hdr_set_delivery_id_type(&options->def_tx_hdr, options->pca_base_priority);
  142. result = 0;
  143. out:
  144. return result < 0 ? result : size;
  145. }
  146. EXPORT_SYMBOL_GPL(uwb_pca_base_priority_store);
  147. /**
  148. * Show current inflight values
  149. *
  150. * Will print the current MAX and THRESHOLD values for the basic flow
  151. * control. In addition it will report how many times the TX queue needed
  152. * to be restarted since the last time this query was made.
  153. */
  154. static ssize_t wlp_tx_inflight_show(struct i1480u_tx_inflight *inflight,
  155. char *buf)
  156. {
  157. ssize_t result;
  158. unsigned long sec_elapsed = (jiffies - inflight->restart_ts)/HZ;
  159. unsigned long restart_count = atomic_read(&inflight->restart_count);
  160. result = scnprintf(buf, PAGE_SIZE, "%lu %lu %d %lu %lu %lu\n"
  161. "#read: threshold max inflight_count restarts "
  162. "seconds restarts/sec\n"
  163. "#write: threshold max\n",
  164. inflight->threshold, inflight->max,
  165. atomic_read(&inflight->count),
  166. restart_count, sec_elapsed,
  167. sec_elapsed == 0 ? 0 : restart_count/sec_elapsed);
  168. inflight->restart_ts = jiffies;
  169. atomic_set(&inflight->restart_count, 0);
  170. return result;
  171. }
  172. static
  173. ssize_t wlp_tx_inflight_store(struct i1480u_tx_inflight *inflight,
  174. const char *buf, size_t size)
  175. {
  176. unsigned long in_threshold, in_max;
  177. ssize_t result;
  178. result = sscanf(buf, "%lu %lu", &in_threshold, &in_max);
  179. if (result != 2)
  180. return -EINVAL;
  181. if (in_max <= in_threshold)
  182. return -EINVAL;
  183. inflight->max = in_max;
  184. inflight->threshold = in_threshold;
  185. return size;
  186. }
  187. /*
  188. * Glue (or function adaptors) for accesing info on sysfs
  189. *
  190. * [we need this indirection because the PCI driver does almost the
  191. * same]
  192. *
  193. * Linux 2.6.21 changed how 'struct netdevice' does attributes (from
  194. * having a 'struct class_dev' to having a 'struct device'). That is
  195. * quite of a pain.
  196. *
  197. * So we try to abstract that here. i1480u_SHOW() and i1480u_STORE()
  198. * create adaptors for extracting the 'struct i1480u' from a 'struct
  199. * dev' and calling a function for doing a sysfs operation (as we have
  200. * them factorized already). i1480u_ATTR creates the attribute file
  201. * (CLASS_DEVICE_ATTR or DEVICE_ATTR) and i1480u_ATTR_NAME produces a
  202. * class_device_attr_NAME or device_attr_NAME (for group registration).
  203. */
  204. #define i1480u_SHOW(name, fn, param) \
  205. static ssize_t i1480u_show_##name(struct device *dev, \
  206. struct device_attribute *attr,\
  207. char *buf) \
  208. { \
  209. struct i1480u *i1480u = netdev_priv(to_net_dev(dev)); \
  210. return fn(&i1480u->param, buf); \
  211. }
  212. #define i1480u_STORE(name, fn, param) \
  213. static ssize_t i1480u_store_##name(struct device *dev, \
  214. struct device_attribute *attr,\
  215. const char *buf, size_t size)\
  216. { \
  217. struct i1480u *i1480u = netdev_priv(to_net_dev(dev)); \
  218. return fn(&i1480u->param, buf, size); \
  219. }
  220. #define i1480u_ATTR(name, perm) static DEVICE_ATTR(name, perm, \
  221. i1480u_show_##name,\
  222. i1480u_store_##name)
  223. #define i1480u_ATTR_SHOW(name) static DEVICE_ATTR(name, \
  224. S_IRUGO, \
  225. i1480u_show_##name, NULL)
  226. #define i1480u_ATTR_NAME(a) (dev_attr_##a)
  227. /*
  228. * Sysfs adaptors
  229. */
  230. i1480u_SHOW(uwb_phy_rate, uwb_phy_rate_show, options);
  231. i1480u_STORE(uwb_phy_rate, uwb_phy_rate_store, options);
  232. i1480u_ATTR(uwb_phy_rate, S_IRUGO | S_IWUSR);
  233. i1480u_SHOW(uwb_rts_cts, uwb_rts_cts_show, options);
  234. i1480u_STORE(uwb_rts_cts, uwb_rts_cts_store, options);
  235. i1480u_ATTR(uwb_rts_cts, S_IRUGO | S_IWUSR);
  236. i1480u_SHOW(uwb_ack_policy, uwb_ack_policy_show, options);
  237. i1480u_STORE(uwb_ack_policy, uwb_ack_policy_store, options);
  238. i1480u_ATTR(uwb_ack_policy, S_IRUGO | S_IWUSR);
  239. i1480u_SHOW(uwb_pca_base_priority, uwb_pca_base_priority_show, options);
  240. i1480u_STORE(uwb_pca_base_priority, uwb_pca_base_priority_store, options);
  241. i1480u_ATTR(uwb_pca_base_priority, S_IRUGO | S_IWUSR);
  242. i1480u_SHOW(wlp_eda, wlp_eda_show, wlp);
  243. i1480u_STORE(wlp_eda, wlp_eda_store, wlp);
  244. i1480u_ATTR(wlp_eda, S_IRUGO | S_IWUSR);
  245. i1480u_SHOW(wlp_uuid, wlp_uuid_show, wlp);
  246. i1480u_STORE(wlp_uuid, wlp_uuid_store, wlp);
  247. i1480u_ATTR(wlp_uuid, S_IRUGO | S_IWUSR);
  248. i1480u_SHOW(wlp_dev_name, wlp_dev_name_show, wlp);
  249. i1480u_STORE(wlp_dev_name, wlp_dev_name_store, wlp);
  250. i1480u_ATTR(wlp_dev_name, S_IRUGO | S_IWUSR);
  251. i1480u_SHOW(wlp_dev_manufacturer, wlp_dev_manufacturer_show, wlp);
  252. i1480u_STORE(wlp_dev_manufacturer, wlp_dev_manufacturer_store, wlp);
  253. i1480u_ATTR(wlp_dev_manufacturer, S_IRUGO | S_IWUSR);
  254. i1480u_SHOW(wlp_dev_model_name, wlp_dev_model_name_show, wlp);
  255. i1480u_STORE(wlp_dev_model_name, wlp_dev_model_name_store, wlp);
  256. i1480u_ATTR(wlp_dev_model_name, S_IRUGO | S_IWUSR);
  257. i1480u_SHOW(wlp_dev_model_nr, wlp_dev_model_nr_show, wlp);
  258. i1480u_STORE(wlp_dev_model_nr, wlp_dev_model_nr_store, wlp);
  259. i1480u_ATTR(wlp_dev_model_nr, S_IRUGO | S_IWUSR);
  260. i1480u_SHOW(wlp_dev_serial, wlp_dev_serial_show, wlp);
  261. i1480u_STORE(wlp_dev_serial, wlp_dev_serial_store, wlp);
  262. i1480u_ATTR(wlp_dev_serial, S_IRUGO | S_IWUSR);
  263. i1480u_SHOW(wlp_dev_prim_category, wlp_dev_prim_category_show, wlp);
  264. i1480u_STORE(wlp_dev_prim_category, wlp_dev_prim_category_store, wlp);
  265. i1480u_ATTR(wlp_dev_prim_category, S_IRUGO | S_IWUSR);
  266. i1480u_SHOW(wlp_dev_prim_OUI, wlp_dev_prim_OUI_show, wlp);
  267. i1480u_STORE(wlp_dev_prim_OUI, wlp_dev_prim_OUI_store, wlp);
  268. i1480u_ATTR(wlp_dev_prim_OUI, S_IRUGO | S_IWUSR);
  269. i1480u_SHOW(wlp_dev_prim_OUI_sub, wlp_dev_prim_OUI_sub_show, wlp);
  270. i1480u_STORE(wlp_dev_prim_OUI_sub, wlp_dev_prim_OUI_sub_store, wlp);
  271. i1480u_ATTR(wlp_dev_prim_OUI_sub, S_IRUGO | S_IWUSR);
  272. i1480u_SHOW(wlp_dev_prim_subcat, wlp_dev_prim_subcat_show, wlp);
  273. i1480u_STORE(wlp_dev_prim_subcat, wlp_dev_prim_subcat_store, wlp);
  274. i1480u_ATTR(wlp_dev_prim_subcat, S_IRUGO | S_IWUSR);
  275. i1480u_SHOW(wlp_neighborhood, wlp_neighborhood_show, wlp);
  276. i1480u_ATTR_SHOW(wlp_neighborhood);
  277. i1480u_SHOW(wss_activate, wlp_wss_activate_show, wlp.wss);
  278. i1480u_STORE(wss_activate, wlp_wss_activate_store, wlp.wss);
  279. i1480u_ATTR(wss_activate, S_IRUGO | S_IWUSR);
  280. /*
  281. * Show the (min, max, avg) Line Quality Estimate (LQE, in dB) as over
  282. * the last 256 received WLP frames (ECMA-368 13.3).
  283. *
  284. * [the -7dB that have to be substracted from the LQI to make the LQE
  285. * are already taken into account].
  286. */
  287. i1480u_SHOW(wlp_lqe, stats_show, lqe_stats);
  288. i1480u_STORE(wlp_lqe, stats_store, lqe_stats);
  289. i1480u_ATTR(wlp_lqe, S_IRUGO | S_IWUSR);
  290. /*
  291. * Show the Receive Signal Strength Indicator averaged over all the
  292. * received WLP frames (ECMA-368 13.3). Still is not clear what
  293. * this value is, but is kind of a percentage of the signal strength
  294. * at the antenna.
  295. */
  296. i1480u_SHOW(wlp_rssi, stats_show, rssi_stats);
  297. i1480u_STORE(wlp_rssi, stats_store, rssi_stats);
  298. i1480u_ATTR(wlp_rssi, S_IRUGO | S_IWUSR);
  299. /**
  300. * We maintain a basic flow control counter. "count" how many TX URBs are
  301. * outstanding. Only allow "max"
  302. * TX URBs to be outstanding. If this value is reached the queue will be
  303. * stopped. The queue will be restarted when there are
  304. * "threshold" URBs outstanding.
  305. */
  306. i1480u_SHOW(wlp_tx_inflight, wlp_tx_inflight_show, tx_inflight);
  307. i1480u_STORE(wlp_tx_inflight, wlp_tx_inflight_store, tx_inflight);
  308. i1480u_ATTR(wlp_tx_inflight, S_IRUGO | S_IWUSR);
  309. static struct attribute *i1480u_attrs[] = {
  310. &i1480u_ATTR_NAME(uwb_phy_rate).attr,
  311. &i1480u_ATTR_NAME(uwb_rts_cts).attr,
  312. &i1480u_ATTR_NAME(uwb_ack_policy).attr,
  313. &i1480u_ATTR_NAME(uwb_pca_base_priority).attr,
  314. &i1480u_ATTR_NAME(wlp_lqe).attr,
  315. &i1480u_ATTR_NAME(wlp_rssi).attr,
  316. &i1480u_ATTR_NAME(wlp_eda).attr,
  317. &i1480u_ATTR_NAME(wlp_uuid).attr,
  318. &i1480u_ATTR_NAME(wlp_dev_name).attr,
  319. &i1480u_ATTR_NAME(wlp_dev_manufacturer).attr,
  320. &i1480u_ATTR_NAME(wlp_dev_model_name).attr,
  321. &i1480u_ATTR_NAME(wlp_dev_model_nr).attr,
  322. &i1480u_ATTR_NAME(wlp_dev_serial).attr,
  323. &i1480u_ATTR_NAME(wlp_dev_prim_category).attr,
  324. &i1480u_ATTR_NAME(wlp_dev_prim_OUI).attr,
  325. &i1480u_ATTR_NAME(wlp_dev_prim_OUI_sub).attr,
  326. &i1480u_ATTR_NAME(wlp_dev_prim_subcat).attr,
  327. &i1480u_ATTR_NAME(wlp_neighborhood).attr,
  328. &i1480u_ATTR_NAME(wss_activate).attr,
  329. &i1480u_ATTR_NAME(wlp_tx_inflight).attr,
  330. NULL,
  331. };
  332. static struct attribute_group i1480u_attr_group = {
  333. .name = NULL, /* we want them in the same directory */
  334. .attrs = i1480u_attrs,
  335. };
  336. int i1480u_sysfs_setup(struct i1480u *i1480u)
  337. {
  338. int result;
  339. struct device *dev = &i1480u->usb_iface->dev;
  340. result = sysfs_create_group(&i1480u->net_dev->dev.kobj,
  341. &i1480u_attr_group);
  342. if (result < 0)
  343. dev_err(dev, "cannot initialize sysfs attributes: %d\n",
  344. result);
  345. return result;
  346. }
  347. void i1480u_sysfs_release(struct i1480u *i1480u)
  348. {
  349. sysfs_remove_group(&i1480u->net_dev->dev.kobj,
  350. &i1480u_attr_group);
  351. }