^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1) /* ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2) * Adaptec AIC79xx device driver for Linux. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 3) * ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 4) * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.c#171 $ ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 5) * ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 6) * -------------------------------------------------------------------------- ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 7) * Copyright (c) 1994-2000 Justin T. Gibbs. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 8) * Copyright (c) 1997-1999 Doug Ledford ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 9) * Copyright (c) 2000-2003 Adaptec Inc. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 10) * All rights reserved. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 11) * ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 12) * Redistribution and use in source and binary forms, with or without ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 13) * modification, are permitted provided that the following conditions ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 14) * are met: ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 15) * 1. Redistributions of source code must retain the above copyright ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 16) * notice, this list of conditions, and the following disclaimer, ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 17) * without modification. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 18) * 2. Redistributions in binary form must reproduce at minimum a disclaimer ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 19) * substantially similar to the "NO WARRANTY" disclaimer below ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 20) * ("Disclaimer") and any redistribution must be conditioned upon ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 21) * including a substantially similar Disclaimer requirement for further ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 22) * binary redistribution. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 23) * 3. Neither the names of the above-listed copyright holders nor the names ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 24) * of any contributors may be used to endorse or promote products derived ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 25) * from this software without specific prior written permission. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 26) * ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 27) * Alternatively, this software may be distributed under the terms of the ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 28) * GNU General Public License ("GPL") version 2 as published by the Free ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 29) * Software Foundation. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 30) * ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 31) * NO WARRANTY ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 32) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 33) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 34) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 35) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 36) * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 37) * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 38) * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 39) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 40) * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 41) * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 42) * POSSIBILITY OF SUCH DAMAGES. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 43) */ ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 44) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 45) #include "aic79xx_osm.h" ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 46) #include "aic79xx_inline.h" ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 47) #include ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 48) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 49) static struct scsi_transport_template *ahd_linux_transport_template = NULL; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 50) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 51) #include /* __setup */ ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 52) #include /* For fetching system memory size */ 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 53) #include /* For block_size() */ ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 54) #include /* For ssleep/msleep */ 017560fca496f (Jeff Garzik 2005-10-24 18:04:36 -0400 55) #include 5a0e3ad6af866 (Tejun Heo 2010-03-24 17:04:11 +0900 56) #include ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 57) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 58) /* ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 59) * Bucket size for counting good commands in between bad ones. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 60) */ ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 61) #define AHD_LINUX_ERR_THRESH 1000 ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 62) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 63) /* ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 64) * Set this to the delay in seconds after SCSI bus reset. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 65) * Note, we honor this only for the initial bus reset. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 66) * The scsi error recovery code performs its own bus settle ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 67) * delay handling for error recovery actions. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 68) */ ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 69) #ifdef CONFIG_AIC79XX_RESET_DELAY_MS ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 70) #define AIC79XX_RESET_DELAY CONFIG_AIC79XX_RESET_DELAY_MS ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 71) #else ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 72) #define AIC79XX_RESET_DELAY 5000 ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 73) #endif ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 74) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 75) /* ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 76) * To change the default number of tagged transactions allowed per-device, ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 77) * add a line to the lilo.conf file like: ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 78) * append="aic79xx=verbose,tag_info:{{32,32,32,32},{32,32,32,32}}" ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 79) * which will result in the first four devices on the first two ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 80) * controllers being set to a tagged queue depth of 32. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 81) * ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 82) * The tag_commands is an array of 16 to allow for wide and twin adapters. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 83) * Twin adapters will use indexes 0-7 for channel 0, and indexes 8-15 ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 84) * for channel 1. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 85) */ ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 86) typedef struct { ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 87) uint16_t tag_commands[16]; /* Allow for wide/twin adapters. */ ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 88) } adapter_tag_info_t; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 89) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 90) /* ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 91) * Modify this as you see fit for your system. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 92) * ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 93) * 0 tagged queuing disabled ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 94) * 1 <= n <= 253 n == max tags ever dispatched. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 95) * ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 96) * The driver will throttle the number of commands dispatched to a ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 97) * device if it returns queue full. For devices with a fixed maximum ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 98) * queue depth, the driver will eventually determine this depth and ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 99) * lock it in (a console message is printed to indicate that a lock ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 100) * has occurred). On some devices, queue full is returned for a temporary ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 101) * resource shortage. These devices will return queue full at varying ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 102) * depths. The driver will throttle back when the queue fulls occur and ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 103) * attempt to slowly increase the depth over time as the device recovers ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 104) * from the resource shortage. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 105) * ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 106) * In this example, the first line will disable tagged queueing for all ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 107) * the devices on the first probed aic79xx adapter. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 108) * ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 109) * The second line enables tagged queueing with 4 commands/LUN for IDs ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 110) * (0, 2-11, 13-15), disables tagged queueing for ID 12, and tells the ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 111) * driver to attempt to use up to 64 tags for ID 1. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 112) * ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 113) * The third line is the same as the first line. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 114) * ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 115) * The fourth line disables tagged queueing for devices 0 and 3. It ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 116) * enables tagged queueing for the other IDs, with 16 commands/LUN ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 117) * for IDs 1 and 4, 127 commands/LUN for ID 8, and 4 commands/LUN for ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 118) * IDs 2, 5-7, and 9-15. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 119) */ ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 120) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 121) /* ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 122) * NOTE: The below structure is for reference only, the actual structure ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 123) * to modify in order to change things is just below this comment block. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 124) adapter_tag_info_t aic79xx_tag_info[] = ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 125) { ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 126) {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 127) {{4, 64, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 4}}, ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 128) {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 129) {{0, 16, 4, 0, 16, 4, 4, 4, 127, 4, 4, 4, 4, 4, 4, 4}} ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 130) }; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 131) */ ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 132) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 133) #ifdef CONFIG_AIC79XX_CMDS_PER_DEVICE ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 134) #define AIC79XX_CMDS_PER_DEVICE CONFIG_AIC79XX_CMDS_PER_DEVICE ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 135) #else ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 136) #define AIC79XX_CMDS_PER_DEVICE AHD_MAX_QUEUE ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 137) #endif ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 138) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 139) #define AIC79XX_CONFIGED_TAG_COMMANDS { \ ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 140) AIC79XX_CMDS_PER_DEVICE, AIC79XX_CMDS_PER_DEVICE, \ ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 141) AIC79XX_CMDS_PER_DEVICE, AIC79XX_CMDS_PER_DEVICE, \ ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 142) AIC79XX_CMDS_PER_DEVICE, AIC79XX_CMDS_PER_DEVICE, \ ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 143) AIC79XX_CMDS_PER_DEVICE, AIC79XX_CMDS_PER_DEVICE, \ ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 144) AIC79XX_CMDS_PER_DEVICE, AIC79XX_CMDS_PER_DEVICE, \ ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 145) AIC79XX_CMDS_PER_DEVICE, AIC79XX_CMDS_PER_DEVICE, \ ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 146) AIC79XX_CMDS_PER_DEVICE, AIC79XX_CMDS_PER_DEVICE, \ ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 147) AIC79XX_CMDS_PER_DEVICE, AIC79XX_CMDS_PER_DEVICE \ ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 148) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 149) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 150) /* ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 151) * By default, use the number of commands specified by ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 152) * the users kernel configuration. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 153) */ ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 154) static adapter_tag_info_t aic79xx_tag_info[] = ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 155) { ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 156) {AIC79XX_CONFIGED_TAG_COMMANDS}, ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 157) {AIC79XX_CONFIGED_TAG_COMMANDS}, ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 158) {AIC79XX_CONFIGED_TAG_COMMANDS}, ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 159) {AIC79XX_CONFIGED_TAG_COMMANDS}, ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 160) {AIC79XX_CONFIGED_TAG_COMMANDS}, ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 161) {AIC79XX_CONFIGED_TAG_COMMANDS}, ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 162) {AIC79XX_CONFIGED_TAG_COMMANDS}, ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 163) {AIC79XX_CONFIGED_TAG_COMMANDS}, ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 164) {AIC79XX_CONFIGED_TAG_COMMANDS}, ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 165) {AIC79XX_CONFIGED_TAG_COMMANDS}, ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 166) {AIC79XX_CONFIGED_TAG_COMMANDS}, ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 167) {AIC79XX_CONFIGED_TAG_COMMANDS}, ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 168) {AIC79XX_CONFIGED_TAG_COMMANDS}, ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 169) {AIC79XX_CONFIGED_TAG_COMMANDS}, ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 170) {AIC79XX_CONFIGED_TAG_COMMANDS}, ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 171) {AIC79XX_CONFIGED_TAG_COMMANDS} ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 172) }; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 173) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 174) /* ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 175) * The I/O cell on the chip is very configurable in respect to its analog ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 176) * characteristics. Set the defaults here; they can be overriden with ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 177) * the proper insmod parameters. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 178) */ ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 179) struct ahd_linux_iocell_opts ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 180) { ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 181) uint8_t precomp; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 182) uint8_t slewrate; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 183) uint8_t amplitude; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 184) }; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 185) #define AIC79XX_DEFAULT_PRECOMP 0xFF ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 186) #define AIC79XX_DEFAULT_SLEWRATE 0xFF ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 187) #define AIC79XX_DEFAULT_AMPLITUDE 0xFF ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 188) #define AIC79XX_DEFAULT_IOOPTS \ ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 189) { \ ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 190) AIC79XX_DEFAULT_PRECOMP, \ ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 191) AIC79XX_DEFAULT_SLEWRATE, \ ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 192) AIC79XX_DEFAULT_AMPLITUDE \ ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 193) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 194) #define AIC79XX_PRECOMP_INDEX 0 ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 195) #define AIC79XX_SLEWRATE_INDEX 1 ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 196) #define AIC79XX_AMPLITUDE_INDEX 2 980b306a29772 (Denys Vlasenko 2008-04-25 04:36:01 +0200 197) static const struct ahd_linux_iocell_opts aic79xx_iocell_info[] = ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 198) { ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 199) AIC79XX_DEFAULT_IOOPTS, ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 200) AIC79XX_DEFAULT_IOOPTS, ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 201) AIC79XX_DEFAULT_IOOPTS, ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 202) AIC79XX_DEFAULT_IOOPTS, ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 203) AIC79XX_DEFAULT_IOOPTS, ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 204) AIC79XX_DEFAULT_IOOPTS, ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 205) AIC79XX_DEFAULT_IOOPTS, ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 206) AIC79XX_DEFAULT_IOOPTS, ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 207) AIC79XX_DEFAULT_IOOPTS, ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 208) AIC79XX_DEFAULT_IOOPTS, ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 209) AIC79XX_DEFAULT_IOOPTS, ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 210) AIC79XX_DEFAULT_IOOPTS, ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 211) AIC79XX_DEFAULT_IOOPTS, ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 212) AIC79XX_DEFAULT_IOOPTS, ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 213) AIC79XX_DEFAULT_IOOPTS, ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 214) AIC79XX_DEFAULT_IOOPTS ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 215) }; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 216) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 217) /* ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 218) * There should be a specific return value for this in scsi.h, but ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 219) * it seems that most drivers ignore it. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 220) */ ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 221) #define DID_UNDERFLOW DID_ERROR ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 222) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 223) void ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 224) ahd_print_path(struct ahd_softc *ahd, struct scb *scb) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 225) { ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 226) printk("(scsi%d:%c:%d:%d): ", ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 227) ahd->platform_data->host->host_no, ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 228) scb != NULL ? SCB_GET_CHANNEL(ahd, scb) : 'X', ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 229) scb != NULL ? SCB_GET_TARGET(ahd, scb) : -1, ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 230) scb != NULL ? SCB_GET_LUN(scb) : -1); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 231) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 232) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 233) /* ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 234) * XXX - these options apply unilaterally to _all_ adapters ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 235) * cards in the system. This should be fixed. Exceptions to this ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 236) * rule are noted in the comments. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 237) */ ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 238) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 239) /* ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 240) * Skip the scsi bus reset. Non 0 make us skip the reset at startup. This ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 241) * has no effect on any later resets that might occur due to things like ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 242) * SCSI bus timeouts. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 243) */ ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 244) static uint32_t aic79xx_no_reset; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 245) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 246) /* ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 247) * Should we force EXTENDED translation on a controller. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 248) * 0 == Use whatever is in the SEEPROM or default to off ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 249) * 1 == Use whatever is in the SEEPROM or default to on ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 250) */ ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 251) static uint32_t aic79xx_extended; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 252) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 253) /* ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 254) * PCI bus parity checking of the Adaptec controllers. This is somewhat ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 255) * dubious at best. To my knowledge, this option has never actually ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 256) * solved a PCI parity problem, but on certain machines with broken PCI ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 257) * chipset configurations, it can generate tons of false error messages. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 258) * It's included in the driver for completeness. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 259) * 0 = Shut off PCI parity check ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 260) * non-0 = Enable PCI parity check ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 261) * ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 262) * NOTE: you can't actually pass -1 on the lilo prompt. So, to set this ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 263) * variable to -1 you would actually want to simply pass the variable ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 264) * name without a number. That will invert the 0 which will result in ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 265) * -1. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 266) */ ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 267) static uint32_t aic79xx_pci_parity = ~0; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 268) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 269) /* ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 270) * There are lots of broken chipsets in the world. Some of them will ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 271) * violate the PCI spec when we issue byte sized memory writes to our ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 272) * controller. I/O mapped register access, if allowed by the given ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 273) * platform, will work in almost all cases. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 274) */ ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 275) uint32_t aic79xx_allow_memio = ~0; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 276) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 277) /* ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 278) * So that we can set how long each device is given as a selection timeout. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 279) * The table of values goes like this: ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 280) * 0 - 256ms ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 281) * 1 - 128ms ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 282) * 2 - 64ms ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 283) * 3 - 32ms ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 284) * We default to 256ms because some older devices need a longer time ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 285) * to respond to initial selection. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 286) */ ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 287) static uint32_t aic79xx_seltime; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 288) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 289) /* ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 290) * Certain devices do not perform any aging on commands. Should the ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 291) * device be saturated by commands in one portion of the disk, it is ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 292) * possible for transactions on far away sectors to never be serviced. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 293) * To handle these devices, we can periodically send an ordered tag to ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 294) * force all outstanding transactions to be serviced prior to a new ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 295) * transaction. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 296) */ 289fe5b1f99c5 (Adrian Bunk 2006-10-20 14:47:57 -0700 297) static uint32_t aic79xx_periodic_otag; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 298) 3fb086126462c (Hannes Reinecke 2006-01-24 10:44:38 +0100 299) /* Some storage boxes are using an LSI chip which has a bug making it 3fb086126462c (Hannes Reinecke 2006-01-24 10:44:38 +0100 300) * impossible to use aic79xx Rev B chip in 320 speeds. The following 3fb086126462c (Hannes Reinecke 2006-01-24 10:44:38 +0100 301) * storage boxes have been reported to be buggy: 3fb086126462c (Hannes Reinecke 2006-01-24 10:44:38 +0100 302) * EonStor 3U 16-Bay: U16U-G3A3 3fb086126462c (Hannes Reinecke 2006-01-24 10:44:38 +0100 303) * EonStor 2U 12-Bay: U12U-G3A3 3fb086126462c (Hannes Reinecke 2006-01-24 10:44:38 +0100 304) * SentinelRAID: 2500F R5 / R6 3fb086126462c (Hannes Reinecke 2006-01-24 10:44:38 +0100 305) * SentinelRAID: 2500F R1 3fb086126462c (Hannes Reinecke 2006-01-24 10:44:38 +0100 306) * SentinelRAID: 2500F/1500F 3fb086126462c (Hannes Reinecke 2006-01-24 10:44:38 +0100 307) * SentinelRAID: 150F 3fb086126462c (Hannes Reinecke 2006-01-24 10:44:38 +0100 308) * 3fb086126462c (Hannes Reinecke 2006-01-24 10:44:38 +0100 309) * To get around this LSI bug, you can set your board to 160 mode 3fb086126462c (Hannes Reinecke 2006-01-24 10:44:38 +0100 310) * or you can enable the SLOWCRC bit. 3fb086126462c (Hannes Reinecke 2006-01-24 10:44:38 +0100 311) */ 3fb086126462c (Hannes Reinecke 2006-01-24 10:44:38 +0100 312) uint32_t aic79xx_slowcrc; 3fb086126462c (Hannes Reinecke 2006-01-24 10:44:38 +0100 313) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 314) /* ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 315) * Module information and settable options. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 316) */ ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 317) static char *aic79xx = NULL; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 318) 64624d4f46d5e (Hannes Reinecke 2007-10-19 10:32:29 +0200 319) MODULE_AUTHOR("Maintainer: Hannes Reinecke "); 64624d4f46d5e (Hannes Reinecke 2007-10-19 10:32:29 +0200 320) MODULE_DESCRIPTION("Adaptec AIC790X U320 SCSI Host Bus Adapter driver"); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 321) MODULE_LICENSE("Dual BSD/GPL"); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 322) MODULE_VERSION(AIC79XX_DRIVER_VERSION); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 323) module_param(aic79xx, charp, 0444); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 324) MODULE_PARM_DESC(aic79xx, 2b6ee9b529546 (Randy Dunlap 2006-08-14 23:09:23 -0700 325) "period-delimited options string:\n" ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 326) " verbose Enable verbose/diagnostic logging\n" ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 327) " allow_memio Allow device registers to be memory mapped\n" ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 328) " debug Bitmask of debug values to enable\n" b1c118121ae37 (Joe Perches 2008-02-03 17:28:22 +0200 329) " no_reset Suppress initial bus resets\n" ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 330) " extended Enable extended geometry on all controllers\n" ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 331) " periodic_otag Send an ordered tagged transaction\n" ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 332) " periodically to prevent tag starvation.\n" ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 333) " This may be required by some older disk\n" ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 334) " or drives/RAID arrays.\n" ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 335) " tag_info: Set per-target tag depth\n" ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 336) " global_tag_depth: Global tag depth for all targets on all buses\n" ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 337) " slewrate:Set the signal slew rate (0-15).\n" ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 338) " precomp: Set the signal precompensation (0-7).\n" ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 339) " amplitude: Set the signal amplitude (0-7).\n" ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 340) " seltime: Selection Timeout:\n" ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 341) " (0/256ms,1/128ms,2/64ms,3/32ms)\n" 3fb086126462c (Hannes Reinecke 2006-01-24 10:44:38 +0100 342) " slowcrc Turn on the SLOWCRC bit (Rev B only)\n" ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 343) "\n" 970e2486492aa (Lucas De Marchi 2012-03-30 13:37:16 -0700 344) " Sample modprobe configuration file:\n" 970e2486492aa (Lucas De Marchi 2012-03-30 13:37:16 -0700 345) " # Enable verbose logging\n" 970e2486492aa (Lucas De Marchi 2012-03-30 13:37:16 -0700 346) " # Set tag depth on Controller 2/Target 2 to 10 tags\n" 970e2486492aa (Lucas De Marchi 2012-03-30 13:37:16 -0700 347) " # Shorten the selection timeout to 128ms\n" ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 348) "\n" ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 349) " options aic79xx 'aic79xx=verbose.tag_info:{{}.{}.{..10}}.seltime:1'\n" 2b6ee9b529546 (Randy Dunlap 2006-08-14 23:09:23 -0700 350) ); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 351) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 352) static void ahd_linux_handle_scsi_status(struct ahd_softc *, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 353) struct scsi_device *, ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 354) struct scb *); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 355) static void ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 356) struct scsi_cmnd *cmd); 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 357) static int ahd_linux_queue_abort_cmd(struct scsi_cmnd *cmd); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 358) static void ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 359) static u_int ahd_linux_user_tagdepth(struct ahd_softc *ahd, ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 360) struct ahd_devinfo *devinfo); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 361) static void ahd_linux_device_queue_depth(struct scsi_device *); 60a1321384029 (Hannes Reinecke 2005-07-22 16:42:28 +0200 362) static int ahd_linux_run_command(struct ahd_softc*, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 363) struct ahd_linux_device *, 60a1321384029 (Hannes Reinecke 2005-07-22 16:42:28 +0200 364) struct scsi_cmnd *); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 365) static void ahd_linux_setup_tag_info_global(char *p); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 366) static int aic79xx_setup(char *c); e3e0ca5143d7a (Adrian Bunk 2007-03-26 21:59:29 -0800 367) static void ahd_freeze_simq(struct ahd_softc *ahd); e3e0ca5143d7a (Adrian Bunk 2007-03-26 21:59:29 -0800 368) static void ahd_release_simq(struct ahd_softc *ahd); 85a46523ff68a (Christoph Hellwig 2005-08-15 13:28:46 +0200 369) 85a46523ff68a (Christoph Hellwig 2005-08-15 13:28:46 +0200 370) static int ahd_linux_unit; 85a46523ff68a (Christoph Hellwig 2005-08-15 13:28:46 +0200 371) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 372) be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 373) /************************** OS Utility Wrappers *******************************/ be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 374) void ahd_delay(long); be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 375) void be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 376) ahd_delay(long usec) be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 377) { be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 378) /* be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 379) * udelay on Linux can have problems for be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 380) * multi-millisecond waits. Wait at most be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 381) * 1024us per call. be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 382) */ be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 383) while (usec > 0) { be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 384) udelay(usec % 1024); be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 385) usec -= 1024; be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 386) } be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 387) } be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 388) be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 389) be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 390) /***************************** Low Level I/O **********************************/ be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 391) uint8_t ahd_inb(struct ahd_softc * ahd, long port); be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 392) void ahd_outb(struct ahd_softc * ahd, long port, uint8_t val); be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 393) void ahd_outw_atomic(struct ahd_softc * ahd, be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 394) long port, uint16_t val); be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 395) void ahd_outsb(struct ahd_softc * ahd, long port, be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 396) uint8_t *, int count); be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 397) void ahd_insb(struct ahd_softc * ahd, long port, be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 398) uint8_t *, int count); be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 399) be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 400) uint8_t be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 401) ahd_inb(struct ahd_softc * ahd, long port) be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 402) { be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 403) uint8_t x; be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 404) be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 405) if (ahd->tags[0] == BUS_SPACE_MEMIO) { be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 406) x = readb(ahd->bshs[0].maddr + port); be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 407) } else { be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 408) x = inb(ahd->bshs[(port) >> 8].ioport + ((port) & 0xFF)); be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 409) } be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 410) mb(); be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 411) return (x); be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 412) } be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 413) d1d7b19d43318 (Denys Vlasenko 2008-04-25 04:34:49 +0200 414) #if 0 /* unused */ d1d7b19d43318 (Denys Vlasenko 2008-04-25 04:34:49 +0200 415) static uint16_t be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 416) ahd_inw_atomic(struct ahd_softc * ahd, long port) be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 417) { be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 418) uint8_t x; be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 419) be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 420) if (ahd->tags[0] == BUS_SPACE_MEMIO) { be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 421) x = readw(ahd->bshs[0].maddr + port); be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 422) } else { be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 423) x = inw(ahd->bshs[(port) >> 8].ioport + ((port) & 0xFF)); be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 424) } be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 425) mb(); be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 426) return (x); be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 427) } d1d7b19d43318 (Denys Vlasenko 2008-04-25 04:34:49 +0200 428) #endif be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 429) be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 430) void be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 431) ahd_outb(struct ahd_softc * ahd, long port, uint8_t val) be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 432) { be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 433) if (ahd->tags[0] == BUS_SPACE_MEMIO) { be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 434) writeb(val, ahd->bshs[0].maddr + port); be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 435) } else { be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 436) outb(val, ahd->bshs[(port) >> 8].ioport + (port & 0xFF)); be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 437) } be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 438) mb(); be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 439) } be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 440) be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 441) void be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 442) ahd_outw_atomic(struct ahd_softc * ahd, long port, uint16_t val) be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 443) { be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 444) if (ahd->tags[0] == BUS_SPACE_MEMIO) { be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 445) writew(val, ahd->bshs[0].maddr + port); be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 446) } else { be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 447) outw(val, ahd->bshs[(port) >> 8].ioport + (port & 0xFF)); be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 448) } be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 449) mb(); be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 450) } be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 451) be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 452) void be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 453) ahd_outsb(struct ahd_softc * ahd, long port, uint8_t *array, int count) be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 454) { be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 455) int i; be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 456) be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 457) /* be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 458) * There is probably a more efficient way to do this on Linux be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 459) * but we don't use this for anything speed critical and this be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 460) * should work. be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 461) */ be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 462) for (i = 0; i < count; i++) be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 463) ahd_outb(ahd, port, *array++); be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 464) } be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 465) be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 466) void be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 467) ahd_insb(struct ahd_softc * ahd, long port, uint8_t *array, int count) be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 468) { be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 469) int i; be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 470) be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 471) /* be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 472) * There is probably a more efficient way to do this on Linux be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 473) * but we don't use this for anything speed critical and this be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 474) * should work. be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 475) */ be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 476) for (i = 0; i < count; i++) be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 477) *array++ = ahd_inb(ahd, port); be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 478) } be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 479) be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 480) /******************************* PCI Routines *********************************/ be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 481) uint32_t be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 482) ahd_pci_read_config(ahd_dev_softc_t pci, int reg, int width) be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 483) { be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 484) switch (width) { be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 485) case 1: be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 486) { be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 487) uint8_t retval; be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 488) be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 489) pci_read_config_byte(pci, reg, &retval); be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 490) return (retval); be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 491) } be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 492) case 2: be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 493) { be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 494) uint16_t retval; be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 495) pci_read_config_word(pci, reg, &retval); be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 496) return (retval); be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 497) } be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 498) case 4: be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 499) { be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 500) uint32_t retval; be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 501) pci_read_config_dword(pci, reg, &retval); be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 502) return (retval); be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 503) } be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 504) default: be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 505) panic("ahd_pci_read_config: Read size too big"); be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 506) /* NOTREACHED */ be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 507) return (0); be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 508) } be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 509) } be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 510) be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 511) void be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 512) ahd_pci_write_config(ahd_dev_softc_t pci, int reg, uint32_t value, int width) be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 513) { be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 514) switch (width) { be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 515) case 1: be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 516) pci_write_config_byte(pci, reg, value); be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 517) break; be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 518) case 2: be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 519) pci_write_config_word(pci, reg, value); be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 520) break; be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 521) case 4: be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 522) pci_write_config_dword(pci, reg, value); be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 523) break; be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 524) default: be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 525) panic("ahd_pci_write_config: Write size too big"); be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 526) /* NOTREACHED */ be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 527) } be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 528) } be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 529) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 530) /****************************** Inlines ***************************************/ be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 531) static void ahd_linux_unmap_scb(struct ahd_softc*, struct scb*); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 532) be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 533) static void ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 534) ahd_linux_unmap_scb(struct ahd_softc *ahd, struct scb *scb) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 535) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 536) struct scsi_cmnd *cmd; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 537) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 538) cmd = scb->io_ctx; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 539) ahd_sync_sglist(ahd, scb, BUS_DMASYNC_POSTWRITE); 4c688fc7df618 (FUJITA Tomonori 2007-05-26 02:02:34 +0900 540) scsi_dma_unmap(cmd); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 541) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 542) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 543) /******************************** Macros **************************************/ ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 544) #define BUILD_SCSIID(ahd, cmd) \ 422c0d61d591c (Jeff Garzik 2005-10-24 18:05:09 -0400 545) (((scmd_id(cmd) << TID_SHIFT) & TID) | (ahd)->our_id) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 546) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 547) /* ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 548) * Return a string describing the driver. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 549) */ ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 550) static const char * ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 551) ahd_linux_info(struct Scsi_Host *host) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 552) { ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 553) static char buffer[512]; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 554) char ahd_info[256]; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 555) char *bp; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 556) struct ahd_softc *ahd; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 557) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 558) bp = &buffer[0]; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 559) ahd = *(struct ahd_softc **)host->hostdata; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 560) memset(bp, 0, sizeof(buffer)); 980b306a29772 (Denys Vlasenko 2008-04-25 04:36:01 +0200 561) strcpy(bp, "Adaptec AIC79XX PCI-X SCSI HBA DRIVER, Rev " AIC79XX_DRIVER_VERSION "\n" 980b306a29772 (Denys Vlasenko 2008-04-25 04:36:01 +0200 562) " <"); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 563) strcat(bp, ahd->description); 980b306a29772 (Denys Vlasenko 2008-04-25 04:36:01 +0200 564) strcat(bp, ">\n" 980b306a29772 (Denys Vlasenko 2008-04-25 04:36:01 +0200 565) " "); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 566) ahd_controller_info(ahd, ahd_info); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 567) strcat(bp, ahd_info); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 568) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 569) return (bp); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 570) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 571) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 572) /* ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 573) * Queue an SCB to the controller. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 574) */ ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 575) static int f281233d3eba1 (Jeff Garzik 2010-11-16 02:10:29 -0500 576) ahd_linux_queue_lck(struct scsi_cmnd * cmd, void (*scsi_done) (struct scsi_cmnd *)) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 577) { ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 578) struct ahd_softc *ahd; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 579) struct ahd_linux_device *dev = scsi_transport_device_data(cmd->device); 4065a413d7684 (Christoph Hellwig 2005-10-31 20:05:01 +0100 580) int rtn = SCSI_MLQUEUE_HOST_BUSY; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 581) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 582) ahd = *(struct ahd_softc **)cmd->device->host->hostdata; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 583) 7b22da38b64a3 (Hannes Reinecke 2006-03-08 12:56:14 +0100 584) cmd->scsi_done = scsi_done; 7b22da38b64a3 (Hannes Reinecke 2006-03-08 12:56:14 +0100 585) cmd->result = CAM_REQ_INPROG << 16; 7b22da38b64a3 (Hannes Reinecke 2006-03-08 12:56:14 +0100 586) rtn = ahd_linux_run_command(ahd, dev, cmd); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 587) 4065a413d7684 (Christoph Hellwig 2005-10-31 20:05:01 +0100 588) return rtn; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 589) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 590) f281233d3eba1 (Jeff Garzik 2010-11-16 02:10:29 -0500 591) static DEF_SCSI_QCMD(ahd_linux_queue) f281233d3eba1 (Jeff Garzik 2010-11-16 02:10:29 -0500 592) be0d67680d524 (Denys Vlasenko 2008-03-23 04:41:22 +0100 593) static struct scsi_target ** 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 594) ahd_linux_target_in_softc(struct scsi_target *starget) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 595) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 596) struct ahd_softc *ahd = 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 597) *((struct ahd_softc **)dev_to_shost(&starget->dev)->hostdata); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 598) unsigned int target_offset; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 599) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 600) target_offset = starget->id; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 601) if (starget->channel != 0) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 602) target_offset += 8; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 603) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 604) return &ahd->platform_data->starget[target_offset]; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 605) } 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 606) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 607) static int 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 608) ahd_linux_target_alloc(struct scsi_target *starget) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 609) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 610) struct ahd_softc *ahd = 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 611) *((struct ahd_softc **)dev_to_shost(&starget->dev)->hostdata); 986a25f96accc (Hannes Reinecke 2006-03-08 12:59:35 +0100 612) struct seeprom_config *sc = ahd->seep_config; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 613) unsigned long flags; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 614) struct scsi_target **ahd_targp = ahd_linux_target_in_softc(starget); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 615) struct ahd_devinfo devinfo; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 616) struct ahd_initiator_tinfo *tinfo; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 617) struct ahd_tmode_tstate *tstate; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 618) char channel = starget->channel + 'A'; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 619) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 620) ahd_lock(ahd, &flags); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 621) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 622) BUG_ON(*ahd_targp != NULL); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 623) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 624) *ahd_targp = starget; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 625) 986a25f96accc (Hannes Reinecke 2006-03-08 12:59:35 +0100 626) if (sc) { 986a25f96accc (Hannes Reinecke 2006-03-08 12:59:35 +0100 627) int flags = sc->device_flags[starget->id]; 986a25f96accc (Hannes Reinecke 2006-03-08 12:59:35 +0100 628) 986a25f96accc (Hannes Reinecke 2006-03-08 12:59:35 +0100 629) tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id, 986a25f96accc (Hannes Reinecke 2006-03-08 12:59:35 +0100 630) starget->id, &tstate); 986a25f96accc (Hannes Reinecke 2006-03-08 12:59:35 +0100 631) 986a25f96accc (Hannes Reinecke 2006-03-08 12:59:35 +0100 632) if ((flags & CFPACKETIZED) == 0) { ea4431906d866 (James Bottomley 2009-06-13 12:19:05 -0500 633) /* don't negotiate packetized (IU) transfers */ ea4431906d866 (James Bottomley 2009-06-13 12:19:05 -0500 634) spi_max_iu(starget) = 0; 986a25f96accc (Hannes Reinecke 2006-03-08 12:59:35 +0100 635) } else { 986a25f96accc (Hannes Reinecke 2006-03-08 12:59:35 +0100 636) if ((ahd->features & AHD_RTI) == 0) 986a25f96accc (Hannes Reinecke 2006-03-08 12:59:35 +0100 637) spi_rti(starget) = 0; 986a25f96accc (Hannes Reinecke 2006-03-08 12:59:35 +0100 638) } 986a25f96accc (Hannes Reinecke 2006-03-08 12:59:35 +0100 639) 986a25f96accc (Hannes Reinecke 2006-03-08 12:59:35 +0100 640) if ((flags & CFQAS) == 0) ea4431906d866 (James Bottomley 2009-06-13 12:19:05 -0500 641) spi_max_qas(starget) = 0; 986a25f96accc (Hannes Reinecke 2006-03-08 12:59:35 +0100 642) 986a25f96accc (Hannes Reinecke 2006-03-08 12:59:35 +0100 643) /* Transinfo values have been set to BIOS settings */ 986a25f96accc (Hannes Reinecke 2006-03-08 12:59:35 +0100 644) spi_max_width(starget) = (flags & CFWIDEB) ? 1 : 0; 986a25f96accc (Hannes Reinecke 2006-03-08 12:59:35 +0100 645) spi_min_period(starget) = tinfo->user.period; 986a25f96accc (Hannes Reinecke 2006-03-08 12:59:35 +0100 646) spi_max_offset(starget) = tinfo->user.offset; 986a25f96accc (Hannes Reinecke 2006-03-08 12:59:35 +0100 647) } 986a25f96accc (Hannes Reinecke 2006-03-08 12:59:35 +0100 648) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 649) tinfo = ahd_fetch_transinfo(ahd, channel, ahd->our_id, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 650) starget->id, &tstate); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 651) ahd_compile_devinfo(&devinfo, ahd->our_id, starget->id, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 652) CAM_LUN_WILDCARD, channel, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 653) ROLE_INITIATOR); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 654) ahd_set_syncrate(ahd, &devinfo, 0, 0, 0, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 655) AHD_TRANS_GOAL, /*paused*/FALSE); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 656) ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 657) AHD_TRANS_GOAL, /*paused*/FALSE); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 658) ahd_unlock(ahd, &flags); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 659) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 660) return 0; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 661) } 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 662) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 663) static void 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 664) ahd_linux_target_destroy(struct scsi_target *starget) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 665) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 666) struct scsi_target **ahd_targp = ahd_linux_target_in_softc(starget); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 667) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 668) *ahd_targp = NULL; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 669) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 670) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 671) static int 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 672) ahd_linux_slave_alloc(struct scsi_device *sdev) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 673) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 674) struct ahd_softc *ahd = 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 675) *((struct ahd_softc **)sdev->host->hostdata); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 676) struct ahd_linux_device *dev; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 677) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 678) if (bootverbose) 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 679) printk("%s: Slave Alloc %d\n", ahd_name(ahd), sdev->id); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 680) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 681) dev = scsi_transport_device_data(sdev); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 682) memset(dev, 0, sizeof(*dev)); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 683) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 684) /* 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 685) * We start out life using untagged 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 686) * transactions of which we allow one. 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 687) */ 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 688) dev->openings = 1; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 689) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 690) /* 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 691) * Set maxtags to 0. This will be changed if we 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 692) * later determine that we are dealing with 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 693) * a tagged queuing capable device. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 694) */ 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 695) dev->maxtags = 0; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 696) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 697) return (0); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 698) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 699) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 700) static int 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 701) ahd_linux_slave_configure(struct scsi_device *sdev) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 702) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 703) struct ahd_softc *ahd; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 704) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 705) ahd = *((struct ahd_softc **)sdev->host->hostdata); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 706) if (bootverbose) 017560fca496f (Jeff Garzik 2005-10-24 18:04:36 -0400 707) sdev_printk(KERN_INFO, sdev, "Slave Configure\n"); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 708) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 709) ahd_linux_device_queue_depth(sdev); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 710) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 711) /* Initial Domain Validation */ 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 712) if (!spi_initial_dv(sdev->sdev_target)) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 713) spi_dv_device(sdev); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 714) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 715) return 0; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 716) } 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 717) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 718) #if defined(__i386__) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 719) /* ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 720) * Return the disk geometry for the given SCSI device. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 721) */ ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 722) static int ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 723) ahd_linux_biosparam(struct scsi_device *sdev, struct block_device *bdev, ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 724) sector_t capacity, int geom[]) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 725) { ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 726) int heads; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 727) int sectors; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 728) int cylinders; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 729) int extended; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 730) struct ahd_softc *ahd; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 731) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 732) ahd = *((struct ahd_softc **)sdev->host->hostdata); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 733) a10183d744fb4 (Christoph Hellwig 2020-03-24 08:25:17 +0100 734) if (scsi_partsize(bdev, capacity, geom)) a10183d744fb4 (Christoph Hellwig 2020-03-24 08:25:17 +0100 735) return 0; a10183d744fb4 (Christoph Hellwig 2020-03-24 08:25:17 +0100 736) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 737) heads = 64; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 738) sectors = 32; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 739) cylinders = aic_sector_div(capacity, heads, sectors); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 740) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 741) if (aic79xx_extended != 0) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 742) extended = 1; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 743) else ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 744) extended = (ahd->flags & AHD_EXTENDED_TRANS_A) != 0; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 745) if (extended && cylinders >= 1024) { ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 746) heads = 255; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 747) sectors = 63; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 748) cylinders = aic_sector_div(capacity, heads, sectors); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 749) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 750) geom[0] = heads; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 751) geom[1] = sectors; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 752) geom[2] = cylinders; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 753) return (0); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 754) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 755) #endif ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 756) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 757) /* ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 758) * Abort the current SCSI command(s). ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 759) */ ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 760) static int 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 761) ahd_linux_abort(struct scsi_cmnd *cmd) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 762) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 763) int error; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 764) 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 765) error = ahd_linux_queue_abort_cmd(cmd); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 766) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 767) return error; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 768) } 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 769) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 770) /* 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 771) * Attempt to send a target reset message to the device that timed out. 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 772) */ 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 773) static int 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 774) ahd_linux_dev_reset(struct scsi_cmnd *cmd) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 775) { 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 776) struct ahd_softc *ahd; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 777) struct ahd_linux_device *dev; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 778) struct scb *reset_scb; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 779) u_int cdb_byte; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 780) int retval = SUCCESS; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 781) int paused; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 782) int wait; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 783) struct ahd_initiator_tinfo *tinfo; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 784) struct ahd_tmode_tstate *tstate; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 785) unsigned long flags; 6e9a4738c9fad (Peter Zijlstra 2006-09-30 23:28:10 -0700 786) DECLARE_COMPLETION_ONSTACK(done); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 787) 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 788) reset_scb = NULL; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 789) paused = FALSE; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 790) wait = FALSE; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 791) ahd = *(struct ahd_softc **)cmd->device->host->hostdata; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 792) 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 793) scmd_printk(KERN_INFO, cmd, 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 794) "Attempting to queue a TARGET RESET message:"); 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 795) 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 796) printk("CDB:"); 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 797) for (cdb_byte = 0; cdb_byte < cmd->cmd_len; cdb_byte++) 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 798) printk(" 0x%x", cmd->cmnd[cdb_byte]); 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 799) printk("\n"); 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 800) 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 801) /* 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 802) * Determine if we currently own this command. 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 803) */ 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 804) dev = scsi_transport_device_data(cmd->device); 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 805) 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 806) if (dev == NULL) { 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 807) /* 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 808) * No target device for this command exists, 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 809) * so we must not still own the command. 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 810) */ 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 811) scmd_printk(KERN_INFO, cmd, "Is not an active device\n"); 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 812) return SUCCESS; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 813) } 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 814) 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 815) /* 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 816) * Generate us a new SCB 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 817) */ 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 818) reset_scb = ahd_get_scb(ahd, AHD_NEVER_COL_IDX); 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 819) if (!reset_scb) { 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 820) scmd_printk(KERN_INFO, cmd, "No SCB available\n"); 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 821) return FAILED; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 822) } 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 823) 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 824) tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id, 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 825) cmd->device->id, &tstate); 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 826) reset_scb->io_ctx = cmd; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 827) reset_scb->platform_data->dev = dev; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 828) reset_scb->sg_count = 0; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 829) ahd_set_residual(reset_scb, 0); 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 830) ahd_set_sense_residual(reset_scb, 0); 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 831) reset_scb->platform_data->xfer_len = 0; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 832) reset_scb->hscb->control = 0; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 833) reset_scb->hscb->scsiid = BUILD_SCSIID(ahd,cmd); 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 834) reset_scb->hscb->lun = cmd->device->lun; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 835) reset_scb->hscb->cdb_len = 0; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 836) reset_scb->hscb->task_management = SIU_TASKMGMT_LUN_RESET; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 837) reset_scb->flags |= SCB_DEVICE_RESET|SCB_RECOVERY_SCB|SCB_ACTIVE; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 838) if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0) { 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 839) reset_scb->flags |= SCB_PACKETIZED; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 840) } else { 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 841) reset_scb->hscb->control |= MK_MESSAGE; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 842) } 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 843) dev->openings--; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 844) dev->active++; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 845) dev->commands_issued++; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 846) 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 847) ahd_lock(ahd, &flags); 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 848) 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 849) LIST_INSERT_HEAD(&ahd->pending_scbs, reset_scb, pending_links); 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 850) ahd_queue_scb(ahd, reset_scb); 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 851) 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 852) ahd->platform_data->eh_done = &done; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 853) ahd_unlock(ahd, &flags); 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 854) 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 855) printk("%s: Device reset code sleeping\n", ahd_name(ahd)); 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 856) if (!wait_for_completion_timeout(&done, 5 * HZ)) { 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 857) ahd_lock(ahd, &flags); 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 858) ahd->platform_data->eh_done = NULL; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 859) ahd_unlock(ahd, &flags); 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 860) printk("%s: Device reset timer expired (active %d)\n", 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 861) ahd_name(ahd), dev->active); 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 862) retval = FAILED; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 863) } 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 864) printk("%s: Device reset returning 0x%x\n", ahd_name(ahd), retval); 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 865) 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 866) return (retval); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 867) } 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 868) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 869) /* 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 870) * Reset the SCSI bus. 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 871) */ 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 872) static int 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 873) ahd_linux_bus_reset(struct scsi_cmnd *cmd) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 874) { ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 875) struct ahd_softc *ahd; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 876) int found; f41b5cec9bd6f (Hannes Reinecke 2006-04-03 08:19:34 +0200 877) unsigned long flags; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 878) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 879) ahd = *(struct ahd_softc **)cmd->device->host->hostdata; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 880) #ifdef AHD_DEBUG 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 881) if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 882) printk("%s: Bus reset called for cmd %p\n", 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 883) ahd_name(ahd), cmd); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 884) #endif f41b5cec9bd6f (Hannes Reinecke 2006-04-03 08:19:34 +0200 885) ahd_lock(ahd, &flags); f41b5cec9bd6f (Hannes Reinecke 2006-04-03 08:19:34 +0200 886) 422c0d61d591c (Jeff Garzik 2005-10-24 18:05:09 -0400 887) found = ahd_reset_channel(ahd, scmd_channel(cmd) + 'A', 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 888) /*initiate reset*/TRUE); f41b5cec9bd6f (Hannes Reinecke 2006-04-03 08:19:34 +0200 889) ahd_unlock(ahd, &flags); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 890) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 891) if (bootverbose) 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 892) printk("%s: SCSI bus reset delivered. " 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 893) "%d SCBs aborted.\n", ahd_name(ahd), found); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 894) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 895) return (SUCCESS); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 896) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 897) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 898) struct scsi_host_template aic79xx_driver_template = { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 899) .module = THIS_MODULE, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 900) .name = "aic79xx", 85a46523ff68a (Christoph Hellwig 2005-08-15 13:28:46 +0200 901) .proc_name = "aic79xx", f6f83a6c92107 (Al Viro 2013-03-31 03:59:17 -0400 902) .show_info = ahd_linux_show_info, f6f83a6c92107 (Al Viro 2013-03-31 03:59:17 -0400 903) .write_info = ahd_proc_write_seeprom, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 904) .info = ahd_linux_info, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 905) .queuecommand = ahd_linux_queue, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 906) .eh_abort_handler = ahd_linux_abort, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 907) .eh_device_reset_handler = ahd_linux_dev_reset, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 908) .eh_bus_reset_handler = ahd_linux_bus_reset, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 909) #if defined(__i386__) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 910) .bios_param = ahd_linux_biosparam, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 911) #endif 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 912) .can_queue = AHD_MAX_QUEUE, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 913) .this_id = -1, 80f1443c66de3 (Hannes Reinecke 2006-10-06 09:22:41 +0200 914) .max_sectors = 8192, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 915) .cmd_per_lun = 2, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 916) .slave_alloc = ahd_linux_slave_alloc, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 917) .slave_configure = ahd_linux_slave_configure, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 918) .target_alloc = ahd_linux_target_alloc, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 919) .target_destroy = ahd_linux_target_destroy, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 920) }; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 921) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 922) /******************************** Bus DMA *************************************/ 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 923) int 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 924) ahd_dma_tag_create(struct ahd_softc *ahd, bus_dma_tag_t parent, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 925) bus_size_t alignment, bus_size_t boundary, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 926) dma_addr_t lowaddr, dma_addr_t highaddr, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 927) bus_dma_filter_t *filter, void *filterarg, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 928) bus_size_t maxsize, int nsegments, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 929) bus_size_t maxsegsz, int flags, bus_dma_tag_t *ret_tag) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 930) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 931) bus_dma_tag_t dmat; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 932) 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 933) dmat = kmalloc(sizeof(*dmat), GFP_ATOMIC); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 934) if (dmat == NULL) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 935) return (ENOMEM); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 936) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 937) /* 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 938) * Linux is very simplistic about DMA memory. For now don't 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 939) * maintain all specification information. Once Linux supplies 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 940) * better facilities for doing these operations, or the 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 941) * needs of this particular driver change, we might need to do 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 942) * more here. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 943) */ 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 944) dmat->alignment = alignment; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 945) dmat->boundary = boundary; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 946) dmat->maxsize = maxsize; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 947) *ret_tag = dmat; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 948) return (0); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 949) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 950) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 951) void 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 952) ahd_dma_tag_destroy(struct ahd_softc *ahd, bus_dma_tag_t dmat) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 953) { 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 954) kfree(dmat); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 955) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 956) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 957) int 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 958) ahd_dmamem_alloc(struct ahd_softc *ahd, bus_dma_tag_t dmat, void** vaddr, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 959) int flags, bus_dmamap_t *mapp) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 960) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 961) *vaddr = pci_alloc_consistent(ahd->dev_softc, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 962) dmat->maxsize, mapp); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 963) if (*vaddr == NULL) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 964) return (ENOMEM); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 965) return(0); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 966) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 967) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 968) void 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 969) ahd_dmamem_free(struct ahd_softc *ahd, bus_dma_tag_t dmat, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 970) void* vaddr, bus_dmamap_t map) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 971) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 972) pci_free_consistent(ahd->dev_softc, dmat->maxsize, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 973) vaddr, map); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 974) } 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 975) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 976) int 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 977) ahd_dmamap_load(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 978) void *buf, bus_size_t buflen, bus_dmamap_callback_t *cb, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 979) void *cb_arg, int flags) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 980) { ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 981) /* 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 982) * Assume for now that this will only be used during 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 983) * initialization and not for per-transaction buffer mapping. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 984) */ 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 985) bus_dma_segment_t stack_sg; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 986) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 987) stack_sg.ds_addr = map; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 988) stack_sg.ds_len = dmat->maxsize; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 989) cb(cb_arg, &stack_sg, /*nseg*/1, /*error*/0); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 990) return (0); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 991) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 992) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 993) void 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 994) ahd_dmamap_destroy(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 995) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 996) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 997) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 998) int 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 999) ahd_dmamap_unload(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1000) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1001) /* Nothing to do */ 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1002) return (0); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1003) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1004) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1005) /********************* Platform Dependent Functions ***************************/ 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1006) static void 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1007) ahd_linux_setup_iocell_info(u_long index, int instance, int targ, int32_t value) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1008) { ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1009) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1010) if ((instance >= 0) 6391a11375de5 (Tobias Klauser 2006-06-08 22:23:48 -0700 1011) && (instance < ARRAY_SIZE(aic79xx_iocell_info))) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1012) uint8_t *iocell_info; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1013) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1014) iocell_info = (uint8_t*)&aic79xx_iocell_info[instance]; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1015) iocell_info[index] = value & 0xFFFF; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1016) if (bootverbose) 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 1017) printk("iocell[%d:%ld] = %d\n", instance, index, value); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1018) } 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1019) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1020) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1021) static void 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1022) ahd_linux_setup_tag_info_global(char *p) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1023) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1024) int tags, i, j; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1025) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1026) tags = simple_strtoul(p + 1, NULL, 0) & 0xff; 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 1027) printk("Setting Global Tags= %d\n", tags); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1028) 6391a11375de5 (Tobias Klauser 2006-06-08 22:23:48 -0700 1029) for (i = 0; i < ARRAY_SIZE(aic79xx_tag_info); i++) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1030) for (j = 0; j < AHD_NUM_TARGETS; j++) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1031) aic79xx_tag_info[i].tag_commands[j] = tags; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1032) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1033) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1034) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1035) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1036) static void 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1037) ahd_linux_setup_tag_info(u_long arg, int instance, int targ, int32_t value) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1038) { ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1039) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1040) if ((instance >= 0) && (targ >= 0) 6391a11375de5 (Tobias Klauser 2006-06-08 22:23:48 -0700 1041) && (instance < ARRAY_SIZE(aic79xx_tag_info)) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1042) && (targ < AHD_NUM_TARGETS)) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1043) aic79xx_tag_info[instance].tag_commands[targ] = value & 0x1FF; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1044) if (bootverbose) 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 1045) printk("tag_info[%d:%d] = %d\n", instance, targ, value); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1046) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1047) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1048) 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1049) static char * 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1050) ahd_parse_brace_option(char *opt_name, char *opt_arg, char *end, int depth, 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1051) void (*callback)(u_long, int, int, int32_t), 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1052) u_long callback_arg) 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1053) { 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1054) char *tok_end; 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1055) char *tok_end2; 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1056) int i; 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1057) int instance; 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1058) int targ; 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1059) int done; 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1060) char tok_list[] = {'.', ',', '{', '}', '\0'}; 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1061) 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1062) /* All options use a ':' name/arg separator */ 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1063) if (*opt_arg != ':') 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1064) return (opt_arg); 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1065) opt_arg++; 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1066) instance = -1; 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1067) targ = -1; 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1068) done = FALSE; 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1069) /* 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1070) * Restore separator that may be in 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1071) * the middle of our option argument. 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1072) */ 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1073) tok_end = strchr(opt_arg, '\0'); 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1074) if (tok_end < end) 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1075) *tok_end = ','; 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1076) while (!done) { 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1077) switch (*opt_arg) { 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1078) case '{': 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1079) if (instance == -1) { 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1080) instance = 0; 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1081) } else { 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1082) if (depth > 1) { 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1083) if (targ == -1) 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1084) targ = 0; 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1085) } else { 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 1086) printk("Malformed Option %s\n", 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1087) opt_name); 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1088) done = TRUE; 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1089) } 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1090) } 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1091) opt_arg++; 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1092) break; 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1093) case '}': 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1094) if (targ != -1) 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1095) targ = -1; 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1096) else if (instance != -1) 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1097) instance = -1; 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1098) opt_arg++; 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1099) break; 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1100) case ',': 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1101) case '.': 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1102) if (instance == -1) 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1103) done = TRUE; 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1104) else if (targ >= 0) 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1105) targ++; 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1106) else if (instance >= 0) 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1107) instance++; 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1108) opt_arg++; 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1109) break; 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1110) case '\0': 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1111) done = TRUE; 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1112) break; 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1113) default: 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1114) tok_end = end; 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1115) for (i = 0; tok_list[i]; i++) { 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1116) tok_end2 = strchr(opt_arg, tok_list[i]); 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1117) if ((tok_end2) && (tok_end2 < tok_end)) 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1118) tok_end = tok_end2; 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1119) } 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1120) callback(callback_arg, instance, targ, 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1121) simple_strtol(opt_arg, NULL, 0)); 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1122) opt_arg = tok_end; 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1123) break; 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1124) } 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1125) } 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1126) return (opt_arg); 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1127) } 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1128) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1129) /* 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1130) * Handle Linux boot parameters. This routine allows for assigning a value 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1131) * to a parameter with a ':' between the parameter and the value. 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1132) * ie. aic79xx=stpwlev:1,extended ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1133) */ ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1134) static int 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1135) aic79xx_setup(char *s) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1136) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1137) int i, n; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1138) char *p; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1139) char *end; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1140) 980b306a29772 (Denys Vlasenko 2008-04-25 04:36:01 +0200 1141) static const struct { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1142) const char *name; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1143) uint32_t *flag; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1144) } options[] = { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1145) { "extended", &aic79xx_extended }, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1146) { "no_reset", &aic79xx_no_reset }, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1147) { "verbose", &aic79xx_verbose }, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1148) { "allow_memio", &aic79xx_allow_memio}, ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1149) #ifdef AHD_DEBUG 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1150) { "debug", &ahd_debug }, ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1151) #endif 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1152) { "periodic_otag", &aic79xx_periodic_otag }, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1153) { "pci_parity", &aic79xx_pci_parity }, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1154) { "seltime", &aic79xx_seltime }, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1155) { "tag_info", NULL }, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1156) { "global_tag_depth", NULL}, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1157) { "slewrate", NULL }, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1158) { "precomp", NULL }, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1159) { "amplitude", NULL }, 3fb086126462c (Hannes Reinecke 2006-01-24 10:44:38 +0100 1160) { "slowcrc", &aic79xx_slowcrc }, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1161) }; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1162) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1163) end = strchr(s, '\0'); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1164) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1165) /* 6391a11375de5 (Tobias Klauser 2006-06-08 22:23:48 -0700 1166) * XXX ia64 gcc isn't smart enough to know that ARRAY_SIZE 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1167) * will never be 0 in this case. 6391a11375de5 (Tobias Klauser 2006-06-08 22:23:48 -0700 1168) */ 6391a11375de5 (Tobias Klauser 2006-06-08 22:23:48 -0700 1169) n = 0; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1170) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1171) while ((p = strsep(&s, ",.")) != NULL) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1172) if (*p == '\0') 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1173) continue; 6391a11375de5 (Tobias Klauser 2006-06-08 22:23:48 -0700 1174) for (i = 0; i < ARRAY_SIZE(options); i++) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1175) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1176) n = strlen(options[i].name); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1177) if (strncmp(options[i].name, p, n) == 0) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1178) break; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1179) } 6391a11375de5 (Tobias Klauser 2006-06-08 22:23:48 -0700 1180) if (i == ARRAY_SIZE(options)) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1181) continue; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1182) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1183) if (strncmp(p, "global_tag_depth", n) == 0) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1184) ahd_linux_setup_tag_info_global(p + n); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1185) } else if (strncmp(p, "tag_info", n) == 0) { 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1186) s = ahd_parse_brace_option("tag_info", p + n, end, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1187) 2, ahd_linux_setup_tag_info, 0); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1188) } else if (strncmp(p, "slewrate", n) == 0) { 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1189) s = ahd_parse_brace_option("slewrate", 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1190) p + n, end, 1, ahd_linux_setup_iocell_info, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1191) AIC79XX_SLEWRATE_INDEX); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1192) } else if (strncmp(p, "precomp", n) == 0) { 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1193) s = ahd_parse_brace_option("precomp", 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1194) p + n, end, 1, ahd_linux_setup_iocell_info, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1195) AIC79XX_PRECOMP_INDEX); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1196) } else if (strncmp(p, "amplitude", n) == 0) { 1ff927306e08b (Christoph Hellwig 2005-08-19 18:57:13 +0200 1197) s = ahd_parse_brace_option("amplitude", 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1198) p + n, end, 1, ahd_linux_setup_iocell_info, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1199) AIC79XX_AMPLITUDE_INDEX); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1200) } else if (p[n] == ':') { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1201) *(options[i].flag) = simple_strtoul(p + n + 1, NULL, 0); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1202) } else if (!strncmp(p, "verbose", n)) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1203) *(options[i].flag) = 1; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1204) } else { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1205) *(options[i].flag) ^= 0xFFFFFFFF; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1206) } 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1207) } 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1208) return 1; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1209) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1210) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1211) __setup("aic79xx=", aic79xx_setup); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1212) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1213) uint32_t aic79xx_verbose; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1214) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1215) int 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1216) ahd_linux_register_host(struct ahd_softc *ahd, struct scsi_host_template *template) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1217) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1218) char buf[80]; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1219) struct Scsi_Host *host; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1220) char *new_name; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1221) u_long s; e7a1ca1d27e20 (Jesper Juhl 2005-12-14 19:27:28 +0100 1222) int retval; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1223) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1224) template->name = ahd->description; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1225) host = scsi_host_alloc(template, sizeof(struct ahd_softc *)); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1226) if (host == NULL) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1227) return (ENOMEM); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1228) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1229) *((struct ahd_softc **)host->hostdata) = ahd; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1230) ahd->platform_data->host = host; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1231) host->can_queue = AHD_MAX_QUEUE; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1232) host->cmd_per_lun = 2; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1233) host->sg_tablesize = AHD_NSEG; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1234) host->this_id = ahd->our_id; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1235) host->irq = ahd->platform_data->irq; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1236) host->max_id = (ahd->features & AHD_WIDE) ? 16 : 8; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1237) host->max_lun = AHD_NUM_LUNS; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1238) host->max_channel = 0; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1239) host->sg_tablesize = AHD_NSEG; eb221849540b7 (Hannes Reinecke 2006-01-30 16:10:31 +0100 1240) ahd_lock(ahd, &s); 85a46523ff68a (Christoph Hellwig 2005-08-15 13:28:46 +0200 1241) ahd_set_unit(ahd, ahd_linux_unit++); eb221849540b7 (Hannes Reinecke 2006-01-30 16:10:31 +0100 1242) ahd_unlock(ahd, &s); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1243) sprintf(buf, "scsi%d", host->host_no); 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 1244) new_name = kmalloc(strlen(buf) + 1, GFP_ATOMIC); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1245) if (new_name != NULL) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1246) strcpy(new_name, buf); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1247) ahd_set_name(ahd, new_name); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1248) } 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1249) host->unique_id = ahd->unit; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1250) ahd_linux_initialize_scsi_bus(ahd); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1251) ahd_intr_enable(ahd, TRUE); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1252) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1253) host->transportt = ahd_linux_transport_template; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1254) e7a1ca1d27e20 (Jesper Juhl 2005-12-14 19:27:28 +0100 1255) retval = scsi_add_host(host, &ahd->dev_softc->dev); e7a1ca1d27e20 (Jesper Juhl 2005-12-14 19:27:28 +0100 1256) if (retval) { e7a1ca1d27e20 (Jesper Juhl 2005-12-14 19:27:28 +0100 1257) printk(KERN_WARNING "aic79xx: scsi_add_host failed\n"); e7a1ca1d27e20 (Jesper Juhl 2005-12-14 19:27:28 +0100 1258) scsi_host_put(host); e7a1ca1d27e20 (Jesper Juhl 2005-12-14 19:27:28 +0100 1259) return retval; e7a1ca1d27e20 (Jesper Juhl 2005-12-14 19:27:28 +0100 1260) } e7a1ca1d27e20 (Jesper Juhl 2005-12-14 19:27:28 +0100 1261) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1262) scsi_scan_host(host); e7a1ca1d27e20 (Jesper Juhl 2005-12-14 19:27:28 +0100 1263) return 0; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1264) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1265) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1266) /* 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1267) * Place the SCSI bus into a known state by either resetting it, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1268) * or forcing transfer negotiations on the next command to any 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1269) * target. 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1270) */ 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1271) static void 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1272) ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1273) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1274) u_int target_id; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1275) u_int numtarg; eb221849540b7 (Hannes Reinecke 2006-01-30 16:10:31 +0100 1276) unsigned long s; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1277) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1278) target_id = 0; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1279) numtarg = 0; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1280) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1281) if (aic79xx_no_reset != 0) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1282) ahd->flags &= ~AHD_RESET_BUS_A; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1283) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1284) if ((ahd->flags & AHD_RESET_BUS_A) != 0) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1285) ahd_reset_channel(ahd, 'A', /*initiate_reset*/TRUE); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1286) else 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1287) numtarg = (ahd->features & AHD_WIDE) ? 16 : 8; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1288) eb221849540b7 (Hannes Reinecke 2006-01-30 16:10:31 +0100 1289) ahd_lock(ahd, &s); eb221849540b7 (Hannes Reinecke 2006-01-30 16:10:31 +0100 1290) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1291) /* 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1292) * Force negotiation to async for all targets that 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1293) * will not see an initial bus reset. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1294) */ 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1295) for (; target_id < numtarg; target_id++) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1296) struct ahd_devinfo devinfo; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1297) struct ahd_initiator_tinfo *tinfo; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1298) struct ahd_tmode_tstate *tstate; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1299) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1300) tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1301) target_id, &tstate); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1302) ahd_compile_devinfo(&devinfo, ahd->our_id, target_id, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1303) CAM_LUN_WILDCARD, 'A', ROLE_INITIATOR); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1304) ahd_update_neg_request(ahd, &devinfo, tstate, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1305) tinfo, AHD_NEG_ALWAYS); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1306) } eb221849540b7 (Hannes Reinecke 2006-01-30 16:10:31 +0100 1307) ahd_unlock(ahd, &s); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1308) /* Give the bus some time to recover */ 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1309) if ((ahd->flags & AHD_RESET_BUS_A) != 0) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1310) ahd_freeze_simq(ahd); eb221849540b7 (Hannes Reinecke 2006-01-30 16:10:31 +0100 1311) msleep(AIC79XX_RESET_DELAY); eb221849540b7 (Hannes Reinecke 2006-01-30 16:10:31 +0100 1312) ahd_release_simq(ahd); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1313) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1314) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1315) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1316) int 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1317) ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1318) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1319) ahd->platform_data = 114fc1d9a8cc7 (Michael Opdenacker 2015-03-26 17:51:46 -0700 1320) kzalloc(sizeof(struct ahd_platform_data), GFP_ATOMIC); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1321) if (ahd->platform_data == NULL) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1322) return (ENOMEM); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1323) ahd->platform_data->irq = AHD_LINUX_NOIRQ; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1324) ahd_lockinit(ahd); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1325) ahd->seltime = (aic79xx_seltime & 0x3) << 4; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1326) return (0); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1327) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1328) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1329) void 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1330) ahd_platform_free(struct ahd_softc *ahd) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1331) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1332) struct scsi_target *starget; f89d0a4e1d011 (Hannes Reinecke 2006-06-22 11:45:00 +0200 1333) int i; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1334) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1335) if (ahd->platform_data != NULL) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1336) /* destroy all of the device and target objects */ 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1337) for (i = 0; i < AHD_NUM_TARGETS; i++) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1338) starget = ahd->platform_data->starget[i]; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1339) if (starget != NULL) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1340) ahd->platform_data->starget[i] = NULL; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1341) } 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1342) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1343) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1344) if (ahd->platform_data->irq != AHD_LINUX_NOIRQ) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1345) free_irq(ahd->platform_data->irq, ahd); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1346) if (ahd->tags[0] == BUS_SPACE_PIO 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1347) && ahd->bshs[0].ioport != 0) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1348) release_region(ahd->bshs[0].ioport, 256); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1349) if (ahd->tags[1] == BUS_SPACE_PIO 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1350) && ahd->bshs[1].ioport != 0) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1351) release_region(ahd->bshs[1].ioport, 256); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1352) if (ahd->tags[0] == BUS_SPACE_MEMIO 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1353) && ahd->bshs[0].maddr != NULL) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1354) iounmap(ahd->bshs[0].maddr); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1355) release_mem_region(ahd->platform_data->mem_busaddr, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1356) 0x1000); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1357) } 97af50f60ff12 (James Bottomley 2005-10-02 15:22:35 -0500 1358) if (ahd->platform_data->host) 97af50f60ff12 (James Bottomley 2005-10-02 15:22:35 -0500 1359) scsi_host_put(ahd->platform_data->host); 97af50f60ff12 (James Bottomley 2005-10-02 15:22:35 -0500 1360) 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 1361) kfree(ahd->platform_data); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1362) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1363) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1364) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1365) void 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1366) ahd_platform_init(struct ahd_softc *ahd) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1367) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1368) /* 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1369) * Lookup and commit any modified IO Cell options. 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1370) */ 6391a11375de5 (Tobias Klauser 2006-06-08 22:23:48 -0700 1371) if (ahd->unit < ARRAY_SIZE(aic79xx_iocell_info)) { 980b306a29772 (Denys Vlasenko 2008-04-25 04:36:01 +0200 1372) const struct ahd_linux_iocell_opts *iocell_opts; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1373) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1374) iocell_opts = &aic79xx_iocell_info[ahd->unit]; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1375) if (iocell_opts->precomp != AIC79XX_DEFAULT_PRECOMP) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1376) AHD_SET_PRECOMP(ahd, iocell_opts->precomp); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1377) if (iocell_opts->slewrate != AIC79XX_DEFAULT_SLEWRATE) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1378) AHD_SET_SLEWRATE(ahd, iocell_opts->slewrate); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1379) if (iocell_opts->amplitude != AIC79XX_DEFAULT_AMPLITUDE) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1380) AHD_SET_AMPLITUDE(ahd, iocell_opts->amplitude); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1381) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1382) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1383) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1384) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1385) void 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1386) ahd_platform_freeze_devq(struct ahd_softc *ahd, struct scb *scb) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1387) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1388) ahd_platform_abort_scbs(ahd, SCB_GET_TARGET(ahd, scb), 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1389) SCB_GET_CHANNEL(ahd, scb), 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1390) SCB_GET_LUN(scb), SCB_LIST_NULL, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1391) ROLE_UNKNOWN, CAM_REQUEUE_REQ); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1392) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1393) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1394) void f89d0a4e1d011 (Hannes Reinecke 2006-06-22 11:45:00 +0200 1395) ahd_platform_set_tags(struct ahd_softc *ahd, struct scsi_device *sdev, f89d0a4e1d011 (Hannes Reinecke 2006-06-22 11:45:00 +0200 1396) struct ahd_devinfo *devinfo, ahd_queue_alg alg) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1397) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1398) struct ahd_linux_device *dev; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1399) int was_queuing; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1400) int now_queuing; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1401) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1402) if (sdev == NULL) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1403) return; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1404) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1405) dev = scsi_transport_device_data(sdev); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1406) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1407) if (dev == NULL) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1408) return; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1409) was_queuing = dev->flags & (AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1410) switch (alg) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1411) default: 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1412) case AHD_QUEUE_NONE: 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1413) now_queuing = 0; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1414) break; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1415) case AHD_QUEUE_BASIC: 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1416) now_queuing = AHD_DEV_Q_BASIC; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1417) break; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1418) case AHD_QUEUE_TAGGED: 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1419) now_queuing = AHD_DEV_Q_TAGGED; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1420) break; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1421) } 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1422) if ((dev->flags & AHD_DEV_FREEZE_TIL_EMPTY) == 0 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1423) && (was_queuing != now_queuing) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1424) && (dev->active != 0)) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1425) dev->flags |= AHD_DEV_FREEZE_TIL_EMPTY; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1426) dev->qfrozen++; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1427) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1428) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1429) dev->flags &= ~(AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED|AHD_DEV_PERIODIC_OTAG); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1430) if (now_queuing) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1431) u_int usertags; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1432) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1433) usertags = ahd_linux_user_tagdepth(ahd, devinfo); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1434) if (!was_queuing) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1435) /* 25985edcedea6 (Lucas De Marchi 2011-03-30 22:57:33 -0300 1436) * Start out aggressively and allow our 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1437) * dynamic queue depth algorithm to take 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1438) * care of the rest. 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1439) */ 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1440) dev->maxtags = usertags; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1441) dev->openings = dev->maxtags - dev->active; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1442) } 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1443) if (dev->maxtags == 0) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1444) /* 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1445) * Queueing is disabled by the user. 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1446) */ 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1447) dev->openings = 1; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1448) } else if (alg == AHD_QUEUE_TAGGED) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1449) dev->flags |= AHD_DEV_Q_TAGGED; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1450) if (aic79xx_periodic_otag != 0) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1451) dev->flags |= AHD_DEV_PERIODIC_OTAG; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1452) } else 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1453) dev->flags |= AHD_DEV_Q_BASIC; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1454) } else { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1455) /* We can only have one opening. */ 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1456) dev->maxtags = 0; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1457) dev->openings = 1 - dev->active; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1458) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1459) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1460) switch ((dev->flags & (AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED))) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1461) case AHD_DEV_Q_BASIC: 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1462) case AHD_DEV_Q_TAGGED: db5ed4dfd5dd0 (Christoph Hellwig 2014-11-13 15:08:42 +0100 1463) scsi_change_queue_depth(sdev, 2ecb204d07ac8 (Christoph Hellwig 2014-11-03 14:09:02 +0100 1464) dev->openings + dev->active); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1465) break; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1466) default: ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1467) /* 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1468) * We allow the OS to queue 2 untagged transactions to 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1469) * us at any time even though we can only execute them 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1470) * serially on the controller/device. This should 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1471) * remove some latency. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1472) */ db5ed4dfd5dd0 (Christoph Hellwig 2014-11-13 15:08:42 +0100 1473) scsi_change_queue_depth(sdev, 1); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1474) break; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1475) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1476) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1477) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1478) int 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1479) ahd_platform_abort_scbs(struct ahd_softc *ahd, int target, char channel, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1480) int lun, u_int tag, role_t role, uint32_t status) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1481) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1482) return 0; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1483) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1484) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1485) static u_int 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1486) ahd_linux_user_tagdepth(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1487) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1488) static int warned_user; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1489) u_int tags; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1490) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1491) tags = 0; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1492) if ((ahd->user_discenable & devinfo->target_mask) != 0) { 6391a11375de5 (Tobias Klauser 2006-06-08 22:23:48 -0700 1493) if (ahd->unit >= ARRAY_SIZE(aic79xx_tag_info)) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1494) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1495) if (warned_user == 0) { 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 1496) printk(KERN_WARNING 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1497) "aic79xx: WARNING: Insufficient tag_info instances\n" 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1498) "aic79xx: for installed controllers. Using defaults\n" 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1499) "aic79xx: Please update the aic79xx_tag_info array in\n" 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1500) "aic79xx: the aic79xx_osm.c source file.\n"); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1501) warned_user++; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1502) } 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1503) tags = AHD_MAX_QUEUE; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1504) } else { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1505) adapter_tag_info_t *tag_info; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1506) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1507) tag_info = &aic79xx_tag_info[ahd->unit]; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1508) tags = tag_info->tag_commands[devinfo->target_offset]; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1509) if (tags > AHD_MAX_QUEUE) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1510) tags = AHD_MAX_QUEUE; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1511) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1512) } 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1513) return (tags); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1514) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1515) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1516) /* 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1517) * Determines the queue depth for a given device. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1518) */ ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1519) static void 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1520) ahd_linux_device_queue_depth(struct scsi_device *sdev) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1521) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1522) struct ahd_devinfo devinfo; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1523) u_int tags; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1524) struct ahd_softc *ahd = *((struct ahd_softc **)sdev->host->hostdata); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1525) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1526) ahd_compile_devinfo(&devinfo, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1527) ahd->our_id, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1528) sdev->sdev_target->id, sdev->lun, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1529) sdev->sdev_target->channel == 0 ? 'A' : 'B', 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1530) ROLE_INITIATOR); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1531) tags = ahd_linux_user_tagdepth(ahd, &devinfo); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1532) if (tags != 0 && sdev->tagged_supported != 0) { ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1533) f89d0a4e1d011 (Hannes Reinecke 2006-06-22 11:45:00 +0200 1534) ahd_platform_set_tags(ahd, sdev, &devinfo, AHD_QUEUE_TAGGED); f89d0a4e1d011 (Hannes Reinecke 2006-06-22 11:45:00 +0200 1535) ahd_send_async(ahd, devinfo.channel, devinfo.target, f89d0a4e1d011 (Hannes Reinecke 2006-06-22 11:45:00 +0200 1536) devinfo.lun, AC_TRANSFER_NEG); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1537) ahd_print_devinfo(ahd, &devinfo); 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 1538) printk("Tagged Queuing enabled. Depth %d\n", tags); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1539) } else { f89d0a4e1d011 (Hannes Reinecke 2006-06-22 11:45:00 +0200 1540) ahd_platform_set_tags(ahd, sdev, &devinfo, AHD_QUEUE_NONE); f89d0a4e1d011 (Hannes Reinecke 2006-06-22 11:45:00 +0200 1541) ahd_send_async(ahd, devinfo.channel, devinfo.target, f89d0a4e1d011 (Hannes Reinecke 2006-06-22 11:45:00 +0200 1542) devinfo.lun, AC_TRANSFER_NEG); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1543) } 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1544) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1545) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1546) static int 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1547) ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1548) struct scsi_cmnd *cmd) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1549) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1550) struct scb *scb; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1551) struct hardware_scb *hscb; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1552) struct ahd_initiator_tinfo *tinfo; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1553) struct ahd_tmode_tstate *tstate; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1554) u_int col_idx; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1555) uint16_t mask; 7b22da38b64a3 (Hannes Reinecke 2006-03-08 12:56:14 +0100 1556) unsigned long flags; 4c688fc7df618 (FUJITA Tomonori 2007-05-26 02:02:34 +0900 1557) int nseg; 7b22da38b64a3 (Hannes Reinecke 2006-03-08 12:56:14 +0100 1558) 2505873afe510 (FUJITA Tomonori 2008-03-09 22:50:40 +0900 1559) nseg = scsi_dma_map(cmd); 2505873afe510 (FUJITA Tomonori 2008-03-09 22:50:40 +0900 1560) if (nseg < 0) 2505873afe510 (FUJITA Tomonori 2008-03-09 22:50:40 +0900 1561) return SCSI_MLQUEUE_HOST_BUSY; 2505873afe510 (FUJITA Tomonori 2008-03-09 22:50:40 +0900 1562) 7b22da38b64a3 (Hannes Reinecke 2006-03-08 12:56:14 +0100 1563) ahd_lock(ahd, &flags); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1564) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1565) /* 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1566) * Get an scb to use. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1567) */ 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1568) tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1569) cmd->device->id, &tstate); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1570) if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) == 0 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1571) || (tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1572) col_idx = AHD_NEVER_COL_IDX; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1573) } else { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1574) col_idx = AHD_BUILD_COL_IDX(cmd->device->id, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1575) cmd->device->lun); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1576) } 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1577) if ((scb = ahd_get_scb(ahd, col_idx)) == NULL) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1578) ahd->flags |= AHD_RESOURCE_SHORTAGE; 7b22da38b64a3 (Hannes Reinecke 2006-03-08 12:56:14 +0100 1579) ahd_unlock(ahd, &flags); 2505873afe510 (FUJITA Tomonori 2008-03-09 22:50:40 +0900 1580) scsi_dma_unmap(cmd); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1581) return SCSI_MLQUEUE_HOST_BUSY; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1582) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1583) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1584) scb->io_ctx = cmd; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1585) scb->platform_data->dev = dev; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1586) hscb = scb->hscb; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1587) cmd->host_scribble = (char *)scb; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1588) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1589) /* 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1590) * Fill out basics of the HSCB. 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1591) */ 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1592) hscb->control = 0; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1593) hscb->scsiid = BUILD_SCSIID(ahd, cmd); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1594) hscb->lun = cmd->device->lun; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1595) scb->hscb->task_management = 0; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1596) mask = SCB_GET_TARGET_MASK(ahd, scb); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1597) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1598) if ((ahd->user_discenable & mask) != 0) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1599) hscb->control |= DISCENB; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1600) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1601) if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1602) scb->flags |= SCB_PACKETIZED; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1603) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1604) if ((tstate->auto_negotiate & mask) != 0) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1605) scb->flags |= SCB_AUTO_NEGOTIATE; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1606) scb->hscb->control |= MK_MESSAGE; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1607) } 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1608) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1609) if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) != 0) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1610) if (dev->commands_since_idle_or_otag == AHD_OTAG_THRESH 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1611) && (dev->flags & AHD_DEV_Q_TAGGED) != 0) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1612) hscb->control |= MSG_ORDERED_TASK; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1613) dev->commands_since_idle_or_otag = 0; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1614) } else { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1615) hscb->control |= MSG_SIMPLE_TASK; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1616) } 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1617) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1618) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1619) hscb->cdb_len = cmd->cmd_len; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1620) memcpy(hscb->shared_data.idata.cdb, cmd->cmnd, hscb->cdb_len); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1621) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1622) scb->platform_data->xfer_len = 0; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1623) ahd_set_residual(scb, 0); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1624) ahd_set_sense_residual(scb, 0); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1625) scb->sg_count = 0; 4c688fc7df618 (FUJITA Tomonori 2007-05-26 02:02:34 +0900 1626) 4c688fc7df618 (FUJITA Tomonori 2007-05-26 02:02:34 +0900 1627) if (nseg > 0) { 4c688fc7df618 (FUJITA Tomonori 2007-05-26 02:02:34 +0900 1628) void *sg = scb->sg_list; 4c688fc7df618 (FUJITA Tomonori 2007-05-26 02:02:34 +0900 1629) struct scatterlist *cur_seg; 4c688fc7df618 (FUJITA Tomonori 2007-05-26 02:02:34 +0900 1630) int i; 4c688fc7df618 (FUJITA Tomonori 2007-05-26 02:02:34 +0900 1631) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1632) scb->platform_data->xfer_len = 0; 4c688fc7df618 (FUJITA Tomonori 2007-05-26 02:02:34 +0900 1633) 4c688fc7df618 (FUJITA Tomonori 2007-05-26 02:02:34 +0900 1634) scsi_for_each_sg(cmd, cur_seg, nseg, i) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1635) dma_addr_t addr; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1636) bus_size_t len; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1637) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1638) addr = sg_dma_address(cur_seg); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1639) len = sg_dma_len(cur_seg); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1640) scb->platform_data->xfer_len += len; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1641) sg = ahd_sg_setup(ahd, scb, sg, addr, len, 4c688fc7df618 (FUJITA Tomonori 2007-05-26 02:02:34 +0900 1642) i == (nseg - 1)); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1643) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1644) } 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1645) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1646) LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1647) dev->openings--; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1648) dev->active++; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1649) dev->commands_issued++; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1650) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1651) if ((dev->flags & AHD_DEV_PERIODIC_OTAG) != 0) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1652) dev->commands_since_idle_or_otag++; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1653) scb->flags |= SCB_ACTIVE; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1654) ahd_queue_scb(ahd, scb); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1655) 7b22da38b64a3 (Hannes Reinecke 2006-03-08 12:56:14 +0100 1656) ahd_unlock(ahd, &flags); 7b22da38b64a3 (Hannes Reinecke 2006-03-08 12:56:14 +0100 1657) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1658) return 0; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1659) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1660) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1661) /* 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1662) * SCSI controller interrupt handler. 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1663) */ 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1664) irqreturn_t 7d12e780e003f (David Howells 2006-10-05 14:55:46 +0100 1665) ahd_linux_isr(int irq, void *dev_id) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1666) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1667) struct ahd_softc *ahd; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1668) u_long flags; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1669) int ours; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1670) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1671) ahd = (struct ahd_softc *) dev_id; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1672) ahd_lock(ahd, &flags); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1673) ours = ahd_intr(ahd); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1674) ahd_unlock(ahd, &flags); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1675) return IRQ_RETVAL(ours); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1676) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1677) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1678) void 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1679) ahd_send_async(struct ahd_softc *ahd, char channel, f89d0a4e1d011 (Hannes Reinecke 2006-06-22 11:45:00 +0200 1680) u_int target, u_int lun, ac_code code) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1681) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1682) switch (code) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1683) case AC_TRANSFER_NEG: 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1684) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1685) struct scsi_target *starget; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1686) struct ahd_initiator_tinfo *tinfo; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1687) struct ahd_tmode_tstate *tstate; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1688) unsigned int target_ppr_options; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1689) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1690) BUG_ON(target == CAM_TARGET_WILDCARD); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1691) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1692) tinfo = ahd_fetch_transinfo(ahd, channel, ahd->our_id, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1693) target, &tstate); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1694) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1695) /* 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1696) * Don't bother reporting results while 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1697) * negotiations are still pending. 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1698) */ 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1699) if (tinfo->curr.period != tinfo->goal.period 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1700) || tinfo->curr.width != tinfo->goal.width 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1701) || tinfo->curr.offset != tinfo->goal.offset 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1702) || tinfo->curr.ppr_options != tinfo->goal.ppr_options) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1703) if (bootverbose == 0) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1704) break; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1705) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1706) /* 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1707) * Don't bother reporting results that 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1708) * are identical to those last reported. 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1709) */ 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1710) starget = ahd->platform_data->starget[target]; fc789a9399485 (James Bottomley 2005-08-05 16:24:54 -0500 1711) if (starget == NULL) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1712) break; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1713) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1714) target_ppr_options = 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1715) (spi_dt(starget) ? MSG_EXT_PPR_DT_REQ : 0) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1716) + (spi_qas(starget) ? MSG_EXT_PPR_QAS_REQ : 0) 3f40d7d6eaade (James Bottomley 2005-08-03 13:25:10 -0500 1717) + (spi_iu(starget) ? MSG_EXT_PPR_IU_REQ : 0) 3f40d7d6eaade (James Bottomley 2005-08-03 13:25:10 -0500 1718) + (spi_rd_strm(starget) ? MSG_EXT_PPR_RD_STRM : 0) 3f40d7d6eaade (James Bottomley 2005-08-03 13:25:10 -0500 1719) + (spi_pcomp_en(starget) ? MSG_EXT_PPR_PCOMP_EN : 0) 3f40d7d6eaade (James Bottomley 2005-08-03 13:25:10 -0500 1720) + (spi_rti(starget) ? MSG_EXT_PPR_RTI : 0) 88ff29a4a5a8c (James Bottomley 2005-08-03 15:59:04 -0500 1721) + (spi_wr_flow(starget) ? MSG_EXT_PPR_WR_FLOW : 0) 88ff29a4a5a8c (James Bottomley 2005-08-03 15:59:04 -0500 1722) + (spi_hold_mcs(starget) ? MSG_EXT_PPR_HOLD_MCS : 0); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1723) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1724) if (tinfo->curr.period == spi_period(starget) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1725) && tinfo->curr.width == spi_width(starget) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1726) && tinfo->curr.offset == spi_offset(starget) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1727) && tinfo->curr.ppr_options == target_ppr_options) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1728) if (bootverbose == 0) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1729) break; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1730) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1731) spi_period(starget) = tinfo->curr.period; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1732) spi_width(starget) = tinfo->curr.width; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1733) spi_offset(starget) = tinfo->curr.offset; a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 1734) spi_dt(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_DT_REQ ? 1 : 0; a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 1735) spi_qas(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_QAS_REQ ? 1 : 0; a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 1736) spi_iu(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ ? 1 : 0; 3f40d7d6eaade (James Bottomley 2005-08-03 13:25:10 -0500 1737) spi_rd_strm(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_RD_STRM ? 1 : 0; 3f40d7d6eaade (James Bottomley 2005-08-03 13:25:10 -0500 1738) spi_pcomp_en(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_PCOMP_EN ? 1 : 0; 3f40d7d6eaade (James Bottomley 2005-08-03 13:25:10 -0500 1739) spi_rti(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_RTI ? 1 : 0; 3f40d7d6eaade (James Bottomley 2005-08-03 13:25:10 -0500 1740) spi_wr_flow(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_WR_FLOW ? 1 : 0; 88ff29a4a5a8c (James Bottomley 2005-08-03 15:59:04 -0500 1741) spi_hold_mcs(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_HOLD_MCS ? 1 : 0; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1742) spi_display_xfer_agreement(starget); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1743) break; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1744) } 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1745) case AC_SENT_BDR: 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1746) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1747) WARN_ON(lun != CAM_LUN_WILDCARD); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1748) scsi_report_device_reset(ahd->platform_data->host, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1749) channel - 'A', target); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1750) break; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1751) } 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1752) case AC_BUS_RESET: 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1753) if (ahd->platform_data->host != NULL) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1754) scsi_report_bus_reset(ahd->platform_data->host, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1755) channel - 'A'); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1756) } 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1757) break; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1758) default: 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1759) panic("ahd_send_async: Unexpected async event"); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1760) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1761) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1762) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1763) /* 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1764) * Calls the higher level scsi done function and frees the scb. 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1765) */ 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1766) void 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1767) ahd_done(struct ahd_softc *ahd, struct scb *scb) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1768) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1769) struct scsi_cmnd *cmd; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1770) struct ahd_linux_device *dev; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1771) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1772) if ((scb->flags & SCB_ACTIVE) == 0) { 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 1773) printk("SCB %d done'd twice\n", SCB_GET_TAG(scb)); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1774) ahd_dump_card_state(ahd); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1775) panic("Stopping for safety"); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1776) } 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1777) LIST_REMOVE(scb, pending_links); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1778) cmd = scb->io_ctx; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1779) dev = scb->platform_data->dev; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1780) dev->active--; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1781) dev->openings++; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1782) if ((cmd->result & (CAM_DEV_QFRZN << 16)) != 0) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1783) cmd->result &= ~(CAM_DEV_QFRZN << 16); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1784) dev->qfrozen--; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1785) } 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1786) ahd_linux_unmap_scb(ahd, scb); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1787) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1788) /* 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1789) * Guard against stale sense data. 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1790) * The Linux mid-layer assumes that sense 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1791) * was retrieved anytime the first byte of 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1792) * the sense buffer looks "sane". ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1793) */ 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1794) cmd->sense_buffer[0] = 0; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1795) if (ahd_get_transaction_status(scb) == CAM_REQ_INPROG) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1796) uint32_t amount_xferred; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1797) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1798) amount_xferred = 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1799) ahd_get_transfer_length(scb) - ahd_get_residual(scb); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1800) if ((scb->flags & SCB_TRANSMISSION_ERROR) != 0) { ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1801) #ifdef AHD_DEBUG 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1802) if ((ahd_debug & AHD_SHOW_MISC) != 0) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1803) ahd_print_path(ahd, scb); 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 1804) printk("Set CAM_UNCOR_PARITY\n"); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1805) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1806) #endif 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1807) ahd_set_transaction_status(scb, CAM_UNCOR_PARITY); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1808) #ifdef AHD_REPORT_UNDERFLOWS ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1809) /* 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1810) * This code is disabled by default as some 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1811) * clients of the SCSI system do not properly 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1812) * initialize the underflow parameter. This 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1813) * results in spurious termination of commands 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1814) * that complete as expected (e.g. underflow is 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1815) * allowed as command can return variable amounts 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1816) * of data. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1817) */ 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1818) } else if (amount_xferred < scb->io_ctx->underflow) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1819) u_int i; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1820) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1821) ahd_print_path(ahd, scb); 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 1822) printk("CDB:"); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1823) for (i = 0; i < scb->io_ctx->cmd_len; i++) 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 1824) printk(" 0x%x", scb->io_ctx->cmnd[i]); 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 1825) printk("\n"); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1826) ahd_print_path(ahd, scb); 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 1827) printk("Saw underflow (%ld of %ld bytes). " 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1828) "Treated as error\n", 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1829) ahd_get_residual(scb), 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1830) ahd_get_transfer_length(scb)); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1831) ahd_set_transaction_status(scb, CAM_DATA_RUN_ERR); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1832) #endif 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1833) } else { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1834) ahd_set_transaction_status(scb, CAM_REQ_CMP); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1835) } 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1836) } else if (ahd_get_transaction_status(scb) == CAM_SCSI_STATUS_ERROR) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1837) ahd_linux_handle_scsi_status(ahd, cmd->device, scb); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1838) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1839) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1840) if (dev->openings == 1 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1841) && ahd_get_transaction_status(scb) == CAM_REQ_CMP 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1842) && ahd_get_scsi_status(scb) != SCSI_STATUS_QUEUE_FULL) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1843) dev->tag_success_count++; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1844) /* 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1845) * Some devices deal with temporary internal resource 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1846) * shortages by returning queue full. When the queue 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1847) * full occurrs, we throttle back. Slowly try to get 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1848) * back to our previous queue depth. 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1849) */ 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1850) if ((dev->openings + dev->active) < dev->maxtags 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1851) && dev->tag_success_count > AHD_TAG_SUCCESS_INTERVAL) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1852) dev->tag_success_count = 0; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1853) dev->openings++; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1854) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1855) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1856) if (dev->active == 0) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1857) dev->commands_since_idle_or_otag = 0; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1858) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1859) if ((scb->flags & SCB_RECOVERY_SCB) != 0) { 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 1860) printk("Recovery SCB completes\n"); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1861) if (ahd_get_transaction_status(scb) == CAM_BDR_SENT 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1862) || ahd_get_transaction_status(scb) == CAM_REQ_ABORTED) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1863) ahd_set_transaction_status(scb, CAM_CMD_TIMEOUT); 7b22da38b64a3 (Hannes Reinecke 2006-03-08 12:56:14 +0100 1864) 7b22da38b64a3 (Hannes Reinecke 2006-03-08 12:56:14 +0100 1865) if (ahd->platform_data->eh_done) 7b22da38b64a3 (Hannes Reinecke 2006-03-08 12:56:14 +0100 1866) complete(ahd->platform_data->eh_done); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1867) } 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1868) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1869) ahd_free_scb(ahd, scb); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1870) ahd_linux_queue_cmd_complete(ahd, cmd); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1871) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1872) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1873) static void 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1874) ahd_linux_handle_scsi_status(struct ahd_softc *ahd, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1875) struct scsi_device *sdev, struct scb *scb) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1876) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1877) struct ahd_devinfo devinfo; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1878) struct ahd_linux_device *dev = scsi_transport_device_data(sdev); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1879) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1880) ahd_compile_devinfo(&devinfo, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1881) ahd->our_id, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1882) sdev->sdev_target->id, sdev->lun, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1883) sdev->sdev_target->channel == 0 ? 'A' : 'B', 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1884) ROLE_INITIATOR); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1885) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1886) /* 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1887) * We don't currently trust the mid-layer to 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1888) * properly deal with queue full or busy. So, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1889) * when one occurs, we tell the mid-layer to 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1890) * unconditionally requeue the command to us 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1891) * so that we can retry it ourselves. We also 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1892) * implement our own throttling mechanism so 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1893) * we don't clobber the device with too many 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1894) * commands. 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1895) */ 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1896) switch (ahd_get_scsi_status(scb)) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1897) default: 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1898) break; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1899) case SCSI_STATUS_CHECK_COND: 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1900) case SCSI_STATUS_CMD_TERMINATED: 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1901) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1902) struct scsi_cmnd *cmd; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1903) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1904) /* 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1905) * Copy sense information to the OS's cmd 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1906) * structure if it is available. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1907) */ 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1908) cmd = scb->io_ctx; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1909) if ((scb->flags & (SCB_SENSE|SCB_PKT_SENSE)) != 0) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1910) struct scsi_status_iu_header *siu; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1911) u_int sense_size; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1912) u_int sense_offset; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1913) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1914) if (scb->flags & SCB_SENSE) { 6d07cb71fdacc (Amol Lad 2006-10-20 14:48:40 -0700 1915) sense_size = min(sizeof(struct scsi_sense_data) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1916) - ahd_get_sense_residual(scb), b80ca4f7ee36c (FUJITA Tomonori 2008-01-13 15:46:13 +0900 1917) (u_long)SCSI_SENSE_BUFFERSIZE); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1918) sense_offset = 0; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1919) } else { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1920) /* 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1921) * Copy only the sense data into the provided 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1922) * buffer. 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1923) */ 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1924) siu = (struct scsi_status_iu_header *) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1925) scb->sense_data; 6d07cb71fdacc (Amol Lad 2006-10-20 14:48:40 -0700 1926) sense_size = min_t(size_t, 6d07cb71fdacc (Amol Lad 2006-10-20 14:48:40 -0700 1927) scsi_4btoul(siu->sense_length), b80ca4f7ee36c (FUJITA Tomonori 2008-01-13 15:46:13 +0900 1928) SCSI_SENSE_BUFFERSIZE); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1929) sense_offset = SIU_SENSE_OFFSET(siu); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1930) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1931) b80ca4f7ee36c (FUJITA Tomonori 2008-01-13 15:46:13 +0900 1932) memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1933) memcpy(cmd->sense_buffer, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1934) ahd_get_sense_buf(ahd, scb) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1935) + sense_offset, sense_size); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1936) cmd->result |= (DRIVER_SENSE << 24); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1937) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1938) #ifdef AHD_DEBUG 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1939) if (ahd_debug & AHD_SHOW_SENSE) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1940) int i; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1941) 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 1942) printk("Copied %d bytes of sense data at %d:", 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1943) sense_size, sense_offset); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1944) for (i = 0; i < sense_size; i++) { ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1945) if ((i & 0xF) == 0) 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 1946) printk("\n"); 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 1947) printk("0x%x ", cmd->sense_buffer[i]); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1948) } 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 1949) printk("\n"); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1950) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1951) #endif ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1952) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1953) break; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1954) } 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1955) case SCSI_STATUS_QUEUE_FULL: 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1956) /* 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1957) * By the time the core driver has returned this 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1958) * command, all other commands that were queued 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1959) * to us but not the device have been returned. 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1960) * This ensures that dev->active is equal to 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1961) * the number of commands actually queued to 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1962) * the device. 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1963) */ 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1964) dev->tag_success_count = 0; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1965) if (dev->active != 0) { ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1966) /* 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1967) * Drop our opening count to the number 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1968) * of commands currently outstanding. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1969) */ 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1970) dev->openings = 0; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1971) #ifdef AHD_DEBUG 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1972) if ((ahd_debug & AHD_SHOW_QFULL) != 0) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1973) ahd_print_path(ahd, scb); 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 1974) printk("Dropping tag count to %d\n", 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1975) dev->active); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1976) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1977) #endif 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1978) if (dev->active == dev->tags_on_last_queuefull) { ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1979) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1980) dev->last_queuefull_same_count++; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1981) /* 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1982) * If we repeatedly see a queue full 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1983) * at the same queue depth, this 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1984) * device has a fixed number of tag 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1985) * slots. Lock in this tag depth 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1986) * so we stop seeing queue fulls from 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1987) * this device. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1988) */ 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1989) if (dev->last_queuefull_same_count 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1990) == AHD_LOCK_TAGS_COUNT) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1991) dev->maxtags = dev->active; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1992) ahd_print_path(ahd, scb); 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 1993) printk("Locking max tag count at %d\n", 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1994) dev->active); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1995) } 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1996) } else { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1997) dev->tags_on_last_queuefull = dev->active; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 1998) dev->last_queuefull_same_count = 0; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1999) } 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2000) ahd_set_transaction_status(scb, CAM_REQUEUE_REQ); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2001) ahd_set_scsi_status(scb, SCSI_STATUS_OK); f89d0a4e1d011 (Hannes Reinecke 2006-06-22 11:45:00 +0200 2002) ahd_platform_set_tags(ahd, sdev, &devinfo, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2003) (dev->flags & AHD_DEV_Q_BASIC) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2004) ? AHD_QUEUE_BASIC : AHD_QUEUE_TAGGED); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2005) break; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2006) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2007) /* 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2008) * Drop down to a single opening, and treat this 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2009) * as if the target returned BUSY SCSI status. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2010) */ 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2011) dev->openings = 1; f89d0a4e1d011 (Hannes Reinecke 2006-06-22 11:45:00 +0200 2012) ahd_platform_set_tags(ahd, sdev, &devinfo, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2013) (dev->flags & AHD_DEV_Q_BASIC) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2014) ? AHD_QUEUE_BASIC : AHD_QUEUE_TAGGED); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2015) ahd_set_scsi_status(scb, SCSI_STATUS_BUSY); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2016) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2017) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2018) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2019) static void 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2020) ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, struct scsi_cmnd *cmd) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2021) { 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2022) int status; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2023) int new_status = DID_OK; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2024) int do_fallback = 0; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2025) int scsi_status; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2026) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2027) /* 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2028) * Map CAM error codes into Linux Error codes. We 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2029) * avoid the conversion so that the DV code has the 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2030) * full error information available when making 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2031) * state change decisions. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2032) */ 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2033) 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2034) status = ahd_cmd_get_transaction_status(cmd); 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2035) switch (status) { 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2036) case CAM_REQ_INPROG: 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2037) case CAM_REQ_CMP: 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2038) new_status = DID_OK; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2039) break; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2040) case CAM_AUTOSENSE_FAIL: 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2041) new_status = DID_ERROR; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2042) /* Fallthrough */ 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2043) case CAM_SCSI_STATUS_ERROR: 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2044) scsi_status = ahd_cmd_get_scsi_status(cmd); 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2045) 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2046) switch(scsi_status) { 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2047) case SCSI_STATUS_CMD_TERMINATED: 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2048) case SCSI_STATUS_CHECK_COND: 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2049) if ((cmd->result >> 24) != DRIVER_SENSE) { 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2050) do_fallback = 1; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2051) } else { 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2052) struct scsi_sense_data *sense; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2053) 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2054) sense = (struct scsi_sense_data *) c1c9ce52c8674 (FUJITA Tomonori 2008-01-27 12:41:09 +0900 2055) cmd->sense_buffer; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2056) if (sense->extra_len >= 5 && 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2057) (sense->add_sense_code == 0x47 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2058) || sense->add_sense_code == 0x48)) 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2059) do_fallback = 1; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2060) } 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2061) break; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2062) default: 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2063) break; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2064) } 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2065) break; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2066) case CAM_REQ_ABORTED: 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2067) new_status = DID_ABORT; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2068) break; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2069) case CAM_BUSY: 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2070) new_status = DID_BUS_BUSY; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2071) break; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2072) case CAM_REQ_INVALID: 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2073) case CAM_PATH_INVALID: 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2074) new_status = DID_BAD_TARGET; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2075) break; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2076) case CAM_SEL_TIMEOUT: 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2077) new_status = DID_NO_CONNECT; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2078) break; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2079) case CAM_SCSI_BUS_RESET: 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2080) case CAM_BDR_SENT: 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2081) new_status = DID_RESET; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2082) break; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2083) case CAM_UNCOR_PARITY: 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2084) new_status = DID_PARITY; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2085) do_fallback = 1; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2086) break; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2087) case CAM_CMD_TIMEOUT: 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2088) new_status = DID_TIME_OUT; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2089) do_fallback = 1; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2090) break; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2091) case CAM_REQ_CMP_ERR: 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2092) case CAM_UNEXP_BUSFREE: 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2093) case CAM_DATA_RUN_ERR: 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2094) new_status = DID_ERROR; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2095) do_fallback = 1; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2096) break; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2097) case CAM_UA_ABORT: 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2098) case CAM_NO_HBA: 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2099) case CAM_SEQUENCE_FAIL: 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2100) case CAM_CCB_LEN_ERR: 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2101) case CAM_PROVIDE_FAIL: 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2102) case CAM_REQ_TERMIO: 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2103) case CAM_UNREC_HBA_ERROR: 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2104) case CAM_REQ_TOO_BIG: 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2105) new_status = DID_ERROR; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2106) break; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2107) case CAM_REQUEUE_REQ: 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2108) new_status = DID_REQUEUE; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2109) break; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2110) default: 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2111) /* We should never get here */ 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2112) new_status = DID_ERROR; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2113) break; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2114) } 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2115) 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2116) if (do_fallback) { 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 2117) printk("%s: device overrun (status %x) on %d:%d:%d\n", 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2118) ahd_name(ahd), status, cmd->device->channel, 9cb78c16f5dad (Hannes Reinecke 2014-06-25 15:27:36 +0200 2119) cmd->device->id, (u8)cmd->device->lun); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2120) } 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2121) 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2122) ahd_cmd_set_transaction_status(cmd, new_status); 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2123) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2124) cmd->scsi_done(cmd); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2125) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2126) e3e0ca5143d7a (Adrian Bunk 2007-03-26 21:59:29 -0800 2127) static void 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2128) ahd_freeze_simq(struct ahd_softc *ahd) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2129) { 7b22da38b64a3 (Hannes Reinecke 2006-03-08 12:56:14 +0100 2130) scsi_block_requests(ahd->platform_data->host); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2131) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2132) e3e0ca5143d7a (Adrian Bunk 2007-03-26 21:59:29 -0800 2133) static void 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2134) ahd_release_simq(struct ahd_softc *ahd) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2135) { 7b22da38b64a3 (Hannes Reinecke 2006-03-08 12:56:14 +0100 2136) scsi_unblock_requests(ahd->platform_data->host); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2137) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2138) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2139) static int 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2140) ahd_linux_queue_abort_cmd(struct scsi_cmnd *cmd) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2141) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2142) struct ahd_softc *ahd; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2143) struct ahd_linux_device *dev; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2144) struct scb *pending_scb; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2145) u_int saved_scbptr; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2146) u_int active_scbptr; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2147) u_int last_phase; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2148) u_int saved_scsiid; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2149) u_int cdb_byte; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2150) int retval; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2151) int was_paused; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2152) int paused; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2153) int wait; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2154) int disconnected; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2155) ahd_mode_state saved_modes; 4065a413d7684 (Christoph Hellwig 2005-10-31 20:05:01 +0100 2156) unsigned long flags; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2157) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2158) pending_scb = NULL; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2159) paused = FALSE; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2160) wait = FALSE; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2161) ahd = *(struct ahd_softc **)cmd->device->host->hostdata; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2162) 017560fca496f (Jeff Garzik 2005-10-24 18:04:36 -0400 2163) scmd_printk(KERN_INFO, cmd, 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2164) "Attempting to queue an ABORT message:"); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2165) 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 2166) printk("CDB:"); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2167) for (cdb_byte = 0; cdb_byte < cmd->cmd_len; cdb_byte++) 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 2168) printk(" 0x%x", cmd->cmnd[cdb_byte]); 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 2169) printk("\n"); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2170) 4065a413d7684 (Christoph Hellwig 2005-10-31 20:05:01 +0100 2171) ahd_lock(ahd, &flags); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2172) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2173) /* 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2174) * First determine if we currently own this command. 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2175) * Start by searching the device queue. If not found 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2176) * there, check the pending_scb list. If not found 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2177) * at all, and the system wanted us to just abort the 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2178) * command, return success. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2179) */ 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2180) dev = scsi_transport_device_data(cmd->device); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2181) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2182) if (dev == NULL) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2183) /* 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2184) * No target device for this command exists, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2185) * so we must not still own the command. 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2186) */ 017560fca496f (Jeff Garzik 2005-10-24 18:04:36 -0400 2187) scmd_printk(KERN_INFO, cmd, "Is not an active device\n"); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2188) retval = SUCCESS; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2189) goto no_cmd; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2190) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2191) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2192) /* 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2193) * See if we can find a matching cmd in the pending list. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2194) */ 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2195) LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2196) if (pending_scb->io_ctx == cmd) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2197) break; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2198) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2199) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2200) if (pending_scb == NULL) { 017560fca496f (Jeff Garzik 2005-10-24 18:04:36 -0400 2201) scmd_printk(KERN_INFO, cmd, "Command not found\n"); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2202) goto no_cmd; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2203) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2204) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2205) if ((pending_scb->flags & SCB_RECOVERY_SCB) != 0) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2206) /* 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2207) * We can't queue two recovery actions using the same SCB 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2208) */ 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2209) retval = FAILED; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2210) goto done; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2211) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2212) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2213) /* 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2214) * Ensure that the card doesn't do anything 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2215) * behind our back. Also make sure that we 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2216) * didn't "just" miss an interrupt that would 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2217) * affect this cmd. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2218) */ 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2219) was_paused = ahd_is_paused(ahd); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2220) ahd_pause_and_flushwork(ahd); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2221) paused = TRUE; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2222) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2223) if ((pending_scb->flags & SCB_ACTIVE) == 0) { 017560fca496f (Jeff Garzik 2005-10-24 18:04:36 -0400 2224) scmd_printk(KERN_INFO, cmd, "Command already completed\n"); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2225) goto no_cmd; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2226) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2227) 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 2228) printk("%s: At time of recovery, card was %spaused\n", 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2229) ahd_name(ahd), was_paused ? "" : "not "); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2230) ahd_dump_card_state(ahd); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2231) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2232) disconnected = TRUE; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2233) if (ahd_search_qinfifo(ahd, cmd->device->id, 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2234) cmd->device->channel + 'A', 9cb78c16f5dad (Hannes Reinecke 2014-06-25 15:27:36 +0200 2235) cmd->device->lun, 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2236) pending_scb->hscb->tag, 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2237) ROLE_INITIATOR, CAM_REQ_ABORTED, 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2238) SEARCH_COMPLETE) > 0) { 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 2239) printk("%s:%d:%d:%d: Cmd aborted from QINFIFO\n", 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2240) ahd_name(ahd), cmd->device->channel, 9cb78c16f5dad (Hannes Reinecke 2014-06-25 15:27:36 +0200 2241) cmd->device->id, (u8)cmd->device->lun); 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2242) retval = SUCCESS; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2243) goto done; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2244) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2245) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2246) saved_modes = ahd_save_modes(ahd); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2247) ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2248) last_phase = ahd_inb(ahd, LASTPHASE); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2249) saved_scbptr = ahd_get_scbptr(ahd); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2250) active_scbptr = saved_scbptr; 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2251) if (disconnected && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2252) struct scb *bus_scb; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2253) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2254) bus_scb = ahd_lookup_scb(ahd, active_scbptr); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2255) if (bus_scb == pending_scb) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2256) disconnected = FALSE; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2257) } 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2258) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2259) /* 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2260) * At this point, pending_scb is the scb associated with the 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2261) * passed in command. That command is currently active on the 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2262) * bus or is in the disconnected state. 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2263) */ 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2264) saved_scsiid = ahd_inb(ahd, SAVED_SCSIID); 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2265) if (last_phase != P_BUSFREE 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2266) && SCB_GET_TAG(pending_scb) == active_scbptr) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2267) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2268) /* 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2269) * We're active on the bus, so assert ATN 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2270) * and hope that the target responds. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2271) */ 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2272) pending_scb = ahd_lookup_scb(ahd, active_scbptr); 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2273) pending_scb->flags |= SCB_RECOVERY_SCB|SCB_ABORT; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2274) ahd_outb(ahd, MSG_OUT, HOST_MSG); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2275) ahd_outb(ahd, SCSISIGO, last_phase|ATNO); 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2276) scmd_printk(KERN_INFO, cmd, "Device is active, asserting ATN\n"); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2277) wait = TRUE; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2278) } else if (disconnected) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2279) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2280) /* 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2281) * Actually re-queue this SCB in an attempt 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2282) * to select the device before it reconnects. 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2283) */ 6902f41610d63 (Hannes Reinecke 2006-03-08 12:58:16 +0100 2284) pending_scb->flags |= SCB_RECOVERY_SCB|SCB_ABORT; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2285) ahd_set_scbptr(ahd, SCB_GET_TAG(pending_scb)); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2286) pending_scb->hscb->cdb_len = 0; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2287) pending_scb->hscb->task_attribute = 0; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2288) pending_scb->hscb->task_management = SIU_TASKMGMT_ABORT_TASK; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2289) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2290) if ((pending_scb->flags & SCB_PACKETIZED) != 0) { ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2291) /* 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2292) * Mark the SCB has having an outstanding 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2293) * task management function. Should the command 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2294) * complete normally before the task management 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2295) * function can be sent, the host will be notified 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2296) * to abort our requeued SCB. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2297) */ 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2298) ahd_outb(ahd, SCB_TASK_MANAGEMENT, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2299) pending_scb->hscb->task_management); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2300) } else { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2301) /* 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2302) * If non-packetized, set the MK_MESSAGE control 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2303) * bit indicating that we desire to send a message. 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2304) * We also set the disconnected flag since there is 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2305) * no guarantee that our SCB control byte matches 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2306) * the version on the card. We don't want the 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2307) * sequencer to abort the command thinking an 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2308) * unsolicited reselection occurred. 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2309) */ 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2310) pending_scb->hscb->control |= MK_MESSAGE|DISCONNECTED; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2311) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2312) /* 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2313) * The sequencer will never re-reference the 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2314) * in-core SCB. To make sure we are notified b71a8eb0fa64e (Uwe Kleine-König 2009-10-06 12:42:51 +0200 2315) * during reselection, set the MK_MESSAGE flag in 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2316) * the card's copy of the SCB. 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2317) */ 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2318) ahd_outb(ahd, SCB_CONTROL, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2319) ahd_inb(ahd, SCB_CONTROL)|MK_MESSAGE); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2320) } 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2321) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2322) /* 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2323) * Clear out any entries in the QINFIFO first 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2324) * so we are the next SCB for this target 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2325) * to run. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2326) */ 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2327) ahd_search_qinfifo(ahd, cmd->device->id, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2328) cmd->device->channel + 'A', cmd->device->lun, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2329) SCB_LIST_NULL, ROLE_INITIATOR, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2330) CAM_REQUEUE_REQ, SEARCH_COMPLETE); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2331) ahd_qinfifo_requeue_tail(ahd, pending_scb); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2332) ahd_set_scbptr(ahd, saved_scbptr); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2333) ahd_print_path(ahd, pending_scb); 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 2334) printk("Device is disconnected, re-queuing SCB\n"); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2335) wait = TRUE; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2336) } else { 017560fca496f (Jeff Garzik 2005-10-24 18:04:36 -0400 2337) scmd_printk(KERN_INFO, cmd, "Unable to deliver message\n"); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2338) retval = FAILED; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2339) goto done; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2340) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2341) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2342) no_cmd: ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2343) /* 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2344) * Our assumption is that if we don't have the command, no 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2345) * recovery action was required, so we return success. Again, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2346) * the semantics of the mid-layer recovery engine are not 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2347) * well defined, so this may change in time. ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2348) */ 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2349) retval = SUCCESS; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2350) done: 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2351) if (paused) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2352) ahd_unpause(ahd); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2353) if (wait) { 6e9a4738c9fad (Peter Zijlstra 2006-09-30 23:28:10 -0700 2354) DECLARE_COMPLETION_ONSTACK(done); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2355) 7b22da38b64a3 (Hannes Reinecke 2006-03-08 12:56:14 +0100 2356) ahd->platform_data->eh_done = &done; 4065a413d7684 (Christoph Hellwig 2005-10-31 20:05:01 +0100 2357) ahd_unlock(ahd, &flags); 4065a413d7684 (Christoph Hellwig 2005-10-31 20:05:01 +0100 2358) 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 2359) printk("%s: Recovery code sleeping\n", ahd_name(ahd)); 7b22da38b64a3 (Hannes Reinecke 2006-03-08 12:56:14 +0100 2360) if (!wait_for_completion_timeout(&done, 5 * HZ)) { 7b22da38b64a3 (Hannes Reinecke 2006-03-08 12:56:14 +0100 2361) ahd_lock(ahd, &flags); 7b22da38b64a3 (Hannes Reinecke 2006-03-08 12:56:14 +0100 2362) ahd->platform_data->eh_done = NULL; 7b22da38b64a3 (Hannes Reinecke 2006-03-08 12:56:14 +0100 2363) ahd_unlock(ahd, &flags); 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 2364) printk("%s: Timer Expired (active %d)\n", 11668bb673c41 (Hannes Reinecke 2006-01-12 12:08:06 +0100 2365) ahd_name(ahd), dev->active); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2366) retval = FAILED; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2367) } 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 2368) printk("Recovery code awake\n"); eb221849540b7 (Hannes Reinecke 2006-01-30 16:10:31 +0100 2369) } else eb221849540b7 (Hannes Reinecke 2006-01-30 16:10:31 +0100 2370) ahd_unlock(ahd, &flags); eb221849540b7 (Hannes Reinecke 2006-01-30 16:10:31 +0100 2371) 7b22da38b64a3 (Hannes Reinecke 2006-03-08 12:56:14 +0100 2372) if (retval != SUCCESS) 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 2373) printk("%s: Command abort returning 0x%x\n", 7b22da38b64a3 (Hannes Reinecke 2006-03-08 12:56:14 +0100 2374) ahd_name(ahd), retval); 7b22da38b64a3 (Hannes Reinecke 2006-03-08 12:56:14 +0100 2375) 7b22da38b64a3 (Hannes Reinecke 2006-03-08 12:56:14 +0100 2376) return retval; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2377) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2378) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2379) static void ahd_linux_set_width(struct scsi_target *starget, int width) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2380) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2381) struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2382) struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2383) struct ahd_devinfo devinfo; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2384) unsigned long flags; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2385) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2386) ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2387) starget->channel + 'A', ROLE_INITIATOR); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2388) ahd_lock(ahd, &flags); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2389) ahd_set_width(ahd, &devinfo, width, AHD_TRANS_GOAL, FALSE); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2390) ahd_unlock(ahd, &flags); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2391) } 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2392) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2393) static void ahd_linux_set_period(struct scsi_target *starget, int period) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2394) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2395) struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2396) struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2397) struct ahd_tmode_tstate *tstate; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2398) struct ahd_initiator_tinfo *tinfo 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2399) = ahd_fetch_transinfo(ahd, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2400) starget->channel + 'A', 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2401) shost->this_id, starget->id, &tstate); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2402) struct ahd_devinfo devinfo; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2403) unsigned int ppr_options = tinfo->goal.ppr_options; a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2404) unsigned int dt; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2405) unsigned long flags; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2406) unsigned long offset = tinfo->goal.offset; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2407) a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2408) #ifdef AHD_DEBUG a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2409) if ((ahd_debug & AHD_SHOW_DV) != 0) 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 2410) printk("%s: set period to %d\n", ahd_name(ahd), period); a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2411) #endif 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2412) if (offset == 0) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2413) offset = MAX_OFFSET; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2414) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2415) if (period < 8) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2416) period = 8; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2417) if (period < 10) { 0f82cb9211f80 (James Bottomley 2007-07-26 17:13:10 -0400 2418) if (spi_max_width(starget)) { 0f82cb9211f80 (James Bottomley 2007-07-26 17:13:10 -0400 2419) ppr_options |= MSG_EXT_PPR_DT_REQ; 0f82cb9211f80 (James Bottomley 2007-07-26 17:13:10 -0400 2420) if (period == 8) 0f82cb9211f80 (James Bottomley 2007-07-26 17:13:10 -0400 2421) ppr_options |= MSG_EXT_PPR_IU_REQ; 0f82cb9211f80 (James Bottomley 2007-07-26 17:13:10 -0400 2422) } else 0f82cb9211f80 (James Bottomley 2007-07-26 17:13:10 -0400 2423) period = 10; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2424) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2425) a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2426) dt = ppr_options & MSG_EXT_PPR_DT_REQ; a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2427) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2428) ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2429) starget->channel + 'A', ROLE_INITIATOR); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2430) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2431) /* all PPR requests apart from QAS require wide transfers */ 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2432) if (ppr_options & ~MSG_EXT_PPR_QAS_REQ) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2433) if (spi_width(starget) == 0) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2434) ppr_options &= MSG_EXT_PPR_QAS_REQ; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2435) } 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2436) a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2437) ahd_find_syncrate(ahd, &period, &ppr_options, a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2438) dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2); a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2439) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2440) ahd_lock(ahd, &flags); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2441) ahd_set_syncrate(ahd, &devinfo, period, offset, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2442) ppr_options, AHD_TRANS_GOAL, FALSE); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2443) ahd_unlock(ahd, &flags); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2444) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2445) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2446) static void ahd_linux_set_offset(struct scsi_target *starget, int offset) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2447) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2448) struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2449) struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2450) struct ahd_tmode_tstate *tstate; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2451) struct ahd_initiator_tinfo *tinfo 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2452) = ahd_fetch_transinfo(ahd, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2453) starget->channel + 'A', 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2454) shost->this_id, starget->id, &tstate); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2455) struct ahd_devinfo devinfo; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2456) unsigned int ppr_options = 0; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2457) unsigned int period = 0; a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2458) unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2459) unsigned long flags; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2460) a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2461) #ifdef AHD_DEBUG a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2462) if ((ahd_debug & AHD_SHOW_DV) != 0) 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 2463) printk("%s: set offset to %d\n", ahd_name(ahd), offset); a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2464) #endif a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2465) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2466) ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2467) starget->channel + 'A', ROLE_INITIATOR); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2468) if (offset != 0) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2469) period = tinfo->goal.period; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2470) ppr_options = tinfo->goal.ppr_options; a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2471) ahd_find_syncrate(ahd, &period, &ppr_options, a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2472) dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2473) } a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2474) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2475) ahd_lock(ahd, &flags); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2476) ahd_set_syncrate(ahd, &devinfo, period, offset, ppr_options, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2477) AHD_TRANS_GOAL, FALSE); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2478) ahd_unlock(ahd, &flags); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2479) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2480) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2481) static void ahd_linux_set_dt(struct scsi_target *starget, int dt) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2482) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2483) struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2484) struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2485) struct ahd_tmode_tstate *tstate; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2486) struct ahd_initiator_tinfo *tinfo 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2487) = ahd_fetch_transinfo(ahd, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2488) starget->channel + 'A', 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2489) shost->this_id, starget->id, &tstate); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2490) struct ahd_devinfo devinfo; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2491) unsigned int ppr_options = tinfo->goal.ppr_options 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2492) & ~MSG_EXT_PPR_DT_REQ; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2493) unsigned int period = tinfo->goal.period; 52b5cfb355b2b (Hannes Reinecke 2005-08-04 09:16:59 +0200 2494) unsigned int width = tinfo->goal.width; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2495) unsigned long flags; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2496) a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2497) #ifdef AHD_DEBUG a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2498) if ((ahd_debug & AHD_SHOW_DV) != 0) 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 2499) printk("%s: %s DT\n", ahd_name(ahd), a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2500) dt ? "enabling" : "disabling"); a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2501) #endif 0f82cb9211f80 (James Bottomley 2007-07-26 17:13:10 -0400 2502) if (dt && spi_max_width(starget)) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2503) ppr_options |= MSG_EXT_PPR_DT_REQ; 52b5cfb355b2b (Hannes Reinecke 2005-08-04 09:16:59 +0200 2504) if (!width) 52b5cfb355b2b (Hannes Reinecke 2005-08-04 09:16:59 +0200 2505) ahd_linux_set_width(starget, 1); a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2506) } else { a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2507) if (period <= 9) a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2508) period = 10; /* If resetting DT, period must be >= 25ns */ a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2509) /* IU is invalid without DT set */ a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2510) ppr_options &= ~MSG_EXT_PPR_IU_REQ; a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2511) } 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2512) ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2513) starget->channel + 'A', ROLE_INITIATOR); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2514) ahd_find_syncrate(ahd, &period, &ppr_options, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2515) dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2); a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2516) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2517) ahd_lock(ahd, &flags); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2518) ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2519) ppr_options, AHD_TRANS_GOAL, FALSE); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2520) ahd_unlock(ahd, &flags); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2521) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2522) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2523) static void ahd_linux_set_qas(struct scsi_target *starget, int qas) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2524) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2525) struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2526) struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2527) struct ahd_tmode_tstate *tstate; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2528) struct ahd_initiator_tinfo *tinfo 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2529) = ahd_fetch_transinfo(ahd, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2530) starget->channel + 'A', 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2531) shost->this_id, starget->id, &tstate); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2532) struct ahd_devinfo devinfo; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2533) unsigned int ppr_options = tinfo->goal.ppr_options 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2534) & ~MSG_EXT_PPR_QAS_REQ; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2535) unsigned int period = tinfo->goal.period; a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2536) unsigned int dt; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2537) unsigned long flags; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2538) a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2539) #ifdef AHD_DEBUG a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2540) if ((ahd_debug & AHD_SHOW_DV) != 0) 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 2541) printk("%s: %s QAS\n", ahd_name(ahd), a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2542) qas ? "enabling" : "disabling"); a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2543) #endif a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2544) a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2545) if (qas) { a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2546) ppr_options |= MSG_EXT_PPR_QAS_REQ; a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2547) } a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2548) a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2549) dt = ppr_options & MSG_EXT_PPR_DT_REQ; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2550) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2551) ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2552) starget->channel + 'A', ROLE_INITIATOR); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2553) ahd_find_syncrate(ahd, &period, &ppr_options, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2554) dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2); a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2555) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2556) ahd_lock(ahd, &flags); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2557) ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2558) ppr_options, AHD_TRANS_GOAL, FALSE); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2559) ahd_unlock(ahd, &flags); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2560) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2561) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2562) static void ahd_linux_set_iu(struct scsi_target *starget, int iu) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2563) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2564) struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2565) struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2566) struct ahd_tmode_tstate *tstate; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2567) struct ahd_initiator_tinfo *tinfo 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2568) = ahd_fetch_transinfo(ahd, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2569) starget->channel + 'A', 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2570) shost->this_id, starget->id, &tstate); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2571) struct ahd_devinfo devinfo; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2572) unsigned int ppr_options = tinfo->goal.ppr_options 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2573) & ~MSG_EXT_PPR_IU_REQ; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2574) unsigned int period = tinfo->goal.period; a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2575) unsigned int dt; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2576) unsigned long flags; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2577) a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2578) #ifdef AHD_DEBUG a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2579) if ((ahd_debug & AHD_SHOW_DV) != 0) 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 2580) printk("%s: %s IU\n", ahd_name(ahd), a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2581) iu ? "enabling" : "disabling"); a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2582) #endif a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2583) 0f82cb9211f80 (James Bottomley 2007-07-26 17:13:10 -0400 2584) if (iu && spi_max_width(starget)) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2585) ppr_options |= MSG_EXT_PPR_IU_REQ; a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2586) ppr_options |= MSG_EXT_PPR_DT_REQ; /* IU requires DT */ a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2587) } a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2588) a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2589) dt = ppr_options & MSG_EXT_PPR_DT_REQ; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2590) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2591) ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2592) starget->channel + 'A', ROLE_INITIATOR); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2593) ahd_find_syncrate(ahd, &period, &ppr_options, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2594) dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2); a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2595) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2596) ahd_lock(ahd, &flags); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2597) ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2598) ppr_options, AHD_TRANS_GOAL, FALSE); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2599) ahd_unlock(ahd, &flags); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2600) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2601) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2602) static void ahd_linux_set_rd_strm(struct scsi_target *starget, int rdstrm) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2603) { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2604) struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2605) struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2606) struct ahd_tmode_tstate *tstate; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2607) struct ahd_initiator_tinfo *tinfo 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2608) = ahd_fetch_transinfo(ahd, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2609) starget->channel + 'A', 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2610) shost->this_id, starget->id, &tstate); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2611) struct ahd_devinfo devinfo; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2612) unsigned int ppr_options = tinfo->goal.ppr_options 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2613) & ~MSG_EXT_PPR_RD_STRM; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2614) unsigned int period = tinfo->goal.period; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2615) unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2616) unsigned long flags; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2617) a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2618) #ifdef AHD_DEBUG a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2619) if ((ahd_debug & AHD_SHOW_DV) != 0) 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 2620) printk("%s: %s Read Streaming\n", ahd_name(ahd), a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2621) rdstrm ? "enabling" : "disabling"); a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2622) #endif a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2623) 0f82cb9211f80 (James Bottomley 2007-07-26 17:13:10 -0400 2624) if (rdstrm && spi_max_width(starget)) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2625) ppr_options |= MSG_EXT_PPR_RD_STRM; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2626) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2627) ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2628) starget->channel + 'A', ROLE_INITIATOR); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2629) ahd_find_syncrate(ahd, &period, &ppr_options, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2630) dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2); a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2631) a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2632) ahd_lock(ahd, &flags); a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2633) ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset, a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2634) ppr_options, AHD_TRANS_GOAL, FALSE); a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2635) ahd_unlock(ahd, &flags); a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2636) } a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2637) a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2638) static void ahd_linux_set_wr_flow(struct scsi_target *starget, int wrflow) a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2639) { a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2640) struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2641) struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata); a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2642) struct ahd_tmode_tstate *tstate; a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2643) struct ahd_initiator_tinfo *tinfo a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2644) = ahd_fetch_transinfo(ahd, a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2645) starget->channel + 'A', a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2646) shost->this_id, starget->id, &tstate); a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2647) struct ahd_devinfo devinfo; a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2648) unsigned int ppr_options = tinfo->goal.ppr_options a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2649) & ~MSG_EXT_PPR_WR_FLOW; a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2650) unsigned int period = tinfo->goal.period; a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2651) unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ; a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2652) unsigned long flags; a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2653) a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2654) #ifdef AHD_DEBUG a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2655) if ((ahd_debug & AHD_SHOW_DV) != 0) 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 2656) printk("%s: %s Write Flow Control\n", ahd_name(ahd), a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2657) wrflow ? "enabling" : "disabling"); a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2658) #endif a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2659) 0f82cb9211f80 (James Bottomley 2007-07-26 17:13:10 -0400 2660) if (wrflow && spi_max_width(starget)) a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2661) ppr_options |= MSG_EXT_PPR_WR_FLOW; a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2662) a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2663) ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2664) starget->channel + 'A', ROLE_INITIATOR); a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2665) ahd_find_syncrate(ahd, &period, &ppr_options, a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2666) dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2); a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2667) a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2668) ahd_lock(ahd, &flags); a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2669) ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset, a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2670) ppr_options, AHD_TRANS_GOAL, FALSE); a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2671) ahd_unlock(ahd, &flags); a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2672) } a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2673) a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2674) static void ahd_linux_set_rti(struct scsi_target *starget, int rti) a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2675) { a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2676) struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2677) struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata); a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2678) struct ahd_tmode_tstate *tstate; a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2679) struct ahd_initiator_tinfo *tinfo a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2680) = ahd_fetch_transinfo(ahd, a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2681) starget->channel + 'A', a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2682) shost->this_id, starget->id, &tstate); a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2683) struct ahd_devinfo devinfo; a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2684) unsigned int ppr_options = tinfo->goal.ppr_options a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2685) & ~MSG_EXT_PPR_RTI; a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2686) unsigned int period = tinfo->goal.period; a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2687) unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ; a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2688) unsigned long flags; a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2689) a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2690) if ((ahd->features & AHD_RTI) == 0) { a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2691) #ifdef AHD_DEBUG a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2692) if ((ahd_debug & AHD_SHOW_DV) != 0) 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 2693) printk("%s: RTI not available\n", ahd_name(ahd)); a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2694) #endif a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2695) return; a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2696) } a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2697) a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2698) #ifdef AHD_DEBUG a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2699) if ((ahd_debug & AHD_SHOW_DV) != 0) 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 2700) printk("%s: %s RTI\n", ahd_name(ahd), a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2701) rti ? "enabling" : "disabling"); a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2702) #endif a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2703) 0f82cb9211f80 (James Bottomley 2007-07-26 17:13:10 -0400 2704) if (rti && spi_max_width(starget)) a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2705) ppr_options |= MSG_EXT_PPR_RTI; a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2706) a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2707) ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2708) starget->channel + 'A', ROLE_INITIATOR); a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2709) ahd_find_syncrate(ahd, &period, &ppr_options, a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2710) dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2); a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2711) a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2712) ahd_lock(ahd, &flags); a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2713) ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset, a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2714) ppr_options, AHD_TRANS_GOAL, FALSE); a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2715) ahd_unlock(ahd, &flags); a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2716) } a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2717) a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2718) static void ahd_linux_set_pcomp_en(struct scsi_target *starget, int pcomp) a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2719) { a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2720) struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2721) struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata); a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2722) struct ahd_tmode_tstate *tstate; a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2723) struct ahd_initiator_tinfo *tinfo a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2724) = ahd_fetch_transinfo(ahd, a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2725) starget->channel + 'A', a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2726) shost->this_id, starget->id, &tstate); a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2727) struct ahd_devinfo devinfo; a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2728) unsigned int ppr_options = tinfo->goal.ppr_options a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2729) & ~MSG_EXT_PPR_PCOMP_EN; a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2730) unsigned int period = tinfo->goal.period; a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2731) unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ; a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2732) unsigned long flags; a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2733) a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2734) #ifdef AHD_DEBUG a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2735) if ((ahd_debug & AHD_SHOW_DV) != 0) 48813cf989eb8 (Pekka Enberg 2010-07-14 13:12:57 +0300 2736) printk("%s: %s Precompensation\n", ahd_name(ahd), a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2737) pcomp ? "Enable" : "Disable"); a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2738) #endif a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2739) 0f82cb9211f80 (James Bottomley 2007-07-26 17:13:10 -0400 2740) if (pcomp && spi_max_width(starget)) { 843822ad63188 (Hannes Reinecke 2006-10-23 15:24:23 +0200 2741) uint8_t precomp; 843822ad63188 (Hannes Reinecke 2006-10-23 15:24:23 +0200 2742) 843822ad63188 (Hannes Reinecke 2006-10-23 15:24:23 +0200 2743) if (ahd->unit < ARRAY_SIZE(aic79xx_iocell_info)) { 980b306a29772 (Denys Vlasenko 2008-04-25 04:36:01 +0200 2744) const struct ahd_linux_iocell_opts *iocell_opts; 843822ad63188 (Hannes Reinecke 2006-10-23 15:24:23 +0200 2745) 843822ad63188 (Hannes Reinecke 2006-10-23 15:24:23 +0200 2746) iocell_opts = &aic79xx_iocell_info[ahd->unit]; 843822ad63188 (Hannes Reinecke 2006-10-23 15:24:23 +0200 2747) precomp = iocell_opts->precomp; 843822ad63188 (Hannes Reinecke 2006-10-23 15:24:23 +0200 2748) } else { 843822ad63188 (Hannes Reinecke 2006-10-23 15:24:23 +0200 2749) precomp = AIC79XX_DEFAULT_PRECOMP; 843822ad63188 (Hannes Reinecke 2006-10-23 15:24:23 +0200 2750) } a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2751) ppr_options |= MSG_EXT_PPR_PCOMP_EN; 843822ad63188 (Hannes Reinecke 2006-10-23 15:24:23 +0200 2752) AHD_SET_PRECOMP(ahd, precomp); 843822ad63188 (Hannes Reinecke 2006-10-23 15:24:23 +0200 2753) } else { 843822ad63188 (Hannes Reinecke 2006-10-23 15:24:23 +0200 2754) AHD_SET_PRECOMP(ahd, 0); 843822ad63188 (Hannes Reinecke 2006-10-23 15:24:23 +0200 2755) } a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2756) a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2757) ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2758) starget->channel + 'A', ROLE_INITIATOR); a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2759) ahd_find_syncrate(ahd, &period, &ppr_options, a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2760) dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2); a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2761) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2762) ahd_lock(ahd, &flags); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2763) ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2764) ppr_options, AHD_TRANS_GOAL, FALSE); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2765) ahd_unlock(ahd, &flags); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2766) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2767) 88ff29a4a5a8c (James Bottomley 2005-08-03 15:59:04 -0500 2768) static void ahd_linux_set_hold_mcs(struct scsi_target *starget, int hold) 88ff29a4a5a8c (James Bottomley 2005-08-03 15:59:04 -0500 2769) { 88ff29a4a5a8c (James Bottomley 2005-08-03 15:59:04 -0500 2770) struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); 88ff29a4a5a8c (James Bottomley 2005-08-03 15:59:04 -0500 2771) struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata); 88ff29a4a5a8c (James Bottomley 2005-08-03 15:59:04 -0500 2772) struct ahd_tmode_tstate *tstate; 88ff29a4a5a8c (James Bottomley 2005-08-03 15:59:04 -0500 2773) struct ahd_initiator_tinfo *tinfo 88ff29a4a5a8c (James Bottomley 2005-08-03 15:59:04 -0500 2774) = ahd_fetch_transinfo(ahd, 88ff29a4a5a8c (James Bottomley 2005-08-03 15:59:04 -0500 2775) starget->channel + 'A', 88ff29a4a5a8c (James Bottomley 2005-08-03 15:59:04 -0500 2776) shost->this_id, starget->id, &tstate); 88ff29a4a5a8c (James Bottomley 2005-08-03 15:59:04 -0500 2777) struct ahd_devinfo devinfo; 88ff29a4a5a8c (James Bottomley 2005-08-03 15:59:04 -0500 2778) unsigned int ppr_options = tinfo->goal.ppr_options 88ff29a4a5a8c (James Bottomley 2005-08-03 15:59:04 -0500 2779) & ~MSG_EXT_PPR_HOLD_MCS; 88ff29a4a5a8c (James Bottomley 2005-08-03 15:59:04 -0500 2780) unsigned int period = tinfo->goal.period; 88ff29a4a5a8c (James Bottomley 2005-08-03 15:59:04 -0500 2781) unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ; 88ff29a4a5a8c (James Bottomley 2005-08-03 15:59:04 -0500 2782) unsigned long flags; 88ff29a4a5a8c (James Bottomley 2005-08-03 15:59:04 -0500 2783) 0f82cb9211f80 (James Bottomley 2007-07-26 17:13:10 -0400 2784) if (hold && spi_max_width(starget)) 88ff29a4a5a8c (James Bottomley 2005-08-03 15:59:04 -0500 2785) ppr_options |= MSG_EXT_PPR_HOLD_MCS; 88ff29a4a5a8c (James Bottomley 2005-08-03 15:59:04 -0500 2786) 88ff29a4a5a8c (James Bottomley 2005-08-03 15:59:04 -0500 2787) ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, 88ff29a4a5a8c (James Bottomley 2005-08-03 15:59:04 -0500 2788) starget->channel + 'A', ROLE_INITIATOR); 88ff29a4a5a8c (James Bottomley 2005-08-03 15:59:04 -0500 2789) ahd_find_syncrate(ahd, &period, &ppr_options, 88ff29a4a5a8c (James Bottomley 2005-08-03 15:59:04 -0500 2790) dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2); 88ff29a4a5a8c (James Bottomley 2005-08-03 15:59:04 -0500 2791) 88ff29a4a5a8c (James Bottomley 2005-08-03 15:59:04 -0500 2792) ahd_lock(ahd, &flags); 88ff29a4a5a8c (James Bottomley 2005-08-03 15:59:04 -0500 2793) ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset, 88ff29a4a5a8c (James Bottomley 2005-08-03 15:59:04 -0500 2794) ppr_options, AHD_TRANS_GOAL, FALSE); 88ff29a4a5a8c (James Bottomley 2005-08-03 15:59:04 -0500 2795) ahd_unlock(ahd, &flags); 88ff29a4a5a8c (James Bottomley 2005-08-03 15:59:04 -0500 2796) } 88ff29a4a5a8c (James Bottomley 2005-08-03 15:59:04 -0500 2797) d6b9ccbbeb625 (Hannes Reinecke 2006-10-23 15:26:37 +0200 2798) static void ahd_linux_get_signalling(struct Scsi_Host *shost) d6b9ccbbeb625 (Hannes Reinecke 2006-10-23 15:26:37 +0200 2799) { d6b9ccbbeb625 (Hannes Reinecke 2006-10-23 15:26:37 +0200 2800) struct ahd_softc *ahd = *(struct ahd_softc **)shost->hostdata; d6b9ccbbeb625 (Hannes Reinecke 2006-10-23 15:26:37 +0200 2801) unsigned long flags; d6b9ccbbeb625 (Hannes Reinecke 2006-10-23 15:26:37 +0200 2802) u8 mode; 88ff29a4a5a8c (James Bottomley 2005-08-03 15:59:04 -0500 2803) d6b9ccbbeb625 (Hannes Reinecke 2006-10-23 15:26:37 +0200 2804) ahd_lock(ahd, &flags); d6b9ccbbeb625 (Hannes Reinecke 2006-10-23 15:26:37 +0200 2805) ahd_pause(ahd); d6b9ccbbeb625 (Hannes Reinecke 2006-10-23 15:26:37 +0200 2806) mode = ahd_inb(ahd, SBLKCTL); d6b9ccbbeb625 (Hannes Reinecke 2006-10-23 15:26:37 +0200 2807) ahd_unpause(ahd); d6b9ccbbeb625 (Hannes Reinecke 2006-10-23 15:26:37 +0200 2808) ahd_unlock(ahd, &flags); d6b9ccbbeb625 (Hannes Reinecke 2006-10-23 15:26:37 +0200 2809) d6b9ccbbeb625 (Hannes Reinecke 2006-10-23 15:26:37 +0200 2810) if (mode & ENAB40) d6b9ccbbeb625 (Hannes Reinecke 2006-10-23 15:26:37 +0200 2811) spi_signalling(shost) = SPI_SIGNAL_LVD; d6b9ccbbeb625 (Hannes Reinecke 2006-10-23 15:26:37 +0200 2812) else if (mode & ENAB20) d6b9ccbbeb625 (Hannes Reinecke 2006-10-23 15:26:37 +0200 2813) spi_signalling(shost) = SPI_SIGNAL_SE; d6b9ccbbeb625 (Hannes Reinecke 2006-10-23 15:26:37 +0200 2814) else d6b9ccbbeb625 (Hannes Reinecke 2006-10-23 15:26:37 +0200 2815) spi_signalling(shost) = SPI_SIGNAL_UNKNOWN; d6b9ccbbeb625 (Hannes Reinecke 2006-10-23 15:26:37 +0200 2816) } 88ff29a4a5a8c (James Bottomley 2005-08-03 15:59:04 -0500 2817) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2818) static struct spi_function_template ahd_linux_transport_functions = { 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2819) .set_offset = ahd_linux_set_offset, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2820) .show_offset = 1, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2821) .set_period = ahd_linux_set_period, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2822) .show_period = 1, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2823) .set_width = ahd_linux_set_width, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2824) .show_width = 1, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2825) .set_dt = ahd_linux_set_dt, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2826) .show_dt = 1, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2827) .set_iu = ahd_linux_set_iu, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2828) .show_iu = 1, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2829) .set_qas = ahd_linux_set_qas, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2830) .show_qas = 1, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2831) .set_rd_strm = ahd_linux_set_rd_strm, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2832) .show_rd_strm = 1, a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2833) .set_wr_flow = ahd_linux_set_wr_flow, a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2834) .show_wr_flow = 1, a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2835) .set_rti = ahd_linux_set_rti, a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2836) .show_rti = 1, a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2837) .set_pcomp_en = ahd_linux_set_pcomp_en, a4b53a11806f5 (Hannes Reinecke 2005-08-01 09:52:56 +0200 2838) .show_pcomp_en = 1, 88ff29a4a5a8c (James Bottomley 2005-08-03 15:59:04 -0500 2839) .set_hold_mcs = ahd_linux_set_hold_mcs, 88ff29a4a5a8c (James Bottomley 2005-08-03 15:59:04 -0500 2840) .show_hold_mcs = 1, d6b9ccbbeb625 (Hannes Reinecke 2006-10-23 15:26:37 +0200 2841) .get_signalling = ahd_linux_get_signalling, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2842) }; 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2843) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2844) static int __init ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2845) ahd_linux_init(void) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2846) { 85a46523ff68a (Christoph Hellwig 2005-08-15 13:28:46 +0200 2847) int error = 0; 85a46523ff68a (Christoph Hellwig 2005-08-15 13:28:46 +0200 2848) 85a46523ff68a (Christoph Hellwig 2005-08-15 13:28:46 +0200 2849) /* 85a46523ff68a (Christoph Hellwig 2005-08-15 13:28:46 +0200 2850) * If we've been passed any parameters, process them now. 85a46523ff68a (Christoph Hellwig 2005-08-15 13:28:46 +0200 2851) */ 85a46523ff68a (Christoph Hellwig 2005-08-15 13:28:46 +0200 2852) if (aic79xx) 85a46523ff68a (Christoph Hellwig 2005-08-15 13:28:46 +0200 2853) aic79xx_setup(aic79xx); 85a46523ff68a (Christoph Hellwig 2005-08-15 13:28:46 +0200 2854) 85a46523ff68a (Christoph Hellwig 2005-08-15 13:28:46 +0200 2855) ahd_linux_transport_template = 85a46523ff68a (Christoph Hellwig 2005-08-15 13:28:46 +0200 2856) spi_attach_transport(&ahd_linux_transport_functions); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2857) if (!ahd_linux_transport_template) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2858) return -ENODEV; 85a46523ff68a (Christoph Hellwig 2005-08-15 13:28:46 +0200 2859) 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2860) scsi_transport_reserve_device(ahd_linux_transport_template, 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2861) sizeof(struct ahd_linux_device)); a80b3424d9fde (James Bottomley 2005-08-08 19:06:50 -0500 2862) 85a46523ff68a (Christoph Hellwig 2005-08-15 13:28:46 +0200 2863) error = ahd_linux_pci_init(); 85a46523ff68a (Christoph Hellwig 2005-08-15 13:28:46 +0200 2864) if (error) 85a46523ff68a (Christoph Hellwig 2005-08-15 13:28:46 +0200 2865) spi_release_transport(ahd_linux_transport_template); 85a46523ff68a (Christoph Hellwig 2005-08-15 13:28:46 +0200 2866) return error; ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2867) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2868) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2869) static void __exit ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2870) ahd_linux_exit(void) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2871) { ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2872) ahd_linux_pci_exit(); 73a2546210077 (Hannes Reinecke 2005-07-22 16:44:04 +0200 2873) spi_release_transport(ahd_linux_transport_template); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2874) } ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2875) ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2876) module_init(ahd_linux_init); ^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2877) module_exit(ahd_linux_exit);