Merge branch 'next' into for-linus
[cascardo/linux.git] / drivers / scsi / lpfc / lpfc_sli.c
index 393662c..32ada05 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2013 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2014 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
@@ -3532,20 +3532,63 @@ lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
        /* Error everything on txq and txcmplq
         * First do the txq.
         */
-       spin_lock_irq(&phba->hbalock);
-       list_splice_init(&pring->txq, &completions);
+       if (phba->sli_rev >= LPFC_SLI_REV4) {
+               spin_lock_irq(&pring->ring_lock);
+               list_splice_init(&pring->txq, &completions);
+               pring->txq_cnt = 0;
+               spin_unlock_irq(&pring->ring_lock);
 
-       /* Next issue ABTS for everything on the txcmplq */
-       list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list)
-               lpfc_sli_issue_abort_iotag(phba, pring, iocb);
+               spin_lock_irq(&phba->hbalock);
+               /* Next issue ABTS for everything on the txcmplq */
+               list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list)
+                       lpfc_sli_issue_abort_iotag(phba, pring, iocb);
+               spin_unlock_irq(&phba->hbalock);
+       } else {
+               spin_lock_irq(&phba->hbalock);
+               list_splice_init(&pring->txq, &completions);
+               pring->txq_cnt = 0;
 
-       spin_unlock_irq(&phba->hbalock);
+               /* Next issue ABTS for everything on the txcmplq */
+               list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list)
+                       lpfc_sli_issue_abort_iotag(phba, pring, iocb);
+               spin_unlock_irq(&phba->hbalock);
+       }
 
        /* Cancel all the IOCBs from the completions list */
        lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
                              IOERR_SLI_ABORTED);
 }
 
+/**
+ * lpfc_sli_abort_fcp_rings - Abort all iocbs in all FCP rings
+ * @phba: Pointer to HBA context object.
+ * @pring: Pointer to driver SLI ring object.
+ *
+ * This function aborts all iocbs in FCP rings and frees all the iocb
+ * objects in txq. This function issues an abort iocb for all the iocb commands
+ * in txcmplq. The iocbs in the txcmplq is not guaranteed to complete before
+ * the return of this function. The caller is not required to hold any locks.
+ **/
+void
+lpfc_sli_abort_fcp_rings(struct lpfc_hba *phba)
+{
+       struct lpfc_sli *psli = &phba->sli;
+       struct lpfc_sli_ring  *pring;
+       uint32_t i;
+
+       /* Look on all the FCP Rings for the iotag */
+       if (phba->sli_rev >= LPFC_SLI_REV4) {
+               for (i = 0; i < phba->cfg_fcp_io_channel; i++) {
+                       pring = &psli->ring[i + MAX_SLI3_CONFIGURED_RINGS];
+                       lpfc_sli_abort_iocb_ring(phba, pring);
+               }
+       } else {
+               pring = &psli->ring[psli->fcp_ring];
+               lpfc_sli_abort_iocb_ring(phba, pring);
+       }
+}
+
+
 /**
  * lpfc_sli_flush_fcp_rings - flush all iocbs in the fcp ring
  * @phba: Pointer to HBA context object.
@@ -3563,28 +3606,55 @@ lpfc_sli_flush_fcp_rings(struct lpfc_hba *phba)
        LIST_HEAD(txcmplq);
        struct lpfc_sli *psli = &phba->sli;
        struct lpfc_sli_ring  *pring;
-
-       /* Currently, only one fcp ring */
-       pring = &psli->ring[psli->fcp_ring];
+       uint32_t i;
 
        spin_lock_irq(&phba->hbalock);
-       /* Retrieve everything on txq */
-       list_splice_init(&pring->txq, &txq);
-
-       /* Retrieve everything on the txcmplq */
-       list_splice_init(&pring->txcmplq, &txcmplq);
-
        /* Indicate the I/O queues are flushed */
        phba->hba_flag |= HBA_FCP_IOQ_FLUSH;
        spin_unlock_irq(&phba->hbalock);
 
