Re: [PATCH 2.6.20-rc5] SPI: alternative fix for spi_busnum_to_master
On Tuesday 23 January 2007 8:07 am, Atsushi Nemoto wrote: > On Tue, 23 Jan 2007 07:42:15 -0800, David Brownell <[EMAIL PROTECTED]> wrote: > > > Indeed the check can be omitted. Should I send a new patch just > > > moving class_device_get() into "if (master->bus_num == bus_num)" > > > block? > > > > Yes, please. > > OK, here is. This patch uses spi_master_get() instead of > class_device_get(). Much better. This should be merged for 2.6.20 ... > > > Subject: SPI: alternative fix for spi_busnum_to_master > > If a SPI master device exists, udev (udevtrigger) causes kernel crash, > due to wrong kobj pointer in kobject_uevent_env(). This problem was > not in 2.6.19. > > The backtrace (on MIPS) was: > [<8024db6c>] kobject_uevent_env+0x54c/0x5e8 > [<802a8264>] store_uevent+0x1c/0x3c (in drivers/class.c) > [<801cb14c>] subsys_attr_store+0x2c/0x50 > [<801cb80c>] flush_write_buffer+0x38/0x5c > [<801cb900>] sysfs_write_file+0xd0/0x190 > [<80181444>] vfs_write+0xc4/0x1a0 > [<80181cdc>] sys_write+0x54/0xa0 > [<8010dae4>] stack_done+0x20/0x3c > > flush_write_buffer() passes kobject of spi_master_class.subsys to > subsys_addr_store(), then subsys_addr_store() passes a pointer to a > struct subsystem to store_uevent() which expects a pointer to a struct > class_device. The problem seems subsys_attr_store() called instead of > class_device_attr_store(). > > This mismatch was caused by commit > 3bd0f6943520e459659d10f3282285e43d3990f1, which overrides kset of > master class. This made spi_master_class.subsys.kset.ktype NULL so > subsys_sysfs_ops is used instead of class_dev_sysfs_ops. > > The commit was to fix spi_busnum_to_master(). Here is a patch fixes > this function in other way, just searching children list of > class_device. > > Signed-off-by: Atsushi Nemoto <[EMAIL PROTECTED]> > --- > diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c > index 270e621..6307428 100644 > --- a/drivers/spi/spi.c > +++ b/drivers/spi/spi.c > @@ -366,7 +366,6 @@ spi_alloc_master(struct device *dev, uns > > class_device_initialize(>cdev); > master->cdev.class = _master_class; > - kobj_set_kset_s(>cdev, spi_master_class.subsys); > master->cdev.dev = get_device(dev); > spi_master_set_devdata(master, [1]); > > @@ -466,14 +465,20 @@ EXPORT_SYMBOL_GPL(spi_unregister_master) > */ > struct spi_master *spi_busnum_to_master(u16 bus_num) > { > - charname[9]; > - struct kobject *bus; > - > - snprintf(name, sizeof name, "spi%u", bus_num); > - bus = kset_find_obj(_master_class.subsys.kset, name); > - if (bus) > - return container_of(bus, struct spi_master, cdev.kobj); > - return NULL; > + struct class_device *cdev; > + struct spi_master *master = NULL; > + struct spi_master *m; > + > + down(_master_class.sem); > + list_for_each_entry(cdev, _master_class.children, node) { > + m = container_of(cdev, struct spi_master, cdev); > + if (m->bus_num == bus_num) { > + master = spi_master_get(m); > + break; > + } > + } > + up(_master_class.sem); > + return master; > } > EXPORT_SYMBOL_GPL(spi_busnum_to_master); > > - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 2.6.20-rc5] SPI: alternative fix for spi_busnum_to_master
On Tue, 23 Jan 2007 07:42:15 -0800, David Brownell <[EMAIL PROTECTED]> wrote: > > Indeed the check can be omitted. Should I send a new patch just > > moving class_device_get() into "if (master->bus_num == bus_num)" > > block? > > Yes, please. OK, here is. This patch uses spi_master_get() instead of class_device_get(). Subject: SPI: alternative fix for spi_busnum_to_master If a SPI master device exists, udev (udevtrigger) causes kernel crash, due to wrong kobj pointer in kobject_uevent_env(). This problem was not in 2.6.19. The backtrace (on MIPS) was: [<8024db6c>] kobject_uevent_env+0x54c/0x5e8 [<802a8264>] store_uevent+0x1c/0x3c (in drivers/class.c) [<801cb14c>] subsys_attr_store+0x2c/0x50 [<801cb80c>] flush_write_buffer+0x38/0x5c [<801cb900>] sysfs_write_file+0xd0/0x190 [<80181444>] vfs_write+0xc4/0x1a0 [<80181cdc>] sys_write+0x54/0xa0 [<8010dae4>] stack_done+0x20/0x3c flush_write_buffer() passes kobject of spi_master_class.subsys to subsys_addr_store(), then subsys_addr_store() passes a pointer to a struct subsystem to store_uevent() which expects a pointer to a struct class_device. The problem seems subsys_attr_store() called instead of class_device_attr_store(). This mismatch was caused by commit 3bd0f6943520e459659d10f3282285e43d3990f1, which overrides kset of master class. This made spi_master_class.subsys.kset.ktype NULL so subsys_sysfs_ops is used instead of class_dev_sysfs_ops. The commit was to fix spi_busnum_to_master(). Here is a patch fixes this function in other way, just searching children list of class_device. Signed-off-by: Atsushi Nemoto <[EMAIL PROTECTED]> --- diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 270e621..6307428 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -366,7 +366,6 @@ spi_alloc_master(struct device *dev, uns class_device_initialize(>cdev); master->cdev.class = _master_class; - kobj_set_kset_s(>cdev, spi_master_class.subsys); master->cdev.dev = get_device(dev); spi_master_set_devdata(master, [1]); @@ -466,14 +465,20 @@ EXPORT_SYMBOL_GPL(spi_unregister_master) */ struct spi_master *spi_busnum_to_master(u16 bus_num) { - charname[9]; - struct kobject *bus; - - snprintf(name, sizeof name, "spi%u", bus_num); - bus = kset_find_obj(_master_class.subsys.kset, name); - if (bus) - return container_of(bus, struct spi_master, cdev.kobj); - return NULL; + struct class_device *cdev; + struct spi_master *master = NULL; + struct spi_master *m; + + down(_master_class.sem); + list_for_each_entry(cdev, _master_class.children, node) { + m = container_of(cdev, struct spi_master, cdev); + if (m->bus_num == bus_num) { + master = spi_master_get(m); + break; + } + } + up(_master_class.sem); + return master; } EXPORT_SYMBOL_GPL(spi_busnum_to_master); - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 2.6.20-rc5] SPI: alternative fix for spi_busnum_to_master
On Monday 22 January 2007 5:10 pm, Atsushi Nemoto wrote: > On Mon, 22 Jan 2007 14:12:02 -0800, David Brownell <[EMAIL PROTECTED]> wrote: > > > Here is a revised version. The children list of spi_master_class > > > contains only spi_master class so we can just compare bus_num member > > > instead of class_id string. > > > > Looks just a bit iffy ... though, thanks for helping to finally > > sort this out! > > Well, so previous patch (which was checking class_id string) would be > preferred? No, with this rename support lurking, checking names becomes risky. > > > + cdev = class_device_get(cdev); > > > + if (!cdev) > > > + continue; > > > > That "continue" case doesn't seem like it should be possible... but > > at any rate, the "get" can be deferred until the relevent class > > device is known, since that _valid_ handle can't disappear so long > > as that semaphore is held. And if you find the right device but > > can't get a reference ... no point in continuing! > > > > Something like a class_find_device() would be the best way to solve > > this sort of problem, IMO. But we don't have one of those. :( > > Indeed the check can be omitted. Should I send a new patch just > moving class_device_get() into "if (master->bus_num == bus_num)" > block? Yes, please. > The crashing with udev is 2.6.20 regression so I wish this fixed very > soon. Thank you for review. Agreed. - Dave > --- > Atsushi Nemoto > - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 2.6.20-rc5] SPI: alternative fix for spi_busnum_to_master
On Monday 22 January 2007 5:10 pm, Atsushi Nemoto wrote: On Mon, 22 Jan 2007 14:12:02 -0800, David Brownell [EMAIL PROTECTED] wrote: Here is a revised version. The children list of spi_master_class contains only spi_master class so we can just compare bus_num member instead of class_id string. Looks just a bit iffy ... though, thanks for helping to finally sort this out! Well, so previous patch (which was checking class_id string) would be preferred? No, with this rename support lurking, checking names becomes risky. + cdev = class_device_get(cdev); + if (!cdev) + continue; That continue case doesn't seem like it should be possible... but at any rate, the get can be deferred until the relevent class device is known, since that _valid_ handle can't disappear so long as that semaphore is held. And if you find the right device but can't get a reference ... no point in continuing! Something like a class_find_device() would be the best way to solve this sort of problem, IMO. But we don't have one of those. :( Indeed the check can be omitted. Should I send a new patch just moving class_device_get() into if (master-bus_num == bus_num) block? Yes, please. The crashing with udev is 2.6.20 regression so I wish this fixed very soon. Thank you for review. Agreed. - Dave --- Atsushi Nemoto - To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 2.6.20-rc5] SPI: alternative fix for spi_busnum_to_master
On Tue, 23 Jan 2007 07:42:15 -0800, David Brownell [EMAIL PROTECTED] wrote: Indeed the check can be omitted. Should I send a new patch just moving class_device_get() into if (master-bus_num == bus_num) block? Yes, please. OK, here is. This patch uses spi_master_get() instead of class_device_get(). Subject: SPI: alternative fix for spi_busnum_to_master If a SPI master device exists, udev (udevtrigger) causes kernel crash, due to wrong kobj pointer in kobject_uevent_env(). This problem was not in 2.6.19. The backtrace (on MIPS) was: [8024db6c] kobject_uevent_env+0x54c/0x5e8 [802a8264] store_uevent+0x1c/0x3c (in drivers/class.c) [801cb14c] subsys_attr_store+0x2c/0x50 [801cb80c] flush_write_buffer+0x38/0x5c [801cb900] sysfs_write_file+0xd0/0x190 [80181444] vfs_write+0xc4/0x1a0 [80181cdc] sys_write+0x54/0xa0 [8010dae4] stack_done+0x20/0x3c flush_write_buffer() passes kobject of spi_master_class.subsys to subsys_addr_store(), then subsys_addr_store() passes a pointer to a struct subsystem to store_uevent() which expects a pointer to a struct class_device. The problem seems subsys_attr_store() called instead of class_device_attr_store(). This mismatch was caused by commit 3bd0f6943520e459659d10f3282285e43d3990f1, which overrides kset of master class. This made spi_master_class.subsys.kset.ktype NULL so subsys_sysfs_ops is used instead of class_dev_sysfs_ops. The commit was to fix spi_busnum_to_master(). Here is a patch fixes this function in other way, just searching children list of class_device. Signed-off-by: Atsushi Nemoto [EMAIL PROTECTED] --- diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 270e621..6307428 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -366,7 +366,6 @@ spi_alloc_master(struct device *dev, uns class_device_initialize(master-cdev); master-cdev.class = spi_master_class; - kobj_set_kset_s(master-cdev, spi_master_class.subsys); master-cdev.dev = get_device(dev); spi_master_set_devdata(master, master[1]); @@ -466,14 +465,20 @@ EXPORT_SYMBOL_GPL(spi_unregister_master) */ struct spi_master *spi_busnum_to_master(u16 bus_num) { - charname[9]; - struct kobject *bus; - - snprintf(name, sizeof name, spi%u, bus_num); - bus = kset_find_obj(spi_master_class.subsys.kset, name); - if (bus) - return container_of(bus, struct spi_master, cdev.kobj); - return NULL; + struct class_device *cdev; + struct spi_master *master = NULL; + struct spi_master *m; + + down(spi_master_class.sem); + list_for_each_entry(cdev, spi_master_class.children, node) { + m = container_of(cdev, struct spi_master, cdev); + if (m-bus_num == bus_num) { + master = spi_master_get(m); + break; + } + } + up(spi_master_class.sem); + return master; } EXPORT_SYMBOL_GPL(spi_busnum_to_master); - To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 2.6.20-rc5] SPI: alternative fix for spi_busnum_to_master
On Tuesday 23 January 2007 8:07 am, Atsushi Nemoto wrote: On Tue, 23 Jan 2007 07:42:15 -0800, David Brownell [EMAIL PROTECTED] wrote: Indeed the check can be omitted. Should I send a new patch just moving class_device_get() into if (master-bus_num == bus_num) block? Yes, please. OK, here is. This patch uses spi_master_get() instead of class_device_get(). Much better. This should be merged for 2.6.20 ... Subject: SPI: alternative fix for spi_busnum_to_master If a SPI master device exists, udev (udevtrigger) causes kernel crash, due to wrong kobj pointer in kobject_uevent_env(). This problem was not in 2.6.19. The backtrace (on MIPS) was: [8024db6c] kobject_uevent_env+0x54c/0x5e8 [802a8264] store_uevent+0x1c/0x3c (in drivers/class.c) [801cb14c] subsys_attr_store+0x2c/0x50 [801cb80c] flush_write_buffer+0x38/0x5c [801cb900] sysfs_write_file+0xd0/0x190 [80181444] vfs_write+0xc4/0x1a0 [80181cdc] sys_write+0x54/0xa0 [8010dae4] stack_done+0x20/0x3c flush_write_buffer() passes kobject of spi_master_class.subsys to subsys_addr_store(), then subsys_addr_store() passes a pointer to a struct subsystem to store_uevent() which expects a pointer to a struct class_device. The problem seems subsys_attr_store() called instead of class_device_attr_store(). This mismatch was caused by commit 3bd0f6943520e459659d10f3282285e43d3990f1, which overrides kset of master class. This made spi_master_class.subsys.kset.ktype NULL so subsys_sysfs_ops is used instead of class_dev_sysfs_ops. The commit was to fix spi_busnum_to_master(). Here is a patch fixes this function in other way, just searching children list of class_device. Signed-off-by: Atsushi Nemoto [EMAIL PROTECTED] --- diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 270e621..6307428 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -366,7 +366,6 @@ spi_alloc_master(struct device *dev, uns class_device_initialize(master-cdev); master-cdev.class = spi_master_class; - kobj_set_kset_s(master-cdev, spi_master_class.subsys); master-cdev.dev = get_device(dev); spi_master_set_devdata(master, master[1]); @@ -466,14 +465,20 @@ EXPORT_SYMBOL_GPL(spi_unregister_master) */ struct spi_master *spi_busnum_to_master(u16 bus_num) { - charname[9]; - struct kobject *bus; - - snprintf(name, sizeof name, spi%u, bus_num); - bus = kset_find_obj(spi_master_class.subsys.kset, name); - if (bus) - return container_of(bus, struct spi_master, cdev.kobj); - return NULL; + struct class_device *cdev; + struct spi_master *master = NULL; + struct spi_master *m; + + down(spi_master_class.sem); + list_for_each_entry(cdev, spi_master_class.children, node) { + m = container_of(cdev, struct spi_master, cdev); + if (m-bus_num == bus_num) { + master = spi_master_get(m); + break; + } + } + up(spi_master_class.sem); + return master; } EXPORT_SYMBOL_GPL(spi_busnum_to_master); - To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 2.6.20-rc5] SPI: alternative fix for spi_busnum_to_master
On Mon, 22 Jan 2007 14:12:02 -0800, David Brownell <[EMAIL PROTECTED]> wrote: > > Here is a revised version. The children list of spi_master_class > > contains only spi_master class so we can just compare bus_num member > > instead of class_id string. > > Looks just a bit iffy ... though, thanks for helping to finally > sort this out! Well, so previous patch (which was checking class_id string) would be preferred? > > + cdev = class_device_get(cdev); > > + if (!cdev) > > + continue; > > That "continue" case doesn't seem like it should be possible... but > at any rate, the "get" can be deferred until the relevent class > device is known, since that _valid_ handle can't disappear so long > as that semaphore is held. And if you find the right device but > can't get a reference ... no point in continuing! > > Something like a class_find_device() would be the best way to solve > this sort of problem, IMO. But we don't have one of those. :( Indeed the check can be omitted. Should I send a new patch just moving class_device_get() into "if (master->bus_num == bus_num)" block? The crashing with udev is 2.6.20 regression so I wish this fixed very soon. Thank you for review. --- Atsushi Nemoto - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 2.6.20-rc5] SPI: alternative fix for spi_busnum_to_master
On Sunday 21 January 2007 6:25 pm, Atsushi Nemoto wrote: > Here is a revised version. The children list of spi_master_class > contains only spi_master class so we can just compare bus_num member > instead of class_id string. Looks just a bit iffy ... though, thanks for helping to finally sort this out! > + down(_master_class.sem); > + list_for_each_entry(cdev, _master_class.children, node) { > + cdev = class_device_get(cdev); > + if (!cdev) > + continue; That "continue" case doesn't seem like it should be possible... but at any rate, the "get" can be deferred until the relevent class device is known, since that _valid_ handle can't disappear so long as that semaphore is held. And if you find the right device but can't get a reference ... no point in continuing! Something like a class_find_device() would be the best way to solve this sort of problem, IMO. But we don't have one of those. :( > + master = container_of(cdev, struct spi_master, cdev); > + if (master->bus_num == bus_num) > + break; > + master = NULL; > + class_device_put(cdev); > + } > + up(_master_class.sem); > + return master; > } > EXPORT_SYMBOL_GPL(spi_busnum_to_master); > > - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 2.6.20-rc5] SPI: alternative fix for spi_busnum_to_master
On Sunday 21 January 2007 6:25 pm, Atsushi Nemoto wrote: Here is a revised version. The children list of spi_master_class contains only spi_master class so we can just compare bus_num member instead of class_id string. Looks just a bit iffy ... though, thanks for helping to finally sort this out! + down(spi_master_class.sem); + list_for_each_entry(cdev, spi_master_class.children, node) { + cdev = class_device_get(cdev); + if (!cdev) + continue; That continue case doesn't seem like it should be possible... but at any rate, the get can be deferred until the relevent class device is known, since that _valid_ handle can't disappear so long as that semaphore is held. And if you find the right device but can't get a reference ... no point in continuing! Something like a class_find_device() would be the best way to solve this sort of problem, IMO. But we don't have one of those. :( + master = container_of(cdev, struct spi_master, cdev); + if (master-bus_num == bus_num) + break; + master = NULL; + class_device_put(cdev); + } + up(spi_master_class.sem); + return master; } EXPORT_SYMBOL_GPL(spi_busnum_to_master); - To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 2.6.20-rc5] SPI: alternative fix for spi_busnum_to_master
On Mon, 22 Jan 2007 14:12:02 -0800, David Brownell [EMAIL PROTECTED] wrote: Here is a revised version. The children list of spi_master_class contains only spi_master class so we can just compare bus_num member instead of class_id string. Looks just a bit iffy ... though, thanks for helping to finally sort this out! Well, so previous patch (which was checking class_id string) would be preferred? + cdev = class_device_get(cdev); + if (!cdev) + continue; That continue case doesn't seem like it should be possible... but at any rate, the get can be deferred until the relevent class device is known, since that _valid_ handle can't disappear so long as that semaphore is held. And if you find the right device but can't get a reference ... no point in continuing! Something like a class_find_device() would be the best way to solve this sort of problem, IMO. But we don't have one of those. :( Indeed the check can be omitted. Should I send a new patch just moving class_device_get() into if (master-bus_num == bus_num) block? The crashing with udev is 2.6.20 regression so I wish this fixed very soon. Thank you for review. --- Atsushi Nemoto - To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 2.6.20-rc5] SPI: alternative fix for spi_busnum_to_master
On Thu, 18 Jan 2007 20:28:49 +0900 (JST), Atsushi Nemoto <[EMAIL PROTECTED]> wrote: > The commit was to fix spi_busnum_to_master(). Here is a patch fixes > this function in other way, just searching children list of > class_device. Here is a revised version. The children list of spi_master_class contains only spi_master class so we can just compare bus_num member instead of class_id string. Subject: SPI: alternative fix for spi_busnum_to_master If a SPI master device exists, udev (udevtrigger) causes kernel crash, due to wrong kobj pointer in kobject_uevent_env(). This problem was not in 2.6.19. The backtrace (on MIPS) was: [<8024db6c>] kobject_uevent_env+0x54c/0x5e8 [<802a8264>] store_uevent+0x1c/0x3c (in drivers/class.c) [<801cb14c>] subsys_attr_store+0x2c/0x50 [<801cb80c>] flush_write_buffer+0x38/0x5c [<801cb900>] sysfs_write_file+0xd0/0x190 [<80181444>] vfs_write+0xc4/0x1a0 [<80181cdc>] sys_write+0x54/0xa0 [<8010dae4>] stack_done+0x20/0x3c flush_write_buffer() passes kobject of spi_master_class.subsys to subsys_addr_store(), then subsys_addr_store() passes a pointer to a struct subsystem to store_uevent() which expects a pointer to a struct class_device. The problem seems subsys_attr_store() called instead of class_device_attr_store(). This mismatch was caused by commit 3bd0f6943520e459659d10f3282285e43d3990f1, which overrides kset of master class. This made spi_master_class.subsys.kset.ktype NULL so subsys_sysfs_ops is used instead of class_dev_sysfs_ops. The commit was to fix spi_busnum_to_master(). Here is a patch fixes this function in other way, just searching children list of class_device. Signed-off-by: Atsushi Nemoto <[EMAIL PROTECTED]> --- diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 270e621..88c945b 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -366,7 +366,6 @@ spi_alloc_master(struct device *dev, uns class_device_initialize(>cdev); master->cdev.class = _master_class; - kobj_set_kset_s(>cdev, spi_master_class.subsys); master->cdev.dev = get_device(dev); spi_master_set_devdata(master, [1]); @@ -466,14 +465,22 @@ EXPORT_SYMBOL_GPL(spi_unregister_master) */ struct spi_master *spi_busnum_to_master(u16 bus_num) { - charname[9]; - struct kobject *bus; - - snprintf(name, sizeof name, "spi%u", bus_num); - bus = kset_find_obj(_master_class.subsys.kset, name); - if (bus) - return container_of(bus, struct spi_master, cdev.kobj); - return NULL; + struct class_device *cdev; + struct spi_master *master = NULL; + + down(_master_class.sem); + list_for_each_entry(cdev, _master_class.children, node) { + cdev = class_device_get(cdev); + if (!cdev) + continue; + master = container_of(cdev, struct spi_master, cdev); + if (master->bus_num == bus_num) + break; + master = NULL; + class_device_put(cdev); + } + up(_master_class.sem); + return master; } EXPORT_SYMBOL_GPL(spi_busnum_to_master); - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 2.6.20-rc5] SPI: alternative fix for spi_busnum_to_master
On Thu, 18 Jan 2007 20:28:49 +0900 (JST), Atsushi Nemoto [EMAIL PROTECTED] wrote: The commit was to fix spi_busnum_to_master(). Here is a patch fixes this function in other way, just searching children list of class_device. Here is a revised version. The children list of spi_master_class contains only spi_master class so we can just compare bus_num member instead of class_id string. Subject: SPI: alternative fix for spi_busnum_to_master If a SPI master device exists, udev (udevtrigger) causes kernel crash, due to wrong kobj pointer in kobject_uevent_env(). This problem was not in 2.6.19. The backtrace (on MIPS) was: [8024db6c] kobject_uevent_env+0x54c/0x5e8 [802a8264] store_uevent+0x1c/0x3c (in drivers/class.c) [801cb14c] subsys_attr_store+0x2c/0x50 [801cb80c] flush_write_buffer+0x38/0x5c [801cb900] sysfs_write_file+0xd0/0x190 [80181444] vfs_write+0xc4/0x1a0 [80181cdc] sys_write+0x54/0xa0 [8010dae4] stack_done+0x20/0x3c flush_write_buffer() passes kobject of spi_master_class.subsys to subsys_addr_store(), then subsys_addr_store() passes a pointer to a struct subsystem to store_uevent() which expects a pointer to a struct class_device. The problem seems subsys_attr_store() called instead of class_device_attr_store(). This mismatch was caused by commit 3bd0f6943520e459659d10f3282285e43d3990f1, which overrides kset of master class. This made spi_master_class.subsys.kset.ktype NULL so subsys_sysfs_ops is used instead of class_dev_sysfs_ops. The commit was to fix spi_busnum_to_master(). Here is a patch fixes this function in other way, just searching children list of class_device. Signed-off-by: Atsushi Nemoto [EMAIL PROTECTED] --- diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 270e621..88c945b 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -366,7 +366,6 @@ spi_alloc_master(struct device *dev, uns class_device_initialize(master-cdev); master-cdev.class = spi_master_class; - kobj_set_kset_s(master-cdev, spi_master_class.subsys); master-cdev.dev = get_device(dev); spi_master_set_devdata(master, master[1]); @@ -466,14 +465,22 @@ EXPORT_SYMBOL_GPL(spi_unregister_master) */ struct spi_master *spi_busnum_to_master(u16 bus_num) { - charname[9]; - struct kobject *bus; - - snprintf(name, sizeof name, spi%u, bus_num); - bus = kset_find_obj(spi_master_class.subsys.kset, name); - if (bus) - return container_of(bus, struct spi_master, cdev.kobj); - return NULL; + struct class_device *cdev; + struct spi_master *master = NULL; + + down(spi_master_class.sem); + list_for_each_entry(cdev, spi_master_class.children, node) { + cdev = class_device_get(cdev); + if (!cdev) + continue; + master = container_of(cdev, struct spi_master, cdev); + if (master-bus_num == bus_num) + break; + master = NULL; + class_device_put(cdev); + } + up(spi_master_class.sem); + return master; } EXPORT_SYMBOL_GPL(spi_busnum_to_master); - To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 2.6.20-rc5] SPI: alternative fix for spi_busnum_to_master
If a SPI master device exists, udev (udevtrigger) causes kernel crash, due to wrong kobj pointer in kobject_uevent_env(). This problem was not in 2.6.19. The backtrace (on MIPS) was: [<8024db6c>] kobject_uevent_env+0x54c/0x5e8 [<802a8264>] store_uevent+0x1c/0x3c (in drivers/class.c) [<801cb14c>] subsys_attr_store+0x2c/0x50 [<801cb80c>] flush_write_buffer+0x38/0x5c [<801cb900>] sysfs_write_file+0xd0/0x190 [<80181444>] vfs_write+0xc4/0x1a0 [<80181cdc>] sys_write+0x54/0xa0 [<8010dae4>] stack_done+0x20/0x3c flush_write_buffer() passes kobject of spi_master_class.subsys to subsys_addr_store(), then subsys_addr_store() passes a pointer to a struct subsystem to store_uevent() which expects a pointer to a struct class_device. The problem seems subsys_attr_store() called instead of class_device_attr_store(). This mismatch was caused by commit 3bd0f6943520e459659d10f3282285e43d3990f1, which overrides kset of master class. This made spi_master_class.subsys.kset.ktype NULL so subsys_sysfs_ops is used instead of class_dev_sysfs_ops. The commit was to fix spi_busnum_to_master(). Here is a patch fixes this function in other way, just searching children list of class_device. Signed-off-by: Atsushi Nemoto <[EMAIL PROTECTED]> --- diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 270e621..0b0101b 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -366,7 +366,6 @@ spi_alloc_master(struct device *dev, uns class_device_initialize(>cdev); master->cdev.class = _master_class; - kobj_set_kset_s(>cdev, spi_master_class.subsys); master->cdev.dev = get_device(dev); spi_master_set_devdata(master, [1]); @@ -467,13 +466,20 @@ EXPORT_SYMBOL_GPL(spi_unregister_master) struct spi_master *spi_busnum_to_master(u16 bus_num) { charname[9]; - struct kobject *bus; + struct class_device *cdev; + struct spi_master *master = NULL; snprintf(name, sizeof name, "spi%u", bus_num); - bus = kset_find_obj(_master_class.subsys.kset, name); - if (bus) - return container_of(bus, struct spi_master, cdev.kobj); - return NULL; + down(_master_class.sem); + list_for_each_entry(cdev, _master_class.children, node) { + if (!strcmp(cdev->class_id, name)) { + cdev = class_device_get(cdev); + master = container_of(cdev, struct spi_master, cdev); + break; + } + } + up(_master_class.sem); + return master; } EXPORT_SYMBOL_GPL(spi_busnum_to_master); - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 2.6.20-rc5] SPI: alternative fix for spi_busnum_to_master
If a SPI master device exists, udev (udevtrigger) causes kernel crash, due to wrong kobj pointer in kobject_uevent_env(). This problem was not in 2.6.19. The backtrace (on MIPS) was: [8024db6c] kobject_uevent_env+0x54c/0x5e8 [802a8264] store_uevent+0x1c/0x3c (in drivers/class.c) [801cb14c] subsys_attr_store+0x2c/0x50 [801cb80c] flush_write_buffer+0x38/0x5c [801cb900] sysfs_write_file+0xd0/0x190 [80181444] vfs_write+0xc4/0x1a0 [80181cdc] sys_write+0x54/0xa0 [8010dae4] stack_done+0x20/0x3c flush_write_buffer() passes kobject of spi_master_class.subsys to subsys_addr_store(), then subsys_addr_store() passes a pointer to a struct subsystem to store_uevent() which expects a pointer to a struct class_device. The problem seems subsys_attr_store() called instead of class_device_attr_store(). This mismatch was caused by commit 3bd0f6943520e459659d10f3282285e43d3990f1, which overrides kset of master class. This made spi_master_class.subsys.kset.ktype NULL so subsys_sysfs_ops is used instead of class_dev_sysfs_ops. The commit was to fix spi_busnum_to_master(). Here is a patch fixes this function in other way, just searching children list of class_device. Signed-off-by: Atsushi Nemoto [EMAIL PROTECTED] --- diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 270e621..0b0101b 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -366,7 +366,6 @@ spi_alloc_master(struct device *dev, uns class_device_initialize(master-cdev); master-cdev.class = spi_master_class; - kobj_set_kset_s(master-cdev, spi_master_class.subsys); master-cdev.dev = get_device(dev); spi_master_set_devdata(master, master[1]); @@ -467,13 +466,20 @@ EXPORT_SYMBOL_GPL(spi_unregister_master) struct spi_master *spi_busnum_to_master(u16 bus_num) { charname[9]; - struct kobject *bus; + struct class_device *cdev; + struct spi_master *master = NULL; snprintf(name, sizeof name, spi%u, bus_num); - bus = kset_find_obj(spi_master_class.subsys.kset, name); - if (bus) - return container_of(bus, struct spi_master, cdev.kobj); - return NULL; + down(spi_master_class.sem); + list_for_each_entry(cdev, spi_master_class.children, node) { + if (!strcmp(cdev-class_id, name)) { + cdev = class_device_get(cdev); + master = container_of(cdev, struct spi_master, cdev); + break; + } + } + up(spi_master_class.sem); + return master; } EXPORT_SYMBOL_GPL(spi_busnum_to_master); - To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/