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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [acpi/] [pci_link.c] - Blame information for rev 67

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

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 *  pci_link.c - ACPI PCI Interrupt Link Device Driver ($Revision: 34 $)
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/sysdev.h>
33
#include <linux/kernel.h>
34
#include <linux/module.h>
35
#include <linux/init.h>
36
#include <linux/types.h>
37
#include <linux/proc_fs.h>
38
#include <linux/spinlock.h>
39
#include <linux/pm.h>
40
#include <linux/pci.h>
41
#include <linux/mutex.h>
42
 
43
#include <acpi/acpi_bus.h>
44
#include <acpi/acpi_drivers.h>
45
 
46
#define _COMPONENT              ACPI_PCI_COMPONENT
47
ACPI_MODULE_NAME("pci_link");
48
#define ACPI_PCI_LINK_CLASS             "pci_irq_routing"
49
#define ACPI_PCI_LINK_DEVICE_NAME       "PCI Interrupt Link"
50
#define ACPI_PCI_LINK_FILE_INFO         "info"
51
#define ACPI_PCI_LINK_FILE_STATUS       "state"
52
#define ACPI_PCI_LINK_MAX_POSSIBLE 16
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_device_id link_device_ids[] = {
57
        {"PNP0C0F", 0},
58
        {"", 0},
59
};
60
MODULE_DEVICE_TABLE(acpi, link_device_ids);
61
 
62
static struct acpi_driver acpi_pci_link_driver = {
63
        .name = "pci_link",
64
        .class = ACPI_PCI_LINK_CLASS,
65
        .ids = link_device_ids,
66
        .ops = {
67
                .add = acpi_pci_link_add,
68
                .remove = acpi_pci_link_remove,
69
                },
70
};
71
 
72
/*
73
 * If a link is initialized, we never change its active and initialized
74
 * later even the link is disable. Instead, we just repick the active irq
75
 */
76
struct acpi_pci_link_irq {
77
        u8 active;              /* Current IRQ */
78
        u8 triggering;          /* All IRQs */
79
        u8 polarity;    /* All IRQs */
80
        u8 resource_type;
81
        u8 possible_count;
82
        u8 possible[ACPI_PCI_LINK_MAX_POSSIBLE];
83
        u8 initialized:1;
84
        u8 reserved:7;
85
};
86
 
87
struct acpi_pci_link {
88
        struct list_head node;
89
        struct acpi_device *device;
90
        struct acpi_pci_link_irq irq;
91
        int refcnt;
92
};
93
 
94
static struct {
95
        int count;
96
        struct list_head entries;
97
} acpi_link;
98
DEFINE_MUTEX(acpi_link_lock);
99
 
100
/* --------------------------------------------------------------------------
101
                            PCI Link Device Management
102
   -------------------------------------------------------------------------- */
103
 
104
/*
105
 * set context (link) possible list from resource list
106
 */
107
static acpi_status
108
acpi_pci_link_check_possible(struct acpi_resource *resource, void *context)
109
{
110
        struct acpi_pci_link *link = context;
111
        u32 i = 0;
112
 
113
 
114
        switch (resource->type) {
115
        case ACPI_RESOURCE_TYPE_START_DEPENDENT:
116
                return AE_OK;
117
        case ACPI_RESOURCE_TYPE_IRQ:
118
                {
119
                        struct acpi_resource_irq *p = &resource->data.irq;
120
                        if (!p || !p->interrupt_count) {
121
                                printk(KERN_WARNING PREFIX "Blank IRQ resource\n");
122
                                return AE_OK;
123
                        }
124
                        for (i = 0;
125
                             (i < p->interrupt_count
126
                              && i < ACPI_PCI_LINK_MAX_POSSIBLE); i++) {
127
                                if (!p->interrupts[i]) {
128
                                        printk(KERN_WARNING PREFIX "Invalid IRQ %d\n",
129
                                                      p->interrupts[i]);
130
                                        continue;
131
                                }
132
                                link->irq.possible[i] = p->interrupts[i];
133
                                link->irq.possible_count++;
134
                        }
135
                        link->irq.triggering = p->triggering;
136
                        link->irq.polarity = p->polarity;
137
                        link->irq.resource_type = ACPI_RESOURCE_TYPE_IRQ;
138
                        break;
139
                }
140
        case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
141
                {
142
                        struct acpi_resource_extended_irq *p =
143
                            &resource->data.extended_irq;
144
                        if (!p || !p->interrupt_count) {
145
                                printk(KERN_WARNING PREFIX
146
                                              "Blank EXT IRQ resource\n");
147
                                return AE_OK;
148
                        }
149
                        for (i = 0;
150
                             (i < p->interrupt_count
151
                              && i < ACPI_PCI_LINK_MAX_POSSIBLE); i++) {
152
                                if (!p->interrupts[i]) {
153
                                        printk(KERN_WARNING PREFIX "Invalid IRQ %d\n",
154
                                                      p->interrupts[i]);
155
                                        continue;
156
                                }
157
                                link->irq.possible[i] = p->interrupts[i];
158
                                link->irq.possible_count++;
159
                        }
160
                        link->irq.triggering = p->triggering;
161
                        link->irq.polarity = p->polarity;
162
                        link->irq.resource_type = ACPI_RESOURCE_TYPE_EXTENDED_IRQ;
163
                        break;
164
                }
165
        default:
166
                printk(KERN_ERR PREFIX "Resource is not an IRQ entry\n");
167
                return AE_OK;
168
        }
169
 
170
        return AE_CTRL_TERMINATE;
171
}
172
 
