Blame view
drivers/cpufreq/speedstep-smi.c
11.2 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
/* * Intel SpeedStep SMI driver. * * (C) 2003 Hiroshi Miura <miura@da-cha.org> * * Licensed under the terms of the GNU GPL License version 2. * */ /********************************************************************* * SPEEDSTEP - DEFINITIONS * *********************************************************************/ #include <linux/kernel.h> |
32ee8c3e4 [CPUFREQ] Lots of... |
16 17 |
#include <linux/module.h> #include <linux/moduleparam.h> |
1da177e4c Linux-2.6.12-rc2 |
18 19 |
#include <linux/init.h> #include <linux/cpufreq.h> |
1da177e4c Linux-2.6.12-rc2 |
20 |
#include <linux/delay.h> |
bbfebd665 [CPUFREQ] checkpa... |
21 |
#include <linux/io.h> |
1da177e4c Linux-2.6.12-rc2 |
22 23 24 25 26 27 28 29 |
#include <asm/ist.h> #include "speedstep-lib.h" /* speedstep system management interface port/command. * * These parameters are got from IST-SMI BIOS call. * If user gives it, these are used. |
32ee8c3e4 [CPUFREQ] Lots of... |
30 |
* |
1da177e4c Linux-2.6.12-rc2 |
31 |
*/ |
bbfebd665 [CPUFREQ] checkpa... |
32 33 34 |
static int smi_port; static int smi_cmd; static unsigned int smi_sig; |
1da177e4c Linux-2.6.12-rc2 |
35 36 |
/* info about the processor */ |
1cce76c2a [CPUFREQ] use an ... |
37 |
static enum speedstep_processor speedstep_processor; |
1da177e4c Linux-2.6.12-rc2 |
38 |
|
32ee8c3e4 [CPUFREQ] Lots of... |
39 40 |
/* * There are only two frequency states for each processor. Values |
1da177e4c Linux-2.6.12-rc2 |
41 42 43 |
* are in kHz for the time being. */ static struct cpufreq_frequency_table speedstep_freqs[] = { |
32ee8c3e4 [CPUFREQ] Lots of... |
44 |
{SPEEDSTEP_HIGH, 0}, |
1da177e4c Linux-2.6.12-rc2 |
45 46 47 48 49 50 51 52 53 54 55 56 |
{SPEEDSTEP_LOW, 0}, {0, CPUFREQ_TABLE_END}, }; #define GET_SPEEDSTEP_OWNER 0 #define GET_SPEEDSTEP_STATE 1 #define SET_SPEEDSTEP_STATE 2 #define GET_SPEEDSTEP_FREQS 4 /* how often shall the SMI call be tried if it failed, e.g. because * of DMA activity going on? */ #define SMI_TRIES 5 |
1da177e4c Linux-2.6.12-rc2 |
57 58 59 |
/** * speedstep_smi_ownership */ |
bbfebd665 [CPUFREQ] checkpa... |
60 |
static int speedstep_smi_ownership(void) |
1da177e4c Linux-2.6.12-rc2 |
61 |
{ |
c6e8256a7 x86, cpufreq: fix... |
62 |
u32 command, result, magic, dummy; |
1da177e4c Linux-2.6.12-rc2 |
63 64 65 66 67 |
u32 function = GET_SPEEDSTEP_OWNER; unsigned char magic_data[] = "Copyright (c) 1999 Intel Corporation"; command = (smi_sig & 0xffffff00) | (smi_cmd & 0xff); magic = virt_to_phys(magic_data); |
2d06d8c49 [CPUFREQ] use dyn... |
68 69 |
pr_debug("trying to obtain ownership with command %x at port %x ", |
bbfebd665 [CPUFREQ] checkpa... |
70 |
command, smi_port); |
1da177e4c Linux-2.6.12-rc2 |
71 72 |
__asm__ __volatile__( |
c6e8256a7 x86, cpufreq: fix... |
73 74 |
"push %%ebp " |
1da177e4c Linux-2.6.12-rc2 |
75 76 |
"out %%al, (%%dx) " |
c6e8256a7 x86, cpufreq: fix... |
77 78 |
"pop %%ebp " |
bbfebd665 [CPUFREQ] checkpa... |
79 80 81 |
: "=D" (result), "=a" (dummy), "=b" (dummy), "=c" (dummy), "=d" (dummy), "=S" (dummy) |
f081a529f [PATCH] cpufreq: ... |
82 |
: "a" (command), "b" (function), "c" (0), "d" (smi_port), |
bbfebd665 [CPUFREQ] checkpa... |
83 |
"D" (0), "S" (magic) |
f081a529f [PATCH] cpufreq: ... |
84 |
: "memory" |
1da177e4c Linux-2.6.12-rc2 |
85 |
); |
2d06d8c49 [CPUFREQ] use dyn... |
86 87 |
pr_debug("result is %x ", result); |
1da177e4c Linux-2.6.12-rc2 |
88 89 90 91 92 93 94 95 96 97 98 99 100 |
return result; } /** * speedstep_smi_get_freqs - get SpeedStep preferred & current freq. * @low: the low frequency value is placed here * @high: the high frequency value is placed here * * Only available on later SpeedStep-enabled systems, returns false results or * even hangs [cf. bugme.osdl.org # 1422] on earlier systems. Empirical testing * shows that the latter occurs if !(ist_info.event & 0xFFFF). */ |
bbfebd665 [CPUFREQ] checkpa... |
101 |
static int speedstep_smi_get_freqs(unsigned int *low, unsigned int *high) |
1da177e4c Linux-2.6.12-rc2 |
102 |
{ |
c6e8256a7 x86, cpufreq: fix... |
103 |
u32 command, result = 0, edi, high_mhz, low_mhz, dummy; |
bbfebd665 [CPUFREQ] checkpa... |
104 |
u32 state = 0; |
1da177e4c Linux-2.6.12-rc2 |
105 106 107 |
u32 function = GET_SPEEDSTEP_FREQS; if (!(ist_info.event & 0xFFFF)) { |
2d06d8c49 [CPUFREQ] use dyn... |
108 109 |
pr_debug("bug #1422 -- can't read freqs from BIOS "); |
1da177e4c Linux-2.6.12-rc2 |
110 111 112 113 |
return -ENODEV; } command = (smi_sig & 0xffffff00) | (smi_cmd & 0xff); |
2d06d8c49 [CPUFREQ] use dyn... |
114 115 |
pr_debug("trying to determine frequencies with command %x at port %x ", |
bbfebd665 [CPUFREQ] checkpa... |
116 |
command, smi_port); |
1da177e4c Linux-2.6.12-rc2 |
117 |
|
c6e8256a7 x86, cpufreq: fix... |
118 119 120 |
__asm__ __volatile__( "push %%ebp " |
1da177e4c Linux-2.6.12-rc2 |
121 122 |
"out %%al, (%%dx) " |
c6e8256a7 x86, cpufreq: fix... |
123 |
"pop %%ebp" |
bbfebd665 [CPUFREQ] checkpa... |
124 125 126 127 128 129 130 131 |
: "=a" (result), "=b" (high_mhz), "=c" (low_mhz), "=d" (state), "=D" (edi), "=S" (dummy) : "a" (command), "b" (function), "c" (state), "d" (smi_port), "S" (0), "D" (0) |
1da177e4c Linux-2.6.12-rc2 |
132 |
); |
2d06d8c49 [CPUFREQ] use dyn... |
133 134 |
pr_debug("result %x, low_freq %u, high_freq %u ", |
bbfebd665 [CPUFREQ] checkpa... |
135 |
result, low_mhz, high_mhz); |
1da177e4c Linux-2.6.12-rc2 |
136 137 138 139 140 141 142 143 144 |
/* abort if results are obviously incorrect... */ if ((high_mhz + low_mhz) < 600) return -EINVAL; *high = high_mhz * 1000; *low = low_mhz * 1000; return result; |
32ee8c3e4 [CPUFREQ] Lots of... |
145 |
} |
1da177e4c Linux-2.6.12-rc2 |
146 147 148 149 150 151 |
/** * speedstep_get_state - set the SpeedStep state * @state: processor frequency state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH) * */ |
bbfebd665 [CPUFREQ] checkpa... |
152 |
static int speedstep_get_state(void) |
1da177e4c Linux-2.6.12-rc2 |
153 |
{ |
bbfebd665 [CPUFREQ] checkpa... |
154 |
u32 function = GET_SPEEDSTEP_STATE; |
c6e8256a7 x86, cpufreq: fix... |
155 |
u32 result, state, edi, command, dummy; |
1da177e4c Linux-2.6.12-rc2 |
156 157 |
command = (smi_sig & 0xffffff00) | (smi_cmd & 0xff); |
2d06d8c49 [CPUFREQ] use dyn... |
158 |
pr_debug("trying to determine current setting with command %x " |
bbfebd665 [CPUFREQ] checkpa... |
159 160 |
"at port %x ", command, smi_port); |
1da177e4c Linux-2.6.12-rc2 |
161 |
|
c6e8256a7 x86, cpufreq: fix... |
162 163 164 |
__asm__ __volatile__( "push %%ebp " |
1da177e4c Linux-2.6.12-rc2 |
165 166 |
"out %%al, (%%dx) " |
c6e8256a7 x86, cpufreq: fix... |
167 168 |
"pop %%ebp " |
bbfebd665 [CPUFREQ] checkpa... |
169 170 171 172 173 |
: "=a" (result), "=b" (state), "=D" (edi), "=c" (dummy), "=d" (dummy), "=S" (dummy) : "a" (command), "b" (function), "c" (0), "d" (smi_port), "S" (0), "D" (0) |
1da177e4c Linux-2.6.12-rc2 |
174 |
); |
2d06d8c49 [CPUFREQ] use dyn... |
175 176 |
pr_debug("state is %x, result is %x ", state, result); |
1da177e4c Linux-2.6.12-rc2 |
177 |
|
bbfebd665 [CPUFREQ] checkpa... |
178 |
return state & 1; |
1da177e4c Linux-2.6.12-rc2 |
179 180 181 182 183 184 185 186 |
} /** * speedstep_set_state - set the SpeedStep state * @state: new processor frequency state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH) * */ |
bbfebd665 [CPUFREQ] checkpa... |
187 |
static void speedstep_set_state(unsigned int state) |
1da177e4c Linux-2.6.12-rc2 |
188 |
{ |
c6e8256a7 x86, cpufreq: fix... |
189 |
unsigned int result = 0, command, new_state, dummy; |
1da177e4c Linux-2.6.12-rc2 |
190 |
unsigned long flags; |
bbfebd665 [CPUFREQ] checkpa... |
191 |
unsigned int function = SET_SPEEDSTEP_STATE; |
1da177e4c Linux-2.6.12-rc2 |
192 193 194 195 196 197 198 199 200 |
unsigned int retry = 0; if (state > 0x1) return; /* Disable IRQs */ local_irq_save(flags); command = (smi_sig & 0xffffff00) | (smi_cmd & 0xff); |
2d06d8c49 [CPUFREQ] use dyn... |
201 |
pr_debug("trying to set frequency to state %u " |
bbfebd665 [CPUFREQ] checkpa... |
202 203 204 |
"with command %x at port %x ", state, command, smi_port); |
1da177e4c Linux-2.6.12-rc2 |
205 206 207 |
do { if (retry) { |
2d06d8c49 [CPUFREQ] use dyn... |
208 209 |
pr_debug("retry %u, previous result %u, waiting... ", |
bbfebd665 [CPUFREQ] checkpa... |
210 |
retry, result); |
1da177e4c Linux-2.6.12-rc2 |
211 212 213 214 |
mdelay(retry * 50); } retry++; __asm__ __volatile__( |
c6e8256a7 x86, cpufreq: fix... |
215 216 |
"push %%ebp " |
1da177e4c Linux-2.6.12-rc2 |
217 218 |
"out %%al, (%%dx) " |
c6e8256a7 x86, cpufreq: fix... |
219 |
"pop %%ebp" |
bbfebd665 [CPUFREQ] checkpa... |
220 221 222 223 224 |
: "=b" (new_state), "=D" (result), "=c" (dummy), "=a" (dummy), "=d" (dummy), "=S" (dummy) : "a" (command), "b" (function), "c" (state), "d" (smi_port), "S" (0), "D" (0) |
1da177e4c Linux-2.6.12-rc2 |
225 226 227 228 229 |
); } while ((new_state != state) && (retry <= SMI_TRIES)); /* enable IRQs */ local_irq_restore(flags); |
bbfebd665 [CPUFREQ] checkpa... |
230 |
if (new_state == state) |
2d06d8c49 [CPUFREQ] use dyn... |
231 |
pr_debug("change to %u MHz succeeded after %u tries " |
bbfebd665 [CPUFREQ] checkpa... |
232 233 234 235 236 237 238 239 240 |
"with result %u ", (speedstep_freqs[new_state].frequency / 1000), retry, result); else printk(KERN_ERR "cpufreq: change to state %u " "failed with new_state %u and result %u ", state, new_state, result); |
1da177e4c Linux-2.6.12-rc2 |
241 242 243 244 245 246 247 248 249 |
return; } /** * speedstep_target - set a new CPUFreq policy * @policy: new policy * @target_freq: new freq |
32ee8c3e4 [CPUFREQ] Lots of... |
250 |
* @relation: |
1da177e4c Linux-2.6.12-rc2 |
251 252 253 |
* * Sets a new CPUFreq policy/freq. */ |
bbfebd665 [CPUFREQ] checkpa... |
254 |
static int speedstep_target(struct cpufreq_policy *policy, |
1da177e4c Linux-2.6.12-rc2 |
255 256 257 258 |
unsigned int target_freq, unsigned int relation) { unsigned int newstate = 0; struct cpufreq_freqs freqs; |
bbfebd665 [CPUFREQ] checkpa... |
259 260 |
if (cpufreq_frequency_table_target(policy, &speedstep_freqs[0], target_freq, relation, &newstate)) |
1da177e4c Linux-2.6.12-rc2 |
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 |
return -EINVAL; freqs.old = speedstep_freqs[speedstep_get_state()].frequency; freqs.new = speedstep_freqs[newstate].frequency; freqs.cpu = 0; /* speedstep.c is UP only driver */ if (freqs.old == freqs.new) return 0; cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); speedstep_set_state(newstate); cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); return 0; } /** * speedstep_verify - verifies a new CPUFreq policy * @policy: new policy * * Limit must be within speedstep_low_freq and speedstep_high_freq, with * at least one border included. */ |
bbfebd665 [CPUFREQ] checkpa... |
285 |
static int speedstep_verify(struct cpufreq_policy *policy) |
1da177e4c Linux-2.6.12-rc2 |
286 287 288 289 290 291 292 293 |
{ return cpufreq_frequency_table_verify(policy, &speedstep_freqs[0]); } static int speedstep_cpu_init(struct cpufreq_policy *policy) { int result; |
bbfebd665 [CPUFREQ] checkpa... |
294 295 |
unsigned int speed, state; unsigned int *low, *high; |
1da177e4c Linux-2.6.12-rc2 |
296 297 298 299 300 301 302 |
/* capability check */ if (policy->cpu != 0) return -ENODEV; result = speedstep_smi_ownership(); if (result) { |
2d06d8c49 [CPUFREQ] use dyn... |
303 304 |
pr_debug("fails in acquiring ownership of a SMI interface. "); |
1da177e4c Linux-2.6.12-rc2 |
305 306 307 308 |
return -EINVAL; } /* detect low and high frequency */ |
bbfebd665 [CPUFREQ] checkpa... |
309 310 311 312 |
low = &speedstep_freqs[SPEEDSTEP_LOW].frequency; high = &speedstep_freqs[SPEEDSTEP_HIGH].frequency; result = speedstep_smi_get_freqs(low, high); |
1da177e4c Linux-2.6.12-rc2 |
313 |
if (result) { |
bbfebd665 [CPUFREQ] checkpa... |
314 315 |
/* fall back to speedstep_lib.c dection mechanism: * try both states out */ |
2d06d8c49 [CPUFREQ] use dyn... |
316 |
pr_debug("could not detect low and high frequencies " |
bbfebd665 [CPUFREQ] checkpa... |
317 318 |
"by SMI call. "); |
1da177e4c Linux-2.6.12-rc2 |
319 |
result = speedstep_get_freqs(speedstep_processor, |
bbfebd665 [CPUFREQ] checkpa... |
320 |
low, high, |
1a10760c9 [CPUFREQ] Measure... |
321 |
NULL, |
1da177e4c Linux-2.6.12-rc2 |
322 323 324 |
&speedstep_set_state); if (result) { |
2d06d8c49 [CPUFREQ] use dyn... |
325 |
pr_debug("could not detect two different speeds" |
bbfebd665 [CPUFREQ] checkpa... |
326 327 |
" -- aborting. "); |
1da177e4c Linux-2.6.12-rc2 |
328 329 |
return result; } else |
2d06d8c49 [CPUFREQ] use dyn... |
330 331 |
pr_debug("workaround worked. "); |
1da177e4c Linux-2.6.12-rc2 |
332 333 334 335 336 |
} /* get current speed setting */ state = speedstep_get_state(); speed = speedstep_freqs[state].frequency; |
2d06d8c49 [CPUFREQ] use dyn... |
337 338 |
pr_debug("currently at %s speed setting - %i MHz ", |
bbfebd665 [CPUFREQ] checkpa... |
339 340 |
(speed == speedstep_freqs[SPEEDSTEP_LOW].frequency) ? "low" : "high", |
1da177e4c Linux-2.6.12-rc2 |
341 342 343 |
(speed / 1000)); /* cpuinfo and default policy values */ |
1da177e4c Linux-2.6.12-rc2 |
344 345 346 347 348 |
policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; policy->cur = speed; result = cpufreq_frequency_table_cpuinfo(policy, speedstep_freqs); if (result) |
bbfebd665 [CPUFREQ] checkpa... |
349 |
return result; |
1da177e4c Linux-2.6.12-rc2 |
350 |
|
32ee8c3e4 [CPUFREQ] Lots of... |
351 |
cpufreq_frequency_table_get_attr(speedstep_freqs, policy->cpu); |
1da177e4c Linux-2.6.12-rc2 |
352 353 354 355 356 357 358 359 360 361 362 363 364 365 |
return 0; } static int speedstep_cpu_exit(struct cpufreq_policy *policy) { cpufreq_frequency_table_put_attr(policy->cpu); return 0; } static unsigned int speedstep_get(unsigned int cpu) { if (cpu) return -ENODEV; |
bbfebd665 [CPUFREQ] checkpa... |
366 |
return speedstep_get_frequency(speedstep_processor); |
1da177e4c Linux-2.6.12-rc2 |
367 368 369 370 371 372 373 374 |
} static int speedstep_resume(struct cpufreq_policy *policy) { int result = speedstep_smi_ownership(); if (result) |
2d06d8c49 [CPUFREQ] use dyn... |
375 376 |
pr_debug("fails in re-acquiring ownership of a SMI interface. "); |
1da177e4c Linux-2.6.12-rc2 |
377 378 379 |
return result; } |
bbfebd665 [CPUFREQ] checkpa... |
380 |
static struct freq_attr *speedstep_attr[] = { |
1da177e4c Linux-2.6.12-rc2 |
381 382 383 |
&cpufreq_freq_attr_scaling_available_freqs, NULL, }; |
221dee285 Revert "[CPUFREQ]... |
384 |
static struct cpufreq_driver speedstep_driver = { |
1da177e4c Linux-2.6.12-rc2 |
385 |
.name = "speedstep-smi", |
32ee8c3e4 [CPUFREQ] Lots of... |
386 387 |
.verify = speedstep_verify, .target = speedstep_target, |
1da177e4c Linux-2.6.12-rc2 |
388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 |
.init = speedstep_cpu_init, .exit = speedstep_cpu_exit, .get = speedstep_get, .resume = speedstep_resume, .owner = THIS_MODULE, .attr = speedstep_attr, }; /** * speedstep_init - initializes the SpeedStep CPUFreq driver * * Initializes the SpeedStep support. Returns -ENODEV on unsupported * BIOS, -EINVAL on problems during initiatization, and zero on * success. */ static int __init speedstep_init(void) { speedstep_processor = speedstep_detect_processor(); switch (speedstep_processor) { |
bbfebd665 [CPUFREQ] checkpa... |
408 409 410 |
case SPEEDSTEP_CPU_PIII_T: case SPEEDSTEP_CPU_PIII_C: case SPEEDSTEP_CPU_PIII_C_EARLY: |
1da177e4c Linux-2.6.12-rc2 |
411 412 413 414 415 416 |
break; default: speedstep_processor = 0; } if (!speedstep_processor) { |
2d06d8c49 [CPUFREQ] use dyn... |
417 418 |
pr_debug("No supported Intel CPU detected. "); |
1da177e4c Linux-2.6.12-rc2 |
419 420 |
return -ENODEV; } |
2d06d8c49 [CPUFREQ] use dyn... |
421 422 423 |
pr_debug("signature:0x%.8ulx, command:0x%.8ulx, " "event:0x%.8ulx, perf_level:0x%.8ulx. ", |
bbfebd665 [CPUFREQ] checkpa... |
424 425 |
ist_info.signature, ist_info.command, ist_info.event, ist_info.perf_level); |
1da177e4c Linux-2.6.12-rc2 |
426 |
|
32ee8c3e4 [CPUFREQ] Lots of... |
427 |
/* Error if no IST-SMI BIOS or no PARM |
1da177e4c Linux-2.6.12-rc2 |
428 |
sig= 'ISGE' aka 'Intel Speedstep Gate E' */ |
32ee8c3e4 [CPUFREQ] Lots of... |
429 |
if ((ist_info.signature != 0x47534943) && ( |
1da177e4c Linux-2.6.12-rc2 |
430 431 432 433 434 435 436 437 438 |
(smi_port == 0) || (smi_cmd == 0))) return -ENODEV; if (smi_sig == 1) smi_sig = 0x47534943; else smi_sig = ist_info.signature; /* setup smi_port from MODLULE_PARM or BIOS */ |
32ee8c3e4 [CPUFREQ] Lots of... |
439 |
if ((smi_port > 0xff) || (smi_port < 0)) |
1da177e4c Linux-2.6.12-rc2 |
440 |
return -EINVAL; |
32ee8c3e4 [CPUFREQ] Lots of... |
441 |
else if (smi_port == 0) |
1da177e4c Linux-2.6.12-rc2 |
442 |
smi_port = ist_info.command & 0xff; |
1da177e4c Linux-2.6.12-rc2 |
443 |
|
32ee8c3e4 [CPUFREQ] Lots of... |
444 |
if ((smi_cmd > 0xff) || (smi_cmd < 0)) |
1da177e4c Linux-2.6.12-rc2 |
445 |
return -EINVAL; |
32ee8c3e4 [CPUFREQ] Lots of... |
446 |
else if (smi_cmd == 0) |
1da177e4c Linux-2.6.12-rc2 |
447 |
smi_cmd = (ist_info.command >> 16) & 0xff; |
1da177e4c Linux-2.6.12-rc2 |
448 449 450 451 452 453 454 455 456 457 458 459 460 461 |
return cpufreq_register_driver(&speedstep_driver); } /** * speedstep_exit - unregisters SpeedStep support * * Unregisters SpeedStep support. */ static void __exit speedstep_exit(void) { cpufreq_unregister_driver(&speedstep_driver); } |
bbfebd665 [CPUFREQ] checkpa... |
462 463 464 |
module_param(smi_port, int, 0444); module_param(smi_cmd, int, 0444); module_param(smi_sig, uint, 0444); |
1da177e4c Linux-2.6.12-rc2 |
465 |
|
bbfebd665 [CPUFREQ] checkpa... |
466 467 468 469 470 471 |
MODULE_PARM_DESC(smi_port, "Override the BIOS-given IST port with this value " "-- Intel's default setting is 0xb2"); MODULE_PARM_DESC(smi_cmd, "Override the BIOS-given IST command with this value " "-- Intel's default setting is 0x82"); MODULE_PARM_DESC(smi_sig, "Set to 1 to fake the IST signature when using the " "SMI interface."); |
1da177e4c Linux-2.6.12-rc2 |
472 |
|
bbfebd665 [CPUFREQ] checkpa... |
473 474 475 |
MODULE_AUTHOR("Hiroshi Miura"); MODULE_DESCRIPTION("Speedstep driver for IST applet SMI interface."); MODULE_LICENSE("GPL"); |
1da177e4c Linux-2.6.12-rc2 |
476 477 478 |
module_init(speedstep_init); module_exit(speedstep_exit); |