Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
75a97cd1
Commit
75a97cd1
authored
Oct 12, 2002
by
Alan Cox
Committed by
Linus Torvalds
Oct 12, 2002
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[PATCH] i2o-scsi next installment
parent
0b71bb7f
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
202 additions
and
59 deletions
+202
-59
drivers/message/i2o/i2o_scsi.c
drivers/message/i2o/i2o_scsi.c
+179
-34
drivers/message/i2o/i2o_scsi.h
drivers/message/i2o/i2o_scsi.h
+23
-25
No files found.
drivers/message/i2o/i2o_scsi.c
View file @
75a97cd1
...
...
@@ -9,10 +9,11 @@
* 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.
* For the avoidance of doubt the "preferred form" of this code is one which
* is in an open non patent encumbered format. Where cryptographic key signing
* forms part of the process of creating an executable the information
* including keys needed to generate an equivalently functional executable
* are deemed to be part of the source code.
*
* Complications for I2O scsi
*
...
...
@@ -61,7 +62,7 @@
#include "../../scsi/sd.h"
#include "i2o_scsi.h"
#define VERSION_STRING "Version 0.1.
0
"
#define VERSION_STRING "Version 0.1.
1
"
#define dprintk(x)
...
...
@@ -114,7 +115,10 @@ static chain_buf *sg_chain_pool = NULL;
static
int
sg_chain_tag
=
0
;
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
* 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
...
...
@@ -134,6 +138,13 @@ static void i2o_retry_run(unsigned long f)
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
)
{
int
i
;
...
...
@@ -150,6 +161,20 @@ static void flush_pending(void)
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
)
{
Scsi_Cmnd
*
current_command
;
...
...
@@ -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
((
"m[2]=%08X: "
,
m
[
2
]));
dprintk
((
"m[4]=%08X
\n
"
,
m
[
4
]));
if
(
m
[
2
]
&
0x80000000
)
{
if
(
m
[
2
]
&
0x40000000
)
...
...
@@ -236,7 +261,7 @@ static void i2o_scsi_reply(struct i2o_handler *h, struct i2o_controller *c, stru
lun_done
=
1
;
return
;
}
printk
(
KERN_
ERR
"i2o_scsi: bus reset reply
.
\n
"
);
printk
(
KERN_
INFO
"i2o_scsi: bus reset completed
.
\n
"
);
return
;
}
/*
...
...
@@ -313,6 +338,18 @@ struct i2o_handler i2o_scsi_handler=
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
)
{
u8
reply
[
8
];
...
...
@@ -331,6 +368,19 @@ static int i2o_find_lun(struct i2o_controller *c, struct i2o_device *d, int *tar
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
)
{
struct
i2o_device
*
unit
;
...
...
@@ -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
)
{
unsigned
long
flags
;
...
...
@@ -398,7 +458,7 @@ static int i2o_scsi_detect(Scsi_Host_Template * tpnt)
int
i
;
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
)
{
...
...
@@ -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
)
{
printk
(
"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: Unable to alloc %d byte SG chain buffer pool.
\n
"
,
SG_CHAIN_POOL_SZ
);
printk
(
KERN_INFO
"i2o_scsi: SG chaining DISABLED!
\n
"
);
sg_max_frags
=
11
;
}
else
{
printk
(
" 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
" chain_pool: %d bytes @ %p
\n
"
,
SG_CHAIN_POOL_SZ
,
sg_chain_pool
);
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_max_frags
=
SG_MAX_FRAGS
;
// 64
}
...
...
@@ -456,14 +516,11 @@ static int i2o_scsi_detect(Scsi_Host_Template * tpnt)
shpnt
=
scsi_register
(
tpnt
,
sizeof
(
struct
i2o_scsi_host
));
if
(
shpnt
==
NULL
)
continue
;
save_flags
(
flags
);
cli
();
shpnt
->
unique_id
=
(
u32
)
d
;
shpnt
->
io_port
=
0
;
shpnt
->
n_io_port
=
0
;
shpnt
->
irq
=
0
;
shpnt
->
this_id
=
/* Good question */
15
;
restore_flags
(
flags
);
i2o_scsi_init
(
c
,
d
,
shpnt
);
count
++
;
}
...
...
@@ -509,6 +566,20 @@ static const char *i2o_scsi_info(struct Scsi_Host *SChost)
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
*
))
{
int
i
;
...
...
@@ -525,6 +596,7 @@ static int i2o_scsi_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
u32
len
;
u32
reqlen
;
u32
tag
;
unsigned
long
flags
;
static
int
max_qd
=
1
;
...
...
@@ -560,24 +632,22 @@ static int i2o_scsi_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
if
(
tid
==
-
1
)
{
SCpnt
->
result
=
DID_NO_CONNECT
<<
16
;
spin_lock_irqsave
(
host
->
host_lock
,
flags
);
done
(
SCpnt
);
spin_unlock_irqrestore
(
host
->
host_lock
,
flags
);
return
0
;
}
dprintk
((
"Real scsi messages.
\n
"
));
/*
* Obtain an I2O message.
Right now we _have_ to obtain one
*
until the scsi layer stuff is cleaned up.
* Obtain an I2O message.
If there are none free then
*
throw it back to the scsi layer
*/
do
{
mb
();
m
=
le32_to_cpu
(
I2O_POST_READ32
(
c
));
}
while
(
m
==
0xFFFFFFFF
);
m
=
le32_to_cpu
(
I2O_POST_READ32
(
c
));
if
(
m
==
0xFFFFFFFF
)
return
1
;
msg
=
(
u32
*
)(
c
->
mem_offset
+
m
);
...
...
@@ -603,7 +673,11 @@ static int i2o_scsi_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
{
/* Unknown - kill the command */
SCpnt
->
result
=
DID_NO_CONNECT
<<
16
;
/* We must lock the request queue while completing */
spin_lock_irqsave
(
host
->
host_lock
,
flags
);
done
(
SCpnt
);
spin_unlock_irqrestore
(
host
->
host_lock
,
flags
);
return
0
;
}
...
...
@@ -772,11 +846,25 @@ static int i2o_scsi_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
return
0
;
}
/**
* internal_done - legacy scsi glue
* @SCPnt: command
*
* Completion function for a synchronous command
*/
static
void
internal_done
(
Scsi_Cmnd
*
SCpnt
)
{
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
)
{
i2o_scsi_queuecommand
(
SCpnt
,
internal_done
);
...
...
@@ -786,6 +874,17 @@ static int i2o_scsi_command(Scsi_Cmnd * SCpnt)
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
)
{
struct
i2o_controller
*
c
;
...
...
@@ -795,21 +894,24 @@ int i2o_scsi_abort(Scsi_Cmnd * SCpnt)
u32
m
;
int
tid
;
printk
(
"i2o_scsi: Aborting command block.
\n
"
);
printk
(
KERN_WARNING
"i2o_scsi: Aborting command block.
\n
"
);
host
=
SCpnt
->
host
;
hostdata
=
(
struct
i2o_scsi_host
*
)
host
->
hostdata
;
tid
=
hostdata
->
task
[
SCpnt
->
target
][
SCpnt
->
lun
];
if
(
tid
==-
1
)
{
printk
(
KERN_ERR
"i
mpossible command to abort.
\n
"
);
return
SCSI_ABORT_NOT_RUNNING
;
printk
(
KERN_ERR
"i
2o_scsi: Impossible command to abort!
\n
"
);
return
FAILED
;
}
c
=
hostdata
->
controller
;
/*
* Obtain an I2O message. Right now we _have_ to obtain one
* 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
...
...
@@ -828,10 +930,21 @@ int i2o_scsi_abort(Scsi_Cmnd * SCpnt)
wmb
();
i2o_post_message
(
c
,
m
);
wmb
();
return
S
CSI_ABORT_PENDING
;
return
S
UCCESS
;
}
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
;
struct
i2o_controller
*
c
;
...
...
@@ -844,7 +957,7 @@ static int i2o_scsi_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags)
* 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
;
hostdata
=
(
struct
i2o_scsi_host
*
)
host
->
hostdata
;
...
...
@@ -875,11 +988,43 @@ static int i2o_scsi_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags)
__raw_writel
(
c
->
unit
<<
16
|
tid
,
msg
+
12
);
wmb
();
i2o_post_message
(
c
,
m
);
return
S
CSI_RESET_PENDING
;
return
S
UCCESS
;
}
/*
* 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
)
...
...
drivers/message/i2o/i2o_scsi.h
View file @
75a97cd1
#ifndef _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/kdev_t.h>
...
...
@@ -19,28 +13,32 @@ static const char *i2o_scsi_info(struct Scsi_Host *);
static
int
i2o_scsi_command
(
Scsi_Cmnd
*
);
static
int
i2o_scsi_queuecommand
(
Scsi_Cmnd
*
,
void
(
*
done
)(
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_release
(
struct
Scsi_Host
*
host
);
#define I2OSCSI { \
next: NULL, \
proc_name: "i2o_scsi", \
name: "I2O SCSI Layer", \
detect: i2o_scsi_detect, \
release: i2o_scsi_release, \
info: i2o_scsi_info, \
command: i2o_scsi_command, \
queuecommand: i2o_scsi_queuecommand, \
abort: i2o_scsi_abort, \
reset: i2o_scsi_reset, \
bios_param: i2o_scsi_bios_param, \
can_queue: I2O_SCSI_CAN_QUEUE, \
this_id: I2O_SCSI_ID, \
sg_tablesize: 8, \
cmd_per_lun: I2O_SCSI_CMD_PER_LUN, \
unchecked_isa_dma: 0, \
use_clustering: ENABLE_CLUSTERING \
#define I2OSCSI { \
next: NULL, \
proc_name: "i2o_scsi", \
name: "I2O SCSI Layer", \
detect: i2o_scsi_detect, \
release: i2o_scsi_release, \
info: i2o_scsi_info, \
command: i2o_scsi_command, \
queuecommand: i2o_scsi_queuecommand, \
eh_abort_handler: i2o_scsi_abort, \
eh_bus_reset_handler: i2o_scsi_bus_reset, \
eh_device_reset_handler: i2o_scsi_device_reset, \
eh_host_reset_handler: i2o_scsi_host_reset, \
bios_param: i2o_scsi_bios_param, \
can_queue: I2O_SCSI_CAN_QUEUE, \
this_id: I2O_SCSI_ID, \
sg_tablesize: 8, \
cmd_per_lun: I2O_SCSI_CMD_PER_LUN, \
unchecked_isa_dma: 0, \
use_clustering: ENABLE_CLUSTERING \
}
#endif
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment