linux-scsi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/12] pm80xx : Updates for the driver version 0.1.39.
@ 2019-12-24  4:41 Deepak Ukey
  2019-12-24  4:41 ` [PATCH 01/12] pm80xx : Increase request sg length Deepak Ukey
                   ` (11 more replies)
  0 siblings, 12 replies; 33+ messages in thread
From: Deepak Ukey @ 2019-12-24  4:41 UTC (permalink / raw)
  To: linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, deepak.ukey, jinpu.wang,
	martin.petersen, dpf, yuuzheng, auradkar, vishakhavc, bjashnani,
	radha, akshatzen

From: Deepak Ukey <Deepak.Ukey@microchip.com>

This patch set includes some bug fixes and features for pm80xx driver.

Deepak Ukey (4):
  pm80xx : Support for char device.
  pm80xx : IOCTL functionality for GPIO.
  pm80xx : IOCTL functionality for SGPIO.
  pm80xx : sysfs attribute for non fatal dump.

Peter Chang (2):
  pm80xx : Increase request sg length.
  pm80xx : Cleanup initialization loading fail path.

Vikram Auradkar (1):
  pm80xx : Deal with kexec reboots.

Viswas G (4):
  pm80xx : sysfs attribute for number of phys.
  pm80xx : IOCTL functionality to get phy profile.
  pm80xx : Introduce read and write length for IOCTL payload structure.
  pm80xx : IOCTL functionality for TWI device.

yuuzheng (1):
  pm80xx : Free the tag when mpi_set_phy_profile_resp is received.

 drivers/scsi/Kconfig              |   7 +
 drivers/scsi/pm8001/pm8001_ctl.c  | 665 +++++++++++++++++++++++++++++++++++++-
 drivers/scsi/pm8001/pm8001_ctl.h  | 185 +++++++++++
 drivers/scsi/pm8001/pm8001_defs.h |   5 +-
 drivers/scsi/pm8001/pm8001_hwi.c  | 303 +++++++++++++++--
 drivers/scsi/pm8001/pm8001_hwi.h  |  18 ++
 drivers/scsi/pm8001/pm8001_init.c | 104 ++++--
 drivers/scsi/pm8001/pm8001_sas.c  |  37 +++
 drivers/scsi/pm8001/pm8001_sas.h  |  72 ++++-
 drivers/scsi/pm8001/pm80xx_hwi.c  | 390 +++++++++++++++++++++-
 drivers/scsi/pm8001/pm80xx_hwi.h  |  55 ++++
 11 files changed, 1779 insertions(+), 62 deletions(-)

-- 
2.16.3


^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 01/12] pm80xx : Increase request sg length.
  2019-12-24  4:41 [PATCH 00/12] pm80xx : Updates for the driver version 0.1.39 Deepak Ukey
@ 2019-12-24  4:41 ` Deepak Ukey
  2019-12-25 15:57   ` kbuild test robot
  2019-12-24  4:41 ` [PATCH 02/12] pm80xx : Deal with kexec reboots Deepak Ukey
                   ` (10 subsequent siblings)
  11 siblings, 1 reply; 33+ messages in thread
From: Deepak Ukey @ 2019-12-24  4:41 UTC (permalink / raw)
  To: linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, deepak.ukey, jinpu.wang,
	martin.petersen, dpf, yuuzheng, auradkar, vishakhavc, bjashnani,
	radha, akshatzen

From: Peter Chang <dpf@google.com>

Increasing the per-request size maximum (max_sectors_kb) runs into
the per-device dma scatter gather list limit (max_segments) for
users of the io vector system calls (eg, readv and writev). This is
because the kernel combines io vectors into dma segments when
possible, but it doesn't work for our user because the vectors in the
buffer cache get scrambled.
This change bumps the advertised max scatter gather length to 528 to
cover 2M w/ x86's 4k pages and some extra for the user checksum.
It trims the size of some of the tables we don't care about and
exposes all of the command slots upstream to the scsi layer.

Signed-off-by: Peter Chang <dpf@google.com>
Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
Signed-off-by: Viswas G <Viswas.G@microchip.com>
Signed-off-by: Vishakha Channapattan <vishakhavc@google.com>
Signed-off-by: Bhavesh Jashnani <bjashnani@google.com>
Signed-off-by: Radha Ramachandran <radha@google.com>
Signed-off-by: Akshat Jain <akshatzen@google.com>
Signed-off-by: Yu Zheng <yuuzheng@google.com>
---
 drivers/scsi/Kconfig              | 7 +++++++
 drivers/scsi/pm8001/pm8001_defs.h | 5 +++--
 drivers/scsi/pm8001/pm8001_init.c | 2 +-
 3 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 90cf4691b8c3..da2073a67b24 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -1504,6 +1504,13 @@ config SCSI_PM8001
 	  This driver supports PMC-Sierra PCIE SAS/SATA 8x6G SPC 8001 chip
 	  based host adapters.
 
+config SCSI_PM8001_MAX_DMA_SG
+	int "max segments per request"
+	depends on SCSI_PM8001
+	default 128
+	help
+	  Allow for larger requests bound by MAX_ORDER of the ccb table.
+
 config SCSI_BFA_FC
 	tristate "Brocade BFA Fibre Channel Support"
 	depends on PCI && SCSI
diff --git a/drivers/scsi/pm8001/pm8001_defs.h b/drivers/scsi/pm8001/pm8001_defs.h
index 48e0624ecc68..1c7f15fd69ce 100644
--- a/drivers/scsi/pm8001/pm8001_defs.h
+++ b/drivers/scsi/pm8001/pm8001_defs.h
@@ -75,7 +75,7 @@ enum port_type {
 };
 
 /* driver compile-time configuration */
-#define	PM8001_MAX_CCB		 512	/* max ccbs supported */
+#define	PM8001_MAX_CCB		 256	/* max ccbs supported */
 #define PM8001_MPI_QUEUE         1024   /* maximum mpi queue entries */
 #define	PM8001_MAX_INB_NUM	 1
 #define	PM8001_MAX_OUTB_NUM	 1
