]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/scsi/arcmsr/arcmsr_hba.c
Merge tag 'v2.6.38' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[mv-sheeva.git] / drivers / scsi / arcmsr / arcmsr_hba.c
index 17e3df4f016f6590cc86aac3ccc586add42cb2c6..984bd527c6c91c42f5edd580ec4092246a18bee2 100644 (file)
@@ -2,7 +2,7 @@
 *******************************************************************************
 **        O.S   : Linux
 **   FILE NAME  : arcmsr_hba.c
-**        BY    : Erich Chen
+**        BY    : Nick Cheng
 **   Description: SCSI RAID Device Driver for
 **                ARECA RAID Host adapter
 *******************************************************************************
@@ -76,7 +76,7 @@ MODULE_DESCRIPTION("ARECA (ARC11xx/12xx/16xx/1880) SATA/SAS RAID Host Bus Adapte
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_VERSION(ARCMSR_DRIVER_VERSION);
 static int sleeptime = 10;
-static int retrycount = 30;
+static int retrycount = 12;
 wait_queue_head_t wait_q;
 static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb,
                                        struct scsi_cmnd *cmd);
@@ -187,7 +187,6 @@ int arcmsr_sleep_for_bus_reset(struct scsi_cmnd *cmd)
                if (isleep > 0) {
                        msleep(isleep*1000);
                }
-               printk(KERN_NOTICE "wake-up\n");
                return 0;
 }
 
@@ -921,7 +920,6 @@ static void arcmsr_report_ccb_state(struct AdapterControlBlock *acb,
 }
 
 static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, struct CommandControlBlock *pCCB, bool error)
-
 {
        int id, lun;
        if ((pCCB->acb != acb) || (pCCB->startdone != ARCMSR_CCB_START)) {
@@ -948,7 +946,7 @@ static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, struct Comma
                                , pCCB->startdone
                                , atomic_read(&acb->ccboutstandingcount));
                  return;
-               }
+       }
        arcmsr_report_ccb_state(acb, pCCB, error);
 }
 
