Commit 2d8331792ea3f5ccfd147288afba148537337019

Authored by Evgeniy Polyakov
Committed by Greg Kroah-Hartman
1 parent 1b11d78cf8

[PATCH] W1: w1_netlink: New init/fini netlink callbacks.

They are guarded with NETLINK_DISABLE compile time options,
so if CONFIG_NET is disabled, no linking errors occur.
Bug noticed by Adrian Bunk <bunk@stusta.de>.

Signed-off-by: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

Showing 3 changed files with 34 additions and 10 deletions Inline Diff

1 /* 1 /*
2 * w1_int.c 2 * w1_int.c
3 * 3 *
4 * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru> 4 * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
5 * 5 *
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by 8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or 9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version. 10 * (at your option) any later version.
11 * 11 *
12 * This program is distributed in the hope that it will be useful, 12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details. 15 * GNU General Public License for more details.
16 * 16 *
17 * You should have received a copy of the GNU General Public License 17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software 18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */ 20 */
21 21
22 #include <linux/kernel.h> 22 #include <linux/kernel.h>
23 #include <linux/list.h> 23 #include <linux/list.h>
24 #include <linux/delay.h> 24 #include <linux/delay.h>
25 25
26 #include "w1.h" 26 #include "w1.h"
27 #include "w1_log.h" 27 #include "w1_log.h"
28 #include "w1_netlink.h" 28 #include "w1_netlink.h"
29 29
30 static u32 w1_ids = 1; 30 static u32 w1_ids = 1;
31 31
32 extern struct device_driver w1_driver; 32 extern struct device_driver w1_driver;
33 extern struct bus_type w1_bus_type; 33 extern struct bus_type w1_bus_type;
34 extern struct device w1_device; 34 extern struct device w1_device;
35 extern int w1_max_slave_count; 35 extern int w1_max_slave_count;
36 extern int w1_max_slave_ttl; 36 extern int w1_max_slave_ttl;
37 extern struct list_head w1_masters; 37 extern struct list_head w1_masters;
38 extern spinlock_t w1_mlock; 38 extern spinlock_t w1_mlock;
39 39
40 extern int w1_process(void *); 40 extern int w1_process(void *);
41 41
42 static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl, 42 static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl,
43 struct device_driver *driver, 43 struct device_driver *driver,
44 struct device *device) 44 struct device *device)
45 { 45 {
46 struct w1_master *dev; 46 struct w1_master *dev;
47 int err; 47 int err;
48 48
49 /* 49 /*
50 * We are in process context(kernel thread), so can sleep. 50 * We are in process context(kernel thread), so can sleep.
51 */ 51 */
52 dev = kmalloc(sizeof(struct w1_master) + sizeof(struct w1_bus_master), GFP_KERNEL); 52 dev = kmalloc(sizeof(struct w1_master) + sizeof(struct w1_bus_master), GFP_KERNEL);
53 if (!dev) { 53 if (!dev) {
54 printk(KERN_ERR 54 printk(KERN_ERR
55 "Failed to allocate %zd bytes for new w1 device.\n", 55 "Failed to allocate %zd bytes for new w1 device.\n",
56 sizeof(struct w1_master)); 56 sizeof(struct w1_master));
57 return NULL; 57 return NULL;
58 } 58 }
59 59
60 memset(dev, 0, sizeof(struct w1_master) + sizeof(struct w1_bus_master)); 60 memset(dev, 0, sizeof(struct w1_master) + sizeof(struct w1_bus_master));
61 61
62 dev->bus_master = (struct w1_bus_master *)(dev + 1); 62 dev->bus_master = (struct w1_bus_master *)(dev + 1);
63 63
64 dev->owner = THIS_MODULE; 64 dev->owner = THIS_MODULE;
65 dev->max_slave_count = slave_count; 65 dev->max_slave_count = slave_count;
66 dev->slave_count = 0; 66 dev->slave_count = 0;
67 dev->attempts = 0; 67 dev->attempts = 0;
68 dev->kpid = -1; 68 dev->kpid = -1;
69 dev->initialized = 0; 69 dev->initialized = 0;
70 dev->id = id; 70 dev->id = id;
71 dev->slave_ttl = slave_ttl; 71 dev->slave_ttl = slave_ttl;
72 dev->search_count = -1; /* continual scan */ 72 dev->search_count = -1; /* continual scan */
73 73
74 atomic_set(&dev->refcnt, 2); 74 atomic_set(&dev->refcnt, 2);
75 75
76 INIT_LIST_HEAD(&dev->slist); 76 INIT_LIST_HEAD(&dev->slist);
77 init_MUTEX(&dev->mutex); 77 init_MUTEX(&dev->mutex);
78 78
79 init_completion(&dev->dev_released); 79 init_completion(&dev->dev_released);
80 init_completion(&dev->dev_exited); 80 init_completion(&dev->dev_exited);
81 81
82 memcpy(&dev->dev, device, sizeof(struct device)); 82 memcpy(&dev->dev, device, sizeof(struct device));
83 snprintf(dev->dev.bus_id, sizeof(dev->dev.bus_id), 83 snprintf(dev->dev.bus_id, sizeof(dev->dev.bus_id),
84 "w1_bus_master%u", dev->id); 84 "w1_bus_master%u", dev->id);
85 snprintf(dev->name, sizeof(dev->name), "w1_bus_master%u", dev->id); 85 snprintf(dev->name, sizeof(dev->name), "w1_bus_master%u", dev->id);
86 86
87 dev->driver = driver; 87 dev->driver = driver;
88 88
89 dev->groups = 1; 89 dev->groups = 1;
90 dev->seq = 1; 90 dev->seq = 1;
91 dev->nls = netlink_kernel_create(NETLINK_W1, 1, NULL, THIS_MODULE); 91 dev_init_netlink(dev);
92 if (!dev->nls) {
93 printk(KERN_ERR "Failed to create new netlink socket(%u) for w1 master %s.\n",
94 NETLINK_NFLOG, dev->dev.bus_id);
95 }
96 92
97 err = device_register(&dev->dev); 93 err = device_register(&dev->dev);
98 if (err) { 94 if (err) {
99 printk(KERN_ERR "Failed to register master device. err=%d\n", err); 95 printk(KERN_ERR "Failed to register master device. err=%d\n", err);
100 if (dev->nls && dev->nls->sk_socket) 96
101 sock_release(dev->nls->sk_socket); 97 dev_fini_netlink(dev);
98
102 memset(dev, 0, sizeof(struct w1_master)); 99 memset(dev, 0, sizeof(struct w1_master));
103 kfree(dev); 100 kfree(dev);
104 dev = NULL; 101 dev = NULL;
105 } 102 }
106 103
107 return dev; 104 return dev;
108 } 105 }
109 106
110 static void w1_free_dev(struct w1_master *dev) 107 void w1_free_dev(struct w1_master *dev)
111 { 108 {
112 device_unregister(&dev->dev); 109 device_unregister(&dev->dev);
113 if (dev->nls && dev->nls->sk_socket) 110 dev_fini_netlink(dev);
114 sock_release(dev->nls->sk_socket);
115 memset(dev, 0, sizeof(struct w1_master) + sizeof(struct w1_bus_master)); 111 memset(dev, 0, sizeof(struct w1_master) + sizeof(struct w1_bus_master));
116 kfree(dev); 112 kfree(dev);
117 } 113 }
118 114
119 int w1_add_master_device(struct w1_bus_master *master) 115 int w1_add_master_device(struct w1_bus_master *master)
120 { 116 {
121 struct w1_master *dev; 117 struct w1_master *dev;
122 int retval = 0; 118 int retval = 0;
123 struct w1_netlink_msg msg; 119 struct w1_netlink_msg msg;
124 120
125 /* validate minimum functionality */ 121 /* validate minimum functionality */
126 if (!(master->touch_bit && master->reset_bus) && 122 if (!(master->touch_bit && master->reset_bus) &&
127 !(master->write_bit && master->read_bit)) { 123 !(master->write_bit && master->read_bit)) {
128 printk(KERN_ERR "w1_add_master_device: invalid function set\n"); 124 printk(KERN_ERR "w1_add_master_device: invalid function set\n");
129 return(-EINVAL); 125 return(-EINVAL);
130 } 126 }
131 127
132 dev = w1_alloc_dev(w1_ids++, w1_max_slave_count, w1_max_slave_ttl, &w1_driver, &w1_device); 128 dev = w1_alloc_dev(w1_ids++, w1_max_slave_count, w1_max_slave_ttl, &w1_driver, &w1_device);
133 if (!dev) 129 if (!dev)
134 return -ENOMEM; 130 return -ENOMEM;
135 131
136 dev->kpid = kernel_thread(&w1_process, dev, 0); 132 dev->kpid = kernel_thread(&w1_process, dev, 0);
137 if (dev->kpid < 0) { 133 if (dev->kpid < 0) {
138 dev_err(&dev->dev, 134 dev_err(&dev->dev,
139 "Failed to create new kernel thread. err=%d\n", 135 "Failed to create new kernel thread. err=%d\n",
140 dev->kpid); 136 dev->kpid);
141 retval = dev->kpid; 137 retval = dev->kpid;
142 goto err_out_free_dev; 138 goto err_out_free_dev;
143 } 139 }
144 140
145 retval = w1_create_master_attributes(dev); 141 retval = w1_create_master_attributes(dev);
146 if (retval) 142 if (retval)
147 goto err_out_kill_thread; 143 goto err_out_kill_thread;
148 144
149 memcpy(dev->bus_master, master, sizeof(struct w1_bus_master)); 145 memcpy(dev->bus_master, master, sizeof(struct w1_bus_master));
150 146
151 dev->initialized = 1; 147 dev->initialized = 1;
152 148
153 spin_lock(&w1_mlock); 149 spin_lock(&w1_mlock);
154 list_add(&dev->w1_master_entry, &w1_masters); 150 list_add(&dev->w1_master_entry, &w1_masters);
155 spin_unlock(&w1_mlock); 151 spin_unlock(&w1_mlock);
156 152
157 msg.id.mst.id = dev->id; 153 msg.id.mst.id = dev->id;
158 msg.id.mst.pid = dev->kpid; 154 msg.id.mst.pid = dev->kpid;
159 msg.type = W1_MASTER_ADD; 155 msg.type = W1_MASTER_ADD;
160 w1_netlink_send(dev, &msg); 156 w1_netlink_send(dev, &msg);
161 157
162 return 0; 158 return 0;
163 159
164 err_out_kill_thread: 160 err_out_kill_thread:
165 set_bit(W1_MASTER_NEED_EXIT, &dev->flags); 161 set_bit(W1_MASTER_NEED_EXIT, &dev->flags);
166 if (kill_proc(dev->kpid, SIGTERM, 1)) 162 if (kill_proc(dev->kpid, SIGTERM, 1))
167 dev_err(&dev->dev, 163 dev_err(&dev->dev,
168 "Failed to send signal to w1 kernel thread %d.\n", 164 "Failed to send signal to w1 kernel thread %d.\n",
169 dev->kpid); 165 dev->kpid);
170 wait_for_completion(&dev->dev_exited); 166 wait_for_completion(&dev->dev_exited);
171 167
172 err_out_free_dev: 168 err_out_free_dev:
173 w1_free_dev(dev); 169 w1_free_dev(dev);
174 170
175 return retval; 171 return retval;
176 } 172 }
177 173
178 void __w1_remove_master_device(struct w1_master *dev) 174 void __w1_remove_master_device(struct w1_master *dev)
179 { 175 {
180 int err; 176 int err;
181 struct w1_netlink_msg msg; 177 struct w1_netlink_msg msg;
182 178
183 set_bit(W1_MASTER_NEED_EXIT, &dev->flags); 179 set_bit(W1_MASTER_NEED_EXIT, &dev->flags);
184 err = kill_proc(dev->kpid, SIGTERM, 1); 180 err = kill_proc(dev->kpid, SIGTERM, 1);
185 if (err) 181 if (err)
186 dev_err(&dev->dev, 182 dev_err(&dev->dev,
187 "%s: Failed to send signal to w1 kernel thread %d.\n", 183 "%s: Failed to send signal to w1 kernel thread %d.\n",
188 __func__, dev->kpid); 184 __func__, dev->kpid);
189 185
190 while (atomic_read(&dev->refcnt)) { 186 while (atomic_read(&dev->refcnt)) {
191 printk(KERN_INFO "Waiting for %s to become free: refcnt=%d.\n", 187 printk(KERN_INFO "Waiting for %s to become free: refcnt=%d.\n",
192 dev->name, atomic_read(&dev->refcnt)); 188 dev->name, atomic_read(&dev->refcnt));
193 189
194 if (msleep_interruptible(1000)) 190 if (msleep_interruptible(1000))
195 flush_signals(current); 191 flush_signals(current);
196 } 192 }
197 193
198 msg.id.mst.id = dev->id; 194 msg.id.mst.id = dev->id;
199 msg.id.mst.pid = dev->kpid; 195 msg.id.mst.pid = dev->kpid;
200 msg.type = W1_MASTER_REMOVE; 196 msg.type = W1_MASTER_REMOVE;
201 w1_netlink_send(dev, &msg); 197 w1_netlink_send(dev, &msg);
202 198
203 w1_free_dev(dev); 199 w1_free_dev(dev);
204 } 200 }
205 201
206 void w1_remove_master_device(struct w1_bus_master *bm) 202 void w1_remove_master_device(struct w1_bus_master *bm)
207 { 203 {
208 struct w1_master *dev = NULL; 204 struct w1_master *dev = NULL;
209 205
210 list_for_each_entry(dev, &w1_masters, w1_master_entry) { 206 list_for_each_entry(dev, &w1_masters, w1_master_entry) {
211 if (!dev->initialized) 207 if (!dev->initialized)
212 continue; 208 continue;
213 209
214 if (dev->bus_master->data == bm->data) 210 if (dev->bus_master->data == bm->data)
215 break; 211 break;
216 } 212 }
217 213
218 if (!dev) { 214 if (!dev) {
219 printk(KERN_ERR "Device doesn't exist.\n"); 215 printk(KERN_ERR "Device doesn't exist.\n");
220 return; 216 return;
221 } 217 }
222 218
223 __w1_remove_master_device(dev); 219 __w1_remove_master_device(dev);
224 } 220 }
225 221
226 EXPORT_SYMBOL(w1_add_master_device); 222 EXPORT_SYMBOL(w1_add_master_device);
227 EXPORT_SYMBOL(w1_remove_master_device); 223 EXPORT_SYMBOL(w1_remove_master_device);
228 224
229 MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_W1); 225 MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_W1);
drivers/w1/w1_netlink.c
1 /* 1 /*
2 * w1_netlink.c 2 * w1_netlink.c
3 * 3 *
4 * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru> 4 * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
5 * 5 *
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by 8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or 9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version. 10 * (at your option) any later version.
11 * 11 *
12 * This program is distributed in the hope that it will be useful, 12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details. 15 * GNU General Public License for more details.
16 * 16 *
17 * You should have received a copy of the GNU General Public License 17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software 18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */ 20 */
21 21
22 #include <linux/skbuff.h> 22 #include <linux/skbuff.h>
23 #include <linux/netlink.h> 23 #include <linux/netlink.h>
24 24
25 #include "w1.h" 25 #include "w1.h"
26 #include "w1_log.h" 26 #include "w1_log.h"
27 #include "w1_netlink.h" 27 #include "w1_netlink.h"
28 28
29 #ifndef NETLINK_DISABLED 29 #ifndef NETLINK_DISABLED
30 void w1_netlink_send(struct w1_master *dev, struct w1_netlink_msg *msg) 30 void w1_netlink_send(struct w1_master *dev, struct w1_netlink_msg *msg)
31 { 31 {
32 unsigned int size; 32 unsigned int size;
33 struct sk_buff *skb; 33 struct sk_buff *skb;
34 struct w1_netlink_msg *data; 34 struct w1_netlink_msg *data;
35 struct nlmsghdr *nlh; 35 struct nlmsghdr *nlh;
36 36
37 if (!dev->nls) 37 if (!dev->nls)
38 return; 38 return;
39 39
40 size = NLMSG_SPACE(sizeof(struct w1_netlink_msg)); 40 size = NLMSG_SPACE(sizeof(struct w1_netlink_msg));
41 41
42 skb = alloc_skb(size, GFP_ATOMIC); 42 skb = alloc_skb(size, GFP_ATOMIC);
43 if (!skb) { 43 if (!skb) {
44 dev_err(&dev->dev, "skb_alloc() failed.\n"); 44 dev_err(&dev->dev, "skb_alloc() failed.\n");
45 return; 45 return;
46 } 46 }
47 47
48 nlh = NLMSG_PUT(skb, 0, dev->seq++, NLMSG_DONE, size - sizeof(*nlh)); 48 nlh = NLMSG_PUT(skb, 0, dev->seq++, NLMSG_DONE, size - sizeof(*nlh));
49 49
50 data = (struct w1_netlink_msg *)NLMSG_DATA(nlh); 50 data = (struct w1_netlink_msg *)NLMSG_DATA(nlh);
51 51
52 memcpy(data, msg, sizeof(struct w1_netlink_msg)); 52 memcpy(data, msg, sizeof(struct w1_netlink_msg));
53 53
54 NETLINK_CB(skb).dst_group = dev->groups; 54 NETLINK_CB(skb).dst_group = dev->groups;
55 netlink_broadcast(dev->nls, skb, 0, dev->groups, GFP_ATOMIC); 55 netlink_broadcast(dev->nls, skb, 0, dev->groups, GFP_ATOMIC);
56 56
57 nlmsg_failure: 57 nlmsg_failure:
58 return; 58 return;
59 } 59 }
60
61 int dev_init_netlink(struct w1_master *dev)
62 {
63 dev->nls = netlink_kernel_create(NETLINK_W1, 1, NULL, THIS_MODULE);
64 if (!dev->nls) {
65 printk(KERN_ERR "Failed to create new netlink socket(%u) for w1 master %s.\n",
66 NETLINK_W1, dev->dev.bus_id);
67 }
68
69 return 0;
70 }
71
72 void dev_fini_netlink(struct w1_master *dev)
73 {
74 if (dev->nls && dev->nls->sk_socket)
75 sock_release(dev->nls->sk_socket);
76 }
60 #else 77 #else
61 #warning Netlink support is disabled. Please compile with NET support enabled. 78 #warning Netlink support is disabled. Please compile with NET support enabled.
62 79
63 void w1_netlink_send(struct w1_master *dev, struct w1_netlink_msg *msg) 80 void w1_netlink_send(struct w1_master *dev, struct w1_netlink_msg *msg)
81 {
82 }
83
84 int dev_init_netlink(struct w1_master *dev)
85 {
86 return 0;
87 }
88
89 void dev_fini_netlink(struct w1_master *dev)
64 { 90 {
65 } 91 }
66 #endif 92 #endif
67 93
drivers/w1/w1_netlink.h
1 /* 1 /*
2 * w1_netlink.h 2 * w1_netlink.h
3 * 3 *
4 * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru> 4 * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
5 * 5 *
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by 8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or 9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version. 10 * (at your option) any later version.
11 * 11 *
12 * This program is distributed in the hope that it will be useful, 12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details. 15 * GNU General Public License for more details.
16 * 16 *
17 * You should have received a copy of the GNU General Public License 17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software 18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */ 20 */
21 21
22 #ifndef __W1_NETLINK_H 22 #ifndef __W1_NETLINK_H
23 #define __W1_NETLINK_H 23 #define __W1_NETLINK_H
24 24
25 #include <asm/types.h> 25 #include <asm/types.h>
26 26
27 #include "w1.h" 27 #include "w1.h"
28 28
29 enum w1_netlink_message_types { 29 enum w1_netlink_message_types {
30 W1_SLAVE_ADD = 0, 30 W1_SLAVE_ADD = 0,
31 W1_SLAVE_REMOVE, 31 W1_SLAVE_REMOVE,
32 W1_MASTER_ADD, 32 W1_MASTER_ADD,
33 W1_MASTER_REMOVE, 33 W1_MASTER_REMOVE,
34 }; 34 };
35 35
36 struct w1_netlink_msg 36 struct w1_netlink_msg
37 { 37 {
38 __u8 type; 38 __u8 type;
39 __u8 reserved[3]; 39 __u8 reserved[3];
40 union 40 union
41 { 41 {
42 struct w1_reg_num id; 42 struct w1_reg_num id;
43 __u64 w1_id; 43 __u64 w1_id;
44 struct 44 struct
45 { 45 {
46 __u32 id; 46 __u32 id;
47 __u32 pid; 47 __u32 pid;
48 } mst; 48 } mst;
49 } id; 49 } id;
50 }; 50 };
51 51
52 #ifdef __KERNEL__ 52 #ifdef __KERNEL__
53 53
54 void w1_netlink_send(struct w1_master *, struct w1_netlink_msg *); 54 void w1_netlink_send(struct w1_master *, struct w1_netlink_msg *);
55 int dev_init_netlink(struct w1_master *dev);
56 void dev_fini_netlink(struct w1_master *dev);
55 57
56 #endif /* __KERNEL__ */ 58 #endif /* __KERNEL__ */
57 #endif /* __W1_NETLINK_H */ 59 #endif /* __W1_NETLINK_H */
58 60