FLUSP logo FLUSP - FLOSS at USP

Linux kernel patch submission guidelines (FSD 2026)

Written by David Tadokoro

Written on , last modified on

1. Clone the right kernel tree and branch

For each Linux subsystem/subproject you want to contribute to, you must use a dedicated git repository (called kernel tree, in this context). The information about where this tree is located so you can do a git clone is at the MAINTAINERS file present at the root of any kernel tree. Here is a Web version of it: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/MAINTAINERS.

Search for the subsystem/subproject you are working on and, if it has a dedicated git tree, it will be indicated in the T: <remote-url> attribute. The <remote-url> points to the tree, so you can do the below to clone the respective kernel tree:

git clone <remote-url>

In the case of the Industrial I/O (IIO) and AMD DRM subsystems, which we have curated issues, the git clone commands are:

# IIO
git clone git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio --branch togreg

# AMD DRM
git clone https://gitlab.freedesktop.org/agd5f/linux.git --branch amd-staging-drm-next

Note: The --branch option that sets the development branch used as a base. This is because, apart from the right kernel tree, we need to ensure we are at the latest development branch before making patches to avoid working on something that has already been solved or that doesn’t make sense anymore.

Unfortunately, I don’t know a clear-cut way of knowing the right development branch of a project. Still, it should be documented somewhere in the subsystem/subproject.

Also, don’t forget to keep the development branch updated with

git pull

Note: If you are working on a branch like testing for IIO, it is also recommended to do a rebase (git pull --rebase) because the maintainers frequently make changes to the tree. This ensures your local branch stays up-to-date and avoids unnecessary merge commits.

2. Create a dedicated local branch to isolate your work

As mentioned, you will be using a specific branch as base for each subsystem/subproject and objective. So, after checking out to the correct base branch (testing for IIO and amd-staging-drm-next), create a new branch to isolate your work. The name doesn’t matter to anyone but you, but having a meaningful name to keep things organized is a good idea:

git switch <base-branch>
git checkout -b <name-of-your-patch-branch>

3. Ensure that your change is being compiled

When tinkering with the Linux codebase, you need to be sure that the code you are modifying (at least) doesn’t break compilation. For this, you need to have a .config file configured to compile the portion of the code you’ve changed in the correct context. Ok, this is really ambiguous and circular, so here is one way you can be sure that the file you are modifying is being considered for compilation.

I can’t confirm that this is the most efficient and reliable way, but this helps on getting an idea of the configurations you need to enable in order to produce the correct compilation. We are going to show an example on how to proceed when you don’t know much about the file you are editing.

Say you are modifying the file drivers/iio/dummy/iio_simple_dummy.c and you don’t know how to include it in the compilation. You should look in the same directory of the file for a Kconfig. This file has many configuration definitions in the form of

config <config_name>

    ...

    help

    <description_of_the_config>

You would look for a config name and description that relates to where you are working, like IIO_SIMPLE_DUMMY. Then, you would open the .config file for editing with make nconfig or kw build --menu. Hit the F8 Key (SymSearch) and type in the config name you’ve noted. This should open a menu with entries starting with Symbol:. You would look for the config name you’ve typed at the top. You should see a Depends on: attribute with the dependencies needed to be enabled before IIO_SIMPLE_DUMMY. There is also a Location: with a series of indentations that show the menus sequence to activate the config you’ve entered; you should see a number by the side of the closest menu entry you can reach.

For example, you might see something like this:

Symbol: IIO_SIMPLE_DUMMY [=n]                                                       
Type  : tristate                                                                    
Defined at drivers/iio/dummy/Kconfig:12                                             
  Prompt: An example driver with no hardware requirements                           
  Depends on: IIO [=y] && IIO_SW_DEVICE [=n]                                        
  Location:                                                                         
    -> Device Drivers                                                               
      -> Industrial I/O support (IIO [=y])                                          
