Commit 61fbfa81 authored by Markus Lidel's avatar Markus Lidel Committed by Linus Torvalds
Browse files

[PATCH] I2O: bugfixes and compability enhancements



Changes:

 - Fixed sysfs bug where user and parent links where added to the I2O
   device itself
 - Fixed bug when calculating TID for the event handler and cleaned up the
   workflow of i2o_driver_dispatch()
 - Fixed oops when no I2O device could be found for an event delivered to
   Exec-OSM
 - Fixed initialization of spinlock in Exec-OSM
 - Fixed memory leak in i2o_cfg_passthru() and i2o_cfg_passthru()
 - Removed MTRR support
 - Added PCI ID of Promise SX6000 with firmware >= 1.20.x.x
 - Turn of caching for ioremapped memory of in_queue
 - Added initialization sequence for Promise controllers
 - Moved definition of u8 / u16 / u32 for raidutils before first use

Signed-off-by: default avatarMarkus Lidel <Markus.Lidel@shadowconnect.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 34d6e075
Loading
Loading
Loading
Loading
+6 −4
Original line number Diff line number Diff line
@@ -401,25 +401,27 @@ static int i2o_device_class_add(struct class_device *cd)

	/* create user entries for this device */
	tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.user_tid);
	if (tmp)
	if (tmp && (tmp != i2o_dev))
		sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj,
				  "user");

	/* create user entries refering to this device */
	list_for_each_entry(tmp, &c->devices, list)
	    if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid)
	    if ((tmp->lct_data.user_tid == i2o_dev->lct_data.tid)
		&& (tmp != i2o_dev))
		sysfs_create_link(&tmp->device.kobj,
				  &i2o_dev->device.kobj, "user");

	/* create parent entries for this device */
	tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.parent_tid);
	if (tmp)
	if (tmp && (tmp != i2o_dev))
		sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj,
				  "parent");

	/* create parent entries refering to this device */
	list_for_each_entry(tmp, &c->devices, list)
	    if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid)
	    if ((tmp->lct_data.parent_tid == i2o_dev->lct_data.tid)
		&& (tmp != i2o_dev))
		sysfs_create_link(&tmp->device.kobj,
				  &i2o_dev->device.kobj, "parent");

+44 −45
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@
#include <linux/rwsem.h>
#include <linux/i2o.h>

#define OSM_NAME	"core"

