221
221
*/
222
222
#define MCODE_BUFF_PER_REQ 256
223
223
224
- /*
225
- * Mark a _pl330_req as free.
226
- * We do it by writing DMAEND as the first instruction
227
- * because no valid request is going to have DMAEND as
228
- * its first instruction to execute.
229
- */
230
- #define MARK_FREE (req ) do { \
231
- _emit_END(0, (req)->mc_cpu); \
232
- (req)->mc_len = 0; \
233
- } while (0)
234
-
235
224
/* If the _pl330_req is available to the client */
236
225
#define IS_FREE (req ) (*((u8 *)((req)->mc_cpu)) == CMD_DMAEND)
237
226
@@ -301,8 +290,10 @@ struct pl330_thread {
301
290
struct pl330_dmac * dmac ;
302
291
/* Only two at a time */
303
292
struct _pl330_req req [2 ];
304
- /* Index of the last submitted request */
293
+ /* Index of the last enqueued request */
305
294
unsigned lstenq ;
295
+ /* Index of the last submitted request or -1 if the DMA is stopped */
296
+ int req_running ;
306
297
};
307
298
308
299
enum pl330_dmac_state {
@@ -778,6 +769,22 @@ static inline void _execute_DBGINSN(struct pl330_thread *thrd,
778
769
writel (0 , regs + DBGCMD );
779
770
}
780
771
772
+ /*
773
+ * Mark a _pl330_req as free.
774
+ * We do it by writing DMAEND as the first instruction
775
+ * because no valid request is going to have DMAEND as
776
+ * its first instruction to execute.
777
+ */
778
+ static void mark_free (struct pl330_thread * thrd , int idx )
779
+ {
780
+ struct _pl330_req * req = & thrd -> req [idx ];
781
+
782
+ _emit_END (0 , req -> mc_cpu );
783
+ req -> mc_len = 0 ;
784
+
785
+ thrd -> req_running = -1 ;
786
+ }
787
+
781
788
static inline u32 _state (struct pl330_thread * thrd )
782
789
{
783
790
void __iomem * regs = thrd -> dmac -> pinfo -> base ;
@@ -836,31 +843,6 @@ static inline u32 _state(struct pl330_thread *thrd)
836
843
}
837
844
}
838
845
839
- /* If the request 'req' of thread 'thrd' is currently active */
840
- static inline bool _req_active (struct pl330_thread * thrd ,
841
- struct _pl330_req * req )
842
- {
843
- void __iomem * regs = thrd -> dmac -> pinfo -> base ;
844
- u32 buf = req -> mc_bus , pc = readl (regs + CPC (thrd -> id ));
845
-
846
- if (IS_FREE (req ))
847
- return false;
848
-
849
- return (pc >= buf && pc <= buf + req -> mc_len ) ? true : false;
850
- }
851
-
852
- /* Returns 0 if the thread is inactive, ID of active req + 1 otherwise */
853
- static inline unsigned _thrd_active (struct pl330_thread * thrd )
854
- {
855
- if (_req_active (thrd , & thrd -> req [0 ]))
856
- return 1 ; /* First req active */
857
-
858
- if (_req_active (thrd , & thrd -> req [1 ]))
859
- return 2 ; /* Second req active */
860
-
861
- return 0 ;
862
- }
863
-
864
846
static void _stop (struct pl330_thread * thrd )
865
847
{
866
848
void __iomem * regs = thrd -> dmac -> pinfo -> base ;
@@ -892,17 +874,22 @@ static bool _trigger(struct pl330_thread *thrd)
892
874
struct _arg_GO go ;
893
875
unsigned ns ;
894
876
u8 insn [6 ] = {0 , 0 , 0 , 0 , 0 , 0 };
877
+ int idx ;
895
878
896
879
/* Return if already ACTIVE */
897
880
if (_state (thrd ) != PL330_STATE_STOPPED )
898
881
return true;
899
882
900
- if (!IS_FREE (& thrd -> req [1 - thrd -> lstenq ]))
901
- req = & thrd -> req [1 - thrd -> lstenq ];
902
- else if (!IS_FREE (& thrd -> req [thrd -> lstenq ]))
903
- req = & thrd -> req [thrd -> lstenq ];
904
- else
905
- req = NULL ;
883
+ idx = 1 - thrd -> lstenq ;
884
+ if (!IS_FREE (& thrd -> req [idx ]))
885
+ req = & thrd -> req [idx ];
886
+ else {
887
+ idx = thrd -> lstenq ;
888
+ if (!IS_FREE (& thrd -> req [idx ]))
889
+ req = & thrd -> req [idx ];
890
+ else
891
+ req = NULL ;
892
+ }
906
893
907
894
/* Return if no request */
908
895
if (!req || !req -> r )
@@ -933,6 +920,8 @@ static bool _trigger(struct pl330_thread *thrd)
933
920
/* Only manager can execute GO */
934
921
_execute_DBGINSN (thrd , insn , true);
935
922
923
+ thrd -> req_running = idx ;
924
+
936
925
return true;
937
926
}
938
927
@@ -1382,8 +1371,8 @@ static void pl330_dotask(unsigned long data)
1382
1371
1383
1372
thrd -> req [0 ].r = NULL ;
1384
1373
thrd -> req [1 ].r = NULL ;
1385
- MARK_FREE ( & thrd -> req [ 0 ] );
1386
- MARK_FREE ( & thrd -> req [ 1 ] );
1374
+ mark_free ( thrd , 0 );
1375
+ mark_free ( thrd , 1 );
1387
1376
1388
1377
/* Clear the reset flag */
1389
1378
pl330 -> dmac_tbd .reset_chan &= ~(1 << i );
@@ -1461,14 +1450,12 @@ int pl330_update(const struct pl330_info *pi)
1461
1450
1462
1451
thrd = & pl330 -> channels [id ];
1463
1452
1464
- active = _thrd_active ( thrd ) ;
1465
- if (! active ) /* Aborted */
1453
+ active = thrd -> req_running ;
1454
+ if (active == -1 ) /* Aborted */
1466
1455
continue ;
1467
1456
1468
- active -= 1 ;
1469
-
1470
1457
rqdone = & thrd -> req [active ];
1471
- MARK_FREE ( rqdone );
1458
+ mark_free ( thrd , active );
1472
1459
1473
1460
/* Get going again ASAP */
1474
1461
_start (thrd );
@@ -1509,7 +1496,7 @@ int pl330_chan_ctrl(void *ch_id, enum pl330_chan_op op)
1509
1496
struct pl330_thread * thrd = ch_id ;
1510
1497
struct pl330_dmac * pl330 ;
1511
1498
unsigned long flags ;
1512
- int ret = 0 , active ;
1499
+ int ret = 0 , active = thrd -> req_running ;
1513
1500
1514
1501
if (!thrd || thrd -> free || thrd -> dmac -> state == DYING )
1515
1502
return - EINVAL ;
@@ -1525,28 +1512,24 @@ int pl330_chan_ctrl(void *ch_id, enum pl330_chan_op op)
1525
1512
1526
1513
thrd -> req [0 ].r = NULL ;
1527
1514
thrd -> req [1 ].r = NULL ;
1528
- MARK_FREE ( & thrd -> req [ 0 ] );
1529
- MARK_FREE ( & thrd -> req [ 1 ] );
1515
+ mark_free ( thrd , 0 );
1516
+ mark_free ( thrd , 1 );
1530
1517
break ;
1531
1518
1532
1519
case PL330_OP_ABORT :
1533
- active = _thrd_active (thrd );
1534
-
1535
1520
/* Make sure the channel is stopped */
1536
1521
_stop (thrd );
1537
1522
1538
1523
/* ABORT is only for the active req */
1539
- if (! active )
1524
+ if (active == -1 )
1540
1525
break ;
1541
1526
1542
- active -- ;
1543
-
1544
1527
thrd -> req [active ].r = NULL ;
1545
- MARK_FREE ( & thrd -> req [ active ] );
1528
+ mark_free ( thrd , active );
1546
1529
1547
1530
/* Start the next */
1548
1531
case PL330_OP_START :
1549
- if (! _thrd_active ( thrd ) && !_start (thrd ))
1532
+ if (( active == -1 ) && !_start (thrd ))
1550
1533
ret = - EIO ;
1551
1534
break ;
1552
1535
@@ -1587,14 +1570,13 @@ int pl330_chan_status(void *ch_id, struct pl330_chanstatus *pstatus)
1587
1570
else
1588
1571
pstatus -> faulting = false;
1589
1572
1590
- active = _thrd_active ( thrd ) ;
1573
+ active = thrd -> req_running ;
1591
1574
1592
- if (! active ) {
1575
+ if (active == -1 ) {
1593
1576
/* Indicate that the thread is not running */
1594
1577
pstatus -> top_req = NULL ;
1595
1578
pstatus -> wait_req = NULL ;
1596
1579
} else {
1597
- active -- ;
1598
1580
pstatus -> top_req = thrd -> req [active ].r ;
1599
1581
pstatus -> wait_req = !IS_FREE (& thrd -> req [1 - active ])
1600
1582
? thrd -> req [1 - active ].r : NULL ;
@@ -1659,9 +1641,9 @@ void *pl330_request_channel(const struct pl330_info *pi)
1659
1641
thrd -> free = false;
1660
1642
thrd -> lstenq = 1 ;
1661
1643
thrd -> req [0 ].r = NULL ;
1662
- MARK_FREE ( & thrd -> req [ 0 ] );
1644
+ mark_free ( thrd , 0 );
1663
1645
thrd -> req [1 ].r = NULL ;
1664
- MARK_FREE ( & thrd -> req [ 1 ] );
1646
+ mark_free ( thrd , 1 );
1665
1647
break ;
1666
1648
}
1667
1649
}
@@ -1767,14 +1749,14 @@ static inline void _reset_thread(struct pl330_thread *thrd)
1767
1749
thrd -> req [0 ].mc_bus = pl330 -> mcode_bus
1768
1750
+ (thrd -> id * pi -> mcbufsz );
1769
1751
thrd -> req [0 ].r = NULL ;
1770
- MARK_FREE ( & thrd -> req [ 0 ] );
1752
+ mark_free ( thrd , 0 );
1771
1753
1772
1754
thrd -> req [1 ].mc_cpu = thrd -> req [0 ].mc_cpu
1773
1755
+ pi -> mcbufsz / 2 ;
1774
1756
thrd -> req [1 ].mc_bus = thrd -> req [0 ].mc_bus
1775
1757
+ pi -> mcbufsz / 2 ;
1776
1758
thrd -> req [1 ].r = NULL ;
1777
- MARK_FREE ( & thrd -> req [ 1 ] );
1759
+ mark_free ( thrd , 1 );
1778
1760
}
1779
1761
1780
1762
static int dmac_alloc_threads (struct pl330_dmac * pl330 )
0 commit comments