diff options
Diffstat (limited to 'drivers/pci/pcie')
-rw-r--r-- | drivers/pci/pcie/portdrv_core.c | 41 |
1 files changed, 28 insertions, 13 deletions
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c index 273e97619bce..265eba033a4a 100644 --- a/drivers/pci/pcie/portdrv_core.c +++ b/drivers/pci/pcie/portdrv_core.c | |||
@@ -43,7 +43,7 @@ static int assign_interrupt_mode(struct pci_dev *dev, int *vectors, int mask) | |||
43 | { | 43 | { |
44 | struct pcie_port_data *port_data = pci_get_drvdata(dev); | 44 | struct pcie_port_data *port_data = pci_get_drvdata(dev); |
45 | int i, pos, nvec, status = -EINVAL; | 45 | int i, pos, nvec, status = -EINVAL; |
46 | int interrupt_mode = PCIE_PORT_INTx_MODE; | 46 | int interrupt_mode = PCIE_PORT_NO_IRQ; |
47 | 47 | ||
48 | /* Set INTx as default */ | 48 | /* Set INTx as default */ |
49 | for (i = 0, nvec = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) { | 49 | for (i = 0, nvec = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) { |
@@ -51,7 +51,9 @@ static int assign_interrupt_mode(struct pci_dev *dev, int *vectors, int mask) | |||
51 | nvec++; | 51 | nvec++; |
52 | vectors[i] = dev->irq; | 52 | vectors[i] = dev->irq; |
53 | } | 53 | } |
54 | 54 | if (dev->pin) | |
55 | interrupt_mode = PCIE_PORT_INTx_MODE; | ||
56 | |||
55 | /* Check MSI quirk */ | 57 | /* Check MSI quirk */ |
56 | if (port_data->port_type == PCIE_RC_PORT && pcie_mch_quirk) | 58 | if (port_data->port_type == PCIE_RC_PORT && pcie_mch_quirk) |
57 | return interrupt_mode; | 59 | return interrupt_mode; |
@@ -141,7 +143,7 @@ static void pcie_device_init(struct pci_dev *parent, struct pcie_device *dev, | |||
141 | dev->id.vendor = parent->vendor; | 143 | dev->id.vendor = parent->vendor; |
142 | dev->id.device = parent->device; | 144 | dev->id.device = parent->device; |
143 | dev->id.port_type = port_type; | 145 | dev->id.port_type = port_type; |
144 | dev->id.service_type = (1 << service_type); | 146 | dev->id.service_type = service_type; |
145 | 147 | ||
146 | /* Initialize generic device interface */ | 148 | /* Initialize generic device interface */ |
147 | device = &dev->device; | 149 | device = &dev->device; |
@@ -232,19 +234,32 @@ int pcie_port_device_register(struct pci_dev *dev) | |||
232 | /* Allocate child services if any */ | 234 | /* Allocate child services if any */ |
233 | for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) { | 235 | for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) { |
234 | struct pcie_device *child; | 236 | struct pcie_device *child; |
237 | int service = 1 << i; | ||
235 | 238 | ||
236 | if (capabilities & (1 << i)) { | 239 | if (!(capabilities & service)) |
237 | child = alloc_pcie_device(dev, i, vectors[i]); | 240 | continue; |
238 | if (child) { | 241 | |
239 | status = device_register(&child->device); | 242 | /* |
240 | if (status) { | 243 | * Don't use service devices that require interrupts if there is |
241 | kfree(child); | 244 | * no way to generate them. |
242 | continue; | 245 | */ |
243 | } | 246 | if (irq_mode == PCIE_PORT_NO_IRQ |
244 | get_device(&child->device); | 247 | && service != PCIE_PORT_SERVICE_VC) |
245 | } | 248 | continue; |
249 | |||
250 | child = alloc_pcie_device(dev, service, vectors[i]); | ||
251 | if (!child) | ||
252 | continue; | ||
253 | |||
254 | status = device_register(&child->device); | ||
255 | if (status) { | ||
256 | kfree(child); | ||
257 | continue; | ||
246 | } | 258 | } |
259 | |||
260 | get_device(&child->device); | ||
247 | } | 261 | } |
262 | |||
248 | return 0; | 263 | return 0; |
249 | } | 264 | } |
250 | 265 | ||