diff options
Diffstat (limited to 'drivers/scsi/mpt3sas')
-rw-r--r-- | drivers/scsi/mpt3sas/Kconfig | 8 | ||||
-rw-r--r-- | drivers/scsi/mpt3sas/Makefile | 3 | ||||
-rw-r--r-- | drivers/scsi/mpt3sas/mpt3sas_base.c | 263 | ||||
-rw-r--r-- | drivers/scsi/mpt3sas/mpt3sas_base.h | 21 | ||||
-rw-r--r-- | drivers/scsi/mpt3sas/mpt3sas_debugfs.c | 157 | ||||
-rw-r--r-- | drivers/scsi/mpt3sas/mpt3sas_scsih.c | 8 |
6 files changed, 338 insertions, 122 deletions
diff --git a/drivers/scsi/mpt3sas/Kconfig b/drivers/scsi/mpt3sas/Kconfig index a072187875df..86209455172d 100644 --- a/drivers/scsi/mpt3sas/Kconfig +++ b/drivers/scsi/mpt3sas/Kconfig @@ -46,7 +46,7 @@ config SCSI_MPT3SAS select SCSI_SAS_ATTRS select RAID_ATTRS select IRQ_POLL - ---help--- + help This driver supports PCI-Express SAS 12Gb/s Host Adapters. config SCSI_MPT2SAS_MAX_SGE @@ -54,7 +54,7 @@ config SCSI_MPT2SAS_MAX_SGE depends on PCI && SCSI && SCSI_MPT3SAS default "128" range 16 256 - ---help--- + help This option allows you to specify the maximum number of scatter- gather entries per I/O. The driver default is 128, which matches MAX_PHYS_SEGMENTS in most kernels. However in SuSE kernels this @@ -66,7 +66,7 @@ config SCSI_MPT3SAS_MAX_SGE depends on PCI && SCSI && SCSI_MPT3SAS default "128" range 16 256 - ---help--- + help This option allows you to specify the maximum number of scatter- gather entries per I/O. The driver default is 128, which matches MAX_PHYS_SEGMENTS in most kernels. However in SuSE kernels this @@ -78,6 +78,6 @@ config SCSI_MPT2SAS default n select SCSI_MPT3SAS depends on PCI && SCSI - ---help--- + help Dummy config option for backwards compatiblity: configure the MPT3SAS driver instead. diff --git a/drivers/scsi/mpt3sas/Makefile b/drivers/scsi/mpt3sas/Makefile index 84fb3fbdb0ca..e76d994dbed3 100644 --- a/drivers/scsi/mpt3sas/Makefile +++ b/drivers/scsi/mpt3sas/Makefile @@ -7,4 +7,5 @@ mpt3sas-y += mpt3sas_base.o \ mpt3sas_transport.o \ mpt3sas_ctl.o \ mpt3sas_trigger_diag.o \ - mpt3sas_warpdrive.o + mpt3sas_warpdrive.o \ + mpt3sas_debugfs.o \ diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 663782bb790d..96b78fdc6b8a 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -413,7 +413,7 @@ static void _clone_sg_entries(struct MPT3SAS_ADAPTER *ioc, { Mpi2SGESimple32_t *sgel, *sgel_next; u32 sgl_flags, sge_chain_count = 0; - bool is_write = 0; + bool is_write = false; u16 i = 0; void __iomem *buffer_iomem; phys_addr_t buffer_iomem_phys; @@ -482,7 +482,7 @@ static void _clone_sg_entries(struct MPT3SAS_ADAPTER *ioc, if (le32_to_cpu(sgel->FlagsLength) & (MPI2_SGE_FLAGS_HOST_TO_IOC << MPI2_SGE_FLAGS_SHIFT)) - is_write = 1; + is_write = true; for (i = 0; i < MPT_MIN_PHYS_SEGMENTS + ioc->facts.MaxChainDepth; i++) { @@ -2806,58 +2806,38 @@ _base_build_sg_ieee(struct MPT3SAS_ADAPTER *ioc, void *psge, static int _base_config_dma_addressing(struct MPT3SAS_ADAPTER *ioc, struct pci_dev *pdev) { - u64 required_mask, coherent_mask; struct sysinfo s; - /* Set 63 bit DMA mask for all SAS3 and SAS35 controllers */ - int dma_mask = (ioc->hba_mpi_version_belonged > MPI2_VERSION) ? 63 : 64; - - if (ioc->is_mcpu_endpoint) - goto try_32bit; + int dma_mask; - required_mask = dma_get_required_mask(&pdev->dev); - if (sizeof(dma_addr_t) == 4 || required_mask == 32) - goto try_32bit; - - if (ioc->dma_mask) - coherent_mask = DMA_BIT_MASK(dma_mask); + if (ioc->is_mcpu_endpoint || + sizeof(dma_addr_t) == 4 || ioc->use_32bit_dma || + dma_get_required_mask(&pdev->dev) <= 32) + dma_mask = 32; + /* Set 63 bit DMA mask for all SAS3 and SAS35 controllers */ + else if (ioc->hba_mpi_version_belonged > MPI2_VERSION) + dma_mask = 63; else - coherent_mask = DMA_BIT_MASK(32); + dma_mask = 64; if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(dma_mask)) || - dma_set_coherent_mask(&pdev->dev, coherent_mask)) - goto try_32bit; - - ioc->base_add_sg_single = &_base_add_sg_single_64; - ioc->sge_size = sizeof(Mpi2SGESimple64_t); - ioc->dma_mask = dma_mask; - goto out; - - try_32bit: - if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32))) + dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(dma_mask))) return -ENODEV; - ioc->base_add_sg_single = &_base_add_sg_single_32; - ioc->sge_size = sizeof(Mpi2SGESimple32_t); - ioc->dma_mask = 32; - out: + if (dma_mask > 32) { + ioc->base_add_sg_single = &_base_add_sg_single_64; + ioc->sge_size = sizeof(Mpi2SGESimple64_t); + } else { + ioc->base_add_sg_single = &_base_add_sg_single_32; + ioc->sge_size = sizeof(Mpi2SGESimple32_t); + } + si_meminfo(&s); ioc_info(ioc, "%d BIT PCI BUS DMA ADDRESSING SUPPORTED, total mem (%ld kB)\n", - ioc->dma_mask, convert_to_kb(s.totalram)); + dma_mask, convert_to_kb(s.totalram)); return 0; } -static int -_base_change_consistent_dma_mask(struct MPT3SAS_ADAPTER *ioc, - struct pci_dev *pdev) -{ - if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(ioc->dma_mask))) { - if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) - return -ENODEV; - } - return 0; -} - /** * _base_check_enable_msix - checks MSIX capabable. * @ioc: per adapter object @@ -4827,8 +4807,9 @@ _base_release_memory_pools(struct MPT3SAS_ADAPTER *ioc) { int i = 0; int j = 0; + int dma_alloc_count = 0; struct chain_tracker *ct; - struct reply_post_struct *rps; + int count = ioc->rdpq_array_enable ? ioc->reply_queue_count : 1; dexitprintk(ioc, ioc_info(ioc, "%s\n", __func__)); @@ -4870,29 +4851,34 @@ _base_release_memory_pools(struct MPT3SAS_ADAPTER *ioc) } if (ioc->reply_post) { - do { - rps = &ioc->reply_post[i]; - if (rps->reply_post_free) { - dma_pool_free( - ioc->reply_post_free_dma_pool, - rps->reply_post_free, - rps->reply_post_free_dma); - dexitprintk(ioc, - ioc_info(ioc, "reply_post_free_pool(0x%p): free\n", - rps->reply_post_free)); - rps->reply_post_free = NULL; + dma_alloc_count = DIV_ROUND_UP(count, + RDPQ_MAX_INDEX_IN_ONE_CHUNK); + for (i = 0; i < count; i++) { + if (i % RDPQ_MAX_INDEX_IN_ONE_CHUNK == 0 + && dma_alloc_count) { + if (ioc->reply_post[i].reply_post_free) { + dma_pool_free( + ioc->reply_post_free_dma_pool, + ioc->reply_post[i].reply_post_free, + ioc->reply_post[i].reply_post_free_dma); + dexitprintk(ioc, ioc_info(ioc, + "reply_post_free_pool(0x%p): free\n", + ioc->reply_post[i].reply_post_free)); + ioc->reply_post[i].reply_post_free = + NULL; + } + --dma_alloc_count; } - } while (ioc->rdpq_array_enable && - (++i < ioc->reply_queue_count)); + } + dma_pool_destroy(ioc->reply_post_free_dma_pool); if (ioc->reply_post_free_array && ioc->rdpq_array_enable) { dma_pool_free(ioc->reply_post_free_array_dma_pool, - ioc->reply_post_free_array, - ioc->reply_post_free_array_dma); + ioc->reply_post_free_array, + ioc->reply_post_free_array_dma); ioc->reply_post_free_array = NULL; } dma_pool_destroy(ioc->reply_post_free_array_dma_pool); - dma_pool_destroy(ioc->reply_post_free_dma_pool); kfree(ioc->reply_post); } @@ -4902,8 +4888,7 @@ _base_release_memory_pools(struct MPT3SAS_ADAPTER *ioc) ioc->pcie_sg_lookup[i].pcie_sgl, ioc->pcie_sg_lookup[i].pcie_sgl_dma); } - if (ioc->pcie_sgl_dma_pool) - dma_pool_destroy(ioc->pcie_sgl_dma_pool); + dma_pool_destroy(ioc->pcie_sgl_dma_pool); } if (ioc->config_page) { @@ -4915,7 +4900,9 @@ _base_release_memory_pools(struct MPT3SAS_ADAPTER *ioc) } kfree(ioc->hpr_lookup); + ioc->hpr_lookup = NULL; kfree(ioc->internal_lookup); + ioc->internal_lookup = NULL; if (ioc->chain_lookup) { for (i = 0; i < ioc->scsiio_depth; i++) { for (j = ioc->chains_per_prp_buffer; @@ -4935,7 +4922,7 @@ _base_release_memory_pools(struct MPT3SAS_ADAPTER *ioc) } /** - * is_MSB_are_same - checks whether all reply queues in a set are + * mpt3sas_check_same_4gb_region - checks whether all reply queues in a set are * having same upper 32bits in their base memory address. * @reply_pool_start_address: Base address of a reply queue set * @pool_sz: Size of single Reply Descriptor Post Queues pool size @@ -4945,7 +4932,7 @@ _base_release_memory_pools(struct MPT3SAS_ADAPTER *ioc) */ static int -is_MSB_are_same(long reply_pool_start_address, u32 pool_sz) +mpt3sas_check_same_4gb_region(long reply_pool_start_address, u32 pool_sz) { long reply_pool_end_address; @@ -4959,6 +4946,85 @@ is_MSB_are_same(long reply_pool_start_address, u32 pool_sz) } /** + * base_alloc_rdpq_dma_pool - Allocating DMA'able memory + * for reply queues. + * @ioc: per adapter object + * @sz: DMA Pool size + * Return: 0 for success, non-zero for failure. + */ +static int +base_alloc_rdpq_dma_pool(struct MPT3SAS_ADAPTER *ioc, int sz) +{ + int i = 0; + u32 dma_alloc_count = 0; + int reply_post_free_sz = ioc->reply_post_queue_depth * + sizeof(Mpi2DefaultReplyDescriptor_t); + int count = ioc->rdpq_array_enable ? ioc->reply_queue_count : 1; + + ioc->reply_post = kcalloc(count, sizeof(struct reply_post_struct), + GFP_KERNEL); + if (!ioc->reply_post) + return -ENOMEM; + /* + * For INVADER_SERIES each set of 8 reply queues(0-7, 8-15, ..) and + * VENTURA_SERIES each set of 16 reply queues(0-15, 16-31, ..) should + * be within 4GB boundary i.e reply queues in a set must have same + * upper 32-bits in their memory address. so here driver is allocating + * the DMA'able memory for reply queues according. + * Driver uses limitation of + * VENTURA_SERIES to manage INVADER_SERIES as well. + */ + dma_alloc_count = DIV_ROUND_UP(count, + RDPQ_MAX_INDEX_IN_ONE_CHUNK); + ioc->reply_post_free_dma_pool = + dma_pool_create("reply_post_free pool", + &ioc->pdev->dev, sz, 16, 0); + if (!ioc->reply_post_free_dma_pool) + return -ENOMEM; + for (i = 0; i < count; i++) { + if ((i % RDPQ_MAX_INDEX_IN_ONE_CHUNK == 0) && dma_alloc_count) { + ioc->reply_post[i].reply_post_free = + dma_pool_zalloc(ioc->reply_post_free_dma_pool, + GFP_KERNEL, + &ioc->reply_post[i].reply_post_free_dma); + if (!ioc->reply_post[i].reply_post_free) + return -ENOMEM; + /* + * Each set of RDPQ pool must satisfy 4gb boundary + * restriction. + * 1) Check if allocated resources for RDPQ pool are in + * the same 4GB range. + * 2) If #1 is true, continue with 64 bit DMA. + * 3) If #1 is false, return 1. which means free all the + * resources and set DMA mask to 32 and allocate. + */ + if (!mpt3sas_check_same_4gb_region( + (long)ioc->reply_post[i].reply_post_free, sz)) { + dinitprintk(ioc, + ioc_err(ioc, "bad Replypost free pool(0x%p)" + "reply_post_free_dma = (0x%llx)\n", + ioc->reply_post[i].reply_post_free, + (unsigned long long) + ioc->reply_post[i].reply_post_free_dma)); + return -EAGAIN; + } + dma_alloc_count--; + + } else { + ioc->reply_post[i].reply_post_free = + (Mpi2ReplyDescriptorsUnion_t *) + ((long)ioc->reply_post[i-1].reply_post_free + + reply_post_free_sz); + ioc->reply_post[i].reply_post_free_dma = + (dma_addr_t) + (ioc->reply_post[i-1].reply_post_free_dma + + reply_post_free_sz); + } + } + return 0; +} + +/** * _base_allocate_memory_pools - allocate start of day memory pools * @ioc: per adapter object * @@ -4972,10 +5038,12 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc) u16 chains_needed_per_io; u32 sz, total_sz, reply_post_free_sz, reply_post_free_array_sz; u32 retry_sz; + u32 rdpq_sz = 0; u16 max_request_credit, nvme_blocks_needed; unsigned short sg_tablesize; u16 sge_size; int i, j; + int ret = 0; struct chain_tracker *ct; dinitprintk(ioc, ioc_info(ioc, "%s\n", __func__)); @@ -5129,54 +5197,28 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc) /* reply post queue, 16 byte align */ reply_post_free_sz = ioc->reply_post_queue_depth * sizeof(Mpi2DefaultReplyDescriptor_t); - - sz = reply_post_free_sz; + rdpq_sz = reply_post_free_sz * RDPQ_MAX_INDEX_IN_ONE_CHUNK; if (_base_is_controller_msix_enabled(ioc) && !ioc->rdpq_array_enable) - sz *= ioc->reply_queue_count; - - ioc->reply_post = kcalloc((ioc->rdpq_array_enable) ? - (ioc->reply_queue_count):1, - sizeof(struct reply_post_struct), GFP_KERNEL); - - if (!ioc->reply_post) { - ioc_err(ioc, "reply_post_free pool: kcalloc failed\n"); - goto out; - } - ioc->reply_post_free_dma_pool = dma_pool_create("reply_post_free pool", - &ioc->pdev->dev, sz, 16, 0); - if (!ioc->reply_post_free_dma_pool) { - ioc_err(ioc, "reply_post_free pool: dma_pool_create failed\n"); - goto out; - } - i = 0; - do { - ioc->reply_post[i].reply_post_free = - dma_pool_zalloc(ioc->reply_post_free_dma_pool, - GFP_KERNEL, - &ioc->reply_post[i].reply_post_free_dma); - if (!ioc->reply_post[i].reply_post_free) { - ioc_err(ioc, "reply_post_free pool: dma_pool_alloc failed\n"); - goto out; - } - dinitprintk(ioc, - ioc_info(ioc, "reply post free pool (0x%p): depth(%d), element_size(%d), pool_size(%d kB)\n", - ioc->reply_post[i].reply_post_free, - ioc->reply_post_queue_depth, - 8, sz / 1024)); - dinitprintk(ioc, - ioc_info(ioc, "reply_post_free_dma = (0x%llx)\n", - (u64)ioc->reply_post[i].reply_post_free_dma)); - total_sz += sz; - } while (ioc->rdpq_array_enable && (++i < ioc->reply_queue_count)); - - if (ioc->dma_mask > 32) { - if (_base_change_consistent_dma_mask(ioc, ioc->pdev) != 0) { - ioc_warn(ioc, "no suitable consistent DMA mask for %s\n", - pci_name(ioc->pdev)); - goto out; + rdpq_sz = reply_post_free_sz * ioc->reply_queue_count; + ret = base_alloc_rdpq_dma_pool(ioc, rdpq_sz); + if (ret == -EAGAIN) { + /* + * Free allocated bad RDPQ memory pools. + * Change dma coherent mask to 32 bit and reallocate RDPQ + */ + _base_release_memory_pools(ioc); + ioc->use_32bit_dma = true; + if (_base_config_dma_addressing(ioc, ioc->pdev) != 0) { + ioc_err(ioc, + "32 DMA mask failed %s\n", pci_name(ioc->pdev)); + return -ENODEV; } - } - + if (base_alloc_rdpq_dma_pool(ioc, rdpq_sz)) + return -ENOMEM; + } else if (ret == -ENOMEM) + return -ENOMEM; + total_sz = rdpq_sz * (!ioc->rdpq_array_enable ? 1 : + DIV_ROUND_UP(ioc->reply_queue_count, RDPQ_MAX_INDEX_IN_ONE_CHUNK)); ioc->scsiio_depth = ioc->hba_queue_depth - ioc->hi_priority_depth - ioc->internal_depth; @@ -5188,7 +5230,6 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc) ioc_info(ioc, "scsi host: can_queue depth (%d)\n", ioc->shost->can_queue)); - /* contiguous pool for request and chains, 16 byte align, one extra " * "frame for smid=0 */ @@ -5405,7 +5446,7 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc) * Actual requirement is not alignment, but we need start and end of * DMA address must have same upper 32 bit address. */ - if (!is_MSB_are_same((long)ioc->sense, sz)) { + if (!mpt3sas_check_same_4gb_region((long)ioc->sense, sz)) { //Release Sense pool & Reallocate dma_pool_free(ioc->sense_dma_pool, ioc->sense, ioc->sense_dma); dma_pool_destroy(ioc->sense_dma_pool); @@ -7158,7 +7199,7 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc) ioc->smp_affinity_enable = smp_affinity_enable; ioc->rdpq_array_enable_assigned = 0; - ioc->dma_mask = 0; + ioc->use_32bit_dma = false; if (ioc->is_aero_ioc) ioc->base_readl = &_base_readl_aero; else diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index e7197150721f..4fca3939c034 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -76,8 +76,8 @@ #define MPT3SAS_DRIVER_NAME "mpt3sas" #define MPT3SAS_AUTHOR "Avago Technologies <MPT-FusionLinux.pdl@avagotech.com>" #define MPT3SAS_DESCRIPTION "LSI MPT Fusion SAS 3.0 Device Driver" -#define MPT3SAS_DRIVER_VERSION "33.100.00.00" -#define MPT3SAS_MAJOR_VERSION 33 +#define MPT3SAS_DRIVER_VERSION "34.100.00.00" +#define MPT3SAS_MAJOR_VERSION 34 #define MPT3SAS_MINOR_VERSION 100 #define MPT3SAS_BUILD_VERSION 0 #define MPT3SAS_RELEASE_VERSION 00 @@ -367,6 +367,7 @@ struct mpt3sas_nvme_cmd { #define MPT3SAS_HIGH_IOPS_REPLY_QUEUES 8 #define MPT3SAS_HIGH_IOPS_BATCH_COUNT 16 #define MPT3SAS_GEN35_MAX_MSIX_QUEUES 128 +#define RDPQ_MAX_INDEX_IN_ONE_CHUNK 16 /* OEM Specific Flags will come from OEM specific header files */ struct Mpi2ManufacturingPage10_t { @@ -1026,7 +1027,6 @@ typedef void (*MPT3SAS_FLUSH_RUNNING_CMDS)(struct MPT3SAS_ADAPTER *ioc); * @ir_firmware: IR firmware present * @bars: bitmask of BAR's that must be configured * @mask_interrupts: ignore interrupt - * @dma_mask: used to set the consistent dma mask * @pci_access_mutex: Mutex to synchronize ioctl, sysfs show path and * pci resource handling * @fault_reset_work_q_name: fw fault work queue @@ -1064,6 +1064,7 @@ typedef void (*MPT3SAS_FLUSH_RUNNING_CMDS)(struct MPT3SAS_ADAPTER *ioc); * @thresh_hold: Max number of reply descriptors processed * before updating Host Index * @drv_support_bitmap: driver's supported feature bit map + * @use_32bit_dma: Flag to use 32 bit consistent dma mask * @scsi_io_cb_idx: shost generated commands * @tm_cb_idx: task management commands * @scsih_cb_idx: scsih internal commands @@ -1205,7 +1206,6 @@ struct MPT3SAS_ADAPTER { u8 ir_firmware; int bars; u8 mask_interrupts; - int dma_mask; /* fw fault handler */ char fault_reset_work_q_name[20]; @@ -1254,6 +1254,7 @@ struct MPT3SAS_ADAPTER { u8 high_iops_queues; u32 drv_support_bitmap; bool enable_sdev_max_qd; + bool use_32bit_dma; /* internal commands, callback index */ u8 scsi_io_cb_idx; @@ -1471,6 +1472,8 @@ struct MPT3SAS_ADAPTER { u16 device_remove_in_progress_sz; u8 is_gen35_ioc; u8 is_aero_ioc; + struct dentry *debugfs_root; + struct dentry *ioc_dump; PUT_SMID_IO_FP_HIP put_smid_scsi_io; PUT_SMID_IO_FP_HIP put_smid_fast_path; PUT_SMID_IO_FP_HIP put_smid_hi_priority; @@ -1478,6 +1481,11 @@ struct MPT3SAS_ADAPTER { GET_MSIX_INDEX get_msix_index_for_smlio; }; +struct mpt3sas_debugfs_buffer { + void *buf; + u32 len; +}; + #define MPT_DRV_SUPPORT_BITMAP_MEMMOVE 0x00000001 typedef u8 (*MPT_CALLBACK)(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, @@ -1781,6 +1789,11 @@ mpt3sas_setup_direct_io(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, /* NCQ Prio Handling Check */ bool scsih_ncq_prio_supp(struct scsi_device *sdev); +void mpt3sas_setup_debugfs(struct MPT3SAS_ADAPTER *ioc); +void mpt3sas_destroy_debugfs(struct MPT3SAS_ADAPTER *ioc); +void mpt3sas_init_debugfs(void); +void mpt3sas_exit_debugfs(void); + /** * _scsih_is_pcie_scsi_device - determines if device is an pcie scsi device * @device_info: bitfield providing information about the device. diff --git a/drivers/scsi/mpt3sas/mpt3sas_debugfs.c b/drivers/scsi/mpt3sas/mpt3sas_debugfs.c new file mode 100644 index 000000000000..a6ab1db81167 --- /dev/null +++ b/drivers/scsi/mpt3sas/mpt3sas_debugfs.c @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Debugfs interface Support for MPT (Message Passing Technology) based + * controllers. + * + * Copyright (C) 2020 Broadcom Inc. + * + * Authors: Broadcom Inc. + * Sreekanth Reddy <sreekanth.reddy@broadcom.com> + * Suganath Prabu <suganath-prabu.subramani@broadcom.com> + * + * Send feedback to : MPT-FusionLinux.pdl@broadcom.com) + * + **/ + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/pci.h> +#include <linux/interrupt.h> +#include <linux/compat.h> +#include <linux/uio.h> + +#include <scsi/scsi.h> +#include <scsi/scsi_device.h> +#include <scsi/scsi_host.h> +#include "mpt3sas_base.h" +#include <linux/debugfs.h> + +static struct dentry *mpt3sas_debugfs_root; + +/* + * _debugfs_iocdump_read - copy ioc dump from debugfs buffer + * @filep: File Pointer + * @ubuf: Buffer to fill data + * @cnt: Length of the buffer + * @ppos: Offset in the file + */ + +static ssize_t +_debugfs_iocdump_read(struct file *filp, char __user *ubuf, size_t cnt, + loff_t *ppos) + +{ + struct mpt3sas_debugfs_buffer *debug = filp->private_data; + + if (!debug || !debug->buf) + return 0; + + return simple_read_from_buffer(ubuf, cnt, ppos, debug->buf, debug->len); +} + +/* + * _debugfs_iocdump_open : open the ioc_dump debugfs attribute file + */ +static int +_debugfs_iocdump_open(struct inode *inode, struct file *file) +{ + struct MPT3SAS_ADAPTER *ioc = inode->i_private; + struct mpt3sas_debugfs_buffer *debug; + + debug = kzalloc(sizeof(struct mpt3sas_debugfs_buffer), GFP_KERNEL); + if (!debug) + return -ENOMEM; + + debug->buf = (void *)ioc; + debug->len = sizeof(struct MPT3SAS_ADAPTER); + file->private_data = debug; + return 0; +} + +/* + * _debugfs_iocdump_release : release the ioc_dump debugfs attribute + * @inode: inode structure to the corresponds device + * @file: File pointer + */ +static int +_debugfs_iocdump_release(struct inode *inode, struct file *file) +{ + struct mpt3sas_debugfs_buffer *debug = file->private_data; + + if (!debug) + return 0; + + file->private_data = NULL; + kfree(debug); + return 0; +} + +static const struct file_operations mpt3sas_debugfs_iocdump_fops = { + .owner = THIS_MODULE, + .open = _debugfs_iocdump_open, + .read = _debugfs_iocdump_read, + .release = _debugfs_iocdump_release, +}; + +/* + * mpt3sas_init_debugfs : Create debugfs root for mpt3sas driver + */ +void mpt3sas_init_debugfs(void) +{ + mpt3sas_debugfs_root = debugfs_create_dir("mpt3sas", NULL); + if (!mpt3sas_debugfs_root) + pr_info("mpt3sas: Cannot create debugfs root\n"); +} + +/* + * mpt3sas_exit_debugfs : Remove debugfs root for mpt3sas driver + */ +void mpt3sas_exit_debugfs(void) +{ + debugfs_remove_recursive(mpt3sas_debugfs_root); +} + +/* + * mpt3sas_setup_debugfs : Setup debugfs per HBA adapter + * ioc: MPT3SAS_ADAPTER object + */ +void +mpt3sas_setup_debugfs(struct MPT3SAS_ADAPTER *ioc) +{ + char name[64]; + + snprintf(name, sizeof(name), "scsi_host%d", ioc->shost->host_no); + if (!ioc->debugfs_root) { + ioc->debugfs_root = + debugfs_create_dir(name, mpt3sas_debugfs_root); + if (!ioc->debugfs_root) { + dev_err(&ioc->pdev->dev, + "Cannot create per adapter debugfs directory\n"); + return; + } + } + + snprintf(name, sizeof(name), "ioc_dump"); + ioc->ioc_dump = debugfs_create_file(name, 0444, + ioc->debugfs_root, ioc, &mpt3sas_debugfs_iocdump_fops); + if (!ioc->ioc_dump) { + dev_err(&ioc->pdev->dev, + "Cannot create ioc_dump debugfs file\n"); + debugfs_remove(ioc->debugfs_root); + return; + } + + snprintf(name, sizeof(name), "host_recovery"); + debugfs_create_u8(name, 0444, ioc->debugfs_root, &ioc->shost_recovery); + +} + +/* + * mpt3sas_destroy_debugfs : Destroy debugfs per HBA adapter + * @ioc: MPT3SAS_ADAPTER object + */ +void mpt3sas_destroy_debugfs(struct MPT3SAS_ADAPTER *ioc) +{ + debugfs_remove_recursive(ioc->debugfs_root); +} + diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 04a40afe60e3..08fc4b381056 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -9928,6 +9928,7 @@ static void scsih_remove(struct pci_dev *pdev) &ioc->ioc_pg1_copy); /* release all the volumes */ _scsih_ir_shutdown(ioc); + mpt3sas_destroy_debugfs(ioc); sas_remove_host(shost); list_for_each_entry_safe(raid_device, next, &ioc->raid_device_list, list) { @@ -10763,8 +10764,8 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) } } /* register EEDP capabilities with SCSI layer */ - if (prot_mask > 0) - scsi_host_set_prot(shost, prot_mask); + if (prot_mask >= 0) + scsi_host_set_prot(shost, (prot_mask & 0x07)); else scsi_host_set_prot(shost, SHOST_DIF_TYPE1_PROTECTION | SHOST_DIF_TYPE2_PROTECTION @@ -10814,6 +10815,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) } scsi_scan_host(shost); + mpt3sas_setup_debugfs(ioc); return 0; out_add_shost_fail: mpt3sas_base_detach(ioc); @@ -11220,6 +11222,7 @@ scsih_init(void) tm_sas_control_cb_idx = mpt3sas_base_register_callback_handler( _scsih_sas_control_complete); + mpt3sas_init_debugfs(); return 0; } @@ -11251,6 +11254,7 @@ scsih_exit(void) if (hbas_to_enumerate != 2) raid_class_release(mpt2sas_raid_template); sas_release_transport(mpt3sas_transport_template); + mpt3sas_exit_debugfs(); } /** |