173
static int acpi_pci_link_get_possible(struct acpi_pci_link *link)
174
{
175
        acpi_status status;
176
 
177
 
178
        if (!link)
179
                return -EINVAL;
180
 
181
        status = acpi_walk_resources(link->device->handle, METHOD_NAME__PRS,
182
                                     acpi_pci_link_check_possible, link);
183
        if (ACPI_FAILURE(status)) {
184
                ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PRS"));
185
                return -ENODEV;
186
        }
187
 
188
        ACPI_DEBUG_PRINT((ACPI_DB_INFO,
189
                          "Found %d possible IRQs\n",
190
                          link->irq.possible_count));
191
 
192
        return 0;
193
}
194
 
195
static acpi_status
196
acpi_pci_link_check_current(struct acpi_resource *resource, void *context)
197
{
198
        int *irq = (int *)context;
199
 
200
 
201
        switch (resource->type) {
202
        case ACPI_RESOURCE_TYPE_IRQ:
203
                {
204
                        struct acpi_resource_irq *p = &resource->data.irq;
205
                        if (!p || !p->interrupt_count) {
206
                                /*
207
                                 * IRQ descriptors may have no IRQ# bits set,
208
                                 * particularly those those w/ _STA disabled
209
                                 */
210
                                ACPI_DEBUG_PRINT((ACPI_DB_INFO,
211
                                                  "Blank IRQ resource\n"));
212
                                return AE_OK;
213
                        }
214
                        *irq = p->interrupts[0];
215
                        break;
216
                }
217
        case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
218
                {
219
                        struct acpi_resource_extended_irq *p =
220
                            &resource->data.extended_irq;
221
                        if (!p || !p->interrupt_count) {
222
                                /*
223
                                 * extended IRQ descriptors must
224
                                 * return at least 1 IRQ
225
                                 */
226
                                printk(KERN_WARNING PREFIX
227
                                              "Blank EXT IRQ resource\n");
228
                                return AE_OK;
229
                        }
230
                        *irq = p->interrupts[0];
231
                        break;
232
                }
233
                break;
234
        default:
235
                printk(KERN_ERR PREFIX "Resource %d isn't an IRQ\n", resource->type);
236
        case ACPI_RESOURCE_TYPE_END_TAG:
237
                return AE_OK;
238
        }
239
        return AE_CTRL_TERMINATE;
240
}
241
 
242
/*
243
 * Run _CRS and set link->irq.active
244
 *
245
 * return value:
246
 * 0 - success
247
 * !0 - failure
248
 */
