^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * linux/drivers/scsi/esas2r/esas2r_flash.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * For use with ATTO ExpressSAS R6xx SAS/SATA RAID controllers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (c) 2001-2013 ATTO Technology, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * (mailto:linuxdrivers@attotech.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * This program is free software; you can redistribute it and/or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * modify it under the terms of the GNU General Public License
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * as published by the Free Software Foundation; either version 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * of the License, or (at your option) any later version.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * This program is distributed in the hope that it will be useful,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * but WITHOUT ANY WARRANTY; without even the implied warranty of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * GNU General Public License for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * NO WARRANTY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * solely responsible for determining the appropriateness of using and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * distributing the Program and assumes all risks associated with its
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * exercise of rights under this Agreement, including but not limited to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * the risks and costs of program errors, damage to or loss of data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * programs or equipment, and unavailability or interruption of operations.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * DISCLAIMER OF LIABILITY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * You should have received a copy of the GNU General Public License
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * along with this program; if not, write to the Free Software
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * USA.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #include "esas2r.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) /* local macro defs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define esas2r_nvramcalc_cksum(n) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) (esas2r_calc_byte_cksum((u8 *)(n), sizeof(struct esas2r_sas_nvram), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) SASNVR_CKSUM_SEED))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define esas2r_nvramcalc_xor_cksum(n) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) (esas2r_calc_byte_xor_cksum((u8 *)(n), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) sizeof(struct esas2r_sas_nvram), 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define ESAS2R_FS_DRVR_VER 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) static struct esas2r_sas_nvram default_sas_nvram = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) { 'E', 'S', 'A', 'S' }, /* signature */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) SASNVR_VERSION, /* version */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) 0, /* checksum */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) 31, /* max_lun_for_target */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) SASNVR_PCILAT_MAX, /* pci_latency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) SASNVR1_BOOT_DRVR, /* options1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) SASNVR2_HEARTBEAT | SASNVR2_SINGLE_BUS /* options2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) | SASNVR2_SW_MUX_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) SASNVR_COAL_DIS, /* int_coalescing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) SASNVR_CMDTHR_NONE, /* cmd_throttle */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) 3, /* dev_wait_time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) 1, /* dev_wait_count */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) 0, /* spin_up_delay */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) 0, /* ssp_align_rate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) { 0x50, 0x01, 0x08, 0x60, /* sas_addr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) 0x00, 0x00, 0x00, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) { SASNVR_SPEED_AUTO }, /* phy_speed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) { SASNVR_MUX_DISABLED }, /* SAS multiplexing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) { 0 }, /* phy_flags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) SASNVR_SORT_SAS_ADDR, /* sort_type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) 3, /* dpm_reqcmd_lmt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) 3, /* dpm_stndby_time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) 0, /* dpm_active_time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) { 0 }, /* phy_target_id */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) SASNVR_VSMH_DISABLED, /* virt_ses_mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) SASNVR_RWM_DEFAULT, /* read_write_mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) 0, /* link down timeout */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) { 0 } /* reserved */
^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) static u8 cmd_to_fls_func[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) 0xFF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) VDA_FLASH_READ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) VDA_FLASH_BEGINW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) VDA_FLASH_WRITE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) VDA_FLASH_COMMIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) VDA_FLASH_CANCEL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) static u8 esas2r_calc_byte_xor_cksum(u8 *addr, u32 len, u8 seed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) u32 cksum = seed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) u8 *p = (u8 *)&cksum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) while (len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) if (((uintptr_t)addr & 3) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) cksum = cksum ^ *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) addr++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) len--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) while (len >= sizeof(u32)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) cksum = cksum ^ *(u32 *)addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) addr += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) len -= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) while (len--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) cksum = cksum ^ *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) addr++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) return p[0] ^ p[1] ^ p[2] ^ p[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) static u8 esas2r_calc_byte_cksum(void *addr, u32 len, u8 seed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) u8 *p = (u8 *)addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) u8 cksum = seed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) while (len--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) cksum = cksum + p[len];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) return cksum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) /* Interrupt callback to process FM API write requests. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) static void esas2r_fmapi_callback(struct esas2r_adapter *a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) struct esas2r_request *rq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) struct atto_vda_flash_req *vrq = &rq->vrq->flash;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) struct esas2r_flash_context *fc =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) (struct esas2r_flash_context *)rq->interrupt_cx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) if (rq->req_stat == RS_SUCCESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) /* Last request was successful. See what to do now. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) switch (vrq->sub_func) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) case VDA_FLASH_BEGINW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) if (fc->sgc.cur_offset == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) goto commit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) vrq->sub_func = VDA_FLASH_WRITE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) rq->req_stat = RS_PENDING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) case VDA_FLASH_WRITE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) commit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) vrq->sub_func = VDA_FLASH_COMMIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) rq->req_stat = RS_PENDING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) rq->interrupt_cb = fc->interrupt_cb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) if (rq->req_stat != RS_PENDING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) * All done. call the real callback to complete the FM API
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) * request. We should only get here if a BEGINW or WRITE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) * operation failed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) (*fc->interrupt_cb)(a, rq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * Build a flash request based on the flash context. The request status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * is filled in on an error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) static void build_flash_msg(struct esas2r_adapter *a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) struct esas2r_request *rq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) struct esas2r_flash_context *fc =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) (struct esas2r_flash_context *)rq->interrupt_cx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) struct esas2r_sg_context *sgc = &fc->sgc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) u8 cksum = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) /* calculate the checksum */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) if (fc->func == VDA_FLASH_BEGINW) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) if (sgc->cur_offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) cksum = esas2r_calc_byte_xor_cksum(sgc->cur_offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) sgc->length,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) rq->interrupt_cb = esas2r_fmapi_callback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) rq->interrupt_cb = fc->interrupt_cb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) esas2r_build_flash_req(a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) rq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) fc->func,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) cksum,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) fc->flsh_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) sgc->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) esas2r_rq_free_sg_lists(rq, a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) * remember the length we asked for. we have to keep track of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) * the current amount done so we know how much to compare when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) * doing the verification phase.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) fc->curr_len = fc->sgc.length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) if (sgc->cur_offset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) /* setup the S/G context to build the S/G table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) esas2r_sgc_init(sgc, a, rq, &rq->vrq->flash.data.sge[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) if (!esas2r_build_sg_list(a, rq, sgc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) rq->req_stat = RS_BUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) fc->sgc.length = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) /* update the flsh_addr to the next one to write to */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) fc->flsh_addr += fc->curr_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) /* determine the method to process the flash request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) static bool load_image(struct esas2r_adapter *a, struct esas2r_request *rq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) * assume we have more to do. if we return with the status set to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) * RS_PENDING, FM API tasks will continue.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) rq->req_stat = RS_PENDING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) if (test_bit(AF_DEGRADED_MODE, &a->flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) /* not suppported for now */;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) build_flash_msg(a, rq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) return rq->req_stat == RS_PENDING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) /* boot image fixer uppers called before downloading the image. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) static void fix_bios(struct esas2r_adapter *a, struct esas2r_flash_img *fi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) struct esas2r_component_header *ch = &fi->cmp_hdr[CH_IT_BIOS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) struct esas2r_pc_image *pi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) struct esas2r_boot_header *bh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) pi = (struct esas2r_pc_image *)((u8 *)fi + ch->image_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) bh =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) (struct esas2r_boot_header *)((u8 *)pi +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) le16_to_cpu(pi->header_offset));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) bh->device_id = cpu_to_le16(a->pcid->device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) /* Recalculate the checksum in the PNP header if there */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) if (pi->pnp_offset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) u8 *pnp_header_bytes =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) ((u8 *)pi + le16_to_cpu(pi->pnp_offset));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) /* Identifier - dword that starts at byte 10 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) *((u32 *)&pnp_header_bytes[10]) =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) cpu_to_le32(MAKEDWORD(a->pcid->subsystem_vendor,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) a->pcid->subsystem_device));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) /* Checksum - byte 9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) pnp_header_bytes[9] -= esas2r_calc_byte_cksum(pnp_header_bytes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 32, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) /* Recalculate the checksum needed by the PC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) pi->checksum = pi->checksum -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) esas2r_calc_byte_cksum((u8 *)pi, ch->length, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) static void fix_efi(struct esas2r_adapter *a, struct esas2r_flash_img *fi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) struct esas2r_component_header *ch = &fi->cmp_hdr[CH_IT_EFI];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) u32 len = ch->length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) u32 offset = ch->image_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) struct esas2r_efi_image *ei;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) struct esas2r_boot_header *bh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) while (len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) u32 thislen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) ei = (struct esas2r_efi_image *)((u8 *)fi + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) bh = (struct esas2r_boot_header *)((u8 *)ei +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) le16_to_cpu(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) ei->header_offset));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) bh->device_id = cpu_to_le16(a->pcid->device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) thislen = (u32)le16_to_cpu(bh->image_length) * 512;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) if (thislen > len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) len -= thislen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) offset += thislen;
^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) /* Complete a FM API request with the specified status. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) static bool complete_fmapi_req(struct esas2r_adapter *a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) struct esas2r_request *rq, u8 fi_stat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) struct esas2r_flash_context *fc =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) (struct esas2r_flash_context *)rq->interrupt_cx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) struct esas2r_flash_img *fi = fc->fi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) fi->status = fi_stat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) fi->driver_error = rq->req_stat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) rq->interrupt_cb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) rq->req_stat = RS_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) if (fi_stat != FI_STAT_IMG_VER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) memset(fc->scratch, 0, FM_BUF_SZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) esas2r_enable_heartbeat(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) clear_bit(AF_FLASH_LOCK, &a->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) /* Process each phase of the flash download process. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) static void fw_download_proc(struct esas2r_adapter *a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) struct esas2r_request *rq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) struct esas2r_flash_context *fc =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) (struct esas2r_flash_context *)rq->interrupt_cx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) struct esas2r_flash_img *fi = fc->fi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) struct esas2r_component_header *ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) u32 len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) u8 *p, *q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) /* If the previous operation failed, just return. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (rq->req_stat != RS_SUCCESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) * If an upload just completed and the compare length is non-zero,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) * then we just read back part of the image we just wrote. verify the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) * section and continue reading until the entire image is verified.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) if (fc->func == VDA_FLASH_READ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) && fc->cmp_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) ch = &fi->cmp_hdr[fc->comp_typ];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) p = fc->scratch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) q = (u8 *)fi /* start of the whole gob */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) + ch->image_offset /* start of the current image */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) + ch->length /* end of the current image */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) - fc->cmp_len; /* where we are now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) * NOTE - curr_len is the exact count of bytes for the read
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) * even when the end is read and its not a full buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) for (len = fc->curr_len; len; len--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) if (*p++ != *q++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) fc->cmp_len -= fc->curr_len; /* # left to compare */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) /* Update fc and determine the length for the next upload */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) if (fc->cmp_len > FM_BUF_SZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) fc->sgc.length = FM_BUF_SZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) fc->sgc.length = fc->cmp_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) fc->sgc.cur_offset = fc->sgc_offset +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) ((u8 *)fc->scratch - (u8 *)fi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) * This code uses a 'while' statement since the next component may
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) * have a length = zero. This can happen since some components are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) * not required. At the end of this 'while' we set up the length
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) * for the next request and therefore sgc.length can be = 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) while (fc->sgc.length == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) ch = &fi->cmp_hdr[fc->comp_typ];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) switch (fc->task) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) case FMTSK_ERASE_BOOT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) /* the BIOS image is written next */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) ch = &fi->cmp_hdr[CH_IT_BIOS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) if (ch->length == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) goto no_bios;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) fc->task = FMTSK_WRTBIOS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) fc->func = VDA_FLASH_BEGINW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) fc->comp_typ = CH_IT_BIOS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) fc->flsh_addr = FLS_OFFSET_BOOT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) fc->sgc.length = ch->length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) fc->sgc.cur_offset = fc->sgc_offset +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) ch->image_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) case FMTSK_WRTBIOS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) * The BIOS image has been written - read it and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) * verify it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) fc->task = FMTSK_READBIOS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) fc->func = VDA_FLASH_READ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) fc->flsh_addr = FLS_OFFSET_BOOT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) fc->cmp_len = ch->length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) fc->sgc.length = FM_BUF_SZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) fc->sgc.cur_offset = fc->sgc_offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) + ((u8 *)fc->scratch -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) (u8 *)fi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) case FMTSK_READBIOS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) no_bios:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) * Mark the component header status for the image
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) * completed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) ch->status = CH_STAT_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) /* The MAC image is written next */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) ch = &fi->cmp_hdr[CH_IT_MAC];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) if (ch->length == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) goto no_mac;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) fc->task = FMTSK_WRTMAC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) fc->func = VDA_FLASH_BEGINW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) fc->comp_typ = CH_IT_MAC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) fc->flsh_addr = FLS_OFFSET_BOOT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) + fi->cmp_hdr[CH_IT_BIOS].length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) fc->sgc.length = ch->length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) fc->sgc.cur_offset = fc->sgc_offset +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) ch->image_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) case FMTSK_WRTMAC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) /* The MAC image has been written - read and verify */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) fc->task = FMTSK_READMAC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) fc->func = VDA_FLASH_READ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) fc->flsh_addr -= ch->length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) fc->cmp_len = ch->length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) fc->sgc.length = FM_BUF_SZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) fc->sgc.cur_offset = fc->sgc_offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) + ((u8 *)fc->scratch -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) (u8 *)fi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) case FMTSK_READMAC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) no_mac:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) * Mark the component header status for the image
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) * completed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) ch->status = CH_STAT_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) /* The EFI image is written next */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) ch = &fi->cmp_hdr[CH_IT_EFI];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) if (ch->length == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) goto no_efi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) fc->task = FMTSK_WRTEFI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) fc->func = VDA_FLASH_BEGINW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) fc->comp_typ = CH_IT_EFI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) fc->flsh_addr = FLS_OFFSET_BOOT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) + fi->cmp_hdr[CH_IT_BIOS].length
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) + fi->cmp_hdr[CH_IT_MAC].length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) fc->sgc.length = ch->length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) fc->sgc.cur_offset = fc->sgc_offset +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) ch->image_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) case FMTSK_WRTEFI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) /* The EFI image has been written - read and verify */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) fc->task = FMTSK_READEFI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) fc->func = VDA_FLASH_READ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) fc->flsh_addr -= ch->length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) fc->cmp_len = ch->length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) fc->sgc.length = FM_BUF_SZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) fc->sgc.cur_offset = fc->sgc_offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) + ((u8 *)fc->scratch -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) (u8 *)fi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) case FMTSK_READEFI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) no_efi:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) * Mark the component header status for the image
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) * completed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) ch->status = CH_STAT_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) /* The CFG image is written next */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) ch = &fi->cmp_hdr[CH_IT_CFG];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) if (ch->length == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) goto no_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) fc->task = FMTSK_WRTCFG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) fc->func = VDA_FLASH_BEGINW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) fc->comp_typ = CH_IT_CFG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) fc->flsh_addr = FLS_OFFSET_CPYR - ch->length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) fc->sgc.length = ch->length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) fc->sgc.cur_offset = fc->sgc_offset +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) ch->image_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) case FMTSK_WRTCFG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) /* The CFG image has been written - read and verify */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) fc->task = FMTSK_READCFG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) fc->func = VDA_FLASH_READ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) fc->flsh_addr = FLS_OFFSET_CPYR - ch->length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) fc->cmp_len = ch->length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) fc->sgc.length = FM_BUF_SZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) fc->sgc.cur_offset = fc->sgc_offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) + ((u8 *)fc->scratch -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) (u8 *)fi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) case FMTSK_READCFG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) no_cfg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) * Mark the component header status for the image
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) * completed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) ch->status = CH_STAT_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) * The download is complete. If in degraded mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) * attempt a chip reset.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) if (test_bit(AF_DEGRADED_MODE, &a->flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) esas2r_local_reset_adapter(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) a->flash_ver = fi->cmp_hdr[CH_IT_BIOS].version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) esas2r_print_flash_rev(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) /* Update the type of boot image on the card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) memcpy(a->image_type, fi->rel_version,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) sizeof(fi->rel_version));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) complete_fmapi_req(a, rq, FI_STAT_SUCCESS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) /* If verifying, don't try reading more than what's there */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) if (fc->func == VDA_FLASH_READ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) && fc->sgc.length > fc->cmp_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) fc->sgc.length = fc->cmp_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) /* Build the request to perform the next action */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) if (!load_image(a, rq)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) if (fc->comp_typ < fi->num_comps) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) ch = &fi->cmp_hdr[fc->comp_typ];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) ch->status = CH_STAT_FAILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) complete_fmapi_req(a, rq, FI_STAT_FAILED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) }
^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) /* Determine the flash image adaptyp for this adapter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) static u8 get_fi_adap_type(struct esas2r_adapter *a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) u8 type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) /* use the device ID to get the correct adap_typ for this HBA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) switch (a->pcid->device) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) case ATTO_DID_INTEL_IOP348:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) type = FI_AT_SUN_LAKE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) case ATTO_DID_MV_88RC9580:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) case ATTO_DID_MV_88RC9580TS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) case ATTO_DID_MV_88RC9580TSE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) case ATTO_DID_MV_88RC9580TL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) type = FI_AT_MV_9580;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) type = FI_AT_UNKNWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) break;
^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) return type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) /* Size of config + copyright + flash_ver images, 0 for failure. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) static u32 chk_cfg(u8 *cfg, u32 length, u32 *flash_ver)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) u16 *pw = (u16 *)cfg - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) u32 sz = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) u32 len = length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) if (len == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) len = FM_BUF_SZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) if (flash_ver)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) *flash_ver = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) while (true) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) u16 type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) u16 size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) type = le16_to_cpu(*pw--);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) size = le16_to_cpu(*pw--);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) if (type != FBT_CPYR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) && type != FBT_SETUP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) && type != FBT_FLASH_VER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) if (type == FBT_FLASH_VER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) && flash_ver)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) *flash_ver = le32_to_cpu(*(u32 *)(pw - 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) sz += size + (2 * sizeof(u16));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) pw -= size / sizeof(u16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) if (sz > len - (2 * sizeof(u16)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) /* See if we are comparing the size to the specified length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) if (length && sz != length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) return sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) /* Verify that the boot image is valid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) static u8 chk_boot(u8 *boot_img, u32 length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) struct esas2r_boot_image *bi = (struct esas2r_boot_image *)boot_img;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) u16 hdroffset = le16_to_cpu(bi->header_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) struct esas2r_boot_header *bh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) if (bi->signature != le16_to_cpu(0xaa55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) || (long)hdroffset >
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) (long)(65536L - sizeof(struct esas2r_boot_header))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) || (hdroffset & 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) || (hdroffset < sizeof(struct esas2r_boot_image))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) || ((u32)hdroffset + sizeof(struct esas2r_boot_header) > length))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) return 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) bh = (struct esas2r_boot_header *)((char *)bi + hdroffset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) if (bh->signature[0] != 'P'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) || bh->signature[1] != 'C'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) || bh->signature[2] != 'I'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) || bh->signature[3] != 'R'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) || le16_to_cpu(bh->struct_length) <
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) (u16)sizeof(struct esas2r_boot_header)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) || bh->class_code[2] != 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) || bh->class_code[1] != 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) || bh->class_code[0] != 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) || (bh->code_type != CODE_TYPE_PC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) && bh->code_type != CODE_TYPE_OPEN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) && bh->code_type != CODE_TYPE_EFI))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) return 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) return bh->code_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) /* The sum of all the WORDS of the image */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) static u16 calc_fi_checksum(struct esas2r_flash_context *fc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) struct esas2r_flash_img *fi = fc->fi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) u16 cksum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) u32 len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) u16 *pw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) for (len = (fi->length - fc->fi_hdr_len) / 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) pw = (u16 *)((u8 *)fi + fc->fi_hdr_len),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) cksum = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) len--, pw++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) cksum = cksum + le16_to_cpu(*pw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) return cksum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) * Verify the flash image structure. The following verifications will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) * be performed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) * 1) verify the fi_version is correct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) * 2) verify the checksum of the entire image.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) * 3) validate the adap_typ, action and length fields.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) * 4) validate each component header. check the img_type and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) * length fields
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) * 5) validate each component image. validate signatures and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) * local checksums
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) static bool verify_fi(struct esas2r_adapter *a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) struct esas2r_flash_context *fc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) struct esas2r_flash_img *fi = fc->fi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) u8 type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) bool imgerr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) u16 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) u32 len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) struct esas2r_component_header *ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) /* Verify the length - length must even since we do a word checksum */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) len = fi->length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) if ((len & 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) || len < fc->fi_hdr_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) fi->status = FI_STAT_LENGTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) /* Get adapter type and verify type in flash image */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) type = get_fi_adap_type(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) if ((type == FI_AT_UNKNWN) || (fi->adap_typ != type)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) fi->status = FI_STAT_ADAPTYP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) * Loop through each component and verify the img_type and length
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) * fields. Keep a running count of the sizes sooze we can verify total
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) * size to additive size.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) imgerr = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) for (i = 0, len = 0, ch = fi->cmp_hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) i < fi->num_comps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) i++, ch++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) bool cmperr = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) * Verify that the component header has the same index as the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) * image type. The headers must be ordered correctly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) if (i != ch->img_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) imgerr = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) ch->status = CH_STAT_INVALID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) switch (ch->img_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) case CH_IT_BIOS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) type = CODE_TYPE_PC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) case CH_IT_MAC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) type = CODE_TYPE_OPEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) case CH_IT_EFI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) type = CODE_TYPE_EFI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) switch (ch->img_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) case CH_IT_FW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) case CH_IT_NVR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) case CH_IT_BIOS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) case CH_IT_MAC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) case CH_IT_EFI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) if (ch->length & 0x1ff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) cmperr = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) /* Test if component image is present */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) if (ch->length == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) /* Image is present - verify the image */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) if (chk_boot((u8 *)fi + ch->image_offset, ch->length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) != type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) cmperr = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) case CH_IT_CFG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) /* Test if component image is present */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) if (ch->length == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) cmperr = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) /* Image is present - verify the image */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) if (!chk_cfg((u8 *)fi + ch->image_offset + ch->length,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) ch->length, NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) cmperr = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) fi->status = FI_STAT_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) if (cmperr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) imgerr = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) ch->status = CH_STAT_INVALID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) ch->status = CH_STAT_PENDING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) len += ch->length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) if (imgerr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) fi->status = FI_STAT_MISSING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) /* Compare fi->length to the sum of ch->length fields */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) if (len != fi->length - fc->fi_hdr_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) fi->status = FI_STAT_LENGTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) /* Compute the checksum - it should come out zero */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) if (fi->checksum != calc_fi_checksum(fc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) fi->status = FI_STAT_CHKSUM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) /* Fill in the FS IOCTL response data from a completed request. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) static void esas2r_complete_fs_ioctl(struct esas2r_adapter *a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) struct esas2r_request *rq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) struct esas2r_ioctl_fs *fs =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) (struct esas2r_ioctl_fs *)rq->interrupt_cx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) if (rq->vrq->flash.sub_func == VDA_FLASH_COMMIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) esas2r_enable_heartbeat(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) fs->driver_error = rq->req_stat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) if (fs->driver_error == RS_SUCCESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) fs->status = ATTO_STS_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) fs->status = ATTO_STS_FAILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) /* Prepare an FS IOCTL request to be sent to the firmware. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) bool esas2r_process_fs_ioctl(struct esas2r_adapter *a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) struct esas2r_ioctl_fs *fs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) struct esas2r_request *rq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) struct esas2r_sg_context *sgc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) u8 cmdcnt = (u8)ARRAY_SIZE(cmd_to_fls_func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) struct esas2r_ioctlfs_command *fsc = &fs->command;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) u8 func = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) u32 datalen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) fs->status = ATTO_STS_FAILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) fs->driver_error = RS_PENDING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) if (fs->version > ESAS2R_FS_VER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) fs->status = ATTO_STS_INV_VERSION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) if (fsc->command >= cmdcnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) fs->status = ATTO_STS_INV_FUNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) func = cmd_to_fls_func[fsc->command];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) if (func == 0xFF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) fs->status = ATTO_STS_INV_FUNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) if (fsc->command != ESAS2R_FS_CMD_CANCEL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) if ((a->pcid->device != ATTO_DID_MV_88RC9580
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) || fs->adap_type != ESAS2R_FS_AT_ESASRAID2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) && (a->pcid->device != ATTO_DID_MV_88RC9580TS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) || fs->adap_type != ESAS2R_FS_AT_TSSASRAID2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) && (a->pcid->device != ATTO_DID_MV_88RC9580TSE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) || fs->adap_type != ESAS2R_FS_AT_TSSASRAID2E)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) && (a->pcid->device != ATTO_DID_MV_88RC9580TL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) || fs->adap_type != ESAS2R_FS_AT_TLSASHBA)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) fs->status = ATTO_STS_INV_ADAPTER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) if (fs->driver_ver > ESAS2R_FS_DRVR_VER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) fs->status = ATTO_STS_INV_DRVR_VER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) if (test_bit(AF_DEGRADED_MODE, &a->flags)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) fs->status = ATTO_STS_DEGRADED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) rq->interrupt_cb = esas2r_complete_fs_ioctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) rq->interrupt_cx = fs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) datalen = le32_to_cpu(fsc->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) esas2r_build_flash_req(a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) rq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) func,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) fsc->checksum,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) le32_to_cpu(fsc->flash_addr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) datalen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) if (func == VDA_FLASH_WRITE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) || func == VDA_FLASH_READ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) if (datalen == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) fs->status = ATTO_STS_INV_FUNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) esas2r_sgc_init(sgc, a, rq, rq->vrq->flash.data.sge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) sgc->length = datalen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) if (!esas2r_build_sg_list(a, rq, sgc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) fs->status = ATTO_STS_OUT_OF_RSRC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) if (func == VDA_FLASH_COMMIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) esas2r_disable_heartbeat(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) esas2r_start_request(a, rq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) static bool esas2r_flash_access(struct esas2r_adapter *a, u32 function)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) u32 starttime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) u32 timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) u32 intstat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) u32 doorbell;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) /* Disable chip interrupts awhile */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) if (function == DRBL_FLASH_REQ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) esas2r_disable_chip_interrupts(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) /* Issue the request to the firmware */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) esas2r_write_register_dword(a, MU_DOORBELL_IN, function);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) /* Now wait for the firmware to process it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) starttime = jiffies_to_msecs(jiffies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) if (test_bit(AF_CHPRST_PENDING, &a->flags) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) test_bit(AF_DISC_PENDING, &a->flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) timeout = 40000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) timeout = 5000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) while (true) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) intstat = esas2r_read_register_dword(a, MU_INT_STATUS_OUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) if (intstat & MU_INTSTAT_DRBL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) /* Got a doorbell interrupt. Check for the function */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) doorbell =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) esas2r_read_register_dword(a, MU_DOORBELL_OUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) esas2r_write_register_dword(a, MU_DOORBELL_OUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) doorbell);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) if (doorbell & function)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) schedule_timeout_interruptible(msecs_to_jiffies(100));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) if ((jiffies_to_msecs(jiffies) - starttime) > timeout) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) * Iimeout. If we were requesting flash access,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) * indicate we are done so the firmware knows we gave
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) * up. If this was a REQ, we also need to re-enable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) * chip interrupts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) if (function == DRBL_FLASH_REQ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) esas2r_hdebug("flash access timeout");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) esas2r_write_register_dword(a, MU_DOORBELL_IN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) DRBL_FLASH_DONE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) esas2r_enable_chip_interrupts(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) esas2r_hdebug("flash release timeout");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) /* if we're done, re-enable chip interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) if (function == DRBL_FLASH_DONE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) esas2r_enable_chip_interrupts(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) #define WINDOW_SIZE ((signed int)MW_DATA_WINDOW_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) bool esas2r_read_flash_block(struct esas2r_adapter *a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) void *to,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) u32 from,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) u32 size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) u8 *end = (u8 *)to;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) /* Try to acquire access to the flash */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) if (!esas2r_flash_access(a, DRBL_FLASH_REQ))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) while (size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) u32 len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) u32 offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) u32 iatvr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) if (test_bit(AF2_SERIAL_FLASH, &a->flags2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) iatvr = MW_DATA_ADDR_SER_FLASH + (from & -WINDOW_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) iatvr = MW_DATA_ADDR_PAR_FLASH + (from & -WINDOW_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) esas2r_map_data_window(a, iatvr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) offset = from & (WINDOW_SIZE - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) len = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) if (len > WINDOW_SIZE - offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) len = WINDOW_SIZE - offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) from += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) size -= len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) while (len--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) *end++ = esas2r_read_data_byte(a, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) offset++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) /* Release flash access */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) esas2r_flash_access(a, DRBL_FLASH_DONE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) return true;
^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) bool esas2r_read_flash_rev(struct esas2r_adapter *a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) u8 bytes[256];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) u16 *pw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) u16 *pwstart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) u16 type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) u16 size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) u32 sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) sz = sizeof(bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) pw = (u16 *)(bytes + sz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) pwstart = (u16 *)bytes + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) if (!esas2r_read_flash_block(a, bytes, FLS_OFFSET_CPYR - sz, sz))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) goto invalid_rev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) while (pw >= pwstart) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) pw--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) type = le16_to_cpu(*pw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) pw--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) size = le16_to_cpu(*pw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) pw -= size / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) if (type == FBT_CPYR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) || type == FBT_SETUP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) || pw < pwstart)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) if (type == FBT_FLASH_VER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) a->flash_ver = le32_to_cpu(*(u32 *)pw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) invalid_rev:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) return esas2r_print_flash_rev(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) bool esas2r_print_flash_rev(struct esas2r_adapter *a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) u16 year = LOWORD(a->flash_ver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) u8 day = LOBYTE(HIWORD(a->flash_ver));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) u8 month = HIBYTE(HIWORD(a->flash_ver));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) if (day == 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) || month == 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) || day > 31
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) || month > 12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) || year < 2006
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) || year > 9999) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) strcpy(a->flash_rev, "not found");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) a->flash_ver = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) sprintf(a->flash_rev, "%02d/%02d/%04d", month, day, year);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) esas2r_hdebug("flash version: %s", a->flash_rev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) * Find the type of boot image type that is currently in the flash.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) * The chip only has a 64 KB PCI-e expansion ROM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) * size so only one image can be flashed at a time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) bool esas2r_read_image_type(struct esas2r_adapter *a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) u8 bytes[256];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) struct esas2r_boot_image *bi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) struct esas2r_boot_header *bh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) u32 sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) u32 len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) u32 offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) /* Start at the base of the boot images and look for a valid image */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) sz = sizeof(bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) len = FLS_LENGTH_BOOT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) while (true) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) if (!esas2r_read_flash_block(a, bytes, FLS_OFFSET_BOOT +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) sz))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) goto invalid_rev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) bi = (struct esas2r_boot_image *)bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) bh = (struct esas2r_boot_header *)((u8 *)bi +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) le16_to_cpu(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) bi->header_offset));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) if (bi->signature != cpu_to_le16(0xAA55))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) goto invalid_rev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) if (bh->code_type == CODE_TYPE_PC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) strcpy(a->image_type, "BIOS");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) } else if (bh->code_type == CODE_TYPE_EFI) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) struct esas2r_efi_image *ei;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) * So we have an EFI image. There are several types
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) * so see which architecture we have.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) ei = (struct esas2r_efi_image *)bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) switch (le16_to_cpu(ei->machine_type)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) case EFI_MACHINE_IA32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) strcpy(a->image_type, "EFI 32-bit");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) case EFI_MACHINE_IA64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) strcpy(a->image_type, "EFI itanium");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) case EFI_MACHINE_X64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) strcpy(a->image_type, "EFI 64-bit");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) case EFI_MACHINE_EBC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) strcpy(a->image_type, "EFI EBC");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) goto invalid_rev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) u32 thislen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) /* jump to the next image */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) thislen = (u32)le16_to_cpu(bh->image_length) * 512;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) if (thislen == 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) || thislen + offset > len
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) || bh->indicator == INDICATOR_LAST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) offset += thislen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) invalid_rev:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) strcpy(a->image_type, "no boot images");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) * Read and validate current NVRAM parameters by accessing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) * physical NVRAM directly. if currently stored parameters are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) * invalid, use the defaults.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) bool esas2r_nvram_read_direct(struct esas2r_adapter *a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) bool result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) if (down_interruptible(&a->nvram_semaphore))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) if (!esas2r_read_flash_block(a, a->nvram, FLS_OFFSET_NVR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) sizeof(struct esas2r_sas_nvram))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) esas2r_hdebug("NVRAM read failed, using defaults");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) up(&a->nvram_semaphore);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) result = esas2r_nvram_validate(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) up(&a->nvram_semaphore);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) /* Interrupt callback to process NVRAM completions. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) static void esas2r_nvram_callback(struct esas2r_adapter *a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) struct esas2r_request *rq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) struct atto_vda_flash_req *vrq = &rq->vrq->flash;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) if (rq->req_stat == RS_SUCCESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) /* last request was successful. see what to do now. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) switch (vrq->sub_func) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) case VDA_FLASH_BEGINW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) vrq->sub_func = VDA_FLASH_WRITE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) rq->req_stat = RS_PENDING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) case VDA_FLASH_WRITE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) vrq->sub_func = VDA_FLASH_COMMIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) rq->req_stat = RS_PENDING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) case VDA_FLASH_READ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) esas2r_nvram_validate(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) case VDA_FLASH_COMMIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) default:
^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) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) if (rq->req_stat != RS_PENDING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) /* update the NVRAM state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) if (rq->req_stat == RS_SUCCESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) set_bit(AF_NVR_VALID, &a->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) clear_bit(AF_NVR_VALID, &a->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) esas2r_enable_heartbeat(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) up(&a->nvram_semaphore);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) * Write the contents of nvram to the adapter's physical NVRAM.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) * The cached copy of the NVRAM is also updated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) bool esas2r_nvram_write(struct esas2r_adapter *a, struct esas2r_request *rq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) struct esas2r_sas_nvram *nvram)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) struct esas2r_sas_nvram *n = nvram;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) u8 sas_address_bytes[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) u32 *sas_address_dwords = (u32 *)&sas_address_bytes[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) struct atto_vda_flash_req *vrq = &rq->vrq->flash;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) if (test_bit(AF_DEGRADED_MODE, &a->flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) if (down_interruptible(&a->nvram_semaphore))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) if (n == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) n = a->nvram;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) /* check the validity of the settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) if (n->version > SASNVR_VERSION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) up(&a->nvram_semaphore);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) memcpy(&sas_address_bytes[0], n->sas_addr, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) if (sas_address_bytes[0] != 0x50
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) || sas_address_bytes[1] != 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) || sas_address_bytes[2] != 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) || (sas_address_bytes[3] & 0xF0) != 0x60
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) || ((sas_address_bytes[3] & 0x0F) | sas_address_dwords[1]) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) up(&a->nvram_semaphore);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) return false;
^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) if (n->spin_up_delay > SASNVR_SPINUP_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) n->spin_up_delay = SASNVR_SPINUP_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) n->version = SASNVR_VERSION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) n->checksum = n->checksum - esas2r_nvramcalc_cksum(n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) memcpy(a->nvram, n, sizeof(struct esas2r_sas_nvram));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) /* write the NVRAM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) n = a->nvram;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) esas2r_disable_heartbeat(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) esas2r_build_flash_req(a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) rq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) VDA_FLASH_BEGINW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) esas2r_nvramcalc_xor_cksum(n),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) FLS_OFFSET_NVR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) sizeof(struct esas2r_sas_nvram));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) if (test_bit(AF_LEGACY_SGE_MODE, &a->flags)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) vrq->data.sge[0].length =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) cpu_to_le32(SGE_LAST |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) sizeof(struct esas2r_sas_nvram));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) vrq->data.sge[0].address = cpu_to_le64(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) a->uncached_phys + (u64)((u8 *)n - a->uncached));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) vrq->data.prde[0].ctl_len =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) cpu_to_le32(sizeof(struct esas2r_sas_nvram));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) vrq->data.prde[0].address = cpu_to_le64(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) a->uncached_phys
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) + (u64)((u8 *)n - a->uncached));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) rq->interrupt_cb = esas2r_nvram_callback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) esas2r_start_request(a, rq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) /* Validate the cached NVRAM. if the NVRAM is invalid, load the defaults. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) bool esas2r_nvram_validate(struct esas2r_adapter *a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) struct esas2r_sas_nvram *n = a->nvram;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) bool rslt = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) if (n->signature[0] != 'E'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) || n->signature[1] != 'S'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) || n->signature[2] != 'A'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) || n->signature[3] != 'S') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) esas2r_hdebug("invalid NVRAM signature");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) } else if (esas2r_nvramcalc_cksum(n)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) esas2r_hdebug("invalid NVRAM checksum");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) } else if (n->version > SASNVR_VERSION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) esas2r_hdebug("invalid NVRAM version");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) set_bit(AF_NVR_VALID, &a->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) rslt = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) if (rslt == false) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) esas2r_hdebug("using defaults");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) esas2r_nvram_set_defaults(a);
^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) return rslt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) * Set the cached NVRAM to defaults. note that this function sets the default
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) * NVRAM when it has been determined that the physical NVRAM is invalid.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) * In this case, the SAS address is fabricated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) void esas2r_nvram_set_defaults(struct esas2r_adapter *a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) struct esas2r_sas_nvram *n = a->nvram;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) u32 time = jiffies_to_msecs(jiffies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) clear_bit(AF_NVR_VALID, &a->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) *n = default_sas_nvram;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) n->sas_addr[3] |= 0x0F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) n->sas_addr[4] = HIBYTE(LOWORD(time));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) n->sas_addr[5] = LOBYTE(LOWORD(time));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) n->sas_addr[6] = a->pcid->bus->number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) n->sas_addr[7] = a->pcid->devfn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) void esas2r_nvram_get_defaults(struct esas2r_adapter *a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) struct esas2r_sas_nvram *nvram)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) u8 sas_addr[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) * in case we are copying the defaults into the adapter, copy the SAS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) * address out first.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) memcpy(&sas_addr[0], a->nvram->sas_addr, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) *nvram = default_sas_nvram;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) memcpy(&nvram->sas_addr[0], &sas_addr[0], 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) bool esas2r_fm_api(struct esas2r_adapter *a, struct esas2r_flash_img *fi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) struct esas2r_request *rq, struct esas2r_sg_context *sgc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) struct esas2r_flash_context *fc = &a->flash_context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) u8 j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) struct esas2r_component_header *ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) if (test_and_set_bit(AF_FLASH_LOCK, &a->flags)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) /* flag was already set */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) fi->status = FI_STAT_BUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) memcpy(&fc->sgc, sgc, sizeof(struct esas2r_sg_context));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) sgc = &fc->sgc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) fc->fi = fi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) fc->sgc_offset = sgc->cur_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) rq->req_stat = RS_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) rq->interrupt_cx = fc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) switch (fi->fi_version) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) case FI_VERSION_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) fc->scratch = ((struct esas2r_flash_img *)fi)->scratch_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) fc->num_comps = FI_NUM_COMPS_V1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) fc->fi_hdr_len = sizeof(struct esas2r_flash_img);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) return complete_fmapi_req(a, rq, FI_STAT_IMG_VER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) if (test_bit(AF_DEGRADED_MODE, &a->flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) return complete_fmapi_req(a, rq, FI_STAT_DEGRADED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) switch (fi->action) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) case FI_ACT_DOWN: /* Download the components */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) /* Verify the format of the flash image */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) if (!verify_fi(a, fc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) return complete_fmapi_req(a, rq, fi->status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) /* Adjust the BIOS fields that are dependent on the HBA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) ch = &fi->cmp_hdr[CH_IT_BIOS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) if (ch->length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) fix_bios(a, fi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) /* Adjust the EFI fields that are dependent on the HBA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) ch = &fi->cmp_hdr[CH_IT_EFI];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) if (ch->length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) fix_efi(a, fi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) * Since the image was just modified, compute the checksum on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) * the modified image. First update the CRC for the composite
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) * expansion ROM image.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) fi->checksum = calc_fi_checksum(fc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) /* Disable the heartbeat */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) esas2r_disable_heartbeat(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) /* Now start up the download sequence */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) fc->task = FMTSK_ERASE_BOOT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) fc->func = VDA_FLASH_BEGINW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) fc->comp_typ = CH_IT_CFG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) fc->flsh_addr = FLS_OFFSET_BOOT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) fc->sgc.length = FLS_LENGTH_BOOT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) fc->sgc.cur_offset = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) /* Setup the callback address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) fc->interrupt_cb = fw_download_proc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) case FI_ACT_UPSZ: /* Get upload sizes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) fi->adap_typ = get_fi_adap_type(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) fi->flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) fi->num_comps = fc->num_comps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) fi->length = fc->fi_hdr_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) /* Report the type of boot image in the rel_version string */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) memcpy(fi->rel_version, a->image_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) sizeof(fi->rel_version));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) /* Build the component headers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) for (j = 0, ch = fi->cmp_hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) j < fi->num_comps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) j++, ch++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) ch->img_type = j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) ch->status = CH_STAT_PENDING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) ch->length = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) ch->version = 0xffffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) ch->image_offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) ch->pad[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) ch->pad[1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) if (a->flash_ver != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) fi->cmp_hdr[CH_IT_BIOS].version =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) fi->cmp_hdr[CH_IT_MAC].version =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) fi->cmp_hdr[CH_IT_EFI].version =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) fi->cmp_hdr[CH_IT_CFG].version
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) = a->flash_ver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) fi->cmp_hdr[CH_IT_BIOS].status =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) fi->cmp_hdr[CH_IT_MAC].status =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) fi->cmp_hdr[CH_IT_EFI].status =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) fi->cmp_hdr[CH_IT_CFG].status =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) CH_STAT_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) return complete_fmapi_req(a, rq, FI_STAT_SUCCESS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) case FI_ACT_UP: /* Upload the components */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) return complete_fmapi_req(a, rq, FI_STAT_INVALID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) * If we make it here, fc has been setup to do the first task. Call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) * load_image to format the request, start it, and get out. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) * interrupt code will call the callback when the first message is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) * complete.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) if (!load_image(a, rq))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) return complete_fmapi_req(a, rq, FI_STAT_FAILED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) esas2r_start_request(a, rq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) }