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