@@ -99,7 +99,8 @@ enum port_type {
 #define OB			(CI + PM8001_MAX_SPCV_INB_NUM)
 #define PI			(OB + PM8001_MAX_SPCV_OUTB_NUM)
 #define USI_MAX_MEMCNT		(PI + PM8001_MAX_SPCV_OUTB_NUM)
-#define PM8001_MAX_DMA_SG	SG_ALL
+#define	CONFIG_SCSI_PM8001_MAX_DMA_SG	528
+#define PM8001_MAX_DMA_SG	CONFIG_SCSI_PM8001_MAX_DMA_SG
 enum memory_region_num {
 	AAP1 = 0x0, /* application acceleration processor */
 	IOP,	    /* IO processor */
diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c
index ff618ad80ebd..3f1e755c52c6 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -95,7 +95,7 @@ static struct scsi_host_template pm8001_sht = {
 	.bios_param		= sas_bios_param,
 	.can_queue		= 1,
 	.this_id		= -1,
-	.sg_tablesize		= SG_ALL,
+	.sg_tablesize		= PM8001_MAX_DMA_SG,
 	.max_sectors		= SCSI_DEFAULT_MAX_SECTORS,
 	.eh_device_reset_handler = sas_eh_device_reset_handler,
 	.eh_target_reset_handler = sas_eh_target_reset_handler,
-- 
2.16.3


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 02/12] pm80xx : Deal with kexec reboots.
  2019-12-24  4:41 [PATCH 00/12] pm80xx : Updates for the driver version 0.1.39 Deepak Ukey
  2019-12-24  4:41 ` [PATCH 01/12] pm80xx : Increase request sg length Deepak Ukey
@ 2019-12-24  4:41 ` Deepak Ukey
  2020-01-02 11:52   ` Jinpu Wang
  2019-12-24  4:41 ` [PATCH 03/12] pm80xx : Free the tag when mpi_set_phy_profile_resp is received Deepak Ukey
                   ` (9 subsequent siblings)
  11 siblings, 1 reply; 33+ messages in thread
From: Deepak Ukey @ 2019-12-24  4:41 UTC (permalink / raw)
  To: linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, deepak.ukey, jinpu.wang,
	martin.petersen, dpf, yuuzheng, auradkar, vishakhavc, bjashnani,
	radha, akshatzen

From: Vikram Auradkar <auradkar@google.com>

A kexec reboot causes the controller fw to assert. This assertion
shows up in two ways, the controller doesn't show up as ready and
an interrupt is waiting as soon as the handler is registered. To
resolve this added below fix:
-split the interrupt handling setup into two parts, setup and
 request.
-If the controller ready register indicates not-ready, but that the
 not readiness is only on the IOC units we can still try a reset to
 bring the system back to the pre-reboot state.

Signed-off-by: Vikram Auradkar <auradkar@google.com>
Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
Signed-off-by: Viswas G <Viswas.G@microchip.com>
Signed-off-by: Vishakha Channapattan <vishakhavc@google.com>
Signed-off-by: Bhavesh Jashnani <bjashnani@google.com>
Signed-off-by: Radha Ramachandran <radha@google.com>
Signed-off-by: Akshat Jain <akshatzen@google.com>
Signed-off-by: Yu Zheng <yuuzheng@google.com>
---
 drivers/scsi/pm8001/pm8001_init.c | 48 +++++++++++++++++++++++++++++++++++----
 drivers/scsi/pm8001/pm80xx_hwi.c  | 15 ++++++++----
 2 files changed, 54 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c
index 3f1e755c52c6..a002eb5a3fe4 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -248,6 +248,9 @@ static irqreturn_t pm8001_interrupt_handler_intx(int irq, void *dev_id)
 	return ret;
 }
 
+static u32 pm8001_setup_irq(struct pm8001_hba_info *pm8001_ha);
+static u32 pm8001_request_irq(struct pm8001_hba_info *pm8001_ha);
+
 /**
  * pm8001_alloc - initiate our hba structure and 6 DMAs area.
  * @pm8001_ha:our hba structure.
@@ -890,9 +893,7 @@ static int pm8001_configure_phy_settings(struct pm8001_hba_info *pm8001_ha)
  */
 static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha)
 {
-	u32 i = 0, j = 0;
 	u32 number_of_intr;
-	int flag = 0;
 	int rc;
 
 	/* SPCv controllers supports 64 msi-x */
@@ -900,11 +901,11 @@ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha)
 		number_of_intr = 1;
 	} else {
 		number_of_intr = PM8001_MAX_MSIX_VEC;
-		flag &= ~IRQF_SHARED;
 	}
 
 	rc = pci_alloc_irq_vectors(pm8001_ha->pdev, number_of_intr,
 			number_of_intr, PCI_IRQ_MSIX);
+	number_of_intr = rc;
 	if (rc < 0)
 		return rc;
 	pm8001_ha->number_of_intr = number_of_intr;
@@ -912,8 +913,22 @@ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha)
 	PM8001_INIT_DBG(pm8001_ha, pm8001_printk(
 		"pci_alloc_irq_vectors request ret:%d no of intr %d\n",
 				rc, pm8001_ha->number_of_intr));
+	return 0;
+}
+
+static u32 pm8001_request_msix(struct pm8001_hba_info *pm8001_ha)
+{
+	u32 i = 0, j = 0;
+	int flag = 0, rc = 0;
 
-	for (i = 0; i < number_of_intr; i++) {
+	if (pm8001_ha->chip_id != chip_8001)
+		flag &= ~IRQF_SHARED;
+
+	PM8001_INIT_DBG(pm8001_ha,
+		pm8001_printk("pci_enable_msix request number of intr %d\n",
+		pm8001_ha->number_of_intr));
+
+	for (i = 0; i < pm8001_ha->number_of_intr; i++) {
 		snprintf(pm8001_ha->intr_drvname[i],
 			sizeof(pm8001_ha->intr_drvname[0]),
 			"%s-%d", pm8001_ha->name, i);
@@ -938,6 +953,21 @@ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha)
 }
 #endif
 
+static u32 pm8001_setup_irq(struct pm8001_hba_info *pm8001_ha)
+{
+	struct pci_dev *pdev;
+
+	pdev = pm8001_ha->pdev;
+
+#ifdef PM8001_USE_MSIX
+	if (pci_find_capability(pdev, PCI_CAP_ID_MSIX))
+		return pm8001_setup_msix(pm8001_ha);
+	PM8001_INIT_DBG(pm8001_ha,
+		pm8001_printk("MSIX not supported!!!\n"));
+#endif
+	return 0;
+}
+
 /**
  * pm8001_request_irq - register interrupt
  * @chip_info: our ha struct.
@@ -951,7 +981,7 @@ static u32 pm8001_request_irq(struct pm8001_hba_info *pm8001_ha)
 
 #ifdef PM8001_USE_MSIX
 	if (pdev->msix_cap && pci_msi_enabled())
-		return pm8001_setup_msix(pm8001_ha);
+		return pm8001_request_msix(pm8001_ha);
 	else {
 		PM8001_INIT_DBG(pm8001_ha,
 			pm8001_printk("MSIX not supported!!!\n"));
@@ -1033,6 +1063,13 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
 		rc = -ENOMEM;
 		goto err_out_free;
 	}
+	/* Setup Interrupt */
+	rc = pm8001_setup_irq(pm8001_ha);
+	if (rc)	{
+		PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
+			"pm8001_setup_irq failed [ret: %d]\n", rc));
+		goto err_out_shost;
+	}
 	list_add_tail(&pm8001_ha->list, &hba_list);
 	PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha);
 	rc = PM8001_CHIP_DISP->chip_init(pm8001_ha);
@@ -1045,6 +1082,7 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
 	rc = scsi_add_host(shost, &pdev->dev);
 	if (rc)
 		goto err_out_ha_free;
+	/* Request Interrupt */
 	rc = pm8001_request_irq(pm8001_ha);
 	if (rc)	{
 		PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index 98dcdbd146d5..d805fd036ddf 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -1438,11 +1438,18 @@ pm80xx_chip_soft_rst(struct pm8001_hba_info *pm8001_ha)
 	if (!pm8001_ha->controller_fatal_error) {
 		/* Check if MPI is in ready state to reset */
 		if (mpi_uninit_check(pm8001_ha) != 0) {
-			regval = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);
+			u32 r0 = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_0);
+			u32 r1 = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);
+			u32 r2 = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_2);
+			u32 r3 = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_3);
 			PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
-				"MPI state is not ready scratch1 :0x%x\n",
-				regval));
-			return -1;
+				"MPI state is not ready scratch: %x:%x:%x:%x\n",
+				r0, r1, r2, r3));
+			/* if things aren't ready but the bootloader is ok then
+			 * try the reset anyway.
+			 */
+			if (r1 & SCRATCH_PAD1_BOOTSTATE_MASK)
+				return -1;
 		}
 	}
 	/* checked for reset register normal state; 0x0 */
-- 
2.16.3


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 03/12] pm80xx : Free the tag when mpi_set_phy_profile_resp is received.
  2019-12-24  4:41 [PATCH 00/12] pm80xx : Updates for the driver version 0.1.39 Deepak Ukey
  2019-12-24  4:41 ` [PATCH 01/12] pm80xx : Increase request sg length Deepak Ukey
  2019-12-24  4:41 ` [PATCH 02/12] pm80xx : Deal with kexec reboots Deepak Ukey
@ 2019-12-24  4:41 ` Deepak Ukey
  2020-01-02 11:55   ` Jinpu Wang
  2019-12-24  4:41 ` [PATCH 04/12] pm80xx : Cleanup initialization loading fail path Deepak Ukey
                   ` (8 subsequent siblings)
  11 siblings, 1 reply; 33+ messages in thread
From: Deepak Ukey @ 2019-12-24  4:41 UTC (permalink / raw)
  To: linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, deepak.ukey, jinpu.wang,
	martin.petersen, dpf, yuuzheng, auradkar, vishakhavc, bjashnani,
	radha, akshatzen

From: yuuzheng <yuuzheng@google.com>

In pm80xx driver, the command mpi_set_phy_profile_req is sent by host
during boot to configure the phy profile such as analog setting page,
rate control page. However, the tag is not freed when its response is
received. As a result, 16 tags are missing for each HBA after boot.
When NCQ is enabled with queue depth 16, it needs at least, 15 * 16 =
240 tags for each HBA to achieve the best performance. In current
pm80xx driver with setting CCB_MAX = 256, the total number of tags in
each HBA is 255 for data IO. Hence, without returning those tags to the
pool after boot, some device will finally be forced to non-ncq mode by
ATA layer due to excessive errors (i.e. LLDD cannot allocate tag for
queued task).

Signed-off-by: yuuzheng <yuuzheng@google.com>
Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
Signed-off-by: Viswas G <Viswas.G@microchip.com>
Signed-off-by: Vishakha Channapattan <vishakhavc@google.com>
Signed-off-by: Bhavesh Jashnani <bjashnani@google.com>
Signed-off-by: Radha Ramachandran <radha@google.com>
Signed-off-by: Akshat Jain <akshatzen@google.com>
---
 drivers/scsi/pm8001/pm80xx_hwi.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index d805fd036ddf..37b82d7aa3d7 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -3715,28 +3715,32 @@ static int mpi_flash_op_ext_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
 static int mpi_set_phy_profile_resp(struct pm8001_hba_info *pm8001_ha,
 			void *piomb)
 {
+	u32 tag;
 	u8 page_code;
+	int rc = 0;
 	struct set_phy_profile_resp *pPayload =
 		(struct set_phy_profile_resp *)(piomb + 4);
 	u32 ppc_phyid = le32_to_cpu(pPayload->ppc_phyid);
 	u32 status = le32_to_cpu(pPayload->status);
 
+	tag = le32_to_cpu(pPayload->tag);
 	page_code = (u8)((ppc_phyid & 0xFF00) >> 8);
 	if (status) {
 		/* status is FAILED */
 		PM8001_FAIL_DBG(pm8001_ha,
 			pm8001_printk("PhyProfile command failed  with status "
 			"0x%08X \n", status));
-		return -1;
+		rc = -1;
 	} else {
 		if (page_code != SAS_PHY_ANALOG_SETTINGS_PAGE) {
 			PM8001_FAIL_DBG(pm8001_ha,
 				pm8001_printk("Invalid page code 0x%X\n",
 					page_code));
-			return -1;
+			rc = -1;
 		}
 	}
-	return 0;
+	pm8001_tag_free(pm8001_ha, tag);
+	return rc;
 }
 
 /**
-- 
2.16.3


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 04/12] pm80xx : Cleanup initialization loading fail path.
  2019-12-24  4:41 [PATCH 00/12] pm80xx : Updates for the driver version 0.1.39 Deepak Ukey
                   ` (2 preceding siblings ...)
  2019-12-24  4:41 ` [PATCH 03/12] pm80xx : Free the tag when mpi_set_phy_profile_resp is received Deepak Ukey
@ 2019-12-24  4:41 ` Deepak Ukey
  2020-01-02 11:58   ` Jinpu Wang
  2019-12-24  4:41 ` [PATCH 05/12] pm80xx : Support for char device Deepak Ukey
                   ` (7 subsequent siblings)
  11 siblings, 1 reply; 33+ messages in thread
From: Deepak Ukey @ 2019-12-24  4:41 UTC (permalink / raw)
  To: linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, deepak.ukey, jinpu.wang,
	martin.petersen, dpf, yuuzheng, auradkar, vishakhavc, bjashnani,
	radha, akshatzen

From: Peter Chang <dpf@google.com>

1)Move the instance tracking down after we think the instance is
good to go. avoids having a use-after free.
2)There are goto targets for trying to cleanup if the hw fails to
initialize, but there's some overlap depending on who thinks they
own the sub-structures.

Signed-off-by: Peter Chang <dpf@google.com>
Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
Signed-off-by: Viswas G <Viswas.G@microchip.com>
Signed-off-by: Vishakha Channapattan <vishakhavc@google.com>
Signed-off-by: Bhavesh Jashnani <bjashnani@google.com>
Signed-off-by: Radha Ramachandran <radha@google.com>
Signed-off-by: Akshat Jain <akshatzen@google.com>
Signed-off-by: Yu Zheng <yuuzheng@google.com>
---
 drivers/scsi/pm8001/pm8001_init.c | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c
index a002eb5a3fe4..775517f9b39d 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -1016,6 +1016,7 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
 	struct pm8001_hba_info *pm8001_ha;
 	struct Scsi_Host *shost = NULL;
 	const struct pm8001_chip_info *chip;
+	struct sas_ha_struct *sha;
 
 	dev_printk(KERN_INFO, &pdev->dev,
 		"pm80xx: driver version %s\n", DRV_VERSION);
@@ -1044,12 +1045,12 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
 		goto err_out_regions;
 	}
 	chip = &pm8001_chips[ent->driver_data];
-	SHOST_TO_SAS_HA(shost) =
-		kzalloc(sizeof(struct sas_ha_struct), GFP_KERNEL);
-	if (!SHOST_TO_SAS_HA(shost)) {
+	sha = kzalloc(sizeof(struct sas_ha_struct), GFP_KERNEL);
+	if (!sha) {
 		rc = -ENOMEM;
 		goto err_out_free_host;
 	}
+	SHOST_TO_SAS_HA(shost) = sha;
 
 	rc = pm8001_prep_sas_ha_init(shost, chip);
 	if (rc) {
@@ -1070,7 +1071,7 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
 			"pm8001_setup_irq failed [ret: %d]\n", rc));
 		goto err_out_shost;
 	}
-	list_add_tail(&pm8001_ha->list, &hba_list);
+
 	PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha);
 	rc = PM8001_CHIP_DISP->chip_init(pm8001_ha);
 	if (rc) {
@@ -1105,8 +1106,12 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
 
 	pm8001_post_sas_ha_init(shost, chip);
 	rc = sas_register_ha(SHOST_TO_SAS_HA(shost));
-	if (rc)
+	if (rc) {
+		PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
+			"sas_register_ha failed [ret: %d]\n", rc));
 		goto err_out_shost;
+	}
+	list_add_tail(&pm8001_ha->list, &hba_list);
 	scsi_scan_host(pm8001_ha->shost);
 	pm8001_ha->flags = PM8001F_RUN_TIME;
 	return 0;
@@ -1116,7 +1121,7 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
 err_out_ha_free:
 	pm8001_free(pm8001_ha);
 err_out_free:
-	kfree(SHOST_TO_SAS_HA(shost));
+	kfree(sha);
 err_out_free_host:
 	scsi_host_put(shost);
 err_out_regions:
-- 
2.16.3


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 05/12] pm80xx : Support for char device.
  2019-12-24  4:41 [PATCH 00/12] pm80xx : Updates for the driver version 0.1.39 Deepak Ukey
                   ` (3 preceding siblings ...)
  2019-12-24  4:41 ` [PATCH 04/12] pm80xx : Cleanup initialization loading fail path Deepak Ukey
@ 2019-12-24  4:41 ` Deepak Ukey
  2020-01-02 12:03   ` Jinpu Wang
  2019-12-24  4:41 ` [PATCH 06/12] pm80xx : sysfs attribute for number of phys Deepak Ukey
                   ` (6 subsequent siblings)
  11 siblings, 1 reply; 33+ messages in thread
From: Deepak Ukey @ 2019-12-24  4:41 UTC (permalink / raw)
  To: linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, deepak.ukey, jinpu.wang,
	martin.petersen, dpf, yuuzheng, auradkar, vishakhavc, bjashnani,
	radha, akshatzen

From: Deepak Ukey <Deepak.Ukey@microchip.com>

Added the support to register char device for pm80xx module and
also added the ioctl functionality to get driver info.

Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
Signed-off-by: Viswas G <Viswas.G@microchip.com>
Signed-off-by: Vishakha Channapattan <vishakhavc@google.com>
Signed-off-by: Bhavesh Jashnani <bjashnani@google.com>
Signed-off-by: Radha Ramachandran <radha@google.com>
Signed-off-by: Akshat Jain <akshatzen@google.com>
Signed-off-by: Yu Zheng <yuuzheng@google.com>
---
 drivers/scsi/pm8001/pm8001_ctl.c  | 148 ++++++++++++++++++++++++++++++++++++++
 drivers/scsi/pm8001/pm8001_ctl.h  |  33 +++++++++
 drivers/scsi/pm8001/pm8001_init.c |   5 ++
 drivers/scsi/pm8001/pm8001_sas.h  |   6 ++
 4 files changed, 192 insertions(+)

diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c
index 7c6be2ec110d..69458b318a20 100644
--- a/drivers/scsi/pm8001/pm8001_ctl.c
+++ b/drivers/scsi/pm8001/pm8001_ctl.c
@@ -41,6 +41,7 @@
 #include <linux/slab.h>
 #include "pm8001_sas.h"
 #include "pm8001_ctl.h"
+int pm80xx_major = -1;
 
 /* scsi host attributes */
 
@@ -845,3 +846,150 @@ struct device_attribute *pm8001_host_attrs[] = {
 	NULL,
 };
 
+/*
+ * pm8001_open - open the configuration file
+ * @inode: inode being opened
+ * @file: file handle attached
+ *
+ * Called when the configuration device is opened. Does the needed
+ * set up on the handle and then returns
+ *
+ */
+static int pm8001_open(struct inode *inode, struct file *file)
+{
+	struct pm8001_hba_info *pm8001_ha;
+	unsigned int minor_number = iminor(inode);
+	int err = -ENODEV;
+
+	list_for_each_entry(pm8001_ha, &hba_list, list) {
+		if (pm8001_ha->id == minor_number) {
+			file->private_data = pm8001_ha;
+			err = 0;
+			break;
+		}
+	}
+
+	return err;
+}
+
+/**
+ * pm8001_close - close the configuration file
+ * @inode: inode being opened
+ * @file: file handle attached
+ *
+ * Called when the configuration device is closed. Does the needed
+ * set up on the handle and then returns
+ *
+ */
+static int pm8001_close(struct inode *inode, struct file *file)
+{
+	return 0;
+}
+
+static long pm8001_info_ioctl(struct pm8001_hba_info *pm8001_ha,
+					unsigned long arg)
+{
+	u32 ret = 0;
+	struct ioctl_info_buffer info_buf;
+
+	strcpy(info_buf.information.sz_name, DRV_NAME);
+
+	info_buf.information.usmajor_revision = DRV_MAJOR;
+	info_buf.information.usminor_revision = DRV_MINOR;
+	info_buf.information.usbuild_revision = DRV_BUILD;
+	if (pm8001_ha->chip_id == chip_8001) {
+		info_buf.information.maxoutstandingIO =
+			pm8001_ha->main_cfg_tbl.pm8001_tbl.max_out_io;
+		info_buf.information.maxdevices =
+			(pm8001_ha->main_cfg_tbl.pm8001_tbl.max_sgl >> 16) &
+			0xFFFF;
+	} else {
+		info_buf.information.maxoutstandingIO =
+			pm8001_ha->main_cfg_tbl.pm80xx_tbl.max_out_io;
+		info_buf.information.maxdevices =
+			(pm8001_ha->main_cfg_tbl.pm80xx_tbl.max_sgl >> 16) &
+			0xFFFF;
+	}
+	info_buf.header.return_code = ADPT_IOCTL_CALL_SUCCESS;
+
+	if (copy_to_user((void *)arg, (void *)&info_buf,
+				sizeof(struct ioctl_info_buffer))) {
+		ret = ADPT_IOCTL_CALL_FAILED;
+	}
+	return ret;
+}
+
+/**
+ *	pm8001_ioctl - pm8001 configuration request
+ *	@inode: inode of device
+ *	@file: file handle
+ *	@cmd: ioctl command code
+ *	@arg: argument
+ *
+ *	Handles a configuration ioctl.
+ *
+ */
+static long pm8001_ioctl(struct file *file,
+		unsigned int cmd, unsigned long arg)
+{
+	u32 ret = -EACCES;
+	struct pm8001_hba_info *pm8001_ha;
+	struct ioctl_header header;
+
+	pm8001_ha = file->private_data;
+
+	switch (cmd) {
+	case ADPT_IOCTL_INFO:
+		ret = pm8001_info_ioctl(pm8001_ha, arg);
+		break;
+	default:
+		ret = ADPT_IOCTL_CALL_INVALID_CODE;
+	}
+
+	if (ret == 0)
+		return ret;
+	header.return_code = ret;
+	ret = -EACCES;
+	if (copy_to_user((void *)arg, (void *)&header,
+				sizeof(struct ioctl_header))) {
+		PM8001_FAIL_DBG(pm8001_ha,
+				pm8001_printk("copy_to_user failed\n"));
+	}
+	return ret;
+}
+
+static const struct file_operations pm8001_fops = {
+	.owner		= THIS_MODULE,
+	.open		= pm8001_open,
+	.release	= pm8001_close,
+	.unlocked_ioctl	= pm8001_ioctl,
+};
+
+/**
+ * pm8001_setup_chrdev - register char device
+ * Return value:
+ * 0 in case of success, otherwise non-zero value
+ */
+int pm8001_setup_chrdev(void)
+{
+	pm80xx_major = register_chrdev(0, DRV_NAME, &pm8001_fops);
+	if (pm80xx_major < 0) {
+		pr_warn("pm8001: unable to register %s  device.\n",
+				DRV_NAME);
+		return pm80xx_major;
+	}
+	return 0;
+}
+
+/**
+ * pm8001_release_chrdev - unregisters per-adapter management interface
+ * Return value:
+ * none
+ */
+void pm8001_release_chrdev(void)
+{
+	if (pm80xx_major > -1) {
+		unregister_chrdev(pm80xx_major, DRV_NAME);
+		pm80xx_major = -1;
+	}
+}
diff --git a/drivers/scsi/pm8001/pm8001_ctl.h b/drivers/scsi/pm8001/pm8001_ctl.h
index d0d43a250b9e..f0f8b1deae27 100644
--- a/drivers/scsi/pm8001/pm8001_ctl.h
+++ b/drivers/scsi/pm8001/pm8001_ctl.h
@@ -59,5 +59,38 @@
 #define SYSFS_OFFSET                    1024
 #define PM80XX_IB_OB_QUEUE_SIZE         (32 * 1024)
 #define PM8001_IB_OB_QUEUE_SIZE         (16 * 1024)
+
+#define ADPT_IOCTL_CALL_SUCCESS		0x00
+#define ADPT_IOCTL_CALL_FAILED		0x01
+#define ADPT_IOCTL_CALL_INVALID_CODE	0x03
+
+struct ioctl_header {
+	u32 io_controller_num;
+	u32 length;
+	u32 return_code;
+	u32 timeout;
+	u16 direction;
+};
+
+struct ioctl_drv_info {
+	u8	sz_name[64];
+	u16	usmajor_revision;
+	u16	usminor_revision;
+	u16	usbuild_revision;
+	u16	reserved0;
+	u32	maxdevices;
+	u32	maxoutstandingIO;
+	u32	reserved[16];
+};
+
+struct ioctl_info_buffer {
+	struct ioctl_header	header;
+	struct ioctl_drv_info	information;
+};
+
+#define ADPT_IOCTL_INFO _IOR(ADPT_MAGIC_NUMBER, 0, struct ioctl_info_buffer *)
+
+#define ADPT_MAGIC_NUMBER	'm'
+
 #endif /* PM8001_CTL_H_INCLUDED */
 
diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c
index 775517f9b39d..25e74f1dbd0c 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -1421,6 +1421,9 @@ static int __init pm8001_init(void)
 	pm8001_stt = sas_domain_attach_transport(&pm8001_transport_ops);
 	if (!pm8001_stt)
 		goto err_wq;
+	rc = pm8001_setup_chrdev();
+	if (rc)
+		goto err_ctl;
 	rc = pci_register_driver(&pm8001_pci_driver);
 	if (rc)
 		goto err_tp;
@@ -1428,6 +1431,8 @@ static int __init pm8001_init(void)
 
 err_tp:
 	sas_release_transport(pm8001_stt);
+err_ctl:
+	pm8001_release_chrdev();
 err_wq:
 	destroy_workqueue(pm8001_wq);
 err:
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index 93438c8f67da..479aac34d7cc 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -59,6 +59,9 @@
 
 #define DRV_NAME		"pm80xx"
 #define DRV_VERSION		"0.1.39"
+#define DRV_MAJOR		1
+#define DRV_MINOR		3
+#define DRV_BUILD		0
 #define PM8001_FAIL_LOGGING	0x01 /* Error message logging */
 #define PM8001_INIT_LOGGING	0x02 /* driver init logging */
 #define PM8001_DISC_LOGGING	0x04 /* discovery layer logging */
@@ -745,6 +748,9 @@ ssize_t pm8001_get_gsm_dump(struct device *cdev, u32, char *buf);
 /* ctl shared API */
 extern struct device_attribute *pm8001_host_attrs[];
 
+int pm8001_setup_chrdev(void);
+void pm8001_release_chrdev(void);
+
 static inline void
 pm8001_ccb_task_free_done(struct pm8001_hba_info *pm8001_ha,
 			struct sas_task *task, struct pm8001_ccb_info *ccb,
-- 
2.16.3


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 06/12] pm80xx : sysfs attribute for number of phys.
  2019-12-24  4:41 [PATCH 00/12] pm80xx : Updates for the driver version 0.1.39 Deepak Ukey
                   ` (4 preceding siblings ...)
  2019-12-24  4:41 ` [PATCH 05/12] pm80xx : Support for char device Deepak Ukey
@ 2019-12-24  4:41 ` Deepak Ukey
  2020-01-02 12:07   ` Jinpu Wang
  2019-12-24  4:41 ` [PATCH 07/12] pm80xx : IOCTL functionality to get phy profile Deepak Ukey
                   ` (5 subsequent siblings)
  11 siblings, 1 reply; 33+ messages in thread
From: Deepak Ukey @ 2019-12-24  4:41 UTC (permalink / raw)
  To: linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, deepak.ukey, jinpu.wang,
	martin.petersen, dpf, yuuzheng, auradkar, vishakhavc, bjashnani,
	radha, akshatzen

From: Viswas G <Viswas.G@microchip.com>

Added sysfs attribute to show number of phys.

Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
Signed-off-by: Viswas G <Viswas.G@microchip.com>
Signed-off-by: Vishakha Channapattan <vishakhavc@google.com>
Signed-off-by: Bhavesh Jashnani <bjashnani@google.com>
Signed-off-by: Radha Ramachandran <radha@google.com>
Signed-off-by: Akshat Jain <akshatzen@google.com>
Signed-off-by: Yu Zheng <yuuzheng@google.com>
---
 drivers/scsi/pm8001/pm8001_ctl.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c
index 69458b318a20..704c0daa7937 100644
--- a/drivers/scsi/pm8001/pm8001_ctl.c
+++ b/drivers/scsi/pm8001/pm8001_ctl.c
@@ -89,6 +89,25 @@ static ssize_t controller_fatal_error_show(struct device *cdev,
 }
 static DEVICE_ATTR_RO(controller_fatal_error);
 
+/**
+ * pm8001_ctl_num_phys_show - Number of phys
+ * @cdev:pointer to embedded class device
+ * @buf:the buffer returned
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t num_phys_show(struct device *cdev,
+		struct device_attribute *attr, char *buf)
+{
+	int ret;
+	struct Scsi_Host *shost = class_to_shost(cdev);
+	struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
+	struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
+
+	ret = sprintf(buf, "%d", pm8001_ha->chip->n_phy);
+	return ret;
+}
+static DEVICE_ATTR_RO(num_phys);
+
 /**
  * pm8001_ctl_fw_version_show - firmware version
  * @cdev: pointer to embedded class device
@@ -825,6 +844,7 @@ static DEVICE_ATTR(update_fw, S_IRUGO|S_IWUSR|S_IWGRP,
 struct device_attribute *pm8001_host_attrs[] = {
 	&dev_attr_interface_rev,
 	&dev_attr_controller_fatal_error,
+	&dev_attr_num_phys,
 	&dev_attr_fw_version,
 	&dev_attr_update_fw,
 	&dev_attr_aap_log,
-- 
2.16.3


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 07/12] pm80xx : IOCTL functionality to get phy profile.
  2019-12-24  4:41 [PATCH 00/12] pm80xx : Updates for the driver version 0.1.39 Deepak Ukey
                   ` (5 preceding siblings ...)
  2019-12-24  4:41 ` [PATCH 06/12] pm80xx : sysfs attribute for number of phys Deepak Ukey
@ 2019-12-24  4:41 ` Deepak Ukey
  2020-01-02 12:10   ` Jinpu Wang
  2019-12-24  4:41 ` [PATCH 08/12] pm80xx : IOCTL functionality for GPIO Deepak Ukey
                   ` (4 subsequent siblings)
  11 siblings, 1 reply; 33+ messages in thread
From: Deepak Ukey @ 2019-12-24  4:41 UTC (permalink / raw)
  To: linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, deepak.ukey, jinpu.wang,
	martin.petersen, dpf, yuuzheng, auradkar, vishakhavc, bjashnani,
	radha, akshatzen

From: Viswas G <Viswas.G@microchip.com>

Added the ioctl functionality to collect phy status and phy error.

Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
Signed-off-by: Viswas G <Viswas.G@microchip.com>
Signed-off-by: Vishakha Channapattan <vishakhavc@google.com>
Signed-off-by: Bhavesh Jashnani <bjashnani@google.com>
Signed-off-by: Radha Ramachandran <radha@google.com>
Signed-off-by: Akshat Jain <akshatzen@google.com>
Signed-off-by: Yu Zheng <yuuzheng@google.com>
---
 drivers/scsi/pm8001/pm8001_ctl.c | 145 +++++++++++++++++++++++++++++++++++++++
 drivers/scsi/pm8001/pm8001_ctl.h |  35 +++++++++-
 drivers/scsi/pm8001/pm8001_sas.h |   9 +++
 drivers/scsi/pm8001/pm80xx_hwi.c |  82 ++++++++++++++++++++++
 drivers/scsi/pm8001/pm80xx_hwi.h |   2 +
 5 files changed, 272 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c
index 704c0daa7937..6daae852d5ac 100644
--- a/drivers/scsi/pm8001/pm8001_ctl.c
+++ b/drivers/scsi/pm8001/pm8001_ctl.c
@@ -41,6 +41,8 @@
 #include <linux/slab.h>
 #include "pm8001_sas.h"
 #include "pm8001_ctl.h"
+#include "pm80xx_hwi.h"
+
 int pm80xx_major = -1;
 
 /* scsi host attributes */
@@ -939,6 +941,143 @@ static long pm8001_info_ioctl(struct pm8001_hba_info *pm8001_ha,
 	return ret;
 }
 
+static int pm8001_ioctl_get_phy_profile(struct pm8001_hba_info *pm8001_ha,
+		unsigned long arg)
+{
+	struct phy_profile phy_prof[MAX_NUM_PHYS];
+	int nphys;
+	DECLARE_COMPLETION_ONSTACK(completion);
+	unsigned long timeout = msecs_to_jiffies(2000);
+	u32 ret = 0, i;
+	int page_code = SAS_PHY_GENERAL_STATUS_PAGE;
+
+	if (pm8001_ha->pdev->device == 0x8001 ||
+				pm8001_ha->pdev->device == 0x8081) {
+		return ADPT_IOCTL_CALL_INVALID_DEVICE;
+	}
+
+	if (copy_from_user(&phy_prof[0], (struct phy_profile *)arg,
+				sizeof(struct phy_profile))) {
+		PM8001_FAIL_DBG(pm8001_ha,
+				pm8001_printk("copy_from_user failed\n"));
+		return ADPT_IOCTL_CALL_FAILED;
+	}
+
+	mutex_lock(&pm8001_ha->ioctl_mutex);
+	nphys = phy_prof[0].phy_id;
+	if (nphys == -1) {
+		for (i = 0; i < pm8001_ha->chip->n_phy; i++) {
+			pm8001_ha->ioctl_completion = &completion;
+			ret = PM8001_CHIP_DISP->get_phy_profile_req(pm8001_ha,
+								i, page_code);
+			if (ret != 0) {
+				PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
+					"Get phy profile request failed\n"));
+				ret = ADPT_IOCTL_CALL_FAILED;
+				goto exit;
+			}
+			timeout = wait_for_completion_timeout(&completion,
+					timeout);
+			if (timeout == 0) {
+				ret = ADPT_IOCTL_CALL_FAILED;
+				goto exit;
+			}
+			memcpy((void *)&phy_prof[i],
+				(void *)&pm8001_ha->phy_profile_resp,
+				sizeof(struct phy_profile));
+		}
+
+		if (copy_to_user((void *)arg, (void *)&phy_prof,
+				sizeof(struct phy_profile) * (i))) {
+			PM8001_FAIL_DBG(pm8001_ha,
+				pm8001_printk("copy_to_user failed\n"));
+			ret = ADPT_IOCTL_CALL_FAILED;
+		}
+	} else {
+		pm8001_ha->ioctl_completion = &completion;
+		ret = PM8001_CHIP_DISP->get_phy_profile_req(pm8001_ha,
+							nphys, page_code);
+		if (ret != 0) {
+			PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
+				"Get phy profile request failed\n"));
+			ret = ADPT_IOCTL_CALL_FAILED;
+			goto exit;
+		}
+		timeout = wait_for_completion_timeout(&completion,
+				timeout);
+		if (timeout == 0) {
+			ret = ADPT_IOCTL_CALL_FAILED;
+			goto exit;
+		}
+
+		if (copy_to_user((void *)arg,
+				(void *)&pm8001_ha->phy_profile_resp,
+				sizeof(struct phy_profile))) {
+			PM8001_FAIL_DBG(pm8001_ha,
+				pm8001_printk("copy_to_user failed\n"));
+			ret = ADPT_IOCTL_CALL_FAILED;
+		}
+	}
+exit:
+	spin_lock_irq(&pm8001_ha->ioctl_lock);
+	pm8001_ha->ioctl_completion = NULL;
+	spin_unlock_irq(&pm8001_ha->ioctl_lock);
+	mutex_unlock(&pm8001_ha->ioctl_mutex);
+	return ret;
+}
+
+static int pm8001_ioctl_get_phy_err(struct pm8001_hba_info *pm8001_ha,
+		unsigned long arg)
+{
+	struct phy_errcnt phy_err[MAX_NUM_PHYS];
+	DECLARE_COMPLETION_ONSTACK(completion);
+	unsigned long timeout = msecs_to_jiffies(2000);
+	u32 ret = 0, i;
+	int page_code = SAS_PHY_ERR_COUNTERS_PAGE;
+	/*6H card does not support phyerr*/
+	if (pm8001_ha->pdev->device == 0x8001 ||
+			pm8001_ha->pdev->device == 0x8081) {
+		return ADPT_IOCTL_CALL_INVALID_DEVICE;
+	}
+
+	mutex_lock(&pm8001_ha->ioctl_mutex);
+
+	for (i = 0; i < pm8001_ha->chip->n_phy; i++) {
+		pm8001_ha->ioctl_completion = &completion;
+		ret = PM8001_CHIP_DISP->get_phy_profile_req(pm8001_ha,
+				i, page_code);
+		if (ret != 0) {
+			PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
+				"Get phy profile request failed\n"));
+			ret = ADPT_IOCTL_CALL_FAILED;
+			goto exit;
+		}
+		timeout = wait_for_completion_timeout(&completion,
+				timeout);
+		if (timeout == 0) {
+			ret = ADPT_IOCTL_CALL_FAILED;
+			goto exit;
+		}
+		memcpy((void *)&phy_err[i],
+			(void *)&pm8001_ha->phy_profile_resp,
+			sizeof(struct phy_errcnt));
+	}
+
+	if (copy_to_user((void *)arg, (void *)&phy_err,
+			sizeof(struct phy_errcnt) * (i))) {
+		PM8001_FAIL_DBG(pm8001_ha,
+			pm8001_printk("copy_to_user failed\n"));
+		ret = ADPT_IOCTL_CALL_FAILED;
+	}
+
+exit:
+	spin_lock_irq(&pm8001_ha->ioctl_lock);
+	pm8001_ha->ioctl_completion = NULL;
+	spin_unlock_irq(&pm8001_ha->ioctl_lock);
+	mutex_unlock(&pm8001_ha->ioctl_mutex);
+	return ret;
+}
+
 /**
  *	pm8001_ioctl - pm8001 configuration request
  *	@inode: inode of device
@@ -962,6 +1101,12 @@ static long pm8001_ioctl(struct file *file,
 	case ADPT_IOCTL_INFO:
 		ret = pm8001_info_ioctl(pm8001_ha, arg);
 		break;
+	case ADPT_IOCTL_GET_PHY_PROFILE:
+		ret = pm8001_ioctl_get_phy_profile(pm8001_ha, arg);
+		return ret;
+	case ADPT_IOCTL_GET_PHY_ERR_CNT:
+		ret = pm8001_ioctl_get_phy_err(pm8001_ha, arg);
+		break;
 	default:
 		ret = ADPT_IOCTL_CALL_INVALID_CODE;
 	}
diff --git a/drivers/scsi/pm8001/pm8001_ctl.h b/drivers/scsi/pm8001/pm8001_ctl.h
index f0f8b1deae27..686ad69f0e0c 100644
--- a/drivers/scsi/pm8001/pm8001_ctl.h
+++ b/drivers/scsi/pm8001/pm8001_ctl.h
@@ -63,6 +63,9 @@
 #define ADPT_IOCTL_CALL_SUCCESS		0x00
 #define ADPT_IOCTL_CALL_FAILED		0x01
 #define ADPT_IOCTL_CALL_INVALID_CODE	0x03
+#define ADPT_IOCTL_CALL_INVALID_DEVICE	0x04
+
+#define MAX_NUM_PHYS			16
 
 struct ioctl_header {
 	u32 io_controller_num;
@@ -88,8 +91,38 @@ struct ioctl_info_buffer {
 	struct ioctl_drv_info	information;
 };
 
-#define ADPT_IOCTL_INFO _IOR(ADPT_MAGIC_NUMBER, 0, struct ioctl_info_buffer *)
+struct phy_profile {
+	char		phy_id;
+	unsigned int	phys:4;
+	unsigned int	nlr:4;
+	unsigned int	plr:4;
+	unsigned int	reserved1:12;
+	unsigned char	port_id;
+	unsigned int	prts:4;
+	unsigned int	reserved2:20;
+} __packed;
+
+struct phy_errcnt {
+	unsigned int  InvalidDword;
+	unsigned int  runningDisparityError;
+	unsigned int  codeViolation;
+	unsigned int  LossOfSyncDW;
+	unsigned int  phyResetProblem;
+	unsigned int  inboundCRCError;
+};
 
+struct phy_prof_resp {
+	union {
+		struct phy_profile status;
+		struct phy_errcnt errcnt;
+	} phy;
+};
+
+#define ADPT_IOCTL_INFO _IOR(ADPT_MAGIC_NUMBER, 0, struct ioctl_info_buffer *)
+#define ADPT_IOCTL_GET_PHY_PROFILE _IOWR(ADPT_MAGIC_NUMBER, 8, \
+		struct phy_profile*)
+#define ADPT_IOCTL_GET_PHY_ERR_CNT _IOWR(ADPT_MAGIC_NUMBER, 9, \
+		struct phy_err*)
 #define ADPT_MAGIC_NUMBER	'm'
 
 #endif /* PM8001_CTL_H_INCLUDED */
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index 479aac34d7cc..99920d53ac09 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -56,6 +56,7 @@
 #include <scsi/sas_ata.h>
 #include <linux/atomic.h>
 #include "pm8001_defs.h"
+#include "pm8001_ctl.h"
 
 #define DRV_NAME		"pm80xx"
 #define DRV_VERSION		"0.1.39"
@@ -246,6 +247,8 @@ struct pm8001_dispatch {
 	int (*sas_diag_execute_req)(struct pm8001_hba_info *pm8001_ha,
 		u32 state);
 	int (*sas_re_init_req)(struct pm8001_hba_info *pm8001_ha);
+	int (*get_phy_profile_req)(struct pm8001_hba_info *pm8001_ha,
+		int phy, int page);
 };
 
 struct pm8001_chip_info {
@@ -560,6 +563,12 @@ struct pm8001_hba_info {
 	bool			controller_fatal_error;
 	const struct firmware 	*fw_image;
 	struct isr_param irq_vector[PM8001_MAX_MSIX_VEC];
+	spinlock_t		ioctl_lock;
+	struct mutex		ioctl_mutex;
+	struct completion	*ioctl_completion;
+	struct timer_list	ioctl_timer;
+	u32			ioctl_timer_expired;
+	struct	phy_prof_resp	phy_profile_resp;
 	u32			reset_in_progress;
 };
 
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index 37b82d7aa3d7..7f2b7b1d4110 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -3688,9 +3688,62 @@ static int mpi_get_controller_config_resp(struct pm8001_hba_info *pm8001_ha,
 static int mpi_get_phy_profile_resp(struct pm8001_hba_info *pm8001_ha,
 			void *piomb)
 {
+	u32 tag, page_code;
+	struct phy_profile *phy_profile, *phy_prof;
+	struct phy_errcnt *phy_err, *phy_err_cnt;
+	struct get_phy_profile_resp *pPayload =
+		(struct get_phy_profile_resp *)(piomb + 4);
+	u32 status = le32_to_cpu(pPayload->status);
+
+	page_code = (u8)((pPayload->ppc_phyid & 0xFF00) >> 8);
+
 	PM8001_MSG_DBG(pm8001_ha,
 			pm8001_printk(" pm80xx_addition_functionality\n"));
 
+	if (status) {
+		/* status is FAILED */
+		PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
+			"mpiGetPhyProfileReq failed  with status 0x%08x\n",
+			status));
+	}
+
+	tag = le32_to_cpu(pPayload->tag);
+
+	spin_lock(&pm8001_ha->ioctl_lock);
+	if (pm8001_ha->ioctl_completion != NULL) {
+		if (status) {
+			/* signal fail status */
+			memset(&pm8001_ha->phy_profile_resp, 0xff,
+				sizeof(pm8001_ha->phy_profile_resp));
+		} else if (page_code == SAS_PHY_ERR_COUNTERS_PAGE) {
+			phy_err =
+			(struct phy_errcnt *)&pm8001_ha->phy_profile_resp;
+			phy_err_cnt =
+				(struct phy_errcnt *)pPayload->ppc_specific_rsp;
+			phy_err->InvalidDword =
+				le32_to_cpu(phy_err_cnt->InvalidDword);
+			phy_err->runningDisparityError =
+				le32_to_cpu(phy_err_cnt->runningDisparityError);
+			phy_err->LossOfSyncDW =
+				le32_to_cpu(phy_err_cnt->LossOfSyncDW);
+			phy_err->phyResetProblem =
+				le32_to_cpu(phy_err_cnt->phyResetProblem);
+		} else if (page_code == SAS_PHY_GENERAL_STATUS_PAGE) {
+			phy_profile =
+			(struct phy_profile *)&pm8001_ha->phy_profile_resp;
+			phy_prof =
+			(struct phy_profile *)pPayload->ppc_specific_rsp;
+			phy_profile->phy_id = le32_to_cpu(phy_prof->phy_id);
+			phy_profile->phys = le32_to_cpu(phy_prof->phys);
+			phy_profile->plr = le32_to_cpu(phy_prof->plr);
+			phy_profile->nlr = le32_to_cpu(phy_prof->nlr);
+			phy_profile->port_id = le32_to_cpu(phy_prof->port_id);
+			phy_profile->prts = le32_to_cpu(phy_prof->prts);
+		}
+		complete(pm8001_ha->ioctl_completion);
+	}
+	spin_unlock(&pm8001_ha->ioctl_lock);
+	pm8001_tag_free(pm8001_ha, tag);
 	return 0;
 }
 
@@ -4883,6 +4936,34 @@ pm80xx_chip_isr(struct pm8001_hba_info *pm8001_ha, u8 vec)
 	return IRQ_HANDLED;
 }
 
+int pm8001_chip_get_phy_profile(struct pm8001_hba_info *pm8001_ha,
+		int phy_id, int page_code)
+{
+
+	u32 tag;
+	struct get_phy_profile_req payload;
+	struct inbound_queue_table *circularQ;
+	int rc, ppc_phyid;
+	u32 opc = OPC_INB_GET_PHY_PROFILE;
+
+	memset(&payload, 0, sizeof(payload));
+
+	rc = pm8001_tag_alloc(pm8001_ha, &tag);
+	if (rc)
+		PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("Invalid tag\n"));
+
+	circularQ = &pm8001_ha->inbnd_q_tbl[0];
+
+	payload.tag = cpu_to_le32(tag);
+	ppc_phyid = (page_code & 0xFF)  << 8 | (phy_id & 0xFF);
+	payload.ppc_phyid = cpu_to_le32(ppc_phyid);
+
+	pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
+			sizeof(payload), 0);
+
+	return rc;
+}
+
 void mpi_set_phy_profile_req(struct pm8001_hba_info *pm8001_ha,
 	u32 operation, u32 phyid, u32 length, u32 *buf)
 {
@@ -4983,4 +5064,5 @@ const struct pm8001_dispatch pm8001_80xx_dispatch = {
 	.set_nvmd_req		= pm8001_chip_set_nvmd_req,
 	.fw_flash_update_req	= pm8001_chip_fw_flash_update_req,
 	.set_dev_state_req	= pm8001_chip_set_dev_state_req,
+	.get_phy_profile_req	= pm8001_chip_get_phy_profile,
 };
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.h b/drivers/scsi/pm8001/pm80xx_hwi.h
index 701951a0f715..b5119c5479da 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.h
+++ b/drivers/scsi/pm8001/pm80xx_hwi.h
@@ -175,7 +175,9 @@
 #define PHY_STOP_ERR_DEVICE_ATTACHED	0x1046
 
 /* phy_profile */
+#define SAS_PHY_ERR_COUNTERS_PAGE	0x01
 #define SAS_PHY_ANALOG_SETTINGS_PAGE	0x04
+#define SAS_PHY_GENERAL_STATUS_PAGE	0x05
 #define PHY_DWORD_LENGTH		0xC
 
 /* Thermal related */
-- 
2.16.3


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 08/12] pm80xx : IOCTL functionality for GPIO.
  2019-12-24  4:41 [PATCH 00/12] pm80xx : Updates for the driver version 0.1.39 Deepak Ukey
                   ` (6 preceding siblings ...)
  2019-12-24  4:41 ` [PATCH 07/12] pm80xx : IOCTL functionality to get phy profile Deepak Ukey
@ 2019-12-24  4:41 ` Deepak Ukey
  2020-01-06 16:25   ` Jinpu Wang
  2019-12-24  4:41 ` [PATCH 09/12] pm80xx : IOCTL functionality for SGPIO Deepak Ukey
                   ` (3 subsequent siblings)
  11 siblings, 1 reply; 33+ messages in thread
From: Deepak Ukey @ 2019-12-24  4:41 UTC (permalink / raw)
  To: linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, deepak.ukey, jinpu.wang,
	martin.petersen, dpf, yuuzheng, auradkar, vishakhavc, bjashnani,
	radha, akshatzen

From: Deepak Ukey <Deepak.Ukey@microchip.com>

Added IOCTL functionality for GPIO.
The SPCv controller provides 24 GPIO signals. The first 12 signals
[11:0] and the last 4 signals [23:20] are for customer use. Eight
signals [19:12] are reserved for the SPCv controller firmware.
Whenever the host performs GPIO setup or a read/write operation
using the GPIO command the host needs to make sure that it does
not disturb the GPIO configuration for the bits [19:12].
Each signal can be configured either as an input or as an output.
When configured as an output, the host can use the GPIO Command to
set the desired level. GPIO inputs can also be configured so that
the SPCv controller sends the GPIO Event notification when specific
GPIO events occur.
Different GPIO features implemented:
1) GPIO Pin Setup
2) GPIO Event Setup
3) GPIO Read
4) GPIO Write

Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
Signed-off-by: Viswas G <Viswas.G@microchip.com>
Signed-off-by: Vishakha Channapattan <vishakhavc@google.com>
Signed-off-by: Bhavesh Jashnani <bjashnani@google.com>
Signed-off-by: Radha Ramachandran <radha@google.com>
Signed-off-by: Akshat Jain <akshatzen@google.com>
Signed-off-by: Yu Zheng <yuuzheng@google.com>
---
 drivers/scsi/pm8001/pm8001_ctl.c  |  95 ++++++++++++++++++++++++++++++++++
 drivers/scsi/pm8001/pm8001_ctl.h  |  24 +++++++++
 drivers/scsi/pm8001/pm8001_init.c |   6 +++
 drivers/scsi/pm8001/pm8001_sas.h  |  17 ++++++
 drivers/scsi/pm8001/pm80xx_hwi.c  | 106 ++++++++++++++++++++++++++++++++++++++
 drivers/scsi/pm8001/pm80xx_hwi.h  |  49 ++++++++++++++++++
 6 files changed, 297 insertions(+)

diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c
index 6daae852d5ac..8292074c1e6f 100644
--- a/drivers/scsi/pm8001/pm8001_ctl.c
+++ b/drivers/scsi/pm8001/pm8001_ctl.c
@@ -39,6 +39,7 @@
  */
 #include <linux/firmware.h>
 #include <linux/slab.h>
+#include <linux/poll.h>
 #include "pm8001_sas.h"
 #include "pm8001_ctl.h"
 #include "pm80xx_hwi.h"
@@ -941,6 +942,73 @@ static long pm8001_info_ioctl(struct pm8001_hba_info *pm8001_ha,
 	return ret;
 }
 
+static long pm8001_gpio_ioctl(struct pm8001_hba_info *pm8001_ha,
+		unsigned long arg)
+{
+	struct gpio_buffer buffer;
+	struct pm8001_gpio *payload;
+	struct gpio_ioctl_resp *gpio_resp;
+	DECLARE_COMPLETION_ONSTACK(completion);
+	unsigned long timeout;
+	u32 ret = 0, operation;
+
+	if (pm8001_ha->pdev->subsystem_vendor == PCI_VENDOR_ID_ADAPTEC2)
+		return ADPT_IOCTL_CALL_INVALID_DEVICE;
+
+	if (copy_from_user(&buffer, (struct gpio_buffer *)arg,
+		sizeof(struct gpio_buffer))) {
+		ret = ADPT_IOCTL_CALL_FAILED;
+	}
+	mutex_lock(&pm8001_ha->ioctl_mutex);
+	pm8001_ha->ioctl_completion = &completion;
+	payload = &buffer.gpio_payload;
+	operation = payload->operation;
+	ret = PM8001_CHIP_DISP->gpio_req(pm8001_ha, payload);
+	if (ret != 0) {
+		ret = ADPT_IOCTL_CALL_FAILED;
+		goto exit;
+	}
+
+	timeout = (unsigned long)buffer.header.timeout * 1000;
+	if (timeout < 2000)
+		timeout = 2000;
+
+	timeout = wait_for_completion_timeout(&completion,
+			msecs_to_jiffies(timeout));
+	if (timeout == 0) {
+		ret = ADPT_IOCTL_CALL_TIMEOUT;
+		goto exit;
+	}
+	gpio_resp = &pm8001_ha->gpio_resp;
+	buffer.header.return_code = ADPT_IOCTL_CALL_SUCCESS;
+
+	if (operation == GPIO_READ) {
+		payload->rd_wr_val		= gpio_resp->gpio_rd_val;
+		payload->input_enable		= gpio_resp->gpio_in_enabled;
+		payload->pinsetup1		= gpio_resp->gpio_pinsetup1;
+		payload->pinsetup2		= gpio_resp->gpio_pinsetup2;
+		payload->event_level		= gpio_resp->gpio_evt_change;
+		payload->event_rising_edge	= gpio_resp->gpio_evt_rise;
+		payload->event_falling_edge	= gpio_resp->gpio_evt_fall;
+
+		if (copy_to_user((void *)arg, (void *)&buffer,
+					sizeof(struct gpio_buffer))) {
+			ret = ADPT_IOCTL_CALL_FAILED;
+		}
+	} else {
+		if (copy_to_user((void *)arg, (void *)&buffer.header,
+					sizeof(struct ioctl_header))) {
+			ret = ADPT_IOCTL_CALL_FAILED;
+		}
+	}
+exit:
+	spin_lock_irq(&pm8001_ha->ioctl_lock);
+	pm8001_ha->ioctl_completion = NULL;
+	spin_unlock_irq(&pm8001_ha->ioctl_lock);
+	mutex_unlock(&pm8001_ha->ioctl_mutex);
+	return ret;
+}
+
 static int pm8001_ioctl_get_phy_profile(struct pm8001_hba_info *pm8001_ha,
 		unsigned long arg)
 {
@@ -1101,6 +1169,9 @@ static long pm8001_ioctl(struct file *file,
 	case ADPT_IOCTL_INFO:
 		ret = pm8001_info_ioctl(pm8001_ha, arg);
 		break;
+	case ADPT_IOCTL_GPIO:
+		ret = pm8001_gpio_ioctl(pm8001_ha, arg);
+		break;
 	case ADPT_IOCTL_GET_PHY_PROFILE:
 		ret = pm8001_ioctl_get_phy_profile(pm8001_ha, arg);
 		return ret;
@@ -1123,11 +1194,35 @@ static long pm8001_ioctl(struct file *file,
 	return ret;
 }
 
+/**
+ *pm8001_poll - pm8001 poll request function
+ *@file: file handle
+ *@wait: poll table to wait
+ *Handles a poll request.
+ */
+__poll_t pm8001_poll(struct file *file, poll_table *wait)
+{
+	struct pm8001_hba_info *pm8001_ha;
+	__poll_t mask = 0;
+
+	pm8001_ha = file->private_data;
+
+	poll_wait(file, &pm8001_ha->pollq,  wait);
+
+	if (pm8001_ha->gpio_event_occurred == 1) {
+		pm8001_ha->gpio_event_occurred = 0;
+		mask |= POLLIN | POLLRDNORM;
+	}
+
+	return mask;
+}
+
 static const struct file_operations pm8001_fops = {
 	.owner		= THIS_MODULE,
 	.open		= pm8001_open,
 	.release	= pm8001_close,
 	.unlocked_ioctl	= pm8001_ioctl,
+	.poll		= pm8001_poll,
 };
 
 /**
diff --git a/drivers/scsi/pm8001/pm8001_ctl.h b/drivers/scsi/pm8001/pm8001_ctl.h
index 686ad69f0e0c..5be43b2672d4 100644
--- a/drivers/scsi/pm8001/pm8001_ctl.h
+++ b/drivers/scsi/pm8001/pm8001_ctl.h
@@ -64,6 +64,7 @@
 #define ADPT_IOCTL_CALL_FAILED		0x01
 #define ADPT_IOCTL_CALL_INVALID_CODE	0x03
 #define ADPT_IOCTL_CALL_INVALID_DEVICE	0x04
+#define ADPT_IOCTL_CALL_TIMEOUT		0x08
 
 #define MAX_NUM_PHYS			16
 
@@ -86,11 +87,33 @@ struct ioctl_drv_info {
 	u32	reserved[16];
 };
 
+#define	GPIO_READ	0
+#define	GPIO_WRITE	1
+#define	GPIO_PINSETUP	2
+#define	GPIO_EVENTSETUP	3
+
+struct pm8001_gpio {
+	u32	operation;
+	u32	mask;
+	u32	rd_wr_val;
+	u32	input_enable;
+	u32	pinsetup1;
+	u32	pinsetup2;
+	u32	event_level;
+	u32	event_rising_edge;
+	u32	event_falling_edge;
+};
+
 struct ioctl_info_buffer {
 	struct ioctl_header	header;
 	struct ioctl_drv_info	information;
 };
 
+struct gpio_buffer {
+	struct ioctl_header	header;
+	struct pm8001_gpio	gpio_payload;
+};
+
 struct phy_profile {
 	char		phy_id;
 	unsigned int	phys:4;
@@ -119,6 +142,7 @@ struct phy_prof_resp {
 };
 
 #define ADPT_IOCTL_INFO _IOR(ADPT_MAGIC_NUMBER, 0, struct ioctl_info_buffer *)
+#define ADPT_IOCTL_GPIO	_IOWR(ADPT_MAGIC_NUMBER, 1, struct  gpio_buffer *)
 #define ADPT_IOCTL_GET_PHY_PROFILE _IOWR(ADPT_MAGIC_NUMBER, 8, \
 		struct phy_profile*)
 #define ADPT_IOCTL_GET_PHY_ERR_CNT _IOWR(ADPT_MAGIC_NUMBER, 9, \
diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c
index 25e74f1dbd0c..6e2512aa5f6e 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -498,6 +498,12 @@ static struct pm8001_hba_info *pm8001_pci_alloc(struct pci_dev *pdev,
 	else
 		pm8001_ha->iomb_size = IOMB_SIZE_SPC;
 
+	mutex_init(&pm8001_ha->ioctl_mutex);
+	pm8001_ha->ioctl_completion = NULL;
+	init_waitqueue_head(&pm8001_ha->pollq);
+	pm8001_ha->gpio_event_occurred = 0;
+	spin_lock_init(&pm8001_ha->ioctl_lock);
+
 #ifdef PM8001_USE_TASKLET
 	/* Tasklet for non msi-x interrupt handler */
 	if ((!pdev->msix_cap || !pci_msi_enabled())
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index 99920d53ac09..8e442214c954 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -132,6 +132,18 @@ extern const struct pm8001_dispatch pm8001_80xx_dispatch;
 struct pm8001_hba_info;
 struct pm8001_ccb_info;
 struct pm8001_device;
+
+struct gpio_ioctl_resp {
+	u32	tag;
+	u32	gpio_rd_val;
+	u32	gpio_in_enabled;
+	u32	gpio_pinsetup1;
+	u32	gpio_pinsetup2;
+	u32	gpio_evt_change;
+	u32	gpio_evt_rise;
+	u32	gpio_evt_fall;
+};
+
 /* define task management IU */
 struct pm8001_tmf_task {
 	u8	tmf;
@@ -247,6 +259,8 @@ struct pm8001_dispatch {
 	int (*sas_diag_execute_req)(struct pm8001_hba_info *pm8001_ha,
 		u32 state);
 	int (*sas_re_init_req)(struct pm8001_hba_info *pm8001_ha);
+	int (*gpio_req)(struct pm8001_hba_info *pm8001_ha,
+		struct pm8001_gpio *gpio_payload);
 	int (*get_phy_profile_req)(struct pm8001_hba_info *pm8001_ha,
 		int phy, int page);
 };
@@ -562,6 +576,9 @@ struct pm8001_hba_info {
 	u32			smp_exp_mode;
 	bool			controller_fatal_error;
 	const struct firmware 	*fw_image;
+	struct			gpio_ioctl_resp  gpio_resp;
+	u32			gpio_event_occurred;
+	wait_queue_head_t	pollq;
 	struct isr_param irq_vector[PM8001_MAX_MSIX_VEC];
 	spinlock_t		ioctl_lock;
 	struct mutex		ioctl_mutex;
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index 7f2b7b1d4110..10a922e5a478 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -3845,6 +3845,50 @@ static int ssp_coalesced_comp_resp(struct pm8001_hba_info *pm8001_ha,
 	return 0;
 }
 
+static int mpi_gpio_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
+{
+	u32 tag;
+	struct gpio_ioctl_resp *pgpio_resp;
+	struct gpio_resp *ppayload = (struct gpio_resp *)(piomb + 4);
+
+	tag = le32_to_cpu(ppayload->tag);
+	spin_lock(&pm8001_ha->ioctl_lock);
+	if (pm8001_ha->ioctl_completion != NULL) {
+		pgpio_resp = &pm8001_ha->gpio_resp;
+		pgpio_resp->gpio_rd_val = le32_to_cpu(ppayload->gpio_rd_val);
+		pgpio_resp->gpio_in_enabled =
+			le32_to_cpu(ppayload->gpio_in_enabled);
+		pgpio_resp->gpio_pinsetup1 =
+			le32_to_cpu(ppayload->gpio_pinsetup1);
+		pgpio_resp->gpio_pinsetup2 =
+			le32_to_cpu(ppayload->gpio_pinsetup2);
+		pgpio_resp->gpio_evt_change =
+			le32_to_cpu(ppayload->gpio_evt_change);
+		pgpio_resp->gpio_evt_rise =
+			le32_to_cpu(ppayload->gpio_evt_rise);
+		pgpio_resp->gpio_evt_fall =
+			le32_to_cpu(ppayload->gpio_evt_fall);
+
+		complete(pm8001_ha->ioctl_completion);
+	}
+	spin_unlock(&pm8001_ha->ioctl_lock);
+	pm8001_tag_free(pm8001_ha, tag);
+	return 0;
+}
+
+static int mpi_gpio_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
+{
+	u32 gpio_event = 0;
+	struct gpio_event *ppayload = (struct gpio_event *)(piomb + 4);
+
+	gpio_event = le32_to_cpu(ppayload->gpio_event);
+	PM8001_MSG_DBG(pm8001_ha,
+			pm8001_printk("GPIO event: 0x%X\n", gpio_event));
+	pm8001_ha->gpio_event_occurred = 1;
+	wake_up_interruptible(&pm8001_ha->pollq);
+	return 0;
+}
+
 /**
  * process_one_iomb - process one outbound Queue memory block
  * @pm8001_ha: our hba card information
@@ -3931,10 +3975,12 @@ static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb)
 	case OPC_OUB_GPIO_RESPONSE:
 		PM8001_MSG_DBG(pm8001_ha,
 			pm8001_printk("OPC_OUB_GPIO_RESPONSE\n"));
+		mpi_gpio_resp(pm8001_ha, piomb);
 		break;
 	case OPC_OUB_GPIO_EVENT:
 		PM8001_MSG_DBG(pm8001_ha,
 			pm8001_printk("OPC_OUB_GPIO_EVENT\n"));
+		mpi_gpio_event(pm8001_ha, piomb);
 		break;
 	case OPC_OUB_GENERAL_EVENT:
 		PM8001_MSG_DBG(pm8001_ha,
@@ -5038,6 +5084,65 @@ void pm8001_set_phy_profile_single(struct pm8001_hba_info *pm8001_ha,
 	PM8001_INIT_DBG(pm8001_ha,
 		pm8001_printk("PHY %d settings applied", phy));
 }
+
+/**
+ * pm80xx_chip_gpio_req - support for GPIO operation
+ * @pm8001_ha: our hba card information.
+ * @ioctl_payload: the payload for the GPIO operation
+ */
+int pm80xx_chip_gpio_req(struct pm8001_hba_info *pm8001_ha,
+		struct pm8001_gpio *gpio_payload)
+{
+	struct gpio_req payload;
+	struct inbound_queue_table *circularQ;
+	int ret;
+	u32 tag;
+	u32 opc = OPC_INB_GPIO;
+
+	if (pm8001_ha->pdev->subsystem_vendor == PCI_VENDOR_ID_ADAPTEC2)
+		return -1;
+
+	ret = pm8001_tag_alloc(pm8001_ha, &tag);
+	if (ret)
+		return -1;
+
+	memset(&payload, 0, sizeof(payload));
+	circularQ = &pm8001_ha->inbnd_q_tbl[0];
+	payload.tag = cpu_to_le32(tag);
+
+	switch (gpio_payload->operation) {
+	case GPIO_READ:
+		payload.eobid_ge_gs_gr_gw = cpu_to_le32(GPIO_GR_BIT);
+		break;
+	case GPIO_WRITE:
+		payload.eobid_ge_gs_gr_gw = cpu_to_le32(GPIO_GW_BIT);
+		payload.gpio_wr_msk = cpu_to_le32(gpio_payload->mask);
+		payload.gpio_wr_val = cpu_to_le32(gpio_payload->rd_wr_val);
+		break;
+	case GPIO_PINSETUP:
+		payload.eobid_ge_gs_gr_gw = cpu_to_le32(GPIO_GS_BIT);
+		payload.gpio_in_enabled =
+			cpu_to_le32(gpio_payload->input_enable);
+		payload.gpio_pinsetup1 = cpu_to_le32(gpio_payload->pinsetup1);
+		payload.gpio_pinsetup2 = cpu_to_le32(gpio_payload->pinsetup2);
+		break;
+	case GPIO_EVENTSETUP:
+		payload.eobid_ge_gs_gr_gw = cpu_to_le32(GPIO_GE_BIT);
+		payload.gpio_evt_change =
+			cpu_to_le32(gpio_payload->event_level);
+		payload.gpio_evt_rise =
+			cpu_to_le32(gpio_payload->event_rising_edge);
+		payload.gpio_evt_fall =
+			cpu_to_le32(gpio_payload->event_falling_edge);
+		break;
+	}
+	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
+			sizeof(payload), 0);
+	if (ret != 0)
+		pm8001_tag_free(pm8001_ha, tag);
+	return ret;
+}
+
 const struct pm8001_dispatch pm8001_80xx_dispatch = {
 	.name			= "pmc80xx",
 	.chip_init		= pm80xx_chip_init,
@@ -5064,5 +5169,6 @@ const struct pm8001_dispatch pm8001_80xx_dispatch = {
 	.set_nvmd_req		= pm8001_chip_set_nvmd_req,
 	.fw_flash_update_req	= pm8001_chip_fw_flash_update_req,
 	.set_dev_state_req	= pm8001_chip_set_dev_state_req,
+	.gpio_req		= pm80xx_chip_gpio_req,
 	.get_phy_profile_req	= pm8001_chip_get_phy_profile,
 };
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.h b/drivers/scsi/pm8001/pm80xx_hwi.h
index b5119c5479da..fed193df93d6 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.h
+++ b/drivers/scsi/pm8001/pm80xx_hwi.h
@@ -529,6 +529,55 @@ struct hw_event_ack_req {
 	u32	reserved1[27];
 } __attribute__((packed, aligned(4)));
 
+/*
+ * brief the data structure of GPIO Commannd
+ * use to control MPI GPIOs (64 bytes)
+ */
+struct gpio_req {
+	__le32	tag;
+	__le32	eobid_ge_gs_gr_gw;
+	__le32	gpio_wr_msk;
+	__le32	gpio_wr_val;
+	__le32	gpio_in_enabled;
+	__le32	gpio_pinsetup1;
+	__le32	gpio_pinsetup2;
+	__le32	gpio_evt_change;
+	__le32	gpio_evt_rise;
+	__le32	gpio_evt_fall;
+	u32	reserved[5];
+} __packed __aligned(4);
+
+#define GPIO_GW_BIT 0x1
+#define GPIO_GR_BIT 0x2
+#define GPIO_GS_BIT 0x4
+#define GPIO_GE_BIT 0x8
+
+/*
+ * brief the data structure of GPIO Response
+ * indicates the completion of GPIO command (64 bytes)
+ */
+struct gpio_resp {
+	__le32	tag;
+	u32	reserved[2];
+	__le32	gpio_rd_val;
+	__le32	gpio_in_enabled;
+	__le32	gpio_pinsetup1;
+	__le32	gpio_pinsetup2;
+	__le32	gpio_evt_change;
+	__le32	gpio_evt_rise;
+	__le32	gpio_evt_fall;
+	u32	reserved1[5];
+} __packed __aligned(4);
+
+/*
+ * brief the data structure of GPIO Event
+ * indicates the generation of GPIO event (64 bytes)
+ */
+struct gpio_event {
+	__le32	gpio_event;
+	u32	reserved[14];
+} __packed __aligned(4);
+
 /*
  * brief the data structure of PHY_START Response Command
  * indicates the completion of PHY_START command (64 bytes)
-- 
2.16.3


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 09/12] pm80xx : IOCTL functionality for SGPIO.
  2019-12-24  4:41 [PATCH 00/12] pm80xx : Updates for the driver version 0.1.39 Deepak Ukey
                   ` (7 preceding siblings ...)
  2019-12-24  4:41 ` [PATCH 08/12] pm80xx : IOCTL functionality for GPIO Deepak Ukey
@ 2019-12-24  4:41 ` Deepak Ukey
  2019-12-30  2:47   ` Nathan Chancellor
  2020-01-06 16:30   ` Jinpu Wang
  2019-12-24  4:41 ` [PATCH 10/12] pm80xx : sysfs attribute for non fatal dump Deepak Ukey
                   ` (2 subsequent siblings)
  11 siblings, 2 replies; 33+ messages in thread
From: Deepak Ukey @ 2019-12-24  4:41 UTC (permalink / raw)
  To: linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, deepak.ukey, jinpu.wang,
	martin.petersen, dpf, yuuzheng, auradkar, vishakhavc, bjashnani,
	radha, akshatzen

From: Deepak Ukey <Deepak.Ukey@microchip.com>

Added the IOCTL functionality for SGPIO.

Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
Signed-off-by: Viswas G <Viswas.G@microchip.com>
Signed-off-by: Vishakha Channapattan <vishakhavc@google.com>
Signed-off-by: Bhavesh Jashnani <bjashnani@google.com>
Signed-off-by: Radha Ramachandran <radha@google.com>
Signed-off-by: Akshat Jain <akshatzen@google.com>
Signed-off-by: Yu Zheng <yuuzheng@google.com>
---
 drivers/scsi/pm8001/pm8001_ctl.c  |  73 ++++++++++++++++
 drivers/scsi/pm8001/pm8001_ctl.h  |  72 ++++++++++++++++
 drivers/scsi/pm8001/pm8001_hwi.c  | 172 +++++++++++++++++++++++++++++++++++++-
 drivers/scsi/pm8001/pm8001_hwi.h  |  17 ++++
 drivers/scsi/pm8001/pm8001_init.c |   3 +
 drivers/scsi/pm8001/pm8001_sas.c  |  37 ++++++++
 drivers/scsi/pm8001/pm8001_sas.h  |  20 +++++
 drivers/scsi/pm8001/pm80xx_hwi.c  |   6 ++
 drivers/scsi/pm8001/pm80xx_hwi.h  |   3 +
 9 files changed, 402 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c
index 8292074c1e6f..3e59b2a7185a 100644
--- a/drivers/scsi/pm8001/pm8001_ctl.c
+++ b/drivers/scsi/pm8001/pm8001_ctl.c
@@ -1009,6 +1009,76 @@ static long pm8001_gpio_ioctl(struct pm8001_hba_info *pm8001_ha,
 	return ret;
 }
 
+static long pm8001_sgpio_ioctl(struct pm8001_hba_info *pm8001_ha,
+		unsigned long arg)
+{
+	struct sgpio_buffer buffer;
+	struct read_write_req_resp *req = &buffer.sgpio_req;
+	struct sgpio_req payload;
+	struct sgpio_ioctl_resp *sgpio_resp;
+	DECLARE_COMPLETION_ONSTACK(completion);
+	unsigned long timeout;
+	u32 ret = 0, i;
+
+	if (copy_from_user(&buffer, (struct sgpio_buffer *)arg,
+		sizeof(struct sgpio_buffer))) {
+		return ADPT_IOCTL_CALL_FAILED;
+	}
+	mutex_lock(&pm8001_ha->ioctl_mutex);
+	pm8001_ha->ioctl_completion = &completion;
+
+	payload.func_reg_index = cpu_to_le32((req->register_index << 24) |
+			(req->register_type << 16) | (req->function << 8) |
+			SMP_FRAME_REQ);
+	payload.count = req->register_count;
+
+	if (req->function == WRITE_SGPIO_REGISTER) {
+		if (req->register_count > MAX_SGPIO_REQ_PAYLOAD) {
+			ret = ADPT_IOCTL_CALL_FAILED;
+			goto exit;
+		}
+		for (i = 0; i < req->register_count; i++)
+			payload.value[i] = req->read_write_data[i];
+	}
+
+	ret = PM8001_CHIP_DISP->sgpio_req(pm8001_ha, &payload);
+	if (ret != 0) {
+		ret = ADPT_IOCTL_CALL_FAILED;
+		goto exit;
+	}
+	if (timeout < 2000)
+		timeout = 2000;
+
+	timeout = wait_for_completion_timeout(&completion,
+			msecs_to_jiffies(timeout));
+	if (timeout == 0) {
+		ret = ADPT_IOCTL_CALL_TIMEOUT;
+		goto exit;
+	}
+
+	sgpio_resp = &pm8001_ha->sgpio_resp;
+	req->frame_type		= sgpio_resp->func_result & 0xff;
+	req->function		= (sgpio_resp->func_result >> 8) & 0xff;
+	req->function_result	= (sgpio_resp->func_result >> 16) & 0xff;
+	if (req->function == READ_SGPIO_REGISTER) {
+		for (i = 0; i < req->register_count; i++)
+			req->read_write_data[i] = sgpio_resp->value[i];
+	}
+	ret = ADPT_IOCTL_CALL_SUCCESS;
+exit:
+	spin_lock_irq(&pm8001_ha->ioctl_lock);
+	pm8001_ha->ioctl_completion = NULL;
+	spin_unlock_irq(&pm8001_ha->ioctl_lock);
+	buffer.header.return_code = ret;
+	if (copy_to_user((void *)arg, (void *)&buffer,
+			sizeof(struct sgpio_buffer))) {
+		ret = ADPT_IOCTL_CALL_FAILED;
+	}
+	mutex_unlock(&pm8001_ha->ioctl_mutex);
+
+	return ret;
+}
+
 static int pm8001_ioctl_get_phy_profile(struct pm8001_hba_info *pm8001_ha,
 		unsigned long arg)
 {
@@ -1172,6 +1242,9 @@ static long pm8001_ioctl(struct file *file,
 	case ADPT_IOCTL_GPIO:
 		ret = pm8001_gpio_ioctl(pm8001_ha, arg);
 		break;
+	case ADPT_IOCTL_SGPIO:
+		ret = pm8001_sgpio_ioctl(pm8001_ha, arg);
+		break;
 	case ADPT_IOCTL_GET_PHY_PROFILE:
 		ret = pm8001_ioctl_get_phy_profile(pm8001_ha, arg);
 		return ret;
diff --git a/drivers/scsi/pm8001/pm8001_ctl.h b/drivers/scsi/pm8001/pm8001_ctl.h
index 5be43b2672d4..b1be0bc065d5 100644
--- a/drivers/scsi/pm8001/pm8001_ctl.h
+++ b/drivers/scsi/pm8001/pm8001_ctl.h
@@ -68,6 +68,39 @@
 
 #define MAX_NUM_PHYS			16
 
+/************************************************************
+ * SGPIO Function and Register type
+ ************************************************************/
+#define READ_SGPIO_REGISTER			0x02
+#define WRITE_SGPIO_REGISTER			0x82
+
+#define SMP_FRAME_REQ				0x40
+#define SMP_FRAME_RESP				0x41
+
+#define SGPIO_CONFIG_REG			0x0
+#define SGPIO_DRIVE_BY_DRIVE_RECEIVE_REG	0x1
+#define SGPIO_GENERAL_PURPOSE_RECEIVE_REG	0x2
+#define SGPIO_DRIVE_BY_DRIVE_TRANSMIT_REG	0x3
+#define SGPIO_GENERAL_PURPOSE_TRANSMIT_REG	0x4
+
+/************************************************************
+ * SGPIO Function result
+ ************************************************************/
+#define SGPIO_COMMAND_SUCCESS				0x00
+#define SGPIO_CMD_ERROR_WRONG_FRAME_TYPE		0x01
+#define SGPIO_CMD_ERROR_WRONG_REG_TYPE			0x02
+#define SGPIO_CMD_ERROR_WRONG_REG_INDEX			0x03
+#define SGPIO_CMD_ERROR_WRONG_REG_COUNT			0x04
+#define SGPIO_CMD_ERROR_WRONG_FRAME_REG_TYPE		0x05
+#define SGPIO_CMD_ERROR_WRONG_FUNCTION			0x06
+#define SGPIO_CMD_ERROR_WRONG_FRAME_TYPE_REG_INDEX	0x19
+#define SGPIO_CMD_ERROR_WRONG_FRAME_TYPE_REG_CNT	0x81
+#define SGPIO_CMD_ERROR_WRONG_REG_TYPE_REG_INDEX	0x1A
+#define SGPIO_CMD_ERROR_WRONG_REG_TYPE_REG_COUNT	0x82
+#define SGPIO_CMD_ERROR_WRONG_REG_INDEX_REG_COUNT	0x83
+#define SGPIO_CMD_ERROR_WRONG_FRAME_REG_TYPE_REG_INDEX	0x1D
+#define SGPIO_CMD_ERROR_WRONG_ALL_HEADER_PARAMS		0x9D
+
 struct ioctl_header {
 	u32 io_controller_num;
 	u32 length;
@@ -104,6 +137,39 @@ struct pm8001_gpio {
 	u32	event_falling_edge;
 };
 
+#define MAX_SGPIO_REQ_PAYLOAD	12
+#define MAX_SGPIO_RESP_PAYLOAD	13
+
+struct read_write_req_resp {
+	u8	frame_type;	/* =0x40 */
+	u8	function;	/* 0x02 for read, 0x82 for write */
+	u8	register_type;
+	u8	register_index;
+	u8	register_count;
+	u8	function_result;
+	u32	read_write_data[MAX_SGPIO_RESP_PAYLOAD];
+};
+
+struct sgpio_cfg_0 {
+	u8	reserved;
+	u8	version:4;
+	u8	reserved1:4;
+	u8	gp_register_count:4;
+	u8	cfg_register_count:3;
+	u8	enable:1;
+	u8	supported_drive_cnt;
+};
+
+struct sgpio_cfg_1 {
+	u8	reserved;
+	u8	blink_gen_a:4;
+	u8	blink_gen_b:4;
+	u8	max_act_on:4;
+	u8	forced_act_off:4;
+	u8	stretch_act_on:4;
+	u8	stretch_act_off:4;
+};
+
 struct ioctl_info_buffer {
 	struct ioctl_header	header;
 	struct ioctl_drv_info	information;
@@ -114,6 +180,11 @@ struct gpio_buffer {
 	struct pm8001_gpio	gpio_payload;
 };
 
+struct sgpio_buffer {
+	struct ioctl_header		header;
+	struct read_write_req_resp	sgpio_req;
+};
+
 struct phy_profile {
 	char		phy_id;
 	unsigned int	phys:4;
@@ -143,6 +214,7 @@ struct phy_prof_resp {
 
 #define ADPT_IOCTL_INFO _IOR(ADPT_MAGIC_NUMBER, 0, struct ioctl_info_buffer *)
 #define ADPT_IOCTL_GPIO	_IOWR(ADPT_MAGIC_NUMBER, 1, struct  gpio_buffer *)
+#define ADPT_IOCTL_SGPIO _IOWR(ADPT_MAGIC_NUMBER, 2, struct sgpio_buffer *)
 #define ADPT_IOCTL_GET_PHY_PROFILE _IOWR(ADPT_MAGIC_NUMBER, 8, \
 		struct phy_profile*)
 #define ADPT_IOCTL_GET_PHY_ERR_CNT _IOWR(ADPT_MAGIC_NUMBER, 9, \
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 2328ff1349ac..f9395d9fd530 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -3666,6 +3666,49 @@ int pm8001_mpi_dereg_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
 	return 0;
 }
 
+/**
+ *pm8001_sgpio_resp - pm8001 SGPIO response
+ *@pm8001_ha: HBA controller information
+ *@piomb: SGPIO payload
+ *Handles SGPIO response from HBA.
+ */
+
+int pm8001_sgpio_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
+{
+	u32 func_result;
+	u32 tag, i;
+	u32 value;
+	struct sgpio_ioctl_resp *sgpio_resp;
+	struct sgpio_reg_resp *registerRespPayload =
+		(struct sgpio_reg_resp *)(piomb + 4);
+
+	tag = le32_to_cpu(registerRespPayload->tag);
+	func_result = le32_to_cpu(registerRespPayload->func_result);
+	value = le32_to_cpu(registerRespPayload->value[0]);
+
+	PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+		"SGPIO func result = 0x%x tag %x value %x\n",
+		func_result, tag, value));
+
+	spin_lock(&pm8001_ha->ioctl_lock);
+	if (pm8001_ha->ioctl_completion != NULL) {
+		sgpio_resp = &pm8001_ha->sgpio_resp;
+		sgpio_resp->func_result = func_result;
+		PM8001_MSG_DBG(pm8001_ha,
+			pm8001_printk("SGPIO response value hexdump\n"));
+		for (i = 0; i < MAX_SGPIO_RESP_PAYLOAD; i++) {
+			sgpio_resp->value[i] =
+				le32_to_cpu(registerRespPayload->value[i]);
+			PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+				"value[%d] = %08x\n", i, sgpio_resp->value[i]));
+		}
+		complete(pm8001_ha->ioctl_completion);
+	}
+	spin_unlock(&pm8001_ha->ioctl_lock);
+	pm8001_tag_free(pm8001_ha, tag);
+	return 0;
+}
+
 /**
  * fw_flash_update_resp - Response from FW for flash update command.
  * @pm8001_ha: our hba card information
@@ -4035,7 +4078,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb)
 static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb)
 {
 	__le32 pHeader = *(__le32 *)piomb;
-	u8 opc = (u8)((le32_to_cpu(pHeader)) & 0xFFF);
+	u16 opc = (u8)((le32_to_cpu(pHeader)) & 0xFFF);
 
 	PM8001_MSG_DBG(pm8001_ha, pm8001_printk("process_one_iomb:"));
 
@@ -4190,6 +4233,11 @@ static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		PM8001_MSG_DBG(pm8001_ha,
 			pm8001_printk("OPC_OUB_SAS_RE_INITIALIZE\n"));
 		break;
+	case OPC_OUB_SGPIO_RESP:
+		PM8001_MSG_DBG(pm8001_ha,
+			pm8001_printk("OPC_OUB_SGPIO RESPONSE\n"));
+		pm8001_sgpio_resp(pm8001_ha, piomb);
+		break;
 	default:
 		PM8001_DEVIO_DBG(pm8001_ha,
 			pm8001_printk("Unknown outbound Queue IOMB OPC = %x\n",
@@ -5136,6 +5184,88 @@ pm8001_chip_set_dev_state_req(struct pm8001_hba_info *pm8001_ha,
 
 }
 
+/**
+ *pm8001_setup_sgpio - Setup SGPIO configuration for SPC/SPCv controllers
+ *pm8001_ha - controller information
+ */
+int pm8001_setup_sgpio(struct pm8001_hba_info *pm8001_ha)
+{
+	struct sgpio_req payload;
+	struct sgpio_cfg_0 *cfg_0;
+	struct sgpio_cfg_1 *cfg_1;
+	int rc, index = 0, i;
+	u32 value = 0;
+	DECLARE_COMPLETION_ONSTACK(completion);
+
+	pm8001_ha->ioctl_completion = &completion;
+	payload.func_reg_index = ((index << 24) | (SGPIO_CONFIG_REG << 16)
+			| (WRITE_SGPIO_REGISTER << 8) | SMP_FRAME_REQ);
+	payload.count = 2;
+
+	cfg_0 = (struct sgpio_cfg_0 *)(&value);
+	cfg_0->enable = 0x1;
+	payload.value[0] = value;
+
+	/*Initialize GPIO CFG 1 register to default as per SFF-8485 spec*/
+	cfg_1 = (struct sgpio_cfg_1 *)(&value);
+	cfg_1->blink_gen_a	= 0;
+	cfg_1->blink_gen_b	= 0;
+	cfg_1->max_act_on	= 0x2;
+	cfg_1->forced_act_off	= 0x1;
+	cfg_1->stretch_act_on	= 0;
+	cfg_1->stretch_act_off	= 0;
+
+	payload.value[1] = value;
+	PM8001_INIT_DBG(pm8001_ha,
+		pm8001_printk("Setting up sgpio. index %x count %x\n",
+		payload.func_reg_index, payload.count));
+
+	mutex_lock(&pm8001_ha->ioctl_mutex);
+	pm8001_ha->ioctl_completion = &completion;
+	rc = PM8001_CHIP_DISP->sgpio_req(pm8001_ha, &payload);
+	if (rc) {
+		PM8001_FAIL_DBG(pm8001_ha,
+			pm8001_printk("failed sgpio_req:%d\n", rc));
+		goto exit;
+	}
+	rc = wait_for_completion_timeout(&completion, msecs_to_jiffies(2000));
+	if (rc == 0) {
+		PM8001_FAIL_DBG(pm8001_ha,
+				pm8001_printk("failed sgpio_req timeout\n"));
+		rc = ADPT_IOCTL_CALL_TIMEOUT;
+		goto exit;
+	}
+	payload.func_reg_index = ((index << 24) |
+			(SGPIO_DRIVE_BY_DRIVE_TRANSMIT_REG << 16) |
+			(WRITE_SGPIO_REGISTER << 8) | SMP_FRAME_REQ);
+	payload.count = pm8001_ha->chip->n_phy/4;
+	value = 0xA0A0A0A0; //Activity=0x5, Locate=0, Error=0
+	for (i = 0; i < payload.count; i++)
+		payload.value[i] = value;
+	reinit_completion(&completion);
+	pm8001_ha->ioctl_completion = &completion;
+	rc = PM8001_CHIP_DISP->sgpio_req(pm8001_ha, &payload);
+	if (rc) {
+		PM8001_FAIL_DBG(pm8001_ha,
+			pm8001_printk("failed sgpio_req:%d\n", rc));
+		goto exit;
+	}
+	rc = wait_for_completion_timeout(&completion, msecs_to_jiffies(2000));
+	if (rc == 0) {
+		PM8001_FAIL_DBG(pm8001_ha,
+				pm8001_printk("failed sgpio_req timeout\n"));
+		rc = ADPT_IOCTL_CALL_TIMEOUT;
+		goto exit;
+	}
+
+exit:
+	spin_lock(&pm8001_ha->ioctl_lock);
+	pm8001_ha->ioctl_completion = NULL;
+	spin_unlock(&pm8001_ha->ioctl_lock);
+	mutex_unlock(&pm8001_ha->ioctl_mutex);
+	return rc;
+}
+
 static int
 pm8001_chip_sas_re_initialization(struct pm8001_hba_info *pm8001_ha)
 {
@@ -5164,6 +5294,45 @@ pm8001_chip_sas_re_initialization(struct pm8001_hba_info *pm8001_ha)
 
 }
 
+/**
+ * pm8001_chip_sgpio_req - support for SGPIO operation
+ * @pm8001_ha: our hba card information.
+ * @ioctl_payload: the payload for the SGPIO operation
+ */
+int pm8001_chip_sgpio_req(struct pm8001_hba_info *pm8001_ha,
+				struct sgpio_req *sgpio_payload)
+{
+	struct sgpio_reg_req payload;
+	struct inbound_queue_table *circularQ;
+	int rc, i;
+	u32 tag;
+	u32 opc = OPC_INB_SGPIO_REG;
+
+	memset(&payload, 0, sizeof(struct sgpio_reg_req));
+	rc = pm8001_tag_alloc(pm8001_ha, &tag);
+	if (rc)
+		return -1;
+
+	circularQ = &pm8001_ha->inbnd_q_tbl[0];
+	payload.tag = cpu_to_le32(tag);
+	payload.func_reg_index = cpu_to_le32(sgpio_payload->func_reg_index);
+	payload.count = cpu_to_le32(sgpio_payload->count);
+
+	for (i = 0; i < sgpio_payload->count; i++)
+		payload.value[i] = cpu_to_le32(sgpio_payload->value[i]);
+
+	PM8001_MSG_DBG(pm8001_ha,
+		pm8001_printk("sgpio operation. tag %x index %x count %x\n",
+		tag, sgpio_payload->func_reg_index, sgpio_payload->count));
+
+	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
+			sizeof(payload), 0);
+	if (rc != 0)
+		pm8001_tag_free(pm8001_ha, tag);
+
+	return rc;
+}
+
 const struct pm8001_dispatch pm8001_8001_dispatch = {
 	.name			= "pmc8001",
 	.chip_init		= pm8001_chip_init,
@@ -5191,4 +5360,5 @@ const struct pm8001_dispatch pm8001_8001_dispatch = {
 	.fw_flash_update_req	= pm8001_chip_fw_flash_update_req,
 	.set_dev_state_req	= pm8001_chip_set_dev_state_req,
 	.sas_re_init_req	= pm8001_chip_sas_re_initialization,
+	.sgpio_req		= pm8001_chip_sgpio_req,
 };
diff --git a/drivers/scsi/pm8001/pm8001_hwi.h b/drivers/scsi/pm8001/pm8001_hwi.h
index 6d91e2446542..aad2322467d2 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.h
+++ b/drivers/scsi/pm8001/pm8001_hwi.h
@@ -82,6 +82,7 @@
 #define OPC_INB_GET_DEVICE_STATE		43	/* 0x02B */
 #define OPC_INB_SET_DEV_INFO			44	/* 0x02C */
 #define OPC_INB_SAS_RE_INITIALIZE		45	/* 0x02D */
+#define OPC_INB_SGPIO_REG			46	/* 0x02E */
 
 /* for Response Opcode of IOMB */
 #define OPC_OUB_ECHO				1	/* 0x001 */
@@ -120,6 +121,7 @@
 #define OPC_OUB_GET_DEVICE_STATE		39	/* 0x027 */
 #define OPC_OUB_SET_DEV_INFO			40	/* 0x028 */
 #define OPC_OUB_SAS_RE_INITIALIZE		41	/* 0x029 */
+#define OPC_OUB_SGPIO_RESP			2094	/* 0x82E */
 
 /* for phy start*/
 #define SPINHOLD_DISABLE		(0x00 << 14)
@@ -697,6 +699,18 @@ struct set_dev_state_resp {
 	u32		reserved[11];
 } __attribute__((packed, aligned(4)));
 
+struct sgpio_reg_req {
+	__le32		tag;
+	__le32		func_reg_index;
+	__le32		count;
+	__le32		value[12];
+} __packed __aligned(4);
+
+struct sgpio_reg_resp {
+	__le32		tag;
+	__le32		func_result;
+	__le32		value[13];
+} __packed __aligned(4);
 
 #define NDS_BITS 0x0F
 #define PDS_BITS 0xF0
@@ -922,6 +936,9 @@ struct set_dev_state_resp {
 #define MAIN_HDA_FLAGS_OFFSET		0x84/* DWORD 0x21 */
 #define MAIN_ANALOG_SETUP_OFFSET	0x88/* DWORD 0x22 */
 
+/*FATAL ERROR INTERRUPT bit definition*/
+#define MAIN_CFG_SGPIO_ENABLE		(0x1 << 2)
+
 /* Gereral Status Table offset - byte offset */
 #define GST_GSTLEN_MPIS_OFFSET		0x00
 #define GST_IQ_FREEZE_STATE0_OFFSET	0x04
diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c
index 6e2512aa5f6e..c8414f1b9652 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -122,6 +122,7 @@ static struct sas_domain_function_template pm8001_transport_ops = {
 	.lldd_I_T_nexus_reset   = pm8001_I_T_nexus_reset,
 	.lldd_lu_reset		= pm8001_lu_reset,
 	.lldd_query_task	= pm8001_query_task,
+	.lldd_write_gpio	= pm8001_write_sgpio,
 };
 
 /**
@@ -1110,6 +1111,8 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
 	if (pm8001_configure_phy_settings(pm8001_ha))
 		goto err_out_shost;
 
+	pm8001_setup_sgpio(pm8001_ha);
+
 	pm8001_post_sas_ha_init(shost, chip);
 	rc = sas_register_ha(SHOST_TO_SAS_HA(shost));
 	if (rc) {
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index b7cbc312843e..1d03c62d8c99 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -1361,3 +1361,40 @@ int pm8001_clear_task_set(struct domain_device *dev, u8 *lun)
 	return pm8001_issue_ssp_tmf(dev, lun, &tmf_task);
 }
 
+int pm8001_write_sgpio(struct sas_ha_struct *sas_ha, u8 reg_type,
+			u8 reg_index, u8 reg_count, u8 *write_data)
+{
+	struct pm8001_hba_info *pm8001_ha = sas_ha->lldd_ha;
+	struct sgpio_req payload;
+	u32 ret = 0, i, j, value;
+
+	PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+		"reg_type=%x, reg_index:%x, reg_count:%x\n",
+		reg_type, reg_index, reg_count));
+
+	mutex_lock(&pm8001_ha->ioctl_mutex);
+
+	payload.func_reg_index = cpu_to_le32((reg_index << 24) |
+		(reg_type << 16) | (WRITE_SGPIO_REGISTER << 8) |
+		SMP_FRAME_REQ);
+
+	payload.count = reg_count;
+
+	for (i = 0; i < reg_count; i++) {
+		value = 0;
+		for (j = 0; j < 4; j++) {
+			value |= (u32)(*write_data) << (24-(j*8));
+			write_data++;
+		}
+		payload.value[i] = value;
+		PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+			"payload value: %x\n", payload.value[i]));
+	}
+
+	ret = PM8001_CHIP_DISP->sgpio_req(pm8001_ha, &payload);
+	if (ret != 0)
+		ret = -1;
+
+	mutex_unlock(&pm8001_ha->ioctl_mutex);
+	return ret;
+}
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index 8e442214c954..f95f4d714983 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -144,6 +144,17 @@ struct gpio_ioctl_resp {
 	u32	gpio_evt_fall;
 };
 
+struct sgpio_req {
+	u32	func_reg_index;
+	u32	count;
+	u32	value[MAX_SGPIO_REQ_PAYLOAD];
+};
+
+struct sgpio_ioctl_resp {
+	u32	func_result;
+	u32	value[MAX_SGPIO_RESP_PAYLOAD];
+};
+
 /* define task management IU */
 struct pm8001_tmf_task {
 	u8	tmf;
@@ -261,6 +272,8 @@ struct pm8001_dispatch {
 	int (*sas_re_init_req)(struct pm8001_hba_info *pm8001_ha);
 	int (*gpio_req)(struct pm8001_hba_info *pm8001_ha,
 		struct pm8001_gpio *gpio_payload);
+	int (*sgpio_req)(struct pm8001_hba_info *pm8001_ha,
+		struct sgpio_req *sgpio_payload);
 	int (*get_phy_profile_req)(struct pm8001_hba_info *pm8001_ha,
 		int phy, int page);
 };
@@ -585,6 +598,7 @@ struct pm8001_hba_info {
 	struct completion	*ioctl_completion;
 	struct timer_list	ioctl_timer;
 	u32			ioctl_timer_expired;
+	struct			sgpio_ioctl_resp sgpio_resp;
 	struct	phy_prof_resp	phy_profile_resp;
 	u32			reset_in_progress;
 };
@@ -698,6 +712,8 @@ int pm8001_lu_reset(struct domain_device *dev, u8 *lun);
 int pm8001_I_T_nexus_reset(struct domain_device *dev);
 int pm8001_I_T_nexus_event_handler(struct domain_device *dev);
 int pm8001_query_task(struct sas_task *task);
+int pm8001_write_sgpio(struct sas_ha_struct *sas_ha, u8 reg_type,
+		u8 reg_index, u8 reg_count, u8 *write_data);
 void pm8001_open_reject_retry(
 	struct pm8001_hba_info *pm8001_ha,
 	struct sas_task *task_to_close,
@@ -733,6 +749,8 @@ int pm8001_chip_abort_task(struct pm8001_hba_info *pm8001_ha,
 				struct pm8001_device *pm8001_dev,
 				u8 flag, u32 task_tag, u32 cmd_tag);
 int pm8001_chip_dereg_dev_req(struct pm8001_hba_info *pm8001_ha, u32 device_id);
+int pm8001_chip_sgpio_req(struct pm8001_hba_info *pm8001_ha,
+		struct sgpio_req *sgpio_payload);
 void pm8001_chip_make_sg(struct scatterlist *scatter, int nr, void *prd);
 void pm8001_work_fn(struct work_struct *work);
 int pm8001_handle_event(struct pm8001_hba_info *pm8001_ha,
@@ -754,6 +772,7 @@ int pm8001_mpi_fw_flash_update_resp(struct pm8001_hba_info *pm8001_ha,
 							void *piomb);
 int pm8001_mpi_general_event(struct pm8001_hba_info *pm8001_ha , void *piomb);
 int pm8001_mpi_task_abort_resp(struct pm8001_hba_info *pm8001_ha, void *piomb);
+int pm8001_sgpio_resp(struct pm8001_hba_info *pm8001_ha, void *piomb);
 struct sas_task *pm8001_alloc_task(void);
 void pm8001_task_done(struct sas_task *task);
 void pm8001_free_task(struct sas_task *task);
@@ -761,6 +780,7 @@ void pm8001_tag_free(struct pm8001_hba_info *pm8001_ha, u32 tag);
 struct pm8001_device *pm8001_find_dev(struct pm8001_hba_info *pm8001_ha,
 					u32 device_id);
 int pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha);
+int pm8001_setup_sgpio(struct pm8001_hba_info *pm8001_ha);
 
 int pm8001_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue);
 void pm8001_set_phy_profile(struct pm8001_hba_info *pm8001_ha,
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index 10a922e5a478..bbcdcff5d25b 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -4100,6 +4100,11 @@ static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb)
 			"OPC_OUB_SSP_COALESCED_COMP_RESP opcode:%x\n", opc));
 		ssp_coalesced_comp_resp(pm8001_ha, piomb);
 		break;
+	case OPC_OUB_SGPIO_RESP:
+		PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+			"OPC_OUB_SGPIO RESPONSE opcode: %x\n", opc));
+		pm8001_sgpio_resp(pm8001_ha, piomb);
+		break;
 	default:
 		PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk(
 			"Unknown outbound Queue IOMB OPC = 0x%x\n", opc));
