debugfs.c 49 KB

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