Skip to content

Commit 7a01ce6

Browse files
committed
Merge branch 'bits/050-nvme' into asahi-wip
2 parents 287060f + 64364dd commit 7a01ce6

1 file changed

Lines changed: 105 additions & 17 deletions

File tree

drivers/nvme/host/apple.c

Lines changed: 105 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
200212
static_assert(sizeof(struct nvme_command) == 64);
201213
static_assert(sizeof(struct apple_nvmmu_tcb) == 128);
202214

@@ -730,6 +742,26 @@ static int apple_nvme_remove_sq(struct apple_nvme *anv)
730742
return nvme_submit_sync_cmd(anv->ctrl.admin_q, &c, NULL, 0);
731743
}
732744

745+
static bool apple_nvme_delayed_flush(struct apple_nvme *anv, struct nvme_ns *ns,
746+
struct request *req)
747+
{
748+
if (!anv->flush_interval || req_op(req) != REQ_OP_FLUSH)
749+
return false;
750+
if (delayed_work_pending(&anv->flush_dwork))
751+
return true;
752+
if (time_before(jiffies, anv->last_flush + anv->flush_interval)) {
753+
kblockd_mod_delayed_work_on(WORK_CPU_UNBOUND, &anv->flush_dwork,
754+
anv->flush_interval);
755+
if (WARN_ON_ONCE(anv->flush_ns && anv->flush_ns != ns))
756+
goto out;
757+
anv->flush_ns = ns;
758+
return true;
759+
}
760+
out:
761+
anv->last_flush = jiffies;
762+
return false;
763+
}
764+
733765
static blk_status_t apple_nvme_queue_rq(struct blk_mq_hw_ctx *hctx,
734766
const struct blk_mq_queue_data *bd)
735767
{
@@ -765,6 +797,12 @@ static blk_status_t apple_nvme_queue_rq(struct blk_mq_hw_ctx *hctx,
765797
}
766798

767799
nvme_start_request(req);
800+
801+
if (apple_nvme_delayed_flush(anv, ns, req)) {
802+
blk_mq_complete_request(req);
803+
return BLK_STS_OK;
804+
}
805+
768806
apple_nvme_submit_cmd(q, cmnd);
769807
return BLK_STS_OK;
770808

@@ -1012,25 +1050,37 @@ static void apple_nvme_reset_work(struct work_struct *work)
10121050
ret = apple_rtkit_shutdown(anv->rtk);
10131051
if (ret)
10141052
goto out;
1053+
1054+
writel(0, anv->mmio_coproc + APPLE_ANS_COPROC_CPU_CONTROL);
10151055
}
10161056

1017-
writel(0, anv->mmio_coproc + APPLE_ANS_COPROC_CPU_CONTROL);
1057+
/*
1058+
* Only do the soft-reset if the CPU is not running, which means either we
1059+
* or the previous stage shut it down cleanly.
1060+
*/
1061+
if (!(readl(anv->mmio_coproc + APPLE_ANS_COPROC_CPU_CONTROL) &
1062+
APPLE_ANS_COPROC_CPU_CONTROL_RUN)) {
10181063

1019-
ret = reset_control_assert(anv->reset);
1020-
if (ret)
1021-
goto out;
1064+
ret = reset_control_assert(anv->reset);
1065+
if (ret)
1066+
goto out;
10221067

1023-
ret = apple_rtkit_reinit(anv->rtk);
1024-
if (ret)
1025-
goto out;
1068+
ret = apple_rtkit_reinit(anv->rtk);
1069+
if (ret)
1070+
goto out;
10261071

1027-
ret = reset_control_deassert(anv->reset);
1028-
if (ret)
1029-
goto out;
1072+
ret = reset_control_deassert(anv->reset);
1073+
if (ret)
1074+
goto out;
1075+
1076+
writel(APPLE_ANS_COPROC_CPU_CONTROL_RUN,
1077+
anv->mmio_coproc + APPLE_ANS_COPROC_CPU_CONTROL);
1078+
1079+
ret = apple_rtkit_boot(anv->rtk);
1080+
} else {
1081+
ret = apple_rtkit_wake(anv->rtk);
1082+
}
10301083