(1)     -> IIO dummy driver                                                         
          -> An example driver with no hardware requirements (IIO_SIMPLE_DUMMY [=n])

In this case you would need to hit ESC, hit F8, and search for IIO_SW_DEVICE (which is not enabled). You could see an output like

Symbol: IIO_SW_DEVICE [=n]                                        
Type  : tristate                                                  
Defined at drivers/iio/Kconfig:53                                 
  Prompt: Enable software IIO device support                      
  Depends on: IIO [=y]                                            
  Location:                                                       
    -> Device Drivers                                             
      -> Industrial I/O support (IIO [=y])                        
(1)     -> Enable software IIO device support (IIO_SW_DEVICE [=n])
Selects: IIO_CONFIGFS [=n]                                        

Hitting 1 should jump you to the menu that enables IIO_SW_DEVICE. Then you would repeat it to enable the IIO_SIMPLE_DUMMY config. Finally, you would save and quit the editing of the .config.

Note that this is a “blind” direction on how to enable a specific config in the Kbuild/Kconfig system, which doesn’t guarantee that the compilation will be “correct” for your patchset context (maybe the config name you’ve noted doesn’t even enable the target file).

Nevertheless, to test if file is being compiled, use the old technique add-a-clear-compilation-error to the file. If the compilation fails, then you can be sure that your file is being compiled (at least, part of it).

4. Backup your .config files

When developing for Linux, having to stop everything to produce a new .config file is tedious and time consuming. So whenever you have a working .config file that is of your interest backup it by copying it to a “safe” location or by using kw kernel-config-manager.

The same goes for the virtual machine images you use to test custom built kernel. You can make backups of these images with simple cp commands.

5. Make atomic commits and work on your commit message

General good commit practices are almost obligatory in the kernel, to the point that a perfect change, from the technical perspective, can be rejected if the commit does multiple things at once, so focus on atomic changes.

Descriptive commit messages that follow the subsystem/subproject pattern are also important. For example, doing

git log drivers/iio/adc/ad4030.c

will output all the commits that modified the file, and can give us with a good base for writing our commit subject. Pay attention to the prefix of the message. For this example, the command will (probably, if you are on the IIO testing branch) output as the latest commit (first entry in the list)

iio: adc: ad4030: Add support for ADAQ4216 and ADAQ4224

What is of interesting to us is the iio: adc: ad4030: part, which we can use as reference for our commit message title. However, the maintainer/community have the final word, so if they ask you to change the format of the title follow the request (even though, you can mention you’ve used a past commit as an example, pointing to it).

Important: The commit message body is obligatory, even if your change is so small and simple that it will be redundant with the title.

For more guidance on writing good commit messages, see [1].

6. Add your Signed-off-by and Co-developed-by

There is another hard-rule that is homogenous for every subsystem/subproject which is the addition of a Signed-off-by: Your Name <your@email.com> line with the author’s name and email. To configure git to automatically add this for you, run

git config --global user.name <Your Name>
git config --global user.email <your@email.com>

then just do commit as follow

git commit --signoff
# or
git commit -s

All integrants of the group must add their own signature. By rule, only the committer should add a Signed-off-by and the remaining developers should add Co-developed-by followed by a Signed-off-by. Apart from the committer that has the signature added automatically (with the --signoff flag) the others should add their signatures manually or when doing the commit by modifying the command to

git commit --signoff --trailer='Co-developed-by: Integrant 2 <email@2.com>' --trailer='Signed-off-by: Integrant 2 <email@2.com>' ...

As an example, imagine that Paulo Meirelles and David Tadokoro are developing the patchset. Considering that Paulo is the committer (the one that runs git commit --signoff), the signatures at the end of the commit message should be

Signed-off-by: Paulo Meirelles <paulormm@ime.usp.br>
Co-developed-by: David Tadokoro <davidbtadokoro@ime.usp.br>
Signed-off-by: David Tadokoro <davidbtadokoro@ime.usp.br>

