All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V2 00/13] pm80xx : Updates for the driver version 0.1.39.
@ 2020-01-17  7:19 Deepak Ukey
  2020-01-17  7:19 ` [PATCH V2 01/13] pm80xx : Increase request sg length Deepak Ukey
                   ` (12 more replies)
  0 siblings, 13 replies; 38+ messages in thread
From: Deepak Ukey @ 2020-01-17  7:19 UTC (permalink / raw)
  To: linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, deepak.ukey, jinpu.wang,
	martin.petersen, 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.

Changes from V1:
	For "Increase request sg length" patch.
		- Fix the compilation warning generated on xtensa architecture.
	For "Support for char device" patch.
		- Modified the description of patch.
	For "IOCTL functionality to get phy profile." patch.
		- Split the patch in two different patches.
		  IOCTL functionality to get phy status and
		  IOCTL functionality to get phy error.
	For "IOCTL functionality for SGPIO" patch.
		- Fixed the compilation warning generated on x86_64 architecture.
	For "sysfs attribute for non fatal dump" patch.
		- Modified the description of patch.
	For "IOCTL functionality for TWI device" patch.
		- Modified the description of patch.

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

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 status.
  pm80xx : IOCTL functionality to get phy error.
  pm80xx : Introduce read and write length for IOCTL payload structure.

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

 drivers/scsi/pm8001/pm8001_ctl.c  | 662 +++++++++++++++++++++++++++++++++++++-
 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  |  70 +++-
 drivers/scsi/pm8001/pm80xx_hwi.c  | 390 +++++++++++++++++++++-
 drivers/scsi/pm8001/pm80xx_hwi.h  |  55 ++++
 10 files changed, 1767 insertions(+), 62 deletions(-)

-- 
2.16.3


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

* [PATCH V2 01/13] pm80xx : Increase request sg length.
  2020-01-17  7:19 [PATCH V2 00/13] pm80xx : Updates for the driver version 0.1.39 Deepak Ukey
@ 2020-01-17  7:19 ` Deepak Ukey
  2020-01-17 14:08   ` Jinpu Wang
  2020-01-17  7:19 ` [PATCH V2 02/13] pm80xx : Deal with kexec reboots Deepak Ukey
                   ` (11 subsequent siblings)
  12 siblings, 1 reply; 38+ messages in thread
From: Deepak Ukey @ 2020-01-17  7:19 UTC (permalink / raw)
  To: linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, deepak.ukey, jinpu.wang,
	martin.petersen, 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: Radha Ramachandran <radha@google.com>
Reported-by: kbuild test robot <lkp@intel.com>
---
 drivers/scsi/pm8001/pm8001_defs.h | 5 +++--
 drivers/scsi/pm8001/pm8001_init.c | 2 +-
 2 files changed, 4 insertions(+), 3 deletions(-)

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] 38+ messages in thread

