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

[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 @@ ...@@ -4,8 +4,6 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/i2o.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_util_cmd(u8 cmd);
static void i2o_report_exec_cmd(u8 cmd); static void i2o_report_exec_cmd(u8 cmd);
static void i2o_report_fail_status(u8 req_status, u32 * msg); 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, ...@@ -23,7 +21,6 @@ void i2o_report_status(const char *severity, const char *str,
u8 cmd = (msg[1] >> 24) & 0xFF; u8 cmd = (msg[1] >> 24) & 0xFF;
u8 req_status = (msg[4] >> 24) & 0xFF; u8 req_status = (msg[4] >> 24) & 0xFF;
u16 detailed_status = msg[4] & 0xFFFF; 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) if (cmd == I2O_CMD_UTIL_EVT_REGISTER)
return; // No status in this reply return; // No status in this reply
......
...@@ -16,9 +16,7 @@ ...@@ -16,9 +16,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/i2o.h> #include <linux/i2o.h>
#include <linux/delay.h> #include <linux/delay.h>
#include "core.h"
/* Exec OSM functions */
extern struct bus_type i2o_bus_type;
/** /**
* i2o_device_issue_claim - claim or release a device * i2o_device_issue_claim - claim or release a device
...@@ -293,12 +291,12 @@ int i2o_device_parse_lct(struct i2o_controller *c) ...@@ -293,12 +291,12 @@ int i2o_device_parse_lct(struct i2o_controller *c)
} }
if (lct->table_size * 4 > c->dlct.len) { 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); up(&c->lct_lock);
return -EAGAIN; 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; lct = c->lct;
...@@ -353,7 +351,7 @@ static ssize_t i2o_device_class_show_class_id(struct class_device *cd, ...@@ -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); 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; return strlen(buf) + 1;
}; };
...@@ -368,7 +366,7 @@ static ssize_t i2o_device_class_show_tid(struct class_device *cd, char *buf) ...@@ -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); 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; return strlen(buf) + 1;
}; };
...@@ -490,7 +488,7 @@ static int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist, ...@@ -490,7 +488,7 @@ static int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist,
if (rc == -ETIMEDOUT) if (rc == -ETIMEDOUT)
return rc; return rc;
memcpy_fromio(reslist, res.virt, res.len); memcpy(reslist, res.virt, res.len);
i2o_dma_free(dev, &res); i2o_dma_free(dev, &res);
/* Query failed */ /* Query failed */
...@@ -532,17 +530,23 @@ int i2o_parm_field_get(struct i2o_device *i2o_dev, int group, int field, ...@@ -532,17 +530,23 @@ int i2o_parm_field_get(struct i2o_device *i2o_dev, int group, int field,
void *buf, int buflen) void *buf, int buflen)
{ {
u16 opblk[] = { 1, 0, I2O_PARAMS_FIELD_GET, group, 1, field }; 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; int size;
if (field == -1) /* whole group */ if (field == -1) /* whole group */
opblk[4] = -1; 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, size = i2o_parm_issue(i2o_dev, I2O_CMD_UTIL_PARAMS_GET, opblk,
sizeof(opblk), resblk, buflen + 8); sizeof(opblk), resblk, buflen + 8);
memcpy(buf, resblk + 8, buflen); /* cut off header */ memcpy(buf, resblk + 8, buflen); /* cut off header */
kfree(resblk);
if (size > buflen) if (size > buflen)
return buflen; return buflen;
......
...@@ -17,11 +17,12 @@ ...@@ -17,11 +17,12 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/rwsem.h> #include <linux/rwsem.h>
#include <linux/i2o.h> #include <linux/i2o.h>
#include "core.h"
#define OSM_NAME "i2o" #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; static unsigned int i2o_max_drivers = I2O_MAX_DRIVERS;
module_param_named(max_drivers, i2o_max_drivers, uint, 0); module_param_named(max_drivers, i2o_max_drivers, uint, 0);
MODULE_PARM_DESC(max_drivers, "maximum number of OSM's to support"); MODULE_PARM_DESC(max_drivers, "maximum number of OSM's to support");
...@@ -179,15 +180,10 @@ void i2o_driver_unregister(struct i2o_driver *drv) ...@@ -179,15 +180,10 @@ void i2o_driver_unregister(struct i2o_driver *drv)
int i2o_driver_dispatch(struct i2o_controller *c, u32 m) int i2o_driver_dispatch(struct i2o_controller *c, u32 m)
{ {
struct i2o_driver *drv; struct i2o_driver *drv;
struct i2o_message __iomem *msg = i2o_msg_out_to_virt(c, m); struct i2o_message *msg = i2o_msg_out_to_virt(c, m);
u32 context; u32 context = le32_to_cpu(msg->u.s.icntxt);
unsigned long flags; unsigned long flags;
if(unlikely(!msg))
return -EIO;
context = readl(&msg->u.s.icntxt);
if (unlikely(context >= i2o_max_drivers)) { if (unlikely(context >= i2o_max_drivers)) {
osm_warn("%s: Spurious reply to unknown driver %d\n", c->name, osm_warn("%s: Spurious reply to unknown driver %d\n", c->name,
context); context);
...@@ -204,11 +200,11 @@ int i2o_driver_dispatch(struct i2o_controller *c, u32 m) ...@@ -204,11 +200,11 @@ int i2o_driver_dispatch(struct i2o_controller *c, u32 m)
return -EIO; 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_device *dev, *tmp;
struct i2o_event *evt; struct i2o_event *evt;
u16 size; 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); osm_debug("event received from device %d\n", tid);
...@@ -216,16 +212,16 @@ int i2o_driver_dispatch(struct i2o_controller *c, u32 m) ...@@ -216,16 +212,16 @@ int i2o_driver_dispatch(struct i2o_controller *c, u32 m)
return -EIO; 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 = (le32_to_cpu(msg->u.head[0]) >> 16) - 5;
evt = kmalloc(size * 4 + sizeof(*evt), GFP_ATOMIC | __GFP_ZERO); evt = kmalloc(size * 4 + sizeof(*evt), GFP_ATOMIC | __GFP_ZERO);
if (!evt) if (!evt)
return -ENOMEM; return -ENOMEM;
evt->size = size; evt->size = size;
evt->tcntxt = readl(&msg->u.s.tcntxt); evt->tcntxt = le32_to_cpu(msg->u.s.tcntxt);
evt->event_indicator = readl(&msg->body[0]); evt->event_indicator = le32_to_cpu(msg->body[0]);
memcpy_fromio(&evt->tcntxt, &msg->u.s.tcntxt, size * 4); memcpy(&evt->tcntxt, &msg->u.s.tcntxt, size * 4);
list_for_each_entry_safe(dev, tmp, &c->devices, list) list_for_each_entry_safe(dev, tmp, &c->devices, list)
if (dev->lct_data.tid == tid) { if (dev->lct_data.tid == tid) {
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/i2o.h> #include <linux/i2o.h>
#include <linux/delay.h> #include <linux/delay.h>
#include "core.h"
#define OSM_NAME "exec-osm" #define OSM_NAME "exec-osm"
...@@ -37,9 +38,6 @@ struct i2o_driver i2o_exec_driver; ...@@ -37,9 +38,6 @@ struct i2o_driver i2o_exec_driver;
static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind); 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 */ /* global wait list for POST WAIT */
static LIST_HEAD(i2o_exec_wait_list); static LIST_HEAD(i2o_exec_wait_list);
...@@ -50,7 +48,7 @@ struct i2o_exec_wait { ...@@ -50,7 +48,7 @@ struct i2o_exec_wait {
u32 tcntxt; /* transaction context from reply */ u32 tcntxt; /* transaction context from reply */
int complete; /* 1 if reply received otherwise 0 */ int complete; /* 1 if reply received otherwise 0 */
u32 m; /* message id */ 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 */ 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 ...@@ -162,7 +160,7 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long
barrier(); barrier();
if (wait->complete) { 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_flush_reply(c, wait->m);
i2o_exec_wait_free(wait); i2o_exec_wait_free(wait);
} else { } else {
...@@ -202,8 +200,7 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long ...@@ -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. * 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 *msg, u32 context)
u32 context)
{ {
struct i2o_exec_wait *wait, *tmp; struct i2o_exec_wait *wait, *tmp;
unsigned long flags; unsigned long flags;
...@@ -378,11 +375,11 @@ static void i2o_exec_lct_modified(struct i2o_controller *c) ...@@ -378,11 +375,11 @@ 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 __iomem *msg) struct i2o_message *msg)
{ {
u32 context; 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 * If Fail bit is set we must take the transaction context of
* the preserved message to find the right request again. * the preserved message to find the right request again.
...@@ -390,7 +387,7 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m, ...@@ -390,7 +387,7 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m,
struct i2o_message __iomem *pmsg; struct i2o_message __iomem *pmsg;
u32 pm; u32 pm;
pm = readl(&msg->body[3]); pm = le32_to_cpu(msg->body[3]);
pmsg = i2o_msg_in_to_virt(c, pm); pmsg = i2o_msg_in_to_virt(c, pm);
...@@ -401,12 +398,12 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m, ...@@ -401,12 +398,12 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m,
/* Release the preserved msg */ /* Release the preserved msg */
i2o_msg_nop(c, pm); i2o_msg_nop(c, pm);
} else } else
context = readl(&msg->u.s.tcntxt); context = le32_to_cpu(msg->u.s.tcntxt);
if (context & 0x80000000) if (context & 0x80000000)
return i2o_msg_post_wait_complete(c, m, msg, context); 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; struct work_struct *work;
pr_debug("%s: LCT notify received\n", c->name); pr_debug("%s: LCT notify received\n", c->name);
...@@ -442,8 +439,8 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m, ...@@ -442,8 +439,8 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m,
*/ */
static void i2o_exec_event(struct i2o_event *evt) static void i2o_exec_event(struct i2o_event *evt)
{ {
if(likely(evt->i2o_dev)) if (likely(evt->i2o_dev))
osm_info("Event received from device: %d\n", osm_debug("Event received from device: %d\n",
evt->i2o_dev->lct_data.tid); evt->i2o_dev->lct_data.tid);
kfree(evt); kfree(evt);
}; };
......
...@@ -62,7 +62,7 @@ ...@@ -62,7 +62,7 @@
#include "i2o_block.h" #include "i2o_block.h"
#define OSM_NAME "block-osm" #define OSM_NAME "block-osm"
#define OSM_VERSION "$Rev$" #define OSM_VERSION "1.287"
#define OSM_DESCRIPTION "I2O Block Device OSM" #define OSM_DESCRIPTION "I2O Block Device OSM"
static struct i2o_driver i2o_block_driver; static struct i2o_driver i2o_block_driver;
...@@ -537,7 +537,7 @@ static int i2o_block_reply(struct i2o_controller *c, u32 m, ...@@ -537,7 +537,7 @@ static int i2o_block_reply(struct i2o_controller *c, u32 m,
static void i2o_block_event(struct i2o_event *evt) static void i2o_block_event(struct i2o_event *evt)
{ {
osm_info("event received\n"); osm_debug("event received\n");
kfree(evt); kfree(evt);
}; };
......
...@@ -36,6 +36,8 @@ ...@@ -36,6 +36,8 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#define SG_TABLESIZE 30
extern int i2o_parm_issue(struct i2o_device *, int, void *, int, void *, int); 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, 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 ...@@ -663,7 +665,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar
goto sg_list_cleanup; goto sg_list_cleanup;
if (sg_offset) { 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 */ /* Copy back the Scatter Gather buffers back to user space */
u32 j; u32 j;
// TODO 64bit fix // TODO 64bit fix
...@@ -671,7 +673,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar ...@@ -671,7 +673,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar
int sg_size; int sg_size;
// re-acquire the original message to handle correctly the sg copy operation // 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 // get user msg size in u32s
if (get_user(size, &user_msg[0])) { if (get_user(size, &user_msg[0])) {
rcode = -EFAULT; rcode = -EFAULT;
...@@ -902,7 +904,7 @@ static int i2o_cfg_passthru(unsigned long arg) ...@@ -902,7 +904,7 @@ static int i2o_cfg_passthru(unsigned long arg)
int sg_size; int sg_size;
// re-acquire the original message to handle correctly the sg copy operation // 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 // get user msg size in u32s
if (get_user(size, &user_msg[0])) { if (get_user(size, &user_msg[0])) {
rcode = -EFAULT; rcode = -EFAULT;
......
...@@ -40,7 +40,6 @@ ...@@ -40,7 +40,6 @@
* 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>
...@@ -338,162 +337,89 @@ static int i2o_scsi_reply(struct i2o_controller *c, u32 m, ...@@ -338,162 +337,89 @@ static int i2o_scsi_reply(struct i2o_controller *c, u32 m,
struct i2o_message *msg) struct i2o_message *msg)
{ {
struct scsi_cmnd *cmd; struct scsi_cmnd *cmd;
u32 error;
struct device *dev; struct device *dev;
u8 as, ds, st;
cmd = i2o_cntxt_list_get(c, le32_to_cpu(msg->u.s.tcntxt)); cmd = i2o_cntxt_list_get(c, le32_to_cpu(msg->u.s.tcntxt));
if (unlikely(!cmd)) {
if (msg->u.head[0] & (1 << 13)) { osm_err("NULL reply received!\n");
struct i2o_message __iomem *pmsg; /* preserved message */ return -1;
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;
} }
/* /*
* Low byte is device status, next is adapter status, * Low byte is device status, next is adapter status,
* (then one byte reserved), then request status. * (then one byte reserved), then request status.
*/ */
ds = (u8) le32_to_cpu(msg->body[0]); error = le32_to_cpu(msg->body[0]);
as = (u8) (le32_to_cpu(msg->body[0]) >> 8);
st = (u8) (le32_to_cpu(msg->body[0]) >> 24); 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) { /* only output error code if AdapterStatus is not HBA_SUCCESS */
if (st) if ((error >> 8) & 0xff)
osm_warn("SCSI abort: %08X", le32_to_cpu(msg->body[0])); osm_err("SCSI error %08x\n", error);
osm_info("SCSI abort completed.\n");
return -EFAULT;
}
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) { cmd->scsi_done(cmd);
u32 count, error;
/* An error has occurred */
switch (st) { return 1;
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); * i2o_scsi_notify_device_add - Retrieve notifications of added devices
osm_debug("Cmd: "); * @i2o_dev: the I2O device which was added
for (i = 0; i < 15; i++) *
pr_debug("%02X ", cmd->cmnd[i]); * If a I2O device is added we catch the notification, because I2O classes
pr_debug(".\n"); * other then SCSI peripheral will not be received through
cmd->result = (DID_ERROR << 16); * 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; break;
default: 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; break;
} }
};
switch (as) { /**
case 0x0E: * i2o_scsi_notify_device_remove - Retrieve notifications of removed
/* SCSI Reset */ * devices
cmd->result = DID_RESET << 16; * @i2o_dev: the I2O device which was removed
break; *
* If a I2O device is removed, we catch the notification to remove the
case 0x0F: * corresponding SCSI device.
cmd->result = DID_PARITY << 16; */
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; break;
default: default:
cmd->result = DID_ERROR << 16;
break; break;
} }
break;
}
cmd->scsi_done(cmd);
return 1;
}
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);
return 1;
}; };
/** /**
...@@ -554,6 +480,8 @@ static struct i2o_driver i2o_scsi_driver = { ...@@ -554,6 +480,8 @@ static struct i2o_driver i2o_scsi_driver = {
.name = OSM_NAME, .name = OSM_NAME,
.reply = i2o_scsi_reply, .reply = i2o_scsi_reply,
.classes = i2o_scsi_class_id, .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_add = i2o_scsi_notify_controller_add,
.notify_controller_remove = i2o_scsi_notify_controller_remove, .notify_controller_remove = i2o_scsi_notify_controller_remove,
.driver = { .driver = {
...@@ -712,7 +640,7 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, ...@@ -712,7 +640,7 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
*/ */
/* Attach tags to the devices */ /* Attach tags to the devices */
/* /* FIXME: implement
if(SCpnt->device->tagged_supported) { if(SCpnt->device->tagged_supported) {
if(SCpnt->tag == HEAD_OF_QUEUE_TAG) if(SCpnt->tag == HEAD_OF_QUEUE_TAG)
scsi_flags |= 0x01000000; scsi_flags |= 0x01000000;
......
...@@ -28,8 +28,10 @@ ...@@ -28,8 +28,10 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/i2o.h> #include <linux/i2o.h>
#include <linux/delay.h> #include <linux/delay.h>
#include "core.h"
#define OSM_VERSION "$Rev$" #define OSM_NAME "i2o"
#define OSM_VERSION "1.288"
#define OSM_DESCRIPTION "I2O subsystem" #define OSM_DESCRIPTION "I2O subsystem"
/* global I2O controller list */ /* global I2O controller list */
...@@ -43,20 +45,6 @@ static struct i2o_dma i2o_systab; ...@@ -43,20 +45,6 @@ static struct i2o_dma i2o_systab;
static int i2o_hrt_get(struct i2o_controller *c); static int i2o_hrt_get(struct i2o_controller *c);
/* Module internal functions from other sources */
extern struct i2o_driver i2o_exec_driver;
extern int i2o_exec_lct_get(struct i2o_controller *);
extern void i2o_device_remove(struct i2o_device *);
extern int __init i2o_driver_init(void);
extern void __exit i2o_driver_exit(void);
extern int __init i2o_exec_init(void);
extern void __exit i2o_exec_exit(void);
extern int __init i2o_pci_init(void);
extern void __exit i2o_pci_exit(void);
extern int i2o_device_init(void);
extern void i2o_device_exit(void);
/** /**
* i2o_msg_nop - Returns a message which is not used * i2o_msg_nop - Returns a message which is not used
* @c: I2O controller from which the message was created * @c: I2O controller from which the message was created
...@@ -92,15 +80,15 @@ void i2o_msg_nop(struct i2o_controller *c, u32 m) ...@@ -92,15 +80,15 @@ void i2o_msg_nop(struct i2o_controller *c, u32 m)
* address from the read port (see the i2o spec). If no message is * address from the read port (see the i2o spec). If no message is
* available returns I2O_QUEUE_EMPTY and msg is leaved untouched. * available returns I2O_QUEUE_EMPTY and msg is leaved untouched.
*/ */
u32 i2o_msg_get_wait(struct i2o_controller *c, struct i2o_message __iomem **msg, u32 i2o_msg_get_wait(struct i2o_controller *c,
int wait) struct i2o_message __iomem ** msg, int wait)
{ {
unsigned long timeout = jiffies + wait * HZ; unsigned long timeout = jiffies + wait * HZ;
u32 m; u32 m;
while ((m = i2o_msg_get(c, msg)) == I2O_QUEUE_EMPTY) { while ((m = i2o_msg_get(c, msg)) == I2O_QUEUE_EMPTY) {
if (time_after(jiffies, timeout)) { if (time_after(jiffies, timeout)) {
pr_debug("%s: Timeout waiting for message frame.\n", osm_debug("%s: Timeout waiting for message frame.\n",
c->name); c->name);
return I2O_QUEUE_EMPTY; return I2O_QUEUE_EMPTY;
} }
...@@ -466,7 +454,7 @@ static int i2o_iop_clear(struct i2o_controller *c) ...@@ -466,7 +454,7 @@ static int i2o_iop_clear(struct i2o_controller *c)
*/ */
static int i2o_iop_init_outbound_queue(struct i2o_controller *c) static int i2o_iop_init_outbound_queue(struct i2o_controller *c)
{ {
u8 *status = c->status.virt; volatile u8 *status = c->status.virt;
u32 m; u32 m;
struct i2o_message __iomem *msg; struct i2o_message __iomem *msg;
ulong timeout; ulong timeout;
...@@ -474,21 +462,20 @@ static int i2o_iop_init_outbound_queue(struct i2o_controller *c) ...@@ -474,21 +462,20 @@ static int i2o_iop_init_outbound_queue(struct i2o_controller *c)
osm_debug("%s: Initializing Outbound Queue...\n", c->name); osm_debug("%s: Initializing Outbound Queue...\n", c->name);
memset(status, 0, 4); memset(c->status.virt, 0, 4);
m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
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]);
/* Outbound msg frame size in words and Initcode */ /* Outbound msg frame size in words and Initcode */
writel(MSG_FRAME_SIZE << 16 | 0x80, &msg->body[1]); writel(I2O_OUTBOUND_MSG_FRAME_SIZE << 16 | 0x80, &msg->body[1]);
writel(0xd0000004, &msg->body[2]); writel(0xd0000004, &msg->body[2]);
writel(i2o_dma_low(c->status.phys), &msg->body[3]); writel(i2o_dma_low(c->status.phys), &msg->body[3]);
writel(i2o_dma_high(c->status.phys), &msg->body[4]); writel(i2o_dma_high(c->status.phys), &msg->body[4]);
...@@ -503,17 +490,15 @@ static int i2o_iop_init_outbound_queue(struct i2o_controller *c) ...@@ -503,17 +490,15 @@ static int i2o_iop_init_outbound_queue(struct i2o_controller *c)
} }
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(1); schedule_timeout(1);
rmb();
} }
m = c->out_queue.phys; m = c->out_queue.phys;
/* Post frames */ /* Post frames */
for (i = 0; i < NMBR_MSG_FRAMES; i++) { for (i = 0; i < I2O_MAX_OUTBOUND_MSG_FRAMES; i++) {
i2o_flush_reply(c, m); i2o_flush_reply(c, m);
udelay(1); /* Promise */ udelay(1); /* Promise */
m += MSG_FRAME_SIZE * 4; m += I2O_OUTBOUND_MSG_FRAME_SIZE * sizeof(u32);
} }
return 0; return 0;
...@@ -530,20 +515,20 @@ static int i2o_iop_init_outbound_queue(struct i2o_controller *c) ...@@ -530,20 +515,20 @@ static int i2o_iop_init_outbound_queue(struct i2o_controller *c)
*/ */
static int i2o_iop_reset(struct i2o_controller *c) static int i2o_iop_reset(struct i2o_controller *c)
{ {
u8 *status = c->status.virt; volatile u8 *status = c->status.virt;
struct i2o_message __iomem *msg; struct i2o_message __iomem *msg;
u32 m; u32 m;
unsigned long timeout; unsigned long timeout;
i2o_status_block *sb = c->status_block.virt; i2o_status_block *sb = c->status_block.virt;
int rc = 0; int rc = 0;
pr_debug("%s: Resetting controller\n", c->name); osm_debug("%s: Resetting controller\n", c->name);
m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
if (m == I2O_QUEUE_EMPTY) if (m == I2O_QUEUE_EMPTY)
return -ETIMEDOUT; return -ETIMEDOUT;
memset(status, 0, 8); memset(c->status_block.virt, 0, 8);
/* Quiesce all IOPs first */ /* Quiesce all IOPs first */
i2o_iop_quiesce_all(); i2o_iop_quiesce_all();
...@@ -568,8 +553,6 @@ static int i2o_iop_reset(struct i2o_controller *c) ...@@ -568,8 +553,6 @@ static int i2o_iop_reset(struct i2o_controller *c)
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(1); schedule_timeout(1);
rmb();
} }
switch (*status) { switch (*status) {
...@@ -984,11 +967,11 @@ int i2o_status_get(struct i2o_controller *c) ...@@ -984,11 +967,11 @@ int i2o_status_get(struct i2o_controller *c)
{ {
struct i2o_message __iomem *msg; struct i2o_message __iomem *msg;
u32 m; u32 m;
u8 *status_block; volatile u8 *status_block;
unsigned long timeout; unsigned long timeout;
status_block = (u8 *) c->status_block.virt; status_block = (u8 *) c->status_block.virt;
memset(status_block, 0, sizeof(i2o_status_block)); memset(c->status_block.virt, 0, sizeof(i2o_status_block));
m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
if (m == I2O_QUEUE_EMPTY) if (m == I2O_QUEUE_EMPTY)
...@@ -1017,8 +1000,6 @@ int i2o_status_get(struct i2o_controller *c) ...@@ -1017,8 +1000,6 @@ int i2o_status_get(struct i2o_controller *c)
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(1); schedule_timeout(1);
rmb();
} }
#ifdef DEBUG #ifdef DEBUG
...@@ -1107,6 +1088,11 @@ static void i2o_iop_release(struct device *dev) ...@@ -1107,6 +1088,11 @@ static void i2o_iop_release(struct device *dev)
i2o_iop_free(c); i2o_iop_free(c);
}; };
/* I2O controller class */
static struct class i2o_controller_class = {
.name = "i2o_controller",
};
/** /**
* i2o_iop_alloc - Allocate and initialize a i2o_controller struct * i2o_iop_alloc - Allocate and initialize a i2o_controller struct
* *
...@@ -1136,8 +1122,14 @@ struct i2o_controller *i2o_iop_alloc(void) ...@@ -1136,8 +1122,14 @@ struct i2o_controller *i2o_iop_alloc(void)
sprintf(c->name, "iop%d", c->unit); sprintf(c->name, "iop%d", c->unit);
device_initialize(&c->device); device_initialize(&c->device);
class_device_initialize(&c->classdev);
c->device.release = &i2o_iop_release; c->device.release = &i2o_iop_release;
c->classdev.class = &i2o_controller_class;
c->classdev.dev = &c->device;
snprintf(c->device.bus_id, BUS_ID_SIZE, "iop%d", c->unit); snprintf(c->device.bus_id, BUS_ID_SIZE, "iop%d", c->unit);
snprintf(c->classdev.class_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);
...@@ -1161,45 +1153,55 @@ int i2o_iop_add(struct i2o_controller *c) ...@@ -1161,45 +1153,55 @@ int i2o_iop_add(struct i2o_controller *c)
{ {
int rc; int rc;
if((rc = device_add(&c->device))) { if ((rc = device_add(&c->device))) {
printk(KERN_ERR "%s: could not register controller\n", c->name); osm_err("%s: could not add controller\n", c->name);
goto iop_reset; goto iop_reset;
} }
printk(KERN_INFO "%s: Activating I2O controller...\n", c->name); if ((rc = class_device_add(&c->classdev))) {
printk(KERN_INFO "%s: This may take a few minutes if there are many " osm_err("%s: could not add controller class\n", c->name);
"devices\n", c->name); goto device_del;
}
if ((rc = i2o_iop_activate(c))) { osm_info("%s: Activating I2O controller...\n", c->name);
printk(KERN_ERR "%s: could not activate controller\n", osm_info("%s: This may take a few minutes if there are many devices\n",
c->name); c->name);
goto iop_reset;
if ((rc = i2o_iop_activate(c))) {
osm_err("%s: could not activate controller\n", c->name);
goto class_del;
} }
pr_debug("%s: building sys table...\n", c->name); osm_debug("%s: building sys table...\n", c->name);
if ((rc = i2o_systab_build())) if ((rc = i2o_systab_build()))
goto iop_reset; goto class_del;
pr_debug("%s: online controller...\n", c->name); osm_debug("%s: online controller...\n", c->name);
if ((rc = i2o_iop_online(c))) if ((rc = i2o_iop_online(c)))
goto iop_reset; goto class_del;
pr_debug("%s: getting LCT...\n", c->name); osm_debug("%s: getting LCT...\n", c->name);
if ((rc = i2o_exec_lct_get(c))) if ((rc = i2o_exec_lct_get(c)))
goto iop_reset; goto class_del;
list_add(&c->list, &i2o_controllers); list_add(&c->list, &i2o_controllers);
i2o_driver_notify_controller_add_all(c); i2o_driver_notify_controller_add_all(c);
printk(KERN_INFO "%s: Controller added\n", c->name); osm_info("%s: Controller added\n", c->name);
return 0; return 0;
iop_reset: class_del:
class_device_del(&c->classdev);
device_del:
device_del(&c->device);
iop_reset:
i2o_iop_reset(c); i2o_iop_reset(c);
return rc; return rc;
...@@ -1260,16 +1262,18 @@ static int __init i2o_iop_init(void) ...@@ -1260,16 +1262,18 @@ static int __init i2o_iop_init(void)
if (rc) if (rc)
goto exit; goto exit;
rc = i2o_driver_init(); if ((rc = class_register(&i2o_controller_class))) {
if (rc) osm_err("can't register class i2o_controller\n");
goto device_exit; goto device_exit;
}
rc = i2o_exec_init(); if ((rc = i2o_driver_init()))
if (rc) goto class_exit;
if ((rc = i2o_exec_init()))
goto driver_exit; goto driver_exit;
rc = i2o_pci_init(); if ((rc = i2o_pci_init()))
if (rc < 0)
goto exec_exit; goto exec_exit;
return 0; return 0;
...@@ -1280,6 +1284,9 @@ static int __init i2o_iop_init(void) ...@@ -1280,6 +1284,9 @@ static int __init i2o_iop_init(void)
driver_exit: driver_exit:
i2o_driver_exit(); i2o_driver_exit();
class_exit:
class_unregister(&i2o_controller_class);
device_exit: device_exit:
i2o_device_exit(); i2o_device_exit();
...@@ -1297,6 +1304,7 @@ static void __exit i2o_iop_exit(void) ...@@ -1297,6 +1304,7 @@ static void __exit i2o_iop_exit(void)
i2o_pci_exit(); i2o_pci_exit();
i2o_exec_exit(); i2o_exec_exit();
i2o_driver_exit(); i2o_driver_exit();
class_unregister(&i2o_controller_class);
i2o_device_exit(); i2o_device_exit();
}; };
......
...@@ -30,15 +30,7 @@ ...@@ -30,15 +30,7 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/i2o.h> #include <linux/i2o.h>
#include "core.h"
/* Module internal functions from other sources */
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 *);
extern int i2o_driver_dispatch(struct i2o_controller *, u32);
/* 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[] = {
...@@ -248,9 +240,7 @@ static int i2o_pci_irq_enable(struct i2o_controller *c) ...@@ -248,9 +240,7 @@ 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;
wmb();
writel(0xffffffff, c->irq_mask); 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,
...@@ -263,7 +253,6 @@ static int i2o_pci_irq_enable(struct i2o_controller *c) ...@@ -263,7 +253,6 @@ static int i2o_pci_irq_enable(struct i2o_controller *c)
} }
writel(0x00000000, c->irq_mask); 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);
...@@ -278,9 +267,7 @@ static int i2o_pci_irq_enable(struct i2o_controller *c) ...@@ -278,9 +267,7 @@ 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)
{ {
wmb();
writel(0xffffffff, c->irq_mask); 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);
...@@ -406,11 +393,11 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, ...@@ -406,11 +393,11 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev,
if ((rc = i2o_iop_add(c))) if ((rc = i2o_iop_add(c)))
goto uninstall; goto uninstall;
get_device(&c->device);
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:
...@@ -478,6 +465,4 @@ void __exit i2o_pci_exit(void) ...@@ -478,6 +465,4 @@ void __exit i2o_pci_exit(void)
{ {
pci_unregister_driver(&i2o_pci_driver); pci_unregister_driver(&i2o_pci_driver);
}; };
EXPORT_SYMBOL(i2o_dma_realloc);
MODULE_DEVICE_TABLE(pci, i2o_pci_ids); MODULE_DEVICE_TABLE(pci, i2o_pci_ids);
...@@ -32,18 +32,6 @@ typedef unsigned int u32; ...@@ -32,18 +32,6 @@ typedef unsigned int u32;
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
/*
* Software module types
*/
#define I2O_SOFTWARE_MODULE_IRTOS 0x11
#define I2O_SOFTWARE_MODULE_IOP_PRIVATE 0x22
#define I2O_SOFTWARE_MODULE_IOP_CONFIG 0x23
/*
* Vendors
*/
#define I2O_VENDOR_DPT 0x001b
/* /*
* I2O Control IOCTLs and structures * I2O Control IOCTLs and structures
*/ */
...@@ -414,6 +402,17 @@ typedef struct _i2o_status_block { ...@@ -414,6 +402,17 @@ typedef struct _i2o_status_block {
#define ADAPTER_STATE_FAILED 0x10 #define ADAPTER_STATE_FAILED 0x10
#define ADAPTER_STATE_FAULTED 0x11 #define ADAPTER_STATE_FAULTED 0x11
/*
* Software module types
*/
#define I2O_SOFTWARE_MODULE_IRTOS 0x11
#define I2O_SOFTWARE_MODULE_IOP_PRIVATE 0x22
#define I2O_SOFTWARE_MODULE_IOP_CONFIG 0x23
/*
* Vendors
*/
#define I2O_VENDOR_DPT 0x001b
/* /*
* DPT / Adaptec specific values for i2o_sg_io_hdr flags. * DPT / Adaptec specific values for i2o_sg_io_hdr flags.
......
...@@ -119,12 +119,21 @@ struct i2o_driver { ...@@ -119,12 +119,21 @@ struct i2o_driver {
}; };
/* /*
* Contains all information which are necessary for DMA operations * Contains DMA mapped address information
*/ */
struct i2o_dma { struct i2o_dma {
void *virt; void *virt;
dma_addr_t phys; dma_addr_t phys;
u32 len; size_t len;
};
/*
* Contains IO mapped address information
*/
struct i2o_io {
void __iomem *virt;
unsigned long phys;
unsigned long len;
}; };
/* /*
...@@ -173,8 +182,8 @@ struct i2o_controller { ...@@ -173,8 +182,8 @@ struct i2o_controller {
struct semaphore lct_lock; /* Lock for LCT updates */ struct semaphore lct_lock; /* Lock for LCT updates */
struct i2o_dma status_block; /* IOP status block */ struct i2o_dma status_block; /* IOP status block */
struct i2o_dma base; /* controller messaging unit */ struct i2o_io base; /* controller messaging unit */
struct i2o_dma in_queue; /* inbound message queue Host->IOP */ struct i2o_io in_queue; /* inbound message queue Host->IOP */
struct i2o_dma out_queue; /* outbound message queue IOP->Host */ struct i2o_dma out_queue; /* outbound message queue IOP->Host */
unsigned int battery:1; /* Has a battery backup */ unsigned int battery:1; /* Has a battery backup */
...@@ -185,6 +194,7 @@ struct i2o_controller { ...@@ -185,6 +194,7 @@ struct i2o_controller {
struct resource mem_resource; /* Mem resource allocated to the IOP */ struct resource mem_resource; /* Mem resource allocated to the IOP */
struct device device; struct device device;
struct class_device classdev; /* I2O controller class */
struct i2o_device *exec; /* Executive */ struct i2o_device *exec; /* Executive */
#if BITS_PER_LONG == 64 #if BITS_PER_LONG == 64
spinlock_t context_list_lock; /* lock for context_list */ spinlock_t context_list_lock; /* lock for context_list */
...@@ -235,9 +245,10 @@ struct i2o_sys_tbl { ...@@ -235,9 +245,10 @@ struct i2o_sys_tbl {
extern struct list_head i2o_controllers; extern struct list_head i2o_controllers;
/* Message functions */ /* Message functions */
static inline u32 i2o_msg_get(struct i2o_controller *, struct i2o_message __iomem **); static inline u32 i2o_msg_get(struct i2o_controller *,
extern u32 i2o_msg_get_wait(struct i2o_controller *, struct i2o_message __iomem **, struct i2o_message __iomem **);
int); extern u32 i2o_msg_get_wait(struct i2o_controller *,
struct i2o_message __iomem **, int);
static inline void i2o_msg_post(struct i2o_controller *, u32); static inline void i2o_msg_post(struct i2o_controller *, u32);
static inline int i2o_msg_post_wait(struct i2o_controller *, u32, static inline int i2o_msg_post_wait(struct i2o_controller *, u32,
unsigned long); unsigned long);
...@@ -638,14 +649,12 @@ extern int i2o_exec_lct_get(struct i2o_controller *); ...@@ -638,14 +649,12 @@ extern int i2o_exec_lct_get(struct i2o_controller *);
* available returns I2O_QUEUE_EMPTY and msg is leaved untouched. * available returns I2O_QUEUE_EMPTY and msg is leaved untouched.
*/ */
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 = readl(c->in_port); u32 m = readl(c->in_port);
if (m != 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;
}; };
...@@ -659,7 +668,6 @@ static inline u32 i2o_msg_get(struct i2o_controller *c, ...@@ -659,7 +668,6 @@ 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)
{ {
wmb();
writel(m, c->in_port); writel(m, c->in_port);
}; };
...@@ -706,14 +714,11 @@ static inline void i2o_flush_reply(struct i2o_controller *c, u32 m) ...@@ -706,14 +714,11 @@ 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 __iomem *i2o_msg_out_to_virt(struct static inline struct i2o_message *i2o_msg_out_to_virt(struct i2o_controller *c,
i2o_controller *c,
u32 m) u32 m)
{ {
if (unlikely BUG_ON(m < c->out_queue.phys
(m < c->out_queue.phys || m >= c->out_queue.phys + c->out_queue.len);
|| m >= c->out_queue.phys + c->out_queue.len))
return NULL;
return c->out_queue.virt + (m - c->out_queue.phys); return c->out_queue.virt + (m - c->out_queue.phys);
}; };
...@@ -729,69 +734,13 @@ static inline struct i2o_message __iomem *i2o_msg_out_to_virt(struct ...@@ -729,69 +734,13 @@ static inline struct i2o_message __iomem *i2o_msg_out_to_virt(struct
* work for receive side messages as they are kmalloc objects * work for receive side messages as they are kmalloc objects
* in a different pool. * in a different pool.
*/ */
static inline struct i2o_message __iomem *i2o_msg_in_to_virt(struct i2o_controller *c, static inline struct i2o_message __iomem *i2o_msg_in_to_virt(struct
i2o_controller *c,
u32 m) u32 m)
{ {
return c->in_queue.virt + m; return c->in_queue.virt + m;
}; };
/**
* i2o_dma_alloc - Allocate DMA memory
* @dev: struct device pointer to the PCI device of the I2O controller
* @addr: i2o_dma struct which should get the DMA buffer
* @len: length of the new DMA memory
* @gfp_mask: GFP mask
*
* Allocate a coherent DMA memory and write the pointers into addr.
*
* Returns 0 on success or -ENOMEM on failure.
*/
static inline int i2o_dma_alloc(struct device *dev, struct i2o_dma *addr,
size_t len, unsigned int gfp_mask)
{
struct pci_dev *pdev = to_pci_dev(dev);
int dma_64 = 0;
if ((sizeof(dma_addr_t) > 4) && (pdev->dma_mask == DMA_64BIT_MASK)) {
dma_64 = 1;
if(pci_set_dma_mask(pdev, DMA_32BIT_MASK))
return -ENOMEM;
}
addr->virt = dma_alloc_coherent(dev, len, &addr->phys, gfp_mask);
if ((sizeof(dma_addr_t) > 4) && dma_64)
if(pci_set_dma_mask(pdev, DMA_64BIT_MASK))
printk(KERN_WARNING "i2o: unable to set 64-bit DMA");
if (!addr->virt)
return -ENOMEM;
memset(addr->virt, 0, len);
addr->len = len;
return 0;
};
/**
* i2o_dma_free - Free DMA memory
* @dev: struct device pointer to the PCI device of the I2O controller
* @addr: i2o_dma struct which contains the DMA buffer
*
* Free a coherent DMA memory and set virtual address of addr to NULL.
*/
static inline void i2o_dma_free(struct device *dev, struct i2o_dma *addr)
{
if (addr->virt) {
if (addr->phys)
dma_free_coherent(dev, addr->len, addr->virt,
addr->phys);
else
kfree(addr->virt);
addr->virt = NULL;
}
};
/* /*
* Endian handling wrapped into the macro - keeps the core code * Endian handling wrapped into the macro - keeps the core code
* cleaner. * cleaner.
...@@ -1141,16 +1090,13 @@ extern void i2o_debug_state(struct i2o_controller *c); ...@@ -1141,16 +1090,13 @@ extern void i2o_debug_state(struct i2o_controller *c);
#define ELEVEN_WORD_MSG_SIZE 0x000B0000 #define ELEVEN_WORD_MSG_SIZE 0x000B0000
#define I2O_MESSAGE_SIZE(x) ((x)<<16) #define I2O_MESSAGE_SIZE(x) ((x)<<16)
/* Special TID Assignments */ /* special TID assignments */
#define ADAPTER_TID 0 #define ADAPTER_TID 0
#define HOST_TID 1 #define HOST_TID 1
#define MSG_FRAME_SIZE 128 /* i2o_scsi assumes >= 32 */ /* outbound queue defines */
#define SG_TABLESIZE 30 #define I2O_MAX_OUTBOUND_MSG_FRAMES 128
#define NMBR_MSG_FRAMES 128 #define I2O_OUTBOUND_MSG_FRAME_SIZE 128 /* in 32-bit words */
#define MSG_POOL_SIZE (MSG_FRAME_SIZE*NMBR_MSG_FRAMES*sizeof(u32))
#define I2O_POST_WAIT_OK 0 #define I2O_POST_WAIT_OK 0
#define I2O_POST_WAIT_TIMEOUT -ETIMEDOUT #define I2O_POST_WAIT_TIMEOUT -ETIMEDOUT
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment