Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

scsi: mpt3sas: Enable interrupt coalescing on high iops

Enable interrupt coalescing only on high iops queues.

In ioc config page 1, offset 0x14 (ProductSpecific field) is used to
determine interrupt coalescing enabled/disabled on per reply descriptor
post queue group(8) basis. If 31st bit is zero, then interrupt coalescing
is enabled for all reply descriptor post queues. If 31st bit is set to one,
then user can enable/disable interrupt coalescing on per reply descriptor
post queue group(8) basis. So to enable interrupt coalescing only on first
reply descriptor post queue group (i.e. on high iops queues), set bit 0 and
31.

This configuration should reset during driver unload or shutdown to the
default settings. For this, the driver takes copy of default ioc page 1 and
copies back the default or unmodified ioc page1 during unload and
shutdown. This means that on next driver load (e.g. if older version driver
is loaded by user), current modified changes on ioc page1 won't take
effect.

Signed-off-by: Suganath Prabu S <suganath-prabu.subramani@broadcom.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

authored by

Suganath Prabu S and committed by
Martin K. Petersen
2426f209 728bbc6c

+109 -2
+1 -1
drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h
··· 1398 1398 U8 PCIBusNum; /*0x0E */ 1399 1399 U8 PCIDomainSegment; /*0x0F */ 1400 1400 U32 Reserved1; /*0x10 */ 1401 - U32 Reserved2; /*0x14 */ 1401 + U32 ProductSpecific; /* 0x14 */ 1402 1402 } MPI2_CONFIG_PAGE_IOC_1, 1403 1403 *PTR_MPI2_CONFIG_PAGE_IOC_1, 1404 1404 Mpi2IOCPage1_t, *pMpi2IOCPage1_t;
+16
drivers/scsi/mpt3sas/mpt3sas_base.c
··· 4439 4439 { 4440 4440 Mpi2ConfigReply_t mpi_reply; 4441 4441 u32 iounit_pg1_flags; 4442 + Mpi2IOCPage1_t ioc_pg1; 4442 4443 4443 4444 ioc->nvme_abort_timeout = 30; 4444 4445 mpt3sas_config_get_manufacturing_pg0(ioc, &mpi_reply, &ioc->manu_pg0); ··· 4471 4470 ioc->nvme_abort_timeout = NVME_TASK_ABORT_MAX_TIMEOUT; 4472 4471 else 4473 4472 ioc->nvme_abort_timeout = ioc->manu_pg11.NVMeAbortTO; 4473 + } 4474 + if (ioc->high_iops_queues) { 4475 + mpt3sas_config_get_ioc_pg1(ioc, &mpi_reply, &ioc_pg1); 4476 + pr_info( 4477 + "%s Enable interrupt coalescing only for first reply queue group(8)\n", 4478 + ioc->name); 4479 + /* If 31st bit is zero then interrupt coalescing is enabled 4480 + * for all reply descriptor post queues. If 31st bit is set 4481 + * to one then user can enable/disable interrupt coalescing 4482 + * on per reply descriptor post queue group(8) basis. So to 4483 + * enable interrupt coalescing only on first reply descriptor 4484 + * post queue group 31st bit and zeroth bit is enabled. 4485 + */ 4486 + ioc_pg1.ProductSpecific = cpu_to_le32(0x80000001); 4487 + mpt3sas_config_set_ioc_pg1(ioc, &mpi_reply, &ioc_pg1); 4474 4488 } 4475 4489 4476 4490 mpt3sas_config_get_bios_pg2(ioc, &mpi_reply, &ioc->bios_pg2);
+5
drivers/scsi/mpt3sas/mpt3sas_base.h
··· 1286 1286 Mpi2IOUnitPage0_t iounit_pg0; 1287 1287 Mpi2IOUnitPage1_t iounit_pg1; 1288 1288 Mpi2IOUnitPage8_t iounit_pg8; 1289 + Mpi2IOCPage1_t ioc_pg1_copy; 1289 1290 1290 1291 struct _boot_device req_boot_device; 1291 1292 struct _boot_device req_alt_boot_device; ··· 1635 1634 int mpt3sas_config_set_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc, 1636 1635 Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page, 1637 1636 u16 sz); 1637 + int mpt3sas_config_get_ioc_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t 1638 + *mpi_reply, Mpi2IOCPage1_t *config_page); 1639 + int mpt3sas_config_set_ioc_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t 1640 + *mpi_reply, Mpi2IOCPage1_t *config_page); 1638 1641 int mpt3sas_config_get_ioc_pg8(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t 1639 1642 *mpi_reply, Mpi2IOCPage8_t *config_page); 1640 1643 int mpt3sas_config_get_expander_pg0(struct MPT3SAS_ADAPTER *ioc,
+71
drivers/scsi/mpt3sas/mpt3sas_config.c
··· 949 949 out: 950 950 return r; 951 951 } 952 + /** 953 + * mpt3sas_config_get_ioc_pg1 - obtain ioc page 1 954 + * @ioc: per adapter object 955 + * @mpi_reply: reply mf payload returned from firmware 956 + * @config_page: contents of the config page 957 + * Context: sleep. 958 + * 959 + * Return: 0 for success, non-zero for failure. 960 + */ 961 + int 962 + mpt3sas_config_get_ioc_pg1(struct MPT3SAS_ADAPTER *ioc, 963 + Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage1_t *config_page) 964 + { 965 + Mpi2ConfigRequest_t mpi_request; 966 + int r; 967 + 968 + memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 969 + mpi_request.Function = MPI2_FUNCTION_CONFIG; 970 + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 971 + mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC; 972 + mpi_request.Header.PageNumber = 1; 973 + mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION; 974 + ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 975 + r = _config_request(ioc, &mpi_request, mpi_reply, 976 + MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 977 + if (r) 978 + goto out; 979 + 980 + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 981 + r = _config_request(ioc, &mpi_request, mpi_reply, 982 + MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 983 + sizeof(*config_page)); 984 + out: 985 + return r; 986 + } 987 + 988 + /** 989 + * mpt3sas_config_set_ioc_pg1 - modify ioc page 1 990 + * @ioc: per adapter object 991 + * @mpi_reply: reply mf payload returned from firmware 992 + * @config_page: contents of the config page 993 + * Context: sleep. 994 + * 995 + * Return: 0 for success, non-zero for failure. 996 + */ 997 + int 998 + mpt3sas_config_set_ioc_pg1(struct MPT3SAS_ADAPTER *ioc, 999 + Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage1_t *config_page) 1000 + { 1001 + Mpi2ConfigRequest_t mpi_request; 1002 + int r; 1003 + 1004 + memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); 1005 + mpi_request.Function = MPI2_FUNCTION_CONFIG; 1006 + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1007 + mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC; 1008 + mpi_request.Header.PageNumber = 1; 1009 + mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION; 1010 + ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); 1011 + r = _config_request(ioc, &mpi_request, mpi_reply, 1012 + MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); 1013 + if (r) 1014 + goto out; 1015 + 1016 + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT; 1017 + r = _config_request(ioc, &mpi_request, mpi_reply, 1018 + MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, 1019 + sizeof(*config_page)); 1020 + out: 1021 + return r; 1022 + } 952 1023 953 1024 /** 954 1025 * mpt3sas_config_get_sas_device_pg0 - obtain sas device page 0
+16 -1
drivers/scsi/mpt3sas/mpt3sas_scsih.c
··· 9671 9671 struct _pcie_device *pcie_device, *pcienext; 9672 9672 struct workqueue_struct *wq; 9673 9673 unsigned long flags; 9674 + Mpi2ConfigReply_t mpi_reply; 9674 9675 9675 9676 ioc->remove_host = 1; 9676 9677 ··· 9686 9685 spin_unlock_irqrestore(&ioc->fw_event_lock, flags); 9687 9686 if (wq) 9688 9687 destroy_workqueue(wq); 9689 - 9688 + /* 9689 + * Copy back the unmodified ioc page1. so that on next driver load, 9690 + * current modified changes on ioc page1 won't take effect. 9691 + */ 9692 + if (ioc->is_aero_ioc) 9693 + mpt3sas_config_set_ioc_pg1(ioc, &mpi_reply, 9694 + &ioc->ioc_pg1_copy); 9690 9695 /* release all the volumes */ 9691 9696 _scsih_ir_shutdown(ioc); 9692 9697 sas_remove_host(shost); ··· 9755 9748 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); 9756 9749 struct workqueue_struct *wq; 9757 9750 unsigned long flags; 9751 + Mpi2ConfigReply_t mpi_reply; 9758 9752 9759 9753 ioc->remove_host = 1; 9760 9754 ··· 9770 9762 spin_unlock_irqrestore(&ioc->fw_event_lock, flags); 9771 9763 if (wq) 9772 9764 destroy_workqueue(wq); 9765 + /* 9766 + * Copy back the unmodified ioc page1 so that on next driver load, 9767 + * current modified changes on ioc page1 won't take effect. 9768 + */ 9769 + if (ioc->is_aero_ioc) 9770 + mpt3sas_config_set_ioc_pg1(ioc, &mpi_reply, 9771 + &ioc->ioc_pg1_copy); 9773 9772 9774 9773 _scsih_ir_shutdown(ioc); 9775 9774 mpt3sas_base_detach(ioc);