aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/isdn
diff options
context:
space:
mode:
authorMatthias Urlichs <smurf@smurf.noris.de>2008-08-15 18:09:24 -0400
committerKarsten Keil <kkeil@suse.de>2009-01-09 16:44:28 -0500
commitb36b654a7e82308cea063cdf909a7f246105c2a3 (patch)
tree8c6fd2651a307a1b67549801796e2fdf8bc7991e /drivers/isdn
parent808a14a1583ca3790bf0a9c20c7d4cbac212c775 (diff)
mISDN: Create /sys/class/mISDN
Create /sys/class/mISDN and implement functions to handle device renames. Signed-Off-By: Matthias Urlichs <matthias@urlichs.de> Signed-off-by: Karsten Keil <kkeil@suse.de>
Diffstat (limited to 'drivers/isdn')
-rw-r--r--drivers/isdn/hardware/mISDN/hfcmulti.c6
-rw-r--r--drivers/isdn/hardware/mISDN/hfcpci.c100
-rw-r--r--drivers/isdn/mISDN/core.c271
-rw-r--r--drivers/isdn/mISDN/l1oip_core.c3
4 files changed, 266 insertions, 114 deletions
diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c
index cd3f3994b7f8..97f4708b3879 100644
--- a/drivers/isdn/hardware/mISDN/hfcmulti.c
+++ b/drivers/isdn/hardware/mISDN/hfcmulti.c
@@ -4718,7 +4718,7 @@ init_e1_port(struct hfc_multi *hc, struct hm_map *m)
4718 } else 4718 } else
4719 hc->chan[hc->dslot].jitter = 2; /* default */ 4719 hc->chan[hc->dslot].jitter = 2; /* default */
4720 snprintf(name, MISDN_MAX_IDLEN - 1, "hfc-e1.%d", HFC_cnt + 1); 4720 snprintf(name, MISDN_MAX_IDLEN - 1, "hfc-e1.%d", HFC_cnt + 1);
4721 ret = mISDN_register_device(&dch->dev, name); 4721 ret = mISDN_register_device(&dch->dev, &hc->pci_dev->dev, name);
4722 if (ret) 4722 if (ret)
4723 goto free_chan; 4723 goto free_chan;
4724 hc->created[0] = 1; 4724 hc->created[0] = 1;
@@ -4826,9 +4826,9 @@ init_multi_port(struct hfc_multi *hc, int pt)
4826 test_and_set_bit(HFC_CFG_DIS_ECHANNEL, 4826 test_and_set_bit(HFC_CFG_DIS_ECHANNEL,
4827 &hc->chan[i + 2].cfg); 4827 &hc->chan[i + 2].cfg);
4828 } 4828 }
4829 snprintf(name, MISDN_MAX_IDLEN - 1, "hfc-%ds.%d/%d", 4829 snprintf(name, MISDN_MAX_IDLEN - 1, "hfc-%ds.%d-%d",
4830 hc->type, HFC_cnt + 1, pt + 1); 4830 hc->type, HFC_cnt + 1, pt + 1);
4831 ret = mISDN_register_device(&dch->dev, name); 4831 ret = mISDN_register_device(&dch->dev, &hc->pci_dev->dev, name);
4832 if (ret) 4832 if (ret)
4833 goto free_chan; 4833 goto free_chan;
4834 hc->created[pt] = 1; 4834 hc->created[pt] = 1;
diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c
index cd5d26c9909f..8df12bf02af3 100644
--- a/drivers/isdn/hardware/mISDN/hfcpci.c
+++ b/drivers/isdn/hardware/mISDN/hfcpci.c
@@ -64,9 +64,6 @@ MODULE_LICENSE("GPL");
64module_param(debug, uint, 0); 64module_param(debug, uint, 0);
65module_param(poll, uint, S_IRUGO | S_IWUSR); 65module_param(poll, uint, S_IRUGO | S_IWUSR);
66 66
67static LIST_HEAD(HFClist);
68static DEFINE_RWLOCK(HFClock);
69
70enum { 67enum {
71 HFC_CCD_2BD0, 68 HFC_CCD_2BD0,
72 HFC_CCD_B000, 69 HFC_CCD_B000,
@@ -136,7 +133,6 @@ struct hfcPCI_hw {
136 133
137 134
138struct hfc_pci { 135struct hfc_pci {
139 struct list_head list;
140 u_char subtype; 136 u_char subtype;
141 u_char chanlimit; 137 u_char chanlimit;
142 u_char initdone; 138 u_char initdone;
@@ -1227,41 +1223,6 @@ hfcpci_int(int intno, void *dev_id)
1227 return IRQ_HANDLED; 1223 return IRQ_HANDLED;
1228} 1224}
1229 1225
1230static void
1231hfcpci_softirq(void *arg)
1232{
1233 u_long flags;
1234 struct bchannel *bch;
1235 struct hfc_pci *hc;
1236
1237 write_lock_irqsave(&HFClock, flags);
1238 list_for_each_entry(hc, &HFClist, list) {
1239 if (hc->hw.int_m2 & HFCPCI_IRQ_ENABLE) {
1240 spin_lock(&hc->lock);
1241 bch = Sel_BCS(hc, hc->hw.bswapped ? 2 : 1);
1242 if (bch && bch->state == ISDN_P_B_RAW) { /* B1 rx&tx */
1243 main_rec_hfcpci(bch);
1244 tx_birq(bch);
1245 }
1246 bch = Sel_BCS(hc, hc->hw.bswapped ? 1 : 2);
1247 if (bch && bch->state == ISDN_P_B_RAW) { /* B2 rx&tx */
1248 main_rec_hfcpci(bch);
1249 tx_birq(bch);
1250 }
1251 spin_unlock(&hc->lock);
1252 }
1253 }
1254 write_unlock_irqrestore(&HFClock, flags);
1255
1256 /* if next event would be in the past ... */
1257 if ((s32)(hfc_jiffies + tics - jiffies) <= 0)
1258 hfc_jiffies = jiffies + 1;
1259 else
1260 hfc_jiffies += tics;
1261 hfc_tl.expires = hfc_jiffies;
1262 add_timer(&hfc_tl);
1263}
1264
1265/* 1226/*
1266 * timer callback for D-chan busy resolution. Currently no function 1227 * timer callback for D-chan busy resolution. Currently no function
1267 */ 1228 */
@@ -2131,7 +2092,6 @@ release_card(struct hfc_pci *hc) {
2131 mISDN_freebchannel(&hc->bch[1]); 2092 mISDN_freebchannel(&hc->bch[1]);
2132 mISDN_freebchannel(&hc->bch[0]); 2093 mISDN_freebchannel(&hc->bch[0]);
2133 mISDN_freedchannel(&hc->dch); 2094 mISDN_freedchannel(&hc->dch);
2134 list_del(&hc->list);
2135 pci_set_drvdata(hc->pdev, NULL); 2095 pci_set_drvdata(hc->pdev, NULL);
2136 kfree(hc); 2096 kfree(hc);
2137} 2097}
@@ -2141,7 +2101,6 @@ setup_card(struct hfc_pci *card)
2141{ 2101{
2142 int err = -EINVAL; 2102 int err = -EINVAL;
2143 u_int i; 2103 u_int i;
2144 u_long flags;
2145 char name[MISDN_MAX_IDLEN]; 2104 char name[MISDN_MAX_IDLEN];
2146 2105
2147 card->dch.debug = debug; 2106 card->dch.debug = debug;
@@ -2169,13 +2128,10 @@ setup_card(struct hfc_pci *card)
2169 if (err) 2128 if (err)
2170 goto error; 2129 goto error;
2171 snprintf(name, MISDN_MAX_IDLEN - 1, "hfc-pci.%d", HFC_cnt + 1); 2130 snprintf(name, MISDN_MAX_IDLEN - 1, "hfc-pci.%d", HFC_cnt + 1);
2172 err = mISDN_register_device(&card->dch.dev, name); 2131 err = mISDN_register_device(&card->dch.dev, &card->pdev->dev, name);
2173 if (err) 2132 if (err)
2174 goto error; 2133 goto error;
2175 HFC_cnt++; 2134 HFC_cnt++;
2176 write_lock_irqsave(&HFClock, flags);
2177 list_add_tail(&card->list, &HFClist);
2178 write_unlock_irqrestore(&HFClock, flags);
2179 printk(KERN_INFO "HFC %d cards installed\n", HFC_cnt); 2135 printk(KERN_INFO "HFC %d cards installed\n", HFC_cnt);
2180 return 0; 2136 return 0;
2181error: 2137error:
@@ -2311,15 +2267,12 @@ static void __devexit
2311hfc_remove_pci(struct pci_dev *pdev) 2267hfc_remove_pci(struct pci_dev *pdev)
2312{ 2268{
2313 struct hfc_pci *card = pci_get_drvdata(pdev); 2269 struct hfc_pci *card = pci_get_drvdata(pdev);
2314 u_long flags;
2315 2270
2316 if (card) { 2271 if (card)
2317 write_lock_irqsave(&HFClock, flags);
2318 release_card(card); 2272 release_card(card);
2319 write_unlock_irqrestore(&HFClock, flags); 2273 else
2320 } else
2321 if (debug) 2274 if (debug)
2322 printk(KERN_WARNING "%s: drvdata allready removed\n", 2275 printk(KERN_WARNING "%s: drvdata already removed\n",
2323 __func__); 2276 __func__);
2324} 2277}
2325 2278
@@ -2331,6 +2284,46 @@ static struct pci_driver hfc_driver = {
2331 .id_table = hfc_ids, 2284 .id_table = hfc_ids,
2332}; 2285};
2333 2286
2287static int
2288_hfcpci_softirq(struct device *dev, void *arg)
2289{
2290 struct hfc_pci *hc = dev_get_drvdata(dev);
2291 struct bchannel *bch;
2292 if (hc == NULL)
2293 return 0;
2294
2295 if (hc->hw.int_m2 & HFCPCI_IRQ_ENABLE) {
2296 spin_lock(&hc->lock);
2297 bch = Sel_BCS(hc, hc->hw.bswapped ? 2 : 1);
2298 if (bch && bch->state == ISDN_P_B_RAW) { /* B1 rx&tx */
2299 main_rec_hfcpci(bch);
2300 tx_birq(bch);
2301 }
2302 bch = Sel_BCS(hc, hc->hw.bswapped ? 1 : 2);
2303 if (bch && bch->state == ISDN_P_B_RAW) { /* B2 rx&tx */
2304 main_rec_hfcpci(bch);
2305 tx_birq(bch);
2306 }
2307 spin_unlock(&hc->lock);
2308 }
2309 return 0;
2310}
2311
2312static void
2313hfcpci_softirq(void *arg)
2314{
2315 (void) driver_for_each_device(&hfc_driver.driver, NULL, arg,
2316 _hfcpci_softirq);
2317
2318 /* if next event would be in the past ... */
2319 if ((s32)(hfc_jiffies + tics - jiffies) <= 0)
2320 hfc_jiffies = jiffies + 1;
2321 else
2322 hfc_jiffies += tics;
2323 hfc_tl.expires = hfc_jiffies;
2324 add_timer(&hfc_tl);
2325}
2326
2334static int __init 2327static int __init
2335HFC_init(void) 2328HFC_init(void)
2336{ 2329{
@@ -2375,14 +2368,9 @@ HFC_init(void)
2375static void __exit 2368static void __exit
2376HFC_cleanup(void) 2369HFC_cleanup(void)
2377{ 2370{
2378 struct hfc_pci *card, *next;
2379
2380 if (timer_pending(&hfc_tl)) 2371 if (timer_pending(&hfc_tl))
2381 del_timer(&hfc_tl); 2372 del_timer(&hfc_tl);
2382 2373
2383 list_for_each_entry_safe(card, next, &HFClist, list) {
2384 release_card(card);
2385 }
2386 pci_unregister_driver(&hfc_driver); 2374 pci_unregister_driver(&hfc_driver);
2387} 2375}
2388 2376
diff --git a/drivers/isdn/mISDN/core.c b/drivers/isdn/mISDN/core.c
index 9116f54def2c..9426c9827e47 100644
--- a/drivers/isdn/mISDN/core.c
+++ b/drivers/isdn/mISDN/core.c
@@ -25,39 +25,183 @@ MODULE_AUTHOR("Karsten Keil");
25MODULE_LICENSE("GPL"); 25MODULE_LICENSE("GPL");
26module_param(debug, uint, S_IRUGO | S_IWUSR); 26module_param(debug, uint, S_IRUGO | S_IWUSR);
27 27
28static LIST_HEAD(devices);
29static DEFINE_RWLOCK(device_lock);
30static u64 device_ids; 28static u64 device_ids;
31#define MAX_DEVICE_ID 63 29#define MAX_DEVICE_ID 63
32 30
33static LIST_HEAD(Bprotocols); 31static LIST_HEAD(Bprotocols);
34static DEFINE_RWLOCK(bp_lock); 32static DEFINE_RWLOCK(bp_lock);
35 33
34static void mISDN_dev_release(struct device *dev)
35{
36 /* nothing to do: the device is part of its parent's data structure */
37}
38
39static ssize_t _show_id(struct device *dev,
40 struct device_attribute *attr, char *buf)
41{
42 struct mISDNdevice *mdev = dev_to_mISDN(dev);
43
44 if (!mdev)
45 return -ENODEV;
46 return sprintf(buf, "%d\n", mdev->id);
47}
48
49static ssize_t _show_nrbchan(struct device *dev,
50 struct device_attribute *attr, char *buf)
51{
52 struct mISDNdevice *mdev = dev_to_mISDN(dev);
53
54 if (!mdev)
55 return -ENODEV;
56 return sprintf(buf, "%d\n", mdev->nrbchan);
57}
58
59static ssize_t _show_d_protocols(struct device *dev,
60 struct device_attribute *attr, char *buf)
61{
62 struct mISDNdevice *mdev = dev_to_mISDN(dev);
63
64 if (!mdev)
65 return -ENODEV;
66 return sprintf(buf, "%d\n", mdev->Dprotocols);
67}
68
69static ssize_t _show_b_protocols(struct device *dev,
70 struct device_attribute *attr, char *buf)
71{
72 struct mISDNdevice *mdev = dev_to_mISDN(dev);
73
74 if (!mdev)
75 return -ENODEV;
76 return sprintf(buf, "%d\n", mdev->Bprotocols | get_all_Bprotocols());
77}
78
79static ssize_t _show_protocol(struct device *dev,
80 struct device_attribute *attr, char *buf)
81{
82 struct mISDNdevice *mdev = dev_to_mISDN(dev);
83
84 if (!mdev)
85 return -ENODEV;
86 return sprintf(buf, "%d\n", mdev->D.protocol);
87}
88
89static ssize_t _show_name(struct device *dev,
90 struct device_attribute *attr, char *buf)
91{
92 strcpy(buf, dev_name(dev));
93 return strlen(buf);
94}
95
96#if 0 /* hangs */
97static ssize_t _set_name(struct device *dev, struct device_attribute *attr,
98 const char *buf, size_t count)
99{
100 int err = 0;
101 char *out = kmalloc(count + 1, GFP_KERNEL);
102
103 if (!out)
104 return -ENOMEM;
105
106 memcpy(out, buf, count);
107 if (count && out[count - 1] == '\n')
108 out[--count] = 0;
109 if (count)
110 err = device_rename(dev, out);
111 kfree(out);
112
113 return (err < 0) ? err : count;
114}
115#endif
116
117static ssize_t _show_channelmap(struct device *dev,
118 struct device_attribute *attr, char *buf)
119{
120 struct mISDNdevice *mdev = dev_to_mISDN(dev);
121 char *bp = buf;
122 int i;
123
124 for (i = 0; i <= mdev->nrbchan; i++)
125 *bp++ = test_channelmap(i, mdev->channelmap) ? '1' : '0';
126
127 return bp - buf;
128}
129
130static struct device_attribute mISDN_dev_attrs[] = {
131 __ATTR(id, S_IRUGO, _show_id, NULL),
132 __ATTR(d_protocols, S_IRUGO, _show_d_protocols, NULL),
133 __ATTR(b_protocols, S_IRUGO, _show_b_protocols, NULL),
134 __ATTR(protocol, S_IRUGO, _show_protocol, NULL),
135 __ATTR(channelmap, S_IRUGO, _show_channelmap, NULL),
136 __ATTR(nrbchan, S_IRUGO, _show_nrbchan, NULL),
137 __ATTR(name, S_IRUGO, _show_name, NULL),
138/* __ATTR(name, S_IRUGO|S_IWUSR, _show_name, _set_name), */
139 {}
140};
141
142#ifdef CONFIG_HOTPLUG
143static int mISDN_uevent(struct device *dev, struct kobj_uevent_env *env)
144{
145 struct mISDNdevice *mdev = dev_to_mISDN(dev);
146
147 if (!mdev)
148 return 0;
149
150 if (add_uevent_var(env, "nchans=%d", mdev->nrbchan))
151 return -ENOMEM;
152
153 return 0;
154}
155#endif
156
157static void mISDN_class_release(struct class *cls)
158{
159 /* do nothing, it's static */
160}
161
162static struct class mISDN_class = {
163 .name = "mISDN",
164 .owner = THIS_MODULE,
165#ifdef CONFIG_HOTPLUG
166 .dev_uevent = mISDN_uevent,
167#endif
168 .dev_attrs = mISDN_dev_attrs,
169 .dev_release = mISDN_dev_release,
170 .class_release = mISDN_class_release,
171};
172
173static int
174_get_mdevice(struct device *dev, void *id)
175{
176 struct mISDNdevice *mdev = dev_to_mISDN(dev);
177
178 if (!mdev)
179 return 0;
180 if (mdev->id != *(u_int *)id)
181 return 0;
182 return 1;
183}
184
36struct mISDNdevice 185struct mISDNdevice
37*get_mdevice(u_int id) 186*get_mdevice(u_int id)
38{ 187{
39 struct mISDNdevice *dev; 188 return dev_to_mISDN(class_find_device(&mISDN_class, NULL, &id,
189 _get_mdevice));
190}
40 191
41 read_lock(&device_lock); 192static int
42 list_for_each_entry(dev, &devices, D.list) 193_get_mdevice_count(struct device *dev, void *cnt)
43 if (dev->id == id) { 194{
44 read_unlock(&device_lock); 195 *(int *)cnt += 1;
45 return dev; 196 return 0;
46 }
47 read_unlock(&device_lock);
48 return NULL;
49} 197}
50 198
51int 199int
52get_mdevice_count(void) 200get_mdevice_count(void)
53{ 201{
54 struct mISDNdevice *dev; 202 int cnt = 0;
55 int cnt = 0;
56 203
57 read_lock(&device_lock); 204 class_for_each_device(&mISDN_class, NULL, &cnt, _get_mdevice_count);
58 list_for_each_entry(dev, &devices, D.list)
59 cnt++;
60 read_unlock(&device_lock);
61 return cnt; 205 return cnt;
62} 206}
63 207
@@ -68,19 +212,24 @@ get_free_devid(void)
68 212
69 for (i = 0; i <= MAX_DEVICE_ID; i++) 213 for (i = 0; i <= MAX_DEVICE_ID; i++)
70 if (!test_and_set_bit(i, (u_long *)&device_ids)) 214 if (!test_and_set_bit(i, (u_long *)&device_ids))
71 return i; 215 break;
72 return -1; 216 if (i > MAX_DEVICE_ID)
217 return -1;
218 return i;
73} 219}
74 220
75int 221int
76mISDN_register_device(struct mISDNdevice *dev, char *name) 222mISDN_register_device(struct mISDNdevice *dev,
223 struct device *parent, char *name)
77{ 224{
78 u_long flags;
79 int err; 225 int err;
80 226
81 dev->id = get_free_devid(); 227 dev->id = get_free_devid();
228 err = -EBUSY;
82 if (dev->id < 0) 229 if (dev->id < 0)
83 return -EBUSY; 230 goto error1;
231
232 device_initialize(&dev->dev);
84 if (name && name[0]) 233 if (name && name[0])
85 dev_set_name(&dev->dev, "%s", name); 234 dev_set_name(&dev->dev, "%s", name);
86 else 235 else
@@ -90,26 +239,39 @@ mISDN_register_device(struct mISDNdevice *dev, char *name)
90 dev_name(&dev->dev), dev->id); 239 dev_name(&dev->dev), dev->id);
91 err = create_stack(dev); 240 err = create_stack(dev);
92 if (err) 241 if (err)
93 return err; 242 goto error1;
94 write_lock_irqsave(&device_lock, flags); 243
95 list_add_tail(&dev->D.list, &devices); 244 dev->dev.class = &mISDN_class;
96 write_unlock_irqrestore(&device_lock, flags); 245 dev->dev.platform_data = dev;
246 dev->dev.parent = parent;
247 dev_set_drvdata(&dev->dev, dev);
248
249 err = device_add(&dev->dev);
250 if (err)
251 goto error3;
97 return 0; 252 return 0;
253
254error3:
255 delete_stack(dev);
256 return err;
257error1:
258 return err;
259
98} 260}
99EXPORT_SYMBOL(mISDN_register_device); 261EXPORT_SYMBOL(mISDN_register_device);
100 262
101void 263void
102mISDN_unregister_device(struct mISDNdevice *dev) { 264mISDN_unregister_device(struct mISDNdevice *dev) {
103 u_long flags;
104
105 if (debug & DEBUG_CORE) 265 if (debug & DEBUG_CORE)
106 printk(KERN_DEBUG "mISDN_unregister %s %d\n", 266 printk(KERN_DEBUG "mISDN_unregister %s %d\n",
107 dev_name(&dev->dev), dev->id); 267 dev_name(&dev->dev), dev->id);
108 write_lock_irqsave(&device_lock, flags); 268 /* sysfs_remove_link(&dev->dev.kobj, "device"); */
109 list_del(&dev->D.list); 269 device_del(&dev->dev);
110 write_unlock_irqrestore(&device_lock, flags); 270 dev_set_drvdata(&dev->dev, NULL);
271
111 test_and_clear_bit(dev->id, (u_long *)&device_ids); 272 test_and_clear_bit(dev->id, (u_long *)&device_ids);
112 delete_stack(dev); 273 delete_stack(dev);
274 put_device(&dev->dev);
113} 275}
114EXPORT_SYMBOL(mISDN_unregister_device); 276EXPORT_SYMBOL(mISDN_unregister_device);
115 277
@@ -201,42 +363,43 @@ mISDNInit(void)
201 MISDN_MAJOR_VERSION, MISDN_MINOR_VERSION, MISDN_RELEASE); 363 MISDN_MAJOR_VERSION, MISDN_MINOR_VERSION, MISDN_RELEASE);
202 mISDN_init_clock(&debug); 364 mISDN_init_clock(&debug);
203 mISDN_initstack(&debug); 365 mISDN_initstack(&debug);
366 err = class_register(&mISDN_class);
367 if (err)
368 goto error1;
204 err = mISDN_inittimer(&debug); 369 err = mISDN_inittimer(&debug);
205 if (err) 370 if (err)
206 goto error; 371 goto error2;
207 err = l1_init(&debug); 372 err = l1_init(&debug);
208 if (err) { 373 if (err)
209 mISDN_timer_cleanup(); 374 goto error3;
210 goto error;
211 }
212 err = Isdnl2_Init(&debug); 375 err = Isdnl2_Init(&debug);
213 if (err) { 376 if (err)
214 mISDN_timer_cleanup(); 377 goto error4;
215 l1_cleanup();
216 goto error;
217 }
218 err = misdn_sock_init(&debug); 378 err = misdn_sock_init(&debug);
219 if (err) { 379 if (err)
220 mISDN_timer_cleanup(); 380 goto error5;
221 l1_cleanup(); 381 return 0;
222 Isdnl2_cleanup(); 382
223 } 383error5:
224error: 384 Isdnl2_cleanup();
385error4:
386 l1_cleanup();
387error3:
388 mISDN_timer_cleanup();
389error2:
390 class_unregister(&mISDN_class);
391error1:
225 return err; 392 return err;
226} 393}
227 394
228static void mISDN_cleanup(void) 395static void mISDN_cleanup(void)
229{ 396{
230 misdn_sock_cleanup(); 397 misdn_sock_cleanup();
231 mISDN_timer_cleanup();
232 l1_cleanup();
233 Isdnl2_cleanup(); 398 Isdnl2_cleanup();
399 l1_cleanup();
400 mISDN_timer_cleanup();
401 class_unregister(&mISDN_class);
234 402
235 if (!list_empty(&devices))
236 printk(KERN_ERR "%s devices still registered\n", __func__);
237
238 if (!list_empty(&Bprotocols))
239 printk(KERN_ERR "%s Bprotocols still registered\n", __func__);
240 printk(KERN_DEBUG "mISDNcore unloaded\n"); 403 printk(KERN_DEBUG "mISDNcore unloaded\n");
241} 404}
242 405
diff --git a/drivers/isdn/mISDN/l1oip_core.c b/drivers/isdn/mISDN/l1oip_core.c
index a6a9e1af2ad6..abe574989572 100644
--- a/drivers/isdn/mISDN/l1oip_core.c
+++ b/drivers/isdn/mISDN/l1oip_core.c
@@ -1433,7 +1433,8 @@ init_card(struct l1oip *hc, int pri, int bundle)
1433 hc->chan[i + ch].bch = bch; 1433 hc->chan[i + ch].bch = bch;
1434 set_channelmap(bch->nr, dch->dev.channelmap); 1434 set_channelmap(bch->nr, dch->dev.channelmap);
1435 } 1435 }
1436 ret = mISDN_register_device(&dch->dev, hc->name); 1436 /* TODO: create a parent device for this driver */
1437 ret = mISDN_register_device(&dch->dev, NULL, hc->name);
1437 if (ret) 1438 if (ret)
1438 return ret; 1439 return ret;
1439 hc->registered = 1; 1440 hc->registered = 1;