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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [pci/] [hotplug/] [acpi_pcihp.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * Common ACPI functions for hot plug platforms
3
 *
4
 * Copyright (C) 2006 Intel Corporation
5
 *
6
 * All rights reserved.
7
 *
8
 * This program is free software; you can redistribute it and/or modify
9
 * it under the terms of the GNU General Public License as published by
10
 * the Free Software Foundation; either version 2 of the License, or (at
11
 * your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful, but
14
 * WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
16
 * NON INFRINGEMENT.  See the GNU General Public License for more
17
 * details.
18
 *
19
 * You should have received a copy of the GNU General Public License
20
 * along with this program; if not, write to the Free Software
21
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22
 *
23
 * Send feedback to <kristen.c.accardi@intel.com>
24
 *
25
 */
26
 
27
#include <linux/module.h>
28
#include <linux/moduleparam.h>
29
#include <linux/kernel.h>
30
#include <linux/types.h>
31
#include <linux/pci.h>
32
#include <linux/pci_hotplug.h>
33
#include <acpi/acpi.h>
34
#include <acpi/acpi_bus.h>
35
#include <acpi/actypes.h>
36
 
37
#define MY_NAME "acpi_pcihp"
38
 
39
#define dbg(fmt, arg...) do { if (debug_acpi) printk(KERN_DEBUG "%s: %s: " fmt , MY_NAME , __FUNCTION__ , ## arg); } while (0)
40
#define err(format, arg...) printk(KERN_ERR "%s: " format , MY_NAME , ## arg)
41
#define info(format, arg...) printk(KERN_INFO "%s: " format , MY_NAME , ## arg)
42
#define warn(format, arg...) printk(KERN_WARNING "%s: " format , MY_NAME , ## arg)
43
 
44
#define METHOD_NAME__SUN        "_SUN"
45
#define METHOD_NAME__HPP        "_HPP"
46
#define METHOD_NAME_OSHP        "OSHP"
47
 
48
static int debug_acpi;
49
 
50
static acpi_status
51
decode_type0_hpx_record(union acpi_object *record, struct hotplug_params *hpx)
52
{
53
        int i;
54
        union acpi_object *fields = record->package.elements;
55
        u32 revision = fields[1].integer.value;
56
 
57
        switch (revision) {
58
        case 1:
59
                if (record->package.count != 6)
60
                        return AE_ERROR;
61
                for (i = 2; i < 6; i++)
62
                        if (fields[i].type != ACPI_TYPE_INTEGER)
63
                                return AE_ERROR;
64
                hpx->t0 = &hpx->type0_data;
65
                hpx->t0->revision        = revision;
66
                hpx->t0->cache_line_size = fields[2].integer.value;
67
                hpx->t0->latency_timer   = fields[3].integer.value;
68
                hpx->t0->enable_serr     = fields[4].integer.value;
69
                hpx->t0->enable_perr     = fields[5].integer.value;
70
                break;
71
        default:
72
                printk(KERN_WARNING
73
                       "%s: Type 0 Revision %d record not supported\n",
74
                       __FUNCTION__, revision);
75
                return AE_ERROR;
76
        }
77
        return AE_OK;
78
}
79
 
80
static acpi_status
81
decode_type1_hpx_record(union acpi_object *record, struct hotplug_params *hpx)
82
{
83
        int i;
84
        union acpi_object *fields = record->package.elements;
85
        u32 revision = fields[1].integer.value;
86
 
87
        switch (revision) {
88
        case 1:
89
                if (record->package.count != 5)
90
                        return AE_ERROR;
91
                for (i = 2; i < 5; i++)
92
                        if (fields[i].type != ACPI_TYPE_INTEGER)
93
                                return AE_ERROR;
94
                hpx->t1 = &hpx->type1_data;
95
                hpx->t1->revision      = revision;
96
                hpx->t1->max_mem_read  = fields[2].integer.value;
97
                hpx->t1->avg_max_split = fields[3].integer.value;
98
                hpx->t1->tot_max_split = fields[4].integer.value;
99
                break;
100
        default:
101
                printk(KERN_WARNING
102
                       "%s: Type 1 Revision %d record not supported\n",
103
                       __FUNCTION__, revision);
104
                return AE_ERROR;
105
        }
106
        return AE_OK;
107
}
108
 
109
static acpi_status
110
decode_type2_hpx_record(union acpi_object *record, struct hotplug_params *hpx)
111
{
112
        int i;
113
        union acpi_object *fields = record->package.elements;
114
        u32 revision = fields[1].integer.value;
115
 
116
        switch (revision) {
117
        case 1:
118
                if (record->package.count != 18)
119
                        return AE_ERROR;
120
                for (i = 2; i < 18; i++)
121
                        if (fields[i].type != ACPI_TYPE_INTEGER)
122
                                return AE_ERROR;
123
                hpx->t2 = &hpx->type2_data;
124
                hpx->t2->revision      = revision;
125
                hpx->t2->unc_err_mask_and      = fields[2].integer.value;
126
                hpx->t2->unc_err_mask_or       = fields[3].integer.value;
127
                hpx->t2->unc_err_sever_and     = fields[4].integer.value;
128
                hpx->t2->unc_err_sever_or      = fields[5].integer.value;
129
                hpx->t2->cor_err_mask_and      = fields[6].integer.value;
130
                hpx->t2->cor_err_mask_or       = fields[7].integer.value;
131
                hpx->t2->adv_err_cap_and       = fields[8].integer.value;
132
                hpx->t2->adv_err_cap_or        = fields[9].integer.value;
133
                hpx->t2->pci_exp_devctl_and    = fields[10].integer.value;
134
                hpx->t2->pci_exp_devctl_or     = fields[11].integer.value;
135
                hpx->t2->pci_exp_lnkctl_and    = fields[12].integer.value;
136
                hpx->t2->pci_exp_lnkctl_or     = fields[13].integer.value;
137
                hpx->t2->sec_unc_err_sever_and = fields[14].integer.value;
138
                hpx->t2->sec_unc_err_sever_or  = fields[15].integer.value;
139
                hpx->t2->sec_unc_err_mask_and  = fields[16].integer.value;
140
                hpx->t2->sec_unc_err_mask_or   = fields[17].integer.value;
141
                break;
142
        default:
143
                printk(KERN_WARNING
144
                       "%s: Type 2 Revision %d record not supported\n",
145
                       __FUNCTION__, revision);
146
                return AE_ERROR;
147
        }
148
        return AE_OK;
149
}
150
 
151
static acpi_status
152
acpi_run_hpx(acpi_handle handle, struct hotplug_params *hpx)
153
{
154
        acpi_status status;
155
        struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
156
        union acpi_object *package, *record, *fields;
157
        u32 type;
158
        int i;
159
 
160
        /* Clear the return buffer with zeros */
161
        memset(hpx, 0, sizeof(struct hotplug_params));
162
 
163
        status = acpi_evaluate_object(handle, "_HPX", NULL, &buffer);
164
        if (ACPI_FAILURE(status))
165
                return status;
166
 
167
        package = (union acpi_object *)buffer.pointer;
168
        if (package->type != ACPI_TYPE_PACKAGE) {
169
                status = AE_ERROR;
170
                goto exit;
171
        }
172
 
173
        for (i = 0; i < package->package.count; i++) {
174
                record = &package->package.elements[i];
175
                if (record->type != ACPI_TYPE_PACKAGE) {
176
                        status = AE_ERROR;
177
                        goto exit;
178
                }
179
 
180
                fields = record->package.elements;
181
                if (fields[0].type != ACPI_TYPE_INTEGER ||
182
                    fields[1].type != ACPI_TYPE_INTEGER) {
183
                        status = AE_ERROR;
184
                        goto exit;
185
                }
186
 
187
                type = fields[0].integer.value;
188
                switch (type) {
189
                case 0:
190
                        status = decode_type0_hpx_record(record, hpx);
191
                        if (ACPI_FAILURE(status))
192
                                goto exit;
193
                        break;
194
                case 1:
195
                        status = decode_type1_hpx_record(record, hpx);
196
                        if (ACPI_FAILURE(status))
197
                                goto exit;
198
                        break;
199
                case 2:
200
                        status = decode_type2_hpx_record(record, hpx);
201
                        if (ACPI_FAILURE(status))
202
                                goto exit;
203
                        break;
204
                default:
205
                        printk(KERN_ERR "%s: Type %d record not supported\n",
206
                               __FUNCTION__, type);
207
                        status = AE_ERROR;
208
                        goto exit;
209
                }
210
        }
211
 exit:
212
        kfree(buffer.pointer);
213
        return status;
214
}
215
 
216
static acpi_status
217
acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
218
{
219
        acpi_status             status;
220
        u8                      nui[4];
221
        struct acpi_buffer      ret_buf = { 0, NULL};
222
        struct acpi_buffer      string = { ACPI_ALLOCATE_BUFFER, NULL };
223
        union acpi_object       *ext_obj, *package;
224
        int                     i, len = 0;
225
 
226
        acpi_get_name(handle, ACPI_FULL_PATHNAME, &string);
227
 
228
        /* Clear the return buffer with zeros */
229
        memset(hpp, 0, sizeof(struct hotplug_params));
230
 
231
        /* get _hpp */
232
        status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf);
233
        switch (status) {
234
        case AE_BUFFER_OVERFLOW:
235
                ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL);
236
                if (!ret_buf.pointer) {
237
                        printk(KERN_ERR "%s:%s alloc for _HPP fail\n",
238
                                __FUNCTION__, (char *)string.pointer);
239
                        kfree(string.pointer);
240
                        return AE_NO_MEMORY;
241
                }
242
                status = acpi_evaluate_object(handle, METHOD_NAME__HPP,
243
                                NULL, &ret_buf);
244
                if (ACPI_SUCCESS(status))
245
                        break;
246
        default:
247
                if (ACPI_FAILURE(status)) {
248
                        pr_debug("%s:%s _HPP fail=0x%x\n", __FUNCTION__,
249
                                (char *)string.pointer, status);
250
                        kfree(string.pointer);
251
                        return status;
252
                }
253
        }
254
 
255
        ext_obj = (union acpi_object *) ret_buf.pointer;
256
        if (ext_obj->type != ACPI_TYPE_PACKAGE) {
257
                printk(KERN_ERR "%s:%s _HPP obj not a package\n", __FUNCTION__,
258
                                (char *)string.pointer);
259
                status = AE_ERROR;
260
                goto free_and_return;
261
        }
262
 
263
        len = ext_obj->package.count;
264
        package = (union acpi_object *) ret_buf.pointer;
265
        for ( i = 0; (i < len) || (i < 4); i++) {
266
                ext_obj = (union acpi_object *) &package->package.elements[i];
267
                switch (ext_obj->type) {
268
                case ACPI_TYPE_INTEGER:
269
                        nui[i] = (u8)ext_obj->integer.value;
270
                        break;
271
                default:
272
                        printk(KERN_ERR "%s:%s _HPP obj type incorrect\n",
273
                                __FUNCTION__, (char *)string.pointer);
274
                        status = AE_ERROR;
275
                        goto free_and_return;
276
                }
277
        }
278
 
279
        hpp->t0 = &hpp->type0_data;
280
        hpp->t0->cache_line_size = nui[0];
281
        hpp->t0->latency_timer = nui[1];
282
        hpp->t0->enable_serr = nui[2];
283
        hpp->t0->enable_perr = nui[3];
284
 
285
        pr_debug("  _HPP: cache_line_size=0x%x\n", hpp->t0->cache_line_size);
286
        pr_debug("  _HPP: latency timer  =0x%x\n", hpp->t0->latency_timer);
287
        pr_debug("  _HPP: enable SERR    =0x%x\n", hpp->t0->enable_serr);
288
        pr_debug("  _HPP: enable PERR    =0x%x\n", hpp->t0->enable_perr);
289
 
290
free_and_return:
291
        kfree(string.pointer);
292
        kfree(ret_buf.pointer);
293
        return status;
294
}
295
 
