2 * I2O Configuration Interface Driver
4 * (C) Copyright 1999 Red Hat Software
6 * Written by Alan Cox, Building Number Three Ltd
8 * Modified 04/20/1999 by Deepak Saxena
9 * - Added basic ioctl() support
10 * Modified 06/07/1999 by Deepak Saxena
11 * - Added software download ioctl (still testing)
12 * Modified 09/10/1999 by Auvo Häkkinen
13 * - Changes to i2o_cfg_reply(), ioctl_parms()
14 * - Added ioct_validate()
15 * Modified 09/30/1999 by Taneli Vähäkangas
16 * - Fixed ioctl_swdl()
17 * Modified 10/04/1999 by Taneli Vähäkangas
18 * - Changed ioctl_swdl(), implemented ioctl_swul() and ioctl_swdel()
19 * Modified 11/18/199 by Deepak Saxena
20 * - Added event managmenet support
22 * This program is free software; you can redistribute it and/or
23 * modify it under the terms of the GNU General Public License
24 * as published by the Free Software Foundation; either version
25 * 2 of the License, or (at your option) any later version.
28 #include <linux/module.h>
29 #include <linux/kernel.h>
30 #include <linux/pci.h>
31 #include <linux/i2o.h>
32 #include <linux/errno.h>
33 #include <linux/init.h>
34 #include <linux/malloc.h>
35 #include <linux/miscdevice.h>
37 #include <linux/spinlock.h>
38 #include <linux/smp_lock.h>
40 #include <asm/uaccess.h>
43 static int i2o_cfg_context
= -1;
44 static void *page_buf
;
45 static void *i2o_buffer
;
46 static spinlock_t i2o_config_lock
= SPIN_LOCK_UNLOCKED
;
47 struct wait_queue
*i2o_wait_queue
;
49 #define MODINC(x,y) (x = x++ % y)
54 struct fasync_struct
*fasync
;
55 struct i2o_evt_info event_q
[I2O_EVT_Q_LEN
];
56 u16 q_in
; // Queue head index
57 u16 q_out
; // Queue tail index
58 u16 q_len
; // Queue length
59 u16 q_lost
; // Number of lost events
60 u32 q_id
; // Event queue ID...used as tx_context
61 struct i2o_cfg_info
*next
;
63 static struct i2o_cfg_info
*open_files
= NULL
;
64 static int i2o_cfg_info_id
= 0;
66 static int ioctl_getiops(unsigned long);
67 static int ioctl_gethrt(unsigned long);
68 static int ioctl_getlct(unsigned long);
69 static int ioctl_parms(unsigned long, unsigned int);
70 static int ioctl_html(unsigned long);
71 static int ioctl_swdl(unsigned long);
72 static int ioctl_swul(unsigned long);
73 static int ioctl_swdel(unsigned long);
74 static int ioctl_validate(unsigned long);
75 static int ioctl_evt_reg(unsigned long, struct file
*);
76 static int ioctl_evt_get(unsigned long, struct file
*);
77 static int cfg_fasync(int, struct file
*, int);
80 * This is the callback for any message we have posted. The message itself
81 * will be returned to the message pool when we return from the IRQ
83 * This runs in irq context so be short and sweet.
85 static void i2o_cfg_reply(struct i2o_handler
*h
, struct i2o_controller
*c
, struct i2o_message
*m
)
89 if (msg
[0] & MSG_FAIL
) {
90 u32
*preserved_msg
= (u32
*)(c
->mem_offset
+ msg
[7]);
92 printk(KERN_ERR
"i2o_config: IOP failed to process the msg.\n");
94 /* Release the preserved msg frame by resubmitting it as a NOP */
96 preserved_msg
[0] = THREE_WORD_MSG_SIZE
| SGL_OFFSET_0
;
97 preserved_msg
[1] = I2O_CMD_UTIL_NOP
<< 24 | HOST_TID
<< 12 | 0;
99 i2o_post_message(c
, msg
[7]);
102 if (msg
[4] >> 24) // ReqStatus != SUCCESS
103 i2o_report_status(KERN_INFO
,"i2o_config", msg
);
105 if(m
->function
== I2O_CMD_UTIL_EVT_REGISTER
)
107 struct i2o_cfg_info
*inf
;
109 for(inf
= open_files
; inf
; inf
= inf
->next
)
110 if(inf
->q_id
== msg
[3])
114 // If this is the case, it means that we're getting
115 // events for a file descriptor that's been close()'d
116 // w/o the user unregistering for events first.
117 // The code currently assumes that the user will
118 // take care of unregistering for events before closing
122 // Should we track event registartion and deregister
123 // for events when a file is close()'d so this doesn't
124 // happen? That would get rid of the search through
125 // the linked list since file->private_data could point
126 // directly to the i2o_config_info data structure...but
127 // it would mean having all sorts of tables to track
128 // what each file is registered for...I think the
129 // current method is simpler. - DS
134 inf
->event_q
[inf
->q_in
].id
.iop
= c
->unit
;
135 inf
->event_q
[inf
->q_in
].id
.tid
= m
->target_tid
;
136 inf
->event_q
[inf
->q_in
].id
.evt_mask
= msg
[4];
139 // Data size = msg size - reply header
141 inf
->event_q
[inf
->q_in
].data_size
= (m
->size
- 5) * 4;
142 if(inf
->event_q
[inf
->q_in
].data_size
)
143 memcpy(inf
->event_q
[inf
->q_in
].evt_data
,
144 (unsigned char *)(msg
+ 5),
145 inf
->event_q
[inf
->q_in
].data_size
);
147 spin_lock(&i2o_config_lock
);
148 MODINC(inf
->q_in
, I2O_EVT_Q_LEN
);
149 if(inf
->q_len
== I2O_EVT_Q_LEN
)
151 MODINC(inf
->q_out
, I2O_EVT_Q_LEN
);
156 // Keep I2OEVTGET on another CPU from touching this
159 spin_unlock(&i2o_config_lock
);
162 // printk(KERN_INFO "File %p w/id %d has %d events\n",
163 // inf->fp, inf->q_id, inf->q_len);
165 kill_fasync(&inf
->fasync
, SIGIO
, POLL_IN
);
172 * Each of these describes an i2o message handler. They are
173 * multiplexed by the i2o_core code
176 struct i2o_handler cfg_handler
=
184 0xffffffff // All classes
187 static long long cfg_llseek(struct file
*file
, long long offset
, int origin
)
193 static ssize_t
cfg_write(struct file
*file
, const char *buf
, size_t count
, loff_t
*ppos
)
195 printk(KERN_INFO
"i2o_config write not yet supported\n");
201 static ssize_t
cfg_read(struct file
*file
, char *buf
, size_t count
, loff_t
*ptr
)
209 static int cfg_ioctl(struct inode
*inode
, struct file
*fp
, unsigned int cmd
,
217 ret
= ioctl_getiops(arg
);
221 ret
= ioctl_gethrt(arg
);
225 ret
= ioctl_getlct(arg
);
229 ret
= ioctl_parms(arg
, I2OPARMSET
);
233 ret
= ioctl_parms(arg
, I2OPARMGET
);
237 ret
= ioctl_swdl(arg
);
241 ret
= ioctl_swul(arg
);
245 ret
= ioctl_swdel(arg
);
249 ret
= ioctl_validate(arg
);
253 ret
= ioctl_html(arg
);
257 ret
= ioctl_evt_reg(arg
, fp
);
261 ret
= ioctl_evt_get(arg
, fp
);
271 int ioctl_getiops(unsigned long arg
)
273 u8
*user_iop_table
= (u8
*)arg
;
274 struct i2o_controller
*c
= NULL
;
276 u8 foo
[MAX_I2O_CONTROLLERS
];
278 if(!access_ok(VERIFY_WRITE
, user_iop_table
, MAX_I2O_CONTROLLERS
))
281 for(i
= 0; i
< MAX_I2O_CONTROLLERS
; i
++)
283 c
= i2o_find_controller(i
);
287 i2o_unlock_controller(c
);
295 __copy_to_user(user_iop_table
, foo
, MAX_I2O_CONTROLLERS
);
299 int ioctl_gethrt(unsigned long arg
)
301 struct i2o_controller
*c
;
302 struct i2o_cmd_hrtlct
*cmd
= (struct i2o_cmd_hrtlct
*)arg
;
303 struct i2o_cmd_hrtlct kcmd
;
309 if(copy_from_user(&kcmd
, cmd
, sizeof(struct i2o_cmd_hrtlct
)))
312 if(get_user(reslen
, kcmd
.reslen
) < 0)
315 if(kcmd
.resbuf
== NULL
)
318 c
= i2o_find_controller(kcmd
.iop
);
322 hrt
= (i2o_hrt
*)c
->hrt
;
324 i2o_unlock_controller(c
);
326 len
= 8 + ((hrt
->entry_len
* hrt
->num_entries
) << 2);
328 /* We did a get user...so assuming mem is ok...is this bad? */
329 put_user(len
, kcmd
.reslen
);
332 if(copy_to_user(kcmd
.resbuf
, (void*)hrt
, len
))
338 int ioctl_getlct(unsigned long arg
)
340 struct i2o_controller
*c
;
341 struct i2o_cmd_hrtlct
*cmd
= (struct i2o_cmd_hrtlct
*)arg
;
342 struct i2o_cmd_hrtlct kcmd
;
348 if(copy_from_user(&kcmd
, cmd
, sizeof(struct i2o_cmd_hrtlct
)))
351 if(get_user(reslen
, kcmd
.reslen
) < 0)
354 if(kcmd
.resbuf
== NULL
)
357 c
= i2o_find_controller(kcmd
.iop
);
361 lct
= (i2o_lct
*)c
->lct
;
362 i2o_unlock_controller(c
);
364 len
= (unsigned int)lct
->table_size
<< 2;
365 put_user(len
, kcmd
.reslen
);
368 else if(copy_to_user(kcmd
.resbuf
, (void*)lct
, len
))
374 static int ioctl_parms(unsigned long arg
, unsigned int type
)
377 struct i2o_controller
*c
;
378 struct i2o_cmd_psetget
*cmd
= (struct i2o_cmd_psetget
*)arg
;
379 struct i2o_cmd_psetget kcmd
;
385 u32 i2o_cmd
= (type
== I2OPARMGET
?
386 I2O_CMD_UTIL_PARAMS_GET
:
387 I2O_CMD_UTIL_PARAMS_SET
);
389 if(copy_from_user(&kcmd
, cmd
, sizeof(struct i2o_cmd_psetget
)))
392 if(get_user(reslen
, kcmd
.reslen
))
395 c
= i2o_find_controller(kcmd
.iop
);
399 ops
= (u8
*)kmalloc(kcmd
.oplen
, GFP_KERNEL
);
402 i2o_unlock_controller(c
);
406 if(copy_from_user(ops
, kcmd
.opbuf
, kcmd
.oplen
))
408 i2o_unlock_controller(c
);
414 * It's possible to have a _very_ large table
415 * and that the user asks for all of it at once...
417 res
= (u8
*)kmalloc(65536, GFP_KERNEL
);
420 i2o_unlock_controller(c
);
425 len
= i2o_issue_params(i2o_cmd
, c
, kcmd
.tid
,
426 ops
, kcmd
.oplen
, res
, 65536);
427 i2o_unlock_controller(c
);
435 put_user(len
, kcmd
.reslen
);
438 else if(copy_to_user(cmd
->resbuf
, res
, len
))
446 int ioctl_html(unsigned long arg
)
448 struct i2o_html
*cmd
= (struct i2o_html
*)arg
;
449 struct i2o_html kcmd
;
450 struct i2o_controller
*c
;
457 u32 msg
[MSG_FRAME_SIZE
/4];
459 if(copy_from_user(&kcmd
, cmd
, sizeof(struct i2o_html
)))
461 printk(KERN_INFO
"i2o_config: can't copy html cmd\n");
465 if(get_user(reslen
, kcmd
.reslen
) < 0)
467 printk(KERN_INFO
"i2o_config: can't copy html reslen\n");
473 printk(KERN_INFO
"i2o_config: NULL html buffer\n");
477 c
= i2o_find_controller(kcmd
.iop
);
481 if(kcmd
.qlen
) /* Check for post data */
483 query
= kmalloc(kcmd
.qlen
, GFP_KERNEL
);
486 i2o_unlock_controller(c
);
489 if(copy_from_user(query
, kcmd
.qbuf
, kcmd
.qlen
))
491 i2o_unlock_controller(c
);
492 printk(KERN_INFO
"i2o_config: could not get query\n");
498 res
= kmalloc(65536, GFP_KERNEL
);
501 i2o_unlock_controller(c
);
505 msg
[1] = (I2O_CMD_UTIL_CONFIG_DIALOG
<< 24)|HOST_TID
<<12|kcmd
.tid
;
506 msg
[2] = i2o_cfg_context
;
509 msg
[5] = 0xD0000000|65536;
510 msg
[6] = virt_to_bus(res
);
511 if(!kcmd
.qlen
) /* Check for post data */
512 msg
[0] = SEVEN_WORD_MSG_SIZE
|SGL_OFFSET_5
;
515 msg
[0] = NINE_WORD_MSG_SIZE
|SGL_OFFSET_5
;
516 msg
[5] = 0x50000000|65536;
517 msg
[7] = 0xD4000000|(kcmd
.qlen
);
518 msg
[8] = virt_to_bus(query
);
521 token
= i2o_post_wait(c
, msg
, 9*4, 10);
524 printk(KERN_DEBUG
"token = %#10x\n", token
);
525 i2o_unlock_controller(c
);
527 if(kcmd
.qlen
) kfree(query
);
531 i2o_unlock_controller(c
);
533 len
= strnlen(res
, 65536);
534 put_user(len
, kcmd
.reslen
);
537 if(copy_to_user(kcmd
.resbuf
, res
, len
))
547 int ioctl_swdl(unsigned long arg
)
549 struct i2o_sw_xfer kxfer
;
550 struct i2o_sw_xfer
*pxfer
= (struct i2o_sw_xfer
*)arg
;
551 unsigned char maxfrag
= 0, curfrag
= 1;
552 unsigned char *buffer
;
554 unsigned int status
= 0, swlen
= 0, fragsize
= 8192;
555 struct i2o_controller
*c
;
557 if(copy_from_user(&kxfer
, pxfer
, sizeof(struct i2o_sw_xfer
)))
560 if(get_user(swlen
, kxfer
.swlen
) < 0)
563 if(get_user(maxfrag
, kxfer
.maxfrag
) < 0)
566 if(get_user(curfrag
, kxfer
.curfrag
) < 0)
569 if(curfrag
==maxfrag
) fragsize
= swlen
-(maxfrag
-1)*8192;
571 if(!kxfer
.buf
|| !access_ok(VERIFY_READ
, kxfer
.buf
, fragsize
))
574 c
= i2o_find_controller(kxfer
.iop
);
578 buffer
=kmalloc(fragsize
, GFP_KERNEL
);
581 i2o_unlock_controller(c
);
584 __copy_from_user(buffer
, kxfer
.buf
, fragsize
);
586 msg
[0]= NINE_WORD_MSG_SIZE
| SGL_OFFSET_7
;
587 msg
[1]= I2O_CMD_SW_DOWNLOAD
<<24 | HOST_TID
<<12 | ADAPTER_TID
;
588 msg
[2]= (u32
)cfg_handler
.context
;
590 msg
[4]= (((u32
)kxfer
.flags
)<<24) | (((u32
)kxfer
.sw_type
)<<16) |
591 (((u32
)maxfrag
)<<8) | (((u32
)curfrag
));
594 msg
[7]= (0xD0000000 | fragsize
);
595 msg
[8]= virt_to_bus(buffer
);
597 // printk("i2o_config: swdl frag %d/%d (size %d)\n", curfrag, maxfrag, fragsize);
598 status
= i2o_post_wait(c
, msg
, sizeof(msg
), 60);
600 i2o_unlock_controller(c
);
603 if (status
!= I2O_POST_WAIT_OK
)
605 // it fails if you try and send frags out of order
606 // and for some yet unknown reasons too
607 printk(KERN_INFO
"i2o_config: swdl failed, DetailedStatus = %d\n", status
);
614 int ioctl_swul(unsigned long arg
)
616 struct i2o_sw_xfer kxfer
;
617 struct i2o_sw_xfer
*pxfer
= (struct i2o_sw_xfer
*)arg
;
618 unsigned char maxfrag
= 0, curfrag
= 1;
619 unsigned char *buffer
;
621 unsigned int status
= 0, swlen
= 0, fragsize
= 8192;
622 struct i2o_controller
*c
;
624 if(copy_from_user(&kxfer
, pxfer
, sizeof(struct i2o_sw_xfer
)))
627 if(get_user(swlen
, kxfer
.swlen
) < 0)
630 if(get_user(maxfrag
, kxfer
.maxfrag
) < 0)
633 if(get_user(curfrag
, kxfer
.curfrag
) < 0)
636 if(curfrag
==maxfrag
) fragsize
= swlen
-(maxfrag
-1)*8192;
638 if(!kxfer
.buf
|| !access_ok(VERIFY_WRITE
, kxfer
.buf
, fragsize
))
641 c
= i2o_find_controller(kxfer
.iop
);
645 buffer
=kmalloc(fragsize
, GFP_KERNEL
);
648 i2o_unlock_controller(c
);
652 msg
[0]= NINE_WORD_MSG_SIZE
| SGL_OFFSET_7
;
653 msg
[1]= I2O_CMD_SW_UPLOAD
<<24 | HOST_TID
<<12 | ADAPTER_TID
;
654 msg
[2]= (u32
)cfg_handler
.context
;
656 msg
[4]= (u32
)kxfer
.flags
<<24|(u32
)kxfer
.sw_type
<<16|(u32
)maxfrag
<<8|(u32
)curfrag
;
659 msg
[7]= (0xD0000000 | fragsize
);
660 msg
[8]= virt_to_bus(buffer
);
662 // printk("i2o_config: swul frag %d/%d (size %d)\n", curfrag, maxfrag, fragsize);
663 status
= i2o_post_wait(c
, msg
, sizeof(msg
), 60);
664 i2o_unlock_controller(c
);
666 if (status
!= I2O_POST_WAIT_OK
)
669 printk(KERN_INFO
"i2o_config: swul failed, DetailedStatus = %d\n", status
);
673 __copy_to_user(kxfer
.buf
, buffer
, fragsize
);
679 int ioctl_swdel(unsigned long arg
)
681 struct i2o_controller
*c
;
682 struct i2o_sw_xfer kxfer
, *pxfer
= (struct i2o_sw_xfer
*)arg
;
687 if (copy_from_user(&kxfer
, pxfer
, sizeof(struct i2o_sw_xfer
)))
690 if (get_user(swlen
, kxfer
.swlen
) < 0)
693 c
= i2o_find_controller(kxfer
.iop
);
697 msg
[0] = SEVEN_WORD_MSG_SIZE
| SGL_OFFSET_0
;
698 msg
[1] = I2O_CMD_SW_REMOVE
<<24 | HOST_TID
<<12 | ADAPTER_TID
;
699 msg
[2] = (u32
)i2o_cfg_context
;
701 msg
[4] = (u32
)kxfer
.flags
<<24 | (u32
)kxfer
.sw_type
<<16;
703 msg
[6] = kxfer
.sw_id
;
705 token
= i2o_post_wait(c
, msg
, sizeof(msg
), 10);
706 i2o_unlock_controller(c
);
708 if (token
!= I2O_POST_WAIT_OK
)
710 printk(KERN_INFO
"i2o_config: swdel failed, DetailedStatus = %d\n", token
);
717 int ioctl_validate(unsigned long arg
)
722 struct i2o_controller
*c
;
724 c
=i2o_find_controller(iop
);
728 msg
[0] = FOUR_WORD_MSG_SIZE
|SGL_OFFSET_0
;
729 msg
[1] = I2O_CMD_CONFIG_VALIDATE
<<24 | HOST_TID
<<12 | iop
;
730 msg
[2] = (u32
)i2o_cfg_context
;
733 token
= i2o_post_wait(c
, msg
, sizeof(msg
), 10);
734 i2o_unlock_controller(c
);
736 if (token
!= I2O_POST_WAIT_OK
)
738 printk(KERN_INFO
"Can't validate configuration, ErrorStatus = %d\n",
746 static int ioctl_evt_reg(unsigned long arg
, struct file
*fp
)
749 struct i2o_evt_id
*pdesc
= (struct i2o_evt_id
*)arg
;
750 struct i2o_evt_id kdesc
;
751 struct i2o_controller
*iop
;
752 struct i2o_device
*d
;
754 if (copy_from_user(&kdesc
, pdesc
, sizeof(struct i2o_evt_id
)))
758 iop
= i2o_find_controller(kdesc
.iop
);
761 i2o_unlock_controller(iop
);
764 for(d
= iop
->devices
; d
; d
= d
->next
)
765 if(d
->lct_data
.tid
== kdesc
.tid
)
771 msg
[0] = FOUR_WORD_MSG_SIZE
|SGL_OFFSET_0
;
772 msg
[1] = I2O_CMD_UTIL_EVT_REGISTER
<<24 | HOST_TID
<<12 | kdesc
.tid
;
773 msg
[2] = (u32
)i2o_cfg_context
;
774 msg
[3] = (u32
)fp
->private_data
;
775 msg
[4] = kdesc
.evt_mask
;
777 i2o_post_this(iop
, msg
, 20);
782 static int ioctl_evt_get(unsigned long arg
, struct file
*fp
)
784 u32 id
= (u32
)fp
->private_data
;
785 struct i2o_cfg_info
*p
= NULL
;
786 struct i2o_evt_get
*uget
= (struct i2o_evt_get
*)arg
;
787 struct i2o_evt_get kget
;
790 // access_ok doesn't check for NULL?!?!
794 if(!access_ok(VERIFY_WRITE
, uget
, sizeof(struct i2o_evt_get
)))
797 for(p
= open_files
; p
; p
= p
->next
)
807 memcpy(&kget
.info
, &p
->event_q
[p
->q_out
], sizeof(struct i2o_evt_info
));
808 MODINC(p
->q_out
, I2O_EVT_Q_LEN
);
809 spin_lock_irqsave(&i2o_config_lock
, flags
);
811 kget
.pending
= p
->q_len
;
812 kget
.lost
= p
->q_lost
;
813 spin_unlock_irqrestore(&i2o_config_lock
, flags
);
815 __copy_to_user(uget
, &kget
, sizeof(struct i2o_evt_get
));
820 static int cfg_open(struct inode
*inode
, struct file
*file
)
822 struct i2o_cfg_info
*tmp
=
823 (struct i2o_cfg_info
*)kmalloc(sizeof(struct i2o_cfg_info
), GFP_KERNEL
);
829 file
->private_data
= (void*)(i2o_cfg_info_id
++);
832 tmp
->q_id
= (u32
)file
->private_data
;
837 tmp
->next
= open_files
;
839 spin_lock_irqsave(&i2o_config_lock
, flags
);
841 spin_unlock_irqrestore(&i2o_config_lock
, flags
);
846 static int cfg_release(struct inode
*inode
, struct file
*file
)
848 u32 id
= (u32
)file
->private_data
;
849 struct i2o_cfg_info
*p1
, *p2
;
855 spin_lock_irqsave(&i2o_config_lock
, flags
);
856 for(p1
= open_files
; p1
; )
862 cfg_fasync(-1, file
, 0);
866 open_files
= p1
->next
;
874 spin_unlock_irqrestore(&i2o_config_lock
, flags
);
880 static int cfg_fasync(int fd
, struct file
*fp
, int on
)
882 u32 id
= (u32
)fp
->private_data
;
883 struct i2o_cfg_info
*p
;
885 for(p
= open_files
; p
; p
= p
->next
)
892 return fasync_helper(fd
, fp
, on
, &p
->fasync
);
895 static struct file_operations config_fops
=
903 release
: cfg_release
,
907 static struct miscdevice i2o_miscdev
= {
914 int init_module(void)
916 int __init
i2o_config_init(void)
919 printk(KERN_INFO
"I2O configuration manager v 0.04.\n");
920 printk(KERN_INFO
" (C) Copyright 1999 Red Hat Software\n");
922 if((page_buf
= kmalloc(4096, GFP_KERNEL
))==NULL
)
924 printk(KERN_ERR
"i2o_config: no memory for page buffer.\n");
927 if(misc_register(&i2o_miscdev
)==-1)
929 printk(KERN_ERR
"i2o_config: can't register device.\n");
934 * Install our handler
936 if(i2o_install_handler(&cfg_handler
)<0)
939 printk(KERN_ERR
"i2o_config: handler register failed.\n");
940 misc_deregister(&i2o_miscdev
);
944 * The low 16bits of the transaction context must match this
945 * for everything we post. Otherwise someone else gets our mail
947 i2o_cfg_context
= cfg_handler
.context
;
953 void cleanup_module(void)
955 misc_deregister(&i2o_miscdev
);
959 if(i2o_cfg_context
!= -1)
960 i2o_remove_handler(&cfg_handler
);
966 MODULE_AUTHOR("Red Hat Software");
967 MODULE_DESCRIPTION("I2O Configuration");