Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux-davinci
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
linux
linux-davinci
Commits
9ee1bea4
Commit
9ee1bea4
authored
Oct 04, 2007
by
Jens Axboe
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
x86-64: update pci-gart iommu to sg helpers
Signed-off-by:
Jens Axboe
<
jens.axboe@oracle.com
>
parent
b922f53b
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
36 additions
and
29 deletions
+36
-29
arch/x86/kernel/pci-gart_64.c
arch/x86/kernel/pci-gart_64.c
+36
-29
No files found.
arch/x86/kernel/pci-gart_64.c
View file @
9ee1bea4
...
@@ -23,6 +23,7 @@
...
@@ -23,6 +23,7 @@
#include <linux/interrupt.h>
#include <linux/interrupt.h>
#include <linux/bitops.h>
#include <linux/bitops.h>
#include <linux/kdebug.h>
#include <linux/kdebug.h>
#include <linux/scatterlist.h>
#include <asm/atomic.h>
#include <asm/atomic.h>
#include <asm/io.h>
#include <asm/io.h>
#include <asm/mtrr.h>
#include <asm/mtrr.h>
...
@@ -278,10 +279,10 @@ static void gart_unmap_single(struct device *dev, dma_addr_t dma_addr,
...
@@ -278,10 +279,10 @@ static void gart_unmap_single(struct device *dev, dma_addr_t dma_addr,
*/
*/
static
void
gart_unmap_sg
(
struct
device
*
dev
,
struct
scatterlist
*
sg
,
int
nents
,
int
dir
)
static
void
gart_unmap_sg
(
struct
device
*
dev
,
struct
scatterlist
*
sg
,
int
nents
,
int
dir
)
{
{
struct
scatterlist
*
s
;
int
i
;
int
i
;
for
(
i
=
0
;
i
<
nents
;
i
++
)
{
for_each_sg
(
sg
,
s
,
nents
,
i
)
{
struct
scatterlist
*
s
=
&
sg
[
i
];
if
(
!
s
->
dma_length
||
!
s
->
length
)
if
(
!
s
->
dma_length
||
!
s
->
length
)
break
;
break
;
gart_unmap_single
(
dev
,
s
->
dma_address
,
s
->
dma_length
,
dir
);
gart_unmap_single
(
dev
,
s
->
dma_address
,
s
->
dma_length
,
dir
);
...
@@ -292,14 +293,14 @@ static void gart_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
...
@@ -292,14 +293,14 @@ static void gart_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
static
int
dma_map_sg_nonforce
(
struct
device
*
dev
,
struct
scatterlist
*
sg
,
static
int
dma_map_sg_nonforce
(
struct
device
*
dev
,
struct
scatterlist
*
sg
,
int
nents
,
int
dir
)
int
nents
,
int
dir
)
{
{
struct
scatterlist
*
s
;
int
i
;
int
i
;
#ifdef CONFIG_IOMMU_DEBUG
#ifdef CONFIG_IOMMU_DEBUG
printk
(
KERN_DEBUG
"dma_map_sg overflow
\n
"
);
printk
(
KERN_DEBUG
"dma_map_sg overflow
\n
"
);
#endif
#endif
for
(
i
=
0
;
i
<
nents
;
i
++
)
{
for_each_sg
(
sg
,
s
,
nents
,
i
)
{
struct
scatterlist
*
s
=
&
sg
[
i
];
unsigned
long
addr
=
page_to_phys
(
s
->
page
)
+
s
->
offset
;
unsigned
long
addr
=
page_to_phys
(
s
->
page
)
+
s
->
offset
;
if
(
nonforced_iommu
(
dev
,
addr
,
s
->
length
))
{
if
(
nonforced_iommu
(
dev
,
addr
,
s
->
length
))
{
addr
=
dma_map_area
(
dev
,
addr
,
s
->
length
,
dir
);
addr
=
dma_map_area
(
dev
,
addr
,
s
->
length
,
dir
);
...
@@ -319,23 +320,23 @@ static int dma_map_sg_nonforce(struct device *dev, struct scatterlist *sg,
...
@@ -319,23 +320,23 @@ static int dma_map_sg_nonforce(struct device *dev, struct scatterlist *sg,
}
}
/* Map multiple scatterlist entries continuous into the first. */
/* Map multiple scatterlist entries continuous into the first. */
static
int
__dma_map_cont
(
struct
scatterlist
*
s
g
,
int
start
,
int
stopat
,
static
int
__dma_map_cont
(
struct
scatterlist
*
s
tart
,
int
nelems
,
struct
scatterlist
*
sout
,
unsigned
long
pages
)
struct
scatterlist
*
sout
,
unsigned
long
pages
)
{
{
unsigned
long
iommu_start
=
alloc_iommu
(
pages
);
unsigned
long
iommu_start
=
alloc_iommu
(
pages
);
unsigned
long
iommu_page
=
iommu_start
;
unsigned
long
iommu_page
=
iommu_start
;
struct
scatterlist
*
s
;
int
i
;
int
i
;
if
(
iommu_start
==
-
1
)
if
(
iommu_start
==
-
1
)
return
-
1
;
return
-
1
;
for
(
i
=
start
;
i
<
stopat
;
i
++
)
{
for_each_sg
(
start
,
s
,
nelems
,
i
)
{
struct
scatterlist
*
s
=
&
sg
[
i
];
unsigned
long
pages
,
addr
;
unsigned
long
pages
,
addr
;
unsigned
long
phys_addr
=
s
->
dma_address
;
unsigned
long
phys_addr
=
s
->
dma_address
;
BUG_ON
(
i
>
start
&&
s
->
offset
);
BUG_ON
(
s
!=
start
&&
s
->
offset
);
if
(
i
==
start
)
{
if
(
s
==
start
)
{
*
sout
=
*
s
;
*
sout
=
*
s
;
sout
->
dma_address
=
iommu_bus_base
;
sout
->
dma_address
=
iommu_bus_base
;
sout
->
dma_address
+=
iommu_page
*
PAGE_SIZE
+
s
->
offset
;
sout
->
dma_address
+=
iommu_page
*
PAGE_SIZE
+
s
->
offset
;
...
@@ -357,17 +358,17 @@ static int __dma_map_cont(struct scatterlist *sg, int start, int stopat,
...
@@ -357,17 +358,17 @@ static int __dma_map_cont(struct scatterlist *sg, int start, int stopat,
return
0
;
return
0
;
}
}
static
inline
int
dma_map_cont
(
struct
scatterlist
*
s
g
,
int
start
,
int
stopat
,
static
inline
int
dma_map_cont
(
struct
scatterlist
*
s
tart
,
int
nelems
,
struct
scatterlist
*
sout
,
struct
scatterlist
*
sout
,
unsigned
long
pages
,
int
need
)
unsigned
long
pages
,
int
need
)
{
{
if
(
!
need
)
{
if
(
!
need
)
{
BUG_ON
(
stopat
-
start
!=
1
);
BUG_ON
(
nelems
!=
1
);
*
sout
=
sg
[
start
];
*
sout
=
*
start
;
sout
->
dma_length
=
s
g
[
start
].
length
;
sout
->
dma_length
=
s
tart
->
length
;
return
0
;
return
0
;
}
}
return
__dma_map_cont
(
s
g
,
start
,
stopat
,
sout
,
pages
);
return
__dma_map_cont
(
s
tart
,
nelems
,
sout
,
pages
);
}
}
/*
/*
...
@@ -381,6 +382,7 @@ int gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
...
@@ -381,6 +382,7 @@ int gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
int
start
;
int
start
;
unsigned
long
pages
=
0
;
unsigned
long
pages
=
0
;
int
need
=
0
,
nextneed
;
int
need
=
0
,
nextneed
;
struct
scatterlist
*
s
,
*
ps
,
*
start_sg
,
*
sgmap
;
if
(
nents
==
0
)
if
(
nents
==
0
)
return
0
;
return
0
;
...
@@ -390,8 +392,9 @@ int gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
...
@@ -390,8 +392,9 @@ int gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
out
=
0
;
out
=
0
;
start
=
0
;
start
=
0
;
for
(
i
=
0
;
i
<
nents
;
i
++
)
{
start_sg
=
sgmap
=
sg
;
struct
scatterlist
*
s
=
&
sg
[
i
];
ps
=
NULL
;
/* shut up gcc */
for_each_sg
(
sg
,
s
,
nents
,
i
)
{
dma_addr_t
addr
=
page_to_phys
(
s
->
page
)
+
s
->
offset
;
dma_addr_t
addr
=
page_to_phys
(
s
->
page
)
+
s
->
offset
;
s
->
dma_address
=
addr
;
s
->
dma_address
=
addr
;
BUG_ON
(
s
->
length
==
0
);
BUG_ON
(
s
->
length
==
0
);
...
@@ -400,29 +403,33 @@ int gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
...
@@ -400,29 +403,33 @@ int gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
/* Handle the previous not yet processed entries */
/* Handle the previous not yet processed entries */
if
(
i
>
start
)
{
if
(
i
>
start
)
{
struct
scatterlist
*
ps
=
&
sg
[
i
-
1
];
/* Can only merge when the last chunk ends on a page
/* Can only merge when the last chunk ends on a page
boundary and the new one doesn't have an offset. */
boundary and the new one doesn't have an offset. */
if
(
!
iommu_merge
||
!
nextneed
||
!
need
||
s
->
offset
||
if
(
!
iommu_merge
||
!
nextneed
||
!
need
||
s
->
offset
||
(
ps
->
offset
+
ps
->
length
)
%
PAGE_SIZE
)
{
(
ps
->
offset
+
ps
->
length
)
%
PAGE_SIZE
)
{
if
(
dma_map_cont
(
s
g
,
start
,
i
,
sg
+
out
,
pages
,
if
(
dma_map_cont
(
s
tart_sg
,
i
-
start
,
sgmap
,
need
)
<
0
)
pages
,
need
)
<
0
)
goto
error
;
goto
error
;
out
++
;
out
++
;
sgmap
=
sg_next
(
sgmap
);
pages
=
0
;
pages
=
0
;
start
=
i
;
start
=
i
;
start_sg
=
s
;
}
}
}
}
need
=
nextneed
;
need
=
nextneed
;
pages
+=
to_pages
(
s
->
offset
,
s
->
length
);
pages
+=
to_pages
(
s
->
offset
,
s
->
length
);
ps
=
s
;
}
}
if
(
dma_map_cont
(
s
g
,
start
,
i
,
sg
+
out
,
pages
,
need
)
<
0
)
if
(
dma_map_cont
(
s
tart_sg
,
i
-
start
,
sgmap
,
pages
,
need
)
<
0
)
goto
error
;
goto
error
;
out
++
;
out
++
;
flush_gart
();
flush_gart
();
if
(
out
<
nents
)
if
(
out
<
nents
)
{
sg
[
out
].
dma_length
=
0
;
sgmap
=
sg_next
(
sgmap
);
sgmap
->
dma_length
=
0
;
}
return
out
;
return
out
;
error:
error:
...
@@ -437,8 +444,8 @@ error:
...
@@ -437,8 +444,8 @@ error:
if
(
panic_on_overflow
)
if
(
panic_on_overflow
)
panic
(
"dma_map_sg: overflow on %lu pages
\n
"
,
pages
);
panic
(
"dma_map_sg: overflow on %lu pages
\n
"
,
pages
);
iommu_full
(
dev
,
pages
<<
PAGE_SHIFT
,
dir
);
iommu_full
(
dev
,
pages
<<
PAGE_SHIFT
,
dir
);
for
(
i
=
0
;
i
<
nents
;
i
++
)
for
_each_sg
(
sg
,
s
,
nents
,
i
)
s
g
[
i
].
dma_address
=
bad_dma_address
;
s
->
dma_address
=
bad_dma_address
;
return
0
;
return
0
;
}
}
...
...
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