debugfs.c 49 KB

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