X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fmessage%2Fi2o%2Fi2o_block.c;h=b17c4b2bc9ef7f6e784c56f8ee571f67c8e4e533;hb=refs%2Fheads%2Fvserver;hp=102fb83164c071f0ca79687051a531e63295a6f5;hpb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;p=linux-2.6.git diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c index 102fb8316..b17c4b2bc 100644 --- a/drivers/message/i2o/i2o_block.c +++ b/drivers/message/i2o/i2o_block.c @@ -59,8 +59,14 @@ #include #include +#include + #include "i2o_block.h" +#define OSM_NAME "block-osm" +#define OSM_VERSION "1.325" +#define OSM_DESCRIPTION "I2O Block Device OSM" + static struct i2o_driver i2o_block_driver; /* global Block OSM request mempool */ @@ -100,8 +106,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); - printk(KERN_INFO "block-osm: 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); @@ -127,21 +133,44 @@ static int i2o_block_remove(struct device *dev) static int i2o_block_device_flush(struct i2o_device *dev) { struct i2o_message *msg; - u32 m; - m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET); - if (m == I2O_QUEUE_EMPTY) - return -ETIMEDOUT; + msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); - writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); - writel(I2O_CMD_BLOCK_CFLUSH << 24 | HOST_TID << 12 | dev->lct_data.tid, - &msg->u.head[1]); - writel(60 << 16, &msg->body[0]); - pr_debug("Flushing...\n"); + msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_BLOCK_CFLUSH << 24 | HOST_TID << 12 | dev-> + lct_data.tid); + msg->body[0] = cpu_to_le32(60 << 16); + osm_debug("Flushing...\n"); - return i2o_msg_post_wait(dev->iop, m, 60); + return i2o_msg_post_wait(dev->iop, msg, 60); }; +/** + * i2o_block_issue_flush - device-flush interface for block-layer + * @queue: the request queue of the device which should be flushed + * @disk: gendisk + * @error_sector: error offset + * + * Helper function to provide flush functionality to block-layer. + * + * Returns 0 on success or negative error code on failure. + */ + +static int i2o_block_issue_flush(request_queue_t * queue, struct gendisk *disk, + sector_t * error_sector) +{ + struct i2o_block_device *i2o_blk_dev = queue->queuedata; + int rc = -ENODEV; + + if (likely(i2o_blk_dev)) + rc = i2o_block_device_flush(i2o_blk_dev->i2o_dev); + + return rc; +} + /** * i2o_block_device_mount - Mount (load) the media of device dev * @dev: I2O device which should receive the mount request @@ -155,20 +184,20 @@ static int i2o_block_device_flush(struct i2o_device *dev) static int i2o_block_device_mount(struct i2o_device *dev, u32 media_id) { struct i2o_message *msg; - u32 m; - m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET); - if (m == I2O_QUEUE_EMPTY) - return -ETIMEDOUT; + msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); - writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); - writel(I2O_CMD_BLOCK_MMOUNT << 24 | HOST_TID << 12 | dev->lct_data.tid, - &msg->u.head[1]); - writel(-1, &msg->body[0]); - writel(0, &msg->body[1]); - pr_debug("Mounting...\n"); + msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_BLOCK_MMOUNT << 24 | HOST_TID << 12 | dev-> + lct_data.tid); + msg->body[0] = cpu_to_le32(-1); + msg->body[1] = cpu_to_le32(0x00000000); + osm_debug("Mounting...\n"); - return i2o_msg_post_wait(dev->iop, m, 2); + return i2o_msg_post_wait(dev->iop, msg, 2); }; /** @@ -184,19 +213,19 @@ static int i2o_block_device_mount(struct i2o_device *dev, u32 media_id) static int i2o_block_device_lock(struct i2o_device *dev, u32 media_id) { struct i2o_message *msg; - u32 m; - m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET); - if (m == I2O_QUEUE_EMPTY) - return -ETIMEDOUT; + msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg) == I2O_QUEUE_EMPTY) + return PTR_ERR(msg); - writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); - writel(I2O_CMD_BLOCK_MLOCK << 24 | HOST_TID << 12 | dev->lct_data.tid, - &msg->u.head[1]); - writel(-1, &msg->body[0]); - pr_debug("Locking...\n"); + msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_BLOCK_MLOCK << 24 | HOST_TID << 12 | dev-> + lct_data.tid); + msg->body[0] = cpu_to_le32(-1); + osm_debug("Locking...\n"); - return i2o_msg_post_wait(dev->iop, m, 2); + return i2o_msg_post_wait(dev->iop, msg, 2); }; /** @@ -212,25 +241,25 @@ static int i2o_block_device_lock(struct i2o_device *dev, u32 media_id) static int i2o_block_device_unlock(struct i2o_device *dev, u32 media_id) { struct i2o_message *msg; - u32 m; - m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET); - if (m == I2O_QUEUE_EMPTY) - return -ETIMEDOUT; + msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); - writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); - writel(I2O_CMD_BLOCK_MUNLOCK << 24 | HOST_TID << 12 | dev->lct_data.tid, - &msg->u.head[1]); - writel(media_id, &msg->body[0]); - pr_debug("Unlocking...\n"); + msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_BLOCK_MUNLOCK << 24 | HOST_TID << 12 | dev-> + lct_data.tid); + msg->body[0] = cpu_to_le32(media_id); + osm_debug("Unlocking...\n"); - return i2o_msg_post_wait(dev->iop, m, 2); + return i2o_msg_post_wait(dev->iop, msg, 2); }; /** * i2o_block_device_power - Power management for device dev * @dev: I2O device which should receive the power management request - * @operation: Operation which should be send + * @op: Operation to send * * Send a power management request to the device dev. * @@ -241,20 +270,20 @@ static int i2o_block_device_power(struct i2o_block_device *dev, u8 op) struct i2o_device *i2o_dev = dev->i2o_dev; struct i2o_controller *c = i2o_dev->iop; struct i2o_message *msg; - u32 m; int rc; - m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); - if (m == I2O_QUEUE_EMPTY) - return -ETIMEDOUT; + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); - writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); - writel(I2O_CMD_BLOCK_POWER << 24 | HOST_TID << 12 | i2o_dev->lct_data. - tid, &msg->u.head[1]); - writel(op << 24, &msg->body[0]); - pr_debug("Power...\n"); + msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_BLOCK_POWER << 24 | HOST_TID << 12 | i2o_dev-> + lct_data.tid); + msg->body[0] = cpu_to_le32(op << 24); + osm_debug("Power...\n"); - rc = i2o_msg_post_wait(c, m, 60); + rc = i2o_msg_post_wait(c, msg, 60); if (!rc) dev->power = op; @@ -286,7 +315,7 @@ static inline struct i2o_block_request *i2o_block_request_alloc(void) * i2o_block_request_free - Frees a I2O block request * @ireq: I2O block request which should be freed * - * Fres the allocated memory (give it back to the request mempool). + * Frees the allocated memory (give it back to the request mempool). */ static inline void i2o_block_request_free(struct i2o_block_request *ireq) { @@ -295,28 +324,32 @@ static inline void i2o_block_request_free(struct i2o_block_request *ireq) /** * i2o_block_sglist_alloc - Allocate the SG list and map it + * @c: I2O controller to which the request belongs * @ireq: I2O block request + * @mptr: message body pointer * - * Builds the SG list and map it into to be accessable by the controller. + * Builds the SG list and map it to be accessable by the controller. * - * Returns the number of elements in the SG list or 0 on failure. + * Returns 0 on failure or 1 on success. */ -static inline int i2o_block_sglist_alloc(struct i2o_block_request *ireq) +static inline int i2o_block_sglist_alloc(struct i2o_controller *c, + struct i2o_block_request *ireq, + u32 ** mptr) { - struct device *dev = &ireq->i2o_blk_dev->i2o_dev->iop->pdev->dev; int nents; + enum dma_data_direction direction; + ireq->dev = &c->pdev->dev; nents = blk_rq_map_sg(ireq->req->q, ireq->req, ireq->sg_table); if (rq_data_dir(ireq->req) == READ) - ireq->sg_dma_direction = PCI_DMA_FROMDEVICE; + direction = PCI_DMA_FROMDEVICE; else - ireq->sg_dma_direction = PCI_DMA_TODEVICE; + direction = PCI_DMA_TODEVICE; - ireq->sg_nents = dma_map_sg(dev, ireq->sg_table, nents, - ireq->sg_dma_direction); + ireq->sg_nents = nents; - return ireq->sg_nents; + return i2o_dma_map_sg(c, ireq->sg_table, nents, direction, mptr); }; /** @@ -327,10 +360,14 @@ static inline int i2o_block_sglist_alloc(struct i2o_block_request *ireq) */ static inline void i2o_block_sglist_free(struct i2o_block_request *ireq) { - struct device *dev = &ireq->i2o_blk_dev->i2o_dev->iop->pdev->dev; + enum dma_data_direction direction; + + if (rq_data_dir(ireq->req) == READ) + direction = PCI_DMA_FROMDEVICE; + else + direction = PCI_DMA_TODEVICE; - dma_unmap_sg(dev, ireq->sg_table, ireq->sg_nents, - ireq->sg_dma_direction); + dma_unmap_sg(ireq->dev, ireq->sg_table, ireq->sg_nents, direction); }; /** @@ -348,45 +385,43 @@ static int i2o_block_prep_req_fn(struct request_queue *q, struct request *req) struct i2o_block_device *i2o_blk_dev = q->queuedata; struct i2o_block_request *ireq; - /* request is already processed by us, so return */ - if (req->flags & REQ_SPECIAL) { - pr_debug("REQ_SPECIAL already set!\n"); - req->flags |= REQ_DONTPREP; - return BLKPREP_OK; + if (unlikely(!i2o_blk_dev)) { + osm_err("block device already removed\n"); + return BLKPREP_KILL; } /* connect the i2o_block_request to the request */ if (!req->special) { ireq = i2o_block_request_alloc(); if (unlikely(IS_ERR(ireq))) { - pr_debug("unable to allocate i2o_block_request!\n"); + osm_debug("unable to allocate i2o_block_request!\n"); return BLKPREP_DEFER; } ireq->i2o_blk_dev = i2o_blk_dev; req->special = ireq; ireq->req = req; - } else - ireq = req->special; - + } /* do not come back here */ - req->flags |= REQ_DONTPREP | REQ_SPECIAL; + req->cmd_flags |= REQ_DONTPREP; return BLKPREP_OK; }; /** * i2o_block_delayed_request_fn - delayed request queue function - * delayed_request: the delayed request with the queue to start + * @work: the delayed request with the queue to start * * If the request queue is stopped for a disk, and there is no open * request, a new event is created, which calls this function to start * the queue after I2O_BLOCK_REQUEST_TIME. Otherwise the queue will never * be started again. */ -static void i2o_block_delayed_request_fn(void *delayed_request) +static void i2o_block_delayed_request_fn(struct work_struct *work) { - struct i2o_block_delayed_request *dreq = delayed_request; + struct i2o_block_delayed_request *dreq = + container_of(work, struct i2o_block_delayed_request, + work.work); struct request_queue *q = dreq->queue; unsigned long flags; @@ -397,104 +432,69 @@ 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 = req->q; unsigned long flags; - /* FAILed message */ - if (unlikely(readl(&msg->u.head[0]) & (1 << 13))) { - struct i2o_message *pmsg; - u32 pm; + if (end_that_request_chunk(req, uptodate, nr_bytes)) { + int leftover = (req->hard_nr_sectors << KERNEL_SECTOR_SHIFT); - printk(KERN_WARNING "FAIL"); - /* - * 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 = readl(&msg->body[3]); - pmsg = c->in_queue.virt + pm; + if (blk_pc_request(req)) + leftover = req->data_len; - req = i2o_cntxt_list_get(c, readl(&pmsg->u.s.tcntxt)); - if (unlikely(!req)) { - printk(KERN_ERR "block-osm: NULL reply received!\n"); - return -1; - } + if (end_io_error(uptodate)) + end_that_request_chunk(req, 0, leftover); + } - ireq = req->special; - dev = ireq->i2o_blk_dev; - q = dev->gd->queue; + add_disk_randomness(req->rq_disk); - req->errors++; - - spin_lock_irqsave(q->queue_lock, flags); + spin_lock_irqsave(q->queue_lock, flags); - while (end_that_request_chunk(req, !req->errors, - readl(&pmsg->body[1]))) ; - end_that_request_last(req); + end_that_request_last(req, uptodate); + if (likely(dev)) { dev->open_queue_depth--; list_del(&ireq->queue); - blk_start_queue(q); - - spin_unlock_irqrestore(q->queue_lock, flags); - - /* Now flush the message by making it a NOP */ - i2o_msg_nop(c, pm); - - return -1; } - req = i2o_cntxt_list_get(c, readl(&msg->u.s.tcntxt)); - if (unlikely(!req)) { - printk(KERN_ERR "block-osm: NULL reply received!\n"); - return -1; - } + blk_start_queue(q); - ireq = req->special; - dev = ireq->i2o_blk_dev; - q = dev->gd->queue; + spin_unlock_irqrestore(q->queue_lock, flags); - 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++; - printk(KERN_WARNING - "I2O Block: Data transfer to deleted device!\n"); - spin_lock_irqsave(q->queue_lock, flags); - while (end_that_request_chunk - (req, !req->errors, readl(&msg->body[1]))) ; - end_that_request_last(req); + i2o_block_sglist_free(ireq); + i2o_block_request_free(ireq); +}; - dev->open_queue_depth--; - list_del(&ireq->queue); - blk_start_queue(q); +/** + * i2o_block_reply - Block OSM reply handler. + * @c: I2O controller from which the message arrives + * @m: message id of reply + * @msg: the actual 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; - spin_unlock_irqrestore(q->queue_lock, flags); + req = i2o_cntxt_list_get(c, le32_to_cpu(msg->u.s.tcntxt)); + if (unlikely(!req)) { + osm_err("NULL reply received!\n"); return -1; } @@ -503,29 +503,8 @@ static int i2o_block_reply(struct i2o_controller *c, u32 m, * request in the context. */ - st = readl(&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 = readl(&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) @@ -538,209 +517,27 @@ static int i2o_block_reply(struct i2o_controller *c, u32 m, * Don't stick a supertrak100 into cache aggressive modes */ - printk(KERN_ERR "\n/dev/%s error: %s", dev->gd->disk_name, - bsa_errors[readl(&msg->body[0]) & 0xffff]); - if (readl(&msg->body[0]) & 0x00ff0000) - printk(" - DDM attempted %d retries", - (readl(&msg->body[0]) >> 16) & 0x00ff); - printk(".\n"); - req->errors++; - } else - req->errors = 0; - - if (!end_that_request_chunk(req, !req->errors, readl(&msg->body[1]))) { - add_disk_randomness(req->rq_disk); - spin_lock_irqsave(q->queue_lock, flags); + osm_err("TID %03x error status: 0x%02x, detailed status: " + "0x%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 - printk(KERN_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) +static void i2o_block_event(struct work_struct *work) { - printk(KERN_INFO "block-osm: event received\n"); + struct i2o_event *evt = container_of(work, struct i2o_event, work); + osm_debug("event received\n"); + kfree(evt); }; -#if 0 -static int i2o_block_event(void *dummy) -{ - unsigned int evt; - unsigned long flags; - struct i2o_block_device *dev; - int unit; - //The only event that has data is the SCSI_SMART event. - struct i2o_reply { - u32 header[4]; - u32 evt_indicator; - u8 ASC; - u8 ASCQ; - u16 pad; - u8 data[16]; - } *evt_local; - - daemonize("i2oblock"); - allow_signal(SIGKILL); - - evt_running = 1; - - while (1) { - if (down_interruptible(&i2ob_evt_sem)) { - evt_running = 0; - printk("exiting..."); - break; - } - - /* - * Keep another CPU/interrupt from overwriting the - * message while we're reading it - * - * We stuffed the unit in the TxContext and grab the event mask - * None of the BSA we care about events have EventData - */ - spin_lock_irqsave(&i2ob_evt_lock, flags); - evt_local = (struct i2o_reply *)evt_msg; - spin_unlock_irqrestore(&i2ob_evt_lock, flags); - - unit = le32_to_cpu(evt_local->header[3]); - evt = le32_to_cpu(evt_local->evt_indicator); - - dev = &i2o_blk_dev[unit]; - switch (evt) { - /* - * New volume loaded on same TID, so we just re-install. - * The TID/controller don't change as it is the same - * I2O device. It's just new media that we have to - * rescan. - */ - case I2O_EVT_IND_BSA_VOLUME_LOAD: - { - i2ob_install_device(dev->i2o_device->iop, - dev->i2o_device, unit); - add_disk(dev->gendisk); - break; - } - - /* - * No media, so set all parameters to 0 and set the media - * change flag. The I2O device is still valid, just doesn't - * have media, so we don't want to clear the controller or - * device pointer. - */ - case I2O_EVT_IND_BSA_VOLUME_UNLOAD: - { - struct gendisk *p = dev->gendisk; - blk_queue_max_sectors(dev->gendisk->queue, 0); - del_gendisk(p); - put_disk(p); - dev->gendisk = NULL; - dev->media_change_flag = 1; - break; - } - - case I2O_EVT_IND_BSA_VOLUME_UNLOAD_REQ: - printk(KERN_WARNING - "%s: Attempt to eject locked media\n", - dev->i2o_device->dev_name); - break; - - /* - * The capacity has changed and we are going to be - * updating the max_sectors and other information - * about this disk. We try a revalidate first. If - * the block device is in use, we don't want to - * do that as there may be I/Os bound for the disk - * at the moment. In that case we read the size - * from the device and update the information ourselves - * and the user can later force a partition table - * update through an ioctl. - */ - case I2O_EVT_IND_BSA_CAPACITY_CHANGE: - { - u64 size; - - if (i2ob_query_device(dev, 0x0004, 0, &size, 8) - != 0) - i2ob_query_device(dev, 0x0000, 4, &size, - 8); - - spin_lock_irqsave(dev->req_queue->queue_lock, - flags); - set_capacity(dev->gendisk, size >> 9); - spin_unlock_irqrestore(dev->req_queue-> - queue_lock, flags); - break; - } - - /* - * We got a SCSI SMART event, we just log the relevant - * information and let the user decide what they want - * to do with the information. - */ - case I2O_EVT_IND_BSA_SCSI_SMART: - { - char buf[16]; - printk(KERN_INFO - "I2O Block: %s received a SCSI SMART Event\n", - dev->i2o_device->dev_name); - evt_local->data[16] = '\0'; - sprintf(buf, "%s", &evt_local->data[0]); - printk(KERN_INFO " Disk Serial#:%s\n", - buf); - printk(KERN_INFO " ASC 0x%02x \n", - evt_local->ASC); - printk(KERN_INFO " ASCQ 0x%02x \n", - evt_local->ASCQ); - break; - } - - /* - * Non event - */ - - case 0: - break; - - /* - * An event we didn't ask for. Call the card manufacturer - * and tell them to fix their firmware :) - */ - - case 0x20: - /* - * If a promise card reports 0x20 event then the brown stuff - * hit the fan big time. The card seems to recover but loses - * the pending writes. Deeply ungood except for testing fsck - */ - if (dev->i2o_device->iop->promise) - panic - ("I2O controller firmware failed. Reboot and force a filesystem check.\n"); - default: - printk(KERN_INFO - "%s: Received event 0x%X we didn't register for\n" - KERN_INFO - " Blame the I2O card manufacturer 8)\n", - dev->i2o_device->dev_name, evt); - break; - } - }; - - complete_and_exit(&i2ob_thread_dead, 0); - return 0; -} -#endif - /* * SCSI-CAM for ioctl geometry mapping * Duplicated with SCSI - this should be moved into somewhere common @@ -796,6 +593,8 @@ static void i2o_block_biosparam(unsigned long capacity, unsigned short *cyls, /** * i2o_block_open - Open the block device + * @inode: inode for block device being opened + * @file: file to open * * Power up the device, mount and lock the media. This function is called, * if the block device is opened for access. @@ -816,13 +615,15 @@ static int i2o_block_open(struct inode *inode, struct file *file) i2o_block_device_lock(dev->i2o_dev, -1); - pr_debug("Ready.\n"); + osm_debug("Ready.\n"); return 0; }; /** * i2o_block_release - Release the I2O block device + * @inode: inode for block device being released + * @file: file to close * * Unlock and unmount the media, and power down the device. Gets called if * the block device is closed. @@ -860,8 +661,17 @@ static int i2o_block_release(struct inode *inode, struct file *file) return 0; } +static int i2o_block_getgeo(struct block_device *bdev, struct hd_geometry *geo) +{ + i2o_block_biosparam(get_capacity(bdev->bd_disk), + &geo->cylinders, &geo->heads, &geo->sectors); + return 0; +} + /** * i2o_block_ioctl - Issue device specific ioctl calls. + * @inode: inode for block device ioctl + * @file: file for ioctl * @cmd: ioctl command * @arg: arg * @@ -874,7 +684,6 @@ static int i2o_block_ioctl(struct inode *inode, struct file *file, { struct gendisk *disk = inode->i_bdev->bd_disk; struct i2o_block_device *dev = disk->private_data; - void __user *argp = (void __user *)arg; /* Anyone capable of this syscall can do *real bad* things */ @@ -882,15 +691,6 @@ static int i2o_block_ioctl(struct inode *inode, struct file *file, return -EPERM; switch (cmd) { - case HDIO_GETGEO: - { - struct hd_geometry g; - i2o_block_biosparam(get_capacity(disk), - &g.cylinders, &g.heads, &g.sectors); - g.start = get_start_sect(inode->i_bdev); - return copy_to_user(argp, &g, sizeof(g)) ? -EFAULT : 0; - } - case BLKI2OGRSTRAT: return put_user(dev->rcache, (int __user *)arg); case BLKI2OGWSTRAT: @@ -943,22 +743,28 @@ static int i2o_block_media_changed(struct gendisk *disk) static int i2o_block_transfer(struct request *req) { struct i2o_block_device *dev = req->rq_disk->private_data; - struct i2o_controller *c = dev->i2o_dev->iop; + struct i2o_controller *c; int tid = dev->i2o_dev->lct_data.tid; struct i2o_message *msg; - void *mptr; + u32 *mptr; struct i2o_block_request *ireq = req->special; - struct scatterlist *sg; - int sgnum; - int i; - u32 m; u32 tcntxt; - u32 sg_flags; + u32 sgl_offset = SGL_OFFSET_8; + u32 ctl_flags = 0x00000000; int rc; + u32 cmd; - m = i2o_msg_get(c, &msg); - if (m == I2O_QUEUE_EMPTY) { - rc = -EBUSY; + if (unlikely(!dev->i2o_dev)) { + osm_err("transfer to removed drive\n"); + rc = -ENODEV; + goto exit; + } + + c = dev->i2o_dev->iop; + + msg = i2o_msg_get(c); + if (IS_ERR(msg)) { + rc = PTR_ERR(msg); goto exit; } @@ -968,95 +774,124 @@ static int i2o_block_transfer(struct request *req) goto nop_msg; } - if ((sgnum = i2o_block_sglist_alloc(ireq)) <= 0) { - rc = -ENOMEM; - goto context_remove; - } - - /* Build the message based on the request. */ - writel(i2o_block_driver.context, &msg->u.s.icntxt); - writel(tcntxt, &msg->u.s.tcntxt); - writel(req->nr_sectors << 9, &msg->body[1]); - - writel((((u64) req->sector) << 9) & 0xffffffff, &msg->body[2]); - writel(req->sector >> 23, &msg->body[3]); + msg->u.s.icntxt = cpu_to_le32(i2o_block_driver.context); + msg->u.s.tcntxt = cpu_to_le32(tcntxt); - mptr = &msg->body[4]; - - sg = ireq->sg_table; + mptr = &msg->body[0]; if (rq_data_dir(req) == READ) { - writel(I2O_CMD_BLOCK_READ << 24 | HOST_TID << 12 | tid, - &msg->u.head[1]); - sg_flags = 0x10000000; + cmd = I2O_CMD_BLOCK_READ << 24; + switch (dev->rcache) { - case CACHE_NULL: - writel(0, &msg->body[0]); - break; case CACHE_PREFETCH: - writel(0x201F0008, &msg->body[0]); + ctl_flags = 0x201F0008; break; + case CACHE_SMARTFETCH: if (req->nr_sectors > 16) - writel(0x201F0008, &msg->body[0]); + ctl_flags = 0x201F0008; else - writel(0x001F0000, &msg->body[0]); + ctl_flags = 0x001F0000; + break; + + default: break; } } else { - writel(I2O_CMD_BLOCK_WRITE << 24 | HOST_TID << 12 | tid, - &msg->u.head[1]); - sg_flags = 0x14000000; + cmd = I2O_CMD_BLOCK_WRITE << 24; + switch (dev->wcache) { - case CACHE_NULL: - writel(0, &msg->body[0]); - break; case CACHE_WRITETHROUGH: - writel(0x001F0008, &msg->body[0]); + ctl_flags = 0x001F0008; break; case CACHE_WRITEBACK: - writel(0x001F0010, &msg->body[0]); + ctl_flags = 0x001F0010; break; case CACHE_SMARTBACK: if (req->nr_sectors > 16) - writel(0x001F0004, &msg->body[0]); + ctl_flags = 0x001F0004; else - writel(0x001F0010, &msg->body[0]); + ctl_flags = 0x001F0010; break; case CACHE_SMARTTHROUGH: if (req->nr_sectors > 16) - writel(0x001F0004, &msg->body[0]); + ctl_flags = 0x001F0004; else - writel(0x001F0010, &msg->body[0]); + ctl_flags = 0x001F0010; + default: + break; } } - for (i = sgnum; i > 0; i--) { - if (i == 1) - sg_flags |= 0x80000000; - writel(sg_flags | sg_dma_len(sg), mptr); - writel(sg_dma_address(sg), mptr + 4); - mptr += 8; - sg++; +#ifdef CONFIG_I2O_EXT_ADAPTEC + if (c->adaptec) { + u8 cmd[10]; + u32 scsi_flags; + u16 hwsec = queue_hardsect_size(req->q) >> KERNEL_SECTOR_SHIFT; + + memset(cmd, 0, 10); + + sgl_offset = SGL_OFFSET_12; + + msg->u.head[1] = + cpu_to_le32(I2O_CMD_PRIVATE << 24 | HOST_TID << 12 | tid); + + *mptr++ = cpu_to_le32(I2O_VENDOR_DPT << 16 | I2O_CMD_SCSI_EXEC); + *mptr++ = cpu_to_le32(tid); + + /* + * ENABLE_DISCONNECT + * SIMPLE_TAG + * RETURN_SENSE_DATA_IN_REPLY_MESSAGE_FRAME + */ + if (rq_data_dir(req) == READ) { + cmd[0] = READ_10; + scsi_flags = 0x60a0000a; + } else { + cmd[0] = WRITE_10; + scsi_flags = 0xa0a0000a; + } + + *mptr++ = cpu_to_le32(scsi_flags); + + *((u32 *) & cmd[2]) = cpu_to_be32(req->sector * hwsec); + *((u16 *) & cmd[7]) = cpu_to_be16(req->nr_sectors * hwsec); + + memcpy(mptr, cmd, 10); + mptr += 4; + *mptr++ = cpu_to_le32(req->nr_sectors << KERNEL_SECTOR_SHIFT); + } else +#endif + { + msg->u.head[1] = cpu_to_le32(cmd | HOST_TID << 12 | tid); + *mptr++ = cpu_to_le32(ctl_flags); + *mptr++ = cpu_to_le32(req->nr_sectors << KERNEL_SECTOR_SHIFT); + *mptr++ = + cpu_to_le32((u32) (req->sector << KERNEL_SECTOR_SHIFT)); + *mptr++ = + cpu_to_le32(req->sector >> (32 - KERNEL_SECTOR_SHIFT)); } - writel(I2O_MESSAGE_SIZE - (((unsigned long)mptr - - (unsigned long)&msg->u.head[0]) >> 2) | SGL_OFFSET_8, - &msg->u.head[0]); + if (!i2o_block_sglist_alloc(c, ireq, &mptr)) { + rc = -ENOMEM; + goto context_remove; + } - i2o_msg_post(c, m); + msg->u.head[0] = + cpu_to_le32(I2O_MESSAGE_SIZE(mptr - &msg->u.head[0]) | sgl_offset); list_add_tail(&ireq->queue, &dev->open_queue); dev->open_queue_depth++; + i2o_msg_post(c, msg); + return 0; context_remove: i2o_cntxt_list_remove(c, req); nop_msg: - i2o_msg_nop(c, m); + i2o_msg_nop(c, msg); exit: return rc; @@ -1064,7 +899,7 @@ static int i2o_block_transfer(struct request *req) /** * i2o_block_request_fn - request queue handling function - * q: request queue from which the request could be fetched + * @q: request queue from which the request could be fetched * * Takes the next request from the queue, transfers it and if no error * occurs dequeue it from the queue. On arrival of the reply the message @@ -1086,11 +921,13 @@ static void i2o_block_request_fn(struct request_queue *q) queue_depth = ireq->i2o_blk_dev->open_queue_depth; - if (queue_depth < I2O_BLOCK_MAX_OPEN_REQUESTS) + if (queue_depth < I2O_BLOCK_MAX_OPEN_REQUESTS) { if (!i2o_block_transfer(req)) { blkdev_dequeue_request(req); continue; - } + } else + osm_info("transfer error\n"); + } if (queue_depth) break; @@ -1101,10 +938,9 @@ static void i2o_block_request_fn(struct request_queue *q) continue; dreq->queue = q; - INIT_WORK(&dreq->work, i2o_block_delayed_request_fn, - dreq); + INIT_DELAYED_WORK(&dreq->work, + i2o_block_delayed_request_fn); - printk(KERN_INFO "block-osm: transfer error\n"); if (!queue_delayed_work(i2o_block_driver.event_queue, &dreq->work, I2O_BLOCK_RETRY_TIME)) @@ -1124,6 +960,7 @@ static struct block_device_operations i2o_block_fops = { .open = i2o_block_open, .release = i2o_block_release, .ioctl = i2o_block_ioctl, + .getgeo = i2o_block_getgeo, .media_changed = i2o_block_media_changed }; @@ -1143,14 +980,12 @@ static struct i2o_block_device *i2o_block_device_alloc(void) struct request_queue *queue; int rc; - dev = kmalloc(sizeof(*dev), GFP_KERNEL); + dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) { - printk(KERN_ERR "block-osm: Insufficient memory to allocate " - "I2O Block disk.\n"); + osm_err("Insufficient memory to allocate I2O Block disk.\n"); rc = -ENOMEM; goto exit; } - memset(dev, 0, sizeof(*dev)); INIT_LIST_HEAD(&dev->open_queue); spin_lock_init(&dev->lock); @@ -1160,8 +995,7 @@ static struct i2o_block_device *i2o_block_device_alloc(void) /* allocate a gendisk with 16 partitions */ gd = alloc_disk(16); if (!gd) { - printk(KERN_ERR "block-osm: Insufficient memory to allocate " - "gendisk.\n"); + osm_err("Insufficient memory to allocate gendisk.\n"); rc = -ENOMEM; goto cleanup_dev; } @@ -1169,13 +1003,13 @@ static struct i2o_block_device *i2o_block_device_alloc(void) /* initialize the request queue */ queue = blk_init_queue(i2o_block_request_fn, &dev->lock); if (!queue) { - printk(KERN_ERR "block-osm: Insufficient memory to allocate " - "request queue.\n"); + osm_err("Insufficient memory to allocate request queue.\n"); rc = -ENOMEM; goto cleanup_queue; } blk_queue_prep_rq(queue, i2o_block_prep_req_fn); + blk_queue_issue_flush_fn(queue, i2o_block_issue_flush); gd->major = I2O_MAJOR; gd->queue = queue; @@ -1208,38 +1042,43 @@ static struct i2o_block_device *i2o_block_device_alloc(void) static int i2o_block_probe(struct device *dev) { struct i2o_device *i2o_dev = to_i2o_device(dev); - struct i2o_block_device *i2o_blk_dev; struct i2o_controller *c = i2o_dev->iop; + struct i2o_block_device *i2o_blk_dev; struct gendisk *gd; struct request_queue *queue; static int unit = 0; int rc; u64 size; u32 blocksize; + u16 body_size = 4; u16 power; - u32 flags, status; - int segments; + unsigned short max_sectors; + +#ifdef CONFIG_I2O_EXT_ADAPTEC + if (c->adaptec) + body_size = 8; +#endif + + if (c->limit_sectors) + max_sectors = I2O_MAX_SECTORS_LIMITED; + else + max_sectors = I2O_MAX_SECTORS; /* skip devices which are used by IOP */ if (i2o_dev->lct_data.user_tid != 0xfff) { - pr_debug("skipping used device %03x\n", i2o_dev->lct_data.tid); + osm_debug("skipping used device %03x\n", i2o_dev->lct_data.tid); return -ENODEV; } - printk(KERN_INFO "block-osm: New device detected (TID: %03x)\n", - i2o_dev->lct_data.tid); - if (i2o_device_claim(i2o_dev)) { - printk(KERN_WARNING "block-osm: Unable to claim device. " - "Installation aborted\n"); + osm_warn("Unable to claim device. Installation aborted\n"); rc = -EFAULT; goto exit; } i2o_blk_dev = i2o_block_device_alloc(); if (IS_ERR(i2o_blk_dev)) { - printk(KERN_ERR "block-osm: could not alloc a new I2O block" - "device"); + osm_err("could not alloc a new I2O block device"); rc = PTR_ERR(i2o_blk_dev); goto claim_release; } @@ -1251,50 +1090,38 @@ static int i2o_block_probe(struct device *dev) gd = i2o_blk_dev->gd; gd->first_minor = unit << 4; sprintf(gd->disk_name, "i2o/hd%c", 'a' + unit); - sprintf(gd->devfs_name, "i2o/hd%c", 'a' + unit); gd->driverfs_dev = &i2o_dev->device; /* setup request queue */ queue = gd->queue; queue->queuedata = i2o_blk_dev; - blk_queue_max_phys_segments(queue, I2O_MAX_SEGMENTS); - blk_queue_max_sectors(queue, I2O_MAX_SECTORS); - - if (c->short_req) - segments = 8; - else { - i2o_status_block *sb; - - sb = c->status_block.virt; - - segments = (sb->inbound_frame_size - - sizeof(struct i2o_message) / 4 - 4) / 2; - } - - blk_queue_max_hw_segments(queue, segments); + blk_queue_max_phys_segments(queue, I2O_MAX_PHYS_SEGMENTS); + blk_queue_max_sectors(queue, max_sectors); + blk_queue_max_hw_segments(queue, i2o_sg_tablesize(c, body_size)); - pr_debug("max sectors: %d\n", I2O_MAX_SECTORS); - pr_debug("phys segments: %d\n", I2O_MAX_SEGMENTS); - pr_debug("hw segments: %d\n", segments); + osm_debug("max sectors = %d\n", queue->max_phys_segments); + osm_debug("phys segments = %d\n", queue->max_sectors); + osm_debug("max hw segments = %d\n", queue->max_hw_segments); /* * 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); - } - pr_debug("blocksize: %d\n", blocksize); + if (!i2o_parm_field_get(i2o_dev, 0x0004, 1, &blocksize, 4) || + !i2o_parm_field_get(i2o_dev, 0x0000, 3, &blocksize, 4)) { + blk_queue_hardsect_size(queue, le32_to_cpu(blocksize)); + } else + osm_warn("unable to get blocksize of %s\n", gd->disk_name); - if (i2o_parm_field_get(i2o_dev, 0x0000, 2, &power, 2)) - power = 0; - i2o_parm_field_get(i2o_dev, 0x0000, 5, &flags, 4); - i2o_parm_field_get(i2o_dev, 0x0000, 6, &status, 4); + if (!i2o_parm_field_get(i2o_dev, 0x0004, 0, &size, 8) || + !i2o_parm_field_get(i2o_dev, 0x0000, 4, &size, 8)) { + set_capacity(gd, le64_to_cpu(size) >> KERNEL_SECTOR_SHIFT); + } else + osm_warn("could not get size of %s\n", gd->disk_name); - set_capacity(gd, size >> 9); + if (!i2o_parm_field_get(i2o_dev, 0x0000, 2, &power, 2)) + i2o_blk_dev->power = power; i2o_event_register(i2o_dev, &i2o_block_driver, 0, 0xffffffff); @@ -1302,6 +1129,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: @@ -1313,7 +1143,7 @@ static int i2o_block_probe(struct device *dev) /* Block OSM driver struct */ static struct i2o_driver i2o_block_driver = { - .name = "block-osm", + .name = OSM_NAME, .event = i2o_block_event, .reply = i2o_block_reply, .classes = i2o_block_class_id, @@ -1336,8 +1166,7 @@ static int __init i2o_block_init(void) int rc; int size; - printk(KERN_INFO "I2O Block Storage OSM v0.9\n"); - printk(KERN_INFO " (c) Copyright 1999-2001 Red Hat Software.\n"); + printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n"); /* Allocate request mempool and slab */ size = sizeof(struct i2o_block_request); @@ -1345,17 +1174,16 @@ static int __init i2o_block_init(void) SLAB_HWCACHE_ALIGN, NULL, NULL); if (!i2o_blk_req_pool.slab) { - printk(KERN_ERR "block-osm: can't init request slab\n"); + osm_err("can't init request slab\n"); rc = -ENOMEM; goto exit; } - i2o_blk_req_pool.pool = mempool_create(I2O_REQ_MEMPOOL_SIZE, - mempool_alloc_slab, - mempool_free_slab, - i2o_blk_req_pool.slab); + i2o_blk_req_pool.pool = + mempool_create_slab_pool(I2O_BLOCK_REQ_MEMPOOL_SIZE, + i2o_blk_req_pool.slab); if (!i2o_blk_req_pool.pool) { - printk(KERN_ERR "block-osm: can't init request mempool\n"); + osm_err("can't init request mempool\n"); rc = -ENOMEM; goto free_slab; } @@ -1363,18 +1191,17 @@ static int __init i2o_block_init(void) /* Register the block device interfaces */ rc = register_blkdev(I2O_MAJOR, "i2o_block"); if (rc) { - printk(KERN_ERR "block-osm: unable to register block device\n"); + osm_err("unable to register block device\n"); goto free_mempool; } #ifdef MODULE - printk(KERN_INFO "block-osm: registered device at major %d\n", - I2O_MAJOR); + osm_info("registered device at major %d\n", I2O_MAJOR); #endif /* Register Block OSM into I2O core */ rc = i2o_driver_register(&i2o_block_driver); if (rc) { - printk(KERN_ERR "block-osm: Could not register Block driver\n"); + osm_err("Could not register Block driver\n"); goto unregister_blkdev; } @@ -1413,8 +1240,9 @@ static void __exit i2o_block_exit(void) }; MODULE_AUTHOR("Red Hat"); -MODULE_DESCRIPTION("I2O Block Device OSM"); MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION(OSM_DESCRIPTION); +MODULE_VERSION(OSM_VERSION); module_init(i2o_block_init); module_exit(i2o_block_exit);