[PATCH] I2O: first code cleanup of spare warnings and unused functions
Changes: - Removed unnecessary checking of NULL before calling kfree() - Make some functions static - Changed pr_debug() into osm_debug() - Use i2o_msg_in_to_virt() for getting a pointer to the message frame - Cleaned up some comments - Changed some le32_to_cpu() into readl() where necessary - Make error messages of OSM's look the same - Cleaned up error handling in i2o_block_end_request() - Removed unused error handling of failed messages in Block-OSM, which are not allowed by the I2O spec - Corrected the blocksize detection in i2o_block - Added hrt and lct sysfs-attribute to controller - Call done() function in SCSI-OSM after freeing DMA buffers - Removed unneeded variable for message size calculation in i2o_scsi_queuecommand() - Make some changes to remove sparse warnings - Reordered some functions - Cleaned up controller initialization - Replaced some magic numbers by defines - Removed unnecessary dma_sync_single_for_cpu() call on coherent DMA - Removed some unused fields in i2o_controller and removed some unused functions Signed-off-by: Markus Lidel <Markus.Lidel@shadowconnect.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
61fbfa8129
commit
f88e119c4b
@ -282,7 +282,6 @@ int i2o_device_parse_lct(struct i2o_controller *c)
|
|||||||
|
|
||||||
down(&c->lct_lock);
|
down(&c->lct_lock);
|
||||||
|
|
||||||
if (c->lct)
|
|
||||||
kfree(c->lct);
|
kfree(c->lct);
|
||||||
|
|
||||||
lct = c->dlct.virt;
|
lct = c->dlct.virt;
|
||||||
@ -447,7 +446,7 @@ static struct class_interface i2o_device_class_interface = {
|
|||||||
* ResultCount, ErrorInfoSize, BlockStatus and BlockSize.
|
* ResultCount, ErrorInfoSize, BlockStatus and BlockSize.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist,
|
static int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist,
|
||||||
int oplen, void *reslist, int reslen)
|
int oplen, void *reslist, int reslen)
|
||||||
{
|
{
|
||||||
struct i2o_message __iomem *msg;
|
struct i2o_message __iomem *msg;
|
||||||
@ -540,7 +539,7 @@ int i2o_parm_field_get(struct i2o_device *i2o_dev, int group, int field,
|
|||||||
opblk[4] = -1;
|
opblk[4] = -1;
|
||||||
|
|
||||||
size = i2o_parm_issue(i2o_dev, I2O_CMD_UTIL_PARAMS_GET, opblk,
|
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 */
|
memcpy(buf, resblk + 8, buflen); /* cut off header */
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
#include <linux/rwsem.h>
|
#include <linux/rwsem.h>
|
||||||
#include <linux/i2o.h>
|
#include <linux/i2o.h>
|
||||||
|
|
||||||
#define OSM_NAME "core"
|
#define OSM_NAME "i2o"
|
||||||
|
|
||||||
/* max_drivers - Maximum I2O drivers (OSMs) which could be registered */
|
/* max_drivers - Maximum I2O drivers (OSMs) which could be registered */
|
||||||
unsigned int i2o_max_drivers = I2O_MAX_DRIVERS;
|
unsigned int i2o_max_drivers = I2O_MAX_DRIVERS;
|
||||||
@ -78,17 +78,16 @@ int i2o_driver_register(struct i2o_driver *drv)
|
|||||||
int rc = 0;
|
int rc = 0;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
pr_debug("i2o: Register driver %s\n", drv->name);
|
osm_debug("Register driver %s\n", drv->name);
|
||||||
|
|
||||||
if (drv->event) {
|
if (drv->event) {
|
||||||
drv->event_queue = create_workqueue(drv->name);
|
drv->event_queue = create_workqueue(drv->name);
|
||||||
if (!drv->event_queue) {
|
if (!drv->event_queue) {
|
||||||
printk(KERN_ERR "i2o: Could not initialize event queue "
|
osm_err("Could not initialize event queue for driver "
|
||||||
"for driver %s\n", drv->name);
|
"%s\n", drv->name);
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
pr_debug("i2o: Event queue initialized for driver %s\n",
|
osm_debug("Event queue initialized for driver %s\n", drv->name);
|
||||||
drv->name);
|
|
||||||
} else
|
} else
|
||||||
drv->event_queue = NULL;
|
drv->event_queue = NULL;
|
||||||
|
|
||||||
@ -99,8 +98,8 @@ int i2o_driver_register(struct i2o_driver *drv)
|
|||||||
|
|
||||||
for (i = 0; i2o_drivers[i]; i++)
|
for (i = 0; i2o_drivers[i]; i++)
|
||||||
if (i >= i2o_max_drivers) {
|
if (i >= i2o_max_drivers) {
|
||||||
printk(KERN_ERR "i2o: too many drivers registered, "
|
osm_err("too many drivers registered, increase "
|
||||||
"increase max_drivers\n");
|
"max_drivers\n");
|
||||||
spin_unlock_irqrestore(&i2o_drivers_lock, flags);
|
spin_unlock_irqrestore(&i2o_drivers_lock, flags);
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
@ -110,8 +109,7 @@ int i2o_driver_register(struct i2o_driver *drv)
|
|||||||
|
|
||||||
spin_unlock_irqrestore(&i2o_drivers_lock, flags);
|
spin_unlock_irqrestore(&i2o_drivers_lock, flags);
|
||||||
|
|
||||||
pr_debug("i2o: driver %s gets context id %d\n", drv->name,
|
osm_debug("driver %s gets context id %d\n", drv->name, drv->context);
|
||||||
drv->context);
|
|
||||||
|
|
||||||
list_for_each_entry(c, &i2o_controllers, list) {
|
list_for_each_entry(c, &i2o_controllers, list) {
|
||||||
struct i2o_device *i2o_dev;
|
struct i2o_device *i2o_dev;
|
||||||
@ -141,7 +139,7 @@ void i2o_driver_unregister(struct i2o_driver *drv)
|
|||||||
struct i2o_controller *c;
|
struct i2o_controller *c;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
pr_debug("i2o: unregister driver %s\n", drv->name);
|
osm_debug("unregister driver %s\n", drv->name);
|
||||||
|
|
||||||
driver_unregister(&drv->driver);
|
driver_unregister(&drv->driver);
|
||||||
|
|
||||||
@ -161,7 +159,7 @@ void i2o_driver_unregister(struct i2o_driver *drv)
|
|||||||
if (drv->event_queue) {
|
if (drv->event_queue) {
|
||||||
destroy_workqueue(drv->event_queue);
|
destroy_workqueue(drv->event_queue);
|
||||||
drv->event_queue = NULL;
|
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
|
* on success and if the message should be flushed afterwords. Returns
|
||||||
* negative error code on failure (the message will be flushed too).
|
* negative error code on failure (the message will be flushed too).
|
||||||
*/
|
*/
|
||||||
int i2o_driver_dispatch(struct i2o_controller *c, u32 m,
|
int i2o_driver_dispatch(struct i2o_controller *c, u32 m)
|
||||||
struct i2o_message __iomem *msg)
|
|
||||||
{
|
{
|
||||||
struct i2o_driver *drv;
|
struct i2o_driver *drv;
|
||||||
|
struct i2o_message __iomem *msg = i2o_msg_out_to_virt(c, m);
|
||||||
u32 context = readl(&msg->u.s.icntxt);
|
u32 context = readl(&msg->u.s.icntxt);
|
||||||
|
|
||||||
if (unlikely(context >= i2o_max_drivers)) {
|
if (unlikely(context >= i2o_max_drivers)) {
|
||||||
printk(KERN_WARNING "%s: Spurious reply to unknown driver "
|
osm_warn("%s: Spurious reply to unknown driver %d\n", c->name,
|
||||||
"%d\n", c->name, readl(&msg->u.s.icntxt));
|
context);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,7 +193,8 @@ int i2o_driver_dispatch(struct i2o_controller *c, u32 m,
|
|||||||
spin_unlock(&i2o_drivers_lock);
|
spin_unlock(&i2o_drivers_lock);
|
||||||
|
|
||||||
if (unlikely(!drv)) {
|
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;
|
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);
|
osm_debug("event received from device %d\n", tid);
|
||||||
|
|
||||||
|
if (!drv->event)
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
/* cut of header from message size (in 32-bit words) */
|
/* cut of header from message size (in 32-bit words) */
|
||||||
size = (readl(&msg->u.head[0]) >> 16) - 5;
|
size = (readl(&msg->u.head[0]) >> 16) - 5;
|
||||||
|
|
||||||
@ -231,7 +233,7 @@ int i2o_driver_dispatch(struct i2o_controller *c, u32 m,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(!drv->reply)) {
|
if (unlikely(!drv->reply)) {
|
||||||
pr_debug("%s: Reply to driver %s, but no reply function"
|
osm_debug("%s: Reply to driver %s, but no reply function"
|
||||||
" defined!\n", c->name, drv->name);
|
" defined!\n", c->name, drv->name);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
@ -333,11 +335,11 @@ int __init i2o_driver_init(void)
|
|||||||
if ((i2o_max_drivers < 2) || (i2o_max_drivers > 64) ||
|
if ((i2o_max_drivers < 2) || (i2o_max_drivers > 64) ||
|
||||||
((i2o_max_drivers ^ (i2o_max_drivers - 1)) !=
|
((i2o_max_drivers ^ (i2o_max_drivers - 1)) !=
|
||||||
(2 * i2o_max_drivers - 1))) {
|
(2 * i2o_max_drivers - 1))) {
|
||||||
printk(KERN_WARNING "i2o: max_drivers set to %d, but must be "
|
osm_warn("max_drivers set to %d, but must be >=2 and <= 64 and "
|
||||||
">=2 and <= 64 and a power of 2\n", i2o_max_drivers);
|
"a power of 2\n", i2o_max_drivers);
|
||||||
i2o_max_drivers = 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 =
|
i2o_drivers =
|
||||||
kmalloc(i2o_max_drivers * sizeof(*i2o_drivers), GFP_KERNEL);
|
kmalloc(i2o_max_drivers * sizeof(*i2o_drivers), GFP_KERNEL);
|
||||||
|
@ -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
|
* buffer must not be freed. Instead the event completion will free them
|
||||||
* for you. In all other cases the buffer are your problem.
|
* 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
|
int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long
|
||||||
timeout, struct i2o_dma *dma)
|
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);
|
DECLARE_WAIT_QUEUE_HEAD(wq);
|
||||||
struct i2o_exec_wait *wait;
|
struct i2o_exec_wait *wait;
|
||||||
static u32 tcntxt = 0x80000000;
|
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;
|
int rc = 0;
|
||||||
|
|
||||||
wait = i2o_exec_wait_alloc();
|
wait = i2o_exec_wait_alloc();
|
||||||
@ -161,8 +162,7 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long
|
|||||||
barrier();
|
barrier();
|
||||||
|
|
||||||
if (wait->complete) {
|
if (wait->complete) {
|
||||||
if (readl(&wait->msg->body[0]) >> 24)
|
rc = readl(&wait->msg->body[0]) >> 24;
|
||||||
rc = readl(&wait->msg->body[0]) & 0xff;
|
|
||||||
i2o_flush_reply(c, wait->m);
|
i2o_flush_reply(c, wait->m);
|
||||||
i2o_exec_wait_free(wait);
|
i2o_exec_wait_free(wait);
|
||||||
} else {
|
} else {
|
||||||
@ -187,6 +187,7 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long
|
|||||||
* @c: I2O controller which answers
|
* @c: I2O controller which answers
|
||||||
* @m: message id
|
* @m: message id
|
||||||
* @msg: pointer to the I2O reply message
|
* @msg: pointer to the I2O reply message
|
||||||
|
* @context: transaction context of request
|
||||||
*
|
*
|
||||||
* This function is called in interrupt context only. If the reply reached
|
* 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
|
* 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.
|
* message must also be given back to the controller.
|
||||||
*/
|
*/
|
||||||
static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m,
|
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;
|
struct i2o_exec_wait *wait, *tmp;
|
||||||
static spinlock_t lock = SPIN_LOCK_UNLOCKED;
|
static spinlock_t lock = SPIN_LOCK_UNLOCKED;
|
||||||
int rc = 1;
|
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
|
* 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);
|
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);
|
context);
|
||||||
|
|
||||||
return -1;
|
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.
|
* code on failure and if the reply should be flushed.
|
||||||
*/
|
*/
|
||||||
static int i2o_exec_reply(struct i2o_controller *c, u32 m,
|
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
|
u32 context;
|
||||||
struct i2o_message __iomem *pmsg; /* preserved message */
|
|
||||||
|
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;
|
u32 pm;
|
||||||
|
|
||||||
pm = le32_to_cpu(msg->body[3]);
|
pm = readl(&msg->body[3]);
|
||||||
|
|
||||||
pmsg = i2o_msg_in_to_virt(c, pm);
|
pmsg = i2o_msg_in_to_virt(c, pm);
|
||||||
|
|
||||||
i2o_report_status(KERN_INFO, "i2o_core", msg);
|
i2o_report_status(KERN_INFO, "i2o_core", msg);
|
||||||
|
|
||||||
/* Release the preserved msg by resubmitting it as a NOP */
|
context = readl(&pmsg->u.s.tcntxt);
|
||||||
|
|
||||||
|
/* Release the preserved msg */
|
||||||
i2o_msg_nop(c, pm);
|
i2o_msg_nop(c, pm);
|
||||||
|
} else
|
||||||
|
context = readl(&msg->u.s.tcntxt);
|
||||||
|
|
||||||
/* If reply to i2o_post_wait failed, return causes a timeout */
|
if (context & 0x80000000)
|
||||||
return -1;
|
return i2o_msg_post_wait_complete(c, m, msg, context);
|
||||||
}
|
|
||||||
|
|
||||||
if (le32_to_cpu(msg->u.s.tcntxt) & 0x80000000)
|
if ((readl(&msg->u.head[1]) >> 24) == I2O_CMD_LCT_NOTIFY) {
|
||||||
return i2o_msg_post_wait_complete(c, m, msg);
|
|
||||||
|
|
||||||
if ((le32_to_cpu(msg->u.head[1]) >> 24) == I2O_CMD_LCT_NOTIFY) {
|
|
||||||
struct work_struct *work;
|
struct work_struct *work;
|
||||||
|
|
||||||
pr_debug("%s: LCT notify received\n", c->name);
|
pr_debug("%s: LCT notify received\n", c->name);
|
||||||
|
@ -104,7 +104,8 @@ static int i2o_block_remove(struct device *dev)
|
|||||||
struct i2o_device *i2o_dev = to_i2o_device(dev);
|
struct i2o_device *i2o_dev = to_i2o_device(dev);
|
||||||
struct i2o_block_device *i2o_blk_dev = dev_get_drvdata(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);
|
i2o_event_register(i2o_dev, &i2o_block_driver, 0, 0);
|
||||||
|
|
||||||
@ -399,6 +400,49 @@ static void i2o_block_delayed_request_fn(void *delayed_request)
|
|||||||
kfree(dreq);
|
kfree(dreq);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* Mark the request as complete. The lock must not be held when entering.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void i2o_block_end_request(struct request *req, int uptodate,
|
||||||
|
int nr_bytes)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
|
||||||
|
if (end_that_request_chunk(req, uptodate, nr_bytes)) {
|
||||||
|
int leftover = (req->hard_nr_sectors << 9);
|
||||||
|
|
||||||
|
if (blk_pc_request(req))
|
||||||
|
leftover = req->data_len;
|
||||||
|
|
||||||
|
if (end_io_error(uptodate))
|
||||||
|
end_that_request_chunk(req, 0, leftover);
|
||||||
|
}
|
||||||
|
|
||||||
|
add_disk_randomness(req->rq_disk);
|
||||||
|
|
||||||
|
spin_lock_irqsave(q->queue_lock, flags);
|
||||||
|
|
||||||
|
end_that_request_last(req);
|
||||||
|
dev->open_queue_depth--;
|
||||||
|
list_del(&ireq->queue);
|
||||||
|
|
||||||
|
blk_start_queue(q);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(q->queue_lock, flags);
|
||||||
|
|
||||||
|
i2o_block_sglist_free(ireq);
|
||||||
|
i2o_block_request_free(ireq);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* i2o_block_reply - Block OSM reply handler.
|
* i2o_block_reply - Block OSM reply handler.
|
||||||
* @c: I2O controller from which the message arrives
|
* @c: I2O controller from which the message arrives
|
||||||
@ -411,60 +455,8 @@ static void i2o_block_delayed_request_fn(void *delayed_request)
|
|||||||
static int i2o_block_reply(struct i2o_controller *c, u32 m,
|
static int i2o_block_reply(struct i2o_controller *c, u32 m,
|
||||||
struct i2o_message *msg)
|
struct i2o_message *msg)
|
||||||
{
|
{
|
||||||
struct i2o_block_request *ireq;
|
|
||||||
struct request *req;
|
struct request *req;
|
||||||
struct i2o_block_device *dev;
|
int uptodate = 1;
|
||||||
struct request_queue *q;
|
|
||||||
u8 st;
|
|
||||||
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);
|
|
||||||
|
|
||||||
req = i2o_cntxt_list_get(c, le32_to_cpu(pmsg->u.s.tcntxt));
|
|
||||||
if (unlikely(!req)) {
|
|
||||||
osm_err("NULL reply received!\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ireq = req->special;
|
|
||||||
dev = ireq->i2o_blk_dev;
|
|
||||||
q = dev->gd->queue;
|
|
||||||
|
|
||||||
req->errors++;
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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, le32_to_cpu(msg->u.s.tcntxt));
|
req = i2o_cntxt_list_get(c, le32_to_cpu(msg->u.s.tcntxt));
|
||||||
if (unlikely(!req)) {
|
if (unlikely(!req)) {
|
||||||
@ -472,61 +464,13 @@ static int i2o_block_reply(struct i2o_controller *c, u32 m,
|
|||||||
return -1;
|
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
|
* Lets see what is cooking. We stuffed the
|
||||||
* request in the context.
|
* request in the context.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
st = le32_to_cpu(msg->body[0]) >> 24;
|
if ((le32_to_cpu(msg->body[0]) >> 24) != 0) {
|
||||||
|
u32 status = le32_to_cpu(msg->body[0]);
|
||||||
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;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Device not ready means two things. One is that the
|
* Device not ready means two things. One is that the
|
||||||
* the thing went offline (but not a removal media)
|
* 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
|
* Don't stick a supertrak100 into cache aggressive modes
|
||||||
*/
|
*/
|
||||||
|
|
||||||
osm_err("block-osm: /dev/%s error: %s", dev->gd->disk_name,
|
osm_err("%03x error status: %02x, detailed status: %04x\n",
|
||||||
bsa_errors[le32_to_cpu(msg->body[0]) & 0xffff]);
|
(le32_to_cpu(msg->u.head[1]) >> 12 & 0xfff),
|
||||||
if (le32_to_cpu(msg->body[0]) & 0x00ff0000)
|
status >> 24, status & 0xffff);
|
||||||
printk(KERN_ERR " - DDM attempted %d retries",
|
|
||||||
(le32_to_cpu(msg->body[0]) >> 16) & 0x00ff);
|
|
||||||
printk(KERN_ERR ".\n");
|
|
||||||
req->errors++;
|
req->errors++;
|
||||||
} else
|
|
||||||
req->errors = 0;
|
|
||||||
|
|
||||||
if (!end_that_request_chunk
|
uptodate = 0;
|
||||||
(req, !req->errors, le32_to_cpu(msg->body[1]))) {
|
}
|
||||||
add_disk_randomness(req->rq_disk);
|
|
||||||
spin_lock_irqsave(q->queue_lock, flags);
|
|
||||||
|
|
||||||
end_that_request_last(req);
|
i2o_block_end_request(req, uptodate, le32_to_cpu(msg->body[1]));
|
||||||
|
|
||||||
dev->open_queue_depth--;
|
|
||||||
list_del(&ireq->queue);
|
|
||||||
blk_start_queue(q);
|
|
||||||
|
|
||||||
spin_unlock_irqrestore(q->queue_lock, flags);
|
|
||||||
|
|
||||||
i2o_block_sglist_free(ireq);
|
|
||||||
i2o_block_request_free(ireq);
|
|
||||||
} else
|
|
||||||
osm_err("still remaining chunks\n");
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void i2o_block_event(struct i2o_event *evt)
|
static void i2o_block_event(struct i2o_event *evt)
|
||||||
{
|
{
|
||||||
osm_info("block-osm: event received\n");
|
osm_info("event received\n");
|
||||||
kfree(evt);
|
kfree(evt);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -875,9 +802,7 @@ static int i2o_block_transfer(struct request *req)
|
|||||||
sg++;
|
sg++;
|
||||||
}
|
}
|
||||||
|
|
||||||
writel(I2O_MESSAGE_SIZE
|
writel(I2O_MESSAGE_SIZE(mptr - &msg->u.head[0]) | SGL_OFFSET_8,
|
||||||
(((unsigned long)mptr -
|
|
||||||
(unsigned long)&msg->u.head[0]) >> 2) | SGL_OFFSET_8,
|
|
||||||
&msg->u.head[0]);
|
&msg->u.head[0]);
|
||||||
|
|
||||||
list_add_tail(&ireq->queue, &dev->open_queue);
|
list_add_tail(&ireq->queue, &dev->open_queue);
|
||||||
@ -1048,7 +973,6 @@ static int i2o_block_probe(struct device *dev)
|
|||||||
int rc;
|
int rc;
|
||||||
u64 size;
|
u64 size;
|
||||||
u32 blocksize;
|
u32 blocksize;
|
||||||
u16 power;
|
|
||||||
u32 flags, status;
|
u32 flags, status;
|
||||||
int segments;
|
int segments;
|
||||||
|
|
||||||
@ -1058,8 +982,6 @@ static int i2o_block_probe(struct device *dev)
|
|||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
osm_info("New device detected (TID: %03x)\n", i2o_dev->lct_data.tid);
|
|
||||||
|
|
||||||
if (i2o_device_claim(i2o_dev)) {
|
if (i2o_device_claim(i2o_dev)) {
|
||||||
osm_warn("Unable to claim device. Installation aborted\n");
|
osm_warn("Unable to claim device. Installation aborted\n");
|
||||||
rc = -EFAULT;
|
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
|
* Ask for the current media data. If that isn't supported
|
||||||
* then we ask for the device capacity data
|
* then we ask for the device capacity data
|
||||||
*/
|
*/
|
||||||
if (i2o_parm_field_get(i2o_dev, 0x0004, 1, &blocksize, 4) != 0
|
if (!i2o_parm_field_get(i2o_dev, 0x0004, 0, &size, 8))
|
||||||
|| i2o_parm_field_get(i2o_dev, 0x0004, 0, &size, 8) != 0) {
|
if (!i2o_parm_field_get(i2o_dev, 0x0000, 4, &size, 8)) {
|
||||||
i2o_parm_field_get(i2o_dev, 0x0000, 3, &blocksize, 4);
|
osm_warn("could not get size of %s\n", gd->disk_name);
|
||||||
i2o_parm_field_get(i2o_dev, 0x0000, 4, &size, 8);
|
size = 0;
|
||||||
}
|
}
|
||||||
osm_debug("blocksize = %d\n", blocksize);
|
|
||||||
|
|
||||||
if (i2o_parm_field_get(i2o_dev, 0x0000, 2, &power, 2))
|
if (!i2o_parm_field_get(i2o_dev, 0x0004, 1, &blocksize, 4))
|
||||||
power = 0;
|
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, 5, &flags, 4);
|
||||||
i2o_parm_field_get(i2o_dev, 0x0000, 6, &status, 4);
|
i2o_parm_field_get(i2o_dev, 0x0000, 6, &status, 4);
|
||||||
|
|
||||||
@ -1131,6 +1059,9 @@ static int i2o_block_probe(struct device *dev)
|
|||||||
|
|
||||||
unit++;
|
unit++;
|
||||||
|
|
||||||
|
osm_info("device added (TID: %03x): %s\n", i2o_dev->lct_data.tid,
|
||||||
|
i2o_blk_dev->gd->disk_name);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
claim_release:
|
claim_release:
|
||||||
|
@ -74,7 +74,7 @@ struct i2o_block_device {
|
|||||||
int rcache; /* read cache flags */
|
int rcache; /* read cache flags */
|
||||||
int wcache; /* write cache flags */
|
int wcache; /* write cache flags */
|
||||||
int flags;
|
int flags;
|
||||||
int power; /* power state */
|
u16 power; /* power state */
|
||||||
int media_change_flag; /* media changed flag */
|
int media_change_flag; /* media changed flag */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -80,13 +80,123 @@ struct i2o_cfg_info {
|
|||||||
static struct i2o_cfg_info *open_files = NULL;
|
static struct i2o_cfg_info *open_files = NULL;
|
||||||
static ulong i2o_cfg_info_id = 0;
|
static ulong i2o_cfg_info_id = 0;
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Each of these describes an i2o message handler. They are
|
* i2o_config_read_hrt - Returns the HRT of the controller
|
||||||
* multiplexed by the i2o_core code
|
* @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 = {
|
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)
|
static int i2o_cfg_getiops(unsigned long arg)
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
* Fix the resource management problems.
|
* Fix the resource management problems.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define DEBUG 1
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
@ -179,6 +180,8 @@ static int i2o_scsi_remove(struct device *dev)
|
|||||||
struct i2o_scsi_host *i2o_shost;
|
struct i2o_scsi_host *i2o_shost;
|
||||||
struct scsi_device *scsi_dev;
|
struct scsi_device *scsi_dev;
|
||||||
|
|
||||||
|
osm_info("device removed (TID: %03x)\n", i2o_dev->lct_data.tid);
|
||||||
|
|
||||||
i2o_shost = i2o_scsi_get_host(c);
|
i2o_shost = i2o_scsi_get_host(c);
|
||||||
|
|
||||||
shost_for_each_device(scsi_dev, i2o_shost->scsi_host)
|
shost_for_each_device(scsi_dev, i2o_shost->scsi_host)
|
||||||
@ -262,7 +265,7 @@ static int i2o_scsi_probe(struct device *dev)
|
|||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
osm_debug("added new SCSI device %03x (cannel: %d, id: %d, lun: %d)\n",
|
osm_info("device added (TID: %03x) channel: %d, id: %d, lun: %d\n",
|
||||||
i2o_dev->lct_data.tid, channel, id, (unsigned int)lun);
|
i2o_dev->lct_data.tid, channel, id, (unsigned int)lun);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -439,8 +442,6 @@ static int i2o_scsi_reply(struct i2o_controller *c, u32 m,
|
|||||||
|
|
||||||
cmd->result = DID_OK << 16 | ds;
|
cmd->result = DID_OK << 16 | ds;
|
||||||
|
|
||||||
cmd->scsi_done(cmd);
|
|
||||||
|
|
||||||
dev = &c->pdev->dev;
|
dev = &c->pdev->dev;
|
||||||
if (cmd->use_sg)
|
if (cmd->use_sg)
|
||||||
dma_unmap_sg(dev, (struct scatterlist *)cmd->buffer,
|
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),
|
dma_unmap_single(dev, (dma_addr_t) ((long)cmd->SCp.ptr),
|
||||||
cmd->request_bufflen, cmd->sc_data_direction);
|
cmd->request_bufflen, cmd->sc_data_direction);
|
||||||
|
|
||||||
|
cmd->scsi_done(cmd);
|
||||||
|
|
||||||
return 1;
|
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_remove_host(i2o_shost->scsi_host);
|
||||||
scsi_host_put(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 */
|
/* SCSI OSM driver struct */
|
||||||
@ -545,7 +548,7 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
|
|||||||
u32 scsi_flags, sg_flags;
|
u32 scsi_flags, sg_flags;
|
||||||
u32 __iomem *mptr;
|
u32 __iomem *mptr;
|
||||||
u32 __iomem *lenptr;
|
u32 __iomem *lenptr;
|
||||||
u32 len, reqlen;
|
u32 len;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -580,12 +583,12 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
|
|||||||
if (m == I2O_QUEUE_EMPTY)
|
if (m == I2O_QUEUE_EMPTY)
|
||||||
return SCSI_MLQUEUE_HOST_BUSY;
|
return SCSI_MLQUEUE_HOST_BUSY;
|
||||||
|
|
||||||
|
mptr = &msg->body[0];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Put together a scsi execscb message
|
* Put together a scsi execscb message
|
||||||
*/
|
*/
|
||||||
|
|
||||||
len = SCpnt->request_bufflen;
|
|
||||||
|
|
||||||
switch (SCpnt->sc_data_direction) {
|
switch (SCpnt->sc_data_direction) {
|
||||||
case PCI_DMA_NONE:
|
case PCI_DMA_NONE:
|
||||||
scsi_flags = 0x00000000; // DATA NO XFER
|
scsi_flags = 0x00000000; // DATA NO XFER
|
||||||
@ -637,17 +640,13 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* Direction, disconnect ok, tag, CDBLen */
|
/* Direction, disconnect ok, tag, CDBLen */
|
||||||
writel(scsi_flags | 0x20200000 | SCpnt->cmd_len, &msg->body[0]);
|
writel(scsi_flags | 0x20200000 | SCpnt->cmd_len, mptr ++);
|
||||||
|
|
||||||
mptr = &msg->body[1];
|
|
||||||
|
|
||||||
/* Write SCSI command into the message - always 16 byte block */
|
/* Write SCSI command into the message - always 16 byte block */
|
||||||
memcpy_toio(mptr, SCpnt->cmnd, 16);
|
memcpy_toio(mptr, SCpnt->cmnd, 16);
|
||||||
mptr += 4;
|
mptr += 4;
|
||||||
lenptr = mptr++; /* Remember me - fill in when we know */
|
lenptr = mptr++; /* Remember me - fill in when we know */
|
||||||
|
|
||||||
reqlen = 12; // SINGLE SGE
|
|
||||||
|
|
||||||
/* Now fill in the SGList and command */
|
/* Now fill in the SGList and command */
|
||||||
if (SCpnt->use_sg) {
|
if (SCpnt->use_sg) {
|
||||||
struct scatterlist *sg;
|
struct scatterlist *sg;
|
||||||
@ -671,7 +670,6 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
|
|||||||
sg++;
|
sg++;
|
||||||
}
|
}
|
||||||
|
|
||||||
reqlen = mptr - &msg->u.head[0];
|
|
||||||
writel(len, lenptr);
|
writel(len, lenptr);
|
||||||
} else {
|
} else {
|
||||||
len = SCpnt->request_bufflen;
|
len = SCpnt->request_bufflen;
|
||||||
@ -691,12 +689,11 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
|
|||||||
sg_flags |= 0xC0000000;
|
sg_flags |= 0xC0000000;
|
||||||
writel(sg_flags | SCpnt->request_bufflen, mptr++);
|
writel(sg_flags | SCpnt->request_bufflen, mptr++);
|
||||||
writel(dma_addr, mptr++);
|
writel(dma_addr, mptr++);
|
||||||
} else
|
}
|
||||||
reqlen = 9;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Stick the headers on */
|
/* 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 */
|
/* Queue the message */
|
||||||
i2o_msg_post(c, m);
|
i2o_msg_post(c, m);
|
||||||
|
@ -68,7 +68,7 @@ extern void i2o_device_exit(void);
|
|||||||
*/
|
*/
|
||||||
void i2o_msg_nop(struct i2o_controller *c, u32 m)
|
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(THREE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
|
||||||
writel(I2O_CMD_UTIL_NOP << 24 | HOST_TID << 12 | ADAPTER_TID,
|
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 */
|
/* Enable all IOPs */
|
||||||
i2o_iop_enable_all();
|
i2o_iop_enable_all();
|
||||||
|
|
||||||
i2o_status_get(c);
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -591,12 +589,11 @@ static int i2o_iop_init_outbound_queue(struct i2o_controller *c)
|
|||||||
if (m == I2O_QUEUE_EMPTY)
|
if (m == I2O_QUEUE_EMPTY)
|
||||||
return -ETIMEDOUT;
|
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,
|
writel(I2O_CMD_OUTBOUND_INIT << 24 | HOST_TID << 12 | ADAPTER_TID,
|
||||||
&msg->u.head[1]);
|
&msg->u.head[1]);
|
||||||
writel(i2o_exec_driver.context, &msg->u.s.icntxt);
|
writel(i2o_exec_driver.context, &msg->u.s.icntxt);
|
||||||
writel(0x0106, &msg->u.s.tcntxt); /* FIXME: why 0x0106, maybe in
|
writel(0x00000000, &msg->u.s.tcntxt);
|
||||||
Spec? */
|
|
||||||
writel(PAGE_SIZE, &msg->body[0]);
|
writel(PAGE_SIZE, &msg->body[0]);
|
||||||
writel(MSG_FRAME_SIZE << 16 | 0x80, &msg->body[1]); /* Outbound msg frame
|
writel(MSG_FRAME_SIZE << 16 | 0x80, &msg->body[1]); /* Outbound msg frame
|
||||||
size in words and Initcode */
|
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)
|
list_for_each_entry_safe(dev, tmp, &c->devices, list)
|
||||||
i2o_device_remove(dev);
|
i2o_device_remove(dev);
|
||||||
|
|
||||||
|
device_del(&c->device);
|
||||||
|
|
||||||
/* Ask the IOP to switch to RESET state */
|
/* Ask the IOP to switch to RESET state */
|
||||||
i2o_iop_reset(c);
|
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].frame_size = sb->inbound_frame_size;
|
||||||
systab->iops[count].last_changed = change_ind;
|
systab->iops[count].last_changed = change_ind;
|
||||||
systab->iops[count].iop_capabilities = sb->iop_capabilities;
|
systab->iops[count].iop_capabilities = sb->iop_capabilities;
|
||||||
systab->iops[count].inbound_low = i2o_ptr_low(c->post_port);
|
systab->iops[count].inbound_low =
|
||||||
systab->iops[count].inbound_high = i2o_ptr_high(c->post_port);
|
i2o_dma_low(c->base.phys + I2O_IN_PORT);
|
||||||
|
systab->iops[count].inbound_high =
|
||||||
|
i2o_dma_high(c->base.phys + I2O_IN_PORT);
|
||||||
|
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
@ -1109,6 +1112,30 @@ static int i2o_hrt_get(struct i2o_controller *c)
|
|||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
* i2o_iop_alloc - Allocate and initialize a i2o_controller struct
|
||||||
*
|
*
|
||||||
@ -1137,6 +1164,10 @@ struct i2o_controller *i2o_iop_alloc(void)
|
|||||||
c->unit = unit++;
|
c->unit = unit++;
|
||||||
sprintf(c->name, "iop%d", c->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
|
#if BITS_PER_LONG == 64
|
||||||
spin_lock_init(&c->context_list_lock);
|
spin_lock_init(&c->context_list_lock);
|
||||||
atomic_set(&c->context_list_counter, 0);
|
atomic_set(&c->context_list_counter, 0);
|
||||||
@ -1146,15 +1177,6 @@ struct i2o_controller *i2o_iop_alloc(void)
|
|||||||
return c;
|
return 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_add - Initialize the I2O controller and add him to the I2O core
|
* i2o_iop_add - Initialize the I2O controller and add him to the I2O core
|
||||||
* @c: controller
|
* @c: controller
|
||||||
@ -1168,6 +1190,11 @@ int i2o_iop_add(struct i2o_controller *c)
|
|||||||
{
|
{
|
||||||
int rc;
|
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: Activating I2O controller...\n", c->name);
|
||||||
printk(KERN_INFO "%s: This may take a few minutes if there are many "
|
printk(KERN_INFO "%s: This may take a few minutes if there are many "
|
||||||
"devices\n", c->name);
|
"devices\n", c->name);
|
||||||
@ -1175,30 +1202,23 @@ int i2o_iop_add(struct i2o_controller *c)
|
|||||||
if ((rc = i2o_iop_activate(c))) {
|
if ((rc = i2o_iop_activate(c))) {
|
||||||
printk(KERN_ERR "%s: could not activate controller\n",
|
printk(KERN_ERR "%s: could not activate controller\n",
|
||||||
c->name);
|
c->name);
|
||||||
i2o_iop_reset(c);
|
goto iop_reset;
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pr_debug("%s: building sys table...\n", c->name);
|
pr_debug("%s: building sys table...\n", c->name);
|
||||||
|
|
||||||
if ((rc = i2o_systab_build())) {
|
if ((rc = i2o_systab_build()))
|
||||||
i2o_iop_reset(c);
|
goto iop_reset;
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
pr_debug("%s: online controller...\n", c->name);
|
pr_debug("%s: online controller...\n", c->name);
|
||||||
|
|
||||||
if ((rc = i2o_iop_online(c))) {
|
if ((rc = i2o_iop_online(c)))
|
||||||
i2o_iop_reset(c);
|
goto iop_reset;
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
pr_debug("%s: getting LCT...\n", c->name);
|
pr_debug("%s: getting LCT...\n", c->name);
|
||||||
|
|
||||||
if ((rc = i2o_exec_lct_get(c))) {
|
if ((rc = i2o_exec_lct_get(c)))
|
||||||
i2o_iop_reset(c);
|
goto iop_reset;
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
list_add(&c->list, &i2o_controllers);
|
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);
|
printk(KERN_INFO "%s: Controller added\n", c->name);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
iop_reset:
|
||||||
|
i2o_iop_reset(c);
|
||||||
|
|
||||||
|
return rc;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -38,8 +38,7 @@ extern void i2o_iop_free(struct i2o_controller *);
|
|||||||
extern int i2o_iop_add(struct i2o_controller *);
|
extern int i2o_iop_add(struct i2o_controller *);
|
||||||
extern void i2o_iop_remove(struct i2o_controller *);
|
extern void i2o_iop_remove(struct i2o_controller *);
|
||||||
|
|
||||||
extern int i2o_driver_dispatch(struct i2o_controller *, u32,
|
extern int i2o_driver_dispatch(struct i2o_controller *, u32);
|
||||||
struct i2o_message *);
|
|
||||||
|
|
||||||
/* PCI device id table for all I2O controllers */
|
/* PCI device id table for all I2O controllers */
|
||||||
static struct pci_device_id __devinitdata i2o_pci_ids[] = {
|
static struct pci_device_id __devinitdata i2o_pci_ids[] = {
|
||||||
@ -89,7 +88,6 @@ static void i2o_pci_free(struct i2o_controller *c)
|
|||||||
|
|
||||||
i2o_dma_free(dev, &c->out_queue);
|
i2o_dma_free(dev, &c->out_queue);
|
||||||
i2o_dma_free(dev, &c->status_block);
|
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->dlct);
|
||||||
i2o_dma_free(dev, &c->hrt);
|
i2o_dma_free(dev, &c->hrt);
|
||||||
@ -187,9 +185,9 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c)
|
|||||||
} else
|
} else
|
||||||
c->in_queue = c->base;
|
c->in_queue = c->base;
|
||||||
|
|
||||||
c->irq_mask = c->base.virt + 0x34;
|
c->irq_mask = c->base.virt + I2O_IRQ_MASK;
|
||||||
c->post_port = c->base.virt + 0x40;
|
c->in_port = c->base.virt + I2O_IN_PORT;
|
||||||
c->reply_port = c->base.virt + 0x44;
|
c->out_port = c->base.virt + I2O_OUT_PORT;
|
||||||
|
|
||||||
if (i2o_dma_alloc(dev, &c->status, 8, GFP_KERNEL)) {
|
if (i2o_dma_alloc(dev, &c->status, 8, GFP_KERNEL)) {
|
||||||
i2o_pci_free(c);
|
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 i2o_controller *c = dev_id;
|
||||||
struct device *dev = &c->pdev->dev;
|
struct device *dev = &c->pdev->dev;
|
||||||
struct i2o_message *m;
|
u32 mv = readl(c->out_port);
|
||||||
u32 mv;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Old 960 steppings had a bug in the I2O unit that caused
|
* Old 960 steppings had a bug in the I2O unit that caused
|
||||||
* the queue to appear empty when it wasn't.
|
* the queue to appear empty when it wasn't.
|
||||||
*/
|
*/
|
||||||
mv = I2O_REPLY_READ32(c);
|
|
||||||
if (mv == I2O_QUEUE_EMPTY) {
|
if (mv == I2O_QUEUE_EMPTY) {
|
||||||
mv = I2O_REPLY_READ32(c);
|
mv = readl(c->out_port);
|
||||||
if (unlikely(mv == I2O_QUEUE_EMPTY)) {
|
if (unlikely(mv == I2O_QUEUE_EMPTY))
|
||||||
return IRQ_NONE;
|
return IRQ_NONE;
|
||||||
} else
|
else
|
||||||
pr_debug("%s: 960 bug detected\n", c->name);
|
pr_debug("%s: 960 bug detected\n", c->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (mv != I2O_QUEUE_EMPTY) {
|
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 */
|
/* dispatch it */
|
||||||
if (i2o_driver_dispatch(c, mv, m))
|
if (i2o_driver_dispatch(c, mv))
|
||||||
/* flush it if result != 0 */
|
/* flush it if result != 0 */
|
||||||
i2o_flush_reply(c, mv);
|
i2o_flush_reply(c, mv);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* That 960 bug again...
|
* That 960 bug again...
|
||||||
*/
|
*/
|
||||||
mv = I2O_REPLY_READ32(c);
|
mv = readl(c->out_port);
|
||||||
if (mv == I2O_QUEUE_EMPTY)
|
if (mv == I2O_QUEUE_EMPTY)
|
||||||
mv = I2O_REPLY_READ32(c);
|
mv = readl(c->out_port);
|
||||||
}
|
}
|
||||||
|
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,7 +277,9 @@ static int i2o_pci_irq_enable(struct i2o_controller *c)
|
|||||||
struct pci_dev *pdev = c->pdev;
|
struct pci_dev *pdev = c->pdev;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
I2O_IRQ_WRITE32(c, 0xffffffff);
|
wmb();
|
||||||
|
writel(0xffffffff, c->irq_mask);
|
||||||
|
wmb();
|
||||||
|
|
||||||
if (pdev->irq) {
|
if (pdev->irq) {
|
||||||
rc = request_irq(pdev->irq, i2o_pci_interrupt, SA_SHIRQ,
|
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);
|
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)
|
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)
|
if (c->pdev->irq > 0)
|
||||||
free_irq(c->pdev->irq, c);
|
free_irq(c->pdev->irq, c);
|
||||||
@ -379,7 +367,7 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev,
|
|||||||
pci_name(pdev));
|
pci_name(pdev));
|
||||||
|
|
||||||
c->pdev = 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... */
|
/* Cards that fall apart if you hit them with large I/O loads... */
|
||||||
if (pdev->vendor == PCI_VENDOR_ID_NCR && pdev->device == 0x0630) {
|
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)
|
if (i960)
|
||||||
pci_write_config_word(i960, 0x42, 0x03ff);
|
pci_write_config_word(i960, 0x42, 0x03ff);
|
||||||
|
|
||||||
|
get_device(&c->device);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
uninstall:
|
uninstall:
|
||||||
@ -438,6 +428,7 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev,
|
|||||||
|
|
||||||
free_controller:
|
free_controller:
|
||||||
i2o_iop_free(c);
|
i2o_iop_free(c);
|
||||||
|
put_device(c->device.parent);
|
||||||
|
|
||||||
disable:
|
disable:
|
||||||
pci_disable_device(pdev);
|
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_irq_disable(c);
|
||||||
i2o_pci_free(c);
|
i2o_pci_free(c);
|
||||||
|
|
||||||
|
pci_disable_device(pdev);
|
||||||
|
|
||||||
printk(KERN_INFO "%s: Controller removed.\n", c->name);
|
printk(KERN_INFO "%s: Controller removed.\n", c->name);
|
||||||
|
|
||||||
i2o_iop_free(c);
|
put_device(c->device.parent);
|
||||||
pci_disable_device(pdev);
|
put_device(&c->device);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* PCI driver for I2O controller */
|
/* PCI driver for I2O controller */
|
||||||
static struct pci_driver i2o_pci_driver = {
|
static struct pci_driver i2o_pci_driver = {
|
||||||
.name = "I2O controller",
|
.name = "PCI_I2O",
|
||||||
.id_table = i2o_pci_ids,
|
.id_table = i2o_pci_ids,
|
||||||
.probe = i2o_pci_probe,
|
.probe = i2o_pci_probe,
|
||||||
.remove = __devexit_p(i2o_pci_remove),
|
.remove = __devexit_p(i2o_pci_remove),
|
||||||
|
@ -153,12 +153,10 @@ struct i2o_controller {
|
|||||||
unsigned int promise:1; /* Promise controller */
|
unsigned int promise:1; /* Promise controller */
|
||||||
|
|
||||||
struct list_head devices; /* list of I2O devices */
|
struct list_head devices; /* list of I2O devices */
|
||||||
|
|
||||||
struct notifier_block *event_notifer; /* Events */
|
|
||||||
atomic_t users;
|
|
||||||
struct list_head list; /* Controller list */
|
struct list_head list; /* Controller list */
|
||||||
void __iomem *post_port; /* Inbout port address */
|
|
||||||
void __iomem *reply_port; /* Outbound port address */
|
void __iomem *in_port; /* Inbout port address */
|
||||||
|
void __iomem *out_port; /* Outbound port address */
|
||||||
void __iomem *irq_mask; /* Interrupt register address */
|
void __iomem *irq_mask; /* Interrupt register address */
|
||||||
|
|
||||||
/* Dynamic LCT related data */
|
/* Dynamic LCT related data */
|
||||||
@ -182,9 +180,6 @@ struct i2o_controller {
|
|||||||
struct resource io_resource; /* I/O resource allocated to the IOP */
|
struct resource io_resource; /* I/O resource allocated to the IOP */
|
||||||
struct resource mem_resource; /* Mem resource allocated to the IOP */
|
struct resource mem_resource; /* Mem resource allocated to the IOP */
|
||||||
|
|
||||||
struct proc_dir_entry *proc_entry; /* /proc dir */
|
|
||||||
|
|
||||||
struct list_head bus_list; /* list of busses on IOP */
|
|
||||||
struct device device;
|
struct device device;
|
||||||
struct i2o_device *exec; /* Executive */
|
struct i2o_device *exec; /* Executive */
|
||||||
#if BITS_PER_LONG == 64
|
#if BITS_PER_LONG == 64
|
||||||
@ -380,49 +375,10 @@ extern int i2o_device_claim_release(struct i2o_device *);
|
|||||||
/* Exec OSM functions */
|
/* Exec OSM functions */
|
||||||
extern int i2o_exec_lct_get(struct i2o_controller *);
|
extern int i2o_exec_lct_get(struct i2o_controller *);
|
||||||
|
|
||||||
/* device to i2o_device and driver to i2o_driver convertion functions */
|
/* device / driver conversion functions */
|
||||||
#define to_i2o_driver(drv) container_of(drv,struct i2o_driver, driver)
|
#define to_i2o_driver(drv) container_of(drv,struct i2o_driver, driver)
|
||||||
#define to_i2o_device(dev) container_of(dev, struct i2o_device, device)
|
#define to_i2o_device(dev) container_of(dev, struct i2o_device, device)
|
||||||
|
#define to_i2o_controller(dev) container_of(dev, struct i2o_controller, device)
|
||||||
/*
|
|
||||||
* Messenger inlines
|
|
||||||
*/
|
|
||||||
static inline u32 I2O_POST_READ32(struct i2o_controller *c)
|
|
||||||
{
|
|
||||||
rmb();
|
|
||||||
return readl(c->post_port);
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline void I2O_POST_WRITE32(struct i2o_controller *c, u32 val)
|
|
||||||
{
|
|
||||||
wmb();
|
|
||||||
writel(val, c->post_port);
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline u32 I2O_REPLY_READ32(struct i2o_controller *c)
|
|
||||||
{
|
|
||||||
rmb();
|
|
||||||
return readl(c->reply_port);
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline void I2O_REPLY_WRITE32(struct i2o_controller *c, u32 val)
|
|
||||||
{
|
|
||||||
wmb();
|
|
||||||
writel(val, c->reply_port);
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline u32 I2O_IRQ_READ32(struct i2o_controller *c)
|
|
||||||
{
|
|
||||||
rmb();
|
|
||||||
return readl(c->irq_mask);
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline void I2O_IRQ_WRITE32(struct i2o_controller *c, u32 val)
|
|
||||||
{
|
|
||||||
wmb();
|
|
||||||
writel(val, c->irq_mask);
|
|
||||||
wmb();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* i2o_msg_get - obtain an I2O message from the IOP
|
* i2o_msg_get - obtain an I2O message from the IOP
|
||||||
@ -440,10 +396,12 @@ static inline void I2O_IRQ_WRITE32(struct i2o_controller *c, u32 val)
|
|||||||
static inline u32 i2o_msg_get(struct i2o_controller *c,
|
static inline u32 i2o_msg_get(struct i2o_controller *c,
|
||||||
struct i2o_message __iomem **msg)
|
struct i2o_message __iomem **msg)
|
||||||
{
|
{
|
||||||
u32 m;
|
u32 m = readl(c->in_port);
|
||||||
|
|
||||||
if ((m = I2O_POST_READ32(c)) != I2O_QUEUE_EMPTY)
|
if (m != I2O_QUEUE_EMPTY) {
|
||||||
*msg = c->in_queue.virt + m;
|
*msg = c->in_queue.virt + m;
|
||||||
|
rmb();
|
||||||
|
}
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
};
|
};
|
||||||
@ -457,7 +415,8 @@ static inline u32 i2o_msg_get(struct i2o_controller *c,
|
|||||||
*/
|
*/
|
||||||
static inline void i2o_msg_post(struct i2o_controller *c, u32 m)
|
static inline void i2o_msg_post(struct i2o_controller *c, u32 m)
|
||||||
{
|
{
|
||||||
I2O_POST_WRITE32(c, m);
|
wmb();
|
||||||
|
writel(m, c->in_port);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -486,12 +445,10 @@ static inline int i2o_msg_post_wait(struct i2o_controller *c, u32 m,
|
|||||||
* The I2O controller must be informed that the reply message is not needed
|
* The I2O controller must be informed that the reply message is not needed
|
||||||
* anymore. If you forget to flush the reply, the message frame can't be
|
* anymore. If you forget to flush the reply, the message frame can't be
|
||||||
* used by the controller anymore and is therefore lost.
|
* used by the controller anymore and is therefore lost.
|
||||||
*
|
|
||||||
* FIXME: is there a timeout after which the controller reuse the message?
|
|
||||||
*/
|
*/
|
||||||
static inline void i2o_flush_reply(struct i2o_controller *c, u32 m)
|
static inline void i2o_flush_reply(struct i2o_controller *c, u32 m)
|
||||||
{
|
{
|
||||||
I2O_REPLY_WRITE32(c, m);
|
writel(m, c->out_port);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -505,7 +462,8 @@ static inline void i2o_flush_reply(struct i2o_controller *c, u32 m)
|
|||||||
* work for sender side messages as they are ioremap objects
|
* work for sender side messages as they are ioremap objects
|
||||||
* provided by the I2O controller.
|
* provided by the I2O controller.
|
||||||
*/
|
*/
|
||||||
static inline struct i2o_message *i2o_msg_out_to_virt(struct i2o_controller *c,
|
static inline struct i2o_message __iomem *i2o_msg_out_to_virt(struct
|
||||||
|
i2o_controller *c,
|
||||||
u32 m)
|
u32 m)
|
||||||
{
|
{
|
||||||
BUG_ON(m < c->out_queue.phys
|
BUG_ON(m < c->out_queue.phys
|
||||||
@ -917,7 +875,7 @@ extern void i2o_debug_state(struct i2o_controller *c);
|
|||||||
#define I2OVER15 0x0001
|
#define I2OVER15 0x0001
|
||||||
#define I2OVER20 0x0002
|
#define I2OVER20 0x0002
|
||||||
|
|
||||||
/* Default is 1.5, FIXME: Need support for both 1.5 and 2.0 */
|
/* Default is 1.5 */
|
||||||
#define I2OVERSION I2OVER15
|
#define I2OVERSION I2OVER15
|
||||||
|
|
||||||
#define SGL_OFFSET_0 I2OVERSION
|
#define SGL_OFFSET_0 I2OVERSION
|
||||||
|
Loading…
Reference in New Issue
Block a user