How to patch 8250_exar driver in RHEL 8 and 9 for Sealevel XR17V35X cards
This is intended for RHEL 8 and RHEL 9 users impacted by the issue described in this support article: https://www.sealevel.com/support/how-to-resolve-communication-issues-affecting-7xxxec-serial-cards-7106e-relio-r1/
The steps below describe blocking the original driver, patching the driver, and loading the patched driver. This procedure is required on RHEL due to 8250_exar being built into the kernel rather than as a loadable module.
1.Install packages needed to compile drivers
>yum groupinstall 'Development Tools'
>yum install kernel-devel kernel-headers
2.Edit GRUB_CMDLINE_LINUX in /etc/default/grub to contain
>8250.nr_uarts=16 initcall_blacklist=exar_pci_driver_init
This will increase the number of supported serial ports to 16 (Use a higher number if you need more) and blacklist the 8250_exar driver used by our XR17V35X cards from loading. We must blacklist the driver to prevent driver conflicts when we load the new driver.
3.Update your grub config.
>sudo grub2-mkconfig -o /boot/grub2/grub.cfg
4.Reboot
5.Download and extract your kernel source from https://mirrors.edge.kernel.org/pub/linux/kernel/
>Tip: You can determine your kernel version by running `cat /proc/version`
>Tip: You may alternatively obtain your source code through your Red Hat Customer Portal login.
6.Navigate to `drivers/tty/serial/8250`in the kernel source.
7.Copy `8250_exar.c`and rename it to `8250_exar_sealevel.c`
>cp 8250_exar.c 8250_exar_sealevel.c
8.Replace the contents of `Makefile`with
```
# SPDX-License-Identifier: GPL-2.0
#
# Makefile for the 8250 serial device drivers.
#
obj-m+= 8250_exar.o
obj-m+= 8250_exar_sealevel.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
```
9.Replace `setup_gpio()`in `8250_exar_sealevel.c`with the content below.
```
static void setup_gpio(struct pci_dev *pcidev, u8 __iomem *p)
{
/*
* The Commtech adapters required the MPIOs to be driven low. The Exar
* devices will export them as GPIOs, so we pre-configure them safely
* as inputs.
*/
u8 dir = 0x00;`
if ((pcidev->vendor == PCI_VENDOR_ID_EXAR) &&
(pcidev->subsystem_vendor != PCI_VENDOR_ID_SEALEVEL)) {
// Configure GPIO as inputs for Commtech adapters
dir = 0xff;
} else {
// Configure GPIO as outputs for SeaLevel adapters
dir = 0x00;
}
writeb(0x00, p + UART_EXAR_MPIOINT_7_0);
writeb(0x00, p + UART_EXAR_MPIOLVL_7_0);
writeb(0x00, p + UART_EXAR_MPIO3T_7_0);
writeb(0x00, p + UART_EXAR_MPIOINV_7_0);
writeb(dir, p + UART_EXAR_MPIOSEL_7_0);
writeb(0x00, p + UART_EXAR_MPIOOD_7_0);
writeb(0x00, p + UART_EXAR_MPIOINT_15_8);
writeb(0x00, p + UART_EXAR_MPIOLVL_15_8);
writeb(0x00, p + UART_EXAR_MPIO3T_15_8);
writeb(0x00, p + UART_EXAR_MPIOINV_15_8);
writeb(dir, p + UART_EXAR_MPIOSEL_15_8);
writeb(0x00, p + UART_EXAR_MPIOOD_15_8);
}
```
>Tip: This is taken from the mainline repository at https://github.com/torvalds/linux/commit/5fdbe136ae19ab751daaa4d08d9a42f3e30d17f9
10.Rename `exar_pci_driver`to match what is shown below. This prevents the new driver from being blacklisted by the changes in step 2.
```
static struct pci_driver exar_sealevel_pci_driver = {
.name= "exar_sealevel_serial",
.probe= exar_pci_probe,
.remove= exar_pci_remove,
.driver = {
.pm = &exar_pci_pm,
},
.id_table= exar_pci_tbl,
};
module_pci_driver(exar_sealevel_pci_driver);
```
11.Save `8250_exar_sealevel.c`
12.Build the driver
>make
13.Load the driver
>insmod 8250_exar_sealevel.ko
14.Verify the driver loaded
>dmesg | grep ttyS
You should see something similar to the message below
```
[ 2757.644239] 0000:01:00.0: ttyS4 at MMIO 0xdfcfc000 (irq = 28, base_baud = 7812500) is a XR17V35X
[ 2757.645930] 0000:01:00.0: ttyS5 at MMIO 0xdfcfc400 (irq = 28, base_baud = 7812500) is a XR17V35X
[ 2757.652420] 0000:01:00.0: ttyS6 at MMIO 0xdfcfc800 (irq = 28, base_baud = 7812500) is a XR17V35X
[ 2757.652841] 0000:01:00.0: ttyS7 at MMIO 0xdfcfcc00 (irq = 28, base_baud = 7812500) is a XR17V35X
```
The steps below describe blocking the original driver, patching the driver, and loading the patched driver. This procedure is required on RHEL due to 8250_exar being built into the kernel rather than as a loadable module.
1.Install packages needed to compile drivers
>yum groupinstall 'Development Tools'
>yum install kernel-devel kernel-headers
2.Edit GRUB_CMDLINE_LINUX in /etc/default/grub to contain
>8250.nr_uarts=16 initcall_blacklist=exar_pci_driver_init
This will increase the number of supported serial ports to 16 (Use a higher number if you need more) and blacklist the 8250_exar driver used by our XR17V35X cards from loading. We must blacklist the driver to prevent driver conflicts when we load the new driver.
3.Update your grub config.
>sudo grub2-mkconfig -o /boot/grub2/grub.cfg
4.Reboot
5.Download and extract your kernel source from https://mirrors.edge.kernel.org/pub/linux/kernel/
>Tip: You can determine your kernel version by running `cat /proc/version`
>Tip: You may alternatively obtain your source code through your Red Hat Customer Portal login.
6.Navigate to `drivers/tty/serial/8250`in the kernel source.
7.Copy `8250_exar.c`and rename it to `8250_exar_sealevel.c`
>cp 8250_exar.c 8250_exar_sealevel.c
8.Replace the contents of `Makefile`with
```
# SPDX-License-Identifier: GPL-2.0
#
# Makefile for the 8250 serial device drivers.
#
obj-m+= 8250_exar.o
obj-m+= 8250_exar_sealevel.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
```
9.Replace `setup_gpio()`in `8250_exar_sealevel.c`with the content below.
```
static void setup_gpio(struct pci_dev *pcidev, u8 __iomem *p)
{
/*
* The Commtech adapters required the MPIOs to be driven low. The Exar
* devices will export them as GPIOs, so we pre-configure them safely
* as inputs.
*/
u8 dir = 0x00;`
if ((pcidev->vendor == PCI_VENDOR_ID_EXAR) &&
(pcidev->subsystem_vendor != PCI_VENDOR_ID_SEALEVEL)) {
// Configure GPIO as inputs for Commtech adapters
dir = 0xff;
} else {
// Configure GPIO as outputs for SeaLevel adapters
dir = 0x00;
}
writeb(0x00, p + UART_EXAR_MPIOINT_7_0);
writeb(0x00, p + UART_EXAR_MPIOLVL_7_0);
writeb(0x00, p + UART_EXAR_MPIO3T_7_0);
writeb(0x00, p + UART_EXAR_MPIOINV_7_0);
writeb(dir, p + UART_EXAR_MPIOSEL_7_0);
writeb(0x00, p + UART_EXAR_MPIOOD_7_0);
writeb(0x00, p + UART_EXAR_MPIOINT_15_8);
writeb(0x00, p + UART_EXAR_MPIOLVL_15_8);
writeb(0x00, p + UART_EXAR_MPIO3T_15_8);
writeb(0x00, p + UART_EXAR_MPIOINV_15_8);
writeb(dir, p + UART_EXAR_MPIOSEL_15_8);
writeb(0x00, p + UART_EXAR_MPIOOD_15_8);
}
```
>Tip: This is taken from the mainline repository at https://github.com/torvalds/linux/commit/5fdbe136ae19ab751daaa4d08d9a42f3e30d17f9
10.Rename `exar_pci_driver`to match what is shown below. This prevents the new driver from being blacklisted by the changes in step 2.
```
static struct pci_driver exar_sealevel_pci_driver = {
.name= "exar_sealevel_serial",
.probe= exar_pci_probe,
.remove= exar_pci_remove,
.driver = {
.pm = &exar_pci_pm,
},
.id_table= exar_pci_tbl,
};
module_pci_driver(exar_sealevel_pci_driver);
```
11.Save `8250_exar_sealevel.c`
12.Build the driver
>make
13.Load the driver
>insmod 8250_exar_sealevel.ko
14.Verify the driver loaded
>dmesg | grep ttyS
You should see something similar to the message below
```
[ 2757.644239] 0000:01:00.0: ttyS4 at MMIO 0xdfcfc000 (irq = 28, base_baud = 7812500) is a XR17V35X
[ 2757.645930] 0000:01:00.0: ttyS5 at MMIO 0xdfcfc400 (irq = 28, base_baud = 7812500) is a XR17V35X
[ 2757.652420] 0000:01:00.0: ttyS6 at MMIO 0xdfcfc800 (irq = 28, base_baud = 7812500) is a XR17V35X
[ 2757.652841] 0000:01:00.0: ttyS7 at MMIO 0xdfcfcc00 (irq = 28, base_baud = 7812500) is a XR17V35X
```
Categories: