1 #include <linux/kernel.h> 2 #include <linux/spinlock.h> 3 #include <linux/device.h> 4 #include <linux/idr.h> 5 #include <linux/kdev_t.h> 6 #include <linux/err.h> 7 #include <linux/dca.h> 8 9 static struct class *dca_class; 10 static struct idr dca_idr; 11 static spinlock_t dca_idr_lock; 12 13 int dca_sysfs_add_req(struct dca_provider *dca, struct device *dev, int slot) 14 { 15 struct device *cd; 16 17 cd = device_create_drvdata(dca_class, dca->cd, 18 MKDEV(0, slot + 1), NULL, 19 "requester%d", slot); 20 if (IS_ERR(cd)) 21 return PTR_ERR(cd); 22 return 0; 23 } 24 25 void dca_sysfs_remove_req(struct dca_provider *dca, int slot) 26 { 27 device_destroy(dca_class, MKDEV(0, slot + 1)); 28 } 29 30 int dca_sysfs_add_provider(struct dca_provider *dca, struct device *dev) 31 { 32 struct device *cd; 33 int err = 0; 34 35 idr_try_again: 36 if (!idr_pre_get(&dca_idr, GFP_KERNEL)) 37 return -ENOMEM; 38 spin_lock(&dca_idr_lock); 39 err = idr_get_new(&dca_idr, dca, &dca->id); 40 spin_unlock(&dca_idr_lock); 41 switch (err) { 42 case 0: 43 break; 44 case -EAGAIN: 45 goto idr_try_again; 46 default: 47 return err; 48 } 49 50 cd = device_create_drvdata(dca_class, dev, MKDEV(0, 0), NULL, 51 "dca%d", dca->id); 52 if (IS_ERR(cd)) { 53 spin_lock(&dca_idr_lock); 54 idr_remove(&dca_idr, dca->id); 55 spin_unlock(&dca_idr_lock); 56 return PTR_ERR(cd); 57 } 58 dca->cd = cd; 59 return 0; 60 } 61 62 void dca_sysfs_remove_provider(struct dca_provider *dca) 63 { 64 device_unregister(dca->cd); 65 dca->cd = NULL; 66 spin_lock(&dca_idr_lock); 67 idr_remove(&dca_idr, dca->id); 68 spin_unlock(&dca_idr_lock); 69 } 70 71 int __init dca_sysfs_init(void) 72 { 73 idr_init(&dca_idr); 74 spin_lock_init(&dca_idr_lock); 75 76 dca_class = class_create(THIS_MODULE, "dca"); 77 if (IS_ERR(dca_class)) { 78 idr_destroy(&dca_idr); 79 return PTR_ERR(dca_class); 80 } 81 return 0; 82 } 83 84 void __exit dca_sysfs_exit(void) 85 { 86 class_destroy(dca_class); 87 idr_destroy(&dca_idr); 88 } 89 90