* [PATCH V2 02/13] pm80xx : Deal with kexec reboots.
  2020-01-17  7:19 [PATCH V2 00/13] pm80xx : Updates for the driver version 0.1.39 Deepak Ukey
  2020-01-17  7:19 ` [PATCH V2 01/13] pm80xx : Increase request sg length Deepak Ukey
@ 2020-01-17  7:19 ` Deepak Ukey
  2020-01-17  7:19 ` [PATCH V2 03/13] pm80xx : Free the tag when mpi_set_phy_profile_resp is received Deepak Ukey
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 38+ messages in thread
From: Deepak Ukey @ 2020-01-17  7:19 UTC (permalink / raw)
  To: linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, deepak.ukey, jinpu.wang,
	martin.petersen, 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: Radha Ramachandran <radha@google.com>
Acked-by: Jack Wang <jinpu.wang@cloud.ionos.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] 38+ messages in thread

* [PATCH V2 03/13] pm80xx : Free the tag when mpi_set_phy_profile_resp is received.
  2020-01-17  7:19 [PATCH V2 00/13] pm80xx : Updates for the driver version 0.1.39 Deepak Ukey
  2020-01-17  7:19 ` [PATCH V2 01/13] pm80xx : Increase request sg length Deepak Ukey
  2020-01-17  7:19 ` [PATCH V2 02/13] pm80xx : Deal with kexec reboots Deepak Ukey
@ 2020-01-17  7:19 ` Deepak Ukey
  2020-01-17  7:19 ` [PATCH V2 04/13] pm80xx : Cleanup initialization loading fail path Deepak Ukey
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 38+ messages in thread
From: Deepak Ukey @ 2020-01-17  7:19 UTC (permalink / raw)
  To: linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, deepak.ukey, jinpu.wang,
	martin.petersen, 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: Radha Ramachandran <radha@google.com>
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 related	[flat|nested] 38+ messages in thread

* [PATCH V2 04/13] pm80xx : Cleanup initialization loading fail path.
  2020-01-17  7:19 [PATCH V2 00/13] pm80xx : Updates for the driver version 0.1.39 Deepak Ukey
                   ` (2 preceding siblings ...)
  2020-01-17  7:19 ` [PATCH V2 03/13] pm80xx : Free the tag when mpi_set_phy_profile_resp is received Deepak Ukey
@ 2020-01-17  7:19 ` Deepak Ukey
  2020-01-17  7:19 ` [PATCH V2 05/13] pm80xx : Support for char device Deepak Ukey
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 38+ messages in thread
From: Deepak Ukey @ 2020-01-17  7:19 UTC (permalink / raw)
  To: linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, deepak.ukey, jinpu.wang,
	martin.petersen, 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: Radha Ramachandran <radha@google.com>
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 related	[flat|nested] 38+ messages in thread

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

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

Added the support to register the char device for pm80xx module so that
management utility fetch the different information from driver with the
help of IOCTL. Also added the IOCTL functionality to get driver info so
that management utility can fetch the information about driver like
driver name, driver major number, driver minor number and build number.

Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
Signed-off-by: Viswas G <Viswas.G@microchip.com>
Signed-off-by: Radha Ramachandran <radha@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] 38+ messages in thread

* [PATCH V2 06/13] pm80xx : sysfs attribute for number of phys.
  2020-01-17  7:19 [PATCH V2 00/13] pm80xx : Updates for the driver version 0.1.39 Deepak Ukey
                   ` (4 preceding siblings ...)
  2020-01-17  7:19 ` [PATCH V2 05/13] pm80xx : Support for char device Deepak Ukey
@ 2020-01-17  7:19 ` Deepak Ukey
  2020-01-17 14:21   ` Jinpu Wang
  2020-01-17  7:19 ` [PATCH V2 07/13] pm80xx : IOCTL functionality to get phy status Deepak Ukey
                   ` (6 subsequent siblings)
  12 siblings, 1 reply; 38+ messages in thread
From: Deepak Ukey @ 2020-01-17  7:19 UTC (permalink / raw)
  To: linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, deepak.ukey, jinpu.wang,
	martin.petersen, 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: Radha Ramachandran <radha@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..8091e78a04b0 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);
 
+/**
+ * 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] 38+ messages in thread

* [PATCH V2 07/13] pm80xx : IOCTL functionality to get phy status.
  2020-01-17  7:19 [PATCH V2 00/13] pm80xx : Updates for the driver version 0.1.39 Deepak Ukey
                   ` (5 preceding siblings ...)
  2020-01-17  7:19 ` [PATCH V2 06/13] pm80xx : sysfs attribute for number of phys Deepak Ukey
@ 2020-01-17  7:19 ` Deepak Ukey
  2020-01-17 14:35   ` Jinpu Wang
  2020-01-17  7:19 ` [PATCH V2 08/13] pm80xx : IOCTL functionality to get phy error Deepak Ukey
                   ` (5 subsequent siblings)
  12 siblings, 1 reply; 38+ messages in thread
From: Deepak Ukey @ 2020-01-17  7:19 UTC (permalink / raw)
  To: linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, deepak.ukey, jinpu.wang,
	martin.petersen, yuuzheng, auradkar, vishakhavc, bjashnani,
	radha, akshatzen

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

Added the IOCTL functionality for phy status so that management
utility can get the information like phy id, phy status, port id
and port status from driver using get phy profile command.

Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
Signed-off-by: Viswas G <Viswas.G@microchip.com>
Signed-off-by: Radha Ramachandran <radha@google.com>
---
 drivers/scsi/pm8001/pm8001_ctl.c | 90 ++++++++++++++++++++++++++++++++++++++++
 drivers/scsi/pm8001/pm8001_ctl.h | 23 +++++++++-
 drivers/scsi/pm8001/pm8001_sas.h |  7 ++++
 drivers/scsi/pm8001/pm80xx_hwi.c | 68 ++++++++++++++++++++++++++++++
 drivers/scsi/pm8001/pm80xx_hwi.h |  1 +
 5 files changed, 188 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c
index 8091e78a04b0..eb64566b2274 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,91 @@ 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;
+}
+
 /**
  *	pm8001_ioctl - pm8001 configuration request
  *	@inode: inode of device
@@ -962,6 +1049,9 @@ 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;
 	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..226fab82845f 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,26 @@ 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_prof_resp {
+	union {
+		struct phy_profile status;
+	} 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_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..87d676810a18 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,10 @@ 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	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..0a36c5d5e2c2 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -3688,9 +3688,48 @@ 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 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_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 +4922,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 +5050,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..230877caeed4 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.h
+++ b/drivers/scsi/pm8001/pm80xx_hwi.h
@@ -176,6 +176,7 @@
 
 /* phy_profile */
 #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] 38+ messages in thread

* [PATCH V2 08/13] pm80xx : IOCTL functionality to get phy error.
  2020-01-17  7:19 [PATCH V2 00/13] pm80xx : Updates for the driver version 0.1.39 Deepak Ukey
                   ` (6 preceding siblings ...)
  2020-01-17  7:19 ` [PATCH V2 07/13] pm80xx : IOCTL functionality to get phy status Deepak Ukey
@ 2020-01-17  7:19 ` Deepak Ukey
  2020-01-17  7:19 ` [PATCH V2 09/13] pm80xx : IOCTL functionality for GPIO Deepak Ukey
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 38+ messages in thread
From: Deepak Ukey @ 2020-01-17  7:19 UTC (permalink / raw)
  To: linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, deepak.ukey, jinpu.wang,
	martin.petersen, yuuzheng, auradkar, vishakhavc, bjashnani,
	radha, akshatzen

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

Added the IOCTL functionality for phy error so that management utility
can get the information like Invalid dword count, Disparity error count,
Loss of sync dword count, phy reset count from driver using get phy
profile command.

Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
Signed-off-by: Viswas G <Viswas.G@microchip.com>
Signed-off-by: Radha Ramachandran <radha@google.com>
---
 drivers/scsi/pm8001/pm8001_ctl.c | 54 ++++++++++++++++++++++++++++++++++++++++
 drivers/scsi/pm8001/pm8001_ctl.h | 12 +++++++++
 drivers/scsi/pm8001/pm80xx_hwi.c | 14 +++++++++++
 drivers/scsi/pm8001/pm80xx_hwi.h |  1 +
 4 files changed, 81 insertions(+)

diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c
index eb64566b2274..7f45e114a31a 100644
--- a/drivers/scsi/pm8001/pm8001_ctl.c
+++ b/drivers/scsi/pm8001/pm8001_ctl.c
@@ -1026,6 +1026,57 @@ static int pm8001_ioctl_get_phy_profile(struct pm8001_hba_info *pm8001_ha,
 	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
@@ -1052,6 +1103,9 @@ static long pm8001_ioctl(struct file *file,
 	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 226fab82845f..686ad69f0e0c 100644
--- a/drivers/scsi/pm8001/pm8001_ctl.h
+++ b/drivers/scsi/pm8001/pm8001_ctl.h
@@ -102,15 +102,27 @@ struct phy_profile {
 	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/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index 0a36c5d5e2c2..e8af262976d6 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -3690,6 +3690,7 @@ static int mpi_get_phy_profile_resp(struct pm8001_hba_info *pm8001_ha,
 {
 	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);
@@ -3725,6 +3726,19 @@ static int mpi_get_phy_profile_resp(struct pm8001_hba_info *pm8001_ha,
 			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);
+		} 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);
 		}
 		complete(pm8001_ha->ioctl_completion);
 	}
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.h b/drivers/scsi/pm8001/pm80xx_hwi.h
index 230877caeed4..b5119c5479da 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.h
+++ b/drivers/scsi/pm8001/pm80xx_hwi.h
@@ -175,6 +175,7 @@
 #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
-- 
2.16.3


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

* [PATCH V2 09/13] pm80xx : IOCTL functionality for GPIO.
  2020-01-17  7:19 [PATCH V2 00/13] pm80xx : Updates for the driver version 0.1.39 Deepak Ukey
                   ` (7 preceding siblings ...)
  2020-01-17  7:19 ` [PATCH V2 08/13] pm80xx : IOCTL functionality to get phy error Deepak Ukey
@ 2020-01-17  7:19 ` Deepak Ukey
  2020-01-17  7:19 ` [PATCH V2 10/13] pm80xx : IOCTL functionality for SGPIO Deepak Ukey
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 38+ messages in thread
From: Deepak Ukey @ 2020-01-17  7:19 UTC (permalink / raw)
  To: linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, deepak.ukey, jinpu.wang,
	martin.petersen, 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: Radha Ramachandran <radha@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 7f45e114a31a..cadb5be394b6 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)
 {
@@ -1100,6 +1168,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;
@@ -1122,11 +1193,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 87d676810a18..7d9920376fb7 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 e8af262976d6..2cdcb1c64970 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] 38+ messages in thread

* [PATCH V2 10/13] pm80xx : IOCTL functionality for SGPIO.
  2020-01-17  7:19 [PATCH V2 00/13] pm80xx : Updates for the driver version 0.1.39 Deepak Ukey
                   ` (8 preceding siblings ...)
  2020-01-17  7:19 ` [PATCH V2 09/13] pm80xx : IOCTL functionality for GPIO Deepak Ukey
@ 2020-01-17  7:19 ` Deepak Ukey
  2020-01-22  8:59   ` Jinpu Wang
  2020-01-17  7:19 ` [PATCH V2 11/13] pm80xx : sysfs attribute for non fatal dump Deepak Ukey
                   ` (2 subsequent siblings)
  12 siblings, 1 reply; 38+ messages in thread
From: Deepak Ukey @ 2020-01-17  7:19 UTC (permalink / raw)
  To: linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, deepak.ukey, jinpu.wang,
	martin.petersen, yuuzheng, auradkar, vishakhavc, bjashnani,
	radha, akshatzen

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

Added the IOCTL functionality for SGPIO through which management
utility can controls SGPIO LEDs on the enclosure of locally attached
drives only. It is used to read from/write into SGPIO registers and
sets one or more SGPIO registers.

Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
Signed-off-by: Viswas G <Viswas.G@microchip.com>
Signed-off-by: Radha Ramachandran <radha@google.com>
Reported-by: kbuild test robot <lkp@intel.com>
---
 drivers/scsi/pm8001/pm8001_ctl.c  |  71 ++++++++++++++++
 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, 400 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c
index cadb5be394b6..d557b423edf6 100644
--- a/drivers/scsi/pm8001/pm8001_ctl.c
+++ b/drivers/scsi/pm8001/pm8001_ctl.c
@@ -1009,6 +1009,74 @@ 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 = wait_for_completion_timeout(&completion,
+			msecs_to_jiffies(2000));
+	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)
 {
@@ -1171,6 +1239,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 7d9920376fb7..4c6c7d86f75e 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);
 };
@@ -583,6 +596,7 @@ struct pm8001_hba_info {
 	spinlock_t		ioctl_lock;
 	struct mutex		ioctl_mutex;
 	struct completion	*ioctl_completion;
+	struct			sgpio_ioctl_resp sgpio_resp;
 	struct	phy_prof_resp	phy_profile_resp;
 	u32			reset_in_progress;
 };
@@ -696,6 +710,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,
@@ -731,6 +747,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,
@@ -752,6 +770,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);
@@ -759,6 +778,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 2cdcb1c64970..e4746fd9c09f 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] 38+ messages in thread

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

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

Added the sysfs attribute for non fatal log so that management utility
can get the non fatal dump from driver. The non-fatal error is an error
condition or abnormal behavior detected by the host, or detected and
reported by the controller to the host.The non-fatal error does not stop
the controller firmware and enables it to still respond to host requests.
A typical example of a non-fatal error is an I/O timeout or an unusual
error notification from the controller. Since the firmware is operational,
the error dump information is pushed to host memory (by firmware) upon
request from the host.

Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
Signed-off-by: Viswas G <Viswas.G@microchip.com>
Signed-off-by: Radha Ramachandran <radha@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 d557b423edf6..9fce19024945 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 4c6c7d86f75e..ae5f880dd9bb 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -599,6 +599,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 {
@@ -788,6 +790,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 e4746fd9c09f..a4e265292d17 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] 38+ messages in thread

* [PATCH V2 12/13] pm80xx : Introduce read and write length for IOCTL payload structure.
  2020-01-17  7:19 [PATCH V2 00/13] pm80xx : Updates for the driver version 0.1.39 Deepak Ukey
                   ` (10 preceding siblings ...)
  2020-01-17  7:19 ` [PATCH V2 11/13] pm80xx : sysfs attribute for non fatal dump Deepak Ukey
@ 2020-01-17  7:19 ` Deepak Ukey
  2020-01-17  7:19 ` [PATCH V2 13/13] pm80xx : IOCTL functionality for TWI device Deepak Ukey
  12 siblings, 0 replies; 38+ messages in thread
From: Deepak Ukey @ 2020-01-17  7:19 UTC (permalink / raw)
  To: linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, deepak.ukey, jinpu.wang,
	martin.petersen, 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: Radha Ramachandran <radha@google.com>
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 9fce19024945..887a15ee69f6 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 ae5f880dd9bb..13d7813b8d74 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] 38+ messages in thread

* [PATCH V2 13/13] pm80xx : IOCTL functionality for TWI device.
  2020-01-17  7:19 [PATCH V2 00/13] pm80xx : Updates for the driver version 0.1.39 Deepak Ukey
                   ` (11 preceding siblings ...)
  2020-01-17  7:19 ` [PATCH V2 12/13] pm80xx : Introduce read and write length for IOCTL payload structure Deepak Ukey
@ 2020-01-17  7:19 ` Deepak Ukey
  12 siblings, 0 replies; 38+ messages in thread
From: Deepak Ukey @ 2020-01-17  7:19 UTC (permalink / raw)
  To: linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, deepak.ukey, jinpu.wang,
	martin.petersen, yuuzheng, auradkar, vishakhavc, bjashnani,
	radha, akshatzen

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

Added the IOCTL functionality for TWI device so that management
utility can manage the TWI device attached to the controller's
TWI. The TWI device includes (but not limited to) the SEEPROM
device. When NVME field set to 0000b (TWI devices), this command
also allows the host to specify:
a. TWI device address
b. TWI Bus number
c. TWI device page size (1, 8, 16 or 32 bytes)
d. TWI device address size (1 or 2 bytes)
Also added the module parameter for TWI device address and page
size in order to add support for different TWI devices.

Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
Signed-off-by: Viswas G <Viswas.G@microchip.com>
Signed-off-by: Radha Ramachandran <radha@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 887a15ee69f6..ce9d1ee5e995 100644
--- a/drivers/scsi/pm8001/pm8001_ctl.c
+++ b/drivers/scsi/pm8001/pm8001_ctl.c
@@ -1122,6 +1122,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)
 {
@@ -1274,6 +1394,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;
 
@@ -1293,6 +1414,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 13d7813b8d74..9074c3a14120 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;
@@ -648,6 +653,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.
  */
@@ -794,6 +804,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 a4e265292d17..767914688b8a 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] 38+ messages in thread

* Re: [PATCH V2 01/13] pm80xx : Increase request sg length.
  2020-01-17  7:19 ` [PATCH V2 01/13] pm80xx : Increase request sg length Deepak Ukey
@ 2020-01-17 14:08   ` Jinpu Wang
  2020-01-17 15:50     ` Deepak.Ukey
  0 siblings, 1 reply; 38+ messages in thread
From: Jinpu Wang @ 2020-01-17 14:08 UTC (permalink / raw)
  To: Deepak Ukey
  Cc: Linux SCSI Mailinglist, Vasanthalakshmi.Tharmarajan, Viswas G,
	Jack Wang, Martin K. Petersen, yuuzheng, Vikram Auradkar,
	vishakhavc, bjashnani, Radha Ramachandran, akshatzen

On Fri, Jan 17, 2020 at 8:10 AM Deepak Ukey <deepak.ukey@microchip.com> wrote:
>
> 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: Radha Ramachandran <radha@google.com>
> Reported-by: kbuild test robot <lkp@intel.com>
> ---
>  drivers/scsi/pm8001/pm8001_defs.h | 5 +++--
>  drivers/scsi/pm8001/pm8001_init.c | 2 +-
>  2 files changed, 4 insertions(+), 3 deletions(-)
>
> 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 */
Hi Deepack,

Why do you reduce PM8001_MAX_CCB?

The patch itself looks fine.

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

* Re: [PATCH V2 05/13] pm80xx : Support for char device.
  2020-01-17  7:19 ` [PATCH V2 05/13] pm80xx : Support for char device Deepak Ukey
