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
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