Index: include/linux/i2o.h =================================================================== --- include/linux/i2o.h (revision 111) +++ include/linux/i2o.h (revision 114) @@ -18,7 +18,7 @@ #ifndef _I2O_H #define _I2O_H -#ifdef __KERNEL__ /* This file to be included by kernel only */ +#ifdef __KERNEL__ /* This file to be included by kernel only */ #include @@ -30,28 +30,25 @@ #include #include - /* message queue empty */ #define I2O_QUEUE_EMPTY 0xffffffff - /* * Message structures */ -struct i2o_message -{ +struct i2o_message { union { struct { - u8 version_offset; - u8 flags; - u16 size; - u32 target_tid:12; - u32 init_tid:12; - u32 function:8; - u32 icntxt; /* initiator context */ - u32 tcntxt; /* transaction context */ + u8 version_offset; + u8 flags; + u16 size; + u32 target_tid:12; + u32 init_tid:12; + u32 function:8; + u32 icntxt; /* initiator context */ + u32 tcntxt; /* transaction context */ } s; - u32 head[4]; + u32 head[4]; } u; /* List follows */ u32 body[0]; @@ -60,16 +57,15 @@ /* * Each I2O device entity has one of these. There is one per device. */ -struct i2o_device -{ - i2o_lct_entry lct_data; /* Device LCT information */ +struct i2o_device { + i2o_lct_entry lct_data; /* Device LCT information */ struct i2o_controller *iop; /* Controlling IOP */ - struct list_head list; /* node in IOP devices list */ + struct list_head list; /* node in IOP devices list */ struct device device; - struct semaphore lock; /* device lock */ + struct semaphore lock; /* device lock */ struct class_device classdev; /* i2o device class */ }; @@ -81,11 +77,11 @@ struct work_struct work; struct i2o_device *i2o_dev; /* I2O device pointer from which the event reply was initiated */ - u16 size; /* Size of data in 32-bit words */ - u32 tcntxt; /* Transaction context used at - registration */ - u32 event_indicator; /* Event indicator from reply */ - u32 data[0]; /* Event data from reply */ + u16 size; /* Size of data in 32-bit words */ + u32 tcntxt; /* Transaction context used at + registration */ + u32 event_indicator; /* Event indicator from reply */ + u32 data[0]; /* Event data from reply */ }; /* @@ -99,20 +95,26 @@ * I2O driver structure for OSMs */ struct i2o_driver { - char *name; /* OSM name */ - int context; /* Low 8 bits of the transaction info */ + char *name; /* OSM name */ + int context; /* Low 8 bits of the transaction info */ struct i2o_class_id *classes; /* I2O classes that this OSM handles */ /* Message reply handler */ - int (*reply)(struct i2o_controller *, u32, struct i2o_message *); + int (*reply) (struct i2o_controller *, u32, struct i2o_message *); /* Event handler */ - void (*event)(struct i2o_event *); + void (*event) (struct i2o_event *); struct workqueue_struct *event_queue; /* Event queue */ struct device_driver driver; + /* notification of changes */ + void (*notify_controller_add) (struct i2o_controller *); + void (*notify_controller_remove) (struct i2o_controller *); + void (*notify_device_add) (struct i2o_device *); + void (*notify_device_remove) (struct i2o_device *); + struct semaphore lock; }; @@ -138,69 +140,68 @@ /* * Each I2O controller has one of these objects */ -struct i2o_controller -{ +struct i2o_controller { char name[16]; int unit; int type; - struct pci_dev *pdev; /* PCI device */ + struct pci_dev *pdev; /* PCI device */ - int short_req:1; /* use small block sizes */ - int no_quiesce:1; /* dont quiesce before reset */ - int raptor:1; /* split bar */ - int promise:1; /* Promise controller */ + int short_req:1; /* use small block sizes */ + int no_quiesce:1; /* dont quiesce before reset */ + int raptor:1; /* split bar */ + int promise:1; /* Promise controller */ #ifdef CONFIG_MTRR - int mtrr_reg0; - int mtrr_reg1; + int mtrr_reg0; + int mtrr_reg1; #endif - struct list_head devices; /* list of I2O devices */ + struct list_head devices; /* list of I2O devices */ struct notifier_block *event_notifer; /* Events */ atomic_t users; - struct list_head list; /* Controller list */ - void *post_port; /* Inbout port address */ - void *reply_port; /* Outbound port address */ - void *irq_mask; /* Interrupt register address */ + struct list_head list; /* Controller list */ + void *post_port; /* Inbout port address */ + void *reply_port; /* Outbound port address */ + void *irq_mask; /* Interrupt register address */ /* Dynamic LCT related data */ - struct i2o_dma status; /* status of IOP */ + struct i2o_dma status; /* status of IOP */ - struct i2o_dma hrt; /* HW Resource Table */ - i2o_lct *lct; /* Logical Config Table */ - struct i2o_dma dlct; /* Temp LCT */ + struct i2o_dma hrt; /* HW Resource Table */ + i2o_lct *lct; /* Logical Config Table */ + struct i2o_dma dlct; /* Temp LCT */ struct semaphore lct_lock; /* Lock for LCT updates */ struct i2o_dma status_block; /* IOP status block */ - - struct i2o_dma base; /* controller messaging unit */ + struct i2o_dma base; /* controller messaging unit */ struct i2o_dma in_queue; /* inbound message queue Host->IOP */ struct i2o_dma out_queue; /* outbound message queue IOP->Host */ - int battery:1; /* Has a battery backup */ - int io_alloc:1; /* An I/O resource was allocated */ - int mem_alloc:1; /* A memory resource was allocated */ + int battery:1; /* Has a battery backup */ + int io_alloc:1; /* An I/O resource was allocated */ + int mem_alloc:1; /* A memory resource was allocated */ - struct resource io_resource; /* I/O resource allocated to the IOP */ - struct resource mem_resource; /* Mem resource allocated to the IOP */ + struct resource io_resource; /* I/O resource allocated to the IOP */ + struct resource mem_resource; /* Mem resource allocated to the IOP */ struct proc_dir_entry *proc_entry; /* /proc dir */ - - struct list_head bus_list; /* list of busses on IOP */ + struct list_head bus_list; /* list of busses on IOP */ struct device device; - struct i2o_device *exec; /* Executive */ + struct i2o_device *exec; /* Executive */ #if BITS_PER_LONG == 64 - spinlock_t context_list_lock; /* lock for context_list */ - atomic_t context_list_counter; /* needed for unique contexts */ - struct list_head context_list; /* list of context id's - and pointers */ + spinlock_t context_list_lock; /* lock for context_list */ + atomic_t context_list_counter; /* needed for unique contexts */ + struct list_head context_list; /* list of context id's + and pointers */ #endif - spinlock_t lock; /* lock for controller - configuration */ + spinlock_t lock; /* lock for controller + configuration */ + + void *driver_data[I2O_MAX_DRIVERS]; /* storage for drivers */ }; /* @@ -210,49 +211,47 @@ * system. It is sent to all IOPs so that they can create peer2peer * connections between them. */ -struct i2o_sys_tbl_entry -{ - u16 org_id; - u16 reserved1; - u32 iop_id:12; - u32 reserved2:20; - u16 seg_num:12; - u16 i2o_version:4; - u8 iop_state; - u8 msg_type; - u16 frame_size; - u16 reserved3; - u32 last_changed; - u32 iop_capabilities; - u32 inbound_low; - u32 inbound_high; +struct i2o_sys_tbl_entry { + u16 org_id; + u16 reserved1; + u32 iop_id:12; + u32 reserved2:20; + u16 seg_num:12; + u16 i2o_version:4; + u8 iop_state; + u8 msg_type; + u16 frame_size; + u16 reserved3; + u32 last_changed; + u32 iop_capabilities; + u32 inbound_low; + u32 inbound_high; }; -struct i2o_sys_tbl -{ - u8 num_entries; - u8 version; - u16 reserved1; - u32 change_ind; - u32 reserved2; - u32 reserved3; +struct i2o_sys_tbl { + u8 num_entries; + u8 version; + u16 reserved1; + u32 change_ind; + u32 reserved2; + u32 reserved3; struct i2o_sys_tbl_entry iops[0]; }; extern struct list_head i2o_controllers; - /* Message functions */ static inline u32 i2o_msg_get(struct i2o_controller *, struct i2o_message **); -extern u32 i2o_msg_get_wait(struct i2o_controller *, struct i2o_message **,int); +extern u32 i2o_msg_get_wait(struct i2o_controller *, struct i2o_message **, + int); static inline void i2o_msg_post(struct i2o_controller *, u32); -static inline int i2o_msg_post_wait(struct i2o_controller *,u32,unsigned long); +static inline int i2o_msg_post_wait(struct i2o_controller *, u32, + unsigned long); extern int i2o_msg_post_wait_mem(struct i2o_controller *, u32, unsigned long, struct i2o_dma *); extern void i2o_msg_nop(struct i2o_controller *, u32); static inline void i2o_flush_reply(struct i2o_controller *, u32); - /* DMA handling functions */ static inline int i2o_dma_alloc(struct device *, struct i2o_dma *, size_t, unsigned int); @@ -266,7 +265,8 @@ extern int i2o_status_get(struct i2o_controller *); extern int i2o_hrt_get(struct i2o_controller *); -extern int i2o_event_register(struct i2o_device *, struct i2o_driver *,int,u32); +extern int i2o_event_register(struct i2o_device *, struct i2o_driver *, int, + u32); extern struct i2o_device *i2o_iop_find_device(struct i2o_controller *, u16); extern struct i2o_controller *i2o_find_iop(int); @@ -275,20 +275,21 @@ extern u32 i2o_cntxt_list_add(struct i2o_controller *, void *); extern void *i2o_cntxt_list_get(struct i2o_controller *, u32); extern u32 i2o_cntxt_list_remove(struct i2o_controller *, void *); +extern u32 i2o_cntxt_list_get_ptr(struct i2o_controller *, void *); static inline u32 i2o_ptr_low(void *ptr) { - return (u32)(u64)ptr; + return (u32) (u64) ptr; }; static inline u32 i2o_ptr_high(void *ptr) { - return (u32)((u64)ptr>>32); + return (u32) ((u64) ptr >> 32); }; #else static inline u32 i2o_cntxt_list_add(struct i2o_controller *c, void *ptr) { - return (u32)ptr; + return (u32) ptr; }; static inline void *i2o_cntxt_list_get(struct i2o_controller *c, u32 context) @@ -298,12 +299,17 @@ static inline u32 i2o_cntxt_list_remove(struct i2o_controller *c, void *ptr) { - return (u32)ptr; + return (u32) ptr; }; +static inline u32 i2o_cntxt_list_get_ptr(struct i2o_controller *c, void *ptr) +{ + return (u32) ptr; +}; + static inline u32 i2o_ptr_low(void *ptr) { - return (u32)ptr; + return (u32) ptr; }; static inline u32 i2o_ptr_high(void *ptr) @@ -316,6 +322,63 @@ extern int i2o_driver_register(struct i2o_driver *); extern void i2o_driver_unregister(struct i2o_driver *); +/** + * i2o_driver_notify_controller_add - Send notification of added controller + * to a single I2O driver + * + * Send notification of added controller to a single registered driver. + */ +static inline void i2o_driver_notify_controller_add(struct i2o_driver *drv, + struct i2o_controller *c) +{ + if (drv->notify_controller_add) + drv->notify_controller_add(c); +}; + +/** + * i2o_driver_notify_controller_remove - Send notification of removed + * controller to a single I2O driver + * + * Send notification of removed controller to a single registered driver. + */ +static inline void i2o_driver_notify_controller_remove(struct i2o_driver *drv, + struct i2o_controller *c) +{ + if (drv->notify_controller_remove) + drv->notify_controller_remove(c); +}; + +/** + * i2o_driver_notify_device_add - Send notification of added device to a + * single I2O driver + * + * Send notification of added device to a single registered driver. + */ +static inline void i2o_driver_notify_device_add(struct i2o_driver *drv, + struct i2o_device *i2o_dev) +{ + if (drv->notify_device_add) + drv->notify_device_add(i2o_dev); +}; + +/** + * i2o_driver_notify_device_remove - Send notification of removed device + * to a single I2O driver + * + * Send notification of removed device to a single registered driver. + */ +static inline void i2o_driver_notify_device_remove(struct i2o_driver *drv, + struct i2o_device *i2o_dev) +{ + if (drv->notify_device_remove) + drv->notify_device_remove(i2o_dev); +}; + +extern void i2o_driver_notify_controller_add_all(struct i2o_controller *); +extern void i2o_driver_notify_controller_remove_all(struct i2o_controller *); +extern void i2o_driver_notify_device_add_all(struct i2o_device *); +extern void i2o_driver_notify_device_remove_all(struct i2o_device *); + /* I2O device functions */ extern int i2o_device_claim(struct i2o_device *); extern int i2o_device_claim_release(struct i2o_device *); @@ -328,7 +391,6 @@ #define to_i2o_driver(drv) container_of(drv,struct i2o_driver, driver) #define to_i2o_device(dev) container_of(dev, struct i2o_device, device) - /* * Messenger inlines */ @@ -344,7 +406,6 @@ writel(val, c->post_port); }; - static inline u32 I2O_REPLY_READ32(struct i2o_controller *c) { rmb(); @@ -357,7 +418,6 @@ writel(val, c->reply_port); }; - static inline u32 I2O_IRQ_READ32(struct i2o_controller *c) { rmb(); @@ -384,11 +444,12 @@ * address from the read port (see the i2o spec). If no message is * available returns I2O_QUEUE_EMPTY and msg is leaved untouched. */ -static inline u32 i2o_msg_get(struct i2o_controller *c,struct i2o_message **msg) +static inline u32 i2o_msg_get(struct i2o_controller *c, + struct i2o_message **msg) { u32 m; - if((m=I2O_POST_READ32(c))!=I2O_QUEUE_EMPTY) + if ((m = I2O_POST_READ32(c)) != I2O_QUEUE_EMPTY) *msg = c->in_queue.virt + m; return m; @@ -455,7 +516,7 @@ size_t len, unsigned int gfp_mask) { addr->virt = dma_alloc_coherent(dev, len, &addr->phys, gfp_mask); - if(!addr->virt) + if (!addr->virt) return -ENOMEM; memset(addr->virt, 0, len); @@ -473,9 +534,10 @@ */ static inline void i2o_dma_free(struct device *dev, struct i2o_dma *addr) { - if(addr->virt) { - if(addr->phys) - dma_free_coherent(dev, addr->len,addr->virt,addr->phys); + if (addr->virt) { + if (addr->phys) + dma_free_coherent(dev, addr->len, addr->virt, + addr->phys); else kfree(addr->virt); addr->virt = NULL; @@ -494,14 +556,14 @@ */ static inline int i2o_dma_map(struct device *dev, struct i2o_dma *addr) { - if(!addr->virt) + if (!addr->virt) return -EFAULT; - if(!addr->phys) + if (!addr->phys) addr->phys = dma_map_single(dev, addr->virt, addr->len, DMA_BIDIRECTIONAL); - if(!addr->phys) - return -ENOMEM; + if (!addr->phys) + return -ENOMEM; return 0; }; @@ -515,16 +577,15 @@ */ static inline void i2o_dma_unmap(struct device *dev, struct i2o_dma *addr) { - if(!addr->virt) + if (!addr->virt) return; - if(addr->phys) { + if (addr->phys) { dma_unmap_single(dev, addr->phys, addr->len, DMA_BIDIRECTIONAL); addr->phys = 0; } }; - /* * Endian handling wrapped into the macro - keeps the core code * cleaner. @@ -532,7 +593,6 @@ #define i2o_raw_writel(val, mem) __raw_writel(cpu_to_le32(val), mem) - extern int i2o_parm_field_get(struct i2o_device *, int, int, void *, int); extern int i2o_parm_field_set(struct i2o_device *, int, int, void *, int); extern int i2o_parm_table_get(struct i2o_device *, int, int, int, void *, int, @@ -547,19 +607,16 @@ void *, int); */ - /* debugging functions */ extern void i2o_report_status(const char *, const char *, struct i2o_message *); extern void i2o_dump_message(struct i2o_message *); extern void i2o_dump_hrt(struct i2o_controller *c); extern void i2o_debug_state(struct i2o_controller *c); - /* * Cache strategies */ - /* The NULL strategy leaves everything up to the controller. This tends to be a * pessimal but functional choice. */ @@ -600,13 +657,11 @@ * Ioctl structures */ - #define BLKI2OGRSTRAT _IOR('2', 1, int) #define BLKI2OGWSTRAT _IOR('2', 2, int) #define BLKI2OSRSTRAT _IOW('2', 3, int) #define BLKI2OSWSTRAT _IOW('2', 4, int) - /* * I2O Function codes */ @@ -843,7 +898,6 @@ #define TRL_SINGLE_VARIABLE_LENGTH 0x40 #define TRL_MULTIPLE_FIXED_LENGTH 0x80 - /* msg header defines for MsgFlags */ #define MSG_STATIC 0x0100 #define MSG_64BIT_CNTXT 0x0200 @@ -864,7 +918,6 @@ #define ELEVEN_WORD_MSG_SIZE 0x000B0000 #define I2O_MESSAGE_SIZE(x) ((x)<<16) - /* Special TID Assignments */ #define ADAPTER_TID 0 @@ -890,6 +943,7 @@ #define I2O_TIMEOUT_RESET 30 #define I2O_TIMEOUT_STATUS_GET 5 #define I2O_TIMEOUT_LCT_GET 20 +#define I2O_TIMEOUT_SCSI_SCB_ABORT 240 /* retries */ #define I2O_HRT_GET_TRIES 3 @@ -901,5 +955,5 @@ #define I2O_REQ_MEMPOOL_SIZE 32 -#endif /* __KERNEL__ */ -#endif /* _I2O_H */ +#endif /* __KERNEL__ */ +#endif /* _I2O_H */ Index: include/linux/i2o-dev.h =================================================================== --- include/linux/i2o-dev.h (revision 111) +++ include/linux/i2o-dev.h (revision 114) @@ -44,27 +44,23 @@ #define I2OPASSTHRU _IOR(I2O_MAGIC_NUMBER,12,struct i2o_cmd_passthru) #define I2OPASSTHRU32 _IOR(I2O_MAGIC_NUMBER,12,struct i2o_cmd_passthru32) -struct i2o_cmd_passthru32 -{ +struct i2o_cmd_passthru32 { unsigned int iop; /* IOP unit number */ u32 msg; /* message */ }; -struct i2o_cmd_passthru -{ +struct i2o_cmd_passthru { unsigned int iop; /* IOP unit number */ - void __user *msg; /* message */ + void __user *msg; /* message */ }; -struct i2o_cmd_hrtlct -{ - unsigned int iop; /* IOP unit number */ - void __user *resbuf; /* Buffer for result */ +struct i2o_cmd_hrtlct { + unsigned int iop; /* IOP unit number */ + void __user *resbuf; /* Buffer for result */ unsigned int __user *reslen; /* Buffer length in bytes */ }; -struct i2o_cmd_psetget -{ +struct i2o_cmd_psetget { unsigned int iop; /* IOP unit number */ unsigned int tid; /* Target device TID */ void __user *opbuf; /* Operation List buffer */ @@ -73,8 +69,7 @@ unsigned int __user *reslen; /* Result List buffer length in bytes */ }; -struct i2o_sw_xfer -{ +struct i2o_sw_xfer { unsigned int iop; /* IOP unit number */ unsigned char flags; /* Flags field */ unsigned char sw_type; /* Software type */ @@ -85,21 +80,19 @@ unsigned int __user *curfrag; /* Current fragment count */ }; -struct i2o_html -{ +struct i2o_html { unsigned int iop; /* IOP unit number */ unsigned int tid; /* Target device ID */ unsigned int page; /* HTML page */ - void __user *resbuf; /* Buffer for reply HTML page */ + void __user *resbuf; /* Buffer for reply HTML page */ unsigned int __user *reslen; /* Length in bytes of reply buffer */ - void __user *qbuf; /* Pointer to HTTP query string */ + void __user *qbuf; /* Pointer to HTTP query string */ unsigned int qlen; /* Length in bytes of query string buffer */ }; #define I2O_EVT_Q_LEN 32 -struct i2o_evt_id -{ +struct i2o_evt_id { unsigned int iop; unsigned int tid; unsigned int evt_mask; @@ -108,21 +101,18 @@ /* Event data size = frame size - message header + evt indicator */ #define I2O_EVT_DATA_SIZE 88 -struct i2o_evt_info -{ +struct i2o_evt_info { struct i2o_evt_id id; unsigned char evt_data[I2O_EVT_DATA_SIZE]; unsigned int data_size; }; -struct i2o_evt_get -{ +struct i2o_evt_get { struct i2o_evt_info info; int pending; int lost; }; - /************************************************************************** * HRT related constants and structures **************************************************************************/ @@ -142,139 +132,127 @@ typedef unsigned short u16; typedef unsigned int u32; -#endif /* __KERNEL__ */ +#endif /* __KERNEL__ */ -typedef struct _i2o_pci_bus -{ - u8 PciFunctionNumber; - u8 PciDeviceNumber; - u8 PciBusNumber; - u8 reserved; - u16 PciVendorID; - u16 PciDeviceID; +typedef struct _i2o_pci_bus { + u8 PciFunctionNumber; + u8 PciDeviceNumber; + u8 PciBusNumber; + u8 reserved; + u16 PciVendorID; + u16 PciDeviceID; } i2o_pci_bus; -typedef struct _i2o_local_bus -{ - u16 LbBaseIOPort; - u16 reserved; - u32 LbBaseMemoryAddress; +typedef struct _i2o_local_bus { + u16 LbBaseIOPort; + u16 reserved; + u32 LbBaseMemoryAddress; } i2o_local_bus; -typedef struct _i2o_isa_bus -{ - u16 IsaBaseIOPort; - u8 CSN; - u8 reserved; - u32 IsaBaseMemoryAddress; +typedef struct _i2o_isa_bus { + u16 IsaBaseIOPort; + u8 CSN; + u8 reserved; + u32 IsaBaseMemoryAddress; } i2o_isa_bus; -typedef struct _i2o_eisa_bus_info -{ - u16 EisaBaseIOPort; - u8 reserved; - u8 EisaSlotNumber; - u32 EisaBaseMemoryAddress; +typedef struct _i2o_eisa_bus_info { + u16 EisaBaseIOPort; + u8 reserved; + u8 EisaSlotNumber; + u32 EisaBaseMemoryAddress; } i2o_eisa_bus; -typedef struct _i2o_mca_bus -{ - u16 McaBaseIOPort; - u8 reserved; - u8 McaSlotNumber; - u32 McaBaseMemoryAddress; +typedef struct _i2o_mca_bus { + u16 McaBaseIOPort; + u8 reserved; + u8 McaSlotNumber; + u32 McaBaseMemoryAddress; } i2o_mca_bus; -typedef struct _i2o_other_bus -{ +typedef struct _i2o_other_bus { u16 BaseIOPort; u16 reserved; u32 BaseMemoryAddress; } i2o_other_bus; -typedef struct _i2o_hrt_entry -{ - u32 adapter_id; - u32 parent_tid:12; - u32 state:4; - u32 bus_num:8; - u32 bus_type:8; - union - { - i2o_pci_bus pci_bus; - i2o_local_bus local_bus; - i2o_isa_bus isa_bus; - i2o_eisa_bus eisa_bus; - i2o_mca_bus mca_bus; - i2o_other_bus other_bus; +typedef struct _i2o_hrt_entry { + u32 adapter_id; + u32 parent_tid:12; + u32 state:4; + u32 bus_num:8; + u32 bus_type:8; + union { + i2o_pci_bus pci_bus; + i2o_local_bus local_bus; + i2o_isa_bus isa_bus; + i2o_eisa_bus eisa_bus; + i2o_mca_bus mca_bus; + i2o_other_bus other_bus; } bus; } i2o_hrt_entry; -typedef struct _i2o_hrt -{ - u16 num_entries; - u8 entry_len; - u8 hrt_version; - u32 change_ind; +typedef struct _i2o_hrt { + u16 num_entries; + u8 entry_len; + u8 hrt_version; + u32 change_ind; i2o_hrt_entry hrt_entry[1]; } i2o_hrt; -typedef struct _i2o_lct_entry -{ - u32 entry_size:16; - u32 tid:12; - u32 reserved:4; - u32 change_ind; - u32 device_flags; - u32 class_id:12; - u32 version:4; - u32 vendor_id:16; - u32 sub_class; - u32 user_tid:12; - u32 parent_tid:12; - u32 bios_info:8; - u8 identity_tag[8]; - u32 event_capabilities; +typedef struct _i2o_lct_entry { + u32 entry_size:16; + u32 tid:12; + u32 reserved:4; + u32 change_ind; + u32 device_flags; + u32 class_id:12; + u32 version:4; + u32 vendor_id:16; + u32 sub_class; + u32 user_tid:12; + u32 parent_tid:12; + u32 bios_info:8; + u8 identity_tag[8]; + u32 event_capabilities; } i2o_lct_entry; -typedef struct _i2o_lct -{ - u32 table_size:16; - u32 boot_tid:12; - u32 lct_ver:4; - u32 iop_flags; - u32 change_ind; +typedef struct _i2o_lct { + u32 table_size:16; + u32 boot_tid:12; + u32 lct_ver:4; + u32 iop_flags; + u32 change_ind; i2o_lct_entry lct_entry[1]; } i2o_lct; -typedef struct _i2o_status_block -{ - u16 org_id; - u16 reserved; - u16 iop_id:12; - u16 reserved1:4; - u16 host_unit_id; - u16 segment_number:12; - u16 i2o_version:4; - u8 iop_state; - u8 msg_type; - u16 inbound_frame_size; - u8 init_code; - u8 reserved2; - u32 max_inbound_frames; - u32 cur_inbound_frames; - u32 max_outbound_frames; - char product_id[24]; - u32 expected_lct_size; - u32 iop_capabilities; - u32 desired_mem_size; - u32 current_mem_size; - u32 current_mem_base; - u32 desired_io_size; - u32 current_io_size; - u32 current_io_base; - u32 reserved3:24; - u32 cmd_status:8; +typedef struct _i2o_status_block { + u16 org_id; + u16 reserved; + u16 iop_id:12; + u16 reserved1:4; + u16 host_unit_id; + u16 segment_number:12; + u16 i2o_version:4; + u8 iop_state; + u8 msg_type; + u16 inbound_frame_size; + u8 init_code; + u8 reserved2; + u32 max_inbound_frames; + u32 cur_inbound_frames; + u32 max_outbound_frames; + char product_id[24]; + u32 expected_lct_size; + u32 iop_capabilities; + u32 desired_mem_size; + u32 current_mem_size; + u32 current_mem_base; + u32 desired_io_size; + u32 current_io_size; + u32 current_io_base; + u32 reserved3:24; + u32 cmd_status:8; } i2o_status_block; /* Event indicator mask flags */ @@ -421,4 +399,4 @@ #define ADAPTER_STATE_FAILED 0x10 #define ADAPTER_STATE_FAULTED 0x11 -#endif /* _I2O_DEV_H */ +#endif /* _I2O_DEV_H */ Index: drivers/message/i2o/i2o_config.c =================================================================== --- drivers/message/i2o/i2o_config.c (revision 111) +++ drivers/message/i2o/i2o_config.c (revision 114) @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -646,9 +647,11 @@ cmd = (struct i2o_cmd_passthru32 __user *)arg; - if (get_user(iop, &cmd->iop) || get_user(user_msg, &cmd->msg)) + if (get_user(iop, &cmd->iop) || get_user(i, &cmd->msg)) return -EFAULT; + user_msg = compat_ptr(i); + c = i2o_find_iop(iop); if (!c) { pr_debug("controller %d not found\n", iop); Index: drivers/message/i2o/device.c =================================================================== --- drivers/message/i2o/device.c (revision 111) +++ drivers/message/i2o/device.c (revision 114) @@ -239,6 +239,8 @@ class_device_register(&dev->classdev); + i2o_driver_notify_device_add_all(dev); + pr_debug("I2O device %s added\n", dev->device.bus_id); return dev; @@ -254,6 +256,7 @@ */ void i2o_device_remove(struct i2o_device *i2o_dev) { + i2o_driver_notify_device_remove_all(i2o_dev); class_device_unregister(&i2o_dev->classdev); list_del(&i2o_dev->list); device_unregister(&i2o_dev->device); Index: drivers/message/i2o/iop.c =================================================================== --- drivers/message/i2o/iop.c (revision 111) +++ drivers/message/i2o/iop.c (revision 114) @@ -108,8 +108,8 @@ #if BITS_PER_LONG == 64 /** * i2o_cntxt_list_add - Append a pointer to context list and return a id + * @c: controller to which the context list belong * @ptr: pointer to add to the context list - * @c: controller to which the context list belong * * Because the context field in I2O is only 32-bit large, on 64-bit the * pointer is to large to fit in the context field. The i2o_cntxt_list @@ -117,7 +117,7 @@ * * Returns context id > 0 on success or 0 on failure. */ -u32 i2o_cntxt_list_add(struct i2o_controller * c, void *ptr) +u32 i2o_cntxt_list_add(struct i2o_controller *c, void *ptr) { struct i2o_context_list_element *entry; unsigned long flags; @@ -154,15 +154,15 @@ /** * i2o_cntxt_list_remove - Remove a pointer from the context list + * @c: controller to which the context list belong * @ptr: pointer which should be removed from the context list - * @c: controller to which the context list belong * * Removes a previously added pointer from the context list and returns * the matching context id. * * Returns context id on succes or 0 on failure. */ -u32 i2o_cntxt_list_remove(struct i2o_controller * c, void *ptr) +u32 i2o_cntxt_list_remove(struct i2o_controller *c, void *ptr) { struct i2o_context_list_element *entry; u32 context = 0; @@ -189,9 +189,11 @@ /** * i2o_cntxt_list_get - Get a pointer from the context list and remove it + * @c: controller to which the context list belong * @context: context id to which the pointer belong - * @c: controller to which the context list belong - * returns pointer to the matching context id + * + * Returns pointer to the matching context id on success or NULL on + * failure. */ void *i2o_cntxt_list_get(struct i2o_controller *c, u32 context) { @@ -216,6 +218,37 @@ return ptr; }; + +/** + * i2o_cntxt_list_get_ptr - Get a context id from the context list + * @c: controller to which the context list belong + * @ptr: pointer to which the context id should be fetched + * + * Returns context id which matches to the pointer on succes or 0 on + * failure. + */ +u32 i2o_cntxt_list_get_ptr(struct i2o_controller * c, void *ptr) +{ + struct i2o_context_list_element *entry; + u32 context = 0; + unsigned long flags; + + spin_lock_irqsave(&c->context_list_lock, flags); + list_for_each_entry(entry, &c->context_list, list) + if (entry->ptr == ptr) { + context = entry->context; + break; + } + spin_unlock_irqrestore(&c->context_list_lock, flags); + + if (!context) + printk(KERN_WARNING "i2o: Could not find nonexistent ptr " + "%p\n", ptr); + + pr_debug("get context id from context list %p -> %d\n", ptr, context); + + return context; +}; #endif /** @@ -782,6 +815,8 @@ pr_debug("Deleting controller %s\n", c->name); + i2o_driver_notify_controller_remove_all(c); + list_del(&c->list); list_for_each_entry_safe(dev, tmp, &c->devices, list) @@ -1098,6 +1133,8 @@ list_add(&c->list, &i2o_controllers); + i2o_driver_notify_controller_add_all(c); + printk(KERN_INFO "%s: Controller added\n", c->name); return 0; @@ -1209,6 +1246,7 @@ EXPORT_SYMBOL(i2o_cntxt_list_add); EXPORT_SYMBOL(i2o_cntxt_list_get); EXPORT_SYMBOL(i2o_cntxt_list_remove); +EXPORT_SYMBOL(i2o_cntxt_list_get_ptr); #endif EXPORT_SYMBOL(i2o_msg_get_wait); EXPORT_SYMBOL(i2o_msg_nop); Index: drivers/message/i2o/i2o_scsi.c =================================================================== --- drivers/message/i2o/i2o_scsi.c (revision 111) +++ drivers/message/i2o/i2o_scsi.c (revision 114) @@ -67,13 +67,12 @@ #define VERSION_STRING "Version 0.1.2" +static struct i2o_driver i2o_scsi_driver; + static int i2o_scsi_max_id = 16; static int i2o_scsi_max_lun = 8; -static LIST_HEAD(i2o_scsi_hosts); - struct i2o_scsi_host { - struct list_head list; /* node in in i2o_scsi_hosts */ struct Scsi_Host *scsi_host; /* pointer to the SCSI host */ struct i2o_controller *iop; /* pointer to the I2O controller */ struct i2o_device *channel[0]; /* channel->i2o_dev mapping table */ @@ -81,19 +80,6 @@ static struct scsi_host_template i2o_scsi_host_template; -/* - * This is only needed, because we can only set the hostdata after the device is - * added to the scsi core. So we need this little workaround. - */ -static DECLARE_MUTEX(i2o_scsi_probe_lock); -static struct i2o_device *i2o_scsi_probe_dev = NULL; - -static int i2o_scsi_slave_alloc(struct scsi_device *sdp) -{ - sdp->hostdata = i2o_scsi_probe_dev; - return 0; -}; - #define I2O_SCSI_CAN_QUEUE 4 /* SCSI OSM class handling definition */ @@ -169,37 +155,11 @@ * is returned, otherwise the I2O controller is added to the SCSI * core. * - * Returns pointer to the I2O SCSI host on success or negative error code - * on failure. + * Returns pointer to the I2O SCSI host on success or NULL on failure. */ static struct i2o_scsi_host *i2o_scsi_get_host(struct i2o_controller *c) { - struct i2o_scsi_host *i2o_shost; - int rc; - - /* skip if already registered as I2O SCSI host */ - list_for_each_entry(i2o_shost, &i2o_scsi_hosts, list) - if (i2o_shost->iop == c) - return i2o_shost; - - i2o_shost = i2o_scsi_host_alloc(c); - if (IS_ERR(i2o_shost)) { - printk(KERN_ERR "scsi-osm: Could not initialize SCSI host\n"); - return i2o_shost; - } - - rc = scsi_add_host(i2o_shost->scsi_host, &c->device); - if (rc) { - printk(KERN_ERR "scsi-osm: Could not add SCSI host\n"); - scsi_host_put(i2o_shost->scsi_host); - return ERR_PTR(rc); - } - - list_add(&i2o_shost->list, &i2o_scsi_hosts); - pr_debug("new I2O SCSI host added\n"); - - return i2o_shost; - + return c->driver_data[i2o_scsi_driver.context]; }; /** @@ -252,8 +212,8 @@ int i; i2o_shost = i2o_scsi_get_host(c); - if (IS_ERR(i2o_shost)) - return PTR_ERR(i2o_shost); + if (!i2o_shost) + return -EFAULT; scsi_host = i2o_shost->scsi_host; @@ -292,11 +252,8 @@ return -EFAULT; } - down_interruptible(&i2o_scsi_probe_lock); - i2o_scsi_probe_dev = i2o_dev; - scsi_dev = scsi_add_device(i2o_shost->scsi_host, channel, id, lun); - i2o_scsi_probe_dev = NULL; - up(&i2o_scsi_probe_lock); + scsi_dev = + __scsi_add_device(i2o_shost->scsi_host, channel, id, lun, i2o_dev); if (!scsi_dev) { printk(KERN_WARNING "scsi-osm: can not add SCSI device " @@ -536,13 +493,70 @@ cmd->request_bufflen, cmd->sc_data_direction); return 1; -} +}; +/** + * i2o_scsi_notify_controller_add - Retrieve notifications of added + * controllers + * @c: the controller which was added + * + * If a I2O controller is added, we catch the notification to add a + * corresponding Scsi_Host. + */ +void i2o_scsi_notify_controller_add(struct i2o_controller *c) +{ + struct i2o_scsi_host *i2o_shost; + int rc; + + i2o_shost = i2o_scsi_host_alloc(c); + if (IS_ERR(i2o_shost)) { + printk(KERN_ERR "scsi-osm: Could not initialize" + " SCSI host\n"); + return; + } + + rc = scsi_add_host(i2o_shost->scsi_host, &c->device); + if (rc) { + printk(KERN_ERR "scsi-osm: Could not add SCSI " + "host\n"); + scsi_host_put(i2o_shost->scsi_host); + return; + } + + c->driver_data[i2o_scsi_driver.context] = i2o_shost; + + pr_debug("new I2O SCSI host added\n"); +}; + +/** + * i2o_scsi_notify_controller_remove - Retrieve notifications of removed + * controllers + * @c: the controller which was removed + * + * If a I2O controller is removed, we catch the notification to remove the + * corresponding Scsi_Host. + */ +void i2o_scsi_notify_controller_remove(struct i2o_controller *c) +{ + struct i2o_scsi_host *i2o_shost; + i2o_shost = i2o_scsi_get_host(c); + if (!i2o_shost) + return; + + c->driver_data[i2o_scsi_driver.context] = NULL; + + scsi_remove_host(i2o_shost->scsi_host); + scsi_host_put(i2o_shost->scsi_host); + pr_debug("I2O SCSI host removed\n"); +}; + /* SCSI OSM driver struct */ static struct i2o_driver i2o_scsi_driver = { .name = "scsi-osm", .reply = i2o_scsi_reply, .classes = i2o_scsi_class_id, + .notify_controller_add = i2o_scsi_notify_controller_add, + .notify_controller_remove = i2o_scsi_notify_controller_remove, .driver = { .probe = i2o_scsi_probe, .remove = i2o_scsi_remove, @@ -736,54 +750,47 @@ return 0; }; -#if 0 -FIXME /** - * i2o_scsi_abort - abort a running command + * i2o_scsi_abort - abort a running command * @SCpnt: command to abort * * Ask the I2O controller to abort a command. This is an asynchrnous - * process and our callback handler will see the command complete - * with an aborted message if it succeeds. + * process and our callback handler will see the command complete with an + * aborted message if it succeeds. * - * Locks: no locks are held or needed + * Returns 0 if the command is successfully aborted or negative error code + * on failure. */ int i2o_scsi_abort(struct scsi_cmnd *SCpnt) { + struct i2o_device *i2o_dev; struct i2o_controller *c; - struct Scsi_Host *host; - struct i2o_scsi_host *hostdata; - u32 msg[5]; + struct i2o_message *msg; + u32 m; int tid; int status = FAILED; printk(KERN_WARNING "i2o_scsi: Aborting command block.\n"); - host = SCpnt->device->host; - hostdata = (struct i2o_scsi_host *)host->hostdata; - tid = hostdata->task[SCpnt->device->id][SCpnt->device->lun]; - if (tid == -1) { - printk(KERN_ERR "i2o_scsi: Impossible command to abort!\n"); - return status; - } - c = hostdata->controller; + i2o_dev = SCpnt->device->hostdata; + c = i2o_dev->iop; + tid = i2o_dev->lct_data.tid; - spin_unlock_irq(host->host_lock); + m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); + if (m == I2O_QUEUE_EMPTY) + return SCSI_MLQUEUE_HOST_BUSY; - msg[0] = FIVE_WORD_MSG_SIZE; - msg[1] = I2O_CMD_SCSI_ABORT << 24 | HOST_TID << 12 | tid; - msg[2] = scsi_context; - msg[3] = 0; - msg[4] = i2o_context_list_remove(SCpnt, c); - if (i2o_post_wait(c, msg, sizeof(msg), 240)) + writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); + writel(I2O_CMD_SCSI_ABORT << 24 | HOST_TID << 12 | tid, + &msg->u.head[1]); + writel(i2o_cntxt_list_get_ptr(c, SCpnt), &msg->body[0]); + + if (i2o_msg_post_wait(c, m, I2O_TIMEOUT_SCSI_SCB_ABORT)) status = SUCCESS; - spin_lock_irq(host->host_lock); return status; } -#endif - /** * i2o_scsi_bios_param - Invent disk geometry * @sdev: scsi device @@ -817,15 +824,12 @@ .name = "I2O SCSI Peripheral OSM", .info = i2o_scsi_info, .queuecommand = i2o_scsi_queuecommand, -/* - .eh_abort_handler = i2o_scsi_abort, -*/ + .eh_abort_handler = i2o_scsi_abort, .bios_param = i2o_scsi_bios_param, .can_queue = I2O_SCSI_CAN_QUEUE, .sg_tablesize = 8, .cmd_per_lun = 6, .use_clustering = ENABLE_CLUSTERING, - .slave_alloc = i2o_scsi_slave_alloc, }; /* @@ -867,14 +871,6 @@ */ static void __exit i2o_scsi_exit(void) { - struct i2o_scsi_host *i2o_shost, *tmp; - - /* Remove I2O SCSI hosts */ - list_for_each_entry_safe(i2o_shost, tmp, &i2o_scsi_hosts, list) { - scsi_remove_host(i2o_shost->scsi_host); - scsi_host_put(i2o_shost->scsi_host); - } - /* Unregister I2O SCSI OSM from I2O core */ i2o_driver_unregister(&i2o_scsi_driver); }; Index: drivers/message/i2o/driver.c =================================================================== --- drivers/message/i2o/driver.c (revision 111) +++ drivers/message/i2o/driver.c (revision 114) @@ -72,6 +72,7 @@ */ int i2o_driver_register(struct i2o_driver *drv) { + struct i2o_controller *c; int i; int rc = 0; unsigned long flags; @@ -108,7 +109,16 @@ spin_unlock_irqrestore(&i2o_drivers_lock, flags); pr_debug("driver %s gets context id %d\n", drv->name, drv->context); + + list_for_each_entry(c, &i2o_controllers, list) { + struct i2o_device *i2o_dev; + i2o_driver_notify_controller_add(drv, c); + list_for_each_entry(i2o_dev, &c->devices, list) + i2o_driver_notify_device_add(drv, i2o_dev); + } + + rc = driver_register(&drv->driver); if (rc) destroy_workqueue(drv->event_queue); @@ -125,12 +135,22 @@ */ void i2o_driver_unregister(struct i2o_driver *drv) { + struct i2o_controller *c; unsigned long flags; pr_debug("unregister driver %s\n", drv->name); driver_unregister(&drv->driver); + list_for_each_entry(c, &i2o_controllers, list) { + struct i2o_device *i2o_dev; + + list_for_each_entry(i2o_dev, &c->devices, list) + i2o_driver_notify_device_remove(drv, i2o_dev); + + i2o_driver_notify_controller_remove(drv, c); + } + spin_lock_irqsave(&i2o_drivers_lock, flags); i2o_drivers[drv->context] = NULL; spin_unlock_irqrestore(&i2o_drivers_lock, flags); @@ -220,6 +240,80 @@ } /** + * i2o_driver_notify_controller_add_all - Send notify of added controller + * to all I2O drivers + * + * Send notifications to all registered drivers that a new controller was + * added. + */ +void i2o_driver_notify_controller_add_all(struct i2o_controller *c) { + int i; + struct i2o_driver *drv; + + for(i = 0; i < I2O_MAX_DRIVERS; i ++) { + drv = i2o_drivers[i]; + + if(drv) + i2o_driver_notify_controller_add(drv, c); + } +} + +/** + * i2o_driver_notify_controller_remove_all - Send notify of removed + * controller to all I2O drivers + * + * Send notifications to all registered drivers that a controller was + * removed. + */ +void i2o_driver_notify_controller_remove_all(struct i2o_controller *c) { + int i; + struct i2o_driver *drv; + + for(i = 0; i < I2O_MAX_DRIVERS; i ++) { + drv = i2o_drivers[i]; + + if(drv) + i2o_driver_notify_controller_remove(drv, c); + } +} + +/** + * i2o_driver_notify_device_add_all - Send notify of added device to all + * I2O drivers + * + * Send notifications to all registered drivers that a device was added. + */ +void i2o_driver_notify_device_add_all(struct i2o_device *i2o_dev) { + int i; + struct i2o_driver *drv; + + for(i = 0; i < I2O_MAX_DRIVERS; i ++) { + drv = i2o_drivers[i]; + + if(drv) + i2o_driver_notify_device_add(drv, i2o_dev); + } +} + +/** + * i2o_driver_notify_device_remove_all - Send notify of removed device to + * all I2O drivers + * + * Send notifications to all registered drivers that a device was removed. + */ +void i2o_driver_notify_device_remove_all(struct i2o_device *i2o_dev) { + int i; + struct i2o_driver *drv; + + for(i = 0; i < I2O_MAX_DRIVERS; i ++) { + drv = i2o_drivers[i]; + + if(drv) + i2o_driver_notify_device_remove(drv, i2o_dev); + } +} + +/** * i2o_driver_init - initialize I2O drivers (OSMs) * * Registers the I2O bus and allocate memory for the array of OSMs. @@ -267,3 +361,7 @@ EXPORT_SYMBOL(i2o_driver_register); EXPORT_SYMBOL(i2o_driver_unregister); +EXPORT_SYMBOL(i2o_driver_notify_controller_add_all); +EXPORT_SYMBOL(i2o_driver_notify_controller_remove_all); +EXPORT_SYMBOL(i2o_driver_notify_device_add_all); +EXPORT_SYMBOL(i2o_driver_notify_device_remove_all);