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 "Fix for SATA device discovery" patch.
- Spilt the patch in two different patches that is "Fix for SATA device discovery" and "Make phy enable completion as NULL"
For "Cleanup command when a reset times out" patch.
- Fix the typo mistake.
For "Controller fatal error through sysfs" patch.
- Updated the function name in comment section.
For " Modified the logic to collect fatal dump" patch.
- Fixed the compiler warning for mips and i386 architecture.
Deepak Ukey (2):
pm80xx : Controller fatal error through sysfs. pm80xx : Modified the logic to collect fatal dump.
John Sperbeck (1):
pm80xx : Initialize variable used as return status.
Vikram Auradkar (3):
pm80xx : Convert 'long' mdelay to msleep. pm80xx : Fix dereferencing dangling pointer. pm80xx : Tie the interrupt name to the module instance.
ianyar (1):
pm80xx : Increase timeout for pm80xx mpi_uninit_check.
peter chang (6):
pm80xx : Fix for SATA device discovery. pm80xx : Make phy enable completion as NULL. pm80xx : Squashed logging cleanup changes. pm80xx : Fix command issue sizing. pm80xx : Cleanup command when a reset times out. pm80xx : Do not request 12G sas speeds.
drivers/scsi/pm8001/pm8001_ctl.c | 20 ++ drivers/scsi/pm8001/pm8001_hwi.c | 131 +++++++---- drivers/scsi/pm8001/pm8001_init.c | 34 ++- drivers/scsi/pm8001/pm8001_sas.c | 70 ++++-- drivers/scsi/pm8001/pm8001_sas.h | 24 +- drivers/scsi/pm8001/pm80xx_hwi.c | 451 ++++++++++++++++++++++++++++---------- drivers/scsi/pm8001/pm80xx_hwi.h | 3 + 7 files changed, 550 insertions(+), 183 deletions(-)
Signature · 1 line
2.16.3
PATCH v2 1/13 pm80xx : Fix for SATA device discovery.
From: peter chang <[email protected]>
Driver was missing complete() call in mpi_sata_completion which result in SATA abort error handling is timing out. That causes the device to be left in the in_recovery state so subsequent commands sent to the device fail and the OS removes access to it.
--- drivers/scsi/pm8001/pm80xx_hwi.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/scsi/pm8001/pm80xx_hwi.c +2 -0
@@ -2382,6 +2382,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)pm8001_printk ("task 0x%p done with io_status 0x%x" " resp 0x%x stat 0x%x but aborted by upper layer!\n" , t, status, ts->resp, ts->stat)); +if (t->slow_task) +complete (&t->slow_task->completion);pm8001_ccb_task_free (pm8001_ha, t, ccb, tag); }else {spin_unlock_irqrestore (&t->task_state_lock, flags);
Signature · 1 line
2.16.3
Re: [PATCH V2 01/13] pm80xx : Fix for SATA device discovery.
Quoted 11 lines · Deepak Ukey
From: peter chang <[email protected]>
Driver was missing
complete()call inmpi_sata_completionwhich result in SATA abort error handling is timing out. That causes the device to be left in thein_recoverystate so subsequent commands sent to the device fail and the OS removes access to it.Signed-off-by peter chang <[email protected]>Signed-off-by Deepak Ukey <[email protected]>Signed-off-by Viswas G <[email protected]>
Thanks
Quoted 20 lines
--- drivers/scsi/pm8001/pm80xx_hwi.c | 2 ++ 1 file changed, 2 insertions(+)drivers/scsi/pm8001/pm80xx_hwi.c +2
-1@@ -2382,6 +2382,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)pm8001_printk ("task 0x%p done with io_status 0x%x" " resp 0x%x stat 0x%x but aborted by upper layer!\n" , t, status, ts->resp, ts->stat)); +if (t->slow_task) +complete (&t->slow_task->completion);pm8001_ccb_task_free (pm8001_ha, t, ccb, tag); }else {spin_unlock_irqrestore (&t->task_state_lock, flags); --2.16.3
PATCH v2 2/13 pm80xx : Make phy enable completion as NULL.
In reply to Deepak UkeyFrom: peter chang <[email protected]>
After the completing the mpi_phy_start_resp make phy enable completion as NULL.
--- drivers/scsi/pm8001/pm80xx_hwi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/scsi/pm8001/pm80xx_hwi.c +3 -1
@@ -3132,8 +3132,10 @@ static int mpi_phy_start_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)if (status ==0 ) { phy->phy_state =PHY_LINK_DOWN ;if (pm8001_ha->flags ==PM8001F_RUN_TIME && - phy->enable_completion !=NULL ) + phy->enable_completion !=NULL ) {complete (phy->enable_completion); + phy->enable_completion =NULL ; + } }return 0 ;
Signature · 1 line
2.16.3
Re: [PATCH V2 02/13] pm80xx : Make phy enable completion as NULL.
Quoted 9 lines · Deepak Ukey
From: peter chang <[email protected]>
After the completing the
mpi_phy_start_respmake phy enable completion as NULL.Signed-off-by peter chang <[email protected]>Signed-off-by Deepak Ukey <[email protected]>Signed-off-by Viswas G <[email protected]>
Thanks
PATCH v2 3/13 pm80xx : Initialize variable used as return status.
In reply to Deepak UkeyFrom: John Sperbeck <[email protected]>
In pm8001_task_exec(), if the PHY is down, then we return the current value of 'rc'. We need to make sure it's initialized.
--- drivers/scsi/pm8001/pm8001_sas.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/scsi/pm8001/pm8001_sas.c +1 -1
@@ -384,7 +384,7 @@ static int pm8001_task_exec(struct sas_task *task,struct pm8001_port *port =NULL ;struct sas_task *t = task;struct pm8001_ccb_info *ccb; -u32 tag =0xdeadbeef , rc, n_elem =0 ; +u32 tag =0xdeadbeef , rc =0 , n_elem =0 ;unsigned long flags =0 ;if (!dev->port) {
Signature · 1 line
2.16.3
PATCH v2 4/13 pm80xx : Convert 'long' mdelay to msleep.
In reply to Deepak UkeyFrom: Vikram Auradkar <[email protected]>
For delays longer than 20ms [um]delay isn't recommended. pm80xx_chip_soft_rst starts off with a 500ms delay before it even gets around to checking for the results of the reset. As long as it's at least 500ms it doesn't matter what the scheduler is doing. The delay in the pm8001_exec_internal_task_abort does nothing, and theory is this is a delay to avoid a double-free.
--- drivers/scsi/pm8001/pm80xx_hwi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/scsi/pm8001/pm80xx_hwi.c +2 -2
@@ -1241,7 +1241,7 @@ pm80xx_chip_soft_rst(struct pm8001_hba_info *pm8001_ha) pm8001_printk("reset register before write : 0x%x\n", regval));pm8001_cw32 (pm8001_ha,0 ,SPC_REG_SOFT_RESET , SPCv_NORMAL_RESET_VALUE); -mdelay (500 ); +msleep (500 ); regval =pm8001_cr32 (pm8001_ha,0 ,SPC_REG_SOFT_RESET ); PM8001_INIT_DBG(pm8001_ha,
@@ -2986,7 +2986,7 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)pm8001_get_attached_sas_addr (phy, phy->sas_phy.attached_sas_addr);spin_unlock_irqrestore (&phy->sas_phy.frame_rcvd_lock, flags);if (pm8001_ha->flags ==PM8001F_RUN_TIME ) -mdelay (200 );/*delay a moment to wait disk to spinup*/ +msleep (200 );/*delay a moment to wait disk to spinup*/ pm8001_bytes_dmaed (pm8001_ha, phy_id); }
Signature · 1 line
2.16.3
PATCH v2 5/13 pm80xx : Squashed logging cleanup changes.
In reply to Deepak UkeyFrom: peter chang <[email protected]>
The default logging doesn't include the device name, so it's difficult to determine which controller is being logged about in error scenarios. The logging level was only settable via sysfs, which made it inconvenient for actual debugging. This changes the default to only cover error handling.
--- drivers/scsi/pm8001/pm8001_hwi.c | 62 ++++++++++++++------ drivers/scsi/pm8001/pm8001_init.c | 6 +- drivers/scsi/pm8001/pm8001_sas.c | 6 +- drivers/scsi/pm8001/pm8001_sas.h | 15 ++++- drivers/scsi/pm8001/pm80xx_hwi.c | 118 +++++++++++++++++++++++++++++++++----- 5 files changed, 170 insertions(+), 37 deletions(-)
drivers/scsi/pm8001/pm8001_hwi.c +44 -18
@@ -1364,7 +1364,7 @@ int pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha,/*Update the PI to the firmware*/ pm8001_cw32 (pm8001_ha, circularQ->pi_pci_bar, circularQ->pi_offset, circularQ->producer_idx); -PM8001_IO_DBG (pm8001_ha, +PM8001_DEVIO_DBG (pm8001_ha,pm8001_printk ("INB Q %x OPCODE:%x , UPDATED PI=%d CI=%d\n" , responseQueue, opCode, circularQ->producer_idx, circularQ->consumer_index));
@@ -1436,6 +1436,10 @@ u32 pm8001_mpi_msg_consume(struct pm8001_hba_info *pm8001_ha,/* read header */ header_tmp =pm8001_read_32 (msgHeader); msgHeader_tmp =cpu_to_le32 (header_tmp); +PM8001_DEVIO_DBG (pm8001_ha,pm8001_printk ( +"outbound opcode msgheader:%x ci=%d pi=%d\n" , + msgHeader_tmp, circularQ->consumer_idx, + circularQ->producer_index));if (0 != (le32_to_cpu (msgHeader_tmp) &0x80000000 )) {if (OPC_OUB_SKIP_ENTRY != (le32_to_cpu (msgHeader_tmp) &0xfff )) {
@@ -1604,7 +1608,8 @@ void pm8001_work_fn(struct work_struct *work)break ;default : -pm8001_printk ("...query task failed!!!\n" ); +PM8001_DEVIO_DBG (pm8001_ha,pm8001_printk ( +"...query task failed!!!\n" ));break ; });
@@ -1890,6 +1895,11 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)pm8001_printk ("SAS Address of IO Failure Drive:" "%016llx", SAS_ADDR(t->dev->sas_addr))); +if (status) +PM8001_IOERR_DBG (pm8001_ha,pm8001_printk ( +"status:0x%x, tag:0x%x, task:0x%p\n" , + status, tag, t)); +switch (status) {case IO_SUCCESS : PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_SUCCESS"
@@ -2072,7 +2082,7 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) ts->open_rej_reason =SAS_OREJ_RSVD_RETRY ;break ;default : -PM8001_IO_DBG (pm8001_ha, +PM8001_DEVIO_DBG (pm8001_ha,pm8001_printk ("Unknown status 0x%x\n" , status));/* not allowed case. Therefore, return failed status */ ts->resp =SAS_TASK_COMPLETE ;
@@ -2125,7 +2135,7 @@ static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha , void *piomb)if (unlikely (!t || !t->lldd_task || !t->dev))return ; ts = &t->task_status; -PM8001_IO_DBG (pm8001_ha, +PM8001_DEVIO_DBG (pm8001_ha,pm8001_printk ("port_id = %x,device_id = %x\n" , port_id, dev_id));switch (event) {
@@ -2263,7 +2273,7 @@ static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha , void *piomb) pm8001_printk(" IO_XFER_CMD_FRAME_ISSUED\n"));return ;default : -PM8001_IO_DBG (pm8001_ha, +PM8001_DEVIO_DBG (pm8001_ha,pm8001_printk ("Unknown status 0x%x\n" , event));/* not allowed case. Therefore, return failed status */ ts->resp =SAS_TASK_COMPLETE ;
@@ -2352,6 +2362,12 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) pm8001_printk("ts null\n"));return ; } + +if (status) +PM8001_IOERR_DBG (pm8001_ha,pm8001_printk ( +"status:0x%x, tag:0x%x, task::0x%p\n" , + status, tag, t)); +/* Print sas address of IO failed device */ if ((status !=IO_SUCCESS ) && (status !=IO_OVERFLOW ) && (status !=IO_UNDERFLOW )) {
@@ -2652,7 +2668,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) ts->open_rej_reason =SAS_OREJ_RSVD_RETRY ;break ;default : -PM8001_IO_DBG (pm8001_ha, +PM8001_DEVIO_DBG (pm8001_ha,pm8001_printk ("Unknown status 0x%x\n" , status));/* not allowed case. Therefore, return failed status */ ts->resp =SAS_TASK_COMPLETE ;
@@ -2723,7 +2739,7 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb)if (unlikely (!t || !t->lldd_task || !t->dev))return ; ts = &t->task_status; -PM8001_IO_DBG (pm8001_ha,pm8001_printk ( +PM8001_DEVIO_DBG (pm8001_ha,pm8001_printk ("port_id:0x%x, device_id:0x%x, tag:0x%x, event:0x%x\n" , port_id, dev_id, tag, event));switch (event) {
@@ -2872,7 +2888,7 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb) ts->stat =SAS_OPEN_TO ;break ;default : -PM8001_IO_DBG (pm8001_ha, +PM8001_DEVIO_DBG (pm8001_ha,pm8001_printk ("Unknown status 0x%x\n" , event));/* not allowed case. Therefore, return failed status */ ts->resp =SAS_TASK_COMPLETE ;
@@ -2917,9 +2933,13 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) t = ccb->task; ts = &t->task_status; pm8001_dev = ccb->device; -if (status) +if (status) {PM8001_FAIL_DBG (pm8001_ha,pm8001_printk ("smp IO status 0x%x\n" , status)); +PM8001_IOERR_DBG (pm8001_ha, +pm8001_printk ("status:0x%x, tag:0x%x, task:0x%p\n" , + status, tag, t)); + }if (unlikely (!t || !t->lldd_task || !t->dev))return ;
@@ -3070,7 +3090,7 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) ts->open_rej_reason =SAS_OREJ_RSVD_RETRY ;break ;default : -PM8001_IO_DBG (pm8001_ha, +PM8001_DEVIO_DBG (pm8001_ha,pm8001_printk ("Unknown status 0x%x\n" , status)); ts->resp =SAS_TASK_COMPLETE ; ts->stat =SAS_DEV_NO_RESPONSE ;
@@ -3416,7 +3436,7 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)pm8001_get_lrate_mode (phy, link_rate);break ;default : -PM8001_MSG_DBG (pm8001_ha, +PM8001_DEVIO_DBG (pm8001_ha,pm8001_printk ("unknown device type(%x)\n" , deviceType));break ; }
@@ -3463,7 +3483,7 @@ hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)struct sas_ha_struct *sas_ha = pm8001_ha->sas;struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];unsigned long flags; -PM8001_MSG_DBG (pm8001_ha, +PM8001_DEVIO_DBG (pm8001_ha,pm8001_printk ("HW_EVENT_SATA_PHY_UP port id = %d," " phy id = %d\n" , port_id, phy_id)); port->port_state = portstate;
@@ -3541,7 +3561,7 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb)break ;default : port->port_attached =0 ; -PM8001_MSG_DBG (pm8001_ha, +PM8001_DEVIO_DBG (pm8001_ha,pm8001_printk (" phy Down and(default) = %x\n" , portstate));break ;
@@ -3689,7 +3709,7 @@ int pm8001_mpi_fw_flash_update_resp(struct pm8001_hba_info *pm8001_ha, pm8001_printk(": FLASH_UPDATE_DISABLED\n"));break ;default : -PM8001_MSG_DBG (pm8001_ha, +PM8001_DEVIO_DBG (pm8001_ha,pm8001_printk ("No matched status = %d\n" , status));break ; }
@@ -3805,8 +3825,9 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb)struct sas_ha_struct *sas_ha = pm8001_ha->sas;struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];struct asd_sas_phy *sas_phy = sas_ha->sas_phy[phy_id]; -PM8001_MSG_DBG (pm8001_ha, -pm8001_printk ("outbound queue HW event & event type : " )); +PM8001_DEVIO_DBG (pm8001_ha,pm8001_printk ( +"SPC HW event for portid:%d, phyid:%d, event:%x, status:%x\n" , + port_id, phy_id, eventType, status));switch (eventType) {case HW_EVENT_PHY_START_STATUS : PM8001_MSG_DBG(pm8001_ha,
@@ -3990,7 +4011,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) pm8001_printk("EVENT_BROADCAST_ASYNCH_EVENT\n"));break ;default : -PM8001_MSG_DBG (pm8001_ha, +PM8001_DEVIO_DBG (pm8001_ha,pm8001_printk ("Unknown event type = %x\n" , eventType));break ; }
@@ -4161,7 +4182,7 @@ static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb) pm8001_printk("OPC_OUB_SAS_RE_INITIALIZE\n"));break ;default : -PM8001_MSG_DBG (pm8001_ha, +PM8001_DEVIO_DBG (pm8001_ha,pm8001_printk ("Unknown outbound Queue IOMB OPC = %x\n" , opc));break ;
@@ -4649,6 +4670,9 @@ static irqreturn_t pm8001_chip_isr(struct pm8001_hba_info *pm8001_ha, u8 vec) {pm8001_chip_interrupt_disable (pm8001_ha, vec); +PM8001_DEVIO_DBG (pm8001_ha,pm8001_printk ( +"irq vec %d, ODMR:0x%x\n" , + vec,pm8001_cr32 (pm8001_ha,0 ,0x30 )));process_oq (pm8001_ha, vec);pm8001_chip_interrupt_enable (pm8001_ha, vec);return IRQ_HANDLED ;
@@ -4960,6 +4984,8 @@ pm8001_chip_fw_flash_update_req(struct pm8001_hba_info *pm8001_ha,if (!fw_control_context)return -ENOMEM ; fw_control = (struct fw_control_info *)&ioctl_payload->func_specific; +PM8001_DEVIO_DBG (pm8001_ha,pm8001_printk ( +"dma fw_control context input length :%x\n" , fw_control->len));memcpy (buffer, fw_control->buffer, fw_control->len); flash_update_info.sgl.addr =cpu_to_le64 (phys_addr); flash_update_info.sgl.im_len.len =cpu_to_le32 (fw_control->len);
drivers/scsi/pm8001/pm8001_init.c +5 -1
@@ -42,6 +42,10 @@#include "pm8001_sas.h" #include "pm8001_chips.h" +static ulong logging_level =PM8001_FAIL_LOGGING |PM8001_IOERR_LOGGING ; +module_param (logging_level, ulong,0644 ); +MODULE_PARM_DESC (logging_level," bits for enabling logging info." ); +static struct scsi_transport_template *pm8001_stt;/**
@@ -466,7 +470,7 @@ static struct pm8001_hba_info *pm8001_pci_alloc(struct pci_dev *pdev, pm8001_ha->sas = sha; pm8001_ha->shost = shost; pm8001_ha->id = pm8001_id++; - pm8001_ha->logging_level =0x01 ; + pm8001_ha->logging_level = logging_level;sprintf (pm8001_ha->name,"%s%d" ,DRV_NAME , pm8001_ha->id);/* IOMB size is 128 for 8088/89 controllers */ if (pm8001_ha->chip_id != chip_8001)
drivers/scsi/pm8001/pm8001_sas.c +4 -2
@@ -119,7 +119,7 @@ int pm8001_mem_alloc(struct pci_dev *pdev, void **virt_addr, mem_virt_alloc =dma_alloc_coherent (&pdev->dev, mem_size + align, &mem_dma_handle,GFP_KERNEL );if (!mem_virt_alloc) { -pm8001_printk ("memory allocation error\n" ); +pr_err ("pm80xx: memory allocation error\n" );return -1 ; } *pphys_addr = mem_dma_handle;
@@ -249,6 +249,8 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,spin_unlock_irqrestore (&pm8001_ha->lock, flags);return 0 ;default : +PM8001_DEVIO_DBG (pm8001_ha, +pm8001_printk ("func 0x%x\n" , func)); rc = -EOPNOTSUPP ; }msleep (300 );
@@ -1179,7 +1181,7 @@ int pm8001_query_task(struct sas_task *task)break ; } } -pm8001_printk (":rc= %d\n" , rc); +pr_err ("pm80xx: rc= %d\n" , rc);return rc; }
drivers/scsi/pm8001/pm8001_sas.h +13 -2
@@ -66,8 +66,11 @@#define PM8001_EH_LOGGING 0x10/* libsas EH function logging*/ #define PM8001_IOCTL_LOGGING 0x20/* IOCTL message logging */ #define PM8001_MSG_LOGGING 0x40/* misc message logging */ -#define pm8001_printk(format, arg...) printk(KERN_INFO "pm80xx %s %d:" \ - format, __func__, __LINE__, ## arg) +#define PM8001_DEV_LOGGING 0x80/* development message logging */ +#define PM8001_DEVIO_LOGGING 0x100/* development io message logging */ +#define PM8001_IOERR_LOGGING 0x200/* development io err message logging */ +#define pm8001_printk(format, arg...) pr_info("%s:: %s %d:" \ + format, pm8001_ha->name, __func__, __LINE__, ## arg)#define PM8001_CHECK_LOGGING (HBA ,LEVEL ,CMD ) \ do { \ if (unlikely(HBA->logging_level & LEVEL)) \
@@ -97,6 +100,14 @@ do { \#define PM8001_MSG_DBG (HBA ,CMD ) \ PM8001_CHECK_LOGGING(HBA, PM8001_MSG_LOGGING, CMD) +#define PM8001_DEV_DBG (HBA ,CMD ) \ + PM8001_CHECK_LOGGING(HBA, PM8001_DEV_LOGGING, CMD) + +#define PM8001_DEVIO_DBG (HBA ,CMD ) \ + PM8001_CHECK_LOGGING(HBA, PM8001_DEVIO_LOGGING, CMD) + +#define PM8001_IOERR_DBG (HBA ,CMD ) \ + PM8001_CHECK_LOGGING(HBA, PM8001_IOERR_LOGGING, CMD)#define PM8001_USE_TASKLET #define PM8001_USE_MSIX
drivers/scsi/pm8001/pm80xx_hwi.c +104 -14
280 lines not on this page · raw message
Signature · 1 line
2.16.3
PATCH v2 6/13 pm80xx : Increase timeout for pm80xx mpi_uninit_check.
In reply to Deepak UkeyFrom: ianyar <[email protected]>
The function mpi_uninit_check takes longer for inbound doorbell register to be cleared. Increased the timeout substantially so that the driver does not fail to load.
--- drivers/scsi/pm8001/pm80xx_hwi.c | 4 ++-- drivers/scsi/pm8001/pm80xx_hwi.h | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-)
drivers/scsi/pm8001/pm80xx_hwi.c +2 -2
@@ -735,9 +735,9 @@ static int mpi_init_check(struct pm8001_hba_info *pm8001_ha)pm8001_cw32 (pm8001_ha,0 ,MSGU_IBDB_SET , SPCv_MSGU_CFG_TABLE_UPDATE);/* wait until Inbound DoorBell Clear Register toggled */ if (IS_SPCV_12G (pm8001_ha->pdev)) { - max_wait_count =4 *1000 *1000 ;/* 4 sec */ + max_wait_count =SPCV_DOORBELL_CLEAR_TIMEOUT ; }else { - max_wait_count =2 *1000 *1000 ;/* 2 sec */ + max_wait_count =SPC_DOORBELL_CLEAR_TIMEOUT ; } do { udelay(1);
drivers/scsi/pm8001/pm80xx_hwi.h +3 -0
@@ -220,6 +220,9 @@#define SAS_DOPNRJT_RTRY_TMO 128#define SAS_COPNRJT_RTRY_TMO 128 +#define SPCV_DOORBELL_CLEAR_TIMEOUT (30 * 1000 * 1000)/* 30 sec */ +#define SPC_DOORBELL_CLEAR_TIMEOUT (15 * 1000 * 1000)/* 15 sec */ +/* Making ORR bigger than IT NEXUS LOSS which is 2000000us = 2 second. Assuming a bigger value 3 second, 3000000/128 = 23437.5 where 128
Signature · 1 line
2.16.3
PATCH v2 7/13 pm80xx : Fix dereferencing dangling pointer.
In reply to Deepak UkeyFrom: Vikram Auradkar <[email protected]>
sas_task structure should not be used after task_done is called. If the device is gone or not attached, we call task_done on t and continue to use in the sas_task in rest of the function. task_done is pointing to sas_ata_task_done, may free the memory associated with the task before returning.
--- drivers/scsi/pm8001/pm8001_sas.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
drivers/scsi/pm8001/pm8001_sas.c +6 -6
@@ -388,6 +388,7 @@ static int pm8001_task_exec(struct sas_task *task,struct pm8001_ccb_info *ccb;u32 tag =0xdeadbeef , rc =0 , n_elem =0 ;unsigned long flags =0 ; +enum sas_protocol task_proto = t->task_proto;if (!dev->port) {struct task_status_struct *tsm = &t->task_status;
@@ -412,7 +413,7 @@ static int pm8001_task_exec(struct sas_task *task, pm8001_dev = dev->lldd_dev; port = &pm8001_ha->port[sas_find_local_port_id (dev)];if (DEV_IS_GONE (pm8001_dev) || !port->port_attached) { -if (sas_protocol_ata (t->task_proto)) { +if (sas_protocol_ata (task_proto)) {struct task_status_struct *ts = &t->task_status; ts->resp =SAS_TASK_UNDELIVERED ; ts->stat =SAS_PHY_DOWN ;
@@ -434,7 +435,7 @@ static int pm8001_task_exec(struct sas_task *task, goto err_out; ccb = &pm8001_ha->ccb_info[tag]; -if (!sas_protocol_ata (t->task_proto)) { +if (!sas_protocol_ata (task_proto)) {if (t->num_scatter) { n_elem = dma_map_sg(pm8001_ha->dev, t->scatter,
@@ -454,7 +455,7 @@ static int pm8001_task_exec(struct sas_task *task, ccb->ccb_tag = tag; ccb->task = t; ccb->device = pm8001_dev; -switch (t->task_proto) { +switch (task_proto) {case SAS_PROTOCOL_SMP : rc =pm8001_task_prep_smp (pm8001_ha, ccb);break ;
@@ -471,8 +472,7 @@ static int pm8001_task_exec(struct sas_task *task,break ;default :dev_printk (KERN_ERR , pm8001_ha->dev, -"unknown sas_task proto: 0x%x\n" , - t->task_proto); +"unknown sas_task proto: 0x%x\n" , task_proto); rc = -EINVAL ;break ; }
@@ -495,7 +495,7 @@ static int pm8001_task_exec(struct sas_task *task,pm8001_tag_free (pm8001_ha, tag); err_out:dev_printk (KERN_ERR , pm8001_ha->dev,"pm8001 exec failed[%d]!\n" , rc); -if (!sas_protocol_ata (t->task_proto)) +if (!sas_protocol_ata (task_proto))if (n_elem)dma_unmap_sg (pm8001_ha->dev, t->scatter, t->num_scatter, t->data_dir);
Signature · 1 line
2.16.3
PATCH v2 8/13 pm80xx : Fix command issue sizing.
In reply to Deepak UkeyFrom: peter chang <[email protected]>
The commands to the controller are sent in fixed sized chunks which are set per-chip-generation and stashed in iomb_size. The driver fills in structs matching the register layout and memcpy this to memory shared with the controller. however, there are two problem cases:
1)Things like phy_start_req are too large because they share the sas_identify_frame definition with libsas, and it includes the crc word. this means that it's overwriting the start of the next command block, that's ok except if it happens at the end of the shared memory area.
2)Things like set_nvm_data_req which are shared between the HAL layers. this means that it's sending 'random' data for things that are in the reserved area. so far we haven't found a case where the controller FW cares, but sending possible gibberish (for most of the structures this is in the reserved area so previously zeroed) is not recommended.
--- drivers/scsi/pm8001/pm8001_hwi.c | 69 ++++++++++++++++++++++++++-------------- drivers/scsi/pm8001/pm8001_sas.h | 3 +- drivers/scsi/pm8001/pm80xx_hwi.c | 47 +++++++++++++++++---------- 3 files changed, 79 insertions(+), 40 deletions(-)
drivers/scsi/pm8001/pm8001_hwi.c +46 -23
@@ -1336,10 +1336,13 @@ int pm8001_mpi_msg_free_get(struct inbound_queue_table *circularQ,* @circularQ: the inbound queue we want to transfer to HBA. * @opCode: the operation code represents commands which LLDD and fw recognized. * @payload: the command payload of each operation command. +* @nb: size in bytes of the command payload +* @responseQueue: queue to interrupt on w/ command response (if any) */ int pm8001_mpi_build_cmd (struct pm8001_hba_info *pm8001_ha,struct inbound_queue_table *circularQ, -u32 opCode,void *payload,u32 responseQueue) +u32 opCode,void *payload,size_t nb, +u32 responseQueue) {u32 Header =0 , hpriority =0 , bc =1 , category =0x02 ;void *pMessage;
@@ -1350,10 +1353,13 @@ int pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha, pm8001_printk("No free mpi buffer\n"));return -ENOMEM ; } -BUG_ON (!payload); -/*Copy to the payload*/ -memcpy (pMessage, payload, (pm8001_ha->iomb_size - -sizeof (struct mpi_msg_hdr ))); + +if (nb > (pm8001_ha->iomb_size -sizeof (struct mpi_msg_hdr ))) + nb = pm8001_ha->iomb_size -sizeof (struct mpi_msg_hdr ); +memcpy (pMessage, payload, nb); +if (nb +sizeof (struct mpi_msg_hdr ) < pm8001_ha->iomb_size) +memset (pMessage + nb,0 , pm8001_ha->iomb_size - + (nb +sizeof (struct mpi_msg_hdr )));/*Build the header*/ Header = ((1 << 31) | (hpriority << 30) | ((bc & 0x1f) << 24)
@@ -1763,7 +1769,8 @@ static void pm8001_send_abort_all(struct pm8001_hba_info *pm8001_ha, task_abort.device_id =cpu_to_le32 (pm8001_ha_dev->device_id); task_abort.tag =cpu_to_le32 (ccb_tag); - ret =pm8001_mpi_build_cmd (pm8001_ha, circularQ, opc, &task_abort,0 ); + ret =pm8001_mpi_build_cmd (pm8001_ha, circularQ, opc, &task_abort, +sizeof (task_abort),0 );if (ret)pm8001_tag_free (pm8001_ha, ccb_tag);
@@ -1836,7 +1843,8 @@ static void pm8001_send_read_log(struct pm8001_hba_info *pm8001_ha, sata_cmd.ncqtag_atap_dir_m |= ((0x1 <<7 ) | (0x5 <<9 ));memcpy (&sata_cmd.sata_fis, &fis,sizeof (struct host_to_dev_fis )); - res =pm8001_mpi_build_cmd (pm8001_ha, circularQ, opc, &sata_cmd,0 ); + res =pm8001_mpi_build_cmd (pm8001_ha, circularQ, opc, &sata_cmd, +sizeof (sata_cmd),0 );if (res) {sas_free_task (task);pm8001_tag_free (pm8001_ha, ccb_tag);
@@ -3375,7 +3383,8 @@ static void pm8001_hw_event_ack_req(struct pm8001_hba_info *pm8001_ha, ((phyId & 0x0F) << 4) | (port_id & 0x0F)); payload.param0 =cpu_to_le32 (param0); payload.param1 =cpu_to_le32 (param1); -pm8001_mpi_build_cmd (pm8001_ha, circularQ, opc, &payload,0 ); +pm8001_mpi_build_cmd (pm8001_ha, circularQ, opc, &payload, +sizeof (payload),0 ); } static int pm8001_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha,
@@ -4305,7 +4314,7 @@ static int pm8001_chip_smp_req(struct pm8001_hba_info *pm8001_ha,cpu_to_le32 ((u32 )sg_dma_len (&task->smp_task.smp_resp)-4 );build_smp_cmd (pm8001_dev->device_id, smp_cmd.tag, &smp_cmd); rc =pm8001_mpi_build_cmd (pm8001_ha, circularQ, opc, - (u32 *)&smp_cmd,0 ); + &smp_cmd,sizeof (smp_cmd),0 );if (rc) goto err_out_2;
@@ -4373,7 +4382,8 @@ static int pm8001_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha, ssp_cmd.len =cpu_to_le32 (task->total_xfer_len); ssp_cmd.esgl =0 ; } - ret =pm8001_mpi_build_cmd (pm8001_ha, circularQ, opc, &ssp_cmd,0 ); + ret =pm8001_mpi_build_cmd (pm8001_ha, circularQ, opc, &ssp_cmd, +sizeof (ssp_cmd),0 );return ret; }
@@ -4482,7 +4492,8 @@ static int pm8001_chip_sata_req(struct pm8001_hba_info *pm8001_ha, } } - ret =pm8001_mpi_build_cmd (pm8001_ha, circularQ, opc, &sata_cmd,0 ); + ret =pm8001_mpi_build_cmd (pm8001_ha, circularQ, opc, &sata_cmd, +sizeof (sata_cmd),0 );return ret; }
@@ -4517,7 +4528,8 @@ pm8001_chip_phy_start_req(struct pm8001_hba_info *pm8001_ha, u8 phy_id)memcpy (payload.sas_identify.sas_addr, pm8001_ha->sas_addr,SAS_ADDR_SIZE ); payload.sas_identify.phy_id = phy_id; - ret =pm8001_mpi_build_cmd (pm8001_ha, circularQ, opcode, &payload,0 ); + ret =pm8001_mpi_build_cmd (pm8001_ha, circularQ, opcode, &payload, +sizeof (payload),0 );return ret; }
@@ -4539,7 +4551,8 @@ static int pm8001_chip_phy_stop_req(struct pm8001_hba_info *pm8001_ha,memset (&payload,0 ,sizeof (payload)); payload.tag =cpu_to_le32 (tag); payload.phy_id =cpu_to_le32 (phy_id); - ret =pm8001_mpi_build_cmd (pm8001_ha, circularQ, opcode, &payload,0 ); + ret =pm8001_mpi_build_cmd (pm8001_ha, circularQ, opcode, &payload, +sizeof (payload),0 );return ret; }
@@ -4598,7 +4611,8 @@ static int pm8001_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha,cpu_to_le32 (ITNT | (firstBurstSize *0x10000 ));memcpy (payload.sas_addr, pm8001_dev->sas_device->sas_addr,SAS_ADDR_SIZE ); - rc =pm8001_mpi_build_cmd (pm8001_ha, circularQ, opc, &payload,0 ); + rc =pm8001_mpi_build_cmd (pm8001_ha, circularQ, opc, &payload, +sizeof (payload),0 );return rc; }
@@ -4619,7 +4633,8 @@ int pm8001_chip_dereg_dev_req(struct pm8001_hba_info *pm8001_ha, payload.device_id =cpu_to_le32 (device_id);PM8001_MSG_DBG (pm8001_ha,pm8001_printk ("unregister device device_id = %d\n" , device_id)); - ret =pm8001_mpi_build_cmd (pm8001_ha, circularQ, opc, &payload,0 ); + ret =pm8001_mpi_build_cmd (pm8001_ha, circularQ, opc, &payload, +sizeof (payload),0 );return ret; }
@@ -4642,7 +4657,8 @@ static int pm8001_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha, payload.tag =cpu_to_le32 (1 ); payload.phyop_phyid =cpu_to_le32 (((phy_op &0xff ) <<8 ) | (phyId &0x0F )); - ret =pm8001_mpi_build_cmd (pm8001_ha, circularQ, opc, &payload,0 ); + ret =pm8001_mpi_build_cmd (pm8001_ha, circularQ, opc, &payload, +sizeof (payload),0 );return ret; }
@@ -4696,7 +4712,8 @@ static int send_task_abort(struct pm8001_hba_info *pm8001_ha, u32 opc, task_abort.device_id =cpu_to_le32 (dev_id); task_abort.tag =cpu_to_le32 (cmd_tag); } - ret =pm8001_mpi_build_cmd (pm8001_ha, circularQ, opc, &task_abort,0 ); + ret =pm8001_mpi_build_cmd (pm8001_ha, circularQ, opc, &task_abort, +sizeof (task_abort),0 );return ret; }
@@ -4753,7 +4770,8 @@ int pm8001_chip_ssp_tm_req(struct pm8001_hba_info *pm8001_ha,if (pm8001_ha->chip_id != chip_8001) sspTMCmd.ds_ads_m =0x08 ; circularQ = &pm8001_ha->inbnd_q_tbl[0 ]; - ret =pm8001_mpi_build_cmd (pm8001_ha, circularQ, opc, &sspTMCmd,0 ); + ret =pm8001_mpi_build_cmd (pm8001_ha, circularQ, opc, &sspTMCmd, +sizeof (sspTMCmd),0 );return ret; }
@@ -4843,7 +4861,8 @@ int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha,default :break ; } - rc =pm8001_mpi_build_cmd (pm8001_ha, circularQ, opc, &nvmd_req,0 ); + rc =pm8001_mpi_build_cmd (pm8001_ha, circularQ, opc, &nvmd_req, +sizeof (nvmd_req),0 );if (rc) {kfree (fw_control_context);pm8001_tag_free (pm8001_ha, tag);
@@ -4927,7 +4946,8 @@ int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha,default :break ; } - rc =pm8001_mpi_build_cmd (pm8001_ha, circularQ, opc, &nvmd_req,0 ); + rc =pm8001_mpi_build_cmd (pm8001_ha, circularQ, opc, &nvmd_req, +sizeof (nvmd_req),0 );if (rc) {kfree (fw_control_context);pm8001_tag_free (pm8001_ha, tag);
@@ -4962,7 +4982,8 @@ pm8001_chip_fw_flash_update_build(struct pm8001_hba_info *pm8001_ha,cpu_to_le32 (lower_32_bits (le64_to_cpu (info->sgl.addr))); payload.sgl_addr_hi =cpu_to_le32 (upper_32_bits (le64_to_cpu (info->sgl.addr))); - ret =pm8001_mpi_build_cmd (pm8001_ha, circularQ, opc, &payload,0 ); + ret =pm8001_mpi_build_cmd (pm8001_ha, circularQ, opc, &payload, +sizeof (payload),0 );return ret; }
@@ -5109,7 +5130,8 @@ pm8001_chip_set_dev_state_req(struct pm8001_hba_info *pm8001_ha, payload.tag =cpu_to_le32 (tag); payload.device_id =cpu_to_le32 (pm8001_dev->device_id); payload.nds =cpu_to_le32 (state); - rc =pm8001_mpi_build_cmd (pm8001_ha, circularQ, opc, &payload,0 ); + rc =pm8001_mpi_build_cmd (pm8001_ha, circularQ, opc, &payload, +sizeof (payload),0 );return rc; }
@@ -5134,7 +5156,8 @@ pm8001_chip_sas_re_initialization(struct pm8001_hba_info *pm8001_ha) payload.SSAHOLT =cpu_to_le32 (0xd <<25 ); payload.sata_hol_tmo =cpu_to_le32 (80 ); payload.open_reject_cmdretries_data_retries =cpu_to_le32 (0xff00ff ); - rc =pm8001_mpi_build_cmd (pm8001_ha, circularQ, opc, &payload,0 ); + rc =pm8001_mpi_build_cmd (pm8001_ha, circularQ, opc, &payload, +sizeof (payload),0 );if (rc)pm8001_tag_free (pm8001_ha, tag);return rc;
drivers/scsi/pm8001/pm8001_sas.h +2 -1
@@ -674,7 +674,8 @@ int pm8001_mem_alloc(struct pci_dev *pdev, void **virt_addr,void pm8001_chip_iounmap (struct pm8001_hba_info *pm8001_ha);int pm8001_mpi_build_cmd (struct pm8001_hba_info *pm8001_ha,struct inbound_queue_table *circularQ, -u32 opCode,void *payload,u32 responseQueue); +u32 opCode,void *payload,size_t nb, +u32 responseQueue);int pm8001_mpi_msg_free_get (struct inbound_queue_table *circularQ,u16 messageSize,void **messagePtr); u32 pm8001_mpi_msg_free_set(struct pm8001_hba_info *pm8001_ha, void *pMsg,
drivers/scsi/pm8001/pm80xx_hwi.c +31 -16
137 lines not on this page · raw message
Signature · 1 line
2.16.3
PATCH v2 9/13 pm80xx : Cleanup command when a reset times out.
In reply to Deepak UkeyFrom: peter chang <[email protected]>
Added the fix so the if driver properly sent the abort it try to remove it from the firmware's list of outstanding commands regardless of the abort status. This means that the task gets free-ed 'now' rather than possibly getting free-ed later when the scsi layer thinks it's leaked but still valid.
--- drivers/scsi/pm8001/pm8001_sas.c | 50 +++++++++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 13 deletions(-)
drivers/scsi/pm8001/pm8001_sas.c +37 -13
@@ -1204,8 +1204,8 @@ int pm8001_abort_task(struct sas_task *task) pm8001_dev = dev->lldd_dev; pm8001_ha =pm8001_find_ha_by_dev (dev); phy_id = pm8001_dev->attached_phy; - rc =pm8001_find_tag (task, &tag); -if (rc ==0 ) { + ret =pm8001_find_tag (task, &tag); +if (ret ==0 ) {pm8001_printk ("no tag for task:%p\n" , task);return TMF_RESP_FUNC_FAILED ; }
@@ -1243,26 +1243,50 @@ int pm8001_abort_task(struct sas_task *task)/* 2. Send Phy Control Hard Reset */ reinit_completion (&completion); + phy->port_reset_status =PORT_RESET_TMO ; phy->reset_success = false; phy->enable_completion = &completion; phy->reset_completion = &completion_reset; ret =PM8001_CHIP_DISP ->phy_ctl_req (pm8001_ha, phy_id,PHY_HARD_RESET ); -if (ret) - goto out; -PM8001_MSG_DBG (pm8001_ha, -pm8001_printk ("Waiting for local phy ctl\n" )); -wait_for_completion (&completion); -if (!phy->reset_success) +if (ret) { + phy->enable_completion =NULL ; + phy->reset_completion =NULL ; goto out; + } -/* 3. Wait for Port Reset complete / Port reset TMO */ +/* In the case of the reset timeout/fail we still +* abort the command at the firmware. The assumption +* here is that the drive is off doing something so +* that it's not processing requests, and we want to +* avoid getting a completion for this and either +* leaking the task in libsas or losing the race and +* getting a double free. +*/ PM8001_MSG_DBG (pm8001_ha, +pm8001_printk ("Waiting for local phy ctl\n" )); + ret =wait_for_completion_timeout (&completion, +PM8001_TASK_TIMEOUT *HZ ); +if (!ret || !phy->reset_success) { + phy->enable_completion =NULL ; + phy->reset_completion =NULL ; + }else { +/* 3. Wait for Port Reset complete or +* Port reset TMO +*/ +PM8001_MSG_DBG (pm8001_ha,pm8001_printk ("Waiting for Port reset\n" )); -wait_for_completion (&completion_reset); -if (phy->port_reset_status) { -pm8001_dev_gone_notify (dev); - goto out; + ret =wait_for_completion_timeout ( + &completion_reset, +PM8001_TASK_TIMEOUT *HZ ); +if (!ret) + phy->reset_completion =NULL ; +WARN_ON (phy->port_reset_status == +PORT_RESET_TMO ); +if (phy->port_reset_status ==PORT_RESET_TMO ) { +pm8001_dev_gone_notify (dev); + goto out; + } }/*
Signature · 1 line
2.16.3
Re: [PATCH V2 09/13] pm80xx : Cleanup command when a reset times out.
Quoted 9 lines · Deepak Ukey
From: peter chang <[email protected]>
Added the fix so the if driver properly sent the abort it try to remove it from the firmware's list of outstanding commands regardless of the abort status. This means that the task gets free-ed 'now' rather than possibly getting free-ed later when the scsi layer thinks it's leaked but still valid.
Quoted 3 lines
Signed-off-by peter chang <[email protected]>Signed-off-by Deepak Ukey <[email protected]>Signed-off-by Viswas G <[email protected]>
Thanks
Quoted 84 lines
--- drivers/scsi/pm8001/pm8001_sas.c | 50 +++++++++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 13 deletions(-)drivers/scsi/pm8001/pm8001_sas.c +37
-14@@ -1204,8 +1204,8 @@ int pm8001_abort_task(struct sas_task *task) pm8001_dev = dev->lldd_dev; pm8001_ha =pm8001_find_ha_by_dev (dev); phy_id = pm8001_dev->attached_phy; - rc =pm8001_find_tag (task, &tag); -if (rc ==0 ) { + ret =pm8001_find_tag (task, &tag); +if (ret ==0 ) {pm8001_printk ("no tag for task:%p\n" , task);return TMF_RESP_FUNC_FAILED ; }@@ -1243,26 +1243,50 @@ int pm8001_abort_task(struct sas_task *task)/* 2. Send Phy Control Hard Reset */ reinit_completion (&completion); + phy->port_reset_status =PORT_RESET_TMO ; phy->reset_success = false; phy->enable_completion = &completion; phy->reset_completion = &completion_reset; ret =PM8001_CHIP_DISP ->phy_ctl_req (pm8001_ha, phy_id,PHY_HARD_RESET ); -if (ret) - goto out; -PM8001_MSG_DBG (pm8001_ha, -pm8001_printk ("Waiting for local phy ctl\n" )); -wait_for_completion (&completion); -if (!phy->reset_success) +if (ret) { + phy->enable_completion =NULL ; + phy->reset_completion =NULL ; goto out; + } -/* 3. Wait for Port Reset complete / Port reset TMO */ +/* In the case of the reset timeout/fail we still +* abort the command at the firmware. The assumption +* here is that the drive is off doing something so +* that it's not processing requests, and we want to +* avoid getting a completion for this and either +* leaking the task in libsas or losing the race and +* getting a double free. +*/ PM8001_MSG_DBG (pm8001_ha, +pm8001_printk ("Waiting for local phy ctl\n" )); + ret =wait_for_completion_timeout (&completion, +PM8001_TASK_TIMEOUT *HZ ); +if (!ret || !phy->reset_success) { + phy->enable_completion =NULL ; + phy->reset_completion =NULL ; + }else { +/* 3. Wait for Port Reset complete or +* Port reset TMO +*/ +PM8001_MSG_DBG (pm8001_ha,pm8001_printk ("Waiting for Port reset\n" )); -wait_for_completion (&completion_reset); -if (phy->port_reset_status) { -pm8001_dev_gone_notify (dev); - goto out; + ret =wait_for_completion_timeout ( + &completion_reset, +PM8001_TASK_TIMEOUT *HZ ); +if (!ret) + phy->reset_completion =NULL ; +WARN_ON (phy->port_reset_status == +PORT_RESET_TMO ); +if (phy->port_reset_status ==PORT_RESET_TMO ) { +pm8001_dev_gone_notify (dev); + goto out; + } }/* -- 2.16.3
PATCH v2 10/13 pm80xx : Do not request 12G sas speeds.
In reply to Deepak UkeyFrom: peter chang <[email protected]>
occasionally, 6G capable drives fail to train at 6G on links that look good from a signal-integrity perspective. PMC suggests configuring the port to not even expect 12G.
--- drivers/scsi/pm8001/pm8001_init.c | 17 +++++++++++++++++ drivers/scsi/pm8001/pm8001_sas.h | 1 + drivers/scsi/pm8001/pm80xx_hwi.c | 21 ++++----------------- 3 files changed, 22 insertions(+), 17 deletions(-)
drivers/scsi/pm8001/pm8001_init.c +17 -0
@@ -41,11 +41,20 @@#include <linux/slab.h> #include "pm8001_sas.h" #include "pm8001_chips.h" +#include "pm80xx_hwi.h" static ulong logging_level =PM8001_FAIL_LOGGING |PM8001_IOERR_LOGGING ;module_param (logging_level, ulong,0644 );MODULE_PARM_DESC (logging_level," bits for enabling logging info." ); +static ulong link_rate =LINKRATE_15 |LINKRATE_30 |LINKRATE_60 |LINKRATE_120 ; +module_param (link_rate, ulong,0644 ); +MODULE_PARM_DESC (link_rate,"Enable link rate.\n" +" 1: Link rate 1.5G\n" +" 2: Link rate 3.0G\n" +" 4: Link rate 6.0G\n" +" 8: Link rate 12.0G\n" ); +static struct scsi_transport_template *pm8001_stt;/**
@@ -471,6 +480,14 @@ 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; +if (link_rate >=1 && link_rate <=15 ) + pm8001_ha->link_rate = (link_rate <<8 ); +else { + pm8001_ha->link_rate =LINKRATE_15 |LINKRATE_30 | +LINKRATE_60 |LINKRATE_120 ; +PM8001_FAIL_DBG (pm8001_ha,pm8001_printk ( +"Setting link rate to default value\n" )); + }sprintf (pm8001_ha->name,"%s%d" ,DRV_NAME , pm8001_ha->id);/* IOMB size is 128 for 8088/89 controllers */ if (pm8001_ha->chip_id != chip_8001)
drivers/scsi/pm8001/pm8001_sas.h +1 -0
@@ -546,6 +546,7 @@ struct pm8001_hba_info {struct tasklet_struct tasklet[PM8001_MAX_MSIX_VEC ];#endif u32 logging_level; +u32 link_rate;u32 fw_status;u32 smp_exp_mode;bool controller_fatal_error;
drivers/scsi/pm8001/pm80xx_hwi.c +4 -17
@@ -37,6 +37,7 @@* POSSIBILITY OF SUCH DAMAGES. * */ +#include <linux/version.h> #include <linux/slab.h> #include "pm8001_sas.h" #include "pm80xx_hwi.h"
@@ -4565,23 +4566,9 @@ pm80xx_chip_phy_start_req(struct pm8001_hba_info *pm8001_ha, u8 phy_id)PM8001_INIT_DBG (pm8001_ha,pm8001_printk ("PHY START REQ for phy_id %d\n" , phy_id)); -/* -** [0:7] PHY Identifier -** [8:11] link rate 1.5G, 3G, 6G -** [12:13] link mode 01b SAS mode; 10b SATA mode; 11b Auto mode -** [14] 0b disable spin up hold; 1b enable spin up hold -** [15] ob no change in current PHY analig setup 1b enable using SPAST -*/ -if (!IS_SPCV_12G (pm8001_ha->pdev)) - payload.ase_sh_lm_slr_phyid =cpu_to_le32 (SPINHOLD_DISABLE | -LINKMODE_AUTO |LINKRATE_15 | -LINKRATE_30 |LINKRATE_60 | phy_id); -else - payload.ase_sh_lm_slr_phyid =cpu_to_le32 (SPINHOLD_DISABLE | -LINKMODE_AUTO |LINKRATE_15 | -LINKRATE_30 |LINKRATE_60 |LINKRATE_120 | - phy_id); + payload.ase_sh_lm_slr_phyid =cpu_to_le32 (SPINHOLD_DISABLE | +LINKMODE_AUTO | pm8001_ha->link_rate | phy_id);/* SSC Disable and SAS Analog ST configuration */ /** payload.ase_sh_lm_slr_phyid =
@@ -4594,7 +4581,7 @@ pm80xx_chip_phy_start_req(struct pm8001_hba_info *pm8001_ha, u8 phy_id) payload.sas_identify.dev_type =SAS_END_DEVICE ; payload.sas_identify.initiator_bits =SAS_PROTOCOL_ALL ;memcpy (payload.sas_identify.sas_addr, - &pm8001_ha->phy[phy_id].dev_sas_addr,SAS_ADDR_SIZE ); + &pm8001_ha->sas_addr,SAS_ADDR_SIZE ); payload.sas_identify.phy_id = phy_id; ret =pm8001_mpi_build_cmd (pm8001_ha, circularQ, opcode, &payload,sizeof (payload),0 );
Signature · 1 line
2.16.3
Re: [PATCH V2 10/13] pm80xx : Do not request 12G sas speeds.
Quoted 5 lines · Deepak Ukey
From: peter chang <[email protected]>
occasionally, 6G capable drives fail to train at 6G on links that look good from a signal-integrity perspective. PMC suggests configuring the port to not even expect 12G.
We can set the PHY max hw linkrate at 6Gbps via sysfs, but I assume that this is not good enough.
So could the driver has the intelligence to know the training failed, and reset the max linkrate accordingly and retry?
It just seems that adding a module parameter to set the max linkrate is a little heavy handed.
BTW, how is this handled in the phy control rate callback, pm8001_phy_control? Would 6Gbps be set as PHY hw linkrate?
Thanks,
John
Quoted 110 lines
Signed-off-by peter chang <[email protected]>Signed-off-by Deepak Ukey <[email protected]>Signed-off-by Viswas G <[email protected]>Acked-by Jack Wang <[email protected]>--- drivers/scsi/pm8001/pm8001_init.c | 17 +++++++++++++++++ drivers/scsi/pm8001/pm8001_sas.h | 1 + drivers/scsi/pm8001/pm80xx_hwi.c | 21 ++++----------------- 3 files changed, 22 insertions(+), 17 deletions(-)drivers/scsi/pm8001/pm8001_init.c +17
-0@@ -41,11 +41,20 @@#include <linux/slab.h> #include "pm8001_sas.h" #include "pm8001_chips.h" +#include "pm80xx_hwi.h" static ulong logging_level =PM8001_FAIL_LOGGING |PM8001_IOERR_LOGGING ;module_param (logging_level, ulong,0644 );MODULE_PARM_DESC (logging_level," bits for enabling logging info." ); +static ulong link_rate =LINKRATE_15 |LINKRATE_30 |LINKRATE_60 |LINKRATE_120 ; +module_param (link_rate, ulong,0644 ); +MODULE_PARM_DESC (link_rate,"Enable link rate.\n" +" 1: Link rate 1.5G\n" +" 2: Link rate 3.0G\n" +" 4: Link rate 6.0G\n" +" 8: Link rate 12.0G\n" ); +static struct scsi_transport_template *pm8001_stt;/** @@ -471,6 +480,14 @@ 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; +if (link_rate >=1 && link_rate <=15 ) + pm8001_ha->link_rate = (link_rate <<8 ); +else { + pm8001_ha->link_rate =LINKRATE_15 |LINKRATE_30 | +LINKRATE_60 |LINKRATE_120 ; +PM8001_FAIL_DBG (pm8001_ha,pm8001_printk ( +"Setting link rate to default value\n" )); + }sprintf (pm8001_ha->name,"%s%d" ,DRV_NAME , pm8001_ha->id);/* IOMB size is 128 for 8088/89 controllers */ if (pm8001_ha->chip_id != chip_8001)drivers/scsi/pm8001/pm8001_sas.h +1
-0@@ -546,6 +546,7 @@ struct pm8001_hba_info {struct tasklet_struct tasklet[PM8001_MAX_MSIX_VEC ];#endif u32 logging_level; +u32 link_rate;u32 fw_status;u32 smp_exp_mode;bool controller_fatal_error;drivers/scsi/pm8001/pm80xx_hwi.c +4
-17@@ -37,6 +37,7 @@* POSSIBILITY OF SUCH DAMAGES. * */ +#include <linux/version.h> #include <linux/slab.h> #include "pm8001_sas.h" #include "pm80xx_hwi.h" @@ -4565,23 +4566,9 @@ pm80xx_chip_phy_start_req(struct pm8001_hba_info *pm8001_ha, u8 phy_id)PM8001_INIT_DBG (pm8001_ha,pm8001_printk ("PHY START REQ for phy_id %d\n" , phy_id)); -/* -** [0:7] PHY Identifier -** [8:11] link rate 1.5G, 3G, 6G -** [12:13] link mode 01b SAS mode; 10b SATA mode; 11b Auto mode -** [14] 0b disable spin up hold; 1b enable spin up hold -** [15] ob no change in current PHY analig setup 1b enable using SPAST -*/ -if (!IS_SPCV_12G (pm8001_ha->pdev)) - payload.ase_sh_lm_slr_phyid =cpu_to_le32 (SPINHOLD_DISABLE | -LINKMODE_AUTO |LINKRATE_15 | -LINKRATE_30 |LINKRATE_60 | phy_id); -else - payload.ase_sh_lm_slr_phyid =cpu_to_le32 (SPINHOLD_DISABLE | -LINKMODE_AUTO |LINKRATE_15 | -LINKRATE_30 |LINKRATE_60 |LINKRATE_120 | - phy_id); + payload.ase_sh_lm_slr_phyid =cpu_to_le32 (SPINHOLD_DISABLE | +LINKMODE_AUTO | pm8001_ha->link_rate | phy_id);/* SSC Disable and SAS Analog ST configuration */ /** payload.ase_sh_lm_slr_phyid = @@ -4594,7 +4581,7 @@ pm80xx_chip_phy_start_req(struct pm8001_hba_info *pm8001_ha, u8 phy_id) payload.sas_identify.dev_type =SAS_END_DEVICE ; payload.sas_identify.initiator_bits =SAS_PROTOCOL_ALL ;memcpy (payload.sas_identify.sas_addr, - &pm8001_ha->phy[phy_id].dev_sas_addr,SAS_ADDR_SIZE ); + &pm8001_ha->sas_addr,SAS_ADDR_SIZE ); payload.sas_identify.phy_id = phy_id; ret =pm8001_mpi_build_cmd (pm8001_ha, circularQ, opcode, &payload,sizeof (payload),0 );
PATCH v2 11/13 pm80xx : Controller fatal error through sysfs.
In reply to Deepak UkeyFrom: Deepak Ukey <[email protected]>
Added support to check controller fatal error through sysfs.
--- drivers/scsi/pm8001/pm8001_ctl.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+)
drivers/scsi/pm8001/pm8001_ctl.c +20 -0
@@ -69,6 +69,25 @@ static ssize_t pm8001_ctl_mpi_interface_rev_show(struct device *cdev,static DEVICE_ATTR(interface_rev, S_IRUGO, pm8001_ctl_mpi_interface_rev_show, NULL); +/** +* controller_fatal_error_show - check controller is under fatal err +* @cdev: pointer to embedded class device +* @buf: the buffer returned +* +* A sysfs 'read only' shost attribute. +*/ +static ssize_t controller_fatal_error_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 ,"%d\n" , + pm8001_ha->controller_fatal_error); +} +static DEVICE_ATTR_RO (controller_fatal_error); +/** * pm8001_ctl_fw_version_show - firmware version * @cdev: pointer to embedded class device
@@ -804,6 +823,7 @@ static DEVICE_ATTR(update_fw, S_IRUGO|S_IWUSR|S_IWGRP, pm8001_show_update_fw, pm8001_store_update_fw);struct device_attribute *pm8001_host_attrs[] = { &dev_attr_interface_rev, + &dev_attr_controller_fatal_error, &dev_attr_fw_version, &dev_attr_update_fw, &dev_attr_aap_log,
Signature · 1 line
2.16.3
Re: [PATCH V2 11/13] pm80xx : Controller fatal error through sysfs.
Quoted 7 lines · Deepak Ukey
From: Deepak Ukey <[email protected]>
Added support to check controller fatal error through sysfs.
Signed-off-by Deepak Ukey <[email protected]>Signed-off-by Viswas G <[email protected]>
Quoted 45 lines
--- drivers/scsi/pm8001/pm8001_ctl.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+)drivers/scsi/pm8001/pm8001_ctl.c +20
-1@@ -69,6 +69,25 @@ static ssize_t pm8001_ctl_mpi_interface_rev_show(struct device *cdev,static DEVICE_ATTR(interface_rev, S_IRUGO, pm8001_ctl_mpi_interface_rev_show, NULL); +/** +* controller_fatal_error_show - check controller is under fatal err +* @cdev: pointer to embedded class device +* @buf: the buffer returned +* +* A sysfs 'read only' shost attribute. +*/ +static ssize_t controller_fatal_error_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 ,"%d\n" , + pm8001_ha->controller_fatal_error); +} +static DEVICE_ATTR_RO (controller_fatal_error); +/** * pm8001_ctl_fw_version_show - firmware version * @cdev: pointer to embedded class device @@ -804,6 +823,7 @@ static DEVICE_ATTR(update_fw, S_IRUGO|S_IWUSR|S_IWGRP, pm8001_show_update_fw, pm8001_store_update_fw);struct device_attribute *pm8001_host_attrs[] = { &dev_attr_interface_rev, + &dev_attr_controller_fatal_error, &dev_attr_fw_version, &dev_attr_update_fw, &dev_attr_aap_log, --2.16.3
PATCH v2 12/13 pm80xx : Tie the interrupt name to the module instance.
In reply to Deepak UkeyFrom: Vikram Auradkar <[email protected]>
With msix enabled, the interrupt instances are <prefix><index> where the prefix is fixed for all module instances, making it a little harder to track down what's what.
--- drivers/scsi/pm8001/pm8001_init.c | 11 ++++++----- drivers/scsi/pm8001/pm8001_sas.h | 2 ++ 2 files changed, 8 insertions(+), 5 deletions(-)
drivers/scsi/pm8001/pm8001_init.c +6 -5
@@ -894,7 +894,6 @@ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha)u32 number_of_intr;int flag =0 ;int rc; -static char intr_drvname[PM8001_MAX_MSIX_VEC ][sizeof (DRV_NAME )+3 ];/* SPCv controllers supports 64 msi-x */ if (pm8001_ha->chip_id == chip_8001) {
@@ -915,14 +914,16 @@ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha) rc, pm8001_ha->number_of_intr));for (i =0 ; i < number_of_intr; i++) { -snprintf (intr_drvname[i],sizeof (intr_drvname[0 ]), -DRV_NAME "%d" , i); +snprintf (pm8001_ha->intr_drvname[i], +sizeof (pm8001_ha->intr_drvname[0 ]), +"%s-%d" , pm8001_ha->name, i); pm8001_ha->irq_vector[i].irq_id = i; pm8001_ha->irq_vector[i].drv_inst = pm8001_ha; rc =request_irq (pci_irq_vector (pm8001_ha->pdev, i), pm8001_interrupt_handler_msix, flag, - intr_drvname[i], &(pm8001_ha->irq_vector[i])); + pm8001_ha->intr_drvname[i], + &(pm8001_ha->irq_vector[i]));if (rc) {for (j =0 ; j < i; j++) { free_irq(pci_irq_vector(pm8001_ha->pdev, i),
@@ -963,7 +964,7 @@ static u32 pm8001_request_irq(struct pm8001_hba_info *pm8001_ha) pm8001_ha->irq_vector[0 ].irq_id =0 ; pm8001_ha->irq_vector[0 ].drv_inst = pm8001_ha; rc =request_irq (pdev->irq, pm8001_interrupt_handler_intx,IRQF_SHARED , -DRV_NAME ,SHOST_TO_SAS_HA (pm8001_ha->shost)); + pm8001_ha->name,SHOST_TO_SAS_HA (pm8001_ha->shost));return rc; }
drivers/scsi/pm8001/pm8001_sas.h +2 -0
@@ -541,6 +541,8 @@ struct pm8001_hba_info {struct pm8001_ccb_info *ccb_info;#ifdef PM8001_USE_MSIX int number_of_intr;/*will be used in remove()*/ +char intr_drvname[PM8001_MAX_MSIX_VEC ] + [PM8001_NAME_LENGTH +1 +3 +1 ];#endif #ifdef PM8001_USE_TASKLET struct tasklet_struct tasklet[PM8001_MAX_MSIX_VEC ];
Signature · 1 line
2.16.3
PATCH v2 13/13 pm80xx : Modified the logic to collect fatal dump.
In reply to Deepak UkeyFrom: Deepak Ukey <[email protected]>
Added the correct method to collect the fatal dump.
--- drivers/scsi/pm8001/pm8001_sas.h | 3 + drivers/scsi/pm8001/pm80xx_hwi.c | 251 ++++++++++++++++++++++++++++++--------- 2 files changed, 195 insertions(+), 59 deletions(-)
drivers/scsi/pm8001/pm8001_sas.h +3 -0
@@ -152,6 +152,8 @@ struct pm8001_ioctl_payload {#define MPI_FATAL_EDUMP_TABLE_HANDSHAKE 0x0C/* FDDHSHK */ #define MPI_FATAL_EDUMP_TABLE_STATUS 0x10/* FDDTSTAT */ #define MPI_FATAL_EDUMP_TABLE_ACCUM_LEN 0x14/* ACCDDLEN */ +#define MPI_FATAL_EDUMP_TABLE_TOTAL_LEN 0x18/* TOTALLEN */ +#define MPI_FATAL_EDUMP_TABLE_SIGNATURE 0x1C/* SIGNITURE */ #define MPI_FATAL_EDUMP_HANDSHAKE_RDY 0x1#define MPI_FATAL_EDUMP_HANDSHAKE_BUSY 0x0#define MPI_FATAL_EDUMP_TABLE_STAT_RSVD 0x0
@@ -507,6 +509,7 @@ struct pm8001_hba_info {u32 forensic_last_offset;u32 fatal_forensic_shift_offset;u32 forensic_fatal_step; +u32 forensic_preserved_accumulated_transfer;u32 evtlog_ib_offset;u32 evtlog_ob_offset;void __iomem *msg_unit_tbl_addr;/*Message Unit Table Addr*/
drivers/scsi/pm8001/pm80xx_hwi.c +192 -59
350 lines not on this page · raw message
Signature · 1 line
2.16.3
Re: [PATCH V2 13/13] pm80xx : Modified the logic to collect fatal dump.
Quoted 8 lines · Deepak Ukey
From: Deepak Ukey <[email protected]>
Added the correct method to collect the fatal dump.
Signed-off-by Deepak Ukey <[email protected]>Signed-off-by Viswas G <[email protected]>Reported-by kbuild test robot <[email protected]>
Quoted 390 lines
--- drivers/scsi/pm8001/pm8001_sas.h | 3 + drivers/scsi/pm8001/pm80xx_hwi.c | 251 ++++++++++++++++++++++++++++++--------- 2 files changed, 195 insertions(+), 59 deletions(-)drivers/scsi/pm8001/pm8001_sas.h +3
-0@@ -152,6 +152,8 @@ struct pm8001_ioctl_payload {#define MPI_FATAL_EDUMP_TABLE_HANDSHAKE 0x0C/* FDDHSHK */ #define MPI_FATAL_EDUMP_TABLE_STATUS 0x10/* FDDTSTAT */ #define MPI_FATAL_EDUMP_TABLE_ACCUM_LEN 0x14/* ACCDDLEN */ +#define MPI_FATAL_EDUMP_TABLE_TOTAL_LEN 0x18/* TOTALLEN */ +#define MPI_FATAL_EDUMP_TABLE_SIGNATURE 0x1C/* SIGNITURE */ #define MPI_FATAL_EDUMP_HANDSHAKE_RDY 0x1#define MPI_FATAL_EDUMP_HANDSHAKE_BUSY 0x0#define MPI_FATAL_EDUMP_TABLE_STAT_RSVD 0x0@@ -507,6 +509,7 @@ struct pm8001_hba_info {u32 forensic_last_offset;u32 fatal_forensic_shift_offset;u32 forensic_fatal_step; +u32 forensic_preserved_accumulated_transfer;u32 evtlog_ib_offset;u32 evtlog_ob_offset;void __iomem *msg_unit_tbl_addr;/*Message Unit Table Addr*/ drivers/scsi/pm8001/pm80xx_hwi.c +192
-60@@ -76,7 +76,7 @@ void pm80xx_pci_mem_copy(struct pm8001_hba_info *pm8001_ha, u32 soffset, destination1 = (u32 *)destination;for (index =0 ; index < dw_count; index +=4 , destination1++) { - offset = (soffset + index /4 ); + offset = (soffset + index);if (offset < (64 *1024 )) { value =pm8001_cr32 (pm8001_ha, bus_base_number, offset); *destination1 =cpu_to_le32 (value);@@ -93,9 +93,12 @@ ssize_t pm80xx_get_fatal_dump(struct device *cdev,struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;void __iomem *fatal_table_address = pm8001_ha->fatal_tbl_addr;u32 accum_len , reg_val, index, *temp; +u32 status =1 ;unsigned long start;u8 *direct_data;char *fatal_error_data = buf; +u32 length_to_read; +u32 offset; pm8001_ha->forensic_info.data_buf.direct_data = buf;if (pm8001_ha->chip_id == chip_8001) {@@ -105,16 +108,35 @@ ssize_t pm80xx_get_fatal_dump(struct device *cdev,return (char *)pm8001_ha->forensic_info.data_buf.direct_data - (char *)buf; } +/* initialize variables for very first call from host application */ if (pm8001_ha->forensic_info.data_buf.direct_offset ==0 ) {PM8001_IO_DBG (pm8001_ha,pm8001_printk ("forensic_info TYPE_NON_FATAL..............\n" )); direct_data = (u8 *)fatal_error_data; pm8001_ha->forensic_info.data_type =TYPE_NON_FATAL ; pm8001_ha->forensic_info.data_buf.direct_len =SYSFS_OFFSET ; + pm8001_ha->forensic_info.data_buf.direct_offset =0 ; pm8001_ha->forensic_info.data_buf.read_len =0 ; + pm8001_ha->forensic_preserved_accumulated_transfer =0 ; - pm8001_ha->forensic_info.data_buf.direct_data = direct_data; +/* Write signature to fatal dump table */ +pm8001_mw32 (fatal_table_address, +MPI_FATAL_EDUMP_TABLE_SIGNATURE ,0x1234abcd ); + pm8001_ha->forensic_info.data_buf.direct_data = direct_data; +PM8001_IO_DBG (pm8001_ha, +pm8001_printk ("ossaHwCB: status1 %d\n" , status)); +PM8001_IO_DBG (pm8001_ha, +pm8001_printk ("ossaHwCB: read_len 0x%x\n" , + pm8001_ha->forensic_info.data_buf.read_len)); +PM8001_IO_DBG (pm8001_ha, +pm8001_printk ("ossaHwCB: direct_len 0x%x\n" , + pm8001_ha->forensic_info.data_buf.direct_len)); +PM8001_IO_DBG (pm8001_ha, +pm8001_printk ("ossaHwCB: direct_offset 0x%x\n" , + pm8001_ha->forensic_info.data_buf.direct_offset)); + } +if (pm8001_ha->forensic_info.data_buf.direct_offset ==0 ) {/* start to get data */ /* Program the MEMBASE II Shifting Register with 0x00.*/ pm8001_cw32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER,@@ -127,30 +149,66 @@ ssize_t pm80xx_get_fatal_dump(struct device *cdev,/* Read until accum_len is retrived */ accum_len =pm8001_mr32 (fatal_table_address,MPI_FATAL_EDUMP_TABLE_ACCUM_LEN ); -PM8001_IO_DBG (pm8001_ha,pm8001_printk ("accum_len 0x%x\n" , - accum_len)); +/* Determine length of data between previously stored transfer length +* and current accumulated transfer length +*/ + length_to_read = + accum_len - pm8001_ha->forensic_preserved_accumulated_transfer; +PM8001_IO_DBG (pm8001_ha, +pm8001_printk ("get_fatal_spcv: accum_len 0x%x\n" , accum_len)); +PM8001_IO_DBG (pm8001_ha, +pm8001_printk ("get_fatal_spcv: length_to_read 0x%x\n" , + length_to_read)); +PM8001_IO_DBG (pm8001_ha, +pm8001_printk ("get_fatal_spcv: last_offset 0x%x\n" , + pm8001_ha->forensic_last_offset)); +PM8001_IO_DBG (pm8001_ha, +pm8001_printk ("get_fatal_spcv: read_len 0x%x\n" , + pm8001_ha->forensic_info.data_buf.read_len)); +PM8001_IO_DBG (pm8001_ha, +pm8001_printk ("get_fatal_spcv:: direct_len 0x%x\n" , + pm8001_ha->forensic_info.data_buf.direct_len)); +PM8001_IO_DBG (pm8001_ha, +pm8001_printk ("get_fatal_spcv:: direct_offset 0x%x\n" , + pm8001_ha->forensic_info.data_buf.direct_offset)); + +/* If accumulated length failed to read correctly fail the attempt.*/ if (accum_len ==0xFFFFFFFF ) {PM8001_IO_DBG (pm8001_ha,pm8001_printk ("Possible PCI issue 0x%x not expected\n" , - accum_len)); -return -EIO ; + accum_len)); +return status; } -if (accum_len ==0 || accum_len >=0x100000 ) { +/* If accumulated length is zero fail the attempt */ +if (accum_len ==0 ) { pm8001_ha->forensic_info.data_buf.direct_data +=sprintf (pm8001_ha->forensic_info.data_buf.direct_data, -"%08x " ,0xFFFFFFFF ); +"%08x " ,0xFFFFFFFF );return (char *)pm8001_ha->forensic_info.data_buf.direct_data - (char *)buf; } +/* Accumulated length is good so start capturing the first data */ temp = (u32 *)pm8001_ha->memoryMap.region[FORENSIC_MEM ].virt_ptr;if (pm8001_ha->forensic_fatal_step ==0 ) { moreData: +/* If data to read is less than SYSFS_OFFSET then reduce the +* length of dataLen +*/ +if (pm8001_ha->forensic_last_offset +SYSFS_OFFSET + > length_to_read) { + pm8001_ha->forensic_info.data_buf.direct_len = + length_to_read - + pm8001_ha->forensic_last_offset; + }else { + pm8001_ha->forensic_info.data_buf.direct_len = +SYSFS_OFFSET ; + }if (pm8001_ha->forensic_info.data_buf.direct_data) {/* Data is in bar, copy to host memory */ -pm80xx_pci_mem_copy (pm8001_ha, pm8001_ha->fatal_bar_loc, - pm8001_ha->memoryMap.region[FORENSIC_MEM ].virt_ptr, - pm8001_ha->forensic_info.data_buf.direct_len , -1 ); +pm80xx_pci_mem_copy (pm8001_ha, + pm8001_ha->fatal_bar_loc, + pm8001_ha->memoryMap.region[FORENSIC_MEM ].virt_ptr, + pm8001_ha->forensic_info.data_buf.direct_len,1 ); } pm8001_ha->fatal_bar_loc += pm8001_ha->forensic_info.data_buf.direct_len;@@ -161,21 +219,29 @@ ssize_t pm80xx_get_fatal_dump(struct device *cdev, pm8001_ha->forensic_info.data_buf.read_len = pm8001_ha->forensic_info.data_buf.direct_len; -if (pm8001_ha->forensic_last_offset >= accum_len) { +if (pm8001_ha->forensic_last_offset >= length_to_read) { pm8001_ha->forensic_info.data_buf.direct_data +=sprintf (pm8001_ha->forensic_info.data_buf.direct_data,"%08x " ,3 ); -for (index =0 ; index < (SYSFS_OFFSET /4 ); index++) { +for (index =0 ; index < + (pm8001_ha->forensic_info.data_buf.direct_len + /4 ); index++) { pm8001_ha->forensic_info.data_buf.direct_data += -sprintf (pm8001_ha-> - forensic_info.data_buf.direct_data, -"%08x " , *(temp + index)); +sprintf ( + pm8001_ha->forensic_info.data_buf.direct_data, +"%08x " , *(temp + index)); } pm8001_ha->fatal_bar_loc =0 ; pm8001_ha->forensic_fatal_step =1 ; pm8001_ha->fatal_forensic_shift_offset =0 ; pm8001_ha->forensic_last_offset =0 ; + status =0 ; + offset = (int ) + ((char *)pm8001_ha->forensic_info.data_buf.direct_data + - (char *)buf); +PM8001_IO_DBG (pm8001_ha, +pm8001_printk ("get_fatal_spcv:return1 0x%x\n" , offset));return (char *)pm8001_ha-> forensic_info.data_buf.direct_data - (char *)buf;@@ -185,12 +251,20 @@ ssize_t pm80xx_get_fatal_dump(struct device *cdev,sprintf (pm8001_ha-> forensic_info.data_buf.direct_data,"%08x " ,2 ); -for (index =0 ; index < (SYSFS_OFFSET /4 ); index++) { - pm8001_ha->forensic_info.data_buf.direct_data += -sprintf (pm8001_ha-> +for (index =0 ; index < + (pm8001_ha->forensic_info.data_buf.direct_len + /4 ); index++) { + pm8001_ha->forensic_info.data_buf.direct_data + +=sprintf (pm8001_ha-> forensic_info.data_buf.direct_data,"%08x " , *(temp + index)); } + status =0 ; + offset = (int ) + ((char *)pm8001_ha->forensic_info.data_buf.direct_data + - (char *)buf); +PM8001_IO_DBG (pm8001_ha, +pm8001_printk ("get_fatal_spcv:return2 0x%x\n" , offset));return (char *)pm8001_ha-> forensic_info.data_buf.direct_data - (char *)buf;@@ -200,63 +274,122 @@ ssize_t pm80xx_get_fatal_dump(struct device *cdev, pm8001_ha->forensic_info.data_buf.direct_data +=sprintf (pm8001_ha->forensic_info.data_buf.direct_data,"%08x " ,2 ); -for (index =0 ; index <256 ; index++) { +for (index =0 ; index < + (pm8001_ha->forensic_info.data_buf.direct_len + /4 ) ; index++) { pm8001_ha->forensic_info.data_buf.direct_data +=sprintf (pm8001_ha-> - forensic_info.data_buf.direct_data, -"%08x " , *(temp + index)); + forensic_info.data_buf.direct_data, +"%08x " , *(temp + index)); } pm8001_ha->fatal_forensic_shift_offset +=0x100 ;pm8001_cw32 (pm8001_ha,0 ,MEMBASE_II_SHIFT_REGISTER , pm8001_ha->fatal_forensic_shift_offset); pm8001_ha->fatal_bar_loc =0 ; + status =0 ; + offset = (int ) + ((char *)pm8001_ha->forensic_info.data_buf.direct_data + - (char *)buf); +PM8001_IO_DBG (pm8001_ha, +pm8001_printk ("get_fatal_spcv: return3 0x%x\n" , offset));return (char *)pm8001_ha->forensic_info.data_buf.direct_data - (char *)buf; }if (pm8001_ha->forensic_fatal_step ==1 ) { - pm8001_ha->fatal_forensic_shift_offset =0 ; -/* Read 64K of the debug data. */ -pm8001_cw32 (pm8001_ha,0 ,MEMBASE_II_SHIFT_REGISTER , - pm8001_ha->fatal_forensic_shift_offset); -pm8001_mw32 (fatal_table_address, -MPI_FATAL_EDUMP_TABLE_HANDSHAKE , +/* store previous accumulated length before triggering next +* accumulated length update +*/ + pm8001_ha->forensic_preserved_accumulated_transfer = +pm8001_mr32 (fatal_table_address, +MPI_FATAL_EDUMP_TABLE_ACCUM_LEN ); + +/* continue capturing the fatal log until Dump status is 0x3 */ +if (pm8001_mr32 (fatal_table_address, +MPI_FATAL_EDUMP_TABLE_STATUS ) < +MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_DONE ) { + +/* reset fddstat bit by writing to zero*/ +pm8001_mw32 (fatal_table_address, +MPI_FATAL_EDUMP_TABLE_STATUS ,0x0 ); + +/* set dump control value to '1' so that new data will +* be transferred to shared memory +*/ +pm8001_mw32 (fatal_table_address, +MPI_FATAL_EDUMP_TABLE_HANDSHAKE ,MPI_FATAL_EDUMP_HANDSHAKE_RDY ); -/* Poll FDDHSHK until clear */ - start = jiffies + (2 *HZ );/* 2 sec */ +/*Poll FDDHSHK until clear */ + start = jiffies + (2 *HZ );/* 2 sec */ -do { - reg_val =pm8001_mr32 (fatal_table_address, +do { + reg_val =pm8001_mr32 (fatal_table_address,MPI_FATAL_EDUMP_TABLE_HANDSHAKE ); - }while ((reg_val) &&time_before (jiffies, start)); + }while ((reg_val) &&time_before (jiffies, start)); -if (reg_val !=0 ) { -PM8001_FAIL_DBG (pm8001_ha, -pm8001_printk ("TIMEOUT:MEMBASE_II_SHIFT_REGISTER" -" = 0x%x\n" , reg_val)); -return -EIO ; - } - -/* Read the next 64K of the debug data. */ - pm8001_ha->forensic_fatal_step =0 ; -if (pm8001_mr32 (fatal_table_address, -MPI_FATAL_EDUMP_TABLE_STATUS ) != -MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_DONE ) { -pm8001_mw32 (fatal_table_address, -MPI_FATAL_EDUMP_TABLE_HANDSHAKE ,0 ); - goto moreData; - }else { - pm8001_ha->forensic_info.data_buf.direct_data += -sprintf (pm8001_ha-> - forensic_info.data_buf.direct_data, -"%08x " ,4 ); - pm8001_ha->forensic_info.data_buf.read_len =0xFFFFFFFF ; - pm8001_ha->forensic_info.data_buf.direct_len =0 ; - pm8001_ha->forensic_info.data_buf.direct_offset =0 ; - pm8001_ha->forensic_info.data_buf.read_len =0 ; +if (reg_val !=0 ) { +PM8001_FAIL_DBG (pm8001_ha,pm8001_printk ( +"TIMEOUT:MPI_FATAL_EDUMP_TABLE_HDSHAKE 0x%x\n" , + reg_val)); +/* Fail the dump if a timeout occurs */ + pm8001_ha->forensic_info.data_buf.direct_data += +sprintf ( + pm8001_ha->forensic_info.data_buf.direct_data, +"%08x " ,0xFFFFFFFF ); +return ((char *) + pm8001_ha->forensic_info.data_buf.direct_data + - (char *)buf); + } +/* Poll status register until set to 2 or +* 3 for up to 2 seconds +*/ + start = jiffies + (2 *HZ );/* 2 sec */ + +do { + reg_val =pm8001_mr32 (fatal_table_address, +MPI_FATAL_EDUMP_TABLE_STATUS ); + }while (((reg_val !=2 ) || (reg_val !=3 )) && +time_before (jiffies, start)); + +if (reg_val <2 ) { +PM8001_FAIL_DBG (pm8001_ha,pm8001_printk ( +"TIMEOUT:MPI_FATAL_EDUMP_TABLE_STATUS = 0x%x\n" , + reg_val)); +/* Fail the dump if a timeout occurs */ + pm8001_ha->forensic_info.data_buf.direct_data += +sprintf ( + pm8001_ha->forensic_info.data_buf.direct_data, +"%08x " ,0xFFFFFFFF ); +pm8001_cw32 (pm8001_ha,0 , +MEMBASE_II_SHIFT_REGISTER , + pm8001_ha->fatal_forensic_shift_offset); + } +/* Read the next block of the debug data.*/ + length_to_read =pm8001_mr32 (fatal_table_address, +MPI_FATAL_EDUMP_TABLE_ACCUM_LEN ) - + pm8001_ha->forensic_preserved_accumulated_transfer; +if (length_to_read !=0x0 ) { + pm8001_ha->forensic_fatal_step =0 ; + goto moreData; + }else { + pm8001_ha->forensic_info.data_buf.direct_data += +sprintf ( + pm8001_ha->forensic_info.data_buf.direct_data, +"%08x " ,4 ); + pm8001_ha->forensic_info.data_buf.read_len + =0xFFFFFFFF ; + pm8001_ha->forensic_info.data_buf.direct_len + =0 ; + pm8001_ha->forensic_info.data_buf.direct_offset + =0 ; + pm8001_ha->forensic_info.data_buf.read_len =0 ; + } } } - + offset = (int )((char *)pm8001_ha->forensic_info.data_buf.direct_data + - (char *)buf); +PM8001_IO_DBG (pm8001_ha, +pm8001_printk ("get_fatal_spcv: return4 0x%x\n" , offset));return (char *)pm8001_ha->forensic_info.data_buf.direct_data - (char *)buf; } --2.16.3
Martin K. Petersen
AppliedDeepak,
Quoted 1 line
This patch set includes some bug fixes and features for pm80xx driver.
Applied to 5.5/scsi-queue, thanks!
Signature · 1 line
Martin K. Petersen Oracle Linux Engineering