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