diff options
Diffstat (limited to 'drivers/message/i2o')
-rw-r--r-- | drivers/message/i2o/device.c | 9 | ||||
-rw-r--r-- | drivers/message/i2o/driver.c | 46 | ||||
-rw-r--r-- | drivers/message/i2o/exec-osm.c | 47 | ||||
-rw-r--r-- | drivers/message/i2o/i2o_block.c | 211 | ||||
-rw-r--r-- | drivers/message/i2o/i2o_block.h | 2 | ||||
-rw-r--r-- | drivers/message/i2o/i2o_config.c | 118 | ||||
-rw-r--r-- | drivers/message/i2o/i2o_scsi.c | 31 | ||||
-rw-r--r-- | drivers/message/i2o/iop.c | 87 | ||||
-rw-r--r-- | drivers/message/i2o/pci.c | 67 |
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), |