]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/patches/suse-2.6.27.31/patches.arch/ppc-pseries-bsr-multinode.patch
Merge branch 'master' into next
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.arch / ppc-pseries-bsr-multinode.patch
CommitLineData
2cb7cef9
BS
1Subject: Add support for multiple BSR nodes in the device tree.
2From: Sonny Rao <sonnyrao@us.ibm.com>
3References: 443665 - LTC49817
4
5Previously, the BSR driver only supported a single OF node describing
6a BSR. Apparently when an LPAR is set to use "all system resources"
7the BSR appears as a single node, but when it is handed out in pieces,
8each 8 byte piece gets its own node. So, keep a list of bsr devices
9instead of the array and include all nodes.
10
11Also, be more inclusive of what BSR devices we accept by only checking
12compatibility and not the device name property (which might change in
13the future versions of BSR).
14
15Signed-off-by: Sonny Rao <sonnyrao@us.ibm.com>
16Signed-off-by: Olaf Hering <olh@suse.de>
17
18---
19 drivers/char/bsr.c | 84 ++++++++++++++++++++++++++++++++++-------------------
20 1 file changed, 55 insertions(+), 29 deletions(-)
21
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 */
26 int bsr_minor;
27
28+ struct list_head bsr_list;
29+
30 dev_t bsr_dev;
31 struct cdev bsr_cdev;
32 struct device *bsr_device;
33@@ -68,8 +70,8 @@ struct bsr_dev {
34
35 };
36
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;
42 static int bsr_major;
43
44@@ -154,24 +156,25 @@ const static struct file_operations bsr_
45
46 static void bsr_cleanup_devs(void)
47 {
48- int i;
49- for (i=0 ; i < num_bsr_devs; i++) {
50- struct bsr_dev *cur = bsr_devs + i;
51+ struct bsr_dev *cur, *n;
52+
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);
57 }
58+ list_del(&cur->bsr_list);
59+ kfree(cur);
60 }
61-
62- kfree(bsr_devs);
63 }
64
65-static int bsr_create_devs(struct device_node *bn)
66+static int bsr_add_node(struct device_node *bn)
67 {
68- int bsr_stride_len, bsr_bytes_len;
69+ int bsr_stride_len, bsr_bytes_len, num_bsr_devs;
70 const u32 *bsr_stride;
71 const u32 *bsr_bytes;
72 unsigned i;
73+ int ret = -ENODEV;
74
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");
81- return -ENODEV;
82+ return ret;
83 }
84
85 num_bsr_devs = bsr_bytes_len / sizeof(u32);
86
87- /* only a warning, its informational since we'll fail and exit */
88- WARN_ON(num_bsr_devs > BSR_MAX_DEVS);
89-
90- bsr_devs = kzalloc(sizeof(struct bsr_dev) * num_bsr_devs, GFP_KERNEL);
91- if (!bsr_devs)
92- return -ENOMEM;
93-
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),
97+ GFP_KERNEL);
98 struct resource res;
99 int result;
100
101+ if (!cur) {
102+ printk(KERN_ERR "Unable to alloc bsr dev\n");
103+ ret = -ENOMEM;
104+ goto out_err;
105+ }
106+
107 result = of_address_to_resource(bn, i, &res);
108 if (result < 0) {
109- printk(KERN_ERR "bsr of-node has invalid reg property\n");
110- goto out_err;
111+ printk(KERN_ERR "bsr of-node has invalid reg property, skipping\n");
112+ kfree(cur);
113+ continue;
114 }
115
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);
124
125 switch(cur->bsr_bytes) {
126 case 8:
127@@ -228,14 +232,15 @@ static int bsr_create_devs(struct device
128 }
129
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);
134
135 cdev_init(&cur->bsr_cdev, &bsr_fops);
136 result = cdev_add(&cur->bsr_cdev, cur->bsr_dev, 1);
137- if (result)
138+ if (result) {
139+ kfree(cur);
140 goto out_err;
141+ }
142
143 cur->bsr_device = device_create_drvdata(bsr_class, NULL,
144 cur->bsr_dev,
145@@ -244,16 +249,37 @@ static int bsr_create_devs(struct device
146 printk(KERN_ERR "device_create failed for %s\n",
147 cur->bsr_name);
148 cdev_del(&cur->bsr_cdev);
149+ kfree(cur);
150 goto out_err;
151 }
152+
153+ bsr_types[cur->bsr_type] = cur->bsr_num + 1;
154+ list_add_tail(&cur->bsr_list, &bsr_devs);
155 }
156
157+ total_bsr_devs += num_bsr_devs;
158+
159 return 0;
160
161 out_err:
162
163 bsr_cleanup_devs();
164- return -ENODEV;
165+ return ret;
166+}
167+
168+static int bsr_create_devs(struct device_node *bn)
169+{
170+ int ret;
171+
172+ while (bn) {
173+ ret = bsr_add_node(bn);
174+ if (ret) {
175+ of_node_put(bn);
176+ return ret;
177+ }
178+ bn = of_find_compatible_node(bn, NULL, "ibm,bsr");
179+ }
180+ return 0;
181 }
182
183 static int __init bsr_init(void)
184@@ -263,7 +289,7 @@ static int __init bsr_init(void)
185 int ret = -ENODEV;
186 int result;
187
188- np = of_find_compatible_node(NULL, "ibm,bsr", "ibm,bsr");
189+ np = of_find_compatible_node(NULL, NULL, "ibm,bsr");
190 if (!np)
191 goto out_err;
192
193@@ -281,10 +307,10 @@ static int __init bsr_init(void)
194 goto out_err_2;
195 }
196
197- if ((ret = bsr_create_devs(np)) < 0)
198+ if ((ret = bsr_create_devs(np)) < 0) {
199+ np = NULL;
200 goto out_err_3;
201-
202- of_node_put(np);
203+ }
204
205 return 0;
206