Here's another patch doign some basic cleanup, this time for the scsi entry points. Index: hch/areca/drivers/scsi/arcmsr/arcmsr_hba.c =================================================================== --- hch.orig/areca/drivers/scsi/arcmsr/arcmsr_hba.c 2006-04-20 21:46:49.000000000 +0200 +++ hch/areca/drivers/scsi/arcmsr/arcmsr_hba.c 2006-04-20 22:33:21.000000000 +0200 @@ -74,43 +74,10 @@ MODULE_VERSION(ARCMSR_DRIVER_VERSION); static int arcmsr_iop_message_xfer(struct AdapterControlBlock *pACB, struct scsi_cmnd *cmd); -static int arcmsr_cmd_abort(struct scsi_cmnd *); -static int arcmsr_bus_reset(struct scsi_cmnd *); -static int arcmsr_bios_param(struct scsi_device *sdev, - struct block_device *bdev, sector_t capacity, int *info); -static int arcmsr_queue_command(struct scsi_cmnd * cmd, - void (*done) (struct scsi_cmnd *)); static void arcmsr_free_ccb_pool(struct AdapterControlBlock *pACB); static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *pACB); static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *pACB); static uint8_t arcmsr_wait_msgint_ready(struct AdapterControlBlock *pACB); -static const char *arcmsr_info(struct Scsi_Host *); - -static int arcmsr_adjust_disk_queue_depth(struct scsi_device *sdev, int queue_depth) -{ - if (queue_depth > ARCMSR_MAX_CMD_PERLUN) - queue_depth = ARCMSR_MAX_CMD_PERLUN; - scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth); - return queue_depth; -} - -static struct scsi_host_template arcmsr_scsi_host_template = { - .module = THIS_MODULE, - .name = "ARCMSR ARECA SATA RAID HOST Adapter" ARCMSR_DRIVER_VERSION, - .info = arcmsr_info, - .queuecommand = arcmsr_queue_command, - .eh_abort_handler = arcmsr_cmd_abort, - .eh_bus_reset_handler = arcmsr_bus_reset, - .bios_param = arcmsr_bios_param, - .change_queue_depth = arcmsr_adjust_disk_queue_depth, - .can_queue = ARCMSR_MAX_OUTSTANDING_CMD, - .this_id = ARCMSR_SCSI_INITIATOR_ID, - .sg_tablesize = ARCMSR_MAX_SG_ENTRIES, - .max_sectors = ARCMSR_MAX_XFER_SECTORS, - .cmd_per_lun = ARCMSR_MAX_CMD_PERLUN, - .use_clustering = ENABLE_CLUSTERING, - .shost_attrs = arcmsr_host_attrs, -}; static irqreturn_t arcmsr_do_interrupt(int irq, void *dev_id, struct pt_regs *regs) @@ -127,8 +94,486 @@ return handle_state; } +static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb) +{ + struct MessageUnit __iomem *reg = acb->pmu; + u32 orig_mask = readl(®->outbound_intmask); + + writel(orig_mask | ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE, + ®->outbound_intmask); + return orig_mask; +} + +static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb, + u32 orig_mask) +{ + struct MessageUnit __iomem *reg = acb->pmu; + u32 mask; + + mask = orig_mask & ~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE | + ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE); + writel(mask, ®->outbound_intmask); +} + +static void arcmsr_pci_unmap_dma(struct CommandControlBlock *pCCB) +{ + struct AdapterControlBlock *acb = pCCB->pACB; + struct scsi_cmnd *pcmd = pCCB->pcmd; + + if (pcmd->use_sg != 0) { + struct scatterlist *sl; + + sl = (struct scatterlist *)pcmd->request_buffer; + pci_unmap_sg(acb->pdev, sl, pcmd->use_sg, pcmd->sc_data_direction); + } + else if (pcmd->request_bufflen != 0) + pci_unmap_single(acb->pdev, + (dma_addr_t)(unsigned long)pcmd->SCp.ptr, + pcmd->request_bufflen, pcmd->sc_data_direction); +} + +static void arcmsr_ccb_complete(struct CommandControlBlock *pCCB, int stand_flag) +{ + struct AdapterControlBlock *acb = pCCB->pACB; + struct scsi_cmnd *pcmd = pCCB->pcmd; + + arcmsr_pci_unmap_dma(pCCB); + if (stand_flag == 1) + atomic_dec(&acb->ccboutstandingcount); + pCCB->startdone = ARCMSR_CCB_DONE; + pCCB->ccb_flags = 0; + list_add_tail(&pCCB->list, &acb->ccb_free_list); + pcmd->scsi_done(pcmd); +} + +static struct CommandControlBlock *arcmsr_get_freeccb( + struct AdapterControlBlock *acb) +{ + struct list_head *head = &acb->ccb_free_list; + struct CommandControlBlock *pCCB = NULL; + + if (!list_empty(head)) { + pCCB = list_entry(head->next, struct CommandControlBlock, list); + list_del(head->next); + } + return pCCB; +} + +static void arcmsr_build_ccb(struct AdapterControlBlock *pACB, struct CommandControlBlock *pCCB, + struct scsi_cmnd *pcmd) +{ + struct ARCMSR_CDB *pARCMSR_CDB = (struct ARCMSR_CDB *)&pCCB->arcmsr_cdb; + int8_t *psge = (int8_t *)&pARCMSR_CDB->u; + uint32_t address_lo, address_hi; + int arccdbsize = 0x30; + + pCCB->pcmd = pcmd; + memset(pARCMSR_CDB, 0, sizeof (struct ARCMSR_CDB)); + pARCMSR_CDB->Bus = 0; + pARCMSR_CDB->TargetID = pcmd->device->id; + pARCMSR_CDB->LUN = pcmd->device->lun; + pARCMSR_CDB->Function = 1; + pARCMSR_CDB->CdbLength = (uint8_t)pcmd->cmd_len; + pARCMSR_CDB->Context = (unsigned long)pARCMSR_CDB; + memcpy(pARCMSR_CDB->Cdb, pcmd->cmnd, pcmd->cmd_len); + if (pcmd->use_sg) { + int length, sgcount, i, cdb_sgcount = 0; + struct scatterlist *sl; + + /* Get Scatter Gather List from scsiport. */ + sl = (struct scatterlist *) pcmd->request_buffer; + sgcount = pci_map_sg(pACB->pdev, sl, pcmd->use_sg, + pcmd->sc_data_direction); + /* map stor port SG list to our iop SG List. */ + for(i = 0; i < sgcount; i++) { + /* Get the physical address of the current data pointer */ + length = cpu_to_le32(sg_dma_len(sl)); + address_lo = cpu_to_le32(dma_addr_lo32(sg_dma_address(sl))); + address_hi = cpu_to_le32(dma_addr_hi32(sg_dma_address(sl))); + if (address_hi == 0) { + struct SG32ENTRY *pdma_sg = (struct SG32ENTRY *)psge; + + pdma_sg->address = address_lo; + pdma_sg->length = length; + psge += sizeof (struct SG32ENTRY); + arccdbsize += sizeof (struct SG32ENTRY); + } else { + struct SG64ENTRY *pdma_sg = (struct SG64ENTRY *)psge; + + pdma_sg->addresshigh = address_hi; + pdma_sg->address = address_lo; + pdma_sg->length = length|IS_SG64_ADDR; + psge += sizeof (struct SG64ENTRY); + arccdbsize += sizeof (struct SG64ENTRY); + } + sl++; + cdb_sgcount++; + } + pARCMSR_CDB->sgcount = (uint8_t)cdb_sgcount; + pARCMSR_CDB->DataLength = pcmd->request_bufflen; + if ( arccdbsize > 256) + pARCMSR_CDB->Flags |= ARCMSR_CDB_FLAG_SGL_BSIZE; + } else if (pcmd->request_bufflen) { + dma_addr_t dma_addr; + dma_addr = pci_map_single(pACB->pdev, pcmd->request_buffer, + pcmd->request_bufflen, pcmd->sc_data_direction); + pcmd->SCp.ptr = (char *)(unsigned long) dma_addr; + address_lo = cpu_to_le32(dma_addr_lo32(dma_addr)); + address_hi = cpu_to_le32(dma_addr_hi32(dma_addr)); + if (address_hi == 0) { + struct SG32ENTRY *pdma_sg = (struct SG32ENTRY *)psge; + pdma_sg->address = address_lo; + pdma_sg->length = pcmd->request_bufflen; + } else { + struct SG64ENTRY *pdma_sg = (struct SG64ENTRY *)psge; + pdma_sg->addresshigh = address_hi; + pdma_sg->address = address_lo; + pdma_sg->length = pcmd->request_bufflen|IS_SG64_ADDR; + } + pARCMSR_CDB->sgcount = 1; + pARCMSR_CDB->DataLength = pcmd->request_bufflen; + } + if (pcmd->sc_data_direction == DMA_TO_DEVICE ) { + pARCMSR_CDB->Flags |= ARCMSR_CDB_FLAG_WRITE; + pCCB->ccb_flags |= CCB_FLAG_WRITE; + } +} + +static void arcmsr_post_ccb(struct AdapterControlBlock *pACB, struct CommandControlBlock *pCCB) +{ + struct MessageUnit __iomem *reg = pACB->pmu; + uint32_t cdb_shifted_phyaddr = pCCB->cdb_shifted_phyaddr; + struct ARCMSR_CDB *pARCMSR_CDB = (struct ARCMSR_CDB *)&pCCB->arcmsr_cdb; + + atomic_inc(&pACB->ccboutstandingcount); + pCCB->startdone = ARCMSR_CCB_START; + if (pARCMSR_CDB->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) + writel(cdb_shifted_phyaddr | ARCMSR_CCBPOST_FLAG_SGL_BSIZE, + ®->inbound_queueport); + else + writel(cdb_shifted_phyaddr, ®->inbound_queueport); +} + +static void arcmsr_report_sense_info(struct CommandControlBlock *pCCB) +{ + struct scsi_cmnd *pcmd = pCCB->pcmd; + struct SENSE_DATA *psenseBuffer = (struct SENSE_DATA *)pcmd->sense_buffer; + + pcmd->result = DID_OK << 16; + if (psenseBuffer) { + int sense_data_length = + sizeof (struct SENSE_DATA) < sizeof (pcmd->sense_buffer) + ? sizeof (struct SENSE_DATA) : sizeof (pcmd->sense_buffer); + memset(psenseBuffer, 0, sizeof (pcmd->sense_buffer)); + memcpy(psenseBuffer, pCCB->arcmsr_cdb.SenseData, sense_data_length); + psenseBuffer->ErrorCode = SCSI_SENSE_CURRENT_ERRORS; + psenseBuffer->Valid = 1; + } +} + +static void arcmsr_polling_ccbdone(struct AdapterControlBlock *pACB, + struct CommandControlBlock *poll_ccb) +{ + struct MessageUnit __iomem *reg = pACB->pmu; + struct CommandControlBlock *pCCB; + uint32_t flag_ccb, outbound_intstatus, poll_ccb_done = 0, poll_count = 0; + int id, lun; + +polling_ccb_retry: + poll_count++; + outbound_intstatus = readl(®->outbound_intstatus) + & pACB->outbound_int_enable; + writel(outbound_intstatus, ®->outbound_intstatus);/*clear interrupt*/ + while (1) { + flag_ccb = readl(®->outbound_queueport); + if (flag_ccb == 0xFFFFFFFF) { + if (poll_ccb_done) + break; + msleep(25); + if (poll_count > 100) + break; + goto polling_ccb_retry; + } + + pCCB = (struct CommandControlBlock *)(pACB->vir2phy_offset + (flag_ccb << 5)); + if ((pCCB->pACB != pACB) || (pCCB->startdone != ARCMSR_CCB_START)) { + if ((pCCB->startdone == ARCMSR_CCB_ABORTED) && (pCCB == poll_ccb)) { + printk(KERN_NOTICE + "arcmsr%d: scsi id=%d lun=%d ccb='0x%p'" + " poll command abort successfully \n" + , pACB->host->host_no + , pCCB->pcmd->device->id + , pCCB->pcmd->device->lun + , pCCB); + pCCB->pcmd->result = DID_ABORT << 16; + arcmsr_ccb_complete(pCCB, 1); + poll_ccb_done = 1; + continue; + } + printk(KERN_NOTICE + "arcmsr%d: polling get an illegal ccb" + " command done ccb='0x%p'" + "ccboutstandingcount=%d \n" + , pACB->host->host_no + , pCCB + , atomic_read(&pACB->ccboutstandingcount)); + continue; + } + id = pCCB->pcmd->device->id; + lun = pCCB->pcmd->device->lun; + if (!(flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR)) { + if (pACB->devstate[id][lun] == ARECA_RAID_GONE) + pACB->devstate[id][lun] = ARECA_RAID_GOOD; + pCCB->pcmd->result = DID_OK << 16; + arcmsr_ccb_complete(pCCB, 1); + continue; + } + + switch(pCCB->arcmsr_cdb.DeviceStatus) { + case ARCMSR_DEV_SELECT_TIMEOUT: + pACB->devstate[id][lun] = ARECA_RAID_GONE; + pCCB->pcmd->result = DID_TIME_OUT << 16; + arcmsr_ccb_complete(pCCB, 1); + break; + case ARCMSR_DEV_ABORTED: + case ARCMSR_DEV_INIT_FAIL: + pACB->devstate[id][lun] = ARECA_RAID_GONE; + pCCB->pcmd->result = DID_BAD_TARGET << 16; + arcmsr_ccb_complete(pCCB, 1); + break; + case ARCMSR_DEV_CHECK_CONDITION: + pACB->devstate[id][lun] = ARECA_RAID_GOOD; + arcmsr_report_sense_info(pCCB); + arcmsr_ccb_complete(pCCB, 1); + break; + default: + printk(KERN_NOTICE "arcmsr%d: scsi id=%d lun=%d " + "polling and getting command error done " + "but got unknown DeviceStatus = 0x%x\n", + pACB->host->host_no, id, lun, + pCCB->arcmsr_cdb.DeviceStatus); + pACB->devstate[id][lun] = ARECA_RAID_GONE; + pCCB->pcmd->result = DID_BAD_TARGET << 16; + arcmsr_ccb_complete(pCCB, 1); + break; + } + } +} + +static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb) +{ + struct MessageUnit __iomem *reg = acb->pmu; + char *acb_firm_model = acb->firm_model; + char *acb_firm_version = acb->firm_version; + char __iomem *iop_firm_model = (char __iomem *) ®->message_rwbuffer[15]; + char __iomem *iop_firm_version = (char __iomem *) ®->message_rwbuffer[17]; + int count; + + writel(ARCMSR_INBOUND_MESG0_GET_CONFIG, ®->inbound_msgaddr0); + if (arcmsr_wait_msgint_ready(acb)) + printk(KERN_NOTICE + "arcmsr%d: wait " + "'get adapter firmware miscellaneous data' timeout \n", + acb->host->host_no); + count = 8; + while (count) { + *acb_firm_model = readb(iop_firm_model); + acb_firm_model++; + iop_firm_model++; + count--; + } + count = 16; + while (count) { + *acb_firm_version = readb(iop_firm_version); + acb_firm_version++; + iop_firm_version++; + count--; + } + + acb->firm_request_len = readl(®->message_rwbuffer[1]); + acb->firm_numbers_queue = readl(®->message_rwbuffer[2]); + acb->firm_sdram_size = readl(®->message_rwbuffer[3]); + acb->firm_hd_channels = readl(®->message_rwbuffer[4]); +} + +static void arcmsr_handle_virtual_command(struct AdapterControlBlock *acb, + struct scsi_cmnd *cmd) +{ + switch (cmd->cmnd[0]) { + case INQUIRY: { + unsigned char inqdata[36]; + char *buffer; + + if (cmd->device->lun) { + cmd->result = (DID_TIME_OUT << 16); + cmd->scsi_done(cmd); + return; + } + + inqdata[0] = TYPE_PROCESSOR; + /* Periph Qualifier & Periph Dev Type */ + inqdata[1] = 0; + /* rem media bit & Dev Type Modifier */ + inqdata[2] = 0; + /* ISO,ECMA,& ANSI versions */ + inqdata[4] = 31; + /* length of additional data */ + strncpy(&inqdata[8], "Areca ", 8); + /* Vendor Identification */ + strncpy(&inqdata[16], "RAID controller ", 16); + /* Product Identification */ + strncpy(&inqdata[32], "R001", 4); /* Product Revision */ + if (cmd->use_sg) { + struct scatterlist *sg; + + sg = (struct scatterlist *) cmd->request_buffer; + buffer = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; + } else { + buffer = cmd->request_buffer; + } + memcpy(buffer, inqdata, sizeof(inqdata)); + if (cmd->use_sg) { + struct scatterlist *sg; + + sg = (struct scatterlist *) cmd->request_buffer; + kunmap_atomic(buffer - sg->offset, KM_IRQ0); + } + cmd->scsi_done(cmd); + } + case WRITE_BUFFER: + case READ_BUFFER: + if (arcmsr_iop_message_xfer(acb, cmd)) + cmd->result = (DID_ERROR << 16); + cmd->scsi_done(cmd); + default: + cmd->scsi_done(cmd); + } +} + +static int arcmsr_queue_command(struct scsi_cmnd *cmd, + void (*done)(struct scsi_cmnd *)) +{ + struct Scsi_Host *host = cmd->device->host; + struct AdapterControlBlock *acb = + (struct AdapterControlBlock *) host->hostdata; + struct CommandControlBlock *pCCB; + int target = cmd->device->id; + int lun = cmd->device->lun; + + cmd->scsi_done = done; + cmd->host_scribble = NULL; + cmd->result = 0; + + if (acb->acb_flags & ACB_F_BUS_RESET) { + printk(KERN_NOTICE "arcmsr%d: bus reset" + " and return busy\n", + acb->host->host_no); + return SCSI_MLQUEUE_HOST_BUSY; + } + + if (target == 16) { + arcmsr_handle_virtual_command(acb, cmd); + return 0; + } + + if (acb->devstate[target][lun] == ARECA_RAID_GONE) { + uint8_t block_cmd; + + block_cmd = cmd->cmnd[0] & 0x0f; + if (block_cmd == 0x08 || block_cmd == 0x0a) { + printk(KERN_NOTICE + "arcmsr%d: block 'read/write'" + "command with gone raid volume" + " Cmd=%2x, TargetId=%d, Lun=%d\n", + acb->host->host_no, cmd->cmnd[0], + target, lun); + cmd->result = (DID_NO_CONNECT << 16); + cmd->scsi_done(cmd); + return 0; + } + } + + if (atomic_read(&acb->ccboutstandingcount) >= + ARCMSR_MAX_OUTSTANDING_CMD) + return SCSI_MLQUEUE_HOST_BUSY; + + pCCB = arcmsr_get_freeccb(acb); + if (!pCCB) + return SCSI_MLQUEUE_HOST_BUSY; + arcmsr_build_ccb(acb, pCCB, cmd); + arcmsr_post_ccb(acb, pCCB); + return 0; +} + +static void arcmsr_abort_one_cmd(struct AdapterControlBlock *acb, + struct CommandControlBlock *ccb) +{ + u32 intmask; + + ccb->startdone = ARCMSR_CCB_ABORTED; + + /* + * Wait for 3 sec for all command done. + */ + msleep_interruptible(3000); + + intmask = arcmsr_disable_outbound_ints(acb); + arcmsr_polling_ccbdone(acb, ccb); + arcmsr_enable_outbound_ints(acb, intmask); +} + +static int arcmsr_abort(struct scsi_cmnd *cmd) +{ + struct AdapterControlBlock *acb = + (struct AdapterControlBlock *)cmd->device->host->hostdata; + int i = 0; + + printk(KERN_NOTICE + "arcmsr%d: abort device command of scsi id=%d lun=%d\n", + acb->host->host_no, cmd->device->id, cmd->device->lun); + acb->num_aborts++; + + /* + * First determine if we currently own this command. + * Start by searching the device queue. If not found + * at all, and the system wanted us to just abort the + * command return success. + */ + if (!atomic_read(&acb->ccboutstandingcount)) + return SUCCESS; + + for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { + struct CommandControlBlock *ccb = acb->pccb_pool[i]; + if (ccb->startdone == ARCMSR_CCB_START && ccb->pcmd == cmd) { + arcmsr_abort_one_cmd(acb, ccb); + break; + } + } + + return SUCCESS; +} + +static int arcmsr_bus_reset(struct scsi_cmnd *cmd) +{ + struct AdapterControlBlock *acb = + (struct AdapterControlBlock *)cmd->device->host->hostdata; + int i; + + acb->num_resets++; + acb->acb_flags |= ACB_F_BUS_RESET; + for (i = 0; i < 400; i++) { + if (!atomic_read(&acb->ccboutstandingcount)) + break; + arcmsr_interrupt(acb); + msleep(25); + } + arcmsr_iop_reset(acb); + acb->acb_flags &= ~ACB_F_BUS_RESET; + return SUCCESS; +} + static int arcmsr_bios_param(struct scsi_device *sdev, - struct block_device *bdev, sector_t capacity, int *geom) + struct block_device *bdev, sector_t capacity, int *geom) { int ret, heads, sectors, cylinders, total_capacity; unsigned char *buffer;/* return copy of block device's partition table */ @@ -155,73 +600,73 @@ return 0; } -static void arcmsr_pci_unmap_dma(struct CommandControlBlock *pCCB) -{ - struct AdapterControlBlock *acb = pCCB->pACB; - struct scsi_cmnd *pcmd = pCCB->pcmd; - - if (pcmd->use_sg != 0) { - struct scatterlist *sl; - - sl = (struct scatterlist *)pcmd->request_buffer; - pci_unmap_sg(acb->pdev, sl, pcmd->use_sg, pcmd->sc_data_direction); - } - else if (pcmd->request_bufflen != 0) - pci_unmap_single(acb->pdev, - (dma_addr_t)(unsigned long)pcmd->SCp.ptr, - pcmd->request_bufflen, pcmd->sc_data_direction); -} - -static void arcmsr_ccb_complete(struct CommandControlBlock *pCCB, int stand_flag) +static int arcmsr_adjust_disk_queue_depth(struct scsi_device *sdev, + int queue_depth) { - struct AdapterControlBlock *acb = pCCB->pACB; - struct scsi_cmnd *pcmd = pCCB->pcmd; - - arcmsr_pci_unmap_dma(pCCB); - if (stand_flag == 1) - atomic_dec(&acb->ccboutstandingcount); - pCCB->startdone = ARCMSR_CCB_DONE; - pCCB->ccb_flags = 0; - list_add_tail(&pCCB->list, &acb->ccb_free_list); - pcmd->scsi_done(pcmd); + if (queue_depth > ARCMSR_MAX_CMD_PERLUN) + queue_depth = ARCMSR_MAX_CMD_PERLUN; + scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth); + return queue_depth; } -static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb) +static const char *arcmsr_info(struct Scsi_Host *host) { - struct MessageUnit __iomem *reg = acb->pmu; - char *acb_firm_model = acb->firm_model; - char *acb_firm_version = acb->firm_version; - char __iomem *iop_firm_model = (char __iomem *) ®->message_rwbuffer[15]; - char __iomem *iop_firm_version = (char __iomem *) ®->message_rwbuffer[17]; - int count; + struct AdapterControlBlock *acb = + (struct AdapterControlBlock *) host->hostdata; + static char buf[256]; + char *type; + int raid6 = 1; - writel(ARCMSR_INBOUND_MESG0_GET_CONFIG, ®->inbound_msgaddr0); - if (arcmsr_wait_msgint_ready(acb)) - printk(KERN_NOTICE - "arcmsr%d: wait " - "'get adapter firmware miscellaneous data' timeout \n", - acb->host->host_no); - count = 8; - while (count) { - *acb_firm_model = readb(iop_firm_model); - acb_firm_model++; - iop_firm_model++; - count--; - } - count = 16; - while (count) { - *acb_firm_version = readb(iop_firm_version); - acb_firm_version++; - iop_firm_version++; - count--; + switch (acb->pdev->device) { + case PCI_DEVICE_ID_ARECA_1110: + case PCI_DEVICE_ID_ARECA_1210: + raid6 = 0; + /*FALLTHRU*/ + case PCI_DEVICE_ID_ARECA_1120: + case PCI_DEVICE_ID_ARECA_1130: + case PCI_DEVICE_ID_ARECA_1160: + case PCI_DEVICE_ID_ARECA_1170: + case PCI_DEVICE_ID_ARECA_1220: + case PCI_DEVICE_ID_ARECA_1230: + case PCI_DEVICE_ID_ARECA_1260: + case PCI_DEVICE_ID_ARECA_1270: + case PCI_DEVICE_ID_ARECA_1280: + type = "SATA"; + break; + case PCI_DEVICE_ID_ARECA_1380: + case PCI_DEVICE_ID_ARECA_1381: + case PCI_DEVICE_ID_ARECA_1680: + case PCI_DEVICE_ID_ARECA_1681: + type = "SAS"; + break; + default: + type = "X-TYPE"; + break; } - acb->firm_request_len = readl(®->message_rwbuffer[1]); - acb->firm_numbers_queue = readl(®->message_rwbuffer[2]); - acb->firm_sdram_size = readl(®->message_rwbuffer[3]); - acb->firm_hd_channels = readl(®->message_rwbuffer[4]); + sprintf(buf, "Areca %s Host Adapter RAID Controller%s\n %s", + type, raid6 ? "( RAID6 capable)" : "", + ARCMSR_DRIVER_VERSION); + return buf; } +static struct scsi_host_template arcmsr_scsi_host_template = { + .module = THIS_MODULE, + .name = "ARCMSR ARECA SATA RAID HOST Adapter" ARCMSR_DRIVER_VERSION, + .info = arcmsr_info, + .queuecommand = arcmsr_queue_command, + .eh_abort_handler = arcmsr_abort, + .eh_bus_reset_handler = arcmsr_bus_reset, + .bios_param = arcmsr_bios_param, + .change_queue_depth = arcmsr_adjust_disk_queue_depth, + .can_queue = ARCMSR_MAX_OUTSTANDING_CMD, + .this_id = ARCMSR_SCSI_INITIATOR_ID, + .sg_tablesize = ARCMSR_MAX_SG_ENTRIES, + .max_sectors = ARCMSR_MAX_XFER_SECTORS, + .cmd_per_lun = ARCMSR_MAX_CMD_PERLUN, + .use_clustering = ENABLE_CLUSTERING, + .shost_attrs = arcmsr_host_attrs, +}; static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb) { @@ -282,9 +727,6 @@ acb->host->host_no); } - writel(readl(®->outbound_intmask) | - ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE, - ®->outbound_intmask); return 0; } @@ -311,8 +753,8 @@ outbound_doorbell = readl(®->outbound_doorbell); writel(outbound_doorbell, ®->outbound_doorbell); writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, ®->inbound_doorbell); - mask = ~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE - | ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE); + mask = ~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE | + ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE); writel(intmask_org & mask, ®->outbound_intmask); acb->outbound_int_enable = ~(intmask_org & mask) & 0x000000ff; acb->acb_flags |= ACB_F_IOP_INITED; @@ -400,6 +842,8 @@ if (error) goto out_iounmap; + arcmsr_disable_outbound_ints(acb); + error = request_irq(pdev->irq, arcmsr_do_interrupt, SA_INTERRUPT | SA_SHIRQ, "arcmsr", acb); if (error) @@ -444,9 +888,7 @@ arcmsr_stop_adapter_bgrb(acb); arcmsr_flush_adapter_cache(acb); - writel(readl(®->outbound_intmask) | - ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE, - ®->outbound_intmask); + arcmsr_disable_outbound_ints(acb); acb->acb_flags |= ACB_F_SCSISTOPADAPTER; acb->acb_flags &= ~ACB_F_IOP_INITED; @@ -536,180 +978,64 @@ static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *pACB) { - struct MessageUnit __iomem *reg=pACB->pmu; - - writel(ARCMSR_INBOUND_MESG0_FLUSH_CACHE, ®->inbound_msgaddr0); - if (arcmsr_wait_msgint_ready(pACB)) - printk(KERN_NOTICE - "arcmsr%d: wait 'flush adapter cache' timeout \n" - , pACB->host->host_no); -} - -static void arcmsr_report_sense_info(struct CommandControlBlock *pCCB) -{ - struct scsi_cmnd *pcmd = pCCB->pcmd; - struct SENSE_DATA *psenseBuffer = (struct SENSE_DATA *)pcmd->sense_buffer; - - pcmd->result = DID_OK << 16; - if (psenseBuffer) { - int sense_data_length = - sizeof (struct SENSE_DATA) < sizeof (pcmd->sense_buffer) - ? sizeof (struct SENSE_DATA) : sizeof (pcmd->sense_buffer); - memset(psenseBuffer, 0, sizeof (pcmd->sense_buffer)); - memcpy(psenseBuffer, pCCB->arcmsr_cdb.SenseData, sense_data_length); - psenseBuffer->ErrorCode = SCSI_SENSE_CURRENT_ERRORS; - psenseBuffer->Valid = 1; - } -} - -static uint8_t arcmsr_wait_msgint_ready(struct AdapterControlBlock *pACB) -{ - struct MessageUnit __iomem *reg = pACB->pmu; - uint32_t Index; - uint8_t Retries = 0x00; - - do { - for(Index = 0; Index < 100; Index++) { - if (readl(®->outbound_intstatus) - & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) { - writel(ARCMSR_MU_OUTBOUND_MESSAGE0_INT - , ®->outbound_intstatus); - return 0x00; - } - msleep_interruptible(10); - }/*max 1 seconds*/ - } while (Retries++ < 20);/*max 20 sec*/ - return 0xff; -} - -void arcmsr_iop_reset(struct AdapterControlBlock *pACB) -{ - struct MessageUnit __iomem *reg = pACB->pmu; - struct CommandControlBlock *pCCB; - uint32_t intmask_org, mask; - int i = 0; - - if (atomic_read(&pACB->ccboutstandingcount) != 0) { - /* talk to iop 331 outstanding command aborted */ - arcmsr_abort_allcmd(pACB); - /* wait for 3 sec for all command aborted*/ - msleep_interruptible(3000); - /* disable all outbound interrupt */ - intmask_org = readl(®->outbound_intmask); - writel(intmask_org | ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE, - ®->outbound_intmask); - /* clear all outbound posted Q */ - for(i = 0; i < ARCMSR_MAX_OUTSTANDING_CMD; i++) - readl(®->outbound_queueport); - for(i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { - pCCB = pACB->pccb_pool[i]; - if (pCCB->startdone == ARCMSR_CCB_START) { - pCCB->startdone = ARCMSR_CCB_ABORTED; - pCCB->pcmd->result = DID_ABORT << 16; - arcmsr_ccb_complete(pCCB, 1); - } - } - /* enable all outbound interrupt */ - mask =~ (ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE - | ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE); - writel(intmask_org & mask, ®->outbound_intmask); - } - atomic_set(&pACB->ccboutstandingcount, 0); -} - -static void arcmsr_build_ccb(struct AdapterControlBlock *pACB, struct CommandControlBlock *pCCB, - struct scsi_cmnd *pcmd) -{ - struct ARCMSR_CDB *pARCMSR_CDB = (struct ARCMSR_CDB *)&pCCB->arcmsr_cdb; - int8_t *psge = (int8_t *)&pARCMSR_CDB->u; - uint32_t address_lo, address_hi; - int arccdbsize = 0x30; - - pCCB->pcmd = pcmd; - memset(pARCMSR_CDB, 0, sizeof (struct ARCMSR_CDB)); - pARCMSR_CDB->Bus = 0; - pARCMSR_CDB->TargetID = pcmd->device->id; - pARCMSR_CDB->LUN = pcmd->device->lun; - pARCMSR_CDB->Function = 1; - pARCMSR_CDB->CdbLength = (uint8_t)pcmd->cmd_len; - pARCMSR_CDB->Context = (unsigned long)pARCMSR_CDB; - memcpy(pARCMSR_CDB->Cdb, pcmd->cmnd, pcmd->cmd_len); - if (pcmd->use_sg) { - int length, sgcount, i, cdb_sgcount = 0; - struct scatterlist *sl; - - /* Get Scatter Gather List from scsiport. */ - sl = (struct scatterlist *) pcmd->request_buffer; - sgcount = pci_map_sg(pACB->pdev, sl, pcmd->use_sg, - pcmd->sc_data_direction); - /* map stor port SG list to our iop SG List. */ - for(i = 0; i < sgcount; i++) { - /* Get the physical address of the current data pointer */ - length = cpu_to_le32(sg_dma_len(sl)); - address_lo = cpu_to_le32(dma_addr_lo32(sg_dma_address(sl))); - address_hi = cpu_to_le32(dma_addr_hi32(sg_dma_address(sl))); - if (address_hi == 0) { - struct SG32ENTRY *pdma_sg = (struct SG32ENTRY *)psge; - - pdma_sg->address = address_lo; - pdma_sg->length = length; - psge += sizeof (struct SG32ENTRY); - arccdbsize += sizeof (struct SG32ENTRY); - } else { - struct SG64ENTRY *pdma_sg = (struct SG64ENTRY *)psge; - - pdma_sg->addresshigh = address_hi; - pdma_sg->address = address_lo; - pdma_sg->length = length|IS_SG64_ADDR; - psge += sizeof (struct SG64ENTRY); - arccdbsize += sizeof (struct SG64ENTRY); - } - sl++; - cdb_sgcount++; - } - pARCMSR_CDB->sgcount = (uint8_t)cdb_sgcount; - pARCMSR_CDB->DataLength = pcmd->request_bufflen; - if ( arccdbsize > 256) - pARCMSR_CDB->Flags |= ARCMSR_CDB_FLAG_SGL_BSIZE; - } else if (pcmd->request_bufflen) { - dma_addr_t dma_addr; - dma_addr = pci_map_single(pACB->pdev, pcmd->request_buffer, - pcmd->request_bufflen, pcmd->sc_data_direction); - pcmd->SCp.ptr = (char *)(unsigned long) dma_addr; - address_lo = cpu_to_le32(dma_addr_lo32(dma_addr)); - address_hi = cpu_to_le32(dma_addr_hi32(dma_addr)); - if (address_hi == 0) { - struct SG32ENTRY *pdma_sg = (struct SG32ENTRY *)psge; - pdma_sg->address = address_lo; - pdma_sg->length = pcmd->request_bufflen; - } else { - struct SG64ENTRY *pdma_sg = (struct SG64ENTRY *)psge; - pdma_sg->addresshigh = address_hi; - pdma_sg->address = address_lo; - pdma_sg->length = pcmd->request_bufflen|IS_SG64_ADDR; - } - pARCMSR_CDB->sgcount = 1; - pARCMSR_CDB->DataLength = pcmd->request_bufflen; - } - if (pcmd->sc_data_direction == DMA_TO_DEVICE ) { - pARCMSR_CDB->Flags |= ARCMSR_CDB_FLAG_WRITE; - pCCB->ccb_flags |= CCB_FLAG_WRITE; - } + struct MessageUnit __iomem *reg=pACB->pmu; + + writel(ARCMSR_INBOUND_MESG0_FLUSH_CACHE, ®->inbound_msgaddr0); + if (arcmsr_wait_msgint_ready(pACB)) + printk(KERN_NOTICE + "arcmsr%d: wait 'flush adapter cache' timeout \n" + , pACB->host->host_no); } -static void arcmsr_post_ccb(struct AdapterControlBlock *pACB, struct CommandControlBlock *pCCB) +static uint8_t arcmsr_wait_msgint_ready(struct AdapterControlBlock *pACB) { struct MessageUnit __iomem *reg = pACB->pmu; - uint32_t cdb_shifted_phyaddr = pCCB->cdb_shifted_phyaddr; - struct ARCMSR_CDB *pARCMSR_CDB = (struct ARCMSR_CDB *)&pCCB->arcmsr_cdb; + uint32_t Index; + uint8_t Retries = 0x00; - atomic_inc(&pACB->ccboutstandingcount); - pCCB->startdone = ARCMSR_CCB_START; - if (pARCMSR_CDB->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) - writel(cdb_shifted_phyaddr | ARCMSR_CCBPOST_FLAG_SGL_BSIZE, - ®->inbound_queueport); - else - writel(cdb_shifted_phyaddr, ®->inbound_queueport); + do { + for(Index = 0; Index < 100; Index++) { + if (readl(®->outbound_intstatus) + & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) { + writel(ARCMSR_MU_OUTBOUND_MESSAGE0_INT + , ®->outbound_intstatus); + return 0x00; + } + msleep_interruptible(10); + }/*max 1 seconds*/ + } while (Retries++ < 20);/*max 20 sec*/ + return 0xff; +} + +void arcmsr_iop_reset(struct AdapterControlBlock *pACB) +{ + struct MessageUnit __iomem *reg = pACB->pmu; + struct CommandControlBlock *pCCB; + uint32_t intmask_org; + int i = 0; + + if (atomic_read(&pACB->ccboutstandingcount) != 0) { + /* talk to iop 331 outstanding command aborted */ + arcmsr_abort_allcmd(pACB); + /* wait for 3 sec for all command aborted*/ + msleep_interruptible(3000); + /* disable all outbound interrupt */ + intmask_org = arcmsr_disable_outbound_ints(pACB); + /* clear all outbound posted Q */ + for(i = 0; i < ARCMSR_MAX_OUTSTANDING_CMD; i++) + readl(®->outbound_queueport); + for(i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { + pCCB = pACB->pccb_pool[i]; + if (pCCB->startdone == ARCMSR_CCB_START) { + pCCB->startdone = ARCMSR_CCB_ABORTED; + pCCB->pcmd->result = DID_ABORT << 16; + arcmsr_ccb_complete(pCCB, 1); + } + } + /* enable all outbound interrupt */ + arcmsr_enable_outbound_ints(pACB, intmask_org); + } + atomic_set(&pACB->ccboutstandingcount, 0); } void arcmsr_post_Qbuffer(struct AdapterControlBlock *pACB) @@ -1130,374 +1456,3 @@ } return retvalue; } - -static struct CommandControlBlock *arcmsr_get_freeccb(struct AdapterControlBlock *pACB) -{ - struct list_head *head = &pACB->ccb_free_list; - struct CommandControlBlock *pCCB = NULL; - - if (!list_empty(head)) { - pCCB = list_entry(head->next, struct CommandControlBlock, list); - list_del(head->next); - } - return pCCB; -} - -static int arcmsr_queue_command(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *)) -{ - struct Scsi_Host *host = cmd->device->host; - struct AdapterControlBlock *pACB = (struct AdapterControlBlock *) host->hostdata; - struct CommandControlBlock *pCCB; - int target = cmd->device->id; - int lun = cmd->device->lun; - uint8_t scsicmd = cmd->cmnd[0]; - - cmd->scsi_done = done; - cmd->host_scribble = NULL; - cmd->result = 0; - if (scsicmd == SYNCHRONIZE_CACHE) { - /* - ** 0x35 avoid synchronizing disk cache cmd after - ** .remove : arcmsr_device_remove (linux bug) - */ - if (pACB->devstate[target][lun] == ARECA_RAID_GONE) - cmd->result = (DID_NO_CONNECT << 16); - cmd->scsi_done(cmd); - return 0; - } - if (pACB->acb_flags & ACB_F_BUS_RESET) { - printk(KERN_NOTICE "arcmsr%d: bus reset" - " and return busy \n" - , pACB->host->host_no); - return SCSI_MLQUEUE_HOST_BUSY; - } - if(target == 16) { - /* virtual device for iop message transfer */ - switch(scsicmd) { - case INQUIRY: { - unsigned char inqdata[36]; - char *buffer; - - if(lun != 0) { - cmd->result = (DID_TIME_OUT << 16); - cmd->scsi_done(cmd); - return 0; - } - inqdata[0] = TYPE_PROCESSOR; - /* Periph Qualifier & Periph Dev Type */ - inqdata[1] = 0; - /* rem media bit & Dev Type Modifier */ - inqdata[2] = 0; - /* ISO,ECMA,& ANSI versions */ - inqdata[4] = 31; - /* length of additional data */ - strncpy(&inqdata[8], "Areca ", 8); - /* Vendor Identification */ - strncpy(&inqdata[16], "RAID controller ", 16); - /* Product Identification */ - strncpy(&inqdata[32], "R001", 4); /* Product Revision */ - if (cmd->use_sg) { - struct scatterlist *sg; - - sg = (struct scatterlist *) cmd->request_buffer; - buffer = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; - } else { - buffer = cmd->request_buffer; - } - memcpy(buffer, inqdata, sizeof(inqdata)); - if (cmd->use_sg) { - struct scatterlist *sg; - - sg = (struct scatterlist *) cmd->request_buffer; - kunmap_atomic(buffer - sg->offset, KM_IRQ0); - } - cmd->scsi_done(cmd); - return 0; - } - case WRITE_BUFFER: - case READ_BUFFER: { - if (arcmsr_iop_message_xfer(pACB, cmd)) { - cmd->result = (DID_ERROR << 16); - } - cmd->scsi_done(cmd); - return 0; - } - default: - cmd->scsi_done(cmd); - return 0; - } - } - if (pACB->devstate[target][lun] == ARECA_RAID_GONE) { - uint8_t block_cmd; - - block_cmd = cmd->cmnd[0] & 0x0f; - if (block_cmd == 0x08 || block_cmd == 0x0a) { - printk(KERN_NOTICE - "arcmsr%d: block 'read/write'" - "command with gone raid volume" - " Cmd=%2x, TargetId=%d, Lun=%d \n" - , pACB->host->host_no - , cmd->cmnd[0] - , target - , lun); - cmd->result = (DID_NO_CONNECT << 16); - cmd->scsi_done(cmd); - return 0; - } - } - if (atomic_read(&pACB->ccboutstandingcount) < ARCMSR_MAX_OUTSTANDING_CMD) { - pCCB = arcmsr_get_freeccb(pACB); - if (pCCB) { - arcmsr_build_ccb(pACB, pCCB, cmd); - arcmsr_post_ccb(pACB, pCCB); - return 0; - } - } - return SCSI_MLQUEUE_HOST_BUSY; -} - -static void arcmsr_polling_ccbdone(struct AdapterControlBlock *pACB, struct CommandControlBlock *poll_ccb) -{ - struct MessageUnit __iomem *reg = pACB->pmu; - struct CommandControlBlock *pCCB; - uint32_t flag_ccb, outbound_intstatus, poll_ccb_done = 0, poll_count = 0; - int id, lun; - -polling_ccb_retry: - poll_count++; - outbound_intstatus = readl(®->outbound_intstatus) - & pACB->outbound_int_enable; - writel(outbound_intstatus, ®->outbound_intstatus);/*clear interrupt*/ - while (1) { - if ((flag_ccb = readl(®->outbound_queueport)) == 0xFFFFFFFF) { - if (poll_ccb_done) - break; - else { - msleep(25); - if (poll_count > 100) - break; - goto polling_ccb_retry; - } - } - pCCB = (struct CommandControlBlock *)(pACB->vir2phy_offset + (flag_ccb << 5)); - if ((pCCB->pACB != pACB) || (pCCB->startdone != ARCMSR_CCB_START)) { - if ((pCCB->startdone == ARCMSR_CCB_ABORTED) && (pCCB == poll_ccb)) { - printk(KERN_NOTICE - "arcmsr%d: scsi id=%d lun=%d ccb='0x%p'" - " poll command abort successfully \n" - , pACB->host->host_no - , pCCB->pcmd->device->id - , pCCB->pcmd->device->lun - , pCCB); - pCCB->pcmd->result = DID_ABORT << 16; - arcmsr_ccb_complete(pCCB, 1); - poll_ccb_done = 1; - continue; - } - printk(KERN_NOTICE - "arcmsr%d: polling get an illegal ccb" - " command done ccb='0x%p'" - "ccboutstandingcount=%d \n" - , pACB->host->host_no - , pCCB - , atomic_read(&pACB->ccboutstandingcount)); - continue; - } - id = pCCB->pcmd->device->id; - lun = pCCB->pcmd->device->lun; - if (!(flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR)) { - if (pACB->devstate[id][lun] == ARECA_RAID_GONE) - pACB->devstate[id][lun] = ARECA_RAID_GOOD; - pCCB->pcmd->result = DID_OK << 16; - arcmsr_ccb_complete(pCCB, 1); - } else { - switch(pCCB->arcmsr_cdb.DeviceStatus) { - case ARCMSR_DEV_SELECT_TIMEOUT: { - pACB->devstate[id][lun] = ARECA_RAID_GONE; - pCCB->pcmd->result = DID_TIME_OUT << 16; - arcmsr_ccb_complete(pCCB, 1); - } - break; - case ARCMSR_DEV_ABORTED: - case ARCMSR_DEV_INIT_FAIL: { - pACB->devstate[id][lun] = ARECA_RAID_GONE; - pCCB->pcmd->result = DID_BAD_TARGET << 16; - arcmsr_ccb_complete(pCCB, 1); - } - break; - case ARCMSR_DEV_CHECK_CONDITION: { - pACB->devstate[id][lun] = ARECA_RAID_GOOD; - arcmsr_report_sense_info(pCCB); - arcmsr_ccb_complete(pCCB, 1); - } - break; - default: - printk(KERN_NOTICE - "arcmsr%d: scsi id=%d lun=%d" - " polling and getting command error done" - "but got unknown DeviceStatus = 0x%x \n" - , pACB->host->host_no - , id - , lun - , pCCB->arcmsr_cdb.DeviceStatus); - pACB->devstate[id][lun] = ARECA_RAID_GONE; - pCCB->pcmd->result = DID_BAD_TARGET << 16; - arcmsr_ccb_complete(pCCB, 1); - break; - } - } - } -} - -static int arcmsr_bus_reset(struct scsi_cmnd *cmd) -{ - struct AdapterControlBlock *pACB; - int retry = 0; - - pACB = (struct AdapterControlBlock *) cmd->device->host->hostdata; - printk(KERN_NOTICE "arcmsr%d: bus reset ..... \n", pACB->host->host_no); - pACB->num_resets++; - pACB->acb_flags |= ACB_F_BUS_RESET; - while (atomic_read(&pACB->ccboutstandingcount) != 0 && retry < 400) { - arcmsr_interrupt(pACB); - msleep(25); - retry++; - } - arcmsr_iop_reset(pACB); - pACB->acb_flags &= ~ACB_F_BUS_RESET; - return SUCCESS; -} - -static int arcmsr_seek_cmd2abort(struct scsi_cmnd *abortcmd) -{ - struct AdapterControlBlock *pACB = (struct AdapterControlBlock *) - abortcmd->device->host->hostdata; - struct MessageUnit __iomem *reg = pACB->pmu; - struct CommandControlBlock *pCCB; - uint32_t intmask_org, mask; - int i = 0; - - pACB->num_aborts++; - /* - ***************************************************************** - ** It is the upper layer do abort command this lock just prior - ** to calling us. - ** First determine if we currently own this command. - ** Start by searching the device queue. If not found - ** at all, and the system wanted us to just abort the - ** command return success. - ***************************************************************** - */ - if (atomic_read(&pACB->ccboutstandingcount) != 0) { - for(i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { - pCCB = pACB->pccb_pool[i]; - if (pCCB->startdone == ARCMSR_CCB_START) { - if (pCCB->pcmd == abortcmd) { - pCCB->startdone = ARCMSR_CCB_ABORTED; - printk(KERN_NOTICE - "arcmsr%d: scsi id=%d lun=%d" - " abort ccb '0x%p' outstanding command\n" - , pACB->host->host_no - , abortcmd->device->id - , abortcmd->device->lun - , pCCB); - goto abort_outstanding_cmd; - } - } - } - } - return SUCCESS; -abort_outstanding_cmd: - /*wait for 3 sec for all command done*/ - msleep_interruptible(3000); - /* disable all outbound interrupt */ - intmask_org = readl(®->outbound_intmask); - writel(intmask_org | ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE - , ®->outbound_intmask); - arcmsr_polling_ccbdone(pACB, pCCB); - /* enable all outbound interrupt */ - mask = ~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE - | ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE); - writel(intmask_org & mask, ®->outbound_intmask); - return SUCCESS; -} - -static int arcmsr_cmd_abort(struct scsi_cmnd *cmd) -{ - struct AdapterControlBlock *pACB = (struct AdapterControlBlock *) - cmd->device->host->hostdata; - int error; - - printk(KERN_NOTICE - "arcmsr%d: abort device command of scsi id=%d lun=%d \n" - , pACB->host->host_no - , cmd->device->id - , cmd->device->lun); - /* - ************************************************ - ** the all interrupt service routine is locked - ** we need to handle it as soon as possible and exit - ************************************************ - */ - error = arcmsr_seek_cmd2abort(cmd); - if (error != SUCCESS) - printk(KERN_NOTICE - "arcmsr%d: abort command failed scsi id=%d lun=%d \n" - , pACB->host->host_no - , cmd->device->id - , cmd->device->lun); - return error; -} - -static const char *arcmsr_info(struct Scsi_Host *host) -{ - static char buf[256]; - struct AdapterControlBlock *pACB; - uint16_t device_id; - - pACB = (struct AdapterControlBlock *) host->hostdata; - device_id = pACB->pdev->device; - switch(device_id) { - case PCI_DEVICE_ID_ARECA_1110: - case PCI_DEVICE_ID_ARECA_1210:{ - sprintf(buf, - "ARECA SATA HOST ADAPTER RAID CONTROLLER " - "\n %s" - , ARCMSR_DRIVER_VERSION); - break; - } - case PCI_DEVICE_ID_ARECA_1120: - case PCI_DEVICE_ID_ARECA_1130: - case PCI_DEVICE_ID_ARECA_1160: - case PCI_DEVICE_ID_ARECA_1170: - case PCI_DEVICE_ID_ARECA_1220: - case PCI_DEVICE_ID_ARECA_1230: - case PCI_DEVICE_ID_ARECA_1260: - case PCI_DEVICE_ID_ARECA_1270: - case PCI_DEVICE_ID_ARECA_1280: { - sprintf(buf, - "ARECA SATA HOST ADAPTER RAID CONTROLLER " - "(RAID6-ENGINE Inside)\n %s" - , ARCMSR_DRIVER_VERSION); - break; - } - case PCI_DEVICE_ID_ARECA_1380: - case PCI_DEVICE_ID_ARECA_1381: - case PCI_DEVICE_ID_ARECA_1680: - case PCI_DEVICE_ID_ARECA_1681: { - sprintf(buf, - "ARECA SAS HOST ADAPTER RAID CONTROLLER " - "(RAID6-ENGINE Inside)\n %s" - , ARCMSR_DRIVER_VERSION); - break; - } - default: { - sprintf(buf, - "ARECA X-TYPE HOST ADAPTER RAID CONTROLLER " - "(RAID6-ENGINE Inside)\n %s" - , ARCMSR_DRIVER_VERSION); - break; - } - } - return buf; -} - : send the line "unsubscribe linux-scsi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html