Commit a1d8128f authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull spi fixes from Mark Brown:
 "As well as a few driver specific fixes we've got a core change here
  which raises the hard coded limit on the number of devices we can
  support on one SPI bus since some FPGA based systems are running into
  the existing limit. This is not a good solution but it's one suitable
  for this point in the release cycle, we should dynamically size the
  relevant data structures which I hope will happen in the next couple
  of merge windows.

  We also pull in a MTD fix for the Qualcomm SNAND driver, the two fixes
  cover the same issue and merging them together minimises bisection
  issues"

* tag 'spi-fix-v6.16-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi:
  spi: cadence-quadspi: fix cleanup of rx_chan on failure paths
  spi: spi-fsl-dspi: Clear completion counter before initiating transfer
  spi: Raise limit on number of chip selects to 24
  mtd: nand: qpic_common: prevent out of bounds access of BAM arrays
  spi: spi-qpic-snand: reallocate BAM transactions
parents df464267 04a8ff1b
Loading
Loading
Loading
Loading
+26 −4
Original line number Diff line number Diff line
@@ -57,14 +57,15 @@ qcom_alloc_bam_transaction(struct qcom_nand_controller *nandc)
	bam_txn_buf += sizeof(*bam_txn);

	bam_txn->bam_ce = bam_txn_buf;
	bam_txn_buf +=
		sizeof(*bam_txn->bam_ce) * QPIC_PER_CW_CMD_ELEMENTS * num_cw;
	bam_txn->bam_ce_nitems = QPIC_PER_CW_CMD_ELEMENTS * num_cw;
	bam_txn_buf += sizeof(*bam_txn->bam_ce) * bam_txn->bam_ce_nitems;

	bam_txn->cmd_sgl = bam_txn_buf;
	bam_txn_buf +=
		sizeof(*bam_txn->cmd_sgl) * QPIC_PER_CW_CMD_SGL * num_cw;
	bam_txn->cmd_sgl_nitems = QPIC_PER_CW_CMD_SGL * num_cw;
	bam_txn_buf += sizeof(*bam_txn->cmd_sgl) * bam_txn->cmd_sgl_nitems;

	bam_txn->data_sgl = bam_txn_buf;
	bam_txn->data_sgl_nitems = QPIC_PER_CW_DATA_SGL * num_cw;

	init_completion(&bam_txn->txn_done);

