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

Subversion Repositories test_project

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * File:        portdrv_pci.c
3
 * Purpose:     PCI Express Port Bus Driver
4
 *
5
 * Copyright (C) 2004 Intel
6
 * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com)
7
 */
8
 
9
#include <linux/module.h>
10
#include <linux/pci.h>
11
#include <linux/kernel.h>
12
#include <linux/errno.h>
13
#include <linux/pm.h>
14
#include <linux/init.h>
15
#include <linux/slab.h>
16
#include <linux/pcieport_if.h>
17
#include <linux/aer.h>
18
 
19
#include "portdrv.h"
20
#include "aer/aerdrv.h"
21
 
22
/*
23
 * Version Information
24
 */
25
#define DRIVER_VERSION "v1.0"
26
#define DRIVER_AUTHOR "tom.l.nguyen@intel.com"
27
#define DRIVER_DESC "PCIE Port Bus Driver"
28
MODULE_AUTHOR(DRIVER_AUTHOR);
29
MODULE_DESCRIPTION(DRIVER_DESC);
30
MODULE_LICENSE("GPL");
31
 
32
/* global data */
33
static const char device_name[] = "pcieport-driver";
34
 
35
static int pcie_portdrv_save_config(struct pci_dev *dev)
36
{
37
        return pci_save_state(dev);
38
}
39
 
40
static int pcie_portdrv_restore_config(struct pci_dev *dev)
41
{
42
        int retval;
43
 
44
        pci_restore_state(dev);
45
        retval = pci_enable_device(dev);
46
        if (retval)
47
                return retval;
48
        pci_set_master(dev);
49
        return 0;
50
}
51
 
52
#ifdef CONFIG_PM
53
static int pcie_portdrv_suspend(struct pci_dev *dev, pm_message_t state)
54
{
55
        int ret = pcie_port_device_suspend(dev, state);
56
 
57
        if (!ret)
58
                ret = pcie_portdrv_save_config(dev);
59
        return ret;
60
}
61
 
62
static int pcie_portdrv_resume(struct pci_dev *dev)
63
{
64
        pcie_portdrv_restore_config(dev);
65
        return pcie_port_device_resume(dev);
66
}
67
#else
68
#define pcie_portdrv_suspend NULL
69
#define pcie_portdrv_resume NULL
70
#endif
71
 
72
/*
73
 * pcie_portdrv_probe - Probe PCI-Express port devices
74
 * @dev: PCI-Express port device being probed
75
 *
76
 * If detected invokes the pcie_port_device_register() method for
77
 * this port device.
78
 *
79
 */
80
static int __devinit pcie_portdrv_probe (struct pci_dev *dev,
81
                                const struct pci_device_id *id )
82
{
83
        int                     status;
84
 
85
        status = pcie_port_device_probe(dev);
86
        if (status)
87
                return status;
88
 
89
        if (pci_enable_device(dev) < 0)
90
                return -ENODEV;
91
 
92
        pci_set_master(dev);
93
        if (!dev->irq && dev->pin) {
94
                printk(KERN_WARNING
95
                "%s->Dev[%04x:%04x] has invalid IRQ. Check vendor BIOS\n",
96
                __FUNCTION__, dev->vendor, dev->device);
97
        }
98
        if (pcie_port_device_register(dev)) {
99
                pci_disable_device(dev);
100
                return -ENOMEM;
101
        }
102
 
103
        pcie_portdrv_save_config(dev);
104
 
105
        pci_enable_pcie_error_reporting(dev);
106
 
107
        return 0;
108
}
109
 
110
static void pcie_portdrv_remove (struct pci_dev *dev)
111
{
112
        pcie_port_device_remove(dev);
113
        kfree(pci_get_drvdata(dev));
114
}
115
 
116
static int error_detected_iter(struct device *device, void *data)
117
{
118
        struct pcie_device *pcie_device;
119
        struct pcie_port_service_driver *driver;
120
        struct aer_broadcast_data *result_data;
121
        pci_ers_result_t status;
122
 
123
        result_data = (struct aer_broadcast_data *) data;
124
 
125
        if (device->bus == &pcie_port_bus_type && device->driver) {
126
                driver = to_service_driver(device->driver);
127
                if (!driver ||
128
                        !driver->err_handler ||
129
                        !driver->err_handler->error_detected)
130
                        return 0;
131
 
132
                pcie_device = to_pcie_device(device);
133
 
134
                /* Forward error detected message to service drivers */
135
                status = driver->err_handler->error_detected(
136
                        pcie_device->port,
137
                        result_data->state);
138
                result_data->result =
139
                        merge_result(result_data->result, status);
140
        }
141
 
142
        return 0;
143
}
144
 
145
static pci_ers_result_t pcie_portdrv_error_detected(struct pci_dev *dev,
146
                                        enum pci_channel_state error)
147
{
148
        struct aer_broadcast_data result_data =
149
                        {error, PCI_ERS_RESULT_CAN_RECOVER};
150
        int retval;
151
 
152
        /* can not fail */
153
        retval = device_for_each_child(&dev->dev, &result_data, error_detected_iter);
154
 
155
        return result_data.result;
156
}
157
 
