OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [acpi/] [pci_link.c] - Blame information for rev 1275

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *  pci_link.c - ACPI PCI Interrupt Link Device Driver ($Revision: 1.1.1.1 $)
3
 *
4
 *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
5
 *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
6
 *  Copyright (C) 2002       Dominik Brodowski <devel@brodo.de>
7
 *
8
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9
 *
10
 *  This program is free software; you can redistribute it and/or modify
11
 *  it under the terms of the GNU General Public License as published by
12
 *  the Free Software Foundation; either version 2 of the License, or (at
13
 *  your option) any later version.
14
 *
15
 *  This program is distributed in the hope that it will be useful, but
16
 *  WITHOUT ANY WARRANTY; without even the implied warranty of
17
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18
 *  General Public License for more details.
19
 *
20
 *  You should have received a copy of the GNU General Public License along
21
 *  with this program; if not, write to the Free Software Foundation, Inc.,
22
 *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
23
 *
24
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25
 *
26
 * TBD:
27
 *      1. Support more than one IRQ resource entry per link device (index).
28
 *      2. Implement start/stop mechanism and use ACPI Bus Driver facilities
29
 *         for IRQ management (e.g. start()->_SRS).
30
 */
31
 
32
#include <linux/kernel.h>
33
#include <linux/module.h>
34
#include <linux/init.h>
35
#include <linux/types.h>
36
#include <linux/proc_fs.h>
37
#include <linux/spinlock.h>
38
#include <linux/pm.h>
39
#include <linux/pci.h>
40
 
41
#include <acpi/acpi_bus.h>
42
#include <acpi/acpi_drivers.h>
43
 
44
 
45
#define _COMPONENT              ACPI_PCI_COMPONENT
46
ACPI_MODULE_NAME                ("pci_link")
47
 
48
#define PREFIX                  "ACPI: "
49
 
50
 
51
#define ACPI_PCI_LINK_MAX_POSSIBLE 16
52
 
53
static int acpi_pci_link_add (struct acpi_device *device);
54
static int acpi_pci_link_remove (struct acpi_device *device, int type);
55
 
56
static struct acpi_driver acpi_pci_link_driver = {
57
        .name =         ACPI_PCI_LINK_DRIVER_NAME,
58
        .class =        ACPI_PCI_LINK_CLASS,
59
        .ids =          ACPI_PCI_LINK_HID,
60
        .ops =          {
61
                                .add =    acpi_pci_link_add,
62
                                .remove = acpi_pci_link_remove,
63
                        },
64
};
65
 
66
struct acpi_pci_link_irq {
67
        u8                      active;                 /* Current IRQ */
68
        u8                      edge_level;             /* All IRQs */
69
        u8                      active_high_low;        /* All IRQs */
70
        u8                      setonboot;
71
        u8                      resource_type;
72
        u8                      possible_count;
73
        u8                      possible[ACPI_PCI_LINK_MAX_POSSIBLE];
74
};
75
 
76
struct acpi_pci_link {
77
        struct list_head        node;
78
        struct acpi_device      *device;
79
        acpi_handle             handle;
80
        struct acpi_pci_link_irq irq;
81
};
82
 
83
static struct {
84
        int                     count;
85
        struct list_head        entries;
86
}                               acpi_link;
87
 
88
 
89
/* --------------------------------------------------------------------------
90
                            PCI Link Device Management
91
   -------------------------------------------------------------------------- */
92
 
93
static acpi_status
94
acpi_pci_link_check_possible (
95
        struct acpi_resource    *resource,
96
        void                    *context)
