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
f9c5d045
Commit
f9c5d045
authored
Jan 07, 2006
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge master.kernel.org:/home/rmk/linux-2.6-mmc
parents
d354d9af
f3e2628b
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
163 additions
and
75 deletions
+163
-75
drivers/mmc/mmc.c
drivers/mmc/mmc.c
+10
-0
drivers/mmc/mmc_block.c
drivers/mmc/mmc_block.c
+113
-62
drivers/mmc/mmci.c
drivers/mmc/mmci.c
+16
-1
drivers/mmc/mmci.h
drivers/mmc/mmci.h
+2
-2
drivers/mmc/wbsd.c
drivers/mmc/wbsd.c
+17
-10
include/linux/mmc/card.h
include/linux/mmc/card.h
+5
-0
No files found.
drivers/mmc/mmc.c
View file @
f9c5d045
...
@@ -550,6 +550,11 @@ static void mmc_decode_csd(struct mmc_card *card)
...
@@ -550,6 +550,11 @@ static void mmc_decode_csd(struct mmc_card *card)
csd
->
capacity
=
(
1
+
m
)
<<
(
e
+
2
);
csd
->
capacity
=
(
1
+
m
)
<<
(
e
+
2
);
csd
->
read_blkbits
=
UNSTUFF_BITS
(
resp
,
80
,
4
);
csd
->
read_blkbits
=
UNSTUFF_BITS
(
resp
,
80
,
4
);
csd
->
read_partial
=
UNSTUFF_BITS
(
resp
,
79
,
1
);
csd
->
write_misalign
=
UNSTUFF_BITS
(
resp
,
78
,
1
);
csd
->
read_misalign
=
UNSTUFF_BITS
(
resp
,
77
,
1
);
csd
->
write_blkbits
=
UNSTUFF_BITS
(
resp
,
22
,
4
);
csd
->
write_partial
=
UNSTUFF_BITS
(
resp
,
21
,
1
);
}
else
{
}
else
{
/*
/*
* We only understand CSD structure v1.1 and v1.2.
* We only understand CSD structure v1.1 and v1.2.
...
@@ -579,6 +584,11 @@ static void mmc_decode_csd(struct mmc_card *card)
...
@@ -579,6 +584,11 @@ static void mmc_decode_csd(struct mmc_card *card)
csd
->
capacity
=
(
1
+
m
)
<<
(
e
+
2
);
csd
->
capacity
=
(
1
+
m
)
<<
(
e
+
2
);
csd
->
read_blkbits
=
UNSTUFF_BITS
(
resp
,
80
,
4
);
csd
->
read_blkbits
=
UNSTUFF_BITS
(
resp
,
80
,
4
);
csd
->
read_partial
=
UNSTUFF_BITS
(
resp
,
79
,
1
);
csd
->
write_misalign
=
UNSTUFF_BITS
(
resp
,
78
,
1
);
csd
->
read_misalign
=
UNSTUFF_BITS
(
resp
,
77
,
1
);
csd
->
write_blkbits
=
UNSTUFF_BITS
(
resp
,
22
,
4
);
csd
->
write_partial
=
UNSTUFF_BITS
(
resp
,
21
,
1
);
}
}
}
}
...
...
drivers/mmc/mmc_block.c
View file @
f9c5d045
...
@@ -54,6 +54,7 @@ struct mmc_blk_data {
...
@@ -54,6 +54,7 @@ struct mmc_blk_data {
unsigned
int
usage
;
unsigned
int
usage
;
unsigned
int
block_bits
;
unsigned
int
block_bits
;
unsigned
int
read_only
;
};
};
static
DECLARE_MUTEX
(
open_lock
);
static
DECLARE_MUTEX
(
open_lock
);
...
@@ -85,12 +86,6 @@ static void mmc_blk_put(struct mmc_blk_data *md)
...
@@ -85,12 +86,6 @@ static void mmc_blk_put(struct mmc_blk_data *md)
up
(
&
open_lock
);
up
(
&
open_lock
);
}
}
static
inline
int
mmc_blk_readonly
(
struct
mmc_card
*
card
)
{
return
mmc_card_readonly
(
card
)
||
!
(
card
->
csd
.
cmdclass
&
CCC_BLOCK_WRITE
);
}
static
int
mmc_blk_open
(
struct
inode
*
inode
,
struct
file
*
filp
)
static
int
mmc_blk_open
(
struct
inode
*
inode
,
struct
file
*
filp
)
{
{
struct
mmc_blk_data
*
md
;
struct
mmc_blk_data
*
md
;
...
@@ -102,8 +97,7 @@ static int mmc_blk_open(struct inode *inode, struct file *filp)
...
@@ -102,8 +97,7 @@ static int mmc_blk_open(struct inode *inode, struct file *filp)
check_disk_change
(
inode
->
i_bdev
);
check_disk_change
(
inode
->
i_bdev
);
ret
=
0
;
ret
=
0
;
if
((
filp
->
f_mode
&
FMODE_WRITE
)
&&
if
((
filp
->
f_mode
&
FMODE_WRITE
)
&&
md
->
read_only
)
mmc_blk_readonly
(
md
->
queue
.
card
))
ret
=
-
EROFS
;
ret
=
-
EROFS
;
}
}
...
@@ -299,6 +293,12 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
...
@@ -299,6 +293,12 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
static
unsigned
long
dev_use
[
MMC_NUM_MINORS
/
(
8
*
sizeof
(
unsigned
long
))];
static
unsigned
long
dev_use
[
MMC_NUM_MINORS
/
(
8
*
sizeof
(
unsigned
long
))];
static
inline
int
mmc_blk_readonly
(
struct
mmc_card
*
card
)
{
return
mmc_card_readonly
(
card
)
||
!
(
card
->
csd
.
cmdclass
&
CCC_BLOCK_WRITE
);
}
static
struct
mmc_blk_data
*
mmc_blk_alloc
(
struct
mmc_card
*
card
)
static
struct
mmc_blk_data
*
mmc_blk_alloc
(
struct
mmc_card
*
card
)
{
{
struct
mmc_blk_data
*
md
;
struct
mmc_blk_data
*
md
;
...
@@ -310,64 +310,121 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
...
@@ -310,64 +310,121 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
__set_bit
(
devidx
,
dev_use
);
__set_bit
(
devidx
,
dev_use
);
md
=
kmalloc
(
sizeof
(
struct
mmc_blk_data
),
GFP_KERNEL
);
md
=
kmalloc
(
sizeof
(
struct
mmc_blk_data
),
GFP_KERNEL
);
if
(
md
)
{
if
(
!
md
)
{
memset
(
md
,
0
,
sizeof
(
struct
mmc_blk_data
));
ret
=
-
ENOMEM
;
goto
out
;
}
md
->
disk
=
alloc_disk
(
1
<<
MMC_SHIFT
);
memset
(
md
,
0
,
sizeof
(
struct
mmc_blk_data
));
if
(
md
->
disk
==
NULL
)
{
kfree
(
md
);
md
=
ERR_PTR
(
-
ENOMEM
);
goto
out
;
}
spin_lock_init
(
&
md
->
lock
);
/*
md
->
usage
=
1
;
* Set the read-only status based on the supported commands
* and the write protect switch.
*/
md
->
read_only
=
mmc_blk_readonly
(
card
);
ret
=
mmc_init_queue
(
&
md
->
queue
,
card
,
&
md
->
lock
);
/*
if
(
ret
)
{
* Figure out a workable block size. MMC cards have:
put_disk
(
md
->
disk
);
* - two block sizes, one for read and one for write.
kfree
(
md
);
* - may support partial reads and/or writes
md
=
ERR_PTR
(
ret
);
* (allows block sizes smaller than specified)
goto
out
;
*/
md
->
block_bits
=
card
->
csd
.
read_blkbits
;
if
(
card
->
csd
.
write_blkbits
!=
card
->
csd
.
read_blkbits
)
{
if
(
card
->
csd
.
write_blkbits
<
card
->
csd
.
read_blkbits
&&
card
->
csd
.
read_partial
)
{
/*
* write block size is smaller than read block
* size, but we support partial reads, so choose
* the smaller write block size.
*/
md
->
block_bits
=
card
->
csd
.
write_blkbits
;
}
else
if
(
card
->
csd
.
write_blkbits
>
card
->
csd
.
read_blkbits
&&
card
->
csd
.
write_partial
)
{
/*
* read block size is smaller than write block
* size, but we support partial writes. Use read
* block size.
*/
}
else
{
/*
* We don't support this configuration for writes.
*/
printk
(
KERN_ERR
"%s: unable to select block size for "
"writing (rb%u wb%u rp%u wp%u)
\n
"
,
md
->
disk
->
disk_name
,
1
<<
card
->
csd
.
read_blkbits
,
1
<<
card
->
csd
.
write_blkbits
,
card
->
csd
.
read_partial
,
card
->
csd
.
write_partial
);
md
->
read_only
=
1
;
}
}
md
->
queue
.
prep_fn
=
mmc_blk_prep_rq
;
}
md
->
queue
.
issue_fn
=
mmc_blk_issue_rq
;
md
->
queue
.
data
=
md
;
md
->
disk
->
major
=
major
;
/*
md
->
disk
->
first_minor
=
devidx
<<
MMC_SHIFT
;
* Refuse to allow block sizes smaller than 512 bytes.
md
->
disk
->
fops
=
&
mmc_bdops
;
*/
md
->
disk
->
private_data
=
md
;
if
(
md
->
block_bits
<
9
)
{
md
->
disk
->
queue
=
md
->
queue
.
queue
;
printk
(
KERN_ERR
"%s: unable to support block size %u
\n
"
,
md
->
disk
->
driverfs_dev
=
&
card
->
dev
;
mmc_card_id
(
card
),
1
<<
md
->
block_bits
);
ret
=
-
EINVAL
;
goto
err_kfree
;
}
/*
md
->
disk
=
alloc_disk
(
1
<<
MMC_SHIFT
);
* As discussed on lkml, GENHD_FL_REMOVABLE should:
if
(
md
->
disk
==
NULL
)
{
*
ret
=
-
ENOMEM
;
* - be set for removable media with permanent block devices
goto
err_kfree
;
* - be unset for removable block devices with permanent media
}
*
* Since MMC block devices clearly fall under the second
* case, we do not set GENHD_FL_REMOVABLE. Userspace
* should use the block device creation/destruction hotplug
* messages to tell when the card is present.
*/
sprintf
(
md
->
disk
->
disk_name
,
"mmcblk%d"
,
devidx
);
spin_lock_init
(
&
md
->
lock
);
sprintf
(
md
->
disk
->
devfs_name
,
"mmc/blk%d"
,
devidx
)
;
md
->
usage
=
1
;
md
->
block_bits
=
card
->
csd
.
read_blkbits
;
ret
=
mmc_init_queue
(
&
md
->
queue
,
card
,
&
md
->
lock
);
if
(
ret
)
goto
err_putdisk
;
blk_queue_hardsect_size
(
md
->
queue
.
queue
,
1
<<
md
->
block_bits
);
md
->
queue
.
prep_fn
=
mmc_blk_prep_rq
;
md
->
queue
.
issue_fn
=
mmc_blk_issue_rq
;
md
->
queue
.
data
=
md
;
/*
md
->
disk
->
major
=
major
;
* The CSD capacity field is in units of read_blkbits.
md
->
disk
->
first_minor
=
devidx
<<
MMC_SHIFT
;
* set_capacity takes units of 512 bytes.
md
->
disk
->
fops
=
&
mmc_bdops
;
*/
md
->
disk
->
private_data
=
md
;
set_capacity
(
md
->
disk
,
card
->
csd
.
capacity
<<
(
card
->
csd
.
read_blkbits
-
9
));
md
->
disk
->
queue
=
md
->
queue
.
queue
;
}
md
->
disk
->
driverfs_dev
=
&
card
->
dev
;
out:
/*
* As discussed on lkml, GENHD_FL_REMOVABLE should:
*
* - be set for removable media with permanent block devices
* - be unset for removable block devices with permanent media
*
* Since MMC block devices clearly fall under the second
* case, we do not set GENHD_FL_REMOVABLE. Userspace
* should use the block device creation/destruction hotplug
* messages to tell when the card is present.
*/
sprintf
(
md
->
disk
->
disk_name
,
"mmcblk%d"
,
devidx
);
sprintf
(
md
->
disk
->
devfs_name
,
"mmc/blk%d"
,
devidx
);
blk_queue_hardsect_size
(
md
->
queue
.
queue
,
1
<<
md
->
block_bits
);
/*
* The CSD capacity field is in units of read_blkbits.
* set_capacity takes units of 512 bytes.
*/
set_capacity
(
md
->
disk
,
card
->
csd
.
capacity
<<
(
card
->
csd
.
read_blkbits
-
9
));
return
md
;
return
md
;
err_putdisk:
put_disk
(
md
->
disk
);
err_kfree:
kfree
(
md
);
out:
return
ERR_PTR
(
ret
);
}
}
static
int
static
int
...
@@ -403,12 +460,6 @@ static int mmc_blk_probe(struct mmc_card *card)
...
@@ -403,12 +460,6 @@ static int mmc_blk_probe(struct mmc_card *card)
if
(
!
(
card
->
csd
.
cmdclass
&
CCC_BLOCK_READ
))
if
(
!
(
card
->
csd
.
cmdclass
&
CCC_BLOCK_READ
))
return
-
ENODEV
;
return
-
ENODEV
;
if
(
card
->
csd
.
read_blkbits
<
9
)
{
printk
(
KERN_WARNING
"%s: read blocksize too small (%u)
\n
"
,
mmc_card_id
(
card
),
1
<<
card
->
csd
.
read_blkbits
);
return
-
ENODEV
;
}
md
=
mmc_blk_alloc
(
card
);
md
=
mmc_blk_alloc
(
card
);
if
(
IS_ERR
(
md
))
if
(
IS_ERR
(
md
))
return
PTR_ERR
(
md
);
return
PTR_ERR
(
md
);
...
@@ -419,7 +470,7 @@ static int mmc_blk_probe(struct mmc_card *card)
...
@@ -419,7 +470,7 @@ static int mmc_blk_probe(struct mmc_card *card)
printk
(
KERN_INFO
"%s: %s %s %luKiB %s
\n
"
,
printk
(
KERN_INFO
"%s: %s %s %luKiB %s
\n
"
,
md
->
disk
->
disk_name
,
mmc_card_id
(
card
),
mmc_card_name
(
card
),
md
->
disk
->
disk_name
,
mmc_card_id
(
card
),
mmc_card_name
(
card
),
get_capacity
(
md
->
disk
)
>>
1
,
m
mc_blk_readonly
(
card
)
?
"(ro)"
:
""
);
get_capacity
(
md
->
disk
)
>>
1
,
m
d
->
read_only
?
"(ro)"
:
""
);
mmc_set_drvdata
(
card
,
md
);
mmc_set_drvdata
(
card
,
md
);
add_disk
(
md
->
disk
);
add_disk
(
md
->
disk
);
...
...
drivers/mmc/mmci.c
View file @
f9c5d045
...
@@ -20,6 +20,7 @@
...
@@ -20,6 +20,7 @@
#include <linux/mmc/host.h>
#include <linux/mmc/host.h>
#include <linux/mmc/protocol.h>
#include <linux/mmc/protocol.h>
#include <asm/cacheflush.h>
#include <asm/div64.h>
#include <asm/div64.h>
#include <asm/io.h>
#include <asm/io.h>
#include <asm/scatterlist.h>
#include <asm/scatterlist.h>
...
@@ -157,6 +158,13 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
...
@@ -157,6 +158,13 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
else
if
(
status
&
(
MCI_TXUNDERRUN
|
MCI_RXOVERRUN
))
else
if
(
status
&
(
MCI_TXUNDERRUN
|
MCI_RXOVERRUN
))
data
->
error
=
MMC_ERR_FIFO
;
data
->
error
=
MMC_ERR_FIFO
;
status
|=
MCI_DATAEND
;
status
|=
MCI_DATAEND
;
/*
* We hit an error condition. Ensure that any data
* partially written to a page is properly coherent.
*/
if
(
host
->
sg_len
&&
data
->
flags
&
MMC_DATA_READ
)
flush_dcache_page
(
host
->
sg_ptr
->
page
);
}
}
if
(
status
&
MCI_DATAEND
)
{
if
(
status
&
MCI_DATAEND
)
{
mmci_stop_data
(
host
);
mmci_stop_data
(
host
);
...
@@ -292,7 +300,7 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id, struct pt_regs *regs)
...
@@ -292,7 +300,7 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id, struct pt_regs *regs)
/*
/*
* Unmap the buffer.
* Unmap the buffer.
*/
*/
mmci_kunmap_atomic
(
host
,
&
flags
);
mmci_kunmap_atomic
(
host
,
buffer
,
&
flags
);
host
->
sg_off
+=
len
;
host
->
sg_off
+=
len
;
host
->
size
-=
len
;
host
->
size
-=
len
;
...
@@ -301,6 +309,13 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id, struct pt_regs *regs)
...
@@ -301,6 +309,13 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id, struct pt_regs *regs)
if
(
remain
)
if
(
remain
)
break
;
break
;
/*
* If we were reading, and we have completed this
* page, ensure that the data cache is coherent.
*/
if
(
status
&
MCI_RXACTIVE
)
flush_dcache_page
(
host
->
sg_ptr
->
page
);
if
(
!
mmci_next_sg
(
host
))
if
(
!
mmci_next_sg
(
host
))
break
;
break
;
...
...
drivers/mmc/mmci.h
View file @
f9c5d045
...
@@ -172,8 +172,8 @@ static inline char *mmci_kmap_atomic(struct mmci_host *host, unsigned long *flag
...
@@ -172,8 +172,8 @@ static inline char *mmci_kmap_atomic(struct mmci_host *host, unsigned long *flag
return
kmap_atomic
(
sg
->
page
,
KM_BIO_SRC_IRQ
)
+
sg
->
offset
;
return
kmap_atomic
(
sg
->
page
,
KM_BIO_SRC_IRQ
)
+
sg
->
offset
;
}
}
static
inline
void
mmci_kunmap_atomic
(
struct
mmci_host
*
host
,
unsigned
long
*
flags
)
static
inline
void
mmci_kunmap_atomic
(
struct
mmci_host
*
host
,
void
*
buffer
,
unsigned
long
*
flags
)
{
{
kunmap_atomic
(
host
->
sg_ptr
->
page
,
KM_BIO_SRC_IRQ
);
kunmap_atomic
(
buffer
,
KM_BIO_SRC_IRQ
);
local_irq_restore
(
*
flags
);
local_irq_restore
(
*
flags
);
}
}
drivers/mmc/wbsd.c
View file @
f9c5d045
...
@@ -1456,13 +1456,11 @@ static int __devinit wbsd_scan(struct wbsd_host* host)
...
@@ -1456,13 +1456,11 @@ static int __devinit wbsd_scan(struct wbsd_host* host)
* Iterate through all ports, all codes to
* Iterate through all ports, all codes to
* find hardware that is in our known list.
* find hardware that is in our known list.
*/
*/
for
(
i
=
0
;
i
<
sizeof
(
config_ports
)
/
sizeof
(
int
);
i
++
)
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
config_ports
);
i
++
)
{
{
if
(
!
request_region
(
config_ports
[
i
],
2
,
DRIVER_NAME
))
if
(
!
request_region
(
config_ports
[
i
],
2
,
DRIVER_NAME
))
continue
;
continue
;
for
(
j
=
0
;
j
<
sizeof
(
unlock_codes
)
/
sizeof
(
int
);
j
++
)
for
(
j
=
0
;
j
<
ARRAY_SIZE
(
unlock_codes
);
j
++
)
{
{
id
=
0xFFFF
;
id
=
0xFFFF
;
host
->
config
=
config_ports
[
i
];
host
->
config
=
config_ports
[
i
];
...
@@ -1478,8 +1476,7 @@ static int __devinit wbsd_scan(struct wbsd_host* host)
...
@@ -1478,8 +1476,7 @@ static int __devinit wbsd_scan(struct wbsd_host* host)
wbsd_lock_config
(
host
);
wbsd_lock_config
(
host
);
for
(
k
=
0
;
k
<
sizeof
(
valid_ids
)
/
sizeof
(
int
);
k
++
)
for
(
k
=
0
;
k
<
ARRAY_SIZE
(
valid_ids
);
k
++
)
{
{
if
(
id
==
valid_ids
[
k
])
if
(
id
==
valid_ids
[
k
])
{
{
host
->
chip_id
=
id
;
host
->
chip_id
=
id
;
...
@@ -2090,10 +2087,20 @@ static int __init wbsd_drv_init(void)
...
@@ -2090,10 +2087,20 @@ static int __init wbsd_drv_init(void)
if
(
result
<
0
)
if
(
result
<
0
)
return
result
;
return
result
;
wbsd_device
=
platform_device_register_simple
(
DRIVER_NAME
,
-
1
,
wbsd_device
=
platform_device_alloc
(
DRIVER_NAME
,
-
1
);
NULL
,
0
);
if
(
!
wbsd_device
)
if
(
IS_ERR
(
wbsd_device
))
{
return
PTR_ERR
(
wbsd_device
);
platform_driver_unregister
(
&
wbsd_driver
);
return
-
ENOMEM
;
}
result
=
platform_device_add
(
wbsd_device
);
if
(
result
)
{
platform_device_put
(
wbsd_device
);
platform_driver_unregister
(
&
wbsd_driver
);
return
result
;
}
}
}
return
0
;
return
0
;
...
...
include/linux/mmc/card.h
View file @
f9c5d045
...
@@ -30,7 +30,12 @@ struct mmc_csd {
...
@@ -30,7 +30,12 @@ struct mmc_csd {
unsigned
int
tacc_ns
;
unsigned
int
tacc_ns
;
unsigned
int
max_dtr
;
unsigned
int
max_dtr
;
unsigned
int
read_blkbits
;
unsigned
int
read_blkbits
;
unsigned
int
write_blkbits
;
unsigned
int
capacity
;
unsigned
int
capacity
;
unsigned
int
read_partial
:
1
,
read_misalign:
1
,
write_partial:
1
,
write_misalign:
1
;
};
};
struct
sd_scr
{
struct
sd_scr
{
...
...
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