Skip to contentSkip to conversation

another I2O patch to fix 64-bit systems on 2.6.x kernel

PATCH Markus Lidel 1 participant 1 message Apr 26, 2004 SCSI

lore
Share & tools
lore
#0 lore raw

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 */