@@ -981,7 +979,7 @@ static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb)
        case ACB_ADAPTER_TYPE_B: {
                struct MessageUnit_B *reg = acb->pmuB;
                /*clear all outbound posted Q*/
-               writel(ARCMSR_DOORBELL_INT_CLEAR_PATTERN, &reg->iop2drv_doorbell); /* clear doorbell interrupt */
+               writel(ARCMSR_DOORBELL_INT_CLEAR_PATTERN, reg->iop2drv_doorbell); /* clear doorbell interrupt */
                for (i = 0; i < ARCMSR_MAX_HBB_POSTQUEUE; i++) {
                        if ((flag_ccb = readl(&reg->done_qbuffer[i])) != 0) {
                                writel(0, &reg->done_qbuffer[i]);
@@ -1171,9 +1169,8 @@ static int arcmsr_build_ccb(struct AdapterControlBlock *acb,
        arcmsr_cdb->msgPages = arccdbsize/0x100 + (arccdbsize % 0x100 ? 1 : 0);
        if ( arccdbsize > 256)
                arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_SGL_BSIZE;
-       if (pcmd->cmnd[0]|WRITE_6 || pcmd->cmnd[0]|WRITE_10 || pcmd->cmnd[0]|WRITE_12 ){
+       if (pcmd->sc_data_direction == DMA_TO_DEVICE)
                arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_WRITE;
-       }
        ccb->arc_cdb_size = arccdbsize;
        return SUCCESS;
 }
@@ -1512,7 +1509,6 @@ static void arcmsr_hba_postqueue_isr(struct AdapterControlBlock *acb)
                arcmsr_drain_donequeue(acb, pCCB, error);
        }
 }
-
 static void arcmsr_hbb_postqueue_isr(struct AdapterControlBlock *acb)
 {
        uint32_t index;
@@ -2107,10 +2103,6 @@ static int arcmsr_queue_command_lck(struct scsi_cmnd *cmd,
        if (atomic_read(&acb->ccboutstandingcount) >=
                        ARCMSR_MAX_OUTSTANDING_CMD)
                return SCSI_MLQUEUE_HOST_BUSY;
-       if ((scsicmd == SCSI_CMD_ARECA_SPECIFIC)) {
-               printk(KERN_NOTICE "Receiveing SCSI_CMD_ARECA_SPECIFIC command..\n");
-               return 0;
-       }
        ccb = arcmsr_get_freeccb(acb);
        if (!ccb)
                return SCSI_MLQUEUE_HOST_BUSY;
@@ -2394,6 +2386,7 @@ static int arcmsr_polling_hbb_ccbdone(struct AdapterControlBlock *acb,
        int index, rtn;
        bool error;
        polling_hbb_ccb_retry:
+
        poll_count++;
        /* clear doorbell interrupt */
        writel(ARCMSR_DOORBELL_INT_CLEAR_PATTERN, reg->iop2drv_doorbell);
@@ -2664,6 +2657,7 @@ static void arcmsr_request_hba_device_map(struct AdapterControlBlock *acb)
 {
        struct MessageUnit_A __iomem *reg = acb->pmuA;
        if (unlikely(atomic_read(&acb->rq_map_token) == 0) || ((acb->acb_flags & ACB_F_BUS_RESET) != 0 ) || ((acb->acb_flags & ACB_F_ABORT) != 0 )){
+               mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6 * HZ));
                return;
        } else {
                acb->fw_flag = FW_NORMAL;
@@ -2671,8 +2665,10 @@ static void arcmsr_request_hba_device_map(struct AdapterControlBlock *acb)
                        atomic_set(&acb->rq_map_token, 16);
                }
                atomic_set(&acb->ante_token_value, atomic_read(&acb->rq_map_token));
-               if (atomic_dec_and_test(&acb->rq_map_token))
+               if (atomic_dec_and_test(&acb->rq_map_token)) {
+                       mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6 * HZ));
                        return;
+               }
                writel(ARCMSR_INBOUND_MESG0_GET_CONFIG, &reg->inbound_msgaddr0);
                mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6 * HZ));
        }
@@ -2683,15 +2679,18 @@ static void arcmsr_request_hbb_device_map(struct AdapterControlBlock *acb)
 {
        struct MessageUnit_B __iomem *reg = acb->pmuB;
        if (unlikely(atomic_read(&acb->rq_map_token) == 0) || ((acb->acb_flags & ACB_F_BUS_RESET) != 0 ) || ((acb->acb_flags & ACB_F_ABORT) != 0 )){
+               mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6 * HZ));
                return;
        } else {
                acb->fw_flag = FW_NORMAL;
                if (atomic_read(&acb->ante_token_value) == atomic_read(&acb->rq_map_token)) {
-                       atomic_set(&acb->rq_map_token,16);
+                       atomic_set(&acb->rq_map_token, 16);
                }
                atomic_set(&acb->ante_token_value, atomic_read(&acb->rq_map_token));
-               if(atomic_dec_and_test(&acb->rq_map_token))
+               if (atomic_dec_and_test(&acb->rq_map_token)) {
+                       mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6 * HZ));
                        return;
+               }
                writel(ARCMSR_MESSAGE_GET_CONFIG, reg->drv2iop_doorbell);
                mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6 * HZ));
        }
@@ -2702,6 +2701,7 @@ static void arcmsr_request_hbc_device_map(struct AdapterControlBlock *acb)
 {
        struct MessageUnit_C __iomem *reg = acb->pmuC;
        if (unlikely(atomic_read(&acb->rq_map_token) == 0) || ((acb->acb_flags & ACB_F_BUS_RESET) != 0) || ((acb->acb_flags & ACB_F_ABORT) != 0)) {
+               mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6 * HZ));
                return;
        } else {
                acb->fw_flag = FW_NORMAL;
@@ -2709,8 +2709,10 @@ static void arcmsr_request_hbc_device_map(struct AdapterControlBlock *acb)
                        atomic_set(&acb->rq_map_token, 16);
                }
                atomic_set(&acb->ante_token_value, atomic_read(&acb->rq_map_token));
