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
Kirill Smelkov
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)
csd
->
capacity
=
(
1
+
m
)
<<
(
e
+
2
);
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
{
/*
* We only understand CSD structure v1.1 and v1.2.
...
...
@@ -579,6 +584,11 @@ static void mmc_decode_csd(struct mmc_card *card)
csd
->
capacity
=
(
1
+
m
)
<<
(
e
+
2
);
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 {
unsigned
int
usage
;
unsigned
int
block_bits
;
unsigned
int
read_only
;
};
static
DECLARE_MUTEX
(
open_lock
);
...
...
@@ -85,12 +86,6 @@ static void mmc_blk_put(struct mmc_blk_data *md)
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
)
{
struct
mmc_blk_data
*
md
;
...
...
@@ -102,8 +97,7 @@ static int mmc_blk_open(struct inode *inode, struct file *filp)
check_disk_change
(
inode
->
i_bdev
);
ret
=
0
;
if
((
filp
->
f_mode
&
FMODE_WRITE
)
&&
mmc_blk_readonly
(
md
->
queue
.
card
))
if
((
filp
->
f_mode
&
FMODE_WRITE
)
&&
md
->
read_only
)
ret
=
-
EROFS
;
}
...
...
@@ -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
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
)
{
struct
mmc_blk_data
*
md
;
...
...
@@ -310,64 +310,121 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
__set_bit
(
devidx
,
dev_use
);
md
=
kmalloc
(
sizeof
(
struct
mmc_blk_data
),
GFP_KERNEL
);
if
(
md
)
{
memset
(
md
,
0
,
sizeof
(
struct
mmc_blk_data
));
if
(
!
md
)
{
ret
=
-
ENOMEM
;
goto
out
;
}
md
->
disk
=
alloc_disk
(
1
<<
MMC_SHIFT
);
if
(
md
->
disk
==
NULL
)
{
kfree
(
md
);
md
=
ERR_PTR
(
-
ENOMEM
);
goto
out
;
}
memset
(
md
,
0
,
sizeof
(
struct
mmc_blk_data
));
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
)
{
put_disk
(
md
->
disk
);
kfree
(
md
);
md
=
ERR_PTR
(
ret
);
goto
out
;
/*
* Figure out a workable block size. MMC cards have:
* - two block sizes, one for read and one for write.
* - may support partial reads and/or writes
* (allows block sizes smaller than specified)
*/
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
;
md
->
disk
->
fops
=
&
mmc_bdops
;
md
->
disk
->
private_data
=
md
;
md
->
disk
->
queue
=
md
->
queue
.
queue
;
md
->
disk
->
driverfs_dev
=
&
card
->
dev
;
/*
* Refuse to allow block sizes smaller than 512 bytes.
*/
if
(
md
->
block_bits
<
9
)
{
printk
(
KERN_ERR
"%s: unable to support block size %u
\n
"
,
mmc_card_id
(
card
),
1
<<
md
->
block_bits
);
ret
=
-
EINVAL
;
goto
err_kfree
;
}
/*
* 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.
*/
md
->
disk
=
alloc_disk
(
1
<<
MMC_SHIFT
);
if
(
md
->
disk
==
NULL
)
{
ret
=
-
ENOMEM
;
goto
err_kfree
;
}
sprintf
(
md
->
disk
->
disk_name
,
"mmcblk%d"
,
devidx
);
sprintf
(
md
->
disk
->
devfs_name
,
"mmc/blk%d"
,
devidx
)
;
spin_lock_init
(
&
md
->
lock
);
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
;
/*
* 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
));
}
out:
md
->
disk
->
major
=
major
;
md
->
disk
->
first_minor
=
devidx
<<
MMC_SHIFT
;
md
->
disk
->
fops
=
&
mmc_bdops
;
md
->
disk
->
private_data
=
md
;
md
->
disk
->
queue
=
md
->
queue
.
queue
;
md
->
disk
->
driverfs_dev
=
&
card
->
dev
;
/*
* 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
;
err_putdisk:
put_disk
(
md
->
disk
);
err_kfree:
kfree
(
md
);
out:
return
ERR_PTR
(
ret
);
}
static
int
...
...
@@ -403,12 +460,6 @@ static int mmc_blk_probe(struct mmc_card *card)
if
(
!
(
card
->
csd
.
cmdclass
&
CCC_BLOCK_READ
))
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
);
if
(
IS_ERR
(
md
))
return
PTR_ERR
(
md
);
...
...
@@ -419,7 +470,7 @@ static int mmc_blk_probe(struct mmc_card *card)
printk
(
KERN_INFO
"%s: %s %s %luKiB %s
\n
"
,
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
);
add_disk
(
md
->
disk
);
...
...
drivers/mmc/mmci.c
View file @
f9c5d045
...
...
@@ -20,6 +20,7 @@
#include <linux/mmc/host.h>
#include <linux/mmc/protocol.h>
#include <asm/cacheflush.h>
#include <asm/div64.h>
#include <asm/io.h>
#include <asm/scatterlist.h>
...
...
@@ -157,6 +158,13 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
else
if
(
status
&
(
MCI_TXUNDERRUN
|
MCI_RXOVERRUN
))
data
->
error
=
MMC_ERR_FIFO
;
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
)
{
mmci_stop_data
(
host
);
...
...
@@ -292,7 +300,7 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id, struct pt_regs *regs)
/*
* Unmap the buffer.
*/
mmci_kunmap_atomic
(
host
,
&
flags
);
mmci_kunmap_atomic
(
host
,
buffer
,
&
flags
);
host
->
sg_off
+=
len
;
host
->
size
-=
len
;
...
...
@@ -301,6 +309,13 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id, struct pt_regs *regs)
if
(
remain
)
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
))
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
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
);
}
drivers/mmc/wbsd.c
View file @
f9c5d045
...
...
@@ -1456,13 +1456,11 @@ static int __devinit wbsd_scan(struct wbsd_host* host)
* Iterate through all ports, all codes to
* 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
))
continue
;
for
(
j
=
0
;
j
<
sizeof
(
unlock_codes
)
/
sizeof
(
int
);
j
++
)
{
for
(
j
=
0
;
j
<
ARRAY_SIZE
(
unlock_codes
);
j
++
)
{
id
=
0xFFFF
;
host
->
config
=
config_ports
[
i
];
...
...
@@ -1478,8 +1476,7 @@ static int __devinit wbsd_scan(struct wbsd_host* 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
])
{
host
->
chip_id
=
id
;
...
...
@@ -2090,10 +2087,20 @@ static int __init wbsd_drv_init(void)
if
(
result
<
0
)
return
result
;
wbsd_device
=
platform_device_register_simple
(
DRIVER_NAME
,
-
1
,
NULL
,
0
);
if
(
IS_ERR
(
wbsd_device
))
return
PTR_ERR
(
wbsd_device
);
wbsd_device
=
platform_device_alloc
(
DRIVER_NAME
,
-
1
);
if
(
!
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
;
...
...
include/linux/mmc/card.h
View file @
f9c5d045
...
...
@@ -30,7 +30,12 @@ struct mmc_csd {
unsigned
int
tacc_ns
;
unsigned
int
max_dtr
;
unsigned
int
read_blkbits
;
unsigned
int
write_blkbits
;
unsigned
int
capacity
;
unsigned
int
read_partial
:
1
,
read_misalign:
1
,
write_partial:
1
,
write_misalign:
1
;
};
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