Commit 75a97cd1 authored by Alan Cox's avatar Alan Cox Committed by Linus Torvalds

[PATCH] i2o-scsi next installment

parent 0b71bb7f
...@@ -9,10 +9,11 @@ ...@@ -9,10 +9,11 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. * General Public License for more details.
* *
* For the purpose of avoiding doubt the preferred form of the work * For the avoidance of doubt the "preferred form" of this code is one which
* for making modifications shall be a standards compliant form such * is in an open non patent encumbered format. Where cryptographic key signing
* gzipped tar and not one requiring a proprietary or patent encumbered * forms part of the process of creating an executable the information
* tool to unpack. * including keys needed to generate an equivalently functional executable
* are deemed to be part of the source code.
* *
* Complications for I2O scsi * Complications for I2O scsi
* *
...@@ -61,7 +62,7 @@ ...@@ -61,7 +62,7 @@
#include "../../scsi/sd.h" #include "../../scsi/sd.h"
#include "i2o_scsi.h" #include "i2o_scsi.h"
#define VERSION_STRING "Version 0.1.0" #define VERSION_STRING "Version 0.1.1"
#define dprintk(x) #define dprintk(x)
...@@ -114,7 +115,10 @@ static chain_buf *sg_chain_pool = NULL; ...@@ -114,7 +115,10 @@ static chain_buf *sg_chain_pool = NULL;
static int sg_chain_tag = 0; static int sg_chain_tag = 0;
static int sg_max_frags = SG_MAX_FRAGS; static int sg_max_frags = SG_MAX_FRAGS;
/* /**
* i2o_retry_run - retry on timeout
* @f: unused
*
* Retry congested frames. This actually needs pushing down into * Retry congested frames. This actually needs pushing down into
* i2o core. We should only bother the OSM with this when we can't * i2o core. We should only bother the OSM with this when we can't
* queue and retry the frame. Or perhaps we should call the OSM * queue and retry the frame. Or perhaps we should call the OSM
...@@ -134,6 +138,13 @@ static void i2o_retry_run(unsigned long f) ...@@ -134,6 +138,13 @@ static void i2o_retry_run(unsigned long f)
spin_unlock_irqrestore(&retry_lock, flags); spin_unlock_irqrestore(&retry_lock, flags);
} }
/**
* flush_pending - empty the retry queue
*
* Turn each of the pending commands into a NOP and post it back
* to the controller to clear it.
*/
static void flush_pending(void) static void flush_pending(void)
{ {
int i; int i;
...@@ -150,6 +161,20 @@ static void flush_pending(void) ...@@ -150,6 +161,20 @@ static void flush_pending(void)
spin_unlock_irqrestore(&retry_lock, flags); spin_unlock_irqrestore(&retry_lock, flags);
} }
/**
* i2o_scsi_reply - scsi message reply processor
* @h: our i2o handler
* @c: controller issuing the reply
* @msg: the message from the controller (mapped)
*
* Process reply messages (interrupts in normal scsi controller think).
* We can get a variety of messages to process. The normal path is
* scsi command completions. We must also deal with IOP failures,
* the reply to a bus reset and the reply to a LUN query.
*
* Locks: the queue lock is taken to call the completion handler
*/
static void i2o_scsi_reply(struct i2o_handler *h, struct i2o_controller *c, struct i2o_message *msg) static void i2o_scsi_reply(struct i2o_handler *h, struct i2o_controller *c, struct i2o_message *msg)
{ {
Scsi_Cmnd *current_command; Scsi_Cmnd *current_command;
...@@ -227,7 +252,7 @@ static void i2o_scsi_reply(struct i2o_handler *h, struct i2o_controller *c, stru ...@@ -227,7 +252,7 @@ static void i2o_scsi_reply(struct i2o_handler *h, struct i2o_controller *c, stru
dprintk(("i2o got a scsi reply %08X: ", m[0])); dprintk(("i2o got a scsi reply %08X: ", m[0]));
dprintk(("m[2]=%08X: ", m[2])); dprintk(("m[2]=%08X: ", m[2]));
dprintk(("m[4]=%08X\n", m[4])); dprintk(("m[4]=%08X\n", m[4]));
if(m[2]&0x80000000) if(m[2]&0x80000000)
{ {
if(m[2]&0x40000000) if(m[2]&0x40000000)
...@@ -236,7 +261,7 @@ static void i2o_scsi_reply(struct i2o_handler *h, struct i2o_controller *c, stru ...@@ -236,7 +261,7 @@ static void i2o_scsi_reply(struct i2o_handler *h, struct i2o_controller *c, stru
lun_done=1; lun_done=1;
return; return;
} }
printk(KERN_ERR "i2o_scsi: bus reset reply.\n"); printk(KERN_INFO "i2o_scsi: bus reset completed.\n");
return; return;
} }
/* /*
...@@ -313,6 +338,18 @@ struct i2o_handler i2o_scsi_handler= ...@@ -313,6 +338,18 @@ struct i2o_handler i2o_scsi_handler=
I2O_CLASS_SCSI_PERIPHERAL I2O_CLASS_SCSI_PERIPHERAL
}; };
/**
* i2o_find_lun - report the lun of an i2o device
* @c: i2o controller owning the device
* @d: i2o disk device
* @target: filled in with target id
* @lun: filled in with target lun
*
* Query an I2O device to find out its SCSI lun and target numbering. We
* don't currently handle some of the fancy SCSI-3 stuff although our
* querying is sufficient to do so.
*/
static int i2o_find_lun(struct i2o_controller *c, struct i2o_device *d, int *target, int *lun) static int i2o_find_lun(struct i2o_controller *c, struct i2o_device *d, int *target, int *lun)
{ {
u8 reply[8]; u8 reply[8];
...@@ -331,6 +368,19 @@ static int i2o_find_lun(struct i2o_controller *c, struct i2o_device *d, int *tar ...@@ -331,6 +368,19 @@ static int i2o_find_lun(struct i2o_controller *c, struct i2o_device *d, int *tar
return 0; return 0;
} }
/**
* i2o_scsi_init - initialize an i2o device for scsi
* @c: i2o controller owning the device
* @d: scsi controller
* @shpnt: scsi device we wish it to become
*
* Enumerate the scsi peripheral/fibre channel peripheral class
* devices that are children of the controller. From that we build
* a translation map for the command queue code. Since I2O works on
* its own tid's we effectively have to think backwards to get what
* the midlayer wants
*/
static void i2o_scsi_init(struct i2o_controller *c, struct i2o_device *d, struct Scsi_Host *shpnt) static void i2o_scsi_init(struct i2o_controller *c, struct i2o_device *d, struct Scsi_Host *shpnt)
{ {
struct i2o_device *unit; struct i2o_device *unit;
...@@ -391,6 +441,16 @@ static void i2o_scsi_init(struct i2o_controller *c, struct i2o_device *d, struct ...@@ -391,6 +441,16 @@ static void i2o_scsi_init(struct i2o_controller *c, struct i2o_device *d, struct
} }
} }
/**
* i2o_scsi_detect - probe for I2O scsi devices
* @tpnt: scsi layer template
*
* I2O is a little odd here. The I2O core already knows what the
* devices are. It also knows them by disk and tape as well as
* by controller. We register each I2O scsi class object as a
* scsi controller and then let the enumeration fake up the rest
*/
static int i2o_scsi_detect(Scsi_Host_Template * tpnt) static int i2o_scsi_detect(Scsi_Host_Template * tpnt)
{ {
unsigned long flags; unsigned long flags;
...@@ -398,7 +458,7 @@ static int i2o_scsi_detect(Scsi_Host_Template * tpnt) ...@@ -398,7 +458,7 @@ static int i2o_scsi_detect(Scsi_Host_Template * tpnt)
int i; int i;
int count; int count;
printk("i2o_scsi.c: %s\n", VERSION_STRING); printk(KERN_INFO "i2o_scsi.c: %s\n", VERSION_STRING);
if(i2o_install_handler(&i2o_scsi_handler)<0) if(i2o_install_handler(&i2o_scsi_handler)<0)
{ {
...@@ -409,14 +469,14 @@ static int i2o_scsi_detect(Scsi_Host_Template * tpnt) ...@@ -409,14 +469,14 @@ static int i2o_scsi_detect(Scsi_Host_Template * tpnt)
if((sg_chain_pool = kmalloc(SG_CHAIN_POOL_SZ, GFP_KERNEL)) == NULL) if((sg_chain_pool = kmalloc(SG_CHAIN_POOL_SZ, GFP_KERNEL)) == NULL)
{ {
printk("i2o_scsi: Unable to alloc %d byte SG chain buffer pool.\n", SG_CHAIN_POOL_SZ); printk(KERN_INFO "i2o_scsi: Unable to alloc %d byte SG chain buffer pool.\n", SG_CHAIN_POOL_SZ);
printk("i2o_scsi: SG chaining DISABLED!\n"); printk(KERN_INFO "i2o_scsi: SG chaining DISABLED!\n");
sg_max_frags = 11; sg_max_frags = 11;
} }
else else
{ {
printk(" chain_pool: %d bytes @ %p\n", SG_CHAIN_POOL_SZ, sg_chain_pool); printk(KERN_INFO " chain_pool: %d bytes @ %p\n", SG_CHAIN_POOL_SZ, sg_chain_pool);
printk(" (%d byte buffers X %d can_queue X %d i2o controllers)\n", printk(KERN_INFO " (%d byte buffers X %d can_queue X %d i2o controllers)\n",
SG_CHAIN_BUF_SZ, I2O_SCSI_CAN_QUEUE, i2o_num_controllers); SG_CHAIN_BUF_SZ, I2O_SCSI_CAN_QUEUE, i2o_num_controllers);
sg_max_frags = SG_MAX_FRAGS; // 64 sg_max_frags = SG_MAX_FRAGS; // 64
} }
...@@ -456,14 +516,11 @@ static int i2o_scsi_detect(Scsi_Host_Template * tpnt) ...@@ -456,14 +516,11 @@ static int i2o_scsi_detect(Scsi_Host_Template * tpnt)
shpnt = scsi_register(tpnt, sizeof(struct i2o_scsi_host)); shpnt = scsi_register(tpnt, sizeof(struct i2o_scsi_host));
if(shpnt==NULL) if(shpnt==NULL)
continue; continue;
save_flags(flags);
cli();
shpnt->unique_id = (u32)d; shpnt->unique_id = (u32)d;
shpnt->io_port = 0; shpnt->io_port = 0;
shpnt->n_io_port = 0; shpnt->n_io_port = 0;
shpnt->irq = 0; shpnt->irq = 0;
shpnt->this_id = /* Good question */15; shpnt->this_id = /* Good question */15;
restore_flags(flags);
i2o_scsi_init(c, d, shpnt); i2o_scsi_init(c, d, shpnt);
count++; count++;
} }
...@@ -509,6 +566,20 @@ static const char *i2o_scsi_info(struct Scsi_Host *SChost) ...@@ -509,6 +566,20 @@ static const char *i2o_scsi_info(struct Scsi_Host *SChost)
return(&hostdata->controller->name[0]); return(&hostdata->controller->name[0]);
} }
/**
* i2o_scsi_queuecommand - queue a SCSI command
* @SCpnt: scsi command pointer
* @done: callback for completion
*
* Issue a scsi comamnd asynchronously. Return 0 on success or 1 if
* we hit an error (normally message queue congestion). The only
* minor complication here is that I2O deals with the device addressing
* so we have to map the bus/dev/lun back to an I2O handle as well
* as faking absent devices ourself.
*
* Locks: takes the controller lock on error path only
*/
static int i2o_scsi_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) static int i2o_scsi_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
{ {
int i; int i;
...@@ -525,6 +596,7 @@ static int i2o_scsi_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) ...@@ -525,6 +596,7 @@ static int i2o_scsi_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
u32 len; u32 len;
u32 reqlen; u32 reqlen;
u32 tag; u32 tag;
unsigned long flags;
static int max_qd = 1; static int max_qd = 1;
...@@ -560,24 +632,22 @@ static int i2o_scsi_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) ...@@ -560,24 +632,22 @@ static int i2o_scsi_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
if(tid == -1) if(tid == -1)
{ {
SCpnt->result = DID_NO_CONNECT << 16; SCpnt->result = DID_NO_CONNECT << 16;
spin_lock_irqsave(host->host_lock, flags);
done(SCpnt); done(SCpnt);
spin_unlock_irqrestore(host->host_lock, flags);
return 0; return 0;
} }
dprintk(("Real scsi messages.\n")); dprintk(("Real scsi messages.\n"));
/* /*
* Obtain an I2O message. Right now we _have_ to obtain one * Obtain an I2O message. If there are none free then
* until the scsi layer stuff is cleaned up. * throw it back to the scsi layer
*/ */
do m = le32_to_cpu(I2O_POST_READ32(c));
{ if(m==0xFFFFFFFF)
mb(); return 1;
m = le32_to_cpu(I2O_POST_READ32(c));
}
while(m==0xFFFFFFFF);
msg = (u32 *)(c->mem_offset + m); msg = (u32 *)(c->mem_offset + m);
...@@ -603,7 +673,11 @@ static int i2o_scsi_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) ...@@ -603,7 +673,11 @@ static int i2o_scsi_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
{ {
/* Unknown - kill the command */ /* Unknown - kill the command */
SCpnt->result = DID_NO_CONNECT << 16; SCpnt->result = DID_NO_CONNECT << 16;
/* We must lock the request queue while completing */
spin_lock_irqsave(host->host_lock, flags);
done(SCpnt); done(SCpnt);
spin_unlock_irqrestore(host->host_lock, flags);
return 0; return 0;
} }
...@@ -772,11 +846,25 @@ static int i2o_scsi_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) ...@@ -772,11 +846,25 @@ static int i2o_scsi_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
return 0; return 0;
} }
/**
* internal_done - legacy scsi glue
* @SCPnt: command
*
* Completion function for a synchronous command
*/
static void internal_done(Scsi_Cmnd * SCpnt) static void internal_done(Scsi_Cmnd * SCpnt)
{ {
SCpnt->SCp.Status++; SCpnt->SCp.Status++;
} }
/**
* i2o_scsi_command - issue a scsi command and wait
* @SCPnt: command
*
* Issue a SCSI command and wait for it to complete.
*/
static int i2o_scsi_command(Scsi_Cmnd * SCpnt) static int i2o_scsi_command(Scsi_Cmnd * SCpnt)
{ {
i2o_scsi_queuecommand(SCpnt, internal_done); i2o_scsi_queuecommand(SCpnt, internal_done);
...@@ -786,6 +874,17 @@ static int i2o_scsi_command(Scsi_Cmnd * SCpnt) ...@@ -786,6 +874,17 @@ static int i2o_scsi_command(Scsi_Cmnd * SCpnt)
return SCpnt->result; return SCpnt->result;
} }
/**
* i2o_scsi_abort - abort a running command
* @SCpnt: command to abort
*
* Ask the I2O controller to abort a command. This is an asynchrnous
* process and oru callback handler will see the command complete
* with an aborted message if it succeeds.
*
* Locks: no locks are held or needed
*/
int i2o_scsi_abort(Scsi_Cmnd * SCpnt) int i2o_scsi_abort(Scsi_Cmnd * SCpnt)
{ {
struct i2o_controller *c; struct i2o_controller *c;
...@@ -795,21 +894,24 @@ int i2o_scsi_abort(Scsi_Cmnd * SCpnt) ...@@ -795,21 +894,24 @@ int i2o_scsi_abort(Scsi_Cmnd * SCpnt)
u32 m; u32 m;
int tid; int tid;
printk("i2o_scsi: Aborting command block.\n"); printk(KERN_WARNING "i2o_scsi: Aborting command block.\n");
host = SCpnt->host; host = SCpnt->host;
hostdata = (struct i2o_scsi_host *)host->hostdata; hostdata = (struct i2o_scsi_host *)host->hostdata;
tid = hostdata->task[SCpnt->target][SCpnt->lun]; tid = hostdata->task[SCpnt->target][SCpnt->lun];
if(tid==-1) if(tid==-1)
{ {
printk(KERN_ERR "impossible command to abort.\n"); printk(KERN_ERR "i2o_scsi: Impossible command to abort!\n");
return SCSI_ABORT_NOT_RUNNING; return FAILED;
} }
c = hostdata->controller; c = hostdata->controller;
/* /*
* Obtain an I2O message. Right now we _have_ to obtain one * Obtain an I2O message. Right now we _have_ to obtain one
* until the scsi layer stuff is cleaned up. * until the scsi layer stuff is cleaned up.
*
* FIXME: we are in error context so we could sleep retry
* a bit and then bail in the improved scsi layer.
*/ */
do do
...@@ -828,10 +930,21 @@ int i2o_scsi_abort(Scsi_Cmnd * SCpnt) ...@@ -828,10 +930,21 @@ int i2o_scsi_abort(Scsi_Cmnd * SCpnt)
wmb(); wmb();
i2o_post_message(c,m); i2o_post_message(c,m);
wmb(); wmb();
return SCSI_ABORT_PENDING; return SUCCESS;
} }
static int i2o_scsi_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags) /**
* i2o_scsi_bus_reset - Issue a SCSI reset
* @SCpnt: the command that caused the reset
*
* Perform a SCSI bus reset operation. In I2O this is just a message
* we pass. I2O can do clever multi-initiator and shared reset stuff
* but we don't support this.
*
* Locks: called with no lock held, requires no locks.
*/
static int i2o_scsi_bus_reset(Scsi_Cmnd * SCpnt)
{ {
int tid; int tid;
struct i2o_controller *c; struct i2o_controller *c;
...@@ -844,7 +957,7 @@ static int i2o_scsi_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags) ...@@ -844,7 +957,7 @@ static int i2o_scsi_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags)
* Find the TID for the bus * Find the TID for the bus
*/ */
printk("i2o_scsi: Attempting to reset the bus.\n"); printk(KERN_WARNING "i2o_scsi: Attempting to reset the bus.\n");
host = SCpnt->host; host = SCpnt->host;
hostdata = (struct i2o_scsi_host *)host->hostdata; hostdata = (struct i2o_scsi_host *)host->hostdata;
...@@ -875,11 +988,43 @@ static int i2o_scsi_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags) ...@@ -875,11 +988,43 @@ static int i2o_scsi_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags)
__raw_writel(c->unit << 16 | tid, msg+12); __raw_writel(c->unit << 16 | tid, msg+12);
wmb(); wmb();
i2o_post_message(c,m); i2o_post_message(c,m);
return SCSI_RESET_PENDING; return SUCCESS;
} }
/* /**
* This is anyones guess quite frankly. * i2o_scsi_host_reset - host reset callback
* @SCpnt: command causing the reset
*
* An I2O controller can be many things at once. While we can
* reset a controller the potential mess from doing so is vast, and
* it's better to simply hold on and pray
*/
static int i2o_scsi_host_reset(Scsi_Cmnd * SCpnt)
{
return FAILED;
}
/**
* i2o_scsi_device_reset - device reset callback
* @SCpnt: command causing the reset
*
* I2O does not (AFAIK) support doing a device reset
*/
static int i2o_scsi_device_reset(Scsi_Cmnd * SCpnt)
{
return FAILED;
}
/**
* i2o_scsi_bios_param - Invent disk geometry
* @disk: device
* @dev: block layer device
* @ip: geometry array
*
* This is anyones guess quite frankly. We use the same rules everyone
* else appears to and hope. It seems to work.
*/ */
static int i2o_scsi_bios_param(Disk * disk, struct block_device *dev, int *ip) static int i2o_scsi_bios_param(Disk * disk, struct block_device *dev, int *ip)
......
#ifndef _I2O_SCSI_H #ifndef _I2O_SCSI_H
#define _I2O_SCSI_H #define _I2O_SCSI_H
#if !defined(LINUX_VERSION_CODE)
#include <linux/version.h>
#endif
#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
#include <linux/types.h> #include <linux/types.h>
#include <linux/kdev_t.h> #include <linux/kdev_t.h>
...@@ -19,28 +13,32 @@ static const char *i2o_scsi_info(struct Scsi_Host *); ...@@ -19,28 +13,32 @@ static const char *i2o_scsi_info(struct Scsi_Host *);
static int i2o_scsi_command(Scsi_Cmnd *); static int i2o_scsi_command(Scsi_Cmnd *);
static int i2o_scsi_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); static int i2o_scsi_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
static int i2o_scsi_abort(Scsi_Cmnd *); static int i2o_scsi_abort(Scsi_Cmnd *);
static int i2o_scsi_reset(Scsi_Cmnd *, unsigned int); static int i2o_scsi_bus_reset(Scsi_Cmnd *);
static int i2o_scsi_host_reset(Scsi_Cmnd *);
static int i2o_scsi_device_reset(Scsi_Cmnd *);
static int i2o_scsi_bios_param(Disk *, struct block_device *, int *); static int i2o_scsi_bios_param(Disk *, struct block_device *, int *);
static int i2o_scsi_release(struct Scsi_Host *host); static int i2o_scsi_release(struct Scsi_Host *host);
#define I2OSCSI { \ #define I2OSCSI { \
next: NULL, \ next: NULL, \
proc_name: "i2o_scsi", \ proc_name: "i2o_scsi", \
name: "I2O SCSI Layer", \ name: "I2O SCSI Layer", \
detect: i2o_scsi_detect, \ detect: i2o_scsi_detect, \
release: i2o_scsi_release, \ release: i2o_scsi_release, \
info: i2o_scsi_info, \ info: i2o_scsi_info, \
command: i2o_scsi_command, \ command: i2o_scsi_command, \
queuecommand: i2o_scsi_queuecommand, \ queuecommand: i2o_scsi_queuecommand, \
abort: i2o_scsi_abort, \ eh_abort_handler: i2o_scsi_abort, \
reset: i2o_scsi_reset, \ eh_bus_reset_handler: i2o_scsi_bus_reset, \
bios_param: i2o_scsi_bios_param, \ eh_device_reset_handler: i2o_scsi_device_reset, \
can_queue: I2O_SCSI_CAN_QUEUE, \ eh_host_reset_handler: i2o_scsi_host_reset, \
this_id: I2O_SCSI_ID, \ bios_param: i2o_scsi_bios_param, \
sg_tablesize: 8, \ can_queue: I2O_SCSI_CAN_QUEUE, \
cmd_per_lun: I2O_SCSI_CMD_PER_LUN, \ this_id: I2O_SCSI_ID, \
unchecked_isa_dma: 0, \ sg_tablesize: 8, \
use_clustering: ENABLE_CLUSTERING \ cmd_per_lun: I2O_SCSI_CMD_PER_LUN, \
unchecked_isa_dma: 0, \
use_clustering: ENABLE_CLUSTERING \
} }
#endif #endif
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