@@ -5170,5 +5175,6 @@ const struct pm8001_dispatch pm8001_80xx_dispatch = {
 	.fw_flash_update_req	= pm8001_chip_fw_flash_update_req,
 	.set_dev_state_req	= pm8001_chip_set_dev_state_req,
 	.gpio_req		= pm80xx_chip_gpio_req,
+	.sgpio_req		= pm8001_chip_sgpio_req,
 	.get_phy_profile_req	= pm8001_chip_get_phy_profile,
 };
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.h b/drivers/scsi/pm8001/pm80xx_hwi.h
index fed193df93d6..2d7f67b1cd93 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.h
+++ b/drivers/scsi/pm8001/pm80xx_hwi.h
@@ -1509,6 +1509,9 @@ typedef struct SASProtocolTimerConfig SASProtocolTimerConfig_t;
 #define MAIN_MPI_ILA_RELEASE_TYPE	0xA4 /* DWORD 0x29 */
 #define MAIN_MPI_INACTIVE_FW_VERSION	0XB0 /* DWORD 0x2C */
 
+/*FATAL ERROR INTERRUPT bit definition*/
+#define MAIN_CFG_SGPIO_ENABLE		(0x1 << 2)
+
 /* Gereral Status Table offset - byte offset */
 #define GST_GSTLEN_MPIS_OFFSET		0x00
 #define GST_IQ_FREEZE_STATE0_OFFSET	0x04