249
static int acpi_pci_link_get_current(struct acpi_pci_link *link)
250
{
251
        int result = 0;
252
        acpi_status status = AE_OK;
253
        int irq = 0;
254
 
255
        if (!link)
256
                return -EINVAL;
257
 
258
        link->irq.active = 0;
259
 
260
        /* in practice, status disabled is meaningless, ignore it */
261
        if (acpi_strict) {
262
                /* Query _STA, set link->device->status */
263
                result = acpi_bus_get_status(link->device);
264
                if (result) {
265
                        printk(KERN_ERR PREFIX "Unable to read status\n");
266
                        goto end;
267
                }
268
 
269
                if (!link->device->status.enabled) {
270
                        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Link disabled\n"));
271
                        return 0;
272
                }
273
        }
274
 
275
        /*
276
         * Query and parse _CRS to get the current IRQ assignment.
277
         */
278
 
279
        status = acpi_walk_resources(link->device->handle, METHOD_NAME__CRS,
280
                                     acpi_pci_link_check_current, &irq);
281
        if (ACPI_FAILURE(status)) {
282
                ACPI_EXCEPTION((AE_INFO, status, "Evaluating _CRS"));
283
                result = -ENODEV;
284
                goto end;
285
        }
286
 
287
        if (acpi_strict && !irq) {
288
                printk(KERN_ERR PREFIX "_CRS returned 0\n");
289
                result = -ENODEV;
290
        }
291
 
292
        link->irq.active = irq;
293
 
294
        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Link at IRQ %d \n", link->irq.active));
295
 
296
      end:
297
        return result;
298
}
299
 
300
static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
301
{
302
        int result = 0;
303
        acpi_status status = AE_OK;
304
        struct {
305
                struct acpi_resource res;
306
                struct acpi_resource end;
307
        } *resource;
308
        struct acpi_buffer buffer = { 0, NULL };
309
 
310
 
311
        if (!link || !irq)
312
                return -EINVAL;
313
 
314
        resource = kzalloc(sizeof(*resource) + 1, irqs_disabled() ? GFP_ATOMIC: GFP_KERNEL);
315
        if (!resource)
316
                return -ENOMEM;
317
 
318
        buffer.length = sizeof(*resource) + 1;
319
        buffer.pointer = resource;
320
 
321
        switch (link->irq.resource_type) {
322
        case ACPI_RESOURCE_TYPE_IRQ:
323
                resource->res.type = ACPI_RESOURCE_TYPE_IRQ;
324
                resource->res.length = sizeof(struct acpi_resource);
325
                resource->res.data.irq.triggering = link->irq.triggering;
326
                resource->res.data.irq.polarity =
327
                    link->irq.polarity;
328
                if (link->irq.triggering == ACPI_EDGE_SENSITIVE)
329
                        resource->res.data.irq.sharable =
330
                            ACPI_EXCLUSIVE;
331
                else
332
                        resource->res.data.irq.sharable = ACPI_SHARED;
333
                resource->res.data.irq.interrupt_count = 1;
334
                resource->res.data.irq.interrupts[0] = irq;
335
                break;
336
 
337
        case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
338
                resource->res.type = ACPI_RESOURCE_TYPE_EXTENDED_IRQ;
339
                resource->res.length = sizeof(struct acpi_resource);
340
                resource->res.data.extended_irq.producer_consumer =
341
                    ACPI_CONSUMER;
342
                resource->res.data.extended_irq.triggering =
343
                    link->irq.triggering;
344
                resource->res.data.extended_irq.polarity =
345
                    link->irq.polarity;
346
                if (link->irq.triggering == ACPI_EDGE_SENSITIVE)
347
                        resource->res.data.irq.sharable =
348
                            ACPI_EXCLUSIVE;
349
                else
350
                        resource->res.data.irq.sharable = ACPI_SHARED;
351
                resource->res.data.extended_irq.interrupt_count = 1;
352
                resource->res.data.extended_irq.interrupts[0] = irq;
353
                /* ignore resource_source, it's optional */
354
                break;
355
        default:
356
                printk(KERN_ERR PREFIX "Invalid Resource_type %d\n", link->irq.resource_type);
357
                result = -EINVAL;
358
                goto end;
359
 
360
        }
361
        resource->end.type = ACPI_RESOURCE_TYPE_END_TAG;
362
 
363
        /* Attempt to set the resource */
364
        status = acpi_set_current_resources(link->device->handle, &buffer);
365
 
366
        /* check for total failure */
367
        if (ACPI_FAILURE(status)) {
368
                ACPI_EXCEPTION((AE_INFO, status, "Evaluating _SRS"));
369
                result = -ENODEV;
370
                goto end;
371
        }
372
 
373
        /* Query _STA, set device->status */
374
        result = acpi_bus_get_status(link->device);
375
        if (result) {
376
                printk(KERN_ERR PREFIX "Unable to read status\n");
377
                goto end;
378
        }
379
        if (!link->device->status.enabled) {
380
                printk(KERN_WARNING PREFIX
381
                              "%s [%s] disabled and referenced, BIOS bug\n",
382
                              acpi_device_name(link->device),
383
                              acpi_device_bid(link->device));
384
        }
385
 
386
        /* Query _CRS, set link->irq.active */
387
        result = acpi_pci_link_get_current(link);
388
        if (result) {
389
                goto end;
390
        }
391
 
392
        /*
393
         * Is current setting not what we set?
394
         * set link->irq.active
395
         */
396
        if (link->irq.active != irq) {
397
                /*
398
                 * policy: when _CRS doesn't return what we just _SRS
399
                 * assume _SRS worked and override _CRS value.
400
                 */
401
                printk(KERN_WARNING PREFIX
402
                              "%s [%s] BIOS reported IRQ %d, using IRQ %d\n",
403
                              acpi_device_name(link->device),
404
                              acpi_device_bid(link->device), link->irq.active, irq);
405
                link->irq.active = irq;
406
        }
407
 
408
        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Set IRQ %d\n", link->irq.active));
409
 
410
      end:
411
        kfree(resource);
412
        return result;
413
}
414
 
