Skip to content

Commit

Permalink
dmaengine: mv_xor: add suspend/resume support
Browse files Browse the repository at this point in the history
This commit adds suspend/resume support to the mv_xor driver. The
config and interrupt mask registers must be saved and restored, and
upon resume, the MBus windows configuration must also be done again.

Tested on Armada 388 GP, with a RAID 5 array, accessed before and
after a suspend to RAM cycle.

Based on work from Ofer Heifetz and Lior Amsalem.

Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
  • Loading branch information
Thomas Petazzoni authored and Vinod Koul committed Jan 6, 2016
1 parent 81aafb3 commit 8b64843
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 0 deletions.
53 changes: 53 additions & 0 deletions drivers/dma/mv_xor.c
Original file line number Diff line number Diff line change
Expand Up @@ -1085,6 +1085,57 @@ mv_xor_conf_mbus_windows(struct mv_xor_device *xordev,
writel(0, base + WINDOW_OVERRIDE_CTRL(1));
}

/*
* Since this XOR driver is basically used only for RAID5, we don't
* need to care about synchronizing ->suspend with DMA activity,
* because the DMA engine will naturally be quiet due to the block
* devices being suspended.
*/
static int mv_xor_suspend(struct platform_device *pdev, pm_message_t state)
{
struct mv_xor_device *xordev = platform_get_drvdata(pdev);
int i;

for (i = 0; i < MV_XOR_MAX_CHANNELS; i++) {
struct mv_xor_chan *mv_chan = xordev->channels[i];

if (!mv_chan)
continue;

mv_chan->saved_config_reg =
readl_relaxed(XOR_CONFIG(mv_chan));
mv_chan->saved_int_mask_reg =
readl_relaxed(XOR_INTR_MASK(mv_chan));
}

return 0;
}

static int mv_xor_resume(struct platform_device *dev)
{
struct mv_xor_device *xordev = platform_get_drvdata(dev);
const struct mbus_dram_target_info *dram;
int i;

for (i = 0; i < MV_XOR_MAX_CHANNELS; i++) {
struct mv_xor_chan *mv_chan = xordev->channels[i];

if (!mv_chan)
continue;

writel_relaxed(mv_chan->saved_config_reg,
XOR_CONFIG(mv_chan));
writel_relaxed(mv_chan->saved_int_mask_reg,
XOR_INTR_MASK(mv_chan));
}

dram = mv_mbus_dram_info();
if (dram)
mv_xor_conf_mbus_windows(xordev, dram);

return 0;
}

static const struct of_device_id mv_xor_dt_ids[] = {
{ .compatible = "marvell,orion-xor", .data = (void *)XOR_MODE_IN_REG },
{ .compatible = "marvell,armada-380-xor", .data = (void *)XOR_MODE_IN_DESC },
Expand Down Expand Up @@ -1246,6 +1297,8 @@ static int mv_xor_probe(struct platform_device *pdev)

static struct platform_driver mv_xor_driver = {
.probe = mv_xor_probe,
.suspend = mv_xor_suspend,
.resume = mv_xor_resume,
.driver = {
.name = MV_XOR_NAME,
.of_match_table = of_match_ptr(mv_xor_dt_ids),
Expand Down
1 change: 1 addition & 0 deletions drivers/dma/mv_xor.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ struct mv_xor_chan {
char dummy_src[MV_XOR_MIN_BYTE_COUNT];
char dummy_dst[MV_XOR_MIN_BYTE_COUNT];
dma_addr_t dummy_src_addr, dummy_dst_addr;
u32 saved_config_reg, saved_int_mask_reg;
};

/**
Expand Down

0 comments on commit 8b64843

Please sign in to comment.