-               if (atomic_dec_and_test(&acb->rq_map_token))
+               if (atomic_dec_and_test(&acb->rq_map_token)) {
+                       mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6 * HZ));
                        return;
+               }
                writel(ARCMSR_INBOUND_MESG0_GET_CONFIG, &reg->inbound_msgaddr0);
                writel(ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE, &reg->inbound_doorbell);
                mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6 * HZ));
@@ -2898,6 +2900,8 @@ static uint8_t arcmsr_iop_reset(struct AdapterControlBlock *acb)
        uint32_t intmask_org;
        uint8_t rtnval = 0x00;
        int i = 0;
+       unsigned long flags;
+
        if (atomic_read(&acb->ccboutstandingcount) != 0) {
                /* disable all outbound interrupt */
                intmask_org = arcmsr_disable_outbound_ints(acb);
@@ -2908,7 +2912,12 @@ static uint8_t arcmsr_iop_reset(struct AdapterControlBlock *acb)
                for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) {
                        ccb = acb->pccb_pool[i];
                        if (ccb->startdone == ARCMSR_CCB_START) {
-                               arcmsr_ccb_complete(ccb);
+                               scsi_dma_unmap(ccb->pcmd);
+                               ccb->startdone = ARCMSR_CCB_DONE;
+                               ccb->ccb_flags = 0;
+                               spin_lock_irqsave(&acb->ccblist_lock, flags);
+                               list_add_tail(&ccb->list, &acb->ccb_free_list);
+                               spin_unlock_irqrestore(&acb->ccblist_lock, flags);
                        }
                }
                atomic_set(&acb->ccboutstandingcount, 0);
@@ -2921,8 +2930,7 @@ static uint8_t arcmsr_iop_reset(struct AdapterControlBlock *acb)
 
 static int arcmsr_bus_reset(struct scsi_cmnd *cmd)
 {
-       struct AdapterControlBlock *acb =
-               (struct AdapterControlBlock *)cmd->device->host->hostdata;
+       struct AdapterControlBlock *acb;
        uint32_t intmask_org, outbound_doorbell;
        int retry_count = 0;
        int rtn = FAILED;
@@ -2972,31 +2980,16 @@ sleep_again:
                                atomic_set(&acb->rq_map_token, 16);
                                atomic_set(&acb->ante_token_value, 16);
                                acb->fw_flag = FW_NORMAL;
-                               init_timer(&acb->eternal_timer);
-                               acb->eternal_timer.expires = jiffies + msecs_to_jiffies(6*HZ);
-                               acb->eternal_timer.data = (unsigned long) acb;
-                               acb->eternal_timer.function = &arcmsr_request_device_map;
-                               add_timer(&acb->eternal_timer);
+                               mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6 * HZ));
                                acb->acb_flags &= ~ACB_F_BUS_RESET;
                                rtn = SUCCESS;
                                printk(KERN_ERR "arcmsr: scsi  bus reset eh returns with success\n");
                        } else {
                                acb->acb_flags &= ~ACB_F_BUS_RESET;
-                               if (atomic_read(&acb->rq_map_token) == 0) {
-                                       atomic_set(&acb->rq_map_token, 16);
-                                       atomic_set(&acb->ante_token_value, 16);
-                                       acb->fw_flag = FW_NORMAL;
-                                       init_timer(&acb->eternal_timer);
-                                               acb->eternal_timer.expires = jiffies + msecs_to_jiffies(6*HZ);
-                                       acb->eternal_timer.data = (unsigned long) acb;
-                                       acb->eternal_timer.function = &arcmsr_request_device_map;
-                                       add_timer(&acb->eternal_timer);
-                               } else {
-                                       atomic_set(&acb->rq_map_token, 16);
-                                       atomic_set(&acb->ante_token_value, 16);
-                                       acb->fw_flag = FW_NORMAL;
-                                       mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6*HZ));
-                               }
+                               atomic_set(&acb->rq_map_token, 16);
+                               atomic_set(&acb->ante_token_value, 16);
+                               acb->fw_flag = FW_NORMAL;
+                               mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6*HZ));
                                rtn = SUCCESS;
                        }
                        break;
