diff options
author | Markus Lidel <Markus.Lidel@shadowconnect.com> | 2005-06-23 22:02:21 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-06-24 00:05:29 -0700 |
commit | 9e87545f06930c1d294423a8091d1077e7444a47 (patch) | |
tree | ef05fca1becfa0e1584f234ddf9b1a430b7d018e | |
parent | b2aaee33fbb354a2f08121aa1c1be55841102761 (diff) | |
download | linux-9e87545f06930c1d294423a8091d1077e7444a47.tar.bz2 |
[PATCH] I2O: second code cleanup of sparse warnings and unneeded syncronization
Changes:
- Added header "core.h" for i2o_core.ko internal definitions
- More sparse fixes
- Changed display of TID's in sysfs attributes from XXX to 0xXXX
- Use the right functions for accessing I/O and normal memory
- Removed error handling of SCSI device errors and let the SCSI layer
take care of it
- Added new device / removed device handling to SCSI-OSM
- Make status access volatile
- Cleaned up activation of I2O controller
- Removed unnecessary wmb() and rmb() calls
- Use own struct i2o_io for I/O memory instead of struct i2o_dma
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>
-rw-r--r-- | drivers/message/i2o/core.h | 55 | ||||
-rw-r--r-- | drivers/message/i2o/debug.c | 3 | ||||
-rw-r--r-- | drivers/message/i2o/device.c | 22 | ||||
-rw-r--r-- | drivers/message/i2o/driver.c | 24 | ||||
-rw-r--r-- | drivers/message/i2o/exec-osm.c | 27 | ||||
-rw-r--r-- | drivers/message/i2o/i2o_block.c | 4 | ||||
-rw-r--r-- | drivers/message/i2o/i2o_config.c | 8 | ||||
-rw-r--r-- | drivers/message/i2o/i2o_scsi.c | 202 | ||||
-rw-r--r-- | drivers/message/i2o/iop.c | 128 | ||||
-rw-r--r-- | drivers/message/i2o/pci.c | 21 | ||||
-rw-r--r-- | include/linux/i2o-dev.h | 23 | ||||
-rw-r--r-- | include/linux/i2o.h | 116 |
12 files changed, 275 insertions, 358 deletions
diff --git a/drivers/message/i2o/core.h b/drivers/message/i2o/core.h new file mode 100644 index 000000000000..49851cccc48d --- /dev/null +++ b/drivers/message/i2o/core.h @@ -0,0 +1,55 @@ +/* + * I2O core internal declarations + * + * Copyright (C) 2005 Markus Lidel <Markus.Lidel@shadowconnect.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * Fixes/additions: + * Markus Lidel <Markus.Lidel@shadowconnect.com> + * initial version. + */ + +/* Exec-OSM */ +extern struct bus_type i2o_bus_type; + +extern struct i2o_driver i2o_exec_driver; +extern int i2o_exec_lct_get(struct i2o_controller *); + +extern int __init i2o_exec_init(void); +extern void __exit i2o_exec_exit(void); + +/* driver */ +extern int i2o_driver_dispatch(struct i2o_controller *, u32); + +extern int __init i2o_driver_init(void); +extern void __exit i2o_driver_exit(void); + +/* PCI */ +extern int __init i2o_pci_init(void); +extern void __exit i2o_pci_exit(void); + +/* device */ +extern void i2o_device_remove(struct i2o_device *); +extern int i2o_device_parse_lct(struct i2o_controller *); + +extern int i2o_device_init(void); +extern void i2o_device_exit(void); + +/* IOP */ +extern struct i2o_controller *i2o_iop_alloc(void); +extern void i2o_iop_free(struct i2o_controller *); + +extern int i2o_iop_add(struct i2o_controller *); +extern void i2o_iop_remove(struct i2o_controller *); + +/* control registers relative to c->base */ +#define I2O_IRQ_STATUS 0x30 +#define I2O_IRQ_MASK 0x34 +#define I2O_IN_PORT 0x40 +#define I2O_OUT_PORT 0x44 + +#define I2O_IRQ_OUTBOUND_POST 0x00000008 diff --git a/drivers/message/i2o/debug.c b/drivers/message/i2o/debug.c index 2a5d478fc60e..018ca887ca85 100644 --- a/drivers/message/i2o/debug.c +++ b/drivers/message/i2o/debug.c @@ -4,8 +4,6 @@ #include <linux/pci.h> #include <linux/i2o.h> -extern struct i2o_driver **i2o_drivers; -extern unsigned int i2o_max_drivers; static void i2o_report_util_cmd(u8 cmd); static void i2o_report_exec_cmd(u8 cmd); static void i2o_report_fail_status(u8 req_status, u32 * msg); @@ -23,7 +21,6 @@ void i2o_report_status(const char *severity, const char *str, u8 cmd = (msg[1] >> 24) & 0xFF; u8 req_status = (msg[4] >> 24) & 0xFF; u16 detailed_status = msg[4] & 0xFFFF; - //struct i2o_driver *h = i2o_drivers[msg[2] & (i2o_max_drivers-1)]; if (cmd == I2O_CMD_UTIL_EVT_REGISTER) return; // No status in this reply diff --git a/drivers/message/i2o/device.c b/drivers/message/i2o/device.c index f1b7eb63d54b..0ee342ea29bc 100644 --- a/drivers/message/i2o/device.c +++ b/drivers/message/i2o/device.c @@ -16,9 +16,7 @@ #include <linux/module.h> #include <linux/i2o.h> #include <linux/delay.h> - -/* Exec OSM functions */ -extern struct bus_type i2o_bus_type; +#include "core.h" /** * i2o_device_issue_claim - claim or release a device @@ -293,12 +291,12 @@ int i2o_device_parse_lct(struct i2o_controller *c) } if (lct->table_size * 4 > c->dlct.len) { - memcpy_fromio(c->lct, c->dlct.virt, c->dlct.len); + memcpy(c->lct, c->dlct.virt, c->dlct.len); up(&c->lct_lock); return -EAGAIN; } - memcpy_fromio(c->lct, c->dlct.virt, lct->table_size * 4); + memcpy(c->lct, c->dlct.virt, lct->table_size * 4); lct = c->lct; @@ -353,7 +351,7 @@ static ssize_t i2o_device_class_show_class_id(struct class_device *cd, { struct i2o_device *dev = to_i2o_device(cd->dev); - sprintf(buf, "%03x\n", dev->lct_data.class_id); + sprintf(buf, "0x%03x\n", dev->lct_data.class_id); return strlen(buf) + 1; }; @@ -368,7 +366,7 @@ static ssize_t i2o_device_class_show_tid(struct class_device *cd, char *buf) { struct i2o_device *dev = to_i2o_device(cd->dev); - sprintf(buf, "%03x\n", dev->lct_data.tid); + sprintf(buf, "0x%03x\n", dev->lct_data.tid); return strlen(buf) + 1; }; @@ -490,7 +488,7 @@ static int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist, if (rc == -ETIMEDOUT) return rc; - memcpy_fromio(reslist, res.virt, res.len); + memcpy(reslist, res.virt, res.len); i2o_dma_free(dev, &res); /* Query failed */ @@ -532,17 +530,23 @@ int i2o_parm_field_get(struct i2o_device *i2o_dev, int group, int field, void *buf, int buflen) { u16 opblk[] = { 1, 0, I2O_PARAMS_FIELD_GET, group, 1, field }; - u8 resblk[8 + buflen]; /* 8 bytes for header */ + u8 *resblk; /* 8 bytes for header */ int size; if (field == -1) /* whole group */ opblk[4] = -1; + resblk = kmalloc(buflen + 8, GFP_KERNEL | GFP_ATOMIC); + if (!resblk) + return -ENOMEM; + size = i2o_parm_issue(i2o_dev, I2O_CMD_UTIL_PARAMS_GET, opblk, sizeof(opblk), resblk, buflen + 8); memcpy(buf, resblk + 8, buflen); /* cut off header */ + kfree(resblk); + if (size > buflen) return buflen; diff --git a/drivers/message/i2o/driver.c b/drivers/message/i2o/driver.c index 393be8e2914c..c32f9dbc5744 100644 --- a/drivers/message/i2o/driver.c +++ b/drivers/message/i2o/driver.c @@ -17,11 +17,12 @@ #include <linux/module.h> #include <linux/rwsem.h> #include <linux/i2o.h> +#include "core.h" #define OSM_NAME "i2o" /* max_drivers - Maximum I2O drivers (OSMs) which could be registered */ -unsigned int i2o_max_drivers = I2O_MAX_DRIVERS; +static unsigned int i2o_max_drivers = I2O_MAX_DRIVERS; module_param_named(max_drivers, i2o_max_drivers, uint, 0); MODULE_PARM_DESC(max_drivers, "maximum number of OSM's to support"); @@ -179,15 +180,10 @@ void i2o_driver_unregister(struct i2o_driver *drv) int i2o_driver_dispatch(struct i2o_controller *c, u32 m) { struct i2o_driver *drv; - struct i2o_message __iomem *msg = i2o_msg_out_to_virt(c, m); - u32 context; + struct i2o_message *msg = i2o_msg_out_to_virt(c, m); + u32 context = le32_to_cpu(msg->u.s.icntxt); unsigned long flags; - if(unlikely(!msg)) - return -EIO; - - context = readl(&msg->u.s.icntxt); - if (unlikely(context >= i2o_max_drivers)) { osm_warn("%s: Spurious reply to unknown driver %d\n", c->name, context); @@ -204,11 +200,11 @@ int i2o_driver_dispatch(struct i2o_controller *c, u32 m) return -EIO; } - if ((readl(&msg->u.head[1]) >> 24) == I2O_CMD_UTIL_EVT_REGISTER) { + if ((le32_to_cpu(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; + u16 tid = le32_to_cpu(msg->u.head[1]) & 0xfff; osm_debug("event received from device %d\n", tid); @@ -216,16 +212,16 @@ int i2o_driver_dispatch(struct i2o_controller *c, u32 m) return -EIO; /* cut of header from message size (in 32-bit words) */ - size = (readl(&msg->u.head[0]) >> 16) - 5; + size = (le32_to_cpu(msg->u.head[0]) >> 16) - 5; evt = kmalloc(size * 4 + sizeof(*evt), GFP_ATOMIC | __GFP_ZERO); if (!evt) return -ENOMEM; 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); + evt->tcntxt = le32_to_cpu(msg->u.s.tcntxt); + evt->event_indicator = le32_to_cpu(msg->body[0]); + memcpy(&evt->tcntxt, &msg->u.s.tcntxt, size * 4); list_for_each_entry_safe(dev, tmp, &c->devices, list) if (dev->lct_data.tid == tid) { diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c index 0160221c802a..ffe0cecfa060 100644 --- a/drivers/message/i2o/exec-osm.c +++ b/drivers/message/i2o/exec-osm.c @@ -30,6 +30,7 @@ #include <linux/module.h> #include <linux/i2o.h> #include <linux/delay.h> +#include "core.h" #define OSM_NAME "exec-osm" @@ -37,9 +38,6 @@ struct i2o_driver i2o_exec_driver; static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind); -/* Module internal functions from other sources */ -extern int i2o_device_parse_lct(struct i2o_controller *); - /* global wait list for POST WAIT */ static LIST_HEAD(i2o_exec_wait_list); @@ -50,7 +48,7 @@ struct i2o_exec_wait { u32 tcntxt; /* transaction context from reply */ int complete; /* 1 if reply received otherwise 0 */ u32 m; /* message id */ - struct i2o_message __iomem *msg; /* pointer to the reply message */ + struct i2o_message *msg; /* pointer to the reply message */ struct list_head list; /* node in global wait list */ }; @@ -162,7 +160,7 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long barrier(); if (wait->complete) { - rc = readl(&wait->msg->body[0]) >> 24; + rc = le32_to_cpu(wait->msg->body[0]) >> 24; i2o_flush_reply(c, wait->m); i2o_exec_wait_free(wait); } else { @@ -202,8 +200,7 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long * message must also be given back to the controller. */ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m, - struct i2o_message __iomem *msg, - u32 context) + struct i2o_message *msg, u32 context) { struct i2o_exec_wait *wait, *tmp; unsigned long flags; @@ -378,11 +375,11 @@ static void i2o_exec_lct_modified(struct i2o_controller *c) * code on failure and if the reply should be flushed. */ static int i2o_exec_reply(struct i2o_controller *c, u32 m, - struct i2o_message __iomem *msg) + struct i2o_message *msg) { u32 context; - if (readl(&msg->u.head[0]) & MSG_FAIL) { + if (le32_to_cpu(msg->u.head[0]) & MSG_FAIL) { /* * If Fail bit is set we must take the transaction context of * the preserved message to find the right request again. @@ -390,7 +387,7 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m, struct i2o_message __iomem *pmsg; u32 pm; - pm = readl(&msg->body[3]); + pm = le32_to_cpu(msg->body[3]); pmsg = i2o_msg_in_to_virt(c, pm); @@ -401,12 +398,12 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m, /* Release the preserved msg */ i2o_msg_nop(c, pm); } else - context = readl(&msg->u.s.tcntxt); + context = le32_to_cpu(msg->u.s.tcntxt); if (context & 0x80000000) return i2o_msg_post_wait_complete(c, m, msg, context); - if ((readl(&msg->u.head[1]) >> 24) == I2O_CMD_LCT_NOTIFY) { + if ((le32_to_cpu(msg->u.head[1]) >> 24) == I2O_CMD_LCT_NOTIFY) { struct work_struct *work; pr_debug("%s: LCT notify received\n", c->name); @@ -442,9 +439,9 @@ 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); + if (likely(evt->i2o_dev)) + osm_debug("Event received from device: %d\n", + evt->i2o_dev->lct_data.tid); kfree(evt); }; diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c index 1dd2b9dad50e..28b3918dbc16 100644 --- a/drivers/message/i2o/i2o_block.c +++ b/drivers/message/i2o/i2o_block.c @@ -62,7 +62,7 @@ #include "i2o_block.h" #define OSM_NAME "block-osm" -#define OSM_VERSION "$Rev$" +#define OSM_VERSION "1.287" #define OSM_DESCRIPTION "I2O Block Device OSM" static struct i2o_driver i2o_block_driver; @@ -537,7 +537,7 @@ static int i2o_block_reply(struct i2o_controller *c, u32 m, static void i2o_block_event(struct i2o_event *evt) { - osm_info("event received\n"); + osm_debug("event received\n"); kfree(evt); }; diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c index 7636833b4623..8160a1f6c73a 100644 --- a/drivers/message/i2o/i2o_config.c +++ b/drivers/message/i2o/i2o_config.c @@ -36,6 +36,8 @@ #include <asm/uaccess.h> +#define SG_TABLESIZE 30 + extern int i2o_parm_issue(struct i2o_device *, int, void *, int, void *, int); static int i2o_cfg_ioctl(struct inode *inode, struct file *fp, unsigned int cmd, @@ -663,7 +665,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar goto sg_list_cleanup; if (sg_offset) { - u32 msg[MSG_FRAME_SIZE]; + u32 msg[I2O_OUTBOUND_MSG_FRAME_SIZE]; /* Copy back the Scatter Gather buffers back to user space */ u32 j; // TODO 64bit fix @@ -671,7 +673,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar int sg_size; // re-acquire the original message to handle correctly the sg copy operation - memset(&msg, 0, MSG_FRAME_SIZE * 4); + memset(&msg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4); // get user msg size in u32s if (get_user(size, &user_msg[0])) { rcode = -EFAULT; @@ -902,7 +904,7 @@ static int i2o_cfg_passthru(unsigned long arg) int sg_size; // re-acquire the original message to handle correctly the sg copy operation - memset(&msg, 0, MSG_FRAME_SIZE * 4); + memset(&msg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4); // get user msg size in u32s if (get_user(size, &user_msg[0])) { rcode = -EFAULT; diff --git a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c index fef53b509a61..9f1744c3933b 100644 --- a/drivers/message/i2o/i2o_scsi.c +++ b/drivers/message/i2o/i2o_scsi.c @@ -40,7 +40,6 @@ * Fix the resource management problems. */ -#define DEBUG 1 #include <linux/module.h> #include <linux/kernel.h> #include <linux/types.h> @@ -338,162 +337,89 @@ static int i2o_scsi_reply(struct i2o_controller *c, u32 m, struct i2o_message *msg) { struct scsi_cmnd *cmd; + u32 error; struct device *dev; - u8 as, ds, st; cmd = i2o_cntxt_list_get(c, le32_to_cpu(msg->u.s.tcntxt)); - - if (msg->u.head[0] & (1 << 13)) { - struct i2o_message __iomem *pmsg; /* preserved message */ - u32 pm; - int err = DID_ERROR; - - pm = le32_to_cpu(msg->body[3]); - - pmsg = i2o_msg_in_to_virt(c, pm); - - osm_err("IOP fail.\n"); - osm_err("From %d To %d Cmd %d.\n", - (msg->u.head[1] >> 12) & 0xFFF, - msg->u.head[1] & 0xFFF, msg->u.head[1] >> 24); - osm_err("Failure Code %d.\n", msg->body[0] >> 24); - if (msg->body[0] & (1 << 16)) - osm_err("Format error.\n"); - if (msg->body[0] & (1 << 17)) - osm_err("Path error.\n"); - if (msg->body[0] & (1 << 18)) - osm_err("Path State.\n"); - if (msg->body[0] & (1 << 18)) - { - osm_err("Congestion.\n"); - err = DID_BUS_BUSY; - } - - osm_debug("Failing message is %p.\n", pmsg); - - cmd = i2o_cntxt_list_get(c, readl(&pmsg->u.s.tcntxt)); - if (!cmd) - return 1; - - cmd->result = err << 16; - cmd->scsi_done(cmd); - - /* Now flush the message by making it a NOP */ - i2o_msg_nop(c, pm); - - return 1; + if (unlikely(!cmd)) { + osm_err("NULL reply received!\n"); + return -1; } /* * Low byte is device status, next is adapter status, * (then one byte reserved), then request status. */ - ds = (u8) le32_to_cpu(msg->body[0]); - as = (u8) (le32_to_cpu(msg->body[0]) >> 8); - st = (u8) (le32_to_cpu(msg->body[0]) >> 24); + error = le32_to_cpu(msg->body[0]); + osm_debug("Completed %ld\n", cmd->serial_number); + + cmd->result = error & 0xff; /* - * Is this a control request coming back - eg an abort ? + * if DeviceStatus is not SCSI_SUCCESS copy over the sense data and let + * the SCSI layer handle the error */ + if (cmd->result) + memcpy(cmd->sense_buffer, &msg->body[3], + min(sizeof(cmd->sense_buffer), (size_t) 40)); - if (!cmd) { - if (st) - osm_warn("SCSI abort: %08X", le32_to_cpu(msg->body[0])); - osm_info("SCSI abort completed.\n"); - return -EFAULT; - } + /* only output error code if AdapterStatus is not HBA_SUCCESS */ + if ((error >> 8) & 0xff) + osm_err("SCSI error %08x\n", error); - osm_debug("Completed %ld\n", cmd->serial_number); + dev = &c->pdev->dev; + if (cmd->use_sg) + dma_unmap_sg(dev, cmd->request_buffer, cmd->use_sg, + cmd->sc_data_direction); + else if (cmd->SCp.dma_handle) + dma_unmap_single(dev, cmd->SCp.dma_handle, cmd->request_bufflen, + cmd->sc_data_direction); - if (st) { - u32 count, error; - /* An error has occurred */ - - switch (st) { - case 0x06: - count = le32_to_cpu(msg->body[1]); - if (count < cmd->underflow) { - int i; - - osm_err("SCSI underflow 0x%08X 0x%08X\n", count, - cmd->underflow); - osm_debug("Cmd: "); - for (i = 0; i < 15; i++) - pr_debug("%02X ", cmd->cmnd[i]); - pr_debug(".\n"); - cmd->result = (DID_ERROR << 16); - } - break; + cmd->scsi_done(cmd); - default: - error = le32_to_cpu(msg->body[0]); - - osm_err("SCSI error %08x\n", error); - - if ((error & 0xff) == 0x02 /*CHECK_CONDITION */ ) { - int i; - u32 len = sizeof(cmd->sense_buffer); - len = (len > 40) ? 40 : len; - // Copy over the sense data - memcpy(cmd->sense_buffer, (void *)&msg->body[3], - len); - for (i = 0; i <= len; i++) - osm_info("%02x\n", - cmd->sense_buffer[i]); - if (cmd->sense_buffer[0] == 0x70 - && cmd->sense_buffer[2] == DATA_PROTECT) { - /* This is to handle an array failed */ - cmd->result = (DID_TIME_OUT << 16); - printk(KERN_WARNING "%s: SCSI Data " - "Protect-Device (%d,%d,%d) " - "hba_status=0x%x, dev_status=" - "0x%x, cmd=0x%x\n", c->name, - (u32) cmd->device->channel, - (u32) cmd->device->id, - (u32) cmd->device->lun, - (error >> 8) & 0xff, - error & 0xff, cmd->cmnd[0]); - } else - cmd->result = (DID_ERROR << 16); - - break; - } - - switch (as) { - case 0x0E: - /* SCSI Reset */ - cmd->result = DID_RESET << 16; - break; - - case 0x0F: - cmd->result = DID_PARITY << 16; - break; - - default: - cmd->result = DID_ERROR << 16; - break; - } + return 1; +}; - break; - } +/** + * i2o_scsi_notify_device_add - Retrieve notifications of added devices + * @i2o_dev: the I2O device which was added + * + * If a I2O device is added we catch the notification, because I2O classes + * other then SCSI peripheral will not be received through + * i2o_scsi_probe(). + */ +static void i2o_scsi_notify_device_add(struct i2o_device *i2o_dev) +{ + switch (i2o_dev->lct_data.class_id) { + case I2O_CLASS_EXECUTIVE: + case I2O_CLASS_RANDOM_BLOCK_STORAGE: + i2o_scsi_probe(&i2o_dev->device); + break; - cmd->scsi_done(cmd); - return 1; + default: + break; } +}; - cmd->result = DID_OK << 16 | ds; - - dev = &c->pdev->dev; - if (cmd->use_sg) - dma_unmap_sg(dev, (struct scatterlist *)cmd->buffer, - cmd->use_sg, cmd->sc_data_direction); - else if (cmd->request_bufflen) - dma_unmap_single(dev, (dma_addr_t) ((long)cmd->SCp.ptr), - cmd->request_bufflen, cmd->sc_data_direction); - - cmd->scsi_done(cmd); +/** + * i2o_scsi_notify_device_remove - Retrieve notifications of removed + * devices + * @i2o_dev: the I2O device which was removed + * + * If a I2O device is removed, we catch the notification to remove the + * corresponding SCSI device. + */ +static void i2o_scsi_notify_device_remove(struct i2o_device *i2o_dev) +{ + switch (i2o_dev->lct_data.class_id) { + case I2O_CLASS_EXECUTIVE: + case I2O_CLASS_RANDOM_BLOCK_STORAGE: + i2o_scsi_remove(&i2o_dev->device); + break; - return 1; + default: + break; + } }; /** @@ -554,6 +480,8 @@ static struct i2o_driver i2o_scsi_driver = { .name = OSM_NAME, .reply = i2o_scsi_reply, .classes = i2o_scsi_class_id, + .notify_device_add = i2o_scsi_notify_device_add, + .notify_device_remove = i2o_scsi_notify_device_remove, .notify_controller_add = i2o_scsi_notify_controller_add, .notify_controller_remove = i2o_scsi_notify_controller_remove, .driver = { @@ -712,7 +640,7 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, */ /* Attach tags to the devices */ - /* + /* FIXME: implement if(SCpnt->device->tagged_supported) { if(SCpnt->tag == HEAD_OF_QUEUE_TAG) scsi_flags |= 0x01000000; diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c index 40312053b38d..c32022bc2a21 100644 --- a/drivers/message/i2o/iop.c +++ b/drivers/message/i2o/iop.c @@ -28,8 +28,10 @@ #include <linux/module.h> #include <linux/i2o.h> #include <linux/delay.h> +#include "core.h" -#define OSM_VERSION "$Rev$" +#define OSM_NAME "i2o" +#define OSM_VERSION "1.288" #define OSM_DESCRIPTION "I2O subsystem" /* global I2O controller list */ @@ -43,20 +45,6 @@ static struct i2o_dma i2o_systab; static int i2o_hrt_get(struct i2o_controller *c); -/* Module internal functions from other sources */ -extern struct i2o_driver i2o_exec_driver; -extern int i2o_exec_lct_get(struct i2o_controller *); -extern void i2o_device_remove(struct i2o_device *); - -extern int __init i2o_driver_init(void); -extern void __exit i2o_driver_exit(void); -extern int __init i2o_exec_init(void); -extern void __exit i2o_exec_exit(void); -extern int __init i2o_pci_init(void); -extern void __exit i2o_pci_exit(void); -extern int i2o_device_init(void); -extern void i2o_device_exit(void); - /** * i2o_msg_nop - Returns a message which is not used * @c: I2O controller from which the message was created @@ -92,16 +80,16 @@ void i2o_msg_nop(struct i2o_controller *c, u32 m) * address from the read port (see the i2o spec). If no message is * available returns I2O_QUEUE_EMPTY and msg is leaved untouched. */ -u32 i2o_msg_get_wait(struct i2o_controller *c, struct i2o_message __iomem **msg, - int wait) +u32 i2o_msg_get_wait(struct i2o_controller *c, + struct i2o_message __iomem ** msg, int wait) { unsigned long timeout = jiffies + wait * HZ; u32 m; while ((m = i2o_msg_get(c, msg)) == I2O_QUEUE_EMPTY) { if (time_after(jiffies, timeout)) { - pr_debug("%s: Timeout waiting for message frame.\n", - c->name); + osm_debug("%s: Timeout waiting for message frame.\n", + c->name); return I2O_QUEUE_EMPTY; } set_current_state(TASK_UNINTERRUPTIBLE); @@ -466,7 +454,7 @@ static int i2o_iop_clear(struct i2o_controller *c) */ static int i2o_iop_init_outbound_queue(struct i2o_controller *c) { - u8 *status = c->status.virt; + volatile u8 *status = c->status.virt; u32 m; struct i2o_message __iomem *msg; ulong timeout; @@ -474,21 +462,20 @@ static int i2o_iop_init_outbound_queue(struct i2o_controller *c) osm_debug("%s: Initializing Outbound Queue...\n", c->name); - memset(status, 0, 4); + memset(c->status.virt, 0, 4); m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); if (m == I2O_QUEUE_EMPTY) return -ETIMEDOUT; - writel(EIGHT_WORD_MSG_SIZE | TRL_OFFSET_6, &msg->u.head[0]); + writel(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6, &msg->u.head[0]); writel(I2O_CMD_OUTBOUND_INIT << 24 | HOST_TID << 12 | ADAPTER_TID, &msg->u.head[1]); writel(i2o_exec_driver.context, &msg->u.s.icntxt); - writel(0x0106, &msg->u.s.tcntxt); /* FIXME: why 0x0106, maybe in - Spec? */ + writel(0x00000000, &msg->u.s.tcntxt); writel(PAGE_SIZE, &msg->body[0]); /* Outbound msg frame size in words and Initcode */ - writel(MSG_FRAME_SIZE << 16 | 0x80, &msg->body[1]); + writel(I2O_OUTBOUND_MSG_FRAME_SIZE << 16 | 0x80, &msg->body[1]); writel(0xd0000004, &msg->body[2]); writel(i2o_dma_low(c->status.phys), &msg->body[3]); writel(i2o_dma_high(c->status.phys), &msg->body[4]); @@ -503,17 +490,15 @@ static int i2o_iop_init_outbound_queue(struct i2o_controller *c) } set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(1); - - rmb(); } m = c->out_queue.phys; /* Post frames */ - for (i = 0; i < NMBR_MSG_FRAMES; i++) { + for (i = 0; i < I2O_MAX_OUTBOUND_MSG_FRAMES; i++) { i2o_flush_reply(c, m); udelay(1); /* Promise */ - m += MSG_FRAME_SIZE * 4; + m += I2O_OUTBOUND_MSG_FRAME_SIZE * sizeof(u32); } return 0; @@ -530,20 +515,20 @@ static int i2o_iop_init_outbound_queue(struct i2o_controller *c) */ static int i2o_iop_reset(struct i2o_controller *c) { - u8 *status = c->status.virt; + volatile u8 *status = c->status.virt; struct i2o_message __iomem *msg; u32 m; unsigned long timeout; i2o_status_block *sb = c->status_block.virt; int rc = 0; - pr_debug("%s: Resetting controller\n", c->name); + osm_debug("%s: Resetting controller\n", c->name); m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); if (m == I2O_QUEUE_EMPTY) return -ETIMEDOUT; - memset(status, 0, 8); + memset(c->status_block.virt, 0, 8); /* Quiesce all IOPs first */ i2o_iop_quiesce_all(); @@ -568,8 +553,6 @@ static int i2o_iop_reset(struct i2o_controller *c) set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(1); - - rmb(); } switch (*status) { @@ -984,11 +967,11 @@ int i2o_status_get(struct i2o_controller *c) { struct i2o_message __iomem *msg; u32 m; - u8 *status_block; + volatile u8 *status_block; unsigned long timeout; status_block = (u8 *) c->status_block.virt; - memset(status_block, 0, sizeof(i2o_status_block)); + memset(c->status_block.virt, 0, sizeof(i2o_status_block)); m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); if (m == I2O_QUEUE_EMPTY) @@ -1017,8 +1000,6 @@ int i2o_status_get(struct i2o_controller *c) set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(1); - - rmb(); } #ifdef DEBUG @@ -1107,6 +1088,11 @@ static void i2o_iop_release(struct device *dev) i2o_iop_free(c); }; +/* I2O controller class */ +static struct class i2o_controller_class = { + .name = "i2o_controller", +}; + /** * i2o_iop_alloc - Allocate and initialize a i2o_controller struct * @@ -1136,8 +1122,14 @@ struct i2o_controller *i2o_iop_alloc(void) sprintf(c->name, "iop%d", c->unit); device_initialize(&c->device); + class_device_initialize(&c->classdev); + c->device.release = &i2o_iop_release; + c->classdev.class = &i2o_controller_class; + c->classdev.dev = &c->device; + snprintf(c->device.bus_id, BUS_ID_SIZE, "iop%d", c->unit); + snprintf(c->classdev.class_id, BUS_ID_SIZE, "iop%d", c->unit); #if BITS_PER_LONG == 64 spin_lock_init(&c->context_list_lock); @@ -1161,45 +1153,55 @@ int i2o_iop_add(struct i2o_controller *c) { int rc; - if((rc = device_add(&c->device))) { - printk(KERN_ERR "%s: could not register controller\n", c->name); + if ((rc = device_add(&c->device))) { + osm_err("%s: could not add controller\n", c->name); goto iop_reset; } - printk(KERN_INFO "%s: Activating I2O controller...\n", c->name); - printk(KERN_INFO "%s: This may take a few minutes if there are many " - "devices\n", c->name); + if ((rc = class_device_add(&c->classdev))) { + osm_err("%s: could not add controller class\n", c->name); + goto device_del; + } + + osm_info("%s: Activating I2O controller...\n", c->name); + osm_info("%s: This may take a few minutes if there are many devices\n", + c->name); if ((rc = i2o_iop_activate(c))) { - printk(KERN_ERR "%s: could not activate controller\n", - c->name); - goto iop_reset; + osm_err("%s: could not activate controller\n", c->name); + goto class_del; } - pr_debug("%s: building sys table...\n", c->name); + osm_debug("%s: building sys table...\n", c->name); if ((rc = i2o_systab_build())) - goto iop_reset; + goto class_del; - pr_debug("%s: online controller...\n", c->name); + osm_debug("%s: online controller...\n", c->name); if ((rc = i2o_iop_online(c))) - goto iop_reset; + goto class_del; - pr_debug("%s: getting LCT...\n", c->name); + osm_debug("%s: getting LCT...\n", c->name); if ((rc = i2o_exec_lct_get(c))) - goto iop_reset; + goto class_del; list_add(&c->list, &i2o_controllers); i2o_driver_notify_controller_add_all(c); - printk(KERN_INFO "%s: Controller added\n", c->name); + osm_info("%s: Controller added\n", c->name); return 0; -iop_reset: + class_del: + class_device_del(&c->classdev); + + device_del: + device_del(&c->device); + + iop_reset: i2o_iop_reset(c); return rc; @@ -1260,16 +1262,18 @@ static int __init i2o_iop_init(void) if (rc) goto exit; - rc = i2o_driver_init(); - if (rc) + if ((rc = class_register(&i2o_controller_class))) { + osm_err("can't register class i2o_controller\n"); goto device_exit; + } - rc = i2o_exec_init(); - if (rc) + if ((rc = i2o_driver_init())) + goto class_exit; + + if ((rc = i2o_exec_init())) goto driver_exit; - rc = i2o_pci_init(); - if (rc < 0) + if ((rc = i2o_pci_init())) goto exec_exit; return 0; @@ -1280,6 +1284,9 @@ static int __init i2o_iop_init(void) driver_exit: i2o_driver_exit(); + class_exit: + class_unregister(&i2o_controller_class); + device_exit: i2o_device_exit(); @@ -1297,6 +1304,7 @@ static void __exit i2o_iop_exit(void) i2o_pci_exit(); i2o_exec_exit(); i2o_driver_exit(); + class_unregister(&i2o_controller_class); i2o_device_exit(); }; diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c index 964fe481849e..442e34506b90 100644 --- a/drivers/message/i2o/pci.c +++ b/drivers/message/i2o/pci.c @@ -30,15 +30,7 @@ #include <linux/pci.h> #include <linux/interrupt.h> #include <linux/i2o.h> - -/* Module internal functions from other sources */ -extern struct i2o_controller *i2o_iop_alloc(void); -extern void i2o_iop_free(struct i2o_controller *); - -extern int i2o_iop_add(struct i2o_controller *); -extern void i2o_iop_remove(struct i2o_controller *); - -extern int i2o_driver_dispatch(struct i2o_controller *, u32); +#include "core.h" /* PCI device id table for all I2O controllers */ static struct pci_device_id __devinitdata i2o_pci_ids[] = { @@ -248,9 +240,7 @@ static int i2o_pci_irq_enable(struct i2o_controller *c) struct pci_dev *pdev = c->pdev; int rc; - wmb(); writel(0xffffffff, c->irq_mask); - wmb(); if (pdev->irq) { rc = request_irq(pdev->irq, i2o_pci_interrupt, SA_SHIRQ, @@ -263,7 +253,6 @@ static int i2o_pci_irq_enable(struct i2o_controller *c) } writel(0x00000000, c->irq_mask); - wmb(); printk(KERN_INFO "%s: Installed at IRQ %d\n", c->name, pdev->irq); @@ -278,9 +267,7 @@ static int i2o_pci_irq_enable(struct i2o_controller *c) */ static void i2o_pci_irq_disable(struct i2o_controller *c) { - wmb(); writel(0xffffffff, c->irq_mask); - wmb(); if (c->pdev->irq > 0) free_irq(c->pdev->irq, c); @@ -406,11 +393,11 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, if ((rc = i2o_iop_add(c))) goto uninstall; + get_device(&c->device); + if (i960) pci_write_config_word(i960, 0x42, 0x03ff); - get_device(&c->device); - return 0; uninstall: @@ -478,6 +465,4 @@ void __exit i2o_pci_exit(void) { pci_unregister_driver(&i2o_pci_driver); }; - -EXPORT_SYMBOL(i2o_dma_realloc); MODULE_DEVICE_TABLE(pci, i2o_pci_ids); diff --git a/include/linux/i2o-dev.h b/include/linux/i2o-dev.h index d4a08d29e36d..36fd18cdad28 100644 --- a/include/linux/i2o-dev.h +++ b/include/linux/i2o-dev.h @@ -33,18 +33,6 @@ typedef unsigned int u32; #endif /* __KERNEL__ */ /* - * Software module types - */ -#define I2O_SOFTWARE_MODULE_IRTOS 0x11 -#define I2O_SOFTWARE_MODULE_IOP_PRIVATE 0x22 -#define I2O_SOFTWARE_MODULE_IOP_CONFIG 0x23 - -/* - * Vendors - */ -#define I2O_VENDOR_DPT 0x001b - -/* * I2O Control IOCTLs and structures */ #define I2O_MAGIC_NUMBER 'i' @@ -414,6 +402,17 @@ typedef struct _i2o_status_block { #define ADAPTER_STATE_FAILED 0x10 #define ADAPTER_STATE_FAULTED 0x11 +/* + * Software module types + */ +#define I2O_SOFTWARE_MODULE_IRTOS 0x11 +#define I2O_SOFTWARE_MODULE_IOP_PRIVATE 0x22 +#define I2O_SOFTWARE_MODULE_IOP_CONFIG 0x23 + +/* + * Vendors + */ +#define I2O_VENDOR_DPT 0x001b /* * DPT / Adaptec specific values for i2o_sg_io_hdr flags. diff --git a/include/linux/i2o.h b/include/linux/i2o.h index 2039a87c2b91..be937d0372a7 100644 --- a/include/linux/i2o.h +++ b/include/linux/i2o.h @@ -119,12 +119,21 @@ struct i2o_driver { }; /* - * Contains all information which are necessary for DMA operations + * Contains DMA mapped address information */ struct i2o_dma { void *virt; dma_addr_t phys; - u32 len; + size_t len; +}; + +/* + * Contains IO mapped address information + */ +struct i2o_io { + void __iomem *virt; + unsigned long phys; + unsigned long len; }; /* @@ -173,8 +182,8 @@ struct i2o_controller { struct semaphore lct_lock; /* Lock for LCT updates */ struct i2o_dma status_block; /* IOP status block */ - struct i2o_dma base; /* controller messaging unit */ - struct i2o_dma in_queue; /* inbound message queue Host->IOP */ + struct i2o_io base; /* controller messaging unit */ + struct i2o_io in_queue; /* inbound message queue Host->IOP */ struct i2o_dma out_queue; /* outbound message queue IOP->Host */ unsigned int battery:1; /* Has a battery backup */ @@ -185,6 +194,7 @@ struct i2o_controller { struct resource mem_resource; /* Mem resource allocated to the IOP */ struct device device; + struct class_device classdev; /* I2O controller class */ struct i2o_device *exec; /* Executive */ #if BITS_PER_LONG == 64 spinlock_t context_list_lock; /* lock for context_list */ @@ -235,9 +245,10 @@ struct i2o_sys_tbl { extern struct list_head i2o_controllers; /* Message functions */ -static inline u32 i2o_msg_get(struct i2o_controller *, struct i2o_message __iomem **); -extern u32 i2o_msg_get_wait(struct i2o_controller *, struct i2o_message __iomem **, - int); +static inline u32 i2o_msg_get(struct i2o_controller *, + struct i2o_message __iomem **); +extern u32 i2o_msg_get_wait(struct i2o_controller *, + struct i2o_message __iomem **, int); static inline void i2o_msg_post(struct i2o_controller *, u32); static inline int i2o_msg_post_wait(struct i2o_controller *, u32, unsigned long); @@ -638,14 +649,12 @@ extern int i2o_exec_lct_get(struct i2o_controller *); * available returns I2O_QUEUE_EMPTY and msg is leaved untouched. */ static inline u32 i2o_msg_get(struct i2o_controller *c, - struct i2o_message __iomem **msg) + struct i2o_message __iomem ** msg) { u32 m = readl(c->in_port); - if (m != I2O_QUEUE_EMPTY) { + if (m != I2O_QUEUE_EMPTY) *msg = c->in_queue.virt + m; - rmb(); - } return m; }; @@ -659,7 +668,6 @@ static inline u32 i2o_msg_get(struct i2o_controller *c, */ static inline void i2o_msg_post(struct i2o_controller *c, u32 m) { - wmb(); writel(m, c->in_port); }; @@ -706,14 +714,11 @@ static inline void i2o_flush_reply(struct i2o_controller *c, u32 m) * work for sender side messages as they are ioremap objects * provided by the I2O controller. */ -static inline struct i2o_message __iomem *i2o_msg_out_to_virt(struct - i2o_controller *c, - u32 m) +static inline struct i2o_message *i2o_msg_out_to_virt(struct i2o_controller *c, + u32 m) { - if (unlikely - (m < c->out_queue.phys - || m >= c->out_queue.phys + c->out_queue.len)) - return NULL; + BUG_ON(m < c->out_queue.phys + || m >= c->out_queue.phys + c->out_queue.len); return c->out_queue.virt + (m - c->out_queue.phys); }; @@ -729,69 +734,13 @@ static inline struct i2o_message __iomem *i2o_msg_out_to_virt(struct * work for receive side messages as they are kmalloc objects * in a different pool. */ -static inline struct i2o_message __iomem *i2o_msg_in_to_virt(struct i2o_controller *c, - u32 m) +static inline struct i2o_message __iomem *i2o_msg_in_to_virt(struct + i2o_controller *c, + u32 m) { return c->in_queue.virt + m; }; -/** - * i2o_dma_alloc - Allocate DMA memory - * @dev: struct device pointer to the PCI device of the I2O controller - * @addr: i2o_dma struct which should get the DMA buffer - * @len: length of the new DMA memory - * @gfp_mask: GFP mask - * - * Allocate a coherent DMA memory and write the pointers into addr. - * - * Returns 0 on success or -ENOMEM on failure. - */ -static inline int i2o_dma_alloc(struct device *dev, struct i2o_dma *addr, - size_t len, unsigned int gfp_mask) -{ - struct pci_dev *pdev = to_pci_dev(dev); - int dma_64 = 0; - - if ((sizeof(dma_addr_t) > 4) && (pdev->dma_mask == DMA_64BIT_MASK)) { - dma_64 = 1; - if(pci_set_dma_mask(pdev, DMA_32BIT_MASK)) - return -ENOMEM; - } - - addr->virt = dma_alloc_coherent(dev, len, &addr->phys, gfp_mask); - - if ((sizeof(dma_addr_t) > 4) && dma_64) - if(pci_set_dma_mask(pdev, DMA_64BIT_MASK)) - printk(KERN_WARNING "i2o: unable to set 64-bit DMA"); - - if (!addr->virt) - return -ENOMEM; - - memset(addr->virt, 0, len); - addr->len = len; - - return 0; -}; - -/** - * i2o_dma_free - Free DMA memory - * @dev: struct device pointer to the PCI device of the I2O controller - * @addr: i2o_dma struct which contains the DMA buffer - * - * Free a coherent DMA memory and set virtual address of addr to NULL. - */ -static inline void i2o_dma_free(struct device *dev, struct i2o_dma *addr) -{ - if (addr->virt) { - if (addr->phys) - dma_free_coherent(dev, addr->len, addr->virt, - addr->phys); - else - kfree(addr->virt); - addr->virt = NULL; - } -}; - /* * Endian handling wrapped into the macro - keeps the core code * cleaner. @@ -1141,16 +1090,13 @@ extern void i2o_debug_state(struct i2o_controller *c); #define ELEVEN_WORD_MSG_SIZE 0x000B0000 #define I2O_MESSAGE_SIZE(x) ((x)<<16) -/* Special TID Assignments */ - +/* special TID assignments */ #define ADAPTER_TID 0 #define HOST_TID 1 -#define MSG_FRAME_SIZE 128 /* i2o_scsi assumes >= 32 */ -#define SG_TABLESIZE 30 -#define NMBR_MSG_FRAMES 128 - -#define MSG_POOL_SIZE (MSG_FRAME_SIZE*NMBR_MSG_FRAMES*sizeof(u32)) +/* outbound queue defines */ +#define I2O_MAX_OUTBOUND_MSG_FRAMES 128 +#define I2O_OUTBOUND_MSG_FRAME_SIZE 128 /* in 32-bit words */ #define I2O_POST_WAIT_OK 0 #define I2O_POST_WAIT_TIMEOUT -ETIMEDOUT |