diff options
author | Alan Cox <alan@linux.intel.com> | 2010-06-18 09:05:52 -0400 |
---|---|---|
committer | Matthew Garrett <mjg@redhat.com> | 2010-08-03 09:48:50 -0400 |
commit | c715a38bb7fc22fb8018b916c8a9f7ff017a8ad7 (patch) | |
tree | b51c087653a2e6cd9a03057cf995eca3100bfb0e /drivers/platform | |
parent | 97ba0af097dc3428b85dc6a1282968d7ba9510f5 (diff) |
rar: Move the RAR driver into the right place as its now clean
We exit staging rar! rar! rar!...
Signed-off-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Matthew Garrett <mjg@redhat.com>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/platform')
-rw-r--r-- | drivers/platform/x86/Kconfig | 22 | ||||
-rw-r--r-- | drivers/platform/x86/Makefile | 1 | ||||
-rw-r--r-- | drivers/platform/x86/intel_rar_register.c | 671 |
3 files changed, 694 insertions, 0 deletions
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 724b2ed1a3cb..2f173bc0ff05 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig | |||
@@ -539,6 +539,28 @@ config INTEL_SCU_IPC | |||
539 | some embedded Intel x86 platforms. This is not needed for PC-type | 539 | some embedded Intel x86 platforms. This is not needed for PC-type |
540 | machines. | 540 | machines. |
541 | 541 | ||
542 | config RAR_REGISTER | ||
543 | bool "Restricted Access Region Register Driver" | ||
544 | depends on PCI && X86_MRST | ||
545 | default n | ||
546 | ---help--- | ||
547 | This driver allows other kernel drivers access to the | ||
548 | contents of the restricted access region control registers. | ||
549 | |||
550 | The restricted access region control registers | ||
551 | (rar_registers) are used to pass address and | ||
552 | locking information on restricted access regions | ||
553 | to other drivers that use restricted access regions. | ||
554 | |||
555 | The restricted access regions are regions of memory | ||
556 | on the Intel MID Platform that are not accessible to | ||
557 | the x86 processor, but are accessible to dedicated | ||
558 | processors on board peripheral devices. | ||
559 | |||
560 | The purpose of the restricted access regions is to | ||
561 | protect sensitive data from compromise by unauthorized | ||
562 | programs running on the x86 processor. | ||
563 | |||
542 | config INTEL_IPS | 564 | config INTEL_IPS |
543 | tristate "Intel Intelligent Power Sharing" | 565 | tristate "Intel Intelligent Power Sharing" |
544 | depends on ACPI | 566 | depends on ACPI |
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index 7318fc2c1629..ed50eca1b556 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile | |||
@@ -26,4 +26,5 @@ obj-$(CONFIG_TOPSTAR_LAPTOP) += topstar-laptop.o | |||
26 | obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o | 26 | obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o |
27 | obj-$(CONFIG_TOSHIBA_BT_RFKILL) += toshiba_bluetooth.o | 27 | obj-$(CONFIG_TOSHIBA_BT_RFKILL) += toshiba_bluetooth.o |
28 | obj-$(CONFIG_INTEL_SCU_IPC) += intel_scu_ipc.o | 28 | obj-$(CONFIG_INTEL_SCU_IPC) += intel_scu_ipc.o |
29 | obj-$(CONFIG_RAR_REGISTER) += intel_rar_register.o | ||
29 | obj-$(CONFIG_INTEL_IPS) += intel_ips.o | 30 | obj-$(CONFIG_INTEL_IPS) += intel_ips.o |
diff --git a/drivers/platform/x86/intel_rar_register.c b/drivers/platform/x86/intel_rar_register.c new file mode 100644 index 000000000000..73f8e6d72669 --- /dev/null +++ b/drivers/platform/x86/intel_rar_register.c | |||
@@ -0,0 +1,671 @@ | |||
1 | /* | ||
2 | * rar_register.c - An Intel Restricted Access Region register driver | ||
3 | * | ||
4 | * Copyright(c) 2009 Intel Corporation. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation; either version 2 of the | ||
9 | * License, or (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||
19 | * 02111-1307, USA. | ||
20 | * | ||
21 | * ------------------------------------------------------------------- | ||
22 | * 20091204 Mark Allyn <mark.a.allyn@intel.com> | ||
23 | * Ossama Othman <ossama.othman@intel.com> | ||
24 | * Cleanup per feedback from Alan Cox and Arjan Van De Ven | ||
25 | * | ||
26 | * 20090806 Ossama Othman <ossama.othman@intel.com> | ||
27 | * Return zero high address if upper 22 bits is zero. | ||
28 | * Cleaned up checkpatch errors. | ||
29 | * Clarified that driver is dealing with bus addresses. | ||
30 | * | ||
31 | * 20090702 Ossama Othman <ossama.othman@intel.com> | ||
32 | * Removed unnecessary include directives | ||
33 | * Cleaned up spinlocks. | ||
34 | * Cleaned up logging. | ||
35 | * Improved invalid parameter checks. | ||
36 | * Fixed and simplified RAR address retrieval and RAR locking | ||
37 | * code. | ||
38 | * | ||
39 | * 20090626 Mark Allyn <mark.a.allyn@intel.com> | ||
40 | * Initial publish | ||
41 | */ | ||
42 | |||
43 | #include <linux/module.h> | ||
44 | #include <linux/pci.h> | ||
45 | #include <linux/spinlock.h> | ||
46 | #include <linux/device.h> | ||
47 | #include <linux/kernel.h> | ||
48 | #include <linux/rar_register.h> | ||
49 | |||
50 | /* === Lincroft Message Bus Interface === */ | ||
51 | #define LNC_MCR_OFFSET 0xD0 /* Message Control Register */ | ||
52 | #define LNC_MDR_OFFSET 0xD4 /* Message Data Register */ | ||
53 | |||
54 | /* Message Opcodes */ | ||
55 | #define LNC_MESSAGE_READ_OPCODE 0xD0 | ||
56 | #define LNC_MESSAGE_WRITE_OPCODE 0xE0 | ||
57 | |||
58 | /* Message Write Byte Enables */ | ||
59 | #define LNC_MESSAGE_BYTE_WRITE_ENABLES 0xF | ||
60 | |||
61 | /* B-unit Port */ | ||
62 | #define LNC_BUNIT_PORT 0x3 | ||
63 | |||
64 | /* === Lincroft B-Unit Registers - Programmed by IA32 firmware === */ | ||
65 | #define LNC_BRAR0L 0x10 | ||
66 | #define LNC_BRAR0H 0x11 | ||
67 | #define LNC_BRAR1L 0x12 | ||
68 | #define LNC_BRAR1H 0x13 | ||
69 | /* Reserved for SeP */ | ||
70 | #define LNC_BRAR2L 0x14 | ||
71 | #define LNC_BRAR2H 0x15 | ||
72 | |||
73 | /* Moorestown supports three restricted access regions. */ | ||
74 | #define MRST_NUM_RAR 3 | ||
75 | |||
76 | /* RAR Bus Address Range */ | ||
77 | struct rar_addr { | ||
78 | dma_addr_t low; | ||
79 | dma_addr_t high; | ||
80 | }; | ||
81 | |||
82 | /* | ||
83 | * We create one of these for each RAR | ||
84 | */ | ||
85 | struct client { | ||
86 | int (*callback)(unsigned long data); | ||
87 | unsigned long driver_priv; | ||
88 | bool busy; | ||
89 | }; | ||
90 | |||
91 | static DEFINE_MUTEX(rar_mutex); | ||
92 | static DEFINE_MUTEX(lnc_reg_mutex); | ||
93 | |||
94 | /* | ||
95 | * One per RAR device (currently only one device) | ||
96 | */ | ||
97 | struct rar_device { | ||
98 | struct rar_addr rar_addr[MRST_NUM_RAR]; | ||
99 | struct pci_dev *rar_dev; | ||
100 | bool registered; | ||
101 | bool allocated; | ||
102 | struct client client[MRST_NUM_RAR]; | ||
103 | }; | ||
104 | |||
105 | /* Current platforms have only one rar_device for 3 rar regions */ | ||
106 | static struct rar_device my_rar_device; | ||
107 | |||
108 | /* | ||
109 | * Abstract out multiple device support. Current platforms only | ||
110 | * have a single RAR device. | ||
111 | */ | ||
112 | |||
113 | /** | ||
114 | * alloc_rar_device - return a new RAR structure | ||
115 | * | ||
116 | * Return a new (but not yet ready) RAR device object | ||
117 | */ | ||
118 | static struct rar_device *alloc_rar_device(void) | ||
119 | { | ||
120 | if (my_rar_device.allocated) | ||
121 | return NULL; | ||
122 | my_rar_device.allocated = 1; | ||
123 | return &my_rar_device; | ||
124 | } | ||
125 | |||
126 | /** | ||
127 | * free_rar_device - free a RAR object | ||
128 | * @rar: the RAR device being freed | ||
129 | * | ||
130 | * Release a RAR object and any attached resources | ||
131 | */ | ||
132 | static void free_rar_device(struct rar_device *rar) | ||
133 | { | ||
134 | pci_dev_put(rar->rar_dev); | ||
135 | rar->allocated = 0; | ||
136 | } | ||
137 | |||
138 | /** | ||
139 | * _rar_to_device - return the device handling this RAR | ||
140 | * @rar: RAR number | ||
141 | * @off: returned offset | ||
142 | * | ||
143 | * Internal helper for looking up RAR devices. This and alloc are the | ||
144 | * two functions that need touching to go to multiple RAR devices. | ||
145 | */ | ||
146 | static struct rar_device *_rar_to_device(int rar, int *off) | ||
147 | { | ||
148 | if (rar >= 0 && rar <= 3) { | ||
149 | *off = rar; | ||
150 | return &my_rar_device; | ||
151 | } | ||
152 | return NULL; | ||
153 | } | ||
154 | |||
155 | /** | ||
156 | * rar_to_device - return the device handling this RAR | ||
157 | * @rar: RAR number | ||
158 | * @off: returned offset | ||
159 | * | ||
160 | * Return the device this RAR maps to if one is present, otherwise | ||
161 | * returns NULL. Reports the offset relative to the base of this | ||
162 | * RAR device in off. | ||
163 | */ | ||
164 | static struct rar_device *rar_to_device(int rar, int *off) | ||
165 | { | ||
166 | struct rar_device *rar_dev = _rar_to_device(rar, off); | ||
167 | if (rar_dev == NULL || !rar_dev->registered) | ||
168 | return NULL; | ||
169 | return rar_dev; | ||
170 | } | ||
171 | |||
172 | /** | ||
173 | * rar_to_client - return the client handling this RAR | ||
174 | * @rar: RAR number | ||
175 | * | ||
176 | * Return the client this RAR maps to if a mapping is known, otherwise | ||
177 | * returns NULL. | ||
178 | */ | ||
179 | static struct client *rar_to_client(int rar) | ||
180 | { | ||
181 | int idx; | ||
182 | struct rar_device *r = _rar_to_device(rar, &idx); | ||
183 | if (r != NULL) | ||
184 | return &r->client[idx]; | ||
185 | return NULL; | ||
186 | } | ||
187 | |||
188 | /** | ||
189 | * rar_read_addr - retrieve a RAR mapping | ||
190 | * @pdev: PCI device for the RAR | ||
191 | * @offset: offset for message | ||
192 | * @addr: returned address | ||
193 | * | ||
194 | * Reads the address of a given RAR register. Returns 0 on success | ||
195 | * or an error code on failure. | ||
196 | */ | ||
197 | static int rar_read_addr(struct pci_dev *pdev, int offset, dma_addr_t *addr) | ||
198 | { | ||
199 | /* | ||
200 | * ======== The Lincroft Message Bus Interface ======== | ||
201 | * Lincroft registers may be obtained via PCI from | ||
202 | * the host bridge using the Lincroft Message Bus | ||
203 | * Interface. That message bus interface is generally | ||
204 | * comprised of two registers: a control register (MCR, 0xDO) | ||
205 | * and a data register (MDR, 0xD4). | ||
206 | * | ||
207 | * The MCR (message control register) format is the following: | ||
208 | * 1. [31:24]: Opcode | ||
209 | * 2. [23:16]: Port | ||
210 | * 3. [15:8]: Register Offset | ||
211 | * 4. [7:4]: Byte Enables (use 0xF to set all of these bits | ||
212 | * to 1) | ||
213 | * 5. [3:0]: reserved | ||
214 | * | ||
215 | * Read (0xD0) and write (0xE0) opcodes are written to the | ||
216 | * control register when reading and writing to Lincroft | ||
217 | * registers, respectively. | ||
218 | * | ||
219 | * We're interested in registers found in the Lincroft | ||
220 | * B-unit. The B-unit port is 0x3. | ||
221 | * | ||
222 | * The six B-unit RAR register offsets we use are listed | ||
223 | * earlier in this file. | ||
224 | * | ||
225 | * Lastly writing to the MCR register requires the "Byte | ||
226 | * enables" bits to be set to 1. This may be achieved by | ||
227 | * writing 0xF at bit 4. | ||
228 | * | ||
229 | * The MDR (message data register) format is the following: | ||
230 | * 1. [31:0]: Read/Write Data | ||
231 | * | ||
232 | * Data being read from this register is only available after | ||
233 | * writing the appropriate control message to the MCR | ||
234 | * register. | ||
235 | * | ||
236 | * Data being written to this register must be written before | ||
237 | * writing the appropriate control message to the MCR | ||
238 | * register. | ||
239 | */ | ||
240 | |||
241 | int result; | ||
242 | u32 addr32; | ||
243 | |||
244 | /* Construct control message */ | ||
245 | u32 const message = | ||
246 | (LNC_MESSAGE_READ_OPCODE << 24) | ||
247 | | (LNC_BUNIT_PORT << 16) | ||
248 | | (offset << 8) | ||
249 | | (LNC_MESSAGE_BYTE_WRITE_ENABLES << 4); | ||
250 | |||
251 | dev_dbg(&pdev->dev, "Offset for 'get' LNC MSG is %x\n", offset); | ||
252 | |||
253 | /* | ||
254 | * We synchronize access to the Lincroft MCR and MDR registers | ||
255 | * until BOTH the command is issued through the MCR register | ||
256 | * and the corresponding data is read from the MDR register. | ||
257 | * Otherwise a race condition would exist between accesses to | ||
258 | * both registers. | ||
259 | */ | ||
260 | |||
261 | mutex_lock(&lnc_reg_mutex); | ||
262 | |||
263 | /* Send the control message */ | ||
264 | result = pci_write_config_dword(pdev, LNC_MCR_OFFSET, message); | ||
265 | if (!result) { | ||
266 | /* Read back the address as a 32bit value */ | ||
267 | result = pci_read_config_dword(pdev, LNC_MDR_OFFSET, &addr32); | ||
268 | *addr = (dma_addr_t)addr32; | ||
269 | } | ||
270 | mutex_unlock(&lnc_reg_mutex); | ||
271 | return result; | ||
272 | } | ||
273 | |||
274 | /** | ||
275 | * rar_set_addr - Set a RAR mapping | ||
276 | * @pdev: PCI device for the RAR | ||
277 | * @offset: offset for message | ||
278 | * @addr: address to set | ||
279 | * | ||
280 | * Sets the address of a given RAR register. Returns 0 on success | ||
281 | * or an error code on failure. | ||
282 | */ | ||
283 | static int rar_set_addr(struct pci_dev *pdev, | ||
284 | int offset, | ||
285 | dma_addr_t addr) | ||
286 | { | ||
287 | /* | ||
288 | * Data being written to this register must be written before | ||
289 | * writing the appropriate control message to the MCR | ||
290 | * register. | ||
291 | * See rar_get_addrs() for a description of the | ||
292 | * message bus interface being used here. | ||
293 | */ | ||
294 | |||
295 | int result; | ||
296 | |||
297 | /* Construct control message */ | ||
298 | u32 const message = (LNC_MESSAGE_WRITE_OPCODE << 24) | ||
299 | | (LNC_BUNIT_PORT << 16) | ||
300 | | (offset << 8) | ||
301 | | (LNC_MESSAGE_BYTE_WRITE_ENABLES << 4); | ||
302 | |||
303 | /* | ||
304 | * We synchronize access to the Lincroft MCR and MDR registers | ||
305 | * until BOTH the command is issued through the MCR register | ||
306 | * and the corresponding data is read from the MDR register. | ||
307 | * Otherwise a race condition would exist between accesses to | ||
308 | * both registers. | ||
309 | */ | ||
310 | |||
311 | mutex_lock(&lnc_reg_mutex); | ||
312 | |||
313 | /* Send the control message */ | ||
314 | result = pci_write_config_dword(pdev, LNC_MDR_OFFSET, addr); | ||
315 | if (!result) | ||
316 | /* And address */ | ||
317 | result = pci_write_config_dword(pdev, LNC_MCR_OFFSET, message); | ||
318 | |||
319 | mutex_unlock(&lnc_reg_mutex); | ||
320 | return result; | ||
321 | } | ||
322 | |||
323 | /* | ||
324 | * rar_init_params - Initialize RAR parameters | ||
325 | * @rar: RAR device to initialise | ||
326 | * | ||
327 | * Initialize RAR parameters, such as bus addresses, etc. Returns 0 | ||
328 | * on success, or an error code on failure. | ||
329 | */ | ||
330 | static int init_rar_params(struct rar_device *rar) | ||
331 | { | ||
332 | struct pci_dev *pdev = rar->rar_dev; | ||
333 | unsigned int i; | ||
334 | int result = 0; | ||
335 | int offset = 0x10; /* RAR 0 to 2 in order low/high/low/high/... */ | ||
336 | |||
337 | /* Retrieve RAR start and end bus addresses. | ||
338 | * Access the RAR registers through the Lincroft Message Bus | ||
339 | * Interface on PCI device: 00:00.0 Host bridge. | ||
340 | */ | ||
341 | |||
342 | for (i = 0; i < MRST_NUM_RAR; ++i) { | ||
343 | struct rar_addr *addr = &rar->rar_addr[i]; | ||
344 | |||
345 | result = rar_read_addr(pdev, offset++, &addr->low); | ||
346 | if (result != 0) | ||
347 | return result; | ||
348 | |||
349 | result = rar_read_addr(pdev, offset++, &addr->high); | ||
350 | if (result != 0) | ||
351 | return result; | ||
352 | |||
353 | |||
354 | /* | ||
355 | * Only the upper 22 bits of the RAR addresses are | ||
356 | * stored in their corresponding RAR registers so we | ||
357 | * must set the lower 10 bits accordingly. | ||
358 | |||
359 | * The low address has its lower 10 bits cleared, and | ||
360 | * the high address has all its lower 10 bits set, | ||
361 | * e.g.: | ||
362 | * low = 0x2ffffc00 | ||
363 | */ | ||
364 | |||
365 | addr->low &= (dma_addr_t)0xfffffc00u; | ||
366 | |||
367 | /* | ||
368 | * Set bits 9:0 on uppser address if bits 31:10 are non | ||
369 | * zero; otherwize clear all bits | ||
370 | */ | ||
371 | |||
372 | if ((addr->high & 0xfffffc00u) == 0) | ||
373 | addr->high = 0; | ||
374 | else | ||
375 | addr->high |= 0x3ffu; | ||
376 | } | ||
377 | /* Done accessing the device. */ | ||
378 | |||
379 | if (result == 0) { | ||
380 | for (i = 0; i != MRST_NUM_RAR; ++i) { | ||
381 | /* | ||
382 | * "BRAR" refers to the RAR registers in the | ||
383 | * Lincroft B-unit. | ||
384 | */ | ||
385 | dev_info(&pdev->dev, "BRAR[%u] bus address range = " | ||
386 | "[%lx, %lx]\n", i, | ||
387 | (unsigned long)rar->rar_addr[i].low, | ||
388 | (unsigned long)rar->rar_addr[i].high); | ||
389 | } | ||
390 | } | ||
391 | return result; | ||
392 | } | ||
393 | |||
394 | /** | ||
395 | * rar_get_address - get the bus address in a RAR | ||
396 | * @start: return value of start address of block | ||
397 | * @end: return value of end address of block | ||
398 | * | ||
399 | * The rar_get_address function is used by other device drivers | ||
400 | * to obtain RAR address information on a RAR. It takes three | ||
401 | * parameters: | ||
402 | * | ||
403 | * The function returns a 0 upon success or an error if there is no RAR | ||
404 | * facility on this system. | ||
405 | */ | ||
406 | int rar_get_address(int rar_index, dma_addr_t *start, dma_addr_t *end) | ||
407 | { | ||
408 | int idx; | ||
409 | struct rar_device *rar = rar_to_device(rar_index, &idx); | ||
410 | |||
411 | if (rar == NULL) { | ||
412 | WARN_ON(1); | ||
413 | return -ENODEV; | ||
414 | } | ||
415 | |||
416 | *start = rar->rar_addr[idx].low; | ||
417 | *end = rar->rar_addr[idx].high; | ||
418 | return 0; | ||
419 | } | ||
420 | EXPORT_SYMBOL(rar_get_address); | ||
421 | |||
422 | /** | ||
423 | * rar_lock - lock a RAR register | ||
424 | * @rar_index: RAR to lock (0-2) | ||
425 | * | ||
426 | * The rar_lock function is ued by other device drivers to lock an RAR. | ||
427 | * once a RAR is locked, it stays locked until the next system reboot. | ||
428 | * | ||
429 | * The function returns a 0 upon success or an error if there is no RAR | ||
430 | * facility on this system, or the locking fails | ||
431 | */ | ||
432 | int rar_lock(int rar_index) | ||
433 | { | ||
434 | struct rar_device *rar; | ||
435 | int result; | ||
436 | int idx; | ||
437 | dma_addr_t low, high; | ||
438 | |||
439 | rar = rar_to_device(rar_index, &idx); | ||
440 | |||
441 | if (rar == NULL) { | ||
442 | WARN_ON(1); | ||
443 | return -EINVAL; | ||
444 | } | ||
445 | |||
446 | low = rar->rar_addr[idx].low & 0xfffffc00u; | ||
447 | high = rar->rar_addr[idx].high & 0xfffffc00u; | ||
448 | |||
449 | /* | ||
450 | * Only allow I/O from the graphics and Langwell; | ||
451 | * not from the x86 processor | ||
452 | */ | ||
453 | |||
454 | if (rar_index == RAR_TYPE_VIDEO) { | ||
455 | low |= 0x00000009; | ||
456 | high |= 0x00000015; | ||
457 | } else if (rar_index == RAR_TYPE_AUDIO) { | ||
458 | /* Only allow I/O from Langwell; nothing from x86 */ | ||
459 | low |= 0x00000008; | ||
460 | high |= 0x00000018; | ||
461 | } else | ||
462 | /* Read-only from all agents */ | ||
463 | high |= 0x00000018; | ||
464 | |||
465 | /* | ||
466 | * Now program the register using the Lincroft message | ||
467 | * bus interface. | ||
468 | */ | ||
469 | result = rar_set_addr(rar->rar_dev, | ||
470 | 2 * idx, low); | ||
471 | |||
472 | if (result == 0) | ||
473 | result = rar_set_addr(rar->rar_dev, | ||
474 | 2 * idx + 1, high); | ||
475 | |||
476 | return result; | ||
477 | } | ||
478 | EXPORT_SYMBOL(rar_lock); | ||
479 | |||
480 | /** | ||
481 | * register_rar - register a RAR handler | ||
482 | * @num: RAR we wish to register for | ||
483 | * @callback: function to call when RAR support is available | ||
484 | * @data: data to pass to this function | ||
485 | * | ||
486 | * The register_rar function is to used by other device drivers | ||
487 | * to ensure that this driver is ready. As we cannot be sure of | ||
488 | * the compile/execute order of drivers in ther kernel, it is | ||
489 | * best to give this driver a callback function to call when | ||
490 | * it is ready to give out addresses. The callback function | ||
491 | * would have those steps that continue the initialization of | ||
492 | * a driver that do require a valid RAR address. One of those | ||
493 | * steps would be to call rar_get_address() | ||
494 | * | ||
495 | * This function return 0 on success or an error code on failure. | ||
496 | */ | ||
497 | int register_rar(int num, int (*callback)(unsigned long data), | ||
498 | unsigned long data) | ||
499 | { | ||
500 | /* For now we hardcode a single RAR device */ | ||
501 | struct rar_device *rar; | ||
502 | struct client *c; | ||
503 | int idx; | ||
504 | int retval = 0; | ||
505 | |||
506 | mutex_lock(&rar_mutex); | ||
507 | |||
508 | /* Do we have a client mapping for this RAR number ? */ | ||
509 | c = rar_to_client(num); | ||
510 | if (c == NULL) { | ||
511 | retval = -ERANGE; | ||
512 | goto done; | ||
513 | } | ||
514 | /* Is it claimed ? */ | ||
515 | if (c->busy) { | ||
516 | retval = -EBUSY; | ||
517 | goto done; | ||
518 | } | ||
519 | c->busy = 1; | ||
520 | |||
521 | /* See if we have a handler for this RAR yet, if we do then fire it */ | ||
522 | rar = rar_to_device(num, &idx); | ||
523 | |||
524 | if (rar) { | ||
525 | /* | ||
526 | * if the driver already registered, then we can simply | ||
527 | * call the callback right now | ||
528 | */ | ||
529 | (*callback)(data); | ||
530 | goto done; | ||
531 | } | ||
532 | |||
533 | /* Arrange to be called back when the hardware is found */ | ||
534 | c->callback = callback; | ||
535 | c->driver_priv = data; | ||
536 | done: | ||
537 | mutex_unlock(&rar_mutex); | ||
538 | return retval; | ||
539 | } | ||
540 | EXPORT_SYMBOL(register_rar); | ||
541 | |||
542 | /** | ||
543 | * unregister_rar - release a RAR allocation | ||
544 | * @num: RAR number | ||
545 | * | ||
546 | * Releases a RAR allocation, or pending allocation. If a callback is | ||
547 | * pending then this function will either complete before the unregister | ||
548 | * returns or not at all. | ||
549 | */ | ||
550 | |||
551 | void unregister_rar(int num) | ||
552 | { | ||
553 | struct client *c; | ||
554 | |||
555 | mutex_lock(&rar_mutex); | ||
556 | c = rar_to_client(num); | ||
557 | if (c == NULL || !c->busy) | ||
558 | WARN_ON(1); | ||
559 | else | ||
560 | c->busy = 0; | ||
561 | mutex_unlock(&rar_mutex); | ||
562 | } | ||
563 | EXPORT_SYMBOL(unregister_rar); | ||
564 | |||
565 | /** | ||
566 | * rar_callback - Process callbacks | ||
567 | * @rar: new RAR device | ||
568 | * | ||
569 | * Process the callbacks for a newly found RAR device. | ||
570 | */ | ||
571 | |||
572 | static void rar_callback(struct rar_device *rar) | ||
573 | { | ||
574 | struct client *c = &rar->client[0]; | ||
575 | int i; | ||
576 | |||
577 | mutex_lock(&rar_mutex); | ||
578 | |||
579 | rar->registered = 1; /* Ensure no more callbacks queue */ | ||
580 | |||
581 | for (i = 0; i < MRST_NUM_RAR; i++) { | ||
582 | if (c->callback && c->busy) { | ||
583 | c->callback(c->driver_priv); | ||
584 | c->callback = NULL; | ||
585 | } | ||
586 | c++; | ||
587 | } | ||
588 | mutex_unlock(&rar_mutex); | ||
589 | } | ||
590 | |||
591 | /** | ||
592 | * rar_probe - PCI probe callback | ||
593 | * @dev: PCI device | ||
594 | * @id: matching entry in the match table | ||
595 | * | ||
596 | * A RAR device has been discovered. Initialise it and if successful | ||
597 | * process any pending callbacks that can now be completed. | ||
598 | */ | ||
599 | static int rar_probe(struct pci_dev *dev, const struct pci_device_id *id) | ||
600 | { | ||
601 | int error; | ||
602 | struct rar_device *rar; | ||
603 | |||
604 | dev_dbg(&dev->dev, "PCI probe starting\n"); | ||
605 | |||
606 | rar = alloc_rar_device(); | ||
607 | if (rar == NULL) | ||
608 | return -EBUSY; | ||
609 | |||
610 | /* Enable the device */ | ||
611 | error = pci_enable_device(dev); | ||
612 | if (error) { | ||
613 | dev_err(&dev->dev, | ||
614 | "Error enabling RAR register PCI device\n"); | ||
615 | goto end_function; | ||
616 | } | ||
617 | |||
618 | /* Fill in the rar_device structure */ | ||
619 | rar->rar_dev = pci_dev_get(dev); | ||
620 | pci_set_drvdata(dev, rar); | ||
621 | |||
622 | /* | ||
623 | * Initialize the RAR parameters, which have to be retrieved | ||
624 | * via the message bus interface. | ||
625 | */ | ||
626 | error = init_rar_params(rar); | ||
627 | if (error) { | ||
628 | pci_disable_device(dev); | ||
629 | dev_err(&dev->dev, "Error retrieving RAR addresses\n"); | ||
630 | goto end_function; | ||
631 | } | ||
632 | /* now call anyone who has registered (using callbacks) */ | ||
633 | rar_callback(rar); | ||
634 | return 0; | ||
635 | end_function: | ||
636 | free_rar_device(rar); | ||
637 | return error; | ||
638 | } | ||
639 | |||
640 | const struct pci_device_id rar_pci_id_tbl[] = { | ||
641 | { PCI_VDEVICE(INTEL, 0x4110) }, | ||
642 | { 0 } | ||
643 | }; | ||
644 | |||
645 | MODULE_DEVICE_TABLE(pci, rar_pci_id_tbl); | ||
646 | |||
647 | const struct pci_device_id *my_id_table = rar_pci_id_tbl; | ||
648 | |||
649 | /* field for registering driver to PCI device */ | ||
650 | static struct pci_driver rar_pci_driver = { | ||
651 | .name = "rar_register_driver", | ||
652 | .id_table = rar_pci_id_tbl, | ||
653 | .probe = rar_probe, | ||
654 | /* Cannot be unplugged - no remove */ | ||
655 | }; | ||
656 | |||
657 | static int __init rar_init_handler(void) | ||
658 | { | ||
659 | return pci_register_driver(&rar_pci_driver); | ||
660 | } | ||
661 | |||
662 | static void __exit rar_exit_handler(void) | ||
663 | { | ||
664 | pci_unregister_driver(&rar_pci_driver); | ||
665 | } | ||
666 | |||
667 | module_init(rar_init_handler); | ||
668 | module_exit(rar_exit_handler); | ||
669 | |||
670 | MODULE_LICENSE("GPL"); | ||
671 | MODULE_DESCRIPTION("Intel Restricted Access Region Register Driver"); | ||