Commit 9e87545f authored by Markus Lidel's avatar Markus Lidel Committed by Linus Torvalds
Browse files

[PATCH] I2O: second code cleanup of sparse warnings and unneeded syncronization



Changes:
 - Added header "core.h" for i2o_core.ko internal definitions
 - More sparse fixes
 - Changed display of TID's in sysfs attributes from XXX to 0xXXX
 - Use the right functions for accessing I/O and normal memory
 - Removed error handling of SCSI device errors and let the SCSI layer
   take care of it
 - Added new device / removed device handling to SCSI-OSM
 - Make status access volatile
 - Cleaned up activation of I2O controller
 - Removed unnecessary wmb() and rmb() calls
 - Use own struct i2o_io for I/O memory instead of struct i2o_dma
Signed-off-by: default avatarMarkus Lidel <Markus.Lidel@shadowconnect.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent b2aaee33
/*
* I2O core internal declarations
*
* Copyright (C) 2005 Markus Lidel <Markus.Lidel@shadowconnect.com>
*
* 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.
*
* Fixes/additions:
* Markus Lidel <Markus.Lidel@shadowconnect.com>
* initial version.
*/
/* Exec-OSM */
extern struct bus_type i2o_bus_type;
extern struct i2o_driver i2o_exec_driver;
extern int i2o_exec_lct_get(struct i2o_controller *);
extern int __init i2o_exec_init(void);
extern void __exit i2o_exec_exit(void);
/* driver */
extern int i2o_driver_dispatch(struct i2o_controller *, u32);
extern int __init i2o_driver_init(void);
extern void __exit i2o_driver_exit(void);
/* PCI */
extern int __init i2o_pci_init(void);
extern void __exit i2o_pci_exit(void);
/* device */
extern void i2o_device_remove(struct i2o_device *);
extern int i2o_device_parse_lct(struct i2o_controller *);
extern int i2o_device_init(void);
extern void i2o_device_exit(void);
/* IOP */
extern struct i2o_controller *i2o_iop_alloc(void);
extern void i2o_iop_free(struct i2o_controller *);
extern int i2o_iop_add(struct i2o_controller *);
extern void i2o_iop_remove(struct i2o_controller *);
/* control registers relative to c->base */
#define I2O_IRQ_STATUS 0x30
#define I2O_IRQ_MASK 0x34
#define I2O_IN_PORT 0x40
#define I2O_OUT_PORT 0x44
#define I2O_IRQ_OUTBOUND_POST 0x00000008
......@@ -4,8 +4,6 @@
#include <linux/pci.h>
#include <linux/i2o.h>
extern struct i2o_driver **i2o_drivers;
extern unsigned int i2o_max_drivers;
static void i2o_report_util_cmd(u8 cmd);
static void i2o_report_exec_cmd(u8 cmd);
static void i2o_report_fail_status(u8 req_status, u32 * msg);
......@@ -23,7 +21,6 @@ void i2o_report_status(const char *severity, const char *str,
u8 cmd = (msg[1] >> 24) & 0xFF;
u8 req_status = (msg[4] >> 24) & 0xFF;
u16 detailed_status = msg[4] & 0xFFFF;
//struct i2o_driver *h = i2o_drivers[msg[2] & (i2o_max_drivers-1)];
if (cmd == I2O_CMD_UTIL_EVT_REGISTER)
return; // No status in this reply
......
......@@ -16,9 +16,7 @@
#include <linux/module.h>
#include <linux/i2o.h>
#include <linux/delay.h>
/* Exec OSM functions */
extern struct bus_type i2o_bus_type;
#include "core.h"
/**
* i2o_device_issue_claim - claim or release a device
......@@ -293,12 +291,12 @@ int i2o_device_parse_lct(struct i2o_controller *c)
}
if (lct->table_size * 4 > c->dlct.len) {
memcpy_fromio(c->lct, c->dlct.virt, c->dlct.len);
memcpy(c->lct, c->dlct.virt, c->dlct.len);
up(&c->lct_lock);
return -EAGAIN;
}
memcpy_fromio(c->lct, c->dlct.virt, lct->table_size * 4);
memcpy(c->lct, c->dlct.virt, lct->table_size * 4);
lct = c->lct;
......@@ -353,7 +351,7 @@ static ssize_t i2o_device_class_show_class_id(struct class_device *cd,
{
struct i2o_device *dev = to_i2o_device(cd->dev);
sprintf(buf, "%03x\n", dev->lct_data.class_id);
sprintf(buf, "0x%03x\n", dev->lct_data.class_id);
return strlen(buf) + 1;
};
......@@ -368,7 +366,7 @@ static ssize_t i2o_device_class_show_tid(struct class_device *cd, char *buf)
{
struct i2o_device *dev = to_i2o_device(cd->dev);
sprintf(buf, "%03x\n", dev->lct_data.tid);
sprintf(buf, "0x%03x\n", dev->lct_data.tid);
return strlen(buf) + 1;
};
......@@ -490,7 +488,7 @@ static int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist,
if (rc == -ETIMEDOUT)
return rc;
memcpy_fromio(reslist, res.virt, res.len);
memcpy(reslist, res.virt, res.len);
i2o_dma_free(dev, &res);
/* Query failed */
......@@ -532,17 +530,23 @@ int i2o_parm_field_get(struct i2o_device *i2o_dev, int group, int field,
void *buf, int buflen)
{
u16 opblk[] = { 1, 0, I2O_PARAMS_FIELD_GET, group, 1, field };
u8 resblk[8 + buflen]; /* 8 bytes for header */
u8 *resblk; /* 8 bytes for header */
int size;
if (field == -1) /* whole group */
opblk[4] = -1;
resblk = kmalloc(buflen + 8, GFP_KERNEL | GFP_ATOMIC);
if (!resblk)
return -ENOMEM;
size = i2o_parm_issue(i2o_dev, I2O_CMD_UTIL_PARAMS_GET, opblk,
sizeof(opblk), resblk, buflen + 8);
memcpy(buf, resblk + 8, buflen); /* cut off header */
kfree(resblk);
if (size > buflen)
return buflen;
......
......@@ -17,11 +17,12 @@
#include <linux/module.h>
#include <linux/rwsem.h>
#include <linux/i2o.h>
#include "core.h"
#define OSM_NAME "i2o"
/* max_drivers - Maximum I2O drivers (OSMs) which could be registered */
unsigned int i2o_max_drivers = I2O_MAX_DRIVERS;
static unsigned int i2o_max_drivers = I2O_MAX_DRIVERS;
module_param_named(max_drivers, i2o_max_drivers, uint, 0);
MODULE_PARM_DESC(max_drivers, "maximum number of OSM's to support");
......@@ -179,15 +180,10 @@ void i2o_driver_unregister(struct i2o_driver *drv)
int i2o_driver_dispatch(struct i2o_controller *c, u32 m)
{
struct i2o_driver *drv;
struct i2o_message __iomem *msg = i2o_msg_out_to_virt(c, m);
u32 context;
struct i2o_message *msg = i2o_msg_out_to_virt(c, m);
u32 context = le32_to_cpu(msg->u.s.icntxt);
unsigned long flags;
if(unlikely(!msg))
return -EIO;
context = readl(&msg->u.s.icntxt);
if (unlikely(context >= i2o_max_drivers)) {
osm_warn("%s: Spurious reply to unknown driver %d\n", c->name,
context);
......@@ -204,11 +200,11 @@ int i2o_driver_dispatch(struct i2o_controller *c, u32 m)
return -EIO;
}
if ((readl(&msg->u.head[1]) >> 24) == I2O_CMD_UTIL_EVT_REGISTER) {
if ((le32_to_cpu(msg->u.head[1]) >> 24) == I2O_CMD_UTIL_EVT_REGISTER) {
struct i2o_device *dev, *tmp;
struct i2o_event *evt;
u16 size;
u16 tid = readl(&msg->u.head[1]) & 0xfff;
u16 tid = le32_to_cpu(msg->u.head[1]) & 0xfff;
osm_debug("event received from device %d\n", tid);
......@@ -216,16 +212,16 @@ int i2o_driver_dispatch(struct i2o_controller *c, u32 m)
return -EIO;
/* cut of header from message size (in 32-bit words) */
size = (readl(&msg->u.head[0]) >> 16) - 5;
size = (le32_to_cpu(msg->u.head[0]) >> 16) - 5;
evt = kmalloc(size * 4 + sizeof(*evt), GFP_ATOMIC | __GFP_ZERO);
if (!evt)
return -ENOMEM;
evt->size = size;
evt->tcntxt = readl(&msg->u.s.tcntxt);
evt->event_indicator = readl(&msg->body[0]);
memcpy_fromio(&evt->tcntxt, &msg->u.s.tcntxt, size * 4);
evt->tcntxt = le32_to_cpu(msg->u.s.tcntxt);
evt->event_indicator = le32_to_cpu(msg->body[0]);
memcpy(&evt->tcntxt, &msg->u.s.tcntxt, size * 4);
list_for_each_entry_safe(dev, tmp, &c->devices, list)
if (dev->lct_data.tid == tid) {
......
......@@ -30,6 +30,7 @@
#include <linux/module.h>
#include <linux/i2o.h>
#include <linux/delay.h>
#include "core.h"
#define OSM_NAME "exec-osm"
......@@ -37,9 +38,6 @@ struct i2o_driver i2o_exec_driver;
static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind);
/* Module internal functions from other sources */
extern int i2o_device_parse_lct(struct i2o_controller *);
/* global wait list for POST WAIT */
static LIST_HEAD(i2o_exec_wait_list);
......@@ -50,7 +48,7 @@ struct i2o_exec_wait {
u32 tcntxt; /* transaction context from reply */
int complete; /* 1 if reply received otherwise 0 */
u32 m; /* message id */
struct i2o_message __iomem *msg; /* pointer to the reply message */
struct i2o_message *msg; /* pointer to the reply message */
struct list_head list; /* node in global wait list */
};
......@@ -162,7 +160,7 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long
barrier();
if (wait->complete) {
rc = readl(&wait->msg->body[0]) >> 24;
rc = le32_to_cpu(wait->msg->body[0]) >> 24;
i2o_flush_reply(c, wait->m);
i2o_exec_wait_free(wait);
} else {
......@@ -202,8 +200,7 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long
* message must also be given back to the controller.
*/
static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m,
struct i2o_message __iomem *msg,
u32 context)
struct i2o_message *msg, u32 context)
{
struct i2o_exec_wait *wait, *tmp;
unsigned long flags;
......@@ -378,11 +375,11 @@ static void i2o_exec_lct_modified(struct i2o_controller *c)
* code on failure and if the reply should be flushed.
*/
static int i2o_exec_reply(struct i2o_controller *c, u32 m,
struct i2o_message __iomem *msg)
struct i2o_message *msg)
{
u32 context;
if (readl(&msg->u.head[0]) & MSG_FAIL) {
if (le32_to_cpu(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.
......@@ -390,7 +387,7 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m,
struct i2o_message __iomem *pmsg;
u32 pm;
pm = readl(&msg->body[3]);
pm = le32_to_cpu(msg->body[3]);
pmsg = i2o_msg_in_to_virt(c, pm);
......@@ -401,12 +398,12 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m,
/* Release the preserved msg */
i2o_msg_nop(c, pm);
} else
context = readl(&msg->u.s.tcntxt);
context = le32_to_cpu(msg->u.s.tcntxt);
if (context & 0x80000000)
return i2o_msg_post_wait_complete(c, m, msg, context);
if ((readl(&msg->u.head[1]) >> 24) == I2O_CMD_LCT_NOTIFY) {
if ((le32_to_cpu(msg->u.head[1]) >> 24) == I2O_CMD_LCT_NOTIFY) {
struct work_struct *work;
pr_debug("%s: LCT notify received\n", c->name);
......@@ -442,9 +439,9 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m,
*/
static void i2o_exec_event(struct i2o_event *evt)
{
if(likely(evt->i2o_dev))
osm_info("Event received from device: %d\n",
evt->i2o_dev->lct_data.tid);
if (likely(evt->i2o_dev))
osm_debug("Event received from device: %d\n",
evt->i2o_dev->lct_data.tid);
kfree(evt);
};
......
......@@ -62,7 +62,7 @@
#include "i2o_block.h"
#define OSM_NAME "block-osm"
#define OSM_VERSION "$Rev$"
#define OSM_VERSION "1.287"
#define OSM_DESCRIPTION "I2O Block Device OSM"
static struct i2o_driver i2o_block_driver;
......@@ -537,7 +537,7 @@ static int i2o_block_reply(struct i2o_controller *c, u32 m,
static void i2o_block_event(struct i2o_event *evt)
{
osm_info("event received\n");
osm_debug("event received\n");
kfree(evt);
};
......
......@@ -36,6 +36,8 @@
#include <asm/uaccess.h>
#define SG_TABLESIZE 30
extern int i2o_parm_issue(struct i2o_device *, int, void *, int, void *, int);
static int i2o_cfg_ioctl(struct inode *inode, struct file *fp, unsigned int cmd,
......@@ -663,7 +665,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar
goto sg_list_cleanup;
if (sg_offset) {
u32 msg[MSG_FRAME_SIZE];
u32 msg[I2O_OUTBOUND_MSG_FRAME_SIZE];
/* Copy back the Scatter Gather buffers back to user space */
u32 j;
// TODO 64bit fix
......@@ -671,7 +673,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar
int sg_size;
// re-acquire the original message to handle correctly the sg copy operation
memset(&msg, 0, MSG_FRAME_SIZE * 4);
memset(&msg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4);
// get user msg size in u32s
if (get_user(size, &user_msg[0])) {
rcode = -EFAULT;
......@@ -902,7 +904,7 @@ static int i2o_cfg_passthru(unsigned long arg)
int sg_size;
// re-acquire the original message to handle correctly the sg copy operation
memset(&msg, 0, MSG_FRAME_SIZE * 4);
memset(&msg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4);
// get user msg size in u32s
if (get_user(size, &user_msg[0])) {
rcode = -EFAULT;
......
......@@ -40,7 +40,6 @@
* Fix the resource management problems.
*/
#define DEBUG 1
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
......@@ -338,162 +337,89 @@ static int i2o_scsi_reply(struct i2o_controller *c, u32 m,
struct i2o_message *msg)
{
struct scsi_cmnd *cmd;
u32 error;
struct device *dev;
u8 as, ds, st;
cmd = i2o_cntxt_list_get(c, le32_to_cpu(msg->u.s.tcntxt));
if (msg->u.head[0] & (1 << 13)) {
struct i2o_message __iomem *pmsg; /* preserved message */
u32 pm;
int err = DID_ERROR;
pm = le32_to_cpu(msg->body[3]);
pmsg = i2o_msg_in_to_virt(c, pm);
osm_err("IOP fail.\n");
osm_err("From %d To %d Cmd %d.\n",
(msg->u.head[1] >> 12) & 0xFFF,
msg->u.head[1] & 0xFFF, msg->u.head[1] >> 24);
osm_err("Failure Code %d.\n", msg->body[0] >> 24);
if (msg->body[0] & (1 << 16))
osm_err("Format error.\n");
if (msg->body[0] & (1 << 17))
osm_err("Path error.\n");
if (msg->body[0] & (1 << 18))
osm_err("Path State.\n");
if (msg->body[0] & (1 << 18))
{
osm_err("Congestion.\n");
err = DID_BUS_BUSY;
}
osm_debug("Failing message is %p.\n", pmsg);
cmd = i2o_cntxt_list_get(c, readl(&pmsg->u.s.tcntxt));
if (!cmd)
return 1;
cmd->result = err << 16;
cmd->scsi_done(cmd);
/* Now flush the message by making it a NOP */
i2o_msg_nop(c, pm);
return 1;
if (unlikely(!cmd)) {
osm_err("NULL reply received!\n");
return -1;
}
/*
* Low byte is device status, next is adapter status,
* (then one byte reserved), then request status.
*/
ds = (u8) le32_to_cpu(msg->body[0]);
as = (u8) (le32_to_cpu(msg->body[0]) >> 8);
st = (u8) (le32_to_cpu(msg->body[0]) >> 24);
error = le32_to_cpu(msg->body[0]);
osm_debug("Completed %ld\n", cmd->serial_number);
cmd->result = error & 0xff;
/*
* Is this a control request coming back - eg an abort ?
* if DeviceStatus is not SCSI_SUCCESS copy over the sense data and let
* the SCSI layer handle the error
*/
if (cmd->result)
memcpy(cmd->sense_buffer, &msg->body[3],
min(sizeof(cmd->sense_buffer), (size_t) 40));
if (!cmd) {
if (st)
osm_warn("SCSI abort: %08X", le32_to_cpu(msg->body[0]));
osm_info("SCSI abort completed.\n");
return -EFAULT;
}
/* only output error code if AdapterStatus is not HBA_SUCCESS */
if ((error >> 8) & 0xff)
osm_err("SCSI error %08x\n", error);
osm_debug("Completed %ld\n", cmd->serial_number);
dev = &c->pdev->dev;
if (cmd->use_sg)
dma_unmap_sg(dev, cmd->request_buffer, cmd->use_sg,
cmd->sc_data_direction);
else if (cmd->SCp.dma_handle)
dma_unmap_single(dev, cmd->SCp.dma_handle, cmd->request_bufflen,
cmd->sc_data_direction);
if (st) {
u32 count, error;
/* An error has occurred */
switch (st) {
case 0x06:
count = le32_to_cpu(msg->body[1]);
if (count < cmd->underflow) {
int i;
osm_err("SCSI underflow 0x%08X 0x%08X\n", count,
cmd->underflow);
osm_debug("Cmd: ");
for (i = 0; i < 15; i++)
pr_debug("%02X ", cmd->cmnd[i]);
pr_debug(".\n");
cmd->result = (DID_ERROR << 16);
}
break;
cmd->scsi_done(cmd);
default:
error = le32_to_cpu(msg->body[0]);
osm_err("SCSI error %08x\n", error);
if ((error & 0xff) == 0x02 /*CHECK_CONDITION */ ) {
int i;
u32 len = sizeof(cmd->sense_buffer);
len = (len > 40) ? 40 : len;
// Copy over the sense data
memcpy(cmd->sense_buffer, (void *)&msg->body[3],
len);
for (i = 0; i <= len; i++)
osm_info("%02x\n",
cmd->sense_buffer[i]);
if (cmd->sense_buffer[0] == 0x70
&& cmd->sense_buffer[2] == DATA_PROTECT) {
/* This is to handle an array failed */
cmd->result = (DID_TIME_OUT << 16);
printk(KERN_WARNING "%s: SCSI Data "
"Protect-Device (%d,%d,%d) "
"hba_status=0x%x, dev_status="
"0x%x, cmd=0x%x\n", c->name,
(u32) cmd->device->channel,
(u32) cmd->device->id,
(u32) cmd->device->lun,
(error >> 8) & 0xff,
error & 0xff, cmd->cmnd[0]);
} else
cmd->result = (DID_ERROR << 16);
break;
}
switch (as) {
case 0x0E:
/* SCSI Reset */
cmd->result = DID_RESET << 16;
break;
case 0x0F:
cmd->result = DID_PARITY << 16;
break;
default:
cmd->result = DID_ERROR << 16;
break;
}
return 1;
};
break;
}
/**
* i2o_scsi_notify_device_add - Retrieve notifications of added devices
* @i2o_dev: the I2O device which was added
*
* If a I2O device is added we catch the notification, because I2O classes
* other then SCSI peripheral will not be received through
* i2o_scsi_probe().
*/
static void i2o_scsi_notify_device_add(struct i2o_device *i2o_dev)
{
switch (i2o_dev->lct_data.class_id) {
case I2O_CLASS_EXECUTIVE:
case I2O_CLASS_RANDOM_BLOCK_STORAGE:
i2o_scsi_probe(&i2o_dev->device);
break;
cmd->scsi_done(cmd);
return 1;
default:
break;
}
};
cmd->result = DID_OK << 16 | ds;
dev = &c->pdev->dev;
if (cmd->use_sg)
dma_unmap_sg(dev, (struct scatterlist *)cmd->buffer,
cmd->use_sg, cmd->sc_data_direction);
else if (cmd->request_bufflen)
dma_unmap_single(dev, (dma_addr_t) ((long)cmd->SCp.ptr),
cmd->request_bufflen, cmd->sc_data_direction);
cmd->scsi_done(cmd);
/**
* i2o_scsi_notify_device_remove - Retrieve notifications of removed
* devices
* @i2o_dev: the I2O device which was removed
*
* If a I2O device is removed, we catch the notification to remove the
* corresponding SCSI device.
*/
static void i2o_scsi_notify_device_remove(struct i2o_device *i2o_dev)
{
switch (i2o_dev->lct_data.class_id) {
case I2O_CLASS_EXECUTIVE:
case I2O_CLASS_RANDOM_BLOCK_STORAGE:
i2o_scsi_remove(&i2o_dev->device);
break;
return 1;
default:
break;
}
};
/**
......@@ -554,6 +480,8 @@ static struct i2o_driver i2o_scsi_driver = {
.name = OSM_NAME,
.reply = i2o_scsi_reply,
.classes = i2o_scsi_class_id,
.notify_device_add = i2o_scsi_notify_device_add,
.notify_device_remove = i2o_scsi_notify_device_remove,
.notify_controller_add = i2o_scsi_notify_controller_add,
.notify_controller_remove = i2o_scsi_notify_controller_remove,
.driver = {
......@@ -712,7 +640,7 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
*/
/* Attach tags to the devices */
/*
/* FIXME: implement
if(SCpnt->device->tagged_supported) {
if(SCpnt->tag == HEAD_OF_QUEUE_TAG)
scsi_flags |= 0x01000000;
......