1/*-
2 * Copyright 2016-2023 Microchip Technology, Inc. and/or its subsidiaries.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 */
25
26
27#include "smartpqi_includes.h"
28
29/*
30 * Checks a firmware feature status, given bit position.
31 */
32static inline boolean_t
33pqi_is_firmware_feature_supported(
34	struct pqi_config_table_firmware_features *firmware_features,
35	unsigned int bit_position)
36{
37	unsigned int byte_index;
38
39	byte_index = bit_position / BITS_PER_BYTE;
40
41	if (byte_index >= firmware_features->num_elements) {
42		DBG_ERR_NO_SOFTS("Invalid byte index for bit position %u\n",
43			bit_position);
44		return false;
45	}
46
47	return (firmware_features->features_supported[byte_index] &
48		(1 << (bit_position % BITS_PER_BYTE))) ? true : false;
49}
50
51/*
52 * Counts down into the enabled section of firmware
53 * features and reports current enabled status, given
54 * bit position.
55 */
56static inline boolean_t
57pqi_is_firmware_feature_enabled(
58	struct pqi_config_table_firmware_features *firmware_features,
59	uint8_t *firmware_features_iomem_addr,
60	unsigned int bit_position)
61{
62	unsigned int byte_index;
63	uint8_t *features_enabled_iomem_addr;
64
65	byte_index = (bit_position / BITS_PER_BYTE) +
66		(firmware_features->num_elements * 2);
67
68	features_enabled_iomem_addr = firmware_features_iomem_addr +
69		offsetof(struct pqi_config_table_firmware_features,
70			features_supported) + byte_index;
71
72	return (*features_enabled_iomem_addr &
73		(1 << (bit_position % BITS_PER_BYTE))) ? true : false;
74}
75
76/*
77 * Sets the given bit position for the driver to request the indicated
78 * firmware feature be enabled.
79 */
80static inline void
81pqi_request_firmware_feature(
82	struct pqi_config_table_firmware_features *firmware_features,
83	unsigned int bit_position)
84{
85	unsigned int byte_index;
86
87	/* byte_index adjusted to index into requested start bits */
88	byte_index = (bit_position / BITS_PER_BYTE) +
89		firmware_features->num_elements;
90
91	/* setting requested bits of local firmware_features */
92	firmware_features->features_supported[byte_index] |=
93		(1 << (bit_position % BITS_PER_BYTE));
94}
95
96/*
97 * Creates and sends the request for firmware to update the config
98 * table.
99 */
100static int
101pqi_config_table_update(pqisrc_softstate_t *softs,
102	uint16_t first_section, uint16_t last_section)
103{
104	struct pqi_vendor_general_request request;
105	int ret;
106
107	memset(&request, 0, sizeof(request));
108
109	request.header.iu_type = PQI_REQUEST_IU_VENDOR_GENERAL;
110	request.header.iu_length = sizeof(request) - PQI_REQUEST_HEADER_LENGTH;
111	request.function_code = PQI_VENDOR_GENERAL_CONFIG_TABLE_UPDATE;
112	request.data.config_table_update.first_section = first_section;
113	request.data.config_table_update.last_section = last_section;
114
115	ret = pqisrc_build_send_vendor_request(softs, &request);
116
117	if (ret != PQI_STATUS_SUCCESS) {
118		DBG_ERR("Failed to submit vendor general request IU, Ret status: %d\n", ret);
119	}
120
121	return ret;
122}
123
124/*
125 * Copies requested features bits into firmware config table,
126 * checks for support, and returns status of updating the config table.
127 */
128static int
129pqi_enable_firmware_features(pqisrc_softstate_t *softs,
130	struct pqi_config_table_firmware_features *firmware_features,
131	uint8_t *firmware_features_abs_addr)
132{
133	uint8_t *features_requested;
134	uint8_t *features_requested_abs_addr;
135	uint16_t *host_max_known_feature_iomem_addr;
136	uint16_t pqi_max_feature = PQI_FIRMWARE_FEATURE_MAXIMUM;
137
138	features_requested = firmware_features->features_supported +
139		firmware_features->num_elements;
140
141	features_requested_abs_addr = firmware_features_abs_addr +
142		(features_requested - (uint8_t*)firmware_features);
143	/*
144	 * NOTE: This memcpy is writing to a BAR-mapped address
145	 * which may not be safe for all OSes without proper API
146	 */
147	memcpy(features_requested_abs_addr, features_requested,
148		firmware_features->num_elements);
149
150	if (pqi_is_firmware_feature_supported(firmware_features,
151		PQI_FIRMWARE_FEATURE_MAX_KNOWN_FEATURE)) {
152		host_max_known_feature_iomem_addr =
153			(uint16_t*)(features_requested_abs_addr +
154			(firmware_features->num_elements * 2) + sizeof(uint16_t));
155			/*
156			 * NOTE: This writes to a BAR-mapped address
157			 * which may not be safe for all OSes without proper API
158			 */
159			*host_max_known_feature_iomem_addr = pqi_max_feature;
160	}
161
162	return pqi_config_table_update(softs,
163		PQI_CONF_TABLE_SECTION_FIRMWARE_FEATURES,
164		PQI_CONF_TABLE_SECTION_FIRMWARE_FEATURES);
165}
166
167typedef struct pqi_firmware_feature pqi_firmware_feature_t;
168typedef void (*feature_status_fn)(pqisrc_softstate_t *softs,
169	pqi_firmware_feature_t *firmware_feature);
170
171struct pqi_firmware_feature {
172	char		*feature_name;
173	unsigned int	feature_bit;
174	boolean_t		supported;
175	boolean_t		enabled;
176	feature_status_fn	feature_status;
177};
178
179static void
180pqi_firmware_feature_status(pqisrc_softstate_t *softs,
181	struct pqi_firmware_feature *firmware_feature)
182{
183	if (!firmware_feature->supported) {
184		DBG_NOTE("%s not supported by controller\n",
185			firmware_feature->feature_name);
186		return;
187	}
188
189	if (firmware_feature->enabled) {
190		DBG_NOTE("%s enabled\n", firmware_feature->feature_name);
191		return;
192	}
193
194	DBG_NOTE("failed to enable %s\n", firmware_feature->feature_name);
195}
196
197static void
198pqi_ctrl_update_feature_flags(pqisrc_softstate_t *softs,
199	struct pqi_firmware_feature *firmware_feature)
200{
201	switch (firmware_feature->feature_bit) {
202	case PQI_FIRMWARE_FEATURE_RAID_1_WRITE_BYPASS:
203		softs->aio_raid1_write_bypass = firmware_feature->enabled;
204		break;
205	case PQI_FIRMWARE_FEATURE_RAID_5_WRITE_BYPASS:
206		softs->aio_raid5_write_bypass = firmware_feature->enabled;
207		break;
208	case PQI_FIRMWARE_FEATURE_RAID_6_WRITE_BYPASS:
209		softs->aio_raid6_write_bypass = firmware_feature->enabled;
210		break;
211	case PQI_FIRMWARE_FEATURE_RAID_IU_TIMEOUT:
212		softs->timeout_in_passthrough = true;
213		break;
214	case PQI_FIRMWARE_FEATURE_TMF_IU_TIMEOUT:
215		softs->timeout_in_tmf = true;
216		break;
217	case PQI_FIRMWARE_FEATURE_UNIQUE_SATA_WWN:
218		break;
219	case PQI_FIRMWARE_FEATURE_PAGE83_IDENTIFIER_FOR_RPL_WWID:
220		softs->page83id_in_rpl = true;
221		break;
222	default:
223		DBG_NOTE("Nothing to do\n");
224		return;
225		break;
226	}
227	/* for any valid feature, also go update the feature status. */
228	pqi_firmware_feature_status(softs, firmware_feature);
229}
230
231
232static inline void
233pqi_firmware_feature_update(pqisrc_softstate_t *softs,
234	struct pqi_firmware_feature *firmware_feature)
235{
236	if (firmware_feature->feature_status)
237		firmware_feature->feature_status(softs, firmware_feature);
238}
239
240/* Defines PQI features that driver wishes to support */
241static struct pqi_firmware_feature pqi_firmware_features[] = {
242#if 0
243	{
244		.feature_name = "Online Firmware Activation",
245		.feature_bit = PQI_FIRMWARE_FEATURE_OFA,
246		.feature_status = pqi_firmware_feature_status,
247	},
248	{
249		.feature_name = "Serial Management Protocol",
250		.feature_bit = PQI_FIRMWARE_FEATURE_SMP,
251		.feature_status = pqi_firmware_feature_status,
252	},
253#endif
254	{
255		.feature_name = "SATA WWN Unique ID",
256		.feature_bit = PQI_FIRMWARE_FEATURE_UNIQUE_SATA_WWN,
257		.feature_status = pqi_ctrl_update_feature_flags,
258	},
259	{
260		.feature_name = "RAID IU Timeout",
261		.feature_bit = PQI_FIRMWARE_FEATURE_RAID_IU_TIMEOUT,
262		.feature_status = pqi_ctrl_update_feature_flags,
263	},
264	{
265		.feature_name = "TMF IU Timeout",
266		.feature_bit = PQI_FIRMWARE_FEATURE_TMF_IU_TIMEOUT,
267		.feature_status = pqi_ctrl_update_feature_flags,
268	},
269	{
270		.feature_name = "Support for RPL WWID filled by Page83 identifier",
271		.feature_bit = PQI_FIRMWARE_FEATURE_PAGE83_IDENTIFIER_FOR_RPL_WWID,
272		.feature_status = pqi_ctrl_update_feature_flags,
273	},
274	/* Features independent of Maximum Known Feature should be added
275	before Maximum Known Feature*/
276	{
277		.feature_name = "Maximum Known Feature",
278		.feature_bit = PQI_FIRMWARE_FEATURE_MAX_KNOWN_FEATURE,
279		.feature_status = pqi_firmware_feature_status,
280	},
281	{
282		.feature_name = "RAID 0 Read Bypass",
283		.feature_bit = PQI_FIRMWARE_FEATURE_RAID_0_READ_BYPASS,
284		.feature_status = pqi_firmware_feature_status,
285	},
286	{
287		.feature_name = "RAID 1 Read Bypass",
288		.feature_bit = PQI_FIRMWARE_FEATURE_RAID_1_READ_BYPASS,
289		.feature_status = pqi_firmware_feature_status,
290	},
291	{
292		.feature_name = "RAID 5 Read Bypass",
293		.feature_bit = PQI_FIRMWARE_FEATURE_RAID_5_READ_BYPASS,
294		.feature_status = pqi_firmware_feature_status,
295	},
296	{
297		.feature_name = "RAID 6 Read Bypass",
298		.feature_bit = PQI_FIRMWARE_FEATURE_RAID_6_READ_BYPASS,
299		.feature_status = pqi_firmware_feature_status,
300	},
301	{
302		.feature_name = "RAID 0 Write Bypass",
303		.feature_bit = PQI_FIRMWARE_FEATURE_RAID_0_WRITE_BYPASS,
304		.feature_status = pqi_firmware_feature_status,
305	},
306	{
307		.feature_name = "RAID 1 Write Bypass",
308		.feature_bit = PQI_FIRMWARE_FEATURE_RAID_1_WRITE_BYPASS,
309		.feature_status = pqi_ctrl_update_feature_flags,
310	},
311	{
312		.feature_name = "RAID 5 Write Bypass",
313		.feature_bit = PQI_FIRMWARE_FEATURE_RAID_5_WRITE_BYPASS,
314		.feature_status = pqi_ctrl_update_feature_flags,
315	},
316	{
317		.feature_name = "RAID 6 Write Bypass",
318		.feature_bit = PQI_FIRMWARE_FEATURE_RAID_6_WRITE_BYPASS,
319		.feature_status = pqi_ctrl_update_feature_flags,
320	},
321#if 0
322	{
323		.feature_name = "New Soft Reset Handshake",
324		.feature_bit = PQI_FIRMWARE_FEATURE_SOFT_RESET_HANDSHAKE,
325		.feature_status = pqi_ctrl_update_feature_flags,
326	},
327#endif
328
329};
330
331static void
332pqi_process_firmware_features(pqisrc_softstate_t *softs,
333	void *features, void *firmware_features_abs_addr)
334{
335	int rc;
336	struct pqi_config_table_firmware_features *firmware_features = features;
337	unsigned int i;
338	unsigned int num_features_supported;
339
340	/* Iterates through local PQI feature support list to
341	see if the controller also supports the feature */
342	for (i = 0, num_features_supported = 0;
343		i < ARRAY_SIZE(pqi_firmware_features); i++) {
344		/*Check if SATA_WWN_FOR_DEV_UNIQUE_ID feature enabled by setting module
345		parameter if not avoid checking for the feature*/
346		if ((pqi_firmware_features[i].feature_bit ==
347			PQI_FIRMWARE_FEATURE_UNIQUE_SATA_WWN) &&
348			(!softs->sata_unique_wwn)) {
349			continue;
350		}
351		if (pqi_is_firmware_feature_supported(firmware_features,
352			pqi_firmware_features[i].feature_bit)) {
353			pqi_firmware_features[i].supported = true;
354			num_features_supported++;
355		} else {
356			DBG_WARN("Feature %s is not supported by firmware\n",
357			pqi_firmware_features[i].feature_name);
358			pqi_firmware_feature_update(softs,
359				&pqi_firmware_features[i]);
360
361			/* if max known feature bit isn't supported,
362 			 * then no other feature bits are supported.
363 			 */
364			if (pqi_firmware_features[i].feature_bit ==
365				PQI_FIRMWARE_FEATURE_MAX_KNOWN_FEATURE)
366				break;
367		}
368	}
369
370	DBG_INFO("Num joint features supported : %u \n", num_features_supported);
371
372	if (num_features_supported == 0)
373		return;
374
375	/* request driver features that are also on firmware-supported list */
376	for (i = 0; i < ARRAY_SIZE(pqi_firmware_features); i++) {
377		if (!pqi_firmware_features[i].supported)
378			continue;
379#ifdef DEVICE_HINT
380		if (check_device_hint_status(softs, pqi_firmware_features[i].feature_bit))
381			continue;
382#endif
383		pqi_request_firmware_feature(firmware_features,
384			pqi_firmware_features[i].feature_bit);
385	}
386
387	/* enable the features that were successfully requested. */
388	rc = pqi_enable_firmware_features(softs, firmware_features,
389		firmware_features_abs_addr);
390	if (rc) {
391		DBG_ERR("failed to enable firmware features in PQI configuration table\n");
392		for (i = 0; i < ARRAY_SIZE(pqi_firmware_features); i++) {
393			if (!pqi_firmware_features[i].supported)
394				continue;
395			pqi_firmware_feature_update(softs,
396				&pqi_firmware_features[i]);
397		}
398		return;
399	}
400
401	/* report the features that were successfully enabled. */
402	for (i = 0; i < ARRAY_SIZE(pqi_firmware_features); i++) {
403		if (!pqi_firmware_features[i].supported)
404			continue;
405		if (pqi_is_firmware_feature_enabled(firmware_features,
406			firmware_features_abs_addr,
407			pqi_firmware_features[i].feature_bit)) {
408				pqi_firmware_features[i].enabled = true;
409		} else {
410			DBG_WARN("Feature %s could not be enabled.\n",
411				pqi_firmware_features[i].feature_name);
412		}
413		pqi_firmware_feature_update(softs,
414			&pqi_firmware_features[i]);
415	}
416}
417
418static void
419pqi_init_firmware_features(void)
420{
421	unsigned int i;
422
423	for (i = 0; i < ARRAY_SIZE(pqi_firmware_features); i++) {
424		pqi_firmware_features[i].supported = false;
425		pqi_firmware_features[i].enabled = false;
426	}
427}
428
429static void
430pqi_process_firmware_features_section(pqisrc_softstate_t *softs,
431	void *features, void *firmware_features_abs_addr)
432{
433	pqi_init_firmware_features();
434	pqi_process_firmware_features(softs, features, firmware_features_abs_addr);
435}
436
437
438/*
439 * Get the PQI configuration table parameters.
440 * Currently using for heart-beat counter scratch-pad register.
441 */
442int
443pqisrc_process_config_table(pqisrc_softstate_t *softs)
444{
445	int ret = PQI_STATUS_FAILURE;
446	uint32_t config_table_size;
447	uint32_t section_off;
448	uint8_t *config_table_abs_addr;
449	struct pqi_conf_table *conf_table;
450	struct pqi_conf_table_section_header *section_hdr;
451
452	config_table_size = softs->pqi_cap.conf_tab_sz;
453
454	if (config_table_size < sizeof(*conf_table) ||
455		config_table_size > PQI_CONF_TABLE_MAX_LEN) {
456		DBG_ERR("Invalid PQI conf table length of %u\n",
457			config_table_size);
458		return ret;
459	}
460
461	conf_table = os_mem_alloc(softs, config_table_size);
462	if (!conf_table) {
463		DBG_ERR("Failed to allocate memory for PQI conf table\n");
464		return ret;
465	}
466
467	config_table_abs_addr = (uint8_t *)(softs->pci_mem_base_vaddr +
468					softs->pqi_cap.conf_tab_off);
469
470	PCI_MEM_GET_BUF(softs, config_table_abs_addr,
471			softs->pqi_cap.conf_tab_off,
472			(uint8_t*)conf_table, config_table_size);
473
474	if (memcmp(conf_table->sign, PQI_CONF_TABLE_SIGNATURE,
475			sizeof(conf_table->sign)) != 0) {
476		DBG_ERR("Invalid PQI config signature\n");
477		goto out;
478	}
479
480	section_off = LE_32(conf_table->first_section_off);
481
482	while (section_off) {
483
484		if (section_off+ sizeof(*section_hdr) >= config_table_size) {
485			DBG_INFO("Reached end of PQI config table. Breaking off.\n");
486			break;
487		}
488
489		section_hdr = (struct pqi_conf_table_section_header *)((uint8_t *)conf_table + section_off);
490
491		switch (LE_16(section_hdr->section_id)) {
492		case PQI_CONF_TABLE_SECTION_GENERAL_INFO:
493			break;
494		case PQI_CONF_TABLE_SECTION_FIRMWARE_FEATURES:
495			pqi_process_firmware_features_section(softs, section_hdr, (config_table_abs_addr + section_off));
496			break;
497		case PQI_CONF_TABLE_SECTION_FIRMWARE_ERRATA:
498		case PQI_CONF_TABLE_SECTION_DEBUG:
499			break;
500		case PQI_CONF_TABLE_SECTION_HEARTBEAT:
501			softs->heartbeat_counter_off = softs->pqi_cap.conf_tab_off +
502				section_off +
503				offsetof(struct pqi_conf_table_heartbeat, heartbeat_counter);
504			softs->heartbeat_counter_abs_addr = (uint64_t *)(softs->pci_mem_base_vaddr +
505				softs->heartbeat_counter_off);
506			ret = PQI_STATUS_SUCCESS;
507			break;
508		case PQI_CONF_TABLE_SOFT_RESET:
509			break;
510		default:
511			DBG_NOTE("unrecognized PQI config table section ID: 0x%x\n",
512				LE_16(section_hdr->section_id));
513			break;
514		}
515		section_off = LE_16(section_hdr->next_section_off);
516	}
517out:
518	os_mem_free(softs, (void *)conf_table,config_table_size);
519	return ret;
520}
521