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
f2d816ef
Commit
f2d816ef
authored
Apr 12, 2004
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge
bk://bk.arm.linux.org.uk/linux-2.6-pcmcia
into ppc970.osdl.org:/home/torvalds/v2.6/linux
parents
5566c10d
7347d800
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
176 additions
and
124 deletions
+176
-124
drivers/pci/bus.c
drivers/pci/bus.c
+1
-0
drivers/pcmcia/cs.c
drivers/pcmcia/cs.c
+1
-2
drivers/pcmcia/cs_internal.h
drivers/pcmcia/cs_internal.h
+1
-1
drivers/pcmcia/rsrc_mgr.c
drivers/pcmcia/rsrc_mgr.c
+167
-121
include/linux/pci.h
include/linux/pci.h
+6
-0
No files found.
drivers/pci/bus.c
View file @
f2d816ef
...
...
@@ -135,5 +135,6 @@ void pci_enable_bridges(struct pci_bus *bus)
}
}
EXPORT_SYMBOL
(
pci_bus_alloc_resource
);
EXPORT_SYMBOL
(
pci_bus_add_devices
);
EXPORT_SYMBOL
(
pci_enable_bridges
);
drivers/pcmcia/cs.c
View file @
f2d816ef
...
...
@@ -2151,9 +2151,8 @@ static int __init init_pcmcia_cs(void)
{
printk
(
KERN_INFO
"%s
\n
"
,
release
);
printk
(
KERN_INFO
" %s
\n
"
,
options
);
class_register
(
&
pcmcia_socket_class
);
return
0
;
return
class_register
(
&
pcmcia_socket_class
)
;
}
static
void
__exit
exit_pcmcia_cs
(
void
)
...
...
drivers/pcmcia/cs_internal.h
View file @
f2d816ef
...
...
@@ -181,7 +181,7 @@ int copy_memory(memory_handle_t handle, copy_op_t *req);
/* In rsrc_mgr */
void
validate_mem
(
struct
pcmcia_socket
*
s
);
int
find_io_region
(
ioaddr_t
*
base
,
ioaddr_t
num
,
ioaddr_t
align
,
int
find_io_region
(
ioaddr_t
*
base
,
ioaddr_t
num
,
unsigned
long
align
,
char
*
name
,
struct
pcmcia_socket
*
s
);
int
find_mem_region
(
u_long
*
base
,
u_long
num
,
u_long
align
,
int
low
,
char
*
name
,
struct
pcmcia_socket
*
s
);
...
...
drivers/pcmcia/rsrc_mgr.c
View file @
f2d816ef
...
...
@@ -107,44 +107,8 @@ static irq_info_t irq_table[NR_IRQS];
======================================================================*/
static
struct
resource
*
resource_parent
(
unsigned
long
b
,
unsigned
long
n
,
int
flags
,
struct
pci_dev
*
dev
)
{
#ifdef CONFIG_PCI
struct
resource
res
,
*
pr
;
if
(
dev
!=
NULL
)
{
res
.
start
=
b
;
res
.
end
=
b
+
n
-
1
;
res
.
flags
=
flags
;
pr
=
pci_find_parent_resource
(
dev
,
&
res
);
if
(
pr
)
return
pr
;
}
#endif
/* CONFIG_PCI */
if
(
flags
&
IORESOURCE_MEM
)
return
&
iomem_resource
;
return
&
ioport_resource
;
}
/* FIXME: Fundamentally racy. */
static
inline
int
check_io_resource
(
unsigned
long
b
,
unsigned
long
n
,
struct
pci_dev
*
dev
)
{
struct
resource
*
region
;
region
=
__request_region
(
resource_parent
(
b
,
n
,
IORESOURCE_IO
,
dev
),
b
,
n
,
"check_io_resource"
);
if
(
!
region
)
return
-
EBUSY
;
release_resource
(
region
);
kfree
(
region
);
return
0
;
}
static
struct
resource
*
make_resource
(
unsigned
long
b
,
unsigned
long
n
,
int
flags
,
char
*
name
)
static
struct
resource
*
make_resource
(
unsigned
long
b
,
unsigned
long
n
,
int
flags
,
char
*
name
)
{
struct
resource
*
res
=
kmalloc
(
sizeof
(
*
res
),
GFP_KERNEL
);
...
...
@@ -158,34 +122,34 @@ static struct resource *make_resource(unsigned long b, unsigned long n,
return
res
;
}
static
int
request_io_resource
(
unsigned
long
b
,
unsigned
long
n
,
char
*
name
,
struct
pci_dev
*
dev
)
static
struct
resource
*
claim_region
(
struct
pcmcia_socket
*
s
,
unsigned
long
base
,
unsigned
long
size
,
int
type
,
char
*
name
)
{
struct
resource
*
res
=
make_resource
(
b
,
n
,
IORESOURCE_IO
,
name
);
struct
resource
*
pr
=
resource_parent
(
b
,
n
,
IORESOURCE_IO
,
dev
);
int
err
=
-
ENOMEM
;
struct
resource
*
res
,
*
parent
;
parent
=
type
&
IORESOURCE_MEM
?
&
iomem_resource
:
&
ioport_resource
;
res
=
make_resource
(
base
,
size
,
type
|
IORESOURCE_BUSY
,
name
);
if
(
res
)
{
err
=
request_resource
(
pr
,
res
);
if
(
err
)
#ifdef CONFIG_PCI
if
(
s
&&
s
->
cb_dev
)
parent
=
pci_find_parent_resource
(
s
->
cb_dev
,
res
);
#endif
if
(
!
parent
||
request_resource
(
parent
,
res
))
{
kfree
(
res
);
res
=
NULL
;
}
}
return
err
;
return
res
;
}
static
int
request_mem_resource
(
unsigned
long
b
,
unsigned
long
n
,
char
*
name
,
struct
pci_dev
*
dev
)
static
void
free_region
(
struct
resource
*
res
)
{
struct
resource
*
res
=
make_resource
(
b
,
n
,
IORESOURCE_MEM
,
name
);
struct
resource
*
pr
=
resource_parent
(
b
,
n
,
IORESOURCE_MEM
,
dev
);
int
err
=
-
ENOMEM
;
if
(
res
)
{
err
=
request_resource
(
pr
,
res
);
if
(
err
)
kfree
(
res
);
release_resource
(
res
);
kfree
(
res
);
}
return
err
;
}
/*======================================================================
...
...
@@ -261,7 +225,7 @@ static int sub_interval(resource_map_t *map, u_long base, u_long num)
#ifdef CONFIG_PCMCIA_PROBE
static
void
do_io_probe
(
ioaddr_t
base
,
ioaddr_t
num
)
{
struct
resource
*
res
;
ioaddr_t
i
,
j
,
bad
,
any
;
u_char
*
b
,
hole
,
most
;
...
...
@@ -276,11 +240,13 @@ static void do_io_probe(ioaddr_t base, ioaddr_t num)
}
memset
(
b
,
0
,
256
);
for
(
i
=
base
,
most
=
0
;
i
<
base
+
num
;
i
+=
8
)
{
if
(
check_io_resource
(
i
,
8
,
NULL
))
res
=
claim_region
(
NULL
,
i
,
8
,
IORESOURCE_IO
,
"PCMCIA IO probe"
);
if
(
!
res
)
continue
;
hole
=
inb
(
i
);
for
(
j
=
1
;
j
<
8
;
j
++
)
if
(
inb
(
i
+
j
)
!=
hole
)
break
;
free_region
(
res
);
if
((
j
==
8
)
&&
(
++
b
[
hole
]
>
b
[
most
]))
most
=
hole
;
if
(
b
[
most
]
==
127
)
break
;
...
...
@@ -289,10 +255,12 @@ static void do_io_probe(ioaddr_t base, ioaddr_t num)
bad
=
any
=
0
;
for
(
i
=
base
;
i
<
base
+
num
;
i
+=
8
)
{
if
(
check_io_resource
(
i
,
8
,
NULL
))
res
=
claim_region
(
NULL
,
i
,
8
,
IORESOURCE_IO
,
"PCMCIA IO probe"
);
if
(
!
res
)
continue
;
for
(
j
=
0
;
j
<
8
;
j
++
)
if
(
inb
(
i
+
j
)
!=
most
)
break
;
free_region
(
res
);
if
(
j
<
8
)
{
if
(
!
any
)
printk
(
" excluding"
);
...
...
@@ -389,18 +357,16 @@ cis_readable(struct pcmcia_socket *s, unsigned long base, unsigned long size)
cisinfo_t
info1
,
info2
;
int
ret
=
0
;
res1
=
request_mem_region
(
base
,
size
/
2
,
"cs memory probe"
);
res2
=
request_mem_region
(
base
+
size
/
2
,
size
/
2
,
"cs memory probe"
);
res1
=
claim_region
(
s
,
base
,
size
/
2
,
IORESOURCE_MEM
,
"cs memory probe"
);
res2
=
claim_region
(
s
,
base
+
size
/
2
,
size
/
2
,
IORESOURCE_MEM
,
"cs memory probe"
);
if
(
res1
&&
res2
)
{
ret
=
readable
(
s
,
res1
,
&
info1
);
ret
+=
readable
(
s
,
res2
,
&
info2
);
}
if
(
res2
)
release_resource
(
res2
);
if
(
res1
)
release_resource
(
res1
);
free_region
(
res2
);
free_region
(
res1
);
return
(
ret
==
2
)
&&
(
info1
.
Chains
==
info2
.
Chains
);
}
...
...
@@ -411,18 +377,16 @@ checksum_match(struct pcmcia_socket *s, unsigned long base, unsigned long size)
struct
resource
*
res1
,
*
res2
;
int
a
=
-
1
,
b
=
-
1
;
res1
=
request_mem_region
(
base
,
size
/
2
,
"cs memory probe"
);
res2
=
request_mem_region
(
base
+
size
/
2
,
size
/
2
,
"cs memory probe"
);
res1
=
claim_region
(
s
,
base
,
size
/
2
,
IORESOURCE_MEM
,
"cs memory probe"
);
res2
=
claim_region
(
s
,
base
+
size
/
2
,
size
/
2
,
IORESOURCE_MEM
,
"cs memory probe"
);
if
(
res1
&&
res2
)
{
a
=
checksum
(
s
,
res1
);
b
=
checksum
(
s
,
res2
);
}
if
(
res2
)
release_resource
(
res2
);
if
(
res1
)
release_resource
(
res1
);
free_region
(
res2
);
free_region
(
res1
);
return
(
a
==
b
)
&&
(
a
>=
0
);
}
...
...
@@ -553,6 +517,68 @@ void validate_mem(struct pcmcia_socket *s)
#endif
/* CONFIG_PCMCIA_PROBE */
struct
pcmcia_align_data
{
unsigned
long
mask
;
unsigned
long
offset
;
resource_map_t
*
map
;
};
static
void
pcmcia_common_align
(
void
*
align_data
,
struct
resource
*
res
,
unsigned
long
size
,
unsigned
long
align
)
{
struct
pcmcia_align_data
*
data
=
align_data
;
unsigned
long
start
;
/*
* Ensure that we have the correct start address
*/
start
=
(
res
->
start
&
~
data
->
mask
)
+
data
->
offset
;
if
(
start
<
res
->
start
)
start
+=
data
->
mask
+
1
;
res
->
start
=
start
;
}
static
void
pcmcia_align
(
void
*
align_data
,
struct
resource
*
res
,
unsigned
long
size
,
unsigned
long
align
)
{
struct
pcmcia_align_data
*
data
=
align_data
;
resource_map_t
*
m
;
pcmcia_common_align
(
data
,
res
,
size
,
align
);
for
(
m
=
data
->
map
->
next
;
m
!=
data
->
map
;
m
=
m
->
next
)
{
unsigned
long
start
=
m
->
base
;
unsigned
long
end
=
m
->
base
+
m
->
num
;
/*
* If the lower resources are not available, try aligning
* to this entry of the resource database to see if it'll
* fit here.
*/
if
(
res
->
start
<
start
)
{
res
->
start
=
start
;
pcmcia_common_align
(
data
,
res
,
size
,
align
);
}
/*
* If we're above the area which was passed in, there's
* no point proceeding.
*/
if
(
res
->
start
>=
res
->
end
)
break
;
if
((
res
->
start
+
size
)
<=
end
)
break
;
}
/*
* If we failed to find something suitable, ensure we fail.
*/
if
(
m
==
data
->
map
)
res
->
start
=
res
->
end
;
}
/*======================================================================
These find ranges of I/O ports or memory addresses that are not
...
...
@@ -566,69 +592,89 @@ void validate_mem(struct pcmcia_socket *s)
======================================================================*/
int
find_io_region
(
ioaddr_t
*
base
,
ioaddr_t
num
,
ioaddr_t
align
,
int
find_io_region
(
ioaddr_t
*
base
,
ioaddr_t
num
,
unsigned
long
align
,
char
*
name
,
struct
pcmcia_socket
*
s
)
{
ioaddr_t
try
;
resource_map_t
*
m
;
int
ret
=
-
1
;
struct
resource
*
res
=
make_resource
(
0
,
num
,
IORESOURCE_IO
,
name
);
struct
pcmcia_align_data
data
;
unsigned
long
min
=
*
base
;
int
ret
;
down
(
&
rsrc_sem
);
for
(
m
=
io_db
.
next
;
m
!=
&
io_db
;
m
=
m
->
next
)
{
try
=
(
m
->
base
&
~
(
align
-
1
))
+
*
base
;
for
(
try
=
(
try
>=
m
->
base
)
?
try
:
try
+
align
;
(
try
>=
m
->
base
)
&&
(
try
+
num
<=
m
->
base
+
m
->
num
);
try
+=
align
)
{
if
(
request_io_resource
(
try
,
num
,
name
,
s
->
cb_dev
)
==
0
)
{
*
base
=
try
;
ret
=
0
;
goto
out
;
}
if
(
!
align
)
break
;
if
(
align
==
0
)
align
=
0x10000UL
;
data
.
mask
=
align
-
1
;
data
.
offset
=
*
base
&
data
.
mask
;
data
.
map
=
&
io_db
;
#ifdef CONFIG_PCI
if
(
s
->
cb_dev
)
{
ret
=
pci_bus_alloc_resource
(
s
->
cb_dev
->
bus
,
res
,
num
,
1
,
min
,
0
,
pcmcia_align
,
&
data
);
}
else
#endif
{
down
(
&
rsrc_sem
);
ret
=
allocate_resource
(
&
ioport_resource
,
res
,
num
,
min
,
~
0UL
,
0
,
pcmcia_align
,
&
data
);
up
(
&
rsrc_sem
);
}
}
out:
up
(
&
rsrc_sem
);
return
ret
;
if
(
ret
!=
0
)
{
kfree
(
res
);
}
else
{
*
base
=
res
->
start
;
}
return
ret
;
}
int
find_mem_region
(
u_long
*
base
,
u_long
num
,
u_long
align
,
int
low
,
char
*
name
,
struct
pcmcia_socket
*
s
)
{
u_long
try
;
resource_map_t
*
m
;
int
ret
=
-
1
;
struct
resource
*
res
=
make_resource
(
0
,
num
,
IORESOURCE_MEM
,
name
);
struct
pcmcia_align_data
data
;
unsigned
long
min
,
max
;
int
ret
,
i
;
low
=
low
||
!
(
s
->
features
&
SS_CAP_PAGE_REGS
);
low
=
low
||
!
(
s
->
features
&
SS_CAP_PAGE_REGS
);
down
(
&
rsrc_sem
);
while
(
1
)
{
for
(
m
=
mem_db
.
next
;
m
!=
&
mem_db
;
m
=
m
->
next
)
{
/* first pass >1MB, second pass <1MB */
if
((
low
!=
0
)
^
(
m
->
base
<
0x100000
))
continue
;
try
=
(
m
->
base
&
~
(
align
-
1
))
+
*
base
;
for
(
try
=
(
try
>=
m
->
base
)
?
try
:
try
+
align
;
(
try
>=
m
->
base
)
&&
(
try
+
num
<=
m
->
base
+
m
->
num
);
try
+=
align
)
{
if
(
request_mem_resource
(
try
,
num
,
name
,
s
->
cb_dev
)
==
0
)
{
*
base
=
try
;
ret
=
0
;
goto
out
;
data
.
mask
=
align
-
1
;
data
.
offset
=
*
base
&
data
.
mask
;
data
.
map
=
&
mem_db
;
for
(
i
=
0
;
i
<
2
;
i
++
)
{
if
(
low
)
{
max
=
0x100000UL
;
min
=
*
base
<
max
?
*
base
:
0
;
}
else
{
max
=
~
0UL
;
min
=
0x100000UL
+
*
base
;
}
if
(
!
align
)
break
;
}
#ifdef CONFIG_PCI
if
(
s
->
cb_dev
)
{
ret
=
pci_bus_alloc_resource
(
s
->
cb_dev
->
bus
,
res
,
num
,
1
,
min
,
0
,
pcmcia_align
,
&
data
);
}
else
#endif
{
down
(
&
rsrc_sem
);
ret
=
allocate_resource
(
&
iomem_resource
,
res
,
num
,
min
,
max
,
0
,
pcmcia_align
,
&
data
);
up
(
&
rsrc_sem
);
}
if
(
ret
==
0
||
low
)
break
;
low
=
1
;
}
if
(
low
)
break
;
low
++
;
}
out:
up
(
&
rsrc_sem
);
return
ret
;
if
(
ret
!=
0
)
{
kfree
(
res
)
;
}
else
{
*
base
=
res
->
start
;
}
return
ret
;
}
/*======================================================================
...
...
include/linux/pci.h
View file @
f2d816ef
...
...
@@ -676,6 +676,12 @@ int pci_request_region(struct pci_dev *, int, char *);
void
pci_release_region
(
struct
pci_dev
*
,
int
);
/* drivers/pci/bus.c */
int
pci_bus_alloc_resource
(
struct
pci_bus
*
bus
,
struct
resource
*
res
,
unsigned
long
size
,
unsigned
long
align
,
unsigned
long
min
,
unsigned
int
type_mask
,
void
(
*
alignf
)(
void
*
,
struct
resource
*
,
unsigned
long
,
unsigned
long
),
void
*
alignf_data
);
void
pci_enable_bridges
(
struct
pci_bus
*
bus
);
/* New-style probing supporting hot-pluggable devices */
...
...
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