1*edd16368SStephen M. Cameron /* 2*edd16368SStephen M. Cameron * Disk Array driver for HP Smart Array SAS controllers 3*edd16368SStephen M. Cameron * Copyright 2000, 2009 Hewlett-Packard Development Company, L.P. 4*edd16368SStephen M. Cameron * 5*edd16368SStephen M. Cameron * This program is free software; you can redistribute it and/or modify 6*edd16368SStephen M. Cameron * it under the terms of the GNU General Public License as published by 7*edd16368SStephen M. Cameron * the Free Software Foundation; version 2 of the License. 8*edd16368SStephen M. Cameron * 9*edd16368SStephen M. Cameron * This program is distributed in the hope that it will be useful, 10*edd16368SStephen M. Cameron * but WITHOUT ANY WARRANTY; without even the implied warranty of 11*edd16368SStephen M. Cameron * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or 12*edd16368SStephen M. Cameron * NON INFRINGEMENT. See the GNU General Public License for more details. 13*edd16368SStephen M. Cameron * 14*edd16368SStephen M. Cameron * You should have received a copy of the GNU General Public License 15*edd16368SStephen M. Cameron * along with this program; if not, write to the Free Software 16*edd16368SStephen M. Cameron * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 17*edd16368SStephen M. Cameron * 18*edd16368SStephen M. Cameron * Questions/Comments/Bugfixes to iss_storagedev@hp.com 19*edd16368SStephen M. Cameron * 20*edd16368SStephen M. Cameron */ 21*edd16368SStephen M. Cameron 22*edd16368SStephen M. Cameron #include <linux/module.h> 23*edd16368SStephen M. Cameron #include <linux/interrupt.h> 24*edd16368SStephen M. Cameron #include <linux/types.h> 25*edd16368SStephen M. Cameron #include <linux/pci.h> 26*edd16368SStephen M. Cameron #include <linux/kernel.h> 27*edd16368SStephen M. Cameron #include <linux/slab.h> 28*edd16368SStephen M. Cameron #include <linux/delay.h> 29*edd16368SStephen M. Cameron #include <linux/fs.h> 30*edd16368SStephen M. Cameron #include <linux/timer.h> 31*edd16368SStephen M. Cameron #include <linux/seq_file.h> 32*edd16368SStephen M. Cameron #include <linux/init.h> 33*edd16368SStephen M. Cameron #include <linux/spinlock.h> 34*edd16368SStephen M. Cameron #include <linux/smp_lock.h> 35*edd16368SStephen M. Cameron #include <linux/compat.h> 36*edd16368SStephen M. Cameron #include <linux/blktrace_api.h> 37*edd16368SStephen M. Cameron #include <linux/uaccess.h> 38*edd16368SStephen M. Cameron #include <linux/io.h> 39*edd16368SStephen M. Cameron #include <linux/dma-mapping.h> 40*edd16368SStephen M. Cameron #include <linux/completion.h> 41*edd16368SStephen M. Cameron #include <linux/moduleparam.h> 42*edd16368SStephen M. Cameron #include <scsi/scsi.h> 43*edd16368SStephen M. Cameron #include <scsi/scsi_cmnd.h> 44*edd16368SStephen M. Cameron #include <scsi/scsi_device.h> 45*edd16368SStephen M. Cameron #include <scsi/scsi_host.h> 46*edd16368SStephen M. Cameron #include <linux/cciss_ioctl.h> 47*edd16368SStephen M. Cameron #include <linux/string.h> 48*edd16368SStephen M. Cameron #include <linux/bitmap.h> 49*edd16368SStephen M. Cameron #include <asm/atomic.h> 50*edd16368SStephen M. Cameron #include <linux/kthread.h> 51*edd16368SStephen M. Cameron #include "hpsa_cmd.h" 52*edd16368SStephen M. Cameron #include "hpsa.h" 53*edd16368SStephen M. Cameron 54*edd16368SStephen M. Cameron /* HPSA_DRIVER_VERSION must be 3 byte values (0-255) separated by '.' */ 55*edd16368SStephen M. Cameron #define HPSA_DRIVER_VERSION "1.0.0" 56*edd16368SStephen M. Cameron #define DRIVER_NAME "HP HPSA Driver (v " HPSA_DRIVER_VERSION ")" 57*edd16368SStephen M. Cameron 58*edd16368SStephen M. Cameron /* How long to wait (in milliseconds) for board to go into simple mode */ 59*edd16368SStephen M. Cameron #define MAX_CONFIG_WAIT 30000 60*edd16368SStephen M. Cameron #define MAX_IOCTL_CONFIG_WAIT 1000 61*edd16368SStephen M. Cameron 62*edd16368SStephen M. Cameron /*define how many times we will try a command because of bus resets */ 63*edd16368SStephen M. Cameron #define MAX_CMD_RETRIES 3 64*edd16368SStephen M. Cameron 65*edd16368SStephen M. Cameron /* Embedded module documentation macros - see modules.h */ 66*edd16368SStephen M. Cameron MODULE_AUTHOR("Hewlett-Packard Company"); 67*edd16368SStephen M. Cameron MODULE_DESCRIPTION("Driver for HP Smart Array Controller version " \ 68*edd16368SStephen M. Cameron HPSA_DRIVER_VERSION); 69*edd16368SStephen M. Cameron MODULE_SUPPORTED_DEVICE("HP Smart Array Controllers"); 70*edd16368SStephen M. Cameron MODULE_VERSION(HPSA_DRIVER_VERSION); 71*edd16368SStephen M. Cameron MODULE_LICENSE("GPL"); 72*edd16368SStephen M. Cameron 73*edd16368SStephen M. Cameron static int hpsa_allow_any; 74*edd16368SStephen M. Cameron module_param(hpsa_allow_any, int, S_IRUGO|S_IWUSR); 75*edd16368SStephen M. Cameron MODULE_PARM_DESC(hpsa_allow_any, 76*edd16368SStephen M. Cameron "Allow hpsa driver to access unknown HP Smart Array hardware"); 77*edd16368SStephen M. Cameron 78*edd16368SStephen M. Cameron /* define the PCI info for the cards we can control */ 79*edd16368SStephen M. Cameron static const struct pci_device_id hpsa_pci_device_id[] = { 80*edd16368SStephen M. Cameron {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC, 0x103C, 0x3223}, 81*edd16368SStephen M. Cameron {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC, 0x103C, 0x3234}, 82*edd16368SStephen M. Cameron {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC, 0x103C, 0x323D}, 83*edd16368SStephen M. Cameron {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3241}, 84*edd16368SStephen M. Cameron {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3243}, 85*edd16368SStephen M. Cameron {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3245}, 86*edd16368SStephen M. Cameron {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3247}, 87*edd16368SStephen M. Cameron {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3249}, 88*edd16368SStephen M. Cameron {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x324a}, 89*edd16368SStephen M. Cameron {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x324b}, 90*edd16368SStephen M. Cameron {PCI_VENDOR_ID_HP, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 91*edd16368SStephen M. Cameron PCI_CLASS_STORAGE_RAID << 8, 0xffff << 8, 0}, 92*edd16368SStephen M. Cameron {0,} 93*edd16368SStephen M. Cameron }; 94*edd16368SStephen M. Cameron 95*edd16368SStephen M. Cameron MODULE_DEVICE_TABLE(pci, hpsa_pci_device_id); 96*edd16368SStephen M. Cameron 97*edd16368SStephen M. Cameron /* board_id = Subsystem Device ID & Vendor ID 98*edd16368SStephen M. Cameron * product = Marketing Name for the board 99*edd16368SStephen M. Cameron * access = Address of the struct of function pointers 100*edd16368SStephen M. Cameron */ 101*edd16368SStephen M. Cameron static struct board_type products[] = { 102*edd16368SStephen M. Cameron {0x3223103C, "Smart Array P800", &SA5_access}, 103*edd16368SStephen M. Cameron {0x3234103C, "Smart Array P400", &SA5_access}, 104*edd16368SStephen M. Cameron {0x323d103c, "Smart Array P700M", &SA5_access}, 105*edd16368SStephen M. Cameron {0x3241103C, "Smart Array P212", &SA5_access}, 106*edd16368SStephen M. Cameron {0x3243103C, "Smart Array P410", &SA5_access}, 107*edd16368SStephen M. Cameron {0x3245103C, "Smart Array P410i", &SA5_access}, 108*edd16368SStephen M. Cameron {0x3247103C, "Smart Array P411", &SA5_access}, 109*edd16368SStephen M. Cameron {0x3249103C, "Smart Array P812", &SA5_access}, 110*edd16368SStephen M. Cameron {0x324a103C, "Smart Array P712m", &SA5_access}, 111*edd16368SStephen M. Cameron {0x324b103C, "Smart Array P711m", &SA5_access}, 112*edd16368SStephen M. Cameron {0xFFFF103C, "Unknown Smart Array", &SA5_access}, 113*edd16368SStephen M. Cameron }; 114*edd16368SStephen M. Cameron 115*edd16368SStephen M. Cameron static int number_of_controllers; 116*edd16368SStephen M. Cameron 117*edd16368SStephen M. Cameron static irqreturn_t do_hpsa_intr(int irq, void *dev_id); 118*edd16368SStephen M. Cameron static int hpsa_ioctl(struct scsi_device *dev, int cmd, void *arg); 119*edd16368SStephen M. Cameron static void start_io(struct ctlr_info *h); 120*edd16368SStephen M. Cameron 121*edd16368SStephen M. Cameron #ifdef CONFIG_COMPAT 122*edd16368SStephen M. Cameron static int hpsa_compat_ioctl(struct scsi_device *dev, int cmd, void *arg); 123*edd16368SStephen M. Cameron #endif 124*edd16368SStephen M. Cameron 125*edd16368SStephen M. Cameron static void cmd_free(struct ctlr_info *h, struct CommandList *c); 126*edd16368SStephen M. Cameron static void cmd_special_free(struct ctlr_info *h, struct CommandList *c); 127*edd16368SStephen M. Cameron static struct CommandList *cmd_alloc(struct ctlr_info *h); 128*edd16368SStephen M. Cameron static struct CommandList *cmd_special_alloc(struct ctlr_info *h); 129*edd16368SStephen M. Cameron static void fill_cmd(struct CommandList *c, __u8 cmd, struct ctlr_info *h, 130*edd16368SStephen M. Cameron void *buff, size_t size, __u8 page_code, unsigned char *scsi3addr, 131*edd16368SStephen M. Cameron int cmd_type); 132*edd16368SStephen M. Cameron 133*edd16368SStephen M. Cameron static int hpsa_scsi_queue_command(struct scsi_cmnd *cmd, 134*edd16368SStephen M. Cameron void (*done)(struct scsi_cmnd *)); 135*edd16368SStephen M. Cameron 136*edd16368SStephen M. Cameron static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd); 137*edd16368SStephen M. Cameron static int hpsa_slave_alloc(struct scsi_device *sdev); 138*edd16368SStephen M. Cameron static void hpsa_slave_destroy(struct scsi_device *sdev); 139*edd16368SStephen M. Cameron 140*edd16368SStephen M. Cameron static ssize_t raid_level_show(struct device *dev, 141*edd16368SStephen M. Cameron struct device_attribute *attr, char *buf); 142*edd16368SStephen M. Cameron static ssize_t lunid_show(struct device *dev, 143*edd16368SStephen M. Cameron struct device_attribute *attr, char *buf); 144*edd16368SStephen M. Cameron static ssize_t unique_id_show(struct device *dev, 145*edd16368SStephen M. Cameron struct device_attribute *attr, char *buf); 146*edd16368SStephen M. Cameron static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno); 147*edd16368SStephen M. Cameron static ssize_t host_store_rescan(struct device *dev, 148*edd16368SStephen M. Cameron struct device_attribute *attr, const char *buf, size_t count); 149*edd16368SStephen M. Cameron static int check_for_unit_attention(struct ctlr_info *h, 150*edd16368SStephen M. Cameron struct CommandList *c); 151*edd16368SStephen M. Cameron static void check_ioctl_unit_attention(struct ctlr_info *h, 152*edd16368SStephen M. Cameron struct CommandList *c); 153*edd16368SStephen M. Cameron 154*edd16368SStephen M. Cameron static DEVICE_ATTR(raid_level, S_IRUGO, raid_level_show, NULL); 155*edd16368SStephen M. Cameron static DEVICE_ATTR(lunid, S_IRUGO, lunid_show, NULL); 156*edd16368SStephen M. Cameron static DEVICE_ATTR(unique_id, S_IRUGO, unique_id_show, NULL); 157*edd16368SStephen M. Cameron static DEVICE_ATTR(rescan, S_IWUSR, NULL, host_store_rescan); 158*edd16368SStephen M. Cameron 159*edd16368SStephen M. Cameron static struct device_attribute *hpsa_sdev_attrs[] = { 160*edd16368SStephen M. Cameron &dev_attr_raid_level, 161*edd16368SStephen M. Cameron &dev_attr_lunid, 162*edd16368SStephen M. Cameron &dev_attr_unique_id, 163*edd16368SStephen M. Cameron NULL, 164*edd16368SStephen M. Cameron }; 165*edd16368SStephen M. Cameron 166*edd16368SStephen M. Cameron static struct device_attribute *hpsa_shost_attrs[] = { 167*edd16368SStephen M. Cameron &dev_attr_rescan, 168*edd16368SStephen M. Cameron NULL, 169*edd16368SStephen M. Cameron }; 170*edd16368SStephen M. Cameron 171*edd16368SStephen M. Cameron static struct scsi_host_template hpsa_driver_template = { 172*edd16368SStephen M. Cameron .module = THIS_MODULE, 173*edd16368SStephen M. Cameron .name = "hpsa", 174*edd16368SStephen M. Cameron .proc_name = "hpsa", 175*edd16368SStephen M. Cameron .queuecommand = hpsa_scsi_queue_command, 176*edd16368SStephen M. Cameron .can_queue = 512, 177*edd16368SStephen M. Cameron .this_id = -1, 178*edd16368SStephen M. Cameron .sg_tablesize = MAXSGENTRIES, 179*edd16368SStephen M. Cameron .cmd_per_lun = 512, 180*edd16368SStephen M. Cameron .use_clustering = ENABLE_CLUSTERING, 181*edd16368SStephen M. Cameron .eh_device_reset_handler = hpsa_eh_device_reset_handler, 182*edd16368SStephen M. Cameron .ioctl = hpsa_ioctl, 183*edd16368SStephen M. Cameron .slave_alloc = hpsa_slave_alloc, 184*edd16368SStephen M. Cameron .slave_destroy = hpsa_slave_destroy, 185*edd16368SStephen M. Cameron #ifdef CONFIG_COMPAT 186*edd16368SStephen M. Cameron .compat_ioctl = hpsa_compat_ioctl, 187*edd16368SStephen M. Cameron #endif 188*edd16368SStephen M. Cameron .sdev_attrs = hpsa_sdev_attrs, 189*edd16368SStephen M. Cameron .shost_attrs = hpsa_shost_attrs, 190*edd16368SStephen M. Cameron }; 191*edd16368SStephen M. Cameron 192*edd16368SStephen M. Cameron static inline struct ctlr_info *sdev_to_hba(struct scsi_device *sdev) 193*edd16368SStephen M. Cameron { 194*edd16368SStephen M. Cameron unsigned long *priv = shost_priv(sdev->host); 195*edd16368SStephen M. Cameron return (struct ctlr_info *) *priv; 196*edd16368SStephen M. Cameron } 197*edd16368SStephen M. Cameron 198*edd16368SStephen M. Cameron static struct task_struct *hpsa_scan_thread; 199*edd16368SStephen M. Cameron static DEFINE_MUTEX(hpsa_scan_mutex); 200*edd16368SStephen M. Cameron static LIST_HEAD(hpsa_scan_q); 201*edd16368SStephen M. Cameron static int hpsa_scan_func(void *data); 202*edd16368SStephen M. Cameron 203*edd16368SStephen M. Cameron /** 204*edd16368SStephen M. Cameron * add_to_scan_list() - add controller to rescan queue 205*edd16368SStephen M. Cameron * @h: Pointer to the controller. 206*edd16368SStephen M. Cameron * 207*edd16368SStephen M. Cameron * Adds the controller to the rescan queue if not already on the queue. 208*edd16368SStephen M. Cameron * 209*edd16368SStephen M. Cameron * returns 1 if added to the queue, 0 if skipped (could be on the 210*edd16368SStephen M. Cameron * queue already, or the controller could be initializing or shutting 211*edd16368SStephen M. Cameron * down). 212*edd16368SStephen M. Cameron **/ 213*edd16368SStephen M. Cameron static int add_to_scan_list(struct ctlr_info *h) 214*edd16368SStephen M. Cameron { 215*edd16368SStephen M. Cameron struct ctlr_info *test_h; 216*edd16368SStephen M. Cameron int found = 0; 217*edd16368SStephen M. Cameron int ret = 0; 218*edd16368SStephen M. Cameron 219*edd16368SStephen M. Cameron if (h->busy_initializing) 220*edd16368SStephen M. Cameron return 0; 221*edd16368SStephen M. Cameron 222*edd16368SStephen M. Cameron /* 223*edd16368SStephen M. Cameron * If we don't get the lock, it means the driver is unloading 224*edd16368SStephen M. Cameron * and there's no point in scheduling a new scan. 225*edd16368SStephen M. Cameron */ 226*edd16368SStephen M. Cameron if (!mutex_trylock(&h->busy_shutting_down)) 227*edd16368SStephen M. Cameron return 0; 228*edd16368SStephen M. Cameron 229*edd16368SStephen M. Cameron mutex_lock(&hpsa_scan_mutex); 230*edd16368SStephen M. Cameron list_for_each_entry(test_h, &hpsa_scan_q, scan_list) { 231*edd16368SStephen M. Cameron if (test_h == h) { 232*edd16368SStephen M. Cameron found = 1; 233*edd16368SStephen M. Cameron break; 234*edd16368SStephen M. Cameron } 235*edd16368SStephen M. Cameron } 236*edd16368SStephen M. Cameron if (!found && !h->busy_scanning) { 237*edd16368SStephen M. Cameron INIT_COMPLETION(h->scan_wait); 238*edd16368SStephen M. Cameron list_add_tail(&h->scan_list, &hpsa_scan_q); 239*edd16368SStephen M. Cameron ret = 1; 240*edd16368SStephen M. Cameron } 241*edd16368SStephen M. Cameron mutex_unlock(&hpsa_scan_mutex); 242*edd16368SStephen M. Cameron mutex_unlock(&h->busy_shutting_down); 243*edd16368SStephen M. Cameron 244*edd16368SStephen M. Cameron return ret; 245*edd16368SStephen M. Cameron } 246*edd16368SStephen M. Cameron 247*edd16368SStephen M. Cameron /** 248*edd16368SStephen M. Cameron * remove_from_scan_list() - remove controller from rescan queue 249*edd16368SStephen M. Cameron * @h: Pointer to the controller. 250*edd16368SStephen M. Cameron * 251*edd16368SStephen M. Cameron * Removes the controller from the rescan queue if present. Blocks if 252*edd16368SStephen M. Cameron * the controller is currently conducting a rescan. The controller 253*edd16368SStephen M. Cameron * can be in one of three states: 254*edd16368SStephen M. Cameron * 1. Doesn't need a scan 255*edd16368SStephen M. Cameron * 2. On the scan list, but not scanning yet (we remove it) 256*edd16368SStephen M. Cameron * 3. Busy scanning (and not on the list). In this case we want to wait for 257*edd16368SStephen M. Cameron * the scan to complete to make sure the scanning thread for this 258*edd16368SStephen M. Cameron * controller is completely idle. 259*edd16368SStephen M. Cameron **/ 260*edd16368SStephen M. Cameron static void remove_from_scan_list(struct ctlr_info *h) 261*edd16368SStephen M. Cameron { 262*edd16368SStephen M. Cameron struct ctlr_info *test_h, *tmp_h; 263*edd16368SStephen M. Cameron 264*edd16368SStephen M. Cameron mutex_lock(&hpsa_scan_mutex); 265*edd16368SStephen M. Cameron list_for_each_entry_safe(test_h, tmp_h, &hpsa_scan_q, scan_list) { 266*edd16368SStephen M. Cameron if (test_h == h) { /* state 2. */ 267*edd16368SStephen M. Cameron list_del(&h->scan_list); 268*edd16368SStephen M. Cameron complete_all(&h->scan_wait); 269*edd16368SStephen M. Cameron mutex_unlock(&hpsa_scan_mutex); 270*edd16368SStephen M. Cameron return; 271*edd16368SStephen M. Cameron } 272*edd16368SStephen M. Cameron } 273*edd16368SStephen M. Cameron if (h->busy_scanning) { /* state 3. */ 274*edd16368SStephen M. Cameron mutex_unlock(&hpsa_scan_mutex); 275*edd16368SStephen M. Cameron wait_for_completion(&h->scan_wait); 276*edd16368SStephen M. Cameron } else { /* state 1, nothing to do. */ 277*edd16368SStephen M. Cameron mutex_unlock(&hpsa_scan_mutex); 278*edd16368SStephen M. Cameron } 279*edd16368SStephen M. Cameron } 280*edd16368SStephen M. Cameron 281*edd16368SStephen M. Cameron /* hpsa_scan_func() - kernel thread used to rescan controllers 282*edd16368SStephen M. Cameron * @data: Ignored. 283*edd16368SStephen M. Cameron * 284*edd16368SStephen M. Cameron * A kernel thread used scan for drive topology changes on 285*edd16368SStephen M. Cameron * controllers. The thread processes only one controller at a time 286*edd16368SStephen M. Cameron * using a queue. Controllers are added to the queue using 287*edd16368SStephen M. Cameron * add_to_scan_list() and removed from the queue either after done 288*edd16368SStephen M. Cameron * processing or using remove_from_scan_list(). 289*edd16368SStephen M. Cameron * 290*edd16368SStephen M. Cameron * returns 0. 291*edd16368SStephen M. Cameron **/ 292*edd16368SStephen M. Cameron static int hpsa_scan_func(__attribute__((unused)) void *data) 293*edd16368SStephen M. Cameron { 294*edd16368SStephen M. Cameron struct ctlr_info *h; 295*edd16368SStephen M. Cameron int host_no; 296*edd16368SStephen M. Cameron 297*edd16368SStephen M. Cameron while (1) { 298*edd16368SStephen M. Cameron set_current_state(TASK_INTERRUPTIBLE); 299*edd16368SStephen M. Cameron schedule(); 300*edd16368SStephen M. Cameron if (kthread_should_stop()) 301*edd16368SStephen M. Cameron break; 302*edd16368SStephen M. Cameron 303*edd16368SStephen M. Cameron while (1) { 304*edd16368SStephen M. Cameron mutex_lock(&hpsa_scan_mutex); 305*edd16368SStephen M. Cameron if (list_empty(&hpsa_scan_q)) { 306*edd16368SStephen M. Cameron mutex_unlock(&hpsa_scan_mutex); 307*edd16368SStephen M. Cameron break; 308*edd16368SStephen M. Cameron } 309*edd16368SStephen M. Cameron h = list_entry(hpsa_scan_q.next, struct ctlr_info, 310*edd16368SStephen M. Cameron scan_list); 311*edd16368SStephen M. Cameron list_del(&h->scan_list); 312*edd16368SStephen M. Cameron h->busy_scanning = 1; 313*edd16368SStephen M. Cameron mutex_unlock(&hpsa_scan_mutex); 314*edd16368SStephen M. Cameron host_no = h->scsi_host ? h->scsi_host->host_no : -1; 315*edd16368SStephen M. Cameron hpsa_update_scsi_devices(h, host_no); 316*edd16368SStephen M. Cameron complete_all(&h->scan_wait); 317*edd16368SStephen M. Cameron mutex_lock(&hpsa_scan_mutex); 318*edd16368SStephen M. Cameron h->busy_scanning = 0; 319*edd16368SStephen M. Cameron mutex_unlock(&hpsa_scan_mutex); 320*edd16368SStephen M. Cameron } 321*edd16368SStephen M. Cameron } 322*edd16368SStephen M. Cameron return 0; 323*edd16368SStephen M. Cameron } 324*edd16368SStephen M. Cameron 325*edd16368SStephen M. Cameron static int check_for_unit_attention(struct ctlr_info *h, 326*edd16368SStephen M. Cameron struct CommandList *c) 327*edd16368SStephen M. Cameron { 328*edd16368SStephen M. Cameron if (c->err_info->SenseInfo[2] != UNIT_ATTENTION) 329*edd16368SStephen M. Cameron return 0; 330*edd16368SStephen M. Cameron 331*edd16368SStephen M. Cameron switch (c->err_info->SenseInfo[12]) { 332*edd16368SStephen M. Cameron case STATE_CHANGED: 333*edd16368SStephen M. Cameron dev_warn(&h->pdev->dev, "hpsa%d: a state change " 334*edd16368SStephen M. Cameron "detected, command retried\n", h->ctlr); 335*edd16368SStephen M. Cameron break; 336*edd16368SStephen M. Cameron case LUN_FAILED: 337*edd16368SStephen M. Cameron dev_warn(&h->pdev->dev, "hpsa%d: LUN failure " 338*edd16368SStephen M. Cameron "detected, action required\n", h->ctlr); 339*edd16368SStephen M. Cameron break; 340*edd16368SStephen M. Cameron case REPORT_LUNS_CHANGED: 341*edd16368SStephen M. Cameron dev_warn(&h->pdev->dev, "hpsa%d: report LUN data " 342*edd16368SStephen M. Cameron "changed\n", h->ctlr); 343*edd16368SStephen M. Cameron /* 344*edd16368SStephen M. Cameron * Here, we could call add_to_scan_list and wake up the scan thread, 345*edd16368SStephen M. Cameron * except that it's quite likely that we will get more than one 346*edd16368SStephen M. Cameron * REPORT_LUNS_CHANGED condition in quick succession, which means 347*edd16368SStephen M. Cameron * that those which occur after the first one will likely happen 348*edd16368SStephen M. Cameron * *during* the hpsa_scan_thread's rescan. And the rescan code is not 349*edd16368SStephen M. Cameron * robust enough to restart in the middle, undoing what it has already 350*edd16368SStephen M. Cameron * done, and it's not clear that it's even possible to do this, since 351*edd16368SStephen M. Cameron * part of what it does is notify the SCSI mid layer, which starts 352*edd16368SStephen M. Cameron * doing it's own i/o to read partition tables and so on, and the 353*edd16368SStephen M. Cameron * driver doesn't have visibility to know what might need undoing. 354*edd16368SStephen M. Cameron * In any event, if possible, it is horribly complicated to get right 355*edd16368SStephen M. Cameron * so we just don't do it for now. 356*edd16368SStephen M. Cameron * 357*edd16368SStephen M. Cameron * Note: this REPORT_LUNS_CHANGED condition only occurs on the MSA2012. 358*edd16368SStephen M. Cameron */ 359*edd16368SStephen M. Cameron break; 360*edd16368SStephen M. Cameron case POWER_OR_RESET: 361*edd16368SStephen M. Cameron dev_warn(&h->pdev->dev, "hpsa%d: a power on " 362*edd16368SStephen M. Cameron "or device reset detected\n", h->ctlr); 363*edd16368SStephen M. Cameron break; 364*edd16368SStephen M. Cameron case UNIT_ATTENTION_CLEARED: 365*edd16368SStephen M. Cameron dev_warn(&h->pdev->dev, "hpsa%d: unit attention " 366*edd16368SStephen M. Cameron "cleared by another initiator\n", h->ctlr); 367*edd16368SStephen M. Cameron break; 368*edd16368SStephen M. Cameron default: 369*edd16368SStephen M. Cameron dev_warn(&h->pdev->dev, "hpsa%d: unknown " 370*edd16368SStephen M. Cameron "unit attention detected\n", h->ctlr); 371*edd16368SStephen M. Cameron break; 372*edd16368SStephen M. Cameron } 373*edd16368SStephen M. Cameron return 1; 374*edd16368SStephen M. Cameron } 375*edd16368SStephen M. Cameron 376*edd16368SStephen M. Cameron static ssize_t host_store_rescan(struct device *dev, 377*edd16368SStephen M. Cameron struct device_attribute *attr, 378*edd16368SStephen M. Cameron const char *buf, size_t count) 379*edd16368SStephen M. Cameron { 380*edd16368SStephen M. Cameron struct ctlr_info *h; 381*edd16368SStephen M. Cameron struct Scsi_Host *shost = class_to_shost(dev); 382*edd16368SStephen M. Cameron unsigned long *priv = shost_priv(shost); 383*edd16368SStephen M. Cameron h = (struct ctlr_info *) *priv; 384*edd16368SStephen M. Cameron if (add_to_scan_list(h)) { 385*edd16368SStephen M. Cameron wake_up_process(hpsa_scan_thread); 386*edd16368SStephen M. Cameron wait_for_completion_interruptible(&h->scan_wait); 387*edd16368SStephen M. Cameron } 388*edd16368SStephen M. Cameron return count; 389*edd16368SStephen M. Cameron } 390*edd16368SStephen M. Cameron 391*edd16368SStephen M. Cameron /* Enqueuing and dequeuing functions for cmdlists. */ 392*edd16368SStephen M. Cameron static inline void addQ(struct hlist_head *list, struct CommandList *c) 393*edd16368SStephen M. Cameron { 394*edd16368SStephen M. Cameron hlist_add_head(&c->list, list); 395*edd16368SStephen M. Cameron } 396*edd16368SStephen M. Cameron 397*edd16368SStephen M. Cameron static void enqueue_cmd_and_start_io(struct ctlr_info *h, 398*edd16368SStephen M. Cameron struct CommandList *c) 399*edd16368SStephen M. Cameron { 400*edd16368SStephen M. Cameron unsigned long flags; 401*edd16368SStephen M. Cameron spin_lock_irqsave(&h->lock, flags); 402*edd16368SStephen M. Cameron addQ(&h->reqQ, c); 403*edd16368SStephen M. Cameron h->Qdepth++; 404*edd16368SStephen M. Cameron start_io(h); 405*edd16368SStephen M. Cameron spin_unlock_irqrestore(&h->lock, flags); 406*edd16368SStephen M. Cameron } 407*edd16368SStephen M. Cameron 408*edd16368SStephen M. Cameron static inline void removeQ(struct CommandList *c) 409*edd16368SStephen M. Cameron { 410*edd16368SStephen M. Cameron if (WARN_ON(hlist_unhashed(&c->list))) 411*edd16368SStephen M. Cameron return; 412*edd16368SStephen M. Cameron hlist_del_init(&c->list); 413*edd16368SStephen M. Cameron } 414*edd16368SStephen M. Cameron 415*edd16368SStephen M. Cameron static inline int is_hba_lunid(unsigned char scsi3addr[]) 416*edd16368SStephen M. Cameron { 417*edd16368SStephen M. Cameron return memcmp(scsi3addr, RAID_CTLR_LUNID, 8) == 0; 418*edd16368SStephen M. Cameron } 419*edd16368SStephen M. Cameron 420*edd16368SStephen M. Cameron static inline int is_logical_dev_addr_mode(unsigned char scsi3addr[]) 421*edd16368SStephen M. Cameron { 422*edd16368SStephen M. Cameron return (scsi3addr[3] & 0xC0) == 0x40; 423*edd16368SStephen M. Cameron } 424*edd16368SStephen M. Cameron 425*edd16368SStephen M. Cameron static const char *raid_label[] = { "0", "4", "1(1+0)", "5", "5+1", "ADG", 426*edd16368SStephen M. Cameron "UNKNOWN" 427*edd16368SStephen M. Cameron }; 428*edd16368SStephen M. Cameron #define RAID_UNKNOWN (ARRAY_SIZE(raid_label) - 1) 429*edd16368SStephen M. Cameron 430*edd16368SStephen M. Cameron static ssize_t raid_level_show(struct device *dev, 431*edd16368SStephen M. Cameron struct device_attribute *attr, char *buf) 432*edd16368SStephen M. Cameron { 433*edd16368SStephen M. Cameron ssize_t l = 0; 434*edd16368SStephen M. Cameron int rlevel; 435*edd16368SStephen M. Cameron struct ctlr_info *h; 436*edd16368SStephen M. Cameron struct scsi_device *sdev; 437*edd16368SStephen M. Cameron struct hpsa_scsi_dev_t *hdev; 438*edd16368SStephen M. Cameron unsigned long flags; 439*edd16368SStephen M. Cameron 440*edd16368SStephen M. Cameron sdev = to_scsi_device(dev); 441*edd16368SStephen M. Cameron h = sdev_to_hba(sdev); 442*edd16368SStephen M. Cameron spin_lock_irqsave(&h->lock, flags); 443*edd16368SStephen M. Cameron hdev = sdev->hostdata; 444*edd16368SStephen M. Cameron if (!hdev) { 445*edd16368SStephen M. Cameron spin_unlock_irqrestore(&h->lock, flags); 446*edd16368SStephen M. Cameron return -ENODEV; 447*edd16368SStephen M. Cameron } 448*edd16368SStephen M. Cameron 449*edd16368SStephen M. Cameron /* Is this even a logical drive? */ 450*edd16368SStephen M. Cameron if (!is_logical_dev_addr_mode(hdev->scsi3addr)) { 451*edd16368SStephen M. Cameron spin_unlock_irqrestore(&h->lock, flags); 452*edd16368SStephen M. Cameron l = snprintf(buf, PAGE_SIZE, "N/A\n"); 453*edd16368SStephen M. Cameron return l; 454*edd16368SStephen M. Cameron } 455*edd16368SStephen M. Cameron 456*edd16368SStephen M. Cameron rlevel = hdev->raid_level; 457*edd16368SStephen M. Cameron spin_unlock_irqrestore(&h->lock, flags); 458*edd16368SStephen M. Cameron if (rlevel < 0 || rlevel > RAID_UNKNOWN) 459*edd16368SStephen M. Cameron rlevel = RAID_UNKNOWN; 460*edd16368SStephen M. Cameron l = snprintf(buf, PAGE_SIZE, "RAID %s\n", raid_label[rlevel]); 461*edd16368SStephen M. Cameron return l; 462*edd16368SStephen M. Cameron } 463*edd16368SStephen M. Cameron 464*edd16368SStephen M. Cameron static ssize_t lunid_show(struct device *dev, 465*edd16368SStephen M. Cameron struct device_attribute *attr, char *buf) 466*edd16368SStephen M. Cameron { 467*edd16368SStephen M. Cameron struct ctlr_info *h; 468*edd16368SStephen M. Cameron struct scsi_device *sdev; 469*edd16368SStephen M. Cameron struct hpsa_scsi_dev_t *hdev; 470*edd16368SStephen M. Cameron unsigned long flags; 471*edd16368SStephen M. Cameron unsigned char lunid[8]; 472*edd16368SStephen M. Cameron 473*edd16368SStephen M. Cameron sdev = to_scsi_device(dev); 474*edd16368SStephen M. Cameron h = sdev_to_hba(sdev); 475*edd16368SStephen M. Cameron spin_lock_irqsave(&h->lock, flags); 476*edd16368SStephen M. Cameron hdev = sdev->hostdata; 477*edd16368SStephen M. Cameron if (!hdev) { 478*edd16368SStephen M. Cameron spin_unlock_irqrestore(&h->lock, flags); 479*edd16368SStephen M. Cameron return -ENODEV; 480*edd16368SStephen M. Cameron } 481*edd16368SStephen M. Cameron memcpy(lunid, hdev->scsi3addr, sizeof(lunid)); 482*edd16368SStephen M. Cameron spin_unlock_irqrestore(&h->lock, flags); 483*edd16368SStephen M. Cameron return snprintf(buf, 20, "0x%02x%02x%02x%02x%02x%02x%02x%02x\n", 484*edd16368SStephen M. Cameron lunid[0], lunid[1], lunid[2], lunid[3], 485*edd16368SStephen M. Cameron lunid[4], lunid[5], lunid[6], lunid[7]); 486*edd16368SStephen M. Cameron } 487*edd16368SStephen M. Cameron 488*edd16368SStephen M. Cameron static ssize_t unique_id_show(struct device *dev, 489*edd16368SStephen M. Cameron struct device_attribute *attr, char *buf) 490*edd16368SStephen M. Cameron { 491*edd16368SStephen M. Cameron struct ctlr_info *h; 492*edd16368SStephen M. Cameron struct scsi_device *sdev; 493*edd16368SStephen M. Cameron struct hpsa_scsi_dev_t *hdev; 494*edd16368SStephen M. Cameron unsigned long flags; 495*edd16368SStephen M. Cameron unsigned char sn[16]; 496*edd16368SStephen M. Cameron 497*edd16368SStephen M. Cameron sdev = to_scsi_device(dev); 498*edd16368SStephen M. Cameron h = sdev_to_hba(sdev); 499*edd16368SStephen M. Cameron spin_lock_irqsave(&h->lock, flags); 500*edd16368SStephen M. Cameron hdev = sdev->hostdata; 501*edd16368SStephen M. Cameron if (!hdev) { 502*edd16368SStephen M. Cameron spin_unlock_irqrestore(&h->lock, flags); 503*edd16368SStephen M. Cameron return -ENODEV; 504*edd16368SStephen M. Cameron } 505*edd16368SStephen M. Cameron memcpy(sn, hdev->device_id, sizeof(sn)); 506*edd16368SStephen M. Cameron spin_unlock_irqrestore(&h->lock, flags); 507*edd16368SStephen M. Cameron return snprintf(buf, 16 * 2 + 2, 508*edd16368SStephen M. Cameron "%02X%02X%02X%02X%02X%02X%02X%02X" 509*edd16368SStephen M. Cameron "%02X%02X%02X%02X%02X%02X%02X%02X\n", 510*edd16368SStephen M. Cameron sn[0], sn[1], sn[2], sn[3], 511*edd16368SStephen M. Cameron sn[4], sn[5], sn[6], sn[7], 512*edd16368SStephen M. Cameron sn[8], sn[9], sn[10], sn[11], 513*edd16368SStephen M. Cameron sn[12], sn[13], sn[14], sn[15]); 514*edd16368SStephen M. Cameron } 515*edd16368SStephen M. Cameron 516*edd16368SStephen M. Cameron static int hpsa_find_target_lun(struct ctlr_info *h, 517*edd16368SStephen M. Cameron unsigned char scsi3addr[], int bus, int *target, int *lun) 518*edd16368SStephen M. Cameron { 519*edd16368SStephen M. Cameron /* finds an unused bus, target, lun for a new physical device 520*edd16368SStephen M. Cameron * assumes h->devlock is held 521*edd16368SStephen M. Cameron */ 522*edd16368SStephen M. Cameron int i, found = 0; 523*edd16368SStephen M. Cameron DECLARE_BITMAP(lun_taken, HPSA_MAX_SCSI_DEVS_PER_HBA); 524*edd16368SStephen M. Cameron 525*edd16368SStephen M. Cameron memset(&lun_taken[0], 0, HPSA_MAX_SCSI_DEVS_PER_HBA >> 3); 526*edd16368SStephen M. Cameron 527*edd16368SStephen M. Cameron for (i = 0; i < h->ndevices; i++) { 528*edd16368SStephen M. Cameron if (h->dev[i]->bus == bus && h->dev[i]->target != -1) 529*edd16368SStephen M. Cameron set_bit(h->dev[i]->target, lun_taken); 530*edd16368SStephen M. Cameron } 531*edd16368SStephen M. Cameron 532*edd16368SStephen M. Cameron for (i = 0; i < HPSA_MAX_SCSI_DEVS_PER_HBA; i++) { 533*edd16368SStephen M. Cameron if (!test_bit(i, lun_taken)) { 534*edd16368SStephen M. Cameron /* *bus = 1; */ 535*edd16368SStephen M. Cameron *target = i; 536*edd16368SStephen M. Cameron *lun = 0; 537*edd16368SStephen M. Cameron found = 1; 538*edd16368SStephen M. Cameron break; 539*edd16368SStephen M. Cameron } 540*edd16368SStephen M. Cameron } 541*edd16368SStephen M. Cameron return !found; 542*edd16368SStephen M. Cameron } 543*edd16368SStephen M. Cameron 544*edd16368SStephen M. Cameron /* Add an entry into h->dev[] array. */ 545*edd16368SStephen M. Cameron static int hpsa_scsi_add_entry(struct ctlr_info *h, int hostno, 546*edd16368SStephen M. Cameron struct hpsa_scsi_dev_t *device, 547*edd16368SStephen M. Cameron struct hpsa_scsi_dev_t *added[], int *nadded) 548*edd16368SStephen M. Cameron { 549*edd16368SStephen M. Cameron /* assumes h->devlock is held */ 550*edd16368SStephen M. Cameron int n = h->ndevices; 551*edd16368SStephen M. Cameron int i; 552*edd16368SStephen M. Cameron unsigned char addr1[8], addr2[8]; 553*edd16368SStephen M. Cameron struct hpsa_scsi_dev_t *sd; 554*edd16368SStephen M. Cameron 555*edd16368SStephen M. Cameron if (n >= HPSA_MAX_SCSI_DEVS_PER_HBA) { 556*edd16368SStephen M. Cameron dev_err(&h->pdev->dev, "too many devices, some will be " 557*edd16368SStephen M. Cameron "inaccessible.\n"); 558*edd16368SStephen M. Cameron return -1; 559*edd16368SStephen M. Cameron } 560*edd16368SStephen M. Cameron 561*edd16368SStephen M. Cameron /* physical devices do not have lun or target assigned until now. */ 562*edd16368SStephen M. Cameron if (device->lun != -1) 563*edd16368SStephen M. Cameron /* Logical device, lun is already assigned. */ 564*edd16368SStephen M. Cameron goto lun_assigned; 565*edd16368SStephen M. Cameron 566*edd16368SStephen M. Cameron /* If this device a non-zero lun of a multi-lun device 567*edd16368SStephen M. Cameron * byte 4 of the 8-byte LUN addr will contain the logical 568*edd16368SStephen M. Cameron * unit no, zero otherise. 569*edd16368SStephen M. Cameron */ 570*edd16368SStephen M. Cameron if (device->scsi3addr[4] == 0) { 571*edd16368SStephen M. Cameron /* This is not a non-zero lun of a multi-lun device */ 572*edd16368SStephen M. Cameron if (hpsa_find_target_lun(h, device->scsi3addr, 573*edd16368SStephen M. Cameron device->bus, &device->target, &device->lun) != 0) 574*edd16368SStephen M. Cameron return -1; 575*edd16368SStephen M. Cameron goto lun_assigned; 576*edd16368SStephen M. Cameron } 577*edd16368SStephen M. Cameron 578*edd16368SStephen M. Cameron /* This is a non-zero lun of a multi-lun device. 579*edd16368SStephen M. Cameron * Search through our list and find the device which 580*edd16368SStephen M. Cameron * has the same 8 byte LUN address, excepting byte 4. 581*edd16368SStephen M. Cameron * Assign the same bus and target for this new LUN. 582*edd16368SStephen M. Cameron * Use the logical unit number from the firmware. 583*edd16368SStephen M. Cameron */ 584*edd16368SStephen M. Cameron memcpy(addr1, device->scsi3addr, 8); 585*edd16368SStephen M. Cameron addr1[4] = 0; 586*edd16368SStephen M. Cameron for (i = 0; i < n; i++) { 587*edd16368SStephen M. Cameron sd = h->dev[i]; 588*edd16368SStephen M. Cameron memcpy(addr2, sd->scsi3addr, 8); 589*edd16368SStephen M. Cameron addr2[4] = 0; 590*edd16368SStephen M. Cameron /* differ only in byte 4? */ 591*edd16368SStephen M. Cameron if (memcmp(addr1, addr2, 8) == 0) { 592*edd16368SStephen M. Cameron device->bus = sd->bus; 593*edd16368SStephen M. Cameron device->target = sd->target; 594*edd16368SStephen M. Cameron device->lun = device->scsi3addr[4]; 595*edd16368SStephen M. Cameron break; 596*edd16368SStephen M. Cameron } 597*edd16368SStephen M. Cameron } 598*edd16368SStephen M. Cameron if (device->lun == -1) { 599*edd16368SStephen M. Cameron dev_warn(&h->pdev->dev, "physical device with no LUN=0," 600*edd16368SStephen M. Cameron " suspect firmware bug or unsupported hardware " 601*edd16368SStephen M. Cameron "configuration.\n"); 602*edd16368SStephen M. Cameron return -1; 603*edd16368SStephen M. Cameron } 604*edd16368SStephen M. Cameron 605*edd16368SStephen M. Cameron lun_assigned: 606*edd16368SStephen M. Cameron 607*edd16368SStephen M. Cameron h->dev[n] = device; 608*edd16368SStephen M. Cameron h->ndevices++; 609*edd16368SStephen M. Cameron added[*nadded] = device; 610*edd16368SStephen M. Cameron (*nadded)++; 611*edd16368SStephen M. Cameron 612*edd16368SStephen M. Cameron /* initially, (before registering with scsi layer) we don't 613*edd16368SStephen M. Cameron * know our hostno and we don't want to print anything first 614*edd16368SStephen M. Cameron * time anyway (the scsi layer's inquiries will show that info) 615*edd16368SStephen M. Cameron */ 616*edd16368SStephen M. Cameron /* if (hostno != -1) */ 617*edd16368SStephen M. Cameron dev_info(&h->pdev->dev, "%s device c%db%dt%dl%d added.\n", 618*edd16368SStephen M. Cameron scsi_device_type(device->devtype), hostno, 619*edd16368SStephen M. Cameron device->bus, device->target, device->lun); 620*edd16368SStephen M. Cameron return 0; 621*edd16368SStephen M. Cameron } 622*edd16368SStephen M. Cameron 623*edd16368SStephen M. Cameron /* Remove an entry from h->dev[] array. */ 624*edd16368SStephen M. Cameron static void hpsa_scsi_remove_entry(struct ctlr_info *h, int hostno, int entry, 625*edd16368SStephen M. Cameron struct hpsa_scsi_dev_t *removed[], int *nremoved) 626*edd16368SStephen M. Cameron { 627*edd16368SStephen M. Cameron /* assumes h->devlock is held */ 628*edd16368SStephen M. Cameron int i; 629*edd16368SStephen M. Cameron struct hpsa_scsi_dev_t *sd; 630*edd16368SStephen M. Cameron 631*edd16368SStephen M. Cameron if (entry < 0 || entry >= HPSA_MAX_SCSI_DEVS_PER_HBA) 632*edd16368SStephen M. Cameron BUG(); 633*edd16368SStephen M. Cameron 634*edd16368SStephen M. Cameron sd = h->dev[entry]; 635*edd16368SStephen M. Cameron removed[*nremoved] = h->dev[entry]; 636*edd16368SStephen M. Cameron (*nremoved)++; 637*edd16368SStephen M. Cameron 638*edd16368SStephen M. Cameron for (i = entry; i < h->ndevices-1; i++) 639*edd16368SStephen M. Cameron h->dev[i] = h->dev[i+1]; 640*edd16368SStephen M. Cameron h->ndevices--; 641*edd16368SStephen M. Cameron dev_info(&h->pdev->dev, "%s device c%db%dt%dl%d removed.\n", 642*edd16368SStephen M. Cameron scsi_device_type(sd->devtype), hostno, sd->bus, sd->target, 643*edd16368SStephen M. Cameron sd->lun); 644*edd16368SStephen M. Cameron } 645*edd16368SStephen M. Cameron 646*edd16368SStephen M. Cameron #define SCSI3ADDR_EQ(a, b) ( \ 647*edd16368SStephen M. Cameron (a)[7] == (b)[7] && \ 648*edd16368SStephen M. Cameron (a)[6] == (b)[6] && \ 649*edd16368SStephen M. Cameron (a)[5] == (b)[5] && \ 650*edd16368SStephen M. Cameron (a)[4] == (b)[4] && \ 651*edd16368SStephen M. Cameron (a)[3] == (b)[3] && \ 652*edd16368SStephen M. Cameron (a)[2] == (b)[2] && \ 653*edd16368SStephen M. Cameron (a)[1] == (b)[1] && \ 654*edd16368SStephen M. Cameron (a)[0] == (b)[0]) 655*edd16368SStephen M. Cameron 656*edd16368SStephen M. Cameron static void fixup_botched_add(struct ctlr_info *h, 657*edd16368SStephen M. Cameron struct hpsa_scsi_dev_t *added) 658*edd16368SStephen M. Cameron { 659*edd16368SStephen M. Cameron /* called when scsi_add_device fails in order to re-adjust 660*edd16368SStephen M. Cameron * h->dev[] to match the mid layer's view. 661*edd16368SStephen M. Cameron */ 662*edd16368SStephen M. Cameron unsigned long flags; 663*edd16368SStephen M. Cameron int i, j; 664*edd16368SStephen M. Cameron 665*edd16368SStephen M. Cameron spin_lock_irqsave(&h->lock, flags); 666*edd16368SStephen M. Cameron for (i = 0; i < h->ndevices; i++) { 667*edd16368SStephen M. Cameron if (h->dev[i] == added) { 668*edd16368SStephen M. Cameron for (j = i; j < h->ndevices-1; j++) 669*edd16368SStephen M. Cameron h->dev[j] = h->dev[j+1]; 670*edd16368SStephen M. Cameron h->ndevices--; 671*edd16368SStephen M. Cameron break; 672*edd16368SStephen M. Cameron } 673*edd16368SStephen M. Cameron } 674*edd16368SStephen M. Cameron spin_unlock_irqrestore(&h->lock, flags); 675*edd16368SStephen M. Cameron kfree(added); 676*edd16368SStephen M. Cameron } 677*edd16368SStephen M. Cameron 678*edd16368SStephen M. Cameron static inline int device_is_the_same(struct hpsa_scsi_dev_t *dev1, 679*edd16368SStephen M. Cameron struct hpsa_scsi_dev_t *dev2) 680*edd16368SStephen M. Cameron { 681*edd16368SStephen M. Cameron if ((is_logical_dev_addr_mode(dev1->scsi3addr) || 682*edd16368SStephen M. Cameron (dev1->lun != -1 && dev2->lun != -1)) && 683*edd16368SStephen M. Cameron dev1->devtype != 0x0C) 684*edd16368SStephen M. Cameron return (memcmp(dev1, dev2, sizeof(*dev1)) == 0); 685*edd16368SStephen M. Cameron 686*edd16368SStephen M. Cameron /* we compare everything except lun and target as these 687*edd16368SStephen M. Cameron * are not yet assigned. Compare parts likely 688*edd16368SStephen M. Cameron * to differ first 689*edd16368SStephen M. Cameron */ 690*edd16368SStephen M. Cameron if (memcmp(dev1->scsi3addr, dev2->scsi3addr, 691*edd16368SStephen M. Cameron sizeof(dev1->scsi3addr)) != 0) 692*edd16368SStephen M. Cameron return 0; 693*edd16368SStephen M. Cameron if (memcmp(dev1->device_id, dev2->device_id, 694*edd16368SStephen M. Cameron sizeof(dev1->device_id)) != 0) 695*edd16368SStephen M. Cameron return 0; 696*edd16368SStephen M. Cameron if (memcmp(dev1->model, dev2->model, sizeof(dev1->model)) != 0) 697*edd16368SStephen M. Cameron return 0; 698*edd16368SStephen M. Cameron if (memcmp(dev1->vendor, dev2->vendor, sizeof(dev1->vendor)) != 0) 699*edd16368SStephen M. Cameron return 0; 700*edd16368SStephen M. Cameron if (memcmp(dev1->revision, dev2->revision, sizeof(dev1->revision)) != 0) 701*edd16368SStephen M. Cameron return 0; 702*edd16368SStephen M. Cameron if (dev1->devtype != dev2->devtype) 703*edd16368SStephen M. Cameron return 0; 704*edd16368SStephen M. Cameron if (dev1->raid_level != dev2->raid_level) 705*edd16368SStephen M. Cameron return 0; 706*edd16368SStephen M. Cameron if (dev1->bus != dev2->bus) 707*edd16368SStephen M. Cameron return 0; 708*edd16368SStephen M. Cameron return 1; 709*edd16368SStephen M. Cameron } 710*edd16368SStephen M. Cameron 711*edd16368SStephen M. Cameron /* Find needle in haystack. If exact match found, return DEVICE_SAME, 712*edd16368SStephen M. Cameron * and return needle location in *index. If scsi3addr matches, but not 713*edd16368SStephen M. Cameron * vendor, model, serial num, etc. return DEVICE_CHANGED, and return needle 714*edd16368SStephen M. Cameron * location in *index. If needle not found, return DEVICE_NOT_FOUND. 715*edd16368SStephen M. Cameron */ 716*edd16368SStephen M. Cameron static int hpsa_scsi_find_entry(struct hpsa_scsi_dev_t *needle, 717*edd16368SStephen M. Cameron struct hpsa_scsi_dev_t *haystack[], int haystack_size, 718*edd16368SStephen M. Cameron int *index) 719*edd16368SStephen M. Cameron { 720*edd16368SStephen M. Cameron int i; 721*edd16368SStephen M. Cameron #define DEVICE_NOT_FOUND 0 722*edd16368SStephen M. Cameron #define DEVICE_CHANGED 1 723*edd16368SStephen M. Cameron #define DEVICE_SAME 2 724*edd16368SStephen M. Cameron for (i = 0; i < haystack_size; i++) { 725*edd16368SStephen M. Cameron if (SCSI3ADDR_EQ(needle->scsi3addr, haystack[i]->scsi3addr)) { 726*edd16368SStephen M. Cameron *index = i; 727*edd16368SStephen M. Cameron if (device_is_the_same(needle, haystack[i])) 728*edd16368SStephen M. Cameron return DEVICE_SAME; 729*edd16368SStephen M. Cameron else 730*edd16368SStephen M. Cameron return DEVICE_CHANGED; 731*edd16368SStephen M. Cameron } 732*edd16368SStephen M. Cameron } 733*edd16368SStephen M. Cameron *index = -1; 734*edd16368SStephen M. Cameron return DEVICE_NOT_FOUND; 735*edd16368SStephen M. Cameron } 736*edd16368SStephen M. Cameron 737*edd16368SStephen M. Cameron static int adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno, 738*edd16368SStephen M. Cameron struct hpsa_scsi_dev_t *sd[], int nsds) 739*edd16368SStephen M. Cameron { 740*edd16368SStephen M. Cameron /* sd contains scsi3 addresses and devtypes, and inquiry 741*edd16368SStephen M. Cameron * data. This function takes what's in sd to be the current 742*edd16368SStephen M. Cameron * reality and updates h->dev[] to reflect that reality. 743*edd16368SStephen M. Cameron */ 744*edd16368SStephen M. Cameron int i, entry, device_change, changes = 0; 745*edd16368SStephen M. Cameron struct hpsa_scsi_dev_t *csd; 746*edd16368SStephen M. Cameron unsigned long flags; 747*edd16368SStephen M. Cameron struct hpsa_scsi_dev_t **added, **removed; 748*edd16368SStephen M. Cameron int nadded, nremoved; 749*edd16368SStephen M. Cameron struct Scsi_Host *sh = NULL; 750*edd16368SStephen M. Cameron 751*edd16368SStephen M. Cameron added = kzalloc(sizeof(*added) * HPSA_MAX_SCSI_DEVS_PER_HBA, 752*edd16368SStephen M. Cameron GFP_KERNEL); 753*edd16368SStephen M. Cameron removed = kzalloc(sizeof(*removed) * HPSA_MAX_SCSI_DEVS_PER_HBA, 754*edd16368SStephen M. Cameron GFP_KERNEL); 755*edd16368SStephen M. Cameron 756*edd16368SStephen M. Cameron if (!added || !removed) { 757*edd16368SStephen M. Cameron dev_warn(&h->pdev->dev, "out of memory in " 758*edd16368SStephen M. Cameron "adjust_hpsa_scsi_table\n"); 759*edd16368SStephen M. Cameron goto free_and_out; 760*edd16368SStephen M. Cameron } 761*edd16368SStephen M. Cameron 762*edd16368SStephen M. Cameron spin_lock_irqsave(&h->devlock, flags); 763*edd16368SStephen M. Cameron 764*edd16368SStephen M. Cameron /* find any devices in h->dev[] that are not in 765*edd16368SStephen M. Cameron * sd[] and remove them from h->dev[], and for any 766*edd16368SStephen M. Cameron * devices which have changed, remove the old device 767*edd16368SStephen M. Cameron * info and add the new device info. 768*edd16368SStephen M. Cameron */ 769*edd16368SStephen M. Cameron i = 0; 770*edd16368SStephen M. Cameron nremoved = 0; 771*edd16368SStephen M. Cameron nadded = 0; 772*edd16368SStephen M. Cameron while (i < h->ndevices) { 773*edd16368SStephen M. Cameron csd = h->dev[i]; 774*edd16368SStephen M. Cameron device_change = hpsa_scsi_find_entry(csd, sd, nsds, &entry); 775*edd16368SStephen M. Cameron if (device_change == DEVICE_NOT_FOUND) { 776*edd16368SStephen M. Cameron changes++; 777*edd16368SStephen M. Cameron hpsa_scsi_remove_entry(h, hostno, i, 778*edd16368SStephen M. Cameron removed, &nremoved); 779*edd16368SStephen M. Cameron continue; /* remove ^^^, hence i not incremented */ 780*edd16368SStephen M. Cameron } else if (device_change == DEVICE_CHANGED) { 781*edd16368SStephen M. Cameron changes++; 782*edd16368SStephen M. Cameron hpsa_scsi_remove_entry(h, hostno, i, 783*edd16368SStephen M. Cameron removed, &nremoved); 784*edd16368SStephen M. Cameron (void) hpsa_scsi_add_entry(h, hostno, sd[entry], 785*edd16368SStephen M. Cameron added, &nadded); 786*edd16368SStephen M. Cameron /* add can't fail, we just removed one. */ 787*edd16368SStephen M. Cameron sd[entry] = NULL; /* prevent it from being freed */ 788*edd16368SStephen M. Cameron } 789*edd16368SStephen M. Cameron i++; 790*edd16368SStephen M. Cameron } 791*edd16368SStephen M. Cameron 792*edd16368SStephen M. Cameron /* Now, make sure every device listed in sd[] is also 793*edd16368SStephen M. Cameron * listed in h->dev[], adding them if they aren't found 794*edd16368SStephen M. Cameron */ 795*edd16368SStephen M. Cameron 796*edd16368SStephen M. Cameron for (i = 0; i < nsds; i++) { 797*edd16368SStephen M. Cameron if (!sd[i]) /* if already added above. */ 798*edd16368SStephen M. Cameron continue; 799*edd16368SStephen M. Cameron device_change = hpsa_scsi_find_entry(sd[i], h->dev, 800*edd16368SStephen M. Cameron h->ndevices, &entry); 801*edd16368SStephen M. Cameron if (device_change == DEVICE_NOT_FOUND) { 802*edd16368SStephen M. Cameron changes++; 803*edd16368SStephen M. Cameron if (hpsa_scsi_add_entry(h, hostno, sd[i], 804*edd16368SStephen M. Cameron added, &nadded) != 0) 805*edd16368SStephen M. Cameron break; 806*edd16368SStephen M. Cameron sd[i] = NULL; /* prevent from being freed later. */ 807*edd16368SStephen M. Cameron } else if (device_change == DEVICE_CHANGED) { 808*edd16368SStephen M. Cameron /* should never happen... */ 809*edd16368SStephen M. Cameron changes++; 810*edd16368SStephen M. Cameron dev_warn(&h->pdev->dev, 811*edd16368SStephen M. Cameron "device unexpectedly changed.\n"); 812*edd16368SStephen M. Cameron /* but if it does happen, we just ignore that device */ 813*edd16368SStephen M. Cameron } 814*edd16368SStephen M. Cameron } 815*edd16368SStephen M. Cameron spin_unlock_irqrestore(&h->devlock, flags); 816*edd16368SStephen M. Cameron 817*edd16368SStephen M. Cameron /* Don't notify scsi mid layer of any changes the first time through 818*edd16368SStephen M. Cameron * (or if there are no changes) scsi_scan_host will do it later the 819*edd16368SStephen M. Cameron * first time through. 820*edd16368SStephen M. Cameron */ 821*edd16368SStephen M. Cameron if (hostno == -1 || !changes) 822*edd16368SStephen M. Cameron goto free_and_out; 823*edd16368SStephen M. Cameron 824*edd16368SStephen M. Cameron sh = h->scsi_host; 825*edd16368SStephen M. Cameron /* Notify scsi mid layer of any removed devices */ 826*edd16368SStephen M. Cameron for (i = 0; i < nremoved; i++) { 827*edd16368SStephen M. Cameron struct scsi_device *sdev = 828*edd16368SStephen M. Cameron scsi_device_lookup(sh, removed[i]->bus, 829*edd16368SStephen M. Cameron removed[i]->target, removed[i]->lun); 830*edd16368SStephen M. Cameron if (sdev != NULL) { 831*edd16368SStephen M. Cameron scsi_remove_device(sdev); 832*edd16368SStephen M. Cameron scsi_device_put(sdev); 833*edd16368SStephen M. Cameron } else { 834*edd16368SStephen M. Cameron /* We don't expect to get here. 835*edd16368SStephen M. Cameron * future cmds to this device will get selection 836*edd16368SStephen M. Cameron * timeout as if the device was gone. 837*edd16368SStephen M. Cameron */ 838*edd16368SStephen M. Cameron dev_warn(&h->pdev->dev, "didn't find c%db%dt%dl%d " 839*edd16368SStephen M. Cameron " for removal.", hostno, removed[i]->bus, 840*edd16368SStephen M. Cameron removed[i]->target, removed[i]->lun); 841*edd16368SStephen M. Cameron } 842*edd16368SStephen M. Cameron kfree(removed[i]); 843*edd16368SStephen M. Cameron removed[i] = NULL; 844*edd16368SStephen M. Cameron } 845*edd16368SStephen M. Cameron 846*edd16368SStephen M. Cameron /* Notify scsi mid layer of any added devices */ 847*edd16368SStephen M. Cameron for (i = 0; i < nadded; i++) { 848*edd16368SStephen M. Cameron if (scsi_add_device(sh, added[i]->bus, 849*edd16368SStephen M. Cameron added[i]->target, added[i]->lun) == 0) 850*edd16368SStephen M. Cameron continue; 851*edd16368SStephen M. Cameron dev_warn(&h->pdev->dev, "scsi_add_device c%db%dt%dl%d failed, " 852*edd16368SStephen M. Cameron "device not added.\n", hostno, added[i]->bus, 853*edd16368SStephen M. Cameron added[i]->target, added[i]->lun); 854*edd16368SStephen M. Cameron /* now we have to remove it from h->dev, 855*edd16368SStephen M. Cameron * since it didn't get added to scsi mid layer 856*edd16368SStephen M. Cameron */ 857*edd16368SStephen M. Cameron fixup_botched_add(h, added[i]); 858*edd16368SStephen M. Cameron } 859*edd16368SStephen M. Cameron 860*edd16368SStephen M. Cameron free_and_out: 861*edd16368SStephen M. Cameron kfree(added); 862*edd16368SStephen M. Cameron kfree(removed); 863*edd16368SStephen M. Cameron return 0; 864*edd16368SStephen M. Cameron } 865*edd16368SStephen M. Cameron 866*edd16368SStephen M. Cameron /* 867*edd16368SStephen M. Cameron * Lookup bus/target/lun and retrun corresponding struct hpsa_scsi_dev_t * 868*edd16368SStephen M. Cameron * Assume's h->devlock is held. 869*edd16368SStephen M. Cameron */ 870*edd16368SStephen M. Cameron static struct hpsa_scsi_dev_t *lookup_hpsa_scsi_dev(struct ctlr_info *h, 871*edd16368SStephen M. Cameron int bus, int target, int lun) 872*edd16368SStephen M. Cameron { 873*edd16368SStephen M. Cameron int i; 874*edd16368SStephen M. Cameron struct hpsa_scsi_dev_t *sd; 875*edd16368SStephen M. Cameron 876*edd16368SStephen M. Cameron for (i = 0; i < h->ndevices; i++) { 877*edd16368SStephen M. Cameron sd = h->dev[i]; 878*edd16368SStephen M. Cameron if (sd->bus == bus && sd->target == target && sd->lun == lun) 879*edd16368SStephen M. Cameron return sd; 880*edd16368SStephen M. Cameron } 881*edd16368SStephen M. Cameron return NULL; 882*edd16368SStephen M. Cameron } 883*edd16368SStephen M. Cameron 884*edd16368SStephen M. Cameron /* link sdev->hostdata to our per-device structure. */ 885*edd16368SStephen M. Cameron static int hpsa_slave_alloc(struct scsi_device *sdev) 886*edd16368SStephen M. Cameron { 887*edd16368SStephen M. Cameron struct hpsa_scsi_dev_t *sd; 888*edd16368SStephen M. Cameron unsigned long flags; 889*edd16368SStephen M. Cameron struct ctlr_info *h; 890*edd16368SStephen M. Cameron 891*edd16368SStephen M. Cameron h = sdev_to_hba(sdev); 892*edd16368SStephen M. Cameron spin_lock_irqsave(&h->devlock, flags); 893*edd16368SStephen M. Cameron sd = lookup_hpsa_scsi_dev(h, sdev_channel(sdev), 894*edd16368SStephen M. Cameron sdev_id(sdev), sdev->lun); 895*edd16368SStephen M. Cameron if (sd != NULL) 896*edd16368SStephen M. Cameron sdev->hostdata = sd; 897*edd16368SStephen M. Cameron spin_unlock_irqrestore(&h->devlock, flags); 898*edd16368SStephen M. Cameron return 0; 899*edd16368SStephen M. Cameron } 900*edd16368SStephen M. Cameron 901*edd16368SStephen M. Cameron static void hpsa_slave_destroy(struct scsi_device *sdev) 902*edd16368SStephen M. Cameron { 903*edd16368SStephen M. Cameron return; /* nothing to do. */ 904*edd16368SStephen M. Cameron } 905*edd16368SStephen M. Cameron 906*edd16368SStephen M. Cameron static void hpsa_scsi_setup(struct ctlr_info *h) 907*edd16368SStephen M. Cameron { 908*edd16368SStephen M. Cameron h->ndevices = 0; 909*edd16368SStephen M. Cameron h->scsi_host = NULL; 910*edd16368SStephen M. Cameron spin_lock_init(&h->devlock); 911*edd16368SStephen M. Cameron return; 912*edd16368SStephen M. Cameron } 913*edd16368SStephen M. Cameron 914*edd16368SStephen M. Cameron static void complete_scsi_command(struct CommandList *cp, 915*edd16368SStephen M. Cameron int timeout, __u32 tag) 916*edd16368SStephen M. Cameron { 917*edd16368SStephen M. Cameron struct scsi_cmnd *cmd; 918*edd16368SStephen M. Cameron struct ctlr_info *h; 919*edd16368SStephen M. Cameron struct ErrorInfo *ei; 920*edd16368SStephen M. Cameron 921*edd16368SStephen M. Cameron unsigned char sense_key; 922*edd16368SStephen M. Cameron unsigned char asc; /* additional sense code */ 923*edd16368SStephen M. Cameron unsigned char ascq; /* additional sense code qualifier */ 924*edd16368SStephen M. Cameron 925*edd16368SStephen M. Cameron ei = cp->err_info; 926*edd16368SStephen M. Cameron cmd = (struct scsi_cmnd *) cp->scsi_cmd; 927*edd16368SStephen M. Cameron h = cp->h; 928*edd16368SStephen M. Cameron 929*edd16368SStephen M. Cameron scsi_dma_unmap(cmd); /* undo the DMA mappings */ 930*edd16368SStephen M. Cameron 931*edd16368SStephen M. Cameron cmd->result = (DID_OK << 16); /* host byte */ 932*edd16368SStephen M. Cameron cmd->result |= (COMMAND_COMPLETE << 8); /* msg byte */ 933*edd16368SStephen M. Cameron cmd->result |= (ei->ScsiStatus << 1); 934*edd16368SStephen M. Cameron 935*edd16368SStephen M. Cameron /* copy the sense data whether we need to or not. */ 936*edd16368SStephen M. Cameron memcpy(cmd->sense_buffer, ei->SenseInfo, 937*edd16368SStephen M. Cameron ei->SenseLen > SCSI_SENSE_BUFFERSIZE ? 938*edd16368SStephen M. Cameron SCSI_SENSE_BUFFERSIZE : 939*edd16368SStephen M. Cameron ei->SenseLen); 940*edd16368SStephen M. Cameron scsi_set_resid(cmd, ei->ResidualCnt); 941*edd16368SStephen M. Cameron 942*edd16368SStephen M. Cameron if (ei->CommandStatus == 0) { 943*edd16368SStephen M. Cameron cmd->scsi_done(cmd); 944*edd16368SStephen M. Cameron cmd_free(h, cp); 945*edd16368SStephen M. Cameron return; 946*edd16368SStephen M. Cameron } 947*edd16368SStephen M. Cameron 948*edd16368SStephen M. Cameron /* an error has occurred */ 949*edd16368SStephen M. Cameron switch (ei->CommandStatus) { 950*edd16368SStephen M. Cameron 951*edd16368SStephen M. Cameron case CMD_TARGET_STATUS: 952*edd16368SStephen M. Cameron if (ei->ScsiStatus) { 953*edd16368SStephen M. Cameron /* Get sense key */ 954*edd16368SStephen M. Cameron sense_key = 0xf & ei->SenseInfo[2]; 955*edd16368SStephen M. Cameron /* Get additional sense code */ 956*edd16368SStephen M. Cameron asc = ei->SenseInfo[12]; 957*edd16368SStephen M. Cameron /* Get addition sense code qualifier */ 958*edd16368SStephen M. Cameron ascq = ei->SenseInfo[13]; 959*edd16368SStephen M. Cameron } 960*edd16368SStephen M. Cameron 961*edd16368SStephen M. Cameron if (ei->ScsiStatus == SAM_STAT_CHECK_CONDITION) { 962*edd16368SStephen M. Cameron if (check_for_unit_attention(h, cp)) { 963*edd16368SStephen M. Cameron cmd->result = DID_SOFT_ERROR << 16; 964*edd16368SStephen M. Cameron break; 965*edd16368SStephen M. Cameron } 966*edd16368SStephen M. Cameron if (sense_key == ILLEGAL_REQUEST) { 967*edd16368SStephen M. Cameron /* 968*edd16368SStephen M. Cameron * SCSI REPORT_LUNS is commonly unsupported on 969*edd16368SStephen M. Cameron * Smart Array. Suppress noisy complaint. 970*edd16368SStephen M. Cameron */ 971*edd16368SStephen M. Cameron if (cp->Request.CDB[0] == REPORT_LUNS) 972*edd16368SStephen M. Cameron break; 973*edd16368SStephen M. Cameron 974*edd16368SStephen M. Cameron /* If ASC/ASCQ indicate Logical Unit 975*edd16368SStephen M. Cameron * Not Supported condition, 976*edd16368SStephen M. Cameron */ 977*edd16368SStephen M. Cameron if ((asc == 0x25) && (ascq == 0x0)) { 978*edd16368SStephen M. Cameron dev_warn(&h->pdev->dev, "cp %p " 979*edd16368SStephen M. Cameron "has check condition\n", cp); 980*edd16368SStephen M. Cameron break; 981*edd16368SStephen M. Cameron } 982*edd16368SStephen M. Cameron } 983*edd16368SStephen M. Cameron 984*edd16368SStephen M. Cameron if (sense_key == NOT_READY) { 985*edd16368SStephen M. Cameron /* If Sense is Not Ready, Logical Unit 986*edd16368SStephen M. Cameron * Not ready, Manual Intervention 987*edd16368SStephen M. Cameron * required 988*edd16368SStephen M. Cameron */ 989*edd16368SStephen M. Cameron if ((asc == 0x04) && (ascq == 0x03)) { 990*edd16368SStephen M. Cameron cmd->result = DID_NO_CONNECT << 16; 991*edd16368SStephen M. Cameron dev_warn(&h->pdev->dev, "cp %p " 992*edd16368SStephen M. Cameron "has check condition: unit " 993*edd16368SStephen M. Cameron "not ready, manual " 994*edd16368SStephen M. Cameron "intervention required\n", cp); 995*edd16368SStephen M. Cameron break; 996*edd16368SStephen M. Cameron } 997*edd16368SStephen M. Cameron } 998*edd16368SStephen M. Cameron 999*edd16368SStephen M. Cameron 1000*edd16368SStephen M. Cameron /* Must be some other type of check condition */ 1001*edd16368SStephen M. Cameron dev_warn(&h->pdev->dev, "cp %p has check condition: " 1002*edd16368SStephen M. Cameron "unknown type: " 1003*edd16368SStephen M. Cameron "Sense: 0x%x, ASC: 0x%x, ASCQ: 0x%x, " 1004*edd16368SStephen M. Cameron "Returning result: 0x%x, " 1005*edd16368SStephen M. Cameron "cmd=[%02x %02x %02x %02x %02x " 1006*edd16368SStephen M. Cameron "%02x %02x %02x %02x %02x]\n", 1007*edd16368SStephen M. Cameron cp, sense_key, asc, ascq, 1008*edd16368SStephen M. Cameron cmd->result, 1009*edd16368SStephen M. Cameron cmd->cmnd[0], cmd->cmnd[1], 1010*edd16368SStephen M. Cameron cmd->cmnd[2], cmd->cmnd[3], 1011*edd16368SStephen M. Cameron cmd->cmnd[4], cmd->cmnd[5], 1012*edd16368SStephen M. Cameron cmd->cmnd[6], cmd->cmnd[7], 1013*edd16368SStephen M. Cameron cmd->cmnd[8], cmd->cmnd[9]); 1014*edd16368SStephen M. Cameron break; 1015*edd16368SStephen M. Cameron } 1016*edd16368SStephen M. Cameron 1017*edd16368SStephen M. Cameron 1018*edd16368SStephen M. Cameron /* Problem was not a check condition 1019*edd16368SStephen M. Cameron * Pass it up to the upper layers... 1020*edd16368SStephen M. Cameron */ 1021*edd16368SStephen M. Cameron if (ei->ScsiStatus) { 1022*edd16368SStephen M. Cameron dev_warn(&h->pdev->dev, "cp %p has status 0x%x " 1023*edd16368SStephen M. Cameron "Sense: 0x%x, ASC: 0x%x, ASCQ: 0x%x, " 1024*edd16368SStephen M. Cameron "Returning result: 0x%x\n", 1025*edd16368SStephen M. Cameron cp, ei->ScsiStatus, 1026*edd16368SStephen M. Cameron sense_key, asc, ascq, 1027*edd16368SStephen M. Cameron cmd->result); 1028*edd16368SStephen M. Cameron } else { /* scsi status is zero??? How??? */ 1029*edd16368SStephen M. Cameron dev_warn(&h->pdev->dev, "cp %p SCSI status was 0. " 1030*edd16368SStephen M. Cameron "Returning no connection.\n", cp), 1031*edd16368SStephen M. Cameron 1032*edd16368SStephen M. Cameron /* Ordinarily, this case should never happen, 1033*edd16368SStephen M. Cameron * but there is a bug in some released firmware 1034*edd16368SStephen M. Cameron * revisions that allows it to happen if, for 1035*edd16368SStephen M. Cameron * example, a 4100 backplane loses power and 1036*edd16368SStephen M. Cameron * the tape drive is in it. We assume that 1037*edd16368SStephen M. Cameron * it's a fatal error of some kind because we 1038*edd16368SStephen M. Cameron * can't show that it wasn't. We will make it 1039*edd16368SStephen M. Cameron * look like selection timeout since that is 1040*edd16368SStephen M. Cameron * the most common reason for this to occur, 1041*edd16368SStephen M. Cameron * and it's severe enough. 1042*edd16368SStephen M. Cameron */ 1043*edd16368SStephen M. Cameron 1044*edd16368SStephen M. Cameron cmd->result = DID_NO_CONNECT << 16; 1045*edd16368SStephen M. Cameron } 1046*edd16368SStephen M. Cameron break; 1047*edd16368SStephen M. Cameron 1048*edd16368SStephen M. Cameron case CMD_DATA_UNDERRUN: /* let mid layer handle it. */ 1049*edd16368SStephen M. Cameron break; 1050*edd16368SStephen M. Cameron case CMD_DATA_OVERRUN: 1051*edd16368SStephen M. Cameron dev_warn(&h->pdev->dev, "cp %p has" 1052*edd16368SStephen M. Cameron " completed with data overrun " 1053*edd16368SStephen M. Cameron "reported\n", cp); 1054*edd16368SStephen M. Cameron break; 1055*edd16368SStephen M. Cameron case CMD_INVALID: { 1056*edd16368SStephen M. Cameron /* print_bytes(cp, sizeof(*cp), 1, 0); 1057*edd16368SStephen M. Cameron print_cmd(cp); */ 1058*edd16368SStephen M. Cameron /* We get CMD_INVALID if you address a non-existent device 1059*edd16368SStephen M. Cameron * instead of a selection timeout (no response). You will 1060*edd16368SStephen M. Cameron * see this if you yank out a drive, then try to access it. 1061*edd16368SStephen M. Cameron * This is kind of a shame because it means that any other 1062*edd16368SStephen M. Cameron * CMD_INVALID (e.g. driver bug) will get interpreted as a 1063*edd16368SStephen M. Cameron * missing target. */ 1064*edd16368SStephen M. Cameron cmd->result = DID_NO_CONNECT << 16; 1065*edd16368SStephen M. Cameron } 1066*edd16368SStephen M. Cameron break; 1067*edd16368SStephen M. Cameron case CMD_PROTOCOL_ERR: 1068*edd16368SStephen M. Cameron dev_warn(&h->pdev->dev, "cp %p has " 1069*edd16368SStephen M. Cameron "protocol error \n", cp); 1070*edd16368SStephen M. Cameron break; 1071*edd16368SStephen M. Cameron case CMD_HARDWARE_ERR: 1072*edd16368SStephen M. Cameron cmd->result = DID_ERROR << 16; 1073*edd16368SStephen M. Cameron dev_warn(&h->pdev->dev, "cp %p had hardware error\n", cp); 1074*edd16368SStephen M. Cameron break; 1075*edd16368SStephen M. Cameron case CMD_CONNECTION_LOST: 1076*edd16368SStephen M. Cameron cmd->result = DID_ERROR << 16; 1077*edd16368SStephen M. Cameron dev_warn(&h->pdev->dev, "cp %p had connection lost\n", cp); 1078*edd16368SStephen M. Cameron break; 1079*edd16368SStephen M. Cameron case CMD_ABORTED: 1080*edd16368SStephen M. Cameron cmd->result = DID_ABORT << 16; 1081*edd16368SStephen M. Cameron dev_warn(&h->pdev->dev, "cp %p was aborted with status 0x%x\n", 1082*edd16368SStephen M. Cameron cp, ei->ScsiStatus); 1083*edd16368SStephen M. Cameron break; 1084*edd16368SStephen M. Cameron case CMD_ABORT_FAILED: 1085*edd16368SStephen M. Cameron cmd->result = DID_ERROR << 16; 1086*edd16368SStephen M. Cameron dev_warn(&h->pdev->dev, "cp %p reports abort failed\n", cp); 1087*edd16368SStephen M. Cameron break; 1088*edd16368SStephen M. Cameron case CMD_UNSOLICITED_ABORT: 1089*edd16368SStephen M. Cameron cmd->result = DID_ABORT << 16; 1090*edd16368SStephen M. Cameron dev_warn(&h->pdev->dev, "cp %p aborted do to an unsolicited " 1091*edd16368SStephen M. Cameron "abort\n", cp); 1092*edd16368SStephen M. Cameron break; 1093*edd16368SStephen M. Cameron case CMD_TIMEOUT: 1094*edd16368SStephen M. Cameron cmd->result = DID_TIME_OUT << 16; 1095*edd16368SStephen M. Cameron dev_warn(&h->pdev->dev, "cp %p timedout\n", cp); 1096*edd16368SStephen M. Cameron break; 1097*edd16368SStephen M. Cameron default: 1098*edd16368SStephen M. Cameron cmd->result = DID_ERROR << 16; 1099*edd16368SStephen M. Cameron dev_warn(&h->pdev->dev, "cp %p returned unknown status %x\n", 1100*edd16368SStephen M. Cameron cp, ei->CommandStatus); 1101*edd16368SStephen M. Cameron } 1102*edd16368SStephen M. Cameron cmd->scsi_done(cmd); 1103*edd16368SStephen M. Cameron cmd_free(h, cp); 1104*edd16368SStephen M. Cameron } 1105*edd16368SStephen M. Cameron 1106*edd16368SStephen M. Cameron static int hpsa_scsi_detect(struct ctlr_info *h) 1107*edd16368SStephen M. Cameron { 1108*edd16368SStephen M. Cameron struct Scsi_Host *sh; 1109*edd16368SStephen M. Cameron int error; 1110*edd16368SStephen M. Cameron 1111*edd16368SStephen M. Cameron sh = scsi_host_alloc(&hpsa_driver_template, sizeof(h)); 1112*edd16368SStephen M. Cameron if (sh == NULL) 1113*edd16368SStephen M. Cameron goto fail; 1114*edd16368SStephen M. Cameron 1115*edd16368SStephen M. Cameron sh->io_port = 0; 1116*edd16368SStephen M. Cameron sh->n_io_port = 0; 1117*edd16368SStephen M. Cameron sh->this_id = -1; 1118*edd16368SStephen M. Cameron sh->max_channel = 3; 1119*edd16368SStephen M. Cameron sh->max_cmd_len = MAX_COMMAND_SIZE; 1120*edd16368SStephen M. Cameron sh->max_lun = HPSA_MAX_LUN; 1121*edd16368SStephen M. Cameron sh->max_id = HPSA_MAX_LUN; 1122*edd16368SStephen M. Cameron h->scsi_host = sh; 1123*edd16368SStephen M. Cameron sh->hostdata[0] = (unsigned long) h; 1124*edd16368SStephen M. Cameron sh->irq = h->intr[SIMPLE_MODE_INT]; 1125*edd16368SStephen M. Cameron sh->unique_id = sh->irq; 1126*edd16368SStephen M. Cameron error = scsi_add_host(sh, &h->pdev->dev); 1127*edd16368SStephen M. Cameron if (error) 1128*edd16368SStephen M. Cameron goto fail_host_put; 1129*edd16368SStephen M. Cameron scsi_scan_host(sh); 1130*edd16368SStephen M. Cameron return 0; 1131*edd16368SStephen M. Cameron 1132*edd16368SStephen M. Cameron fail_host_put: 1133*edd16368SStephen M. Cameron dev_err(&h->pdev->dev, "hpsa_scsi_detect: scsi_add_host" 1134*edd16368SStephen M. Cameron " failed for controller %d\n", h->ctlr); 1135*edd16368SStephen M. Cameron scsi_host_put(sh); 1136*edd16368SStephen M. Cameron return -1; 1137*edd16368SStephen M. Cameron fail: 1138*edd16368SStephen M. Cameron dev_err(&h->pdev->dev, "hpsa_scsi_detect: scsi_host_alloc" 1139*edd16368SStephen M. Cameron " failed for controller %d\n", h->ctlr); 1140*edd16368SStephen M. Cameron return -1; 1141*edd16368SStephen M. Cameron } 1142*edd16368SStephen M. Cameron 1143*edd16368SStephen M. Cameron static void hpsa_pci_unmap(struct pci_dev *pdev, 1144*edd16368SStephen M. Cameron struct CommandList *c, int sg_used, int data_direction) 1145*edd16368SStephen M. Cameron { 1146*edd16368SStephen M. Cameron int i; 1147*edd16368SStephen M. Cameron union u64bit addr64; 1148*edd16368SStephen M. Cameron 1149*edd16368SStephen M. Cameron for (i = 0; i < sg_used; i++) { 1150*edd16368SStephen M. Cameron addr64.val32.lower = c->SG[i].Addr.lower; 1151*edd16368SStephen M. Cameron addr64.val32.upper = c->SG[i].Addr.upper; 1152*edd16368SStephen M. Cameron pci_unmap_single(pdev, (dma_addr_t) addr64.val, c->SG[i].Len, 1153*edd16368SStephen M. Cameron data_direction); 1154*edd16368SStephen M. Cameron } 1155*edd16368SStephen M. Cameron } 1156*edd16368SStephen M. Cameron 1157*edd16368SStephen M. Cameron static void hpsa_map_one(struct pci_dev *pdev, 1158*edd16368SStephen M. Cameron struct CommandList *cp, 1159*edd16368SStephen M. Cameron unsigned char *buf, 1160*edd16368SStephen M. Cameron size_t buflen, 1161*edd16368SStephen M. Cameron int data_direction) 1162*edd16368SStephen M. Cameron { 1163*edd16368SStephen M. Cameron __u64 addr64; 1164*edd16368SStephen M. Cameron 1165*edd16368SStephen M. Cameron if (buflen == 0 || data_direction == PCI_DMA_NONE) { 1166*edd16368SStephen M. Cameron cp->Header.SGList = 0; 1167*edd16368SStephen M. Cameron cp->Header.SGTotal = 0; 1168*edd16368SStephen M. Cameron return; 1169*edd16368SStephen M. Cameron } 1170*edd16368SStephen M. Cameron 1171*edd16368SStephen M. Cameron addr64 = (__u64) pci_map_single(pdev, buf, buflen, data_direction); 1172*edd16368SStephen M. Cameron cp->SG[0].Addr.lower = 1173*edd16368SStephen M. Cameron (__u32) (addr64 & (__u64) 0x00000000FFFFFFFF); 1174*edd16368SStephen M. Cameron cp->SG[0].Addr.upper = 1175*edd16368SStephen M. Cameron (__u32) ((addr64 >> 32) & (__u64) 0x00000000FFFFFFFF); 1176*edd16368SStephen M. Cameron cp->SG[0].Len = buflen; 1177*edd16368SStephen M. Cameron cp->Header.SGList = (__u8) 1; /* no. SGs contig in this cmd */ 1178*edd16368SStephen M. Cameron cp->Header.SGTotal = (__u16) 1; /* total sgs in this cmd list */ 1179*edd16368SStephen M. Cameron } 1180*edd16368SStephen M. Cameron 1181*edd16368SStephen M. Cameron static inline void hpsa_scsi_do_simple_cmd_core(struct ctlr_info *h, 1182*edd16368SStephen M. Cameron struct CommandList *c) 1183*edd16368SStephen M. Cameron { 1184*edd16368SStephen M. Cameron DECLARE_COMPLETION_ONSTACK(wait); 1185*edd16368SStephen M. Cameron 1186*edd16368SStephen M. Cameron c->waiting = &wait; 1187*edd16368SStephen M. Cameron enqueue_cmd_and_start_io(h, c); 1188*edd16368SStephen M. Cameron wait_for_completion(&wait); 1189*edd16368SStephen M. Cameron } 1190*edd16368SStephen M. Cameron 1191*edd16368SStephen M. Cameron static void hpsa_scsi_do_simple_cmd_with_retry(struct ctlr_info *h, 1192*edd16368SStephen M. Cameron struct CommandList *c, int data_direction) 1193*edd16368SStephen M. Cameron { 1194*edd16368SStephen M. Cameron int retry_count = 0; 1195*edd16368SStephen M. Cameron 1196*edd16368SStephen M. Cameron do { 1197*edd16368SStephen M. Cameron memset(c->err_info, 0, sizeof(c->err_info)); 1198*edd16368SStephen M. Cameron hpsa_scsi_do_simple_cmd_core(h, c); 1199*edd16368SStephen M. Cameron retry_count++; 1200*edd16368SStephen M. Cameron } while (check_for_unit_attention(h, c) && retry_count <= 3); 1201*edd16368SStephen M. Cameron hpsa_pci_unmap(h->pdev, c, 1, data_direction); 1202*edd16368SStephen M. Cameron } 1203*edd16368SStephen M. Cameron 1204*edd16368SStephen M. Cameron static void hpsa_scsi_interpret_error(struct CommandList *cp) 1205*edd16368SStephen M. Cameron { 1206*edd16368SStephen M. Cameron struct ErrorInfo *ei; 1207*edd16368SStephen M. Cameron struct device *d = &cp->h->pdev->dev; 1208*edd16368SStephen M. Cameron 1209*edd16368SStephen M. Cameron ei = cp->err_info; 1210*edd16368SStephen M. Cameron switch (ei->CommandStatus) { 1211*edd16368SStephen M. Cameron case CMD_TARGET_STATUS: 1212*edd16368SStephen M. Cameron dev_warn(d, "cmd %p has completed with errors\n", cp); 1213*edd16368SStephen M. Cameron dev_warn(d, "cmd %p has SCSI Status = %x\n", cp, 1214*edd16368SStephen M. Cameron ei->ScsiStatus); 1215*edd16368SStephen M. Cameron if (ei->ScsiStatus == 0) 1216*edd16368SStephen M. Cameron dev_warn(d, "SCSI status is abnormally zero. " 1217*edd16368SStephen M. Cameron "(probably indicates selection timeout " 1218*edd16368SStephen M. Cameron "reported incorrectly due to a known " 1219*edd16368SStephen M. Cameron "firmware bug, circa July, 2001.)\n"); 1220*edd16368SStephen M. Cameron break; 1221*edd16368SStephen M. Cameron case CMD_DATA_UNDERRUN: /* let mid layer handle it. */ 1222*edd16368SStephen M. Cameron dev_info(d, "UNDERRUN\n"); 1223*edd16368SStephen M. Cameron break; 1224*edd16368SStephen M. Cameron case CMD_DATA_OVERRUN: 1225*edd16368SStephen M. Cameron dev_warn(d, "cp %p has completed with data overrun\n", cp); 1226*edd16368SStephen M. Cameron break; 1227*edd16368SStephen M. Cameron case CMD_INVALID: { 1228*edd16368SStephen M. Cameron /* controller unfortunately reports SCSI passthru's 1229*edd16368SStephen M. Cameron * to non-existent targets as invalid commands. 1230*edd16368SStephen M. Cameron */ 1231*edd16368SStephen M. Cameron dev_warn(d, "cp %p is reported invalid (probably means " 1232*edd16368SStephen M. Cameron "target device no longer present)\n", cp); 1233*edd16368SStephen M. Cameron /* print_bytes((unsigned char *) cp, sizeof(*cp), 1, 0); 1234*edd16368SStephen M. Cameron print_cmd(cp); */ 1235*edd16368SStephen M. Cameron } 1236*edd16368SStephen M. Cameron break; 1237*edd16368SStephen M. Cameron case CMD_PROTOCOL_ERR: 1238*edd16368SStephen M. Cameron dev_warn(d, "cp %p has protocol error \n", cp); 1239*edd16368SStephen M. Cameron break; 1240*edd16368SStephen M. Cameron case CMD_HARDWARE_ERR: 1241*edd16368SStephen M. Cameron /* cmd->result = DID_ERROR << 16; */ 1242*edd16368SStephen M. Cameron dev_warn(d, "cp %p had hardware error\n", cp); 1243*edd16368SStephen M. Cameron break; 1244*edd16368SStephen M. Cameron case CMD_CONNECTION_LOST: 1245*edd16368SStephen M. Cameron dev_warn(d, "cp %p had connection lost\n", cp); 1246*edd16368SStephen M. Cameron break; 1247*edd16368SStephen M. Cameron case CMD_ABORTED: 1248*edd16368SStephen M. Cameron dev_warn(d, "cp %p was aborted\n", cp); 1249*edd16368SStephen M. Cameron break; 1250*edd16368SStephen M. Cameron case CMD_ABORT_FAILED: 1251*edd16368SStephen M. Cameron dev_warn(d, "cp %p reports abort failed\n", cp); 1252*edd16368SStephen M. Cameron break; 1253*edd16368SStephen M. Cameron case CMD_UNSOLICITED_ABORT: 1254*edd16368SStephen M. Cameron dev_warn(d, "cp %p aborted due to an unsolicited abort\n", cp); 1255*edd16368SStephen M. Cameron break; 1256*edd16368SStephen M. Cameron case CMD_TIMEOUT: 1257*edd16368SStephen M. Cameron dev_warn(d, "cp %p timed out\n", cp); 1258*edd16368SStephen M. Cameron break; 1259*edd16368SStephen M. Cameron default: 1260*edd16368SStephen M. Cameron dev_warn(d, "cp %p returned unknown status %x\n", cp, 1261*edd16368SStephen M. Cameron ei->CommandStatus); 1262*edd16368SStephen M. Cameron } 1263*edd16368SStephen M. Cameron } 1264*edd16368SStephen M. Cameron 1265*edd16368SStephen M. Cameron static int hpsa_scsi_do_inquiry(struct ctlr_info *h, unsigned char *scsi3addr, 1266*edd16368SStephen M. Cameron unsigned char page, unsigned char *buf, 1267*edd16368SStephen M. Cameron unsigned char bufsize) 1268*edd16368SStephen M. Cameron { 1269*edd16368SStephen M. Cameron int rc = IO_OK; 1270*edd16368SStephen M. Cameron struct CommandList *c; 1271*edd16368SStephen M. Cameron struct ErrorInfo *ei; 1272*edd16368SStephen M. Cameron 1273*edd16368SStephen M. Cameron c = cmd_special_alloc(h); 1274*edd16368SStephen M. Cameron 1275*edd16368SStephen M. Cameron if (c == NULL) { /* trouble... */ 1276*edd16368SStephen M. Cameron dev_warn(&h->pdev->dev, "cmd_special_alloc returned NULL!\n"); 1277*edd16368SStephen M. Cameron return -1; 1278*edd16368SStephen M. Cameron } 1279*edd16368SStephen M. Cameron 1280*edd16368SStephen M. Cameron fill_cmd(c, HPSA_INQUIRY, h, buf, bufsize, page, scsi3addr, TYPE_CMD); 1281*edd16368SStephen M. Cameron hpsa_scsi_do_simple_cmd_with_retry(h, c, PCI_DMA_FROMDEVICE); 1282*edd16368SStephen M. Cameron ei = c->err_info; 1283*edd16368SStephen M. Cameron if (ei->CommandStatus != 0 && ei->CommandStatus != CMD_DATA_UNDERRUN) { 1284*edd16368SStephen M. Cameron hpsa_scsi_interpret_error(c); 1285*edd16368SStephen M. Cameron rc = -1; 1286*edd16368SStephen M. Cameron } 1287*edd16368SStephen M. Cameron cmd_special_free(h, c); 1288*edd16368SStephen M. Cameron return rc; 1289*edd16368SStephen M. Cameron } 1290*edd16368SStephen M. Cameron 1291*edd16368SStephen M. Cameron static int hpsa_send_reset(struct ctlr_info *h, unsigned char *scsi3addr) 1292*edd16368SStephen M. Cameron { 1293*edd16368SStephen M. Cameron int rc = IO_OK; 1294*edd16368SStephen M. Cameron struct CommandList *c; 1295*edd16368SStephen M. Cameron struct ErrorInfo *ei; 1296*edd16368SStephen M. Cameron 1297*edd16368SStephen M. Cameron c = cmd_special_alloc(h); 1298*edd16368SStephen M. Cameron 1299*edd16368SStephen M. Cameron if (c == NULL) { /* trouble... */ 1300*edd16368SStephen M. Cameron dev_warn(&h->pdev->dev, "cmd_special_alloc returned NULL!\n"); 1301*edd16368SStephen M. Cameron return -1; 1302*edd16368SStephen M. Cameron } 1303*edd16368SStephen M. Cameron 1304*edd16368SStephen M. Cameron fill_cmd(c, HPSA_DEVICE_RESET_MSG, h, NULL, 0, 0, scsi3addr, TYPE_MSG); 1305*edd16368SStephen M. Cameron hpsa_scsi_do_simple_cmd_core(h, c); 1306*edd16368SStephen M. Cameron /* no unmap needed here because no data xfer. */ 1307*edd16368SStephen M. Cameron 1308*edd16368SStephen M. Cameron ei = c->err_info; 1309*edd16368SStephen M. Cameron if (ei->CommandStatus != 0) { 1310*edd16368SStephen M. Cameron hpsa_scsi_interpret_error(c); 1311*edd16368SStephen M. Cameron rc = -1; 1312*edd16368SStephen M. Cameron } 1313*edd16368SStephen M. Cameron cmd_special_free(h, c); 1314*edd16368SStephen M. Cameron return rc; 1315*edd16368SStephen M. Cameron } 1316*edd16368SStephen M. Cameron 1317*edd16368SStephen M. Cameron static void hpsa_get_raid_level(struct ctlr_info *h, 1318*edd16368SStephen M. Cameron unsigned char *scsi3addr, unsigned char *raid_level) 1319*edd16368SStephen M. Cameron { 1320*edd16368SStephen M. Cameron int rc; 1321*edd16368SStephen M. Cameron unsigned char *buf; 1322*edd16368SStephen M. Cameron 1323*edd16368SStephen M. Cameron *raid_level = RAID_UNKNOWN; 1324*edd16368SStephen M. Cameron buf = kzalloc(64, GFP_KERNEL); 1325*edd16368SStephen M. Cameron if (!buf) 1326*edd16368SStephen M. Cameron return; 1327*edd16368SStephen M. Cameron rc = hpsa_scsi_do_inquiry(h, scsi3addr, 0xC1, buf, 64); 1328*edd16368SStephen M. Cameron if (rc == 0) 1329*edd16368SStephen M. Cameron *raid_level = buf[8]; 1330*edd16368SStephen M. Cameron if (*raid_level > RAID_UNKNOWN) 1331*edd16368SStephen M. Cameron *raid_level = RAID_UNKNOWN; 1332*edd16368SStephen M. Cameron kfree(buf); 1333*edd16368SStephen M. Cameron return; 1334*edd16368SStephen M. Cameron } 1335*edd16368SStephen M. Cameron 1336*edd16368SStephen M. Cameron /* Get the device id from inquiry page 0x83 */ 1337*edd16368SStephen M. Cameron static int hpsa_get_device_id(struct ctlr_info *h, unsigned char *scsi3addr, 1338*edd16368SStephen M. Cameron unsigned char *device_id, int buflen) 1339*edd16368SStephen M. Cameron { 1340*edd16368SStephen M. Cameron int rc; 1341*edd16368SStephen M. Cameron unsigned char *buf; 1342*edd16368SStephen M. Cameron 1343*edd16368SStephen M. Cameron if (buflen > 16) 1344*edd16368SStephen M. Cameron buflen = 16; 1345*edd16368SStephen M. Cameron buf = kzalloc(64, GFP_KERNEL); 1346*edd16368SStephen M. Cameron if (!buf) 1347*edd16368SStephen M. Cameron return -1; 1348*edd16368SStephen M. Cameron rc = hpsa_scsi_do_inquiry(h, scsi3addr, 0x83, buf, 64); 1349*edd16368SStephen M. Cameron if (rc == 0) 1350*edd16368SStephen M. Cameron memcpy(device_id, &buf[8], buflen); 1351*edd16368SStephen M. Cameron kfree(buf); 1352*edd16368SStephen M. Cameron return rc != 0; 1353*edd16368SStephen M. Cameron } 1354*edd16368SStephen M. Cameron 1355*edd16368SStephen M. Cameron static int hpsa_scsi_do_report_luns(struct ctlr_info *h, int logical, 1356*edd16368SStephen M. Cameron struct ReportLUNdata *buf, int bufsize, 1357*edd16368SStephen M. Cameron int extended_response) 1358*edd16368SStephen M. Cameron { 1359*edd16368SStephen M. Cameron int rc = IO_OK; 1360*edd16368SStephen M. Cameron struct CommandList *c; 1361*edd16368SStephen M. Cameron unsigned char scsi3addr[8]; 1362*edd16368SStephen M. Cameron struct ErrorInfo *ei; 1363*edd16368SStephen M. Cameron 1364*edd16368SStephen M. Cameron c = cmd_special_alloc(h); 1365*edd16368SStephen M. Cameron if (c == NULL) { /* trouble... */ 1366*edd16368SStephen M. Cameron dev_err(&h->pdev->dev, "cmd_special_alloc returned NULL!\n"); 1367*edd16368SStephen M. Cameron return -1; 1368*edd16368SStephen M. Cameron } 1369*edd16368SStephen M. Cameron 1370*edd16368SStephen M. Cameron memset(&scsi3addr[0], 0, 8); /* address the controller */ 1371*edd16368SStephen M. Cameron 1372*edd16368SStephen M. Cameron fill_cmd(c, logical ? HPSA_REPORT_LOG : HPSA_REPORT_PHYS, h, 1373*edd16368SStephen M. Cameron buf, bufsize, 0, scsi3addr, TYPE_CMD); 1374*edd16368SStephen M. Cameron if (extended_response) 1375*edd16368SStephen M. Cameron c->Request.CDB[1] = extended_response; 1376*edd16368SStephen M. Cameron hpsa_scsi_do_simple_cmd_with_retry(h, c, PCI_DMA_FROMDEVICE); 1377*edd16368SStephen M. Cameron ei = c->err_info; 1378*edd16368SStephen M. Cameron if (ei->CommandStatus != 0 && 1379*edd16368SStephen M. Cameron ei->CommandStatus != CMD_DATA_UNDERRUN) { 1380*edd16368SStephen M. Cameron hpsa_scsi_interpret_error(c); 1381*edd16368SStephen M. Cameron rc = -1; 1382*edd16368SStephen M. Cameron } 1383*edd16368SStephen M. Cameron cmd_special_free(h, c); 1384*edd16368SStephen M. Cameron return rc; 1385*edd16368SStephen M. Cameron } 1386*edd16368SStephen M. Cameron 1387*edd16368SStephen M. Cameron static inline int hpsa_scsi_do_report_phys_luns(struct ctlr_info *h, 1388*edd16368SStephen M. Cameron struct ReportLUNdata *buf, 1389*edd16368SStephen M. Cameron int bufsize, int extended_response) 1390*edd16368SStephen M. Cameron { 1391*edd16368SStephen M. Cameron return hpsa_scsi_do_report_luns(h, 0, buf, bufsize, extended_response); 1392*edd16368SStephen M. Cameron } 1393*edd16368SStephen M. Cameron 1394*edd16368SStephen M. Cameron static inline int hpsa_scsi_do_report_log_luns(struct ctlr_info *h, 1395*edd16368SStephen M. Cameron struct ReportLUNdata *buf, int bufsize) 1396*edd16368SStephen M. Cameron { 1397*edd16368SStephen M. Cameron return hpsa_scsi_do_report_luns(h, 1, buf, bufsize, 0); 1398*edd16368SStephen M. Cameron } 1399*edd16368SStephen M. Cameron 1400*edd16368SStephen M. Cameron static inline void hpsa_set_bus_target_lun(struct hpsa_scsi_dev_t *device, 1401*edd16368SStephen M. Cameron int bus, int target, int lun) 1402*edd16368SStephen M. Cameron { 1403*edd16368SStephen M. Cameron device->bus = bus; 1404*edd16368SStephen M. Cameron device->target = target; 1405*edd16368SStephen M. Cameron device->lun = lun; 1406*edd16368SStephen M. Cameron } 1407*edd16368SStephen M. Cameron 1408*edd16368SStephen M. Cameron static int hpsa_update_device_info(struct ctlr_info *h, 1409*edd16368SStephen M. Cameron unsigned char scsi3addr[], struct hpsa_scsi_dev_t *this_device) 1410*edd16368SStephen M. Cameron { 1411*edd16368SStephen M. Cameron #define OBDR_TAPE_INQ_SIZE 49 1412*edd16368SStephen M. Cameron unsigned char *inq_buff = NULL; 1413*edd16368SStephen M. Cameron 1414*edd16368SStephen M. Cameron inq_buff = kmalloc(OBDR_TAPE_INQ_SIZE, GFP_KERNEL); 1415*edd16368SStephen M. Cameron if (!inq_buff) 1416*edd16368SStephen M. Cameron goto bail_out; 1417*edd16368SStephen M. Cameron 1418*edd16368SStephen M. Cameron memset(inq_buff, 0, OBDR_TAPE_INQ_SIZE); 1419*edd16368SStephen M. Cameron /* Do an inquiry to the device to see what it is. */ 1420*edd16368SStephen M. Cameron if (hpsa_scsi_do_inquiry(h, scsi3addr, 0, inq_buff, 1421*edd16368SStephen M. Cameron (unsigned char) OBDR_TAPE_INQ_SIZE) != 0) { 1422*edd16368SStephen M. Cameron /* Inquiry failed (msg printed already) */ 1423*edd16368SStephen M. Cameron dev_err(&h->pdev->dev, 1424*edd16368SStephen M. Cameron "hpsa_update_device_info: inquiry failed\n"); 1425*edd16368SStephen M. Cameron goto bail_out; 1426*edd16368SStephen M. Cameron } 1427*edd16368SStephen M. Cameron 1428*edd16368SStephen M. Cameron /* As a side effect, record the firmware version number 1429*edd16368SStephen M. Cameron * if we happen to be talking to the RAID controller. 1430*edd16368SStephen M. Cameron */ 1431*edd16368SStephen M. Cameron if (is_hba_lunid(scsi3addr)) 1432*edd16368SStephen M. Cameron memcpy(h->firm_ver, &inq_buff[32], 4); 1433*edd16368SStephen M. Cameron 1434*edd16368SStephen M. Cameron this_device->devtype = (inq_buff[0] & 0x1f); 1435*edd16368SStephen M. Cameron memcpy(this_device->scsi3addr, scsi3addr, 8); 1436*edd16368SStephen M. Cameron memcpy(this_device->vendor, &inq_buff[8], 1437*edd16368SStephen M. Cameron sizeof(this_device->vendor)); 1438*edd16368SStephen M. Cameron memcpy(this_device->model, &inq_buff[16], 1439*edd16368SStephen M. Cameron sizeof(this_device->model)); 1440*edd16368SStephen M. Cameron memcpy(this_device->revision, &inq_buff[32], 1441*edd16368SStephen M. Cameron sizeof(this_device->revision)); 1442*edd16368SStephen M. Cameron memset(this_device->device_id, 0, 1443*edd16368SStephen M. Cameron sizeof(this_device->device_id)); 1444*edd16368SStephen M. Cameron hpsa_get_device_id(h, scsi3addr, this_device->device_id, 1445*edd16368SStephen M. Cameron sizeof(this_device->device_id)); 1446*edd16368SStephen M. Cameron 1447*edd16368SStephen M. Cameron if (this_device->devtype == TYPE_DISK && 1448*edd16368SStephen M. Cameron is_logical_dev_addr_mode(scsi3addr)) 1449*edd16368SStephen M. Cameron hpsa_get_raid_level(h, scsi3addr, &this_device->raid_level); 1450*edd16368SStephen M. Cameron else 1451*edd16368SStephen M. Cameron this_device->raid_level = RAID_UNKNOWN; 1452*edd16368SStephen M. Cameron 1453*edd16368SStephen M. Cameron kfree(inq_buff); 1454*edd16368SStephen M. Cameron return 0; 1455*edd16368SStephen M. Cameron 1456*edd16368SStephen M. Cameron bail_out: 1457*edd16368SStephen M. Cameron kfree(inq_buff); 1458*edd16368SStephen M. Cameron return 1; 1459*edd16368SStephen M. Cameron } 1460*edd16368SStephen M. Cameron 1461*edd16368SStephen M. Cameron static unsigned char *msa2xxx_model[] = { 1462*edd16368SStephen M. Cameron "MSA2012", 1463*edd16368SStephen M. Cameron "MSA2024", 1464*edd16368SStephen M. Cameron "MSA2312", 1465*edd16368SStephen M. Cameron "MSA2324", 1466*edd16368SStephen M. Cameron NULL, 1467*edd16368SStephen M. Cameron }; 1468*edd16368SStephen M. Cameron 1469*edd16368SStephen M. Cameron static int is_msa2xxx(struct ctlr_info *h, struct hpsa_scsi_dev_t *device) 1470*edd16368SStephen M. Cameron { 1471*edd16368SStephen M. Cameron int i; 1472*edd16368SStephen M. Cameron 1473*edd16368SStephen M. Cameron for (i = 0; msa2xxx_model[i]; i++) 1474*edd16368SStephen M. Cameron if (strncmp(device->model, msa2xxx_model[i], 1475*edd16368SStephen M. Cameron strlen(msa2xxx_model[i])) == 0) 1476*edd16368SStephen M. Cameron return 1; 1477*edd16368SStephen M. Cameron return 0; 1478*edd16368SStephen M. Cameron } 1479*edd16368SStephen M. Cameron 1480*edd16368SStephen M. Cameron /* Helper function to assign bus, target, lun mapping of devices. 1481*edd16368SStephen M. Cameron * Puts non-msa2xxx logical volumes on bus 0, msa2xxx logical 1482*edd16368SStephen M. Cameron * volumes on bus 1, physical devices on bus 2. and the hba on bus 3. 1483*edd16368SStephen M. Cameron * Logical drive target and lun are assigned at this time, but 1484*edd16368SStephen M. Cameron * physical device lun and target assignment are deferred (assigned 1485*edd16368SStephen M. Cameron * in hpsa_find_target_lun, called by hpsa_scsi_add_entry.) 1486*edd16368SStephen M. Cameron */ 1487*edd16368SStephen M. Cameron static void figure_bus_target_lun(struct ctlr_info *h, 1488*edd16368SStephen M. Cameron __u8 *lunaddrbytes, int *bus, int *target, int *lun, 1489*edd16368SStephen M. Cameron struct hpsa_scsi_dev_t *device) 1490*edd16368SStephen M. Cameron { 1491*edd16368SStephen M. Cameron 1492*edd16368SStephen M. Cameron __u32 lunid; 1493*edd16368SStephen M. Cameron 1494*edd16368SStephen M. Cameron if (is_logical_dev_addr_mode(lunaddrbytes)) { 1495*edd16368SStephen M. Cameron /* logical device */ 1496*edd16368SStephen M. Cameron memcpy(&lunid, lunaddrbytes, sizeof(lunid)); 1497*edd16368SStephen M. Cameron lunid = le32_to_cpu(lunid); 1498*edd16368SStephen M. Cameron 1499*edd16368SStephen M. Cameron if (is_msa2xxx(h, device)) { 1500*edd16368SStephen M. Cameron *bus = 1; 1501*edd16368SStephen M. Cameron *target = (lunid >> 16) & 0x3fff; 1502*edd16368SStephen M. Cameron *lun = lunid & 0x00ff; 1503*edd16368SStephen M. Cameron } else { 1504*edd16368SStephen M. Cameron *bus = 0; 1505*edd16368SStephen M. Cameron *lun = 0; 1506*edd16368SStephen M. Cameron *target = lunid & 0x3fff; 1507*edd16368SStephen M. Cameron } 1508*edd16368SStephen M. Cameron } else { 1509*edd16368SStephen M. Cameron /* physical device */ 1510*edd16368SStephen M. Cameron if (is_hba_lunid(lunaddrbytes)) 1511*edd16368SStephen M. Cameron *bus = 3; 1512*edd16368SStephen M. Cameron else 1513*edd16368SStephen M. Cameron *bus = 2; 1514*edd16368SStephen M. Cameron *target = -1; 1515*edd16368SStephen M. Cameron *lun = -1; /* we will fill these in later. */ 1516*edd16368SStephen M. Cameron } 1517*edd16368SStephen M. Cameron } 1518*edd16368SStephen M. Cameron 1519*edd16368SStephen M. Cameron /* 1520*edd16368SStephen M. Cameron * If there is no lun 0 on a target, linux won't find any devices. 1521*edd16368SStephen M. Cameron * For the MSA2xxx boxes, we have to manually detect the enclosure 1522*edd16368SStephen M. Cameron * which is at lun zero, as CCISS_REPORT_PHYSICAL_LUNS doesn't report 1523*edd16368SStephen M. Cameron * it for some reason. *tmpdevice is the target we're adding, 1524*edd16368SStephen M. Cameron * this_device is a pointer into the current element of currentsd[] 1525*edd16368SStephen M. Cameron * that we're building up in update_scsi_devices(), below. 1526*edd16368SStephen M. Cameron * lunzerobits is a bitmap that tracks which targets already have a 1527*edd16368SStephen M. Cameron * lun 0 assigned. 1528*edd16368SStephen M. Cameron * Returns 1 if an enclosure was added, 0 if not. 1529*edd16368SStephen M. Cameron */ 1530*edd16368SStephen M. Cameron static int add_msa2xxx_enclosure_device(struct ctlr_info *h, 1531*edd16368SStephen M. Cameron struct hpsa_scsi_dev_t *tmpdevice, 1532*edd16368SStephen M. Cameron struct hpsa_scsi_dev_t *this_device, __u8 *lunaddrbytes, 1533*edd16368SStephen M. Cameron int bus, int target, int lun, unsigned long lunzerobits[], 1534*edd16368SStephen M. Cameron int *nmsa2xxx_enclosures) 1535*edd16368SStephen M. Cameron { 1536*edd16368SStephen M. Cameron unsigned char scsi3addr[8]; 1537*edd16368SStephen M. Cameron 1538*edd16368SStephen M. Cameron if (test_bit(target, lunzerobits)) 1539*edd16368SStephen M. Cameron return 0; /* There is already a lun 0 on this target. */ 1540*edd16368SStephen M. Cameron 1541*edd16368SStephen M. Cameron if (!is_logical_dev_addr_mode(lunaddrbytes)) 1542*edd16368SStephen M. Cameron return 0; /* It's the logical targets that may lack lun 0. */ 1543*edd16368SStephen M. Cameron 1544*edd16368SStephen M. Cameron if (!is_msa2xxx(h, tmpdevice)) 1545*edd16368SStephen M. Cameron return 0; /* It's only the MSA2xxx that have this problem. */ 1546*edd16368SStephen M. Cameron 1547*edd16368SStephen M. Cameron if (lun == 0) /* if lun is 0, then obviously we have a lun 0. */ 1548*edd16368SStephen M. Cameron return 0; 1549*edd16368SStephen M. Cameron 1550*edd16368SStephen M. Cameron if (is_hba_lunid(scsi3addr)) 1551*edd16368SStephen M. Cameron return 0; /* Don't add the RAID controller here. */ 1552*edd16368SStephen M. Cameron 1553*edd16368SStephen M. Cameron #define MAX_MSA2XXX_ENCLOSURES 32 1554*edd16368SStephen M. Cameron if (*nmsa2xxx_enclosures >= MAX_MSA2XXX_ENCLOSURES) { 1555*edd16368SStephen M. Cameron dev_warn(&h->pdev->dev, "Maximum number of MSA2XXX " 1556*edd16368SStephen M. Cameron "enclosures exceeded. Check your hardware " 1557*edd16368SStephen M. Cameron "configuration."); 1558*edd16368SStephen M. Cameron return 0; 1559*edd16368SStephen M. Cameron } 1560*edd16368SStephen M. Cameron 1561*edd16368SStephen M. Cameron memset(scsi3addr, 0, 8); 1562*edd16368SStephen M. Cameron scsi3addr[3] = target; 1563*edd16368SStephen M. Cameron if (hpsa_update_device_info(h, scsi3addr, this_device)) 1564*edd16368SStephen M. Cameron return 0; 1565*edd16368SStephen M. Cameron (*nmsa2xxx_enclosures)++; 1566*edd16368SStephen M. Cameron hpsa_set_bus_target_lun(this_device, bus, target, 0); 1567*edd16368SStephen M. Cameron set_bit(target, lunzerobits); 1568*edd16368SStephen M. Cameron return 1; 1569*edd16368SStephen M. Cameron } 1570*edd16368SStephen M. Cameron 1571*edd16368SStephen M. Cameron /* 1572*edd16368SStephen M. Cameron * Do CISS_REPORT_PHYS and CISS_REPORT_LOG. Data is returned in physdev, 1573*edd16368SStephen M. Cameron * logdev. The number of luns in physdev and logdev are returned in 1574*edd16368SStephen M. Cameron * *nphysicals and *nlogicals, respectively. 1575*edd16368SStephen M. Cameron * Returns 0 on success, -1 otherwise. 1576*edd16368SStephen M. Cameron */ 1577*edd16368SStephen M. Cameron static int hpsa_gather_lun_info(struct ctlr_info *h, 1578*edd16368SStephen M. Cameron int reportlunsize, 1579*edd16368SStephen M. Cameron struct ReportLUNdata *physdev, __u32 *nphysicals, 1580*edd16368SStephen M. Cameron struct ReportLUNdata *logdev, __u32 *nlogicals) 1581*edd16368SStephen M. Cameron { 1582*edd16368SStephen M. Cameron if (hpsa_scsi_do_report_phys_luns(h, physdev, reportlunsize, 0)) { 1583*edd16368SStephen M. Cameron dev_err(&h->pdev->dev, "report physical LUNs failed.\n"); 1584*edd16368SStephen M. Cameron return -1; 1585*edd16368SStephen M. Cameron } 1586*edd16368SStephen M. Cameron memcpy(nphysicals, &physdev->LUNListLength[0], sizeof(*nphysicals)); 1587*edd16368SStephen M. Cameron *nphysicals = be32_to_cpu(*nphysicals) / 8; 1588*edd16368SStephen M. Cameron #ifdef DEBUG 1589*edd16368SStephen M. Cameron dev_info(&h->pdev->dev, "number of physical luns is %d\n", *nphysicals); 1590*edd16368SStephen M. Cameron #endif 1591*edd16368SStephen M. Cameron if (*nphysicals > HPSA_MAX_PHYS_LUN) { 1592*edd16368SStephen M. Cameron dev_warn(&h->pdev->dev, "maximum physical LUNs (%d) exceeded." 1593*edd16368SStephen M. Cameron " %d LUNs ignored.\n", HPSA_MAX_PHYS_LUN, 1594*edd16368SStephen M. Cameron *nphysicals - HPSA_MAX_PHYS_LUN); 1595*edd16368SStephen M. Cameron *nphysicals = HPSA_MAX_PHYS_LUN; 1596*edd16368SStephen M. Cameron } 1597*edd16368SStephen M. Cameron if (hpsa_scsi_do_report_log_luns(h, logdev, reportlunsize)) { 1598*edd16368SStephen M. Cameron dev_err(&h->pdev->dev, "report logical LUNs failed.\n"); 1599*edd16368SStephen M. Cameron return -1; 1600*edd16368SStephen M. Cameron } 1601*edd16368SStephen M. Cameron memcpy(nlogicals, &logdev->LUNListLength[0], sizeof(*nlogicals)); 1602*edd16368SStephen M. Cameron *nlogicals = be32_to_cpu(*nlogicals) / 8; 1603*edd16368SStephen M. Cameron #ifdef DEBUG 1604*edd16368SStephen M. Cameron dev_info(&h->pdev->dev, "number of logical luns is %d\n", *nlogicals); 1605*edd16368SStephen M. Cameron #endif 1606*edd16368SStephen M. Cameron /* Reject Logicals in excess of our max capability. */ 1607*edd16368SStephen M. Cameron if (*nlogicals > HPSA_MAX_LUN) { 1608*edd16368SStephen M. Cameron dev_warn(&h->pdev->dev, 1609*edd16368SStephen M. Cameron "maximum logical LUNs (%d) exceeded. " 1610*edd16368SStephen M. Cameron "%d LUNs ignored.\n", HPSA_MAX_LUN, 1611*edd16368SStephen M. Cameron *nlogicals - HPSA_MAX_LUN); 1612*edd16368SStephen M. Cameron *nlogicals = HPSA_MAX_LUN; 1613*edd16368SStephen M. Cameron } 1614*edd16368SStephen M. Cameron if (*nlogicals + *nphysicals > HPSA_MAX_PHYS_LUN) { 1615*edd16368SStephen M. Cameron dev_warn(&h->pdev->dev, 1616*edd16368SStephen M. Cameron "maximum logical + physical LUNs (%d) exceeded. " 1617*edd16368SStephen M. Cameron "%d LUNs ignored.\n", HPSA_MAX_PHYS_LUN, 1618*edd16368SStephen M. Cameron *nphysicals + *nlogicals - HPSA_MAX_PHYS_LUN); 1619*edd16368SStephen M. Cameron *nlogicals = HPSA_MAX_PHYS_LUN - *nphysicals; 1620*edd16368SStephen M. Cameron } 1621*edd16368SStephen M. Cameron return 0; 1622*edd16368SStephen M. Cameron } 1623*edd16368SStephen M. Cameron 1624*edd16368SStephen M. Cameron static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno) 1625*edd16368SStephen M. Cameron { 1626*edd16368SStephen M. Cameron /* the idea here is we could get notified 1627*edd16368SStephen M. Cameron * that some devices have changed, so we do a report 1628*edd16368SStephen M. Cameron * physical luns and report logical luns cmd, and adjust 1629*edd16368SStephen M. Cameron * our list of devices accordingly. 1630*edd16368SStephen M. Cameron * 1631*edd16368SStephen M. Cameron * The scsi3addr's of devices won't change so long as the 1632*edd16368SStephen M. Cameron * adapter is not reset. That means we can rescan and 1633*edd16368SStephen M. Cameron * tell which devices we already know about, vs. new 1634*edd16368SStephen M. Cameron * devices, vs. disappearing devices. 1635*edd16368SStephen M. Cameron */ 1636*edd16368SStephen M. Cameron struct ReportLUNdata *physdev_list = NULL; 1637*edd16368SStephen M. Cameron struct ReportLUNdata *logdev_list = NULL; 1638*edd16368SStephen M. Cameron unsigned char *inq_buff = NULL; 1639*edd16368SStephen M. Cameron __u32 nphysicals = 0; 1640*edd16368SStephen M. Cameron __u32 nlogicals = 0; 1641*edd16368SStephen M. Cameron __u32 ndev_allocated = 0; 1642*edd16368SStephen M. Cameron struct hpsa_scsi_dev_t **currentsd, *this_device, *tmpdevice; 1643*edd16368SStephen M. Cameron int ncurrent = 0; 1644*edd16368SStephen M. Cameron int reportlunsize = sizeof(*physdev_list) + HPSA_MAX_PHYS_LUN * 8; 1645*edd16368SStephen M. Cameron int i, nmsa2xxx_enclosures, ndevs_to_allocate; 1646*edd16368SStephen M. Cameron int bus, target, lun; 1647*edd16368SStephen M. Cameron DECLARE_BITMAP(lunzerobits, HPSA_MAX_TARGETS_PER_CTLR); 1648*edd16368SStephen M. Cameron 1649*edd16368SStephen M. Cameron currentsd = kzalloc(sizeof(*currentsd) * HPSA_MAX_SCSI_DEVS_PER_HBA, 1650*edd16368SStephen M. Cameron GFP_KERNEL); 1651*edd16368SStephen M. Cameron physdev_list = kzalloc(reportlunsize, GFP_KERNEL); 1652*edd16368SStephen M. Cameron logdev_list = kzalloc(reportlunsize, GFP_KERNEL); 1653*edd16368SStephen M. Cameron inq_buff = kmalloc(OBDR_TAPE_INQ_SIZE, GFP_KERNEL); 1654*edd16368SStephen M. Cameron tmpdevice = kzalloc(sizeof(*tmpdevice), GFP_KERNEL); 1655*edd16368SStephen M. Cameron 1656*edd16368SStephen M. Cameron if (!currentsd || !physdev_list || !logdev_list || 1657*edd16368SStephen M. Cameron !inq_buff || !tmpdevice) { 1658*edd16368SStephen M. Cameron dev_err(&h->pdev->dev, "out of memory\n"); 1659*edd16368SStephen M. Cameron goto out; 1660*edd16368SStephen M. Cameron } 1661*edd16368SStephen M. Cameron memset(lunzerobits, 0, sizeof(lunzerobits)); 1662*edd16368SStephen M. Cameron 1663*edd16368SStephen M. Cameron if (hpsa_gather_lun_info(h, reportlunsize, physdev_list, &nphysicals, 1664*edd16368SStephen M. Cameron logdev_list, &nlogicals)) 1665*edd16368SStephen M. Cameron goto out; 1666*edd16368SStephen M. Cameron 1667*edd16368SStephen M. Cameron /* We might see up to 32 MSA2xxx enclosures, actually 8 of them 1668*edd16368SStephen M. Cameron * but each of them 4 times through different paths. The plus 1 1669*edd16368SStephen M. Cameron * is for the RAID controller. 1670*edd16368SStephen M. Cameron */ 1671*edd16368SStephen M. Cameron ndevs_to_allocate = nphysicals + nlogicals + MAX_MSA2XXX_ENCLOSURES + 1; 1672*edd16368SStephen M. Cameron 1673*edd16368SStephen M. Cameron /* Allocate the per device structures */ 1674*edd16368SStephen M. Cameron for (i = 0; i < ndevs_to_allocate; i++) { 1675*edd16368SStephen M. Cameron currentsd[i] = kzalloc(sizeof(*currentsd[i]), GFP_KERNEL); 1676*edd16368SStephen M. Cameron if (!currentsd[i]) { 1677*edd16368SStephen M. Cameron dev_warn(&h->pdev->dev, "out of memory at %s:%d\n", 1678*edd16368SStephen M. Cameron __FILE__, __LINE__); 1679*edd16368SStephen M. Cameron goto out; 1680*edd16368SStephen M. Cameron } 1681*edd16368SStephen M. Cameron ndev_allocated++; 1682*edd16368SStephen M. Cameron } 1683*edd16368SStephen M. Cameron 1684*edd16368SStephen M. Cameron /* adjust our table of devices */ 1685*edd16368SStephen M. Cameron nmsa2xxx_enclosures = 0; 1686*edd16368SStephen M. Cameron for (i = 0; i < nphysicals + nlogicals + 1; i++) { 1687*edd16368SStephen M. Cameron __u8 *lunaddrbytes; 1688*edd16368SStephen M. Cameron 1689*edd16368SStephen M. Cameron /* Figure out where the LUN ID info is coming from */ 1690*edd16368SStephen M. Cameron if (i < nphysicals) 1691*edd16368SStephen M. Cameron lunaddrbytes = &physdev_list->LUN[i][0]; 1692*edd16368SStephen M. Cameron else 1693*edd16368SStephen M. Cameron if (i < nphysicals + nlogicals) 1694*edd16368SStephen M. Cameron lunaddrbytes = 1695*edd16368SStephen M. Cameron &logdev_list->LUN[i-nphysicals][0]; 1696*edd16368SStephen M. Cameron else /* jam in the RAID controller at the end */ 1697*edd16368SStephen M. Cameron lunaddrbytes = RAID_CTLR_LUNID; 1698*edd16368SStephen M. Cameron 1699*edd16368SStephen M. Cameron /* skip masked physical devices. */ 1700*edd16368SStephen M. Cameron if (lunaddrbytes[3] & 0xC0 && i < nphysicals) 1701*edd16368SStephen M. Cameron continue; 1702*edd16368SStephen M. Cameron 1703*edd16368SStephen M. Cameron /* Get device type, vendor, model, device id */ 1704*edd16368SStephen M. Cameron if (hpsa_update_device_info(h, lunaddrbytes, tmpdevice)) 1705*edd16368SStephen M. Cameron continue; /* skip it if we can't talk to it. */ 1706*edd16368SStephen M. Cameron figure_bus_target_lun(h, lunaddrbytes, &bus, &target, &lun, 1707*edd16368SStephen M. Cameron tmpdevice); 1708*edd16368SStephen M. Cameron this_device = currentsd[ncurrent]; 1709*edd16368SStephen M. Cameron 1710*edd16368SStephen M. Cameron /* 1711*edd16368SStephen M. Cameron * For the msa2xxx boxes, we have to insert a LUN 0 which 1712*edd16368SStephen M. Cameron * doesn't show up in CCISS_REPORT_PHYSICAL data, but there 1713*edd16368SStephen M. Cameron * is nonetheless an enclosure device there. We have to 1714*edd16368SStephen M. Cameron * present that otherwise linux won't find anything if 1715*edd16368SStephen M. Cameron * there is no lun 0. 1716*edd16368SStephen M. Cameron */ 1717*edd16368SStephen M. Cameron if (add_msa2xxx_enclosure_device(h, tmpdevice, this_device, 1718*edd16368SStephen M. Cameron lunaddrbytes, bus, target, lun, lunzerobits, 1719*edd16368SStephen M. Cameron &nmsa2xxx_enclosures)) { 1720*edd16368SStephen M. Cameron ncurrent++; 1721*edd16368SStephen M. Cameron this_device = currentsd[ncurrent]; 1722*edd16368SStephen M. Cameron } 1723*edd16368SStephen M. Cameron 1724*edd16368SStephen M. Cameron *this_device = *tmpdevice; 1725*edd16368SStephen M. Cameron hpsa_set_bus_target_lun(this_device, bus, target, lun); 1726*edd16368SStephen M. Cameron 1727*edd16368SStephen M. Cameron switch (this_device->devtype) { 1728*edd16368SStephen M. Cameron case TYPE_ROM: { 1729*edd16368SStephen M. Cameron /* We don't *really* support actual CD-ROM devices, 1730*edd16368SStephen M. Cameron * just "One Button Disaster Recovery" tape drive 1731*edd16368SStephen M. Cameron * which temporarily pretends to be a CD-ROM drive. 1732*edd16368SStephen M. Cameron * So we check that the device is really an OBDR tape 1733*edd16368SStephen M. Cameron * device by checking for "$DR-10" in bytes 43-48 of 1734*edd16368SStephen M. Cameron * the inquiry data. 1735*edd16368SStephen M. Cameron */ 1736*edd16368SStephen M. Cameron char obdr_sig[7]; 1737*edd16368SStephen M. Cameron #define OBDR_TAPE_SIG "$DR-10" 1738*edd16368SStephen M. Cameron strncpy(obdr_sig, &inq_buff[43], 6); 1739*edd16368SStephen M. Cameron obdr_sig[6] = '\0'; 1740*edd16368SStephen M. Cameron if (strncmp(obdr_sig, OBDR_TAPE_SIG, 6) != 0) 1741*edd16368SStephen M. Cameron /* Not OBDR device, ignore it. */ 1742*edd16368SStephen M. Cameron break; 1743*edd16368SStephen M. Cameron } 1744*edd16368SStephen M. Cameron ncurrent++; 1745*edd16368SStephen M. Cameron break; 1746*edd16368SStephen M. Cameron case TYPE_DISK: 1747*edd16368SStephen M. Cameron if (i < nphysicals) 1748*edd16368SStephen M. Cameron break; 1749*edd16368SStephen M. Cameron ncurrent++; 1750*edd16368SStephen M. Cameron break; 1751*edd16368SStephen M. Cameron case TYPE_TAPE: 1752*edd16368SStephen M. Cameron case TYPE_MEDIUM_CHANGER: 1753*edd16368SStephen M. Cameron ncurrent++; 1754*edd16368SStephen M. Cameron break; 1755*edd16368SStephen M. Cameron case TYPE_RAID: 1756*edd16368SStephen M. Cameron /* Only present the Smartarray HBA as a RAID controller. 1757*edd16368SStephen M. Cameron * If it's a RAID controller other than the HBA itself 1758*edd16368SStephen M. Cameron * (an external RAID controller, MSA500 or similar) 1759*edd16368SStephen M. Cameron * don't present it. 1760*edd16368SStephen M. Cameron */ 1761*edd16368SStephen M. Cameron if (!is_hba_lunid(lunaddrbytes)) 1762*edd16368SStephen M. Cameron break; 1763*edd16368SStephen M. Cameron ncurrent++; 1764*edd16368SStephen M. Cameron break; 1765*edd16368SStephen M. Cameron default: 1766*edd16368SStephen M. Cameron break; 1767*edd16368SStephen M. Cameron } 1768*edd16368SStephen M. Cameron if (ncurrent >= HPSA_MAX_SCSI_DEVS_PER_HBA) 1769*edd16368SStephen M. Cameron break; 1770*edd16368SStephen M. Cameron } 1771*edd16368SStephen M. Cameron adjust_hpsa_scsi_table(h, hostno, currentsd, ncurrent); 1772*edd16368SStephen M. Cameron out: 1773*edd16368SStephen M. Cameron kfree(tmpdevice); 1774*edd16368SStephen M. Cameron for (i = 0; i < ndev_allocated; i++) 1775*edd16368SStephen M. Cameron kfree(currentsd[i]); 1776*edd16368SStephen M. Cameron kfree(currentsd); 1777*edd16368SStephen M. Cameron kfree(inq_buff); 1778*edd16368SStephen M. Cameron kfree(physdev_list); 1779*edd16368SStephen M. Cameron kfree(logdev_list); 1780*edd16368SStephen M. Cameron return; 1781*edd16368SStephen M. Cameron } 1782*edd16368SStephen M. Cameron 1783*edd16368SStephen M. Cameron /* hpsa_scatter_gather takes a struct scsi_cmnd, (cmd), and does the pci 1784*edd16368SStephen M. Cameron * dma mapping and fills in the scatter gather entries of the 1785*edd16368SStephen M. Cameron * hpsa command, cp. 1786*edd16368SStephen M. Cameron */ 1787*edd16368SStephen M. Cameron static int hpsa_scatter_gather(struct pci_dev *pdev, 1788*edd16368SStephen M. Cameron struct CommandList *cp, 1789*edd16368SStephen M. Cameron struct scsi_cmnd *cmd) 1790*edd16368SStephen M. Cameron { 1791*edd16368SStephen M. Cameron unsigned int len; 1792*edd16368SStephen M. Cameron struct scatterlist *sg; 1793*edd16368SStephen M. Cameron __u64 addr64; 1794*edd16368SStephen M. Cameron int use_sg, i; 1795*edd16368SStephen M. Cameron 1796*edd16368SStephen M. Cameron BUG_ON(scsi_sg_count(cmd) > MAXSGENTRIES); 1797*edd16368SStephen M. Cameron 1798*edd16368SStephen M. Cameron use_sg = scsi_dma_map(cmd); 1799*edd16368SStephen M. Cameron if (use_sg < 0) 1800*edd16368SStephen M. Cameron return use_sg; 1801*edd16368SStephen M. Cameron 1802*edd16368SStephen M. Cameron if (!use_sg) 1803*edd16368SStephen M. Cameron goto sglist_finished; 1804*edd16368SStephen M. Cameron 1805*edd16368SStephen M. Cameron scsi_for_each_sg(cmd, sg, use_sg, i) { 1806*edd16368SStephen M. Cameron addr64 = (__u64) sg_dma_address(sg); 1807*edd16368SStephen M. Cameron len = sg_dma_len(sg); 1808*edd16368SStephen M. Cameron cp->SG[i].Addr.lower = 1809*edd16368SStephen M. Cameron (__u32) (addr64 & (__u64) 0x00000000FFFFFFFF); 1810*edd16368SStephen M. Cameron cp->SG[i].Addr.upper = 1811*edd16368SStephen M. Cameron (__u32) ((addr64 >> 32) & (__u64) 0x00000000FFFFFFFF); 1812*edd16368SStephen M. Cameron cp->SG[i].Len = len; 1813*edd16368SStephen M. Cameron cp->SG[i].Ext = 0; /* we are not chaining */ 1814*edd16368SStephen M. Cameron } 1815*edd16368SStephen M. Cameron 1816*edd16368SStephen M. Cameron sglist_finished: 1817*edd16368SStephen M. Cameron 1818*edd16368SStephen M. Cameron cp->Header.SGList = (__u8) use_sg; /* no. SGs contig in this cmd */ 1819*edd16368SStephen M. Cameron cp->Header.SGTotal = (__u16) use_sg; /* total sgs in this cmd list */ 1820*edd16368SStephen M. Cameron return 0; 1821*edd16368SStephen M. Cameron } 1822*edd16368SStephen M. Cameron 1823*edd16368SStephen M. Cameron 1824*edd16368SStephen M. Cameron static int hpsa_scsi_queue_command(struct scsi_cmnd *cmd, 1825*edd16368SStephen M. Cameron void (*done)(struct scsi_cmnd *)) 1826*edd16368SStephen M. Cameron { 1827*edd16368SStephen M. Cameron struct ctlr_info *h; 1828*edd16368SStephen M. Cameron struct hpsa_scsi_dev_t *dev; 1829*edd16368SStephen M. Cameron unsigned char scsi3addr[8]; 1830*edd16368SStephen M. Cameron struct CommandList *c; 1831*edd16368SStephen M. Cameron unsigned long flags; 1832*edd16368SStephen M. Cameron 1833*edd16368SStephen M. Cameron /* Get the ptr to our adapter structure out of cmd->host. */ 1834*edd16368SStephen M. Cameron h = sdev_to_hba(cmd->device); 1835*edd16368SStephen M. Cameron dev = cmd->device->hostdata; 1836*edd16368SStephen M. Cameron if (!dev) { 1837*edd16368SStephen M. Cameron cmd->result = DID_NO_CONNECT << 16; 1838*edd16368SStephen M. Cameron done(cmd); 1839*edd16368SStephen M. Cameron return 0; 1840*edd16368SStephen M. Cameron } 1841*edd16368SStephen M. Cameron memcpy(scsi3addr, dev->scsi3addr, sizeof(scsi3addr)); 1842*edd16368SStephen M. Cameron 1843*edd16368SStephen M. Cameron /* Need a lock as this is being allocated from the pool */ 1844*edd16368SStephen M. Cameron spin_lock_irqsave(&h->lock, flags); 1845*edd16368SStephen M. Cameron c = cmd_alloc(h); 1846*edd16368SStephen M. Cameron spin_unlock_irqrestore(&h->lock, flags); 1847*edd16368SStephen M. Cameron if (c == NULL) { /* trouble... */ 1848*edd16368SStephen M. Cameron dev_err(&h->pdev->dev, "cmd_alloc returned NULL!\n"); 1849*edd16368SStephen M. Cameron return SCSI_MLQUEUE_HOST_BUSY; 1850*edd16368SStephen M. Cameron } 1851*edd16368SStephen M. Cameron 1852*edd16368SStephen M. Cameron /* Fill in the command list header */ 1853*edd16368SStephen M. Cameron 1854*edd16368SStephen M. Cameron cmd->scsi_done = done; /* save this for use by completion code */ 1855*edd16368SStephen M. Cameron 1856*edd16368SStephen M. Cameron /* save c in case we have to abort it */ 1857*edd16368SStephen M. Cameron cmd->host_scribble = (unsigned char *) c; 1858*edd16368SStephen M. Cameron 1859*edd16368SStephen M. Cameron c->cmd_type = CMD_SCSI; 1860*edd16368SStephen M. Cameron c->scsi_cmd = cmd; 1861*edd16368SStephen M. Cameron c->Header.ReplyQueue = 0; /* unused in simple mode */ 1862*edd16368SStephen M. Cameron memcpy(&c->Header.LUN.LunAddrBytes[0], &scsi3addr[0], 8); 1863*edd16368SStephen M. Cameron c->Header.Tag.lower = c->busaddr; /* Use k. address of cmd as tag */ 1864*edd16368SStephen M. Cameron 1865*edd16368SStephen M. Cameron /* Fill in the request block... */ 1866*edd16368SStephen M. Cameron 1867*edd16368SStephen M. Cameron c->Request.Timeout = 0; 1868*edd16368SStephen M. Cameron memset(c->Request.CDB, 0, sizeof(c->Request.CDB)); 1869*edd16368SStephen M. Cameron BUG_ON(cmd->cmd_len > sizeof(c->Request.CDB)); 1870*edd16368SStephen M. Cameron c->Request.CDBLen = cmd->cmd_len; 1871*edd16368SStephen M. Cameron memcpy(c->Request.CDB, cmd->cmnd, cmd->cmd_len); 1872*edd16368SStephen M. Cameron c->Request.Type.Type = TYPE_CMD; 1873*edd16368SStephen M. Cameron c->Request.Type.Attribute = ATTR_SIMPLE; 1874*edd16368SStephen M. Cameron switch (cmd->sc_data_direction) { 1875*edd16368SStephen M. Cameron case DMA_TO_DEVICE: 1876*edd16368SStephen M. Cameron c->Request.Type.Direction = XFER_WRITE; 1877*edd16368SStephen M. Cameron break; 1878*edd16368SStephen M. Cameron case DMA_FROM_DEVICE: 1879*edd16368SStephen M. Cameron c->Request.Type.Direction = XFER_READ; 1880*edd16368SStephen M. Cameron break; 1881*edd16368SStephen M. Cameron case DMA_NONE: 1882*edd16368SStephen M. Cameron c->Request.Type.Direction = XFER_NONE; 1883*edd16368SStephen M. Cameron break; 1884*edd16368SStephen M. Cameron case DMA_BIDIRECTIONAL: 1885*edd16368SStephen M. Cameron /* This can happen if a buggy application does a scsi passthru 1886*edd16368SStephen M. Cameron * and sets both inlen and outlen to non-zero. ( see 1887*edd16368SStephen M. Cameron * ../scsi/scsi_ioctl.c:scsi_ioctl_send_command() ) 1888*edd16368SStephen M. Cameron */ 1889*edd16368SStephen M. Cameron 1890*edd16368SStephen M. Cameron c->Request.Type.Direction = XFER_RSVD; 1891*edd16368SStephen M. Cameron /* This is technically wrong, and hpsa controllers should 1892*edd16368SStephen M. Cameron * reject it with CMD_INVALID, which is the most correct 1893*edd16368SStephen M. Cameron * response, but non-fibre backends appear to let it 1894*edd16368SStephen M. Cameron * slide by, and give the same results as if this field 1895*edd16368SStephen M. Cameron * were set correctly. Either way is acceptable for 1896*edd16368SStephen M. Cameron * our purposes here. 1897*edd16368SStephen M. Cameron */ 1898*edd16368SStephen M. Cameron 1899*edd16368SStephen M. Cameron break; 1900*edd16368SStephen M. Cameron 1901*edd16368SStephen M. Cameron default: 1902*edd16368SStephen M. Cameron dev_err(&h->pdev->dev, "unknown data direction: %d\n", 1903*edd16368SStephen M. Cameron cmd->sc_data_direction); 1904*edd16368SStephen M. Cameron BUG(); 1905*edd16368SStephen M. Cameron break; 1906*edd16368SStephen M. Cameron } 1907*edd16368SStephen M. Cameron 1908*edd16368SStephen M. Cameron if (hpsa_scatter_gather(h->pdev, c, cmd) < 0) { /* Fill SG list */ 1909*edd16368SStephen M. Cameron cmd_free(h, c); 1910*edd16368SStephen M. Cameron return SCSI_MLQUEUE_HOST_BUSY; 1911*edd16368SStephen M. Cameron } 1912*edd16368SStephen M. Cameron enqueue_cmd_and_start_io(h, c); 1913*edd16368SStephen M. Cameron /* the cmd'll come back via intr handler in complete_scsi_command() */ 1914*edd16368SStephen M. Cameron return 0; 1915*edd16368SStephen M. Cameron } 1916*edd16368SStephen M. Cameron 1917*edd16368SStephen M. Cameron static void hpsa_unregister_scsi(struct ctlr_info *h) 1918*edd16368SStephen M. Cameron { 1919*edd16368SStephen M. Cameron /* we are being forcibly unloaded, and may not refuse. */ 1920*edd16368SStephen M. Cameron scsi_remove_host(h->scsi_host); 1921*edd16368SStephen M. Cameron scsi_host_put(h->scsi_host); 1922*edd16368SStephen M. Cameron h->scsi_host = NULL; 1923*edd16368SStephen M. Cameron } 1924*edd16368SStephen M. Cameron 1925*edd16368SStephen M. Cameron static int hpsa_register_scsi(struct ctlr_info *h) 1926*edd16368SStephen M. Cameron { 1927*edd16368SStephen M. Cameron int rc; 1928*edd16368SStephen M. Cameron 1929*edd16368SStephen M. Cameron hpsa_update_scsi_devices(h, -1); 1930*edd16368SStephen M. Cameron rc = hpsa_scsi_detect(h); 1931*edd16368SStephen M. Cameron if (rc != 0) 1932*edd16368SStephen M. Cameron dev_err(&h->pdev->dev, "hpsa_register_scsi: failed" 1933*edd16368SStephen M. Cameron " hpsa_scsi_detect(), rc is %d\n", rc); 1934*edd16368SStephen M. Cameron return rc; 1935*edd16368SStephen M. Cameron } 1936*edd16368SStephen M. Cameron 1937*edd16368SStephen M. Cameron static int wait_for_device_to_become_ready(struct ctlr_info *h, 1938*edd16368SStephen M. Cameron unsigned char lunaddr[]) 1939*edd16368SStephen M. Cameron { 1940*edd16368SStephen M. Cameron int rc = 0; 1941*edd16368SStephen M. Cameron int count = 0; 1942*edd16368SStephen M. Cameron int waittime = 1; /* seconds */ 1943*edd16368SStephen M. Cameron struct CommandList *c; 1944*edd16368SStephen M. Cameron 1945*edd16368SStephen M. Cameron c = cmd_special_alloc(h); 1946*edd16368SStephen M. Cameron if (!c) { 1947*edd16368SStephen M. Cameron dev_warn(&h->pdev->dev, "out of memory in " 1948*edd16368SStephen M. Cameron "wait_for_device_to_become_ready.\n"); 1949*edd16368SStephen M. Cameron return IO_ERROR; 1950*edd16368SStephen M. Cameron } 1951*edd16368SStephen M. Cameron 1952*edd16368SStephen M. Cameron /* Send test unit ready until device ready, or give up. */ 1953*edd16368SStephen M. Cameron while (count < HPSA_TUR_RETRY_LIMIT) { 1954*edd16368SStephen M. Cameron 1955*edd16368SStephen M. Cameron /* Wait for a bit. do this first, because if we send 1956*edd16368SStephen M. Cameron * the TUR right away, the reset will just abort it. 1957*edd16368SStephen M. Cameron */ 1958*edd16368SStephen M. Cameron msleep(1000 * waittime); 1959*edd16368SStephen M. Cameron count++; 1960*edd16368SStephen M. Cameron 1961*edd16368SStephen M. Cameron /* Increase wait time with each try, up to a point. */ 1962*edd16368SStephen M. Cameron if (waittime < HPSA_MAX_WAIT_INTERVAL_SECS) 1963*edd16368SStephen M. Cameron waittime = waittime * 2; 1964*edd16368SStephen M. Cameron 1965*edd16368SStephen M. Cameron /* Send the Test Unit Ready */ 1966*edd16368SStephen M. Cameron fill_cmd(c, TEST_UNIT_READY, h, NULL, 0, 0, lunaddr, TYPE_CMD); 1967*edd16368SStephen M. Cameron hpsa_scsi_do_simple_cmd_core(h, c); 1968*edd16368SStephen M. Cameron /* no unmap needed here because no data xfer. */ 1969*edd16368SStephen M. Cameron 1970*edd16368SStephen M. Cameron if (c->err_info->CommandStatus == CMD_SUCCESS) 1971*edd16368SStephen M. Cameron break; 1972*edd16368SStephen M. Cameron 1973*edd16368SStephen M. Cameron if (c->err_info->CommandStatus == CMD_TARGET_STATUS && 1974*edd16368SStephen M. Cameron c->err_info->ScsiStatus == SAM_STAT_CHECK_CONDITION && 1975*edd16368SStephen M. Cameron (c->err_info->SenseInfo[2] == NO_SENSE || 1976*edd16368SStephen M. Cameron c->err_info->SenseInfo[2] == UNIT_ATTENTION)) 1977*edd16368SStephen M. Cameron break; 1978*edd16368SStephen M. Cameron 1979*edd16368SStephen M. Cameron dev_warn(&h->pdev->dev, "waiting %d secs " 1980*edd16368SStephen M. Cameron "for device to become ready.\n", waittime); 1981*edd16368SStephen M. Cameron rc = 1; /* device not ready. */ 1982*edd16368SStephen M. Cameron } 1983*edd16368SStephen M. Cameron 1984*edd16368SStephen M. Cameron if (rc) 1985*edd16368SStephen M. Cameron dev_warn(&h->pdev->dev, "giving up on device.\n"); 1986*edd16368SStephen M. Cameron else 1987*edd16368SStephen M. Cameron dev_warn(&h->pdev->dev, "device is ready.\n"); 1988*edd16368SStephen M. Cameron 1989*edd16368SStephen M. Cameron cmd_special_free(h, c); 1990*edd16368SStephen M. Cameron return rc; 1991*edd16368SStephen M. Cameron } 1992*edd16368SStephen M. Cameron 1993*edd16368SStephen M. Cameron /* Need at least one of these error handlers to keep ../scsi/hosts.c from 1994*edd16368SStephen M. Cameron * complaining. Doing a host- or bus-reset can't do anything good here. 1995*edd16368SStephen M. Cameron */ 1996*edd16368SStephen M. Cameron static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd) 1997*edd16368SStephen M. Cameron { 1998*edd16368SStephen M. Cameron int rc; 1999*edd16368SStephen M. Cameron struct ctlr_info *h; 2000*edd16368SStephen M. Cameron struct hpsa_scsi_dev_t *dev; 2001*edd16368SStephen M. Cameron 2002*edd16368SStephen M. Cameron /* find the controller to which the command to be aborted was sent */ 2003*edd16368SStephen M. Cameron h = sdev_to_hba(scsicmd->device); 2004*edd16368SStephen M. Cameron if (h == NULL) /* paranoia */ 2005*edd16368SStephen M. Cameron return FAILED; 2006*edd16368SStephen M. Cameron dev_warn(&h->pdev->dev, "resetting drive\n"); 2007*edd16368SStephen M. Cameron 2008*edd16368SStephen M. Cameron dev = scsicmd->device->hostdata; 2009*edd16368SStephen M. Cameron if (!dev) { 2010*edd16368SStephen M. Cameron dev_err(&h->pdev->dev, "hpsa_eh_device_reset_handler: " 2011*edd16368SStephen M. Cameron "device lookup failed.\n"); 2012*edd16368SStephen M. Cameron return FAILED; 2013*edd16368SStephen M. Cameron } 2014*edd16368SStephen M. Cameron /* send a reset to the SCSI LUN which the command was sent to */ 2015*edd16368SStephen M. Cameron rc = hpsa_send_reset(h, dev->scsi3addr); 2016*edd16368SStephen M. Cameron if (rc == 0 && wait_for_device_to_become_ready(h, dev->scsi3addr) == 0) 2017*edd16368SStephen M. Cameron return SUCCESS; 2018*edd16368SStephen M. Cameron 2019*edd16368SStephen M. Cameron dev_warn(&h->pdev->dev, "resetting device failed.\n"); 2020*edd16368SStephen M. Cameron return FAILED; 2021*edd16368SStephen M. Cameron } 2022*edd16368SStephen M. Cameron 2023*edd16368SStephen M. Cameron /* 2024*edd16368SStephen M. Cameron * For operations that cannot sleep, a command block is allocated at init, 2025*edd16368SStephen M. Cameron * and managed by cmd_alloc() and cmd_free() using a simple bitmap to track 2026*edd16368SStephen M. Cameron * which ones are free or in use. Lock must be held when calling this. 2027*edd16368SStephen M. Cameron * cmd_free() is the complement. 2028*edd16368SStephen M. Cameron */ 2029*edd16368SStephen M. Cameron static struct CommandList *cmd_alloc(struct ctlr_info *h) 2030*edd16368SStephen M. Cameron { 2031*edd16368SStephen M. Cameron struct CommandList *c; 2032*edd16368SStephen M. Cameron int i; 2033*edd16368SStephen M. Cameron union u64bit temp64; 2034*edd16368SStephen M. Cameron dma_addr_t cmd_dma_handle, err_dma_handle; 2035*edd16368SStephen M. Cameron 2036*edd16368SStephen M. Cameron do { 2037*edd16368SStephen M. Cameron i = find_first_zero_bit(h->cmd_pool_bits, h->nr_cmds); 2038*edd16368SStephen M. Cameron if (i == h->nr_cmds) 2039*edd16368SStephen M. Cameron return NULL; 2040*edd16368SStephen M. Cameron } while (test_and_set_bit 2041*edd16368SStephen M. Cameron (i & (BITS_PER_LONG - 1), 2042*edd16368SStephen M. Cameron h->cmd_pool_bits + (i / BITS_PER_LONG)) != 0); 2043*edd16368SStephen M. Cameron c = h->cmd_pool + i; 2044*edd16368SStephen M. Cameron memset(c, 0, sizeof(*c)); 2045*edd16368SStephen M. Cameron cmd_dma_handle = h->cmd_pool_dhandle 2046*edd16368SStephen M. Cameron + i * sizeof(*c); 2047*edd16368SStephen M. Cameron c->err_info = h->errinfo_pool + i; 2048*edd16368SStephen M. Cameron memset(c->err_info, 0, sizeof(*c->err_info)); 2049*edd16368SStephen M. Cameron err_dma_handle = h->errinfo_pool_dhandle 2050*edd16368SStephen M. Cameron + i * sizeof(*c->err_info); 2051*edd16368SStephen M. Cameron h->nr_allocs++; 2052*edd16368SStephen M. Cameron 2053*edd16368SStephen M. Cameron c->cmdindex = i; 2054*edd16368SStephen M. Cameron 2055*edd16368SStephen M. Cameron INIT_HLIST_NODE(&c->list); 2056*edd16368SStephen M. Cameron c->busaddr = (__u32) cmd_dma_handle; 2057*edd16368SStephen M. Cameron temp64.val = (__u64) err_dma_handle; 2058*edd16368SStephen M. Cameron c->ErrDesc.Addr.lower = temp64.val32.lower; 2059*edd16368SStephen M. Cameron c->ErrDesc.Addr.upper = temp64.val32.upper; 2060*edd16368SStephen M. Cameron c->ErrDesc.Len = sizeof(*c->err_info); 2061*edd16368SStephen M. Cameron 2062*edd16368SStephen M. Cameron c->h = h; 2063*edd16368SStephen M. Cameron return c; 2064*edd16368SStephen M. Cameron } 2065*edd16368SStephen M. Cameron 2066*edd16368SStephen M. Cameron /* For operations that can wait for kmalloc to possibly sleep, 2067*edd16368SStephen M. Cameron * this routine can be called. Lock need not be held to call 2068*edd16368SStephen M. Cameron * cmd_special_alloc. cmd_special_free() is the complement. 2069*edd16368SStephen M. Cameron */ 2070*edd16368SStephen M. Cameron static struct CommandList *cmd_special_alloc(struct ctlr_info *h) 2071*edd16368SStephen M. Cameron { 2072*edd16368SStephen M. Cameron struct CommandList *c; 2073*edd16368SStephen M. Cameron union u64bit temp64; 2074*edd16368SStephen M. Cameron dma_addr_t cmd_dma_handle, err_dma_handle; 2075*edd16368SStephen M. Cameron 2076*edd16368SStephen M. Cameron c = pci_alloc_consistent(h->pdev, sizeof(*c), &cmd_dma_handle); 2077*edd16368SStephen M. Cameron if (c == NULL) 2078*edd16368SStephen M. Cameron return NULL; 2079*edd16368SStephen M. Cameron memset(c, 0, sizeof(*c)); 2080*edd16368SStephen M. Cameron 2081*edd16368SStephen M. Cameron c->cmdindex = -1; 2082*edd16368SStephen M. Cameron 2083*edd16368SStephen M. Cameron c->err_info = pci_alloc_consistent(h->pdev, sizeof(*c->err_info), 2084*edd16368SStephen M. Cameron &err_dma_handle); 2085*edd16368SStephen M. Cameron 2086*edd16368SStephen M. Cameron if (c->err_info == NULL) { 2087*edd16368SStephen M. Cameron pci_free_consistent(h->pdev, 2088*edd16368SStephen M. Cameron sizeof(*c), c, cmd_dma_handle); 2089*edd16368SStephen M. Cameron return NULL; 2090*edd16368SStephen M. Cameron } 2091*edd16368SStephen M. Cameron memset(c->err_info, 0, sizeof(*c->err_info)); 2092*edd16368SStephen M. Cameron 2093*edd16368SStephen M. Cameron INIT_HLIST_NODE(&c->list); 2094*edd16368SStephen M. Cameron c->busaddr = (__u32) cmd_dma_handle; 2095*edd16368SStephen M. Cameron temp64.val = (__u64) err_dma_handle; 2096*edd16368SStephen M. Cameron c->ErrDesc.Addr.lower = temp64.val32.lower; 2097*edd16368SStephen M. Cameron c->ErrDesc.Addr.upper = temp64.val32.upper; 2098*edd16368SStephen M. Cameron c->ErrDesc.Len = sizeof(*c->err_info); 2099*edd16368SStephen M. Cameron 2100*edd16368SStephen M. Cameron c->h = h; 2101*edd16368SStephen M. Cameron return c; 2102*edd16368SStephen M. Cameron } 2103*edd16368SStephen M. Cameron 2104*edd16368SStephen M. Cameron static void cmd_free(struct ctlr_info *h, struct CommandList *c) 2105*edd16368SStephen M. Cameron { 2106*edd16368SStephen M. Cameron int i; 2107*edd16368SStephen M. Cameron 2108*edd16368SStephen M. Cameron i = c - h->cmd_pool; 2109*edd16368SStephen M. Cameron clear_bit(i & (BITS_PER_LONG - 1), 2110*edd16368SStephen M. Cameron h->cmd_pool_bits + (i / BITS_PER_LONG)); 2111*edd16368SStephen M. Cameron h->nr_frees++; 2112*edd16368SStephen M. Cameron } 2113*edd16368SStephen M. Cameron 2114*edd16368SStephen M. Cameron static void cmd_special_free(struct ctlr_info *h, struct CommandList *c) 2115*edd16368SStephen M. Cameron { 2116*edd16368SStephen M. Cameron union u64bit temp64; 2117*edd16368SStephen M. Cameron 2118*edd16368SStephen M. Cameron temp64.val32.lower = c->ErrDesc.Addr.lower; 2119*edd16368SStephen M. Cameron temp64.val32.upper = c->ErrDesc.Addr.upper; 2120*edd16368SStephen M. Cameron pci_free_consistent(h->pdev, sizeof(*c->err_info), 2121*edd16368SStephen M. Cameron c->err_info, (dma_addr_t) temp64.val); 2122*edd16368SStephen M. Cameron pci_free_consistent(h->pdev, sizeof(*c), 2123*edd16368SStephen M. Cameron c, (dma_addr_t) c->busaddr); 2124*edd16368SStephen M. Cameron } 2125*edd16368SStephen M. Cameron 2126*edd16368SStephen M. Cameron #ifdef CONFIG_COMPAT 2127*edd16368SStephen M. Cameron 2128*edd16368SStephen M. Cameron static int do_ioctl(struct scsi_device *dev, int cmd, void *arg) 2129*edd16368SStephen M. Cameron { 2130*edd16368SStephen M. Cameron int ret; 2131*edd16368SStephen M. Cameron 2132*edd16368SStephen M. Cameron lock_kernel(); 2133*edd16368SStephen M. Cameron ret = hpsa_ioctl(dev, cmd, arg); 2134*edd16368SStephen M. Cameron unlock_kernel(); 2135*edd16368SStephen M. Cameron return ret; 2136*edd16368SStephen M. Cameron } 2137*edd16368SStephen M. Cameron 2138*edd16368SStephen M. Cameron static int hpsa_ioctl32_passthru(struct scsi_device *dev, int cmd, void *arg); 2139*edd16368SStephen M. Cameron static int hpsa_ioctl32_big_passthru(struct scsi_device *dev, 2140*edd16368SStephen M. Cameron int cmd, void *arg); 2141*edd16368SStephen M. Cameron 2142*edd16368SStephen M. Cameron static int hpsa_compat_ioctl(struct scsi_device *dev, int cmd, void *arg) 2143*edd16368SStephen M. Cameron { 2144*edd16368SStephen M. Cameron switch (cmd) { 2145*edd16368SStephen M. Cameron case CCISS_GETPCIINFO: 2146*edd16368SStephen M. Cameron case CCISS_GETINTINFO: 2147*edd16368SStephen M. Cameron case CCISS_SETINTINFO: 2148*edd16368SStephen M. Cameron case CCISS_GETNODENAME: 2149*edd16368SStephen M. Cameron case CCISS_SETNODENAME: 2150*edd16368SStephen M. Cameron case CCISS_GETHEARTBEAT: 2151*edd16368SStephen M. Cameron case CCISS_GETBUSTYPES: 2152*edd16368SStephen M. Cameron case CCISS_GETFIRMVER: 2153*edd16368SStephen M. Cameron case CCISS_GETDRIVVER: 2154*edd16368SStephen M. Cameron case CCISS_REVALIDVOLS: 2155*edd16368SStephen M. Cameron case CCISS_DEREGDISK: 2156*edd16368SStephen M. Cameron case CCISS_REGNEWDISK: 2157*edd16368SStephen M. Cameron case CCISS_REGNEWD: 2158*edd16368SStephen M. Cameron case CCISS_RESCANDISK: 2159*edd16368SStephen M. Cameron case CCISS_GETLUNINFO: 2160*edd16368SStephen M. Cameron return do_ioctl(dev, cmd, arg); 2161*edd16368SStephen M. Cameron 2162*edd16368SStephen M. Cameron case CCISS_PASSTHRU32: 2163*edd16368SStephen M. Cameron return hpsa_ioctl32_passthru(dev, cmd, arg); 2164*edd16368SStephen M. Cameron case CCISS_BIG_PASSTHRU32: 2165*edd16368SStephen M. Cameron return hpsa_ioctl32_big_passthru(dev, cmd, arg); 2166*edd16368SStephen M. Cameron 2167*edd16368SStephen M. Cameron default: 2168*edd16368SStephen M. Cameron return -ENOIOCTLCMD; 2169*edd16368SStephen M. Cameron } 2170*edd16368SStephen M. Cameron } 2171*edd16368SStephen M. Cameron 2172*edd16368SStephen M. Cameron static int hpsa_ioctl32_passthru(struct scsi_device *dev, int cmd, void *arg) 2173*edd16368SStephen M. Cameron { 2174*edd16368SStephen M. Cameron IOCTL32_Command_struct __user *arg32 = 2175*edd16368SStephen M. Cameron (IOCTL32_Command_struct __user *) arg; 2176*edd16368SStephen M. Cameron IOCTL_Command_struct arg64; 2177*edd16368SStephen M. Cameron IOCTL_Command_struct __user *p = compat_alloc_user_space(sizeof(arg64)); 2178*edd16368SStephen M. Cameron int err; 2179*edd16368SStephen M. Cameron u32 cp; 2180*edd16368SStephen M. Cameron 2181*edd16368SStephen M. Cameron err = 0; 2182*edd16368SStephen M. Cameron err |= copy_from_user(&arg64.LUN_info, &arg32->LUN_info, 2183*edd16368SStephen M. Cameron sizeof(arg64.LUN_info)); 2184*edd16368SStephen M. Cameron err |= copy_from_user(&arg64.Request, &arg32->Request, 2185*edd16368SStephen M. Cameron sizeof(arg64.Request)); 2186*edd16368SStephen M. Cameron err |= copy_from_user(&arg64.error_info, &arg32->error_info, 2187*edd16368SStephen M. Cameron sizeof(arg64.error_info)); 2188*edd16368SStephen M. Cameron err |= get_user(arg64.buf_size, &arg32->buf_size); 2189*edd16368SStephen M. Cameron err |= get_user(cp, &arg32->buf); 2190*edd16368SStephen M. Cameron arg64.buf = compat_ptr(cp); 2191*edd16368SStephen M. Cameron err |= copy_to_user(p, &arg64, sizeof(arg64)); 2192*edd16368SStephen M. Cameron 2193*edd16368SStephen M. Cameron if (err) 2194*edd16368SStephen M. Cameron return -EFAULT; 2195*edd16368SStephen M. Cameron 2196*edd16368SStephen M. Cameron err = do_ioctl(dev, CCISS_PASSTHRU, (void *)p); 2197*edd16368SStephen M. Cameron if (err) 2198*edd16368SStephen M. Cameron return err; 2199*edd16368SStephen M. Cameron err |= copy_in_user(&arg32->error_info, &p->error_info, 2200*edd16368SStephen M. Cameron sizeof(arg32->error_info)); 2201*edd16368SStephen M. Cameron if (err) 2202*edd16368SStephen M. Cameron return -EFAULT; 2203*edd16368SStephen M. Cameron return err; 2204*edd16368SStephen M. Cameron } 2205*edd16368SStephen M. Cameron 2206*edd16368SStephen M. Cameron static int hpsa_ioctl32_big_passthru(struct scsi_device *dev, 2207*edd16368SStephen M. Cameron int cmd, void *arg) 2208*edd16368SStephen M. Cameron { 2209*edd16368SStephen M. Cameron BIG_IOCTL32_Command_struct __user *arg32 = 2210*edd16368SStephen M. Cameron (BIG_IOCTL32_Command_struct __user *) arg; 2211*edd16368SStephen M. Cameron BIG_IOCTL_Command_struct arg64; 2212*edd16368SStephen M. Cameron BIG_IOCTL_Command_struct __user *p = 2213*edd16368SStephen M. Cameron compat_alloc_user_space(sizeof(arg64)); 2214*edd16368SStephen M. Cameron int err; 2215*edd16368SStephen M. Cameron u32 cp; 2216*edd16368SStephen M. Cameron 2217*edd16368SStephen M. Cameron err = 0; 2218*edd16368SStephen M. Cameron err |= copy_from_user(&arg64.LUN_info, &arg32->LUN_info, 2219*edd16368SStephen M. Cameron sizeof(arg64.LUN_info)); 2220*edd16368SStephen M. Cameron err |= copy_from_user(&arg64.Request, &arg32->Request, 2221*edd16368SStephen M. Cameron sizeof(arg64.Request)); 2222*edd16368SStephen M. Cameron err |= copy_from_user(&arg64.error_info, &arg32->error_info, 2223*edd16368SStephen M. Cameron sizeof(arg64.error_info)); 2224*edd16368SStephen M. Cameron err |= get_user(arg64.buf_size, &arg32->buf_size); 2225*edd16368SStephen M. Cameron err |= get_user(arg64.malloc_size, &arg32->malloc_size); 2226*edd16368SStephen M. Cameron err |= get_user(cp, &arg32->buf); 2227*edd16368SStephen M. Cameron arg64.buf = compat_ptr(cp); 2228*edd16368SStephen M. Cameron err |= copy_to_user(p, &arg64, sizeof(arg64)); 2229*edd16368SStephen M. Cameron 2230*edd16368SStephen M. Cameron if (err) 2231*edd16368SStephen M. Cameron return -EFAULT; 2232*edd16368SStephen M. Cameron 2233*edd16368SStephen M. Cameron err = do_ioctl(dev, CCISS_BIG_PASSTHRU, (void *)p); 2234*edd16368SStephen M. Cameron if (err) 2235*edd16368SStephen M. Cameron return err; 2236*edd16368SStephen M. Cameron err |= copy_in_user(&arg32->error_info, &p->error_info, 2237*edd16368SStephen M. Cameron sizeof(arg32->error_info)); 2238*edd16368SStephen M. Cameron if (err) 2239*edd16368SStephen M. Cameron return -EFAULT; 2240*edd16368SStephen M. Cameron return err; 2241*edd16368SStephen M. Cameron } 2242*edd16368SStephen M. Cameron #endif 2243*edd16368SStephen M. Cameron 2244*edd16368SStephen M. Cameron static int hpsa_getpciinfo_ioctl(struct ctlr_info *h, void __user *argp) 2245*edd16368SStephen M. Cameron { 2246*edd16368SStephen M. Cameron struct hpsa_pci_info pciinfo; 2247*edd16368SStephen M. Cameron 2248*edd16368SStephen M. Cameron if (!argp) 2249*edd16368SStephen M. Cameron return -EINVAL; 2250*edd16368SStephen M. Cameron pciinfo.domain = pci_domain_nr(h->pdev->bus); 2251*edd16368SStephen M. Cameron pciinfo.bus = h->pdev->bus->number; 2252*edd16368SStephen M. Cameron pciinfo.dev_fn = h->pdev->devfn; 2253*edd16368SStephen M. Cameron pciinfo.board_id = h->board_id; 2254*edd16368SStephen M. Cameron if (copy_to_user(argp, &pciinfo, sizeof(pciinfo))) 2255*edd16368SStephen M. Cameron return -EFAULT; 2256*edd16368SStephen M. Cameron return 0; 2257*edd16368SStephen M. Cameron } 2258*edd16368SStephen M. Cameron 2259*edd16368SStephen M. Cameron static int hpsa_getdrivver_ioctl(struct ctlr_info *h, void __user *argp) 2260*edd16368SStephen M. Cameron { 2261*edd16368SStephen M. Cameron DriverVer_type DriverVer; 2262*edd16368SStephen M. Cameron unsigned char vmaj, vmin, vsubmin; 2263*edd16368SStephen M. Cameron int rc; 2264*edd16368SStephen M. Cameron 2265*edd16368SStephen M. Cameron rc = sscanf(HPSA_DRIVER_VERSION, "%hhu.%hhu.%hhu", 2266*edd16368SStephen M. Cameron &vmaj, &vmin, &vsubmin); 2267*edd16368SStephen M. Cameron if (rc != 3) { 2268*edd16368SStephen M. Cameron dev_info(&h->pdev->dev, "driver version string '%s' " 2269*edd16368SStephen M. Cameron "unrecognized.", HPSA_DRIVER_VERSION); 2270*edd16368SStephen M. Cameron vmaj = 0; 2271*edd16368SStephen M. Cameron vmin = 0; 2272*edd16368SStephen M. Cameron vsubmin = 0; 2273*edd16368SStephen M. Cameron } 2274*edd16368SStephen M. Cameron DriverVer = (vmaj << 16) | (vmin << 8) | vsubmin; 2275*edd16368SStephen M. Cameron if (!argp) 2276*edd16368SStephen M. Cameron return -EINVAL; 2277*edd16368SStephen M. Cameron if (copy_to_user(argp, &DriverVer, sizeof(DriverVer_type))) 2278*edd16368SStephen M. Cameron return -EFAULT; 2279*edd16368SStephen M. Cameron return 0; 2280*edd16368SStephen M. Cameron } 2281*edd16368SStephen M. Cameron 2282*edd16368SStephen M. Cameron static int hpsa_passthru_ioctl(struct ctlr_info *h, void __user *argp) 2283*edd16368SStephen M. Cameron { 2284*edd16368SStephen M. Cameron IOCTL_Command_struct iocommand; 2285*edd16368SStephen M. Cameron struct CommandList *c; 2286*edd16368SStephen M. Cameron char *buff = NULL; 2287*edd16368SStephen M. Cameron union u64bit temp64; 2288*edd16368SStephen M. Cameron 2289*edd16368SStephen M. Cameron if (!argp) 2290*edd16368SStephen M. Cameron return -EINVAL; 2291*edd16368SStephen M. Cameron if (!capable(CAP_SYS_RAWIO)) 2292*edd16368SStephen M. Cameron return -EPERM; 2293*edd16368SStephen M. Cameron if (copy_from_user(&iocommand, argp, sizeof(iocommand))) 2294*edd16368SStephen M. Cameron return -EFAULT; 2295*edd16368SStephen M. Cameron if ((iocommand.buf_size < 1) && 2296*edd16368SStephen M. Cameron (iocommand.Request.Type.Direction != XFER_NONE)) { 2297*edd16368SStephen M. Cameron return -EINVAL; 2298*edd16368SStephen M. Cameron } 2299*edd16368SStephen M. Cameron if (iocommand.buf_size > 0) { 2300*edd16368SStephen M. Cameron buff = kmalloc(iocommand.buf_size, GFP_KERNEL); 2301*edd16368SStephen M. Cameron if (buff == NULL) 2302*edd16368SStephen M. Cameron return -EFAULT; 2303*edd16368SStephen M. Cameron } 2304*edd16368SStephen M. Cameron if (iocommand.Request.Type.Direction == XFER_WRITE) { 2305*edd16368SStephen M. Cameron /* Copy the data into the buffer we created */ 2306*edd16368SStephen M. Cameron if (copy_from_user(buff, iocommand.buf, iocommand.buf_size)) { 2307*edd16368SStephen M. Cameron kfree(buff); 2308*edd16368SStephen M. Cameron return -EFAULT; 2309*edd16368SStephen M. Cameron } 2310*edd16368SStephen M. Cameron } else 2311*edd16368SStephen M. Cameron memset(buff, 0, iocommand.buf_size); 2312*edd16368SStephen M. Cameron c = cmd_special_alloc(h); 2313*edd16368SStephen M. Cameron if (c == NULL) { 2314*edd16368SStephen M. Cameron kfree(buff); 2315*edd16368SStephen M. Cameron return -ENOMEM; 2316*edd16368SStephen M. Cameron } 2317*edd16368SStephen M. Cameron /* Fill in the command type */ 2318*edd16368SStephen M. Cameron c->cmd_type = CMD_IOCTL_PEND; 2319*edd16368SStephen M. Cameron /* Fill in Command Header */ 2320*edd16368SStephen M. Cameron c->Header.ReplyQueue = 0; /* unused in simple mode */ 2321*edd16368SStephen M. Cameron if (iocommand.buf_size > 0) { /* buffer to fill */ 2322*edd16368SStephen M. Cameron c->Header.SGList = 1; 2323*edd16368SStephen M. Cameron c->Header.SGTotal = 1; 2324*edd16368SStephen M. Cameron } else { /* no buffers to fill */ 2325*edd16368SStephen M. Cameron c->Header.SGList = 0; 2326*edd16368SStephen M. Cameron c->Header.SGTotal = 0; 2327*edd16368SStephen M. Cameron } 2328*edd16368SStephen M. Cameron memcpy(&c->Header.LUN, &iocommand.LUN_info, sizeof(c->Header.LUN)); 2329*edd16368SStephen M. Cameron /* use the kernel address the cmd block for tag */ 2330*edd16368SStephen M. Cameron c->Header.Tag.lower = c->busaddr; 2331*edd16368SStephen M. Cameron 2332*edd16368SStephen M. Cameron /* Fill in Request block */ 2333*edd16368SStephen M. Cameron memcpy(&c->Request, &iocommand.Request, 2334*edd16368SStephen M. Cameron sizeof(c->Request)); 2335*edd16368SStephen M. Cameron 2336*edd16368SStephen M. Cameron /* Fill in the scatter gather information */ 2337*edd16368SStephen M. Cameron if (iocommand.buf_size > 0) { 2338*edd16368SStephen M. Cameron temp64.val = pci_map_single(h->pdev, buff, 2339*edd16368SStephen M. Cameron iocommand.buf_size, PCI_DMA_BIDIRECTIONAL); 2340*edd16368SStephen M. Cameron c->SG[0].Addr.lower = temp64.val32.lower; 2341*edd16368SStephen M. Cameron c->SG[0].Addr.upper = temp64.val32.upper; 2342*edd16368SStephen M. Cameron c->SG[0].Len = iocommand.buf_size; 2343*edd16368SStephen M. Cameron c->SG[0].Ext = 0; /* we are not chaining*/ 2344*edd16368SStephen M. Cameron } 2345*edd16368SStephen M. Cameron hpsa_scsi_do_simple_cmd_core(h, c); 2346*edd16368SStephen M. Cameron hpsa_pci_unmap(h->pdev, c, 1, PCI_DMA_BIDIRECTIONAL); 2347*edd16368SStephen M. Cameron check_ioctl_unit_attention(h, c); 2348*edd16368SStephen M. Cameron 2349*edd16368SStephen M. Cameron /* Copy the error information out */ 2350*edd16368SStephen M. Cameron memcpy(&iocommand.error_info, c->err_info, 2351*edd16368SStephen M. Cameron sizeof(iocommand.error_info)); 2352*edd16368SStephen M. Cameron if (copy_to_user(argp, &iocommand, sizeof(iocommand))) { 2353*edd16368SStephen M. Cameron kfree(buff); 2354*edd16368SStephen M. Cameron cmd_special_free(h, c); 2355*edd16368SStephen M. Cameron return -EFAULT; 2356*edd16368SStephen M. Cameron } 2357*edd16368SStephen M. Cameron 2358*edd16368SStephen M. Cameron if (iocommand.Request.Type.Direction == XFER_READ) { 2359*edd16368SStephen M. Cameron /* Copy the data out of the buffer we created */ 2360*edd16368SStephen M. Cameron if (copy_to_user(iocommand.buf, buff, iocommand.buf_size)) { 2361*edd16368SStephen M. Cameron kfree(buff); 2362*edd16368SStephen M. Cameron cmd_special_free(h, c); 2363*edd16368SStephen M. Cameron return -EFAULT; 2364*edd16368SStephen M. Cameron } 2365*edd16368SStephen M. Cameron } 2366*edd16368SStephen M. Cameron kfree(buff); 2367*edd16368SStephen M. Cameron cmd_special_free(h, c); 2368*edd16368SStephen M. Cameron return 0; 2369*edd16368SStephen M. Cameron } 2370*edd16368SStephen M. Cameron 2371*edd16368SStephen M. Cameron static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp) 2372*edd16368SStephen M. Cameron { 2373*edd16368SStephen M. Cameron BIG_IOCTL_Command_struct *ioc; 2374*edd16368SStephen M. Cameron struct CommandList *c; 2375*edd16368SStephen M. Cameron unsigned char **buff = NULL; 2376*edd16368SStephen M. Cameron int *buff_size = NULL; 2377*edd16368SStephen M. Cameron union u64bit temp64; 2378*edd16368SStephen M. Cameron BYTE sg_used = 0; 2379*edd16368SStephen M. Cameron int status = 0; 2380*edd16368SStephen M. Cameron int i; 2381*edd16368SStephen M. Cameron __u32 left; 2382*edd16368SStephen M. Cameron __u32 sz; 2383*edd16368SStephen M. Cameron BYTE __user *data_ptr; 2384*edd16368SStephen M. Cameron 2385*edd16368SStephen M. Cameron if (!argp) 2386*edd16368SStephen M. Cameron return -EINVAL; 2387*edd16368SStephen M. Cameron if (!capable(CAP_SYS_RAWIO)) 2388*edd16368SStephen M. Cameron return -EPERM; 2389*edd16368SStephen M. Cameron ioc = (BIG_IOCTL_Command_struct *) 2390*edd16368SStephen M. Cameron kmalloc(sizeof(*ioc), GFP_KERNEL); 2391*edd16368SStephen M. Cameron if (!ioc) { 2392*edd16368SStephen M. Cameron status = -ENOMEM; 2393*edd16368SStephen M. Cameron goto cleanup1; 2394*edd16368SStephen M. Cameron } 2395*edd16368SStephen M. Cameron if (copy_from_user(ioc, argp, sizeof(*ioc))) { 2396*edd16368SStephen M. Cameron status = -EFAULT; 2397*edd16368SStephen M. Cameron goto cleanup1; 2398*edd16368SStephen M. Cameron } 2399*edd16368SStephen M. Cameron if ((ioc->buf_size < 1) && 2400*edd16368SStephen M. Cameron (ioc->Request.Type.Direction != XFER_NONE)) { 2401*edd16368SStephen M. Cameron status = -EINVAL; 2402*edd16368SStephen M. Cameron goto cleanup1; 2403*edd16368SStephen M. Cameron } 2404*edd16368SStephen M. Cameron /* Check kmalloc limits using all SGs */ 2405*edd16368SStephen M. Cameron if (ioc->malloc_size > MAX_KMALLOC_SIZE) { 2406*edd16368SStephen M. Cameron status = -EINVAL; 2407*edd16368SStephen M. Cameron goto cleanup1; 2408*edd16368SStephen M. Cameron } 2409*edd16368SStephen M. Cameron if (ioc->buf_size > ioc->malloc_size * MAXSGENTRIES) { 2410*edd16368SStephen M. Cameron status = -EINVAL; 2411*edd16368SStephen M. Cameron goto cleanup1; 2412*edd16368SStephen M. Cameron } 2413*edd16368SStephen M. Cameron buff = kzalloc(MAXSGENTRIES * sizeof(char *), GFP_KERNEL); 2414*edd16368SStephen M. Cameron if (!buff) { 2415*edd16368SStephen M. Cameron status = -ENOMEM; 2416*edd16368SStephen M. Cameron goto cleanup1; 2417*edd16368SStephen M. Cameron } 2418*edd16368SStephen M. Cameron buff_size = kmalloc(MAXSGENTRIES * sizeof(int), GFP_KERNEL); 2419*edd16368SStephen M. Cameron if (!buff_size) { 2420*edd16368SStephen M. Cameron status = -ENOMEM; 2421*edd16368SStephen M. Cameron goto cleanup1; 2422*edd16368SStephen M. Cameron } 2423*edd16368SStephen M. Cameron left = ioc->buf_size; 2424*edd16368SStephen M. Cameron data_ptr = ioc->buf; 2425*edd16368SStephen M. Cameron while (left) { 2426*edd16368SStephen M. Cameron sz = (left > ioc->malloc_size) ? ioc->malloc_size : left; 2427*edd16368SStephen M. Cameron buff_size[sg_used] = sz; 2428*edd16368SStephen M. Cameron buff[sg_used] = kmalloc(sz, GFP_KERNEL); 2429*edd16368SStephen M. Cameron if (buff[sg_used] == NULL) { 2430*edd16368SStephen M. Cameron status = -ENOMEM; 2431*edd16368SStephen M. Cameron goto cleanup1; 2432*edd16368SStephen M. Cameron } 2433*edd16368SStephen M. Cameron if (ioc->Request.Type.Direction == XFER_WRITE) { 2434*edd16368SStephen M. Cameron if (copy_from_user(buff[sg_used], data_ptr, sz)) { 2435*edd16368SStephen M. Cameron status = -ENOMEM; 2436*edd16368SStephen M. Cameron goto cleanup1; 2437*edd16368SStephen M. Cameron } 2438*edd16368SStephen M. Cameron } else 2439*edd16368SStephen M. Cameron memset(buff[sg_used], 0, sz); 2440*edd16368SStephen M. Cameron left -= sz; 2441*edd16368SStephen M. Cameron data_ptr += sz; 2442*edd16368SStephen M. Cameron sg_used++; 2443*edd16368SStephen M. Cameron } 2444*edd16368SStephen M. Cameron c = cmd_special_alloc(h); 2445*edd16368SStephen M. Cameron if (c == NULL) { 2446*edd16368SStephen M. Cameron status = -ENOMEM; 2447*edd16368SStephen M. Cameron goto cleanup1; 2448*edd16368SStephen M. Cameron } 2449*edd16368SStephen M. Cameron c->cmd_type = CMD_IOCTL_PEND; 2450*edd16368SStephen M. Cameron c->Header.ReplyQueue = 0; 2451*edd16368SStephen M. Cameron 2452*edd16368SStephen M. Cameron if (ioc->buf_size > 0) { 2453*edd16368SStephen M. Cameron c->Header.SGList = sg_used; 2454*edd16368SStephen M. Cameron c->Header.SGTotal = sg_used; 2455*edd16368SStephen M. Cameron } else { 2456*edd16368SStephen M. Cameron c->Header.SGList = 0; 2457*edd16368SStephen M. Cameron c->Header.SGTotal = 0; 2458*edd16368SStephen M. Cameron } 2459*edd16368SStephen M. Cameron memcpy(&c->Header.LUN, &ioc->LUN_info, sizeof(c->Header.LUN)); 2460*edd16368SStephen M. Cameron c->Header.Tag.lower = c->busaddr; 2461*edd16368SStephen M. Cameron memcpy(&c->Request, &ioc->Request, sizeof(c->Request)); 2462*edd16368SStephen M. Cameron if (ioc->buf_size > 0) { 2463*edd16368SStephen M. Cameron int i; 2464*edd16368SStephen M. Cameron for (i = 0; i < sg_used; i++) { 2465*edd16368SStephen M. Cameron temp64.val = pci_map_single(h->pdev, buff[i], 2466*edd16368SStephen M. Cameron buff_size[i], PCI_DMA_BIDIRECTIONAL); 2467*edd16368SStephen M. Cameron c->SG[i].Addr.lower = temp64.val32.lower; 2468*edd16368SStephen M. Cameron c->SG[i].Addr.upper = temp64.val32.upper; 2469*edd16368SStephen M. Cameron c->SG[i].Len = buff_size[i]; 2470*edd16368SStephen M. Cameron /* we are not chaining */ 2471*edd16368SStephen M. Cameron c->SG[i].Ext = 0; 2472*edd16368SStephen M. Cameron } 2473*edd16368SStephen M. Cameron } 2474*edd16368SStephen M. Cameron hpsa_scsi_do_simple_cmd_core(h, c); 2475*edd16368SStephen M. Cameron hpsa_pci_unmap(h->pdev, c, sg_used, PCI_DMA_BIDIRECTIONAL); 2476*edd16368SStephen M. Cameron check_ioctl_unit_attention(h, c); 2477*edd16368SStephen M. Cameron /* Copy the error information out */ 2478*edd16368SStephen M. Cameron memcpy(&ioc->error_info, c->err_info, sizeof(ioc->error_info)); 2479*edd16368SStephen M. Cameron if (copy_to_user(argp, ioc, sizeof(*ioc))) { 2480*edd16368SStephen M. Cameron cmd_special_free(h, c); 2481*edd16368SStephen M. Cameron status = -EFAULT; 2482*edd16368SStephen M. Cameron goto cleanup1; 2483*edd16368SStephen M. Cameron } 2484*edd16368SStephen M. Cameron if (ioc->Request.Type.Direction == XFER_READ) { 2485*edd16368SStephen M. Cameron /* Copy the data out of the buffer we created */ 2486*edd16368SStephen M. Cameron BYTE __user *ptr = ioc->buf; 2487*edd16368SStephen M. Cameron for (i = 0; i < sg_used; i++) { 2488*edd16368SStephen M. Cameron if (copy_to_user(ptr, buff[i], buff_size[i])) { 2489*edd16368SStephen M. Cameron cmd_special_free(h, c); 2490*edd16368SStephen M. Cameron status = -EFAULT; 2491*edd16368SStephen M. Cameron goto cleanup1; 2492*edd16368SStephen M. Cameron } 2493*edd16368SStephen M. Cameron ptr += buff_size[i]; 2494*edd16368SStephen M. Cameron } 2495*edd16368SStephen M. Cameron } 2496*edd16368SStephen M. Cameron cmd_special_free(h, c); 2497*edd16368SStephen M. Cameron status = 0; 2498*edd16368SStephen M. Cameron cleanup1: 2499*edd16368SStephen M. Cameron if (buff) { 2500*edd16368SStephen M. Cameron for (i = 0; i < sg_used; i++) 2501*edd16368SStephen M. Cameron kfree(buff[i]); 2502*edd16368SStephen M. Cameron kfree(buff); 2503*edd16368SStephen M. Cameron } 2504*edd16368SStephen M. Cameron kfree(buff_size); 2505*edd16368SStephen M. Cameron kfree(ioc); 2506*edd16368SStephen M. Cameron return status; 2507*edd16368SStephen M. Cameron } 2508*edd16368SStephen M. Cameron 2509*edd16368SStephen M. Cameron static void check_ioctl_unit_attention(struct ctlr_info *h, 2510*edd16368SStephen M. Cameron struct CommandList *c) 2511*edd16368SStephen M. Cameron { 2512*edd16368SStephen M. Cameron if (c->err_info->CommandStatus == CMD_TARGET_STATUS && 2513*edd16368SStephen M. Cameron c->err_info->ScsiStatus != SAM_STAT_CHECK_CONDITION) 2514*edd16368SStephen M. Cameron (void) check_for_unit_attention(h, c); 2515*edd16368SStephen M. Cameron } 2516*edd16368SStephen M. Cameron /* 2517*edd16368SStephen M. Cameron * ioctl 2518*edd16368SStephen M. Cameron */ 2519*edd16368SStephen M. Cameron static int hpsa_ioctl(struct scsi_device *dev, int cmd, void *arg) 2520*edd16368SStephen M. Cameron { 2521*edd16368SStephen M. Cameron struct ctlr_info *h; 2522*edd16368SStephen M. Cameron void __user *argp = (void __user *)arg; 2523*edd16368SStephen M. Cameron 2524*edd16368SStephen M. Cameron h = sdev_to_hba(dev); 2525*edd16368SStephen M. Cameron 2526*edd16368SStephen M. Cameron switch (cmd) { 2527*edd16368SStephen M. Cameron case CCISS_DEREGDISK: 2528*edd16368SStephen M. Cameron case CCISS_REGNEWDISK: 2529*edd16368SStephen M. Cameron case CCISS_REGNEWD: 2530*edd16368SStephen M. Cameron hpsa_update_scsi_devices(h, dev->host->host_no); 2531*edd16368SStephen M. Cameron return 0; 2532*edd16368SStephen M. Cameron case CCISS_GETPCIINFO: 2533*edd16368SStephen M. Cameron return hpsa_getpciinfo_ioctl(h, argp); 2534*edd16368SStephen M. Cameron case CCISS_GETDRIVVER: 2535*edd16368SStephen M. Cameron return hpsa_getdrivver_ioctl(h, argp); 2536*edd16368SStephen M. Cameron case CCISS_PASSTHRU: 2537*edd16368SStephen M. Cameron return hpsa_passthru_ioctl(h, argp); 2538*edd16368SStephen M. Cameron case CCISS_BIG_PASSTHRU: 2539*edd16368SStephen M. Cameron return hpsa_big_passthru_ioctl(h, argp); 2540*edd16368SStephen M. Cameron default: 2541*edd16368SStephen M. Cameron return -ENOTTY; 2542*edd16368SStephen M. Cameron } 2543*edd16368SStephen M. Cameron } 2544*edd16368SStephen M. Cameron 2545*edd16368SStephen M. Cameron static void fill_cmd(struct CommandList *c, __u8 cmd, struct ctlr_info *h, 2546*edd16368SStephen M. Cameron void *buff, size_t size, __u8 page_code, unsigned char *scsi3addr, 2547*edd16368SStephen M. Cameron int cmd_type) 2548*edd16368SStephen M. Cameron { 2549*edd16368SStephen M. Cameron int pci_dir = XFER_NONE; 2550*edd16368SStephen M. Cameron 2551*edd16368SStephen M. Cameron c->cmd_type = CMD_IOCTL_PEND; 2552*edd16368SStephen M. Cameron c->Header.ReplyQueue = 0; 2553*edd16368SStephen M. Cameron if (buff != NULL && size > 0) { 2554*edd16368SStephen M. Cameron c->Header.SGList = 1; 2555*edd16368SStephen M. Cameron c->Header.SGTotal = 1; 2556*edd16368SStephen M. Cameron } else { 2557*edd16368SStephen M. Cameron c->Header.SGList = 0; 2558*edd16368SStephen M. Cameron c->Header.SGTotal = 0; 2559*edd16368SStephen M. Cameron } 2560*edd16368SStephen M. Cameron c->Header.Tag.lower = c->busaddr; 2561*edd16368SStephen M. Cameron memcpy(c->Header.LUN.LunAddrBytes, scsi3addr, 8); 2562*edd16368SStephen M. Cameron 2563*edd16368SStephen M. Cameron c->Request.Type.Type = cmd_type; 2564*edd16368SStephen M. Cameron if (cmd_type == TYPE_CMD) { 2565*edd16368SStephen M. Cameron switch (cmd) { 2566*edd16368SStephen M. Cameron case HPSA_INQUIRY: 2567*edd16368SStephen M. Cameron /* are we trying to read a vital product page */ 2568*edd16368SStephen M. Cameron if (page_code != 0) { 2569*edd16368SStephen M. Cameron c->Request.CDB[1] = 0x01; 2570*edd16368SStephen M. Cameron c->Request.CDB[2] = page_code; 2571*edd16368SStephen M. Cameron } 2572*edd16368SStephen M. Cameron c->Request.CDBLen = 6; 2573*edd16368SStephen M. Cameron c->Request.Type.Attribute = ATTR_SIMPLE; 2574*edd16368SStephen M. Cameron c->Request.Type.Direction = XFER_READ; 2575*edd16368SStephen M. Cameron c->Request.Timeout = 0; 2576*edd16368SStephen M. Cameron c->Request.CDB[0] = HPSA_INQUIRY; 2577*edd16368SStephen M. Cameron c->Request.CDB[4] = size & 0xFF; 2578*edd16368SStephen M. Cameron break; 2579*edd16368SStephen M. Cameron case HPSA_REPORT_LOG: 2580*edd16368SStephen M. Cameron case HPSA_REPORT_PHYS: 2581*edd16368SStephen M. Cameron /* Talking to controller so It's a physical command 2582*edd16368SStephen M. Cameron mode = 00 target = 0. Nothing to write. 2583*edd16368SStephen M. Cameron */ 2584*edd16368SStephen M. Cameron c->Request.CDBLen = 12; 2585*edd16368SStephen M. Cameron c->Request.Type.Attribute = ATTR_SIMPLE; 2586*edd16368SStephen M. Cameron c->Request.Type.Direction = XFER_READ; 2587*edd16368SStephen M. Cameron c->Request.Timeout = 0; 2588*edd16368SStephen M. Cameron c->Request.CDB[0] = cmd; 2589*edd16368SStephen M. Cameron c->Request.CDB[6] = (size >> 24) & 0xFF; /* MSB */ 2590*edd16368SStephen M. Cameron c->Request.CDB[7] = (size >> 16) & 0xFF; 2591*edd16368SStephen M. Cameron c->Request.CDB[8] = (size >> 8) & 0xFF; 2592*edd16368SStephen M. Cameron c->Request.CDB[9] = size & 0xFF; 2593*edd16368SStephen M. Cameron break; 2594*edd16368SStephen M. Cameron 2595*edd16368SStephen M. Cameron case HPSA_READ_CAPACITY: 2596*edd16368SStephen M. Cameron c->Request.CDBLen = 10; 2597*edd16368SStephen M. Cameron c->Request.Type.Attribute = ATTR_SIMPLE; 2598*edd16368SStephen M. Cameron c->Request.Type.Direction = XFER_READ; 2599*edd16368SStephen M. Cameron c->Request.Timeout = 0; 2600*edd16368SStephen M. Cameron c->Request.CDB[0] = cmd; 2601*edd16368SStephen M. Cameron break; 2602*edd16368SStephen M. Cameron case HPSA_CACHE_FLUSH: 2603*edd16368SStephen M. Cameron c->Request.CDBLen = 12; 2604*edd16368SStephen M. Cameron c->Request.Type.Attribute = ATTR_SIMPLE; 2605*edd16368SStephen M. Cameron c->Request.Type.Direction = XFER_WRITE; 2606*edd16368SStephen M. Cameron c->Request.Timeout = 0; 2607*edd16368SStephen M. Cameron c->Request.CDB[0] = BMIC_WRITE; 2608*edd16368SStephen M. Cameron c->Request.CDB[6] = BMIC_CACHE_FLUSH; 2609*edd16368SStephen M. Cameron break; 2610*edd16368SStephen M. Cameron case TEST_UNIT_READY: 2611*edd16368SStephen M. Cameron c->Request.CDBLen = 6; 2612*edd16368SStephen M. Cameron c->Request.Type.Attribute = ATTR_SIMPLE; 2613*edd16368SStephen M. Cameron c->Request.Type.Direction = XFER_NONE; 2614*edd16368SStephen M. Cameron c->Request.Timeout = 0; 2615*edd16368SStephen M. Cameron break; 2616*edd16368SStephen M. Cameron default: 2617*edd16368SStephen M. Cameron dev_warn(&h->pdev->dev, "unknown command 0x%c\n", cmd); 2618*edd16368SStephen M. Cameron BUG(); 2619*edd16368SStephen M. Cameron return; 2620*edd16368SStephen M. Cameron } 2621*edd16368SStephen M. Cameron } else if (cmd_type == TYPE_MSG) { 2622*edd16368SStephen M. Cameron switch (cmd) { 2623*edd16368SStephen M. Cameron 2624*edd16368SStephen M. Cameron case HPSA_DEVICE_RESET_MSG: 2625*edd16368SStephen M. Cameron c->Request.CDBLen = 16; 2626*edd16368SStephen M. Cameron c->Request.Type.Type = 1; /* It is a MSG not a CMD */ 2627*edd16368SStephen M. Cameron c->Request.Type.Attribute = ATTR_SIMPLE; 2628*edd16368SStephen M. Cameron c->Request.Type.Direction = XFER_NONE; 2629*edd16368SStephen M. Cameron c->Request.Timeout = 0; /* Don't time out */ 2630*edd16368SStephen M. Cameron c->Request.CDB[0] = 0x01; /* RESET_MSG is 0x01 */ 2631*edd16368SStephen M. Cameron c->Request.CDB[1] = 0x03; /* Reset target above */ 2632*edd16368SStephen M. Cameron /* If bytes 4-7 are zero, it means reset the */ 2633*edd16368SStephen M. Cameron /* LunID device */ 2634*edd16368SStephen M. Cameron c->Request.CDB[4] = 0x00; 2635*edd16368SStephen M. Cameron c->Request.CDB[5] = 0x00; 2636*edd16368SStephen M. Cameron c->Request.CDB[6] = 0x00; 2637*edd16368SStephen M. Cameron c->Request.CDB[7] = 0x00; 2638*edd16368SStephen M. Cameron break; 2639*edd16368SStephen M. Cameron 2640*edd16368SStephen M. Cameron default: 2641*edd16368SStephen M. Cameron dev_warn(&h->pdev->dev, "unknown message type %d\n", 2642*edd16368SStephen M. Cameron cmd); 2643*edd16368SStephen M. Cameron BUG(); 2644*edd16368SStephen M. Cameron } 2645*edd16368SStephen M. Cameron } else { 2646*edd16368SStephen M. Cameron dev_warn(&h->pdev->dev, "unknown command type %d\n", cmd_type); 2647*edd16368SStephen M. Cameron BUG(); 2648*edd16368SStephen M. Cameron } 2649*edd16368SStephen M. Cameron 2650*edd16368SStephen M. Cameron switch (c->Request.Type.Direction) { 2651*edd16368SStephen M. Cameron case XFER_READ: 2652*edd16368SStephen M. Cameron pci_dir = PCI_DMA_FROMDEVICE; 2653*edd16368SStephen M. Cameron break; 2654*edd16368SStephen M. Cameron case XFER_WRITE: 2655*edd16368SStephen M. Cameron pci_dir = PCI_DMA_TODEVICE; 2656*edd16368SStephen M. Cameron break; 2657*edd16368SStephen M. Cameron case XFER_NONE: 2658*edd16368SStephen M. Cameron pci_dir = PCI_DMA_NONE; 2659*edd16368SStephen M. Cameron break; 2660*edd16368SStephen M. Cameron default: 2661*edd16368SStephen M. Cameron pci_dir = PCI_DMA_BIDIRECTIONAL; 2662*edd16368SStephen M. Cameron } 2663*edd16368SStephen M. Cameron 2664*edd16368SStephen M. Cameron hpsa_map_one(h->pdev, c, buff, size, pci_dir); 2665*edd16368SStephen M. Cameron 2666*edd16368SStephen M. Cameron return; 2667*edd16368SStephen M. Cameron } 2668*edd16368SStephen M. Cameron 2669*edd16368SStephen M. Cameron /* 2670*edd16368SStephen M. Cameron * Map (physical) PCI mem into (virtual) kernel space 2671*edd16368SStephen M. Cameron */ 2672*edd16368SStephen M. Cameron static void __iomem *remap_pci_mem(ulong base, ulong size) 2673*edd16368SStephen M. Cameron { 2674*edd16368SStephen M. Cameron ulong page_base = ((ulong) base) & PAGE_MASK; 2675*edd16368SStephen M. Cameron ulong page_offs = ((ulong) base) - page_base; 2676*edd16368SStephen M. Cameron void __iomem *page_remapped = ioremap(page_base, page_offs + size); 2677*edd16368SStephen M. Cameron 2678*edd16368SStephen M. Cameron return page_remapped ? (page_remapped + page_offs) : NULL; 2679*edd16368SStephen M. Cameron } 2680*edd16368SStephen M. Cameron 2681*edd16368SStephen M. Cameron /* Takes cmds off the submission queue and sends them to the hardware, 2682*edd16368SStephen M. Cameron * then puts them on the queue of cmds waiting for completion. 2683*edd16368SStephen M. Cameron */ 2684*edd16368SStephen M. Cameron static void start_io(struct ctlr_info *h) 2685*edd16368SStephen M. Cameron { 2686*edd16368SStephen M. Cameron struct CommandList *c; 2687*edd16368SStephen M. Cameron 2688*edd16368SStephen M. Cameron while (!hlist_empty(&h->reqQ)) { 2689*edd16368SStephen M. Cameron c = hlist_entry(h->reqQ.first, struct CommandList, list); 2690*edd16368SStephen M. Cameron /* can't do anything if fifo is full */ 2691*edd16368SStephen M. Cameron if ((h->access.fifo_full(h))) { 2692*edd16368SStephen M. Cameron dev_warn(&h->pdev->dev, "fifo full\n"); 2693*edd16368SStephen M. Cameron break; 2694*edd16368SStephen M. Cameron } 2695*edd16368SStephen M. Cameron 2696*edd16368SStephen M. Cameron /* Get the first entry from the Request Q */ 2697*edd16368SStephen M. Cameron removeQ(c); 2698*edd16368SStephen M. Cameron h->Qdepth--; 2699*edd16368SStephen M. Cameron 2700*edd16368SStephen M. Cameron /* Tell the controller execute command */ 2701*edd16368SStephen M. Cameron h->access.submit_command(h, c); 2702*edd16368SStephen M. Cameron 2703*edd16368SStephen M. Cameron /* Put job onto the completed Q */ 2704*edd16368SStephen M. Cameron addQ(&h->cmpQ, c); 2705*edd16368SStephen M. Cameron } 2706*edd16368SStephen M. Cameron } 2707*edd16368SStephen M. Cameron 2708*edd16368SStephen M. Cameron static inline unsigned long get_next_completion(struct ctlr_info *h) 2709*edd16368SStephen M. Cameron { 2710*edd16368SStephen M. Cameron return h->access.command_completed(h); 2711*edd16368SStephen M. Cameron } 2712*edd16368SStephen M. Cameron 2713*edd16368SStephen M. Cameron static inline int interrupt_pending(struct ctlr_info *h) 2714*edd16368SStephen M. Cameron { 2715*edd16368SStephen M. Cameron return h->access.intr_pending(h); 2716*edd16368SStephen M. Cameron } 2717*edd16368SStephen M. Cameron 2718*edd16368SStephen M. Cameron static inline long interrupt_not_for_us(struct ctlr_info *h) 2719*edd16368SStephen M. Cameron { 2720*edd16368SStephen M. Cameron return ((h->access.intr_pending(h) == 0) || 2721*edd16368SStephen M. Cameron (h->interrupts_enabled == 0)); 2722*edd16368SStephen M. Cameron } 2723*edd16368SStephen M. Cameron 2724*edd16368SStephen M. Cameron static inline int bad_tag(struct ctlr_info *h, __u32 tag_index, 2725*edd16368SStephen M. Cameron __u32 raw_tag) 2726*edd16368SStephen M. Cameron { 2727*edd16368SStephen M. Cameron if (unlikely(tag_index >= h->nr_cmds)) { 2728*edd16368SStephen M. Cameron dev_warn(&h->pdev->dev, "bad tag 0x%08x ignored.\n", raw_tag); 2729*edd16368SStephen M. Cameron return 1; 2730*edd16368SStephen M. Cameron } 2731*edd16368SStephen M. Cameron return 0; 2732*edd16368SStephen M. Cameron } 2733*edd16368SStephen M. Cameron 2734*edd16368SStephen M. Cameron static inline void finish_cmd(struct CommandList *c, __u32 raw_tag) 2735*edd16368SStephen M. Cameron { 2736*edd16368SStephen M. Cameron removeQ(c); 2737*edd16368SStephen M. Cameron if (likely(c->cmd_type == CMD_SCSI)) 2738*edd16368SStephen M. Cameron complete_scsi_command(c, 0, raw_tag); 2739*edd16368SStephen M. Cameron else if (c->cmd_type == CMD_IOCTL_PEND) 2740*edd16368SStephen M. Cameron complete(c->waiting); 2741*edd16368SStephen M. Cameron } 2742*edd16368SStephen M. Cameron 2743*edd16368SStephen M. Cameron static irqreturn_t do_hpsa_intr(int irq, void *dev_id) 2744*edd16368SStephen M. Cameron { 2745*edd16368SStephen M. Cameron struct ctlr_info *h = dev_id; 2746*edd16368SStephen M. Cameron struct CommandList *c; 2747*edd16368SStephen M. Cameron unsigned long flags; 2748*edd16368SStephen M. Cameron __u32 raw_tag, tag, tag_index; 2749*edd16368SStephen M. Cameron struct hlist_node *tmp; 2750*edd16368SStephen M. Cameron 2751*edd16368SStephen M. Cameron if (interrupt_not_for_us(h)) 2752*edd16368SStephen M. Cameron return IRQ_NONE; 2753*edd16368SStephen M. Cameron spin_lock_irqsave(&h->lock, flags); 2754*edd16368SStephen M. Cameron while (interrupt_pending(h)) { 2755*edd16368SStephen M. Cameron while ((raw_tag = get_next_completion(h)) != FIFO_EMPTY) { 2756*edd16368SStephen M. Cameron if (likely(HPSA_TAG_CONTAINS_INDEX(raw_tag))) { 2757*edd16368SStephen M. Cameron tag_index = HPSA_TAG_TO_INDEX(raw_tag); 2758*edd16368SStephen M. Cameron if (bad_tag(h, tag_index, raw_tag)) 2759*edd16368SStephen M. Cameron return IRQ_HANDLED; 2760*edd16368SStephen M. Cameron c = h->cmd_pool + tag_index; 2761*edd16368SStephen M. Cameron finish_cmd(c, raw_tag); 2762*edd16368SStephen M. Cameron continue; 2763*edd16368SStephen M. Cameron } 2764*edd16368SStephen M. Cameron tag = HPSA_TAG_DISCARD_ERROR_BITS(raw_tag); 2765*edd16368SStephen M. Cameron c = NULL; 2766*edd16368SStephen M. Cameron hlist_for_each_entry(c, tmp, &h->cmpQ, list) { 2767*edd16368SStephen M. Cameron if (c->busaddr == tag) { 2768*edd16368SStephen M. Cameron finish_cmd(c, raw_tag); 2769*edd16368SStephen M. Cameron break; 2770*edd16368SStephen M. Cameron } 2771*edd16368SStephen M. Cameron } 2772*edd16368SStephen M. Cameron } 2773*edd16368SStephen M. Cameron } 2774*edd16368SStephen M. Cameron spin_unlock_irqrestore(&h->lock, flags); 2775*edd16368SStephen M. Cameron return IRQ_HANDLED; 2776*edd16368SStephen M. Cameron } 2777*edd16368SStephen M. Cameron 2778*edd16368SStephen M. Cameron /* Send a message CDB to the firmware. */ 2779*edd16368SStephen M. Cameron static __devinit int hpsa_message(struct pci_dev *pdev, unsigned char opcode, 2780*edd16368SStephen M. Cameron unsigned char type) 2781*edd16368SStephen M. Cameron { 2782*edd16368SStephen M. Cameron struct Command { 2783*edd16368SStephen M. Cameron struct CommandListHeader CommandHeader; 2784*edd16368SStephen M. Cameron struct RequestBlock Request; 2785*edd16368SStephen M. Cameron struct ErrDescriptor ErrorDescriptor; 2786*edd16368SStephen M. Cameron }; 2787*edd16368SStephen M. Cameron struct Command *cmd; 2788*edd16368SStephen M. Cameron static const size_t cmd_sz = sizeof(*cmd) + 2789*edd16368SStephen M. Cameron sizeof(cmd->ErrorDescriptor); 2790*edd16368SStephen M. Cameron dma_addr_t paddr64; 2791*edd16368SStephen M. Cameron uint32_t paddr32, tag; 2792*edd16368SStephen M. Cameron void __iomem *vaddr; 2793*edd16368SStephen M. Cameron int i, err; 2794*edd16368SStephen M. Cameron 2795*edd16368SStephen M. Cameron vaddr = pci_ioremap_bar(pdev, 0); 2796*edd16368SStephen M. Cameron if (vaddr == NULL) 2797*edd16368SStephen M. Cameron return -ENOMEM; 2798*edd16368SStephen M. Cameron 2799*edd16368SStephen M. Cameron /* The Inbound Post Queue only accepts 32-bit physical addresses for the 2800*edd16368SStephen M. Cameron * CCISS commands, so they must be allocated from the lower 4GiB of 2801*edd16368SStephen M. Cameron * memory. 2802*edd16368SStephen M. Cameron */ 2803*edd16368SStephen M. Cameron err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); 2804*edd16368SStephen M. Cameron if (err) { 2805*edd16368SStephen M. Cameron iounmap(vaddr); 2806*edd16368SStephen M. Cameron return -ENOMEM; 2807*edd16368SStephen M. Cameron } 2808*edd16368SStephen M. Cameron 2809*edd16368SStephen M. Cameron cmd = pci_alloc_consistent(pdev, cmd_sz, &paddr64); 2810*edd16368SStephen M. Cameron if (cmd == NULL) { 2811*edd16368SStephen M. Cameron iounmap(vaddr); 2812*edd16368SStephen M. Cameron return -ENOMEM; 2813*edd16368SStephen M. Cameron } 2814*edd16368SStephen M. Cameron 2815*edd16368SStephen M. Cameron /* This must fit, because of the 32-bit consistent DMA mask. Also, 2816*edd16368SStephen M. Cameron * although there's no guarantee, we assume that the address is at 2817*edd16368SStephen M. Cameron * least 4-byte aligned (most likely, it's page-aligned). 2818*edd16368SStephen M. Cameron */ 2819*edd16368SStephen M. Cameron paddr32 = paddr64; 2820*edd16368SStephen M. Cameron 2821*edd16368SStephen M. Cameron cmd->CommandHeader.ReplyQueue = 0; 2822*edd16368SStephen M. Cameron cmd->CommandHeader.SGList = 0; 2823*edd16368SStephen M. Cameron cmd->CommandHeader.SGTotal = 0; 2824*edd16368SStephen M. Cameron cmd->CommandHeader.Tag.lower = paddr32; 2825*edd16368SStephen M. Cameron cmd->CommandHeader.Tag.upper = 0; 2826*edd16368SStephen M. Cameron memset(&cmd->CommandHeader.LUN.LunAddrBytes, 0, 8); 2827*edd16368SStephen M. Cameron 2828*edd16368SStephen M. Cameron cmd->Request.CDBLen = 16; 2829*edd16368SStephen M. Cameron cmd->Request.Type.Type = TYPE_MSG; 2830*edd16368SStephen M. Cameron cmd->Request.Type.Attribute = ATTR_HEADOFQUEUE; 2831*edd16368SStephen M. Cameron cmd->Request.Type.Direction = XFER_NONE; 2832*edd16368SStephen M. Cameron cmd->Request.Timeout = 0; /* Don't time out */ 2833*edd16368SStephen M. Cameron cmd->Request.CDB[0] = opcode; 2834*edd16368SStephen M. Cameron cmd->Request.CDB[1] = type; 2835*edd16368SStephen M. Cameron memset(&cmd->Request.CDB[2], 0, 14); /* rest of the CDB is reserved */ 2836*edd16368SStephen M. Cameron cmd->ErrorDescriptor.Addr.lower = paddr32 + sizeof(*cmd); 2837*edd16368SStephen M. Cameron cmd->ErrorDescriptor.Addr.upper = 0; 2838*edd16368SStephen M. Cameron cmd->ErrorDescriptor.Len = sizeof(struct ErrorInfo); 2839*edd16368SStephen M. Cameron 2840*edd16368SStephen M. Cameron writel(paddr32, vaddr + SA5_REQUEST_PORT_OFFSET); 2841*edd16368SStephen M. Cameron 2842*edd16368SStephen M. Cameron for (i = 0; i < HPSA_MSG_SEND_RETRY_LIMIT; i++) { 2843*edd16368SStephen M. Cameron tag = readl(vaddr + SA5_REPLY_PORT_OFFSET); 2844*edd16368SStephen M. Cameron if (HPSA_TAG_DISCARD_ERROR_BITS(tag) == paddr32) 2845*edd16368SStephen M. Cameron break; 2846*edd16368SStephen M. Cameron msleep(HPSA_MSG_SEND_RETRY_INTERVAL_MSECS); 2847*edd16368SStephen M. Cameron } 2848*edd16368SStephen M. Cameron 2849*edd16368SStephen M. Cameron iounmap(vaddr); 2850*edd16368SStephen M. Cameron 2851*edd16368SStephen M. Cameron /* we leak the DMA buffer here ... no choice since the controller could 2852*edd16368SStephen M. Cameron * still complete the command. 2853*edd16368SStephen M. Cameron */ 2854*edd16368SStephen M. Cameron if (i == HPSA_MSG_SEND_RETRY_LIMIT) { 2855*edd16368SStephen M. Cameron dev_err(&pdev->dev, "controller message %02x:%02x timed out\n", 2856*edd16368SStephen M. Cameron opcode, type); 2857*edd16368SStephen M. Cameron return -ETIMEDOUT; 2858*edd16368SStephen M. Cameron } 2859*edd16368SStephen M. Cameron 2860*edd16368SStephen M. Cameron pci_free_consistent(pdev, cmd_sz, cmd, paddr64); 2861*edd16368SStephen M. Cameron 2862*edd16368SStephen M. Cameron if (tag & HPSA_ERROR_BIT) { 2863*edd16368SStephen M. Cameron dev_err(&pdev->dev, "controller message %02x:%02x failed\n", 2864*edd16368SStephen M. Cameron opcode, type); 2865*edd16368SStephen M. Cameron return -EIO; 2866*edd16368SStephen M. Cameron } 2867*edd16368SStephen M. Cameron 2868*edd16368SStephen M. Cameron dev_info(&pdev->dev, "controller message %02x:%02x succeeded\n", 2869*edd16368SStephen M. Cameron opcode, type); 2870*edd16368SStephen M. Cameron return 0; 2871*edd16368SStephen M. Cameron } 2872*edd16368SStephen M. Cameron 2873*edd16368SStephen M. Cameron #define hpsa_soft_reset_controller(p) hpsa_message(p, 1, 0) 2874*edd16368SStephen M. Cameron #define hpsa_noop(p) hpsa_message(p, 3, 0) 2875*edd16368SStephen M. Cameron 2876*edd16368SStephen M. Cameron static __devinit int hpsa_reset_msi(struct pci_dev *pdev) 2877*edd16368SStephen M. Cameron { 2878*edd16368SStephen M. Cameron /* the #defines are stolen from drivers/pci/msi.h. */ 2879*edd16368SStephen M. Cameron #define msi_control_reg(base) (base + PCI_MSI_FLAGS) 2880*edd16368SStephen M. Cameron #define PCI_MSIX_FLAGS_ENABLE (1 << 15) 2881*edd16368SStephen M. Cameron 2882*edd16368SStephen M. Cameron int pos; 2883*edd16368SStephen M. Cameron u16 control = 0; 2884*edd16368SStephen M. Cameron 2885*edd16368SStephen M. Cameron pos = pci_find_capability(pdev, PCI_CAP_ID_MSI); 2886*edd16368SStephen M. Cameron if (pos) { 2887*edd16368SStephen M. Cameron pci_read_config_word(pdev, msi_control_reg(pos), &control); 2888*edd16368SStephen M. Cameron if (control & PCI_MSI_FLAGS_ENABLE) { 2889*edd16368SStephen M. Cameron dev_info(&pdev->dev, "resetting MSI\n"); 2890*edd16368SStephen M. Cameron pci_write_config_word(pdev, msi_control_reg(pos), 2891*edd16368SStephen M. Cameron control & ~PCI_MSI_FLAGS_ENABLE); 2892*edd16368SStephen M. Cameron } 2893*edd16368SStephen M. Cameron } 2894*edd16368SStephen M. Cameron 2895*edd16368SStephen M. Cameron pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX); 2896*edd16368SStephen M. Cameron if (pos) { 2897*edd16368SStephen M. Cameron pci_read_config_word(pdev, msi_control_reg(pos), &control); 2898*edd16368SStephen M. Cameron if (control & PCI_MSIX_FLAGS_ENABLE) { 2899*edd16368SStephen M. Cameron dev_info(&pdev->dev, "resetting MSI-X\n"); 2900*edd16368SStephen M. Cameron pci_write_config_word(pdev, msi_control_reg(pos), 2901*edd16368SStephen M. Cameron control & ~PCI_MSIX_FLAGS_ENABLE); 2902*edd16368SStephen M. Cameron } 2903*edd16368SStephen M. Cameron } 2904*edd16368SStephen M. Cameron 2905*edd16368SStephen M. Cameron return 0; 2906*edd16368SStephen M. Cameron } 2907*edd16368SStephen M. Cameron 2908*edd16368SStephen M. Cameron /* This does a hard reset of the controller using PCI power management 2909*edd16368SStephen M. Cameron * states. 2910*edd16368SStephen M. Cameron */ 2911*edd16368SStephen M. Cameron static __devinit int hpsa_hard_reset_controller(struct pci_dev *pdev) 2912*edd16368SStephen M. Cameron { 2913*edd16368SStephen M. Cameron u16 pmcsr, saved_config_space[32]; 2914*edd16368SStephen M. Cameron int i, pos; 2915*edd16368SStephen M. Cameron 2916*edd16368SStephen M. Cameron dev_info(&pdev->dev, "using PCI PM to reset controller\n"); 2917*edd16368SStephen M. Cameron 2918*edd16368SStephen M. Cameron /* This is very nearly the same thing as 2919*edd16368SStephen M. Cameron * 2920*edd16368SStephen M. Cameron * pci_save_state(pci_dev); 2921*edd16368SStephen M. Cameron * pci_set_power_state(pci_dev, PCI_D3hot); 2922*edd16368SStephen M. Cameron * pci_set_power_state(pci_dev, PCI_D0); 2923*edd16368SStephen M. Cameron * pci_restore_state(pci_dev); 2924*edd16368SStephen M. Cameron * 2925*edd16368SStephen M. Cameron * but we can't use these nice canned kernel routines on 2926*edd16368SStephen M. Cameron * kexec, because they also check the MSI/MSI-X state in PCI 2927*edd16368SStephen M. Cameron * configuration space and do the wrong thing when it is 2928*edd16368SStephen M. Cameron * set/cleared. Also, the pci_save/restore_state functions 2929*edd16368SStephen M. Cameron * violate the ordering requirements for restoring the 2930*edd16368SStephen M. Cameron * configuration space from the CCISS document (see the 2931*edd16368SStephen M. Cameron * comment below). So we roll our own .... 2932*edd16368SStephen M. Cameron */ 2933*edd16368SStephen M. Cameron 2934*edd16368SStephen M. Cameron for (i = 0; i < 32; i++) 2935*edd16368SStephen M. Cameron pci_read_config_word(pdev, 2*i, &saved_config_space[i]); 2936*edd16368SStephen M. Cameron 2937*edd16368SStephen M. Cameron pos = pci_find_capability(pdev, PCI_CAP_ID_PM); 2938*edd16368SStephen M. Cameron if (pos == 0) { 2939*edd16368SStephen M. Cameron dev_err(&pdev->dev, 2940*edd16368SStephen M. Cameron "hpsa_reset_controller: PCI PM not supported\n"); 2941*edd16368SStephen M. Cameron return -ENODEV; 2942*edd16368SStephen M. Cameron } 2943*edd16368SStephen M. Cameron 2944*edd16368SStephen M. Cameron /* Quoting from the Open CISS Specification: "The Power 2945*edd16368SStephen M. Cameron * Management Control/Status Register (CSR) controls the power 2946*edd16368SStephen M. Cameron * state of the device. The normal operating state is D0, 2947*edd16368SStephen M. Cameron * CSR=00h. The software off state is D3, CSR=03h. To reset 2948*edd16368SStephen M. Cameron * the controller, place the interface device in D3 then to 2949*edd16368SStephen M. Cameron * D0, this causes a secondary PCI reset which will reset the 2950*edd16368SStephen M. Cameron * controller." 2951*edd16368SStephen M. Cameron */ 2952*edd16368SStephen M. Cameron 2953*edd16368SStephen M. Cameron /* enter the D3hot power management state */ 2954*edd16368SStephen M. Cameron pci_read_config_word(pdev, pos + PCI_PM_CTRL, &pmcsr); 2955*edd16368SStephen M. Cameron pmcsr &= ~PCI_PM_CTRL_STATE_MASK; 2956*edd16368SStephen M. Cameron pmcsr |= PCI_D3hot; 2957*edd16368SStephen M. Cameron pci_write_config_word(pdev, pos + PCI_PM_CTRL, pmcsr); 2958*edd16368SStephen M. Cameron 2959*edd16368SStephen M. Cameron msleep(500); 2960*edd16368SStephen M. Cameron 2961*edd16368SStephen M. Cameron /* enter the D0 power management state */ 2962*edd16368SStephen M. Cameron pmcsr &= ~PCI_PM_CTRL_STATE_MASK; 2963*edd16368SStephen M. Cameron pmcsr |= PCI_D0; 2964*edd16368SStephen M. Cameron pci_write_config_word(pdev, pos + PCI_PM_CTRL, pmcsr); 2965*edd16368SStephen M. Cameron 2966*edd16368SStephen M. Cameron msleep(500); 2967*edd16368SStephen M. Cameron 2968*edd16368SStephen M. Cameron /* Restore the PCI configuration space. The Open CISS 2969*edd16368SStephen M. Cameron * Specification says, "Restore the PCI Configuration 2970*edd16368SStephen M. Cameron * Registers, offsets 00h through 60h. It is important to 2971*edd16368SStephen M. Cameron * restore the command register, 16-bits at offset 04h, 2972*edd16368SStephen M. Cameron * last. Do not restore the configuration status register, 2973*edd16368SStephen M. Cameron * 16-bits at offset 06h." Note that the offset is 2*i. 2974*edd16368SStephen M. Cameron */ 2975*edd16368SStephen M. Cameron for (i = 0; i < 32; i++) { 2976*edd16368SStephen M. Cameron if (i == 2 || i == 3) 2977*edd16368SStephen M. Cameron continue; 2978*edd16368SStephen M. Cameron pci_write_config_word(pdev, 2*i, saved_config_space[i]); 2979*edd16368SStephen M. Cameron } 2980*edd16368SStephen M. Cameron wmb(); 2981*edd16368SStephen M. Cameron pci_write_config_word(pdev, 4, saved_config_space[2]); 2982*edd16368SStephen M. Cameron 2983*edd16368SStephen M. Cameron return 0; 2984*edd16368SStephen M. Cameron } 2985*edd16368SStephen M. Cameron 2986*edd16368SStephen M. Cameron /* 2987*edd16368SStephen M. Cameron * We cannot read the structure directly, for portability we must use 2988*edd16368SStephen M. Cameron * the io functions. 2989*edd16368SStephen M. Cameron * This is for debug only. 2990*edd16368SStephen M. Cameron */ 2991*edd16368SStephen M. Cameron #ifdef HPSA_DEBUG 2992*edd16368SStephen M. Cameron static void print_cfg_table(struct device *dev, struct CfgTable *tb) 2993*edd16368SStephen M. Cameron { 2994*edd16368SStephen M. Cameron int i; 2995*edd16368SStephen M. Cameron char temp_name[17]; 2996*edd16368SStephen M. Cameron 2997*edd16368SStephen M. Cameron dev_info(dev, "Controller Configuration information\n"); 2998*edd16368SStephen M. Cameron dev_info(dev, "------------------------------------\n"); 2999*edd16368SStephen M. Cameron for (i = 0; i < 4; i++) 3000*edd16368SStephen M. Cameron temp_name[i] = readb(&(tb->Signature[i])); 3001*edd16368SStephen M. Cameron temp_name[4] = '\0'; 3002*edd16368SStephen M. Cameron dev_info(dev, " Signature = %s\n", temp_name); 3003*edd16368SStephen M. Cameron dev_info(dev, " Spec Number = %d\n", readl(&(tb->SpecValence))); 3004*edd16368SStephen M. Cameron dev_info(dev, " Transport methods supported = 0x%x\n", 3005*edd16368SStephen M. Cameron readl(&(tb->TransportSupport))); 3006*edd16368SStephen M. Cameron dev_info(dev, " Transport methods active = 0x%x\n", 3007*edd16368SStephen M. Cameron readl(&(tb->TransportActive))); 3008*edd16368SStephen M. Cameron dev_info(dev, " Requested transport Method = 0x%x\n", 3009*edd16368SStephen M. Cameron readl(&(tb->HostWrite.TransportRequest))); 3010*edd16368SStephen M. Cameron dev_info(dev, " Coalesce Interrupt Delay = 0x%x\n", 3011*edd16368SStephen M. Cameron readl(&(tb->HostWrite.CoalIntDelay))); 3012*edd16368SStephen M. Cameron dev_info(dev, " Coalesce Interrupt Count = 0x%x\n", 3013*edd16368SStephen M. Cameron readl(&(tb->HostWrite.CoalIntCount))); 3014*edd16368SStephen M. Cameron dev_info(dev, " Max outstanding commands = 0x%d\n", 3015*edd16368SStephen M. Cameron readl(&(tb->CmdsOutMax))); 3016*edd16368SStephen M. Cameron dev_info(dev, " Bus Types = 0x%x\n", readl(&(tb->BusTypes))); 3017*edd16368SStephen M. Cameron for (i = 0; i < 16; i++) 3018*edd16368SStephen M. Cameron temp_name[i] = readb(&(tb->ServerName[i])); 3019*edd16368SStephen M. Cameron temp_name[16] = '\0'; 3020*edd16368SStephen M. Cameron dev_info(dev, " Server Name = %s\n", temp_name); 3021*edd16368SStephen M. Cameron dev_info(dev, " Heartbeat Counter = 0x%x\n\n\n", 3022*edd16368SStephen M. Cameron readl(&(tb->HeartBeat))); 3023*edd16368SStephen M. Cameron } 3024*edd16368SStephen M. Cameron #endif /* HPSA_DEBUG */ 3025*edd16368SStephen M. Cameron 3026*edd16368SStephen M. Cameron static int find_PCI_BAR_index(struct pci_dev *pdev, unsigned long pci_bar_addr) 3027*edd16368SStephen M. Cameron { 3028*edd16368SStephen M. Cameron int i, offset, mem_type, bar_type; 3029*edd16368SStephen M. Cameron 3030*edd16368SStephen M. Cameron if (pci_bar_addr == PCI_BASE_ADDRESS_0) /* looking for BAR zero? */ 3031*edd16368SStephen M. Cameron return 0; 3032*edd16368SStephen M. Cameron offset = 0; 3033*edd16368SStephen M. Cameron for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { 3034*edd16368SStephen M. Cameron bar_type = pci_resource_flags(pdev, i) & PCI_BASE_ADDRESS_SPACE; 3035*edd16368SStephen M. Cameron if (bar_type == PCI_BASE_ADDRESS_SPACE_IO) 3036*edd16368SStephen M. Cameron offset += 4; 3037*edd16368SStephen M. Cameron else { 3038*edd16368SStephen M. Cameron mem_type = pci_resource_flags(pdev, i) & 3039*edd16368SStephen M. Cameron PCI_BASE_ADDRESS_MEM_TYPE_MASK; 3040*edd16368SStephen M. Cameron switch (mem_type) { 3041*edd16368SStephen M. Cameron case PCI_BASE_ADDRESS_MEM_TYPE_32: 3042*edd16368SStephen M. Cameron case PCI_BASE_ADDRESS_MEM_TYPE_1M: 3043*edd16368SStephen M. Cameron offset += 4; /* 32 bit */ 3044*edd16368SStephen M. Cameron break; 3045*edd16368SStephen M. Cameron case PCI_BASE_ADDRESS_MEM_TYPE_64: 3046*edd16368SStephen M. Cameron offset += 8; 3047*edd16368SStephen M. Cameron break; 3048*edd16368SStephen M. Cameron default: /* reserved in PCI 2.2 */ 3049*edd16368SStephen M. Cameron dev_warn(&pdev->dev, 3050*edd16368SStephen M. Cameron "base address is invalid\n"); 3051*edd16368SStephen M. Cameron return -1; 3052*edd16368SStephen M. Cameron break; 3053*edd16368SStephen M. Cameron } 3054*edd16368SStephen M. Cameron } 3055*edd16368SStephen M. Cameron if (offset == pci_bar_addr - PCI_BASE_ADDRESS_0) 3056*edd16368SStephen M. Cameron return i + 1; 3057*edd16368SStephen M. Cameron } 3058*edd16368SStephen M. Cameron return -1; 3059*edd16368SStephen M. Cameron } 3060*edd16368SStephen M. Cameron 3061*edd16368SStephen M. Cameron /* If MSI/MSI-X is supported by the kernel we will try to enable it on 3062*edd16368SStephen M. Cameron * controllers that are capable. If not, we use IO-APIC mode. 3063*edd16368SStephen M. Cameron */ 3064*edd16368SStephen M. Cameron 3065*edd16368SStephen M. Cameron static void __devinit hpsa_interrupt_mode(struct ctlr_info *h, 3066*edd16368SStephen M. Cameron struct pci_dev *pdev, __u32 board_id) 3067*edd16368SStephen M. Cameron { 3068*edd16368SStephen M. Cameron #ifdef CONFIG_PCI_MSI 3069*edd16368SStephen M. Cameron int err; 3070*edd16368SStephen M. Cameron struct msix_entry hpsa_msix_entries[4] = { {0, 0}, {0, 1}, 3071*edd16368SStephen M. Cameron {0, 2}, {0, 3} 3072*edd16368SStephen M. Cameron }; 3073*edd16368SStephen M. Cameron 3074*edd16368SStephen M. Cameron /* Some boards advertise MSI but don't really support it */ 3075*edd16368SStephen M. Cameron if ((board_id == 0x40700E11) || 3076*edd16368SStephen M. Cameron (board_id == 0x40800E11) || 3077*edd16368SStephen M. Cameron (board_id == 0x40820E11) || (board_id == 0x40830E11)) 3078*edd16368SStephen M. Cameron goto default_int_mode; 3079*edd16368SStephen M. Cameron if (pci_find_capability(pdev, PCI_CAP_ID_MSIX)) { 3080*edd16368SStephen M. Cameron dev_info(&pdev->dev, "MSIX\n"); 3081*edd16368SStephen M. Cameron err = pci_enable_msix(pdev, hpsa_msix_entries, 4); 3082*edd16368SStephen M. Cameron if (!err) { 3083*edd16368SStephen M. Cameron h->intr[0] = hpsa_msix_entries[0].vector; 3084*edd16368SStephen M. Cameron h->intr[1] = hpsa_msix_entries[1].vector; 3085*edd16368SStephen M. Cameron h->intr[2] = hpsa_msix_entries[2].vector; 3086*edd16368SStephen M. Cameron h->intr[3] = hpsa_msix_entries[3].vector; 3087*edd16368SStephen M. Cameron h->msix_vector = 1; 3088*edd16368SStephen M. Cameron return; 3089*edd16368SStephen M. Cameron } 3090*edd16368SStephen M. Cameron if (err > 0) { 3091*edd16368SStephen M. Cameron dev_warn(&pdev->dev, "only %d MSI-X vectors " 3092*edd16368SStephen M. Cameron "available\n", err); 3093*edd16368SStephen M. Cameron goto default_int_mode; 3094*edd16368SStephen M. Cameron } else { 3095*edd16368SStephen M. Cameron dev_warn(&pdev->dev, "MSI-X init failed %d\n", 3096*edd16368SStephen M. Cameron err); 3097*edd16368SStephen M. Cameron goto default_int_mode; 3098*edd16368SStephen M. Cameron } 3099*edd16368SStephen M. Cameron } 3100*edd16368SStephen M. Cameron if (pci_find_capability(pdev, PCI_CAP_ID_MSI)) { 3101*edd16368SStephen M. Cameron dev_info(&pdev->dev, "MSI\n"); 3102*edd16368SStephen M. Cameron if (!pci_enable_msi(pdev)) 3103*edd16368SStephen M. Cameron h->msi_vector = 1; 3104*edd16368SStephen M. Cameron else 3105*edd16368SStephen M. Cameron dev_warn(&pdev->dev, "MSI init failed\n"); 3106*edd16368SStephen M. Cameron } 3107*edd16368SStephen M. Cameron default_int_mode: 3108*edd16368SStephen M. Cameron #endif /* CONFIG_PCI_MSI */ 3109*edd16368SStephen M. Cameron /* if we get here we're going to use the default interrupt mode */ 3110*edd16368SStephen M. Cameron h->intr[SIMPLE_MODE_INT] = pdev->irq; 3111*edd16368SStephen M. Cameron return; 3112*edd16368SStephen M. Cameron } 3113*edd16368SStephen M. Cameron 3114*edd16368SStephen M. Cameron static int hpsa_pci_init(struct ctlr_info *h, struct pci_dev *pdev) 3115*edd16368SStephen M. Cameron { 3116*edd16368SStephen M. Cameron ushort subsystem_vendor_id, subsystem_device_id, command; 3117*edd16368SStephen M. Cameron __u32 board_id, scratchpad = 0; 3118*edd16368SStephen M. Cameron __u64 cfg_offset; 3119*edd16368SStephen M. Cameron __u32 cfg_base_addr; 3120*edd16368SStephen M. Cameron __u64 cfg_base_addr_index; 3121*edd16368SStephen M. Cameron int i, prod_index, err; 3122*edd16368SStephen M. Cameron 3123*edd16368SStephen M. Cameron subsystem_vendor_id = pdev->subsystem_vendor; 3124*edd16368SStephen M. Cameron subsystem_device_id = pdev->subsystem_device; 3125*edd16368SStephen M. Cameron board_id = (((__u32) (subsystem_device_id << 16) & 0xffff0000) | 3126*edd16368SStephen M. Cameron subsystem_vendor_id); 3127*edd16368SStephen M. Cameron 3128*edd16368SStephen M. Cameron for (i = 0; i < ARRAY_SIZE(products); i++) 3129*edd16368SStephen M. Cameron if (board_id == products[i].board_id) 3130*edd16368SStephen M. Cameron break; 3131*edd16368SStephen M. Cameron 3132*edd16368SStephen M. Cameron prod_index = i; 3133*edd16368SStephen M. Cameron 3134*edd16368SStephen M. Cameron if (prod_index == ARRAY_SIZE(products)) { 3135*edd16368SStephen M. Cameron prod_index--; 3136*edd16368SStephen M. Cameron if (subsystem_vendor_id != PCI_VENDOR_ID_HP || 3137*edd16368SStephen M. Cameron !hpsa_allow_any) { 3138*edd16368SStephen M. Cameron dev_warn(&pdev->dev, "unrecognized board ID:" 3139*edd16368SStephen M. Cameron " 0x%08lx, ignoring.\n", 3140*edd16368SStephen M. Cameron (unsigned long) board_id); 3141*edd16368SStephen M. Cameron return -ENODEV; 3142*edd16368SStephen M. Cameron } 3143*edd16368SStephen M. Cameron } 3144*edd16368SStephen M. Cameron /* check to see if controller has been disabled 3145*edd16368SStephen M. Cameron * BEFORE trying to enable it 3146*edd16368SStephen M. Cameron */ 3147*edd16368SStephen M. Cameron (void)pci_read_config_word(pdev, PCI_COMMAND, &command); 3148*edd16368SStephen M. Cameron if (!(command & 0x02)) { 3149*edd16368SStephen M. Cameron dev_warn(&pdev->dev, "controller appears to be disabled\n"); 3150*edd16368SStephen M. Cameron return -ENODEV; 3151*edd16368SStephen M. Cameron } 3152*edd16368SStephen M. Cameron 3153*edd16368SStephen M. Cameron err = pci_enable_device(pdev); 3154*edd16368SStephen M. Cameron if (err) { 3155*edd16368SStephen M. Cameron dev_warn(&pdev->dev, "unable to enable PCI device\n"); 3156*edd16368SStephen M. Cameron return err; 3157*edd16368SStephen M. Cameron } 3158*edd16368SStephen M. Cameron 3159*edd16368SStephen M. Cameron err = pci_request_regions(pdev, "hpsa"); 3160*edd16368SStephen M. Cameron if (err) { 3161*edd16368SStephen M. Cameron dev_err(&pdev->dev, "cannot obtain PCI resources, aborting\n"); 3162*edd16368SStephen M. Cameron return err; 3163*edd16368SStephen M. Cameron } 3164*edd16368SStephen M. Cameron 3165*edd16368SStephen M. Cameron /* If the kernel supports MSI/MSI-X we will try to enable that, 3166*edd16368SStephen M. Cameron * else we use the IO-APIC interrupt assigned to us by system ROM. 3167*edd16368SStephen M. Cameron */ 3168*edd16368SStephen M. Cameron hpsa_interrupt_mode(h, pdev, board_id); 3169*edd16368SStephen M. Cameron 3170*edd16368SStephen M. Cameron /* find the memory BAR */ 3171*edd16368SStephen M. Cameron for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { 3172*edd16368SStephen M. Cameron if (pci_resource_flags(pdev, i) & IORESOURCE_MEM) 3173*edd16368SStephen M. Cameron break; 3174*edd16368SStephen M. Cameron } 3175*edd16368SStephen M. Cameron if (i == DEVICE_COUNT_RESOURCE) { 3176*edd16368SStephen M. Cameron dev_warn(&pdev->dev, "no memory BAR found\n"); 3177*edd16368SStephen M. Cameron err = -ENODEV; 3178*edd16368SStephen M. Cameron goto err_out_free_res; 3179*edd16368SStephen M. Cameron } 3180*edd16368SStephen M. Cameron 3181*edd16368SStephen M. Cameron h->paddr = pci_resource_start(pdev, i); /* addressing mode bits 3182*edd16368SStephen M. Cameron * already removed 3183*edd16368SStephen M. Cameron */ 3184*edd16368SStephen M. Cameron 3185*edd16368SStephen M. Cameron h->vaddr = remap_pci_mem(h->paddr, 0x250); 3186*edd16368SStephen M. Cameron 3187*edd16368SStephen M. Cameron /* Wait for the board to become ready. */ 3188*edd16368SStephen M. Cameron for (i = 0; i < HPSA_BOARD_READY_ITERATIONS; i++) { 3189*edd16368SStephen M. Cameron scratchpad = readl(h->vaddr + SA5_SCRATCHPAD_OFFSET); 3190*edd16368SStephen M. Cameron if (scratchpad == HPSA_FIRMWARE_READY) 3191*edd16368SStephen M. Cameron break; 3192*edd16368SStephen M. Cameron msleep(HPSA_BOARD_READY_POLL_INTERVAL_MSECS); 3193*edd16368SStephen M. Cameron } 3194*edd16368SStephen M. Cameron if (scratchpad != HPSA_FIRMWARE_READY) { 3195*edd16368SStephen M. Cameron dev_warn(&pdev->dev, "board not ready, timed out.\n"); 3196*edd16368SStephen M. Cameron err = -ENODEV; 3197*edd16368SStephen M. Cameron goto err_out_free_res; 3198*edd16368SStephen M. Cameron } 3199*edd16368SStephen M. Cameron 3200*edd16368SStephen M. Cameron /* get the address index number */ 3201*edd16368SStephen M. Cameron cfg_base_addr = readl(h->vaddr + SA5_CTCFG_OFFSET); 3202*edd16368SStephen M. Cameron cfg_base_addr &= (__u32) 0x0000ffff; 3203*edd16368SStephen M. Cameron cfg_base_addr_index = find_PCI_BAR_index(pdev, cfg_base_addr); 3204*edd16368SStephen M. Cameron if (cfg_base_addr_index == -1) { 3205*edd16368SStephen M. Cameron dev_warn(&pdev->dev, "cannot find cfg_base_addr_index\n"); 3206*edd16368SStephen M. Cameron err = -ENODEV; 3207*edd16368SStephen M. Cameron goto err_out_free_res; 3208*edd16368SStephen M. Cameron } 3209*edd16368SStephen M. Cameron 3210*edd16368SStephen M. Cameron cfg_offset = readl(h->vaddr + SA5_CTMEM_OFFSET); 3211*edd16368SStephen M. Cameron h->cfgtable = remap_pci_mem(pci_resource_start(pdev, 3212*edd16368SStephen M. Cameron cfg_base_addr_index) + cfg_offset, 3213*edd16368SStephen M. Cameron sizeof(h->cfgtable)); 3214*edd16368SStephen M. Cameron h->board_id = board_id; 3215*edd16368SStephen M. Cameron 3216*edd16368SStephen M. Cameron /* Query controller for max supported commands: */ 3217*edd16368SStephen M. Cameron h->max_commands = readl(&(h->cfgtable->CmdsOutMax)); 3218*edd16368SStephen M. Cameron 3219*edd16368SStephen M. Cameron h->product_name = products[prod_index].product_name; 3220*edd16368SStephen M. Cameron h->access = *(products[prod_index].access); 3221*edd16368SStephen M. Cameron /* Allow room for some ioctls */ 3222*edd16368SStephen M. Cameron h->nr_cmds = h->max_commands - 4; 3223*edd16368SStephen M. Cameron 3224*edd16368SStephen M. Cameron if ((readb(&h->cfgtable->Signature[0]) != 'C') || 3225*edd16368SStephen M. Cameron (readb(&h->cfgtable->Signature[1]) != 'I') || 3226*edd16368SStephen M. Cameron (readb(&h->cfgtable->Signature[2]) != 'S') || 3227*edd16368SStephen M. Cameron (readb(&h->cfgtable->Signature[3]) != 'S')) { 3228*edd16368SStephen M. Cameron dev_warn(&pdev->dev, "not a valid CISS config table\n"); 3229*edd16368SStephen M. Cameron err = -ENODEV; 3230*edd16368SStephen M. Cameron goto err_out_free_res; 3231*edd16368SStephen M. Cameron } 3232*edd16368SStephen M. Cameron #ifdef CONFIG_X86 3233*edd16368SStephen M. Cameron { 3234*edd16368SStephen M. Cameron /* Need to enable prefetch in the SCSI core for 6400 in x86 */ 3235*edd16368SStephen M. Cameron __u32 prefetch; 3236*edd16368SStephen M. Cameron prefetch = readl(&(h->cfgtable->SCSI_Prefetch)); 3237*edd16368SStephen M. Cameron prefetch |= 0x100; 3238*edd16368SStephen M. Cameron writel(prefetch, &(h->cfgtable->SCSI_Prefetch)); 3239*edd16368SStephen M. Cameron } 3240*edd16368SStephen M. Cameron #endif 3241*edd16368SStephen M. Cameron 3242*edd16368SStephen M. Cameron /* Disabling DMA prefetch for the P600 3243*edd16368SStephen M. Cameron * An ASIC bug may result in a prefetch beyond 3244*edd16368SStephen M. Cameron * physical memory. 3245*edd16368SStephen M. Cameron */ 3246*edd16368SStephen M. Cameron if (board_id == 0x3225103C) { 3247*edd16368SStephen M. Cameron __u32 dma_prefetch; 3248*edd16368SStephen M. Cameron dma_prefetch = readl(h->vaddr + I2O_DMA1_CFG); 3249*edd16368SStephen M. Cameron dma_prefetch |= 0x8000; 3250*edd16368SStephen M. Cameron writel(dma_prefetch, h->vaddr + I2O_DMA1_CFG); 3251*edd16368SStephen M. Cameron } 3252*edd16368SStephen M. Cameron 3253*edd16368SStephen M. Cameron h->max_commands = readl(&(h->cfgtable->CmdsOutMax)); 3254*edd16368SStephen M. Cameron /* Update the field, and then ring the doorbell */ 3255*edd16368SStephen M. Cameron writel(CFGTBL_Trans_Simple, &(h->cfgtable->HostWrite.TransportRequest)); 3256*edd16368SStephen M. Cameron writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL); 3257*edd16368SStephen M. Cameron 3258*edd16368SStephen M. Cameron /* under certain very rare conditions, this can take awhile. 3259*edd16368SStephen M. Cameron * (e.g.: hot replace a failed 144GB drive in a RAID 5 set right 3260*edd16368SStephen M. Cameron * as we enter this code.) 3261*edd16368SStephen M. Cameron */ 3262*edd16368SStephen M. Cameron for (i = 0; i < MAX_CONFIG_WAIT; i++) { 3263*edd16368SStephen M. Cameron if (!(readl(h->vaddr + SA5_DOORBELL) & CFGTBL_ChangeReq)) 3264*edd16368SStephen M. Cameron break; 3265*edd16368SStephen M. Cameron /* delay and try again */ 3266*edd16368SStephen M. Cameron msleep(10); 3267*edd16368SStephen M. Cameron } 3268*edd16368SStephen M. Cameron 3269*edd16368SStephen M. Cameron #ifdef HPSA_DEBUG 3270*edd16368SStephen M. Cameron print_cfg_table(&pdev->dev, h->cfgtable); 3271*edd16368SStephen M. Cameron #endif /* HPSA_DEBUG */ 3272*edd16368SStephen M. Cameron 3273*edd16368SStephen M. Cameron if (!(readl(&(h->cfgtable->TransportActive)) & CFGTBL_Trans_Simple)) { 3274*edd16368SStephen M. Cameron dev_warn(&pdev->dev, "unable to get board into simple mode\n"); 3275*edd16368SStephen M. Cameron err = -ENODEV; 3276*edd16368SStephen M. Cameron goto err_out_free_res; 3277*edd16368SStephen M. Cameron } 3278*edd16368SStephen M. Cameron return 0; 3279*edd16368SStephen M. Cameron 3280*edd16368SStephen M. Cameron err_out_free_res: 3281*edd16368SStephen M. Cameron /* 3282*edd16368SStephen M. Cameron * Deliberately omit pci_disable_device(): it does something nasty to 3283*edd16368SStephen M. Cameron * Smart Array controllers that pci_enable_device does not undo 3284*edd16368SStephen M. Cameron */ 3285*edd16368SStephen M. Cameron pci_release_regions(pdev); 3286*edd16368SStephen M. Cameron return err; 3287*edd16368SStephen M. Cameron } 3288*edd16368SStephen M. Cameron 3289*edd16368SStephen M. Cameron static int __devinit hpsa_init_one(struct pci_dev *pdev, 3290*edd16368SStephen M. Cameron const struct pci_device_id *ent) 3291*edd16368SStephen M. Cameron { 3292*edd16368SStephen M. Cameron int i; 3293*edd16368SStephen M. Cameron int dac; 3294*edd16368SStephen M. Cameron struct ctlr_info *h; 3295*edd16368SStephen M. Cameron 3296*edd16368SStephen M. Cameron if (number_of_controllers == 0) 3297*edd16368SStephen M. Cameron printk(KERN_INFO DRIVER_NAME "\n"); 3298*edd16368SStephen M. Cameron if (reset_devices) { 3299*edd16368SStephen M. Cameron /* Reset the controller with a PCI power-cycle */ 3300*edd16368SStephen M. Cameron if (hpsa_hard_reset_controller(pdev) || hpsa_reset_msi(pdev)) 3301*edd16368SStephen M. Cameron return -ENODEV; 3302*edd16368SStephen M. Cameron 3303*edd16368SStephen M. Cameron /* Some devices (notably the HP Smart Array 5i Controller) 3304*edd16368SStephen M. Cameron need a little pause here */ 3305*edd16368SStephen M. Cameron msleep(HPSA_POST_RESET_PAUSE_MSECS); 3306*edd16368SStephen M. Cameron 3307*edd16368SStephen M. Cameron /* Now try to get the controller to respond to a no-op */ 3308*edd16368SStephen M. Cameron for (i = 0; i < HPSA_POST_RESET_NOOP_RETRIES; i++) { 3309*edd16368SStephen M. Cameron if (hpsa_noop(pdev) == 0) 3310*edd16368SStephen M. Cameron break; 3311*edd16368SStephen M. Cameron else 3312*edd16368SStephen M. Cameron dev_warn(&pdev->dev, "no-op failed%s\n", 3313*edd16368SStephen M. Cameron (i < 11 ? "; re-trying" : "")); 3314*edd16368SStephen M. Cameron } 3315*edd16368SStephen M. Cameron } 3316*edd16368SStephen M. Cameron 3317*edd16368SStephen M. Cameron BUILD_BUG_ON(sizeof(struct CommandList) % 8); 3318*edd16368SStephen M. Cameron h = kzalloc(sizeof(*h), GFP_KERNEL); 3319*edd16368SStephen M. Cameron if (!h) 3320*edd16368SStephen M. Cameron return -1; 3321*edd16368SStephen M. Cameron 3322*edd16368SStephen M. Cameron h->busy_initializing = 1; 3323*edd16368SStephen M. Cameron INIT_HLIST_HEAD(&h->cmpQ); 3324*edd16368SStephen M. Cameron INIT_HLIST_HEAD(&h->reqQ); 3325*edd16368SStephen M. Cameron mutex_init(&h->busy_shutting_down); 3326*edd16368SStephen M. Cameron init_completion(&h->scan_wait); 3327*edd16368SStephen M. Cameron if (hpsa_pci_init(h, pdev) != 0) 3328*edd16368SStephen M. Cameron goto clean1; 3329*edd16368SStephen M. Cameron 3330*edd16368SStephen M. Cameron sprintf(h->devname, "hpsa%d", number_of_controllers); 3331*edd16368SStephen M. Cameron h->ctlr = number_of_controllers; 3332*edd16368SStephen M. Cameron number_of_controllers++; 3333*edd16368SStephen M. Cameron h->pdev = pdev; 3334*edd16368SStephen M. Cameron 3335*edd16368SStephen M. Cameron /* configure PCI DMA stuff */ 3336*edd16368SStephen M. Cameron if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) 3337*edd16368SStephen M. Cameron dac = 1; 3338*edd16368SStephen M. Cameron else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) 3339*edd16368SStephen M. Cameron dac = 0; 3340*edd16368SStephen M. Cameron else { 3341*edd16368SStephen M. Cameron dev_err(&pdev->dev, "no suitable DMA available\n"); 3342*edd16368SStephen M. Cameron goto clean1; 3343*edd16368SStephen M. Cameron } 3344*edd16368SStephen M. Cameron 3345*edd16368SStephen M. Cameron /* make sure the board interrupts are off */ 3346*edd16368SStephen M. Cameron h->access.set_intr_mask(h, HPSA_INTR_OFF); 3347*edd16368SStephen M. Cameron if (request_irq(h->intr[SIMPLE_MODE_INT], do_hpsa_intr, 3348*edd16368SStephen M. Cameron IRQF_DISABLED | IRQF_SHARED, h->devname, h)) { 3349*edd16368SStephen M. Cameron dev_err(&pdev->dev, "unable to get irq %d for %s\n", 3350*edd16368SStephen M. Cameron h->intr[SIMPLE_MODE_INT], h->devname); 3351*edd16368SStephen M. Cameron goto clean2; 3352*edd16368SStephen M. Cameron } 3353*edd16368SStephen M. Cameron 3354*edd16368SStephen M. Cameron dev_info(&pdev->dev, "%s: <0x%x> at PCI %s IRQ %d%s using DAC\n", 3355*edd16368SStephen M. Cameron h->devname, pdev->device, pci_name(pdev), 3356*edd16368SStephen M. Cameron h->intr[SIMPLE_MODE_INT], dac ? "" : " not"); 3357*edd16368SStephen M. Cameron 3358*edd16368SStephen M. Cameron h->cmd_pool_bits = 3359*edd16368SStephen M. Cameron kmalloc(((h->nr_cmds + BITS_PER_LONG - 3360*edd16368SStephen M. Cameron 1) / BITS_PER_LONG) * sizeof(unsigned long), GFP_KERNEL); 3361*edd16368SStephen M. Cameron h->cmd_pool = pci_alloc_consistent(h->pdev, 3362*edd16368SStephen M. Cameron h->nr_cmds * sizeof(*h->cmd_pool), 3363*edd16368SStephen M. Cameron &(h->cmd_pool_dhandle)); 3364*edd16368SStephen M. Cameron h->errinfo_pool = pci_alloc_consistent(h->pdev, 3365*edd16368SStephen M. Cameron h->nr_cmds * sizeof(*h->errinfo_pool), 3366*edd16368SStephen M. Cameron &(h->errinfo_pool_dhandle)); 3367*edd16368SStephen M. Cameron if ((h->cmd_pool_bits == NULL) 3368*edd16368SStephen M. Cameron || (h->cmd_pool == NULL) 3369*edd16368SStephen M. Cameron || (h->errinfo_pool == NULL)) { 3370*edd16368SStephen M. Cameron dev_err(&pdev->dev, "out of memory"); 3371*edd16368SStephen M. Cameron goto clean4; 3372*edd16368SStephen M. Cameron } 3373*edd16368SStephen M. Cameron spin_lock_init(&h->lock); 3374*edd16368SStephen M. Cameron 3375*edd16368SStephen M. Cameron pci_set_drvdata(pdev, h); 3376*edd16368SStephen M. Cameron memset(h->cmd_pool_bits, 0, 3377*edd16368SStephen M. Cameron ((h->nr_cmds + BITS_PER_LONG - 3378*edd16368SStephen M. Cameron 1) / BITS_PER_LONG) * sizeof(unsigned long)); 3379*edd16368SStephen M. Cameron 3380*edd16368SStephen M. Cameron hpsa_scsi_setup(h); 3381*edd16368SStephen M. Cameron 3382*edd16368SStephen M. Cameron /* Turn the interrupts on so we can service requests */ 3383*edd16368SStephen M. Cameron h->access.set_intr_mask(h, HPSA_INTR_ON); 3384*edd16368SStephen M. Cameron 3385*edd16368SStephen M. Cameron hpsa_register_scsi(h); /* hook ourselves into SCSI subsystem */ 3386*edd16368SStephen M. Cameron h->busy_initializing = 0; 3387*edd16368SStephen M. Cameron return 1; 3388*edd16368SStephen M. Cameron 3389*edd16368SStephen M. Cameron clean4: 3390*edd16368SStephen M. Cameron kfree(h->cmd_pool_bits); 3391*edd16368SStephen M. Cameron if (h->cmd_pool) 3392*edd16368SStephen M. Cameron pci_free_consistent(h->pdev, 3393*edd16368SStephen M. Cameron h->nr_cmds * sizeof(struct CommandList), 3394*edd16368SStephen M. Cameron h->cmd_pool, h->cmd_pool_dhandle); 3395*edd16368SStephen M. Cameron if (h->errinfo_pool) 3396*edd16368SStephen M. Cameron pci_free_consistent(h->pdev, 3397*edd16368SStephen M. Cameron h->nr_cmds * sizeof(struct ErrorInfo), 3398*edd16368SStephen M. Cameron h->errinfo_pool, 3399*edd16368SStephen M. Cameron h->errinfo_pool_dhandle); 3400*edd16368SStephen M. Cameron free_irq(h->intr[SIMPLE_MODE_INT], h); 3401*edd16368SStephen M. Cameron clean2: 3402*edd16368SStephen M. Cameron clean1: 3403*edd16368SStephen M. Cameron h->busy_initializing = 0; 3404*edd16368SStephen M. Cameron kfree(h); 3405*edd16368SStephen M. Cameron return -1; 3406*edd16368SStephen M. Cameron } 3407*edd16368SStephen M. Cameron 3408*edd16368SStephen M. Cameron static void hpsa_flush_cache(struct ctlr_info *h) 3409*edd16368SStephen M. Cameron { 3410*edd16368SStephen M. Cameron char *flush_buf; 3411*edd16368SStephen M. Cameron struct CommandList *c; 3412*edd16368SStephen M. Cameron 3413*edd16368SStephen M. Cameron flush_buf = kzalloc(4, GFP_KERNEL); 3414*edd16368SStephen M. Cameron if (!flush_buf) 3415*edd16368SStephen M. Cameron return; 3416*edd16368SStephen M. Cameron 3417*edd16368SStephen M. Cameron c = cmd_special_alloc(h); 3418*edd16368SStephen M. Cameron if (!c) { 3419*edd16368SStephen M. Cameron dev_warn(&h->pdev->dev, "cmd_special_alloc returned NULL!\n"); 3420*edd16368SStephen M. Cameron goto out_of_memory; 3421*edd16368SStephen M. Cameron } 3422*edd16368SStephen M. Cameron fill_cmd(c, HPSA_CACHE_FLUSH, h, flush_buf, 4, 0, 3423*edd16368SStephen M. Cameron RAID_CTLR_LUNID, TYPE_CMD); 3424*edd16368SStephen M. Cameron hpsa_scsi_do_simple_cmd_with_retry(h, c, PCI_DMA_TODEVICE); 3425*edd16368SStephen M. Cameron if (c->err_info->CommandStatus != 0) 3426*edd16368SStephen M. Cameron dev_warn(&h->pdev->dev, 3427*edd16368SStephen M. Cameron "error flushing cache on controller\n"); 3428*edd16368SStephen M. Cameron cmd_special_free(h, c); 3429*edd16368SStephen M. Cameron out_of_memory: 3430*edd16368SStephen M. Cameron kfree(flush_buf); 3431*edd16368SStephen M. Cameron } 3432*edd16368SStephen M. Cameron 3433*edd16368SStephen M. Cameron static void hpsa_shutdown(struct pci_dev *pdev) 3434*edd16368SStephen M. Cameron { 3435*edd16368SStephen M. Cameron struct ctlr_info *h; 3436*edd16368SStephen M. Cameron 3437*edd16368SStephen M. Cameron h = pci_get_drvdata(pdev); 3438*edd16368SStephen M. Cameron /* Turn board interrupts off and send the flush cache command 3439*edd16368SStephen M. Cameron * sendcmd will turn off interrupt, and send the flush... 3440*edd16368SStephen M. Cameron * To write all data in the battery backed cache to disks 3441*edd16368SStephen M. Cameron */ 3442*edd16368SStephen M. Cameron hpsa_flush_cache(h); 3443*edd16368SStephen M. Cameron h->access.set_intr_mask(h, HPSA_INTR_OFF); 3444*edd16368SStephen M. Cameron free_irq(h->intr[2], h); 3445*edd16368SStephen M. Cameron #ifdef CONFIG_PCI_MSI 3446*edd16368SStephen M. Cameron if (h->msix_vector) 3447*edd16368SStephen M. Cameron pci_disable_msix(h->pdev); 3448*edd16368SStephen M. Cameron else if (h->msi_vector) 3449*edd16368SStephen M. Cameron pci_disable_msi(h->pdev); 3450*edd16368SStephen M. Cameron #endif /* CONFIG_PCI_MSI */ 3451*edd16368SStephen M. Cameron } 3452*edd16368SStephen M. Cameron 3453*edd16368SStephen M. Cameron static void __devexit hpsa_remove_one(struct pci_dev *pdev) 3454*edd16368SStephen M. Cameron { 3455*edd16368SStephen M. Cameron struct ctlr_info *h; 3456*edd16368SStephen M. Cameron 3457*edd16368SStephen M. Cameron if (pci_get_drvdata(pdev) == NULL) { 3458*edd16368SStephen M. Cameron dev_err(&pdev->dev, "unable to remove device \n"); 3459*edd16368SStephen M. Cameron return; 3460*edd16368SStephen M. Cameron } 3461*edd16368SStephen M. Cameron h = pci_get_drvdata(pdev); 3462*edd16368SStephen M. Cameron mutex_lock(&h->busy_shutting_down); 3463*edd16368SStephen M. Cameron remove_from_scan_list(h); 3464*edd16368SStephen M. Cameron hpsa_unregister_scsi(h); /* unhook from SCSI subsystem */ 3465*edd16368SStephen M. Cameron hpsa_shutdown(pdev); 3466*edd16368SStephen M. Cameron iounmap(h->vaddr); 3467*edd16368SStephen M. Cameron pci_free_consistent(h->pdev, 3468*edd16368SStephen M. Cameron h->nr_cmds * sizeof(struct CommandList), 3469*edd16368SStephen M. Cameron h->cmd_pool, h->cmd_pool_dhandle); 3470*edd16368SStephen M. Cameron pci_free_consistent(h->pdev, 3471*edd16368SStephen M. Cameron h->nr_cmds * sizeof(struct ErrorInfo), 3472*edd16368SStephen M. Cameron h->errinfo_pool, h->errinfo_pool_dhandle); 3473*edd16368SStephen M. Cameron kfree(h->cmd_pool_bits); 3474*edd16368SStephen M. Cameron /* 3475*edd16368SStephen M. Cameron * Deliberately omit pci_disable_device(): it does something nasty to 3476*edd16368SStephen M. Cameron * Smart Array controllers that pci_enable_device does not undo 3477*edd16368SStephen M. Cameron */ 3478*edd16368SStephen M. Cameron pci_release_regions(pdev); 3479*edd16368SStephen M. Cameron pci_set_drvdata(pdev, NULL); 3480*edd16368SStephen M. Cameron mutex_unlock(&h->busy_shutting_down); 3481*edd16368SStephen M. Cameron kfree(h); 3482*edd16368SStephen M. Cameron } 3483*edd16368SStephen M. Cameron 3484*edd16368SStephen M. Cameron static int hpsa_suspend(__attribute__((unused)) struct pci_dev *pdev, 3485*edd16368SStephen M. Cameron __attribute__((unused)) pm_message_t state) 3486*edd16368SStephen M. Cameron { 3487*edd16368SStephen M. Cameron return -ENOSYS; 3488*edd16368SStephen M. Cameron } 3489*edd16368SStephen M. Cameron 3490*edd16368SStephen M. Cameron static int hpsa_resume(__attribute__((unused)) struct pci_dev *pdev) 3491*edd16368SStephen M. Cameron { 3492*edd16368SStephen M. Cameron return -ENOSYS; 3493*edd16368SStephen M. Cameron } 3494*edd16368SStephen M. Cameron 3495*edd16368SStephen M. Cameron static struct pci_driver hpsa_pci_driver = { 3496*edd16368SStephen M. Cameron .name = "hpsa", 3497*edd16368SStephen M. Cameron .probe = hpsa_init_one, 3498*edd16368SStephen M. Cameron .remove = __devexit_p(hpsa_remove_one), 3499*edd16368SStephen M. Cameron .id_table = hpsa_pci_device_id, /* id_table */ 3500*edd16368SStephen M. Cameron .shutdown = hpsa_shutdown, 3501*edd16368SStephen M. Cameron .suspend = hpsa_suspend, 3502*edd16368SStephen M. Cameron .resume = hpsa_resume, 3503*edd16368SStephen M. Cameron }; 3504*edd16368SStephen M. Cameron 3505*edd16368SStephen M. Cameron /* 3506*edd16368SStephen M. Cameron * This is it. Register the PCI driver information for the cards we control 3507*edd16368SStephen M. Cameron * the OS will call our registered routines when it finds one of our cards. 3508*edd16368SStephen M. Cameron */ 3509*edd16368SStephen M. Cameron static int __init hpsa_init(void) 3510*edd16368SStephen M. Cameron { 3511*edd16368SStephen M. Cameron int err; 3512*edd16368SStephen M. Cameron /* Start the scan thread */ 3513*edd16368SStephen M. Cameron hpsa_scan_thread = kthread_run(hpsa_scan_func, NULL, "hpsa_scan"); 3514*edd16368SStephen M. Cameron if (IS_ERR(hpsa_scan_thread)) { 3515*edd16368SStephen M. Cameron err = PTR_ERR(hpsa_scan_thread); 3516*edd16368SStephen M. Cameron return -ENODEV; 3517*edd16368SStephen M. Cameron } 3518*edd16368SStephen M. Cameron err = pci_register_driver(&hpsa_pci_driver); 3519*edd16368SStephen M. Cameron if (err) 3520*edd16368SStephen M. Cameron kthread_stop(hpsa_scan_thread); 3521*edd16368SStephen M. Cameron return err; 3522*edd16368SStephen M. Cameron } 3523*edd16368SStephen M. Cameron 3524*edd16368SStephen M. Cameron static void __exit hpsa_cleanup(void) 3525*edd16368SStephen M. Cameron { 3526*edd16368SStephen M. Cameron pci_unregister_driver(&hpsa_pci_driver); 3527*edd16368SStephen M. Cameron kthread_stop(hpsa_scan_thread); 3528*edd16368SStephen M. Cameron } 3529*edd16368SStephen M. Cameron 3530*edd16368SStephen M. Cameron module_init(hpsa_init); 3531*edd16368SStephen M. Cameron module_exit(hpsa_cleanup); 3532