-- 
2.16.3


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 10/12] pm80xx : sysfs attribute for non fatal dump.
  2019-12-24  4:41 [PATCH 00/12] pm80xx : Updates for the driver version 0.1.39 Deepak Ukey
                   ` (8 preceding siblings ...)
  2019-12-24  4:41 ` [PATCH 09/12] pm80xx : IOCTL functionality for SGPIO Deepak Ukey
@ 2019-12-24  4:41 ` Deepak Ukey
  2020-01-06 16:34   ` Jinpu Wang
  2019-12-24  4:41 ` [PATCH 11/12] pm80xx : Introduce read and write length for IOCTL payload structure Deepak Ukey
  2019-12-24  4:41 ` [PATCH 12/12] pm80xx : IOCTL functionality for TWI device Deepak Ukey
  11 siblings, 1 reply; 33+ messages in thread
From: Deepak Ukey @ 2019-12-24  4:41 UTC (permalink / raw)
  To: linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, deepak.ukey, jinpu.wang,
	martin.petersen, dpf, yuuzheng, auradkar, vishakhavc, bjashnani,
	radha, akshatzen

From: Deepak Ukey <Deepak.Ukey@microchip.com>

Added the functionality to collect non fatal dump.

Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
Signed-off-by: Viswas G <Viswas.G@microchip.com>
Signed-off-by: Vishakha Channapattan <vishakhavc@google.com>
Signed-off-by: Bhavesh Jashnani <bjashnani@google.com>
Signed-off-by: Radha Ramachandran <radha@google.com>
Signed-off-by: Akshat Jain <akshatzen@google.com>
Signed-off-by: Yu Zheng <yuuzheng@google.com>
---
 drivers/scsi/pm8001/pm8001_ctl.c  |  45 +++++++++++++
 drivers/scsi/pm8001/pm8001_init.c |   1 +
 drivers/scsi/pm8001/pm8001_sas.h  |   4 ++
 drivers/scsi/pm8001/pm80xx_hwi.c  | 130 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 180 insertions(+)

diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c
index 3e59b2a7185a..669c60a8d123 100644
--- a/drivers/scsi/pm8001/pm8001_ctl.c
+++ b/drivers/scsi/pm8001/pm8001_ctl.c
@@ -577,6 +577,49 @@ static ssize_t pm8001_ctl_fatal_log_show(struct device *cdev,
 
 static DEVICE_ATTR(fatal_log, S_IRUGO, pm8001_ctl_fatal_log_show, NULL);
 
+/**
+ ** non_fatal_log_show - non fatal error logging
+ ** @cdev:pointer to embedded class device
+ ** @buf: the buffer returned
+ **
+ ** A sysfs 'read-only' shost attribute.
+ **/
+static ssize_t non_fatal_log_show(struct device *cdev,
+	struct device_attribute *attr, char *buf)
+{
+	u32 count;
+
+	count = pm80xx_get_non_fatal_dump(cdev, attr, buf);
+	return count;
+}
+static DEVICE_ATTR_RO(non_fatal_log);
+
+static ssize_t non_fatal_count_show(struct device *cdev,
+		struct device_attribute *attr, char *buf)
+{
+	struct Scsi_Host *shost = class_to_shost(cdev);
+	struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
+	struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
+
+	return snprintf(buf, PAGE_SIZE, "%08x",
+			pm8001_ha->non_fatal_count);
+}
+
+static ssize_t non_fatal_count_store(struct device *cdev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct Scsi_Host *shost = class_to_shost(cdev);
+	struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
+	struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
+	int val = 0;
+
+	if (kstrtoint(buf, 16, &val) != 0)
+		return -EINVAL;
+
+	pm8001_ha->non_fatal_count = val;
+	return strlen(buf);
+}
+static DEVICE_ATTR_RW(non_fatal_count);
 
 /**
  ** pm8001_ctl_gsm_log_show - gsm dump collection
@@ -853,6 +896,8 @@ struct device_attribute *pm8001_host_attrs[] = {
 	&dev_attr_aap_log,
 	&dev_attr_iop_log,
 	&dev_attr_fatal_log,
+	&dev_attr_non_fatal_log,
+	&dev_attr_non_fatal_count,
 	&dev_attr_gsm_log,
 	&dev_attr_max_out_io,
 	&dev_attr_max_devices,
diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c
index c8414f1b9652..b74282bc1ed0 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -484,6 +484,7 @@ static struct pm8001_hba_info *pm8001_pci_alloc(struct pci_dev *pdev,
 	pm8001_ha->shost = shost;
 	pm8001_ha->id = pm8001_id++;
 	pm8001_ha->logging_level = logging_level;
+	pm8001_ha->non_fatal_count = 0;
 	if (link_rate >= 1 && link_rate <= 15)
 		pm8001_ha->link_rate = (link_rate << 8);
 	else {
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index f95f4d714983..47607a25f819 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -601,6 +601,8 @@ struct pm8001_hba_info {
 	struct			sgpio_ioctl_resp sgpio_resp;
 	struct	phy_prof_resp	phy_profile_resp;
 	u32			reset_in_progress;
+	u32			non_fatal_count;
+	u32			non_fatal_read_length;
 };
 
 struct pm8001_work {
@@ -790,6 +792,8 @@ void pm8001_set_phy_profile_single(struct pm8001_hba_info *pm8001_ha,
 int pm80xx_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue);
 ssize_t pm80xx_get_fatal_dump(struct device *cdev,
 		struct device_attribute *attr, char *buf);
+ssize_t pm80xx_get_non_fatal_dump(struct device *cdev,
+		struct device_attribute *attr, char *buf);
 ssize_t pm8001_get_gsm_dump(struct device *cdev, u32, char *buf);
 /* ctl shared API */
 extern struct device_attribute *pm8001_host_attrs[];
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index bbcdcff5d25b..4923660304aa 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -393,6 +393,136 @@ ssize_t pm80xx_get_fatal_dump(struct device *cdev,
 		(char *)buf;
 }
 
+/* pm80xx_get_non_fatal_dump - dump the nonfatal data from the dma
+ * location by the firmware.
+ */
+ssize_t pm80xx_get_non_fatal_dump(struct device *cdev,
+	struct device_attribute *attr, char *buf)
+{
+	struct Scsi_Host *shost = class_to_shost(cdev);
+	struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
+	struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
+	void __iomem *nonfatal_table_address = pm8001_ha->fatal_tbl_addr;
+	u32 accum_len = 0;
+	u32 total_len = 0;
+	u32 reg_val = 0;
+	u32 *temp = NULL;
+	u32 index = 0;
+	u32 output_length;
+	unsigned long start = 0;
+	char *buf_copy = buf;
+
+	temp = (u32 *)pm8001_ha->memoryMap.region[FORENSIC_MEM].virt_ptr;
+	if (++pm8001_ha->non_fatal_count == 1) {
+		if (pm8001_ha->chip_id == chip_8001) {
+			snprintf(pm8001_ha->forensic_info.data_buf.direct_data,
+				PAGE_SIZE, "Not supported for SPC controller");
+			return 0;
+		}
+		PM8001_IO_DBG(pm8001_ha,
+			pm8001_printk("forensic_info TYPE_NON_FATAL...\n"));
+		/*
+		 * Step 1: Write the host buffer parameters in the MPI Fatal and
+		 * Non-Fatal Error Dump Capture Table.This is the buffer
+		 * where debug data will be DMAed to.
+		 */
+		pm8001_mw32(nonfatal_table_address,
+		MPI_FATAL_EDUMP_TABLE_LO_OFFSET,
+		pm8001_ha->memoryMap.region[FORENSIC_MEM].phys_addr_lo);
+
+		pm8001_mw32(nonfatal_table_address,
+		MPI_FATAL_EDUMP_TABLE_HI_OFFSET,
+		pm8001_ha->memoryMap.region[FORENSIC_MEM].phys_addr_hi);
+
+		pm8001_mw32(nonfatal_table_address,
+		MPI_FATAL_EDUMP_TABLE_LENGTH, SYSFS_OFFSET);
+
+		/* Optionally, set the DUMPCTRL bit to 1 if the host
+		 * keeps sending active I/Os while capturing the non-fatal
+		 * debug data. Otherwise, leave this bit set to zero
+		 */
+		pm8001_mw32(nonfatal_table_address,
+		MPI_FATAL_EDUMP_TABLE_HANDSHAKE, MPI_FATAL_EDUMP_HANDSHAKE_RDY);
+
+		/*
+		 * Step 2: Clear Accumulative Length of Debug Data Transferred
+		 * [ACCDDLEN] field in the MPI Fatal and Non-Fatal Error Dump
+		 * Capture Table to zero.
+		 */
+		pm8001_mw32(nonfatal_table_address,
+				MPI_FATAL_EDUMP_TABLE_ACCUM_LEN, 0);
+
+		/* initiallize previous accumulated length to 0 */
+		pm8001_ha->forensic_preserved_accumulated_transfer = 0;
+		pm8001_ha->non_fatal_read_length = 0;
+	}
+
+	total_len = pm8001_mr32(nonfatal_table_address,
+			MPI_FATAL_EDUMP_TABLE_TOTAL_LEN);
+	/*
+	 * Step 3:Clear Fatal/Non-Fatal Debug Data Transfer Status [FDDTSTAT]
+	 * field and then request that the SPCv controller transfer the debug
+	 * data by setting bit 7 of the Inbound Doorbell Set Register.
+	 */
+	pm8001_mw32(nonfatal_table_address, MPI_FATAL_EDUMP_TABLE_STATUS, 0);
+	pm8001_cw32(pm8001_ha, 0, MSGU_IBDB_SET,
+			SPCv_MSGU_CFG_TABLE_NONFATAL_DUMP);
+
+	/*
+	 * Step 4.1: Read back the Inbound Doorbell Set Register (by polling for
+	 * 2 seconds) until register bit 7 is cleared.
+	 * This step only indicates the request is accepted by the controller.
+	 */
+	start = jiffies + (2 * HZ); /* 2 sec */
+	do {
+		reg_val = pm8001_cr32(pm8001_ha, 0, MSGU_IBDB_SET) &
+			SPCv_MSGU_CFG_TABLE_NONFATAL_DUMP;
+	} while ((reg_val != 0) && time_before(jiffies, start));
+
+	/* Step 4.2: To check the completion of the transfer, poll the Fatal/Non
+	 * Fatal Debug Data Transfer Status [FDDTSTAT] field for 2 seconds in
+	 * the MPI Fatal and Non-Fatal Error Dump Capture Table.
+	 */
+	start = jiffies + (2 * HZ); /* 2 sec */
+	do {
+		reg_val = pm8001_mr32(nonfatal_table_address,
+				MPI_FATAL_EDUMP_TABLE_STATUS);
+	} while ((!reg_val) && time_before(jiffies, start));
+
+	if ((reg_val == 0x00) ||
+		(reg_val == MPI_FATAL_EDUMP_TABLE_STAT_DMA_FAILED) ||
+		(reg_val > MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_DONE)) {
+		pm8001_ha->non_fatal_read_length = 0;
+		buf_copy += snprintf(buf_copy, PAGE_SIZE, "%08x ", 0xFFFFFFFF);
+		pm8001_ha->non_fatal_count = 0;
+		return (buf_copy - buf);
+	} else if (reg_val ==
+			MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_MORE_DATA) {
+		buf_copy += snprintf(buf_copy, PAGE_SIZE, "%08x ", 2);
+	} else if ((reg_val == MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_DONE) ||
+		(pm8001_ha->non_fatal_read_length >= total_len)) {
+		pm8001_ha->non_fatal_read_length = 0;
+		buf_copy += snprintf(buf_copy, PAGE_SIZE, "%08x ", 4);
+		pm8001_ha->non_fatal_count = 0;
+	}
+	accum_len = pm8001_mr32(nonfatal_table_address,
+			MPI_FATAL_EDUMP_TABLE_ACCUM_LEN);
+	output_length = accum_len -
+		pm8001_ha->forensic_preserved_accumulated_transfer;
+
+	for (index = 0; index < output_length/4; index++)
+		buf_copy += snprintf(buf_copy, PAGE_SIZE,
+				"%08x ", *(temp+index));
+
+	pm8001_ha->non_fatal_read_length += output_length;
+
+	/* store current accumulated length to use in next iteration as
+	 * the previous accumulated length
+	 */
+	pm8001_ha->forensic_preserved_accumulated_transfer = accum_len;
+	return (buf_copy - buf);
+}
+
 /**
  * read_main_config_table - read the configure table and save it.
  * @pm8001_ha: our hba card information
-- 
2.16.3


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 11/12] pm80xx : Introduce read and write length for IOCTL payload structure.
  2019-12-24  4:41 [PATCH 00/12] pm80xx : Updates for the driver version 0.1.39 Deepak Ukey
                   ` (9 preceding siblings ...)
  2019-12-24  4:41 ` [PATCH 10/12] pm80xx : sysfs attribute for non fatal dump Deepak Ukey
@ 2019-12-24  4:41 ` Deepak Ukey
  2020-01-06 16:35   ` Jinpu Wang
  2019-12-24  4:41 ` [PATCH 12/12] pm80xx : IOCTL functionality for TWI device Deepak Ukey
  11 siblings, 1 reply; 33+ messages in thread
From: Deepak Ukey @ 2019-12-24  4:41 UTC (permalink / raw)
  To: linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, deepak.ukey, jinpu.wang,
	martin.petersen, dpf, yuuzheng, auradkar, vishakhavc, bjashnani,
	radha, akshatzen

From: Viswas G <Viswas.G@microchip.com>

Removed the common length and introduce read and write length for
IOCTL payload structure.

Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
Signed-off-by: Viswas G <Viswas.G@microchip.com>
Signed-off-by: Vishakha Channapattan <vishakhavc@google.com>
Signed-off-by: Bhavesh Jashnani <bjashnani@google.com>
Signed-off-by: Radha Ramachandran <radha@google.com>
Signed-off-by: Akshat Jain <akshatzen@google.com>
Signed-off-by: Yu Zheng <yuuzheng@google.com>
---
 drivers/scsi/pm8001/pm8001_ctl.c  |  6 +++---
 drivers/scsi/pm8001/pm8001_hwi.c  | 22 +++++++++++-----------
 drivers/scsi/pm8001/pm8001_init.c | 12 ++++++------
 drivers/scsi/pm8001/pm8001_sas.h  |  3 ++-
 4 files changed, 22 insertions(+), 21 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c
index 669c60a8d123..63bd2a384d2e 100644
--- a/drivers/scsi/pm8001/pm8001_ctl.c
+++ b/drivers/scsi/pm8001/pm8001_ctl.c
@@ -486,7 +486,7 @@ static ssize_t pm8001_ctl_bios_version_show(struct device *cdev,
 	pm8001_ha->nvmd_completion = &completion;
 	payload.minor_function = 7;
 	payload.offset = 0;
-	payload.length = 4096;
+	payload.rd_length = 4096;
 	payload.func_specific = kzalloc(4096, GFP_KERNEL);
 	if (!payload.func_specific)
 		return -ENOMEM;
@@ -697,7 +697,7 @@ static int pm8001_set_nvmd(struct pm8001_hba_info *pm8001_ha)
 	payload = (struct pm8001_ioctl_payload *)ioctlbuffer;
 	memcpy((u8 *)&payload->func_specific, (u8 *)pm8001_ha->fw_image->data,
 				pm8001_ha->fw_image->size);
-	payload->length = pm8001_ha->fw_image->size;
+	payload->wr_length = pm8001_ha->fw_image->size;
 	payload->id = 0;
 	payload->minor_function = 0x1;
 	pm8001_ha->nvmd_completion = &completion;
@@ -743,7 +743,7 @@ static int pm8001_update_flash(struct pm8001_hba_info *pm8001_ha)
 					IOCTL_BUF_SIZE);
 		for (loopNumber = 0; loopNumber < loopcount; loopNumber++) {
 			payload = (struct pm8001_ioctl_payload *)ioctlbuffer;
-			payload->length = 1024*16;
+			payload->wr_length = 1024*16;
 			payload->id = 0;
 			fwControl =
 			      (struct fw_control_info *)&payload->func_specific;
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index f9395d9fd530..16dc7a92ad68 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -4841,7 +4841,7 @@ int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha,
 	if (!fw_control_context)
 		return -ENOMEM;
 	fw_control_context->usrAddr = (u8 *)ioctl_payload->func_specific;
-	fw_control_context->len = ioctl_payload->length;
+	fw_control_context->len = ioctl_payload->rd_length;
 	circularQ = &pm8001_ha->inbnd_q_tbl[0];
 	memset(&nvmd_req, 0, sizeof(nvmd_req));
 	rc = pm8001_tag_alloc(pm8001_ha, &tag);
@@ -4862,7 +4862,7 @@ int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha,
 
 		nvmd_req.len_ir_vpdd = cpu_to_le32(IPMode | twi_addr << 16 |
 			twi_page_size << 8 | TWI_DEVICE);
-		nvmd_req.resp_len = cpu_to_le32(ioctl_payload->length);
+		nvmd_req.resp_len = cpu_to_le32(ioctl_payload->rd_length);
 		nvmd_req.resp_addr_hi =
 		    cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_hi);
 		nvmd_req.resp_addr_lo =
@@ -4871,7 +4871,7 @@ int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha,
 	}
 	case C_SEEPROM: {
 		nvmd_req.len_ir_vpdd = cpu_to_le32(IPMode | C_SEEPROM);
-		nvmd_req.resp_len = cpu_to_le32(ioctl_payload->length);
+		nvmd_req.resp_len = cpu_to_le32(ioctl_payload->rd_length);
 		nvmd_req.resp_addr_hi =
 		    cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_hi);
 		nvmd_req.resp_addr_lo =
@@ -4880,7 +4880,7 @@ int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha,
 	}
 	case VPD_FLASH: {
 		nvmd_req.len_ir_vpdd = cpu_to_le32(IPMode | VPD_FLASH);
-		nvmd_req.resp_len = cpu_to_le32(ioctl_payload->length);
+		nvmd_req.resp_len = cpu_to_le32(ioctl_payload->rd_length);
 		nvmd_req.resp_addr_hi =
 		    cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_hi);
 		nvmd_req.resp_addr_lo =
@@ -4889,7 +4889,7 @@ int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha,
 	}
 	case EXPAN_ROM: {
 		nvmd_req.len_ir_vpdd = cpu_to_le32(IPMode | EXPAN_ROM);
-		nvmd_req.resp_len = cpu_to_le32(ioctl_payload->length);
+		nvmd_req.resp_len = cpu_to_le32(ioctl_payload->rd_length);
 		nvmd_req.resp_addr_hi =
 		    cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_hi);
 		nvmd_req.resp_addr_lo =
@@ -4898,7 +4898,7 @@ int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha,
 	}
 	case IOP_RDUMP: {
 		nvmd_req.len_ir_vpdd = cpu_to_le32(IPMode | IOP_RDUMP);
-		nvmd_req.resp_len = cpu_to_le32(ioctl_payload->length);
+		nvmd_req.resp_len = cpu_to_le32(ioctl_payload->rd_length);
 		nvmd_req.vpd_offset = cpu_to_le32(ioctl_payload->offset);
 		nvmd_req.resp_addr_hi =
 		cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_hi);
@@ -4938,7 +4938,7 @@ int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha,
 	circularQ = &pm8001_ha->inbnd_q_tbl[0];
 	memcpy(pm8001_ha->memoryMap.region[NVMD].virt_ptr,
 		&ioctl_payload->func_specific,
-		ioctl_payload->length);
+		ioctl_payload->wr_length);
 	memset(&nvmd_req, 0, sizeof(nvmd_req));
 	rc = pm8001_tag_alloc(pm8001_ha, &tag);
 	if (rc) {
@@ -4957,7 +4957,7 @@ int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha,
 		nvmd_req.reserved[0] = cpu_to_le32(0xFEDCBA98);
 		nvmd_req.len_ir_vpdd = cpu_to_le32(IPMode | twi_addr << 16 |
 			twi_page_size << 8 | TWI_DEVICE);
-		nvmd_req.resp_len = cpu_to_le32(ioctl_payload->length);
+		nvmd_req.resp_len = cpu_to_le32(ioctl_payload->wr_length);
 		nvmd_req.resp_addr_hi =
 		    cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_hi);
 		nvmd_req.resp_addr_lo =
@@ -4966,7 +4966,7 @@ int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha,
 	}
 	case C_SEEPROM:
 		nvmd_req.len_ir_vpdd = cpu_to_le32(IPMode | C_SEEPROM);
-		nvmd_req.resp_len = cpu_to_le32(ioctl_payload->length);
+		nvmd_req.resp_len = cpu_to_le32(ioctl_payload->wr_length);
 		nvmd_req.reserved[0] = cpu_to_le32(0xFEDCBA98);
 		nvmd_req.resp_addr_hi =
 		    cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_hi);
@@ -4975,7 +4975,7 @@ int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha,
 		break;
 	case VPD_FLASH:
 		nvmd_req.len_ir_vpdd = cpu_to_le32(IPMode | VPD_FLASH);
-		nvmd_req.resp_len = cpu_to_le32(ioctl_payload->length);
+		nvmd_req.resp_len = cpu_to_le32(ioctl_payload->wr_length);
 		nvmd_req.reserved[0] = cpu_to_le32(0xFEDCBA98);
 		nvmd_req.resp_addr_hi =
 		    cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_hi);
@@ -4984,7 +4984,7 @@ int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha,
 		break;
 	case EXPAN_ROM:
 		nvmd_req.len_ir_vpdd = cpu_to_le32(IPMode | EXPAN_ROM);
-		nvmd_req.resp_len = cpu_to_le32(ioctl_payload->length);
+		nvmd_req.resp_len = cpu_to_le32(ioctl_payload->wr_length);
 		nvmd_req.reserved[0] = cpu_to_le32(0xFEDCBA98);
 		nvmd_req.resp_addr_hi =
 		    cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_hi);
diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c
index b74282bc1ed0..6e037638656d 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -643,22 +643,22 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha)
 	if (pm8001_ha->chip_id == chip_8001) {
 		if (deviceid == 0x8081 || deviceid == 0x0042) {
 			payload.minor_function = 4;
-			payload.length = 4096;
+			payload.rd_length = 4096;
 		} else {
 			payload.minor_function = 0;
-			payload.length = 128;
+			payload.rd_length = 128;
 		}
 	} else if ((pm8001_ha->chip_id == chip_8070 ||
 			pm8001_ha->chip_id == chip_8072) &&
 			pm8001_ha->pdev->subsystem_vendor == PCI_VENDOR_ID_ATTO) {
 		payload.minor_function = 4;
-		payload.length = 4096;
+		payload.rd_length = 4096;
 	} else {
 		payload.minor_function = 1;
-		payload.length = 4096;
+		payload.rd_length = 4096;
 	}
 	payload.offset = 0;
-	payload.func_specific = kzalloc(payload.length, GFP_KERNEL);
+	payload.func_specific = kzalloc(payload.rd_length, GFP_KERNEL);
 	if (!payload.func_specific) {
 		PM8001_INIT_DBG(pm8001_ha, pm8001_printk("mem alloc fail\n"));
 		return;
@@ -728,7 +728,7 @@ static int pm8001_get_phy_settings_info(struct pm8001_hba_info *pm8001_ha)
 	/* SAS ADDRESS read from flash / EEPROM */
 	payload.minor_function = 6;
 	payload.offset = 0;
-	payload.length = 4096;
+	payload.rd_length = 4096;
 	payload.func_specific = kzalloc(4096, GFP_KERNEL);
 	if (!payload.func_specific)
 		return -ENOMEM;
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index 47607a25f819..917a17f4d595 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -164,10 +164,11 @@ struct pm8001_ioctl_payload {
 	u32	signature;
 	u16	major_function;
 	u16	minor_function;
-	u16	length;
 	u16	status;
 	u16	offset;
 	u16	id;
+	u32	wr_length;
+	u32	rd_length;
 	u8	*func_specific;
 };
 
-- 
2.16.3


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 12/12] pm80xx : IOCTL functionality for TWI device.
  2019-12-24  4:41 [PATCH 00/12] pm80xx : Updates for the driver version 0.1.39 Deepak Ukey
                   ` (10 preceding siblings ...)
  2019-12-24  4:41 ` [PATCH 11/12] pm80xx : Introduce read and write length for IOCTL payload structure Deepak Ukey