415
/* --------------------------------------------------------------------------
416
                            PCI Link IRQ Management
417
   -------------------------------------------------------------------------- */
418
 
419
/*
420
 * "acpi_irq_balance" (default in APIC mode) enables ACPI to use PIC Interrupt
421
 * Link Devices to move the PIRQs around to minimize sharing.
422
 *
423
 * "acpi_irq_nobalance" (default in PIC mode) tells ACPI not to move any PIC IRQs
424
 * that the BIOS has already set to active.  This is necessary because
425
 * ACPI has no automatic means of knowing what ISA IRQs are used.  Note that
426
 * if the BIOS doesn't set a Link Device active, ACPI needs to program it
427
 * even if acpi_irq_nobalance is set.
428
 *
429
 * A tables of penalties avoids directing PCI interrupts to well known
430
 * ISA IRQs. Boot params are available to over-ride the default table:
431
 *
432
 * List interrupts that are free for PCI use.
433
 * acpi_irq_pci=n[,m]
434
 *
435
 * List interrupts that should not be used for PCI:
436
 * acpi_irq_isa=n[,m]
437
 *
438
 * Note that PCI IRQ routers have a list of possible IRQs,
439
 * which may not include the IRQs this table says are available.
440
 *
441
 * Since this heuristic can't tell the difference between a link
442
 * that no device will attach to, vs. a link which may be shared
443
 * by multiple active devices -- it is not optimal.
444
 *
445
 * If interrupt performance is that important, get an IO-APIC system
446
 * with a pin dedicated to each device.  Or for that matter, an MSI
447
 * enabled system.
448
 */
449
 
450
#define ACPI_MAX_IRQS           256
451
#define ACPI_MAX_ISA_IRQ        16
452
 
453
#define PIRQ_PENALTY_PCI_AVAILABLE      (0)
454
#define PIRQ_PENALTY_PCI_POSSIBLE       (16*16)
455
#define PIRQ_PENALTY_PCI_USING          (16*16*16)
456
#define PIRQ_PENALTY_ISA_TYPICAL        (16*16*16*16)
457
#define PIRQ_PENALTY_ISA_USED           (16*16*16*16*16)
458
#define PIRQ_PENALTY_ISA_ALWAYS         (16*16*16*16*16*16)
459
 