-       /* Flush the txq */
-       lpfc_sli_cancel_iocbs(phba, &txq, IOSTAT_LOCAL_REJECT,
-                             IOERR_SLI_DOWN);
+       /* Look on all the FCP Rings for the iotag */
+       if (phba->sli_rev >= LPFC_SLI_REV4) {
+               for (i = 0; i < phba->cfg_fcp_io_channel; i++) {
+                       pring = &psli->ring[i + MAX_SLI3_CONFIGURED_RINGS];
+
+                       spin_lock_irq(&pring->ring_lock);
+                       /* Retrieve everything on txq */
+                       list_splice_init(&pring->txq, &txq);
+                       /* Retrieve everything on the txcmplq */
+                       list_splice_init(&pring->txcmplq, &txcmplq);
+                       pring->txq_cnt = 0;
+                       pring->txcmplq_cnt = 0;
+                       spin_unlock_irq(&pring->ring_lock);
+
+                       /* Flush the txq */
+                       lpfc_sli_cancel_iocbs(phba, &txq,
+                                             IOSTAT_LOCAL_REJECT,
+                                             IOERR_SLI_DOWN);
+                       /* Flush the txcmpq */
+                       lpfc_sli_cancel_iocbs(phba, &txcmplq,
+                                             IOSTAT_LOCAL_REJECT,
+                                             IOERR_SLI_DOWN);
+               }
+       } else {
+               pring = &psli->ring[psli->fcp_ring];
 
-       /* Flush the txcmpq */
-       lpfc_sli_cancel_iocbs(phba, &txcmplq, IOSTAT_LOCAL_REJECT,
-                             IOERR_SLI_DOWN);
+               spin_lock_irq(&phba->hbalock);
+               /* Retrieve everything on txq */
+               list_splice_init(&pring->txq, &txq);
+               /* Retrieve everything on the txcmplq */
+               list_splice_init(&pring->txcmplq, &txcmplq);
+               pring->txq_cnt = 0;
+               pring->txcmplq_cnt = 0;
+               spin_unlock_irq(&phba->hbalock);
+
+               /* Flush the txq */
+               lpfc_sli_cancel_iocbs(phba, &txq, IOSTAT_LOCAL_REJECT,
+                                     IOERR_SLI_DOWN);
+               /* Flush the txcmpq */
+               lpfc_sli_cancel_iocbs(phba, &txcmplq, IOSTAT_LOCAL_REJECT,
+                                     IOERR_SLI_DOWN);
+       }
 }
 
 /**
@@ -3987,12 +4057,13 @@ lpfc_sli4_brdreset(struct lpfc_hba *phba)
 {
        struct lpfc_sli *psli = &phba->sli;
        uint16_t cfg_value;
-       int rc;
+       int rc = 0;
 
        /* Reset HBA */
        lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
-                       "0295 Reset HBA Data: x%x x%x\n",
-                       phba->pport->port_state, psli->sli_flag);
+                       "0295 Reset HBA Data: x%x x%x x%x\n",
+                       phba->pport->port_state, psli->sli_flag,
+                       phba->hba_flag);
 
        /* perform board reset */
        phba->fc_eventTag = 0;
@@ -4005,6 +4076,12 @@ lpfc_sli4_brdreset(struct lpfc_hba *phba)
        phba->fcf.fcf_flag = 0;
        spin_unlock_irq(&phba->hbalock);
 
+       /* SLI4 INTF 2: if FW dump is being taken skip INIT_PORT */
+       if (phba->hba_flag & HBA_FW_DUMP_OP) {
+               phba->hba_flag &= ~HBA_FW_DUMP_OP;
+               return rc;
+       }
+
        /* Now physically reset the device */
        lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
                        "0389 Performing PCI function reset!\n");
