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
88261001
Commit
88261001
authored
Jun 11, 2002
by
James Bottomley
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[SCSI 53c700] add specimen block layer tcq
parent
b06ae2a2
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
67 additions
and
180 deletions
+67
-180
drivers/scsi/53c700.c
drivers/scsi/53c700.c
+65
-177
drivers/scsi/53c700.h
drivers/scsi/53c700.h
+2
-3
No files found.
drivers/scsi/53c700.c
View file @
88261001
...
...
@@ -284,6 +284,7 @@ NCR_700_detect(Scsi_Host_Template *tpnt,
tpnt
->
cmd_per_lun
=
NCR_700_MAX_TAGS
;
tpnt
->
use_clustering
=
DISABLE_CLUSTERING
;
tpnt
->
proc_info
=
NCR_700_proc_directory_info
;
tpnt
->
use_blk_tcq
=
1
;
if
(
tpnt
->
name
==
NULL
)
tpnt
->
name
=
"53c700"
;
...
...
@@ -499,46 +500,12 @@ STATIC void
free_slot
(
struct
NCR_700_command_slot
*
slot
,
struct
NCR_700_Host_Parameters
*
hostdata
)
{
int
hash
;
struct
NCR_700_command_slot
**
forw
,
**
back
;
if
((
slot
->
state
&
NCR_700_SLOT_MASK
)
!=
NCR_700_SLOT_MAGIC
)
{
printk
(
KERN_ERR
"53c700: SLOT %p is not MAGIC!!!
\n
"
,
slot
);
}
if
(
slot
->
state
==
NCR_700_SLOT_FREE
)
{
printk
(
KERN_ERR
"53c700: SLOT %p is FREE!!!
\n
"
,
slot
);
}
/* remove from queues */
if
(
slot
->
tag
!=
NCR_700_NO_TAG
)
{
hash
=
hash_ITLQ
(
slot
->
cmnd
->
target
,
slot
->
cmnd
->
lun
,
slot
->
tag
);
if
(
slot
->
ITLQ_forw
==
NULL
)
back
=
&
hostdata
->
ITLQ_Hash_back
[
hash
];
else
back
=
&
slot
->
ITLQ_forw
->
ITLQ_back
;
if
(
slot
->
ITLQ_back
==
NULL
)
forw
=
&
hostdata
->
ITLQ_Hash_forw
[
hash
];
else
forw
=
&
slot
->
ITLQ_back
->
ITLQ_forw
;
*
forw
=
slot
->
ITLQ_forw
;
*
back
=
slot
->
ITLQ_back
;
}
hash
=
hash_ITL
(
slot
->
cmnd
->
target
,
slot
->
cmnd
->
lun
);
if
(
slot
->
ITL_forw
==
NULL
)
back
=
&
hostdata
->
ITL_Hash_back
[
hash
];
else
back
=
&
slot
->
ITL_forw
->
ITL_back
;
if
(
slot
->
ITL_back
==
NULL
)
forw
=
&
hostdata
->
ITL_Hash_forw
[
hash
];
else
forw
=
&
slot
->
ITL_back
->
ITL_forw
;
*
forw
=
slot
->
ITL_forw
;
*
back
=
slot
->
ITL_back
;
slot
->
resume_offset
=
0
;
slot
->
cmnd
=
NULL
;
...
...
@@ -566,48 +533,6 @@ save_for_reselection(struct NCR_700_Host_Parameters *hostdata,
hostdata
->
cmd
=
NULL
;
}
/* Most likely nexus is the oldest in each case */
STATIC
inline
struct
NCR_700_command_slot
*
find_ITL_Nexus
(
struct
NCR_700_Host_Parameters
*
hostdata
,
__u8
pun
,
__u8
lun
)
{
int
hash
=
hash_ITL
(
pun
,
lun
);
struct
NCR_700_command_slot
*
slot
=
hostdata
->
ITL_Hash_back
[
hash
];
while
(
slot
!=
NULL
&&
!
(
slot
->
cmnd
->
target
==
pun
&&
slot
->
cmnd
->
lun
==
lun
))
slot
=
slot
->
ITL_back
;
return
slot
;
}
STATIC
inline
struct
NCR_700_command_slot
*
find_ITLQ_Nexus
(
struct
NCR_700_Host_Parameters
*
hostdata
,
__u8
pun
,
__u8
lun
,
__u8
tag
)
{
int
hash
=
hash_ITLQ
(
pun
,
lun
,
tag
);
struct
NCR_700_command_slot
*
slot
=
hostdata
->
ITLQ_Hash_back
[
hash
];
while
(
slot
!=
NULL
&&
!
(
slot
->
cmnd
->
target
==
pun
&&
slot
->
cmnd
->
lun
==
lun
&&
slot
->
tag
==
tag
))
slot
=
slot
->
ITLQ_back
;
#ifdef NCR_700_TAG_DEBUG
if
(
slot
!=
NULL
)
{
struct
NCR_700_command_slot
*
n
=
slot
->
ITLQ_back
;
while
(
n
!=
NULL
&&
n
->
cmnd
->
target
!=
pun
&&
n
->
cmnd
->
lun
!=
lun
&&
n
->
tag
!=
tag
)
n
=
n
->
ITLQ_back
;
if
(
n
!=
NULL
&&
n
->
cmnd
->
target
==
pun
&&
n
->
cmnd
->
lun
==
lun
&&
n
->
tag
==
tag
)
{
printk
(
KERN_WARNING
"53c700: WARNING: DUPLICATE tag %d
\n
"
,
tag
);
}
}
#endif
return
slot
;
}
/* This translates the SDTR message offset and period to a value
* which can be loaded into the SXFER_REG.
*
...
...
@@ -697,7 +622,6 @@ NCR_700_scsi_done(struct NCR_700_Host_Parameters *hostdata,
SCp
->
underflow
=
SCp
->
old_underflow
;
}
free_slot
(
slot
,
hostdata
);
#ifdef NCR_700_DEBUG
if
(
NCR_700_get_depth
(
SCp
->
device
)
==
0
||
...
...
@@ -1148,6 +1072,7 @@ process_script_interrupt(__u32 dsps, __u32 dsp, Scsi_Cmnd *SCp,
__u8
lun
;
struct
NCR_700_command_slot
*
slot
;
__u8
reselection_id
=
hostdata
->
reselection_id
;
Scsi_Device
*
SDp
;
lun
=
hostdata
->
msgin
[
0
]
&
0x1f
;
...
...
@@ -1155,34 +1080,39 @@ process_script_interrupt(__u32 dsps, __u32 dsp, Scsi_Cmnd *SCp,
DEBUG
((
"scsi%d: (%d:%d) RESELECTED!
\n
"
,
host
->
host_no
,
reselection_id
,
lun
));
/* clear the reselection indicator */
SDp
=
scsi_find_device
(
host
,
0
,
reselection_id
,
lun
);
if
(
unlikely
(
SDp
==
NULL
))
{
printk
(
KERN_ERR
"scsi%d: (%d:%d) HAS NO device
\n
"
,
host
->
host_no
,
reselection_id
,
lun
);
BUG
();
}
if
(
hostdata
->
msgin
[
1
]
==
A_SIMPLE_TAG_MSG
)
{
slot
=
find_ITLQ_Nexus
(
hostdata
,
reselection_id
,
lun
,
hostdata
->
msgin
[
2
]);
Scsi_Cmnd
*
SCp
=
scsi_find_tag
(
SDp
,
hostdata
->
msgin
[
2
]);
if
(
unlikely
(
SCp
==
NULL
))
{
printk
(
KERN_ERR
"scsi%d: (%d:%d) no saved request for tag %d
\n
"
,
host
->
host_no
,
reselection_id
,
lun
,
hostdata
->
msgin
[
2
]);
BUG
();
}
slot
=
(
struct
NCR_700_command_slot
*
)
SCp
->
host_scribble
;
DEBUG
((
"53c700: %d:%d:%d, reselection is tag %d, slot %p(%d)
\n
"
,
host
->
host_no
,
SDp
->
id
,
SDp
->
lun
,
hostdata
->
msgin
[
2
],
slot
,
slot
->
tag
));
}
else
{
slot
=
find_ITL_Nexus
(
hostdata
,
reselection_id
,
lun
);
Scsi_Cmnd
*
SCp
=
scsi_find_tag
(
SDp
,
SCSI_NO_TAG
);
if
(
unlikely
(
SCp
==
NULL
))
{
printk
(
KERN_ERR
"scsi%d: (%d:%d) no saved request for untagged cmd
\n
"
,
host
->
host_no
,
reselection_id
,
lun
);
BUG
();
}
slot
=
(
struct
NCR_700_command_slot
*
)
SCp
->
host_scribble
;
}
retry:
if
(
slot
==
NULL
)
{
struct
NCR_700_command_slot
*
s
=
find_ITL_Nexus
(
hostdata
,
reselection_id
,
lun
);
printk
(
KERN_ERR
"scsi%d: (%d:%d) RESELECTED but no saved command (MSG = %02x %02x %02x)!!
\n
"
,
host
->
host_no
,
reselection_id
,
lun
,
hostdata
->
msgin
[
0
],
hostdata
->
msgin
[
1
],
hostdata
->
msgin
[
2
]);
printk
(
KERN_ERR
" OUTSTANDING TAGS:"
);
while
(
s
!=
NULL
)
{
if
(
s
->
cmnd
->
target
==
reselection_id
&&
s
->
cmnd
->
lun
==
lun
)
{
printk
(
"%d "
,
s
->
tag
);
if
(
s
->
tag
==
hostdata
->
msgin
[
2
])
{
printk
(
" ***FOUND***
\n
"
);
slot
=
s
;
goto
retry
;
}
}
s
=
s
->
ITL_back
;
}
printk
(
"
\n
"
);
}
else
{
if
(
hostdata
->
state
!=
NCR_700_HOST_BUSY
)
printk
(
KERN_ERR
"scsi%d: FATAL, host not busy during valid reselection!
\n
"
,
...
...
@@ -1474,9 +1404,8 @@ NCR_700_start_command(Scsi_Cmnd *SCp)
* will refuse all tags, so send the request sense as untagged
* */
if
((
hostdata
->
tag_negotiated
&
(
1
<<
SCp
->
target
))
&&
(
slot
->
tag
!=
NCR_700_NO_TAG
&&
SCp
->
cmnd
[
0
]
!=
REQUEST_SENSE
))
{
hostdata
->
msgout
[
count
++
]
=
A_SIMPLE_TAG_MSG
;
hostdata
->
msgout
[
count
++
]
=
slot
->
tag
;
&&
(
slot
->
tag
!=
SCSI_NO_TAG
&&
SCp
->
cmnd
[
0
]
!=
REQUEST_SENSE
))
{
count
+=
scsi_populate_tag_msg
(
SCp
,
&
hostdata
->
msgout
[
count
]);
}
if
(
hostdata
->
fast
&&
...
...
@@ -1836,7 +1765,6 @@ NCR_700_queuecommand(Scsi_Cmnd *SCp, void (*done)(Scsi_Cmnd *))
__u32
move_ins
;
int
pci_direction
;
struct
NCR_700_command_slot
*
slot
;
int
hash
;
if
(
hostdata
->
command_slot_count
>=
NCR_700_COMMAND_SLOTS_PER_HOST
)
{
/* We're over our allocation, this should never happen
...
...
@@ -1844,7 +1772,15 @@ NCR_700_queuecommand(Scsi_Cmnd *SCp, void (*done)(Scsi_Cmnd *))
printk
(
KERN_WARNING
"scsi%d: Command depth has gone over queue depth
\n
"
,
SCp
->
host
->
host_no
);
return
1
;
}
if
(
NCR_700_get_depth
(
SCp
->
device
)
!=
0
&&
!
(
hostdata
->
tag_negotiated
&
(
1
<<
SCp
->
target
)))
{
/* check for untagged commands. We cannot have any outstanding
* commands if we accept them. Commands could be untagged because:
*
* - The tag negotiated bitmap is clear
* - The blk layer sent and untagged command
*/
if
(
NCR_700_get_depth
(
SCp
->
device
)
!=
0
&&
(
!
(
hostdata
->
tag_negotiated
&
(
1
<<
SCp
->
target
))
||
!
blk_rq_tagged
(
SCp
->
request
)))
{
DEBUG
((
KERN_ERR
"scsi%d (%d:%d) has non zero depth %d
\n
"
,
SCp
->
host
->
host_no
,
SCp
->
target
,
SCp
->
lun
,
NCR_700_get_depth
(
SCp
->
device
)));
...
...
@@ -1883,84 +1819,40 @@ NCR_700_queuecommand(Scsi_Cmnd *SCp, void (*done)(Scsi_Cmnd *))
* NOTE: There is a danger here: the mid layer supports
* tag queuing per LUN. We only support it per PUN because
* of potential reselection issues */
printk
(
KERN_NOTICE
"scsi%d: (%d:%d) beginning blk layer TCQ
\n
"
,
SCp
->
device
->
host
->
host_no
,
SCp
->
target
,
SCp
->
lun
);
scsi_activate_tcq
(
SCp
->
device
,
NCR_700_MAX_TAGS
);
}
if
(
blk_rq_tagged
(
SCp
->
request
)
&&
(
hostdata
->
tag_negotiated
&
(
1
<<
SCp
->
target
))
==
0
)
{
printk
(
KERN_INFO
"scsi%d: (%d:%d) Enabling Tag Command Queuing
\n
"
,
SCp
->
device
->
host
->
host_no
,
SCp
->
target
,
SCp
->
lun
);
hostdata
->
tag_negotiated
|=
(
1
<<
SCp
->
target
);
NCR_700_set_flag
(
SCp
->
device
,
NCR_700_DEV_BEGIN_TAG_QUEUEING
);
SCp
->
device
->
tagged_queue
=
1
;
}
if
(
hostdata
->
tag_negotiated
&
(
1
<<
SCp
->
target
))
{
/* here we may have to process an untagged command. The gate
* above ensures that this will be the only one outstanding,
* so clear the tag negotiated bit.
*
* FIXME: This will royally screw up on multiple LUN devices
* */
if
(
!
blk_rq_tagged
(
SCp
->
request
)
&&
(
hostdata
->
tag_negotiated
&
(
1
<<
SCp
->
target
)))
{
printk
(
KERN_INFO
"scsi%d: (%d:%d) Disabling Tag Command Queuing
\n
"
,
SCp
->
device
->
host
->
host_no
,
SCp
->
target
,
SCp
->
lun
);
hostdata
->
tag_negotiated
&=
~
(
1
<<
SCp
->
target
);
}
struct
NCR_700_command_slot
*
old
=
find_ITL_Nexus
(
hostdata
,
SCp
->
target
,
SCp
->
lun
);
#ifdef NCR_700_TAG_DEBUG
struct
NCR_700_command_slot
*
found
;
#endif
if
(
old
!=
NULL
&&
old
->
tag
==
SCp
->
device
->
current_tag
)
{
/* On some badly starving drives, this can be
* a frequent occurance, so print the message
* only once */
if
(
NCR_700_is_flag_clear
(
SCp
->
device
,
NCR_700_DEV_TAG_STARVATION_WARNED
))
{
printk
(
KERN_WARNING
"scsi%d (%d:%d) Target is suffering from tag starvation.
\n
"
,
SCp
->
host
->
host_no
,
SCp
->
target
,
SCp
->
lun
);
NCR_700_set_flag
(
SCp
->
device
,
NCR_700_DEV_TAG_STARVATION_WARNED
);
}
/* Release the slot and ajust the depth before refusing
* the command */
free_slot
(
slot
,
hostdata
);
NCR_700_set_depth
(
SCp
->
device
,
NCR_700_get_depth
(
SCp
->
device
)
-
1
);
return
1
;
}
slot
->
tag
=
SCp
->
device
->
current_tag
++
;
#ifdef NCR_700_TAG_DEBUG
while
((
found
=
find_ITLQ_Nexus
(
hostdata
,
SCp
->
target
,
SCp
->
lun
,
slot
->
tag
))
!=
NULL
)
{
printk
(
"
\n\n
**ERROR** already using tag %d, but oldest is %d
\n
"
,
slot
->
tag
,
(
old
==
NULL
)
?
-
1
:
old
->
tag
);
printk
(
" FOUND = %p, tag = %d, pun = %d, lun = %d
\n
"
,
found
,
found
->
tag
,
found
->
cmnd
->
target
,
found
->
cmnd
->
lun
);
slot
->
tag
=
SCp
->
device
->
current_tag
++
;
printk
(
" Tag list is: "
);
while
(
old
!=
NULL
)
{
if
(
old
->
cmnd
->
target
==
SCp
->
target
&&
old
->
cmnd
->
lun
==
SCp
->
lun
)
printk
(
"%d "
,
old
->
tag
);
old
=
old
->
ITL_back
;
}
printk
(
"
\n\n
"
);
}
#endif
hash
=
hash_ITLQ
(
SCp
->
target
,
SCp
->
lun
,
slot
->
tag
);
/* link into the ITLQ hash queues */
slot
->
ITLQ_forw
=
hostdata
->
ITLQ_Hash_forw
[
hash
];
hostdata
->
ITLQ_Hash_forw
[
hash
]
=
slot
;
#ifdef NCR_700_TAG_DEBUG
if
(
slot
->
ITLQ_forw
!=
NULL
&&
slot
->
ITLQ_forw
->
ITLQ_back
!=
NULL
)
{
printk
(
KERN_ERR
"scsi%d (%d:%d) ITLQ_back is not NULL!!!!
\n
"
,
SCp
->
host
->
host_no
,
SCp
->
target
,
SCp
->
lun
);
}
#endif
if
(
slot
->
ITLQ_forw
!=
NULL
)
slot
->
ITLQ_forw
->
ITLQ_back
=
slot
;
else
hostdata
->
ITLQ_Hash_back
[
hash
]
=
slot
;
slot
->
ITLQ_back
=
NULL
;
if
((
hostdata
->
tag_negotiated
&
(
1
<<
SCp
->
target
)))
{
slot
->
tag
=
SCp
->
request
->
tag
;
DEBUG
((
"53c700 %d:%d:%d, sending out tag %d, slot %p
\n
"
,
SCp
->
host
->
host_no
,
SCp
->
target
,
SCp
->
lun
,
slot
->
tag
,
slot
));
}
else
{
slot
->
tag
=
NCR_700_NO_TAG
;
slot
->
tag
=
SCSI_NO_TAG
;
/* must populate current_cmnd for scsi_find_tag to work */
SCp
->
device
->
current_cmnd
=
SCp
;
}
/* link into the ITL hash queues */
hash
=
hash_ITL
(
SCp
->
target
,
SCp
->
lun
);
slot
->
ITL_forw
=
hostdata
->
ITL_Hash_forw
[
hash
];
hostdata
->
ITL_Hash_forw
[
hash
]
=
slot
;
#ifdef NCR_700_TAG_DEBUG
if
(
slot
->
ITL_forw
!=
NULL
&&
slot
->
ITL_forw
->
ITL_back
!=
NULL
)
{
printk
(
KERN_ERR
"scsi%d (%d:%d) ITL_back is not NULL!!!!
\n
"
,
SCp
->
host
->
host_no
,
SCp
->
target
,
SCp
->
lun
);
}
#endif
if
(
slot
->
ITL_forw
!=
NULL
)
slot
->
ITL_forw
->
ITL_back
=
slot
;
else
hostdata
->
ITL_Hash_back
[
hash
]
=
slot
;
slot
->
ITL_back
=
NULL
;
/* sanity check: some of the commands generated by the mid-layer
* have an eccentric idea of their sc_data_direction */
if
(
!
SCp
->
use_sg
&&
!
SCp
->
request_bufflen
...
...
@@ -2054,16 +1946,12 @@ STATIC int
NCR_700_abort
(
Scsi_Cmnd
*
SCp
)
{
struct
NCR_700_command_slot
*
slot
;
struct
NCR_700_Host_Parameters
*
hostdata
=
(
struct
NCR_700_Host_Parameters
*
)
SCp
->
host
->
hostdata
[
0
];
printk
(
KERN_INFO
"scsi%d (%d:%d) New error handler wants to abort command
\n\t
"
,
SCp
->
host
->
host_no
,
SCp
->
target
,
SCp
->
lun
);
print_command
(
SCp
->
cmnd
);
slot
=
find_ITL_Nexus
(
hostdata
,
SCp
->
target
,
SCp
->
lun
);
while
(
slot
!=
NULL
&&
slot
->
cmnd
!=
SCp
)
slot
=
slot
->
ITL_back
;
slot
=
(
struct
NCR_700_command_slot
*
)
SCp
->
host_scribble
;
if
(
slot
==
NULL
)
/* no outstanding command to abort */
...
...
drivers/scsi/53c700.h
View file @
88261001
...
...
@@ -9,7 +9,7 @@
#define _53C700_H
/* Turn on for general debugging---too verbose for normal use */
#undef
NCR_700_DEBUG
#undef
NCR_700_DEBUG
/* Debug the tag queues, checking hash queue allocation and deallocation
* and search for duplicate tags */
#undef NCR_700_TAG_DEBUG
...
...
@@ -189,8 +189,7 @@ struct NCR_700_command_slot {
#define NCR_700_SLOT_BUSY (1|NCR_700_SLOT_MAGIC)
/* slot has command active on HA */
#define NCR_700_SLOT_QUEUED (2|NCR_700_SLOT_MAGIC)
/* slot has command to be made active on HA */
__u8
state
;
#define NCR_700_NO_TAG 0xdead
__u16
tag
;
int
tag
;
__u32
resume_offset
;
Scsi_Cmnd
*
cmnd
;
/* The pci_mapped address of the actual command in cmnd */
...
...
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