Thursday, May 10, 2018

disruptive technology Reactive Data/ACK jammer

and now comes the 7Up

  1. diff -Naur backports-4.4.2-1/defconfigs/ath9k-debug backports-4.4.2-1-modwifi/defconfigs/ath9k-debug
  2. --- backports-4.4.2-1/defconfigs/ath9k-debug    2016-02-18 22:41:34.000000000 +0100
  3. +++ backports-4.4.2-1-modwifi/defconfigs/ath9k-debug    2016-04-03 13:28:53.000000000 +0200
  4. @@ -17,3 +17,4 @@
  5.  CPTCFG_ATH9K_HTC=m
  6.  CPTCFG_ATH_DEBUG=y
  7.  CPTCFG_ATH9K_DEBUGFS=y
  8. +CPTCFG_ATH9K_HTC_DEBUGFS=y
  9. diff -Naur backports-4.4.2-1/drivers/net/wireless/ath/ath9k/htc_drv_debug.c backports-4.4.2-1-modwifi/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
  10. --- backports-4.4.2-1/drivers/net/wireless/ath/ath9k/htc_drv_debug.c    2016-02-18 22:41:35.000000000 +0100
  11. +++ backports-4.4.2-1-modwifi/drivers/net/wireless/ath/ath9k/htc_drv_debug.c    2016-04-03 13:28:54.000000000 +0200
  12. @@ -15,6 +15,61 @@
  13.   */
  14.  
  15.  #include "htc.h"
  16. +#include "hw.h"
  17. +
  18. +typedef u32 (*GetTimeFunc)(struct ath_hw *ah);
  19. +typedef void (*SetTimeFunc)(struct ath_hw *ah, u32 us);
  20. +
  21. +struct time_func {
  22. +   const char *name;
  23. +   GetTimeFunc getter;
  24. +   SetTimeFunc setter;
  25. +   const char *comments;
  26. +};
  27. +
  28. +struct time_func_context {
  29. +   struct time_func *timefunc;
  30. +   struct ath9k_htc_priv *htcpriv;
  31. +};
  32. +
  33. +struct time_func timefunctions[] =
  34. +{
  35. +   {"time_sifs",       ath9k_hw_get_sifs_time,     ath9k_hw_set_sifs_time,
  36. +       "SIFS time in microseconds (us) = Rx/Tx time = required time to wait after Rx."},
  37. +   {"time_slottime",   ath9k_hw_getslottime,       ath9k_hw_setslottime,
  38. +       "Slot time (aSlotTime) in microseconds (us) = slot time as used in backoff algo."},
  39. +   {"time_ack_timeout",    ath9k_hw_get_ack_timeout,   ath9k_hw_set_ack_timeout,
  40. +       "ACK timeout in microseconds (us)"},
  41. +   {"time_cts_timeout",    ath9k_hw_get_cts_timeout,   ath9k_hw_set_cts_timeout,
  42. +       "CTS timeout in microseconds (us)"},
  43. +   {"time_eifs",       ath9k_hw_get_eifs_timeout,  ath9k_hw_set_eifs_timeout,
  44. +       "EIFS time in microseconds (us)"}
  45. +};
  46. +
  47. +struct reg_ops registers[] = {
  48. +   // Backoff parameters
  49. +   {"ifs_cwmin_queue0",        AR_DLCL_IFS(0),     AR_D_LCL_IFS_CWMIN,
  50. +       "Backoff behaviour (queue 0): CW_MIN is the minimum number of time slots to wait."},
  51. +   {"ifs_cwmax_queue0",        AR_DLCL_IFS(0),     AR_D_LCL_IFS_CWMAX,
  52. +       "Backoff behaviour (queue 0): CW_MAX is the maximum number of time slots to wait."},
  53. +   {"ifs_aifs_queue0",     AR_DLCL_IFS(0),     AR_D_LCL_IFS_AIFS,
  54. +       "AIFS (in number of aSlotTime's) for queue 0."},
  55. +   // Disable backoff
  56. +   {"ifs_ignore_backoff",      AR_D_GBL_IFS_MISC,  AR_D_GBL_IFS_MISC_IGNORE_BACKOFF,
  57. +       "Ignore backoff (perhaps you also want to disable waiting for ACKs - see inject_noack)."},
  58. +   // Virtual and physical carrier sense
  59. +   {"ignore_virt_cs",      AR_DIAG_SW,     AR_DIAG_IGNORE_VIRT_CS,
  60. +       "Disables virtual carrier (cts/rts) sense when set."},
  61. +   {"force_channel_idle",      AR_DIAG_SW,     AR_DIAG_FORCE_CH_IDLE_HIGH,
  62. +       "Disables physical carrier sense (air clear) when set."},
  63. +   {"diag_rx_disable",     AR_DIAG_SW,     AR_DIAG_RX_DIS,
  64. +       "Block incoming frames from being sent to the firmware."},
  65. +   // Other
  66. +   {"diag_corrupt_fcs",        AR_DIAG_SW,     AR_DIAG_CORR_FCS,
  67. +       "If set, every transmitted packet is given an incorrect FCS."},
  68. +   {"cpu_freq_pll",        0x00056000,     -1,
  69. +       "Value = frequency * 4 + 5 (Setting of the Phase Locked Loop)."},
  70. +};
  71.  
  72.  static ssize_t read_file_tgt_int_stats(struct file *file, char __user *user_buf,
  73.                        size_t count, loff_t *ppos)
  74. @@ -398,6 +453,633 @@
  75.     .llseek = default_llseek,
  76.  };
  77.  
  78. +static ssize_t read_file_reg_ops(struct file *file, char __user *user_buf,
  79. +                size_t count, loff_t *ppos)
  80. +{
  81. +   struct reg_ops_instance *instance = file->private_data;
  82. +   struct ath9k_htc_priv *priv = instance->owner;
  83. +   struct reg_ops *regops = instance->regops;
  84. +   char buf[512];
  85. +   unsigned int len;
  86. +   unsigned int regval, mask;
  87. +
  88. +   ath9k_htc_ps_wakeup(priv);
  89. +   regval = REG_READ(priv->ah, regops->address);
  90. +   ath9k_htc_ps_restore(priv);
  91. +
  92. +   // apply mask, and shift according to mask
  93. +   regval &= regops->mask;
  94. +   mask = regops->mask;
  95. +   while ( (mask & 1) == 0) {
  96. +       mask >>= 1;
  97. +       regval >>= 1;
  98. +   }
  99. +
  100. +   len = snprintf(buf, sizeof(buf), "%s: %s\nValue: 0x%08X = %d (forced: %d)\n",
  101. +                   regops->name, regops->description, regval, regval,
  102. +                   !!(instance->valueset));
  103. +
  104. +   return simple_read_from_buffer(user_buf, count, ppos, buf, len);
  105. +}
  106. +
  107. +static ssize_t write_file_reg_ops(struct file *file, const char __user *user_buf,
  108. +                 size_t count, loff_t *ppos)
  109. +{
  110. +   struct reg_ops_instance *instance = file->private_data;
  111. +   struct ath9k_htc_priv *priv = instance->owner;
  112. +   struct reg_ops *regops = instance->regops;
  113. +   unsigned long val;
  114. +   char buf[32];
  115. +   ssize_t len;
  116. +   unsigned int mask, regval;
  117. +
  118. +   len = min(count, sizeof(buf) - 1);
  119. +   if (copy_from_user(buf, user_buf, len))
  120. +       return -EINVAL;
  121. +
  122. +   buf[len] = '\0';
  123. +   if (kstrtoul(buf, 0, &val))
  124. +       return -EINVAL;
  125. +
  126. +   // shift according to mask
  127. +   mask = regops->mask;
  128. +   while ( (mask & 1) == 0) {
  129. +       mask >>= 1;
  130. +       val <<= 1;
  131. +   }
  132. +
  133. +   // apply mask to assure we're not overwriting anything else
  134. +   val &= regops->mask;
  135. +
  136. +   ath9k_htc_ps_wakeup(priv);
  137. +   regval = REG_READ(priv->ah, regops->address);
  138. +   regval = (regval & ~regops->mask) | val;
  139. +   REG_WRITE(priv->ah, regops->address, regval);
  140. +   ath9k_htc_ps_restore(priv);
  141. +
  142. +   instance->valueset = 1;
  143. +   instance->value = val;
  144. +
  145. +   return count;
  146. +}
  147. +
  148. +static const struct file_operations fops_reg_ops = {
  149. +   .read = read_file_reg_ops,
  150. +   .write = write_file_reg_ops,
  151. +   .open = simple_open,
  152. +   .owner = THIS_MODULE,
  153. +   .llseek = default_llseek,
  154. +};
  155. +
  156. +static ssize_t read_file_dmesg(struct file *file, char __user *user_buf,
  157. +                  size_t count, loff_t *ppos)
  158. +{
  159. +   struct ath9k_htc_priv *priv = file->private_data;
  160. +   struct wmi_debugmsg_cmd cmd;
  161. +   struct wmi_debugmsg_resp cmd_rsp;
  162. +   /** ppos is the amount of data already read (maintained by caller) */
  163. +   int offset = *ppos;
  164. +   int ret;
  165. +
  166. +   /** Note: don't need to wake the WiFi MAC chip to get debug messages! */
  167. +   memset(&cmd, 0, sizeof(cmd));
  168. +   cmd.offset = cpu_to_be16(offset);
  169. +
  170. +   memset(&cmd_rsp, 0, sizeof(cmd_rsp));
  171. +   ret = ath9k_wmi_cmd(priv->wmi, WMI_DEBUGMSG_CMDID,
  172. +               (u8*)&cmd, sizeof(cmd),
  173. +               (u8*)&cmd_rsp, sizeof(cmd_rsp),
  174. +               HZ*2);
  175. +   if (ret) {
  176. +       printk("ath9k_htc %s: Something went wrong reading firmware dmesg (ret: %d, len: %d)\n",
  177. +           __FUNCTION__, ret, cmd_rsp.length);
  178. +       return -EIO;
  179. +   }
  180. +
  181. +   // Don't overflow user_buf
  182. +   if (count < cmd_rsp.length)
  183. +       cmd_rsp.length = count;
  184. +
  185. +   // Length of zero signifies EOF
  186. +   if (cmd_rsp.length != 0) {
  187. +       // Returns number of bytes that could not be copied
  188. +       if (copy_to_user(user_buf, cmd_rsp.buffer, cmd_rsp.length) != 0)
  189. +           return -EFAULT;
  190. +   }
  191. +
  192. +   *ppos += cmd_rsp.length;
  193. +   return cmd_rsp.length;
  194. +}
  195. +
  196. +static const struct file_operations fops_dmesg = {
  197. +   .read = read_file_dmesg,
  198. +   .open = simple_open,
  199. +   .owner = THIS_MODULE,
  200. +   .llseek = default_llseek,
  201. +};
  202. +
  203. +static ssize_t read_file_reactivejam(struct file *file, char __user *user_buf,
  204. +                size_t count, loff_t *ppos)
  205. +{
  206. +   char output[] = "Jam beacons and probe responses by writing the bssid and"
  207. +           "duration (in msecs) to this file as 'XX:XX:XX:XX:XX:XX,10000'.\n"
  208. +           "Duration of 0 means an infinite jam (device becomes unresponsive).\n";
  209. +   return simple_read_from_buffer(user_buf, count, ppos, output, sizeof(output));
  210. +}
  211. +
  212. +static ssize_t write_file_reactivejam(struct file *file, const char __user *user_buf,
  213. +                     size_t count, loff_t *ppos)
  214. +{
  215. +   struct ath9k_htc_priv *priv = file->private_data;
  216. +   struct wmi_reactivejam_cmd cmd;
  217. +   char buf[32] = {0}, reply[128] = {0};
  218. +   unsigned int intmac[6];
  219. +   unsigned int duration;
  220. +   int rval, len, i;
  221. +
  222. +   if (*ppos != 0) return 0;
  223. +
  224. +   // copy over input
  225. +   len = min(count, sizeof(buf) - 1);
  226. +   if (unlikely(copy_from_user(buf, user_buf, len))) {
  227. +       printk("ath9k_htc %s: copy_from_user failed\n", __FUNCTION__);
  228. +       return -EFAULT;
  229. +   }
  230. +   buf[sizeof(buf) - 1] = 0;
  231. +
  232. +   // parse input
  233. +   if ( 7 != sscanf(buf, "%x:%x:%x:%x:%x:%x,%u", &intmac[0], &intmac[1], &intmac[2],
  234. +       &intmac[3], &intmac[4], &intmac[5], &duration) ) {
  235. +       printk("ath9k_htc %s: invalid format\n", __FUNCTION__);
  236. +       return -EINVAL;
  237. +   }
  238. +
  239. +   // save input to command
  240. +   for (i = 0; i < 6; ++i)
  241. +       cmd.bssid[i] = intmac[i];
  242. +   cmd.mduration = cpu_to_be32(duration);
  243. +
  244. +   printk("ath9k_htc: Reactively jamming %x:%x:%x:%x:%x:%x ", cmd.bssid[0], cmd.bssid[1],
  245. +       cmd.bssid[2], cmd.bssid[3], cmd.bssid[4], cmd.bssid[5]);
  246. +   if (cmd.mduration == 0)
  247. +       printk("indefinitely (device will be unresponsive)\n");
  248. +   else
  249. +       printk("for %u miliseconds\n", duration);
  250. +
  251. +   // Blocking call! Wait for duration + 4 seconds. Response is an ASCII string. If the duration
  252. +   // is zero, firmware instantly replies, but will then become unresponsive (infinite jam).
  253. +   ath9k_htc_ps_wakeup(priv); 
  254. +   rval = ath9k_wmi_cmd(priv->wmi, WMI_REACTIVEJAM_CMDID,
  255. +           (u8*)&cmd, sizeof(cmd),
  256. +           (u8*)reply, sizeof(reply),
  257. +           HZ * (duration / 1000 + 4));
  258. +   ath9k_htc_ps_restore(priv);
  259. +
  260. +   if (unlikely(rval) && cmd.mduration != 0) {
  261. +       printk("ath9k_htc %s: WMI_REACTIVEJAM_CMD failed with %d\n", __FUNCTION__, rval);
  262. +       return -EBUSY;
  263. +   }
  264. +
  265. +   // Reset radio settings
  266. +   ath9k_hw_init_global_settings(priv->ah);
  267. +
  268. +   return count;
  269. +}
  270. +
  271. +static const struct file_operations fops_reactivejam = {
  272. +   .read = read_file_reactivejam,
  273. +   .write = write_file_reactivejam,
  274. +   .open = simple_open,
  275. +   .owner = THIS_MODULE,
  276. +   .llseek = default_llseek,
  277. +};
  278. +
  279. +static ssize_t read_file_constantjam(struct file *file, char __user *user_buf,
  280. +                  size_t count, loff_t *ppos)
  281. +{
  282. +   struct ath9k_htc_priv *priv = file->private_data;
  283. +   struct wmi_constantjam_resp cmd_rsp;
  284. +   struct wmi_constantjam_cmd cmd;
  285. +   char buf[128];
  286. +   unsigned int len;
  287. +   int rval;
  288. +  
  289. +   if (*ppos != 0) return 0;
  290. +
  291. +   memset(&cmd, 0, sizeof(cmd));
  292. +   cmd.request = CONSTJAM_STATUS;
  293. +
  294. +   // Send command to firmware
  295. +   rval = ath9k_wmi_cmd(priv->wmi, WMI_CONSTANTJAM_CMDID,
  296. +           (u8 *)&cmd, sizeof(cmd),
  297. +           (u8 *)&cmd_rsp, sizeof(cmd_rsp),
  298. +           HZ*2);
  299. +
  300. +   if (unlikely(rval)) {
  301. +       printk(">>>> WMI_CONSTANTJAM_CMD failed: %d\n", rval);
  302. +       return -EIO;
  303. +   }
  304. +
  305. +   len = snprintf(buf, sizeof(buf), "Constant jammer running: %d\n", cmd_rsp.status);
  306. +   return simple_read_from_buffer(user_buf, count, ppos, buf, len);
  307. +}
  308. +
  309. +static ssize_t write_file_constantjam(struct file *file, const char __user *user_buf,
  310. +                size_t count, loff_t *ppos)
  311. +{
  312. +   struct ath9k_htc_priv *priv = file->private_data;
  313. +   struct wmi_constantjam_resp cmd_rsp;
  314. +   struct wmi_constantjam_cmd cmd;
  315. +   unsigned long val;
  316. +   char buf[32];
  317. +   ssize_t len;
  318. +   int rval = 0;
  319. +
  320. +   if (*ppos != 0) return 0;
  321. +
  322. +   // parse input
  323. +   len = min(count, sizeof(buf) - 1);
  324. +   if (copy_from_user(buf, user_buf, len))
  325. +       return -EINVAL;
  326. +
  327. +   buf[len] = '\0';
  328. +   if (kstrtoul(buf, 0, &val))
  329. +       return -EINVAL;
  330. +
  331. +   memset(&cmd, 0, sizeof(cmd));
  332. +   // should we start or stop
  333. +   cmd.request = val == 0 ? CONSTJAM_STOP : CONSTJAM_START;
  334. +   // full continuous jamming (disable carrier sense, no timeouts between packets)
  335. +   cmd.conf_radio = 1;
  336. +   // length of packet used for jamming (pick a small one to avoid memory issues)
  337. +   cmd.len = cpu_to_be16(50);
  338. +
  339. +   // Send command to firmware
  340. +   ath9k_htc_ps_wakeup(priv);
  341. +   rval = ath9k_wmi_cmd(priv->wmi, WMI_CONSTANTJAM_CMDID,
  342. +           (u8 *)&cmd, sizeof(cmd),
  343. +           (u8 *)&cmd_rsp, sizeof(cmd_rsp),
  344. +           HZ*2);
  345. +
  346. +   if (unlikely(rval)) {
  347. +       printk(">>>> WMI_CONSTANTJAM_CMD failed: %d\n", rval);
  348. +       return -EIO;
  349. +   }
  350. +
  351. +   if (cmd.request == CONSTJAM_STOP)
  352. +       ath9k_htc_ps_restore(priv);
  353. +
  354. +   return count;
  355. +}
  356. +
  357. +static const struct file_operations fops_constantjam = {
  358. +   .read = read_file_constantjam,
  359. +   .write = write_file_constantjam,
  360. +   .open = simple_open,
  361. +   .owner = THIS_MODULE,
  362. +   .llseek = default_llseek,
  363. +};
  364. +
  365. +static ssize_t read_file_macaddr(struct file *file, char __user *user_buf,
  366. +                size_t count, loff_t *ppos)
  367. +{
  368. +   struct ath9k_htc_priv *priv = file->private_data;
  369. +   char buf[512];
  370. +   unsigned int len;
  371. +   unsigned int low, upper;
  372. +
  373. +   ath9k_htc_ps_wakeup(priv);
  374. +   low = REG_READ(priv->ah, AR_STA_ID0);
  375. +   upper = REG_READ(priv->ah, AR_STA_ID1) & AR_STA_ID1_SADH_MASK;
  376. +   ath9k_htc_ps_restore(priv);
  377. +
  378. +   len = snprintf(buf, sizeof(buf), "%02X:%02X:%02X:%02X:%02X:%02X\n",
  379. +           low & 0xFF, (low >> 8) & 0xFF, (low >> 16) & 0xFF,
  380. +           (low >> 24) & 0xFF, upper & 0xFF, (upper >> 8) & 0xFF);
  381. +   return simple_read_from_buffer(user_buf, count, ppos, buf, len);
  382. +}
  383. +
  384. +static ssize_t write_file_macaddr(struct file *file, const char __user *user_buf,
  385. +                 size_t count, loff_t *ppos)
  386. +{
  387. +   struct ath9k_htc_priv *priv = file->private_data;
  388. +   char buf[32];
  389. +   unsigned int mac[6];
  390. +   unsigned int low, upper;
  391. +   ssize_t len;
  392. +
  393. +   len = min(count, sizeof(buf) - 1);
  394. +   if (copy_from_user(buf, user_buf, len))
  395. +       return -EFAULT;
  396. +   buf[sizeof(buf) - 1] = 0;
  397. +
  398. +   if ( 6 != sscanf(buf, "%x:%x:%x:%x:%x:%x", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]) )
  399. +       return -EINVAL;
  400. +
  401. +   low = mac[0] | (mac[1] << 8) | (mac[2] << 16) | (mac[3] << 24);
  402. +   upper = mac[4] | (mac[5] << 8);
  403. +
  404. +   ath9k_htc_ps_wakeup(priv);
  405. +   REG_WRITE(priv->ah, AR_STA_ID0, low);
  406. +   REG_WRITE(priv->ah, AR_STA_ID1, upper & AR_STA_ID1_SADH_MASK);
  407. +   ath9k_htc_ps_restore(priv);
  408. +
  409. +   return count;
  410. +}
  411. +
  412. +static const struct file_operations fops_macaddr = {
  413. +   .read = read_file_macaddr,
  414. +   .write = write_file_macaddr,
  415. +   .open = simple_open,
  416. +   .owner = THIS_MODULE,
  417. +   .llseek = default_llseek,
  418. +};
  419. +
  420. +static ssize_t read_file_bssidmask(struct file *file, char __user *user_buf,
  421. +                  size_t count, loff_t *ppos)
  422. +{
  423. +   struct ath9k_htc_priv *priv = file->private_data;
  424. +   char buf[512];
  425. +   unsigned int len;
  426. +   unsigned int low, upper;       
  427. +
  428. +   ath9k_htc_ps_wakeup(priv);
  429. +   low = REG_READ(priv->ah, AR_BSSMSKL);
  430. +   upper = REG_READ(priv->ah, AR_BSSMSKU);
  431. +   ath9k_htc_ps_restore(priv);
  432. +
  433. +   len = snprintf(buf, sizeof(buf), "%02X:%02X:%02X:%02X:%02X:%02X\n",
  434. +           low & 0xFF, (low >> 8) & 0xFF, (low >> 16) & 0xFF,
  435. +           (low >> 24) & 0xFF, upper & 0xFF, (upper >> 8) & 0xFF);
  436. +   return simple_read_from_buffer(user_buf, count, ppos, buf, len);
  437. +}
  438. +
  439. +static ssize_t write_file_bssidmask(struct file *file, const char __user *user_buf,
  440. +                   size_t count, loff_t *ppos)
  441. +{
  442. +   struct ath9k_htc_priv *priv = file->private_data;
  443. +   char buf[32];
  444. +   unsigned int mask[6];
  445. +   unsigned int low, upper;
  446. +   ssize_t len;
  447. +
  448. +   len = min(count, sizeof(buf) - 1);
  449. +   if (copy_from_user(buf, user_buf, len))
  450. +       return -EFAULT;
  451. +   buf[sizeof(buf) - 1] = 0;
  452. +
  453. +   if ( 6 != sscanf(buf, "%x:%x:%x:%x:%x:%x", &mask[0], &mask[1], &mask[2], &mask[3], &mask[4], &mask[5]) )
  454. +       return -EINVAL;
  455. +
  456. +   low = mask[0] | (mask[1] << 8) | (mask[2] << 16) | (mask[3] << 24);
  457. +   upper = mask[4] | (mask[5] << 8);
  458. +
  459. +   ath9k_htc_ps_wakeup(priv);
  460. +   REG_WRITE(priv->ah, AR_BSSMSKL, low);
  461. +   REG_WRITE(priv->ah, AR_BSSMSKU, upper & AR_BSS_ID1_U16);
  462. +   ath9k_htc_ps_restore(priv);
  463. +
  464. +   return count;
  465. +}
  466. +
  467. +static const struct file_operations fops_bssidmask = {
  468. +   .read = read_file_bssidmask,
  469. +   .write = write_file_bssidmask,
  470. +   .open = simple_open,
  471. +   .owner = THIS_MODULE,
  472. +   .llseek = default_llseek,
  473. +};
  474. +
  475. +static ssize_t read_file_inject_noack(struct file *file, char __user *user_buf,
  476. +                size_t count, loff_t *ppos)
  477. +{
  478. +   struct ath9k_htc_priv *priv = file->private_data;
  479. +   char buf[64];
  480. +   int len;
  481. +
  482. +   len = snprintf(buf, sizeof(buf), "%d\n", priv->inject_noack);
  483. +   return simple_read_from_buffer(user_buf, count, ppos, buf, len);
  484. +}
  485. +
  486. +static ssize_t write_file_inject_noack(struct file *file, const char __user *user_buf,
  487. +                 size_t count, loff_t *ppos)
  488. +{
  489. +   struct ath9k_htc_priv *priv = file->private_data;
  490. +   char buf[32];
  491. +   unsigned long val;
  492. +   int len;
  493. +
  494. +   len = min(count, sizeof(buf) - 1);
  495. +   if (copy_from_user(buf, user_buf, len))
  496. +       return -EFAULT;
  497. +
  498. +   buf[len] = '\0';
  499. +   if (kstrtoul(buf, 0, &val))
  500. +       return -EINVAL;
  501. +
  502. +   priv->inject_noack = val;
  503. +
  504. +   return count;
  505. +}
  506. +
  507. +static const struct file_operations fops_inject_noack = {
  508. +   .read = read_file_inject_noack,
  509. +   .write = write_file_inject_noack,
  510. +   .open = simple_open,
  511. +   .owner = THIS_MODULE,
  512. +   .llseek = default_llseek,
  513. +};
  514. +
  515. +static ssize_t read_file_fastreply_packet(struct file *file, char __user *user_buf,
  516. +                  size_t count, loff_t *ppos)
  517. +{
  518. +   char buf[128] = "Write the reply packet used in fastreply_start to this file.\n";
  519. +   return simple_read_from_buffer(user_buf, count, ppos, buf, sizeof(buf));
  520. +}
  521. +
  522. +static ssize_t write_file_fastreply_packet(struct file *file,
  523. +   const char __user *user_buf, size_t count, loff_t *ppos)
  524. +{
  525. +   struct ath9k_htc_priv *priv = file->private_data;
  526. +   struct wmi_fastreply_cmd cmd;
  527. +   uint8_t buff[256];
  528. +   unsigned int offset;
  529. +   int reply, rval;
  530. +
  531. +   if (*ppos != 0) return 0;
  532. +
  533. +   //
  534. +   // 1. copy input
  535. +   //
  536. +
  537. +   if (count > 256) {
  538. +       printk("fastreply_packet: packet is too long (%zu)\n", count);
  539. +       return -EMSGSIZE;
  540. +   }
  541. +
  542. +   if (copy_from_user(buff, user_buf, count))
  543. +       return -EFAULT;
  544. +
  545. +   //
  546. +   // 2. send the buffer to the firmware
  547. +   //
  548. +      
  549. +   cmd.type = FASTREPLY_PKT;
  550. +   cmd.pkt.length = count;
  551. +
  552. +   ath9k_htc_ps_wakeup(priv);
  553. +
  554. +   for (offset = 0; offset < count; offset += sizeof(cmd.pkt.data))
  555. +   {
  556. +       cmd.pkt.offset = offset;
  557. +       cmd.pkt.datalen = min(40U, (unsigned int)(count - offset));
  558. +       memcpy(cmd.pkt.data, &buff[offset], cmd.pkt.datalen);
  559. +
  560. +       rval = ath9k_wmi_cmd(priv->wmi, WMI_FASTREPLY_CMDID,
  561. +               (u8*)&cmd, sizeof(cmd),
  562. +               (u8*)&reply, sizeof(reply),
  563. +               2*HZ);
  564. +
  565. +       if (unlikely(rval)) {
  566. +           printk("ath9k_htc %s: WMI_FASTREPLY_CMDID failed with %d\n", __FUNCTION__, rval);
  567. +           ath9k_htc_ps_restore(priv);
  568. +           return -EIO;
  569. +       }
  570. +   }
  571. +
  572. +   ath9k_htc_ps_restore(priv);
  573. +
  574. +   return count;
  575. +}
  576. +
  577. +
  578. +static const struct file_operations fops_fastreply_packet = {
  579. +   .read = read_file_fastreply_packet,
  580. +   .write = write_file_fastreply_packet,
  581. +   .open = simple_open,
  582. +   .owner = THIS_MODULE,
  583. +   .llseek = default_llseek,
  584. +};
  585. +
  586. +static ssize_t read_file_fastreply_start(struct file *file, char __user *user_buf,
  587. +                  size_t count, loff_t *ppos)
  588. +{
  589. +   char buf[128] = "Write the source MAC and duration ( 90:18:7c:6e:6b:20,10000 ) to this file.\n"
  590. +           "Set the reply packet using fastreply_packet.\n";
  591. +   return simple_read_from_buffer(user_buf, count, ppos, buf, sizeof(buf));
  592. +}
  593. +
  594. +static ssize_t write_file_fastreply_start(struct file *file,
  595. +   const char __user *user_buf, size_t count, loff_t *ppos)
  596. +{
  597. +   struct ath9k_htc_priv *priv = file->private_data;
  598. +   struct wmi_fastreply_cmd cmd;
  599. +   char input[256];
  600. +   int mac[6];
  601. +   unsigned int duration;
  602. +   int len, reply, rval, i;
  603. +
  604. +   if (*ppos != 0) return 0;
  605. +
  606. +   // 1. parse input
  607. +
  608. +   len = min(count, sizeof(input) - 1);
  609. +   if (copy_from_user(input, user_buf, len))
  610. +       return -EFAULT;
  611. +   input[len] = '\0';
  612. +
  613. +   if (sscanf(input, "%x:%x:%x:%x:%x:%x,%u", &mac[0], &mac[1], &mac[2],
  614. +       &mac[3], &mac[4], &mac[5], &duration) != 7) {
  615. +       printk("%s: sscanf parsing failed\n", __FUNCTION__);
  616. +       return -EINVAL;
  617. +   }
  618. +
  619. +   // 2. send the start command
  620. +  
  621. +   cmd.type = FASTREPLY_START;
  622. +   cmd.start.mduration = cpu_to_be32(duration);
  623. +   for (i = 0; i < 6; ++i)
  624. +       cmd.start.source[i] = mac[i];
  625. +
  626. +   ath9k_htc_ps_wakeup(priv);
  627. +  
  628. +   rval = ath9k_wmi_cmd(priv->wmi, WMI_FASTREPLY_CMDID,
  629. +           (u8*)&cmd, sizeof(cmd),
  630. +           (u8*)&reply, sizeof(reply),
  631. +           HZ * (duration / 1000 + 4));
  632. +
  633. +   ath9k_htc_ps_restore(priv);
  634. +
  635. +   if (unlikely(rval)) {
  636. +       printk("ath9k_htc %s: WMI_FASTREPLY_CMDID failed with %d\n", __FUNCTION__, rval);
  637. +       return -EBUSY;
  638. +   }
  639. +
  640. +   return count;
  641. +}
  642. +
  643. +static const struct file_operations fops_fastreply_start = {
  644. +   .read = read_file_fastreply_start,
  645. +   .write = write_file_fastreply_start,
  646. +   .open = simple_open,
  647. +   .owner = THIS_MODULE,
  648. +   .llseek = default_llseek,
  649. +};
  650. +
  651. +
  652. +static ssize_t read_file_timefunc(struct file *file, char __user *user_buf,
  653. +                 size_t count, loff_t *ppos)
  654. +{
  655. +   struct time_func_context *context = file->private_data;
  656. +   struct time_func *timefunc = context->timefunc;
  657. +   struct ath9k_htc_priv *priv = context->htcpriv;
  658. +   char buf[512];
  659. +   unsigned int len, val;
  660. +
  661. +   // FIXME: Is the wakeup/restore call needed?
  662. +   ath9k_htc_ps_wakeup(priv);
  663. +   val = timefunc->getter(priv->ah);
  664. +   ath9k_htc_ps_restore(priv);
  665. +
  666. +   len = snprintf(buf, sizeof(buf), "%s: %s\nValue: 0x%08X = %d\n",
  667. +       timefunc->name, timefunc->comments, val, val);
  668. +   return simple_read_from_buffer(user_buf, count, ppos, buf, len);
  669. +}
  670. +
  671. +static ssize_t write_file_timefunc(struct file *file, const char __user *user_buf,
  672. +                  size_t count, loff_t *ppos)
  673. +{
  674. +   struct time_func_context *context = file->private_data;
  675. +   struct time_func *timefunc = context->timefunc;
  676. +   struct ath9k_htc_priv *priv = context->htcpriv;
  677. +   unsigned long val;
  678. +   char buf[32];
  679. +   ssize_t len;
  680. +
  681. +   len = min(count, sizeof(buf) - 1);
  682. +   if (copy_from_user(buf, user_buf, len))
  683. +       return -EINVAL;
  684. +
  685. +   buf[len] = '\0';
  686. +   if (kstrtoul(buf, 0, &val))
  687. +       return -EINVAL;
  688. +
  689. +   // FIXME: Is the wakeup/restore call needed?
  690. +   ath9k_htc_ps_wakeup(priv);
  691. +   timefunc->setter(priv->ah, (u32)val);
  692. +   ath9k_htc_ps_restore(priv);
  693. +
  694. +   return count;
  695. +}
  696. +
  697. +static const struct file_operations fops_timefunc = {
  698. +   .read = read_file_timefunc,
  699. +   .write = write_file_timefunc,
  700. +   .open = simple_open,
  701. +   .owner = THIS_MODULE,
  702. +   .llseek = default_llseek,
  703. +};
  704. +
  705.  /* Ethtool support for get-stats */
  706.  #define AMKSTR(nm) #nm "_BE", #nm "_BK", #nm "_VI", #nm "_VO"
  707.  static const char ath9k_htc_gstrings_stats[][ETH_GSTRING_LEN] = {
  708. @@ -488,6 +1170,8 @@
  709.  {
  710.     struct ath_common *common = ath9k_hw_common(ah);
  711.     struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
  712. +   struct reg_ops_instance *previnstance;
  713. +   int i;
  714.  
  715.     priv->debug.debugfs_phy = debugfs_create_dir(KBUILD_MODNAME,
  716.                          priv->hw->wiphy->debugfsdir);
  717. @@ -516,9 +1200,79 @@
  718.                 priv, &fops_queue);
  719.     debugfs_create_file("debug", S_IRUSR | S_IWUSR, priv->debug.debugfs_phy,
  720.                 priv, &fops_debug);
  721. +   debugfs_create_file("dmesg", S_IRUSR, priv->debug.debugfs_phy,
  722. +               priv, &fops_dmesg);
  723. +   debugfs_create_file("reactivejam", S_IRUSR, priv->debug.debugfs_phy,
  724. +               priv, &fops_reactivejam);
  725. +   debugfs_create_file("constantjam", S_IRUSR, priv->debug.debugfs_phy,
  726. +               priv, &fops_constantjam);
  727. +   debugfs_create_file("fastreply_packet", S_IRUSR | S_IWUSR,
  728. +               priv->debug.debugfs_phy, priv, &fops_fastreply_packet);
  729. +   debugfs_create_file("fastreply_start", S_IRUSR | S_IWUSR,
  730. +               priv->debug.debugfs_phy, priv, &fops_fastreply_start);
  731. +   debugfs_create_file("macaddr", S_IRUSR | S_IWUSR, priv->debug.debugfs_phy,
  732. +               priv, &fops_macaddr);
  733. +   debugfs_create_file("bssidmask", S_IRUSR | S_IWUSR, priv->debug.debugfs_phy,
  734. +               priv, &fops_bssidmask);
  735. +   debugfs_create_file("inject_noack", S_IRUSR | S_IWUSR,
  736. +               priv->debug.debugfs_phy, priv, &fops_inject_noack);
  737.  
  738.     ath9k_cmn_debug_base_eeprom(priv->debug.debugfs_phy, priv->ah);
  739.     ath9k_cmn_debug_modal_eeprom(priv->debug.debugfs_phy, priv->ah);
  740.  
  741. +   //
  742. +   // Read/write access to registers
  743. +   //
  744. +
  745. +   priv->debug.debugfs_phy_regs = debugfs_create_dir("registers", priv->debug.debugfs_phy);
  746. +   if (!priv->debug.debugfs_phy_regs)
  747. +       return -ENOMEM;
  748. +
  749. +   previnstance = NULL;
  750. +   for (i = 0; i < sizeof(registers) / sizeof(registers[0]); ++i)
  751. +   {
  752. +       struct reg_ops *regops = &registers[i];
  753. +       struct reg_ops_instance *instance;
  754. +
  755. +       // Allocated linked list is freed in ath9k_hw_deinit
  756. +       instance = kzalloc(sizeof(struct reg_ops_instance), GFP_KERNEL);
  757. +       if (!instance) return -ENOMEM;
  758. +
  759. +       instance->regops = regops;
  760. +       instance->owner = priv;
  761. +
  762. +       instance->valueset = 0;
  763. +       instance->value = 0;
  764. +       instance->next = previnstance;
  765. +
  766. +       // Read/write access using general functions
  767. +       debugfs_create_file(regops->name, S_IRUSR|S_IWUSR,
  768. +           priv->debug.debugfs_phy_regs, instance, &fops_reg_ops);
  769. +
  770. +       previnstance = instance;
  771. +   }
  772. +  
  773. +   priv->ah->modified_registers = previnstance;
  774. +  
  775. +
  776. +   //
  777. +   // Time functions
  778. +   //
  779. +
  780. +   for (i = 0; i < sizeof(timefunctions) / sizeof(timefunctions[0]); ++i)
  781. +   {
  782. +       // Allocate a context
  783. +       struct time_func_context *context;
  784. +       context = devm_kzalloc(priv->dev, sizeof(struct time_func_context), GFP_KERNEL);
  785. +       if (!context) return -ENOMEM;
  786. +
  787. +       context->timefunc = &timefunctions[i];
  788. +       context->htcpriv = priv;
  789. +
  790. +       // Read/write access using general functions
  791. +       debugfs_create_file(context->timefunc->name, S_IRUSR|S_IWUSR,
  792. +           priv->debug.debugfs_phy, context, &fops_timefunc);
  793. +   }
  794. +
  795.     return 0;
  796.  }
  797. diff -Naur backports-4.4.2-1/drivers/net/wireless/ath/ath9k/htc_drv_init.c backports-4.4.2-1-modwifi/drivers/net/wireless/ath/ath9k/htc_drv_init.c
  798. --- backports-4.4.2-1/drivers/net/wireless/ath/ath9k/htc_drv_init.c 2016-02-18 22:41:35.000000000 +0100
  799. +++ backports-4.4.2-1-modwifi/drivers/net/wireless/ath/ath9k/htc_drv_init.c 2016-04-03 13:28:54.000000000 +0200
  800. @@ -99,6 +99,18 @@
  801.  
  802.  static void ath9k_deinit_priv(struct ath9k_htc_priv *priv)
  803.  {
  804. +   if (priv->debug.debugfs_phy_regs)
  805. +       debugfs_remove(priv->debug.debugfs_phy_regs);
  806. +   priv->debug.debugfs_phy_regs = NULL;
  807. +
  808. +   if (priv->debug.debugfs_phy)
  809. +       debugfs_remove(priv->debug.debugfs_phy);
  810. +   priv->debug.debugfs_phy = NULL;
  811. +
  812. +   if (priv->hw->wiphy->debugfsdir)
  813. +       debugfs_remove(priv->hw->wiphy->debugfsdir);
  814. +   priv->hw->wiphy->debugfsdir = NULL;
  815. +
  816.     ath9k_hw_deinit(priv->ah);
  817.     kfree(priv->ah);
  818.     priv->ah = NULL;
  819. diff -Naur backports-4.4.2-1/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c backports-4.4.2-1-modwifi/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
  820. --- backports-4.4.2-1/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c 2016-02-18 22:41:36.000000000 +0100
  821. +++ backports-4.4.2-1-modwifi/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c 2016-04-03 13:28:54.000000000 +0200
  822. @@ -211,6 +211,7 @@
  823.     return error;
  824.  }
  825.  
  826. +/** Used to handle management and injected frames */
  827.  static void ath9k_htc_tx_mgmt(struct ath9k_htc_priv *priv,
  828.                   struct ath9k_htc_vif *avp,
  829.                   struct sk_buff *skb,
  830. @@ -222,6 +223,7 @@
  831.     struct tx_mgmt_hdr mgmt_hdr;
  832.     struct ath9k_htc_tx_ctl *tx_ctl;
  833.     u8 *tx_fhdr;
  834. +   u8 flags = 0;
  835.  
  836.     tx_ctl = HTC_SKB_CB(skb);
  837.     hdr = (struct ieee80211_hdr *) skb->data;
  838. @@ -238,12 +240,19 @@
  839.         mgmt->u.probe_resp.timestamp = avp->tsfadjust;
  840.     }
  841.  
  842. +   /* Should firmware assign sequence number */
  843. +   if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)
  844. +       flags |= ATH9K_HTC_TX_ASSIGN_SEQ;
  845. +   /* Don't retransmit injected packets if requested so */
  846. +   if (unlikely(priv->inject_noack && (tx_info->flags & IEEE80211_TX_CTL_INJECTED)))
  847. +       flags |= ATH9K_HTC_TX_NO_ACK;
  848. +
  849.     tx_ctl->type = ATH9K_HTC_MGMT;
  850.  
  851.     mgmt_hdr.node_idx = sta_idx;
  852.     mgmt_hdr.vif_idx = vif_idx;
  853.     mgmt_hdr.tidno = 0;
  854. -   mgmt_hdr.flags = 0;
  855. +   mgmt_hdr.flags = flags;
  856.     mgmt_hdr.cookie = slot;
  857.  
  858.     mgmt_hdr.key_type = ath9k_cmn_get_hw_crypto_keytype(skb);
  859. @@ -302,6 +311,13 @@
  860.         tx_hdr.tidno = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
  861.     }
  862.  
  863. +   /* Should firmware assign sequence number */
  864. +   if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)
  865. +       flags |= ATH9K_HTC_TX_ASSIGN_SEQ;
  866. +   /* Don't retransmit injected packets if requested so */
  867. +   if (unlikely(priv->inject_noack && (tx_info->flags & IEEE80211_TX_CTL_INJECTED)))
  868. +       flags |= ATH9K_HTC_TX_NO_ACK;
  869. +
  870.     /* Check for RTS protection */
  871.     if (priv->hw->wiphy->rts_threshold != (u32) -1)
  872.         if (skb->len > priv->hw->wiphy->rts_threshold)
  873. @@ -373,12 +389,11 @@
  874.         sta_idx = priv->vif_sta_pos[vif_idx];
  875.     }
  876.  
  877. -   if (ieee80211_is_data(hdr->frame_control))
  878. -       ath9k_htc_tx_data(priv, vif, skb,
  879. -                 sta_idx, vif_idx, slot, is_cab);
  880. +   /** Treat injected frames as management frames to avoid modifications to them */
  881. +   if (ieee80211_is_data(hdr->frame_control) && !(tx_info->flags & IEEE80211_TX_CTL_INJECTED))
  882. +       ath9k_htc_tx_data(priv, vif, skb, sta_idx, vif_idx, slot, is_cab);
  883.     else
  884. -       ath9k_htc_tx_mgmt(priv, avp, skb,
  885. -                 sta_idx, vif_idx, slot);
  886. +       ath9k_htc_tx_mgmt(priv, avp, skb, sta_idx, vif_idx, slot);
  887.  
  888.  
  889.     return htc_send(priv->htc, skb);
  890. diff -Naur backports-4.4.2-1/drivers/net/wireless/ath/ath9k/htc.h backports-4.4.2-1-modwifi/drivers/net/wireless/ath/ath9k/htc.h
  891. --- backports-4.4.2-1/drivers/net/wireless/ath/ath9k/htc.h  2016-02-18 22:41:35.000000000 +0100
  892. +++ backports-4.4.2-1-modwifi/drivers/net/wireless/ath/ath9k/htc.h  2016-04-03 13:28:54.000000000 +0200
  893. @@ -69,6 +69,8 @@
  894.  
  895.  #define ATH9K_HTC_TX_CTSONLY      0x1
  896.  #define ATH9K_HTC_TX_RTSCTS       0x2
  897. +#define ATH9K_HTC_TX_ASSIGN_SEQ   0x10
  898. +#define ATH9K_HTC_TX_NO_ACK       0x20
  899.  
  900.  struct tx_frame_hdr {
  901.     u8 data_type;
  902. @@ -357,6 +359,7 @@
  903.  
  904.  struct ath9k_debug {
  905.     struct dentry *debugfs_phy;
  906. +   struct dentry *debugfs_phy_regs;
  907.     struct ath_tx_stats tx_stats;
  908.     struct ath_rx_stats rx_stats;
  909.     struct ath_skbrx_stats skbrx_stats;
  910. @@ -510,6 +513,9 @@
  911.     bool ps_enabled;
  912.     bool ps_idle;
  913.  
  914. +   /** If set, injected packets are never retransmitted (not waiting for ACK) */
  915. +   u8 inject_noack;
  916. +
  917.  #ifdef CPTCFG_MAC80211_LEDS
  918.     enum led_brightness brightness;
  919.     bool led_registered;
  920. diff -Naur backports-4.4.2-1/drivers/net/wireless/ath/ath9k/hw.c backports-4.4.2-1-modwifi/drivers/net/wireless/ath/ath9k/hw.c
  921. --- backports-4.4.2-1/drivers/net/wireless/ath/ath9k/hw.c   2016-02-18 22:41:36.000000000 +0100
  922. +++ backports-4.4.2-1-modwifi/drivers/net/wireless/ath/ath9k/hw.c   2016-04-03 13:28:54.000000000 +0200
  923. @@ -67,6 +67,7 @@
  924.     common->clockrate = clockrate;
  925.  }
  926.  
  927. +/** This is the clockrate of the wireless chip (not the chip running the firmware for ath9k_htc) */
  928.  static u32 ath9k_hw_mac_to_clks(struct ath_hw *ah, u32 usecs)
  929.  {
  930.     struct ath_common *common = ath9k_hw_common(ah);
  931. @@ -74,6 +75,17 @@
  932.     return usecs * common->clockrate;
  933.  }
  934.  
  935. +/** This is the clockrate of the wireless chip (not the chip running the firmware for ath9k_htc) */
  936. +static u32 ath9k_hw_mac_to_usecs(struct ath_hw *ah, u32 clks)
  937. +{
  938. +   struct ath_common *common = ath9k_hw_common(ah);
  939. +
  940. +   if (common->clockrate == 0)
  941. +       return 0xFFFFFFFF;
  942. +
  943. +   return clks / common->clockrate;
  944. +}
  945. +
  946.  bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout)
  947.  {
  948.     int i;
  949. @@ -246,6 +258,24 @@
  950.         centers->synth_center + (extoff * HT40_CHANNEL_CENTER_SHIFT);
  951.  }
  952.  
  953. +static void ath9k_restore_registers(struct ath_hw *ah)
  954. +{
  955. +   struct reg_ops_instance *saved_reg = ah->modified_registers;
  956. +   int regval;
  957. +
  958. +   while (saved_reg != NULL)
  959. +   {
  960. +       if (saved_reg->valueset)
  961. +       {
  962. +           regval = REG_READ(ah, saved_reg->regops->address);
  963. +           regval = (regval & ~saved_reg->regops->mask) | saved_reg->value;
  964. +           REG_WRITE(ah, saved_reg->regops->address, regval);
  965. +       }
  966. +
  967. +       saved_reg = saved_reg->next;
  968. +   }
  969. +}
  970. +
  971.  /******************/
  972.  /* Chip Revisions */
  973.  /******************/
  974. @@ -972,33 +1002,78 @@
  975.     }
  976.  }
  977.  
  978. -static void ath9k_hw_set_sifs_time(struct ath_hw *ah, u32 us)
  979. +void ath9k_hw_set_sifs_time(struct ath_hw *ah, u32 us)
  980.  {
  981.     u32 val = ath9k_hw_mac_to_clks(ah, us - 2);
  982. -   val = min(val, (u32) 0xFFFF);
  983. +   val &= AR_D_GBL_IFS_SIFS_M;
  984.     REG_WRITE(ah, AR_D_GBL_IFS_SIFS, val);
  985.  }
  986. +EXPORT_SYMBOL(ath9k_hw_set_sifs_time);
  987.  
  988.  void ath9k_hw_setslottime(struct ath_hw *ah, u32 us)
  989.  {
  990.     u32 val = ath9k_hw_mac_to_clks(ah, us);
  991. -   val = min(val, (u32) 0xFFFF);
  992. +   val &= AR_D_GBL_IFS_SLOT_M;
  993.     REG_WRITE(ah, AR_D_GBL_IFS_SLOT, val);
  994.  }
  995. +EXPORT_SYMBOL(ath9k_hw_setslottime);
  996.  
  997.  void ath9k_hw_set_ack_timeout(struct ath_hw *ah, u32 us)
  998.  {
  999.     u32 val = ath9k_hw_mac_to_clks(ah, us);
  1000. -   val = min(val, (u32) MS(0xFFFFFFFF, AR_TIME_OUT_ACK));
  1001.     REG_RMW_FIELD(ah, AR_TIME_OUT, AR_TIME_OUT_ACK, val);
  1002.  }
  1003. +EXPORT_SYMBOL(ath9k_hw_set_ack_timeout);
  1004.  
  1005.  void ath9k_hw_set_cts_timeout(struct ath_hw *ah, u32 us)
  1006.  {
  1007.     u32 val = ath9k_hw_mac_to_clks(ah, us);
  1008. -   val = min(val, (u32) MS(0xFFFFFFFF, AR_TIME_OUT_CTS));
  1009.     REG_RMW_FIELD(ah, AR_TIME_OUT, AR_TIME_OUT_CTS, val);
  1010.  }
  1011. +EXPORT_SYMBOL(ath9k_hw_set_cts_timeout);
  1012. +
  1013. +void ath9k_hw_set_eifs_timeout(struct ath_hw *ah, u32 us)
  1014. +{
  1015. +   u32 val = ath9k_hw_mac_to_clks(ah, us);
  1016. +   val &= AR_D_GBL_IFS_EIFS;
  1017. +   REG_WRITE(ah, AR_D_GBL_IFS_EIFS, val);
  1018. +}
  1019. +EXPORT_SYMBOL(ath9k_hw_set_eifs_timeout);
  1020. +
  1021. +u32 ath9k_hw_get_sifs_time(struct ath_hw *ah)
  1022. +{
  1023. +   u32 val = REG_READ(ah, AR_D_GBL_IFS_SIFS) & AR_D_GBL_IFS_SIFS_M;
  1024. +   return ath9k_hw_mac_to_usecs(ah, val) + 2;
  1025. +}
  1026. +EXPORT_SYMBOL(ath9k_hw_get_sifs_time);
  1027. +
  1028. +u32 ath9k_hw_getslottime(struct ath_hw *ah)
  1029. +{
  1030. +   u32 val = REG_READ(ah, AR_D_GBL_IFS_SLOT) & AR_D_GBL_IFS_SLOT_M;
  1031. +   return ath9k_hw_mac_to_usecs(ah, val);
  1032. +}
  1033. +EXPORT_SYMBOL(ath9k_hw_getslottime);
  1034. +
  1035. +u32 ath9k_hw_get_ack_timeout(struct ath_hw *ah)
  1036. +{
  1037. +   u32 val = MS(REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_ACK);
  1038. +   return ath9k_hw_mac_to_usecs(ah, val);
  1039. +}
  1040. +EXPORT_SYMBOL(ath9k_hw_get_ack_timeout);
  1041. +
  1042. +u32 ath9k_hw_get_cts_timeout(struct ath_hw *ah)
  1043. +{
  1044. +   u32 val = MS(REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_CTS);
  1045. +   return ath9k_hw_mac_to_usecs(ah, val);
  1046. +}
  1047. +EXPORT_SYMBOL(ath9k_hw_get_cts_timeout);
  1048. +
  1049. +u32 ath9k_hw_get_eifs_timeout(struct ath_hw *ah)
  1050. +{
  1051. +   u32 val = REG_READ(ah, AR_D_GBL_IFS_EIFS) & AR_D_GBL_IFS_EIFS_M;
  1052. +   return ath9k_hw_mac_to_usecs(ah, val);
  1053. +}
  1054. +EXPORT_SYMBOL(ath9k_hw_get_eifs_timeout);
  1055.  
  1056.  static bool ath9k_hw_set_global_txtimeout(struct ath_hw *ah, u32 tu)
  1057.  {
  1058. @@ -2025,6 +2100,8 @@
  1059.     if (AR_SREV_9565(ah) && common->bt_ant_diversity)
  1060.         REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, AR_BTCOEX_WL_LNADIV_FORCE_ON);
  1061.  
  1062. +   ath9k_restore_registers(ah);
  1063. +
  1064.     if (ah->hw->conf.radar_enabled) {
  1065.         /* set HW specific DFS configuration */
  1066.         ah->radar_conf.ext_channel = IS_CHAN_HT40(chan);
  1067. @@ -2173,6 +2250,8 @@
  1068.  
  1069.     REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
  1070.  
  1071. +   ath9k_restore_registers(ah);
  1072. +
  1073.     return true;
  1074.  }
  1075.  
  1076. diff -Naur backports-4.4.2-1/drivers/net/wireless/ath/ath9k/hw.h backports-4.4.2-1-modwifi/drivers/net/wireless/ath/ath9k/hw.h
  1077. --- backports-4.4.2-1/drivers/net/wireless/ath/ath9k/hw.h   2016-02-18 22:41:36.000000000 +0100
  1078. +++ backports-4.4.2-1-modwifi/drivers/net/wireless/ath/ath9k/hw.h   2016-04-03 13:28:54.000000000 +0200
  1079. @@ -761,6 +761,40 @@
  1080.     TX_CL_CAL         = BIT(2),
  1081.  };
  1082.  
  1083. +/**
  1084. + * reg_ops - describes one specific functionality of a particular register
  1085. + *
  1086. + * @name: name of the register as used in debugfs
  1087. + * @address: memory address of the register
  1088. + * @mask: mask for the specific functionality we are exposing. One single addresses
  1089. + *        may have multiple reg_ops, one for each mask/functionality.
  1090. + * @description: human readable description of the functionality
  1091. + */
  1092. +struct reg_ops {
  1093. +   const char *name;
  1094. +   unsigned int address;
  1095. +   unsigned int mask;
  1096. +   const char *description;
  1097. +};
  1098. +
  1099. +/**
  1100. + * reg_ops_instance - describes a specific configuration of a reg_ops register
  1101. + *
  1102. + * @regops: the register functionality we are referencing
  1103. + * @valueset: did the user write a custom value to this register?
  1104. + * @value: the value the user wrote to the register
  1105. + * @owner: the interface on which the custom value was set
  1106. + *
  1107. + * @next: pointer to next reg_ops_instance, to create linked lists
  1108. + */
  1109. +struct reg_ops_instance {
  1110. +   struct reg_ops *regops;
  1111. +   char valueset;
  1112. +   unsigned int value;
  1113. +   struct ath9k_htc_priv *owner;
  1114. +   struct reg_ops_instance *next;
  1115. +};
  1116. +
  1117.  /* ah_flags */
  1118.  #define AH_USE_EEPROM   0x1
  1119.  #define AH_UNPLUGGED    0x2 /* The card has been physically removed. */
  1120. @@ -972,6 +1006,9 @@
  1121.  
  1122.     struct ath_dynack dynack;
  1123.  
  1124. +   /** Linked list of (possibly) manually overwritten registers */
  1125. +   struct reg_ops_instance *modified_registers;
  1126. +
  1127.     bool tpc_enabled;
  1128.     u8 tx_power[Ar5416RateSize];
  1129.     u8 tx_power_stbc[Ar5416RateSize];
  1130. @@ -1066,6 +1103,18 @@
  1131.  
  1132.  bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode);
  1133.  
  1134. +void ath9k_hw_set_sifs_time(struct ath_hw *ah, u32 us);
  1135. +void ath9k_hw_setslottime(struct ath_hw *ah, u32 us);
  1136. +void ath9k_hw_set_ack_timeout(struct ath_hw *ah, u32 us);
  1137. +void ath9k_hw_set_cts_timeout(struct ath_hw *ah, u32 us);
  1138. +void ath9k_hw_set_eifs_timeout(struct ath_hw *ah, u32 us);
  1139. +
  1140. +u32 ath9k_hw_get_sifs_time(struct ath_hw *ah);
  1141. +u32 ath9k_hw_getslottime(struct ath_hw *ah);
  1142. +u32 ath9k_hw_get_ack_timeout(struct ath_hw *ah);
  1143. +u32 ath9k_hw_get_cts_timeout(struct ath_hw *ah);
  1144. +u32 ath9k_hw_get_eifs_timeout(struct ath_hw *ah);
  1145. +
  1146.  /* Generic hw timer primitives */
  1147.  struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah,
  1148.                       void (*trigger)(void *),
  1149. diff -Naur backports-4.4.2-1/drivers/net/wireless/ath/ath9k/Kconfig backports-4.4.2-1-modwifi/drivers/net/wireless/ath/ath9k/Kconfig
  1150. --- backports-4.4.2-1/drivers/net/wireless/ath/ath9k/Kconfig    2016-02-18 22:41:36.000000000 +0100
  1151. +++ backports-4.4.2-1-modwifi/drivers/net/wireless/ath/ath9k/Kconfig    2016-04-03 13:28:55.000000000 +0200
  1152. @@ -167,6 +167,7 @@
  1153.         select BPAUTO_LEDS_CLASS
  1154.         select BPAUTO_NEW_LEDS
  1155.         select ATH9K_COMMON
  1156. +       select ATH9K_HTC_DEBUGFS
  1157.         ---help---
  1158.      Support for Atheros HTC based cards.
  1159.      Chipsets supported: AR9271
  1160. @@ -177,6 +178,6 @@
  1161.  
  1162.  config ATH9K_HTC_DEBUGFS
  1163.     bool "Atheros ath9k_htc debugging"
  1164. -   depends on ATH9K_HTC && DEBUG_FS
  1165. +   depends on DEBUG_FS
  1166.     ---help---
  1167.       Say Y, if you need access to ath9k_htc's statistics.
  1168. diff -Naur backports-4.4.2-1/drivers/net/wireless/ath/ath9k/wmi.c backports-4.4.2-1-modwifi/drivers/net/wireless/ath/ath9k/wmi.c
  1169. --- backports-4.4.2-1/drivers/net/wireless/ath/ath9k/wmi.c  2016-02-18 22:41:35.000000000 +0100
  1170. +++ backports-4.4.2-1-modwifi/drivers/net/wireless/ath/ath9k/wmi.c  2016-04-03 13:28:54.000000000 +0200
  1171. @@ -83,6 +83,14 @@
  1172.         return "WMI_RX_STATS_CMDID";
  1173.     case WMI_BITRATE_MASK_CMDID:
  1174.         return "WMI_BITRATE_MASK_CMDID";
  1175. +   case WMI_DEBUGMSG_CMDID:
  1176. +       return "WMI_DEBUGMSG_CMDID";
  1177. +   case WMI_REACTIVEJAM_CMDID:
  1178. +       return "WMI_REACTIVEJAM_CMDID";
  1179. +   case WMI_FASTREPLY_CMDID:
  1180. +       return "WMI_FASTREPLY_CMDID";
  1181. +   case WMI_CONSTANTJAM_CMDID:
  1182. +       return "WMI_CONSTANTJAM_CMDID";
  1183.     }
  1184.  
  1185.     return "Bogus";
  1186. diff -Naur backports-4.4.2-1/drivers/net/wireless/ath/ath9k/wmi.h backports-4.4.2-1-modwifi/drivers/net/wireless/ath/ath9k/wmi.h
  1187. --- backports-4.4.2-1/drivers/net/wireless/ath/ath9k/wmi.h  2016-02-18 22:41:36.000000000 +0100
  1188. +++ backports-4.4.2-1-modwifi/drivers/net/wireless/ath/ath9k/wmi.h  2016-04-03 13:28:54.000000000 +0200
  1189. @@ -113,6 +113,12 @@
  1190.     WMI_RX_STATS_CMDID,
  1191.     WMI_BITRATE_MASK_CMDID,
  1192.     WMI_REG_RMW_CMDID,
  1193. +
  1194. +   /* Custom commands added */
  1195. +   WMI_DEBUGMSG_CMDID = 0x0080,
  1196. +   WMI_REACTIVEJAM_CMDID,
  1197. +   WMI_FASTREPLY_CMDID,
  1198. +   WMI_CONSTANTJAM_CMDID,
  1199.  };
  1200.  
  1201.  enum wmi_event_id {
  1202. @@ -145,6 +151,65 @@
  1203.     struct list_head list;
  1204.  };
  1205.  
  1206. +struct wmi_debugmsg_cmd {
  1207. +   __be16 offset;
  1208. +} __packed;
  1209. +
  1210. +struct wmi_debugmsg_resp {
  1211. +   /** Length of zero signifies that no more data is available */
  1212. +   u8 length;
  1213. +   /** Debug message(s) **/
  1214. +   u8 buffer[40];
  1215. +} __packed;
  1216. +
  1217. +struct wmi_reactivejam_cmd {
  1218. +   u8 bssid[6];
  1219. +   u32 mduration;
  1220. +} __packed;
  1221. +
  1222. +struct wmi_constantjam_cmd {
  1223. +   /** A value from CONSTJAM_REQUEST to denote the request */
  1224. +   u8 request;
  1225. +   /** Set to 1 to disable CS and inter-frame-timeouts */
  1226. +   u8 conf_radio;
  1227. +   /** Length of the packet which is continuously transmitted */
  1228. +   u16 len;
  1229. +} __packed;
  1230. +
  1231. +struct wmi_constantjam_resp {
  1232. +   /** Is 1 when jammer is running, 0 otherwise */
  1233. +   u8 status;
  1234. +} __packed;
  1235. +
  1236. +enum CONSTJAM_REQUEST {
  1237. +   CONSTJAM_START,
  1238. +   CONSTJAM_STOP,
  1239. +   CONSTJAM_STATUS
  1240. +};
  1241. +
  1242. +struct wmi_fastreply_cmd {
  1243. +   u8 type;
  1244. +   union {
  1245. +       // transmit response packet in multiple commands
  1246. +       struct {
  1247. +           u8 length;
  1248. +           u8 offset;
  1249. +           u8 datalen;
  1250. +           u8 data[40];
  1251. +       } pkt;
  1252. +       // command to start monitoring
  1253. +       struct {
  1254. +           u32 mduration;
  1255. +           u8 source[6];
  1256. +       } start;
  1257. +   };
  1258. +} __packed;
  1259. +
  1260. +enum FASTREPLY_TYPE {
  1261. +   FASTREPLY_PKT,
  1262. +   FASTREPLY_START
  1263. +};
  1264. +
  1265.  struct wmi {
  1266.     struct ath9k_htc_priv *drv_priv;
  1267.     struct htc_target *htc;

No comments: