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
6d66c8d1
Commit
6d66c8d1
authored
Feb 04, 2019
by
Vinod Koul
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'fix/brcm' into fixes
parents
341198ed
9e528c79
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
25 additions
and
45 deletions
+25
-45
drivers/dma/bcm2835-dma.c
drivers/dma/bcm2835-dma.c
+25
-45
No files found.
drivers/dma/bcm2835-dma.c
View file @
6d66c8d1
...
...
@@ -406,38 +406,32 @@ static void bcm2835_dma_fill_cb_chain_with_sg(
}
}
static
int
bcm2835_dma_abort
(
void
__iomem
*
chan_base
)
static
int
bcm2835_dma_abort
(
struct
bcm2835_chan
*
c
)
{
unsigned
long
cs
;
void
__iomem
*
chan_base
=
c
->
chan_base
;
long
int
timeout
=
10000
;
cs
=
readl
(
chan_base
+
BCM2835_DMA_CS
);
if
(
!
(
cs
&
BCM2835_DMA_ACTIVE
))
/*
* A zero control block address means the channel is idle.
* (The ACTIVE flag in the CS register is not a reliable indicator.)
*/
if
(
!
readl
(
chan_base
+
BCM2835_DMA_ADDR
))
return
0
;
/* Write 0 to the active bit - Pause the DMA */
writel
(
0
,
chan_base
+
BCM2835_DMA_CS
);
/* Wait for any current AXI transfer to complete */
while
((
cs
&
BCM2835_DMA_ISPAUSED
)
&&
--
timeout
)
{
while
((
readl
(
chan_base
+
BCM2835_DMA_CS
)
&
BCM2835_DMA_WAITING_FOR_WRITES
)
&&
--
timeout
)
cpu_relax
();
cs
=
readl
(
chan_base
+
BCM2835_DMA_CS
);
}
/*
We'll un-pause when we set of our next DMA
*/
/*
Peripheral might be stuck and fail to signal AXI write responses
*/
if
(
!
timeout
)
return
-
ETIMEDOUT
;
if
(
!
(
cs
&
BCM2835_DMA_ACTIVE
))
return
0
;
/* Terminate the control block chain */
writel
(
0
,
chan_base
+
BCM2835_DMA_NEXTCB
);
/* Abort the whole DMA */
writel
(
BCM2835_DMA_ABORT
|
BCM2835_DMA_ACTIVE
,
chan_base
+
BCM2835_DMA_CS
);
dev_err
(
c
->
vc
.
chan
.
device
->
dev
,
"failed to complete outstanding writes
\n
"
);
writel
(
BCM2835_DMA_RESET
,
chan_base
+
BCM2835_DMA_CS
);
return
0
;
}
...
...
@@ -476,8 +470,15 @@ static irqreturn_t bcm2835_dma_callback(int irq, void *data)
spin_lock_irqsave
(
&
c
->
vc
.
lock
,
flags
);
/* Acknowledge interrupt */
writel
(
BCM2835_DMA_INT
,
c
->
chan_base
+
BCM2835_DMA_CS
);
/*
* Clear the INT flag to receive further interrupts. Keep the channel
* active in case the descriptor is cyclic or in case the client has
* already terminated the descriptor and issued a new one. (May happen
* if this IRQ handler is threaded.) If the channel is finished, it
* will remain idle despite the ACTIVE flag being set.
*/
writel
(
BCM2835_DMA_INT
|
BCM2835_DMA_ACTIVE
,
c
->
chan_base
+
BCM2835_DMA_CS
);
d
=
c
->
desc
;
...
...
@@ -485,11 +486,7 @@ static irqreturn_t bcm2835_dma_callback(int irq, void *data)
if
(
d
->
cyclic
)
{
/* call the cyclic callback */
vchan_cyclic_callback
(
&
d
->
vd
);
/* Keep the DMA engine running */
writel
(
BCM2835_DMA_ACTIVE
,
c
->
chan_base
+
BCM2835_DMA_CS
);
}
else
{
}
else
if
(
!
readl
(
c
->
chan_base
+
BCM2835_DMA_ADDR
))
{
vchan_cookie_complete
(
&
c
->
desc
->
vd
);
bcm2835_dma_start_desc
(
c
);
}
...
...
@@ -779,7 +776,6 @@ static int bcm2835_dma_terminate_all(struct dma_chan *chan)
struct
bcm2835_chan
*
c
=
to_bcm2835_dma_chan
(
chan
);
struct
bcm2835_dmadev
*
d
=
to_bcm2835_dma_dev
(
c
->
vc
.
chan
.
device
);
unsigned
long
flags
;
int
timeout
=
10000
;
LIST_HEAD
(
head
);
spin_lock_irqsave
(
&
c
->
vc
.
lock
,
flags
);
...
...
@@ -789,27 +785,11 @@ static int bcm2835_dma_terminate_all(struct dma_chan *chan)
list_del_init
(
&
c
->
node
);
spin_unlock
(
&
d
->
lock
);
/*
* Stop DMA activity: we assume the callback will not be called
* after bcm_dma_abort() returns (even if it does, it will see
* c->desc is NULL and exit.)
*/
/* stop DMA activity */
if
(
c
->
desc
)
{
vchan_terminate_vdesc
(
&
c
->
desc
->
vd
);
c
->
desc
=
NULL
;
bcm2835_dma_abort
(
c
->
chan_base
);
/* Wait for stopping */
while
(
--
timeout
)
{
if
(
!
(
readl
(
c
->
chan_base
+
BCM2835_DMA_CS
)
&
BCM2835_DMA_ACTIVE
))
break
;
cpu_relax
();
}
if
(
!
timeout
)
dev_err
(
d
->
ddev
.
dev
,
"DMA transfer could not be terminated
\n
"
);
bcm2835_dma_abort
(
c
);
}
vchan_get_all_descriptors
(
&
c
->
vc
,
&
head
);
...
...
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