Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    3)  * QLogic Fibre Channel HBA Driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    4)  * Copyright (c)  2003-2014 QLogic Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    5)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    6) #include "qla_def.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    7) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    8) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    9) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   10) #include <linux/vmalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   11) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   12) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   13) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   14)  * NVRAM support routines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   15)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   16) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   17) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   18)  * qla2x00_lock_nvram_access() -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   19)  * @ha: HA context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   20)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   21) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   22) qla2x00_lock_nvram_access(struct qla_hw_data *ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   23) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   24) 	uint16_t data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   25) 	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   26) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   27) 	if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA2300(ha)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   28) 		data = rd_reg_word(&reg->nvram);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   29) 		while (data & NVR_BUSY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   30) 			udelay(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   31) 			data = rd_reg_word(&reg->nvram);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   32) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   33) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   34) 		/* Lock resource */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   35) 		wrt_reg_word(&reg->u.isp2300.host_semaphore, 0x1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   36) 		rd_reg_word(&reg->u.isp2300.host_semaphore);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   37) 		udelay(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   38) 		data = rd_reg_word(&reg->u.isp2300.host_semaphore);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   39) 		while ((data & BIT_0) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   40) 			/* Lock failed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   41) 			udelay(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   42) 			wrt_reg_word(&reg->u.isp2300.host_semaphore, 0x1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   43) 			rd_reg_word(&reg->u.isp2300.host_semaphore);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   44) 			udelay(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   45) 			data = rd_reg_word(&reg->u.isp2300.host_semaphore);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   46) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   47) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   48) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   50) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   51)  * qla2x00_unlock_nvram_access() -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   52)  * @ha: HA context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   53)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   54) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   55) qla2x00_unlock_nvram_access(struct qla_hw_data *ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   56) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   57) 	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   58) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   59) 	if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA2300(ha)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   60) 		wrt_reg_word(&reg->u.isp2300.host_semaphore, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   61) 		rd_reg_word(&reg->u.isp2300.host_semaphore);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   62) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   64) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   65) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   66)  * qla2x00_nv_write() - Prepare for NVRAM read/write operation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   67)  * @ha: HA context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   68)  * @data: Serial interface selector
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   69)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   70) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   71) qla2x00_nv_write(struct qla_hw_data *ha, uint16_t data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   72) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   73) 	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   74) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   75) 	wrt_reg_word(&reg->nvram, data | NVR_SELECT | NVR_WRT_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   76) 	rd_reg_word(&reg->nvram);		/* PCI Posting. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   77) 	NVRAM_DELAY();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   78) 	wrt_reg_word(&reg->nvram, data | NVR_SELECT | NVR_CLOCK |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   79) 	    NVR_WRT_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   80) 	rd_reg_word(&reg->nvram);		/* PCI Posting. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   81) 	NVRAM_DELAY();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   82) 	wrt_reg_word(&reg->nvram, data | NVR_SELECT | NVR_WRT_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   83) 	rd_reg_word(&reg->nvram);		/* PCI Posting. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   84) 	NVRAM_DELAY();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   86) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   87) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   88)  * qla2x00_nvram_request() - Sends read command to NVRAM and gets data from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   89)  *	NVRAM.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   90)  * @ha: HA context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   91)  * @nv_cmd: NVRAM command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   92)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   93)  * Bit definitions for NVRAM command:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   94)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   95)  *	Bit 26     = start bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   96)  *	Bit 25, 24 = opcode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   97)  *	Bit 23-16  = address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   98)  *	Bit 15-0   = write data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   99)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  100)  * Returns the word read from nvram @addr.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  101)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  102) static uint16_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  103) qla2x00_nvram_request(struct qla_hw_data *ha, uint32_t nv_cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  105) 	uint8_t		cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  106) 	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  107) 	uint16_t	data = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  108) 	uint16_t	reg_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  110) 	/* Send command to NVRAM. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  111) 	nv_cmd <<= 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  112) 	for (cnt = 0; cnt < 11; cnt++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  113) 		if (nv_cmd & BIT_31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  114) 			qla2x00_nv_write(ha, NVR_DATA_OUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  115) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  116) 			qla2x00_nv_write(ha, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  117) 		nv_cmd <<= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  118) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  119) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  120) 	/* Read data from NVRAM. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  121) 	for (cnt = 0; cnt < 16; cnt++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  122) 		wrt_reg_word(&reg->nvram, NVR_SELECT | NVR_CLOCK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  123) 		rd_reg_word(&reg->nvram);	/* PCI Posting. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  124) 		NVRAM_DELAY();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  125) 		data <<= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  126) 		reg_data = rd_reg_word(&reg->nvram);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  127) 		if (reg_data & NVR_DATA_IN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  128) 			data |= BIT_0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  129) 		wrt_reg_word(&reg->nvram, NVR_SELECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  130) 		rd_reg_word(&reg->nvram);	/* PCI Posting. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  131) 		NVRAM_DELAY();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  132) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  133) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  134) 	/* Deselect chip. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  135) 	wrt_reg_word(&reg->nvram, NVR_DESELECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  136) 	rd_reg_word(&reg->nvram);		/* PCI Posting. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  137) 	NVRAM_DELAY();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  139) 	return data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  142) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  143) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  144)  * qla2x00_get_nvram_word() - Calculates word position in NVRAM and calls the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  145)  *	request routine to get the word from NVRAM.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  146)  * @ha: HA context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  147)  * @addr: Address in NVRAM to read
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  148)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  149)  * Returns the word read from nvram @addr.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  150)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  151) static uint16_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  152) qla2x00_get_nvram_word(struct qla_hw_data *ha, uint32_t addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  153) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  154) 	uint16_t	data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  155) 	uint32_t	nv_cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  157) 	nv_cmd = addr << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  158) 	nv_cmd |= NV_READ_OP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  159) 	data = qla2x00_nvram_request(ha, nv_cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  160) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  161) 	return (data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  163) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  164) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  165)  * qla2x00_nv_deselect() - Deselect NVRAM operations.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  166)  * @ha: HA context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  167)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  168) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  169) qla2x00_nv_deselect(struct qla_hw_data *ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  170) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  171) 	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  173) 	wrt_reg_word(&reg->nvram, NVR_DESELECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  174) 	rd_reg_word(&reg->nvram);		/* PCI Posting. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  175) 	NVRAM_DELAY();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  177) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  178) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  179)  * qla2x00_write_nvram_word() - Write NVRAM data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  180)  * @ha: HA context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  181)  * @addr: Address in NVRAM to write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  182)  * @data: word to program
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  183)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  184) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  185) qla2x00_write_nvram_word(struct qla_hw_data *ha, uint32_t addr, __le16 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  186) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  187) 	int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  188) 	uint16_t word;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  189) 	uint32_t nv_cmd, wait_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  190) 	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  191) 	scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  192) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  193) 	qla2x00_nv_write(ha, NVR_DATA_OUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  194) 	qla2x00_nv_write(ha, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  195) 	qla2x00_nv_write(ha, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  197) 	for (word = 0; word < 8; word++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  198) 		qla2x00_nv_write(ha, NVR_DATA_OUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  199) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  200) 	qla2x00_nv_deselect(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  201) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  202) 	/* Write data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  203) 	nv_cmd = (addr << 16) | NV_WRITE_OP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  204) 	nv_cmd |= (__force u16)data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  205) 	nv_cmd <<= 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  206) 	for (count = 0; count < 27; count++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  207) 		if (nv_cmd & BIT_31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  208) 			qla2x00_nv_write(ha, NVR_DATA_OUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  209) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  210) 			qla2x00_nv_write(ha, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  211) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  212) 		nv_cmd <<= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  213) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  214) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  215) 	qla2x00_nv_deselect(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  216) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  217) 	/* Wait for NVRAM to become ready */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  218) 	wrt_reg_word(&reg->nvram, NVR_SELECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  219) 	rd_reg_word(&reg->nvram);		/* PCI Posting. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  220) 	wait_cnt = NVR_WAIT_CNT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  221) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  222) 		if (!--wait_cnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  223) 			ql_dbg(ql_dbg_user, vha, 0x708d,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  224) 			    "NVRAM didn't go ready...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  225) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  226) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  227) 		NVRAM_DELAY();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  228) 		word = rd_reg_word(&reg->nvram);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  229) 	} while ((word & NVR_DATA_IN) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  230) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  231) 	qla2x00_nv_deselect(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  232) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  233) 	/* Disable writes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  234) 	qla2x00_nv_write(ha, NVR_DATA_OUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  235) 	for (count = 0; count < 10; count++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  236) 		qla2x00_nv_write(ha, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  237) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  238) 	qla2x00_nv_deselect(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  240) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  241) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  242) qla2x00_write_nvram_word_tmo(struct qla_hw_data *ha, uint32_t addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  243) 			     __le16 data, uint32_t tmo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  244) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  245) 	int ret, count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  246) 	uint16_t word;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  247) 	uint32_t nv_cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  248) 	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  250) 	ret = QLA_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  251) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  252) 	qla2x00_nv_write(ha, NVR_DATA_OUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  253) 	qla2x00_nv_write(ha, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  254) 	qla2x00_nv_write(ha, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  255) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  256) 	for (word = 0; word < 8; word++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  257) 		qla2x00_nv_write(ha, NVR_DATA_OUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  258) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  259) 	qla2x00_nv_deselect(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  260) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  261) 	/* Write data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  262) 	nv_cmd = (addr << 16) | NV_WRITE_OP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  263) 	nv_cmd |= (__force u16)data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  264) 	nv_cmd <<= 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  265) 	for (count = 0; count < 27; count++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  266) 		if (nv_cmd & BIT_31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  267) 			qla2x00_nv_write(ha, NVR_DATA_OUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  268) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  269) 			qla2x00_nv_write(ha, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  270) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  271) 		nv_cmd <<= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  272) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  273) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  274) 	qla2x00_nv_deselect(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  275) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  276) 	/* Wait for NVRAM to become ready */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  277) 	wrt_reg_word(&reg->nvram, NVR_SELECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  278) 	rd_reg_word(&reg->nvram);		/* PCI Posting. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  279) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  280) 		NVRAM_DELAY();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  281) 		word = rd_reg_word(&reg->nvram);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  282) 		if (!--tmo) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  283) 			ret = QLA_FUNCTION_FAILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  284) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  285) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  286) 	} while ((word & NVR_DATA_IN) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  287) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  288) 	qla2x00_nv_deselect(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  289) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  290) 	/* Disable writes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  291) 	qla2x00_nv_write(ha, NVR_DATA_OUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  292) 	for (count = 0; count < 10; count++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  293) 		qla2x00_nv_write(ha, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  294) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  295) 	qla2x00_nv_deselect(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  296) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  297) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  299) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  300) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  301)  * qla2x00_clear_nvram_protection() -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  302)  * @ha: HA context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  303)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  304) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  305) qla2x00_clear_nvram_protection(struct qla_hw_data *ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  306) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  307) 	int ret, stat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  308) 	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  309) 	uint32_t word, wait_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  310) 	__le16 wprot, wprot_old;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  311) 	scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  312) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  313) 	/* Clear NVRAM write protection. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  314) 	ret = QLA_FUNCTION_FAILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  315) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  316) 	wprot_old = cpu_to_le16(qla2x00_get_nvram_word(ha, ha->nvram_base));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  317) 	stat = qla2x00_write_nvram_word_tmo(ha, ha->nvram_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  318) 					    cpu_to_le16(0x1234), 100000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  319) 	wprot = cpu_to_le16(qla2x00_get_nvram_word(ha, ha->nvram_base));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  320) 	if (stat != QLA_SUCCESS || wprot != cpu_to_le16(0x1234)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  321) 		/* Write enable. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  322) 		qla2x00_nv_write(ha, NVR_DATA_OUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  323) 		qla2x00_nv_write(ha, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  324) 		qla2x00_nv_write(ha, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  325) 		for (word = 0; word < 8; word++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  326) 			qla2x00_nv_write(ha, NVR_DATA_OUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  327) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  328) 		qla2x00_nv_deselect(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  329) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  330) 		/* Enable protection register. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  331) 		qla2x00_nv_write(ha, NVR_PR_ENABLE | NVR_DATA_OUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  332) 		qla2x00_nv_write(ha, NVR_PR_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  333) 		qla2x00_nv_write(ha, NVR_PR_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  334) 		for (word = 0; word < 8; word++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  335) 			qla2x00_nv_write(ha, NVR_DATA_OUT | NVR_PR_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  336) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  337) 		qla2x00_nv_deselect(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  338) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  339) 		/* Clear protection register (ffff is cleared). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  340) 		qla2x00_nv_write(ha, NVR_PR_ENABLE | NVR_DATA_OUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  341) 		qla2x00_nv_write(ha, NVR_PR_ENABLE | NVR_DATA_OUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  342) 		qla2x00_nv_write(ha, NVR_PR_ENABLE | NVR_DATA_OUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  343) 		for (word = 0; word < 8; word++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  344) 			qla2x00_nv_write(ha, NVR_DATA_OUT | NVR_PR_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  345) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  346) 		qla2x00_nv_deselect(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  347) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  348) 		/* Wait for NVRAM to become ready. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  349) 		wrt_reg_word(&reg->nvram, NVR_SELECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  350) 		rd_reg_word(&reg->nvram);	/* PCI Posting. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  351) 		wait_cnt = NVR_WAIT_CNT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  352) 		do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  353) 			if (!--wait_cnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  354) 				ql_dbg(ql_dbg_user, vha, 0x708e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  355) 				    "NVRAM didn't go ready...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  356) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  357) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  358) 			NVRAM_DELAY();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  359) 			word = rd_reg_word(&reg->nvram);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  360) 		} while ((word & NVR_DATA_IN) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  361) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  362) 		if (wait_cnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  363) 			ret = QLA_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  364) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  365) 		qla2x00_write_nvram_word(ha, ha->nvram_base, wprot_old);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  366) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  367) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  369) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  370) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  371) qla2x00_set_nvram_protection(struct qla_hw_data *ha, int stat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  372) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  373) 	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  374) 	uint32_t word, wait_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  375) 	scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  376) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  377) 	if (stat != QLA_SUCCESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  378) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  379) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  380) 	/* Set NVRAM write protection. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  381) 	/* Write enable. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  382) 	qla2x00_nv_write(ha, NVR_DATA_OUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  383) 	qla2x00_nv_write(ha, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  384) 	qla2x00_nv_write(ha, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  385) 	for (word = 0; word < 8; word++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  386) 		qla2x00_nv_write(ha, NVR_DATA_OUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  387) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  388) 	qla2x00_nv_deselect(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  389) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  390) 	/* Enable protection register. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  391) 	qla2x00_nv_write(ha, NVR_PR_ENABLE | NVR_DATA_OUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  392) 	qla2x00_nv_write(ha, NVR_PR_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  393) 	qla2x00_nv_write(ha, NVR_PR_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  394) 	for (word = 0; word < 8; word++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  395) 		qla2x00_nv_write(ha, NVR_DATA_OUT | NVR_PR_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  396) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  397) 	qla2x00_nv_deselect(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  398) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  399) 	/* Enable protection register. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  400) 	qla2x00_nv_write(ha, NVR_PR_ENABLE | NVR_DATA_OUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  401) 	qla2x00_nv_write(ha, NVR_PR_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  402) 	qla2x00_nv_write(ha, NVR_PR_ENABLE | NVR_DATA_OUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  403) 	for (word = 0; word < 8; word++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  404) 		qla2x00_nv_write(ha, NVR_PR_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  405) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  406) 	qla2x00_nv_deselect(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  407) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  408) 	/* Wait for NVRAM to become ready. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  409) 	wrt_reg_word(&reg->nvram, NVR_SELECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  410) 	rd_reg_word(&reg->nvram);		/* PCI Posting. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  411) 	wait_cnt = NVR_WAIT_CNT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  412) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  413) 		if (!--wait_cnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  414) 			ql_dbg(ql_dbg_user, vha, 0x708f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  415) 			    "NVRAM didn't go ready...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  416) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  417) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  418) 		NVRAM_DELAY();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  419) 		word = rd_reg_word(&reg->nvram);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  420) 	} while ((word & NVR_DATA_IN) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  422) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  423) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  424) /*****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  425) /* Flash Manipulation Routines                                               */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  426) /*****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  427) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  428) static inline uint32_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  429) flash_conf_addr(struct qla_hw_data *ha, uint32_t faddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  430) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  431) 	return ha->flash_conf_off + faddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  432) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  433) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  434) static inline uint32_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  435) flash_data_addr(struct qla_hw_data *ha, uint32_t faddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  436) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  437) 	return ha->flash_data_off + faddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  438) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  439) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  440) static inline uint32_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  441) nvram_conf_addr(struct qla_hw_data *ha, uint32_t naddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  442) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  443) 	return ha->nvram_conf_off + naddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  445) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  446) static inline uint32_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  447) nvram_data_addr(struct qla_hw_data *ha, uint32_t naddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  448) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  449) 	return ha->nvram_data_off + naddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  450) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  451) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  452) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  453) qla24xx_read_flash_dword(struct qla_hw_data *ha, uint32_t addr, uint32_t *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  454) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  455) 	struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  456) 	ulong cnt = 30000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  457) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  458) 	wrt_reg_dword(&reg->flash_addr, addr & ~FARX_DATA_FLAG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  459) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  460) 	while (cnt--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  461) 		if (rd_reg_dword(&reg->flash_addr) & FARX_DATA_FLAG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  462) 			*data = rd_reg_dword(&reg->flash_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  463) 			return QLA_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  464) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  465) 		udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  466) 		cond_resched();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  467) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  468) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  469) 	ql_log(ql_log_warn, pci_get_drvdata(ha->pdev), 0x7090,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  470) 	    "Flash read dword at %x timeout.\n", addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  471) 	*data = 0xDEADDEAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  472) 	return QLA_FUNCTION_TIMEOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  474) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  475) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  476) qla24xx_read_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  477)     uint32_t dwords)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  478) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  479) 	ulong i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  480) 	int ret = QLA_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  481) 	struct qla_hw_data *ha = vha->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  482) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  483) 	/* Dword reads to flash. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  484) 	faddr =  flash_data_addr(ha, faddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  485) 	for (i = 0; i < dwords; i++, faddr++, dwptr++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  486) 		ret = qla24xx_read_flash_dword(ha, faddr, dwptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  487) 		if (ret != QLA_SUCCESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  488) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  489) 		cpu_to_le32s(dwptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  490) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  491) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  492) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  494) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  495) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  496) qla24xx_write_flash_dword(struct qla_hw_data *ha, uint32_t addr, uint32_t data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  497) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  498) 	struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  499) 	ulong cnt = 500000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  500) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  501) 	wrt_reg_dword(&reg->flash_data, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  502) 	wrt_reg_dword(&reg->flash_addr, addr | FARX_DATA_FLAG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  503) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  504) 	while (cnt--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  505) 		if (!(rd_reg_dword(&reg->flash_addr) & FARX_DATA_FLAG))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  506) 			return QLA_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  507) 		udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  508) 		cond_resched();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  509) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  510) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  511) 	ql_log(ql_log_warn, pci_get_drvdata(ha->pdev), 0x7090,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  512) 	    "Flash write dword at %x timeout.\n", addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  513) 	return QLA_FUNCTION_TIMEOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  514) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  515) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  516) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  517) qla24xx_get_flash_manufacturer(struct qla_hw_data *ha, uint8_t *man_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  518)     uint8_t *flash_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  519) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  520) 	uint32_t faddr, ids = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  521) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  522) 	*man_id = *flash_id = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  523) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  524) 	faddr = flash_conf_addr(ha, 0x03ab);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  525) 	if (!qla24xx_read_flash_dword(ha, faddr, &ids)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  526) 		*man_id = LSB(ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  527) 		*flash_id = MSB(ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  528) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  529) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  530) 	/* Check if man_id and flash_id are valid. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  531) 	if (ids != 0xDEADDEAD && (*man_id == 0 || *flash_id == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  532) 		/* Read information using 0x9f opcode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  533) 		 * Device ID, Mfg ID would be read in the format:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  534) 		 *   <Ext Dev Info><Device ID Part2><Device ID Part 1><Mfg ID>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  535) 		 * Example: ATMEL 0x00 01 45 1F
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  536) 		 * Extract MFG and Dev ID from last two bytes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  537) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  538) 		faddr = flash_conf_addr(ha, 0x009f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  539) 		if (!qla24xx_read_flash_dword(ha, faddr, &ids)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  540) 			*man_id = LSB(ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  541) 			*flash_id = MSB(ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  542) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  543) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  544) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  545) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  546) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  547) qla2xxx_find_flt_start(scsi_qla_host_t *vha, uint32_t *start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  548) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  549) 	const char *loc, *locations[] = { "DEF", "PCI" };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  550) 	uint32_t pcihdr, pcids;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  551) 	uint16_t cnt, chksum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  552) 	__le16 *wptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  553) 	struct qla_hw_data *ha = vha->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  554) 	struct req_que *req = ha->req_q_map[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  555) 	struct qla_flt_location *fltl = (void *)req->ring;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  556) 	uint32_t *dcode = (uint32_t *)req->ring;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  557) 	uint8_t *buf = (void *)req->ring, *bcode,  last_image;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  558) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  559) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  560) 	 * FLT-location structure resides after the last PCI region.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  561) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  562) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  563) 	/* Begin with sane defaults. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  564) 	loc = locations[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  565) 	*start = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  566) 	if (IS_QLA24XX_TYPE(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  567) 		*start = FA_FLASH_LAYOUT_ADDR_24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  568) 	else if (IS_QLA25XX(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  569) 		*start = FA_FLASH_LAYOUT_ADDR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  570) 	else if (IS_QLA81XX(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  571) 		*start = FA_FLASH_LAYOUT_ADDR_81;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  572) 	else if (IS_P3P_TYPE(ha)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  573) 		*start = FA_FLASH_LAYOUT_ADDR_82;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  574) 		goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  575) 	} else if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  576) 		*start = FA_FLASH_LAYOUT_ADDR_83;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  577) 		goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  578) 	} else if (IS_QLA28XX(ha)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  579) 		*start = FA_FLASH_LAYOUT_ADDR_28;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  580) 		goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  581) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  582) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  583) 	/* Begin with first PCI expansion ROM header. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  584) 	pcihdr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  585) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  586) 		/* Verify PCI expansion ROM header. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  587) 		qla24xx_read_flash_data(vha, dcode, pcihdr >> 2, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  588) 		bcode = buf + (pcihdr % 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  589) 		if (bcode[0x0] != 0x55 || bcode[0x1] != 0xaa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  590) 			goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  591) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  592) 		/* Locate PCI data structure. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  593) 		pcids = pcihdr + ((bcode[0x19] << 8) | bcode[0x18]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  594) 		qla24xx_read_flash_data(vha, dcode, pcids >> 2, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  595) 		bcode = buf + (pcihdr % 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  596) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  597) 		/* Validate signature of PCI data structure. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  598) 		if (bcode[0x0] != 'P' || bcode[0x1] != 'C' ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  599) 		    bcode[0x2] != 'I' || bcode[0x3] != 'R')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  600) 			goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  601) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  602) 		last_image = bcode[0x15] & BIT_7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  603) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  604) 		/* Locate next PCI expansion ROM. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  605) 		pcihdr += ((bcode[0x11] << 8) | bcode[0x10]) * 512;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  606) 	} while (!last_image);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  607) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  608) 	/* Now verify FLT-location structure. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  609) 	qla24xx_read_flash_data(vha, dcode, pcihdr >> 2, sizeof(*fltl) >> 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  610) 	if (memcmp(fltl->sig, "QFLT", 4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  611) 		goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  612) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  613) 	wptr = (__force __le16 *)req->ring;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  614) 	cnt = sizeof(*fltl) / sizeof(*wptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  615) 	for (chksum = 0; cnt--; wptr++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  616) 		chksum += le16_to_cpu(*wptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  617) 	if (chksum) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  618) 		ql_log(ql_log_fatal, vha, 0x0045,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  619) 		    "Inconsistent FLTL detected: checksum=0x%x.\n", chksum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  620) 		ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x010e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  621) 		    fltl, sizeof(*fltl));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  622) 		return QLA_FUNCTION_FAILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  623) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  624) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  625) 	/* Good data.  Use specified location. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  626) 	loc = locations[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  627) 	*start = (le16_to_cpu(fltl->start_hi) << 16 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  628) 	    le16_to_cpu(fltl->start_lo)) >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  629) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  630) 	ql_dbg(ql_dbg_init, vha, 0x0046,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  631) 	    "FLTL[%s] = 0x%x.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  632) 	    loc, *start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  633) 	return QLA_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  634) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  635) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  636) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  637) qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  638) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  639) 	const char *locations[] = { "DEF", "FLT" }, *loc = locations[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  640) 	const uint32_t def_fw[] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  641) 		{ FA_RISC_CODE_ADDR, FA_RISC_CODE_ADDR, FA_RISC_CODE_ADDR_81 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  642) 	const uint32_t def_boot[] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  643) 		{ FA_BOOT_CODE_ADDR, FA_BOOT_CODE_ADDR, FA_BOOT_CODE_ADDR_81 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  644) 	const uint32_t def_vpd_nvram[] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  645) 		{ FA_VPD_NVRAM_ADDR, FA_VPD_NVRAM_ADDR, FA_VPD_NVRAM_ADDR_81 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  646) 	const uint32_t def_vpd0[] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  647) 		{ 0, 0, FA_VPD0_ADDR_81 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  648) 	const uint32_t def_vpd1[] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  649) 		{ 0, 0, FA_VPD1_ADDR_81 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  650) 	const uint32_t def_nvram0[] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  651) 		{ 0, 0, FA_NVRAM0_ADDR_81 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  652) 	const uint32_t def_nvram1[] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  653) 		{ 0, 0, FA_NVRAM1_ADDR_81 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  654) 	const uint32_t def_fdt[] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  655) 		{ FA_FLASH_DESCR_ADDR_24, FA_FLASH_DESCR_ADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  656) 			FA_FLASH_DESCR_ADDR_81 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  657) 	const uint32_t def_npiv_conf0[] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  658) 		{ FA_NPIV_CONF0_ADDR_24, FA_NPIV_CONF0_ADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  659) 			FA_NPIV_CONF0_ADDR_81 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  660) 	const uint32_t def_npiv_conf1[] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  661) 		{ FA_NPIV_CONF1_ADDR_24, FA_NPIV_CONF1_ADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  662) 			FA_NPIV_CONF1_ADDR_81 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  663) 	const uint32_t fcp_prio_cfg0[] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  664) 		{ FA_FCP_PRIO0_ADDR, FA_FCP_PRIO0_ADDR_25,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  665) 			0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  666) 	const uint32_t fcp_prio_cfg1[] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  667) 		{ FA_FCP_PRIO1_ADDR, FA_FCP_PRIO1_ADDR_25,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  668) 			0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  669) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  670) 	struct qla_hw_data *ha = vha->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  671) 	uint32_t def = IS_QLA81XX(ha) ? 2 : IS_QLA25XX(ha) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  672) 	struct qla_flt_header *flt = ha->flt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  673) 	struct qla_flt_region *region = &flt->region[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  674) 	__le16 *wptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  675) 	uint16_t cnt, chksum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  676) 	uint32_t start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  677) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  678) 	/* Assign FCP prio region since older adapters may not have FLT, or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  679) 	   FCP prio region in it's FLT.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  680) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  681) 	ha->flt_region_fcp_prio = (ha->port_no == 0) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  682) 	    fcp_prio_cfg0[def] : fcp_prio_cfg1[def];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  683) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  684) 	ha->flt_region_flt = flt_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  685) 	wptr = (__force __le16 *)ha->flt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  686) 	ha->isp_ops->read_optrom(vha, flt, flt_addr << 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  687) 	    (sizeof(struct qla_flt_header) + FLT_REGIONS_SIZE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  688) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  689) 	if (le16_to_cpu(*wptr) == 0xffff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  690) 		goto no_flash_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  691) 	if (flt->version != cpu_to_le16(1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  692) 		ql_log(ql_log_warn, vha, 0x0047,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  693) 		    "Unsupported FLT detected: version=0x%x length=0x%x checksum=0x%x.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  694) 		    le16_to_cpu(flt->version), le16_to_cpu(flt->length),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  695) 		    le16_to_cpu(flt->checksum));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  696) 		goto no_flash_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  697) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  698) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  699) 	cnt = (sizeof(*flt) + le16_to_cpu(flt->length)) / sizeof(*wptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  700) 	for (chksum = 0; cnt--; wptr++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  701) 		chksum += le16_to_cpu(*wptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  702) 	if (chksum) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  703) 		ql_log(ql_log_fatal, vha, 0x0048,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  704) 		    "Inconsistent FLT detected: version=0x%x length=0x%x checksum=0x%x.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  705) 		    le16_to_cpu(flt->version), le16_to_cpu(flt->length),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  706) 		    le16_to_cpu(flt->checksum));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  707) 		goto no_flash_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  708) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  709) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  710) 	cnt = le16_to_cpu(flt->length) / sizeof(*region);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  711) 	for ( ; cnt; cnt--, region++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  712) 		/* Store addresses as DWORD offsets. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  713) 		start = le32_to_cpu(region->start) >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  714) 		ql_dbg(ql_dbg_init, vha, 0x0049,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  715) 		    "FLT[%#x]: start=%#x end=%#x size=%#x.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  716) 		    le16_to_cpu(region->code), start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  717) 		    le32_to_cpu(region->end) >> 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  718) 		    le32_to_cpu(region->size) >> 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  719) 		if (region->attribute)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  720) 			ql_log(ql_dbg_init, vha, 0xffff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  721) 			    "Region %x is secure\n", region->code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  722) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  723) 		switch (le16_to_cpu(region->code)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  724) 		case FLT_REG_FCOE_FW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  725) 			if (!IS_QLA8031(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  726) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  727) 			ha->flt_region_fw = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  728) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  729) 		case FLT_REG_FW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  730) 			if (IS_QLA8031(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  731) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  732) 			ha->flt_region_fw = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  733) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  734) 		case FLT_REG_BOOT_CODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  735) 			ha->flt_region_boot = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  736) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  737) 		case FLT_REG_VPD_0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  738) 			if (IS_QLA8031(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  739) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  740) 			ha->flt_region_vpd_nvram = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  741) 			if (IS_P3P_TYPE(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  742) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  743) 			if (ha->port_no == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  744) 				ha->flt_region_vpd = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  745) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  746) 		case FLT_REG_VPD_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  747) 			if (IS_P3P_TYPE(ha) || IS_QLA8031(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  748) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  749) 			if (ha->port_no == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  750) 				ha->flt_region_vpd = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  751) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  752) 		case FLT_REG_VPD_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  753) 			if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  754) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  755) 			if (ha->port_no == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  756) 				ha->flt_region_vpd = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  757) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  758) 		case FLT_REG_VPD_3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  759) 			if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  760) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  761) 			if (ha->port_no == 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  762) 				ha->flt_region_vpd = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  763) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  764) 		case FLT_REG_NVRAM_0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  765) 			if (IS_QLA8031(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  766) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  767) 			if (ha->port_no == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  768) 				ha->flt_region_nvram = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  769) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  770) 		case FLT_REG_NVRAM_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  771) 			if (IS_QLA8031(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  772) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  773) 			if (ha->port_no == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  774) 				ha->flt_region_nvram = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  775) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  776) 		case FLT_REG_NVRAM_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  777) 			if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  778) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  779) 			if (ha->port_no == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  780) 				ha->flt_region_nvram = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  781) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  782) 		case FLT_REG_NVRAM_3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  783) 			if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  784) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  785) 			if (ha->port_no == 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  786) 				ha->flt_region_nvram = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  787) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  788) 		case FLT_REG_FDT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  789) 			ha->flt_region_fdt = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  790) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  791) 		case FLT_REG_NPIV_CONF_0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  792) 			if (ha->port_no == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  793) 				ha->flt_region_npiv_conf = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  794) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  795) 		case FLT_REG_NPIV_CONF_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  796) 			if (ha->port_no == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  797) 				ha->flt_region_npiv_conf = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  798) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  799) 		case FLT_REG_GOLD_FW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  800) 			ha->flt_region_gold_fw = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  801) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  802) 		case FLT_REG_FCP_PRIO_0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  803) 			if (ha->port_no == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  804) 				ha->flt_region_fcp_prio = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  805) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  806) 		case FLT_REG_FCP_PRIO_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  807) 			if (ha->port_no == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  808) 				ha->flt_region_fcp_prio = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  809) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  810) 		case FLT_REG_BOOT_CODE_82XX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  811) 			ha->flt_region_boot = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  812) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  813) 		case FLT_REG_BOOT_CODE_8044:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  814) 			if (IS_QLA8044(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  815) 				ha->flt_region_boot = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  816) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  817) 		case FLT_REG_FW_82XX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  818) 			ha->flt_region_fw = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  819) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  820) 		case FLT_REG_CNA_FW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  821) 			if (IS_CNA_CAPABLE(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  822) 				ha->flt_region_fw = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  823) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  824) 		case FLT_REG_GOLD_FW_82XX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  825) 			ha->flt_region_gold_fw = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  826) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  827) 		case FLT_REG_BOOTLOAD_82XX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  828) 			ha->flt_region_bootload = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  829) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  830) 		case FLT_REG_VPD_8XXX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  831) 			if (IS_CNA_CAPABLE(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  832) 				ha->flt_region_vpd = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  833) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  834) 		case FLT_REG_FCOE_NVRAM_0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  835) 			if (!(IS_QLA8031(ha) || IS_QLA8044(ha)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  836) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  837) 			if (ha->port_no == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  838) 				ha->flt_region_nvram = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  839) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  840) 		case FLT_REG_FCOE_NVRAM_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  841) 			if (!(IS_QLA8031(ha) || IS_QLA8044(ha)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  842) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  843) 			if (ha->port_no == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  844) 				ha->flt_region_nvram = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  845) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  846) 		case FLT_REG_IMG_PRI_27XX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  847) 			if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  848) 				ha->flt_region_img_status_pri = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  849) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  850) 		case FLT_REG_IMG_SEC_27XX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  851) 			if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  852) 				ha->flt_region_img_status_sec = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  853) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  854) 		case FLT_REG_FW_SEC_27XX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  855) 			if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  856) 				ha->flt_region_fw_sec = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  857) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  858) 		case FLT_REG_BOOTLOAD_SEC_27XX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  859) 			if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  860) 				ha->flt_region_boot_sec = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  861) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  862) 		case FLT_REG_AUX_IMG_PRI_28XX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  863) 			if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  864) 				ha->flt_region_aux_img_status_pri = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  865) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  866) 		case FLT_REG_AUX_IMG_SEC_28XX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  867) 			if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  868) 				ha->flt_region_aux_img_status_sec = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  869) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  870) 		case FLT_REG_NVRAM_SEC_28XX_0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  871) 			if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  872) 				if (ha->port_no == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  873) 					ha->flt_region_nvram_sec = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  874) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  875) 		case FLT_REG_NVRAM_SEC_28XX_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  876) 			if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  877) 				if (ha->port_no == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  878) 					ha->flt_region_nvram_sec = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  879) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  880) 		case FLT_REG_NVRAM_SEC_28XX_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  881) 			if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  882) 				if (ha->port_no == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  883) 					ha->flt_region_nvram_sec = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  884) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  885) 		case FLT_REG_NVRAM_SEC_28XX_3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  886) 			if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  887) 				if (ha->port_no == 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  888) 					ha->flt_region_nvram_sec = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  889) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  890) 		case FLT_REG_VPD_SEC_27XX_0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  891) 		case FLT_REG_VPD_SEC_28XX_0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  892) 			if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  893) 				ha->flt_region_vpd_nvram_sec = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  894) 				if (ha->port_no == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  895) 					ha->flt_region_vpd_sec = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  896) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  897) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  898) 		case FLT_REG_VPD_SEC_27XX_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  899) 		case FLT_REG_VPD_SEC_28XX_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  900) 			if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  901) 				if (ha->port_no == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  902) 					ha->flt_region_vpd_sec = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  903) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  904) 		case FLT_REG_VPD_SEC_27XX_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  905) 		case FLT_REG_VPD_SEC_28XX_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  906) 			if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  907) 				if (ha->port_no == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  908) 					ha->flt_region_vpd_sec = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  909) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  910) 		case FLT_REG_VPD_SEC_27XX_3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  911) 		case FLT_REG_VPD_SEC_28XX_3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  912) 			if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  913) 				if (ha->port_no == 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  914) 					ha->flt_region_vpd_sec = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  915) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  916) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  917) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  918) 	goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  919) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  920) no_flash_data:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  921) 	/* Use hardcoded defaults. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  922) 	loc = locations[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  923) 	ha->flt_region_fw = def_fw[def];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  924) 	ha->flt_region_boot = def_boot[def];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  925) 	ha->flt_region_vpd_nvram = def_vpd_nvram[def];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  926) 	ha->flt_region_vpd = (ha->port_no == 0) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  927) 	    def_vpd0[def] : def_vpd1[def];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  928) 	ha->flt_region_nvram = (ha->port_no == 0) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  929) 	    def_nvram0[def] : def_nvram1[def];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  930) 	ha->flt_region_fdt = def_fdt[def];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  931) 	ha->flt_region_npiv_conf = (ha->port_no == 0) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  932) 	    def_npiv_conf0[def] : def_npiv_conf1[def];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  933) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  934) 	ql_dbg(ql_dbg_init, vha, 0x004a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  935) 	    "FLT[%s]: boot=0x%x fw=0x%x vpd_nvram=0x%x vpd=0x%x nvram=0x%x "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  936) 	    "fdt=0x%x flt=0x%x npiv=0x%x fcp_prif_cfg=0x%x.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  937) 	    loc, ha->flt_region_boot, ha->flt_region_fw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  938) 	    ha->flt_region_vpd_nvram, ha->flt_region_vpd, ha->flt_region_nvram,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  939) 	    ha->flt_region_fdt, ha->flt_region_flt, ha->flt_region_npiv_conf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  940) 	    ha->flt_region_fcp_prio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  941) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  942) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  943) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  944) qla2xxx_get_fdt_info(scsi_qla_host_t *vha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  945) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  946) #define FLASH_BLK_SIZE_4K	0x1000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  947) #define FLASH_BLK_SIZE_32K	0x8000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  948) #define FLASH_BLK_SIZE_64K	0x10000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  949) 	const char *loc, *locations[] = { "MID", "FDT" };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  950) 	struct qla_hw_data *ha = vha->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  951) 	struct req_que *req = ha->req_q_map[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  952) 	uint16_t cnt, chksum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  953) 	__le16 *wptr = (__force __le16 *)req->ring;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  954) 	struct qla_fdt_layout *fdt = (struct qla_fdt_layout *)req->ring;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  955) 	uint8_t	man_id, flash_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  956) 	uint16_t mid = 0, fid = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  957) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  958) 	ha->isp_ops->read_optrom(vha, fdt, ha->flt_region_fdt << 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  959) 	    OPTROM_BURST_DWORDS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  960) 	if (le16_to_cpu(*wptr) == 0xffff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  961) 		goto no_flash_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  962) 	if (memcmp(fdt->sig, "QLID", 4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  963) 		goto no_flash_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  964) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  965) 	for (cnt = 0, chksum = 0; cnt < sizeof(*fdt) >> 1; cnt++, wptr++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  966) 		chksum += le16_to_cpu(*wptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  967) 	if (chksum) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  968) 		ql_dbg(ql_dbg_init, vha, 0x004c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  969) 		    "Inconsistent FDT detected:"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  970) 		    " checksum=0x%x id=%c version0x%x.\n", chksum,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  971) 		    fdt->sig[0], le16_to_cpu(fdt->version));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  972) 		ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0113,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  973) 		    fdt, sizeof(*fdt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  974) 		goto no_flash_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  975) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  976) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  977) 	loc = locations[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  978) 	mid = le16_to_cpu(fdt->man_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  979) 	fid = le16_to_cpu(fdt->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  980) 	ha->fdt_wrt_disable = fdt->wrt_disable_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  981) 	ha->fdt_wrt_enable = fdt->wrt_enable_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  982) 	ha->fdt_wrt_sts_reg_cmd = fdt->wrt_sts_reg_cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  983) 	if (IS_QLA8044(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  984) 		ha->fdt_erase_cmd = fdt->erase_cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  985) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  986) 		ha->fdt_erase_cmd =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  987) 		    flash_conf_addr(ha, 0x0300 | fdt->erase_cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  988) 	ha->fdt_block_size = le32_to_cpu(fdt->block_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  989) 	if (fdt->unprotect_sec_cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  990) 		ha->fdt_unprotect_sec_cmd = flash_conf_addr(ha, 0x0300 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  991) 		    fdt->unprotect_sec_cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  992) 		ha->fdt_protect_sec_cmd = fdt->protect_sec_cmd ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  993) 		    flash_conf_addr(ha, 0x0300 | fdt->protect_sec_cmd) :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  994) 		    flash_conf_addr(ha, 0x0336);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  995) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  996) 	goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  997) no_flash_data:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  998) 	loc = locations[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  999) 	if (IS_P3P_TYPE(ha)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) 		ha->fdt_block_size = FLASH_BLK_SIZE_64K;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) 		goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) 	qla24xx_get_flash_manufacturer(ha, &man_id, &flash_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) 	mid = man_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) 	fid = flash_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) 	ha->fdt_wrt_disable = 0x9c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) 	ha->fdt_erase_cmd = flash_conf_addr(ha, 0x03d8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) 	switch (man_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) 	case 0xbf: /* STT flash. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) 		if (flash_id == 0x8e)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) 			ha->fdt_block_size = FLASH_BLK_SIZE_64K;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) 			ha->fdt_block_size = FLASH_BLK_SIZE_32K;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) 		if (flash_id == 0x80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) 			ha->fdt_erase_cmd = flash_conf_addr(ha, 0x0352);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) 	case 0x13: /* ST M25P80. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) 		ha->fdt_block_size = FLASH_BLK_SIZE_64K;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) 	case 0x1f: /* Atmel 26DF081A. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) 		ha->fdt_block_size = FLASH_BLK_SIZE_4K;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) 		ha->fdt_erase_cmd = flash_conf_addr(ha, 0x0320);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) 		ha->fdt_unprotect_sec_cmd = flash_conf_addr(ha, 0x0339);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) 		ha->fdt_protect_sec_cmd = flash_conf_addr(ha, 0x0336);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) 		/* Default to 64 kb sector size. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) 		ha->fdt_block_size = FLASH_BLK_SIZE_64K;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) 	ql_dbg(ql_dbg_init, vha, 0x004d,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) 	    "FDT[%s]: (0x%x/0x%x) erase=0x%x "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) 	    "pr=%x wrtd=0x%x blk=0x%x.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) 	    loc, mid, fid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) 	    ha->fdt_erase_cmd, ha->fdt_protect_sec_cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) 	    ha->fdt_wrt_disable, ha->fdt_block_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) qla2xxx_get_idc_param(scsi_qla_host_t *vha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) #define QLA82XX_IDC_PARAM_ADDR       0x003e885c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) 	__le32 *wptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) 	struct qla_hw_data *ha = vha->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) 	struct req_que *req = ha->req_q_map[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) 	if (!(IS_P3P_TYPE(ha)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) 	wptr = (__force __le32 *)req->ring;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) 	ha->isp_ops->read_optrom(vha, req->ring, QLA82XX_IDC_PARAM_ADDR, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) 	if (*wptr == cpu_to_le32(0xffffffff)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) 		ha->fcoe_dev_init_timeout = QLA82XX_ROM_DEV_INIT_TIMEOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) 		ha->fcoe_reset_timeout = QLA82XX_ROM_DRV_RESET_ACK_TIMEOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) 		ha->fcoe_dev_init_timeout = le32_to_cpu(*wptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) 		wptr++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) 		ha->fcoe_reset_timeout = le32_to_cpu(*wptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) 	ql_dbg(ql_dbg_init, vha, 0x004e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) 	    "fcoe_dev_init_timeout=%d "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) 	    "fcoe_reset_timeout=%d.\n", ha->fcoe_dev_init_timeout,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) 	    ha->fcoe_reset_timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) 	return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) qla2xxx_get_flash_info(scsi_qla_host_t *vha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) 	uint32_t flt_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) 	struct qla_hw_data *ha = vha->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) 	if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) 	    !IS_CNA_CAPABLE(ha) && !IS_QLA2031(ha) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) 	    !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) 		return QLA_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) 	ret = qla2xxx_find_flt_start(vha, &flt_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) 	if (ret != QLA_SUCCESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) 	qla2xxx_get_flt_info(vha, flt_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) 	qla2xxx_get_fdt_info(vha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) 	qla2xxx_get_idc_param(vha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) 	return QLA_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) qla2xxx_flash_npiv_conf(scsi_qla_host_t *vha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) #define NPIV_CONFIG_SIZE	(16*1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) 	void *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) 	__le16 *wptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) 	uint16_t cnt, chksum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) 	struct qla_npiv_header hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) 	struct qla_npiv_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) 	struct qla_hw_data *ha = vha->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) 	if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) 	    !IS_CNA_CAPABLE(ha) && !IS_QLA2031(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) 	if (ha->flags.nic_core_reset_hdlr_active)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) 	if (IS_QLA8044(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) 	ha->isp_ops->read_optrom(vha, &hdr, ha->flt_region_npiv_conf << 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) 	    sizeof(struct qla_npiv_header));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) 	if (hdr.version == cpu_to_le16(0xffff))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) 	if (hdr.version != cpu_to_le16(1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) 		ql_dbg(ql_dbg_user, vha, 0x7090,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) 		    "Unsupported NPIV-Config "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) 		    "detected: version=0x%x entries=0x%x checksum=0x%x.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) 		    le16_to_cpu(hdr.version), le16_to_cpu(hdr.entries),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) 		    le16_to_cpu(hdr.checksum));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) 	data = kmalloc(NPIV_CONFIG_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) 	if (!data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) 		ql_log(ql_log_warn, vha, 0x7091,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) 		    "Unable to allocate memory for data.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) 	ha->isp_ops->read_optrom(vha, data, ha->flt_region_npiv_conf << 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) 	    NPIV_CONFIG_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) 	cnt = (sizeof(hdr) + le16_to_cpu(hdr.entries) * sizeof(*entry)) >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) 	for (wptr = data, chksum = 0; cnt--; wptr++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) 		chksum += le16_to_cpu(*wptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) 	if (chksum) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) 		ql_dbg(ql_dbg_user, vha, 0x7092,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) 		    "Inconsistent NPIV-Config "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) 		    "detected: version=0x%x entries=0x%x checksum=0x%x.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) 		    le16_to_cpu(hdr.version), le16_to_cpu(hdr.entries),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) 		    le16_to_cpu(hdr.checksum));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) 		goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) 	entry = data + sizeof(struct qla_npiv_header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) 	cnt = le16_to_cpu(hdr.entries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) 	for (i = 0; cnt; cnt--, entry++, i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) 		uint16_t flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) 		struct fc_vport_identifiers vid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) 		struct fc_vport *vport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) 		memcpy(&ha->npiv_info[i], entry, sizeof(struct qla_npiv_entry));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) 		flags = le16_to_cpu(entry->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) 		if (flags == 0xffff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) 		if ((flags & BIT_0) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) 		memset(&vid, 0, sizeof(vid));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) 		vid.roles = FC_PORT_ROLE_FCP_INITIATOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) 		vid.vport_type = FC_PORTTYPE_NPIV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) 		vid.disable = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) 		vid.port_name = wwn_to_u64(entry->port_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) 		vid.node_name = wwn_to_u64(entry->node_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) 		ql_dbg(ql_dbg_user, vha, 0x7093,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) 		    "NPIV[%02x]: wwpn=%llx wwnn=%llx vf_id=%#x Q_qos=%#x F_qos=%#x.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) 		    cnt, vid.port_name, vid.node_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) 		    le16_to_cpu(entry->vf_id),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) 		    entry->q_qos, entry->f_qos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) 		if (i < QLA_PRECONFIG_VPORTS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) 			vport = fc_vport_create(vha->host, 0, &vid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) 			if (!vport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) 				ql_log(ql_log_warn, vha, 0x7094,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) 				    "NPIV-Config Failed to create vport [%02x]: wwpn=%llx wwnn=%llx.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) 				    cnt, vid.port_name, vid.node_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) 	kfree(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) qla24xx_unprotect_flash(scsi_qla_host_t *vha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) 	struct qla_hw_data *ha = vha->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) 	struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) 	if (ha->flags.fac_supported)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) 		return qla81xx_fac_do_write_enable(vha, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) 	/* Enable flash write. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) 	wrt_reg_dword(&reg->ctrl_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) 	    rd_reg_dword(&reg->ctrl_status) | CSRX_FLASH_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) 	rd_reg_dword(&reg->ctrl_status);	/* PCI Posting. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) 	if (!ha->fdt_wrt_disable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) 		goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) 	/* Disable flash write-protection, first clear SR protection bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) 	qla24xx_write_flash_dword(ha, flash_conf_addr(ha, 0x101), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) 	/* Then write zero again to clear remaining SR bits.*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) 	qla24xx_write_flash_dword(ha, flash_conf_addr(ha, 0x101), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) 	return QLA_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) qla24xx_protect_flash(scsi_qla_host_t *vha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) 	struct qla_hw_data *ha = vha->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) 	struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) 	ulong cnt = 300;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) 	uint32_t faddr, dword;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) 	if (ha->flags.fac_supported)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) 		return qla81xx_fac_do_write_enable(vha, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) 	if (!ha->fdt_wrt_disable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) 		goto skip_wrt_protect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) 	/* Enable flash write-protection and wait for completion. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) 	faddr = flash_conf_addr(ha, 0x101);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) 	qla24xx_write_flash_dword(ha, faddr, ha->fdt_wrt_disable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) 	faddr = flash_conf_addr(ha, 0x5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) 	while (cnt--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) 		if (!qla24xx_read_flash_dword(ha, faddr, &dword)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) 			if (!(dword & BIT_0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) 		udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) skip_wrt_protect:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) 	/* Disable flash write. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) 	wrt_reg_dword(&reg->ctrl_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) 	    rd_reg_dword(&reg->ctrl_status) & ~CSRX_FLASH_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) 	return QLA_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) qla24xx_erase_sector(scsi_qla_host_t *vha, uint32_t fdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) 	struct qla_hw_data *ha = vha->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) 	uint32_t start, finish;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) 	if (ha->flags.fac_supported) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) 		start = fdata >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) 		finish = start + (ha->fdt_block_size >> 2) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) 		return qla81xx_fac_erase_sector(vha, flash_data_addr(ha,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) 		    start), flash_data_addr(ha, finish));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) 	return qla24xx_write_flash_dword(ha, ha->fdt_erase_cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) 	    (fdata & 0xff00) | ((fdata << 16) & 0xff0000) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) 	    ((fdata >> 16) & 0xff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) qla24xx_write_flash_data(scsi_qla_host_t *vha, __le32 *dwptr, uint32_t faddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270)     uint32_t dwords)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) 	ulong liter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) 	ulong dburst = OPTROM_BURST_DWORDS; /* burst size in dwords */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) 	uint32_t sec_mask, rest_addr, fdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) 	dma_addr_t optrom_dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) 	void *optrom = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) 	struct qla_hw_data *ha = vha->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) 	if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) 	    !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) 		goto next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) 	/* Allocate dma buffer for burst write */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) 	optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) 	    &optrom_dma, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) 	if (!optrom) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) 		ql_log(ql_log_warn, vha, 0x7095,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) 		    "Failed allocate burst (%x bytes)\n", OPTROM_BURST_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) next:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) 	ql_log(ql_log_warn + ql_dbg_verbose, vha, 0x7095,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) 	    "Unprotect flash...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) 	ret = qla24xx_unprotect_flash(vha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) 		ql_log(ql_log_warn, vha, 0x7096,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) 		    "Failed to unprotect flash.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) 		goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) 	rest_addr = (ha->fdt_block_size >> 2) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) 	sec_mask = ~rest_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) 	for (liter = 0; liter < dwords; liter++, faddr++, dwptr++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) 		fdata = (faddr & sec_mask) << 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) 		/* Are we at the beginning of a sector? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) 		if (!(faddr & rest_addr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) 			ql_log(ql_log_warn + ql_dbg_verbose, vha, 0x7095,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) 			    "Erase sector %#x...\n", faddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) 			ret = qla24xx_erase_sector(vha, fdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) 			if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) 				ql_dbg(ql_dbg_user, vha, 0x7007,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) 				    "Failed to erase sector %x.\n", faddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) 		if (optrom) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) 			/* If smaller than a burst remaining */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) 			if (dwords - liter < dburst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) 				dburst = dwords - liter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) 			/* Copy to dma buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) 			memcpy(optrom, dwptr, dburst << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) 			/* Burst write */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) 			ql_log(ql_log_warn + ql_dbg_verbose, vha, 0x7095,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) 			    "Write burst (%#lx dwords)...\n", dburst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) 			ret = qla2x00_load_ram(vha, optrom_dma,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) 			    flash_data_addr(ha, faddr), dburst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) 			if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) 				liter += dburst - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) 				faddr += dburst - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) 				dwptr += dburst - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) 			ql_log(ql_log_warn, vha, 0x7097,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) 			    "Failed burst-write at %x (%p/%#llx)....\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) 			    flash_data_addr(ha, faddr), optrom,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) 			    (u64)optrom_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) 			dma_free_coherent(&ha->pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) 			    OPTROM_BURST_SIZE, optrom, optrom_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) 			optrom = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) 			if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) 			ql_log(ql_log_warn, vha, 0x7098,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) 			    "Reverting to slow write...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) 		/* Slow write */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) 		ret = qla24xx_write_flash_dword(ha,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) 		    flash_data_addr(ha, faddr), le32_to_cpu(*dwptr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) 		if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) 			ql_dbg(ql_dbg_user, vha, 0x7006,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) 			    "Failed slow write %x (%x)\n", faddr, *dwptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) 	ql_log(ql_log_warn + ql_dbg_verbose, vha, 0x7095,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) 	    "Protect flash...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) 	ret = qla24xx_protect_flash(vha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) 		ql_log(ql_log_warn, vha, 0x7099,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) 		    "Failed to protect flash\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) 	if (optrom)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) 		dma_free_coherent(&ha->pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) 		    OPTROM_BURST_SIZE, optrom, optrom_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) uint8_t *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) qla2x00_read_nvram_data(scsi_qla_host_t *vha, void *buf, uint32_t naddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380)     uint32_t bytes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) 	uint32_t i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) 	__le16 *wptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) 	struct qla_hw_data *ha = vha->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) 	/* Word reads to NVRAM via registers. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) 	wptr = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) 	qla2x00_lock_nvram_access(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) 	for (i = 0; i < bytes >> 1; i++, naddr++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) 		wptr[i] = cpu_to_le16(qla2x00_get_nvram_word(ha,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) 		    naddr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) 	qla2x00_unlock_nvram_access(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) 	return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) uint8_t *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) qla24xx_read_nvram_data(scsi_qla_host_t *vha, void *buf, uint32_t naddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399)     uint32_t bytes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) 	struct qla_hw_data *ha = vha->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) 	uint32_t *dwptr = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) 	uint32_t i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) 	if (IS_P3P_TYPE(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) 		return  buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) 	/* Dword reads to flash. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) 	naddr = nvram_data_addr(ha, naddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) 	bytes >>= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) 	for (i = 0; i < bytes; i++, naddr++, dwptr++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) 		if (qla24xx_read_flash_dword(ha, naddr, dwptr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) 		cpu_to_le32s(dwptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) 	return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) qla2x00_write_nvram_data(scsi_qla_host_t *vha, void *buf, uint32_t naddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422)     uint32_t bytes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) 	int ret, stat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) 	uint32_t i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) 	uint16_t *wptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) 	struct qla_hw_data *ha = vha->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) 	ret = QLA_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) 	spin_lock_irqsave(&ha->hardware_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) 	qla2x00_lock_nvram_access(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) 	/* Disable NVRAM write-protection. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) 	stat = qla2x00_clear_nvram_protection(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) 	wptr = (uint16_t *)buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) 	for (i = 0; i < bytes >> 1; i++, naddr++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) 		qla2x00_write_nvram_word(ha, naddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) 		    cpu_to_le16(*wptr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) 		wptr++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) 	/* Enable NVRAM write-protection. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) 	qla2x00_set_nvram_protection(ha, stat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) 	qla2x00_unlock_nvram_access(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) qla24xx_write_nvram_data(scsi_qla_host_t *vha, void *buf, uint32_t naddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456)     uint32_t bytes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) 	struct qla_hw_data *ha = vha->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) 	struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) 	__le32 *dwptr = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) 	uint32_t i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) 	ret = QLA_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) 	if (IS_P3P_TYPE(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) 	/* Enable flash write. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) 	wrt_reg_dword(&reg->ctrl_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) 	    rd_reg_dword(&reg->ctrl_status) | CSRX_FLASH_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) 	rd_reg_dword(&reg->ctrl_status);	/* PCI Posting. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) 	/* Disable NVRAM write-protection. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) 	qla24xx_write_flash_dword(ha, nvram_conf_addr(ha, 0x101), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) 	qla24xx_write_flash_dword(ha, nvram_conf_addr(ha, 0x101), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) 	/* Dword writes to flash. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) 	naddr = nvram_data_addr(ha, naddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) 	bytes >>= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) 	for (i = 0; i < bytes; i++, naddr++, dwptr++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) 		if (qla24xx_write_flash_dword(ha, naddr, le32_to_cpu(*dwptr))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) 			ql_dbg(ql_dbg_user, vha, 0x709a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) 			    "Unable to program nvram address=%x data=%x.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) 			    naddr, *dwptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) 	/* Enable NVRAM write-protection. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) 	qla24xx_write_flash_dword(ha, nvram_conf_addr(ha, 0x101), 0x8c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) 	/* Disable flash write. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) 	wrt_reg_dword(&reg->ctrl_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) 	    rd_reg_dword(&reg->ctrl_status) & ~CSRX_FLASH_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) 	rd_reg_dword(&reg->ctrl_status);	/* PCI Posting. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) uint8_t *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) qla25xx_read_nvram_data(scsi_qla_host_t *vha, void *buf, uint32_t naddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503)     uint32_t bytes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) 	struct qla_hw_data *ha = vha->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) 	uint32_t *dwptr = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) 	uint32_t i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) 	/* Dword reads to flash. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) 	naddr = flash_data_addr(ha, ha->flt_region_vpd_nvram | naddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) 	bytes >>= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) 	for (i = 0; i < bytes; i++, naddr++, dwptr++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) 		if (qla24xx_read_flash_dword(ha, naddr, dwptr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) 		cpu_to_le32s(dwptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) 	return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) #define RMW_BUFFER_SIZE	(64 * 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) qla25xx_write_nvram_data(scsi_qla_host_t *vha, void *buf, uint32_t naddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525)     uint32_t bytes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) 	struct qla_hw_data *ha = vha->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) 	uint8_t *dbuf = vmalloc(RMW_BUFFER_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) 	if (!dbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) 		return QLA_MEMORY_ALLOC_FAILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) 	ha->isp_ops->read_optrom(vha, dbuf, ha->flt_region_vpd_nvram << 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) 	    RMW_BUFFER_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) 	memcpy(dbuf + (naddr << 2), buf, bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) 	ha->isp_ops->write_optrom(vha, dbuf, ha->flt_region_vpd_nvram << 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) 	    RMW_BUFFER_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) 	vfree(dbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) 	return QLA_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) qla2x00_flip_colors(struct qla_hw_data *ha, uint16_t *pflags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) 	if (IS_QLA2322(ha)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) 		/* Flip all colors. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) 		if (ha->beacon_color_state == QLA_LED_ALL_ON) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) 			/* Turn off. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) 			ha->beacon_color_state = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) 			*pflags = GPIO_LED_ALL_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) 			/* Turn on. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) 			ha->beacon_color_state = QLA_LED_ALL_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) 			*pflags = GPIO_LED_RGA_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) 		/* Flip green led only. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) 		if (ha->beacon_color_state == QLA_LED_GRN_ON) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) 			/* Turn off. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) 			ha->beacon_color_state = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) 			*pflags = GPIO_LED_GREEN_OFF_AMBER_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) 			/* Turn on. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) 			ha->beacon_color_state = QLA_LED_GRN_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) 			*pflags = GPIO_LED_GREEN_ON_AMBER_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) #define PIO_REG(h, r) ((h)->pio_address + offsetof(struct device_reg_2xxx, r))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) qla2x00_beacon_blink(struct scsi_qla_host *vha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) 	uint16_t gpio_enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) 	uint16_t gpio_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) 	uint16_t led_color = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) 	struct qla_hw_data *ha = vha->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) 	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) 	if (IS_P3P_TYPE(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) 	spin_lock_irqsave(&ha->hardware_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) 	/* Save the Original GPIOE. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) 	if (ha->pio_address) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) 		gpio_enable = RD_REG_WORD_PIO(PIO_REG(ha, gpioe));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) 		gpio_data = RD_REG_WORD_PIO(PIO_REG(ha, gpiod));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) 		gpio_enable = rd_reg_word(&reg->gpioe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) 		gpio_data = rd_reg_word(&reg->gpiod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) 	/* Set the modified gpio_enable values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) 	gpio_enable |= GPIO_LED_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) 	if (ha->pio_address) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) 		WRT_REG_WORD_PIO(PIO_REG(ha, gpioe), gpio_enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) 		wrt_reg_word(&reg->gpioe, gpio_enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) 		rd_reg_word(&reg->gpioe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) 	qla2x00_flip_colors(ha, &led_color);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) 	/* Clear out any previously set LED color. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) 	gpio_data &= ~GPIO_LED_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) 	/* Set the new input LED color to GPIOD. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) 	gpio_data |= led_color;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) 	/* Set the modified gpio_data values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) 	if (ha->pio_address) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) 		WRT_REG_WORD_PIO(PIO_REG(ha, gpiod), gpio_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) 		wrt_reg_word(&reg->gpiod, gpio_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) 		rd_reg_word(&reg->gpiod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) qla2x00_beacon_on(struct scsi_qla_host *vha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) 	uint16_t gpio_enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) 	uint16_t gpio_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) 	struct qla_hw_data *ha = vha->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) 	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) 	ha->fw_options[1] &= ~FO1_SET_EMPHASIS_SWING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) 	ha->fw_options[1] |= FO1_DISABLE_GPIO6_7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) 	if (qla2x00_set_fw_options(vha, ha->fw_options) != QLA_SUCCESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) 		ql_log(ql_log_warn, vha, 0x709b,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) 		    "Unable to update fw options (beacon on).\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) 		return QLA_FUNCTION_FAILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) 	/* Turn off LEDs. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) 	spin_lock_irqsave(&ha->hardware_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) 	if (ha->pio_address) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) 		gpio_enable = RD_REG_WORD_PIO(PIO_REG(ha, gpioe));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) 		gpio_data = RD_REG_WORD_PIO(PIO_REG(ha, gpiod));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) 		gpio_enable = rd_reg_word(&reg->gpioe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) 		gpio_data = rd_reg_word(&reg->gpiod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) 	gpio_enable |= GPIO_LED_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) 	/* Set the modified gpio_enable values. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) 	if (ha->pio_address) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) 		WRT_REG_WORD_PIO(PIO_REG(ha, gpioe), gpio_enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) 		wrt_reg_word(&reg->gpioe, gpio_enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) 		rd_reg_word(&reg->gpioe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) 	/* Clear out previously set LED colour. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) 	gpio_data &= ~GPIO_LED_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) 	if (ha->pio_address) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) 		WRT_REG_WORD_PIO(PIO_REG(ha, gpiod), gpio_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) 		wrt_reg_word(&reg->gpiod, gpio_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) 		rd_reg_word(&reg->gpiod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) 	 * Let the per HBA timer kick off the blinking process based on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) 	 * the following flags. No need to do anything else now.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) 	ha->beacon_blink_led = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) 	ha->beacon_color_state = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) 	return QLA_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) qla2x00_beacon_off(struct scsi_qla_host *vha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) 	int rval = QLA_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) 	struct qla_hw_data *ha = vha->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) 	ha->beacon_blink_led = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) 	/* Set the on flag so when it gets flipped it will be off. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) 	if (IS_QLA2322(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) 		ha->beacon_color_state = QLA_LED_ALL_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) 		ha->beacon_color_state = QLA_LED_GRN_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) 	ha->isp_ops->beacon_blink(vha);	/* This turns green LED off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) 	ha->fw_options[1] &= ~FO1_SET_EMPHASIS_SWING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) 	ha->fw_options[1] &= ~FO1_DISABLE_GPIO6_7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) 	rval = qla2x00_set_fw_options(vha, ha->fw_options);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) 	if (rval != QLA_SUCCESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) 		ql_log(ql_log_warn, vha, 0x709c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) 		    "Unable to update fw options (beacon off).\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) 	return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) qla24xx_flip_colors(struct qla_hw_data *ha, uint16_t *pflags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) 	/* Flip all colors. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) 	if (ha->beacon_color_state == QLA_LED_ALL_ON) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) 		/* Turn off. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) 		ha->beacon_color_state = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) 		*pflags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) 		/* Turn on. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) 		ha->beacon_color_state = QLA_LED_ALL_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) 		*pflags = GPDX_LED_YELLOW_ON | GPDX_LED_AMBER_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) qla24xx_beacon_blink(struct scsi_qla_host *vha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) 	uint16_t led_color = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) 	uint32_t gpio_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) 	struct qla_hw_data *ha = vha->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) 	struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) 	/* Save the Original GPIOD. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) 	spin_lock_irqsave(&ha->hardware_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) 	gpio_data = rd_reg_dword(&reg->gpiod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) 	/* Enable the gpio_data reg for update. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) 	gpio_data |= GPDX_LED_UPDATE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) 	wrt_reg_dword(&reg->gpiod, gpio_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) 	gpio_data = rd_reg_dword(&reg->gpiod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) 	/* Set the color bits. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) 	qla24xx_flip_colors(ha, &led_color);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) 	/* Clear out any previously set LED color. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) 	gpio_data &= ~GPDX_LED_COLOR_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) 	/* Set the new input LED color to GPIOD. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) 	gpio_data |= led_color;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) 	/* Set the modified gpio_data values. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) 	wrt_reg_dword(&reg->gpiod, gpio_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) 	gpio_data = rd_reg_dword(&reg->gpiod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) static uint32_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) qla83xx_select_led_port(struct qla_hw_data *ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) 	uint32_t led_select_value = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) 	if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) 	if (ha->port_no == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) 		led_select_value = QLA83XX_LED_PORT0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) 		led_select_value = QLA83XX_LED_PORT1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) 	return led_select_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) qla83xx_beacon_blink(struct scsi_qla_host *vha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) 	uint32_t led_select_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) 	struct qla_hw_data *ha = vha->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) 	uint16_t led_cfg[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) 	uint16_t orig_led_cfg[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) 	uint32_t led_10_value, led_43_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) 	if (!IS_QLA83XX(ha) && !IS_QLA81XX(ha) && !IS_QLA27XX(ha) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) 	    !IS_QLA28XX(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) 	if (!ha->beacon_blink_led)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) 	if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) 		qla2x00_write_ram_word(vha, 0x1003, 0x40000230);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) 		qla2x00_write_ram_word(vha, 0x1004, 0x40000230);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) 	} else if (IS_QLA2031(ha)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) 		led_select_value = qla83xx_select_led_port(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) 		qla83xx_wr_reg(vha, led_select_value, 0x40000230);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) 		qla83xx_wr_reg(vha, led_select_value + 4, 0x40000230);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) 	} else if (IS_QLA8031(ha)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) 		led_select_value = qla83xx_select_led_port(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) 		qla83xx_rd_reg(vha, led_select_value, &led_10_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) 		qla83xx_rd_reg(vha, led_select_value + 0x10, &led_43_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) 		qla83xx_wr_reg(vha, led_select_value, 0x01f44000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) 		msleep(500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) 		qla83xx_wr_reg(vha, led_select_value, 0x400001f4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) 		msleep(1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) 		qla83xx_wr_reg(vha, led_select_value, led_10_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) 		qla83xx_wr_reg(vha, led_select_value + 0x10, led_43_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) 	} else if (IS_QLA81XX(ha)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) 		int rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) 		/* Save Current */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) 		rval = qla81xx_get_led_config(vha, orig_led_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) 		/* Do the blink */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) 		if (rval == QLA_SUCCESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) 			if (IS_QLA81XX(ha)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) 				led_cfg[0] = 0x4000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) 				led_cfg[1] = 0x2000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) 				led_cfg[2] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) 				led_cfg[3] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) 				led_cfg[4] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) 				led_cfg[5] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) 				led_cfg[0] = 0x4000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) 				led_cfg[1] = 0x4000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) 				led_cfg[2] = 0x4000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) 				led_cfg[3] = 0x2000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) 				led_cfg[4] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) 				led_cfg[5] = 0x2000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) 			rval = qla81xx_set_led_config(vha, led_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) 			msleep(1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) 			if (IS_QLA81XX(ha)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) 				led_cfg[0] = 0x4000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) 				led_cfg[1] = 0x2000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) 				led_cfg[2] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) 				led_cfg[0] = 0x4000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) 				led_cfg[1] = 0x2000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) 				led_cfg[2] = 0x4000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) 				led_cfg[3] = 0x4000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) 				led_cfg[4] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) 				led_cfg[5] = 0x2000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) 			rval = qla81xx_set_led_config(vha, led_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) 		/* On exit, restore original (presumes no status change) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) 		qla81xx_set_led_config(vha, orig_led_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) qla24xx_beacon_on(struct scsi_qla_host *vha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) 	uint32_t gpio_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) 	struct qla_hw_data *ha = vha->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) 	struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) 	if (IS_P3P_TYPE(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) 		return QLA_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) 	if (IS_QLA8031(ha) || IS_QLA81XX(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) 		goto skip_gpio; /* let blink handle it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) 	if (ha->beacon_blink_led == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) 		/* Enable firmware for update */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) 		ha->fw_options[1] |= ADD_FO1_DISABLE_GPIO_LED_CTRL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) 		if (qla2x00_set_fw_options(vha, ha->fw_options) != QLA_SUCCESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) 			return QLA_FUNCTION_FAILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) 		if (qla2x00_get_fw_options(vha, ha->fw_options) !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) 		    QLA_SUCCESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) 			ql_log(ql_log_warn, vha, 0x7009,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) 			    "Unable to update fw options (beacon on).\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) 			return QLA_FUNCTION_FAILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) 		if (IS_QLA2031(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) 			goto skip_gpio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) 		spin_lock_irqsave(&ha->hardware_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) 		gpio_data = rd_reg_dword(&reg->gpiod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) 		/* Enable the gpio_data reg for update. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) 		gpio_data |= GPDX_LED_UPDATE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) 		wrt_reg_dword(&reg->gpiod, gpio_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) 		rd_reg_dword(&reg->gpiod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) 		spin_unlock_irqrestore(&ha->hardware_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) 	/* So all colors blink together. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) 	ha->beacon_color_state = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) skip_gpio:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) 	/* Let the per HBA timer kick off the blinking process. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) 	ha->beacon_blink_led = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) 	return QLA_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) qla24xx_beacon_off(struct scsi_qla_host *vha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) 	uint32_t gpio_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) 	struct qla_hw_data *ha = vha->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) 	struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) 	if (IS_P3P_TYPE(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) 		return QLA_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) 	if (!ha->flags.fw_started)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) 		return QLA_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) 	ha->beacon_blink_led = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) 	if (IS_QLA2031(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) 		goto set_fw_options;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) 	if (IS_QLA8031(ha) || IS_QLA81XX(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) 		return QLA_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) 	ha->beacon_color_state = QLA_LED_ALL_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) 	ha->isp_ops->beacon_blink(vha);	/* Will flip to all off. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) 	/* Give control back to firmware. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) 	spin_lock_irqsave(&ha->hardware_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) 	gpio_data = rd_reg_dword(&reg->gpiod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) 	/* Disable the gpio_data reg for update. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) 	gpio_data &= ~GPDX_LED_UPDATE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) 	wrt_reg_dword(&reg->gpiod, gpio_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) 	rd_reg_dword(&reg->gpiod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) set_fw_options:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) 	ha->fw_options[1] &= ~ADD_FO1_DISABLE_GPIO_LED_CTRL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) 	if (qla2x00_set_fw_options(vha, ha->fw_options) != QLA_SUCCESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) 		ql_log(ql_log_warn, vha, 0x704d,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) 		    "Unable to update fw options (beacon on).\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) 		return QLA_FUNCTION_FAILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) 	if (qla2x00_get_fw_options(vha, ha->fw_options) != QLA_SUCCESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) 		ql_log(ql_log_warn, vha, 0x704e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) 		    "Unable to update fw options (beacon on).\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) 		return QLA_FUNCTION_FAILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) 	return QLA_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961)  * Flash support routines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965)  * qla2x00_flash_enable() - Setup flash for reading and writing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966)  * @ha: HA context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) qla2x00_flash_enable(struct qla_hw_data *ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) 	uint16_t data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) 	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) 	data = rd_reg_word(&reg->ctrl_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) 	data |= CSR_FLASH_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) 	wrt_reg_word(&reg->ctrl_status, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) 	rd_reg_word(&reg->ctrl_status);		/* PCI Posting. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981)  * qla2x00_flash_disable() - Disable flash and allow RISC to run.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982)  * @ha: HA context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) qla2x00_flash_disable(struct qla_hw_data *ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) 	uint16_t data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) 	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) 	data = rd_reg_word(&reg->ctrl_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) 	data &= ~(CSR_FLASH_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) 	wrt_reg_word(&reg->ctrl_status, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) 	rd_reg_word(&reg->ctrl_status);		/* PCI Posting. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997)  * qla2x00_read_flash_byte() - Reads a byte from flash
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998)  * @ha: HA context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999)  * @addr: Address in flash to read
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001)  * A word is read from the chip, but, only the lower byte is valid.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003)  * Returns the byte read from flash @addr.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) static uint8_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) qla2x00_read_flash_byte(struct qla_hw_data *ha, uint32_t addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) 	uint16_t data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) 	uint16_t bank_select;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) 	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) 	bank_select = rd_reg_word(&reg->ctrl_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) 	if (IS_QLA2322(ha) || IS_QLA6322(ha)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) 		/* Specify 64K address range: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) 		/*  clear out Module Select and Flash Address bits [19:16]. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) 		bank_select &= ~0xf8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018) 		bank_select |= addr >> 12 & 0xf0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) 		bank_select |= CSR_FLASH_64K_BANK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) 		wrt_reg_word(&reg->ctrl_status, bank_select);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) 		rd_reg_word(&reg->ctrl_status);	/* PCI Posting. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) 		wrt_reg_word(&reg->flash_address, (uint16_t)addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) 		data = rd_reg_word(&reg->flash_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) 		return (uint8_t)data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) 	/* Setup bit 16 of flash address. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) 	if ((addr & BIT_16) && ((bank_select & CSR_FLASH_64K_BANK) == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) 		bank_select |= CSR_FLASH_64K_BANK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) 		wrt_reg_word(&reg->ctrl_status, bank_select);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) 		rd_reg_word(&reg->ctrl_status);	/* PCI Posting. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) 	} else if (((addr & BIT_16) == 0) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035) 	    (bank_select & CSR_FLASH_64K_BANK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) 		bank_select &= ~(CSR_FLASH_64K_BANK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) 		wrt_reg_word(&reg->ctrl_status, bank_select);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038) 		rd_reg_word(&reg->ctrl_status);	/* PCI Posting. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041) 	/* Always perform IO mapped accesses to the FLASH registers. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) 	if (ha->pio_address) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043) 		uint16_t data2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) 		WRT_REG_WORD_PIO(PIO_REG(ha, flash_address), (uint16_t)addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046) 		do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) 			data = RD_REG_WORD_PIO(PIO_REG(ha, flash_data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) 			barrier();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) 			cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) 			data2 = RD_REG_WORD_PIO(PIO_REG(ha, flash_data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051) 		} while (data != data2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) 		wrt_reg_word(&reg->flash_address, (uint16_t)addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) 		data = qla2x00_debounce_register(&reg->flash_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) 	return (uint8_t)data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061)  * qla2x00_write_flash_byte() - Write a byte to flash
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062)  * @ha: HA context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063)  * @addr: Address in flash to write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064)  * @data: Data to write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) qla2x00_write_flash_byte(struct qla_hw_data *ha, uint32_t addr, uint8_t data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) 	uint16_t bank_select;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070) 	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072) 	bank_select = rd_reg_word(&reg->ctrl_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) 	if (IS_QLA2322(ha) || IS_QLA6322(ha)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) 		/* Specify 64K address range: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075) 		/*  clear out Module Select and Flash Address bits [19:16]. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) 		bank_select &= ~0xf8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) 		bank_select |= addr >> 12 & 0xf0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) 		bank_select |= CSR_FLASH_64K_BANK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) 		wrt_reg_word(&reg->ctrl_status, bank_select);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) 		rd_reg_word(&reg->ctrl_status);	/* PCI Posting. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082) 		wrt_reg_word(&reg->flash_address, (uint16_t)addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083) 		rd_reg_word(&reg->ctrl_status);		/* PCI Posting. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) 		wrt_reg_word(&reg->flash_data, (uint16_t)data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) 		rd_reg_word(&reg->ctrl_status);		/* PCI Posting. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090) 	/* Setup bit 16 of flash address. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) 	if ((addr & BIT_16) && ((bank_select & CSR_FLASH_64K_BANK) == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092) 		bank_select |= CSR_FLASH_64K_BANK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) 		wrt_reg_word(&reg->ctrl_status, bank_select);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) 		rd_reg_word(&reg->ctrl_status);	/* PCI Posting. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) 	} else if (((addr & BIT_16) == 0) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096) 	    (bank_select & CSR_FLASH_64K_BANK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097) 		bank_select &= ~(CSR_FLASH_64K_BANK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) 		wrt_reg_word(&reg->ctrl_status, bank_select);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) 		rd_reg_word(&reg->ctrl_status);	/* PCI Posting. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) 	/* Always perform IO mapped accesses to the FLASH registers. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103) 	if (ha->pio_address) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) 		WRT_REG_WORD_PIO(PIO_REG(ha, flash_address), (uint16_t)addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) 		WRT_REG_WORD_PIO(PIO_REG(ha, flash_data), (uint16_t)data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107) 		wrt_reg_word(&reg->flash_address, (uint16_t)addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108) 		rd_reg_word(&reg->ctrl_status);		/* PCI Posting. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109) 		wrt_reg_word(&reg->flash_data, (uint16_t)data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) 		rd_reg_word(&reg->ctrl_status);		/* PCI Posting. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115)  * qla2x00_poll_flash() - Polls flash for completion.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116)  * @ha: HA context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117)  * @addr: Address in flash to poll
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118)  * @poll_data: Data to be polled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119)  * @man_id: Flash manufacturer ID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120)  * @flash_id: Flash ID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122)  * This function polls the device until bit 7 of what is read matches data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123)  * bit 7 or until data bit 5 becomes a 1.  If that hapens, the flash ROM timed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124)  * out (a fatal error).  The flash book recommeds reading bit 7 again after
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125)  * reading bit 5 as a 1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127)  * Returns 0 on success, else non-zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130) qla2x00_poll_flash(struct qla_hw_data *ha, uint32_t addr, uint8_t poll_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131)     uint8_t man_id, uint8_t flash_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133) 	int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134) 	uint8_t flash_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) 	uint32_t cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137) 	status = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139) 	/* Wait for 30 seconds for command to finish. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140) 	poll_data &= BIT_7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141) 	for (cnt = 3000000; cnt; cnt--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142) 		flash_data = qla2x00_read_flash_byte(ha, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) 		if ((flash_data & BIT_7) == poll_data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144) 			status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148) 		if (man_id != 0x40 && man_id != 0xda) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) 			if ((flash_data & BIT_5) && cnt > 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) 				cnt = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152) 		udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153) 		barrier();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) 		cond_resched();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) 	return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160)  * qla2x00_program_flash_address() - Programs a flash address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161)  * @ha: HA context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162)  * @addr: Address in flash to program
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163)  * @data: Data to be written in flash
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164)  * @man_id: Flash manufacturer ID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165)  * @flash_id: Flash ID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167)  * Returns 0 on success, else non-zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170) qla2x00_program_flash_address(struct qla_hw_data *ha, uint32_t addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171)     uint8_t data, uint8_t man_id, uint8_t flash_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173) 	/* Write Program Command Sequence. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) 	if (IS_OEM_001(ha)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175) 		qla2x00_write_flash_byte(ha, 0xaaa, 0xaa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176) 		qla2x00_write_flash_byte(ha, 0x555, 0x55);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177) 		qla2x00_write_flash_byte(ha, 0xaaa, 0xa0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178) 		qla2x00_write_flash_byte(ha, addr, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180) 		if (man_id == 0xda && flash_id == 0xc1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181) 			qla2x00_write_flash_byte(ha, addr, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182) 			if (addr & 0x7e)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183) 				return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185) 			qla2x00_write_flash_byte(ha, 0x5555, 0xaa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186) 			qla2x00_write_flash_byte(ha, 0x2aaa, 0x55);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187) 			qla2x00_write_flash_byte(ha, 0x5555, 0xa0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188) 			qla2x00_write_flash_byte(ha, addr, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192) 	udelay(150);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194) 	/* Wait for write to complete. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195) 	return qla2x00_poll_flash(ha, addr, data, man_id, flash_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199)  * qla2x00_erase_flash() - Erase the flash.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200)  * @ha: HA context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201)  * @man_id: Flash manufacturer ID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202)  * @flash_id: Flash ID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204)  * Returns 0 on success, else non-zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207) qla2x00_erase_flash(struct qla_hw_data *ha, uint8_t man_id, uint8_t flash_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209) 	/* Individual Sector Erase Command Sequence */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210) 	if (IS_OEM_001(ha)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211) 		qla2x00_write_flash_byte(ha, 0xaaa, 0xaa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212) 		qla2x00_write_flash_byte(ha, 0x555, 0x55);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213) 		qla2x00_write_flash_byte(ha, 0xaaa, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214) 		qla2x00_write_flash_byte(ha, 0xaaa, 0xaa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215) 		qla2x00_write_flash_byte(ha, 0x555, 0x55);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216) 		qla2x00_write_flash_byte(ha, 0xaaa, 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218) 		qla2x00_write_flash_byte(ha, 0x5555, 0xaa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219) 		qla2x00_write_flash_byte(ha, 0x2aaa, 0x55);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220) 		qla2x00_write_flash_byte(ha, 0x5555, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221) 		qla2x00_write_flash_byte(ha, 0x5555, 0xaa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222) 		qla2x00_write_flash_byte(ha, 0x2aaa, 0x55);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223) 		qla2x00_write_flash_byte(ha, 0x5555, 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226) 	udelay(150);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228) 	/* Wait for erase to complete. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229) 	return qla2x00_poll_flash(ha, 0x00, 0x80, man_id, flash_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2233)  * qla2x00_erase_flash_sector() - Erase a flash sector.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2234)  * @ha: HA context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2235)  * @addr: Flash sector to erase
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2236)  * @sec_mask: Sector address mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2237)  * @man_id: Flash manufacturer ID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2238)  * @flash_id: Flash ID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2239)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2240)  * Returns 0 on success, else non-zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2241)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2242) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2243) qla2x00_erase_flash_sector(struct qla_hw_data *ha, uint32_t addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2244)     uint32_t sec_mask, uint8_t man_id, uint8_t flash_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2245) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2246) 	/* Individual Sector Erase Command Sequence */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2247) 	qla2x00_write_flash_byte(ha, 0x5555, 0xaa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2248) 	qla2x00_write_flash_byte(ha, 0x2aaa, 0x55);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2249) 	qla2x00_write_flash_byte(ha, 0x5555, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2250) 	qla2x00_write_flash_byte(ha, 0x5555, 0xaa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2251) 	qla2x00_write_flash_byte(ha, 0x2aaa, 0x55);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2252) 	if (man_id == 0x1f && flash_id == 0x13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2253) 		qla2x00_write_flash_byte(ha, addr & sec_mask, 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2254) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2255) 		qla2x00_write_flash_byte(ha, addr & sec_mask, 0x30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2256) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2257) 	udelay(150);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2258) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2259) 	/* Wait for erase to complete. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2260) 	return qla2x00_poll_flash(ha, addr, 0x80, man_id, flash_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2262) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2263) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2264)  * qla2x00_get_flash_manufacturer() - Read manufacturer ID from flash chip.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2265)  * @ha: host adapter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2266)  * @man_id: Flash manufacturer ID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2267)  * @flash_id: Flash ID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2268)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2269) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2270) qla2x00_get_flash_manufacturer(struct qla_hw_data *ha, uint8_t *man_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2271)     uint8_t *flash_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2272) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2273) 	qla2x00_write_flash_byte(ha, 0x5555, 0xaa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2274) 	qla2x00_write_flash_byte(ha, 0x2aaa, 0x55);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2275) 	qla2x00_write_flash_byte(ha, 0x5555, 0x90);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2276) 	*man_id = qla2x00_read_flash_byte(ha, 0x0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2277) 	*flash_id = qla2x00_read_flash_byte(ha, 0x0001);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2278) 	qla2x00_write_flash_byte(ha, 0x5555, 0xaa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2279) 	qla2x00_write_flash_byte(ha, 0x2aaa, 0x55);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2280) 	qla2x00_write_flash_byte(ha, 0x5555, 0xf0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2282) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2283) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2284) qla2x00_read_flash_data(struct qla_hw_data *ha, uint8_t *tmp_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2285) 	uint32_t saddr, uint32_t length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2286) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2287) 	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2288) 	uint32_t midpoint, ilength;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2289) 	uint8_t data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2290) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2291) 	midpoint = length / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2292) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2293) 	wrt_reg_word(&reg->nvram, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294) 	rd_reg_word(&reg->nvram);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2295) 	for (ilength = 0; ilength < length; saddr++, ilength++, tmp_buf++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2296) 		if (ilength == midpoint) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2297) 			wrt_reg_word(&reg->nvram, NVR_SELECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298) 			rd_reg_word(&reg->nvram);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2299) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2300) 		data = qla2x00_read_flash_byte(ha, saddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2301) 		if (saddr % 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2302) 			udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2303) 		*tmp_buf = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2304) 		cond_resched();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2305) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2307) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2308) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2309) qla2x00_suspend_hba(struct scsi_qla_host *vha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2310) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2311) 	int cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2312) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2313) 	struct qla_hw_data *ha = vha->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2314) 	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2315) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2316) 	/* Suspend HBA. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2317) 	scsi_block_requests(vha->host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2318) 	ha->isp_ops->disable_intrs(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2319) 	set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2320) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2321) 	/* Pause RISC. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2322) 	spin_lock_irqsave(&ha->hardware_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2323) 	wrt_reg_word(&reg->hccr, HCCR_PAUSE_RISC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2324) 	rd_reg_word(&reg->hccr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2325) 	if (IS_QLA2100(ha) || IS_QLA2200(ha) || IS_QLA2300(ha)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2326) 		for (cnt = 0; cnt < 30000; cnt++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2327) 			if ((rd_reg_word(&reg->hccr) & HCCR_RISC_PAUSE) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2328) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2329) 			udelay(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2330) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2331) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2332) 		udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2333) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2334) 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2336) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2337) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2338) qla2x00_resume_hba(struct scsi_qla_host *vha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2339) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2340) 	struct qla_hw_data *ha = vha->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2341) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2342) 	/* Resume HBA. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2343) 	clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2344) 	set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2345) 	qla2xxx_wake_dpc(vha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2346) 	qla2x00_wait_for_chip_reset(vha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2347) 	scsi_unblock_requests(vha->host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2348) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2349) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2350) void *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2351) qla2x00_read_optrom_data(struct scsi_qla_host *vha, void *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2352)     uint32_t offset, uint32_t length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2353) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2354) 	uint32_t addr, midpoint;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2355) 	uint8_t *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2356) 	struct qla_hw_data *ha = vha->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2357) 	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2358) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2359) 	/* Suspend HBA. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2360) 	qla2x00_suspend_hba(vha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2361) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2362) 	/* Go with read. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2363) 	midpoint = ha->optrom_size / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2364) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2365) 	qla2x00_flash_enable(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2366) 	wrt_reg_word(&reg->nvram, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2367) 	rd_reg_word(&reg->nvram);		/* PCI Posting. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2368) 	for (addr = offset, data = buf; addr < length; addr++, data++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2369) 		if (addr == midpoint) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2370) 			wrt_reg_word(&reg->nvram, NVR_SELECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2371) 			rd_reg_word(&reg->nvram);	/* PCI Posting. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2372) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2373) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2374) 		*data = qla2x00_read_flash_byte(ha, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2375) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2376) 	qla2x00_flash_disable(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2377) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2378) 	/* Resume HBA. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2379) 	qla2x00_resume_hba(vha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2380) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2381) 	return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2383) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2384) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2385) qla2x00_write_optrom_data(struct scsi_qla_host *vha, void *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2386)     uint32_t offset, uint32_t length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2387) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2388) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2389) 	int rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2390) 	uint8_t man_id, flash_id, sec_number, *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2391) 	uint16_t wd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2392) 	uint32_t addr, liter, sec_mask, rest_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2393) 	struct qla_hw_data *ha = vha->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2394) 	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2395) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2396) 	/* Suspend HBA. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2397) 	qla2x00_suspend_hba(vha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2398) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2399) 	rval = QLA_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2400) 	sec_number = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2401) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2402) 	/* Reset ISP chip. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2403) 	wrt_reg_word(&reg->ctrl_status, CSR_ISP_SOFT_RESET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2404) 	pci_read_config_word(ha->pdev, PCI_COMMAND, &wd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2405) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2406) 	/* Go with write. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2407) 	qla2x00_flash_enable(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2408) 	do {	/* Loop once to provide quick error exit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2409) 		/* Structure of flash memory based on manufacturer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2410) 		if (IS_OEM_001(ha)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2411) 			/* OEM variant with special flash part. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2412) 			man_id = flash_id = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2413) 			rest_addr = 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2414) 			sec_mask   = 0x10000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2415) 			goto update_flash;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2416) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2417) 		qla2x00_get_flash_manufacturer(ha, &man_id, &flash_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2418) 		switch (man_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2419) 		case 0x20: /* ST flash. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2420) 			if (flash_id == 0xd2 || flash_id == 0xe3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2421) 				/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2422) 				 * ST m29w008at part - 64kb sector size with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2423) 				 * 32kb,8kb,8kb,16kb sectors at memory address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2424) 				 * 0xf0000.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2425) 				 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2426) 				rest_addr = 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2427) 				sec_mask = 0x10000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2428) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2429) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2430) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2431) 			 * ST m29w010b part - 16kb sector size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2432) 			 * Default to 16kb sectors
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2433) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2434) 			rest_addr = 0x3fff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2435) 			sec_mask = 0x1c000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2436) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2437) 		case 0x40: /* Mostel flash. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2438) 			/* Mostel v29c51001 part - 512 byte sector size. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2439) 			rest_addr = 0x1ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2440) 			sec_mask = 0x1fe00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2441) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2442) 		case 0xbf: /* SST flash. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2443) 			/* SST39sf10 part - 4kb sector size. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2444) 			rest_addr = 0xfff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2445) 			sec_mask = 0x1f000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2446) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2447) 		case 0xda: /* Winbond flash. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2448) 			/* Winbond W29EE011 part - 256 byte sector size. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2449) 			rest_addr = 0x7f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2450) 			sec_mask = 0x1ff80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2451) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2452) 		case 0xc2: /* Macronix flash. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2453) 			/* 64k sector size. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2454) 			if (flash_id == 0x38 || flash_id == 0x4f) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2455) 				rest_addr = 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2456) 				sec_mask = 0x10000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2457) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2458) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2459) 			fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2460) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2461) 		case 0x1f: /* Atmel flash. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2462) 			/* 512k sector size. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2463) 			if (flash_id == 0x13) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2464) 				rest_addr = 0x7fffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2465) 				sec_mask =   0x80000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2466) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2467) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2468) 			fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2469) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2470) 		case 0x01: /* AMD flash. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2471) 			if (flash_id == 0x38 || flash_id == 0x40 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2472) 			    flash_id == 0x4f) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2473) 				/* Am29LV081 part - 64kb sector size. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2474) 				/* Am29LV002BT part - 64kb sector size. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2475) 				rest_addr = 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2476) 				sec_mask = 0x10000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2477) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2478) 			} else if (flash_id == 0x3e) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2479) 				/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2480) 				 * Am29LV008b part - 64kb sector size with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2481) 				 * 32kb,8kb,8kb,16kb sector at memory address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2482) 				 * h0xf0000.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2483) 				 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2484) 				rest_addr = 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2485) 				sec_mask = 0x10000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2486) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2487) 			} else if (flash_id == 0x20 || flash_id == 0x6e) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2488) 				/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2489) 				 * Am29LV010 part or AM29f010 - 16kb sector
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2490) 				 * size.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2491) 				 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2492) 				rest_addr = 0x3fff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2493) 				sec_mask = 0x1c000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2494) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2495) 			} else if (flash_id == 0x6d) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2496) 				/* Am29LV001 part - 8kb sector size. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2497) 				rest_addr = 0x1fff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2498) 				sec_mask = 0x1e000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2499) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2500) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2501) 			fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2502) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2503) 			/* Default to 16 kb sector size. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2504) 			rest_addr = 0x3fff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2505) 			sec_mask = 0x1c000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2506) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2507) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2508) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2509) update_flash:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2510) 		if (IS_QLA2322(ha) || IS_QLA6322(ha)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2511) 			if (qla2x00_erase_flash(ha, man_id, flash_id)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2512) 				rval = QLA_FUNCTION_FAILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2513) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2514) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2515) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2516) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2517) 		for (addr = offset, liter = 0; liter < length; liter++,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2518) 		    addr++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2519) 			data = buf + liter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2520) 			/* Are we at the beginning of a sector? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2521) 			if ((addr & rest_addr) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2522) 				if (IS_QLA2322(ha) || IS_QLA6322(ha)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2523) 					if (addr >= 0x10000UL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2524) 						if (((addr >> 12) & 0xf0) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2525) 						    ((man_id == 0x01 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2526) 							flash_id == 0x3e) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2527) 						     (man_id == 0x20 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2528) 							 flash_id == 0xd2))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2529) 							sec_number++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2530) 							if (sec_number == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2531) 								rest_addr =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2532) 								    0x7fff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2533) 								sec_mask =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2534) 								    0x18000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2535) 							} else if (
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2536) 							    sec_number == 2 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2537) 							    sec_number == 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2538) 								rest_addr =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2539) 								    0x1fff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2540) 								sec_mask =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2541) 								    0x1e000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2542) 							} else if (
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2543) 							    sec_number == 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2544) 								rest_addr =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2545) 								    0x3fff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2546) 								sec_mask =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2547) 								    0x1c000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2548) 							}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2549) 						}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2550) 					}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2551) 				} else if (addr == ha->optrom_size / 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2552) 					wrt_reg_word(&reg->nvram, NVR_SELECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2553) 					rd_reg_word(&reg->nvram);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2554) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2555) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2556) 				if (flash_id == 0xda && man_id == 0xc1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2557) 					qla2x00_write_flash_byte(ha, 0x5555,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2558) 					    0xaa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2559) 					qla2x00_write_flash_byte(ha, 0x2aaa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2560) 					    0x55);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2561) 					qla2x00_write_flash_byte(ha, 0x5555,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2562) 					    0xa0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2563) 				} else if (!IS_QLA2322(ha) && !IS_QLA6322(ha)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2564) 					/* Then erase it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2565) 					if (qla2x00_erase_flash_sector(ha,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2566) 					    addr, sec_mask, man_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2567) 					    flash_id)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2568) 						rval = QLA_FUNCTION_FAILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2569) 						break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2570) 					}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2571) 					if (man_id == 0x01 && flash_id == 0x6d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2572) 						sec_number++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2573) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2574) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2575) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2576) 			if (man_id == 0x01 && flash_id == 0x6d) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2577) 				if (sec_number == 1 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2578) 				    addr == (rest_addr - 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2579) 					rest_addr = 0x0fff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2580) 					sec_mask   = 0x1f000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2581) 				} else if (sec_number == 3 && (addr & 0x7ffe)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2582) 					rest_addr = 0x3fff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2583) 					sec_mask   = 0x1c000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2584) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2585) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2586) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2587) 			if (qla2x00_program_flash_address(ha, addr, *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2588) 			    man_id, flash_id)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2589) 				rval = QLA_FUNCTION_FAILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2590) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2591) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2592) 			cond_resched();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2593) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2594) 	} while (0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2595) 	qla2x00_flash_disable(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2596) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2597) 	/* Resume HBA. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2598) 	qla2x00_resume_hba(vha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2599) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2600) 	return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2601) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2602) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2603) void *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2604) qla24xx_read_optrom_data(struct scsi_qla_host *vha, void *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2605)     uint32_t offset, uint32_t length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2606) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2607) 	struct qla_hw_data *ha = vha->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2608) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2609) 	/* Suspend HBA. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2610) 	scsi_block_requests(vha->host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2611) 	set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2612) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2613) 	/* Go with read. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2614) 	qla24xx_read_flash_data(vha, buf, offset >> 2, length >> 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2615) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2616) 	/* Resume HBA. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2617) 	clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2618) 	scsi_unblock_requests(vha->host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2619) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2620) 	return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2621) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2622) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2623) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2624) qla28xx_extract_sfub_and_verify(struct scsi_qla_host *vha, uint32_t *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2625)     uint32_t len, uint32_t buf_size_without_sfub, uint8_t *sfub_buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2626) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2627) 	uint32_t *p, check_sum = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2628) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2629) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2630) 	p = buf + buf_size_without_sfub;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2631) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2632) 	/* Extract SFUB from end of file */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2633) 	memcpy(sfub_buf, (uint8_t *)p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2634) 	    sizeof(struct secure_flash_update_block));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2635) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2636) 	for (i = 0; i < (sizeof(struct secure_flash_update_block) >> 2); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2637) 		check_sum += p[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2638) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2639) 	check_sum = (~check_sum) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2640) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2641) 	if (check_sum != p[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2642) 		ql_log(ql_log_warn, vha, 0x7097,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2643) 		    "SFUB checksum failed, 0x%x, 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2644) 		    check_sum, p[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2645) 		return QLA_COMMAND_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2646) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2647) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2648) 	return QLA_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2649) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2650) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2651) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2652) qla28xx_get_flash_region(struct scsi_qla_host *vha, uint32_t start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2653)     struct qla_flt_region *region)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2654) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2655) 	struct qla_hw_data *ha = vha->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2656) 	struct qla_flt_header *flt = ha->flt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2657) 	struct qla_flt_region *flt_reg = &flt->region[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2658) 	uint16_t cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2659) 	int rval = QLA_FUNCTION_FAILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2660) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2661) 	if (!ha->flt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2662) 		return QLA_FUNCTION_FAILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2663) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2664) 	cnt = le16_to_cpu(flt->length) / sizeof(struct qla_flt_region);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2665) 	for (; cnt; cnt--, flt_reg++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2666) 		if (le32_to_cpu(flt_reg->start) == start) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2667) 			memcpy((uint8_t *)region, flt_reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2668) 			    sizeof(struct qla_flt_region));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2669) 			rval = QLA_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2670) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2671) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2672) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2673) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2674) 	return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2675) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2676) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2677) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2678) qla28xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2679)     uint32_t dwords)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2680) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2681) 	struct qla_hw_data *ha = vha->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2682) 	ulong liter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2683) 	ulong dburst = OPTROM_BURST_DWORDS; /* burst size in dwords */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2684) 	uint32_t sec_mask, rest_addr, fdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2685) 	void *optrom = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2686) 	dma_addr_t optrom_dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2687) 	int rval, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2688) 	struct secure_flash_update_block *sfub;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2689) 	dma_addr_t sfub_dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2690) 	uint32_t offset = faddr << 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2691) 	uint32_t buf_size_without_sfub = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2692) 	struct qla_flt_region region;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2693) 	bool reset_to_rom = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2694) 	uint32_t risc_size, risc_attr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2695) 	__be32 *fw_array = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2696) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2697) 	/* Retrieve region info - must be a start address passed in */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2698) 	rval = qla28xx_get_flash_region(vha, offset, &region);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2699) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2700) 	if (rval != QLA_SUCCESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2701) 		ql_log(ql_log_warn, vha, 0xffff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2702) 		    "Invalid address %x - not a region start address\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2703) 		    offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2704) 		goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2705) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2706) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2707) 	/* Allocate dma buffer for burst write */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2708) 	optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2709) 	    &optrom_dma, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2710) 	if (!optrom) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2711) 		ql_log(ql_log_warn, vha, 0x7095,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2712) 		    "Failed allocate burst (%x bytes)\n", OPTROM_BURST_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2713) 		rval = QLA_COMMAND_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2714) 		goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2715) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2716) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2717) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2718) 	 * If adapter supports secure flash and region is secure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2719) 	 * extract secure flash update block (SFUB) and verify
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2720) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2721) 	if (ha->flags.secure_adapter && region.attribute) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2722) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2723) 		ql_log(ql_log_warn + ql_dbg_verbose, vha, 0xffff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2724) 		    "Region %x is secure\n", region.code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2725) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2726) 		switch (le16_to_cpu(region.code)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2727) 		case FLT_REG_FW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2728) 		case FLT_REG_FW_SEC_27XX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2729) 		case FLT_REG_MPI_PRI_28XX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2730) 		case FLT_REG_MPI_SEC_28XX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2731) 			fw_array = (__force __be32 *)dwptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2732) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2733) 			/* 1st fw array */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2734) 			risc_size = be32_to_cpu(fw_array[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2735) 			risc_attr = be32_to_cpu(fw_array[9]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2736) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2737) 			buf_size_without_sfub = risc_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2738) 			fw_array += risc_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2739) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2740) 			/* 2nd fw array */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2741) 			risc_size = be32_to_cpu(fw_array[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2742) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2743) 			buf_size_without_sfub += risc_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2744) 			fw_array += risc_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2745) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2746) 			/* 1st dump template */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2747) 			risc_size = be32_to_cpu(fw_array[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2748) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2749) 			/* skip header and ignore checksum */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2750) 			buf_size_without_sfub += risc_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2751) 			fw_array += risc_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2752) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2753) 			if (risc_attr & BIT_9) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2754) 				/* 2nd dump template */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2755) 				risc_size = be32_to_cpu(fw_array[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2756) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2757) 				/* skip header and ignore checksum */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2758) 				buf_size_without_sfub += risc_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2759) 				fw_array += risc_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2760) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2761) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2762) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2763) 		case FLT_REG_PEP_PRI_28XX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2764) 		case FLT_REG_PEP_SEC_28XX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2765) 			fw_array = (__force __be32 *)dwptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2766) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2767) 			/* 1st fw array */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2768) 			risc_size = be32_to_cpu(fw_array[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2769) 			risc_attr = be32_to_cpu(fw_array[9]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2770) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2771) 			buf_size_without_sfub = risc_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2772) 			fw_array += risc_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2773) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2774) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2775) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2776) 			ql_log(ql_log_warn + ql_dbg_verbose, vha,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2777) 			    0xffff, "Secure region %x not supported\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2778) 			    region.code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2779) 			rval = QLA_COMMAND_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2780) 			goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2781) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2782) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2783) 		sfub = dma_alloc_coherent(&ha->pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2784) 			sizeof(struct secure_flash_update_block), &sfub_dma,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2785) 			GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2786) 		if (!sfub) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2787) 			ql_log(ql_log_warn, vha, 0xffff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2788) 			    "Unable to allocate memory for SFUB\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2789) 			rval = QLA_COMMAND_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2790) 			goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2791) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2792) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2793) 		rval = qla28xx_extract_sfub_and_verify(vha, dwptr, dwords,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2794) 			buf_size_without_sfub, (uint8_t *)sfub);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2795) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2796) 		if (rval != QLA_SUCCESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2797) 			goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2798) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2799) 		ql_log(ql_log_warn + ql_dbg_verbose, vha, 0xffff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2800) 		    "SFUB extract and verify successful\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2801) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2802) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2803) 	rest_addr = (ha->fdt_block_size >> 2) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2804) 	sec_mask = ~rest_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2805) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2806) 	/* Lock semaphore */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2807) 	rval = qla81xx_fac_semaphore_access(vha, FAC_SEMAPHORE_LOCK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2808) 	if (rval != QLA_SUCCESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2809) 		ql_log(ql_log_warn, vha, 0xffff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2810) 		    "Unable to lock flash semaphore.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2811) 		goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2812) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2813) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2814) 	ql_log(ql_log_warn + ql_dbg_verbose, vha, 0x7095,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2815) 	    "Unprotect flash...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2816) 	rval = qla24xx_unprotect_flash(vha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2817) 	if (rval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2818) 		qla81xx_fac_semaphore_access(vha, FAC_SEMAPHORE_UNLOCK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2819) 		ql_log(ql_log_warn, vha, 0x7096, "Failed unprotect flash\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2820) 		goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2821) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2822) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2823) 	for (liter = 0; liter < dwords; liter++, faddr++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2824) 		fdata = (faddr & sec_mask) << 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2825) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2826) 		/* If start of sector */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2827) 		if (!(faddr & rest_addr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2828) 			ql_log(ql_log_warn + ql_dbg_verbose, vha, 0x7095,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2829) 			    "Erase sector %#x...\n", faddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2830) 			rval = qla24xx_erase_sector(vha, fdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2831) 			if (rval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2832) 				ql_dbg(ql_dbg_user, vha, 0x7007,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2833) 				    "Failed erase sector %#x\n", faddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2834) 				goto write_protect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2835) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2836) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2837) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2838) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2839) 	if (ha->flags.secure_adapter) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2840) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2841) 		 * If adapter supports secure flash but FW doesn't,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2842) 		 * disable write protect, release semaphore and reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2843) 		 * chip to execute ROM code in order to update region securely
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2844) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2845) 		if (!ha->flags.secure_fw) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2846) 			ql_log(ql_log_warn + ql_dbg_verbose, vha, 0xffff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2847) 			    "Disable Write and Release Semaphore.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2848) 			rval = qla24xx_protect_flash(vha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2849) 			if (rval != QLA_SUCCESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2850) 				qla81xx_fac_semaphore_access(vha,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2851) 					FAC_SEMAPHORE_UNLOCK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2852) 				ql_log(ql_log_warn, vha, 0xffff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2853) 				    "Unable to protect flash.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2854) 				goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2855) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2856) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2857) 			ql_log(ql_log_warn + ql_dbg_verbose, vha, 0xffff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2858) 			    "Reset chip to ROM.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2859) 			set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2860) 			set_bit(ISP_ABORT_TO_ROM, &vha->dpc_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2861) 			qla2xxx_wake_dpc(vha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2862) 			rval = qla2x00_wait_for_chip_reset(vha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2863) 			if (rval != QLA_SUCCESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2864) 				ql_log(ql_log_warn, vha, 0xffff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2865) 				    "Unable to reset to ROM code.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2866) 				goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2867) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2868) 			reset_to_rom = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2869) 			ha->flags.fac_supported = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2870) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2871) 			ql_log(ql_log_warn + ql_dbg_verbose, vha, 0xffff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2872) 			    "Lock Semaphore");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2873) 			rval = qla2xxx_write_remote_register(vha,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2874) 			    FLASH_SEMAPHORE_REGISTER_ADDR, 0x00020002);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2875) 			if (rval != QLA_SUCCESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2876) 				ql_log(ql_log_warn, vha, 0xffff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2877) 				    "Unable to lock flash semaphore.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2878) 				goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2879) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2880) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2881) 			/* Unprotect flash */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2882) 			ql_log(ql_log_warn + ql_dbg_verbose, vha, 0xffff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2883) 			    "Enable Write.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2884) 			rval = qla2x00_write_ram_word(vha, 0x7ffd0101, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2885) 			if (rval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2886) 				ql_log(ql_log_warn, vha, 0x7096,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2887) 				    "Failed unprotect flash\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2888) 				goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2889) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2890) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2891) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2892) 		/* If region is secure, send Secure Flash MB Cmd */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2893) 		if (region.attribute && buf_size_without_sfub) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2894) 			ql_log(ql_log_warn + ql_dbg_verbose, vha, 0xffff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2895) 			    "Sending Secure Flash MB Cmd\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2896) 			rval = qla28xx_secure_flash_update(vha, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2897) 				le16_to_cpu(region.code),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2898) 				buf_size_without_sfub, sfub_dma,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2899) 				sizeof(struct secure_flash_update_block) >> 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2900) 			if (rval != QLA_SUCCESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2901) 				ql_log(ql_log_warn, vha, 0xffff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2902) 				    "Secure Flash MB Cmd failed %x.", rval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2903) 				goto write_protect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2904) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2905) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2906) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2907) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2908) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2909) 	/* re-init flash offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2910) 	faddr = offset >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2911) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2912) 	for (liter = 0; liter < dwords; liter++, faddr++, dwptr++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2913) 		fdata = (faddr & sec_mask) << 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2914) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2915) 		/* If smaller than a burst remaining */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2916) 		if (dwords - liter < dburst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2917) 			dburst = dwords - liter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2918) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2919) 		/* Copy to dma buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2920) 		memcpy(optrom, dwptr, dburst << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2921) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2922) 		/* Burst write */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2923) 		ql_log(ql_log_warn + ql_dbg_verbose, vha, 0x7095,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2924) 		    "Write burst (%#lx dwords)...\n", dburst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2925) 		rval = qla2x00_load_ram(vha, optrom_dma,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2926) 		    flash_data_addr(ha, faddr), dburst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2927) 		if (rval != QLA_SUCCESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2928) 			ql_log(ql_log_warn, vha, 0x7097,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2929) 			    "Failed burst write at %x (%p/%#llx)...\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2930) 			    flash_data_addr(ha, faddr), optrom,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2931) 			    (u64)optrom_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2932) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2933) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2934) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2935) 		liter += dburst - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2936) 		faddr += dburst - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2937) 		dwptr += dburst - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2938) 		continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2939) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2940) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2941) write_protect:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2942) 	ql_log(ql_log_warn + ql_dbg_verbose, vha, 0x7095,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2943) 	    "Protect flash...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2944) 	ret = qla24xx_protect_flash(vha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2945) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2946) 		qla81xx_fac_semaphore_access(vha, FAC_SEMAPHORE_UNLOCK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2947) 		ql_log(ql_log_warn, vha, 0x7099,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2948) 		    "Failed protect flash\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2949) 		rval = QLA_COMMAND_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2950) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2951) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2952) 	if (reset_to_rom == true) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2953) 		/* Schedule DPC to restart the RISC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2954) 		set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2955) 		qla2xxx_wake_dpc(vha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2956) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2957) 		ret = qla2x00_wait_for_hba_online(vha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2958) 		if (ret != QLA_SUCCESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2959) 			ql_log(ql_log_warn, vha, 0xffff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2960) 			    "Adapter did not come out of reset\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2961) 			rval = QLA_COMMAND_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2962) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2963) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2964) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2965) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2966) 	if (optrom)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2967) 		dma_free_coherent(&ha->pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2968) 		    OPTROM_BURST_SIZE, optrom, optrom_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2969) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2970) 	return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2971) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2972) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2973) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2974) qla24xx_write_optrom_data(struct scsi_qla_host *vha, void *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2975)     uint32_t offset, uint32_t length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2976) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2977) 	int rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2978) 	struct qla_hw_data *ha = vha->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2979) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2980) 	/* Suspend HBA. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2981) 	scsi_block_requests(vha->host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2982) 	set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2983) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2984) 	/* Go with write. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2985) 	if (IS_QLA28XX(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2986) 		rval = qla28xx_write_flash_data(vha, buf, offset >> 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2987) 						length >> 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2988) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2989) 		rval = qla24xx_write_flash_data(vha, buf, offset >> 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2990) 						length >> 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2991) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2992) 	clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2993) 	scsi_unblock_requests(vha->host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2994) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2995) 	return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2996) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2997) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2998) void *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2999) qla25xx_read_optrom_data(struct scsi_qla_host *vha, void *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3000)     uint32_t offset, uint32_t length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3001) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3002) 	int rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3003) 	dma_addr_t optrom_dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3004) 	void *optrom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3005) 	uint8_t *pbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3006) 	uint32_t faddr, left, burst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3007) 	struct qla_hw_data *ha = vha->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3008) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3009) 	if (IS_QLA25XX(ha) || IS_QLA81XX(ha) || IS_QLA83XX(ha) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3010) 	    IS_QLA27XX(ha) || IS_QLA28XX(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3011) 		goto try_fast;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3012) 	if (offset & 0xfff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3013) 		goto slow_read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3014) 	if (length < OPTROM_BURST_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3015) 		goto slow_read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3016) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3017) try_fast:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3018) 	if (offset & 0xff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3019) 		goto slow_read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3020) 	optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3021) 	    &optrom_dma, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3022) 	if (!optrom) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3023) 		ql_log(ql_log_warn, vha, 0x00cc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3024) 		    "Unable to allocate memory for optrom burst read (%x KB).\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3025) 		    OPTROM_BURST_SIZE / 1024);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3026) 		goto slow_read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3027) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3028) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3029) 	pbuf = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3030) 	faddr = offset >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3031) 	left = length >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3032) 	burst = OPTROM_BURST_DWORDS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3033) 	while (left != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3034) 		if (burst > left)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3035) 			burst = left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3036) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3037) 		rval = qla2x00_dump_ram(vha, optrom_dma,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3038) 		    flash_data_addr(ha, faddr), burst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3039) 		if (rval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3040) 			ql_log(ql_log_warn, vha, 0x00f5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3041) 			    "Unable to burst-read optrom segment (%x/%x/%llx).\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3042) 			    rval, flash_data_addr(ha, faddr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3043) 			    (unsigned long long)optrom_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3044) 			ql_log(ql_log_warn, vha, 0x00f6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3045) 			    "Reverting to slow-read.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3046) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3047) 			dma_free_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3048) 			    optrom, optrom_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3049) 			goto slow_read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3050) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3051) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3052) 		memcpy(pbuf, optrom, burst * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3053) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3054) 		left -= burst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3055) 		faddr += burst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3056) 		pbuf += burst * 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3057) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3058) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3059) 	dma_free_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE, optrom,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3060) 	    optrom_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3061) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3062) 	return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3063) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3064) slow_read:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3065)     return qla24xx_read_optrom_data(vha, buf, offset, length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3066) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3067) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3068) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3069)  * qla2x00_get_fcode_version() - Determine an FCODE image's version.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3070)  * @ha: HA context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3071)  * @pcids: Pointer to the FCODE PCI data structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3072)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3073)  * The process of retrieving the FCODE version information is at best
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3074)  * described as interesting.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3075)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3076)  * Within the first 100h bytes of the image an ASCII string is present
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3077)  * which contains several pieces of information including the FCODE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3078)  * version.  Unfortunately it seems the only reliable way to retrieve
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3079)  * the version is by scanning for another sentinel within the string,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3080)  * the FCODE build date:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3081)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3082)  *	... 2.00.02 10/17/02 ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3083)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3084)  * Returns QLA_SUCCESS on successful retrieval of version.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3085)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3086) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3087) qla2x00_get_fcode_version(struct qla_hw_data *ha, uint32_t pcids)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3088) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3089) 	int ret = QLA_FUNCTION_FAILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3090) 	uint32_t istart, iend, iter, vend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3091) 	uint8_t do_next, rbyte, *vbyte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3092) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3093) 	memset(ha->fcode_revision, 0, sizeof(ha->fcode_revision));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3094) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3095) 	/* Skip the PCI data structure. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3096) 	istart = pcids +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3097) 	    ((qla2x00_read_flash_byte(ha, pcids + 0x0B) << 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3098) 		qla2x00_read_flash_byte(ha, pcids + 0x0A));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3099) 	iend = istart + 0x100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3100) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3101) 		/* Scan for the sentinel date string...eeewww. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3102) 		do_next = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3103) 		iter = istart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3104) 		while ((iter < iend) && !do_next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3105) 			iter++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3106) 			if (qla2x00_read_flash_byte(ha, iter) == '/') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3107) 				if (qla2x00_read_flash_byte(ha, iter + 2) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3108) 				    '/')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3109) 					do_next++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3110) 				else if (qla2x00_read_flash_byte(ha,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3111) 				    iter + 3) == '/')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3112) 					do_next++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3113) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3114) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3115) 		if (!do_next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3116) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3117) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3118) 		/* Backtrack to previous ' ' (space). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3119) 		do_next = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3120) 		while ((iter > istart) && !do_next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3121) 			iter--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3122) 			if (qla2x00_read_flash_byte(ha, iter) == ' ')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3123) 				do_next++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3124) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3125) 		if (!do_next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3126) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3127) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3128) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3129) 		 * Mark end of version tag, and find previous ' ' (space) or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3130) 		 * string length (recent FCODE images -- major hack ahead!!!).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3131) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3132) 		vend = iter - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3133) 		do_next = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3134) 		while ((iter > istart) && !do_next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3135) 			iter--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3136) 			rbyte = qla2x00_read_flash_byte(ha, iter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3137) 			if (rbyte == ' ' || rbyte == 0xd || rbyte == 0x10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3138) 				do_next++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3139) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3140) 		if (!do_next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3141) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3142) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3143) 		/* Mark beginning of version tag, and copy data. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3144) 		iter++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3145) 		if ((vend - iter) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3146) 		    ((vend - iter) < sizeof(ha->fcode_revision))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3147) 			vbyte = ha->fcode_revision;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3148) 			while (iter <= vend) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3149) 				*vbyte++ = qla2x00_read_flash_byte(ha, iter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3150) 				iter++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3151) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3152) 			ret = QLA_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3153) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3154) 	} while (0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3155) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3156) 	if (ret != QLA_SUCCESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3157) 		memset(ha->fcode_revision, 0, sizeof(ha->fcode_revision));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3160) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3161) qla2x00_get_flash_version(scsi_qla_host_t *vha, void *mbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3162) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3163) 	int ret = QLA_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3164) 	uint8_t code_type, last_image;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3165) 	uint32_t pcihdr, pcids;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3166) 	uint8_t *dbyte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3167) 	uint16_t *dcode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3168) 	struct qla_hw_data *ha = vha->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3169) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3170) 	if (!ha->pio_address || !mbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3171) 		return QLA_FUNCTION_FAILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3173) 	memset(ha->bios_revision, 0, sizeof(ha->bios_revision));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3174) 	memset(ha->efi_revision, 0, sizeof(ha->efi_revision));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3175) 	memset(ha->fcode_revision, 0, sizeof(ha->fcode_revision));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3176) 	memset(ha->fw_revision, 0, sizeof(ha->fw_revision));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3177) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3178) 	qla2x00_flash_enable(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3179) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3180) 	/* Begin with first PCI expansion ROM header. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3181) 	pcihdr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3182) 	last_image = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3183) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3184) 		/* Verify PCI expansion ROM header. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3185) 		if (qla2x00_read_flash_byte(ha, pcihdr) != 0x55 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3186) 		    qla2x00_read_flash_byte(ha, pcihdr + 0x01) != 0xaa) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3187) 			/* No signature */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3188) 			ql_log(ql_log_fatal, vha, 0x0050,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3189) 			    "No matching ROM signature.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3190) 			ret = QLA_FUNCTION_FAILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3191) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3192) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3193) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3194) 		/* Locate PCI data structure. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3195) 		pcids = pcihdr +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3196) 		    ((qla2x00_read_flash_byte(ha, pcihdr + 0x19) << 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3197) 			qla2x00_read_flash_byte(ha, pcihdr + 0x18));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3198) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3199) 		/* Validate signature of PCI data structure. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3200) 		if (qla2x00_read_flash_byte(ha, pcids) != 'P' ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3201) 		    qla2x00_read_flash_byte(ha, pcids + 0x1) != 'C' ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3202) 		    qla2x00_read_flash_byte(ha, pcids + 0x2) != 'I' ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3203) 		    qla2x00_read_flash_byte(ha, pcids + 0x3) != 'R') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3204) 			/* Incorrect header. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3205) 			ql_log(ql_log_fatal, vha, 0x0051,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3206) 			    "PCI data struct not found pcir_adr=%x.\n", pcids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3207) 			ret = QLA_FUNCTION_FAILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3208) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3209) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3210) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3211) 		/* Read version */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3212) 		code_type = qla2x00_read_flash_byte(ha, pcids + 0x14);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3213) 		switch (code_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3214) 		case ROM_CODE_TYPE_BIOS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3215) 			/* Intel x86, PC-AT compatible. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3216) 			ha->bios_revision[0] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3217) 			    qla2x00_read_flash_byte(ha, pcids + 0x12);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3218) 			ha->bios_revision[1] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3219) 			    qla2x00_read_flash_byte(ha, pcids + 0x13);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3220) 			ql_dbg(ql_dbg_init, vha, 0x0052,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3221) 			    "Read BIOS %d.%d.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3222) 			    ha->bios_revision[1], ha->bios_revision[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3223) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3224) 		case ROM_CODE_TYPE_FCODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3225) 			/* Open Firmware standard for PCI (FCode). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3226) 			/* Eeeewww... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3227) 			qla2x00_get_fcode_version(ha, pcids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3228) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3229) 		case ROM_CODE_TYPE_EFI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3230) 			/* Extensible Firmware Interface (EFI). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3231) 			ha->efi_revision[0] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3232) 			    qla2x00_read_flash_byte(ha, pcids + 0x12);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3233) 			ha->efi_revision[1] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3234) 			    qla2x00_read_flash_byte(ha, pcids + 0x13);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3235) 			ql_dbg(ql_dbg_init, vha, 0x0053,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3236) 			    "Read EFI %d.%d.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3237) 			    ha->efi_revision[1], ha->efi_revision[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3238) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3239) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3240) 			ql_log(ql_log_warn, vha, 0x0054,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3241) 			    "Unrecognized code type %x at pcids %x.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3242) 			    code_type, pcids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3243) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3244) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3245) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3246) 		last_image = qla2x00_read_flash_byte(ha, pcids + 0x15) & BIT_7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3247) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3248) 		/* Locate next PCI expansion ROM. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3249) 		pcihdr += ((qla2x00_read_flash_byte(ha, pcids + 0x11) << 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3250) 		    qla2x00_read_flash_byte(ha, pcids + 0x10)) * 512;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3251) 	} while (!last_image);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3252) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3253) 	if (IS_QLA2322(ha)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3254) 		/* Read firmware image information. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3255) 		memset(ha->fw_revision, 0, sizeof(ha->fw_revision));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3256) 		dbyte = mbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3257) 		memset(dbyte, 0, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3258) 		dcode = (uint16_t *)dbyte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3259) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3260) 		qla2x00_read_flash_data(ha, dbyte, ha->flt_region_fw * 4 + 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3261) 		    8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3262) 		ql_dbg(ql_dbg_init + ql_dbg_buffer, vha, 0x010a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3263) 		    "Dumping fw "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3264) 		    "ver from flash:.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3265) 		ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x010b,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3266) 		    dbyte, 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3267) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3268) 		if ((dcode[0] == 0xffff && dcode[1] == 0xffff &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3269) 		    dcode[2] == 0xffff && dcode[3] == 0xffff) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3270) 		    (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3271) 		    dcode[3] == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3272) 			ql_log(ql_log_warn, vha, 0x0057,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3273) 			    "Unrecognized fw revision at %x.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3274) 			    ha->flt_region_fw * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3275) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3276) 			/* values are in big endian */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3277) 			ha->fw_revision[0] = dbyte[0] << 16 | dbyte[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3278) 			ha->fw_revision[1] = dbyte[2] << 16 | dbyte[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3279) 			ha->fw_revision[2] = dbyte[4] << 16 | dbyte[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3280) 			ql_dbg(ql_dbg_init, vha, 0x0058,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3281) 			    "FW Version: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3282) 			    "%d.%d.%d.\n", ha->fw_revision[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3283) 			    ha->fw_revision[1], ha->fw_revision[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3284) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3285) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3286) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3287) 	qla2x00_flash_disable(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3288) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3289) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3291) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3292) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3293) qla82xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3294) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3295) 	int ret = QLA_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3296) 	uint32_t pcihdr, pcids;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3297) 	uint32_t *dcode = mbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3298) 	uint8_t *bcode = mbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3299) 	uint8_t code_type, last_image;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3300) 	struct qla_hw_data *ha = vha->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3301) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3302) 	if (!mbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3303) 		return QLA_FUNCTION_FAILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3304) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3305) 	memset(ha->bios_revision, 0, sizeof(ha->bios_revision));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3306) 	memset(ha->efi_revision, 0, sizeof(ha->efi_revision));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3307) 	memset(ha->fcode_revision, 0, sizeof(ha->fcode_revision));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3308) 	memset(ha->fw_revision, 0, sizeof(ha->fw_revision));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3309) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3310) 	/* Begin with first PCI expansion ROM header. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3311) 	pcihdr = ha->flt_region_boot << 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3312) 	last_image = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3313) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3314) 		/* Verify PCI expansion ROM header. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3315) 		ha->isp_ops->read_optrom(vha, dcode, pcihdr, 0x20 * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3316) 		bcode = mbuf + (pcihdr % 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3317) 		if (memcmp(bcode, "\x55\xaa", 2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3318) 			/* No signature */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3319) 			ql_log(ql_log_fatal, vha, 0x0154,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3320) 			    "No matching ROM signature.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3321) 			ret = QLA_FUNCTION_FAILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3322) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3323) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3324) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3325) 		/* Locate PCI data structure. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3326) 		pcids = pcihdr + ((bcode[0x19] << 8) | bcode[0x18]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3327) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3328) 		ha->isp_ops->read_optrom(vha, dcode, pcids, 0x20 * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3329) 		bcode = mbuf + (pcihdr % 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3330) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3331) 		/* Validate signature of PCI data structure. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3332) 		if (memcmp(bcode, "PCIR", 4)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3333) 			/* Incorrect header. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3334) 			ql_log(ql_log_fatal, vha, 0x0155,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3335) 			    "PCI data struct not found pcir_adr=%x.\n", pcids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3336) 			ret = QLA_FUNCTION_FAILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3337) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3338) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3339) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3340) 		/* Read version */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3341) 		code_type = bcode[0x14];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3342) 		switch (code_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3343) 		case ROM_CODE_TYPE_BIOS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3344) 			/* Intel x86, PC-AT compatible. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3345) 			ha->bios_revision[0] = bcode[0x12];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3346) 			ha->bios_revision[1] = bcode[0x13];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3347) 			ql_dbg(ql_dbg_init, vha, 0x0156,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3348) 			    "Read BIOS %d.%d.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3349) 			    ha->bios_revision[1], ha->bios_revision[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3350) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3351) 		case ROM_CODE_TYPE_FCODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3352) 			/* Open Firmware standard for PCI (FCode). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3353) 			ha->fcode_revision[0] = bcode[0x12];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3354) 			ha->fcode_revision[1] = bcode[0x13];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3355) 			ql_dbg(ql_dbg_init, vha, 0x0157,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3356) 			    "Read FCODE %d.%d.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3357) 			    ha->fcode_revision[1], ha->fcode_revision[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3358) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3359) 		case ROM_CODE_TYPE_EFI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3360) 			/* Extensible Firmware Interface (EFI). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3361) 			ha->efi_revision[0] = bcode[0x12];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3362) 			ha->efi_revision[1] = bcode[0x13];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3363) 			ql_dbg(ql_dbg_init, vha, 0x0158,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3364) 			    "Read EFI %d.%d.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3365) 			    ha->efi_revision[1], ha->efi_revision[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3366) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3367) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3368) 			ql_log(ql_log_warn, vha, 0x0159,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3369) 			    "Unrecognized code type %x at pcids %x.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3370) 			    code_type, pcids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3371) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3372) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3373) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3374) 		last_image = bcode[0x15] & BIT_7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3375) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3376) 		/* Locate next PCI expansion ROM. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3377) 		pcihdr += ((bcode[0x11] << 8) | bcode[0x10]) * 512;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3378) 	} while (!last_image);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3379) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3380) 	/* Read firmware image information. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3381) 	memset(ha->fw_revision, 0, sizeof(ha->fw_revision));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3382) 	dcode = mbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3383) 	ha->isp_ops->read_optrom(vha, dcode, ha->flt_region_fw << 2, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3384) 	bcode = mbuf + (pcihdr % 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3385) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3386) 	/* Validate signature of PCI data structure. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3387) 	if (bcode[0x0] == 0x3 && bcode[0x1] == 0x0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3388) 	    bcode[0x2] == 0x40 && bcode[0x3] == 0x40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3389) 		ha->fw_revision[0] = bcode[0x4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3390) 		ha->fw_revision[1] = bcode[0x5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3391) 		ha->fw_revision[2] = bcode[0x6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3392) 		ql_dbg(ql_dbg_init, vha, 0x0153,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3393) 		    "Firmware revision %d.%d.%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3394) 		    ha->fw_revision[0], ha->fw_revision[1],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3395) 		    ha->fw_revision[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3396) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3397) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3398) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3400) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3401) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3402) qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3403) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3404) 	int ret = QLA_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3405) 	uint32_t pcihdr = 0, pcids = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3406) 	uint32_t *dcode = mbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3407) 	uint8_t *bcode = mbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3408) 	uint8_t code_type, last_image;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3409) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3410) 	struct qla_hw_data *ha = vha->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3411) 	uint32_t faddr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3412) 	struct active_regions active_regions = { };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3413) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3414) 	if (IS_P3P_TYPE(ha))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3415) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3416) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3417) 	if (!mbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3418) 		return QLA_FUNCTION_FAILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3419) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3420) 	memset(ha->bios_revision, 0, sizeof(ha->bios_revision));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3421) 	memset(ha->efi_revision, 0, sizeof(ha->efi_revision));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3422) 	memset(ha->fcode_revision, 0, sizeof(ha->fcode_revision));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3423) 	memset(ha->fw_revision, 0, sizeof(ha->fw_revision));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3424) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3425) 	pcihdr = ha->flt_region_boot << 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3426) 	if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3427) 		qla27xx_get_active_image(vha, &active_regions);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3428) 		if (active_regions.global == QLA27XX_SECONDARY_IMAGE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3429) 			pcihdr = ha->flt_region_boot_sec << 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3430) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3431) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3432) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3433) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3434) 		/* Verify PCI expansion ROM header. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3435) 		qla24xx_read_flash_data(vha, dcode, pcihdr >> 2, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3436) 		bcode = mbuf + (pcihdr % 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3437) 		if (memcmp(bcode, "\x55\xaa", 2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3438) 			/* No signature */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3439) 			ql_log(ql_log_fatal, vha, 0x0059,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3440) 			    "No matching ROM signature.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3441) 			ret = QLA_FUNCTION_FAILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3442) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3443) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3444) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3445) 		/* Locate PCI data structure. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3446) 		pcids = pcihdr + ((bcode[0x19] << 8) | bcode[0x18]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3447) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3448) 		qla24xx_read_flash_data(vha, dcode, pcids >> 2, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3449) 		bcode = mbuf + (pcihdr % 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3450) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3451) 		/* Validate signature of PCI data structure. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3452) 		if (memcmp(bcode, "PCIR", 4)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3453) 			/* Incorrect header. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3454) 			ql_log(ql_log_fatal, vha, 0x005a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3455) 			    "PCI data struct not found pcir_adr=%x.\n", pcids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3456) 			ql_dump_buffer(ql_dbg_init, vha, 0x0059, dcode, 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3457) 			ret = QLA_FUNCTION_FAILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3458) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3459) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3460) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3461) 		/* Read version */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3462) 		code_type = bcode[0x14];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3463) 		switch (code_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3464) 		case ROM_CODE_TYPE_BIOS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3465) 			/* Intel x86, PC-AT compatible. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3466) 			ha->bios_revision[0] = bcode[0x12];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3467) 			ha->bios_revision[1] = bcode[0x13];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3468) 			ql_dbg(ql_dbg_init, vha, 0x005b,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3469) 			    "Read BIOS %d.%d.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3470) 			    ha->bios_revision[1], ha->bios_revision[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3471) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3472) 		case ROM_CODE_TYPE_FCODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3473) 			/* Open Firmware standard for PCI (FCode). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3474) 			ha->fcode_revision[0] = bcode[0x12];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3475) 			ha->fcode_revision[1] = bcode[0x13];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3476) 			ql_dbg(ql_dbg_init, vha, 0x005c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3477) 			    "Read FCODE %d.%d.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3478) 			    ha->fcode_revision[1], ha->fcode_revision[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3479) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3480) 		case ROM_CODE_TYPE_EFI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3481) 			/* Extensible Firmware Interface (EFI). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3482) 			ha->efi_revision[0] = bcode[0x12];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3483) 			ha->efi_revision[1] = bcode[0x13];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3484) 			ql_dbg(ql_dbg_init, vha, 0x005d,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3485) 			    "Read EFI %d.%d.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3486) 			    ha->efi_revision[1], ha->efi_revision[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3487) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3488) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3489) 			ql_log(ql_log_warn, vha, 0x005e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3490) 			    "Unrecognized code type %x at pcids %x.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3491) 			    code_type, pcids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3492) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3493) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3494) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3495) 		last_image = bcode[0x15] & BIT_7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3496) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3497) 		/* Locate next PCI expansion ROM. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3498) 		pcihdr += ((bcode[0x11] << 8) | bcode[0x10]) * 512;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3499) 	} while (!last_image);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3500) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3501) 	/* Read firmware image information. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3502) 	memset(ha->fw_revision, 0, sizeof(ha->fw_revision));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3503) 	faddr = ha->flt_region_fw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3504) 	if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3505) 		qla27xx_get_active_image(vha, &active_regions);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3506) 		if (active_regions.global == QLA27XX_SECONDARY_IMAGE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3507) 			faddr = ha->flt_region_fw_sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3508) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3509) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3510) 	qla24xx_read_flash_data(vha, dcode, faddr, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3511) 	if (qla24xx_risc_firmware_invalid(dcode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3512) 		ql_log(ql_log_warn, vha, 0x005f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3513) 		    "Unrecognized fw revision at %x.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3514) 		    ha->flt_region_fw * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3515) 		ql_dump_buffer(ql_dbg_init, vha, 0x005f, dcode, 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3516) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3517) 		for (i = 0; i < 4; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3518) 			ha->fw_revision[i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3519) 				be32_to_cpu((__force __be32)dcode[4+i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3520) 		ql_dbg(ql_dbg_init, vha, 0x0060,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3521) 		    "Firmware revision (flash) %u.%u.%u (%x).\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3522) 		    ha->fw_revision[0], ha->fw_revision[1],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3523) 		    ha->fw_revision[2], ha->fw_revision[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3524) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3525) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3526) 	/* Check for golden firmware and get version if available */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3527) 	if (!IS_QLA81XX(ha)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3528) 		/* Golden firmware is not present in non 81XX adapters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3529) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3530) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3531) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3532) 	memset(ha->gold_fw_version, 0, sizeof(ha->gold_fw_version));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3533) 	faddr = ha->flt_region_gold_fw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3534) 	qla24xx_read_flash_data(vha, dcode, ha->flt_region_gold_fw, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3535) 	if (qla24xx_risc_firmware_invalid(dcode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3536) 		ql_log(ql_log_warn, vha, 0x0056,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3537) 		    "Unrecognized golden fw at %#x.\n", faddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3538) 		ql_dump_buffer(ql_dbg_init, vha, 0x0056, dcode, 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3539) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3540) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3541) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3542) 	for (i = 0; i < 4; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3543) 		ha->gold_fw_version[i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3544) 			be32_to_cpu((__force __be32)dcode[4+i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3545) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3546) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3547) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3548) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3549) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3550) qla2xxx_is_vpd_valid(uint8_t *pos, uint8_t *end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3551) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3552) 	if (pos >= end || *pos != 0x82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3553) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3554) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3555) 	pos += 3 + pos[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3556) 	if (pos >= end || *pos != 0x90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3557) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3558) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3559) 	pos += 3 + pos[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3560) 	if (pos >= end || *pos != 0x78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3561) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3562) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3563) 	return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3564) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3565) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3566) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3567) qla2xxx_get_vpd_field(scsi_qla_host_t *vha, char *key, char *str, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3568) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3569) 	struct qla_hw_data *ha = vha->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3570) 	uint8_t *pos = ha->vpd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3571) 	uint8_t *end = pos + ha->vpd_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3572) 	int len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3573) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3574) 	if (!IS_FWI2_CAPABLE(ha) || !qla2xxx_is_vpd_valid(pos, end))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3575) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3576) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3577) 	while (pos < end && *pos != 0x78) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3578) 		len = (*pos == 0x82) ? pos[1] : pos[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3579) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3580) 		if (!strncmp(pos, key, strlen(key)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3581) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3582) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3583) 		if (*pos != 0x90 && *pos != 0x91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3584) 			pos += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3585) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3586) 		pos += 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3587) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3588) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3589) 	if (pos < end - len && *pos != 0x78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3590) 		return scnprintf(str, size, "%.*s", len, pos + 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3591) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3592) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3593) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3594) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3595) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3596) qla24xx_read_fcp_prio_cfg(scsi_qla_host_t *vha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3597) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3598) 	int len, max_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3599) 	uint32_t fcp_prio_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3600) 	struct qla_hw_data *ha = vha->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3601) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3602) 	if (!ha->fcp_prio_cfg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3603) 		ha->fcp_prio_cfg = vmalloc(FCP_PRIO_CFG_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3604) 		if (!ha->fcp_prio_cfg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3605) 			ql_log(ql_log_warn, vha, 0x00d5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3606) 			    "Unable to allocate memory for fcp priority data (%x).\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3607) 			    FCP_PRIO_CFG_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3608) 			return QLA_FUNCTION_FAILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3609) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3610) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3611) 	memset(ha->fcp_prio_cfg, 0, FCP_PRIO_CFG_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3612) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3613) 	fcp_prio_addr = ha->flt_region_fcp_prio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3614) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3615) 	/* first read the fcp priority data header from flash */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3616) 	ha->isp_ops->read_optrom(vha, ha->fcp_prio_cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3617) 			fcp_prio_addr << 2, FCP_PRIO_CFG_HDR_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3618) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3619) 	if (!qla24xx_fcp_prio_cfg_valid(vha, ha->fcp_prio_cfg, 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3620) 		goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3621) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3622) 	/* read remaining FCP CMD config data from flash */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3623) 	fcp_prio_addr += (FCP_PRIO_CFG_HDR_SIZE >> 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3624) 	len = ha->fcp_prio_cfg->num_entries * sizeof(struct qla_fcp_prio_entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3625) 	max_len = FCP_PRIO_CFG_SIZE - FCP_PRIO_CFG_HDR_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3626) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3627) 	ha->isp_ops->read_optrom(vha, &ha->fcp_prio_cfg->entry[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3628) 			fcp_prio_addr << 2, (len < max_len ? len : max_len));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3629) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3630) 	/* revalidate the entire FCP priority config data, including entries */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3631) 	if (!qla24xx_fcp_prio_cfg_valid(vha, ha->fcp_prio_cfg, 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3632) 		goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3633) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3634) 	ha->flags.fcp_prio_enabled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3635) 	return QLA_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3636) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3637) 	vfree(ha->fcp_prio_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3638) 	ha->fcp_prio_cfg = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3639) 	return QLA_FUNCTION_FAILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3640) }