diff options
Diffstat (limited to 'drivers')
54 files changed, 851 insertions, 629 deletions
diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 12173d16bea7..7d8a7ce73fb3 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c | |||
@@ -372,19 +372,30 @@ int bus_add_device(struct device * dev) | |||
372 | pr_debug("bus %s: add device %s\n", bus->name, dev->bus_id); | 372 | pr_debug("bus %s: add device %s\n", bus->name, dev->bus_id); |
373 | error = device_add_attrs(bus, dev); | 373 | error = device_add_attrs(bus, dev); |
374 | if (error) | 374 | if (error) |
375 | goto out; | 375 | goto out_put; |
376 | error = sysfs_create_link(&bus->devices.kobj, | 376 | error = sysfs_create_link(&bus->devices.kobj, |
377 | &dev->kobj, dev->bus_id); | 377 | &dev->kobj, dev->bus_id); |
378 | if (error) | 378 | if (error) |
379 | goto out; | 379 | goto out_id; |
380 | error = sysfs_create_link(&dev->kobj, | 380 | error = sysfs_create_link(&dev->kobj, |
381 | &dev->bus->subsys.kset.kobj, "subsystem"); | 381 | &dev->bus->subsys.kset.kobj, "subsystem"); |
382 | if (error) | 382 | if (error) |
383 | goto out; | 383 | goto out_subsys; |
384 | error = sysfs_create_link(&dev->kobj, | 384 | error = sysfs_create_link(&dev->kobj, |
385 | &dev->bus->subsys.kset.kobj, "bus"); | 385 | &dev->bus->subsys.kset.kobj, "bus"); |
386 | if (error) | ||
387 | goto out_deprecated; | ||
386 | } | 388 | } |
387 | out: | 389 | return 0; |
390 | |||
391 | out_deprecated: | ||
392 | sysfs_remove_link(&dev->kobj, "subsystem"); | ||
393 | out_subsys: | ||
394 | sysfs_remove_link(&bus->devices.kobj, dev->bus_id); | ||
395 | out_id: | ||
396 | device_remove_attrs(bus, dev); | ||
397 | out_put: | ||
398 | put_bus(dev->bus); | ||
388 | return error; | 399 | return error; |
389 | } | 400 | } |
390 | 401 | ||
@@ -428,8 +439,10 @@ void bus_remove_device(struct device * dev) | |||
428 | sysfs_remove_link(&dev->kobj, "bus"); | 439 | sysfs_remove_link(&dev->kobj, "bus"); |
429 | sysfs_remove_link(&dev->bus->devices.kobj, dev->bus_id); | 440 | sysfs_remove_link(&dev->bus->devices.kobj, dev->bus_id); |
430 | device_remove_attrs(dev->bus, dev); | 441 | device_remove_attrs(dev->bus, dev); |
431 | dev->is_registered = 0; | 442 | if (dev->is_registered) { |
432 | klist_del(&dev->knode_bus); | 443 | dev->is_registered = 0; |
444 | klist_del(&dev->knode_bus); | ||
445 | } | ||
433 | pr_debug("bus %s: remove device %s\n", dev->bus->name, dev->bus_id); | 446 | pr_debug("bus %s: remove device %s\n", dev->bus->name, dev->bus_id); |
434 | device_release_driver(dev); | 447 | device_release_driver(dev); |
435 | put_bus(dev->bus); | 448 | put_bus(dev->bus); |
@@ -505,34 +518,36 @@ int bus_add_driver(struct device_driver *drv) | |||
505 | struct bus_type * bus = get_bus(drv->bus); | 518 | struct bus_type * bus = get_bus(drv->bus); |
506 | int error = 0; | 519 | int error = 0; |
507 | 520 | ||
508 | if (bus) { | 521 | if (!bus) |
509 | pr_debug("bus %s: add driver %s\n", bus->name, drv->name); | 522 | return 0; |
510 | error = kobject_set_name(&drv->kobj, "%s", drv->name); | 523 | |
511 | if (error) | 524 | pr_debug("bus %s: add driver %s\n", bus->name, drv->name); |
512 | goto out_put_bus; | 525 | error = kobject_set_name(&drv->kobj, "%s", drv->name); |
513 | drv->kobj.kset = &bus->drivers; | 526 | if (error) |
514 | if ((error = kobject_register(&drv->kobj))) | 527 | goto out_put_bus; |
515 | goto out_put_bus; | 528 | drv->kobj.kset = &bus->drivers; |
516 | 529 | if ((error = kobject_register(&drv->kobj))) | |
517 | error = driver_attach(drv); | 530 | goto out_put_bus; |
518 | if (error) | 531 | |
519 | goto out_unregister; | 532 | error = driver_attach(drv); |
520 | klist_add_tail(&drv->knode_bus, &bus->klist_drivers); | 533 | if (error) |
521 | module_add_driver(drv->owner, drv); | 534 | goto out_unregister; |
522 | 535 | klist_add_tail(&drv->knode_bus, &bus->klist_drivers); | |
523 | error = driver_add_attrs(bus, drv); | 536 | module_add_driver(drv->owner, drv); |
524 | if (error) { | 537 | |
525 | /* How the hell do we get out of this pickle? Give up */ | 538 | error = driver_add_attrs(bus, drv); |
526 | printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n", | 539 | if (error) { |
527 | __FUNCTION__, drv->name); | 540 | /* How the hell do we get out of this pickle? Give up */ |
528 | } | 541 | printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n", |
529 | error = add_bind_files(drv); | 542 | __FUNCTION__, drv->name); |
530 | if (error) { | ||
531 | /* Ditto */ | ||
532 | printk(KERN_ERR "%s: add_bind_files(%s) failed\n", | ||
533 | __FUNCTION__, drv->name); | ||
534 | } | ||
535 | } | 543 | } |
544 | error = add_bind_files(drv); | ||
545 | if (error) { | ||
546 | /* Ditto */ | ||
547 | printk(KERN_ERR "%s: add_bind_files(%s) failed\n", | ||
548 | __FUNCTION__, drv->name); | ||
549 | } | ||
550 | |||
536 | return error; | 551 | return error; |
537 | out_unregister: | 552 | out_unregister: |
538 | kobject_unregister(&drv->kobj); | 553 | kobject_unregister(&drv->kobj); |
@@ -552,16 +567,17 @@ out_put_bus: | |||
552 | 567 | ||
553 | void bus_remove_driver(struct device_driver * drv) | 568 | void bus_remove_driver(struct device_driver * drv) |
554 | { | 569 | { |
555 | if (drv->bus) { | 570 | if (!drv->bus) |
556 | remove_bind_files(drv); | 571 | return; |
557 | driver_remove_attrs(drv->bus, drv); | 572 | |
558 | klist_remove(&drv->knode_bus); | 573 | remove_bind_files(drv); |
559 | pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name); | 574 | driver_remove_attrs(drv->bus, drv); |
560 | driver_detach(drv); | 575 | klist_remove(&drv->knode_bus); |
561 | module_remove_driver(drv); | 576 | pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name); |
562 | kobject_unregister(&drv->kobj); | 577 | driver_detach(drv); |
563 | put_bus(drv->bus); | 578 | module_remove_driver(drv); |
564 | } | 579 | kobject_unregister(&drv->kobj); |
580 | put_bus(drv->bus); | ||
565 | } | 581 | } |
566 | 582 | ||
567 | 583 | ||
@@ -732,11 +748,15 @@ int bus_register(struct bus_type * bus) | |||
732 | 748 | ||
733 | klist_init(&bus->klist_devices, klist_devices_get, klist_devices_put); | 749 | klist_init(&bus->klist_devices, klist_devices_get, klist_devices_put); |
734 | klist_init(&bus->klist_drivers, NULL, NULL); | 750 | klist_init(&bus->klist_drivers, NULL, NULL); |
735 | bus_add_attrs(bus); | 751 | retval = bus_add_attrs(bus); |
752 | if (retval) | ||
753 | goto bus_attrs_fail; | ||
736 | 754 | ||
737 | pr_debug("bus type '%s' registered\n", bus->name); | 755 | pr_debug("bus type '%s' registered\n", bus->name); |
738 | return 0; | 756 | return 0; |
739 | 757 | ||
758 | bus_attrs_fail: | ||
759 | kset_unregister(&bus->drivers); | ||
740 | bus_drivers_fail: | 760 | bus_drivers_fail: |
741 | kset_unregister(&bus->devices); | 761 | kset_unregister(&bus->devices); |
742 | bus_devices_fail: | 762 | bus_devices_fail: |
diff --git a/drivers/base/class.c b/drivers/base/class.c index b32b77ff2dcd..0ff267a248db 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c | |||
@@ -562,7 +562,10 @@ int class_device_add(struct class_device *class_dev) | |||
562 | goto out2; | 562 | goto out2; |
563 | 563 | ||
564 | /* add the needed attributes to this device */ | 564 | /* add the needed attributes to this device */ |
565 | sysfs_create_link(&class_dev->kobj, &parent_class->subsys.kset.kobj, "subsystem"); | 565 | error = sysfs_create_link(&class_dev->kobj, |
566 | &parent_class->subsys.kset.kobj, "subsystem"); | ||
567 | if (error) | ||
568 | goto out3; | ||
566 | class_dev->uevent_attr.attr.name = "uevent"; | 569 | class_dev->uevent_attr.attr.name = "uevent"; |
567 | class_dev->uevent_attr.attr.mode = S_IWUSR; | 570 | class_dev->uevent_attr.attr.mode = S_IWUSR; |
568 | class_dev->uevent_attr.attr.owner = parent_class->owner; | 571 | class_dev->uevent_attr.attr.owner = parent_class->owner; |
diff --git a/drivers/base/core.c b/drivers/base/core.c index b224bb43ff63..68ad11af22b4 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
@@ -44,7 +44,7 @@ const char *dev_driver_string(struct device *dev) | |||
44 | return dev->driver ? dev->driver->name : | 44 | return dev->driver ? dev->driver->name : |
45 | (dev->bus ? dev->bus->name : ""); | 45 | (dev->bus ? dev->bus->name : ""); |
46 | } | 46 | } |
47 | EXPORT_SYMBOL_GPL(dev_driver_string); | 47 | EXPORT_SYMBOL(dev_driver_string); |
48 | 48 | ||
49 | #define to_dev(obj) container_of(obj, struct device, kobj) | 49 | #define to_dev(obj) container_of(obj, struct device, kobj) |
50 | #define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr) | 50 | #define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr) |
@@ -433,14 +433,16 @@ int device_add(struct device *dev) | |||
433 | if (dev->driver) | 433 | if (dev->driver) |
434 | dev->uevent_attr.attr.owner = dev->driver->owner; | 434 | dev->uevent_attr.attr.owner = dev->driver->owner; |
435 | dev->uevent_attr.store = store_uevent; | 435 | dev->uevent_attr.store = store_uevent; |
436 | device_create_file(dev, &dev->uevent_attr); | 436 | error = device_create_file(dev, &dev->uevent_attr); |
437 | if (error) | ||
438 | goto attrError; | ||
437 | 439 | ||
438 | if (MAJOR(dev->devt)) { | 440 | if (MAJOR(dev->devt)) { |
439 | struct device_attribute *attr; | 441 | struct device_attribute *attr; |
440 | attr = kzalloc(sizeof(*attr), GFP_KERNEL); | 442 | attr = kzalloc(sizeof(*attr), GFP_KERNEL); |
441 | if (!attr) { | 443 | if (!attr) { |
442 | error = -ENOMEM; | 444 | error = -ENOMEM; |
443 | goto PMError; | 445 | goto ueventattrError; |
444 | } | 446 | } |
445 | attr->attr.name = "dev"; | 447 | attr->attr.name = "dev"; |
446 | attr->attr.mode = S_IRUGO; | 448 | attr->attr.mode = S_IRUGO; |
@@ -450,7 +452,7 @@ int device_add(struct device *dev) | |||
450 | error = device_create_file(dev, attr); | 452 | error = device_create_file(dev, attr); |
451 | if (error) { | 453 | if (error) { |
452 | kfree(attr); | 454 | kfree(attr); |
453 | goto attrError; | 455 | goto ueventattrError; |
454 | } | 456 | } |
455 | 457 | ||
456 | dev->devt_attr = attr; | 458 | dev->devt_attr = attr; |
@@ -477,7 +479,8 @@ int device_add(struct device *dev) | |||
477 | if ((error = bus_add_device(dev))) | 479 | if ((error = bus_add_device(dev))) |
478 | goto BusError; | 480 | goto BusError; |
479 | kobject_uevent(&dev->kobj, KOBJ_ADD); | 481 | kobject_uevent(&dev->kobj, KOBJ_ADD); |
480 | bus_attach_device(dev); | 482 | if ((error = bus_attach_device(dev))) |
483 | goto AttachError; | ||
481 | if (parent) | 484 | if (parent) |
482 | klist_add_tail(&dev->knode_parent, &parent->klist_children); | 485 | klist_add_tail(&dev->knode_parent, &parent->klist_children); |
483 | 486 | ||
@@ -496,6 +499,8 @@ int device_add(struct device *dev) | |||
496 | kfree(class_name); | 499 | kfree(class_name); |
497 | put_device(dev); | 500 | put_device(dev); |
498 | return error; | 501 | return error; |
502 | AttachError: | ||
503 | bus_remove_device(dev); | ||
499 | BusError: | 504 | BusError: |
500 | device_pm_remove(dev); | 505 | device_pm_remove(dev); |
501 | PMError: | 506 | PMError: |
@@ -507,6 +512,8 @@ int device_add(struct device *dev) | |||
507 | device_remove_file(dev, dev->devt_attr); | 512 | device_remove_file(dev, dev->devt_attr); |
508 | kfree(dev->devt_attr); | 513 | kfree(dev->devt_attr); |
509 | } | 514 | } |
515 | ueventattrError: | ||
516 | device_remove_file(dev, &dev->uevent_attr); | ||
510 | attrError: | 517 | attrError: |
511 | kobject_uevent(&dev->kobj, KOBJ_REMOVE); | 518 | kobject_uevent(&dev->kobj, KOBJ_REMOVE); |
512 | kobject_del(&dev->kobj); | 519 | kobject_del(&dev->kobj); |
@@ -805,8 +812,10 @@ int device_rename(struct device *dev, char *new_name) | |||
805 | 812 | ||
806 | if (dev->class) { | 813 | if (dev->class) { |
807 | old_symlink_name = kmalloc(BUS_ID_SIZE, GFP_KERNEL); | 814 | old_symlink_name = kmalloc(BUS_ID_SIZE, GFP_KERNEL); |
808 | if (!old_symlink_name) | 815 | if (!old_symlink_name) { |
809 | return -ENOMEM; | 816 | error = -ENOMEM; |
817 | goto out_free_old_class; | ||
818 | } | ||
810 | strlcpy(old_symlink_name, dev->bus_id, BUS_ID_SIZE); | 819 | strlcpy(old_symlink_name, dev->bus_id, BUS_ID_SIZE); |
811 | } | 820 | } |
812 | 821 | ||
@@ -830,9 +839,10 @@ int device_rename(struct device *dev, char *new_name) | |||
830 | } | 839 | } |
831 | put_device(dev); | 840 | put_device(dev); |
832 | 841 | ||
833 | kfree(old_class_name); | ||
834 | kfree(new_class_name); | 842 | kfree(new_class_name); |
835 | kfree(old_symlink_name); | 843 | kfree(old_symlink_name); |
844 | out_free_old_class: | ||
845 | kfree(old_class_name); | ||
836 | 846 | ||
837 | return error; | 847 | return error; |
838 | } | 848 | } |
diff --git a/drivers/base/dd.c b/drivers/base/dd.c index b5f43c3e44fa..db01b95a47a5 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c | |||
@@ -171,6 +171,8 @@ int driver_probe_device(struct device_driver * drv, struct device * dev) | |||
171 | drv->bus->name, dev->bus_id, drv->name); | 171 | drv->bus->name, dev->bus_id, drv->name); |
172 | 172 | ||
173 | data = kmalloc(sizeof(*data), GFP_KERNEL); | 173 | data = kmalloc(sizeof(*data), GFP_KERNEL); |
174 | if (!data) | ||
175 | return -ENOMEM; | ||
174 | data->drv = drv; | 176 | data->drv = drv; |
175 | data->dev = dev; | 177 | data->dev = dev; |
176 | 178 | ||
@@ -178,7 +180,7 @@ int driver_probe_device(struct device_driver * drv, struct device * dev) | |||
178 | probe_task = kthread_run(really_probe, data, | 180 | probe_task = kthread_run(really_probe, data, |
179 | "probe-%s", dev->bus_id); | 181 | "probe-%s", dev->bus_id); |
180 | if (IS_ERR(probe_task)) | 182 | if (IS_ERR(probe_task)) |
181 | ret = PTR_ERR(probe_task); | 183 | ret = really_probe(data); |
182 | } else | 184 | } else |
183 | ret = really_probe(data); | 185 | ret = really_probe(data); |
184 | 186 | ||
diff --git a/drivers/base/dmapool.c b/drivers/base/dmapool.c index 33c5cce1560b..b2efbd4cf710 100644 --- a/drivers/base/dmapool.c +++ b/drivers/base/dmapool.c | |||
@@ -141,11 +141,20 @@ dma_pool_create (const char *name, struct device *dev, | |||
141 | init_waitqueue_head (&retval->waitq); | 141 | init_waitqueue_head (&retval->waitq); |
142 | 142 | ||
143 | if (dev) { | 143 | if (dev) { |
144 | int ret; | ||
145 | |||
144 | down (&pools_lock); | 146 | down (&pools_lock); |
145 | if (list_empty (&dev->dma_pools)) | 147 | if (list_empty (&dev->dma_pools)) |
146 | device_create_file (dev, &dev_attr_pools); | 148 | ret = device_create_file (dev, &dev_attr_pools); |
149 | else | ||
150 | ret = 0; | ||
147 | /* note: not currently insisting "name" be unique */ | 151 | /* note: not currently insisting "name" be unique */ |
148 | list_add (&retval->pools, &dev->dma_pools); | 152 | if (!ret) |
153 | list_add (&retval->pools, &dev->dma_pools); | ||
154 | else { | ||
155 | kfree(retval); | ||
156 | retval = NULL; | ||
157 | } | ||
149 | up (&pools_lock); | 158 | up (&pools_lock); |
150 | } else | 159 | } else |
151 | INIT_LIST_HEAD (&retval->pools); | 160 | INIT_LIST_HEAD (&retval->pools); |
diff --git a/drivers/base/topology.c b/drivers/base/topology.c index 3ef9d514b916..28dccb730af9 100644 --- a/drivers/base/topology.c +++ b/drivers/base/topology.c | |||
@@ -97,8 +97,7 @@ static struct attribute_group topology_attr_group = { | |||
97 | /* Add/Remove cpu_topology interface for CPU device */ | 97 | /* Add/Remove cpu_topology interface for CPU device */ |
98 | static int __cpuinit topology_add_dev(struct sys_device * sys_dev) | 98 | static int __cpuinit topology_add_dev(struct sys_device * sys_dev) |
99 | { | 99 | { |
100 | sysfs_create_group(&sys_dev->kobj, &topology_attr_group); | 100 | return sysfs_create_group(&sys_dev->kobj, &topology_attr_group); |
101 | return 0; | ||
102 | } | 101 | } |
103 | 102 | ||
104 | static int __cpuinit topology_remove_dev(struct sys_device * sys_dev) | 103 | static int __cpuinit topology_remove_dev(struct sys_device * sys_dev) |
diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index 6eebcb7be97e..6d111228cfac 100644 --- a/drivers/block/aoe/aoe.h +++ b/drivers/block/aoe/aoe.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */ | 1 | /* Copyright (c) 2006 Coraid, Inc. See COPYING for GPL terms. */ |
2 | #define VERSION "22" | 2 | #define VERSION "32" |
3 | #define AOE_MAJOR 152 | 3 | #define AOE_MAJOR 152 |
4 | #define DEVICE_NAME "aoe" | 4 | #define DEVICE_NAME "aoe" |
5 | 5 | ||
@@ -65,7 +65,7 @@ struct aoe_atahdr { | |||
65 | struct aoe_cfghdr { | 65 | struct aoe_cfghdr { |
66 | __be16 bufcnt; | 66 | __be16 bufcnt; |
67 | __be16 fwver; | 67 | __be16 fwver; |
68 | unsigned char res; | 68 | unsigned char scnt; |
69 | unsigned char aoeccmd; | 69 | unsigned char aoeccmd; |
70 | unsigned char cslen[2]; | 70 | unsigned char cslen[2]; |
71 | }; | 71 | }; |
@@ -78,12 +78,14 @@ enum { | |||
78 | DEVFL_GDALLOC = (1<<4), /* need to alloc gendisk */ | 78 | DEVFL_GDALLOC = (1<<4), /* need to alloc gendisk */ |
79 | DEVFL_PAUSE = (1<<5), | 79 | DEVFL_PAUSE = (1<<5), |
80 | DEVFL_NEWSIZE = (1<<6), /* need to update dev size in block layer */ | 80 | DEVFL_NEWSIZE = (1<<6), /* need to update dev size in block layer */ |
81 | DEVFL_MAXBCNT = (1<<7), /* d->maxbcnt is not changeable */ | ||
82 | DEVFL_KICKME = (1<<8), | ||
81 | 83 | ||
82 | BUFFL_FAIL = 1, | 84 | BUFFL_FAIL = 1, |
83 | }; | 85 | }; |
84 | 86 | ||
85 | enum { | 87 | enum { |
86 | MAXATADATA = 1024, | 88 | DEFAULTBCNT = 2 * 512, /* 2 sectors */ |
87 | NPERSHELF = 16, /* number of slots per shelf address */ | 89 | NPERSHELF = 16, /* number of slots per shelf address */ |
88 | FREETAG = -1, | 90 | FREETAG = -1, |
89 | MIN_BUFS = 8, | 91 | MIN_BUFS = 8, |
@@ -107,11 +109,9 @@ struct frame { | |||
107 | ulong waited; | 109 | ulong waited; |
108 | struct buf *buf; | 110 | struct buf *buf; |
109 | char *bufaddr; | 111 | char *bufaddr; |
110 | int writedatalen; | 112 | ulong bcnt; |
111 | int ndata; | 113 | sector_t lba; |
112 | 114 | struct sk_buff *skb; | |
113 | /* largest possible */ | ||
114 | unsigned char data[sizeof(struct aoe_hdr) + sizeof(struct aoe_atahdr)]; | ||
115 | }; | 115 | }; |
116 | 116 | ||
117 | struct aoedev { | 117 | struct aoedev { |
@@ -121,9 +121,12 @@ struct aoedev { | |||
121 | ulong sysminor; | 121 | ulong sysminor; |
122 | ulong aoemajor; | 122 | ulong aoemajor; |
123 | ulong aoeminor; | 123 | ulong aoeminor; |
124 | ulong nopen; /* (bd_openers isn't available without sleeping) */ | 124 | u16 nopen; /* (bd_openers isn't available without sleeping) */ |
125 | ulong rttavg; /* round trip average of requests/responses */ | 125 | u16 lasttag; /* last tag sent */ |
126 | u16 rttavg; /* round trip average of requests/responses */ | ||
127 | u16 mintimer; | ||
126 | u16 fw_ver; /* version of blade's firmware */ | 128 | u16 fw_ver; /* version of blade's firmware */ |
129 | u16 maxbcnt; | ||
127 | struct work_struct work;/* disk create work struct */ | 130 | struct work_struct work;/* disk create work struct */ |
128 | struct gendisk *gd; | 131 | struct gendisk *gd; |
129 | request_queue_t blkq; | 132 | request_queue_t blkq; |
@@ -137,8 +140,8 @@ struct aoedev { | |||
137 | mempool_t *bufpool; /* for deadlock-free Buf allocation */ | 140 | mempool_t *bufpool; /* for deadlock-free Buf allocation */ |
138 | struct list_head bufq; /* queue of bios to work on */ | 141 | struct list_head bufq; /* queue of bios to work on */ |
139 | struct buf *inprocess; /* the one we're currently working on */ | 142 | struct buf *inprocess; /* the one we're currently working on */ |
140 | ulong lasttag; /* last tag sent */ | 143 | ushort lostjumbo; |
141 | ulong nframes; /* number of frames below */ | 144 | ushort nframes; /* number of frames below */ |
142 | struct frame *frames; | 145 | struct frame *frames; |
143 | }; | 146 | }; |
144 | 147 | ||
@@ -157,6 +160,7 @@ void aoecmd_cfg(ushort aoemajor, unsigned char aoeminor); | |||
157 | void aoecmd_ata_rsp(struct sk_buff *); | 160 | void aoecmd_ata_rsp(struct sk_buff *); |
158 | void aoecmd_cfg_rsp(struct sk_buff *); | 161 | void aoecmd_cfg_rsp(struct sk_buff *); |
159 | void aoecmd_sleepwork(void *vp); | 162 | void aoecmd_sleepwork(void *vp); |
163 | struct sk_buff *new_skb(ulong); | ||
160 | 164 | ||
161 | int aoedev_init(void); | 165 | int aoedev_init(void); |
162 | void aoedev_exit(void); | 166 | void aoedev_exit(void); |
diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c index 393b86a3dbf8..d433f27e0ce2 100644 --- a/drivers/block/aoe/aoeblk.c +++ b/drivers/block/aoe/aoeblk.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */ | 1 | /* Copyright (c) 2006 Coraid, Inc. See COPYING for GPL terms. */ |
2 | /* | 2 | /* |
3 | * aoeblk.c | 3 | * aoeblk.c |
4 | * block device routines | 4 | * block device routines |
@@ -14,7 +14,6 @@ | |||
14 | 14 | ||
15 | static kmem_cache_t *buf_pool_cache; | 15 | static kmem_cache_t *buf_pool_cache; |
16 | 16 | ||
17 | /* add attributes for our block devices in sysfs */ | ||
18 | static ssize_t aoedisk_show_state(struct gendisk * disk, char *page) | 17 | static ssize_t aoedisk_show_state(struct gendisk * disk, char *page) |
19 | { | 18 | { |
20 | struct aoedev *d = disk->private_data; | 19 | struct aoedev *d = disk->private_data; |
@@ -64,21 +63,26 @@ static struct disk_attribute disk_attr_fwver = { | |||
64 | .show = aoedisk_show_fwver | 63 | .show = aoedisk_show_fwver |
65 | }; | 64 | }; |
66 | 65 | ||
67 | static void | 66 | static struct attribute *aoe_attrs[] = { |
67 | &disk_attr_state.attr, | ||
68 | &disk_attr_mac.attr, | ||
69 | &disk_attr_netif.attr, | ||
70 | &disk_attr_fwver.attr, | ||
71 | }; | ||
72 | |||
73 | static const struct attribute_group attr_group = { | ||
74 | .attrs = aoe_attrs, | ||
75 | }; | ||
76 | |||
77 | static int | ||
68 | aoedisk_add_sysfs(struct aoedev *d) | 78 | aoedisk_add_sysfs(struct aoedev *d) |
69 | { | 79 | { |
70 | sysfs_create_file(&d->gd->kobj, &disk_attr_state.attr); | 80 | return sysfs_create_group(&d->gd->kobj, &attr_group); |
71 | sysfs_create_file(&d->gd->kobj, &disk_attr_mac.attr); | ||
72 | sysfs_create_file(&d->gd->kobj, &disk_attr_netif.attr); | ||
73 | sysfs_create_file(&d->gd->kobj, &disk_attr_fwver.attr); | ||
74 | } | 81 | } |
75 | void | 82 | void |
76 | aoedisk_rm_sysfs(struct aoedev *d) | 83 | aoedisk_rm_sysfs(struct aoedev *d) |
77 | { | 84 | { |
78 | sysfs_remove_link(&d->gd->kobj, "state"); | 85 | sysfs_remove_group(&d->gd->kobj, &attr_group); |
79 | sysfs_remove_link(&d->gd->kobj, "mac"); | ||
80 | sysfs_remove_link(&d->gd->kobj, "netif"); | ||
81 | sysfs_remove_link(&d->gd->kobj, "firmware-version"); | ||
82 | } | 86 | } |
83 | 87 | ||
84 | static int | 88 | static int |
@@ -132,8 +136,7 @@ aoeblk_make_request(request_queue_t *q, struct bio *bio) | |||
132 | d = bio->bi_bdev->bd_disk->private_data; | 136 | d = bio->bi_bdev->bd_disk->private_data; |
133 | buf = mempool_alloc(d->bufpool, GFP_NOIO); | 137 | buf = mempool_alloc(d->bufpool, GFP_NOIO); |
134 | if (buf == NULL) { | 138 | if (buf == NULL) { |
135 | printk(KERN_INFO "aoe: aoeblk_make_request: buf allocation " | 139 | printk(KERN_INFO "aoe: buf allocation failure\n"); |
136 | "failure\n"); | ||
137 | bio_endio(bio, bio->bi_size, -ENOMEM); | 140 | bio_endio(bio, bio->bi_size, -ENOMEM); |
138 | return 0; | 141 | return 0; |
139 | } | 142 | } |
@@ -143,14 +146,15 @@ aoeblk_make_request(request_queue_t *q, struct bio *bio) | |||
143 | buf->bio = bio; | 146 | buf->bio = bio; |
144 | buf->resid = bio->bi_size; | 147 | buf->resid = bio->bi_size; |
145 | buf->sector = bio->bi_sector; | 148 | buf->sector = bio->bi_sector; |
146 | buf->bv = buf->bio->bi_io_vec; | 149 | buf->bv = &bio->bi_io_vec[bio->bi_idx]; |
150 | WARN_ON(buf->bv->bv_len == 0); | ||
147 | buf->bv_resid = buf->bv->bv_len; | 151 | buf->bv_resid = buf->bv->bv_len; |
148 | buf->bufaddr = page_address(buf->bv->bv_page) + buf->bv->bv_offset; | 152 | buf->bufaddr = page_address(buf->bv->bv_page) + buf->bv->bv_offset; |
149 | 153 | ||
150 | spin_lock_irqsave(&d->lock, flags); | 154 | spin_lock_irqsave(&d->lock, flags); |
151 | 155 | ||
152 | if ((d->flags & DEVFL_UP) == 0) { | 156 | if ((d->flags & DEVFL_UP) == 0) { |
153 | printk(KERN_INFO "aoe: aoeblk_make_request: device %ld.%ld is not up\n", | 157 | printk(KERN_INFO "aoe: device %ld.%ld is not up\n", |
154 | d->aoemajor, d->aoeminor); | 158 | d->aoemajor, d->aoeminor); |
155 | spin_unlock_irqrestore(&d->lock, flags); | 159 | spin_unlock_irqrestore(&d->lock, flags); |
156 | mempool_free(buf, d->bufpool); | 160 | mempool_free(buf, d->bufpool); |
@@ -176,7 +180,7 @@ aoeblk_getgeo(struct block_device *bdev, struct hd_geometry *geo) | |||
176 | struct aoedev *d = bdev->bd_disk->private_data; | 180 | struct aoedev *d = bdev->bd_disk->private_data; |
177 | 181 | ||
178 | if ((d->flags & DEVFL_UP) == 0) { | 182 | if ((d->flags & DEVFL_UP) == 0) { |
179 | printk(KERN_ERR "aoe: aoeblk_ioctl: disk not up\n"); | 183 | printk(KERN_ERR "aoe: disk not up\n"); |
180 | return -ENODEV; | 184 | return -ENODEV; |
181 | } | 185 | } |
182 | 186 | ||
@@ -203,8 +207,8 @@ aoeblk_gdalloc(void *vp) | |||
203 | 207 | ||
204 | gd = alloc_disk(AOE_PARTITIONS); | 208 | gd = alloc_disk(AOE_PARTITIONS); |
205 | if (gd == NULL) { | 209 | if (gd == NULL) { |
206 | printk(KERN_ERR "aoe: aoeblk_gdalloc: cannot allocate disk " | 210 | printk(KERN_ERR "aoe: cannot allocate disk structure for %ld.%ld\n", |
207 | "structure for %ld.%ld\n", d->aoemajor, d->aoeminor); | 211 | d->aoemajor, d->aoeminor); |
208 | spin_lock_irqsave(&d->lock, flags); | 212 | spin_lock_irqsave(&d->lock, flags); |
209 | d->flags &= ~DEVFL_GDALLOC; | 213 | d->flags &= ~DEVFL_GDALLOC; |
210 | spin_unlock_irqrestore(&d->lock, flags); | 214 | spin_unlock_irqrestore(&d->lock, flags); |
@@ -213,8 +217,8 @@ aoeblk_gdalloc(void *vp) | |||
213 | 217 | ||
214 | d->bufpool = mempool_create_slab_pool(MIN_BUFS, buf_pool_cache); | 218 | d->bufpool = mempool_create_slab_pool(MIN_BUFS, buf_pool_cache); |
215 | if (d->bufpool == NULL) { | 219 | if (d->bufpool == NULL) { |
216 | printk(KERN_ERR "aoe: aoeblk_gdalloc: cannot allocate bufpool " | 220 | printk(KERN_ERR "aoe: cannot allocate bufpool for %ld.%ld\n", |
217 | "for %ld.%ld\n", d->aoemajor, d->aoeminor); | 221 | d->aoemajor, d->aoeminor); |
218 | put_disk(gd); | 222 | put_disk(gd); |
219 | spin_lock_irqsave(&d->lock, flags); | 223 | spin_lock_irqsave(&d->lock, flags); |
220 | d->flags &= ~DEVFL_GDALLOC; | 224 | d->flags &= ~DEVFL_GDALLOC; |
diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c index 1bc1cf9603f1..e22b4c9520a9 100644 --- a/drivers/block/aoe/aoechr.c +++ b/drivers/block/aoe/aoechr.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */ | 1 | /* Copyright (c) 2006 Coraid, Inc. See COPYING for GPL terms. */ |
2 | /* | 2 | /* |
3 | * aoechr.c | 3 | * aoechr.c |
4 | * AoE character device driver | 4 | * AoE character device driver |
@@ -15,7 +15,6 @@ enum { | |||
15 | MINOR_INTERFACES, | 15 | MINOR_INTERFACES, |
16 | MINOR_REVALIDATE, | 16 | MINOR_REVALIDATE, |
17 | MSGSZ = 2048, | 17 | MSGSZ = 2048, |
18 | NARGS = 10, | ||
19 | NMSG = 100, /* message backlog to retain */ | 18 | NMSG = 100, /* message backlog to retain */ |
20 | }; | 19 | }; |
21 | 20 | ||
@@ -56,9 +55,8 @@ static int | |||
56 | interfaces(const char __user *str, size_t size) | 55 | interfaces(const char __user *str, size_t size) |
57 | { | 56 | { |
58 | if (set_aoe_iflist(str, size)) { | 57 | if (set_aoe_iflist(str, size)) { |
59 | printk(KERN_CRIT | 58 | printk(KERN_ERR |
60 | "%s: could not set interface list: %s\n", | 59 | "aoe: could not set interface list: too many interfaces\n"); |
61 | __FUNCTION__, "too many interfaces"); | ||
62 | return -EINVAL; | 60 | return -EINVAL; |
63 | } | 61 | } |
64 | return 0; | 62 | return 0; |
@@ -81,8 +79,7 @@ revalidate(const char __user *str, size_t size) | |||
81 | /* should be e%d.%d format */ | 79 | /* should be e%d.%d format */ |
82 | n = sscanf(buf, "e%d.%d", &major, &minor); | 80 | n = sscanf(buf, "e%d.%d", &major, &minor); |
83 | if (n != 2) { | 81 | if (n != 2) { |
84 | printk(KERN_ERR "aoe: %s: invalid device specification\n", | 82 | printk(KERN_ERR "aoe: invalid device specification\n"); |
85 | __FUNCTION__); | ||
86 | return -EINVAL; | 83 | return -EINVAL; |
87 | } | 84 | } |
88 | d = aoedev_by_aoeaddr(major, minor); | 85 | d = aoedev_by_aoeaddr(major, minor); |
@@ -90,6 +87,7 @@ revalidate(const char __user *str, size_t size) | |||
90 | return -EINVAL; | 87 | return -EINVAL; |
91 | 88 | ||
92 | spin_lock_irqsave(&d->lock, flags); | 89 | spin_lock_irqsave(&d->lock, flags); |
90 | d->flags &= ~DEVFL_MAXBCNT; | ||
93 | d->flags |= DEVFL_PAUSE; | 91 | d->flags |= DEVFL_PAUSE; |
94 | spin_unlock_irqrestore(&d->lock, flags); | 92 | spin_unlock_irqrestore(&d->lock, flags); |
95 | aoecmd_cfg(major, minor); | 93 | aoecmd_cfg(major, minor); |
@@ -116,7 +114,7 @@ bail: spin_unlock_irqrestore(&emsgs_lock, flags); | |||
116 | 114 | ||
117 | mp = kmalloc(n, GFP_ATOMIC); | 115 | mp = kmalloc(n, GFP_ATOMIC); |
118 | if (mp == NULL) { | 116 | if (mp == NULL) { |
119 | printk(KERN_CRIT "aoe: aoechr_error: allocation failure, len=%ld\n", n); | 117 | printk(KERN_ERR "aoe: allocation failure, len=%ld\n", n); |
120 | goto bail; | 118 | goto bail; |
121 | } | 119 | } |
122 | 120 | ||
@@ -141,7 +139,7 @@ aoechr_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offp | |||
141 | 139 | ||
142 | switch ((unsigned long) filp->private_data) { | 140 | switch ((unsigned long) filp->private_data) { |
143 | default: | 141 | default: |
144 | printk(KERN_INFO "aoe: aoechr_write: can't write to that file.\n"); | 142 | printk(KERN_INFO "aoe: can't write to that file.\n"); |
145 | break; | 143 | break; |
146 | case MINOR_DISCOVER: | 144 | case MINOR_DISCOVER: |
147 | ret = discover(); | 145 | ret = discover(); |
@@ -250,7 +248,7 @@ aoechr_init(void) | |||
250 | 248 | ||
251 | n = register_chrdev(AOE_MAJOR, "aoechr", &aoe_fops); | 249 | n = register_chrdev(AOE_MAJOR, "aoechr", &aoe_fops); |
252 | if (n < 0) { | 250 | if (n < 0) { |
253 | printk(KERN_ERR "aoe: aoechr_init: can't register char device\n"); | 251 | printk(KERN_ERR "aoe: can't register char device\n"); |
254 | return n; | 252 | return n; |
255 | } | 253 | } |
256 | sema_init(&emsgs_sema, 0); | 254 | sema_init(&emsgs_sema, 0); |
diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 39da28d344fe..8a13b1af8bab 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */ | 1 | /* Copyright (c) 2006 Coraid, Inc. See COPYING for GPL terms. */ |
2 | /* | 2 | /* |
3 | * aoecmd.c | 3 | * aoecmd.c |
4 | * Filesystem request handling methods | 4 | * Filesystem request handling methods |
@@ -15,17 +15,19 @@ | |||
15 | #define TIMERTICK (HZ / 10) | 15 | #define TIMERTICK (HZ / 10) |
16 | #define MINTIMER (2 * TIMERTICK) | 16 | #define MINTIMER (2 * TIMERTICK) |
17 | #define MAXTIMER (HZ << 1) | 17 | #define MAXTIMER (HZ << 1) |
18 | #define MAXWAIT (60 * 3) /* After MAXWAIT seconds, give up and fail dev */ | ||
19 | 18 | ||
20 | static struct sk_buff * | 19 | static int aoe_deadsecs = 60 * 3; |
21 | new_skb(struct net_device *if_dev, ulong len) | 20 | module_param(aoe_deadsecs, int, 0644); |
21 | MODULE_PARM_DESC(aoe_deadsecs, "After aoe_deadsecs seconds, give up and fail dev."); | ||
22 | |||
23 | struct sk_buff * | ||
24 | new_skb(ulong len) | ||
22 | { | 25 | { |
23 | struct sk_buff *skb; | 26 | struct sk_buff *skb; |
24 | 27 | ||
25 | skb = alloc_skb(len, GFP_ATOMIC); | 28 | skb = alloc_skb(len, GFP_ATOMIC); |
26 | if (skb) { | 29 | if (skb) { |
27 | skb->nh.raw = skb->mac.raw = skb->data; | 30 | skb->nh.raw = skb->mac.raw = skb->data; |
28 | skb->dev = if_dev; | ||
29 | skb->protocol = __constant_htons(ETH_P_AOE); | 31 | skb->protocol = __constant_htons(ETH_P_AOE); |
30 | skb->priority = 0; | 32 | skb->priority = 0; |
31 | skb_put(skb, len); | 33 | skb_put(skb, len); |
@@ -40,29 +42,6 @@ new_skb(struct net_device *if_dev, ulong len) | |||
40 | return skb; | 42 | return skb; |
41 | } | 43 | } |
42 | 44 | ||
43 | static struct sk_buff * | ||
44 | skb_prepare(struct aoedev *d, struct frame *f) | ||
45 | { | ||
46 | struct sk_buff *skb; | ||
47 | char *p; | ||
48 | |||
49 | skb = new_skb(d->ifp, f->ndata + f->writedatalen); | ||
50 | if (!skb) { | ||
51 | printk(KERN_INFO "aoe: skb_prepare: failure to allocate skb\n"); | ||
52 | return NULL; | ||
53 | } | ||
54 | |||
55 | p = skb->mac.raw; | ||
56 | memcpy(p, f->data, f->ndata); | ||
57 | |||
58 | if (f->writedatalen) { | ||
59 | p += sizeof(struct aoe_hdr) + sizeof(struct aoe_atahdr); | ||
60 | memcpy(p, f->bufaddr, f->writedatalen); | ||
61 | } | ||
62 | |||
63 | return skb; | ||
64 | } | ||
65 | |||
66 | static struct frame * | 45 | static struct frame * |
67 | getframe(struct aoedev *d, int tag) | 46 | getframe(struct aoedev *d, int tag) |
68 | { | 47 | { |
@@ -107,6 +86,17 @@ aoehdr_atainit(struct aoedev *d, struct aoe_hdr *h) | |||
107 | return host_tag; | 86 | return host_tag; |
108 | } | 87 | } |
109 | 88 | ||
89 | static inline void | ||
90 | put_lba(struct aoe_atahdr *ah, sector_t lba) | ||
91 | { | ||
92 | ah->lba0 = lba; | ||
93 | ah->lba1 = lba >>= 8; | ||
94 | ah->lba2 = lba >>= 8; | ||
95 | ah->lba3 = lba >>= 8; | ||
96 | ah->lba4 = lba >>= 8; | ||
97 | ah->lba5 = lba >>= 8; | ||
98 | } | ||
99 | |||
110 | static void | 100 | static void |
111 | aoecmd_ata_rw(struct aoedev *d, struct frame *f) | 101 | aoecmd_ata_rw(struct aoedev *d, struct frame *f) |
112 | { | 102 | { |
@@ -125,29 +115,27 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f) | |||
125 | 115 | ||
126 | sector = buf->sector; | 116 | sector = buf->sector; |
127 | bcnt = buf->bv_resid; | 117 | bcnt = buf->bv_resid; |
128 | if (bcnt > MAXATADATA) | 118 | if (bcnt > d->maxbcnt) |
129 | bcnt = MAXATADATA; | 119 | bcnt = d->maxbcnt; |
130 | 120 | ||
131 | /* initialize the headers & frame */ | 121 | /* initialize the headers & frame */ |
132 | h = (struct aoe_hdr *) f->data; | 122 | skb = f->skb; |
123 | h = (struct aoe_hdr *) skb->mac.raw; | ||
133 | ah = (struct aoe_atahdr *) (h+1); | 124 | ah = (struct aoe_atahdr *) (h+1); |
134 | f->ndata = sizeof *h + sizeof *ah; | 125 | skb->len = sizeof *h + sizeof *ah; |
135 | memset(h, 0, f->ndata); | 126 | memset(h, 0, ETH_ZLEN); |
136 | f->tag = aoehdr_atainit(d, h); | 127 | f->tag = aoehdr_atainit(d, h); |
137 | f->waited = 0; | 128 | f->waited = 0; |
138 | f->buf = buf; | 129 | f->buf = buf; |
139 | f->bufaddr = buf->bufaddr; | 130 | f->bufaddr = buf->bufaddr; |
131 | f->bcnt = bcnt; | ||
132 | f->lba = sector; | ||
140 | 133 | ||
141 | /* set up ata header */ | 134 | /* set up ata header */ |
142 | ah->scnt = bcnt >> 9; | 135 | ah->scnt = bcnt >> 9; |
143 | ah->lba0 = sector; | 136 | put_lba(ah, sector); |
144 | ah->lba1 = sector >>= 8; | ||
145 | ah->lba2 = sector >>= 8; | ||
146 | ah->lba3 = sector >>= 8; | ||
147 | if (d->flags & DEVFL_EXT) { | 137 | if (d->flags & DEVFL_EXT) { |
148 | ah->aflags |= AOEAFL_EXT; | 138 | ah->aflags |= AOEAFL_EXT; |
149 | ah->lba4 = sector >>= 8; | ||
150 | ah->lba5 = sector >>= 8; | ||
151 | } else { | 139 | } else { |
152 | extbit = 0; | 140 | extbit = 0; |
153 | ah->lba3 &= 0x0f; | 141 | ah->lba3 &= 0x0f; |
@@ -155,11 +143,14 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f) | |||
155 | } | 143 | } |
156 | 144 | ||
157 | if (bio_data_dir(buf->bio) == WRITE) { | 145 | if (bio_data_dir(buf->bio) == WRITE) { |
146 | skb_fill_page_desc(skb, 0, virt_to_page(f->bufaddr), | ||
147 | offset_in_page(f->bufaddr), bcnt); | ||
158 | ah->aflags |= AOEAFL_WRITE; | 148 | ah->aflags |= AOEAFL_WRITE; |
159 | f->writedatalen = bcnt; | 149 | skb->len += bcnt; |
150 | skb->data_len = bcnt; | ||
160 | } else { | 151 | } else { |
152 | skb->len = ETH_ZLEN; | ||
161 | writebit = 0; | 153 | writebit = 0; |
162 | f->writedatalen = 0; | ||
163 | } | 154 | } |
164 | 155 | ||
165 | ah->cmdstat = WIN_READ | writebit | extbit; | 156 | ah->cmdstat = WIN_READ | writebit | extbit; |
@@ -168,26 +159,27 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f) | |||
168 | buf->nframesout += 1; | 159 | buf->nframesout += 1; |
169 | buf->bufaddr += bcnt; | 160 | buf->bufaddr += bcnt; |
170 | buf->bv_resid -= bcnt; | 161 | buf->bv_resid -= bcnt; |
171 | /* printk(KERN_INFO "aoe: bv_resid=%ld\n", buf->bv_resid); */ | 162 | /* printk(KERN_DEBUG "aoe: bv_resid=%ld\n", buf->bv_resid); */ |
172 | buf->resid -= bcnt; | 163 | buf->resid -= bcnt; |
173 | buf->sector += bcnt >> 9; | 164 | buf->sector += bcnt >> 9; |
174 | if (buf->resid == 0) { | 165 | if (buf->resid == 0) { |
175 | d->inprocess = NULL; | 166 | d->inprocess = NULL; |
176 | } else if (buf->bv_resid == 0) { | 167 | } else if (buf->bv_resid == 0) { |
177 | buf->bv++; | 168 | buf->bv++; |
169 | WARN_ON(buf->bv->bv_len == 0); | ||
178 | buf->bv_resid = buf->bv->bv_len; | 170 | buf->bv_resid = buf->bv->bv_len; |
179 | buf->bufaddr = page_address(buf->bv->bv_page) + buf->bv->bv_offset; | 171 | buf->bufaddr = page_address(buf->bv->bv_page) + buf->bv->bv_offset; |
180 | } | 172 | } |
181 | 173 | ||
182 | skb = skb_prepare(d, f); | 174 | skb->dev = d->ifp; |
183 | if (skb) { | 175 | skb = skb_clone(skb, GFP_ATOMIC); |
184 | skb->next = NULL; | 176 | if (skb == NULL) |
185 | if (d->sendq_hd) | 177 | return; |
186 | d->sendq_tl->next = skb; | 178 | if (d->sendq_hd) |
187 | else | 179 | d->sendq_tl->next = skb; |
188 | d->sendq_hd = skb; | 180 | else |
189 | d->sendq_tl = skb; | 181 | d->sendq_hd = skb; |
190 | } | 182 | d->sendq_tl = skb; |
191 | } | 183 | } |
192 | 184 | ||
193 | /* some callers cannot sleep, and they can call this function, | 185 | /* some callers cannot sleep, and they can call this function, |
@@ -209,11 +201,12 @@ aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff **tail) | |||
209 | if (!is_aoe_netif(ifp)) | 201 | if (!is_aoe_netif(ifp)) |
210 | continue; | 202 | continue; |
211 | 203 | ||
212 | skb = new_skb(ifp, sizeof *h + sizeof *ch); | 204 | skb = new_skb(sizeof *h + sizeof *ch); |
213 | if (skb == NULL) { | 205 | if (skb == NULL) { |
214 | printk(KERN_INFO "aoe: aoecmd_cfg: skb alloc failure\n"); | 206 | printk(KERN_INFO "aoe: skb alloc failure\n"); |
215 | continue; | 207 | continue; |
216 | } | 208 | } |
209 | skb->dev = ifp; | ||
217 | if (sl_tail == NULL) | 210 | if (sl_tail == NULL) |
218 | sl_tail = skb; | 211 | sl_tail = skb; |
219 | h = (struct aoe_hdr *) skb->mac.raw; | 212 | h = (struct aoe_hdr *) skb->mac.raw; |
@@ -237,6 +230,29 @@ aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff **tail) | |||
237 | return sl; | 230 | return sl; |
238 | } | 231 | } |
239 | 232 | ||
233 | static struct frame * | ||
234 | freeframe(struct aoedev *d) | ||
235 | { | ||
236 | struct frame *f, *e; | ||
237 | int n = 0; | ||
238 | |||
239 | f = d->frames; | ||
240 | e = f + d->nframes; | ||
241 | for (; f<e; f++) { | ||
242 | if (f->tag != FREETAG) | ||
243 | continue; | ||
244 | if (atomic_read(&skb_shinfo(f->skb)->dataref) == 1) { | ||
245 | skb_shinfo(f->skb)->nr_frags = f->skb->data_len = 0; | ||
246 | return f; | ||
247 | } | ||
248 | n++; | ||
249 | } | ||
250 | if (n == d->nframes) /* wait for network layer */ | ||
251 | d->flags |= DEVFL_KICKME; | ||
252 | |||
253 | return NULL; | ||
254 | } | ||
255 | |||
240 | /* enters with d->lock held */ | 256 | /* enters with d->lock held */ |
241 | void | 257 | void |
242 | aoecmd_work(struct aoedev *d) | 258 | aoecmd_work(struct aoedev *d) |
@@ -252,7 +268,7 @@ aoecmd_work(struct aoedev *d) | |||
252 | } | 268 | } |
253 | 269 | ||
254 | loop: | 270 | loop: |
255 | f = getframe(d, FREETAG); | 271 | f = freeframe(d); |
256 | if (f == NULL) | 272 | if (f == NULL) |
257 | return; | 273 | return; |
258 | if (d->inprocess == NULL) { | 274 | if (d->inprocess == NULL) { |
@@ -260,7 +276,7 @@ loop: | |||
260 | return; | 276 | return; |
261 | buf = container_of(d->bufq.next, struct buf, bufs); | 277 | buf = container_of(d->bufq.next, struct buf, bufs); |
262 | list_del(d->bufq.next); | 278 | list_del(d->bufq.next); |
263 | /*printk(KERN_INFO "aoecmd_work: bi_size=%ld\n", buf->bio->bi_size); */ | 279 | /*printk(KERN_DEBUG "aoe: bi_size=%ld\n", buf->bio->bi_size); */ |
264 | d->inprocess = buf; | 280 | d->inprocess = buf; |
265 | } | 281 | } |
266 | aoecmd_ata_rw(d, f); | 282 | aoecmd_ata_rw(d, f); |
@@ -272,6 +288,7 @@ rexmit(struct aoedev *d, struct frame *f) | |||
272 | { | 288 | { |
273 | struct sk_buff *skb; | 289 | struct sk_buff *skb; |
274 | struct aoe_hdr *h; | 290 | struct aoe_hdr *h; |
291 | struct aoe_atahdr *ah; | ||
275 | char buf[128]; | 292 | char buf[128]; |
276 | u32 n; | 293 | u32 n; |
277 | 294 | ||
@@ -283,21 +300,41 @@ rexmit(struct aoedev *d, struct frame *f) | |||
283 | d->aoemajor, d->aoeminor, f->tag, jiffies, n); | 300 | d->aoemajor, d->aoeminor, f->tag, jiffies, n); |
284 | aoechr_error(buf); | 301 | aoechr_error(buf); |
285 | 302 | ||
286 | h = (struct aoe_hdr *) f->data; | 303 | skb = f->skb; |
304 | h = (struct aoe_hdr *) skb->mac.raw; | ||
305 | ah = (struct aoe_atahdr *) (h+1); | ||
287 | f->tag = n; | 306 | f->tag = n; |
288 | h->tag = cpu_to_be32(n); | 307 | h->tag = cpu_to_be32(n); |
289 | memcpy(h->dst, d->addr, sizeof h->dst); | 308 | memcpy(h->dst, d->addr, sizeof h->dst); |
290 | memcpy(h->src, d->ifp->dev_addr, sizeof h->src); | 309 | memcpy(h->src, d->ifp->dev_addr, sizeof h->src); |
291 | 310 | ||
292 | skb = skb_prepare(d, f); | 311 | n = DEFAULTBCNT / 512; |
293 | if (skb) { | 312 | if (ah->scnt > n) { |
294 | skb->next = NULL; | 313 | ah->scnt = n; |
295 | if (d->sendq_hd) | 314 | if (ah->aflags & AOEAFL_WRITE) { |
296 | d->sendq_tl->next = skb; | 315 | skb_fill_page_desc(skb, 0, virt_to_page(f->bufaddr), |
297 | else | 316 | offset_in_page(f->bufaddr), DEFAULTBCNT); |
298 | d->sendq_hd = skb; | 317 | skb->len = sizeof *h + sizeof *ah + DEFAULTBCNT; |
299 | d->sendq_tl = skb; | 318 | skb->data_len = DEFAULTBCNT; |
319 | } | ||
320 | if (++d->lostjumbo > (d->nframes << 1)) | ||
321 | if (d->maxbcnt != DEFAULTBCNT) { | ||
322 | printk(KERN_INFO "aoe: e%ld.%ld: too many lost jumbo on %s - using 1KB frames.\n", | ||
323 | d->aoemajor, d->aoeminor, d->ifp->name); | ||
324 | d->maxbcnt = DEFAULTBCNT; | ||
325 | d->flags |= DEVFL_MAXBCNT; | ||
326 | } | ||
300 | } | 327 | } |
328 | |||
329 | skb->dev = d->ifp; | ||
330 | skb = skb_clone(skb, GFP_ATOMIC); | ||
331 | if (skb == NULL) | ||
332 | return; | ||
333 | if (d->sendq_hd) | ||
334 | d->sendq_tl->next = skb; | ||
335 | else | ||
336 | d->sendq_hd = skb; | ||
337 | d->sendq_tl = skb; | ||
301 | } | 338 | } |
302 | 339 | ||
303 | static int | 340 | static int |
@@ -340,13 +377,17 @@ rexmit_timer(ulong vp) | |||
340 | if (f->tag != FREETAG && tsince(f->tag) >= timeout) { | 377 | if (f->tag != FREETAG && tsince(f->tag) >= timeout) { |
341 | n = f->waited += timeout; | 378 | n = f->waited += timeout; |
342 | n /= HZ; | 379 | n /= HZ; |
343 | if (n > MAXWAIT) { /* waited too long. device failure. */ | 380 | if (n > aoe_deadsecs) { /* waited too long for response */ |
344 | aoedev_downdev(d); | 381 | aoedev_downdev(d); |
345 | break; | 382 | break; |
346 | } | 383 | } |
347 | rexmit(d, f); | 384 | rexmit(d, f); |
348 | } | 385 | } |
349 | } | 386 | } |
387 | if (d->flags & DEVFL_KICKME) { | ||
388 | d->flags &= ~DEVFL_KICKME; | ||
389 | aoecmd_work(d); | ||
390 | } | ||
350 | 391 | ||
351 | sl = d->sendq_hd; | 392 | sl = d->sendq_hd; |
352 | d->sendq_hd = d->sendq_tl = NULL; | 393 | d->sendq_hd = d->sendq_tl = NULL; |
@@ -431,8 +472,8 @@ ataid_complete(struct aoedev *d, unsigned char *id) | |||
431 | } | 472 | } |
432 | 473 | ||
433 | if (d->ssize != ssize) | 474 | if (d->ssize != ssize) |
434 | printk(KERN_INFO "aoe: %012llx e%lu.%lu v%04x has %llu " | 475 | printk(KERN_INFO "aoe: %012llx e%lu.%lu v%04x has %llu sectors\n", |
435 | "sectors\n", (unsigned long long)mac_addr(d->addr), | 476 | (unsigned long long)mac_addr(d->addr), |
436 | d->aoemajor, d->aoeminor, | 477 | d->aoemajor, d->aoeminor, |
437 | d->fw_ver, (long long)ssize); | 478 | d->fw_ver, (long long)ssize); |
438 | d->ssize = ssize; | 479 | d->ssize = ssize; |
@@ -442,11 +483,9 @@ ataid_complete(struct aoedev *d, unsigned char *id) | |||
442 | d->flags |= DEVFL_NEWSIZE; | 483 | d->flags |= DEVFL_NEWSIZE; |
443 | } else { | 484 | } else { |
444 | if (d->flags & DEVFL_GDALLOC) { | 485 | if (d->flags & DEVFL_GDALLOC) { |
445 | printk(KERN_INFO "aoe: %s: %s e%lu.%lu, %s\n", | 486 | printk(KERN_ERR "aoe: can't schedule work for e%lu.%lu, %s\n", |
446 | __FUNCTION__, | ||
447 | "can't schedule work for", | ||
448 | d->aoemajor, d->aoeminor, | 487 | d->aoemajor, d->aoeminor, |
449 | "it's already on! (This really shouldn't happen).\n"); | 488 | "it's already on! This shouldn't happen.\n"); |
450 | return; | 489 | return; |
451 | } | 490 | } |
452 | d->flags |= DEVFL_GDALLOC; | 491 | d->flags |= DEVFL_GDALLOC; |
@@ -460,8 +499,15 @@ calc_rttavg(struct aoedev *d, int rtt) | |||
460 | register long n; | 499 | register long n; |
461 | 500 | ||
462 | n = rtt; | 501 | n = rtt; |
463 | if (n < MINTIMER) | 502 | if (n < 0) { |
464 | n = MINTIMER; | 503 | n = -rtt; |
504 | if (n < MINTIMER) | ||
505 | n = MINTIMER; | ||
506 | else if (n > MAXTIMER) | ||
507 | n = MAXTIMER; | ||
508 | d->mintimer += (n - d->mintimer) >> 1; | ||
509 | } else if (n < d->mintimer) | ||
510 | n = d->mintimer; | ||
465 | else if (n > MAXTIMER) | 511 | else if (n > MAXTIMER) |
466 | n = MAXTIMER; | 512 | n = MAXTIMER; |
467 | 513 | ||
@@ -474,7 +520,7 @@ void | |||
474 | aoecmd_ata_rsp(struct sk_buff *skb) | 520 | aoecmd_ata_rsp(struct sk_buff *skb) |
475 | { | 521 | { |
476 | struct aoedev *d; | 522 | struct aoedev *d; |
477 | struct aoe_hdr *hin; | 523 | struct aoe_hdr *hin, *hout; |
478 | struct aoe_atahdr *ahin, *ahout; | 524 | struct aoe_atahdr *ahin, *ahout; |
479 | struct frame *f; | 525 | struct frame *f; |
480 | struct buf *buf; | 526 | struct buf *buf; |
@@ -497,8 +543,10 @@ aoecmd_ata_rsp(struct sk_buff *skb) | |||
497 | 543 | ||
498 | spin_lock_irqsave(&d->lock, flags); | 544 | spin_lock_irqsave(&d->lock, flags); |
499 | 545 | ||
500 | f = getframe(d, be32_to_cpu(hin->tag)); | 546 | n = be32_to_cpu(hin->tag); |
547 | f = getframe(d, n); | ||
501 | if (f == NULL) { | 548 | if (f == NULL) { |
549 | calc_rttavg(d, -tsince(n)); | ||
502 | spin_unlock_irqrestore(&d->lock, flags); | 550 | spin_unlock_irqrestore(&d->lock, flags); |
503 | snprintf(ebuf, sizeof ebuf, | 551 | snprintf(ebuf, sizeof ebuf, |
504 | "%15s e%d.%d tag=%08x@%08lx\n", | 552 | "%15s e%d.%d tag=%08x@%08lx\n", |
@@ -514,26 +562,27 @@ aoecmd_ata_rsp(struct sk_buff *skb) | |||
514 | calc_rttavg(d, tsince(f->tag)); | 562 | calc_rttavg(d, tsince(f->tag)); |
515 | 563 | ||
516 | ahin = (struct aoe_atahdr *) (hin+1); | 564 | ahin = (struct aoe_atahdr *) (hin+1); |
517 | ahout = (struct aoe_atahdr *) (f->data + sizeof(struct aoe_hdr)); | 565 | hout = (struct aoe_hdr *) f->skb->mac.raw; |
566 | ahout = (struct aoe_atahdr *) (hout+1); | ||
518 | buf = f->buf; | 567 | buf = f->buf; |
519 | 568 | ||
520 | if (ahout->cmdstat == WIN_IDENTIFY) | 569 | if (ahout->cmdstat == WIN_IDENTIFY) |
521 | d->flags &= ~DEVFL_PAUSE; | 570 | d->flags &= ~DEVFL_PAUSE; |
522 | if (ahin->cmdstat & 0xa9) { /* these bits cleared on success */ | 571 | if (ahin->cmdstat & 0xa9) { /* these bits cleared on success */ |
523 | printk(KERN_CRIT "aoe: aoecmd_ata_rsp: ata error cmd=%2.2Xh " | 572 | printk(KERN_ERR |
524 | "stat=%2.2Xh from e%ld.%ld\n", | 573 | "aoe: ata error cmd=%2.2Xh stat=%2.2Xh from e%ld.%ld\n", |
525 | ahout->cmdstat, ahin->cmdstat, | 574 | ahout->cmdstat, ahin->cmdstat, |
526 | d->aoemajor, d->aoeminor); | 575 | d->aoemajor, d->aoeminor); |
527 | if (buf) | 576 | if (buf) |
528 | buf->flags |= BUFFL_FAIL; | 577 | buf->flags |= BUFFL_FAIL; |
529 | } else { | 578 | } else { |
579 | n = ahout->scnt << 9; | ||
530 | switch (ahout->cmdstat) { | 580 | switch (ahout->cmdstat) { |
531 | case WIN_READ: | 581 | case WIN_READ: |
532 | case WIN_READ_EXT: | 582 | case WIN_READ_EXT: |
533 | n = ahout->scnt << 9; | ||
534 | if (skb->len - sizeof *hin - sizeof *ahin < n) { | 583 | if (skb->len - sizeof *hin - sizeof *ahin < n) { |
535 | printk(KERN_CRIT "aoe: aoecmd_ata_rsp: runt " | 584 | printk(KERN_ERR |
536 | "ata data size in read. skb->len=%d\n", | 585 | "aoe: runt data size in read. skb->len=%d\n", |
537 | skb->len); | 586 | skb->len); |
538 | /* fail frame f? just returning will rexmit. */ | 587 | /* fail frame f? just returning will rexmit. */ |
539 | spin_unlock_irqrestore(&d->lock, flags); | 588 | spin_unlock_irqrestore(&d->lock, flags); |
@@ -542,22 +591,49 @@ aoecmd_ata_rsp(struct sk_buff *skb) | |||
542 | memcpy(f->bufaddr, ahin+1, n); | 591 | memcpy(f->bufaddr, ahin+1, n); |
543 | case WIN_WRITE: | 592 | case WIN_WRITE: |
544 | case WIN_WRITE_EXT: | 593 | case WIN_WRITE_EXT: |
594 | if (f->bcnt -= n) { | ||
595 | skb = f->skb; | ||
596 | f->bufaddr += n; | ||
597 | put_lba(ahout, f->lba += ahout->scnt); | ||
598 | n = f->bcnt; | ||
599 | if (n > DEFAULTBCNT) | ||
600 | n = DEFAULTBCNT; | ||
601 | ahout->scnt = n >> 9; | ||
602 | if (ahout->aflags & AOEAFL_WRITE) { | ||
603 | skb_fill_page_desc(skb, 0, | ||
604 | virt_to_page(f->bufaddr), | ||
605 | offset_in_page(f->bufaddr), n); | ||
606 | skb->len = sizeof *hout + sizeof *ahout + n; | ||
607 | skb->data_len = n; | ||
608 | } | ||
609 | f->tag = newtag(d); | ||
610 | hout->tag = cpu_to_be32(f->tag); | ||
611 | skb->dev = d->ifp; | ||
612 | skb = skb_clone(skb, GFP_ATOMIC); | ||
613 | spin_unlock_irqrestore(&d->lock, flags); | ||
614 | if (skb) | ||
615 | aoenet_xmit(skb); | ||
616 | return; | ||
617 | } | ||
618 | if (n > DEFAULTBCNT) | ||
619 | d->lostjumbo = 0; | ||
545 | break; | 620 | break; |
546 | case WIN_IDENTIFY: | 621 | case WIN_IDENTIFY: |
547 | if (skb->len - sizeof *hin - sizeof *ahin < 512) { | 622 | if (skb->len - sizeof *hin - sizeof *ahin < 512) { |
548 | printk(KERN_INFO "aoe: aoecmd_ata_rsp: runt data size " | 623 | printk(KERN_INFO |
549 | "in ataid. skb->len=%d\n", skb->len); | 624 | "aoe: runt data size in ataid. skb->len=%d\n", |
625 | skb->len); | ||
550 | spin_unlock_irqrestore(&d->lock, flags); | 626 | spin_unlock_irqrestore(&d->lock, flags); |
551 | return; | 627 | return; |
552 | } | 628 | } |
553 | ataid_complete(d, (char *) (ahin+1)); | 629 | ataid_complete(d, (char *) (ahin+1)); |
554 | break; | 630 | break; |
555 | default: | 631 | default: |
556 | printk(KERN_INFO "aoe: aoecmd_ata_rsp: unrecognized " | 632 | printk(KERN_INFO |
557 | "outbound ata command %2.2Xh for %d.%d\n", | 633 | "aoe: unrecognized ata command %2.2Xh for %d.%d\n", |
558 | ahout->cmdstat, | 634 | ahout->cmdstat, |
559 | be16_to_cpu(hin->major), | 635 | be16_to_cpu(hin->major), |
560 | hin->minor); | 636 | hin->minor); |
561 | } | 637 | } |
562 | } | 638 | } |
563 | 639 | ||
@@ -612,33 +688,32 @@ aoecmd_ata_id(struct aoedev *d) | |||
612 | struct frame *f; | 688 | struct frame *f; |
613 | struct sk_buff *skb; | 689 | struct sk_buff *skb; |
614 | 690 | ||
615 | f = getframe(d, FREETAG); | 691 | f = freeframe(d); |
616 | if (f == NULL) { | 692 | if (f == NULL) { |
617 | printk(KERN_CRIT "aoe: aoecmd_ata_id: can't get a frame. " | 693 | printk(KERN_ERR "aoe: can't get a frame. This shouldn't happen.\n"); |
618 | "This shouldn't happen.\n"); | ||
619 | return NULL; | 694 | return NULL; |
620 | } | 695 | } |
621 | 696 | ||
622 | /* initialize the headers & frame */ | 697 | /* initialize the headers & frame */ |
623 | h = (struct aoe_hdr *) f->data; | 698 | skb = f->skb; |
699 | h = (struct aoe_hdr *) skb->mac.raw; | ||
624 | ah = (struct aoe_atahdr *) (h+1); | 700 | ah = (struct aoe_atahdr *) (h+1); |
625 | f->ndata = sizeof *h + sizeof *ah; | 701 | skb->len = ETH_ZLEN; |
626 | memset(h, 0, f->ndata); | 702 | memset(h, 0, ETH_ZLEN); |
627 | f->tag = aoehdr_atainit(d, h); | 703 | f->tag = aoehdr_atainit(d, h); |
628 | f->waited = 0; | 704 | f->waited = 0; |
629 | f->writedatalen = 0; | ||
630 | 705 | ||
631 | /* set up ata header */ | 706 | /* set up ata header */ |
632 | ah->scnt = 1; | 707 | ah->scnt = 1; |
633 | ah->cmdstat = WIN_IDENTIFY; | 708 | ah->cmdstat = WIN_IDENTIFY; |
634 | ah->lba3 = 0xa0; | 709 | ah->lba3 = 0xa0; |
635 | 710 | ||
636 | skb = skb_prepare(d, f); | 711 | skb->dev = d->ifp; |
637 | 712 | ||
638 | d->rttavg = MAXTIMER; | 713 | d->rttavg = MAXTIMER; |
639 | d->timer.function = rexmit_timer; | 714 | d->timer.function = rexmit_timer; |
640 | 715 | ||
641 | return skb; | 716 | return skb_clone(skb, GFP_ATOMIC); |
642 | } | 717 | } |
643 | 718 | ||
644 | void | 719 | void |
@@ -648,9 +723,9 @@ aoecmd_cfg_rsp(struct sk_buff *skb) | |||
648 | struct aoe_hdr *h; | 723 | struct aoe_hdr *h; |
649 | struct aoe_cfghdr *ch; | 724 | struct aoe_cfghdr *ch; |
650 | ulong flags, sysminor, aoemajor; | 725 | ulong flags, sysminor, aoemajor; |
651 | u16 bufcnt; | ||
652 | struct sk_buff *sl; | 726 | struct sk_buff *sl; |
653 | enum { MAXFRAMES = 16 }; | 727 | enum { MAXFRAMES = 16 }; |
728 | u16 n; | ||
654 | 729 | ||
655 | h = (struct aoe_hdr *) skb->mac.raw; | 730 | h = (struct aoe_hdr *) skb->mac.raw; |
656 | ch = (struct aoe_cfghdr *) (h+1); | 731 | ch = (struct aoe_cfghdr *) (h+1); |
@@ -661,26 +736,25 @@ aoecmd_cfg_rsp(struct sk_buff *skb) | |||
661 | */ | 736 | */ |
662 | aoemajor = be16_to_cpu(h->major); | 737 | aoemajor = be16_to_cpu(h->major); |
663 | if (aoemajor == 0xfff) { | 738 | if (aoemajor == 0xfff) { |
664 | printk(KERN_CRIT "aoe: aoecmd_cfg_rsp: Warning: shelf " | 739 | printk(KERN_ERR "aoe: Warning: shelf address is all ones. " |
665 | "address is all ones. Check shelf dip switches\n"); | 740 | "Check shelf dip switches.\n"); |
666 | return; | 741 | return; |
667 | } | 742 | } |
668 | 743 | ||
669 | sysminor = SYSMINOR(aoemajor, h->minor); | 744 | sysminor = SYSMINOR(aoemajor, h->minor); |
670 | if (sysminor * AOE_PARTITIONS + AOE_PARTITIONS > MINORMASK) { | 745 | if (sysminor * AOE_PARTITIONS + AOE_PARTITIONS > MINORMASK) { |
671 | printk(KERN_INFO | 746 | printk(KERN_INFO "aoe: e%ld.%d: minor number too large\n", |
672 | "aoe: e%ld.%d: minor number too large\n", | ||
673 | aoemajor, (int) h->minor); | 747 | aoemajor, (int) h->minor); |
674 | return; | 748 | return; |
675 | } | 749 | } |
676 | 750 | ||
677 | bufcnt = be16_to_cpu(ch->bufcnt); | 751 | n = be16_to_cpu(ch->bufcnt); |
678 | if (bufcnt > MAXFRAMES) /* keep it reasonable */ | 752 | if (n > MAXFRAMES) /* keep it reasonable */ |
679 | bufcnt = MAXFRAMES; | 753 | n = MAXFRAMES; |
680 | 754 | ||
681 | d = aoedev_by_sysminor_m(sysminor, bufcnt); | 755 | d = aoedev_by_sysminor_m(sysminor, n); |
682 | if (d == NULL) { | 756 | if (d == NULL) { |
683 | printk(KERN_INFO "aoe: aoecmd_cfg_rsp: device sysminor_m failure\n"); | 757 | printk(KERN_INFO "aoe: device sysminor_m failure\n"); |
684 | return; | 758 | return; |
685 | } | 759 | } |
686 | 760 | ||
@@ -689,6 +763,20 @@ aoecmd_cfg_rsp(struct sk_buff *skb) | |||
689 | /* permit device to migrate mac and network interface */ | 763 | /* permit device to migrate mac and network interface */ |
690 | d->ifp = skb->dev; | 764 | d->ifp = skb->dev; |
691 | memcpy(d->addr, h->src, sizeof d->addr); | 765 | memcpy(d->addr, h->src, sizeof d->addr); |
766 | if (!(d->flags & DEVFL_MAXBCNT)) { | ||
767 | n = d->ifp->mtu; | ||
768 | n -= sizeof (struct aoe_hdr) + sizeof (struct aoe_atahdr); | ||
769 | n /= 512; | ||
770 | if (n > ch->scnt) | ||
771 | n = ch->scnt; | ||
772 | n = n ? n * 512 : DEFAULTBCNT; | ||
773 | if (n != d->maxbcnt) { | ||
774 | printk(KERN_INFO | ||
775 | "aoe: e%ld.%ld: setting %d byte data frames on %s\n", | ||
776 | d->aoemajor, d->aoeminor, n, d->ifp->name); | ||
777 | d->maxbcnt = n; | ||
778 | } | ||
779 | } | ||
692 | 780 | ||
693 | /* don't change users' perspective */ | 781 | /* don't change users' perspective */ |
694 | if (d->nopen && !(d->flags & DEVFL_PAUSE)) { | 782 | if (d->nopen && !(d->flags & DEVFL_PAUSE)) { |
@@ -696,6 +784,7 @@ aoecmd_cfg_rsp(struct sk_buff *skb) | |||
696 | return; | 784 | return; |
697 | } | 785 | } |
698 | d->flags |= DEVFL_PAUSE; /* force pause */ | 786 | d->flags |= DEVFL_PAUSE; /* force pause */ |
787 | d->mintimer = MINTIMER; | ||
699 | d->fw_ver = be16_to_cpu(ch->fwver); | 788 | d->fw_ver = be16_to_cpu(ch->fwver); |
700 | 789 | ||
701 | /* check for already outstanding ataid */ | 790 | /* check for already outstanding ataid */ |
diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c index ed4258a62df5..6125921bbec4 100644 --- a/drivers/block/aoe/aoedev.c +++ b/drivers/block/aoe/aoedev.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */ | 1 | /* Copyright (c) 2006 Coraid, Inc. See COPYING for GPL terms. */ |
2 | /* | 2 | /* |
3 | * aoedev.c | 3 | * aoedev.c |
4 | * AoE device utility functions; maintains device list. | 4 | * AoE device utility functions; maintains device list. |
@@ -20,11 +20,8 @@ aoedev_isbusy(struct aoedev *d) | |||
20 | f = d->frames; | 20 | f = d->frames; |
21 | e = f + d->nframes; | 21 | e = f + d->nframes; |
22 | do { | 22 | do { |
23 | if (f->tag != FREETAG) { | 23 | if (f->tag != FREETAG) |
24 | printk(KERN_DEBUG "aoe: %ld.%ld isbusy\n", | ||
25 | d->aoemajor, d->aoeminor); | ||
26 | return 1; | 24 | return 1; |
27 | } | ||
28 | } while (++f < e); | 25 | } while (++f < e); |
29 | 26 | ||
30 | return 0; | 27 | return 0; |
@@ -66,22 +63,32 @@ aoedev_newdev(ulong nframes) | |||
66 | struct frame *f, *e; | 63 | struct frame *f, *e; |
67 | 64 | ||
68 | d = kzalloc(sizeof *d, GFP_ATOMIC); | 65 | d = kzalloc(sizeof *d, GFP_ATOMIC); |
69 | if (d == NULL) | ||
70 | return NULL; | ||
71 | f = kcalloc(nframes, sizeof *f, GFP_ATOMIC); | 66 | f = kcalloc(nframes, sizeof *f, GFP_ATOMIC); |
72 | if (f == NULL) { | 67 | switch (!d || !f) { |
73 | kfree(d); | 68 | case 0: |
69 | d->nframes = nframes; | ||
70 | d->frames = f; | ||
71 | e = f + nframes; | ||
72 | for (; f<e; f++) { | ||
73 | f->tag = FREETAG; | ||
74 | f->skb = new_skb(ETH_ZLEN); | ||
75 | if (!f->skb) | ||
76 | break; | ||
77 | } | ||
78 | if (f == e) | ||
79 | break; | ||
80 | while (f > d->frames) { | ||
81 | f--; | ||
82 | dev_kfree_skb(f->skb); | ||
83 | } | ||
84 | default: | ||
85 | if (f) | ||
86 | kfree(f); | ||
87 | if (d) | ||
88 | kfree(d); | ||
74 | return NULL; | 89 | return NULL; |
75 | } | 90 | } |
76 | |||
77 | INIT_WORK(&d->work, aoecmd_sleepwork, d); | 91 | INIT_WORK(&d->work, aoecmd_sleepwork, d); |
78 | |||
79 | d->nframes = nframes; | ||
80 | d->frames = f; | ||
81 | e = f + nframes; | ||
82 | for (; f<e; f++) | ||
83 | f->tag = FREETAG; | ||
84 | |||
85 | spin_lock_init(&d->lock); | 92 | spin_lock_init(&d->lock); |
86 | init_timer(&d->timer); | 93 | init_timer(&d->timer); |
87 | d->timer.data = (ulong) d; | 94 | d->timer.data = (ulong) d; |
@@ -114,6 +121,7 @@ aoedev_downdev(struct aoedev *d) | |||
114 | mempool_free(buf, d->bufpool); | 121 | mempool_free(buf, d->bufpool); |
115 | bio_endio(bio, bio->bi_size, -EIO); | 122 | bio_endio(bio, bio->bi_size, -EIO); |
116 | } | 123 | } |
124 | skb_shinfo(f->skb)->nr_frags = f->skb->data_len = 0; | ||
117 | } | 125 | } |
118 | d->inprocess = NULL; | 126 | d->inprocess = NULL; |
119 | 127 | ||
@@ -148,7 +156,7 @@ aoedev_by_sysminor_m(ulong sysminor, ulong bufcnt) | |||
148 | d = aoedev_newdev(bufcnt); | 156 | d = aoedev_newdev(bufcnt); |
149 | if (d == NULL) { | 157 | if (d == NULL) { |
150 | spin_unlock_irqrestore(&devlist_lock, flags); | 158 | spin_unlock_irqrestore(&devlist_lock, flags); |
151 | printk(KERN_INFO "aoe: aoedev_set: aoedev_newdev failure.\n"); | 159 | printk(KERN_INFO "aoe: aoedev_newdev failure.\n"); |
152 | return NULL; | 160 | return NULL; |
153 | } | 161 | } |
154 | d->sysminor = sysminor; | 162 | d->sysminor = sysminor; |
@@ -163,11 +171,19 @@ aoedev_by_sysminor_m(ulong sysminor, ulong bufcnt) | |||
163 | static void | 171 | static void |
164 | aoedev_freedev(struct aoedev *d) | 172 | aoedev_freedev(struct aoedev *d) |
165 | { | 173 | { |
174 | struct frame *f, *e; | ||
175 | |||
166 | if (d->gd) { | 176 | if (d->gd) { |
167 | aoedisk_rm_sysfs(d); | 177 | aoedisk_rm_sysfs(d); |
168 | del_gendisk(d->gd); | 178 | del_gendisk(d->gd); |
169 | put_disk(d->gd); | 179 | put_disk(d->gd); |
170 | } | 180 | } |
181 | f = d->frames; | ||
182 | e = f + d->nframes; | ||
183 | for (; f<e; f++) { | ||
184 | skb_shinfo(f->skb)->nr_frags = 0; | ||
185 | dev_kfree_skb(f->skb); | ||
186 | } | ||
171 | kfree(d->frames); | 187 | kfree(d->frames); |
172 | if (d->bufpool) | 188 | if (d->bufpool) |
173 | mempool_destroy(d->bufpool); | 189 | mempool_destroy(d->bufpool); |
diff --git a/drivers/block/aoe/aoemain.c b/drivers/block/aoe/aoemain.c index de08491ebe66..a04b7d613299 100644 --- a/drivers/block/aoe/aoemain.c +++ b/drivers/block/aoe/aoemain.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */ | 1 | /* Copyright (c) 2006 Coraid, Inc. See COPYING for GPL terms. */ |
2 | /* | 2 | /* |
3 | * aoemain.c | 3 | * aoemain.c |
4 | * Module initialization routines, discover timer | 4 | * Module initialization routines, discover timer |
@@ -84,13 +84,11 @@ aoe_init(void) | |||
84 | goto net_fail; | 84 | goto net_fail; |
85 | ret = register_blkdev(AOE_MAJOR, DEVICE_NAME); | 85 | ret = register_blkdev(AOE_MAJOR, DEVICE_NAME); |
86 | if (ret < 0) { | 86 | if (ret < 0) { |
87 | printk(KERN_ERR "aoe: aoeblk_init: can't register major\n"); | 87 | printk(KERN_ERR "aoe: can't register major\n"); |
88 | goto blkreg_fail; | 88 | goto blkreg_fail; |
89 | } | 89 | } |
90 | 90 | ||
91 | printk(KERN_INFO | 91 | printk(KERN_INFO "aoe: AoE v%s initialised.\n", VERSION); |
92 | "aoe: aoe_init: AoE v%s initialised.\n", | ||
93 | VERSION); | ||
94 | discover_timer(TINIT); | 92 | discover_timer(TINIT); |
95 | return 0; | 93 | return 0; |
96 | 94 | ||
@@ -103,7 +101,7 @@ aoe_init(void) | |||
103 | chr_fail: | 101 | chr_fail: |
104 | aoedev_exit(); | 102 | aoedev_exit(); |
105 | 103 | ||
106 | printk(KERN_INFO "aoe: aoe_init: initialisation failure.\n"); | 104 | printk(KERN_INFO "aoe: initialisation failure.\n"); |
107 | return ret; | 105 | return ret; |
108 | } | 106 | } |
109 | 107 | ||
diff --git a/drivers/block/aoe/aoenet.c b/drivers/block/aoe/aoenet.c index c1434ed11880..9626e0f5da9d 100644 --- a/drivers/block/aoe/aoenet.c +++ b/drivers/block/aoe/aoenet.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */ | 1 | /* Copyright (c) 2006 Coraid, Inc. See COPYING for GPL terms. */ |
2 | /* | 2 | /* |
3 | * aoenet.c | 3 | * aoenet.c |
4 | * Ethernet portion of AoE driver | 4 | * Ethernet portion of AoE driver |
@@ -74,7 +74,7 @@ set_aoe_iflist(const char __user *user_str, size_t size) | |||
74 | return -EINVAL; | 74 | return -EINVAL; |
75 | 75 | ||
76 | if (copy_from_user(aoe_iflist, user_str, size)) { | 76 | if (copy_from_user(aoe_iflist, user_str, size)) { |
77 | printk(KERN_INFO "aoe: %s: copy from user failed\n", __FUNCTION__); | 77 | printk(KERN_INFO "aoe: copy from user failed\n"); |
78 | return -EFAULT; | 78 | return -EFAULT; |
79 | } | 79 | } |
80 | aoe_iflist[size] = 0x00; | 80 | aoe_iflist[size] = 0x00; |
@@ -132,8 +132,7 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, | |||
132 | if (n > NECODES) | 132 | if (n > NECODES) |
133 | n = 0; | 133 | n = 0; |
134 | if (net_ratelimit()) | 134 | if (net_ratelimit()) |
135 | printk(KERN_ERR "aoe: aoenet_rcv: error packet from %d.%d; " | 135 | printk(KERN_ERR "aoe: error packet from %d.%d; ecode=%d '%s'\n", |
136 | "ecode=%d '%s'\n", | ||
137 | be16_to_cpu(h->major), h->minor, | 136 | be16_to_cpu(h->major), h->minor, |
138 | h->err, aoe_errlist[n]); | 137 | h->err, aoe_errlist[n]); |
139 | goto exit; | 138 | goto exit; |
@@ -147,7 +146,7 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, | |||
147 | aoecmd_cfg_rsp(skb); | 146 | aoecmd_cfg_rsp(skb); |
148 | break; | 147 | break; |
149 | default: | 148 | default: |
150 | printk(KERN_INFO "aoe: aoenet_rcv: unknown cmd %d\n", h->cmd); | 149 | printk(KERN_INFO "aoe: unknown cmd %d\n", h->cmd); |
151 | } | 150 | } |
152 | exit: | 151 | exit: |
153 | dev_kfree_skb(skb); | 152 | dev_kfree_skb(skb); |
diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c index 51cb9f817c22..270a33cc08f6 100644 --- a/drivers/pci/hotplug/acpi_pcihp.c +++ b/drivers/pci/hotplug/acpi_pcihp.c | |||
@@ -29,10 +29,10 @@ | |||
29 | #include <linux/kernel.h> | 29 | #include <linux/kernel.h> |
30 | #include <linux/types.h> | 30 | #include <linux/types.h> |
31 | #include <linux/pci.h> | 31 | #include <linux/pci.h> |
32 | #include <linux/pci_hotplug.h> | ||
32 | #include <acpi/acpi.h> | 33 | #include <acpi/acpi.h> |
33 | #include <acpi/acpi_bus.h> | 34 | #include <acpi/acpi_bus.h> |
34 | #include <acpi/actypes.h> | 35 | #include <acpi/actypes.h> |
35 | #include "pci_hotplug.h" | ||
36 | 36 | ||
37 | #define MY_NAME "acpi_pcihp" | 37 | #define MY_NAME "acpi_pcihp" |
38 | 38 | ||
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index 7fff07e877c7..59c5b242d86d 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h | |||
@@ -38,7 +38,7 @@ | |||
38 | #include <linux/acpi.h> | 38 | #include <linux/acpi.h> |
39 | #include <linux/kobject.h> /* for KOBJ_NAME_LEN */ | 39 | #include <linux/kobject.h> /* for KOBJ_NAME_LEN */ |
40 | #include <linux/mutex.h> | 40 | #include <linux/mutex.h> |
41 | #include "pci_hotplug.h" | 41 | #include <linux/pci_hotplug.h> |
42 | 42 | ||
43 | #define dbg(format, arg...) \ | 43 | #define dbg(format, arg...) \ |
44 | do { \ | 44 | do { \ |
diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c index e2fef60c2d06..c57d9d5ce84e 100644 --- a/drivers/pci/hotplug/acpiphp_core.c +++ b/drivers/pci/hotplug/acpiphp_core.c | |||
@@ -37,10 +37,10 @@ | |||
37 | 37 | ||
38 | #include <linux/kernel.h> | 38 | #include <linux/kernel.h> |
39 | #include <linux/pci.h> | 39 | #include <linux/pci.h> |
40 | #include <linux/pci_hotplug.h> | ||
40 | #include <linux/slab.h> | 41 | #include <linux/slab.h> |
41 | #include <linux/smp.h> | 42 | #include <linux/smp.h> |
42 | #include <linux/smp_lock.h> | 43 | #include <linux/smp_lock.h> |
43 | #include "pci_hotplug.h" | ||
44 | #include "acpiphp.h" | 44 | #include "acpiphp.h" |
45 | 45 | ||
46 | #define MY_NAME "acpiphp" | 46 | #define MY_NAME "acpiphp" |
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 83e8e4412de5..c44311ac2fd3 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c | |||
@@ -45,11 +45,11 @@ | |||
45 | 45 | ||
46 | #include <linux/kernel.h> | 46 | #include <linux/kernel.h> |
47 | #include <linux/pci.h> | 47 | #include <linux/pci.h> |
48 | #include <linux/pci_hotplug.h> | ||
48 | #include <linux/smp_lock.h> | 49 | #include <linux/smp_lock.h> |
49 | #include <linux/mutex.h> | 50 | #include <linux/mutex.h> |
50 | 51 | ||
51 | #include "../pci.h" | 52 | #include "../pci.h" |
52 | #include "pci_hotplug.h" | ||
53 | #include "acpiphp.h" | 53 | #include "acpiphp.h" |
54 | 54 | ||
55 | static LIST_HEAD(bridge_list); | 55 | static LIST_HEAD(bridge_list); |
diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c index d0a07d9ab30c..bd40aee10e16 100644 --- a/drivers/pci/hotplug/acpiphp_ibm.c +++ b/drivers/pci/hotplug/acpiphp_ibm.c | |||
@@ -35,7 +35,6 @@ | |||
35 | #include <linux/moduleparam.h> | 35 | #include <linux/moduleparam.h> |
36 | 36 | ||
37 | #include "acpiphp.h" | 37 | #include "acpiphp.h" |
38 | #include "pci_hotplug.h" | ||
39 | 38 | ||
40 | #define DRIVER_VERSION "1.0.1" | 39 | #define DRIVER_VERSION "1.0.1" |
41 | #define DRIVER_AUTHOR "Irene Zubarev <zubarev@us.ibm.com>, Vernon Mauery <vernux@us.ibm.com>" | 40 | #define DRIVER_AUTHOR "Irene Zubarev <zubarev@us.ibm.com>, Vernon Mauery <vernux@us.ibm.com>" |
diff --git a/drivers/pci/hotplug/cpci_hotplug_core.c b/drivers/pci/hotplug/cpci_hotplug_core.c index d06ab4045134..684551559d44 100644 --- a/drivers/pci/hotplug/cpci_hotplug_core.c +++ b/drivers/pci/hotplug/cpci_hotplug_core.c | |||
@@ -29,12 +29,12 @@ | |||
29 | #include <linux/kernel.h> | 29 | #include <linux/kernel.h> |
30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
31 | #include <linux/pci.h> | 31 | #include <linux/pci.h> |
32 | #include <linux/pci_hotplug.h> | ||
32 | #include <linux/init.h> | 33 | #include <linux/init.h> |
33 | #include <linux/interrupt.h> | 34 | #include <linux/interrupt.h> |
34 | #include <linux/smp_lock.h> | 35 | #include <linux/smp_lock.h> |
35 | #include <asm/atomic.h> | 36 | #include <asm/atomic.h> |
36 | #include <linux/delay.h> | 37 | #include <linux/delay.h> |
37 | #include "pci_hotplug.h" | ||
38 | #include "cpci_hotplug.h" | 38 | #include "cpci_hotplug.h" |
39 | 39 | ||
40 | #define DRIVER_AUTHOR "Scott Murray <scottm@somanetworks.com>" | 40 | #define DRIVER_AUTHOR "Scott Murray <scottm@somanetworks.com>" |
diff --git a/drivers/pci/hotplug/cpci_hotplug_pci.c b/drivers/pci/hotplug/cpci_hotplug_pci.c index 4afcaffd031c..7b1beaad2752 100644 --- a/drivers/pci/hotplug/cpci_hotplug_pci.c +++ b/drivers/pci/hotplug/cpci_hotplug_pci.c | |||
@@ -26,9 +26,9 @@ | |||
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
28 | #include <linux/pci.h> | 28 | #include <linux/pci.h> |
29 | #include <linux/pci_hotplug.h> | ||
29 | #include <linux/proc_fs.h> | 30 | #include <linux/proc_fs.h> |
30 | #include "../pci.h" | 31 | #include "../pci.h" |
31 | #include "pci_hotplug.h" | ||
32 | #include "cpci_hotplug.h" | 32 | #include "cpci_hotplug.h" |
33 | 33 | ||
34 | #define MY_NAME "cpci_hotplug" | 34 | #define MY_NAME "cpci_hotplug" |
diff --git a/drivers/pci/hotplug/cpcihp_generic.c b/drivers/pci/hotplug/cpcihp_generic.c index e847f0d6c7fe..f3852a6b74ea 100644 --- a/drivers/pci/hotplug/cpcihp_generic.c +++ b/drivers/pci/hotplug/cpcihp_generic.c | |||
@@ -84,7 +84,7 @@ static int __init validate_parameters(void) | |||
84 | 84 | ||
85 | if(!bridge) { | 85 | if(!bridge) { |
86 | info("not configured, disabling."); | 86 | info("not configured, disabling."); |
87 | return 1; | 87 | return -EINVAL; |
88 | } | 88 | } |
89 | str = bridge; | 89 | str = bridge; |
90 | if(!*str) | 90 | if(!*str) |
@@ -147,7 +147,7 @@ static int __init cpcihp_generic_init(void) | |||
147 | 147 | ||
148 | info(DRIVER_DESC " version: " DRIVER_VERSION); | 148 | info(DRIVER_DESC " version: " DRIVER_VERSION); |
149 | status = validate_parameters(); | 149 | status = validate_parameters(); |
150 | if(status != 0) | 150 | if (status) |
151 | return status; | 151 | return status; |
152 | 152 | ||
153 | r = request_region(port, 1, "#ENUM hotswap signal register"); | 153 | r = request_region(port, 1, "#ENUM hotswap signal register"); |
diff --git a/drivers/pci/hotplug/cpqphp.h b/drivers/pci/hotplug/cpqphp.h index ea040c32f47d..298ad7f3f4f4 100644 --- a/drivers/pci/hotplug/cpqphp.h +++ b/drivers/pci/hotplug/cpqphp.h | |||
@@ -28,7 +28,6 @@ | |||
28 | #ifndef _CPQPHP_H | 28 | #ifndef _CPQPHP_H |
29 | #define _CPQPHP_H | 29 | #define _CPQPHP_H |
30 | 30 | ||
31 | #include "pci_hotplug.h" | ||
32 | #include <linux/interrupt.h> | 31 | #include <linux/interrupt.h> |
33 | #include <asm/io.h> /* for read? and write? functions */ | 32 | #include <asm/io.h> /* for read? and write? functions */ |
34 | #include <linux/delay.h> /* for delays */ | 33 | #include <linux/delay.h> /* for delays */ |
diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c index 1fc259913b68..5617cfdadc5c 100644 --- a/drivers/pci/hotplug/cpqphp_core.c +++ b/drivers/pci/hotplug/cpqphp_core.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/slab.h> | 37 | #include <linux/slab.h> |
38 | #include <linux/workqueue.h> | 38 | #include <linux/workqueue.h> |
39 | #include <linux/pci.h> | 39 | #include <linux/pci.h> |
40 | #include <linux/pci_hotplug.h> | ||
40 | #include <linux/init.h> | 41 | #include <linux/init.h> |
41 | #include <linux/interrupt.h> | 42 | #include <linux/interrupt.h> |
42 | 43 | ||
diff --git a/drivers/pci/hotplug/cpqphp_ctrl.c b/drivers/pci/hotplug/cpqphp_ctrl.c index 3ec2ad7db49a..79ff6b4de3a6 100644 --- a/drivers/pci/hotplug/cpqphp_ctrl.c +++ b/drivers/pci/hotplug/cpqphp_ctrl.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/wait.h> | 36 | #include <linux/wait.h> |
37 | #include <linux/smp_lock.h> | 37 | #include <linux/smp_lock.h> |
38 | #include <linux/pci.h> | 38 | #include <linux/pci.h> |
39 | #include <linux/pci_hotplug.h> | ||
39 | #include "cpqphp.h" | 40 | #include "cpqphp.h" |
40 | 41 | ||
41 | static u32 configure_new_device(struct controller* ctrl, struct pci_func *func, | 42 | static u32 configure_new_device(struct controller* ctrl, struct pci_func *func, |
diff --git a/drivers/pci/hotplug/cpqphp_nvram.c b/drivers/pci/hotplug/cpqphp_nvram.c index cf0878917537..298a6cfd8406 100644 --- a/drivers/pci/hotplug/cpqphp_nvram.c +++ b/drivers/pci/hotplug/cpqphp_nvram.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
34 | #include <linux/workqueue.h> | 34 | #include <linux/workqueue.h> |
35 | #include <linux/pci.h> | 35 | #include <linux/pci.h> |
36 | #include <linux/pci_hotplug.h> | ||
36 | #include <linux/init.h> | 37 | #include <linux/init.h> |
37 | #include <asm/uaccess.h> | 38 | #include <asm/uaccess.h> |
38 | #include "cpqphp.h" | 39 | #include "cpqphp.h" |
diff --git a/drivers/pci/hotplug/cpqphp_pci.c b/drivers/pci/hotplug/cpqphp_pci.c index 0d9688952f4a..fc7c74d72595 100644 --- a/drivers/pci/hotplug/cpqphp_pci.c +++ b/drivers/pci/hotplug/cpqphp_pci.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/workqueue.h> | 33 | #include <linux/workqueue.h> |
34 | #include <linux/proc_fs.h> | 34 | #include <linux/proc_fs.h> |
35 | #include <linux/pci.h> | 35 | #include <linux/pci.h> |
36 | #include <linux/pci_hotplug.h> | ||
36 | #include "../pci.h" | 37 | #include "../pci.h" |
37 | #include "cpqphp.h" | 38 | #include "cpqphp.h" |
38 | #include "cpqphp_nvram.h" | 39 | #include "cpqphp_nvram.h" |
diff --git a/drivers/pci/hotplug/cpqphp_sysfs.c b/drivers/pci/hotplug/cpqphp_sysfs.c index 5bab666cd67e..634f74d919d3 100644 --- a/drivers/pci/hotplug/cpqphp_sysfs.c +++ b/drivers/pci/hotplug/cpqphp_sysfs.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/proc_fs.h> | 32 | #include <linux/proc_fs.h> |
33 | #include <linux/workqueue.h> | 33 | #include <linux/workqueue.h> |
34 | #include <linux/pci.h> | 34 | #include <linux/pci.h> |
35 | #include <linux/pci_hotplug.h> | ||
35 | #include <linux/debugfs.h> | 36 | #include <linux/debugfs.h> |
36 | #include "cpqphp.h" | 37 | #include "cpqphp.h" |
37 | 38 | ||
diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c index 05a4f0f90186..e27907c91d92 100644 --- a/drivers/pci/hotplug/fakephp.c +++ b/drivers/pci/hotplug/fakephp.c | |||
@@ -35,10 +35,10 @@ | |||
35 | #include <linux/kernel.h> | 35 | #include <linux/kernel.h> |
36 | #include <linux/module.h> | 36 | #include <linux/module.h> |
37 | #include <linux/pci.h> | 37 | #include <linux/pci.h> |
38 | #include <linux/pci_hotplug.h> | ||
38 | #include <linux/init.h> | 39 | #include <linux/init.h> |
39 | #include <linux/string.h> | 40 | #include <linux/string.h> |
40 | #include <linux/slab.h> | 41 | #include <linux/slab.h> |
41 | #include "pci_hotplug.h" | ||
42 | #include "../pci.h" | 42 | #include "../pci.h" |
43 | 43 | ||
44 | #if !defined(MODULE) | 44 | #if !defined(MODULE) |
@@ -181,7 +181,9 @@ static void pci_rescan_slot(struct pci_dev *temp) | |||
181 | 181 | ||
182 | if (!pci_read_config_byte(temp, PCI_HEADER_TYPE, &hdr_type)) { | 182 | if (!pci_read_config_byte(temp, PCI_HEADER_TYPE, &hdr_type)) { |
183 | temp->hdr_type = hdr_type & 0x7f; | 183 | temp->hdr_type = hdr_type & 0x7f; |
184 | if (!pci_find_slot(bus->number, temp->devfn)) { | 184 | if ((dev = pci_get_slot(bus, temp->devfn)) != NULL) |
185 | pci_dev_put(dev); | ||
186 | else { | ||
185 | dev = pci_scan_single_device(bus, temp->devfn); | 187 | dev = pci_scan_single_device(bus, temp->devfn); |
186 | if (dev) { | 188 | if (dev) { |
187 | dbg("New device on %s function %x:%x\n", | 189 | dbg("New device on %s function %x:%x\n", |
@@ -205,7 +207,9 @@ static void pci_rescan_slot(struct pci_dev *temp) | |||
205 | continue; | 207 | continue; |
206 | temp->hdr_type = hdr_type & 0x7f; | 208 | temp->hdr_type = hdr_type & 0x7f; |
207 | 209 | ||
208 | if (!pci_find_slot(bus->number, temp->devfn)) { | 210 | if ((dev = pci_get_slot(bus, temp->devfn)) != NULL) |
211 | pci_dev_put(dev); | ||
212 | else { | ||
209 | dev = pci_scan_single_device(bus, temp->devfn); | 213 | dev = pci_scan_single_device(bus, temp->devfn); |
210 | if (dev) { | 214 | if (dev) { |
211 | dbg("New device on %s function %x:%x\n", | 215 | dbg("New device on %s function %x:%x\n", |
@@ -305,7 +309,7 @@ static int disable_slot(struct hotplug_slot *slot) | |||
305 | /* search for subfunctions and disable them first */ | 309 | /* search for subfunctions and disable them first */ |
306 | if (!(dslot->dev->devfn & 7)) { | 310 | if (!(dslot->dev->devfn & 7)) { |
307 | for (func = 1; func < 8; func++) { | 311 | for (func = 1; func < 8; func++) { |
308 | dev = pci_find_slot(dslot->dev->bus->number, | 312 | dev = pci_get_slot(dslot->dev->bus, |
309 | dslot->dev->devfn + func); | 313 | dslot->dev->devfn + func); |
310 | if (dev) { | 314 | if (dev) { |
311 | hslot = get_slot_from_dev(dev); | 315 | hslot = get_slot_from_dev(dev); |
@@ -315,6 +319,7 @@ static int disable_slot(struct hotplug_slot *slot) | |||
315 | err("Hotplug slot not found for subfunction of PCI device\n"); | 319 | err("Hotplug slot not found for subfunction of PCI device\n"); |
316 | return -ENODEV; | 320 | return -ENODEV; |
317 | } | 321 | } |
322 | pci_dev_put(dev); | ||
318 | } else | 323 | } else |
319 | dbg("No device in slot found\n"); | 324 | dbg("No device in slot found\n"); |
320 | } | 325 | } |
diff --git a/drivers/pci/hotplug/ibmphp.h b/drivers/pci/hotplug/ibmphp.h index dba6d8ca9bda..612d96301509 100644 --- a/drivers/pci/hotplug/ibmphp.h +++ b/drivers/pci/hotplug/ibmphp.h | |||
@@ -30,7 +30,7 @@ | |||
30 | * | 30 | * |
31 | */ | 31 | */ |
32 | 32 | ||
33 | #include "pci_hotplug.h" | 33 | #include <linux/pci_hotplug.h> |
34 | 34 | ||
35 | extern int ibmphp_debug; | 35 | extern int ibmphp_debug; |
36 | 36 | ||
diff --git a/drivers/pci/hotplug/pci_hotplug.h b/drivers/pci/hotplug/pci_hotplug.h deleted file mode 100644 index 772523dc3860..000000000000 --- a/drivers/pci/hotplug/pci_hotplug.h +++ /dev/null | |||
@@ -1,236 +0,0 @@ | |||
1 | /* | ||
2 | * PCI HotPlug Core Functions | ||
3 | * | ||
4 | * Copyright (C) 1995,2001 Compaq Computer Corporation | ||
5 | * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) | ||
6 | * Copyright (C) 2001 IBM Corp. | ||
7 | * | ||
8 | * All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or (at | ||
13 | * your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, but | ||
16 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
18 | * NON INFRINGEMENT. See the GNU General Public License for more | ||
19 | * details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | * | ||
25 | * Send feedback to <greg@kroah.com> | ||
26 | * | ||
27 | */ | ||
28 | #ifndef _PCI_HOTPLUG_H | ||
29 | #define _PCI_HOTPLUG_H | ||
30 | |||
31 | |||
32 | /* These values come from the PCI Hotplug Spec */ | ||
33 | enum pci_bus_speed { | ||
34 | PCI_SPEED_33MHz = 0x00, | ||
35 | PCI_SPEED_66MHz = 0x01, | ||
36 | PCI_SPEED_66MHz_PCIX = 0x02, | ||
37 | PCI_SPEED_100MHz_PCIX = 0x03, | ||
38 | PCI_SPEED_133MHz_PCIX = 0x04, | ||
39 | PCI_SPEED_66MHz_PCIX_ECC = 0x05, | ||
40 | PCI_SPEED_100MHz_PCIX_ECC = 0x06, | ||
41 | PCI_SPEED_133MHz_PCIX_ECC = 0x07, | ||
42 | PCI_SPEED_66MHz_PCIX_266 = 0x09, | ||
43 | PCI_SPEED_100MHz_PCIX_266 = 0x0a, | ||
44 | PCI_SPEED_133MHz_PCIX_266 = 0x0b, | ||
45 | PCI_SPEED_66MHz_PCIX_533 = 0x11, | ||
46 | PCI_SPEED_100MHz_PCIX_533 = 0x12, | ||
47 | PCI_SPEED_133MHz_PCIX_533 = 0x13, | ||
48 | PCI_SPEED_UNKNOWN = 0xff, | ||
49 | }; | ||
50 | |||
51 | /* These values come from the PCI Express Spec */ | ||
52 | enum pcie_link_width { | ||
53 | PCIE_LNK_WIDTH_RESRV = 0x00, | ||
54 | PCIE_LNK_X1 = 0x01, | ||
55 | PCIE_LNK_X2 = 0x02, | ||
56 | PCIE_LNK_X4 = 0x04, | ||
57 | PCIE_LNK_X8 = 0x08, | ||
58 | PCIE_LNK_X12 = 0x0C, | ||
59 | PCIE_LNK_X16 = 0x10, | ||
60 | PCIE_LNK_X32 = 0x20, | ||
61 | PCIE_LNK_WIDTH_UNKNOWN = 0xFF, | ||
62 | }; | ||
63 | |||
64 | enum pcie_link_speed { | ||
65 | PCIE_2PT5GB = 0x14, | ||
66 | PCIE_LNK_SPEED_UNKNOWN = 0xFF, | ||
67 | }; | ||
68 | |||
69 | struct hotplug_slot; | ||
70 | struct hotplug_slot_attribute { | ||
71 | struct attribute attr; | ||
72 | ssize_t (*show)(struct hotplug_slot *, char *); | ||
73 | ssize_t (*store)(struct hotplug_slot *, const char *, size_t); | ||
74 | }; | ||
75 | #define to_hotplug_attr(n) container_of(n, struct hotplug_slot_attribute, attr); | ||
76 | |||
77 | /** | ||
78 | * struct hotplug_slot_ops -the callbacks that the hotplug pci core can use | ||
79 | * @owner: The module owner of this structure | ||
80 | * @enable_slot: Called when the user wants to enable a specific pci slot | ||
81 | * @disable_slot: Called when the user wants to disable a specific pci slot | ||
82 | * @set_attention_status: Called to set the specific slot's attention LED to | ||
83 | * the specified value | ||
84 | * @hardware_test: Called to run a specified hardware test on the specified | ||
85 | * slot. | ||
86 | * @get_power_status: Called to get the current power status of a slot. | ||
87 | * If this field is NULL, the value passed in the struct hotplug_slot_info | ||
88 | * will be used when this value is requested by a user. | ||
89 | * @get_attention_status: Called to get the current attention status of a slot. | ||
90 | * If this field is NULL, the value passed in the struct hotplug_slot_info | ||
91 | * will be used when this value is requested by a user. | ||
92 | * @get_latch_status: Called to get the current latch status of a slot. | ||
93 | * If this field is NULL, the value passed in the struct hotplug_slot_info | ||
94 | * will be used when this value is requested by a user. | ||
95 | * @get_adapter_status: Called to get see if an adapter is present in the slot or not. | ||
96 | * If this field is NULL, the value passed in the struct hotplug_slot_info | ||
97 | * will be used when this value is requested by a user. | ||
98 | * @get_address: Called to get pci address of a slot. | ||
99 | * If this field is NULL, the value passed in the struct hotplug_slot_info | ||
100 | * will be used when this value is requested by a user. | ||
101 | * @get_max_bus_speed: Called to get the max bus speed for a slot. | ||
102 | * If this field is NULL, the value passed in the struct hotplug_slot_info | ||
103 | * will be used when this value is requested by a user. | ||
104 | * @get_cur_bus_speed: Called to get the current bus speed for a slot. | ||
105 | * If this field is NULL, the value passed in the struct hotplug_slot_info | ||
106 | * will be used when this value is requested by a user. | ||
107 | * | ||
108 | * The table of function pointers that is passed to the hotplug pci core by a | ||
109 | * hotplug pci driver. These functions are called by the hotplug pci core when | ||
110 | * the user wants to do something to a specific slot (query it for information, | ||
111 | * set an LED, enable / disable power, etc.) | ||
112 | */ | ||
113 | struct hotplug_slot_ops { | ||
114 | struct module *owner; | ||
115 | int (*enable_slot) (struct hotplug_slot *slot); | ||
116 | int (*disable_slot) (struct hotplug_slot *slot); | ||
117 | int (*set_attention_status) (struct hotplug_slot *slot, u8 value); | ||
118 | int (*hardware_test) (struct hotplug_slot *slot, u32 value); | ||
119 | int (*get_power_status) (struct hotplug_slot *slot, u8 *value); | ||
120 | int (*get_attention_status) (struct hotplug_slot *slot, u8 *value); | ||
121 | int (*get_latch_status) (struct hotplug_slot *slot, u8 *value); | ||
122 | int (*get_adapter_status) (struct hotplug_slot *slot, u8 *value); | ||
123 | int (*get_address) (struct hotplug_slot *slot, u32 *value); | ||
124 | int (*get_max_bus_speed) (struct hotplug_slot *slot, enum pci_bus_speed *value); | ||
125 | int (*get_cur_bus_speed) (struct hotplug_slot *slot, enum pci_bus_speed *value); | ||
126 | }; | ||
127 | |||
128 | /** | ||
129 | * struct hotplug_slot_info - used to notify the hotplug pci core of the state of the slot | ||
130 | * @power: if power is enabled or not (1/0) | ||
131 | * @attention_status: if the attention light is enabled or not (1/0) | ||
132 | * @latch_status: if the latch (if any) is open or closed (1/0) | ||
133 | * @adapter_present: if there is a pci board present in the slot or not (1/0) | ||
134 | * @address: (domain << 16 | bus << 8 | dev) | ||
135 | * | ||
136 | * Used to notify the hotplug pci core of the status of a specific slot. | ||
137 | */ | ||
138 | struct hotplug_slot_info { | ||
139 | u8 power_status; | ||
140 | u8 attention_status; | ||
141 | u8 latch_status; | ||
142 | u8 adapter_status; | ||
143 | u32 address; | ||
144 | enum pci_bus_speed max_bus_speed; | ||
145 | enum pci_bus_speed cur_bus_speed; | ||
146 | }; | ||
147 | |||
148 | /** | ||
149 | * struct hotplug_slot - used to register a physical slot with the hotplug pci core | ||
150 | * @name: the name of the slot being registered. This string must | ||
151 | * be unique amoung slots registered on this system. | ||
152 | * @ops: pointer to the &struct hotplug_slot_ops to be used for this slot | ||
153 | * @info: pointer to the &struct hotplug_slot_info for the initial values for | ||
154 | * this slot. | ||
155 | * @release: called during pci_hp_deregister to free memory allocated in a | ||
156 | * hotplug_slot structure. | ||
157 | * @private: used by the hotplug pci controller driver to store whatever it | ||
158 | * needs. | ||
159 | */ | ||
160 | struct hotplug_slot { | ||
161 | char *name; | ||
162 | struct hotplug_slot_ops *ops; | ||
163 | struct hotplug_slot_info *info; | ||
164 | void (*release) (struct hotplug_slot *slot); | ||
165 | void *private; | ||
166 | |||
167 | /* Variables below this are for use only by the hotplug pci core. */ | ||
168 | struct list_head slot_list; | ||
169 | struct kobject kobj; | ||
170 | }; | ||
171 | #define to_hotplug_slot(n) container_of(n, struct hotplug_slot, kobj) | ||
172 | |||
173 | extern int pci_hp_register (struct hotplug_slot *slot); | ||
174 | extern int pci_hp_deregister (struct hotplug_slot *slot); | ||
175 | extern int __must_check pci_hp_change_slot_info (struct hotplug_slot *slot, | ||
176 | struct hotplug_slot_info *info); | ||
177 | extern struct subsystem pci_hotplug_slots_subsys; | ||
178 | |||
179 | /* PCI Setting Record (Type 0) */ | ||
180 | struct hpp_type0 { | ||
181 | u32 revision; | ||
182 | u8 cache_line_size; | ||
183 | u8 latency_timer; | ||
184 | u8 enable_serr; | ||
185 | u8 enable_perr; | ||
186 | }; | ||
187 | |||
188 | /* PCI-X Setting Record (Type 1) */ | ||
189 | struct hpp_type1 { | ||
190 | u32 revision; | ||
191 | u8 max_mem_read; | ||
192 | u8 avg_max_split; | ||
193 | u16 tot_max_split; | ||
194 | }; | ||
195 | |||
196 | /* PCI Express Setting Record (Type 2) */ | ||
197 | struct hpp_type2 { | ||
198 | u32 revision; | ||
199 | u32 unc_err_mask_and; | ||
200 | u32 unc_err_mask_or; | ||
201 | u32 unc_err_sever_and; | ||
202 | u32 unc_err_sever_or; | ||
203 | u32 cor_err_mask_and; | ||
204 | u32 cor_err_mask_or; | ||
205 | u32 adv_err_cap_and; | ||
206 | u32 adv_err_cap_or; | ||
207 | u16 pci_exp_devctl_and; | ||
208 | u16 pci_exp_devctl_or; | ||
209 | u16 pci_exp_lnkctl_and; | ||
210 | u16 pci_exp_lnkctl_or; | ||
211 | u32 sec_unc_err_sever_and; | ||
212 | u32 sec_unc_err_sever_or; | ||
213 | u32 sec_unc_err_mask_and; | ||
214 | u32 sec_unc_err_mask_or; | ||
215 | }; | ||
216 | |||
217 | struct hotplug_params { | ||
218 | struct hpp_type0 *t0; /* Type0: NULL if not available */ | ||
219 | struct hpp_type1 *t1; /* Type1: NULL if not available */ | ||
220 | struct hpp_type2 *t2; /* Type2: NULL if not available */ | ||
221 | struct hpp_type0 type0_data; | ||
222 | struct hpp_type1 type1_data; | ||
223 | struct hpp_type2 type2_data; | ||
224 | }; | ||
225 | |||
226 | #ifdef CONFIG_ACPI | ||
227 | #include <acpi/acpi.h> | ||
228 | #include <acpi/acpi_bus.h> | ||
229 | #include <acpi/actypes.h> | ||
230 | extern acpi_status acpi_run_oshp(acpi_handle handle); | ||
231 | extern acpi_status acpi_get_hp_params_from_firmware(struct pci_bus *bus, | ||
232 | struct hotplug_params *hpp); | ||
233 | int acpi_root_bridge(acpi_handle handle); | ||
234 | #endif | ||
235 | #endif | ||
236 | |||
diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c index e2823ea9c4ed..f5d632e72323 100644 --- a/drivers/pci/hotplug/pci_hotplug_core.c +++ b/drivers/pci/hotplug/pci_hotplug_core.c | |||
@@ -21,9 +21,7 @@ | |||
21 | * along with this program; if not, write to the Free Software | 21 | * along with this program; if not, write to the Free Software |
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
23 | * | 23 | * |
24 | * Send feedback to <greg@kroah.com> | 24 | * Send feedback to <kristen.c.accardi@intel.com> |
25 | * | ||
26 | * Filesystem portion based on work done by Pat Mochel on ddfs/driverfs | ||
27 | * | 25 | * |
28 | */ | 26 | */ |
29 | 27 | ||
@@ -32,6 +30,8 @@ | |||
32 | #include <linux/kernel.h> | 30 | #include <linux/kernel.h> |
33 | #include <linux/types.h> | 31 | #include <linux/types.h> |
34 | #include <linux/list.h> | 32 | #include <linux/list.h> |
33 | #include <linux/kobject.h> | ||
34 | #include <linux/sysfs.h> | ||
35 | #include <linux/pagemap.h> | 35 | #include <linux/pagemap.h> |
36 | #include <linux/slab.h> | 36 | #include <linux/slab.h> |
37 | #include <linux/smp_lock.h> | 37 | #include <linux/smp_lock.h> |
@@ -39,11 +39,8 @@ | |||
39 | #include <linux/mount.h> | 39 | #include <linux/mount.h> |
40 | #include <linux/namei.h> | 40 | #include <linux/namei.h> |
41 | #include <linux/pci.h> | 41 | #include <linux/pci.h> |
42 | #include <linux/pci_hotplug.h> | ||
42 | #include <asm/uaccess.h> | 43 | #include <asm/uaccess.h> |
43 | #include <linux/kobject.h> | ||
44 | #include <linux/sysfs.h> | ||
45 | #include "pci_hotplug.h" | ||
46 | |||
47 | 44 | ||
48 | #define MY_NAME "pci_hotplug" | 45 | #define MY_NAME "pci_hotplug" |
49 | 46 | ||
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index eaea9d36a1bb..4fb12fcda563 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h | |||
@@ -31,11 +31,11 @@ | |||
31 | 31 | ||
32 | #include <linux/types.h> | 32 | #include <linux/types.h> |
33 | #include <linux/pci.h> | 33 | #include <linux/pci.h> |
34 | #include <linux/pci_hotplug.h> | ||
34 | #include <linux/delay.h> | 35 | #include <linux/delay.h> |
35 | #include <linux/sched.h> /* signal_pending() */ | 36 | #include <linux/sched.h> /* signal_pending() */ |
36 | #include <linux/pcieport_if.h> | 37 | #include <linux/pcieport_if.h> |
37 | #include <linux/mutex.h> | 38 | #include <linux/mutex.h> |
38 | #include "pci_hotplug.h" | ||
39 | 39 | ||
40 | #define MY_NAME "pciehp" | 40 | #define MY_NAME "pciehp" |
41 | 41 | ||
@@ -92,6 +92,7 @@ struct php_ctlr_state_s { | |||
92 | struct controller { | 92 | struct controller { |
93 | struct controller *next; | 93 | struct controller *next; |
94 | struct mutex crit_sect; /* critical section mutex */ | 94 | struct mutex crit_sect; /* critical section mutex */ |
95 | struct mutex ctrl_lock; /* controller lock */ | ||
95 | struct php_ctlr_state_s *hpc_ctlr_handle; /* HPC controller handle */ | 96 | struct php_ctlr_state_s *hpc_ctlr_handle; /* HPC controller handle */ |
96 | int num_slots; /* Number of slots on ctlr */ | 97 | int num_slots; /* Number of slots on ctlr */ |
97 | int slot_num_inc; /* 1 or -1 */ | 98 | int slot_num_inc; /* 1 or -1 */ |
@@ -166,10 +167,10 @@ struct controller { | |||
166 | * error Messages | 167 | * error Messages |
167 | */ | 168 | */ |
168 | #define msg_initialization_err "Initialization failure, error=%d\n" | 169 | #define msg_initialization_err "Initialization failure, error=%d\n" |
169 | #define msg_button_on "PCI slot #%d - powering on due to button press.\n" | 170 | #define msg_button_on "PCI slot #%s - powering on due to button press.\n" |
170 | #define msg_button_off "PCI slot #%d - powering off due to button press.\n" | 171 | #define msg_button_off "PCI slot #%s - powering off due to button press.\n" |
171 | #define msg_button_cancel "PCI slot #%d - action canceled due to button press.\n" | 172 | #define msg_button_cancel "PCI slot #%s - action canceled due to button press.\n" |
172 | #define msg_button_ignore "PCI slot #%d - button press ignored. (action in progress...)\n" | 173 | #define msg_button_ignore "PCI slot #%s - button press ignored. (action in progress...)\n" |
173 | 174 | ||
174 | /* controller functions */ | 175 | /* controller functions */ |
175 | extern int pciehp_event_start_thread (void); | 176 | extern int pciehp_event_start_thread (void); |
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index c67b7c3f1ddf..f93e81e2d2c7 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c | |||
@@ -448,7 +448,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ | |||
448 | } | 448 | } |
449 | 449 | ||
450 | /* Wait for exclusive access to hardware */ | 450 | /* Wait for exclusive access to hardware */ |
451 | mutex_lock(&ctrl->crit_sect); | 451 | mutex_lock(&ctrl->ctrl_lock); |
452 | 452 | ||
453 | t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */ | 453 | t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */ |
454 | 454 | ||
@@ -456,7 +456,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ | |||
456 | rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/ | 456 | rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/ |
457 | if (rc) { | 457 | if (rc) { |
458 | /* Done with exclusive hardware access */ | 458 | /* Done with exclusive hardware access */ |
459 | mutex_unlock(&ctrl->crit_sect); | 459 | mutex_unlock(&ctrl->ctrl_lock); |
460 | goto err_out_free_ctrl_slot; | 460 | goto err_out_free_ctrl_slot; |
461 | } else | 461 | } else |
462 | /* Wait for the command to complete */ | 462 | /* Wait for the command to complete */ |
@@ -464,7 +464,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ | |||
464 | } | 464 | } |
465 | 465 | ||
466 | /* Done with exclusive hardware access */ | 466 | /* Done with exclusive hardware access */ |
467 | mutex_unlock(&ctrl->crit_sect); | 467 | mutex_unlock(&ctrl->ctrl_lock); |
468 | 468 | ||
469 | return 0; | 469 | return 0; |
470 | 470 | ||
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 41290a106bd8..372c63e35aa9 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c | |||
@@ -43,6 +43,11 @@ static int event_finished; | |||
43 | static unsigned long pushbutton_pending; /* = 0 */ | 43 | static unsigned long pushbutton_pending; /* = 0 */ |
44 | static unsigned long surprise_rm_pending; /* = 0 */ | 44 | static unsigned long surprise_rm_pending; /* = 0 */ |
45 | 45 | ||
46 | static inline char *slot_name(struct slot *p_slot) | ||
47 | { | ||
48 | return p_slot->hotplug_slot->name; | ||
49 | } | ||
50 | |||
46 | u8 pciehp_handle_attention_button(u8 hp_slot, void *inst_id) | 51 | u8 pciehp_handle_attention_button(u8 hp_slot, void *inst_id) |
47 | { | 52 | { |
48 | struct controller *ctrl = (struct controller *) inst_id; | 53 | struct controller *ctrl = (struct controller *) inst_id; |
@@ -68,7 +73,7 @@ u8 pciehp_handle_attention_button(u8 hp_slot, void *inst_id) | |||
68 | /* | 73 | /* |
69 | * Button pressed - See if need to TAKE ACTION!!! | 74 | * Button pressed - See if need to TAKE ACTION!!! |
70 | */ | 75 | */ |
71 | info("Button pressed on Slot(%d)\n", ctrl->first_slot + hp_slot); | 76 | info("Button pressed on Slot(%s)\n", slot_name(p_slot)); |
72 | taskInfo->event_type = INT_BUTTON_PRESS; | 77 | taskInfo->event_type = INT_BUTTON_PRESS; |
73 | 78 | ||
74 | if ((p_slot->state == BLINKINGON_STATE) | 79 | if ((p_slot->state == BLINKINGON_STATE) |
@@ -78,7 +83,7 @@ u8 pciehp_handle_attention_button(u8 hp_slot, void *inst_id) | |||
78 | * or hot-remove | 83 | * or hot-remove |
79 | */ | 84 | */ |
80 | taskInfo->event_type = INT_BUTTON_CANCEL; | 85 | taskInfo->event_type = INT_BUTTON_CANCEL; |
81 | info("Button cancel on Slot(%d)\n", ctrl->first_slot + hp_slot); | 86 | info("Button cancel on Slot(%s)\n", slot_name(p_slot)); |
82 | } else if ((p_slot->state == POWERON_STATE) | 87 | } else if ((p_slot->state == POWERON_STATE) |
83 | || (p_slot->state == POWEROFF_STATE)) { | 88 | || (p_slot->state == POWEROFF_STATE)) { |
84 | /* Ignore if the slot is on power-on or power-off state; this | 89 | /* Ignore if the slot is on power-on or power-off state; this |
@@ -86,7 +91,7 @@ u8 pciehp_handle_attention_button(u8 hp_slot, void *inst_id) | |||
86 | * hot-remove is undergoing | 91 | * hot-remove is undergoing |
87 | */ | 92 | */ |
88 | taskInfo->event_type = INT_BUTTON_IGNORE; | 93 | taskInfo->event_type = INT_BUTTON_IGNORE; |
89 | info("Button ignore on Slot(%d)\n", ctrl->first_slot + hp_slot); | 94 | info("Button ignore on Slot(%s)\n", slot_name(p_slot)); |
90 | } | 95 | } |
91 | 96 | ||
92 | if (rc) | 97 | if (rc) |
@@ -122,13 +127,13 @@ u8 pciehp_handle_switch_change(u8 hp_slot, void *inst_id) | |||
122 | /* | 127 | /* |
123 | * Switch opened | 128 | * Switch opened |
124 | */ | 129 | */ |
125 | info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot); | 130 | info("Latch open on Slot(%s)\n", slot_name(p_slot)); |
126 | taskInfo->event_type = INT_SWITCH_OPEN; | 131 | taskInfo->event_type = INT_SWITCH_OPEN; |
127 | } else { | 132 | } else { |
128 | /* | 133 | /* |
129 | * Switch closed | 134 | * Switch closed |
130 | */ | 135 | */ |
131 | info("Latch close on Slot(%d)\n", ctrl->first_slot + hp_slot); | 136 | info("Latch close on Slot(%s)\n", slot_name(p_slot)); |
132 | taskInfo->event_type = INT_SWITCH_CLOSE; | 137 | taskInfo->event_type = INT_SWITCH_CLOSE; |
133 | } | 138 | } |
134 | 139 | ||
@@ -166,13 +171,13 @@ u8 pciehp_handle_presence_change(u8 hp_slot, void *inst_id) | |||
166 | /* | 171 | /* |
167 | * Card Present | 172 | * Card Present |
168 | */ | 173 | */ |
169 | info("Card present on Slot(%d)\n", ctrl->first_slot + hp_slot); | 174 | info("Card present on Slot(%s)\n", slot_name(p_slot)); |
170 | taskInfo->event_type = INT_PRESENCE_ON; | 175 | taskInfo->event_type = INT_PRESENCE_ON; |
171 | } else { | 176 | } else { |
172 | /* | 177 | /* |
173 | * Not Present | 178 | * Not Present |
174 | */ | 179 | */ |
175 | info("Card not present on Slot(%d)\n", ctrl->first_slot + hp_slot); | 180 | info("Card not present on Slot(%s)\n", slot_name(p_slot)); |
176 | taskInfo->event_type = INT_PRESENCE_OFF; | 181 | taskInfo->event_type = INT_PRESENCE_OFF; |
177 | } | 182 | } |
178 | 183 | ||
@@ -206,13 +211,13 @@ u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id) | |||
206 | /* | 211 | /* |
207 | * power fault Cleared | 212 | * power fault Cleared |
208 | */ | 213 | */ |
209 | info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot); | 214 | info("Power fault cleared on Slot(%s)\n", slot_name(p_slot)); |
210 | taskInfo->event_type = INT_POWER_FAULT_CLEAR; | 215 | taskInfo->event_type = INT_POWER_FAULT_CLEAR; |
211 | } else { | 216 | } else { |
212 | /* | 217 | /* |
213 | * power fault | 218 | * power fault |
214 | */ | 219 | */ |
215 | info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot); | 220 | info("Power fault on Slot(%s)\n", slot_name(p_slot)); |
216 | taskInfo->event_type = INT_POWER_FAULT; | 221 | taskInfo->event_type = INT_POWER_FAULT; |
217 | info("power fault bit %x set\n", hp_slot); | 222 | info("power fault bit %x set\n", hp_slot); |
218 | } | 223 | } |
@@ -229,13 +234,13 @@ u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id) | |||
229 | static void set_slot_off(struct controller *ctrl, struct slot * pslot) | 234 | static void set_slot_off(struct controller *ctrl, struct slot * pslot) |
230 | { | 235 | { |
231 | /* Wait for exclusive access to hardware */ | 236 | /* Wait for exclusive access to hardware */ |
232 | mutex_lock(&ctrl->crit_sect); | 237 | mutex_lock(&ctrl->ctrl_lock); |
233 | 238 | ||
234 | /* turn off slot, turn on Amber LED, turn off Green LED if supported*/ | 239 | /* turn off slot, turn on Amber LED, turn off Green LED if supported*/ |
235 | if (POWER_CTRL(ctrl->ctrlcap)) { | 240 | if (POWER_CTRL(ctrl->ctrlcap)) { |
236 | if (pslot->hpc_ops->power_off_slot(pslot)) { | 241 | if (pslot->hpc_ops->power_off_slot(pslot)) { |
237 | err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__); | 242 | err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__); |
238 | mutex_unlock(&ctrl->crit_sect); | 243 | mutex_unlock(&ctrl->ctrl_lock); |
239 | return; | 244 | return; |
240 | } | 245 | } |
241 | wait_for_ctrl_irq (ctrl); | 246 | wait_for_ctrl_irq (ctrl); |
@@ -249,14 +254,14 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot) | |||
249 | if (ATTN_LED(ctrl->ctrlcap)) { | 254 | if (ATTN_LED(ctrl->ctrlcap)) { |
250 | if (pslot->hpc_ops->set_attention_status(pslot, 1)) { | 255 | if (pslot->hpc_ops->set_attention_status(pslot, 1)) { |
251 | err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__); | 256 | err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__); |
252 | mutex_unlock(&ctrl->crit_sect); | 257 | mutex_unlock(&ctrl->ctrl_lock); |
253 | return; | 258 | return; |
254 | } | 259 | } |
255 | wait_for_ctrl_irq (ctrl); | 260 | wait_for_ctrl_irq (ctrl); |
256 | } | 261 | } |
257 | 262 | ||
258 | /* Done with exclusive hardware access */ | 263 | /* Done with exclusive hardware access */ |
259 | mutex_unlock(&ctrl->crit_sect); | 264 | mutex_unlock(&ctrl->ctrl_lock); |
260 | } | 265 | } |
261 | 266 | ||
262 | /** | 267 | /** |
@@ -279,13 +284,13 @@ static int board_added(struct slot *p_slot) | |||
279 | ctrl->slot_device_offset, hp_slot); | 284 | ctrl->slot_device_offset, hp_slot); |
280 | 285 | ||
281 | /* Wait for exclusive access to hardware */ | 286 | /* Wait for exclusive access to hardware */ |
282 | mutex_lock(&ctrl->crit_sect); | 287 | mutex_lock(&ctrl->ctrl_lock); |
283 | 288 | ||
284 | if (POWER_CTRL(ctrl->ctrlcap)) { | 289 | if (POWER_CTRL(ctrl->ctrlcap)) { |
285 | /* Power on slot */ | 290 | /* Power on slot */ |
286 | rc = p_slot->hpc_ops->power_on_slot(p_slot); | 291 | rc = p_slot->hpc_ops->power_on_slot(p_slot); |
287 | if (rc) { | 292 | if (rc) { |
288 | mutex_unlock(&ctrl->crit_sect); | 293 | mutex_unlock(&ctrl->ctrl_lock); |
289 | return -1; | 294 | return -1; |
290 | } | 295 | } |
291 | 296 | ||
@@ -301,7 +306,7 @@ static int board_added(struct slot *p_slot) | |||
301 | } | 306 | } |
302 | 307 | ||
303 | /* Done with exclusive hardware access */ | 308 | /* Done with exclusive hardware access */ |
304 | mutex_unlock(&ctrl->crit_sect); | 309 | mutex_unlock(&ctrl->ctrl_lock); |
305 | 310 | ||
306 | /* Wait for ~1 second */ | 311 | /* Wait for ~1 second */ |
307 | wait_for_ctrl_irq (ctrl); | 312 | wait_for_ctrl_irq (ctrl); |
@@ -335,7 +340,7 @@ static int board_added(struct slot *p_slot) | |||
335 | pci_fixup_device(pci_fixup_final, ctrl->pci_dev); | 340 | pci_fixup_device(pci_fixup_final, ctrl->pci_dev); |
336 | if (PWR_LED(ctrl->ctrlcap)) { | 341 | if (PWR_LED(ctrl->ctrlcap)) { |
337 | /* Wait for exclusive access to hardware */ | 342 | /* Wait for exclusive access to hardware */ |
338 | mutex_lock(&ctrl->crit_sect); | 343 | mutex_lock(&ctrl->ctrl_lock); |
339 | 344 | ||
340 | p_slot->hpc_ops->green_led_on(p_slot); | 345 | p_slot->hpc_ops->green_led_on(p_slot); |
341 | 346 | ||
@@ -343,7 +348,7 @@ static int board_added(struct slot *p_slot) | |||
343 | wait_for_ctrl_irq (ctrl); | 348 | wait_for_ctrl_irq (ctrl); |
344 | 349 | ||
345 | /* Done with exclusive hardware access */ | 350 | /* Done with exclusive hardware access */ |
346 | mutex_unlock(&ctrl->crit_sect); | 351 | mutex_unlock(&ctrl->ctrl_lock); |
347 | } | 352 | } |
348 | return 0; | 353 | return 0; |
349 | 354 | ||
@@ -375,14 +380,14 @@ static int remove_board(struct slot *p_slot) | |||
375 | dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot); | 380 | dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot); |
376 | 381 | ||
377 | /* Wait for exclusive access to hardware */ | 382 | /* Wait for exclusive access to hardware */ |
378 | mutex_lock(&ctrl->crit_sect); | 383 | mutex_lock(&ctrl->ctrl_lock); |
379 | 384 | ||
380 | if (POWER_CTRL(ctrl->ctrlcap)) { | 385 | if (POWER_CTRL(ctrl->ctrlcap)) { |
381 | /* power off slot */ | 386 | /* power off slot */ |
382 | rc = p_slot->hpc_ops->power_off_slot(p_slot); | 387 | rc = p_slot->hpc_ops->power_off_slot(p_slot); |
383 | if (rc) { | 388 | if (rc) { |
384 | err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); | 389 | err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); |
385 | mutex_unlock(&ctrl->crit_sect); | 390 | mutex_unlock(&ctrl->ctrl_lock); |
386 | return rc; | 391 | return rc; |
387 | } | 392 | } |
388 | /* Wait for the command to complete */ | 393 | /* Wait for the command to complete */ |
@@ -398,7 +403,7 @@ static int remove_board(struct slot *p_slot) | |||
398 | } | 403 | } |
399 | 404 | ||
400 | /* Done with exclusive hardware access */ | 405 | /* Done with exclusive hardware access */ |
401 | mutex_unlock(&ctrl->crit_sect); | 406 | mutex_unlock(&ctrl->ctrl_lock); |
402 | 407 | ||
403 | return 0; | 408 | return 0; |
404 | } | 409 | } |
@@ -445,7 +450,7 @@ static void pciehp_pushbutton_thread(unsigned long slot) | |||
445 | 450 | ||
446 | if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) { | 451 | if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) { |
447 | /* Wait for exclusive access to hardware */ | 452 | /* Wait for exclusive access to hardware */ |
448 | mutex_lock(&p_slot->ctrl->crit_sect); | 453 | mutex_lock(&p_slot->ctrl->ctrl_lock); |
449 | 454 | ||
450 | p_slot->hpc_ops->green_led_off(p_slot); | 455 | p_slot->hpc_ops->green_led_off(p_slot); |
451 | 456 | ||
@@ -453,7 +458,7 @@ static void pciehp_pushbutton_thread(unsigned long slot) | |||
453 | wait_for_ctrl_irq (p_slot->ctrl); | 458 | wait_for_ctrl_irq (p_slot->ctrl); |
454 | 459 | ||
455 | /* Done with exclusive hardware access */ | 460 | /* Done with exclusive hardware access */ |
456 | mutex_unlock(&p_slot->ctrl->crit_sect); | 461 | mutex_unlock(&p_slot->ctrl->ctrl_lock); |
457 | } | 462 | } |
458 | p_slot->state = STATIC_STATE; | 463 | p_slot->state = STATIC_STATE; |
459 | } | 464 | } |
@@ -495,7 +500,7 @@ static void pciehp_surprise_rm_thread(unsigned long slot) | |||
495 | 500 | ||
496 | if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) { | 501 | if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) { |
497 | /* Wait for exclusive access to hardware */ | 502 | /* Wait for exclusive access to hardware */ |
498 | mutex_lock(&p_slot->ctrl->crit_sect); | 503 | mutex_lock(&p_slot->ctrl->ctrl_lock); |
499 | 504 | ||
500 | p_slot->hpc_ops->green_led_off(p_slot); | 505 | p_slot->hpc_ops->green_led_off(p_slot); |
501 | 506 | ||
@@ -503,7 +508,7 @@ static void pciehp_surprise_rm_thread(unsigned long slot) | |||
503 | wait_for_ctrl_irq (p_slot->ctrl); | 508 | wait_for_ctrl_irq (p_slot->ctrl); |
504 | 509 | ||
505 | /* Done with exclusive hardware access */ | 510 | /* Done with exclusive hardware access */ |
506 | mutex_unlock(&p_slot->ctrl->crit_sect); | 511 | mutex_unlock(&p_slot->ctrl->ctrl_lock); |
507 | } | 512 | } |
508 | p_slot->state = STATIC_STATE; | 513 | p_slot->state = STATIC_STATE; |
509 | } | 514 | } |
@@ -616,7 +621,7 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
616 | switch (p_slot->state) { | 621 | switch (p_slot->state) { |
617 | case BLINKINGOFF_STATE: | 622 | case BLINKINGOFF_STATE: |
618 | /* Wait for exclusive access to hardware */ | 623 | /* Wait for exclusive access to hardware */ |
619 | mutex_lock(&ctrl->crit_sect); | 624 | mutex_lock(&ctrl->ctrl_lock); |
620 | 625 | ||
621 | if (PWR_LED(ctrl->ctrlcap)) { | 626 | if (PWR_LED(ctrl->ctrlcap)) { |
622 | p_slot->hpc_ops->green_led_on(p_slot); | 627 | p_slot->hpc_ops->green_led_on(p_slot); |
@@ -630,11 +635,11 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
630 | wait_for_ctrl_irq (ctrl); | 635 | wait_for_ctrl_irq (ctrl); |
631 | } | 636 | } |
632 | /* Done with exclusive hardware access */ | 637 | /* Done with exclusive hardware access */ |
633 | mutex_unlock(&ctrl->crit_sect); | 638 | mutex_unlock(&ctrl->ctrl_lock); |
634 | break; | 639 | break; |
635 | case BLINKINGON_STATE: | 640 | case BLINKINGON_STATE: |
636 | /* Wait for exclusive access to hardware */ | 641 | /* Wait for exclusive access to hardware */ |
637 | mutex_lock(&ctrl->crit_sect); | 642 | mutex_lock(&ctrl->ctrl_lock); |
638 | 643 | ||
639 | if (PWR_LED(ctrl->ctrlcap)) { | 644 | if (PWR_LED(ctrl->ctrlcap)) { |
640 | p_slot->hpc_ops->green_led_off(p_slot); | 645 | p_slot->hpc_ops->green_led_off(p_slot); |
@@ -647,14 +652,14 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
647 | wait_for_ctrl_irq (ctrl); | 652 | wait_for_ctrl_irq (ctrl); |
648 | } | 653 | } |
649 | /* Done with exclusive hardware access */ | 654 | /* Done with exclusive hardware access */ |
650 | mutex_unlock(&ctrl->crit_sect); | 655 | mutex_unlock(&ctrl->ctrl_lock); |
651 | 656 | ||
652 | break; | 657 | break; |
653 | default: | 658 | default: |
654 | warn("Not a valid state\n"); | 659 | warn("Not a valid state\n"); |
655 | return; | 660 | return; |
656 | } | 661 | } |
657 | info(msg_button_cancel, p_slot->number); | 662 | info(msg_button_cancel, slot_name(p_slot)); |
658 | p_slot->state = STATIC_STATE; | 663 | p_slot->state = STATIC_STATE; |
659 | } | 664 | } |
660 | /* ***********Button Pressed (No action on 1st press...) */ | 665 | /* ***********Button Pressed (No action on 1st press...) */ |
@@ -667,16 +672,16 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
667 | /* slot is on */ | 672 | /* slot is on */ |
668 | dbg("slot is on\n"); | 673 | dbg("slot is on\n"); |
669 | p_slot->state = BLINKINGOFF_STATE; | 674 | p_slot->state = BLINKINGOFF_STATE; |
670 | info(msg_button_off, p_slot->number); | 675 | info(msg_button_off, slot_name(p_slot)); |
671 | } else { | 676 | } else { |
672 | /* slot is off */ | 677 | /* slot is off */ |
673 | dbg("slot is off\n"); | 678 | dbg("slot is off\n"); |
674 | p_slot->state = BLINKINGON_STATE; | 679 | p_slot->state = BLINKINGON_STATE; |
675 | info(msg_button_on, p_slot->number); | 680 | info(msg_button_on, slot_name(p_slot)); |
676 | } | 681 | } |
677 | 682 | ||
678 | /* Wait for exclusive access to hardware */ | 683 | /* Wait for exclusive access to hardware */ |
679 | mutex_lock(&ctrl->crit_sect); | 684 | mutex_lock(&ctrl->ctrl_lock); |
680 | 685 | ||
681 | /* blink green LED and turn off amber */ | 686 | /* blink green LED and turn off amber */ |
682 | if (PWR_LED(ctrl->ctrlcap)) { | 687 | if (PWR_LED(ctrl->ctrlcap)) { |
@@ -693,7 +698,7 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
693 | } | 698 | } |
694 | 699 | ||
695 | /* Done with exclusive hardware access */ | 700 | /* Done with exclusive hardware access */ |
696 | mutex_unlock(&ctrl->crit_sect); | 701 | mutex_unlock(&ctrl->ctrl_lock); |
697 | 702 | ||
698 | init_timer(&p_slot->task_event); | 703 | init_timer(&p_slot->task_event); |
699 | p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */ | 704 | p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */ |
@@ -708,7 +713,7 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
708 | if (POWER_CTRL(ctrl->ctrlcap)) { | 713 | if (POWER_CTRL(ctrl->ctrlcap)) { |
709 | dbg("power fault\n"); | 714 | dbg("power fault\n"); |
710 | /* Wait for exclusive access to hardware */ | 715 | /* Wait for exclusive access to hardware */ |
711 | mutex_lock(&ctrl->crit_sect); | 716 | mutex_lock(&ctrl->ctrl_lock); |
712 | 717 | ||
713 | if (ATTN_LED(ctrl->ctrlcap)) { | 718 | if (ATTN_LED(ctrl->ctrlcap)) { |
714 | p_slot->hpc_ops->set_attention_status(p_slot, 1); | 719 | p_slot->hpc_ops->set_attention_status(p_slot, 1); |
@@ -721,7 +726,7 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
721 | } | 726 | } |
722 | 727 | ||
723 | /* Done with exclusive hardware access */ | 728 | /* Done with exclusive hardware access */ |
724 | mutex_unlock(&ctrl->crit_sect); | 729 | mutex_unlock(&ctrl->ctrl_lock); |
725 | } | 730 | } |
726 | } | 731 | } |
727 | /***********SURPRISE REMOVAL********************/ | 732 | /***********SURPRISE REMOVAL********************/ |
@@ -760,14 +765,16 @@ int pciehp_enable_slot(struct slot *p_slot) | |||
760 | 765 | ||
761 | rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); | 766 | rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); |
762 | if (rc || !getstatus) { | 767 | if (rc || !getstatus) { |
763 | info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); | 768 | info("%s: no adapter on slot(%s)\n", __FUNCTION__, |
769 | slot_name(p_slot)); | ||
764 | mutex_unlock(&p_slot->ctrl->crit_sect); | 770 | mutex_unlock(&p_slot->ctrl->crit_sect); |
765 | return -ENODEV; | 771 | return -ENODEV; |
766 | } | 772 | } |
767 | if (MRL_SENS(p_slot->ctrl->ctrlcap)) { | 773 | if (MRL_SENS(p_slot->ctrl->ctrlcap)) { |
768 | rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); | 774 | rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); |
769 | if (rc || getstatus) { | 775 | if (rc || getstatus) { |
770 | info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); | 776 | info("%s: latch open on slot(%s)\n", __FUNCTION__, |
777 | slot_name(p_slot)); | ||
771 | mutex_unlock(&p_slot->ctrl->crit_sect); | 778 | mutex_unlock(&p_slot->ctrl->crit_sect); |
772 | return -ENODEV; | 779 | return -ENODEV; |
773 | } | 780 | } |
@@ -776,12 +783,12 @@ int pciehp_enable_slot(struct slot *p_slot) | |||
776 | if (POWER_CTRL(p_slot->ctrl->ctrlcap)) { | 783 | if (POWER_CTRL(p_slot->ctrl->ctrlcap)) { |
777 | rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); | 784 | rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); |
778 | if (rc || getstatus) { | 785 | if (rc || getstatus) { |
779 | info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number); | 786 | info("%s: already enabled on slot(%s)\n", __FUNCTION__, |
787 | slot_name(p_slot)); | ||
780 | mutex_unlock(&p_slot->ctrl->crit_sect); | 788 | mutex_unlock(&p_slot->ctrl->crit_sect); |
781 | return -EINVAL; | 789 | return -EINVAL; |
782 | } | 790 | } |
783 | } | 791 | } |
784 | mutex_unlock(&p_slot->ctrl->crit_sect); | ||
785 | 792 | ||
786 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); | 793 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); |
787 | 794 | ||
@@ -790,9 +797,9 @@ int pciehp_enable_slot(struct slot *p_slot) | |||
790 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); | 797 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); |
791 | } | 798 | } |
792 | 799 | ||
793 | if (p_slot) | 800 | update_slot_info(p_slot); |
794 | update_slot_info(p_slot); | ||
795 | 801 | ||
802 | mutex_unlock(&p_slot->ctrl->crit_sect); | ||
796 | return rc; | 803 | return rc; |
797 | } | 804 | } |
798 | 805 | ||
@@ -811,7 +818,8 @@ int pciehp_disable_slot(struct slot *p_slot) | |||
811 | if (!HP_SUPR_RM(p_slot->ctrl->ctrlcap)) { | 818 | if (!HP_SUPR_RM(p_slot->ctrl->ctrlcap)) { |
812 | ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); | 819 | ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); |
813 | if (ret || !getstatus) { | 820 | if (ret || !getstatus) { |
814 | info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); | 821 | info("%s: no adapter on slot(%s)\n", __FUNCTION__, |
822 | slot_name(p_slot)); | ||
815 | mutex_unlock(&p_slot->ctrl->crit_sect); | 823 | mutex_unlock(&p_slot->ctrl->crit_sect); |
816 | return -ENODEV; | 824 | return -ENODEV; |
817 | } | 825 | } |
@@ -820,7 +828,8 @@ int pciehp_disable_slot(struct slot *p_slot) | |||
820 | if (MRL_SENS(p_slot->ctrl->ctrlcap)) { | 828 | if (MRL_SENS(p_slot->ctrl->ctrlcap)) { |
821 | ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); | 829 | ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); |
822 | if (ret || getstatus) { | 830 | if (ret || getstatus) { |
823 | info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); | 831 | info("%s: latch open on slot(%s)\n", __FUNCTION__, |
832 | slot_name(p_slot)); | ||
824 | mutex_unlock(&p_slot->ctrl->crit_sect); | 833 | mutex_unlock(&p_slot->ctrl->crit_sect); |
825 | return -ENODEV; | 834 | return -ENODEV; |
826 | } | 835 | } |
@@ -829,16 +838,17 @@ int pciehp_disable_slot(struct slot *p_slot) | |||
829 | if (POWER_CTRL(p_slot->ctrl->ctrlcap)) { | 838 | if (POWER_CTRL(p_slot->ctrl->ctrlcap)) { |
830 | ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); | 839 | ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); |
831 | if (ret || !getstatus) { | 840 | if (ret || !getstatus) { |
832 | info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number); | 841 | info("%s: already disabled slot(%s)\n", __FUNCTION__, |
842 | slot_name(p_slot)); | ||
833 | mutex_unlock(&p_slot->ctrl->crit_sect); | 843 | mutex_unlock(&p_slot->ctrl->crit_sect); |
834 | return -EINVAL; | 844 | return -EINVAL; |
835 | } | 845 | } |
836 | } | 846 | } |
837 | 847 | ||
838 | mutex_unlock(&p_slot->ctrl->crit_sect); | ||
839 | |||
840 | ret = remove_board(p_slot); | 848 | ret = remove_board(p_slot); |
841 | update_slot_info(p_slot); | 849 | update_slot_info(p_slot); |
850 | |||
851 | mutex_unlock(&p_slot->ctrl->crit_sect); | ||
842 | return ret; | 852 | return ret; |
843 | } | 853 | } |
844 | 854 | ||
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 703a64a39fe8..1c551c697c35 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c | |||
@@ -1402,6 +1402,8 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) | |||
1402 | pdev->subsystem_vendor, pdev->subsystem_device); | 1402 | pdev->subsystem_vendor, pdev->subsystem_device); |
1403 | 1403 | ||
1404 | mutex_init(&ctrl->crit_sect); | 1404 | mutex_init(&ctrl->crit_sect); |
1405 | mutex_init(&ctrl->ctrl_lock); | ||
1406 | |||
1405 | /* setup wait queue */ | 1407 | /* setup wait queue */ |
1406 | init_waitqueue_head(&ctrl->queue); | 1408 | init_waitqueue_head(&ctrl->queue); |
1407 | 1409 | ||
diff --git a/drivers/pci/hotplug/pcihp_skeleton.c b/drivers/pci/hotplug/pcihp_skeleton.c index 2b9e10e38613..50bcd3fe61da 100644 --- a/drivers/pci/hotplug/pcihp_skeleton.c +++ b/drivers/pci/hotplug/pcihp_skeleton.c | |||
@@ -33,8 +33,8 @@ | |||
33 | #include <linux/kernel.h> | 33 | #include <linux/kernel.h> |
34 | #include <linux/slab.h> | 34 | #include <linux/slab.h> |
35 | #include <linux/pci.h> | 35 | #include <linux/pci.h> |
36 | #include <linux/pci_hotplug.h> | ||
36 | #include <linux/init.h> | 37 | #include <linux/init.h> |
37 | #include "pci_hotplug.h" | ||
38 | 38 | ||
39 | #define SLOT_NAME_SIZE 10 | 39 | #define SLOT_NAME_SIZE 10 |
40 | struct slot { | 40 | struct slot { |
diff --git a/drivers/pci/hotplug/rpadlpar_sysfs.c b/drivers/pci/hotplug/rpadlpar_sysfs.c index db69be85b458..6c5be3ff578c 100644 --- a/drivers/pci/hotplug/rpadlpar_sysfs.c +++ b/drivers/pci/hotplug/rpadlpar_sysfs.c | |||
@@ -14,7 +14,7 @@ | |||
14 | */ | 14 | */ |
15 | #include <linux/kobject.h> | 15 | #include <linux/kobject.h> |
16 | #include <linux/string.h> | 16 | #include <linux/string.h> |
17 | #include "pci_hotplug.h" | 17 | #include <linux/pci_hotplug.h> |
18 | #include "rpadlpar.h" | 18 | #include "rpadlpar.h" |
19 | 19 | ||
20 | #define DLPAR_KOBJ_NAME "control" | 20 | #define DLPAR_KOBJ_NAME "control" |
diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c index 7288a3eccfb3..141486df235b 100644 --- a/drivers/pci/hotplug/rpaphp_core.c +++ b/drivers/pci/hotplug/rpaphp_core.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/moduleparam.h> | 27 | #include <linux/moduleparam.h> |
28 | #include <linux/pci.h> | 28 | #include <linux/pci.h> |
29 | #include <linux/pci_hotplug.h> | ||
29 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
30 | #include <linux/smp.h> | 31 | #include <linux/smp.h> |
31 | #include <linux/smp_lock.h> | 32 | #include <linux/smp_lock.h> |
@@ -36,7 +37,6 @@ | |||
36 | #include "../pci.h" /* for pci_add_new_bus */ | 37 | #include "../pci.h" /* for pci_add_new_bus */ |
37 | /* and pci_do_scan_bus */ | 38 | /* and pci_do_scan_bus */ |
38 | #include "rpaphp.h" | 39 | #include "rpaphp.h" |
39 | #include "pci_hotplug.h" | ||
40 | 40 | ||
41 | int debug; | 41 | int debug; |
42 | static struct semaphore rpaphp_sem; | 42 | static struct semaphore rpaphp_sem; |
diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c index f31d83c2c633..b62ad31a9739 100644 --- a/drivers/pci/hotplug/sgi_hotplug.c +++ b/drivers/pci/hotplug/sgi_hotplug.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/pci.h> | 15 | #include <linux/pci.h> |
16 | #include <linux/pci_hotplug.h> | ||
16 | #include <linux/proc_fs.h> | 17 | #include <linux/proc_fs.h> |
17 | #include <linux/types.h> | 18 | #include <linux/types.h> |
18 | #include <linux/mutex.h> | 19 | #include <linux/mutex.h> |
@@ -29,7 +30,6 @@ | |||
29 | #include <asm/sn/types.h> | 30 | #include <asm/sn/types.h> |
30 | 31 | ||
31 | #include "../pci.h" | 32 | #include "../pci.h" |
32 | #include "pci_hotplug.h" | ||
33 | 33 | ||
34 | MODULE_LICENSE("GPL"); | 34 | MODULE_LICENSE("GPL"); |
35 | MODULE_AUTHOR("SGI (prarit@sgi.com, dickie@sgi.com, habeck@sgi.com)"); | 35 | MODULE_AUTHOR("SGI (prarit@sgi.com, dickie@sgi.com, habeck@sgi.com)"); |
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index c7103ac5cd06..ea2087c34149 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h | |||
@@ -31,12 +31,11 @@ | |||
31 | 31 | ||
32 | #include <linux/types.h> | 32 | #include <linux/types.h> |
33 | #include <linux/pci.h> | 33 | #include <linux/pci.h> |
34 | #include <linux/pci_hotplug.h> | ||
34 | #include <linux/delay.h> | 35 | #include <linux/delay.h> |
35 | #include <linux/sched.h> /* signal_pending(), struct timer_list */ | 36 | #include <linux/sched.h> /* signal_pending(), struct timer_list */ |
36 | #include <linux/mutex.h> | 37 | #include <linux/mutex.h> |
37 | 38 | ||
38 | #include "pci_hotplug.h" | ||
39 | |||
40 | #if !defined(MODULE) | 39 | #if !defined(MODULE) |
41 | #define MY_NAME "shpchp" | 40 | #define MY_NAME "shpchp" |
42 | #else | 41 | #else |
@@ -103,7 +102,6 @@ struct controller { | |||
103 | u32 cap_offset; | 102 | u32 cap_offset; |
104 | unsigned long mmio_base; | 103 | unsigned long mmio_base; |
105 | unsigned long mmio_size; | 104 | unsigned long mmio_size; |
106 | volatile int cmd_busy; | ||
107 | }; | 105 | }; |
108 | 106 | ||
109 | 107 | ||
diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index 4d8aee119134..83a5226ba9ed 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c | |||
@@ -302,21 +302,51 @@ static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int sec) | |||
302 | add_timer(&php_ctlr->int_poll_timer); | 302 | add_timer(&php_ctlr->int_poll_timer); |
303 | } | 303 | } |
304 | 304 | ||
305 | static inline int is_ctrl_busy(struct controller *ctrl) | ||
306 | { | ||
307 | u16 cmd_status = shpc_readw(ctrl, CMD_STATUS); | ||
308 | return cmd_status & 0x1; | ||
309 | } | ||
310 | |||
311 | /* | ||
312 | * Returns 1 if SHPC finishes executing a command within 1 sec, | ||
313 | * otherwise returns 0. | ||
314 | */ | ||
315 | static inline int shpc_poll_ctrl_busy(struct controller *ctrl) | ||
316 | { | ||
317 | int i; | ||
318 | |||
319 | if (!is_ctrl_busy(ctrl)) | ||
320 | return 1; | ||
321 | |||
322 | /* Check every 0.1 sec for a total of 1 sec */ | ||
323 | for (i = 0; i < 10; i++) { | ||
324 | msleep(100); | ||
325 | if (!is_ctrl_busy(ctrl)) | ||
326 | return 1; | ||
327 | } | ||
328 | |||
329 | return 0; | ||
330 | } | ||
331 | |||
305 | static inline int shpc_wait_cmd(struct controller *ctrl) | 332 | static inline int shpc_wait_cmd(struct controller *ctrl) |
306 | { | 333 | { |
307 | int retval = 0; | 334 | int retval = 0; |
308 | unsigned int timeout_msec = shpchp_poll_mode ? 2000 : 1000; | 335 | unsigned long timeout = msecs_to_jiffies(1000); |
309 | unsigned long timeout = msecs_to_jiffies(timeout_msec); | 336 | int rc; |
310 | int rc = wait_event_interruptible_timeout(ctrl->queue, | 337 | |
311 | !ctrl->cmd_busy, timeout); | 338 | if (shpchp_poll_mode) |
312 | if (!rc) { | 339 | rc = shpc_poll_ctrl_busy(ctrl); |
340 | else | ||
341 | rc = wait_event_interruptible_timeout(ctrl->queue, | ||
342 | !is_ctrl_busy(ctrl), timeout); | ||
343 | if (!rc && is_ctrl_busy(ctrl)) { | ||
313 | retval = -EIO; | 344 | retval = -EIO; |
314 | err("Command not completed in %d msec\n", timeout_msec); | 345 | err("Command not completed in 1000 msec\n"); |
315 | } else if (rc < 0) { | 346 | } else if (rc < 0) { |
316 | retval = -EINTR; | 347 | retval = -EINTR; |
317 | info("Command was interrupted by a signal\n"); | 348 | info("Command was interrupted by a signal\n"); |
318 | } | 349 | } |
319 | ctrl->cmd_busy = 0; | ||
320 | 350 | ||
321 | return retval; | 351 | return retval; |
322 | } | 352 | } |
@@ -327,26 +357,15 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) | |||
327 | u16 cmd_status; | 357 | u16 cmd_status; |
328 | int retval = 0; | 358 | int retval = 0; |
329 | u16 temp_word; | 359 | u16 temp_word; |
330 | int i; | ||
331 | 360 | ||
332 | DBG_ENTER_ROUTINE | 361 | DBG_ENTER_ROUTINE |
333 | 362 | ||
334 | mutex_lock(&slot->ctrl->cmd_lock); | 363 | mutex_lock(&slot->ctrl->cmd_lock); |
335 | 364 | ||
336 | for (i = 0; i < 10; i++) { | 365 | if (!shpc_poll_ctrl_busy(ctrl)) { |
337 | cmd_status = shpc_readw(ctrl, CMD_STATUS); | ||
338 | |||
339 | if (!(cmd_status & 0x1)) | ||
340 | break; | ||
341 | /* Check every 0.1 sec for a total of 1 sec*/ | ||
342 | msleep(100); | ||
343 | } | ||
344 | |||
345 | cmd_status = shpc_readw(ctrl, CMD_STATUS); | ||
346 | |||
347 | if (cmd_status & 0x1) { | ||
348 | /* After 1 sec and and the controller is still busy */ | 366 | /* After 1 sec and and the controller is still busy */ |
349 | err("%s : Controller is still busy after 1 sec.\n", __FUNCTION__); | 367 | err("%s : Controller is still busy after 1 sec.\n", |
368 | __FUNCTION__); | ||
350 | retval = -EBUSY; | 369 | retval = -EBUSY; |
351 | goto out; | 370 | goto out; |
352 | } | 371 | } |
@@ -358,7 +377,6 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) | |||
358 | /* To make sure the Controller Busy bit is 0 before we send out the | 377 | /* To make sure the Controller Busy bit is 0 before we send out the |
359 | * command. | 378 | * command. |
360 | */ | 379 | */ |
361 | slot->ctrl->cmd_busy = 1; | ||
362 | shpc_writew(ctrl, CMD, temp_word); | 380 | shpc_writew(ctrl, CMD, temp_word); |
363 | 381 | ||
364 | /* | 382 | /* |
@@ -908,7 +926,6 @@ static irqreturn_t shpc_isr(int irq, void *dev_id) | |||
908 | serr_int &= ~SERR_INTR_RSVDZ_MASK; | 926 | serr_int &= ~SERR_INTR_RSVDZ_MASK; |
909 | shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int); | 927 | shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int); |
910 | 928 | ||
911 | ctrl->cmd_busy = 0; | ||
912 | wake_up_interruptible(&ctrl->queue); | 929 | wake_up_interruptible(&ctrl->queue); |
913 | } | 930 | } |
914 | 931 | ||
@@ -1101,7 +1118,7 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) | |||
1101 | { | 1118 | { |
1102 | struct php_ctlr_state_s *php_ctlr, *p; | 1119 | struct php_ctlr_state_s *php_ctlr, *p; |
1103 | void *instance_id = ctrl; | 1120 | void *instance_id = ctrl; |
1104 | int rc, num_slots = 0; | 1121 | int rc = -1, num_slots = 0; |
1105 | u8 hp_slot; | 1122 | u8 hp_slot; |
1106 | u32 shpc_base_offset; | 1123 | u32 shpc_base_offset; |
1107 | u32 tempdword, slot_reg, slot_config; | 1124 | u32 tempdword, slot_reg, slot_config; |
@@ -1167,11 +1184,15 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) | |||
1167 | info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device, pdev->subsystem_vendor, | 1184 | info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device, pdev->subsystem_vendor, |
1168 | pdev->subsystem_device); | 1185 | pdev->subsystem_device); |
1169 | 1186 | ||
1170 | if (pci_enable_device(pdev)) | 1187 | rc = pci_enable_device(pdev); |
1188 | if (rc) { | ||
1189 | err("%s: pci_enable_device failed\n", __FUNCTION__); | ||
1171 | goto abort_free_ctlr; | 1190 | goto abort_free_ctlr; |
1191 | } | ||
1172 | 1192 | ||
1173 | if (!request_mem_region(ctrl->mmio_base, ctrl->mmio_size, MY_NAME)) { | 1193 | if (!request_mem_region(ctrl->mmio_base, ctrl->mmio_size, MY_NAME)) { |
1174 | err("%s: cannot reserve MMIO region\n", __FUNCTION__); | 1194 | err("%s: cannot reserve MMIO region\n", __FUNCTION__); |
1195 | rc = -1; | ||
1175 | goto abort_free_ctlr; | 1196 | goto abort_free_ctlr; |
1176 | } | 1197 | } |
1177 | 1198 | ||
@@ -1180,6 +1201,7 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) | |||
1180 | err("%s: cannot remap MMIO region %lx @ %lx\n", __FUNCTION__, | 1201 | err("%s: cannot remap MMIO region %lx @ %lx\n", __FUNCTION__, |
1181 | ctrl->mmio_size, ctrl->mmio_base); | 1202 | ctrl->mmio_size, ctrl->mmio_base); |
1182 | release_mem_region(ctrl->mmio_base, ctrl->mmio_size); | 1203 | release_mem_region(ctrl->mmio_base, ctrl->mmio_size); |
1204 | rc = -1; | ||
1183 | goto abort_free_ctlr; | 1205 | goto abort_free_ctlr; |
1184 | } | 1206 | } |
1185 | dbg("%s: php_ctlr->creg %p\n", __FUNCTION__, php_ctlr->creg); | 1207 | dbg("%s: php_ctlr->creg %p\n", __FUNCTION__, php_ctlr->creg); |
@@ -1282,8 +1304,10 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) | |||
1282 | */ | 1304 | */ |
1283 | if (atomic_add_return(1, &shpchp_num_controllers) == 1) { | 1305 | if (atomic_add_return(1, &shpchp_num_controllers) == 1) { |
1284 | shpchp_wq = create_singlethread_workqueue("shpchpd"); | 1306 | shpchp_wq = create_singlethread_workqueue("shpchpd"); |
1285 | if (!shpchp_wq) | 1307 | if (!shpchp_wq) { |
1286 | return -ENOMEM; | 1308 | rc = -ENOMEM; |
1309 | goto abort_free_ctlr; | ||
1310 | } | ||
1287 | } | 1311 | } |
1288 | 1312 | ||
1289 | /* | 1313 | /* |
@@ -1313,8 +1337,10 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) | |||
1313 | 1337 | ||
1314 | /* We end up here for the many possible ways to fail this API. */ | 1338 | /* We end up here for the many possible ways to fail this API. */ |
1315 | abort_free_ctlr: | 1339 | abort_free_ctlr: |
1340 | if (php_ctlr->creg) | ||
1341 | iounmap(php_ctlr->creg); | ||
1316 | kfree(php_ctlr); | 1342 | kfree(php_ctlr); |
1317 | abort: | 1343 | abort: |
1318 | DBG_LEAVE_ROUTINE | 1344 | DBG_LEAVE_ROUTINE |
1319 | return -1; | 1345 | return rc; |
1320 | } | 1346 | } |
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index f9fdc54473c4..9fc9a34ef24a 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c | |||
@@ -627,22 +627,24 @@ static int msix_capability_init(struct pci_dev *dev, | |||
627 | * pci_msi_supported - check whether MSI may be enabled on device | 627 | * pci_msi_supported - check whether MSI may be enabled on device |
628 | * @dev: pointer to the pci_dev data structure of MSI device function | 628 | * @dev: pointer to the pci_dev data structure of MSI device function |
629 | * | 629 | * |
630 | * MSI must be globally enabled and supported by the device and its root | 630 | * Look at global flags, the device itself, and its parent busses |
631 | * bus. But, the root bus is not easy to find since some architectures | 631 | * to return 0 if MSI are supported for the device. |
632 | * have virtual busses on top of the PCI hierarchy (for instance the | ||
633 | * hypertransport bus), while the actual bus where MSI must be supported | ||
634 | * is below. So we test the MSI flag on all parent busses and assume | ||
635 | * that no quirk will ever set the NO_MSI flag on a non-root bus. | ||
636 | **/ | 632 | **/ |
637 | static | 633 | static |
638 | int pci_msi_supported(struct pci_dev * dev) | 634 | int pci_msi_supported(struct pci_dev * dev) |
639 | { | 635 | { |
640 | struct pci_bus *bus; | 636 | struct pci_bus *bus; |
641 | 637 | ||
638 | /* MSI must be globally enabled and supported by the device */ | ||
642 | if (!pci_msi_enable || !dev || dev->no_msi) | 639 | if (!pci_msi_enable || !dev || dev->no_msi) |
643 | return -EINVAL; | 640 | return -EINVAL; |
644 | 641 | ||
645 | /* check MSI flags of all parent busses */ | 642 | /* Any bridge which does NOT route MSI transactions from it's |
643 | * secondary bus to it's primary bus must set NO_MSI flag on | ||
644 | * the secondary pci_bus. | ||
645 | * We expect only arch-specific PCI host bus controller driver | ||
646 | * or quirks for specific PCI bridges to be setting NO_MSI. | ||
647 | */ | ||
646 | for (bus = dev->bus; bus; bus = bus->parent) | 648 | for (bus = dev->bus; bus; bus = bus->parent) |
647 | if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI) | 649 | if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI) |
648 | return -EINVAL; | 650 | return -EINVAL; |
diff --git a/drivers/pci/pcie/portdrv.h b/drivers/pci/pcie/portdrv.h index 67fcd176babd..3656e0349dd1 100644 --- a/drivers/pci/pcie/portdrv.h +++ b/drivers/pci/pcie/portdrv.h | |||
@@ -9,6 +9,8 @@ | |||
9 | #ifndef _PORTDRV_H_ | 9 | #ifndef _PORTDRV_H_ |
10 | #define _PORTDRV_H_ | 10 | #define _PORTDRV_H_ |
11 | 11 | ||
12 | #include <linux/compiler.h> | ||
13 | |||
12 | #if !defined(PCI_CAP_ID_PME) | 14 | #if !defined(PCI_CAP_ID_PME) |
13 | #define PCI_CAP_ID_PME 1 | 15 | #define PCI_CAP_ID_PME 1 |
14 | #endif | 16 | #endif |
@@ -39,7 +41,7 @@ extern int pcie_port_device_suspend(struct pci_dev *dev, pm_message_t state); | |||
39 | extern int pcie_port_device_resume(struct pci_dev *dev); | 41 | extern int pcie_port_device_resume(struct pci_dev *dev); |
40 | #endif | 42 | #endif |
41 | extern void pcie_port_device_remove(struct pci_dev *dev); | 43 | extern void pcie_port_device_remove(struct pci_dev *dev); |
42 | extern int pcie_port_bus_register(void); | 44 | extern int __must_check pcie_port_bus_register(void); |
43 | extern void pcie_port_bus_unregister(void); | 45 | extern void pcie_port_bus_unregister(void); |
44 | 46 | ||
45 | #endif /* _PORTDRV_H_ */ | 47 | #endif /* _PORTDRV_H_ */ |
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c index bd6615b4d40e..b20a9b81dae2 100644 --- a/drivers/pci/pcie/portdrv_core.c +++ b/drivers/pci/pcie/portdrv_core.c | |||
@@ -6,7 +6,6 @@ | |||
6 | * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com) | 6 | * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com) |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/compiler.h> | ||
10 | #include <linux/module.h> | 9 | #include <linux/module.h> |
11 | #include <linux/pci.h> | 10 | #include <linux/pci.h> |
12 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
@@ -401,7 +400,7 @@ void pcie_port_device_remove(struct pci_dev *dev) | |||
401 | pci_disable_msi(dev); | 400 | pci_disable_msi(dev); |
402 | } | 401 | } |
403 | 402 | ||
404 | int __must_check pcie_port_bus_register(void) | 403 | int pcie_port_bus_register(void) |
405 | { | 404 | { |
406 | return bus_register(&pcie_port_bus_type); | 405 | return bus_register(&pcie_port_bus_type); |
407 | } | 406 | } |
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index 037690e08f5f..b4da7954611e 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c | |||
@@ -37,7 +37,6 @@ static int pcie_portdrv_save_config(struct pci_dev *dev) | |||
37 | return pci_save_state(dev); | 37 | return pci_save_state(dev); |
38 | } | 38 | } |
39 | 39 | ||
40 | #ifdef CONFIG_PM | ||
41 | static int pcie_portdrv_restore_config(struct pci_dev *dev) | 40 | static int pcie_portdrv_restore_config(struct pci_dev *dev) |
42 | { | 41 | { |
43 | int retval; | 42 | int retval; |
@@ -50,6 +49,7 @@ static int pcie_portdrv_restore_config(struct pci_dev *dev) | |||
50 | return 0; | 49 | return 0; |
51 | } | 50 | } |
52 | 51 | ||
52 | #ifdef CONFIG_PM | ||
53 | static int pcie_portdrv_suspend(struct pci_dev *dev, pm_message_t state) | 53 | static int pcie_portdrv_suspend(struct pci_dev *dev, pm_message_t state) |
54 | { | 54 | { |
55 | int ret = pcie_port_device_suspend(dev, state); | 55 | int ret = pcie_port_device_suspend(dev, state); |
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index a3b0a5eb5054..e159d6604494 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
@@ -1067,3 +1067,95 @@ EXPORT_SYMBOL(pci_scan_bridge); | |||
1067 | EXPORT_SYMBOL(pci_scan_single_device); | 1067 | EXPORT_SYMBOL(pci_scan_single_device); |
1068 | EXPORT_SYMBOL_GPL(pci_scan_child_bus); | 1068 | EXPORT_SYMBOL_GPL(pci_scan_child_bus); |
1069 | #endif | 1069 | #endif |
1070 | |||
1071 | static int __init pci_sort_bf_cmp(const struct pci_dev *a, const struct pci_dev *b) | ||
1072 | { | ||
1073 | if (pci_domain_nr(a->bus) < pci_domain_nr(b->bus)) return -1; | ||
1074 | else if (pci_domain_nr(a->bus) > pci_domain_nr(b->bus)) return 1; | ||
1075 | |||
1076 | if (a->bus->number < b->bus->number) return -1; | ||
1077 | else if (a->bus->number > b->bus->number) return 1; | ||
1078 | |||
1079 | if (a->devfn < b->devfn) return -1; | ||
1080 | else if (a->devfn > b->devfn) return 1; | ||
1081 | |||
1082 | return 0; | ||
1083 | } | ||
1084 | |||
1085 | /* | ||
1086 | * Yes, this forcably breaks the klist abstraction temporarily. It | ||
1087 | * just wants to sort the klist, not change reference counts and | ||
1088 | * take/drop locks rapidly in the process. It does all this while | ||
1089 | * holding the lock for the list, so objects can't otherwise be | ||
1090 | * added/removed while we're swizzling. | ||
1091 | */ | ||
1092 | static void __init pci_insertion_sort_klist(struct pci_dev *a, struct list_head *list) | ||
1093 | { | ||
1094 | struct list_head *pos; | ||
1095 | struct klist_node *n; | ||
1096 | struct device *dev; | ||
1097 | struct pci_dev *b; | ||
1098 | |||
1099 | list_for_each(pos, list) { | ||
1100 | n = container_of(pos, struct klist_node, n_node); | ||
1101 | dev = container_of(n, struct device, knode_bus); | ||
1102 | b = to_pci_dev(dev); | ||
1103 | if (pci_sort_bf_cmp(a, b) <= 0) { | ||
1104 | list_move_tail(&a->dev.knode_bus.n_node, &b->dev.knode_bus.n_node); | ||
1105 | return; | ||
1106 | } | ||
1107 | } | ||
1108 | list_move_tail(&a->dev.knode_bus.n_node, list); | ||
1109 | } | ||
1110 | |||
1111 | static void __init pci_sort_breadthfirst_klist(void) | ||
1112 | { | ||
1113 | LIST_HEAD(sorted_devices); | ||
1114 | struct list_head *pos, *tmp; | ||
1115 | struct klist_node *n; | ||
1116 | struct device *dev; | ||
1117 | struct pci_dev *pdev; | ||
1118 | |||
1119 | spin_lock(&pci_bus_type.klist_devices.k_lock); | ||
1120 | list_for_each_safe(pos, tmp, &pci_bus_type.klist_devices.k_list) { | ||
1121 | n = container_of(pos, struct klist_node, n_node); | ||
1122 | dev = container_of(n, struct device, knode_bus); | ||
1123 | pdev = to_pci_dev(dev); | ||
1124 | pci_insertion_sort_klist(pdev, &sorted_devices); | ||
1125 | } | ||
1126 | list_splice(&sorted_devices, &pci_bus_type.klist_devices.k_list); | ||
1127 | spin_unlock(&pci_bus_type.klist_devices.k_lock); | ||
1128 | } | ||
1129 | |||
1130 | static void __init pci_insertion_sort_devices(struct pci_dev *a, struct list_head *list) | ||
1131 | { | ||
1132 | struct pci_dev *b; | ||
1133 | |||
1134 | list_for_each_entry(b, list, global_list) { | ||
1135 | if (pci_sort_bf_cmp(a, b) <= 0) { | ||
1136 | list_move_tail(&a->global_list, &b->global_list); | ||
1137 | return; | ||
1138 | } | ||
1139 | } | ||
1140 | list_move_tail(&a->global_list, list); | ||
1141 | } | ||
1142 | |||
1143 | static void __init pci_sort_breadthfirst_devices(void) | ||
1144 | { | ||
1145 | LIST_HEAD(sorted_devices); | ||
1146 | struct pci_dev *dev, *tmp; | ||
1147 | |||
1148 | down_write(&pci_bus_sem); | ||
1149 | list_for_each_entry_safe(dev, tmp, &pci_devices, global_list) { | ||
1150 | pci_insertion_sort_devices(dev, &sorted_devices); | ||
1151 | } | ||
1152 | list_splice(&sorted_devices, &pci_devices); | ||
1153 | up_write(&pci_bus_sem); | ||
1154 | } | ||
1155 | |||
1156 | void __init pci_sort_breadthfirst(void) | ||
1157 | { | ||
1158 | pci_sort_breadthfirst_devices(); | ||
1159 | pci_sort_breadthfirst_klist(); | ||
1160 | } | ||
1161 | |||
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 23b599d6a9d5..e8a7f1b1b2bc 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c | |||
@@ -453,6 +453,12 @@ static void __devinit quirk_ich6_lpc_acpi(struct pci_dev *dev) | |||
453 | } | 453 | } |
454 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0, quirk_ich6_lpc_acpi ); | 454 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0, quirk_ich6_lpc_acpi ); |
455 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, quirk_ich6_lpc_acpi ); | 455 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, quirk_ich6_lpc_acpi ); |
456 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0, quirk_ich6_lpc_acpi ); | ||
457 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1, quirk_ich6_lpc_acpi ); | ||
458 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_31, quirk_ich6_lpc_acpi ); | ||
459 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_0, quirk_ich6_lpc_acpi ); | ||
460 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_2, quirk_ich6_lpc_acpi ); | ||
461 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_3, quirk_ich6_lpc_acpi ); | ||
456 | 462 | ||
457 | /* | 463 | /* |
458 | * VIA ACPI: One IO region pointed to by longword at | 464 | * VIA ACPI: One IO region pointed to by longword at |
@@ -648,11 +654,43 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_vi | |||
648 | * Some of the on-chip devices are actually '586 devices' so they are | 654 | * Some of the on-chip devices are actually '586 devices' so they are |
649 | * listed here. | 655 | * listed here. |
650 | */ | 656 | */ |
657 | |||
658 | static int via_irq_fixup_needed = -1; | ||
659 | |||
660 | /* | ||
661 | * As some VIA hardware is available in PCI-card form, we need to restrict | ||
662 | * this quirk to VIA PCI hardware built onto VIA-based motherboards only. | ||
663 | * We try to locate a VIA southbridge before deciding whether the quirk | ||
664 | * should be applied. | ||
665 | */ | ||
666 | static const struct pci_device_id via_irq_fixup_tbl[] = { | ||
667 | { | ||
668 | .vendor = PCI_VENDOR_ID_VIA, | ||
669 | .device = PCI_ANY_ID, | ||
670 | .subvendor = PCI_ANY_ID, | ||
671 | .subdevice = PCI_ANY_ID, | ||
672 | .class = PCI_CLASS_BRIDGE_ISA << 8, | ||
673 | .class_mask = 0xffff00, | ||
674 | }, | ||
675 | { 0, }, | ||
676 | }; | ||
677 | |||
651 | static void quirk_via_irq(struct pci_dev *dev) | 678 | static void quirk_via_irq(struct pci_dev *dev) |
652 | { | 679 | { |
653 | u8 irq, new_irq; | 680 | u8 irq, new_irq; |
654 | 681 | ||
655 | new_irq = dev->irq & 0xf; | 682 | if (via_irq_fixup_needed == -1) |
683 | via_irq_fixup_needed = pci_dev_present(via_irq_fixup_tbl); | ||
684 | |||
685 | if (!via_irq_fixup_needed) | ||
686 | return; | ||
687 | |||
688 | new_irq = dev->irq; | ||
689 | |||
690 | /* Don't quirk interrupts outside the legacy IRQ range */ | ||
691 | if (!new_irq || new_irq > 15) | ||
692 | return; | ||
693 | |||
656 | pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); | 694 | pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); |
657 | if (new_irq != irq) { | 695 | if (new_irq != irq) { |
658 | printk(KERN_INFO "PCI: VIA IRQ fixup for %s, from %d to %d\n", | 696 | printk(KERN_INFO "PCI: VIA IRQ fixup for %s, from %d to %d\n", |
@@ -661,14 +699,7 @@ static void quirk_via_irq(struct pci_dev *dev) | |||
661 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq); | 699 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq); |
662 | } | 700 | } |
663 | } | 701 | } |
664 | DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0, quirk_via_irq); | 702 | DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_irq); |
665 | DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, quirk_via_irq); | ||
666 | DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_2, quirk_via_irq); | ||
667 | DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_via_irq); | ||
668 | DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235_USB_2, quirk_via_irq); | ||
669 | DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_irq); | ||
670 | DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_via_irq); | ||
671 | DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5, quirk_via_irq); | ||
672 | 703 | ||
673 | /* | 704 | /* |
674 | * VIA VT82C598 has its device ID settable and many BIOSes | 705 | * VIA VT82C598 has its device ID settable and many BIOSes |
@@ -1588,6 +1619,51 @@ static void __devinit fixup_rev1_53c810(struct pci_dev* dev) | |||
1588 | } | 1619 | } |
1589 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, fixup_rev1_53c810); | 1620 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, fixup_rev1_53c810); |
1590 | 1621 | ||
1622 | /* | ||
1623 | * Fixup to mark boot BIOS video selected by BIOS before it changes | ||
1624 | * | ||
1625 | * From information provided by "Jon Smirl" <jonsmirl@gmail.com> | ||
1626 | * | ||
1627 | * The standard boot ROM sequence for an x86 machine uses the BIOS | ||
1628 | * to select an initial video card for boot display. This boot video | ||
1629 | * card will have it's BIOS copied to C0000 in system RAM. | ||
1630 | * IORESOURCE_ROM_SHADOW is used to associate the boot video | ||
1631 | * card with this copy. On laptops this copy has to be used since | ||
1632 | * the main ROM may be compressed or combined with another image. | ||
1633 | * See pci_map_rom() for use of this flag. IORESOURCE_ROM_SHADOW | ||
1634 | * is marked here since the boot video device will be the only enabled | ||
1635 | * video device at this point. | ||
1636 | */ | ||
1637 | |||
1638 | static void __devinit fixup_video(struct pci_dev *pdev) | ||
1639 | { | ||
1640 | struct pci_dev *bridge; | ||
1641 | struct pci_bus *bus; | ||
1642 | u16 config; | ||
1643 | |||
1644 | if ((pdev->class >> 8) != PCI_CLASS_DISPLAY_VGA) | ||
1645 | return; | ||
1646 | |||
1647 | /* Is VGA routed to us? */ | ||
1648 | bus = pdev->bus; | ||
1649 | while (bus) { | ||
1650 | bridge = bus->self; | ||
1651 | if (bridge) { | ||
1652 | pci_read_config_word(bridge, PCI_BRIDGE_CONTROL, | ||
1653 | &config); | ||
1654 | if (!(config & PCI_BRIDGE_CTL_VGA)) | ||
1655 | return; | ||
1656 | } | ||
1657 | bus = bus->parent; | ||
1658 | } | ||
1659 | pci_read_config_word(pdev, PCI_COMMAND, &config); | ||
1660 | if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) { | ||
1661 | pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW; | ||
1662 | printk(KERN_DEBUG "Boot video device is %s\n", pci_name(pdev)); | ||
1663 | } | ||
1664 | } | ||
1665 | DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, fixup_video); | ||
1666 | |||
1591 | 1667 | ||
1592 | static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end) | 1668 | static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end) |
1593 | { | 1669 | { |
@@ -1764,7 +1840,7 @@ static void __devinit quirk_nvidia_ck804_msi_ht_cap(struct pci_dev *dev) | |||
1764 | /* check HT MSI cap on this chipset and the root one. | 1840 | /* check HT MSI cap on this chipset and the root one. |
1765 | * a single one having MSI is enough to be sure that MSI are supported. | 1841 | * a single one having MSI is enough to be sure that MSI are supported. |
1766 | */ | 1842 | */ |
1767 | pdev = pci_find_slot(dev->bus->number, 0); | 1843 | pdev = pci_get_slot(dev->bus, 0); |
1768 | if (dev->subordinate && !msi_ht_cap_enabled(dev) | 1844 | if (dev->subordinate && !msi_ht_cap_enabled(dev) |
1769 | && !msi_ht_cap_enabled(pdev)) { | 1845 | && !msi_ht_cap_enabled(pdev)) { |
1770 | printk(KERN_WARNING "PCI: MSI quirk detected. " | 1846 | printk(KERN_WARNING "PCI: MSI quirk detected. " |
@@ -1772,6 +1848,7 @@ static void __devinit quirk_nvidia_ck804_msi_ht_cap(struct pci_dev *dev) | |||
1772 | pci_name(dev)); | 1848 | pci_name(dev)); |
1773 | dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI; | 1849 | dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI; |
1774 | } | 1850 | } |
1851 | pci_dev_put(pdev); | ||
1775 | } | 1852 | } |
1776 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE, | 1853 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE, |
1777 | quirk_nvidia_ck804_msi_ht_cap); | 1854 | quirk_nvidia_ck804_msi_ht_cap); |
diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c index f5ee7ce16fa6..43e4a49f2cc4 100644 --- a/drivers/pci/rom.c +++ b/drivers/pci/rom.c | |||
@@ -71,7 +71,10 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size) | |||
71 | void __iomem *image; | 71 | void __iomem *image; |
72 | int last_image; | 72 | int last_image; |
73 | 73 | ||
74 | /* IORESOURCE_ROM_SHADOW only set on x86 */ | 74 | /* |
75 | * IORESOURCE_ROM_SHADOW set if the VGA enable bit of the Bridge Control | ||
76 | * register is set for embedded VGA. | ||
77 | */ | ||
75 | if (res->flags & IORESOURCE_ROM_SHADOW) { | 78 | if (res->flags & IORESOURCE_ROM_SHADOW) { |
76 | /* primary video rom always starts here */ | 79 | /* primary video rom always starts here */ |
77 | start = (loff_t)0xC0000; | 80 | start = (loff_t)0xC0000; |
diff --git a/drivers/pci/search.c b/drivers/pci/search.c index d529462d1b53..2f13eba5d5ae 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c | |||
@@ -140,6 +140,31 @@ struct pci_dev * pci_get_slot(struct pci_bus *bus, unsigned int devfn) | |||
140 | } | 140 | } |
141 | 141 | ||
142 | /** | 142 | /** |
143 | * pci_get_bus_and_slot - locate PCI device from a given PCI slot | ||
144 | * @bus: number of PCI bus on which desired PCI device resides | ||
145 | * @devfn: encodes number of PCI slot in which the desired PCI | ||
146 | * device resides and the logical device number within that slot | ||
147 | * in case of multi-function devices. | ||
148 | * | ||
149 | * Given a PCI bus and slot/function number, the desired PCI device | ||
150 | * is located in system global list of PCI devices. If the device | ||
151 | * is found, a pointer to its data structure is returned. If no | ||
152 | * device is found, %NULL is returned. The returned device has its | ||
153 | * reference count bumped by one. | ||
154 | */ | ||
155 | |||
156 | struct pci_dev * pci_get_bus_and_slot(unsigned int bus, unsigned int devfn) | ||
157 | { | ||
158 | struct pci_dev *dev = NULL; | ||
159 | |||
160 | while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { | ||
161 | if (dev->bus->number == bus && dev->devfn == devfn) | ||
162 | return dev; | ||
163 | } | ||
164 | return NULL; | ||
165 | } | ||
166 | |||
167 | /** | ||
143 | * pci_find_subsys - begin or continue searching for a PCI device by vendor/subvendor/device/subdevice id | 168 | * pci_find_subsys - begin or continue searching for a PCI device by vendor/subvendor/device/subdevice id |
144 | * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids | 169 | * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids |
145 | * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids | 170 | * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids |
@@ -274,6 +299,45 @@ pci_get_device(unsigned int vendor, unsigned int device, struct pci_dev *from) | |||
274 | return pci_get_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from); | 299 | return pci_get_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from); |
275 | } | 300 | } |
276 | 301 | ||
302 | /** | ||
303 | * pci_get_device_reverse - begin or continue searching for a PCI device by vendor/device id | ||
304 | * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids | ||
305 | * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids | ||
306 | * @from: Previous PCI device found in search, or %NULL for new search. | ||
307 | * | ||
308 | * Iterates through the list of known PCI devices in the reverse order of | ||
309 | * pci_get_device. | ||
310 | * If a PCI device is found with a matching @vendor and @device, the reference | ||
311 | * count to the device is incremented and a pointer to its device structure | ||
312 | * is returned Otherwise, %NULL is returned. A new search is initiated by | ||
313 | * passing %NULL as the @from argument. Otherwise if @from is not %NULL, | ||
314 | * searches continue from next device on the global list. The reference | ||
315 | * count for @from is always decremented if it is not %NULL. | ||
316 | */ | ||
317 | struct pci_dev * | ||
318 | pci_get_device_reverse(unsigned int vendor, unsigned int device, struct pci_dev *from) | ||
319 | { | ||
320 | struct list_head *n; | ||
321 | struct pci_dev *dev; | ||
322 | |||
323 | WARN_ON(in_interrupt()); | ||
324 | down_read(&pci_bus_sem); | ||
325 | n = from ? from->global_list.prev : pci_devices.prev; | ||
326 | |||
327 | while (n && (n != &pci_devices)) { | ||
328 | dev = pci_dev_g(n); | ||
329 | if ((vendor == PCI_ANY_ID || dev->vendor == vendor) && | ||
330 | (device == PCI_ANY_ID || dev->device == device)) | ||
331 | goto exit; | ||
332 | n = n->prev; | ||
333 | } | ||
334 | dev = NULL; | ||
335 | exit: | ||
336 | dev = pci_dev_get(dev); | ||
337 | up_read(&pci_bus_sem); | ||
338 | pci_dev_put(from); | ||
339 | return dev; | ||
340 | } | ||
277 | 341 | ||
278 | /** | 342 | /** |
279 | * pci_find_device_reverse - begin or continue searching for a PCI device by vendor/device id | 343 | * pci_find_device_reverse - begin or continue searching for a PCI device by vendor/device id |
@@ -382,12 +446,16 @@ exit: | |||
382 | } | 446 | } |
383 | EXPORT_SYMBOL(pci_dev_present); | 447 | EXPORT_SYMBOL(pci_dev_present); |
384 | 448 | ||
385 | EXPORT_SYMBOL(pci_find_bus); | ||
386 | EXPORT_SYMBOL(pci_find_next_bus); | ||
387 | EXPORT_SYMBOL(pci_find_device); | 449 | EXPORT_SYMBOL(pci_find_device); |
388 | EXPORT_SYMBOL(pci_find_device_reverse); | 450 | EXPORT_SYMBOL(pci_find_device_reverse); |
389 | EXPORT_SYMBOL(pci_find_slot); | 451 | EXPORT_SYMBOL(pci_find_slot); |
452 | /* For boot time work */ | ||
453 | EXPORT_SYMBOL(pci_find_bus); | ||
454 | EXPORT_SYMBOL(pci_find_next_bus); | ||
455 | /* For everyone */ | ||
390 | EXPORT_SYMBOL(pci_get_device); | 456 | EXPORT_SYMBOL(pci_get_device); |
457 | EXPORT_SYMBOL(pci_get_device_reverse); | ||
391 | EXPORT_SYMBOL(pci_get_subsys); | 458 | EXPORT_SYMBOL(pci_get_subsys); |
392 | EXPORT_SYMBOL(pci_get_slot); | 459 | EXPORT_SYMBOL(pci_get_slot); |
460 | EXPORT_SYMBOL(pci_get_bus_and_slot); | ||
393 | EXPORT_SYMBOL(pci_get_class); | 461 | EXPORT_SYMBOL(pci_get_class); |
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index dc79b0a0059f..379048fdf05d 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c | |||
@@ -776,21 +776,32 @@ static void pnpacpi_encode_dma(struct acpi_resource *resource, | |||
776 | struct resource *p) | 776 | struct resource *p) |
777 | { | 777 | { |
778 | /* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */ | 778 | /* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */ |
779 | if (p->flags & IORESOURCE_DMA_COMPATIBLE) | 779 | switch (p->flags & IORESOURCE_DMA_SPEED_MASK) { |
780 | resource->data.dma.type = ACPI_COMPATIBILITY; | 780 | case IORESOURCE_DMA_TYPEA: |
781 | else if (p->flags & IORESOURCE_DMA_TYPEA) | 781 | resource->data.dma.type = ACPI_TYPE_A; |
782 | resource->data.dma.type = ACPI_TYPE_A; | 782 | break; |
783 | else if (p->flags & IORESOURCE_DMA_TYPEB) | 783 | case IORESOURCE_DMA_TYPEB: |
784 | resource->data.dma.type = ACPI_TYPE_B; | 784 | resource->data.dma.type = ACPI_TYPE_B; |
785 | else if (p->flags & IORESOURCE_DMA_TYPEF) | 785 | break; |
786 | resource->data.dma.type = ACPI_TYPE_F; | 786 | case IORESOURCE_DMA_TYPEF: |
787 | if (p->flags & IORESOURCE_DMA_8BIT) | 787 | resource->data.dma.type = ACPI_TYPE_F; |
788 | resource->data.dma.transfer = ACPI_TRANSFER_8; | 788 | break; |
789 | else if (p->flags & IORESOURCE_DMA_8AND16BIT) | 789 | default: |
790 | resource->data.dma.transfer = ACPI_TRANSFER_8_16; | 790 | resource->data.dma.type = ACPI_COMPATIBILITY; |
791 | else if (p->flags & IORESOURCE_DMA_16BIT) | 791 | } |
792 | resource->data.dma.transfer = ACPI_TRANSFER_16; | 792 | |
793 | resource->data.dma.bus_master = p->flags & IORESOURCE_DMA_MASTER; | 793 | switch (p->flags & IORESOURCE_DMA_TYPE_MASK) { |
794 | case IORESOURCE_DMA_8BIT: | ||
795 | resource->data.dma.transfer = ACPI_TRANSFER_8; | ||
796 | break; | ||
797 | case IORESOURCE_DMA_8AND16BIT: | ||
798 | resource->data.dma.transfer = ACPI_TRANSFER_8_16; | ||
799 | break; | ||
800 | default: | ||
801 | resource->data.dma.transfer = ACPI_TRANSFER_16; | ||
802 | } | ||
803 | |||
804 | resource->data.dma.bus_master = !!(p->flags & IORESOURCE_DMA_MASTER); | ||
794 | resource->data.dma.channel_count = 1; | 805 | resource->data.dma.channel_count = 1; |
795 | resource->data.dma.channels[0] = p->start; | 806 | resource->data.dma.channels[0] = p->start; |
796 | } | 807 | } |
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index d0647d116eaa..79ffef6bfaf8 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c | |||
@@ -203,6 +203,7 @@ dasd_state_basic_to_known(struct dasd_device * device) | |||
203 | rc = dasd_flush_ccw_queue(device, 1); | 203 | rc = dasd_flush_ccw_queue(device, 1); |
204 | if (rc) | 204 | if (rc) |
205 | return rc; | 205 | return rc; |
206 | dasd_clear_timer(device); | ||
206 | 207 | ||
207 | DBF_DEV_EVENT(DBF_EMERG, device, "%p debug area deleted", device); | 208 | DBF_DEV_EVENT(DBF_EMERG, device, "%p debug area deleted", device); |
208 | if (device->debug_area != NULL) { | 209 | if (device->debug_area != NULL) { |
diff --git a/drivers/s390/char/monwriter.c b/drivers/s390/char/monwriter.c index abd02ed501cb..b9b0fc3f812b 100644 --- a/drivers/s390/char/monwriter.c +++ b/drivers/s390/char/monwriter.c | |||
@@ -73,12 +73,15 @@ static inline struct mon_buf *monwrite_find_hdr(struct mon_private *monpriv, | |||
73 | struct mon_buf *entry, *next; | 73 | struct mon_buf *entry, *next; |
74 | 74 | ||
75 | list_for_each_entry_safe(entry, next, &monpriv->list, list) | 75 | list_for_each_entry_safe(entry, next, &monpriv->list, list) |
76 | if (entry->hdr.applid == monhdr->applid && | 76 | if ((entry->hdr.mon_function == monhdr->mon_function || |
77 | monhdr->mon_function == MONWRITE_STOP_INTERVAL) && | ||
78 | entry->hdr.applid == monhdr->applid && | ||
77 | entry->hdr.record_num == monhdr->record_num && | 79 | entry->hdr.record_num == monhdr->record_num && |
78 | entry->hdr.version == monhdr->version && | 80 | entry->hdr.version == monhdr->version && |
79 | entry->hdr.release == monhdr->release && | 81 | entry->hdr.release == monhdr->release && |
80 | entry->hdr.mod_level == monhdr->mod_level) | 82 | entry->hdr.mod_level == monhdr->mod_level) |
81 | return entry; | 83 | return entry; |
84 | |||
82 | return NULL; | 85 | return NULL; |
83 | } | 86 | } |
84 | 87 | ||
@@ -92,7 +95,9 @@ static int monwrite_new_hdr(struct mon_private *monpriv) | |||
92 | monhdr->mon_function > MONWRITE_START_CONFIG || | 95 | monhdr->mon_function > MONWRITE_START_CONFIG || |
93 | monhdr->hdrlen != sizeof(struct monwrite_hdr)) | 96 | monhdr->hdrlen != sizeof(struct monwrite_hdr)) |
94 | return -EINVAL; | 97 | return -EINVAL; |
95 | monbuf = monwrite_find_hdr(monpriv, monhdr); | 98 | monbuf = NULL; |
99 | if (monhdr->mon_function != MONWRITE_GEN_EVENT) | ||
100 | monbuf = monwrite_find_hdr(monpriv, monhdr); | ||
96 | if (monbuf) { | 101 | if (monbuf) { |
97 | if (monhdr->mon_function == MONWRITE_STOP_INTERVAL) { | 102 | if (monhdr->mon_function == MONWRITE_STOP_INTERVAL) { |
98 | monhdr->datalen = monbuf->hdr.datalen; | 103 | monhdr->datalen = monbuf->hdr.datalen; |
@@ -104,7 +109,7 @@ static int monwrite_new_hdr(struct mon_private *monpriv) | |||
104 | kfree(monbuf); | 109 | kfree(monbuf); |
105 | monbuf = NULL; | 110 | monbuf = NULL; |
106 | } | 111 | } |
107 | } else { | 112 | } else if (monhdr->mon_function != MONWRITE_STOP_INTERVAL) { |
108 | if (mon_buf_count >= mon_max_bufs) | 113 | if (mon_buf_count >= mon_max_bufs) |
109 | return -ENOSPC; | 114 | return -ENOSPC; |
110 | monbuf = kzalloc(sizeof(struct mon_buf), GFP_KERNEL); | 115 | monbuf = kzalloc(sizeof(struct mon_buf), GFP_KERNEL); |
@@ -118,7 +123,8 @@ static int monwrite_new_hdr(struct mon_private *monpriv) | |||
118 | } | 123 | } |
119 | monbuf->hdr = *monhdr; | 124 | monbuf->hdr = *monhdr; |
120 | list_add_tail(&monbuf->list, &monpriv->list); | 125 | list_add_tail(&monbuf->list, &monpriv->list); |
121 | mon_buf_count++; | 126 | if (monhdr->mon_function != MONWRITE_GEN_EVENT) |
127 | mon_buf_count++; | ||
122 | } | 128 | } |
123 | monpriv->current_buf = monbuf; | 129 | monpriv->current_buf = monbuf; |
124 | return 0; | 130 | return 0; |
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index fcaf28d7b4eb..de3d0857db9f 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c | |||
@@ -578,9 +578,13 @@ ccw_device_verify_done(struct ccw_device *cdev, int err) | |||
578 | } | 578 | } |
579 | break; | 579 | break; |
580 | case -ETIME: | 580 | case -ETIME: |
581 | /* Reset oper notify indication after verify error. */ | ||
582 | cdev->private->flags.donotify = 0; | ||
581 | ccw_device_done(cdev, DEV_STATE_BOXED); | 583 | ccw_device_done(cdev, DEV_STATE_BOXED); |
582 | break; | 584 | break; |
583 | default: | 585 | default: |
586 | /* Reset oper notify indication after verify error. */ | ||
587 | cdev->private->flags.donotify = 0; | ||
584 | PREPARE_WORK(&cdev->private->kick_work, | 588 | PREPARE_WORK(&cdev->private->kick_work, |
585 | ccw_device_nopath_notify, cdev); | 589 | ccw_device_nopath_notify, cdev); |
586 | queue_work(ccw_device_notify_work, &cdev->private->kick_work); | 590 | queue_work(ccw_device_notify_work, &cdev->private->kick_work); |
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c index 0648ce5bb684..476aa1da5cbc 100644 --- a/drivers/s390/cio/qdio.c +++ b/drivers/s390/cio/qdio.c | |||
@@ -3529,7 +3529,7 @@ do_QDIO(struct ccw_device *cdev,unsigned int callflags, | |||
3529 | #ifdef CONFIG_QDIO_DEBUG | 3529 | #ifdef CONFIG_QDIO_DEBUG |
3530 | char dbf_text[20]; | 3530 | char dbf_text[20]; |
3531 | 3531 | ||
3532 | sprintf(dbf_text,"doQD%04x",cdev->private->sch_no); | 3532 | sprintf(dbf_text,"doQD%04x",cdev->private->schid.sch_no); |
3533 | QDIO_DBF_TEXT3(0,trace,dbf_text); | 3533 | QDIO_DBF_TEXT3(0,trace,dbf_text); |
3534 | #endif /* CONFIG_QDIO_DEBUG */ | 3534 | #endif /* CONFIG_QDIO_DEBUG */ |
3535 | 3535 | ||