diff options
author | Kyungsik Lee <kyungsik.lee@lge.com> | 2012-08-02 20:58:03 -0400 |
---|---|---|
committer | Chris Ball <cjb@laptop.org> | 2012-09-19 04:29:42 -0400 |
commit | 1a41313e7f8c5b724a2e3ff66558dbe811844423 (patch) | |
tree | c6a536fc3288f76049b6301c7c7a4e8ce553e067 | |
parent | 8f63795c60ef5bc3dbfcbf19c1ac64ed79d23c62 (diff) |
mmc: core: Remove bounce buffer in mmc_send_cxd_data()
It is expected that Extended CSD register (the size of this register
is larger than CID/CSD) will be referenced more frequently as more
fields have been added to Extended CSD and it seems that it is not
a good option to double the memory used.
This patch is intended to avoid the use of bounce buffer for reading
Extended CSD register in mmc_send_cxd_data(). It will provide a better
performance gain by removing memcpy() overhead for a half KiB and
a redundant bounce buffer allocated repeatedly at the cost of providing
DMA-capable buffer from upper caller (but on-stack buffer is allowed
with no performance gain).
Signed-off-by: Kyungsik Lee <kyungsik.lee@lge.com>
Reviewed-by: Venkatraman S <svenkatr@ti.com>
Signed-off-by: Chris Ball <cjb@laptop.org>
-rw-r--r-- | drivers/mmc/core/mmc_ops.c | 58 |
1 files changed, 42 insertions, 16 deletions
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 0ed2cc5f35b6..225371a28861 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c | |||
@@ -230,6 +230,10 @@ mmc_send_cxd_native(struct mmc_host *host, u32 arg, u32 *cxd, int opcode) | |||
230 | return 0; | 230 | return 0; |
231 | } | 231 | } |
232 | 232 | ||
233 | /* | ||
234 | * NOTE: void *buf, caller for the buf is required to use DMA-capable | ||
235 | * buffer or on-stack buffer (with some overhead in callee). | ||
236 | */ | ||
233 | static int | 237 | static int |
234 | mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host, | 238 | mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host, |
235 | u32 opcode, void *buf, unsigned len) | 239 | u32 opcode, void *buf, unsigned len) |
@@ -239,13 +243,19 @@ mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host, | |||
239 | struct mmc_data data = {0}; | 243 | struct mmc_data data = {0}; |
240 | struct scatterlist sg; | 244 | struct scatterlist sg; |
241 | void *data_buf; | 245 | void *data_buf; |
246 | int is_on_stack; | ||
242 | 247 | ||
243 | /* dma onto stack is unsafe/nonportable, but callers to this | 248 | is_on_stack = object_is_on_stack(buf); |
244 | * routine normally provide temporary on-stack buffers ... | 249 | if (is_on_stack) { |
245 | */ | 250 | /* |
246 | data_buf = kmalloc(len, GFP_KERNEL); | 251 | * dma onto stack is unsafe/nonportable, but callers to this |
247 | if (data_buf == NULL) | 252 | * routine normally provide temporary on-stack buffers ... |
248 | return -ENOMEM; | 253 | */ |
254 | data_buf = kmalloc(len, GFP_KERNEL); | ||
255 | if (!data_buf) | ||
256 | return -ENOMEM; | ||
257 | } else | ||
258 | data_buf = buf; | ||
249 | 259 | ||
250 | mrq.cmd = &cmd; | 260 | mrq.cmd = &cmd; |
251 | mrq.data = &data; | 261 | mrq.data = &data; |
@@ -280,8 +290,10 @@ mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host, | |||
280 | 290 | ||
281 | mmc_wait_for_req(host, &mrq); | 291 | mmc_wait_for_req(host, &mrq); |
282 | 292 | ||
283 | memcpy(buf, data_buf, len); | 293 | if (is_on_stack) { |
284 | kfree(data_buf); | 294 | memcpy(buf, data_buf, len); |
295 | kfree(data_buf); | ||
296 | } | ||
285 | 297 | ||
286 | if (cmd.error) | 298 | if (cmd.error) |
287 | return cmd.error; | 299 | return cmd.error; |
@@ -294,24 +306,32 @@ mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host, | |||
294 | int mmc_send_csd(struct mmc_card *card, u32 *csd) | 306 | int mmc_send_csd(struct mmc_card *card, u32 *csd) |
295 | { | 307 | { |
296 | int ret, i; | 308 | int ret, i; |
309 | u32 *csd_tmp; | ||
297 | 310 | ||
298 | if (!mmc_host_is_spi(card->host)) | 311 | if (!mmc_host_is_spi(card->host)) |
299 | return mmc_send_cxd_native(card->host, card->rca << 16, | 312 | return mmc_send_cxd_native(card->host, card->rca << 16, |
300 | csd, MMC_SEND_CSD); | 313 | csd, MMC_SEND_CSD); |
301 | 314 | ||
302 | ret = mmc_send_cxd_data(card, card->host, MMC_SEND_CSD, csd, 16); | 315 | csd_tmp = kmalloc(16, GFP_KERNEL); |
316 | if (!csd_tmp) | ||
317 | return -ENOMEM; | ||
318 | |||
319 | ret = mmc_send_cxd_data(card, card->host, MMC_SEND_CSD, csd_tmp, 16); | ||
303 | if (ret) | 320 | if (ret) |
304 | return ret; | 321 | goto err; |
305 | 322 | ||
306 | for (i = 0;i < 4;i++) | 323 | for (i = 0;i < 4;i++) |
307 | csd[i] = be32_to_cpu(csd[i]); | 324 | csd[i] = be32_to_cpu(csd_tmp[i]); |
308 | 325 | ||
309 | return 0; | 326 | err: |
327 | kfree(csd_tmp); | ||
328 | return ret; | ||
310 | } | 329 | } |
311 | 330 | ||
312 | int mmc_send_cid(struct mmc_host *host, u32 *cid) | 331 | int mmc_send_cid(struct mmc_host *host, u32 *cid) |
313 | { | 332 | { |
314 | int ret, i; | 333 | int ret, i; |
334 | u32 *cid_tmp; | ||
315 | 335 | ||
316 | if (!mmc_host_is_spi(host)) { | 336 | if (!mmc_host_is_spi(host)) { |
317 | if (!host->card) | 337 | if (!host->card) |
@@ -320,14 +340,20 @@ int mmc_send_cid(struct mmc_host *host, u32 *cid) | |||
320 | cid, MMC_SEND_CID); | 340 | cid, MMC_SEND_CID); |
321 | } | 341 | } |
322 | 342 | ||
323 | ret = mmc_send_cxd_data(NULL, host, MMC_SEND_CID, cid, 16); | 343 | cid_tmp = kmalloc(16, GFP_KERNEL); |
344 | if (!cid_tmp) | ||
345 | return -ENOMEM; | ||
346 | |||
347 | ret = mmc_send_cxd_data(NULL, host, MMC_SEND_CID, cid_tmp, 16); | ||
324 | if (ret) | 348 | if (ret) |
325 | return ret; | 349 | goto err; |
326 | 350 | ||
327 | for (i = 0;i < 4;i++) | 351 | for (i = 0;i < 4;i++) |
328 | cid[i] = be32_to_cpu(cid[i]); | 352 | cid[i] = be32_to_cpu(cid_tmp[i]); |
329 | 353 | ||
330 | return 0; | 354 | err: |
355 | kfree(cid_tmp); | ||
356 | return ret; | ||
331 | } | 357 | } |
332 | 358 | ||
333 | int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd) | 359 | int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd) |