diff options
author | Evgeniy Polyakov <johnpol@2ka.mipt.ru> | 2005-08-11 05:20:07 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2005-09-08 17:41:26 -0400 |
commit | 7f772ed8df27c6941952452330c618512389c4c7 (patch) | |
tree | 6ad8320e0ee8bd2f4709176381662460ec4b1e45 /drivers/w1/w1.c | |
parent | 8949d2aa05ddf5e9a31d738568a79915970cb38e (diff) |
[PATCH] w1: hotplug support.
Here is W1 hotplug in addition to netlink notifications.
Signed-off-by: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/w1/w1.c')
-rw-r--r-- | drivers/w1/w1.c | 90 |
1 files changed, 79 insertions, 11 deletions
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index 0bbf029b1ef1..9c7777b6bbdc 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c | |||
@@ -125,27 +125,41 @@ static struct bin_attribute w1_slave_bin_attribute = { | |||
125 | .read = &w1_default_read_bin, | 125 | .read = &w1_default_read_bin, |
126 | }; | 126 | }; |
127 | 127 | ||
128 | static int w1_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size); | ||
128 | 129 | ||
129 | static struct bus_type w1_bus_type = { | 130 | static struct bus_type w1_bus_type = { |
130 | .name = "w1", | 131 | .name = "w1", |
131 | .match = w1_master_match, | 132 | .match = w1_master_match, |
133 | .hotplug = w1_hotplug, | ||
132 | }; | 134 | }; |
133 | 135 | ||
134 | struct device_driver w1_driver = { | 136 | struct device_driver w1_master_driver = { |
135 | .name = "w1_driver", | 137 | .name = "w1_master_driver", |
136 | .bus = &w1_bus_type, | 138 | .bus = &w1_bus_type, |
137 | .probe = w1_master_probe, | 139 | .probe = w1_master_probe, |
138 | .remove = w1_master_remove, | 140 | .remove = w1_master_remove, |
139 | }; | 141 | }; |
140 | 142 | ||
141 | struct device w1_device = { | 143 | struct device w1_master_device = { |
142 | .parent = NULL, | 144 | .parent = NULL, |
143 | .bus = &w1_bus_type, | 145 | .bus = &w1_bus_type, |
144 | .bus_id = "w1 bus master", | 146 | .bus_id = "w1 bus master", |
145 | .driver = &w1_driver, | 147 | .driver = &w1_master_driver, |
146 | .release = &w1_master_release | 148 | .release = &w1_master_release |
147 | }; | 149 | }; |
148 | 150 | ||
151 | struct device_driver w1_slave_driver = { | ||
152 | .name = "w1_slave_driver", | ||
153 | .bus = &w1_bus_type, | ||
154 | }; | ||
155 | |||
156 | struct device w1_slave_device = { | ||
157 | .parent = NULL, | ||
158 | .bus = &w1_bus_type, | ||
159 | .bus_id = "w1 bus slave", | ||
160 | .driver = &w1_slave_driver, | ||
161 | }; | ||
162 | |||
149 | static ssize_t w1_master_attribute_show_name(struct device *dev, struct device_attribute *attr, char *buf) | 163 | static ssize_t w1_master_attribute_show_name(struct device *dev, struct device_attribute *attr, char *buf) |
150 | { | 164 | { |
151 | struct w1_master *md = container_of(dev, struct w1_master, dev); | 165 | struct w1_master *md = container_of(dev, struct w1_master, dev); |
@@ -329,12 +343,55 @@ void w1_destroy_master_attributes(struct w1_master *master) | |||
329 | sysfs_remove_group(&master->dev.kobj, &w1_master_defattr_group); | 343 | sysfs_remove_group(&master->dev.kobj, &w1_master_defattr_group); |
330 | } | 344 | } |
331 | 345 | ||
346 | #ifdef CONFIG_HOTPLUG | ||
347 | static int w1_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size) | ||
348 | { | ||
349 | struct w1_master *md = NULL; | ||
350 | struct w1_slave *sl = NULL; | ||
351 | char *event_owner, *name; | ||
352 | int err, cur_index=0, cur_len=0; | ||
353 | |||
354 | if (dev->driver == &w1_master_driver) { | ||
355 | md = container_of(dev, struct w1_master, dev); | ||
356 | event_owner = "master"; | ||
357 | name = md->name; | ||
358 | } else if (dev->driver == &w1_slave_driver) { | ||
359 | sl = container_of(dev, struct w1_slave, dev); | ||
360 | event_owner = "slave"; | ||
361 | name = sl->name; | ||
362 | } else { | ||
363 | dev_dbg(dev, "Unknown hotplug event.\n"); | ||
364 | return -EINVAL; | ||
365 | } | ||
366 | |||
367 | dev_dbg(dev, "Hotplug event for %s %s, bus_id=%s.\n", event_owner, name, dev->bus_id); | ||
368 | |||
369 | if (dev->driver != &w1_slave_driver || !sl) | ||
370 | return 0; | ||
371 | |||
372 | err = add_hotplug_env_var(envp, num_envp, &cur_index, buffer, buffer_size, &cur_len, "W1_FID=%02X", sl->reg_num.family); | ||
373 | if (err) | ||
374 | return err; | ||
375 | |||
376 | err = add_hotplug_env_var(envp, num_envp, &cur_index, buffer, buffer_size, &cur_len, "W1_SLAVE_ID=%024llX", sl->reg_num.id); | ||
377 | if (err) | ||
378 | return err; | ||
379 | |||
380 | return 0; | ||
381 | }; | ||
382 | #else | ||
383 | static int w1_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size) | ||
384 | { | ||
385 | return 0; | ||
386 | } | ||
387 | #endif | ||
388 | |||
332 | static int __w1_attach_slave_device(struct w1_slave *sl) | 389 | static int __w1_attach_slave_device(struct w1_slave *sl) |
333 | { | 390 | { |
334 | int err; | 391 | int err; |
335 | 392 | ||
336 | sl->dev.parent = &sl->master->dev; | 393 | sl->dev.parent = &sl->master->dev; |
337 | sl->dev.driver = sl->master->driver; | 394 | sl->dev.driver = &w1_slave_driver; |
338 | sl->dev.bus = &w1_bus_type; | 395 | sl->dev.bus = &w1_bus_type; |
339 | sl->dev.release = &w1_slave_release; | 396 | sl->dev.release = &w1_slave_release; |
340 | 397 | ||
@@ -507,7 +564,6 @@ void w1_reconnect_slaves(struct w1_family *f) | |||
507 | spin_unlock_bh(&w1_mlock); | 564 | spin_unlock_bh(&w1_mlock); |
508 | } | 565 | } |
509 | 566 | ||
510 | |||
511 | static void w1_slave_found(unsigned long data, u64 rn) | 567 | static void w1_slave_found(unsigned long data, u64 rn) |
512 | { | 568 | { |
513 | int slave_count; | 569 | int slave_count; |
@@ -783,7 +839,7 @@ static int w1_init(void) | |||
783 | goto err_out_exit_init; | 839 | goto err_out_exit_init; |
784 | } | 840 | } |
785 | 841 | ||
786 | retval = driver_register(&w1_driver); | 842 | retval = driver_register(&w1_master_driver); |
787 | if (retval) { | 843 | if (retval) { |
788 | printk(KERN_ERR | 844 | printk(KERN_ERR |
789 | "Failed to register master driver. err=%d.\n", | 845 | "Failed to register master driver. err=%d.\n", |
@@ -791,18 +847,29 @@ static int w1_init(void) | |||
791 | goto err_out_bus_unregister; | 847 | goto err_out_bus_unregister; |
792 | } | 848 | } |
793 | 849 | ||
850 | retval = driver_register(&w1_slave_driver); | ||
851 | if (retval) { | ||
852 | printk(KERN_ERR | ||
853 | "Failed to register master driver. err=%d.\n", | ||
854 | retval); | ||
855 | goto err_out_master_unregister; | ||
856 | } | ||
857 | |||
794 | control_thread = kernel_thread(&w1_control, NULL, 0); | 858 | control_thread = kernel_thread(&w1_control, NULL, 0); |
795 | if (control_thread < 0) { | 859 | if (control_thread < 0) { |
796 | printk(KERN_ERR "Failed to create control thread. err=%d\n", | 860 | printk(KERN_ERR "Failed to create control thread. err=%d\n", |
797 | control_thread); | 861 | control_thread); |
798 | retval = control_thread; | 862 | retval = control_thread; |
799 | goto err_out_driver_unregister; | 863 | goto err_out_slave_unregister; |
800 | } | 864 | } |
801 | 865 | ||
802 | return 0; | 866 | return 0; |
803 | 867 | ||
804 | err_out_driver_unregister: | 868 | err_out_slave_unregister: |
805 | driver_unregister(&w1_driver); | 869 | driver_unregister(&w1_slave_driver); |
870 | |||
871 | err_out_master_unregister: | ||
872 | driver_unregister(&w1_master_driver); | ||
806 | 873 | ||
807 | err_out_bus_unregister: | 874 | err_out_bus_unregister: |
808 | bus_unregister(&w1_bus_type); | 875 | bus_unregister(&w1_bus_type); |
@@ -821,7 +888,8 @@ static void w1_fini(void) | |||
821 | control_needs_exit = 1; | 888 | control_needs_exit = 1; |
822 | wait_for_completion(&w1_control_complete); | 889 | wait_for_completion(&w1_control_complete); |
823 | 890 | ||
824 | driver_unregister(&w1_driver); | 891 | driver_unregister(&w1_slave_driver); |
892 | driver_unregister(&w1_master_driver); | ||
825 | bus_unregister(&w1_bus_type); | 893 | bus_unregister(&w1_bus_type); |
826 | } | 894 | } |
827 | 895 | ||