Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux-elphel
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Commits
Open sidebar
Elphel
linux-elphel
Commits
c6524ce2
Commit
c6524ce2
authored
Dec 19, 2016
by
Mikhail Karpenko
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix incorrect updates of write pointer in disk driver
parent
ad354aec
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
21 additions
and
11 deletions
+21
-11
ahci_elphel.c
src/drivers/ata/ahci_elphel.c
+21
-11
No files found.
src/drivers/ata/ahci_elphel.c
View file @
c6524ce2
...
@@ -178,7 +178,7 @@ static void process_timeout(unsigned long data)
...
@@ -178,7 +178,7 @@ static void process_timeout(unsigned long data)
{
{
struct
elphel_ahci_priv
*
dpriv
=
(
struct
elphel_ahci_priv
*
)
data
;
struct
elphel_ahci_priv
*
dpriv
=
(
struct
elphel_ahci_priv
*
)
data
;
dev_err
(
dpriv
->
dev
,
"AHCI error: command execution timeout, LBA start = 0x%x
\n
"
,
dpriv
->
lba_ptr
.
lba_write
);
dev_err
(
dpriv
->
dev
,
"AHCI error: command execution timeout, LBA start = 0x%
ll
x
\n
"
,
dpriv
->
lba_ptr
.
lba_write
);
set_flag
(
dpriv
,
START_EH
);
set_flag
(
dpriv
,
START_EH
);
}
}
...
@@ -253,6 +253,7 @@ static irqreturn_t elphel_irq_handler(int irq, void * dev_instance)
...
@@ -253,6 +253,7 @@ static irqreturn_t elphel_irq_handler(int irq, void * dev_instance)
if
(
dpriv
->
flags
&
(
START_EH
|
WAIT_EH
))
{
if
(
dpriv
->
flags
&
(
START_EH
|
WAIT_EH
))
{
// tell to EH that the command will be processed in normal way
// tell to EH that the command will be processed in normal way
set_flag
(
dpriv
,
DELAYED_IRQ_RCVD
);
set_flag
(
dpriv
,
DELAYED_IRQ_RCVD
);
wake_up_interruptible
(
&
dpriv
->
eh
.
wait
);
}
else
{
}
else
{
tasklet_schedule
(
&
dpriv
->
bh
);
tasklet_schedule
(
&
dpriv
->
bh
);
}
}
...
@@ -307,9 +308,10 @@ void process_queue(unsigned long data)
...
@@ -307,9 +308,10 @@ void process_queue(unsigned long data)
finish_rec
(
dpriv
);
finish_rec
(
dpriv
);
}
else
{
}
else
{
/* all commands have been processed */
/* all commands have been processed */
spin_lock_irqsave
(
&
dpriv
->
flags_lock
,
irq_flags
);
// spin_lock_irqsave(&dpriv->flags_lock, irq_flags);
dpriv
->
flags
&=
~
DISK_BUSY
;
// dpriv->flags &= ~DISK_BUSY;
spin_unlock_irqrestore
(
&
dpriv
->
flags_lock
,
irq_flags
);
// spin_unlock_irqrestore(&dpriv->flags_lock, irq_flags);
reset_flag
(
dpriv
,
DISK_BUSY
);
}
}
}
}
}
}
...
@@ -1060,15 +1062,19 @@ static inline struct elphel_ahci_priv *dev_get_dpriv(struct device *dev)
...
@@ -1060,15 +1062,19 @@ static inline struct elphel_ahci_priv *dev_get_dpriv(struct device *dev)
/** Process command and return the number of S/G entries mapped */
/** Process command and return the number of S/G entries mapped */
static
int
process_cmd
(
struct
elphel_ahci_priv
*
dpriv
)
static
int
process_cmd
(
struct
elphel_ahci_priv
*
dpriv
)
{
{
unsigned
long
irq_flags
;
struct
fvec
*
cbuff
;
struct
fvec
*
cbuff
;
struct
ata_host
*
host
=
dev_get_drvdata
(
dpriv
->
dev
);
struct
ata_host
*
host
=
dev_get_drvdata
(
dpriv
->
dev
);
struct
ata_port
*
port
=
host
->
ports
[
DEFAULT_PORT_NUM
];
struct
ata_port
*
port
=
host
->
ports
[
DEFAULT_PORT_NUM
];
size_t
max_sz
=
(
MAX_LBA_COUNT
+
1
)
*
PHY_BLOCK_SIZE
;
size_t
max_sz
=
(
MAX_LBA_COUNT
+
1
)
*
PHY_BLOCK_SIZE
;
size_t
rem_sz
=
get_size_from
(
dpriv
->
data_chunks
[
dpriv
->
head_ptr
],
dpriv
->
curr_data_chunk
,
dpriv
->
curr_data_offset
,
EXCLUDE_REM
);
size_t
rem_sz
=
get_size_from
(
dpriv
->
data_chunks
[
dpriv
->
head_ptr
],
dpriv
->
curr_data_chunk
,
dpriv
->
curr_data_offset
,
EXCLUDE_REM
);
dev_dbg
(
dpriv
->
dev
,
"flags = 0x%x
\n
"
,
dpriv
->
flags
);
spin_lock_irqsave
(
&
dpriv
->
flags_lock
,
irq_flags
);
if
(
dpriv
->
flags
&
PROC_CMD
)
if
(
dpriv
->
flags
&
PROC_CMD
)
dpriv
->
lba_ptr
.
lba_write
+=
dpriv
->
lba_ptr
.
wr_count
;
dpriv
->
lba_ptr
.
lba_write
+=
dpriv
->
lba_ptr
.
wr_count
;
dpriv
->
flags
|=
PROC_CMD
;
dpriv
->
flags
|=
PROC_CMD
;
spin_unlock_irqrestore
(
&
dpriv
->
flags_lock
,
irq_flags
);
/* define ATA command to use for current transaction */
/* define ATA command to use for current transaction */
if
((
dpriv
->
lba_ptr
.
lba_write
&
~
ADDR_MASK_28_BIT
)
||
rem_sz
>
max_sz
)
{
if
((
dpriv
->
lba_ptr
.
lba_write
&
~
ADDR_MASK_28_BIT
)
||
rem_sz
>
max_sz
)
{
...
@@ -1102,8 +1108,10 @@ static int process_cmd(struct elphel_ahci_priv *dpriv)
...
@@ -1102,8 +1108,10 @@ static int process_cmd(struct elphel_ahci_priv *dpriv)
static
void
finish_cmd
(
struct
elphel_ahci_priv
*
dpriv
)
static
void
finish_cmd
(
struct
elphel_ahci_priv
*
dpriv
)
{
{
int
all
;
int
all
;
unsigned
long
irq_flags
;
remove_timer
(
dpriv
);
remove_timer
(
dpriv
);
spin_lock_irqsave
(
&
dpriv
->
flags_lock
,
irq_flags
);
dpriv
->
lba_ptr
.
wr_count
=
0
;
dpriv
->
lba_ptr
.
wr_count
=
0
;
if
((
dpriv
->
flags
&
LAST_BLOCK
)
==
0
)
{
if
((
dpriv
->
flags
&
LAST_BLOCK
)
==
0
)
{
all
=
0
;
all
=
0
;
...
@@ -1117,6 +1125,7 @@ static void finish_cmd(struct elphel_ahci_priv *dpriv)
...
@@ -1117,6 +1125,7 @@ static void finish_cmd(struct elphel_ahci_priv *dpriv)
dpriv
->
curr_data_chunk
=
0
;
dpriv
->
curr_data_chunk
=
0
;
dpriv
->
curr_data_offset
=
0
;
dpriv
->
curr_data_offset
=
0
;
dpriv
->
flags
&=
~
PROC_CMD
;
dpriv
->
flags
&=
~
PROC_CMD
;
spin_unlock_irqrestore
(
&
dpriv
->
flags_lock
,
irq_flags
);
}
}
/** Fill free space in REM buffer with 0 and save the remaining data chunk */
/** Fill free space in REM buffer with 0 and save the remaining data chunk */
...
@@ -1244,14 +1253,15 @@ void error_handler(struct elphel_ahci_priv *dpriv)
...
@@ -1244,14 +1253,15 @@ void error_handler(struct elphel_ahci_priv *dpriv)
}
}
rc
=
wait_event_interruptible_timeout
(
dpriv
->
eh
.
wait
,
dpriv
->
flags
&
DELAYED_IRQ_RCVD
,
deadline
);
rc
=
wait_event_interruptible_timeout
(
dpriv
->
eh
.
wait
,
dpriv
->
flags
&
DELAYED_IRQ_RCVD
,
deadline
);
dev_warn
(
dpriv
->
dev
,
"wait_event_interruptible_timeout returned %ld
\n
"
,
rc
);
if
(
!
rc
)
{
if
(
!
rc
)
{
/* interrupt has not been received after more than (DEFAULT_CMD_TIMEOUT + WAIT_IRQ_TIMEOUT) ms,
/* interrupt has not been received after more than (DEFAULT_CMD_TIMEOUT + WAIT_IRQ_TIMEOUT) ms,
* try to recover the link usi
gn
WAIT_IRQ_TIMEOUT value for next deadline
* try to recover the link usi
ng
WAIT_IRQ_TIMEOUT value for next deadline
*/
*/
deadline
=
jiffies
+
msecs_to_jiffies
(
WAIT_IRQ_TIMEOUT
);
deadline
=
jiffies
+
msecs_to_jiffies
(
WAIT_IRQ_TIMEOUT
);
rc
=
ap
->
ops
->
hardreset
(
link
,
&
class
,
deadline
);
rc
=
ap
->
ops
->
hardreset
(
link
,
&
class
,
deadline
);
if
(
!
rc
)
if
(
!
rc
)
dev_err
(
dpriv
->
dev
,
"error: ahci_hardreset returned %d
\n
"
,
rc
);
dev_err
(
dpriv
->
dev
,
"error: ahci_hardreset returned %
l
d
\n
"
,
rc
);
ata_port_wait_eh
(
ap
);
ata_port_wait_eh
(
ap
);
// here we assume that circbuf has not been overrun yet, prepare to repeat current command
// here we assume that circbuf has not been overrun yet, prepare to repeat current command
...
@@ -1272,7 +1282,7 @@ void error_handler(struct elphel_ahci_priv *dpriv)
...
@@ -1272,7 +1282,7 @@ void error_handler(struct elphel_ahci_priv *dpriv)
}
}
dpriv
->
stat
.
last_irq_delay
=
jiffies_to_msecs
(
delay
)
+
DEFAULT_CMD_TIMEOUT
;
dpriv
->
stat
.
last_irq_delay
=
jiffies_to_msecs
(
delay
)
+
DEFAULT_CMD_TIMEOUT
;
dpriv
->
stat
.
stat_ready
=
1
;
dpriv
->
stat
.
stat_ready
=
1
;
dev_warn
(
dpriv
->
dev
,
"late interrupt received, delay is %u ms
\n
"
,
dpriv
->
stat
.
last_irq_delay
);
dev_warn
(
dpriv
->
dev
,
"late interrupt received, delay is %
l
u ms
\n
"
,
dpriv
->
stat
.
last_irq_delay
);
reset_flag
(
dpriv
,
DELAYED_IRQ_RCVD
|
START_EH
);
reset_flag
(
dpriv
,
DELAYED_IRQ_RCVD
|
START_EH
);
}
}
reset_flag
(
dpriv
,
WAIT_EH
);
reset_flag
(
dpriv
,
WAIT_EH
);
...
@@ -1300,7 +1310,7 @@ static ssize_t rawdev_write(struct device *dev, ///< device structure associate
...
@@ -1300,7 +1310,7 @@ static ssize_t rawdev_write(struct device *dev, ///< device structure associate
ssize_t
rcvd
=
0
;
ssize_t
rcvd
=
0
;
bool
proceed
=
false
;
bool
proceed
=
false
;
bool
start_eh
=
false
;
bool
start_eh
=
false
;
unsigned
long
irq_flags
,
n
;
unsigned
long
irq_flags
;
struct
elphel_ahci_priv
*
dpriv
=
dev_get_dpriv
(
dev
);
struct
elphel_ahci_priv
*
dpriv
=
dev_get_dpriv
(
dev
);
struct
frame_data
fdata
;
struct
frame_data
fdata
;
struct
frame_buffers
*
buffs
;
struct
frame_buffers
*
buffs
;
...
@@ -1684,7 +1694,7 @@ static ssize_t timeout_read(struct device *dev, struct device_attribute *attr, c
...
@@ -1684,7 +1694,7 @@ static ssize_t timeout_read(struct device *dev, struct device_attribute *attr, c
return
snprintf
(
buff
,
64
,
"Command execution timeout: %u ms
\n
"
,
dpriv
->
cmd_timeout
);
return
snprintf
(
buff
,
64
,
"Command execution timeout: %u ms
\n
"
,
dpriv
->
cmd_timeout
);
}
}
static
ssize_t
io_error_read
(
struct
device
*
dev
,
struct
device_attribute
s
*
attr
,
char
*
buff
)
static
ssize_t
io_error_read
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buff
)
{
{
struct
elphel_ahci_priv
*
dpriv
=
dev_get_dpriv
(
dev
);
struct
elphel_ahci_priv
*
dpriv
=
dev_get_dpriv
(
dev
);
...
@@ -1706,7 +1716,7 @@ static ssize_t stat_delay_write(struct device *dev, struct device_attribute *att
...
@@ -1706,7 +1716,7 @@ static ssize_t stat_delay_write(struct device *dev, struct device_attribute *att
return
buff_sz
;
return
buff_sz
;
}
}
static
ssize_t
stat_delay_read
(
struct
device
*
dev
,
struct
device_attribute
s
*
attr
,
char
*
buff
)
static
ssize_t
stat_delay_read
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buff
)
{
{
unsigned
int
data
;
unsigned
int
data
;
struct
elphel_ahci_priv
*
dpriv
=
dev_get_dpriv
(
dev
);
struct
elphel_ahci_priv
*
dpriv
=
dev_get_dpriv
(
dev
);
...
@@ -1716,7 +1726,7 @@ static ssize_t stat_delay_read(struct device *dev, struct device_attributes *att
...
@@ -1716,7 +1726,7 @@ static ssize_t stat_delay_read(struct device *dev, struct device_attributes *att
else
else
data
=
0
;
data
=
0
;
return
scnprintf
(
buff
,
"%u
\n
"
,
data
);
return
scnprintf
(
buff
,
20
,
"%u
\n
"
,
data
);
}
}
static
DEVICE_ATTR
(
load_module
,
S_IWUSR
|
S_IWGRP
,
NULL
,
set_load_flag
);
static
DEVICE_ATTR
(
load_module
,
S_IWUSR
|
S_IWGRP
,
NULL
,
set_load_flag
);
...
...
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