296
 
297
 
298
/* acpi_run_oshp - get control of hotplug from the firmware
299
 *
300
 * @handle - the handle of the hotplug controller.
301
 */
302
acpi_status acpi_run_oshp(acpi_handle handle)
303
{
304
        acpi_status             status;
305
        struct acpi_buffer      string = { ACPI_ALLOCATE_BUFFER, NULL };
306
 
307
        acpi_get_name(handle, ACPI_FULL_PATHNAME, &string);
308
 
309
        /* run OSHP */
310
        status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL);
311
        if (ACPI_FAILURE(status))
312
                if (status != AE_NOT_FOUND)
313
                        printk(KERN_ERR "%s:%s OSHP fails=0x%x\n",
314
                               __FUNCTION__, (char *)string.pointer, status);
315
                else
316
                        dbg("%s:%s OSHP not found\n",
317
                            __FUNCTION__, (char *)string.pointer);
318
        else
319
                pr_debug("%s:%s OSHP passes\n", __FUNCTION__,
320
                        (char *)string.pointer);
321
 
322
        kfree(string.pointer);
323
        return status;
324
}
325
EXPORT_SYMBOL_GPL(acpi_run_oshp);
326
 
327
 
328
 
329
/* acpi_get_hp_params_from_firmware
330
 *
331
 * @bus - the pci_bus of the bus on which the device is newly added
332
 * @hpp - allocated by the caller
333
 */