97
{
98
        struct acpi_pci_link    *link = (struct acpi_pci_link *) context;
99
        u32                     i = 0;
100
 
101
        ACPI_FUNCTION_TRACE("acpi_pci_link_check_possible");
102
 
103
        switch (resource->id) {
104
        case ACPI_RSTYPE_START_DPF:
105
                return AE_OK;
106
        case ACPI_RSTYPE_IRQ:
107
        {
108
                struct acpi_resource_irq *p = &resource->data.irq;
109
                if (!p || !p->number_of_interrupts) {
110
                        ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Blank IRQ resource\n"));
111
                        return AE_OK;
112
                }
113
                for (i = 0; (i<p->number_of_interrupts && i<ACPI_PCI_LINK_MAX_POSSIBLE); i++) {
114
                        if (!p->interrupts[i]) {
115
                                ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ %d\n", p->interrupts[i]));
116
                                continue;
117
                        }
118
                        link->irq.possible[i] = p->interrupts[i];
119
                        link->irq.possible_count++;
120
                }
121
                link->irq.edge_level = p->edge_level;
122
                link->irq.active_high_low = p->active_high_low;
123
                link->irq.resource_type = ACPI_RSTYPE_IRQ;
124
                break;
125
        }
126
        case ACPI_RSTYPE_EXT_IRQ:
127
        {
128
                struct acpi_resource_ext_irq *p = &resource->data.extended_irq;
129
                if (!p || !p->number_of_interrupts) {
130
                        ACPI_DEBUG_PRINT((ACPI_DB_WARN,
131
                                "Blank IRQ resource\n"));
132
                        return AE_OK;
133
                }
134
                for (i = 0; (i<p->number_of_interrupts && i<ACPI_PCI_LINK_MAX_POSSIBLE); i++) {
135
                        if (!p->interrupts[i]) {
136
                                ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ %d\n", p->interrupts[i]));
137
                                continue;
138
                        }
139
                        link->irq.possible[i] = p->interrupts[i];
140
                        link->irq.possible_count++;
141
                }
142
                link->irq.edge_level = p->edge_level;
143
                link->irq.active_high_low = p->active_high_low;
144
                link->irq.resource_type = ACPI_RSTYPE_EXT_IRQ;
145
                break;
146
        }
147
        default:
148
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
149
                        "Resource is not an IRQ entry\n"));
150
                return AE_OK;
151
        }
152
 
153
        return AE_CTRL_TERMINATE;
154
}
155
 
156
 
157
static int
158
acpi_pci_link_get_possible (
159
        struct acpi_pci_link    *link)
160
{
161
        acpi_status             status;
162
 
163
        ACPI_FUNCTION_TRACE("acpi_pci_link_get_possible");
164
 
165
        if (!link)
166
                return_VALUE(-EINVAL);
167
 
168
        status = acpi_walk_resources(link->handle, METHOD_NAME__PRS,
169
                        acpi_pci_link_check_possible, link);
170
        if (ACPI_FAILURE(status)) {
171
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRS\n"));
172
                return_VALUE(-ENODEV);
173
        }
174
 
175
        ACPI_DEBUG_PRINT((ACPI_DB_INFO,
176
                "Found %d possible IRQs\n", link->irq.possible_count));
177
 
178
        return_VALUE(0);
179
}
180
 
181
 
182
static acpi_status
183
acpi_pci_link_check_current (
184
        struct acpi_resource    *resource,
185
        void                    *context)
186
{
187
        int                     *irq = (int *) context;
188
 
189
        ACPI_FUNCTION_TRACE("acpi_pci_link_check_current");
190
 
191
        switch (resource->id) {
192
        case ACPI_RSTYPE_IRQ:
193
        {
194
                struct acpi_resource_irq *p = &resource->data.irq;
195
                if (!p || !p->number_of_interrupts) {
196
                        ACPI_DEBUG_PRINT((ACPI_DB_WARN,
197
                                "Blank IRQ resource\n"));
198
                        return AE_OK;
199
                }
200
                *irq = p->interrupts[0];
201
                break;
202
        }
203
        case ACPI_RSTYPE_EXT_IRQ:
204
        {
205
                struct acpi_resource_ext_irq *p = &resource->data.extended_irq;
206
                if (!p || !p->number_of_interrupts) {
207
                        ACPI_DEBUG_PRINT((ACPI_DB_WARN,
208
                                "Blank IRQ resource\n"));
209
                        return AE_OK;
210
                }
211
                *irq = p->interrupts[0];
212
                break;
213
        }
214
        default:
215
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
216
                        "Resource isn't an IRQ\n"));
217
                return AE_OK;
218
        }
219
        return AE_CTRL_TERMINATE;
220
}
221
 
222
static int
223
acpi_pci_link_get_current (
224
        struct acpi_pci_link    *link)
