Skip to content

Commit

Permalink
mtd: rawnand: qcom: Release resources on failure within qcom_nandc_al…
Browse files Browse the repository at this point in the history
…loc()

In case when DMA channel request or alloc_bam_transaction() fails,
dma_unmap_single() and any channels already requested should be released.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Link: https://lore.kernel.org/linux-mtd/20200227123749.24064-6-peter.ujfalusi@ti.com
  • Loading branch information
Peter Ujfalusi authored and Miquel Raynal committed Mar 11, 2020
1 parent ac80c55 commit 80c3012
Showing 1 changed file with 34 additions and 27 deletions.
61 changes: 34 additions & 27 deletions drivers/mtd/nand/raw/qcom_nandc.c
Original file line number Diff line number Diff line change
Expand Up @@ -2628,6 +2628,29 @@ static const struct nand_controller_ops qcom_nandc_ops = {
.attach_chip = qcom_nand_attach_chip,
};

static void qcom_nandc_unalloc(struct qcom_nand_controller *nandc)
{
if (nandc->props->is_bam) {
if (!dma_mapping_error(nandc->dev, nandc->reg_read_dma))
dma_unmap_single(nandc->dev, nandc->reg_read_dma,
MAX_REG_RD *
sizeof(*nandc->reg_read_buf),
DMA_FROM_DEVICE);

if (nandc->tx_chan)
dma_release_channel(nandc->tx_chan);

if (nandc->rx_chan)
dma_release_channel(nandc->rx_chan);

if (nandc->cmd_chan)
dma_release_channel(nandc->cmd_chan);
} else {
if (nandc->chan)
dma_release_channel(nandc->chan);
}
}

static int qcom_nandc_alloc(struct qcom_nand_controller *nandc)
{
int ret;
Expand Down Expand Up @@ -2676,19 +2699,22 @@ static int qcom_nandc_alloc(struct qcom_nand_controller *nandc)
nandc->tx_chan = dma_request_slave_channel(nandc->dev, "tx");
if (!nandc->tx_chan) {
dev_err(nandc->dev, "failed to request tx channel\n");
return -ENODEV;
ret = -ENODEV;
goto unalloc;
}

nandc->rx_chan = dma_request_slave_channel(nandc->dev, "rx");
if (!nandc->rx_chan) {
dev_err(nandc->dev, "failed to request rx channel\n");
return -ENODEV;
ret = -ENODEV;
goto unalloc;
}

nandc->cmd_chan = dma_request_slave_channel(nandc->dev, "cmd");
if (!nandc->cmd_chan) {
dev_err(nandc->dev, "failed to request cmd channel\n");
return -ENODEV;
ret = -ENODEV;
goto unalloc;
}

/*
Expand All @@ -2702,7 +2728,8 @@ static int qcom_nandc_alloc(struct qcom_nand_controller *nandc)
if (!nandc->bam_txn) {
dev_err(nandc->dev,
"failed to allocate bam transaction\n");
return -ENOMEM;
ret = -ENOMEM;
goto unalloc;
}
} else {
nandc->chan = dma_request_slave_channel(nandc->dev, "rxtx");
Expand All @@ -2720,29 +2747,9 @@ static int qcom_nandc_alloc(struct qcom_nand_controller *nandc)
nandc->controller.ops = &qcom_nandc_ops;

return 0;
}

static void qcom_nandc_unalloc(struct qcom_nand_controller *nandc)
{
if (nandc->props->is_bam) {
if (!dma_mapping_error(nandc->dev, nandc->reg_read_dma))
dma_unmap_single(nandc->dev, nandc->reg_read_dma,
MAX_REG_RD *
sizeof(*nandc->reg_read_buf),
DMA_FROM_DEVICE);

if (nandc->tx_chan)
dma_release_channel(nandc->tx_chan);

if (nandc->rx_chan)
dma_release_channel(nandc->rx_chan);

if (nandc->cmd_chan)
dma_release_channel(nandc->cmd_chan);
} else {
if (nandc->chan)
dma_release_channel(nandc->chan);
}
unalloc:
qcom_nandc_unalloc(nandc);
return ret;
}

/* one time setup of a few nand controller registers */
Expand Down

0 comments on commit 80c3012

Please sign in to comment.