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
nexedi
linux
Commits
4af8adfb
Commit
4af8adfb
authored
Nov 21, 2002
by
Doug Ledford
Browse files
Options
Browse Files
Download
Plain Diff
Merge
ssh://linux-scsi.bkbits.net/scsi-misc-2.5
into flossy.devel.redhat.com:/usr/local/home/dledford/bk/linus-2.5
parents
71267d9b
4794bf02
Changes
14
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
305 additions
and
461 deletions
+305
-461
drivers/block/scsi_ioctl.c
drivers/block/scsi_ioctl.c
+3
-9
drivers/scsi/NCR53c406a.c
drivers/scsi/NCR53c406a.c
+0
-1
drivers/scsi/cpqfcTSinit.c
drivers/scsi/cpqfcTSinit.c
+1
-1
drivers/scsi/gdth.c
drivers/scsi/gdth.c
+2
-2
drivers/scsi/gdth_proc.c
drivers/scsi/gdth_proc.c
+2
-2
drivers/scsi/hosts.c
drivers/scsi/hosts.c
+46
-39
drivers/scsi/hosts.h
drivers/scsi/hosts.h
+1
-1
drivers/scsi/megaraid.h
drivers/scsi/megaraid.h
+0
-2
drivers/scsi/scsi.c
drivers/scsi/scsi.c
+96
-146
drivers/scsi/scsi.h
drivers/scsi/scsi.h
+7
-21
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_lib.c
+38
-74
drivers/scsi/scsi_proc.c
drivers/scsi/scsi_proc.c
+6
-67
drivers/scsi/scsi_scan.c
drivers/scsi/scsi_scan.c
+103
-95
drivers/scsi/scsi_syms.c
drivers/scsi/scsi_syms.c
+0
-1
No files found.
drivers/block/scsi_ioctl.c
View file @
4af8adfb
...
...
@@ -7,7 +7,7 @@
*
* 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.
*
...
...
@@ -16,26 +16,20 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-
*
*/
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/config.h>
#include <linux/swap.h>
#include <linux/init.h>
#include <linux/smp_lock.h>
#include <linux/module.h>
#include <linux/blk.h>
#include <linux/blk
dev
.h>
#include <linux/completion.h>
#include <linux/cdrom.h>
#include <linux/slab.h>
#include <linux/bio.h>
#include <asm/uaccess.h>
#include "../scsi/scsi.h"
#include <scsi/scsi.h>
#include <scsi/scsi_ioctl.h>
#include <asm/uaccess.h>
/* Command group 3 is reserved and should never be used. */
const
unsigned
char
scsi_command_size
[
8
]
=
...
...
drivers/scsi/NCR53c406a.c
View file @
4af8adfb
...
...
@@ -55,7 +55,6 @@
#include <linux/spinlock.h>
#include "scsi.h"
#include "hosts.h"
#include "NCR53c406a.h"
/* ============================================================= */
...
...
drivers/scsi/cpqfcTSinit.c
View file @
4af8adfb
...
...
@@ -1601,7 +1601,7 @@ return -ENOTSUPP;
scsi_cdb
[
0
]
=
RELEASE
;
// allocate with wait = true, interruptible = false
SCpnt
=
scsi_allocate_device
(
ScsiDev
,
1
,
0
);
SCpnt
=
scsi_allocate_device
(
ScsiDev
,
1
);
{
CPQFC_DECLARE_COMPLETION
(
wait
);
...
...
drivers/scsi/gdth.c
View file @
4af8adfb
...
...
@@ -4599,7 +4599,7 @@ static void gdth_flush(int hanum)
#if LINUX_VERSION_CODE >= 0x020322
sdev
=
scsi_get_host_dev
(
gdth_ctr_tab
[
hanum
]);
scp
=
scsi_allocate_device
(
sdev
,
1
,
FALSE
);
scp
=
scsi_allocate_device
(
sdev
,
1
);
scp
->
cmd_len
=
12
;
scp
->
use_sg
=
0
;
#else
...
...
@@ -4673,7 +4673,7 @@ void gdth_halt(void)
memset
(
cmnd
,
0xff
,
MAX_COMMAND_SIZE
);
#if LINUX_VERSION_CODE >= 0x020322
sdev
=
scsi_get_host_dev
(
gdth_ctr_tab
[
hanum
]);
scp
=
scsi_allocate_device
(
sdev
,
1
,
FALSE
);
scp
=
scsi_allocate_device
(
sdev
,
1
);
scp
->
cmd_len
=
12
;
scp
->
use_sg
=
0
;
#else
...
...
drivers/scsi/gdth_proc.c
View file @
4af8adfb
...
...
@@ -48,7 +48,7 @@ static int gdth_set_info(char *buffer,int length,int vh,int hanum,int busnum)
#if LINUX_VERSION_CODE >= 0x020322
sdev
=
scsi_get_host_dev
(
gdth_ctr_vtab
[
vh
]);
scp
=
scsi_allocate_device
(
sdev
,
1
,
FALSE
);
scp
=
scsi_allocate_device
(
sdev
,
1
);
if
(
!
scp
)
return
-
ENOMEM
;
scp
->
cmd_len
=
12
;
...
...
@@ -712,7 +712,7 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,
#if LINUX_VERSION_CODE >= 0x020322
sdev
=
scsi_get_host_dev
(
gdth_ctr_vtab
[
vh
]);
scp
=
scsi_allocate_device
(
sdev
,
1
,
FALSE
);
scp
=
scsi_allocate_device
(
sdev
,
1
);
if
(
!
scp
)
return
-
ENOMEM
;
scp
->
cmd_len
=
12
;
...
...
drivers/scsi/hosts.c
View file @
4af8adfb
...
...
@@ -208,6 +208,48 @@ static int scsi_remove_legacy_host(struct Scsi_Host *shost)
return
0
;
}
static
int
scsi_check_device_busy
(
struct
scsi_device
*
sdev
)
{
struct
Scsi_Host
*
shost
=
sdev
->
host
;
struct
scsi_cmnd
*
scmd
;
/*
* Loop over all of the commands associated with the
* device. If any of them are busy, then set the state
* back to inactive and bail.
*/
for
(
scmd
=
sdev
->
device_queue
;
scmd
;
scmd
=
scmd
->
next
)
{
if
(
scmd
->
request
&&
scmd
->
request
->
rq_status
!=
RQ_INACTIVE
)
goto
active
;
/*
* No, this device is really free. Mark it as such, and
* continue on.
*/
scmd
->
state
=
SCSI_STATE_DISCONNECTING
;
if
(
scmd
->
request
)
scmd
->
request
->
rq_status
=
RQ_SCSI_DISCONNECTING
;
}
return
0
;
active:
printk
(
KERN_ERR
"SCSI device not inactive - rq_status=%d, target=%d, "
"pid=%ld, state=%d, owner=%d.
\n
"
,
scmd
->
request
->
rq_status
,
scmd
->
target
,
scmd
->
pid
,
scmd
->
state
,
scmd
->
owner
);
for
(
sdev
=
shost
->
host_queue
;
sdev
;
sdev
=
sdev
->
next
)
{
for
(
scmd
=
sdev
->
device_queue
;
scmd
;
scmd
=
scmd
->
next
)
{
if
(
scmd
->
request
->
rq_status
==
RQ_SCSI_DISCONNECTING
)
scmd
->
request
->
rq_status
=
RQ_INACTIVE
;
}
}
printk
(
KERN_ERR
"Device busy???
\n
"
);
return
1
;
}
/**
* scsi_remove_host - check a scsi host for release and release
* @shost: a pointer to a scsi host to release
...
...
@@ -218,7 +260,6 @@ static int scsi_remove_legacy_host(struct Scsi_Host *shost)
int
scsi_remove_host
(
struct
Scsi_Host
*
shost
)
{
struct
scsi_device
*
sdev
;
struct
scsi_cmnd
*
scmd
;
/*
* FIXME Do ref counting. We force all of the devices offline to
...
...
@@ -228,43 +269,9 @@ int scsi_remove_host(struct Scsi_Host *shost)
for
(
sdev
=
shost
->
host_queue
;
sdev
;
sdev
=
sdev
->
next
)
sdev
->
online
=
FALSE
;
for
(
sdev
=
shost
->
host_queue
;
sdev
;
sdev
=
sdev
->
next
)
{
/*
* Loop over all of the commands associated with the
* device. If any of them are busy, then set the state
* back to inactive and bail.
*/
for
(
scmd
=
sdev
->
device_queue
;
scmd
;
scmd
=
scmd
->
next
)
{
if
(
scmd
->
request
&&
scmd
->
request
->
rq_status
!=
RQ_INACTIVE
)
{
printk
(
KERN_ERR
"SCSI device not inactive"
"- rq_status=%d, target=%d, pid=%ld,"
"state=%d, owner=%d.
\n
"
,
scmd
->
request
->
rq_status
,
scmd
->
target
,
scmd
->
pid
,
scmd
->
state
,
scmd
->
owner
);
for
(
sdev
=
shost
->
host_queue
;
sdev
;
sdev
=
sdev
->
next
)
{
for
(
scmd
=
sdev
->
device_queue
;
scmd
;
scmd
=
scmd
->
next
)
if
(
scmd
->
request
->
rq_status
==
RQ_SCSI_DISCONNECTING
)
scmd
->
request
->
rq_status
=
RQ_INACTIVE
;
}
printk
(
KERN_ERR
"Device busy???
\n
"
);
return
1
;
}
/*
* No, this device is really free. Mark it as such, and
* continue on.
*/
scmd
->
state
=
SCSI_STATE_DISCONNECTING
;
if
(
scmd
->
request
)
scmd
->
request
->
rq_status
=
RQ_SCSI_DISCONNECTING
;
/* Mark as
busy */
}
}
for
(
sdev
=
shost
->
host_queue
;
sdev
;
sdev
=
sdev
->
next
)
if
(
scsi_check_device_busy
(
sdev
))
return
1
;
/*
* Next we detach the high level drivers from the Scsi_Device
...
...
@@ -308,7 +315,7 @@ int scsi_add_host(struct Scsi_Host *shost)
sht
->
info
?
sht
->
info
(
shost
)
:
sht
->
name
);
device_register
(
&
shost
->
host_driverfs_dev
);
sc
an_scsis
(
shost
,
0
,
0
,
0
,
0
);
sc
si_scan_host
(
shost
);
for
(
sdev
=
shost
->
host_queue
;
sdev
;
sdev
=
sdev
->
next
)
{
if
(
sdev
->
host
->
hostt
!=
sht
)
...
...
drivers/scsi/hosts.h
View file @
4af8adfb
...
...
@@ -519,7 +519,7 @@ static inline void scsi_set_pci_device(struct Scsi_Host *shost,
/*
* Prototypes for functions/data in scsi_scan.c
*/
extern
void
sc
an_scsis
(
struct
Scsi_Host
*
,
uint
,
uint
,
uint
,
uint
);
extern
void
sc
si_scan_host
(
struct
Scsi_Host
*
);
struct
Scsi_Device_Template
{
...
...
drivers/scsi/megaraid.h
View file @
4af8adfb
...
...
@@ -974,13 +974,11 @@ static void mega_build_kernel_sg (char *barea, ulong xfersize, mega_scb * pScb,
mega_ioctl_mbox
*
mbox
);
#endif
static
int
megadev_open
(
struct
inode
*
,
struct
file
*
);
static
int
megadev_ioctl_entry
(
struct
inode
*
,
struct
file
*
,
unsigned
int
,
unsigned
long
);
static
int
megadev_ioctl
(
struct
inode
*
,
struct
file
*
,
unsigned
int
,
unsigned
long
);
static
mega_scb
*
megadev_doioctl
(
mega_host_config
*
,
Scsi_Cmnd
*
);
static
int
megadev_close
(
struct
inode
*
,
struct
file
*
);
static
void
megadev_ioctl_done
(
Scsi_Cmnd
*
);
static
int
mega_init_scb
(
mega_host_config
*
);
static
void
enq_scb_freelist
(
mega_host_config
*
,
mega_scb
*
,
...
...
drivers/scsi/scsi.c
View file @
4af8adfb
...
...
@@ -346,6 +346,41 @@ void scsi_release_request(Scsi_Request * req)
kfree
(
req
);
}
/*
* FIXME(eric) - this is not at all optimal. Given that
* single lun devices are rare and usually slow
* (i.e. CD changers), this is good enough for now, but
* we may want to come back and optimize this later.
*
* Scan through all of the devices attached to this
* host, and see if any are active or not. If so,
* we need to defer this command.
*
* We really need a busy counter per device. This would
* allow us to more easily figure out whether we should
* do anything here or not.
*/
static
int
check_all_luns
(
struct
Scsi_Host
*
shost
,
struct
scsi_device
*
myself
)
{
struct
scsi_device
*
sdev
;
for
(
sdev
=
shost
->
host_queue
;
sdev
;
sdev
=
sdev
->
next
)
{
/*
* Only look for other devices on the same bus
* with the same target ID.
*/
if
(
sdev
->
channel
!=
myself
->
channel
||
sdev
->
id
!=
myself
->
id
)
continue
;
if
(
sdev
==
myself
)
continue
;
if
(
atomic_read
(
&
sdev
->
device_active
))
return
1
;
}
return
0
;
}
/*
* Function: scsi_allocate_device
*
...
...
@@ -372,172 +407,87 @@ void scsi_release_request(Scsi_Request * req)
* This function is deprecated, and drivers should be
* rewritten to use Scsi_Request instead of Scsi_Cmnd.
*/
Scsi_Cmnd
*
scsi_allocate_device
(
Scsi_Device
*
device
,
int
wait
,
int
interruptable
)
struct
scsi_cmnd
*
scsi_allocate_device
(
struct
scsi_device
*
sdev
,
int
wait
)
{
struct
Scsi_Host
*
host
;
Scsi_Cmnd
*
SCpnt
=
NULL
;
Scsi_Device
*
SDpnt
;
DECLARE_WAITQUEUE
(
wq
,
current
)
;
struct
Scsi_Host
*
shost
=
sdev
->
host
;
struct
scsi_cmnd
*
scmnd
;
unsigned
long
flags
;
if
(
!
device
)
panic
(
"No device passed to scsi_allocate_device().
\n
"
);
host
=
device
->
host
;
spin_lock_irqsave
(
&
device_request_lock
,
flags
);
while
(
1
==
1
)
{
SCpnt
=
NULL
;
if
(
!
device
->
device_blocked
)
{
if
(
device
->
single_lun
)
{
/*
* FIXME(eric) - this is not at all optimal. Given that
* single lun devices are rare and usually slow
* (i.e. CD changers), this is good enough for now, but
* we may want to come back and optimize this later.
*
* Scan through all of the devices attached to this
* host, and see if any are active or not. If so,
* we need to defer this command.
*
* We really need a busy counter per device. This would
* allow us to more easily figure out whether we should
* do anything here or not.
*/
for
(
SDpnt
=
host
->
host_queue
;
SDpnt
;
SDpnt
=
SDpnt
->
next
)
{
/*
* Only look for other devices on the same bus
* with the same target ID.
*/
if
(
SDpnt
->
channel
!=
device
->
channel
||
SDpnt
->
id
!=
device
->
id
||
SDpnt
==
device
)
{
continue
;
}
if
(
atomic_read
(
&
SDpnt
->
device_active
)
!=
0
)
{
break
;
}
}
if
(
SDpnt
)
{
/*
* Some other device in this cluster is busy.
* If asked to wait, we need to wait, otherwise
* return NULL.
*/
SCpnt
=
NULL
;
goto
busy
;
}
}
/*
* Now we can check for a free command block for this device.
*/
for
(
SCpnt
=
device
->
device_queue
;
SCpnt
;
SCpnt
=
SCpnt
->
next
)
{
if
(
SCpnt
->
request
==
NULL
)
break
;
}
}
while
(
1
)
{
if
(
sdev
->
device_blocked
)
goto
busy
;
if
(
sdev
->
single_lun
&&
check_all_luns
(
shost
,
sdev
))
goto
busy
;
/*
* If we couldn't find a free command block, and we have been
* asked to wait, then do so.
* Now we can check for a free command block for this device.
*/
if
(
SCpnt
)
{
break
;
}
busy:
for
(
scmnd
=
sdev
->
device_queue
;
scmnd
;
scmnd
=
scmnd
->
next
)
if
(
!
scmnd
->
request
)
goto
found
;
busy:
if
(
!
wait
)
goto
fail
;
/*
* If we have been asked to wait for a free block, then
* wait here.
* We need to wait for a free commandblock. We need to
* insert ourselves into the list before we release the
* lock. This way if a block were released the same
* microsecond that we released the lock, the call
* to schedule() wouldn't block (well, it might switch,
* but the current task will still be schedulable.
*/
if
(
wait
)
{
DECLARE_WAITQUEUE
(
wait
,
current
);
/*
* We need to wait for a free commandblock. We need to
* insert ourselves into the list before we release the
* lock. This way if a block were released the same
* microsecond that we released the lock, the call
* to schedule() wouldn't block (well, it might switch,
* but the current task will still be schedulable.
*/
add_wait_queue
(
&
device
->
scpnt_wait
,
&
wait
);
if
(
interruptable
)
{
set_current_state
(
TASK_INTERRUPTIBLE
);
}
else
{
set_current_state
(
TASK_UNINTERRUPTIBLE
);
}
spin_unlock_irqrestore
(
&
device_request_lock
,
flags
);
/*
* This should block until a device command block
* becomes available.
*/
schedule
();
add_wait_queue
(
&
sdev
->
scpnt_wait
,
&
wq
);
set_current_state
(
TASK_UNINTERRUPTIBLE
);
spin_lock_irqsave
(
&
device_request_lock
,
flags
);
spin_unlock_irqrestore
(
&
device_request_lock
,
flags
);
schedule
();
spin_lock_irqsave
(
&
device_request_lock
,
flags
);
remove_wait_queue
(
&
device
->
scpnt_wait
,
&
wait
);
/*
* FIXME - Isn't this redundant?? Someone
* else will have forced the state back to running.
*/
set_current_state
(
TASK_RUNNING
);
/*
* In the event that a signal has arrived that we need
* to consider, then simply return NULL. Everyone
* that calls us should be prepared for this
* possibility, and pass the appropriate code back
* to the user.
*/
if
(
interruptable
)
{
if
(
signal_pending
(
current
))
{
spin_unlock_irqrestore
(
&
device_request_lock
,
flags
);
return
NULL
;
}
}
}
else
{
spin_unlock_irqrestore
(
&
device_request_lock
,
flags
);
return
NULL
;
}
remove_wait_queue
(
&
sdev
->
scpnt_wait
,
&
wq
);
set_current_state
(
TASK_RUNNING
);
}
SCpnt
->
request
=
NULL
;
atomic_inc
(
&
SCpnt
->
host
->
host_active
);
atomic_inc
(
&
SCpnt
->
device
->
device_active
);
found:
scmnd
->
request
=
NULL
;
atomic_inc
(
&
scmnd
->
host
->
host_active
);
atomic_inc
(
&
scmnd
->
device
->
device_active
);
SCpnt
->
buffer
=
NULL
;
SCpnt
->
bufflen
=
0
;
SCpnt
->
request_buffer
=
NULL
;
SCpnt
->
request_bufflen
=
0
;
scmnd
->
buffer
=
NULL
;
scmnd
->
bufflen
=
0
;
scmnd
->
request_buffer
=
NULL
;
scmnd
->
request_bufflen
=
0
;
SCpnt
->
use_sg
=
0
;
/* Reset the scatter-gather flag */
SCpnt
->
old_use_sg
=
0
;
SCpnt
->
transfersize
=
0
;
/* No default transfer size */
SCpnt
->
cmd_len
=
0
;
scmnd
->
use_sg
=
0
;
/* Reset the scatter-gather flag */
scmnd
->
old_use_sg
=
0
;
scmnd
->
transfersize
=
0
;
/* No default transfer size */
scmnd
->
cmd_len
=
0
;
SCpnt
->
sc_data_direction
=
SCSI_DATA_UNKNOWN
;
SCpnt
->
sc_request
=
NULL
;
SCpnt
->
sc_magic
=
SCSI_CMND_MAGIC
;
scmnd
->
sc_data_direction
=
SCSI_DATA_UNKNOWN
;
scmnd
->
sc_request
=
NULL
;
scmnd
->
sc_magic
=
SCSI_CMND_MAGIC
;
SCpnt
->
result
=
0
;
SCpnt
->
underflow
=
0
;
/* Do not flag underflow conditions */
SCpnt
->
old_underflow
=
0
;
SCpnt
->
resid
=
0
;
SCpnt
->
state
=
SCSI_STATE_INITIALIZING
;
SCpnt
->
owner
=
SCSI_OWNER_HIGHLEVEL
;
scmnd
->
result
=
0
;
scmnd
->
underflow
=
0
;
/* Do not flag underflow conditions */
scmnd
->
old_underflow
=
0
;
scmnd
->
resid
=
0
;
scmnd
->
state
=
SCSI_STATE_INITIALIZING
;
scmnd
->
owner
=
SCSI_OWNER_HIGHLEVEL
;
spin_unlock_irqrestore
(
&
device_request_lock
,
flags
);
SCSI_LOG_MLQUEUE
(
5
,
printk
(
"Activating command for device %d (%d)
\n
"
,
SCpnt
->
target
,
atomic_read
(
&
SCpnt
->
host
->
host_active
)));
scmnd
->
target
,
atomic_read
(
&
scmnd
->
host
->
host_active
)));
return
scmnd
;
return
SCpnt
;
fail:
spin_unlock_irqrestore
(
&
device_request_lock
,
flags
);
return
NULL
;
}
inline
void
__scsi_release_command
(
Scsi_Cmnd
*
SCpnt
)
...
...
drivers/scsi/scsi.h
View file @
4af8adfb
...
...
@@ -15,23 +15,10 @@
#ifndef _SCSI_H
#define _SCSI_H
#include <linux/config.h>
/* for CONFIG_SCSI_LOGGING */
#include <linux/devfs_fs_kernel.h>
#include <linux/proc_fs.h>
#include <linux/init.h>
/*
* Some of the public constants are being moved to this file.
* We include it here so that what came from where is transparent.
*/
#include <linux/config.h>
/* for CONFIG_SCSI_LOGGING */
#include <linux/devfs_fs_kernel.h>
/* some morons don't know struct pointers */
#include <scsi/scsi.h>
#include <linux/random.h>
#include <asm/hardirq.h>
#include <asm/scatterlist.h>
#include <asm/io.h>
/*
* These are the values that the SCpnt->sc_data_direction and
...
...
@@ -396,6 +383,7 @@ extern const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE];
* Forward-declaration of structs for prototypes.
*/
struct
Scsi_Host
;
struct
scatterlist
;
/*
* Add some typedefs so that we can prototyope a bunch of the functions.
...
...
@@ -445,10 +433,6 @@ void scsi_free_sgtable(struct scatterlist *sgl, int index);
* Prototypes for functions in scsi_lib.c
*/
extern
int
scsi_maybe_unblock_host
(
Scsi_Device
*
SDpnt
);
extern
Scsi_Cmnd
*
scsi_end_request
(
Scsi_Cmnd
*
SCpnt
,
int
uptodate
,
int
sectors
);
extern
struct
Scsi_Device_Template
*
scsi_get_request_dev
(
struct
request
*
);
extern
int
scsi_init_cmd_errh
(
Scsi_Cmnd
*
SCpnt
);
extern
void
scsi_setup_cmd_retry
(
Scsi_Cmnd
*
SCpnt
);
extern
int
scsi_insert_special_cmd
(
Scsi_Cmnd
*
SCpnt
,
int
);
extern
void
scsi_io_completion
(
Scsi_Cmnd
*
SCpnt
,
int
good_sectors
,
...
...
@@ -471,7 +455,7 @@ extern void scsi_slave_detach(struct scsi_device *sdev);
extern
void
scsi_done
(
Scsi_Cmnd
*
SCpnt
);
extern
void
scsi_finish_command
(
Scsi_Cmnd
*
);
extern
int
scsi_retry_command
(
Scsi_Cmnd
*
);
extern
Scsi_Cmnd
*
scsi_allocate_device
(
Scsi_Device
*
,
int
,
int
);
extern
Scsi_Cmnd
*
scsi_allocate_device
(
Scsi_Device
*
,
int
);
extern
void
__scsi_release_command
(
Scsi_Cmnd
*
);
extern
void
scsi_release_command
(
Scsi_Cmnd
*
);
extern
void
scsi_do_cmd
(
Scsi_Cmnd
*
,
const
void
*
cmnd
,
...
...
@@ -525,6 +509,8 @@ static inline void scsi_proc_host_rm(struct Scsi_Host *);
extern
struct
scsi_device
*
scsi_alloc_sdev
(
struct
Scsi_Host
*
,
uint
,
uint
,
uint
);
extern
void
scsi_free_sdev
(
struct
scsi_device
*
);
extern
int
scsi_add_single_device
(
uint
,
uint
,
uint
,
uint
);
extern
int
scsi_remove_single_device
(
uint
,
uint
,
uint
,
uint
);
/*
* Prototypes for functions in constants.c
...
...
@@ -551,7 +537,7 @@ struct dev_info {
unsigned
flags
;
};
extern
struct
dev_info
scsi_static_device_list
[]
__initdata
;
extern
struct
dev_info
scsi_static_device_list
[];
/*
* scsi_dev_info_list: structure to hold black/white listed devices.
...
...
drivers/scsi/scsi_lib.c
View file @
4af8adfb
...
...
@@ -95,7 +95,7 @@ int scsi_insert_special_req(Scsi_Request * SRpnt, int at_head)
* fields related to error handling. Typically this will
* be called once for each command, as required.
*/
int
scsi_init_cmd_errh
(
Scsi_Cmnd
*
SCpnt
)
static
int
scsi_init_cmd_errh
(
Scsi_Cmnd
*
SCpnt
)
{
SCpnt
->
owner
=
SCSI_OWNER_MIDLEVEL
;
SCpnt
->
reset_chain
=
NULL
;
...
...
@@ -306,11 +306,10 @@ void scsi_queue_next_request(request_queue_t * q, Scsi_Cmnd * SCpnt)
* We are guaranteeing that the request queue will be goosed
* at some point during this call.
*/
static
Scsi_Cmnd
*
__
scsi_end_request
(
Scsi_Cmnd
*
SCpnt
,
static
Scsi_Cmnd
*
scsi_end_request
(
Scsi_Cmnd
*
SCpnt
,
int
uptodate
,
int
sectors
,
int
requeue
,
int
frequeue
)
int
requeue
)
{
request_queue_t
*
q
=
&
SCpnt
->
device
->
request_queue
;
struct
request
*
req
=
SCpnt
->
request
;
...
...
@@ -337,12 +336,9 @@ static Scsi_Cmnd *__scsi_end_request(Scsi_Cmnd * SCpnt,
add_disk_randomness
(
req
->
rq_disk
);
spin_lock_irqsave
(
q
->
queue_lock
,
flags
);
if
(
blk_rq_tagged
(
req
))
blk_queue_end_tag
(
q
,
req
);
end_that_request_last
(
req
);
spin_unlock_irqrestore
(
q
->
queue_lock
,
flags
);
/*
...
...
@@ -350,38 +346,10 @@ static Scsi_Cmnd *__scsi_end_request(Scsi_Cmnd * SCpnt,
* need to worry about launching another command.
*/
__scsi_release_command
(
SCpnt
);
if
(
frequeue
)
scsi_queue_next_request
(
q
,
NULL
);
scsi_queue_next_request
(
q
,
NULL
);
return
NULL
;
}
/*
* Function: scsi_end_request()
*
* Purpose: Post-processing of completed commands called from interrupt
* handler or a bottom-half handler.
*
* Arguments: SCpnt - command that is complete.
* uptodate - 1 if I/O indicates success, 0 for I/O error.
* sectors - number of sectors we want to mark.
*
* Lock status: Assumed that lock is not held upon entry.
*
* Returns: Nothing
*
* Notes: This is called for block device requests in order to
* mark some number of sectors as complete.
*
* We are guaranteeing that the request queue will be goosed
* at some point during this call.
*/
Scsi_Cmnd
*
scsi_end_request
(
Scsi_Cmnd
*
SCpnt
,
int
uptodate
,
int
sectors
)
{
return
__scsi_end_request
(
SCpnt
,
uptodate
,
sectors
,
1
,
1
);
}
/*
* Function: scsi_release_buffers()
*
...
...
@@ -428,6 +396,29 @@ static void scsi_release_buffers(Scsi_Cmnd * SCpnt)
SCpnt
->
request_bufflen
=
0
;
}
/*
* Function: scsi_get_request_dev()
*
* Purpose: Find the upper-level driver that is responsible for this
* request
*
* Arguments: request - I/O request we are preparing to queue.
*
* Lock status: No locks assumed to be held, but as it happens the
* q->queue_lock is held when this is called.
*
* Returns: Nothing
*
* Notes: The requests in the request queue may have originated
* from any block device driver. We need to find out which
* one so that we can later form the appropriate command.
*/
static
struct
Scsi_Device_Template
*
scsi_get_request_dev
(
struct
request
*
req
)
{
struct
gendisk
*
p
=
req
->
rq_disk
;
return
p
?
*
(
struct
Scsi_Device_Template
**
)
p
->
private_data
:
NULL
;
}
/*
* Function: scsi_io_completion()
*
...
...
@@ -527,11 +518,7 @@ void scsi_io_completion(Scsi_Cmnd * SCpnt, int good_sectors,
* requeueing right here - we will requeue down below
* when we handle the bad sectors.
*/
SCpnt
=
__scsi_end_request
(
SCpnt
,
1
,
good_sectors
,
result
==
0
,
1
);
SCpnt
=
scsi_end_request
(
SCpnt
,
1
,
good_sectors
,
result
==
0
);
/*
* If the command completed without error, then either finish off the
...
...
@@ -574,7 +561,8 @@ void scsi_io_completion(Scsi_Cmnd * SCpnt, int good_sectors,
* and quietly refuse further access.
*/
SCpnt
->
device
->
changed
=
1
;
SCpnt
=
scsi_end_request
(
SCpnt
,
0
,
this_count
);
SCpnt
=
scsi_end_request
(
SCpnt
,
0
,
this_count
,
1
);
return
;
}
else
{
/*
...
...
@@ -606,14 +594,14 @@ void scsi_io_completion(Scsi_Cmnd * SCpnt, int good_sectors,
scsi_queue_next_request
(
q
,
SCpnt
);
result
=
0
;
}
else
{
SCpnt
=
scsi_end_request
(
SCpnt
,
0
,
this_count
);
SCpnt
=
scsi_end_request
(
SCpnt
,
0
,
this_count
,
1
);
return
;
}
break
;
case
NOT_READY
:
printk
(
KERN_INFO
"Device %s not ready.
\n
"
,
req
->
rq_disk
?
req
->
rq_disk
->
disk_name
:
""
);
SCpnt
=
scsi_end_request
(
SCpnt
,
0
,
this_count
);
SCpnt
=
scsi_end_request
(
SCpnt
,
0
,
this_count
,
1
);
return
;
break
;
case
MEDIUM_ERROR
:
...
...
@@ -623,7 +611,7 @@ void scsi_io_completion(Scsi_Cmnd * SCpnt, int good_sectors,
(
int
)
SCpnt
->
target
,
(
int
)
SCpnt
->
lun
);
print_command
(
SCpnt
->
data_cmnd
);
print_sense
(
"sd"
,
SCpnt
);
SCpnt
=
scsi_end_request
(
SCpnt
,
0
,
block_sectors
);
SCpnt
=
scsi_end_request
(
SCpnt
,
0
,
block_sectors
,
1
);
return
;
default:
break
;
...
...
@@ -656,34 +644,11 @@ void scsi_io_completion(Scsi_Cmnd * SCpnt, int good_sectors,
* We sometimes get this cruft in the event that a medium error
* isn't properly reported.
*/
SCpnt
=
scsi_end_request
(
SCpnt
,
0
,
req
->
current_nr_sectors
);
SCpnt
=
scsi_end_request
(
SCpnt
,
0
,
req
->
current_nr_sectors
,
1
);
return
;
}
}
/*
* Function: scsi_get_request_dev()
*
* Purpose: Find the upper-level driver that is responsible for this
* request
*
* Arguments: request - I/O request we are preparing to queue.
*
* Lock status: No locks assumed to be held, but as it happens the
* q->queue_lock is held when this is called.
*
* Returns: Nothing
*
* Notes: The requests in the request queue may have originated
* from any block device driver. We need to find out which
* one so that we can later form the appropriate command.
*/
struct
Scsi_Device_Template
*
scsi_get_request_dev
(
struct
request
*
req
)
{
struct
gendisk
*
p
=
req
->
rq_disk
;
return
p
?
*
(
struct
Scsi_Device_Template
**
)
p
->
private_data
:
NULL
;
}
/*
* Function: scsi_init_io()
*
...
...
@@ -763,7 +728,7 @@ static int scsi_init_io(Scsi_Cmnd *SCpnt)
/*
* kill it. there should be no leftover blocks in this request
*/
SCpnt
=
scsi_end_request
(
SCpnt
,
0
,
req
->
nr_sectors
);
SCpnt
=
scsi_end_request
(
SCpnt
,
0
,
req
->
nr_sectors
,
1
);
BUG_ON
(
SCpnt
);
ret
=
BLKPREP_KILL
;
out:
...
...
@@ -797,8 +762,7 @@ int scsi_prep_fn(struct request_queue *q, struct request *req)
SRpnt
=
(
Scsi_Request
*
)
req
->
special
;
if
(
SRpnt
->
sr_magic
==
SCSI_REQ_MAGIC
)
{
SCpnt
=
scsi_allocate_device
(
SRpnt
->
sr_device
,
FALSE
,
FALSE
);
SCpnt
=
scsi_allocate_device
(
SRpnt
->
sr_device
,
0
);
if
(
!
SCpnt
)
return
BLKPREP_DEFER
;
scsi_init_cmd_from_req
(
SCpnt
,
SRpnt
);
...
...
@@ -809,9 +773,9 @@ int scsi_prep_fn(struct request_queue *q, struct request *req)
* Now try and find a command block that we can use.
*/
if
(
req
->
special
)
{
SCpnt
=
(
Scsi_Cmnd
*
)
req
->
special
;
SCpnt
=
(
Scsi_Cmnd
*
)
req
->
special
;
}
else
{
SCpnt
=
scsi_allocate_device
(
SDpnt
,
FALSE
,
FALSE
);
SCpnt
=
scsi_allocate_device
(
SDpnt
,
0
);
}
/*
* if command allocation failure, wait a bit
...
...
drivers/scsi/scsi_proc.c
View file @
4af8adfb
...
...
@@ -399,11 +399,8 @@ static void scsi_dump_status(int level)
static
int
proc_scsi_gen_write
(
struct
file
*
file
,
const
char
*
buf
,
unsigned
long
length
,
void
*
data
)
{
Scsi_Device
*
sdev
;
struct
Scsi_Host
*
shost
;
char
*
p
;
int
host
,
channel
,
id
,
lun
;
char
*
buffer
;
char
*
buffer
,
*
p
;
int
err
;
if
(
!
buf
||
length
>
PAGE_SIZE
)
...
...
@@ -529,35 +526,9 @@ static int proc_scsi_gen_write(struct file * file, const char * buf,
id
=
simple_strtoul
(
p
+
1
,
&
p
,
0
);
lun
=
simple_strtoul
(
p
+
1
,
&
p
,
0
);
printk
(
KERN_INFO
"scsi singledevice %d %d %d %d
\n
"
,
host
,
channel
,
id
,
lun
);
for
(
shost
=
scsi_host_get_next
(
NULL
);
shost
;
shost
=
scsi_host_get_next
(
shost
))
{
if
(
shost
->
host_no
==
host
)
{
break
;
}
}
err
=
-
ENXIO
;
if
(
!
shost
)
goto
out
;
for
(
sdev
=
shost
->
host_queue
;
sdev
;
sdev
=
sdev
->
next
)
{
if
((
sdev
->
channel
==
channel
&&
sdev
->
id
==
id
&&
sdev
->
lun
==
lun
))
{
break
;
}
}
err
=
-
ENOSYS
;
if
(
sdev
)
goto
out
;
/* We do not yet support unplugging */
scan_scsis
(
shost
,
1
,
channel
,
id
,
lun
);
err
=
length
;
goto
out
;
}
err
=
scsi_add_single_device
(
host
,
channel
,
id
,
lun
);
if
(
err
>=
0
)
err
=
length
;
/*
* Usage: echo "scsi remove-single-device 0 1 2 3" >/proc/scsi/scsi
* with "0 1 2 3" replaced by your "Host Channel Id Lun".
...
...
@@ -569,7 +540,7 @@ static int proc_scsi_gen_write(struct file * file, const char * buf,
* hardware and thoroughly confuse the SCSI subsystem.
*
*/
else
if
(
!
strncmp
(
"remove-single-device"
,
buffer
+
5
,
20
))
{
}
else
if
(
!
strncmp
(
"remove-single-device"
,
buffer
+
5
,
20
))
{
p
=
buffer
+
26
;
host
=
simple_strtoul
(
p
,
&
p
,
0
);
...
...
@@ -577,39 +548,7 @@ static int proc_scsi_gen_write(struct file * file, const char * buf,
id
=
simple_strtoul
(
p
+
1
,
&
p
,
0
);
lun
=
simple_strtoul
(
p
+
1
,
&
p
,
0
);
for
(
shost
=
scsi_host_get_next
(
NULL
);
shost
;
shost
=
scsi_host_get_next
(
shost
))
{
if
(
shost
->
host_no
==
host
)
{
break
;
}
}
err
=
-
ENODEV
;
if
(
!
shost
)
goto
out
;
for
(
sdev
=
shost
->
host_queue
;
sdev
;
sdev
=
sdev
->
next
)
{
if
((
sdev
->
channel
==
channel
&&
sdev
->
id
==
id
&&
sdev
->
lun
==
lun
))
{
break
;
}
}
if
(
sdev
==
NULL
)
goto
out
;
/* there is no such device attached */
err
=
-
EBUSY
;
if
(
sdev
->
access_count
)
goto
out
;
scsi_detach_device
(
sdev
);
if
(
sdev
->
attached
==
0
)
{
devfs_unregister
(
sdev
->
de
);
scsi_free_sdev
(
sdev
);
err
=
0
;
}
err
=
scsi_remove_single_device
(
host
,
channel
,
id
,
lun
);
}
out:
...
...
drivers/scsi/scsi_scan.c
View file @
4af8adfb
...
...
@@ -1862,6 +1862,69 @@ static int scsi_report_lun_scan(Scsi_Device *sdevscan)
}
int
scsi_add_single_device
(
uint
host
,
uint
channel
,
uint
id
,
uint
lun
)
{
struct
scsi_device
*
sdevscan
,
*
sdev
;
struct
Scsi_Host
*
shost
;
int
error
=
-
ENODEV
;
shost
=
scsi_host_hn_get
(
host
);
if
(
!
shost
)
return
-
ENODEV
;
sdev
=
scsi_find_device
(
shost
,
channel
,
id
,
lun
);
if
(
!
sdev
)
goto
out
;
error
=
-
ENOMEM
;
sdevscan
=
scsi_alloc_sdev
(
shost
,
channel
,
id
,
lun
);
if
(
!
sdevscan
)
goto
out
;
sdevscan
->
scsi_level
=
scsi_find_scsi_level
(
channel
,
id
,
shost
);
error
=
scsi_probe_and_add_lun
(
sdevscan
,
&
sdev
,
NULL
);
scsi_free_sdev
(
sdevscan
);
error
=
-
ENODEV
;
if
(
error
!=
SCSI_SCAN_LUN_PRESENT
)
goto
out
;
scsi_attach_device
(
sdev
);
error
=
0
;
out:
scsi_host_put
(
shost
);
return
error
;
}
int
scsi_remove_single_device
(
uint
host
,
uint
channel
,
uint
id
,
uint
lun
)
{
struct
scsi_device
*
sdev
;
struct
Scsi_Host
*
shost
;
int
error
=
-
ENODEV
;
shost
=
scsi_host_hn_get
(
host
);
if
(
!
shost
)
return
-
ENODEV
;
sdev
=
scsi_find_device
(
shost
,
channel
,
id
,
lun
);
if
(
!
sdev
)
goto
out
;
error
=
-
EBUSY
;
if
(
sdev
->
access_count
)
goto
out
;
scsi_detach_device
(
sdev
);
if
(
sdev
->
attached
)
goto
out
;
devfs_unregister
(
sdev
->
de
);
scsi_free_sdev
(
sdev
);
error
=
0
;
out:
scsi_host_put
(
shost
);
return
error
;
}
/**
* scsi_scan_target - scan a target id, possibly including all LUNs on the
* target.
...
...
@@ -1927,111 +1990,56 @@ static void scsi_scan_target(Scsi_Device *sdevscan, struct Scsi_Host *shost,
}
/**
* scsi_scan_selected_lun - probe and add one LUN
* scsi_scan_host - scan the given adapter
* @shost: adapter to scan
*
* Description:
* Probe a single LUN on @shost, @channel, @id and @lun. If the LUN is
* found, set the queue depth, allocate command blocks, and call
* init/attach/finish of the upper level (sd, sg, etc.) drivers.
* Iterate and call scsi_scan_target to scan all possible target id's
* on all possible channels.
**/
static
void
scsi_scan_selected_lun
(
struct
Scsi_Host
*
shost
,
uint
channel
,
uint
id
,
uint
lun
)
void
scsi_scan_host
(
struct
Scsi_Host
*
shost
)
{
Scsi_Device
*
sdevscan
,
*
sdev
=
NULL
;
int
res
;
struct
scsi_device
*
sdevscan
;
uint
channel
,
id
,
order_id
;
if
((
channel
>
shost
->
max_channel
)
||
(
id
>=
shost
->
max_id
)
||
(
lun
>=
shost
->
max_lun
))
return
;
sdevscan
=
scsi_alloc_sdev
(
shost
,
channel
,
id
,
lun
);
/*
* The blk layer queue allocation is a bit expensive to
* repeat for each channel and id - for FCP max_id is near
* 255: each call to scsi_alloc_sdev() implies a call to
* blk_init_queue, and then blk_init_free_list, where 2 *
* queue_nr_requests requests are allocated. Don't do so
* here for scsi_scan_selected_lun, since we end up
* calling select_queue_depths with an extra Scsi_Device
* on the host_queue list.
*/
sdevscan
=
scsi_alloc_sdev
(
shost
,
0
,
0
,
0
);
if
(
sdevscan
==
NULL
)
return
;
sdevscan
->
scsi_level
=
scsi_find_scsi_level
(
channel
,
id
,
shost
);
res
=
scsi_probe_and_add_lun
(
sdevscan
,
&
sdev
,
NULL
);
scsi_free_sdev
(
sdevscan
);
if
(
res
!=
SCSI_SCAN_LUN_PRESENT
)
return
;
scsi_attach_device
(
sdev
);
}
/**
* scan_scsis - scan the given adapter, or scan a single LUN
* @shost: adapter to scan
* @hardcoded: 1 if a single channel/id/lun should be scanned, else 0
* @hchannel: channel to scan for hardcoded case
* @hid: target id to scan for hardcoded case
* @hlun: lun to scan for hardcoded case
*
* Description:
* If @hardcoded is 1, call scsi_scan_selected_lun to scan a single
* LUN; else, iterate and call scsi_scan_target to scan all possible
* target id's on all possible channels.
**/
void
scan_scsis
(
struct
Scsi_Host
*
shost
,
uint
hardcoded
,
uint
hchannel
,
uint
hid
,
uint
hlun
)
{
if
(
hardcoded
==
1
)
{
/*
* The sdevscan host, channel, id and lun are filled in as
* needed to scan.
*/
for
(
channel
=
0
;
channel
<=
shost
->
max_channel
;
channel
++
)
{
/*
* XXX Overload hchannel/hid/hlun to figure out what to
* scan, and use the standard scanning code rather than
* this function - that way, an entire bus (or fabric), or
* target id can be scanned. There are problems with queue
* depth and the init/attach/finish that must be resolved
* before (re-)scanning can handle finding more than one new
* LUN.
* XXX adapter drivers when possible (FCP, iSCSI)
* could modify max_id to match the current max,
* not the absolute max.
*
* For example, set hchannel 0 and hid to 5, and hlun to -1
* in order to scan all LUNs on channel 0, target id 5.
* XXX add a shost id iterator, so for example,
* the FC ID can be the same as a target id
* without a huge overhead of sparse id's.
*/
scsi_scan_selected_lun
(
shost
,
hchannel
,
hid
,
hlun
);
}
else
{
Scsi_Device
*
sdevscan
;
uint
channel
;
unsigned
int
id
,
order_id
;
/*
* The blk layer queue allocation is a bit expensive to
* repeat for each channel and id - for FCP max_id is near
* 255: each call to scsi_alloc_sdev() implies a call to
* blk_init_queue, and then blk_init_free_list, where 2 *
* queue_nr_requests requests are allocated. Don't do so
* here for scsi_scan_selected_lun, since we end up
* calling select_queue_depths with an extra Scsi_Device
* on the host_queue list.
*/
sdevscan
=
scsi_alloc_sdev
(
shost
,
0
,
0
,
0
);
if
(
sdevscan
==
NULL
)
return
;
/*
* The sdevscan host, channel, id and lun are filled in as
* needed to scan.
*/
for
(
channel
=
0
;
channel
<=
shost
->
max_channel
;
channel
++
)
{
/*
* XXX adapter drivers when possible (FCP, iSCSI)
* could modify max_id to match the current max,
* not the absolute max.
*
* XXX add a shost id iterator, so for example,
* the FC ID can be the same as a target id
* without a huge overhead of sparse id's.
*/
for
(
id
=
0
;
id
<
shost
->
max_id
;
++
id
)
{
if
(
shost
->
reverse_ordering
)
/*
* Scan from high to low id.
*/
order_id
=
shost
->
max_id
-
id
-
1
;
else
order_id
=
id
;
scsi_scan_target
(
sdevscan
,
shost
,
channel
,
order_id
);
}
for
(
id
=
0
;
id
<
shost
->
max_id
;
++
id
)
{
if
(
shost
->
reverse_ordering
)
/*
* Scan from high to low id.
*/
order_id
=
shost
->
max_id
-
id
-
1
;
else
order_id
=
id
;
scsi_scan_target
(
sdevscan
,
shost
,
channel
,
order_id
);
}
scsi_free_sdev
(
sdevscan
);
}
scsi_free_sdev
(
sdevscan
);
}
drivers/scsi/scsi_syms.c
View file @
4af8adfb
...
...
@@ -75,7 +75,6 @@ EXPORT_SYMBOL(scsi_free_host_dev);
EXPORT_SYMBOL
(
scsi_sleep
);
EXPORT_SYMBOL
(
scsi_io_completion
);
EXPORT_SYMBOL
(
scsi_end_request
);
EXPORT_SYMBOL
(
scsi_register_blocked_host
);
EXPORT_SYMBOL
(
scsi_deregister_blocked_host
);
...
...
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