@ 2019-12-24  4:41 ` Deepak Ukey
  2020-01-02 12:20   ` Jinpu Wang
  11 siblings, 1 reply; 33+ messages in thread
From: Deepak Ukey @ 2019-12-24  4:41 UTC (permalink / raw)
  To: linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, deepak.ukey, jinpu.wang,
	martin.petersen, dpf, yuuzheng, auradkar, vishakhavc, bjashnani,
	radha, akshatzen

From: Viswas G <Viswas.G@microchip.com>

Added the IOCTL functionality for TWI device.

Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
Signed-off-by: Viswas G <Viswas.G@microchip.com>
Signed-off-by: Vishakha Channapattan <vishakhavc@google.com>
Signed-off-by: Bhavesh Jashnani <bjashnani@google.com>
Signed-off-by: Radha Ramachandran <radha@google.com>
Signed-off-by: Akshat Jain <akshatzen@google.com>
Signed-off-by: Yu Zheng <yuuzheng@google.com>
---
 drivers/scsi/pm8001/pm8001_ctl.c  | 133 ++++++++++++++++++++++++++++++++++++++
 drivers/scsi/pm8001/pm8001_ctl.h  |  23 +++++++
 drivers/scsi/pm8001/pm8001_hwi.c  | 113 ++++++++++++++++++++++++++------
 drivers/scsi/pm8001/pm8001_hwi.h  |   1 +
 drivers/scsi/pm8001/pm8001_init.c |  10 +++
 drivers/scsi/pm8001/pm8001_sas.h  |  13 ++++
 drivers/scsi/pm8001/pm80xx_hwi.c  |  41 ++++++++++++
 drivers/scsi/pm8001/pm80xx_hwi.h  |   1 +
 8 files changed, 314 insertions(+), 21 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c
index 63bd2a384d2e..ed791de44217 100644
--- a/drivers/scsi/pm8001/pm8001_ctl.c
+++ b/drivers/scsi/pm8001/pm8001_ctl.c
@@ -1124,6 +1124,126 @@ static long pm8001_sgpio_ioctl(struct pm8001_hba_info *pm8001_ha,
 	return ret;
 }
 
+static int icotl_twi_wr_request(int twi_wr,
+			struct pm8001_hba_info *pm8001_ha, unsigned long arg)
+{
+	int ret = 0;
+	unsigned char *buf;
+	int bus;
+	int addr;
+	bool addr_mode_7bit = true;
+	int rd_size = 0;
+	int wr_size = 0;
+	int offset = 0;
+	bool direct_addr  = true;
+	struct twi_ioctl_payload *twi_ioctl;
+
+	twi_ioctl = kmalloc(sizeof(struct twi_ioctl_payload), GFP_KERNEL);
+	if (!twi_ioctl) {
+		PM8001_FAIL_DBG(pm8001_ha,
+				pm8001_printk("Failed to allocate ioctl\n"));
+		return -ENOMEM;
+	}
+	ret = copy_from_user(twi_ioctl, (u8 *)arg, sizeof(*twi_ioctl));
+	if (ret) {
+		PM8001_FAIL_DBG(pm8001_ha,
+			pm8001_printk("Failed to get ioctl args\n"));
+		return -EIO;
+	}
+
+	bus = twi_ioctl->bus;
+	addr = twi_ioctl->addr;
+
+	switch (twi_wr) {
+	case TW_WRITE:
+		wr_size = twi_ioctl->wr_size;
+		/* first 1K read/write is not possible,
+		 * from 2k we have customer specific seeprom
+		 */
+		offset = twi_ioctl->offset;
+		if (wr_size > 48)
+			direct_addr = false;
+		buf = kzalloc(wr_size, GFP_KERNEL);
+
+		if (buf == NULL) {
+			PM8001_FAIL_DBG(pm8001_ha,
+				pm8001_printk("No Memory for write\n"));
+			return -ENOMEM;
+		}
+		ret = copy_from_user(buf, (u8 *)twi_ioctl->buf, wr_size);
+		if (!ret) {
+			ret = pm80xx_twi_wr_request(pm8001_ha, bus, addr,
+				addr_mode_7bit, rd_size, wr_size, offset,
+				direct_addr, buf);
+		} else {
+			PM8001_FAIL_DBG(pm8001_ha, pm8001_printk
+				("Failed to get data from buffer\n"));
+			return -EIO;
+		}
+		kfree(buf);
+		break;
+	case TW_READ:
+		rd_size = twi_ioctl->rd_size;
+		offset = twi_ioctl->offset;
+		if (rd_size > 48)
+			direct_addr = false;
+		buf = kzalloc(rd_size, GFP_KERNEL);
+		if (buf == NULL) {
+			PM8001_FAIL_DBG(pm8001_ha,
+				pm8001_printk("No Memory for read\n"));
+			return -ENOMEM;
+		}
+		ret = pm80xx_twi_wr_request(pm8001_ha, bus, addr,
+			addr_mode_7bit, rd_size, wr_size, offset,
+			direct_addr, buf);
+		if (!ret) {
+			ret = copy_to_user((u8 *)twi_ioctl->buf, buf, rd_size);
+			kfree(buf);
+		} else {
+			PM8001_FAIL_DBG(pm8001_ha, pm8001_printk
+				("pm80xx_twi_wr_request failed !!!\n"));
+			return -EIO;
+		}
+		break;
+	case TW_WRITE_READ:
+		rd_size = twi_ioctl->rd_size;
+		wr_size = twi_ioctl->wr_size;
+		offset = twi_ioctl->offset;
+		if (wr_size > 48 || rd_size > 48)
+			direct_addr = false;
+		buf = kzalloc(max_t(int, wr_size, rd_size), GFP_KERNEL);
+		if (buf == NULL) {
+			PM8001_FAIL_DBG(pm8001_ha,
+				pm8001_printk("No Memory for read\n"));
+			return -ENOMEM;
+		}
+		ret = copy_from_user(buf, (u8 *)twi_ioctl->buf, wr_size);
+		if (!ret) {
+			ret = pm80xx_twi_wr_request(pm8001_ha, bus, addr,
+				addr_mode_7bit, rd_size, wr_size, offset,
+				direct_addr, buf);
+			if (!ret)
+				ret = copy_to_user((u8 *)twi_ioctl->buf,
+					buf, rd_size);
+			else {
+				PM8001_FAIL_DBG(pm8001_ha, pm8001_printk
+				("Failed to copy data to read buffer\n"));
+				ret = -EIO;
+			}
+		} else {
+			PM8001_FAIL_DBG(pm8001_ha, pm8001_printk
+				("Failed to get data from write buffer\n"));
+			return -ENOMEM;
+		}
+		break;
+	default:
+		PM8001_FAIL_DBG(pm8001_ha, pm8001_printk
+			("Invalid twi operation\n"));
+		return -EINVAL;
+	}
+	return ret;
+}
+
 static int pm8001_ioctl_get_phy_profile(struct pm8001_hba_info *pm8001_ha,
 		unsigned long arg)
 {
@@ -1277,6 +1397,7 @@ static long pm8001_ioctl(struct file *file,
 	u32 ret = -EACCES;
 	struct pm8001_hba_info *pm8001_ha;
 	struct ioctl_header header;
+	u8 twi_wr = 0;
 
 	pm8001_ha = file->private_data;
 
@@ -1296,6 +1417,18 @@ static long pm8001_ioctl(struct file *file,
 	case ADPT_IOCTL_GET_PHY_ERR_CNT:
 		ret = pm8001_ioctl_get_phy_err(pm8001_ha, arg);
 		break;
+	case ADPT_IOCTL_TWI_WRITE:
+		twi_wr = 0x01;
+		ret = icotl_twi_wr_request(twi_wr, pm8001_ha, arg);
+		return ret;
+	case ADPT_IOCTL_TWI_READ:
+		twi_wr = 0x02;
+		ret = icotl_twi_wr_request(twi_wr, pm8001_ha, arg);
+		return ret;
+	case ADPT_IOCTL_TWI_WRITE_READ:
+		twi_wr = 0x03;
+		ret = icotl_twi_wr_request(twi_wr, pm8001_ha, arg);
+		return ret;
 	default:
 		ret = ADPT_IOCTL_CALL_INVALID_CODE;
 	}
diff --git a/drivers/scsi/pm8001/pm8001_ctl.h b/drivers/scsi/pm8001/pm8001_ctl.h
index b1be0bc065d5..57bf597aa9c3 100644
--- a/drivers/scsi/pm8001/pm8001_ctl.h
+++ b/drivers/scsi/pm8001/pm8001_ctl.h
@@ -101,6 +101,26 @@
 #define SGPIO_CMD_ERROR_WRONG_FRAME_REG_TYPE_REG_INDEX	0x1D
 #define SGPIO_CMD_ERROR_WRONG_ALL_HEADER_PARAMS		0x9D
 
+#define TWI_SEEPROM_BUS_NUMBER	0
+#define TWI_SEEPROM_DEV_ADDR	0xa0
+#define TWI_SEEPROM_READ_SIZE	1024
+#define TWI_SEEPROM_WRITE_SIZE	1024
+
+#define TW_IOCTL_STATUS_SUCCESS		0
+#define TW_IOCTL_STATUS_FAILURE		1
+#define TW_IOCTL_STATUS_WRONG_ADDR	0xA
+
+struct twi_ioctl_payload {
+	u32	bus;
+	u32	addr;
+	u32	rd_size;
+	u32	wr_size;
+	u32	offset;
+	u8	addr_mode;
+	u8	*buf;
+	u32	status;
+};
+
 struct ioctl_header {
 	u32 io_controller_num;
 	u32 length;
@@ -219,6 +239,9 @@ struct phy_prof_resp {
 		struct phy_profile*)
 #define ADPT_IOCTL_GET_PHY_ERR_CNT _IOWR(ADPT_MAGIC_NUMBER, 9, \
 		struct phy_err*)
+#define ADPT_IOCTL_TWI_READ _IOR('m', 10, char *)
+#define ADPT_IOCTL_TWI_WRITE _IOW('m', 11, char *)
+#define ADPT_IOCTL_TWI_WRITE_READ _IOWR('m', 12, char *)
 #define ADPT_MAGIC_NUMBER	'm'
 
 #endif /* PM8001_CTL_H_INCLUDED */
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 16dc7a92ad68..0736c4b8cf7b 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -3152,13 +3152,34 @@ void pm8001_mpi_set_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
 	u32 tag = le32_to_cpu(pPayload->tag);
 	struct pm8001_ccb_info *ccb = &pm8001_ha->ccb_info[tag];
 	u32 dlen_status = le32_to_cpu(pPayload->dlen_status);
-	complete(pm8001_ha->nvmd_completion);
-	PM8001_MSG_DBG(pm8001_ha, pm8001_printk("Set nvm data complete!\n"));
+	u32 *nvmd_data_addr;
+	u32 ir_tds_bn_dps_das_nvm =
+		le32_to_cpu(pPayload->ir_tda_bn_dps_das_nvm);
+	int tw_wr = (ir_tds_bn_dps_das_nvm & TR_MASK) >> 29;
+	struct fw_control_ex	*fw_control_context;
+
+	fw_control_context = ccb->fw_control_context;
 	if ((dlen_status & NVMD_STAT) != 0) {
 		PM8001_FAIL_DBG(pm8001_ha,
 			pm8001_printk("Set nvm data error!\n"));
+		complete(pm8001_ha->nvmd_completion);
 		return;
 	}
+
+	if ((ir_tds_bn_dps_das_nvm & NVMD_TYPE) == TWI_DEVICE) {
+		if (tw_wr == TW_READ || tw_wr == TW_WRITE_READ) {
+			if (ir_tds_bn_dps_das_nvm & IPMode) {
+				nvmd_data_addr =
+				pm8001_ha->memoryMap.region[NVMD].virt_ptr;
+			} else {
+				nvmd_data_addr = pPayload->nvm_data;
+			}
+			memcpy(fw_control_context->usrAddr, nvmd_data_addr,
+				fw_control_context->len);
+		}
+	}
+	complete(pm8001_ha->nvmd_completion);
+	PM8001_MSG_DBG(pm8001_ha, pm8001_printk("Set nvm data complete!\n"));
 	ccb->task = NULL;
 	ccb->ccb_tag = 0xFFFFFFFF;
 	pm8001_tag_free(pm8001_ha, tag);
@@ -3223,11 +3244,11 @@ pm8001_mpi_get_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
 	memcpy(fw_control_context->usrAddr,
 		pm8001_ha->memoryMap.region[NVMD].virt_ptr,
 		fw_control_context->len);
+	complete(pm8001_ha->nvmd_completion);
 	kfree(ccb->fw_control_context);
 	ccb->task = NULL;
 	ccb->ccb_tag = 0xFFFFFFFF;
 	pm8001_tag_free(pm8001_ha, tag);
-	complete(pm8001_ha->nvmd_completion);
 }
 
 int pm8001_mpi_local_phy_ctl(struct pm8001_hba_info *pm8001_ha, void *piomb)
@@ -4856,12 +4877,17 @@ int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha,
 
 	switch (nvmd_type) {
 	case TWI_DEVICE: {
-		u32 twi_addr, twi_page_size;
-		twi_addr = 0xa8;
-		twi_page_size = 2;
+		u32 twi_addr, twi_page_size, twi_addr_size, twi_busno;
+
+		twi_addr = pm8001_ha->twi_address;
+		twi_page_size = pm8001_ha->twi_page_size;
+		twi_addr_size = 1;
+		twi_busno = 0;
 
 		nvmd_req.len_ir_vpdd = cpu_to_le32(IPMode | twi_addr << 16 |
-			twi_page_size << 8 | TWI_DEVICE);
+				twi_busno << 12 | twi_page_size << 8 |
+				twi_addr_size << 4 | TWI_DEVICE);
+		nvmd_req.vpd_offset = cpu_to_le32(ioctl_payload->offset);
 		nvmd_req.resp_len = cpu_to_le32(ioctl_payload->rd_length);
 		nvmd_req.resp_addr_hi =
 		    cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_hi);
@@ -4936,32 +4962,77 @@ int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha,
 	if (!fw_control_context)
 		return -ENOMEM;
 	circularQ = &pm8001_ha->inbnd_q_tbl[0];
-	memcpy(pm8001_ha->memoryMap.region[NVMD].virt_ptr,
-		&ioctl_payload->func_specific,
-		ioctl_payload->wr_length);
+	if (nvmd_type != TWI_DEVICE) {
+		memcpy(pm8001_ha->memoryMap.region[NVMD].virt_ptr,
+			&ioctl_payload->func_specific,
+			ioctl_payload->wr_length);
+	}
 	memset(&nvmd_req, 0, sizeof(nvmd_req));
 	rc = pm8001_tag_alloc(pm8001_ha, &tag);
 	if (rc) {
 		kfree(fw_control_context);
-		return -EBUSY;
+		return rc;
 	}
 	ccb = &pm8001_ha->ccb_info[tag];
 	ccb->fw_control_context = fw_control_context;
 	ccb->ccb_tag = tag;
 	nvmd_req.tag = cpu_to_le32(tag);
+
 	switch (nvmd_type) {
 	case TWI_DEVICE: {
-		u32 twi_addr, twi_page_size;
-		twi_addr = 0xa8;
-		twi_page_size = 2;
+		u32 twi_addr, twi_page_size, twi_addr_size, twi_busno;
+		u32 addr_mode;
+		u8 *nvmd_data_addr;
+		u8 tr = 0, d_len = 0;
+		u32 ipdl = 0;//indirect data payload len
+		u32 tr_dl = 0; //twi read data len
+
+		addr_mode = (ioctl_payload->twi_direct_addr == true) ?
+			0 : IPMode;
+		if (ioctl_payload->rd_length) {
+			tr_dl = ioctl_payload->rd_length;
+			fw_control_context->usrAddr =
+				(u8 *)ioctl_payload->func_specific;
+			fw_control_context->len = ioctl_payload->rd_length;
+			tr = TW_READ;
+		}
+		if (ioctl_payload->wr_length) {
+			if (addr_mode  == 0) {
+				d_len = ioctl_payload->wr_length;
+				nvmd_data_addr =  (u8 *)&(nvmd_req.reserved[0]);
+			} else	{
+				ipdl = ioctl_payload->wr_length;
+				nvmd_data_addr =
+				pm8001_ha->memoryMap.region[NVMD].virt_ptr;
+			}
+			memcpy(nvmd_data_addr, ioctl_payload->func_specific,
+					ioctl_payload->wr_length);
+			tr = TW_WRITE;
+		}
+		if (ioctl_payload->wr_length && ioctl_payload->rd_length)
+			tr = TW_WRITE_READ;
+		twi_addr = ioctl_payload->twi_addr;
+		if (twi_addr == TWI_SEEPROM_DEV_ADDR)
+			tr = 0;//Reserved for SEEPROM access ,as by fw
+		twi_page_size = 0;
+		twi_addr_size = 1;
+		twi_busno = ioctl_payload->bus;
 		nvmd_req.reserved[0] = cpu_to_le32(0xFEDCBA98);
-		nvmd_req.len_ir_vpdd = cpu_to_le32(IPMode | twi_addr << 16 |
-			twi_page_size << 8 | TWI_DEVICE);
-		nvmd_req.resp_len = cpu_to_le32(ioctl_payload->wr_length);
-		nvmd_req.resp_addr_hi =
-		    cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_hi);
-		nvmd_req.resp_addr_lo =
-		    cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_lo);
+		nvmd_req.len_ir_vpdd = cpu_to_le32(addr_mode | (tr << 29) |
+				twi_addr << 16 | twi_busno << 12 |
+				twi_page_size << 8 | twi_addr_size << 4 |
+				TWI_DEVICE);
+		nvmd_req.vpd_offset = cpu_to_le32(d_len  << 24 |
+				ioctl_payload->offset);
+		nvmd_req.resp_len = cpu_to_le32(ipdl);
+
+		if (addr_mode == IPMode) {
+			nvmd_req.resp_addr_hi = cpu_to_le32
+			(pm8001_ha->memoryMap.region[NVMD].phys_addr_hi);
+			nvmd_req.resp_addr_lo = cpu_to_le32
+			(pm8001_ha->memoryMap.region[NVMD].phys_addr_lo);
+		}
+		nvmd_req.tr_dl = cpu_to_le32(tr_dl);
 		break;
 	}
 	case C_SEEPROM:
diff --git a/drivers/scsi/pm8001/pm8001_hwi.h b/drivers/scsi/pm8001/pm8001_hwi.h
index aad2322467d2..98e9ea6a4d6e 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.h
+++ b/drivers/scsi/pm8001/pm8001_hwi.h
@@ -634,6 +634,7 @@ struct set_nvm_data_req {
 	__le32	resp_addr_hi;
 	__le32	resp_len;
 	u32	reserved1;
+	__le32	tr_dl;
 } __attribute__((packed, aligned(4)));
 
 
diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c
index 6e037638656d..61fb9f622a5d 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -55,6 +55,14 @@ MODULE_PARM_DESC(link_rate, "Enable link rate.\n"
 		" 4: Link rate 6.0G\n"
 		" 8: Link rate 12.0G\n");
 
+static ulong twi_address = 0xa0;
+module_param(twi_address, ulong, 0644);
+MODULE_PARM_DESC(twi_address, "set the address of twi device.");
+
+static ulong twi_page_size;
+module_param(twi_page_size, ulong, 0644);
+MODULE_PARM_DESC(twi_page_size, "set the page size of twi device.");
+
 static struct scsi_transport_template *pm8001_stt;
 
 /**
@@ -484,6 +492,8 @@ static struct pm8001_hba_info *pm8001_pci_alloc(struct pci_dev *pdev,
 	pm8001_ha->shost = shost;
 	pm8001_ha->id = pm8001_id++;
 	pm8001_ha->logging_level = logging_level;
+	pm8001_ha->twi_address = twi_address;
+	pm8001_ha->twi_page_size = twi_page_size;
 	pm8001_ha->non_fatal_count = 0;
 	if (link_rate >= 1 && link_rate <= 15)
 		pm8001_ha->link_rate = (link_rate << 8);
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index 917a17f4d595..45128f89aebe 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -169,6 +169,9 @@ struct pm8001_ioctl_payload {
 	u16	id;
 	u32	wr_length;
 	u32	rd_length;
+	bool	twi_direct_addr;
+	u8	bus;
+	u8	twi_addr;
 	u8	*func_specific;
 };
 
@@ -586,6 +589,8 @@ struct pm8001_hba_info {
 #endif
 	u32			logging_level;
 	u32			link_rate;
+	u32			twi_address;
+	u32			twi_page_size;
 	u32			fw_status;
 	u32			smp_exp_mode;
 	bool			controller_fatal_error;
@@ -650,6 +655,11 @@ struct pm8001_fw_image_header {
 #define DS_IN_ERROR				0x04
 #define DS_NON_OPERATIONAL			0x07
 
+#define TR_MASK			0x60000000
+#define TW_WRITE		0x01
+#define TW_READ			0x02
+#define TW_WRITE_READ		0x03
+
 /**
  * brief param structure for firmware flash update.
  */
@@ -796,6 +806,9 @@ ssize_t pm80xx_get_fatal_dump(struct device *cdev,
 ssize_t pm80xx_get_non_fatal_dump(struct device *cdev,
 		struct device_attribute *attr, char *buf);
 ssize_t pm8001_get_gsm_dump(struct device *cdev, u32, char *buf);
+int pm80xx_twi_wr_request(struct pm8001_hba_info *pm8001_ha, int bus, int addr,
+		bool addr_mode_7bit, int rd_size, int wr_size,
+		int offset, bool direct_addr, unsigned char *buf);
 /* ctl shared API */
 extern struct device_attribute *pm8001_host_attrs[];
 
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index 4923660304aa..453202ee4d80 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -46,6 +46,47 @@
 #define SMP_DIRECT 1
 #define SMP_INDIRECT 2
 
+int pm80xx_twi_wr_request(struct pm8001_hba_info *pm8001_ha, int bus, int addr,
+			bool addr_mode_7bit, int rd_size, int wr_size,
+			int offset, bool direct_addr, unsigned char *buf)
+{
+	struct pm8001_ioctl_payload *payload;
+	u8 *ioctlbuffer = NULL;
+	int length, ret;
+	DECLARE_COMPLETION_ONSTACK(completion);
+
+	if ((wr_size > 48 || rd_size > 48) && direct_addr == true) {
+		PM8001_FAIL_DBG(pm8001_ha, pm8001_printk
+		("Direct addressing mode used if payload size < 48\n"));
+		return -EINVAL;
+	}
+
+	length = sizeof(*payload);
+	ioctlbuffer = kzalloc(length, GFP_KERNEL);
+	if (!ioctlbuffer)
+		return -ENOMEM;
+	payload = (struct pm8001_ioctl_payload *)ioctlbuffer;
+
+	pm8001_ha->nvmd_completion = &completion;
+	payload->minor_function = 0;
+
+	payload->rd_length = rd_size;
+	payload->wr_length = wr_size;
+	payload->bus = bus;
+	payload->twi_addr = addr;
+	payload->twi_direct_addr = direct_addr;
+	payload->offset = offset;
+
+	payload->func_specific = buf;
+
+	ret = PM8001_CHIP_DISP->set_nvmd_req(pm8001_ha, payload);
+
+	wait_for_completion(&completion);
+
+	kfree(ioctlbuffer);
+
+	return ret;
+}
 
 int pm80xx_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shift_value)
 {
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.h b/drivers/scsi/pm8001/pm80xx_hwi.h
index 2d7f67b1cd93..ba49d0abd6f4 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.h
+++ b/drivers/scsi/pm8001/pm80xx_hwi.h
@@ -966,6 +966,7 @@ struct set_nvm_data_req {
 	__le32	resp_addr_hi;
 	__le32	resp_len;
 	u32	reserved1[17];
+	__le32	tr_dl;
 } __attribute__((packed, aligned(4)));
 
 /**
-- 
2.16.3


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* Re: [PATCH 01/12] pm80xx : Increase request sg length.
  2019-12-24  4:41 ` [PATCH 01/12] pm80xx : Increase request sg length Deepak Ukey
@ 2019-12-25 15:57   ` kbuild test robot
  0 siblings, 0 replies; 33+ messages in thread
From: kbuild test robot @ 2019-12-25 15:57 UTC (permalink / raw)
  To: Deepak Ukey
  Cc: kbuild-all, linux-scsi, Vasanthalakshmi.Tharmarajan, Viswas.G,
	deepak.ukey, jinpu.wang, martin.petersen, dpf, yuuzheng,
	auradkar, vishakhavc, bjashnani, radha, akshatzen

[-- Attachment #1: Type: text/plain, Size: 2716 bytes --]

Hi Deepak,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on mkp-scsi/for-next]
[cannot apply to scsi/for-next v5.5-rc3 next-20191219]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]

url:    https://github.com/0day-ci/linux/commits/Deepak-Ukey/pm80xx-Updates-for-the-driver-version-0-1-39/20191225-181036
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git for-next
config: xtensa-allyesconfig (attached as .config)
compiler: xtensa-linux-gcc (GCC) 7.5.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        GCC_VERSION=7.5.0 make.cross ARCH=xtensa 

If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

   In file included from drivers/scsi/pm8001/pm8001_sas.h:58:0,
                    from drivers/scsi/pm8001/pm8001_init.c:42:
>> drivers/scsi/pm8001/pm8001_defs.h:102:0: warning: "CONFIG_SCSI_PM8001_MAX_DMA_SG" redefined
    #define CONFIG_SCSI_PM8001_MAX_DMA_SG 528
    
   In file included from include/linux/kconfig.h:5:0,
                    from <command-line>:0:
   ./include/generated/autoconf.h:9320:0: note: this is the location of the previous definition
    #define CONFIG_SCSI_PM8001_MAX_DMA_SG 128
    

vim +/CONFIG_SCSI_PM8001_MAX_DMA_SG +102 drivers/scsi/pm8001/pm8001_defs.h

    95	
    96	#define USI_MAX_MEMCNT_BASE	5
    97	#define IB			(USI_MAX_MEMCNT_BASE + 1)
    98	#define CI			(IB + PM8001_MAX_SPCV_INB_NUM)
    99	#define OB			(CI + PM8001_MAX_SPCV_INB_NUM)
   100	#define PI			(OB + PM8001_MAX_SPCV_OUTB_NUM)
   101	#define USI_MAX_MEMCNT		(PI + PM8001_MAX_SPCV_OUTB_NUM)
 > 102	#define	CONFIG_SCSI_PM8001_MAX_DMA_SG	528
   103	#define PM8001_MAX_DMA_SG	CONFIG_SCSI_PM8001_MAX_DMA_SG
   104	enum memory_region_num {
   105		AAP1 = 0x0, /* application acceleration processor */
   106		IOP,	    /* IO processor */
   107		NVMD,	    /* NVM device */
   108		DEV_MEM,    /* memory for devices */
   109		CCB_MEM,    /* memory for command control block */
   110		FW_FLASH,    /* memory for fw flash update */
   111		FORENSIC_MEM  /* memory for fw forensic data */
   112	};
   113	#define	PM8001_EVENT_LOG_SIZE	 (128 * 1024)
   114	

