^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(®->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(®->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(®->u.isp2300.host_semaphore, 0x1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) rd_reg_word(®->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(®->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(®->u.isp2300.host_semaphore, 0x1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) rd_reg_word(®->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(®->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(®->u.isp2300.host_semaphore, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) rd_reg_word(®->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(®->nvram, data | NVR_SELECT | NVR_WRT_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) rd_reg_word(®->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(®->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(®->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(®->nvram, data | NVR_SELECT | NVR_WRT_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) rd_reg_word(®->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(®->nvram, NVR_SELECT | NVR_CLOCK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) rd_reg_word(®->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(®->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(®->nvram, NVR_SELECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) rd_reg_word(®->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(®->nvram, NVR_DESELECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) rd_reg_word(®->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(®->nvram, NVR_DESELECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) rd_reg_word(®->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(®->nvram, NVR_SELECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) rd_reg_word(®->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(®->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(®->nvram, NVR_SELECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) rd_reg_word(®->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(®->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(®->nvram, NVR_SELECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) rd_reg_word(®->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(®->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(®->nvram, NVR_SELECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) rd_reg_word(®->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(®->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(®->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(®->flash_addr) & FARX_DATA_FLAG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) *data = rd_reg_dword(®->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(®->flash_data, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) wrt_reg_dword(®->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(®->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(®->ctrl_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) rd_reg_dword(®->ctrl_status) | CSRX_FLASH_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) rd_reg_dword(®->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(®->ctrl_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) rd_reg_dword(®->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(®->ctrl_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) rd_reg_dword(®->ctrl_status) | CSRX_FLASH_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) rd_reg_dword(®->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(®->ctrl_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) rd_reg_dword(®->ctrl_status) & ~CSRX_FLASH_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) rd_reg_dword(®->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(®->gpioe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) gpio_data = rd_reg_word(®->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(®->gpioe, gpio_enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) rd_reg_word(®->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(®->gpiod, gpio_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) rd_reg_word(®->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(®->gpioe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) gpio_data = rd_reg_word(®->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(®->gpioe, gpio_enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) rd_reg_word(®->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(®->gpiod, gpio_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) rd_reg_word(®->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(®->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(®->gpiod, gpio_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) gpio_data = rd_reg_dword(®->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(®->gpiod, gpio_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) gpio_data = rd_reg_dword(®->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(®->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(®->gpiod, gpio_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) rd_reg_dword(®->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(®->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(®->gpiod, gpio_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) rd_reg_dword(®->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(®->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(®->ctrl_status, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) rd_reg_word(®->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(®->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(®->ctrl_status, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) rd_reg_word(®->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(®->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(®->ctrl_status, bank_select);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) rd_reg_word(®->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(®->flash_address, (uint16_t)addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) data = rd_reg_word(®->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(®->ctrl_status, bank_select);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) rd_reg_word(®->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(®->ctrl_status, bank_select);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038) rd_reg_word(®->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(®->flash_address, (uint16_t)addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) data = qla2x00_debounce_register(®->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(®->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(®->ctrl_status, bank_select);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) rd_reg_word(®->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(®->flash_address, (uint16_t)addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083) rd_reg_word(®->ctrl_status); /* PCI Posting. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) wrt_reg_word(®->flash_data, (uint16_t)data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) rd_reg_word(®->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(®->ctrl_status, bank_select);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) rd_reg_word(®->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(®->ctrl_status, bank_select);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) rd_reg_word(®->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(®->flash_address, (uint16_t)addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108) rd_reg_word(®->ctrl_status); /* PCI Posting. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109) wrt_reg_word(®->flash_data, (uint16_t)data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) rd_reg_word(®->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(®->nvram, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294) rd_reg_word(®->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(®->nvram, NVR_SELECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298) rd_reg_word(®->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(®->hccr, HCCR_PAUSE_RISC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2324) rd_reg_word(®->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(®->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(®->nvram, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2367) rd_reg_word(®->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(®->nvram, NVR_SELECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2371) rd_reg_word(®->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(®->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(®->nvram, NVR_SELECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2553) rd_reg_word(®->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, ®ion);
^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) }