aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Maier <balagi@justmail.de>2006-12-08 05:36:12 -0500
committerLinus Torvalds <torvalds@woody.osdl.org>2006-12-08 11:28:38 -0500
commit32694850a91bd4fedcdd4a46292f870588be81d1 (patch)
tree370e1f97c9dff8f4feb71b8a1cf03cfe37b15d8b
parent0a0fc9601dd1024ec7171993bf075a789246e1ed (diff)
[PATCH] pktcdvd: add sysfs and debugfs interface
Add a sysfs and debugfs interface to the pktcdvd driver. Look into the Documentation/ABI/testing/* files in the patch for more info. Signed-off-by: Thomas Maier <balagi@justmail.de> Signed-off-by: Peter Osterlund <petero2@telia.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--Documentation/ABI/testing/debugfs-pktcdvd20
-rw-r--r--Documentation/ABI/testing/sysfs-class-pktcdvd72
-rw-r--r--Documentation/cdrom/packet-writing.txt35
-rw-r--r--drivers/block/pktcdvd.c443
-rw-r--r--include/linux/pktcdvd.h18
5 files changed, 583 insertions, 5 deletions
diff --git a/Documentation/ABI/testing/debugfs-pktcdvd b/Documentation/ABI/testing/debugfs-pktcdvd
new file mode 100644
index 000000000000..03dbd883cc41
--- /dev/null
+++ b/Documentation/ABI/testing/debugfs-pktcdvd
@@ -0,0 +1,20 @@
1What: /debug/pktcdvd/pktcdvd[0-7]
2Date: Oct. 2006
3KernelVersion: 2.6.19
4Contact: Thomas Maier <balagi@justmail.de>
5Description:
6
7debugfs interface
8-----------------
9
10The pktcdvd module (packet writing driver) creates
11these files in debugfs:
12
13/debug/pktcdvd/pktcdvd[0-7]/
14 info (0444) Lots of human readable driver
15 statistics and infos. Multiple lines!
16
17Example:
18-------
19
20cat /debug/pktcdvd/pktcdvd0/info
diff --git a/Documentation/ABI/testing/sysfs-class-pktcdvd b/Documentation/ABI/testing/sysfs-class-pktcdvd
new file mode 100644
index 000000000000..c4c55edc9a5c
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-pktcdvd
@@ -0,0 +1,72 @@
1What: /sys/class/pktcdvd/
2Date: Oct. 2006
3KernelVersion: 2.6.19
4Contact: Thomas Maier <balagi@justmail.de>
5Description:
6
7sysfs interface
8---------------
9
10The pktcdvd module (packet writing driver) creates
11these files in the sysfs:
12(<devid> is in format major:minor )
13
14/sys/class/pktcdvd/
15 add (0200) Write a block device id (major:minor)
16 to create a new pktcdvd device and map
17 it to the block device.
18
19 remove (0200) Write the pktcdvd device id (major:minor)
20 to it to remove the pktcdvd device.
21
22 device_map (0444) Shows the device mapping in format:
23 pktcdvd[0-7] <pktdevid> <blkdevid>
24
25/sys/class/pktcdvd/pktcdvd[0-7]/
26 dev (0444) Device id
27 uevent (0200) To send an uevent.
28
29/sys/class/pktcdvd/pktcdvd[0-7]/stat/
30 packets_started (0444) Number of started packets.
31 packets_finished (0444) Number of finished packets.
32
33 kb_written (0444) kBytes written.
34 kb_read (0444) kBytes read.
35 kb_read_gather (0444) kBytes read to fill write packets.
36
37 reset (0200) Write any value to it to reset
38 pktcdvd device statistic values, like
39 bytes read/written.
40
41/sys/class/pktcdvd/pktcdvd[0-7]/write_queue/
42 size (0444) Contains the size of the bio write
43 queue.
44
45 congestion_off (0644) If bio write queue size is below
46 this mark, accept new bio requests
47 from the block layer.
48
49 congestion_on (0644) If bio write queue size is higher
50 as this mark, do no longer accept
51 bio write requests from the block
52 layer and wait till the pktcdvd
53 device has processed enough bio's
54 so that bio write queue size is
55 below congestion off mark.
56 A value of <= 0 disables congestion
57 control.
58
59
60Example:
61--------
62To use the pktcdvd sysfs interface directly, you can do:
63
64# create a new pktcdvd device mapped to /dev/hdc
65echo "22:0" >/sys/class/pktcdvd/add
66cat /sys/class/pktcdvd/device_map
67# assuming device pktcdvd0 was created, look at stat's
68cat /sys/class/pktcdvd/pktcdvd0/stat/kb_written
69# print the device id of the mapped block device
70fgrep pktcdvd0 /sys/class/pktcdvd/device_map
71# remove device, using pktcdvd0 device id 253:0
72echo "253:0" >/sys/class/pktcdvd/remove
diff --git a/Documentation/cdrom/packet-writing.txt b/Documentation/cdrom/packet-writing.txt
index 3d44c561fe6d..7715d2247c4d 100644
--- a/Documentation/cdrom/packet-writing.txt
+++ b/Documentation/cdrom/packet-writing.txt
@@ -90,6 +90,41 @@ Notes
90 to create an ext2 filesystem on the disc. 90 to create an ext2 filesystem on the disc.
91 91
92 92
93Using the pktcdvd sysfs interface
94---------------------------------
95
96Since Linux 2.6.19, the pktcdvd module has a sysfs interface
97and can be controlled by it. For example the "pktcdvd" tool uses
98this interface. (see http://people.freenet.de/BalaGi#pktcdvd )
99
100"pktcdvd" works similar to "pktsetup", e.g.:
101
102 # pktcdvd -a dev_name /dev/hdc
103 # mkudffs /dev/pktcdvd/dev_name
104 # mount -t udf -o rw,noatime /dev/pktcdvd/dev_name /dvdram
105 # cp files /dvdram
106 # umount /dvdram
107 # pktcdvd -r dev_name
108
109
110For a description of the sysfs interface look into the file:
111
112 Documentation/ABI/testing/sysfs-block-pktcdvd
113
114
115Using the pktcdvd debugfs interface
116-----------------------------------
117
118To read pktcdvd device infos in human readable form, do:
119
120 # cat /debug/pktcdvd/pktcdvd[0-7]/info
121
122For a description of the debugfs interface look into the file:
123
124 Documentation/ABI/testing/debugfs-pktcdvd
125
126
127
93Links 128Links
94----- 129-----
95 130
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index 91fbe7fd6d0b..7c95c762950f 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -60,6 +60,8 @@
60#include <scsi/scsi_cmnd.h> 60#include <scsi/scsi_cmnd.h>
61#include <scsi/scsi_ioctl.h> 61#include <scsi/scsi_ioctl.h>
62#include <scsi/scsi.h> 62#include <scsi/scsi.h>
63#include <linux/debugfs.h>
64#include <linux/device.h>
63 65
64#include <asm/uaccess.h> 66#include <asm/uaccess.h>
65 67
@@ -89,6 +91,419 @@ static int write_congestion_off = PKT_WRITE_CONGESTION_OFF;
89static struct mutex ctl_mutex; /* Serialize open/close/setup/teardown */ 91static struct mutex ctl_mutex; /* Serialize open/close/setup/teardown */
90static mempool_t *psd_pool; 92static mempool_t *psd_pool;
91 93
94static struct class *class_pktcdvd = NULL; /* /sys/class/pktcdvd */
95static struct dentry *pkt_debugfs_root = NULL; /* /debug/pktcdvd */
96
97/* forward declaration */
98static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev);
99static int pkt_remove_dev(dev_t pkt_dev);
100static int pkt_seq_show(struct seq_file *m, void *p);
101
102
103
104/*
105 * create and register a pktcdvd kernel object.
106 */
107static struct pktcdvd_kobj* pkt_kobj_create(struct pktcdvd_device *pd,
108 const char* name,
109 struct kobject* parent,
110 struct kobj_type* ktype)
111{
112 struct pktcdvd_kobj *p;
113 p = kzalloc(sizeof(*p), GFP_KERNEL);
114 if (!p)
115 return NULL;
116 kobject_set_name(&p->kobj, "%s", name);
117 p->kobj.parent = parent;
118 p->kobj.ktype = ktype;
119 p->pd = pd;
120 if (kobject_register(&p->kobj) != 0)
121 return NULL;
122 return p;
123}
124/*
125 * remove a pktcdvd kernel object.
126 */
127static void pkt_kobj_remove(struct pktcdvd_kobj *p)
128{
129 if (p)
130 kobject_unregister(&p->kobj);
131}
132/*
133 * default release function for pktcdvd kernel objects.
134 */
135static void pkt_kobj_release(struct kobject *kobj)
136{
137 kfree(to_pktcdvdkobj(kobj));
138}
139
140
141/**********************************************************
142 *
143 * sysfs interface for pktcdvd
144 * by (C) 2006 Thomas Maier <balagi@justmail.de>
145 *
146 **********************************************************/
147
148#define DEF_ATTR(_obj,_name,_mode) \
149 static struct attribute _obj = { \
150 .name = _name, .owner = THIS_MODULE, .mode = _mode }
151
152/**********************************************************
153 /sys/class/pktcdvd/pktcdvd[0-7]/
154 stat/reset
155 stat/packets_started
156 stat/packets_finished
157 stat/kb_written
158 stat/kb_read
159 stat/kb_read_gather
160 write_queue/size
161 write_queue/congestion_off
162 write_queue/congestion_on
163 **********************************************************/
164
165DEF_ATTR(kobj_pkt_attr_st1, "reset", 0200);
166DEF_ATTR(kobj_pkt_attr_st2, "packets_started", 0444);
167DEF_ATTR(kobj_pkt_attr_st3, "packets_finished", 0444);
168DEF_ATTR(kobj_pkt_attr_st4, "kb_written", 0444);
169DEF_ATTR(kobj_pkt_attr_st5, "kb_read", 0444);
170DEF_ATTR(kobj_pkt_attr_st6, "kb_read_gather", 0444);
171
172static struct attribute *kobj_pkt_attrs_stat[] = {
173 &kobj_pkt_attr_st1,
174 &kobj_pkt_attr_st2,
175 &kobj_pkt_attr_st3,
176 &kobj_pkt_attr_st4,
177 &kobj_pkt_attr_st5,
178 &kobj_pkt_attr_st6,
179 NULL
180};
181
182DEF_ATTR(kobj_pkt_attr_wq1, "size", 0444);
183DEF_ATTR(kobj_pkt_attr_wq2, "congestion_off", 0644);
184DEF_ATTR(kobj_pkt_attr_wq3, "congestion_on", 0644);
185
186static struct attribute *kobj_pkt_attrs_wqueue[] = {
187 &kobj_pkt_attr_wq1,
188 &kobj_pkt_attr_wq2,
189 &kobj_pkt_attr_wq3,
190 NULL
191};
192
193/* declares a char buffer[64] _dbuf, copies data from
194 * _b with length _l into it and ensures that _dbuf ends
195 * with a \0 character.
196 */
197#define DECLARE_BUF_AS_STRING(_dbuf, _b, _l) \
198 char _dbuf[64]; int dlen = (_l) < 0 ? 0 : (_l); \
199 if (dlen >= sizeof(_dbuf)) dlen = sizeof(_dbuf)-1; \
200 memcpy(_dbuf, _b, dlen); _dbuf[dlen] = 0
201
202static ssize_t kobj_pkt_show(struct kobject *kobj,
203 struct attribute *attr, char *data)
204{
205 struct pktcdvd_device *pd = to_pktcdvdkobj(kobj)->pd;
206 int n = 0;
207 int v;
208 if (strcmp(attr->name, "packets_started") == 0) {
209 n = sprintf(data, "%lu\n", pd->stats.pkt_started);
210
211 } else if (strcmp(attr->name, "packets_finished") == 0) {
212 n = sprintf(data, "%lu\n", pd->stats.pkt_ended);
213
214 } else if (strcmp(attr->name, "kb_written") == 0) {
215 n = sprintf(data, "%lu\n", pd->stats.secs_w >> 1);
216
217 } else if (strcmp(attr->name, "kb_read") == 0) {
218 n = sprintf(data, "%lu\n", pd->stats.secs_r >> 1);
219
220 } else if (strcmp(attr->name, "kb_read_gather") == 0) {
221 n = sprintf(data, "%lu\n", pd->stats.secs_rg >> 1);
222
223 } else if (strcmp(attr->name, "size") == 0) {
224 spin_lock(&pd->lock);
225 v = pd->bio_queue_size;
226 spin_unlock(&pd->lock);
227 n = sprintf(data, "%d\n", v);
228
229 } else if (strcmp(attr->name, "congestion_off") == 0) {
230 spin_lock(&pd->lock);
231 v = pd->write_congestion_off;
232 spin_unlock(&pd->lock);
233 n = sprintf(data, "%d\n", v);
234
235 } else if (strcmp(attr->name, "congestion_on") == 0) {
236 spin_lock(&pd->lock);
237 v = pd->write_congestion_on;
238 spin_unlock(&pd->lock);
239 n = sprintf(data, "%d\n", v);
240 }
241 return n;
242}
243
244static void init_write_congestion_marks(int* lo, int* hi)
245{
246 if (*hi > 0) {
247 *hi = max(*hi, 500);
248 *hi = min(*hi, 1000000);
249 if (*lo <= 0)
250 *lo = *hi - 100;
251 else {
252 *lo = min(*lo, *hi - 100);
253 *lo = max(*lo, 100);
254 }
255 } else {
256 *hi = -1;
257 *lo = -1;
258 }
259}
260
261static ssize_t kobj_pkt_store(struct kobject *kobj,
262 struct attribute *attr,
263 const char *data, size_t len)
264{
265 struct pktcdvd_device *pd = to_pktcdvdkobj(kobj)->pd;
266 int val;
267 DECLARE_BUF_AS_STRING(dbuf, data, len); /* ensure sscanf scans a string */
268
269 if (strcmp(attr->name, "reset") == 0 && dlen > 0) {
270 pd->stats.pkt_started = 0;
271 pd->stats.pkt_ended = 0;
272 pd->stats.secs_w = 0;
273 pd->stats.secs_rg = 0;
274 pd->stats.secs_r = 0;
275
276 } else if (strcmp(attr->name, "congestion_off") == 0
277 && sscanf(dbuf, "%d", &val) == 1) {
278 spin_lock(&pd->lock);
279 pd->write_congestion_off = val;
280 init_write_congestion_marks(&pd->write_congestion_off,
281 &pd->write_congestion_on);
282 spin_unlock(&pd->lock);
283
284 } else if (strcmp(attr->name, "congestion_on") == 0
285 && sscanf(dbuf, "%d", &val) == 1) {
286 spin_lock(&pd->lock);
287 pd->write_congestion_on = val;
288 init_write_congestion_marks(&pd->write_congestion_off,
289 &pd->write_congestion_on);
290 spin_unlock(&pd->lock);
291 }
292 return len;
293}
294
295static struct sysfs_ops kobj_pkt_ops = {
296 .show = kobj_pkt_show,
297 .store = kobj_pkt_store
298};
299static struct kobj_type kobj_pkt_type_stat = {
300 .release = pkt_kobj_release,
301 .sysfs_ops = &kobj_pkt_ops,
302 .default_attrs = kobj_pkt_attrs_stat
303};
304static struct kobj_type kobj_pkt_type_wqueue = {
305 .release = pkt_kobj_release,
306 .sysfs_ops = &kobj_pkt_ops,
307 .default_attrs = kobj_pkt_attrs_wqueue
308};
309
310static void pkt_sysfs_dev_new(struct pktcdvd_device *pd)
311{
312 if (class_pktcdvd) {
313 pd->clsdev = class_device_create(class_pktcdvd,
314 NULL, pd->pkt_dev,
315 NULL, "%s", pd->name);
316 if (IS_ERR(pd->clsdev))
317 pd->clsdev = NULL;
318 }
319 if (pd->clsdev) {
320 pd->kobj_stat = pkt_kobj_create(pd, "stat",
321 &pd->clsdev->kobj,
322 &kobj_pkt_type_stat);
323 pd->kobj_wqueue = pkt_kobj_create(pd, "write_queue",
324 &pd->clsdev->kobj,
325 &kobj_pkt_type_wqueue);
326 }
327}
328
329static void pkt_sysfs_dev_remove(struct pktcdvd_device *pd)
330{
331 pkt_kobj_remove(pd->kobj_stat);
332 pkt_kobj_remove(pd->kobj_wqueue);
333 if (class_pktcdvd)
334 class_device_destroy(class_pktcdvd, pd->pkt_dev);
335}
336
337
338/********************************************************************
339 /sys/class/pktcdvd/
340 add map block device
341 remove unmap packet dev
342 device_map show mappings
343 *******************************************************************/
344
345static void class_pktcdvd_release(struct class *cls)
346{
347 kfree(cls);
348}
349static ssize_t class_pktcdvd_show_map(struct class *c, char *data)
350{
351 int n = 0;
352 int idx;
353 mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
354 for (idx = 0; idx < MAX_WRITERS; idx++) {
355 struct pktcdvd_device *pd = pkt_devs[idx];
356 if (!pd)
357 continue;
358 n += sprintf(data+n, "%s %u:%u %u:%u\n",
359 pd->name,
360 MAJOR(pd->pkt_dev), MINOR(pd->pkt_dev),
361 MAJOR(pd->bdev->bd_dev),
362 MINOR(pd->bdev->bd_dev));
363 }
364 mutex_unlock(&ctl_mutex);
365 return n;
366}
367
368static ssize_t class_pktcdvd_store_add(struct class *c, const char *buf,
369 size_t count)
370{
371 unsigned int major, minor;
372 DECLARE_BUF_AS_STRING(dbuf, buf, count);
373 if (sscanf(dbuf, "%u:%u", &major, &minor) == 2) {
374 pkt_setup_dev(MKDEV(major, minor), NULL);
375 return count;
376 }
377 return -EINVAL;
378}
379
380static ssize_t class_pktcdvd_store_remove(struct class *c, const char *buf,
381 size_t count)
382{
383 unsigned int major, minor;
384 DECLARE_BUF_AS_STRING(dbuf, buf, count);
385 if (sscanf(dbuf, "%u:%u", &major, &minor) == 2) {
386 pkt_remove_dev(MKDEV(major, minor));
387 return count;
388 }
389 return -EINVAL;
390}
391
392static struct class_attribute class_pktcdvd_attrs[] = {
393 __ATTR(add, 0200, NULL, class_pktcdvd_store_add),
394 __ATTR(remove, 0200, NULL, class_pktcdvd_store_remove),
395 __ATTR(device_map, 0444, class_pktcdvd_show_map, NULL),
396 __ATTR_NULL
397};
398
399
400static int pkt_sysfs_init(void)
401{
402 int ret = 0;
403
404 /*
405 * create control files in sysfs
406 * /sys/class/pktcdvd/...
407 */
408 class_pktcdvd = kzalloc(sizeof(*class_pktcdvd), GFP_KERNEL);
409 if (!class_pktcdvd)
410 return -ENOMEM;
411 class_pktcdvd->name = DRIVER_NAME;
412 class_pktcdvd->owner = THIS_MODULE;
413 class_pktcdvd->class_release = class_pktcdvd_release;
414 class_pktcdvd->class_attrs = class_pktcdvd_attrs;
415 ret = class_register(class_pktcdvd);
416 if (ret) {
417 kfree(class_pktcdvd);
418 class_pktcdvd = NULL;
419 printk(DRIVER_NAME": failed to create class pktcdvd\n");
420 return ret;
421 }
422 return 0;
423}
424
425static void pkt_sysfs_cleanup(void)
426{
427 if (class_pktcdvd)
428 class_destroy(class_pktcdvd);
429 class_pktcdvd = NULL;
430}
431
432/********************************************************************
433 entries in debugfs
434
435 /debugfs/pktcdvd[0-7]/
436 info
437
438 *******************************************************************/
439
440static int pkt_debugfs_seq_show(struct seq_file *m, void *p)
441{
442 return pkt_seq_show(m, p);
443}
444
445static int pkt_debugfs_fops_open(struct inode *inode, struct file *file)
446{
447 return single_open(file, pkt_debugfs_seq_show, inode->i_private);
448}
449
450static struct file_operations debug_fops = {
451 .open = pkt_debugfs_fops_open,
452 .read = seq_read,
453 .llseek = seq_lseek,
454 .release = single_release,
455 .owner = THIS_MODULE,
456};
457
458static void pkt_debugfs_dev_new(struct pktcdvd_device *pd)
459{
460 if (!pkt_debugfs_root)
461 return;
462 pd->dfs_f_info = NULL;
463 pd->dfs_d_root = debugfs_create_dir(pd->name, pkt_debugfs_root);
464 if (IS_ERR(pd->dfs_d_root)) {
465 pd->dfs_d_root = NULL;
466 return;
467 }
468 pd->dfs_f_info = debugfs_create_file("info", S_IRUGO,
469 pd->dfs_d_root, pd, &debug_fops);
470 if (IS_ERR(pd->dfs_f_info)) {
471 pd->dfs_f_info = NULL;
472 return;
473 }
474}
475
476static void pkt_debugfs_dev_remove(struct pktcdvd_device *pd)
477{
478 if (!pkt_debugfs_root)
479 return;
480 if (pd->dfs_f_info)
481 debugfs_remove(pd->dfs_f_info);
482 pd->dfs_f_info = NULL;
483 if (pd->dfs_d_root)
484 debugfs_remove(pd->dfs_d_root);
485 pd->dfs_d_root = NULL;
486}
487
488static void pkt_debugfs_init(void)
489{
490 pkt_debugfs_root = debugfs_create_dir(DRIVER_NAME, NULL);
491 if (IS_ERR(pkt_debugfs_root)) {
492 pkt_debugfs_root = NULL;
493 return;
494 }
495}
496
497static void pkt_debugfs_cleanup(void)
498{
499 if (!pkt_debugfs_root)
500 return;
501 debugfs_remove(pkt_debugfs_root);
502 pkt_debugfs_root = NULL;
503}
504
505/* ----------------------------------------------------------*/
506
92 507
93static void pkt_bio_finished(struct pktcdvd_device *pd) 508static void pkt_bio_finished(struct pktcdvd_device *pd)
94{ 509{
@@ -2527,6 +2942,9 @@ static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev)
2527 2942
2528 add_disk(disk); 2943 add_disk(disk);
2529 2944
2945 pkt_sysfs_dev_new(pd);
2946 pkt_debugfs_dev_new(pd);
2947
2530 pkt_devs[idx] = pd; 2948 pkt_devs[idx] = pd;
2531 if (pkt_dev) 2949 if (pkt_dev)
2532 *pkt_dev = pd->pkt_dev; 2950 *pkt_dev = pd->pkt_dev;
@@ -2577,6 +2995,11 @@ static int pkt_remove_dev(dev_t pkt_dev)
2577 if (!IS_ERR(pd->cdrw.thread)) 2995 if (!IS_ERR(pd->cdrw.thread))
2578 kthread_stop(pd->cdrw.thread); 2996 kthread_stop(pd->cdrw.thread);
2579 2997
2998 pkt_devs[idx] = NULL;
2999
3000 pkt_debugfs_dev_remove(pd);
3001 pkt_sysfs_dev_remove(pd);
3002
2580 blkdev_put(pd->bdev); 3003 blkdev_put(pd->bdev);
2581 3004
2582 remove_proc_entry(pd->name, pkt_proc); 3005 remove_proc_entry(pd->name, pkt_proc);
@@ -2586,7 +3009,6 @@ static int pkt_remove_dev(dev_t pkt_dev)
2586 blk_cleanup_queue(pd->disk->queue); 3009 blk_cleanup_queue(pd->disk->queue);
2587 put_disk(pd->disk); 3010 put_disk(pd->disk);
2588 3011
2589 pkt_devs[idx] = NULL;
2590 mempool_destroy(pd->rb_pool); 3012 mempool_destroy(pd->rb_pool);
2591 kfree(pd); 3013 kfree(pd);
2592 3014
@@ -2670,6 +3092,8 @@ static int __init pkt_init(void)
2670{ 3092{
2671 int ret; 3093 int ret;
2672 3094
3095 mutex_init(&ctl_mutex);
3096
2673 psd_pool = mempool_create_kmalloc_pool(PSD_POOL_SIZE, 3097 psd_pool = mempool_create_kmalloc_pool(PSD_POOL_SIZE,
2674 sizeof(struct packet_stacked_data)); 3098 sizeof(struct packet_stacked_data));
2675 if (!psd_pool) 3099 if (!psd_pool)
@@ -2683,18 +3107,25 @@ static int __init pkt_init(void)
2683 if (!pktdev_major) 3107 if (!pktdev_major)
2684 pktdev_major = ret; 3108 pktdev_major = ret;
2685 3109
3110 ret = pkt_sysfs_init();
3111 if (ret)
3112 goto out;
3113
3114 pkt_debugfs_init();
3115
2686 ret = misc_register(&pkt_misc); 3116 ret = misc_register(&pkt_misc);
2687 if (ret) { 3117 if (ret) {
2688 printk(DRIVER_NAME": Unable to register misc device\n"); 3118 printk(DRIVER_NAME": Unable to register misc device\n");
2689 goto out; 3119 goto out_misc;
2690 } 3120 }
2691 3121
2692 mutex_init(&ctl_mutex);
2693
2694 pkt_proc = proc_mkdir(DRIVER_NAME, proc_root_driver); 3122 pkt_proc = proc_mkdir(DRIVER_NAME, proc_root_driver);
2695 3123
2696 return 0; 3124 return 0;
2697 3125
3126out_misc:
3127 pkt_debugfs_cleanup();
3128 pkt_sysfs_cleanup();
2698out: 3129out:
2699 unregister_blkdev(pktdev_major, DRIVER_NAME); 3130 unregister_blkdev(pktdev_major, DRIVER_NAME);
2700out2: 3131out2:
@@ -2706,6 +3137,10 @@ static void __exit pkt_exit(void)
2706{ 3137{
2707 remove_proc_entry(DRIVER_NAME, proc_root_driver); 3138 remove_proc_entry(DRIVER_NAME, proc_root_driver);
2708 misc_deregister(&pkt_misc); 3139 misc_deregister(&pkt_misc);
3140
3141 pkt_debugfs_cleanup();
3142 pkt_sysfs_cleanup();
3143
2709 unregister_blkdev(pktdev_major, DRIVER_NAME); 3144 unregister_blkdev(pktdev_major, DRIVER_NAME);
2710 mempool_destroy(psd_pool); 3145 mempool_destroy(psd_pool);
2711} 3146}
diff --git a/include/linux/pktcdvd.h b/include/linux/pktcdvd.h
index 9b1a185fb1e5..5ea4f05683f6 100644
--- a/include/linux/pktcdvd.h
+++ b/include/linux/pktcdvd.h
@@ -111,7 +111,8 @@ struct pkt_ctrl_command {
111#include <linux/blkdev.h> 111#include <linux/blkdev.h>
112#include <linux/completion.h> 112#include <linux/completion.h>
113#include <linux/cdrom.h> 113#include <linux/cdrom.h>
114 114#include <linux/kobject.h>
115#include <linux/sysfs.h>
115 116
116/* default bio write queue congestion marks */ 117/* default bio write queue congestion marks */
117#define PKT_WRITE_CONGESTION_ON 10000 118#define PKT_WRITE_CONGESTION_ON 10000
@@ -247,6 +248,14 @@ struct packet_stacked_data
247}; 248};
248#define PSD_POOL_SIZE 64 249#define PSD_POOL_SIZE 64
249 250
251struct pktcdvd_kobj
252{
253 struct kobject kobj;
254 struct pktcdvd_device *pd;
255};
256#define to_pktcdvdkobj(_k) \
257 ((struct pktcdvd_kobj*)container_of(_k,struct pktcdvd_kobj,kobj))
258
250struct pktcdvd_device 259struct pktcdvd_device
251{ 260{
252 struct block_device *bdev; /* dev attached */ 261 struct block_device *bdev; /* dev attached */
@@ -280,6 +289,13 @@ struct pktcdvd_device
280 289
281 int write_congestion_off; 290 int write_congestion_off;
282 int write_congestion_on; 291 int write_congestion_on;
292
293 struct class_device *clsdev; /* sysfs pktcdvd[0-7] class dev */
294 struct pktcdvd_kobj *kobj_stat; /* sysfs pktcdvd[0-7]/stat/ */
295 struct pktcdvd_kobj *kobj_wqueue; /* sysfs pktcdvd[0-7]/write_queue/ */
296
297 struct dentry *dfs_d_root; /* debugfs: devname directory */
298 struct dentry *dfs_f_info; /* debugfs: info file */
283}; 299};
284 300
285#endif /* __KERNEL__ */ 301#endif /* __KERNEL__ */