aic94xx SCSI timeout fix
Subsystems (2)
PATCH 1/2 aic94xx SCSI timeout fix
The patch updates DDB0 in the aic94xx driver itself. It doesn't supply or use lldd_port_formed field. DDB0 is updated prior to posting notification to libsas layer.
Signed-off-by Malahal Naineni <[email protected]>
drivers/scsi/aic94xx/aic94xx_hwi.c +18 -0
@@ -112,6 +112,21 @@ static int asd_init_phy(struct asd_phy *return 0 ; } +static void asd_init_ports (struct asd_ha_struct *asd_ha) +{ +int i; + +spin_lock_init (&asd_ha->asd_ports_lock); +for (i =0 ; i <ASD_MAX_PHYS ; i++) { +struct asd_port *asd_port = &asd_ha->asd_ports[i]; + +memset (asd_port->sas_addr,0 ,SAS_ADDR_SIZE ); +memset (asd_port->attached_sas_addr,0 ,SAS_ADDR_SIZE ); + asd_port->phy_mask =0 ; + asd_port->num_phys =0 ; + } +} +static int asd_init_phys (struct asd_ha_struct *asd_ha) {u8 i;
@@ -121,6 +136,7 @@ static int asd_init_phys(struct asd_ha_sstruct asd_phy *phy = &asd_ha->phys[i]; phy->phy_desc = &asd_ha->hw_prof.phy_desc[i]; + phy->asd_port =NULL ; phy->sas_phy.enabled =0 ; phy->sas_phy.id = i;
@@ -657,6 +673,8 @@ int asd_init_hw(struct asd_ha_struct *as pci_name(asd_ha->pcidev)); goto Out; } + +asd_init_ports (asd_ha); err =asd_init_scbs (asd_ha);if (err) {
drivers/scsi/aic94xx/aic94xx_hwi.h +12 -0
@@ -192,6 +192,16 @@ struct asd_seq_data {struct asd_ascb **escb_arr;/* array of pointers to escbs */ }; +/* This is an internal port structure. These are used to get accurate +* phy_mask for updating DDB 0. +*/ +struct asd_port { +u8 sas_addr[SAS_ADDR_SIZE ]; +u8 attached_sas_addr[SAS_ADDR_SIZE ]; +u32 phy_mask; +int num_phys; +}; +/* This is the Host Adapter structure. It describes the hardware * SAS adapter. */
@@ -210,6 +220,8 @@ struct asd_ha_struct {struct hw_profile hw_prof;struct asd_phy phys[ASD_MAX_PHYS ]; +spinlock_t asd_ports_lock; +struct asd_port asd_ports[ASD_MAX_PHYS ];struct asd_sas_port ports[ASD_MAX_PHYS ];struct dma_pool *scb_pool;
drivers/scsi/aic94xx/aic94xx_init.c +0 -2
@@ -766,8 +766,6 @@ static void asd_remove_driver_attrs(stru }static struct sas_domain_function_template aic94xx_transport_functions = { - .lldd_port_formed = asd_update_port_links, - .lldd_dev_found = asd_dev_found, .lldd_dev_gone = asd_dev_gone,
drivers/scsi/aic94xx/aic94xx_sas.h +1 -0
@@ -733,6 +733,7 @@ struct asd_phy {struct sas_identify_frame *identify_frame;struct asd_dma_tok *id_frm_tok; +struct asd_port *asd_port;u8 frame_rcvd[ASD_EDB_SIZE ]; };
drivers/scsi/aic94xx/aic94xx_scb.c +72 -0
120 lines not on this page · raw message
drivers/scsi/aic94xx/aic94xx_seq.c +3 -4
@@ -1369,10 +1369,9 @@ int asd_start_seqs(struct asd_ha_struct* port_map_by_links is also used as the conn_mask byte in the * initiator/target port DDB. */ -void asd_update_port_links (struct asd_sas_phy *sas_phy) -{ -struct asd_ha_struct *asd_ha = sas_phy->ha->lldd_ha; -const u8 phy_mask = (u8 ) sas_phy->port->phy_mask; +void asd_update_port_links (struct asd_ha_struct *asd_ha,struct asd_phy *phy) +{ +const u8 phy_mask = (u8 ) phy->asd_port->phy_mask;u8 phy_is_up;u8 mask;int i, err;
drivers/scsi/aic94xx/aic94xx_seq.h +1 -1
@@ -64,7 +64,7 @@ int asd_init_seqs(struct asd_ha_struct *int asd_init_seqs (struct asd_ha_struct *asd_ha);int asd_start_seqs (struct asd_ha_struct *asd_ha); -void asd_update_port_links (struct asd_sas_phy *phy); +void asd_update_port_links (struct asd_ha_struct *asd_ha,struct asd_phy *phy);#endif #endif
PATCH 2/2 aic94xx SCSI timeout fix: SMP retry fix.
Updating DDB0 inside aic94xx driver itself caused SMP command timeout. I hit this SMP timeout problem twice but I am not able to reproduce it since then. Here is a fix that retries an SMP command.
igned-off-by Malahal Naineni <[email protected]>
drivers/scsi/libsas/sas_expander.c +53 -43
@@ -71,55 +71,65 @@ static int smp_execute_task(struct domaistatic int smp_execute_task (struct domain_device *dev,void *req,int req_size,void *resp,int resp_size) { -int res; -struct sas_task *task =sas_alloc_task (GFP_KERNEL ); +int res, retry; +struct sas_task *task =NULL ;struct sas_internal *i =to_sas_internal (dev->port->ha->core.shost->transportt); -if (!task) -return -ENOMEM ; - - task->dev = dev; - task->task_proto = dev->tproto; -sg_init_one (&task->smp_task.smp_req, req, req_size); -sg_init_one (&task->smp_task.smp_resp, resp, resp_size); - - task->task_done = smp_task_done; - - task->timer.data = (unsigned long ) task; - task->timer.function = smp_task_timedout; - task->timer.expires = jiffies +SMP_TIMEOUT *HZ ; -add_timer (&task->timer); - - res = i->dft->lldd_execute_task (task,1 ,GFP_KERNEL ); - -if (res) { -del_timer (&task->timer); -SAS_DPRINTK ("executing SMP task failed:%d\n" , res); - goto ex_err; - } - -wait_for_completion (&task->completion); - res = -ETASK ; -if ((task->task_state_flags &SAS_TASK_STATE_ABORTED )) { -SAS_DPRINTK ("smp task timed out or aborted\n" ); - i->dft->lldd_abort_task (task); -if (!(task->task_state_flags &SAS_TASK_STATE_DONE )) { -SAS_DPRINTK ("SMP task aborted and not done\n" ); +for (retry =0 ; retry <3 ; retry++) { + task =sas_alloc_task (GFP_KERNEL ); +if (!task) +return -ENOMEM ; + + task->dev = dev; + task->task_proto = dev->tproto; +sg_init_one (&task->smp_task.smp_req, req, req_size); +sg_init_one (&task->smp_task.smp_resp, resp, resp_size); + + task->task_done = smp_task_done; + + task->timer.data = (unsigned long ) task; + task->timer.function = smp_task_timedout; + task->timer.expires = jiffies +SMP_TIMEOUT *HZ ; +add_timer (&task->timer); + + res = i->dft->lldd_execute_task (task,1 ,GFP_KERNEL ); + +if (res) { +del_timer (&task->timer); +SAS_DPRINTK ("executing SMP task failed:%d\n" , res); goto ex_err; } - } -if (task->task_status.resp ==SAS_TASK_COMPLETE && - task->task_status.stat ==SAM_GOOD ) - res =0 ; -else -SAS_DPRINTK ("%s: task to dev %016llx response: 0x%x " -"status 0x%x\n" , __FUNCTION__, -SAS_ADDR (dev->sas_addr), - task->task_status.resp, - task->task_status.stat); + +wait_for_completion (&task->completion); + res = -ETASK ; +if ((task->task_state_flags &SAS_TASK_STATE_ABORTED )) { +SAS_DPRINTK ("smp task timed out or aborted\n" ); + i->dft->lldd_abort_task (task); +if (!(task->task_state_flags &SAS_TASK_STATE_DONE )) { +SAS_DPRINTK ("SMP task aborted and not done\n" ); + goto ex_err; + } + } +if (task->task_status.resp ==SAS_TASK_COMPLETE && + task->task_status.stat ==SAM_GOOD ) { + res =0 ; +break ; + }else { +SAS_DPRINTK ("%s: task to dev %016llx response: 0x%x " +"status 0x%x\n" , __FUNCTION__, +SAS_ADDR (dev->sas_addr), + task->task_status.resp, + task->task_status.stat); +sas_free_task (task); + task =NULL ; + } + } ex_err: -sas_free_task (task); +BUG_ON (retry ==3 && task !=NULL ); +if (task !=NULL ) { +sas_free_task (task); + }return res; }