[SCSI] qla2xxx: Enable target mode support for ISP83xx.
authorArun Easi <arun.easi@qlogic.com>
Wed, 30 Jan 2013 08:34:39 +0000 (03:34 -0500)
committerJames Bottomley <JBottomley@Parallels.com>
Fri, 22 Feb 2013 11:32:12 +0000 (11:32 +0000)
Signed-off-by: Arun Easi <arun.easi@qlogic.com>
Signed-off-by: Saurav Kashyap <saurav.kashyap@qlogic.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
drivers/scsi/qla2xxx/qla_dbg.c
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_fw.h
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_isr.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/qla2xxx/qla_target.c
drivers/scsi/qla2xxx/qla_target.h

index f7cdd259ef0b947018cb2b59e1bc9817c44be1a8..e690d052246aa33a2c0ffcd5eb88f675a5fd8b1c 100644 (file)
@@ -39,7 +39,7 @@
  * | MultiQ                       |       0xc00c       |               |
  * | Misc                         |       0xd010       |               |
  * | Target Mode                 |       0xe06f       |                |
- * | Target Mode Management      |       0xf071       |                |
+ * | Target Mode Management      |       0xf072       |                |
  * | Target Mode Task Management  |      0x1000b      |                |
  * ----------------------------------------------------------------------
  */