7. Check that your patchset doesn’t introduce coding style problems

To make your patchset more robust, it is advisable to check for possible coding style problems that your patchset may be introducing. To do this, run

git format-patch -1 --stdout | ./scripts/checkpatch.pl --

This will make checkpatch.pl check for problems on the current commit (the one pointed by the HEAD; the commit you are at the moment) and will output the ones it finds.

Important: The problems found by the tool are not always correct, so be critic about them and apply them only if they are reasonable.

8. Official Linux kernel guidelines in submitting patches

There is also an official guide on submitting patches done by the Linux kernel community[2]. It is very extensive (even more than the one I did above), but you can check it if you are in doubt about anything more specific.

9. Configure git send-email

Before sending patches, you need to do some configuration. We assume you are using you @usp.br email, which is gmail under the hood. The configuration is described in this tutorial: Sending patches with git and a USP email

10. Send your contribution to our CI before sending it “to the world”

After your patch(set) is ready, before sending your contributions to the respective mailing list(s) and maintainer(s), send your contribution only to the address kernel@lists.ime.usp.br. Below is the safe command to send the last <n> commits.

kw send-patch --send -<n> --simulate --private --to=kernel@lists.ime.usp.br

The above command is safe because the --simulate option makes kw do everything except sending the message(s). Before removing this option to actually send the message(s), make sure that the recipients (the RCPT TO: fields) are correct. You can optionally append a --cc=<your@email.com> at the end the command to copy yourself and be more comfortable about the email being delivered.

All the patches sent to the mailing list will be available on our lore instance: https://lore.kernel.ime.usp.br/kernel.ime/

It may take some time for the patch to appear in the mailing list archive.

Sending the patchset to this address will trigger our local CI where the patch will be applied to the corresponding kernel tree, compiled, and booted into a VM where a basic boot cycle test will be executed. The main job stages are build and test. The former is responsible for applying and compiling the kernel image. The latter loads it and runs the boot cycle.

We have 4 CI repositories. When submitting a patch, you can track its progress on the respective repository, by finding the CI pipeline that was triggered the moment you’ve sent the patch.

  1. DSL-LINUX is the main CI repository. It detects the tree that matches your patch and triggers the build and test jobs to one of the repository below. You can track the entire CI flow for every tree from here.
  2. IIO-CI is the repository for the IIO tree. CI jobs for IIO patches will be here;
  3. AMD-DISPLAY-CI is the repository for the AMD DISPLAY tree. CI jobs for AMD DISPLAY jobs will be here;
  4. LINUX-NEXT-CI is the repository for the LINUX-NEXT tree. This tree contains bleeding edge from all development trees and is used as a fallback if your patch doesn’t match the IIO or AMD trees.

Important: Despite being functional, our UI/UX for CI feedback is still lacking a centralized and organized interface. You may ask one of the teacher assistants if you struggle to track the CI status of your patch. Keep in mind that the UI aspect of our CI is WIP and may face significant improvements during the next days (and this documentation will be updated accordingly)

The CI pipeline may present some bugs, such as wrong job failures. If your patch gets buggy pipelines, we’ll address the bug and manually run your patch through the CI until it is properly evaluated by our CI system.

11. Send your patchset “to the world” after approval from our CI

After your patchset has been approved in the previous step, you can send it to the correct maintainers and mailing list by running the previous command without the additional --private and --to options:

kw send-patch --send -<n> --simulate

Remember to drop the --simulate flag after you feel confident that the messages to be sent are correct and destined to the correct recipients.

History

References

[1] cbeams. “How to Write a Git Commit Message”. (2014) URL: https://cbea.ms/git-commit/

[2] Linux Kernel Community. “Submitting Patches - The Linux Kernel”. (2026) URL: https://www.kernel.org/doc/html/v6.14/process/submitting-patches.html


comments powered by Disqus