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
518a6e87
Commit
518a6e87
authored
Jun 19, 2002
by
Dave Jones
Committed by
Linus Torvalds
Jun 19, 2002
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[PATCH] udpated 3ware driver from vendor.
parent
6eb57548
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
94 additions
and
56 deletions
+94
-56
drivers/scsi/3w-xxxx.c
drivers/scsi/3w-xxxx.c
+59
-24
drivers/scsi/3w-xxxx.h
drivers/scsi/3w-xxxx.h
+35
-32
No files found.
drivers/scsi/3w-xxxx.c
View file @
518a6e87
...
...
@@ -141,12 +141,23 @@
Empty stale responses before draining aen queue.
Fix tw_scsi_eh_abort() to not reset on every io abort.
Set can_queue in SHT to 255 to prevent hang from AEN.
1.02.00.022 - Fix possible null pointer dereference in tw_scsi_release().
1.02.00.023 - Fix bug in tw_aen_drain_queue() where unit # was always zero.
1.02.00.024 - Add severity levels to AEN strings.
1.02.00.025 - Fix command interrupt spurious error messages.
Fix bug in raw command post with data ioctl method.
Fix bug where rollcall sometimes failed with cable errors.
Print unit # on all command timeouts.
*/
#include <linux/module.h>
MODULE_AUTHOR
(
"3ware Inc."
);
#ifdef __SMP__
MODULE_DESCRIPTION
(
"3ware Storage Controller Linux Driver (SMP)"
);
#else
MODULE_DESCRIPTION
(
"3ware Storage Controller Linux Driver"
);
#endif
MODULE_LICENSE
(
"GPL"
);
#include <linux/kernel.h>
...
...
@@ -190,7 +201,7 @@ static struct notifier_block tw_notifier = {
};
/* Globals */
char
*
tw_driver_version
=
"1.02.00.02
1
"
;
char
*
tw_driver_version
=
"1.02.00.02
5
"
;
TW_Device_Extension
*
tw_device_extension_list
[
TW_MAX_SLOT
];
int
tw_device_extension_count
=
0
;
...
...
@@ -214,7 +225,7 @@ int tw_aen_complete(TW_Device_Extension *tw_dev, int request_id)
/* Print some useful info when certain aen codes come out */
if
(
aen
==
0x0ff
)
{
printk
(
KERN_WARNING
"3w-xxxx: scsi%d: AEN: AEN queue overflow.
\n
"
,
tw_dev
->
host
->
host_no
);
printk
(
KERN_WARNING
"3w-xxxx: scsi%d: AEN:
INFO:
AEN queue overflow.
\n
"
,
tw_dev
->
host
->
host_no
);
}
else
{
if
((
aen
&
0x0ff
)
<
TW_AEN_STRING_MAX
)
{
if
((
tw_aen_string
[
aen
&
0xff
][
strlen
(
tw_aen_string
[
aen
&
0xff
])
-
1
])
==
'#'
)
{
...
...
@@ -286,7 +297,7 @@ int tw_aen_drain_queue(TW_Device_Extension *tw_dev)
status_reg_addr
=
tw_dev
->
registers
.
status_reg_addr
;
response_que_addr
=
tw_dev
->
registers
.
response_que_addr
;
if
(
tw_poll_status
(
tw_dev
,
TW_STATUS_ATTENTION_INTERRUPT
,
30
))
{
if
(
tw_poll_status
(
tw_dev
,
TW_STATUS_ATTENTION_INTERRUPT
|
TW_STATUS_MICROCONTROLLER_READY
,
30
))
{
dprintk
(
KERN_WARNING
"3w-xxxx: tw_aen_drain_queue(): No attention interrupt for card %d.
\n
"
,
tw_device_extension_count
);
return
1
;
}
...
...
@@ -396,7 +407,7 @@ int tw_aen_drain_queue(TW_Device_Extension *tw_dev)
break
;
default:
if
(
aen
==
0x0ff
)
{
printk
(
KERN_WARNING
"3w-xxxx: AEN: AEN queue overflow.
\n
"
);
printk
(
KERN_WARNING
"3w-xxxx: AEN:
INFO:
AEN queue overflow.
\n
"
);
}
else
{
if
((
aen
&
0x0ff
)
<
TW_AEN_STRING_MAX
)
{
if
((
tw_aen_string
[
aen
&
0xff
][
strlen
(
tw_aen_string
[
aen
&
0xff
])
-
1
])
==
'#'
)
{
...
...
@@ -413,7 +424,7 @@ int tw_aen_drain_queue(TW_Device_Extension *tw_dev)
/* Now put the aen on the aen_queue */
if
(
queue
==
1
)
{
tw_dev
->
aen_queue
[
tw_dev
->
aen_tail
]
=
aen
_code
;
tw_dev
->
aen_queue
[
tw_dev
->
aen_tail
]
=
aen
;
if
(
tw_dev
->
aen_tail
==
TW_Q_LENGTH
-
1
)
{
tw_dev
->
aen_tail
=
TW_Q_START
;
}
else
{
...
...
@@ -1348,7 +1359,7 @@ static void tw_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
}
tw_dev
->
pending_request_count
--
;
}
else
{
printk
(
KERN_WARNING
"3w-xxxx: scsi%d: Error posting pending commands.
\n
"
,
tw_dev
->
host
->
host_no
);
/* If we get here, we will continue re-posting on the next command interrupt */
break
;
}
}
...
...
@@ -1379,9 +1390,14 @@ static void tw_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
/* Check for correct state */
if
(
tw_dev
->
state
[
request_id
]
!=
TW_S_POSTED
)
{
/* Handle timed out ioctl's */
if
(
tw_dev
->
srb
[
request_id
]
!=
0
)
{
if
(
tw_dev
->
srb
[
request_id
]
->
cmnd
[
0
]
!=
TW_IOCTL
)
{
printk
(
KERN_WARNING
"3w-xxxx: scsi%d: Received a request id (%d) (opcode = 0x%x) that wasn't posted.
\n
"
,
tw_dev
->
host
->
host_no
,
request_id
,
command_packet
->
byte0
.
opcode
);
error
=
1
;
}
}
}
dprintk
(
KERN_NOTICE
"3w-xxxx: tw_interrupt(): Response queue request id: %d.
\n
"
,
request_id
);
...
...
@@ -1472,8 +1488,9 @@ int tw_ioctl(TW_Device_Extension *tw_dev, int request_id)
TW_Passthru
*
passthru
=
NULL
;
int
tw_aen_code
,
i
,
use_sg
;
char
*
data_ptr
;
int
total_bytes
=
0
;
int
total_bytes
=
0
,
posted
=
0
;
dma_addr_t
dma_handle
;
struct
timeval
before
,
timeout
;
ioctl
=
(
TW_Ioctl
*
)
tw_dev
->
srb
[
request_id
]
->
request_buffer
;
if
(
ioctl
==
NULL
)
{
...
...
@@ -1625,7 +1642,7 @@ int tw_ioctl(TW_Device_Extension *tw_dev, int request_id)
if
((
u32
*
)
command_packet
->
byte8
.
param
.
sgl
[
i
].
address
!=
NULL
)
{
error
=
copy_from_user
(
data_ptr
,
(
u32
*
)
command_packet
->
byte8
.
param
.
sgl
[
i
].
address
,
command_packet
->
byte8
.
param
.
sgl
[
i
].
length
);
if
(
error
)
{
printk
(
KERN_WARNING
"3w-xxxx: scsi%d: Error copying param sglist from userspace.
\n
"
,
tw_dev
->
host
->
host_no
);
d
printk
(
KERN_WARNING
"3w-xxxx: scsi%d: Error copying param sglist from userspace.
\n
"
,
tw_dev
->
host
->
host_no
);
goto
tw_ioctl_bail
;
}
}
else
{
...
...
@@ -1656,7 +1673,7 @@ int tw_ioctl(TW_Device_Extension *tw_dev, int request_id)
if
((
u32
*
)
command_packet
->
byte8
.
io
.
sgl
[
i
].
address
!=
NULL
)
{
error
=
copy_from_user
(
data_ptr
,
(
u32
*
)
command_packet
->
byte8
.
io
.
sgl
[
i
].
address
,
command_packet
->
byte8
.
io
.
sgl
[
i
].
length
);
if
(
error
)
{
printk
(
KERN_WARNING
"3w-xxxx: scsi%d: Error copying io sglist from userspace.
\n
"
,
tw_dev
->
host
->
host_no
);
d
printk
(
KERN_WARNING
"3w-xxxx: scsi%d: Error copying io sglist from userspace.
\n
"
,
tw_dev
->
host
->
host_no
);
goto
tw_ioctl_bail
;
}
}
else
{
...
...
@@ -1672,15 +1689,31 @@ int tw_ioctl(TW_Device_Extension *tw_dev, int request_id)
command_packet
->
byte8
.
io
.
sgl
[
0
].
length
=
total_bytes
;
}
spin_unlock
(
&
tw_dev
->
tw_lock
);
spin_unlock_irq
(
tw_dev
->
host
->
host_lock
);
spin_unlock_irq
(
&
tw_dev
->
tw_lock
);
set_bit
(
TW_IN_IOCTL
,
&
tw_dev
->
flags
);
/* Finally post the command packet */
tw_post_command_packet
(
tw_dev
,
request_id
);
posted
=
1
;
do_gettimeofday
(
&
before
);
tw_ioctl_retry:
mdelay
(
TW_IOCTL_WAIT_TIME
);
spin_lock_irq
(
&
tw_dev
->
tw_lock
);
if
(
test_bit
(
TW_IN_IOCTL
,
&
tw_dev
->
flags
))
{
do_gettimeofday
(
&
timeout
);
if
(
before
.
tv_sec
+
TW_IOCTL_TIMEOUT
<
timeout
.
tv_sec
)
{
spin_lock_irq
(
tw_dev
->
host
->
host_lock
);
spin_lock
(
&
tw_dev
->
tw_lock
);
goto
tw_ioctl_bail
;
}
else
{
goto
tw_ioctl_retry
;
}
}
spin_lock_irq
(
tw_dev
->
host
->
host_lock
);
spin_lock
(
&
tw_dev
->
tw_lock
);
if
(
signal_pending
(
current
))
{
dprintk
(
KERN_WARNING
"3w-xxxx: scsi%d: tw_ioctl(): Signal pending, aborting ioctl().
\n
"
,
tw_dev
->
host
->
host_no
);
...
...
@@ -1697,7 +1730,7 @@ int tw_ioctl(TW_Device_Extension *tw_dev, int request_id)
if
((
u32
*
)
command_save
->
byte8
.
param
.
sgl
[
i
].
address
!=
NULL
)
{
error
=
copy_to_user
((
u32
*
)
command_save
->
byte8
.
param
.
sgl
[
i
].
address
,
data_ptr
,
command_save
->
byte8
.
param
.
sgl
[
i
].
length
);
if
(
error
)
{
printk
(
KERN_WARNING
"3w-xxxx: scsi%d: Error copying param sglist to userspace.
\n
"
,
tw_dev
->
host
->
host_no
);
d
printk
(
KERN_WARNING
"3w-xxxx: scsi%d: Error copying param sglist to userspace.
\n
"
,
tw_dev
->
host
->
host_no
);
goto
tw_ioctl_bail
;
}
dprintk
(
KERN_WARNING
"3w-xxxx: scsi%d: Copied %ld bytes to pid %d.
\n
"
,
tw_dev
->
host
->
host_no
,
command_save
->
byte8
.
param
.
sgl
[
i
].
length
,
current
->
pid
);
...
...
@@ -1717,7 +1750,7 @@ int tw_ioctl(TW_Device_Extension *tw_dev, int request_id)
if
((
u32
*
)
command_save
->
byte8
.
io
.
sgl
[
i
].
address
!=
NULL
)
{
error
=
copy_to_user
((
u32
*
)
command_save
->
byte8
.
io
.
sgl
[
i
].
address
,
data_ptr
,
command_save
->
byte8
.
io
.
sgl
[
i
].
length
);
if
(
error
)
{
printk
(
KERN_WARNING
"3w-xxxx: scsi%d: Error copying io sglist to userspace.
\n
"
,
tw_dev
->
host
->
host_no
);
d
printk
(
KERN_WARNING
"3w-xxxx: scsi%d: Error copying io sglist to userspace.
\n
"
,
tw_dev
->
host
->
host_no
);
goto
tw_ioctl_bail
;
}
dprintk
(
KERN_WARNING
"3w-xxxx: scsi%d: Copied %ld bytes to pid %d.
\n
"
,
tw_dev
->
host
->
host_no
,
command_save
->
byte8
.
io
.
sgl
[
i
].
length
,
current
->
pid
);
...
...
@@ -1742,6 +1775,7 @@ int tw_ioctl(TW_Device_Extension *tw_dev, int request_id)
/* Now complete the io */
tw_dev
->
state
[
request_id
]
=
TW_S_COMPLETED
;
tw_state_request_finish
(
tw_dev
,
request_id
);
if
(
posted
)
tw_dev
->
posted_request_count
--
;
tw_dev
->
srb
[
request_id
]
->
scsi_done
(
tw_dev
->
srb
[
request_id
]);
return
0
;
...
...
@@ -1818,6 +1852,7 @@ int tw_ioctl_complete(TW_Device_Extension *tw_dev, int request_id)
break
;
case
TW_CMD_PACKET_WITH_DATA
:
dprintk
(
KERN_WARNING
"3w-xxxx: tw_ioctl_complete(): caught TW_CMD_PACKET_WITH_DATA.
\n
"
);
clear_bit
(
TW_IN_IOCTL
,
&
tw_dev
->
flags
);
return
TW_ISR_DONT_COMPLETE
;
/* Special case for isr to not complete io */
default:
memset
(
buff
,
0
,
tw_dev
->
srb
[
request_id
]
->
request_bufflen
);
...
...
@@ -2121,14 +2156,14 @@ int tw_scsi_eh_abort(Scsi_Cmnd *SCpnt)
for
(
i
=
0
;
i
<
TW_Q_LENGTH
;
i
++
)
{
if
(
tw_dev
->
srb
[
i
]
==
SCpnt
)
{
if
(
tw_dev
->
state
[
i
]
==
TW_S_STARTED
)
{
printk
(
KERN_WARNING
"3w-xxxx: scsi%d:
Command (0x%x) timed out.
\n
"
,
tw_dev
->
host
->
host_no
,
(
u32
)
SCpnt
);
printk
(
KERN_WARNING
"3w-xxxx: scsi%d:
Unit #%d: Command (0x%x) timed out.
\n
"
,
tw_dev
->
host
->
host_no
,
tw_dev
->
srb
[
i
]
==
0
?
0
:
tw_dev
->
srb
[
i
]
->
target
,
(
u32
)
SCpnt
);
tw_dev
->
state
[
i
]
=
TW_S_COMPLETED
;
tw_state_request_finish
(
tw_dev
,
i
);
spin_unlock
(
&
tw_dev
->
tw_lock
);
return
(
SUCCESS
);
}
if
(
tw_dev
->
state
[
i
]
==
TW_S_PENDING
)
{
printk
(
KERN_WARNING
"3w-xxxx: scsi%d:
Command (0x%x) timed out.
\n
"
,
tw_dev
->
host
->
host_no
,
(
u32
)
SCpnt
);
printk
(
KERN_WARNING
"3w-xxxx: scsi%d:
Unit #%d: Command (0x%x) timed out.
\n
"
,
tw_dev
->
host
->
host_no
,
tw_dev
->
srb
[
i
]
==
0
?
0
:
tw_dev
->
srb
[
i
]
->
target
,
(
u32
)
SCpnt
);
if
(
tw_dev
->
pending_head
==
TW_Q_LENGTH
-
1
)
{
tw_dev
->
pending_head
=
TW_Q_START
;
}
else
{
...
...
@@ -2142,7 +2177,7 @@ int tw_scsi_eh_abort(Scsi_Cmnd *SCpnt)
}
if
(
tw_dev
->
state
[
i
]
==
TW_S_POSTED
)
{
/* If the command has already been posted, we have to reset the card */
printk
(
KERN_WARNING
"3w-xxxx: scsi%d:
Command (0x%x) timed out, resetting card.
\n
"
,
tw_dev
->
host
->
host_no
,
(
u32
)
SCpnt
);
printk
(
KERN_WARNING
"3w-xxxx: scsi%d:
Unit #%d: Command (0x%x) timed out, resetting card.
\n
"
,
tw_dev
->
host
->
host_no
,
tw_dev
->
srb
[
i
]
==
0
?
0
:
tw_dev
->
srb
[
i
]
->
target
,
(
u32
)
SCpnt
);
/* We have to let AEN requests through before the reset */
spin_unlock
(
&
tw_dev
->
tw_lock
);
spin_unlock_irq
(
tw_dev
->
host
->
host_lock
);
...
...
@@ -2360,6 +2395,11 @@ int tw_scsi_release(struct Scsi_Host *tw_host)
dprintk
(
KERN_NOTICE
"3w-xxxx: tw_scsi_release()
\n
"
);
/* Fake like we just shut down, so notify the card that
* we "shut down cleanly".
*/
tw_halt
(
0
,
0
,
0
);
// parameters aren't actually used
/* Free up the IO region */
release_region
((
tw_dev
->
tw_pci_dev
->
resource
[
0
].
start
),
TW_IO_ADDRESS_RANGE
);
...
...
@@ -2372,11 +2412,6 @@ int tw_scsi_release(struct Scsi_Host *tw_host)
/* Tell kernel scsi-layer we are gone */
scsi_unregister
(
tw_host
);
/* Fake like we just shut down, so notify the card that
* we "shut down cleanly".
*/
tw_halt
(
0
,
0
,
0
);
// parameters aren't actually used
return
0
;
}
/* End tw_scsi_release() */
...
...
drivers/scsi/3w-xxxx.h
View file @
518a6e87
...
...
@@ -60,43 +60,44 @@
/* AEN strings */
static
char
*
tw_aen_string
[]
=
{
"
AEN queue empty"
,
// 0x000
"
Soft reset occurred"
,
// 0x001
"Unit degraded: Unit #"
,
// 0x002
"Controller error"
,
// 0x003
"Rebuild failed: Unit #"
,
// 0x004
"
Rebuild complete: Unit #"
,
// 0x005
"Incomplete unit detected: Unit #"
,
// 0x006
"I
nitialization complete: Unit #"
,
// 0x007
"
Unclean shutdown detected: Unit #"
,
// 0x008
"
ATA port timeout: Port #"
,
// 0x009
"Drive error: Port #"
,
// 0x00A
"
Rebuild started: Unit #"
,
// 0x00B
"I
nitialization started: Unit #"
,
// 0x00C
"Logical unit deleted: Unit #"
,
// 0x00D
"
INFO: AEN queue empty"
,
// 0x000
"
INFO: Soft reset occurred"
,
// 0x001
"
ERROR:
Unit degraded: Unit #"
,
// 0x002
"
ERROR:
Controller error"
,
// 0x003
"
ERROR:
Rebuild failed: Unit #"
,
// 0x004
"
INFO: Rebuild complete: Unit #"
,
// 0x005
"
ERROR:
Incomplete unit detected: Unit #"
,
// 0x006
"I
NFO: Initialization complete: Unit #"
,
// 0x007
"
WARNING: Unclean shutdown detected: Unit #"
,
// 0x008
"
WARNING: ATA port timeout: Port #"
,
// 0x009
"
ERROR:
Drive error: Port #"
,
// 0x00A
"
INFO: Rebuild started: Unit #"
,
// 0x00B
"I
NFO: Initialization started: Unit #"
,
// 0x00C
"
ERROR:
Logical unit deleted: Unit #"
,
// 0x00D
NULL
,
// 0x00E unused
"
SMART threshold exceeded: Port #"
,
// 0x00F
"
WARNING: SMART threshold exceeded: Port #"
,
// 0x00F
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
// 0x010-0x020 unused
"ATA UDMA downgrade: Port #"
,
// 0x021
"ATA UDMA upgrade: Port #"
,
// 0x022
"Sector repair occurred: Port #"
,
// 0x023
"SBUF integrity check failure"
,
// 0x024
"Lost cached write: Port #"
,
// 0x025
"Drive ECC error detected: Port #"
,
// 0x026
"DCB checksum error: Port #"
,
// 0x027
"DCB unsupported version: Port #"
,
// 0x028
"Verify started: Unit #"
,
// 0x029
"Verify failed: Port #"
,
// 0x02A
"Verify complete: Unit #"
,
// 0x02B
"Overwrote bad sector during rebuild: Port #"
,
//0x2C
"Encountered bad sector during rebuild: Port #"
,
//0x2D
"Replacement drive is too small: Port #"
//0x2E
"WARNING: ATA UDMA downgrade: Port #"
,
// 0x021
"WARNING: ATA UDMA upgrade: Port #"
,
// 0x022
"WARNING: Sector repair occurred: Port #"
,
// 0x023
"ERROR: SBUF integrity check failure"
,
// 0x024
"ERROR: Lost cached write: Port #"
,
// 0x025
"ERROR: Drive ECC error detected: Port #"
,
// 0x026
"ERROR: DCB checksum error: Port #"
,
// 0x027
"ERROR: DCB unsupported version: Port #"
,
// 0x028
"INFO: Verify started: Unit #"
,
// 0x029
"ERROR: Verify failed: Port #"
,
// 0x02A
"INFO: Verify complete: Unit #"
,
// 0x02B
"ERROR: Overwrote bad sector during rebuild: Port #"
,
//0x02C
"ERROR: Encountered bad sector during rebuild: Port #"
,
//0x02D
"INFO: Replacement drive is too small: Port #"
,
//0x02E
"WARNING: Verify error: Unit not previously initialized: Unit #"
//0x02F
};
#define TW_AEN_STRING_MAX 0x0
2F
#define TW_AEN_STRING_MAX 0x0
30
/*
Sense key lookup table
...
...
@@ -225,11 +226,13 @@ static unsigned char tw_sense_table[][4] =
#define TW_MAX_AEN_TRIES 100
#define TW_UNIT_ONLINE 1
#define TW_IN_INTR 1
#define TW_IN_IOCTL 2
#define TW_MAX_SECTORS 256
#define TW_AEN_WAIT_TIME 1000
#define TW_IOCTL_WAIT_TIME (1 * HZ)
/* 1 second */
#define TW_ISR_DONT_COMPLETE 2
#define TW_ISR_DONT_RESULT 3
#define TW_IOCTL_TIMEOUT 25
/* 25 seconds */
/* Macros */
#define TW_STATUS_ERRORS(x) \
...
...
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