@ 2020-01-17 14:15   ` Jinpu Wang
  2020-01-21  0:24     ` Martin K. Petersen
  0 siblings, 1 reply; 38+ messages in thread
From: Jinpu Wang @ 2020-01-17 14:15 UTC (permalink / raw)
  To: Deepak Ukey, Martin K. Petersen, James E.J. Bottomley
  Cc: Linux SCSI Mailinglist, Vasanthalakshmi.Tharmarajan, Viswas G,
	Jack Wang, yuuzheng, Vikram Auradkar, vishakhavc, bjashnani,
	Radha Ramachandran, akshatzen

On Fri, Jan 17, 2020 at 8:10 AM Deepak Ukey <deepak.ukey@microchip.com> wrote:
>
> From: Deepak Ukey <Deepak.Ukey@microchip.com>
>
> Added the support to register the char device for pm80xx module so that
> management utility fetch the different information from driver with the
> help of IOCTL. Also added the IOCTL functionality to get driver info so
> that management utility can fetch the information about driver like
> driver name, driver major number, driver minor number and build number.
>
> Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
> Signed-off-by: Viswas G <Viswas.G@microchip.com>
> Signed-off-by: Radha Ramachandran <radha@google.com>

Thanks for the commit message, looks much better. In the past, people
are against IOCTL, suggesting netlink,
have you considered that?

Martin, James, what do you think?

Regards,
Jack

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

* Re: [PATCH V2 06/13] pm80xx : sysfs attribute for number of phys.
  2020-01-17  7:19 ` [PATCH V2 06/13] pm80xx : sysfs attribute for number of phys Deepak Ukey
@ 2020-01-17 14:21   ` Jinpu Wang
  2020-01-20  4:50     ` Deepak.Ukey
  0 siblings, 1 reply; 38+ messages in thread
From: Jinpu Wang @ 2020-01-17 14:21 UTC (permalink / raw)
  To: Deepak Ukey
  Cc: Linux SCSI Mailinglist, Vasanthalakshmi.Tharmarajan, Viswas G,
	Jack Wang, Martin K. Petersen, yuuzheng, Vikram Auradkar,
	vishakhavc, bjashnani, Radha Ramachandran, akshatzen

On Fri, Jan 17, 2020 at 8:10 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: Radha Ramachandran <radha@google.com>
I agree with John Gary, the mgmt tool can get the info from
/sys/class/sas_phy, no need to add an extra sysfs.

I suggest dropping the patch.

Thanks!

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

* Re: [PATCH V2 11/13] pm80xx : sysfs attribute for non fatal dump.
  2020-01-17  7:19 ` [PATCH V2 11/13] pm80xx : sysfs attribute for non fatal dump Deepak Ukey
@ 2020-01-17 14:26   ` Jinpu Wang
  0 siblings, 0 replies; 38+ messages in thread
From: Jinpu Wang @ 2020-01-17 14:26 UTC (permalink / raw)
  To: Deepak Ukey
  Cc: Linux SCSI Mailinglist, Vasanthalakshmi.Tharmarajan, Viswas G,
	Jack Wang, Martin K. Petersen, yuuzheng, Vikram Auradkar,
	vishakhavc, bjashnani, Radha Ramachandran, akshatzen

On Fri, Jan 17, 2020 at 8:10 AM Deepak Ukey <deepak.ukey@microchip.com> wrote:
>
> From: Deepak Ukey <Deepak.Ukey@microchip.com>
>
> Added the sysfs attribute for non fatal log so that management utility
> can get the non fatal dump from driver. The non-fatal error is an error
> condition or abnormal behavior detected by the host, or detected and
> reported by the controller to the host.The non-fatal error does not stop
> the controller firmware and enables it to still respond to host requests.
> A typical example of a non-fatal error is an I/O timeout or an unusual
> error notification from the controller. Since the firmware is operational,
> the error dump information is pushed to host memory (by firmware) upon
> request from the host.
>
> Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
> Signed-off-by: Viswas G <Viswas.G@microchip.com>
> Signed-off-by: Radha Ramachandran <radha@google.com>
Acked-by: Jack Wang <jinpu.wang@cloud.ionos.com>

Thanks

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

* Re: [PATCH V2 07/13] pm80xx : IOCTL functionality to get phy status.
  2020-01-17  7:19 ` [PATCH V2 07/13] pm80xx : IOCTL functionality to get phy status Deepak Ukey
@ 2020-01-17 14:35   ` Jinpu Wang
  0 siblings, 0 replies; 38+ messages in thread
From: Jinpu Wang @ 2020-01-17 14:35 UTC (permalink / raw)
  To: Deepak Ukey
  Cc: Linux SCSI Mailinglist, Vasanthalakshmi.Tharmarajan, Viswas G,
	Jack Wang, Martin K. Petersen, yuuzheng, Vikram Auradkar,
	vishakhavc, bjashnani, Radha Ramachandran, akshatzen

>  struct pm8001_chip_info {
> @@ -560,6 +563,10 @@ 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;
did you ever initial both lock? why do you need both? I failed to find them.
> +       struct completion       *ioctl_completion;
> +       struct  phy_prof_resp   phy_profile_resp;
>         u32                     reset_in_progress;
>  };

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

* RE: [PATCH V2 01/13] pm80xx : Increase request sg length.
  2020-01-17 14:08   ` Jinpu Wang
@ 2020-01-17 15:50     ` Deepak.Ukey
  2020-01-17 15:53       ` Jinpu Wang
  0 siblings, 1 reply; 38+ messages in thread
From: Deepak.Ukey @ 2020-01-17 15:50 UTC (permalink / raw)
  To: jinpu.wang
  Cc: linux-scsi, Vasanthalakshmi.Tharmarajan, Viswas.G, jinpu.wang,
	martin.petersen, yuuzheng, auradkar, vishakhavc, bjashnani,
	radha, akshatzen

On Fri, Jan 17, 2020 at 8:10 AM Deepak Ukey <deepak.ukey@microchip.com> wrote:
>
> 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: Radha Ramachandran <radha@google.com>
> Reported-by: kbuild test robot <lkp@intel.com>
> ---
>  drivers/scsi/pm8001/pm8001_defs.h | 5 +++--  
> drivers/scsi/pm8001/pm8001_init.c | 2 +-
>  2 files changed, 4 insertions(+), 3 deletions(-)
>
> 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 */
Hi Deepack,

Why do you reduce PM8001_MAX_CCB?
--- PM8001 driver has a memory limit in the machine. If we increase the sg length, we need to trade-off it by decreasing PM8001_MAX_CCB. PM8001_MAX_CCB = 256 does not have any influence on normal use.

The patch itself looks fine.

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

* Re: [PATCH V2 01/13] pm80xx : Increase request sg length.
  2020-01-17 15:50     ` Deepak.Ukey
@ 2020-01-17 15:53       ` Jinpu Wang
  2020-01-20  4:20         ` Deepak.Ukey
  0 siblings, 1 reply; 38+ messages in thread
From: Jinpu Wang @ 2020-01-17 15:53 UTC (permalink / raw)
  To: Deepak Ukey
  Cc: Linux SCSI Mailinglist, Vasanthalakshmi.Tharmarajan, Viswas G,
	Jack Wang, Martin K. Petersen, yuuzheng, Vikram Auradkar,
	vishakhavc, bjashnani, Radha Ramachandran, akshatzen

On Fri, Jan 17, 2020 at 4:50 PM <Deepak.Ukey@microchip.com> wrote:
>
> On Fri, Jan 17, 2020 at 8:10 AM Deepak Ukey <deepak.ukey@microchip.com> wrote:
> >
> > 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: Radha Ramachandran <radha@google.com>
> > Reported-by: kbuild test robot <lkp@intel.com>
> > ---
> >  drivers/scsi/pm8001/pm8001_defs.h | 5 +++--
> > drivers/scsi/pm8001/pm8001_init.c | 2 +-
> >  2 files changed, 4 insertions(+), 3 deletions(-)
> >
> > 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 */
> Hi Deepack,
>
> Why do you reduce PM8001_MAX_CCB?
> --- PM8001 driver has a memory limit in the machine.
which limit, do you see allocation failure from kernel?
Thanks

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

* RE: [PATCH V2 01/13] pm80xx : Increase request sg length.
  2020-01-17 15:53       ` Jinpu Wang
@ 2020-01-20  4:20         ` Deepak.Ukey
  2020-01-20  8:47           ` Jinpu Wang
  0 siblings, 1 reply; 38+ messages in thread
From: Deepak.Ukey @ 2020-01-20  4:20 UTC (permalink / raw)
  To: jinpu.wang
  Cc: linux-scsi, Vasanthalakshmi.Tharmarajan, Viswas.G, jinpu.wang,
	martin.petersen, yuuzheng, auradkar, vishakhavc, bjashnani,
	radha, akshatzen


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

On Fri, Jan 17, 2020 at 4:50 PM <Deepak.Ukey@microchip.com> wrote:
>
> On Fri, Jan 17, 2020 at 8:10 AM Deepak Ukey <deepak.ukey@microchip.com> wrote:
> >
> > 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: Radha Ramachandran <radha@google.com>
> > Reported-by: kbuild test robot <lkp@intel.com>
> > ---
> >  drivers/scsi/pm8001/pm8001_defs.h | 5 +++-- 
> > drivers/scsi/pm8001/pm8001_init.c | 2 +-
> >  2 files changed, 4 insertions(+), 3 deletions(-)
> >
> > 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 */
> Hi Deepack,
>
> Why do you reduce PM8001_MAX_CCB?
> --- PM8001 driver has a memory limit in the machine.
which limit, do you see allocation failure from kernel?
-- I think it depends on machine's capability. For our machines, PM8001_MAX_CCB = 512 caused kernel installation failure. I saw it when I was debugging ncq feature
Thanks

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

