patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / drivers / scsi / qla2xxx / qla_os.c
index 788aa7a..cf3b812 100644 (file)
@@ -168,7 +168,6 @@ static struct scsi_host_template qla2x00_driver_template = {
        .slave_configure        = qla2xxx_slave_configure,
 
        .this_id                = -1,
-       .can_queue              = REQUEST_ENTRY_CNT+128,
        .cmd_per_lun            = 3,
        .use_clustering         = ENABLE_CLUSTERING,
        .sg_tablesize           = SG_ALL,
@@ -776,10 +775,13 @@ qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*fn)(struct scsi_cmnd *))
 
        /* Only modify the allowed count if the target is a *non* tape device */
        if ((fcport->flags & FCF_TAPE_PRESENT) == 0) {
+               sp->flags &= ~SRB_TAPE;
                if (cmd->allowed < ql2xretrycount) {
                        cmd->allowed = ql2xretrycount;
                }
-       }
+       } else
+               sp->flags |= SRB_TAPE;
+
 
        DEBUG5(printk("scsi(%ld:%2d:%2d): (queuecmd) queue sp = %p, "
            "flags=0x%x fo retry=%d, pid=%ld\n",
@@ -808,7 +810,7 @@ qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*fn)(struct scsi_cmnd *))
            atomic_read(&ha2->loop_state) == LOOP_DEAD) {
                /*
                 * Add the command to the done-queue for later failover
-                * processing
+                * processing.
                 */
                cmd->result = DID_NO_CONNECT << 16;
                if (atomic_read(&ha2->loop_state) == LOOP_DOWN) 
@@ -822,7 +824,8 @@ qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*fn)(struct scsi_cmnd *))
                spin_lock_irq(ha->host->host_lock);
                return (0);
        }
-       if (tq && test_bit(TQF_SUSPENDED, &tq->flags)) {
+       if (tq && test_bit(TQF_SUSPENDED, &tq->flags) &&
+           (sp->flags & SRB_TAPE) == 0) {
                /* If target suspended put incoming I/O in retry_q. */
                qla2x00_extend_timeout(sp->cmd, 10);
                add_to_scsi_retry_queue(ha, sp);
@@ -834,7 +837,7 @@ qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*fn)(struct scsi_cmnd *))
                device_reg_t *reg;
                reg = ha->iobase;
                
-               if (RD_REG_WORD(ISP_RSP_Q_IN(ha, reg)) != ha->rsp_ring_index) {
+               if (ha->response_ring_ptr->signature != RESPONSE_PROCESSED) {
                        spin_lock_irqsave(&ha->hardware_lock, flags);   
                        qla2x00_process_response_queue(ha);
                        spin_unlock_irqrestore(&ha->hardware_lock, flags);
@@ -914,7 +917,7 @@ qla2x00_eh_wait_on_command(scsi_qla_host_t *ha, struct scsi_cmnd *cmd)
 
                spin_unlock_irq(ha->host->host_lock);
 
-               set_current_state(TASK_INTERRUPTIBLE);
+               set_current_state(TASK_UNINTERRUPTIBLE);
                schedule_timeout(2*HZ);
 
                spin_lock_irq(ha->host->host_lock);
@@ -962,7 +965,7 @@ qla2x00_wait_for_hba_online(scsi_qla_host_t *ha)
            test_bit(ISP_ABORT_RETRY, &ha->dpc_flags)) &&
                time_before(jiffies, wait_online)) {
 
-               set_current_state(TASK_INTERRUPTIBLE);
+               set_current_state(TASK_UNINTERRUPTIBLE);
                schedule_timeout(HZ);
        }
        if (ha->flags.online == TRUE) 
