]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/pci/pcie/portdrv_core.c
6ca5a40cc61c19042c85d20dfa12ee121f1650ed
[linux-2.6-omap-h63xx.git] / drivers / pci / pcie / portdrv_core.c
1 /*
2  * File:        portdrv_core.c
3  * Purpose:     PCI Express Port Bus Driver's Core Functions
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/string.h>
15 #include <linux/slab.h>
16 #include <linux/pcieport_if.h>
17
18 #include "portdrv.h"
19
20 extern int pcie_mch_quirk;      /* MSI-quirk Indicator */
21
22 static int pcie_port_probe_service(struct device *dev)
23 {
24         struct pcie_device *pciedev;
25         struct pcie_port_service_driver *driver;
26         int status;
27
28         if (!dev || !dev->driver)
29                 return -ENODEV;
30
31         driver = to_service_driver(dev->driver);
32         if (!driver || !driver->probe)
33                 return -ENODEV;
34
35         pciedev = to_pcie_device(dev);
36         status = driver->probe(pciedev, driver->id_table);
37         if (!status) {
38                 dev_printk(KERN_DEBUG, dev, "service driver %s loaded\n",
39                         driver->name);
40                 get_device(dev);
41         }
42         return status;
43 }
44
45 static int pcie_port_remove_service(struct device *dev)
46 {
47         struct pcie_device *pciedev;
48         struct pcie_port_service_driver *driver;
49
50         if (!dev || !dev->driver)
51                 return 0;
52
53         pciedev = to_pcie_device(dev);
54         driver = to_service_driver(dev->driver);
55         if (driver && driver->remove) { 
56                 dev_printk(KERN_DEBUG, dev, "unloading service driver %s\n",
57                         driver->name);
58                 driver->remove(pciedev);
59                 put_device(dev);
60         }
61         return 0;
62 }
63
64 static void pcie_port_shutdown_service(struct device *dev) {}
65
66 /**
67  * release_pcie_device - free PCI Express port service device structure
68  * @dev: Port service device to release
69  *
70  * Invoked automatically when device is being removed in response to
71  * device_unregister(dev).  Release all resources being claimed.
72  */
73 static void release_pcie_device(struct device *dev)
74 {
75         kfree(to_pcie_device(dev));                     
76 }
77
78 static int is_msi_quirked(struct pci_dev *dev)
79 {
80         int port_type, quirk = 0;
81         u16 reg16;
82
83         pci_read_config_word(dev, 
84                 pci_find_capability(dev, PCI_CAP_ID_EXP) + 
85                 PCIE_CAPABILITIES_REG, &reg16);
86         port_type = (reg16 >> 4) & PORT_TYPE_MASK;
87         switch(port_type) {
88         case PCIE_RC_PORT:
89                 if (pcie_mch_quirk == 1)
90                         quirk = 1;
91                 break;
92         case PCIE_SW_UPSTREAM_PORT:
93         case PCIE_SW_DOWNSTREAM_PORT:
94         default:
95                 break;  
96         }
97         return quirk;
98 }
99
100 /**
101  * assign_interrupt_mode - choose interrupt mode for PCI Express port services
102  *                         (INTx, MSI-X, MSI) and set up vectors
103  * @dev: PCI Express port to handle
104  * @vectors: Array of interrupt vectors to populate
105  * @mask: Bitmask of port capabilities returned by get_port_device_capability()
106  *
107  * Return value: Interrupt mode associated with the port
108  */
109 static int assign_interrupt_mode(struct pci_dev *dev, int *vectors, int mask)
110 {
111         int i, pos, nvec, status = -EINVAL;
112         int interrupt_mode = PCIE_PORT_INTx_MODE;
113
114         /* Set INTx as default */
115         for (i = 0, nvec = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) {
116                 if (mask & (1 << i)) 
117                         nvec++;
118                 vectors[i] = dev->irq;
119         }
120         
121         /* Check MSI quirk */
122         if (is_msi_quirked(dev))
123                 return interrupt_mode;
124
125         /* Select MSI-X over MSI if supported */                
126         pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
127         if (pos) {
128                 struct msix_entry msix_entries[PCIE_PORT_DEVICE_MAXSERVICES] = 
129                         {{0, 0}, {0, 1}, {0, 2}, {0, 3}};
130                 status = pci_enable_msix(dev, msix_entries, nvec);
131                 if (!status) {
132                         int j = 0;
133
134                         interrupt_mode = PCIE_PORT_MSIX_MODE;
135                         for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) {
136                                 if (mask & (1 << i)) 
137                                         vectors[i] = msix_entries[j++].vector;
138                         }
139                 }
140         } 
141         if (status) {
142                 pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
143                 if (pos) {
144                         status = pci_enable_msi(dev);
145                         if (!status) {
146                                 interrupt_mode = PCIE_PORT_MSI_MODE;
147                                 for (i = 0;i < PCIE_PORT_DEVICE_MAXSERVICES;i++)
148                                         vectors[i] = dev->irq;
149                         }
150                 }
151         } 
152         return interrupt_mode;
153 }
154
155 /**
156  * get_port_device_capability - discover capabilities of a PCI Express port
157  * @dev: PCI Express port to examine
158  *
159  * The capabilities are read from the port's PCI Express configuration registers
160  * as described in PCI Express Base Specification 1.0a sections 7.8.2, 7.8.9 and
161  * 7.9 - 7.11.
162  *
163  * Return value: Bitmask of discovered port capabilities
164  */
165 static int get_port_device_capability(struct pci_dev *dev)
166 {
167         int services = 0, pos;
168         u16 reg16;
169         u32 reg32;
170
171         pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
172         pci_read_config_word(dev, pos + PCIE_CAPABILITIES_REG, &reg16);
173         /* Hot-Plug Capable */
174         if (reg16 & PORT_TO_SLOT_MASK) {
175                 pci_read_config_dword(dev, 
176                         pos + PCIE_SLOT_CAPABILITIES_REG, &reg32);
177                 if (reg32 & SLOT_HP_CAPABLE_MASK)
178                         services |= PCIE_PORT_SERVICE_HP;
179         } 
180         /* PME Capable - root port capability */
181         if (((reg16 >> 4) & PORT_TYPE_MASK) == PCIE_RC_PORT)
182                 services |= PCIE_PORT_SERVICE_PME;
183
184         if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR))
185                 services |= PCIE_PORT_SERVICE_AER;
186         if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_VC))
187                 services |= PCIE_PORT_SERVICE_VC;
188
189         return services;
190 }
191
192 /**
193  * pcie_device_init - initialize PCI Express port service device
194  * @dev: Port service device to initialize
195  * @parent: PCI Express port to associate the service device with
196  * @port_type: Type of the port
197  * @service_type: Type of service to associate with the service device
198  * @irq: Interrupt vector to associate with the service device
199  * @irq_mode: Interrupt mode of the service (INTx, MSI-X, MSI)
200  */
201 static void pcie_device_init(struct pci_dev *parent, struct pcie_device *dev, 
202         int port_type, int service_type, int irq, int irq_mode)
203 {
204         struct device *device;
205
206         dev->port = parent;
207         dev->interrupt_mode = irq_mode;
208         dev->irq = irq;
209         dev->id.vendor = parent->vendor;
210         dev->id.device = parent->device;
211         dev->id.port_type = port_type;
212         dev->id.service_type = (1 << service_type);
213
214         /* Initialize generic device interface */
215         device = &dev->device;
216         memset(device, 0, sizeof(struct device));
217         device->bus = &pcie_port_bus_type;
218         device->driver = NULL;
219         device->driver_data = NULL;
220         device->release = release_pcie_device;  /* callback to free pcie dev */
221         dev_set_name(device, "%s:pcie%02x",
222                  pci_name(parent), get_descriptor_id(port_type, service_type));
223         device->parent = &parent->dev;
224 }
225
226 /**
227  * alloc_pcie_device - allocate PCI Express port service device structure
228  * @parent: PCI Express port to associate the service device with
229  * @port_type: Type of the port
230  * @service_type: Type of service to associate with the service device
231  * @irq: Interrupt vector to associate with the service device
232  * @irq_mode: Interrupt mode of the service (INTx, MSI-X, MSI)
233  */
234 static struct pcie_device* alloc_pcie_device(struct pci_dev *parent,
235         int port_type, int service_type, int irq, int irq_mode)
236 {
237         struct pcie_device *device;
238
239         device = kzalloc(sizeof(struct pcie_device), GFP_KERNEL);
240         if (!device)
241                 return NULL;
242
243         pcie_device_init(parent, device, port_type, service_type, irq,irq_mode);
244         return device;
245 }
246
247 /**
248  * pcie_port_device_probe - check if device is a PCI Express port
249  * @dev: Device to check
250  */
251 int pcie_port_device_probe(struct pci_dev *dev)
252 {
253         int pos, type;
254         u16 reg;
255
256         if (!(pos = pci_find_capability(dev, PCI_CAP_ID_EXP)))
257                 return -ENODEV;
258
259         pci_read_config_word(dev, pos + PCIE_CAPABILITIES_REG, &reg);
260         type = (reg >> 4) & PORT_TYPE_MASK;
261         if (    type == PCIE_RC_PORT || type == PCIE_SW_UPSTREAM_PORT ||
262                 type == PCIE_SW_DOWNSTREAM_PORT )
263                 return 0;
264
265         return -ENODEV;
266 }
267
268 /**
269  * pcie_port_device_register - register PCI Express port
270  * @dev: PCI Express port to register
271  *
272  * Allocate the port extension structure and register services associated with
273  * the port.
274  */
275 int pcie_port_device_register(struct pci_dev *dev)
276 {
277         struct pcie_port_device_ext *p_ext;
278         int status, type, capabilities, irq_mode, i;
279         int vectors[PCIE_PORT_DEVICE_MAXSERVICES];
280         u16 reg16;
281
282         /* Allocate port device extension */
283         if (!(p_ext = kmalloc(sizeof(struct pcie_port_device_ext), GFP_KERNEL)))
284                 return -ENOMEM;
285
286         pci_set_drvdata(dev, p_ext);
287
288         /* Get port type */
289         pci_read_config_word(dev,
290                 pci_find_capability(dev, PCI_CAP_ID_EXP) +
291                 PCIE_CAPABILITIES_REG, &reg16);
292         type = (reg16 >> 4) & PORT_TYPE_MASK;
293
294         /* Now get port services */
295         capabilities = get_port_device_capability(dev);
296         irq_mode = assign_interrupt_mode(dev, vectors, capabilities);
297         p_ext->interrupt_mode = irq_mode;
298
299         /* Allocate child services if any */
300         for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) {
301                 struct pcie_device *child;
302
303                 if (capabilities & (1 << i)) {
304                         child = alloc_pcie_device(
305                                 dev,            /* parent */
306                                 type,           /* port type */
307                                 i,              /* service type */
308                                 vectors[i],     /* irq */
309                                 irq_mode        /* interrupt mode */);
310                         if (child) {
311                                 status = device_register(&child->device);
312                                 if (status) {
313                                         kfree(child);
314                                         continue;
315                                 }
316                                 get_device(&child->device);
317                         }
318                 }
319         }
320         return 0;
321 }
322
323 #ifdef CONFIG_PM
324 static int suspend_iter(struct device *dev, void *data)
325 {
326         struct pcie_port_service_driver *service_driver;
327         pm_message_t state = * (pm_message_t *) data;
328
329         if ((dev->bus == &pcie_port_bus_type) &&
330             (dev->driver)) {
331                 service_driver = to_service_driver(dev->driver);
332                 if (service_driver->suspend)
333                         service_driver->suspend(to_pcie_device(dev), state);
334         }
335         return 0;
336 }
337
338 /**
339  * pcie_port_device_suspend - suspend port services associated with a PCIe port
340  * @dev: PCI Express port to handle
341  * @state: Representation of system power management transition in progress
342  */
343 int pcie_port_device_suspend(struct pci_dev *dev, pm_message_t state)
344 {
345         return device_for_each_child(&dev->dev, &state, suspend_iter);
346 }
347
348 static int resume_iter(struct device *dev, void *data)
349 {
350         struct pcie_port_service_driver *service_driver;
351
352         if ((dev->bus == &pcie_port_bus_type) &&
353             (dev->driver)) {
354                 service_driver = to_service_driver(dev->driver);
355                 if (service_driver->resume)
356                         service_driver->resume(to_pcie_device(dev));
357         }
358         return 0;
359 }
360
361 /**
362  * pcie_port_device_suspend - resume port services associated with a PCIe port
363  * @dev: PCI Express port to handle
364  */
365 int pcie_port_device_resume(struct pci_dev *dev)
366 {
367         return device_for_each_child(&dev->dev, NULL, resume_iter);
368 }
369 #endif
370
371 static int remove_iter(struct device *dev, void *data)
372 {
373         struct pcie_port_service_driver *service_driver;
374
375         if (dev->bus == &pcie_port_bus_type) {
376                 if (dev->driver) {
377                         service_driver = to_service_driver(dev->driver);
378                         if (service_driver->remove)
379                                 service_driver->remove(to_pcie_device(dev));
380                 }
381                 *(unsigned long*)data = (unsigned long)dev;
382                 return 1;
383         }
384         return 0;
385 }
386
387 /**
388  * pcie_port_device_remove - unregister PCI Express port service devices
389  * @dev: PCI Express port the service devices to unregister are associated with
390  *
391  * Remove PCI Express port service devices associated with given port and
392  * disable MSI-X or MSI for the port.
393  */
394 void pcie_port_device_remove(struct pci_dev *dev)
395 {
396         struct device *device;
397         unsigned long device_addr;
398         int interrupt_mode = PCIE_PORT_INTx_MODE;
399         int status;
400
401         do {
402                 status = device_for_each_child(&dev->dev, &device_addr, remove_iter);
403                 if (status) {
404                         device = (struct device*)device_addr;
405                         interrupt_mode = (to_pcie_device(device))->interrupt_mode;
406                         put_device(device);
407                         device_unregister(device);
408                 }
409         } while (status);
410         /* Switch to INTx by default if MSI enabled */
411         if (interrupt_mode == PCIE_PORT_MSIX_MODE)
412                 pci_disable_msix(dev);
413         else if (interrupt_mode == PCIE_PORT_MSI_MODE)
414                 pci_disable_msi(dev);
415 }
416
417 int pcie_port_bus_register(void)
418 {
419         return bus_register(&pcie_port_bus_type);
420 }
421
422 void pcie_port_bus_unregister(void)
423 {
424         bus_unregister(&pcie_port_bus_type);
425 }
426
427 int pcie_port_service_register(struct pcie_port_service_driver *new)
428 {
429         new->driver.name = (char *)new->name;
430         new->driver.bus = &pcie_port_bus_type;
431         new->driver.probe = pcie_port_probe_service;
432         new->driver.remove = pcie_port_remove_service;
433         new->driver.shutdown = pcie_port_shutdown_service;
434
435         return driver_register(&new->driver);
436 }
437
438 void pcie_port_service_unregister(struct pcie_port_service_driver *new)
439 {
440         driver_unregister(&new->driver);
441 }
442
443 EXPORT_SYMBOL(pcie_port_service_register);
444 EXPORT_SYMBOL(pcie_port_service_unregister);