debugfs.c 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927
  1. #include <linux/module.h>
  2. #include <linux/dcache.h>
  3. #include <linux/debugfs.h>
  4. #include <linux/delay.h>
  5. #include <linux/mm.h>
  6. #include <net/iw_handler.h>
  7. #include "dev.h"
  8. #include "decl.h"
  9. #include "host.h"
  10. #include "debugfs.h"
  11. static struct dentry *libertas_dir = NULL;
  12. static char *szStates[] = {
  13. "Connected",
  14. "Disconnected"
  15. };
  16. #ifdef PROC_DEBUG
  17. static void libertas_debug_init(wlan_private * priv, struct net_device *dev);
  18. #endif
  19. static int open_file_generic(struct inode *inode, struct file *file)
  20. {
  21. file->private_data = inode->i_private;
  22. return 0;
  23. }
  24. static ssize_t write_file_dummy(struct file *file, const char __user *buf,
  25. size_t count, loff_t *ppos)
  26. {
  27. return -EINVAL;
  28. }
  29. static const size_t len = PAGE_SIZE;
  30. static ssize_t libertas_dev_info(struct file *file, char __user *userbuf,
  31. size_t count, loff_t *ppos)
  32. {
  33. wlan_private *priv = file->private_data;
  34. size_t pos = 0;
  35. unsigned long addr = get_zeroed_page(GFP_KERNEL);
  36. char *buf = (char *)addr;
  37. ssize_t res;
  38. pos += snprintf(buf+pos, len-pos, "state = %s\n",
  39. szStates[priv->adapter->connect_status]);
  40. pos += snprintf(buf+pos, len-pos, "region_code = %02x\n",
  41. (u32) priv->adapter->regioncode);
  42. res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
  43. free_page(addr);
  44. return res;
  45. }
  46. static ssize_t libertas_getscantable(struct file *file, char __user *userbuf,
  47. size_t count, loff_t *ppos)
  48. {
  49. wlan_private *priv = file->private_data;
  50. size_t pos = 0;
  51. int numscansdone = 0, res;
  52. unsigned long addr = get_zeroed_page(GFP_KERNEL);
  53. char *buf = (char *)addr;
  54. struct bss_descriptor * iter_bss;
  55. pos += snprintf(buf+pos, len-pos,
  56. "# | ch | ss | bssid | cap | TSF | Qual | SSID \n");
  57. mutex_lock(&priv->adapter->lock);
  58. list_for_each_entry (iter_bss, &priv->adapter->network_list, list) {
  59. u16 cap;
  60. memcpy(&cap, &iter_bss->cap, sizeof(cap));
  61. pos += snprintf(buf+pos, len-pos,
  62. "%02u| %03d | %03ld | %02x:%02x:%02x:%02x:%02x:%02x |",
  63. numscansdone, iter_bss->channel, iter_bss->rssi,
  64. iter_bss->bssid[0], iter_bss->bssid[1],
  65. iter_bss->bssid[2], iter_bss->bssid[3],
  66. iter_bss->bssid[4], iter_bss->bssid[5]);
  67. pos += snprintf(buf+pos, len-pos, " %04x-", cap);
  68. pos += snprintf(buf+pos, len-pos, "%c%c%c |",
  69. iter_bss->cap.ibss ? 'A' : 'I',
  70. iter_bss->cap.privacy ? 'P' : ' ',
  71. iter_bss->cap.spectrummgmt ? 'S' : ' ');
  72. pos += snprintf(buf+pos, len-pos, " %08llx |", iter_bss->networktsf);
  73. pos += snprintf(buf+pos, len-pos, " %d |", SCAN_RSSI(iter_bss->rssi));
  74. pos += snprintf(buf+pos, len-pos, " %s\n", iter_bss->ssid.ssid);
  75. numscansdone++;
  76. }
  77. mutex_unlock(&priv->adapter->lock);
  78. res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
  79. free_page(addr);
  80. return res;
  81. }
  82. static ssize_t libertas_sleepparams_write(struct file *file,
  83. const char __user *user_buf, size_t count,
  84. loff_t *ppos)
  85. {
  86. wlan_private *priv = file->private_data;
  87. ssize_t buf_size, res;
  88. int p1, p2, p3, p4, p5, p6;
  89. struct sleep_params sp;
  90. unsigned long addr = get_zeroed_page(GFP_KERNEL);
  91. char *buf = (char *)addr;
  92. buf_size = min(count, len - 1);
  93. if (copy_from_user(buf, user_buf, buf_size)) {
  94. res = -EFAULT;
  95. goto out_unlock;
  96. }
  97. res = sscanf(buf, "%d %d %d %d %d %d", &p1, &p2, &p3, &p4, &p5, &p6);
  98. if (res != 6) {
  99. res = -EFAULT;
  100. goto out_unlock;
  101. }
  102. sp.sp_error = p1;
  103. sp.sp_offset = p2;
  104. sp.sp_stabletime = p3;
  105. sp.sp_calcontrol = p4;
  106. sp.sp_extsleepclk = p5;
  107. sp.sp_reserved = p6;
  108. memcpy(&priv->adapter->sp, &sp, sizeof(struct sleep_params));
  109. res = libertas_prepare_and_send_command(priv,
  110. cmd_802_11_sleep_params,
  111. cmd_act_set,
  112. cmd_option_waitforrsp, 0, NULL);
  113. if (!res)
  114. res = count;
  115. else
  116. res = -EINVAL;
  117. out_unlock:
  118. free_page(addr);
  119. return res;
  120. }
  121. static ssize_t libertas_sleepparams_read(struct file *file, char __user *userbuf,
  122. size_t count, loff_t *ppos)
  123. {
  124. wlan_private *priv = file->private_data;
  125. wlan_adapter *adapter = priv->adapter;
  126. ssize_t res;
  127. size_t pos = 0;
  128. unsigned long addr = get_zeroed_page(GFP_KERNEL);
  129. char *buf = (char *)addr;
  130. res = libertas_prepare_and_send_command(priv,
  131. cmd_802_11_sleep_params,
  132. cmd_act_get,
  133. cmd_option_waitforrsp, 0, NULL);
  134. if (res) {
  135. res = -EFAULT;
  136. goto out_unlock;
  137. }
  138. pos += snprintf(buf, len, "%d %d %d %d %d %d\n", adapter->sp.sp_error,
  139. adapter->sp.sp_offset, adapter->sp.sp_stabletime,
  140. adapter->sp.sp_calcontrol, adapter->sp.sp_extsleepclk,
  141. adapter->sp.sp_reserved);
  142. res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
  143. out_unlock:
  144. free_page(addr);
  145. return res;
  146. }
  147. static ssize_t libertas_extscan(struct file *file, const char __user *userbuf,
  148. size_t count, loff_t *ppos)
  149. {
  150. wlan_private *priv = file->private_data;
  151. ssize_t res, buf_size;
  152. struct WLAN_802_11_SSID extscan_ssid;
  153. union iwreq_data wrqu;
  154. unsigned long addr = get_zeroed_page(GFP_KERNEL);
  155. char *buf = (char *)addr;
  156. buf_size = min(count, len - 1);
  157. if (copy_from_user(buf, userbuf, buf_size)) {
  158. res = -EFAULT;
  159. goto out_unlock;
  160. }
  161. memcpy(&extscan_ssid.ssid, buf, strlen(buf)-1);
  162. extscan_ssid.ssidlength = strlen(buf)-1;
  163. libertas_send_specific_SSID_scan(priv, &extscan_ssid, 0);
  164. memset(&wrqu, 0, sizeof(union iwreq_data));
  165. wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
  166. out_unlock:
  167. free_page(addr);
  168. return count;
  169. }
  170. static int libertas_parse_chan(char *buf, size_t count,
  171. struct wlan_ioctl_user_scan_cfg *scan_cfg, int dur)
  172. {
  173. char *start, *end, *hold, *str;
  174. int i = 0;
  175. start = strstr(buf, "chan=");
  176. if (!start)
  177. return -EINVAL;
  178. start += 5;
  179. end = strstr(start, " ");
  180. if (!end)
  181. end = buf + count;
  182. hold = kzalloc((end - start)+1, GFP_KERNEL);
  183. if (!hold)
  184. return -ENOMEM;
  185. strncpy(hold, start, end - start);
  186. hold[(end-start)+1] = '\0';
  187. while(hold && (str = strsep(&hold, ","))) {
  188. int chan;
  189. char band, passive = 0;
  190. sscanf(str, "%d%c%c", &chan, &band, &passive);
  191. scan_cfg->chanlist[i].channumber = chan;
  192. scan_cfg->chanlist[i].scantype = passive ? 1 : 0;
  193. if (band == 'b' || band == 'g')
  194. scan_cfg->chanlist[i].radiotype = 0;
  195. else if (band == 'a')
  196. scan_cfg->chanlist[i].radiotype = 1;
  197. scan_cfg->chanlist[i].scantime = dur;
  198. i++;
  199. }
  200. kfree(hold);
  201. return i;
  202. }
  203. static void libertas_parse_bssid(char *buf, size_t count,
  204. struct wlan_ioctl_user_scan_cfg *scan_cfg)
  205. {
  206. char *hold;
  207. unsigned int mac[ETH_ALEN];
  208. hold = strstr(buf, "bssid=");
  209. if (!hold)
  210. return;
  211. hold += 6;
  212. sscanf(hold, MAC_FMT, mac, mac+1, mac+2, mac+3, mac+4, mac+5);
  213. memcpy(scan_cfg->bssid, mac, ETH_ALEN);
  214. }
  215. static void libertas_parse_ssid(char *buf, size_t count,
  216. struct wlan_ioctl_user_scan_cfg *scan_cfg)
  217. {
  218. char *hold, *end;
  219. ssize_t size;
  220. hold = strstr(buf, "ssid=");
  221. if (!hold)
  222. return;
  223. hold += 5;
  224. end = strstr(hold, " ");
  225. if (!end)
  226. end = buf + count - 1;
  227. size = min((size_t)IW_ESSID_MAX_SIZE, (size_t) (end - hold));
  228. strncpy(scan_cfg->ssid, hold, size);
  229. return;
  230. }
  231. static int libertas_parse_clear(char *buf, size_t count, const char *tag)
  232. {
  233. char *hold;
  234. int val;
  235. hold = strstr(buf, tag);
  236. if (!hold)
  237. return 0;
  238. hold += strlen(tag);
  239. sscanf(hold, "%d", &val);
  240. if (val != 0)
  241. val = 1;
  242. return val;
  243. }
  244. static int libertas_parse_dur(char *buf, size_t count,
  245. struct wlan_ioctl_user_scan_cfg *scan_cfg)
  246. {
  247. char *hold;
  248. int val;
  249. hold = strstr(buf, "dur=");
  250. if (!hold)
  251. return 0;
  252. hold += 4;
  253. sscanf(hold, "%d", &val);
  254. return val;
  255. }
  256. static void libertas_parse_probes(char *buf, size_t count,
  257. struct wlan_ioctl_user_scan_cfg *scan_cfg)
  258. {
  259. char *hold;
  260. int val;
  261. hold = strstr(buf, "probes=");
  262. if (!hold)
  263. return;
  264. hold += 7;
  265. sscanf(hold, "%d", &val);
  266. scan_cfg->numprobes = val;
  267. return;
  268. }
  269. static void libertas_parse_type(char *buf, size_t count,
  270. struct wlan_ioctl_user_scan_cfg *scan_cfg)
  271. {
  272. char *hold;
  273. int val;
  274. hold = strstr(buf, "type=");
  275. if (!hold)
  276. return;
  277. hold += 5;
  278. sscanf(hold, "%d", &val);
  279. /* type=1,2 or 3 */
  280. if (val < 1 || val > 3)
  281. return;
  282. scan_cfg->bsstype = val;
  283. return;
  284. }
  285. static ssize_t libertas_setuserscan(struct file *file,
  286. const char __user *userbuf,
  287. size_t count, loff_t *ppos)
  288. {
  289. wlan_private *priv = file->private_data;
  290. ssize_t res, buf_size;
  291. struct wlan_ioctl_user_scan_cfg *scan_cfg;
  292. union iwreq_data wrqu;
  293. int dur;
  294. unsigned long addr = get_zeroed_page(GFP_KERNEL);
  295. char *buf = (char *)addr;
  296. scan_cfg = kzalloc(sizeof(struct wlan_ioctl_user_scan_cfg), GFP_KERNEL);
  297. if (!scan_cfg)
  298. return -ENOMEM;
  299. buf_size = min(count, len - 1);
  300. if (copy_from_user(buf, userbuf, buf_size)) {
  301. res = -EFAULT;
  302. goto out_unlock;
  303. }
  304. scan_cfg->bsstype = WLAN_SCAN_BSS_TYPE_ANY;
  305. dur = libertas_parse_dur(buf, count, scan_cfg);
  306. libertas_parse_chan(buf, count, scan_cfg, dur);
  307. libertas_parse_bssid(buf, count, scan_cfg);
  308. scan_cfg->clear_bssid = libertas_parse_clear(buf, count, "clear_bssid=");
  309. libertas_parse_ssid(buf, count, scan_cfg);
  310. scan_cfg->clear_ssid = libertas_parse_clear(buf, count, "clear_ssid=");
  311. libertas_parse_probes(buf, count, scan_cfg);
  312. libertas_parse_type(buf, count, scan_cfg);
  313. wlan_scan_networks(priv, scan_cfg, 1);
  314. wait_event_interruptible(priv->adapter->cmd_pending,
  315. !priv->adapter->nr_cmd_pending);
  316. memset(&wrqu, 0x00, sizeof(union iwreq_data));
  317. wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
  318. out_unlock:
  319. free_page(addr);
  320. kfree(scan_cfg);
  321. return count;
  322. }
  323. static int libertas_event_initcmd(wlan_private *priv, void **response_buf,
  324. struct cmd_ctrl_node **cmdnode,
  325. struct cmd_ds_command **cmd)
  326. {
  327. u16 wait_option = cmd_option_waitforrsp;
  328. if (!(*cmdnode = libertas_get_free_cmd_ctrl_node(priv))) {
  329. lbs_deb_debugfs("failed libertas_get_free_cmd_ctrl_node\n");
  330. return -ENOMEM;
  331. }
  332. if (!(*response_buf = kmalloc(3000, GFP_KERNEL))) {
  333. lbs_deb_debugfs("failed to allocate response buffer!\n");
  334. return -ENOMEM;
  335. }
  336. libertas_set_cmd_ctrl_node(priv, *cmdnode, 0, wait_option, NULL);
  337. init_waitqueue_head(&(*cmdnode)->cmdwait_q);
  338. (*cmdnode)->pdata_buf = *response_buf;
  339. (*cmdnode)->cmdflags |= CMD_F_HOSTCMD;
  340. (*cmdnode)->cmdwaitqwoken = 0;
  341. *cmd = (struct cmd_ds_command *)(*cmdnode)->bufvirtualaddr;
  342. (*cmd)->command = cmd_802_11_subscribe_event;
  343. (*cmd)->seqnum = ++priv->adapter->seqnum;
  344. (*cmd)->result = 0;
  345. return 0;
  346. }
  347. static ssize_t libertas_lowrssi_read(struct file *file, char __user *userbuf,
  348. size_t count, loff_t *ppos)
  349. {
  350. wlan_private *priv = file->private_data;
  351. wlan_adapter *adapter = priv->adapter;
  352. struct cmd_ctrl_node *pcmdnode;
  353. struct cmd_ds_command *pcmdptr;
  354. struct cmd_ds_802_11_subscribe_event *event;
  355. void *response_buf;
  356. int res, cmd_len;
  357. ssize_t pos = 0;
  358. unsigned long addr = get_zeroed_page(GFP_KERNEL);
  359. char *buf = (char *)addr;
  360. res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
  361. if (res < 0) {
  362. free_page(addr);
  363. return res;
  364. }
  365. event = &pcmdptr->params.subscribe_event;
  366. event->action = cmd_act_get;
  367. pcmdptr->size =
  368. cpu_to_le16(sizeof(struct cmd_ds_802_11_subscribe_event) + S_DS_GEN);
  369. libertas_queue_cmd(adapter, pcmdnode, 1);
  370. wake_up_interruptible(&priv->mainthread.waitq);
  371. /* Sleep until response is generated by FW */
  372. wait_event_interruptible(pcmdnode->cmdwait_q,
  373. pcmdnode->cmdwaitqwoken);
  374. pcmdptr = response_buf;
  375. if (pcmdptr->result) {
  376. lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
  377. pcmdptr->result);
  378. kfree(response_buf);
  379. free_page(addr);
  380. return 0;
  381. }
  382. if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
  383. lbs_pr_err("command response incorrect!\n");
  384. kfree(response_buf);
  385. free_page(addr);
  386. return 0;
  387. }
  388. cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
  389. event = (struct cmd_ds_802_11_subscribe_event *)(response_buf + S_DS_GEN);
  390. while (cmd_len < pcmdptr->size) {
  391. struct mrvlietypesheader *header = (struct mrvlietypesheader *)(response_buf + cmd_len);
  392. switch(header->type) {
  393. struct mrvlietypes_rssithreshold *Lowrssi;
  394. case TLV_TYPE_RSSI_LOW:
  395. Lowrssi = (struct mrvlietypes_rssithreshold *)(response_buf + cmd_len);
  396. pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
  397. Lowrssi->rssivalue,
  398. Lowrssi->rssifreq,
  399. (event->events & 0x0001)?1:0);
  400. default:
  401. cmd_len += sizeof(struct mrvlietypes_snrthreshold);
  402. break;
  403. }
  404. }
  405. kfree(response_buf);
  406. res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
  407. free_page(addr);
  408. return res;
  409. }
  410. static u16 libertas_get_events_bitmap(wlan_private *priv)
  411. {
  412. wlan_adapter *adapter = priv->adapter;
  413. struct cmd_ctrl_node *pcmdnode;
  414. struct cmd_ds_command *pcmdptr;
  415. struct cmd_ds_802_11_subscribe_event *event;
  416. void *response_buf;
  417. int res;
  418. u16 event_bitmap;
  419. res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
  420. if (res < 0)
  421. return res;
  422. event = &pcmdptr->params.subscribe_event;
  423. event->action = cmd_act_get;
  424. pcmdptr->size =
  425. cpu_to_le16(sizeof(struct cmd_ds_802_11_subscribe_event) + S_DS_GEN);
  426. libertas_queue_cmd(adapter, pcmdnode, 1);
  427. wake_up_interruptible(&priv->mainthread.waitq);
  428. /* Sleep until response is generated by FW */
  429. wait_event_interruptible(pcmdnode->cmdwait_q,
  430. pcmdnode->cmdwaitqwoken);
  431. pcmdptr = response_buf;
  432. if (pcmdptr->result) {
  433. lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
  434. pcmdptr->result);
  435. kfree(response_buf);
  436. return 0;
  437. }
  438. if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
  439. lbs_pr_err("command response incorrect!\n");
  440. kfree(response_buf);
  441. return 0;
  442. }
  443. event = (struct cmd_ds_802_11_subscribe_event *)(response_buf + S_DS_GEN);
  444. event_bitmap = event->events;
  445. kfree(response_buf);
  446. return event_bitmap;
  447. }
  448. static ssize_t libertas_lowrssi_write(struct file *file,
  449. const char __user *userbuf,
  450. size_t count, loff_t *ppos)
  451. {
  452. wlan_private *priv = file->private_data;
  453. wlan_adapter *adapter = priv->adapter;
  454. ssize_t res, buf_size;
  455. int value, freq, subscribed, cmd_len;
  456. struct cmd_ctrl_node *pcmdnode;
  457. struct cmd_ds_command *pcmdptr;
  458. struct cmd_ds_802_11_subscribe_event *event;
  459. struct mrvlietypes_rssithreshold *rssi_threshold;
  460. void *response_buf;
  461. u16 event_bitmap;
  462. u8 *ptr;
  463. unsigned long addr = get_zeroed_page(GFP_KERNEL);
  464. char *buf = (char *)addr;
  465. buf_size = min(count, len - 1);
  466. if (copy_from_user(buf, userbuf, buf_size)) {
  467. res = -EFAULT;
  468. goto out_unlock;
  469. }
  470. res = sscanf(buf, "%d %d %d", &value, &freq, &subscribed);
  471. if (res != 3) {
  472. res = -EFAULT;
  473. goto out_unlock;
  474. }
  475. event_bitmap = libertas_get_events_bitmap(priv);
  476. res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
  477. if (res < 0)
  478. goto out_unlock;
  479. event = &pcmdptr->params.subscribe_event;
  480. event->action = cmd_act_set;
  481. pcmdptr->size = cpu_to_le16(S_DS_GEN +
  482. sizeof(struct cmd_ds_802_11_subscribe_event) +
  483. sizeof(struct mrvlietypes_rssithreshold));
  484. cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
  485. ptr = (u8*) pcmdptr+cmd_len;
  486. rssi_threshold = (struct mrvlietypes_rssithreshold *)(ptr);
  487. rssi_threshold->header.type = cpu_to_le16(0x0104);
  488. rssi_threshold->header.len = 2;
  489. rssi_threshold->rssivalue = cpu_to_le16(value);
  490. rssi_threshold->rssifreq = cpu_to_le16(freq);
  491. event_bitmap |= subscribed ? 0x0001 : 0x0;
  492. event->events = event_bitmap;
  493. libertas_queue_cmd(adapter, pcmdnode, 1);
  494. wake_up_interruptible(&priv->mainthread.waitq);
  495. /* Sleep until response is generated by FW */
  496. wait_event_interruptible(pcmdnode->cmdwait_q,
  497. pcmdnode->cmdwaitqwoken);
  498. pcmdptr = response_buf;
  499. if (pcmdptr->result) {
  500. lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
  501. pcmdptr->result);
  502. kfree(response_buf);
  503. free_page(addr);
  504. return 0;
  505. }
  506. if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
  507. lbs_pr_err("command response incorrect!\n");
  508. kfree(response_buf);
  509. free_page(addr);
  510. return 0;
  511. }
  512. res = count;
  513. out_unlock:
  514. free_page(addr);
  515. return res;
  516. }
  517. static ssize_t libertas_lowsnr_read(struct file *file, char __user *userbuf,
  518. size_t count, loff_t *ppos)
  519. {
  520. wlan_private *priv = file->private_data;
  521. wlan_adapter *adapter = priv->adapter;
  522. struct cmd_ctrl_node *pcmdnode;
  523. struct cmd_ds_command *pcmdptr;
  524. struct cmd_ds_802_11_subscribe_event *event;
  525. void *response_buf;
  526. int res, cmd_len;
  527. ssize_t pos = 0;
  528. unsigned long addr = get_zeroed_page(GFP_KERNEL);
  529. char *buf = (char *)addr;
  530. res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
  531. if (res < 0) {
  532. free_page(addr);
  533. return res;
  534. }
  535. event = &pcmdptr->params.subscribe_event;
  536. event->action = cmd_act_get;
  537. pcmdptr->size =
  538. cpu_to_le16(sizeof(struct cmd_ds_802_11_subscribe_event) + S_DS_GEN);
  539. libertas_queue_cmd(adapter, pcmdnode, 1);
  540. wake_up_interruptible(&priv->mainthread.waitq);
  541. /* Sleep until response is generated by FW */
  542. wait_event_interruptible(pcmdnode->cmdwait_q,
  543. pcmdnode->cmdwaitqwoken);
  544. pcmdptr = response_buf;
  545. if (pcmdptr->result) {
  546. lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
  547. pcmdptr->result);
  548. kfree(response_buf);
  549. free_page(addr);
  550. return 0;
  551. }
  552. if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
  553. lbs_pr_err("command response incorrect!\n");
  554. kfree(response_buf);
  555. free_page(addr);
  556. return 0;
  557. }
  558. cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
  559. event = (struct cmd_ds_802_11_subscribe_event *)(response_buf + S_DS_GEN);
  560. while (cmd_len < pcmdptr->size) {
  561. struct mrvlietypesheader *header = (struct mrvlietypesheader *)(response_buf + cmd_len);
  562. switch(header->type) {
  563. struct mrvlietypes_snrthreshold *LowSnr;
  564. case TLV_TYPE_SNR_LOW:
  565. LowSnr = (struct mrvlietypes_snrthreshold *)(response_buf + cmd_len);
  566. pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
  567. LowSnr->snrvalue,
  568. LowSnr->snrfreq,
  569. (event->events & 0x0002)?1:0);
  570. default:
  571. cmd_len += sizeof(struct mrvlietypes_snrthreshold);
  572. break;
  573. }
  574. }
  575. kfree(response_buf);
  576. res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
  577. free_page(addr);
  578. return res;
  579. }
  580. static ssize_t libertas_lowsnr_write(struct file *file,
  581. const char __user *userbuf,
  582. size_t count, loff_t *ppos)
  583. {
  584. wlan_private *priv = file->private_data;
  585. wlan_adapter *adapter = priv->adapter;
  586. ssize_t res, buf_size;
  587. int value, freq, subscribed, cmd_len;
  588. struct cmd_ctrl_node *pcmdnode;
  589. struct cmd_ds_command *pcmdptr;
  590. struct cmd_ds_802_11_subscribe_event *event;
  591. struct mrvlietypes_snrthreshold *snr_threshold;
  592. void *response_buf;
  593. u16 event_bitmap;
  594. u8 *ptr;
  595. unsigned long addr = get_zeroed_page(GFP_KERNEL);
  596. char *buf = (char *)addr;
  597. buf_size = min(count, len - 1);
  598. if (copy_from_user(buf, userbuf, buf_size)) {
  599. res = -EFAULT;
  600. goto out_unlock;
  601. }
  602. res = sscanf(buf, "%d %d %d", &value, &freq, &subscribed);
  603. if (res != 3) {
  604. res = -EFAULT;
  605. goto out_unlock;
  606. }
  607. event_bitmap = libertas_get_events_bitmap(priv);
  608. res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
  609. if (res < 0)
  610. goto out_unlock;
  611. event = &pcmdptr->params.subscribe_event;
  612. event->action = cmd_act_set;
  613. pcmdptr->size = cpu_to_le16(S_DS_GEN +
  614. sizeof(struct cmd_ds_802_11_subscribe_event) +
  615. sizeof(struct mrvlietypes_snrthreshold));
  616. cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
  617. ptr = (u8*) pcmdptr+cmd_len;
  618. snr_threshold = (struct mrvlietypes_snrthreshold *)(ptr);
  619. snr_threshold->header.type = cpu_to_le16(TLV_TYPE_SNR_LOW);
  620. snr_threshold->header.len = 2;
  621. snr_threshold->snrvalue = cpu_to_le16(value);
  622. snr_threshold->snrfreq = cpu_to_le16(freq);
  623. event_bitmap |= subscribed ? 0x0002 : 0x0;
  624. event->events = event_bitmap;
  625. libertas_queue_cmd(adapter, pcmdnode, 1);
  626. wake_up_interruptible(&priv->mainthread.waitq);
  627. /* Sleep until response is generated by FW */
  628. wait_event_interruptible(pcmdnode->cmdwait_q,
  629. pcmdnode->cmdwaitqwoken);
  630. pcmdptr = response_buf;
  631. if (pcmdptr->result) {
  632. lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
  633. pcmdptr->result);
  634. kfree(response_buf);
  635. free_page(addr);
  636. return 0;
  637. }
  638. if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
  639. lbs_pr_err("command response incorrect!\n");
  640. kfree(response_buf);
  641. free_page(addr);
  642. return 0;
  643. }
  644. res = count;
  645. out_unlock:
  646. free_page(addr);
  647. return res;
  648. }
  649. static ssize_t libertas_failcount_read(struct file *file, char __user *userbuf,
  650. size_t count, loff_t *ppos)
  651. {
  652. wlan_private *priv = file->private_data;
  653. wlan_adapter *adapter = priv->adapter;
  654. struct cmd_ctrl_node *pcmdnode;
  655. struct cmd_ds_command *pcmdptr;
  656. struct cmd_ds_802_11_subscribe_event *event;
  657. void *response_buf;
  658. int res, cmd_len;
  659. ssize_t pos = 0;
  660. unsigned long addr = get_zeroed_page(GFP_KERNEL);
  661. char *buf = (char *)addr;
  662. res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
  663. if (res < 0) {
  664. free_page(addr);
  665. return res;
  666. }
  667. event = &pcmdptr->params.subscribe_event;
  668. event->action = cmd_act_get;
  669. pcmdptr->size =
  670. cpu_to_le16(sizeof(struct cmd_ds_802_11_subscribe_event) + S_DS_GEN);
  671. libertas_queue_cmd(adapter, pcmdnode, 1);
  672. wake_up_interruptible(&priv->mainthread.waitq);
  673. /* Sleep until response is generated by FW */
  674. wait_event_interruptible(pcmdnode->cmdwait_q,
  675. pcmdnode->cmdwaitqwoken);
  676. pcmdptr = response_buf;
  677. if (pcmdptr->result) {
  678. lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
  679. pcmdptr->result);
  680. kfree(response_buf);
  681. free_page(addr);
  682. return 0;
  683. }
  684. if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
  685. lbs_pr_err("command response incorrect!\n");
  686. kfree(response_buf);
  687. free_page(addr);
  688. return 0;
  689. }
  690. cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
  691. event = (struct cmd_ds_802_11_subscribe_event *)(response_buf + S_DS_GEN);
  692. while (cmd_len < pcmdptr->size) {
  693. struct mrvlietypesheader *header = (struct mrvlietypesheader *)(response_buf + cmd_len);
  694. switch(header->type) {
  695. struct mrvlietypes_failurecount *failcount;
  696. case TLV_TYPE_FAILCOUNT:
  697. failcount = (struct mrvlietypes_failurecount *)(response_buf + cmd_len);
  698. pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
  699. failcount->failvalue,
  700. failcount->Failfreq,
  701. (event->events & 0x0004)?1:0);
  702. default:
  703. cmd_len += sizeof(struct mrvlietypes_failurecount);
  704. break;
  705. }
  706. }
  707. kfree(response_buf);
  708. res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
  709. free_page(addr);
  710. return res;
  711. }
  712. static ssize_t libertas_failcount_write(struct file *file,
  713. const char __user *userbuf,
  714. size_t count, loff_t *ppos)
  715. {
  716. wlan_private *priv = file->private_data;
  717. wlan_adapter *adapter = priv->adapter;
  718. ssize_t res, buf_size;
  719. int value, freq, subscribed, cmd_len;
  720. struct cmd_ctrl_node *pcmdnode;
  721. struct cmd_ds_command *pcmdptr;
  722. struct cmd_ds_802_11_subscribe_event *event;
  723. struct mrvlietypes_failurecount *failcount;
  724. void *response_buf;
  725. u16 event_bitmap;
  726. u8 *ptr;
  727. unsigned long addr = get_zeroed_page(GFP_KERNEL);
  728. char *buf = (char *)addr;
  729. buf_size = min(count, len - 1);
  730. if (copy_from_user(buf, userbuf, buf_size)) {
  731. res = -EFAULT;
  732. goto out_unlock;
  733. }
  734. res = sscanf(buf, "%d %d %d", &value, &freq, &subscribed);
  735. if (res != 3) {
  736. res = -EFAULT;
  737. goto out_unlock;
  738. }
  739. event_bitmap = libertas_get_events_bitmap(priv);
  740. res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
  741. if (res < 0)
  742. goto out_unlock;
  743. event = &pcmdptr->params.subscribe_event;
  744. event->action = cmd_act_set;
  745. pcmdptr->size = cpu_to_le16(S_DS_GEN +
  746. sizeof(struct cmd_ds_802_11_subscribe_event) +
  747. sizeof(struct mrvlietypes_failurecount));
  748. cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
  749. ptr = (u8*) pcmdptr+cmd_len;
  750. failcount = (struct mrvlietypes_failurecount *)(ptr);
  751. failcount->header.type = cpu_to_le16(TLV_TYPE_FAILCOUNT);
  752. failcount->header.len = 2;
  753. failcount->failvalue = cpu_to_le16(value);
  754. failcount->Failfreq = cpu_to_le16(freq);
  755. event_bitmap |= subscribed ? 0x0004 : 0x0;
  756. event->events = event_bitmap;
  757. libertas_queue_cmd(adapter, pcmdnode, 1);
  758. wake_up_interruptible(&priv->mainthread.waitq);
  759. /* Sleep until response is generated by FW */
  760. wait_event_interruptible(pcmdnode->cmdwait_q,
  761. pcmdnode->cmdwaitqwoken);
  762. pcmdptr = (struct cmd_ds_command *)response_buf;
  763. if (pcmdptr->result) {
  764. lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
  765. pcmdptr->result);
  766. kfree(response_buf);
  767. free_page(addr);
  768. return 0;
  769. }
  770. if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
  771. lbs_pr_err("command response incorrect!\n");
  772. kfree(response_buf);
  773. free_page(addr);
  774. return 0;
  775. }
  776. res = count;
  777. out_unlock:
  778. free_page(addr);
  779. return res;
  780. }
  781. static ssize_t libertas_bcnmiss_read(struct file *file, char __user *userbuf,
  782. size_t count, loff_t *ppos)
  783. {
  784. wlan_private *priv = file->private_data;
  785. wlan_adapter *adapter = priv->adapter;
  786. struct cmd_ctrl_node *pcmdnode;
  787. struct cmd_ds_command *pcmdptr;
  788. struct cmd_ds_802_11_subscribe_event *event;
  789. void *response_buf;
  790. int res, cmd_len;
  791. ssize_t pos = 0;
  792. unsigned long addr = get_zeroed_page(GFP_KERNEL);
  793. char *buf = (char *)addr;
  794. res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
  795. if (res < 0) {
  796. free_page(addr);
  797. return res;
  798. }
  799. event = &pcmdptr->params.subscribe_event;
  800. event->action = cmd_act_get;
  801. pcmdptr->size =
  802. cpu_to_le16(sizeof(struct cmd_ds_802_11_subscribe_event) + S_DS_GEN);
  803. libertas_queue_cmd(adapter, pcmdnode, 1);
  804. wake_up_interruptible(&priv->mainthread.waitq);
  805. /* Sleep until response is generated by FW */
  806. wait_event_interruptible(pcmdnode->cmdwait_q,
  807. pcmdnode->cmdwaitqwoken);
  808. pcmdptr = response_buf;
  809. if (pcmdptr->result) {
  810. lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
  811. pcmdptr->result);
  812. free_page(addr);
  813. kfree(response_buf);
  814. return 0;
  815. }
  816. if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
  817. lbs_pr_err("command response incorrect!\n");
  818. free_page(addr);
  819. kfree(response_buf);
  820. return 0;
  821. }
  822. cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
  823. event = (struct cmd_ds_802_11_subscribe_event *)(response_buf + S_DS_GEN);
  824. while (cmd_len < pcmdptr->size) {
  825. struct mrvlietypesheader *header = (struct mrvlietypesheader *)(response_buf + cmd_len);
  826. switch(header->type) {
  827. struct mrvlietypes_beaconsmissed *bcnmiss;
  828. case TLV_TYPE_BCNMISS:
  829. bcnmiss = (struct mrvlietypes_beaconsmissed *)(response_buf + cmd_len);
  830. pos += snprintf(buf+pos, len-pos, "%d N/A %d\n",
  831. bcnmiss->beaconmissed,
  832. (event->events & 0x0008)?1:0);
  833. default:
  834. cmd_len += sizeof(struct mrvlietypes_beaconsmissed);
  835. break;
  836. }
  837. }
  838. kfree(response_buf);
  839. res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
  840. free_page(addr);
  841. return res;
  842. }
  843. static ssize_t libertas_bcnmiss_write(struct file *file,
  844. const char __user *userbuf,
  845. size_t count, loff_t *ppos)
  846. {
  847. wlan_private *priv = file->private_data;
  848. wlan_adapter *adapter = priv->adapter;
  849. ssize_t res, buf_size;
  850. int value, freq, subscribed, cmd_len;
  851. struct cmd_ctrl_node *pcmdnode;
  852. struct cmd_ds_command *pcmdptr;
  853. struct cmd_ds_802_11_subscribe_event *event;
  854. struct mrvlietypes_beaconsmissed *bcnmiss;
  855. void *response_buf;
  856. u16 event_bitmap;
  857. u8 *ptr;
  858. unsigned long addr = get_zeroed_page(GFP_KERNEL);
  859. char *buf = (char *)addr;
  860. buf_size = min(count, len - 1);
  861. if (copy_from_user(buf, userbuf, buf_size)) {
  862. res = -EFAULT;
  863. goto out_unlock;
  864. }
  865. res = sscanf(buf, "%d %d %d", &value, &freq, &subscribed);
  866. if (res != 3) {
  867. res = -EFAULT;
  868. goto out_unlock;
  869. }
  870. event_bitmap = libertas_get_events_bitmap(priv);
  871. res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
  872. if (res < 0)
  873. goto out_unlock;
  874. event = &pcmdptr->params.subscribe_event;
  875. event->action = cmd_act_set;
  876. pcmdptr->size = cpu_to_le16(S_DS_GEN +
  877. sizeof(struct cmd_ds_802_11_subscribe_event) +
  878. sizeof(struct mrvlietypes_beaconsmissed));
  879. cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
  880. ptr = (u8*) pcmdptr+cmd_len;
  881. bcnmiss = (struct mrvlietypes_beaconsmissed *)(ptr);
  882. bcnmiss->header.type = cpu_to_le16(TLV_TYPE_BCNMISS);
  883. bcnmiss->header.len = 2;
  884. bcnmiss->beaconmissed = cpu_to_le16(value);
  885. event_bitmap |= subscribed ? 0x0008 : 0x0;
  886. event->events = event_bitmap;
  887. libertas_queue_cmd(adapter, pcmdnode, 1);
  888. wake_up_interruptible(&priv->mainthread.waitq);
  889. /* Sleep until response is generated by FW */
  890. wait_event_interruptible(pcmdnode->cmdwait_q,
  891. pcmdnode->cmdwaitqwoken);
  892. pcmdptr = response_buf;
  893. if (pcmdptr->result) {
  894. lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
  895. pcmdptr->result);
  896. kfree(response_buf);
  897. free_page(addr);
  898. return 0;
  899. }
  900. if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
  901. lbs_pr_err("command response incorrect!\n");
  902. free_page(addr);
  903. kfree(response_buf);
  904. return 0;
  905. }
  906. res = count;
  907. out_unlock:
  908. free_page(addr);
  909. return res;
  910. }
  911. static ssize_t libertas_highrssi_read(struct file *file, char __user *userbuf,
  912. size_t count, loff_t *ppos)
  913. {
  914. wlan_private *priv = file->private_data;
  915. wlan_adapter *adapter = priv->adapter;
  916. struct cmd_ctrl_node *pcmdnode;
  917. struct cmd_ds_command *pcmdptr;
  918. struct cmd_ds_802_11_subscribe_event *event;
  919. void *response_buf;
  920. int res, cmd_len;
  921. ssize_t pos = 0;
  922. unsigned long addr = get_zeroed_page(GFP_KERNEL);
  923. char *buf = (char *)addr;
  924. res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
  925. if (res < 0) {
  926. free_page(addr);
  927. return res;
  928. }
  929. event = &pcmdptr->params.subscribe_event;
  930. event->action = cmd_act_get;
  931. pcmdptr->size =
  932. cpu_to_le16(sizeof(struct cmd_ds_802_11_subscribe_event) + S_DS_GEN);
  933. libertas_queue_cmd(adapter, pcmdnode, 1);
  934. wake_up_interruptible(&priv->mainthread.waitq);
  935. /* Sleep until response is generated by FW */
  936. wait_event_interruptible(pcmdnode->cmdwait_q,
  937. pcmdnode->cmdwaitqwoken);
  938. pcmdptr = response_buf;
  939. if (pcmdptr->result) {
  940. lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
  941. pcmdptr->result);
  942. kfree(response_buf);
  943. free_page(addr);
  944. return 0;
  945. }
  946. if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
  947. lbs_pr_err("command response incorrect!\n");
  948. kfree(response_buf);
  949. free_page(addr);
  950. return 0;
  951. }
  952. cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
  953. event = (struct cmd_ds_802_11_subscribe_event *)(response_buf + S_DS_GEN);
  954. while (cmd_len < pcmdptr->size) {
  955. struct mrvlietypesheader *header = (struct mrvlietypesheader *)(response_buf + cmd_len);
  956. switch(header->type) {
  957. struct mrvlietypes_rssithreshold *Highrssi;
  958. case TLV_TYPE_RSSI_HIGH:
  959. Highrssi = (struct mrvlietypes_rssithreshold *)(response_buf + cmd_len);
  960. pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
  961. Highrssi->rssivalue,
  962. Highrssi->rssifreq,
  963. (event->events & 0x0010)?1:0);
  964. default:
  965. cmd_len += sizeof(struct mrvlietypes_snrthreshold);
  966. break;
  967. }
  968. }
  969. kfree(response_buf);
  970. res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
  971. free_page(addr);
  972. return res;
  973. }
  974. static ssize_t libertas_highrssi_write(struct file *file,
  975. const char __user *userbuf,
  976. size_t count, loff_t *ppos)
  977. {
  978. wlan_private *priv = file->private_data;
  979. wlan_adapter *adapter = priv->adapter;
  980. ssize_t res, buf_size;
  981. int value, freq, subscribed, cmd_len;
  982. struct cmd_ctrl_node *pcmdnode;
  983. struct cmd_ds_command *pcmdptr;
  984. struct cmd_ds_802_11_subscribe_event *event;
  985. struct mrvlietypes_rssithreshold *rssi_threshold;
  986. void *response_buf;
  987. u16 event_bitmap;
  988. u8 *ptr;
  989. unsigned long addr = get_zeroed_page(GFP_KERNEL);
  990. char *buf = (char *)addr;
  991. buf_size = min(count, len - 1);
  992. if (copy_from_user(buf, userbuf, buf_size)) {
  993. res = -EFAULT;
  994. goto out_unlock;
  995. }
  996. res = sscanf(buf, "%d %d %d", &value, &freq, &subscribed);
  997. if (res != 3) {
  998. res = -EFAULT;
  999. goto out_unlock;
  1000. }
  1001. event_bitmap = libertas_get_events_bitmap(priv);
  1002. res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
  1003. if (res < 0)
  1004. goto out_unlock;
  1005. event = &pcmdptr->params.subscribe_event;
  1006. event->action = cmd_act_set;
  1007. pcmdptr->size = cpu_to_le16(S_DS_GEN +
  1008. sizeof(struct cmd_ds_802_11_subscribe_event) +
  1009. sizeof(struct mrvlietypes_rssithreshold));
  1010. cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
  1011. ptr = (u8*) pcmdptr+cmd_len;
  1012. rssi_threshold = (struct mrvlietypes_rssithreshold *)(ptr);
  1013. rssi_threshold->header.type = cpu_to_le16(TLV_TYPE_RSSI_HIGH);
  1014. rssi_threshold->header.len = 2;
  1015. rssi_threshold->rssivalue = cpu_to_le16(value);
  1016. rssi_threshold->rssifreq = cpu_to_le16(freq);
  1017. event_bitmap |= subscribed ? 0x0010 : 0x0;
  1018. event->events = event_bitmap;
  1019. libertas_queue_cmd(adapter, pcmdnode, 1);
  1020. wake_up_interruptible(&priv->mainthread.waitq);
  1021. /* Sleep until response is generated by FW */
  1022. wait_event_interruptible(pcmdnode->cmdwait_q,
  1023. pcmdnode->cmdwaitqwoken);
  1024. pcmdptr = response_buf;
  1025. if (pcmdptr->result) {
  1026. lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
  1027. pcmdptr->result);
  1028. kfree(response_buf);
  1029. return 0;
  1030. }
  1031. if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
  1032. lbs_pr_err("command response incorrect!\n");
  1033. kfree(response_buf);
  1034. return 0;
  1035. }
  1036. res = count;
  1037. out_unlock:
  1038. free_page(addr);
  1039. return res;
  1040. }
  1041. static ssize_t libertas_highsnr_read(struct file *file, char __user *userbuf,
  1042. size_t count, loff_t *ppos)
  1043. {
  1044. wlan_private *priv = file->private_data;
  1045. wlan_adapter *adapter = priv->adapter;
  1046. struct cmd_ctrl_node *pcmdnode;
  1047. struct cmd_ds_command *pcmdptr;
  1048. struct cmd_ds_802_11_subscribe_event *event;
  1049. void *response_buf;
  1050. int res, cmd_len;
  1051. ssize_t pos = 0;
  1052. unsigned long addr = get_zeroed_page(GFP_KERNEL);
  1053. char *buf = (char *)addr;
  1054. res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
  1055. if (res < 0) {
  1056. free_page(addr);
  1057. return res;
  1058. }
  1059. event = &pcmdptr->params.subscribe_event;
  1060. event->action = cmd_act_get;
  1061. pcmdptr->size =
  1062. cpu_to_le16(sizeof(struct cmd_ds_802_11_subscribe_event) + S_DS_GEN);
  1063. libertas_queue_cmd(adapter, pcmdnode, 1);
  1064. wake_up_interruptible(&priv->mainthread.waitq);
  1065. /* Sleep until response is generated by FW */
  1066. wait_event_interruptible(pcmdnode->cmdwait_q,
  1067. pcmdnode->cmdwaitqwoken);
  1068. pcmdptr = response_buf;
  1069. if (pcmdptr->result) {
  1070. lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
  1071. pcmdptr->result);
  1072. kfree(response_buf);
  1073. free_page(addr);
  1074. return 0;
  1075. }
  1076. if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
  1077. lbs_pr_err("command response incorrect!\n");
  1078. kfree(response_buf);
  1079. free_page(addr);
  1080. return 0;
  1081. }
  1082. cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
  1083. event = (struct cmd_ds_802_11_subscribe_event *)(response_buf + S_DS_GEN);
  1084. while (cmd_len < pcmdptr->size) {
  1085. struct mrvlietypesheader *header = (struct mrvlietypesheader *)(response_buf + cmd_len);
  1086. switch(header->type) {
  1087. struct mrvlietypes_snrthreshold *HighSnr;
  1088. case TLV_TYPE_SNR_HIGH:
  1089. HighSnr = (struct mrvlietypes_snrthreshold *)(response_buf + cmd_len);
  1090. pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
  1091. HighSnr->snrvalue,
  1092. HighSnr->snrfreq,
  1093. (event->events & 0x0020)?1:0);
  1094. default:
  1095. cmd_len += sizeof(struct mrvlietypes_snrthreshold);
  1096. break;
  1097. }
  1098. }
  1099. kfree(response_buf);
  1100. res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
  1101. free_page(addr);
  1102. return res;
  1103. }
  1104. static ssize_t libertas_highsnr_write(struct file *file,
  1105. const char __user *userbuf,
  1106. size_t count, loff_t *ppos)
  1107. {
  1108. wlan_private *priv = file->private_data;
  1109. wlan_adapter *adapter = priv->adapter;
  1110. ssize_t res, buf_size;
  1111. int value, freq, subscribed, cmd_len;
  1112. struct cmd_ctrl_node *pcmdnode;
  1113. struct cmd_ds_command *pcmdptr;
  1114. struct cmd_ds_802_11_subscribe_event *event;
  1115. struct mrvlietypes_snrthreshold *snr_threshold;
  1116. void *response_buf;
  1117. u16 event_bitmap;
  1118. u8 *ptr;
  1119. unsigned long addr = get_zeroed_page(GFP_KERNEL);
  1120. char *buf = (char *)addr;
  1121. buf_size = min(count, len - 1);
  1122. if (copy_from_user(buf, userbuf, buf_size)) {
  1123. res = -EFAULT;
  1124. goto out_unlock;
  1125. }
  1126. res = sscanf(buf, "%d %d %d", &value, &freq, &subscribed);
  1127. if (res != 3) {
  1128. res = -EFAULT;
  1129. goto out_unlock;
  1130. }
  1131. event_bitmap = libertas_get_events_bitmap(priv);
  1132. res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
  1133. if (res < 0)
  1134. goto out_unlock;
  1135. event = &pcmdptr->params.subscribe_event;
  1136. event->action = cmd_act_set;
  1137. pcmdptr->size = cpu_to_le16(S_DS_GEN +
  1138. sizeof(struct cmd_ds_802_11_subscribe_event) +
  1139. sizeof(struct mrvlietypes_snrthreshold));
  1140. cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
  1141. ptr = (u8*) pcmdptr+cmd_len;
  1142. snr_threshold = (struct mrvlietypes_snrthreshold *)(ptr);
  1143. snr_threshold->header.type = cpu_to_le16(TLV_TYPE_SNR_HIGH);
  1144. snr_threshold->header.len = 2;
  1145. snr_threshold->snrvalue = cpu_to_le16(value);
  1146. snr_threshold->snrfreq = cpu_to_le16(freq);
  1147. event_bitmap |= subscribed ? 0x0020 : 0x0;
  1148. event->events = event_bitmap;
  1149. libertas_queue_cmd(adapter, pcmdnode, 1);
  1150. wake_up_interruptible(&priv->mainthread.waitq);
  1151. /* Sleep until response is generated by FW */
  1152. wait_event_interruptible(pcmdnode->cmdwait_q,
  1153. pcmdnode->cmdwaitqwoken);
  1154. pcmdptr = response_buf;
  1155. if (pcmdptr->result) {
  1156. lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
  1157. pcmdptr->result);
  1158. kfree(response_buf);
  1159. free_page(addr);
  1160. return 0;
  1161. }
  1162. if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
  1163. lbs_pr_err("command response incorrect!\n");
  1164. kfree(response_buf);
  1165. free_page(addr);
  1166. return 0;
  1167. }
  1168. res = count;
  1169. out_unlock:
  1170. free_page(addr);
  1171. return res;
  1172. }
  1173. static ssize_t libertas_rdmac_read(struct file *file, char __user *userbuf,
  1174. size_t count, loff_t *ppos)
  1175. {
  1176. wlan_private *priv = file->private_data;
  1177. wlan_adapter *adapter = priv->adapter;
  1178. struct wlan_offset_value offval;
  1179. ssize_t pos = 0;
  1180. int ret;
  1181. unsigned long addr = get_zeroed_page(GFP_KERNEL);
  1182. char *buf = (char *)addr;
  1183. offval.offset = priv->mac_offset;
  1184. offval.value = 0;
  1185. ret = libertas_prepare_and_send_command(priv,
  1186. cmd_mac_reg_access, 0,
  1187. cmd_option_waitforrsp, 0, &offval);
  1188. mdelay(10);
  1189. pos += snprintf(buf+pos, len-pos, "MAC[0x%x] = 0x%08x\n",
  1190. priv->mac_offset, adapter->offsetvalue.value);
  1191. ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
  1192. free_page(addr);
  1193. return ret;
  1194. }
  1195. static ssize_t libertas_rdmac_write(struct file *file,
  1196. const char __user *userbuf,
  1197. size_t count, loff_t *ppos)
  1198. {
  1199. wlan_private *priv = file->private_data;
  1200. ssize_t res, buf_size;
  1201. unsigned long addr = get_zeroed_page(GFP_KERNEL);
  1202. char *buf = (char *)addr;
  1203. buf_size = min(count, len - 1);
  1204. if (copy_from_user(buf, userbuf, buf_size)) {
  1205. res = -EFAULT;
  1206. goto out_unlock;
  1207. }
  1208. priv->mac_offset = simple_strtoul((char *)buf, NULL, 16);
  1209. res = count;
  1210. out_unlock:
  1211. free_page(addr);
  1212. return res;
  1213. }
  1214. static ssize_t libertas_wrmac_write(struct file *file,
  1215. const char __user *userbuf,
  1216. size_t count, loff_t *ppos)
  1217. {
  1218. wlan_private *priv = file->private_data;
  1219. ssize_t res, buf_size;
  1220. u32 offset, value;
  1221. struct wlan_offset_value offval;
  1222. unsigned long addr = get_zeroed_page(GFP_KERNEL);
  1223. char *buf = (char *)addr;
  1224. buf_size = min(count, len - 1);
  1225. if (copy_from_user(buf, userbuf, buf_size)) {
  1226. res = -EFAULT;
  1227. goto out_unlock;
  1228. }
  1229. res = sscanf(buf, "%x %x", &offset, &value);
  1230. if (res != 2) {
  1231. res = -EFAULT;
  1232. goto out_unlock;
  1233. }
  1234. offval.offset = offset;
  1235. offval.value = value;
  1236. res = libertas_prepare_and_send_command(priv,
  1237. cmd_mac_reg_access, 1,
  1238. cmd_option_waitforrsp, 0, &offval);
  1239. mdelay(10);
  1240. res = count;
  1241. out_unlock:
  1242. free_page(addr);
  1243. return res;
  1244. }
  1245. static ssize_t libertas_rdbbp_read(struct file *file, char __user *userbuf,
  1246. size_t count, loff_t *ppos)
  1247. {
  1248. wlan_private *priv = file->private_data;
  1249. wlan_adapter *adapter = priv->adapter;
  1250. struct wlan_offset_value offval;
  1251. ssize_t pos = 0;
  1252. int ret;
  1253. unsigned long addr = get_zeroed_page(GFP_KERNEL);
  1254. char *buf = (char *)addr;
  1255. offval.offset = priv->bbp_offset;
  1256. offval.value = 0;
  1257. ret = libertas_prepare_and_send_command(priv,
  1258. cmd_bbp_reg_access, 0,
  1259. cmd_option_waitforrsp, 0, &offval);
  1260. mdelay(10);
  1261. pos += snprintf(buf+pos, len-pos, "BBP[0x%x] = 0x%08x\n",
  1262. priv->bbp_offset, adapter->offsetvalue.value);
  1263. ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
  1264. free_page(addr);
  1265. return ret;
  1266. }
  1267. static ssize_t libertas_rdbbp_write(struct file *file,
  1268. const char __user *userbuf,
  1269. size_t count, loff_t *ppos)
  1270. {
  1271. wlan_private *priv = file->private_data;
  1272. ssize_t res, buf_size;
  1273. unsigned long addr = get_zeroed_page(GFP_KERNEL);
  1274. char *buf = (char *)addr;
  1275. buf_size = min(count, len - 1);
  1276. if (copy_from_user(buf, userbuf, buf_size)) {
  1277. res = -EFAULT;
  1278. goto out_unlock;
  1279. }
  1280. priv->bbp_offset = simple_strtoul((char *)buf, NULL, 16);
  1281. res = count;
  1282. out_unlock:
  1283. free_page(addr);
  1284. return res;
  1285. }
  1286. static ssize_t libertas_wrbbp_write(struct file *file,
  1287. const char __user *userbuf,
  1288. size_t count, loff_t *ppos)
  1289. {
  1290. wlan_private *priv = file->private_data;
  1291. ssize_t res, buf_size;
  1292. u32 offset, value;
  1293. struct wlan_offset_value offval;
  1294. unsigned long addr = get_zeroed_page(GFP_KERNEL);
  1295. char *buf = (char *)addr;
  1296. buf_size = min(count, len - 1);
  1297. if (copy_from_user(buf, userbuf, buf_size)) {
  1298. res = -EFAULT;
  1299. goto out_unlock;
  1300. }
  1301. res = sscanf(buf, "%x %x", &offset, &value);
  1302. if (res != 2) {
  1303. res = -EFAULT;
  1304. goto out_unlock;
  1305. }
  1306. offval.offset = offset;
  1307. offval.value = value;
  1308. res = libertas_prepare_and_send_command(priv,
  1309. cmd_bbp_reg_access, 1,
  1310. cmd_option_waitforrsp, 0, &offval);
  1311. mdelay(10);
  1312. res = count;
  1313. out_unlock:
  1314. free_page(addr);
  1315. return res;
  1316. }
  1317. static ssize_t libertas_rdrf_read(struct file *file, char __user *userbuf,
  1318. size_t count, loff_t *ppos)
  1319. {
  1320. wlan_private *priv = file->private_data;
  1321. wlan_adapter *adapter = priv->adapter;
  1322. struct wlan_offset_value offval;
  1323. ssize_t pos = 0;
  1324. int ret;
  1325. unsigned long addr = get_zeroed_page(GFP_KERNEL);
  1326. char *buf = (char *)addr;
  1327. offval.offset = priv->rf_offset;
  1328. offval.value = 0;
  1329. ret = libertas_prepare_and_send_command(priv,
  1330. cmd_rf_reg_access, 0,
  1331. cmd_option_waitforrsp, 0, &offval);
  1332. mdelay(10);
  1333. pos += snprintf(buf+pos, len-pos, "RF[0x%x] = 0x%08x\n",
  1334. priv->rf_offset, adapter->offsetvalue.value);
  1335. ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
  1336. free_page(addr);
  1337. return ret;
  1338. }
  1339. static ssize_t libertas_rdrf_write(struct file *file,
  1340. const char __user *userbuf,
  1341. size_t count, loff_t *ppos)
  1342. {
  1343. wlan_private *priv = file->private_data;
  1344. ssize_t res, buf_size;
  1345. unsigned long addr = get_zeroed_page(GFP_KERNEL);
  1346. char *buf = (char *)addr;
  1347. buf_size = min(count, len - 1);
  1348. if (copy_from_user(buf, userbuf, buf_size)) {
  1349. res = -EFAULT;
  1350. goto out_unlock;
  1351. }
  1352. priv->rf_offset = simple_strtoul((char *)buf, NULL, 16);
  1353. res = count;
  1354. out_unlock:
  1355. free_page(addr);
  1356. return res;
  1357. }
  1358. static ssize_t libertas_wrrf_write(struct file *file,
  1359. const char __user *userbuf,
  1360. size_t count, loff_t *ppos)
  1361. {
  1362. wlan_private *priv = file->private_data;
  1363. ssize_t res, buf_size;
  1364. u32 offset, value;
  1365. struct wlan_offset_value offval;
  1366. unsigned long addr = get_zeroed_page(GFP_KERNEL);
  1367. char *buf = (char *)addr;
  1368. buf_size = min(count, len - 1);
  1369. if (copy_from_user(buf, userbuf, buf_size)) {
  1370. res = -EFAULT;
  1371. goto out_unlock;
  1372. }
  1373. res = sscanf(buf, "%x %x", &offset, &value);
  1374. if (res != 2) {
  1375. res = -EFAULT;
  1376. goto out_unlock;
  1377. }
  1378. offval.offset = offset;
  1379. offval.value = value;
  1380. res = libertas_prepare_and_send_command(priv,
  1381. cmd_rf_reg_access, 1,
  1382. cmd_option_waitforrsp, 0, &offval);
  1383. mdelay(10);
  1384. res = count;
  1385. out_unlock:
  1386. free_page(addr);
  1387. return res;
  1388. }
  1389. #define FOPS(fread, fwrite) { \
  1390. .owner = THIS_MODULE, \
  1391. .open = open_file_generic, \
  1392. .read = (fread), \
  1393. .write = (fwrite), \
  1394. }
  1395. struct libertas_debugfs_files {
  1396. char *name;
  1397. int perm;
  1398. struct file_operations fops;
  1399. };
  1400. static struct libertas_debugfs_files debugfs_files[] = {
  1401. { "info", 0444, FOPS(libertas_dev_info, write_file_dummy), },
  1402. { "getscantable", 0444, FOPS(libertas_getscantable,
  1403. write_file_dummy), },
  1404. { "sleepparams", 0644, FOPS(libertas_sleepparams_read,
  1405. libertas_sleepparams_write), },
  1406. { "extscan", 0600, FOPS(NULL, libertas_extscan), },
  1407. { "setuserscan", 0600, FOPS(NULL, libertas_setuserscan), },
  1408. };
  1409. static struct libertas_debugfs_files debugfs_events_files[] = {
  1410. {"low_rssi", 0644, FOPS(libertas_lowrssi_read,
  1411. libertas_lowrssi_write), },
  1412. {"low_snr", 0644, FOPS(libertas_lowsnr_read,
  1413. libertas_lowsnr_write), },
  1414. {"failure_count", 0644, FOPS(libertas_failcount_read,
  1415. libertas_failcount_write), },
  1416. {"beacon_missed", 0644, FOPS(libertas_bcnmiss_read,
  1417. libertas_bcnmiss_write), },
  1418. {"high_rssi", 0644, FOPS(libertas_highrssi_read,
  1419. libertas_highrssi_write), },
  1420. {"high_snr", 0644, FOPS(libertas_highsnr_read,
  1421. libertas_highsnr_write), },
  1422. };
  1423. static struct libertas_debugfs_files debugfs_regs_files[] = {
  1424. {"rdmac", 0644, FOPS(libertas_rdmac_read, libertas_rdmac_write), },
  1425. {"wrmac", 0600, FOPS(NULL, libertas_wrmac_write), },
  1426. {"rdbbp", 0644, FOPS(libertas_rdbbp_read, libertas_rdbbp_write), },
  1427. {"wrbbp", 0600, FOPS(NULL, libertas_wrbbp_write), },
  1428. {"rdrf", 0644, FOPS(libertas_rdrf_read, libertas_rdrf_write), },
  1429. {"wrrf", 0600, FOPS(NULL, libertas_wrrf_write), },
  1430. };
  1431. void libertas_debugfs_init(void)
  1432. {
  1433. if (!libertas_dir)
  1434. libertas_dir = debugfs_create_dir("libertas_wireless", NULL);
  1435. return;
  1436. }
  1437. void libertas_debugfs_remove(void)
  1438. {
  1439. if (libertas_dir)
  1440. debugfs_remove(libertas_dir);
  1441. return;
  1442. }
  1443. void libertas_debugfs_init_one(wlan_private *priv, struct net_device *dev)
  1444. {
  1445. int i;
  1446. struct libertas_debugfs_files *files;
  1447. if (!libertas_dir)
  1448. goto exit;
  1449. priv->debugfs_dir = debugfs_create_dir(dev->name, libertas_dir);
  1450. if (!priv->debugfs_dir)
  1451. goto exit;
  1452. for (i=0; i<ARRAY_SIZE(debugfs_files); i++) {
  1453. files = &debugfs_files[i];
  1454. priv->debugfs_files[i] = debugfs_create_file(files->name,
  1455. files->perm,
  1456. priv->debugfs_dir,
  1457. priv,
  1458. &files->fops);
  1459. }
  1460. priv->events_dir = debugfs_create_dir("subscribed_events", priv->debugfs_dir);
  1461. if (!priv->events_dir)
  1462. goto exit;
  1463. for (i=0; i<ARRAY_SIZE(debugfs_events_files); i++) {
  1464. files = &debugfs_events_files[i];
  1465. priv->debugfs_events_files[i] = debugfs_create_file(files->name,
  1466. files->perm,
  1467. priv->events_dir,
  1468. priv,
  1469. &files->fops);
  1470. }
  1471. priv->regs_dir = debugfs_create_dir("registers", priv->debugfs_dir);
  1472. if (!priv->regs_dir)
  1473. goto exit;
  1474. for (i=0; i<ARRAY_SIZE(debugfs_regs_files); i++) {
  1475. files = &debugfs_regs_files[i];
  1476. priv->debugfs_regs_files[i] = debugfs_create_file(files->name,
  1477. files->perm,
  1478. priv->regs_dir,
  1479. priv,
  1480. &files->fops);
  1481. }
  1482. #ifdef PROC_DEBUG
  1483. libertas_debug_init(priv, dev);
  1484. #endif
  1485. exit:
  1486. return;
  1487. }
  1488. void libertas_debugfs_remove_one(wlan_private *priv)
  1489. {
  1490. int i;
  1491. for(i=0; i<ARRAY_SIZE(debugfs_regs_files); i++)
  1492. debugfs_remove(priv->debugfs_regs_files[i]);
  1493. debugfs_remove(priv->regs_dir);
  1494. for(i=0; i<ARRAY_SIZE(debugfs_events_files); i++)
  1495. debugfs_remove(priv->debugfs_events_files[i]);
  1496. debugfs_remove(priv->events_dir);
  1497. #ifdef PROC_DEBUG
  1498. debugfs_remove(priv->debugfs_debug);
  1499. #endif
  1500. for(i=0; i<ARRAY_SIZE(debugfs_files); i++)
  1501. debugfs_remove(priv->debugfs_files[i]);
  1502. debugfs_remove(priv->debugfs_dir);
  1503. }
  1504. /* debug entry */
  1505. #ifdef PROC_DEBUG
  1506. #define item_size(n) (FIELD_SIZEOF(wlan_adapter, n))
  1507. #define item_addr(n) (offsetof(wlan_adapter, n))
  1508. struct debug_data {
  1509. char name[32];
  1510. u32 size;
  1511. size_t addr;
  1512. };
  1513. /* To debug any member of wlan_adapter, simply add one line here.
  1514. */
  1515. static struct debug_data items[] = {
  1516. {"intcounter", item_size(intcounter), item_addr(intcounter)},
  1517. {"psmode", item_size(psmode), item_addr(psmode)},
  1518. {"psstate", item_size(psstate), item_addr(psstate)},
  1519. };
  1520. static int num_of_items = ARRAY_SIZE(items);
  1521. /**
  1522. * @brief proc read function
  1523. *
  1524. * @param page pointer to buffer
  1525. * @param s read data starting position
  1526. * @param off offset
  1527. * @param cnt counter
  1528. * @param eof end of file flag
  1529. * @param data data to output
  1530. * @return number of output data
  1531. */
  1532. static ssize_t wlan_debugfs_read(struct file *file, char __user *userbuf,
  1533. size_t count, loff_t *ppos)
  1534. {
  1535. int val = 0;
  1536. size_t pos = 0;
  1537. ssize_t res;
  1538. char *p;
  1539. int i;
  1540. struct debug_data *d;
  1541. unsigned long addr = get_zeroed_page(GFP_KERNEL);
  1542. char *buf = (char *)addr;
  1543. p = buf;
  1544. d = (struct debug_data *)file->private_data;
  1545. for (i = 0; i < num_of_items; i++) {
  1546. if (d[i].size == 1)
  1547. val = *((u8 *) d[i].addr);
  1548. else if (d[i].size == 2)
  1549. val = *((u16 *) d[i].addr);
  1550. else if (d[i].size == 4)
  1551. val = *((u32 *) d[i].addr);
  1552. else if (d[i].size == 8)
  1553. val = *((u64 *) d[i].addr);
  1554. pos += sprintf(p + pos, "%s=%d\n", d[i].name, val);
  1555. }
  1556. res = simple_read_from_buffer(userbuf, count, ppos, p, pos);
  1557. free_page(addr);
  1558. return res;
  1559. }
  1560. /**
  1561. * @brief proc write function
  1562. *
  1563. * @param f file pointer
  1564. * @param buf pointer to data buffer
  1565. * @param cnt data number to write
  1566. * @param data data to write
  1567. * @return number of data
  1568. */
  1569. static ssize_t wlan_debugfs_write(struct file *f, const char __user *buf,
  1570. size_t cnt, loff_t *ppos)
  1571. {
  1572. int r, i;
  1573. char *pdata;
  1574. char *p;
  1575. char *p0;
  1576. char *p1;
  1577. char *p2;
  1578. struct debug_data *d = (struct debug_data *)f->private_data;
  1579. pdata = (char *)kmalloc(cnt, GFP_KERNEL);
  1580. if (pdata == NULL)
  1581. return 0;
  1582. if (copy_from_user(pdata, buf, cnt)) {
  1583. lbs_deb_debugfs("Copy from user failed\n");
  1584. kfree(pdata);
  1585. return 0;
  1586. }
  1587. p0 = pdata;
  1588. for (i = 0; i < num_of_items; i++) {
  1589. do {
  1590. p = strstr(p0, d[i].name);
  1591. if (p == NULL)
  1592. break;
  1593. p1 = strchr(p, '\n');
  1594. if (p1 == NULL)
  1595. break;
  1596. p0 = p1++;
  1597. p2 = strchr(p, '=');
  1598. if (!p2)
  1599. break;
  1600. p2++;
  1601. r = simple_strtoul(p2, NULL, 0);
  1602. if (d[i].size == 1)
  1603. *((u8 *) d[i].addr) = (u8) r;
  1604. else if (d[i].size == 2)
  1605. *((u16 *) d[i].addr) = (u16) r;
  1606. else if (d[i].size == 4)
  1607. *((u32 *) d[i].addr) = (u32) r;
  1608. else if (d[i].size == 8)
  1609. *((u64 *) d[i].addr) = (u64) r;
  1610. break;
  1611. } while (1);
  1612. }
  1613. kfree(pdata);
  1614. return (ssize_t)cnt;
  1615. }
  1616. static struct file_operations libertas_debug_fops = {
  1617. .owner = THIS_MODULE,
  1618. .open = open_file_generic,
  1619. .write = wlan_debugfs_write,
  1620. .read = wlan_debugfs_read,
  1621. };
  1622. /**
  1623. * @brief create debug proc file
  1624. *
  1625. * @param priv pointer wlan_private
  1626. * @param dev pointer net_device
  1627. * @return N/A
  1628. */
  1629. static void libertas_debug_init(wlan_private * priv, struct net_device *dev)
  1630. {
  1631. int i;
  1632. if (!priv->debugfs_dir)
  1633. return;
  1634. for (i = 0; i < num_of_items; i++)
  1635. items[i].addr += (size_t) priv->adapter;
  1636. priv->debugfs_debug = debugfs_create_file("debug", 0644,
  1637. priv->debugfs_dir, &items[0],
  1638. &libertas_debug_fops);
  1639. }
  1640. #endif