@@ -1005,7 +1008,7 @@ qla2x00_wait_for_loop_ready(scsi_qla_host_t *ha)
            atomic_read(&ha->loop_state) == LOOP_DOWN) ||
            test_bit(CFG_ACTIVE, &ha->cfg_flags) ||
            atomic_read(&ha->loop_state) != LOOP_READY) {
-               set_current_state(TASK_INTERRUPTIBLE);
+               set_current_state(TASK_UNINTERRUPTIBLE);
                schedule_timeout(HZ);
                if (time_after_eq(jiffies, loop_timeout)) {
                        return_status = QLA_FUNCTION_FAILED;
@@ -1783,10 +1786,9 @@ qla2xxx_slave_configure(struct scsi_device *sdev)
                queue_depth = 32;
 
        if (sdev->tagged_supported) {
-#if defined(MODULE)
-               if (!(ql2xmaxqdepth == 0 || ql2xmaxqdepth > 256))
+               if (ql2xmaxqdepth != 0 && ql2xmaxqdepth <= 0xffffU)
                        queue_depth = ql2xmaxqdepth;
-#endif 
+
                ql2xmaxqdepth = queue_depth;
 
                scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth);
@@ -1983,19 +1985,24 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
        if (IS_QLA2100(ha)) {
                ha->max_targets = MAX_TARGETS_2100;
                ha->mbx_count = MAILBOX_REGISTER_COUNT_2100;
+               ha->request_q_length = REQUEST_ENTRY_CNT_2100;
                ha->response_q_length = RESPONSE_ENTRY_CNT_2100;
                ha->last_loop_id = SNS_LAST_LOOP_ID_2100;
+               host->sg_tablesize = 32;
        } else if (IS_QLA2200(ha)) {
                ha->max_targets = MAX_TARGETS_2200;
                ha->mbx_count = MAILBOX_REGISTER_COUNT;
+               ha->request_q_length = REQUEST_ENTRY_CNT_2200;
                ha->response_q_length = RESPONSE_ENTRY_CNT_2100;
                ha->last_loop_id = SNS_LAST_LOOP_ID_2100;
        } else /*if (IS_QLA2300(ha))*/ {
                ha->max_targets = MAX_TARGETS_2200;
                ha->mbx_count = MAILBOX_REGISTER_COUNT;
+               ha->request_q_length = REQUEST_ENTRY_CNT_2200;
                ha->response_q_length = RESPONSE_ENTRY_CNT_2300;
                ha->last_loop_id = SNS_LAST_LOOP_ID_2300;
        }
+       host->can_queue = ha->request_q_length + 128;
 
        /* load the F/W, read paramaters, and init the H/W */
        ha->instance = num_hosts;
@@ -2020,6 +2027,7 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
        spin_lock_init(&ha->mbx_reg_lock);
        spin_lock_init(&ha->list_lock);
 
+       ha->dpc_pid = -1;
        init_completion(&ha->dpc_inited);
        init_completion(&ha->dpc_exited);
 
@@ -2125,8 +2133,8 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
 
                qla2x00_check_fabric_devices(ha);
 
-               set_current_state(TASK_INTERRUPTIBLE);
-               schedule_timeout(5);
+               set_current_state(TASK_UNINTERRUPTIBLE);
+               schedule_timeout(HZ/100);
        }
 
        pci_set_drvdata(pdev, ha);
@@ -2313,18 +2321,17 @@ qla2x00_proc_info(struct Scsi_Host *shost, char *buffer,
     char **start, off_t offset, int length, int inout)
 {
        struct info_str info;
-       int             i;
        int             retval = -EINVAL;
        os_lun_t        *up;
-       fc_port_t       *fcport;
+       os_tgt_t        *tq;
        unsigned int    t, l;
        uint32_t        tmp_sn;
-       unsigned long   *flags;
+       uint32_t        *flags;
        uint8_t         *loop_state;
        int     found;
        scsi_qla_host_t *ha;
        char fw_info[30];
-
        DEBUG3(printk(KERN_INFO
            "Entering proc_info buff_in=%p, offset=0x%lx, length=0x%x\n",
            buffer, offset, length);)
@@ -2390,8 +2397,8 @@ qla2x00_proc_info(struct Scsi_Host *shost, char *buffer,
                (unsigned long long)ha->response_dma);
 
        copy_info(&info,
-           "Request Queue count = %ld, Response Queue count = %ld\n",
-           (long)REQUEST_ENTRY_CNT, (long)ha->response_q_length);
+           "Request Queue count = %d, Response Queue count = %d\n",
+           ha->request_q_length, ha->response_q_length);
 
        copy_info(&info,
            "Total number of active commands = %ld\n",
@@ -2428,7 +2435,7 @@ qla2x00_proc_info(struct Scsi_Host *shost, char *buffer,
            ha->done_q_cnt, ha->scsi_retry_q_cnt);
 
 
-       flags = (unsigned long *) &ha->flags;
+       flags = (uint32_t *) &ha->flags;
 
        if (atomic_read(&ha->loop_state) == LOOP_DOWN) {
                loop_state = "DOWN";
@@ -2502,24 +2509,19 @@ qla2x00_proc_info(struct Scsi_Host *shost, char *buffer,
            ha->init_cb->port_name[7]);
 
        /* Print out device port names */
-       i = 0;
-       list_for_each_entry(fcport, &ha->fcports, list) {
-               if (fcport->port_type != FCT_TARGET)
+       for (t = 0; t < MAX_FIBRE_DEVICES; t++) {
+               if ((tq = TGT_Q(ha, t)) == NULL)
                        continue;
 
                copy_info(&info,
                    "scsi-qla%d-target-%d="
-                   "%02x%02x%02x%02x%02x%02x%02x%02x:%02x%02x%02x;\n",
-                   (int)ha->instance, i,
-                   fcport->port_name[0], fcport->port_name[1],
-                   fcport->port_name[2], fcport->port_name[3],
-                   fcport->port_name[4], fcport->port_name[5],
-                   fcport->port_name[6], fcport->port_name[7],
-                   fcport->d_id.b.domain, fcport->d_id.b.area,
-                   fcport->d_id.b.al_pa);
-               i++;
+                   "%02x%02x%02x%02x%02x%02x%02x%02x;\n",
+                   (int)ha->instance, t,
+                   tq->port_name[0], tq->port_name[1],
+                   tq->port_name[2], tq->port_name[3],
+                   tq->port_name[4], tq->port_name[5],
+                   tq->port_name[6], tq->port_name[7]);
        }
-
        copy_info(&info, "\nSCSI LUN Information:\n");
        copy_info(&info,
            "(Id:Lun)  * - indicates lun is not registered with the OS.\n");
@@ -2861,14 +2863,14 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha)
                 * little delay and a retry.
                 */
                ha->request_ring = pci_alloc_consistent(ha->pdev,
-                   ((REQUEST_ENTRY_CNT + 1) * (sizeof(request_t))),
+                   ((ha->request_q_length + 1) * (sizeof(request_t))),
                    &ha->request_dma);
                if (ha->request_ring == NULL) {
                        qla_printk(KERN_WARNING, ha,
                            "Memory Allocation failed - request_ring\n");
 
                        qla2x00_mem_free(ha);
-                       set_current_state(TASK_INTERRUPTIBLE);
+                       set_current_state(TASK_UNINTERRUPTIBLE);
                        schedule_timeout(HZ/10);
 
                        continue;
@@ -2882,7 +2884,7 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha)
                            "Memory Allocation failed - response_ring\n");
 
                        qla2x00_mem_free(ha);
-                       set_current_state(TASK_INTERRUPTIBLE);
+                       set_current_state(TASK_UNINTERRUPTIBLE);
                        schedule_timeout(HZ/10);
 
                        continue;
@@ -2896,7 +2898,7 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha)
                            "Memory Allocation failed - init_cb\n");
 
                        qla2x00_mem_free(ha);