460
static int acpi_irq_penalty[ACPI_MAX_IRQS] = {
461
        PIRQ_PENALTY_ISA_ALWAYS,        /* IRQ0 timer */
462
        PIRQ_PENALTY_ISA_ALWAYS,        /* IRQ1 keyboard */
463
        PIRQ_PENALTY_ISA_ALWAYS,        /* IRQ2 cascade */
464
        PIRQ_PENALTY_ISA_TYPICAL,       /* IRQ3 serial */
465
        PIRQ_PENALTY_ISA_TYPICAL,       /* IRQ4 serial */
466
        PIRQ_PENALTY_ISA_TYPICAL,       /* IRQ5 sometimes SoundBlaster */
467
        PIRQ_PENALTY_ISA_TYPICAL,       /* IRQ6 */
468
        PIRQ_PENALTY_ISA_TYPICAL,       /* IRQ7 parallel, spurious */
469
        PIRQ_PENALTY_ISA_TYPICAL,       /* IRQ8 rtc, sometimes */
470
        PIRQ_PENALTY_PCI_AVAILABLE,     /* IRQ9  PCI, often acpi */
471
        PIRQ_PENALTY_PCI_AVAILABLE,     /* IRQ10 PCI */
472
        PIRQ_PENALTY_PCI_AVAILABLE,     /* IRQ11 PCI */
473
        PIRQ_PENALTY_ISA_USED,  /* IRQ12 mouse */
474
        PIRQ_PENALTY_ISA_USED,  /* IRQ13 fpe, sometimes */
475
        PIRQ_PENALTY_ISA_USED,  /* IRQ14 ide0 */
476
        PIRQ_PENALTY_ISA_USED,  /* IRQ15 ide1 */
477
        /* >IRQ15 */
478
};
479
 
480
int __init acpi_irq_penalty_init(void)
481
{
482
        struct list_head *node = NULL;
483
        struct acpi_pci_link *link = NULL;
484
        int i = 0;
485
 
486
 
487
        /*
488
         * Update penalties to facilitate IRQ balancing.
489
         */
490
        list_for_each(node, &acpi_link.entries) {
491
 
492
                link = list_entry(node, struct acpi_pci_link, node);
493
                if (!link) {
494
                        printk(KERN_ERR PREFIX "Invalid link context\n");
495
                        continue;
496
                }
497
 
498
                /*
499
                 * reflect the possible and active irqs in the penalty table --
500
                 * useful for breaking ties.
501
                 */
502
                if (link->irq.possible_count) {
503
                        int penalty =
504
                            PIRQ_PENALTY_PCI_POSSIBLE /
505
                            link->irq.possible_count;
506
 
507
                        for (i = 0; i < link->irq.possible_count; i++) {
508
                                if (link->irq.possible[i] < ACPI_MAX_ISA_IRQ)
509
                                        acpi_irq_penalty[link->irq.
510
                                                         possible[i]] +=
511
                                            penalty;
512
                        }
513
 
514
                } else if (link->irq.active) {
515
                        acpi_irq_penalty[link->irq.active] +=
516
                            PIRQ_PENALTY_PCI_POSSIBLE;
517
                }
518
        }
519
        /* Add a penalty for the SCI */
520
        acpi_irq_penalty[acpi_gbl_FADT.sci_interrupt] += PIRQ_PENALTY_PCI_USING;
521
 
522
        return 0;
523
}
524
 
525
static int acpi_irq_balance;    /* 0: static, 1: balance */
526
 
527
static int acpi_pci_link_allocate(struct acpi_pci_link *link)
528
{
529
        int irq;
530
        int i;
531
 
532
 
533
        if (link->irq.initialized) {
534
                if (link->refcnt == 0)
535
                        /* This means the link is disabled but initialized */
536
                        acpi_pci_link_set(link, link->irq.active);
537
                return 0;
538
        }
539
 
540
        /*
541
         * search for active IRQ in list of possible IRQs.
542
         */
543
        for (i = 0; i < link->irq.possible_count; ++i) {
544
                if (link->irq.active == link->irq.possible[i])
545
                        break;
546
        }
547
        /*
548
         * forget active IRQ that is not in possible list
549
         */
550
        if (i == link->irq.possible_count) {
551
                if (acpi_strict)
552
                        printk(KERN_WARNING PREFIX "_CRS %d not found"
553
                                      " in _PRS\n", link->irq.active);
554
                link->irq.active = 0;
555
        }
556
 
557
        /*
558
         * if active found, use it; else pick entry from end of possible list.
559
         */
560
        if (link->irq.active) {
561
                irq = link->irq.active;
562
        } else {
563
                irq = link->irq.possible[link->irq.possible_count - 1];
564
        }
565
 
566
        if (acpi_irq_balance || !link->irq.active) {
567
                /*
568
                 * Select the best IRQ.  This is done in reverse to promote
569
                 * the use of IRQs 9, 10, 11, and >15.
570
                 */
571
                for (i = (link->irq.possible_count - 1); i >= 0; i--) {
572
                        if (acpi_irq_penalty[irq] >
573
                            acpi_irq_penalty[link->irq.possible[i]])
574
                                irq = link->irq.possible[i];
575
                }
576
        }
577
 
578
        /* Attempt to enable the link device at this IRQ. */
579
        if (acpi_pci_link_set(link, irq)) {
580
                printk(KERN_ERR PREFIX "Unable to set IRQ for %s [%s]. "
581
                            "Try pci=noacpi or acpi=off\n",
582
                            acpi_device_name(link->device),
583
                            acpi_device_bid(link->device));
584
                return -ENODEV;
585
        } else {
586
                acpi_irq_penalty[link->irq.active] += PIRQ_PENALTY_PCI_USING;
587
                printk(PREFIX "%s [%s] enabled at IRQ %d\n",
588
                       acpi_device_name(link->device),
589
                       acpi_device_bid(link->device), link->irq.active);
590
        }
591
 
592
        link->irq.initialized = 1;
593
 
594
        return 0;
595
}
596
 