* RE: [PATCH V2 06/13] pm80xx : sysfs attribute for number of phys.
  2020-01-17 14:21   ` Jinpu Wang
@ 2020-01-20  4:50     ` Deepak.Ukey
  2020-01-21  7:55       ` Jinpu Wang
  0 siblings, 1 reply; 38+ messages in thread
From: Deepak.Ukey @ 2020-01-20  4:50 UTC (permalink / raw)
  To: jinpu.wang
  Cc: linux-scsi, Vasanthalakshmi.Tharmarajan, Viswas.G, jinpu.wang,
	martin.petersen, yuuzheng, auradkar, vishakhavc, bjashnani,
	radha, akshatzen


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

On Fri, Jan 17, 2020 at 8:10 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: Radha Ramachandran <radha@google.com>
I agree with John Gary, the mgmt tool can get the info from /sys/class/sas_phy, no need to add an extra sysfs.

I suggest dropping the patch.
> We have HBA application already in use by customer which uses this sysfs entry. So is it fine to keep this patch?
Thanks!

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

* Re: [PATCH V2 01/13] pm80xx : Increase request sg length.
  2020-01-20  4:20         ` Deepak.Ukey
@ 2020-01-20  8:47           ` Jinpu Wang
  2020-01-29  9:02             ` Deepak.Ukey
  0 siblings, 1 reply; 38+ messages in thread
From: Jinpu Wang @ 2020-01-20  8:47 UTC (permalink / raw)
  To: Deepak Ukey
  Cc: Linux SCSI Mailinglist, Vasanthalakshmi.Tharmarajan, Viswas G,
	Jack Wang, Martin K. Petersen, yuuzheng, Vikram Auradkar,
	vishakhavc, bjashnani, Radha Ramachandran, akshatzen

On Mon, Jan 20, 2020 at 5:20 AM <Deepak.Ukey@microchip.com> wrote:
>
>
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>
> On Fri, Jan 17, 2020 at 4:50 PM <Deepak.Ukey@microchip.com> wrote:
> >
> > On Fri, Jan 17, 2020 at 8:10 AM Deepak Ukey <deepak.ukey@microchip.com> wrote:
> > >
> > > 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: Radha Ramachandran <radha@google.com>
> > > Reported-by: kbuild test robot <lkp@intel.com>
> > > ---
> > >  drivers/scsi/pm8001/pm8001_defs.h | 5 +++--
> > > drivers/scsi/pm8001/pm8001_init.c | 2 +-
> > >  2 files changed, 4 insertions(+), 3 deletions(-)
> > >
> > > 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 */
> > Hi Deepack,
> >
> > Why do you reduce PM8001_MAX_CCB?
> > --- PM8001 driver has a memory limit in the machine.
> which limit, do you see allocation failure from kernel?
> -- I think it depends on machine's capability. For our machines, PM8001_MAX_CCB = 512 caused kernel installation failure. I saw it when I was debugging ncq feature
> Thanks
Ok, would be helpful to put this info to commit message.

Thanks

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

* Re: [PATCH V2 05/13] pm80xx : Support for char device.
  2020-01-17 14:15   ` Jinpu Wang
@ 2020-01-21  0:24     ` Martin K. Petersen
  2020-01-21  5:33       ` Deepak.Ukey
  0 siblings, 1 reply; 38+ messages in thread
From: Martin K. Petersen @ 2020-01-21  0:24 UTC (permalink / raw)
  To: Jinpu Wang
  Cc: Deepak Ukey, Martin K. Petersen, James E.J. Bottomley,
	Linux SCSI Mailinglist, Vasanthalakshmi.Tharmarajan, Viswas G,
	Jack Wang, yuuzheng, Vikram Auradkar, vishakhavc, bjashnani,
	Radha Ramachandran, akshatzen


Jinpu,

> Thanks for the commit message, looks much better. In the past, people
> are against IOCTL, suggesting netlink, have you considered that?

Not so keen on adding more ioctls. It's 2020 and all...

Given the nature of the exported information, what's wrong with putting
it in sysfs?

-- 
Martin K. Petersen	Oracle Linux Engineering

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

* RE: [PATCH V2 05/13] pm80xx : Support for char device.
  2020-01-21  0:24     ` Martin K. Petersen
@ 2020-01-21  5:33       ` Deepak.Ukey
  2020-01-21 12:39         ` John Garry
  0 siblings, 1 reply; 38+ messages in thread
From: Deepak.Ukey @ 2020-01-21  5:33 UTC (permalink / raw)
  To: martin.petersen, jinpu.wang
  Cc: jejb, linux-scsi, Vasanthalakshmi.Tharmarajan, Viswas.G,
	jinpu.wang, yuuzheng, auradkar, vishakhavc, bjashnani, radha,
	akshatzen


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

Martin,

> Thanks for the commit message, looks much better. In the past, people 
> are against IOCTL, suggesting netlink, have you considered that?

Not so keen on adding more ioctls. It's 2020 and all...

Given the nature of the exported information, what's wrong with putting it in sysfs?
-- We have some upcoming patches which uses this IOCTL interface and that cannot be supported through sysfs.
Below are the patches in this patchset which requires IOCTL interface.
0007-pm80xx-IOCTL-functionality-to-get-phy-status
0008-pm80xx-IOCTL-functionality-to-get-phy-error
0009-pm80xx-IOCTL-functionality-for-GPIO
0010-pm80xx-IOCTL-functionality-for-SGPIO
0013-pm80xx-IOCTL-functionality-for-TWI-device

Regards,
Deepak

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

* Re: [PATCH V2 06/13] pm80xx : sysfs attribute for number of phys.
  2020-01-20  4:50     ` Deepak.Ukey
@ 2020-01-21  7:55       ` Jinpu Wang
  0 siblings, 0 replies; 38+ messages in thread
From: Jinpu Wang @ 2020-01-21  7:55 UTC (permalink / raw)
  To: Deepak Ukey
  Cc: Linux SCSI Mailinglist, Vasanthalakshmi.Tharmarajan, Viswas G,
	Jack Wang, Martin K. Petersen, yuuzheng, Vikram Auradkar,
	vishakhavc, bjashnani, Radha Ramachandran, akshatzen

On Mon, Jan 20, 2020 at 5:50 AM <Deepak.Ukey@microchip.com> wrote:
>
>
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>
> On Fri, Jan 17, 2020 at 8:10 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: Radha Ramachandran <radha@google.com>
> I agree with John Gary, the mgmt tool can get the info from /sys/class/sas_phy, no need to add an extra sysfs.
>
> I suggest dropping the patch.
> > We have HBA application already in use by customer which uses this sysfs entry. So is it fine to keep this patch?
> Thanks!

How much effort to convert the HBA application to use general sas_phy
information? IMHO converting HBA application to use general interface
is the right way to go.

Thanks

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

* Re: [PATCH V2 05/13] pm80xx : Support for char device.
  2020-01-21  5:33       ` Deepak.Ukey
@ 2020-01-21 12:39         ` John Garry
  2020-01-22  8:50           ` Deepak.Ukey
  0 siblings, 1 reply; 38+ messages in thread
From: John Garry @ 2020-01-21 12:39 UTC (permalink / raw)
  To: Deepak.Ukey, martin.petersen, jinpu.wang
  Cc: jejb, linux-scsi, Vasanthalakshmi.Tharmarajan, Viswas.G,
	jinpu.wang, yuuzheng, auradkar, vishakhavc, bjashnani, radha,
	akshatzen

On 21/01/2020 05:33, Deepak.Ukey@microchip.com wrote:
> 
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> Martin,
> 
>> Thanks for the commit message, looks much better. In the past, people
>> are against IOCTL, suggesting netlink, have you considered that?
> 
> Not so keen on adding more ioctls. It's 2020 and all...
> 
> Given the nature of the exported information, what's wrong with putting it in sysfs?
> -- We have some upcoming patches which uses this IOCTL interface and that cannot be supported through sysfs.
> Below are the patches in this patchset which requires IOCTL interface.
> 0007-pm80xx-IOCTL-functionality-to-get-phy-status
> 0008-pm80xx-IOCTL-functionality-to-get-phy-error

Please note that there definitely seems to be replication of what sysfs 
already provides in some of these patches:

- 0007-pm80xx-IOCTL-functionality-to-get-phy-status gets things like
Programmed Link Rate, Negotiated Link Rate, PHY Identifier

- 0008-pm80xx-IOCTL-functionality-to-get-phy-error provides other things 
like Invalid Dword Error Count, Disparity Error Count

See ***:

root@ubuntu:/sys/class/sas_phy/phy-0:0# ls -l
total 0
lrwxrwxrwx 1 root root    0 Jan 21 12:05 device -> ../../../phy-0:0
-r--r--r-- 1 root root 4096 Jan 21 12:05 device_type
-rw-r--r-- 1 root root 4096 Jan 21 12:05 enable ***
--w------- 1 root root 4096 Jan 21 12:05 hard_reset
-r--r--r-- 1 root root 4096 Jan 21 12:05 initiator_port_protocols
-r--r--r-- 1 root root 4096 Jan 21 12:05 invalid_dword_count ***
--w------- 1 root root 4096 Jan 21 12:05 link_reset
-r--r--r-- 1 root root 4096 Jan 21 12:05 loss_of_dword_sync_count ***
-rw-r--r-- 1 root root 4096 Jan 21 12:05 maximum_linkrate ***
-r--r--r-- 1 root root 4096 Jan 21 12:05 maximum_linkrate_hw ***
-rw-r--r-- 1 root root 4096 Jan 21 12:05 minimum_linkrate ***
-r--r--r-- 1 root root 4096 Jan 21 12:05 minimum_linkrate_hw ***
-r--r--r-- 1 root root 4096 Jan 21 12:05 negotiated_linkrate ***
-r--r--r-- 1 root root 4096 Jan 21 11:58 phy_identifier ***
-r--r--r-- 1 root root 4096 Jan 21 12:05 phy_reset_problem_count ***
drwxr-xr-x 2 root root    0 Jan 21 12:05 power
-r--r--r-- 1 root root 4096 Jan 21 12:05 running_disparity_error_count ***
-r--r--r-- 1 root root 4096 Jan 21 12:05 sas_address
lrwxrwxrwx 1 root root    0 Jan 21 11:45 subsystem -> 
../../../../../../../class/sas_phy
-r--r--r-- 1 root root 4096 Jan 21 12:05 target_port_protocols
-rw-r--r-- 1 root root 4096 Jan 21 11:45 uevent

Maybe the other stuff provided in the patches are useful, I don't know. 
But debugfs seems better for that.

 > 0009-pm80xx-IOCTL-functionality-for-GPIO
 > 0010-pm80xx-IOCTL-functionality-for-SGPIO

I don't know why an ioctl is required here.

 > 0013-pm80xx-IOCTL-functionality-for-TWI-device

Thanks,
John

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

* RE: [PATCH V2 05/13] pm80xx : Support for char device.
  2020-01-21 12:39         ` John Garry