225
{
226
        int                     result = 0;
227
        acpi_status             status = AE_OK;
228
        int                     irq = 0;
229
 
230
        ACPI_FUNCTION_TRACE("acpi_pci_link_get_current");
231
 
232
        if (!link || !link->handle)
233
                return_VALUE(-EINVAL);
234
 
235
        link->irq.active = 0;
236
 
237
        /* Make sure the link is enabled (no use querying if it isn't). */
238
        result = acpi_bus_get_status(link->device);
239
        if (result) {
240
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to read status\n"));
241
                goto end;
242
        }
243
        if (!link->device->status.enabled) {
244
                ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Link disabled\n"));
245
                return_VALUE(0);
246
        }
247
 
248
        /*
249
         * Query and parse _CRS to get the current IRQ assignment.
250
         */
251
 
252
        status = acpi_walk_resources(link->handle, METHOD_NAME__CRS,
253
                        acpi_pci_link_check_current, &irq);
254
        if (ACPI_FAILURE(status)) {
255
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _CRS\n"));
256
                result = -ENODEV;
257
                goto end;
258
        }
259
 
260
        if (!irq) {
261
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "No IRQ resource found\n"));
262
                result = -ENODEV;
263
                goto end;
264
        }
265
 
266
        /*
267
         * Note that we don't validate that the current IRQ (_CRS) exists
268
         * within the possible IRQs (_PRS): we blindly assume that whatever
269
         * IRQ a boot-enabled Link device is set to is the correct one.
270
         * (Required to support systems such as the Toshiba 5005-S504.)
271
         */
272
        link->irq.active = irq;
273
 
274
        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Link at IRQ %d \n", link->irq.active));
275
 
276
end:
277
        return_VALUE(result);
278
}
279
 
280
static int
281
acpi_pci_link_try_get_current (
282
        struct acpi_pci_link *link,
283
        int irq)
284
{
285
        int result;
286
 
287
        ACPI_FUNCTION_TRACE("acpi_pci_link_try_get_current");
288
 
289
        result = acpi_pci_link_get_current(link);
290
        if (result && link->irq.active) {
291
                return_VALUE(result);
292
        }
293
 
294
        if (!link->irq.active) {
295
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "No active IRQ resource found\n"));
296
                printk(KERN_WARNING "_CRS returns NULL! Using IRQ %d for"
297
                        "device (%s [%s]).\n", irq,
298
                        acpi_device_name(link->device),
299
                        acpi_device_bid(link->device));
300
                link->irq.active = irq;
301
        }
302
 
303
        return 0;
304
}
305
 
306
static int
307
acpi_pci_link_set (
308
        struct acpi_pci_link    *link,
309
        int                     irq)