334
acpi_status acpi_get_hp_params_from_firmware(struct pci_bus *bus,
335
                struct hotplug_params *hpp)
336
{
337
        acpi_status status = AE_NOT_FOUND;
338
        acpi_handle handle, phandle;
339
        struct pci_bus *pbus = bus;
340
        struct pci_dev *pdev;
341
 
342
        do {
343
                pdev = pbus->self;
344
                if (!pdev) {
345
                        handle = acpi_get_pci_rootbridge_handle(
346
                                pci_domain_nr(pbus), pbus->number);
347
                        break;
348
                }
349
                handle = DEVICE_ACPI_HANDLE(&(pdev->dev));
350
                pbus = pbus->parent;
351
        } while (!handle);
352
 
353
        /*
354
         * _HPP settings apply to all child buses, until another _HPP is
355
         * encountered. If we don't find an _HPP for the input pci dev,
356
         * look for it in the parent device scope since that would apply to
357
         * this pci dev. If we don't find any _HPP, use hardcoded defaults
358
         */
359
        while (handle) {
360
                status = acpi_run_hpx(handle, hpp);
361
                if (ACPI_SUCCESS(status))
362
                        break;
363
                status = acpi_run_hpp(handle, hpp);
364
                if (ACPI_SUCCESS(status))
365
                        break;
366
                if (acpi_root_bridge(handle))
367
                        break;
368
                status = acpi_get_parent(handle, &phandle);
369
                if (ACPI_FAILURE(status))
370
                        break;
371
                handle = phandle;
372
        }
373
        return status;
374
}
375
EXPORT_SYMBOL_GPL(acpi_get_hp_params_from_firmware);
376
 
