2222#include <linux/ioport.h>
2323#include <linux/module.h>
2424#include <linux/platform_device.h>
25- #include <linux/scatterlist.h>
2625#include <linux/seq_file.h>
2726#include <linux/slab.h>
2827#include <linux/stat.h>
@@ -502,8 +501,14 @@ static void dw_mci_submit_data(struct dw_mci *host, struct mmc_data *data)
502501 host -> dir_status = DW_MCI_SEND_STATUS ;
503502
504503 if (dw_mci_submit_data_dma (host , data )) {
504+ int flags = SG_MITER_ATOMIC ;
505+ if (host -> data -> flags & MMC_DATA_READ )
506+ flags |= SG_MITER_TO_SG ;
507+ else
508+ flags |= SG_MITER_FROM_SG ;
509+
510+ sg_miter_start (& host -> sg_miter , data -> sg , data -> sg_len , flags );
505511 host -> sg = data -> sg ;
506- host -> pio_offset = 0 ;
507512 host -> part_buf_start = 0 ;
508513 host -> part_buf_count = 0 ;
509514
@@ -972,6 +977,7 @@ static void dw_mci_tasklet_func(unsigned long priv)
972977 * generates a block interrupt, hence setting
973978 * the scatter-gather pointer to NULL.
974979 */
980+ sg_miter_stop (& host -> sg_miter );
975981 host -> sg = NULL ;
976982 ctrl = mci_readl (host , CTRL );
977983 ctrl |= SDMMC_CTRL_FIFO_RESET ;
@@ -1311,54 +1317,44 @@ static void dw_mci_pull_data(struct dw_mci *host, void *buf, int cnt)
13111317
13121318static void dw_mci_read_data_pio (struct dw_mci * host )
13131319{
1314- struct scatterlist * sg = host -> sg ;
1315- void * buf = sg_virt ( sg ) ;
1316- unsigned int offset = host -> pio_offset ;
1320+ struct sg_mapping_iter * sg_miter = & host -> sg_miter ;
1321+ void * buf ;
1322+ unsigned int offset ;
13171323 struct mmc_data * data = host -> data ;
13181324 int shift = host -> data_shift ;
13191325 u32 status ;
13201326 unsigned int nbytes = 0 , len ;
1327+ unsigned int remain , fcnt ;
13211328
13221329 do {
1323- len = host -> part_buf_count +
1324- (SDMMC_GET_FCNT (mci_readl (host , STATUS )) << shift );
1325- if (offset + len <= sg -> length ) {
1330+ if (!sg_miter_next (sg_miter ))
1331+ goto done ;
1332+
1333+ host -> sg = sg_miter -> __sg ;
1334+ buf = sg_miter -> addr ;
1335+ remain = sg_miter -> length ;
1336+ offset = 0 ;
1337+
1338+ do {
1339+ fcnt = (SDMMC_GET_FCNT (mci_readl (host , STATUS ))
1340+ << shift ) + host -> part_buf_count ;
1341+ len = min (remain , fcnt );
1342+ if (!len )
1343+ break ;
13261344 dw_mci_pull_data (host , (void * )(buf + offset ), len );
1327-
13281345 offset += len ;
13291346 nbytes += len ;
1330-
1331- if (offset == sg -> length ) {
1332- flush_dcache_page (sg_page (sg ));
1333- host -> sg = sg = sg_next (sg );
1334- if (!sg )
1335- goto done ;
1336-
1337- offset = 0 ;
1338- buf = sg_virt (sg );
1339- }
1340- } else {
1341- unsigned int remaining = sg -> length - offset ;
1342- dw_mci_pull_data (host , (void * )(buf + offset ),
1343- remaining );
1344- nbytes += remaining ;
1345-
1346- flush_dcache_page (sg_page (sg ));
1347- host -> sg = sg = sg_next (sg );
1348- if (!sg )
1349- goto done ;
1350-
1351- offset = len - remaining ;
1352- buf = sg_virt (sg );
1353- dw_mci_pull_data (host , buf , offset );
1354- nbytes += offset ;
1355- }
1347+ remain -= len ;
1348+ } while (remain );
1349+ sg_miter -> consumed = offset ;
13561350
13571351 status = mci_readl (host , MINTSTS );
13581352 mci_writel (host , RINTSTS , SDMMC_INT_RXDR );
13591353 if (status & DW_MCI_DATA_ERROR_FLAGS ) {
13601354 host -> data_status = status ;
13611355 data -> bytes_xfered += nbytes ;
1356+ sg_miter_stop (sg_miter );
1357+ host -> sg = NULL ;
13621358 smp_wmb ();
13631359
13641360 set_bit (EVENT_DATA_ERROR , & host -> pending_events );
@@ -1367,65 +1363,66 @@ static void dw_mci_read_data_pio(struct dw_mci *host)
13671363 return ;
13681364 }
13691365 } while (status & SDMMC_INT_RXDR ); /*if the RXDR is ready read again*/
1370- host -> pio_offset = offset ;
13711366 data -> bytes_xfered += nbytes ;
1367+
1368+ if (!remain ) {
1369+ if (!sg_miter_next (sg_miter ))
1370+ goto done ;
1371+ sg_miter -> consumed = 0 ;
1372+ }
1373+ sg_miter_stop (sg_miter );
13721374 return ;
13731375
13741376done :
13751377 data -> bytes_xfered += nbytes ;
1378+ sg_miter_stop (sg_miter );
1379+ host -> sg = NULL ;
13761380 smp_wmb ();
13771381 set_bit (EVENT_XFER_COMPLETE , & host -> pending_events );
13781382}
13791383
13801384static void dw_mci_write_data_pio (struct dw_mci * host )
13811385{
1382- struct scatterlist * sg = host -> sg ;
1383- void * buf = sg_virt ( sg ) ;
1384- unsigned int offset = host -> pio_offset ;
1386+ struct sg_mapping_iter * sg_miter = & host -> sg_miter ;
1387+ void * buf ;
1388+ unsigned int offset ;
13851389 struct mmc_data * data = host -> data ;
13861390 int shift = host -> data_shift ;
13871391 u32 status ;
13881392 unsigned int nbytes = 0 , len ;
1393+ unsigned int fifo_depth = host -> fifo_depth ;
1394+ unsigned int remain , fcnt ;
13891395
13901396 do {
1391- len = ((host -> fifo_depth -
1392- SDMMC_GET_FCNT (mci_readl (host , STATUS ))) << shift )
1393- - host -> part_buf_count ;
1394- if (offset + len <= sg -> length ) {
1397+ if (!sg_miter_next (sg_miter ))
1398+ goto done ;
1399+
1400+ host -> sg = sg_miter -> __sg ;
1401+ buf = sg_miter -> addr ;
1402+ remain = sg_miter -> length ;
1403+ offset = 0 ;
1404+
1405+ do {
1406+ fcnt = ((fifo_depth -
1407+ SDMMC_GET_FCNT (mci_readl (host , STATUS )))
1408+ << shift ) - host -> part_buf_count ;
1409+ len = min (remain , fcnt );
1410+ if (!len )
1411+ break ;
13951412 host -> push_data (host , (void * )(buf + offset ), len );
1396-
13971413 offset += len ;
13981414 nbytes += len ;
1399- if (offset == sg -> length ) {
1400- host -> sg = sg = sg_next (sg );
1401- if (!sg )
1402- goto done ;
1403-
1404- offset = 0 ;
1405- buf = sg_virt (sg );
1406- }
1407- } else {
1408- unsigned int remaining = sg -> length - offset ;
1409-
1410- host -> push_data (host , (void * )(buf + offset ),
1411- remaining );
1412- nbytes += remaining ;
1413-
1414- host -> sg = sg = sg_next (sg );
1415- if (!sg )
1416- goto done ;
1417-
1418- offset = len - remaining ;
1419- buf = sg_virt (sg );
1420- host -> push_data (host , (void * )buf , offset );
1421- nbytes += offset ;
1422- }
1415+ remain -= len ;
1416+ } while (remain );
1417+ sg_miter -> consumed = offset ;
14231418
14241419 status = mci_readl (host , MINTSTS );
14251420 mci_writel (host , RINTSTS , SDMMC_INT_TXDR );
14261421 if (status & DW_MCI_DATA_ERROR_FLAGS ) {
14271422 host -> data_status = status ;
14281423 data -> bytes_xfered += nbytes ;
1424+ sg_miter_stop (sg_miter );
1425+ host -> sg = NULL ;
14291426
14301427 smp_wmb ();
14311428
@@ -1435,12 +1432,20 @@ static void dw_mci_write_data_pio(struct dw_mci *host)
14351432 return ;
14361433 }
14371434 } while (status & SDMMC_INT_TXDR ); /* if TXDR write again */
1438- host -> pio_offset = offset ;
14391435 data -> bytes_xfered += nbytes ;
1436+
1437+ if (!remain ) {
1438+ if (!sg_miter_next (sg_miter ))
1439+ goto done ;
1440+ sg_miter -> consumed = 0 ;
1441+ }
1442+ sg_miter_stop (sg_miter );
14401443 return ;
14411444
14421445done :
14431446 data -> bytes_xfered += nbytes ;
1447+ sg_miter_stop (sg_miter );
1448+ host -> sg = NULL ;
14441449 smp_wmb ();
14451450 set_bit (EVENT_XFER_COMPLETE , & host -> pending_events );
14461451}
@@ -1643,6 +1648,7 @@ static void dw_mci_work_routine_card(struct work_struct *work)
16431648 * block interrupt, hence setting the
16441649 * scatter-gather pointer to NULL.
16451650 */
1651+ sg_miter_stop (& host -> sg_miter );
16461652 host -> sg = NULL ;
16471653
16481654 ctrl = mci_readl (host , CTRL );
0 commit comments