1 /*- 2 * Copyright (c) 2018 Microsemi Corporation. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 /* $FreeBSD$ */ 28 29 #include "smartpqi_includes.h" 30 31 /* 32 * Function used to validate the adapter health. 33 */ 34 boolean_t pqisrc_ctrl_offline(pqisrc_softstate_t *softs) 35 { 36 DBG_FUNC("IN\n"); 37 38 DBG_FUNC("OUT\n"); 39 40 return !softs->ctrl_online; 41 } 42 43 /* 44 * Function used to take exposed devices to OS as offline. 45 */ 46 void pqisrc_take_devices_offline(pqisrc_softstate_t *softs) 47 { 48 pqi_scsi_dev_t *device = NULL; 49 int i,j; 50 51 DBG_FUNC("IN\n"); 52 for(i = 0; i < PQI_MAX_DEVICES; i++) { 53 for(j = 0; j < PQI_MAX_MULTILUN; j++) { 54 if(softs->device_list[i][j] == NULL) 55 continue; 56 device = softs->device_list[i][j]; 57 pqisrc_remove_device(softs, device); 58 } 59 } 60 61 DBG_FUNC("OUT\n"); 62 } 63 64 /* 65 * Function used to take adapter offline. 66 */ 67 void pqisrc_take_ctrl_offline(pqisrc_softstate_t *softs) 68 { 69 70 DBG_FUNC("IN\n"); 71 72 softs->ctrl_online = false; 73 pqisrc_trigger_nmi_sis(softs); 74 os_complete_outstanding_cmds_nodevice(softs); 75 pqisrc_take_devices_offline(softs); 76 77 DBG_FUNC("OUT\n"); 78 } 79 80 /* 81 * Timer handler for the adapter heart-beat. 82 */ 83 void pqisrc_heartbeat_timer_handler(pqisrc_softstate_t *softs) 84 { 85 uint64_t num_intrs; 86 uint8_t take_offline = false; 87 88 DBG_FUNC("IN\n"); 89 90 num_intrs = OS_ATOMIC64_READ(softs, num_intrs); 91 92 if (PQI_NEW_HEARTBEAT_MECHANISM(softs)) { 93 if (CTRLR_HEARTBEAT_CNT(softs) == softs->prev_heartbeat_count) { 94 take_offline = true; 95 goto take_ctrl_offline; 96 } 97 softs->prev_heartbeat_count = CTRLR_HEARTBEAT_CNT(softs); 98 DBG_INFO("CTRLR_HEARTBEAT_CNT(softs) = %lx \ 99 softs->prev_heartbeat_count = %lx\n", 100 CTRLR_HEARTBEAT_CNT(softs), softs->prev_heartbeat_count); 101 } else { 102 if (num_intrs == softs->prev_num_intrs) { 103 softs->num_heartbeats_requested++; 104 if (softs->num_heartbeats_requested > PQI_MAX_HEARTBEAT_REQUESTS) { 105 take_offline = true; 106 goto take_ctrl_offline; 107 } 108 softs->pending_events[PQI_EVENT_HEARTBEAT].pending = true; 109 110 pqisrc_ack_all_events((void*)softs); 111 112 } else { 113 softs->num_heartbeats_requested = 0; 114 } 115 softs->prev_num_intrs = num_intrs; 116 } 117 118 take_ctrl_offline: 119 if (take_offline){ 120 DBG_ERR("controller is offline\n"); 121 pqisrc_take_ctrl_offline(softs); 122 os_stop_heartbeat_timer(softs); 123 } 124 DBG_FUNC("OUT\n"); 125 } 126 127 /* 128 * Conditional variable management routine for internal commands. 129 */ 130 int pqisrc_wait_on_condition(pqisrc_softstate_t *softs, rcb_t *rcb){ 131 132 DBG_FUNC("IN\n"); 133 134 int ret = PQI_STATUS_SUCCESS; 135 uint32_t loop_cnt = 0; 136 137 while (rcb->req_pending == true) { 138 OS_SLEEP(500); /* Micro sec */ 139 140 /*Polling needed for FreeBSD : since ithread routine is not scheduled 141 during bootup, we could use polling until interrupts are 142 enabled (using 'if (cold)'to check for the boot time before 143 interrupts are enabled). */ 144 IS_POLLING_REQUIRED(softs); 145 146 if (loop_cnt++ == PQISRC_CMD_TIMEOUT_CNT) { 147 DBG_ERR("ERR: Requested cmd timed out !!!\n"); 148 ret = PQI_STATUS_TIMEOUT; 149 break; 150 } 151 152 if (pqisrc_ctrl_offline(softs)) { 153 DBG_ERR("Controller is Offline"); 154 ret = PQI_STATUS_FAILURE; 155 break; 156 } 157 158 } 159 rcb->req_pending = true; 160 161 DBG_FUNC("OUT\n"); 162 163 return ret; 164 } 165 166 /* Function used to validate the device wwid. */ 167 boolean_t pqisrc_device_equal(pqi_scsi_dev_t *dev1, 168 pqi_scsi_dev_t *dev2) 169 { 170 return dev1->wwid == dev2->wwid; 171 } 172 173 /* Function used to validate the device scsi3addr. */ 174 boolean_t pqisrc_scsi3addr_equal(uint8_t *scsi3addr1, uint8_t *scsi3addr2) 175 { 176 return memcmp(scsi3addr1, scsi3addr2, 8) == 0; 177 } 178 179 /* Function used to validate hba_lunid */ 180 boolean_t pqisrc_is_hba_lunid(uint8_t *scsi3addr) 181 { 182 return pqisrc_scsi3addr_equal(scsi3addr, (uint8_t*)RAID_CTLR_LUNID); 183 } 184 185 /* Function used to validate type of device */ 186 boolean_t pqisrc_is_logical_device(pqi_scsi_dev_t *device) 187 { 188 return !device->is_physical_device; 189 } 190 191 /* Function used to sanitize inquiry string */ 192 void pqisrc_sanitize_inquiry_string(unsigned char *s, int len) 193 { 194 boolean_t terminated = false; 195 196 DBG_FUNC("IN\n"); 197 198 for (; len > 0; (--len, ++s)) { 199 if (*s == 0) 200 terminated = true; 201 if (terminated || *s < 0x20 || *s > 0x7e) 202 *s = ' '; 203 } 204 205 DBG_FUNC("OUT\n"); 206 } 207 208 static char *raid_levels[] = { 209 "RAID 0", 210 "RAID 4", 211 "RAID 1(1+0)", 212 "RAID 5", 213 "RAID 5+1", 214 "RAID ADG", 215 "RAID 1(ADM)", 216 "RAID 6", 217 }; 218 219 /* Get the RAID level from the index */ 220 char *pqisrc_raidlevel_to_string(uint8_t raid_level) 221 { 222 DBG_FUNC("IN\n"); 223 if (raid_level < ARRAY_SIZE(raid_levels)) 224 return raid_levels[raid_level]; 225 DBG_FUNC("OUT\n"); 226 227 return " "; 228 } 229 230 /* Debug routine for displaying device info */ 231 void pqisrc_display_device_info(pqisrc_softstate_t *softs, 232 char *action, pqi_scsi_dev_t *device) 233 { 234 DBG_INFO( "%s scsi BTL %d:%d:%d: %.8s %.16s %-12s SSDSmartPathCap%c En%c Exp%c qd=%d\n", 235 action, 236 device->bus, 237 device->target, 238 device->lun, 239 device->vendor, 240 device->model, 241 pqisrc_raidlevel_to_string(device->raid_level), 242 device->offload_config ? '+' : '-', 243 device->offload_enabled_pending ? '+' : '-', 244 device->expose_device ? '+' : '-', 245 device->queue_depth); 246 pqisrc_raidlevel_to_string(device->raid_level); /* To use this function */ 247 } 248 249 /* validate the structure sizes */ 250 void check_struct_sizes() 251 { 252 253 ASSERT(sizeof(SCSI3Addr_struct)== 2); 254 ASSERT(sizeof(PhysDevAddr_struct) == 8); 255 ASSERT(sizeof(LogDevAddr_struct)== 8); 256 ASSERT(sizeof(LUNAddr_struct)==8); 257 ASSERT(sizeof(RequestBlock_struct) == 20); 258 ASSERT(sizeof(MoreErrInfo_struct)== 8); 259 ASSERT(sizeof(ErrorInfo_struct)== 48); 260 ASSERT(sizeof(IOCTL_Command_struct)== 86); 261 ASSERT(sizeof(struct bmic_host_wellness_driver_version)== 42); 262 ASSERT(sizeof(struct bmic_host_wellness_time)== 20); 263 ASSERT(sizeof(struct pqi_dev_adminq_cap)== 8); 264 ASSERT(sizeof(struct admin_q_param)== 4); 265 ASSERT(sizeof(struct pqi_registers)== 256); 266 ASSERT(sizeof(struct ioa_registers)== 4128); 267 ASSERT(sizeof(struct pqi_pref_settings)==4); 268 ASSERT(sizeof(struct pqi_cap)== 20); 269 ASSERT(sizeof(iu_header_t)== 4); 270 ASSERT(sizeof(gen_adm_req_iu_t)== 64); 271 ASSERT(sizeof(gen_adm_resp_iu_t)== 64); 272 ASSERT(sizeof(op_q_params) == 9); 273 ASSERT(sizeof(raid_path_error_info_elem_t)== 276); 274 ASSERT(sizeof(aio_path_error_info_elem_t)== 276); 275 ASSERT(sizeof(struct init_base_struct)== 24); 276 ASSERT(sizeof(pqi_iu_layer_desc_t)== 16); 277 ASSERT(sizeof(pqi_dev_cap_t)== 576); 278 ASSERT(sizeof(pqi_aio_req_t)== 128); 279 ASSERT(sizeof(pqisrc_raid_req_t)== 128); 280 ASSERT(sizeof(pqi_tmf_req_t)== 32); 281 ASSERT(sizeof(struct pqi_io_response)== 16); 282 ASSERT(sizeof(struct sense_header_scsi)== 8); 283 ASSERT(sizeof(reportlun_header_t)==8); 284 ASSERT(sizeof(reportlun_ext_entry_t)== 24); 285 ASSERT(sizeof(reportlun_data_ext_t)== 32); 286 ASSERT(sizeof(raidmap_data_t)==8); 287 ASSERT(sizeof(pqisrc_raid_map_t)== 8256); 288 ASSERT(sizeof(bmic_ident_ctrl_t)== 325); 289 ASSERT(sizeof(bmic_ident_physdev_t)==2048); 290 291 } 292