597
/*
598
 * acpi_pci_link_allocate_irq
599
 * success: return IRQ >= 0
600
 * failure: return -1
601
 */
602
 
603
int
604
acpi_pci_link_allocate_irq(acpi_handle handle,
605
                           int index,
606
                           int *triggering, int *polarity, char **name)
607
{
608
        int result = 0;
609
        struct acpi_device *device = NULL;
610
        struct acpi_pci_link *link = NULL;
611
 
612
 
613
        result = acpi_bus_get_device(handle, &device);
614
        if (result) {
615
                printk(KERN_ERR PREFIX "Invalid link device\n");
616
                return -1;
617
        }
618
 
619
        link = acpi_driver_data(device);
620
        if (!link) {
621
                printk(KERN_ERR PREFIX "Invalid link context\n");
622
                return -1;
623
        }
624
 
625
        /* TBD: Support multiple index (IRQ) entries per Link Device */
626
        if (index) {
627
                printk(KERN_ERR PREFIX "Invalid index %d\n", index);
628
                return -1;
629
        }
630
 
631
        mutex_lock(&acpi_link_lock);
632
        if (acpi_pci_link_allocate(link)) {
633
                mutex_unlock(&acpi_link_lock);
634
                return -1;
635
        }
636
 
637
        if (!link->irq.active) {
638
                mutex_unlock(&acpi_link_lock);
639
                printk(KERN_ERR PREFIX "Link active IRQ is 0!\n");
640
                return -1;
641
        }
642
        link->refcnt++;
643
        mutex_unlock(&acpi_link_lock);
644
 
645
        if (triggering)
646
                *triggering = link->irq.triggering;
647
        if (polarity)
648
                *polarity = link->irq.polarity;
649
        if (name)
650
                *name = acpi_device_bid(link->device);
651
        ACPI_DEBUG_PRINT((ACPI_DB_INFO,
652
                          "Link %s is referenced\n",
653
                          acpi_device_bid(link->device)));
654
        return (link->irq.active);
655
}
656
 
657
/*
658
 * We don't change link's irq information here.  After it is reenabled, we
659
 * continue use the info
660
 */
661
int acpi_pci_link_free_irq(acpi_handle handle)
662
{
663
        struct acpi_device *device = NULL;
664
        struct acpi_pci_link *link = NULL;
665
        acpi_status result;
666
 
667
 
668
        result = acpi_bus_get_device(handle, &device);
669
        if (result) {
670
                printk(KERN_ERR PREFIX "Invalid link device\n");
671
                return -1;
672
        }
673
 
674
        link = acpi_driver_data(device);
675
        if (!link) {
676
                printk(KERN_ERR PREFIX "Invalid link context\n");
677
                return -1;
678
        }
679
 
680
        mutex_lock(&acpi_link_lock);
681
        if (!link->irq.initialized) {
682
                mutex_unlock(&acpi_link_lock);
683
                printk(KERN_ERR PREFIX "Link isn't initialized\n");
684
                return -1;
685
        }
686
#ifdef  FUTURE_USE
687
        /*
688
         * The Link reference count allows us to _DISable an unused link
689
         * and suspend time, and set it again  on resume.
690
         * However, 2.6.12 still has irq_router.resume
691
         * which blindly restores the link state.
692
         * So we disable the reference count method
693
         * to prevent duplicate acpi_pci_link_set()
694
         * which would harm some systems
695
         */
696
        link->refcnt--;
697
#endif
698
        ACPI_DEBUG_PRINT((ACPI_DB_INFO,
699
                          "Link %s is dereferenced\n",
700
                          acpi_device_bid(link->device)));
701
 
702
        if (link->refcnt == 0) {
703
                acpi_ut_evaluate_object(link->device->handle, "_DIS", 0, NULL);
704
        }
705
        mutex_unlock(&acpi_link_lock);
706
        return (link->irq.active);
707
}
708
 
