Commit 3d0affc8 authored by James Bottomley's avatar James Bottomley Committed by James Bottomley

i20 rewrite

From: Markus Lidel <Markus.Lidel@shadowconnect.com>

generic:
- split i2o_core into several files, grouped by same function
- I2O devices are now registered as devices and show up in sysfs
- the various I2O OSM's (e.g. i2o_scsi) now register in the I2O core
   and also use the 2.6 driver mechanism.
- I2O messages will be created in the message frame instead of creating
   it in local memory and copying it over later on.
- context list for 64 pointer to 32 context conversion now uses a
   double linked list

PCI:
- driver now registers as a PCI device driver and uses probe function to
   get the possible controllers. (needed for hotplugging)
- converted DMA handling from pci_* to generic dma_* functions

Block OSM:
- use one request queue per I2O block device instead of one per
   controller
- I2O block devices and queues are allocated dynamically and therefore
   no more limit of block devices

SCSI OSM:
- corrected bug in SCSI reply function which caused the memory to be
   freed before the done function was called.
- one I2O controller registers as one scsi host instead of one scsi host
   per channel
- no more ch,id,lun => tid mapping table

Config OSM:
- added ioctl32 for passthru and getiops.
- removed ioctl_html

Documentation:
- removed TODO entries from README
- moved docs under Documentation/i2o
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 8ef4b795
Linux I2O Support (c) Copyright 1999 Red Hat Software
and others.
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.
AUTHORS (so far)
Alan Cox, Building Number Three Ltd.
Core code, SCSI and Block OSMs
Steve Ralston, LSI Logic Corp.
Debugging SCSI and Block OSM
Deepak Saxena, Intel Corp.
Various core/block extensions
/proc interface, bug fixes
Ioctl interfaces for control
Debugging LAN OSM
Philip Rumpf
Fixed assorted dumb SMP locking bugs
Juha Sievanen, University of Helsinki Finland
LAN OSM code
/proc interface to LAN class
Bug fixes
Core code extensions
Auvo Häkkinen, University of Helsinki Finland
LAN OSM code
/Proc interface to LAN class
Bug fixes
Core code extensions
Taneli Vähäkangas, University of Helsinki Finland
Fixes to i2o_config
CREDITS
This work was made possible by
Red Hat Software
Funding for the Building #3 part of the project
Symbios Logic (Now LSI)
Host adapters, hints, known to work platforms when I hit
compatibility problems
BoxHill Corporation
Loan of initial FibreChannel disk array used for development work.
European Comission
Funding the work done by the University of Helsinki
SysKonnect
Loan of FDDI and Gigabit Ethernet cards
ASUSTeK
Loan of I2O motherboard
This diff is collapsed.
......@@ -5,6 +5,7 @@
# In the future, some of these should be built conditionally.
#
i2o_core-y += iop.o driver.o device.o debug.o pci.o exec-osm.o
obj-$(CONFIG_I2O) += i2o_core.o
obj-$(CONFIG_I2O_CONFIG)+= i2o_config.o
obj-$(CONFIG_I2O_BLOCK) += i2o_block.o
......
This diff is collapsed.
This diff is collapsed.
/*
* Functions to handle I2O drivers (OSMs) and I2O bus type for sysfs
*
* Copyright (C) 2004 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.
*/
#include <linux/device.h>
#include <linux/module.h>
#include <linux/rwsem.h>
#include <linux/i2o.h>
/* max_drivers - Maximum I2O drivers (OSMs) which could be registered */
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");
/* I2O drivers lock and array */
static spinlock_t i2o_drivers_lock = SPIN_LOCK_UNLOCKED;
static struct i2o_driver **i2o_drivers;
/**
* i2o_bus_match - Tell if a I2O device class id match the class ids of
* the I2O driver (OSM)
*
* @dev: device which should be verified
* @drv: the driver to match against
*
* Used by the bus to check if the driver wants to handle the device.
*
* Returns 1 if the class ids of the driver match the class id of the
* device, otherwise 0.
*/
static int i2o_bus_match(struct device *dev, struct device_driver *drv)
{
struct i2o_device *i2o_dev = to_i2o_device(dev);
struct i2o_driver *i2o_drv = to_i2o_driver(drv);
struct i2o_class_id *ids = i2o_drv->classes;
if (ids)
while (ids->class_id != I2O_CLASS_END) {
if (ids->class_id == i2o_dev->lct_data.class_id)
return 1;
ids++;
}
return 0;
};
/* I2O bus type */
struct bus_type i2o_bus_type = {
.name = "i2o",
.match = i2o_bus_match,
};
/**
* i2o_driver_register - Register a I2O driver (OSM) in the I2O core
* @drv: I2O driver which should be registered
*
* Registers the OSM drv in the I2O core and creates an event queues if
* necessary.
*
* Returns 0 on success or negative error code on failure.
*/
int i2o_driver_register(struct i2o_driver *drv)
{
int i;
int rc = 0;
unsigned long flags;
pr_debug("Register driver %s\n", drv->name);
if (drv->event) {
drv->event_queue = create_workqueue(drv->name);
if (!drv->event_queue) {
printk(KERN_ERR "i2o: Could not initialize event queue "
"for driver %s\n", drv->name);
return -EFAULT;
}
pr_debug("Event queue initialized for driver %s\n", drv->name);
} else
drv->event_queue = NULL;
drv->driver.name = drv->name;
drv->driver.bus = &i2o_bus_type;
spin_lock_irqsave(&i2o_drivers_lock, flags);
for (i = 0; i2o_drivers[i]; i++)
if (i >= i2o_max_drivers) {
printk(KERN_ERR "i2o: too many drivers registered, "
"increase max_drivers\n");
spin_unlock_irqrestore(&i2o_drivers_lock, flags);
return -EFAULT;
}
drv->context = i;
i2o_drivers[i] = drv;
spin_unlock_irqrestore(&i2o_drivers_lock, flags);
pr_debug("driver %s gets context id %d\n", drv->name, drv->context);
rc = driver_register(&drv->driver);
if (rc)
destroy_workqueue(drv->event_queue);
return rc;
};
/**
* i2o_driver_unregister - Unregister a I2O driver (OSM) from the I2O core
* @drv: I2O driver which should be unregistered
*
* Unregisters the OSM drv from the I2O core and cleanup event queues if
* necessary.
*/
void i2o_driver_unregister(struct i2o_driver *drv)
{
unsigned long flags;
pr_debug("unregister driver %s\n", drv->name);
driver_unregister(&drv->driver);
spin_lock_irqsave(&i2o_drivers_lock, flags);
i2o_drivers[drv->context] = NULL;
spin_unlock_irqrestore(&i2o_drivers_lock, flags);
if (drv->event_queue) {
destroy_workqueue(drv->event_queue);
drv->event_queue = NULL;
pr_debug("event queue removed for %s\n", drv->name);
}
};
/**
* i2o_driver_dispatch - dispatch an I2O reply message
* @c: I2O controller of the message
* @m: I2O message number
* @msg: I2O message to be delivered
*
* The reply is delivered to the driver from which the original message
* was. This function is only called from interrupt context.
*
* Returns 0 on success and the message should not be flushed. Returns > 0
* on success and if the message should be flushed afterwords. Returns
* negative error code on failure (the message will be flushed too).
*/
int i2o_driver_dispatch(struct i2o_controller *c, u32 m,
struct i2o_message *msg)
{
struct i2o_driver *drv;
u32 context = readl(&msg->u.s.icntxt);
if (likely(context < i2o_max_drivers)) {
spin_lock(&i2o_drivers_lock);
drv = i2o_drivers[context];
spin_unlock(&i2o_drivers_lock);
if (unlikely(!drv)) {
printk(KERN_WARNING "i2o: Spurious reply to unknown "
"driver %d\n", context);
return -EIO;
}
if ((readl(&msg->u.head[1]) >> 24) == I2O_CMD_UTIL_EVT_REGISTER) {
struct i2o_device *dev, *tmp;
struct i2o_event *evt;
u16 size;
u16 tid;
tid = readl(&msg->u.head[1]) & 0x1fff;
pr_debug("%s: event received from device %d\n", c->name,
tid);
/* cut of header from message size (in 32-bit words) */
size = (readl(&msg->u.head[0]) >> 16) - 5;
evt = kmalloc(size * 4 + sizeof(*evt), GFP_ATOMIC);
if (!evt)
return -ENOMEM;
memset(evt, 0, size * 4 + sizeof(*evt));
evt->size = size;
memcpy_fromio(&evt->tcntxt, &msg->u.s.tcntxt,
(size + 2) * 4);
list_for_each_entry_safe(dev, tmp, &c->devices, list)
if (dev->lct_data.tid == tid) {
evt->i2o_dev = dev;
break;
}
INIT_WORK(&evt->work, (void (*)(void *))drv->event,
evt);
queue_work(drv->event_queue, &evt->work);
return 1;
}
if (likely(drv->reply))
return drv->reply(c, m, msg);
else
pr_debug("%s: Reply to driver %s, but no reply function"
" defined!\n", c->name, drv->name);
return -EIO;
} else
printk(KERN_WARNING "i2o: Spurious reply to unknown driver "
"%d\n", readl(&msg->u.s.icntxt));
return -EIO;
}
/**
* i2o_driver_init - initialize I2O drivers (OSMs)
*
* Registers the I2O bus and allocate memory for the array of OSMs.
*
* Returns 0 on success or negative error code on failure.
*/
int __init i2o_driver_init(void)
{
int rc = 0;
if ((i2o_max_drivers < 2) || (i2o_max_drivers > 64) ||
((i2o_max_drivers ^ (i2o_max_drivers - 1)) !=
(2 * i2o_max_drivers - 1))) {
printk(KERN_WARNING "i2o: max_drivers set to %d, but must be "
">=2 and <= 64 and a power of 2\n", i2o_max_drivers);
i2o_max_drivers = I2O_MAX_DRIVERS;
}
printk(KERN_INFO "i2o: max_drivers=%d\n", i2o_max_drivers);
i2o_drivers =
kmalloc(i2o_max_drivers * sizeof(*i2o_drivers), GFP_KERNEL);
if (!i2o_drivers)
return -ENOMEM;
memset(i2o_drivers, 0, i2o_max_drivers * sizeof(*i2o_drivers));
rc = bus_register(&i2o_bus_type);
if (rc < 0)
kfree(i2o_drivers);
return rc;
};
/**
* i2o_driver_exit - clean up I2O drivers (OSMs)
*
* Unregisters the I2O bus and free driver array.
*/
void __exit i2o_driver_exit(void)
{
bus_unregister(&i2o_bus_type);
kfree(i2o_drivers);
};
EXPORT_SYMBOL(i2o_driver_register);
EXPORT_SYMBOL(i2o_driver_unregister);
This diff is collapsed.
This diff is collapsed.
/*
* Block OSM structures/API
*
* Copyright (C) 1999-2002 Red Hat Software
*
* Written by Alan Cox, Building Number Three Ltd
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* For the purpose of avoiding doubt the preferred form of the work
* for making modifications shall be a standards compliant form such
* gzipped tar and not one requiring a proprietary or patent encumbered
* tool to unpack.
*
* Fixes/additions:
* Steve Ralston:
* Multiple device handling error fixes,
* Added a queue depth.
* Alan Cox:
* FC920 has an rmw bug. Dont or in the end marker.
* Removed queue walk, fixed for 64bitness.
* Rewrote much of the code over time
* Added indirect block lists
* Handle 64K limits on many controllers
* Don't use indirects on the Promise (breaks)
* Heavily chop down the queue depths
* Deepak Saxena:
* Independent queues per IOP
* Support for dynamic device creation/deletion
* Code cleanup
* Support for larger I/Os through merge* functions
* (taken from DAC960 driver)
* Boji T Kannanthanam:
* Set the I2O Block devices to be detected in increasing
* order of TIDs during boot.
* Search and set the I2O block device that we boot off
* from as the first device to be claimed (as /dev/i2o/hda)
* Properly attach/detach I2O gendisk structure from the
* system gendisk list. The I2O block devices now appear in
* /proc/partitions.
* Markus Lidel <Markus.Lidel@shadowconnect.com>:
* Minor bugfixes for 2.6.
*/
#ifndef I2O_BLOCK_OSM_H
#define I2O_BLOCK_OSM_H
#define I2O_BLOCK_RETRY_TIME HZ/4
#define I2O_BLOCK_MAX_OPEN_REQUESTS 50
/* I2O Block OSM mempool struct */
struct i2o_block_mempool {
kmem_cache_t *slab;
mempool_t *pool;
};
/* I2O Block device descriptor */
struct i2o_block_device {
struct i2o_device *i2o_dev; /* pointer to I2O device */
struct gendisk *gd;
spinlock_t lock; /* queue lock */
struct list_head open_queue; /* list of transfered, but unfinished
requests */
unsigned int open_queue_depth; /* number of requests in the queue */
int rcache; /* read cache flags */
int wcache; /* write cache flags */
int flags;
int power; /* power state */
int media_change_flag; /* media changed flag */
};
/* I2O Block device request */
struct i2o_block_request
{
struct list_head queue;
struct request *req; /* corresponding request */
struct i2o_block_device *i2o_blk_dev; /* I2O block device */
int sg_dma_direction; /* direction of DMA buffer read/write */
int sg_nents; /* number of SG elements */
struct scatterlist sg_table[I2O_MAX_SEGMENTS]; /* SG table */
};
/* I2O Block device delayed request */
struct i2o_block_delayed_request
{
struct work_struct work;
struct request_queue *queue;
};
#endif
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
* I2O user space accessible structures/APIs
*
*
* (c) Copyright 1999, 2000 Red Hat Software
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
*************************************************************************
*
* This header file defines the I2O APIs that are available to both
......@@ -23,7 +23,7 @@
/* How many controllers are we allowing */
#define MAX_I2O_CONTROLLERS 32
#include <linux/ioctl.h>
//#include <linux/ioctl.h>
/*
* I2O Control IOCTLs and structures
......@@ -42,17 +42,24 @@
#define I2OEVTREG _IOW(I2O_MAGIC_NUMBER,10,struct i2o_evt_id)
#define I2OEVTGET _IOR(I2O_MAGIC_NUMBER,11,struct i2o_evt_info)
#define I2OPASSTHRU _IOR(I2O_MAGIC_NUMBER,12,struct i2o_cmd_passthru)
#define I2OPASSTHRU32 _IOR(I2O_MAGIC_NUMBER,12,struct i2o_cmd_passthru32)
struct i2o_cmd_passthru32
{
unsigned int iop; /* IOP unit number */
u32 msg; /* message */
};
struct i2o_cmd_passthru
{
unsigned int iop; /* IOP unit number */
void __user *msg; /* message */
void __user *msg; /* message */
};
struct i2o_cmd_hrtlct
{
unsigned int iop; /* IOP unit number */
void __user *resbuf; /* Buffer for result */
unsigned int iop; /* IOP unit number */
void __user *resbuf; /* Buffer for result */
unsigned int __user *reslen; /* Buffer length in bytes */
};
......@@ -351,14 +358,15 @@ typedef struct _i2o_status_block
#define I2O_CLASS_BUS_ADAPTER_PORT 0x080
#define I2O_CLASS_PEER_TRANSPORT_AGENT 0x090
#define I2O_CLASS_PEER_TRANSPORT 0x091
#define I2O_CLASS_END 0xfff
/*
/*
* Rest of 0x092 - 0x09f reserved for peer-to-peer classes
*/
#define I2O_CLASS_MATCH_ANYCLASS 0xffffffff
/*
/*
* Subclasses
*/
......@@ -380,7 +388,7 @@ typedef struct _i2o_status_block
#define I2O_PARAMS_TABLE_CLEAR 0x000A
/*
* I2O serial number conventions / formats
* I2O serial number conventions / formats
* (circa v1.5)
*/
......@@ -391,7 +399,7 @@ typedef struct _i2o_status_block
#define I2O_SNFORMAT_LAN48_MAC 4
#define I2O_SNFORMAT_WAN 5
/*
/*
* Plus new in v2.0 (Yellowstone pdf doc)
*/
......@@ -402,7 +410,7 @@ typedef struct _i2o_status_block
#define I2O_SNFORMAT_UNKNOWN2 0xff
/*
* I2O Get Status State values
* I2O Get Status State values
*/
#define ADAPTER_STATE_INITIALIZING 0x01
......
This diff is collapsed.
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