/*
* Block OSM
*
* Copyright (C) 1999-2002 Red Hat Software
*
* Written by Alan Cox, Building Number Three Ltd
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* For the purpose of avoiding doubt the preferred form of the work
* for making modifications shall be a standards compliant form such
* gzipped tar and not one requiring a proprietary or patent encumbered
* tool to unpack.
*
* Fixes/additions:
* Steve Ralston:
* Multiple device handling error fixes,
* Added a queue depth.
* Alan Cox:
* FC920 has an rmw bug. Dont or in the end marker.
* Removed queue walk, fixed for 64bitness.
* Rewrote much of the code over time
* Added indirect block lists
* Handle 64K limits on many controllers
* Don't use indirects on the Promise (breaks)
* Heavily chop down the queue depths
* Deepak Saxena:
* Independent queues per IOP
* Support for dynamic device creation/deletion
* Code cleanup
* Support for larger I/Os through merge* functions
* (taken from DAC960 driver)
* Boji T Kannanthanam:
* Set the I2O Block devices to be detected in increasing
* order of TIDs during boot.
* Search and set the I2O block device that we boot off
* from as the first device to be claimed (as /dev/i2o/hda)
* Properly attach/detach I2O gendisk structure from the
* system gendisk list. The I2O block devices now appear in
* /proc/partitions.
* Markus Lidel <Markus.Lidel@shadowconnect.com>:
* Minor bugfixes for 2.6.
*/
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/i2o.h>
#include <linux/mutex.h>
#include <linux/mempool.h>
#include <linux/genhd.h>
#include <linux/blkdev.h>
#include <linux/hdreg.h>
#include <scsi/scsi.h>
#include "i2o_block.h"
#define OSM_NAME "block-osm"
#define OSM_VERSION "1.325"
#define OSM_DESCRIPTION "I2O Block Device OSM"
static DEFINE_MUTEX(i2o_block_mutex);
static struct i2o_driver i2o_block_driver;
/* global Block OSM request mempool */
static struct i2o_block_mempool i2o_blk_req_pool;
/* Block OSM class handling definition */
static struct i2o_class_id i2o_block_class_id[] = {
{I2O_CLASS_RANDOM_BLOCK_STORAGE},
{I2O_CLASS_END}
};
/**
* i2o_block_device_free - free the memory of the I2O Block device
* @dev: I2O Block device, which should be cleaned up
*
* Frees the request queue, gendisk and the i2o_block_device structure.
*/
static void i2o_block_device_free(struct i2o_block_device *dev)
{
blk_cleanup_queue(dev->gd->queue);
put_disk(dev->gd);
kfree(dev);
};
/**
* i2o_block_remove - remove the I2O Block device from the system again
* @dev: I2O Block device which should be removed
*
* Remove gendisk from system and free all allocated memory.
*
* Always returns 0.
*/
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 (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);
del_gendisk(i2o_blk_dev->gd);
dev_set_drvdata(dev, NULL);
i2o_device_claim_release(i2o_dev);
i2o_block_device_free(i2o_blk_dev);
return 0;
};
/**
* i2o_block_device flush - Flush all dirty data of I2O device dev
* @dev: I2O device which should be flushed
*
* Flushes all dirty data on device dev.
*
* Returns 0 on success or negative error code on failure.
*/
static int i2o_block_device_flush(struct i2o_device *dev)
{
struct i2o_message *msg;
msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET);
if (IS_ERR(msg))
return PTR_ERR(msg);
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