@ 2020-01-22  8:50           ` Deepak.Ukey
  2020-01-22 12:38             ` John Garry
  0 siblings, 1 reply; 38+ messages in thread
From: Deepak.Ukey @ 2020-01-22  8:50 UTC (permalink / raw)
  To: john.garry, martin.petersen, jinpu.wang
  Cc: jejb, linux-scsi, Vasanthalakshmi.Tharmarajan, Viswas.G,
	jinpu.wang, yuuzheng, auradkar, vishakhavc, bjashnani, radha,
	akshatzen


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

On 21/01/2020 05:33, Deepak.Ukey@microchip.com wrote:
>
> EXTERNAL EMAIL: Do not click links or open attachments unless you know 
> the content is safe
>
> Martin,
>
>> Thanks for the commit message, looks much better. In the past, people 
>> are against IOCTL, suggesting netlink, have you considered that?
>
> Not so keen on adding more ioctls. It's 2020 and all...
>
> Given the nature of the exported information, what's wrong with putting it in sysfs?
> -- We have some upcoming patches which uses this IOCTL interface and that cannot be supported through sysfs.
> Below are the patches in this patchset which requires IOCTL interface.
> 0007-pm80xx-IOCTL-functionality-to-get-phy-status
> 0008-pm80xx-IOCTL-functionality-to-get-phy-error

Please note that there definitely seems to be replication of what sysfs already provides in some of these patches:

- 0007-pm80xx-IOCTL-functionality-to-get-phy-status gets things like Programmed Link Rate, Negotiated Link Rate, PHY Identifier

- 0008-pm80xx-IOCTL-functionality-to-get-phy-error provides other things like Invalid Dword Error Count, Disparity Error Count

See ***:

root@ubuntu:/sys/class/sas_phy/phy-0:0# ls -l total 0
lrwxrwxrwx 1 root root    0 Jan 21 12:05 device -> ../../../phy-0:0
-r--r--r-- 1 root root 4096 Jan 21 12:05 device_type
-rw-r--r-- 1 root root 4096 Jan 21 12:05 enable ***
--w------- 1 root root 4096 Jan 21 12:05 hard_reset
-r--r--r-- 1 root root 4096 Jan 21 12:05 initiator_port_protocols
-r--r--r-- 1 root root 4096 Jan 21 12:05 invalid_dword_count ***
--w------- 1 root root 4096 Jan 21 12:05 link_reset
-r--r--r-- 1 root root 4096 Jan 21 12:05 loss_of_dword_sync_count ***
-rw-r--r-- 1 root root 4096 Jan 21 12:05 maximum_linkrate ***
-r--r--r-- 1 root root 4096 Jan 21 12:05 maximum_linkrate_hw ***
-rw-r--r-- 1 root root 4096 Jan 21 12:05 minimum_linkrate ***
-r--r--r-- 1 root root 4096 Jan 21 12:05 minimum_linkrate_hw ***
-r--r--r-- 1 root root 4096 Jan 21 12:05 negotiated_linkrate ***
-r--r--r-- 1 root root 4096 Jan 21 11:58 phy_identifier ***
-r--r--r-- 1 root root 4096 Jan 21 12:05 phy_reset_problem_count ***
drwxr-xr-x 2 root root    0 Jan 21 12:05 power
-r--r--r-- 1 root root 4096 Jan 21 12:05 running_disparity_error_count ***
-r--r--r-- 1 root root 4096 Jan 21 12:05 sas_address
lrwxrwxrwx 1 root root    0 Jan 21 11:45 subsystem ->
../../../../../../../class/sas_phy
-r--r--r-- 1 root root 4096 Jan 21 12:05 target_port_protocols
-rw-r--r-- 1 root root 4096 Jan 21 11:45 uevent

Maybe the other stuff provided in the patches are useful, I don't know.
But debugfs seems better for that.

	- 0006-pm80xx-sysfs-attribute-for-number-of-phys
	- 0007-pm80xx-IOCTL-functionality-to-get-phy-status gets things like Programmed Link Rate, Negotiated Link Rate, PHY Identifier
	- 0008-pm80xx-IOCTL-functionality-to-get-phy-error provides other things like Invalid Dword Error Count, Disparity Error Count
	- Thanks for addressing it. We can get this info from /sys/class/sas_phy and /sys/class/sas_port so we will drop these above mentioned three patches from the next 		- patch series.

 > 0009-pm80xx-IOCTL-functionality-for-GPIO
 > 0010-pm80xx-IOCTL-functionality-for-SGPIO

I don't know why an ioctl is required here.

 > 0013-pm80xx-IOCTL-functionality-for-TWI-device

	- 0009-pm80xx-IOCTL-functionality-for-GPIO
	- 0010-pm80xx-IOCTL-functionality-for-SGPIO
	- 0013-pm80xx-IOCTL-functionality-for-TWI-device
	- For the above patches management utility passes command specific information to driver through IOCTL structure, which used by driver to frame the command and 	- send to FW.  We are using the IOCTL interface for the same. Please let us know your thought.

Regards,
Deepak

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

* Re: [PATCH V2 10/13] pm80xx : IOCTL functionality for SGPIO.
  2020-01-17  7:19 ` [PATCH V2 10/13] pm80xx : IOCTL functionality for SGPIO Deepak Ukey
@ 2020-01-22  8:59   ` Jinpu Wang
  0 siblings, 0 replies; 38+ messages in thread
From: Jinpu Wang @ 2020-01-22  8:59 UTC (permalink / raw)
  To: Deepak Ukey
  Cc: Linux SCSI Mailinglist, Vasanthalakshmi.Tharmarajan, Viswas G,
	Jack Wang, Martin K. Petersen, yuuzheng, Vikram Auradkar,
	vishakhavc, bjashnani, Radha Ramachandran, akshatzen

On Fri, Jan 17, 2020 at 8:10 AM Deepak Ukey <deepak.ukey@microchip.com> wrote:
>
> From: Deepak Ukey <Deepak.Ukey@microchip.com>
>
> Added the IOCTL functionality for SGPIO through which management
> utility can controls SGPIO LEDs on the enclosure of locally attached
> drives only. It is used to read from/write into SGPIO registers and
> sets one or more SGPIO registers.
Hi,
Thanks for addressing my comments.
another question:
Is it enough to only hook lldd_write_gpio without IOCTL to control SGPIO LED?

Thanks

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

* Re: [PATCH V2 05/13] pm80xx : Support for char device.
  2020-01-22  8:50           ` Deepak.Ukey
@ 2020-01-22 12:38             ` John Garry
  2020-01-28  9:43               ` Deepak.Ukey
  0 siblings, 1 reply; 38+ messages in thread
From: John Garry @ 2020-01-22 12:38 UTC (permalink / raw)
  To: Deepak.Ukey, martin.petersen, jinpu.wang
  Cc: jejb, linux-scsi, Vasanthalakshmi.Tharmarajan, Viswas.G,
	jinpu.wang, yuuzheng, auradkar, vishakhavc, bjashnani, radha,
	akshatzen

On 22/01/2020 08:50, Deepak.Ukey@microchip.com wrote:
> -r--r--r-- 1 root root 4096 Jan 21 12:05 running_disparity_error_count ***
> -r--r--r-- 1 root root 4096 Jan 21 12:05 sas_address
> lrwxrwxrwx 1 root root    0 Jan 21 11:45 subsystem ->
> ../../../../../../../class/sas_phy
> -r--r--r-- 1 root root 4096 Jan 21 12:05 target_port_protocols
> -rw-r--r-- 1 root root 4096 Jan 21 11:45 uevent
> 
> Maybe the other stuff provided in the patches are useful, I don't know.
> But debugfs seems better for that.
> 
> 	- 0006-pm80xx-sysfs-attribute-for-number-of-phys
> 	- 0007-pm80xx-IOCTL-functionality-to-get-phy-status gets things like Programmed Link Rate, Negotiated Link Rate, PHY Identifier
> 	- 0008-pm80xx-IOCTL-functionality-to-get-phy-error provides other things like Invalid Dword Error Count, Disparity Error Count
> 	- Thanks for addressing it. We can get this info from /sys/class/sas_phy and /sys/class/sas_port so we will drop these above mentioned three patches from the next 		- patch series.
> 
>   > 0009-pm80xx-IOCTL-functionality-for-GPIO
>   > 0010-pm80xx-IOCTL-functionality-for-SGPIO
> 
> I don't know why an ioctl is required here.
> 
>   > 0013-pm80xx-IOCTL-functionality-for-TWI-device
> 
> 	- 0009-pm80xx-IOCTL-functionality-for-GPIO
> 	- 0010-pm80xx-IOCTL-functionality-for-SGPIO
> 	- 0013-pm80xx-IOCTL-functionality-for-TWI-device
> 	- For the above patches management utility passes command specific information to driver through IOCTL structure, which used by driver to frame the command and 	- send to FW.  We are using the IOCTL interface for the same. Please let us know your thought.

So I specifically questioned the SGPIO patch and why it would have an 
IOCTL, as this function is supported in kernel libsas/SAS transport code 
as an SMP function.

For the GPIO IOCTL, could you use register a gpio driver to provide a 
gpiolib sysfs?

As for TWI, it seems to be for serial EEPROM, so you could ask these 
experts about how to handle it properly in the kernel for standard sysfs 
interfaces:

:~/linux$ ./scripts/get_maintainer.pl -f drivers/misc/eeprom/eeprom.c
Jean Delvare <jdelvare@suse.com> (maintainer:LEGACY EEPROM DRIVER)
Arnd Bergmann <arnd@arndb.de> (supporter:CHAR and MISC DRIVERS)
Greg Kroah-Hartman <gregkh@linuxfoundation.org> (supporter:CHAR and MISC 
DRIVERS)

Thanks,
John

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

* RE: [PATCH V2 05/13] pm80xx : Support for char device.
  2020-01-22 12:38             ` John Garry
@ 2020-01-28  9:43               ` Deepak.Ukey
  2020-03-11 17:08                 ` Jinpu Wang
  0 siblings, 1 reply; 38+ messages in thread
