1 Subject: Add support for multiple BSR nodes in the device tree.
2 From: Sonny Rao <sonnyrao@us.ibm.com>
3 References: 443665 - LTC49817
5 Previously, the BSR driver only supported a single OF node describing
6 a BSR. Apparently when an LPAR is set to use "all system resources"
7 the BSR appears as a single node, but when it is handed out in pieces,
8 each 8 byte piece gets its own node. So, keep a list of bsr devices
9 instead of the array and include all nodes.
11 Also, be more inclusive of what BSR devices we accept by only checking
12 compatibility and not the device name property (which might change in
13 the future versions of BSR).
15 Signed-off-by: Sonny Rao <sonnyrao@us.ibm.com>
16 Signed-off-by: Olaf Hering <olh@suse.de>
19 drivers/char/bsr.c | 84 ++++++++++++++++++++++++++++++++++-------------------
20 1 file changed, 55 insertions(+), 29 deletions(-)
22 --- a/drivers/char/bsr.c
23 +++ b/drivers/char/bsr.c
24 @@ -61,6 +61,8 @@ struct bsr_dev {
25 unsigned bsr_num; /* bsr id number for its type */
28 + struct list_head bsr_list;
32 struct device *bsr_device;
33 @@ -68,8 +70,8 @@ struct bsr_dev {
37 -static unsigned num_bsr_devs;
38 -static struct bsr_dev *bsr_devs;
39 +static unsigned total_bsr_devs;
40 +static struct list_head bsr_devs = LIST_HEAD_INIT(bsr_devs);
41 static struct class *bsr_class;
44 @@ -154,24 +156,25 @@ const static struct file_operations bsr_
46 static void bsr_cleanup_devs(void)
49 - for (i=0 ; i < num_bsr_devs; i++) {
50 - struct bsr_dev *cur = bsr_devs + i;
51 + struct bsr_dev *cur, *n;
53 + list_for_each_entry_safe(cur, n, &bsr_devs, bsr_list) {
54 if (cur->bsr_device) {
55 cdev_del(&cur->bsr_cdev);
56 device_del(cur->bsr_device);
58 + list_del(&cur->bsr_list);
65 -static int bsr_create_devs(struct device_node *bn)
66 +static int bsr_add_node(struct device_node *bn)
68 - int bsr_stride_len, bsr_bytes_len;
69 + int bsr_stride_len, bsr_bytes_len, num_bsr_devs;
70 const u32 *bsr_stride;
75 bsr_stride = of_get_property(bn, "ibm,lock-stride", &bsr_stride_len);
76 bsr_bytes = of_get_property(bn, "ibm,#lock-bytes", &bsr_bytes_len);
77 @@ -179,35 +182,36 @@ static int bsr_create_devs(struct device
78 if (!bsr_stride || !bsr_bytes ||
79 (bsr_stride_len != bsr_bytes_len)) {
80 printk(KERN_ERR "bsr of-node has missing/incorrect property\n");
85 num_bsr_devs = bsr_bytes_len / sizeof(u32);
87 - /* only a warning, its informational since we'll fail and exit */
88 - WARN_ON(num_bsr_devs > BSR_MAX_DEVS);
90 - bsr_devs = kzalloc(sizeof(struct bsr_dev) * num_bsr_devs, GFP_KERNEL);
94 for (i = 0 ; i < num_bsr_devs; i++) {
95 - struct bsr_dev *cur = bsr_devs + i;
96 + struct bsr_dev *cur = kzalloc(sizeof(struct bsr_dev),
102 + printk(KERN_ERR "Unable to alloc bsr dev\n");
107 result = of_address_to_resource(bn, i, &res);
109 - printk(KERN_ERR "bsr of-node has invalid reg property\n");
111 + printk(KERN_ERR "bsr of-node has invalid reg property, skipping\n");
116 - cur->bsr_minor = i;
117 + cur->bsr_minor = i + total_bsr_devs;
118 cur->bsr_addr = res.start;
119 cur->bsr_len = res.end - res.start + 1;
120 cur->bsr_bytes = bsr_bytes[i];
121 cur->bsr_stride = bsr_stride[i];
122 - cur->bsr_dev = MKDEV(bsr_major, i);
123 + cur->bsr_dev = MKDEV(bsr_major, i + total_bsr_devs);
125 switch(cur->bsr_bytes) {
127 @@ -228,14 +232,15 @@ static int bsr_create_devs(struct device
130 cur->bsr_num = bsr_types[cur->bsr_type];
131 - bsr_types[cur->bsr_type] = cur->bsr_num + 1;
132 snprintf(cur->bsr_name, 32, "bsr%d_%d",
133 cur->bsr_bytes, cur->bsr_num);
135 cdev_init(&cur->bsr_cdev, &bsr_fops);
136 result = cdev_add(&cur->bsr_cdev, cur->bsr_dev, 1);
143 cur->bsr_device = device_create_drvdata(bsr_class, NULL,
145 @@ -244,16 +249,37 @@ static int bsr_create_devs(struct device
146 printk(KERN_ERR "device_create failed for %s\n",
148 cdev_del(&cur->bsr_cdev);
153 + bsr_types[cur->bsr_type] = cur->bsr_num + 1;
154 + list_add_tail(&cur->bsr_list, &bsr_devs);
157 + total_bsr_devs += num_bsr_devs;
168 +static int bsr_create_devs(struct device_node *bn)
173 + ret = bsr_add_node(bn);
178 + bn = of_find_compatible_node(bn, NULL, "ibm,bsr");
183 static int __init bsr_init(void)
184 @@ -263,7 +289,7 @@ static int __init bsr_init(void)
188 - np = of_find_compatible_node(NULL, "ibm,bsr", "ibm,bsr");
189 + np = of_find_compatible_node(NULL, NULL, "ibm,bsr");
193 @@ -281,10 +307,10 @@ static int __init bsr_init(void)
197 - if ((ret = bsr_create_devs(np)) < 0)
198 + if ((ret = bsr_create_devs(np)) < 0) {