@@ -238,6 +239,11 @@ int qcom_prep_bam_dma_desc_cmd(struct qcom_nand_controller *nandc, bool read,
	struct bam_transaction *bam_txn = nandc->bam_txn;
	u32 offset;

	if (bam_txn->bam_ce_pos + size > bam_txn->bam_ce_nitems) {
		dev_err(nandc->dev, "BAM %s array is full\n", "CE");
		return -EINVAL;
	}

	bam_ce_buffer = &bam_txn->bam_ce[bam_txn->bam_ce_pos];

	/* fill the command desc */
@@ -258,6 +264,12 @@ int qcom_prep_bam_dma_desc_cmd(struct qcom_nand_controller *nandc, bool read,

	/* use the separate sgl after this command */
	if (flags & NAND_BAM_NEXT_SGL) {
		if (bam_txn->cmd_sgl_pos >= bam_txn->cmd_sgl_nitems) {
			dev_err(nandc->dev, "BAM %s array is full\n",
				"CMD sgl");
			return -EINVAL;
		}

		bam_ce_buffer = &bam_txn->bam_ce[bam_txn->bam_ce_start];
		bam_ce_size = (bam_txn->bam_ce_pos -
				bam_txn->bam_ce_start) *
@@ -297,10 +309,20 @@ int qcom_prep_bam_dma_desc_data(struct qcom_nand_controller *nandc, bool read,
	struct bam_transaction *bam_txn = nandc->bam_txn;

	if (read) {
		if (bam_txn->rx_sgl_pos >= bam_txn->data_sgl_nitems) {
			dev_err(nandc->dev, "BAM %s array is full\n", "RX sgl");
			return -EINVAL;
		}

		sg_set_buf(&bam_txn->data_sgl[bam_txn->rx_sgl_pos],
			   vaddr, size);
		bam_txn->rx_sgl_pos++;
	} else {
		if (bam_txn->tx_sgl_pos >= bam_txn->data_sgl_nitems) {
			dev_err(nandc->dev, "BAM %s array is full\n", "TX sgl");
			return -EINVAL;
		}

		sg_set_buf(&bam_txn->data_sgl[bam_txn->tx_sgl_pos],
			   vaddr, size);
		bam_txn->tx_sgl_pos++;
+0 −5
Original line number Diff line number Diff line
@@ -1960,11 +1960,6 @@ static int cqspi_probe(struct platform_device *pdev)

	pm_runtime_enable(dev);

	if (cqspi->rx_chan) {
		dma_release_channel(cqspi->rx_chan);
		goto probe_setup_failed;
	}

	pm_runtime_set_autosuspend_delay(dev, CQSPI_AUTOSUSPEND_TIMEOUT);
	pm_runtime_use_autosuspend(dev);
	pm_runtime_get_noresume(dev);
+10 −1
Original line number Diff line number Diff line
@@ -983,11 +983,20 @@ static int dspi_transfer_one_message(struct spi_controller *ctlr,
		if (dspi->devtype_data->trans_mode == DSPI_DMA_MODE) {
			status = dspi_dma_xfer(dspi);
		} else {
			/*
			 * Reinitialize the completion before transferring data
			 * to avoid the case where it might remain in the done
			 * state due to a spurious interrupt from a previous
			 * transfer. This could falsely signal that the current
			 * transfer has completed.
			 */
			if (dspi->irq)
				reinit_completion(&dspi->xfer_done);

			dspi_fifo_write(dspi);

			if (dspi->irq) {
				wait_for_completion(&dspi->xfer_done);
				reinit_completion(&dspi->xfer_done);
			} else {
				do {
					status = dspi_poll(dspi);
+16 −0
Original line number Diff line number Diff line
@@ -315,6 +315,22 @@ static int qcom_spi_ecc_init_ctx_pipelined(struct nand_device *nand)

	mtd_set_ooblayout(mtd, &qcom_spi_ooblayout);

	/*
	 * Free the temporary BAM transaction allocated initially by
	 * qcom_nandc_alloc(), and allocate a new one based on the
	 * updated max_cwperpage value.
	 */
	qcom_free_bam_transaction(snandc);

	snandc->max_cwperpage = cwperpage;

	snandc->bam_txn = qcom_alloc_bam_transaction(snandc);
	if (!snandc->bam_txn) {
		dev_err(snandc->dev, "failed to allocate BAM transaction\n");
		ret = -ENOMEM;
		goto err_free_ecc_cfg;
	}

	ecc_cfg->cfg0 = FIELD_PREP(CW_PER_PAGE_MASK, (cwperpage - 1)) |
			FIELD_PREP(UD_SIZE_BYTES_MASK, ecc_cfg->cw_data) |
			FIELD_PREP(DISABLE_STATUS_AFTER_WRITE, 1) |
+8 −0
Original line number Diff line number Diff line
@@ -237,6 +237,9 @@
 * @last_data_desc - last DMA desc in data channel (tx/rx).
 * @last_cmd_desc - last DMA desc in command channel.
 * @txn_done - completion for NAND transfer.
 * @bam_ce_nitems - the number of elements in the @bam_ce array
 * @cmd_sgl_nitems - the number of elements in the @cmd_sgl array
 * @data_sgl_nitems - the number of elements in the @data_sgl array
 * @bam_ce_pos - the index in bam_ce which is available for next sgl
 * @bam_ce_start - the index in bam_ce which marks the start position ce
 *		   for current sgl. It will be used for size calculation
@@ -255,6 +258,11 @@ struct bam_transaction {
	struct dma_async_tx_descriptor *last_data_desc;
	struct dma_async_tx_descriptor *last_cmd_desc;
	struct completion txn_done;

	unsigned int bam_ce_nitems;
	unsigned int cmd_sgl_nitems;
	unsigned int data_sgl_nitems;

	struct_group(bam_positions,
		u32 bam_ce_pos;
		u32 bam_ce_start;
Loading