diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-12-28 16:54:33 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-12-28 16:54:33 -0800 |
commit | 3c92ec8ae91ecf59d88c798301833d7cf83f2179 (patch) | |
tree | 08a38cd3523c42bd49882f17cd501fd879e7ca1c /drivers/char/bsr.c | |
parent | c4c9f0183b7c4e97836e8fecbb67898b06c47e78 (diff) | |
parent | ca9153a3a2a7556d091dfe080e42b0e67881fff6 (diff) | |
download | linux-3c92ec8ae91ecf59d88c798301833d7cf83f2179.tar.bz2 |
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc: (144 commits)
powerpc/44x: Support 16K/64K base page sizes on 44x
powerpc: Force memory size to be a multiple of PAGE_SIZE
powerpc/32: Wire up the trampoline code for kdump
powerpc/32: Add the ability for a classic ppc kernel to be loaded at 32M
powerpc/32: Allow __ioremap on RAM addresses for kdump kernel
powerpc/32: Setup OF properties for kdump
powerpc/32/kdump: Implement crash_setup_regs() using ppc_save_regs()
powerpc: Prepare xmon_save_regs for use with kdump
powerpc: Remove default kexec/crash_kernel ops assignments
powerpc: Make default kexec/crash_kernel ops implicit
powerpc: Setup OF properties for ppc32 kexec
powerpc/pseries: Fix cpu hotplug
powerpc: Fix KVM build on ppc440
powerpc/cell: add QPACE as a separate Cell platform
powerpc/cell: fix build breakage with CONFIG_SPUFS disabled
powerpc/mpc5200: fix error paths in PSC UART probe function
powerpc/mpc5200: add rts/cts handling in PSC UART driver
powerpc/mpc5200: Make PSC UART driver update serial errors counters
powerpc/mpc5200: Remove obsolete code from mpc5200 MDIO driver
powerpc/mpc5200: Add MDMA/UDMA support to MPC5200 ATA driver
...
Fix trivial conflict in drivers/char/Makefile as per Paul's directions
Diffstat (limited to 'drivers/char/bsr.c')
-rw-r--r-- | drivers/char/bsr.c | 84 |
1 files changed, 55 insertions, 29 deletions
diff --git a/drivers/char/bsr.c b/drivers/char/bsr.c index 456f54db73e2..977dfb1096a0 100644 --- a/drivers/char/bsr.c +++ b/drivers/char/bsr.c @@ -60,6 +60,8 @@ struct bsr_dev { unsigned bsr_num; /* bsr id number for its type */ int bsr_minor; + struct list_head bsr_list; + dev_t bsr_dev; struct cdev bsr_cdev; struct device *bsr_device; @@ -67,8 +69,8 @@ struct bsr_dev { }; -static unsigned num_bsr_devs; -static struct bsr_dev *bsr_devs; +static unsigned total_bsr_devs; +static struct list_head bsr_devs = LIST_HEAD_INIT(bsr_devs); static struct class *bsr_class; static int bsr_major; @@ -146,24 +148,25 @@ const static struct file_operations bsr_fops = { static void bsr_cleanup_devs(void) { - int i; - for (i=0 ; i < num_bsr_devs; i++) { - struct bsr_dev *cur = bsr_devs + i; + struct bsr_dev *cur, *n; + + list_for_each_entry_safe(cur, n, &bsr_devs, bsr_list) { if (cur->bsr_device) { cdev_del(&cur->bsr_cdev); device_del(cur->bsr_device); } + list_del(&cur->bsr_list); + kfree(cur); } - - kfree(bsr_devs); } -static int bsr_create_devs(struct device_node *bn) +static int bsr_add_node(struct device_node *bn) { - int bsr_stride_len, bsr_bytes_len; + int bsr_stride_len, bsr_bytes_len, num_bsr_devs; const u32 *bsr_stride; const u32 *bsr_bytes; unsigned i; + int ret = -ENODEV; bsr_stride = of_get_property(bn, "ibm,lock-stride", &bsr_stride_len); bsr_bytes = of_get_property(bn, "ibm,#lock-bytes", &bsr_bytes_len); @@ -171,35 +174,36 @@ static int bsr_create_devs(struct device_node *bn) if (!bsr_stride || !bsr_bytes || (bsr_stride_len != bsr_bytes_len)) { printk(KERN_ERR "bsr of-node has missing/incorrect property\n"); - return -ENODEV; + return ret; } num_bsr_devs = bsr_bytes_len / sizeof(u32); - /* only a warning, its informational since we'll fail and exit */ - WARN_ON(num_bsr_devs > BSR_MAX_DEVS); - - bsr_devs = kzalloc(sizeof(struct bsr_dev) * num_bsr_devs, GFP_KERNEL); - if (!bsr_devs) - return -ENOMEM; - for (i = 0 ; i < num_bsr_devs; i++) { - struct bsr_dev *cur = bsr_devs + i; + struct bsr_dev *cur = kzalloc(sizeof(struct bsr_dev), + GFP_KERNEL); struct resource res; int result; + if (!cur) { + printk(KERN_ERR "Unable to alloc bsr dev\n"); + ret = -ENOMEM; + goto out_err; + } + result = of_address_to_resource(bn, i, &res); if (result < 0) { - printk(KERN_ERR "bsr of-node has invalid reg property\n"); - goto out_err; + printk(KERN_ERR "bsr of-node has invalid reg property, skipping\n"); + kfree(cur); + continue; } - cur->bsr_minor = i; + cur->bsr_minor = i + total_bsr_devs; cur->bsr_addr = res.start; cur->bsr_len = res.end - res.start + 1; cur->bsr_bytes = bsr_bytes[i]; cur->bsr_stride = bsr_stride[i]; - cur->bsr_dev = MKDEV(bsr_major, i); + cur->bsr_dev = MKDEV(bsr_major, i + total_bsr_devs); switch(cur->bsr_bytes) { case 8: @@ -220,14 +224,15 @@ static int bsr_create_devs(struct device_node *bn) } cur->bsr_num = bsr_types[cur->bsr_type]; - bsr_types[cur->bsr_type] = cur->bsr_num + 1; snprintf(cur->bsr_name, 32, "bsr%d_%d", cur->bsr_bytes, cur->bsr_num); cdev_init(&cur->bsr_cdev, &bsr_fops); result = cdev_add(&cur->bsr_cdev, cur->bsr_dev, 1); - if (result) + if (result) { + kfree(cur); goto out_err; + } cur->bsr_device = device_create(bsr_class, NULL, cur->bsr_dev, cur, cur->bsr_name); @@ -235,16 +240,37 @@ static int bsr_create_devs(struct device_node *bn) printk(KERN_ERR "device_create failed for %s\n", cur->bsr_name); cdev_del(&cur->bsr_cdev); + kfree(cur); goto out_err; } + + bsr_types[cur->bsr_type] = cur->bsr_num + 1; + list_add_tail(&cur->bsr_list, &bsr_devs); } + total_bsr_devs += num_bsr_devs; + return 0; out_err: bsr_cleanup_devs(); - return -ENODEV; + return ret; +} + +static int bsr_create_devs(struct device_node *bn) +{ + int ret; + + while (bn) { + ret = bsr_add_node(bn); + if (ret) { + of_node_put(bn); + return ret; + } + bn = of_find_compatible_node(bn, NULL, "ibm,bsr"); + } + return 0; } static int __init bsr_init(void) @@ -254,7 +280,7 @@ static int __init bsr_init(void) int ret = -ENODEV; int result; - np = of_find_compatible_node(NULL, "ibm,bsr", "ibm,bsr"); + np = of_find_compatible_node(NULL, NULL, "ibm,bsr"); if (!np) goto out_err; @@ -272,10 +298,10 @@ static int __init bsr_init(void) goto out_err_2; } - if ((ret = bsr_create_devs(np)) < 0) + if ((ret = bsr_create_devs(np)) < 0) { + np = NULL; goto out_err_3; - - of_node_put(np); + } return 0; |