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
f4b5f77e
Commit
f4b5f77e
authored
Nov 04, 2002
by
Alan Cox
Committed by
Dave Jones
Nov 04, 2002
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[PATCH] NCR5380 fix the locking fix fix
parent
01087a66
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
134 additions
and
125 deletions
+134
-125
drivers/scsi/NCR5380.c
drivers/scsi/NCR5380.c
+134
-125
No files found.
drivers/scsi/NCR5380.c
View file @
f4b5f77e
...
@@ -345,6 +345,51 @@ static __inline__ void initialize_SCp(Scsi_Cmnd * cmd)
...
@@ -345,6 +345,51 @@ static __inline__ void initialize_SCp(Scsi_Cmnd * cmd)
}
}
}
}
/**
* NCR5380_poll_politely - wait for NCR5380 status bits
* @instance: controller to poll
* @reg: 5380 register to poll
* @bit: Bitmask to check
* @val: Value required to exit
*
* Polls the NCR5380 in a reasonably efficient manner waiting for
* an event to occur, after a short quick poll we begin giving the
* CPU back in non IRQ contexts
*
* Returns the value of the register or a negative error code.
*/
static
int
NCR5380_poll_politely
(
struct
Scsi_Host
*
instance
,
int
reg
,
int
bit
,
int
val
,
int
t
)
{
NCR5380_local_declare
();
int
n
=
500
;
/* At about 8uS a cycle for the cpu access */
unsigned
long
end
=
jiffies
+
t
;
int
r
;
NCR5380_setup
(
instance
);
while
(
n
--
>
0
)
{
r
=
NCR5380_read
(
reg
);
if
((
r
&
bit
)
==
val
)
return
r
;
cpu_relax
();
}
/* t time yet ? */
while
(
time_before
(
jiffies
,
end
))
{
r
=
NCR5380_read
(
reg
);
if
((
r
&
bit
)
==
val
)
return
r
;
if
(
!
in_interrupt
())
yield
();
else
cpu_relax
();
}
return
-
ETIMEDOUT
;
}
static
struct
{
static
struct
{
unsigned
char
value
;
unsigned
char
value
;
const
char
*
name
;
const
char
*
name
;
...
@@ -679,7 +724,10 @@ static int __init NCR5380_probe_irq(struct Scsi_Host *instance, int possible)
...
@@ -679,7 +724,10 @@ static int __init NCR5380_probe_irq(struct Scsi_Host *instance, int possible)
NCR5380_write
(
INITIATOR_COMMAND_REG
,
ICR_BASE
|
ICR_ASSERT_DATA
|
ICR_ASSERT_SEL
);
NCR5380_write
(
INITIATOR_COMMAND_REG
,
ICR_BASE
|
ICR_ASSERT_DATA
|
ICR_ASSERT_SEL
);
while
(
probe_irq
==
IRQ_NONE
&&
time_before
(
jiffies
,
timeout
))
while
(
probe_irq
==
IRQ_NONE
&&
time_before
(
jiffies
,
timeout
))
barrier
();
{
set_current_state
(
TASK_UNINTERRUPTIBLE
);
schedule_timeout
(
1
);
}
NCR5380_write
(
SELECT_ENABLE_REG
,
0
);
NCR5380_write
(
SELECT_ENABLE_REG
,
0
);
NCR5380_write
(
INITIATOR_COMMAND_REG
,
ICR_BASE
);
NCR5380_write
(
INITIATOR_COMMAND_REG
,
ICR_BASE
);
...
@@ -1026,11 +1074,7 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
...
@@ -1026,11 +1074,7 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
case
5
:
case
5
:
printk
(
KERN_INFO
"scsi%d: SCSI bus busy, waiting up to five seconds
\n
"
,
instance
->
host_no
);
printk
(
KERN_INFO
"scsi%d: SCSI bus busy, waiting up to five seconds
\n
"
,
instance
->
host_no
);
timeout
=
jiffies
+
5
*
HZ
;
timeout
=
jiffies
+
5
*
HZ
;
while
(
time_before
(
jiffies
,
timeout
)
&&
(
NCR5380_read
(
STATUS_REG
)
&
SR_BSY
))
NCR5380_poll_politely
(
instance
,
STATUS_REG
,
SR_BSY
,
0
,
5
*
HZ
);
{
set_current_state
(
TASK_UNINTERRUPTIBLE
);
schedule_timeout
(
1
);
}
break
;
break
;
case
2
:
case
2
:
printk
(
KERN_WARNING
"scsi%d: bus busy, attempting abort
\n
"
,
instance
->
host_no
);
printk
(
KERN_WARNING
"scsi%d: bus busy, attempting abort
\n
"
,
instance
->
host_no
);
...
@@ -1057,8 +1101,7 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
...
@@ -1057,8 +1101,7 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
* twiddling done to the host specific fields of cmd. If the
* twiddling done to the host specific fields of cmd. If the
* main coroutine is not running, it is restarted.
* main coroutine is not running, it is restarted.
*
*
* Locks: host lock taken by caller. Called functions drop and
* Locks: host lock taken by caller
* retake this lock. Called functions take dma lock.
*/
*/
static
int
NCR5380_queue_command
(
Scsi_Cmnd
*
cmd
,
void
(
*
done
)
(
Scsi_Cmnd
*
))
static
int
NCR5380_queue_command
(
Scsi_Cmnd
*
cmd
,
void
(
*
done
)
(
Scsi_Cmnd
*
))
...
@@ -1164,6 +1207,7 @@ static void NCR5380_main(void *p)
...
@@ -1164,6 +1207,7 @@ static void NCR5380_main(void *p)
instance
=
hostdata
->
host
;
instance
=
hostdata
->
host
;
if
(
instance
->
irq
!=
IRQ_NONE
)
spin_lock_irqsave
(
instance
->
host_lock
,
flags
);
spin_lock_irqsave
(
instance
->
host_lock
,
flags
);
do
{
do
{
...
@@ -1243,12 +1287,9 @@ static void NCR5380_main(void *p)
...
@@ -1243,12 +1287,9 @@ static void NCR5380_main(void *p)
do not respond to commands immediately
do not respond to commands immediately
after a scan */
after a scan */
printk
(
KERN_DEBUG
"scsi%d: device %d did not respond in time
\n
"
,
instance
->
host_no
,
tmp
->
target
);
printk
(
KERN_DEBUG
"scsi%d: device %d did not respond in time
\n
"
,
instance
->
host_no
,
tmp
->
target
);
//spin_lock_irq(&io_request_lock);
LIST
(
tmp
,
hostdata
->
issue_queue
);
LIST
(
tmp
,
hostdata
->
issue_queue
);
tmp
->
host_scribble
=
(
unsigned
char
*
)
hostdata
->
issue_queue
;
tmp
->
host_scribble
=
(
unsigned
char
*
)
hostdata
->
issue_queue
;
hostdata
->
issue_queue
=
tmp
;
hostdata
->
issue_queue
=
tmp
;
//spin_unlock_irq(&io_request_lock);
hostdata
->
time_expires
=
jiffies
+
USLEEP_WAITLONG
;
hostdata
->
time_expires
=
jiffies
+
USLEEP_WAITLONG
;
NCR5380_set_timer
(
instance
);
NCR5380_set_timer
(
instance
);
}
}
...
@@ -1267,6 +1308,7 @@ static void NCR5380_main(void *p)
...
@@ -1267,6 +1308,7 @@ static void NCR5380_main(void *p)
break
;
break
;
}
while
(
!
done
);
}
while
(
!
done
);
if
(
instance
->
irq
!=
IRQ_NONE
)
spin_unlock_irqrestore
(
instance
->
host_lock
,
flags
);
spin_unlock_irqrestore
(
instance
->
host_lock
,
flags
);
}
}
...
@@ -1341,24 +1383,9 @@ static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs)
...
@@ -1341,24 +1383,9 @@ static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs)
hostdata
->
dmalen
=
0
;
hostdata
->
dmalen
=
0
;
(
void
)
NCR5380_read
(
RESET_PARITY_INTERRUPT_REG
);
(
void
)
NCR5380_read
(
RESET_PARITY_INTERRUPT_REG
);
#if NCR_TIMEOUT
{
unsigned
long
timeout
=
jiffies
+
NCR_TIMEOUT
;
spin_unlock_irq
(
instance
->
host_lock
);
/* FIXME: we need to poll briefly then defer a workqueue task ! */
/* FIXME: prove timer is always running here! */
NCR5380_poll_politely
(
hostdata
,
BUS_AND_STATUS_REG
,
BASR_ACK
,
0
,
2
*
HZ
);
while
(
NCR5380_read
(
BUS_AND_STATUS_REG
)
&
BASR_ACK
&&
time_before
(
jiffies
,
timeout
))
cpu_relax
();
spin_lock_irq
(
instance
->
host_lock
);
if
(
time_after_eq
(
jiffies
,
timeout
))
printk
(
"scsi%d: timeout at NCR5380.c:%d
\n
"
,
host
->
host_no
,
__LINE__
);
}
#else
/* NCR_TIMEOUT */
while
(
NCR5380_read
(
BUS_AND_STATUS_REG
)
&
BASR_ACK
)
cpu_relax
();
#endif
NCR5380_write
(
MODE_REG
,
MR_BASE
);
NCR5380_write
(
MODE_REG
,
MR_BASE
);
NCR5380_write
(
INITIATOR_COMMAND_REG
,
ICR_BASE
);
NCR5380_write
(
INITIATOR_COMMAND_REG
,
ICR_BASE
);
...
@@ -1438,7 +1465,7 @@ static void collect_stats(struct NCR5380_hostdata *hostdata, Scsi_Cmnd * cmd)
...
@@ -1438,7 +1465,7 @@ static void collect_stats(struct NCR5380_hostdata *hostdata, Scsi_Cmnd * cmd)
* If failed (no target) : cmd->scsi_done() will be called, and the
* If failed (no target) : cmd->scsi_done() will be called, and the
* cmd->result host byte set to DID_BAD_TARGET.
* cmd->result host byte set to DID_BAD_TARGET.
*
*
* Locks: caller holds hostdata lock
* Locks: caller holds hostdata lock
in IRQ mode
*/
*/
static
int
NCR5380_select
(
struct
Scsi_Host
*
instance
,
Scsi_Cmnd
*
cmd
,
int
tag
)
static
int
NCR5380_select
(
struct
Scsi_Host
*
instance
,
Scsi_Cmnd
*
cmd
,
int
tag
)
...
@@ -1451,8 +1478,11 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
...
@@ -1451,8 +1478,11 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
unsigned
long
timeout
;
unsigned
long
timeout
;
unsigned
char
value
;
unsigned
char
value
;
NCR5380_setup
(
instance
);
NCR5380_setup
(
instance
);
int
err
;
if
(
hostdata
->
selecting
)
{
if
(
hostdata
->
selecting
)
{
if
(
instance
->
irq
!=
IRQ_NONE
)
spin_unlock_irq
(
instance
->
host_lock
);
goto
part2
;
/* RvC: sorry prof. Dijkstra, but it keeps the
goto
part2
;
/* RvC: sorry prof. Dijkstra, but it keeps the
rest of the code nearly the same */
rest of the code nearly the same */
}
}
...
@@ -1476,29 +1506,22 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
...
@@ -1476,29 +1506,22 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
NCR5380_write
(
OUTPUT_DATA_REG
,
hostdata
->
id_mask
);
NCR5380_write
(
OUTPUT_DATA_REG
,
hostdata
->
id_mask
);
NCR5380_write
(
MODE_REG
,
MR_ARBITRATE
);
NCR5380_write
(
MODE_REG
,
MR_ARBITRATE
);
/* Wait for arbitration logic to complete */
if
(
instance
->
irq
!=
IRQ_NONE
)
#if NCR_TIMEOUT
{
unsigned
long
timeout
=
jiffies
+
2
*
NCR_TIMEOUT
;
spin_unlock_irq
(
instance
->
host_lock
);
spin_unlock_irq
(
instance
->
host_lock
);
while
(
!
(
NCR5380_read
(
INITIATOR_COMMAND_REG
)
&
ICR_ARBITRATION_PROGRESS
)
/* We can be relaxed here, interrupts are on, we are
&&
time_before
(
jiffies
,
timeout
))
in workqueue context, the birds are singing in the trees */
cpu_relax
();
err
=
NCR5380_poll_politely
(
instance
,
INITIATOR_COMMAND_REG
,
ICR_ARBITRATION_PROGRESS
,
ICR_ARBITRATION_PROGRESS
,
5
*
HZ
);
if
(
instance
->
irq
!=
IRQ_NONE
)
spin_lock_irq
(
instance
->
host_lock
);
spin_lock_irq
(
instance
->
host_lock
);
if
(
time_after_eq
(
jiffies
,
timeout
)
)
{
if
(
err
<
0
)
{
printk
(
"scsi: arbitration timeout at %d
\n
"
,
__LINE__
);
printk
(
KERN_DEBUG
"scsi: arbitration timeout at %d
\n
"
,
__LINE__
);
NCR5380_write
(
MODE_REG
,
MR_BASE
);
NCR5380_write
(
MODE_REG
,
MR_BASE
);
NCR5380_write
(
SELECT_ENABLE_REG
,
hostdata
->
id_mask
);
NCR5380_write
(
SELECT_ENABLE_REG
,
hostdata
->
id_mask
);
return
-
1
;
goto
failed
;
}
}
}
#else
/* NCR_TIMEOUT */
while
(
!
(
NCR5380_read
(
INITIATOR_COMMAND_REG
)
&
ICR_ARBITRATION_PROGRESS
));
#endif
dprintk
(
NDEBUG_ARBITRATION
,
(
"scsi%d : arbitration complete
\n
"
,
instance
->
host_no
));
dprintk
(
NDEBUG_ARBITRATION
,
(
"scsi%d : arbitration complete
\n
"
,
instance
->
host_no
));
...
@@ -1515,7 +1538,7 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
...
@@ -1515,7 +1538,7 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
if
((
NCR5380_read
(
INITIATOR_COMMAND_REG
)
&
ICR_ARBITRATION_LOST
)
||
(
NCR5380_read
(
CURRENT_SCSI_DATA_REG
)
&
hostdata
->
id_higher_mask
)
||
(
NCR5380_read
(
INITIATOR_COMMAND_REG
)
&
ICR_ARBITRATION_LOST
))
{
if
((
NCR5380_read
(
INITIATOR_COMMAND_REG
)
&
ICR_ARBITRATION_LOST
)
||
(
NCR5380_read
(
CURRENT_SCSI_DATA_REG
)
&
hostdata
->
id_higher_mask
)
||
(
NCR5380_read
(
INITIATOR_COMMAND_REG
)
&
ICR_ARBITRATION_LOST
))
{
NCR5380_write
(
MODE_REG
,
MR_BASE
);
NCR5380_write
(
MODE_REG
,
MR_BASE
);
dprintk
(
NDEBUG_ARBITRATION
,
(
"scsi%d : lost arbitration, deasserting MR_ARBITRATE
\n
"
,
instance
->
host_no
));
dprintk
(
NDEBUG_ARBITRATION
,
(
"scsi%d : lost arbitration, deasserting MR_ARBITRATE
\n
"
,
instance
->
host_no
));
return
-
1
;
goto
failed
;
}
}
NCR5380_write
(
INITIATOR_COMMAND_REG
,
ICR_BASE
|
ICR_ASSERT_SEL
);
NCR5380_write
(
INITIATOR_COMMAND_REG
,
ICR_BASE
|
ICR_ASSERT_SEL
);
...
@@ -1528,7 +1551,7 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
...
@@ -1528,7 +1551,7 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
NCR5380_write
(
MODE_REG
,
MR_BASE
);
NCR5380_write
(
MODE_REG
,
MR_BASE
);
NCR5380_write
(
INITIATOR_COMMAND_REG
,
ICR_BASE
);
NCR5380_write
(
INITIATOR_COMMAND_REG
,
ICR_BASE
);
dprintk
(
NDEBUG_ARBITRATION
,
(
"scsi%d : lost arbitration, deasserting ICR_ASSERT_SEL
\n
"
,
instance
->
host_no
));
dprintk
(
NDEBUG_ARBITRATION
,
(
"scsi%d : lost arbitration, deasserting ICR_ASSERT_SEL
\n
"
,
instance
->
host_no
));
return
-
1
;
goto
failed
;
}
}
/*
/*
* Again, bus clear + bus settle time is 1.2us, however, this is
* Again, bus clear + bus settle time is 1.2us, however, this is
...
@@ -1613,8 +1636,7 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
...
@@ -1613,8 +1636,7 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
we poll only once ech clock tick */
we poll only once ech clock tick */
value
=
NCR5380_read
(
STATUS_REG
)
&
(
SR_BSY
|
SR_IO
);
value
=
NCR5380_read
(
STATUS_REG
)
&
(
SR_BSY
|
SR_IO
);
/* FIXME HZ=100 assumption ? */
if
(
!
value
&&
(
hostdata
->
select_time
<
HZ
/
4
))
{
if
(
!
value
&&
(
hostdata
->
select_time
<
25
))
{
/* RvC: we still must wait for a device response */
/* RvC: we still must wait for a device response */
hostdata
->
select_time
++
;
/* after 25 ticks the device has failed */
hostdata
->
select_time
++
;
/* after 25 ticks the device has failed */
hostdata
->
time_expires
=
jiffies
+
1
;
hostdata
->
time_expires
=
jiffies
+
1
;
...
@@ -1627,6 +1649,8 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
...
@@ -1627,6 +1649,8 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
waiting period */
waiting period */
if
((
NCR5380_read
(
STATUS_REG
)
&
(
SR_SEL
|
SR_IO
))
==
(
SR_SEL
|
SR_IO
))
{
if
((
NCR5380_read
(
STATUS_REG
)
&
(
SR_SEL
|
SR_IO
))
==
(
SR_SEL
|
SR_IO
))
{
NCR5380_write
(
INITIATOR_COMMAND_REG
,
ICR_BASE
);
NCR5380_write
(
INITIATOR_COMMAND_REG
,
ICR_BASE
);
if
(
instance
->
irq
!=
IRQ_NONE
)
spin_lock_irq
(
instance
->
host_lock
);
NCR5380_reselect
(
instance
);
NCR5380_reselect
(
instance
);
printk
(
"scsi%d : reselection after won arbitration?
\n
"
,
instance
->
host_no
);
printk
(
"scsi%d : reselection after won arbitration?
\n
"
,
instance
->
host_no
);
NCR5380_write
(
SELECT_ENABLE_REG
,
hostdata
->
id_mask
);
NCR5380_write
(
SELECT_ENABLE_REG
,
hostdata
->
id_mask
);
...
@@ -1645,13 +1669,15 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
...
@@ -1645,13 +1669,15 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
if
(
!
(
NCR5380_read
(
STATUS_REG
)
&
SR_BSY
))
{
if
(
!
(
NCR5380_read
(
STATUS_REG
)
&
SR_BSY
))
{
NCR5380_write
(
INITIATOR_COMMAND_REG
,
ICR_BASE
);
NCR5380_write
(
INITIATOR_COMMAND_REG
,
ICR_BASE
);
if
(
hostdata
->
targets_present
&
(
1
<<
cmd
->
target
))
{
if
(
hostdata
->
targets_present
&
(
1
<<
cmd
->
target
))
{
printk
(
"scsi%d : weirdness
\n
"
,
instance
->
host_no
);
printk
(
KERN_DEBUG
"scsi%d : weirdness
\n
"
,
instance
->
host_no
);
if
(
hostdata
->
restart_select
)
if
(
hostdata
->
restart_select
)
printk
(
"
\t
restart select
\n
"
);
printk
(
KERN_DEBUG
"
\t
restart select
\n
"
);
NCR5380_dprint
(
NDEBUG_SELECTION
,
instance
);
NCR5380_dprint
(
NDEBUG_SELECTION
,
instance
);
NCR5380_write
(
SELECT_ENABLE_REG
,
hostdata
->
id_mask
);
NCR5380_write
(
SELECT_ENABLE_REG
,
hostdata
->
id_mask
);
return
-
1
;
return
-
1
;
}
}
if
(
instance
->
irq
!=
IRQ_NONE
)
spin_lock_irq
(
instance
->
host_lock
);
cmd
->
result
=
DID_BAD_TARGET
<<
16
;
cmd
->
result
=
DID_BAD_TARGET
<<
16
;
collect_stats
(
hostdata
,
cmd
);
collect_stats
(
hostdata
,
cmd
);
cmd
->
scsi_done
(
cmd
);
cmd
->
scsi_done
(
cmd
);
...
@@ -1678,29 +1704,21 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
...
@@ -1678,29 +1704,21 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
*/
*/
/* Wait for start of REQ/ACK handshake */
/* Wait for start of REQ/ACK handshake */
#ifdef NCR_TIMEOUT
{
unsigned
long
timeout
=
jiffies
+
NCR_TIMEOUT
;
spin_unlock_irq
(
instance
->
host_lock
);
err
=
NCR5380_poll_politely
(
instance
,
STATUS_REG
,
SR_REQ
,
SR_REQ
,
HZ
);
while
(
!
(
NCR5380_read
(
STATUS_REG
)
&
SR_REQ
)
&&
time_before
(
jiffies
,
timeout
))
cpu_relax
();
spin_lock_irq
(
instance
->
host_lock
);
if
(
time_after_eq
(
jiffies
,
timeout
))
{
if
(
err
)
printk
(
"scsi%d: timeout at NCR5380.c:%d
\n
"
,
instance
->
host_no
,
__LINE__
);
{
printk
(
KERN_ERR
"scsi%d: timeout at NCR5380.c:%d
\n
"
,
instance
->
host_no
,
__LINE__
);
NCR5380_write
(
SELECT_ENABLE_REG
,
hostdata
->
id_mask
);
NCR5380_write
(
SELECT_ENABLE_REG
,
hostdata
->
id_mask
);
return
-
1
;
goto
failed
;
}
}
}
#else
/* NCR_TIMEOUT */
while
(
!
(
NCR5380_read
(
STATUS_REG
)
&
SR_REQ
))
cpu_relax
();
#endif
/* def NCR_TIMEOUT */
dprintk
(
NDEBUG_SELECTION
,
(
"scsi%d : target %d selected, going into MESSAGE OUT phase.
\n
"
,
instance
->
host_no
,
cmd
->
target
));
dprintk
(
NDEBUG_SELECTION
,
(
"scsi%d : target %d selected, going into MESSAGE OUT phase.
\n
"
,
instance
->
host_no
,
cmd
->
target
));
tmp
[
0
]
=
IDENTIFY
(((
instance
->
irq
==
IRQ_NONE
)
?
0
:
1
),
cmd
->
lun
);
tmp
[
0
]
=
IDENTIFY
(((
instance
->
irq
==
IRQ_NONE
)
?
0
:
1
),
cmd
->
lun
);
if
(
instance
->
irq
!=
IRQ_NONE
)
spin_lock_irq
(
instance
->
host_lock
);
len
=
1
;
len
=
1
;
cmd
->
tag
=
0
;
cmd
->
tag
=
0
;
...
@@ -1717,6 +1735,13 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
...
@@ -1717,6 +1735,13 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
return
0
;
return
0
;
/* Selection failed */
failed:
if
(
instance
->
irq
!=
IRQ_NONE
)
spin_lock_irq
(
instance
->
host_lock
);
return
-
1
;
}
}
/*
/*
...
@@ -1786,6 +1811,7 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase
...
@@ -1786,6 +1811,7 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase
* if breaking is not allowed, we keep polling as long as needed
* if breaking is not allowed, we keep polling as long as needed
*/
*/
/* FIXME */
while
(
!
((
tmp
=
NCR5380_read
(
STATUS_REG
))
&
SR_REQ
)
&&
!
break_allowed
);
while
(
!
((
tmp
=
NCR5380_read
(
STATUS_REG
))
&
SR_REQ
)
&&
!
break_allowed
);
if
(
!
(
tmp
&
SR_REQ
))
{
if
(
!
(
tmp
&
SR_REQ
))
{
/* timeout condition */
/* timeout condition */
...
@@ -1832,8 +1858,8 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase
...
@@ -1832,8 +1858,8 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase
NCR5380_write
(
INITIATOR_COMMAND_REG
,
ICR_BASE
|
ICR_ASSERT_ACK
);
NCR5380_write
(
INITIATOR_COMMAND_REG
,
ICR_BASE
|
ICR_ASSERT_ACK
);
}
}
while
(
NCR5380_read
(
STATUS_REG
)
&
SR_REQ
);
/* FIXME - if this fails bus reset ?? */
NCR5380_poll_politely
(
instance
,
STATUS_REG
,
SR_REQ
,
0
,
5
*
HZ
);
dprintk
(
NDEBUG_HANDSHAKE
,
(
"scsi%d : req false, handshake complete
\n
"
,
instance
->
host_no
));
dprintk
(
NDEBUG_HANDSHAKE
,
(
"scsi%d : req false, handshake complete
\n
"
,
instance
->
host_no
));
/*
/*
...
@@ -1905,8 +1931,9 @@ static void do_reset(struct Scsi_Host *host) {
...
@@ -1905,8 +1931,9 @@ static void do_reset(struct Scsi_Host *host) {
static
int
do_abort
(
struct
Scsi_Host
*
host
)
{
static
int
do_abort
(
struct
Scsi_Host
*
host
)
{
NCR5380_local_declare
();
NCR5380_local_declare
();
unsigned
char
tmp
,
*
msgptr
,
phase
;
unsigned
char
*
msgptr
,
phase
,
tmp
;
int
len
;
int
len
;
int
rc
;
NCR5380_setup
(
host
);
NCR5380_setup
(
host
);
...
@@ -1923,15 +1950,21 @@ static int do_abort(struct Scsi_Host *host) {
...
@@ -1923,15 +1950,21 @@ static int do_abort(struct Scsi_Host *host) {
* the target sees, so we just handshake.
* the target sees, so we just handshake.
*/
*/
while
(
!
(
tmp
=
NCR5380_read
(
STATUS_REG
))
&
SR_REQ
)
rc
=
NCR5380_poll_politely
(
host
,
STATUS_REG
,
SR_REQ
,
SR_REQ
,
60
*
HZ
);
cpu_relax
();
if
(
rc
<
0
)
return
-
1
;
tmp
=
(
unsigned
char
)
rc
;
NCR5380_write
(
TARGET_COMMAND_REG
,
PHASE_SR_TO_TCR
(
tmp
));
NCR5380_write
(
TARGET_COMMAND_REG
,
PHASE_SR_TO_TCR
(
tmp
));
if
((
tmp
&
PHASE_MASK
)
!=
PHASE_MSGOUT
)
{
if
((
tmp
&
PHASE_MASK
)
!=
PHASE_MSGOUT
)
{
NCR5380_write
(
INITIATOR_COMMAND_REG
,
ICR_BASE
|
ICR_ASSERT_ATN
|
ICR_ASSERT_ACK
);
NCR5380_write
(
INITIATOR_COMMAND_REG
,
ICR_BASE
|
ICR_ASSERT_ATN
|
ICR_ASSERT_ACK
);
while
(
NCR5380_read
(
STATUS_REG
)
&
SR_REQ
);
rc
=
NCR5380_poll_politely
(
host
,
STATUS_REG
,
SR_REQ
,
0
,
3
*
HZ
);
NCR5380_write
(
INITIATOR_COMMAND_REG
,
ICR_BASE
|
ICR_ASSERT_ATN
);
NCR5380_write
(
INITIATOR_COMMAND_REG
,
ICR_BASE
|
ICR_ASSERT_ATN
);
if
(
rc
==
-
1
)
return
-
1
;
}
}
tmp
=
ABORT
;
tmp
=
ABORT
;
msgptr
=
&
tmp
;
msgptr
=
&
tmp
;
...
@@ -2245,7 +2278,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase
...
@@ -2245,7 +2278,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase
* XXX Note : we need to watch for bus free or a reset condition here
* XXX Note : we need to watch for bus free or a reset condition here
* to recover from an unexpected bus free condition.
* to recover from an unexpected bus free condition.
*
*
* Locks: io_request_lock held by caller
* Locks: io_request_lock held by caller
in IRQ mode
*/
*/
static
void
NCR5380_information_transfer
(
struct
Scsi_Host
*
instance
)
{
static
void
NCR5380_information_transfer
(
struct
Scsi_Host
*
instance
)
{
...
@@ -2503,7 +2536,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
...
@@ -2503,7 +2536,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
/* Enable reselect interrupts */
/* Enable reselect interrupts */
NCR5380_write
(
SELECT_ENABLE_REG
,
hostdata
->
id_mask
);
NCR5380_write
(
SELECT_ENABLE_REG
,
hostdata
->
id_mask
);
/* Wait for bus free to avoid nasty timeouts */
/* Wait for bus free to avoid nasty timeouts - FIXME timeout !*/
/* NCR538_poll_politely(instance, STATUS_REG, SR_BSY, 0, 30 * HZ); */
while
((
NCR5380_read
(
STATUS_REG
)
&
SR_BSY
)
&&
!
hostdata
->
connected
)
while
((
NCR5380_read
(
STATUS_REG
)
&
SR_BSY
)
&&
!
hostdata
->
connected
)
barrier
();
barrier
();
return
;
return
;
...
@@ -2658,7 +2692,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
...
@@ -2658,7 +2692,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
*
*
* Inputs : instance - this instance of the NCR5380.
* Inputs : instance - this instance of the NCR5380.
*
*
* Locks: io_request_lock held by caller
* Locks: io_request_lock held by caller
if IRQ driven
*/
*/
static
void
NCR5380_reselect
(
struct
Scsi_Host
*
instance
)
{
static
void
NCR5380_reselect
(
struct
Scsi_Host
*
instance
)
{
...
@@ -2696,16 +2730,19 @@ static void NCR5380_reselect(struct Scsi_Host *instance) {
...
@@ -2696,16 +2730,19 @@ static void NCR5380_reselect(struct Scsi_Host *instance) {
NCR5380_write
(
INITIATOR_COMMAND_REG
,
ICR_BASE
|
ICR_ASSERT_BSY
);
NCR5380_write
(
INITIATOR_COMMAND_REG
,
ICR_BASE
|
ICR_ASSERT_BSY
);
while
(
NCR5380_read
(
STATUS_REG
)
&
SR_SEL
);
/* FIXME: timeout too long, must fail to workqueue */
if
(
NCR5380_poll_politely
(
instance
,
STATUS_REG
,
SR_SEL
,
0
,
2
*
HZ
)
<
0
)
abort
=
1
;
NCR5380_write
(
INITIATOR_COMMAND_REG
,
ICR_BASE
);
NCR5380_write
(
INITIATOR_COMMAND_REG
,
ICR_BASE
);
/*
/*
* Wait for target to go into MSGIN.
* Wait for target to go into MSGIN.
* FIXME: timeout needed
* FIXME: timeout needed
and fail to work queeu
*/
*/
while
(
!
(
NCR5380_read
(
STATUS_REG
)
&
SR_REQ
))
if
(
NCR5380_poll_politely
(
instance
,
STATUS_REG
,
SR_REQ
,
SR_REQ
,
2
*
HZ
))
cpu_relax
()
;
abort
=
1
;
len
=
1
;
len
=
1
;
data
=
msg
;
data
=
msg
;
...
@@ -2713,7 +2750,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) {
...
@@ -2713,7 +2750,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) {
NCR5380_transfer_pio
(
instance
,
&
phase
,
&
len
,
&
data
);
NCR5380_transfer_pio
(
instance
,
&
phase
,
&
len
,
&
data
);
if
(
!
msg
[
0
]
&
0x80
)
{
if
(
!
msg
[
0
]
&
0x80
)
{
printk
(
"scsi%d : expecting IDENTIFY message, got "
,
instance
->
host_no
);
printk
(
KERN_ERR
"scsi%d : expecting IDENTIFY message, got "
,
instance
->
host_no
);
print_msg
(
msg
);
print_msg
(
msg
);
abort
=
1
;
abort
=
1
;
}
else
{
}
else
{
...
@@ -2747,7 +2784,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) {
...
@@ -2747,7 +2784,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) {
break
;
break
;
}
}
if
(
!
tmp
)
{
if
(
!
tmp
)
{
printk
(
"scsi%d : warning : target bitmask %02x lun %d not in disconnect_queue.
\n
"
,
instance
->
host_no
,
target_mask
,
lun
);
printk
(
KERN_ERR
"scsi%d : warning : target bitmask %02x lun %d not in disconnect_queue.
\n
"
,
instance
->
host_no
,
target_mask
,
lun
);
/*
/*
* Since we have an established nexus that we can't do anything with,
* Since we have an established nexus that we can't do anything with,
* we must abort it.
* we must abort it.
...
@@ -2790,9 +2827,11 @@ static void NCR5380_dma_complete(NCR5380_instance * instance) {
...
@@ -2790,9 +2827,11 @@ static void NCR5380_dma_complete(NCR5380_instance * instance) {
*
*
* We should use the Last Byte Sent bit, unfortunately this is
* We should use the Last Byte Sent bit, unfortunately this is
* not available on the 5380/5381 (only the various CMOS chips)
* not available on the 5380/5381 (only the various CMOS chips)
*
* FIXME: timeout, and need to handle long timeout/irq case
*/
*/
while
(
NCR5380_read
(
BUS_AND_STATUS_REG
)
&
BASR_ACK
);
NCR5380_poll_politely
(
instance
,
BUS_AND_STATUS_REG
,
BASR_ACK
,
0
,
5
*
HZ
);
NCR5380_write
(
MODE_REG
,
MR_BASE
);
NCR5380_write
(
MODE_REG
,
MR_BASE
);
NCR5380_write
(
INITIATOR_COMMAND_REG
,
ICR_BASE
);
NCR5380_write
(
INITIATOR_COMMAND_REG
,
ICR_BASE
);
...
@@ -2827,21 +2866,15 @@ static void NCR5380_dma_complete(NCR5380_instance * instance) {
...
@@ -2827,21 +2866,15 @@ static void NCR5380_dma_complete(NCR5380_instance * instance) {
* a problem, we could implement longjmp() / setjmp(), setjmp()
* a problem, we could implement longjmp() / setjmp(), setjmp()
* called where the loop started in NCR5380_main().
* called where the loop started in NCR5380_main().
*
*
* Locks: host lock taken by
function
* Locks: host lock taken by
caller
*/
*/
#ifndef NCR5380_abort
static
int
NCR5380_abort
(
Scsi_Cmnd
*
cmd
)
{
static
#endif
int
NCR5380_abort
(
Scsi_Cmnd
*
cmd
)
{
NCR5380_local_declare
();
NCR5380_local_declare
();
struct
Scsi_Host
*
instance
=
cmd
->
host
;
struct
Scsi_Host
*
instance
=
cmd
->
host
;
unsigned
long
flags
;
struct
NCR5380_hostdata
*
hostdata
=
(
struct
NCR5380_hostdata
*
)
instance
->
hostdata
;
struct
NCR5380_hostdata
*
hostdata
=
(
struct
NCR5380_hostdata
*
)
instance
->
hostdata
;
Scsi_Cmnd
*
tmp
,
**
prev
;
Scsi_Cmnd
*
tmp
,
**
prev
;
spin_lock_irqsave
(
instance
->
host_lock
,
flags
);
printk
(
KERN_WARNING
"scsi%d : aborting command
\n
"
,
instance
->
host_no
);
printk
(
KERN_WARNING
"scsi%d : aborting command
\n
"
,
instance
->
host_no
);
print_Scsi_Cmnd
(
cmd
);
print_Scsi_Cmnd
(
cmd
);
...
@@ -2884,7 +2917,6 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
...
@@ -2884,7 +2917,6 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
* aborted flag and get back into our main loop.
* aborted flag and get back into our main loop.
*/
*/
spin_unlock_irqrestore(instance->host_lock, flags);
return 0;
return 0;
}
}
#endif
#endif
...
@@ -2894,8 +2926,6 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
...
@@ -2894,8 +2926,6 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
* from the issue queue.
* from the issue queue.
*/
*/
/* FIXME: check - I think we need the hostdata lock here */
/* KLL */
dprintk
(
NDEBUG_ABORT
,
(
"scsi%d : abort going into loop.
\n
"
,
instance
->
host_no
));
dprintk
(
NDEBUG_ABORT
,
(
"scsi%d : abort going into loop.
\n
"
,
instance
->
host_no
));
for
(
prev
=
(
Scsi_Cmnd
**
)
&
(
hostdata
->
issue_queue
),
tmp
=
(
Scsi_Cmnd
*
)
hostdata
->
issue_queue
;
tmp
;
prev
=
(
Scsi_Cmnd
**
)
&
(
tmp
->
host_scribble
),
tmp
=
(
Scsi_Cmnd
*
)
tmp
->
host_scribble
)
for
(
prev
=
(
Scsi_Cmnd
**
)
&
(
hostdata
->
issue_queue
),
tmp
=
(
Scsi_Cmnd
*
)
hostdata
->
issue_queue
;
tmp
;
prev
=
(
Scsi_Cmnd
**
)
&
(
tmp
->
host_scribble
),
tmp
=
(
Scsi_Cmnd
*
)
tmp
->
host_scribble
)
if
(
cmd
==
tmp
)
{
if
(
cmd
==
tmp
)
{
...
@@ -2905,7 +2935,6 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
...
@@ -2905,7 +2935,6 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
tmp
->
result
=
DID_ABORT
<<
16
;
tmp
->
result
=
DID_ABORT
<<
16
;
dprintk
(
NDEBUG_ABORT
,
(
"scsi%d : abort removed command from issue queue.
\n
"
,
instance
->
host_no
));
dprintk
(
NDEBUG_ABORT
,
(
"scsi%d : abort removed command from issue queue.
\n
"
,
instance
->
host_no
));
tmp
->
done
(
tmp
);
tmp
->
done
(
tmp
);
spin_unlock_irqrestore
(
instance
->
host_lock
,
flags
);
return
SUCCESS
;
return
SUCCESS
;
}
}
#if (NDEBUG & NDEBUG_ABORT)
#if (NDEBUG & NDEBUG_ABORT)
...
@@ -2927,7 +2956,6 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
...
@@ -2927,7 +2956,6 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
if
(
hostdata
->
connected
)
{
if
(
hostdata
->
connected
)
{
dprintk
(
NDEBUG_ABORT
,
(
"scsi%d : abort failed, command connected.
\n
"
,
instance
->
host_no
));
dprintk
(
NDEBUG_ABORT
,
(
"scsi%d : abort failed, command connected.
\n
"
,
instance
->
host_no
));
spin_unlock_irqrestore
(
instance
->
host_lock
,
flags
);
return
FAILED
;
return
FAILED
;
}
}
/*
/*
...
@@ -2972,7 +3000,6 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
...
@@ -2972,7 +3000,6 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
tmp
->
host_scribble
=
NULL
;
tmp
->
host_scribble
=
NULL
;
tmp
->
result
=
DID_ABORT
<<
16
;
tmp
->
result
=
DID_ABORT
<<
16
;
tmp
->
done
(
tmp
);
tmp
->
done
(
tmp
);
spin_unlock_irqrestore
(
instance
->
host_lock
,
flags
);
return
SUCCESS
;
return
SUCCESS
;
}
}
}
}
...
@@ -2985,7 +3012,6 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
...
@@ -2985,7 +3012,6 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
* so we won't panic, but we will notify the user in case something really
* so we won't panic, but we will notify the user in case something really
* broke.
* broke.
*/
*/
spin_unlock_irqrestore
(
instance
->
host_lock
,
flags
);
printk
(
KERN_WARNING
"scsi%d : warning : SCSI command probably completed successfully
\n
"
printk
(
KERN_WARNING
"scsi%d : warning : SCSI command probably completed successfully
\n
"
" before abortion
\n
"
,
instance
->
host_no
);
" before abortion
\n
"
,
instance
->
host_no
);
return
FAILED
;
return
FAILED
;
...
@@ -2999,22 +3025,15 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
...
@@ -2999,22 +3025,15 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
*
*
* Returns : SUCCESS
* Returns : SUCCESS
*
*
* Locks: host lock taken by
function
* Locks: host lock taken by
caller
*/
*/
#ifndef NCR5380_bus_reset
static
int
NCR5380_bus_reset
(
Scsi_Cmnd
*
cmd
)
{
static
#endif
int
NCR5380_bus_reset
(
Scsi_Cmnd
*
cmd
)
{
unsigned
long
flags
;
struct
Scsi_Host
*
instance
=
cmd
->
host
;
NCR5380_local_declare
();
NCR5380_local_declare
();
NCR5380_setup
(
cmd
->
host
);
NCR5380_setup
(
cmd
->
host
);
spin_lock_irqsave
(
instance
->
host_lock
,
flags
);
NCR5380_print_status
(
cmd
->
host
);
NCR5380_print_status
(
cmd
->
host
);
do_reset
(
cmd
->
host
);
do_reset
(
cmd
->
host
);
spin_unlock_irqrestore
(
instance
->
host_lock
,
flags
);
return
SUCCESS
;
return
SUCCESS
;
}
}
...
@@ -3028,12 +3047,7 @@ int NCR5380_bus_reset(Scsi_Cmnd * cmd) {
...
@@ -3028,12 +3047,7 @@ int NCR5380_bus_reset(Scsi_Cmnd * cmd) {
* Locks: io_request_lock held by caller
* Locks: io_request_lock held by caller
*/
*/
#ifndef NCR5380_device_reset
static
int
NCR5380_device_reset
(
Scsi_Cmnd
*
cmd
)
{
static
#endif
int
NCR5380_device_reset
(
Scsi_Cmnd
*
cmd
)
{
NCR5380_local_declare
();
NCR5380_setup
(
cmd
->
host
);
return
FAILED
;
return
FAILED
;
}
}
...
@@ -3047,11 +3061,6 @@ int NCR5380_device_reset(Scsi_Cmnd * cmd) {
...
@@ -3047,11 +3061,6 @@ int NCR5380_device_reset(Scsi_Cmnd * cmd) {
* Locks: io_request_lock held by caller
* Locks: io_request_lock held by caller
*/
*/
#ifndef NCR5380_host_reset
static
int
NCR5380_host_reset
(
Scsi_Cmnd
*
cmd
)
{
static
#endif
int
NCR5380_host_reset
(
Scsi_Cmnd
*
cmd
)
{
NCR5380_local_declare
();
NCR5380_setup
(
cmd
->
host
);
return
FAILED
;
return
FAILED
;
}
}
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