Skip to content

Commit

Permalink
kernel-dma: Keep UART4 working
Browse files Browse the repository at this point in the history
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
  • Loading branch information
miquelraynal committed Jul 27, 2023
1 parent f3944ba commit e41a8a5
Showing 1 changed file with 15 additions and 12 deletions.
27 changes: 15 additions & 12 deletions labs/kernel-serial-dma/kernel-serial-dma.tex
Expand Up @@ -39,7 +39,8 @@ \section{Preparing the driver}
\code{serial_write_dma}. Remember to also update the \code{.write}
member of \code{serial_fops} to run the DMA variant. If you want to
avoid warnings because \code{serial_write_pio} would now be unused, you
can define it with the \code{__maybe_unused} keyword.
can temporarily define it with the \code{__maybe_unused} keyword, until
we re-use it again (see below).

Let's now create two helpers supposed to initialize and cleanup our DMA
setup. We will call \code{serial_init_dma()} right before registering
Expand All @@ -60,13 +61,13 @@ \section{Prepare the DMA controller}

We should at the very least request the DMA channel to use. Open the SoC
device tree and find the uart2 and uart4 nodes. Look for \code{dma}
channel properties and their names. Yes, while uart2 seem to be
connected to the DMA controller through two different channels (one for
each direction), uart4 is not. Hence, when requesting the channels with
\kfunc{dma_request_chan()}, we must take care of not error-out upon the
channel properties and their names. While uart2 seem to be connected to
the DMA controller through two different channels (one for each
direction), uart4 is not. Hence, when requesting the channels with
\kfunc{dma_request_chan()}, we must take care of not erroring-out upon the
absence of channel. Mind the return value which is a \kstruct{dma_chan}
pointer, it must be checked with the \code{IS_ERR()} macro. You may display the
corresponding error string with {\tt \%pe}!
pointer, it must be checked with the \code{IS_ERR()} macro. You may
display the corresponding error string with {\tt \%pe}!

This channel will be used by all the \code{dmaengine} helpers, so better
save it in our \code{serial_dev} structure.
Expand Down Expand Up @@ -154,8 +155,13 @@ \section{Process user write requests}
};
\end{verbatim}

As we do not want to deal with concurrent operations anymore to simplify DMA
handling, we can start and end the write hook with something like:
In the write hook, we shall first check if the DMA channel has been
properly retrieved. If not, we should definitely fallback to the PIO
implementation.

Then, in order to simplify the code, we will no longer deal with
concurrent operations. In order to safely serialize writes, we can start
and end the write hook with something like:

\begin{verbatim}
/* Prevent concurrent Tx */
Expand All @@ -174,9 +180,6 @@ \section{Process user write requests}
spin_unlock_irqrestore(&serial->lock, flags);
\end{verbatim}

Also do not forget to check the absence of DMA channel, return
\code{-EOPNOTSUPP} in this case.

The first step in this \code{->write()} hook is to use \code{serial->tx_buf} as
bounce buffer by copying the user data using \kfunc{copy_from_user}. Let's
handle up to \code{SERIAL_BUFSIZE} bytes at a time. One can use \kfunc{min_t}
Expand Down

0 comments on commit e41a8a5

Please sign in to comment.