@@ -3008,21 +3001,10 @@ sleep_again:
                                rtn = FAILED;
                        } else {
                                acb->acb_flags &= ~ACB_F_BUS_RESET;
-                               if (atomic_read(&acb->rq_map_token) == 0) {
-                                       atomic_set(&acb->rq_map_token, 16);
-                                       atomic_set(&acb->ante_token_value, 16);
-                                       acb->fw_flag = FW_NORMAL;
-                                       init_timer(&acb->eternal_timer);
-                                               acb->eternal_timer.expires = jiffies + msecs_to_jiffies(6*HZ);
-                                       acb->eternal_timer.data = (unsigned long) acb;
-                                       acb->eternal_timer.function = &arcmsr_request_device_map;
-                                       add_timer(&acb->eternal_timer);
-                               } else {
-                                       atomic_set(&acb->rq_map_token, 16);
-                                       atomic_set(&acb->ante_token_value, 16);
-                                       acb->fw_flag = FW_NORMAL;
-                                       mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6*HZ));
-                               }
+                               atomic_set(&acb->rq_map_token, 16);
+                               atomic_set(&acb->ante_token_value, 16);
+                               acb->fw_flag = FW_NORMAL;
+                               mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6 * HZ));
                                rtn = SUCCESS;
                        }
                        break;
@@ -3068,31 +3050,16 @@ sleep:
                                atomic_set(&acb->rq_map_token, 16);
                                atomic_set(&acb->ante_token_value, 16);
                                acb->fw_flag = FW_NORMAL;
-                               init_timer(&acb->eternal_timer);
-                               acb->eternal_timer.expires = jiffies + msecs_to_jiffies(6 * HZ);
-                               acb->eternal_timer.data = (unsigned long) acb;
-                               acb->eternal_timer.function = &arcmsr_request_device_map;
-                               add_timer(&acb->eternal_timer);
+                               mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6 * HZ));
                                acb->acb_flags &= ~ACB_F_BUS_RESET;
                                rtn = SUCCESS;
                                printk(KERN_ERR "arcmsr: scsi bus reset eh returns with success\n");
                        } else {
                                acb->acb_flags &= ~ACB_F_BUS_RESET;
-                               if (atomic_read(&acb->rq_map_token) == 0) {
-                                       atomic_set(&acb->rq_map_token, 16);
-                                       atomic_set(&acb->ante_token_value, 16);
-                                       acb->fw_flag = FW_NORMAL;
-                                       init_timer(&acb->eternal_timer);
-                                               acb->eternal_timer.expires = jiffies + msecs_to_jiffies(6*HZ);
-                                       acb->eternal_timer.data = (unsigned long) acb;
-                                       acb->eternal_timer.function = &arcmsr_request_device_map;
-                                       add_timer(&acb->eternal_timer);
-                               } else {
-                                       atomic_set(&acb->rq_map_token, 16);
-                                       atomic_set(&acb->ante_token_value, 16);
-                                       acb->fw_flag = FW_NORMAL;
-                                       mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6*HZ));
-                               }
+                               atomic_set(&acb->rq_map_token, 16);
+                               atomic_set(&acb->ante_token_value, 16);
+                               acb->fw_flag = FW_NORMAL;
+                               mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6*HZ));
                                rtn = SUCCESS;
                        }
                        break;