Advertisement
phip

linux-phc-0.3.2_3.0.7.patch

Oct 22nd, 2011
118
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 16.60 KB | None | 0 0
  1. diff -u a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c
  2. --- a/drivers/cpufreq/acpi-cpufreq.c    2011-07-22 04:17:23.000000000 +0200
  3. +++ b/drivers/cpufreq/acpi-cpufreq.c    2011-10-22 19:28:27.000000000 +0200
  4. @@ -23,6 +23,11 @@
  5.   *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  6.   *
  7.   * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  8. + *
  9. + * This file has been patched with Linux PHC: www.linux-phc.org
  10. + * Patch version: linux-phc-0.3.2
  11. + *
  12. + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  13.   */
  14.  
  15.  #include <linux/kernel.h>
  16. @@ -58,12 +63,17 @@
  17.  };
  18.  
  19.  #define INTEL_MSR_RANGE        (0xffff)
  20. +#define INTEL_MSR_VID_MASK (0x00ff)
  21. +#define INTEL_MSR_FID_MASK (0xff00)
  22. +#define INTEL_MSR_FID_SHIFT    (0x8)
  23. +#define PHC_VERSION_STRING "0.3.2:2"
  24.  
  25.  struct acpi_cpufreq_data {
  26.     struct acpi_processor_performance *acpi_data;
  27.     struct cpufreq_frequency_table *freq_table;
  28.     unsigned int resume;
  29.     unsigned int cpu_feature;
  30. +   acpi_integer *original_controls;
  31.  };
  32.  
  33.  static DEFINE_PER_CPU(struct acpi_cpufreq_data *, acfreq_data);
  34. @@ -99,13 +109,14 @@
  35.  static unsigned extract_msr(u32 msr, struct acpi_cpufreq_data *data)
  36.  {
  37.     int i;
  38. +   u32 fid;
  39.     struct acpi_processor_performance *perf;
  40.  
  41. -   msr &= INTEL_MSR_RANGE;
  42. +   fid = msr & INTEL_MSR_FID_MASK;
  43.     perf = data->acpi_data;
  44.  
  45.     for (i = 0; data->freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
  46. -       if (msr == perf->states[data->freq_table[i].index].status)
  47. +       if (fid == (perf->states[data->freq_table[i].index].status & INTEL_MSR_FID_MASK))
  48.             return data->freq_table[i].frequency;
  49.     }
  50.     return data->freq_table[0].frequency;
  51. @@ -699,6 +710,8 @@
  52.         acpi_processor_unregister_performance(data->acpi_data,
  53.                               policy->cpu);
  54.         kfree(data->freq_table);
  55. +       if (data->original_controls)
  56. +           kfree(data->original_controls);
  57.         kfree(data);
  58.     }
  59.  
  60. @@ -716,8 +729,501 @@
  61.     return 0;
  62.  }
  63.  
  64. +
  65. +/*********************************************************************
  66. + *                          SYSFS INTERFACE                          *
  67. + *                to change operating points voltages                *
  68. + *********************************************************************/
  69. +
  70. +static unsigned int extract_fid_from_control(unsigned int control)
  71. +{
  72. +   return ((control & INTEL_MSR_FID_MASK) >> INTEL_MSR_FID_SHIFT);
  73. +}
  74. +
  75. +static unsigned int extract_vid_from_control(unsigned int control)
  76. +{
  77. +   return (control & INTEL_MSR_VID_MASK);
  78. +}
  79. +
  80. +/**
  81. + * check if the cpu we are running on is capable of setting new control data
  82. + */
  83. +static bool check_cpu_control_capability(struct acpi_cpufreq_data *data) {
  84. +   if (unlikely(data == NULL ||
  85. +                data->acpi_data == NULL ||
  86. +                data->freq_table == NULL ||
  87. +                data->cpu_feature != SYSTEM_INTEL_MSR_CAPABLE)) {
  88. +       return false;
  89. +   } else {
  90. +       return true;
  91. +   };
  92. +}
  93. +
  94. +
  95. +static ssize_t check_origial_table (struct acpi_cpufreq_data *data)
  96. +{
  97. +
  98. +   struct acpi_processor_performance *acpi_data;
  99. +   struct cpufreq_frequency_table *freq_table;
  100. +   unsigned int state_index;
  101. +
  102. +   acpi_data = data->acpi_data;
  103. +   freq_table = data->freq_table;
  104. +
  105. +   if (data->original_controls == NULL) {
  106. +       // Backup original control values
  107. +       data->original_controls = kcalloc(acpi_data->state_count,
  108. +                                         sizeof(acpi_integer), GFP_KERNEL);
  109. +       if (data->original_controls == NULL) {
  110. +           printk("failed to allocate memory for original control values\n");
  111. +           return -ENOMEM;
  112. +       }
  113. +       for (state_index = 0; state_index < acpi_data->state_count; state_index++) {
  114. +           data->original_controls[state_index] = acpi_data->states[state_index].control;
  115. +       }
  116. +   }
  117. +   return 0;
  118. +}
  119. +
  120. +/**
  121. + * display phc's voltage id's
  122. + */
  123. +static ssize_t show_freq_attr_vids(struct cpufreq_policy *policy, char *buf)
  124. +{
  125. +   struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
  126. +   struct acpi_processor_performance *acpi_data;
  127. +   struct cpufreq_frequency_table *freq_table;
  128. +   unsigned int i;
  129. +   unsigned int vid;
  130. +   ssize_t count = 0;
  131. +
  132. +   if (!check_cpu_control_capability(data)) return -ENODEV; //check if CPU is capable of changing controls
  133. +
  134. +   acpi_data = data->acpi_data;
  135. +   freq_table = data->freq_table;
  136. +
  137. +   for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
  138. +       vid = extract_vid_from_control(acpi_data->states[freq_table[i].index].control);
  139. +       count += sprintf(&buf[count], "%u ", vid);
  140. +   }
  141. +   count += sprintf(&buf[count], "\n");
  142. +
  143. +   return count;
  144. +}
  145. +
  146. +/**
  147. + * display acpi's default voltage id's
  148. + */
  149. +static ssize_t show_freq_attr_default_vids(struct cpufreq_policy *policy, char *buf)
  150. +{
  151. +   struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
  152. +   struct cpufreq_frequency_table *freq_table;
  153. +   unsigned int i;
  154. +   unsigned int vid;
  155. +   ssize_t count = 0;
  156. +   ssize_t retval;
  157. +
  158. +   if (!check_cpu_control_capability(data)) return -ENODEV; //check if CPU is capable of changing controls
  159. +
  160. +   retval = check_origial_table(data);
  161. +        if (0 != retval)
  162. +       return retval;
  163. +
  164. +   freq_table = data->freq_table;
  165. +
  166. +   for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
  167. +       vid = extract_vid_from_control(data->original_controls[freq_table[i].index]);
  168. +       count += sprintf(&buf[count], "%u ", vid);
  169. +   }
  170. +   count += sprintf(&buf[count], "\n");
  171. +
  172. +   return count;
  173. +}
  174. +
  175. +/**
  176. + * display phc's frequeny id's
  177. + */
  178. +static ssize_t show_freq_attr_fids(struct cpufreq_policy *policy, char *buf)
  179. +{
  180. +   struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
  181. +   struct acpi_processor_performance *acpi_data;
  182. +   struct cpufreq_frequency_table *freq_table;
  183. +   unsigned int i;
  184. +   unsigned int fid;
  185. +   ssize_t count = 0;
  186. +
  187. +   if (!check_cpu_control_capability(data)) return -ENODEV; //check if CPU is capable of changing controls
  188. +
  189. +   acpi_data = data->acpi_data;
  190. +   freq_table = data->freq_table;
  191. +
  192. +   for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
  193. +       fid = extract_fid_from_control(acpi_data->states[freq_table[i].index].control);
  194. +       count += sprintf(&buf[count], "%u ", fid);
  195. +   }
  196. +   count += sprintf(&buf[count], "\n");
  197. +
  198. +   return count;
  199. +}
  200. +
  201. +/**
  202. + * display phc's controls for the cpu (frequency id's and related voltage id's)
  203. + */
  204. +static ssize_t show_freq_attr_controls(struct cpufreq_policy *policy, char *buf)
  205. +{
  206. +   struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
  207. +   struct acpi_processor_performance *acpi_data;
  208. +   struct cpufreq_frequency_table *freq_table;
  209. +   unsigned int i;
  210. +   unsigned int fid;
  211. +   unsigned int vid;
  212. +   ssize_t count = 0;
  213. +
  214. +   if (!check_cpu_control_capability(data)) return -ENODEV; //check if CPU is capable of changing controls
  215. +
  216. +   acpi_data = data->acpi_data;
  217. +   freq_table = data->freq_table;
  218. +
  219. +   for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
  220. +       fid = extract_fid_from_control(acpi_data->states[freq_table[i].index].control);
  221. +       vid = extract_vid_from_control(acpi_data->states[freq_table[i].index].control);
  222. +       count += sprintf(&buf[count], "%u:%u ", fid, vid);
  223. +   }
  224. +   count += sprintf(&buf[count], "\n");
  225. +
  226. +   return count;
  227. +}
  228. +
  229. +/**
  230. + * display acpi's default controls for the cpu (frequency id's and related voltage id's)
  231. + */
  232. +static ssize_t show_freq_attr_default_controls(struct cpufreq_policy *policy, char *buf)
  233. +{
  234. +   struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
  235. +   struct cpufreq_frequency_table *freq_table;
  236. +   unsigned int i;
  237. +   unsigned int fid;
  238. +   unsigned int vid;
  239. +   ssize_t count = 0;
  240. +   ssize_t retval;
  241. +
  242. +   if (!check_cpu_control_capability(data)) return -ENODEV; //check if CPU is capable of changing controls
  243. +
  244. +   retval = check_origial_table(data);
  245. +        if (0 != retval)
  246. +       return retval;
  247. +
  248. +   freq_table = data->freq_table;
  249. +
  250. +   for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
  251. +       fid = extract_fid_from_control(data->original_controls[freq_table[i].index]);
  252. +       vid = extract_vid_from_control(data->original_controls[freq_table[i].index]);
  253. +       count += sprintf(&buf[count], "%u:%u ", fid, vid);
  254. +   }
  255. +   count += sprintf(&buf[count], "\n");
  256. +
  257. +   return count;
  258. +}
  259. +
  260. +/**
  261. + * store the voltage id's for the related frequency
  262. + * We are going to do some sanity checks here to prevent users
  263. + * from setting higher voltages than the default one.
  264. + */
  265. +static ssize_t store_freq_attr_vids(struct cpufreq_policy *policy, const char *buf, size_t count)
  266. +
  267. +{
  268. +   struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
  269. +   struct acpi_processor_performance *acpi_data;
  270. +   struct cpufreq_frequency_table *freq_table;
  271. +   unsigned int freq_index;
  272. +   unsigned int state_index;
  273. +   unsigned int new_vid;
  274. +   unsigned int original_vid;
  275. +   unsigned int new_control;
  276. +   unsigned int original_control;
  277. +   const char *curr_buf = buf;
  278. +   char *next_buf;
  279. +   ssize_t retval;
  280. +
  281. +   if (!check_cpu_control_capability(data)) return -ENODEV; //check if CPU is capable of changing controls
  282. +
  283. +   retval = check_origial_table(data);
  284. +        if (0 != retval)
  285. +       return retval;
  286. +
  287. +   acpi_data = data->acpi_data;
  288. +   freq_table = data->freq_table;
  289. +
  290. +   // for each value taken from the sysfs interfalce (phc_vids) get entrys and convert them to unsigned long integers
  291. +   for (freq_index = 0; freq_table[freq_index].frequency != CPUFREQ_TABLE_END; freq_index++) {
  292. +       new_vid = simple_strtoul(curr_buf, &next_buf, 10);
  293. +       if (next_buf == curr_buf) {
  294. +           if ((curr_buf - buf == count - 1) && (*curr_buf == '\n')) {   //end of line?
  295. +               curr_buf++;
  296. +               break;
  297. +           }
  298. +           // if we didn't got end of line but there is nothing more to read something went wrong...
  299. +           printk("failed to parse vid value at %i (%s)\n", freq_index, curr_buf);
  300. +           return -EINVAL;
  301. +       }
  302. +
  303. +       state_index = freq_table[freq_index].index;
  304. +       original_control = data->original_controls[state_index];
  305. +       original_vid = original_control & INTEL_MSR_VID_MASK;
  306. +      
  307. +       // before we store the values we do some checks to prevent
  308. +       // users to set up values higher than the default one
  309. +       if (new_vid <= original_vid) {
  310. +           new_control = (original_control & ~INTEL_MSR_VID_MASK) | new_vid;
  311. +           pr_debug("setting control at %i to %x (default is %x)\n",
  312. +                   freq_index, new_control, original_control);
  313. +           acpi_data->states[state_index].control = new_control;
  314. +
  315. +       } else {
  316. +           printk("skipping vid at %i, %u is greater than default %u\n",
  317. +                  freq_index, new_vid, original_vid);
  318. +       }
  319. +
  320. +       curr_buf = next_buf;
  321. +       // jump over value seperators (space or comma).
  322. +       // There could be more than one space or comma character
  323. +       // to separate two values so we better do it using a loop.
  324. +       while ((curr_buf - buf < count) && ((*curr_buf == ' ') || (*curr_buf == ','))) {
  325. +           curr_buf++;
  326. +       }
  327. +   }
  328. +
  329. +   // set new voltage for current frequency
  330. +   data->resume = 1;
  331. +   acpi_cpufreq_target(policy, get_cur_freq_on_cpu(policy->cpu), CPUFREQ_RELATION_L);
  332. +
  333. +   return curr_buf - buf;
  334. +}
  335. +
  336. +/**
  337. + * store the controls (frequency id's and related voltage id's)
  338. + * We are going to do some sanity checks here to prevent users
  339. + * from setting higher voltages than the default one.
  340. + */
  341. +static ssize_t store_freq_attr_controls(struct cpufreq_policy *policy, const char *buf, size_t count)
  342. +{
  343. +   struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
  344. +   struct acpi_processor_performance *acpi_data;
  345. +   struct cpufreq_frequency_table *freq_table;
  346. +   const char   *curr_buf;
  347. +   unsigned int  op_count;
  348. +   unsigned int  state_index;
  349. +   int           isok;
  350. +   char         *next_buf;
  351. +   ssize_t       retval;
  352. +   unsigned int  new_vid;
  353. +   unsigned int  original_vid;
  354. +   unsigned int  new_fid;
  355. +   unsigned int  old_fid;
  356. +   unsigned int  original_control;
  357. +   unsigned int  old_control;
  358. +   unsigned int  new_control;
  359. +   int           found;
  360. +
  361. +   if (!check_cpu_control_capability(data)) return -ENODEV;
  362. +
  363. +   retval = check_origial_table(data);
  364. +        if (0 != retval)
  365. +       return retval;
  366. +
  367. +   acpi_data = data->acpi_data;
  368. +   freq_table = data->freq_table;
  369. +
  370. +   op_count = 0;
  371. +   curr_buf = buf;
  372. +   next_buf = NULL;
  373. +   isok     = 1;
  374. +  
  375. +   while ( (isok) && (curr_buf != NULL) )
  376. +   {
  377. +       op_count++;
  378. +       // Parse fid
  379. +       new_fid = simple_strtoul(curr_buf, &next_buf, 10);
  380. +       if ((next_buf != curr_buf) && (next_buf != NULL))
  381. +       {
  382. +           // Parse separator between frequency and voltage
  383. +           curr_buf = next_buf;
  384. +           next_buf = NULL;
  385. +           if (*curr_buf==':')
  386. +           {
  387. +               curr_buf++;
  388. +               // Parse vid
  389. +               new_vid = simple_strtoul(curr_buf, &next_buf, 10);
  390. +               if ((next_buf != curr_buf) && (next_buf != NULL))
  391. +               {
  392. +                   found = 0;
  393. +                   for (state_index = 0; state_index < acpi_data->state_count; state_index++) {
  394. +                       old_control = acpi_data->states[state_index].control;
  395. +                       old_fid = extract_fid_from_control(old_control);
  396. +                       if (new_fid == old_fid)
  397. +                       {
  398. +                           found = 1;
  399. +                           original_control = data->original_controls[state_index];
  400. +                           original_vid = extract_vid_from_control(original_control);
  401. +                           if (new_vid <= original_vid)
  402. +                           {
  403. +                               new_control = (original_control & ~INTEL_MSR_VID_MASK) | new_vid;
  404. +                               pr_debug("setting control at %i to %x (default is %x)\n",
  405. +                                       state_index, new_control, original_control);
  406. +                               acpi_data->states[state_index].control = new_control;
  407. +
  408. +                           } else {
  409. +                               printk("skipping vid at %i, %u is greater than default %u\n",
  410. +                                      state_index, new_vid, original_vid);
  411. +                           }
  412. +                       }
  413. +                   }
  414. +
  415. +                   if (found == 0)
  416. +                   {
  417. +                       printk("operating point # %u not found (FID = %u)\n", op_count, new_fid);
  418. +                       isok = 0;
  419. +                   }
  420. +
  421. +                   // Parse seprator before next operating point, if any
  422. +                   curr_buf = next_buf;
  423. +                   next_buf = NULL;
  424. +                   if ((*curr_buf == ',') || (*curr_buf == ' '))
  425. +                       curr_buf++;
  426. +                   else
  427. +                       curr_buf = NULL;
  428. +               }
  429. +               else
  430. +               {
  431. +                   printk("failed to parse VID of operating point # %u (%s)\n", op_count, curr_buf);
  432. +                   isok = 0;
  433. +               }
  434. +           }
  435. +           else
  436. +           {
  437. +               printk("failed to parse operating point # %u (%s)\n", op_count, curr_buf);
  438. +               isok = 0;
  439. +           }
  440. +       }
  441. +       else
  442. +       {
  443. +           printk("failed to parse FID of operating point # %u (%s)\n", op_count, curr_buf);
  444. +           isok = 0;
  445. +       }
  446. +   }
  447. +
  448. +   if (isok)
  449. +   {
  450. +       retval = count;
  451. +       // set new voltage at current frequency
  452. +       data->resume = 1;
  453. +       acpi_cpufreq_target(policy, get_cur_freq_on_cpu(policy->cpu), CPUFREQ_RELATION_L);
  454. +   }
  455. +   else
  456. +   {
  457. +       retval = -EINVAL;
  458. +   }
  459. +
  460. +   return retval;
  461. +}
  462. +
  463. +/**
  464. + * print out the phc version string set at the beginning of that file
  465. + */
  466. +static ssize_t show_freq_attr_phc_version(struct cpufreq_policy *policy, char *buf)
  467. +{
  468. +   ssize_t count = 0;
  469. +   count += sprintf(&buf[count], "%s\n", PHC_VERSION_STRING);
  470. +   return count;
  471. +}
  472. +
  473. +/**
  474. + * display phc's version string
  475. + */
  476. +static struct freq_attr cpufreq_freq_attr_phc_version =
  477. +{
  478. +   .attr = {   .name = "phc_version",
  479. +               .mode = 0444,
  480. +//             .owner = THIS_MODULE
  481. +           },
  482. +   .show = show_freq_attr_phc_version,
  483. +   .store = NULL,
  484. +};
  485. +
  486. +/**
  487. + * display phc's voltage id's for the cpu
  488. + */
  489. +static struct freq_attr cpufreq_freq_attr_vids =
  490. +{
  491. +   .attr = {   .name = "phc_vids",
  492. +               .mode = 0644,
  493. +//             .owner = THIS_MODULE
  494. +           },
  495. +   .show = show_freq_attr_vids,
  496. +   .store = store_freq_attr_vids,
  497. +};
  498. +
  499. +/**
  500. + * display acpi's default frequency id's for the cpu
  501. + */
  502. +static struct freq_attr cpufreq_freq_attr_default_vids =
  503. +{
  504. +   .attr = {   .name = "phc_default_vids",
  505. +               .mode = 0444,
  506. +//             .owner = THIS_MODULE
  507. +           },
  508. +   .show = show_freq_attr_default_vids,
  509. +   .store = NULL,
  510. +};
  511. +
  512. +/**
  513. + * display phc's default frequency id's for the cpu
  514. + */
  515. +static struct freq_attr cpufreq_freq_attr_fids =
  516. +{
  517. +   .attr = {   .name = "phc_fids",
  518. +               .mode = 0444,
  519. +//             .owner = THIS_MODULE
  520. +           },
  521. +   .show = show_freq_attr_fids,
  522. +   .store = NULL,
  523. +};
  524. +
  525. +/**
  526. + * display phc's current voltage/frequency controls for the cpu
  527. + */
  528. +static struct freq_attr cpufreq_freq_attr_controls =
  529. +{
  530. +   .attr = {   .name = "phc_controls",
  531. +               .mode = 0644,
  532. +//             .owner = THIS_MODULE
  533. +           },
  534. +   .show = show_freq_attr_controls,
  535. +   .store = store_freq_attr_controls,
  536. +};
  537. +
  538. +/**
  539. + * display acpi's default voltage/frequency controls for the cpu
  540. + */
  541. +static struct freq_attr cpufreq_freq_attr_default_controls =
  542. +{
  543. +   .attr = {   .name = "phc_default_controls",
  544. +               .mode = 0444,
  545. +//             .owner = THIS_MODULE
  546. +           },
  547. +   .show = show_freq_attr_default_controls,
  548. +   .store = NULL,
  549. +};
  550. +
  551.  static struct freq_attr *acpi_cpufreq_attr[] = {
  552.     &cpufreq_freq_attr_scaling_available_freqs,
  553. +   &cpufreq_freq_attr_phc_version,
  554. +   &cpufreq_freq_attr_vids,
  555. +   &cpufreq_freq_attr_default_vids,
  556. +   &cpufreq_freq_attr_fids,
  557. +   &cpufreq_freq_attr_controls,
  558. +   &cpufreq_freq_attr_default_controls,
  559.     NULL,
  560.  };
  561.  
  562.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement