pm80xx : Updates for the driver version 0.1.39.
Subsystems (2)
v2 cover pm80xx : Updates for the driver version 0.1.39.
From: Deepak Ukey <[email protected]>
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(-)
Signature · 1 line
2.16.3
PATCH v2 1/13 pm80xx : Increase request sg length.
From: Peter Chang <[email protected]>
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
--- drivers/scsi/pm8001/pm8001_defs.h | 5 +++-- drivers/scsi/pm8001/pm8001_init.c | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-)
drivers/scsi/pm8001/pm8001_defs.h +3 -2
@@ -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_SGenum memory_region_num {AAP1 =0x0 ,/* application acceleration processor */ IOP ,/* IO processor */
drivers/scsi/pm8001/pm8001_init.c +1 -1
@@ -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,
Signature · 1 line
2.16.3
Jinpu Wang
maintainerRe: [PATCH V2 01/13] pm80xx : Increase request sg length.
Quoted 29 lines · Deepak Ukey
From: Peter Chang <[email protected]>
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 layerSigned-off-by Peter Chang <[email protected]>Signed-off-by Deepak Ukey <[email protected]>Signed-off-by Viswas G <[email protected]>Signed-off-by Radha Ramachandran <[email protected]>Reported-by kbuild test robot <[email protected]>--- drivers/scsi/pm8001/pm8001_defs.h | 5 +++-- drivers/scsi/pm8001/pm8001_init.c | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-)drivers/scsi/pm8001/pm8001_defs.h +0
-0
drivers/scsi/pm8001/pm8001_defs.h enum port_type { · line 78
Quoted 5 lines
drivers/scsi/pm8001/pm8001_defs.h +1
-1@@ -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.
RE: [PATCH V2 01/13] pm80xx : Increase request sg length.
Quoted 30 lines · Deepak Ukey
From: Peter Chang <[email protected]>
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 layerSigned-off-by Peter Chang <[email protected]>Signed-off-by Deepak Ukey <[email protected]>Signed-off-by Viswas G <[email protected]>Signed-off-by Radha Ramachandran <[email protected]>Reported-by kbuild test robot <[email protected]>--- drivers/scsi/pm8001/pm8001_defs.h | 5 +++-- drivers/scsi/pm8001/pm8001_init.c | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-)drivers/scsi/pm8001/pm8001_defs.h +0
-0
drivers/scsi/pm8001/pm8001_defs.h enum port_type { · line 78
Quoted 5 lines
drivers/scsi/pm8001/pm8001_defs.h +1
-1@@ -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.
Jinpu Wang
maintainerRe: [PATCH V2 01/13] pm80xx : Increase request sg length.
Quoted 34 lines · On Fri, Jan 17, 2020 at 4:50 PM <[email protected]> wrote:
Quoted 32 lines · Deepak Ukey
From: Peter Chang <[email protected]>
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 layerSigned-off-by Peter Chang <[email protected]>Signed-off-by Deepak Ukey <[email protected]>Signed-off-by Viswas G <[email protected]>Signed-off-by Radha Ramachandran <[email protected]>Reported-by kbuild test robot <[email protected]>--- drivers/scsi/pm8001/pm8001_defs.h | 5 +++-- drivers/scsi/pm8001/pm8001_init.c | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-)drivers/scsi/pm8001/pm8001_defs.h +0
-0@@ -75,7 +75,7 @@ enum port_type { };
Quoted 7 lines
drivers/scsi/pm8001/pm8001_defs.h enum port_type { · line 78
Quoted 3 lines
drivers/scsi/pm8001/pm8001_defs.h +1
-1/* 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
RE: [PATCH V2 01/13] pm80xx : Increase request sg length.
EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
Quoted 34 lines · On Fri, Jan 17, 2020 at 4:50 PM <[email protected]> wrote:
Quoted 32 lines · Deepak Ukey
From: Peter Chang <[email protected]>
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 layerSigned-off-by Peter Chang <[email protected]>Signed-off-by Deepak Ukey <[email protected]>Signed-off-by Viswas G <[email protected]>Signed-off-by Radha Ramachandran <[email protected]>Reported-by kbuild test robot <[email protected]>--- drivers/scsi/pm8001/pm8001_defs.h | 5 +++-- drivers/scsi/pm8001/pm8001_init.c | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-)drivers/scsi/pm8001/pm8001_defs.h +0
-0@@ -75,7 +75,7 @@ enum port_type { };
Quoted 7 lines
drivers/scsi/pm8001/pm8001_defs.h enum port_type { · line 78
Quoted 3 lines
drivers/scsi/pm8001/pm8001_defs.h +1
-1/* 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
Jinpu Wang
maintainerRe: [PATCH V2 01/13] pm80xx : Increase request sg length.
Quoted 44 lines · On Mon, Jan 20, 2020 at 5:20 AM <[email protected]> wrote:
EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
Quoted 39 lines · On Fri, Jan 17, 2020 at 4:50 PM <[email protected]> wrote:
Quoted 30 lines · Deepak Ukey
From: Peter Chang <[email protected]>
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 layerSigned-off-by Peter Chang <[email protected]>Signed-off-by Deepak Ukey <[email protected]>Signed-off-by Viswas G <[email protected]>Signed-off-by Radha Ramachandran <[email protected]>Reported-by kbuild test robot <[email protected]>--- drivers/scsi/pm8001/pm8001_defs.h | 5 +++-- drivers/scsi/pm8001/pm8001_init.c | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-)drivers/scsi/pm8001/pm8001_defs.h +0
-0drivers/scsi/pm8001/pm8001_defs.h enum port_type { · line 78
Quoted 5 lines
drivers/scsi/pm8001/pm8001_defs.h +1
-1@@ -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,
Quoted 5 lines
Quoted 2 lines
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
RE: [PATCH V2 01/13] pm80xx : Increase request sg length.
EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
Quoted 44 lines · On Mon, Jan 20, 2020 at 5:20 AM <[email protected]> wrote:
EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
Quoted 38 lines · On Fri, Jan 17, 2020 at 4:50 PM <[email protected]> wrote:
Quoted 30 lines · Deepak Ukey
From: Peter Chang <[email protected]>
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 layerSigned-off-by Peter Chang <[email protected]>Signed-off-by Deepak Ukey <[email protected]>Signed-off-by Viswas G <[email protected]>Signed-off-by Radha Ramachandran <[email protected]>Reported-by kbuild test robot <[email protected]>--- drivers/scsi/pm8001/pm8001_defs.h | 5 +++-- drivers/scsi/pm8001/pm8001_init.c | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-)drivers/scsi/pm8001/pm8001_defs.h +0
-0drivers/scsi/pm8001/pm8001_defs.h enum port_type { }; · line 77
Quoted 4 lines
drivers/scsi/pm8001/pm8001_defs.h +1
-1@@ -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,
Quoted 6 lines
Quoted 2 lines
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.
Quoted 1 line
Thanks. I will add this in version 3 of the patchest.
Thanks
PATCH v2 2/13 pm80xx : Deal with kexec reboots.
In reply to Deepak UkeyFrom: Vikram Auradkar <[email protected]>
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.
--- drivers/scsi/pm8001/pm8001_init.c | 48 +++++++++++++++++++++++++++++++++++---- drivers/scsi/pm8001/pm80xx_hwi.c | 15 ++++++++---- 2 files changed, 54 insertions(+), 9 deletions(-)
drivers/scsi/pm8001/pm8001_init.c +43 -5
@@ -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(
drivers/scsi/pm8001/pm80xx_hwi.c +11 -4
@@ -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 */
Signature · 1 line
2.16.3
PATCH v2 3/13 pm80xx : Free the tag when mpi_set_phy_profile_resp is received.
In reply to Deepak UkeyFrom: yuuzheng <[email protected]>
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).
--- drivers/scsi/pm8001/pm80xx_hwi.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
drivers/scsi/pm8001/pm80xx_hwi.c +7 -3
@@ -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; }/**
Signature · 1 line
2.16.3
PATCH v2 4/13 pm80xx : Cleanup initialization loading fail path.
In reply to Deepak UkeyFrom: Peter Chang <[email protected]>
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.
--- drivers/scsi/pm8001/pm8001_init.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-)
drivers/scsi/pm8001/pm8001_init.c +11 -6
@@ -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:
Signature · 1 line
2.16.3
PATCH v2 5/13 pm80xx : Support for char device.
In reply to Deepak UkeyFrom: Deepak Ukey <[email protected]>
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.
--- 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(+)
drivers/scsi/pm8001/pm8001_ctl.c +148 -0
@@ -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 ; + } +}
drivers/scsi/pm8001/pm8001_ctl.h +33 -0
@@ -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 */
drivers/scsi/pm8001/pm8001_init.c +5 -0
@@ -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:
drivers/scsi/pm8001/pm8001_sas.h +6 -0
@@ -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,
Signature · 1 line
2.16.3
Jinpu Wang
maintainerRe: [PATCH V2 05/13] pm80xx : Support for char device.
Quoted 9 lines · Deepak Ukey
From: Deepak Ukey <[email protected]>
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.
Quoted 3 lines
Signed-off-by Deepak Ukey <[email protected]>Signed-off-by Viswas G <[email protected]>Signed-off-by Radha Ramachandran <[email protected]>
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
Re: [PATCH V2 05/13] pm80xx : Support for char device.
Jinpu,
Quoted 2 lines
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?
Signature · 1 line
Martin K. Petersen Oracle Linux Engineering
RE: [PATCH V2 05/13] pm80xx : Support for char device.
EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
Martin,
Quoted 2 lines
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
Re: [PATCH V2 05/13] pm80xx : Support for char device.
Quoted 8 lines · On 21/01/2020 05:33, [email protected] wrote:
EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
Martin,
Quoted 2 lines
Thanks for the commit message, looks much better. In the past, people are against IOCTL, suggesting netlink, have you considered that?
Quoted 7 lines
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.
Quoted 2 lines
0009-pm80xx-IOCTL-functionality-for-GPIO
0010-pm80xx-IOCTL-functionality-for-SGPIO
I don't know why an ioctl is required here.
Quoted 1 line
0013-pm80xx-IOCTL-functionality-for-TWI-device
Thanks,
John
RE: [PATCH V2 05/13] pm80xx : Support for char device.
EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
Quoted 9 lines · On 21/01/2020 05:33, [email protected] wrote:
EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
Martin,
Quoted 2 lines
Thanks for the commit message, looks much better. In the past, people are against IOCTL, suggesting netlink, have you considered that?
Quoted 7 lines
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.
Quoted 2 lines
0009-pm80xx-IOCTL-functionality-for-GPIO
0010-pm80xx-IOCTL-functionality-for-SGPIO
I don't know why an ioctl is required here.
Quoted 1 line
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
Re: [PATCH V2 05/13] pm80xx : Support for char device.
Quoted 18 lines · On 22/01/2020 08:50, [email protected] wrote:
(quoted diff) +0
-2-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_addresslrwxrwxrwx 1 root root 0 Jan 21 11:45 subsystem ->
../../../../../../../class/sas_phy(quoted diff) +0
-2-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 ueventMaybe 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_phyand/sys/class/sas_portso we will drop these above mentioned three patches from the next - patch series.Quoted 2 lines
0009-pm80xx-IOCTL-functionality-for-GPIO
0010-pm80xx-IOCTL-functionality-for-SGPIO
Quoted 8 lines
I don't know why an ioctl is required here.
Quoted 1 line
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 <[email protected]> (maintainer:LEGACY EEPROM DRIVER) Arnd Bergmann <[email protected]> (supporter:CHAR and MISC DRIVERS) Greg Kroah-Hartman <[email protected]> (supporter:CHAR and MISC DRIVERS)
Thanks,
John
RE: [PATCH V2 05/13] pm80xx : Support for char device.
EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
Quoted 19 lines · On 22/01/2020 08:50, [email protected] 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:05sas_address
lrwxrwxrwx 1 root root 0 Jan 21 11:45 subsystem ->
../../../../../../../class/sas_phy(quoted diff) +0
-2-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 ueventMaybe 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_phyand/sys/class/sas_portso we will drop these above mentioned three patches from the next - patch series.Quoted 2 lines
0009-pm80xx-IOCTL-functionality-for-GPIO
0010-pm80xx-IOCTL-functionality-for-SGPIO
Quoted 8 lines
I don't know why an ioctl is required here.
Quoted 1 line
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.
Quoted 1 line
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?
Quoted 3 lines
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:
Quoted 2 lines
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 <[email protected]> (maintainer:LEGACY EEPROM DRIVER) Arnd Bergmann <[email protected]> (supporter:CHAR and MISC DRIVERS) Greg Kroah-Hartman <[email protected]> (supporter:CHAR and MISC DRIVERS)
Thanks,
Deepak
Jinpu Wang
maintainerRe: [PATCH V2 05/13] pm80xx : Support for char device.
Quoted 23 lines · On Tue, Jan 28, 2020 at 10:43 AM <[email protected]> wrote:
EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
Quoted 18 lines · On 22/01/2020 08:50, [email protected] 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:05sas_address
lrwxrwxrwx 1 root root 0 Jan 21 11:45 subsystem ->
../../../../../../../class/sas_phy(quoted diff) +0
-2-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 ueventMaybe 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_phyand/sys/class/sas_portso we will drop these above mentioned three patches from the next - patch series.
Quoted 6 lines
Quoted 3 lines
- 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.
Quoted 1 line
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
Re: [PATCH V2 05/13] pm80xx : Support for char device.
Quoted 31 lines · Jinpu Wang
Quoted 23 lines · On Tue, Jan 28, 2020 at 10:43 AM <[email protected]> wrote:
EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
Quoted 18 lines · On 22/01/2020 08:50, [email protected] 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:05sas_address
lrwxrwxrwx 1 root root 0 Jan 21 11:45 subsystem ->
../../../../../../../class/sas_phy(quoted diff) +0
-2-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 ueventMaybe 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_phyand/sys/class/sas_portso we will drop these above mentioned three patches from the next - patch series.Quoted 6 lines
Quoted 3 lines
- 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.
Quoted 1 line
Thank you for your suggestions. We will make use of function supported in libsas.
Quoted 8 lines
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: 16When 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.
Jinpu Wang
maintainerRe: [PATCH V2 05/13] pm80xx : Support for char device.
Quoted 62 lines · Douglas Gilbert
Quoted 31 lines · Jinpu Wang
Quoted 23 lines · On Tue, Jan 28, 2020 at 10:43 AM <[email protected]> wrote:
EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
Quoted 18 lines · On 22/01/2020 08:50, [email protected] 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:05sas_address
lrwxrwxrwx 1 root root 0 Jan 21 11:45 subsystem ->
../../../../../../../class/sas_phy(quoted diff) +0
-2-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 ueventMaybe 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_phyand/sys/class/sas_portso we will drop these above mentioned three patches from the next - patch series.Quoted 6 lines
Quoted 3 lines
- 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.
Quoted 1 line
Thank you for your suggestions. We will make use of function supported in libsas.
Quoted 8 lines
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_host3It 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
Quoted 3 lines
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
Re: [PATCH V2 05/13] pm80xx : Support for char device.
Quoted 54 lines · Jinpu Wang
Quoted 53 lines · Douglas Gilbert
Quoted 31 lines · Jinpu Wang
Quoted 23 lines · On Tue, Jan 28, 2020 at 10:43 AM <[email protected]> wrote:
EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
Quoted 18 lines · On 22/01/2020 08:50, [email protected] 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:05sas_address
lrwxrwxrwx 1 root root 0 Jan 21 11:45 subsystem ->
../../../../../../../class/sas_phy(quoted diff) +0
-2-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 ueventMaybe 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_phyand/sys/class/sas_portso we will drop these above mentioned three patches from the next - patch series.Quoted 6 lines
Quoted 3 lines
- 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.
Quoted 1 line
Thank you for your suggestions. We will make use of function supported in libsas.
Quoted 8 lines
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_host3It is the last device node: "
sas_host3". How do I know it is a SMP target? Because this works:
Quoted 9 lines
Quoted 9 lines
# 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
Quoted 2 lines
Quoted 2 lines
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...
Quoted 9 lines
Quoted 1 line
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
.
RE: [PATCH V2 05/13] pm80xx : Support for char device.
EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
Quoted 56 lines · Jinpu Wang
Quoted 55 lines · Douglas Gilbert
Quoted 33 lines · Jinpu Wang
Quoted 25 lines · On Tue, Jan 28, 2020 at 10:43 AM <[email protected]> wrote:
EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
Quoted 19 lines · On 22/01/2020 08:50, [email protected] 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:05sas_address
lrwxrwxrwx 1 root root 0 Jan 21 11:45 subsystem ->
../../../../../../../class/sas_phy(quoted diff) +0
-2-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 ueventMaybe 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_phyand/sys/class/sas_portso we will drop these above mentioned three patches from the next - patch series.Quoted 6 lines
Quoted 3 lines
- 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.
Quoted 1 line
Thank you for your suggestions. We will make use of function supported in libsas.
Quoted 8 lines
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_host3It is the last device node: "
sas_host3". How do I know it is a SMP target? Because this works:
Quoted 9 lines
Quoted 9 lines
# 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
Quoted 2 lines
Quoted 2 lines
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...
Quoted 5 lines
Quoted 2 lines
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.
Quoted 5 lines
Regards,
Deepak
.
PATCH v2 6/13 pm80xx : sysfs attribute for number of phys.
In reply to Deepak UkeyFrom: Viswas G <[email protected]>
Added sysfs attribute to show number of phys.
--- drivers/scsi/pm8001/pm8001_ctl.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+)
drivers/scsi/pm8001/pm8001_ctl.c +20 -0
@@ -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,
Signature · 1 line
2.16.3
Jinpu Wang
maintainerRe: [PATCH V2 06/13] pm80xx : sysfs attribute for number of phys.
Quoted 8 lines · Deepak Ukey
From: Viswas G <[email protected]>
Added sysfs attribute to show number of phys.
Signed-off-by Deepak Ukey <[email protected]>Signed-off-by Viswas G <[email protected]>Signed-off-by Radha Ramachandran <[email protected]>
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!
RE: [PATCH V2 06/13] pm80xx : sysfs attribute for number of phys.
EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
Quoted 8 lines · Deepak Ukey
From: Viswas G <[email protected]>
Added sysfs attribute to show number of phys.
Signed-off-by Deepak Ukey <[email protected]>Signed-off-by Viswas G <[email protected]>Signed-off-by Radha Ramachandran <[email protected]>
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.
Quoted 1 line
We have HBA application already in use by customer which uses this sysfs entry. So is it fine to keep this patch?
Thanks!
Jinpu Wang
maintainerRe: [PATCH V2 06/13] pm80xx : sysfs attribute for number of phys.
Quoted 10 lines · On Mon, Jan 20, 2020 at 5:50 AM <[email protected]> wrote:
EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
Quoted 5 lines · Deepak Ukey
From: Viswas G <[email protected]>
Added sysfs attribute to show number of phys.
Quoted 8 lines
Quoted 3 lines
Signed-off-by Deepak Ukey <[email protected]>Signed-off-by Viswas G <[email protected]>Signed-off-by Radha Ramachandran <[email protected]>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.
Quoted 1 line
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
PATCH v2 7/13 pm80xx : IOCTL functionality to get phy status.
In reply to Deepak UkeyFrom: Viswas G <[email protected]>
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.
--- 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(-)
drivers/scsi/pm8001/pm8001_ctl.c +90 -0
@@ -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 ; }
drivers/scsi/pm8001/pm8001_ctl.h +22 -1
@@ -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 16struct 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 */
drivers/scsi/pm8001/pm8001_sas.h +7 -0
@@ -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; };
drivers/scsi/pm8001/pm80xx_hwi.c +68 -0
87 lines not on this page · raw message
drivers/scsi/pm8001/pm80xx_hwi.h +1 -0
@@ -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 */
Signature · 1 line
2.16.3
Jinpu Wang
maintainerRe: [PATCH V2 07/13] pm80xx : IOCTL functionality to get phy status.
drivers/scsi/pm8001/pm8001_sas.h struct pm8001_hba_info { · line 567
Quoted 7 lines
struct
pm8001_chip_info{drivers/scsi/pm8001/pm8001_sas.h +2
-0@@ -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.
Quoted 4 lines
drivers/scsi/pm8001/pm8001_sas.h +2
-0+struct completion *ioctl_completion; +struct phy_prof_resp phy_profile_resp;u32 reset_in_progress; };
PATCH v2 8/13 pm80xx : IOCTL functionality to get phy error.
In reply to Deepak UkeyFrom: Viswas G <[email protected]>
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.
--- 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(+)
drivers/scsi/pm8001/pm8001_ctl.c +54 -0
@@ -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 ; }
drivers/scsi/pm8001/pm8001_ctl.h +12 -0
@@ -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 */
drivers/scsi/pm8001/pm80xx_hwi.c +14 -0
@@ -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); }
drivers/scsi/pm8001/pm80xx_hwi.h +1 -0
@@ -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
Signature · 1 line
2.16.3
PATCH v2 9/13 pm80xx : IOCTL functionality for GPIO.
In reply to Deepak UkeyFrom: Deepak Ukey <[email protected]>
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
--- 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(+)
drivers/scsi/pm8001/pm8001_ctl.c +95 -0
@@ -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, };/**
drivers/scsi/pm8001/pm8001_ctl.h +24 -0
@@ -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, \
drivers/scsi/pm8001/pm8001_init.c +6 -0
@@ -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())
drivers/scsi/pm8001/pm8001_sas.h +17 -0
@@ -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;
drivers/scsi/pm8001/pm80xx_hwi.c +106 -0
133 lines not on this page · raw message
drivers/scsi/pm8001/pm80xx_hwi.h +49 -0
55 lines not on this page · raw message
Signature · 1 line
2.16.3
PATCH v2 10/13 pm80xx : IOCTL functionality for SGPIO.
In reply to Deepak UkeyFrom: Deepak Ukey <[email protected]>
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.
--- 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(-)
drivers/scsi/pm8001/pm8001_ctl.c +71 -0
@@ -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;
drivers/scsi/pm8001/pm8001_ctl.h +72 -0
96 lines not on this page · raw message
drivers/scsi/pm8001/pm8001_hwi.c +171 -1
206 lines not on this page · raw message
drivers/scsi/pm8001/pm8001_hwi.h +17 -0
@@ -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
drivers/scsi/pm8001/pm8001_init.c +3 -0
@@ -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) {
drivers/scsi/pm8001/pm8001_sas.c +37 -0
@@ -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; +}
drivers/scsi/pm8001/pm8001_sas.h +20 -0
@@ -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,
drivers/scsi/pm8001/pm80xx_hwi.c +6 -0
@@ -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, };
drivers/scsi/pm8001/pm80xx_hwi.h +3 -0
@@ -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
Signature · 1 line
2.16.3
Jinpu Wang
maintainerRe: [PATCH V2 10/13] pm80xx : IOCTL functionality for SGPIO.
Quoted 7 lines · Deepak Ukey
From: Deepak Ukey <[email protected]>
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
PATCH v2 11/13 pm80xx : sysfs attribute for non fatal dump.
In reply to Deepak UkeyFrom: Deepak Ukey <[email protected]>
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.
--- 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(+)
drivers/scsi/pm8001/pm8001_ctl.c +45 -0
@@ -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,
drivers/scsi/pm8001/pm8001_init.c +1 -0
@@ -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 {
drivers/scsi/pm8001/pm8001_sas.h +4 -0
@@ -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[];
drivers/scsi/pm8001/pm80xx_hwi.c +130 -0
136 lines not on this page · raw message
Signature · 1 line
2.16.3
Re: [PATCH V2 11/13] pm80xx : sysfs attribute for non fatal dump.
Quoted 13 lines · Deepak Ukey
From: Deepak Ukey <[email protected]>
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.
Quoted 3 lines
Signed-off-by Deepak Ukey <[email protected]>Signed-off-by Viswas G <[email protected]>Signed-off-by Radha Ramachandran <[email protected]>
Thanks
PATCH v2 12/13 pm80xx : Introduce read and write length for IOCTL payload structure.
In reply to Deepak UkeyFrom: Viswas G <[email protected]>
Removed the common length and introduce read and write length for IOCTL payload structure.
--- 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(-)
drivers/scsi/pm8001/pm8001_ctl.c +3 -3
@@ -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;
drivers/scsi/pm8001/pm8001_hwi.c +11 -11
@@ -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);
drivers/scsi/pm8001/pm8001_init.c +6 -6
@@ -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 ;
drivers/scsi/pm8001/pm8001_sas.h +2 -1
@@ -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; };
Signature · 1 line
2.16.3
PATCH v2 13/13 pm80xx : IOCTL functionality for TWI device.
In reply to Deepak UkeyFrom: Deepak Ukey <[email protected]>
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.
--- 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(-)
drivers/scsi/pm8001/pm8001_ctl.c +133 -0
@@ -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 ; }
drivers/scsi/pm8001/pm8001_ctl.h +23 -0
@@ -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 */
drivers/scsi/pm8001/pm8001_hwi.c +92 -21
160 lines not on this page · raw message
drivers/scsi/pm8001/pm8001_hwi.h +1 -0
@@ -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)));
drivers/scsi/pm8001/pm8001_init.c +10 -0
@@ -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 );
drivers/scsi/pm8001/pm8001_sas.h +13 -0
@@ -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[];
drivers/scsi/pm8001/pm80xx_hwi.c +41 -0
47 lines not on this page · raw message
drivers/scsi/pm8001/pm80xx_hwi.h +1 -0
@@ -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)));/**
Signature · 1 line
2.16.3