Skip to content

Commit 8774655

Browse files
committed
Merge branch 'bits/050-nvme' into asahi-wip
2 parents d3e9888 + 8f682bc commit 8774655

1 file changed

Lines changed: 107 additions & 17 deletions

File tree

drivers/nvme/host/apple.c

Lines changed: 107 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

@@ -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+
732764
static 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+
13911463
static 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;
15201592
put_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)
15461627
out_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

15691654
static 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

15781667
static 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

Comments
 (0)