310
{
311
        int                     result = 0;
312
        acpi_status             status = AE_OK;
313
        struct {
314
                struct acpi_resource    res;
315
                struct acpi_resource    end;
316
        }                       resource;
317
        struct acpi_buffer      buffer = {sizeof(resource)+1, &resource};
318
        int                     i = 0;
319
        int                     valid = 0;
320
        int                     resource_type = 0;
321
 
322
        ACPI_FUNCTION_TRACE("acpi_pci_link_set");
323
 
324
        if (!link || !irq)
325
                return_VALUE(-EINVAL);
326
 
327
        /* We don't check irqs the first time around */
328
        if (link->irq.setonboot) {
329
                /* See if we're already at the target IRQ. */
330
                if (irq == link->irq.active)
331
                        return_VALUE(0);
332
 
333
                /* Make sure the target IRQ in the list of possible IRQs. */
334
                for (i=0; i<link->irq.possible_count; i++) {
335
                        if (irq == link->irq.possible[i])
336
                                valid = 1;
337
                }
338
                if (!valid) {
339
                        ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Target IRQ %d invalid\n", irq));
340
                        return_VALUE(-EINVAL);
341
                }
342
        }
343
 
344
        resource_type = link->irq.resource_type;
345
 
346
        if (resource_type != ACPI_RSTYPE_IRQ &&
347
                        resource_type != ACPI_RSTYPE_EXT_IRQ){
348
        /* If IRQ<=15, first try with a "normal" IRQ descriptor. If that fails, try with
349
         * an extended one */
350
                if (irq <= 15) {
351
                        resource_type = ACPI_RSTYPE_IRQ;
352
                } else {
353
                        resource_type = ACPI_RSTYPE_EXT_IRQ;
354
                }
355
        }
356
 
357
retry_programming:
358
 
359
        memset(&resource, 0, sizeof(resource));
360
 
361
        /* NOTE: PCI interrupts are always level / active_low / shared. But not all
362
           interrupts > 15 are PCI interrupts. Rely on the ACPI IRQ definition for
363
           parameters */
364
        switch(resource_type) {
365
        case ACPI_RSTYPE_IRQ:
366
                resource.res.id = ACPI_RSTYPE_IRQ;
367
                resource.res.length = sizeof(struct acpi_resource);
368
                resource.res.data.irq.edge_level = link->irq.edge_level;
369
                resource.res.data.irq.active_high_low = link->irq.active_high_low;
370
                resource.res.data.irq.shared_exclusive = ACPI_SHARED;
371
                resource.res.data.irq.number_of_interrupts = 1;
372
                resource.res.data.irq.interrupts[0] = irq;
373
                break;
374
 
375
        case ACPI_RSTYPE_EXT_IRQ:
376
                resource.res.id = ACPI_RSTYPE_EXT_IRQ;
377
                resource.res.length = sizeof(struct acpi_resource);
378
                resource.res.data.extended_irq.producer_consumer = ACPI_CONSUMER;
379
                resource.res.data.extended_irq.edge_level = link->irq.edge_level;
380
                resource.res.data.extended_irq.active_high_low = link->irq.active_high_low;
381
                resource.res.data.extended_irq.shared_exclusive = ACPI_SHARED;
382
                resource.res.data.extended_irq.number_of_interrupts = 1;
383
                resource.res.data.extended_irq.interrupts[0] = irq;
384
                /* ignore resource_source, it's optional */
385
                break;
386
        }
387
        resource.end.id = ACPI_RSTYPE_END_TAG;
388
 
389
        /* Attempt to set the resource */
390
        status = acpi_set_current_resources(link->handle, &buffer);
391
 
392
 
393
        /* if we failed and IRQ <= 15, try again with an extended descriptor */
394
        if (ACPI_FAILURE(status) && (resource_type == ACPI_RSTYPE_IRQ)) {
395
                resource_type = ACPI_RSTYPE_EXT_IRQ;
396
                printk(PREFIX "Retrying with extended IRQ descriptor\n");
397
                goto retry_programming;
398
        }
399
 
400
        /* check for total failure */
401
        if (ACPI_FAILURE(status)) {
402
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _SRS\n"));
403
                return_VALUE(-ENODEV);
404
        }
405
 
406
        /* Make sure the device is enabled. */
407
        result = acpi_bus_get_status(link->device);
408
        if (result) {
409
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to read status\n"));
410
                return_VALUE(result);
411
        }
412
        if (!link->device->status.enabled) {
413
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link disabled\n"));
414
                return_VALUE(-ENODEV);
415
        }
416
 
417
        /* Make sure the active IRQ is the one we requested. */
418
        result = acpi_pci_link_try_get_current(link, irq);
419
        if (result) {
420
                return_VALUE(result);
421
        }
422
 
423
        if (link->irq.active != irq) {
424
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
425
                        "Attempt to enable at IRQ %d resulted in IRQ %d\n",
426
                        irq, link->irq.active));
427
                link->irq.active = 0;
428
                acpi_ut_evaluate_object (link->handle, "_DIS", 0, NULL);
429
                return_VALUE(-ENODEV);
430
        }
431
 
432
        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Set IRQ %d\n", link->irq.active));
433
 
434
        return_VALUE(0);
435
}
436
 
437
 
438
/* --------------------------------------------------------------------------
439
                            PCI Link IRQ Management
440
   -------------------------------------------------------------------------- */
441
 
442
/*
443
 * "acpi_irq_balance" (default in APIC mode) enables ACPI to use PIC Interrupt
444
 * Link Devices to move the PIRQs around to minimize sharing.
445
 *
446
 * "acpi_irq_nobalance" (default in PIC mode) tells ACPI not to move any PIC IRQs
447
 * that the BIOS has already set to active.  This is necessary because
448
 * ACPI has no automatic means of knowing what ISA IRQs are used.  Note that
449
 * if the BIOS doesn't set a Link Device active, ACPI needs to program it
450
 * even if acpi_irq_nobalance is set.
451
 *
452
 * A tables of penalties avoids directing PCI interrupts to well known
453
 * ISA IRQs. Boot params are available to over-ride the default table:
454
 *
455
 * List interrupts that are free for PCI use.
456
 * acpi_irq_pci=n[,m]
457
 *
458
 * List interrupts that should not be used for PCI:
459
 * acpi_irq_isa=n[,m]
460
 *
461
 * Note that PCI IRQ routers have a list of possible IRQs,
462
 * which may not include the IRQs this table says are available.
463
 *
464
 * Since this heuristic can't tell the difference between a link
465
 * that no device will attach to, vs. a link which may be shared
466
 * by multiple active devices -- it is not optimal.
467
 *
468
 * If interrupt performance is that important, get an IO-APIC system
469
 * with a pin dedicated to each device.  Or for that matter, an MSI
470
 * enabled system.
471
 */