@@ -5002,7 +5079,7 @@ lpfc_sli4_arm_cqeq_intr(struct lpfc_hba *phba)
                } while (++fcp_eqidx < phba->cfg_fcp_io_channel);
        }
 
-       if (phba->cfg_EnableXLane)
+       if (phba->cfg_fof)
                lpfc_sli4_cq_release(phba->sli4_hba.oas_cq, LPFC_QUEUE_REARM);
 
        if (phba->sli4_hba.hba_eq) {
@@ -6722,7 +6799,6 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba)
        LPFC_MBOXQ_t *pmbox = phba->sli.mbox_active;
        MAILBOX_t *mb = &pmbox->u.mb;
        struct lpfc_sli *psli = &phba->sli;
-       struct lpfc_sli_ring *pring;
 
        /* If the mailbox completed, process the completion and return */
        if (lpfc_sli4_process_missed_mbox_completions(phba))
@@ -6764,8 +6840,7 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba)
        psli->sli_flag &= ~LPFC_SLI_ACTIVE;
        spin_unlock_irq(&phba->hbalock);
 
-       pring = &psli->ring[psli->fcp_ring];
-       lpfc_sli_abort_iocb_ring(phba, pring);
+       lpfc_sli_abort_fcp_rings(phba);
 
        lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
                        "0345 Resetting board due to mailbox timeout\n");
@@ -8133,6 +8208,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
        abort_tag = (uint32_t) iocbq->iotag;
        xritag = iocbq->sli4_xritag;
        wqe->generic.wqe_com.word7 = 0; /* The ct field has moved so reset */