---
0-DAY kernel test infrastructure                 Open Source Technology Center
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 60576 bytes --]

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 09/12] pm80xx : IOCTL functionality for SGPIO.
  2019-12-24  4:41 ` [PATCH 09/12] pm80xx : IOCTL functionality for SGPIO Deepak Ukey
@ 2019-12-30  2:47   ` Nathan Chancellor
  2020-01-06 16:30   ` Jinpu Wang
  1 sibling, 0 replies; 33+ messages in thread
From: Nathan Chancellor @ 2019-12-30  2:47 UTC (permalink / raw)
  To: Deepak Ukey
  Cc: linux-scsi, Vasanthalakshmi.Tharmarajan, Viswas.G, jinpu.wang,
	martin.petersen, dpf, yuuzheng, auradkar, vishakhavc, bjashnani,
	radha, akshatzen, clang-built-linux

Hi Deepak,

The 0day bot reported an issue with this patch with Clang, would you
mind taking a look at it? The full report is attached at the bottom,
I've added a comment inline before it though.

On Tue, Dec 24, 2019 at 10:11:40AM +0530, Deepak Ukey wrote:
> From: Deepak Ukey <Deepak.Ukey@microchip.com>
> 
> Added the IOCTL functionality for SGPIO.
> 
> Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
> Signed-off-by: Viswas G <Viswas.G@microchip.com>
> Signed-off-by: Vishakha Channapattan <vishakhavc@google.com>
> Signed-off-by: Bhavesh Jashnani <bjashnani@google.com>
> Signed-off-by: Radha Ramachandran <radha@google.com>
> Signed-off-by: Akshat Jain <akshatzen@google.com>
> Signed-off-by: Yu Zheng <yuuzheng@google.com>
> ---
>  drivers/scsi/pm8001/pm8001_ctl.c  |  73 ++++++++++++++++
>  drivers/scsi/pm8001/pm8001_ctl.h  |  72 ++++++++++++++++
>  drivers/scsi/pm8001/pm8001_hwi.c  | 172 +++++++++++++++++++++++++++++++++++++-
>  drivers/scsi/pm8001/pm8001_hwi.h  |  17 ++++
>  drivers/scsi/pm8001/pm8001_init.c |   3 +
>  drivers/scsi/pm8001/pm8001_sas.c  |  37 ++++++++
>  drivers/scsi/pm8001/pm8001_sas.h  |  20 +++++
>  drivers/scsi/pm8001/pm80xx_hwi.c  |   6 ++
>  drivers/scsi/pm8001/pm80xx_hwi.h  |   3 +
>  9 files changed, 402 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c
> index 8292074c1e6f..3e59b2a7185a 100644
> --- a/drivers/scsi/pm8001/pm8001_ctl.c
> +++ b/drivers/scsi/pm8001/pm8001_ctl.c
> @@ -1009,6 +1009,76 @@ static long pm8001_gpio_ioctl(struct pm8001_hba_info *pm8001_ha,
>  	return ret;
>  }
>  
> +static long pm8001_sgpio_ioctl(struct pm8001_hba_info *pm8001_ha,
> +		unsigned long arg)
> +{
> +	struct sgpio_buffer buffer;
> +	struct read_write_req_resp *req = &buffer.sgpio_req;
> +	struct sgpio_req payload;
> +	struct sgpio_ioctl_resp *sgpio_resp;
> +	DECLARE_COMPLETION_ONSTACK(completion);
> +	unsigned long timeout;
> +	u32 ret = 0, i;
> +
> +	if (copy_from_user(&buffer, (struct sgpio_buffer *)arg,
> +		sizeof(struct sgpio_buffer))) {
> +		return ADPT_IOCTL_CALL_FAILED;
> +	}
> +	mutex_lock(&pm8001_ha->ioctl_mutex);
> +	pm8001_ha->ioctl_completion = &completion;
> +
> +	payload.func_reg_index = cpu_to_le32((req->register_index << 24) |
> +			(req->register_type << 16) | (req->function << 8) |
> +			SMP_FRAME_REQ);
> +	payload.count = req->register_count;
> +
> +	if (req->function == WRITE_SGPIO_REGISTER) {
> +		if (req->register_count > MAX_SGPIO_REQ_PAYLOAD) {
> +			ret = ADPT_IOCTL_CALL_FAILED;
> +			goto exit;
> +		}
> +		for (i = 0; i < req->register_count; i++)
> +			payload.value[i] = req->read_write_data[i];
> +	}
> +
> +	ret = PM8001_CHIP_DISP->sgpio_req(pm8001_ha, &payload);
> +	if (ret != 0) {
> +		ret = ADPT_IOCTL_CALL_FAILED;
> +		goto exit;
> +	}

timeout is uninitialized here; could this if statement be removed and
have the msecs_to_jiffies just hardcode the 2000?

> +	if (timeout < 2000)
> +		timeout = 2000;
> +
> +	timeout = wait_for_completion_timeout(&completion,
> +			msecs_to_jiffies(timeout));
> +	if (timeout == 0) {
> +		ret = ADPT_IOCTL_CALL_TIMEOUT;
> +		goto exit;
> +	}
> +
> +	sgpio_resp = &pm8001_ha->sgpio_resp;
> +	req->frame_type		= sgpio_resp->func_result & 0xff;
> +	req->function		= (sgpio_resp->func_result >> 8) & 0xff;
> +	req->function_result	= (sgpio_resp->func_result >> 16) & 0xff;
> +	if (req->function == READ_SGPIO_REGISTER) {
> +		for (i = 0; i < req->register_count; i++)
> +			req->read_write_data[i] = sgpio_resp->value[i];
> +	}
> +	ret = ADPT_IOCTL_CALL_SUCCESS;
> +exit:
> +	spin_lock_irq(&pm8001_ha->ioctl_lock);
> +	pm8001_ha->ioctl_completion = NULL;
> +	spin_unlock_irq(&pm8001_ha->ioctl_lock);
> +	buffer.header.return_code = ret;
> +	if (copy_to_user((void *)arg, (void *)&buffer,
> +			sizeof(struct sgpio_buffer))) {
> +		ret = ADPT_IOCTL_CALL_FAILED;
> +	}
> +	mutex_unlock(&pm8001_ha->ioctl_mutex);
> +
> +	return ret;
> +}
> +
>  static int pm8001_ioctl_get_phy_profile(struct pm8001_hba_info *pm8001_ha,
>  		unsigned long arg)
>  {
> @@ -1172,6 +1242,9 @@ static long pm8001_ioctl(struct file *file,
>  	case ADPT_IOCTL_GPIO:
>  		ret = pm8001_gpio_ioctl(pm8001_ha, arg);
>  		break;
> +	case ADPT_IOCTL_SGPIO:
> +		ret = pm8001_sgpio_ioctl(pm8001_ha, arg);
> +		break;
>  	case ADPT_IOCTL_GET_PHY_PROFILE:
>  		ret = pm8001_ioctl_get_phy_profile(pm8001_ha, arg);
>  		return ret;

On Thu, Dec 26, 2019 at 06:16:43AM +0800, kbuild test robot wrote:
> CC: kbuild-all@lists.01.org
> In-Reply-To: <20191224044143.8178-10-deepak.ukey@microchip.com>
> References: <20191224044143.8178-10-deepak.ukey@microchip.com>
> TO: Deepak Ukey <deepak.ukey@microchip.com>
> CC: linux-scsi@vger.kernel.org
> CC: Vasanthalakshmi.Tharmarajan@microchip.com, Viswas.G@microchip.com, deepak.ukey@microchip.com, jinpu.wang@profitbricks.com, martin.petersen@oracle.com, dpf@google.com, yuuzheng@google.com, auradkar@google.com, vishakhavc@google.com, bjashnani@google.com, radha@google.com, akshatzen@google.com
> 
> Hi Deepak,
> 
> Thank you for the patch! Perhaps something to improve:
> 
> [auto build test WARNING on mkp-scsi/for-next]
> [cannot apply to scsi/for-next v5.5-rc3 next-20191220]
> [if your patch is applied to the wrong git tree, please drop us a note to help
> improve the system. BTW, we also suggest to use '--base' option to specify the
> base tree in git format-patch, please see https://stackoverflow.com/a/37406982]
> 
> url:    https://github.com/0day-ci/linux/commits/Deepak-Ukey/pm80xx-Updates-for-the-driver-version-0-1-39/20191225-181036
> base:   https://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git for-next
> config: x86_64-allyesconfig (attached as .config)
> compiler: clang version 10.0.0 (git://gitmirror/llvm_project 9a77c2095439ba41bd8f6f35931b94075b2fd45b)
> reproduce:
>         # save the attached .config to linux build tree
>         make ARCH=x86_64 
> 
> If you fix the issue, kindly add following tag
> Reported-by: kbuild test robot <lkp@intel.com>
> 
> All warnings (new ones prefixed by >>):
> 
>    In file included from drivers/scsi/pm8001/pm8001_ctl.c:43:
>    In file included from drivers/scsi/pm8001/pm8001_sas.h:58:
>    drivers/scsi/pm8001/pm8001_defs.h:102:9: warning: 'CONFIG_SCSI_PM8001_MAX_DMA_SG' macro redefined [-Wmacro-redefined]
>    #define CONFIG_SCSI_PM8001_MAX_DMA_SG   528
>            ^
>    ./include/generated/autoconf.h:10861:9: note: previous definition is here
>    #define CONFIG_SCSI_PM8001_MAX_DMA_SG 128
>            ^
> >> drivers/scsi/pm8001/pm8001_ctl.c:1049:6: warning: variable 'timeout' is uninitialized when used here [-Wuninitialized]
>            if (timeout < 2000)
>                ^~~~~~~
>    drivers/scsi/pm8001/pm8001_ctl.c:1020:23: note: initialize the variable 'timeout' to silence this warning
>            unsigned long timeout;
>                                 ^
>                                  = 0
>    2 warnings generated.
> 
> vim +/timeout +1049 drivers/scsi/pm8001/pm8001_ctl.c
> 
>   1011	
>   1012	static long pm8001_sgpio_ioctl(struct pm8001_hba_info *pm8001_ha,
>   1013			unsigned long arg)
>   1014	{
>   1015		struct sgpio_buffer buffer;
>   1016		struct read_write_req_resp *req = &buffer.sgpio_req;
>   1017		struct sgpio_req payload;
>   1018		struct sgpio_ioctl_resp *sgpio_resp;
>   1019		DECLARE_COMPLETION_ONSTACK(completion);
>   1020		unsigned long timeout;
>   1021		u32 ret = 0, i;
>   1022	
>   1023		if (copy_from_user(&buffer, (struct sgpio_buffer *)arg,
>   1024			sizeof(struct sgpio_buffer))) {
>   1025			return ADPT_IOCTL_CALL_FAILED;
>   1026		}
>   1027		mutex_lock(&pm8001_ha->ioctl_mutex);
>   1028		pm8001_ha->ioctl_completion = &completion;
>   1029	
>   1030		payload.func_reg_index = cpu_to_le32((req->register_index << 24) |
>   1031				(req->register_type << 16) | (req->function << 8) |
>   1032				SMP_FRAME_REQ);
>   1033		payload.count = req->register_count;
>   1034	
>   1035		if (req->function == WRITE_SGPIO_REGISTER) {
>   1036			if (req->register_count > MAX_SGPIO_REQ_PAYLOAD) {
>   1037				ret = ADPT_IOCTL_CALL_FAILED;
>   1038				goto exit;
>   1039			}
>   1040			for (i = 0; i < req->register_count; i++)
>   1041				payload.value[i] = req->read_write_data[i];
>   1042		}
>   1043	
>   1044		ret = PM8001_CHIP_DISP->sgpio_req(pm8001_ha, &payload);
>   1045		if (ret != 0) {
>   1046			ret = ADPT_IOCTL_CALL_FAILED;
>   1047			goto exit;
>   1048		}
> > 1049		if (timeout < 2000)
>   1050			timeout = 2000;
>   1051	
>   1052		timeout = wait_for_completion_timeout(&completion,
>   1053				msecs_to_jiffies(timeout));
>   1054		if (timeout == 0) {
>   1055			ret = ADPT_IOCTL_CALL_TIMEOUT;
>   1056			goto exit;
>   1057		}
>   1058	
>   1059		sgpio_resp = &pm8001_ha->sgpio_resp;
>   1060		req->frame_type		= sgpio_resp->func_result & 0xff;
>   1061		req->function		= (sgpio_resp->func_result >> 8) & 0xff;
>   1062		req->function_result	= (sgpio_resp->func_result >> 16) & 0xff;
>   1063		if (req->function == READ_SGPIO_REGISTER) {
>   1064			for (i = 0; i < req->register_count; i++)
>   1065				req->read_write_data[i] = sgpio_resp->value[i];
>   1066		}
>   1067		ret = ADPT_IOCTL_CALL_SUCCESS;
>   1068	exit:
>   1069		spin_lock_irq(&pm8001_ha->ioctl_lock);
>   1070		pm8001_ha->ioctl_completion = NULL;
>   1071		spin_unlock_irq(&pm8001_ha->ioctl_lock);
>   1072		buffer.header.return_code = ret;
>   1073		if (copy_to_user((void *)arg, (void *)&buffer,
>   1074				sizeof(struct sgpio_buffer))) {
>   1075			ret = ADPT_IOCTL_CALL_FAILED;
>   1076		}
>   1077		mutex_unlock(&pm8001_ha->ioctl_mutex);
>   1078	
>   1079		return ret;
>   1080	}
>   1081	
> 
> ---
> 0-DAY kernel test infrastructure                 Open Source Technology Center
> https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org Intel Corporation

Cheers,
Nathan

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 02/12] pm80xx : Deal with kexec reboots.
  2019-12-24  4:41 ` [PATCH 02/12] pm80xx : Deal with kexec reboots Deepak Ukey
@ 2020-01-02 11:52   ` Jinpu Wang
  0 siblings, 0 replies; 33+ messages in thread
From: Jinpu Wang @ 2020-01-02 11:52 UTC (permalink / raw)
  To: Deepak Ukey
  Cc: Linux SCSI Mailinglist, Vasanthalakshmi.Tharmarajan, Viswas G,
	Jack Wang, Martin K. Petersen, dpf, yuuzheng, Vikram Auradkar,
	vishakhavc, bjashnani, radha, akshatzen

On Tue, Dec 24, 2019 at 5:40 AM Deepak Ukey <deepak.ukey@microchip.com> wrote:
>
> From: Vikram Auradkar <auradkar@google.com>
>
> A kexec reboot causes the controller fw to assert. This assertion
> shows up in two ways, the controller doesn't show up as ready and
> an interrupt is waiting as soon as the handler is registered. To
> resolve this added below fix:
> -split the interrupt handling setup into two parts, setup and
>  request.
> -If the controller ready register indicates not-ready, but that the
>  not readiness is only on the IOC units we can still try a reset to
>  bring the system back to the pre-reboot state.
>
> Signed-off-by: Vikram Auradkar <auradkar@google.com>
> Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
> Signed-off-by: Viswas G <Viswas.G@microchip.com>
> Signed-off-by: Vishakha Channapattan <vishakhavc@google.com>
> Signed-off-by: Bhavesh Jashnani <bjashnani@google.com>
> Signed-off-by: Radha Ramachandran <radha@google.com>
> Signed-off-by: Akshat Jain <akshatzen@google.com>
> Signed-off-by: Yu Zheng <yuuzheng@google.com>

The patch looks fine, Acked-by: Jack Wang <jinpu.wang@cloud.ionos.com>
ps: the signed-off-by chain was surprisingly long for such simple
patch, do they all contribute to the patch?
> ---
>  drivers/scsi/pm8001/pm8001_init.c | 48 +++++++++++++++++++++++++++++++++++----
>  drivers/scsi/pm8001/pm80xx_hwi.c  | 15 ++++++++----
>  2 files changed, 54 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c
> index 3f1e755c52c6..a002eb5a3fe4 100644
> --- a/drivers/scsi/pm8001/pm8001_init.c
> +++ b/drivers/scsi/pm8001/pm8001_init.c
> @@ -248,6 +248,9 @@ static irqreturn_t pm8001_interrupt_handler_intx(int irq, void *dev_id)
>         return ret;
>  }
>
> +static u32 pm8001_setup_irq(struct pm8001_hba_info *pm8001_ha);
> +static u32 pm8001_request_irq(struct pm8001_hba_info *pm8001_ha);
> +
>  /**
>   * pm8001_alloc - initiate our hba structure and 6 DMAs area.
>   * @pm8001_ha:our hba structure.
> @@ -890,9 +893,7 @@ static int pm8001_configure_phy_settings(struct pm8001_hba_info *pm8001_ha)
>   */
>  static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha)
>  {
> -       u32 i = 0, j = 0;
>         u32 number_of_intr;
> -       int flag = 0;
>         int rc;
>
>         /* SPCv controllers supports 64 msi-x */
> @@ -900,11 +901,11 @@ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha)
>                 number_of_intr = 1;
>         } else {
>                 number_of_intr = PM8001_MAX_MSIX_VEC;
> -               flag &= ~IRQF_SHARED;
>         }
>
>         rc = pci_alloc_irq_vectors(pm8001_ha->pdev, number_of_intr,
>                         number_of_intr, PCI_IRQ_MSIX);
> +       number_of_intr = rc;
>         if (rc < 0)
>                 return rc;
>         pm8001_ha->number_of_intr = number_of_intr;
> @@ -912,8 +913,22 @@ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha)
>         PM8001_INIT_DBG(pm8001_ha, pm8001_printk(
>                 "pci_alloc_irq_vectors request ret:%d no of intr %d\n",
>                                 rc, pm8001_ha->number_of_intr));
> +       return 0;
> +}
> +
> +static u32 pm8001_request_msix(struct pm8001_hba_info *pm8001_ha)
> +{
> +       u32 i = 0, j = 0;
> +       int flag = 0, rc = 0;
>
> -       for (i = 0; i < number_of_intr; i++) {
> +       if (pm8001_ha->chip_id != chip_8001)
> +               flag &= ~IRQF_SHARED;
> +
> +       PM8001_INIT_DBG(pm8001_ha,
> +               pm8001_printk("pci_enable_msix request number of intr %d\n",
> +               pm8001_ha->number_of_intr));
> +
> +       for (i = 0; i < pm8001_ha->number_of_intr; i++) {
>                 snprintf(pm8001_ha->intr_drvname[i],
>                         sizeof(pm8001_ha->intr_drvname[0]),
>                         "%s-%d", pm8001_ha->name, i);
> @@ -938,6 +953,21 @@ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha)
>  }
>  #endif
>
> +static u32 pm8001_setup_irq(struct pm8001_hba_info *pm8001_ha)
> +{
> +       struct pci_dev *pdev;
> +
> +       pdev = pm8001_ha->pdev;
> +
> +#ifdef PM8001_USE_MSIX
> +       if (pci_find_capability(pdev, PCI_CAP_ID_MSIX))
> +               return pm8001_setup_msix(pm8001_ha);
> +       PM8001_INIT_DBG(pm8001_ha,
> +               pm8001_printk("MSIX not supported!!!\n"));
> +#endif
> +       return 0;
> +}
> +
>  /**
>   * pm8001_request_irq - register interrupt
>   * @chip_info: our ha struct.
> @@ -951,7 +981,7 @@ static u32 pm8001_request_irq(struct pm8001_hba_info *pm8001_ha)
>
>  #ifdef PM8001_USE_MSIX
>         if (pdev->msix_cap && pci_msi_enabled())
> -               return pm8001_setup_msix(pm8001_ha);
> +               return pm8001_request_msix(pm8001_ha);
>         else {
>                 PM8001_INIT_DBG(pm8001_ha,
>                         pm8001_printk("MSIX not supported!!!\n"));
> @@ -1033,6 +1063,13 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
>                 rc = -ENOMEM;
>                 goto err_out_free;
>         }
> +       /* Setup Interrupt */
> +       rc = pm8001_setup_irq(pm8001_ha);
> +       if (rc) {
> +               PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
> +                       "pm8001_setup_irq failed [ret: %d]\n", rc));
> +               goto err_out_shost;
> +       }
>         list_add_tail(&pm8001_ha->list, &hba_list);
>         PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha);
>         rc = PM8001_CHIP_DISP->chip_init(pm8001_ha);
> @@ -1045,6 +1082,7 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
>         rc = scsi_add_host(shost, &pdev->dev);
>         if (rc)
>                 goto err_out_ha_free;
> +       /* Request Interrupt */
>         rc = pm8001_request_irq(pm8001_ha);
>         if (rc) {
>                 PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
> diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
> index 98dcdbd146d5..d805fd036ddf 100644
> --- a/drivers/scsi/pm8001/pm80xx_hwi.c
> +++ b/drivers/scsi/pm8001/pm80xx_hwi.c
> @@ -1438,11 +1438,18 @@ pm80xx_chip_soft_rst(struct pm8001_hba_info *pm8001_ha)
>         if (!pm8001_ha->controller_fatal_error) {
>                 /* Check if MPI is in ready state to reset */
>                 if (mpi_uninit_check(pm8001_ha) != 0) {
> -                       regval = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);
> +                       u32 r0 = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_0);
> +                       u32 r1 = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);
> +                       u32 r2 = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_2);
> +                       u32 r3 = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_3);
>                         PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
> -                               "MPI state is not ready scratch1 :0x%x\n",
> -                               regval));
> -                       return -1;
> +                               "MPI state is not ready scratch: %x:%x:%x:%x\n",
> +                               r0, r1, r2, r3));
> +                       /* if things aren't ready but the bootloader is ok then
> +                        * try the reset anyway.
> +                        */
> +                       if (r1 & SCRATCH_PAD1_BOOTSTATE_MASK)
> +                               return -1;
>                 }
>         }
>         /* checked for reset register normal state; 0x0 */
> --
> 2.16.3
>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 03/12] pm80xx : Free the tag when mpi_set_phy_profile_resp is received.
  2019-12-24  4:41 ` [PATCH 03/12] pm80xx : Free the tag when mpi_set_phy_profile_resp is received Deepak Ukey
@ 2020-01-02 11:55   ` Jinpu Wang
  0 siblings, 0 replies; 33+ messages in thread
From: Jinpu Wang @ 2020-01-02 11:55 UTC (permalink / raw)
  To: Deepak Ukey
  Cc: Linux SCSI Mailinglist, Vasanthalakshmi.Tharmarajan, Viswas G,
	Jack Wang, Martin K. Petersen, dpf, yuuzheng, Vikram Auradkar,
	vishakhavc, bjashnani, Radha Ramachandran, akshatzen

On Tue, Dec 24, 2019 at 5:41 AM Deepak Ukey <deepak.ukey@microchip.com> wrote:
>
> From: yuuzheng <yuuzheng@google.com>
>
> In pm80xx driver, the command mpi_set_phy_profile_req is sent by host
> during boot to configure the phy profile such as analog setting page,
> rate control page. However, the tag is not freed when its response is
> received. As a result, 16 tags are missing for each HBA after boot.
> When NCQ is enabled with queue depth 16, it needs at least, 15 * 16 =
> 240 tags for each HBA to achieve the best performance. In current
> pm80xx driver with setting CCB_MAX = 256, the total number of tags in
> each HBA is 255 for data IO. Hence, without returning those tags to the
> pool after boot, some device will finally be forced to non-ncq mode by
> ATA layer due to excessive errors (i.e. LLDD cannot allocate tag for
> queued task).
>
> Signed-off-by: yuuzheng <yuuzheng@google.com>
> Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
> Signed-off-by: Viswas G <Viswas.G@microchip.com>
> Signed-off-by: Vishakha Channapattan <vishakhavc@google.com>
> Signed-off-by: Bhavesh Jashnani <bjashnani@google.com>
> Signed-off-by: Radha Ramachandran <radha@google.com>
> Signed-off-by: Akshat Jain <akshatzen@google.com>
The patch looks fine.
Acked-by: Jack Wang <jinpu.wang@cloud.ionos.com>
> ---
>  drivers/scsi/pm8001/pm80xx_hwi.c | 10 +++++++---
>  1 file changed, 7 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
> index d805fd036ddf..37b82d7aa3d7 100644
> --- a/drivers/scsi/pm8001/pm80xx_hwi.c
> +++ b/drivers/scsi/pm8001/pm80xx_hwi.c
> @@ -3715,28 +3715,32 @@ static int mpi_flash_op_ext_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
>  static int mpi_set_phy_profile_resp(struct pm8001_hba_info *pm8001_ha,
>                         void *piomb)
>  {
> +       u32 tag;
>         u8 page_code;
> +       int rc = 0;
>         struct set_phy_profile_resp *pPayload =
>                 (struct set_phy_profile_resp *)(piomb + 4);
>         u32 ppc_phyid = le32_to_cpu(pPayload->ppc_phyid);
>         u32 status = le32_to_cpu(pPayload->status);
>
> +       tag = le32_to_cpu(pPayload->tag);
>         page_code = (u8)((ppc_phyid & 0xFF00) >> 8);
>         if (status) {
>                 /* status is FAILED */
>                 PM8001_FAIL_DBG(pm8001_ha,
>                         pm8001_printk("PhyProfile command failed  with status "
>                         "0x%08X \n", status));
> -               return -1;
> +               rc = -1;
>         } else {
>                 if (page_code != SAS_PHY_ANALOG_SETTINGS_PAGE) {
>                         PM8001_FAIL_DBG(pm8001_ha,
>                                 pm8001_printk("Invalid page code 0x%X\n",
>                                         page_code));
> -                       return -1;
> +                       rc = -1;
>                 }
>         }
> -       return 0;
> +       pm8001_tag_free(pm8001_ha, tag);
> +       return rc;
>  }
>
>  /**
> --
> 2.16.3
>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 04/12] pm80xx : Cleanup initialization loading fail path.
  2019-12-24  4:41 ` [PATCH 04/12] pm80xx : Cleanup initialization loading fail path Deepak Ukey
@ 2020-01-02 11:58   ` Jinpu Wang
  0 siblings, 0 replies; 33+ messages in thread
From: Jinpu Wang @ 2020-01-02 11:58 UTC (permalink / raw)
  To: Deepak Ukey
  Cc: Linux SCSI Mailinglist, Vasanthalakshmi.Tharmarajan, Viswas G,
	Jack Wang, Martin K. Petersen, dpf, yuuzheng, Vikram Auradkar,
	vishakhavc, bjashnani, Radha Ramachandran, akshatzen

On Tue, Dec 24, 2019 at 5:41 AM Deepak Ukey <deepak.ukey@microchip.com> wrote:
>
> From: Peter Chang <dpf@google.com>
>
> 1)Move the instance tracking down after we think the instance is
> good to go. avoids having a use-after free.
> 2)There are goto targets for trying to cleanup if the hw fails to
> initialize, but there's some overlap depending on who thinks they
> own the sub-structures.
>
> Signed-off-by: Peter Chang <dpf@google.com>
> Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
> Signed-off-by: Viswas G <Viswas.G@microchip.com>
> Signed-off-by: Vishakha Channapattan <vishakhavc@google.com>
> Signed-off-by: Bhavesh Jashnani <bjashnani@google.com>
> Signed-off-by: Radha Ramachandran <radha@google.com>
> Signed-off-by: Akshat Jain <akshatzen@google.com>
> Signed-off-by: Yu Zheng <yuuzheng@google.com>
The patch looks fine,
Acked-by: Jack Wang <jinpu.wang@cloud.ionos.com>
> ---
>  drivers/scsi/pm8001/pm8001_init.c | 17 +++++++++++------
>  1 file changed, 11 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c
> index a002eb5a3fe4..775517f9b39d 100644
> --- a/drivers/scsi/pm8001/pm8001_init.c
> +++ b/drivers/scsi/pm8001/pm8001_init.c
> @@ -1016,6 +1016,7 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
>         struct pm8001_hba_info *pm8001_ha;
>         struct Scsi_Host *shost = NULL;
>         const struct pm8001_chip_info *chip;
> +       struct sas_ha_struct *sha;
>
>         dev_printk(KERN_INFO, &pdev->dev,
>                 "pm80xx: driver version %s\n", DRV_VERSION);
> @@ -1044,12 +1045,12 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
>                 goto err_out_regions;
>         }
>         chip = &pm8001_chips[ent->driver_data];
> -       SHOST_TO_SAS_HA(shost) =
> -               kzalloc(sizeof(struct sas_ha_struct), GFP_KERNEL);
> -       if (!SHOST_TO_SAS_HA(shost)) {
> +       sha = kzalloc(sizeof(struct sas_ha_struct), GFP_KERNEL);
> +       if (!sha) {
>                 rc = -ENOMEM;
>                 goto err_out_free_host;
>         }
> +       SHOST_TO_SAS_HA(shost) = sha;
>
>         rc = pm8001_prep_sas_ha_init(shost, chip);
>         if (rc) {
> @@ -1070,7 +1071,7 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
>                         "pm8001_setup_irq failed [ret: %d]\n", rc));
>                 goto err_out_shost;
>         }
> -       list_add_tail(&pm8001_ha->list, &hba_list);
> +
>         PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha);
>         rc = PM8001_CHIP_DISP->chip_init(pm8001_ha);
>         if (rc) {
> @@ -1105,8 +1106,12 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
>
>         pm8001_post_sas_ha_init(shost, chip);
>         rc = sas_register_ha(SHOST_TO_SAS_HA(shost));
> -       if (rc)
> +       if (rc) {
> +               PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
> +                       "sas_register_ha failed [ret: %d]\n", rc));
>                 goto err_out_shost;
> +       }
> +       list_add_tail(&pm8001_ha->list, &hba_list);
>         scsi_scan_host(pm8001_ha->shost);
>         pm8001_ha->flags = PM8001F_RUN_TIME;
>         return 0;
> @@ -1116,7 +1121,7 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
>  err_out_ha_free:
>         pm8001_free(pm8001_ha);
>  err_out_free:
> -       kfree(SHOST_TO_SAS_HA(shost));
> +       kfree(sha);
>  err_out_free_host:
>         scsi_host_put(shost);
>  err_out_regions:
> --
> 2.16.3
>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 05/12] pm80xx : Support for char device.
  2019-12-24  4:41 ` [PATCH 05/12] pm80xx : Support for char device Deepak Ukey
@ 2020-01-02 12:03   ` Jinpu Wang
  0 siblings, 0 replies; 33+ messages in thread
From: Jinpu Wang @ 2020-01-02 12:03 UTC (permalink / raw)
  To: Deepak Ukey
  Cc: Linux SCSI Mailinglist, Vasanthalakshmi.Tharmarajan, Viswas G,
	Jack Wang, Martin K. Petersen, dpf, yuuzheng, Vikram Auradkar,
	vishakhavc, bjashnani, Radha Ramachandran, akshatzen

On Tue, Dec 24, 2019 at 5:41 AM Deepak Ukey <deepak.ukey@microchip.com> wrote:
>
> From: Deepak Ukey <Deepak.Ukey@microchip.com>
>
> Added the support to register char device for pm80xx module and
> also added the ioctl functionality to get driver info.

Please describe why do you need a char device, also the use case for
this get driver info functionality.

>
> Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
> Signed-off-by: Viswas G <Viswas.G@microchip.com>
> Signed-off-by: Vishakha Channapattan <vishakhavc@google.com>
> Signed-off-by: Bhavesh Jashnani <bjashnani@google.com>
> Signed-off-by: Radha Ramachandran <radha@google.com>
> Signed-off-by: Akshat Jain <akshatzen@google.com>
> Signed-off-by: Yu Zheng <yuuzheng@google.com>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 06/12] pm80xx : sysfs attribute for number of phys.
  2019-12-24  4:41 ` [PATCH 06/12] pm80xx : sysfs attribute for number of phys Deepak Ukey
