Skip to content

Commit

Permalink
[PATCH] I2O: bugfixes and compability enhancements
Browse files Browse the repository at this point in the history
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: Markus Lidel <Markus.Lidel@shadowconnect.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
  • Loading branch information
Markus Lidel authored and Linus Torvalds committed Jun 24, 2005
1 parent 34d6e07 commit 61fbfa8
Show file tree
Hide file tree
Showing 8 changed files with 124 additions and 149 deletions.
10 changes: 6 additions & 4 deletions drivers/message/i2o/device.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");

Expand Down
89 changes: 44 additions & 45 deletions drivers/message/i2o/driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -182,62 +184,59 @@ 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)) {
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);
return -EIO;
}
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;
}

if ((readl(&msg->u.head[1]) >> 24) == I2O_CMD_UTIL_EVT_REGISTER) {
struct i2o_device *dev, *tmp;
struct i2o_event *evt;
u16 size;
u16 tid;
spin_lock(&i2o_drivers_lock);
drv = i2o_drivers[context];
spin_unlock(&i2o_drivers_lock);

tid = readl(&msg->u.head[1]) & 0x1fff;
if (unlikely(!drv)) {
osm_warn("Spurious reply to unknown driver %d\n", context);
return -EIO;
}

pr_debug("%s: event received from device %d\n", c->name,
tid);
if ((readl(&msg->u.head[1]) >> 24) == I2O_CMD_UTIL_EVT_REGISTER) {
struct i2o_device *dev, *tmp;
struct i2o_event *evt;
u16 size;
u16 tid = readl(&msg->u.head[1]) & 0xfff;

/* cut of header from message size (in 32-bit words) */
size = (readl(&msg->u.head[0]) >> 16) - 5;
osm_debug("event received from device %d\n", tid);

evt = kmalloc(size * 4 + sizeof(*evt), GFP_ATOMIC);
if (!evt)
return -ENOMEM;
memset(evt, 0, size * 4 + sizeof(*evt));
/* cut of header from message size (in 32-bit words) */
size = (readl(&msg->u.head[0]) >> 16) - 5;

evt->size = size;
memcpy_fromio(&evt->tcntxt, &msg->u.s.tcntxt,
(size + 2) * 4);
evt = kmalloc(size * 4 + sizeof(*evt), GFP_ATOMIC | __GFP_ZERO);
if (!evt)
return -ENOMEM;

list_for_each_entry_safe(dev, tmp, &c->devices, list)
if (dev->lct_data.tid == tid) {
evt->i2o_dev = dev;
break;
}
evt->size = size;
evt->tcntxt = readl(&msg->u.s.tcntxt);
evt->event_indicator = readl(&msg->body[0]);
memcpy_fromio(&evt->tcntxt, &msg->u.s.tcntxt, size * 4);

INIT_WORK(&evt->work, (void (*)(void *))drv->event,
evt);
queue_work(drv->event_queue, &evt->work);
return 1;
list_for_each_entry_safe(dev, tmp, &c->devices, list)
if (dev->lct_data.tid == tid) {
evt->i2o_dev = dev;
break;
}

if (likely(drv->reply))
return drv->reply(c, m, msg);
else
pr_debug("%s: Reply to driver %s, but no reply function"
" defined!\n", c->name, drv->name);
INIT_WORK(&evt->work, (void (*)(void *))drv->event, evt);
queue_work(drv->event_queue, &evt->work);
return 1;
}

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);
}

/**
Expand Down
9 changes: 4 additions & 5 deletions drivers/message/i2o/exec-osm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

/*
Expand Down Expand Up @@ -381,8 +379,9 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m,
*/
static void i2o_exec_event(struct i2o_event *evt)
{
osm_info("Event received from device: %d\n",
evt->i2o_dev->lct_data.tid);
if(likely(evt->i2o_dev))
osm_info("Event received from device: %d\n",
evt->i2o_dev->lct_data.tid);
kfree(evt);
};

Expand Down
48 changes: 29 additions & 19 deletions drivers/message/i2o/i2o_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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++) {
Expand All @@ -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,
Expand All @@ -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].
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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);
Expand All @@ -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;
}
}
}
Expand All @@ -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
Expand All @@ -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;
Expand Down Expand Up @@ -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++) {
Expand All @@ -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 */
Expand All @@ -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 */
Expand All @@ -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
Expand All @@ -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];
Expand All @@ -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);
Expand All @@ -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;
}
}
}
Expand All @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion drivers/message/i2o/i2o_scsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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++;
}

Expand Down
Loading

0 comments on commit 61fbfa8

Please sign in to comment.