Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/smartpqi/smartpqi_discovery.c
Show All 35 Lines | static inline boolean_t pqisrc_scsi_sense_valid(const struct sense_header_scsi *sshdr) | ||||
if (!sshdr) | if (!sshdr) | ||||
return false; | return false; | ||||
DBG_FUNC("OUT\n"); | DBG_FUNC("OUT\n"); | ||||
return (sshdr->response_code & 0x70) == 0x70; | return (sshdr->response_code & 0x70) == 0x70; | ||||
} | } | ||||
/* Initialize target ID pool for HBA/PDs */ | |||||
void pqisrc_init_targetid_pool(pqisrc_softstate_t *softs) | |||||
{ | |||||
int i, tid = PQI_MAX_PHYSICALS + PQI_MAX_LOGICALS - 1; | |||||
for(i = 0; i < PQI_MAX_PHYSICALS; i++) { | |||||
softs->tid_pool.tid[i] = tid--; | |||||
} | |||||
softs->tid_pool.index = i - 1; | |||||
} | |||||
int pqisrc_alloc_tid(pqisrc_softstate_t *softs) | |||||
{ | |||||
if(softs->tid_pool.index <= -1) { | |||||
DBG_ERR("Target ID exhausted\n"); | |||||
return INVALID_ELEM; | |||||
} | |||||
return softs->tid_pool.tid[softs->tid_pool.index--]; | |||||
} | |||||
void pqisrc_free_tid(pqisrc_softstate_t *softs, int tid) | |||||
{ | |||||
if(softs->tid_pool.index >= PQI_MAX_PHYSICALS) { | |||||
DBG_ERR("Target ID queue is full\n"); | |||||
return; | |||||
} | |||||
softs->tid_pool.index++; | |||||
softs->tid_pool.tid[softs->tid_pool.index] = tid; | |||||
} | |||||
/* Update scsi sense info to a local buffer*/ | /* Update scsi sense info to a local buffer*/ | ||||
boolean_t pqisrc_update_scsi_sense(const uint8_t *buff, int len, | boolean_t pqisrc_update_scsi_sense(const uint8_t *buff, int len, | ||||
struct sense_header_scsi *header) | struct sense_header_scsi *header) | ||||
{ | { | ||||
DBG_FUNC("IN\n"); | DBG_FUNC("IN\n"); | ||||
if (!buff || !len) | if (!buff || !len) | ||||
▲ Show 20 Lines • Show All 119 Lines • ▼ Show 20 Lines | case SA_GET_RAID_MAP: | ||||
request->data_direction = SOP_DATA_DIR_TO_DEVICE; | request->data_direction = SOP_DATA_DIR_TO_DEVICE; | ||||
cdb[0] = SA_CISS_READ; | cdb[0] = SA_CISS_READ; | ||||
cdb[1] = cmd; | cdb[1] = cmd; | ||||
cdb[8] = (uint8_t)((datasize) >> 8); | cdb[8] = (uint8_t)((datasize) >> 8); | ||||
cdb[9] = (uint8_t)datasize; | cdb[9] = (uint8_t)datasize; | ||||
break; | break; | ||||
case SA_CACHE_FLUSH: | case SA_CACHE_FLUSH: | ||||
request->data_direction = SOP_DATA_DIR_FROM_DEVICE; | request->data_direction = SOP_DATA_DIR_FROM_DEVICE; | ||||
memcpy(device_mem.virt_addr, buff, datasize); | |||||
cdb[0] = BMIC_WRITE; | cdb[0] = BMIC_WRITE; | ||||
cdb[6] = BMIC_CACHE_FLUSH; | cdb[6] = BMIC_CACHE_FLUSH; | ||||
cdb[7] = (uint8_t)((datasize) << 8); | cdb[7] = (uint8_t)((datasize) << 8); | ||||
cdb[8] = (uint8_t)((datasize) >> 8); | cdb[8] = (uint8_t)((datasize) >> 8); | ||||
break; | break; | ||||
case BMIC_IDENTIFY_CONTROLLER: | case BMIC_IDENTIFY_CONTROLLER: | ||||
case BMIC_IDENTIFY_PHYSICAL_DEVICE: | case BMIC_IDENTIFY_PHYSICAL_DEVICE: | ||||
request->data_direction = SOP_DATA_DIR_TO_DEVICE; | request->data_direction = SOP_DATA_DIR_TO_DEVICE; | ||||
▲ Show 20 Lines • Show All 66 Lines • ▼ Show 20 Lines | if(error_info) { | ||||
rcb->error_info, | rcb->error_info, | ||||
sizeof(*error_info)); | sizeof(*error_info)); | ||||
if (error_info->data_out_result == | if (error_info->data_out_result == | ||||
PQI_RAID_DATA_IN_OUT_UNDERFLOW) { | PQI_RAID_DATA_IN_OUT_UNDERFLOW) { | ||||
ret = PQI_STATUS_SUCCESS; | ret = PQI_STATUS_SUCCESS; | ||||
} | } | ||||
else{ | else{ | ||||
DBG_INFO("Error!! Bus=%u Target=%u, Cmd=0x%x," | DBG_DISC("Error!! Bus=%u Target=%u, Cmd=0x%x," | ||||
"Ret=%d\n", BMIC_GET_LEVEL_2_BUS(scsi3addr), | "Ret=%d\n", BMIC_GET_LEVEL_2_BUS(scsi3addr), | ||||
BMIC_GET_LEVEL_TWO_TARGET(scsi3addr), | BMIC_GET_LEVEL_TWO_TARGET(scsi3addr), | ||||
cmd, ret); | cmd, ret); | ||||
ret = PQI_STATUS_FAILURE; | ret = PQI_STATUS_FAILURE; | ||||
} | } | ||||
} | } | ||||
} else { | } else { | ||||
if(error_info) { | if(error_info) { | ||||
▲ Show 20 Lines • Show All 67 Lines • ▼ Show 20 Lines | retry: | ||||
lun_data = os_mem_alloc(softs, data_len); | lun_data = os_mem_alloc(softs, data_len); | ||||
if (!lun_data) { | if (!lun_data) { | ||||
DBG_ERR("failed to allocate memory for lun_data\n"); | DBG_ERR("failed to allocate memory for lun_data\n"); | ||||
return PQI_STATUS_FAILURE; | return PQI_STATUS_FAILURE; | ||||
} | } | ||||
if (list_len == 0) { | if (list_len == 0) { | ||||
DBG_INFO("list_len is 0\n"); | DBG_DISC("list_len is 0\n"); | ||||
memcpy(lun_data, &report_lun_header, sizeof(report_lun_header)); | memcpy(lun_data, &report_lun_header, sizeof(report_lun_header)); | ||||
goto out; | goto out; | ||||
} | } | ||||
ret = pqisrc_report_luns(softs, cmd, lun_data, data_len); | ret = pqisrc_report_luns(softs, cmd, lun_data, data_len); | ||||
if (ret) { | if (ret) { | ||||
DBG_ERR("error\n"); | DBG_ERR("error\n"); | ||||
▲ Show 20 Lines • Show All 132 Lines • ▼ Show 20 Lines | if (pqisrc_is_hba_lunid(scsi3addr)) { | ||||
/* The specified device is the controller. */ | /* The specified device is the controller. */ | ||||
pqisrc_set_btl(device, PQI_HBA_BUS, PQI_CTLR_INDEX, lunid & 0x3fff); | pqisrc_set_btl(device, PQI_HBA_BUS, PQI_CTLR_INDEX, lunid & 0x3fff); | ||||
device->target_lun_valid = true; | device->target_lun_valid = true; | ||||
return; | return; | ||||
} | } | ||||
if (pqisrc_is_logical_device(device)) { | if (pqisrc_is_logical_device(device)) { | ||||
if (pqisrc_is_external_raid_device(device)) { | if (pqisrc_is_external_raid_device(device)) { | ||||
DBG_INFO("External Raid Device!!!"); | DBG_DISC("External Raid Device!!!"); | ||||
bus = PQI_EXTERNAL_RAID_VOLUME_BUS; | bus = PQI_EXTERNAL_RAID_VOLUME_BUS; | ||||
target = (lunid >> 16) & 0x3fff; | target = (lunid >> 16) & 0x3fff; | ||||
lun = lunid & 0xff; | lun = lunid & 0xff; | ||||
} else { | } else { | ||||
bus = PQI_RAID_VOLUME_BUS; | bus = PQI_RAID_VOLUME_BUS; | ||||
lun = 0; | lun = 0; | ||||
target = lunid & 0x3fff; | target = lunid & 0x3fff; | ||||
} | } | ||||
pqisrc_set_btl(device, bus, target, lun); | pqisrc_set_btl(device, bus, target, lun); | ||||
device->target_lun_valid = true; | device->target_lun_valid = true; | ||||
return; | return; | ||||
} | } | ||||
/* physical device */ | |||||
pqisrc_set_btl(device, PQI_PHYSICAL_DEVICE_BUS, PQI_PD_INDEX(scsi3addr[6]), 0); | |||||
DBG_FUNC("OUT\n"); | DBG_FUNC("OUT\n"); | ||||
} | } | ||||
/* Build and send the internal INQUIRY command to particular device */ | /* Build and send the internal INQUIRY command to particular device */ | ||||
static int pqisrc_send_scsi_inquiry(pqisrc_softstate_t *softs, | static int pqisrc_send_scsi_inquiry(pqisrc_softstate_t *softs, | ||||
uint8_t *scsi3addr, uint16_t vpd_page, uint8_t *buff, int buf_len) | uint8_t *scsi3addr, uint16_t vpd_page, uint8_t *buff, int buf_len) | ||||
{ | { | ||||
int ret = PQI_STATUS_SUCCESS; | int ret = PQI_STATUS_SUCCESS; | ||||
Show All 23 Lines | static void pqisrc_fetch_sense_info(const uint8_t *sense_data, | ||||
*asc = 0; | *asc = 0; | ||||
if (pqisrc_update_scsi_sense(sense_data, sense_data_length, &header)) { | if (pqisrc_update_scsi_sense(sense_data, sense_data_length, &header)) { | ||||
*sense_key = header.sense_key; | *sense_key = header.sense_key; | ||||
*asc = header.asc; | *asc = header.asc; | ||||
*ascq = header.ascq; | *ascq = header.ascq; | ||||
} | } | ||||
DBG_INFO("sense_key: %x asc: %x ascq: %x\n", *sense_key, *asc, *ascq); | DBG_DISC("sense_key: %x asc: %x ascq: %x\n", *sense_key, *asc, *ascq); | ||||
DBG_FUNC("OUT\n"); | DBG_FUNC("OUT\n"); | ||||
} | } | ||||
/* Function used to validate volume offline status */ | /* Function used to validate volume offline status */ | ||||
static uint8_t pqisrc_get_volume_offline_status(pqisrc_softstate_t *softs, | static uint8_t pqisrc_get_volume_offline_status(pqisrc_softstate_t *softs, | ||||
uint8_t *scsi3addr) | uint8_t *scsi3addr) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 72 Lines • ▼ Show 20 Lines | if (scsi_status != 2 || | ||||
sense_key != 2 || | sense_key != 2 || | ||||
asc != ASC_LUN_NOT_READY) { | asc != ASC_LUN_NOT_READY) { | ||||
return SA_LV_OK; | return SA_LV_OK; | ||||
} | } | ||||
/* Determine the reason for not ready state. */ | /* Determine the reason for not ready state. */ | ||||
off_status = pqisrc_get_volume_offline_status(softs, scsi3addr); | off_status = pqisrc_get_volume_offline_status(softs, scsi3addr); | ||||
DBG_INFO("offline_status 0x%x\n", off_status); | DBG_DISC("offline_status 0x%x\n", off_status); | ||||
/* Keep volume offline in certain cases. */ | /* Keep volume offline in certain cases. */ | ||||
switch (off_status) { | switch (off_status) { | ||||
case SA_LV_UNDERGOING_ERASE: | case SA_LV_UNDERGOING_ERASE: | ||||
case SA_LV_NOT_AVAILABLE: | case SA_LV_NOT_AVAILABLE: | ||||
case SA_LV_UNDERGOING_RPI: | case SA_LV_UNDERGOING_RPI: | ||||
case SA_LV_PENDING_RPI: | case SA_LV_PENDING_RPI: | ||||
case SA_LV_ENCRYPTED_NO_KEY: | case SA_LV_ENCRYPTED_NO_KEY: | ||||
▲ Show 20 Lines • Show All 153 Lines • ▼ Show 20 Lines | static void pqisrc_get_dev_ioaccel_status(pqisrc_softstate_t *softs, | ||||
if (device->offload_config) { | if (device->offload_config) { | ||||
device->offload_enabled_pending = | device->offload_enabled_pending = | ||||
!!(ioaccel_status & OFFLOAD_ENABLED_BIT); | !!(ioaccel_status & OFFLOAD_ENABLED_BIT); | ||||
if (pqisrc_get_device_raidmap(softs, device)) | if (pqisrc_get_device_raidmap(softs, device)) | ||||
device->offload_enabled_pending = false; | device->offload_enabled_pending = false; | ||||
} | } | ||||
DBG_INFO("offload_config: 0x%x offload_enabled_pending: 0x%x \n", | DBG_DISC("offload_config: 0x%x offload_enabled_pending: 0x%x \n", | ||||
device->offload_config, device->offload_enabled_pending); | device->offload_config, device->offload_enabled_pending); | ||||
err_out: | err_out: | ||||
os_mem_free(softs, (char*)buff, 64); | os_mem_free(softs, (char*)buff, 64); | ||||
DBG_FUNC("OUT\n"); | DBG_FUNC("OUT\n"); | ||||
} | } | ||||
/* Get RAID level of requested device */ | /* Get RAID level of requested device */ | ||||
Show All 16 Lines | if (ret == 0) { | ||||
raid_level = buff[8]; | raid_level = buff[8]; | ||||
if (raid_level > SA_RAID_MAX) | if (raid_level > SA_RAID_MAX) | ||||
raid_level = SA_RAID_UNKNOWN; | raid_level = SA_RAID_UNKNOWN; | ||||
} | } | ||||
os_mem_free(softs, (char*)buff, 64); | os_mem_free(softs, (char*)buff, 64); | ||||
} | } | ||||
device->raid_level = raid_level; | device->raid_level = raid_level; | ||||
DBG_INFO("RAID LEVEL: %x \n", raid_level); | DBG_DISC("RAID LEVEL: %x \n", raid_level); | ||||
DBG_FUNC("OUT\n"); | DBG_FUNC("OUT\n"); | ||||
} | } | ||||
/* Parse the inquiry response and determine the type of device */ | /* Parse the inquiry response and determine the type of device */ | ||||
static int pqisrc_get_dev_data(pqisrc_softstate_t *softs, | static int pqisrc_get_dev_data(pqisrc_softstate_t *softs, | ||||
pqi_scsi_dev_t *device) | pqi_scsi_dev_t *device) | ||||
{ | { | ||||
int ret = PQI_STATUS_SUCCESS; | int ret = PQI_STATUS_SUCCESS; | ||||
Show All 13 Lines | static int pqisrc_get_dev_data(pqisrc_softstate_t *softs, | ||||
pqisrc_sanitize_inquiry_string(&inq_buff[8], 8); | pqisrc_sanitize_inquiry_string(&inq_buff[8], 8); | ||||
pqisrc_sanitize_inquiry_string(&inq_buff[16], 16); | pqisrc_sanitize_inquiry_string(&inq_buff[16], 16); | ||||
device->devtype = inq_buff[0] & 0x1f; | device->devtype = inq_buff[0] & 0x1f; | ||||
memcpy(device->vendor, &inq_buff[8], | memcpy(device->vendor, &inq_buff[8], | ||||
sizeof(device->vendor)); | sizeof(device->vendor)); | ||||
memcpy(device->model, &inq_buff[16], | memcpy(device->model, &inq_buff[16], | ||||
sizeof(device->model)); | sizeof(device->model)); | ||||
DBG_INFO("DEV_TYPE: %x VENDOR: %s MODEL: %s\n", device->devtype, device->vendor, device->model); | DBG_DISC("DEV_TYPE: %x VENDOR: %s MODEL: %s\n", device->devtype, device->vendor, device->model); | ||||
if (pqisrc_is_logical_device(device) && device->devtype == DISK_DEVICE) { | if (pqisrc_is_logical_device(device) && device->devtype == DISK_DEVICE) { | ||||
if (pqisrc_is_external_raid_device(device)) { | if (pqisrc_is_external_raid_device(device)) { | ||||
device->raid_level = SA_RAID_UNKNOWN; | device->raid_level = SA_RAID_UNKNOWN; | ||||
device->volume_status = SA_LV_OK; | device->volume_status = SA_LV_OK; | ||||
device->volume_offline = false; | device->volume_offline = false; | ||||
} | } | ||||
else { | else { | ||||
▲ Show 20 Lines • Show All 64 Lines • ▼ Show 20 Lines | memcpy(softs->fw_version, identify_ctrl->fw_version, | ||||
sizeof(identify_ctrl->fw_version)); | sizeof(identify_ctrl->fw_version)); | ||||
softs->fw_version[sizeof(identify_ctrl->fw_version)] = '\0'; | softs->fw_version[sizeof(identify_ctrl->fw_version)] = '\0'; | ||||
snprintf(softs->fw_version + | snprintf(softs->fw_version + | ||||
strlen(softs->fw_version), | strlen(softs->fw_version), | ||||
sizeof(softs->fw_version), | sizeof(softs->fw_version), | ||||
"-%u", identify_ctrl->fw_build_number); | "-%u", identify_ctrl->fw_build_number); | ||||
out: | out: | ||||
os_mem_free(softs, (char *)identify_ctrl, sizeof(*identify_ctrl)); | os_mem_free(softs, (char *)identify_ctrl, sizeof(*identify_ctrl)); | ||||
DBG_INFO("Firmware version: %s Firmware build number: %d\n", softs->fw_version, softs->fw_build_number); | DBG_INIT("Firmware version: %s Firmware build number: %d\n", softs->fw_version, softs->fw_build_number); | ||||
DBG_FUNC("OUT\n"); | DBG_FUNC("OUT\n"); | ||||
return ret; | return ret; | ||||
} | } | ||||
/* BMIC command to determine scsi device identify params */ | /* BMIC command to determine scsi device identify params */ | ||||
static int pqisrc_identify_physical_disk(pqisrc_softstate_t *softs, | static int pqisrc_identify_physical_disk(pqisrc_softstate_t *softs, | ||||
pqi_scsi_dev_t *device, | pqi_scsi_dev_t *device, | ||||
bmic_ident_physdev_t *buff, | bmic_ident_physdev_t *buff, | ||||
▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | static void pqisrc_get_physical_device_info(pqisrc_softstate_t *softs, | ||||
memcpy(&device->box, | memcpy(&device->box, | ||||
&id_phys->alternate_paths_phys_box_on_port, | &id_phys->alternate_paths_phys_box_on_port, | ||||
sizeof(device->box)); | sizeof(device->box)); | ||||
memcpy(&device->phys_connector, | memcpy(&device->phys_connector, | ||||
&id_phys->alternate_paths_phys_connector, | &id_phys->alternate_paths_phys_connector, | ||||
sizeof(device->phys_connector)); | sizeof(device->phys_connector)); | ||||
device->bay = id_phys->phys_bay_in_box; | device->bay = id_phys->phys_bay_in_box; | ||||
DBG_INFO("BMIC DEV_TYPE: %x QUEUE DEPTH: 0x%x \n", device->device_type, device->queue_depth); | DBG_DISC("BMIC DEV_TYPE: %x QUEUE DEPTH: 0x%x \n", device->device_type, device->queue_depth); | ||||
DBG_FUNC("OUT\n"); | DBG_FUNC("OUT\n"); | ||||
} | } | ||||
/* Function used to find the entry of the device in a list */ | /* Function used to find the entry of the device in a list */ | ||||
static device_status_t pqisrc_scsi_find_entry(pqisrc_softstate_t *softs, | static device_status_t pqisrc_scsi_find_entry(pqisrc_softstate_t *softs, | ||||
pqi_scsi_dev_t *device_to_find, | pqi_scsi_dev_t *device_to_find, | ||||
pqi_scsi_dev_t **same_device) | pqi_scsi_dev_t **same_device) | ||||
▲ Show 20 Lines • Show All 97 Lines • ▼ Show 20 Lines | static void pqisrc_update_log_dev_qdepth(pqisrc_softstate_t *softs) | ||||
unsigned phys_dev_num; | unsigned phys_dev_num; | ||||
unsigned num_raidmap_entries; | unsigned num_raidmap_entries; | ||||
unsigned queue_depth; | unsigned queue_depth; | ||||
pqisrc_raid_map_t *raid_map; | pqisrc_raid_map_t *raid_map; | ||||
pqi_scsi_dev_t *device; | pqi_scsi_dev_t *device; | ||||
raidmap_data_t *dev_data; | raidmap_data_t *dev_data; | ||||
pqi_scsi_dev_t *phys_disk; | pqi_scsi_dev_t *phys_disk; | ||||
unsigned j; | unsigned j; | ||||
unsigned k; | |||||
DBG_FUNC("IN\n"); | DBG_FUNC("IN\n"); | ||||
for(i = 0; i < PQI_MAX_DEVICES; i++) { | for(i = 0; i < PQI_MAX_DEVICES; i++) { | ||||
for(j = 0; j < PQI_MAX_MULTILUN; j++) { | for(j = 0; j < PQI_MAX_MULTILUN; j++) { | ||||
if(softs->device_list[i][j] == NULL) | if(softs->device_list[i][j] == NULL) | ||||
continue; | continue; | ||||
device = softs->device_list[i][j]; | device = softs->device_list[i][j]; | ||||
if (device->devtype != DISK_DEVICE) | if (device->devtype != DISK_DEVICE) | ||||
Show All 9 Lines | for(j = 0; j < PQI_MAX_MULTILUN; j++) { | ||||
dev_data = raid_map->dev_data; | dev_data = raid_map->dev_data; | ||||
phys_dev_num = LE_16(raid_map->layout_map_count) * | phys_dev_num = LE_16(raid_map->layout_map_count) * | ||||
(LE_16(raid_map->data_disks_per_row) + | (LE_16(raid_map->data_disks_per_row) + | ||||
LE_16(raid_map->metadata_disks_per_row)); | LE_16(raid_map->metadata_disks_per_row)); | ||||
num_raidmap_entries = phys_dev_num * | num_raidmap_entries = phys_dev_num * | ||||
LE_16(raid_map->row_cnt); | LE_16(raid_map->row_cnt); | ||||
queue_depth = 0; | queue_depth = 0; | ||||
for (i = 0; i < num_raidmap_entries; i++) { | for (k = 0; k < num_raidmap_entries; k++) { | ||||
phys_disk = pqisrc_identify_device_via_ioaccel(softs, | phys_disk = pqisrc_identify_device_via_ioaccel(softs, | ||||
dev_data[i].ioaccel_handle); | dev_data[k].ioaccel_handle); | ||||
if (!phys_disk) { | if (!phys_disk) { | ||||
DBG_WARN( | DBG_WARN( | ||||
"Failed to find physical disk handle for logical drive %016llx\n", | "Failed to find physical disk handle for logical drive %016llx\n", | ||||
(unsigned long long)BE_64(device->scsi3addr[0])); | (unsigned long long)BE_64(device->scsi3addr[0])); | ||||
device->offload_enabled = false; | device->offload_enabled = false; | ||||
device->offload_enabled_pending = false; | device->offload_enabled_pending = false; | ||||
if (raid_map) | if (raid_map) | ||||
Show All 11 Lines | static void pqisrc_update_log_dev_qdepth(pqisrc_softstate_t *softs) | ||||
DBG_FUNC("OUT\n"); | DBG_FUNC("OUT\n"); | ||||
} | } | ||||
/* Function used to add a scsi device to OS scsi subsystem */ | /* Function used to add a scsi device to OS scsi subsystem */ | ||||
static int pqisrc_add_device(pqisrc_softstate_t *softs, | static int pqisrc_add_device(pqisrc_softstate_t *softs, | ||||
pqi_scsi_dev_t *device) | pqi_scsi_dev_t *device) | ||||
{ | { | ||||
DBG_FUNC("IN\n"); | DBG_FUNC("IN\n"); | ||||
DBG_INFO("vendor: %s model: %s bus:%d target:%d lun:%d is_physical_device:0x%x expose_device:0x%x volume_offline 0x%x volume_status 0x%x \n", | DBG_WARN("vendor: %s model: %s bus:%d target:%d lun:%d is_physical_device:0x%x expose_device:0x%x volume_offline 0x%x volume_status 0x%x \n", | ||||
device->vendor, device->model, device->bus, device->target, device->lun, device->is_physical_device, device->expose_device, device->volume_offline, device->volume_status); | device->vendor, device->model, device->bus, device->target, device->lun, device->is_physical_device, device->expose_device, device->volume_offline, device->volume_status); | ||||
device->invalid = false; | device->invalid = false; | ||||
if(device->expose_device) { | if(device->expose_device) { | ||||
/* TBD: Call OS upper layer function to add the device entry */ | /* TBD: Call OS upper layer function to add the device entry */ | ||||
os_add_device(softs,device); | os_add_device(softs,device); | ||||
} | } | ||||
DBG_FUNC("OUT\n"); | DBG_FUNC("OUT\n"); | ||||
return PQI_STATUS_SUCCESS; | return PQI_STATUS_SUCCESS; | ||||
} | } | ||||
/* Function used to remove a scsi device from OS scsi subsystem */ | /* Function used to remove a scsi device from OS scsi subsystem */ | ||||
void pqisrc_remove_device(pqisrc_softstate_t *softs, | void pqisrc_remove_device(pqisrc_softstate_t *softs, | ||||
pqi_scsi_dev_t *device) | pqi_scsi_dev_t *device) | ||||
{ | { | ||||
DBG_FUNC("IN\n"); | DBG_FUNC("IN\n"); | ||||
DBG_INFO("vendor: %s model: %s bus:%d target:%d lun:%d is_physical_device:0x%x expose_device:0x%x volume_offline 0x%x volume_status 0x%x \n", | DBG_DISC("vendor: %s model: %s bus:%d target:%d lun:%d is_physical_device:0x%x expose_device:0x%x volume_offline 0x%x volume_status 0x%x \n", | ||||
device->vendor, device->model, device->bus, device->target, device->lun, device->is_physical_device, device->expose_device, device->volume_offline, device->volume_status); | device->vendor, device->model, device->bus, device->target, device->lun, device->is_physical_device, device->expose_device, device->volume_offline, device->volume_status); | ||||
/* TBD: Call OS upper layer function to remove the device entry */ | /* TBD: Call OS upper layer function to remove the device entry */ | ||||
device->invalid = true; | device->invalid = true; | ||||
os_remove_device(softs,device); | os_remove_device(softs,device); | ||||
DBG_FUNC("OUT\n"); | DBG_FUNC("OUT\n"); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 67 Lines • ▼ Show 20 Lines | static void pqisrc_display_volume_status(pqisrc_softstate_t *softs, | ||||
case SA_LV_STATUS_VPD_UNSUPPORTED: | case SA_LV_STATUS_VPD_UNSUPPORTED: | ||||
status = "Volume status is not available through vital product data pages."; | status = "Volume status is not available through vital product data pages."; | ||||
break; | break; | ||||
default: | default: | ||||
status = "Volume is in an unknown state."; | status = "Volume is in an unknown state."; | ||||
break; | break; | ||||
} | } | ||||
DBG_INFO("scsi BTL %d:%d:%d %s\n", | DBG_DISC("scsi BTL %d:%d:%d %s\n", | ||||
device->bus, device->target, device->lun, status); | device->bus, device->target, device->lun, status); | ||||
DBG_FUNC("OUT\n"); | DBG_FUNC("OUT\n"); | ||||
} | } | ||||
void pqisrc_device_mem_free(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device) | void pqisrc_device_mem_free(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device) | ||||
{ | { | ||||
DBG_INFO("IN\n"); | DBG_FUNC("IN\n"); | ||||
if (!device) | if (!device) | ||||
return; | return; | ||||
if (device->raid_map) { | if (device->raid_map) { | ||||
os_mem_free(softs, (char *)device->raid_map, sizeof(pqisrc_raid_map_t)); | os_mem_free(softs, (char *)device->raid_map, sizeof(pqisrc_raid_map_t)); | ||||
} | } | ||||
os_mem_free(softs, (char *)device,sizeof(*device)); | os_mem_free(softs, (char *)device,sizeof(*device)); | ||||
DBG_INFO("OUT\n"); | DBG_FUNC("OUT\n"); | ||||
} | } | ||||
/* OS should call this function to free the scsi device */ | /* OS should call this function to free the scsi device */ | ||||
void pqisrc_free_device(pqisrc_softstate_t * softs,pqi_scsi_dev_t *device) | void pqisrc_free_device(pqisrc_softstate_t * softs,pqi_scsi_dev_t *device) | ||||
{ | { | ||||
OS_ACQUIRE_SPINLOCK(&softs->devlist_lock); | OS_ACQUIRE_SPINLOCK(&softs->devlist_lock); | ||||
if (!pqisrc_is_logical_device(device)) { | |||||
pqisrc_free_tid(softs,device->target); | |||||
} | |||||
pqisrc_device_mem_free(softs, device); | pqisrc_device_mem_free(softs, device); | ||||
OS_RELEASE_SPINLOCK(&softs->devlist_lock); | OS_RELEASE_SPINLOCK(&softs->devlist_lock); | ||||
} | } | ||||
/* Update the newly added devices to the device list */ | /* Update the newly added devices to the device list */ | ||||
static void pqisrc_update_device_list(pqisrc_softstate_t *softs, | static void pqisrc_update_device_list(pqisrc_softstate_t *softs, | ||||
pqi_scsi_dev_t *new_device_list[], int num_new_devices) | pqi_scsi_dev_t *new_device_list[], int num_new_devices) | ||||
{ | { | ||||
int ret; | int ret; | ||||
int i; | int i; | ||||
device_status_t dev_status; | device_status_t dev_status; | ||||
pqi_scsi_dev_t *device; | pqi_scsi_dev_t *device; | ||||
pqi_scsi_dev_t *same_device; | pqi_scsi_dev_t *same_device; | ||||
pqi_scsi_dev_t **added = NULL; | pqi_scsi_dev_t **added = NULL; | ||||
pqi_scsi_dev_t **removed = NULL; | pqi_scsi_dev_t **removed = NULL; | ||||
int nadded = 0, nremoved = 0; | int nadded = 0, nremoved = 0; | ||||
int j; | int j; | ||||
DBG_INFO("IN\n"); | int tid = 0; | ||||
DBG_FUNC("IN\n"); | |||||
added = os_mem_alloc(softs, sizeof(*added) * PQI_MAX_DEVICES); | added = os_mem_alloc(softs, sizeof(*added) * PQI_MAX_DEVICES); | ||||
removed = os_mem_alloc(softs, sizeof(*removed) * PQI_MAX_DEVICES); | removed = os_mem_alloc(softs, sizeof(*removed) * PQI_MAX_DEVICES); | ||||
if (!added || !removed) { | if (!added || !removed) { | ||||
DBG_WARN("Out of memory \n"); | DBG_WARN("Out of memory \n"); | ||||
goto free_and_out; | goto free_and_out; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | static void pqisrc_update_device_list(pqisrc_softstate_t *softs, | ||||
/* Process all new devices. */ | /* Process all new devices. */ | ||||
for (i = 0, nadded = 0; i < num_new_devices; i++) { | for (i = 0, nadded = 0; i < num_new_devices; i++) { | ||||
device = new_device_list[i]; | device = new_device_list[i]; | ||||
if (!device->new_device) | if (!device->new_device) | ||||
continue; | continue; | ||||
if (device->volume_offline) | if (device->volume_offline) | ||||
continue; | continue; | ||||
/* physical device */ | |||||
if (!pqisrc_is_logical_device(device)) { | |||||
tid = pqisrc_alloc_tid(softs); | |||||
if(INVALID_ELEM != tid) | |||||
pqisrc_set_btl(device, PQI_PHYSICAL_DEVICE_BUS, tid, 0); | |||||
} | |||||
softs->device_list[device->target][device->lun] = device; | softs->device_list[device->target][device->lun] = device; | ||||
DBG_INFO("Added device %p at B : %d T : %d L : %d\n",device, | DBG_DISC("Added device %p at B : %d T : %d L : %d\n",device, | ||||
device->bus,device->target,device->lun); | device->bus,device->target,device->lun); | ||||
/* To prevent this entry from being freed later. */ | /* To prevent this entry from being freed later. */ | ||||
new_device_list[i] = NULL; | new_device_list[i] = NULL; | ||||
added[nadded] = device; | added[nadded] = device; | ||||
nadded++; | nadded++; | ||||
} | } | ||||
pqisrc_update_log_dev_qdepth(softs); | pqisrc_update_log_dev_qdepth(softs); | ||||
▲ Show 20 Lines • Show All 66 Lines • ▼ Show 20 Lines | |||||
free_and_out: | free_and_out: | ||||
if (added) | if (added) | ||||
os_mem_free(softs, (char *)added, | os_mem_free(softs, (char *)added, | ||||
sizeof(*added) * PQI_MAX_DEVICES); | sizeof(*added) * PQI_MAX_DEVICES); | ||||
if (removed) | if (removed) | ||||
os_mem_free(softs, (char *)removed, | os_mem_free(softs, (char *)removed, | ||||
sizeof(*removed) * PQI_MAX_DEVICES); | sizeof(*removed) * PQI_MAX_DEVICES); | ||||
DBG_INFO("OUT\n"); | DBG_FUNC("OUT\n"); | ||||
} | } | ||||
/* | /* | ||||
* Let the Adapter know about driver version using one of BMIC | * Let the Adapter know about driver version using one of BMIC | ||||
* BMIC_WRITE_HOST_WELLNESS | * BMIC_WRITE_HOST_WELLNESS | ||||
*/ | */ | ||||
int pqisrc_write_driver_version_to_host_wellness(pqisrc_softstate_t *softs) | int pqisrc_write_driver_version_to_host_wellness(pqisrc_softstate_t *softs) | ||||
{ | { | ||||
Show All 21 Lines | int pqisrc_write_driver_version_to_host_wellness(pqisrc_softstate_t *softs) | ||||
host_wellness_driver_ver->driver_version_tag[1] = 'V'; | host_wellness_driver_ver->driver_version_tag[1] = 'V'; | ||||
host_wellness_driver_ver->driver_version_length = LE_16(sizeof(host_wellness_driver_ver->driver_version)); | host_wellness_driver_ver->driver_version_length = LE_16(sizeof(host_wellness_driver_ver->driver_version)); | ||||
strncpy(host_wellness_driver_ver->driver_version, softs->os_name, | strncpy(host_wellness_driver_ver->driver_version, softs->os_name, | ||||
sizeof(host_wellness_driver_ver->driver_version)); | sizeof(host_wellness_driver_ver->driver_version)); | ||||
if (strlen(softs->os_name) < sizeof(host_wellness_driver_ver->driver_version) ) { | if (strlen(softs->os_name) < sizeof(host_wellness_driver_ver->driver_version) ) { | ||||
strncpy(host_wellness_driver_ver->driver_version + strlen(softs->os_name), PQISRC_DRIVER_VERSION, | strncpy(host_wellness_driver_ver->driver_version + strlen(softs->os_name), PQISRC_DRIVER_VERSION, | ||||
sizeof(host_wellness_driver_ver->driver_version) - strlen(softs->os_name)); | sizeof(host_wellness_driver_ver->driver_version) - strlen(softs->os_name)); | ||||
} else { | } else { | ||||
DBG_INFO("OS name length(%lu) is longer than buffer of driver_version\n", | DBG_DISC("OS name length(%lu) is longer than buffer of driver_version\n", | ||||
strlen(softs->os_name)); | strlen(softs->os_name)); | ||||
} | } | ||||
host_wellness_driver_ver->driver_version[sizeof(host_wellness_driver_ver->driver_version) - 1] = '\0'; | host_wellness_driver_ver->driver_version[sizeof(host_wellness_driver_ver->driver_version) - 1] = '\0'; | ||||
host_wellness_driver_ver->end_tag[0] = 'Z'; | host_wellness_driver_ver->end_tag[0] = 'Z'; | ||||
host_wellness_driver_ver->end_tag[1] = 'Z'; | host_wellness_driver_ver->end_tag[1] = 'Z'; | ||||
rval = pqisrc_build_send_raid_request(softs, &request, host_wellness_driver_ver,data_length, | rval = pqisrc_build_send_raid_request(softs, &request, host_wellness_driver_ver,data_length, | ||||
BMIC_WRITE_HOST_WELLNESS, 0, (uint8_t *)RAID_CTLR_LUNID, NULL); | BMIC_WRITE_HOST_WELLNESS, 0, (uint8_t *)RAID_CTLR_LUNID, NULL); | ||||
▲ Show 20 Lines • Show All 84 Lines • ▼ Show 20 Lines | if (ret) | ||||
goto err_out; | goto err_out; | ||||
physical_cnt = BE_32(physical_dev_list->header.list_length) | physical_cnt = BE_32(physical_dev_list->header.list_length) | ||||
/ sizeof(physical_dev_list->lun_entries[0]); | / sizeof(physical_dev_list->lun_entries[0]); | ||||
logical_cnt = BE_32(logical_dev_list->header.list_length) | logical_cnt = BE_32(logical_dev_list->header.list_length) | ||||
/ sizeof(logical_dev_list->lun_entries[0]); | / sizeof(logical_dev_list->lun_entries[0]); | ||||
DBG_INFO("physical_cnt %d logical_cnt %d\n", physical_cnt, logical_cnt); | DBG_DISC("physical_cnt %d logical_cnt %d\n", physical_cnt, logical_cnt); | ||||
if (physical_cnt) { | if (physical_cnt) { | ||||
bmic_phy_info = os_mem_alloc(softs, sizeof(*bmic_phy_info)); | bmic_phy_info = os_mem_alloc(softs, sizeof(*bmic_phy_info)); | ||||
if (bmic_phy_info == NULL) { | if (bmic_phy_info == NULL) { | ||||
ret = PQI_STATUS_FAILURE; | ret = PQI_STATUS_FAILURE; | ||||
DBG_ERR("failed to allocate memory for BMIC ID PHYS Device : %d\n", ret); | DBG_ERR("failed to allocate memory for BMIC ID PHYS Device : %d\n", ret); | ||||
goto err_out; | goto err_out; | ||||
} | } | ||||
Show All 28 Lines | if (i < physical_cnt) { | ||||
lun_ext_entry = &physical_dev_list->lun_entries[i]; | lun_ext_entry = &physical_dev_list->lun_entries[i]; | ||||
} else { | } else { | ||||
is_physical_device = false; | is_physical_device = false; | ||||
lun_ext_entry = | lun_ext_entry = | ||||
&logical_dev_list->lun_entries[i - physical_cnt]; | &logical_dev_list->lun_entries[i - physical_cnt]; | ||||
} | } | ||||
scsi3addr = lun_ext_entry->lunid; | scsi3addr = lun_ext_entry->lunid; | ||||
/* Save the target sas adderess for external raid device */ | |||||
if(lun_ext_entry->device_type == CONTROLLER_DEVICE) { | |||||
int target = lun_ext_entry->lunid[3] & 0x3f; | |||||
softs->target_sas_addr[target] = BE_64(lun_ext_entry->wwid); | |||||
} | |||||
/* Skip masked physical non-disk devices. */ | /* Skip masked physical non-disk devices. */ | ||||
if (MASKED_DEVICE(scsi3addr) && is_physical_device) | if (MASKED_DEVICE(scsi3addr) && is_physical_device | ||||
&& (lun_ext_entry->ioaccel_handle == 0)) | |||||
continue; | continue; | ||||
device = new_device_list[new_dev_cnt]; | device = new_device_list[new_dev_cnt]; | ||||
memset(device, 0, sizeof(*device)); | memset(device, 0, sizeof(*device)); | ||||
memcpy(device->scsi3addr, scsi3addr, sizeof(device->scsi3addr)); | memcpy(device->scsi3addr, scsi3addr, sizeof(device->scsi3addr)); | ||||
device->wwid = lun_ext_entry->wwid; | device->wwid = lun_ext_entry->wwid; | ||||
device->is_physical_device = is_physical_device; | device->is_physical_device = is_physical_device; | ||||
if (!is_physical_device) | if (!is_physical_device) | ||||
device->is_external_raid_device = | device->is_external_raid_device = | ||||
pqisrc_is_external_raid_addr(scsi3addr); | pqisrc_is_external_raid_addr(scsi3addr); | ||||
/* Get device type, vendor, model, device ID. */ | /* Get device type, vendor, model, device ID. */ | ||||
ret = pqisrc_get_dev_data(softs, device); | ret = pqisrc_get_dev_data(softs, device); | ||||
if (ret) { | if (ret) { | ||||
DBG_WARN("Inquiry failed, skipping device %016llx\n", | DBG_WARN("Inquiry failed, skipping device %016llx\n", | ||||
(unsigned long long)BE_64(device->scsi3addr[0])); | (unsigned long long)BE_64(device->scsi3addr[0])); | ||||
DBG_INFO("INQUIRY FAILED \n"); | DBG_DISC("INQUIRY FAILED \n"); | ||||
continue; | continue; | ||||
} | } | ||||
pqisrc_assign_btl(device); | pqisrc_assign_btl(device); | ||||
/* | /* | ||||
* Expose all devices except for physical devices that | * Expose all devices except for physical devices that | ||||
* are masked. | * are masked. | ||||
*/ | */ | ||||
Show All 24 Lines | for (i = 0; i < phy_log_dev_cnt; i++) { | ||||
case ZBC_DEVICE: | case ZBC_DEVICE: | ||||
if (device->is_physical_device) { | if (device->is_physical_device) { | ||||
device->ioaccel_handle = | device->ioaccel_handle = | ||||
lun_ext_entry->ioaccel_handle; | lun_ext_entry->ioaccel_handle; | ||||
device->sas_address = BE_64(lun_ext_entry->wwid); | device->sas_address = BE_64(lun_ext_entry->wwid); | ||||
pqisrc_get_physical_device_info(softs, device, | pqisrc_get_physical_device_info(softs, device, | ||||
bmic_phy_info); | bmic_phy_info); | ||||
} | } | ||||
/* Logical device doesn't have SAS address | |||||
* so requires target SAS address for MSA. | |||||
*/ | |||||
if(device->is_external_raid_device) | |||||
device->sas_address = BE_64((uint64_t)lun_ext_entry->lunid); | |||||
new_dev_cnt++; | new_dev_cnt++; | ||||
break; | break; | ||||
case ENCLOSURE_DEVICE: | case ENCLOSURE_DEVICE: | ||||
if (device->is_physical_device) { | if (device->is_physical_device) { | ||||
device->sas_address = BE_64(lun_ext_entry->wwid); | device->sas_address = BE_64(lun_ext_entry->wwid); | ||||
} | } | ||||
new_dev_cnt++; | new_dev_cnt++; | ||||
break; | break; | ||||
case TAPE_DEVICE: | case TAPE_DEVICE: | ||||
case MEDIUM_CHANGER_DEVICE: | case MEDIUM_CHANGER_DEVICE: | ||||
new_dev_cnt++; | new_dev_cnt++; | ||||
break; | break; | ||||
case RAID_DEVICE: | case RAID_DEVICE: | ||||
/* | /* | ||||
* Only present the HBA controller itself as a RAID | * Only present the HBA controller itself as a RAID | ||||
* controller. If it's a RAID controller other than | * controller. If it's a RAID controller other than | ||||
* the HBA itself (an external RAID controller, MSA500 | * the HBA itself (an external RAID controller, MSA500 | ||||
* or similar), don't present it. | * or similar), don't present it. | ||||
*/ | */ | ||||
if (pqisrc_is_hba_lunid(scsi3addr)) | if (pqisrc_is_hba_lunid(scsi3addr)) | ||||
new_dev_cnt++; | new_dev_cnt++; | ||||
break; | break; | ||||
case SES_DEVICE: | |||||
case CONTROLLER_DEVICE: | |||||
break; | |||||
} | } | ||||
} | } | ||||
DBG_INFO("new_dev_cnt %d\n", new_dev_cnt); | DBG_DISC("new_dev_cnt %d\n", new_dev_cnt); | ||||
pqisrc_update_device_list(softs, new_device_list, new_dev_cnt); | pqisrc_update_device_list(softs, new_device_list, new_dev_cnt); | ||||
err_out: | err_out: | ||||
if (new_device_list) { | if (new_device_list) { | ||||
for (i = 0; i < ndev_allocated; i++) { | for (i = 0; i < ndev_allocated; i++) { | ||||
if (new_device_list[i]) { | if (new_device_list[i]) { | ||||
if(new_device_list[i]->raid_map) | if(new_device_list[i]->raid_map) | ||||
▲ Show 20 Lines • Show All 42 Lines • Show Last 20 Lines |