diff options
-rw-r--r-- | arch/powerpc/kernel/ibmebus.c | 100 |
1 files changed, 82 insertions, 18 deletions
diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c index af21306e2ef9..d21658140b6e 100644 --- a/arch/powerpc/kernel/ibmebus.c +++ b/arch/powerpc/kernel/ibmebus.c | |||
@@ -51,6 +51,13 @@ static struct device ibmebus_bus_device = { /* fake "parent" device */ | |||
51 | 51 | ||
52 | struct bus_type ibmebus_bus_type; | 52 | struct bus_type ibmebus_bus_type; |
53 | 53 | ||
54 | /* These devices will automatically be added to the bus during init */ | ||
55 | static struct of_device_id builtin_matches[] = { | ||
56 | { .compatible = "IBM,lhca" }, | ||
57 | { .compatible = "IBM,lhea" }, | ||
58 | {}, | ||
59 | }; | ||
60 | |||
54 | static void *ibmebus_alloc_coherent(struct device *dev, | 61 | static void *ibmebus_alloc_coherent(struct device *dev, |
55 | size_t size, | 62 | size_t size, |
56 | dma_addr_t *dma_handle, | 63 | dma_addr_t *dma_handle, |
@@ -125,6 +132,67 @@ static struct dma_mapping_ops ibmebus_dma_ops = { | |||
125 | .dma_supported = ibmebus_dma_supported, | 132 | .dma_supported = ibmebus_dma_supported, |
126 | }; | 133 | }; |
127 | 134 | ||
135 | static int ibmebus_match_path(struct device *dev, void *data) | ||
136 | { | ||
137 | struct device_node *dn = to_of_device(dev)->node; | ||
138 | return (dn->full_name && | ||
139 | (strcasecmp((char *)data, dn->full_name) == 0)); | ||
140 | } | ||
141 | |||
142 | static int ibmebus_match_node(struct device *dev, void *data) | ||
143 | { | ||
144 | * defines the generic type and initializers * * linux/spinlock_up.h: * contains the arch_spin_*()/etc. version of UP * builds. (which are NOPs on non-debug, non-preempt * builds) * * (included on UP-non-debug builds:) * * linux/spinlock_api_up.h: * builds the _spin_*() APIs. * * linux/spinlock.h: builds the final spin_*() APIs. */ #include <linux/typecheck.h> #include <linux/preempt.h> #include <linux/linkage.h> #include <linux/compiler.h> #include <linux/irqflags.h> #include <linux/thread_info.h> #include <linux/kernel.h> #include <linux/stringify.h> #include <linux/bottom_half.h> #include <asm/barrier.h> /* * Must define these before including other files, inline functions need them */ #define LOCK_SECTION_NAME ".text..lock."KBUILD_BASENAME #define LOCK_SECTION_START(extra) \ ".subsection 1\n\t" \ extra \ ".ifndef " LOCK_SECTION_NAME "\n\t" \ LOCK_SECTION_NAME ":\n\t" \ ".endif\n" #define LOCK_SECTION_END \ ".previous\n\t" #define __lockfunc __attribute__((section(".spinlock.text"))) /* * Pull the arch_spinlock_t and arch_rwlock_t definitions: */ #include <linux/spinlock_types.h> /* * Pull the arch_spin*() functions/declarations (UP-nondebug doesn't need them): */ #ifdef CONFIG_SMP # include <asm/spinlock.h> #else # include <linux/spinlock_up.h> #endif #ifdef CONFIG_DEBUG_SPINLOCK extern void __raw_spin_lock_init(raw_spinlock_t *lock, const char *name, struct lock_class_key *key); # define raw_spin_lock_init(lock) \ do { \ static struct lock_class_key __key; \ \ __raw_spin_lock_init((lock), #lock, &__key); \ } while (0) #else # define raw_spin_lock_init(lock) \ do { *(lock) = __RAW_SPIN_LOCK_UNLOCKED(lock); } while (0) #endif #define raw_spin_is_locked(lock) arch_spin_is_locked(&(lock)->raw_lock) #ifdef CONFIG_GENERIC_LOCKBREAK #define raw_spin_is_contended(lock) ((lock)->break_lock) #else #ifdef arch_spin_is_contended #define raw_spin_is_contended(lock) arch_spin_is_contended(&(lock)->raw_lock) #else #define raw_spin_is_contended(lock) (((void)(lock), 0)) #endif /*arch_spin_is_contended*/ #endif /* * Despite its name it doesn't necessarily has to be a full barrier. * It should only guarantee that a STORE before the critical section * can not be reordered with a LOAD inside this section. * spin_lock() is the one-way barrier, this LOAD can not escape out * of the region. So the default implementation simply ensures that * a STORE can not move into the critical section, smp_wmb() should * serialize it with another STORE done by spin_lock(). */ #ifndef smp_mb__before_spinlock #define smp_mb__before_spinlock() smp_wmb() #endif /** * raw_spin_unlock_wait - wait until the spinlock gets unlocked * @lock: the spinlock in question. */ #define raw_spin_unlock_wait(lock) arch_spin_unlock_wait(&(lock)->raw_lock) #ifdef CONFIG_DEBUG_SPINLOCK extern void do_raw_spin_lock(raw_spinlock_t *lock) __acquires(lock); #define do_raw_spin_lock_flags(lock, flags) do_raw_spin_lock(lock) extern int do_raw_spin_trylock(raw_spinlock_t *lock); extern void do_raw_spin_unlock(raw_spinlock_t *lock) __releases(lock); #else static inline void do_raw_spin_lock(raw_spinlock_t *lock) __acquires(lock) { __acquire(lock); arch_spin_lock(&lock->raw_lock); } static inline void do_raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long *flags) __acquires(lock) { __acquire(lock); arch_spin_lock_flags(&lock->raw_lock, *flags); } ibmebus_match_node)) | ||
181 | continue; | ||
182 | |||
183 | ret = ibmebus_create_device(child); | ||
184 | if (ret) { | ||
185 | printk(KERN_ERR "%s: failed to create device (%i)", | ||
186 | __FUNCTION__, ret); | ||
187 | of_node_put(child); | ||
188 | break; | ||
189 | } | ||
190 | } | ||
191 | |||
192 | of_node_put(root); | ||
193 | return ret; | ||
194 | } | ||
195 | |||
128 | int ibmebus_register_driver(struct ibmebus_driver *drv) | 196 | int ibmebus_register_driver(struct ibmebus_driver *drv) |
129 | { | 197 | { |
130 | return 0; | 198 | return 0; |
@@ -173,18 +241,6 @@ static struct device_attribute ibmebus_dev_attrs[] = { | |||
173 | __ATTR_NULL | 241 | __ATTR_NULL |
174 | }; | 242 | }; |
175 | 243 | ||
176 | static int ibmebus_match_path(struct device *dev, void *data) | ||
177 | { | ||
178 | int rc; | ||
179 | struct device_node *dn = | ||
180 | of_node_get(to_ibmebus_dev(dev)->ofdev.node); | ||
181 | |||
182 | rc = (dn->full_name && (strcasecmp((char*)data, dn->full_name) == 0)); | ||
183 | |||
184 | of_node_put(dn); | ||
185 | return rc; | ||
186 | } | ||
187 | |||
188 | static char *ibmebus_chomp(const char *in, size_t count) | 244 | static char *ibmebus_chomp(const char *in, size_t count) |
189 | { | 245 | { |
190 | char *out = kmalloc(count + 1, GFP_KERNEL); | 246 | char *out = kmalloc(count + 1, GFP_KERNEL); |
@@ -204,9 +260,8 @@ static ssize_t ibmebus_store_probe(struct bus_type *bus, | |||
204 | const char *buf, size_t count) | 260 | const char *buf, size_t count) |
205 | { | 261 | { |
206 | struct device_node *dn = NULL; | 262 | struct device_node *dn = NULL; |
207 | struct ibmebus_dev *dev; | ||
208 | char *path; | 263 | char *path; |
209 | ssize_t rc; | 264 | ssize_t rc = 0; |
210 | 265 | ||
211 | path = ibmebus_chomp(buf, count); | 266 | path = ibmebus_chomp(buf, count); |
212 | if (!path) | 267 | if (!path) |
@@ -221,9 +276,8 @@ static ssize_t ibmebus_store_probe(struct bus_type *bus, | |||
221 | } | 276 | } |
222 | 277 | ||
223 | if ((dn = of_find_node_by_path(path))) { | 278 | if ((dn = of_find_node_by_path(path))) { |
224 | /* dev = ibmebus_register_device_node(dn); */ | 279 | rc = ibmebus_create_device(dn); |
225 | of_node_put(dn); | 280 | of_node_put(dn); |
226 | rc = IS_ERR(dev) ? PTR_ERR(dev) : count; | ||
227 | } else { | 281 | } else { |
228 | printk(KERN_WARNING "%s: no such device node: %s\n", | 282 | printk(KERN_WARNING "%s: no such device node: %s\n", |
229 | __FUNCTION__, path); | 283 | __FUNCTION__, path); |
@@ -232,7 +286,9 @@ static ssize_t ibmebus_store_probe(struct bus_type *bus, | |||
232 | 286 | ||
233 | out: | 287 | out: |
234 | kfree(path); | 288 | kfree(path); |
235 | return rc; | 289 | if (rc) |
290 | return rc; | ||
291 | return count; | ||
236 | } | 292 | } |
237 | 293 | ||
238 | static ssize_t ibmebus_store_remove(struct bus_type *bus, | 294 | static ssize_t ibmebus_store_remove(struct bus_type *bus, |
@@ -247,7 +303,7 @@ static ssize_t ibmebus_store_remove(struct bus_type *bus, | |||
247 | 303 | ||
248 | if ((dev = bus_find_device(&ibmebus_bus_type, NULL, path, | 304 | if ((dev = bus_find_device(&ibmebus_bus_type, NULL, path, |
249 | ibmebus_match_path))) { | 305 | ibmebus_match_path))) { |
250 | /* ibmebus_unregister_device(dev); */ | 306 | of_device_unregister(to_of_device(dev)); |
251 | 307 | ||
252 | kfree(path); | 308 | kfree(path); |
253 | return count; | 309 | return count; |
@@ -267,6 +323,7 @@ static struct bus_attribute ibmebus_bus_attrs[] = { | |||
267 | }; | 323 | }; |
268 | 324 | ||
269 | struct bus_type ibmebus_bus_type = { | 325 | struct bus_type ibmebus_bus_type = { |
326 | .uevent = of_device_uevent, | ||
270 | .dev_attrs = ibmebus_dev_attrs, | 327 | .dev_attrs = ibmebus_dev_attrs, |
271 | .bus_attrs = ibmebus_bus_attrs | 328 | .bus_attrs = ibmebus_bus_attrs |
272 | }; | 329 | }; |
@@ -294,6 +351,13 @@ static int __init ibmebus_bus_init(void) | |||
294 | return err; | 351 | return err; |
295 | } | 352 | } |
296 | 353 | ||
354 | err = ibmebus_create_devices(builtin_matches); | ||
355 | if (err) { | ||
356 | device_unregister(&ibmebus_bus_device); | ||
357 | bus_unregister(&ibmebus_bus_type); | ||
358 | return err; | ||
359 | } | ||
360 | |||
297 | return 0; | 361 | return 0; |
298 | } | 362 | } |
299 | postcore_initcall(ibmebus_bus_init); | 363 | postcore_initcall(ibmebus_bus_init); |