@ 2020-01-02 12:07   ` Jinpu Wang
  2020-01-02 12:33     ` John Garry
  0 siblings, 1 reply; 33+ messages in thread
From: Jinpu Wang @ 2020-01-02 12:07 UTC (permalink / raw)
  To: Deepak Ukey
  Cc: Linux SCSI Mailinglist, Vasanthalakshmi.Tharmarajan, Viswas G,
	Jack Wang, Martin K. Petersen, dpf, yuuzheng, Vikram Auradkar,
	vishakhavc, bjashnani, Radha Ramachandran, akshatzen

On Tue, Dec 24, 2019 at 5:41 AM Deepak Ukey <deepak.ukey@microchip.com> wrote:
>
> From: Viswas G <Viswas.G@microchip.com>
>
> Added sysfs attribute to show number of phys.
>
> Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
> Signed-off-by: Viswas G <Viswas.G@microchip.com>
> Signed-off-by: Vishakha Channapattan <vishakhavc@google.com>
> Signed-off-by: Bhavesh Jashnani <bjashnani@google.com>
> Signed-off-by: Radha Ramachandran <radha@google.com>
> Signed-off-by: Akshat Jain <akshatzen@google.com>
> Signed-off-by: Yu Zheng <yuuzheng@google.com>
> ---
>  drivers/scsi/pm8001/pm8001_ctl.c | 20 ++++++++++++++++++++
>  1 file changed, 20 insertions(+)
>
> diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c
> index 69458b318a20..704c0daa7937 100644
> --- a/drivers/scsi/pm8001/pm8001_ctl.c
> +++ b/drivers/scsi/pm8001/pm8001_ctl.c
> @@ -89,6 +89,25 @@ static ssize_t controller_fatal_error_show(struct device *cdev,
>  }
>  static DEVICE_ATTR_RO(controller_fatal_error);
>
> +/**
> + * pm8001_ctl_num_phys_show - Number of phys
> + * @cdev:pointer to embedded class device
> + * @buf:the buffer returned
> + * A sysfs 'read-only' shost attribute.
> + */
> +static ssize_t num_phys_show(struct device *cdev,
> +               struct device_attribute *attr, char *buf)
please use pm8001_ctl_num_phys_show as function name, so it follows
same conversion as other functions.
Better also rename controller_fatal_error too.

Thanks
> +{
> +       int ret;
> +       struct Scsi_Host *shost = class_to_shost(cdev);
> +       struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
> +       struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
> +
> +       ret = sprintf(buf, "%d", pm8001_ha->chip->n_phy);
> +       return ret;
> +}
> +static DEVICE_ATTR_RO(num_phys);
> +
>  /**
>   * pm8001_ctl_fw_version_show - firmware version
>   * @cdev: pointer to embedded class device
> @@ -825,6 +844,7 @@ static DEVICE_ATTR(update_fw, S_IRUGO|S_IWUSR|S_IWGRP,
>  struct device_attribute *pm8001_host_attrs[] = {
>         &dev_attr_interface_rev,
>         &dev_attr_controller_fatal_error,
> +       &dev_attr_num_phys,
>         &dev_attr_fw_version,
>         &dev_attr_update_fw,
>         &dev_attr_aap_log,
> --
> 2.16.3
>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 07/12] pm80xx : IOCTL functionality to get phy profile.
  2019-12-24  4:41 ` [PATCH 07/12] pm80xx : IOCTL functionality to get phy profile Deepak Ukey
@ 2020-01-02 12:10   ` Jinpu Wang
  2020-01-02 16:42     ` Viswas.G
  0 siblings, 1 reply; 33+ messages in thread
From: Jinpu Wang @ 2020-01-02 12:10 UTC (permalink / raw)
  To: Deepak Ukey
  Cc: Linux SCSI Mailinglist, Vasanthalakshmi.Tharmarajan, Viswas G,
	Jack Wang, Martin K. Petersen, dpf, yuuzheng, Vikram Auradkar,
	vishakhavc, bjashnani, Radha Ramachandran, akshatzen

On Tue, Dec 24, 2019 at 5:41 AM Deepak Ukey <deepak.ukey@microchip.com> wrote:
>
> From: Viswas G <Viswas.G@microchip.com>
>
> Added the ioctl functionality to collect phy status and phy error.

Please split it to 2 patches, one for phy status and one for phy error

Thanks

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 12/12] pm80xx : IOCTL functionality for TWI device.
  2019-12-24  4:41 ` [PATCH 12/12] pm80xx : IOCTL functionality for TWI device Deepak Ukey
@ 2020-01-02 12:20   ` Jinpu Wang
  2020-01-02 16:41     ` Viswas.G
  0 siblings, 1 reply; 33+ messages in thread
From: Jinpu Wang @ 2020-01-02 12:20 UTC (permalink / raw)
  To: Deepak Ukey
  Cc: Linux SCSI Mailinglist, Vasanthalakshmi.Tharmarajan, Viswas G,
	Jack Wang, Martin K. Petersen, dpf, yuuzheng, Vikram Auradkar,
	vishakhavc, bjashnani, Radha Ramachandran, akshatzen

On Tue, Dec 24, 2019 at 5:41 AM Deepak Ukey <deepak.ukey@microchip.com> wrote:
>
> From: Viswas G <Viswas.G@microchip.com>
>
> Added the IOCTL functionality for TWI device.
>
Please extend the commit message, what's the new functionality, what's
the use case.

Thanks

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 06/12] pm80xx : sysfs attribute for number of phys.
  2020-01-02 12:07   ` Jinpu Wang
@ 2020-01-02 12:33     ` John Garry
  2020-01-02 16:38       ` Viswas.G
  0 siblings, 1 reply; 33+ messages in thread
From: John Garry @ 2020-01-02 12:33 UTC (permalink / raw)
  To: Jinpu Wang, Deepak Ukey
  Cc: Linux SCSI Mailinglist, Vasanthalakshmi.Tharmarajan, Viswas G,
	Jack Wang, Martin K. Petersen, dpf, yuuzheng, Vikram Auradkar,
	vishakhavc, bjashnani, Radha Ramachandran, akshatzen

On 02/01/2020 12:07, Jinpu Wang wrote:
> On Tue, Dec 24, 2019 at 5:41 AM Deepak Ukey <deepak.ukey@microchip.com> wrote:
>>
>> From: Viswas G <Viswas.G@microchip.com>
>>
>> Added sysfs attribute to show number of phys.
>>
>> Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
>> Signed-off-by: Viswas G <Viswas.G@microchip.com>
>> Signed-off-by: Vishakha Channapattan <vishakhavc@google.com>
>> Signed-off-by: Bhavesh Jashnani <bjashnani@google.com>
>> Signed-off-by: Radha Ramachandran <radha@google.com>
>> Signed-off-by: Akshat Jain <akshatzen@google.com>
>> Signed-off-by: Yu Zheng <yuuzheng@google.com>
>> ---
>>   drivers/scsi/pm8001/pm8001_ctl.c | 20 ++++++++++++++++++++
>>   1 file changed, 20 insertions(+)
>>
>> diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c
>> index 69458b318a20..704c0daa7937 100644
>> --- a/drivers/scsi/pm8001/pm8001_ctl.c
>> +++ b/drivers/scsi/pm8001/pm8001_ctl.c
>> @@ -89,6 +89,25 @@ static ssize_t controller_fatal_error_show(struct device *cdev,
>>   }
>>   static DEVICE_ATTR_RO(controller_fatal_error);
>>
>> +/**
>> + * pm8001_ctl_num_phys_show - Number of phys
>> + * @cdev:pointer to embedded class device
>> + * @buf:the buffer returned
>> + * A sysfs 'read-only' shost attribute.
>> + */
>> +static ssize_t num_phys_show(struct device *cdev,
>> +               struct device_attribute *attr, char *buf)
> please use pm8001_ctl_num_phys_show as function name, so it follows
> same conversion as other functions.
> Better also rename controller_fatal_error too.

If you don't mind me saying, this info is already available in sysfs for 
any libsas or even SAS host (using scsi_transport_sas.c), like this:

john@ubuntu:/sys/class/sas_phy$ ls
phy-0:0     phy-0:0:12  phy-0:0:17  phy-0:0:21  phy-0:0:4  phy-0:0:9 
phy-0:5
phy-0:0:0   phy-0:0:13  phy-0:0:18  phy-0:0:22  phy-0:0:5  phy-0:1 
phy-0:6
phy-0:0:1   phy-0:0:14  phy-0:0:19  phy-0:0:23  phy-0:0:6  phy-0:2 
phy-0:7
phy-0:0:10  phy-0:0:15  phy-0:0:2   phy-0:0:24  phy-0:0:7  phy-0:3
phy-0:0:11  phy-0:0:16  phy-0:0:20  phy-0:0:3   phy-0:0:8  phy-0:4


Any phy-X:Y is a root phy, and X denotes the host index and Y is the phy 
index.

> 
> Thanks
>> +{
>> +       int ret;
>> +       struct Scsi_Host *shost = class_to_shost(cdev);
>> +       struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
>> +       struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
>> +
>> +       ret = sprintf(buf, "%d", pm8001_ha->chip->n_phy);
>> +       return ret;
>> +}
>> +static DEVICE_ATTR_RO(num_phys);
>> +
>>   /**
>>    * pm8001_ctl_fw_version_show - firmware version
>>    * @cdev: pointer to embedded class device
>> @@ -825,6 +844,7 @@ static DEVICE_ATTR(update_fw, S_IRUGO|S_IWUSR|S_IWGRP,
>>   struct device_attribute *pm8001_host_attrs[] = {
>>          &dev_attr_interface_rev,
>>          &dev_attr_controller_fatal_error,
>> +       &dev_attr_num_phys,
>>          &dev_attr_fw_version,
>>          &dev_attr_update_fw,
>>          &dev_attr_aap_log,
>> --
>> 2.16.3
>>
> .
> 


^ permalink raw reply	[flat|nested] 33+ messages in thread

* RE: [PATCH 06/12] pm80xx : sysfs attribute for number of phys.
  2020-01-02 12:33     ` John Garry
@ 2020-01-02 16:38       ` Viswas.G
  2020-01-13  9:26         ` Deepak.Ukey
  0 siblings, 1 reply; 33+ messages in thread
From: Viswas.G @ 2020-01-02 16:38 UTC (permalink / raw)
  To: john.garry, jinpu.wang, Deepak.Ukey
  Cc: linux-scsi, Vasanthalakshmi.Tharmarajan, jinpu.wang,
	martin.petersen, dpf, yuuzheng, auradkar, vishakhavc, bjashnani,
	radha, akshatzen

Thanks John Garry. The intention here is to get the total number of phys for the controller through sysfs and it is used by the management utility as well. 

Regards,
Viswas G

-----Original Message-----
From: John Garry <john.garry@huawei.com> 
Sent: Thursday, January 2, 2020 6:03 PM
To: Jinpu Wang <jinpu.wang@cloud.ionos.com>; Deepak Ukey - I31172 <Deepak.Ukey@microchip.com>
Cc: Linux SCSI Mailinglist <linux-scsi@vger.kernel.org>; Vasanthalakshmi Tharmarajan - I30664 <Vasanthalakshmi.Tharmarajan@microchip.com>; Viswas G - I30667 <Viswas.G@microchip.com>; Jack Wang <jinpu.wang@profitbricks.com>; Martin K. Petersen <martin.petersen@oracle.com>; dpf@google.com; yuuzheng@google.com; Vikram Auradkar <auradkar@google.com>; vishakhavc@google.com; bjashnani@google.com; Radha Ramachandran <radha@google.com>; akshatzen@google.com
Subject: Re: [PATCH 06/12] pm80xx : sysfs attribute for number of phys.

EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe

On 02/01/2020 12:07, Jinpu Wang wrote:
> On Tue, Dec 24, 2019 at 5:41 AM Deepak Ukey <mailto:deepak.ukey@microchip.com> wrote:
>>
>> From: Viswas G <mailto:Viswas.G@microchip.com>
>>
>> Added sysfs attribute to show number of phys.
>>
>> Signed-off-by: Deepak Ukey <mailto:deepak.ukey@microchip.com>
>> Signed-off-by: Viswas G <mailto:Viswas.G@microchip.com>
>> Signed-off-by: Vishakha Channapattan <mailto:vishakhavc@google.com>
>> Signed-off-by: Bhavesh Jashnani <mailto:bjashnani@google.com>
>> Signed-off-by: Radha Ramachandran <mailto:radha@google.com>
>> Signed-off-by: Akshat Jain <mailto:akshatzen@google.com>
>> Signed-off-by: Yu Zheng <mailto:yuuzheng@google.com>
>> ---
>>   drivers/scsi/pm8001/pm8001_ctl.c | 20 ++++++++++++++++++++
>>   1 file changed, 20 insertions(+)
>>
>> diff --git a/drivers/scsi/pm8001/pm8001_ctl.c 
>> b/drivers/scsi/pm8001/pm8001_ctl.c
>> index 69458b318a20..704c0daa7937 100644
>> --- a/drivers/scsi/pm8001/pm8001_ctl.c
>> +++ b/drivers/scsi/pm8001/pm8001_ctl.c
>> @@ -89,6 +89,25 @@ static ssize_t controller_fatal_error_show(struct device *cdev,
>>   }
>>   static DEVICE_ATTR_RO(controller_fatal_error);
>>
>> +/**
>> + * pm8001_ctl_num_phys_show - Number of phys
>> + * @cdev:pointer to embedded class device
>> + * @buf:the buffer returned
>> + * A sysfs 'read-only' shost attribute.
>> + */
>> +static ssize_t num_phys_show(struct device *cdev,
>> +               struct device_attribute *attr, char *buf)
> please use pm8001_ctl_num_phys_show as function name, so it follows 
> same conversion as other functions.
> Better also rename controller_fatal_error too.

If you don't mind me saying, this info is already available in sysfs for any libsas or even SAS host (using scsi_transport_sas.c), like this:

john@ubuntu:/sys/class/sas_phy$ ls
phy-0:0     phy-0:0:12  phy-0:0:17  phy-0:0:21  phy-0:0:4  phy-0:0:9
phy-0:5
phy-0:0:0   phy-0:0:13  phy-0:0:18  phy-0:0:22  phy-0:0:5  phy-0:1
phy-0:6
phy-0:0:1   phy-0:0:14  phy-0:0:19  phy-0:0:23  phy-0:0:6  phy-0:2
phy-0:7
phy-0:0:10  phy-0:0:15  phy-0:0:2   phy-0:0:24  phy-0:0:7  phy-0:3
phy-0:0:11  phy-0:0:16  phy-0:0:20  phy-0:0:3   phy-0:0:8  phy-0:4


Any phy-X:Y is a root phy, and X denotes the host index and Y is the phy index.

