[SCSI] Merge tag 'fcoe-02-19-13' into for-linus
[cascardo/linux.git] / drivers / scsi / qla2xxx / qla_target.c
index 80f4b84..61b5d8c 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;
@@ -1570,7 +1571,7 @@ static inline uint32_t qlt_make_handle(struct scsi_qla_host *vha)
        /* always increment cmd handle */
        do {
                ++h;
-               if (h > MAX_OUTSTANDING_COMMANDS)
+               if (h > DEFAULT_OUTSTANDING_COMMANDS)
                        h = 1; /* 0 is QLA_TGT_NULL_HANDLE */
                if (h == ha->tgt.current_handle) {
                        ql_dbg(ql_dbg_tgt, vha, 0xe04e,
@@ -2441,7 +2442,7 @@ static struct qla_tgt_cmd *qlt_ctio_to_cmd(struct scsi_qla_host *vha,
                        return NULL;
                }
                /* handle-1 is actually used */
-               if (unlikely(handle > MAX_OUTSTANDING_COMMANDS)) {
+               if (unlikely(handle > DEFAULT_OUTSTANDING_COMMANDS)) {
                        ql_dbg(ql_dbg_tgt, vha, 0xe052,
                            "qla_target(%d): Wrong handle %x received\n",
                            vha->vp_idx, handle);
@@ -4305,6 +4306,12 @@ int qlt_add_target(struct qla_hw_data *ha, struct scsi_qla_host *base_vha)
        if (!QLA_TGT_MODE_ENABLED())
                return 0;
 
+       if (!IS_TGT_MODE_CAPABLE(ha)) {
+               ql_log(ql_log_warn, base_vha, 0xe070,
+                   "This adapter does not support target mode.\n");
+               return 0;
+       }
+
        ql_dbg(ql_dbg_tgt, base_vha, 0xe03b,
            "Registering target for host %ld(%p)", base_vha->host_no, ha);
 
@@ -4666,7 +4673,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 +4700,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 +4804,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 +4931,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)
 {