another I2O patch to fix 64-bit systems on 2.6.x kernel
Hello,
now i have a patch, which implements a mapping between 64-bit pointers and 32-bit context id fields. This function is used in i2o_scsi, which should work again on 64-bit system.
Could anybody tell when the I2O-patches will be integrated into the main kernel?
At the moment the following ones are still missing (which could all be downloaded at http://i2o.shadowconnect.com/):
i2o_block-cleanup.patch
i2o-64-bit-fix.patch
i2o-passthru.patch
i2o-config-clean.patch
Thank you very much.
Best regards,
Markus Lidel
------------------------------------------
Markus Lidel (Senior IT Consultant)
Shadow Connect GmbH
Carl-Reisch-Weg 12
D-86381 Krumbach
Germany
Phone: +49 82 82/99 51-0 Fax: +49 82 82/99 51-11
E-Mail: [email protected] URL: http://www.shadowconnect.com
drivers/message/i2o/i2o_core.c +136 -0
@@ -213,6 +213,135 @@static int verbose; +#if BITS_PER_LONG ==64 +/** +* i2o_context_list_add - append an ptr to the context list and return a +* matching context id. +* @ptr: pointer to add to the context list +* @c: controller to which the context list belong +* returns context id, which could be used in the transaction context +* field. +* +* 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_context_list +* functiones map pointers to context fields. +*/ +u32 i2o_context_list_add (void *ptr,struct i2o_controller *c) { +u32 context =1 ; +struct i2o_context_list_element **entry = &c->context_list; +struct i2o_context_list_element *element; +unsigned long flags; + +spin_lock_irqsave (&c->context_list_lock, flags); +while (*entry && ((*entry)->flags &I2O_CONTEXT_LIST_USED )) { +if ((*entry)->context >= context) + context = (*entry)->context +1 ; + entry = &((*entry)->next); + } + +if (!*entry) { +if (unlikely (!context)) { +spin_unlock_irqrestore (&c->context_list_lock, flags); +printk (KERN_EMERG "i2o_core: context list overflow\n" ); +return 0 ; + } + + element =kmalloc (sizeof (struct i2o_context_list_element ),GFP_KERNEL ); +if (!element) { +printk (KERN_EMERG "i2o_core: could not allocate memory for context list element\n" ); +return 0 ; + } + element->context = context; + element->next =NULL ; + *entry = element; + }else + element = *entry; + + element->ptr = ptr; + element->flags =I2O_CONTEXT_LIST_USED ; + +spin_unlock_irqrestore (&c->context_list_lock, flags); +dprintk (KERN_DEBUG "i2o_core: add context to list %p -> %d\n" , ptr, context); +return context; +} + +/** +* i2o_context_list_remove - remove a ptr from the context list and return +* the matching context id. +* @ptr: pointer to be removed from the context list +* @c: controller to which the context list belong +* returns context id, which could be used in the transaction context +* field. +*/ +u32 i2o_context_list_remove (void *ptr,struct i2o_controller *c) { +struct i2o_context_list_element **entry = &c->context_list; +struct i2o_context_list_element *element; +u32 context; +unsigned long flags; + +spin_lock_irqsave (&c->context_list_lock, flags); +while (*entry && ((*entry)->ptr != ptr)) + entry = &((*entry)->next); + +if (unlikely (!*entry)) { +spin_unlock_irqrestore (&c->context_list_lock, flags); +printk (KERN_WARNING "i2o_core: could not remove nonexistent ptr %p\n" , ptr); +return 0 ; + } + + element = *entry; + + context = element->context; + element->ptr =NULL ; + element->flags |=I2O_CONTEXT_LIST_DELETED ; + +spin_unlock_irqrestore (&c->context_list_lock, flags); +dprintk (KERN_DEBUG "i2o_core: markt as deleted in context list %p -> %d\n" , ptr, context); +return context; +} + +/** +* i2o_context_list_get - get a ptr from the context list and remove it +* from the list. +* @context: context id to which the pointer belong +* @c: controller to which the context list belong +* returns pointer to the matching context id +*/ +void *i2o_context_list_get (u32 context,struct i2o_controller *c) { +struct i2o_context_list_element **entry = &c->context_list; +struct i2o_context_list_element *element; +void *ptr; +int count =0 ; +unsigned long flags; + +spin_lock_irqsave (&c->context_list_lock, flags); +while (*entry && ((*entry)->context != context)) { + entry = &((*entry)->next); + count ++; + } + +if (unlikely (!*entry)) { +spin_unlock_irqrestore (&c->context_list_lock, flags); +printk (KERN_WARNING "i2o_core: context id %d not found\n" , context); +return NULL ; + } + + element = *entry; + ptr = element->ptr; +if (count >=I2O_CONTEXT_LIST_MIN_LENGTH ) { + *entry = (*entry)->next; +kfree (element); + }else { + element->ptr =NULL ; + element->flags &= !I2O_CONTEXT_LIST_USED ; + } + +spin_unlock_irqrestore (&c->context_list_lock, flags); +dprintk (KERN_DEBUG "i2o_core: get ptr from context list %d -> %p\n" , context, ptr); +return ptr; +} +#endif +/* * I2O Core reply handler */
@@ -3551,6 +3678,10 @@ c->short_req =0 ; c->pdev = dev; +#if BITS_PER_LONG ==64 + c->context_list_lock =SPIN_LOCK_UNLOCKED ; +#endif + c->irq_mask = mem+0x34 ; c->post_port = mem+0x40 ; c->reply_port = mem+0x44 ;
@@ -3788,3 +3919,6 @@EXPORT_SYMBOL (i2o_report_status);EXPORT_SYMBOL (i2o_dump_message);EXPORT_SYMBOL (i2o_get_class_name); +EXPORT_SYMBOL (i2o_context_list_add); +EXPORT_SYMBOL (i2o_context_list_get); +EXPORT_SYMBOL (i2o_context_list_remove);
drivers/message/i2o/i2o_scsi.c +21 -43
132 lines not on this page · raw message
include/linux/i2o.h +40 -0
@@ -76,6 +76,16 @@ };/* +* context queue entry, used for 32-bit context on 64-bit systems +*/ +struct i2o_context_list_element { +struct i2o_context_list_element *next; +u32 context; +void *ptr; +unsigned int flags; +}; + +/* * Each I2O controller has one of these objects */ struct i2o_controller
@@ -133,6 +143,11 @@void *page_frame;/* Message buffers */ dma_addr_t page_frame_map;/* Cache map */ +#if BITS_PER_LONG ==64 +spinlock_t context_list_lock;/* lock for context_list */ +struct i2o_context_list_element *context_list;/* list of context id's +and pointers */ +#endif };/*
@@ -322,6 +335,27 @@extern void i2o_run_queue (struct i2o_controller *);extern int i2o_delete_controller (struct i2o_controller *); +#if BITS_PER_LONG ==64 +extern u32 i2o_context_list_add (void *,struct i2o_controller *); +extern void *i2o_context_list_get (u32 ,struct i2o_controller *); +extern u32 i2o_context_list_remove (void *,struct i2o_controller *); +#else +static inline u32 i2o_context_list_add (void *ptr,struct i2o_controller *c) +{ +return (u32 )ptr; +} + +static inline void *i2o_context_list_get (u32 context,struct i2o_controller *c) +{ +return (void *)context; +} + +static inline u32 i2o_context_list_remove (void *ptr,struct i2o_controller *c) +{ +return (u32 )ptr; +} +#endif +/* * Cache strategies */
@@ -647,5 +683,9 @@#define I2O_POST_WAIT_OK 0#define I2O_POST_WAIT_TIMEOUT -ETIMEDOUT +#define I2O_CONTEXT_LIST_MIN_LENGTH 15 +#define I2O_CONTEXT_LIST_USED 0x01 +#define I2O_CONTEXT_LIST_DELETED 0x02 +#endif /* __KERNEL__ */ #endif /* _I2O_H */