709
/* --------------------------------------------------------------------------
710
                                 Driver Interface
711
   -------------------------------------------------------------------------- */
712
 
713
static int acpi_pci_link_add(struct acpi_device *device)
714
{
715
        int result = 0;
716
        struct acpi_pci_link *link = NULL;
717
        int i = 0;
718
        int found = 0;
719
 
720
 
721
        if (!device)
722
                return -EINVAL;
723
 
724
        link = kzalloc(sizeof(struct acpi_pci_link), GFP_KERNEL);
725
        if (!link)
726
                return -ENOMEM;
727
 
728
        link->device = device;
729
        strcpy(acpi_device_name(device), ACPI_PCI_LINK_DEVICE_NAME);
730
        strcpy(acpi_device_class(device), ACPI_PCI_LINK_CLASS);
731
        acpi_driver_data(device) = link;
732
 
733
        mutex_lock(&acpi_link_lock);
734
        result = acpi_pci_link_get_possible(link);
735
        if (result)
736
                goto end;
737
 
738
        /* query and set link->irq.active */
739
        acpi_pci_link_get_current(link);
740
 
741
        printk(KERN_INFO PREFIX "%s [%s] (IRQs", acpi_device_name(device),
742
               acpi_device_bid(device));
743
        for (i = 0; i < link->irq.possible_count; i++) {
744
                if (link->irq.active == link->irq.possible[i]) {
745
                        printk(" *%d", link->irq.possible[i]);
746
                        found = 1;
747
                } else
748
                        printk(" %d", link->irq.possible[i]);
749
        }
750
 
751
        printk(")");
752
 
753
        if (!found)
754
                printk(" *%d", link->irq.active);
755
 
756
        if (!link->device->status.enabled)
757
                printk(", disabled.");
758
 
759
        printk("\n");
760
 
761
        /* TBD: Acquire/release lock */
762
        list_add_tail(&link->node, &acpi_link.entries);
763
        acpi_link.count++;
764
 
765
      end:
766
        /* disable all links -- to be activated on use */
767
        acpi_ut_evaluate_object(device->handle, "_DIS", 0, NULL);
768
        mutex_unlock(&acpi_link_lock);
769
 
770
        if (result)
771
                kfree(link);
772
 
773
        return result;
774
}
775
 
776
static int acpi_pci_link_resume(struct acpi_pci_link *link)
777
{
778
 
779
        if (link->refcnt && link->irq.active && link->irq.initialized)
780
                return (acpi_pci_link_set(link, link->irq.active));
781
        else
782
                return 0;
783
}
784
 
785
static int irqrouter_resume(struct sys_device *dev)
786
{
787
        struct list_head *node = NULL;
788
        struct acpi_pci_link *link = NULL;
789
 
790
 
791
        /* Make sure SCI is enabled again (Apple firmware bug?) */
792
        acpi_set_register(ACPI_BITREG_SCI_ENABLE, 1);
793
 
794
        list_for_each(node, &acpi_link.entries) {
795
                link = list_entry(node, struct acpi_pci_link, node);
796
                if (!link) {
797
                        printk(KERN_ERR PREFIX "Invalid link context\n");
798
                        continue;
799
                }
800
                acpi_pci_link_resume(link);
801
        }
802
        return 0;
803
}
804
 
805
static int acpi_pci_link_remove(struct acpi_device *device, int type)
806
{
807
        struct acpi_pci_link *link = NULL;
808
 
809
 
810
        if (!device || !acpi_driver_data(device))
811
                return -EINVAL;
812
 
813
        link = acpi_driver_data(device);
814
 
815
        mutex_lock(&acpi_link_lock);
816
        list_del(&link->node);
817
        mutex_unlock(&acpi_link_lock);
818
 
819
        kfree(link);
820
 
821
        return 0;
822
}
823
 
