Re: [PATCH 3/8] pm80xx: check main config table address

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Dec 30, 2020 at 5:47 AM Viswas G <Viswas.G@xxxxxxxxxxxxxxxxx> wrote:
>
> From: akshatzen <akshatzen@xxxxxxxxxx>
>
> pm8001 driver initializes main configuration, general status, inbound
> queue and outbound queue table address based on value read from
> MSGU_SCRATCH_PAD_0 register.
>
> We should validate these addresses before dereferencing them.
>
> This change adds two validations:
> 1. Check if main configuration table offset lies within the pcibar
> mapped
> 2. Check if first dword of main configuration table reads "PMCS"
>
> There are two calls to init_pci_device_addresses() done during
> pm8001_pci_probe() in this sequence:
> 1. First inside chip_soft_rst, where if init_pci_device_addresses fails
> we will go ahead assuming MPI state is not ready and reset the device as
> long as bootloader is okay.  This gives chance to second call of
> init_pci_device_addresses to set up the addresses after reset.
>
> 2. The second call is via pm80xx_chip_init, after soft reset is done and
> firmware is checked to be ready. Once that is done we are safe to go
> ahead and initialize default table values and use them.
>
> Tested:
>
> 1. Enabled debugging logs and observed no issues during initialization,
> with a controller with No issues.
>
> pm80xx0:: pm8001_setup_msix 1034: pci_alloc_irq_vectors request ret:64
> no of intr 64
> pm80xx0:: init_pci_device_addresses 917: Scratchpad 0 Offset: 0x2000
> value 0x40002000
> pm80xx0:: init_pci_device_addresses 925: Scratchpad 0 PCI BAR: 0
> pm80xx0:: init_pci_device_addresses 952: VALID main config signature
> 0x53434d50
> pm80xx0:: init_pci_device_addresses 975: GST OFFSET 0xc4
> pm80xx0:: init_pci_device_addresses 978: INBND OFFSET 0x20000128
> pm80xx0:: init_pci_device_addresses 981: OBND OFFSET 0x24000928
> pm80xx0:: init_pci_device_addresses 984: IVT OFFSET 0x8001408
> pm80xx0:: init_pci_device_addresses 987: PSPA OFFSET 0x8001608
> pm80xx0:: init_pci_device_addresses 991: addr - main cfg (ptrval)
> general status (ptrval)
> pm80xx0:: init_pci_device_addresses 995: addr - inbnd (ptrval) obnd
> (ptrval)
> pm80xx0:: init_pci_device_addresses 999: addr - pspa (ptrval) ivt
> (ptrval)
> pm80xx0:: pm80xx_chip_soft_rst 1446: reset register before write : 0x0
> pm80xx0:: pm80xx_chip_soft_rst 1478: reset register after write 0x40
> pm80xx0:: pm80xx_chip_soft_rst 1544: SPCv soft reset Complete
> pm80xx0:: init_pci_device_addresses 917: Scratchpad 0 Offset: 0x2000
> value 0x40002000
> pm80xx0:: init_pci_device_addresses 925: Scratchpad 0 PCI BAR: 0
> pm80xx0:: init_pci_device_addresses 952: VALID main config signature
> 0x53434d50
> pm80xx0:: init_pci_device_addresses 975: GST OFFSET 0xc4
> pm80xx0:: init_pci_device_addresses 978: INBND OFFSET 0x20000128
> pm80xx0:: init_pci_device_addresses 981: OBND OFFSET 0x24000928
> pm80xx0:: init_pci_device_addresses 984: IVT OFFSET 0x8001408
> pm80xx0:: init_pci_device_addresses 987: PSPA OFFSET 0x8001608
> pm80xx0:: init_pci_device_addresses 991: addr - main cfg (ptrval)
> general status (ptrval)
> pm80xx0:: init_pci_device_addresses 995: addr - inbnd (ptrval) obnd
> (ptrval)
> pm80xx0:: init_pci_device_addresses 999: addr - pspa (ptrval) ivt
> (ptrval)
> pm80xx0:: pm80xx_chip_init 1329: MPI initialize successful!
>
> 2. Tested controller with firmware known to have initialization issue
> and observed no crashes with this fix
>
> pm80xx 0000:01:00.0: pm80xx: driver version 0.1.38
> pm80xx 0000:01:00.0: Removing from 1:1 domain
> pm80xx 0000:01:00.0: Requesting non-1:1 mappings
> pm80xx0:: init_pci_device_addresses 948: BAD main config signature 0x0
> pm80xx0:: mpi_uninit_check 1365: Failed to init pci addresses
> pm80xx0:: pm80xx_chip_soft_rst 1435: MPI state is not ready
> scratch:0:8:62a01000:0
> pm80xx0:: pm80xx_chip_soft_rst 1518: Firmware is not ready!
> pm80xx0:: pm80xx_chip_soft_rst 1532: iButton Feature is not Available!!!
> pm80xx0:: pm80xx_chip_init 1301: Firmware is not ready!
> pm80xx0:: pm8001_pci_probe 1215: chip_init failed [ret: -16]
> pm80xx: probe of 0000:01:00.0 failed with error -16
> pm80xx 0000:07:00.0: pm80xx: driver version 0.1.38
> pm80xx 0000:07:00.0: Removing from 1:1 domain
> pm80xx 0000:07:00.0: Requesting non-1:1 mappings
> scsi host6: pm80xx
> pm80xx1:: pm8001_setup_sgpio 5568: failed sgpio_req timeout
> pm80xx1:: mpi_phy_start_resp 3447: phy start resp status:0x0, phyid:0x0
> pm80xx 0000:08:00.0: pm80xx: driver version 0.1.38
> pm80xx 0000:08:00.0: Removing from 1:1 domain
> pm80xx 0000:08:00.0: Requesting non-1:1 mappings
>
> 3. Without this fix we observe crash on the same controller.
>
> pm80xx 0000:01:00.0: pm80xx: driver version 0.1.38
> pm80xx 0000:01:00.0: Removing from 1:1 domain
> pm80xx 0000:01:00.0: Requesting non-1:1 mappings
> [<ffffffffc0451b3b>] pm80xx_chip_soft_rst+0x6b/0x4c0 [pm80xx]
> [<ffffffffc043a933>] pm8001_pci_probe+0xa43/0x1630 [pm80xx]
> RIP: 0010:pm80xx_chip_soft_rst+0x71/0x4c0 [pm80xx]
> [<ffffffffc0451b3b>] ? pm80xx_chip_soft_rst+0x6b/0x4c0 [pm80xx]
> [<ffffffffc043a933>] pm8001_pci_probe+0xa43/0x1630 [pm80xx]
> pm80xx0:: mpi_uninit_check 1339: TIMEOUT:IBDB value/=2
> pm80xx0:: pm80xx_chip_soft_rst 1387: MPI state is not ready
> scratch:0:8:62a01000:0
> pm80xx0:: pm80xx_chip_soft_rst 1470: Firmware is not ready!
> pm80xx0:: pm80xx_chip_soft_rst 1484: iButton Feature is not Available!!!
> pm80xx0:: pm80xx_chip_init 1266: Firmware is not ready!
> pm80xx0:: pm8001_pci_probe 1207: chip_init failed [ret: -16]
> pm80xx: probe of 0000:01:00.0 failed with error -16
>
> Signed-off-by: akshatzen <akshatzen@xxxxxxxxxx>
> Signed-off-by: Viswas G <Viswas.G@xxxxxxxxxxxxx>
> Signed-off-by: Ruksar Devadi <Ruksar.devadi@xxxxxxxxxxxxx>
> Signed-off-by: Radha Ramachandran <radha@xxxxxxxxxx>
Acked-by: Jack Wang <jinpu.wang@xxxxxxxxxxxxxxx>
Thx
> ---
>  drivers/scsi/pm8001/pm8001_init.c | 11 +++++---
>  drivers/scsi/pm8001/pm80xx_hwi.c  | 53 ++++++++++++++++++++++++++++++++++++---
>  2 files changed, 58 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c
> index ee2de177d0d0..d21078ca7fb3 100644
> --- a/drivers/scsi/pm8001/pm8001_init.c
> +++ b/drivers/scsi/pm8001/pm8001_init.c
> @@ -466,9 +466,12 @@ static int pm8001_ioremap(struct pm8001_hba_info *pm8001_ha)
>                         pm8001_ha->io_mem[logicalBar].memvirtaddr =
>                                 ioremap(pm8001_ha->io_mem[logicalBar].membase,
>                                 pm8001_ha->io_mem[logicalBar].memsize);
> -                       pm8001_dbg(pm8001_ha, INIT,
> -                                  "PCI: bar %d, logicalBar %d\n",
> +                       if (!pm8001_ha->io_mem[logicalBar].memvirtaddr) {
> +                               pm8001_dbg(pm8001_ha, INIT,
> +                                       "Failed to ioremap bar %d, logicalBar %d",
>                                    bar, logicalBar);
> +                               return -ENOMEM;
> +                       }
>                         pm8001_dbg(pm8001_ha, INIT,
>                                    "base addr %llx virt_addr=%llx len=%d\n",
>                                    (u64)pm8001_ha->io_mem[logicalBar].membase,
> @@ -540,9 +543,11 @@ static struct pm8001_hba_info *pm8001_pci_alloc(struct pci_dev *pdev,
>                         tasklet_init(&pm8001_ha->tasklet[j], pm8001_tasklet,
>                                 (unsigned long)&(pm8001_ha->irq_vector[j]));
>  #endif
> -       pm8001_ioremap(pm8001_ha);
> +       if (pm8001_ioremap(pm8001_ha))
> +               goto failed_pci_alloc;
>         if (!pm8001_alloc(pm8001_ha, ent))
>                 return pm8001_ha;
> +failed_pci_alloc:
>         pm8001_free(pm8001_ha);
>         return NULL;
>  }
> diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
> index 86a3d483749c..7d0eada11d3c 100644
> --- a/drivers/scsi/pm8001/pm80xx_hwi.c
> +++ b/drivers/scsi/pm8001/pm80xx_hwi.c
> @@ -1115,7 +1115,7 @@ static int check_fw_ready(struct pm8001_hba_info *pm8001_ha)
>         return ret;
>  }
>
> -static void init_pci_device_addresses(struct pm8001_hba_info *pm8001_ha)
> +static int init_pci_device_addresses(struct pm8001_hba_info *pm8001_ha)
>  {
>         void __iomem *base_addr;
>         u32     value;
> @@ -1124,15 +1124,48 @@ static void init_pci_device_addresses(struct pm8001_hba_info *pm8001_ha)
>         u32     pcilogic;
>
>         value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_0);
> +
> +       /**
> +        * lower 26 bits of SCRATCHPAD0 register describes offset within the
> +        * PCIe BAR where the MPI configuration table is present
> +        */
>         offset = value & 0x03FFFFFF; /* scratch pad 0 TBL address */
>
>         pm8001_dbg(pm8001_ha, DEV, "Scratchpad 0 Offset: 0x%x value 0x%x\n",
>                    offset, value);
> +       /**
> +        * Upper 6 bits describe the offset within PCI config space where BAR
> +        * is located.
> +        */
>         pcilogic = (value & 0xFC000000) >> 26;
>         pcibar = get_pci_bar_index(pcilogic);
>         pm8001_dbg(pm8001_ha, INIT, "Scratchpad 0 PCI BAR: %d\n", pcibar);
> +
> +       /**
> +        * Make sure the offset falls inside the ioremapped PCI BAR
> +        */
> +       if (offset > pm8001_ha->io_mem[pcibar].memsize) {
> +               pm8001_dbg(pm8001_ha, FAIL,
> +                       "Main cfg tbl offset outside %u > %u\n",
> +                               offset, pm8001_ha->io_mem[pcibar].memsize);
> +               return -EBUSY;
> +       }
>         pm8001_ha->main_cfg_tbl_addr = base_addr =
>                 pm8001_ha->io_mem[pcibar].memvirtaddr + offset;
> +
> +       /**
> +        * Validate main configuration table address: first DWord should read
> +        * "PMCS"
> +        */
> +       value = pm8001_mr32(pm8001_ha->main_cfg_tbl_addr, 0);
> +       if (memcmp(&value, "PMCS", 4) != 0) {
> +               pm8001_dbg(pm8001_ha, FAIL,
> +                       "BAD main config signature 0x%x\n",
> +                               value);
> +               return -EBUSY;
> +       }
> +       pm8001_dbg(pm8001_ha, INIT,
> +                       "VALID main config signature 0x%x\n", value);
>         pm8001_ha->general_stat_tbl_addr =
>                 base_addr + (pm8001_cr32(pm8001_ha, pcibar, offset + 0x18) &
>                                         0xFFFFFF);
> @@ -1171,6 +1204,7 @@ static void init_pci_device_addresses(struct pm8001_hba_info *pm8001_ha)
>         pm8001_dbg(pm8001_ha, INIT, "addr - pspa %p ivt %p\n",
>                    pm8001_ha->pspa_q_tbl_addr,
>                    pm8001_ha->ivt_tbl_addr);
> +       return 0;
>  }
>
>  /**
> @@ -1438,7 +1472,12 @@ static int pm80xx_chip_init(struct pm8001_hba_info *pm8001_ha)
>         pm8001_ha->controller_fatal_error = false;
>
>         /* Initialize pci space address eg: mpi offset */
> -       init_pci_device_addresses(pm8001_ha);
> +       ret = init_pci_device_addresses(pm8001_ha);
> +       if (ret) {
> +               pm8001_dbg(pm8001_ha, FAIL,
> +                       "Failed to init pci addresses");
> +               return ret;
> +       }
>         init_default_table_values(pm8001_ha);
>         read_main_config_table(pm8001_ha);
>         read_general_status_table(pm8001_ha);
> @@ -1482,7 +1521,15 @@ static int mpi_uninit_check(struct pm8001_hba_info *pm8001_ha)
>         u32 max_wait_count;
>         u32 value;
>         u32 gst_len_mpistate;
> -       init_pci_device_addresses(pm8001_ha);
> +       int ret;
> +
> +       ret = init_pci_device_addresses(pm8001_ha);
> +       if (ret) {
> +               pm8001_dbg(pm8001_ha, FAIL,
> +                       "Failed to init pci addresses");
> +               return ret;
> +       }
> +
>         /* Write bit1=1 to Inbound DoorBell Register to tell the SPC FW the
>         table is stop */
>         pm8001_cw32(pm8001_ha, 0, MSGU_IBDB_SET, SPCv_MSGU_CFG_TABLE_RESET);
> --
> 2.16.3
>



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]

  Powered by Linux