^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * QLogic iSCSI HBA Driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (c) 2003-2013 QLogic Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include "ql4_def.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include "ql4_glbl.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include "ql4_dbg.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include "ql4_inline.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) static inline void eeprom_cmd(uint32_t cmd, struct scsi_qla_host *ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) writel(cmd, isp_nvram(ha));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) readl(isp_nvram(ha));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) static inline int eeprom_size(struct scsi_qla_host *ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) return is_qla4010(ha) ? FM93C66A_SIZE_16 : FM93C86A_SIZE_16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) static inline int eeprom_no_addr_bits(struct scsi_qla_host *ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) return is_qla4010(ha) ? FM93C56A_NO_ADDR_BITS_16 :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) FM93C86A_NO_ADDR_BITS_16 ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) static inline int eeprom_no_data_bits(struct scsi_qla_host *ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) return FM93C56A_DATA_BITS_16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) static int fm93c56a_select(struct scsi_qla_host * ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) DEBUG5(printk(KERN_ERR "fm93c56a_select:\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) ha->eeprom_cmd_data = AUBURN_EEPROM_CS_1 | 0x000f0000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) eeprom_cmd(ha->eeprom_cmd_data, ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static int fm93c56a_cmd(struct scsi_qla_host * ha, int cmd, int addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) int mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) int dataBit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) int previousBit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /* Clock in a zero, then do the start bit. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) eeprom_cmd(ha->eeprom_cmd_data | AUBURN_EEPROM_DO_1, ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) eeprom_cmd(ha->eeprom_cmd_data | AUBURN_EEPROM_DO_1 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) AUBURN_EEPROM_CLK_RISE, ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) eeprom_cmd(ha->eeprom_cmd_data | AUBURN_EEPROM_DO_1 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) AUBURN_EEPROM_CLK_FALL, ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) mask = 1 << (FM93C56A_CMD_BITS - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) /* Force the previous data bit to be different. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) previousBit = 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) for (i = 0; i < FM93C56A_CMD_BITS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) dataBit =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) (cmd & mask) ? AUBURN_EEPROM_DO_1 : AUBURN_EEPROM_DO_0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) if (previousBit != dataBit) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * If the bit changed, then change the DO state to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * match.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) eeprom_cmd(ha->eeprom_cmd_data | dataBit, ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) previousBit = dataBit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) eeprom_cmd(ha->eeprom_cmd_data | dataBit |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) AUBURN_EEPROM_CLK_RISE, ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) eeprom_cmd(ha->eeprom_cmd_data | dataBit |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) AUBURN_EEPROM_CLK_FALL, ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) cmd = cmd << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) mask = 1 << (eeprom_no_addr_bits(ha) - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) /* Force the previous data bit to be different. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) previousBit = 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) for (i = 0; i < eeprom_no_addr_bits(ha); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) dataBit = addr & mask ? AUBURN_EEPROM_DO_1 :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) AUBURN_EEPROM_DO_0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) if (previousBit != dataBit) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) * If the bit changed, then change the DO state to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) * match.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) eeprom_cmd(ha->eeprom_cmd_data | dataBit, ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) previousBit = dataBit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) eeprom_cmd(ha->eeprom_cmd_data | dataBit |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) AUBURN_EEPROM_CLK_RISE, ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) eeprom_cmd(ha->eeprom_cmd_data | dataBit |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) AUBURN_EEPROM_CLK_FALL, ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) addr = addr << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) static int fm93c56a_deselect(struct scsi_qla_host * ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) ha->eeprom_cmd_data = AUBURN_EEPROM_CS_0 | 0x000f0000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) eeprom_cmd(ha->eeprom_cmd_data, ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static int fm93c56a_datain(struct scsi_qla_host * ha, unsigned short *value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) int data = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) int dataBit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) /* Read the data bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) * The first bit is a dummy. Clock right over it. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) for (i = 0; i < eeprom_no_data_bits(ha); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) eeprom_cmd(ha->eeprom_cmd_data |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) AUBURN_EEPROM_CLK_RISE, ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) eeprom_cmd(ha->eeprom_cmd_data |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) AUBURN_EEPROM_CLK_FALL, ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) dataBit = (readw(isp_nvram(ha)) & AUBURN_EEPROM_DI_1) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) data = (data << 1) | dataBit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) *value = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) static int eeprom_readword(int eepromAddr, u16 * value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) struct scsi_qla_host * ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) fm93c56a_select(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) fm93c56a_cmd(ha, FM93C56A_READ, eepromAddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) fm93c56a_datain(ha, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) fm93c56a_deselect(ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) /* Hardware_lock must be set before calling */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) u16 rd_nvram_word(struct scsi_qla_host * ha, int offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) u16 val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) /* NOTE: NVRAM uses half-word addresses */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) eeprom_readword(offset, &val, ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) u8 rd_nvram_byte(struct scsi_qla_host *ha, int offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) u16 val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) u8 rval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) int index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) if (offset & 0x1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) index = (offset - 1) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) index = offset / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) val = le16_to_cpu(rd_nvram_word(ha, index));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) if (offset & 0x1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) rval = (u8)((val & 0xff00) >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) rval = (u8)((val & 0x00ff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) int qla4xxx_is_nvram_configuration_valid(struct scsi_qla_host * ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) int status = QLA_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) uint16_t checksum = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) uint32_t index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) spin_lock_irqsave(&ha->hardware_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) for (index = 0; index < eeprom_size(ha); index++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) checksum += rd_nvram_word(ha, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) spin_unlock_irqrestore(&ha->hardware_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) if (checksum == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) status = QLA_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) /*************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) * Hardware Semaphore routines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) *************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) int ql4xxx_sem_spinlock(struct scsi_qla_host * ha, u32 sem_mask, u32 sem_bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) uint32_t value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) unsigned int seconds = 30;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) DEBUG2(printk("scsi%ld : Trying to get SEM lock - mask= 0x%x, code = "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) "0x%x\n", ha->host_no, sem_mask, sem_bits));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) spin_lock_irqsave(&ha->hardware_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) writel((sem_mask | sem_bits), isp_semaphore(ha));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) value = readw(isp_semaphore(ha));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) spin_unlock_irqrestore(&ha->hardware_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) if ((value & (sem_mask >> 16)) == sem_bits) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) DEBUG2(printk("scsi%ld : Got SEM LOCK - mask= 0x%x, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) "code = 0x%x\n", ha->host_no,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) sem_mask, sem_bits));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) return QLA_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) ssleep(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) } while (--seconds);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) return QLA_ERROR;
^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) void ql4xxx_sem_unlock(struct scsi_qla_host * ha, u32 sem_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) spin_lock_irqsave(&ha->hardware_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) writel(sem_mask, isp_semaphore(ha));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) readl(isp_semaphore(ha));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) spin_unlock_irqrestore(&ha->hardware_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) DEBUG2(printk("scsi%ld : UNLOCK SEM - mask= 0x%x\n", ha->host_no,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) sem_mask));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) int ql4xxx_sem_lock(struct scsi_qla_host * ha, u32 sem_mask, u32 sem_bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) uint32_t value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) spin_lock_irqsave(&ha->hardware_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) writel((sem_mask | sem_bits), isp_semaphore(ha));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) value = readw(isp_semaphore(ha));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) spin_unlock_irqrestore(&ha->hardware_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) if ((value & (sem_mask >> 16)) == sem_bits) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) DEBUG2(printk("scsi%ld : Got SEM LOCK - mask= 0x%x, code = "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) "0x%x, sema code=0x%x\n", ha->host_no,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) sem_mask, sem_bits, value));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) }