From: Deepak.Ukey @ 2020-01-28  9:43 UTC (permalink / raw)
  To: john.garry, martin.petersen, jinpu.wang
  Cc: jejb, linux-scsi, Vasanthalakshmi.Tharmarajan, Viswas.G,
	jinpu.wang, yuuzheng, auradkar, vishakhavc, bjashnani, radha,
	akshatzen


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

On 22/01/2020 08:50, Deepak.Ukey@microchip.com wrote:
> -r--r--r-- 1 root root 4096 Jan 21 12:05 running_disparity_error_count 
> ***
> -r--r--r-- 1 root root 4096 Jan 21 12:05 sas_address
> lrwxrwxrwx 1 root root    0 Jan 21 11:45 subsystem ->
> ../../../../../../../class/sas_phy
> -r--r--r-- 1 root root 4096 Jan 21 12:05 target_port_protocols
> -rw-r--r-- 1 root root 4096 Jan 21 11:45 uevent
>
> Maybe the other stuff provided in the patches are useful, I don't know.
> But debugfs seems better for that.
>
>       - 0006-pm80xx-sysfs-attribute-for-number-of-phys
>       - 0007-pm80xx-IOCTL-functionality-to-get-phy-status gets things like Programmed Link Rate, Negotiated Link Rate, PHY Identifier
>       - 0008-pm80xx-IOCTL-functionality-to-get-phy-error provides other things like Invalid Dword Error Count, Disparity Error Count
>       - Thanks for addressing it. We can get this info from /sys/class/sas_phy and /sys/class/sas_port so we will drop these above mentioned three patches from the next              - patch series.
>
>   > 0009-pm80xx-IOCTL-functionality-for-GPIO
>   > 0010-pm80xx-IOCTL-functionality-for-SGPIO
>
> I don't know why an ioctl is required here.
>
>   > 0013-pm80xx-IOCTL-functionality-for-TWI-device
>
>       - 0009-pm80xx-IOCTL-functionality-for-GPIO
>       - 0010-pm80xx-IOCTL-functionality-for-SGPIO
>       - 0013-pm80xx-IOCTL-functionality-for-TWI-device
>       - For the above patches management utility passes command specific information to driver through IOCTL structure, which used by driver to frame the command and         - send to FW.  We are using the IOCTL interface for the same. Please let us know your thought.

So I specifically questioned the SGPIO patch and why it would have an IOCTL, as this function is supported in kernel libsas/SAS transport code as an SMP function.
>  Thank you for your suggestions. We will make use of function supported in libsas.

For the GPIO IOCTL, could you use register a gpio driver to provide a gpiolib sysfs?
> We cannot use GPIO driver to provide gpiolib sysfs. There are 24 GPIO signals pin provided by the SPCV controller out of which 16 signals pin are used by customer.  The host application perform different operations on that pins for example pin setup, event setup and read/write GPIO pins.
> For this, applications passes different combination of values to execute the specific operation with help of a payload structure and application passes that structure to driver using IOCTL.
> Driver fetch the information like input enable pin setup, typepart1/typepart2 pin setup, gpio event level setup, gpio rising / falling edge setup, gpio pin mask setup  passed by application and then send with specific command format to execute the gpio operation.

As for TWI, it seems to be for serial EEPROM, so you could ask these experts about how to handle it properly in the kernel for standard sysfs
interfaces:
> Driver supports different TWI devices not limited to the Serial EEPROM. Application passes the address of the attached TWI device to read and write the TWI binary along with the payload structure which contains information like offset, address mode, read/write size.
> Drivers fetch the information passed by application and then send with specific command format to execute operation.

:~/linux$ ./scripts/get_maintainer.pl -f drivers/misc/eeprom/eeprom.c Jean Delvare <jdelvare@suse.com> (maintainer:LEGACY EEPROM DRIVER) Arnd Bergmann <arnd@arndb.de> (supporter:CHAR and MISC DRIVERS) Greg Kroah-Hartman <gregkh@linuxfoundation.org> (supporter:CHAR and MISC
DRIVERS)

Thanks,
Deepak

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

* RE: [PATCH V2 01/13] pm80xx : Increase request sg length.
  2020-01-20  8:47           ` Jinpu Wang
@ 2020-01-29  9:02             ` Deepak.Ukey
  0 siblings, 0 replies; 38+ messages in thread
From: Deepak.Ukey @ 2020-01-29  9:02 UTC (permalink / raw)
  To: jinpu.wang
  Cc: linux-scsi, Vasanthalakshmi.Tharmarajan, Viswas.G, jinpu.wang,
	martin.petersen, yuuzheng, auradkar, vishakhavc, bjashnani,
	radha, akshatzen


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

On Mon, Jan 20, 2020 at 5:20 AM <Deepak.Ukey@microchip.com> wrote:
>
>
> EXTERNAL EMAIL: Do not click links or open attachments unless you know 
> the content is safe
>
> On Fri, Jan 17, 2020 at 4:50 PM <Deepak.Ukey@microchip.com> wrote:
> >
> > On Fri, Jan 17, 2020 at 8:10 AM Deepak Ukey <deepak.ukey@microchip.com> wrote:
> > >
> > > 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: Radha Ramachandran <radha@google.com>
> > > Reported-by: kbuild test robot <lkp@intel.com>
> > > ---
> > >  drivers/scsi/pm8001/pm8001_defs.h | 5 +++-- 
> > > drivers/scsi/pm8001/pm8001_init.c | 2 +-
> > >  2 files changed, 4 insertions(+), 3 deletions(-)
> > >
> > > 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 */
> > Hi Deepack,
> >
> > Why do you reduce PM8001_MAX_CCB?
> > --- PM8001 driver has a memory limit in the machine.
> which limit, do you see allocation failure from kernel?
> -- I think it depends on machine's capability. For our machines, 
> PM8001_MAX_CCB = 512 caused kernel installation failure. I saw it when 
> I was debugging ncq feature Thanks
Ok, would be helpful to put this info to commit message.
> Thanks. I will add this in version 3 of the patchest.

Thanks

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

* Re: [PATCH V2 05/13] pm80xx : Support for char device.
  2020-01-28  9:43               ` Deepak.Ukey
@ 2020-03-11 17:08                 ` Jinpu Wang
  2020-03-11 22:13                   ` Douglas Gilbert
  0 siblings, 1 reply; 38+ messages in thread
From: Jinpu Wang @ 2020-03-11 17:08 UTC (permalink / raw)
  To: Deepak Ukey
  Cc: John Garry, Martin K. Petersen, James E.J. Bottomley,
	Linux SCSI Mailinglist, Vasanthalakshmi.Tharmarajan, Viswas G,
	Jack Wang, yuuzheng, Vikram Auradkar, vishakhavc, bjashnani,
	Radha Ramachandran, akshatzen

On Tue, Jan 28, 2020 at 10:43 AM <Deepak.Ukey@microchip.com> wrote:
>
>
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>
> On 22/01/2020 08:50, Deepak.Ukey@microchip.com wrote:
> > -r--r--r-- 1 root root 4096 Jan 21 12:05 running_disparity_error_count
> > ***
> > -r--r--r-- 1 root root 4096 Jan 21 12:05 sas_address
> > lrwxrwxrwx 1 root root    0 Jan 21 11:45 subsystem ->
> > ../../../../../../../class/sas_phy
> > -r--r--r-- 1 root root 4096 Jan 21 12:05 target_port_protocols
> > -rw-r--r-- 1 root root 4096 Jan 21 11:45 uevent
> >
> > Maybe the other stuff provided in the patches are useful, I don't know.
> > But debugfs seems better for that.
> >
> >       - 0006-pm80xx-sysfs-attribute-for-number-of-phys
> >       - 0007-pm80xx-IOCTL-functionality-to-get-phy-status gets things like Programmed Link Rate, Negotiated Link Rate, PHY Identifier
> >       - 0008-pm80xx-IOCTL-functionality-to-get-phy-error provides other things like Invalid Dword Error Count, Disparity Error Count
> >       - Thanks for addressing it. We can get this info from /sys/class/sas_phy and /sys/class/sas_port so we will drop these above mentioned three patches from the next              - patch series.
> >

> >
> >       - 0009-pm80xx-IOCTL-functionality-for-GPIO
> >       - 0013-pm80xx-IOCTL-functionality-for-TWI-device
> >       - For the above patches management utility passes command specific information to driver through IOCTL structure, which used by driver to frame the command and         - send to FW.  We are using the IOCTL interface for the same. Please let us know your thought.
>
> So I specifically questioned the SGPIO patch and why it would have an IOCTL, as this function is supported in kernel libsas/SAS transport code as an SMP function.
> >  Thank you for your suggestions. We will make use of function supported in libsas.

So basically you only need IOCTL for GPIO and TWI devices, others can
implement via libsas interface or from sysfs directly.

I would like to suggest you do send out other changes without the
IOCTL parts first, and consider again Is it really needed by the user
to control GPIO and TWI, and if there is other way to do it?

Sorry, I don't have a better suggestion!

Regards,
Jack Wang

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

* Re: [PATCH V2 05/13] pm80xx : Support for char device.
  2020-03-11 17:08                 ` Jinpu Wang
@ 2020-03-11 22:13                   ` Douglas Gilbert
  2020-03-12  8:49                     ` Jinpu Wang
  0 siblings, 1 reply; 38+ messages in thread
From: Douglas Gilbert @ 2020-03-11 22:13 UTC (permalink / raw)
  To: Jinpu Wang, Deepak Ukey
  Cc: John Garry, Martin K. Petersen, James E.J. Bottomley,
	Linux SCSI Mailinglist, Vasanthalakshmi.Tharmarajan, Viswas G,
	Jack Wang, yuuzheng, Vikram Auradkar, vishakhavc, bjashnani,
	Radha Ramachandran, akshatzen