-                       set_current_state(TASK_INTERRUPTIBLE);
+                       set_current_state(TASK_UNINTERRUPTIBLE);
                        schedule_timeout(HZ/10);
 
                        continue;
@@ -2909,7 +2911,7 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha)
                            "Memory Allocation failed - ioctl_mem\n");
 
                        qla2x00_mem_free(ha);
-                       set_current_state(TASK_INTERRUPTIBLE);
+                       set_current_state(TASK_UNINTERRUPTIBLE);
                        schedule_timeout(HZ/10);
 
                        continue;
@@ -2921,14 +2923,14 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha)
                            "qla2x00_allocate_sp_pool()\n");
 
                        qla2x00_mem_free(ha);
-                       set_current_state(TASK_INTERRUPTIBLE);
+                       set_current_state(TASK_UNINTERRUPTIBLE);
                        schedule_timeout(HZ/10);
 
                        continue;
                }
 
                /* Allocate memory for SNS commands */
-               if (IS_QLA2200(ha)) {
+               if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
                        /* Get consistent memory allocated for SNS commands */
                        ha->sns_cmd = pci_alloc_consistent(ha->pdev,
                            sizeof(struct sns_cmd_pkt), &ha->sns_cmd_dma);
@@ -2938,13 +2940,13 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha)
                                    "Memory Allocation failed - sns_cmd\n");
 
                                qla2x00_mem_free(ha);