/* max_drivers - Maximum I2O drivers (OSMs) which could be registered */
unsigned int i2o_max_drivers = I2O_MAX_DRIVERS;
module_param_named(max_drivers, i2o_max_drivers, uint, 0);
@@ -182,14 +184,18 @@ int i2o_driver_dispatch(struct i2o_controller *c, u32 m,
	struct i2o_driver *drv;
	u32 context = readl(&msg->u.s.icntxt);

	if (likely(context < i2o_max_drivers)) {
	if (unlikely(context >= i2o_max_drivers)) {
		printk(KERN_WARNING "%s: Spurious reply to unknown driver "
		       "%d\n", c->name, readl(&msg->u.s.icntxt));
		return -EIO;
	}

	spin_lock(&i2o_drivers_lock);
	drv = i2o_drivers[context];
	spin_unlock(&i2o_drivers_lock);

	if (unlikely(!drv)) {
			printk(KERN_WARNING "%s: Spurious reply to unknown "
			       "driver %d\n", c->name, context);
		osm_warn("Spurious reply to unknown driver %d\n", context);
		return -EIO;
	}

@@ -197,24 +203,21 @@ int i2o_driver_dispatch(struct i2o_controller *c, u32 m,
		struct i2o_device *dev, *tmp;
		struct i2o_event *evt;
		u16 size;
			u16 tid;
		u16 tid = readl(&msg->u.head[1]) & 0xfff;

			tid = readl(&msg->u.head[1]) & 0x1fff;

			pr_debug("%s: event received from device %d\n", c->name,
				 tid);
		osm_debug("event received from device %d\n", tid);

		/* cut of header from message size (in 32-bit words) */
		size = (readl(&msg->u.head[0]) >> 16) - 5;

			evt = kmalloc(size * 4 + sizeof(*evt), GFP_ATOMIC);
		evt = kmalloc(size * 4 + sizeof(*evt), GFP_ATOMIC | __GFP_ZERO);
		if (!evt)
			return -ENOMEM;
			memset(evt, 0, size * 4 + sizeof(*evt));

		evt->size = size;
			memcpy_fromio(&evt->tcntxt, &msg->u.s.tcntxt,
				      (size + 2) * 4);
		evt->tcntxt = readl(&msg->u.s.tcntxt);
		evt->event_indicator = readl(&msg->body[0]);
		memcpy_fromio(&evt->tcntxt, &msg->u.s.tcntxt, size * 4);

		list_for_each_entry_safe(dev, tmp, &c->devices, list)
		    if (dev->lct_data.tid == tid) {
@@ -222,22 +225,18 @@ int i2o_driver_dispatch(struct i2o_controller *c, u32 m,
			break;
		}

			INIT_WORK(&evt->work, (void (*)(void *))drv->event,
				  evt);
		INIT_WORK(&evt->work, (void (*)(void *))drv->event, evt);
		queue_work(drv->event_queue, &evt->work);
		return 1;
	}

		if (likely(drv->reply))
			return drv->reply(c, m, msg);
		else
	if (unlikely(!drv->reply)) {
		pr_debug("%s: Reply to driver %s, but no reply function"
			 " defined!\n", c->name, drv->name);
		return -EIO;
	} else
		printk(KERN_WARNING "%s: Spurious reply to unknown driver "
		       "%d\n", c->name, readl(&msg->u.s.icntxt));
	return -EIO;
	}

	return drv->reply(c, m, msg);
}

/**
+4 −5
Original line number Diff line number Diff line
@@ -204,12 +204,10 @@ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m,
				      struct i2o_message __iomem *msg)
{
	struct i2o_exec_wait *wait, *tmp;
	static spinlock_t lock;
	static spinlock_t lock = SPIN_LOCK_UNLOCKED;
	int rc = 1;
	u32 context;

	spin_lock_init(&lock);

	context = readl(&msg->u.s.tcntxt);

	/*
@@ -381,6 +379,7 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m,
 */
static void i2o_exec_event(struct i2o_event *evt)
{
	if(likely(evt->i2o_dev))
		osm_info("Event received from device: %d\n",
			 evt->i2o_dev->lct_data.tid);
	kfree(evt);
+29 −19
Original line number Diff line number Diff line
@@ -555,6 +555,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar
	u32 sg_offset = 0;
	u32 sg_count = 0;
	u32 i = 0;
	u32 sg_index = 0;
	i2o_status_block *sb;
	struct i2o_message *msg;
	u32 m;
@@ -634,8 +635,8 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar
		if (sg_count > SG_TABLESIZE) {
			printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n",
			       c->name, sg_count);
			kfree(reply);
			return -EINVAL;
			rcode = -EINVAL;
			goto cleanup;
		}

		for (i = 0; i < sg_count; i++) {
@@ -651,7 +652,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar
				goto cleanup;
			}
			sg_size = sg[i].flag_count & 0xffffff;
			p = &(sg_list[i]);
			p = &(sg_list[sg_index++]);
			/* Allocate memory for the transfer */
			if (i2o_dma_alloc
			    (&c->pdev->dev, p, sg_size,
@@ -660,7 +661,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar
				       "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
				       c->name, sg_size, i, sg_count);
				rcode = -ENOMEM;
				goto cleanup;
				goto sg_list_cleanup;
			}
			/* Copy in the user's SG buffer if necessary */
			if (sg[i].
@@ -673,7 +674,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar
					       "%s: Could not copy SG buf %d FROM user\n",
					       c->name, i);
					rcode = -EFAULT;
					goto cleanup;
					goto sg_list_cleanup;
				}
			}
			//TODO 64bit fix
@@ -683,10 +684,10 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar

	rcode = i2o_msg_post_wait(c, m, 60);
	if (rcode)
		goto cleanup;
		goto sg_list_cleanup;

	if (sg_offset) {
		u32 msg[128];
		u32 msg[MSG_FRAME_SIZE];
		/* Copy back the Scatter Gather buffers back to user space */
		u32 j;
		// TODO 64bit fix
@@ -698,14 +699,14 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar
		// get user msg size in u32s
		if (get_user(size, &user_msg[0])) {
			rcode = -EFAULT;
			goto cleanup;
			goto sg_list_cleanup;
		}
		size = size >> 16;
		size *= 4;
		/* Copy in the user's I2O command */
		if (copy_from_user(msg, user_msg, size)) {
			rcode = -EFAULT;
			goto cleanup;
			goto sg_list_cleanup;
		}
		sg_count =
		    (size - sg_offset * 4) / sizeof(struct sg_simple_element);
@@ -727,7 +728,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar
					       c->name, sg_list[j].virt,
					       sg[j].addr_bus);
					rcode = -EFAULT;
					goto cleanup;
					goto sg_list_cleanup;
				}
			}
		}