472
 
473
#define ACPI_MAX_IRQS           256
474
#define ACPI_MAX_ISA_IRQ        16
475
 
476
#define PIRQ_PENALTY_PCI_AVAILABLE      (0)
477
#define PIRQ_PENALTY_PCI_POSSIBLE       (16*16)
478
#define PIRQ_PENALTY_PCI_USING          (16*16*16)
479
#define PIRQ_PENALTY_ISA_TYPICAL        (16*16*16*16)
480
#define PIRQ_PENALTY_ISA_USED           (16*16*16*16*16)
481
#define PIRQ_PENALTY_ISA_ALWAYS         (16*16*16*16*16*16)
482
 
483
static int acpi_irq_penalty[ACPI_MAX_IRQS] = {
484
        PIRQ_PENALTY_ISA_ALWAYS,        /* IRQ0 timer */
485
        PIRQ_PENALTY_ISA_ALWAYS,        /* IRQ1 keyboard */
486
        PIRQ_PENALTY_ISA_ALWAYS,        /* IRQ2 cascade */
487
        PIRQ_PENALTY_ISA_TYPICAL,       /* IRQ3 serial */
488
        PIRQ_PENALTY_ISA_TYPICAL,       /* IRQ4 serial */
489
        PIRQ_PENALTY_ISA_TYPICAL,       /* IRQ5 sometimes SoundBlaster */
490
        PIRQ_PENALTY_ISA_TYPICAL,       /* IRQ6 */
491
        PIRQ_PENALTY_ISA_TYPICAL,       /* IRQ7 parallel, spurious */
492
        PIRQ_PENALTY_ISA_TYPICAL,       /* IRQ8 rtc, sometimes */
493
        PIRQ_PENALTY_PCI_AVAILABLE,     /* IRQ9  PCI, often acpi */
494
        PIRQ_PENALTY_PCI_AVAILABLE,     /* IRQ10 PCI */
495
        PIRQ_PENALTY_PCI_AVAILABLE,     /* IRQ11 PCI */
496
        PIRQ_PENALTY_ISA_TYPICAL,       /* IRQ12 mouse */
497
        PIRQ_PENALTY_ISA_USED,  /* IRQ13 fpe, sometimes */
498
        PIRQ_PENALTY_ISA_USED,  /* IRQ14 ide0 */
499
        PIRQ_PENALTY_ISA_USED,  /* IRQ15 ide1 */
500
                        /* >IRQ15 */
501
};
502
 
503
int
504
acpi_pci_link_check (void)
505
{
506
        struct list_head        *node = NULL;
507
        struct acpi_pci_link    *link = NULL;
508
        int                     i = 0;
509
 
510
        ACPI_FUNCTION_TRACE("acpi_pci_link_check");
511
 
512
        /*
513
         * Update penalties to facilitate IRQ balancing.
514
         */
515
        list_for_each(node, &acpi_link.entries) {
516
 
517
                link = list_entry(node, struct acpi_pci_link, node);
518
                if (!link) {
519
                        ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n"));
520
                        continue;
521
                }
522
 
523
                /*
524
                 * reflect the possible and active irqs in the penalty table --
525
                 * useful for breaking ties.
526
                 */
527
                if (link->irq.possible_count) {
528
                        int penalty = PIRQ_PENALTY_PCI_POSSIBLE / link->irq.possible_count;
529
 
530
                        for (i = 0; i < link->irq.possible_count; i++) {
531
                                if (link->irq.possible[i] < ACPI_MAX_ISA_IRQ)
532
                                        acpi_irq_penalty[link->irq.possible[i]] += penalty;
533
                        }
534
 
535
                } else if (link->irq.active) {
536
                        acpi_irq_penalty[link->irq.active] += PIRQ_PENALTY_PCI_POSSIBLE;
537
                }
538
        }
539
        /* Add a penalty for the SCI */
540
        acpi_irq_penalty[acpi_fadt.sci_int] += PIRQ_PENALTY_PCI_USING;
541
 
542
        return_VALUE(0);
543
}
544
 
545
static int acpi_irq_balance;    /* 0: static, 1: balance */
546
 