-                               set_current_state(TASK_INTERRUPTIBLE);
+                               set_current_state(TASK_UNINTERRUPTIBLE);
                                schedule_timeout(HZ/10);
 
                                continue;
                        }
                        memset(ha->sns_cmd, 0, sizeof(struct sns_cmd_pkt));
-               } else if (!IS_QLA2100(ha)) {
+               } else {
                        /* Get consistent memory allocated for MS IOCB */
                        ha->ms_iocb = pci_alloc_consistent(ha->pdev,
                            sizeof(ms_iocb_entry_t), &ha->ms_iocb_dma);
@@ -2954,7 +2956,7 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha)
                                    "Memory Allocation failed - ms_iocb\n");
 
                                qla2x00_mem_free(ha);
-                               set_current_state(TASK_INTERRUPTIBLE);
+                               set_current_state(TASK_UNINTERRUPTIBLE);
                                schedule_timeout(HZ/10);
 
                                continue;
@@ -2973,7 +2975,7 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha)
                                    "Memory Allocation failed - ct_sns\n");
 
                                qla2x00_mem_free(ha);
-                               set_current_state(TASK_INTERRUPTIBLE);
+                               set_current_state(TASK_UNINTERRUPTIBLE);
                                schedule_timeout(HZ/10);
 
                                continue;
@@ -2990,7 +2992,7 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha)
                            "Memory Allocation failed - iodesc_pd\n");
 
                        qla2x00_mem_free(ha);
-                       set_current_state(TASK_INTERRUPTIBLE);
+                       set_current_state(TASK_UNINTERRUPTIBLE);
                        schedule_timeout(HZ/10);
 
                        continue;
@@ -3077,7 +3079,7 @@ qla2x00_mem_free(scsi_qla_host_t *ha)
 
        if (ha->request_ring) {
                pci_free_consistent(ha->pdev,
-                   ((REQUEST_ENTRY_CNT + 1) * (sizeof(request_t))),
+                   ((ha->request_q_length + 1) * (sizeof(request_t))),
                    ha->request_ring, ha->request_dma);
        }
 
@@ -3852,6 +3854,8 @@ qla2x00_timer(scsi_qla_host_t *ha)
                                DEBUG(printk("scsi(%ld): Loop down - "
                                    "aborting ISP.\n",
                                    ha->host_no));
+                               qla_printk(KERN_WARNING, ha,
+                                   "Loop down - aborting ISP.\n");
 
                                set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
                        }
@@ -3936,8 +3940,8 @@ qla2x00_cmd_timeout(srb_t *sp)
        int processed;
        scsi_qla_host_t *vis_ha, *dest_ha;
        struct scsi_cmnd *cmd;
-       ulong      flags;
-       fc_port_t       *fcport;
+       unsigned long flags, cpu_flags;
+       fc_port_t *fcport;
 
        cmd = sp->cmd;
        vis_ha = (scsi_qla_host_t *)cmd->device->host->hostdata;
@@ -4032,6 +4036,64 @@ qla2x00_cmd_timeout(srb_t *sp)
                 return;
        }
 