158
static int mmio_enabled_iter(struct device *device, void *data)
159
{
160
        struct pcie_device *pcie_device;
161
        struct pcie_port_service_driver *driver;
162
        pci_ers_result_t status, *result;
163
 
164
        result = (pci_ers_result_t *) data;
165
 
166
        if (device->bus == &pcie_port_bus_type && device->driver) {
167
                driver = to_service_driver(device->driver);
168
                if (driver &&
169
                        driver->err_handler &&
170
                        driver->err_handler->mmio_enabled) {
171
                        pcie_device = to_pcie_device(device);
172
 
173
                        /* Forward error message to service drivers */
174
                        status = driver->err_handler->mmio_enabled(
175
                                        pcie_device->port);
176
                        *result = merge_result(*result, status);
177
                }
178
        }
179
 
180
        return 0;
181
}
182
 
183
static pci_ers_result_t pcie_portdrv_mmio_enabled(struct pci_dev *dev)
184
{
185
        pci_ers_result_t status = PCI_ERS_RESULT_RECOVERED;
186
        int retval;
187
 
188
        /* get true return value from &status */
189
        retval = device_for_each_child(&dev->dev, &status, mmio_enabled_iter);
190
        return status;
191
}
192
 
193
static int slot_reset_iter(struct device *device, void *data)
194
{
195
        struct pcie_device *pcie_device;
196
        struct pcie_port_service_driver *driver;
197
        pci_ers_result_t status, *result;
198
 
199
        result = (pci_ers_result_t *) data;
200
 
201
        if (device->bus == &pcie_port_bus_type && device->driver) {
202
                driver = to_service_driver(device->driver);
203
                if (driver &&
204
                        driver->err_handler &&
205
                        driver->err_handler->slot_reset) {
206
                        pcie_device = to_pcie_device(device);
207
 
208
                        /* Forward error message to service drivers */
209
                        status = driver->err_handler->slot_reset(
210
                                        pcie_device->port);
211
                        *result = merge_result(*result, status);
212
                }
213
        }
214
 
215
        return 0;
216
}
217
 
218
static pci_ers_result_t pcie_portdrv_slot_reset(struct pci_dev *dev)
219
{
220
        pci_ers_result_t status = PCI_ERS_RESULT_NONE;
221
        int retval;
222
 
223
        /* If fatal, restore cfg space for possible link reset at upstream */
224
        if (dev->error_state == pci_channel_io_frozen) {
225
                pcie_portdrv_restore_config(dev);
226
                pci_enable_pcie_error_reporting(dev);
227
        }
228
 
229
        /* get true return value from &status */
230
        retval = device_for_each_child(&dev->dev, &status, slot_reset_iter);
231
 
232
        return status;
233
}
234
 
235
static int resume_iter(struct device *device, void *data)
236
{
237
        struct pcie_device *pcie_device;
238
        struct pcie_port_service_driver *driver;
239
 
240
        if (device->bus == &pcie_port_bus_type && device->driver) {
241
                driver = to_service_driver(device->driver);
242
                if (driver &&
243
                        driver->err_handler &&
244
                        driver->err_handler->resume) {
245
                        pcie_device = to_pcie_device(device);
246
 
247
                        /* Forward error message to service drivers */
248
                        driver->err_handler->resume(pcie_device->port);
249
                }
250
        }
251
 
252
        return 0;
253
}
254
 
255
static void pcie_portdrv_err_resume(struct pci_dev *dev)
256
{
257
        int retval;
258
        /* nothing to do with error value, if it ever happens */
259
        retval = device_for_each_child(&dev->dev, NULL, resume_iter);
260
}
261
 
262
/*
263
 * LINUX Device Driver Model
264
 */
265
static const struct pci_device_id port_pci_ids[] = { {
266
        /* handle any PCI-Express port */
267
        PCI_DEVICE_CLASS(((PCI_CLASS_BRIDGE_PCI << 8) | 0x00), ~0),
268
        }, { /* end: all zeroes */ }
269
};
270
MODULE_DEVICE_TABLE(pci, port_pci_ids);
271
 
272
static struct pci_error_handlers pcie_portdrv_err_handler = {
273
                .error_detected = pcie_portdrv_error_detected,
274
                .mmio_enabled = pcie_portdrv_mmio_enabled,
275
                .slot_reset = pcie_portdrv_slot_reset,
276
                .resume = pcie_portdrv_err_resume,
277
};
278
 
279
static struct pci_driver pcie_portdriver = {
280
        .name           = (char *)device_name,
281
        .id_table       = &port_pci_ids[0],
282
 
283
        .probe          = pcie_portdrv_probe,
284
        .remove         = pcie_portdrv_remove,
285
 
286
        .suspend        = pcie_portdrv_suspend,
287
        .resume         = pcie_portdrv_resume,
288
 
289
        .err_handler    = &pcie_portdrv_err_handler,
290
};
291
 
292
static int __init pcie_portdrv_init(void)
293
{
294
        int retval;
295
 
296
        retval = pcie_port_bus_register();
297
        if (retval) {
298
                printk(KERN_WARNING "PCIE: bus_register error: %d\n", retval);
299
                goto out;
300
        }
301
        retval = pci_register_driver(&pcie_portdriver);
302
        if (retval)
303
                pcie_port_bus_unregister();
304
 out:
305
        return retval;
306
}
307
 
308
static void __exit pcie_portdrv_exit(void)
309
{
310
        pci_unregister_driver(&pcie_portdriver);
311
        pcie_port_bus_unregister();
312
}
313
 
314
module_init(pcie_portdrv_init);
315
module_exit(pcie_portdrv_exit);

powered by: WebSVN 2.1.0

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