aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJitendra Bhivare <jitendra.bhivare@broadcom.com>2016-08-19 05:50:13 -0400
committerMartin K. Petersen <martin.petersen@oracle.com>2016-08-23 22:42:43 -0400
commit10bcd47dff496206de68223aeb1a581bccad03d3 (patch)
tree6a2f2d240aa57e61258c2f8b747266368ba697f0
parent50a4b824be9e4a01f3b87790865e26b1546fcbb8 (diff)
scsi: be2iscsi: Fix to add timer for UE detection
UE detection in health check is done in a work scheduled in global wq. UE caused due to transient parity errors are recoverable and reported within 1s. If this check for TPE gets delayed, PF0 might initiate soft-reset and then status of UE recoverable is lost. Handle UE detection in timer routine. Move out EQ delay update work from health check. Make the IOCTL for EQ delay update non-blocking as the completion status is ignored. Signed-off-by: Jitendra Bhivare <jitendra.bhivare@broadcom.com> Reviewed-by: Hannes Reinecke <hare@suse.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r--drivers/scsi/be2iscsi/be.h9
-rw-r--r--drivers/scsi/be2iscsi/be_cmds.c7
-rw-r--r--drivers/scsi/be2iscsi/be_cmds.h2
-rw-r--r--drivers/scsi/be2iscsi/be_main.c90
-rw-r--r--drivers/scsi/be2iscsi/be_main.h7
-rw-r--r--drivers/scsi/be2iscsi/be_mgmt.c11
6 files changed, 75 insertions, 51 deletions
diff --git a/drivers/scsi/be2iscsi/be.h b/drivers/scsi/be2iscsi/be.h
index 454002d98bcd..bb4042c9acfb 100644
--- a/drivers/scsi/be2iscsi/be.h
+++ b/drivers/scsi/be2iscsi/be.h
@@ -89,7 +89,7 @@ struct be_aic_obj { /* Adaptive interrupt coalescing (AIC) info */
89 u32 max_eqd; /* in usecs */ 89 u32 max_eqd; /* in usecs */
90 u32 prev_eqd; /* in usecs */ 90 u32 prev_eqd; /* in usecs */
91 u32 et_eqd; /* configured val when aic is off */ 91 u32 et_eqd; /* configured val when aic is off */
92 ulong jiffs; 92 ulong jiffies;
93 u64 eq_prev; /* Used to calculate eqe */ 93 u64 eq_prev; /* Used to calculate eqe */
94}; 94};
95 95
@@ -111,9 +111,10 @@ struct be_mcc_obj {
111 111
112struct beiscsi_mcc_tag_state { 112struct beiscsi_mcc_tag_state {
113 unsigned long tag_state; 113 unsigned long tag_state;
114#define MCC_TAG_STATE_RUNNING 1 114#define MCC_TAG_STATE_RUNNING 0
115#define MCC_TAG_STATE_TIMEOUT 2 115#define MCC_TAG_STATE_TIMEOUT 1
116#define MCC_TAG_STATE_ASYNC 3 116#define MCC_TAG_STATE_ASYNC 2
117#define MCC_TAG_STATE_IGNORE 3
117 void (*cbfn)(struct beiscsi_hba *, unsigned int); 118 void (*cbfn)(struct beiscsi_hba *, unsigned int);
118 struct be_dma_mem tag_mem_state; 119 struct be_dma_mem tag_mem_state;
119}; 120};
diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c
index 27d10cee0c40..7cb009e0030e 100644
--- a/drivers/scsi/be2iscsi/be_cmds.c
+++ b/drivers/scsi/be2iscsi/be_cmds.c
@@ -515,6 +515,13 @@ int beiscsi_process_mcc_compl(struct be_ctrl_info *ctrl,
515 return 0; 515 return 0;
516 } 516 }
517 517
518 if (test_bit(MCC_TAG_STATE_IGNORE, &ctrl->ptag_state[tag].tag_state)) {
519 /* just check completion status and free wrb */
520 __beiscsi_mcc_compl_status(phba, tag, NULL, NULL);
521 free_mcc_wrb(ctrl, tag);
522 return 0;
523 }
524
518 wake_up_interruptible(&ctrl->mcc_wait[tag]); 525 wake_up_interruptible(&ctrl->mcc_wait[tag]);
519 return 0; 526 return 0;
520} 527}
diff --git a/drivers/scsi/be2iscsi/be_cmds.h b/drivers/scsi/be2iscsi/be_cmds.h
index 0510b6767341..6fb9673248b3 100644
--- a/drivers/scsi/be2iscsi/be_cmds.h
+++ b/drivers/scsi/be2iscsi/be_cmds.h
@@ -743,7 +743,7 @@ unsigned int be_cmd_get_initname(struct beiscsi_hba *phba);
743 743
744void free_mcc_wrb(struct be_ctrl_info *ctrl, unsigned int tag); 744void free_mcc_wrb(struct be_ctrl_info *ctrl, unsigned int tag);
745 745
746int be_cmd_modify_eq_delay(struct beiscsi_hba *phba, struct be_set_eqd *, 746int beiscsi_modify_eq_delay(struct beiscsi_hba *phba, struct be_set_eqd *,
747 int num); 747 int num);
748int beiscsi_mccq_compl_wait(struct beiscsi_hba *phba, 748int beiscsi_mccq_compl_wait(struct beiscsi_hba *phba,
749 unsigned int tag, 749 unsigned int tag,
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
index eb4ce17a683d..3dd4f9d126ae 100644
--- a/drivers/scsi/be2iscsi/be_main.c
+++ b/drivers/scsi/be2iscsi/be_main.c
@@ -4999,8 +4999,9 @@ static void beiscsi_quiesce(struct beiscsi_hba *phba)
4999 if (phba->pcidev->irq) 4999 if (phba->pcidev->irq)
5000 free_irq(phba->pcidev->irq, phba); 5000 free_irq(phba->pcidev->irq, phba);
5001 pci_disable_msix(phba->pcidev); 5001 pci_disable_msix(phba->pcidev);
5002 cancel_delayed_work_sync(&phba->beiscsi_hw_check_task); 5002 cancel_delayed_work_sync(&phba->eqd_update);
5003 cancel_work_sync(&phba->boot_work); 5003 cancel_work_sync(&phba->boot_work);
5004 del_timer_sync(&phba->hw_check);
5004 5005
5005 for (i = 0; i < phba->num_cpus; i++) { 5006 for (i = 0; i < phba->num_cpus; i++) {
5006 pbe_eq = &phwi_context->be_eq[i]; 5007 pbe_eq = &phwi_context->be_eq[i];
@@ -5339,18 +5340,32 @@ static void beiscsi_boot_work(struct work_struct *work)
5339 } 5340 }
5340} 5341}
5341 5342
5342static void be_eqd_update(struct beiscsi_hba *phba) 5343static void beiscsi_hw_health_check(unsigned long ptr)
5343{ 5344{
5345 struct beiscsi_hba *phba;
5346
5347 phba = (struct beiscsi_hba *)ptr;
5348 beiscsi_ue_detect(phba);
5349 if (test_bit(BEISCSI_HBA_IN_UE, &phba->state))
5350 return;
5351
5352 mod_timer(&phba->hw_check,
5353 jiffies + msecs_to_jiffies(BEISCSI_UE_DETECT_INTERVAL));
5354}
5355
5356static void beiscsi_eqd_update_work(struct work_struct *work)
5357{
5358 struct hwi_context_memory *phwi_context;
5344 struct be_set_eqd set_eqd[MAX_CPUS]; 5359 struct be_set_eqd set_eqd[MAX_CPUS];
5345 struct be_aic_obj *aic;
5346 struct be_eq_obj *pbe_eq;
5347 struct hwi_controller *phwi_ctrlr; 5360 struct hwi_controller *phwi_ctrlr;
5348 struct hwi_context_memory *phwi_context; 5361 struct be_eq_obj *pbe_eq;
5362 struct beiscsi_hba *phba;
5363 unsigned int pps, delta;
5364 struct be_aic_obj *aic;
5349 int eqd, i, num = 0; 5365 int eqd, i, num = 0;
5350 ulong now; 5366 unsigned long now;
5351 u32 pps, delta;
5352 unsigned int tag;
5353 5367
5368 phba = container_of(work, struct beiscsi_hba, eqd_update.work);
5354 if (beiscsi_hba_in_error(phba)) 5369 if (beiscsi_hba_in_error(phba))
5355 return; 5370 return;
5356 5371
@@ -5361,13 +5376,13 @@ static void be_eqd_update(struct beiscsi_hba *phba)
5361 aic = &phba->aic_obj[i]; 5376 aic = &phba->aic_obj[i];
5362 pbe_eq = &phwi_context->be_eq[i]; 5377 pbe_eq = &phwi_context->be_eq[i];
5363 now = jiffies; 5378 now = jiffies;
5364 if (!aic->jiffs || time_before(now, aic->jiffs) || 5379 if (!aic->jiffies || time_before(now, aic->jiffies) ||
5365 pbe_eq->cq_count < aic->eq_prev) { 5380 pbe_eq->cq_count < aic->eq_prev) {
5366 aic->jiffs = now; 5381 aic->jiffies = now;
5367 aic->eq_prev = pbe_eq->cq_count; 5382 aic->eq_prev = pbe_eq->cq_count;
5368 continue; 5383 continue;
5369 } 5384 }
5370 delta = jiffies_to_msecs(now - aic->jiffs); 5385 delta = jiffies_to_msecs(now - aic->jiffies);
5371 pps = (((u32)(pbe_eq->cq_count - aic->eq_prev) * 1000) / delta); 5386 pps = (((u32)(pbe_eq->cq_count - aic->eq_prev) * 1000) / delta);
5372 eqd = (pps / 1500) << 2; 5387 eqd = (pps / 1500) << 2;
5373 5388
@@ -5376,7 +5391,7 @@ static void be_eqd_update(struct beiscsi_hba *phba)
5376 eqd = min_t(u32, eqd, phwi_context->max_eqd); 5391 eqd = min_t(u32, eqd, phwi_context->max_eqd);
5377 eqd = max_t(u32, eqd, phwi_context->min_eqd); 5392 eqd = max_t(u32, eqd, phwi_context->min_eqd);
5378 5393
5379 aic->jiffs = now; 5394 aic->jiffies = now;
5380 aic->eq_prev = pbe_eq->cq_count; 5395 aic->eq_prev = pbe_eq->cq_count;
5381 5396
5382 if (eqd != aic->prev_eqd) { 5397 if (eqd != aic->prev_eqd) {
@@ -5386,32 +5401,12 @@ static void be_eqd_update(struct beiscsi_hba *phba)
5386 num++; 5401 num++;
5387 } 5402 }
5388 } 5403 }
5389 if (num) { 5404 if (num)
5390 tag = be_cmd_modify_eq_delay(phba, set_eqd, num); 5405 /* completion of this is ignored */
5391 if (tag) 5406 beiscsi_modify_eq_delay(phba, set_eqd, num);
5392 beiscsi_mccq_compl_wait(phba, tag, NULL, NULL);
5393 }
5394}
5395 5407
5396/* 5408 schedule_delayed_work(&phba->eqd_update,
5397 * beiscsi_hw_health_check()- Check adapter health 5409 msecs_to_jiffies(BEISCSI_EQD_UPDATE_INTERVAL));
5398 * @work: work item to check HW health
5399 *
5400 * Check if adapter in an unrecoverable state or not.
5401 **/
5402static void
5403beiscsi_hw_health_check(struct work_struct *work)
5404{
5405 struct beiscsi_hba *phba =
5406 container_of(work, struct beiscsi_hba,
5407 beiscsi_hw_check_task.work);
5408
5409 be_eqd_update(phba);
5410
5411 beiscsi_ue_detect(phba);
5412
5413 schedule_delayed_work(&phba->beiscsi_hw_check_task,
5414 msecs_to_jiffies(1000));
5415} 5410}
5416 5411
5417 5412
@@ -5560,6 +5555,11 @@ static void beiscsi_eeh_resume(struct pci_dev *pdev)
5560 hwi_enable_intr(phba); 5555 hwi_enable_intr(phba);
5561 clear_bit(BEISCSI_HBA_PCI_ERR, &phba->state); 5556 clear_bit(BEISCSI_HBA_PCI_ERR, &phba->state);
5562 5557
5558 /* start hw_check timer and eqd_update work */
5559 schedule_delayed_work(&phba->eqd_update,
5560 msecs_to_jiffies(BEISCSI_EQD_UPDATE_INTERVAL));
5561 mod_timer(&phba->hw_check,
5562 jiffies + msecs_to_jiffies(BEISCSI_UE_DETECT_INTERVAL));
5563 return; 5563 return;
5564ret_err: 5564ret_err:
5565 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 5565 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
@@ -5707,8 +5707,7 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev,
5707 goto free_twq; 5707 goto free_twq;
5708 } 5708 }
5709 5709
5710 INIT_DELAYED_WORK(&phba->beiscsi_hw_check_task, 5710 INIT_DELAYED_WORK(&phba->eqd_update, beiscsi_eqd_update_work);
5711 beiscsi_hw_health_check);
5712 5711
5713 phwi_ctrlr = phba->phwi_ctrlr; 5712 phwi_ctrlr = phba->phwi_ctrlr;
5714 phwi_context = phwi_ctrlr->phwi_ctxt; 5713 phwi_context = phwi_ctrlr->phwi_ctxt;
@@ -5749,8 +5748,17 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev,
5749 } 5748 }
5750 5749
5751 beiscsi_iface_create_default(phba); 5750 beiscsi_iface_create_default(phba);
5752 schedule_delayed_work(&phba->beiscsi_hw_check_task, 5751 schedule_delayed_work(&phba->eqd_update,
5753 msecs_to_jiffies(1000)); 5752 msecs_to_jiffies(BEISCSI_EQD_UPDATE_INTERVAL));
5753 /**
5754 * Start UE detection here. UE before this will cause stall in probe
5755 * and eventually fail the probe.
5756 */
5757 init_timer(&phba->hw_check);
5758 phba->hw_check.function = beiscsi_hw_health_check;
5759 phba->hw_check.data = (unsigned long)phba;
5760 mod_timer(&phba->hw_check,
5761 jiffies + msecs_to_jiffies(BEISCSI_UE_DETECT_INTERVAL));
5754 5762
5755 beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, 5763 beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
5756 "\n\n\n BM_%d : SUCCESS - DRIVER LOADED\n\n\n"); 5764 "\n\n\n BM_%d : SUCCESS - DRIVER LOADED\n\n\n");
diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h
index 780c3fc16ec6..0d34ac611d2f 100644
--- a/drivers/scsi/be2iscsi/be_main.h
+++ b/drivers/scsi/be2iscsi/be_main.h
@@ -414,7 +414,12 @@ struct beiscsi_hba {
414 (1 << BEISCSI_HBA_IN_UE)) 414 (1 << BEISCSI_HBA_IN_UE))
415 415
416 u8 optic_state; 416 u8 optic_state;
417 struct delayed_work beiscsi_hw_check_task; 417 struct delayed_work eqd_update;
418 /* update EQ delay timer every 1000ms */
419#define BEISCSI_EQD_UPDATE_INTERVAL 1000
420 struct timer_list hw_check;
421 /* check for UE every 1000ms */
422#define BEISCSI_UE_DETECT_INTERVAL 1000
418 423
419 bool mac_addr_set; 424 bool mac_addr_set;
420 u8 mac_address[ETH_ALEN]; 425 u8 mac_address[ETH_ALEN];
diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c
index 756e7ae33e2c..60a116388467 100644
--- a/drivers/scsi/be2iscsi/be_mgmt.c
+++ b/drivers/scsi/be2iscsi/be_mgmt.c
@@ -97,7 +97,7 @@ static const char * const desc_ue_status_hi[] = {
97}; 97};
98 98
99/* 99/*
100 * beiscsi_ue_detec()- Detect Unrecoverable Error on adapter 100 * beiscsi_ue_detect()- Detect Unrecoverable Error on adapter
101 * @phba: Driver priv structure 101 * @phba: Driver priv structure
102 * 102 *
103 * Read registers linked to UE and check for the UE status 103 * Read registers linked to UE and check for the UE status
@@ -152,8 +152,9 @@ void beiscsi_ue_detect(struct beiscsi_hba *phba)
152 } 152 }
153} 153}
154 154
155int be_cmd_modify_eq_delay(struct beiscsi_hba *phba, 155int beiscsi_modify_eq_delay(struct beiscsi_hba *phba,
156 struct be_set_eqd *set_eqd, int num) 156 struct be_set_eqd *set_eqd,
157 int num)
157{ 158{
158 struct be_ctrl_info *ctrl = &phba->ctrl; 159 struct be_ctrl_info *ctrl = &phba->ctrl;
159 struct be_mcc_wrb *wrb; 160 struct be_mcc_wrb *wrb;
@@ -171,7 +172,7 @@ int be_cmd_modify_eq_delay(struct beiscsi_hba *phba,
171 req = embedded_payload(wrb); 172 req = embedded_payload(wrb);
172 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); 173 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
173 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 174 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
174 OPCODE_COMMON_MODIFY_EQ_DELAY, sizeof(*req)); 175 OPCODE_COMMON_MODIFY_EQ_DELAY, sizeof(*req));
175 176
176 req->num_eq = cpu_to_le32(num); 177 req->num_eq = cpu_to_le32(num);
177 for (i = 0; i < num; i++) { 178 for (i = 0; i < num; i++) {
@@ -181,6 +182,8 @@ int be_cmd_modify_eq_delay(struct beiscsi_hba *phba,
181 cpu_to_le32(set_eqd[i].delay_multiplier); 182 cpu_to_le32(set_eqd[i].delay_multiplier);
182 } 183 }
183 184
185 /* ignore the completion of this mbox command */
186 set_bit(MCC_TAG_STATE_IGNORE, &ctrl->ptag_state[tag].tag_state);
184 be_mcc_notify(phba, tag); 187 be_mcc_notify(phba, tag);
185 mutex_unlock(&ctrl->mbox_lock); 188 mutex_unlock(&ctrl->mbox_lock);
186 return tag; 189 return tag;