@@ -195,8 +195,20 @@ struct apple_nvme {
195195
196196 int irq ;
197197 spinlock_t lock ;
198+
199+ /*
200+ * Delayed cache flush handling state
201+ */
202+ struct nvme_ns * flush_ns ;
203+ unsigned long flush_interval ;
204+ unsigned long last_flush ;
205+ struct delayed_work flush_dwork ;
198206};
199207
208+ unsigned int flush_interval = 1000 ;
209+ module_param (flush_interval , uint , 0644 );
210+ MODULE_PARM_DESC (flush_interval , "Grace period in msecs between flushes" );
211+
200212static_assert (sizeof (struct nvme_command ) == 64 );
201213static_assert (sizeof (struct apple_nvmmu_tcb ) == 128 );
202214
@@ -729,6 +741,26 @@ static int apple_nvme_remove_sq(struct apple_nvme *anv)
729741 return nvme_submit_sync_cmd (anv -> ctrl .admin_q , & c , NULL , 0 );
730742}
731743
744+ static bool apple_nvme_delayed_flush (struct apple_nvme * anv , struct nvme_ns * ns ,
745+ struct request * req )
746+ {
747+ if (!anv -> flush_interval || req_op (req ) != REQ_OP_FLUSH )
748+ return false;
749+ if (delayed_work_pending (& anv -> flush_dwork ))
750+ return true;
751+ if (time_before (jiffies , anv -> last_flush + anv -> flush_interval )) {
752+ kblockd_mod_delayed_work_on (WORK_CPU_UNBOUND , & anv -> flush_dwork ,
753+ anv -> flush_interval );
754+ if (WARN_ON_ONCE (anv -> flush_ns && anv -> flush_ns != ns ))
755+ goto out ;
756+ anv -> flush_ns = ns ;
757+ return true;
758+ }
759+ out :
760+ anv -> last_flush = jiffies ;
761+ return false;
762+ }
763+
732764static blk_status_t apple_nvme_queue_rq (struct blk_mq_hw_ctx * hctx ,
733765 const struct blk_mq_queue_data * bd )
734766{
@@ -764,6 +796,12 @@ static blk_status_t apple_nvme_queue_rq(struct blk_mq_hw_ctx *hctx,
764796 }
765797
766798 nvme_start_request (req );
799+
800+ if (apple_nvme_delayed_flush (anv , ns , req )) {
801+ blk_mq_complete_request (req );
802+ return BLK_STS_OK ;
803+ }
804+
767805 apple_nvme_submit_cmd (q , cmnd );
768806 return BLK_STS_OK ;
769807
@@ -1011,25 +1049,37 @@ static void apple_nvme_reset_work(struct work_struct *work)
10111049 ret = apple_rtkit_shutdown (anv -> rtk );
10121050 if (ret )
10131051 goto out ;
1052+
1053+ writel (0 , anv -> mmio_coproc + APPLE_ANS_COPROC_CPU_CONTROL );
10141054 }
10151055
1016- writel (0 , anv -> mmio_coproc + APPLE_ANS_COPROC_CPU_CONTROL );
1056+ /*
1057+ * Only do the soft-reset if the CPU is not running, which means either we
1058+ * or the previous stage shut it down cleanly.
1059+ */
1060+ if (!(readl (anv -> mmio_coproc + APPLE_ANS_COPROC_CPU_CONTROL ) &
1061+ APPLE_ANS_COPROC_CPU_CONTROL_RUN )) {
10171062
1018- ret = reset_control_assert (anv -> reset );
1019- if (ret )
1020- goto out ;
1063+ ret = reset_control_assert (anv -> reset );
1064+ if (ret )
1065+ goto out ;
10211066
1022- ret = apple_rtkit_reinit (anv -> rtk );
1023- if (ret )
1024- goto out ;
1067+ ret = apple_rtkit_reinit (anv -> rtk );
1068+ if (ret )
1069+ goto out ;
10251070
1026- ret = reset_control_deassert (anv -> reset );
1027- if (ret )
1028- goto out ;
1071+ ret = reset_control_deassert (anv -> reset );
1072+ if (ret )
1073+ goto out ;
1074+
1075+ writel (APPLE_ANS_COPROC_CPU_CONTROL_RUN ,
1076+ anv -> mmio_coproc + APPLE_ANS_COPROC_CPU_CONTROL );
1077+
1078+ ret = apple_rtkit_boot (anv -> rtk );
1079+ } else {
1080+ ret = apple_rtkit_wake (anv -> rtk );
1081+ }
10291082
1030- writel (APPLE_ANS_COPROC_CPU_CONTROL_RUN ,
1031- anv -> mmio_coproc + APPLE_ANS_COPROC_CPU_CONTROL );
1032- ret = apple_rtkit_boot (anv -> rtk );
10331083 if (ret ) {
10341084 dev_err (anv -> dev , "ANS did not boot" );
10351085 goto out ;
@@ -1388,6 +1438,28 @@ static void devm_apple_nvme_mempool_destroy(void *data)
13881438 mempool_destroy (data );
13891439}
13901440
1441+ static void apple_nvme_flush_work (struct work_struct * work )
1442+ {
1443+ struct nvme_command c = { };
1444+ struct apple_nvme * anv ;
1445+ struct nvme_ns * ns ;
1446+ int err ;
1447+
1448+ anv = container_of (work , struct apple_nvme , flush_dwork .work );
1449+ ns = anv -> flush_ns ;
1450+ if (WARN_ON_ONCE (!ns ))
1451+ return ;
1452+
1453+ c .common .opcode = nvme_cmd_flush ;
1454+ c .common .nsid = cpu_to_le32 (anv -> flush_ns -> head -> ns_id );
1455+ err = nvme_submit_sync_cmd (ns -> queue , & c , NULL , 0 );
1456+ if (err ) {
1457+ dev_err (anv -> dev , "Deferred flush failed: %d\n" , err );
1458+ } else {
1459+ anv -> last_flush = jiffies ;
1460+ }
1461+ }
1462+
13911463static struct apple_nvme * apple_nvme_alloc (struct platform_device * pdev )
13921464{
13931465 struct device * dev = & pdev -> dev ;
@@ -1518,6 +1590,7 @@ static struct apple_nvme *apple_nvme_alloc(struct platform_device *pdev)
15181590
15191591 return anv ;
15201592put_dev :
1593+ apple_nvme_detach_genpd (anv );
15211594 put_device (anv -> dev );
15221595 return ERR_PTR (ret );
15231596}
@@ -1538,6 +1611,14 @@ static int apple_nvme_probe(struct platform_device *pdev)
15381611 goto out_uninit_ctrl ;
15391612 }
15401613
1614+ if (flush_interval ) {
1615+ anv -> flush_interval = msecs_to_jiffies (flush_interval );
1616+ anv -> flush_ns = NULL ;
1617+ anv -> last_flush = jiffies - anv -> flush_interval ;
1618+ }
1619+
1620+ INIT_DELAYED_WORK (& anv -> flush_dwork , apple_nvme_flush_work );
1621+
15411622 nvme_reset_ctrl (& anv -> ctrl );
15421623 async_schedule (apple_nvme_async_probe , anv );
15431624
@@ -1546,6 +1627,7 @@ static int apple_nvme_probe(struct platform_device *pdev)
15461627out_uninit_ctrl :
15471628 nvme_uninit_ctrl (& anv -> ctrl );
15481629 nvme_put_ctrl (& anv -> ctrl );
1630+ apple_nvme_detach_genpd (anv );
15491631 return ret ;
15501632}
15511633
@@ -1560,19 +1642,26 @@ static void apple_nvme_remove(struct platform_device *pdev)
15601642 apple_nvme_disable (anv , true);
15611643 nvme_uninit_ctrl (& anv -> ctrl );
15621644
1563- if (apple_rtkit_is_running (anv -> rtk ))
1645+ if (apple_rtkit_is_running (anv -> rtk )) {
15641646 apple_rtkit_shutdown (anv -> rtk );
15651647
1648+ writel (0 , anv -> mmio_coproc + APPLE_ANS_COPROC_CPU_CONTROL );
1649+ }
1650+
15661651 apple_nvme_detach_genpd (anv );
15671652}
15681653
15691654static void apple_nvme_shutdown (struct platform_device * pdev )
15701655{
15711656 struct apple_nvme * anv = platform_get_drvdata (pdev );
15721657
1658+ flush_delayed_work (& anv -> flush_dwork );
15731659 apple_nvme_disable (anv , true);
1574- if (apple_rtkit_is_running (anv -> rtk ))
1660+ if (apple_rtkit_is_running (anv -> rtk )) {
15751661 apple_rtkit_shutdown (anv -> rtk );
1662+
1663+ writel (0 , anv -> mmio_coproc + APPLE_ANS_COPROC_CPU_CONTROL );
1664+ }
15761665}
15771666
15781667static int apple_nvme_resume (struct device * dev )
@@ -1589,10 +1678,11 @@ static int apple_nvme_suspend(struct device *dev)
15891678
15901679 apple_nvme_disable (anv , true);
15911680
1592- if (apple_rtkit_is_running (anv -> rtk ))
1681+ if (apple_rtkit_is_running (anv -> rtk )) {
15931682 ret = apple_rtkit_shutdown (anv -> rtk );
15941683
1595- writel (0 , anv -> mmio_coproc + APPLE_ANS_COPROC_CPU_CONTROL );
1684+ writel (0 , anv -> mmio_coproc + APPLE_ANS_COPROC_CPU_CONTROL );
1685+ }
15961686
15971687 return ret ;
15981688}
0 commit comments