diff options
Diffstat (limited to 'arch/parisc/kernel/drivers.c')
| -rw-r--r-- | arch/parisc/kernel/drivers.c | 273 |
1 files changed, 187 insertions, 86 deletions
diff --git a/arch/parisc/kernel/drivers.c b/arch/parisc/kernel/drivers.c index d34bbe7ae0e3..988844a169e6 100644 --- a/arch/parisc/kernel/drivers.c +++ b/arch/parisc/kernel/drivers.c | |||
| @@ -46,36 +46,51 @@ static struct device root = { | |||
| 46 | .bus_id = "parisc", | 46 | .bus_id = "parisc", |
| 47 | }; | 47 | }; |
| 48 | 48 | ||
| 49 | #define for_each_padev(padev) \ | 49 | static inline int check_dev(struct device *dev) |
| 50 | for (padev = next_dev(&root); padev != NULL; \ | 50 | { |
| 51 | padev = next_dev(&padev->dev)) | 51 | if (dev->bus == &parisc_bus_type) { |
| 52 | struct parisc_device *pdev; | ||
| 53 | pdev = to_parisc_device(dev); | ||
| 54 | return pdev->id.hw_type != HPHW_FAULTY; | ||
| 55 | } | ||
| 56 | return 1; | ||
| 57 | } | ||
| 58 | |||
| 59 | static struct device * | ||
| 60 | parse_tree_node(struct device *parent, int index, struct hardware_path *modpath); | ||
| 52 | 61 | ||
| 53 | #define check_dev(padev) \ | 62 | struct recurse_struct { |
| 54 | (padev->id.hw_type != HPHW_FAULTY) ? padev : next_dev(&padev->dev) | 63 | void * obj; |
| 64 | int (*fn)(struct device *, void *); | ||
| 65 | }; | ||
| 66 | |||
| 67 | static int descend_children(struct device * dev, void * data) | ||
| 68 | { | ||
| 69 | struct recurse_struct * recurse_data = (struct recurse_struct *)data; | ||
| 70 | |||
| 71 | if (recurse_data->fn(dev, recurse_data->obj)) | ||
| 72 | return 1; | ||
| 73 | else | ||
| 74 | return device_for_each_child(dev, recurse_data, descend_children); | ||
| 75 | } | ||
| 55 | 76 | ||
| 56 | /** | 77 | /** |
| 57 | * next_dev - enumerates registered devices | 78 | * for_each_padev - Iterate over all devices in the tree |
| 58 | * @dev: the previous device returned from next_dev | 79 | * @fn: Function to call for each device. |
| 80 | * @data: Data to pass to the called function. | ||
| 59 | * | 81 | * |
| 60 | * next_dev does a depth-first search of the tree, returning parents | 82 | * This performs a depth-first traversal of the tree, calling the |
| 61 | * before children. Returns NULL when there are no more devices. | 83 | * function passed for each node. It calls the function for parents |
| 84 | * before children. | ||
| 62 | */ | 85 | */ |
| 63 | static struct parisc_device *next_dev(struct device *dev) | ||
| 64 | { | ||
| 65 | if (!list_empty(&dev->children)) { | ||
| 66 | dev = list_to_dev(dev->children.next); | ||
| 67 | return check_dev(to_parisc_device(dev)); | ||
| 68 | } | ||
| 69 | 86 | ||
| 70 | while (dev != &root) { | 87 | static int for_each_padev(int (*fn)(struct device *, void *), void * data) |
| 71 | if (dev->node.next != &dev->parent->children) { | 88 | { |
| 72 | dev = list_to_dev(dev->node.next); | 89 | struct recurse_struct recurse_data = { |
| 73 | return to_parisc_device(dev); | 90 | .obj = data, |
| 74 | } | 91 | .fn = fn, |
| 75 | dev = dev->parent; | 92 | }; |
| 76 | } | 93 | return device_for_each_child(&root, &recurse_data, descend_children); |
| 77 | |||
| 78 | return NULL; | ||
| 79 | } | 94 | } |
| 80 | 95 | ||
| 81 | /** | 96 | /** |
| @@ -105,12 +120,6 @@ static int match_device(struct parisc_driver *driver, struct parisc_device *dev) | |||
| 105 | return 0; | 120 | return 0; |
| 106 | } | 121 | } |
| 107 | 122 | ||
| 108 | static void claim_device(struct parisc_driver *driver, struct parisc_device *dev) | ||
| 109 | { | ||
| 110 | dev->driver = driver; | ||
| 111 | request_mem_region(dev->hpa, 0x1000, driver->name); | ||
| 112 | } | ||
| 113 | |||
| 114 | static int parisc_driver_probe(struct device *dev) | 123 | static int parisc_driver_probe(struct device *dev) |
| 115 | { | 124 | { |
| 116 | int rc; | 125 | int rc; |
| @@ -119,8 +128,8 @@ static int parisc_driver_probe(struct device *dev) | |||
| 119 | 128 | ||
| 120 | rc = pa_drv->probe(pa_dev); | 129 | rc = pa_drv->probe(pa_dev); |
| 121 | 130 | ||
| 122 | if(!rc) | 131 | if (!rc) |
| 123 | claim_device(pa_drv, pa_dev); | 132 | pa_dev->driver = pa_drv; |
| 124 | 133 | ||
| 125 | return rc; | 134 | return rc; |
| 126 | } | 135 | } |
| @@ -131,7 +140,6 @@ static int parisc_driver_remove(struct device *dev) | |||
| 131 | struct parisc_driver *pa_drv = to_parisc_driver(dev->driver); | 140 | struct parisc_driver *pa_drv = to_parisc_driver(dev->driver); |
| 132 | if (pa_drv->remove) | 141 | if (pa_drv->remove) |
| 133 | pa_drv->remove(pa_dev); | 142 | pa_drv->remove(pa_dev); |
| 134 | release_mem_region(pa_dev->hpa, 0x1000); | ||
| 135 | 143 | ||
| 136 | return 0; | 144 | return 0; |
| 137 | } | 145 | } |
| @@ -173,6 +181,24 @@ int register_parisc_driver(struct parisc_driver *driver) | |||
| 173 | } | 181 | } |
| 174 | EXPORT_SYMBOL(register_parisc_driver); | 182 | EXPORT_SYMBOL(register_parisc_driver); |
| 175 | 183 | ||
| 184 | |||
| 185 | struct match_count { | ||
| 186 | struct parisc_driver * driver; | ||
| 187 | int count; | ||
| 188 | }; | ||
| 189 | |||
| 190 | static int match_and_count(struct device * dev, void * data) | ||
| 191 | { | ||
| 192 | struct match_count * m = data; | ||
| 193 | struct parisc_device * pdev = to_parisc_device(dev); | ||
| 194 | |||
| 195 | if (check_dev(dev)) { | ||
| 196 | if (match_device(m->driver, pdev)) | ||
| 197 | m->count++; | ||
| 198 | } | ||
| 199 | return 0; | ||
| 200 | } | ||
| 201 | |||
| 176 | /** | 202 | /** |
| 177 | * count_parisc_driver - count # of devices this driver would match | 203 | * count_parisc_driver - count # of devices this driver would match |
| 178 | * @driver: the PA-RISC driver to try | 204 | * @driver: the PA-RISC driver to try |
| @@ -182,15 +208,14 @@ EXPORT_SYMBOL(register_parisc_driver); | |||
| 182 | */ | 208 | */ |
| 183 | int count_parisc_driver(struct parisc_driver *driver) | 209 | int count_parisc_driver(struct parisc_driver *driver) |
| 184 | { | 210 | { |
| 185 | struct parisc_device *device; | 211 | struct match_count m = { |
| 186 | int cnt = 0; | 212 | .driver = driver, |
| 213 | .count = 0, | ||
| 214 | }; | ||
| 187 | 215 | ||
| 188 | for_each_padev(device) { | 216 | for_each_padev(match_and_count, &m); |
| 189 | if (match_device(driver, device)) | ||
| 190 | cnt++; | ||
| 191 | } | ||
| 192 | 217 | ||
| 193 | return cnt; | 218 | return m.count; |
| 194 | } | 219 | } |
| 195 | 220 | ||
| 196 | 221 | ||
| @@ -206,14 +231,34 @@ int unregister_parisc_driver(struct parisc_driver *driver) | |||
| 206 | } | 231 | } |
| 207 | EXPORT_SYMBOL(unregister_parisc_driver); | 232 | EXPORT_SYMBOL(unregister_parisc_driver); |
| 208 | 233 | ||
| 209 | static struct parisc_device *find_device_by_addr(unsigned long hpa) | 234 | struct find_data { |
| 235 | unsigned long hpa; | ||
| 236 | struct parisc_device * dev; | ||
| 237 | }; | ||
| 238 | |||
| 239 | static int find_device(struct device * dev, void * data) | ||
| 210 | { | 240 | { |
| 211 | struct parisc_device *dev; | 241 | struct parisc_device * pdev = to_parisc_device(dev); |
| 212 | for_each_padev(dev) { | 242 | struct find_data * d = (struct find_data*)data; |
| 213 | if (dev->hpa == hpa) | 243 | |
| 214 | return dev; | 244 | if (check_dev(dev)) { |
| 245 | if (pdev->hpa.start == d->hpa) { | ||
| 246 | d->dev = pdev; | ||
| 247 | return 1; | ||
| 248 | } | ||
| 215 | } | 249 | } |
| 216 | return NULL; | 250 | return 0; |
| 251 | } | ||
| 252 | |||
| 253 | static struct parisc_device *find_device_by_addr(unsigned long hpa) | ||
| 254 | { | ||
| 255 | struct find_data d = { | ||
| 256 | .hpa = hpa, | ||
| 257 | }; | ||
| 258 | int ret; | ||
| 259 | |||
| 260 | ret = for_each_padev(find_device, &d); | ||
| 261 | return ret ? d.dev : NULL; | ||
| 217 | } | 262 | } |
| 218 | 263 | ||
| 219 | /** | 264 | /** |
| @@ -387,6 +432,23 @@ struct parisc_device * create_tree_node(char id, struct device *parent) | |||
| 387 | return dev; | 432 | return dev; |
| 388 | } | 433 | } |
| 389 | 434 | ||
| 435 | struct match_id_data { | ||
| 436 | char id; | ||
| 437 | struct parisc_device * dev; | ||
| 438 | }; | ||
| 439 | |||
| 440 | static int match_by_id(struct device * dev, void * data) | ||
| 441 | { | ||
| 442 | struct parisc_device * pdev = to_parisc_device(dev); | ||
| 443 | struct match_id_data * d = data; | ||
| 444 | |||
| 445 | if (pdev->hw_path == d->id) { | ||
| 446 | d->dev = pdev; | ||
| 447 | return 1; | ||
| 448 | } | ||
| 449 | return 0; | ||
| 450 | } | ||
| 451 | |||
| 390 | /** | 452 | /** |
| 391 | * alloc_tree_node - returns a device entry in the iotree | 453 | * alloc_tree_node - returns a device entry in the iotree |
| 392 | * @parent: the parent node in the tree | 454 | * @parent: the parent node in the tree |
| @@ -397,15 +459,13 @@ struct parisc_device * create_tree_node(char id, struct device *parent) | |||
| 397 | */ | 459 | */ |
| 398 | static struct parisc_device * alloc_tree_node(struct device *parent, char id) | 460 | static struct parisc_device * alloc_tree_node(struct device *parent, char id) |
| 399 | { | 461 | { |
| 400 | struct device *dev; | 462 | struct match_id_data d = { |
| 401 | 463 | .id = id, | |
| 402 | list_for_each_entry(dev, &parent->children, node) { | 464 | }; |
| 403 | struct parisc_device *padev = to_parisc_device(dev); | 465 | if (device_for_each_child(parent, &d, match_by_id)) |
| 404 | if (padev->hw_path == id) | 466 | return d.dev; |
| 405 | return padev; | 467 | else |
| 406 | } | 468 | return create_tree_node(id, parent); |
| 407 | |||
| 408 | return create_tree_node(id, parent); | ||
| 409 | } | 469 | } |
| 410 | 470 | ||
| 411 | static struct parisc_device *create_parisc_device(struct hardware_path *modpath) | 471 | static struct parisc_device *create_parisc_device(struct hardware_path *modpath) |
| @@ -439,10 +499,8 @@ alloc_pa_dev(unsigned long hpa, struct hardware_path *mod_path) | |||
| 439 | 499 | ||
| 440 | dev = create_parisc_device(mod_path); | 500 | dev = create_parisc_device(mod_path); |
| 441 | if (dev->id.hw_type != HPHW_FAULTY) { | 501 | if (dev->id.hw_type != HPHW_FAULTY) { |
| 442 | char p[64]; | ||
| 443 | print_pa_hwpath(dev, p); | ||
| 444 | printk("Two devices have hardware path %s. Please file a bug with HP.\n" | 502 | printk("Two devices have hardware path %s. Please file a bug with HP.\n" |
| 445 | "In the meantime, you could try rearranging your cards.\n", p); | 503 | "In the meantime, you could try rearranging your cards.\n", parisc_pathname(dev)); |
| 446 | return NULL; | 504 | return NULL; |
| 447 | } | 505 | } |
| 448 | 506 | ||
| @@ -451,12 +509,27 @@ alloc_pa_dev(unsigned long hpa, struct hardware_path *mod_path) | |||
| 451 | dev->id.hversion_rev = iodc_data[1] & 0x0f; | 509 | dev->id.hversion_rev = iodc_data[1] & 0x0f; |
| 452 | dev->id.sversion = ((iodc_data[4] & 0x0f) << 16) | | 510 | dev->id.sversion = ((iodc_data[4] & 0x0f) << 16) | |
| 453 | (iodc_data[5] << 8) | iodc_data[6]; | 511 | (iodc_data[5] << 8) | iodc_data[6]; |
| 454 | dev->hpa = hpa; | 512 | dev->hpa.name = parisc_pathname(dev); |
| 513 | dev->hpa.start = hpa; | ||
| 514 | if (hpa == 0xf4000000 || hpa == 0xf6000000 || | ||
| 515 | hpa == 0xf8000000 || hpa == 0xfa000000) { | ||
| 516 | dev->hpa.end = hpa + 0x01ffffff; | ||
| 517 | } else { | ||
| 518 | dev->hpa.end = hpa + 0xfff; | ||
| 519 | } | ||
| 520 | dev->hpa.flags = IORESOURCE_MEM; | ||
| 455 | name = parisc_hardware_description(&dev->id); | 521 | name = parisc_hardware_description(&dev->id); |
| 456 | if (name) { | 522 | if (name) { |
| 457 | strlcpy(dev->name, name, sizeof(dev->name)); | 523 | strlcpy(dev->name, name, sizeof(dev->name)); |
| 458 | } | 524 | } |
| 459 | 525 | ||
| 526 | /* Silently fail things like mouse ports which are subsumed within | ||
| 527 | * the keyboard controller | ||
| 528 | */ | ||
| 529 | if ((hpa & 0xfff) == 0 && insert_resource(&iomem_resource, &dev->hpa)) | ||
| 530 | printk("Unable to claim HPA %lx for device %s\n", | ||
| 531 | hpa, name); | ||
| 532 | |||
| 460 | return dev; | 533 | return dev; |
| 461 | } | 534 | } |
| 462 | 535 | ||
| @@ -555,6 +628,33 @@ static int match_parisc_device(struct device *dev, int index, | |||
| 555 | return (curr->hw_path == id); | 628 | return (curr->hw_path == id); |
| 556 | } | 629 | } |
| 557 | 630 | ||
| 631 | struct parse_tree_data { | ||
| 632 | int index; | ||
| 633 | struct hardware_path * modpath; | ||
| 634 | struct device * dev; | ||
| 635 | }; | ||
| 636 | |||
| 637 | static int check_parent(struct device * dev, void * data) | ||
| 638 | { | ||
| 639 | struct parse_tree_data * d = data; | ||
| 640 | |||
| 641 | if (check_dev(dev)) { | ||
| 642 | if (dev->bus == &parisc_bus_type) { | ||
| 643 | if (match_parisc_device(dev, d->index, d->modpath)) | ||
| 644 | d->dev = dev; | ||
| 645 | } else if (is_pci_dev(dev)) { | ||
| 646 | if (match_pci_device(dev, d->index, d->modpath)) | ||
| 647 | d->dev = dev; | ||
| 648 | } else if (dev->bus == NULL) { | ||
| 649 | /* we are on a bus bridge */ | ||
| 650 | struct device *new = parse_tree_node(dev, d->index, d->modpath); | ||
| 651 | if (new) | ||
| 652 | d->dev = new; | ||
| 653 | } | ||
| 654 | } | ||
| 655 | return d->dev != NULL; | ||
| 656 | } | ||
| 657 | |||
| 558 | /** | 658 | /** |
| 559 | * parse_tree_node - returns a device entry in the iotree | 659 | * parse_tree_node - returns a device entry in the iotree |
| 560 | * @parent: the parent node in the tree | 660 | * @parent: the parent node in the tree |
| @@ -568,24 +668,18 @@ static int match_parisc_device(struct device *dev, int index, | |||
| 568 | static struct device * | 668 | static struct device * |
| 569 | parse_tree_node(struct device *parent, int index, struct hardware_path *modpath) | 669 | parse_tree_node(struct device *parent, int index, struct hardware_path *modpath) |
| 570 | { | 670 | { |
| 571 | struct device *device; | 671 | struct parse_tree_data d = { |
| 572 | 672 | .index = index, | |
| 573 | list_for_each_entry(device, &parent->children, node) { | 673 | .modpath = modpath, |
| 574 | if (device->bus == &parisc_bus_type) { | 674 | }; |
| 575 | if (match_parisc_device(device, index, modpath)) | ||
| 576 | return device; | ||
| 577 | } else if (is_pci_dev(device)) { | ||
| 578 | if (match_pci_device(device, index, modpath)) | ||
| 579 | return device; | ||
| 580 | } else if (device->bus == NULL) { | ||
| 581 | /* we are on a bus bridge */ | ||
| 582 | struct device *new = parse_tree_node(device, index, modpath); | ||
| 583 | if (new) | ||
| 584 | return new; | ||
| 585 | } | ||
| 586 | } | ||
| 587 | 675 | ||
| 588 | return NULL; | 676 | struct recurse_struct recurse_data = { |
| 677 | .obj = &d, | ||
| 678 | .fn = check_parent, | ||
| 679 | }; | ||
| 680 | |||
| 681 | device_for_each_child(parent, &recurse_data, descend_children); | ||
| 682 | return d.dev; | ||
| 589 | } | 683 | } |
| 590 | 684 | ||
| 591 | /** | 685 | /** |
| @@ -636,7 +730,7 @@ EXPORT_SYMBOL(device_to_hwpath); | |||
| 636 | ((dev->id.hw_type == HPHW_IOA) || (dev->id.hw_type == HPHW_BCPORT)) | 730 | ((dev->id.hw_type == HPHW_IOA) || (dev->id.hw_type == HPHW_BCPORT)) |
| 637 | 731 | ||
| 638 | #define IS_LOWER_PORT(dev) \ | 732 | #define IS_LOWER_PORT(dev) \ |
| 639 | ((gsc_readl(dev->hpa + offsetof(struct bc_module, io_status)) \ | 733 | ((gsc_readl(dev->hpa.start + offsetof(struct bc_module, io_status)) \ |
| 640 | & BC_PORT_MASK) == BC_LOWER_PORT) | 734 | & BC_PORT_MASK) == BC_LOWER_PORT) |
| 641 | 735 | ||
| 642 | #define MAX_NATIVE_DEVICES 64 | 736 | #define MAX_NATIVE_DEVICES 64 |
| @@ -645,8 +739,8 @@ EXPORT_SYMBOL(device_to_hwpath); | |||
| 645 | #define FLEX_MASK F_EXTEND(0xfffc0000) | 739 | #define FLEX_MASK F_EXTEND(0xfffc0000) |
| 646 | #define IO_IO_LOW offsetof(struct bc_module, io_io_low) | 740 | #define IO_IO_LOW offsetof(struct bc_module, io_io_low) |
| 647 | #define IO_IO_HIGH offsetof(struct bc_module, io_io_high) | 741 | #define IO_IO_HIGH offsetof(struct bc_module, io_io_high) |
| 648 | #define READ_IO_IO_LOW(dev) (unsigned long)(signed int)gsc_readl(dev->hpa + IO_IO_LOW) | 742 | #define READ_IO_IO_LOW(dev) (unsigned long)(signed int)gsc_readl(dev->hpa.start + IO_IO_LOW) |
| 649 | #define READ_IO_IO_HIGH(dev) (unsigned long)(signed int)gsc_readl(dev->hpa + IO_IO_HIGH) | 743 | #define READ_IO_IO_HIGH(dev) (unsigned long)(signed int)gsc_readl(dev->hpa.start + IO_IO_HIGH) |
| 650 | 744 | ||
| 651 | static void walk_native_bus(unsigned long io_io_low, unsigned long io_io_high, | 745 | static void walk_native_bus(unsigned long io_io_low, unsigned long io_io_high, |
| 652 | struct device *parent); | 746 | struct device *parent); |
| @@ -655,10 +749,10 @@ void walk_lower_bus(struct parisc_device *dev) | |||
| 655 | { | 749 | { |
| 656 | unsigned long io_io_low, io_io_high; | 750 | unsigned long io_io_low, io_io_high; |
| 657 | 751 | ||
| 658 | if(!BUS_CONVERTER(dev) || IS_LOWER_PORT(dev)) | 752 | if (!BUS_CONVERTER(dev) || IS_LOWER_PORT(dev)) |
| 659 | return; | 753 | return; |
| 660 | 754 | ||
| 661 | if(dev->id.hw_type == HPHW_IOA) { | 755 | if (dev->id.hw_type == HPHW_IOA) { |
| 662 | io_io_low = (unsigned long)(signed int)(READ_IO_IO_LOW(dev) << 16); | 756 | io_io_low = (unsigned long)(signed int)(READ_IO_IO_LOW(dev) << 16); |
| 663 | io_io_high = io_io_low + MAX_NATIVE_DEVICES * NATIVE_DEVICE_OFFSET; | 757 | io_io_high = io_io_low + MAX_NATIVE_DEVICES * NATIVE_DEVICE_OFFSET; |
| 664 | } else { | 758 | } else { |
| @@ -731,7 +825,7 @@ static void print_parisc_device(struct parisc_device *dev) | |||
| 731 | 825 | ||
| 732 | print_pa_hwpath(dev, hw_path); | 826 | print_pa_hwpath(dev, hw_path); |
| 733 | printk(KERN_INFO "%d. %s at 0x%lx [%s] { %d, 0x%x, 0x%.3x, 0x%.5x }", | 827 | printk(KERN_INFO "%d. %s at 0x%lx [%s] { %d, 0x%x, 0x%.3x, 0x%.5x }", |
| 734 | ++count, dev->name, dev->hpa, hw_path, dev->id.hw_type, | 828 | ++count, dev->name, dev->hpa.start, hw_path, dev->id.hw_type, |
| 735 | dev->id.hversion_rev, dev->id.hversion, dev->id.sversion); | 829 | dev->id.hversion_rev, dev->id.hversion, dev->id.sversion); |
| 736 | 830 | ||
| 737 | if (dev->num_addrs) { | 831 | if (dev->num_addrs) { |
| @@ -753,13 +847,20 @@ void init_parisc_bus(void) | |||
| 753 | get_device(&root); | 847 | get_device(&root); |
| 754 | } | 848 | } |
| 755 | 849 | ||
| 850 | |||
| 851 | static int print_one_device(struct device * dev, void * data) | ||
| 852 | { | ||
| 853 | struct parisc_device * pdev = to_parisc_device(dev); | ||
| 854 | |||
| 855 | if (check_dev(dev)) | ||
| 856 | print_parisc_device(pdev); | ||
| 857 | return 0; | ||
| 858 | } | ||
| 859 | |||
| 756 | /** | 860 | /** |
| 757 | * print_parisc_devices - Print out a list of devices found in this system | 861 | * print_parisc_devices - Print out a list of devices found in this system |
| 758 | */ | 862 | */ |
| 759 | void print_parisc_devices(void) | 863 | void print_parisc_devices(void) |
| 760 | { | 864 | { |
| 761 | struct parisc_device *dev; | 865 | for_each_padev(print_one_device, NULL); |
| 762 | for_each_padev(dev) { | ||
| 763 | print_parisc_device(dev); | ||
| 764 | } | ||
| 765 | } | 866 | } |
