177266186SHannes Reinecke // SPDX-License-Identifier: GPL-2.0 277266186SHannes Reinecke /* 377266186SHannes Reinecke * Linux Driver for Mylex DAC960/AcceleRAID/eXtremeRAID PCI RAID Controllers 477266186SHannes Reinecke * 577266186SHannes Reinecke * This driver supports the newer, SCSI-based firmware interface only. 677266186SHannes Reinecke * 777266186SHannes Reinecke * Copyright 2017 Hannes Reinecke, SUSE Linux GmbH <hare@suse.com> 877266186SHannes Reinecke * 977266186SHannes Reinecke * Based on the original DAC960 driver, which has 1077266186SHannes Reinecke * Copyright 1998-2001 by Leonard N. Zubkoff <lnz@dandelion.com> 1177266186SHannes Reinecke * Portions Copyright 2002 by Mylex (An IBM Business Unit) 1277266186SHannes Reinecke */ 1377266186SHannes Reinecke 1477266186SHannes Reinecke #include <linux/module.h> 1577266186SHannes Reinecke #include <linux/types.h> 1677266186SHannes Reinecke #include <linux/delay.h> 1777266186SHannes Reinecke #include <linux/interrupt.h> 1877266186SHannes Reinecke #include <linux/pci.h> 1977266186SHannes Reinecke #include <linux/raid_class.h> 2077266186SHannes Reinecke #include <asm/unaligned.h> 2177266186SHannes Reinecke #include <scsi/scsi.h> 2277266186SHannes Reinecke #include <scsi/scsi_host.h> 2377266186SHannes Reinecke #include <scsi/scsi_device.h> 2477266186SHannes Reinecke #include <scsi/scsi_cmnd.h> 2577266186SHannes Reinecke #include <scsi/scsi_tcq.h> 2677266186SHannes Reinecke #include "myrs.h" 2777266186SHannes Reinecke 2877266186SHannes Reinecke static struct raid_template *myrs_raid_template; 2977266186SHannes Reinecke 3077266186SHannes Reinecke static struct myrs_devstate_name_entry { 3177266186SHannes Reinecke enum myrs_devstate state; 3277266186SHannes Reinecke char *name; 3377266186SHannes Reinecke } myrs_devstate_name_list[] = { 3477266186SHannes Reinecke { MYRS_DEVICE_UNCONFIGURED, "Unconfigured" }, 3577266186SHannes Reinecke { MYRS_DEVICE_ONLINE, "Online" }, 3677266186SHannes Reinecke { MYRS_DEVICE_REBUILD, "Rebuild" }, 3777266186SHannes Reinecke { MYRS_DEVICE_MISSING, "Missing" }, 3877266186SHannes Reinecke { MYRS_DEVICE_SUSPECTED_CRITICAL, "SuspectedCritical" }, 3977266186SHannes Reinecke { MYRS_DEVICE_OFFLINE, "Offline" }, 4077266186SHannes Reinecke { MYRS_DEVICE_CRITICAL, "Critical" }, 4177266186SHannes Reinecke { MYRS_DEVICE_SUSPECTED_DEAD, "SuspectedDead" }, 4277266186SHannes Reinecke { MYRS_DEVICE_COMMANDED_OFFLINE, "CommandedOffline" }, 4377266186SHannes Reinecke { MYRS_DEVICE_STANDBY, "Standby" }, 4477266186SHannes Reinecke { MYRS_DEVICE_INVALID_STATE, "Invalid" }, 4577266186SHannes Reinecke }; 4677266186SHannes Reinecke 4777266186SHannes Reinecke static char *myrs_devstate_name(enum myrs_devstate state) 4877266186SHannes Reinecke { 4977266186SHannes Reinecke struct myrs_devstate_name_entry *entry = myrs_devstate_name_list; 5077266186SHannes Reinecke int i; 5177266186SHannes Reinecke 5277266186SHannes Reinecke for (i = 0; i < ARRAY_SIZE(myrs_devstate_name_list); i++) { 5377266186SHannes Reinecke if (entry[i].state == state) 5477266186SHannes Reinecke return entry[i].name; 5577266186SHannes Reinecke } 5677266186SHannes Reinecke return NULL; 5777266186SHannes Reinecke } 5877266186SHannes Reinecke 5977266186SHannes Reinecke static struct myrs_raid_level_name_entry { 6077266186SHannes Reinecke enum myrs_raid_level level; 6177266186SHannes Reinecke char *name; 6277266186SHannes Reinecke } myrs_raid_level_name_list[] = { 6377266186SHannes Reinecke { MYRS_RAID_LEVEL0, "RAID0" }, 6477266186SHannes Reinecke { MYRS_RAID_LEVEL1, "RAID1" }, 6577266186SHannes Reinecke { MYRS_RAID_LEVEL3, "RAID3 right asymmetric parity" }, 6677266186SHannes Reinecke { MYRS_RAID_LEVEL5, "RAID5 right asymmetric parity" }, 6777266186SHannes Reinecke { MYRS_RAID_LEVEL6, "RAID6" }, 6877266186SHannes Reinecke { MYRS_RAID_JBOD, "JBOD" }, 6977266186SHannes Reinecke { MYRS_RAID_NEWSPAN, "New Mylex SPAN" }, 7077266186SHannes Reinecke { MYRS_RAID_LEVEL3F, "RAID3 fixed parity" }, 7177266186SHannes Reinecke { MYRS_RAID_LEVEL3L, "RAID3 left symmetric parity" }, 7277266186SHannes Reinecke { MYRS_RAID_SPAN, "Mylex SPAN" }, 7377266186SHannes Reinecke { MYRS_RAID_LEVEL5L, "RAID5 left symmetric parity" }, 7477266186SHannes Reinecke { MYRS_RAID_LEVELE, "RAIDE (concatenation)" }, 7577266186SHannes Reinecke { MYRS_RAID_PHYSICAL, "Physical device" }, 7677266186SHannes Reinecke }; 7777266186SHannes Reinecke 7877266186SHannes Reinecke static char *myrs_raid_level_name(enum myrs_raid_level level) 7977266186SHannes Reinecke { 8077266186SHannes Reinecke struct myrs_raid_level_name_entry *entry = myrs_raid_level_name_list; 8177266186SHannes Reinecke int i; 8277266186SHannes Reinecke 8377266186SHannes Reinecke for (i = 0; i < ARRAY_SIZE(myrs_raid_level_name_list); i++) { 8477266186SHannes Reinecke if (entry[i].level == level) 8577266186SHannes Reinecke return entry[i].name; 8677266186SHannes Reinecke } 8777266186SHannes Reinecke return NULL; 8877266186SHannes Reinecke } 8977266186SHannes Reinecke 908a692fdbSLee Jones /* 9177266186SHannes Reinecke * myrs_reset_cmd - clears critical fields in struct myrs_cmdblk 9277266186SHannes Reinecke */ 9377266186SHannes Reinecke static inline void myrs_reset_cmd(struct myrs_cmdblk *cmd_blk) 9477266186SHannes Reinecke { 9577266186SHannes Reinecke union myrs_cmd_mbox *mbox = &cmd_blk->mbox; 9677266186SHannes Reinecke 9777266186SHannes Reinecke memset(mbox, 0, sizeof(union myrs_cmd_mbox)); 9877266186SHannes Reinecke cmd_blk->status = 0; 9977266186SHannes Reinecke } 10077266186SHannes Reinecke 1018a692fdbSLee Jones /* 10277266186SHannes Reinecke * myrs_qcmd - queues Command for DAC960 V2 Series Controllers. 10377266186SHannes Reinecke */ 10477266186SHannes Reinecke static void myrs_qcmd(struct myrs_hba *cs, struct myrs_cmdblk *cmd_blk) 10577266186SHannes Reinecke { 10677266186SHannes Reinecke void __iomem *base = cs->io_base; 10777266186SHannes Reinecke union myrs_cmd_mbox *mbox = &cmd_blk->mbox; 10877266186SHannes Reinecke union myrs_cmd_mbox *next_mbox = cs->next_cmd_mbox; 10977266186SHannes Reinecke 11077266186SHannes Reinecke cs->write_cmd_mbox(next_mbox, mbox); 11177266186SHannes Reinecke 11277266186SHannes Reinecke if (cs->prev_cmd_mbox1->words[0] == 0 || 11377266186SHannes Reinecke cs->prev_cmd_mbox2->words[0] == 0) 11477266186SHannes Reinecke cs->get_cmd_mbox(base); 11577266186SHannes Reinecke 11677266186SHannes Reinecke cs->prev_cmd_mbox2 = cs->prev_cmd_mbox1; 11777266186SHannes Reinecke cs->prev_cmd_mbox1 = next_mbox; 11877266186SHannes Reinecke 11977266186SHannes Reinecke if (++next_mbox > cs->last_cmd_mbox) 12077266186SHannes Reinecke next_mbox = cs->first_cmd_mbox; 12177266186SHannes Reinecke 12277266186SHannes Reinecke cs->next_cmd_mbox = next_mbox; 12377266186SHannes Reinecke } 12477266186SHannes Reinecke 1258a692fdbSLee Jones /* 12677266186SHannes Reinecke * myrs_exec_cmd - executes V2 Command and waits for completion. 12777266186SHannes Reinecke */ 12877266186SHannes Reinecke static void myrs_exec_cmd(struct myrs_hba *cs, 12977266186SHannes Reinecke struct myrs_cmdblk *cmd_blk) 13077266186SHannes Reinecke { 13177266186SHannes Reinecke DECLARE_COMPLETION_ONSTACK(complete); 13277266186SHannes Reinecke unsigned long flags; 13377266186SHannes Reinecke 13477266186SHannes Reinecke cmd_blk->complete = &complete; 13577266186SHannes Reinecke spin_lock_irqsave(&cs->queue_lock, flags); 13677266186SHannes Reinecke myrs_qcmd(cs, cmd_blk); 13777266186SHannes Reinecke spin_unlock_irqrestore(&cs->queue_lock, flags); 13877266186SHannes Reinecke 13977266186SHannes Reinecke WARN_ON(in_interrupt()); 14077266186SHannes Reinecke wait_for_completion(&complete); 14177266186SHannes Reinecke } 14277266186SHannes Reinecke 1438a692fdbSLee Jones /* 14477266186SHannes Reinecke * myrs_report_progress - prints progress message 14577266186SHannes Reinecke */ 14677266186SHannes Reinecke static void myrs_report_progress(struct myrs_hba *cs, unsigned short ldev_num, 14777266186SHannes Reinecke unsigned char *msg, unsigned long blocks, 14877266186SHannes Reinecke unsigned long size) 14977266186SHannes Reinecke { 15077266186SHannes Reinecke shost_printk(KERN_INFO, cs->host, 15177266186SHannes Reinecke "Logical Drive %d: %s in Progress: %d%% completed\n", 15277266186SHannes Reinecke ldev_num, msg, 15377266186SHannes Reinecke (100 * (int)(blocks >> 7)) / (int)(size >> 7)); 15477266186SHannes Reinecke } 15577266186SHannes Reinecke 1568a692fdbSLee Jones /* 15777266186SHannes Reinecke * myrs_get_ctlr_info - executes a Controller Information IOCTL Command 15877266186SHannes Reinecke */ 15977266186SHannes Reinecke static unsigned char myrs_get_ctlr_info(struct myrs_hba *cs) 16077266186SHannes Reinecke { 16177266186SHannes Reinecke struct myrs_cmdblk *cmd_blk = &cs->dcmd_blk; 16277266186SHannes Reinecke union myrs_cmd_mbox *mbox = &cmd_blk->mbox; 16377266186SHannes Reinecke dma_addr_t ctlr_info_addr; 16477266186SHannes Reinecke union myrs_sgl *sgl; 16577266186SHannes Reinecke unsigned char status; 16677409c4cSArnd Bergmann unsigned short ldev_present, ldev_critical, ldev_offline; 16777266186SHannes Reinecke 16877409c4cSArnd Bergmann ldev_present = cs->ctlr_info->ldev_present; 16977409c4cSArnd Bergmann ldev_critical = cs->ctlr_info->ldev_critical; 17077409c4cSArnd Bergmann ldev_offline = cs->ctlr_info->ldev_offline; 17177409c4cSArnd Bergmann 17277266186SHannes Reinecke ctlr_info_addr = dma_map_single(&cs->pdev->dev, cs->ctlr_info, 17377266186SHannes Reinecke sizeof(struct myrs_ctlr_info), 17477266186SHannes Reinecke DMA_FROM_DEVICE); 17577266186SHannes Reinecke if (dma_mapping_error(&cs->pdev->dev, ctlr_info_addr)) 17677266186SHannes Reinecke return MYRS_STATUS_FAILED; 17777266186SHannes Reinecke 17877266186SHannes Reinecke mutex_lock(&cs->dcmd_mutex); 17977266186SHannes Reinecke myrs_reset_cmd(cmd_blk); 18077266186SHannes Reinecke mbox->ctlr_info.id = MYRS_DCMD_TAG; 18177266186SHannes Reinecke mbox->ctlr_info.opcode = MYRS_CMD_OP_IOCTL; 18277266186SHannes Reinecke mbox->ctlr_info.control.dma_ctrl_to_host = true; 18377266186SHannes Reinecke mbox->ctlr_info.control.no_autosense = true; 18477266186SHannes Reinecke mbox->ctlr_info.dma_size = sizeof(struct myrs_ctlr_info); 18577266186SHannes Reinecke mbox->ctlr_info.ctlr_num = 0; 18677266186SHannes Reinecke mbox->ctlr_info.ioctl_opcode = MYRS_IOCTL_GET_CTLR_INFO; 18777266186SHannes Reinecke sgl = &mbox->ctlr_info.dma_addr; 18877266186SHannes Reinecke sgl->sge[0].sge_addr = ctlr_info_addr; 18977266186SHannes Reinecke sgl->sge[0].sge_count = mbox->ctlr_info.dma_size; 19077266186SHannes Reinecke dev_dbg(&cs->host->shost_gendev, "Sending GetControllerInfo\n"); 19177266186SHannes Reinecke myrs_exec_cmd(cs, cmd_blk); 19277266186SHannes Reinecke status = cmd_blk->status; 19377266186SHannes Reinecke mutex_unlock(&cs->dcmd_mutex); 19477266186SHannes Reinecke dma_unmap_single(&cs->pdev->dev, ctlr_info_addr, 19577266186SHannes Reinecke sizeof(struct myrs_ctlr_info), DMA_FROM_DEVICE); 19677266186SHannes Reinecke if (status == MYRS_STATUS_SUCCESS) { 19777266186SHannes Reinecke if (cs->ctlr_info->bg_init_active + 19877266186SHannes Reinecke cs->ctlr_info->ldev_init_active + 19977266186SHannes Reinecke cs->ctlr_info->pdev_init_active + 20077266186SHannes Reinecke cs->ctlr_info->cc_active + 20177266186SHannes Reinecke cs->ctlr_info->rbld_active + 20277266186SHannes Reinecke cs->ctlr_info->exp_active != 0) 20377266186SHannes Reinecke cs->needs_update = true; 20477409c4cSArnd Bergmann if (cs->ctlr_info->ldev_present != ldev_present || 20577409c4cSArnd Bergmann cs->ctlr_info->ldev_critical != ldev_critical || 20677409c4cSArnd Bergmann cs->ctlr_info->ldev_offline != ldev_offline) 20777266186SHannes Reinecke shost_printk(KERN_INFO, cs->host, 20877266186SHannes Reinecke "Logical drive count changes (%d/%d/%d)\n", 20977266186SHannes Reinecke cs->ctlr_info->ldev_critical, 21077266186SHannes Reinecke cs->ctlr_info->ldev_offline, 21177266186SHannes Reinecke cs->ctlr_info->ldev_present); 21277266186SHannes Reinecke } 21377266186SHannes Reinecke 21477266186SHannes Reinecke return status; 21577266186SHannes Reinecke } 21677266186SHannes Reinecke 2178a692fdbSLee Jones /* 21877266186SHannes Reinecke * myrs_get_ldev_info - executes a Logical Device Information IOCTL Command 21977266186SHannes Reinecke */ 22077266186SHannes Reinecke static unsigned char myrs_get_ldev_info(struct myrs_hba *cs, 22177266186SHannes Reinecke unsigned short ldev_num, struct myrs_ldev_info *ldev_info) 22277266186SHannes Reinecke { 22377266186SHannes Reinecke struct myrs_cmdblk *cmd_blk = &cs->dcmd_blk; 22477266186SHannes Reinecke union myrs_cmd_mbox *mbox = &cmd_blk->mbox; 22577266186SHannes Reinecke dma_addr_t ldev_info_addr; 22677266186SHannes Reinecke struct myrs_ldev_info ldev_info_orig; 22777266186SHannes Reinecke union myrs_sgl *sgl; 22877266186SHannes Reinecke unsigned char status; 22977266186SHannes Reinecke 23077266186SHannes Reinecke memcpy(&ldev_info_orig, ldev_info, sizeof(struct myrs_ldev_info)); 23177266186SHannes Reinecke ldev_info_addr = dma_map_single(&cs->pdev->dev, ldev_info, 23277266186SHannes Reinecke sizeof(struct myrs_ldev_info), 23377266186SHannes Reinecke DMA_FROM_DEVICE); 23477266186SHannes Reinecke if (dma_mapping_error(&cs->pdev->dev, ldev_info_addr)) 23577266186SHannes Reinecke return MYRS_STATUS_FAILED; 23677266186SHannes Reinecke 23777266186SHannes Reinecke mutex_lock(&cs->dcmd_mutex); 23877266186SHannes Reinecke myrs_reset_cmd(cmd_blk); 23977266186SHannes Reinecke mbox->ldev_info.id = MYRS_DCMD_TAG; 24077266186SHannes Reinecke mbox->ldev_info.opcode = MYRS_CMD_OP_IOCTL; 24177266186SHannes Reinecke mbox->ldev_info.control.dma_ctrl_to_host = true; 24277266186SHannes Reinecke mbox->ldev_info.control.no_autosense = true; 24377266186SHannes Reinecke mbox->ldev_info.dma_size = sizeof(struct myrs_ldev_info); 24477266186SHannes Reinecke mbox->ldev_info.ldev.ldev_num = ldev_num; 24577266186SHannes Reinecke mbox->ldev_info.ioctl_opcode = MYRS_IOCTL_GET_LDEV_INFO_VALID; 24677266186SHannes Reinecke sgl = &mbox->ldev_info.dma_addr; 24777266186SHannes Reinecke sgl->sge[0].sge_addr = ldev_info_addr; 24877266186SHannes Reinecke sgl->sge[0].sge_count = mbox->ldev_info.dma_size; 24977266186SHannes Reinecke dev_dbg(&cs->host->shost_gendev, 25077266186SHannes Reinecke "Sending GetLogicalDeviceInfoValid for ldev %d\n", ldev_num); 25177266186SHannes Reinecke myrs_exec_cmd(cs, cmd_blk); 25277266186SHannes Reinecke status = cmd_blk->status; 25377266186SHannes Reinecke mutex_unlock(&cs->dcmd_mutex); 25477266186SHannes Reinecke dma_unmap_single(&cs->pdev->dev, ldev_info_addr, 25577266186SHannes Reinecke sizeof(struct myrs_ldev_info), DMA_FROM_DEVICE); 25677266186SHannes Reinecke if (status == MYRS_STATUS_SUCCESS) { 25777266186SHannes Reinecke unsigned short ldev_num = ldev_info->ldev_num; 25877266186SHannes Reinecke struct myrs_ldev_info *new = ldev_info; 25977266186SHannes Reinecke struct myrs_ldev_info *old = &ldev_info_orig; 26077266186SHannes Reinecke unsigned long ldev_size = new->cfg_devsize; 26177266186SHannes Reinecke 26277266186SHannes Reinecke if (new->dev_state != old->dev_state) { 26377266186SHannes Reinecke const char *name; 26477266186SHannes Reinecke 26577266186SHannes Reinecke name = myrs_devstate_name(new->dev_state); 26677266186SHannes Reinecke shost_printk(KERN_INFO, cs->host, 26777266186SHannes Reinecke "Logical Drive %d is now %s\n", 26877266186SHannes Reinecke ldev_num, name ? name : "Invalid"); 26977266186SHannes Reinecke } 27077266186SHannes Reinecke if ((new->soft_errs != old->soft_errs) || 27177266186SHannes Reinecke (new->cmds_failed != old->cmds_failed) || 27277266186SHannes Reinecke (new->deferred_write_errs != old->deferred_write_errs)) 27377266186SHannes Reinecke shost_printk(KERN_INFO, cs->host, 27477266186SHannes Reinecke "Logical Drive %d Errors: Soft = %d, Failed = %d, Deferred Write = %d\n", 27577266186SHannes Reinecke ldev_num, new->soft_errs, 27677266186SHannes Reinecke new->cmds_failed, 27777266186SHannes Reinecke new->deferred_write_errs); 27877266186SHannes Reinecke if (new->bg_init_active) 27977266186SHannes Reinecke myrs_report_progress(cs, ldev_num, 28077266186SHannes Reinecke "Background Initialization", 28177266186SHannes Reinecke new->bg_init_lba, ldev_size); 28277266186SHannes Reinecke else if (new->fg_init_active) 28377266186SHannes Reinecke myrs_report_progress(cs, ldev_num, 28477266186SHannes Reinecke "Foreground Initialization", 28577266186SHannes Reinecke new->fg_init_lba, ldev_size); 28677266186SHannes Reinecke else if (new->migration_active) 28777266186SHannes Reinecke myrs_report_progress(cs, ldev_num, 28877266186SHannes Reinecke "Data Migration", 28977266186SHannes Reinecke new->migration_lba, ldev_size); 29077266186SHannes Reinecke else if (new->patrol_active) 29177266186SHannes Reinecke myrs_report_progress(cs, ldev_num, 29277266186SHannes Reinecke "Patrol Operation", 29377266186SHannes Reinecke new->patrol_lba, ldev_size); 29477266186SHannes Reinecke if (old->bg_init_active && !new->bg_init_active) 29577266186SHannes Reinecke shost_printk(KERN_INFO, cs->host, 29677266186SHannes Reinecke "Logical Drive %d: Background Initialization %s\n", 29777266186SHannes Reinecke ldev_num, 29877266186SHannes Reinecke (new->ldev_control.ldev_init_done ? 29977266186SHannes Reinecke "Completed" : "Failed")); 30077266186SHannes Reinecke } 30177266186SHannes Reinecke return status; 30277266186SHannes Reinecke } 30377266186SHannes Reinecke 3048a692fdbSLee Jones /* 30577266186SHannes Reinecke * myrs_get_pdev_info - executes a "Read Physical Device Information" Command 30677266186SHannes Reinecke */ 30777266186SHannes Reinecke static unsigned char myrs_get_pdev_info(struct myrs_hba *cs, 30877266186SHannes Reinecke unsigned char channel, unsigned char target, unsigned char lun, 30977266186SHannes Reinecke struct myrs_pdev_info *pdev_info) 31077266186SHannes Reinecke { 31177266186SHannes Reinecke struct myrs_cmdblk *cmd_blk = &cs->dcmd_blk; 31277266186SHannes Reinecke union myrs_cmd_mbox *mbox = &cmd_blk->mbox; 31377266186SHannes Reinecke dma_addr_t pdev_info_addr; 31477266186SHannes Reinecke union myrs_sgl *sgl; 31577266186SHannes Reinecke unsigned char status; 31677266186SHannes Reinecke 31777266186SHannes Reinecke pdev_info_addr = dma_map_single(&cs->pdev->dev, pdev_info, 31877266186SHannes Reinecke sizeof(struct myrs_pdev_info), 31977266186SHannes Reinecke DMA_FROM_DEVICE); 32077266186SHannes Reinecke if (dma_mapping_error(&cs->pdev->dev, pdev_info_addr)) 32177266186SHannes Reinecke return MYRS_STATUS_FAILED; 32277266186SHannes Reinecke 32377266186SHannes Reinecke mutex_lock(&cs->dcmd_mutex); 32477266186SHannes Reinecke myrs_reset_cmd(cmd_blk); 32577266186SHannes Reinecke mbox->pdev_info.opcode = MYRS_CMD_OP_IOCTL; 32677266186SHannes Reinecke mbox->pdev_info.id = MYRS_DCMD_TAG; 32777266186SHannes Reinecke mbox->pdev_info.control.dma_ctrl_to_host = true; 32877266186SHannes Reinecke mbox->pdev_info.control.no_autosense = true; 32977266186SHannes Reinecke mbox->pdev_info.dma_size = sizeof(struct myrs_pdev_info); 33077266186SHannes Reinecke mbox->pdev_info.pdev.lun = lun; 33177266186SHannes Reinecke mbox->pdev_info.pdev.target = target; 33277266186SHannes Reinecke mbox->pdev_info.pdev.channel = channel; 33377266186SHannes Reinecke mbox->pdev_info.ioctl_opcode = MYRS_IOCTL_GET_PDEV_INFO_VALID; 33477266186SHannes Reinecke sgl = &mbox->pdev_info.dma_addr; 33577266186SHannes Reinecke sgl->sge[0].sge_addr = pdev_info_addr; 33677266186SHannes Reinecke sgl->sge[0].sge_count = mbox->pdev_info.dma_size; 33777266186SHannes Reinecke dev_dbg(&cs->host->shost_gendev, 33877266186SHannes Reinecke "Sending GetPhysicalDeviceInfoValid for pdev %d:%d:%d\n", 33977266186SHannes Reinecke channel, target, lun); 34077266186SHannes Reinecke myrs_exec_cmd(cs, cmd_blk); 34177266186SHannes Reinecke status = cmd_blk->status; 34277266186SHannes Reinecke mutex_unlock(&cs->dcmd_mutex); 34377266186SHannes Reinecke dma_unmap_single(&cs->pdev->dev, pdev_info_addr, 34477266186SHannes Reinecke sizeof(struct myrs_pdev_info), DMA_FROM_DEVICE); 34577266186SHannes Reinecke return status; 34677266186SHannes Reinecke } 34777266186SHannes Reinecke 3488a692fdbSLee Jones /* 34977266186SHannes Reinecke * myrs_dev_op - executes a "Device Operation" Command 35077266186SHannes Reinecke */ 35177266186SHannes Reinecke static unsigned char myrs_dev_op(struct myrs_hba *cs, 35277266186SHannes Reinecke enum myrs_ioctl_opcode opcode, enum myrs_opdev opdev) 35377266186SHannes Reinecke { 35477266186SHannes Reinecke struct myrs_cmdblk *cmd_blk = &cs->dcmd_blk; 35577266186SHannes Reinecke union myrs_cmd_mbox *mbox = &cmd_blk->mbox; 35677266186SHannes Reinecke unsigned char status; 35777266186SHannes Reinecke 35877266186SHannes Reinecke mutex_lock(&cs->dcmd_mutex); 35977266186SHannes Reinecke myrs_reset_cmd(cmd_blk); 36077266186SHannes Reinecke mbox->dev_op.opcode = MYRS_CMD_OP_IOCTL; 36177266186SHannes Reinecke mbox->dev_op.id = MYRS_DCMD_TAG; 36277266186SHannes Reinecke mbox->dev_op.control.dma_ctrl_to_host = true; 36377266186SHannes Reinecke mbox->dev_op.control.no_autosense = true; 36477266186SHannes Reinecke mbox->dev_op.ioctl_opcode = opcode; 36577266186SHannes Reinecke mbox->dev_op.opdev = opdev; 36677266186SHannes Reinecke myrs_exec_cmd(cs, cmd_blk); 36777266186SHannes Reinecke status = cmd_blk->status; 36877266186SHannes Reinecke mutex_unlock(&cs->dcmd_mutex); 36977266186SHannes Reinecke return status; 37077266186SHannes Reinecke } 37177266186SHannes Reinecke 3728a692fdbSLee Jones /* 37377266186SHannes Reinecke * myrs_translate_pdev - translates a Physical Device Channel and 37477266186SHannes Reinecke * TargetID into a Logical Device. 37577266186SHannes Reinecke */ 37677266186SHannes Reinecke static unsigned char myrs_translate_pdev(struct myrs_hba *cs, 37777266186SHannes Reinecke unsigned char channel, unsigned char target, unsigned char lun, 37877266186SHannes Reinecke struct myrs_devmap *devmap) 37977266186SHannes Reinecke { 38077266186SHannes Reinecke struct pci_dev *pdev = cs->pdev; 38177266186SHannes Reinecke dma_addr_t devmap_addr; 38277266186SHannes Reinecke struct myrs_cmdblk *cmd_blk; 38377266186SHannes Reinecke union myrs_cmd_mbox *mbox; 38477266186SHannes Reinecke union myrs_sgl *sgl; 38577266186SHannes Reinecke unsigned char status; 38677266186SHannes Reinecke 38777266186SHannes Reinecke memset(devmap, 0x0, sizeof(struct myrs_devmap)); 38877266186SHannes Reinecke devmap_addr = dma_map_single(&pdev->dev, devmap, 38977266186SHannes Reinecke sizeof(struct myrs_devmap), 39077266186SHannes Reinecke DMA_FROM_DEVICE); 39177266186SHannes Reinecke if (dma_mapping_error(&pdev->dev, devmap_addr)) 39277266186SHannes Reinecke return MYRS_STATUS_FAILED; 39377266186SHannes Reinecke 39477266186SHannes Reinecke mutex_lock(&cs->dcmd_mutex); 39577266186SHannes Reinecke cmd_blk = &cs->dcmd_blk; 39677266186SHannes Reinecke mbox = &cmd_blk->mbox; 39777266186SHannes Reinecke mbox->pdev_info.opcode = MYRS_CMD_OP_IOCTL; 39877266186SHannes Reinecke mbox->pdev_info.control.dma_ctrl_to_host = true; 39977266186SHannes Reinecke mbox->pdev_info.control.no_autosense = true; 40077266186SHannes Reinecke mbox->pdev_info.dma_size = sizeof(struct myrs_devmap); 40177266186SHannes Reinecke mbox->pdev_info.pdev.target = target; 40277266186SHannes Reinecke mbox->pdev_info.pdev.channel = channel; 40377266186SHannes Reinecke mbox->pdev_info.pdev.lun = lun; 40477266186SHannes Reinecke mbox->pdev_info.ioctl_opcode = MYRS_IOCTL_XLATE_PDEV_TO_LDEV; 40577266186SHannes Reinecke sgl = &mbox->pdev_info.dma_addr; 40677266186SHannes Reinecke sgl->sge[0].sge_addr = devmap_addr; 40777266186SHannes Reinecke sgl->sge[0].sge_count = mbox->pdev_info.dma_size; 40877266186SHannes Reinecke 40977266186SHannes Reinecke myrs_exec_cmd(cs, cmd_blk); 41077266186SHannes Reinecke status = cmd_blk->status; 41177266186SHannes Reinecke mutex_unlock(&cs->dcmd_mutex); 41277266186SHannes Reinecke dma_unmap_single(&pdev->dev, devmap_addr, 41377266186SHannes Reinecke sizeof(struct myrs_devmap), DMA_FROM_DEVICE); 41477266186SHannes Reinecke return status; 41577266186SHannes Reinecke } 41677266186SHannes Reinecke 4178a692fdbSLee Jones /* 41877266186SHannes Reinecke * myrs_get_event - executes a Get Event Command 41977266186SHannes Reinecke */ 42077266186SHannes Reinecke static unsigned char myrs_get_event(struct myrs_hba *cs, 42177266186SHannes Reinecke unsigned int event_num, struct myrs_event *event_buf) 42277266186SHannes Reinecke { 42377266186SHannes Reinecke struct pci_dev *pdev = cs->pdev; 42477266186SHannes Reinecke dma_addr_t event_addr; 42577266186SHannes Reinecke struct myrs_cmdblk *cmd_blk = &cs->mcmd_blk; 42677266186SHannes Reinecke union myrs_cmd_mbox *mbox = &cmd_blk->mbox; 42777266186SHannes Reinecke union myrs_sgl *sgl; 42877266186SHannes Reinecke unsigned char status; 42977266186SHannes Reinecke 43077266186SHannes Reinecke event_addr = dma_map_single(&pdev->dev, event_buf, 43177266186SHannes Reinecke sizeof(struct myrs_event), DMA_FROM_DEVICE); 43277266186SHannes Reinecke if (dma_mapping_error(&pdev->dev, event_addr)) 43377266186SHannes Reinecke return MYRS_STATUS_FAILED; 43477266186SHannes Reinecke 43577266186SHannes Reinecke mbox->get_event.opcode = MYRS_CMD_OP_IOCTL; 43677266186SHannes Reinecke mbox->get_event.dma_size = sizeof(struct myrs_event); 43777266186SHannes Reinecke mbox->get_event.evnum_upper = event_num >> 16; 43877266186SHannes Reinecke mbox->get_event.ctlr_num = 0; 43977266186SHannes Reinecke mbox->get_event.ioctl_opcode = MYRS_IOCTL_GET_EVENT; 44077266186SHannes Reinecke mbox->get_event.evnum_lower = event_num & 0xFFFF; 44177266186SHannes Reinecke sgl = &mbox->get_event.dma_addr; 44277266186SHannes Reinecke sgl->sge[0].sge_addr = event_addr; 44377266186SHannes Reinecke sgl->sge[0].sge_count = mbox->get_event.dma_size; 44477266186SHannes Reinecke myrs_exec_cmd(cs, cmd_blk); 44577266186SHannes Reinecke status = cmd_blk->status; 44677266186SHannes Reinecke dma_unmap_single(&pdev->dev, event_addr, 44777266186SHannes Reinecke sizeof(struct myrs_event), DMA_FROM_DEVICE); 44877266186SHannes Reinecke 44977266186SHannes Reinecke return status; 45077266186SHannes Reinecke } 45177266186SHannes Reinecke 45277266186SHannes Reinecke /* 45377266186SHannes Reinecke * myrs_get_fwstatus - executes a Get Health Status Command 45477266186SHannes Reinecke */ 45577266186SHannes Reinecke static unsigned char myrs_get_fwstatus(struct myrs_hba *cs) 45677266186SHannes Reinecke { 45777266186SHannes Reinecke struct myrs_cmdblk *cmd_blk = &cs->mcmd_blk; 45877266186SHannes Reinecke union myrs_cmd_mbox *mbox = &cmd_blk->mbox; 45977266186SHannes Reinecke union myrs_sgl *sgl; 46077266186SHannes Reinecke unsigned char status = cmd_blk->status; 46177266186SHannes Reinecke 46277266186SHannes Reinecke myrs_reset_cmd(cmd_blk); 46377266186SHannes Reinecke mbox->common.opcode = MYRS_CMD_OP_IOCTL; 46477266186SHannes Reinecke mbox->common.id = MYRS_MCMD_TAG; 46577266186SHannes Reinecke mbox->common.control.dma_ctrl_to_host = true; 46677266186SHannes Reinecke mbox->common.control.no_autosense = true; 46777266186SHannes Reinecke mbox->common.dma_size = sizeof(struct myrs_fwstat); 46877266186SHannes Reinecke mbox->common.ioctl_opcode = MYRS_IOCTL_GET_HEALTH_STATUS; 46977266186SHannes Reinecke sgl = &mbox->common.dma_addr; 47077266186SHannes Reinecke sgl->sge[0].sge_addr = cs->fwstat_addr; 47177266186SHannes Reinecke sgl->sge[0].sge_count = mbox->ctlr_info.dma_size; 47277266186SHannes Reinecke dev_dbg(&cs->host->shost_gendev, "Sending GetHealthStatus\n"); 47377266186SHannes Reinecke myrs_exec_cmd(cs, cmd_blk); 47477266186SHannes Reinecke status = cmd_blk->status; 47577266186SHannes Reinecke 47677266186SHannes Reinecke return status; 47777266186SHannes Reinecke } 47877266186SHannes Reinecke 4798a692fdbSLee Jones /* 48077266186SHannes Reinecke * myrs_enable_mmio_mbox - enables the Memory Mailbox Interface 48177266186SHannes Reinecke */ 48277266186SHannes Reinecke static bool myrs_enable_mmio_mbox(struct myrs_hba *cs, 48377266186SHannes Reinecke enable_mbox_t enable_mbox_fn) 48477266186SHannes Reinecke { 48577266186SHannes Reinecke void __iomem *base = cs->io_base; 48677266186SHannes Reinecke struct pci_dev *pdev = cs->pdev; 48777266186SHannes Reinecke union myrs_cmd_mbox *cmd_mbox; 48877266186SHannes Reinecke struct myrs_stat_mbox *stat_mbox; 48977266186SHannes Reinecke union myrs_cmd_mbox *mbox; 49077266186SHannes Reinecke dma_addr_t mbox_addr; 49177266186SHannes Reinecke unsigned char status = MYRS_STATUS_FAILED; 49277266186SHannes Reinecke 49377266186SHannes Reinecke if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) 49477266186SHannes Reinecke if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(32))) { 49577266186SHannes Reinecke dev_err(&pdev->dev, "DMA mask out of range\n"); 49677266186SHannes Reinecke return false; 49777266186SHannes Reinecke } 49877266186SHannes Reinecke 49977266186SHannes Reinecke /* Temporary dma mapping, used only in the scope of this function */ 50077266186SHannes Reinecke mbox = dma_alloc_coherent(&pdev->dev, sizeof(union myrs_cmd_mbox), 50177266186SHannes Reinecke &mbox_addr, GFP_KERNEL); 50277266186SHannes Reinecke if (dma_mapping_error(&pdev->dev, mbox_addr)) 50377266186SHannes Reinecke return false; 50477266186SHannes Reinecke 50577266186SHannes Reinecke /* These are the base addresses for the command memory mailbox array */ 50677266186SHannes Reinecke cs->cmd_mbox_size = MYRS_MAX_CMD_MBOX * sizeof(union myrs_cmd_mbox); 50777266186SHannes Reinecke cmd_mbox = dma_alloc_coherent(&pdev->dev, cs->cmd_mbox_size, 50877266186SHannes Reinecke &cs->cmd_mbox_addr, GFP_KERNEL); 50977266186SHannes Reinecke if (dma_mapping_error(&pdev->dev, cs->cmd_mbox_addr)) { 51077266186SHannes Reinecke dev_err(&pdev->dev, "Failed to map command mailbox\n"); 51177266186SHannes Reinecke goto out_free; 51277266186SHannes Reinecke } 51377266186SHannes Reinecke cs->first_cmd_mbox = cmd_mbox; 51477266186SHannes Reinecke cmd_mbox += MYRS_MAX_CMD_MBOX - 1; 51577266186SHannes Reinecke cs->last_cmd_mbox = cmd_mbox; 51677266186SHannes Reinecke cs->next_cmd_mbox = cs->first_cmd_mbox; 51777266186SHannes Reinecke cs->prev_cmd_mbox1 = cs->last_cmd_mbox; 51877266186SHannes Reinecke cs->prev_cmd_mbox2 = cs->last_cmd_mbox - 1; 51977266186SHannes Reinecke 52077266186SHannes Reinecke /* These are the base addresses for the status memory mailbox array */ 52177266186SHannes Reinecke cs->stat_mbox_size = MYRS_MAX_STAT_MBOX * sizeof(struct myrs_stat_mbox); 52277266186SHannes Reinecke stat_mbox = dma_alloc_coherent(&pdev->dev, cs->stat_mbox_size, 52377266186SHannes Reinecke &cs->stat_mbox_addr, GFP_KERNEL); 52477266186SHannes Reinecke if (dma_mapping_error(&pdev->dev, cs->stat_mbox_addr)) { 52577266186SHannes Reinecke dev_err(&pdev->dev, "Failed to map status mailbox\n"); 52677266186SHannes Reinecke goto out_free; 52777266186SHannes Reinecke } 52877266186SHannes Reinecke 52977266186SHannes Reinecke cs->first_stat_mbox = stat_mbox; 53077266186SHannes Reinecke stat_mbox += MYRS_MAX_STAT_MBOX - 1; 53177266186SHannes Reinecke cs->last_stat_mbox = stat_mbox; 53277266186SHannes Reinecke cs->next_stat_mbox = cs->first_stat_mbox; 53377266186SHannes Reinecke 53477266186SHannes Reinecke cs->fwstat_buf = dma_alloc_coherent(&pdev->dev, 53577266186SHannes Reinecke sizeof(struct myrs_fwstat), 53677266186SHannes Reinecke &cs->fwstat_addr, GFP_KERNEL); 53777266186SHannes Reinecke if (dma_mapping_error(&pdev->dev, cs->fwstat_addr)) { 53877266186SHannes Reinecke dev_err(&pdev->dev, "Failed to map firmware health buffer\n"); 53977266186SHannes Reinecke cs->fwstat_buf = NULL; 54077266186SHannes Reinecke goto out_free; 54177266186SHannes Reinecke } 54277266186SHannes Reinecke cs->ctlr_info = kzalloc(sizeof(struct myrs_ctlr_info), 54377266186SHannes Reinecke GFP_KERNEL | GFP_DMA); 54477266186SHannes Reinecke if (!cs->ctlr_info) 54577266186SHannes Reinecke goto out_free; 54677266186SHannes Reinecke 54777266186SHannes Reinecke cs->event_buf = kzalloc(sizeof(struct myrs_event), 54877266186SHannes Reinecke GFP_KERNEL | GFP_DMA); 54977266186SHannes Reinecke if (!cs->event_buf) 55077266186SHannes Reinecke goto out_free; 55177266186SHannes Reinecke 55277266186SHannes Reinecke /* Enable the Memory Mailbox Interface. */ 55377266186SHannes Reinecke memset(mbox, 0, sizeof(union myrs_cmd_mbox)); 55477266186SHannes Reinecke mbox->set_mbox.id = 1; 55577266186SHannes Reinecke mbox->set_mbox.opcode = MYRS_CMD_OP_IOCTL; 55677266186SHannes Reinecke mbox->set_mbox.control.no_autosense = true; 55777266186SHannes Reinecke mbox->set_mbox.first_cmd_mbox_size_kb = 55877266186SHannes Reinecke (MYRS_MAX_CMD_MBOX * sizeof(union myrs_cmd_mbox)) >> 10; 55977266186SHannes Reinecke mbox->set_mbox.first_stat_mbox_size_kb = 56077266186SHannes Reinecke (MYRS_MAX_STAT_MBOX * sizeof(struct myrs_stat_mbox)) >> 10; 56177266186SHannes Reinecke mbox->set_mbox.second_cmd_mbox_size_kb = 0; 56277266186SHannes Reinecke mbox->set_mbox.second_stat_mbox_size_kb = 0; 56377266186SHannes Reinecke mbox->set_mbox.sense_len = 0; 56477266186SHannes Reinecke mbox->set_mbox.ioctl_opcode = MYRS_IOCTL_SET_MEM_MBOX; 56577266186SHannes Reinecke mbox->set_mbox.fwstat_buf_size_kb = 1; 56677266186SHannes Reinecke mbox->set_mbox.fwstat_buf_addr = cs->fwstat_addr; 56777266186SHannes Reinecke mbox->set_mbox.first_cmd_mbox_addr = cs->cmd_mbox_addr; 56877266186SHannes Reinecke mbox->set_mbox.first_stat_mbox_addr = cs->stat_mbox_addr; 56977266186SHannes Reinecke status = enable_mbox_fn(base, mbox_addr); 57077266186SHannes Reinecke 57177266186SHannes Reinecke out_free: 57277266186SHannes Reinecke dma_free_coherent(&pdev->dev, sizeof(union myrs_cmd_mbox), 57377266186SHannes Reinecke mbox, mbox_addr); 57477266186SHannes Reinecke if (status != MYRS_STATUS_SUCCESS) 57577266186SHannes Reinecke dev_err(&pdev->dev, "Failed to enable mailbox, status %X\n", 57677266186SHannes Reinecke status); 57777266186SHannes Reinecke return (status == MYRS_STATUS_SUCCESS); 57877266186SHannes Reinecke } 57977266186SHannes Reinecke 5808a692fdbSLee Jones /* 58177266186SHannes Reinecke * myrs_get_config - reads the Configuration Information 58277266186SHannes Reinecke */ 58377266186SHannes Reinecke static int myrs_get_config(struct myrs_hba *cs) 58477266186SHannes Reinecke { 58577266186SHannes Reinecke struct myrs_ctlr_info *info = cs->ctlr_info; 58677266186SHannes Reinecke struct Scsi_Host *shost = cs->host; 58777266186SHannes Reinecke unsigned char status; 58877266186SHannes Reinecke unsigned char model[20]; 58977266186SHannes Reinecke unsigned char fw_version[12]; 59077266186SHannes Reinecke int i, model_len; 59177266186SHannes Reinecke 59277266186SHannes Reinecke /* Get data into dma-able area, then copy into permanent location */ 59377266186SHannes Reinecke mutex_lock(&cs->cinfo_mutex); 59477266186SHannes Reinecke status = myrs_get_ctlr_info(cs); 59577266186SHannes Reinecke mutex_unlock(&cs->cinfo_mutex); 59677266186SHannes Reinecke if (status != MYRS_STATUS_SUCCESS) { 59777266186SHannes Reinecke shost_printk(KERN_ERR, shost, 59877266186SHannes Reinecke "Failed to get controller information\n"); 59977266186SHannes Reinecke return -ENODEV; 60077266186SHannes Reinecke } 60177266186SHannes Reinecke 60277266186SHannes Reinecke /* Initialize the Controller Model Name and Full Model Name fields. */ 60377266186SHannes Reinecke model_len = sizeof(info->ctlr_name); 60477266186SHannes Reinecke if (model_len > sizeof(model)-1) 60577266186SHannes Reinecke model_len = sizeof(model)-1; 60677266186SHannes Reinecke memcpy(model, info->ctlr_name, model_len); 60777266186SHannes Reinecke model_len--; 60877266186SHannes Reinecke while (model[model_len] == ' ' || model[model_len] == '\0') 60977266186SHannes Reinecke model_len--; 61077266186SHannes Reinecke model[++model_len] = '\0'; 61177266186SHannes Reinecke strcpy(cs->model_name, "DAC960 "); 61277266186SHannes Reinecke strcat(cs->model_name, model); 61377266186SHannes Reinecke /* Initialize the Controller Firmware Version field. */ 61477266186SHannes Reinecke sprintf(fw_version, "%d.%02d-%02d", 61577266186SHannes Reinecke info->fw_major_version, info->fw_minor_version, 61677266186SHannes Reinecke info->fw_turn_number); 61777266186SHannes Reinecke if (info->fw_major_version == 6 && 61877266186SHannes Reinecke info->fw_minor_version == 0 && 61977266186SHannes Reinecke info->fw_turn_number < 1) { 62077266186SHannes Reinecke shost_printk(KERN_WARNING, shost, 62177266186SHannes Reinecke "FIRMWARE VERSION %s DOES NOT PROVIDE THE CONTROLLER\n" 62277266186SHannes Reinecke "STATUS MONITORING FUNCTIONALITY NEEDED BY THIS DRIVER.\n" 62377266186SHannes Reinecke "PLEASE UPGRADE TO VERSION 6.00-01 OR ABOVE.\n", 62477266186SHannes Reinecke fw_version); 62577266186SHannes Reinecke return -ENODEV; 62677266186SHannes Reinecke } 62777266186SHannes Reinecke /* Initialize the Controller Channels and Targets. */ 62877266186SHannes Reinecke shost->max_channel = info->physchan_present + info->virtchan_present; 62977266186SHannes Reinecke shost->max_id = info->max_targets[0]; 63077266186SHannes Reinecke for (i = 1; i < 16; i++) { 63177266186SHannes Reinecke if (!info->max_targets[i]) 63277266186SHannes Reinecke continue; 63377266186SHannes Reinecke if (shost->max_id < info->max_targets[i]) 63477266186SHannes Reinecke shost->max_id = info->max_targets[i]; 63577266186SHannes Reinecke } 63677266186SHannes Reinecke 63777266186SHannes Reinecke /* 63877266186SHannes Reinecke * Initialize the Controller Queue Depth, Driver Queue Depth, 63977266186SHannes Reinecke * Logical Drive Count, Maximum Blocks per Command, Controller 64077266186SHannes Reinecke * Scatter/Gather Limit, and Driver Scatter/Gather Limit. 64177266186SHannes Reinecke * The Driver Queue Depth must be at most three less than 64277266186SHannes Reinecke * the Controller Queue Depth; tag '1' is reserved for 64377266186SHannes Reinecke * direct commands, and tag '2' for monitoring commands. 64477266186SHannes Reinecke */ 64577266186SHannes Reinecke shost->can_queue = info->max_tcq - 3; 64677266186SHannes Reinecke if (shost->can_queue > MYRS_MAX_CMD_MBOX - 3) 64777266186SHannes Reinecke shost->can_queue = MYRS_MAX_CMD_MBOX - 3; 64877266186SHannes Reinecke shost->max_sectors = info->max_transfer_size; 64977266186SHannes Reinecke shost->sg_tablesize = info->max_sge; 65077266186SHannes Reinecke if (shost->sg_tablesize > MYRS_SG_LIMIT) 65177266186SHannes Reinecke shost->sg_tablesize = MYRS_SG_LIMIT; 65277266186SHannes Reinecke 65377266186SHannes Reinecke shost_printk(KERN_INFO, shost, 65477266186SHannes Reinecke "Configuring %s PCI RAID Controller\n", model); 65577266186SHannes Reinecke shost_printk(KERN_INFO, shost, 65677266186SHannes Reinecke " Firmware Version: %s, Channels: %d, Memory Size: %dMB\n", 65777266186SHannes Reinecke fw_version, info->physchan_present, info->mem_size_mb); 65877266186SHannes Reinecke 65977266186SHannes Reinecke shost_printk(KERN_INFO, shost, 66077266186SHannes Reinecke " Controller Queue Depth: %d, Maximum Blocks per Command: %d\n", 66177266186SHannes Reinecke shost->can_queue, shost->max_sectors); 66277266186SHannes Reinecke 66377266186SHannes Reinecke shost_printk(KERN_INFO, shost, 66477266186SHannes Reinecke " Driver Queue Depth: %d, Scatter/Gather Limit: %d of %d Segments\n", 66577266186SHannes Reinecke shost->can_queue, shost->sg_tablesize, MYRS_SG_LIMIT); 66677266186SHannes Reinecke for (i = 0; i < info->physchan_max; i++) { 66777266186SHannes Reinecke if (!info->max_targets[i]) 66877266186SHannes Reinecke continue; 66977266186SHannes Reinecke shost_printk(KERN_INFO, shost, 67077266186SHannes Reinecke " Device Channel %d: max %d devices\n", 67177266186SHannes Reinecke i, info->max_targets[i]); 67277266186SHannes Reinecke } 67377266186SHannes Reinecke shost_printk(KERN_INFO, shost, 67477266186SHannes Reinecke " Physical: %d/%d channels, %d disks, %d devices\n", 67577266186SHannes Reinecke info->physchan_present, info->physchan_max, 67677266186SHannes Reinecke info->pdisk_present, info->pdev_present); 67777266186SHannes Reinecke 67877266186SHannes Reinecke shost_printk(KERN_INFO, shost, 67977266186SHannes Reinecke " Logical: %d/%d channels, %d disks\n", 68077266186SHannes Reinecke info->virtchan_present, info->virtchan_max, 68177266186SHannes Reinecke info->ldev_present); 68277266186SHannes Reinecke return 0; 68377266186SHannes Reinecke } 68477266186SHannes Reinecke 6858a692fdbSLee Jones /* 68677266186SHannes Reinecke * myrs_log_event - prints a Controller Event message 68777266186SHannes Reinecke */ 68877266186SHannes Reinecke static struct { 68977266186SHannes Reinecke int ev_code; 69077266186SHannes Reinecke unsigned char *ev_msg; 69177266186SHannes Reinecke } myrs_ev_list[] = { 69277266186SHannes Reinecke /* Physical Device Events (0x0000 - 0x007F) */ 69377266186SHannes Reinecke { 0x0001, "P Online" }, 69477266186SHannes Reinecke { 0x0002, "P Standby" }, 69577266186SHannes Reinecke { 0x0005, "P Automatic Rebuild Started" }, 69677266186SHannes Reinecke { 0x0006, "P Manual Rebuild Started" }, 69777266186SHannes Reinecke { 0x0007, "P Rebuild Completed" }, 69877266186SHannes Reinecke { 0x0008, "P Rebuild Cancelled" }, 69977266186SHannes Reinecke { 0x0009, "P Rebuild Failed for Unknown Reasons" }, 70077266186SHannes Reinecke { 0x000A, "P Rebuild Failed due to New Physical Device" }, 70177266186SHannes Reinecke { 0x000B, "P Rebuild Failed due to Logical Drive Failure" }, 70277266186SHannes Reinecke { 0x000C, "S Offline" }, 70377266186SHannes Reinecke { 0x000D, "P Found" }, 70477266186SHannes Reinecke { 0x000E, "P Removed" }, 70577266186SHannes Reinecke { 0x000F, "P Unconfigured" }, 70677266186SHannes Reinecke { 0x0010, "P Expand Capacity Started" }, 70777266186SHannes Reinecke { 0x0011, "P Expand Capacity Completed" }, 70877266186SHannes Reinecke { 0x0012, "P Expand Capacity Failed" }, 70977266186SHannes Reinecke { 0x0013, "P Command Timed Out" }, 71077266186SHannes Reinecke { 0x0014, "P Command Aborted" }, 71177266186SHannes Reinecke { 0x0015, "P Command Retried" }, 71277266186SHannes Reinecke { 0x0016, "P Parity Error" }, 71377266186SHannes Reinecke { 0x0017, "P Soft Error" }, 71477266186SHannes Reinecke { 0x0018, "P Miscellaneous Error" }, 71577266186SHannes Reinecke { 0x0019, "P Reset" }, 71677266186SHannes Reinecke { 0x001A, "P Active Spare Found" }, 71777266186SHannes Reinecke { 0x001B, "P Warm Spare Found" }, 71877266186SHannes Reinecke { 0x001C, "S Sense Data Received" }, 71977266186SHannes Reinecke { 0x001D, "P Initialization Started" }, 72077266186SHannes Reinecke { 0x001E, "P Initialization Completed" }, 72177266186SHannes Reinecke { 0x001F, "P Initialization Failed" }, 72277266186SHannes Reinecke { 0x0020, "P Initialization Cancelled" }, 72377266186SHannes Reinecke { 0x0021, "P Failed because Write Recovery Failed" }, 72477266186SHannes Reinecke { 0x0022, "P Failed because SCSI Bus Reset Failed" }, 72577266186SHannes Reinecke { 0x0023, "P Failed because of Double Check Condition" }, 72677266186SHannes Reinecke { 0x0024, "P Failed because Device Cannot Be Accessed" }, 72777266186SHannes Reinecke { 0x0025, "P Failed because of Gross Error on SCSI Processor" }, 72877266186SHannes Reinecke { 0x0026, "P Failed because of Bad Tag from Device" }, 72977266186SHannes Reinecke { 0x0027, "P Failed because of Command Timeout" }, 73077266186SHannes Reinecke { 0x0028, "P Failed because of System Reset" }, 73177266186SHannes Reinecke { 0x0029, "P Failed because of Busy Status or Parity Error" }, 73277266186SHannes Reinecke { 0x002A, "P Failed because Host Set Device to Failed State" }, 73377266186SHannes Reinecke { 0x002B, "P Failed because of Selection Timeout" }, 73477266186SHannes Reinecke { 0x002C, "P Failed because of SCSI Bus Phase Error" }, 73577266186SHannes Reinecke { 0x002D, "P Failed because Device Returned Unknown Status" }, 73677266186SHannes Reinecke { 0x002E, "P Failed because Device Not Ready" }, 73777266186SHannes Reinecke { 0x002F, "P Failed because Device Not Found at Startup" }, 73877266186SHannes Reinecke { 0x0030, "P Failed because COD Write Operation Failed" }, 73977266186SHannes Reinecke { 0x0031, "P Failed because BDT Write Operation Failed" }, 74077266186SHannes Reinecke { 0x0039, "P Missing at Startup" }, 74177266186SHannes Reinecke { 0x003A, "P Start Rebuild Failed due to Physical Drive Too Small" }, 74277266186SHannes Reinecke { 0x003C, "P Temporarily Offline Device Automatically Made Online" }, 74377266186SHannes Reinecke { 0x003D, "P Standby Rebuild Started" }, 74477266186SHannes Reinecke /* Logical Device Events (0x0080 - 0x00FF) */ 74577266186SHannes Reinecke { 0x0080, "M Consistency Check Started" }, 74677266186SHannes Reinecke { 0x0081, "M Consistency Check Completed" }, 74777266186SHannes Reinecke { 0x0082, "M Consistency Check Cancelled" }, 74877266186SHannes Reinecke { 0x0083, "M Consistency Check Completed With Errors" }, 74977266186SHannes Reinecke { 0x0084, "M Consistency Check Failed due to Logical Drive Failure" }, 75077266186SHannes Reinecke { 0x0085, "M Consistency Check Failed due to Physical Device Failure" }, 75177266186SHannes Reinecke { 0x0086, "L Offline" }, 75277266186SHannes Reinecke { 0x0087, "L Critical" }, 75377266186SHannes Reinecke { 0x0088, "L Online" }, 75477266186SHannes Reinecke { 0x0089, "M Automatic Rebuild Started" }, 75577266186SHannes Reinecke { 0x008A, "M Manual Rebuild Started" }, 75677266186SHannes Reinecke { 0x008B, "M Rebuild Completed" }, 75777266186SHannes Reinecke { 0x008C, "M Rebuild Cancelled" }, 75877266186SHannes Reinecke { 0x008D, "M Rebuild Failed for Unknown Reasons" }, 75977266186SHannes Reinecke { 0x008E, "M Rebuild Failed due to New Physical Device" }, 76077266186SHannes Reinecke { 0x008F, "M Rebuild Failed due to Logical Drive Failure" }, 76177266186SHannes Reinecke { 0x0090, "M Initialization Started" }, 76277266186SHannes Reinecke { 0x0091, "M Initialization Completed" }, 76377266186SHannes Reinecke { 0x0092, "M Initialization Cancelled" }, 76477266186SHannes Reinecke { 0x0093, "M Initialization Failed" }, 76577266186SHannes Reinecke { 0x0094, "L Found" }, 76677266186SHannes Reinecke { 0x0095, "L Deleted" }, 76777266186SHannes Reinecke { 0x0096, "M Expand Capacity Started" }, 76877266186SHannes Reinecke { 0x0097, "M Expand Capacity Completed" }, 76977266186SHannes Reinecke { 0x0098, "M Expand Capacity Failed" }, 77077266186SHannes Reinecke { 0x0099, "L Bad Block Found" }, 77177266186SHannes Reinecke { 0x009A, "L Size Changed" }, 77277266186SHannes Reinecke { 0x009B, "L Type Changed" }, 77377266186SHannes Reinecke { 0x009C, "L Bad Data Block Found" }, 77477266186SHannes Reinecke { 0x009E, "L Read of Data Block in BDT" }, 77577266186SHannes Reinecke { 0x009F, "L Write Back Data for Disk Block Lost" }, 77677266186SHannes Reinecke { 0x00A0, "L Temporarily Offline RAID-5/3 Drive Made Online" }, 77777266186SHannes Reinecke { 0x00A1, "L Temporarily Offline RAID-6/1/0/7 Drive Made Online" }, 77877266186SHannes Reinecke { 0x00A2, "L Standby Rebuild Started" }, 77977266186SHannes Reinecke /* Fault Management Events (0x0100 - 0x017F) */ 78077266186SHannes Reinecke { 0x0140, "E Fan %d Failed" }, 78177266186SHannes Reinecke { 0x0141, "E Fan %d OK" }, 78277266186SHannes Reinecke { 0x0142, "E Fan %d Not Present" }, 78377266186SHannes Reinecke { 0x0143, "E Power Supply %d Failed" }, 78477266186SHannes Reinecke { 0x0144, "E Power Supply %d OK" }, 78577266186SHannes Reinecke { 0x0145, "E Power Supply %d Not Present" }, 78677266186SHannes Reinecke { 0x0146, "E Temperature Sensor %d Temperature Exceeds Safe Limit" }, 78777266186SHannes Reinecke { 0x0147, "E Temperature Sensor %d Temperature Exceeds Working Limit" }, 78877266186SHannes Reinecke { 0x0148, "E Temperature Sensor %d Temperature Normal" }, 78977266186SHannes Reinecke { 0x0149, "E Temperature Sensor %d Not Present" }, 79077266186SHannes Reinecke { 0x014A, "E Enclosure Management Unit %d Access Critical" }, 79177266186SHannes Reinecke { 0x014B, "E Enclosure Management Unit %d Access OK" }, 79277266186SHannes Reinecke { 0x014C, "E Enclosure Management Unit %d Access Offline" }, 79377266186SHannes Reinecke /* Controller Events (0x0180 - 0x01FF) */ 79477266186SHannes Reinecke { 0x0181, "C Cache Write Back Error" }, 79577266186SHannes Reinecke { 0x0188, "C Battery Backup Unit Found" }, 79677266186SHannes Reinecke { 0x0189, "C Battery Backup Unit Charge Level Low" }, 79777266186SHannes Reinecke { 0x018A, "C Battery Backup Unit Charge Level OK" }, 79877266186SHannes Reinecke { 0x0193, "C Installation Aborted" }, 79977266186SHannes Reinecke { 0x0195, "C Battery Backup Unit Physically Removed" }, 80077266186SHannes Reinecke { 0x0196, "C Memory Error During Warm Boot" }, 80177266186SHannes Reinecke { 0x019E, "C Memory Soft ECC Error Corrected" }, 80277266186SHannes Reinecke { 0x019F, "C Memory Hard ECC Error Corrected" }, 80377266186SHannes Reinecke { 0x01A2, "C Battery Backup Unit Failed" }, 80477266186SHannes Reinecke { 0x01AB, "C Mirror Race Recovery Failed" }, 80577266186SHannes Reinecke { 0x01AC, "C Mirror Race on Critical Drive" }, 80677266186SHannes Reinecke /* Controller Internal Processor Events */ 80777266186SHannes Reinecke { 0x0380, "C Internal Controller Hung" }, 80877266186SHannes Reinecke { 0x0381, "C Internal Controller Firmware Breakpoint" }, 80977266186SHannes Reinecke { 0x0390, "C Internal Controller i960 Processor Specific Error" }, 81077266186SHannes Reinecke { 0x03A0, "C Internal Controller StrongARM Processor Specific Error" }, 81177266186SHannes Reinecke { 0, "" } 81277266186SHannes Reinecke }; 81377266186SHannes Reinecke 81477266186SHannes Reinecke static void myrs_log_event(struct myrs_hba *cs, struct myrs_event *ev) 81577266186SHannes Reinecke { 81677266186SHannes Reinecke unsigned char msg_buf[MYRS_LINE_BUFFER_SIZE]; 81777266186SHannes Reinecke int ev_idx = 0, ev_code; 81877266186SHannes Reinecke unsigned char ev_type, *ev_msg; 81977266186SHannes Reinecke struct Scsi_Host *shost = cs->host; 82077266186SHannes Reinecke struct scsi_device *sdev; 82141552199SYueHaibing struct scsi_sense_hdr sshdr = {0}; 82277266186SHannes Reinecke unsigned char sense_info[4]; 82377266186SHannes Reinecke unsigned char cmd_specific[4]; 82477266186SHannes Reinecke 82577266186SHannes Reinecke if (ev->ev_code == 0x1C) { 82677266186SHannes Reinecke if (!scsi_normalize_sense(ev->sense_data, 40, &sshdr)) { 82777266186SHannes Reinecke memset(&sshdr, 0x0, sizeof(sshdr)); 82877266186SHannes Reinecke memset(sense_info, 0x0, sizeof(sense_info)); 82977266186SHannes Reinecke memset(cmd_specific, 0x0, sizeof(cmd_specific)); 83077266186SHannes Reinecke } else { 83177266186SHannes Reinecke memcpy(sense_info, &ev->sense_data[3], 4); 83277266186SHannes Reinecke memcpy(cmd_specific, &ev->sense_data[7], 4); 83377266186SHannes Reinecke } 83477266186SHannes Reinecke } 83577266186SHannes Reinecke if (sshdr.sense_key == VENDOR_SPECIFIC && 83677266186SHannes Reinecke (sshdr.asc == 0x80 || sshdr.asc == 0x81)) 83777266186SHannes Reinecke ev->ev_code = ((sshdr.asc - 0x80) << 8 | sshdr.ascq); 83877266186SHannes Reinecke while (true) { 83977266186SHannes Reinecke ev_code = myrs_ev_list[ev_idx].ev_code; 84077266186SHannes Reinecke if (ev_code == ev->ev_code || ev_code == 0) 84177266186SHannes Reinecke break; 84277266186SHannes Reinecke ev_idx++; 84377266186SHannes Reinecke } 84477266186SHannes Reinecke ev_type = myrs_ev_list[ev_idx].ev_msg[0]; 84577266186SHannes Reinecke ev_msg = &myrs_ev_list[ev_idx].ev_msg[2]; 84677266186SHannes Reinecke if (ev_code == 0) { 84777266186SHannes Reinecke shost_printk(KERN_WARNING, shost, 84877266186SHannes Reinecke "Unknown Controller Event Code %04X\n", 84977266186SHannes Reinecke ev->ev_code); 85077266186SHannes Reinecke return; 85177266186SHannes Reinecke } 85277266186SHannes Reinecke switch (ev_type) { 85377266186SHannes Reinecke case 'P': 85477266186SHannes Reinecke sdev = scsi_device_lookup(shost, ev->channel, 85577266186SHannes Reinecke ev->target, 0); 85677266186SHannes Reinecke sdev_printk(KERN_INFO, sdev, "event %d: Physical Device %s\n", 85777266186SHannes Reinecke ev->ev_seq, ev_msg); 85877266186SHannes Reinecke if (sdev && sdev->hostdata && 85977266186SHannes Reinecke sdev->channel < cs->ctlr_info->physchan_present) { 86077266186SHannes Reinecke struct myrs_pdev_info *pdev_info = sdev->hostdata; 86177266186SHannes Reinecke 86277266186SHannes Reinecke switch (ev->ev_code) { 86377266186SHannes Reinecke case 0x0001: 86477266186SHannes Reinecke case 0x0007: 86577266186SHannes Reinecke pdev_info->dev_state = MYRS_DEVICE_ONLINE; 86677266186SHannes Reinecke break; 86777266186SHannes Reinecke case 0x0002: 86877266186SHannes Reinecke pdev_info->dev_state = MYRS_DEVICE_STANDBY; 86977266186SHannes Reinecke break; 87077266186SHannes Reinecke case 0x000C: 87177266186SHannes Reinecke pdev_info->dev_state = MYRS_DEVICE_OFFLINE; 87277266186SHannes Reinecke break; 87377266186SHannes Reinecke case 0x000E: 87477266186SHannes Reinecke pdev_info->dev_state = MYRS_DEVICE_MISSING; 87577266186SHannes Reinecke break; 87677266186SHannes Reinecke case 0x000F: 87777266186SHannes Reinecke pdev_info->dev_state = MYRS_DEVICE_UNCONFIGURED; 87877266186SHannes Reinecke break; 87977266186SHannes Reinecke } 88077266186SHannes Reinecke } 88177266186SHannes Reinecke break; 88277266186SHannes Reinecke case 'L': 88377266186SHannes Reinecke shost_printk(KERN_INFO, shost, 88477266186SHannes Reinecke "event %d: Logical Drive %d %s\n", 88577266186SHannes Reinecke ev->ev_seq, ev->lun, ev_msg); 88677266186SHannes Reinecke cs->needs_update = true; 88777266186SHannes Reinecke break; 88877266186SHannes Reinecke case 'M': 88977266186SHannes Reinecke shost_printk(KERN_INFO, shost, 89077266186SHannes Reinecke "event %d: Logical Drive %d %s\n", 89177266186SHannes Reinecke ev->ev_seq, ev->lun, ev_msg); 89277266186SHannes Reinecke cs->needs_update = true; 89377266186SHannes Reinecke break; 89477266186SHannes Reinecke case 'S': 89577266186SHannes Reinecke if (sshdr.sense_key == NO_SENSE || 89677266186SHannes Reinecke (sshdr.sense_key == NOT_READY && 89777266186SHannes Reinecke sshdr.asc == 0x04 && (sshdr.ascq == 0x01 || 89877266186SHannes Reinecke sshdr.ascq == 0x02))) 89977266186SHannes Reinecke break; 90077266186SHannes Reinecke shost_printk(KERN_INFO, shost, 90177266186SHannes Reinecke "event %d: Physical Device %d:%d %s\n", 90277266186SHannes Reinecke ev->ev_seq, ev->channel, ev->target, ev_msg); 90377266186SHannes Reinecke shost_printk(KERN_INFO, shost, 90477266186SHannes Reinecke "Physical Device %d:%d Sense Key = %X, ASC = %02X, ASCQ = %02X\n", 90577266186SHannes Reinecke ev->channel, ev->target, 90677266186SHannes Reinecke sshdr.sense_key, sshdr.asc, sshdr.ascq); 90777266186SHannes Reinecke shost_printk(KERN_INFO, shost, 90877266186SHannes Reinecke "Physical Device %d:%d Sense Information = %02X%02X%02X%02X %02X%02X%02X%02X\n", 90977266186SHannes Reinecke ev->channel, ev->target, 91077266186SHannes Reinecke sense_info[0], sense_info[1], 91177266186SHannes Reinecke sense_info[2], sense_info[3], 91277266186SHannes Reinecke cmd_specific[0], cmd_specific[1], 91377266186SHannes Reinecke cmd_specific[2], cmd_specific[3]); 91477266186SHannes Reinecke break; 91577266186SHannes Reinecke case 'E': 91677266186SHannes Reinecke if (cs->disable_enc_msg) 91777266186SHannes Reinecke break; 91877266186SHannes Reinecke sprintf(msg_buf, ev_msg, ev->lun); 91977266186SHannes Reinecke shost_printk(KERN_INFO, shost, "event %d: Enclosure %d %s\n", 92077266186SHannes Reinecke ev->ev_seq, ev->target, msg_buf); 92177266186SHannes Reinecke break; 92277266186SHannes Reinecke case 'C': 92377266186SHannes Reinecke shost_printk(KERN_INFO, shost, "event %d: Controller %s\n", 92477266186SHannes Reinecke ev->ev_seq, ev_msg); 92577266186SHannes Reinecke break; 92677266186SHannes Reinecke default: 92777266186SHannes Reinecke shost_printk(KERN_INFO, shost, 92877266186SHannes Reinecke "event %d: Unknown Event Code %04X\n", 92977266186SHannes Reinecke ev->ev_seq, ev->ev_code); 93077266186SHannes Reinecke break; 93177266186SHannes Reinecke } 93277266186SHannes Reinecke } 93377266186SHannes Reinecke 93477266186SHannes Reinecke /* 93577266186SHannes Reinecke * SCSI sysfs interface functions 93677266186SHannes Reinecke */ 93777266186SHannes Reinecke static ssize_t raid_state_show(struct device *dev, 93877266186SHannes Reinecke struct device_attribute *attr, char *buf) 93977266186SHannes Reinecke { 94077266186SHannes Reinecke struct scsi_device *sdev = to_scsi_device(dev); 94177266186SHannes Reinecke struct myrs_hba *cs = shost_priv(sdev->host); 94277266186SHannes Reinecke int ret; 94377266186SHannes Reinecke 94477266186SHannes Reinecke if (!sdev->hostdata) 94577266186SHannes Reinecke return snprintf(buf, 16, "Unknown\n"); 94677266186SHannes Reinecke 94777266186SHannes Reinecke if (sdev->channel >= cs->ctlr_info->physchan_present) { 94877266186SHannes Reinecke struct myrs_ldev_info *ldev_info = sdev->hostdata; 94977266186SHannes Reinecke const char *name; 95077266186SHannes Reinecke 95177266186SHannes Reinecke name = myrs_devstate_name(ldev_info->dev_state); 95277266186SHannes Reinecke if (name) 95377266186SHannes Reinecke ret = snprintf(buf, 32, "%s\n", name); 95477266186SHannes Reinecke else 95577266186SHannes Reinecke ret = snprintf(buf, 32, "Invalid (%02X)\n", 95677266186SHannes Reinecke ldev_info->dev_state); 95777266186SHannes Reinecke } else { 95877266186SHannes Reinecke struct myrs_pdev_info *pdev_info; 95977266186SHannes Reinecke const char *name; 96077266186SHannes Reinecke 96177266186SHannes Reinecke pdev_info = sdev->hostdata; 96277266186SHannes Reinecke name = myrs_devstate_name(pdev_info->dev_state); 96377266186SHannes Reinecke if (name) 96477266186SHannes Reinecke ret = snprintf(buf, 32, "%s\n", name); 96577266186SHannes Reinecke else 96677266186SHannes Reinecke ret = snprintf(buf, 32, "Invalid (%02X)\n", 96777266186SHannes Reinecke pdev_info->dev_state); 96877266186SHannes Reinecke } 96977266186SHannes Reinecke return ret; 97077266186SHannes Reinecke } 97177266186SHannes Reinecke 97277266186SHannes Reinecke static ssize_t raid_state_store(struct device *dev, 97377266186SHannes Reinecke struct device_attribute *attr, const char *buf, size_t count) 97477266186SHannes Reinecke { 97577266186SHannes Reinecke struct scsi_device *sdev = to_scsi_device(dev); 97677266186SHannes Reinecke struct myrs_hba *cs = shost_priv(sdev->host); 97777266186SHannes Reinecke struct myrs_cmdblk *cmd_blk; 97877266186SHannes Reinecke union myrs_cmd_mbox *mbox; 97977266186SHannes Reinecke enum myrs_devstate new_state; 98077266186SHannes Reinecke unsigned short ldev_num; 98177266186SHannes Reinecke unsigned char status; 98277266186SHannes Reinecke 98377266186SHannes Reinecke if (!strncmp(buf, "offline", 7) || 98477266186SHannes Reinecke !strncmp(buf, "kill", 4)) 98577266186SHannes Reinecke new_state = MYRS_DEVICE_OFFLINE; 98677266186SHannes Reinecke else if (!strncmp(buf, "online", 6)) 98777266186SHannes Reinecke new_state = MYRS_DEVICE_ONLINE; 98877266186SHannes Reinecke else if (!strncmp(buf, "standby", 7)) 98977266186SHannes Reinecke new_state = MYRS_DEVICE_STANDBY; 99077266186SHannes Reinecke else 99177266186SHannes Reinecke return -EINVAL; 99277266186SHannes Reinecke 99377266186SHannes Reinecke if (sdev->channel < cs->ctlr_info->physchan_present) { 99477266186SHannes Reinecke struct myrs_pdev_info *pdev_info = sdev->hostdata; 99577266186SHannes Reinecke struct myrs_devmap *pdev_devmap = 99677266186SHannes Reinecke (struct myrs_devmap *)&pdev_info->rsvd13; 99777266186SHannes Reinecke 99877266186SHannes Reinecke if (pdev_info->dev_state == new_state) { 99977266186SHannes Reinecke sdev_printk(KERN_INFO, sdev, 100077266186SHannes Reinecke "Device already in %s\n", 100177266186SHannes Reinecke myrs_devstate_name(new_state)); 100277266186SHannes Reinecke return count; 100377266186SHannes Reinecke } 100477266186SHannes Reinecke status = myrs_translate_pdev(cs, sdev->channel, sdev->id, 100577266186SHannes Reinecke sdev->lun, pdev_devmap); 100677266186SHannes Reinecke if (status != MYRS_STATUS_SUCCESS) 100777266186SHannes Reinecke return -ENXIO; 100877266186SHannes Reinecke ldev_num = pdev_devmap->ldev_num; 100977266186SHannes Reinecke } else { 101077266186SHannes Reinecke struct myrs_ldev_info *ldev_info = sdev->hostdata; 101177266186SHannes Reinecke 101277266186SHannes Reinecke if (ldev_info->dev_state == new_state) { 101377266186SHannes Reinecke sdev_printk(KERN_INFO, sdev, 101477266186SHannes Reinecke "Device already in %s\n", 101577266186SHannes Reinecke myrs_devstate_name(new_state)); 101677266186SHannes Reinecke return count; 101777266186SHannes Reinecke } 101877266186SHannes Reinecke ldev_num = ldev_info->ldev_num; 101977266186SHannes Reinecke } 102077266186SHannes Reinecke mutex_lock(&cs->dcmd_mutex); 102177266186SHannes Reinecke cmd_blk = &cs->dcmd_blk; 102277266186SHannes Reinecke myrs_reset_cmd(cmd_blk); 102377266186SHannes Reinecke mbox = &cmd_blk->mbox; 102477266186SHannes Reinecke mbox->common.opcode = MYRS_CMD_OP_IOCTL; 102577266186SHannes Reinecke mbox->common.id = MYRS_DCMD_TAG; 102677266186SHannes Reinecke mbox->common.control.dma_ctrl_to_host = true; 102777266186SHannes Reinecke mbox->common.control.no_autosense = true; 102877266186SHannes Reinecke mbox->set_devstate.ioctl_opcode = MYRS_IOCTL_SET_DEVICE_STATE; 102977266186SHannes Reinecke mbox->set_devstate.state = new_state; 103077266186SHannes Reinecke mbox->set_devstate.ldev.ldev_num = ldev_num; 103177266186SHannes Reinecke myrs_exec_cmd(cs, cmd_blk); 103277266186SHannes Reinecke status = cmd_blk->status; 103377266186SHannes Reinecke mutex_unlock(&cs->dcmd_mutex); 103477266186SHannes Reinecke if (status == MYRS_STATUS_SUCCESS) { 103577266186SHannes Reinecke if (sdev->channel < cs->ctlr_info->physchan_present) { 103677266186SHannes Reinecke struct myrs_pdev_info *pdev_info = sdev->hostdata; 103777266186SHannes Reinecke 103877266186SHannes Reinecke pdev_info->dev_state = new_state; 103977266186SHannes Reinecke } else { 104077266186SHannes Reinecke struct myrs_ldev_info *ldev_info = sdev->hostdata; 104177266186SHannes Reinecke 104277266186SHannes Reinecke ldev_info->dev_state = new_state; 104377266186SHannes Reinecke } 104477266186SHannes Reinecke sdev_printk(KERN_INFO, sdev, 104577266186SHannes Reinecke "Set device state to %s\n", 104677266186SHannes Reinecke myrs_devstate_name(new_state)); 104777266186SHannes Reinecke return count; 104877266186SHannes Reinecke } 104977266186SHannes Reinecke sdev_printk(KERN_INFO, sdev, 105077266186SHannes Reinecke "Failed to set device state to %s, status 0x%02x\n", 105177266186SHannes Reinecke myrs_devstate_name(new_state), status); 105277266186SHannes Reinecke return -EINVAL; 105377266186SHannes Reinecke } 105477266186SHannes Reinecke static DEVICE_ATTR_RW(raid_state); 105577266186SHannes Reinecke 105677266186SHannes Reinecke static ssize_t raid_level_show(struct device *dev, 105777266186SHannes Reinecke struct device_attribute *attr, char *buf) 105877266186SHannes Reinecke { 105977266186SHannes Reinecke struct scsi_device *sdev = to_scsi_device(dev); 106077266186SHannes Reinecke struct myrs_hba *cs = shost_priv(sdev->host); 106177266186SHannes Reinecke const char *name = NULL; 106277266186SHannes Reinecke 106377266186SHannes Reinecke if (!sdev->hostdata) 106477266186SHannes Reinecke return snprintf(buf, 16, "Unknown\n"); 106577266186SHannes Reinecke 106677266186SHannes Reinecke if (sdev->channel >= cs->ctlr_info->physchan_present) { 106777266186SHannes Reinecke struct myrs_ldev_info *ldev_info; 106877266186SHannes Reinecke 106977266186SHannes Reinecke ldev_info = sdev->hostdata; 107077266186SHannes Reinecke name = myrs_raid_level_name(ldev_info->raid_level); 107177266186SHannes Reinecke if (!name) 107277266186SHannes Reinecke return snprintf(buf, 32, "Invalid (%02X)\n", 107377266186SHannes Reinecke ldev_info->dev_state); 107477266186SHannes Reinecke 107577266186SHannes Reinecke } else 107677266186SHannes Reinecke name = myrs_raid_level_name(MYRS_RAID_PHYSICAL); 107777266186SHannes Reinecke 107877266186SHannes Reinecke return snprintf(buf, 32, "%s\n", name); 107977266186SHannes Reinecke } 108077266186SHannes Reinecke static DEVICE_ATTR_RO(raid_level); 108177266186SHannes Reinecke 108277266186SHannes Reinecke static ssize_t rebuild_show(struct device *dev, 108377266186SHannes Reinecke struct device_attribute *attr, char *buf) 108477266186SHannes Reinecke { 108577266186SHannes Reinecke struct scsi_device *sdev = to_scsi_device(dev); 108677266186SHannes Reinecke struct myrs_hba *cs = shost_priv(sdev->host); 108777266186SHannes Reinecke struct myrs_ldev_info *ldev_info; 108877266186SHannes Reinecke unsigned short ldev_num; 108977266186SHannes Reinecke unsigned char status; 109077266186SHannes Reinecke 109177266186SHannes Reinecke if (sdev->channel < cs->ctlr_info->physchan_present) 109277266186SHannes Reinecke return snprintf(buf, 32, "physical device - not rebuilding\n"); 109377266186SHannes Reinecke 109477266186SHannes Reinecke ldev_info = sdev->hostdata; 109577266186SHannes Reinecke ldev_num = ldev_info->ldev_num; 109677266186SHannes Reinecke status = myrs_get_ldev_info(cs, ldev_num, ldev_info); 109777266186SHannes Reinecke if (status != MYRS_STATUS_SUCCESS) { 109877266186SHannes Reinecke sdev_printk(KERN_INFO, sdev, 109977266186SHannes Reinecke "Failed to get device information, status 0x%02x\n", 110077266186SHannes Reinecke status); 110177266186SHannes Reinecke return -EIO; 110277266186SHannes Reinecke } 110377266186SHannes Reinecke if (ldev_info->rbld_active) { 110477266186SHannes Reinecke return snprintf(buf, 32, "rebuilding block %zu of %zu\n", 110577266186SHannes Reinecke (size_t)ldev_info->rbld_lba, 110677266186SHannes Reinecke (size_t)ldev_info->cfg_devsize); 110777266186SHannes Reinecke } else 110877266186SHannes Reinecke return snprintf(buf, 32, "not rebuilding\n"); 110977266186SHannes Reinecke } 111077266186SHannes Reinecke 111177266186SHannes Reinecke static ssize_t rebuild_store(struct device *dev, 111277266186SHannes Reinecke struct device_attribute *attr, const char *buf, size_t count) 111377266186SHannes Reinecke { 111477266186SHannes Reinecke struct scsi_device *sdev = to_scsi_device(dev); 111577266186SHannes Reinecke struct myrs_hba *cs = shost_priv(sdev->host); 111677266186SHannes Reinecke struct myrs_ldev_info *ldev_info; 111777266186SHannes Reinecke struct myrs_cmdblk *cmd_blk; 111877266186SHannes Reinecke union myrs_cmd_mbox *mbox; 111977266186SHannes Reinecke unsigned short ldev_num; 112077266186SHannes Reinecke unsigned char status; 112177266186SHannes Reinecke int rebuild, ret; 112277266186SHannes Reinecke 112377266186SHannes Reinecke if (sdev->channel < cs->ctlr_info->physchan_present) 112477266186SHannes Reinecke return -EINVAL; 112577266186SHannes Reinecke 112677266186SHannes Reinecke ldev_info = sdev->hostdata; 112777266186SHannes Reinecke if (!ldev_info) 112877266186SHannes Reinecke return -ENXIO; 112977266186SHannes Reinecke ldev_num = ldev_info->ldev_num; 113077266186SHannes Reinecke 113177266186SHannes Reinecke ret = kstrtoint(buf, 0, &rebuild); 113277266186SHannes Reinecke if (ret) 113377266186SHannes Reinecke return ret; 113477266186SHannes Reinecke 113577266186SHannes Reinecke status = myrs_get_ldev_info(cs, ldev_num, ldev_info); 113677266186SHannes Reinecke if (status != MYRS_STATUS_SUCCESS) { 113777266186SHannes Reinecke sdev_printk(KERN_INFO, sdev, 113877266186SHannes Reinecke "Failed to get device information, status 0x%02x\n", 113977266186SHannes Reinecke status); 114077266186SHannes Reinecke return -EIO; 114177266186SHannes Reinecke } 114277266186SHannes Reinecke 114377266186SHannes Reinecke if (rebuild && ldev_info->rbld_active) { 114477266186SHannes Reinecke sdev_printk(KERN_INFO, sdev, 114577266186SHannes Reinecke "Rebuild Not Initiated; already in progress\n"); 114677266186SHannes Reinecke return -EALREADY; 114777266186SHannes Reinecke } 114877266186SHannes Reinecke if (!rebuild && !ldev_info->rbld_active) { 114977266186SHannes Reinecke sdev_printk(KERN_INFO, sdev, 115077266186SHannes Reinecke "Rebuild Not Cancelled; no rebuild in progress\n"); 115177266186SHannes Reinecke return count; 115277266186SHannes Reinecke } 115377266186SHannes Reinecke 115477266186SHannes Reinecke mutex_lock(&cs->dcmd_mutex); 115577266186SHannes Reinecke cmd_blk = &cs->dcmd_blk; 115677266186SHannes Reinecke myrs_reset_cmd(cmd_blk); 115777266186SHannes Reinecke mbox = &cmd_blk->mbox; 115877266186SHannes Reinecke mbox->common.opcode = MYRS_CMD_OP_IOCTL; 115977266186SHannes Reinecke mbox->common.id = MYRS_DCMD_TAG; 116077266186SHannes Reinecke mbox->common.control.dma_ctrl_to_host = true; 116177266186SHannes Reinecke mbox->common.control.no_autosense = true; 116277266186SHannes Reinecke if (rebuild) { 116377266186SHannes Reinecke mbox->ldev_info.ldev.ldev_num = ldev_num; 116477266186SHannes Reinecke mbox->ldev_info.ioctl_opcode = MYRS_IOCTL_RBLD_DEVICE_START; 116577266186SHannes Reinecke } else { 116677266186SHannes Reinecke mbox->ldev_info.ldev.ldev_num = ldev_num; 116777266186SHannes Reinecke mbox->ldev_info.ioctl_opcode = MYRS_IOCTL_RBLD_DEVICE_STOP; 116877266186SHannes Reinecke } 116977266186SHannes Reinecke myrs_exec_cmd(cs, cmd_blk); 117077266186SHannes Reinecke status = cmd_blk->status; 117177266186SHannes Reinecke mutex_unlock(&cs->dcmd_mutex); 117277266186SHannes Reinecke if (status) { 117377266186SHannes Reinecke sdev_printk(KERN_INFO, sdev, 117477266186SHannes Reinecke "Rebuild Not %s, status 0x%02x\n", 117577266186SHannes Reinecke rebuild ? "Initiated" : "Cancelled", status); 117677266186SHannes Reinecke ret = -EIO; 117777266186SHannes Reinecke } else { 117877266186SHannes Reinecke sdev_printk(KERN_INFO, sdev, "Rebuild %s\n", 117977266186SHannes Reinecke rebuild ? "Initiated" : "Cancelled"); 118077266186SHannes Reinecke ret = count; 118177266186SHannes Reinecke } 118277266186SHannes Reinecke 118377266186SHannes Reinecke return ret; 118477266186SHannes Reinecke } 118577266186SHannes Reinecke static DEVICE_ATTR_RW(rebuild); 118677266186SHannes Reinecke 118777266186SHannes Reinecke static ssize_t consistency_check_show(struct device *dev, 118877266186SHannes Reinecke struct device_attribute *attr, char *buf) 118977266186SHannes Reinecke { 119077266186SHannes Reinecke struct scsi_device *sdev = to_scsi_device(dev); 119177266186SHannes Reinecke struct myrs_hba *cs = shost_priv(sdev->host); 119277266186SHannes Reinecke struct myrs_ldev_info *ldev_info; 119377266186SHannes Reinecke unsigned short ldev_num; 119477266186SHannes Reinecke unsigned char status; 119577266186SHannes Reinecke 119677266186SHannes Reinecke if (sdev->channel < cs->ctlr_info->physchan_present) 119777266186SHannes Reinecke return snprintf(buf, 32, "physical device - not checking\n"); 119877266186SHannes Reinecke 119977266186SHannes Reinecke ldev_info = sdev->hostdata; 120077266186SHannes Reinecke if (!ldev_info) 120177266186SHannes Reinecke return -ENXIO; 120277266186SHannes Reinecke ldev_num = ldev_info->ldev_num; 120377266186SHannes Reinecke status = myrs_get_ldev_info(cs, ldev_num, ldev_info); 120477266186SHannes Reinecke if (ldev_info->cc_active) 120577266186SHannes Reinecke return snprintf(buf, 32, "checking block %zu of %zu\n", 120677266186SHannes Reinecke (size_t)ldev_info->cc_lba, 120777266186SHannes Reinecke (size_t)ldev_info->cfg_devsize); 120877266186SHannes Reinecke else 120977266186SHannes Reinecke return snprintf(buf, 32, "not checking\n"); 121077266186SHannes Reinecke } 121177266186SHannes Reinecke 121277266186SHannes Reinecke static ssize_t consistency_check_store(struct device *dev, 121377266186SHannes Reinecke struct device_attribute *attr, const char *buf, size_t count) 121477266186SHannes Reinecke { 121577266186SHannes Reinecke struct scsi_device *sdev = to_scsi_device(dev); 121677266186SHannes Reinecke struct myrs_hba *cs = shost_priv(sdev->host); 121777266186SHannes Reinecke struct myrs_ldev_info *ldev_info; 121877266186SHannes Reinecke struct myrs_cmdblk *cmd_blk; 121977266186SHannes Reinecke union myrs_cmd_mbox *mbox; 122077266186SHannes Reinecke unsigned short ldev_num; 122177266186SHannes Reinecke unsigned char status; 122277266186SHannes Reinecke int check, ret; 122377266186SHannes Reinecke 122477266186SHannes Reinecke if (sdev->channel < cs->ctlr_info->physchan_present) 122577266186SHannes Reinecke return -EINVAL; 122677266186SHannes Reinecke 122777266186SHannes Reinecke ldev_info = sdev->hostdata; 122877266186SHannes Reinecke if (!ldev_info) 122977266186SHannes Reinecke return -ENXIO; 123077266186SHannes Reinecke ldev_num = ldev_info->ldev_num; 123177266186SHannes Reinecke 123277266186SHannes Reinecke ret = kstrtoint(buf, 0, &check); 123377266186SHannes Reinecke if (ret) 123477266186SHannes Reinecke return ret; 123577266186SHannes Reinecke 123677266186SHannes Reinecke status = myrs_get_ldev_info(cs, ldev_num, ldev_info); 123777266186SHannes Reinecke if (status != MYRS_STATUS_SUCCESS) { 123877266186SHannes Reinecke sdev_printk(KERN_INFO, sdev, 123977266186SHannes Reinecke "Failed to get device information, status 0x%02x\n", 124077266186SHannes Reinecke status); 124177266186SHannes Reinecke return -EIO; 124277266186SHannes Reinecke } 124377266186SHannes Reinecke if (check && ldev_info->cc_active) { 124477266186SHannes Reinecke sdev_printk(KERN_INFO, sdev, 124577266186SHannes Reinecke "Consistency Check Not Initiated; " 124677266186SHannes Reinecke "already in progress\n"); 124777266186SHannes Reinecke return -EALREADY; 124877266186SHannes Reinecke } 124977266186SHannes Reinecke if (!check && !ldev_info->cc_active) { 125077266186SHannes Reinecke sdev_printk(KERN_INFO, sdev, 125177266186SHannes Reinecke "Consistency Check Not Cancelled; " 125277266186SHannes Reinecke "check not in progress\n"); 125377266186SHannes Reinecke return count; 125477266186SHannes Reinecke } 125577266186SHannes Reinecke 125677266186SHannes Reinecke mutex_lock(&cs->dcmd_mutex); 125777266186SHannes Reinecke cmd_blk = &cs->dcmd_blk; 125877266186SHannes Reinecke myrs_reset_cmd(cmd_blk); 125977266186SHannes Reinecke mbox = &cmd_blk->mbox; 126077266186SHannes Reinecke mbox->common.opcode = MYRS_CMD_OP_IOCTL; 126177266186SHannes Reinecke mbox->common.id = MYRS_DCMD_TAG; 126277266186SHannes Reinecke mbox->common.control.dma_ctrl_to_host = true; 126377266186SHannes Reinecke mbox->common.control.no_autosense = true; 126477266186SHannes Reinecke if (check) { 126577266186SHannes Reinecke mbox->cc.ldev.ldev_num = ldev_num; 126677266186SHannes Reinecke mbox->cc.ioctl_opcode = MYRS_IOCTL_CC_START; 126777266186SHannes Reinecke mbox->cc.restore_consistency = true; 126877266186SHannes Reinecke mbox->cc.initialized_area_only = false; 126977266186SHannes Reinecke } else { 127077266186SHannes Reinecke mbox->cc.ldev.ldev_num = ldev_num; 127177266186SHannes Reinecke mbox->cc.ioctl_opcode = MYRS_IOCTL_CC_STOP; 127277266186SHannes Reinecke } 127377266186SHannes Reinecke myrs_exec_cmd(cs, cmd_blk); 127477266186SHannes Reinecke status = cmd_blk->status; 127577266186SHannes Reinecke mutex_unlock(&cs->dcmd_mutex); 127677266186SHannes Reinecke if (status != MYRS_STATUS_SUCCESS) { 127777266186SHannes Reinecke sdev_printk(KERN_INFO, sdev, 127877266186SHannes Reinecke "Consistency Check Not %s, status 0x%02x\n", 127977266186SHannes Reinecke check ? "Initiated" : "Cancelled", status); 128077266186SHannes Reinecke ret = -EIO; 128177266186SHannes Reinecke } else { 128277266186SHannes Reinecke sdev_printk(KERN_INFO, sdev, "Consistency Check %s\n", 128377266186SHannes Reinecke check ? "Initiated" : "Cancelled"); 128477266186SHannes Reinecke ret = count; 128577266186SHannes Reinecke } 128677266186SHannes Reinecke 128777266186SHannes Reinecke return ret; 128877266186SHannes Reinecke } 128977266186SHannes Reinecke static DEVICE_ATTR_RW(consistency_check); 129077266186SHannes Reinecke 129177266186SHannes Reinecke static struct device_attribute *myrs_sdev_attrs[] = { 129277266186SHannes Reinecke &dev_attr_consistency_check, 129377266186SHannes Reinecke &dev_attr_rebuild, 129477266186SHannes Reinecke &dev_attr_raid_state, 129577266186SHannes Reinecke &dev_attr_raid_level, 129677266186SHannes Reinecke NULL, 129777266186SHannes Reinecke }; 129877266186SHannes Reinecke 129977266186SHannes Reinecke static ssize_t serial_show(struct device *dev, 130077266186SHannes Reinecke struct device_attribute *attr, char *buf) 130177266186SHannes Reinecke { 130277266186SHannes Reinecke struct Scsi_Host *shost = class_to_shost(dev); 130377266186SHannes Reinecke struct myrs_hba *cs = shost_priv(shost); 130477266186SHannes Reinecke char serial[17]; 130577266186SHannes Reinecke 130677266186SHannes Reinecke memcpy(serial, cs->ctlr_info->serial_number, 16); 130777266186SHannes Reinecke serial[16] = '\0'; 130877266186SHannes Reinecke return snprintf(buf, 16, "%s\n", serial); 130977266186SHannes Reinecke } 131077266186SHannes Reinecke static DEVICE_ATTR_RO(serial); 131177266186SHannes Reinecke 131277266186SHannes Reinecke static ssize_t ctlr_num_show(struct device *dev, 131377266186SHannes Reinecke struct device_attribute *attr, char *buf) 131477266186SHannes Reinecke { 131577266186SHannes Reinecke struct Scsi_Host *shost = class_to_shost(dev); 131677266186SHannes Reinecke struct myrs_hba *cs = shost_priv(shost); 131777266186SHannes Reinecke 131877266186SHannes Reinecke return snprintf(buf, 20, "%d\n", cs->host->host_no); 131977266186SHannes Reinecke } 132077266186SHannes Reinecke static DEVICE_ATTR_RO(ctlr_num); 132177266186SHannes Reinecke 132277266186SHannes Reinecke static struct myrs_cpu_type_tbl { 132377266186SHannes Reinecke enum myrs_cpu_type type; 132477266186SHannes Reinecke char *name; 132577266186SHannes Reinecke } myrs_cpu_type_names[] = { 132677266186SHannes Reinecke { MYRS_CPUTYPE_i960CA, "i960CA" }, 132777266186SHannes Reinecke { MYRS_CPUTYPE_i960RD, "i960RD" }, 132877266186SHannes Reinecke { MYRS_CPUTYPE_i960RN, "i960RN" }, 132977266186SHannes Reinecke { MYRS_CPUTYPE_i960RP, "i960RP" }, 133077266186SHannes Reinecke { MYRS_CPUTYPE_NorthBay, "NorthBay" }, 133177266186SHannes Reinecke { MYRS_CPUTYPE_StrongArm, "StrongARM" }, 133277266186SHannes Reinecke { MYRS_CPUTYPE_i960RM, "i960RM" }, 133377266186SHannes Reinecke }; 133477266186SHannes Reinecke 133577266186SHannes Reinecke static ssize_t processor_show(struct device *dev, 133677266186SHannes Reinecke struct device_attribute *attr, char *buf) 133777266186SHannes Reinecke { 133877266186SHannes Reinecke struct Scsi_Host *shost = class_to_shost(dev); 133977266186SHannes Reinecke struct myrs_hba *cs = shost_priv(shost); 134077266186SHannes Reinecke struct myrs_cpu_type_tbl *tbl; 134177266186SHannes Reinecke const char *first_processor = NULL; 134277266186SHannes Reinecke const char *second_processor = NULL; 134377266186SHannes Reinecke struct myrs_ctlr_info *info = cs->ctlr_info; 134477266186SHannes Reinecke ssize_t ret; 134577266186SHannes Reinecke int i; 134677266186SHannes Reinecke 134777266186SHannes Reinecke if (info->cpu[0].cpu_count) { 134877266186SHannes Reinecke tbl = myrs_cpu_type_names; 134977266186SHannes Reinecke for (i = 0; i < ARRAY_SIZE(myrs_cpu_type_names); i++) { 135077266186SHannes Reinecke if (tbl[i].type == info->cpu[0].cpu_type) { 135177266186SHannes Reinecke first_processor = tbl[i].name; 135277266186SHannes Reinecke break; 135377266186SHannes Reinecke } 135477266186SHannes Reinecke } 135577266186SHannes Reinecke } 135677266186SHannes Reinecke if (info->cpu[1].cpu_count) { 135777266186SHannes Reinecke tbl = myrs_cpu_type_names; 135877266186SHannes Reinecke for (i = 0; i < ARRAY_SIZE(myrs_cpu_type_names); i++) { 135977266186SHannes Reinecke if (tbl[i].type == info->cpu[1].cpu_type) { 136077266186SHannes Reinecke second_processor = tbl[i].name; 136177266186SHannes Reinecke break; 136277266186SHannes Reinecke } 136377266186SHannes Reinecke } 136477266186SHannes Reinecke } 136577266186SHannes Reinecke if (first_processor && second_processor) 136677266186SHannes Reinecke ret = snprintf(buf, 64, "1: %s (%s, %d cpus)\n" 136777266186SHannes Reinecke "2: %s (%s, %d cpus)\n", 136877266186SHannes Reinecke info->cpu[0].cpu_name, 136977266186SHannes Reinecke first_processor, info->cpu[0].cpu_count, 137077266186SHannes Reinecke info->cpu[1].cpu_name, 137177266186SHannes Reinecke second_processor, info->cpu[1].cpu_count); 1372a0db8a75SDan Carpenter else if (first_processor && !second_processor) 137377266186SHannes Reinecke ret = snprintf(buf, 64, "1: %s (%s, %d cpus)\n2: absent\n", 137477266186SHannes Reinecke info->cpu[0].cpu_name, 137577266186SHannes Reinecke first_processor, info->cpu[0].cpu_count); 1376a0db8a75SDan Carpenter else if (!first_processor && second_processor) 137777266186SHannes Reinecke ret = snprintf(buf, 64, "1: absent\n2: %s (%s, %d cpus)\n", 137877266186SHannes Reinecke info->cpu[1].cpu_name, 137977266186SHannes Reinecke second_processor, info->cpu[1].cpu_count); 138077266186SHannes Reinecke else 138177266186SHannes Reinecke ret = snprintf(buf, 64, "1: absent\n2: absent\n"); 138277266186SHannes Reinecke 138377266186SHannes Reinecke return ret; 138477266186SHannes Reinecke } 138577266186SHannes Reinecke static DEVICE_ATTR_RO(processor); 138677266186SHannes Reinecke 138777266186SHannes Reinecke static ssize_t model_show(struct device *dev, 138877266186SHannes Reinecke struct device_attribute *attr, char *buf) 138977266186SHannes Reinecke { 139077266186SHannes Reinecke struct Scsi_Host *shost = class_to_shost(dev); 139177266186SHannes Reinecke struct myrs_hba *cs = shost_priv(shost); 139277266186SHannes Reinecke 139377266186SHannes Reinecke return snprintf(buf, 28, "%s\n", cs->model_name); 139477266186SHannes Reinecke } 139577266186SHannes Reinecke static DEVICE_ATTR_RO(model); 139677266186SHannes Reinecke 139777266186SHannes Reinecke static ssize_t ctlr_type_show(struct device *dev, 139877266186SHannes Reinecke struct device_attribute *attr, char *buf) 139977266186SHannes Reinecke { 140077266186SHannes Reinecke struct Scsi_Host *shost = class_to_shost(dev); 140177266186SHannes Reinecke struct myrs_hba *cs = shost_priv(shost); 140277266186SHannes Reinecke 140377266186SHannes Reinecke return snprintf(buf, 4, "%d\n", cs->ctlr_info->ctlr_type); 140477266186SHannes Reinecke } 140577266186SHannes Reinecke static DEVICE_ATTR_RO(ctlr_type); 140677266186SHannes Reinecke 140777266186SHannes Reinecke static ssize_t cache_size_show(struct device *dev, 140877266186SHannes Reinecke struct device_attribute *attr, char *buf) 140977266186SHannes Reinecke { 141077266186SHannes Reinecke struct Scsi_Host *shost = class_to_shost(dev); 141177266186SHannes Reinecke struct myrs_hba *cs = shost_priv(shost); 141277266186SHannes Reinecke 141377266186SHannes Reinecke return snprintf(buf, 8, "%d MB\n", cs->ctlr_info->cache_size_mb); 141477266186SHannes Reinecke } 141577266186SHannes Reinecke static DEVICE_ATTR_RO(cache_size); 141677266186SHannes Reinecke 141777266186SHannes Reinecke static ssize_t firmware_show(struct device *dev, 141877266186SHannes Reinecke struct device_attribute *attr, char *buf) 141977266186SHannes Reinecke { 142077266186SHannes Reinecke struct Scsi_Host *shost = class_to_shost(dev); 142177266186SHannes Reinecke struct myrs_hba *cs = shost_priv(shost); 142277266186SHannes Reinecke 142377266186SHannes Reinecke return snprintf(buf, 16, "%d.%02d-%02d\n", 142477266186SHannes Reinecke cs->ctlr_info->fw_major_version, 142577266186SHannes Reinecke cs->ctlr_info->fw_minor_version, 142677266186SHannes Reinecke cs->ctlr_info->fw_turn_number); 142777266186SHannes Reinecke } 142877266186SHannes Reinecke static DEVICE_ATTR_RO(firmware); 142977266186SHannes Reinecke 143077266186SHannes Reinecke static ssize_t discovery_store(struct device *dev, 143177266186SHannes Reinecke struct device_attribute *attr, const char *buf, size_t count) 143277266186SHannes Reinecke { 143377266186SHannes Reinecke struct Scsi_Host *shost = class_to_shost(dev); 143477266186SHannes Reinecke struct myrs_hba *cs = shost_priv(shost); 143577266186SHannes Reinecke struct myrs_cmdblk *cmd_blk; 143677266186SHannes Reinecke union myrs_cmd_mbox *mbox; 143777266186SHannes Reinecke unsigned char status; 143877266186SHannes Reinecke 143977266186SHannes Reinecke mutex_lock(&cs->dcmd_mutex); 144077266186SHannes Reinecke cmd_blk = &cs->dcmd_blk; 144177266186SHannes Reinecke myrs_reset_cmd(cmd_blk); 144277266186SHannes Reinecke mbox = &cmd_blk->mbox; 144377266186SHannes Reinecke mbox->common.opcode = MYRS_CMD_OP_IOCTL; 144477266186SHannes Reinecke mbox->common.id = MYRS_DCMD_TAG; 144577266186SHannes Reinecke mbox->common.control.dma_ctrl_to_host = true; 144677266186SHannes Reinecke mbox->common.control.no_autosense = true; 144777266186SHannes Reinecke mbox->common.ioctl_opcode = MYRS_IOCTL_START_DISCOVERY; 144877266186SHannes Reinecke myrs_exec_cmd(cs, cmd_blk); 144977266186SHannes Reinecke status = cmd_blk->status; 145077266186SHannes Reinecke mutex_unlock(&cs->dcmd_mutex); 145177266186SHannes Reinecke if (status != MYRS_STATUS_SUCCESS) { 145277266186SHannes Reinecke shost_printk(KERN_INFO, shost, 145377266186SHannes Reinecke "Discovery Not Initiated, status %02X\n", 145477266186SHannes Reinecke status); 145577266186SHannes Reinecke return -EINVAL; 145677266186SHannes Reinecke } 145777266186SHannes Reinecke shost_printk(KERN_INFO, shost, "Discovery Initiated\n"); 145877266186SHannes Reinecke cs->next_evseq = 0; 145977266186SHannes Reinecke cs->needs_update = true; 146077266186SHannes Reinecke queue_delayed_work(cs->work_q, &cs->monitor_work, 1); 146177266186SHannes Reinecke flush_delayed_work(&cs->monitor_work); 146277266186SHannes Reinecke shost_printk(KERN_INFO, shost, "Discovery Completed\n"); 146377266186SHannes Reinecke 146477266186SHannes Reinecke return count; 146577266186SHannes Reinecke } 146677266186SHannes Reinecke static DEVICE_ATTR_WO(discovery); 146777266186SHannes Reinecke 146877266186SHannes Reinecke static ssize_t flush_cache_store(struct device *dev, 146977266186SHannes Reinecke struct device_attribute *attr, const char *buf, size_t count) 147077266186SHannes Reinecke { 147177266186SHannes Reinecke struct Scsi_Host *shost = class_to_shost(dev); 147277266186SHannes Reinecke struct myrs_hba *cs = shost_priv(shost); 147377266186SHannes Reinecke unsigned char status; 147477266186SHannes Reinecke 147577266186SHannes Reinecke status = myrs_dev_op(cs, MYRS_IOCTL_FLUSH_DEVICE_DATA, 147677266186SHannes Reinecke MYRS_RAID_CONTROLLER); 147777266186SHannes Reinecke if (status == MYRS_STATUS_SUCCESS) { 147877266186SHannes Reinecke shost_printk(KERN_INFO, shost, "Cache Flush Completed\n"); 147977266186SHannes Reinecke return count; 148077266186SHannes Reinecke } 148177266186SHannes Reinecke shost_printk(KERN_INFO, shost, 148277266186SHannes Reinecke "Cache Flush failed, status 0x%02x\n", status); 148377266186SHannes Reinecke return -EIO; 148477266186SHannes Reinecke } 148577266186SHannes Reinecke static DEVICE_ATTR_WO(flush_cache); 148677266186SHannes Reinecke 148777266186SHannes Reinecke static ssize_t disable_enclosure_messages_show(struct device *dev, 148877266186SHannes Reinecke struct device_attribute *attr, char *buf) 148977266186SHannes Reinecke { 149077266186SHannes Reinecke struct Scsi_Host *shost = class_to_shost(dev); 149177266186SHannes Reinecke struct myrs_hba *cs = shost_priv(shost); 149277266186SHannes Reinecke 149377266186SHannes Reinecke return snprintf(buf, 3, "%d\n", cs->disable_enc_msg); 149477266186SHannes Reinecke } 149577266186SHannes Reinecke 149677266186SHannes Reinecke static ssize_t disable_enclosure_messages_store(struct device *dev, 149777266186SHannes Reinecke struct device_attribute *attr, const char *buf, size_t count) 149877266186SHannes Reinecke { 149977266186SHannes Reinecke struct scsi_device *sdev = to_scsi_device(dev); 150077266186SHannes Reinecke struct myrs_hba *cs = shost_priv(sdev->host); 150177266186SHannes Reinecke int value, ret; 150277266186SHannes Reinecke 150377266186SHannes Reinecke ret = kstrtoint(buf, 0, &value); 150477266186SHannes Reinecke if (ret) 150577266186SHannes Reinecke return ret; 150677266186SHannes Reinecke 150777266186SHannes Reinecke if (value > 2) 150877266186SHannes Reinecke return -EINVAL; 150977266186SHannes Reinecke 151077266186SHannes Reinecke cs->disable_enc_msg = value; 151177266186SHannes Reinecke return count; 151277266186SHannes Reinecke } 151377266186SHannes Reinecke static DEVICE_ATTR_RW(disable_enclosure_messages); 151477266186SHannes Reinecke 151577266186SHannes Reinecke static struct device_attribute *myrs_shost_attrs[] = { 151677266186SHannes Reinecke &dev_attr_serial, 151777266186SHannes Reinecke &dev_attr_ctlr_num, 151877266186SHannes Reinecke &dev_attr_processor, 151977266186SHannes Reinecke &dev_attr_model, 152077266186SHannes Reinecke &dev_attr_ctlr_type, 152177266186SHannes Reinecke &dev_attr_cache_size, 152277266186SHannes Reinecke &dev_attr_firmware, 152377266186SHannes Reinecke &dev_attr_discovery, 152477266186SHannes Reinecke &dev_attr_flush_cache, 152577266186SHannes Reinecke &dev_attr_disable_enclosure_messages, 152677266186SHannes Reinecke NULL, 152777266186SHannes Reinecke }; 152877266186SHannes Reinecke 152977266186SHannes Reinecke /* 153077266186SHannes Reinecke * SCSI midlayer interface 153177266186SHannes Reinecke */ 1532*ebe41b99SJason Yan static int myrs_host_reset(struct scsi_cmnd *scmd) 153377266186SHannes Reinecke { 153477266186SHannes Reinecke struct Scsi_Host *shost = scmd->device->host; 153577266186SHannes Reinecke struct myrs_hba *cs = shost_priv(shost); 153677266186SHannes Reinecke 153777266186SHannes Reinecke cs->reset(cs->io_base); 153877266186SHannes Reinecke return SUCCESS; 153977266186SHannes Reinecke } 154077266186SHannes Reinecke 154177266186SHannes Reinecke static void myrs_mode_sense(struct myrs_hba *cs, struct scsi_cmnd *scmd, 154277266186SHannes Reinecke struct myrs_ldev_info *ldev_info) 154377266186SHannes Reinecke { 154477266186SHannes Reinecke unsigned char modes[32], *mode_pg; 154577266186SHannes Reinecke bool dbd; 154677266186SHannes Reinecke size_t mode_len; 154777266186SHannes Reinecke 154877266186SHannes Reinecke dbd = (scmd->cmnd[1] & 0x08) == 0x08; 154977266186SHannes Reinecke if (dbd) { 155077266186SHannes Reinecke mode_len = 24; 155177266186SHannes Reinecke mode_pg = &modes[4]; 155277266186SHannes Reinecke } else { 155377266186SHannes Reinecke mode_len = 32; 155477266186SHannes Reinecke mode_pg = &modes[12]; 155577266186SHannes Reinecke } 155677266186SHannes Reinecke memset(modes, 0, sizeof(modes)); 155777266186SHannes Reinecke modes[0] = mode_len - 1; 155877266186SHannes Reinecke modes[2] = 0x10; /* Enable FUA */ 155977266186SHannes Reinecke if (ldev_info->ldev_control.wce == MYRS_LOGICALDEVICE_RO) 156077266186SHannes Reinecke modes[2] |= 0x80; 156177266186SHannes Reinecke if (!dbd) { 156277266186SHannes Reinecke unsigned char *block_desc = &modes[4]; 156377266186SHannes Reinecke 156477266186SHannes Reinecke modes[3] = 8; 156577266186SHannes Reinecke put_unaligned_be32(ldev_info->cfg_devsize, &block_desc[0]); 156677266186SHannes Reinecke put_unaligned_be32(ldev_info->devsize_bytes, &block_desc[5]); 156777266186SHannes Reinecke } 156877266186SHannes Reinecke mode_pg[0] = 0x08; 156977266186SHannes Reinecke mode_pg[1] = 0x12; 157077266186SHannes Reinecke if (ldev_info->ldev_control.rce == MYRS_READCACHE_DISABLED) 157177266186SHannes Reinecke mode_pg[2] |= 0x01; 157277266186SHannes Reinecke if (ldev_info->ldev_control.wce == MYRS_WRITECACHE_ENABLED || 157377266186SHannes Reinecke ldev_info->ldev_control.wce == MYRS_INTELLIGENT_WRITECACHE_ENABLED) 157477266186SHannes Reinecke mode_pg[2] |= 0x04; 157577266186SHannes Reinecke if (ldev_info->cacheline_size) { 157677266186SHannes Reinecke mode_pg[2] |= 0x08; 157777266186SHannes Reinecke put_unaligned_be16(1 << ldev_info->cacheline_size, 157877266186SHannes Reinecke &mode_pg[14]); 157977266186SHannes Reinecke } 158077266186SHannes Reinecke 158177266186SHannes Reinecke scsi_sg_copy_from_buffer(scmd, modes, mode_len); 158277266186SHannes Reinecke } 158377266186SHannes Reinecke 158477266186SHannes Reinecke static int myrs_queuecommand(struct Scsi_Host *shost, 158577266186SHannes Reinecke struct scsi_cmnd *scmd) 158677266186SHannes Reinecke { 158777266186SHannes Reinecke struct myrs_hba *cs = shost_priv(shost); 158877266186SHannes Reinecke struct myrs_cmdblk *cmd_blk = scsi_cmd_priv(scmd); 158977266186SHannes Reinecke union myrs_cmd_mbox *mbox = &cmd_blk->mbox; 159077266186SHannes Reinecke struct scsi_device *sdev = scmd->device; 159177266186SHannes Reinecke union myrs_sgl *hw_sge; 159277266186SHannes Reinecke dma_addr_t sense_addr; 159377266186SHannes Reinecke struct scatterlist *sgl; 159477266186SHannes Reinecke unsigned long flags, timeout; 159577266186SHannes Reinecke int nsge; 159677266186SHannes Reinecke 159777266186SHannes Reinecke if (!scmd->device->hostdata) { 159877266186SHannes Reinecke scmd->result = (DID_NO_CONNECT << 16); 159977266186SHannes Reinecke scmd->scsi_done(scmd); 160077266186SHannes Reinecke return 0; 160177266186SHannes Reinecke } 160277266186SHannes Reinecke 160377266186SHannes Reinecke switch (scmd->cmnd[0]) { 160477266186SHannes Reinecke case REPORT_LUNS: 160577266186SHannes Reinecke scsi_build_sense_buffer(0, scmd->sense_buffer, ILLEGAL_REQUEST, 160677266186SHannes Reinecke 0x20, 0x0); 160777266186SHannes Reinecke scmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; 160877266186SHannes Reinecke scmd->scsi_done(scmd); 160977266186SHannes Reinecke return 0; 161077266186SHannes Reinecke case MODE_SENSE: 161177266186SHannes Reinecke if (scmd->device->channel >= cs->ctlr_info->physchan_present) { 161277266186SHannes Reinecke struct myrs_ldev_info *ldev_info = sdev->hostdata; 161377266186SHannes Reinecke 161477266186SHannes Reinecke if ((scmd->cmnd[2] & 0x3F) != 0x3F && 161577266186SHannes Reinecke (scmd->cmnd[2] & 0x3F) != 0x08) { 161677266186SHannes Reinecke /* Illegal request, invalid field in CDB */ 161777266186SHannes Reinecke scsi_build_sense_buffer(0, scmd->sense_buffer, 161877266186SHannes Reinecke ILLEGAL_REQUEST, 0x24, 0); 161977266186SHannes Reinecke scmd->result = (DRIVER_SENSE << 24) | 162077266186SHannes Reinecke SAM_STAT_CHECK_CONDITION; 162177266186SHannes Reinecke } else { 162277266186SHannes Reinecke myrs_mode_sense(cs, scmd, ldev_info); 162377266186SHannes Reinecke scmd->result = (DID_OK << 16); 162477266186SHannes Reinecke } 162577266186SHannes Reinecke scmd->scsi_done(scmd); 162677266186SHannes Reinecke return 0; 162777266186SHannes Reinecke } 162877266186SHannes Reinecke break; 162977266186SHannes Reinecke } 163077266186SHannes Reinecke 163177266186SHannes Reinecke myrs_reset_cmd(cmd_blk); 163277266186SHannes Reinecke cmd_blk->sense = dma_pool_alloc(cs->sense_pool, GFP_ATOMIC, 163377266186SHannes Reinecke &sense_addr); 163477266186SHannes Reinecke if (!cmd_blk->sense) 163577266186SHannes Reinecke return SCSI_MLQUEUE_HOST_BUSY; 163677266186SHannes Reinecke cmd_blk->sense_addr = sense_addr; 163777266186SHannes Reinecke 163877266186SHannes Reinecke timeout = scmd->request->timeout; 163977266186SHannes Reinecke if (scmd->cmd_len <= 10) { 164077266186SHannes Reinecke if (scmd->device->channel >= cs->ctlr_info->physchan_present) { 164177266186SHannes Reinecke struct myrs_ldev_info *ldev_info = sdev->hostdata; 164277266186SHannes Reinecke 164377266186SHannes Reinecke mbox->SCSI_10.opcode = MYRS_CMD_OP_SCSI_10; 164477266186SHannes Reinecke mbox->SCSI_10.pdev.lun = ldev_info->lun; 164577266186SHannes Reinecke mbox->SCSI_10.pdev.target = ldev_info->target; 164677266186SHannes Reinecke mbox->SCSI_10.pdev.channel = ldev_info->channel; 164777266186SHannes Reinecke mbox->SCSI_10.pdev.ctlr = 0; 164877266186SHannes Reinecke } else { 164977266186SHannes Reinecke mbox->SCSI_10.opcode = MYRS_CMD_OP_SCSI_10_PASSTHRU; 165077266186SHannes Reinecke mbox->SCSI_10.pdev.lun = sdev->lun; 165177266186SHannes Reinecke mbox->SCSI_10.pdev.target = sdev->id; 165277266186SHannes Reinecke mbox->SCSI_10.pdev.channel = sdev->channel; 165377266186SHannes Reinecke } 165477266186SHannes Reinecke mbox->SCSI_10.id = scmd->request->tag + 3; 165577266186SHannes Reinecke mbox->SCSI_10.control.dma_ctrl_to_host = 165677266186SHannes Reinecke (scmd->sc_data_direction == DMA_FROM_DEVICE); 165777266186SHannes Reinecke if (scmd->request->cmd_flags & REQ_FUA) 165877266186SHannes Reinecke mbox->SCSI_10.control.fua = true; 165977266186SHannes Reinecke mbox->SCSI_10.dma_size = scsi_bufflen(scmd); 166077266186SHannes Reinecke mbox->SCSI_10.sense_addr = cmd_blk->sense_addr; 166177266186SHannes Reinecke mbox->SCSI_10.sense_len = MYRS_SENSE_SIZE; 166277266186SHannes Reinecke mbox->SCSI_10.cdb_len = scmd->cmd_len; 166377266186SHannes Reinecke if (timeout > 60) { 166477266186SHannes Reinecke mbox->SCSI_10.tmo.tmo_scale = MYRS_TMO_SCALE_MINUTES; 166577266186SHannes Reinecke mbox->SCSI_10.tmo.tmo_val = timeout / 60; 166677266186SHannes Reinecke } else { 166777266186SHannes Reinecke mbox->SCSI_10.tmo.tmo_scale = MYRS_TMO_SCALE_SECONDS; 166877266186SHannes Reinecke mbox->SCSI_10.tmo.tmo_val = timeout; 166977266186SHannes Reinecke } 167077266186SHannes Reinecke memcpy(&mbox->SCSI_10.cdb, scmd->cmnd, scmd->cmd_len); 167177266186SHannes Reinecke hw_sge = &mbox->SCSI_10.dma_addr; 167277266186SHannes Reinecke cmd_blk->dcdb = NULL; 167377266186SHannes Reinecke } else { 167477266186SHannes Reinecke dma_addr_t dcdb_dma; 167577266186SHannes Reinecke 167677266186SHannes Reinecke cmd_blk->dcdb = dma_pool_alloc(cs->dcdb_pool, GFP_ATOMIC, 167777266186SHannes Reinecke &dcdb_dma); 167877266186SHannes Reinecke if (!cmd_blk->dcdb) { 167977266186SHannes Reinecke dma_pool_free(cs->sense_pool, cmd_blk->sense, 168077266186SHannes Reinecke cmd_blk->sense_addr); 168177266186SHannes Reinecke cmd_blk->sense = NULL; 168277266186SHannes Reinecke cmd_blk->sense_addr = 0; 168377266186SHannes Reinecke return SCSI_MLQUEUE_HOST_BUSY; 168477266186SHannes Reinecke } 168577266186SHannes Reinecke cmd_blk->dcdb_dma = dcdb_dma; 168677266186SHannes Reinecke if (scmd->device->channel >= cs->ctlr_info->physchan_present) { 168777266186SHannes Reinecke struct myrs_ldev_info *ldev_info = sdev->hostdata; 168877266186SHannes Reinecke 168977266186SHannes Reinecke mbox->SCSI_255.opcode = MYRS_CMD_OP_SCSI_256; 169077266186SHannes Reinecke mbox->SCSI_255.pdev.lun = ldev_info->lun; 169177266186SHannes Reinecke mbox->SCSI_255.pdev.target = ldev_info->target; 169277266186SHannes Reinecke mbox->SCSI_255.pdev.channel = ldev_info->channel; 169377266186SHannes Reinecke mbox->SCSI_255.pdev.ctlr = 0; 169477266186SHannes Reinecke } else { 169577266186SHannes Reinecke mbox->SCSI_255.opcode = MYRS_CMD_OP_SCSI_255_PASSTHRU; 169677266186SHannes Reinecke mbox->SCSI_255.pdev.lun = sdev->lun; 169777266186SHannes Reinecke mbox->SCSI_255.pdev.target = sdev->id; 169877266186SHannes Reinecke mbox->SCSI_255.pdev.channel = sdev->channel; 169977266186SHannes Reinecke } 170077266186SHannes Reinecke mbox->SCSI_255.id = scmd->request->tag + 3; 170177266186SHannes Reinecke mbox->SCSI_255.control.dma_ctrl_to_host = 170277266186SHannes Reinecke (scmd->sc_data_direction == DMA_FROM_DEVICE); 170377266186SHannes Reinecke if (scmd->request->cmd_flags & REQ_FUA) 170477266186SHannes Reinecke mbox->SCSI_255.control.fua = true; 170577266186SHannes Reinecke mbox->SCSI_255.dma_size = scsi_bufflen(scmd); 170677266186SHannes Reinecke mbox->SCSI_255.sense_addr = cmd_blk->sense_addr; 170777266186SHannes Reinecke mbox->SCSI_255.sense_len = MYRS_SENSE_SIZE; 170877266186SHannes Reinecke mbox->SCSI_255.cdb_len = scmd->cmd_len; 170977266186SHannes Reinecke mbox->SCSI_255.cdb_addr = cmd_blk->dcdb_dma; 171077266186SHannes Reinecke if (timeout > 60) { 171177266186SHannes Reinecke mbox->SCSI_255.tmo.tmo_scale = MYRS_TMO_SCALE_MINUTES; 171277266186SHannes Reinecke mbox->SCSI_255.tmo.tmo_val = timeout / 60; 171377266186SHannes Reinecke } else { 171477266186SHannes Reinecke mbox->SCSI_255.tmo.tmo_scale = MYRS_TMO_SCALE_SECONDS; 171577266186SHannes Reinecke mbox->SCSI_255.tmo.tmo_val = timeout; 171677266186SHannes Reinecke } 171777266186SHannes Reinecke memcpy(cmd_blk->dcdb, scmd->cmnd, scmd->cmd_len); 171877266186SHannes Reinecke hw_sge = &mbox->SCSI_255.dma_addr; 171977266186SHannes Reinecke } 172077266186SHannes Reinecke if (scmd->sc_data_direction == DMA_NONE) 172177266186SHannes Reinecke goto submit; 172277266186SHannes Reinecke nsge = scsi_dma_map(scmd); 172377266186SHannes Reinecke if (nsge == 1) { 172477266186SHannes Reinecke sgl = scsi_sglist(scmd); 172577266186SHannes Reinecke hw_sge->sge[0].sge_addr = (u64)sg_dma_address(sgl); 172677266186SHannes Reinecke hw_sge->sge[0].sge_count = (u64)sg_dma_len(sgl); 172777266186SHannes Reinecke } else { 172877266186SHannes Reinecke struct myrs_sge *hw_sgl; 172977266186SHannes Reinecke dma_addr_t hw_sgl_addr; 173077266186SHannes Reinecke int i; 173177266186SHannes Reinecke 173277266186SHannes Reinecke if (nsge > 2) { 173377266186SHannes Reinecke hw_sgl = dma_pool_alloc(cs->sg_pool, GFP_ATOMIC, 173477266186SHannes Reinecke &hw_sgl_addr); 173577266186SHannes Reinecke if (WARN_ON(!hw_sgl)) { 173677266186SHannes Reinecke if (cmd_blk->dcdb) { 173777266186SHannes Reinecke dma_pool_free(cs->dcdb_pool, 173877266186SHannes Reinecke cmd_blk->dcdb, 173977266186SHannes Reinecke cmd_blk->dcdb_dma); 174077266186SHannes Reinecke cmd_blk->dcdb = NULL; 174177266186SHannes Reinecke cmd_blk->dcdb_dma = 0; 174277266186SHannes Reinecke } 174377266186SHannes Reinecke dma_pool_free(cs->sense_pool, 174477266186SHannes Reinecke cmd_blk->sense, 174577266186SHannes Reinecke cmd_blk->sense_addr); 174677266186SHannes Reinecke cmd_blk->sense = NULL; 174777266186SHannes Reinecke cmd_blk->sense_addr = 0; 174877266186SHannes Reinecke return SCSI_MLQUEUE_HOST_BUSY; 174977266186SHannes Reinecke } 175077266186SHannes Reinecke cmd_blk->sgl = hw_sgl; 175177266186SHannes Reinecke cmd_blk->sgl_addr = hw_sgl_addr; 175277266186SHannes Reinecke if (scmd->cmd_len <= 10) 175377266186SHannes Reinecke mbox->SCSI_10.control.add_sge_mem = true; 175477266186SHannes Reinecke else 175577266186SHannes Reinecke mbox->SCSI_255.control.add_sge_mem = true; 175677266186SHannes Reinecke hw_sge->ext.sge0_len = nsge; 175777266186SHannes Reinecke hw_sge->ext.sge0_addr = cmd_blk->sgl_addr; 175877266186SHannes Reinecke } else 175977266186SHannes Reinecke hw_sgl = hw_sge->sge; 176077266186SHannes Reinecke 176177266186SHannes Reinecke scsi_for_each_sg(scmd, sgl, nsge, i) { 176277266186SHannes Reinecke if (WARN_ON(!hw_sgl)) { 176377266186SHannes Reinecke scsi_dma_unmap(scmd); 176477266186SHannes Reinecke scmd->result = (DID_ERROR << 16); 176577266186SHannes Reinecke scmd->scsi_done(scmd); 176677266186SHannes Reinecke return 0; 176777266186SHannes Reinecke } 176877266186SHannes Reinecke hw_sgl->sge_addr = (u64)sg_dma_address(sgl); 176977266186SHannes Reinecke hw_sgl->sge_count = (u64)sg_dma_len(sgl); 177077266186SHannes Reinecke hw_sgl++; 177177266186SHannes Reinecke } 177277266186SHannes Reinecke } 177377266186SHannes Reinecke submit: 177477266186SHannes Reinecke spin_lock_irqsave(&cs->queue_lock, flags); 177577266186SHannes Reinecke myrs_qcmd(cs, cmd_blk); 177677266186SHannes Reinecke spin_unlock_irqrestore(&cs->queue_lock, flags); 177777266186SHannes Reinecke 177877266186SHannes Reinecke return 0; 177977266186SHannes Reinecke } 178077266186SHannes Reinecke 178177266186SHannes Reinecke static unsigned short myrs_translate_ldev(struct myrs_hba *cs, 178277266186SHannes Reinecke struct scsi_device *sdev) 178377266186SHannes Reinecke { 178477266186SHannes Reinecke unsigned short ldev_num; 178577266186SHannes Reinecke unsigned int chan_offset = 178677266186SHannes Reinecke sdev->channel - cs->ctlr_info->physchan_present; 178777266186SHannes Reinecke 178877266186SHannes Reinecke ldev_num = sdev->id + chan_offset * sdev->host->max_id; 178977266186SHannes Reinecke 179077266186SHannes Reinecke return ldev_num; 179177266186SHannes Reinecke } 179277266186SHannes Reinecke 179377266186SHannes Reinecke static int myrs_slave_alloc(struct scsi_device *sdev) 179477266186SHannes Reinecke { 179577266186SHannes Reinecke struct myrs_hba *cs = shost_priv(sdev->host); 179677266186SHannes Reinecke unsigned char status; 179777266186SHannes Reinecke 179877266186SHannes Reinecke if (sdev->channel > sdev->host->max_channel) 179977266186SHannes Reinecke return 0; 180077266186SHannes Reinecke 180177266186SHannes Reinecke if (sdev->channel >= cs->ctlr_info->physchan_present) { 180277266186SHannes Reinecke struct myrs_ldev_info *ldev_info; 180377266186SHannes Reinecke unsigned short ldev_num; 180477266186SHannes Reinecke 180577266186SHannes Reinecke if (sdev->lun > 0) 180677266186SHannes Reinecke return -ENXIO; 180777266186SHannes Reinecke 180877266186SHannes Reinecke ldev_num = myrs_translate_ldev(cs, sdev); 180977266186SHannes Reinecke 181077266186SHannes Reinecke ldev_info = kzalloc(sizeof(*ldev_info), GFP_KERNEL|GFP_DMA); 181177266186SHannes Reinecke if (!ldev_info) 181277266186SHannes Reinecke return -ENOMEM; 181377266186SHannes Reinecke 181477266186SHannes Reinecke status = myrs_get_ldev_info(cs, ldev_num, ldev_info); 181577266186SHannes Reinecke if (status != MYRS_STATUS_SUCCESS) { 181677266186SHannes Reinecke sdev->hostdata = NULL; 181777266186SHannes Reinecke kfree(ldev_info); 181877266186SHannes Reinecke } else { 181977266186SHannes Reinecke enum raid_level level; 182077266186SHannes Reinecke 182177266186SHannes Reinecke dev_dbg(&sdev->sdev_gendev, 182277266186SHannes Reinecke "Logical device mapping %d:%d:%d -> %d\n", 182377266186SHannes Reinecke ldev_info->channel, ldev_info->target, 182477266186SHannes Reinecke ldev_info->lun, ldev_info->ldev_num); 182577266186SHannes Reinecke 182677266186SHannes Reinecke sdev->hostdata = ldev_info; 182777266186SHannes Reinecke switch (ldev_info->raid_level) { 182877266186SHannes Reinecke case MYRS_RAID_LEVEL0: 182977266186SHannes Reinecke level = RAID_LEVEL_LINEAR; 183077266186SHannes Reinecke break; 183177266186SHannes Reinecke case MYRS_RAID_LEVEL1: 183277266186SHannes Reinecke level = RAID_LEVEL_1; 183377266186SHannes Reinecke break; 183477266186SHannes Reinecke case MYRS_RAID_LEVEL3: 183577266186SHannes Reinecke case MYRS_RAID_LEVEL3F: 183677266186SHannes Reinecke case MYRS_RAID_LEVEL3L: 183777266186SHannes Reinecke level = RAID_LEVEL_3; 183877266186SHannes Reinecke break; 183977266186SHannes Reinecke case MYRS_RAID_LEVEL5: 184077266186SHannes Reinecke case MYRS_RAID_LEVEL5L: 184177266186SHannes Reinecke level = RAID_LEVEL_5; 184277266186SHannes Reinecke break; 184377266186SHannes Reinecke case MYRS_RAID_LEVEL6: 184477266186SHannes Reinecke level = RAID_LEVEL_6; 184577266186SHannes Reinecke break; 184677266186SHannes Reinecke case MYRS_RAID_LEVELE: 184777266186SHannes Reinecke case MYRS_RAID_NEWSPAN: 184877266186SHannes Reinecke case MYRS_RAID_SPAN: 184977266186SHannes Reinecke level = RAID_LEVEL_LINEAR; 185077266186SHannes Reinecke break; 185177266186SHannes Reinecke case MYRS_RAID_JBOD: 185277266186SHannes Reinecke level = RAID_LEVEL_JBOD; 185377266186SHannes Reinecke break; 185477266186SHannes Reinecke default: 185577266186SHannes Reinecke level = RAID_LEVEL_UNKNOWN; 185677266186SHannes Reinecke break; 185777266186SHannes Reinecke } 185877266186SHannes Reinecke raid_set_level(myrs_raid_template, 185977266186SHannes Reinecke &sdev->sdev_gendev, level); 186077266186SHannes Reinecke if (ldev_info->dev_state != MYRS_DEVICE_ONLINE) { 186177266186SHannes Reinecke const char *name; 186277266186SHannes Reinecke 186377266186SHannes Reinecke name = myrs_devstate_name(ldev_info->dev_state); 186477266186SHannes Reinecke sdev_printk(KERN_DEBUG, sdev, 186577266186SHannes Reinecke "logical device in state %s\n", 186677266186SHannes Reinecke name ? name : "Invalid"); 186777266186SHannes Reinecke } 186877266186SHannes Reinecke } 186977266186SHannes Reinecke } else { 187077266186SHannes Reinecke struct myrs_pdev_info *pdev_info; 187177266186SHannes Reinecke 187277266186SHannes Reinecke pdev_info = kzalloc(sizeof(*pdev_info), GFP_KERNEL|GFP_DMA); 187377266186SHannes Reinecke if (!pdev_info) 187477266186SHannes Reinecke return -ENOMEM; 187577266186SHannes Reinecke 187677266186SHannes Reinecke status = myrs_get_pdev_info(cs, sdev->channel, 187777266186SHannes Reinecke sdev->id, sdev->lun, 187877266186SHannes Reinecke pdev_info); 187977266186SHannes Reinecke if (status != MYRS_STATUS_SUCCESS) { 188077266186SHannes Reinecke sdev->hostdata = NULL; 188177266186SHannes Reinecke kfree(pdev_info); 188277266186SHannes Reinecke return -ENXIO; 188377266186SHannes Reinecke } 188477266186SHannes Reinecke sdev->hostdata = pdev_info; 188577266186SHannes Reinecke } 188677266186SHannes Reinecke return 0; 188777266186SHannes Reinecke } 188877266186SHannes Reinecke 188977266186SHannes Reinecke static int myrs_slave_configure(struct scsi_device *sdev) 189077266186SHannes Reinecke { 189177266186SHannes Reinecke struct myrs_hba *cs = shost_priv(sdev->host); 189277266186SHannes Reinecke struct myrs_ldev_info *ldev_info; 189377266186SHannes Reinecke 189477266186SHannes Reinecke if (sdev->channel > sdev->host->max_channel) 189577266186SHannes Reinecke return -ENXIO; 189677266186SHannes Reinecke 189777266186SHannes Reinecke if (sdev->channel < cs->ctlr_info->physchan_present) { 189877266186SHannes Reinecke /* Skip HBA device */ 189977266186SHannes Reinecke if (sdev->type == TYPE_RAID) 190077266186SHannes Reinecke return -ENXIO; 190177266186SHannes Reinecke sdev->no_uld_attach = 1; 190277266186SHannes Reinecke return 0; 190377266186SHannes Reinecke } 190477266186SHannes Reinecke if (sdev->lun != 0) 190577266186SHannes Reinecke return -ENXIO; 190677266186SHannes Reinecke 190777266186SHannes Reinecke ldev_info = sdev->hostdata; 190877266186SHannes Reinecke if (!ldev_info) 190977266186SHannes Reinecke return -ENXIO; 191077266186SHannes Reinecke if (ldev_info->ldev_control.wce == MYRS_WRITECACHE_ENABLED || 191177266186SHannes Reinecke ldev_info->ldev_control.wce == MYRS_INTELLIGENT_WRITECACHE_ENABLED) 191277266186SHannes Reinecke sdev->wce_default_on = 1; 191377266186SHannes Reinecke sdev->tagged_supported = 1; 191477266186SHannes Reinecke return 0; 191577266186SHannes Reinecke } 191677266186SHannes Reinecke 191777266186SHannes Reinecke static void myrs_slave_destroy(struct scsi_device *sdev) 191877266186SHannes Reinecke { 191977266186SHannes Reinecke kfree(sdev->hostdata); 192077266186SHannes Reinecke } 192177266186SHannes Reinecke 1922*ebe41b99SJason Yan static struct scsi_host_template myrs_template = { 192377266186SHannes Reinecke .module = THIS_MODULE, 192477266186SHannes Reinecke .name = "DAC960", 192577266186SHannes Reinecke .proc_name = "myrs", 192677266186SHannes Reinecke .queuecommand = myrs_queuecommand, 192777266186SHannes Reinecke .eh_host_reset_handler = myrs_host_reset, 192877266186SHannes Reinecke .slave_alloc = myrs_slave_alloc, 192977266186SHannes Reinecke .slave_configure = myrs_slave_configure, 193077266186SHannes Reinecke .slave_destroy = myrs_slave_destroy, 193177266186SHannes Reinecke .cmd_size = sizeof(struct myrs_cmdblk), 193277266186SHannes Reinecke .shost_attrs = myrs_shost_attrs, 193377266186SHannes Reinecke .sdev_attrs = myrs_sdev_attrs, 193477266186SHannes Reinecke .this_id = -1, 193577266186SHannes Reinecke }; 193677266186SHannes Reinecke 193777266186SHannes Reinecke static struct myrs_hba *myrs_alloc_host(struct pci_dev *pdev, 193877266186SHannes Reinecke const struct pci_device_id *entry) 193977266186SHannes Reinecke { 194077266186SHannes Reinecke struct Scsi_Host *shost; 194177266186SHannes Reinecke struct myrs_hba *cs; 194277266186SHannes Reinecke 194377266186SHannes Reinecke shost = scsi_host_alloc(&myrs_template, sizeof(struct myrs_hba)); 194477266186SHannes Reinecke if (!shost) 194577266186SHannes Reinecke return NULL; 194677266186SHannes Reinecke 194777266186SHannes Reinecke shost->max_cmd_len = 16; 194877266186SHannes Reinecke shost->max_lun = 256; 194977266186SHannes Reinecke cs = shost_priv(shost); 195077266186SHannes Reinecke mutex_init(&cs->dcmd_mutex); 195177266186SHannes Reinecke mutex_init(&cs->cinfo_mutex); 195277266186SHannes Reinecke cs->host = shost; 195377266186SHannes Reinecke 195477266186SHannes Reinecke return cs; 195577266186SHannes Reinecke } 195677266186SHannes Reinecke 195777266186SHannes Reinecke /* 195877266186SHannes Reinecke * RAID template functions 195977266186SHannes Reinecke */ 196077266186SHannes Reinecke 196177266186SHannes Reinecke /** 196277266186SHannes Reinecke * myrs_is_raid - return boolean indicating device is raid volume 196377266186SHannes Reinecke * @dev the device struct object 196477266186SHannes Reinecke */ 196577266186SHannes Reinecke static int 196677266186SHannes Reinecke myrs_is_raid(struct device *dev) 196777266186SHannes Reinecke { 196877266186SHannes Reinecke struct scsi_device *sdev = to_scsi_device(dev); 196977266186SHannes Reinecke struct myrs_hba *cs = shost_priv(sdev->host); 197077266186SHannes Reinecke 197177266186SHannes Reinecke return (sdev->channel >= cs->ctlr_info->physchan_present) ? 1 : 0; 197277266186SHannes Reinecke } 197377266186SHannes Reinecke 197477266186SHannes Reinecke /** 197577266186SHannes Reinecke * myrs_get_resync - get raid volume resync percent complete 197677266186SHannes Reinecke * @dev the device struct object 197777266186SHannes Reinecke */ 197877266186SHannes Reinecke static void 197977266186SHannes Reinecke myrs_get_resync(struct device *dev) 198077266186SHannes Reinecke { 198177266186SHannes Reinecke struct scsi_device *sdev = to_scsi_device(dev); 198277266186SHannes Reinecke struct myrs_hba *cs = shost_priv(sdev->host); 198377266186SHannes Reinecke struct myrs_ldev_info *ldev_info = sdev->hostdata; 1984d592dd64SJames Bottomley u64 percent_complete = 0; 1985d592dd64SJames Bottomley u8 status; 198677266186SHannes Reinecke 198777266186SHannes Reinecke if (sdev->channel < cs->ctlr_info->physchan_present || !ldev_info) 198877266186SHannes Reinecke return; 198977266186SHannes Reinecke if (ldev_info->rbld_active) { 199077266186SHannes Reinecke unsigned short ldev_num = ldev_info->ldev_num; 199177266186SHannes Reinecke 199277266186SHannes Reinecke status = myrs_get_ldev_info(cs, ldev_num, ldev_info); 1993d592dd64SJames Bottomley percent_complete = ldev_info->rbld_lba * 100; 1994d592dd64SJames Bottomley do_div(percent_complete, ldev_info->cfg_devsize); 199577266186SHannes Reinecke } 199677266186SHannes Reinecke raid_set_resync(myrs_raid_template, dev, percent_complete); 199777266186SHannes Reinecke } 199877266186SHannes Reinecke 199977266186SHannes Reinecke /** 200077266186SHannes Reinecke * myrs_get_state - get raid volume status 200177266186SHannes Reinecke * @dev the device struct object 200277266186SHannes Reinecke */ 200377266186SHannes Reinecke static void 200477266186SHannes Reinecke myrs_get_state(struct device *dev) 200577266186SHannes Reinecke { 200677266186SHannes Reinecke struct scsi_device *sdev = to_scsi_device(dev); 200777266186SHannes Reinecke struct myrs_hba *cs = shost_priv(sdev->host); 200877266186SHannes Reinecke struct myrs_ldev_info *ldev_info = sdev->hostdata; 200977266186SHannes Reinecke enum raid_state state = RAID_STATE_UNKNOWN; 201077266186SHannes Reinecke 201177266186SHannes Reinecke if (sdev->channel < cs->ctlr_info->physchan_present || !ldev_info) 201277266186SHannes Reinecke state = RAID_STATE_UNKNOWN; 201377266186SHannes Reinecke else { 201477266186SHannes Reinecke switch (ldev_info->dev_state) { 201577266186SHannes Reinecke case MYRS_DEVICE_ONLINE: 201677266186SHannes Reinecke state = RAID_STATE_ACTIVE; 201777266186SHannes Reinecke break; 201877266186SHannes Reinecke case MYRS_DEVICE_SUSPECTED_CRITICAL: 201977266186SHannes Reinecke case MYRS_DEVICE_CRITICAL: 202077266186SHannes Reinecke state = RAID_STATE_DEGRADED; 202177266186SHannes Reinecke break; 202277266186SHannes Reinecke case MYRS_DEVICE_REBUILD: 202377266186SHannes Reinecke state = RAID_STATE_RESYNCING; 202477266186SHannes Reinecke break; 202577266186SHannes Reinecke case MYRS_DEVICE_UNCONFIGURED: 202677266186SHannes Reinecke case MYRS_DEVICE_INVALID_STATE: 202777266186SHannes Reinecke state = RAID_STATE_UNKNOWN; 202877266186SHannes Reinecke break; 202977266186SHannes Reinecke default: 203077266186SHannes Reinecke state = RAID_STATE_OFFLINE; 203177266186SHannes Reinecke } 203277266186SHannes Reinecke } 203377266186SHannes Reinecke raid_set_state(myrs_raid_template, dev, state); 203477266186SHannes Reinecke } 203577266186SHannes Reinecke 2036*ebe41b99SJason Yan static struct raid_function_template myrs_raid_functions = { 203777266186SHannes Reinecke .cookie = &myrs_template, 203877266186SHannes Reinecke .is_raid = myrs_is_raid, 203977266186SHannes Reinecke .get_resync = myrs_get_resync, 204077266186SHannes Reinecke .get_state = myrs_get_state, 204177266186SHannes Reinecke }; 204277266186SHannes Reinecke 204377266186SHannes Reinecke /* 204477266186SHannes Reinecke * PCI interface functions 204577266186SHannes Reinecke */ 2046*ebe41b99SJason Yan static void myrs_flush_cache(struct myrs_hba *cs) 204777266186SHannes Reinecke { 204877266186SHannes Reinecke myrs_dev_op(cs, MYRS_IOCTL_FLUSH_DEVICE_DATA, MYRS_RAID_CONTROLLER); 204977266186SHannes Reinecke } 205077266186SHannes Reinecke 205177266186SHannes Reinecke static void myrs_handle_scsi(struct myrs_hba *cs, struct myrs_cmdblk *cmd_blk, 205277266186SHannes Reinecke struct scsi_cmnd *scmd) 205377266186SHannes Reinecke { 205477266186SHannes Reinecke unsigned char status; 205577266186SHannes Reinecke 205677266186SHannes Reinecke if (!cmd_blk) 205777266186SHannes Reinecke return; 205877266186SHannes Reinecke 205977266186SHannes Reinecke scsi_dma_unmap(scmd); 206077266186SHannes Reinecke status = cmd_blk->status; 206177266186SHannes Reinecke if (cmd_blk->sense) { 206277266186SHannes Reinecke if (status == MYRS_STATUS_FAILED && cmd_blk->sense_len) { 206377266186SHannes Reinecke unsigned int sense_len = SCSI_SENSE_BUFFERSIZE; 206477266186SHannes Reinecke 206577266186SHannes Reinecke if (sense_len > cmd_blk->sense_len) 206677266186SHannes Reinecke sense_len = cmd_blk->sense_len; 206777266186SHannes Reinecke memcpy(scmd->sense_buffer, cmd_blk->sense, sense_len); 206877266186SHannes Reinecke } 206977266186SHannes Reinecke dma_pool_free(cs->sense_pool, cmd_blk->sense, 207077266186SHannes Reinecke cmd_blk->sense_addr); 207177266186SHannes Reinecke cmd_blk->sense = NULL; 207277266186SHannes Reinecke cmd_blk->sense_addr = 0; 207377266186SHannes Reinecke } 207477266186SHannes Reinecke if (cmd_blk->dcdb) { 207577266186SHannes Reinecke dma_pool_free(cs->dcdb_pool, cmd_blk->dcdb, 207677266186SHannes Reinecke cmd_blk->dcdb_dma); 207777266186SHannes Reinecke cmd_blk->dcdb = NULL; 207877266186SHannes Reinecke cmd_blk->dcdb_dma = 0; 207977266186SHannes Reinecke } 208077266186SHannes Reinecke if (cmd_blk->sgl) { 208177266186SHannes Reinecke dma_pool_free(cs->sg_pool, cmd_blk->sgl, 208277266186SHannes Reinecke cmd_blk->sgl_addr); 208377266186SHannes Reinecke cmd_blk->sgl = NULL; 208477266186SHannes Reinecke cmd_blk->sgl_addr = 0; 208577266186SHannes Reinecke } 208677266186SHannes Reinecke if (cmd_blk->residual) 208777266186SHannes Reinecke scsi_set_resid(scmd, cmd_blk->residual); 208877266186SHannes Reinecke if (status == MYRS_STATUS_DEVICE_NON_RESPONSIVE || 208977266186SHannes Reinecke status == MYRS_STATUS_DEVICE_NON_RESPONSIVE2) 209077266186SHannes Reinecke scmd->result = (DID_BAD_TARGET << 16); 209177266186SHannes Reinecke else 20929a231caaSDan Carpenter scmd->result = (DID_OK << 16) | status; 209377266186SHannes Reinecke scmd->scsi_done(scmd); 209477266186SHannes Reinecke } 209577266186SHannes Reinecke 209677266186SHannes Reinecke static void myrs_handle_cmdblk(struct myrs_hba *cs, struct myrs_cmdblk *cmd_blk) 209777266186SHannes Reinecke { 209877266186SHannes Reinecke if (!cmd_blk) 209977266186SHannes Reinecke return; 210077266186SHannes Reinecke 210177266186SHannes Reinecke if (cmd_blk->complete) { 210277266186SHannes Reinecke complete(cmd_blk->complete); 210377266186SHannes Reinecke cmd_blk->complete = NULL; 210477266186SHannes Reinecke } 210577266186SHannes Reinecke } 210677266186SHannes Reinecke 210777266186SHannes Reinecke static void myrs_monitor(struct work_struct *work) 210877266186SHannes Reinecke { 210977266186SHannes Reinecke struct myrs_hba *cs = container_of(work, struct myrs_hba, 211077266186SHannes Reinecke monitor_work.work); 211177266186SHannes Reinecke struct Scsi_Host *shost = cs->host; 211277266186SHannes Reinecke struct myrs_ctlr_info *info = cs->ctlr_info; 211377266186SHannes Reinecke unsigned int epoch = cs->fwstat_buf->epoch; 211477266186SHannes Reinecke unsigned long interval = MYRS_PRIMARY_MONITOR_INTERVAL; 211577266186SHannes Reinecke unsigned char status; 211677266186SHannes Reinecke 211777266186SHannes Reinecke dev_dbg(&shost->shost_gendev, "monitor tick\n"); 211877266186SHannes Reinecke 211977266186SHannes Reinecke status = myrs_get_fwstatus(cs); 212077266186SHannes Reinecke 212177266186SHannes Reinecke if (cs->needs_update) { 212277266186SHannes Reinecke cs->needs_update = false; 212377266186SHannes Reinecke mutex_lock(&cs->cinfo_mutex); 212477266186SHannes Reinecke status = myrs_get_ctlr_info(cs); 212577266186SHannes Reinecke mutex_unlock(&cs->cinfo_mutex); 212677266186SHannes Reinecke } 212777266186SHannes Reinecke if (cs->fwstat_buf->next_evseq - cs->next_evseq > 0) { 212877266186SHannes Reinecke status = myrs_get_event(cs, cs->next_evseq, 212977266186SHannes Reinecke cs->event_buf); 213077266186SHannes Reinecke if (status == MYRS_STATUS_SUCCESS) { 213177266186SHannes Reinecke myrs_log_event(cs, cs->event_buf); 213277266186SHannes Reinecke cs->next_evseq++; 213377266186SHannes Reinecke interval = 1; 213477266186SHannes Reinecke } 213577266186SHannes Reinecke } 213677266186SHannes Reinecke 213777266186SHannes Reinecke if (time_after(jiffies, cs->secondary_monitor_time 213877266186SHannes Reinecke + MYRS_SECONDARY_MONITOR_INTERVAL)) 213977266186SHannes Reinecke cs->secondary_monitor_time = jiffies; 214077266186SHannes Reinecke 214177266186SHannes Reinecke if (info->bg_init_active + 214277266186SHannes Reinecke info->ldev_init_active + 214377266186SHannes Reinecke info->pdev_init_active + 214477266186SHannes Reinecke info->cc_active + 214577266186SHannes Reinecke info->rbld_active + 214677266186SHannes Reinecke info->exp_active != 0) { 214777266186SHannes Reinecke struct scsi_device *sdev; 214877266186SHannes Reinecke 214977266186SHannes Reinecke shost_for_each_device(sdev, shost) { 215077266186SHannes Reinecke struct myrs_ldev_info *ldev_info; 215177266186SHannes Reinecke int ldev_num; 215277266186SHannes Reinecke 215377266186SHannes Reinecke if (sdev->channel < info->physchan_present) 215477266186SHannes Reinecke continue; 215577266186SHannes Reinecke ldev_info = sdev->hostdata; 215677266186SHannes Reinecke if (!ldev_info) 215777266186SHannes Reinecke continue; 215877266186SHannes Reinecke ldev_num = ldev_info->ldev_num; 215977266186SHannes Reinecke myrs_get_ldev_info(cs, ldev_num, ldev_info); 216077266186SHannes Reinecke } 216177266186SHannes Reinecke cs->needs_update = true; 216277266186SHannes Reinecke } 216377266186SHannes Reinecke if (epoch == cs->epoch && 216477266186SHannes Reinecke cs->fwstat_buf->next_evseq == cs->next_evseq && 216577266186SHannes Reinecke (cs->needs_update == false || 216677266186SHannes Reinecke time_before(jiffies, cs->primary_monitor_time 216777266186SHannes Reinecke + MYRS_PRIMARY_MONITOR_INTERVAL))) { 216877266186SHannes Reinecke interval = MYRS_SECONDARY_MONITOR_INTERVAL; 216977266186SHannes Reinecke } 217077266186SHannes Reinecke 217177266186SHannes Reinecke if (interval > 1) 217277266186SHannes Reinecke cs->primary_monitor_time = jiffies; 217377266186SHannes Reinecke queue_delayed_work(cs->work_q, &cs->monitor_work, interval); 217477266186SHannes Reinecke } 217577266186SHannes Reinecke 217677266186SHannes Reinecke static bool myrs_create_mempools(struct pci_dev *pdev, struct myrs_hba *cs) 217777266186SHannes Reinecke { 217877266186SHannes Reinecke struct Scsi_Host *shost = cs->host; 217977266186SHannes Reinecke size_t elem_size, elem_align; 218077266186SHannes Reinecke 218177266186SHannes Reinecke elem_align = sizeof(struct myrs_sge); 218277266186SHannes Reinecke elem_size = shost->sg_tablesize * elem_align; 218377266186SHannes Reinecke cs->sg_pool = dma_pool_create("myrs_sg", &pdev->dev, 218477266186SHannes Reinecke elem_size, elem_align, 0); 218577266186SHannes Reinecke if (cs->sg_pool == NULL) { 218677266186SHannes Reinecke shost_printk(KERN_ERR, shost, 218777266186SHannes Reinecke "Failed to allocate SG pool\n"); 218877266186SHannes Reinecke return false; 218977266186SHannes Reinecke } 219077266186SHannes Reinecke 219177266186SHannes Reinecke cs->sense_pool = dma_pool_create("myrs_sense", &pdev->dev, 219277266186SHannes Reinecke MYRS_SENSE_SIZE, sizeof(int), 0); 219377266186SHannes Reinecke if (cs->sense_pool == NULL) { 219477266186SHannes Reinecke dma_pool_destroy(cs->sg_pool); 219577266186SHannes Reinecke cs->sg_pool = NULL; 219677266186SHannes Reinecke shost_printk(KERN_ERR, shost, 219777266186SHannes Reinecke "Failed to allocate sense data pool\n"); 219877266186SHannes Reinecke return false; 219977266186SHannes Reinecke } 220077266186SHannes Reinecke 220177266186SHannes Reinecke cs->dcdb_pool = dma_pool_create("myrs_dcdb", &pdev->dev, 220277266186SHannes Reinecke MYRS_DCDB_SIZE, 220377266186SHannes Reinecke sizeof(unsigned char), 0); 220477266186SHannes Reinecke if (!cs->dcdb_pool) { 220577266186SHannes Reinecke dma_pool_destroy(cs->sg_pool); 220677266186SHannes Reinecke cs->sg_pool = NULL; 220777266186SHannes Reinecke dma_pool_destroy(cs->sense_pool); 220877266186SHannes Reinecke cs->sense_pool = NULL; 220977266186SHannes Reinecke shost_printk(KERN_ERR, shost, 221077266186SHannes Reinecke "Failed to allocate DCDB pool\n"); 221177266186SHannes Reinecke return false; 221277266186SHannes Reinecke } 221377266186SHannes Reinecke 221477266186SHannes Reinecke snprintf(cs->work_q_name, sizeof(cs->work_q_name), 221577266186SHannes Reinecke "myrs_wq_%d", shost->host_no); 221677266186SHannes Reinecke cs->work_q = create_singlethread_workqueue(cs->work_q_name); 221777266186SHannes Reinecke if (!cs->work_q) { 221877266186SHannes Reinecke dma_pool_destroy(cs->dcdb_pool); 221977266186SHannes Reinecke cs->dcdb_pool = NULL; 222077266186SHannes Reinecke dma_pool_destroy(cs->sg_pool); 222177266186SHannes Reinecke cs->sg_pool = NULL; 222277266186SHannes Reinecke dma_pool_destroy(cs->sense_pool); 222377266186SHannes Reinecke cs->sense_pool = NULL; 222477266186SHannes Reinecke shost_printk(KERN_ERR, shost, 222577266186SHannes Reinecke "Failed to create workqueue\n"); 222677266186SHannes Reinecke return false; 222777266186SHannes Reinecke } 222877266186SHannes Reinecke 222977266186SHannes Reinecke /* Initialize the Monitoring Timer. */ 223077266186SHannes Reinecke INIT_DELAYED_WORK(&cs->monitor_work, myrs_monitor); 223177266186SHannes Reinecke queue_delayed_work(cs->work_q, &cs->monitor_work, 1); 223277266186SHannes Reinecke 223377266186SHannes Reinecke return true; 223477266186SHannes Reinecke } 223577266186SHannes Reinecke 223677266186SHannes Reinecke static void myrs_destroy_mempools(struct myrs_hba *cs) 223777266186SHannes Reinecke { 223877266186SHannes Reinecke cancel_delayed_work_sync(&cs->monitor_work); 223977266186SHannes Reinecke destroy_workqueue(cs->work_q); 224077266186SHannes Reinecke 224177266186SHannes Reinecke dma_pool_destroy(cs->sg_pool); 224277266186SHannes Reinecke dma_pool_destroy(cs->dcdb_pool); 224377266186SHannes Reinecke dma_pool_destroy(cs->sense_pool); 224477266186SHannes Reinecke } 224577266186SHannes Reinecke 224677266186SHannes Reinecke static void myrs_unmap(struct myrs_hba *cs) 224777266186SHannes Reinecke { 224877266186SHannes Reinecke kfree(cs->event_buf); 224977266186SHannes Reinecke kfree(cs->ctlr_info); 225077266186SHannes Reinecke if (cs->fwstat_buf) { 225177266186SHannes Reinecke dma_free_coherent(&cs->pdev->dev, sizeof(struct myrs_fwstat), 225277266186SHannes Reinecke cs->fwstat_buf, cs->fwstat_addr); 225377266186SHannes Reinecke cs->fwstat_buf = NULL; 225477266186SHannes Reinecke } 225577266186SHannes Reinecke if (cs->first_stat_mbox) { 225677266186SHannes Reinecke dma_free_coherent(&cs->pdev->dev, cs->stat_mbox_size, 225777266186SHannes Reinecke cs->first_stat_mbox, cs->stat_mbox_addr); 225877266186SHannes Reinecke cs->first_stat_mbox = NULL; 225977266186SHannes Reinecke } 226077266186SHannes Reinecke if (cs->first_cmd_mbox) { 226177266186SHannes Reinecke dma_free_coherent(&cs->pdev->dev, cs->cmd_mbox_size, 226277266186SHannes Reinecke cs->first_cmd_mbox, cs->cmd_mbox_addr); 226377266186SHannes Reinecke cs->first_cmd_mbox = NULL; 226477266186SHannes Reinecke } 226577266186SHannes Reinecke } 226677266186SHannes Reinecke 226777266186SHannes Reinecke static void myrs_cleanup(struct myrs_hba *cs) 226877266186SHannes Reinecke { 226977266186SHannes Reinecke struct pci_dev *pdev = cs->pdev; 227077266186SHannes Reinecke 227177266186SHannes Reinecke /* Free the memory mailbox, status, and related structures */ 227277266186SHannes Reinecke myrs_unmap(cs); 227377266186SHannes Reinecke 227477266186SHannes Reinecke if (cs->mmio_base) { 227577266186SHannes Reinecke cs->disable_intr(cs); 227677266186SHannes Reinecke iounmap(cs->mmio_base); 227777266186SHannes Reinecke } 227877266186SHannes Reinecke if (cs->irq) 227977266186SHannes Reinecke free_irq(cs->irq, cs); 228077266186SHannes Reinecke if (cs->io_addr) 228177266186SHannes Reinecke release_region(cs->io_addr, 0x80); 228277266186SHannes Reinecke iounmap(cs->mmio_base); 228377266186SHannes Reinecke pci_set_drvdata(pdev, NULL); 228477266186SHannes Reinecke pci_disable_device(pdev); 228577266186SHannes Reinecke scsi_host_put(cs->host); 228677266186SHannes Reinecke } 228777266186SHannes Reinecke 228877266186SHannes Reinecke static struct myrs_hba *myrs_detect(struct pci_dev *pdev, 228977266186SHannes Reinecke const struct pci_device_id *entry) 229077266186SHannes Reinecke { 229177266186SHannes Reinecke struct myrs_privdata *privdata = 229277266186SHannes Reinecke (struct myrs_privdata *)entry->driver_data; 229377266186SHannes Reinecke irq_handler_t irq_handler = privdata->irq_handler; 229477266186SHannes Reinecke unsigned int mmio_size = privdata->mmio_size; 229577266186SHannes Reinecke struct myrs_hba *cs = NULL; 229677266186SHannes Reinecke 229777266186SHannes Reinecke cs = myrs_alloc_host(pdev, entry); 229877266186SHannes Reinecke if (!cs) { 229977266186SHannes Reinecke dev_err(&pdev->dev, "Unable to allocate Controller\n"); 230077266186SHannes Reinecke return NULL; 230177266186SHannes Reinecke } 230277266186SHannes Reinecke cs->pdev = pdev; 230377266186SHannes Reinecke 230477266186SHannes Reinecke if (pci_enable_device(pdev)) 230577266186SHannes Reinecke goto Failure; 230677266186SHannes Reinecke 230777266186SHannes Reinecke cs->pci_addr = pci_resource_start(pdev, 0); 230877266186SHannes Reinecke 230977266186SHannes Reinecke pci_set_drvdata(pdev, cs); 231077266186SHannes Reinecke spin_lock_init(&cs->queue_lock); 231177266186SHannes Reinecke /* Map the Controller Register Window. */ 231277266186SHannes Reinecke if (mmio_size < PAGE_SIZE) 231377266186SHannes Reinecke mmio_size = PAGE_SIZE; 23144bdc0d67SChristoph Hellwig cs->mmio_base = ioremap(cs->pci_addr & PAGE_MASK, mmio_size); 231577266186SHannes Reinecke if (cs->mmio_base == NULL) { 231677266186SHannes Reinecke dev_err(&pdev->dev, 231777266186SHannes Reinecke "Unable to map Controller Register Window\n"); 231877266186SHannes Reinecke goto Failure; 231977266186SHannes Reinecke } 232077266186SHannes Reinecke 232177266186SHannes Reinecke cs->io_base = cs->mmio_base + (cs->pci_addr & ~PAGE_MASK); 232277266186SHannes Reinecke if (privdata->hw_init(pdev, cs, cs->io_base)) 232377266186SHannes Reinecke goto Failure; 232477266186SHannes Reinecke 232577266186SHannes Reinecke /* Acquire shared access to the IRQ Channel. */ 232677266186SHannes Reinecke if (request_irq(pdev->irq, irq_handler, IRQF_SHARED, "myrs", cs) < 0) { 232777266186SHannes Reinecke dev_err(&pdev->dev, 232877266186SHannes Reinecke "Unable to acquire IRQ Channel %d\n", pdev->irq); 232977266186SHannes Reinecke goto Failure; 233077266186SHannes Reinecke } 233177266186SHannes Reinecke cs->irq = pdev->irq; 233277266186SHannes Reinecke return cs; 233377266186SHannes Reinecke 233477266186SHannes Reinecke Failure: 233577266186SHannes Reinecke dev_err(&pdev->dev, 233677266186SHannes Reinecke "Failed to initialize Controller\n"); 233777266186SHannes Reinecke myrs_cleanup(cs); 233877266186SHannes Reinecke return NULL; 233977266186SHannes Reinecke } 234077266186SHannes Reinecke 23418a692fdbSLee Jones /* 234277266186SHannes Reinecke * myrs_err_status reports Controller BIOS Messages passed through 23438a692fdbSLee Jones * the Error Status Register when the driver performs the BIOS handshaking. 23448a692fdbSLee Jones * It returns true for fatal errors and false otherwise. 234577266186SHannes Reinecke */ 234677266186SHannes Reinecke 234777266186SHannes Reinecke static bool myrs_err_status(struct myrs_hba *cs, unsigned char status, 234877266186SHannes Reinecke unsigned char parm0, unsigned char parm1) 234977266186SHannes Reinecke { 235077266186SHannes Reinecke struct pci_dev *pdev = cs->pdev; 235177266186SHannes Reinecke 235277266186SHannes Reinecke switch (status) { 235377266186SHannes Reinecke case 0x00: 235477266186SHannes Reinecke dev_info(&pdev->dev, 235577266186SHannes Reinecke "Physical Device %d:%d Not Responding\n", 235677266186SHannes Reinecke parm1, parm0); 235777266186SHannes Reinecke break; 235877266186SHannes Reinecke case 0x08: 235977266186SHannes Reinecke dev_notice(&pdev->dev, "Spinning Up Drives\n"); 236077266186SHannes Reinecke break; 236177266186SHannes Reinecke case 0x30: 236277266186SHannes Reinecke dev_notice(&pdev->dev, "Configuration Checksum Error\n"); 236377266186SHannes Reinecke break; 236477266186SHannes Reinecke case 0x60: 236577266186SHannes Reinecke dev_notice(&pdev->dev, "Mirror Race Recovery Failed\n"); 236677266186SHannes Reinecke break; 236777266186SHannes Reinecke case 0x70: 236877266186SHannes Reinecke dev_notice(&pdev->dev, "Mirror Race Recovery In Progress\n"); 236977266186SHannes Reinecke break; 237077266186SHannes Reinecke case 0x90: 237177266186SHannes Reinecke dev_notice(&pdev->dev, "Physical Device %d:%d COD Mismatch\n", 237277266186SHannes Reinecke parm1, parm0); 237377266186SHannes Reinecke break; 237477266186SHannes Reinecke case 0xA0: 237577266186SHannes Reinecke dev_notice(&pdev->dev, "Logical Drive Installation Aborted\n"); 237677266186SHannes Reinecke break; 237777266186SHannes Reinecke case 0xB0: 237877266186SHannes Reinecke dev_notice(&pdev->dev, "Mirror Race On A Critical Logical Drive\n"); 237977266186SHannes Reinecke break; 238077266186SHannes Reinecke case 0xD0: 238177266186SHannes Reinecke dev_notice(&pdev->dev, "New Controller Configuration Found\n"); 238277266186SHannes Reinecke break; 238377266186SHannes Reinecke case 0xF0: 238477266186SHannes Reinecke dev_err(&pdev->dev, "Fatal Memory Parity Error\n"); 238577266186SHannes Reinecke return true; 238677266186SHannes Reinecke default: 238777266186SHannes Reinecke dev_err(&pdev->dev, "Unknown Initialization Error %02X\n", 238877266186SHannes Reinecke status); 238977266186SHannes Reinecke return true; 239077266186SHannes Reinecke } 239177266186SHannes Reinecke return false; 239277266186SHannes Reinecke } 239377266186SHannes Reinecke 239477266186SHannes Reinecke /* 239577266186SHannes Reinecke * Hardware-specific functions 239677266186SHannes Reinecke */ 239777266186SHannes Reinecke 239877266186SHannes Reinecke /* 239977266186SHannes Reinecke * DAC960 GEM Series Controllers. 240077266186SHannes Reinecke */ 240177266186SHannes Reinecke 240277266186SHannes Reinecke static inline void DAC960_GEM_hw_mbox_new_cmd(void __iomem *base) 240377266186SHannes Reinecke { 240477266186SHannes Reinecke __le32 val = cpu_to_le32(DAC960_GEM_IDB_HWMBOX_NEW_CMD << 24); 240577266186SHannes Reinecke 240677266186SHannes Reinecke writel(val, base + DAC960_GEM_IDB_READ_OFFSET); 240777266186SHannes Reinecke } 240877266186SHannes Reinecke 240977266186SHannes Reinecke static inline void DAC960_GEM_ack_hw_mbox_status(void __iomem *base) 241077266186SHannes Reinecke { 241177266186SHannes Reinecke __le32 val = cpu_to_le32(DAC960_GEM_IDB_HWMBOX_ACK_STS << 24); 241277266186SHannes Reinecke 241377266186SHannes Reinecke writel(val, base + DAC960_GEM_IDB_CLEAR_OFFSET); 241477266186SHannes Reinecke } 241577266186SHannes Reinecke 241677266186SHannes Reinecke static inline void DAC960_GEM_gen_intr(void __iomem *base) 241777266186SHannes Reinecke { 241877266186SHannes Reinecke __le32 val = cpu_to_le32(DAC960_GEM_IDB_GEN_IRQ << 24); 241977266186SHannes Reinecke 242077266186SHannes Reinecke writel(val, base + DAC960_GEM_IDB_READ_OFFSET); 242177266186SHannes Reinecke } 242277266186SHannes Reinecke 242377266186SHannes Reinecke static inline void DAC960_GEM_reset_ctrl(void __iomem *base) 242477266186SHannes Reinecke { 242577266186SHannes Reinecke __le32 val = cpu_to_le32(DAC960_GEM_IDB_CTRL_RESET << 24); 242677266186SHannes Reinecke 242777266186SHannes Reinecke writel(val, base + DAC960_GEM_IDB_READ_OFFSET); 242877266186SHannes Reinecke } 242977266186SHannes Reinecke 243077266186SHannes Reinecke static inline void DAC960_GEM_mem_mbox_new_cmd(void __iomem *base) 243177266186SHannes Reinecke { 243277266186SHannes Reinecke __le32 val = cpu_to_le32(DAC960_GEM_IDB_HWMBOX_NEW_CMD << 24); 243377266186SHannes Reinecke 243477266186SHannes Reinecke writel(val, base + DAC960_GEM_IDB_READ_OFFSET); 243577266186SHannes Reinecke } 243677266186SHannes Reinecke 243777266186SHannes Reinecke static inline bool DAC960_GEM_hw_mbox_is_full(void __iomem *base) 243877266186SHannes Reinecke { 243977266186SHannes Reinecke __le32 val; 244077266186SHannes Reinecke 244177266186SHannes Reinecke val = readl(base + DAC960_GEM_IDB_READ_OFFSET); 244277266186SHannes Reinecke return (le32_to_cpu(val) >> 24) & DAC960_GEM_IDB_HWMBOX_FULL; 244377266186SHannes Reinecke } 244477266186SHannes Reinecke 244577266186SHannes Reinecke static inline bool DAC960_GEM_init_in_progress(void __iomem *base) 244677266186SHannes Reinecke { 244777266186SHannes Reinecke __le32 val; 244877266186SHannes Reinecke 244977266186SHannes Reinecke val = readl(base + DAC960_GEM_IDB_READ_OFFSET); 245077266186SHannes Reinecke return (le32_to_cpu(val) >> 24) & DAC960_GEM_IDB_INIT_IN_PROGRESS; 245177266186SHannes Reinecke } 245277266186SHannes Reinecke 245377266186SHannes Reinecke static inline void DAC960_GEM_ack_hw_mbox_intr(void __iomem *base) 245477266186SHannes Reinecke { 245577266186SHannes Reinecke __le32 val = cpu_to_le32(DAC960_GEM_ODB_HWMBOX_ACK_IRQ << 24); 245677266186SHannes Reinecke 245777266186SHannes Reinecke writel(val, base + DAC960_GEM_ODB_CLEAR_OFFSET); 245877266186SHannes Reinecke } 245977266186SHannes Reinecke 246077266186SHannes Reinecke static inline void DAC960_GEM_ack_mem_mbox_intr(void __iomem *base) 246177266186SHannes Reinecke { 246277266186SHannes Reinecke __le32 val = cpu_to_le32(DAC960_GEM_ODB_MMBOX_ACK_IRQ << 24); 246377266186SHannes Reinecke 246477266186SHannes Reinecke writel(val, base + DAC960_GEM_ODB_CLEAR_OFFSET); 246577266186SHannes Reinecke } 246677266186SHannes Reinecke 246777266186SHannes Reinecke static inline void DAC960_GEM_ack_intr(void __iomem *base) 246877266186SHannes Reinecke { 246977266186SHannes Reinecke __le32 val = cpu_to_le32((DAC960_GEM_ODB_HWMBOX_ACK_IRQ | 247077266186SHannes Reinecke DAC960_GEM_ODB_MMBOX_ACK_IRQ) << 24); 247177266186SHannes Reinecke 247277266186SHannes Reinecke writel(val, base + DAC960_GEM_ODB_CLEAR_OFFSET); 247377266186SHannes Reinecke } 247477266186SHannes Reinecke 247577266186SHannes Reinecke static inline bool DAC960_GEM_hw_mbox_status_available(void __iomem *base) 247677266186SHannes Reinecke { 247777266186SHannes Reinecke __le32 val; 247877266186SHannes Reinecke 247977266186SHannes Reinecke val = readl(base + DAC960_GEM_ODB_READ_OFFSET); 248077266186SHannes Reinecke return (le32_to_cpu(val) >> 24) & DAC960_GEM_ODB_HWMBOX_STS_AVAIL; 248177266186SHannes Reinecke } 248277266186SHannes Reinecke 248377266186SHannes Reinecke static inline bool DAC960_GEM_mem_mbox_status_available(void __iomem *base) 248477266186SHannes Reinecke { 248577266186SHannes Reinecke __le32 val; 248677266186SHannes Reinecke 248777266186SHannes Reinecke val = readl(base + DAC960_GEM_ODB_READ_OFFSET); 248877266186SHannes Reinecke return (le32_to_cpu(val) >> 24) & DAC960_GEM_ODB_MMBOX_STS_AVAIL; 248977266186SHannes Reinecke } 249077266186SHannes Reinecke 249177266186SHannes Reinecke static inline void DAC960_GEM_enable_intr(void __iomem *base) 249277266186SHannes Reinecke { 249377266186SHannes Reinecke __le32 val = cpu_to_le32((DAC960_GEM_IRQMASK_HWMBOX_IRQ | 249477266186SHannes Reinecke DAC960_GEM_IRQMASK_MMBOX_IRQ) << 24); 249577266186SHannes Reinecke writel(val, base + DAC960_GEM_IRQMASK_CLEAR_OFFSET); 249677266186SHannes Reinecke } 249777266186SHannes Reinecke 249877266186SHannes Reinecke static inline void DAC960_GEM_disable_intr(void __iomem *base) 249977266186SHannes Reinecke { 250077266186SHannes Reinecke __le32 val = 0; 250177266186SHannes Reinecke 250277266186SHannes Reinecke writel(val, base + DAC960_GEM_IRQMASK_READ_OFFSET); 250377266186SHannes Reinecke } 250477266186SHannes Reinecke 250577266186SHannes Reinecke static inline bool DAC960_GEM_intr_enabled(void __iomem *base) 250677266186SHannes Reinecke { 250777266186SHannes Reinecke __le32 val; 250877266186SHannes Reinecke 250977266186SHannes Reinecke val = readl(base + DAC960_GEM_IRQMASK_READ_OFFSET); 251077266186SHannes Reinecke return !((le32_to_cpu(val) >> 24) & 251177266186SHannes Reinecke (DAC960_GEM_IRQMASK_HWMBOX_IRQ | 251277266186SHannes Reinecke DAC960_GEM_IRQMASK_MMBOX_IRQ)); 251377266186SHannes Reinecke } 251477266186SHannes Reinecke 251577266186SHannes Reinecke static inline void DAC960_GEM_write_cmd_mbox(union myrs_cmd_mbox *mem_mbox, 251677266186SHannes Reinecke union myrs_cmd_mbox *mbox) 251777266186SHannes Reinecke { 251877266186SHannes Reinecke memcpy(&mem_mbox->words[1], &mbox->words[1], 251977266186SHannes Reinecke sizeof(union myrs_cmd_mbox) - sizeof(unsigned int)); 252077266186SHannes Reinecke /* Barrier to avoid reordering */ 252177266186SHannes Reinecke wmb(); 252277266186SHannes Reinecke mem_mbox->words[0] = mbox->words[0]; 252377266186SHannes Reinecke /* Barrier to force PCI access */ 252477266186SHannes Reinecke mb(); 252577266186SHannes Reinecke } 252677266186SHannes Reinecke 252777266186SHannes Reinecke static inline void DAC960_GEM_write_hw_mbox(void __iomem *base, 252877266186SHannes Reinecke dma_addr_t cmd_mbox_addr) 252977266186SHannes Reinecke { 253077266186SHannes Reinecke dma_addr_writeql(cmd_mbox_addr, base + DAC960_GEM_CMDMBX_OFFSET); 253177266186SHannes Reinecke } 253277266186SHannes Reinecke 253377266186SHannes Reinecke static inline unsigned short DAC960_GEM_read_cmd_ident(void __iomem *base) 253477266186SHannes Reinecke { 253577266186SHannes Reinecke return readw(base + DAC960_GEM_CMDSTS_OFFSET); 253677266186SHannes Reinecke } 253777266186SHannes Reinecke 253877266186SHannes Reinecke static inline unsigned char DAC960_GEM_read_cmd_status(void __iomem *base) 253977266186SHannes Reinecke { 254077266186SHannes Reinecke return readw(base + DAC960_GEM_CMDSTS_OFFSET + 2); 254177266186SHannes Reinecke } 254277266186SHannes Reinecke 254377266186SHannes Reinecke static inline bool 254477266186SHannes Reinecke DAC960_GEM_read_error_status(void __iomem *base, unsigned char *error, 254577266186SHannes Reinecke unsigned char *param0, unsigned char *param1) 254677266186SHannes Reinecke { 254777266186SHannes Reinecke __le32 val; 254877266186SHannes Reinecke 254977266186SHannes Reinecke val = readl(base + DAC960_GEM_ERRSTS_READ_OFFSET); 255077266186SHannes Reinecke if (!((le32_to_cpu(val) >> 24) & DAC960_GEM_ERRSTS_PENDING)) 255177266186SHannes Reinecke return false; 255277266186SHannes Reinecke *error = val & ~(DAC960_GEM_ERRSTS_PENDING << 24); 255377266186SHannes Reinecke *param0 = readb(base + DAC960_GEM_CMDMBX_OFFSET + 0); 255477266186SHannes Reinecke *param1 = readb(base + DAC960_GEM_CMDMBX_OFFSET + 1); 255577266186SHannes Reinecke writel(0x03000000, base + DAC960_GEM_ERRSTS_CLEAR_OFFSET); 255677266186SHannes Reinecke return true; 255777266186SHannes Reinecke } 255877266186SHannes Reinecke 255977266186SHannes Reinecke static inline unsigned char 256077266186SHannes Reinecke DAC960_GEM_mbox_init(void __iomem *base, dma_addr_t mbox_addr) 256177266186SHannes Reinecke { 256277266186SHannes Reinecke unsigned char status; 256377266186SHannes Reinecke 256477266186SHannes Reinecke while (DAC960_GEM_hw_mbox_is_full(base)) 256577266186SHannes Reinecke udelay(1); 256677266186SHannes Reinecke DAC960_GEM_write_hw_mbox(base, mbox_addr); 256777266186SHannes Reinecke DAC960_GEM_hw_mbox_new_cmd(base); 256877266186SHannes Reinecke while (!DAC960_GEM_hw_mbox_status_available(base)) 256977266186SHannes Reinecke udelay(1); 257077266186SHannes Reinecke status = DAC960_GEM_read_cmd_status(base); 257177266186SHannes Reinecke DAC960_GEM_ack_hw_mbox_intr(base); 257277266186SHannes Reinecke DAC960_GEM_ack_hw_mbox_status(base); 257377266186SHannes Reinecke 257477266186SHannes Reinecke return status; 257577266186SHannes Reinecke } 257677266186SHannes Reinecke 257777266186SHannes Reinecke static int DAC960_GEM_hw_init(struct pci_dev *pdev, 257877266186SHannes Reinecke struct myrs_hba *cs, void __iomem *base) 257977266186SHannes Reinecke { 258077266186SHannes Reinecke int timeout = 0; 258177266186SHannes Reinecke unsigned char status, parm0, parm1; 258277266186SHannes Reinecke 258377266186SHannes Reinecke DAC960_GEM_disable_intr(base); 258477266186SHannes Reinecke DAC960_GEM_ack_hw_mbox_status(base); 258577266186SHannes Reinecke udelay(1000); 258677266186SHannes Reinecke while (DAC960_GEM_init_in_progress(base) && 258777266186SHannes Reinecke timeout < MYRS_MAILBOX_TIMEOUT) { 258877266186SHannes Reinecke if (DAC960_GEM_read_error_status(base, &status, 258977266186SHannes Reinecke &parm0, &parm1) && 259077266186SHannes Reinecke myrs_err_status(cs, status, parm0, parm1)) 259177266186SHannes Reinecke return -EIO; 259277266186SHannes Reinecke udelay(10); 259377266186SHannes Reinecke timeout++; 259477266186SHannes Reinecke } 259577266186SHannes Reinecke if (timeout == MYRS_MAILBOX_TIMEOUT) { 259677266186SHannes Reinecke dev_err(&pdev->dev, 259777266186SHannes Reinecke "Timeout waiting for Controller Initialisation\n"); 259877266186SHannes Reinecke return -ETIMEDOUT; 259977266186SHannes Reinecke } 260077266186SHannes Reinecke if (!myrs_enable_mmio_mbox(cs, DAC960_GEM_mbox_init)) { 260177266186SHannes Reinecke dev_err(&pdev->dev, 260277266186SHannes Reinecke "Unable to Enable Memory Mailbox Interface\n"); 260377266186SHannes Reinecke DAC960_GEM_reset_ctrl(base); 260477266186SHannes Reinecke return -EAGAIN; 260577266186SHannes Reinecke } 260677266186SHannes Reinecke DAC960_GEM_enable_intr(base); 260777266186SHannes Reinecke cs->write_cmd_mbox = DAC960_GEM_write_cmd_mbox; 260877266186SHannes Reinecke cs->get_cmd_mbox = DAC960_GEM_mem_mbox_new_cmd; 260977266186SHannes Reinecke cs->disable_intr = DAC960_GEM_disable_intr; 261077266186SHannes Reinecke cs->reset = DAC960_GEM_reset_ctrl; 261177266186SHannes Reinecke return 0; 261277266186SHannes Reinecke } 261377266186SHannes Reinecke 261477266186SHannes Reinecke static irqreturn_t DAC960_GEM_intr_handler(int irq, void *arg) 261577266186SHannes Reinecke { 261677266186SHannes Reinecke struct myrs_hba *cs = arg; 261777266186SHannes Reinecke void __iomem *base = cs->io_base; 261877266186SHannes Reinecke struct myrs_stat_mbox *next_stat_mbox; 261977266186SHannes Reinecke unsigned long flags; 262077266186SHannes Reinecke 262177266186SHannes Reinecke spin_lock_irqsave(&cs->queue_lock, flags); 262277266186SHannes Reinecke DAC960_GEM_ack_intr(base); 262377266186SHannes Reinecke next_stat_mbox = cs->next_stat_mbox; 262477266186SHannes Reinecke while (next_stat_mbox->id > 0) { 262577266186SHannes Reinecke unsigned short id = next_stat_mbox->id; 262677266186SHannes Reinecke struct scsi_cmnd *scmd = NULL; 262777266186SHannes Reinecke struct myrs_cmdblk *cmd_blk = NULL; 262877266186SHannes Reinecke 262977266186SHannes Reinecke if (id == MYRS_DCMD_TAG) 263077266186SHannes Reinecke cmd_blk = &cs->dcmd_blk; 263177266186SHannes Reinecke else if (id == MYRS_MCMD_TAG) 263277266186SHannes Reinecke cmd_blk = &cs->mcmd_blk; 263377266186SHannes Reinecke else { 263477266186SHannes Reinecke scmd = scsi_host_find_tag(cs->host, id - 3); 263577266186SHannes Reinecke if (scmd) 263677266186SHannes Reinecke cmd_blk = scsi_cmd_priv(scmd); 263777266186SHannes Reinecke } 263877266186SHannes Reinecke if (cmd_blk) { 263977266186SHannes Reinecke cmd_blk->status = next_stat_mbox->status; 264077266186SHannes Reinecke cmd_blk->sense_len = next_stat_mbox->sense_len; 264177266186SHannes Reinecke cmd_blk->residual = next_stat_mbox->residual; 264277266186SHannes Reinecke } else 264377266186SHannes Reinecke dev_err(&cs->pdev->dev, 264477266186SHannes Reinecke "Unhandled command completion %d\n", id); 264577266186SHannes Reinecke 264677266186SHannes Reinecke memset(next_stat_mbox, 0, sizeof(struct myrs_stat_mbox)); 264777266186SHannes Reinecke if (++next_stat_mbox > cs->last_stat_mbox) 264877266186SHannes Reinecke next_stat_mbox = cs->first_stat_mbox; 264977266186SHannes Reinecke 265077266186SHannes Reinecke if (cmd_blk) { 265177266186SHannes Reinecke if (id < 3) 265277266186SHannes Reinecke myrs_handle_cmdblk(cs, cmd_blk); 265377266186SHannes Reinecke else 265477266186SHannes Reinecke myrs_handle_scsi(cs, cmd_blk, scmd); 265577266186SHannes Reinecke } 265677266186SHannes Reinecke } 265777266186SHannes Reinecke cs->next_stat_mbox = next_stat_mbox; 265877266186SHannes Reinecke spin_unlock_irqrestore(&cs->queue_lock, flags); 265977266186SHannes Reinecke return IRQ_HANDLED; 266077266186SHannes Reinecke } 266177266186SHannes Reinecke 266277266186SHannes Reinecke struct myrs_privdata DAC960_GEM_privdata = { 266377266186SHannes Reinecke .hw_init = DAC960_GEM_hw_init, 266477266186SHannes Reinecke .irq_handler = DAC960_GEM_intr_handler, 266577266186SHannes Reinecke .mmio_size = DAC960_GEM_mmio_size, 266677266186SHannes Reinecke }; 266777266186SHannes Reinecke 266877266186SHannes Reinecke /* 266977266186SHannes Reinecke * DAC960 BA Series Controllers. 267077266186SHannes Reinecke */ 267177266186SHannes Reinecke 267277266186SHannes Reinecke static inline void DAC960_BA_hw_mbox_new_cmd(void __iomem *base) 267377266186SHannes Reinecke { 267477266186SHannes Reinecke writeb(DAC960_BA_IDB_HWMBOX_NEW_CMD, base + DAC960_BA_IDB_OFFSET); 267577266186SHannes Reinecke } 267677266186SHannes Reinecke 267777266186SHannes Reinecke static inline void DAC960_BA_ack_hw_mbox_status(void __iomem *base) 267877266186SHannes Reinecke { 267977266186SHannes Reinecke writeb(DAC960_BA_IDB_HWMBOX_ACK_STS, base + DAC960_BA_IDB_OFFSET); 268077266186SHannes Reinecke } 268177266186SHannes Reinecke 268277266186SHannes Reinecke static inline void DAC960_BA_gen_intr(void __iomem *base) 268377266186SHannes Reinecke { 268477266186SHannes Reinecke writeb(DAC960_BA_IDB_GEN_IRQ, base + DAC960_BA_IDB_OFFSET); 268577266186SHannes Reinecke } 268677266186SHannes Reinecke 268777266186SHannes Reinecke static inline void DAC960_BA_reset_ctrl(void __iomem *base) 268877266186SHannes Reinecke { 268977266186SHannes Reinecke writeb(DAC960_BA_IDB_CTRL_RESET, base + DAC960_BA_IDB_OFFSET); 269077266186SHannes Reinecke } 269177266186SHannes Reinecke 269277266186SHannes Reinecke static inline void DAC960_BA_mem_mbox_new_cmd(void __iomem *base) 269377266186SHannes Reinecke { 269477266186SHannes Reinecke writeb(DAC960_BA_IDB_MMBOX_NEW_CMD, base + DAC960_BA_IDB_OFFSET); 269577266186SHannes Reinecke } 269677266186SHannes Reinecke 269777266186SHannes Reinecke static inline bool DAC960_BA_hw_mbox_is_full(void __iomem *base) 269877266186SHannes Reinecke { 269977266186SHannes Reinecke u8 val; 270077266186SHannes Reinecke 270177266186SHannes Reinecke val = readb(base + DAC960_BA_IDB_OFFSET); 270277266186SHannes Reinecke return !(val & DAC960_BA_IDB_HWMBOX_EMPTY); 270377266186SHannes Reinecke } 270477266186SHannes Reinecke 270577266186SHannes Reinecke static inline bool DAC960_BA_init_in_progress(void __iomem *base) 270677266186SHannes Reinecke { 270777266186SHannes Reinecke u8 val; 270877266186SHannes Reinecke 270977266186SHannes Reinecke val = readb(base + DAC960_BA_IDB_OFFSET); 271077266186SHannes Reinecke return !(val & DAC960_BA_IDB_INIT_DONE); 271177266186SHannes Reinecke } 271277266186SHannes Reinecke 271377266186SHannes Reinecke static inline void DAC960_BA_ack_hw_mbox_intr(void __iomem *base) 271477266186SHannes Reinecke { 271577266186SHannes Reinecke writeb(DAC960_BA_ODB_HWMBOX_ACK_IRQ, base + DAC960_BA_ODB_OFFSET); 271677266186SHannes Reinecke } 271777266186SHannes Reinecke 271877266186SHannes Reinecke static inline void DAC960_BA_ack_mem_mbox_intr(void __iomem *base) 271977266186SHannes Reinecke { 272077266186SHannes Reinecke writeb(DAC960_BA_ODB_MMBOX_ACK_IRQ, base + DAC960_BA_ODB_OFFSET); 272177266186SHannes Reinecke } 272277266186SHannes Reinecke 272377266186SHannes Reinecke static inline void DAC960_BA_ack_intr(void __iomem *base) 272477266186SHannes Reinecke { 272577266186SHannes Reinecke writeb(DAC960_BA_ODB_HWMBOX_ACK_IRQ | DAC960_BA_ODB_MMBOX_ACK_IRQ, 272677266186SHannes Reinecke base + DAC960_BA_ODB_OFFSET); 272777266186SHannes Reinecke } 272877266186SHannes Reinecke 272977266186SHannes Reinecke static inline bool DAC960_BA_hw_mbox_status_available(void __iomem *base) 273077266186SHannes Reinecke { 273177266186SHannes Reinecke u8 val; 273277266186SHannes Reinecke 273377266186SHannes Reinecke val = readb(base + DAC960_BA_ODB_OFFSET); 273477266186SHannes Reinecke return val & DAC960_BA_ODB_HWMBOX_STS_AVAIL; 273577266186SHannes Reinecke } 273677266186SHannes Reinecke 273777266186SHannes Reinecke static inline bool DAC960_BA_mem_mbox_status_available(void __iomem *base) 273877266186SHannes Reinecke { 273977266186SHannes Reinecke u8 val; 274077266186SHannes Reinecke 274177266186SHannes Reinecke val = readb(base + DAC960_BA_ODB_OFFSET); 274277266186SHannes Reinecke return val & DAC960_BA_ODB_MMBOX_STS_AVAIL; 274377266186SHannes Reinecke } 274477266186SHannes Reinecke 274577266186SHannes Reinecke static inline void DAC960_BA_enable_intr(void __iomem *base) 274677266186SHannes Reinecke { 274777266186SHannes Reinecke writeb(~DAC960_BA_IRQMASK_DISABLE_IRQ, base + DAC960_BA_IRQMASK_OFFSET); 274877266186SHannes Reinecke } 274977266186SHannes Reinecke 275077266186SHannes Reinecke static inline void DAC960_BA_disable_intr(void __iomem *base) 275177266186SHannes Reinecke { 275277266186SHannes Reinecke writeb(0xFF, base + DAC960_BA_IRQMASK_OFFSET); 275377266186SHannes Reinecke } 275477266186SHannes Reinecke 275577266186SHannes Reinecke static inline bool DAC960_BA_intr_enabled(void __iomem *base) 275677266186SHannes Reinecke { 275777266186SHannes Reinecke u8 val; 275877266186SHannes Reinecke 275977266186SHannes Reinecke val = readb(base + DAC960_BA_IRQMASK_OFFSET); 276077266186SHannes Reinecke return !(val & DAC960_BA_IRQMASK_DISABLE_IRQ); 276177266186SHannes Reinecke } 276277266186SHannes Reinecke 276377266186SHannes Reinecke static inline void DAC960_BA_write_cmd_mbox(union myrs_cmd_mbox *mem_mbox, 276477266186SHannes Reinecke union myrs_cmd_mbox *mbox) 276577266186SHannes Reinecke { 276677266186SHannes Reinecke memcpy(&mem_mbox->words[1], &mbox->words[1], 276777266186SHannes Reinecke sizeof(union myrs_cmd_mbox) - sizeof(unsigned int)); 276877266186SHannes Reinecke /* Barrier to avoid reordering */ 276977266186SHannes Reinecke wmb(); 277077266186SHannes Reinecke mem_mbox->words[0] = mbox->words[0]; 277177266186SHannes Reinecke /* Barrier to force PCI access */ 277277266186SHannes Reinecke mb(); 277377266186SHannes Reinecke } 277477266186SHannes Reinecke 277577266186SHannes Reinecke 277677266186SHannes Reinecke static inline void DAC960_BA_write_hw_mbox(void __iomem *base, 277777266186SHannes Reinecke dma_addr_t cmd_mbox_addr) 277877266186SHannes Reinecke { 277977266186SHannes Reinecke dma_addr_writeql(cmd_mbox_addr, base + DAC960_BA_CMDMBX_OFFSET); 278077266186SHannes Reinecke } 278177266186SHannes Reinecke 278277266186SHannes Reinecke static inline unsigned short DAC960_BA_read_cmd_ident(void __iomem *base) 278377266186SHannes Reinecke { 278477266186SHannes Reinecke return readw(base + DAC960_BA_CMDSTS_OFFSET); 278577266186SHannes Reinecke } 278677266186SHannes Reinecke 278777266186SHannes Reinecke static inline unsigned char DAC960_BA_read_cmd_status(void __iomem *base) 278877266186SHannes Reinecke { 278977266186SHannes Reinecke return readw(base + DAC960_BA_CMDSTS_OFFSET + 2); 279077266186SHannes Reinecke } 279177266186SHannes Reinecke 279277266186SHannes Reinecke static inline bool 279377266186SHannes Reinecke DAC960_BA_read_error_status(void __iomem *base, unsigned char *error, 279477266186SHannes Reinecke unsigned char *param0, unsigned char *param1) 279577266186SHannes Reinecke { 279677266186SHannes Reinecke u8 val; 279777266186SHannes Reinecke 279877266186SHannes Reinecke val = readb(base + DAC960_BA_ERRSTS_OFFSET); 279977266186SHannes Reinecke if (!(val & DAC960_BA_ERRSTS_PENDING)) 280077266186SHannes Reinecke return false; 280177266186SHannes Reinecke val &= ~DAC960_BA_ERRSTS_PENDING; 280277266186SHannes Reinecke *error = val; 280377266186SHannes Reinecke *param0 = readb(base + DAC960_BA_CMDMBX_OFFSET + 0); 280477266186SHannes Reinecke *param1 = readb(base + DAC960_BA_CMDMBX_OFFSET + 1); 280577266186SHannes Reinecke writeb(0xFF, base + DAC960_BA_ERRSTS_OFFSET); 280677266186SHannes Reinecke return true; 280777266186SHannes Reinecke } 280877266186SHannes Reinecke 280977266186SHannes Reinecke static inline unsigned char 281077266186SHannes Reinecke DAC960_BA_mbox_init(void __iomem *base, dma_addr_t mbox_addr) 281177266186SHannes Reinecke { 281277266186SHannes Reinecke unsigned char status; 281377266186SHannes Reinecke 281477266186SHannes Reinecke while (DAC960_BA_hw_mbox_is_full(base)) 281577266186SHannes Reinecke udelay(1); 281677266186SHannes Reinecke DAC960_BA_write_hw_mbox(base, mbox_addr); 281777266186SHannes Reinecke DAC960_BA_hw_mbox_new_cmd(base); 281877266186SHannes Reinecke while (!DAC960_BA_hw_mbox_status_available(base)) 281977266186SHannes Reinecke udelay(1); 282077266186SHannes Reinecke status = DAC960_BA_read_cmd_status(base); 282177266186SHannes Reinecke DAC960_BA_ack_hw_mbox_intr(base); 282277266186SHannes Reinecke DAC960_BA_ack_hw_mbox_status(base); 282377266186SHannes Reinecke 282477266186SHannes Reinecke return status; 282577266186SHannes Reinecke } 282677266186SHannes Reinecke 282777266186SHannes Reinecke static int DAC960_BA_hw_init(struct pci_dev *pdev, 282877266186SHannes Reinecke struct myrs_hba *cs, void __iomem *base) 282977266186SHannes Reinecke { 283077266186SHannes Reinecke int timeout = 0; 283177266186SHannes Reinecke unsigned char status, parm0, parm1; 283277266186SHannes Reinecke 283377266186SHannes Reinecke DAC960_BA_disable_intr(base); 283477266186SHannes Reinecke DAC960_BA_ack_hw_mbox_status(base); 283577266186SHannes Reinecke udelay(1000); 283677266186SHannes Reinecke while (DAC960_BA_init_in_progress(base) && 283777266186SHannes Reinecke timeout < MYRS_MAILBOX_TIMEOUT) { 283877266186SHannes Reinecke if (DAC960_BA_read_error_status(base, &status, 283977266186SHannes Reinecke &parm0, &parm1) && 284077266186SHannes Reinecke myrs_err_status(cs, status, parm0, parm1)) 284177266186SHannes Reinecke return -EIO; 284277266186SHannes Reinecke udelay(10); 284377266186SHannes Reinecke timeout++; 284477266186SHannes Reinecke } 284577266186SHannes Reinecke if (timeout == MYRS_MAILBOX_TIMEOUT) { 284677266186SHannes Reinecke dev_err(&pdev->dev, 284777266186SHannes Reinecke "Timeout waiting for Controller Initialisation\n"); 284877266186SHannes Reinecke return -ETIMEDOUT; 284977266186SHannes Reinecke } 285077266186SHannes Reinecke if (!myrs_enable_mmio_mbox(cs, DAC960_BA_mbox_init)) { 285177266186SHannes Reinecke dev_err(&pdev->dev, 285277266186SHannes Reinecke "Unable to Enable Memory Mailbox Interface\n"); 285377266186SHannes Reinecke DAC960_BA_reset_ctrl(base); 285477266186SHannes Reinecke return -EAGAIN; 285577266186SHannes Reinecke } 285677266186SHannes Reinecke DAC960_BA_enable_intr(base); 285777266186SHannes Reinecke cs->write_cmd_mbox = DAC960_BA_write_cmd_mbox; 285877266186SHannes Reinecke cs->get_cmd_mbox = DAC960_BA_mem_mbox_new_cmd; 285977266186SHannes Reinecke cs->disable_intr = DAC960_BA_disable_intr; 286077266186SHannes Reinecke cs->reset = DAC960_BA_reset_ctrl; 286177266186SHannes Reinecke return 0; 286277266186SHannes Reinecke } 286377266186SHannes Reinecke 286477266186SHannes Reinecke static irqreturn_t DAC960_BA_intr_handler(int irq, void *arg) 286577266186SHannes Reinecke { 286677266186SHannes Reinecke struct myrs_hba *cs = arg; 286777266186SHannes Reinecke void __iomem *base = cs->io_base; 286877266186SHannes Reinecke struct myrs_stat_mbox *next_stat_mbox; 286977266186SHannes Reinecke unsigned long flags; 287077266186SHannes Reinecke 287177266186SHannes Reinecke spin_lock_irqsave(&cs->queue_lock, flags); 287277266186SHannes Reinecke DAC960_BA_ack_intr(base); 287377266186SHannes Reinecke next_stat_mbox = cs->next_stat_mbox; 287477266186SHannes Reinecke while (next_stat_mbox->id > 0) { 287577266186SHannes Reinecke unsigned short id = next_stat_mbox->id; 287677266186SHannes Reinecke struct scsi_cmnd *scmd = NULL; 287777266186SHannes Reinecke struct myrs_cmdblk *cmd_blk = NULL; 287877266186SHannes Reinecke 287977266186SHannes Reinecke if (id == MYRS_DCMD_TAG) 288077266186SHannes Reinecke cmd_blk = &cs->dcmd_blk; 288177266186SHannes Reinecke else if (id == MYRS_MCMD_TAG) 288277266186SHannes Reinecke cmd_blk = &cs->mcmd_blk; 288377266186SHannes Reinecke else { 288477266186SHannes Reinecke scmd = scsi_host_find_tag(cs->host, id - 3); 288577266186SHannes Reinecke if (scmd) 288677266186SHannes Reinecke cmd_blk = scsi_cmd_priv(scmd); 288777266186SHannes Reinecke } 288877266186SHannes Reinecke if (cmd_blk) { 288977266186SHannes Reinecke cmd_blk->status = next_stat_mbox->status; 289077266186SHannes Reinecke cmd_blk->sense_len = next_stat_mbox->sense_len; 289177266186SHannes Reinecke cmd_blk->residual = next_stat_mbox->residual; 289277266186SHannes Reinecke } else 289377266186SHannes Reinecke dev_err(&cs->pdev->dev, 289477266186SHannes Reinecke "Unhandled command completion %d\n", id); 289577266186SHannes Reinecke 289677266186SHannes Reinecke memset(next_stat_mbox, 0, sizeof(struct myrs_stat_mbox)); 289777266186SHannes Reinecke if (++next_stat_mbox > cs->last_stat_mbox) 289877266186SHannes Reinecke next_stat_mbox = cs->first_stat_mbox; 289977266186SHannes Reinecke 290077266186SHannes Reinecke if (cmd_blk) { 290177266186SHannes Reinecke if (id < 3) 290277266186SHannes Reinecke myrs_handle_cmdblk(cs, cmd_blk); 290377266186SHannes Reinecke else 290477266186SHannes Reinecke myrs_handle_scsi(cs, cmd_blk, scmd); 290577266186SHannes Reinecke } 290677266186SHannes Reinecke } 290777266186SHannes Reinecke cs->next_stat_mbox = next_stat_mbox; 290877266186SHannes Reinecke spin_unlock_irqrestore(&cs->queue_lock, flags); 290977266186SHannes Reinecke return IRQ_HANDLED; 291077266186SHannes Reinecke } 291177266186SHannes Reinecke 291277266186SHannes Reinecke struct myrs_privdata DAC960_BA_privdata = { 291377266186SHannes Reinecke .hw_init = DAC960_BA_hw_init, 291477266186SHannes Reinecke .irq_handler = DAC960_BA_intr_handler, 291577266186SHannes Reinecke .mmio_size = DAC960_BA_mmio_size, 291677266186SHannes Reinecke }; 291777266186SHannes Reinecke 291877266186SHannes Reinecke /* 291977266186SHannes Reinecke * DAC960 LP Series Controllers. 292077266186SHannes Reinecke */ 292177266186SHannes Reinecke 292277266186SHannes Reinecke static inline void DAC960_LP_hw_mbox_new_cmd(void __iomem *base) 292377266186SHannes Reinecke { 292477266186SHannes Reinecke writeb(DAC960_LP_IDB_HWMBOX_NEW_CMD, base + DAC960_LP_IDB_OFFSET); 292577266186SHannes Reinecke } 292677266186SHannes Reinecke 292777266186SHannes Reinecke static inline void DAC960_LP_ack_hw_mbox_status(void __iomem *base) 292877266186SHannes Reinecke { 292977266186SHannes Reinecke writeb(DAC960_LP_IDB_HWMBOX_ACK_STS, base + DAC960_LP_IDB_OFFSET); 293077266186SHannes Reinecke } 293177266186SHannes Reinecke 293277266186SHannes Reinecke static inline void DAC960_LP_gen_intr(void __iomem *base) 293377266186SHannes Reinecke { 293477266186SHannes Reinecke writeb(DAC960_LP_IDB_GEN_IRQ, base + DAC960_LP_IDB_OFFSET); 293577266186SHannes Reinecke } 293677266186SHannes Reinecke 293777266186SHannes Reinecke static inline void DAC960_LP_reset_ctrl(void __iomem *base) 293877266186SHannes Reinecke { 293977266186SHannes Reinecke writeb(DAC960_LP_IDB_CTRL_RESET, base + DAC960_LP_IDB_OFFSET); 294077266186SHannes Reinecke } 294177266186SHannes Reinecke 294277266186SHannes Reinecke static inline void DAC960_LP_mem_mbox_new_cmd(void __iomem *base) 294377266186SHannes Reinecke { 294477266186SHannes Reinecke writeb(DAC960_LP_IDB_MMBOX_NEW_CMD, base + DAC960_LP_IDB_OFFSET); 294577266186SHannes Reinecke } 294677266186SHannes Reinecke 294777266186SHannes Reinecke static inline bool DAC960_LP_hw_mbox_is_full(void __iomem *base) 294877266186SHannes Reinecke { 294977266186SHannes Reinecke u8 val; 295077266186SHannes Reinecke 295177266186SHannes Reinecke val = readb(base + DAC960_LP_IDB_OFFSET); 295277266186SHannes Reinecke return val & DAC960_LP_IDB_HWMBOX_FULL; 295377266186SHannes Reinecke } 295477266186SHannes Reinecke 295577266186SHannes Reinecke static inline bool DAC960_LP_init_in_progress(void __iomem *base) 295677266186SHannes Reinecke { 295777266186SHannes Reinecke u8 val; 295877266186SHannes Reinecke 295977266186SHannes Reinecke val = readb(base + DAC960_LP_IDB_OFFSET); 296077266186SHannes Reinecke return val & DAC960_LP_IDB_INIT_IN_PROGRESS; 296177266186SHannes Reinecke } 296277266186SHannes Reinecke 296377266186SHannes Reinecke static inline void DAC960_LP_ack_hw_mbox_intr(void __iomem *base) 296477266186SHannes Reinecke { 296577266186SHannes Reinecke writeb(DAC960_LP_ODB_HWMBOX_ACK_IRQ, base + DAC960_LP_ODB_OFFSET); 296677266186SHannes Reinecke } 296777266186SHannes Reinecke 296877266186SHannes Reinecke static inline void DAC960_LP_ack_mem_mbox_intr(void __iomem *base) 296977266186SHannes Reinecke { 297077266186SHannes Reinecke writeb(DAC960_LP_ODB_MMBOX_ACK_IRQ, base + DAC960_LP_ODB_OFFSET); 297177266186SHannes Reinecke } 297277266186SHannes Reinecke 297377266186SHannes Reinecke static inline void DAC960_LP_ack_intr(void __iomem *base) 297477266186SHannes Reinecke { 297577266186SHannes Reinecke writeb(DAC960_LP_ODB_HWMBOX_ACK_IRQ | DAC960_LP_ODB_MMBOX_ACK_IRQ, 297677266186SHannes Reinecke base + DAC960_LP_ODB_OFFSET); 297777266186SHannes Reinecke } 297877266186SHannes Reinecke 297977266186SHannes Reinecke static inline bool DAC960_LP_hw_mbox_status_available(void __iomem *base) 298077266186SHannes Reinecke { 298177266186SHannes Reinecke u8 val; 298277266186SHannes Reinecke 298377266186SHannes Reinecke val = readb(base + DAC960_LP_ODB_OFFSET); 298477266186SHannes Reinecke return val & DAC960_LP_ODB_HWMBOX_STS_AVAIL; 298577266186SHannes Reinecke } 298677266186SHannes Reinecke 298777266186SHannes Reinecke static inline bool DAC960_LP_mem_mbox_status_available(void __iomem *base) 298877266186SHannes Reinecke { 298977266186SHannes Reinecke u8 val; 299077266186SHannes Reinecke 299177266186SHannes Reinecke val = readb(base + DAC960_LP_ODB_OFFSET); 299277266186SHannes Reinecke return val & DAC960_LP_ODB_MMBOX_STS_AVAIL; 299377266186SHannes Reinecke } 299477266186SHannes Reinecke 299577266186SHannes Reinecke static inline void DAC960_LP_enable_intr(void __iomem *base) 299677266186SHannes Reinecke { 299777266186SHannes Reinecke writeb(~DAC960_LP_IRQMASK_DISABLE_IRQ, base + DAC960_LP_IRQMASK_OFFSET); 299877266186SHannes Reinecke } 299977266186SHannes Reinecke 300077266186SHannes Reinecke static inline void DAC960_LP_disable_intr(void __iomem *base) 300177266186SHannes Reinecke { 300277266186SHannes Reinecke writeb(0xFF, base + DAC960_LP_IRQMASK_OFFSET); 300377266186SHannes Reinecke } 300477266186SHannes Reinecke 300577266186SHannes Reinecke static inline bool DAC960_LP_intr_enabled(void __iomem *base) 300677266186SHannes Reinecke { 300777266186SHannes Reinecke u8 val; 300877266186SHannes Reinecke 300977266186SHannes Reinecke val = readb(base + DAC960_LP_IRQMASK_OFFSET); 301077266186SHannes Reinecke return !(val & DAC960_LP_IRQMASK_DISABLE_IRQ); 301177266186SHannes Reinecke } 301277266186SHannes Reinecke 301377266186SHannes Reinecke static inline void DAC960_LP_write_cmd_mbox(union myrs_cmd_mbox *mem_mbox, 301477266186SHannes Reinecke union myrs_cmd_mbox *mbox) 301577266186SHannes Reinecke { 301677266186SHannes Reinecke memcpy(&mem_mbox->words[1], &mbox->words[1], 301777266186SHannes Reinecke sizeof(union myrs_cmd_mbox) - sizeof(unsigned int)); 301877266186SHannes Reinecke /* Barrier to avoid reordering */ 301977266186SHannes Reinecke wmb(); 302077266186SHannes Reinecke mem_mbox->words[0] = mbox->words[0]; 302177266186SHannes Reinecke /* Barrier to force PCI access */ 302277266186SHannes Reinecke mb(); 302377266186SHannes Reinecke } 302477266186SHannes Reinecke 302577266186SHannes Reinecke static inline void DAC960_LP_write_hw_mbox(void __iomem *base, 302677266186SHannes Reinecke dma_addr_t cmd_mbox_addr) 302777266186SHannes Reinecke { 302877266186SHannes Reinecke dma_addr_writeql(cmd_mbox_addr, base + DAC960_LP_CMDMBX_OFFSET); 302977266186SHannes Reinecke } 303077266186SHannes Reinecke 303177266186SHannes Reinecke static inline unsigned short DAC960_LP_read_cmd_ident(void __iomem *base) 303277266186SHannes Reinecke { 303377266186SHannes Reinecke return readw(base + DAC960_LP_CMDSTS_OFFSET); 303477266186SHannes Reinecke } 303577266186SHannes Reinecke 303677266186SHannes Reinecke static inline unsigned char DAC960_LP_read_cmd_status(void __iomem *base) 303777266186SHannes Reinecke { 303877266186SHannes Reinecke return readw(base + DAC960_LP_CMDSTS_OFFSET + 2); 303977266186SHannes Reinecke } 304077266186SHannes Reinecke 304177266186SHannes Reinecke static inline bool 304277266186SHannes Reinecke DAC960_LP_read_error_status(void __iomem *base, unsigned char *error, 304377266186SHannes Reinecke unsigned char *param0, unsigned char *param1) 304477266186SHannes Reinecke { 304577266186SHannes Reinecke u8 val; 304677266186SHannes Reinecke 304777266186SHannes Reinecke val = readb(base + DAC960_LP_ERRSTS_OFFSET); 304877266186SHannes Reinecke if (!(val & DAC960_LP_ERRSTS_PENDING)) 304977266186SHannes Reinecke return false; 305077266186SHannes Reinecke val &= ~DAC960_LP_ERRSTS_PENDING; 305177266186SHannes Reinecke *error = val; 305277266186SHannes Reinecke *param0 = readb(base + DAC960_LP_CMDMBX_OFFSET + 0); 305377266186SHannes Reinecke *param1 = readb(base + DAC960_LP_CMDMBX_OFFSET + 1); 305477266186SHannes Reinecke writeb(0xFF, base + DAC960_LP_ERRSTS_OFFSET); 305577266186SHannes Reinecke return true; 305677266186SHannes Reinecke } 305777266186SHannes Reinecke 305877266186SHannes Reinecke static inline unsigned char 305977266186SHannes Reinecke DAC960_LP_mbox_init(void __iomem *base, dma_addr_t mbox_addr) 306077266186SHannes Reinecke { 306177266186SHannes Reinecke unsigned char status; 306277266186SHannes Reinecke 306377266186SHannes Reinecke while (DAC960_LP_hw_mbox_is_full(base)) 306477266186SHannes Reinecke udelay(1); 306577266186SHannes Reinecke DAC960_LP_write_hw_mbox(base, mbox_addr); 306677266186SHannes Reinecke DAC960_LP_hw_mbox_new_cmd(base); 306777266186SHannes Reinecke while (!DAC960_LP_hw_mbox_status_available(base)) 306877266186SHannes Reinecke udelay(1); 306977266186SHannes Reinecke status = DAC960_LP_read_cmd_status(base); 307077266186SHannes Reinecke DAC960_LP_ack_hw_mbox_intr(base); 307177266186SHannes Reinecke DAC960_LP_ack_hw_mbox_status(base); 307277266186SHannes Reinecke 307377266186SHannes Reinecke return status; 307477266186SHannes Reinecke } 307577266186SHannes Reinecke 307677266186SHannes Reinecke static int DAC960_LP_hw_init(struct pci_dev *pdev, 307777266186SHannes Reinecke struct myrs_hba *cs, void __iomem *base) 307877266186SHannes Reinecke { 307977266186SHannes Reinecke int timeout = 0; 308077266186SHannes Reinecke unsigned char status, parm0, parm1; 308177266186SHannes Reinecke 308277266186SHannes Reinecke DAC960_LP_disable_intr(base); 308377266186SHannes Reinecke DAC960_LP_ack_hw_mbox_status(base); 308477266186SHannes Reinecke udelay(1000); 308577266186SHannes Reinecke while (DAC960_LP_init_in_progress(base) && 308677266186SHannes Reinecke timeout < MYRS_MAILBOX_TIMEOUT) { 308777266186SHannes Reinecke if (DAC960_LP_read_error_status(base, &status, 308877266186SHannes Reinecke &parm0, &parm1) && 308977266186SHannes Reinecke myrs_err_status(cs, status, parm0, parm1)) 309077266186SHannes Reinecke return -EIO; 309177266186SHannes Reinecke udelay(10); 309277266186SHannes Reinecke timeout++; 309377266186SHannes Reinecke } 309477266186SHannes Reinecke if (timeout == MYRS_MAILBOX_TIMEOUT) { 309577266186SHannes Reinecke dev_err(&pdev->dev, 309677266186SHannes Reinecke "Timeout waiting for Controller Initialisation\n"); 309777266186SHannes Reinecke return -ETIMEDOUT; 309877266186SHannes Reinecke } 309977266186SHannes Reinecke if (!myrs_enable_mmio_mbox(cs, DAC960_LP_mbox_init)) { 310077266186SHannes Reinecke dev_err(&pdev->dev, 310177266186SHannes Reinecke "Unable to Enable Memory Mailbox Interface\n"); 310277266186SHannes Reinecke DAC960_LP_reset_ctrl(base); 310377266186SHannes Reinecke return -ENODEV; 310477266186SHannes Reinecke } 310577266186SHannes Reinecke DAC960_LP_enable_intr(base); 310677266186SHannes Reinecke cs->write_cmd_mbox = DAC960_LP_write_cmd_mbox; 310777266186SHannes Reinecke cs->get_cmd_mbox = DAC960_LP_mem_mbox_new_cmd; 310877266186SHannes Reinecke cs->disable_intr = DAC960_LP_disable_intr; 310977266186SHannes Reinecke cs->reset = DAC960_LP_reset_ctrl; 311077266186SHannes Reinecke 311177266186SHannes Reinecke return 0; 311277266186SHannes Reinecke } 311377266186SHannes Reinecke 311477266186SHannes Reinecke static irqreturn_t DAC960_LP_intr_handler(int irq, void *arg) 311577266186SHannes Reinecke { 311677266186SHannes Reinecke struct myrs_hba *cs = arg; 311777266186SHannes Reinecke void __iomem *base = cs->io_base; 311877266186SHannes Reinecke struct myrs_stat_mbox *next_stat_mbox; 311977266186SHannes Reinecke unsigned long flags; 312077266186SHannes Reinecke 312177266186SHannes Reinecke spin_lock_irqsave(&cs->queue_lock, flags); 312277266186SHannes Reinecke DAC960_LP_ack_intr(base); 312377266186SHannes Reinecke next_stat_mbox = cs->next_stat_mbox; 312477266186SHannes Reinecke while (next_stat_mbox->id > 0) { 312577266186SHannes Reinecke unsigned short id = next_stat_mbox->id; 312677266186SHannes Reinecke struct scsi_cmnd *scmd = NULL; 312777266186SHannes Reinecke struct myrs_cmdblk *cmd_blk = NULL; 312877266186SHannes Reinecke 312977266186SHannes Reinecke if (id == MYRS_DCMD_TAG) 313077266186SHannes Reinecke cmd_blk = &cs->dcmd_blk; 313177266186SHannes Reinecke else if (id == MYRS_MCMD_TAG) 313277266186SHannes Reinecke cmd_blk = &cs->mcmd_blk; 313377266186SHannes Reinecke else { 313477266186SHannes Reinecke scmd = scsi_host_find_tag(cs->host, id - 3); 313577266186SHannes Reinecke if (scmd) 313677266186SHannes Reinecke cmd_blk = scsi_cmd_priv(scmd); 313777266186SHannes Reinecke } 313877266186SHannes Reinecke if (cmd_blk) { 313977266186SHannes Reinecke cmd_blk->status = next_stat_mbox->status; 314077266186SHannes Reinecke cmd_blk->sense_len = next_stat_mbox->sense_len; 314177266186SHannes Reinecke cmd_blk->residual = next_stat_mbox->residual; 314277266186SHannes Reinecke } else 314377266186SHannes Reinecke dev_err(&cs->pdev->dev, 314477266186SHannes Reinecke "Unhandled command completion %d\n", id); 314577266186SHannes Reinecke 314677266186SHannes Reinecke memset(next_stat_mbox, 0, sizeof(struct myrs_stat_mbox)); 314777266186SHannes Reinecke if (++next_stat_mbox > cs->last_stat_mbox) 314877266186SHannes Reinecke next_stat_mbox = cs->first_stat_mbox; 314977266186SHannes Reinecke 315077266186SHannes Reinecke if (cmd_blk) { 315177266186SHannes Reinecke if (id < 3) 315277266186SHannes Reinecke myrs_handle_cmdblk(cs, cmd_blk); 315377266186SHannes Reinecke else 315477266186SHannes Reinecke myrs_handle_scsi(cs, cmd_blk, scmd); 315577266186SHannes Reinecke } 315677266186SHannes Reinecke } 315777266186SHannes Reinecke cs->next_stat_mbox = next_stat_mbox; 315877266186SHannes Reinecke spin_unlock_irqrestore(&cs->queue_lock, flags); 315977266186SHannes Reinecke return IRQ_HANDLED; 316077266186SHannes Reinecke } 316177266186SHannes Reinecke 316277266186SHannes Reinecke struct myrs_privdata DAC960_LP_privdata = { 316377266186SHannes Reinecke .hw_init = DAC960_LP_hw_init, 316477266186SHannes Reinecke .irq_handler = DAC960_LP_intr_handler, 316577266186SHannes Reinecke .mmio_size = DAC960_LP_mmio_size, 316677266186SHannes Reinecke }; 316777266186SHannes Reinecke 316877266186SHannes Reinecke /* 316977266186SHannes Reinecke * Module functions 317077266186SHannes Reinecke */ 317177266186SHannes Reinecke static int 317277266186SHannes Reinecke myrs_probe(struct pci_dev *dev, const struct pci_device_id *entry) 317377266186SHannes Reinecke { 317477266186SHannes Reinecke struct myrs_hba *cs; 317577266186SHannes Reinecke int ret; 317677266186SHannes Reinecke 317777266186SHannes Reinecke cs = myrs_detect(dev, entry); 317877266186SHannes Reinecke if (!cs) 317977266186SHannes Reinecke return -ENODEV; 318077266186SHannes Reinecke 318177266186SHannes Reinecke ret = myrs_get_config(cs); 318277266186SHannes Reinecke if (ret < 0) { 318377266186SHannes Reinecke myrs_cleanup(cs); 318477266186SHannes Reinecke return ret; 318577266186SHannes Reinecke } 318677266186SHannes Reinecke 318777266186SHannes Reinecke if (!myrs_create_mempools(dev, cs)) { 318877266186SHannes Reinecke ret = -ENOMEM; 318977266186SHannes Reinecke goto failed; 319077266186SHannes Reinecke } 319177266186SHannes Reinecke 319277266186SHannes Reinecke ret = scsi_add_host(cs->host, &dev->dev); 319377266186SHannes Reinecke if (ret) { 319477266186SHannes Reinecke dev_err(&dev->dev, "scsi_add_host failed with %d\n", ret); 319577266186SHannes Reinecke myrs_destroy_mempools(cs); 319677266186SHannes Reinecke goto failed; 319777266186SHannes Reinecke } 319877266186SHannes Reinecke scsi_scan_host(cs->host); 319977266186SHannes Reinecke return 0; 320077266186SHannes Reinecke failed: 320177266186SHannes Reinecke myrs_cleanup(cs); 320277266186SHannes Reinecke return ret; 320377266186SHannes Reinecke } 320477266186SHannes Reinecke 320577266186SHannes Reinecke 320677266186SHannes Reinecke static void myrs_remove(struct pci_dev *pdev) 320777266186SHannes Reinecke { 320877266186SHannes Reinecke struct myrs_hba *cs = pci_get_drvdata(pdev); 320977266186SHannes Reinecke 321077266186SHannes Reinecke if (cs == NULL) 321177266186SHannes Reinecke return; 321277266186SHannes Reinecke 321377266186SHannes Reinecke shost_printk(KERN_NOTICE, cs->host, "Flushing Cache..."); 321477266186SHannes Reinecke myrs_flush_cache(cs); 321577266186SHannes Reinecke myrs_destroy_mempools(cs); 321677266186SHannes Reinecke myrs_cleanup(cs); 321777266186SHannes Reinecke } 321877266186SHannes Reinecke 321977266186SHannes Reinecke 322077266186SHannes Reinecke static const struct pci_device_id myrs_id_table[] = { 322177266186SHannes Reinecke { 322277266186SHannes Reinecke PCI_DEVICE_SUB(PCI_VENDOR_ID_MYLEX, 322377266186SHannes Reinecke PCI_DEVICE_ID_MYLEX_DAC960_GEM, 322477266186SHannes Reinecke PCI_VENDOR_ID_MYLEX, PCI_ANY_ID), 322577266186SHannes Reinecke .driver_data = (unsigned long) &DAC960_GEM_privdata, 322677266186SHannes Reinecke }, 322777266186SHannes Reinecke { 322877266186SHannes Reinecke PCI_DEVICE_DATA(MYLEX, DAC960_BA, &DAC960_BA_privdata), 322977266186SHannes Reinecke }, 323077266186SHannes Reinecke { 323177266186SHannes Reinecke PCI_DEVICE_DATA(MYLEX, DAC960_LP, &DAC960_LP_privdata), 323277266186SHannes Reinecke }, 323377266186SHannes Reinecke {0, }, 323477266186SHannes Reinecke }; 323577266186SHannes Reinecke 323677266186SHannes Reinecke MODULE_DEVICE_TABLE(pci, myrs_id_table); 323777266186SHannes Reinecke 323877266186SHannes Reinecke static struct pci_driver myrs_pci_driver = { 323977266186SHannes Reinecke .name = "myrs", 324077266186SHannes Reinecke .id_table = myrs_id_table, 324177266186SHannes Reinecke .probe = myrs_probe, 324277266186SHannes Reinecke .remove = myrs_remove, 324377266186SHannes Reinecke }; 324477266186SHannes Reinecke 324577266186SHannes Reinecke static int __init myrs_init_module(void) 324677266186SHannes Reinecke { 324777266186SHannes Reinecke int ret; 324877266186SHannes Reinecke 324977266186SHannes Reinecke myrs_raid_template = raid_class_attach(&myrs_raid_functions); 325077266186SHannes Reinecke if (!myrs_raid_template) 325177266186SHannes Reinecke return -ENODEV; 325277266186SHannes Reinecke 325377266186SHannes Reinecke ret = pci_register_driver(&myrs_pci_driver); 325477266186SHannes Reinecke if (ret) 325577266186SHannes Reinecke raid_class_release(myrs_raid_template); 325677266186SHannes Reinecke 325777266186SHannes Reinecke return ret; 325877266186SHannes Reinecke } 325977266186SHannes Reinecke 326077266186SHannes Reinecke static void __exit myrs_cleanup_module(void) 326177266186SHannes Reinecke { 326277266186SHannes Reinecke pci_unregister_driver(&myrs_pci_driver); 326377266186SHannes Reinecke raid_class_release(myrs_raid_template); 326477266186SHannes Reinecke } 326577266186SHannes Reinecke 326677266186SHannes Reinecke module_init(myrs_init_module); 326777266186SHannes Reinecke module_exit(myrs_cleanup_module); 326877266186SHannes Reinecke 326977266186SHannes Reinecke MODULE_DESCRIPTION("Mylex DAC960/AcceleRAID/eXtremeRAID driver (SCSI Interface)"); 327077266186SHannes Reinecke MODULE_AUTHOR("Hannes Reinecke <hare@suse.com>"); 327177266186SHannes Reinecke MODULE_LICENSE("GPL"); 3272