On 2020-03-11 1:08 p.m., Jinpu Wang wrote:
> On Tue, Jan 28, 2020 at 10:43 AM <Deepak.Ukey@microchip.com> wrote:
>>
>>
>> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>>
>> On 22/01/2020 08:50, Deepak.Ukey@microchip.com wrote:
>>> -r--r--r-- 1 root root 4096 Jan 21 12:05 running_disparity_error_count
>>> ***
>>> -r--r--r-- 1 root root 4096 Jan 21 12:05 sas_address
>>> lrwxrwxrwx 1 root root    0 Jan 21 11:45 subsystem ->
>>> ../../../../../../../class/sas_phy
>>> -r--r--r-- 1 root root 4096 Jan 21 12:05 target_port_protocols
>>> -rw-r--r-- 1 root root 4096 Jan 21 11:45 uevent
>>>
>>> Maybe the other stuff provided in the patches are useful, I don't know.
>>> But debugfs seems better for that.
>>>
>>>        - 0006-pm80xx-sysfs-attribute-for-number-of-phys
>>>        - 0007-pm80xx-IOCTL-functionality-to-get-phy-status gets things like Programmed Link Rate, Negotiated Link Rate, PHY Identifier
>>>        - 0008-pm80xx-IOCTL-functionality-to-get-phy-error provides other things like Invalid Dword Error Count, Disparity Error Count
>>>        - Thanks for addressing it. We can get this info from /sys/class/sas_phy and /sys/class/sas_port so we will drop these above mentioned three patches from the next              - patch series.
>>>
> 
>>>
>>>        - 0009-pm80xx-IOCTL-functionality-for-GPIO
>>>        - 0013-pm80xx-IOCTL-functionality-for-TWI-device
>>>        - For the above patches management utility passes command specific information to driver through IOCTL structure, which used by driver to frame the command and         - send to FW.  We are using the IOCTL interface for the same. Please let us know your thought.
>>
>> So I specifically questioned the SGPIO patch and why it would have an IOCTL, as this function is supported in kernel libsas/SAS transport code as an SMP function.
>>>   Thank you for your suggestions. We will make use of function supported in libsas.
> 
> So basically you only need IOCTL for GPIO and TWI devices, others can
> implement via libsas interface or from sysfs directly.
> 
> I would like to suggest you do send out other changes without the
> IOCTL parts first, and consider again Is it really needed by the user
> to control GPIO and TWI, and if there is other way to do it?
> 
> Sorry, I don't have a better suggestion!

LSI SAS HBAs (LSI now owned by Broadcom) implement an internal ** SMP
target. It can be seen here:

# ls /dev/bsg
3:0:0:0  3:0:3:0  8:0:0:0  8:0:0:3	     end_device-3:1    expander-3:0
3:0:1:0  4:0:0:0  8:0:0:1  8:0:0:4	     end_device-3:1:0  expander-3:1
3:0:2:0  7:0:0:0  8:0:0:2  end_device-3:0:1  end_device-3:2    sas_host3

It is the last device node: "sas_host3". How do I know it is a SMP target?
Because this works:

# smp_read_gpio /dev/bsg/sas_host3
Read GPIO register response:
   GPIO_CFG[0]:
     version: 0
     GPIO enable: 1
     cfg register count: 2
     gp register count: 1
     supported drive count: 16

When you work out what LSI are doing with this, perhaps you could write
an article about it and make it publicly available.
It is always a good idea to see how your competitors solve problems :-)

Doug Gilbert


** I call it "internal" because it is not seen when doing a SMP DISCOVER
    on a SAS expander to which that SAS HBA is connected.

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

* Re: [PATCH V2 05/13] pm80xx : Support for char device.
  2020-03-11 22:13                   ` Douglas Gilbert
@ 2020-03-12  8:49                     ` Jinpu Wang
  2020-03-12 10:58                       ` John Garry
  0 siblings, 1 reply; 38+ messages in thread
From: Jinpu Wang @ 2020-03-12  8:49 UTC (permalink / raw)
  To: Doug Gilbert, Deepak Ukey
  Cc: John Garry, Martin K. Petersen, James E.J. Bottomley,
	Linux SCSI Mailinglist, Vasanthalakshmi.Tharmarajan, Viswas G,
	Jack Wang, yuuzheng, Vikram Auradkar, vishakhavc, bjashnani,
	Radha Ramachandran, akshatzen

On Wed, Mar 11, 2020 at 11:13 PM Douglas Gilbert <dgilbert@interlog.com> wrote:
>
> On 2020-03-11 1:08 p.m., Jinpu Wang wrote:
> > On Tue, Jan 28, 2020 at 10:43 AM <Deepak.Ukey@microchip.com> wrote:
> >>
> >>
> >> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> >>
> >> On 22/01/2020 08:50, Deepak.Ukey@microchip.com wrote:
> >>> -r--r--r-- 1 root root 4096 Jan 21 12:05 running_disparity_error_count
> >>> ***
> >>> -r--r--r-- 1 root root 4096 Jan 21 12:05 sas_address
> >>> lrwxrwxrwx 1 root root    0 Jan 21 11:45 subsystem ->
> >>> ../../../../../../../class/sas_phy
> >>> -r--r--r-- 1 root root 4096 Jan 21 12:05 target_port_protocols
> >>> -rw-r--r-- 1 root root 4096 Jan 21 11:45 uevent
> >>>
> >>> Maybe the other stuff provided in the patches are useful, I don't know.
> >>> But debugfs seems better for that.
> >>>
> >>>        - 0006-pm80xx-sysfs-attribute-for-number-of-phys
> >>>        - 0007-pm80xx-IOCTL-functionality-to-get-phy-status gets things like Programmed Link Rate, Negotiated Link Rate, PHY Identifier
> >>>        - 0008-pm80xx-IOCTL-functionality-to-get-phy-error provides other things like Invalid Dword Error Count, Disparity Error Count
> >>>        - Thanks for addressing it. We can get this info from /sys/class/sas_phy and /sys/class/sas_port so we will drop these above mentioned three patches from the next              - patch series.
> >>>
> >
> >>>
> >>>        - 0009-pm80xx-IOCTL-functionality-for-GPIO
> >>>        - 0013-pm80xx-IOCTL-functionality-for-TWI-device
> >>>        - For the above patches management utility passes command specific information to driver through IOCTL structure, which used by driver to frame the command and         - send to FW.  We are using the IOCTL interface for the same. Please let us know your thought.
> >>
> >> So I specifically questioned the SGPIO patch and why it would have an IOCTL, as this function is supported in kernel libsas/SAS transport code as an SMP function.
> >>>   Thank you for your suggestions. We will make use of function supported in libsas.
> >
> > So basically you only need IOCTL for GPIO and TWI devices, others can
> > implement via libsas interface or from sysfs directly.
> >
> > I would like to suggest you do send out other changes without the
> > IOCTL parts first, and consider again Is it really needed by the user
> > to control GPIO and TWI, and if there is other way to do it?
> >
> > Sorry, I don't have a better suggestion!
>
> LSI SAS HBAs (LSI now owned by Broadcom) implement an internal ** SMP
> target. It can be seen here:
>
> # ls /dev/bsg
> 3:0:0:0  3:0:3:0  8:0:0:0  8:0:0:3           end_device-3:1    expander-3:0
> 3:0:1:0  4:0:0:0  8:0:0:1  8:0:0:4           end_device-3:1:0  expander-3:1
> 3:0:2:0  7:0:0:0  8:0:0:2  end_device-3:0:1  end_device-3:2    sas_host3
>
> It is the last device node: "sas_host3". How do I know it is a SMP target?
> Because this works:
>
> # smp_read_gpio /dev/bsg/sas_host3
> Read GPIO register response:
>    GPIO_CFG[0]:
>      version: 0
>      GPIO enable: 1
>      cfg register count: 2
>      gp register count: 1
>      supported drive count: 16
>
> When you work out what LSI are doing with this, perhaps you could write
> an article about it and make it publicly available.
> It is always a good idea to see how your competitors solve problems :-)
This sounds indeed a better solution, thanks for the info, Doug

@Deepak Ukey can you check if you guys can also do it this way?

Regards,
Jack Wang

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

* Re: [PATCH V2 05/13] pm80xx : Support for char device.
  2020-03-12  8:49                     ` Jinpu Wang
@ 2020-03-12 10:58                       ` John Garry
  2020-03-16  6:22                         ` Deepak.Ukey
  0 siblings, 1 reply; 38+ messages in thread
From: John Garry @ 2020-03-12 10:58 UTC (permalink / raw)
  To: Jinpu Wang, Doug Gilbert, Deepak Ukey
  Cc: Martin K. Petersen, James E.J. Bottomley, Linux SCSI Mailinglist,
	Vasanthalakshmi.Tharmarajan, Viswas G, Jack Wang, yuuzheng,
	Vikram Auradkar, vishakhavc, bjashnani, Radha Ramachandran,
	akshatzen

On 12/03/2020 08:49, Jinpu Wang wrote:
> On Wed, Mar 11, 2020 at 11:13 PM Douglas Gilbert <dgilbert@interlog.com> wrote:
>>
>> On 2020-03-11 1:08 p.m., Jinpu Wang wrote:
>>> On Tue, Jan 28, 2020 at 10:43 AM <Deepak.Ukey@microchip.com> wrote:
>>>>
>>>>
>>>> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>>>>
>>>> On 22/01/2020 08:50, Deepak.Ukey@microchip.com wrote:
>>>>> -r--r--r-- 1 root root 4096 Jan 21 12:05 running_disparity_error_count
>>>>> ***
>>>>> -r--r--r-- 1 root root 4096 Jan 21 12:05 sas_address
>>>>> lrwxrwxrwx 1 root root    0 Jan 21 11:45 subsystem ->
>>>>> ../../../../../../../class/sas_phy
>>>>> -r--r--r-- 1 root root 4096 Jan 21 12:05 target_port_protocols
>>>>> -rw-r--r-- 1 root root 4096 Jan 21 11:45 uevent
>>>>>
>>>>> Maybe the other stuff provided in the patches are useful, I don't know.
>>>>> But debugfs seems better for that.
>>>>>
>>>>>         - 0006-pm80xx-sysfs-attribute-for-number-of-phys
>>>>>         - 0007-pm80xx-IOCTL-functionality-to-get-phy-status gets things like Programmed Link Rate, Negotiated Link Rate, PHY Identifier
>>>>>         - 0008-pm80xx-IOCTL-functionality-to-get-phy-error provides other things like Invalid Dword Error Count, Disparity Error Count
>>>>>         - Thanks for addressing it. We can get this info from /sys/class/sas_phy and /sys/class/sas_port so we will drop these above mentioned three patches from the next              - patch series.
>>>>>
>>>
>>>>>
>>>>>         - 0009-pm80xx-IOCTL-functionality-for-GPIO
>>>>>         - 0013-pm80xx-IOCTL-functionality-for-TWI-device
>>>>>         - For the above patches management utility passes command specific information to driver through IOCTL structure, which used by driver to frame the command and         - send to FW.  We are using the IOCTL interface for the same. Please let us know your thought.
>>>>
>>>> So I specifically questioned the SGPIO patch and why it would have an IOCTL, as this function is supported in kernel libsas/SAS transport code as an SMP function.
>>>>>    Thank you for your suggestions. We will make use of function supported in libsas.
>>>
>>> So basically you only need IOCTL for GPIO and TWI devices, others can
>>> implement via libsas interface or from sysfs directly.
>>>
>>> I would like to suggest you do send out other changes without the
>>> IOCTL parts first, and consider again Is it really needed by the user
>>> to control GPIO and TWI, and if there is other way to do it?
>>>
>>> Sorry, I don't have a better suggestion!
>>
>> LSI SAS HBAs (LSI now owned by Broadcom) implement an internal ** SMP
>> target. It can be seen here:
>>
>> # ls /dev/bsg
>> 3:0:0:0  3:0:3:0  8:0:0:0  8:0:0:3           end_device-3:1    expander-3:0
>> 3:0:1:0  4:0:0:0  8:0:0:1  8:0:0:4           end_device-3:1:0  expander-3:1
>> 3:0:2:0  7:0:0:0  8:0:0:2  end_device-3:0:1  end_device-3:2    sas_host3
>>
>> It is the last device node: "sas_host3". How do I know it is a SMP target?
>> Because this works:
>>
>> # smp_read_gpio /dev/bsg/sas_host3
>> Read GPIO register response:
>>     GPIO_CFG[0]:
>>       version: 0
>>       GPIO enable: 1
>>       cfg register count: 2
>>       gp register count: 1
>>       supported drive count: 16
>>

