/* * Disk Array driver for HP Smart Array SAS controllers * Copyright (c) 2019-2020 Microchip Technology Inc. and its subsidiaries * Copyright 2016 Microsemi Corporation * Copyright 2014-2015 PMC-Sierra, Inc. * Copyright 2000,2009-2015 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. * * Questions/Comments/Bugfixes to esc.storagedev@microsemi.com *
*/
/* * HPSA_DRIVER_VERSION must be 3 byte values (0-255) separated by '.' * with an optional trailing '-' followed by a byte value (0-255).
*/ #define HPSA_DRIVER_VERSION "3.4.20-200" #define DRIVER_NAME "HP HPSA Driver (v " HPSA_DRIVER_VERSION ")" #define HPSA "hpsa"
/* How long to wait for CISS doorbell communication */ #define CLEAR_EVENT_WAIT_INTERVAL 20 /* ms for each msleep() call */ #define MODE_CHANGE_WAIT_INTERVAL 10 /* ms for each msleep() call */ #define MAX_CLEAR_EVENT_WAIT 30000 /* times 20 ms = 600 s */ #define MAX_MODE_CHANGE_WAIT 2000 /* times 10 ms = 20 s */ #define MAX_IOCTL_CONFIG_WAIT 1000
/*define how many times we will try a command because of bus resets */ #define MAX_CMD_RETRIES 3 /* How long to wait before giving up on a command */ #define HPSA_EH_PTRAID_TIMEOUT (240 * HZ)
/* 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_VERSION(HPSA_DRIVER_VERSION);
MODULE_LICENSE("GPL");
MODULE_ALIAS("cciss");
staticint 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'");
switch (asc) { case STATE_CHANGED:
dev_warn(&h->pdev->dev, "%s: a state change detected, command retried\n",
h->devname); break; case LUN_FAILED:
dev_warn(&h->pdev->dev, "%s: LUN failure detected\n", h->devname); break; case REPORT_LUNS_CHANGED:
dev_warn(&h->pdev->dev, "%s: report LUN data changed\n", h->devname); /* * Note: this REPORT_LUNS_CHANGED condition only occurs on the external * target (array) devices.
*/ break; case POWER_OR_RESET:
dev_warn(&h->pdev->dev, "%s: a power on or device reset detected\n",
h->devname); break; case UNIT_ATTENTION_CLEARED:
dev_warn(&h->pdev->dev, "%s: unit attention cleared by another initiator\n",
h->devname); break; default:
dev_warn(&h->pdev->dev, "%s: unknown unit attention detected\n",
h->devname); break;
} return 1;
}
/* 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 */
};
staticint board_id_in_array(u32 a[], int nelems, u32 board_id)
{ int i;
for (i = 0; i < nelems; i++) if (a[i] == board_id) return 1; return 0;
}
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_device(hdev)) {
spin_unlock_irqrestore(&h->lock, flags);
l = snprintf(buf, PAGE_SIZE, "N/A\n"); return l;
}
sdev = to_scsi_device(dev);
h = sdev_to_hba(sdev);
spin_lock_irqsave(&h->devlock, flags);
hdev = sdev->hostdata; if (!hdev) {
spin_unlock_irqrestore(&h->devlock, flags); return -ENODEV;
}
bay = hdev->bay; for (i = 0; i < MAX_PATHS; i++) {
path_map_index = 1<<i; if (i == hdev->active_path_index)
active = "Active"; elseif (hdev->path_map & path_map_index)
active = "Inactive"; else continue;
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++;
atomic_dec(&h->commands_outstanding);
} 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
*/ #define DEFAULT_REPLY_QUEUE (-1) staticvoid set_performant_mode(struct ctlr_info *h, struct CommandList *c, int reply_queue)
{ if (likely(h->transMethod & CFGTBL_Trans_Performant)) {
c->busaddr |= 1 | (h->blockFetchTable[c->Header.SGList] << 1); if (unlikely(!h->msix_vectors)) return;
c->Header.ReplyQueue = reply_queue;
}
}
/* * Tell the controller to post the reply to the queue for this * processor. This seems to give the best I/O throughput.
*/
cp->ReplyQueue = reply_queue; /* * 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;
}
/* 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 = reply_queue; /* 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[0];
}
/* * 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 = reply_queue; /* * 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]);
}
/* * 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) #define HPSA_EVENT_MONITOR_INTERVAL (15 * HZ) staticvoid 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;
}
staticvoid __enqueue_cmd_and_start_io(struct ctlr_info *h, struct CommandList *c, int reply_queue)
{
dial_down_lockup_detection_during_fw_flash(h, c);
atomic_inc(&h->commands_outstanding); /* * Check to see if the command is being retried.
*/ if (c->device && !c->retry_pending)
atomic_inc(&c->device->commands_outstanding);
staticinlineint 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;
}
staticint hpsa_find_target_lun(struct ctlr_info *h, unsignedchar 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. */ staticint hpsa_scsi_add_entry(struct ctlr_info *h, 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; unsignedchar 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 otherwise.
*/ 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 and 5. * 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;
addr1[5] = 0; for (i = 0; i < n; i++) {
sd = h->dev[i];
memcpy(addr2, sd->scsi3addr, 8);
addr2[4] = 0;
addr2[5] = 0; /* differ only in byte 4 and 5? */ 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;
}
/* * Called during a scan operation. * * Update an entry in h->dev[] array.
*/ staticvoid hpsa_scsi_update_entry(struct ctlr_info *h, int entry, struct hpsa_scsi_dev_t *new_entry)
{ /* assumes h->devlock is held */
BUG_ON(entry < 0 || entry >= HPSA_MAX_DEVICES);
/* * ioacccel_handle may have changed for a dual domain disk
*/
h->dev[entry]->ioaccel_handle = new_entry->ioaccel_handle;
/* Raid offload parameters changed. Careful about the ordering. */ if (new_entry->offload_config && new_entry->offload_to_be_enabled) { /* * if drive is newly offload_enabled, we want to copy the * raid map data first. If previously offload_enabled and * offload_config were set, raid map data had better be * the same as it was before. If raid map data has changed * then it had better be the case that * h->dev[entry]->offload_enabled is currently 0.
*/
h->dev[entry]->raid_map = new_entry->raid_map;
h->dev[entry]->ioaccel_handle = new_entry->ioaccel_handle;
} if (new_entry->offload_to_be_enabled) {
h->dev[entry]->ioaccel_handle = new_entry->ioaccel_handle;
wmb(); /* set ioaccel_handle *before* hba_ioaccel_enabled */
}
h->dev[entry]->hba_ioaccel_enabled = new_entry->hba_ioaccel_enabled;
h->dev[entry]->offload_config = new_entry->offload_config;
h->dev[entry]->offload_to_mirror = new_entry->offload_to_mirror;
h->dev[entry]->queue_depth = new_entry->queue_depth;
/* * We can turn off ioaccel offload now, but need to delay turning * ioaccel on until we can update h->dev[entry]->phys_disk[], but we * can't do that until all the devices are updated.
*/
h->dev[entry]->offload_to_be_enabled = new_entry->offload_to_be_enabled;
/* * turn ioaccel off immediately if told to do so.
*/ if (!new_entry->offload_to_be_enabled)
h->dev[entry]->offload_enabled = 0;
/* Replace an entry from h->dev[] array. */ staticvoid hpsa_scsi_replace_entry(struct ctlr_info *h, 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;
}
/* Remove an entry from h->dev[] array. */ staticvoid hpsa_scsi_remove_entry(struct ctlr_info *h, int entry, struct hpsa_scsi_dev_t *removed[], int *nremoved)
{ /* assumes h->devlock is held */ int i; struct hpsa_scsi_dev_t *sd;
staticvoid 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.
*/ unsignedlong 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);
}
staticinlineint 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;
}
staticinlineint 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_to_be_enabled != dev2->offload_to_be_enabled) return 1; if (!is_logical_dev_addr_mode(dev1->scsi3addr)) if (dev1->queue_depth != dev2->queue_depth) return 1; /* * This can happen for dual domain devices. An active * path change causes the ioaccel handle to change * * for example note the handle differences between p0 and p1 * Device WWN ,WWN hash,Handle * D016 p0|0x3 [02]P2E:01:01,0x5000C5005FC4DACA,0x9B5616,0x01030003 * p1 0x5000C5005FC4DAC9,0x6798C0,0x00040004
*/ if (dev1->ioaccel_handle != dev2->ioaccel_handle) 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.
*/ staticint 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 if (needle == NULL) return DEVICE_NOT_FOUND;
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;
}
/* 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) return;
/* Print a message explaining various offline volume states */ staticvoid 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_NOT_AVAILABLE:
dev_info(&h->pdev->dev, "C%d:B%d:T%d:L%d Volume is waiting for transforming volume.\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 init.\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;
}
}
/* * Figure the list of physical drive pointers for a logical drive with * raid offload configured.
*/ staticvoid hpsa_figure_phys_disk_ptrs(struct ctlr_info *h, struct hpsa_scsi_dev_t *dev[], int ndevices, struct hpsa_scsi_dev_t *logical_drive)
{ struct raid_map_data *map = &logical_drive->raid_map; struct raid_map_disk_data *dd = &map->data[0]; int i, j; int total_disks_per_row = le16_to_cpu(map->data_disks_per_row) +
le16_to_cpu(map->metadata_disks_per_row); int nraid_map_entries = le16_to_cpu(map->row_cnt) *
le16_to_cpu(map->layout_map_count) *
total_disks_per_row; int nphys_disk = le16_to_cpu(map->layout_map_count) *
total_disks_per_row; int qdepth;
if (nraid_map_entries > RAID_MAP_MAX_ENTRIES)
nraid_map_entries = RAID_MAP_MAX_ENTRIES;
qdepth = 0; for (i = 0; i < nraid_map_entries; i++) {
logical_drive->phys_disk[i] = NULL; if (!logical_drive->offload_config) continue; for (j = 0; j < ndevices; j++) { if (dev[j] == NULL) continue; if (dev[j]->devtype != TYPE_DISK &&
dev[j]->devtype != TYPE_ZBC) continue; if (is_logical_device(dev[j])) continue; if (dev[j]->ioaccel_handle != dd[i].ioaccel_handle) continue;
logical_drive->phys_disk[i] = dev[j]; if (i < nphys_disk)
qdepth = min(h->nr_cmds, qdepth +
logical_drive->phys_disk[i]->queue_depth); break;
}
/* * This can happen if a physical drive is removed and * the logical drive is degraded. In that case, the RAID * map data will refer to a physical disk which isn't actually * present. And in that case offload_enabled should already * be 0, but we'll turn it off here just in case
*/ if (!logical_drive->phys_disk[i]) {
dev_warn(&h->pdev->dev, "%s: [%d:%d:%d:%d] A phys disk component of LV is missing, turning off offload_enabled for LV.\n",
__func__,
h->scsi_host->host_no, logical_drive->bus,
logical_drive->target, logical_drive->lun);
hpsa_turn_off_ioaccel_for_device(logical_drive);
logical_drive->queue_depth = 8;
}
} if (nraid_map_entries) /* * This is correct for reads, too high for full stripe writes, * way too high for partial stripe writes
*/
logical_drive->queue_depth = qdepth; else { if (logical_drive->external)
logical_drive->queue_depth = EXTERNAL_QD; else
logical_drive->queue_depth = h->nr_cmds;
}
}
staticvoid hpsa_update_log_drive_phys_drive_ptrs(struct ctlr_info *h, struct hpsa_scsi_dev_t *dev[], int ndevices)
{ int i;
for (i = 0; i < ndevices; i++) { if (dev[i] == NULL) continue; if (dev[i]->devtype != TYPE_DISK &&
dev[i]->devtype != TYPE_ZBC) continue; if (!is_logical_device(dev[i])) continue;
/* * If offload is currently enabled, the RAID map and * phys_disk[] assignment *better* not be changing * because we would be changing ioaccel phsy_disk[] pointers * on a ioaccel volume processing I/O requests. * * If an ioaccel volume status changed, initially because it was * re-configured and thus underwent a transformation, or * a drive failed, we would have received a state change * request and ioaccel should have been turned off. When the * transformation completes, we get another state change * request to turn ioaccel back on. In this case, we need * to update the ioaccel information. * * Thus: If it is not currently enabled, but will be after * the scan completes, make sure the ioaccel pointers * are up to date.
*/
if (!dev[i]->offload_enabled && dev[i]->offload_to_be_enabled)
hpsa_figure_phys_disk_ptrs(h, dev, ndevices, dev[i]);
}
}
/* * Allow for commands to drain
*/
device->removed = 1;
hpsa_wait_for_outstanding_commands_for_dev(h, device);
if (is_logical_device(device)) { /* RAID */
sdev = scsi_device_lookup(h->scsi_host, device->bus,
device->target, device->lun); if (sdev) {
scsi_remove_device(sdev);
scsi_device_put(sdev);
} else { /* * We don't expect to get here. Future commands * to this device will get a selection timeout as * if the device were gone.
*/
hpsa_show_dev_msg(KERN_WARNING, h, device, "didn't find device for removal.");
}
} else { /* HBA */
hpsa_remove_sas_device(device);
}
}
staticvoid adjust_hpsa_scsi_table(struct ctlr_info *h, 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; unsignedlong flags; struct hpsa_scsi_dev_t **added, **removed; int nadded, nremoved;
/* * A reset can cause a device status to change * re-schedule the scan to see what happened.
*/
spin_lock_irqsave(&h->reset_lock, flags); if (h->reset_in_progress) {
h->drv_req_rescan = 1;
spin_unlock_irqrestore(&h->reset_lock, flags); return;
}
spin_unlock_irqrestore(&h->reset_lock, flags);
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, i, removed, &nremoved); continue; /* remove ^^^, hence i not incremented */
} elseif (device_change == DEVICE_CHANGED) {
changes++;
hpsa_scsi_replace_entry(h, 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;
} elseif (device_change == DEVICE_UPDATED) {
hpsa_scsi_update_entry(h, 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]);
hpsa_show_dev_msg(KERN_INFO, h, sd[i], "offline"); 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, sd[i], added, &nadded) != 0) break;
sd[i] = NULL; /* prevent from being freed later. */
} elseif (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 */
}
}
hpsa_update_log_drive_phys_drive_ptrs(h, h->dev, h->ndevices);
/* * Now that h->dev[]->phys_disk[] is coherent, we can enable * any logical drives that need it enabled. * * The raid map should be current by now. * * We are updating the device list used for I/O requests.
*/ for (i = 0; i < h->ndevices; i++) { if (h->dev[i] == NULL) continue;
h->dev[i]->offload_enabled = h->dev[i]->offload_to_be_enabled;
}
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 (!changes) goto free_and_out;
/* Notify scsi mid layer of any removed devices */ for (i = 0; i < nremoved; i++) { if (removed[i] == NULL) continue; if (removed[i]->expose_device)
hpsa_remove_device(h, removed[i]);
kfree(removed[i]);
removed[i] = NULL;
}
/* Notify scsi mid layer of any added devices */ for (i = 0; i < nadded; i++) { int rc = 0;
if (added[i] == NULL) continue; if (!(added[i]->expose_device)) continue;
rc = hpsa_add_device(h, added[i]); if (!rc) continue;
dev_warn(&h->pdev->dev, "addition failed %d, device not added.", rc); /* 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]);
h->drv_req_rescan = 1;
}
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.
*/ staticstruct 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;
}
staticvoid 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;
}
staticint hpsa_alloc_sg_chain_blocks(struct ctlr_info *h)
{ int i;
if (h->chainsize <= 0) return 0;
h->cmd_sg_list = kcalloc(h->nr_cmds, sizeof(*h->cmd_sg_list),
GFP_KERNEL); if (!h->cmd_sg_list) return -ENOMEM;
for (i = 0; i < h->nr_cmds; i++) {
h->cmd_sg_list[i] = kmalloc_array(h->chainsize, sizeof(*h->cmd_sg_list[i]),
GFP_KERNEL); if (!h->cmd_sg_list[i]) goto clean;
/* 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.
*/ staticint handle_ioaccel_mode2_error(struct ctlr_info *h, struct CommandList *c, struct scsi_cmnd *cmd, struct io_accel2_cmd *c2, struct hpsa_scsi_dev_t *dev)
{ int data_len; int retry = 0;
u32 ioaccel2_resid = 0;
switch (c2->error_data.serv_response) { case IOACCEL2_SERV_RESPONSE_COMPLETE: switch (c2->error_data.status) { case IOACCEL2_STATUS_SR_TASK_COMP_GOOD: if (cmd)
cmd->result = 0; break; case IOACCEL2_STATUS_SR_TASK_COMP_CHK_COND:
cmd->result |= SAM_STAT_CHECK_CONDITION; if (c2->error_data.data_present !=
IOACCEL2_SENSE_DATA_PRESENT) {
memset(cmd->sense_buffer, 0,
SCSI_SENSE_BUFFERSIZE); 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);
retry = 1; break; case IOACCEL2_STATUS_SR_TASK_COMP_BUSY:
retry = 1; break; case IOACCEL2_STATUS_SR_TASK_COMP_RES_CON:
retry = 1; break; case IOACCEL2_STATUS_SR_TASK_COMP_SET_FULL:
retry = 1; break; case IOACCEL2_STATUS_SR_TASK_COMP_ABORTED:
retry = 1; break; default:
retry = 1; break;
} break; case IOACCEL2_SERV_RESPONSE_FAILURE: switch (c2->error_data.status) { case IOACCEL2_STATUS_SR_IO_ERROR: case IOACCEL2_STATUS_SR_IO_ABORTED: case IOACCEL2_STATUS_SR_OVERRUN:
retry = 1; break; case IOACCEL2_STATUS_SR_UNDERRUN:
cmd->result = (DID_OK << 16); /* host byte */
ioaccel2_resid = get_unaligned_le32(
&c2->error_data.resid_cnt[0]);
scsi_set_resid(cmd, ioaccel2_resid); break; case IOACCEL2_STATUS_SR_NO_PATH_TO_DEVICE: case IOACCEL2_STATUS_SR_INVALID_DEVICE: case IOACCEL2_STATUS_SR_IOACCEL_DISABLED: /* * Did an HBA disk disappear? We will eventually * get a state change event from the controller but * in the meantime, we need to tell the OS that the * HBA disk is no longer there and stop I/O * from going down. This allows the potential re-insert * of the disk to get the same device node.
*/ if (dev->physical_device && dev->expose_device) {
cmd->result = DID_NO_CONNECT << 16;
dev->removed = 1;
h->drv_req_rescan = 1;
dev_warn(&h->pdev->dev, "%s: device is gone!\n", __func__);
} else /* * Retry by sending down the RAID path. * We will get an event from ctlr to * trigger rescan regardless.
*/
retry = 1; break; default:
retry = 1;
} break; case IOACCEL2_SERV_RESPONSE_TMF_COMPLETE: break; case IOACCEL2_SERV_RESPONSE_TMF_SUCCESS: break; case IOACCEL2_SERV_RESPONSE_TMF_REJECTED:
retry = 1; break; case IOACCEL2_SERV_RESPONSE_TMF_WRONG_LUN: break; default:
retry = 1; break;
}
/* * Reset c->scsi_cmd here so that the reset handler will know * this command has completed. Then, check to see if the handler is * waiting for this command, and, if so, wake it.
*/
c->scsi_cmd = SCSI_CMD_IDLE;
mb(); /* Declare command idle before checking for pending events. */ if (dev) {
atomic_dec(&dev->commands_outstanding); if (dev->in_reset &&
atomic_read(&dev->commands_outstanding) <= 0)
wake_up_all(&h->event_sync_wait_queue);
}
}
/* check for good status */ if (likely(c2->error_data.serv_response == 0 &&
c2->error_data.status == 0)) {
cmd->result = 0; return hpsa_cmd_free_and_done(h, c, cmd);
}
/* * Any RAID offload error results in retry which will use * the normal I/O path so the controller can handle whatever is * wrong.
*/ if (is_logical_device(dev) &&
c2->error_data.serv_response ==
IOACCEL2_SERV_RESPONSE_FAILURE) { if (c2->error_data.status ==
IOACCEL2_STATUS_SR_IOACCEL_DISABLED) {
hpsa_turn_off_ioaccel_for_device(dev);
}
switch (tmf_status) { case CISS_TMF_COMPLETE: /* * CISS_TMF_COMPLETE never happens, instead, * ei->CommandStatus == 0 for this case.
*/ case CISS_TMF_SUCCESS: return 0; case CISS_TMF_INVALID_FRAME: case CISS_TMF_NOT_SUPPORTED: case CISS_TMF_FAILED: case CISS_TMF_WRONG_LUN: case CISS_TMF_OVERLAPPED_TAG: break; default:
dev_warn(&h->pdev->dev, "Unknown TMF status: 0x%02x\n",
tmf_status); break;
} return -tmf_status;
}
/* * We check for lockup status here as it may be set for * CMD_SCSI, CMD_IOACCEL1 and CMD_IOACCEL2 commands by * fail_all_oustanding_cmds()
*/ if (unlikely(ei->CommandStatus == CMD_CTLR_LOCKUP)) { /* DID_NO_CONNECT will prevent a retry */
cmd->result = DID_NO_CONNECT << 16; return hpsa_cmd_free_and_done(h, cp, cmd);
}
if (cp->cmd_type == CMD_IOACCEL2) return process_ioaccel2_completion(h, cp, cmd, dev);
scsi_set_resid(cmd, ei->ResidualCnt); if (ei->CommandStatus == 0) return hpsa_cmd_free_and_done(h, cp, cmd);
/* 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 = scsi_sg_count(cmd);
cp->Header.SGTotal = cpu_to_le16(cp->Header.SGList);
cp->Request.CDBLen = le16_to_cpu(c->io_flags) &
IOACCEL1_IOFLAGS_CDBLEN_MASK;
cp->Header.tag = c->tag;
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_device(dev)) { if (ei->CommandStatus == CMD_IOACCEL_DISABLED)
dev->offload_enabled = 0; return hpsa_retry_cmd(h, cp);
}
}
/* an error has occurred */ switch (ei->CommandStatus) {
case CMD_TARGET_STATUS:
cmd->result |= ei->ScsiStatus; /* copy the sense data */ 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); if (ei->ScsiStatus)
decode_sense_data(ei->SenseInfo, sense_data_size,
&sense_key, &asc, &ascq); if (ei->ScsiStatus == SAM_STAT_CHECK_CONDITION) { switch (sense_key) { case ABORTED_COMMAND:
cmd->result |= DID_SOFT_ERROR << 16; break; case UNIT_ATTENTION: if (asc == 0x3F && ascq == 0x0E)
h->drv_req_rescan = 1; break; case ILLEGAL_REQUEST: if (asc == 0x25 && ascq == 0x00) {
dev->removed = 1;
cmd->result = DID_NO_CONNECT << 16;
} break;
} 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, "CDB %16phN data overrun\n", cp->Request.CDB); 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, "CDB %16phN : protocol error\n",
cp->Request.CDB); break; case CMD_HARDWARE_ERR:
cmd->result = DID_ERROR << 16;
dev_warn(&h->pdev->dev, "CDB %16phN : hardware error\n",
cp->Request.CDB); break; case CMD_CONNECTION_LOST:
cmd->result = DID_ERROR << 16;
dev_warn(&h->pdev->dev, "CDB %16phN : connection lost\n",
cp->Request.CDB); break; case CMD_ABORTED:
cmd->result = DID_ABORT << 16; break; case CMD_ABORT_FAILED:
cmd->result = DID_ERROR << 16;
dev_warn(&h->pdev->dev, "CDB %16phN : abort failed\n",
cp->Request.CDB); break; case CMD_UNSOLICITED_ABORT:
cmd->result = DID_SOFT_ERROR << 16; /* retry the command */
dev_warn(&h->pdev->dev, "CDB %16phN : unsolicited abort\n",
cp->Request.CDB); break; case CMD_TIMEOUT:
cmd->result = DID_TIME_OUT << 16;
dev_warn(&h->pdev->dev, "CDB %16phN timed out\n",
cp->Request.CDB); break; case CMD_UNABORTABLE:
cmd->result = DID_ERROR << 16;
dev_warn(&h->pdev->dev, "Command unabortable\n"); break; case CMD_TMF_STATUS: if (hpsa_evaluate_tmf_status(h, cp)) /* TMF failed? */
cmd->result = DID_ERROR << 16; 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);
}
return hpsa_cmd_free_and_done(h, cp, cmd);
}
staticvoid hpsa_pci_unmap(struct pci_dev *pdev, struct CommandList *c, int sg_used, enum dma_data_direction data_direction)
{ int i;
for (i = 0; i < sg_used; i++)
dma_unmap_single(&pdev->dev, le64_to_cpu(c->SG[i].Addr),
le32_to_cpu(c->SG[i].Len),
data_direction);
}
/* fill_cmd can't fail here, no data buffer to map. */
(void) fill_cmd(c, reset_type, h, NULL, 0, 0, dev->scsi3addr, TYPE_MSG);
rc = hpsa_scsi_do_simple_cmd(h, c, reply_queue, NO_TIMEOUT); if (rc) {
dev_warn(&h->pdev->dev, "Failed to send reset command\n"); goto out;
} /* no unmap needed here because no data xfer. */
ei = c->err_info; if (ei->CommandStatus != 0) {
hpsa_scsi_interpret_error(h, c);
rc = -1;
}
out:
cmd_free(h, c); return rc;
}
switch (c->cmd_type) { case CMD_SCSI: case CMD_IOCTL_PEND:
match = !memcmp(scsi3addr, &c->Header.LUN.LunAddrBytes, sizeof(c->Header.LUN.LunAddrBytes)); break;
case CMD_IOACCEL1: case CMD_IOACCEL2: if (c->phys_disk == dev) { /* HBA mode match */
match = true;
} else { /* Possible RAID mode -- check each phys dev. */ /* FIXME: Do we need to take out a lock here? If * so, we could just call hpsa_get_pdisk_of_ioaccel2()
* instead. */ for (i = 0; i < dev->nphysical_disks && !match; i++) { /* FIXME: an alternate test might be * * match = dev->phys_disk[i]->ioaccel_handle
* == c2->scsi_nexus; */
match = dev->phys_disk[i] == c->phys_disk;
}
} break;
case IOACCEL2_TMF: for (i = 0; i < dev->nphysical_disks && !match; i++) {
match = dev->phys_disk[i]->ioaccel_handle ==
le32_to_cpu(ac->it_nexus);
} break;
case 0: /* The command is in the middle of being initialized. */
match = false; break;
staticint hpsa_do_reset(struct ctlr_info *h, struct hpsa_scsi_dev_t *dev,
u8 reset_type, int reply_queue)
{ int rc = 0;
/* We can really only handle one reset at a time */ if (mutex_lock_interruptible(&h->reset_mutex) == -EINTR) {
dev_warn(&h->pdev->dev, "concurrent reset wait interrupted.\n"); return -EINTR;
}
rc = hpsa_send_reset(h, dev, reset_type, reply_queue); if (!rc) { /* incremented by sending the reset request */
atomic_dec(&dev->commands_outstanding);
wait_event(h->event_sync_wait_queue,
atomic_read(&dev->commands_outstanding) <= 0 ||
lockup_detected(h));
}
if (unlikely(lockup_detected(h))) {
dev_warn(&h->pdev->dev, "Controller lockup detected during reset wait\n");
rc = -ENODEV;
}
if (!rc)
rc = wait_for_device_to_become_ready(h, dev->scsi3addr, 0);
for (i = 0; i < nphysicals; i++) { if (physdev->LUN[i].device_type ==
BMIC_DEVICE_TYPE_CONTROLLER
&& !is_hba_lunid(physdev->LUN[i].lunid)) {
dev_info(&h->pdev->dev, "External controller present, activate discovery polling and disable rld caching\n");
hpsa_disable_rld_caching(h);
h->discovery_polling = 1; break;
}
}
}
/* Get a device id from inquiry page 0x83 */ staticbool hpsa_vpd_page_supported(struct ctlr_info *h, unsignedchar scsi3addr[], u8 page)
{ int rc; int i; int pages; unsignedchar *buf, bufsize;
buf = kzalloc(256, GFP_KERNEL); if (!buf) returnfalse;
/* Get the size of the page list first */
rc = hpsa_scsi_do_inquiry(h, scsi3addr,
VPD_PAGE | HPSA_VPD_SUPPORTED_PAGES,
buf, HPSA_VPD_HEADER_SZ); if (rc != 0) goto exit_unsupported;
pages = buf[3]; if ((pages + HPSA_VPD_HEADER_SZ) <= 255)
bufsize = pages + HPSA_VPD_HEADER_SZ; else
bufsize = 255;
/* Get the whole VPD page list */
rc = hpsa_scsi_do_inquiry(h, scsi3addr,
VPD_PAGE | HPSA_VPD_SUPPORTED_PAGES,
buf, bufsize); if (rc != 0) goto exit_unsupported;
pages = buf[3]; for (i = 1; i <= pages; i++) if (buf[3 + i] == page) goto exit_supported;
exit_unsupported:
kfree(buf); returnfalse;
exit_supported:
kfree(buf); returntrue;
}
/* * Called during a scan operation. * Sets ioaccel status on the new device list, not the existing device list * * The device list used during I/O will be updated later in * adjust_hpsa_scsi_table.
*/ staticvoid hpsa_get_ioaccel_status(struct ctlr_info *h, unsignedchar *scsi3addr, struct hpsa_scsi_dev_t *this_device)
{ int rc; unsignedchar *buf;
u8 ioaccel_status;
buf = kzalloc(64, GFP_KERNEL); if (!buf) return; if (!hpsa_vpd_page_supported(h, scsi3addr, HPSA_VPD_LV_IOACCEL_STATUS)) goto out;
rc = hpsa_scsi_do_inquiry(h, scsi3addr,
VPD_PAGE | HPSA_VPD_LV_IOACCEL_STATUS, buf, 64); if (rc != 0) goto out;
#define IOACCEL_STATUS_BYTE 4 #define OFFLOAD_CONFIGURED_BIT 0x01 #define OFFLOAD_ENABLED_BIT 0x02
ioaccel_status = buf[IOACCEL_STATUS_BYTE];
this_device->offload_config =
!!(ioaccel_status & OFFLOAD_CONFIGURED_BIT); if (this_device->offload_config) { bool offload_enabled =
!!(ioaccel_status & OFFLOAD_ENABLED_BIT); /* * Check to see if offload can be enabled.
*/ if (offload_enabled) {
rc = hpsa_get_raid_map(h, scsi3addr, this_device); if (rc) /* could not load raid_map */ goto out;
this_device->offload_to_be_enabled = 1;
}
}
out:
kfree(buf); return;
}
/* Get the device id from inquiry page 0x83 */ staticint hpsa_get_device_id(struct ctlr_info *h, unsignedchar *scsi3addr, unsignedchar *device_id, int index, int buflen)
{ int rc; unsignedchar *buf;
/* Does controller have VPD for device id? */ if (!hpsa_vpd_page_supported(h, scsi3addr, HPSA_VPD_LV_DEVICE_ID)) return 1; /* not supported */
buf = kzalloc(64, GFP_KERNEL); if (!buf) return -ENOMEM;
staticinlinevoid hpsa_set_bus_target_lun(struct hpsa_scsi_dev_t *device, int bus, int target, int lun)
{
device->bus = bus;
device->target = target;
device->lun = lun;
}
/* Use VPD inquiry to get details of volume status */ staticint hpsa_get_volume_status(struct ctlr_info *h, unsignedchar scsi3addr[])
{ int rc; int status; int size; unsignedchar *buf;
buf = kzalloc(64, GFP_KERNEL); if (!buf) return HPSA_VPD_LV_STATUS_UNSUPPORTED;
/* Does controller have VPD for logical volume status? */ if (!hpsa_vpd_page_supported(h, scsi3addr, HPSA_VPD_LV_STATUS)) goto exit_failed;
/* Get the size of the VPD return buffer */
rc = hpsa_scsi_do_inquiry(h, scsi3addr, VPD_PAGE | HPSA_VPD_LV_STATUS,
buf, HPSA_VPD_HEADER_SZ); if (rc != 0) goto exit_failed;
size = buf[3];
/* Now get the whole VPD buffer */
rc = hpsa_scsi_do_inquiry(h, scsi3addr, VPD_PAGE | HPSA_VPD_LV_STATUS,
buf, size + HPSA_VPD_HEADER_SZ); if (rc != 0) goto exit_failed;
status = buf[4]; /* status byte */
/* Determine offline status of a volume. * Return either: * 0 (not offline) * 0xff (offline for unknown reasons) * # (integer code indicating one of several NOT READY states * describing why a volume is to be kept offline)
*/ staticunsignedchar hpsa_volume_offline(struct ctlr_info *h, unsignedchar scsi3addr[])
{ struct CommandList *c; unsignedchar *sense;
u8 sense_key, asc, ascq; int sense_len; int rc, ldstat = 0; #define ASC_LUN_NOT_READY 0x04 #define ASCQ_LUN_NOT_READY_FORMAT_IN_PROGRESS 0x04 #define ASCQ_LUN_NOT_READY_INITIALIZING_CMD_REQ 0x02
/* Determine the reason for not ready state */
ldstat = hpsa_get_volume_status(h, scsi3addr);
/* Keep volume offline in certain cases: */ switch (ldstat) { case HPSA_LV_FAILED: case HPSA_LV_UNDERGOING_ERASE: case HPSA_LV_NOT_AVAILABLE: case HPSA_LV_UNDERGOING_RPI: case HPSA_LV_PENDING_RPI: case HPSA_LV_ENCRYPTED_NO_KEY: case HPSA_LV_PLAINTEXT_IN_ENCRYPT_ONLY_CONTROLLER: case HPSA_LV_UNDERGOING_ENCRYPTION: case HPSA_LV_UNDERGOING_ENCRYPTION_REKEYING: case HPSA_LV_ENCRYPTED_IN_NON_ENCRYPTED_CONTROLLER: return ldstat; case HPSA_VPD_LV_STATUS_UNSUPPORTED: /* If VPD status page isn't available, * use ASC/ASCQ to determine state
*/ if ((ascq == ASCQ_LUN_NOT_READY_FORMAT_IN_PROGRESS) ||
(ascq == ASCQ_LUN_NOT_READY_INITIALIZING_CMD_REQ)) return ldstat; break; default: break;
} return HPSA_LV_OK;
}
/* Do an inquiry to the device to see what it is. */ if (hpsa_scsi_do_inquiry(h, scsi3addr, 0, inq_buff,
(unsignedchar) OBDR_TAPE_INQ_SIZE) != 0) {
dev_err(&h->pdev->dev, "%s: inquiry failed, device will be skipped.\n",
__func__);
rc = HPSA_INQUIRY_FAILED; goto bail_out;
}
hpsa_get_raid_level(h, scsi3addr, &this_device->raid_level); if (h->fw_support & MISC_FW_RAID_OFFLOAD_BASIC)
hpsa_get_ioaccel_status(h, scsi3addr, this_device);
volume_offline = hpsa_volume_offline(h, scsi3addr); if (volume_offline == HPSA_VPD_LV_STATUS_UNSUPPORTED &&
h->legacy_board) { /* * Legacy boards might not support volume status
*/
dev_info(&h->pdev->dev, "C0:T%d:L%d Volume status not available, assuming online.\n",
this_device->target, this_device->lun);
volume_offline = 0;
}
this_device->volume_offline = volume_offline; if (volume_offline == HPSA_LV_FAILED) {
rc = HPSA_LV_FAILED;
dev_err(&h->pdev->dev, "%s: LV failed, device will be skipped.\n",
__func__); goto bail_out;
}
} else {
this_device->raid_level = RAID_UNKNOWN;
this_device->offload_config = 0;
hpsa_turn_off_ioaccel_for_device(this_device);
this_device->hba_ioaccel_enabled = 0;
this_device->volume_offline = 0;
this_device->queue_depth = h->nr_cmds;
}
if (this_device->external)
this_device->queue_depth = EXTERNAL_QD;
if (is_OBDR_device) { /* See if this is a One-Button-Disaster-Recovery device * by looking for "$DR-10" at offset 43 in inquiry data.
*/
obdr_sig = &inq_buff[OBDR_SIG_OFFSET];
*is_OBDR_device = (this_device->devtype == TYPE_ROM &&
strncmp(obdr_sig, OBDR_TAPE_SIG,
OBDR_SIG_LEN) == 0);
}
kfree(inq_buff); return 0;
bail_out:
kfree(inq_buff); return rc;
}
/* * Helper function to assign bus, target, lun mapping of devices. * Logical drive target and lun are assigned at this time, but * physical device lun and target assignment are deferred (assigned * in hpsa_find_target_lun, called by hpsa_scsi_add_entry.)
*/ staticvoid figure_bus_target_lun(struct ctlr_info *h,
u8 *lunaddrbytes, struct hpsa_scsi_dev_t *device)
{
u32 lunid = get_unaligned_le32(lunaddrbytes);
if (!is_logical_dev_addr_mode(lunaddrbytes)) { /* physical device, target and lun filled in later */ if (is_hba_lunid(lunaddrbytes)) { int bus = HPSA_HBA_BUS;
staticint figure_external_status(struct ctlr_info *h, int raid_ctlr_position, int i, int nphysicals, int nlocal_logicals)
{ /* In report logicals, local logicals are listed first, * then any externals.
*/ int logicals_start = nphysicals + (raid_ctlr_position == 0);
if (i == raid_ctlr_position) return 0;
if (i < logicals_start) return 0;
/* i is in logicals range, but still within local logicals */ if ((i - nphysicals - (raid_ctlr_position == 0)) < nlocal_logicals) return 0;
return 1; /* it's an external lun */
}
/* * Do CISS_REPORT_PHYS and CISS_REPORT_LOG. Data is returned in physdev, * logdev. The number of luns in physdev and logdev are returned in * *nphysicals and *nlogicals, respectively. * Returns 0 on success, -1 otherwise.
*/ staticint hpsa_gather_lun_info(struct ctlr_info *h, struct ReportExtendedLUNdata *physdev, u32 *nphysicals, struct ReportLUNdata *logdev, u32 *nlogicals)
{ if (hpsa_scsi_do_report_phys_luns(h, physdev, sizeof(*physdev))) {
dev_err(&h->pdev->dev, "report physical LUNs failed.\n"); return -1;
}
*nphysicals = be32_to_cpu(*((__be32 *)physdev->LUNListLength)) / 24; if (*nphysicals > HPSA_MAX_PHYS_LUN) {
dev_warn(&h->pdev->dev, "maximum physical LUNs (%d) exceeded. %d LUNs ignored.\n",
HPSA_MAX_PHYS_LUN, *nphysicals - HPSA_MAX_PHYS_LUN);
*nphysicals = HPSA_MAX_PHYS_LUN;
} if (hpsa_scsi_do_report_log_luns(h, logdev, sizeof(*logdev))) {
dev_err(&h->pdev->dev, "report logical LUNs failed.\n"); return -1;
}
*nlogicals = be32_to_cpu(*((__be32 *) logdev->LUNListLength)) / 8; /* Reject Logicals in excess of our max capability. */ if (*nlogicals > HPSA_MAX_LUN) {
dev_warn(&h->pdev->dev, "maximum logical LUNs (%d) exceeded. " "%d LUNs ignored.\n", HPSA_MAX_LUN,
*nlogicals - HPSA_MAX_LUN);
*nlogicals = HPSA_MAX_LUN;
} if (*nlogicals + *nphysicals > HPSA_MAX_PHYS_LUN) {
dev_warn(&h->pdev->dev, "maximum logical + physical LUNs (%d) exceeded. " "%d LUNs ignored.\n", HPSA_MAX_PHYS_LUN,
*nphysicals + *nlogicals - HPSA_MAX_PHYS_LUN);
*nlogicals = HPSA_MAX_PHYS_LUN - *nphysicals;
} return 0;
}
static u8 *figure_lunaddrbytes(struct ctlr_info *h, int raid_ctlr_position, int i, int nphysicals, int nlogicals, struct ReportExtendedLUNdata *physdev_list, struct ReportLUNdata *logdev_list)
{ /* Helper function, figure out where the LUN ID info is coming from * given index i, lists of physical and logical devices, where in * the list the raid controller is supposed to appear (first or last)
*/
int logicals_start = nphysicals + (raid_ctlr_position == 0); int last_device = nphysicals + nlogicals + (raid_ctlr_position == 0);
if (i == raid_ctlr_position) return RAID_CTLR_LUNID;
if (i < logicals_start) return &physdev_list->LUN[i -
(raid_ctlr_position == 0)].lunid[0];
if (i < last_device) return &logdev_list->LUN[i - nphysicals -
(raid_ctlr_position == 0)][0];
BUG(); return NULL;
}
/* get physical drive ioaccel handle and queue depth */ staticvoid hpsa_get_ioaccel_drive_info(struct ctlr_info *h, struct hpsa_scsi_dev_t *dev, struct ReportExtendedLUNdata *rlep, int rle_index, struct bmic_identify_physical_device *id_phys)
{ int rc; struct ext_report_lun_entry *rle;
if (rle_index < 0 || rle_index >= HPSA_MAX_PHYS_LUN) return;
/* get number of local logical disks. */ staticint hpsa_set_local_logical_count(struct ctlr_info *h, struct bmic_identify_controller *id_ctlr,
u32 *nlocals)
{ int rc;
if (device_flags & RPL_DEV_FLAG_NON_DISK) { if (device_type == BMIC_DEVICE_TYPE_ENCLOSURE) returnfalse; returntrue;
}
if (!(device_flags & RPL_DEV_FLAG_UNCONFIG_DISK_REPORTING_SUPPORTED)) returnfalse;
if (device_flags & RPL_DEV_FLAG_UNCONFIG_DISK) returnfalse;
/* * Spares may be spun down, we do not want to * do an Inquiry to a RAID set spare drive as * that would have them spun up, that is a * performance hit because I/O to the RAID device * stops while the spin up occurs which can take * over 50 seconds.
*/ if (hpsa_is_disk_spare(h, lunaddrbytes)) returntrue;
returnfalse;
}
staticvoid hpsa_update_scsi_devices(struct ctlr_info *h)
{ /* the idea here is we could get notified * that some devices have changed, so we do a report * physical luns and report logical luns cmd, and adjust * our list of devices accordingly. * * The scsi3addr's of devices won't change so long as the * adapter is not reset. That means we can rescan and * tell which devices we already know about, vs. new * devices, vs. disappearing devices.
*/ struct ReportExtendedLUNdata *physdev_list = NULL; struct ReportLUNdata *logdev_list = NULL; struct bmic_identify_physical_device *id_phys = NULL; struct bmic_identify_controller *id_ctlr = NULL;
u32 nphysicals = 0;
u32 nlogicals = 0;
u32 nlocal_logicals = 0;
u32 ndev_allocated = 0; struct hpsa_scsi_dev_t **currentsd, *this_device, *tmpdevice; int ncurrent = 0; int i, ndevs_to_allocate; int raid_ctlr_position; bool physical_device;
/* Set number of local logicals (non PTRAID) */ if (hpsa_set_local_logical_count(h, id_ctlr, &nlocal_logicals)) {
dev_warn(&h->pdev->dev, "%s: Can't determine number of local logical devices.\n",
__func__);
}
/* We might see up to the maximum number of logical and physical disks * plus external target devices, and a device for the local RAID * controller.
*/
ndevs_to_allocate = nphysicals + nlogicals + MAX_EXT_TARGETS + 1;
hpsa_ext_ctrl_present(h, physdev_list);
/* Allocate the per device structures */ for (i = 0; i < ndevs_to_allocate; i++) { if (i >= HPSA_MAX_DEVICES) {
dev_warn(&h->pdev->dev, "maximum devices (%d) exceeded." " %d devices ignored.\n", HPSA_MAX_DEVICES,
ndevs_to_allocate - HPSA_MAX_DEVICES); break;
}
/* adjust our table of devices */ for (i = 0; i < nphysicals + nlogicals + 1; i++) {
u8 *lunaddrbytes, is_OBDR = 0; int rc = 0; int phys_dev_index = i - (raid_ctlr_position == 0); bool skip_device = false;
memset(tmpdevice, 0, sizeof(*tmpdevice));
physical_device = i < nphysicals + (raid_ctlr_position == 0);
/* Figure out where the LUN ID info is coming from */
lunaddrbytes = figure_lunaddrbytes(h, raid_ctlr_position,
i, nphysicals, nlogicals, physdev_list, logdev_list);
/* Determine if this is a lun from an external target array */
tmpdevice->external =
figure_external_status(h, raid_ctlr_position, i,
nphysicals, nlocal_logicals);
/* * Skip over some devices such as a spare.
*/ if (phys_dev_index >= 0 && !tmpdevice->external &&
physical_device) {
skip_device = hpsa_skip_device(h, lunaddrbytes,
&physdev_list->LUN[phys_dev_index]); if (skip_device) continue;
}
/* * Expose all devices except for physical devices that * are masked.
*/ if (MASKED_DEVICE(lunaddrbytes) && this_device->physical_device)
this_device->expose_device = 0; else
this_device->expose_device = 1;
/* * Get the SAS address for physical devices that are exposed.
*/ if (this_device->physical_device && this_device->expose_device)
hpsa_get_sas_address(h, lunaddrbytes, this_device);
switch (this_device->devtype) { case TYPE_ROM: /* We don't *really* support actual CD-ROM devices, * just "One Button Disaster Recovery" tape drive * which temporarily pretends to be a CD-ROM drive. * So we check that the device is really an OBDR tape * device by checking for "$DR-10" in bytes 43-48 of * the inquiry data.
*/ if (is_OBDR)
ncurrent++; break; case TYPE_DISK: case TYPE_ZBC: if (this_device->physical_device) { /* The disk is in HBA mode. */ /* Never use RAID mapper in HBA mode. */
this_device->offload_enabled = 0;
hpsa_get_ioaccel_drive_info(h, this_device,
physdev_list, phys_dev_index, id_phys);
hpsa_get_path_info(this_device,
physdev_list, phys_dev_index, id_phys);
}
ncurrent++; break; case TYPE_TAPE: case TYPE_MEDIUM_CHANGER:
ncurrent++; break; case TYPE_ENCLOSURE: if (!this_device->external)
hpsa_get_enclosure_info(h, lunaddrbytes,
physdev_list, phys_dev_index,
this_device);
ncurrent++; break; case TYPE_RAID: /* Only present the Smartarray HBA as a RAID controller. * If it's a RAID controller other than the HBA itself * (an external RAID controller, MSA500 or similar) * don't present it.
*/ if (!is_hba_lunid(lunaddrbytes)) break;
ncurrent++; break; default: break;
} if (ncurrent >= HPSA_MAX_DEVICES) break;
}
if (h->sas_host == NULL) { int rc = 0;
rc = hpsa_add_sas_host(h); if (rc) {
dev_warn(&h->pdev->dev, "Could not add sas host %d\n", rc); goto out;
}
}
adjust_hpsa_scsi_table(h, currentsd, ncurrent);
out:
kfree(tmpdevice); for (i = 0; i < ndev_allocated; i++)
kfree(currentsd[i]);
kfree(currentsd);
kfree(physdev_list);
kfree(logdev_list);
kfree(id_ctlr);
kfree(id_phys);
}
/* * hpsa_scatter_gather takes a struct scsi_cmnd, (cmd), and does the pci * dma mapping and fills in the scatter gather entries of the * hpsa command, cp.
*/ staticint hpsa_scatter_gather(struct ctlr_info *h, struct CommandList *cp, struct scsi_cmnd *cmd)
{ struct scatterlist *sg; int use_sg, i, sg_limit, chained; struct SGDescriptor *curr_sg;
BUG_ON(scsi_sg_count(cmd) > h->maxsgentries);
use_sg = scsi_dma_map(cmd); if (use_sg < 0) return use_sg;
if (!use_sg) goto sglist_finished;
/* * If the number of entries is greater than the max for a single list, * then we have a chained list; we will set up all but one entry in the * first list (the last entry is saved for link information); * otherwise, we don't have a chained list and we'll set up at each of * the entries in the one list.
*/
curr_sg = cp->SG;
chained = use_sg > h->max_cmd_sg_entries;
sg_limit = chained ? h->max_cmd_sg_entries - 1 : use_sg;
scsi_for_each_sg(cmd, sg, sg_limit, i) {
hpsa_set_sg_descriptor(curr_sg, sg);
curr_sg++;
}
if (chained) { /* * Continue with the chained list. Set curr_sg to the chained * list. Modify the limit to the total count less the entries * we've already set up. Resume the scan at the list entry * where the previous loop left off.
*/
curr_sg = h->cmd_sg_list[cp->cmdindex];
sg_limit = use_sg - sg_limit;
for_each_sg(sg, sg, sg_limit, i) {
hpsa_set_sg_descriptor(curr_sg, sg);
curr_sg++;
}
}
/* Back the pointer up to the last entry and mark it as "last". */
(curr_sg - 1)->Ext = cpu_to_le32(HPSA_SG_LAST);
/* Block zero-length transfer sizes on certain commands. */ switch (cdb[0]) { case READ_10: case WRITE_10: case VERIFY: /* 0x2F */ case WRITE_VERIFY: /* 0x2E */
block_cnt = get_unaligned_be16(&cdb[7]); break; case READ_12: case WRITE_12: case VERIFY_12: /* 0xAF */ case WRITE_VERIFY_12: /* 0xAE */
block_cnt = get_unaligned_be32(&cdb[6]); break; case READ_16: case WRITE_16: case VERIFY_16: /* 0x8F */
block_cnt = get_unaligned_be32(&cdb[10]); break; default: returnfalse;
}
return block_cnt == 0;
}
staticint fixup_ioaccel_cdb(u8 *cdb, int *cdb_len)
{ int is_write = 0;
u32 block;
u32 block_cnt;
/* Perform some CDB fixups if needed using 10 byte reads/writes only */ switch (cdb[0]) { case WRITE_6: case WRITE_12:
is_write = 1;
fallthrough; case READ_6: case READ_12: if (*cdb_len == 6) {
block = (((cdb[1] & 0x1F) << 16) |
(cdb[2] << 8) |
cdb[3]);
block_cnt = cdb[4]; if (block_cnt == 0)
block_cnt = 256;
} else {
BUG_ON(*cdb_len != 12);
block = get_unaligned_be32(&cdb[2]);
block_cnt = get_unaligned_be32(&cdb[6]);
} if (block_cnt > 0xffff) return IO_ACCEL_INELIGIBLE;
if (fixup_ioaccel_cdb(cdb, &cdb_len)) {
atomic_dec(&phys_disk->ioaccel_cmds_out); return IO_ACCEL_INELIGIBLE;
}
c->cmd_type = CMD_IOACCEL1;
/* Adjust the DMA address to point to the accelerated command buffer */
c->busaddr = (u32) h->ioaccel_cmd_pool_dhandle +
(c->cmdindex * sizeof(*cp));
BUG_ON(c->busaddr & 0x0000007F);
switch (cmd->sc_data_direction) { case DMA_TO_DEVICE:
control |= IOACCEL1_CONTROL_DATA_OUT; break; case DMA_FROM_DEVICE:
control |= IOACCEL1_CONTROL_DATA_IN; break; case DMA_NONE:
control |= IOACCEL1_CONTROL_NODATAXFER; break; default:
dev_err(&h->pdev->dev, "unknown data direction: %d\n",
cmd->sc_data_direction);
BUG(); break;
}
} else {
control |= IOACCEL1_CONTROL_NODATAXFER;
}
c->Header.SGList = use_sg; /* Fill out the command structure to submit */
cp->dev_handle = cpu_to_le16(ioaccel_handle & 0xFFFF);
cp->transfer_len = cpu_to_le32(total_len);
cp->io_flags = cpu_to_le16(IOACCEL1_IOFLAGS_IO_REQ |
(cdb_len & IOACCEL1_IOFLAGS_CDBLEN_MASK));
cp->control = cpu_to_le32(control);
memcpy(cp->CDB, cdb, cdb_len);
memcpy(cp->CISS_LUN, scsi3addr, 8); /* Tag was already set at init time. */
enqueue_cmd_and_start_io(h, c); return 0;
}
/* * Queue a command directly to a device behind the controller using the * I/O accelerator path.
*/ staticint hpsa_scsi_ioaccel_direct_map(struct ctlr_info *h, struct CommandList *c)
{ struct scsi_cmnd *cmd = c->scsi_cmd; struct hpsa_scsi_dev_t *dev = cmd->device->hostdata;
/* Are we doing encryption on this device */ if (!(le16_to_cpu(map->flags) & RAID_MAP_FLAG_ENCRYPT_ON)) return; /* Set the data encryption key index. */
cp->dekindex = map->dekindex;
/* Set the encryption enable flag, encoded into direction field. */
cp->direction |= IOACCEL2_DIRECTION_ENCRYPT_MASK;
/* Set encryption tweak values based on logical block address * If block size is 512, tweak value is LBA. * For other block sizes, tweak is (LBA * block size)/ 512)
*/ switch (cmd->cmnd[0]) { /* Required? 6-byte cdbs eliminated by fixup_ioaccel_cdb */ case READ_6: case WRITE_6:
first_block = (((cmd->cmnd[1] & 0x1F) << 16) |
(cmd->cmnd[2] << 8) |
cmd->cmnd[3]); break; case WRITE_10: case READ_10: /* Required? 12-byte cdbs eliminated by fixup_ioaccel_cdb */ case WRITE_12: case READ_12:
first_block = get_unaligned_be32(&cmd->cmnd[2]); break; case WRITE_16: case READ_16:
first_block = get_unaligned_be64(&cmd->cmnd[2]); break; default:
dev_err(&h->pdev->dev, "ERROR: %s: size (0x%x) not supported for encryption\n",
__func__, cmd->cmnd[0]);
BUG(); break;
}
if (le32_to_cpu(map->volume_blk_size) != 512)
first_block = first_block *
le32_to_cpu(map->volume_blk_size)/512;
/* * Queue a command to the correct I/O accelerator path.
*/ staticint hpsa_scsi_ioaccel_queue_command(struct ctlr_info *h, struct CommandList *c, u32 ioaccel_handle, u8 *cdb, int cdb_len,
u8 *scsi3addr, struct hpsa_scsi_dev_t *phys_disk)
{ if (!c->scsi_cmd->device) return -1;
if (!c->scsi_cmd->device->hostdata) return -1;
if (phys_disk->in_reset) return -1;
/* Try to honor the device's queue depth */ if (atomic_inc_return(&phys_disk->ioaccel_cmds_out) >
phys_disk->queue_depth) {
atomic_dec(&phys_disk->ioaccel_cmds_out); return IO_ACCEL_INELIGIBLE;
} if (h->transMethod & CFGTBL_Trans_io_accel1) return hpsa_scsi_ioaccel1_queue_command(h, c, ioaccel_handle,
cdb, cdb_len, scsi3addr,
phys_disk); else return hpsa_scsi_ioaccel2_queue_command(h, c, ioaccel_handle,
cdb, cdb_len, scsi3addr,
phys_disk);
}
staticvoid raid_map_helper(struct raid_map_data *map, int offload_to_mirror, u32 *map_index, u32 *current_group)
{ if (offload_to_mirror == 0) { /* use physical disk in the first mirrored group. */
*map_index %= le16_to_cpu(map->data_disks_per_row); return;
} do { /* determine mirror group that *map_index indicates */
*current_group = *map_index /
le16_to_cpu(map->data_disks_per_row); if (offload_to_mirror == *current_group) continue; if (*current_group < le16_to_cpu(map->layout_map_count) - 1) { /* select map index from next group */
*map_index += le16_to_cpu(map->data_disks_per_row);
(*current_group)++;
} else { /* select map index from first group */
*map_index %= le16_to_cpu(map->data_disks_per_row);
*current_group = 0;
}
} while (offload_to_mirror != *current_group);
}
/* if this isn't a single row/column then give to the controller */ if ((first_row != last_row) || (first_column != last_column)) return IO_ACCEL_INELIGIBLE;
switch (dev->raid_level) { case HPSA_RAID_0: break; /* nothing special to do */ case HPSA_RAID_1: /* Handles load balance across RAID 1 members. * (2-drive R1 and R10 with even # of drives.) * Appropriate for SSDs, not optimal for HDDs * Ensure we have the correct raid_map.
*/ if (le16_to_cpu(map->layout_map_count) != 2) {
hpsa_turn_off_ioaccel_for_device(dev); return IO_ACCEL_INELIGIBLE;
} if (dev->offload_to_mirror)
map_index += le16_to_cpu(map->data_disks_per_row);
dev->offload_to_mirror = !dev->offload_to_mirror; break; case HPSA_RAID_ADM: /* Handles N-way mirrors (R1-ADM) * and R10 with # of drives divisible by 3.) * Ensure we have the correct raid_map.
*/ if (le16_to_cpu(map->layout_map_count) != 3) {
hpsa_turn_off_ioaccel_for_device(dev); return IO_ACCEL_INELIGIBLE;
}
offload_to_mirror = dev->offload_to_mirror;
raid_map_helper(map, offload_to_mirror,
&map_index, ¤t_group); /* set mirror group to use next time */
offload_to_mirror =
(offload_to_mirror >=
le16_to_cpu(map->layout_map_count) - 1)
? 0 : offload_to_mirror + 1;
dev->offload_to_mirror = offload_to_mirror; /* Avoid direct use of dev->offload_to_mirror within this * function since multiple threads might simultaneously * increment it beyond the range of dev->layout_map_count -1.
*/ break; case HPSA_RAID_5: case HPSA_RAID_6: if (le16_to_cpu(map->layout_map_count) <= 1) break;
/* Verify first and last block are in same RAID group */
r5or6_blocks_per_row =
le16_to_cpu(map->strip_size) *
le16_to_cpu(map->data_disks_per_row); if (r5or6_blocks_per_row == 0) {
hpsa_turn_off_ioaccel_for_device(dev); return IO_ACCEL_INELIGIBLE;
}
stripesize = r5or6_blocks_per_row *
le16_to_cpu(map->layout_map_count); #if BITS_PER_LONG == 32
tmpdiv = first_block;
first_group = do_div(tmpdiv, stripesize);
tmpdiv = first_group;
(void) do_div(tmpdiv, r5or6_blocks_per_row);
first_group = tmpdiv;
tmpdiv = last_block;
last_group = do_div(tmpdiv, stripesize);
tmpdiv = last_group;
(void) do_div(tmpdiv, r5or6_blocks_per_row);
last_group = tmpdiv; #else
first_group = (first_block % stripesize) / r5or6_blocks_per_row;
last_group = (last_block % stripesize) / r5or6_blocks_per_row; #endif if (first_group != last_group) return IO_ACCEL_INELIGIBLE;
/* * Submit commands down the "normal" RAID stack path * All callers to hpsa_ciss_submit must check lockup_detected * beforehand, before (opt.) and after calling cmd_alloc
*/ staticint hpsa_ciss_submit(struct ctlr_info *h, struct CommandList *c, struct scsi_cmnd *cmd, struct hpsa_scsi_dev_t *dev)
{
cmd->host_scribble = (unsignedchar *) c;
c->cmd_type = CMD_SCSI;
c->scsi_cmd = cmd;
c->Header.ReplyQueue = 0; /* unused in simple mode */
memcpy(&c->Header.LUN.LunAddrBytes[0], &dev->scsi3addr[0], 8);
c->Header.tag = cpu_to_le64((c->cmdindex << DIRECT_LOOKUP_SHIFT));
/* Fill in the request block... */
c->Request.Timeout = 0;
BUG_ON(cmd->cmd_len > sizeof(c->Request.CDB));
c->Request.CDBLen = cmd->cmd_len;
memcpy(c->Request.CDB, cmd->cmnd, cmd->cmd_len); switch (cmd->sc_data_direction) { case DMA_TO_DEVICE:
c->Request.type_attr_dir =
TYPE_ATTR_DIR(TYPE_CMD, ATTR_SIMPLE, XFER_WRITE); break; case DMA_FROM_DEVICE:
c->Request.type_attr_dir =
TYPE_ATTR_DIR(TYPE_CMD, ATTR_SIMPLE, XFER_READ); break; case DMA_NONE:
c->Request.type_attr_dir =
TYPE_ATTR_DIR(TYPE_CMD, ATTR_SIMPLE, XFER_NONE); break; case DMA_BIDIRECTIONAL: /* This can happen if a buggy application does a scsi passthru * and sets both inlen and outlen to non-zero. ( see * ../scsi/scsi_ioctl.c:scsi_ioctl_send_command() )
*/
c->Request.type_attr_dir =
TYPE_ATTR_DIR(TYPE_CMD, ATTR_SIMPLE, XFER_RSVD); /* This is technically wrong, and hpsa controllers should * reject it with CMD_INVALID, which is the most correct * response, but non-fibre backends appear to let it * slide by, and give the same results as if this field * were set correctly. Either way is acceptable for * our purposes here.
*/
break;
default:
dev_err(&h->pdev->dev, "unknown data direction: %d\n",
cmd->sc_data_direction);
BUG(); break;
}
if (hpsa_scatter_gather(h, c, cmd) < 0) { /* Fill SG list */
hpsa_cmd_resolve_and_free(h, c); return SCSI_MLQUEUE_HOST_BUSY;
}
if (dev->in_reset) {
hpsa_cmd_resolve_and_free(h, c); return SCSI_MLQUEUE_HOST_BUSY;
}
c->device = dev;
enqueue_cmd_and_start_io(h, c); /* the cmd'll come back via intr handler in complete_scsi_command() */ return 0;
}
if (c->cmd_type == CMD_IOACCEL2) { struct ctlr_info *h = c->h; struct io_accel2_cmd *c2 = &h->ioaccel2_cmd_pool[c->cmdindex]; int rc;
if (c2->error_data.serv_response ==
IOACCEL2_STATUS_SR_TASK_COMP_SET_FULL) { /* Resubmit with the retry_pending flag set. */
rc = hpsa_ioaccel_submit(h, c, cmd, true); if (rc == 0) return; if (rc == SCSI_MLQUEUE_HOST_BUSY) { /* * If we get here, it means dma mapping failed. * Try again via scsi mid layer, which will * then get SCSI_MLQUEUE_HOST_BUSY.
*/
cmd->result = DID_IMM_RETRY << 16; return hpsa_cmd_free_and_done(h, c, cmd);
} /* else, fall thru and resubmit down CISS path */
}
}
hpsa_cmd_partial_init(c->h, c->cmdindex, c); /* * Here we have not come in though queue_command, so we * can set the retry_pending flag to true for a driver initiated * retry attempt (I.E. not a SML retry). * I.E. We are submitting a driver initiated retry. * Note: hpsa_ciss_submit does not zero out the command fields like * ioaccel submit does.
*/
c->retry_pending = true; if (hpsa_ciss_submit(c->h, c, cmd, dev)) { /* * If we get here, it means dma mapping failed. Try * again via scsi mid layer, which will then get * SCSI_MLQUEUE_HOST_BUSY. * * hpsa_ciss_submit will have already freed c * if it encountered a dma mapping failure.
*/
cmd->result = DID_IMM_RETRY << 16;
scsi_done(cmd);
}
}
/* Running in struct Scsi_Host->host_lock less mode */ staticint hpsa_scsi_queue_command(struct Scsi_Host *sh, struct scsi_cmnd *cmd)
{ struct ctlr_info *h; struct hpsa_scsi_dev_t *dev; struct CommandList *c; int rc = 0;
/* Get the ptr to our adapter structure out of cmd->host. */
h = sdev_to_hba(cmd->device);
BUG_ON(scsi_cmd_to_rq(cmd)->tag < 0);
dev = cmd->device->hostdata; if (!dev) {
cmd->result = DID_NO_CONNECT << 16;
scsi_done(cmd); return 0;
}
if (dev->in_reset) return SCSI_MLQUEUE_DEVICE_BUSY;
c = cmd_tagged_alloc(h, cmd); if (c == NULL) return SCSI_MLQUEUE_DEVICE_BUSY;
/* * This is necessary because the SML doesn't zero out this field during * error recovery.
*/
cmd->result = 0;
/* * Call alternate submit routine for I/O accelerated commands. * Retries always go down the normal I/O path. * Note: If cmd->retries is non-zero, then this is a SML * initiated retry and not a driver initiated retry. * This command has been obtained from cmd_tagged_alloc * and is therefore a brand-new command.
*/ if (likely(cmd->retries == 0 &&
!blk_rq_is_passthrough(scsi_cmd_to_rq(cmd)) &&
h->acciopath_status)) { /* Submit with the retry_pending flag unset. */
rc = hpsa_ioaccel_submit(h, c, cmd, false); if (rc == 0) return 0; if (rc == SCSI_MLQUEUE_HOST_BUSY) {
hpsa_cmd_resolve_and_free(h, c); return SCSI_MLQUEUE_HOST_BUSY;
}
} return hpsa_ciss_submit(h, c, cmd, dev);
}
/* * Don't let rescans be initiated on a controller known to be locked * up. If the controller locks up *during* a rescan, that thread is * probably hosed, but at least we can prevent new rescan threads from * piling up on a locked up controller.
*/ if (unlikely(lockup_detected(h))) return hpsa_scan_complete(h);
/* * If a scan is already waiting to run, no need to add another
*/
spin_lock_irqsave(&h->scan_lock, flags); if (h->scan_waiting) {
spin_unlock_irqrestore(&h->scan_lock, flags); return;
}
spin_unlock_irqrestore(&h->scan_lock, flags);
/* wait until any scan already in progress is finished. */ while (1) {
spin_lock_irqsave(&h->scan_lock, flags); if (h->scan_finished) break;
h->scan_waiting = 1;
spin_unlock_irqrestore(&h->scan_lock, flags);
wait_event(h->scan_wait_queue, h->scan_finished); /* Note: We don't need to worry about a race between this * thread and driver unload because the midlayer will * have incremented the reference count, so unload won't * happen if we're in here.
*/
}
h->scan_finished = 0; /* mark scan as in progress */
h->scan_waiting = 0;
spin_unlock_irqrestore(&h->scan_lock, flags);
if (unlikely(lockup_detected(h))) return hpsa_scan_complete(h);
/* * Do the scan after a reset completion
*/
spin_lock_irqsave(&h->reset_lock, flags); if (h->reset_in_progress) {
h->drv_req_rescan = 1;
spin_unlock_irqrestore(&h->reset_lock, flags);
hpsa_scan_complete(h); return;
}
spin_unlock_irqrestore(&h->reset_lock, flags);
/* * The block layer has already gone to the trouble of picking out a unique, * small-integer tag for this request. We use an offset from that value as * an index to select our command block. (The offset allows us to reserve the * low-numbered entries for our own uses.)
*/ staticint hpsa_get_cmd_index(struct scsi_cmnd *scmd)
{ int idx = scsi_cmd_to_rq(scmd)->tag;
if (idx < 0) return idx;
/* Offset to leave space for internal cmds. */ return idx += HPSA_NRESERVED_CMDS;
}
/* * Send a TEST_UNIT_READY command to the specified LUN using the specified * reply queue; returns zero if the unit is ready, and non-zero otherwise.
*/ staticint hpsa_send_test_unit_ready(struct ctlr_info *h, struct CommandList *c, unsignedchar lunaddr[], int reply_queue)
{ int rc;
/* Send the Test Unit Ready, fill_cmd can't fail, no mapping */
(void) fill_cmd(c, TEST_UNIT_READY, h,
NULL, 0, 0, lunaddr, TYPE_CMD);
rc = hpsa_scsi_do_simple_cmd(h, c, reply_queue, NO_TIMEOUT); if (rc) return rc; /* no unmap needed here because no data xfer. */
/* Check if the unit is already ready. */ if (c->err_info->CommandStatus == CMD_SUCCESS) return 0;
/* * The first command sent after reset will receive "unit attention" to * indicate that the LUN has been reset...this is actually what we're * looking for (but, success is good too).
*/ if (c->err_info->CommandStatus == CMD_TARGET_STATUS &&
c->err_info->ScsiStatus == SAM_STAT_CHECK_CONDITION &&
(c->err_info->SenseInfo[2] == NO_SENSE ||
c->err_info->SenseInfo[2] == UNIT_ATTENTION)) return 0;
return 1;
}
/* * Wait for a TEST_UNIT_READY command to complete, retrying as necessary; * returns zero when the unit is ready, and non-zero when giving up.
*/ staticint hpsa_wait_for_test_unit_ready(struct ctlr_info *h, struct CommandList *c, unsignedchar lunaddr[], int reply_queue)
{ int rc; int count = 0; int waittime = 1; /* seconds */
/* Send test unit ready until device ready, or give up. */ for (count = 0; count < HPSA_TUR_RETRY_LIMIT; count++) {
/* * Wait for a bit. do this first, because if we send * the TUR right away, the reset will just abort it.
*/
msleep(1000 * waittime);
rc = hpsa_send_test_unit_ready(h, c, lunaddr, reply_queue); if (!rc) break;
/* Increase wait time with each try, up to a point. */ if (waittime < HPSA_MAX_WAIT_INTERVAL_SECS)
waittime *= 2;
dev_warn(&h->pdev->dev, "waiting %d secs for device to become ready.\n",
waittime);
}
return rc;
}
staticint wait_for_device_to_become_ready(struct ctlr_info *h, unsignedchar lunaddr[], int reply_queue)
{ int first_queue; int last_queue; int rq; int rc = 0; struct CommandList *c;
c = cmd_alloc(h);
/* * If no specific reply queue was requested, then send the TUR * repeatedly, requesting a reply on each reply queue; otherwise execute * the loop exactly once using only the specified queue.
*/ if (reply_queue == DEFAULT_REPLY_QUEUE) {
first_queue = 0;
last_queue = h->nreply_queues - 1;
} else {
first_queue = reply_queue;
last_queue = reply_queue;
}
for (rq = first_queue; rq <= last_queue; rq++) {
rc = hpsa_wait_for_test_unit_ready(h, c, lunaddr, rq); if (rc) break;
}
if (rc)
dev_warn(&h->pdev->dev, "giving up on device.\n"); else
dev_warn(&h->pdev->dev, "device is ready.\n");
cmd_free(h, c); return rc;
}
/* Need at least one of these error handlers to keep ../scsi/hosts.c from * complaining. Doing a host- or bus-reset can't do anything good here.
*/ staticint hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd)
{ int rc = SUCCESS; int i; struct ctlr_info *h; struct hpsa_scsi_dev_t *dev = NULL;
u8 reset_type; char msg[48]; unsignedlong flags;
/* find the controller to which the command to be aborted was sent */
h = sdev_to_hba(scsicmd->device); if (h == NULL) /* paranoia */ return FAILED;
/* if controller locked up, we can guarantee command won't complete */ if (lockup_detected(h)) {
snprintf(msg, sizeof(msg), "cmd %d RESET FAILED, lockup detected",
hpsa_get_cmd_index(scsicmd));
hpsa_show_dev_msg(KERN_WARNING, h, dev, msg);
rc = FAILED; goto return_reset_status;
}
/* this reset request might be the result of a lockup; check */ if (detect_controller_lockup(h)) {
snprintf(msg, sizeof(msg), "cmd %d RESET FAILED, new lockup detected",
hpsa_get_cmd_index(scsicmd));
hpsa_show_dev_msg(KERN_WARNING, h, dev, msg);
rc = FAILED; goto return_reset_status;
}
/* Do not attempt on controller */ if (is_hba_lunid(dev->scsi3addr)) {
rc = SUCCESS; goto return_reset_status;
}
if (is_logical_dev_addr_mode(dev->scsi3addr))
reset_type = HPSA_DEVICE_RESET_MSG; else
reset_type = HPSA_PHYS_TARGET_RESET;
/* * wait to see if any commands will complete before sending reset
*/
dev->in_reset = true; /* block any new cmds from OS for this device */ for (i = 0; i < 10; i++) { if (atomic_read(&dev->commands_outstanding) > 0)
msleep(1000); else break;
}
/* send a reset to the SCSI LUN which the command was sent to */
rc = hpsa_do_reset(h, dev, reset_type, DEFAULT_REPLY_QUEUE); if (rc == 0)
rc = SUCCESS; else
rc = FAILED;
/* * For operations with an associated SCSI command, a command block is allocated * at init, and managed by cmd_tagged_alloc() and cmd_tagged_free() using the * block request tag as an index into a table of entries. cmd_tagged_free() is * the complement, although cmd_free() may be called instead. * This function is only called for new requests from queue_command.
*/ staticstruct CommandList *cmd_tagged_alloc(struct ctlr_info *h, struct scsi_cmnd *scmd)
{ int idx = hpsa_get_cmd_index(scmd); struct CommandList *c = h->cmd_pool + idx;
if (idx < HPSA_NRESERVED_CMDS || idx >= h->nr_cmds) {
dev_err(&h->pdev->dev, "Bad block tag: %d not in [%d..%d]\n",
idx, HPSA_NRESERVED_CMDS, h->nr_cmds - 1); /* The index value comes from the block layer, so if it's out of * bounds, it's probably not our bug.
*/
BUG();
}
if (unlikely(!hpsa_is_cmd_idle(c))) { /* * We expect that the SCSI layer will hand us a unique tag * value. Thus, there should never be a collision here between * two requests...because if the selected command isn't idle * then someone is going to be very disappointed.
*/ if (idx != h->last_collision_tag) { /* Print once per tag */
dev_warn(&h->pdev->dev, "%s: tag collision (tag=%d)\n", __func__, idx); if (scmd)
scsi_print_command(scmd);
h->last_collision_tag = idx;
} return NULL;
}
/* * This is a new command obtained from queue_command so * there have not been any driver initiated retry attempts.
*/
c->retry_pending = false;
return c;
}
staticvoid cmd_tagged_free(struct ctlr_info *h, struct CommandList *c)
{ /* * Release our reference to the block. We don't need to do anything * else to free it, because it is accessed by index.
*/
(void)atomic_dec(&c->refcount);
}
/* * For operations that cannot sleep, a command block is allocated at init, * and managed by cmd_alloc() and cmd_free() using a simple bitmap to track * which ones are free or in use. Lock must be held when calling this. * cmd_free() is the complement. * This function never gives up and returns NULL. If it hangs, * another thread must call cmd_free() to free some tags.
*/
staticstruct CommandList *cmd_alloc(struct ctlr_info *h)
{ struct CommandList *c; int refcount, i; int offset = 0;
/* * There is some *extremely* small but non-zero chance that that * multiple threads could get in here, and one thread could * be scanning through the list of bits looking for a free * one, but the free ones are always behind him, and other * threads sneak in behind him and eat them before he can * get to them, so that while there is always a free one, a * very unlucky thread might be starved anyway, never able to * beat the other threads. In reality, this happens so * infrequently as to be indistinguishable from never. * * Note that we start allocating commands before the SCSI host structure * is initialized. Since the search starts at bit zero, this * all works, since we have at least one command structure available; * however, it means that the structures with the low indexes have to be * reserved for driver-initiated requests, while requests from the block * layer will use the higher indexes.
*/
for (;;) {
i = find_next_zero_bit(h->cmd_pool_bits,
HPSA_NRESERVED_CMDS,
offset); if (unlikely(i >= HPSA_NRESERVED_CMDS)) {
offset = 0; continue;
}
c = h->cmd_pool + i;
refcount = atomic_inc_return(&c->refcount); if (unlikely(refcount > 1)) {
cmd_free(h, c); /* already in use */
offset = (i + 1) % HPSA_NRESERVED_CMDS; continue;
}
set_bit(i, h->cmd_pool_bits); break; /* it's ours now. */
}
hpsa_cmd_partial_init(h, i, c);
c->device = NULL;
/* * cmd_alloc is for "internal" commands and they are never * retried.
*/
c->retry_pending = false;
return c;
}
/* * This is the complementary operation to cmd_alloc(). Note, however, in some * corner cases it may also be used to free blocks allocated by * cmd_tagged_alloc() in which case the ref-count decrement does the trick and * the clear-bit is harmless.
*/ staticvoid cmd_free(struct ctlr_info *h, struct CommandList *c)
{ if (atomic_dec_and_test(&c->refcount)) { int i;
i = c - h->cmd_pool;
clear_bit(i, h->cmd_pool_bits);
}
}
if (!arg) return -EINVAL;
memset(&arg64, 0, sizeof(arg64)); if (copy_from_user(&arg64, arg32,
offsetof(BIG_IOCTL32_Command_struct, buf))) return -EFAULT; if (get_user(cp, &arg32->buf)) return -EFAULT;
arg64.buf = compat_ptr(cp);
if (atomic_dec_if_positive(&h->passthru_cmds_avail) < 0) return -EAGAIN;
err = hpsa_big_passthru_ioctl(h, &arg64);
atomic_inc(&h->passthru_cmds_avail); if (err) return err; if (copy_to_user(&arg32->error_info, &arg64.error_info, sizeof(arg32->error_info))) return -EFAULT; return 0;
}
staticint hpsa_compat_ioctl(struct scsi_device *dev, unsignedint cmd, void __user *arg)
{ switch (cmd) { case CCISS_GETPCIINFO: case CCISS_GETINTINFO: case CCISS_SETINTINFO: case CCISS_GETNODENAME: case CCISS_SETNODENAME: case CCISS_GETHEARTBEAT: case CCISS_GETBUSTYPES: case CCISS_GETFIRMVER: case CCISS_GETDRIVVER: case CCISS_REVALIDVOLS: case CCISS_DEREGDISK: case CCISS_REGNEWDISK: case CCISS_REGNEWD: case CCISS_RESCANDISK: case CCISS_GETLUNINFO: return hpsa_ioctl(dev, cmd, arg);
case CCISS_PASSTHRU32: return hpsa_ioctl32_passthru(dev, cmd, arg); case CCISS_BIG_PASSTHRU32: return hpsa_ioctl32_big_passthru(dev, cmd, arg);
if (!capable(CAP_SYS_RAWIO)) return -EPERM; if ((iocommand->buf_size < 1) &&
(iocommand->Request.Type.Direction != XFER_NONE)) { return -EINVAL;
} if (iocommand->buf_size > 0) {
buff = kmalloc(iocommand->buf_size, GFP_KERNEL); if (buff == NULL) return -ENOMEM; if (iocommand->Request.Type.Direction & XFER_WRITE) { /* Copy the data into the buffer we created */ if (copy_from_user(buff, iocommand->buf,
iocommand->buf_size)) {
rc = -EFAULT; goto out_kfree;
}
} else {
memset(buff, 0, iocommand->buf_size);
}
}
c = cmd_alloc(h);
/* Fill in the command type */
c->cmd_type = CMD_IOCTL_PEND;
c->scsi_cmd = SCSI_CMD_BUSY; /* Fill in Command Header */
c->Header.ReplyQueue = 0; /* unused in simple mode */ if (iocommand->buf_size > 0) { /* buffer to fill */
c->Header.SGList = 1;
c->Header.SGTotal = cpu_to_le16(1);
} else { /* no buffers to fill */
c->Header.SGList = 0;
c->Header.SGTotal = cpu_to_le16(0);
}
memcpy(&c->Header.LUN, &iocommand->LUN_info, sizeof(c->Header.LUN));
/* Fill in Request block */
memcpy(&c->Request, &iocommand->Request, sizeof(c->Request));
/* Fill in the scatter gather information */ if (iocommand->buf_size > 0) {
temp64 = dma_map_single(&h->pdev->dev, buff,
iocommand->buf_size, DMA_BIDIRECTIONAL); if (dma_mapping_error(&h->pdev->dev, (dma_addr_t) temp64)) {
c->SG[0].Addr = cpu_to_le64(0);
c->SG[0].Len = cpu_to_le32(0);
rc = -ENOMEM; goto out;
}
c->SG[0].Addr = cpu_to_le64(temp64);
c->SG[0].Len = cpu_to_le32(iocommand->buf_size);
c->SG[0].Ext = cpu_to_le32(HPSA_SG_LAST); /* not chaining */
}
rc = hpsa_scsi_do_simple_cmd(h, c, DEFAULT_REPLY_QUEUE,
NO_TIMEOUT); if (iocommand->buf_size > 0)
hpsa_pci_unmap(h->pdev, c, 1, DMA_BIDIRECTIONAL);
check_ioctl_unit_attention(h, c); if (rc) {
rc = -EIO; goto out;
}
/* Copy the error information out */
memcpy(&iocommand->error_info, c->err_info, sizeof(iocommand->error_info)); if ((iocommand->Request.Type.Direction & XFER_READ) &&
iocommand->buf_size > 0) { /* Copy the data out of the buffer we created */ if (copy_to_user(iocommand->buf, buff, iocommand->buf_size)) {
rc = -EFAULT; goto out;
}
}
out:
cmd_free(h, c);
out_kfree:
kfree(buff); return rc;
}
if ((ioc->buf_size < 1) &&
(ioc->Request.Type.Direction != XFER_NONE)) return -EINVAL; /* Check kmalloc limits using all SGs */ if (ioc->malloc_size > MAX_KMALLOC_SIZE) return -EINVAL; if (ioc->buf_size > ioc->malloc_size * SG_ENTRIES_IN_CMD) return -EINVAL;
buff = kcalloc(SG_ENTRIES_IN_CMD, sizeof(char *), GFP_KERNEL); if (!buff) {
status = -ENOMEM; goto cleanup1;
}
buff_size = kmalloc_array(SG_ENTRIES_IN_CMD, sizeof(int), GFP_KERNEL); if (!buff_size) {
status = -ENOMEM; goto cleanup1;
}
left = ioc->buf_size;
data_ptr = ioc->buf; while (left) {
sz = (left > ioc->malloc_size) ? ioc->malloc_size : left;
buff_size[sg_used] = sz;
if (ioc->Request.Type.Direction & XFER_WRITE) {
buff[sg_used] = memdup_user(data_ptr, sz); if (IS_ERR(buff[sg_used])) {
status = PTR_ERR(buff[sg_used]); goto cleanup1;
}
} else {
buff[sg_used] = kzalloc(sz, GFP_KERNEL); if (!buff[sg_used]) {
status = -ENOMEM; goto cleanup1;
}
}
left -= sz;
data_ptr += sz;
sg_used++;
}
c = cmd_alloc(h);
c->cmd_type = CMD_IOCTL_PEND;
c->scsi_cmd = SCSI_CMD_BUSY;
c->Header.ReplyQueue = 0;
c->Header.SGList = (u8) sg_used;
c->Header.SGTotal = cpu_to_le16(sg_used);
memcpy(&c->Header.LUN, &ioc->LUN_info, sizeof(c->Header.LUN));
memcpy(&c->Request, &ioc->Request, sizeof(c->Request)); if (ioc->buf_size > 0) { int i; for (i = 0; i < sg_used; i++) {
temp64 = dma_map_single(&h->pdev->dev, buff[i],
buff_size[i], DMA_BIDIRECTIONAL); if (dma_mapping_error(&h->pdev->dev,
(dma_addr_t) temp64)) {
c->SG[i].Addr = cpu_to_le64(0);
c->SG[i].Len = cpu_to_le32(0);
hpsa_pci_unmap(h->pdev, c, i,
DMA_BIDIRECTIONAL);
status = -ENOMEM; goto cleanup0;
}
c->SG[i].Addr = cpu_to_le64(temp64);
c->SG[i].Len = cpu_to_le32(buff_size[i]);
c->SG[i].Ext = cpu_to_le32(0);
}
c->SG[--i].Ext = cpu_to_le32(HPSA_SG_LAST);
}
status = hpsa_scsi_do_simple_cmd(h, c, DEFAULT_REPLY_QUEUE,
NO_TIMEOUT); if (sg_used)
hpsa_pci_unmap(h->pdev, c, sg_used, DMA_BIDIRECTIONAL);
check_ioctl_unit_attention(h, c); if (status) {
status = -EIO; goto cleanup0;
}
/* Copy the error information out */
memcpy(&ioc->error_info, c->err_info, sizeof(ioc->error_info)); if ((ioc->Request.Type.Direction & XFER_READ) && ioc->buf_size > 0) { int i;
/* Copy the data out of the buffer we created */
BYTE __user *ptr = ioc->buf; for (i = 0; i < sg_used; i++) { if (copy_to_user(ptr, buff[i], buff_size[i])) {
status = -EFAULT; goto cleanup0;
}
ptr += buff_size[i];
}
}
status = 0;
cleanup0:
cmd_free(h, c);
cleanup1: if (buff) { int i;
for (i = 0; i < sg_used; i++)
kfree(buff[i]);
kfree(buff);
}
kfree(buff_size); return status;
}
switch (cmd) { case CCISS_DEREGDISK: case CCISS_REGNEWDISK: case CCISS_REGNEWD:
hpsa_scan_start(h->scsi_host); return 0; case CCISS_GETPCIINFO: return hpsa_getpciinfo_ioctl(h, argp); case CCISS_GETDRIVVER: return hpsa_getdrivver_ioctl(h, argp); case CCISS_PASSTHRU: {
IOCTL_Command_struct iocommand;
if (!argp) return -EINVAL; if (copy_from_user(&iocommand, argp, sizeof(iocommand))) return -EFAULT; if (atomic_dec_if_positive(&h->passthru_cmds_avail) < 0) return -EAGAIN;
rc = hpsa_passthru_ioctl(h, &iocommand);
atomic_inc(&h->passthru_cmds_avail); if (!rc && copy_to_user(argp, &iocommand, sizeof(iocommand)))
rc = -EFAULT; return rc;
} case CCISS_BIG_PASSTHRU: {
BIG_IOCTL_Command_struct ioc; if (!argp) return -EINVAL; if (copy_from_user(&ioc, argp, sizeof(ioc))) return -EFAULT; if (atomic_dec_if_positive(&h->passthru_cmds_avail) < 0) return -EAGAIN;
rc = hpsa_big_passthru_ioctl(h, &ioc);
atomic_inc(&h->passthru_cmds_avail); if (!rc && copy_to_user(argp, &ioc, sizeof(ioc)))
rc = -EFAULT; return rc;
} default: return -ENOTTY;
}
}
/* fill_cmd can't fail here, no data buffer to map */
(void) fill_cmd(c, HPSA_DEVICE_RESET_MSG, h, NULL, 0, 0,
RAID_CTLR_LUNID, TYPE_MSG);
c->Request.CDB[1] = reset_type; /* fill_cmd defaults to target reset */
c->waiting = NULL;
enqueue_cmd_and_start_io(h, c); /* Don't wait for completion, the reset won't complete. Don't free * the command either. This is the last command we will send before * re-initializing everything, so it doesn't matter and won't leak.
*/ return;
}
case HPSA_PHYS_TARGET_RESET:
c->Request.CDBLen = 16;
c->Request.type_attr_dir =
TYPE_ATTR_DIR(cmd_type, ATTR_SIMPLE, XFER_NONE);
c->Request.Timeout = 0; /* Don't time out */
memset(&c->Request.CDB[0], 0, sizeof(c->Request.CDB));
c->Request.CDB[0] = HPSA_RESET;
c->Request.CDB[1] = HPSA_TARGET_RESET_TYPE; /* Physical target reset needs no control bytes 4-7*/
c->Request.CDB[4] = 0x00;
c->Request.CDB[5] = 0x00;
c->Request.CDB[6] = 0x00;
c->Request.CDB[7] = 0x00; break; case HPSA_DEVICE_RESET_MSG:
c->Request.CDBLen = 16;
c->Request.type_attr_dir =
TYPE_ATTR_DIR(cmd_type, ATTR_SIMPLE, XFER_NONE);
c->Request.Timeout = 0; /* Don't time out */
memset(&c->Request.CDB[0], 0, sizeof(c->Request.CDB));
c->Request.CDB[0] = cmd;
c->Request.CDB[1] = HPSA_RESET_TYPE_LUN; /* If bytes 4-7 are zero, it means reset the */ /* LunID device */
c->Request.CDB[4] = 0x00;
c->Request.CDB[5] = 0x00;
c->Request.CDB[6] = 0x00;
c->Request.CDB[7] = 0x00; break; default:
dev_warn(&h->pdev->dev, "unknown message type %d\n",
cmd);
BUG();
}
} else {
dev_warn(&h->pdev->dev, "unknown command type %d\n", cmd_type);
BUG();
}
switch (GET_DIR(c->Request.type_attr_dir)) { case XFER_READ:
dir = DMA_FROM_DEVICE; break; case XFER_WRITE:
dir = DMA_TO_DEVICE; break; case XFER_NONE:
dir = DMA_NONE; break; default:
dir = DMA_BIDIRECTIONAL;
} if (hpsa_map_one(h->pdev, c, buff, size, dir)) return -1; return 0;
}
/* process completion of an indexed ("direct lookup") command */ staticinlinevoid process_indexed_cmd(struct ctlr_info *h,
u32 raw_tag)
{
u32 tag_index; struct CommandList *c;
tag_index = raw_tag >> DIRECT_LOOKUP_SHIFT; if (!bad_tag(h, tag_index, raw_tag)) {
c = h->cmd_pool + tag_index;
finish_cmd(c);
}
}
/* Some controllers, like p400, will give us one interrupt * after a soft reset, even if we turned interrupts off. * Only need to check for this in the hpsa_xxx_discard_completions * functions.
*/ staticint ignore_bogus_interrupt(struct ctlr_info *h)
{ if (likely(!reset_devices)) return 0;
/* * Convert &h->q[x] (passed to interrupt handlers) back to h. * Relies on (h-q[x] == x) being true for x such that * 0 <= x < MAX_REPLY_QUEUES.
*/ staticstruct ctlr_info *queue_to_hba(u8 *queue)
{ return container_of((queue - *queue), struct ctlr_info, q[0]);
}
/* Send a message CDB to the firmware. Careful, this only works * in simple mode, not performant mode due to the tag lookup. * We only ever use this immediately after a controller reset.
*/ staticint hpsa_message(struct pci_dev *pdev, unsignedchar opcode, unsignedchar type)
{ struct Command { struct CommandListHeader CommandHeader; struct RequestBlock Request; struct ErrDescriptor ErrorDescriptor;
}; struct Command *cmd; staticconst size_t cmd_sz = sizeof(*cmd) + sizeof(cmd->ErrorDescriptor);
dma_addr_t paddr64;
__le32 paddr32;
u32 tag; void __iomem *vaddr; int i, err;
vaddr = pci_ioremap_bar(pdev, 0); if (vaddr == NULL) return -ENOMEM;
/* The Inbound Post Queue only accepts 32-bit physical addresses for the * CCISS commands, so they must be allocated from the lower 4GiB of * memory.
*/
err = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); if (err) {
iounmap(vaddr); return err;
}
/* This must fit, because of the 32-bit consistent DMA mask. Also, * although there's no guarantee, we assume that the address is at * least 4-byte aligned (most likely, it's page-aligned).
*/
paddr32 = cpu_to_le32(paddr64);
for (i = 0; i < HPSA_MSG_SEND_RETRY_LIMIT; i++) {
tag = readl(vaddr + SA5_REPLY_PORT_OFFSET); if ((tag & ~HPSA_SIMPLE_ERROR_BITS) == paddr64) break;
msleep(HPSA_MSG_SEND_RETRY_INTERVAL_MSECS);
}
iounmap(vaddr);
/* we leak the DMA buffer here ... no choice since the controller could * still complete the command.
*/ if (i == HPSA_MSG_SEND_RETRY_LIMIT) {
dev_err(&pdev->dev, "controller message %02x:%02x timed out\n",
opcode, type); return -ETIMEDOUT;
}
if (use_doorbell) { /* For everything after the P600, the PCI power state method * of resetting the controller doesn't work, so we have this * other way using the doorbell register.
*/
dev_info(&pdev->dev, "using doorbell to reset controller\n");
writel(use_doorbell, vaddr + SA5_DOORBELL);
/* PMC hardware guys tell us we need a 10 second delay after * doorbell reset and before any attempt to talk to the board * at all to ensure that this actually works and doesn't fall * over in some weird corner cases.
*/
msleep(10000);
} else { /* Try to do it the PCI power state way */
/* Quoting from the Open CISS Specification: "The Power * Management Control/Status Register (CSR) controls the power * state of the device. The normal operating state is D0, * CSR=00h. The software off state is D3, CSR=03h. To reset * the controller, place the interface device in D3 then to D0, * this causes a secondary PCI reset which will reset the
* controller." */
int rc = 0;
dev_info(&pdev->dev, "using PCI PM to reset controller\n");
/* enter the D3hot power management state */
rc = pci_set_power_state(pdev, PCI_D3hot); if (rc) return rc;
msleep(500);
/* enter the D0 power management state */
rc = pci_set_power_state(pdev, PCI_D0); if (rc) return rc;
/* * The P600 requires a small delay when changing states. * Otherwise we may think the board did not reset and we bail. * This for kdump only and is particular to the P600.
*/
msleep(500);
} return 0;
}
/* After a reset, the 32 bytes of "driver version" in the cfgtable * should have been changed, otherwise we know the reset failed.
*/
init_driver_version(old_driver_ver, size);
read_driver_ver_from_cfgtable(cfgtable, driver_ver);
rc = !memcmp(driver_ver, old_driver_ver, size);
kfree(old_driver_ver); return rc;
} /* This does a hard reset of the controller using PCI power management * states or the using the doorbell register.
*/ staticint hpsa_kdump_hard_reset_controller(struct pci_dev *pdev, u32 board_id)
{
u64 cfg_offset;
u32 cfg_base_addr;
u64 cfg_base_addr_index; void __iomem *vaddr; unsignedlong paddr;
u32 misc_fw_support; int rc; struct CfgTable __iomem *cfgtable;
u32 use_doorbell;
u16 command_register;
/* For controllers as old as the P600, this is very nearly * the same thing as * * pci_save_state(pci_dev); * pci_set_power_state(pci_dev, PCI_D3hot); * pci_set_power_state(pci_dev, PCI_D0); * pci_restore_state(pci_dev); * * For controllers newer than the P600, the pci power state * method of resetting doesn't work so we have another way * using the doorbell register.
*/
if (!ctlr_is_resettable(board_id)) {
dev_warn(&pdev->dev, "Controller not resettable\n"); return -ENODEV;
}
/* if controller is soft- but not hard resettable... */ if (!ctlr_is_hard_resettable(board_id)) return -ENOTSUPP; /* try soft reset later. */
/* Save the PCI command register */
pci_read_config_word(pdev, 4, &command_register);
pci_save_state(pdev);
/* find the first memory BAR, so we can find the cfg table */
rc = hpsa_pci_find_memory_BAR(pdev, &paddr); if (rc) return rc;
vaddr = remap_pci_mem(paddr, 0x250); if (!vaddr) return -ENOMEM;
/* find cfgtable in order to check if reset via doorbell is supported */
rc = hpsa_find_cfg_addrs(pdev, vaddr, &cfg_base_addr,
&cfg_base_addr_index, &cfg_offset); if (rc) goto unmap_vaddr;
cfgtable = remap_pci_mem(pci_resource_start(pdev,
cfg_base_addr_index) + cfg_offset, sizeof(*cfgtable)); if (!cfgtable) {
rc = -ENOMEM; goto unmap_vaddr;
}
rc = write_driver_ver_to_cfgtable(cfgtable); if (rc) goto unmap_cfgtable;
/* If reset via doorbell register is supported, use that. * There are two such methods. Favor the newest method.
*/
misc_fw_support = readl(&cfgtable->misc_fw_support);
use_doorbell = misc_fw_support & MISC_FW_DOORBELL_RESET2; if (use_doorbell) {
use_doorbell = DOORBELL_CTLR_RESET2;
} else {
use_doorbell = misc_fw_support & MISC_FW_DOORBELL_RESET; if (use_doorbell) {
dev_warn(&pdev->dev, "Soft reset not supported. Firmware update is required.\n");
rc = -ENOTSUPP; /* try soft reset */ goto unmap_cfgtable;
}
}
rc = hpsa_controller_hard_reset(pdev, vaddr, use_doorbell); if (rc) goto unmap_cfgtable;
/* Some devices (notably the HP Smart Array 5i Controller)
need a little pause here */
msleep(HPSA_POST_RESET_PAUSE_MSECS);
rc = hpsa_wait_for_board_state(pdev, vaddr, BOARD_READY); if (rc) {
dev_warn(&pdev->dev, "Failed waiting for board to become ready after hard reset\n"); goto unmap_cfgtable;
}
rc = controller_reset_failed(vaddr); if (rc < 0) goto unmap_cfgtable; if (rc) {
dev_warn(&pdev->dev, "Unable to successfully reset " "controller. Will try soft reset.\n");
rc = -ENOTSUPP;
} else {
dev_info(&pdev->dev, "board ready after hard reset.\n");
}
unmap_cfgtable:
iounmap(cfgtable);
unmap_vaddr:
iounmap(vaddr); return rc;
}
/* * We cannot read the structure directly, for portability we must use * the io functions. * This is for debug only.
*/ staticvoid print_cfg_table(struct device *dev, struct CfgTable __iomem *tb)
{ #ifdef HPSA_DEBUG int i; char temp_name[17];
dev_info(dev, "Controller Configuration information\n");
dev_info(dev, "------------------------------------\n"); for (i = 0; i < 4; i++)
temp_name[i] = readb(&(tb->Signature[i]));
temp_name[4] = '\0';
dev_info(dev, " Signature = %s\n", temp_name);
dev_info(dev, " Spec Number = %d\n", readl(&(tb->SpecValence)));
dev_info(dev, " Transport methods supported = 0x%x\n",
readl(&(tb->TransportSupport)));
dev_info(dev, " Transport methods active = 0x%x\n",
readl(&(tb->TransportActive)));
dev_info(dev, " Requested transport Method = 0x%x\n",
readl(&(tb->HostWrite.TransportRequest)));
dev_info(dev, " Coalesce Interrupt Delay = 0x%x\n",
readl(&(tb->HostWrite.CoalIntDelay)));
dev_info(dev, " Coalesce Interrupt Count = 0x%x\n",
readl(&(tb->HostWrite.CoalIntCount)));
dev_info(dev, " Max outstanding commands = %d\n",
readl(&(tb->CmdsOutMax)));
dev_info(dev, " Bus Types = 0x%x\n", readl(&(tb->BusTypes))); for (i = 0; i < 16; i++)
temp_name[i] = readb(&(tb->ServerName[i]));
temp_name[16] = '\0';
dev_info(dev, " Server Name = %s\n", temp_name);
dev_info(dev, " Heartbeat Counter = 0x%x\n\n\n",
readl(&(tb->HeartBeat))); #endif/* HPSA_DEBUG */
}
staticint find_PCI_BAR_index(struct pci_dev *pdev, unsignedlong pci_bar_addr)
{ int i, offset, mem_type, bar_type;
if (pci_bar_addr == PCI_BASE_ADDRESS_0) /* looking for BAR zero? */ return 0;
offset = 0; for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
bar_type = pci_resource_flags(pdev, i) & PCI_BASE_ADDRESS_SPACE; if (bar_type == PCI_BASE_ADDRESS_SPACE_IO)
offset += 4; else {
mem_type = pci_resource_flags(pdev, i) &
PCI_BASE_ADDRESS_MEM_TYPE_MASK; switch (mem_type) { case PCI_BASE_ADDRESS_MEM_TYPE_32: case PCI_BASE_ADDRESS_MEM_TYPE_1M:
offset += 4; /* 32 bit */ break; case PCI_BASE_ADDRESS_MEM_TYPE_64:
offset += 8; break; default: /* reserved in PCI 2.2 */
dev_warn(&pdev->dev, "base address is invalid\n"); return -1;
}
} if (offset == pci_bar_addr - PCI_BASE_ADDRESS_0) return i + 1;
} return -1;
}
/* If MSI/MSI-X is supported by the kernel we will try to enable it on * controllers that are capable. If not, we use legacy INTx mode.
*/ staticint hpsa_interrupt_mode(struct ctlr_info *h)
{ unsignedint flags = PCI_IRQ_INTX; int ret;
/* Some boards advertise MSI but don't really support it */ switch (h->board_id) { case 0x40700E11: case 0x40800E11: case 0x40820E11: case 0x40830E11: break; default:
ret = pci_alloc_irq_vectors(h->pdev, 1, MAX_REPLY_QUEUES,
PCI_IRQ_MSIX | PCI_IRQ_AFFINITY); if (ret > 0) {
h->msix_vectors = ret; return 0;
}
flags |= PCI_IRQ_MSI; break;
}
ret = pci_alloc_irq_vectors(h->pdev, 1, 1, flags); if (ret < 0) return ret; return 0;
}
/* Find and map CISS config table and transfer table + * several items must be unmapped (freed) later
+ * */ staticint hpsa_find_cfgtables(struct ctlr_info *h)
{
u64 cfg_offset;
u32 cfg_base_addr;
u64 cfg_base_addr_index;
u32 trans_offset; int rc;
/* Limit commands in memory limited kdump scenario. */ if (reset_devices && h->max_commands > 32)
h->max_commands = 32;
if (h->max_commands < MIN_MAX_COMMANDS) {
dev_warn(&h->pdev->dev, "Controller reports max supported commands of %d Using %d instead. Ensure that firmware is up to date.\n",
h->max_commands,
MIN_MAX_COMMANDS);
h->max_commands = MIN_MAX_COMMANDS;
}
}
/* If the controller reports that the total max sg entries is greater than 512, * then we know that chained SG blocks work. (Original smart arrays did not * support chained SG blocks and would return zero for max sg entries.)
*/ staticint hpsa_supports_chained_sg_blocks(struct ctlr_info *h)
{ return h->maxsgentries > 512;
}
/* Interrogate the hardware for some limits: * max commands, max SG elements without chaining, and with chaining, * SG chain block size, etc.
*/ staticvoid hpsa_find_board_params(struct ctlr_info *h)
{
hpsa_get_max_perf_mode_cmds(h);
h->nr_cmds = h->max_commands;
h->maxsgentries = readl(&(h->cfgtable->MaxScatterGatherElements));
h->fw_support = readl(&(h->cfgtable->misc_fw_support)); if (hpsa_supports_chained_sg_blocks(h)) { /* Limit in-command s/g elements to 32 save dma'able memory. */
h->max_cmd_sg_entries = 32;
h->chainsize = h->maxsgentries - h->max_cmd_sg_entries;
h->maxsgentries--; /* save one for chain pointer */
} else { /* * Original smart arrays supported at most 31 s/g entries * embedded inline in the command (trying to use more * would lock up the controller)
*/
h->max_cmd_sg_entries = 31;
h->maxsgentries = 31; /* default to traditional values */
h->chainsize = 0;
}
/* Find out what task management functions are supported and cache */
h->TMFSupportFlags = readl(&(h->cfgtable->TMFSupportFlags)); if (!(HPSATMF_PHYS_TASK_ABORT & h->TMFSupportFlags))
dev_warn(&h->pdev->dev, "Physical aborts not supported\n"); if (!(HPSATMF_LOG_TASK_ABORT & h->TMFSupportFlags))
dev_warn(&h->pdev->dev, "Logical aborts not supported\n"); if (!(HPSATMF_IOACCEL_ENABLED & h->TMFSupportFlags))
dev_warn(&h->pdev->dev, "HP SSD Smart Path aborts not supported\n");
}
driver_support = readl(&(h->cfgtable->driver_support)); /* Need to enable prefetch in the SCSI core for 6400 in x86 */ #ifdef CONFIG_X86
driver_support |= ENABLE_SCSI_PREFETCH; #endif
driver_support |= ENABLE_UNIT_ATTN;
writel(driver_support, &(h->cfgtable->driver_support));
}
/* Disable DMA prefetch for the P600. Otherwise an ASIC bug may result * in a prefetch beyond physical memory.
*/ staticinlinevoid hpsa_p600_dma_prefetch_quirk(struct ctlr_info *h)
{
u32 dma_prefetch;
/* under certain very rare conditions, this can take awhile. * (e.g.: hot replace a failed 144GB drive in a RAID 5 set right * as we enter this code.)
*/ for (i = 0; i < MAX_MODE_CHANGE_WAIT; i++) { if (h->remove_in_progress) goto done;
spin_lock_irqsave(&h->lock, flags);
doorbell_value = readl(h->vaddr + SA5_DOORBELL);
spin_unlock_irqrestore(&h->lock, flags); if (!(doorbell_value & CFGTBL_ChangeReq)) goto done; /* delay and try again */
msleep(MODE_CHANGE_WAIT_INTERVAL);
} return -ENODEV;
done: return 0;
}
/* return -ENODEV or other reason on error, 0 on success */ staticint hpsa_enter_simple_mode(struct ctlr_info *h)
{
u32 trans_support;
trans_support = readl(&(h->cfgtable->TransportSupport)); if (!(trans_support & SIMPLE_MODE)) return -ENOTSUPP;
/* Update the field, and then ring the doorbell */
writel(CFGTBL_Trans_Simple, &(h->cfgtable->HostWrite.TransportRequest));
writel(0, &h->cfgtable->HostWrite.command_pool_addr_hi);
writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL); if (hpsa_wait_for_mode_change_ack(h)) goto error;
print_cfg_table(&h->pdev->dev, h->cfgtable); if (!(readl(&(h->cfgtable->TransportActive)) & CFGTBL_Trans_Simple)) goto error;
h->transMethod = CFGTBL_Trans_Simple; return 0;
error:
dev_err(&h->pdev->dev, "failed to enter simple mode\n"); return -ENODEV;
}
/* kdump kernel is loading, we don't know in which state is * the pci interface. The dev->enable_cnt is equal zero * so we call enable+disable, wait a while and switch it on.
*/
rc = pci_enable_device(pdev); if (rc) {
dev_warn(&pdev->dev, "Failed to enable PCI device\n"); return -ENODEV;
}
pci_disable_device(pdev);
msleep(260); /* a randomly chosen number */
rc = pci_enable_device(pdev); if (rc) {
dev_warn(&pdev->dev, "failed to enable device.\n"); return -ENODEV;
}
/* Reset the controller with a PCI power-cycle or via doorbell */
rc = hpsa_kdump_hard_reset_controller(pdev, board_id);
/* -ENOTSUPP here means we cannot reset the controller * but it's already (and still) up and running in * "performant mode". Or, it might be 640x, which can't reset * due to concerns about shared bbwc between 6402/6404 pair.
*/ if (rc) goto out_disable;
/* Now try to get the controller to respond to a no-op */
dev_info(&pdev->dev, "Waiting for controller to respond to no-op\n"); for (i = 0; i < HPSA_POST_RESET_NOOP_RETRIES; i++) { if (hpsa_noop(pdev) == 0) break; else
dev_warn(&pdev->dev, "no-op failed%s\n",
(i < 11 ? "; re-trying" : ""));
}
/* clear affinity hints and free MSI-X, MSI, or legacy INTx vectors */ staticvoid hpsa_free_irqs(struct ctlr_info *h)
{ int i; int irq_vector = 0;
if (hpsa_simple_mode)
irq_vector = h->intr_mode;
if (!h->msix_vectors || h->intr_mode != PERF_MODE_INT) { /* Single reply queue, only one irq to free */
free_irq(pci_irq_vector(h->pdev, irq_vector),
&h->q[h->intr_mode]);
h->q[h->intr_mode] = 0; return;
}
for (i = 0; i < h->msix_vectors; i++) {
free_irq(pci_irq_vector(h->pdev, i), &h->q[i]);
h->q[i] = 0;
} for (; i < MAX_REPLY_QUEUES; i++)
h->q[i] = 0;
}
/* returns 0 on success; cleans up and returns -Enn on error */ staticint hpsa_request_irqs(struct ctlr_info *h,
irqreturn_t (*msixhandler)(int, void *),
irqreturn_t (*intxhandler)(int, void *))
{ int rc, i; int irq_vector = 0;
if (hpsa_simple_mode)
irq_vector = h->intr_mode;
/* * initialize h->q[x] = x so that interrupt handlers know which * queue to process.
*/ for (i = 0; i < MAX_REPLY_QUEUES; i++)
h->q[i] = (u8) i;
if (h->intr_mode == PERF_MODE_INT && h->msix_vectors > 0) { /* If performant mode and MSI-X, use multiple reply queues */ for (i = 0; i < h->msix_vectors; i++) {
sprintf(h->intrname[i], "%s-msix%d", h->devname, i);
rc = request_irq(pci_irq_vector(h->pdev, i), msixhandler,
0, h->intrname[i],
&h->q[i]); if (rc) { int j;
dev_err(&h->pdev->dev, "failed to get irq %d for %s\n",
pci_irq_vector(h->pdev, i), h->devname); for (j = 0; j < i; j++) {
free_irq(pci_irq_vector(h->pdev, j), &h->q[j]);
h->q[j] = 0;
} for (; j < MAX_REPLY_QUEUES; j++)
h->q[j] = 0; return rc;
}
}
} else { /* Use single reply pool */ if (h->msix_vectors > 0 || h->pdev->msi_enabled) {
sprintf(h->intrname[0], "%s-msi%s", h->devname,
h->msix_vectors ? "x" : "");
rc = request_irq(pci_irq_vector(h->pdev, irq_vector),
msixhandler, 0,
h->intrname[0],
&h->q[h->intr_mode]);
} else {
sprintf(h->intrname[h->intr_mode], "%s-intx", h->devname);
rc = request_irq(pci_irq_vector(h->pdev, irq_vector),
intxhandler, IRQF_SHARED,
h->intrname[0],
&h->q[h->intr_mode]);
}
} if (rc) {
dev_err(&h->pdev->dev, "failed to get irq %d for %s\n",
pci_irq_vector(h->pdev, irq_vector), h->devname);
hpsa_free_irqs(h); return -ENODEV;
} return 0;
}
staticint hpsa_kdump_soft_reset(struct ctlr_info *h)
{ int rc;
hpsa_send_host_reset(h, HPSA_RESET_TYPE_CONTROLLER);
dev_info(&h->pdev->dev, "Waiting for board to soft reset.\n");
rc = hpsa_wait_for_board_state(h->pdev, h->vaddr, BOARD_NOT_READY); if (rc) {
dev_warn(&h->pdev->dev, "Soft reset had no effect.\n"); return rc;
}
dev_info(&h->pdev->dev, "Board reset, awaiting READY status.\n");
rc = hpsa_wait_for_board_state(h->pdev, h->vaddr, BOARD_READY); if (rc) {
dev_warn(&h->pdev->dev, "Board failed to become ready " "after soft reset.\n"); return rc;
}
return 0;
}
staticvoid hpsa_free_reply_queues(struct ctlr_info *h)
{ int i;
for (i = 0; i < h->nreply_queues; i++) { if (!h->reply_queue[i].head) continue;
dma_free_coherent(&h->pdev->dev,
h->reply_queue_size,
h->reply_queue[i].head,
h->reply_queue[i].busaddr);
h->reply_queue[i].head = NULL;
h->reply_queue[i].busaddr = 0;
}
h->reply_queue_size = 0;
}
/* Called when controller lockup detected. */ staticvoid fail_all_outstanding_cmds(struct ctlr_info *h)
{ int i, refcount; struct CommandList *c; int failcount = 0;
flush_workqueue(h->resubmit_wq); /* ensure all cmds are fully built */ for (i = 0; i < h->nr_cmds; i++) {
c = h->cmd_pool + i;
refcount = atomic_inc_return(&c->refcount); if (refcount > 1) {
c->err_info->CommandStatus = CMD_CTLR_LOCKUP;
finish_cmd(c);
atomic_dec(&h->commands_outstanding);
failcount++;
}
cmd_free(h, c);
}
dev_warn(&h->pdev->dev, "failed %d commands in fail_all\n", failcount);
}
staticvoid set_lockup_detected_for_all_cpus(struct ctlr_info *h, u32 value)
{ int cpu;
for_each_online_cpu(cpu) {
u32 *lockup_detected;
lockup_detected = per_cpu_ptr(h->lockup_detected, cpu);
*lockup_detected = value;
}
wmb(); /* be sure the per-cpu variables are out to memory */
}
now = get_jiffies_64(); /* If we've received an interrupt recently, we're ok. */ if (time_after64(h->last_intr_timestamp +
(h->heartbeat_sample_interval), now)) returnfalse;
/* * If we've already checked the heartbeat recently, we're ok. * This could happen if someone sends us a signal. We * otherwise don't care about signals in this thread.
*/ if (time_after64(h->last_heartbeat_timestamp +
(h->heartbeat_sample_interval), now)) returnfalse;
/* If heartbeat has not changed since we last looked, we're not ok. */
spin_lock_irqsave(&h->lock, flags);
heartbeat = readl(&h->cfgtable->HeartBeat);
spin_unlock_irqrestore(&h->lock, flags); if (h->last_heartbeat == heartbeat) {
controller_lockup_detected(h); returntrue;
}
/* * Set ioaccel status for all ioaccel volumes. * * Called from monitor controller worker (hpsa_event_monitor_worker) * * A Volume (or Volumes that comprise an Array set) may be undergoing a * transformation, so we will be turning off ioaccel for all volumes that * make up the Array.
*/ staticvoid hpsa_set_ioaccel_status(struct ctlr_info *h)
{ int rc; int i;
u8 ioaccel_status; unsignedchar *buf; struct hpsa_scsi_dev_t *device;
if (!h) return;
buf = kmalloc(64, GFP_KERNEL); if (!buf) return;
/* * Run through current device list used during I/O requests.
*/ for (i = 0; i < h->ndevices; i++) { int offload_to_be_enabled = 0; int offload_config = 0;
device = h->dev[i];
if (!device) continue; if (!hpsa_vpd_page_supported(h, device->scsi3addr,
HPSA_VPD_LV_IOACCEL_STATUS)) continue;
/* * Check if offload is still configured on
*/
offload_config =
!!(ioaccel_status & OFFLOAD_CONFIGURED_BIT); /* * If offload is configured on, check to see if ioaccel * needs to be enabled.
*/ if (offload_config)
offload_to_be_enabled =
!!(ioaccel_status & OFFLOAD_ENABLED_BIT);
/* * If ioaccel is to be re-enabled, re-enable later during the * scan operation so the driver can get a fresh raidmap * before turning ioaccel back on.
*/ if (offload_to_be_enabled) continue;
/* * Immediately turn off ioaccel for any volume the * controller tells us to. Some of the reasons could be: * transformation - change to the LVs of an Array. * degraded volume - component failure
*/
hpsa_turn_off_ioaccel_for_device(device);
}
if (!(h->fw_support & MISC_FW_EVENT_NOTIFY)) return;
/* Ask the controller to clear the events we're handling. */ if ((h->transMethod & (CFGTBL_Trans_io_accel1
| CFGTBL_Trans_io_accel2)) &&
(h->events & HPSA_EVENT_NOTIFY_ACCEL_IO_PATH_STATE_CHANGE ||
h->events & HPSA_EVENT_NOTIFY_ACCEL_IO_PATH_CONFIG_CHANGE)) {
if (h->events & HPSA_EVENT_NOTIFY_ACCEL_IO_PATH_STATE_CHANGE)
event_type = "state change"; if (h->events & HPSA_EVENT_NOTIFY_ACCEL_IO_PATH_CONFIG_CHANGE)
event_type = "configuration change"; /* Stop sending new RAID offload reqs via the IO accelerator */
scsi_block_requests(h->scsi_host);
hpsa_set_ioaccel_status(h);
hpsa_drain_accel_commands(h); /* Set 'accelerator path config change' bit */
dev_warn(&h->pdev->dev, "Acknowledging event: 0x%08x (HP SSD Smart Path %s)\n",
h->events, event_type);
writel(h->events, &(h->cfgtable->clear_event_notify)); /* Set the "clear event notify field update" bit 6 */
writel(DOORBELL_CLEAR_EVENTS, h->vaddr + SA5_DOORBELL); /* Wait until ctlr clears 'clear event notify field', bit 6 */
hpsa_wait_for_clear_event_notify_ack(h);
scsi_unblock_requests(h->scsi_host);
} else { /* Acknowledge controller notification events. */
writel(h->events, &(h->cfgtable->clear_event_notify));
writel(DOORBELL_CLEAR_EVENTS, h->vaddr + SA5_DOORBELL);
hpsa_wait_for_clear_event_notify_ack(h);
} return;
}
/* Check a register on the controller to see if there are configuration * changes (added/changed/removed logical drives, etc.) which mean that * we should rescan the controller for devices. * Also check flag for driver-initiated rescan.
*/ staticint hpsa_ctlr_needs_rescan(struct ctlr_info *h)
{ if (h->drv_req_rescan) {
h->drv_req_rescan = 0; return 1;
}
if (!(h->fw_support & MISC_FW_EVENT_NOTIFY)) return 0;
/* * Check if any of the offline devices have become ready
*/ staticint hpsa_offline_devices_ready(struct ctlr_info *h)
{ unsignedlong flags; struct offline_device_entry *d; struct list_head *this, *tmp;
/* * Do the scan after the reset
*/
spin_lock_irqsave(&h->reset_lock, flags); if (h->reset_in_progress) {
h->drv_req_rescan = 1;
spin_unlock_irqrestore(&h->reset_lock, flags); return;
}
spin_unlock_irqrestore(&h->reset_lock, flags);
sh = scsi_host_get(h->scsi_host); if (sh != NULL) {
hpsa_scan_start(sh);
scsi_host_put(sh);
h->drv_req_rescan = 0;
}
}
if (number_of_controllers == 0)
printk(KERN_INFO DRIVER_NAME "\n");
rc = hpsa_lookup_board_id(pdev, &board_id, NULL); if (rc < 0) {
dev_warn(&pdev->dev, "Board ID not found\n"); return rc;
}
rc = hpsa_init_reset_devices(pdev, board_id); if (rc) { if (rc != -ENOTSUPP) return rc; /* If the reset fails in a particular way (it has no way to do * a proper hard reset, so returns -ENOTSUPP) we can try to do * a soft reset once we get the controller configured up to the * point that it can accept a command.
*/
try_soft_reset = 1;
rc = 0;
}
reinit_after_soft_reset:
/* Command structures must be aligned on a 32-byte boundary because * the 5 lower bits of the address are used by the hardware. and by * the driver. See comments in hpsa.h for more info.
*/
BUILD_BUG_ON(sizeof(struct CommandList) % COMMANDLIST_ALIGNMENT);
h = hpda_alloc_ctlr_info(); if (!h) {
dev_err(&pdev->dev, "Failed to allocate controller head\n"); return -ENOMEM;
}
/* relies on h-> settings made by hpsa_pci_init, including
* interrupt_mode h->intr */
rc = hpsa_scsi_host_alloc(h); if (rc) goto clean2_5; /* pci, lu, aer/h */
/* * At this point, the controller is ready to take commands. * Now, if reset_devices and the hard reset didn't work, try * the soft reset and see if that works.
*/ if (try_soft_reset) {
/* This is kind of gross. We may or may not get a completion * from the soft reset command, and if we do, then the value * from the fifo may or may not be valid. So, we wait 10 secs * after the reset throwing away any completions we get during * that time. Unregister the interrupt handler and register * fake ones to scoop up any residual completions.
*/
spin_lock_irqsave(&h->lock, flags);
h->access.set_intr_mask(h, HPSA_INTR_OFF);
spin_unlock_irqrestore(&h->lock, flags);
hpsa_free_irqs(h);
rc = hpsa_request_irqs(h, hpsa_msix_discard_completions,
hpsa_intx_discard_completions); if (rc) {
dev_warn(&h->pdev->dev, "Failed to request_irq after soft reset.\n"); /* * cannot goto clean7 or free_irqs will be called * again. Instead, do its work
*/
hpsa_free_performant_mode(h); /* clean7 */
hpsa_free_sg_chain_blocks(h); /* clean6 */
hpsa_free_cmd_pool(h); /* clean5 */ /* * skip hpsa_free_irqs(h) clean4 since that * was just called before request_irqs failed
*/ goto clean3;
}
rc = hpsa_kdump_soft_reset(h); if (rc) /* Neither hard nor soft reset worked, we're hosed. */ goto clean7;
dev_info(&h->pdev->dev, "Board READY.\n");
dev_info(&h->pdev->dev, "Waiting for stale completions to drain.\n");
h->access.set_intr_mask(h, HPSA_INTR_ON);
msleep(10000);
h->access.set_intr_mask(h, HPSA_INTR_OFF);
rc = controller_reset_failed(h->cfgtable); if (rc)
dev_info(&h->pdev->dev, "Soft reset appears to have failed.\n");
/* since the controller's reset, we have to go back and re-init * everything. Easiest to just forget what we've done and do it * all over again.
*/
hpsa_undo_allocations_after_kdump_soft_reset(h);
try_soft_reset = 0; if (rc) /* don't goto clean, we already unallocated */ return -ENODEV;
if (unlikely(lockup_detected(h))) return;
flush_buf = kzalloc(4, GFP_KERNEL); if (!flush_buf) return;
c = cmd_alloc(h);
if (fill_cmd(c, HPSA_CACHE_FLUSH, h, flush_buf, 4, 0,
RAID_CTLR_LUNID, TYPE_CMD)) { goto out;
}
rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, DMA_TO_DEVICE,
DEFAULT_TIMEOUT); if (rc) goto out; if (c->err_info->CommandStatus != 0)
out:
dev_warn(&h->pdev->dev, "error flushing cache on controller\n");
cmd_free(h, c);
kfree(flush_buf);
}
/* Make controller gather fresh report lun data each time we * send down a report luns request
*/ staticvoid hpsa_disable_rld_caching(struct ctlr_info *h)
{
u32 *options; struct CommandList *c; int rc;
/* Don't bother trying to set diag options if locked up */ if (unlikely(h->lockup_detected)) return;
options = kzalloc(sizeof(*options), GFP_KERNEL); if (!options) return;
c = cmd_alloc(h);
/* first, get the current diag options settings */ if (fill_cmd(c, BMIC_SENSE_DIAG_OPTIONS, h, options, 4, 0,
RAID_CTLR_LUNID, TYPE_CMD)) goto errout;
h = pci_get_drvdata(pdev); /* Turn board interrupts off and send the flush cache command * sendcmd will turn off interrupt, and send the flush... * To write all data in the battery backed cache to disks
*/
hpsa_flush_cache(h);
h->access.set_intr_mask(h, HPSA_INTR_OFF);
hpsa_free_irqs(h); /* init_one 4 */
hpsa_disable_interrupt_mode(h); /* pci_init 2 */
}
if (pci_get_drvdata(pdev) == NULL) {
dev_err(&pdev->dev, "unable to remove device\n"); return;
}
h = pci_get_drvdata(pdev);
/* Get rid of any controller monitoring work items */
spin_lock_irqsave(&h->lock, flags);
h->remove_in_progress = 1;
spin_unlock_irqrestore(&h->lock, flags);
cancel_delayed_work_sync(&h->monitor_ctlr_work);
cancel_delayed_work_sync(&h->rescan_ctlr_work);
cancel_delayed_work_sync(&h->event_monitor_work);
destroy_workqueue(h->rescan_ctlr_wq);
destroy_workqueue(h->resubmit_wq);
destroy_workqueue(h->monitor_ctlr_wq);
hpsa_delete_sas_host(h);
/* * Call before disabling interrupts. * scsi_remove_host can trigger I/O operations especially * when multipath is enabled. There can be SYNCHRONIZE CACHE * operations which cannot complete and will hang the system.
*/ if (h->scsi_host)
scsi_remove_host(h->scsi_host); /* init_one 8 */ /* includes hpsa_free_irqs - init_one 4 */ /* includes hpsa_disable_interrupt_mode - pci_init 2 */
__hpsa_shutdown(pdev);
/* Fill in bucket_map[], given nsgs (the max number of * scatter gather elements supported) and bucket[], * which is an array of 8 integers. The bucket[] array * contains 8 different DMA transfer sizes (in 16 * byte increments) which the controller uses to fetch * commands. This function fills in bucket_map[], which * maps a given number of scatter gather elements to one of * the 8 DMA transfer sizes. The point of it is to allow the * controller to only do as much DMA as needed to fetch the * command, with the DMA transfer size encoded in the lower * bits of the command address.
*/ staticvoid calc_bucket_map(int bucket[], int num_buckets, int nsgs, int min_blocks, u32 *bucket_map)
{ int i, j, b, size;
/* Note, bucket_map must have nsgs+1 entries. */ for (i = 0; i <= nsgs; i++) { /* Compute size of a command with i SG entries */
size = i + min_blocks;
b = num_buckets; /* Assume the biggest bucket */ /* Find the bucket that is just big enough */ for (j = 0; j < num_buckets; j++) { if (bucket[j] >= size) {
b = j; break;
}
} /* for a command with i SG entries, use bucket b. */
bucket_map[i] = b;
}
}
/* * return -ENODEV on err, 0 on success (or no action) * allocates numerous items that must be freed later
*/ staticint hpsa_enter_performant_mode(struct ctlr_info *h, u32 trans_support)
{ int i; unsignedlong register_value; unsignedlong transMethod = CFGTBL_Trans_Performant |
(trans_support & CFGTBL_Trans_use_short_tags) |
CFGTBL_Trans_enable_directed_msix |
(trans_support & (CFGTBL_Trans_io_accel1 |
CFGTBL_Trans_io_accel2)); struct access_method access = SA5_performant_access;
/* This is a bit complicated. There are 8 registers on * the controller which we write to to tell it 8 different * sizes of commands which there may be. It's a way of * reducing the DMA done to fetch each command. Encoded into * each command's tag are 3 bits which communicate to the controller * which of the eight sizes that command fits within. The size of * each command depends on how many scatter gather entries there are. * Each SG entry requires 16 bytes. The eight registers are programmed * with the number of 16-byte blocks a command of that size requires. * The smallest command possible requires 5 such 16 byte blocks. * the largest command possible requires SG_ENTRIES_IN_CMD + 4 16-byte * blocks. Note, this only extends to the SG entries contained * within the command block, and does not extend to chained blocks * of SG elements. bft[] contains the eight values we write to * the registers. They are not evenly distributed, but have more * sizes for small commands, and fewer sizes for larger commands.
*/ int bft[8] = {5, 6, 8, 10, 12, 20, 28, SG_ENTRIES_IN_CMD + 4}; #define MIN_IOACCEL2_BFT_ENTRY 5 #define HPSA_IOACCEL2_HEADER_SZ 4 int bft2[16] = {MIN_IOACCEL2_BFT_ENTRY, 6, 7, 8, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18, 19,
HPSA_IOACCEL2_HEADER_SZ + IOACCEL2_MAXSGENTRIES};
BUILD_BUG_ON(ARRAY_SIZE(bft2) != 16);
BUILD_BUG_ON(ARRAY_SIZE(bft) != 8);
BUILD_BUG_ON(offsetof(struct io_accel2_cmd, sg) >
16 * MIN_IOACCEL2_BFT_ENTRY);
BUILD_BUG_ON(sizeof(struct ioaccel2_sg_element) != 16);
BUILD_BUG_ON(28 > SG_ENTRIES_IN_CMD + 4); /* 5 = 1 s/g entry or 4k * 6 = 2 s/g entry or 8k * 8 = 4 s/g entry or 16k * 10 = 6 s/g entry or 24k
*/
/* If the controller supports either ioaccel method then * we can also use the RAID stack submit path that does not * perform the superfluous readl() after each command submission.
*/ if (trans_support & (CFGTBL_Trans_io_accel1 | CFGTBL_Trans_io_accel2))
access = SA5_performant_access_no_read;
/* Controller spec: zero out this buffer. */ for (i = 0; i < h->nreply_queues; i++)
memset(h->reply_queue[i].head, 0, h->reply_queue_size);
bft[7] = SG_ENTRIES_IN_CMD + 4;
calc_bucket_map(bft, ARRAY_SIZE(bft),
SG_ENTRIES_IN_CMD, 4, h->blockFetchTable); for (i = 0; i < 8; i++)
writel(bft[i], &h->transtable->BlockFetch[i]);
/* size of controller ring buffer */
writel(h->max_commands, &h->transtable->RepQSize);
writel(h->nreply_queues, &h->transtable->RepQCount);
writel(0, &h->transtable->RepQCtrAddrLow32);
writel(0, &h->transtable->RepQCtrAddrHigh32);
for (i = 0; i < h->nreply_queues; i++) {
writel(0, &h->transtable->RepQAddr[i].upper);
writel(h->reply_queue[i].busaddr,
&h->transtable->RepQAddr[i].lower);
}
writel(0, &h->cfgtable->HostWrite.command_pool_addr_hi);
writel(transMethod, &(h->cfgtable->HostWrite.TransportRequest)); /* * enable outbound interrupt coalescing in accelerator mode;
*/ if (trans_support & CFGTBL_Trans_io_accel1) {
access = SA5_ioaccel_mode1_access;
writel(10, &h->cfgtable->HostWrite.CoalIntDelay);
writel(4, &h->cfgtable->HostWrite.CoalIntCount);
} else if (trans_support & CFGTBL_Trans_io_accel2)
access = SA5_ioaccel_mode2_access;
writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL); if (hpsa_wait_for_mode_change_ack(h)) {
dev_err(&h->pdev->dev, "performant mode problem - doorbell timeout\n"); return -ENODEV;
}
register_value = readl(&(h->cfgtable->TransportActive)); if (!(register_value & CFGTBL_Trans_Performant)) {
dev_err(&h->pdev->dev, "performant mode problem - transport not active\n"); return -ENODEV;
} /* Change the access methods to the performant access methods */
h->access = access;
h->transMethod = transMethod;
if (!((trans_support & CFGTBL_Trans_io_accel1) ||
(trans_support & CFGTBL_Trans_io_accel2))) return 0;
if (trans_support & CFGTBL_Trans_io_accel1) { /* Set up I/O accelerator mode */ for (i = 0; i < h->nreply_queues; i++) {
writel(i, h->vaddr + IOACCEL_MODE1_REPLY_QUEUE_INDEX);
h->reply_queue[i].current_entry =
readl(h->vaddr + IOACCEL_MODE1_PRODUCER_INDEX);
}
bft[7] = h->ioaccel_maxsg + 8;
calc_bucket_map(bft, ARRAY_SIZE(bft), h->ioaccel_maxsg, 8,
h->ioaccel1_blockFetchTable);
/* initialize all reply queue entries to unused */ for (i = 0; i < h->nreply_queues; i++)
memset(h->reply_queue[i].head,
(u8) IOACCEL_MODE1_REPLY_UNUSED,
h->reply_queue_size);
/* set all the constant fields in the accelerator command * frames once at init time to save CPU cycles later.
*/ for (i = 0; i < h->nr_cmds; i++) { struct io_accel1_cmd *cp = &h->ioaccel_cmd_pool[i];
/* Command structures must be aligned on a 128-byte boundary * because the 7 lower bits of the address are used by the * hardware.
*/
BUILD_BUG_ON(sizeof(struct io_accel1_cmd) %
IOACCEL1_COMMANDLIST_ALIGNMENT);
h->ioaccel_cmd_pool =
dma_alloc_coherent(&h->pdev->dev,
h->nr_cmds * sizeof(*h->ioaccel_cmd_pool),
&h->ioaccel_cmd_pool_dhandle, GFP_KERNEL);
/* return -ENODEV on error, 0 on success (or no action) * allocates numerous items that must be freed later
*/ staticint hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h)
{
u32 trans_support; int i, rc;
if (hpsa_simple_mode) return 0;
trans_support = readl(&(h->cfgtable->TransportSupport)); if (!(trans_support & PERFORMANT_MODE)) return 0;
/* Check for I/O accelerator mode support */ if (trans_support & CFGTBL_Trans_io_accel1) {
rc = hpsa_alloc_ioaccel1_cmd_and_bft(h); if (rc) return rc;
} elseif (trans_support & CFGTBL_Trans_io_accel2) {
rc = hpsa_alloc_ioaccel2_cmd_and_bft(h); if (rc) return rc;
}
h->nreply_queues = h->msix_vectors > 0 ? h->msix_vectors : 1;
hpsa_get_max_perf_mode_cmds(h); /* Performant mode ring buffer and supporting data structures */
h->reply_queue_size = h->max_commands * sizeof(u64);
for (i = 0; i < h->nreply_queues; i++) {
h->reply_queue[i].head = dma_alloc_coherent(&h->pdev->dev,
h->reply_queue_size,
&h->reply_queue[i].busaddr,
GFP_KERNEL); if (!h->reply_queue[i].head) {
rc = -ENOMEM; goto clean1; /* rq, ioaccel */
}
h->reply_queue[i].size = h->max_commands;
h->reply_queue[i].wraparound = 1; /* spec: init to 1 */
h->reply_queue[i].current_entry = 0;
}
/* Need a block fetch table for performant mode */
h->blockFetchTable = kmalloc(((SG_ENTRIES_IN_CMD + 1) * sizeof(u32)), GFP_KERNEL); if (!h->blockFetchTable) {
rc = -ENOMEM; goto clean1; /* rq, ioaccel */
}
staticvoid hpsa_drain_accel_commands(struct ctlr_info *h)
{ struct CommandList *c = NULL; int i, accel_cmds_out; int refcount;
do { /* wait for all outstanding ioaccel commands to drain out */
accel_cmds_out = 0; for (i = 0; i < h->nr_cmds; i++) {
c = h->cmd_pool + i;
refcount = atomic_inc_return(&c->refcount); if (refcount > 1) /* Command is allocated */
accel_cmds_out += is_accelerated_cmd(c);
cmd_free(h, c);
} if (accel_cmds_out <= 0) break;
msleep(100);
} while (1);
}
/* * This is it. Register the PCI driver information for the cards we control * the OS will call our registered routines when it finds one of our cards.
*/ staticint __init hpsa_init(void)
{ int rc;
hpsa_sas_transport_template =
sas_attach_transport(&hpsa_sas_transport_functions); if (!hpsa_sas_transport_template) return -ENODEV;
rc = pci_register_driver(&hpsa_pci_driver);
if (rc)
sas_release_transport(hpsa_sas_transport_template);
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.307Bemerkung:
(vorverarbeitet am 2026-04-26)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.