diff options
Diffstat (limited to 'drivers/pci/pcie')
-rw-r--r-- | drivers/pci/pcie/portdrv_core.c | 77 |
1 files changed, 70 insertions, 7 deletions
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c index 6a9f83ccaff4..8f09b353d2af 100644 --- a/drivers/pci/pcie/portdrv_core.c +++ b/drivers/pci/pcie/portdrv_core.c | |||
@@ -94,12 +94,12 @@ static int pcie_port_resume_service(struct device *dev) | |||
94 | return 0; | 94 | return 0; |
95 | } | 95 | } |
96 | 96 | ||
97 | /* | 97 | /** |
98 | * release_pcie_device | 98 | * release_pcie_device - free PCI Express port service device structure |
99 | * | 99 | * @dev: Port service device to release |
100 | * Being invoked automatically when device is being removed | 100 | * |
101 | * in response to device_unregister(dev) call. | 101 | * Invoked automatically when device is being removed in response to |
102 | * Release all resources being claimed. | 102 | * device_unregister(dev). Release all resources being claimed. |
103 | */ | 103 | */ |
104 | static void release_pcie_device(struct device *dev) | 104 | static void release_pcie_device(struct device *dev) |
105 | { | 105 | { |
@@ -127,7 +127,16 @@ static int is_msi_quirked(struct pci_dev *dev) | |||
127 | } | 127 | } |
128 | return quirk; | 128 | return quirk; |
129 | } | 129 | } |
130 | 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 | */ | ||
131 | static int assign_interrupt_mode(struct pci_dev *dev, int *vectors, int mask) | 140 | static int assign_interrupt_mode(struct pci_dev *dev, int *vectors, int mask) |
132 | { | 141 | { |
133 | int i, pos, nvec, status = -EINVAL; | 142 | int i, pos, nvec, status = -EINVAL; |
@@ -174,6 +183,16 @@ static int assign_interrupt_mode(struct pci_dev *dev, int *vectors, int mask) | |||
174 | return interrupt_mode; | 183 | return interrupt_mode; |
175 | } | 184 | } |
176 | 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 | */ | ||
177 | static int get_port_device_capability(struct pci_dev *dev) | 196 | static int get_port_device_capability(struct pci_dev *dev) |
178 | { | 197 | { |
179 | int services = 0, pos; | 198 | int services = 0, pos; |
@@ -201,6 +220,15 @@ static int get_port_device_capability(struct pci_dev *dev) | |||
201 | return services; | 220 | return services; |
202 | } | 221 | } |
203 | 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 | */ | ||
204 | static void pcie_device_init(struct pci_dev *parent, struct pcie_device *dev, | 232 | static void pcie_device_init(struct pci_dev *parent, struct pcie_device *dev, |
205 | int port_type, int service_type, int irq, int irq_mode) | 233 | int port_type, int service_type, int irq, int irq_mode) |
206 | { | 234 | { |
@@ -226,6 +254,14 @@ static void pcie_device_init(struct pci_dev *parent, struct pcie_device *dev, | |||
226 | device->parent = &parent->dev; | 254 | device->parent = &parent->dev; |
227 | } | 255 | } |
228 | 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 | */ | ||
229 | static struct pcie_device* alloc_pcie_device(struct pci_dev *parent, | 265 | static struct pcie_device* alloc_pcie_device(struct pci_dev *parent, |
230 | int port_type, int service_type, int irq, int irq_mode) | 266 | int port_type, int service_type, int irq, int irq_mode) |
231 | { | 267 | { |
@@ -239,6 +275,10 @@ static struct pcie_device* alloc_pcie_device(struct pci_dev *parent, | |||
239 | return device; | 275 | return device; |
240 | } | 276 | } |
241 | 277 | ||
278 | /** | ||
279 | * pcie_port_device_probe - check if device is a PCI Express port | ||
280 | * @dev: Device to check | ||
281 | */ | ||
242 | int pcie_port_device_probe(struct pci_dev *dev) | 282 | int pcie_port_device_probe(struct pci_dev *dev) |
243 | { | 283 | { |
244 | int pos, type; | 284 | int pos, type; |
@@ -256,6 +296,13 @@ int pcie_port_device_probe(struct pci_dev *dev) | |||
256 | return -ENODEV; | 296 | return -ENODEV; |
257 | } | 297 | } |
258 | 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 | */ | ||
259 | int pcie_port_device_register(struct pci_dev *dev) | 306 | int pcie_port_device_register(struct pci_dev *dev) |
260 | { | 307 | { |
261 | struct pcie_port_device_ext *p_ext; | 308 | struct pcie_port_device_ext *p_ext; |
@@ -319,6 +366,11 @@ static int suspend_iter(struct device *dev, void *data) | |||
319 | return 0; | 366 | return 0; |
320 | } | 367 | } |
321 | 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 | */ | ||
322 | int pcie_port_device_suspend(struct pci_dev *dev, pm_message_t state) | 374 | int pcie_port_device_suspend(struct pci_dev *dev, pm_message_t state) |
323 | { | 375 | { |
324 | return device_for_each_child(&dev->dev, &state, suspend_iter); | 376 | return device_for_each_child(&dev->dev, &state, suspend_iter); |
@@ -337,6 +389,10 @@ static int resume_iter(struct device *dev, void *data) | |||
337 | return 0; | 389 | return 0; |
338 | } | 390 | } |
339 | 391 | ||
392 | /** | ||
393 | * pcie_port_device_suspend - resume port services associated with a PCIe port | ||
394 | * @dev: PCI Express port to handle | ||
395 | */ | ||
340 | int pcie_port_device_resume(struct pci_dev *dev) | 396 | int pcie_port_device_resume(struct pci_dev *dev) |
341 | { | 397 | { |
342 | return device_for_each_child(&dev->dev, NULL, resume_iter); | 398 | return device_for_each_child(&dev->dev, NULL, resume_iter); |
@@ -359,6 +415,13 @@ static int remove_iter(struct device *dev, void *data) | |||
359 | return 0; | 415 | return 0; |
360 | } | 416 | } |
361 | 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 | */ | ||
362 | void pcie_port_device_remove(struct pci_dev *dev) | 425 | void pcie_port_device_remove(struct pci_dev *dev) |
363 | { | 426 | { |
364 | struct device *device; | 427 | struct device *device; |