aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Soni Jose <sony.john-n@emulex.com>2012-10-19 19:12:49 -0400
committerJames Bottomley <JBottomley@Parallels.com>2012-11-26 23:59:37 -0500
commit72fb46a9d5ec2dfe4dc65eb3bfb795510aacbd1f (patch)
treecf0af61715353461aa901599c9a38944e0365045
parent4d4d1ef8cbc33b650a96bbdf0ca9b14db10e1b29 (diff)
[SCSI] be2iscsi: Fix kernel panic in blk_iopoll disable mode.
Kernel used to panic while running IO is disable mode, as there was an issue with getting the correct EQ on which completion has come. Fix done is create workqueue per hba and work item for each EQ created. Signed-off-by: John Soni Jose <sony.john-n@emulex.com> Signed-off-by: Jayamohan Kallickal <jayamohan.kallickal@emulex.com> Reviewed-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r--drivers/scsi/be2iscsi/be.h3
-rw-r--r--drivers/scsi/be2iscsi/be_main.c83
-rw-r--r--drivers/scsi/be2iscsi/be_main.h3
3 files changed, 52 insertions, 37 deletions
diff --git a/drivers/scsi/be2iscsi/be.h b/drivers/scsi/be2iscsi/be.h
index a50b6a9030e8..3c1f8e9a15e7 100644
--- a/drivers/scsi/be2iscsi/be.h
+++ b/drivers/scsi/be2iscsi/be.h
@@ -84,9 +84,12 @@ static inline void queue_tail_inc(struct be_queue_info *q)
84/*ISCSI */ 84/*ISCSI */
85 85
86struct be_eq_obj { 86struct be_eq_obj {
87 bool todo_mcc_cq;
88 bool todo_cq;
87 struct be_queue_info q; 89 struct be_queue_info q;
88 struct beiscsi_hba *phba; 90 struct beiscsi_hba *phba;
89 struct be_queue_info *cq; 91 struct be_queue_info *cq;
92 struct work_struct work_cqs; /* Work Item */
90 struct blk_iopoll iopoll; 93 struct blk_iopoll iopoll;
91}; 94};
92 95
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
index 41c7c56fcfcb..021799798b14 100644
--- a/drivers/scsi/be2iscsi/be_main.c
+++ b/drivers/scsi/be2iscsi/be_main.c
@@ -769,7 +769,7 @@ static irqreturn_t be_isr_mcc(int irq, void *dev_id)
769 resource_id) / 32] & 769 resource_id) / 32] &
770 EQE_RESID_MASK) >> 16) == mcc->id) { 770 EQE_RESID_MASK) >> 16) == mcc->id) {
771 spin_lock_irqsave(&phba->isr_lock, flags); 771 spin_lock_irqsave(&phba->isr_lock, flags);
772 phba->todo_mcc_cq = 1; 772 pbe_eq->todo_mcc_cq = true;
773 spin_unlock_irqrestore(&phba->isr_lock, flags); 773 spin_unlock_irqrestore(&phba->isr_lock, flags);
774 } 774 }
775 AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); 775 AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0);
@@ -777,8 +777,8 @@ static irqreturn_t be_isr_mcc(int irq, void *dev_id)
777 eqe = queue_tail_node(eq); 777 eqe = queue_tail_node(eq);
778 num_eq_processed++; 778 num_eq_processed++;
779 } 779 }
780 if (phba->todo_mcc_cq) 780 if (pbe_eq->todo_mcc_cq)
781 queue_work(phba->wq, &phba->work_cqs); 781 queue_work(phba->wq, &pbe_eq->work_cqs);
782 if (num_eq_processed) 782 if (num_eq_processed)
783 hwi_ring_eq_db(phba, eq->id, 1, num_eq_processed, 1, 1); 783 hwi_ring_eq_db(phba, eq->id, 1, num_eq_processed, 1, 1);
784 784
@@ -818,29 +818,26 @@ static irqreturn_t be_isr_msix(int irq, void *dev_id)
818 eqe = queue_tail_node(eq); 818 eqe = queue_tail_node(eq);
819 num_eq_processed++; 819 num_eq_processed++;
820 } 820 }
821 if (num_eq_processed)
822 hwi_ring_eq_db(phba, eq->id, 1, num_eq_processed, 0, 1);
823
824 return IRQ_HANDLED;
825 } else { 821 } else {
826 while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] 822 while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32]
827 & EQE_VALID_MASK) { 823 & EQE_VALID_MASK) {
828 spin_lock_irqsave(&phba->isr_lock, flags); 824 spin_lock_irqsave(&phba->isr_lock, flags);
829 phba->todo_cq = 1; 825 pbe_eq->todo_cq = true;
830 spin_unlock_irqrestore(&phba->isr_lock, flags); 826 spin_unlock_irqrestore(&phba->isr_lock, flags);
831 AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); 827 AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0);
832 queue_tail_inc(eq); 828 queue_tail_inc(eq);
833 eqe = queue_tail_node(eq); 829 eqe = queue_tail_node(eq);
834 num_eq_processed++; 830 num_eq_processed++;
835 } 831 }
836 if (phba->todo_cq)
837 queue_work(phba->wq, &phba->work_cqs);
838
839 if (num_eq_processed)
840 hwi_ring_eq_db(phba, eq->id, 1, num_eq_processed, 1, 1);
841 832
842 return IRQ_HANDLED; 833 if (pbe_eq->todo_cq)
834 queue_work(phba->wq, &pbe_eq->work_cqs);
843 } 835 }
836
837 if (num_eq_processed)
838 hwi_ring_eq_db(phba, eq->id, 1, num_eq_processed, 0, 1);
839
840 return IRQ_HANDLED;
844} 841}
845 842
846/** 843/**
@@ -888,7 +885,7 @@ static irqreturn_t be_isr(int irq, void *dev_id)
888 resource_id) / 32] & 885 resource_id) / 32] &
889 EQE_RESID_MASK) >> 16) == mcc->id) { 886 EQE_RESID_MASK) >> 16) == mcc->id) {
890 spin_lock_irqsave(&phba->isr_lock, flags); 887 spin_lock_irqsave(&phba->isr_lock, flags);
891 phba->todo_mcc_cq = 1; 888 pbe_eq->todo_mcc_cq = true;
892 spin_unlock_irqrestore(&phba->isr_lock, flags); 889 spin_unlock_irqrestore(&phba->isr_lock, flags);
893 num_mcceq_processed++; 890 num_mcceq_processed++;
894 } else { 891 } else {
@@ -901,8 +898,8 @@ static irqreturn_t be_isr(int irq, void *dev_id)
901 eqe = queue_tail_node(eq); 898 eqe = queue_tail_node(eq);
902 } 899 }
903 if (num_ioeq_processed || num_mcceq_processed) { 900 if (num_ioeq_processed || num_mcceq_processed) {
904 if (phba->todo_mcc_cq) 901 if (pbe_eq->todo_mcc_cq)
905 queue_work(phba->wq, &phba->work_cqs); 902 queue_work(phba->wq, &pbe_eq->work_cqs);
906 903
907 if ((num_mcceq_processed) && (!num_ioeq_processed)) 904 if ((num_mcceq_processed) && (!num_ioeq_processed))
908 hwi_ring_eq_db(phba, eq->id, 0, 905 hwi_ring_eq_db(phba, eq->id, 0,
@@ -925,11 +922,11 @@ static irqreturn_t be_isr(int irq, void *dev_id)
925 resource_id) / 32] & 922 resource_id) / 32] &
926 EQE_RESID_MASK) >> 16) != cq->id) { 923 EQE_RESID_MASK) >> 16) != cq->id) {
927 spin_lock_irqsave(&phba->isr_lock, flags); 924 spin_lock_irqsave(&phba->isr_lock, flags);
928 phba->todo_mcc_cq = 1; 925 pbe_eq->todo_mcc_cq = true;
929 spin_unlock_irqrestore(&phba->isr_lock, flags); 926 spin_unlock_irqrestore(&phba->isr_lock, flags);
930 } else { 927 } else {
931 spin_lock_irqsave(&phba->isr_lock, flags); 928 spin_lock_irqsave(&phba->isr_lock, flags);
932 phba->todo_cq = 1; 929 pbe_eq->todo_cq = true;
933 spin_unlock_irqrestore(&phba->isr_lock, flags); 930 spin_unlock_irqrestore(&phba->isr_lock, flags);
934 } 931 }
935 AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); 932 AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0);
@@ -937,8 +934,8 @@ static irqreturn_t be_isr(int irq, void *dev_id)
937 eqe = queue_tail_node(eq); 934 eqe = queue_tail_node(eq);
938 num_ioeq_processed++; 935 num_ioeq_processed++;
939 } 936 }
940 if (phba->todo_cq || phba->todo_mcc_cq) 937 if (pbe_eq->todo_cq || pbe_eq->todo_mcc_cq)
941 queue_work(phba->wq, &phba->work_cqs); 938 queue_work(phba->wq, &pbe_eq->work_cqs);
942 939
943 if (num_ioeq_processed) { 940 if (num_ioeq_processed) {
944 hwi_ring_eq_db(phba, eq->id, 0, 941 hwi_ring_eq_db(phba, eq->id, 0,
@@ -2108,30 +2105,30 @@ void beiscsi_process_all_cqs(struct work_struct *work)
2108 unsigned long flags; 2105 unsigned long flags;
2109 struct hwi_controller *phwi_ctrlr; 2106 struct hwi_controller *phwi_ctrlr;
2110 struct hwi_context_memory *phwi_context; 2107 struct hwi_context_memory *phwi_context;
2111 struct be_eq_obj *pbe_eq; 2108 struct beiscsi_hba *phba;
2112 struct beiscsi_hba *phba = 2109 struct be_eq_obj *pbe_eq =
2113 container_of(work, struct beiscsi_hba, work_cqs); 2110 container_of(work, struct be_eq_obj, work_cqs);
2114 2111
2112 phba = pbe_eq->phba;
2115 phwi_ctrlr = phba->phwi_ctrlr; 2113 phwi_ctrlr = phba->phwi_ctrlr;
2116 phwi_context = phwi_ctrlr->phwi_ctxt; 2114 phwi_context = phwi_ctrlr->phwi_ctxt;
2117 if (phba->msix_enabled)
2118 pbe_eq = &phwi_context->be_eq[phba->num_cpus];
2119 else
2120 pbe_eq = &phwi_context->be_eq[0];
2121 2115
2122 if (phba->todo_mcc_cq) { 2116 if (pbe_eq->todo_mcc_cq) {
2123 spin_lock_irqsave(&phba->isr_lock, flags); 2117 spin_lock_irqsave(&phba->isr_lock, flags);
2124 phba->todo_mcc_cq = 0; 2118 pbe_eq->todo_mcc_cq = false;
2125 spin_unlock_irqrestore(&phba->isr_lock, flags); 2119 spin_unlock_irqrestore(&phba->isr_lock, flags);
2126 beiscsi_process_mcc_isr(phba); 2120 beiscsi_process_mcc_isr(phba);
2127 } 2121 }
2128 2122
2129 if (phba->todo_cq) { 2123 if (pbe_eq->todo_cq) {
2130 spin_lock_irqsave(&phba->isr_lock, flags); 2124 spin_lock_irqsave(&phba->isr_lock, flags);
2131 phba->todo_cq = 0; 2125 pbe_eq->todo_cq = false;
2132 spin_unlock_irqrestore(&phba->isr_lock, flags); 2126 spin_unlock_irqrestore(&phba->isr_lock, flags);
2133 beiscsi_process_cq(pbe_eq); 2127 beiscsi_process_cq(pbe_eq);
2134 } 2128 }
2129
2130 /* rearm EQ for further interrupts */
2131 hwi_ring_eq_db(phba, pbe_eq->q.id, 0, 0, 1, 1);
2135} 2132}
2136 2133
2137static int be_iopoll(struct blk_iopoll *iop, int budget) 2134static int be_iopoll(struct blk_iopoll *iop, int budget)
@@ -4642,7 +4639,7 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
4642 4639
4643 phba->ctrl.mcc_alloc_index = phba->ctrl.mcc_free_index = 0; 4640 phba->ctrl.mcc_alloc_index = phba->ctrl.mcc_free_index = 0;
4644 4641
4645 snprintf(phba->wq_name, sizeof(phba->wq_name), "beiscsi_q_irq%u", 4642 snprintf(phba->wq_name, sizeof(phba->wq_name), "beiscsi_%02x_wq",
4646 phba->shost->host_no); 4643 phba->shost->host_no);
4647 phba->wq = alloc_workqueue(phba->wq_name, WQ_MEM_RECLAIM, 1); 4644 phba->wq = alloc_workqueue(phba->wq_name, WQ_MEM_RECLAIM, 1);
4648 if (!phba->wq) { 4645 if (!phba->wq) {
@@ -4652,10 +4649,10 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
4652 goto free_twq; 4649 goto free_twq;
4653 } 4650 }
4654 4651
4655 INIT_WORK(&phba->work_cqs, beiscsi_process_all_cqs);
4656 4652
4657 phwi_ctrlr = phba->phwi_ctrlr; 4653 phwi_ctrlr = phba->phwi_ctrlr;
4658 phwi_context = phwi_ctrlr->phwi_ctxt; 4654 phwi_context = phwi_ctrlr->phwi_ctxt;
4655
4659 if (blk_iopoll_enabled) { 4656 if (blk_iopoll_enabled) {
4660 for (i = 0; i < phba->num_cpus; i++) { 4657 for (i = 0; i < phba->num_cpus; i++) {
4661 pbe_eq = &phwi_context->be_eq[i]; 4658 pbe_eq = &phwi_context->be_eq[i];
@@ -4663,7 +4660,25 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
4663 be_iopoll); 4660 be_iopoll);
4664 blk_iopoll_enable(&pbe_eq->iopoll); 4661 blk_iopoll_enable(&pbe_eq->iopoll);
4665 } 4662 }
4663
4664 i = (phba->msix_enabled) ? i : 0;
4665 /* Work item for MCC handling */
4666 pbe_eq = &phwi_context->be_eq[i];
4667 INIT_WORK(&pbe_eq->work_cqs, beiscsi_process_all_cqs);
4668 } else {
4669 if (phba->msix_enabled) {
4670 for (i = 0; i <= phba->num_cpus; i++) {
4671 pbe_eq = &phwi_context->be_eq[i];
4672 INIT_WORK(&pbe_eq->work_cqs,
4673 beiscsi_process_all_cqs);
4674 }
4675 } else {
4676 pbe_eq = &phwi_context->be_eq[0];
4677 INIT_WORK(&pbe_eq->work_cqs,
4678 beiscsi_process_all_cqs);
4679 }
4666 } 4680 }
4681
4667 ret = beiscsi_init_irqs(phba); 4682 ret = beiscsi_init_irqs(phba);
4668 if (ret < 0) { 4683 if (ret < 0) {
4669 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 4684 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h
index e24d55015424..02b23c954e1e 100644
--- a/drivers/scsi/be2iscsi/be_main.h
+++ b/drivers/scsi/be2iscsi/be_main.h
@@ -327,11 +327,8 @@ struct beiscsi_hba {
327 } fw_config; 327 } fw_config;
328 328
329 u8 mac_address[ETH_ALEN]; 329 u8 mac_address[ETH_ALEN];
330 unsigned short todo_cq;
331 unsigned short todo_mcc_cq;
332 char wq_name[20]; 330 char wq_name[20];
333 struct workqueue_struct *wq; /* The actuak work queue */ 331 struct workqueue_struct *wq; /* The actuak work queue */
334 struct work_struct work_cqs; /* The work being queued */
335 struct be_ctrl_info ctrl; 332 struct be_ctrl_info ctrl;
336 unsigned int generation; 333 unsigned int generation;
337 unsigned int interface_handle; 334 unsigned int interface_handle;