summaryrefslogtreecommitdiffstats
path: root/drivers/message/i2o
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/message/i2o')
-rw-r--r--drivers/message/i2o/device.c9
-rw-r--r--drivers/message/i2o/driver.c46
-rw-r--r--drivers/message/i2o/exec-osm.c47
-rw-r--r--drivers/message/i2o/i2o_block.c211
-rw-r--r--drivers/message/i2o/i2o_block.h2
-rw-r--r--drivers/message/i2o/i2o_config.c118
-rw-r--r--drivers/message/i2o/i2o_scsi.c31
-rw-r--r--drivers/message/i2o/iop.c87
-rw-r--r--drivers/message/i2o/pci.c67
9 files changed, 340 insertions, 278 deletions
diff --git a/drivers/message/i2o/device.c b/drivers/message/i2o/device.c
index 280627ae6cf7..f1b7eb63d54b 100644
--- a/drivers/message/i2o/device.c
+++ b/drivers/message/i2o/device.c
@@ -282,8 +282,7 @@ int i2o_device_parse_lct(struct i2o_controller *c)
down(&c->lct_lock);
- if (c->lct)
- kfree(c->lct);
+ kfree(c->lct);
lct = c->dlct.virt;
@@ -447,8 +446,8 @@ static struct class_interface i2o_device_class_interface = {
* ResultCount, ErrorInfoSize, BlockStatus and BlockSize.
*/
-int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist,
- int oplen, void *reslist, int reslen)
+static int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist,
+ int oplen, void *reslist, int reslen)
{
struct i2o_message __iomem *msg;
u32 m;
@@ -540,7 +539,7 @@ int i2o_parm_field_get(struct i2o_device *i2o_dev, int group, int field,
opblk[4] = -1;
size = i2o_parm_issue(i2o_dev, I2O_CMD_UTIL_PARAMS_GET, opblk,
- sizeof(opblk), resblk, sizeof(resblk));
+ sizeof(opblk), resblk, buflen + 8);
memcpy(buf, resblk + 8, buflen); /* cut off header */
diff --git a/drivers/message/i2o/driver.c b/drivers/message/i2o/driver.c
index c71e68f70e7d..bebdd509b5d8 100644
--- a/drivers/message/i2o/driver.c
+++ b/drivers/message/i2o/driver.c
@@ -18,7 +18,7 @@
#include <linux/rwsem.h>
#include <linux/i2o.h>
-#define OSM_NAME "core"
+#define OSM_NAME "i2o"
/* max_drivers - Maximum I2O drivers (OSMs) which could be registered */
unsigned int i2o_max_drivers = I2O_MAX_DRIVERS;
@@ -78,17 +78,16 @@ int i2o_driver_register(struct i2o_driver *drv)
int rc = 0;
unsigned long flags;
- pr_debug("i2o: Register driver %s\n", drv->name);
+ osm_debug("Register driver %s\n", drv->name);
if (drv->event) {
drv->event_queue = create_workqueue(drv->name);
if (!drv->event_queue) {
- printk(KERN_ERR "i2o: Could not initialize event queue "
- "for driver %s\n", drv->name);
+ osm_err("Could not initialize event queue for driver "
+ "%s\n", drv->name);
return -EFAULT;
}
- pr_debug("i2o: Event queue initialized for driver %s\n",
- drv->name);
+ osm_debug("Event queue initialized for driver %s\n", drv->name);
} else
drv->event_queue = NULL;
@@ -99,8 +98,8 @@ int i2o_driver_register(struct i2o_driver *drv)
for (i = 0; i2o_drivers[i]; i++)
if (i >= i2o_max_drivers) {
- printk(KERN_ERR "i2o: too many drivers registered, "
- "increase max_drivers\n");
+ osm_err("too many drivers registered, increase "
+ "max_drivers\n");
spin_unlock_irqrestore(&i2o_drivers_lock, flags);
return -EFAULT;
}
@@ -110,8 +109,7 @@ int i2o_driver_register(struct i2o_driver *drv)
spin_unlock_irqrestore(&i2o_drivers_lock, flags);
- pr_debug("i2o: driver %s gets context id %d\n", drv->name,
- drv->context);
+ osm_debug("driver %s gets context id %d\n", drv->name, drv->context);
list_for_each_entry(c, &i2o_controllers, list) {
struct i2o_device *i2o_dev;
@@ -141,7 +139,7 @@ void i2o_driver_unregister(struct i2o_driver *drv)
struct i2o_controller *c;
unsigned long flags;
- pr_debug("i2o: unregister driver %s\n", drv->name);
+ osm_debug("unregister driver %s\n", drv->name);
driver_unregister(&drv->driver);
@@ -161,7 +159,7 @@ void i2o_driver_unregister(struct i2o_driver *drv)
if (drv->event_queue) {
destroy_workqueue(drv->event_queue);
drv->event_queue = NULL;
- pr_debug("i2o: event queue removed for %s\n", drv->name);
+ osm_debug("event queue removed for %s\n", drv->name);
}
};
@@ -178,15 +176,15 @@ void i2o_driver_unregister(struct i2o_driver *drv)
* on success and if the message should be flushed afterwords. Returns
* negative error code on failure (the message will be flushed too).
*/
-int i2o_driver_dispatch(struct i2o_controller *c, u32 m,
- struct i2o_message __iomem *msg)
+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 = readl(&msg->u.s.icntxt);
if (unlikely(context >= i2o_max_drivers)) {
- printk(KERN_WARNING "%s: Spurious reply to unknown driver "
- "%d\n", c->name, readl(&msg->u.s.icntxt));
+ osm_warn("%s: Spurious reply to unknown driver %d\n", c->name,
+ context);
return -EIO;
}
@@ -195,7 +193,8 @@ int i2o_driver_dispatch(struct i2o_controller *c, u32 m,
spin_unlock(&i2o_drivers_lock);
if (unlikely(!drv)) {
- osm_warn("Spurious reply to unknown driver %d\n", context);
+ osm_warn("%s: Spurious reply to unknown driver %d\n", c->name,
+ context);
return -EIO;
}
@@ -207,6 +206,9 @@ int i2o_driver_dispatch(struct i2o_controller *c, u32 m,
osm_debug("event received from device %d\n", tid);
+ if (!drv->event)
+ return -EIO;
+
/* cut of header from message size (in 32-bit words) */
size = (readl(&msg->u.head[0]) >> 16) - 5;
@@ -231,8 +233,8 @@ int i2o_driver_dispatch(struct i2o_controller *c, u32 m,
}
if (unlikely(!drv->reply)) {
- pr_debug("%s: Reply to driver %s, but no reply function"
- " defined!\n", c->name, drv->name);
+ osm_debug("%s: Reply to driver %s, but no reply function"
+ " defined!\n", c->name, drv->name);
return -EIO;
}
@@ -333,11 +335,11 @@ int __init i2o_driver_init(void)
if ((i2o_max_drivers < 2) || (i2o_max_drivers > 64) ||
((i2o_max_drivers ^ (i2o_max_drivers - 1)) !=
(2 * i2o_max_drivers - 1))) {
- printk(KERN_WARNING "i2o: max_drivers set to %d, but must be "
- ">=2 and <= 64 and a power of 2\n", i2o_max_drivers);
+ osm_warn("max_drivers set to %d, but must be >=2 and <= 64 and "
+ "a power of 2\n", i2o_max_drivers);
i2o_max_drivers = I2O_MAX_DRIVERS;
}
- printk(KERN_INFO "i2o: max drivers = %d\n", i2o_max_drivers);
+ osm_info("max drivers = %d\n", i2o_max_drivers);
i2o_drivers =
kmalloc(i2o_max_drivers * sizeof(*i2o_drivers), GFP_KERNEL);
diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c
index 1e28e886f1ca..5581344fbba6 100644
--- a/drivers/message/i2o/exec-osm.c
+++ b/drivers/message/i2o/exec-osm.c
@@ -108,7 +108,8 @@ static void i2o_exec_wait_free(struct i2o_exec_wait *wait)
* buffer must not be freed. Instead the event completion will free them
* for you. In all other cases the buffer are your problem.
*
- * Returns 0 on success or negative error code on failure.
+ * Returns 0 on success, negative error code on timeout or positive error
+ * code from reply.
*/
int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long
timeout, struct i2o_dma *dma)
@@ -116,7 +117,7 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long
DECLARE_WAIT_QUEUE_HEAD(wq);
struct i2o_exec_wait *wait;
static u32 tcntxt = 0x80000000;
- struct i2o_message __iomem *msg = c->in_queue.virt + m;
+ struct i2o_message __iomem *msg = i2o_msg_in_to_virt(c, m);
int rc = 0;
wait = i2o_exec_wait_alloc();
@@ -161,8 +162,7 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long
barrier();
if (wait->complete) {
- if (readl(&wait->msg->body[0]) >> 24)
- rc = readl(&wait->msg->body[0]) & 0xff;
+ rc = readl(&wait->msg->body[0]) >> 24;
i2o_flush_reply(c, wait->m);
i2o_exec_wait_free(wait);
} else {
@@ -187,6 +187,7 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long
* @c: I2O controller which answers
* @m: message id
* @msg: pointer to the I2O reply message
+ * @context: transaction context of request
*
* This function is called in interrupt context only. If the reply reached
* before the timeout, the i2o_exec_wait struct is filled with the message
@@ -201,14 +202,12 @@ 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)
+ struct i2o_message __iomem *msg,
+ u32 context)
{
struct i2o_exec_wait *wait, *tmp;
static spinlock_t lock = SPIN_LOCK_UNLOCKED;
int rc = 1;
- u32 context;
-
- context = readl(&msg->u.s.tcntxt);
/*
* We need to search through the i2o_exec_wait_list to see if the given
@@ -251,7 +250,7 @@ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m,
spin_unlock(&lock);
- pr_debug("%s: Bogus reply in POST WAIT (tr-context: %08x)!\n", c->name,
+ osm_warn("%s: Bogus reply in POST WAIT (tr-context: %08x)!\n", c->name,
context);
return -1;
@@ -321,29 +320,35 @@ 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 *msg)
+ struct i2o_message __iomem *msg)
{
- if (le32_to_cpu(msg->u.head[0]) & MSG_FAIL) { // Fail bit is set
- struct i2o_message __iomem *pmsg; /* preserved message */
+ u32 context;
+
+ if (readl(&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.
+ */
+ struct i2o_message __iomem *pmsg;
u32 pm;
- pm = le32_to_cpu(msg->body[3]);
+ pm = readl(&msg->body[3]);
pmsg = i2o_msg_in_to_virt(c, pm);
i2o_report_status(KERN_INFO, "i2o_core", msg);
- /* Release the preserved msg by resubmitting it as a NOP */
- i2o_msg_nop(c, pm);
+ context = readl(&pmsg->u.s.tcntxt);
- /* If reply to i2o_post_wait failed, return causes a timeout */
- return -1;
- }
+ /* Release the preserved msg */
+ i2o_msg_nop(c, pm);
+ } else
+ context = readl(&msg->u.s.tcntxt);
- if (le32_to_cpu(msg->u.s.tcntxt) & 0x80000000)
- return i2o_msg_post_wait_complete(c, m, msg);
+ if (context & 0x80000000)
+ return i2o_msg_post_wait_complete(c, m, msg, context);
- if ((le32_to_cpu(msg->u.head[1]) >> 24) == I2O_CMD_LCT_NOTIFY) {
+ if ((readl(&msg->u.head[1]) >> 24) == I2O_CMD_LCT_NOTIFY) {
struct work_struct *work;
pr_debug("%s: LCT notify received\n", c->name);
diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c
index 4830b7759061..e69421e36ac5 100644
--- a/drivers/message/i2o/i2o_block.c
+++ b/drivers/message/i2o/i2o_block.c
@@ -104,7 +104,8 @@ static int i2o_block_remove(struct device *dev)
struct i2o_device *i2o_dev = to_i2o_device(dev);
struct i2o_block_device *i2o_blk_dev = dev_get_drvdata(dev);
- osm_info("Device removed %s\n", i2o_blk_dev->gd->disk_name);
+ osm_info("device removed (TID: %03x): %s\n", i2o_dev->lct_data.tid,
+ i2o_blk_dev->gd->disk_name);
i2o_event_register(i2o_dev, &i2o_block_driver, 0, 0);
@@ -400,71 +401,62 @@ static void i2o_block_delayed_request_fn(void *delayed_request)
};
/**
- * i2o_block_reply - Block OSM reply handler.
- * @c: I2O controller from which the message arrives
- * @m: message id of reply
- * qmsg: the actuall I2O message reply
+ * i2o_block_end_request - Post-processing of completed commands
+ * @req: request which should be completed
+ * @uptodate: 1 for success, 0 for I/O error, < 0 for specific error
+ * @nr_bytes: number of bytes to complete
*
- * This function gets all the message replies.
+ * Mark the request as complete. The lock must not be held when entering.
*
*/
-static int i2o_block_reply(struct i2o_controller *c, u32 m,
- struct i2o_message *msg)
+static void i2o_block_end_request(struct request *req, int uptodate,
+ int nr_bytes)
{
- struct i2o_block_request *ireq;
- struct request *req;
- struct i2o_block_device *dev;
- struct request_queue *q;
- u8 st;
+ struct i2o_block_request *ireq = req->special;
+ struct i2o_block_device *dev = ireq->i2o_blk_dev;
+ request_queue_t *q = dev->gd->queue;
unsigned long flags;
- /* FAILed message */
- if (unlikely(le32_to_cpu(msg->u.head[0]) & (1 << 13))) {
- struct i2o_message *pmsg;
- u32 pm;
-
- /*
- * FAILed message from controller
- * We increment the error count and abort it
- *
- * In theory this will never happen. The I2O block class
- * specification states that block devices never return
- * FAILs but instead use the REQ status field...but
- * better be on the safe side since no one really follows
- * the spec to the book :)
- */
- pm = le32_to_cpu(msg->body[3]);
- pmsg = i2o_msg_in_to_virt(c, pm);
+ if (end_that_request_chunk(req, uptodate, nr_bytes)) {
+ int leftover = (req->hard_nr_sectors << 9);
- req = i2o_cntxt_list_get(c, le32_to_cpu(pmsg->u.s.tcntxt));
- if (unlikely(!req)) {
- osm_err("NULL reply received!\n");
- return -1;
- }
+ if (blk_pc_request(req))
+ leftover = req->data_len;
- ireq = req->special;
- dev = ireq->i2o_blk_dev;
- q = dev->gd->queue;
+ if (end_io_error(uptodate))
+ end_that_request_chunk(req, 0, leftover);
+ }
- req->errors++;
+ add_disk_randomness(req->rq_disk);
- spin_lock_irqsave(q->queue_lock, flags);
+ spin_lock_irqsave(q->queue_lock, flags);
- while (end_that_request_chunk(req, !req->errors,
- le32_to_cpu(pmsg->body[1]))) ;
- end_that_request_last(req);
+ end_that_request_last(req);
+ dev->open_queue_depth--;
+ list_del(&ireq->queue);
- dev->open_queue_depth--;
- list_del(&ireq->queue);
- blk_start_queue(q);
+ blk_start_queue(q);
- spin_unlock_irqrestore(q->queue_lock, flags);
+ spin_unlock_irqrestore(q->queue_lock, flags);
- /* Now flush the message by making it a NOP */
- i2o_msg_nop(c, pm);
+ i2o_block_sglist_free(ireq);
+ i2o_block_request_free(ireq);
+};
- return -1;
- }
+/**
+ * i2o_block_reply - Block OSM reply handler.
+ * @c: I2O controller from which the message arrives
+ * @m: message id of reply
+ * qmsg: the actuall I2O message reply
+ *
+ * This function gets all the message replies.
+ *
+ */
+static int i2o_block_reply(struct i2o_controller *c, u32 m,
+ struct i2o_message *msg)
+{
+ struct request *req;
+ int uptodate = 1;
req = i2o_cntxt_list_get(c, le32_to_cpu(msg->u.s.tcntxt));
if (unlikely(!req)) {
@@ -472,61 +464,13 @@ static int i2o_block_reply(struct i2o_controller *c, u32 m,
return -1;
}
- ireq = req->special;
- dev = ireq->i2o_blk_dev;
- q = dev->gd->queue;
-
- if (unlikely(!dev->i2o_dev)) {
- /*
- * This is HACK, but Intel Integrated RAID allows user
- * to delete a volume that is claimed, locked, and in use
- * by the OS. We have to check for a reply from a
- * non-existent device and flag it as an error or the system
- * goes kaput...
- */
- req->errors++;
- osm_warn("Data transfer to deleted device!\n");
- spin_lock_irqsave(q->queue_lock, flags);
- while (end_that_request_chunk
- (req, !req->errors, le32_to_cpu(msg->body[1]))) ;
- end_that_request_last(req);
-
- dev->open_queue_depth--;
- list_del(&ireq->queue);
- blk_start_queue(q);
-
- spin_unlock_irqrestore(q->queue_lock, flags);
- return -1;
- }
-
/*
* Lets see what is cooking. We stuffed the
* request in the context.
*/
- st = le32_to_cpu(msg->body[0]) >> 24;
-
- if (st != 0) {
- int err;
- char *bsa_errors[] = {
- "Success",
- "Media Error",
- "Failure communicating to device",
- "Device Failure",
- "Device is not ready",
- "Media not present",
- "Media is locked by another user",
- "Media has failed",
- "Failure communicating to device",
- "Device bus failure",
- "Device is locked by another user",
- "Device is write protected",
- "Device has reset",
- "Volume has changed, waiting for acknowledgement"
- };
-
- err = le32_to_cpu(msg->body[0]) & 0xffff;
-
+ if ((le32_to_cpu(msg->body[0]) >> 24) != 0) {
+ u32 status = le32_to_cpu(msg->body[0]);
/*
* Device not ready means two things. One is that the
* the thing went offline (but not a removal media)
@@ -539,40 +483,23 @@ static int i2o_block_reply(struct i2o_controller *c, u32 m,
* Don't stick a supertrak100 into cache aggressive modes
*/
- osm_err("block-osm: /dev/%s error: %s", dev->gd->disk_name,
- bsa_errors[le32_to_cpu(msg->body[0]) & 0xffff]);
- if (le32_to_cpu(msg->body[0]) & 0x00ff0000)
- printk(KERN_ERR " - DDM attempted %d retries",
- (le32_to_cpu(msg->body[0]) >> 16) & 0x00ff);
- printk(KERN_ERR ".\n");
- req->errors++;
- } else
- req->errors = 0;
-
- if (!end_that_request_chunk
- (req, !req->errors, le32_to_cpu(msg->body[1]))) {
- add_disk_randomness(req->rq_disk);
- spin_lock_irqsave(q->queue_lock, flags);
+ osm_err("%03x error status: %02x, detailed status: %04x\n",
+ (le32_to_cpu(msg->u.head[1]) >> 12 & 0xfff),
+ status >> 24, status & 0xffff);
- end_that_request_last(req);
+ req->errors++;
- dev->open_queue_depth--;
- list_del(&ireq->queue);
- blk_start_queue(q);
+ uptodate = 0;
+ }
- spin_unlock_irqrestore(q->queue_lock, flags);
-
- i2o_block_sglist_free(ireq);
- i2o_block_request_free(ireq);
- } else
- osm_err("still remaining chunks\n");
+ i2o_block_end_request(req, uptodate, le32_to_cpu(msg->body[1]));
return 1;
};
static void i2o_block_event(struct i2o_event *evt)
{
- osm_info("block-osm: event received\n");
+ osm_info("event received\n");
kfree(evt);
};
@@ -875,9 +802,7 @@ static int i2o_block_transfer(struct request *req)
sg++;
}
- writel(I2O_MESSAGE_SIZE
- (((unsigned long)mptr -
- (unsigned long)&msg->u.head[0]) >> 2) | SGL_OFFSET_8,
+ writel(I2O_MESSAGE_SIZE(mptr - &msg->u.head[0]) | SGL_OFFSET_8,
&msg->u.head[0]);
list_add_tail(&ireq->queue, &dev->open_queue);
@@ -1048,7 +973,6 @@ static int i2o_block_probe(struct device *dev)
int rc;
u64 size;
u32 blocksize;
- u16 power;
u32 flags, status;
int segments;
@@ -1058,8 +982,6 @@ static int i2o_block_probe(struct device *dev)
return -ENODEV;
}
- osm_info("New device detected (TID: %03x)\n", i2o_dev->lct_data.tid);
-
if (i2o_device_claim(i2o_dev)) {
osm_warn("Unable to claim device. Installation aborted\n");
rc = -EFAULT;
@@ -1111,15 +1033,21 @@ static int i2o_block_probe(struct device *dev)
* Ask for the current media data. If that isn't supported
* then we ask for the device capacity data
*/
- if (i2o_parm_field_get(i2o_dev, 0x0004, 1, &blocksize, 4) != 0
- || i2o_parm_field_get(i2o_dev, 0x0004, 0, &size, 8) != 0) {
- i2o_parm_field_get(i2o_dev, 0x0000, 3, &blocksize, 4);
- i2o_parm_field_get(i2o_dev, 0x0000, 4, &size, 8);
- }
- osm_debug("blocksize = %d\n", blocksize);
+ if (!i2o_parm_field_get(i2o_dev, 0x0004, 0, &size, 8))
+ if (!i2o_parm_field_get(i2o_dev, 0x0000, 4, &size, 8)) {
+ osm_warn("could not get size of %s\n", gd->disk_name);
+ size = 0;
+ }
- if (i2o_parm_field_get(i2o_dev, 0x0000, 2, &power, 2))
- power = 0;
+ if (!i2o_parm_field_get(i2o_dev, 0x0004, 1, &blocksize, 4))
+ if (!i2o_parm_field_get(i2o_dev, 0x0000, 3, &blocksize, 4)) {
+ osm_warn("unable to get blocksize of %s\n",
+ gd->disk_name);
+ blocksize = 0;
+ }
+
+ if (!i2o_parm_field_get(i2o_dev, 0x0000, 2, &i2o_blk_dev->power, 2))
+ i2o_blk_dev->power = 0;
i2o_parm_field_get(i2o_dev, 0x0000, 5, &flags, 4);
i2o_parm_field_get(i2o_dev, 0x0000, 6, &status, 4);
@@ -1131,6 +1059,9 @@ static int i2o_block_probe(struct device *dev)
unit++;
+ osm_info("device added (TID: %03x): %s\n", i2o_dev->lct_data.tid,
+ i2o_blk_dev->gd->disk_name);
+
return 0;
claim_release:
diff --git a/drivers/message/i2o/i2o_block.h b/drivers/message/i2o/i2o_block.h
index ddd9a15679c0..712111ffa638 100644
--- a/drivers/message/i2o/i2o_block.h
+++ b/drivers/message/i2o/i2o_block.h
@@ -74,7 +74,7 @@ struct i2o_block_device {
int rcache; /* read cache flags */
int wcache; /* write cache flags */
int flags;
- int power; /* power state */
+ u16 power; /* power state */
int media_change_flag; /* media changed flag */
};
diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c
index 46d373287a30..383e89a5c9f0 100644
--- a/drivers/message/i2o/i2o_config.c
+++ b/drivers/message/i2o/i2o_config.c
@@ -80,13 +80,123 @@ struct i2o_cfg_info {
static struct i2o_cfg_info *open_files = NULL;
static ulong i2o_cfg_info_id = 0;
-/*
- * Each of these describes an i2o message handler. They are
- * multiplexed by the i2o_core code
+/**
+ * i2o_config_read_hrt - Returns the HRT of the controller
+ * @kob: kernel object handle
+ * @buf: buffer into which the HRT should be copied
+ * @off: file offset
+ * @count: number of bytes to read
+ *
+ * Put @count bytes starting at @off into @buf from the HRT of the I2O
+ * controller corresponding to @kobj.
+ *
+ * Returns number of bytes copied into buffer.
+ */
+static ssize_t i2o_config_read_hrt(struct kobject *kobj, char *buf,
+ loff_t offset, size_t count)
+{
+ struct i2o_controller *c = to_i2o_controller(container_of(kobj,
+ struct device,
+ kobj));
+ i2o_hrt *hrt = c->hrt.virt;
+
+ u32 size = (hrt->num_entries * hrt->entry_len + 2) * 4;
+
+ if(offset > size)
+ return 0;
+
+ if(offset + count > size)
+ count = size - offset;
+
+ memcpy(buf, (u8 *) hrt + offset, count);
+
+ return count;
+};
+
+/**
+ * i2o_config_read_lct - Returns the LCT of the controller
+ * @kob: kernel object handle
+ * @buf: buffer into which the LCT should be copied
+ * @off: file offset
+ * @count: number of bytes to read
+ *
+ * Put @count bytes starting at @off into @buf from the LCT of the I2O
+ * controller corresponding to @kobj.
+ *
+ * Returns number of bytes copied into buffer.
+ */
+static ssize_t i2o_config_read_lct(struct kobject *kobj, char *buf,
+ loff_t offset, size_t count)
+{
+ struct i2o_controller *c = to_i2o_controller(container_of(kobj,
+ struct device,
+ kobj));
+ u32 size = c->lct->table_size * 4;
+
+ if(offset > size)
+ return 0;
+
+ if(offset + count > size)
+ count = size - offset;
+
+ memcpy(buf, (u8 *) c->lct + offset, count);
+
+ return count;
+};
+
+/* attribute for HRT in sysfs */
+static struct bin_attribute i2o_config_hrt_attr = {
+ .attr = {
+ .name = "hrt",
+ .mode = S_IRUGO,
+ .owner = THIS_MODULE
+ },
+ .size = 0,
+ .read = i2o_config_read_hrt
+};
+
+/* attribute for LCT in sysfs */
+static struct bin_attribute i2o_config_lct_attr = {
+ .attr = {
+ .name = "lct",
+ .mode = S_IRUGO,
+ .owner = THIS_MODULE
+ },
+ .size = 0,
+ .read = i2o_config_read_lct
+};
+
+/**
+ * i2o_config_notify_controller_add - Notify of added controller
+ * @c: the controller which was added
+ *
+ * If a I2O controller is added, we catch the notification to add sysfs
+ * entries.
+ */
+static void i2o_config_notify_controller_add(struct i2o_controller *c)
+{
+ sysfs_create_bin_file(&(c->device.kobj), &i2o_config_hrt_attr);
+ sysfs_create_bin_file(&(c->device.kobj), &i2o_config_lct_attr);
+};
+
+/**
+ * i2o_config_notify_controller_remove - Notify of removed controller
+ * @c: the controller which was removed
+ *
+ * If a I2O controller is removed, we catch the notification to remove the
+ * sysfs entries.
*/
+static void i2o_config_notify_controller_remove(struct i2o_controller *c)
+{
+ sysfs_remove_bin_file(&c->device.kobj, &i2o_config_lct_attr);
+ sysfs_remove_bin_file(&c->device.kobj, &i2o_config_hrt_attr);
+};
+/* Config OSM driver struct */
static struct i2o_driver i2o_config_driver = {
- .name = OSM_NAME
+ .name = OSM_NAME,
+ .notify_controller_add = i2o_config_notify_controller_add,
+ .notify_controller_remove = i2o_config_notify_controller_remove
};
static int i2o_cfg_getiops(unsigned long arg)
diff --git a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c
index af40f1c1ec77..812c29ec86d3 100644
--- a/drivers/message/i2o/i2o_scsi.c
+++ b/drivers/message/i2o/i2o_scsi.c
@@ -40,6 +40,7 @@
* Fix the resource management problems.
*/
+#define DEBUG 1
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
@@ -179,6 +180,8 @@ static int i2o_scsi_remove(struct device *dev)
struct i2o_scsi_host *i2o_shost;
struct scsi_device *scsi_dev;
+ osm_info("device removed (TID: %03x)\n", i2o_dev->lct_data.tid);
+
i2o_shost = i2o_scsi_get_host(c);
shost_for_each_device(scsi_dev, i2o_shost->scsi_host)
@@ -262,8 +265,8 @@ static int i2o_scsi_probe(struct device *dev)
return -EFAULT;
}
- osm_debug("added new SCSI device %03x (cannel: %d, id: %d, lun: %d)\n",
- i2o_dev->lct_data.tid, channel, id, (unsigned int)lun);
+ osm_info("device added (TID: %03x) channel: %d, id: %d, lun: %d\n",
+ i2o_dev->lct_data.tid, channel, id, (unsigned int)lun);
return 0;
};
@@ -439,8 +442,6 @@ static int i2o_scsi_reply(struct i2o_controller *c, u32 m,
cmd->result = DID_OK << 16 | ds;
- cmd->scsi_done(cmd);
-
dev = &c->pdev->dev;
if (cmd->use_sg)
dma_unmap_sg(dev, (struct scatterlist *)cmd->buffer,
@@ -449,6 +450,8 @@ static int i2o_scsi_reply(struct i2o_controller *c, u32 m,
dma_unmap_single(dev, (dma_addr_t) ((long)cmd->SCp.ptr),
cmd->request_bufflen, cmd->sc_data_direction);
+ cmd->scsi_done(cmd);
+
return 1;
};
@@ -502,7 +505,7 @@ static void i2o_scsi_notify_controller_remove(struct i2o_controller *c)
scsi_remove_host(i2o_shost->scsi_host);
scsi_host_put(i2o_shost->scsi_host);
- pr_info("I2O SCSI host removed\n");
+ osm_debug("I2O SCSI host removed\n");
};
/* SCSI OSM driver struct */
@@ -545,7 +548,7 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
u32 scsi_flags, sg_flags;
u32 __iomem *mptr;
u32 __iomem *lenptr;
- u32 len, reqlen;
+ u32 len;
int i;
/*
@@ -580,12 +583,12 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
if (m == I2O_QUEUE_EMPTY)
return SCSI_MLQUEUE_HOST_BUSY;
+ mptr = &msg->body[0];
+
/*
* Put together a scsi execscb message
*/
- len = SCpnt->request_bufflen;
-
switch (SCpnt->sc_data_direction) {
case PCI_DMA_NONE:
scsi_flags = 0x00000000; // DATA NO XFER
@@ -637,17 +640,13 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
*/
/* Direction, disconnect ok, tag, CDBLen */
- writel(scsi_flags | 0x20200000 | SCpnt->cmd_len, &msg->body[0]);
-
- mptr = &msg->body[1];
+ writel(scsi_flags | 0x20200000 | SCpnt->cmd_len, mptr ++);
/* Write SCSI command into the message - always 16 byte block */
memcpy_toio(mptr, SCpnt->cmnd, 16);
mptr += 4;
lenptr = mptr++; /* Remember me - fill in when we know */
- reqlen = 12; // SINGLE SGE
-
/* Now fill in the SGList and command */
if (SCpnt->use_sg) {
struct scatterlist *sg;
@@ -671,7 +670,6 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
sg++;
}
- reqlen = mptr - &msg->u.head[0];
writel(len, lenptr);
} else {
len = SCpnt->request_bufflen;
@@ -691,12 +689,11 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
sg_flags |= 0xC0000000;
writel(sg_flags | SCpnt->request_bufflen, mptr++);
writel(dma_addr, mptr++);
- } else
- reqlen = 9;
+ }
}
/* Stick the headers on */
- writel(reqlen << 16 | SGL_OFFSET_10, &msg->u.head[0]);
+ writel((mptr - &msg->u.head[0]) << 16 | SGL_OFFSET_10, &msg->u.head[0]);
/* Queue the message */
i2o_msg_post(c, m);
diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c
index 50c8cedf7a2d..62b0d8bed186 100644
--- a/drivers/message/i2o/iop.c
+++ b/drivers/message/i2o/iop.c
@@ -68,7 +68,7 @@ extern void i2o_device_exit(void);
*/
void i2o_msg_nop(struct i2o_controller *c, u32 m)
{
- struct i2o_message __iomem *msg = c->in_queue.virt + m;
+ struct i2o_message __iomem *msg = i2o_msg_in_to_virt(c, m);
writel(THREE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
writel(I2O_CMD_UTIL_NOP << 24 | HOST_TID << 12 | ADAPTER_TID,
@@ -452,8 +452,6 @@ static int i2o_iop_clear(struct i2o_controller *c)
/* Enable all IOPs */
i2o_iop_enable_all();
- i2o_status_get(c);
-
return rc;
}
@@ -591,12 +589,11 @@ static int i2o_iop_init_outbound_queue(struct i2o_controller *c)
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]);
writel(MSG_FRAME_SIZE << 16 | 0x80, &msg->body[1]); /* Outbound msg frame
size in words and Initcode */
@@ -891,8 +888,12 @@ void i2o_iop_remove(struct i2o_controller *c)
list_for_each_entry_safe(dev, tmp, &c->devices, list)
i2o_device_remove(dev);
+ device_del(&c->device);
+
/* Ask the IOP to switch to RESET state */
i2o_iop_reset(c);
+
+ put_device(&c->device);
}
/**
@@ -971,8 +972,10 @@ static int i2o_systab_build(void)
systab->iops[count].frame_size = sb->inbound_frame_size;
systab->iops[count].last_changed = change_ind;
systab->iops[count].iop_capabilities = sb->iop_capabilities;
- systab->iops[count].inbound_low = i2o_ptr_low(c->post_port);
- systab->iops[count].inbound_high = i2o_ptr_high(c->post_port);
+ systab->iops[count].inbound_low =
+ i2o_dma_low(c->base.phys + I2O_IN_PORT);
+ systab->iops[count].inbound_high =
+ i2o_dma_high(c->base.phys + I2O_IN_PORT);
count++;
}
@@ -1110,6 +1113,30 @@ static int i2o_hrt_get(struct i2o_controller *c)
}
/**
+ * i2o_iop_free - Free the i2o_controller struct
+ * @c: I2O controller to free
+ */
+void i2o_iop_free(struct i2o_controller *c)
+{
+ kfree(c);
+};
+
+
+/**
+ * i2o_iop_release - release the memory for a I2O controller
+ * @dev: I2O controller which should be released
+ *
+ * Release the allocated memory. This function is called if refcount of
+ * device reaches 0 automatically.
+ */
+static void i2o_iop_release(struct device *dev)
+{
+ struct i2o_controller *c = to_i2o_controller(dev);
+
+ i2o_iop_free(c);
+};
+
+/**
* i2o_iop_alloc - Allocate and initialize a i2o_controller struct
*
* Allocate the necessary memory for a i2o_controller struct and
@@ -1137,6 +1164,10 @@ struct i2o_controller *i2o_iop_alloc(void)
c->unit = unit++;
sprintf(c->name, "iop%d", c->unit);
+ device_initialize(&c->device);
+ c->device.release = &i2o_iop_release;
+ snprintf(c->device.bus_id, BUS_ID_SIZE, "iop%d", c->unit);
+
#if BITS_PER_LONG == 64
spin_lock_init(&c->context_list_lock);
atomic_set(&c->context_list_counter, 0);
@@ -1147,15 +1178,6 @@ struct i2o_controller *i2o_iop_alloc(void)
};
/**
- * i2o_iop_free - Free the i2o_controller struct
- * @c: I2O controller to free
- */
-void i2o_iop_free(struct i2o_controller *c)
-{
- kfree(c);
-};
-
-/**
* i2o_iop_add - Initialize the I2O controller and add him to the I2O core
* @c: controller
*
@@ -1168,6 +1190,11 @@ 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);
+ 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);
@@ -1175,30 +1202,23 @@ int i2o_iop_add(struct i2o_controller *c)
if ((rc = i2o_iop_activate(c))) {
printk(KERN_ERR "%s: could not activate controller\n",
c->name);
- i2o_iop_reset(c);
- return rc;
+ goto iop_reset;
}
pr_debug("%s: building sys table...\n", c->name);
- if ((rc = i2o_systab_build())) {
- i2o_iop_reset(c);
- return rc;
- }
+ if ((rc = i2o_systab_build()))
+ goto iop_reset;
pr_debug("%s: online controller...\n", c->name);
- if ((rc = i2o_iop_online(c))) {
- i2o_iop_reset(c);
- return rc;
- }
+ if ((rc = i2o_iop_online(c)))
+ goto iop_reset;
pr_debug("%s: getting LCT...\n", c->name);
- if ((rc = i2o_exec_lct_get(c))) {
- i2o_iop_reset(c);
- return rc;
- }
+ if ((rc = i2o_exec_lct_get(c)))
+ goto iop_reset;
list_add(&c->list, &i2o_controllers);
@@ -1207,6 +1227,11 @@ int i2o_iop_add(struct i2o_controller *c)
printk(KERN_INFO "%s: Controller added\n", c->name);
return 0;
+
+iop_reset:
+ i2o_iop_reset(c);
+
+ return rc;
};
/**
diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c
index 579a8b7a2120..f33fd81f77a4 100644
--- a/drivers/message/i2o/pci.c
+++ b/drivers/message/i2o/pci.c
@@ -38,8 +38,7 @@ 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,
- struct i2o_message *);
+extern int i2o_driver_dispatch(struct i2o_controller *, u32);
/* PCI device id table for all I2O controllers */
static struct pci_device_id __devinitdata i2o_pci_ids[] = {
@@ -89,8 +88,7 @@ static void i2o_pci_free(struct i2o_controller *c)
i2o_dma_free(dev, &c->out_queue);
i2o_dma_free(dev, &c->status_block);
- if (c->lct)
- kfree(c->lct);
+ kfree(c->lct);
i2o_dma_free(dev, &c->dlct);
i2o_dma_free(dev, &c->hrt);
i2o_dma_free(dev, &c->status);
@@ -187,9 +185,9 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c)
} else
c->in_queue = c->base;
- c->irq_mask = c->base.virt + 0x34;
- c->post_port = c->base.virt + 0x40;
- c->reply_port = c->base.virt + 0x44;
+ c->irq_mask = c->base.virt + I2O_IRQ_MASK;
+ c->in_port = c->base.virt + I2O_IN_PORT;
+ c->out_port = c->base.virt + I2O_OUT_PORT;
if (i2o_dma_alloc(dev, &c->status, 8, GFP_KERNEL)) {
i2o_pci_free(c);
@@ -235,49 +233,34 @@ static irqreturn_t i2o_pci_interrupt(int irq, void *dev_id, struct pt_regs *r)
{
struct i2o_controller *c = dev_id;
struct device *dev = &c->pdev->dev;
- struct i2o_message *m;
- u32 mv;
+ u32 mv = readl(c->out_port);
/*
* Old 960 steppings had a bug in the I2O unit that caused
* the queue to appear empty when it wasn't.
*/
- mv = I2O_REPLY_READ32(c);
if (mv == I2O_QUEUE_EMPTY) {
- mv = I2O_REPLY_READ32(c);
- if (unlikely(mv == I2O_QUEUE_EMPTY)) {
+ mv = readl(c->out_port);
+ if (unlikely(mv == I2O_QUEUE_EMPTY))
return IRQ_NONE;
- } else
+ else
pr_debug("%s: 960 bug detected\n", c->name);
}
while (mv != I2O_QUEUE_EMPTY) {
- /*
- * Map the message from the page frame map to kernel virtual.
- * Because bus_to_virt is deprecated, we have calculate the
- * location by ourself!
- */
- m = i2o_msg_out_to_virt(c, mv);
-
- /*
- * Ensure this message is seen coherently but cachably by
- * the processor
- */
- dma_sync_single_for_cpu(dev, mv, MSG_FRAME_SIZE * 4,
- PCI_DMA_FROMDEVICE);
-
/* dispatch it */
- if (i2o_driver_dispatch(c, mv, m))
+ if (i2o_driver_dispatch(c, mv))
/* flush it if result != 0 */
i2o_flush_reply(c, mv);
/*
* That 960 bug again...
*/
- mv = I2O_REPLY_READ32(c);
+ mv = readl(c->out_port);
if (mv == I2O_QUEUE_EMPTY)
- mv = I2O_REPLY_READ32(c);
+ mv = readl(c->out_port);
}
+
return IRQ_HANDLED;
}
@@ -294,7 +277,9 @@ static int i2o_pci_irq_enable(struct i2o_controller *c)
struct pci_dev *pdev = c->pdev;
int rc;
- I2O_IRQ_WRITE32(c, 0xffffffff);
+ wmb();
+ writel(0xffffffff, c->irq_mask);
+ wmb();
if (pdev->irq) {
rc = request_irq(pdev->irq, i2o_pci_interrupt, SA_SHIRQ,
@@ -306,7 +291,8 @@ static int i2o_pci_irq_enable(struct i2o_controller *c)
}
}
- I2O_IRQ_WRITE32(c, 0x00000000);
+ writel(0x00000000, c->irq_mask);
+ wmb();
printk(KERN_INFO "%s: Installed at IRQ %d\n", c->name, pdev->irq);
@@ -321,7 +307,9 @@ static int i2o_pci_irq_enable(struct i2o_controller *c)
*/
static void i2o_pci_irq_disable(struct i2o_controller *c)
{
- I2O_IRQ_WRITE32(c, 0xffffffff);
+ wmb();
+ writel(0xffffffff, c->irq_mask);
+ wmb();
if (c->pdev->irq > 0)
free_irq(c->pdev->irq, c);
@@ -379,7 +367,7 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev,
pci_name(pdev));
c->pdev = pdev;
- c->device = pdev->dev;
+ c->device.parent = get_device(&pdev->dev);
/* Cards that fall apart if you hit them with large I/O loads... */
if (pdev->vendor == PCI_VENDOR_ID_NCR && pdev->device == 0x0630) {
@@ -428,6 +416,8 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev,
if (i960)
pci_write_config_word(i960, 0x42, 0x03ff);
+ get_device(&c->device);
+
return 0;
uninstall:
@@ -438,6 +428,7 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev,
free_controller:
i2o_iop_free(c);
+ put_device(c->device.parent);
disable:
pci_disable_device(pdev);
@@ -461,15 +452,17 @@ static void __devexit i2o_pci_remove(struct pci_dev *pdev)
i2o_pci_irq_disable(c);
i2o_pci_free(c);
+ pci_disable_device(pdev);
+
printk(KERN_INFO "%s: Controller removed.\n", c->name);
- i2o_iop_free(c);
- pci_disable_device(pdev);
+ put_device(c->device.parent);
+ put_device(&c->device);
};
/* PCI driver for I2O controller */
static struct pci_driver i2o_pci_driver = {
- .name = "I2O controller",
+ .name = "PCI_I2O",
.id_table = i2o_pci_ids,
.probe = i2o_pci_probe,
.remove = __devexit_p(i2o_pci_remove),