Loading drivers/isdn/hardware/mISDN/hfcmulti.c +3 −3 Original line number Diff line number Diff line Loading @@ -4718,7 +4718,7 @@ init_e1_port(struct hfc_multi *hc, struct hm_map *m) } else hc->chan[hc->dslot].jitter = 2; /* default */ snprintf(name, MISDN_MAX_IDLEN - 1, "hfc-e1.%d", HFC_cnt + 1); ret = mISDN_register_device(&dch->dev, name); ret = mISDN_register_device(&dch->dev, &hc->pci_dev->dev, name); if (ret) goto free_chan; hc->created[0] = 1; Loading Loading @@ -4826,9 +4826,9 @@ init_multi_port(struct hfc_multi *hc, int pt) test_and_set_bit(HFC_CFG_DIS_ECHANNEL, &hc->chan[i + 2].cfg); } snprintf(name, MISDN_MAX_IDLEN - 1, "hfc-%ds.%d/%d", snprintf(name, MISDN_MAX_IDLEN - 1, "hfc-%ds.%d-%d", hc->type, HFC_cnt + 1, pt + 1); ret = mISDN_register_device(&dch->dev, name); ret = mISDN_register_device(&dch->dev, &hc->pci_dev->dev, name); if (ret) goto free_chan; hc->created[pt] = 1; Loading drivers/isdn/hardware/mISDN/hfcpci.c +44 −56 Original line number Diff line number Diff line Loading @@ -64,9 +64,6 @@ MODULE_LICENSE("GPL"); module_param(debug, uint, 0); module_param(poll, uint, S_IRUGO | S_IWUSR); static LIST_HEAD(HFClist); static DEFINE_RWLOCK(HFClock); enum { HFC_CCD_2BD0, HFC_CCD_B000, Loading Loading @@ -136,7 +133,6 @@ struct hfcPCI_hw { struct hfc_pci { struct list_head list; u_char subtype; u_char chanlimit; u_char initdone; Loading Loading @@ -1227,41 +1223,6 @@ hfcpci_int(int intno, void *dev_id) return IRQ_HANDLED; } static void hfcpci_softirq(void *arg) { u_long flags; struct bchannel *bch; struct hfc_pci *hc; write_lock_irqsave(&HFClock, flags); list_for_each_entry(hc, &HFClist, list) { if (hc->hw.int_m2 & HFCPCI_IRQ_ENABLE) { spin_lock(&hc->lock); bch = Sel_BCS(hc, hc->hw.bswapped ? 2 : 1); if (bch && bch->state == ISDN_P_B_RAW) { /* B1 rx&tx */ main_rec_hfcpci(bch); tx_birq(bch); } bch = Sel_BCS(hc, hc->hw.bswapped ? 1 : 2); if (bch && bch->state == ISDN_P_B_RAW) { /* B2 rx&tx */ main_rec_hfcpci(bch); tx_birq(bch); } spin_unlock(&hc->lock); } } write_unlock_irqrestore(&HFClock, flags); /* if next event would be in the past ... */ if ((s32)(hfc_jiffies + tics - jiffies) <= 0) hfc_jiffies = jiffies + 1; else hfc_jiffies += tics; hfc_tl.expires = hfc_jiffies; add_timer(&hfc_tl); } /* * timer callback for D-chan busy resolution. Currently no function */ Loading Loading @@ -2131,7 +2092,6 @@ release_card(struct hfc_pci *hc) { mISDN_freebchannel(&hc->bch[1]); mISDN_freebchannel(&hc->bch[0]); mISDN_freedchannel(&hc->dch); list_del(&hc->list); pci_set_drvdata(hc->pdev, NULL); kfree(hc); } Loading @@ -2141,7 +2101,6 @@ setup_card(struct hfc_pci *card) { int err = -EINVAL; u_int i; u_long flags; char name[MISDN_MAX_IDLEN]; card->dch.debug = debug; Loading Loading @@ -2169,13 +2128,10 @@ setup_card(struct hfc_pci *card) if (err) goto error; snprintf(name, MISDN_MAX_IDLEN - 1, "hfc-pci.%d", HFC_cnt + 1); err = mISDN_register_device(&card->dch.dev, name); err = mISDN_register_device(&card->dch.dev, &card->pdev->dev, name); if (err) goto error; HFC_cnt++; write_lock_irqsave(&HFClock, flags); list_add_tail(&card->list, &HFClist); write_unlock_irqrestore(&HFClock, flags); printk(KERN_INFO "HFC %d cards installed\n", HFC_cnt); return 0; error: Loading Loading @@ -2311,15 +2267,12 @@ static void __devexit hfc_remove_pci(struct pci_dev *pdev) { struct hfc_pci *card = pci_get_drvdata(pdev); u_long flags; if (card) { write_lock_irqsave(&HFClock, flags); if (card) release_card(card); write_unlock_irqrestore(&HFClock, flags); } else else if (debug) printk(KERN_WARNING "%s: drvdata allready removed\n", printk(KERN_WARNING "%s: drvdata already removed\n", __func__); } Loading @@ -2331,6 +2284,46 @@ static struct pci_driver hfc_driver = { .id_table = hfc_ids, }; static int _hfcpci_softirq(struct device *dev, void *arg) { struct hfc_pci *hc = dev_get_drvdata(dev); struct bchannel *bch; if (hc == NULL) return 0; if (hc->hw.int_m2 & HFCPCI_IRQ_ENABLE) { spin_lock(&hc->lock); bch = Sel_BCS(hc, hc->hw.bswapped ? 2 : 1); if (bch && bch->state == ISDN_P_B_RAW) { /* B1 rx&tx */ main_rec_hfcpci(bch); tx_birq(bch); } bch = Sel_BCS(hc, hc->hw.bswapped ? 1 : 2); if (bch && bch->state == ISDN_P_B_RAW) { /* B2 rx&tx */ main_rec_hfcpci(bch); tx_birq(bch); } spin_unlock(&hc->lock); } return 0; } static void hfcpci_softirq(void *arg) { (void) driver_for_each_device(&hfc_driver.driver, NULL, arg, _hfcpci_softirq); /* if next event would be in the past ... */ if ((s32)(hfc_jiffies + tics - jiffies) <= 0) hfc_jiffies = jiffies + 1; else hfc_jiffies += tics; hfc_tl.expires = hfc_jiffies; add_timer(&hfc_tl); } static int __init HFC_init(void) { Loading Loading @@ -2375,14 +2368,9 @@ HFC_init(void) static void __exit HFC_cleanup(void) { struct hfc_pci *card, *next; if (timer_pending(&hfc_tl)) del_timer(&hfc_tl); list_for_each_entry_safe(card, next, &HFClist, list) { release_card(card); } pci_unregister_driver(&hfc_driver); } Loading drivers/isdn/mISDN/core.c +217 −54 Original line number Diff line number Diff line Loading @@ -25,39 +25,183 @@ MODULE_AUTHOR("Karsten Keil"); MODULE_LICENSE("GPL"); module_param(debug, uint, S_IRUGO | S_IWUSR); static LIST_HEAD(devices); static DEFINE_RWLOCK(device_lock); static u64 device_ids; #define MAX_DEVICE_ID 63 static LIST_HEAD(Bprotocols); static DEFINE_RWLOCK(bp_lock); static void mISDN_dev_release(struct device *dev) { /* nothing to do: the device is part of its parent's data structure */ } static ssize_t _show_id(struct device *dev, struct device_attribute *attr, char *buf) { struct mISDNdevice *mdev = dev_to_mISDN(dev); if (!mdev) return -ENODEV; return sprintf(buf, "%d\n", mdev->id); } static ssize_t _show_nrbchan(struct device *dev, struct device_attribute *attr, char *buf) { struct mISDNdevice *mdev = dev_to_mISDN(dev); if (!mdev) return -ENODEV; return sprintf(buf, "%d\n", mdev->nrbchan); } static ssize_t _show_d_protocols(struct device *dev, struct device_attribute *attr, char *buf) { struct mISDNdevice *mdev = dev_to_mISDN(dev); if (!mdev) return -ENODEV; return sprintf(buf, "%d\n", mdev->Dprotocols); } static ssize_t _show_b_protocols(struct device *dev, struct device_attribute *attr, char *buf) { struct mISDNdevice *mdev = dev_to_mISDN(dev); if (!mdev) return -ENODEV; return sprintf(buf, "%d\n", mdev->Bprotocols | get_all_Bprotocols()); } static ssize_t _show_protocol(struct device *dev, struct device_attribute *attr, char *buf) { struct mISDNdevice *mdev = dev_to_mISDN(dev); if (!mdev) return -ENODEV; return sprintf(buf, "%d\n", mdev->D.protocol); } static ssize_t _show_name(struct device *dev, struct device_attribute *attr, char *buf) { strcpy(buf, dev_name(dev)); return strlen(buf); } #if 0 /* hangs */ static ssize_t _set_name(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int err = 0; char *out = kmalloc(count + 1, GFP_KERNEL); if (!out) return -ENOMEM; memcpy(out, buf, count); if (count && out[count - 1] == '\n') out[--count] = 0; if (count) err = device_rename(dev, out); kfree(out); return (err < 0) ? err : count; } #endif static ssize_t _show_channelmap(struct device *dev, struct device_attribute *attr, char *buf) { struct mISDNdevice *mdev = dev_to_mISDN(dev); char *bp = buf; int i; for (i = 0; i <= mdev->nrbchan; i++) *bp++ = test_channelmap(i, mdev->channelmap) ? '1' : '0'; return bp - buf; } static struct device_attribute mISDN_dev_attrs[] = { __ATTR(id, S_IRUGO, _show_id, NULL), __ATTR(d_protocols, S_IRUGO, _show_d_protocols, NULL), __ATTR(b_protocols, S_IRUGO, _show_b_protocols, NULL), __ATTR(protocol, S_IRUGO, _show_protocol, NULL), __ATTR(channelmap, S_IRUGO, _show_channelmap, NULL), __ATTR(nrbchan, S_IRUGO, _show_nrbchan, NULL), __ATTR(name, S_IRUGO, _show_name, NULL), /* __ATTR(name, S_IRUGO|S_IWUSR, _show_name, _set_name), */ {} }; #ifdef CONFIG_HOTPLUG static int mISDN_uevent(struct device *dev, struct kobj_uevent_env *env) { struct mISDNdevice *mdev = dev_to_mISDN(dev); if (!mdev) return 0; if (add_uevent_var(env, "nchans=%d", mdev->nrbchan)) return -ENOMEM; return 0; } #endif static void mISDN_class_release(struct class *cls) { /* do nothing, it's static */ } static struct class mISDN_class = { .name = "mISDN", .owner = THIS_MODULE, #ifdef CONFIG_HOTPLUG .dev_uevent = mISDN_uevent, #endif .dev_attrs = mISDN_dev_attrs, .dev_release = mISDN_dev_release, .class_release = mISDN_class_release, }; static int _get_mdevice(struct device *dev, void *id) { struct mISDNdevice *mdev = dev_to_mISDN(dev); if (!mdev) return 0; if (mdev->id != *(u_int *)id) return 0; return 1; } struct mISDNdevice *get_mdevice(u_int id) { struct mISDNdevice *dev; read_lock(&device_lock); list_for_each_entry(dev, &devices, D.list) if (dev->id == id) { read_unlock(&device_lock); return dev; return dev_to_mISDN(class_find_device(&mISDN_class, NULL, &id, _get_mdevice)); } read_unlock(&device_lock); return NULL; static int _get_mdevice_count(struct device *dev, void *cnt) { *(int *)cnt += 1; return 0; } int get_mdevice_count(void) { struct mISDNdevice *dev; int cnt = 0; read_lock(&device_lock); list_for_each_entry(dev, &devices, D.list) cnt++; read_unlock(&device_lock); class_for_each_device(&mISDN_class, NULL, &cnt, _get_mdevice_count); return cnt; } Loading @@ -68,19 +212,24 @@ get_free_devid(void) for (i = 0; i <= MAX_DEVICE_ID; i++) if (!test_and_set_bit(i, (u_long *)&device_ids)) return i; break; if (i > MAX_DEVICE_ID) return -1; return i; } int mISDN_register_device(struct mISDNdevice *dev, char *name) mISDN_register_device(struct mISDNdevice *dev, struct device *parent, char *name) { u_long flags; int err; dev->id = get_free_devid(); err = -EBUSY; if (dev->id < 0) return -EBUSY; goto error1; device_initialize(&dev->dev); if (name && name[0]) dev_set_name(&dev->dev, "%s", name); else Loading @@ -90,26 +239,39 @@ mISDN_register_device(struct mISDNdevice *dev, char *name) dev_name(&dev->dev), dev->id); err = create_stack(dev); if (err) return err; write_lock_irqsave(&device_lock, flags); list_add_tail(&dev->D.list, &devices); write_unlock_irqrestore(&device_lock, flags); goto error1; dev->dev.class = &mISDN_class; dev->dev.platform_data = dev; dev->dev.parent = parent; dev_set_drvdata(&dev->dev, dev); err = device_add(&dev->dev); if (err) goto error3; return 0; error3: delete_stack(dev); return err; error1: return err; } EXPORT_SYMBOL(mISDN_register_device); void mISDN_unregister_device(struct mISDNdevice *dev) { u_long flags; if (debug & DEBUG_CORE) printk(KERN_DEBUG "mISDN_unregister %s %d\n", dev_name(&dev->dev), dev->id); write_lock_irqsave(&device_lock, flags); list_del(&dev->D.list); write_unlock_irqrestore(&device_lock, flags); /* sysfs_remove_link(&dev->dev.kobj, "device"); */ device_del(&dev->dev); dev_set_drvdata(&dev->dev, NULL); test_and_clear_bit(dev->id, (u_long *)&device_ids); delete_stack(dev); put_device(&dev->dev); } EXPORT_SYMBOL(mISDN_unregister_device); Loading Loading @@ -201,42 +363,43 @@ mISDNInit(void) MISDN_MAJOR_VERSION, MISDN_MINOR_VERSION, MISDN_RELEASE); mISDN_init_clock(&debug); mISDN_initstack(&debug); err = class_register(&mISDN_class); if (err) goto error1; err = mISDN_inittimer(&debug); if (err) goto error; goto error2; err = l1_init(&debug); if (err) { mISDN_timer_cleanup(); goto error; } if (err) goto error3; err = Isdnl2_Init(&debug); if (err) { mISDN_timer_cleanup(); l1_cleanup(); goto error; } if (err) goto error4; err = misdn_sock_init(&debug); if (err) { mISDN_timer_cleanup(); l1_cleanup(); if (err) goto error5; return 0; error5: Isdnl2_cleanup(); } error: error4: l1_cleanup(); error3: mISDN_timer_cleanup(); error2: class_unregister(&mISDN_class); error1: return err; } static void mISDN_cleanup(void) { misdn_sock_cleanup(); mISDN_timer_cleanup(); l1_cleanup(); Isdnl2_cleanup(); l1_cleanup(); mISDN_timer_cleanup(); class_unregister(&mISDN_class); if (!list_empty(&devices)) printk(KERN_ERR "%s devices still registered\n", __func__); if (!list_empty(&Bprotocols)) printk(KERN_ERR "%s Bprotocols still registered\n", __func__); printk(KERN_DEBUG "mISDNcore unloaded\n"); } Loading drivers/isdn/mISDN/l1oip_core.c +2 −1 Original line number Diff line number Diff line Loading @@ -1433,7 +1433,8 @@ init_card(struct l1oip *hc, int pri, int bundle) hc->chan[i + ch].bch = bch; set_channelmap(bch->nr, dch->dev.channelmap); } ret = mISDN_register_device(&dch->dev, hc->name); /* TODO: create a parent device for this driver */ ret = mISDN_register_device(&dch->dev, NULL, hc->name); if (ret) return ret; hc->registered = 1; Loading include/linux/mISDNif.h +7 −1 Original line number Diff line number Diff line Loading @@ -531,7 +531,8 @@ _queue_data(struct mISDNchannel *ch, u_int prim, /* global register/unregister functions */ extern int mISDN_register_device(struct mISDNdevice *, char *name); extern int mISDN_register_device(struct mISDNdevice *, struct device *parent, char *name); extern void mISDN_unregister_device(struct mISDNdevice *); extern int mISDN_register_Bprotocol(struct Bprotocol *); extern void mISDN_unregister_Bprotocol(struct Bprotocol *); Loading @@ -539,6 +540,11 @@ extern struct mISDNclock *mISDN_register_clock(char *, int, clockctl_func_t *, void *); extern void mISDN_unregister_clock(struct mISDNclock *); static inline struct mISDNdevice *dev_to_mISDN(struct device *dev) { return dev_get_drvdata(dev); } extern void set_channel_address(struct mISDNchannel *, u_int, u_int); extern void mISDN_clock_update(struct mISDNclock *, int, struct timeval *); extern unsigned short mISDN_clock_get(void); Loading Loading
drivers/isdn/hardware/mISDN/hfcmulti.c +3 −3 Original line number Diff line number Diff line Loading @@ -4718,7 +4718,7 @@ init_e1_port(struct hfc_multi *hc, struct hm_map *m) } else hc->chan[hc->dslot].jitter = 2; /* default */ snprintf(name, MISDN_MAX_IDLEN - 1, "hfc-e1.%d", HFC_cnt + 1); ret = mISDN_register_device(&dch->dev, name); ret = mISDN_register_device(&dch->dev, &hc->pci_dev->dev, name); if (ret) goto free_chan; hc->created[0] = 1; Loading Loading @@ -4826,9 +4826,9 @@ init_multi_port(struct hfc_multi *hc, int pt) test_and_set_bit(HFC_CFG_DIS_ECHANNEL, &hc->chan[i + 2].cfg); } snprintf(name, MISDN_MAX_IDLEN - 1, "hfc-%ds.%d/%d", snprintf(name, MISDN_MAX_IDLEN - 1, "hfc-%ds.%d-%d", hc->type, HFC_cnt + 1, pt + 1); ret = mISDN_register_device(&dch->dev, name); ret = mISDN_register_device(&dch->dev, &hc->pci_dev->dev, name); if (ret) goto free_chan; hc->created[pt] = 1; Loading
drivers/isdn/hardware/mISDN/hfcpci.c +44 −56 Original line number Diff line number Diff line Loading @@ -64,9 +64,6 @@ MODULE_LICENSE("GPL"); module_param(debug, uint, 0); module_param(poll, uint, S_IRUGO | S_IWUSR); static LIST_HEAD(HFClist); static DEFINE_RWLOCK(HFClock); enum { HFC_CCD_2BD0, HFC_CCD_B000, Loading Loading @@ -136,7 +133,6 @@ struct hfcPCI_hw { struct hfc_pci { struct list_head list; u_char subtype; u_char chanlimit; u_char initdone; Loading Loading @@ -1227,41 +1223,6 @@ hfcpci_int(int intno, void *dev_id) return IRQ_HANDLED; } static void hfcpci_softirq(void *arg) { u_long flags; struct bchannel *bch; struct hfc_pci *hc; write_lock_irqsave(&HFClock, flags); list_for_each_entry(hc, &HFClist, list) { if (hc->hw.int_m2 & HFCPCI_IRQ_ENABLE) { spin_lock(&hc->lock); bch = Sel_BCS(hc, hc->hw.bswapped ? 2 : 1); if (bch && bch->state == ISDN_P_B_RAW) { /* B1 rx&tx */ main_rec_hfcpci(bch); tx_birq(bch); } bch = Sel_BCS(hc, hc->hw.bswapped ? 1 : 2); if (bch && bch->state == ISDN_P_B_RAW) { /* B2 rx&tx */ main_rec_hfcpci(bch); tx_birq(bch); } spin_unlock(&hc->lock); } } write_unlock_irqrestore(&HFClock, flags); /* if next event would be in the past ... */ if ((s32)(hfc_jiffies + tics - jiffies) <= 0) hfc_jiffies = jiffies + 1; else hfc_jiffies += tics; hfc_tl.expires = hfc_jiffies; add_timer(&hfc_tl); } /* * timer callback for D-chan busy resolution. Currently no function */ Loading Loading @@ -2131,7 +2092,6 @@ release_card(struct hfc_pci *hc) { mISDN_freebchannel(&hc->bch[1]); mISDN_freebchannel(&hc->bch[0]); mISDN_freedchannel(&hc->dch); list_del(&hc->list); pci_set_drvdata(hc->pdev, NULL); kfree(hc); } Loading @@ -2141,7 +2101,6 @@ setup_card(struct hfc_pci *card) { int err = -EINVAL; u_int i; u_long flags; char name[MISDN_MAX_IDLEN]; card->dch.debug = debug; Loading Loading @@ -2169,13 +2128,10 @@ setup_card(struct hfc_pci *card) if (err) goto error; snprintf(name, MISDN_MAX_IDLEN - 1, "hfc-pci.%d", HFC_cnt + 1); err = mISDN_register_device(&card->dch.dev, name); err = mISDN_register_device(&card->dch.dev, &card->pdev->dev, name); if (err) goto error; HFC_cnt++; write_lock_irqsave(&HFClock, flags); list_add_tail(&card->list, &HFClist); write_unlock_irqrestore(&HFClock, flags); printk(KERN_INFO "HFC %d cards installed\n", HFC_cnt); return 0; error: Loading Loading @@ -2311,15 +2267,12 @@ static void __devexit hfc_remove_pci(struct pci_dev *pdev) { struct hfc_pci *card = pci_get_drvdata(pdev); u_long flags; if (card) { write_lock_irqsave(&HFClock, flags); if (card) release_card(card); write_unlock_irqrestore(&HFClock, flags); } else else if (debug) printk(KERN_WARNING "%s: drvdata allready removed\n", printk(KERN_WARNING "%s: drvdata already removed\n", __func__); } Loading @@ -2331,6 +2284,46 @@ static struct pci_driver hfc_driver = { .id_table = hfc_ids, }; static int _hfcpci_softirq(struct device *dev, void *arg) { struct hfc_pci *hc = dev_get_drvdata(dev); struct bchannel *bch; if (hc == NULL) return 0; if (hc->hw.int_m2 & HFCPCI_IRQ_ENABLE) { spin_lock(&hc->lock); bch = Sel_BCS(hc, hc->hw.bswapped ? 2 : 1); if (bch && bch->state == ISDN_P_B_RAW) { /* B1 rx&tx */ main_rec_hfcpci(bch); tx_birq(bch); } bch = Sel_BCS(hc, hc->hw.bswapped ? 1 : 2); if (bch && bch->state == ISDN_P_B_RAW) { /* B2 rx&tx */ main_rec_hfcpci(bch); tx_birq(bch); } spin_unlock(&hc->lock); } return 0; } static void hfcpci_softirq(void *arg) { (void) driver_for_each_device(&hfc_driver.driver, NULL, arg, _hfcpci_softirq); /* if next event would be in the past ... */ if ((s32)(hfc_jiffies + tics - jiffies) <= 0) hfc_jiffies = jiffies + 1; else hfc_jiffies += tics; hfc_tl.expires = hfc_jiffies; add_timer(&hfc_tl); } static int __init HFC_init(void) { Loading Loading @@ -2375,14 +2368,9 @@ HFC_init(void) static void __exit HFC_cleanup(void) { struct hfc_pci *card, *next; if (timer_pending(&hfc_tl)) del_timer(&hfc_tl); list_for_each_entry_safe(card, next, &HFClist, list) { release_card(card); } pci_unregister_driver(&hfc_driver); } Loading
drivers/isdn/mISDN/core.c +217 −54 Original line number Diff line number Diff line Loading @@ -25,39 +25,183 @@ MODULE_AUTHOR("Karsten Keil"); MODULE_LICENSE("GPL"); module_param(debug, uint, S_IRUGO | S_IWUSR); static LIST_HEAD(devices); static DEFINE_RWLOCK(device_lock); static u64 device_ids; #define MAX_DEVICE_ID 63 static LIST_HEAD(Bprotocols); static DEFINE_RWLOCK(bp_lock); static void mISDN_dev_release(struct device *dev) { /* nothing to do: the device is part of its parent's data structure */ } static ssize_t _show_id(struct device *dev, struct device_attribute *attr, char *buf) { struct mISDNdevice *mdev = dev_to_mISDN(dev); if (!mdev) return -ENODEV; return sprintf(buf, "%d\n", mdev->id); } static ssize_t _show_nrbchan(struct device *dev, struct device_attribute *attr, char *buf) { struct mISDNdevice *mdev = dev_to_mISDN(dev); if (!mdev) return -ENODEV; return sprintf(buf, "%d\n", mdev->nrbchan); } static ssize_t _show_d_protocols(struct device *dev, struct device_attribute *attr, char *buf) { struct mISDNdevice *mdev = dev_to_mISDN(dev); if (!mdev) return -ENODEV; return sprintf(buf, "%d\n", mdev->Dprotocols); } static ssize_t _show_b_protocols(struct device *dev, struct device_attribute *attr, char *buf) { struct mISDNdevice *mdev = dev_to_mISDN(dev); if (!mdev) return -ENODEV; return sprintf(buf, "%d\n", mdev->Bprotocols | get_all_Bprotocols()); } static ssize_t _show_protocol(struct device *dev, struct device_attribute *attr, char *buf) { struct mISDNdevice *mdev = dev_to_mISDN(dev); if (!mdev) return -ENODEV; return sprintf(buf, "%d\n", mdev->D.protocol); } static ssize_t _show_name(struct device *dev, struct device_attribute *attr, char *buf) { strcpy(buf, dev_name(dev)); return strlen(buf); } #if 0 /* hangs */ static ssize_t _set_name(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int err = 0; char *out = kmalloc(count + 1, GFP_KERNEL); if (!out) return -ENOMEM; memcpy(out, buf, count); if (count && out[count - 1] == '\n') out[--count] = 0; if (count) err = device_rename(dev, out); kfree(out); return (err < 0) ? err : count; } #endif static ssize_t _show_channelmap(struct device *dev, struct device_attribute *attr, char *buf) { struct mISDNdevice *mdev = dev_to_mISDN(dev); char *bp = buf; int i; for (i = 0; i <= mdev->nrbchan; i++) *bp++ = test_channelmap(i, mdev->channelmap) ? '1' : '0'; return bp - buf; } static struct device_attribute mISDN_dev_attrs[] = { __ATTR(id, S_IRUGO, _show_id, NULL), __ATTR(d_protocols, S_IRUGO, _show_d_protocols, NULL), __ATTR(b_protocols, S_IRUGO, _show_b_protocols, NULL), __ATTR(protocol, S_IRUGO, _show_protocol, NULL), __ATTR(channelmap, S_IRUGO, _show_channelmap, NULL), __ATTR(nrbchan, S_IRUGO, _show_nrbchan, NULL), __ATTR(name, S_IRUGO, _show_name, NULL), /* __ATTR(name, S_IRUGO|S_IWUSR, _show_name, _set_name), */ {} }; #ifdef CONFIG_HOTPLUG static int mISDN_uevent(struct device *dev, struct kobj_uevent_env *env) { struct mISDNdevice *mdev = dev_to_mISDN(dev); if (!mdev) return 0; if (add_uevent_var(env, "nchans=%d", mdev->nrbchan)) return -ENOMEM; return 0; } #endif static void mISDN_class_release(struct class *cls) { /* do nothing, it's static */ } static struct class mISDN_class = { .name = "mISDN", .owner = THIS_MODULE, #ifdef CONFIG_HOTPLUG .dev_uevent = mISDN_uevent, #endif .dev_attrs = mISDN_dev_attrs, .dev_release = mISDN_dev_release, .class_release = mISDN_class_release, }; static int _get_mdevice(struct device *dev, void *id) { struct mISDNdevice *mdev = dev_to_mISDN(dev); if (!mdev) return 0; if (mdev->id != *(u_int *)id) return 0; return 1; } struct mISDNdevice *get_mdevice(u_int id) { struct mISDNdevice *dev; read_lock(&device_lock); list_for_each_entry(dev, &devices, D.list) if (dev->id == id) { read_unlock(&device_lock); return dev; return dev_to_mISDN(class_find_device(&mISDN_class, NULL, &id, _get_mdevice)); } read_unlock(&device_lock); return NULL; static int _get_mdevice_count(struct device *dev, void *cnt) { *(int *)cnt += 1; return 0; } int get_mdevice_count(void) { struct mISDNdevice *dev; int cnt = 0; read_lock(&device_lock); list_for_each_entry(dev, &devices, D.list) cnt++; read_unlock(&device_lock); class_for_each_device(&mISDN_class, NULL, &cnt, _get_mdevice_count); return cnt; } Loading @@ -68,19 +212,24 @@ get_free_devid(void) for (i = 0; i <= MAX_DEVICE_ID; i++) if (!test_and_set_bit(i, (u_long *)&device_ids)) return i; break; if (i > MAX_DEVICE_ID) return -1; return i; } int mISDN_register_device(struct mISDNdevice *dev, char *name) mISDN_register_device(struct mISDNdevice *dev, struct device *parent, char *name) { u_long flags; int err; dev->id = get_free_devid(); err = -EBUSY; if (dev->id < 0) return -EBUSY; goto error1; device_initialize(&dev->dev); if (name && name[0]) dev_set_name(&dev->dev, "%s", name); else Loading @@ -90,26 +239,39 @@ mISDN_register_device(struct mISDNdevice *dev, char *name) dev_name(&dev->dev), dev->id); err = create_stack(dev); if (err) return err; write_lock_irqsave(&device_lock, flags); list_add_tail(&dev->D.list, &devices); write_unlock_irqrestore(&device_lock, flags); goto error1; dev->dev.class = &mISDN_class; dev->dev.platform_data = dev; dev->dev.parent = parent; dev_set_drvdata(&dev->dev, dev); err = device_add(&dev->dev); if (err) goto error3; return 0; error3: delete_stack(dev); return err; error1: return err; } EXPORT_SYMBOL(mISDN_register_device); void mISDN_unregister_device(struct mISDNdevice *dev) { u_long flags; if (debug & DEBUG_CORE) printk(KERN_DEBUG "mISDN_unregister %s %d\n", dev_name(&dev->dev), dev->id); write_lock_irqsave(&device_lock, flags); list_del(&dev->D.list); write_unlock_irqrestore(&device_lock, flags); /* sysfs_remove_link(&dev->dev.kobj, "device"); */ device_del(&dev->dev); dev_set_drvdata(&dev->dev, NULL); test_and_clear_bit(dev->id, (u_long *)&device_ids); delete_stack(dev); put_device(&dev->dev); } EXPORT_SYMBOL(mISDN_unregister_device); Loading Loading @@ -201,42 +363,43 @@ mISDNInit(void) MISDN_MAJOR_VERSION, MISDN_MINOR_VERSION, MISDN_RELEASE); mISDN_init_clock(&debug); mISDN_initstack(&debug); err = class_register(&mISDN_class); if (err) goto error1; err = mISDN_inittimer(&debug); if (err) goto error; goto error2; err = l1_init(&debug); if (err) { mISDN_timer_cleanup(); goto error; } if (err) goto error3; err = Isdnl2_Init(&debug); if (err) { mISDN_timer_cleanup(); l1_cleanup(); goto error; } if (err) goto error4; err = misdn_sock_init(&debug); if (err) { mISDN_timer_cleanup(); l1_cleanup(); if (err) goto error5; return 0; error5: Isdnl2_cleanup(); } error: error4: l1_cleanup(); error3: mISDN_timer_cleanup(); error2: class_unregister(&mISDN_class); error1: return err; } static void mISDN_cleanup(void) { misdn_sock_cleanup(); mISDN_timer_cleanup(); l1_cleanup(); Isdnl2_cleanup(); l1_cleanup(); mISDN_timer_cleanup(); class_unregister(&mISDN_class); if (!list_empty(&devices)) printk(KERN_ERR "%s devices still registered\n", __func__); if (!list_empty(&Bprotocols)) printk(KERN_ERR "%s Bprotocols still registered\n", __func__); printk(KERN_DEBUG "mISDNcore unloaded\n"); } Loading
drivers/isdn/mISDN/l1oip_core.c +2 −1 Original line number Diff line number Diff line Loading @@ -1433,7 +1433,8 @@ init_card(struct l1oip *hc, int pri, int bundle) hc->chan[i + ch].bch = bch; set_channelmap(bch->nr, dch->dev.channelmap); } ret = mISDN_register_device(&dch->dev, hc->name); /* TODO: create a parent device for this driver */ ret = mISDN_register_device(&dch->dev, NULL, hc->name); if (ret) return ret; hc->registered = 1; Loading
include/linux/mISDNif.h +7 −1 Original line number Diff line number Diff line Loading @@ -531,7 +531,8 @@ _queue_data(struct mISDNchannel *ch, u_int prim, /* global register/unregister functions */ extern int mISDN_register_device(struct mISDNdevice *, char *name); extern int mISDN_register_device(struct mISDNdevice *, struct device *parent, char *name); extern void mISDN_unregister_device(struct mISDNdevice *); extern int mISDN_register_Bprotocol(struct Bprotocol *); extern void mISDN_unregister_Bprotocol(struct Bprotocol *); Loading @@ -539,6 +540,11 @@ extern struct mISDNclock *mISDN_register_clock(char *, int, clockctl_func_t *, void *); extern void mISDN_unregister_clock(struct mISDNclock *); static inline struct mISDNdevice *dev_to_mISDN(struct device *dev) { return dev_get_drvdata(dev); } extern void set_channel_address(struct mISDNchannel *, u_int, u_int); extern void mISDN_clock_update(struct mISDNclock *, int, struct timeval *); extern unsigned short mISDN_clock_get(void); Loading