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

[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
...@@ -401,25 +401,27 @@ static int i2o_device_class_add(struct class_device *cd) ...@@ -401,25 +401,27 @@ static int i2o_device_class_add(struct class_device *cd)
/* create user entries for this device */ /* create user entries for this device */
tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.user_tid); 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, sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj,
"user"); "user");
/* create user entries refering to this device */ /* create user entries refering to this device */
list_for_each_entry(tmp, &c->devices, list) 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, sysfs_create_link(&tmp->device.kobj,
&i2o_dev->device.kobj, "user"); &i2o_dev->device.kobj, "user");
/* create parent entries for this device */ /* create parent entries for this device */
tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.parent_tid); 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, sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj,
"parent"); "parent");
/* create parent entries refering to this device */ /* create parent entries refering to this device */
list_for_each_entry(tmp, &c->devices, list) 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, sysfs_create_link(&tmp->device.kobj,
&i2o_dev->device.kobj, "parent"); &i2o_dev->device.kobj, "parent");
......
...@@ -18,6 +18,8 @@ ...@@ -18,6 +18,8 @@
#include <linux/rwsem.h> #include <linux/rwsem.h>
#include <linux/i2o.h> #include <linux/i2o.h>
#define OSM_NAME "core"
/* max_drivers - Maximum I2O drivers (OSMs) which could be registered */ /* max_drivers - Maximum I2O drivers (OSMs) which could be registered */
unsigned int i2o_max_drivers = I2O_MAX_DRIVERS; unsigned int i2o_max_drivers = I2O_MAX_DRIVERS;
module_param_named(max_drivers, i2o_max_drivers, uint, 0); module_param_named(max_drivers, i2o_max_drivers, uint, 0);
...@@ -182,62 +184,59 @@ int i2o_driver_dispatch(struct i2o_controller *c, u32 m, ...@@ -182,62 +184,59 @@ int i2o_driver_dispatch(struct i2o_controller *c, u32 m,
struct i2o_driver *drv; struct i2o_driver *drv;
u32 context = readl(&msg->u.s.icntxt); u32 context = readl(&msg->u.s.icntxt);
if (likely(context < i2o_max_drivers)) { if (unlikely(context >= i2o_max_drivers)) {
spin_lock(&i2o_drivers_lock); printk(KERN_WARNING "%s: Spurious reply to unknown driver "
drv = i2o_drivers[context]; "%d\n", c->name, readl(&msg->u.s.icntxt));
spin_unlock(&i2o_drivers_lock); return -EIO;
}
if (unlikely(!drv)) {
printk(KERN_WARNING "%s: Spurious reply to unknown "
"driver %d\n", c->name, context);
return -EIO;
}
if ((readl(&msg->u.head[1]) >> 24) == I2O_CMD_UTIL_EVT_REGISTER) { spin_lock(&i2o_drivers_lock);
struct i2o_device *dev, *tmp; drv = i2o_drivers[context];
struct i2o_event *evt; spin_unlock(&i2o_drivers_lock);
u16 size;
u16 tid;
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, if ((readl(&msg->u.head[1]) >> 24) == I2O_CMD_UTIL_EVT_REGISTER) {
tid); 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) */ osm_debug("event received from device %d\n", tid);
size = (readl(&msg->u.head[0]) >> 16) - 5;
evt = kmalloc(size * 4 + sizeof(*evt), GFP_ATOMIC); /* cut of header from message size (in 32-bit words) */
if (!evt) size = (readl(&msg->u.head[0]) >> 16) - 5;
return -ENOMEM;
memset(evt, 0, size * 4 + sizeof(*evt));
evt->size = size; evt = kmalloc(size * 4 + sizeof(*evt), GFP_ATOMIC | __GFP_ZERO);
memcpy_fromio(&evt->tcntxt, &msg->u.s.tcntxt, if (!evt)
(size + 2) * 4); return -ENOMEM;
list_for_each_entry_safe(dev, tmp, &c->devices, list) evt->size = size;
if (dev->lct_data.tid == tid) { evt->tcntxt = readl(&msg->u.s.tcntxt);
evt->i2o_dev = dev; evt->event_indicator = readl(&msg->body[0]);
break; memcpy_fromio(&evt->tcntxt, &msg->u.s.tcntxt, size * 4);
}
INIT_WORK(&evt->work, (void (*)(void *))drv->event, list_for_each_entry_safe(dev, tmp, &c->devices, list)
evt); if (dev->lct_data.tid == tid) {
queue_work(drv->event_queue, &evt->work); evt->i2o_dev = dev;
return 1; break;
} }
if (likely(drv->reply)) INIT_WORK(&evt->work, (void (*)(void *))drv->event, evt);
return drv->reply(c, m, msg); queue_work(drv->event_queue, &evt->work);
else return 1;
pr_debug("%s: Reply to driver %s, but no reply function" }
" defined!\n", c->name, drv->name);
if (unlikely(!drv->reply)) {
pr_debug("%s: Reply to driver %s, but no reply function"
" defined!\n", c->name, drv->name);
return -EIO; return -EIO;
} else }
printk(KERN_WARNING "%s: Spurious reply to unknown driver "
"%d\n", c->name, readl(&msg->u.s.icntxt)); return drv->reply(c, m, msg);
return -EIO;
} }
/** /**
......
...@@ -204,12 +204,10 @@ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m, ...@@ -204,12 +204,10 @@ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m,
struct i2o_message __iomem *msg) struct i2o_message __iomem *msg)
{ {
struct i2o_exec_wait *wait, *tmp; struct i2o_exec_wait *wait, *tmp;
static spinlock_t lock; static spinlock_t lock = SPIN_LOCK_UNLOCKED;
int rc = 1; int rc = 1;
u32 context; u32 context;
spin_lock_init(&lock);
context = readl(&msg->u.s.tcntxt); context = readl(&msg->u.s.tcntxt);
/* /*
...@@ -381,8 +379,9 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m, ...@@ -381,8 +379,9 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m,
*/ */
static void i2o_exec_event(struct i2o_event *evt) static void i2o_exec_event(struct i2o_event *evt)
{ {
osm_info("Event received from device: %d\n", if(likely(evt->i2o_dev))
evt->i2o_dev->lct_data.tid); osm_info("Event received from device: %d\n",
evt->i2o_dev->lct_data.tid);
kfree(evt); kfree(evt);
}; };
......
...@@ -555,6 +555,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar ...@@ -555,6 +555,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar
u32 sg_offset = 0; u32 sg_offset = 0;
u32 sg_count = 0; u32 sg_count = 0;
u32 i = 0; u32 i = 0;
u32 sg_index = 0;
i2o_status_block *sb; i2o_status_block *sb;
struct i2o_message *msg; struct i2o_message *msg;
u32 m; u32 m;
...@@ -634,8 +635,8 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar ...@@ -634,8 +635,8 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar
if (sg_count > SG_TABLESIZE) { if (sg_count > SG_TABLESIZE) {
printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n", printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n",
c->name, sg_count); c->name, sg_count);
kfree(reply); rcode = -EINVAL;
return -EINVAL; goto cleanup;
} }
for (i = 0; i < sg_count; i++) { for (i = 0; i < sg_count; i++) {
...@@ -651,7 +652,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar ...@@ -651,7 +652,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar
goto cleanup; goto cleanup;
} }
sg_size = sg[i].flag_count & 0xffffff; sg_size = sg[i].flag_count & 0xffffff;
p = &(sg_list[i]); p = &(sg_list[sg_index++]);
/* Allocate memory for the transfer */ /* Allocate memory for the transfer */
if (i2o_dma_alloc if (i2o_dma_alloc
(&c->pdev->dev, p, sg_size, (&c->pdev->dev, p, sg_size,
...@@ -660,7 +661,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar ...@@ -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", "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
c->name, sg_size, i, sg_count); c->name, sg_size, i, sg_count);
rcode = -ENOMEM; rcode = -ENOMEM;
goto cleanup; goto sg_list_cleanup;
} }
/* Copy in the user's SG buffer if necessary */ /* Copy in the user's SG buffer if necessary */
if (sg[i]. if (sg[i].
...@@ -673,7 +674,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar ...@@ -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", "%s: Could not copy SG buf %d FROM user\n",
c->name, i); c->name, i);
rcode = -EFAULT; rcode = -EFAULT;
goto cleanup; goto sg_list_cleanup;
} }
} }
//TODO 64bit fix //TODO 64bit fix
...@@ -683,10 +684,10 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar ...@@ -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); rcode = i2o_msg_post_wait(c, m, 60);
if (rcode) if (rcode)
goto cleanup; goto sg_list_cleanup;
if (sg_offset) { if (sg_offset) {
u32 msg[128]; u32 msg[MSG_FRAME_SIZE];
/* Copy back the Scatter Gather buffers back to user space */ /* Copy back the Scatter Gather buffers back to user space */
u32 j; u32 j;
// TODO 64bit fix // TODO 64bit fix
...@@ -698,14 +699,14 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar ...@@ -698,14 +699,14 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar
// get user msg size in u32s // get user msg size in u32s
if (get_user(size, &user_msg[0])) { if (get_user(size, &user_msg[0])) {
rcode = -EFAULT; rcode = -EFAULT;
goto cleanup; goto sg_list_cleanup;
} }
size = size >> 16; size = size >> 16;
size *= 4; size *= 4;
/* Copy in the user's I2O command */ /* Copy in the user's I2O command */
if (copy_from_user(msg, user_msg, size)) { if (copy_from_user(msg, user_msg, size)) {
rcode = -EFAULT; rcode = -EFAULT;
goto cleanup; goto sg_list_cleanup;
} }
sg_count = sg_count =
(size - sg_offset * 4) / sizeof(struct sg_simple_element); (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 ...@@ -727,7 +728,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar
c->name, sg_list[j].virt, c->name, sg_list[j].virt,
sg[j].addr_bus); sg[j].addr_bus);
rcode = -EFAULT; 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 ...@@ -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", "%s: Could not copy message context FROM user\n",
c->name); c->name);
rcode = -EFAULT; rcode = -EFAULT;
goto sg_list_cleanup;
} }
if (copy_to_user(user_reply, reply, reply_size)) { if (copy_to_user(user_reply, reply, reply_size)) {
printk(KERN_WARNING printk(KERN_WARNING
...@@ -749,6 +751,10 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar ...@@ -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: cleanup:
kfree(reply); kfree(reply);
return rcode; return rcode;
...@@ -862,8 +868,8 @@ static int i2o_cfg_passthru(unsigned long arg) ...@@ -862,8 +868,8 @@ static int i2o_cfg_passthru(unsigned long arg)
if (sg_count > SG_TABLESIZE) { if (sg_count > SG_TABLESIZE) {
printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n", printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n",
c->name, sg_count); c->name, sg_count);
kfree(reply); rcode = -EINVAL;
return -EINVAL; goto cleanup;
} }
for (i = 0; i < sg_count; i++) { for (i = 0; i < sg_count; i++) {
...@@ -875,7 +881,7 @@ static int i2o_cfg_passthru(unsigned long arg) ...@@ -875,7 +881,7 @@ static int i2o_cfg_passthru(unsigned long arg)
"%s:Bad SG element %d - not simple (%x)\n", "%s:Bad SG element %d - not simple (%x)\n",
c->name, i, sg[i].flag_count); c->name, i, sg[i].flag_count);
rcode = -EINVAL; rcode = -EINVAL;
goto cleanup; goto sg_list_cleanup;
} }
sg_size = sg[i].flag_count & 0xffffff; sg_size = sg[i].flag_count & 0xffffff;
/* Allocate memory for the transfer */ /* Allocate memory for the transfer */
...@@ -885,7 +891,7 @@ static int i2o_cfg_passthru(unsigned long arg) ...@@ -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", "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
c->name, sg_size, i, sg_count); c->name, sg_size, i, sg_count);
rcode = -ENOMEM; rcode = -ENOMEM;
goto cleanup; goto sg_list_cleanup;
} }
sg_list[sg_index++] = p; // sglist indexed with input frame, not our internal frame. sg_list[sg_index++] = p; // sglist indexed with input frame, not our internal frame.
/* Copy in the user's SG buffer if necessary */ /* Copy in the user's SG buffer if necessary */
...@@ -899,7 +905,7 @@ static int i2o_cfg_passthru(unsigned long arg) ...@@ -899,7 +905,7 @@ static int i2o_cfg_passthru(unsigned long arg)
"%s: Could not copy SG buf %d FROM user\n", "%s: Could not copy SG buf %d FROM user\n",
c->name, i); c->name, i);
rcode = -EFAULT; rcode = -EFAULT;
goto cleanup; goto sg_list_cleanup;
} }
} }
//TODO 64bit fix //TODO 64bit fix
...@@ -909,7 +915,7 @@ static int i2o_cfg_passthru(unsigned long arg) ...@@ -909,7 +915,7 @@ static int i2o_cfg_passthru(unsigned long arg)
rcode = i2o_msg_post_wait(c, m, 60); rcode = i2o_msg_post_wait(c, m, 60);
if (rcode) if (rcode)
goto cleanup; goto sg_list_cleanup;
if (sg_offset) { if (sg_offset) {
u32 msg[128]; u32 msg[128];
...@@ -924,14 +930,14 @@ static int i2o_cfg_passthru(unsigned long arg) ...@@ -924,14 +930,14 @@ static int i2o_cfg_passthru(unsigned long arg)
// get user msg size in u32s // get user msg size in u32s
if (get_user(size, &user_msg[0])) { if (get_user(size, &user_msg[0])) {
rcode = -EFAULT; rcode = -EFAULT;
goto cleanup; goto sg_list_cleanup;
} }
size = size >> 16; size = size >> 16;
size *= 4; size *= 4;
/* Copy in the user's I2O command */ /* Copy in the user's I2O command */
if (copy_from_user(msg, user_msg, size)) { if (copy_from_user(msg, user_msg, size)) {
rcode = -EFAULT; rcode = -EFAULT;
goto cleanup; goto sg_list_cleanup;
} }
sg_count = sg_count =
(size - sg_offset * 4) / sizeof(struct sg_simple_element); (size - sg_offset * 4) / sizeof(struct sg_simple_element);
...@@ -953,7 +959,7 @@ static int i2o_cfg_passthru(unsigned long arg) ...@@ -953,7 +959,7 @@ static int i2o_cfg_passthru(unsigned long arg)
c->name, sg_list[j], c->name, sg_list[j],
sg[j].addr_bus); sg[j].addr_bus);
rcode = -EFAULT; rcode = -EFAULT;
goto cleanup; goto sg_list_cleanup;
} }
} }
} }
...@@ -975,6 +981,10 @@ static int i2o_cfg_passthru(unsigned long arg) ...@@ -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: cleanup:
kfree(reply); kfree(reply);
return rcode; return rcode;
......
...@@ -103,7 +103,8 @@ static struct i2o_scsi_host *i2o_scsi_host_alloc(struct i2o_controller *c) ...@@ -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) list_for_each_entry(i2o_dev, &c->devices, list)
if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER_PORT) { 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++; max_channel++;
} }
......
...@@ -31,10 +31,6 @@ ...@@ -31,10 +31,6 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/i2o.h> #include <linux/i2o.h>
#ifdef CONFIG_MTRR
#include <asm/mtrr.h>
#endif // CONFIG_MTRR
/* Module internal functions from other sources */ /* Module internal functions from other sources */
extern struct i2o_controller *i2o_iop_alloc(void); extern struct i2o_controller *i2o_iop_alloc(void);
extern void i2o_iop_free(struct i2o_controller *); extern void i2o_iop_free(struct i2o_controller *);
...@@ -49,6 +45,8 @@ extern int i2o_driver_dispatch(struct i2o_controller *, u32, ...@@ -49,6 +45,8 @@ extern int i2o_driver_dispatch(struct i2o_controller *, u32,
static struct pci_device_id __devinitdata i2o_pci_ids[] = { static struct pci_device_id __devinitdata i2o_pci_ids[] = {
{PCI_DEVICE_CLASS(PCI_CLASS_INTELLIGENT_I2O << 8, 0xffff00)}, {PCI_DEVICE_CLASS(PCI_CLASS_INTELLIGENT_I2O << 8, 0xffff00)},
{PCI_DEVICE(PCI_VENDOR_ID_DPT, 0xa511)}, {PCI_DEVICE(PCI_VENDOR_ID_DPT, 0xa511)},
{.vendor = PCI_VENDOR_ID_INTEL,.device = 0x1962,
.subvendor = PCI_VENDOR_ID_PROMISE,.subdevice = PCI_ANY_ID},
{0} {0}
}; };
...@@ -97,13 +95,6 @@ static void i2o_pci_free(struct i2o_controller *c) ...@@ -97,13 +95,6 @@ static void i2o_pci_free(struct i2o_controller *c)
i2o_dma_free(dev, &c->hrt); i2o_dma_free(dev, &c->hrt);
i2o_dma_free(dev, &c->status); i2o_dma_free(dev, &c->status);
#ifdef CONFIG_MTRR
if (c->mtrr_reg0 >= 0)
mtrr_del(c->mtrr_reg0, 0, 0);
if (c->mtrr_reg1 >= 0)
mtrr_del(c->mtrr_reg1, 0, 0);
#endif
if (c->raptor && c->in_queue.virt) if (c->raptor && c->in_queue.virt)
iounmap(c->in_queue.virt); iounmap(c->in_queue.virt);
...@@ -178,14 +169,15 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c) ...@@ -178,14 +169,15 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c)
c->name, (unsigned long)c->base.phys, c->name, (unsigned long)c->base.phys,
(unsigned long)c->base.len); (unsigned long)c->base.len);
c->base.virt = ioremap(c->base.phys, c->base.len); c->base.virt = ioremap_nocache(c->base.phys, c->base.len);
if (!c->base.virt) { if (!c->base.virt) {
printk(KERN_ERR "%s: Unable to map controller.\n", c->name); printk(KERN_ERR "%s: Unable to map controller.\n", c->name);
return -ENOMEM; return -ENOMEM;
} }
if (c->raptor) { if (c->raptor) {
c->in_queue.virt = ioremap(c->in_queue.phys, c->in_queue.len); c->in_queue.virt =
ioremap_nocache(c->in_queue.phys, c->in_queue.len);
if (!c->in_queue.virt) { if (!c->in_queue.virt) {
printk(KERN_ERR "%s: Unable to map controller.\n", printk(KERN_ERR "%s: Unable to map controller.\n",
c->name); c->name);
...@@ -199,40 +191,6 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c) ...@@ -199,40 +191,6 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c)
c->post_port = c->base.virt + 0x40; c->post_port = c->base.virt + 0x40;
c->reply_port = c->base.virt + 0x44; c->reply_port = c->base.virt + 0x44;
#ifdef CONFIG_MTRR
/* Enable Write Combining MTRR for IOP's memory region */
c->mtrr_reg0 = mtrr_add(c->in_queue.phys, c->in_queue.len,
MTRR_TYPE_WRCOMB, 1);
c->mtrr_reg1 = -1;
if (c->mtrr_reg0 < 0)
printk(KERN_WARNING "%s: could not enable write combining "
"MTRR\n", c->name);
else
printk(KERN_INFO "%s: using write combining MTRR\n", c->name);
/*
* If it is an INTEL i960 I/O processor then set the first 64K to
* Uncacheable since the region contains the messaging unit which
* shouldn't be cached.
*/
if ((pdev->vendor == PCI_VENDOR_ID_INTEL ||
pdev->vendor == PCI_VENDOR_ID_DPT) && !c->raptor) {
printk(KERN_INFO "%s: MTRR workaround for Intel i960 processor"
"\n", c->name);
c->mtrr_reg1 = mtrr_add(c->base.phys, 0x10000,
MTRR_TYPE_UNCACHABLE, 1);
if (c->mtrr_reg1 < 0) {
printk(KERN_WARNING "%s: Error in setting "
"MTRR_TYPE_UNCACHABLE\n", c->name);
mtrr_del(c->mtrr_reg0, c->in_queue.phys,
c->in_queue.len);
c->mtrr_reg0 = -1;
}
}
#endif
if (i2o_dma_alloc(dev, &c->status, 8, GFP_KERNEL)) { if (i2o_dma_alloc(dev, &c->status, 8, GFP_KERNEL)) {
i2o_pci_free(c); i2o_pci_free(c);
return -ENOMEM; return -ENOMEM;
...@@ -385,28 +343,25 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, ...@@ -385,28 +343,25 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev,
{ {
struct i2o_controller *c; struct i2o_controller *c;
int rc; int rc;
struct pci_dev *i960 = NULL;
printk(KERN_INFO "i2o: Checking for PCI I2O controllers...\n"); printk(KERN_INFO "i2o: Checking for PCI I2O controllers...\n");
if ((pdev->class & 0xff) > 1) { if ((pdev->class & 0xff) > 1) {
printk(KERN_WARNING "i2o: I2O controller found but does not " printk(KERN_WARNING "i2o: %s does not support I2O 1.5 "
"support I2O 1.5 (skipping).\n"); "(skipping).\n", pci_name(pdev));
return -ENODEV; return -ENODEV;
} }
if ((rc = pci_enable_device(pdev))) { if ((rc = pci_enable_device(pdev))) {
printk(KERN_WARNING "i2o: I2O controller found but could not be" printk(KERN_WARNING "i2o: couldn't enable device %s\n",
" enabled.\n"); pci_name(pdev));
return rc; return rc;
} }
printk(KERN_INFO "i2o: I2O controller found on bus %d at %d.\n",
pdev->bus->number, pdev->devfn);
if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
printk(KERN_WARNING "i2o: I2O controller on bus %d at %d: No " printk(KERN_WARNING "i2o: no suitable DMA found for %s\n",
"suitable DMA available!\n", pdev->bus->number, pci_name(pdev));
pdev->devfn);
rc = -ENODEV; rc = -ENODEV;
goto disable; goto disable;
} }
...@@ -415,11 +370,13 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, ...@@ -415,11 +370,13 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev,
c = i2o_iop_alloc(); c = i2o_iop_alloc();
if (IS_ERR(c)) { if (IS_ERR(c)) {
printk(KERN_ERR "i2o: memory for I2O controller could not be " printk(KERN_ERR "i2o: couldn't allocate memory for %s\n",
"allocated\n"); pci_name(pdev));
rc = PTR_ERR(c); rc = PTR_ERR(c);
goto disable; goto disable;
} } else
printk(KERN_INFO "%s: controller found (%s)\n", c->name,
pci_name(pdev));
c->pdev = pdev; c->pdev = pdev;
c->device = pdev->dev; c->device = pdev->dev;
...@@ -432,9 +389,18 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, ...@@ -432,9 +389,18 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev,
} }
if (pdev->subsystem_vendor == PCI_VENDOR_ID_PROMISE) { if (pdev->subsystem_vendor == PCI_VENDOR_ID_PROMISE) {
/*
* Expose the ship behind i960 for initialization, or it will
* failed
*/
i960 =
pci_find_slot(c->pdev->bus->number,
PCI_DEVFN(PCI_SLOT(c->pdev->devfn), 0));
if (i960)
pci_write_config_word(i960, 0x42, 0);
c->promise = 1; c->promise = 1;
printk(KERN_INFO "%s: Promise workarounds activated.\n",
c->name);
} }
/* Cards that go bananas if you quiesce them before you reset them. */ /* Cards that go bananas if you quiesce them before you reset them. */
...@@ -459,6 +425,9 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, ...@@ -459,6 +425,9 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev,
if ((rc = i2o_iop_add(c))) if ((rc = i2o_iop_add(c)))
goto uninstall; goto uninstall;
if (i960)
pci_write_config_word(i960, 0x42, 0x03ff);
return 0; return 0;
uninstall: uninstall:
......
...@@ -24,6 +24,14 @@ ...@@ -24,6 +24,14 @@
#define MAX_I2O_CONTROLLERS 32 #define MAX_I2O_CONTROLLERS 32
//#include <linux/ioctl.h> //#include <linux/ioctl.h>
#ifndef __KERNEL__
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
#endif /* __KERNEL__ */
/* /*
* I2O Control IOCTLs and structures * I2O Control IOCTLs and structures
...@@ -126,14 +134,6 @@ struct i2o_evt_get { ...@@ -126,14 +134,6 @@ struct i2o_evt_get {
#define I2O_BUS_CARDBUS 7 #define I2O_BUS_CARDBUS 7
#define I2O_BUS_UNKNOWN 0x80 #define I2O_BUS_UNKNOWN 0x80
#ifndef __KERNEL__
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
#endif /* __KERNEL__ */
typedef struct _i2o_pci_bus { typedef struct _i2o_pci_bus {
u8 PciFunctionNumber; u8 PciFunctionNumber;
u8 PciDeviceNumber; u8 PciDeviceNumber;
......
...@@ -152,11 +152,6 @@ struct i2o_controller { ...@@ -152,11 +152,6 @@ struct i2o_controller {
unsigned int raptor:1; /* split bar */ unsigned int raptor:1; /* split bar */
unsigned int promise:1; /* Promise controller */ unsigned int promise:1; /* Promise controller */
#ifdef CONFIG_MTRR
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 */ struct notifier_block *event_notifer; /* Events */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment