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
251f6b40
Commit
251f6b40
authored
Oct 27, 2004
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge
bk://bk.arm.linux.org.uk/linux-2.6-mmc
into ppc970.osdl.org:/home/torvalds/v2.6/linux
parents
6228bab7
93309015
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
65 additions
and
45 deletions
+65
-45
drivers/mmc/mmc_block.c
drivers/mmc/mmc_block.c
+3
-0
drivers/mmc/mmc_queue.c
drivers/mmc/mmc_queue.c
+20
-4
drivers/mmc/mmc_queue.h
drivers/mmc/mmc_queue.h
+1
-0
drivers/mmc/mmci.c
drivers/mmc/mmci.c
+1
-1
drivers/mmc/mmci.h
drivers/mmc/mmci.h
+2
-6
drivers/mmc/pxamci.c
drivers/mmc/pxamci.c
+34
-33
include/linux/mmc/mmc.h
include/linux/mmc/mmc.h
+4
-1
No files found.
drivers/mmc/mmc_block.c
View file @
251f6b40
...
@@ -200,6 +200,9 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
...
@@ -200,6 +200,9 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
}
}
brq
.
mrq
.
stop
=
brq
.
data
.
blocks
>
1
?
&
brq
.
stop
:
NULL
;
brq
.
mrq
.
stop
=
brq
.
data
.
blocks
>
1
?
&
brq
.
stop
:
NULL
;
brq
.
data
.
sg
=
mq
->
sg
;
brq
.
data
.
sg_len
=
blk_rq_map_sg
(
req
->
q
,
req
,
brq
.
data
.
sg
);
mmc_wait_for_req
(
card
->
host
,
&
brq
.
mrq
);
mmc_wait_for_req
(
card
->
host
,
&
brq
.
mrq
);
if
(
brq
.
cmd
.
error
)
{
if
(
brq
.
cmd
.
error
)
{
printk
(
KERN_ERR
"%s: error %d sending read/write command
\n
"
,
printk
(
KERN_ERR
"%s: error %d sending read/write command
\n
"
,
...
...
drivers/mmc/mmc_queue.c
View file @
251f6b40
...
@@ -80,7 +80,7 @@ static int mmc_queue_thread(void *d)
...
@@ -80,7 +80,7 @@ static int mmc_queue_thread(void *d)
set_current_state
(
TASK_INTERRUPTIBLE
);
set_current_state
(
TASK_INTERRUPTIBLE
);
if
(
!
blk_queue_plugged
(
q
))
if
(
!
blk_queue_plugged
(
q
))
mq
->
req
=
req
=
elv_next_request
(
q
);
mq
->
req
=
req
=
elv_next_request
(
q
);
spin_unlock
(
q
->
queue_lock
);
spin_unlock
_irq
(
q
->
queue_lock
);
if
(
!
req
)
{
if
(
!
req
)
{
if
(
mq
->
flags
&
MMC_QUEUE_EXIT
)
if
(
mq
->
flags
&
MMC_QUEUE_EXIT
)
...
@@ -147,19 +147,31 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock
...
@@ -147,19 +147,31 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock
mq
->
queue
->
queuedata
=
mq
;
mq
->
queue
->
queuedata
=
mq
;
mq
->
req
=
NULL
;
mq
->
req
=
NULL
;
mq
->
sg
=
kmalloc
(
sizeof
(
struct
scatterlist
)
*
host
->
max_phys_segs
,
GFP_KERNEL
);
if
(
!
mq
->
sg
)
{
ret
=
-
ENOMEM
;
goto
cleanup
;
}
init_completion
(
&
mq
->
thread_complete
);
init_completion
(
&
mq
->
thread_complete
);
init_waitqueue_head
(
&
mq
->
thread_wq
);
init_waitqueue_head
(
&
mq
->
thread_wq
);
init_MUTEX
(
&
mq
->
thread_sem
);
init_MUTEX
(
&
mq
->
thread_sem
);
ret
=
kernel_thread
(
mmc_queue_thread
,
mq
,
CLONE_KERNEL
);
ret
=
kernel_thread
(
mmc_queue_thread
,
mq
,
CLONE_KERNEL
);
if
(
ret
<
0
)
{
if
(
ret
>=
0
)
{
blk_cleanup_queue
(
mq
->
queue
);
}
else
{
wait_for_completion
(
&
mq
->
thread_complete
);
wait_for_completion
(
&
mq
->
thread_complete
);
init_completion
(
&
mq
->
thread_complete
);
init_completion
(
&
mq
->
thread_complete
);
ret
=
0
;
ret
=
0
;
goto
out
;
}
}
cleanup:
kfree
(
mq
->
sg
);
mq
->
sg
=
NULL
;
blk_cleanup_queue
(
mq
->
queue
);
out:
return
ret
;
return
ret
;
}
}
EXPORT_SYMBOL
(
mmc_init_queue
);
EXPORT_SYMBOL
(
mmc_init_queue
);
...
@@ -169,6 +181,10 @@ void mmc_cleanup_queue(struct mmc_queue *mq)
...
@@ -169,6 +181,10 @@ void mmc_cleanup_queue(struct mmc_queue *mq)
mq
->
flags
|=
MMC_QUEUE_EXIT
;
mq
->
flags
|=
MMC_QUEUE_EXIT
;
wake_up
(
&
mq
->
thread_wq
);
wake_up
(
&
mq
->
thread_wq
);
wait_for_completion
(
&
mq
->
thread_complete
);
wait_for_completion
(
&
mq
->
thread_complete
);
kfree
(
mq
->
sg
);
mq
->
sg
=
NULL
;
blk_cleanup_queue
(
mq
->
queue
);
blk_cleanup_queue
(
mq
->
queue
);
mq
->
card
=
NULL
;
mq
->
card
=
NULL
;
...
...
drivers/mmc/mmc_queue.h
View file @
251f6b40
...
@@ -15,6 +15,7 @@ struct mmc_queue {
...
@@ -15,6 +15,7 @@ struct mmc_queue {
int
(
*
issue_fn
)(
struct
mmc_queue
*
,
struct
request
*
);
int
(
*
issue_fn
)(
struct
mmc_queue
*
,
struct
request
*
);
void
*
data
;
void
*
data
;
struct
request_queue
*
queue
;
struct
request_queue
*
queue
;
struct
scatterlist
*
sg
;
};
};
struct
mmc_io_request
{
struct
mmc_io_request
{
...
...
drivers/mmc/mmci.c
View file @
251f6b40
...
@@ -501,7 +501,7 @@ static int mmci_probe(struct amba_device *dev, void *id)
...
@@ -501,7 +501,7 @@ static int mmci_probe(struct amba_device *dev, void *id)
* We can do SGIO
* We can do SGIO
*/
*/
mmc
->
max_hw_segs
=
16
;
mmc
->
max_hw_segs
=
16
;
mmc
->
max_phys_segs
=
16
;
mmc
->
max_phys_segs
=
NR_SG
;
/*
/*
* Since we only have a 16-bit data length register, we must
* Since we only have a 16-bit data length register, we must
...
...
drivers/mmc/mmci.h
View file @
251f6b40
...
@@ -139,7 +139,6 @@ struct mmci_host {
...
@@ -139,7 +139,6 @@ struct mmci_host {
struct
timer_list
timer
;
struct
timer_list
timer
;
unsigned
int
oldstat
;
unsigned
int
oldstat
;
struct
scatterlist
sg
[
NR_SG
];
unsigned
int
sg_len
;
unsigned
int
sg_len
;
/* pio stuff */
/* pio stuff */
...
@@ -150,14 +149,11 @@ struct mmci_host {
...
@@ -150,14 +149,11 @@ struct mmci_host {
static
inline
void
mmci_init_sg
(
struct
mmci_host
*
host
,
struct
mmc_data
*
data
)
static
inline
void
mmci_init_sg
(
struct
mmci_host
*
host
,
struct
mmc_data
*
data
)
{
{
struct
scatterlist
*
sg
=
host
->
sg
;
struct
request
*
req
=
data
->
req
;
/*
/*
* Ideally, we want the higher levels to pass us a scatter list.
* Ideally, we want the higher levels to pass us a scatter list.
*/
*/
host
->
sg_len
=
blk_rq_map_sg
(
req
->
q
,
req
,
sg
)
;
host
->
sg_len
=
data
->
sg_len
;
host
->
sg_ptr
=
sg
;
host
->
sg_ptr
=
data
->
sg
;
host
->
sg_off
=
0
;
host
->
sg_off
=
0
;
}
}
...
...
drivers/mmc/pxamci.c
View file @
251f6b40
...
@@ -44,6 +44,10 @@
...
@@ -44,6 +44,10 @@
#define DBG(x...) do { } while (0)
#define DBG(x...) do { } while (0)
#endif
#endif
#define DRIVER_NAME "pxa2xx-mci"
#define NR_SG 1
struct
pxamci_host
{
struct
pxamci_host
{
struct
mmc_host
*
mmc
;
struct
mmc_host
*
mmc
;
spinlock_t
lock
;
spinlock_t
lock
;
...
@@ -63,9 +67,8 @@ struct pxamci_host {
...
@@ -63,9 +67,8 @@ struct pxamci_host {
dma_addr_t
sg_dma
;
dma_addr_t
sg_dma
;
struct
pxa_dma_desc
*
sg_cpu
;
struct
pxa_dma_desc
*
sg_cpu
;
unsigned
int
dma_len
;
dma_addr_t
dma_buf
;
unsigned
int
dma_size
;
unsigned
int
dma_dir
;
unsigned
int
dma_dir
;
};
};
...
@@ -122,10 +125,9 @@ static void pxamci_disable_irq(struct pxamci_host *host, unsigned int mask)
...
@@ -122,10 +125,9 @@ static void pxamci_disable_irq(struct pxamci_host *host, unsigned int mask)
static
void
pxamci_setup_data
(
struct
pxamci_host
*
host
,
struct
mmc_data
*
data
)
static
void
pxamci_setup_data
(
struct
pxamci_host
*
host
,
struct
mmc_data
*
data
)
{
{
unsigned
int
nob
=
data
->
blocks
;
unsigned
int
nob
=
data
->
blocks
;
unsigned
int
timeout
,
size
;
unsigned
int
timeout
;
dma_addr_t
dma
;
u32
dcmd
;
u32
dcmd
;
int
i
;
int
i
,
len
;
host
->
data
=
data
;
host
->
data
=
data
;
...
@@ -152,35 +154,22 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data)
...
@@ -152,35 +154,22 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data)
dcmd
|=
DCMD_BURST32
|
DCMD_WIDTH1
;
dcmd
|=
DCMD_BURST32
|
DCMD_WIDTH1
;
host
->
dma_size
=
data
->
blocks
<<
data
->
blksz_bits
;
host
->
dma_len
=
dma_map_sg
(
mmc_dev
(
host
->
mmc
),
data
->
sg
,
data
->
sg_len
,
host
->
dma_buf
=
dma_map_single
(
mmc_dev
(
host
->
mmc
),
data
->
req
->
buffer
,
host
->
dma_dir
);
host
->
dma_size
,
host
->
dma_dir
);
for
(
i
=
0
,
size
=
host
->
dma_size
,
dma
=
host
->
dma_buf
;
size
;
i
++
)
{
u32
len
=
size
;
if
(
len
>
DCMD_LENGTH
)
len
=
0x1000
;
for
(
i
=
0
;
i
<
host
->
dma_len
;
i
++
)
{
if
(
data
->
flags
&
MMC_DATA_READ
)
{
if
(
data
->
flags
&
MMC_DATA_READ
)
{
host
->
sg_cpu
[
i
].
dsadr
=
host
->
res
->
start
+
MMC_RXFIFO
;
host
->
sg_cpu
[
i
].
dsadr
=
host
->
res
->
start
+
MMC_RXFIFO
;
host
->
sg_cpu
[
i
].
dtadr
=
dma
;
host
->
sg_cpu
[
i
].
dtadr
=
sg_dma_address
(
&
data
->
sg
[
i
])
;
}
else
{
}
else
{
host
->
sg_cpu
[
i
].
dsadr
=
dma
;
host
->
sg_cpu
[
i
].
dsadr
=
sg_dma_address
(
&
data
->
sg
[
i
])
;
host
->
sg_cpu
[
i
].
dtadr
=
host
->
res
->
start
+
MMC_TXFIFO
;
host
->
sg_cpu
[
i
].
dtadr
=
host
->
res
->
start
+
MMC_TXFIFO
;
}
}
host
->
sg_cpu
[
i
].
dcmd
=
dcmd
|
len
;
host
->
sg_cpu
[
i
].
dcmd
=
dcmd
|
sg_dma_len
(
&
data
->
sg
[
i
]);
host
->
sg_cpu
[
i
].
ddadr
=
host
->
sg_dma
+
(
i
+
1
)
*
dma
+=
len
;
sizeof
(
struct
pxa_dma_desc
);
size
-=
len
;
if
(
size
)
{
host
->
sg_cpu
[
i
].
ddadr
=
host
->
sg_dma
+
(
i
+
1
)
*
sizeof
(
struct
pxa_dma_desc
);
}
else
{
host
->
sg_cpu
[
i
].
ddadr
=
DDADR_STOP
;
}
}
}
host
->
sg_cpu
[
host
->
dma_len
-
1
].
ddadr
=
DDADR_STOP
;
wmb
();
wmb
();
DDADR
(
host
->
dma
)
=
host
->
sg_dma
;
DDADR
(
host
->
dma
)
=
host
->
sg_dma
;
...
@@ -276,8 +265,8 @@ static int pxamci_data_done(struct pxamci_host *host, unsigned int stat)
...
@@ -276,8 +265,8 @@ static int pxamci_data_done(struct pxamci_host *host, unsigned int stat)
return
0
;
return
0
;
DCSR
(
host
->
dma
)
=
0
;
DCSR
(
host
->
dma
)
=
0
;
dma_unmap_s
ingle
(
mmc_dev
(
host
->
mmc
),
host
->
dma_buf
,
host
->
dma_size
,
dma_unmap_s
g
(
mmc_dev
(
host
->
mmc
),
data
->
sg
,
host
->
dma_len
,
host
->
dma_dir
);
host
->
dma_dir
);
if
(
stat
&
STAT_READ_TIME_OUT
)
if
(
stat
&
STAT_READ_TIME_OUT
)
data
->
error
=
MMC_ERR_TIMEOUT
;
data
->
error
=
MMC_ERR_TIMEOUT
;
...
@@ -429,7 +418,7 @@ static int pxamci_probe(struct device *dev)
...
@@ -429,7 +418,7 @@ static int pxamci_probe(struct device *dev)
if
(
!
r
||
irq
==
NO_IRQ
)
if
(
!
r
||
irq
==
NO_IRQ
)
return
-
ENXIO
;
return
-
ENXIO
;
r
=
request_mem_region
(
r
->
start
,
SZ_4K
,
"PXAMCI"
);
r
=
request_mem_region
(
r
->
start
,
SZ_4K
,
DRIVER_NAME
);
if
(
!
r
)
if
(
!
r
)
return
-
EBUSY
;
return
-
EBUSY
;
...
@@ -443,6 +432,17 @@ static int pxamci_probe(struct device *dev)
...
@@ -443,6 +432,17 @@ static int pxamci_probe(struct device *dev)
mmc
->
f_min
=
312500
;
mmc
->
f_min
=
312500
;
mmc
->
f_max
=
20000000
;
mmc
->
f_max
=
20000000
;
/*
* We can do SG-DMA, but we don't because we never know how much
* data we successfully wrote to the card.
*/
mmc
->
max_phys_segs
=
NR_SG
;
/*
* Our hardware DMA can handle a maximum of one page per SG entry.
*/
mmc
->
max_seg_size
=
PAGE_SIZE
;
host
=
mmc_priv
(
mmc
);
host
=
mmc_priv
(
mmc
);
host
->
mmc
=
mmc
;
host
->
mmc
=
mmc
;
host
->
dma
=
-
1
;
host
->
dma
=
-
1
;
...
@@ -482,13 +482,14 @@ static int pxamci_probe(struct device *dev)
...
@@ -482,13 +482,14 @@ static int pxamci_probe(struct device *dev)
pxa_gpio_mode
(
GPIO8_MMCCS0_MD
);
pxa_gpio_mode
(
GPIO8_MMCCS0_MD
);
pxa_set_cken
(
CKEN12_MMC
,
1
);
pxa_set_cken
(
CKEN12_MMC
,
1
);
host
->
dma
=
pxa_request_dma
(
"PXAMCI"
,
DMA_PRIO_LOW
,
pxamci_dma_irq
,
host
);
host
->
dma
=
pxa_request_dma
(
DRIVER_NAME
,
DMA_PRIO_LOW
,
pxamci_dma_irq
,
host
);
if
(
host
->
dma
<
0
)
{
if
(
host
->
dma
<
0
)
{
ret
=
-
EBUSY
;
ret
=
-
EBUSY
;
goto
out
;
goto
out
;
}
}
ret
=
request_irq
(
host
->
irq
,
pxamci_irq
,
0
,
"PXAMCI"
,
host
);
ret
=
request_irq
(
host
->
irq
,
pxamci_irq
,
0
,
DRIVER_NAME
,
host
);
if
(
ret
)
if
(
ret
)
goto
out
;
goto
out
;
...
@@ -579,7 +580,7 @@ static int pxamci_resume(struct device *dev, u32 level)
...
@@ -579,7 +580,7 @@ static int pxamci_resume(struct device *dev, u32 level)
#endif
#endif
static
struct
device_driver
pxamci_driver
=
{
static
struct
device_driver
pxamci_driver
=
{
.
name
=
"pxa2xx-mci"
,
.
name
=
DRIVER_NAME
,
.
bus
=
&
platform_bus_type
,
.
bus
=
&
platform_bus_type
,
.
probe
=
pxamci_probe
,
.
probe
=
pxamci_probe
,
.
remove
=
pxamci_remove
,
.
remove
=
pxamci_remove
,
...
...
include/linux/mmc/mmc.h
View file @
251f6b40
...
@@ -57,7 +57,7 @@ struct mmc_data {
...
@@ -57,7 +57,7 @@ struct mmc_data {
unsigned
int
timeout_clks
;
/* data timeout (in clocks) */
unsigned
int
timeout_clks
;
/* data timeout (in clocks) */
unsigned
int
blksz_bits
;
/* data block size */
unsigned
int
blksz_bits
;
/* data block size */
unsigned
int
blocks
;
/* number of blocks */
unsigned
int
blocks
;
/* number of blocks */
struct
request
*
req
;
/* request structure
*/
struct
request
*
req
__attribute__
((
deprecated
));
/* request structure (use the sg list instead)
*/
unsigned
int
error
;
/* data error */
unsigned
int
error
;
/* data error */
unsigned
int
flags
;
unsigned
int
flags
;
...
@@ -69,6 +69,9 @@ struct mmc_data {
...
@@ -69,6 +69,9 @@ struct mmc_data {
struct
mmc_command
*
stop
;
/* stop command */
struct
mmc_command
*
stop
;
/* stop command */
struct
mmc_request
*
mrq
;
/* assoicated request */
struct
mmc_request
*
mrq
;
/* assoicated request */
unsigned
int
sg_len
;
/* size of scatter list */
struct
scatterlist
*
sg
;
/* I/O scatter list */
};
};
struct
mmc_request
{
struct
mmc_request
{
...
...
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