1031-
writel(APPLE_ANS_COPROC_CPU_CONTROL_RUN,
1032-
anv->mmio_coproc + APPLE_ANS_COPROC_CPU_CONTROL);
1033-
ret = apple_rtkit_boot(anv->rtk);
10341084
if (ret) {
10351085
dev_err(anv->dev, "ANS did not boot");
10361086
goto out;
@@ -1389,6 +1439,28 @@ static void devm_apple_nvme_mempool_destroy(void *data)
13891439
mempool_destroy(data);
13901440
}
13911441

1442+
static void apple_nvme_flush_work(struct work_struct *work)
1443+
{
1444+
struct nvme_command c = { };
1445+
struct apple_nvme *anv;
1446+
struct nvme_ns *ns;
1447+
int err;
1448+
1449+
anv = container_of(work, struct apple_nvme, flush_dwork.work);
1450+
ns = anv->flush_ns;
1451+
if (WARN_ON_ONCE(!ns))
1452+
return;
1453+
1454+
c.common.opcode = nvme_cmd_flush;
1455+
c.common.nsid = cpu_to_le32(anv->flush_ns->head->ns_id);
1456+
err = nvme_submit_sync_cmd(ns->queue, &c, NULL, 0);
1457+
if (err) {
1458+
dev_err(anv->dev, "Deferred flush failed: %d\n", err);
1459+
} else {
1460+
anv->last_flush = jiffies;
1461+
}
1462+
}
1463+
13921464
static struct apple_nvme *apple_nvme_alloc(struct platform_device *pdev)
13931465
{
13941466
struct device *dev = &pdev->dev;
@@ -1544,6 +1616,14 @@ static int apple_nvme_probe(struct platform_device *pdev)
15441616
goto out_uninit_ctrl;
15451617
}
15461618

1619+
if (flush_interval) {
1620+
anv->flush_interval = msecs_to_jiffies(flush_interval);
1621+
anv->flush_ns = NULL;
1622+
anv->last_flush = jiffies - anv->flush_interval;
1623+
}
1624+
1625+
INIT_DELAYED_WORK(&anv->flush_dwork, apple_nvme_flush_work);
1626+
15471627
nvme_reset_ctrl(&anv->ctrl);
15481628
async_schedule(apple_nvme_async_probe, anv);
15491629

@@ -1568,19 +1648,26 @@ static void apple_nvme_remove(struct platform_device *pdev)
15681648
apple_nvme_disable(anv, true);
15691649
nvme_uninit_ctrl(&anv->ctrl);
15701650

1571-
if (apple_rtkit_is_running(anv->rtk))
1651+
if (apple_rtkit_is_running(anv->rtk)) {
15721652
apple_rtkit_shutdown(anv->rtk);
15731653

1654+
writel(0, anv->mmio_coproc + APPLE_ANS_COPROC_CPU_CONTROL);
1655+
}
1656+
15741657
apple_nvme_detach_genpd(anv);
15751658
}
15761659

15771660
static void apple_nvme_shutdown(struct platform_device *pdev)
15781661
{
15791662
struct apple_nvme *anv = platform_get_drvdata(pdev);
15801663

1664+
flush_delayed_work(&anv->flush_dwork);
15811665
apple_nvme_disable(anv, true);
1582-
if (apple_rtkit_is_running(anv->rtk))
1666+
if (apple_rtkit_is_running(anv->rtk)) {
15831667
apple_rtkit_shutdown(anv->rtk);
1668+
1669+
writel(0, anv->mmio_coproc + APPLE_ANS_COPROC_CPU_CONTROL);
1670+
}
15841671
}
15851672

15861673
static int apple_nvme_resume(struct device *dev)
@@ -1597,10 +1684,11 @@ static int apple_nvme_suspend(struct device *dev)
15971684

15981685
apple_nvme_disable(anv, true);
15991686

1600-
if (apple_rtkit_is_running(anv->rtk))
1687+
if (apple_rtkit_is_running(anv->rtk)) {
16011688
ret = apple_rtkit_shutdown(anv->rtk);
16021689

1603-
writel(0, anv->mmio_coproc + APPLE_ANS_COPROC_CPU_CONTROL);
1690+
writel(0, anv->mmio_coproc + APPLE_ANS_COPROC_CPU_CONTROL);
1691+
}
16041692

16051693
return ret;
16061694
}

0 commit comments

Comments
 (0)