+       spin_lock_irqsave(&dest_ha->list_lock, cpu_flags);
+       if (sp->state == SRB_DONE_STATE) {
+               /* IO in done_q  -- leave it */
+               DEBUG(printk("scsi(%ld): Found in Done queue pid %ld sp=%p.\n",
+                   dest_ha->host_no, cmd->serial_number, sp));
+       } else if (sp->state == SRB_SUSPENDED_STATE) {
+               DEBUG(printk("scsi(%ld): Found SP %p in suspended state  "
+                   "- pid %ld:\n",
+                   dest_ha->host_no, sp, cmd->serial_number));
+               DEBUG(qla2x00_dump_buffer((uint8_t *)sp, sizeof(srb_t));)
+       } else if (sp->state == SRB_ACTIVE_STATE) {
+               /*
+                * IO is with ISP find the command in our active list.
+                */
+               spin_unlock_irqrestore(&dest_ha->list_lock, cpu_flags);
+               spin_lock_irqsave(&dest_ha->hardware_lock, flags);
+               if (sp == dest_ha->outstanding_cmds[
+                   (unsigned long)sp->cmd->host_scribble]) {
+
+                       DEBUG(printk("cmd_timeout: Found in ISP \n"));
+
+                       if (sp->flags & SRB_TAPE) {
+                               /*
+                                * We cannot allow the midlayer error handler
+                                * to wakeup and begin the abort process.
+                                * Extend the timer so that the firmware can
+                                * properly return the IOCB.
+                                */
+                               DEBUG(printk("cmd_timeout: Extending timeout "
+                                   "of FCP2 tape command!\n"));
+                               qla2x00_extend_timeout(sp->cmd,
+                                   EXTEND_CMD_TIMEOUT);
+                       }
+                       sp->state = SRB_ACTIVE_TIMEOUT_STATE;
+                       spin_unlock_irqrestore(&dest_ha->hardware_lock, flags);
+               } else {
+                       spin_unlock_irqrestore(&dest_ha->hardware_lock, flags);
+                       printk(KERN_INFO 
+                               "qla_cmd_timeout: State indicates it is with "
+                               "ISP, But not in active array\n");
+               }
+               spin_lock_irqsave(&dest_ha->list_lock, cpu_flags);
+       } else if (sp->state == SRB_ACTIVE_TIMEOUT_STATE) {
+               DEBUG(printk("qla2100%ld: Found in Active timeout state"
+                               "pid %ld, State = %x., \n",
+                               dest_ha->host_no,
+                               sp->cmd->serial_number, sp->state);)
+       } else {
+               /* EMPTY */
+               DEBUG2(printk("cmd_timeout%ld: LOST command state = "
+                               "0x%x, sp=%p\n",
+                               vis_ha->host_no, sp->state,sp);)
+
+               qla_printk(KERN_INFO, vis_ha,
+                       "cmd_timeout: LOST command state = 0x%x\n", sp->state);
+       }
+       spin_unlock_irqrestore(&dest_ha->list_lock, cpu_flags);
+
        DEBUG3(printk("cmd_timeout: Leaving\n");)
 }
 
@@ -4180,9 +4242,6 @@ qla2x00_process_response_queue_in_zio_mode(scsi_qla_host_t *ha)
        spin_lock_irqsave(&ha->hardware_lock,flags);
        qla2x00_process_response_queue(ha);
        spin_unlock_irqrestore(&ha->hardware_lock, flags);
-
-       if (!list_empty(&ha->done_queue))
-               qla2x00_done(ha);
 }
 
 /*
@@ -4261,7 +4320,7 @@ qla2x00_next(scsi_qla_host_t *vis_ha)
                 * continues until the LOOP DOWN time expires or the condition
                 * goes away.
                 */
-               if (!(sp->flags & SRB_IOCTL) &&
+               if (!(sp->flags & (SRB_IOCTL | SRB_TAPE)) &&
                    (atomic_read(&fcport->state) != FCS_ONLINE ||
                        test_bit(ABORT_ISP_ACTIVE, &dest_ha->dpc_flags) ||
                        atomic_read(&dest_ha->loop_state) != LOOP_READY)) {
@@ -4286,7 +4345,7 @@ qla2x00_next(scsi_qla_host_t *vis_ha)
                 * If this request's lun is suspended then put the request on
                 * the  scsi_retry queue. 
                 */
-               if (!(sp->flags & SRB_IOCTL) &&
+               if (!(sp->flags & (SRB_IOCTL | SRB_TAPE)) &&
                    sp->lun_queue->q_state == LUN_STATE_WAIT) {
                        DEBUG3(printk("scsi(%ld): lun wait state - pid=%ld, "
                            "opcode=%d, allowed=%d, retries=%d\n",