/* * Disk Array driver for HP Smart Array SAS controllers * Copyright 2000, 2014 Hewlett-Packard Development Company, L.P. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or * NON INFRINGEMENT. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Questions/Comments/Bugfixes to iss_storagedev@hp.com * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "hpsa_cmd.h" #include "hpsa.h" /* HPSA_DRIVER_VERSION must be 3 byte values (0-255) separated by '.' */ #define HPSA_DRIVER_VERSION "3.4.4-1" #define DRIVER_NAME "HP HPSA Driver (v " HPSA_DRIVER_VERSION ")" #define HPSA "hpsa" /* How long to wait (in milliseconds) for board to go into simple mode */ #define MAX_CONFIG_WAIT 30000 #define MAX_IOCTL_CONFIG_WAIT 1000 /*define how many times we will try a command because of bus resets */ #define MAX_CMD_RETRIES 3 /* Embedded module documentation macros - see modules.h */ MODULE_AUTHOR("Hewlett-Packard Company"); MODULE_DESCRIPTION("Driver for HP Smart Array Controller version " \ HPSA_DRIVER_VERSION); MODULE_SUPPORTED_DEVICE("HP Smart Array Controllers"); MODULE_VERSION(HPSA_DRIVER_VERSION); MODULE_LICENSE("GPL"); static int hpsa_allow_any; module_param(hpsa_allow_any, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(hpsa_allow_any, "Allow hpsa driver to access unknown HP Smart Array hardware"); static int hpsa_simple_mode; module_param(hpsa_simple_mode, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(hpsa_simple_mode, "Use 'simple mode' rather than 'performant mode'"); /* define the PCI info for the cards we can control */ static const struct pci_device_id hpsa_pci_device_id[] = { {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3241}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3243}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3245}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3247}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3249}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x324A}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x324B}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3233}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSF, 0x103C, 0x3350}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSF, 0x103C, 0x3351}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSF, 0x103C, 0x3352}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSF, 0x103C, 0x3353}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSF, 0x103C, 0x3354}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSF, 0x103C, 0x3355}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSF, 0x103C, 0x3356}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1921}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1922}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1923}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1924}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1925}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1926}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1928}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1929}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSI, 0x103C, 0x21BD}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSI, 0x103C, 0x21BE}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSI, 0x103C, 0x21BF}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSI, 0x103C, 0x21C0}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSI, 0x103C, 0x21C1}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSI, 0x103C, 0x21C2}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSI, 0x103C, 0x21C3}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSI, 0x103C, 0x21C4}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSI, 0x103C, 0x21C5}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSI, 0x103C, 0x21C7}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSI, 0x103C, 0x21C8}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSI, 0x103C, 0x21C9}, {PCI_VENDOR_ID_HP_3PAR, 0x0075, 0x1590, 0x0076}, {PCI_VENDOR_ID_HP_3PAR, 0x0075, 0x1590, 0x0087}, {PCI_VENDOR_ID_HP_3PAR, 0x0075, 0x1590, 0x007D}, {PCI_VENDOR_ID_HP_3PAR, 0x0075, 0x1590, 0x0088}, {PCI_VENDOR_ID_HP, 0x333f, 0x103c, 0x333f}, {PCI_VENDOR_ID_HP, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_RAID << 8, 0xffff << 8, 0}, {0,} }; MODULE_DEVICE_TABLE(pci, hpsa_pci_device_id); /* board_id = Subsystem Device ID & Vendor ID * product = Marketing Name for the board * access = Address of the struct of function pointers */ static struct board_type products[] = { {0x3241103C, "Smart Array P212", &SA5_access}, {0x3243103C, "Smart Array P410", &SA5_access}, {0x3245103C, "Smart Array P410i", &SA5_access}, {0x3247103C, "Smart Array P411", &SA5_access}, {0x3249103C, "Smart Array P812", &SA5_access}, {0x324A103C, "Smart Array P712m", &SA5_access}, {0x324B103C, "Smart Array P711m", &SA5_access}, {0x3350103C, "Smart Array P222", &SA5_access}, {0x3351103C, "Smart Array P420", &SA5_access}, {0x3352103C, "Smart Array P421", &SA5_access}, {0x3353103C, "Smart Array P822", &SA5_access}, {0x3354103C, "Smart Array P420i", &SA5_access}, {0x3355103C, "Smart Array P220i", &SA5_access}, {0x3356103C, "Smart Array P721m", &SA5_access}, {0x1921103C, "Smart Array P830i", &SA5_access}, {0x1922103C, "Smart Array P430", &SA5_access}, {0x1923103C, "Smart Array P431", &SA5_access}, {0x1924103C, "Smart Array P830", &SA5_access}, {0x1926103C, "Smart Array P731m", &SA5_access}, {0x1928103C, "Smart Array P230i", &SA5_access}, {0x1929103C, "Smart Array P530", &SA5_access}, {0x21BD103C, "Smart Array", &SA5_access}, {0x21BE103C, "Smart Array", &SA5_access}, {0x21BF103C, "Smart Array", &SA5_access}, {0x21C0103C, "Smart Array", &SA5_access}, {0x21C1103C, "Smart Array", &SA5_access}, {0x21C2103C, "Smart Array", &SA5_access}, {0x21C3103C, "Smart Array", &SA5_access}, {0x21C4103C, "Smart Array", &SA5_access}, {0x21C5103C, "Smart Array", &SA5_access}, {0x21C7103C, "Smart Array", &SA5_access}, {0x21C8103C, "Smart Array", &SA5_access}, {0x21C9103C, "Smart Array", &SA5_access}, {0x00761590, "HP Storage P1224 Array Controller", &SA5_access}, {0x00871590, "HP Storage P1224e Array Controller", &SA5_access}, {0x007D1590, "HP Storage P1228 Array Controller", &SA5_access}, {0x00881590, "HP Storage P1228e Array Controller", &SA5_access}, {0x333f103c, "HP StorageWorks 1210m Array Controller", &SA5_access}, {0xFFFF103C, "Unknown Smart Array", &SA5_access}, }; static int number_of_controllers; static irqreturn_t do_hpsa_intr_intx(int irq, void *dev_id); static irqreturn_t do_hpsa_intr_msi(int irq, void *dev_id); static int hpsa_ioctl(struct scsi_device *dev, int cmd, void *arg); static void start_io(struct ctlr_info *h); #ifdef CONFIG_COMPAT static int hpsa_compat_ioctl(struct scsi_device *dev, int cmd, void *arg); #endif static void cmd_free(struct ctlr_info *h, struct CommandList *c); static void cmd_special_free(struct ctlr_info *h, struct CommandList *c); static struct CommandList *cmd_alloc(struct ctlr_info *h); static struct CommandList *cmd_special_alloc(struct ctlr_info *h); static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h, void *buff, size_t size, u16 page_code, unsigned char *scsi3addr, int cmd_type); #define VPD_PAGE (1 << 8) static int hpsa_scsi_queue_command(struct Scsi_Host *h, struct scsi_cmnd *cmd); static void hpsa_scan_start(struct Scsi_Host *); static int hpsa_scan_finished(struct Scsi_Host *sh, unsigned long elapsed_time); static int hpsa_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason); static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd); static int hpsa_eh_abort_handler(struct scsi_cmnd *scsicmd); static int hpsa_slave_alloc(struct scsi_device *sdev); static void hpsa_slave_destroy(struct scsi_device *sdev); static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno); static int check_for_unit_attention(struct ctlr_info *h, struct CommandList *c); static void check_ioctl_unit_attention(struct ctlr_info *h, struct CommandList *c); /* performant mode helper functions */ static void calc_bucket_map(int *bucket, int num_buckets, int nsgs, int min_blocks, int *bucket_map); static void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h); static inline u32 next_command(struct ctlr_info *h, u8 q); static int hpsa_find_cfg_addrs(struct pci_dev *pdev, void __iomem *vaddr, u32 *cfg_base_addr, u64 *cfg_base_addr_index, u64 *cfg_offset); static int hpsa_pci_find_memory_BAR(struct pci_dev *pdev, unsigned long *memory_bar); static int hpsa_lookup_board_id(struct pci_dev *pdev, u32 *board_id); static int hpsa_wait_for_board_state(struct pci_dev *pdev, void __iomem *vaddr, int wait_for_ready); static inline void finish_cmd(struct CommandList *c); static void hpsa_wait_for_mode_change_ack(struct ctlr_info *h); #define BOARD_NOT_READY 0 #define BOARD_READY 1 static void hpsa_drain_accel_commands(struct ctlr_info *h); static void hpsa_flush_cache(struct ctlr_info *h); static int hpsa_scsi_ioaccel_queue_command(struct ctlr_info *h, struct CommandList *c, u32 ioaccel_handle, u8 *cdb, int cdb_len, u8 *scsi3addr); static inline struct ctlr_info *sdev_to_hba(struct scsi_device *sdev) { unsigned long *priv = shost_priv(sdev->host); return (struct ctlr_info *) *priv; } static inline struct ctlr_info *shost_to_hba(struct Scsi_Host *sh) { unsigned long *priv = shost_priv(sh); return (struct ctlr_info *) *priv; } static int check_for_unit_attention(struct ctlr_info *h, struct CommandList *c) { if (c->err_info->SenseInfo[2] != UNIT_ATTENTION) return 0; switch (c->err_info->SenseInfo[12]) { case STATE_CHANGED: dev_warn(&h->pdev->dev, HPSA "%d: a state change " "detected, command retried\n", h->ctlr); break; case LUN_FAILED: dev_warn(&h->pdev->dev, HPSA "%d: LUN failure " "detected, action required\n", h->ctlr); break; case REPORT_LUNS_CHANGED: dev_warn(&h->pdev->dev, HPSA "%d: report LUN data " "changed, action required\n", h->ctlr); /* * Note: this REPORT_LUNS_CHANGED condition only occurs on the external * target (array) devices. */ break; case POWER_OR_RESET: dev_warn(&h->pdev->dev, HPSA "%d: a power on " "or device reset detected\n", h->ctlr); break; case UNIT_ATTENTION_CLEARED: dev_warn(&h->pdev->dev, HPSA "%d: unit attention " "cleared by another initiator\n", h->ctlr); break; default: dev_warn(&h->pdev->dev, HPSA "%d: unknown " "unit attention detected\n", h->ctlr); break; } return 1; } static int check_for_busy(struct ctlr_info *h, struct CommandList *c) { if (c->err_info->CommandStatus != CMD_TARGET_STATUS || (c->err_info->ScsiStatus != SAM_STAT_BUSY && c->err_info->ScsiStatus != SAM_STAT_TASK_SET_FULL)) return 0; dev_warn(&h->pdev->dev, HPSA "device busy"); return 1; } static ssize_t host_store_hp_ssd_smart_path_status(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int status, len; struct ctlr_info *h; struct Scsi_Host *shost = class_to_shost(dev); char tmpbuf[10]; if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) return -EACCES; len = count > sizeof(tmpbuf) - 1 ? sizeof(tmpbuf) - 1 : count; strncpy(tmpbuf, buf, len); tmpbuf[len] = '\0'; if (sscanf(tmpbuf, "%d", &status) != 1) return -EINVAL; h = shost_to_hba(shost); h->acciopath_status = !!status; dev_warn(&h->pdev->dev, "hpsa: HP SSD Smart Path %s via sysfs update.\n", h->acciopath_status ? "enabled" : "disabled"); return count; } static ssize_t host_store_raid_offload_debug(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int debug_level, len; struct ctlr_info *h; struct Scsi_Host *shost = class_to_shost(dev); char tmpbuf[10]; if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) return -EACCES; len = count > sizeof(tmpbuf) - 1 ? sizeof(tmpbuf) - 1 : count; strncpy(tmpbuf, buf, len); tmpbuf[len] = '\0'; if (sscanf(tmpbuf, "%d", &debug_level) != 1) return -EINVAL; if (debug_level < 0) debug_level = 0; h = shost_to_hba(shost); h->raid_offload_debug = debug_level; dev_warn(&h->pdev->dev, "hpsa: Set raid_offload_debug level = %d\n", h->raid_offload_debug); return count; } static ssize_t host_store_rescan(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct ctlr_info *h; struct Scsi_Host *shost = class_to_shost(dev); h = shost_to_hba(shost); hpsa_scan_start(h->scsi_host); return count; } static ssize_t host_show_firmware_revision(struct device *dev, struct device_attribute *attr, char *buf) { struct ctlr_info *h; struct Scsi_Host *shost = class_to_shost(dev); unsigned char *fwrev; h = shost_to_hba(shost); if (!h->hba_inquiry_data) return 0; fwrev = &h->hba_inquiry_data[32]; return snprintf(buf, 20, "%c%c%c%c\n", fwrev[0], fwrev[1], fwrev[2], fwrev[3]); } static ssize_t host_show_commands_outstanding(struct device *dev, struct device_attribute *attr, char *buf) { struct Scsi_Host *shost = class_to_shost(dev); struct ctlr_info *h = shost_to_hba(shost); return snprintf(buf, 20, "%d\n", h->commands_outstanding); } static ssize_t host_show_transport_mode(struct device *dev, struct device_attribute *attr, char *buf) { struct ctlr_info *h; struct Scsi_Host *shost = class_to_shost(dev); h = shost_to_hba(shost); return snprintf(buf, 20, "%s\n", h->transMethod & CFGTBL_Trans_Performant ? "performant" : "simple"); } static ssize_t host_show_hp_ssd_smart_path_status(struct device *dev, struct device_attribute *attr, char *buf) { struct ctlr_info *h; struct Scsi_Host *shost = class_to_shost(dev); h = shost_to_hba(shost); return snprintf(buf, 30, "HP SSD Smart Path %s\n", (h->acciopath_status == 1) ? "enabled" : "disabled"); } /* List of controllers which cannot be hard reset on kexec with reset_devices */ static u32 unresettable_controller[] = { 0x324a103C, /* Smart Array P712m */ 0x324b103C, /* SmartArray P711m */ 0x3223103C, /* Smart Array P800 */ 0x3234103C, /* Smart Array P400 */ 0x3235103C, /* Smart Array P400i */ 0x3211103C, /* Smart Array E200i */ 0x3212103C, /* Smart Array E200 */ 0x3213103C, /* Smart Array E200i */ 0x3214103C, /* Smart Array E200i */ 0x3215103C, /* Smart Array E200i */ 0x3237103C, /* Smart Array E500 */ 0x323D103C, /* Smart Array P700m */ 0x40800E11, /* Smart Array 5i */ 0x409C0E11, /* Smart Array 6400 */ 0x409D0E11, /* Smart Array 6400 EM */ 0x40700E11, /* Smart Array 5300 */ 0x40820E11, /* Smart Array 532 */ 0x40830E11, /* Smart Array 5312 */ 0x409A0E11, /* Smart Array 641 */ 0x409B0E11, /* Smart Array 642 */ 0x40910E11, /* Smart Array 6i */ }; /* List of controllers which cannot even be soft reset */ static u32 soft_unresettable_controller[] = { 0x40800E11, /* Smart Array 5i */ 0x40700E11, /* Smart Array 5300 */ 0x40820E11, /* Smart Array 532 */ 0x40830E11, /* Smart Array 5312 */ 0x409A0E11, /* Smart Array 641 */ 0x409B0E11, /* Smart Array 642 */ 0x40910E11, /* Smart Array 6i */ /* Exclude 640x boards. These are two pci devices in one slot * which share a battery backed cache module. One controls the * cache, the other accesses the cache through the one that controls * it. If we reset the one controlling the cache, the other will * likely not be happy. Just forbid resetting this conjoined mess. * The 640x isn't really supported by hpsa anyway. */ 0x409C0E11, /* Smart Array 6400 */ 0x409D0E11, /* Smart Array 6400 EM */ }; static int ctlr_is_hard_resettable(u32 board_id) { int i; for (i = 0; i < ARRAY_SIZE(unresettable_controller); i++) if (unresettable_controller[i] == board_id) return 0; return 1; } static int ctlr_is_soft_resettable(u32 board_id) { int i; for (i = 0; i < ARRAY_SIZE(soft_unresettable_controller); i++) if (soft_unresettable_controller[i] == board_id) return 0; return 1; } static int ctlr_is_resettable(u32 board_id) { return ctlr_is_hard_resettable(board_id) || ctlr_is_soft_resettable(board_id); } static ssize_t host_show_resettable(struct device *dev, struct device_attribute *attr, char *buf) { struct ctlr_info *h; struct Scsi_Host *shost = class_to_shost(dev); h = shost_to_hba(shost); return snprintf(buf, 20, "%d\n", ctlr_is_resettable(h->board_id)); } static inline int is_logical_dev_addr_mode(unsigned char scsi3addr[]) { return (scsi3addr[3] & 0xC0) == 0x40; } static const char *raid_label[] = { "0", "4", "1(1+0)", "5", "5+1", "ADG", "1(ADM)", "UNKNOWN" }; #define HPSA_RAID_0 0 #define HPSA_RAID_4 1 #define HPSA_RAID_1 2 /* also used for RAID 10 */ #define HPSA_RAID_5 3 /* also used for RAID 50 */ #define HPSA_RAID_51 4 #define HPSA_RAID_6 5 /* also used for RAID 60 */ #define HPSA_RAID_ADM 6 /* also used for RAID 1+0 ADM */ #define RAID_UNKNOWN (ARRAY_SIZE(raid_label) - 1) static ssize_t raid_level_show(struct device *dev, struct device_attribute *attr, char *buf) { ssize_t l = 0; unsigned char rlevel; struct ctlr_info *h; struct scsi_device *sdev; struct hpsa_scsi_dev_t *hdev; unsigned long flags; sdev = to_scsi_device(dev); h = sdev_to_hba(sdev); spin_lock_irqsave(&h->lock, flags); hdev = sdev->hostdata; if (!hdev) { spin_unlock_irqrestore(&h->lock, flags); return -ENODEV; } /* Is this even a logical drive? */ if (!is_logical_dev_addr_mode(hdev->scsi3addr)) { spin_unlock_irqrestore(&h->lock, flags); l = snprintf(buf, PAGE_SIZE, "N/A\n"); return l; } rlevel = hdev->raid_level; spin_unlock_irqrestore(&h->lock, flags); if (rlevel > RAID_UNKNOWN) rlevel = RAID_UNKNOWN; l = snprintf(buf, PAGE_SIZE, "RAID %s\n", raid_label[rlevel]); return l; } static ssize_t lunid_show(struct device *dev, struct device_attribute *attr, char *buf) { struct ctlr_info *h; struct scsi_device *sdev; struct hpsa_scsi_dev_t *hdev; unsigned long flags; unsigned char lunid[8]; sdev = to_scsi_device(dev); h = sdev_to_hba(sdev); spin_lock_irqsave(&h->lock, flags); hdev = sdev->hostdata; if (!hdev) { spin_unlock_irqrestore(&h->lock, flags); return -ENODEV; } memcpy(lunid, hdev->scsi3addr, sizeof(lunid)); spin_unlock_irqrestore(&h->lock, flags); return snprintf(buf, 20, "0x%02x%02x%02x%02x%02x%02x%02x%02x\n", lunid[0], lunid[1], lunid[2], lunid[3], lunid[4], lunid[5], lunid[6], lunid[7]); } static ssize_t unique_id_show(struct device *dev, struct device_attribute *attr, char *buf) { struct ctlr_info *h; struct scsi_device *sdev; struct hpsa_scsi_dev_t *hdev; unsigned long flags; unsigned char sn[16]; sdev = to_scsi_device(dev); h = sdev_to_hba(sdev); spin_lock_irqsave(&h->lock, flags); hdev = sdev->hostdata; if (!hdev) { spin_unlock_irqrestore(&h->lock, flags); return -ENODEV; } memcpy(sn, hdev->device_id, sizeof(sn)); spin_unlock_irqrestore(&h->lock, flags); return snprintf(buf, 16 * 2 + 2, "%02X%02X%02X%02X%02X%02X%02X%02X" "%02X%02X%02X%02X%02X%02X%02X%02X\n", sn[0], sn[1], sn[2], sn[3], sn[4], sn[5], sn[6], sn[7], sn[8], sn[9], sn[10], sn[11], sn[12], sn[13], sn[14], sn[15]); } static ssize_t host_show_hp_ssd_smart_path_enabled(struct device *dev, struct device_attribute *attr, char *buf) { struct ctlr_info *h; struct scsi_device *sdev; struct hpsa_scsi_dev_t *hdev; unsigned long flags; int offload_enabled; sdev = to_scsi_device(dev); h = sdev_to_hba(sdev); spin_lock_irqsave(&h->lock, flags); hdev = sdev->hostdata; if (!hdev) { spin_unlock_irqrestore(&h->lock, flags); return -ENODEV; } offload_enabled = hdev->offload_enabled; spin_unlock_irqrestore(&h->lock, flags); return snprintf(buf, 20, "%d\n", offload_enabled); } static DEVICE_ATTR(raid_level, S_IRUGO, raid_level_show, NULL); static DEVICE_ATTR(lunid, S_IRUGO, lunid_show, NULL); static DEVICE_ATTR(unique_id, S_IRUGO, unique_id_show, NULL); static DEVICE_ATTR(rescan, S_IWUSR, NULL, host_store_rescan); static DEVICE_ATTR(hp_ssd_smart_path_enabled, S_IRUGO, host_show_hp_ssd_smart_path_enabled, NULL); static DEVICE_ATTR(hp_ssd_smart_path_status, S_IWUSR|S_IRUGO|S_IROTH, host_show_hp_ssd_smart_path_status, host_store_hp_ssd_smart_path_status); static DEVICE_ATTR(raid_offload_debug, S_IWUSR, NULL, host_store_raid_offload_debug); static DEVICE_ATTR(firmware_revision, S_IRUGO, host_show_firmware_revision, NULL); static DEVICE_ATTR(commands_outstanding, S_IRUGO, host_show_commands_outstanding, NULL); static DEVICE_ATTR(transport_mode, S_IRUGO, host_show_transport_mode, NULL); static DEVICE_ATTR(resettable, S_IRUGO, host_show_resettable, NULL); static struct device_attribute *hpsa_sdev_attrs[] = { &dev_attr_raid_level, &dev_attr_lunid, &dev_attr_unique_id, &dev_attr_hp_ssd_smart_path_enabled, NULL, }; static struct device_attribute *hpsa_shost_attrs[] = { &dev_attr_rescan, &dev_attr_firmware_revision, &dev_attr_commands_outstanding, &dev_attr_transport_mode, &dev_attr_resettable, &dev_attr_hp_ssd_smart_path_status, &dev_attr_raid_offload_debug, NULL, }; static struct scsi_host_template hpsa_driver_template = { .module = THIS_MODULE, .name = HPSA, .proc_name = HPSA, .queuecommand = hpsa_scsi_queue_command, .scan_start = hpsa_scan_start, .scan_finished = hpsa_scan_finished, .change_queue_depth = hpsa_change_queue_depth, .this_id = -1, .use_clustering = ENABLE_CLUSTERING, .eh_abort_handler = hpsa_eh_abort_handler, .eh_device_reset_handler = hpsa_eh_device_reset_handler, .ioctl = hpsa_ioctl, .slave_alloc = hpsa_slave_alloc, .slave_destroy = hpsa_slave_destroy, #ifdef CONFIG_COMPAT .compat_ioctl = hpsa_compat_ioctl, #endif .sdev_attrs = hpsa_sdev_attrs, .shost_attrs = hpsa_shost_attrs, .max_sectors = 8192, .no_write_same = 1, }; /* Enqueuing and dequeuing functions for cmdlists. */ static inline void addQ(struct list_head *list, struct CommandList *c) { list_add_tail(&c->list, list); } static inline u32 next_command(struct ctlr_info *h, u8 q) { u32 a; struct reply_pool *rq = &h->reply_queue[q]; unsigned long flags; if (h->transMethod & CFGTBL_Trans_io_accel1) return h->access.command_completed(h, q); if (unlikely(!(h->transMethod & CFGTBL_Trans_Performant))) return h->access.command_completed(h, q); if ((rq->head[rq->current_entry] & 1) == rq->wraparound) { a = rq->head[rq->current_entry]; rq->current_entry++; spin_lock_irqsave(&h->lock, flags); h->commands_outstanding--; spin_unlock_irqrestore(&h->lock, flags); } else { a = FIFO_EMPTY; } /* Check for wraparound */ if (rq->current_entry == h->max_commands) { rq->current_entry = 0; rq->wraparound ^= 1; } return a; } /* * There are some special bits in the bus address of the * command that we have to set for the controller to know * how to process the command: * * Normal performant mode: * bit 0: 1 means performant mode, 0 means simple mode. * bits 1-3 = block fetch table entry * bits 4-6 = command type (== 0) * * ioaccel1 mode: * bit 0 = "performant mode" bit. * bits 1-3 = block fetch table entry * bits 4-6 = command type (== 110) * (command type is needed because ioaccel1 mode * commands are submitted through the same register as normal * mode commands, so this is how the controller knows whether * the command is normal mode or ioaccel1 mode.) * * ioaccel2 mode: * bit 0 = "performant mode" bit. * bits 1-4 = block fetch table entry (note extra bit) * bits 4-6 = not needed, because ioaccel2 mode has * a separate special register for submitting commands. */ /* set_performant_mode: Modify the tag for cciss performant * set bit 0 for pull model, bits 3-1 for block fetch * register number */ static void set_performant_mode(struct ctlr_info *h, struct CommandList *c) { if (likely(h->transMethod & CFGTBL_Trans_Performant)) { c->busaddr |= 1 | (h->blockFetchTable[c->Header.SGList] << 1); if (likely(h->msix_vector > 0)) c->Header.ReplyQueue = raw_smp_processor_id() % h->nreply_queues; } } static void set_ioaccel1_performant_mode(struct ctlr_info *h, struct CommandList *c) { struct io_accel1_cmd *cp = &h->ioaccel_cmd_pool[c->cmdindex]; /* Tell the controller to post the reply to the queue for this * processor. This seems to give the best I/O throughput. */ cp->ReplyQueue = smp_processor_id() % h->nreply_queues; /* Set the bits in the address sent down to include: * - performant mode bit (bit 0) * - pull count (bits 1-3) * - command type (bits 4-6) */ c->busaddr |= 1 | (h->ioaccel1_blockFetchTable[c->Header.SGList] << 1) | IOACCEL1_BUSADDR_CMDTYPE; } static void set_ioaccel2_performant_mode(struct ctlr_info *h, struct CommandList *c) { struct io_accel2_cmd *cp = &h->ioaccel2_cmd_pool[c->cmdindex]; /* Tell the controller to post the reply to the queue for this * processor. This seems to give the best I/O throughput. */ cp->reply_queue = smp_processor_id() % h->nreply_queues; /* Set the bits in the address sent down to include: * - performant mode bit not used in ioaccel mode 2 * - pull count (bits 0-3) * - command type isn't needed for ioaccel2 */ c->busaddr |= (h->ioaccel2_blockFetchTable[cp->sg_count]); } static int is_firmware_flash_cmd(u8 *cdb) { return cdb[0] == BMIC_WRITE && cdb[6] == BMIC_FLASH_FIRMWARE; } /* * During firmware flash, the heartbeat register may not update as frequently * as it should. So we dial down lockup detection during firmware flash. and * dial it back up when firmware flash completes. */ #define HEARTBEAT_SAMPLE_INTERVAL_DURING_FLASH (240 * HZ) #define HEARTBEAT_SAMPLE_INTERVAL (30 * HZ) static void dial_down_lockup_detection_during_fw_flash(struct ctlr_info *h, struct CommandList *c) { if (!is_firmware_flash_cmd(c->Request.CDB)) return; atomic_inc(&h->firmware_flash_in_progress); h->heartbeat_sample_interval = HEARTBEAT_SAMPLE_INTERVAL_DURING_FLASH; } static void dial_up_lockup_detection_on_fw_flash_complete(struct ctlr_info *h, struct CommandList *c) { if (is_firmware_flash_cmd(c->Request.CDB) && atomic_dec_and_test(&h->firmware_flash_in_progress)) h->heartbeat_sample_interval = HEARTBEAT_SAMPLE_INTERVAL; } static void enqueue_cmd_and_start_io(struct ctlr_info *h, struct CommandList *c) { unsigned long flags; switch (c->cmd_type) { case CMD_IOACCEL1: set_ioaccel1_performant_mode(h, c); break; case CMD_IOACCEL2: set_ioaccel2_performant_mode(h, c); break; default: set_performant_mode(h, c); } dial_down_lockup_detection_during_fw_flash(h, c); spin_lock_irqsave(&h->lock, flags); addQ(&h->reqQ, c); h->Qdepth++; spin_unlock_irqrestore(&h->lock, flags); start_io(h); } static inline void removeQ(struct CommandList *c) { if (WARN_ON(list_empty(&c->list))) return; list_del_init(&c->list); } static inline int is_hba_lunid(unsigned char scsi3addr[]) { return memcmp(scsi3addr, RAID_CTLR_LUNID, 8) == 0; } static inline int is_scsi_rev_5(struct ctlr_info *h) { if (!h->hba_inquiry_data) return 0; if ((h->hba_inquiry_data[2] & 0x07) == 5) return 1; return 0; } static int hpsa_find_target_lun(struct ctlr_info *h, unsigned char scsi3addr[], int bus, int *target, int *lun) { /* finds an unused bus, target, lun for a new physical device * assumes h->devlock is held */ int i, found = 0; DECLARE_BITMAP(lun_taken, HPSA_MAX_DEVICES); bitmap_zero(lun_taken, HPSA_MAX_DEVICES); for (i = 0; i < h->ndevices; i++) { if (h->dev[i]->bus == bus && h->dev[i]->target != -1) __set_bit(h->dev[i]->target, lun_taken); } i = find_first_zero_bit(lun_taken, HPSA_MAX_DEVICES); if (i < HPSA_MAX_DEVICES) { /* *bus = 1; */ *target = i; *lun = 0; found = 1; } return !found; } /* Add an entry into h->dev[] array. */ static int hpsa_scsi_add_entry(struct ctlr_info *h, int hostno, struct hpsa_scsi_dev_t *device, struct hpsa_scsi_dev_t *added[], int *nadded) { /* assumes h->devlock is held */ int n = h->ndevices; int i; unsigned char addr1[8], addr2[8]; struct hpsa_scsi_dev_t *sd; if (n >= HPSA_MAX_DEVICES) { dev_err(&h->pdev->dev, "too many devices, some will be " "inaccessible.\n"); return -1; } /* physical devices do not have lun or target assigned until now. */ if (device->lun != -1) /* Logical device, lun is already assigned. */ goto lun_assigned; /* If this device a non-zero lun of a multi-lun device * byte 4 of the 8-byte LUN addr will contain the logical * unit no, zero otherise. */ if (device->scsi3addr[4] == 0) { /* This is not a non-zero lun of a multi-lun device */ if (hpsa_find_target_lun(h, device->scsi3addr, device->bus, &device->target, &device->lun) != 0) return -1; goto lun_assigned; } /* This is a non-zero lun of a multi-lun device. * Search through our list and find the device which * has the same 8 byte LUN address, excepting byte 4. * Assign the same bus and target for this new LUN. * Use the logical unit number from the firmware. */ memcpy(addr1, device->scsi3addr, 8); addr1[4] = 0; for (i = 0; i < n; i++) { sd = h->dev[i]; memcpy(addr2, sd->scsi3addr, 8); addr2[4] = 0; /* differ only in byte 4? */ if (memcmp(addr1, addr2, 8) == 0) { device->bus = sd->bus; device->target = sd->target; device->lun = device->scsi3addr[4]; break; } } if (device->lun == -1) { dev_warn(&h->pdev->dev, "physical device with no LUN=0," " suspect firmware bug or unsupported hardware " "configuration.\n"); return -1; } lun_assigned: h->dev[n] = device; h->ndevices++; added[*nadded] = device; (*nadded)++; /* initially, (before registering with scsi layer) we don't * know our hostno and we don't want to print anything first * time anyway (the scsi layer's inquiries will show that info) */ /* if (hostno != -1) */ dev_info(&h->pdev->dev, "%s device c%db%dt%dl%d added.\n", scsi_device_type(device->devtype), hostno, device->bus, device->target, device->lun); return 0; } /* Update an entry in h->dev[] array. */ static void hpsa_scsi_update_entry(struct ctlr_info *h, int hostno, int entry, struct hpsa_scsi_dev_t *new_entry) { /* assumes h->devlock is held */ BUG_ON(entry < 0 || entry >= HPSA_MAX_DEVICES); /* Raid level changed. */ h->dev[entry]->raid_level = new_entry->raid_level; /* Raid offload parameters changed. */ h->dev[entry]->offload_config = new_entry->offload_config; h->dev[entry]->offload_enabled = new_entry->offload_enabled; h->dev[entry]->ioaccel_handle = new_entry->ioaccel_handle; h->dev[entry]->offload_to_mirror = new_entry->offload_to_mirror; h->dev[entry]->raid_map = new_entry->raid_map; dev_info(&h->pdev->dev, "%s device c%db%dt%dl%d updated.\n", scsi_device_type(new_entry->devtype), hostno, new_entry->bus, new_entry->target, new_entry->lun); } /* Replace an entry from h->dev[] array. */ static void hpsa_scsi_replace_entry(struct ctlr_info *h, int hostno, int entry, struct hpsa_scsi_dev_t *new_entry, struct hpsa_scsi_dev_t *added[], int *nadded, struct hpsa_scsi_dev_t *removed[], int *nremoved) { /* assumes h->devlock is held */ BUG_ON(entry < 0 || entry >= HPSA_MAX_DEVICES); removed[*nremoved] = h->dev[entry]; (*nremoved)++; /* * New physical devices won't have target/lun assigned yet * so we need to preserve the values in the slot we are replacing. */ if (new_entry->target == -1) { new_entry->target = h->dev[entry]->target; new_entry->lun = h->dev[entry]->lun; } h->dev[entry] = new_entry; added[*nadded] = new_entry; (*nadded)++; dev_info(&h->pdev->dev, "%s device c%db%dt%dl%d changed.\n", scsi_device_type(new_entry->devtype), hostno, new_entry->bus, new_entry->target, new_entry->lun); } /* Remove an entry from h->dev[] array. */ static void hpsa_scsi_remove_entry(struct ctlr_info *h, int hostno, int entry, struct hpsa_scsi_dev_t *removed[], int *nremoved) { /* assumes h->devlock is held */ int i; struct hpsa_scsi_dev_t *sd; BUG_ON(entry < 0 || entry >= HPSA_MAX_DEVICES); sd = h->dev[entry]; removed[*nremoved] = h->dev[entry]; (*nremoved)++; for (i = entry; i < h->ndevices-1; i++) h->dev[i] = h->dev[i+1]; h->ndevices--; dev_info(&h->pdev->dev, "%s device c%db%dt%dl%d removed.\n", scsi_device_type(sd->devtype), hostno, sd->bus, sd->target, sd->lun); } #define SCSI3ADDR_EQ(a, b) ( \ (a)[7] == (b)[7] && \ (a)[6] == (b)[6] && \ (a)[5] == (b)[5] && \ (a)[4] == (b)[4] && \ (a)[3] == (b)[3] && \ (a)[2] == (b)[2] && \ (a)[1] == (b)[1] && \ (a)[0] == (b)[0]) static void fixup_botched_add(struct ctlr_info *h, struct hpsa_scsi_dev_t *added) { /* called when scsi_add_device fails in order to re-adjust * h->dev[] to match the mid layer's view. */ unsigned long flags; int i, j; spin_lock_irqsave(&h->lock, flags); for (i = 0; i < h->ndevices; i++) { if (h->dev[i] == added) { for (j = i; j < h->ndevices-1; j++) h->dev[j] = h->dev[j+1]; h->ndevices--; break; } } spin_unlock_irqrestore(&h->lock, flags); kfree(added); } static inline int device_is_the_same(struct hpsa_scsi_dev_t *dev1, struct hpsa_scsi_dev_t *dev2) { /* we compare everything except lun and target as these * are not yet assigned. Compare parts likely * to differ first */ if (memcmp(dev1->scsi3addr, dev2->scsi3addr, sizeof(dev1->scsi3addr)) != 0) return 0; if (memcmp(dev1->device_id, dev2->device_id, sizeof(dev1->device_id)) != 0) return 0; if (memcmp(dev1->model, dev2->model, sizeof(dev1->model)) != 0) return 0; if (memcmp(dev1->vendor, dev2->vendor, sizeof(dev1->vendor)) != 0) return 0; if (dev1->devtype != dev2->devtype) return 0; if (dev1->bus != dev2->bus) return 0; return 1; } static inline int device_updated(struct hpsa_scsi_dev_t *dev1, struct hpsa_scsi_dev_t *dev2) { /* Device attributes that can change, but don't mean * that the device is a different device, nor that the OS * needs to be told anything about the change. */ if (dev1->raid_level != dev2->raid_level) return 1; if (dev1->offload_config != dev2->offload_config) return 1; if (dev1->offload_enabled != dev2->offload_enabled) return 1; return 0; } /* Find needle in haystack. If exact match found, return DEVICE_SAME, * and return needle location in *index. If scsi3addr matches, but not * vendor, model, serial num, etc. return DEVICE_CHANGED, and return needle * location in *index. * In the case of a minor device attribute change, such as RAID level, just * return DEVICE_UPDATED, along with the updated device's location in index. * If needle not found, return DEVICE_NOT_FOUND. */ static int hpsa_scsi_find_entry(struct hpsa_scsi_dev_t *needle, struct hpsa_scsi_dev_t *haystack[], int haystack_size, int *index) { int i; #define DEVICE_NOT_FOUND 0 #define DEVICE_CHANGED 1 #define DEVICE_SAME 2 #define DEVICE_UPDATED 3 for (i = 0; i < haystack_size; i++) { if (haystack[i] == NULL) /* previously removed. */ continue; if (SCSI3ADDR_EQ(needle->scsi3addr, haystack[i]->scsi3addr)) { *index = i; if (device_is_the_same(needle, haystack[i])) { if (device_updated(needle, haystack[i])) return DEVICE_UPDATED; return DEVICE_SAME; } else { /* Keep offline devices offline */ if (needle->volume_offline) return DEVICE_NOT_FOUND; return DEVICE_CHANGED; } } } *index = -1; return DEVICE_NOT_FOUND; } static void hpsa_monitor_offline_device(struct ctlr_info *h, unsigned char scsi3addr[]) { struct offline_device_entry *device; unsigned long flags; /* Check to see if device is already on the list */ spin_lock_irqsave(&h->offline_device_lock, flags); list_for_each_entry(device, &h->offline_device_list, offline_list) { if (memcmp(device->scsi3addr, scsi3addr, sizeof(device->scsi3addr)) == 0) { spin_unlock_irqrestore(&h->offline_device_lock, flags); return; } } spin_unlock_irqrestore(&h->offline_device_lock, flags); /* Device is not on the list, add it. */ device = kmalloc(sizeof(*device), GFP_KERNEL); if (!device) { dev_warn(&h->pdev->dev, "out of memory in %s\n", __func__); return; } memcpy(device->scsi3addr, scsi3addr, sizeof(device->scsi3addr)); spin_lock_irqsave(&h->offline_device_lock, flags); list_add_tail(&device->offline_list, &h->offline_device_list); spin_unlock_irqrestore(&h->offline_device_lock, flags); } /* Print a message explaining various offline volume states */ static void hpsa_show_volume_status(struct ctlr_info *h, struct hpsa_scsi_dev_t *sd) { if (sd->volume_offline == HPSA_VPD_LV_STATUS_UNSUPPORTED) dev_info(&h->pdev->dev, "C%d:B%d:T%d:L%d Volume status is not available through vital product data pages.\n", h->scsi_host->host_no, sd->bus, sd->target, sd->lun); switch (sd->volume_offline) { case HPSA_LV_OK: break; case HPSA_LV_UNDERGOING_ERASE: dev_info(&h->pdev->dev, "C%d:B%d:T%d:L%d Volume is undergoing background erase process.\n", h->scsi_host->host_no, sd->bus, sd->target, sd->lun); break; case HPSA_LV_UNDERGOING_RPI: dev_info(&h->pdev->dev, "C%d:B%d:T%d:L%d Volume is undergoing rapid parity initialization process.\n", h->scsi_host->host_no, sd->bus, sd->target, sd->lun); break; case HPSA_LV_PENDING_RPI: dev_info(&h->pdev->dev, "C%d:B%d:T%d:L%d Volume is queued for rapid parity initialization process.\n", h->scsi_host->host_no, sd->bus, sd->target, sd->lun); break; case HPSA_LV_ENCRYPTED_NO_KEY: dev_info(&h->pdev->dev, "C%d:B%d:T%d:L%d Volume is encrypted and cannot be accessed because key is not present.\n", h->scsi_host->host_no, sd->bus, sd->target, sd->lun); break; case HPSA_LV_PLAINTEXT_IN_ENCRYPT_ONLY_CONTROLLER: dev_info(&h->pdev->dev, "C%d:B%d:T%d:L%d Volume is not encrypted and cannot be accessed because controller is in encryption-only mode.\n", h->scsi_host->host_no, sd->bus, sd->target, sd->lun); break; case HPSA_LV_UNDERGOING_ENCRYPTION: dev_info(&h->pdev->dev, "C%d:B%d:T%d:L%d Volume is undergoing encryption process.\n", h->scsi_host->host_no, sd->bus, sd->target, sd->lun); break; case HPSA_LV_UNDERGOING_ENCRYPTION_REKEYING: dev_info(&h->pdev->dev, "C%d:B%d:T%d:L%d Volume is undergoing encryption re-keying process.\n", h->scsi_host->host_no, sd->bus, sd->target, sd->lun); break; case HPSA_LV_ENCRYPTED_IN_NON_ENCRYPTED_CONTROLLER: dev_info(&h->pdev->dev, "C%d:B%d:T%d:L%d Volume is encrypted and cannot be accessed because controller does not have encryption enabled.\n", h->scsi_host->host_no, sd->bus, sd->target, sd->lun); break; case HPSA_LV_PENDING_ENCRYPTION: dev_info(&h->pdev->dev, "C%d:B%d:T%d:L%d Volume is pending migration to encrypted state, but process has not started.\n", h->scsi_host->host_no, sd->bus, sd->target, sd->lun); break; case HPSA_LV_PENDING_ENCRYPTION_REKEYING: dev_info(&h->pdev->dev, "C%d:B%d:T%d:L%d Volume is encrypted and is pending encryption rekeying.\n", h->scsi_host->host_no, sd->bus, sd->target, sd->lun); break; } } static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno, struct hpsa_scsi_dev_t *sd[], int nsds) { /* sd contains scsi3 addresses and devtypes, and inquiry * data. This function takes what's in sd to be the current * reality and updates h->dev[] to reflect that reality. */ int i, entry, device_change, changes = 0; struct hpsa_scsi_dev_t *csd; unsigned long flags; struct hpsa_scsi_dev_t **added, **removed; int nadded, nremoved; struct Scsi_Host *sh = NULL; added = kzalloc(sizeof(*added) * HPSA_MAX_DEVICES, GFP_KERNEL); removed = kzalloc(sizeof(*removed) * HPSA_MAX_DEVICES, GFP_KERNEL); if (!added || !removed) { dev_warn(&h->pdev->dev, "out of memory in " "adjust_hpsa_scsi_table\n"); goto free_and_out; } spin_lock_irqsave(&h->devlock, flags); /* find any devices in h->dev[] that are not in * sd[] and remove them from h->dev[], and for any * devices which have changed, remove the old device * info and add the new device info. * If minor device attributes change, just update * the existing device structure. */ i = 0; nremoved = 0; nadded = 0; while (i < h->ndevices) { csd = h->dev[i]; device_change = hpsa_scsi_find_entry(csd, sd, nsds, &entry); if (device_change == DEVICE_NOT_FOUND) { changes++; hpsa_scsi_remove_entry(h, hostno, i, removed, &nremoved); continue; /* remove ^^^, hence i not incremented */ } else if (device_change == DEVICE_CHANGED) { changes++; hpsa_scsi_replace_entry(h, hostno, i, sd[entry], added, &nadded, removed, &nremoved); /* Set it to NULL to prevent it from being freed * at the bottom of hpsa_update_scsi_devices() */ sd[entry] = NULL; } else if (device_change == DEVICE_UPDATED) { hpsa_scsi_update_entry(h, hostno, i, sd[entry]); } i++; } /* Now, make sure every device listed in sd[] is also * listed in h->dev[], adding them if they aren't found */ for (i = 0; i < nsds; i++) { if (!sd[i]) /* if already added above. */ continue; /* Don't add devices which are NOT READY, FORMAT IN PROGRESS * as the SCSI mid-layer does not handle such devices well. * It relentlessly loops sending TUR at 3Hz, then READ(10) * at 160Hz, and prevents the system from coming up. */ if (sd[i]->volume_offline) { hpsa_show_volume_status(h, sd[i]); dev_info(&h->pdev->dev, "c%db%dt%dl%d: temporarily offline\n", h->scsi_host->host_no, sd[i]->bus, sd[i]->target, sd[i]->lun); continue; } device_change = hpsa_scsi_find_entry(sd[i], h->dev, h->ndevices, &entry); if (device_change == DEVICE_NOT_FOUND) { changes++; if (hpsa_scsi_add_entry(h, hostno, sd[i], added, &nadded) != 0) break; sd[i] = NULL; /* prevent from being freed later. */ } else if (device_change == DEVICE_CHANGED) { /* should never happen... */ changes++; dev_warn(&h->pdev->dev, "device unexpectedly changed.\n"); /* but if it does happen, we just ignore that device */ } } spin_unlock_irqrestore(&h->devlock, flags); /* Monitor devices which are in one of several NOT READY states to be * brought online later. This must be done without holding h->devlock, * so don't touch h->dev[] */ for (i = 0; i < nsds; i++) { if (!sd[i]) /* if already added above. */ continue; if (sd[i]->volume_offline) hpsa_monitor_offline_device(h, sd[i]->scsi3addr); } /* Don't notify scsi mid layer of any changes the first time through * (or if there are no changes) scsi_scan_host will do it later the * first time through. */ if (hostno == -1 || !changes) goto free_and_out; sh = h->scsi_host; /* Notify scsi mid layer of any removed devices */ for (i = 0; i < nremoved; i++) { struct scsi_device *sdev = scsi_device_lookup(sh, removed[i]->bus, removed[i]->target, removed[i]->lun); if (sdev != NULL) { scsi_remove_device(sdev); scsi_device_put(sdev); } else { /* We don't expect to get here. * future cmds to this device will get selection * timeout as if the device was gone. */ dev_warn(&h->pdev->dev, "didn't find c%db%dt%dl%d " " for removal.", hostno, removed[i]->bus, removed[i]->target, removed[i]->lun); } kfree(removed[i]); removed[i] = NULL; } /* Notify scsi mid layer of any added devices */ for (i = 0; i < nadded; i++) { if (scsi_add_device(sh, added[i]->bus, added[i]->target, added[i]->lun) == 0) continue; dev_warn(&h->pdev->dev, "scsi_add_device c%db%dt%dl%d failed, " "device not added.\n", hostno, added[i]->bus, added[i]->target, added[i]->lun); /* now we have to remove it from h->dev, * since it didn't get added to scsi mid layer */ fixup_botched_add(h, added[i]); } free_and_out: kfree(added); kfree(removed); } /* * Lookup bus/target/lun and return corresponding struct hpsa_scsi_dev_t * * Assume's h->devlock is held. */ static struct hpsa_scsi_dev_t *lookup_hpsa_scsi_dev(struct ctlr_info *h, int bus, int target, int lun) { int i; struct hpsa_scsi_dev_t *sd; for (i = 0; i < h->ndevices; i++) { sd = h->dev[i]; if (sd->bus == bus && sd->target == target && sd->lun == lun) return sd; } return NULL; } /* link sdev->hostdata to our per-device structure. */ static int hpsa_slave_alloc(struct scsi_device *sdev) { struct hpsa_scsi_dev_t *sd; unsigned long flags; struct ctlr_info *h; h = sdev_to_hba(sdev); spin_lock_irqsave(&h->devlock, flags); sd = lookup_hpsa_scsi_dev(h, sdev_channel(sdev), sdev_id(sdev), sdev->lun); if (sd != NULL) sdev->hostdata = sd; spin_unlock_irqrestore(&h->devlock, flags); return 0; } static void hpsa_slave_destroy(struct scsi_device *sdev) { /* nothing to do. */ } static void hpsa_free_sg_chain_blocks(struct ctlr_info *h) { int i; if (!h->cmd_sg_list) return; for (i = 0; i < h->nr_cmds; i++) { kfree(h->cmd_sg_list[i]); h->cmd_sg_list[i] = NULL; } kfree(h->cmd_sg_list); h->cmd_sg_list = NULL; } static int hpsa_allocate_sg_chain_blocks(struct ctlr_info *h) { int i; if (h->chainsize <= 0) return 0; h->cmd_sg_list = kzalloc(sizeof(*h->cmd_sg_list) * h->nr_cmds, GFP_KERNEL); if (!h->cmd_sg_list) return -ENOMEM; for (i = 0; i < h->nr_cmds; i++) { h->cmd_sg_list[i] = kmalloc(sizeof(*h->cmd_sg_list[i]) * h->chainsize, GFP_KERNEL); if (!h->cmd_sg_list[i]) goto clean; } return 0; clean: hpsa_free_sg_chain_blocks(h); return -ENOMEM; } static int hpsa_map_sg_chain_block(struct ctlr_info *h, struct CommandList *c) { struct SGDescriptor *chain_sg, *chain_block; u64 temp64; chain_sg = &c->SG[h->max_cmd_sg_entries - 1]; chain_block = h->cmd_sg_list[c->cmdindex]; chain_sg->Ext = HPSA_SG_CHAIN; chain_sg->Len = sizeof(*chain_sg) * (c->Header.SGTotal - h->max_cmd_sg_entries); temp64 = pci_map_single(h->pdev, chain_block, chain_sg->Len, PCI_DMA_TODEVICE); if (dma_mapping_error(&h->pdev->dev, temp64)) { /* prevent subsequent unmapping */ chain_sg->Addr.lower = 0; chain_sg->Addr.upper = 0; return -1; } chain_sg->Addr.lower = (u32) (temp64 & 0x0FFFFFFFFULL); chain_sg->Addr.upper = (u32) ((temp64 >> 32) & 0x0FFFFFFFFULL); return 0; } static void hpsa_unmap_sg_chain_block(struct ctlr_info *h, struct CommandList *c) { struct SGDescriptor *chain_sg; union u64bit temp64; if (c->Header.SGTotal <= h->max_cmd_sg_entries) return; chain_sg = &c->SG[h->max_cmd_sg_entries - 1]; temp64.val32.lower = chain_sg->Addr.lower; temp64.val32.upper = chain_sg->Addr.upper; pci_unmap_single(h->pdev, temp64.val, chain_sg->Len, PCI_DMA_TODEVICE); } /* Decode the various types of errors on ioaccel2 path. * Return 1 for any error that should generate a RAID path retry. * Return 0 for errors that don't require a RAID path retry. */ static int handle_ioaccel_mode2_error(struct ctlr_info *h, struct CommandList *c, struct scsi_cmnd *cmd, struct io_accel2_cmd *c2) { int data_len; int retry = 0; switch (c2->error_data.serv_response) { case IOACCEL2_SERV_RESPONSE_COMPLETE: switch (c2->error_data.status) { case IOACCEL2_STATUS_SR_TASK_COMP_GOOD: break; case IOACCEL2_STATUS_SR_TASK_COMP_CHK_COND: dev_warn(&h->pdev->dev, "%s: task complete with check condition.\n", "HP SSD Smart Path"); if (c2->error_data.data_present != IOACCEL2_SENSE_DATA_PRESENT) break; /* copy the sense data */ data_len = c2->error_data.sense_data_len; if (data_len > SCSI_SENSE_BUFFERSIZE) data_len = SCSI_SENSE_BUFFERSIZE; if (data_len > sizeof(c2->error_data.sense_data_buff)) data_len = sizeof(c2->error_data.sense_data_buff); memcpy(cmd->sense_buffer, c2->error_data.sense_data_buff, data_len); cmd->result |= SAM_STAT_CHECK_CONDITION; retry = 1; break; case IOACCEL2_STATUS_SR_TASK_COMP_BUSY: dev_warn(&h->pdev->dev, "%s: task complete with BUSY status.\n", "HP SSD Smart Path"); retry = 1; break; case IOACCEL2_STATUS_SR_TASK_COMP_RES_CON: dev_warn(&h->pdev->dev, "%s: task complete with reservation conflict.\n", "HP SSD Smart Path"); retry = 1; break; case IOACCEL2_STATUS_SR_TASK_COMP_SET_FULL: /* Make scsi midlayer do unlimited retries */ cmd->result = DID_IMM_RETRY << 16; break; case IOACCEL2_STATUS_SR_TASK_COMP_ABORTED: dev_warn(&h->pdev->dev, "%s: task complete with aborted status.\n", "HP SSD Smart Path"); retry = 1; break; default: dev_warn(&h->pdev->dev, "%s: task complete with unrecognized status: 0x%02x\n", "HP SSD Smart Path", c2->error_data.status); retry = 1; break; } break; case IOACCEL2_SERV_RESPONSE_FAILURE: /* don't expect to get here. */ dev_warn(&h->pdev->dev, "unexpected delivery or target failure, status = 0x%02x\n", c2->error_data.status); retry = 1; break; case IOACCEL2_SERV_RESPONSE_TMF_COMPLETE: break; case IOACCEL2_SERV_RESPONSE_TMF_SUCCESS: break; case IOACCEL2_SERV_RESPONSE_TMF_REJECTED: dev_warn(&h->pdev->dev, "task management function rejected.\n"); retry = 1; break; case IOACCEL2_SERV_RESPONSE_TMF_WRONG_LUN: dev_warn(&h->pdev->dev, "task management function invalid LUN\n"); break; default: dev_warn(&h->pdev->dev, "%s: Unrecognized server response: 0x%02x\n", "HP SSD Smart Path", c2->error_data.serv_response); retry = 1; break; } return retry; /* retry on raid path? */ } static void process_ioaccel2_completion(struct ctlr_info *h, struct CommandList *c, struct scsi_cmnd *cmd, struct hpsa_scsi_dev_t *dev) { struct io_accel2_cmd *c2 = &h->ioaccel2_cmd_pool[c->cmdindex]; int raid_retry = 0; /* check for good status */ if (likely(c2->error_data.serv_response == 0 && c2->error_data.status == 0)) { cmd_free(h, c); cmd->scsi_done(cmd); return; } /* Any RAID offload error results in retry which will use * the normal I/O path so the controller can handle whatever's * wrong. */ if (is_logical_dev_addr_mode(dev->scsi3addr) && c2->error_data.serv_response == IOACCEL2_SERV_RESPONSE_FAILURE) { if (c2->error_data.status == IOACCEL2_STATUS_SR_IOACCEL_DISABLED) dev_warn(&h->pdev->dev, "%s: Path is unavailable, retrying on standard path.\n", "HP SSD Smart Path"); else dev_warn(&h->pdev->dev, "%s: Error 0x%02x, retrying on standard path.\n", "HP SSD Smart Path", c2->error_data.status); dev->offload_enabled = 0; h->drv_req_rescan = 1; /* schedule controller for a rescan */ cmd->result = DID_SOFT_ERROR << 16; cmd_free(h, c); cmd->scsi_done(cmd); return; } raid_retry = handle_ioaccel_mode2_error(h, c, cmd, c2); /* If error found, disable Smart Path, schedule a rescan, * and force a retry on the standard path. */ if (raid_retry) { dev_warn(&h->pdev->dev, "%s: Retrying on standard path.\n", "HP SSD Smart Path"); dev->offload_enabled = 0; /* Disable Smart Path */ h->drv_req_rescan = 1; /* schedule controller rescan */ cmd->result = DID_SOFT_ERROR << 16; } cmd_free(h, c); cmd->scsi_done(cmd); } static void complete_scsi_command(struct CommandList *cp) { struct scsi_cmnd *cmd; struct ctlr_info *h; struct ErrorInfo *ei; struct hpsa_scsi_dev_t *dev; unsigned char sense_key; unsigned char asc; /* additional sense code */ unsigned char ascq; /* additional sense code qualifier */ unsigned long sense_data_size; ei = cp->err_info; cmd = (struct scsi_cmnd *) cp->scsi_cmd; h = cp->h; dev = cmd->device->hostdata; scsi_dma_unmap(cmd); /* undo the DMA mappings */ if ((cp->cmd_type == CMD_SCSI) && (cp->Header.SGTotal > h->max_cmd_sg_entries)) hpsa_unmap_sg_chain_block(h, cp); cmd->result = (DID_OK << 16); /* host byte */ cmd->result |= (COMMAND_COMPLETE << 8); /* msg byte */ if (cp->cmd_type == CMD_IOACCEL2) return process_ioaccel2_completion(h, cp, cmd, dev); cmd->result |= ei->ScsiStatus; /* copy the sense data whether we need to or not. */ if (SCSI_SENSE_BUFFERSIZE < sizeof(ei->SenseInfo)) sense_data_size = SCSI_SENSE_BUFFERSIZE; else sense_data_size = sizeof(ei->SenseInfo); if (ei->SenseLen < sense_data_size) sense_data_size = ei->SenseLen; memcpy(cmd->sense_buffer, ei->SenseInfo, sense_data_size); scsi_set_resid(cmd, ei->ResidualCnt); if (ei->CommandStatus == 0) { cmd_free(h, cp); cmd->scsi_done(cmd); return; } /* For I/O accelerator commands, copy over some fields to the normal * CISS header used below for error handling. */ if (cp->cmd_type == CMD_IOACCEL1) { struct io_accel1_cmd *c = &h->ioaccel_cmd_pool[cp->cmdindex]; cp->Header.SGList = cp->Header.SGTotal = scsi_sg_count(cmd); cp->Request.CDBLen = c->io_flags & IOACCEL1_IOFLAGS_CDBLEN_MASK; cp->Header.Tag.lower = c->Tag.lower; cp->Header.Tag.upper = c->Tag.upper; memcpy(cp->Header.LUN.LunAddrBytes, c->CISS_LUN, 8); memcpy(cp->Request.CDB, c->CDB, cp->Request.CDBLen); /* Any RAID offload error results in retry which will use * the normal I/O path so the controller can handle whatever's * wrong. */ if (is_logical_dev_addr_mode(dev->scsi3addr)) { if (ei->CommandStatus == CMD_IOACCEL_DISABLED) dev->offload_enabled = 0; cmd->result = DID_SOFT_ERROR << 16; cmd_free(h, cp); cmd->scsi_done(cmd); return; } } /* an error has occurred */ switch (ei->CommandStatus) { case CMD_TARGET_STATUS: if (ei->ScsiStatus) { /* Get sense key */ sense_key = 0xf & ei->SenseInfo[2]; /* Get additional sense code */ asc = ei->SenseInfo[12]; /* Get addition sense code qualifier */ ascq = ei->SenseInfo[13]; } if (ei->ScsiStatus == SAM_STAT_CHECK_CONDITION) { if (check_for_unit_attention(h, cp)) break; if (sense_key == ILLEGAL_REQUEST) { /* * SCSI REPORT_LUNS is commonly unsupported on * Smart Array. Suppress noisy complaint. */ if (cp->Request.CDB[0] == REPORT_LUNS) break; /* If ASC/ASCQ indicate Logical Unit * Not Supported condition, */ if ((asc == 0x25) && (ascq == 0x0)) { dev_warn(&h->pdev->dev, "cp %p " "has check condition\n", cp); break; } } if (sense_key == NOT_READY) { /* If Sense is Not Ready, Logical Unit * Not ready, Manual Intervention * required */ if ((asc == 0x04) && (ascq == 0x03)) { dev_warn(&h->pdev->dev, "cp %p " "has check condition: unit " "not ready, manual " "intervention required\n", cp); break; } } if (sense_key == ABORTED_COMMAND) { /* Aborted command is retryable */ dev_warn(&h->pdev->dev, "cp %p " "has check condition: aborted command: " "ASC: 0x%x, ASCQ: 0x%x\n", cp, asc, ascq); cmd->result |= DID_SOFT_ERROR << 16; break; } /* Must be some other type of check condition */ dev_dbg(&h->pdev->dev, "cp %p has check condition: " "unknown type: " "Sense: 0x%x, ASC: 0x%x, ASCQ: 0x%x, " "Returning result: 0x%x, " "cmd=[%02x %02x %02x %02x %02x " "%02x %02x %02x %02x %02x %02x " "%02x %02x %02x %02x %02x]\n", cp, sense_key, asc, ascq, cmd->result, cmd->cmnd[0], cmd->cmnd[1], cmd->cmnd[2], cmd->cmnd[3], cmd->cmnd[4], cmd->cmnd[5], cmd->cmnd[6], cmd->cmnd[7], cmd->cmnd[8], cmd->cmnd[9], cmd->cmnd[10], cmd->cmnd[11], cmd->cmnd[12], cmd->cmnd[13], cmd->cmnd[14], cmd->cmnd[15]); break; } /* Problem was not a check condition * Pass it up to the upper layers... */ if (ei->ScsiStatus) { dev_warn(&h->pdev->dev, "cp %p has status 0x%x " "Sense: 0x%x, ASC: 0x%x, ASCQ: 0x%x, " "Returning result: 0x%x\n", cp, ei->ScsiStatus, sense_key, asc, ascq, cmd->result); } else { /* scsi status is zero??? How??? */ dev_warn(&h->pdev->dev, "cp %p SCSI status was 0. " "Returning no connection.\n", cp), /* Ordinarily, this case should never happen, * but there is a bug in some released firmware * revisions that allows it to happen if, for * example, a 4100 backplane loses power and * the tape drive is in it. We assume that * it's a fatal error of some kind because we * can't show that it wasn't. We will make it * look like selection timeout since that is * the most common reason for this to occur, * and it's severe enough. */ cmd->result = DID_NO_CONNECT << 16; } break; case CMD_DATA_UNDERRUN: /* let mid layer handle it. */ break; case CMD_DATA_OVERRUN: dev_warn(&h->pdev->dev, "cp %p has" " completed with data overrun " "reported\n", cp); break; case CMD_INVALID: { /* print_bytes(cp, sizeof(*cp), 1, 0); print_cmd(cp); */ /* We get CMD_INVALID if you address a non-existent device * instead of a selection timeout (no response). You will * see this if you yank out a drive, then try to access it. * This is kind of a shame because it means that any other * CMD_INVALID (e.g. driver bug) will get interpreted as a * missing target. */ cmd->result = DID_NO_CONNECT << 16; } break; case CMD_PROTOCOL_ERR: cmd->result = DID_ERROR << 16; dev_warn(&h->pdev->dev, "cp %p has " "protocol error\n", cp); break; case CMD_HARDWARE_ERR: cmd->result = DID_ERROR << 16; dev_warn(&h->pdev->dev, "cp %p had hardware error\n", cp); break; case CMD_CONNECTION_LOST: cmd->result = DID_ERROR << 16; dev_warn(&h->pdev->dev, "cp %p had connection lost\n", cp); break; case CMD_ABORTED: cmd->result = DID_ABORT << 16; dev_warn(&h->pdev->dev, "cp %p was aborted with status 0x%x\n", cp, ei->ScsiStatus); break; case CMD_ABORT_FAILED: cmd->result = DID_ERROR << 16; dev_warn(&h->pdev->dev, "cp %p reports abort failed\n", cp); break; case CMD_UNSOLICITED_ABORT: cmd->result = DID_SOFT_ERROR << 16; /* retry the command */ dev_warn(&h->pdev->dev, "cp %p aborted due to an unsolicited " "abort\n", cp); break; case CMD_TIMEOUT: cmd->result = DID_TIME_OUT << 16; dev_warn(&h->pdev->dev, "cp %p timedout\n", cp); break; case CMD_UNABORTABLE: cmd->result = DID_ERROR << 16; dev_warn(&h->pdev->dev, "Command unabortable\n"); break; case CMD_IOACCEL_DISABLED: /* This only handles the direct pass-through case since RAID * offload is handled above. Just attempt a retry. */ cmd->result = DID_SOFT_ERROR << 16; dev_warn(&h->pdev->dev, "cp %p had HP SSD Smart Path error\n", cp); break; default: cmd->result = DID_ERROR << 16; dev_warn(&h->pdev->dev, "cp %p returned unknown status %x\n", cp, ei->CommandStatus); } cmd_free(h, cp); cmd->scsi_done(cmd); } static void hpsa_pci_unmap(struct pci_dev *pdev, struct CommandList *c, int sg_used, int data_direction) { int i; union u64bit addr64; for (i = 0; i < sg_used; i++) { addr64.val32.lower = c->SG[i].Addr.lower; addr64.val32.upper = c->SG[i].Addr.upper; pci_unmap_single(pdev, (dma_addr_t) addr64.val, c->SG[i].Len, data_direction); } } static int hpsa_map_one(struct pci_dev *pdev, struct CommandList *cp, unsigned char *buf, size_t buflen, int data_direction) { u64 addr64; if (buflen == 0 || data_direction == PCI_DMA_NONE) { cp->Header.SGList = 0; cp->Header.SGTotal = 0; return 0; } addr64 = (u64) pci_map_single(pdev, buf, buflen, data_direction); if (dma_mapping_error(&pdev->dev, addr64)) { /* Prevent subsequent unmap of something never mapped */ cp->Header.SGList = 0; cp->Header.SGTotal = 0; return -1; } cp->SG[0].Addr.lower = (u32) (addr64 & (u64) 0x00000000FFFFFFFF); cp->SG[0].Addr.upper = (u32) ((addr64 >> 32) & (u64) 0x00000000FFFFFFFF); cp->SG[0].Len = buflen; cp->SG[0].Ext = HPSA_SG_LAST; /* we are not chaining */ cp->Header.SGList = (u8) 1; /* no. SGs contig in this cmd */ cp->Header.SGTotal = (u16) 1; /* total sgs in this cmd list */ return 0; } static inline void hpsa_scsi_do_simple_cmd_core(struct ctlr_info *h, struct CommandList *c) { DECLARE_COMPLETION_ONSTACK(wait); c->waiting = &wait; enqueue_cmd_and_start_io(h, c); wait_for_completion(&wait); } static void hpsa_scsi_do_simple_cmd_core_if_no_lockup(struct ctlr_info *h, struct CommandList *c) { unsigned long flags; /* If controller lockup detected, fake a hardware error. */ spin_lock_irqsave(&h->lock, flags); if (unlikely(h->lockup_detected)) { spin_unlock_irqrestore(&h->lock, flags); c->err_info->CommandStatus = CMD_HARDWARE_ERR; } else { spin_unlock_irqrestore(&h->lock, flags); hpsa_scsi_do_simple_cmd_core(h, c); } } #define MAX_DRIVER_CMD_RETRIES 25 static void hpsa_scsi_do_simple_cmd_with_retry(struct ctlr_info *h, struct CommandList *c, int data_direction) { int backoff_time = 10, retry_count = 0; do { memset(c->err_info, 0, sizeof(*c->err_info)); hpsa_scsi_do_simple_cmd_core(h, c); retry_count++; if (retry_count > 3) { msleep(backoff_time); if (backoff_time < 1000) backoff_time *= 2; } } while ((check_for_unit_attention(h, c) || check_for_busy(h, c)) && retry_count <= MAX_DRIVER_CMD_RETRIES); hpsa_pci_unmap(h->pdev, c, 1, data_direction); } static void hpsa_print_cmd(struct ctlr_info *h, char *txt, struct CommandList *c) { const u8 *cdb = c->Request.CDB; const u8 *lun = c->Header.LUN.LunAddrBytes; dev_warn(&h->pdev->dev, "%s: LUN:%02x%02x%02x%02x%02x%02x%02x%02x" " CDB:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", txt, lun[0], lun[1], lun[2], lun[3], lun[4], lun[5], lun[6], lun[7], cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], cdb[8], cdb[9], cdb[10], cdb[11], cdb[12], cdb[13], cdb[14], cdb[15]); } static void hpsa_scsi_interpret_error(struct ctlr_info *h, struct CommandList *cp) { const struct ErrorInfo *ei = cp->err_info; struct device *d = &cp->h->pdev->dev; const u8 *sd = ei->SenseInfo; switch (ei->CommandStatus) { case CMD_TARGET_STATUS: hpsa_print_cmd(h, "SCSI status", cp); if (ei->ScsiStatus == SAM_STAT_CHECK_CONDITION) dev_warn(d, "SCSI Status = 02, Sense key = %02x, ASC = %02x, ASCQ = %02x\n", sd[2] & 0x0f, sd[12], sd[13]); else dev_warn(d, "SCSI Status = %02x\n", ei->ScsiStatus); if (ei->ScsiStatus == 0) dev_warn(d, "SCSI status is abnormally zero. " "(probably indicates selection timeout " "reported incorrectly due to a known " "firmware bug, circa July, 2001.)\n"); break; case CMD_DATA_UNDERRUN: /* let mid layer handle it. */ break; case CMD_DATA_OVERRUN: hpsa_print_cmd(h, "overrun condition", cp); break; case CMD_INVALID: { /* controller unfortunately reports SCSI passthru's * to non-existent targets as invalid commands. */ hpsa_print_cmd(h, "invalid command", cp); dev_warn(d, "probably means device no longer present\n"); } break; case CMD_PROTOCOL_ERR: hpsa_print_cmd(h, "protocol error", cp); break; case CMD_HARDWARE_ERR: hpsa_print_cmd(h, "hardware error", cp); break; case CMD_CONNECTION_LOST: hpsa_print_cmd(h, "connection lost", cp); break; case CMD_ABORTED: hpsa_print_cmd(h, "aborted", cp); break; case CMD_ABORT_FAILED: hpsa_print_cmd(h, "abort failed", cp); break; case CMD_UNSOLICITED_ABORT: hpsa_print_cmd(h, "unsolicited abort", cp); break; case CMD_TIMEOUT: hpsa_print_cmd(h, "timed out", cp); break; case CMD_UNABORTABLE: hpsa_print_cmd(h, "unabortable", cp); break; default: hpsa_print_cmd(h, "unknown status", cp); dev_warn(d, "Unknown command status %x\n", ei->CommandStatus); } } static int hpsa_scsi_do_inquiry(struct ctlr_info *h, unsigned char *scsi3addr, u16 page, unsigned char *buf, unsigned char bufsize) { int rc = IO_OK; struct CommandList *c; struct ErrorInfo *ei; c = cmd_special_alloc(h); if (c == NULL) { /* trouble... */ dev_warn(&h->pdev->dev, "cmd_special_alloc returned NULL!\n"); return -ENOMEM; } if (fill_cmd(c, HPSA_INQUIRY, h, buf, bufsize, page, scsi3addr, TYPE_CMD)) { rc = -1;