xref: /freebsd/sys/dev/smartpqi/smartpqi_helper.c (revision 9fac68fc3853b696c8479bb3a8181d62cb9f59c9)
11e66f787SSean Bruno /*-
2*9fac68fcSPAPANI SRIKANTH  * Copyright 2016-2021 Microchip Technology, Inc. and/or its subsidiaries.
31e66f787SSean Bruno  *
41e66f787SSean Bruno  * Redistribution and use in source and binary forms, with or without
51e66f787SSean Bruno  * modification, are permitted provided that the following conditions
61e66f787SSean Bruno  * are met:
71e66f787SSean Bruno  * 1. Redistributions of source code must retain the above copyright
81e66f787SSean Bruno  *    notice, this list of conditions and the following disclaimer.
91e66f787SSean Bruno  * 2. Redistributions in binary form must reproduce the above copyright
101e66f787SSean Bruno  *    notice, this list of conditions and the following disclaimer in the
111e66f787SSean Bruno  *    documentation and/or other materials provided with the distribution.
121e66f787SSean Bruno  *
131e66f787SSean Bruno  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
141e66f787SSean Bruno  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
151e66f787SSean Bruno  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
161e66f787SSean Bruno  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
171e66f787SSean Bruno  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
181e66f787SSean Bruno  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
191e66f787SSean Bruno  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
201e66f787SSean Bruno  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
211e66f787SSean Bruno  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
221e66f787SSean Bruno  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
231e66f787SSean Bruno  * SUCH DAMAGE.
241e66f787SSean Bruno  */
251e66f787SSean Bruno 
261e66f787SSean Bruno /* $FreeBSD$ */
271e66f787SSean Bruno 
281e66f787SSean Bruno #include "smartpqi_includes.h"
291e66f787SSean Bruno 
30*9fac68fcSPAPANI SRIKANTH /* read and modify controller diagnostic option - PQI_PTRAID_UPDATE_ON_RESCAN_LUNS */
31*9fac68fcSPAPANI SRIKANTH void
32*9fac68fcSPAPANI SRIKANTH pqisrc_ctrl_diagnostic_options(pqisrc_softstate_t *softs)
33*9fac68fcSPAPANI SRIKANTH {
34*9fac68fcSPAPANI SRIKANTH 	int ret = PQI_STATUS_SUCCESS;
35*9fac68fcSPAPANI SRIKANTH 	uint32_t diags_options = 0;
36*9fac68fcSPAPANI SRIKANTH 	pqisrc_raid_req_t request;
37*9fac68fcSPAPANI SRIKANTH 
38*9fac68fcSPAPANI SRIKANTH 	DBG_NOTE("IN\n");
39*9fac68fcSPAPANI SRIKANTH 
40*9fac68fcSPAPANI SRIKANTH 	memset(&request, 0, sizeof(request));
41*9fac68fcSPAPANI SRIKANTH 	/* read diags options of controller */
42*9fac68fcSPAPANI SRIKANTH 	ret =  pqisrc_build_send_raid_request(softs, &request,
43*9fac68fcSPAPANI SRIKANTH 					(void*)&diags_options,
44*9fac68fcSPAPANI SRIKANTH 					sizeof(diags_options),
45*9fac68fcSPAPANI SRIKANTH 					BMIC_SENSE_DIAGS_OPTIONS,
46*9fac68fcSPAPANI SRIKANTH 					0, (uint8_t *)RAID_CTLR_LUNID, NULL);
47*9fac68fcSPAPANI SRIKANTH 	if (ret != PQI_STATUS_SUCCESS) {
48*9fac68fcSPAPANI SRIKANTH 		DBG_WARN("Request failed for BMIC Sense Diags Option command."
49*9fac68fcSPAPANI SRIKANTH 			"ret:%d\n",ret);
50*9fac68fcSPAPANI SRIKANTH 		return;
51*9fac68fcSPAPANI SRIKANTH 	}
52*9fac68fcSPAPANI SRIKANTH 	DBG_NOTE("diags options data after read: %#x\n",diags_options);
53*9fac68fcSPAPANI SRIKANTH 	diags_options |= PQI_PTRAID_UPDATE_ON_RESCAN_LUNS;
54*9fac68fcSPAPANI SRIKANTH 	DBG_NOTE("diags options data to write: %#x\n",diags_options);
55*9fac68fcSPAPANI SRIKANTH 	memset(&request, 0, sizeof(request));
56*9fac68fcSPAPANI SRIKANTH 	/* write specified diags options to controller */
57*9fac68fcSPAPANI SRIKANTH 	ret =  pqisrc_build_send_raid_request(softs, &request,
58*9fac68fcSPAPANI SRIKANTH 					(void*)&diags_options,
59*9fac68fcSPAPANI SRIKANTH 					sizeof(diags_options),
60*9fac68fcSPAPANI SRIKANTH 					BMIC_SET_DIAGS_OPTIONS,
61*9fac68fcSPAPANI SRIKANTH 					0, (uint8_t *)RAID_CTLR_LUNID, NULL);
62*9fac68fcSPAPANI SRIKANTH 	if (ret != PQI_STATUS_SUCCESS)
63*9fac68fcSPAPANI SRIKANTH 		DBG_WARN("Request failed for BMIC Set Diags Option command."
64*9fac68fcSPAPANI SRIKANTH 			"ret:%d\n",ret);
65*9fac68fcSPAPANI SRIKANTH #if 0
66*9fac68fcSPAPANI SRIKANTH 	diags_options = 0;
67*9fac68fcSPAPANI SRIKANTH 	memset(&request, 0, sizeof(request));
68*9fac68fcSPAPANI SRIKANTH 	ret =  pqisrc_build_send_raid_request(softs, &request,
69*9fac68fcSPAPANI SRIKANTH 					(void*)&diags_options,
70*9fac68fcSPAPANI SRIKANTH 					sizeof(diags_options),
71*9fac68fcSPAPANI SRIKANTH 					BMIC_SENSE_DIAGS_OPTIONS,
72*9fac68fcSPAPANI SRIKANTH 					0, (uint8_t *)RAID_CTLR_LUNID, NULL);
73*9fac68fcSPAPANI SRIKANTH 	if (ret != PQI_STATUS_SUCCESS)
74*9fac68fcSPAPANI SRIKANTH 		DBG_WARN("Request failed for BMIC Sense Diags Option command."
75*9fac68fcSPAPANI SRIKANTH 			"ret:%d\n",ret);
76*9fac68fcSPAPANI SRIKANTH 	DBG_NOTE("diags options after re-read: %#x\n",diags_options);
77*9fac68fcSPAPANI SRIKANTH #endif
78*9fac68fcSPAPANI SRIKANTH 	DBG_NOTE("OUT\n");
79*9fac68fcSPAPANI SRIKANTH }
80*9fac68fcSPAPANI SRIKANTH 
811e66f787SSean Bruno /*
821e66f787SSean Bruno  * Function used to validate the adapter health.
831e66f787SSean Bruno  */
84*9fac68fcSPAPANI SRIKANTH boolean_t
85*9fac68fcSPAPANI SRIKANTH pqisrc_ctrl_offline(pqisrc_softstate_t *softs)
861e66f787SSean Bruno {
871e66f787SSean Bruno 	DBG_FUNC("IN\n");
881e66f787SSean Bruno 
891e66f787SSean Bruno 	DBG_FUNC("OUT\n");
901e66f787SSean Bruno 
911e66f787SSean Bruno 	return !softs->ctrl_online;
921e66f787SSean Bruno }
931e66f787SSean Bruno 
94b17f4335SSean Bruno /* Function used set/clear legacy INTx bit in Legacy Interrupt INTx
95b17f4335SSean Bruno  * mask clear pqi register
96b17f4335SSean Bruno  */
97*9fac68fcSPAPANI SRIKANTH void
98*9fac68fcSPAPANI SRIKANTH pqisrc_configure_legacy_intx(pqisrc_softstate_t *softs, boolean_t enable_intx)
99b17f4335SSean Bruno {
100b17f4335SSean Bruno 	uint32_t intx_mask;
101b17f4335SSean Bruno 	uint32_t *reg_addr = NULL;
102b17f4335SSean Bruno 
103b17f4335SSean Bruno 	DBG_FUNC("IN\n");
104b17f4335SSean Bruno 
105b17f4335SSean Bruno 	if (enable_intx)
106b17f4335SSean Bruno 		reg_addr = &softs->pqi_reg->legacy_intr_mask_clr;
107b17f4335SSean Bruno 	else
108b17f4335SSean Bruno 		reg_addr = &softs->pqi_reg->legacy_intr_mask_set;
109b17f4335SSean Bruno 
110b17f4335SSean Bruno 	intx_mask = PCI_MEM_GET32(softs, reg_addr, PQI_LEGACY_INTR_MASK_CLR);
111b17f4335SSean Bruno 	intx_mask |= PQISRC_LEGACY_INTX_MASK;
112b17f4335SSean Bruno 	PCI_MEM_PUT32(softs, reg_addr, PQI_LEGACY_INTR_MASK_CLR ,intx_mask);
113b17f4335SSean Bruno 
114b17f4335SSean Bruno 	DBG_FUNC("OUT\n");
115b17f4335SSean Bruno }
116b17f4335SSean Bruno 
1171e66f787SSean Bruno /*
1181e66f787SSean Bruno  * Function used to take exposed devices to OS as offline.
1191e66f787SSean Bruno  */
120*9fac68fcSPAPANI SRIKANTH void
121*9fac68fcSPAPANI SRIKANTH pqisrc_take_devices_offline(pqisrc_softstate_t *softs)
1221e66f787SSean Bruno {
1231e66f787SSean Bruno 	pqi_scsi_dev_t *device = NULL;
1241e66f787SSean Bruno 	int i,j;
1251e66f787SSean Bruno 
1261e66f787SSean Bruno 	DBG_FUNC("IN\n");
1271e66f787SSean Bruno 	for(i = 0; i < PQI_MAX_DEVICES; i++) {
1281e66f787SSean Bruno 		for(j = 0; j < PQI_MAX_MULTILUN; j++) {
1291e66f787SSean Bruno 			if(softs->device_list[i][j] == NULL)
1301e66f787SSean Bruno 				continue;
1311e66f787SSean Bruno 			device = softs->device_list[i][j];
1321e66f787SSean Bruno 			pqisrc_remove_device(softs, device);
1331e66f787SSean Bruno 		}
1341e66f787SSean Bruno 	}
1351e66f787SSean Bruno 
1361e66f787SSean Bruno 	DBG_FUNC("OUT\n");
1371e66f787SSean Bruno }
1381e66f787SSean Bruno 
1391e66f787SSean Bruno /*
1401e66f787SSean Bruno  * Function used to take adapter offline.
1411e66f787SSean Bruno  */
142*9fac68fcSPAPANI SRIKANTH void
143*9fac68fcSPAPANI SRIKANTH pqisrc_take_ctrl_offline(pqisrc_softstate_t *softs)
1441e66f787SSean Bruno {
1451e66f787SSean Bruno 	DBG_FUNC("IN\n");
1461e66f787SSean Bruno 
1471e66f787SSean Bruno 	softs->ctrl_online = false;
148*9fac68fcSPAPANI SRIKANTH 
149*9fac68fcSPAPANI SRIKANTH 	int lockupcode = 0;
150*9fac68fcSPAPANI SRIKANTH 
151*9fac68fcSPAPANI SRIKANTH 	if (SIS_IS_KERNEL_PANIC(softs)) {
152*9fac68fcSPAPANI SRIKANTH                 lockupcode = PCI_MEM_GET32(softs, &softs->ioa_reg->mb[7], LEGACY_SIS_SRCV_OFFSET_MAILBOX_7);
153*9fac68fcSPAPANI SRIKANTH                 DBG_ERR("Controller FW is not runnning, Lockup code = %x\n", lockupcode);
154*9fac68fcSPAPANI SRIKANTH         }
155*9fac68fcSPAPANI SRIKANTH         else {
1561e66f787SSean Bruno                 pqisrc_trigger_nmi_sis(softs);
157*9fac68fcSPAPANI SRIKANTH         }
158*9fac68fcSPAPANI SRIKANTH 
1591e66f787SSean Bruno 	os_complete_outstanding_cmds_nodevice(softs);
160*9fac68fcSPAPANI SRIKANTH 	pqisrc_wait_for_rescan_complete(softs);
1611e66f787SSean Bruno 	pqisrc_take_devices_offline(softs);
1621e66f787SSean Bruno 
1631e66f787SSean Bruno 	DBG_FUNC("OUT\n");
1641e66f787SSean Bruno }
1651e66f787SSean Bruno 
1661e66f787SSean Bruno /*
1671e66f787SSean Bruno  * Timer handler for the adapter heart-beat.
1681e66f787SSean Bruno  */
169*9fac68fcSPAPANI SRIKANTH void
170*9fac68fcSPAPANI SRIKANTH pqisrc_heartbeat_timer_handler(pqisrc_softstate_t *softs)
1711e66f787SSean Bruno {
1721e66f787SSean Bruno 	uint8_t take_offline = false;
1731e66f787SSean Bruno 
1741e66f787SSean Bruno 	DBG_FUNC("IN\n");
1751e66f787SSean Bruno 
1761e66f787SSean Bruno 	if (CTRLR_HEARTBEAT_CNT(softs) == softs->prev_heartbeat_count) {
1771e66f787SSean Bruno 		take_offline = true;
1781e66f787SSean Bruno 		goto take_ctrl_offline;
1791e66f787SSean Bruno 	}
1801e66f787SSean Bruno 	softs->prev_heartbeat_count = CTRLR_HEARTBEAT_CNT(softs);
1811e66f787SSean Bruno 	DBG_INFO("CTRLR_HEARTBEAT_CNT(softs)  = %lx \
1821e66f787SSean Bruno 		softs->prev_heartbeat_count = %lx\n",
1831e66f787SSean Bruno 		CTRLR_HEARTBEAT_CNT(softs), softs->prev_heartbeat_count);
1841e66f787SSean Bruno 
1851e66f787SSean Bruno take_ctrl_offline:
1861e66f787SSean Bruno 	if (take_offline){
1871e66f787SSean Bruno 		DBG_ERR("controller is offline\n");
1881e66f787SSean Bruno 		pqisrc_take_ctrl_offline(softs);
1891e66f787SSean Bruno 		os_stop_heartbeat_timer(softs);
1901e66f787SSean Bruno 	}
1911e66f787SSean Bruno 	DBG_FUNC("OUT\n");
1921e66f787SSean Bruno }
1931e66f787SSean Bruno 
1941e66f787SSean Bruno /*
1951e66f787SSean Bruno  * Conditional variable management routine for internal commands.
1961e66f787SSean Bruno  */
197*9fac68fcSPAPANI SRIKANTH int
198*9fac68fcSPAPANI SRIKANTH pqisrc_wait_on_condition(pqisrc_softstate_t *softs, rcb_t *rcb,
199*9fac68fcSPAPANI SRIKANTH 				uint32_t timeout_in_msec)
200*9fac68fcSPAPANI SRIKANTH {
2011e66f787SSean Bruno 	DBG_FUNC("IN\n");
2021e66f787SSean Bruno 
2031e66f787SSean Bruno 	int ret = PQI_STATUS_SUCCESS;
204*9fac68fcSPAPANI SRIKANTH 
205*9fac68fcSPAPANI SRIKANTH 	/* 1 msec = 500 usec * 2 */
206*9fac68fcSPAPANI SRIKANTH 	uint32_t loop_cnt = timeout_in_msec * 2;
207*9fac68fcSPAPANI SRIKANTH 	uint32_t i = 0;
2081e66f787SSean Bruno 
2091e66f787SSean Bruno 	while (rcb->req_pending == true) {
2101e66f787SSean Bruno 		OS_SLEEP(500); /* Micro sec */
2111e66f787SSean Bruno 		/* Polling needed for FreeBSD : since ithread routine is not scheduled
212*9fac68fcSPAPANI SRIKANTH 		 * during bootup, we could use polling until interrupts are
213*9fac68fcSPAPANI SRIKANTH 		 * enabled (using 'if (cold)'to check for the boot time before
214*9fac68fcSPAPANI SRIKANTH 		 * interrupts are enabled). */
2151e66f787SSean Bruno 		IS_POLLING_REQUIRED(softs);
2161e66f787SSean Bruno 
217*9fac68fcSPAPANI SRIKANTH 		if ((timeout_in_msec != TIMEOUT_INFINITE) && (i++ == loop_cnt)) {
2181e66f787SSean Bruno 			DBG_ERR("ERR: Requested cmd timed out !!!\n");
2191e66f787SSean Bruno 			ret = PQI_STATUS_TIMEOUT;
220*9fac68fcSPAPANI SRIKANTH 			rcb->timedout = true;
2211e66f787SSean Bruno 			break;
2221e66f787SSean Bruno 		}
2231e66f787SSean Bruno 
2241e66f787SSean Bruno 		if (pqisrc_ctrl_offline(softs)) {
2251e66f787SSean Bruno 			DBG_ERR("Controller is Offline");
2261e66f787SSean Bruno 			ret = PQI_STATUS_FAILURE;
2271e66f787SSean Bruno 			break;
2281e66f787SSean Bruno 		}
229*9fac68fcSPAPANI SRIKANTH 
2301e66f787SSean Bruno 	}
2311e66f787SSean Bruno 	rcb->req_pending = true;
2321e66f787SSean Bruno 
2331e66f787SSean Bruno 	DBG_FUNC("OUT\n");
2341e66f787SSean Bruno 
2351e66f787SSean Bruno 	return ret;
2361e66f787SSean Bruno }
2371e66f787SSean Bruno 
2381e66f787SSean Bruno /* Function used to validate the device wwid. */
239*9fac68fcSPAPANI SRIKANTH boolean_t
240*9fac68fcSPAPANI SRIKANTH pqisrc_device_equal(pqi_scsi_dev_t *dev1,
2411e66f787SSean Bruno 	pqi_scsi_dev_t *dev2)
2421e66f787SSean Bruno {
2431e66f787SSean Bruno 	return dev1->wwid == dev2->wwid;
2441e66f787SSean Bruno }
2451e66f787SSean Bruno 
2461e66f787SSean Bruno /* Function used to validate the device scsi3addr. */
247*9fac68fcSPAPANI SRIKANTH boolean_t
248*9fac68fcSPAPANI SRIKANTH pqisrc_scsi3addr_equal(uint8_t *scsi3addr1, uint8_t *scsi3addr2)
2491e66f787SSean Bruno {
2501e66f787SSean Bruno 	return memcmp(scsi3addr1, scsi3addr2, 8) == 0;
2511e66f787SSean Bruno }
2521e66f787SSean Bruno 
2531e66f787SSean Bruno /* Function used to validate hba_lunid */
254*9fac68fcSPAPANI SRIKANTH boolean_t
255*9fac68fcSPAPANI SRIKANTH pqisrc_is_hba_lunid(uint8_t *scsi3addr)
2561e66f787SSean Bruno {
2571e66f787SSean Bruno 	return pqisrc_scsi3addr_equal(scsi3addr, (uint8_t*)RAID_CTLR_LUNID);
2581e66f787SSean Bruno }
2591e66f787SSean Bruno 
2601e66f787SSean Bruno /* Function used to validate type of device */
261*9fac68fcSPAPANI SRIKANTH boolean_t
262*9fac68fcSPAPANI SRIKANTH pqisrc_is_logical_device(pqi_scsi_dev_t *device)
2631e66f787SSean Bruno {
2641e66f787SSean Bruno 	return !device->is_physical_device;
2651e66f787SSean Bruno }
2661e66f787SSean Bruno 
2671e66f787SSean Bruno /* Function used to sanitize inquiry string */
268*9fac68fcSPAPANI SRIKANTH void
269*9fac68fcSPAPANI SRIKANTH pqisrc_sanitize_inquiry_string(unsigned char *s, int len)
2701e66f787SSean Bruno {
2711e66f787SSean Bruno 	boolean_t terminated = false;
2721e66f787SSean Bruno 
2731e66f787SSean Bruno 	DBG_FUNC("IN\n");
2741e66f787SSean Bruno 
2751e66f787SSean Bruno 	for (; len > 0; (--len, ++s)) {
2761e66f787SSean Bruno 		if (*s == 0)
2771e66f787SSean Bruno 			terminated = true;
2781e66f787SSean Bruno 		if (terminated || *s < 0x20 || *s > 0x7e)
2791e66f787SSean Bruno 			*s = ' ';
2801e66f787SSean Bruno 	}
2811e66f787SSean Bruno 
2821e66f787SSean Bruno 	DBG_FUNC("OUT\n");
2831e66f787SSean Bruno }
2841e66f787SSean Bruno 
2851e66f787SSean Bruno static char *raid_levels[] = {
2861e66f787SSean Bruno 	"RAID 0",
2871e66f787SSean Bruno 	"RAID 4",
2881e66f787SSean Bruno 	"RAID 1(1+0)",
2891e66f787SSean Bruno 	"RAID 5",
2901e66f787SSean Bruno 	"RAID 5+1",
2911e66f787SSean Bruno 	"RAID ADG",
2921e66f787SSean Bruno 	"RAID 1(ADM)",
2931e66f787SSean Bruno };
2941e66f787SSean Bruno 
2951e66f787SSean Bruno /* Get the RAID level from the index */
296*9fac68fcSPAPANI SRIKANTH char *
297*9fac68fcSPAPANI SRIKANTH pqisrc_raidlevel_to_string(uint8_t raid_level)
2981e66f787SSean Bruno {
2991e66f787SSean Bruno 	DBG_FUNC("IN\n");
3001e66f787SSean Bruno 	if (raid_level < ARRAY_SIZE(raid_levels))
3011e66f787SSean Bruno 		return raid_levels[raid_level];
3021e66f787SSean Bruno 	DBG_FUNC("OUT\n");
3031e66f787SSean Bruno 
3041e66f787SSean Bruno 	return " ";
3051e66f787SSean Bruno }
3061e66f787SSean Bruno 
3071e66f787SSean Bruno /* Debug routine for displaying device info */
308*9fac68fcSPAPANI SRIKANTH void
309*9fac68fcSPAPANI SRIKANTH pqisrc_display_device_info(pqisrc_softstate_t *softs,
3101e66f787SSean Bruno 	char *action, pqi_scsi_dev_t *device)
3111e66f787SSean Bruno {
3121e66f787SSean Bruno 	DBG_INFO( "%s scsi BTL %d:%d:%d:  %.8s %.16s %-12s SSDSmartPathCap%c En%c Exp%c qd=%d\n",
3131e66f787SSean Bruno 		action,
3141e66f787SSean Bruno 		device->bus,
3151e66f787SSean Bruno 		device->target,
3161e66f787SSean Bruno 		device->lun,
3171e66f787SSean Bruno 		device->vendor,
3181e66f787SSean Bruno 		device->model,
3191e66f787SSean Bruno 		pqisrc_raidlevel_to_string(device->raid_level),
3201e66f787SSean Bruno 		device->offload_config ? '+' : '-',
3211e66f787SSean Bruno 		device->offload_enabled_pending ? '+' : '-',
3221e66f787SSean Bruno 		device->expose_device ? '+' : '-',
3231e66f787SSean Bruno 		device->queue_depth);
3241e66f787SSean Bruno 	pqisrc_raidlevel_to_string(device->raid_level); /* To use this function */
3251e66f787SSean Bruno }
3261e66f787SSean Bruno 
3271e66f787SSean Bruno /* validate the structure sizes */
328*9fac68fcSPAPANI SRIKANTH void
329*9fac68fcSPAPANI SRIKANTH check_struct_sizes()
3301e66f787SSean Bruno {
3311e66f787SSean Bruno 
3321e66f787SSean Bruno     ASSERT(sizeof(SCSI3Addr_struct)== 2);
3331e66f787SSean Bruno     ASSERT(sizeof(PhysDevAddr_struct) == 8);
3341e66f787SSean Bruno     ASSERT(sizeof(LogDevAddr_struct)== 8);
3351e66f787SSean Bruno     ASSERT(sizeof(LUNAddr_struct)==8);
3361e66f787SSean Bruno     ASSERT(sizeof(RequestBlock_struct) == 20);
3371e66f787SSean Bruno     ASSERT(sizeof(MoreErrInfo_struct)== 8);
3381e66f787SSean Bruno     ASSERT(sizeof(ErrorInfo_struct)== 48);
339*9fac68fcSPAPANI SRIKANTH     /* Checking the size of IOCTL_Command_struct for both
340*9fac68fcSPAPANI SRIKANTH        64 bit and 32 bit system*/
341*9fac68fcSPAPANI SRIKANTH     ASSERT(sizeof(IOCTL_Command_struct)== 86 ||
342*9fac68fcSPAPANI SRIKANTH            sizeof(IOCTL_Command_struct)== 82);
3431e66f787SSean Bruno     ASSERT(sizeof(struct bmic_host_wellness_driver_version)== 42);
3441e66f787SSean Bruno     ASSERT(sizeof(struct bmic_host_wellness_time)== 20);
3451e66f787SSean Bruno     ASSERT(sizeof(struct pqi_dev_adminq_cap)== 8);
3461e66f787SSean Bruno     ASSERT(sizeof(struct admin_q_param)== 4);
3471e66f787SSean Bruno     ASSERT(sizeof(struct pqi_registers)== 256);
3481e66f787SSean Bruno     ASSERT(sizeof(struct ioa_registers)== 4128);
3491e66f787SSean Bruno     ASSERT(sizeof(struct pqi_pref_settings)==4);
3501e66f787SSean Bruno     ASSERT(sizeof(struct pqi_cap)== 20);
3511e66f787SSean Bruno     ASSERT(sizeof(iu_header_t)== 4);
3521e66f787SSean Bruno     ASSERT(sizeof(gen_adm_req_iu_t)== 64);
3531e66f787SSean Bruno     ASSERT(sizeof(gen_adm_resp_iu_t)== 64);
3541e66f787SSean Bruno     ASSERT(sizeof(op_q_params) == 9);
3551e66f787SSean Bruno     ASSERT(sizeof(raid_path_error_info_elem_t)== 276);
3561e66f787SSean Bruno     ASSERT(sizeof(aio_path_error_info_elem_t)== 276);
3571e66f787SSean Bruno     ASSERT(sizeof(struct init_base_struct)== 24);
3581e66f787SSean Bruno     ASSERT(sizeof(pqi_iu_layer_desc_t)== 16);
3591e66f787SSean Bruno     ASSERT(sizeof(pqi_dev_cap_t)== 576);
3601e66f787SSean Bruno     ASSERT(sizeof(pqi_aio_req_t)== 128);
3611e66f787SSean Bruno     ASSERT(sizeof(pqisrc_raid_req_t)== 128);
362*9fac68fcSPAPANI SRIKANTH     ASSERT(sizeof(pqi_raid_tmf_req_t)== 32);
363*9fac68fcSPAPANI SRIKANTH     ASSERT(sizeof(pqi_aio_tmf_req_t)== 32);
3641e66f787SSean Bruno     ASSERT(sizeof(struct pqi_io_response)== 16);
3651e66f787SSean Bruno     ASSERT(sizeof(struct sense_header_scsi)== 8);
3661e66f787SSean Bruno     ASSERT(sizeof(reportlun_header_t)==8);
3671e66f787SSean Bruno     ASSERT(sizeof(reportlun_ext_entry_t)== 24);
3681e66f787SSean Bruno     ASSERT(sizeof(reportlun_data_ext_t)== 32);
3691e66f787SSean Bruno     ASSERT(sizeof(raidmap_data_t)==8);
3701e66f787SSean Bruno     ASSERT(sizeof(pqisrc_raid_map_t)== 8256);
3711e66f787SSean Bruno     ASSERT(sizeof(bmic_ident_ctrl_t)== 325);
3721e66f787SSean Bruno     ASSERT(sizeof(bmic_ident_physdev_t)==2048);
3731e66f787SSean Bruno 
3741e66f787SSean Bruno }
375*9fac68fcSPAPANI SRIKANTH 
376*9fac68fcSPAPANI SRIKANTH uint32_t
377*9fac68fcSPAPANI SRIKANTH pqisrc_count_num_scsi_active_requests_on_dev(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device)
378*9fac68fcSPAPANI SRIKANTH {
379*9fac68fcSPAPANI SRIKANTH 	uint32_t i, active_io = 0;
380*9fac68fcSPAPANI SRIKANTH 	rcb_t* rcb;
381*9fac68fcSPAPANI SRIKANTH 
382*9fac68fcSPAPANI SRIKANTH 	for(i = 1; i <= softs->max_outstanding_io; i++) {
383*9fac68fcSPAPANI SRIKANTH 		rcb = &softs->rcb[i];
384*9fac68fcSPAPANI SRIKANTH 		if(rcb && IS_OS_SCSICMD(rcb) && (rcb->dvp == device) && rcb->req_pending) {
385*9fac68fcSPAPANI SRIKANTH 			active_io++;
386*9fac68fcSPAPANI SRIKANTH 		}
387*9fac68fcSPAPANI SRIKANTH 	}
388*9fac68fcSPAPANI SRIKANTH 	return active_io;
389*9fac68fcSPAPANI SRIKANTH }
390*9fac68fcSPAPANI SRIKANTH 
391*9fac68fcSPAPANI SRIKANTH void
392*9fac68fcSPAPANI SRIKANTH check_device_pending_commands_to_complete(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device)
393*9fac68fcSPAPANI SRIKANTH {
394*9fac68fcSPAPANI SRIKANTH 	uint32_t tag = softs->max_outstanding_io, active_requests;
395*9fac68fcSPAPANI SRIKANTH 	uint64_t timeout = 0, delay_in_usec = 1000; //In micro Seconds
396*9fac68fcSPAPANI SRIKANTH 	rcb_t* rcb;
397*9fac68fcSPAPANI SRIKANTH 
398*9fac68fcSPAPANI SRIKANTH 	DBG_FUNC("IN\n");
399*9fac68fcSPAPANI SRIKANTH 
400*9fac68fcSPAPANI SRIKANTH 	active_requests = pqisrc_count_num_scsi_active_requests_on_dev(softs, device);
401*9fac68fcSPAPANI SRIKANTH 
402*9fac68fcSPAPANI SRIKANTH 	DBG_WARN("Device Outstanding IO count = %u\n", active_requests);
403*9fac68fcSPAPANI SRIKANTH 
404*9fac68fcSPAPANI SRIKANTH 	if(!active_requests)
405*9fac68fcSPAPANI SRIKANTH 		return;
406*9fac68fcSPAPANI SRIKANTH 
407*9fac68fcSPAPANI SRIKANTH 	do {
408*9fac68fcSPAPANI SRIKANTH 		rcb = &softs->rcb[tag];
409*9fac68fcSPAPANI SRIKANTH 		if(rcb && IS_OS_SCSICMD(rcb) && (rcb->dvp == device) && rcb->req_pending) {
410*9fac68fcSPAPANI SRIKANTH 			OS_BUSYWAIT(delay_in_usec);
411*9fac68fcSPAPANI SRIKANTH 			timeout += delay_in_usec;
412*9fac68fcSPAPANI SRIKANTH 		}
413*9fac68fcSPAPANI SRIKANTH 		else
414*9fac68fcSPAPANI SRIKANTH 			tag--;
415*9fac68fcSPAPANI SRIKANTH 		if(timeout >= PQISRC_PENDING_IO_TIMEOUT_USEC) {
416*9fac68fcSPAPANI SRIKANTH 			DBG_WARN("timed out waiting for pending IO\n");
417*9fac68fcSPAPANI SRIKANTH 			return;
418*9fac68fcSPAPANI SRIKANTH 		}
419*9fac68fcSPAPANI SRIKANTH 	} while(tag);
420*9fac68fcSPAPANI SRIKANTH 
421*9fac68fcSPAPANI SRIKANTH }
422*9fac68fcSPAPANI SRIKANTH 
423*9fac68fcSPAPANI SRIKANTH inline uint64_t
424*9fac68fcSPAPANI SRIKANTH pqisrc_increment_device_active_io(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device)
425*9fac68fcSPAPANI SRIKANTH {
426*9fac68fcSPAPANI SRIKANTH #if PQISRC_DEVICE_IO_COUNTER
427*9fac68fcSPAPANI SRIKANTH 	/*Increment device active io count by one*/
428*9fac68fcSPAPANI SRIKANTH 	return OS_ATOMIC64_INC(&device->active_requests);
429*9fac68fcSPAPANI SRIKANTH #endif
430*9fac68fcSPAPANI SRIKANTH }
431*9fac68fcSPAPANI SRIKANTH 
432*9fac68fcSPAPANI SRIKANTH inline uint64_t
433*9fac68fcSPAPANI SRIKANTH pqisrc_decrement_device_active_io(pqisrc_softstate_t *softs,  pqi_scsi_dev_t *device)
434*9fac68fcSPAPANI SRIKANTH {
435*9fac68fcSPAPANI SRIKANTH #if PQISRC_DEVICE_IO_COUNTER
436*9fac68fcSPAPANI SRIKANTH 	/*Decrement device active io count by one*/
437*9fac68fcSPAPANI SRIKANTH 	return OS_ATOMIC64_DEC(&device->active_requests);
438*9fac68fcSPAPANI SRIKANTH #endif
439*9fac68fcSPAPANI SRIKANTH }
440*9fac68fcSPAPANI SRIKANTH 
441*9fac68fcSPAPANI SRIKANTH inline void
442*9fac68fcSPAPANI SRIKANTH pqisrc_init_device_active_io(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device)
443*9fac68fcSPAPANI SRIKANTH {
444*9fac68fcSPAPANI SRIKANTH #if PQISRC_DEVICE_IO_COUNTER
445*9fac68fcSPAPANI SRIKANTH 	/* Reset device count to Zero */
446*9fac68fcSPAPANI SRIKANTH 	OS_ATOMIC64_INIT(&device->active_requests, 0);
447*9fac68fcSPAPANI SRIKANTH #endif
448*9fac68fcSPAPANI SRIKANTH }
449*9fac68fcSPAPANI SRIKANTH 
450*9fac68fcSPAPANI SRIKANTH inline uint64_t
451*9fac68fcSPAPANI SRIKANTH pqisrc_read_device_active_io(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device)
452*9fac68fcSPAPANI SRIKANTH {
453*9fac68fcSPAPANI SRIKANTH #if PQISRC_DEVICE_IO_COUNTER
454*9fac68fcSPAPANI SRIKANTH 	/* read device active count*/
455*9fac68fcSPAPANI SRIKANTH 	return OS_ATOMIC64_READ(&device->active_requests);
456*9fac68fcSPAPANI SRIKANTH #endif
457*9fac68fcSPAPANI SRIKANTH }
458*9fac68fcSPAPANI SRIKANTH 
459*9fac68fcSPAPANI SRIKANTH void
460*9fac68fcSPAPANI SRIKANTH pqisrc_wait_for_device_commands_to_complete(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device)
461*9fac68fcSPAPANI SRIKANTH {
462*9fac68fcSPAPANI SRIKANTH 	uint64_t timeout_in_usec = 0, delay_in_usec = 1000; //In microseconds
463*9fac68fcSPAPANI SRIKANTH 
464*9fac68fcSPAPANI SRIKANTH 	DBG_FUNC("IN\n");
465*9fac68fcSPAPANI SRIKANTH 
466*9fac68fcSPAPANI SRIKANTH 	if(!softs->ctrl_online)
467*9fac68fcSPAPANI SRIKANTH 		return;
468*9fac68fcSPAPANI SRIKANTH 
469*9fac68fcSPAPANI SRIKANTH #if PQISRC_DEVICE_IO_COUNTER
470*9fac68fcSPAPANI SRIKANTH 	DBG_NOTE("Device Outstanding IO count = %ld\n", pqisrc_read_device_active_io(softs, device));
471*9fac68fcSPAPANI SRIKANTH 
472*9fac68fcSPAPANI SRIKANTH 	while(pqisrc_read_device_active_io(softs, device)) {
473*9fac68fcSPAPANI SRIKANTH 		OS_BUSYWAIT(delay_in_usec); // In microseconds
474*9fac68fcSPAPANI SRIKANTH 		if(!softs->ctrl_online) {
475*9fac68fcSPAPANI SRIKANTH 			DBG_WARN("Controller Offline was detected.\n");
476*9fac68fcSPAPANI SRIKANTH 		}
477*9fac68fcSPAPANI SRIKANTH 		timeout_in_usec += delay_in_usec;
478*9fac68fcSPAPANI SRIKANTH 		if(timeout_in_usec >= PQISRC_PENDING_IO_TIMEOUT_USEC) {
479*9fac68fcSPAPANI SRIKANTH 			DBG_WARN("timed out waiting for pending IO. DeviceOutStandingIo's=%ld\n",
480*9fac68fcSPAPANI SRIKANTH                                  pqisrc_read_device_active_io(softs, device));
481*9fac68fcSPAPANI SRIKANTH 			return;
482*9fac68fcSPAPANI SRIKANTH 		}
483*9fac68fcSPAPANI SRIKANTH 	}
484*9fac68fcSPAPANI SRIKANTH #else
485*9fac68fcSPAPANI SRIKANTH 	check_device_pending_commands_to_complete(softs, device);
486*9fac68fcSPAPANI SRIKANTH #endif
487*9fac68fcSPAPANI SRIKANTH }
488