+       wqe->generic.wqe_com.word10 = 0;
        /* words0-2 bpl convert bde */
        if (iocbq->iocb.un.genreq64.bdl.bdeFlags == BUFF_TYPE_BLP_64) {
                numBdes = iocbq->iocb.un.genreq64.bdl.bdeSize /
@@ -8639,8 +8715,7 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number,
 
        if ((piocb->iocb_flag & LPFC_IO_FCP) ||
            (piocb->iocb_flag & LPFC_USE_FCPWQIDX)) {
-               if (!phba->cfg_EnableXLane || (!(piocb->iocb_flag &
-                       LPFC_IO_OAS))) {
+               if (!phba->cfg_fof || (!(piocb->iocb_flag & LPFC_IO_OAS))) {
                        wq = phba->sli4_hba.fcp_wq[piocb->fcp_wqidx];
                } else {
                        wq = phba->sli4_hba.oas_wq;
@@ -8735,7 +8810,7 @@ lpfc_sli_issue_iocb(struct lpfc_hba *phba, uint32_t ring_number,
 
        if (phba->sli_rev == LPFC_SLI_REV4) {
                if (piocb->iocb_flag &  LPFC_IO_FCP) {
-                       if (!phba->cfg_EnableXLane || (!(piocb->iocb_flag &
+                       if (!phba->cfg_fof || (!(piocb->iocb_flag &
                                LPFC_IO_OAS))) {
                                if (unlikely(!phba->sli4_hba.fcp_wq))
                                        return IOCB_ERROR;
@@ -9170,6 +9245,7 @@ lpfc_sli_queue_setup(struct lpfc_hba *phba)
                pring->sli.sli3.next_cmdidx  = 0;
                pring->sli.sli3.local_getidx = 0;
                pring->sli.sli3.cmdidx = 0;
+               pring->flag = 0;
                INIT_LIST_HEAD(&pring->txq);
                INIT_LIST_HEAD(&pring->txcmplq);
                INIT_LIST_HEAD(&pring->iocb_continueq);
@@ -9804,43 +9880,6 @@ abort_iotag_exit:
        return retval;
 }
 
-/**
- * lpfc_sli_iocb_ring_abort - Unconditionally abort all iocbs on an iocb ring
- * @phba: Pointer to HBA context object.
- * @pring: Pointer to driver SLI ring object.
- *
- * This function aborts all iocbs in the given ring and frees all the iocb
- * objects in txq. This function issues abort iocbs unconditionally for all
- * the iocb commands in txcmplq. The iocbs in the txcmplq is not guaranteed
- * to complete before the return of this function. The caller is not required
- * to hold any locks.
- **/
-static void
-lpfc_sli_iocb_ring_abort(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
-{
-       LIST_HEAD(completions);
-       struct lpfc_iocbq *iocb, *next_iocb;
-
-       if (pring->ringno == LPFC_ELS_RING)
-               lpfc_fabric_abort_hba(phba);
-
-       spin_lock_irq(&phba->hbalock);
-
-       /* Take off all the iocbs on txq for cancelling */
-       list_splice_init(&pring->txq, &completions);
-       pring->txq_cnt = 0;
-
-       /* Next issue ABTS for everything on the txcmplq */
-       list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list)
-               lpfc_sli_abort_iotag_issue(phba, pring, iocb);
-
-       spin_unlock_irq(&phba->hbalock);
-
-       /* Cancel all the IOCBs from the completions list */
-       lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
-                             IOERR_SLI_ABORTED);
-}
-
 /**
  * lpfc_sli_hba_iocb_abort - Abort all iocbs to an hba.
  * @phba: pointer to lpfc HBA data structure.
@@ -9856,7 +9895,7 @@ lpfc_sli_hba_iocb_abort(struct lpfc_hba *phba)
 
        for (i = 0; i < psli->num_rings; i++) {
                pring = &psli->ring[i];
-               lpfc_sli_iocb_ring_abort(phba, pring);
+               lpfc_sli_abort_iocb_ring(phba, pring);
        }
 }
 
@@ -10080,6 +10119,124 @@ lpfc_sli_abort_iocb(struct lpfc_vport *vport, struct lpfc_sli_ring *pring,
        return errcnt;
 }
 
+/**
+ * lpfc_sli_abort_taskmgmt - issue abort for all commands on a host/target/LUN
+ * @vport: Pointer to virtual port.
+ * @pring: Pointer to driver SLI ring object.
+ * @tgt_id: SCSI ID of the target.
+ * @lun_id: LUN ID of the scsi device.
+ * @taskmgmt_cmd: LPFC_CTX_LUN/LPFC_CTX_TGT/LPFC_CTX_HOST.
+ *
+ * This function sends an abort command for every SCSI command
+ * associated with the given virtual port pending on the ring
+ * filtered by lpfc_sli_validate_fcp_iocb function.
+ * When taskmgmt_cmd == LPFC_CTX_LUN, the function sends abort only to the
+ * FCP iocbs associated with lun specified by tgt_id and lun_id
+ * parameters
+ * When taskmgmt_cmd == LPFC_CTX_TGT, the function sends abort only to the
+ * FCP iocbs associated with SCSI target specified by tgt_id parameter.
+ * When taskmgmt_cmd == LPFC_CTX_HOST, the function sends abort to all
+ * FCP iocbs associated with virtual port.
+ * This function returns number of iocbs it aborted .
+ * This function is called with no locks held right after a taskmgmt
+ * command is sent.
+ **/
+int
+lpfc_sli_abort_taskmgmt(struct lpfc_vport *vport, struct lpfc_sli_ring *pring,
+                       uint16_t tgt_id, uint64_t lun_id, lpfc_ctx_cmd cmd)
+{
+       struct lpfc_hba *phba = vport->phba;
+       struct lpfc_iocbq *abtsiocbq;
+       struct lpfc_iocbq *iocbq;
+       IOCB_t *icmd;
+       int sum, i, ret_val;
+       unsigned long iflags;
+       struct lpfc_sli_ring *pring_s4;
+       uint32_t ring_number;
+
+       spin_lock_irq(&phba->hbalock);
+
+       /* all I/Os are in process of being flushed */
+       if (phba->hba_flag & HBA_FCP_IOQ_FLUSH) {
+               spin_unlock_irq(&phba->hbalock);
+               return 0;
+       }
+       sum = 0;
+
+       for (i = 1; i <= phba->sli.last_iotag; i++) {
+               iocbq = phba->sli.iocbq_lookup[i];
+
+               if (lpfc_sli_validate_fcp_iocb(iocbq, vport, tgt_id, lun_id,
+                                              cmd) != 0)
+                       continue;
+
+               /*
+                * If the iocbq is already being aborted, don't take a second
+                * action, but do count it.
+                */
+               if (iocbq->iocb_flag & LPFC_DRIVER_ABORTED)
+                       continue;
+
+               /* issue ABTS for this IOCB based on iotag */
+               abtsiocbq = __lpfc_sli_get_iocbq(phba);
+               if (abtsiocbq == NULL)
+                       continue;
+
+               icmd = &iocbq->iocb;
+               abtsiocbq->iocb.un.acxri.abortType = ABORT_TYPE_ABTS;
+               abtsiocbq->iocb.un.acxri.abortContextTag = icmd->ulpContext;
+               if (phba->sli_rev == LPFC_SLI_REV4)
+                       abtsiocbq->iocb.un.acxri.abortIoTag =
+                                                        iocbq->sli4_xritag;
+               else
+                       abtsiocbq->iocb.un.acxri.abortIoTag = icmd->ulpIoTag;
+               abtsiocbq->iocb.ulpLe = 1;
+               abtsiocbq->iocb.ulpClass = icmd->ulpClass;
+               abtsiocbq->vport = vport;
+
+               /* ABTS WQE must go to the same WQ as the WQE to be aborted */
+               abtsiocbq->fcp_wqidx = iocbq->fcp_wqidx;
+               if (iocbq->iocb_flag & LPFC_IO_FCP)
+                       abtsiocbq->iocb_flag |= LPFC_USE_FCPWQIDX;
+
+               if (lpfc_is_link_up(phba))
+                       abtsiocbq->iocb.ulpCommand = CMD_ABORT_XRI_CN;
+               else
+                       abtsiocbq->iocb.ulpCommand = CMD_CLOSE_XRI_CN;
+
+               /* Setup callback routine and issue the command. */
+               abtsiocbq->iocb_cmpl = lpfc_sli_abort_fcp_cmpl;
+
+               /*
+                * Indicate the IO is being aborted by the driver and set
+                * the caller's flag into the aborted IO.
+                */
+               iocbq->iocb_flag |= LPFC_DRIVER_ABORTED;
+
+               if (phba->sli_rev == LPFC_SLI_REV4) {
+                       ring_number = MAX_SLI3_CONFIGURED_RINGS +
+                                        iocbq->fcp_wqidx;
+                       pring_s4 = &phba->sli.ring[ring_number];
+                       /* Note: both hbalock and ring_lock must be set here */
+                       spin_lock_irqsave(&pring_s4->ring_lock, iflags);
+                       ret_val = __lpfc_sli_issue_iocb(phba, pring_s4->ringno,
+                                                       abtsiocbq, 0);
+                       spin_unlock_irqrestore(&pring_s4->ring_lock, iflags);
+               } else {
+                       ret_val = __lpfc_sli_issue_iocb(phba, pring->ringno,
+                                                       abtsiocbq, 0);
+               }
+
+
+               if (ret_val == IOCB_ERROR)
+                       __lpfc_sli_release_iocbq(phba, abtsiocbq);
+               else
+                       sum++;
+       }
+       spin_unlock_irq(&phba->hbalock);
+       return sum;
+}
+
 /**
  * lpfc_sli_wake_iocb_wait - lpfc_sli_issue_iocb_wait's completion handler
  * @phba: Pointer to HBA context object.