index 06c6271d5911fd7d6882474a795e0f6f6cf56e23..b5fc478e90c1ae3ccdb07838042602f120342875 100644 (file)
@@ -537,6 +537,8 @@ struct device_reg_25xxmq {
        uint32_t req_q_out;
        uint32_t rsp_q_in;
        uint32_t rsp_q_out;
+       uint32_t atio_q_in;
+       uint32_t atio_q_out;
 };
 
 typedef union {
@@ -563,6 +565,9 @@ typedef union {
         &(reg)->u.isp2100.mailbox5 : \
         &(reg)->u.isp2300.rsp_q_out)
 
+#define ISP_ATIO_Q_IN(vha) (vha->hw->tgt.atio_q_in)
+#define ISP_ATIO_Q_OUT(vha) (vha->hw->tgt.atio_q_out)
+
 #define MAILBOX_REG(ha, reg, num) \
        (IS_QLA2100(ha) || IS_QLA2200(ha) ? \
         (num < 8 ? \
@@ -2559,6 +2564,8 @@ struct qlt_hw_data {
        struct atio *atio_ring_ptr;     /* Current address. */
        uint16_t atio_ring_index; /* Current index. */
        uint16_t atio_q_length;
+       uint32_t __iomem *atio_q_in;
+       uint32_t __iomem *atio_q_out;
 
        void *target_lport_ptr;
        struct qla_tgt_func_tmpl *tgt_ops;
@@ -2790,6 +2797,7 @@ struct qla_hw_data {
 #define IS_PI_SPLIT_DET_CAPABLE_HBA(ha)        (IS_QLA83XX(ha))
 #define IS_PI_SPLIT_DET_CAPABLE(ha)    (IS_PI_SPLIT_DET_CAPABLE_HBA(ha) && \
     (((ha)->fw_attributes_h << 16 | (ha)->fw_attributes) & BIT_22))
+#define IS_ATIO_MSIX_CAPABLE(ha) (IS_QLA83XX(ha))
 
        /* HBA serial number */
        uint8_t         serial0;
index be6d61a89edcb812fa57db086fe26e58e6af10ed..7105d5e794e4ae7d04a20fe987a50000a1606f9c 100644 (file)
@@ -300,7 +300,8 @@ struct init_cb_24xx {
        uint32_t prio_request_q_address[2];
 
        uint16_t msix;
-       uint8_t reserved_2[6];
+       uint16_t msix_atio;
+       uint8_t reserved_2[4];
 
        uint16_t atio_q_inpointer;
        uint16_t atio_q_length;
index 81e8ccacf55bbb124345ae457e5b29505ab902dc..a581c850ad741cf6d95953195d4ea39c1b375d9a 100644 (file)
@@ -1964,7 +1964,7 @@ qla24xx_config_rings(struct scsi_qla_host *vha)
                WRT_REG_DWORD(&reg->isp24.rsp_q_in, 0);
                WRT_REG_DWORD(&reg->isp24.rsp_q_out, 0);
        }
-       qlt_24xx_config_rings(vha, reg);
+       qlt_24xx_config_rings(vha);
 
        /* PCI posting */
        RD_REG_DWORD(&ioreg->hccr);
@@ -5579,6 +5579,8 @@ qla81xx_nvram_config(scsi_qla_host_t *vha)
        if (IS_T10_PI_CAPABLE(ha))
                nv->frame_payload_size &= ~7;
 
+       qlt_81xx_config_nvram_stage1(vha, nv);
+
        /* Reset Initialization control block */
        memset(icb, 0, ha->init_cb_size);
 
@@ -5619,6 +5621,8 @@ qla81xx_nvram_config(scsi_qla_host_t *vha)
        qla2x00_set_model_info(vha, nv->model_name, sizeof(nv->model_name),
            "QLE8XXX");
 
+       qlt_81xx_config_nvram_stage2(vha, icb);
+
        /* Use alternate WWN? */
        if (nv->host_p & __constant_cpu_to_le32(BIT_15)) {
                memcpy(icb->node_name, nv->alternate_node_name, WWN_SIZE);
index 1b192c8bb133102a6612ec16ef2d615a6e2ba32f..26a3086a7e3a403ba8ac6ab88104266896a767c2 100644 (file)
@@ -13,6 +13,8 @@
 #include <scsi/scsi_bsg_fc.h>
 #include <scsi/scsi_eh.h>
 
+#include "qla_target.h"
+
 static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t);
 static void qla2x00_process_completed_request(struct scsi_qla_host *,
        struct req_que *, uint32_t);
@@ -2751,6 +2753,12 @@ static struct qla_init_msix_entry qla82xx_msix_entries[2] = {
        { "qla2xxx (rsp_q)", qla82xx_msix_rsp_q },
 };
 
+static struct qla_init_msix_entry qla83xx_msix_entries[3] = {
+       { "qla2xxx (default)", qla24xx_msix_default },
+       { "qla2xxx (rsp_q)", qla24xx_msix_rsp_q },
+       { "qla2xxx (atio_q)", qla83xx_msix_atio_q },
+};
+
 static void
 qla24xx_disable_msix(struct qla_hw_data *ha)
 {
@@ -2831,9 +2839,13 @@ msix_failed:
        }
 
        /* Enable MSI-X vectors for the base queue */
-       for (i = 0; i < 2; i++) {
+       for (i = 0; i < ha->msix_count; i++) {
                qentry = &ha->msix_entries[i];
-               if (IS_QLA82XX(ha)) {
+               if (QLA_TGT_MODE_ENABLED() && IS_ATIO_MSIX_CAPABLE(ha)) {
+                       ret = request_irq(qentry->vector,
+                               qla83xx_msix_entries[i].handler,
+                               0, qla83xx_msix_entries[i].name, rsp);
+               } else if (IS_QLA82XX(ha)) {
                        ret = request_irq(qentry->vector,
                                qla82xx_msix_entries[i].handler,
                                0, qla82xx_msix_entries[i].name, rsp);
index da86d3828c1d985d8bec11b2303781a08c10ad68..e93408f8e7e1c9212c513d8f929d5154b2e0007c 100644 (file)
@@ -1812,6 +1812,9 @@ qla83xx_iospace_config(struct qla_hw_data *ha)
 
 mqiobase_exit:
        ha->msix_count = ha->max_rsp_queues + 1;
+
+       qlt_83xx_iospace_config(ha);
+
        ql_dbg_pci(ql_dbg_init, ha->pdev, 0x011f,
            "MSIX Count:%d.\n", ha->msix_count);
        return 0;
@@ -2390,6 +2393,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
                ha->mbx_count = MAILBOX_REGISTER_COUNT;
                req_length = REQUEST_ENTRY_CNT_24XX;
                rsp_length = RESPONSE_ENTRY_CNT_2300;
+               ha->tgt.atio_q_length = ATIO_ENTRY_CNT_24XX;
                ha->max_loop_id = SNS_LAST_LOOP_ID_2300;
                ha->init_cb_size = sizeof(struct mid_init_cb_81xx);
                ha->gid_list_info_size = 8;
index aa2e86917a0a7a4c36515ec0a75e059d3f94e4f6..cb8ea4463886c288977b994c9f9686912ecdad65 100644 (file)
@@ -52,7 +52,7 @@ MODULE_PARM_DESC(qlini_mode,
        "\"disabled\" - initiator mode will never be enabled; "
        "\"enabled\" (default) - initiator mode will always stay enabled.");
 
-static int ql2x_ini_mode = QLA2XXX_INI_MODE_EXCLUSIVE;
+int ql2x_ini_mode = QLA2XXX_INI_MODE_EXCLUSIVE;
 
 /*
  * From scsi/fc/fc_fcp.h
@@ -1119,6 +1119,7 @@ static void qlt_send_notify_ack(struct scsi_qla_host *vha,
        nack->u.isp24.srr_rx_id = ntfy->u.isp24.srr_rx_id;
        nack->u.isp24.status = ntfy->u.isp24.status;
        nack->u.isp24.status_subcode = ntfy->u.isp24.status_subcode;
+       nack->u.isp24.fw_handle = ntfy->u.isp24.fw_handle;
        nack->u.isp24.exchange_address = ntfy->u.isp24.exchange_address;
        nack->u.isp24.srr_rel_offs = ntfy->u.isp24.srr_rel_offs;
        nack->u.isp24.srr_ui = ntfy->u.isp24.srr_ui;
@@ -4666,7 +4667,6 @@ void
 qlt_24xx_process_atio_queue(struct scsi_qla_host *vha)
 {
        struct qla_hw_data *ha = vha->hw;
-       struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
        struct atio_from_isp *pkt;
        int cnt, i;
 
@@ -4694,26 +4694,28 @@ qlt_24xx_process_atio_queue(struct scsi_qla_host *vha)
        }
 
        /* Adjust ring index */
-       WRT_REG_DWORD(&reg->atio_q_out, ha->tgt.atio_ring_index);
+       WRT_REG_DWORD(ISP_ATIO_Q_OUT(vha), ha->tgt.atio_ring_index);
 }
 
 void
-qlt_24xx_config_rings(struct scsi_qla_host *vha, device_reg_t __iomem *reg)
+qlt_24xx_config_rings(struct scsi_qla_host *vha)
 {
        struct qla_hw_data *ha = vha->hw;
+       if (!QLA_TGT_MODE_ENABLED())
+               return;
 
-/* FIXME: atio_q in/out for ha->mqenable=1..? */
-       if (ha->mqenable) {
-#if 0
-               WRT_REG_DWORD(&reg->isp25mq.atio_q_in, 0);
-               WRT_REG_DWORD(&reg->isp25mq.atio_q_out, 0);
-               RD_REG_DWORD(&reg->isp25mq.atio_q_out);
-#endif
-       } else {
-               /* Setup APTIO registers for target mode */
-               WRT_REG_DWORD(&reg->isp24.atio_q_in, 0);
-               WRT_REG_DWORD(&reg->isp24.atio_q_out, 0);
-               RD_REG_DWORD(&reg->isp24.atio_q_out);
+       WRT_REG_DWORD(ISP_ATIO_Q_IN(vha), 0);
+       WRT_REG_DWORD(ISP_ATIO_Q_OUT(vha), 0);
+       RD_REG_DWORD(ISP_ATIO_Q_OUT(vha));
+
+       if (IS_ATIO_MSIX_CAPABLE(ha)) {
+               struct qla_msix_entry *msix = &ha->msix_entries[2];
+               struct init_cb_24xx *icb = (struct init_cb_24xx *)ha->init_cb;
+
+               icb->msix_atio = cpu_to_le16(msix->entry);
+               ql_dbg(ql_dbg_init, vha, 0xf072,
+                   "Registering ICB vector 0x%x for atio que.\n",
+                   msix->entry);
        }
 }
 
@@ -4796,6 +4798,101 @@ qlt_24xx_config_nvram_stage2(struct scsi_qla_host *vha,
        }
 }
 
+void
+qlt_81xx_config_nvram_stage1(struct scsi_qla_host *vha, struct nvram_81xx *nv)
+{
+       struct qla_hw_data *ha = vha->hw;
+
+       if (!QLA_TGT_MODE_ENABLED())
+               return;
+
+       if (qla_tgt_mode_enabled(vha)) {
+               if (!ha->tgt.saved_set) {
+                       /* We save only once */
+                       ha->tgt.saved_exchange_count = nv->exchange_count;
+                       ha->tgt.saved_firmware_options_1 =
+                           nv->firmware_options_1;
+                       ha->tgt.saved_firmware_options_2 =
+                           nv->firmware_options_2;
+                       ha->tgt.saved_firmware_options_3 =
+                           nv->firmware_options_3;
+                       ha->tgt.saved_set = 1;
+               }
+
+               nv->exchange_count = __constant_cpu_to_le16(0xFFFF);
+
+               /* Enable target mode */
+               nv->firmware_options_1 |= __constant_cpu_to_le32(BIT_4);
+
+               /* Disable ini mode, if requested */
+               if (!qla_ini_mode_enabled(vha))
+                       nv->firmware_options_1 |=
+                           __constant_cpu_to_le32(BIT_5);
+
+               /* Disable Full Login after LIP */
+               nv->firmware_options_1 &= __constant_cpu_to_le32(~BIT_13);
+               /* Enable initial LIP */
+               nv->firmware_options_1 &= __constant_cpu_to_le32(~BIT_9);
+               /* Enable FC tapes support */
+               nv->firmware_options_2 |= __constant_cpu_to_le32(BIT_12);
+               /* Disable Full Login after LIP */
+               nv->host_p &= __constant_cpu_to_le32(~BIT_10);
+               /* Enable target PRLI control */
+               nv->firmware_options_2 |= __constant_cpu_to_le32(BIT_14);
+       } else {
+               if (ha->tgt.saved_set) {
+                       nv->exchange_count = ha->tgt.saved_exchange_count;
+                       nv->firmware_options_1 =
+                           ha->tgt.saved_firmware_options_1;
+                       nv->firmware_options_2 =
+                           ha->tgt.saved_firmware_options_2;
+                       nv->firmware_options_3 =
+                           ha->tgt.saved_firmware_options_3;
+               }
+               return;
+       }
+
+       /* out-of-order frames reassembly */
+       nv->firmware_options_3 |= BIT_6|BIT_9;
+
+       if (ha->tgt.enable_class_2) {
+               if (vha->flags.init_done)
+                       fc_host_supported_classes(vha->host) =
+                               FC_COS_CLASS2 | FC_COS_CLASS3;
+
+               nv->firmware_options_2 |= __constant_cpu_to_le32(BIT_8);
+       } else {
+               if (vha->flags.init_done)
+                       fc_host_supported_classes(vha->host) = FC_COS_CLASS3;
+
+               nv->firmware_options_2 &= ~__constant_cpu_to_le32(BIT_8);
+       }
+}
+
+void
+qlt_81xx_config_nvram_stage2(struct scsi_qla_host *vha,
+       struct init_cb_81xx *icb)
+{
+       struct qla_hw_data *ha = vha->hw;
+
+       if (!QLA_TGT_MODE_ENABLED())
+               return;
+
+       if (ha->tgt.node_name_set) {
+               memcpy(icb->node_name, ha->tgt.tgt_node_name, WWN_SIZE);
+               icb->firmware_options_1 |= __constant_cpu_to_le32(BIT_14);
+       }
+}
+
+void
+qlt_83xx_iospace_config(struct qla_hw_data *ha)
+{
+       if (!QLA_TGT_MODE_ENABLED())
+               return;
+
+       ha->msix_count += 1; /* For ATIO Q */
+}
+
 int
 qlt_24xx_process_response_error(struct scsi_qla_host *vha,
        struct sts_entry_24xx *pkt)
@@ -4828,11 +4925,41 @@ qlt_probe_one_stage1(struct scsi_qla_host *base_vha, struct qla_hw_data *ha)
        if (!QLA_TGT_MODE_ENABLED())
                return;
 
+       if  (ha->mqenable || IS_QLA83XX(ha)) {
+               ISP_ATIO_Q_IN(base_vha) = &ha->mqiobase->isp25mq.atio_q_in;
+               ISP_ATIO_Q_OUT(base_vha) = &ha->mqiobase->isp25mq.atio_q_out;
+       } else {
+               ISP_ATIO_Q_IN(base_vha) = &ha->iobase->isp24.atio_q_in;
+               ISP_ATIO_Q_OUT(base_vha) = &ha->iobase->isp24.atio_q_out;
+       }
+
        mutex_init(&ha->tgt.tgt_mutex);
        mutex_init(&ha->tgt.tgt_host_action_mutex);
        qlt_clear_mode(base_vha);
 }
 
+irqreturn_t
+qla83xx_msix_atio_q(int irq, void *dev_id)
+{
+       struct rsp_que *rsp;
+       scsi_qla_host_t *vha;
+       struct qla_hw_data *ha;
+       unsigned long flags;
+
+       rsp = (struct rsp_que *) dev_id;
+       ha = rsp->hw;
+       vha = pci_get_drvdata(ha->pdev);
+
+       spin_lock_irqsave(&ha->hardware_lock, flags);
+
+       qlt_24xx_process_atio_queue(vha);
+       qla24xx_process_response_queue(vha, rsp);
+
+       spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+       return IRQ_HANDLED;
+}
+
 int
 qlt_mem_alloc(struct qla_hw_data *ha)
 {
index fc61d6ab925e5c508b46261d1a7beccd74d7d1a9..ff9ccb9fd036f446fceef58b464bff7f0dfa374c 100644 (file)
@@ -162,7 +162,7 @@ struct imm_ntfy_from_isp {
                        uint16_t srr_rx_id;
                        uint16_t status;
                        uint8_t  status_subcode;
-                       uint8_t  reserved_3;
+                       uint8_t  fw_handle;
                        uint32_t exchange_address;
                        uint32_t srr_rel_offs;
                        uint16_t srr_ui;
@@ -218,7 +218,7 @@ struct nack_to_isp {
                        uint16_t srr_rx_id;
                        uint16_t status;
                        uint8_t  status_subcode;
-                       uint8_t  reserved_3;
+                       uint8_t  fw_handle;
                        uint32_t exchange_address;
                        uint32_t srr_rel_offs;
                        uint16_t srr_ui;
@@ -949,6 +949,7 @@ extern void qlt_update_vp_map(struct scsi_qla_host *, int);
  * is not set. Right now, ha value is ignored.
  */
 #define QLA_TGT_MODE_ENABLED() (ql2x_ini_mode != QLA2XXX_INI_MODE_ENABLED)
+extern int ql2x_ini_mode;
 
 static inline bool qla_tgt_mode_enabled(struct scsi_qla_host *ha)
 {
@@ -986,12 +987,15 @@ extern void qlt_vport_create(struct scsi_qla_host *, struct qla_hw_data *);
 extern void qlt_rff_id(struct scsi_qla_host *, struct ct_sns_req *);
 extern void qlt_init_atio_q_entries(struct scsi_qla_host *);
 extern void qlt_24xx_process_atio_queue(struct scsi_qla_host *);
-extern void qlt_24xx_config_rings(struct scsi_qla_host *,
-       device_reg_t __iomem *);
+extern void qlt_24xx_config_rings(struct scsi_qla_host *);
 extern void qlt_24xx_config_nvram_stage1(struct scsi_qla_host *,
        struct nvram_24xx *);
 extern void qlt_24xx_config_nvram_stage2(struct scsi_qla_host *,
        struct init_cb_24xx *);
+extern void qlt_81xx_config_nvram_stage2(struct scsi_qla_host *,
+       struct init_cb_81xx *);
+extern void qlt_81xx_config_nvram_stage1(struct scsi_qla_host *,
+       struct nvram_81xx *);
 extern int qlt_24xx_process_response_error(struct scsi_qla_host *,
        struct sts_entry_24xx *);
 extern void qlt_modify_vp_config(struct scsi_qla_host *,
@@ -1001,5 +1005,7 @@ extern int qlt_mem_alloc(struct qla_hw_data *);
 extern void qlt_mem_free(struct qla_hw_data *);
 extern void qlt_stop_phase1(struct qla_tgt *);
 extern void qlt_stop_phase2(struct qla_tgt *);
+extern irqreturn_t qla83xx_msix_atio_q(int, void *);
+extern void qlt_83xx_iospace_config(struct qla_hw_data *);
 
 #endif /* __QLA_TARGET_H */