547
static int acpi_pci_link_allocate(struct acpi_pci_link* link) {
548
        int irq;
549
        int i;
550
 
551
        ACPI_FUNCTION_TRACE("acpi_pci_link_allocate");
552
 
553
        if (link->irq.setonboot)
554
                return_VALUE(0);
555
 
556
        if (link->irq.active) {
557
                irq = link->irq.active;
558
        } else {
559
                irq = link->irq.possible[0];
560
        }
561
 
562
        if (acpi_irq_balance || !link->irq.active) {
563
                /*
564
                 * Select the best IRQ.  This is done in reverse to promote
565
                 * the use of IRQs 9, 10, 11, and >15.
566
                 */
567
                for (i = (link->irq.possible_count - 1); i >= 0; i--) {
568
                        if (acpi_irq_penalty[irq] > acpi_irq_penalty[link->irq.possible[i]])
569
                                irq = link->irq.possible[i];
570
                }
571
        }
572
 
573
        /* Attempt to enable the link device at this IRQ. */
574
        if (acpi_pci_link_set(link, irq)) {
575
                printk(PREFIX "Unable to set IRQ for %s [%s] (likely buggy ACPI BIOS). Aborting ACPI-based IRQ routing. Try pci=noacpi or acpi=off\n",
576
                        acpi_device_name(link->device),
577
                        acpi_device_bid(link->device));
578
                return_VALUE(-ENODEV);
579
        } else {
580
                acpi_irq_penalty[link->irq.active] += PIRQ_PENALTY_PCI_USING;
581
                printk(PREFIX "%s [%s] enabled at IRQ %d\n",
582
                        acpi_device_name(link->device),
583
                        acpi_device_bid(link->device), link->irq.active);
584
        }
585
 
586
        link->irq.setonboot = 1;
587
 
588
        return_VALUE(0);
589
}
590
 
591
 
592
int
593
acpi_pci_link_get_irq (
594
        acpi_handle             handle,
595
        int                     index,
596
        int*                    edge_level,
597
        int*                    active_high_low)
598
{
599
        int                     result = 0;
600
        struct acpi_device      *device = NULL;
601
        struct acpi_pci_link    *link = NULL;
602
 
603
        ACPI_FUNCTION_TRACE("acpi_pci_link_get_irq");
604
 
605
        result = acpi_bus_get_device(handle, &device);
606
        if (result) {
607
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link device\n"));
608
                return_VALUE(0);
609
        }
610
 
611
        link = (struct acpi_pci_link *) acpi_driver_data(device);
612
        if (!link) {
613
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n"));
614
                return_VALUE(0);
615
        }
616
 
617
        /* TBD: Support multiple index (IRQ) entries per Link Device */
618
        if (index) {
619
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid index %d\n", index));
620
                return_VALUE(0);
621
        }
622
 
623
        if (acpi_pci_link_allocate(link))
624
                return_VALUE(0);
625
 
626
        if (!link->irq.active) {
627
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link disabled\n"));
628
                return_VALUE(0);
629
        }
630
 
631
        if (edge_level) *edge_level = link->irq.edge_level;
632
        if (active_high_low) *active_high_low = link->irq.active_high_low;
633
        return_VALUE(link->irq.active);
634
}
635
 
636
 
637
/* --------------------------------------------------------------------------
638
                                 Driver Interface
639
   -------------------------------------------------------------------------- */
640
 
641
static int
642
acpi_pci_link_add (
643
        struct acpi_device *device)
