Even before probe for function was completed, iSCSI Daemon had initiated login to target while OS was coming up. The targets which had node.startup=automatic, login process was initiated.Since function specific initialization was still in progress this lead to kernel panic. The reson was MCCQ was not yet created and login Mbx_Cmd was sent on MCCQ. wrb_from_mccq() failed with kernel-panic access. In this fix, we check alloc_mcc_tag() if driver initialization is complete or not. Based on the result driver continues or return with an Error. Signed-off-by: John Soni Jose <sony.john-n@xxxxxxxxxx> Signed-off-by: Jayamohan Kallickal <Jayamohan.Kallickal@xxxxxxxxxx> --- drivers/scsi/be2iscsi/be_main.c | 75 +++++++++++++++++++++++++---------------- drivers/scsi/be2iscsi/be_main.h | 1 + 2 files changed, 47 insertions(+), 29 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 9be818f..317deee 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -598,6 +598,7 @@ static struct beiscsi_hba *beiscsi_hba_alloc(struct pci_dev *pcidev) phba->pcidev = pci_dev_get(pcidev); pci_set_drvdata(pcidev, phba); phba->interface_handle = 0xFFFFFFFF; + phba->state = BE_ADAPTER_INIT_PHASE; if (iscsi_host_add(shost, &phba->pcidev->dev)) goto free_devices; @@ -895,45 +896,37 @@ static irqreturn_t be_isr_msix(int irq, void *dev_id) struct beiscsi_hba *phba; struct be_eq_entry *eqe = NULL; struct be_queue_info *eq; - struct be_queue_info *cq; unsigned int num_eq_processed; struct be_eq_obj *pbe_eq; unsigned long flags; pbe_eq = dev_id; eq = &pbe_eq->q; - cq = pbe_eq->cq; - eqe = queue_tail_node(eq); phba = pbe_eq->phba; - num_eq_processed = 0; if (blk_iopoll_enabled) { - while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] - & EQE_VALID_MASK) { - if (!blk_iopoll_sched_prep(&pbe_eq->iopoll)) - blk_iopoll_sched(&pbe_eq->iopoll); - - AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); - queue_tail_inc(eq); - eqe = queue_tail_node(eq); - num_eq_processed++; - } - } else { - while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] - & EQE_VALID_MASK) { - spin_lock_irqsave(&phba->isr_lock, flags); - pbe_eq->todo_cq = true; - spin_unlock_irqrestore(&phba->isr_lock, flags); - AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); - queue_tail_inc(eq); - eqe = queue_tail_node(eq); - num_eq_processed++; - } + hwi_ring_eq_db(phba, eq->id, 1, 0, 1, 1); + if (!blk_iopoll_sched_prep(&pbe_eq->iopoll)) + blk_iopoll_sched(&pbe_eq->iopoll); + return IRQ_HANDLED; + } - if (pbe_eq->todo_cq) - queue_work(phba->wq, &pbe_eq->work_cqs); + num_eq_processed = 0; + eqe = queue_tail_node(eq); + while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] + & EQE_VALID_MASK) { + spin_lock_irqsave(&phba->isr_lock, flags); + pbe_eq->todo_cq = true; + spin_unlock_irqrestore(&phba->isr_lock, flags); + AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); + queue_tail_inc(eq); + eqe = queue_tail_node(eq); + num_eq_processed++; } + if (pbe_eq->todo_cq) + queue_work(phba->wq, &pbe_eq->work_cqs); + if (num_eq_processed) hwi_ring_eq_db(phba, eq->id, 1, num_eq_processed, 0, 1); @@ -2281,6 +2274,10 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq) queue_tail_inc(cq); sol = queue_tail_node(cq); num_processed++; + + /* we want to relinquish control to other tasks */ + if (tot_nump >= BE2_MAX_NUM_CQ_PROC) + break; } if (num_processed > 0) { @@ -2323,14 +2320,33 @@ void beiscsi_process_all_cqs(struct work_struct *work) static int be_iopoll(struct blk_iopoll *iop, int budget) { - unsigned int ret; + unsigned int ret, num_eq_processed; struct beiscsi_hba *phba; struct be_eq_obj *pbe_eq; + struct be_eq_entry *eqe = NULL; + struct be_queue_info *eq; + num_eq_processed = 0; pbe_eq = container_of(iop, struct be_eq_obj, iopoll); + phba = pbe_eq->phba; + eq = &pbe_eq->q; + eqe = queue_tail_node(eq); + + hwi_ring_eq_db(phba, eq->id, 1, num_eq_processed, 0, 1); + + while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] + & EQE_VALID_MASK) { + + AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); + queue_tail_inc(eq); + eqe = queue_tail_node(eq); + num_eq_processed++; + } + + hwi_ring_eq_db(phba, eq->id, 1, num_eq_processed, 0, 1); + ret = beiscsi_process_cq(pbe_eq); if (ret < budget) { - phba = pbe_eq->phba; blk_iopoll_complete(iop); beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG | BEISCSI_LOG_IO, @@ -5699,6 +5715,7 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev, goto free_blkenbld; } hwi_enable_intr(phba); + phba->state &= ~BE_ADAPTER_INIT_PHASE; if (beiscsi_setup_boot_info(phba)) /* diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h index d5901a7..581ebdb 100644 --- a/drivers/scsi/be2iscsi/be_main.h +++ b/drivers/scsi/be2iscsi/be_main.h @@ -105,6 +105,7 @@ #define BE_ADAPTER_LINK_DOWN 0x002 #define BE_ADAPTER_PCI_ERR 0x004 #define BE_ADAPTER_STATE_SHUTDOWN 0x008 +#define BE_ADAPTER_INIT_PHASE 0x8000 #define BEISCSI_CLEAN_UNLOAD 0x01 -- 1.8.5.3 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html