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