@@ -741,6 +742,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar
			       "%s: Could not copy message context FROM user\n",
			       c->name);
			rcode = -EFAULT;
			goto sg_list_cleanup;
		}
		if (copy_to_user(user_reply, reply, reply_size)) {
			printk(KERN_WARNING
@@ -749,6 +751,10 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar
		}
	}

      sg_list_cleanup:
	for (i = 0; i < sg_index; i++)
		i2o_dma_free(&c->pdev->dev, &sg_list[i]);

      cleanup:
	kfree(reply);
	return rcode;
@@ -862,8 +868,8 @@ static int i2o_cfg_passthru(unsigned long arg)
		if (sg_count > SG_TABLESIZE) {
			printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n",
			       c->name, sg_count);
			kfree(reply);
			return -EINVAL;
			rcode = -EINVAL;
			goto cleanup;
		}

		for (i = 0; i < sg_count; i++) {
@@ -875,7 +881,7 @@ static int i2o_cfg_passthru(unsigned long arg)
				       "%s:Bad SG element %d - not simple (%x)\n",
				       c->name, i, sg[i].flag_count);
				rcode = -EINVAL;
				goto cleanup;
				goto sg_list_cleanup;
			}
			sg_size = sg[i].flag_count & 0xffffff;
			/* Allocate memory for the transfer */
@@ -885,7 +891,7 @@ static int i2o_cfg_passthru(unsigned long arg)
				       "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
				       c->name, sg_size, i, sg_count);
				rcode = -ENOMEM;
				goto cleanup;
				goto sg_list_cleanup;
			}
			sg_list[sg_index++] = p;	// sglist indexed with input frame, not our internal frame.
			/* Copy in the user's SG buffer if necessary */
@@ -899,7 +905,7 @@ static int i2o_cfg_passthru(unsigned long arg)
					       "%s: Could not copy SG buf %d FROM user\n",
					       c->name, i);
					rcode = -EFAULT;
					goto cleanup;
					goto sg_list_cleanup;
				}
			}
			//TODO 64bit fix
@@ -909,7 +915,7 @@ static int i2o_cfg_passthru(unsigned long arg)

	rcode = i2o_msg_post_wait(c, m, 60);
	if (rcode)
		goto cleanup;
		goto sg_list_cleanup;

	if (sg_offset) {
		u32 msg[128];
@@ -924,14 +930,14 @@ static int i2o_cfg_passthru(unsigned long arg)
		// get user msg size in u32s
		if (get_user(size, &user_msg[0])) {
			rcode = -EFAULT;
			goto cleanup;
			goto sg_list_cleanup;
		}
		size = size >> 16;
		size *= 4;
		/* Copy in the user's I2O command */
		if (copy_from_user(msg, user_msg, size)) {
			rcode = -EFAULT;
			goto cleanup;
			goto sg_list_cleanup;
		}
		sg_count =
		    (size - sg_offset * 4) / sizeof(struct sg_simple_element);
@@ -953,7 +959,7 @@ static int i2o_cfg_passthru(unsigned long arg)
					       c->name, sg_list[j],
					       sg[j].addr_bus);
					rcode = -EFAULT;
					goto cleanup;
					goto sg_list_cleanup;
				}
			}
		}
@@ -975,6 +981,10 @@ static int i2o_cfg_passthru(unsigned long arg)
		}
	}

      sg_list_cleanup:
	for (i = 0; i < sg_index; i++)
		kfree(sg_list[i]);

      cleanup:
	kfree(reply);
	return rcode;
+2 −1
Original line number Diff line number Diff line
@@ -103,7 +103,8 @@ static struct i2o_scsi_host *i2o_scsi_host_alloc(struct i2o_controller *c)

	list_for_each_entry(i2o_dev, &c->devices, list)
	    if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER_PORT) {
		if (i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1) || (type == 1))	/* SCSI bus */
		if (i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1)
		   && (type == 0x01))	/* SCSI bus */
			max_channel++;
	}

Loading