]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/scsi/qla2xxx/qla_isr.c
Merge branch 'x86-ptrace-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[mv-sheeva.git] / drivers / scsi / qla2xxx / qla_isr.c
index 6fc63b98818cfdf76ac25a26b7e20b832914dc5b..ab90329ff2e4877ce57ccd15e1a7ee28ab5acd9f 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <linux/delay.h>
 #include <scsi/scsi_tcq.h>
+#include <scsi/scsi_bsg_fc.h>
 
 static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t);
 static void qla2x00_process_completed_request(struct scsi_qla_host *,
@@ -881,7 +882,9 @@ qla2x00_get_sp_from_handle(scsi_qla_host_t *vha, const char *func,
                    index);
                return NULL;
        }
+
        req->outstanding_cmds[index] = NULL;
+
 done:
        return sp;
 }
@@ -981,6 +984,100 @@ done_post_logio_done_work:
        lio->ctx.free(sp);
 }
 
+static void
+qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
+    struct sts_entry_24xx *pkt, int iocb_type)
+{
+       const char func[] = "ELS_CT_IOCB";
+       const char *type;
+       struct qla_hw_data *ha = vha->hw;
+       srb_t *sp;
+       struct srb_bsg *sp_bsg;
+       struct fc_bsg_job *bsg_job;
+       uint16_t comp_status;
+       uint32_t fw_status[3];
+       uint8_t* fw_sts_ptr;
+
+       sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
+       if (!sp)
+               return;
+       sp_bsg = (struct srb_bsg*)sp->ctx;
+       bsg_job = sp_bsg->bsg_job;
+
+       type = NULL;
+       switch (sp_bsg->ctx.type) {
+       case SRB_ELS_CMD_RPT:
+       case SRB_ELS_CMD_HST:
+               type = "els";
+               break;
+       case SRB_CT_CMD:
+               type = "ct pass-through";
+               break;
+       default:
+               qla_printk(KERN_WARNING, ha,
+                   "%s: Unrecognized SRB: (%p) type=%d.\n", func, sp,
+                   sp_bsg->ctx.type);
+               return;
+       }
+
+       comp_status = fw_status[0] = le16_to_cpu(pkt->comp_status);
+       fw_status[1] = le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->error_subcode_1);
+       fw_status[2] = le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->error_subcode_2);
+
+       /* return FC_CTELS_STATUS_OK and leave the decoding of the ELS/CT
+        * fc payload  to the caller
+        */
+       bsg_job->reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK;
+       bsg_job->reply_len = sizeof(struct fc_bsg_reply) + sizeof(fw_status);
+
+       if (comp_status != CS_COMPLETE) {
+               if (comp_status == CS_DATA_UNDERRUN) {
+                       bsg_job->reply->result = DID_OK << 16;
+                       bsg_job->reply->reply_payload_rcv_len =
+                               le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->total_byte_count);
+
+                       DEBUG2(qla_printk(KERN_WARNING, ha,
+                           "scsi(%ld:0x%x): ELS-CT pass-through-%s error comp_status-status=0x%x "
+                           "error subcode 1=0x%x error subcode 2=0x%x total_byte = 0x%x.\n",
+                               vha->host_no, sp->handle, type, comp_status, fw_status[1], fw_status[2],
+                               le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->total_byte_count)));
+                       fw_sts_ptr = ((uint8_t*)bsg_job->req->sense) + sizeof(struct fc_bsg_reply);
+                       memcpy( fw_sts_ptr, fw_status, sizeof(fw_status));
+               }
+               else {
+                       DEBUG2(qla_printk(KERN_WARNING, ha,
+                           "scsi(%ld:0x%x): ELS-CT pass-through-%s error comp_status-status=0x%x "
+                           "error subcode 1=0x%x error subcode 2=0x%x.\n",
+                               vha->host_no, sp->handle, type, comp_status,
+                               le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->error_subcode_1),
+                               le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->error_subcode_2)));
+                       bsg_job->reply->result = DID_ERROR << 16;
+                       bsg_job->reply->reply_payload_rcv_len = 0;
+                       fw_sts_ptr = ((uint8_t*)bsg_job->req->sense) + sizeof(struct fc_bsg_reply);
+                       memcpy( fw_sts_ptr, fw_status, sizeof(fw_status));
+               }
+               DEBUG2(qla2x00_dump_buffer((uint8_t *)pkt, sizeof(*pkt)));
+       }
+       else {
+               bsg_job->reply->result =  DID_OK << 16;;
+               bsg_job->reply->reply_payload_rcv_len = bsg_job->reply_payload.payload_len;
+               bsg_job->reply_len = 0;
+       }
+
+       dma_unmap_sg(&ha->pdev->dev,
+           bsg_job->request_payload.sg_list,
+           bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
+       dma_unmap_sg(&ha->pdev->dev,
+           bsg_job->reply_payload.sg_list,
+           bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
+       if ((sp_bsg->ctx.type == SRB_ELS_CMD_HST) ||
+           (sp_bsg->ctx.type == SRB_CT_CMD))
+               kfree(sp->fcport);
+       kfree(sp->ctx);
+       mempool_free(sp, ha->srb_mempool);
+       bsg_job->job_done(bsg_job);
+}
+
 static void
 qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
     struct logio_entry_24xx *logio)
@@ -1749,6 +1846,13 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
                        qla24xx_logio_entry(vha, rsp->req,
                            (struct logio_entry_24xx *)pkt);
                        break;
+                case CT_IOCB_TYPE:
+                       qla24xx_els_ct_entry(vha, rsp->req, pkt, CT_IOCB_TYPE);
+                       clear_bit(MBX_INTERRUPT, &vha->hw->mbx_cmd_flags);
+                       break;
+                case ELS_IOCB_TYPE:
+                       qla24xx_els_ct_entry(vha, rsp->req, pkt, ELS_IOCB_TYPE);
+                       break;
                default:
                        /* Type Not Supported. */
                        DEBUG4(printk(KERN_WARNING
@@ -2049,7 +2153,6 @@ qla24xx_msix_default(int irq, void *dev_id)
                set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
                complete(&ha->mbx_intr_comp);
        }
-
        return IRQ_HANDLED;
 }
 
@@ -2255,10 +2358,11 @@ qla2x00_free_irqs(scsi_qla_host_t *vha)
 
        if (ha->flags.msix_enabled)
                qla24xx_disable_msix(ha);
-       else if (ha->flags.inta_enabled) {
+       else if (ha->flags.msi_enabled) {
                free_irq(ha->pdev->irq, rsp);
                pci_disable_msi(ha->pdev);
-       }
+       } else
+               free_irq(ha->pdev->irq, rsp);
 }