>
> Thanks
>> +{
>> +       int ret;
>> +       struct Scsi_Host *shost = class_to_shost(cdev);
>> +       struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
>> +       struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
>> +
>> +       ret = sprintf(buf, "%d", pm8001_ha->chip->n_phy);
>> +       return ret;
>> +}
>> +static DEVICE_ATTR_RO(num_phys);
>> +
>>   /**
>>    * pm8001_ctl_fw_version_show - firmware version
>>    * @cdev: pointer to embedded class device @@ -825,6 +844,7 @@ 
>> static DEVICE_ATTR(update_fw, S_IRUGO|S_IWUSR|S_IWGRP,
>>   struct device_attribute *pm8001_host_attrs[] = {
>>          &dev_attr_interface_rev,
>>          &dev_attr_controller_fatal_error,
>> +       &dev_attr_num_phys,
>>          &dev_attr_fw_version,
>>          &dev_attr_update_fw,
>>          &dev_attr_aap_log,
>> --
>> 2.16.3
>>
> .
>


^ permalink raw reply	[flat|nested] 33+ messages in thread

* RE: [PATCH 12/12] pm80xx : IOCTL functionality for TWI device.
  2020-01-02 12:20   ` Jinpu Wang
@ 2020-01-02 16:41     ` Viswas.G
  0 siblings, 0 replies; 33+ messages in thread
From: Viswas.G @ 2020-01-02 16:41 UTC (permalink / raw)
  To: jinpu.wang, Deepak.Ukey
  Cc: linux-scsi, Vasanthalakshmi.Tharmarajan, jinpu.wang,
	martin.petersen, dpf, yuuzheng, auradkar, vishakhavc, bjashnani,
	radha, akshatzen

Thanks Jinpu Wang . We will address this in the v2 patch set.

Regards,
Viswas G

-----Original Message-----
From: Jinpu Wang <jinpu.wang@cloud.ionos.com> 
Sent: Thursday, January 2, 2020 5:51 PM
To: Deepak Ukey - I31172 <Deepak.Ukey@microchip.com>
Cc: Linux SCSI Mailinglist <linux-scsi@vger.kernel.org>; Vasanthalakshmi Tharmarajan - I30664 <Vasanthalakshmi.Tharmarajan@microchip.com>; Viswas G - I30667 <Viswas.G@microchip.com>; Jack Wang <jinpu.wang@profitbricks.com>; Martin K. Petersen <martin.petersen@oracle.com>; dpf@google.com; yuuzheng@google.com; Vikram Auradkar <auradkar@google.com>; vishakhavc@google.com; bjashnani@google.com; Radha Ramachandran <radha@google.com>; akshatzen@google.com
Subject: Re: [PATCH 12/12] pm80xx : IOCTL functionality for TWI device.

EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe

On Tue, Dec 24, 2019 at 5:41 AM Deepak Ukey <deepak.ukey@microchip.com> wrote:
>
> From: Viswas G <Viswas.G@microchip.com>
>
> Added the IOCTL functionality for TWI device.
>
Please extend the commit message, what's the new functionality, what's the use case.

Thanks

^ permalink raw reply	[flat|nested] 33+ messages in thread

* RE: [PATCH 07/12] pm80xx : IOCTL functionality to get phy profile.
  2020-01-02 12:10   ` Jinpu Wang
@ 2020-01-02 16:42     ` Viswas.G
  0 siblings, 0 replies; 33+ messages in thread
From: Viswas.G @ 2020-01-02 16:42 UTC (permalink / raw)
  To: jinpu.wang, Deepak.Ukey
  Cc: linux-scsi, Vasanthalakshmi.Tharmarajan, jinpu.wang,
	martin.petersen, dpf, yuuzheng, auradkar, vishakhavc, bjashnani,
	radha, akshatzen

Thanks Jinpu Wang . We will address this in the v2 patch set.

Regards,
Viswas G

-----Original Message-----
From: Jinpu Wang <jinpu.wang@cloud.ionos.com> 
Sent: Thursday, January 2, 2020 5:41 PM
To: Deepak Ukey - I31172 <Deepak.Ukey@microchip.com>
Cc: Linux SCSI Mailinglist <linux-scsi@vger.kernel.org>; Vasanthalakshmi Tharmarajan - I30664 <Vasanthalakshmi.Tharmarajan@microchip.com>; Viswas G - I30667 <Viswas.G@microchip.com>; Jack Wang <jinpu.wang@profitbricks.com>; Martin K. Petersen <martin.petersen@oracle.com>; dpf@google.com; yuuzheng@google.com; Vikram Auradkar <auradkar@google.com>; vishakhavc@google.com; bjashnani@google.com; Radha Ramachandran <radha@google.com>; akshatzen@google.com
Subject: Re: [PATCH 07/12] pm80xx : IOCTL functionality to get phy profile.

EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe

On Tue, Dec 24, 2019 at 5:41 AM Deepak Ukey <deepak.ukey@microchip.com> wrote:
>
> From: Viswas G <Viswas.G@microchip.com>
>
> Added the ioctl functionality to collect phy status and phy error.

Please split it to 2 patches, one for phy status and one for phy error

Thanks

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 08/12] pm80xx : IOCTL functionality for GPIO.
  2019-12-24  4:41 ` [PATCH 08/12] pm80xx : IOCTL functionality for GPIO Deepak Ukey
@ 2020-01-06 16:25   ` Jinpu Wang
  2020-01-06 16:39     ` Jinpu Wang
  0 siblings, 1 reply; 33+ messages in thread
From: Jinpu Wang @ 2020-01-06 16:25 UTC (permalink / raw)
  To: Deepak Ukey
  Cc: Linux SCSI Mailinglist, Vasanthalakshmi.Tharmarajan, Viswas G,
	Jack Wang, Martin K. Petersen, dpf, yuuzheng, Vikram Auradkar,
	vishakhavc, bjashnani, Radha Ramachandran, akshatzen

On Tue, Dec 24, 2019 at 5:41 AM Deepak Ukey <deepak.ukey@microchip.com> wrote:
>
> From: Deepak Ukey <Deepak.Ukey@microchip.com>
>
> Added IOCTL functionality for GPIO.
> The SPCv controller provides 24 GPIO signals. The first 12 signals
> [11:0] and the last 4 signals [23:20] are for customer use. Eight
> signals [19:12] are reserved for the SPCv controller firmware.
> Whenever the host performs GPIO setup or a read/write operation
> using the GPIO command the host needs to make sure that it does
> not disturb the GPIO configuration for the bits [19:12].
> Each signal can be configured either as an input or as an output.
> When configured as an output, the host can use the GPIO Command to
> set the desired level. GPIO inputs can also be configured so that
> the SPCv controller sends the GPIO Event notification when specific
> GPIO events occur.
> Different GPIO features implemented:
> 1) GPIO Pin Setup
> 2) GPIO Event Setup
> 3) GPIO Read
> 4) GPIO Write
>

I think you can also implement lldd_write_gpio callback, so smp_utils
can also control gpio, right?

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 09/12] pm80xx : IOCTL functionality for SGPIO.
  2019-12-24  4:41 ` [PATCH 09/12] pm80xx : IOCTL functionality for SGPIO Deepak Ukey
  2019-12-30  2:47   ` Nathan Chancellor
@ 2020-01-06 16:30   ` Jinpu Wang
  1 sibling, 0 replies; 33+ messages in thread
From: Jinpu Wang @ 2020-01-06 16:30 UTC (permalink / raw)
  To: Deepak Ukey
  Cc: Linux SCSI Mailinglist, Vasanthalakshmi.Tharmarajan, Viswas G,
	Jack Wang, Martin K. Petersen, dpf, yuuzheng, Vikram Auradkar,
	vishakhavc, bjashnani, Radha Ramachandran, akshatzen

On Tue, Dec 24, 2019 at 5:41 AM Deepak Ukey <deepak.ukey@microchip.com> wrote:
>
> From: Deepak Ukey <Deepak.Ukey@microchip.com>
>
> Added the IOCTL functionality for SGPIO.
>
Please extends your commit message, what's the use case, please fix
the warnings Nathan reported.

Thanks

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 10/12] pm80xx : sysfs attribute for non fatal dump.
  2019-12-24  4:41 ` [PATCH 10/12] pm80xx : sysfs attribute for non fatal dump Deepak Ukey
@ 2020-01-06 16:34   ` Jinpu Wang
  0 siblings, 0 replies; 33+ messages in thread
From: Jinpu Wang @ 2020-01-06 16:34 UTC (permalink / raw)
  To: Deepak Ukey
  Cc: Linux SCSI Mailinglist, Vasanthalakshmi.Tharmarajan, Viswas G,
	Jack Wang, Martin K. Petersen, dpf, yuuzheng, Vikram Auradkar,
	vishakhavc, bjashnani, Radha Ramachandran, akshatzen

On Tue, Dec 24, 2019 at 5:41 AM Deepak Ukey <deepak.ukey@microchip.com> wrote:
>
> From: Deepak Ukey <Deepak.Ukey@microchip.com>
>
> Added the functionality to collect non fatal dump.
Please extend the commit message, what the use case, how to use it.
>
> Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
> Signed-off-by: Viswas G <Viswas.G@microchip.com>
> Signed-off-by: Vishakha Channapattan <vishakhavc@google.com>
> Signed-off-by: Bhavesh Jashnani <bjashnani@google.com>
> Signed-off-by: Radha Ramachandran <radha@google.com>
> Signed-off-by: Akshat Jain <akshatzen@google.com>
> Signed-off-by: Yu Zheng <yuuzheng@google.com>
> ---
>  drivers/scsi/pm8001/pm8001_ctl.c  |  45 +++++++++++++
>  drivers/scsi/pm8001/pm8001_init.c |   1 +
>  drivers/scsi/pm8001/pm8001_sas.h  |   4 ++
>  drivers/scsi/pm8001/pm80xx_hwi.c  | 130 ++++++++++++++++++++++++++++++++++++++
>  4 files changed, 180 insertions(+)
>
> diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c
> index 3e59b2a7185a..669c60a8d123 100644
> --- a/drivers/scsi/pm8001/pm8001_ctl.c
> +++ b/drivers/scsi/pm8001/pm8001_ctl.c
> @@ -577,6 +577,49 @@ static ssize_t pm8001_ctl_fatal_log_show(struct device *cdev,
>
>  static DEVICE_ATTR(fatal_log, S_IRUGO, pm8001_ctl_fatal_log_show, NULL);
>
> +/**
> + ** non_fatal_log_show - non fatal error logging
> + ** @cdev:pointer to embedded class device
> + ** @buf: the buffer returned
> + **
> + ** A sysfs 'read-only' shost attribute.
> + **/
> +static ssize_t non_fatal_log_show(struct device *cdev,
> +       struct device_attribute *attr, char *buf)
> +{
> +       u32 count;
> +
> +       count = pm80xx_get_non_fatal_dump(cdev, attr, buf);
> +       return count;
> +}
> +static DEVICE_ATTR_RO(non_fatal_log);
I would suggest to use pm8001_ctl_non_fatal_log_show as function name,
or convert remove
the prefix for other functions, it's annoying to have different naming
convention.
> +
> +static ssize_t non_fatal_count_show(struct device *cdev,
> +               struct device_attribute *attr, char *buf)
> +{
> +       struct Scsi_Host *shost = class_to_shost(cdev);
> +       struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
> +       struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
> +
> +       return snprintf(buf, PAGE_SIZE, "%08x",
> +                       pm8001_ha->non_fatal_count);
> +}
> +
> +static ssize_t non_fatal_count_store(struct device *cdev,
> +               struct device_attribute *attr, const char *buf, size_t count)
> +{
> +       struct Scsi_Host *shost = class_to_shost(cdev);
> +       struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
> +       struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
> +       int val = 0;
> +
> +       if (kstrtoint(buf, 16, &val) != 0)
> +               return -EINVAL;
> +
> +       pm8001_ha->non_fatal_count = val;
> +       return strlen(buf);
> +}
> +static DEVICE_ATTR_RW(non_fatal_count);
>
>  /**
>   ** pm8001_ctl_gsm_log_show - gsm dump collection
> @@ -853,6 +896,8 @@ struct device_attribute *pm8001_host_attrs[] = {
>         &dev_attr_aap_log,
>         &dev_attr_iop_log,
>         &dev_attr_fatal_log,
> +       &dev_attr_non_fatal_log,
> +       &dev_attr_non_fatal_count,
>         &dev_attr_gsm_log,
>         &dev_attr_max_out_io,
>         &dev_attr_max_devices,
> diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c
> index c8414f1b9652..b74282bc1ed0 100644
> --- a/drivers/scsi/pm8001/pm8001_init.c
> +++ b/drivers/scsi/pm8001/pm8001_init.c
> @@ -484,6 +484,7 @@ static struct pm8001_hba_info *pm8001_pci_alloc(struct pci_dev *pdev,
>         pm8001_ha->shost = shost;
>         pm8001_ha->id = pm8001_id++;
>         pm8001_ha->logging_level = logging_level;
> +       pm8001_ha->non_fatal_count = 0;
>         if (link_rate >= 1 && link_rate <= 15)
>                 pm8001_ha->link_rate = (link_rate << 8);
>         else {
> diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
> index f95f4d714983..47607a25f819 100644
> --- a/drivers/scsi/pm8001/pm8001_sas.h
> +++ b/drivers/scsi/pm8001/pm8001_sas.h
> @@ -601,6 +601,8 @@ struct pm8001_hba_info {
>         struct                  sgpio_ioctl_resp sgpio_resp;
>         struct  phy_prof_resp   phy_profile_resp;
>         u32                     reset_in_progress;
> +       u32                     non_fatal_count;
> +       u32                     non_fatal_read_length;
>  };
>
>  struct pm8001_work {
> @@ -790,6 +792,8 @@ void pm8001_set_phy_profile_single(struct pm8001_hba_info *pm8001_ha,
>  int pm80xx_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue);
>  ssize_t pm80xx_get_fatal_dump(struct device *cdev,
>                 struct device_attribute *attr, char *buf);
> +ssize_t pm80xx_get_non_fatal_dump(struct device *cdev,
> +               struct device_attribute *attr, char *buf);
>  ssize_t pm8001_get_gsm_dump(struct device *cdev, u32, char *buf);
>  /* ctl shared API */
>  extern struct device_attribute *pm8001_host_attrs[];
> diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
> index bbcdcff5d25b..4923660304aa 100644
> --- a/drivers/scsi/pm8001/pm80xx_hwi.c
> +++ b/drivers/scsi/pm8001/pm80xx_hwi.c
> @@ -393,6 +393,136 @@ ssize_t pm80xx_get_fatal_dump(struct device *cdev,
>                 (char *)buf;
>  }
>
> +/* pm80xx_get_non_fatal_dump - dump the nonfatal data from the dma
> + * location by the firmware.
> + */
> +ssize_t pm80xx_get_non_fatal_dump(struct device *cdev,
> +       struct device_attribute *attr, char *buf)
> +{
> +       struct Scsi_Host *shost = class_to_shost(cdev);
> +       struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
> +       struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
> +       void __iomem *nonfatal_table_address = pm8001_ha->fatal_tbl_addr;
> +       u32 accum_len = 0;
> +       u32 total_len = 0;
> +       u32 reg_val = 0;
> +       u32 *temp = NULL;
> +       u32 index = 0;
> +       u32 output_length;
> +       unsigned long start = 0;
> +       char *buf_copy = buf;
> +
> +       temp = (u32 *)pm8001_ha->memoryMap.region[FORENSIC_MEM].virt_ptr;
> +       if (++pm8001_ha->non_fatal_count == 1) {
> +               if (pm8001_ha->chip_id == chip_8001) {
> +                       snprintf(pm8001_ha->forensic_info.data_buf.direct_data,
> +                               PAGE_SIZE, "Not supported for SPC controller");
> +                       return 0;
> +               }
> +               PM8001_IO_DBG(pm8001_ha,
> +                       pm8001_printk("forensic_info TYPE_NON_FATAL...\n"));
> +               /*
> +                * Step 1: Write the host buffer parameters in the MPI Fatal and
> +                * Non-Fatal Error Dump Capture Table.This is the buffer
> +                * where debug data will be DMAed to.
> +                */
> +               pm8001_mw32(nonfatal_table_address,
> +               MPI_FATAL_EDUMP_TABLE_LO_OFFSET,
> +               pm8001_ha->memoryMap.region[FORENSIC_MEM].phys_addr_lo);
> +
> +               pm8001_mw32(nonfatal_table_address,
> +               MPI_FATAL_EDUMP_TABLE_HI_OFFSET,
> +               pm8001_ha->memoryMap.region[FORENSIC_MEM].phys_addr_hi);
> +
> +               pm8001_mw32(nonfatal_table_address,
> +               MPI_FATAL_EDUMP_TABLE_LENGTH, SYSFS_OFFSET);
> +
> +               /* Optionally, set the DUMPCTRL bit to 1 if the host
> +                * keeps sending active I/Os while capturing the non-fatal
> +                * debug data. Otherwise, leave this bit set to zero
> +                */
> +               pm8001_mw32(nonfatal_table_address,
> +               MPI_FATAL_EDUMP_TABLE_HANDSHAKE, MPI_FATAL_EDUMP_HANDSHAKE_RDY);
> +
> +               /*
> +                * Step 2: Clear Accumulative Length of Debug Data Transferred
> +                * [ACCDDLEN] field in the MPI Fatal and Non-Fatal Error Dump
> +                * Capture Table to zero.
> +                */
> +               pm8001_mw32(nonfatal_table_address,
> +                               MPI_FATAL_EDUMP_TABLE_ACCUM_LEN, 0);
> +
> +               /* initiallize previous accumulated length to 0 */
> +               pm8001_ha->forensic_preserved_accumulated_transfer = 0;
> +               pm8001_ha->non_fatal_read_length = 0;
> +       }
> +
> +       total_len = pm8001_mr32(nonfatal_table_address,
> +                       MPI_FATAL_EDUMP_TABLE_TOTAL_LEN);
> +       /*
> +        * Step 3:Clear Fatal/Non-Fatal Debug Data Transfer Status [FDDTSTAT]
> +        * field and then request that the SPCv controller transfer the debug
> +        * data by setting bit 7 of the Inbound Doorbell Set Register.
> +        */
> +       pm8001_mw32(nonfatal_table_address, MPI_FATAL_EDUMP_TABLE_STATUS, 0);
> +       pm8001_cw32(pm8001_ha, 0, MSGU_IBDB_SET,
> +                       SPCv_MSGU_CFG_TABLE_NONFATAL_DUMP);
> +
> +       /*
> +        * Step 4.1: Read back the Inbound Doorbell Set Register (by polling for
> +        * 2 seconds) until register bit 7 is cleared.
> +        * This step only indicates the request is accepted by the controller.
> +        */
> +       start = jiffies + (2 * HZ); /* 2 sec */
> +       do {
> +               reg_val = pm8001_cr32(pm8001_ha, 0, MSGU_IBDB_SET) &
> +                       SPCv_MSGU_CFG_TABLE_NONFATAL_DUMP;
> +       } while ((reg_val != 0) && time_before(jiffies, start));
> +
> +       /* Step 4.2: To check the completion of the transfer, poll the Fatal/Non
> +        * Fatal Debug Data Transfer Status [FDDTSTAT] field for 2 seconds in
> +        * the MPI Fatal and Non-Fatal Error Dump Capture Table.
> +        */
> +       start = jiffies + (2 * HZ); /* 2 sec */
> +       do {
> +               reg_val = pm8001_mr32(nonfatal_table_address,
> +                               MPI_FATAL_EDUMP_TABLE_STATUS);
> +       } while ((!reg_val) && time_before(jiffies, start));
> +
> +       if ((reg_val == 0x00) ||
> +               (reg_val == MPI_FATAL_EDUMP_TABLE_STAT_DMA_FAILED) ||
> +               (reg_val > MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_DONE)) {
> +               pm8001_ha->non_fatal_read_length = 0;
> +               buf_copy += snprintf(buf_copy, PAGE_SIZE, "%08x ", 0xFFFFFFFF);
> +               pm8001_ha->non_fatal_count = 0;
> +               return (buf_copy - buf);
> +       } else if (reg_val ==
> +                       MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_MORE_DATA) {
> +               buf_copy += snprintf(buf_copy, PAGE_SIZE, "%08x ", 2);
> +       } else if ((reg_val == MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_DONE) ||
> +               (pm8001_ha->non_fatal_read_length >= total_len)) {
> +               pm8001_ha->non_fatal_read_length = 0;
> +               buf_copy += snprintf(buf_copy, PAGE_SIZE, "%08x ", 4);
> +               pm8001_ha->non_fatal_count = 0;
> +       }
> +       accum_len = pm8001_mr32(nonfatal_table_address,
> +                       MPI_FATAL_EDUMP_TABLE_ACCUM_LEN);
> +       output_length = accum_len -
> +               pm8001_ha->forensic_preserved_accumulated_transfer;
> +
> +       for (index = 0; index < output_length/4; index++)
> +               buf_copy += snprintf(buf_copy, PAGE_SIZE,
> +                               "%08x ", *(temp+index));
> +
> +       pm8001_ha->non_fatal_read_length += output_length;
> +
> +       /* store current accumulated length to use in next iteration as
> +        * the previous accumulated length
> +        */
> +       pm8001_ha->forensic_preserved_accumulated_transfer = accum_len;
> +       return (buf_copy - buf);
> +}
> +
>  /**
>   * read_main_config_table - read the configure table and save it.
>   * @pm8001_ha: our hba card information
> --
> 2.16.3
>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 11/12] pm80xx : Introduce read and write length for IOCTL payload structure.
  2019-12-24  4:41 ` [PATCH 11/12] pm80xx : Introduce read and write length for IOCTL payload structure Deepak Ukey
@ 2020-01-06 16:35   ` Jinpu Wang
  0 siblings, 0 replies; 33+ messages in thread
From: Jinpu Wang @ 2020-01-06 16:35 UTC (permalink / raw)
  To: Deepak Ukey
  Cc: Linux SCSI Mailinglist, Vasanthalakshmi.Tharmarajan, Viswas G,
	Jack Wang, Martin K. Petersen, dpf, yuuzheng, Vikram Auradkar,
	vishakhavc, bjashnani, Radha Ramachandran, akshatzen

On Tue, Dec 24, 2019 at 5:41 AM Deepak Ukey <deepak.ukey@microchip.com> wrote:
>
> From: Viswas G <Viswas.G@microchip.com>
>
> Removed the common length and introduce read and write length for
> IOCTL payload structure.
>
> Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
> Signed-off-by: Viswas G <Viswas.G@microchip.com>
> Signed-off-by: Vishakha Channapattan <vishakhavc@google.com>
> Signed-off-by: Bhavesh Jashnani <bjashnani@google.com>
> Signed-off-by: Radha Ramachandran <radha@google.com>
> Signed-off-by: Akshat Jain <akshatzen@google.com>
> Signed-off-by: Yu Zheng <yuuzheng@google.com>
Looks fine to me.
Acked-by: Jack Wang <jinpu.wang@cloud.ionos.com>
> ---
>  drivers/scsi/pm8001/pm8001_ctl.c  |  6 +++---
>  drivers/scsi/pm8001/pm8001_hwi.c  | 22 +++++++++++-----------
>  drivers/scsi/pm8001/pm8001_init.c | 12 ++++++------
>  drivers/scsi/pm8001/pm8001_sas.h  |  3 ++-
>  4 files changed, 22 insertions(+), 21 deletions(-)
>
> diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c
> index 669c60a8d123..63bd2a384d2e 100644
> --- a/drivers/scsi/pm8001/pm8001_ctl.c
> +++ b/drivers/scsi/pm8001/pm8001_ctl.c
> @@ -486,7 +486,7 @@ static ssize_t pm8001_ctl_bios_version_show(struct device *cdev,
>         pm8001_ha->nvmd_completion = &completion;
>         payload.minor_function = 7;
>         payload.offset = 0;
> -       payload.length = 4096;
> +       payload.rd_length = 4096;
>         payload.func_specific = kzalloc(4096, GFP_KERNEL);
>         if (!payload.func_specific)
>                 return -ENOMEM;
> @@ -697,7 +697,7 @@ static int pm8001_set_nvmd(struct pm8001_hba_info *pm8001_ha)
>         payload = (struct pm8001_ioctl_payload *)ioctlbuffer;
>         memcpy((u8 *)&payload->func_specific, (u8 *)pm8001_ha->fw_image->data,
>                                 pm8001_ha->fw_image->size);
> -       payload->length = pm8001_ha->fw_image->size;
> +       payload->wr_length = pm8001_ha->fw_image->size;
>         payload->id = 0;
>         payload->minor_function = 0x1;
>         pm8001_ha->nvmd_completion = &completion;
> @@ -743,7 +743,7 @@ static int pm8001_update_flash(struct pm8001_hba_info *pm8001_ha)
>                                         IOCTL_BUF_SIZE);
>                 for (loopNumber = 0; loopNumber < loopcount; loopNumber++) {
>                         payload = (struct pm8001_ioctl_payload *)ioctlbuffer;
> -                       payload->length = 1024*16;
> +                       payload->wr_length = 1024*16;
>                         payload->id = 0;
>                         fwControl =
>                               (struct fw_control_info *)&payload->func_specific;
> diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
> index f9395d9fd530..16dc7a92ad68 100644
> --- a/drivers/scsi/pm8001/pm8001_hwi.c
> +++ b/drivers/scsi/pm8001/pm8001_hwi.c
> @@ -4841,7 +4841,7 @@ int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha,
>         if (!fw_control_context)
>                 return -ENOMEM;
>         fw_control_context->usrAddr = (u8 *)ioctl_payload->func_specific;
> -       fw_control_context->len = ioctl_payload->length;
> +       fw_control_context->len = ioctl_payload->rd_length;
>         circularQ = &pm8001_ha->inbnd_q_tbl[0];
>         memset(&nvmd_req, 0, sizeof(nvmd_req));
>         rc = pm8001_tag_alloc(pm8001_ha, &tag);
> @@ -4862,7 +4862,7 @@ int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha,
>
>                 nvmd_req.len_ir_vpdd = cpu_to_le32(IPMode | twi_addr << 16 |
>                         twi_page_size << 8 | TWI_DEVICE);
> -               nvmd_req.resp_len = cpu_to_le32(ioctl_payload->length);
> +               nvmd_req.resp_len = cpu_to_le32(ioctl_payload->rd_length);
>                 nvmd_req.resp_addr_hi =
>                     cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_hi);
>                 nvmd_req.resp_addr_lo =
> @@ -4871,7 +4871,7 @@ int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha,
>         }
>         case C_SEEPROM: {
>                 nvmd_req.len_ir_vpdd = cpu_to_le32(IPMode | C_SEEPROM);
> -               nvmd_req.resp_len = cpu_to_le32(ioctl_payload->length);
> +               nvmd_req.resp_len = cpu_to_le32(ioctl_payload->rd_length);
>                 nvmd_req.resp_addr_hi =
>                     cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_hi);
>                 nvmd_req.resp_addr_lo =
> @@ -4880,7 +4880,7 @@ int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha,
>         }
>         case VPD_FLASH: {
>                 nvmd_req.len_ir_vpdd = cpu_to_le32(IPMode | VPD_FLASH);
> -               nvmd_req.resp_len = cpu_to_le32(ioctl_payload->length);
> +               nvmd_req.resp_len = cpu_to_le32(ioctl_payload->rd_length);
>                 nvmd_req.resp_addr_hi =
>                     cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_hi);
>                 nvmd_req.resp_addr_lo =
> @@ -4889,7 +4889,7 @@ int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha,
>         }
>         case EXPAN_ROM: {
>                 nvmd_req.len_ir_vpdd = cpu_to_le32(IPMode | EXPAN_ROM);
> -               nvmd_req.resp_len = cpu_to_le32(ioctl_payload->length);
> +               nvmd_req.resp_len = cpu_to_le32(ioctl_payload->rd_length);
>                 nvmd_req.resp_addr_hi =
>                     cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_hi);
>                 nvmd_req.resp_addr_lo =
> @@ -4898,7 +4898,7 @@ int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha,
>         }
>         case IOP_RDUMP: {
>                 nvmd_req.len_ir_vpdd = cpu_to_le32(IPMode | IOP_RDUMP);
> -               nvmd_req.resp_len = cpu_to_le32(ioctl_payload->length);
> +               nvmd_req.resp_len = cpu_to_le32(ioctl_payload->rd_length);
>                 nvmd_req.vpd_offset = cpu_to_le32(ioctl_payload->offset);
>                 nvmd_req.resp_addr_hi =
>                 cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_hi);
> @@ -4938,7 +4938,7 @@ int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha,
>         circularQ = &pm8001_ha->inbnd_q_tbl[0];
>         memcpy(pm8001_ha->memoryMap.region[NVMD].virt_ptr,
>                 &ioctl_payload->func_specific,
> -               ioctl_payload->length);
> +               ioctl_payload->wr_length);
>         memset(&nvmd_req, 0, sizeof(nvmd_req));
>         rc = pm8001_tag_alloc(pm8001_ha, &tag);
>         if (rc) {
> @@ -4957,7 +4957,7 @@ int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha,
>                 nvmd_req.reserved[0] = cpu_to_le32(0xFEDCBA98);
>                 nvmd_req.len_ir_vpdd = cpu_to_le32(IPMode | twi_addr << 16 |
>                         twi_page_size << 8 | TWI_DEVICE);
> -               nvmd_req.resp_len = cpu_to_le32(ioctl_payload->length);
> +               nvmd_req.resp_len = cpu_to_le32(ioctl_payload->wr_length);
>                 nvmd_req.resp_addr_hi =
>                     cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_hi);
>                 nvmd_req.resp_addr_lo =
> @@ -4966,7 +4966,7 @@ int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha,
>         }
>         case C_SEEPROM:
>                 nvmd_req.len_ir_vpdd = cpu_to_le32(IPMode | C_SEEPROM);
> -               nvmd_req.resp_len = cpu_to_le32(ioctl_payload->length);
> +               nvmd_req.resp_len = cpu_to_le32(ioctl_payload->wr_length);
>                 nvmd_req.reserved[0] = cpu_to_le32(0xFEDCBA98);
>                 nvmd_req.resp_addr_hi =
>                     cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_hi);
> @@ -4975,7 +4975,7 @@ int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha,
>                 break;
>         case VPD_FLASH:
>                 nvmd_req.len_ir_vpdd = cpu_to_le32(IPMode | VPD_FLASH);
> -               nvmd_req.resp_len = cpu_to_le32(ioctl_payload->length);
> +               nvmd_req.resp_len = cpu_to_le32(ioctl_payload->wr_length);
>                 nvmd_req.reserved[0] = cpu_to_le32(0xFEDCBA98);
>                 nvmd_req.resp_addr_hi =
>                     cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_hi);
> @@ -4984,7 +4984,7 @@ int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha,
>                 break;
>         case EXPAN_ROM:
>                 nvmd_req.len_ir_vpdd = cpu_to_le32(IPMode | EXPAN_ROM);
> -               nvmd_req.resp_len = cpu_to_le32(ioctl_payload->length);
> +               nvmd_req.resp_len = cpu_to_le32(ioctl_payload->wr_length);
>                 nvmd_req.reserved[0] = cpu_to_le32(0xFEDCBA98);
>                 nvmd_req.resp_addr_hi =
>                     cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_hi);
> diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c
> index b74282bc1ed0..6e037638656d 100644
> --- a/drivers/scsi/pm8001/pm8001_init.c
> +++ b/drivers/scsi/pm8001/pm8001_init.c
> @@ -643,22 +643,22 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha)
>         if (pm8001_ha->chip_id == chip_8001) {
>                 if (deviceid == 0x8081 || deviceid == 0x0042) {
>                         payload.minor_function = 4;
> -                       payload.length = 4096;
> +                       payload.rd_length = 4096;
>                 } else {
>                         payload.minor_function = 0;
> -                       payload.length = 128;
> +                       payload.rd_length = 128;
>                 }
>         } else if ((pm8001_ha->chip_id == chip_8070 ||
>                         pm8001_ha->chip_id == chip_8072) &&
>                         pm8001_ha->pdev->subsystem_vendor == PCI_VENDOR_ID_ATTO) {
>                 payload.minor_function = 4;
> -               payload.length = 4096;
> +               payload.rd_length = 4096;
>         } else {
>                 payload.minor_function = 1;
> -               payload.length = 4096;
> +               payload.rd_length = 4096;
>         }
>         payload.offset = 0;
> -       payload.func_specific = kzalloc(payload.length, GFP_KERNEL);
> +       payload.func_specific = kzalloc(payload.rd_length, GFP_KERNEL);
>         if (!payload.func_specific) {
>                 PM8001_INIT_DBG(pm8001_ha, pm8001_printk("mem alloc fail\n"));
>                 return;
> @@ -728,7 +728,7 @@ static int pm8001_get_phy_settings_info(struct pm8001_hba_info *pm8001_ha)
>         /* SAS ADDRESS read from flash / EEPROM */
>         payload.minor_function = 6;
>         payload.offset = 0;
> -       payload.length = 4096;
> +       payload.rd_length = 4096;
>         payload.func_specific = kzalloc(4096, GFP_KERNEL);
>         if (!payload.func_specific)
>                 return -ENOMEM;
> diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
> index 47607a25f819..917a17f4d595 100644
> --- a/drivers/scsi/pm8001/pm8001_sas.h
> +++ b/drivers/scsi/pm8001/pm8001_sas.h
> @@ -164,10 +164,11 @@ struct pm8001_ioctl_payload {
>         u32     signature;
>         u16     major_function;
>         u16     minor_function;
> -       u16     length;
>         u16     status;
>         u16     offset;
>         u16     id;
> +       u32     wr_length;
> +       u32     rd_length;
>         u8      *func_specific;
>  };
>
> --
> 2.16.3
>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 08/12] pm80xx : IOCTL functionality for GPIO.
  2020-01-06 16:25   ` Jinpu Wang
@ 2020-01-06 16:39     ` Jinpu Wang
  0 siblings, 0 replies; 33+ messages in thread
From: Jinpu Wang @ 2020-01-06 16:39 UTC (permalink / raw)
  To: Deepak Ukey
  Cc: Linux SCSI Mailinglist, Vasanthalakshmi.Tharmarajan, Viswas G,
	Jack Wang, Martin K. Petersen, dpf, yuuzheng, Vikram Auradkar,
	vishakhavc, bjashnani, Radha Ramachandran, akshatzen

On Mon, Jan 6, 2020 at 5:25 PM Jinpu Wang <jinpu.wang@cloud.ionos.com> wrote:
>
> On Tue, Dec 24, 2019 at 5:41 AM Deepak Ukey <deepak.ukey@microchip.com> wrote:
> >
> > From: Deepak Ukey <Deepak.Ukey@microchip.com>
> >
> > Added IOCTL functionality for GPIO.
> > The SPCv controller provides 24 GPIO signals. The first 12 signals
> > [11:0] and the last 4 signals [23:20] are for customer use. Eight
> > signals [19:12] are reserved for the SPCv controller firmware.
> > Whenever the host performs GPIO setup or a read/write operation
> > using the GPIO command the host needs to make sure that it does
> > not disturb the GPIO configuration for the bits [19:12].
> > Each signal can be configured either as an input or as an output.
> > When configured as an output, the host can use the GPIO Command to
> > set the desired level. GPIO inputs can also be configured so that
> > the SPCv controller sends the GPIO Event notification when specific
> > GPIO events occur.
> > Different GPIO features implemented:
> > 1) GPIO Pin Setup
> > 2) GPIO Event Setup
> > 3) GPIO Read
> > 4) GPIO Write
> >
>
> I think you can also implement lldd_write_gpio callback, so smp_utils
> can also control gpio, right?
This comment should go to SGPIO, patch09

^ permalink raw reply	[flat|nested] 33+ messages in thread

* RE: [PATCH 06/12] pm80xx : sysfs attribute for number of phys.
  2020-01-02 16:38       ` Viswas.G
@ 2020-01-13  9:26         ` Deepak.Ukey
  2020-01-13  9:39           ` Jinpu Wang
  0 siblings, 1 reply; 33+ messages in thread
From: Deepak.Ukey @ 2020-01-13  9:26 UTC (permalink / raw)
  To: Viswas.G, john.garry, jinpu.wang
  Cc: linux-scsi, Vasanthalakshmi.Tharmarajan, jinpu.wang,
	martin.petersen, dpf, yuuzheng, auradkar, vishakhavc, bjashnani,
	radha, akshatzen

Hi Jinpu,

please use pm8001_ctl_num_phys_show as function name, so it follows 
> same conversion as other functions.
> Better also rename controller_fatal_error too.

If I tried to keep the function name as pm8001_ctl_num_phys_show as other function follows then checkpatch.pl gives the below warning. 

------
WARNING: Consider renaming function(s) 'pm8001_ctl_num_phys_show' to 'num_phys_show'
#37: FILE: drivers/scsi/pm8001/pm8001_ctl.c:108:
+}

total: 0 errors, 1 warnings, 32 lines checked
-------

That’s the only reason  I have changes the function name. For making the other function with same naming convention, I will change the function name of all other function like num_phys_show' and we will submit this patch in  our upcoming patch set.

Regards,
Deepak
  
-----Original Message-----
From: Viswas G - I30667 
Sent: Thursday, January 2, 2020 10:09 PM
To: John Garry <john.garry@huawei.com>; Jinpu Wang <jinpu.wang@cloud.ionos.com>; Deepak Ukey - I31172 <Deepak.Ukey@microchip.com>
Cc: Linux SCSI Mailinglist <linux-scsi@vger.kernel.org>; Vasanthalakshmi Tharmarajan - I30664 <Vasanthalakshmi.Tharmarajan@microchip.com>; Jack Wang <jinpu.wang@profitbricks.com>; Martin K. Petersen <martin.petersen@oracle.com>; dpf@google.com; yuuzheng@google.com; Vikram Auradkar <auradkar@google.com>; vishakhavc@google.com; bjashnani@google.com; Radha Ramachandran <radha@google.com>; akshatzen@google.com
Subject: RE: [PATCH 06/12] pm80xx : sysfs attribute for number of phys.

Thanks John Garry. The intention here is to get the total number of phys for the controller through sysfs and it is used by the management utility as well. 

Regards,
Viswas G

-----Original Message-----
From: John Garry <john.garry@huawei.com>
Sent: Thursday, January 2, 2020 6:03 PM
To: Jinpu Wang <jinpu.wang@cloud.ionos.com>; Deepak Ukey - I31172 <Deepak.Ukey@microchip.com>
Cc: Linux SCSI Mailinglist <linux-scsi@vger.kernel.org>; Vasanthalakshmi Tharmarajan - I30664 <Vasanthalakshmi.Tharmarajan@microchip.com>; Viswas G - I30667 <Viswas.G@microchip.com>; Jack Wang <jinpu.wang@profitbricks.com>; Martin K. Petersen <martin.petersen@oracle.com>; dpf@google.com; yuuzheng@google.com; Vikram Auradkar <auradkar@google.com>; vishakhavc@google.com; bjashnani@google.com; Radha Ramachandran <radha@google.com>; akshatzen@google.com
Subject: Re: [PATCH 06/12] pm80xx : sysfs attribute for number of phys.

EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe

On 02/01/2020 12:07, Jinpu Wang wrote:
> On Tue, Dec 24, 2019 at 5:41 AM Deepak Ukey <mailto:deepak.ukey@microchip.com> wrote:
>>
>> From: Viswas G <mailto:Viswas.G@microchip.com>
>>
>> Added sysfs attribute to show number of phys.
>>
>> Signed-off-by: Deepak Ukey <mailto:deepak.ukey@microchip.com>
>> Signed-off-by: Viswas G <mailto:Viswas.G@microchip.com>
>> Signed-off-by: Vishakha Channapattan <mailto:vishakhavc@google.com>
>> Signed-off-by: Bhavesh Jashnani <mailto:bjashnani@google.com>
>> Signed-off-by: Radha Ramachandran <mailto:radha@google.com>
>> Signed-off-by: Akshat Jain <mailto:akshatzen@google.com>
>> Signed-off-by: Yu Zheng <mailto:yuuzheng@google.com>
>> ---
>>   drivers/scsi/pm8001/pm8001_ctl.c | 20 ++++++++++++++++++++
>>   1 file changed, 20 insertions(+)
>>
>> diff --git a/drivers/scsi/pm8001/pm8001_ctl.c
>> b/drivers/scsi/pm8001/pm8001_ctl.c
>> index 69458b318a20..704c0daa7937 100644
>> --- a/drivers/scsi/pm8001/pm8001_ctl.c
>> +++ b/drivers/scsi/pm8001/pm8001_ctl.c
>> @@ -89,6 +89,25 @@ static ssize_t controller_fatal_error_show(struct device *cdev,
>>   }
>>   static DEVICE_ATTR_RO(controller_fatal_error);
>>
>> +/**
>> + * pm8001_ctl_num_phys_show - Number of phys
>> + * @cdev:pointer to embedded class device
>> + * @buf:the buffer returned
>> + * A sysfs 'read-only' shost attribute.
>> + */
>> +static ssize_t num_phys_show(struct device *cdev,
>> +               struct device_attribute *attr, char *buf)
> please use pm8001_ctl_num_phys_show as function name, so it follows 
> same conversion as other functions.
> Better also rename controller_fatal_error too.

If you don't mind me saying, this info is already available in sysfs for any libsas or even SAS host (using scsi_transport_sas.c), like this:

john@ubuntu:/sys/class/sas_phy$ ls
phy-0:0     phy-0:0:12  phy-0:0:17  phy-0:0:21  phy-0:0:4  phy-0:0:9
phy-0:5
phy-0:0:0   phy-0:0:13  phy-0:0:18  phy-0:0:22  phy-0:0:5  phy-0:1
phy-0:6
phy-0:0:1   phy-0:0:14  phy-0:0:19  phy-0:0:23  phy-0:0:6  phy-0:2
phy-0:7
phy-0:0:10  phy-0:0:15  phy-0:0:2   phy-0:0:24  phy-0:0:7  phy-0:3
phy-0:0:11  phy-0:0:16  phy-0:0:20  phy-0:0:3   phy-0:0:8  phy-0:4


Any phy-X:Y is a root phy, and X denotes the host index and Y is the phy index.

>
> Thanks
>> +{
>> +       int ret;
>> +       struct Scsi_Host *shost = class_to_shost(cdev);
>> +       struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
>> +       struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
>> +
>> +       ret = sprintf(buf, "%d", pm8001_ha->chip->n_phy);
>> +       return ret;
>> +}
>> +static DEVICE_ATTR_RO(num_phys);
>> +
>>   /**
>>    * pm8001_ctl_fw_version_show - firmware version
>>    * @cdev: pointer to embedded class device @@ -825,6 +844,7 @@ 
>> static DEVICE_ATTR(update_fw, S_IRUGO|S_IWUSR|S_IWGRP,
>>   struct device_attribute *pm8001_host_attrs[] = {
>>          &dev_attr_interface_rev,
>>          &dev_attr_controller_fatal_error,
>> +       &dev_attr_num_phys,
>>          &dev_attr_fw_version,
>>          &dev_attr_update_fw,
>>          &dev_attr_aap_log,
>> --
>> 2.16.3
>>
> .
>


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 06/12] pm80xx : sysfs attribute for number of phys.
  2020-01-13  9:26         ` Deepak.Ukey
@ 2020-01-13  9:39           ` Jinpu Wang
  0 siblings, 0 replies; 33+ messages in thread
From: Jinpu Wang @ 2020-01-13  9:39 UTC (permalink / raw)
  To: Deepak Ukey
  Cc: Viswas G, John Garry, Linux SCSI Mailinglist,
	Vasanthalakshmi.Tharmarajan, Jack Wang, Martin K. Petersen, dpf,
	yuuzheng, Vikram Auradkar, vishakhavc, bjashnani,
	Radha Ramachandran, akshatzen

On Mon, Jan 13, 2020 at 10:26 AM <Deepak.Ukey@microchip.com> wrote:
>
> Hi Jinpu,
>
> please use pm8001_ctl_num_phys_show as function name, so it follows
> > same conversion as other functions.
> > Better also rename controller_fatal_error too.
>
> If I tried to keep the function name as pm8001_ctl_num_phys_show as other function follows then checkpatch.pl gives the below warning.
>
> ------
> WARNING: Consider renaming function(s) 'pm8001_ctl_num_phys_show' to 'num_phys_show'
> #37: FILE: drivers/scsi/pm8001/pm8001_ctl.c:108:
> +}
>
> total: 0 errors, 1 warnings, 32 lines checked
> -------
>
> That’s the only reason  I have changes the function name. For making the other function with same naming convention, I will change the function name of all other function like num_phys_show' and we will submit this patch in  our upcoming patch set.
>
> Regards,
> Deepak


Thanks for checking, then we can do it later.
PS: please avoid top-posting.

^ permalink raw reply	[flat|nested] 33+ messages in thread

end of thread, other threads:[~2020-01-13  9:39 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-12-24  4:41 [PATCH 00/12] pm80xx : Updates for the driver version 0.1.39 Deepak Ukey
2019-12-24  4:41 ` [PATCH 01/12] pm80xx : Increase request sg length Deepak Ukey
2019-12-25 15:57   ` kbuild test robot
2019-12-24  4:41 ` [PATCH 02/12] pm80xx : Deal with kexec reboots Deepak Ukey
2020-01-02 11:52   ` Jinpu Wang
2019-12-24  4:41 ` [PATCH 03/12] pm80xx : Free the tag when mpi_set_phy_profile_resp is received Deepak Ukey
2020-01-02 11:55   ` Jinpu Wang
2019-12-24  4:41 ` [PATCH 04/12] pm80xx : Cleanup initialization loading fail path Deepak Ukey
2020-01-02 11:58   ` Jinpu Wang
2019-12-24  4:41 ` [PATCH 05/12] pm80xx : Support for char device Deepak Ukey
2020-01-02 12:03   ` Jinpu Wang
2019-12-24  4:41 ` [PATCH 06/12] pm80xx : sysfs attribute for number of phys Deepak Ukey
2020-01-02 12:07   ` Jinpu Wang
2020-01-02 12:33     ` John Garry
2020-01-02 16:38       ` Viswas.G
2020-01-13  9:26         ` Deepak.Ukey
2020-01-13  9:39           ` Jinpu Wang
2019-12-24  4:41 ` [PATCH 07/12] pm80xx : IOCTL functionality to get phy profile Deepak Ukey
2020-01-02 12:10   ` Jinpu Wang
2020-01-02 16:42     ` Viswas.G
2019-12-24  4:41 ` [PATCH 08/12] pm80xx : IOCTL functionality for GPIO Deepak Ukey
2020-01-06 16:25   ` Jinpu Wang
2020-01-06 16:39     ` Jinpu Wang
2019-12-24  4:41 ` [PATCH 09/12] pm80xx : IOCTL functionality for SGPIO Deepak Ukey
2019-12-30  2:47   ` Nathan Chancellor
2020-01-06 16:30   ` Jinpu Wang
2019-12-24  4:41 ` [PATCH 10/12] pm80xx : sysfs attribute for non fatal dump Deepak Ukey
2020-01-06 16:34   ` Jinpu Wang
2019-12-24  4:41 ` [PATCH 11/12] pm80xx : Introduce read and write length for IOCTL payload structure Deepak Ukey
2020-01-06 16:35   ` Jinpu Wang
2019-12-24  4:41 ` [PATCH 12/12] pm80xx : IOCTL functionality for TWI device Deepak Ukey
2020-01-02 12:20   ` Jinpu Wang
2020-01-02 16:41     ` Viswas.G

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).