aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/pcie
diff options
context:
space:
mode:
authorlong <tlnguyen@snoqualmie.dp.intel.com>2005-03-29 16:36:43 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2005-06-20 18:15:26 -0400
commitd0e2b4a0a9dd3eed71b56c47268bf4e40cff6d0f (patch)
tree567d849ed870807599d439e459e1bbe3cfec2877 /drivers/pci/pcie
parent64360322ab3330d4881166380ad43a1eec2f123d (diff)
[PATCH] use device_for_each_child() to properly access child devices.
On Friday, March 25, 2005 8:47 PM Greg KH wrote: >Here's a fix for pci express. For some reason I don't think they are >using the driver model properly here, but I could be wrong... Thanks for making the changes. However, changes in functions: void pcie_port_device_remove(struct pci_dev *dev) and static int remove_iter(struct device *dev, void *data) are not correct. Please use the patch, which is based on kernel 2.6.12-rc1, below for a fix for these. Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/pci/pcie')
-rw-r--r--drivers/pci/pcie/portdrv_core.c139
1 files changed, 65 insertions, 74 deletions
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c
index 576285765e98..f5c5f10a3d2f 100644
--- a/drivers/pci/pcie/portdrv_core.c
+++ b/drivers/pci/pcie/portdrv_core.c
@@ -232,19 +232,16 @@ static void pcie_device_init(struct pci_dev *parent, struct pcie_device *dev,
232 /* Initialize generic device interface */ 232 /* Initialize generic device interface */
233 device = &dev->device; 233 device = &dev->device;
234 memset(device, 0, sizeof(struct device)); 234 memset(device, 0, sizeof(struct device));
235 INIT_LIST_HEAD(&device->node);
236 INIT_LIST_HEAD(&device->children);
237 INIT_LIST_HEAD(&device->bus_list);
238 device->bus = &pcie_port_bus_type; 235 device->bus = &pcie_port_bus_type;
239 device->driver = NULL; 236 device->driver = NULL;
240 device->driver_data = NULL; 237 device->driver_data = NULL;
241 device->release = release_pcie_device; /* callback to free pcie dev */ 238 device->release = release_pcie_device; /* callback to free pcie dev */
242 sprintf(&device->bus_id[0], "pcie%02x", 239 sprintf(&device->bus_id[0], "pcie%02x",
243 get_descriptor_id(port_type, service_type)); 240 get_descriptor_id(port_type, service_type));
244 device->parent = &parent->dev; 241 device->parent = &parent->dev;
245} 242}
246 243
247static struct pcie_device* alloc_pcie_device(struct pci_dev *parent, 244static struct pcie_device* alloc_pcie_device(struct pci_dev *parent,
248 int port_type, int service_type, int irq, int irq_mode) 245 int port_type, int service_type, int irq, int irq_mode)
249{ 246{
250 struct pcie_device *device; 247 struct pcie_device *device;
@@ -270,9 +267,9 @@ int pcie_port_device_probe(struct pci_dev *dev)
270 pci_read_config_word(dev, pos + PCIE_CAPABILITIES_REG, &reg); 267 pci_read_config_word(dev, pos + PCIE_CAPABILITIES_REG, &reg);
271 type = (reg >> 4) & PORT_TYPE_MASK; 268 type = (reg >> 4) & PORT_TYPE_MASK;
272 if ( type == PCIE_RC_PORT || type == PCIE_SW_UPSTREAM_PORT || 269 if ( type == PCIE_RC_PORT || type == PCIE_SW_UPSTREAM_PORT ||
273 type == PCIE_SW_DOWNSTREAM_PORT ) 270 type == PCIE_SW_DOWNSTREAM_PORT )
274 return 0; 271 return 0;
275 272
276 return -ENODEV; 273 return -ENODEV;
277} 274}
278 275
@@ -283,8 +280,8 @@ int pcie_port_device_register(struct pci_dev *dev)
283 u16 reg16; 280 u16 reg16;
284 281
285 /* Get port type */ 282 /* Get port type */
286 pci_read_config_word(dev, 283 pci_read_config_word(dev,
287 pci_find_capability(dev, PCI_CAP_ID_EXP) + 284 pci_find_capability(dev, PCI_CAP_ID_EXP) +
288 PCIE_CAPABILITIES_REG, &reg16); 285 PCIE_CAPABILITIES_REG, &reg16);
289 type = (reg16 >> 4) & PORT_TYPE_MASK; 286 type = (reg16 >> 4) & PORT_TYPE_MASK;
290 287
@@ -299,11 +296,11 @@ int pcie_port_device_register(struct pci_dev *dev)
299 if (capabilities & (1 << i)) { 296 if (capabilities & (1 << i)) {
300 child = alloc_pcie_device( 297 child = alloc_pcie_device(
301 dev, /* parent */ 298 dev, /* parent */
302 type, /* port type */ 299 type, /* port type */
303 i, /* service type */ 300 i, /* service type */
304 vectors[i], /* irq */ 301 vectors[i], /* irq */
305 irq_mode /* interrupt mode */); 302 irq_mode /* interrupt mode */);
306 if (child) { 303 if (child) {
307 status = device_register(&child->device); 304 status = device_register(&child->device);
308 if (status) { 305 if (status) {
309 kfree(child); 306 kfree(child);
@@ -317,84 +314,78 @@ int pcie_port_device_register(struct pci_dev *dev)
317} 314}
318 315
319#ifdef CONFIG_PM 316#ifdef CONFIG_PM
320int pcie_port_device_suspend(struct pci_dev *dev, pm_message_t state) 317static int suspend_iter(struct device *dev, void *data)
321{ 318{
322 struct list_head *head, *tmp;
323 struct device *parent, *child;
324 struct device_driver *driver;
325 struct pcie_port_service_driver *service_driver; 319 struct pcie_port_service_driver *service_driver;
320 u32 state = (u32)data;
321
322 if ((dev->bus == &pcie_port_bus_type) &&
323 (dev->driver)) {
324 service_driver = to_service_driver(dev->driver);
325 if (service_driver->suspend)
326 service_driver->suspend(to_pcie_device(dev), state);
327 }
328 return 0;
329}
326 330
327 parent = &dev->dev; 331int pcie_port_device_suspend(struct pci_dev *dev, u32 state)
328 head = &parent->children; 332{
329 tmp = head->next; 333 device_for_each_child(&dev->dev, (void *)state, suspend_iter);
330 while (head != tmp) { 334 return 0;
331 child = container_of(tmp, struct device, node);
332 tmp = tmp->next;
333 if (child->bus != &pcie_port_bus_type)
334 continue;
335 driver = child->driver;
336 if (!driver)
337 continue;
338 service_driver = to_service_driver(driver);
339 if (service_driver->suspend)
340 service_driver->suspend(to_pcie_device(child), state);
341 }
342 return 0;
343} 335}
344 336
345int pcie_port_device_resume(struct pci_dev *dev) 337static int resume_iter(struct device *dev, void *data)
346{ 338{
347 struct list_head *head, *tmp;
348 struct device *parent, *child;
349 struct device_driver *driver;
350 struct pcie_port_service_driver *service_driver; 339 struct pcie_port_service_driver *service_driver;
351 340
352 parent = &dev->dev; 341 if ((dev->bus == &pcie_port_bus_type) &&
353 head = &parent->children; 342 (dev->driver)) {
354 tmp = head->next; 343 service_driver = to_service_driver(dev->driver);
355 while (head != tmp) { 344 if (service_driver->resume)
356 child = container_of(tmp, struct device, node); 345 service_driver->resume(to_pcie_device(dev));
357 tmp = tmp->next;
358 if (child->bus != &pcie_port_bus_type)
359 continue;
360 driver = child->driver;
361 if (!driver)
362 continue;
363 service_driver = to_service_driver(driver);
364 if (service_driver->resume)
365 service_driver->resume(to_pcie_device(child));
366 } 346 }
367 return 0; 347 return 0;
348}
368 349
350int pcie_port_device_resume(struct pci_dev *dev)
351{
352 device_for_each_child(&dev->dev, NULL, resume_iter);
353 return 0;
369} 354}
370#endif 355#endif
371 356
372void pcie_port_device_remove(struct pci_dev *dev) 357static int remove_iter(struct device *dev, void *data)
373{ 358{
374 struct list_head *head, *tmp;
375 struct device *parent, *child;
376 struct device_driver *driver;
377 struct pcie_port_service_driver *service_driver; 359 struct pcie_port_service_driver *service_driver;
378 int interrupt_mode = PCIE_PORT_INTx_MODE;
379 360
380 parent = &dev->dev; 361 if (dev->bus == &pcie_port_bus_type) {
381 head = &parent->children; 362 if (dev->driver) {
382 tmp = head->next; 363 service_driver = to_service_driver(dev->driver);
383 while (head != tmp) { 364 if (service_driver->remove)
384 child = container_of(tmp, struct device, node); 365 service_driver->remove(to_pcie_device(dev));
385 tmp = tmp->next;
386 if (child->bus != &pcie_port_bus_type)
387 continue;
388 driver = child->driver;
389 if (driver) {
390 service_driver = to_service_driver(driver);
391 if (service_driver->remove)
392 service_driver->remove(to_pcie_device(child));
393 } 366 }
394 interrupt_mode = (to_pcie_device(child))->interrupt_mode; 367 *(unsigned long*)data = (unsigned long)dev;
395 put_device(child); 368 return 1;
396 device_unregister(child);
397 } 369 }
370 return 0;
371}
372
373void pcie_port_device_remove(struct pci_dev *dev)
374{
375 struct device *device;
376 unsigned long device_addr;
377 int interrupt_mode = PCIE_PORT_INTx_MODE;
378 int status;
379
380 do {
381 status = device_for_each_child(&dev->dev, &device_addr, remove_iter);
382 if (status) {
383 device = (struct device*)device_addr;
384 interrupt_mode = (to_pcie_device(device))->interrupt_mode;
385 put_device(device);
386 device_unregister(device);
387 }
388 } while (status);
398 /* Switch to INTx by default if MSI enabled */ 389 /* Switch to INTx by default if MSI enabled */
399 if (interrupt_mode == PCIE_PORT_MSIX_MODE) 390 if (interrupt_mode == PCIE_PORT_MSIX_MODE)
400 pci_disable_msix(dev); 391 pci_disable_msix(dev);
@@ -423,7 +414,7 @@ int pcie_port_service_register(struct pcie_port_service_driver *new)
423 new->driver.resume = pcie_port_resume_service; 414 new->driver.resume = pcie_port_resume_service;
424 415
425 return driver_register(&new->driver); 416 return driver_register(&new->driver);
426} 417}
427 418
428void pcie_port_service_unregister(struct pcie_port_service_driver *new) 419void pcie_port_service_unregister(struct pcie_port_service_driver *new)
429{ 420{