824
/*
825
 * modify acpi_irq_penalty[] from cmdline
826
 */
827
static int __init acpi_irq_penalty_update(char *str, int used)
828
{
829
        int i;
830
 
831
        for (i = 0; i < 16; i++) {
832
                int retval;
833
                int irq;
834
 
835
                retval = get_option(&str, &irq);
836
 
837
                if (!retval)
838
                        break;  /* no number found */
839
 
840
                if (irq < 0)
841
                        continue;
842
 
843
                if (irq >= ACPI_MAX_IRQS)
844
                        continue;
845
 
846
                if (used)
847
                        acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_USED;
848
                else
849
                        acpi_irq_penalty[irq] = PIRQ_PENALTY_PCI_AVAILABLE;
850
 
851
                if (retval != 2)        /* no next number */
852
                        break;
853
        }
854
        return 1;
855
}
856
 
857
/*
858
 * We'd like PNP to call this routine for the
859
 * single ISA_USED value for each legacy device.
860
 * But instead it calls us with each POSSIBLE setting.
861
 * There is no ISA_POSSIBLE weight, so we simply use
862
 * the (small) PCI_USING penalty.
863
 */
864
void acpi_penalize_isa_irq(int irq, int active)
865
{
866
        if (active)
867
                acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_USED;
868
        else
869
                acpi_irq_penalty[irq] += PIRQ_PENALTY_PCI_USING;
870
}
871
 
872
/*
873
 * Over-ride default table to reserve additional IRQs for use by ISA
874
 * e.g. acpi_irq_isa=5
875
 * Useful for telling ACPI how not to interfere with your ISA sound card.
876
 */
877
static int __init acpi_irq_isa(char *str)
878
{
879
        return acpi_irq_penalty_update(str, 1);
880
}
881
 
882
__setup("acpi_irq_isa=", acpi_irq_isa);
883
 
884
/*
885
 * Over-ride default table to free additional IRQs for use by PCI
886
 * e.g. acpi_irq_pci=7,15
887
 * Used for acpi_irq_balance to free up IRQs to reduce PCI IRQ sharing.
888
 */
889
static int __init acpi_irq_pci(char *str)
890
{
891
        return acpi_irq_penalty_update(str, 0);
892
}
893
 
894
__setup("acpi_irq_pci=", acpi_irq_pci);
895
 
896
static int __init acpi_irq_nobalance_set(char *str)
897
{
898
        acpi_irq_balance = 0;
899
        return 1;
900
}
901
 
902
__setup("acpi_irq_nobalance", acpi_irq_nobalance_set);
903
 
904
int __init acpi_irq_balance_set(char *str)
905
{
906
        acpi_irq_balance = 1;
907
        return 1;
908
}
909
 
910
__setup("acpi_irq_balance", acpi_irq_balance_set);
911
 
912
/* FIXME: we will remove this interface after all drivers call pci_disable_device */
913
static struct sysdev_class irqrouter_sysdev_class = {
914
        set_kset_name("irqrouter"),
915
        .resume = irqrouter_resume,
916
};
917
 
918
static struct sys_device device_irqrouter = {
919
        .id = 0,
920
        .cls = &irqrouter_sysdev_class,
921
};
922
 
923
static int __init irqrouter_init_sysfs(void)
924
{
925
        int error;
926
 
927
 
928
        if (acpi_disabled || acpi_noirq)
929
                return 0;
930
 
931
        error = sysdev_class_register(&irqrouter_sysdev_class);
932
        if (!error)
933
                error = sysdev_register(&device_irqrouter);
934
 
935
        return error;
936
}
937
 
938
device_initcall(irqrouter_init_sysfs);
939
 
940
static int __init acpi_pci_link_init(void)
941
{
942
 
943
        if (acpi_noirq)
944
                return 0;
945
 
946
        acpi_link.count = 0;
947
        INIT_LIST_HEAD(&acpi_link.entries);
948
 
949
        if (acpi_bus_register_driver(&acpi_pci_link_driver) < 0)
950
                return -ENODEV;
951
 
952
        return 0;
953
}
954
 
955
subsys_initcall(acpi_pci_link_init);

powered by: WebSVN 2.1.0

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