• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/pci/pcie/
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#include <linux/aer.h>
18#include <linux/pci-aspm.h>
19
20#include "../pci.h"
21#include "portdrv.h"
22
23/**
24 * release_pcie_device - free PCI Express port service device structure
25 * @dev: Port service device to release
26 *
27 * Invoked automatically when device is being removed in response to
28 * device_unregister(dev).  Release all resources being claimed.
29 */
30static void release_pcie_device(struct device *dev)
31{
32	kfree(to_pcie_device(dev));
33}
34
35/**
36 * pcie_port_msix_add_entry - add entry to given array of MSI-X entries
37 * @entries: Array of MSI-X entries
38 * @new_entry: Index of the entry to add to the array
39 * @nr_entries: Number of entries aleady in the array
40 *
41 * Return value: Position of the added entry in the array
42 */
43static int pcie_port_msix_add_entry(
44	struct msix_entry *entries, int new_entry, int nr_entries)
45{
46	int j;
47
48	for (j = 0; j < nr_entries; j++)
49		if (entries[j].entry == new_entry)
50			return j;
51
52	entries[j].entry = new_entry;
53	return j;
54}
55
56/**
57 * pcie_port_enable_msix - try to set up MSI-X as interrupt mode for given port
58 * @dev: PCI Express port to handle
59 * @vectors: Array of interrupt vectors to populate
60 * @mask: Bitmask of port capabilities returned by get_port_device_capability()
61 *
62 * Return value: 0 on success, error code on failure
63 */
64static int pcie_port_enable_msix(struct pci_dev *dev, int *vectors, int mask)
65{
66	struct msix_entry *msix_entries;
67	int idx[PCIE_PORT_DEVICE_MAXSERVICES];
68	int nr_entries, status, pos, i, nvec;
69	u16 reg16;
70	u32 reg32;
71
72	nr_entries = pci_msix_table_size(dev);
73	if (!nr_entries)
74		return -EINVAL;
75	if (nr_entries > PCIE_PORT_MAX_MSIX_ENTRIES)
76		nr_entries = PCIE_PORT_MAX_MSIX_ENTRIES;
77
78	msix_entries = kzalloc(sizeof(*msix_entries) * nr_entries, GFP_KERNEL);
79	if (!msix_entries)
80		return -ENOMEM;
81
82	/*
83	 * Allocate as many entries as the port wants, so that we can check
84	 * which of them will be useful.  Moreover, if nr_entries is correctly
85	 * equal to the number of entries this port actually uses, we'll happily
86	 * go through without any tricks.
87	 */
88	for (i = 0; i < nr_entries; i++)
89		msix_entries[i].entry = i;
90
91	status = pci_enable_msix(dev, msix_entries, nr_entries);
92	if (status)
93		goto Exit;
94
95	for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++)
96		idx[i] = -1;
97	status = -EIO;
98	nvec = 0;
99
100	if (mask & (PCIE_PORT_SERVICE_PME | PCIE_PORT_SERVICE_HP)) {
101		int entry;
102
103		/*
104		 * The code below follows the PCI Express Base Specification 2.0
105		 * stating in Section 6.1.6 that "PME and Hot-Plug Event
106		 * interrupts (when both are implemented) always share the same
107		 * MSI or MSI-X vector, as indicated by the Interrupt Message
108		 * Number field in the PCI Express Capabilities register", where
109		 * according to Section 7.8.2 of the specification "For MSI-X,
110		 * the value in this field indicates which MSI-X Table entry is
111		 * used to generate the interrupt message."
112		 */
113		pos = pci_pcie_cap(dev);
114		pci_read_config_word(dev, pos + PCI_EXP_FLAGS, &reg16);
115		entry = (reg16 & PCI_EXP_FLAGS_IRQ) >> 9;
116		if (entry >= nr_entries)
117			goto Error;
118
119		i = pcie_port_msix_add_entry(msix_entries, entry, nvec);
120		if (i == nvec)
121			nvec++;
122
123		idx[PCIE_PORT_SERVICE_PME_SHIFT] = i;
124		idx[PCIE_PORT_SERVICE_HP_SHIFT] = i;
125	}
126
127	if (mask & PCIE_PORT_SERVICE_AER) {
128		int entry;
129
130		/*
131		 * The code below follows Section 7.10.10 of the PCI Express
132		 * Base Specification 2.0 stating that bits 31-27 of the Root
133		 * Error Status Register contain a value indicating which of the
134		 * MSI/MSI-X vectors assigned to the port is going to be used
135		 * for AER, where "For MSI-X, the value in this register
136		 * indicates which MSI-X Table entry is used to generate the
137		 * interrupt message."
138		 */
139		pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
140		pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, &reg32);
141		entry = reg32 >> 27;
142		if (entry >= nr_entries)
143			goto Error;
144
145		i = pcie_port_msix_add_entry(msix_entries, entry, nvec);
146		if (i == nvec)
147			nvec++;
148
149		idx[PCIE_PORT_SERVICE_AER_SHIFT] = i;
150	}
151
152	if (nvec == nr_entries) {
153		status = 0;
154	} else {
155		/* Drop the temporary MSI-X setup */
156		pci_disable_msix(dev);
157
158		/* Now allocate the MSI-X vectors for real */
159		status = pci_enable_msix(dev, msix_entries, nvec);
160		if (status)
161			goto Exit;
162	}
163
164	for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++)
165		vectors[i] = idx[i] >= 0 ? msix_entries[idx[i]].vector : -1;
166
167 Exit:
168	kfree(msix_entries);
169	return status;
170
171 Error:
172	pci_disable_msix(dev);
173	goto Exit;
174}
175
176/**
177 * init_service_irqs - initialize irqs for PCI Express port services
178 * @dev: PCI Express port to handle
179 * @irqs: Array of irqs to populate
180 * @mask: Bitmask of port capabilities returned by get_port_device_capability()
181 *
182 * Return value: Interrupt mode associated with the port
183 */
184static int init_service_irqs(struct pci_dev *dev, int *irqs, int mask)
185{
186	int i, irq = -1;
187
188	/* We have to use INTx if MSI cannot be used for PCIe PME. */
189	if ((mask & PCIE_PORT_SERVICE_PME) && pcie_pme_no_msi()) {
190		if (dev->pin)
191			irq = dev->irq;
192		goto no_msi;
193	}
194
195	/* Try to use MSI-X if supported */
196	if (!pcie_port_enable_msix(dev, irqs, mask))
197		return 0;
198
199	/* We're not going to use MSI-X, so try MSI and fall back to INTx */
200	if (!pci_enable_msi(dev) || dev->pin)
201		irq = dev->irq;
202
203 no_msi:
204	for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++)
205		irqs[i] = irq;
206	irqs[PCIE_PORT_SERVICE_VC_SHIFT] = -1;
207
208	if (irq < 0)
209		return -ENODEV;
210	return 0;
211}
212
213static void cleanup_service_irqs(struct pci_dev *dev)
214{
215	if (dev->msix_enabled)
216		pci_disable_msix(dev);
217	else if (dev->msi_enabled)
218		pci_disable_msi(dev);
219}
220
221/**
222 * get_port_device_capability - discover capabilities of a PCI Express port
223 * @dev: PCI Express port to examine
224 *
225 * The capabilities are read from the port's PCI Express configuration registers
226 * as described in PCI Express Base Specification 1.0a sections 7.8.2, 7.8.9 and
227 * 7.9 - 7.11.
228 *
229 * Return value: Bitmask of discovered port capabilities
230 */
231static int get_port_device_capability(struct pci_dev *dev)
232{
233	int services = 0, pos;
234	u16 reg16;
235	u32 reg32;
236	int cap_mask;
237	int err;
238
239	err = pcie_port_platform_notify(dev, &cap_mask);
240	if (pcie_ports_auto) {
241		if (err) {
242			pcie_no_aspm();
243			return 0;
244		}
245	} else {
246		cap_mask = PCIE_PORT_SERVICE_PME | PCIE_PORT_SERVICE_HP
247				| PCIE_PORT_SERVICE_VC;
248		if (pci_aer_available())
249			cap_mask |= PCIE_PORT_SERVICE_AER;
250	}
251
252	pos = pci_pcie_cap(dev);
253	pci_read_config_word(dev, pos + PCI_EXP_FLAGS, &reg16);
254	/* Hot-Plug Capable */
255	if ((cap_mask & PCIE_PORT_SERVICE_HP) && (reg16 & PCI_EXP_FLAGS_SLOT)) {
256		pci_read_config_dword(dev, pos + PCI_EXP_SLTCAP, &reg32);
257		if (reg32 & PCI_EXP_SLTCAP_HPC) {
258			services |= PCIE_PORT_SERVICE_HP;
259			/*
260			 * Disable hot-plug interrupts in case they have been
261			 * enabled by the BIOS and the hot-plug service driver
262			 * is not loaded.
263			 */
264			pos += PCI_EXP_SLTCTL;
265			pci_read_config_word(dev, pos, &reg16);
266			reg16 &= ~(PCI_EXP_SLTCTL_CCIE | PCI_EXP_SLTCTL_HPIE);
267			pci_write_config_word(dev, pos, reg16);
268		}
269	}
270	/* AER capable */
271	if ((cap_mask & PCIE_PORT_SERVICE_AER)
272	    && pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR)) {
273		services |= PCIE_PORT_SERVICE_AER;
274		/*
275		 * Disable AER on this port in case it's been enabled by the
276		 * BIOS (the AER service driver will enable it when necessary).
277		 */
278		pci_disable_pcie_error_reporting(dev);
279	}
280	/* VC support */
281	if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_VC))
282		services |= PCIE_PORT_SERVICE_VC;
283	/* Root ports are capable of generating PME too */
284	if ((cap_mask & PCIE_PORT_SERVICE_PME)
285	    && dev->pcie_type == PCI_EXP_TYPE_ROOT_PORT) {
286		services |= PCIE_PORT_SERVICE_PME;
287		/*
288		 * Disable PME interrupt on this port in case it's been enabled
289		 * by the BIOS (the PME service driver will enable it when
290		 * necessary).
291		 */
292		pcie_pme_interrupt_enable(dev, false);
293	}
294
295	return services;
296}
297
298/**
299 * pcie_device_init - allocate and initialize PCI Express port service device
300 * @pdev: PCI Express port to associate the service device with
301 * @service: Type of service to associate with the service device
302 * @irq: Interrupt vector to associate with the service device
303 */
304static int pcie_device_init(struct pci_dev *pdev, int service, int irq)
305{
306	int retval;
307	struct pcie_device *pcie;
308	struct device *device;
309
310	pcie = kzalloc(sizeof(*pcie), GFP_KERNEL);
311	if (!pcie)
312		return -ENOMEM;
313	pcie->port = pdev;
314	pcie->irq = irq;
315	pcie->service = service;
316
317	/* Initialize generic device interface */
318	device = &pcie->device;
319	device->bus = &pcie_port_bus_type;
320	device->release = release_pcie_device;	/* callback to free pcie dev */
321	dev_set_name(device, "%s:pcie%02x",
322		     pci_name(pdev),
323		     get_descriptor_id(pdev->pcie_type, service));
324	device->parent = &pdev->dev;
325	device_enable_async_suspend(device);
326
327	retval = device_register(device);
328	if (retval)
329		kfree(pcie);
330	else
331		get_device(device);
332	return retval;
333}
334
335/**
336 * pcie_port_device_register - register PCI Express port
337 * @dev: PCI Express port to register
338 *
339 * Allocate the port extension structure and register services associated with
340 * the port.
341 */
342int pcie_port_device_register(struct pci_dev *dev)
343{
344	int status, capabilities, i, nr_service;
345	int irqs[PCIE_PORT_DEVICE_MAXSERVICES];
346
347	/* Get and check PCI Express port services */
348	capabilities = get_port_device_capability(dev);
349	if (!capabilities)
350		return -ENODEV;
351
352	/* Enable PCI Express port device */
353	status = pci_enable_device(dev);
354	if (status)
355		return status;
356	pci_set_master(dev);
357	/*
358	 * Initialize service irqs. Don't use service devices that
359	 * require interrupts if there is no way to generate them.
360	 */
361	status = init_service_irqs(dev, irqs, capabilities);
362	if (status) {
363		capabilities &= PCIE_PORT_SERVICE_VC;
364		if (!capabilities)
365			goto error_disable;
366	}
367
368	/* Allocate child services if any */
369	status = -ENODEV;
370	nr_service = 0;
371	for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) {
372		int service = 1 << i;
373		if (!(capabilities & service))
374			continue;
375		if (!pcie_device_init(dev, service, irqs[i]))
376			nr_service++;
377	}
378	if (!nr_service)
379		goto error_cleanup_irqs;
380
381	return 0;
382
383error_cleanup_irqs:
384	cleanup_service_irqs(dev);
385error_disable:
386	pci_disable_device(dev);
387	return status;
388}
389
390#ifdef CONFIG_PM
391static int suspend_iter(struct device *dev, void *data)
392{
393	struct pcie_port_service_driver *service_driver;
394
395	if ((dev->bus == &pcie_port_bus_type) && dev->driver) {
396		service_driver = to_service_driver(dev->driver);
397		if (service_driver->suspend)
398			service_driver->suspend(to_pcie_device(dev));
399	}
400	return 0;
401}
402
403/**
404 * pcie_port_device_suspend - suspend port services associated with a PCIe port
405 * @dev: PCI Express port to handle
406 */
407int pcie_port_device_suspend(struct device *dev)
408{
409	return device_for_each_child(dev, NULL, suspend_iter);
410}
411
412static int resume_iter(struct device *dev, void *data)
413{
414	struct pcie_port_service_driver *service_driver;
415
416	if ((dev->bus == &pcie_port_bus_type) &&
417	    (dev->driver)) {
418		service_driver = to_service_driver(dev->driver);
419		if (service_driver->resume)
420			service_driver->resume(to_pcie_device(dev));
421	}
422	return 0;
423}
424
425/**
426 * pcie_port_device_suspend - resume port services associated with a PCIe port
427 * @dev: PCI Express port to handle
428 */
429int pcie_port_device_resume(struct device *dev)
430{
431	return device_for_each_child(dev, NULL, resume_iter);
432}
433#endif /* PM */
434
435static int remove_iter(struct device *dev, void *data)
436{
437	if (dev->bus == &pcie_port_bus_type) {
438		put_device(dev);
439		device_unregister(dev);
440	}
441	return 0;
442}
443
444/**
445 * pcie_port_device_remove - unregister PCI Express port service devices
446 * @dev: PCI Express port the service devices to unregister are associated with
447 *
448 * Remove PCI Express port service devices associated with given port and
449 * disable MSI-X or MSI for the port.
450 */
451void pcie_port_device_remove(struct pci_dev *dev)
452{
453	device_for_each_child(&dev->dev, NULL, remove_iter);
454	cleanup_service_irqs(dev);
455	pci_disable_device(dev);
456}
457
458/**
459 * pcie_port_probe_service - probe driver for given PCI Express port service
460 * @dev: PCI Express port service device to probe against
461 *
462 * If PCI Express port service driver is registered with
463 * pcie_port_service_register(), this function will be called by the driver core
464 * whenever match is found between the driver and a port service device.
465 */
466static int pcie_port_probe_service(struct device *dev)
467{
468	struct pcie_device *pciedev;
469	struct pcie_port_service_driver *driver;
470	int status;
471
472	if (!dev || !dev->driver)
473		return -ENODEV;
474
475	driver = to_service_driver(dev->driver);
476	if (!driver || !driver->probe)
477		return -ENODEV;
478
479	pciedev = to_pcie_device(dev);
480	status = driver->probe(pciedev);
481	if (!status) {
482		dev_printk(KERN_DEBUG, dev, "service driver %s loaded\n",
483			driver->name);
484		get_device(dev);
485	}
486	return status;
487}
488
489/**
490 * pcie_port_remove_service - detach driver from given PCI Express port service
491 * @dev: PCI Express port service device to handle
492 *
493 * If PCI Express port service driver is registered with
494 * pcie_port_service_register(), this function will be called by the driver core
495 * when device_unregister() is called for the port service device associated
496 * with the driver.
497 */
498static int pcie_port_remove_service(struct device *dev)
499{
500	struct pcie_device *pciedev;
501	struct pcie_port_service_driver *driver;
502
503	if (!dev || !dev->driver)
504		return 0;
505
506	pciedev = to_pcie_device(dev);
507	driver = to_service_driver(dev->driver);
508	if (driver && driver->remove) {
509		dev_printk(KERN_DEBUG, dev, "unloading service driver %s\n",
510			driver->name);
511		driver->remove(pciedev);
512		put_device(dev);
513	}
514	return 0;
515}
516
517/**
518 * pcie_port_shutdown_service - shut down given PCI Express port service
519 * @dev: PCI Express port service device to handle
520 *
521 * If PCI Express port service driver is registered with
522 * pcie_port_service_register(), this function will be called by the driver core
523 * when device_shutdown() is called for the port service device associated
524 * with the driver.
525 */
526static void pcie_port_shutdown_service(struct device *dev) {}
527
528/**
529 * pcie_port_service_register - register PCI Express port service driver
530 * @new: PCI Express port service driver to register
531 */
532int pcie_port_service_register(struct pcie_port_service_driver *new)
533{
534	if (pcie_ports_disabled)
535		return -ENODEV;
536
537	new->driver.name = (char *)new->name;
538	new->driver.bus = &pcie_port_bus_type;
539	new->driver.probe = pcie_port_probe_service;
540	new->driver.remove = pcie_port_remove_service;
541	new->driver.shutdown = pcie_port_shutdown_service;
542
543	return driver_register(&new->driver);
544}
545EXPORT_SYMBOL(pcie_port_service_register);
546
547/**
548 * pcie_port_service_unregister - unregister PCI Express port service driver
549 * @drv: PCI Express port service driver to unregister
550 */
551void pcie_port_service_unregister(struct pcie_port_service_driver *drv)
552{
553	driver_unregister(&drv->driver);
554}
555EXPORT_SYMBOL(pcie_port_service_unregister);
556