JFYI, that specific command is not implemented for libsas SMP host 
handler (see 
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/scsi/libsas/sas_host_smp.c?h=v5.6-rc5#n278), 
but the write command should be ok

>> When you work out what LSI are doing with this, perhaps you could write
>> an article about it and make it publicly available.

Firmware magic...

>> It is always a good idea to see how your competitors solve problems :-)
> This sounds indeed a better solution, thanks for the info, Doug
> 
> @Deepak Ukey can you check if you guys can also do it this way?
> 
> Regards,
> Jack Wang
> .
> 


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

* RE: [PATCH V2 05/13] pm80xx : Support for char device.
  2020-03-12 10:58                       ` John Garry
@ 2020-03-16  6:22                         ` Deepak.Ukey
  0 siblings, 0 replies; 38+ messages in thread
From: Deepak.Ukey @ 2020-03-16  6:22 UTC (permalink / raw)
  To: john.garry, jinpu.wang, dgilbert
  Cc: martin.petersen, jejb, linux-scsi, Vasanthalakshmi.Tharmarajan,
	Viswas.G, jinpu.wang, yuuzheng, auradkar, vishakhavc, bjashnani,
	radha, akshatzen

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

On 12/03/2020 08:49, Jinpu Wang wrote:
> On Wed, Mar 11, 2020 at 11:13 PM Douglas Gilbert <dgilbert@interlog.com> wrote:
>>
>> On 2020-03-11 1:08 p.m., Jinpu Wang wrote:
>>> On Tue, Jan 28, 2020 at 10:43 AM <Deepak.Ukey@microchip.com> wrote:
>>>>
>>>>
>>>> EXTERNAL EMAIL: Do not click links or open attachments unless you 
>>>> know the content is safe
>>>>
>>>> On 22/01/2020 08:50, Deepak.Ukey@microchip.com wrote:
>>>>> -r--r--r-- 1 root root 4096 Jan 21 12:05 
>>>>> running_disparity_error_count
>>>>> ***
>>>>> -r--r--r-- 1 root root 4096 Jan 21 12:05 sas_address
>>>>> lrwxrwxrwx 1 root root    0 Jan 21 11:45 subsystem ->
>>>>> ../../../../../../../class/sas_phy
>>>>> -r--r--r-- 1 root root 4096 Jan 21 12:05 target_port_protocols
>>>>> -rw-r--r-- 1 root root 4096 Jan 21 11:45 uevent
>>>>>
>>>>> Maybe the other stuff provided in the patches are useful, I don't know.
>>>>> But debugfs seems better for that.
>>>>>
>>>>>         - 0006-pm80xx-sysfs-attribute-for-number-of-phys
>>>>>         - 0007-pm80xx-IOCTL-functionality-to-get-phy-status gets things like Programmed Link Rate, Negotiated Link Rate, PHY Identifier
>>>>>         - 0008-pm80xx-IOCTL-functionality-to-get-phy-error provides other things like Invalid Dword Error Count, Disparity Error Count
>>>>>         - Thanks for addressing it. We can get this info from /sys/class/sas_phy and /sys/class/sas_port so we will drop these above mentioned three patches from the next              - patch series.
>>>>>
>>>
>>>>>
>>>>>         - 0009-pm80xx-IOCTL-functionality-for-GPIO
>>>>>         - 0013-pm80xx-IOCTL-functionality-for-TWI-device
>>>>>         - For the above patches management utility passes command specific information to driver through IOCTL structure, which used by driver to frame the command and         - send to FW.  We are using the IOCTL interface for the same. Please let us know your thought.
>>>>
>>>> So I specifically questioned the SGPIO patch and why it would have an IOCTL, as this function is supported in kernel libsas/SAS transport code as an SMP function.
>>>>>    Thank you for your suggestions. We will make use of function supported in libsas.
>>>
>>> So basically you only need IOCTL for GPIO and TWI devices, others 
>>> can implement via libsas interface or from sysfs directly.
>>>
>>> I would like to suggest you do send out other changes without the 
>>> IOCTL parts first, and consider again Is it really needed by the 
>>> user to control GPIO and TWI, and if there is other way to do it?
>>>
>>> Sorry, I don't have a better suggestion!
>>
>> LSI SAS HBAs (LSI now owned by Broadcom) implement an internal ** SMP 
>> target. It can be seen here:
>>
>> # ls /dev/bsg
>> 3:0:0:0  3:0:3:0  8:0:0:0  8:0:0:3           end_device-3:1    expander-3:0
>> 3:0:1:0  4:0:0:0  8:0:0:1  8:0:0:4           end_device-3:1:0  expander-3:1
>> 3:0:2:0  7:0:0:0  8:0:0:2  end_device-3:0:1  end_device-3:2    sas_host3
>>
>> It is the last device node: "sas_host3". How do I know it is a SMP target?
>> Because this works:
>>
>> # smp_read_gpio /dev/bsg/sas_host3
>> Read GPIO register response:
>>     GPIO_CFG[0]:
>>       version: 0
>>       GPIO enable: 1
>>       cfg register count: 2
>>       gp register count: 1
>>       supported drive count: 16
>>

JFYI, that specific command is not implemented for libsas SMP host handler (see https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/scsi/libsas/sas_host_smp.c?h=v5.6-rc5#n278),
but the write command should be ok

>> When you work out what LSI are doing with this, perhaps you could 
>> write an article about it and make it publicly available.

Firmware magic...

>> It is always a good idea to see how your competitors solve problems 
>> :-)
> This sounds indeed a better solution, thanks for the info, Doug
>
> @Deepak Ukey can you check if you guys can also do it this way?
We are going to submit the version 3 of the patchset without IOCTL patches and in future we will come up with the different solution for IOCTL patches. Also we will go through the solution suggested by Doug.
>
> Regards,
> Deepak
> .
>


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

end of thread, other threads:[~2020-03-16  6:22 UTC | newest]

Thread overview: 38+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-01-17  7:19 [PATCH V2 00/13] pm80xx : Updates for the driver version 0.1.39 Deepak Ukey
2020-01-17  7:19 ` [PATCH V2 01/13] pm80xx : Increase request sg length Deepak Ukey
2020-01-17 14:08   ` Jinpu Wang
2020-01-17 15:50     ` Deepak.Ukey
2020-01-17 15:53       ` Jinpu Wang
2020-01-20  4:20         ` Deepak.Ukey
2020-01-20  8:47           ` Jinpu Wang
2020-01-29  9:02             ` Deepak.Ukey
2020-01-17  7:19 ` [PATCH V2 02/13] pm80xx : Deal with kexec reboots Deepak Ukey
2020-01-17  7:19 ` [PATCH V2 03/13] pm80xx : Free the tag when mpi_set_phy_profile_resp is received Deepak Ukey
2020-01-17  7:19 ` [PATCH V2 04/13] pm80xx : Cleanup initialization loading fail path Deepak Ukey
2020-01-17  7:19 ` [PATCH V2 05/13] pm80xx : Support for char device Deepak Ukey
2020-01-17 14:15   ` Jinpu Wang
2020-01-21  0:24     ` Martin K. Petersen
2020-01-21  5:33       ` Deepak.Ukey
2020-01-21 12:39         ` John Garry
2020-01-22  8:50           ` Deepak.Ukey
2020-01-22 12:38             ` John Garry
2020-01-28  9:43               ` Deepak.Ukey
2020-03-11 17:08                 ` Jinpu Wang
2020-03-11 22:13                   ` Douglas Gilbert
2020-03-12  8:49                     ` Jinpu Wang
2020-03-12 10:58                       ` John Garry
2020-03-16  6:22                         ` Deepak.Ukey
2020-01-17  7:19 ` [PATCH V2 06/13] pm80xx : sysfs attribute for number of phys Deepak Ukey
2020-01-17 14:21   ` Jinpu Wang
2020-01-20  4:50     ` Deepak.Ukey
2020-01-21  7:55       ` Jinpu Wang
2020-01-17  7:19 ` [PATCH V2 07/13] pm80xx : IOCTL functionality to get phy status Deepak Ukey
2020-01-17 14:35   ` Jinpu Wang
2020-01-17  7:19 ` [PATCH V2 08/13] pm80xx : IOCTL functionality to get phy error Deepak Ukey
2020-01-17  7:19 ` [PATCH V2 09/13] pm80xx : IOCTL functionality for GPIO Deepak Ukey
2020-01-17  7:19 ` [PATCH V2 10/13] pm80xx : IOCTL functionality for SGPIO Deepak Ukey
2020-01-22  8:59   ` Jinpu Wang
2020-01-17  7:19 ` [PATCH V2 11/13] pm80xx : sysfs attribute for non fatal dump Deepak Ukey
2020-01-17 14:26   ` Jinpu Wang
2020-01-17  7:19 ` [PATCH V2 12/13] pm80xx : Introduce read and write length for IOCTL payload structure Deepak Ukey
2020-01-17  7:19 ` [PATCH V2 13/13] pm80xx : IOCTL functionality for TWI device Deepak Ukey

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.