644
{
645
        int                     result = 0;
646
        struct acpi_pci_link    *link = NULL;
647
        int                     i = 0;
648
        int                     found = 0;
649
 
650
        ACPI_FUNCTION_TRACE("acpi_pci_link_add");
651
 
652
        if (!device)
653
                return_VALUE(-EINVAL);
654
 
655
        link = kmalloc(sizeof(struct acpi_pci_link), GFP_KERNEL);
656
        if (!link)
657
                return_VALUE(-ENOMEM);
658
        memset(link, 0, sizeof(struct acpi_pci_link));
659
 
660
        link->device = device;
661
        link->handle = device->handle;
662
        sprintf(acpi_device_name(device), "%s", ACPI_PCI_LINK_DEVICE_NAME);
663
        sprintf(acpi_device_class(device), "%s", ACPI_PCI_LINK_CLASS);
664
        acpi_driver_data(device) = link;
665
 
666
        result = acpi_pci_link_get_possible(link);
667
        if (result)
668
                goto end;
669
 
670
        /* query and set link->irq.active */
671
        acpi_pci_link_get_current(link);
672
 
673
//#ifdef CONFIG_ACPI_DEBUG
674
        printk(PREFIX "%s [%s] (IRQs", acpi_device_name(device),
675
                acpi_device_bid(device));
676
        for (i = 0; i < link->irq.possible_count; i++) {
677
                if (link->irq.active == link->irq.possible[i]) {
678
                        printk(" *%d", link->irq.possible[i]);
679
                        found = 1;
680
                }
681
                else
682
                        printk(" %d", link->irq.possible[i]);
683
        }
684
        printk(")\n");
685
//#endif /* CONFIG_ACPI_DEBUG */
686
 
687
        /* TBD: Acquire/release lock */
688
        list_add_tail(&link->node, &acpi_link.entries);
689
        acpi_link.count++;
690
 
691
end:
692
        if (result)
693
                kfree(link);
694
 
695
        return_VALUE(result);
696
}
697
 
698
 
699
static int
700
acpi_pci_link_remove (
701
        struct acpi_device      *device,
702
        int                     type)
703
{
704
        struct acpi_pci_link *link = NULL;
705
 
706
        ACPI_FUNCTION_TRACE("acpi_pci_link_remove");
707
 
708
        if (!device || !acpi_driver_data(device))
709
                return_VALUE(-EINVAL);
710
 
711
        link = (struct acpi_pci_link *) acpi_driver_data(device);
712
 
713
        /* TBD: Acquire/release lock */
714
        list_del(&link->node);
715
 
716
        kfree(link);
717
 
718
        return_VALUE(0);
719
}
720
 
721
/*
722
 * modify acpi_irq_penalty[] from cmdline
723
 */
724
static int __init acpi_irq_penalty_update(char *str, int used)
725
{
726
        int i;
727
 
728
        for (i = 0; i < 16; i++) {
729
                int retval;
730
                int irq;
731
 
732
                retval = get_option(&str,&irq);
733
 
734
                if (!retval)
735
                        break;  /* no number found */
736
 
737
                if (irq < 0)
738
                        continue;
739
 
740
                if (irq >= ACPI_MAX_IRQS)
741
                        continue;
742
 
743
                if (used)
744
                        acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_USED;
745
                else
746
                        acpi_irq_penalty[irq] = PIRQ_PENALTY_PCI_AVAILABLE;
747
 
748
                if (retval != 2)        /* no next number */
749
                        break;
750
        }
751
        return 1;
752
}
753
 
754
/*
755
 * Over-ride default table to reserve additional IRQs for use by ISA
756
 * e.g. acpi_irq_isa=5
757
 * Useful for telling ACPI how not to interfere with your ISA sound card.
758
 */
759
static int __init acpi_irq_isa(char *str)
760
{
761
        return(acpi_irq_penalty_update(str, 1));
762
}
763
__setup("acpi_irq_isa=", acpi_irq_isa);
764
 
765
/*
766
 * Over-ride default table to free additional IRQs for use by PCI
767
 * e.g. acpi_irq_pci=7,15
768
 * Used for acpi_irq_balance to free up IRQs to reduce PCI IRQ sharing.
769
 */
770
static int __init acpi_irq_pci(char *str)
771
{
772
        return(acpi_irq_penalty_update(str, 0));
773
}
774
__setup("acpi_irq_pci=", acpi_irq_pci);
775
 
776
static int __init acpi_irq_nobalance_set(char *str)
777
{
778
        acpi_irq_balance = 0;
779
        return(1);
780
}
781
__setup("acpi_irq_nobalance", acpi_irq_nobalance_set);
782
 
783
int __init acpi_irq_balance_set(char *str)
784
{
785
        acpi_irq_balance = 1;
786
        return(1);
787
}
788
__setup("acpi_irq_balance", acpi_irq_balance_set);
789
 
790
 
791
int __init
792
acpi_pci_link_init (void)
793
{
794
        ACPI_FUNCTION_TRACE("acpi_pci_link_init");
795
 
796
        acpi_link.count = 0;
797
        INIT_LIST_HEAD(&acpi_link.entries);
798
 
799
        if (acpi_bus_register_driver(&acpi_pci_link_driver) < 0)
800
                return_VALUE(-ENODEV);
801
 
802
        return_VALUE(0);
803
}

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.