377
 
378
/* acpi_root_bridge - check to see if this acpi object is a root bridge
379
 *
380
 * @handle - the acpi object in question.
381
 */
382
int acpi_root_bridge(acpi_handle handle)
383
{
384
        acpi_status status;
385
        struct acpi_device_info *info;
386
        struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
387
        int i;
388
 
389
        status = acpi_get_object_info(handle, &buffer);
390
        if (ACPI_SUCCESS(status)) {
391
                info = buffer.pointer;
392
                if ((info->valid & ACPI_VALID_HID) &&
393
                        !strcmp(PCI_ROOT_HID_STRING,
394
                                        info->hardware_id.value)) {
395
                        kfree(buffer.pointer);
396
                        return 1;
397
                }
398
                if (info->valid & ACPI_VALID_CID) {
399
                        for (i=0; i < info->compatibility_id.count; i++) {
400
                                if (!strcmp(PCI_ROOT_HID_STRING,
401
                                        info->compatibility_id.id[i].value)) {
402
                                        kfree(buffer.pointer);
403
                                        return 1;
404
                                }
405
                        }
406
                }
407
                kfree(buffer.pointer);
408
        }
409
        return 0;
410
}
411
EXPORT_SYMBOL_GPL(acpi_root_bridge);
412
 
413
module_param(debug_acpi, bool, 0644);
414
MODULE_PARM_DESC(debug_acpi, "Debugging mode for ACPI enabled or not");

powered by: WebSVN 2.1.0

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