[iwm] Sync IWM_MVM_ALIVE waiting and start_fw handling with iwlwifi.
* Use the notification wait API, like it's done in the Linux iwlwifi code, to wait for the IWM_MVM_ALIVE notification. * This also should fix some firmware load interrupt issues, and errors in the nic lock using. Tested: * (adrian) Intel 7260, STA mode Obtained from: dragonflybsd.git a7697ea01c11fd493aec52260a02f31df680eb91
This commit is contained in:
parent
cebadebe7e
commit
36aeb6e0ad
@ -285,8 +285,14 @@ struct iwm_nvm_section {
|
||||
uint8_t *data;
|
||||
};
|
||||
|
||||
#define IWM_MVM_UCODE_ALIVE_TIMEOUT hz
|
||||
#define IWM_MVM_UCODE_CALIB_TIMEOUT (2*hz)
|
||||
|
||||
struct iwm_mvm_alive_data {
|
||||
int valid;
|
||||
uint32_t scd_base_addr;
|
||||
};
|
||||
|
||||
static int iwm_store_cscheme(struct iwm_softc *, const uint8_t *, size_t);
|
||||
static int iwm_firmware_store_section(struct iwm_softc *,
|
||||
enum iwm_ucode_type,
|
||||
@ -320,7 +326,7 @@ static int iwm_nic_rx_init(struct iwm_softc *);
|
||||
static int iwm_nic_tx_init(struct iwm_softc *);
|
||||
static int iwm_nic_init(struct iwm_softc *);
|
||||
static int iwm_enable_txq(struct iwm_softc *, int, int, int);
|
||||
static int iwm_post_alive(struct iwm_softc *);
|
||||
static int iwm_trans_pcie_fw_alive(struct iwm_softc *, uint32_t);
|
||||
static int iwm_nvm_read_chunk(struct iwm_softc *, uint16_t, uint16_t,
|
||||
uint16_t, uint8_t *, uint16_t *);
|
||||
static int iwm_nvm_read_section(struct iwm_softc *, uint16_t, uint8_t *,
|
||||
@ -367,7 +373,7 @@ static int iwm_pcie_load_given_ucode_8000(struct iwm_softc *,
|
||||
const struct iwm_fw_sects *);
|
||||
static int iwm_pcie_load_given_ucode(struct iwm_softc *,
|
||||
const struct iwm_fw_sects *);
|
||||
static int iwm_start_fw(struct iwm_softc *, enum iwm_ucode_type);
|
||||
static int iwm_start_fw(struct iwm_softc *, const struct iwm_fw_sects *);
|
||||
static int iwm_send_tx_ant_cfg(struct iwm_softc *, uint8_t);
|
||||
static int iwm_send_phy_cfg_cmd(struct iwm_softc *);
|
||||
static int iwm_mvm_load_ucode_wait_alive(struct iwm_softc *,
|
||||
@ -1633,20 +1639,33 @@ iwm_enable_txq(struct iwm_softc *sc, int sta_id, int qid, int fifo)
|
||||
(0 << IWM_SCD_QUEUE_STTS_REG_POS_ACTIVE)
|
||||
| (1 << IWM_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN));
|
||||
|
||||
iwm_nic_unlock(sc);
|
||||
|
||||
iwm_clear_bits_prph(sc, IWM_SCD_AGGR_SEL, (1 << qid));
|
||||
|
||||
if (!iwm_nic_lock(sc)) {
|
||||
device_printf(sc->sc_dev,
|
||||
"%s: cannot enable txq %d\n", __func__, qid);
|
||||
return EBUSY;
|
||||
}
|
||||
iwm_write_prph(sc, IWM_SCD_QUEUE_RDPTR(qid), 0);
|
||||
iwm_nic_unlock(sc);
|
||||
|
||||
iwm_write_mem32(sc, sc->sched_base + IWM_SCD_CONTEXT_QUEUE_OFFSET(qid), 0);
|
||||
iwm_write_mem32(sc, sc->scd_base_addr + IWM_SCD_CONTEXT_QUEUE_OFFSET(qid), 0);
|
||||
/* Set scheduler window size and frame limit. */
|
||||
iwm_write_mem32(sc,
|
||||
sc->sched_base + IWM_SCD_CONTEXT_QUEUE_OFFSET(qid) +
|
||||
sc->scd_base_addr + IWM_SCD_CONTEXT_QUEUE_OFFSET(qid) +
|
||||
sizeof(uint32_t),
|
||||
((IWM_FRAME_LIMIT << IWM_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) &
|
||||
IWM_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) |
|
||||
((IWM_FRAME_LIMIT << IWM_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) &
|
||||
IWM_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK));
|
||||
|
||||
if (!iwm_nic_lock(sc)) {
|
||||
device_printf(sc->sc_dev,
|
||||
"%s: cannot enable txq %d\n", __func__, qid);
|
||||
return EBUSY;
|
||||
}
|
||||
iwm_write_prph(sc, IWM_SCD_QUEUE_STATUS_BITS(qid),
|
||||
(1 << IWM_SCD_QUEUE_STTS_REG_POS_ACTIVE) |
|
||||
(fifo << IWM_SCD_QUEUE_STTS_REG_POS_TXF) |
|
||||
@ -1690,33 +1709,37 @@ iwm_enable_txq(struct iwm_softc *sc, int sta_id, int qid, int fifo)
|
||||
}
|
||||
|
||||
static int
|
||||
iwm_post_alive(struct iwm_softc *sc)
|
||||
iwm_trans_pcie_fw_alive(struct iwm_softc *sc, uint32_t scd_base_addr)
|
||||
{
|
||||
int nwords;
|
||||
int error, chnl;
|
||||
uint32_t base;
|
||||
|
||||
int clear_dwords = (IWM_SCD_TRANS_TBL_MEM_UPPER_BOUND -
|
||||
IWM_SCD_CONTEXT_MEM_LOWER_BOUND) / sizeof(uint32_t);
|
||||
|
||||
if (!iwm_nic_lock(sc))
|
||||
return EBUSY;
|
||||
|
||||
base = iwm_read_prph(sc, IWM_SCD_SRAM_BASE_ADDR);
|
||||
if (sc->sched_base != base) {
|
||||
device_printf(sc->sc_dev,
|
||||
"%s: sched addr mismatch: alive: 0x%x prph: 0x%x\n",
|
||||
__func__, sc->sched_base, base);
|
||||
}
|
||||
|
||||
iwm_ict_reset(sc);
|
||||
|
||||
/* Clear TX scheduler state in SRAM. */
|
||||
nwords = (IWM_SCD_TRANS_TBL_MEM_UPPER_BOUND -
|
||||
IWM_SCD_CONTEXT_MEM_LOWER_BOUND)
|
||||
/ sizeof(uint32_t);
|
||||
iwm_nic_unlock(sc);
|
||||
|
||||
sc->scd_base_addr = iwm_read_prph(sc, IWM_SCD_SRAM_BASE_ADDR);
|
||||
if (scd_base_addr != 0 &&
|
||||
scd_base_addr != sc->scd_base_addr) {
|
||||
device_printf(sc->sc_dev,
|
||||
"%s: sched addr mismatch: alive: 0x%x prph: 0x%x\n",
|
||||
__func__, sc->scd_base_addr, scd_base_addr);
|
||||
}
|
||||
|
||||
/* reset context data, TX status and translation data */
|
||||
error = iwm_write_mem(sc,
|
||||
sc->sched_base + IWM_SCD_CONTEXT_MEM_LOWER_BOUND,
|
||||
NULL, nwords);
|
||||
sc->scd_base_addr + IWM_SCD_CONTEXT_MEM_LOWER_BOUND,
|
||||
NULL, clear_dwords);
|
||||
if (error)
|
||||
goto out;
|
||||
return EBUSY;
|
||||
|
||||
if (!iwm_nic_lock(sc))
|
||||
return EBUSY;
|
||||
|
||||
/* Set physical address of TX scheduler rings (1KB aligned). */
|
||||
iwm_write_prph(sc, IWM_SCD_DRAM_BASE_ADDR, sc->sched_dma.paddr >> 10);
|
||||
@ -1745,14 +1768,14 @@ iwm_post_alive(struct iwm_softc *sc)
|
||||
IWM_SETBITS(sc, IWM_FH_TX_CHICKEN_BITS_REG,
|
||||
IWM_FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN);
|
||||
|
||||
iwm_nic_unlock(sc);
|
||||
|
||||
/* Enable L1-Active */
|
||||
if (sc->cfg->device_family != IWM_DEVICE_FAMILY_8000) {
|
||||
iwm_clear_bits_prph(sc, IWM_APMG_PCIDEV_STT_REG,
|
||||
IWM_APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
|
||||
}
|
||||
|
||||
out:
|
||||
iwm_nic_unlock(sc);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -2589,6 +2612,8 @@ iwm_pcie_load_cpu_sections_8000(struct iwm_softc *sc,
|
||||
|
||||
*first_ucode_section = last_read_idx;
|
||||
|
||||
iwm_enable_interrupts(sc);
|
||||
|
||||
if (iwm_nic_lock(sc)) {
|
||||
if (cpu == 1)
|
||||
IWM_WRITE(sc, IWM_FH_UCODE_LOAD_STATUS, 0xFFFF);
|
||||
@ -2681,6 +2706,9 @@ iwm_pcie_load_given_ucode(struct iwm_softc *sc,
|
||||
return ret;
|
||||
}
|
||||
|
||||
iwm_enable_interrupts(sc);
|
||||
|
||||
/* release CPU reset */
|
||||
IWM_WRITE(sc, IWM_CSR_RESET, 0);
|
||||
|
||||
return 0;
|
||||
@ -2711,59 +2739,56 @@ iwm_pcie_load_given_ucode_8000(struct iwm_softc *sc,
|
||||
&first_ucode_section);
|
||||
}
|
||||
|
||||
static int
|
||||
iwm_load_firmware(struct iwm_softc *sc, enum iwm_ucode_type ucode_type)
|
||||
/* XXX Get rid of this definition */
|
||||
static inline void
|
||||
iwm_enable_fw_load_int(struct iwm_softc *sc)
|
||||
{
|
||||
int error, w;
|
||||
|
||||
if (sc->cfg->device_family == IWM_DEVICE_FAMILY_8000) {
|
||||
error = iwm_pcie_load_given_ucode_8000(sc,
|
||||
&sc->sc_fw.fw_sects[ucode_type]);
|
||||
} else {
|
||||
error = iwm_pcie_load_given_ucode(sc,
|
||||
&sc->sc_fw.fw_sects[ucode_type]);
|
||||
}
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/* wait for the firmware to load */
|
||||
for (w = 0; !sc->sc_uc.uc_intr && w < 10; w++) {
|
||||
error = msleep(&sc->sc_uc, &sc->sc_mtx, 0, "iwmuc", hz/10);
|
||||
}
|
||||
if (error || !sc->sc_uc.uc_ok) {
|
||||
device_printf(sc->sc_dev, "could not load firmware\n");
|
||||
if (sc->cfg->device_family == IWM_DEVICE_FAMILY_8000) {
|
||||
device_printf(sc->sc_dev, "cpu1 status: 0x%x\n",
|
||||
iwm_read_prph(sc, IWM_SB_CPU_1_STATUS));
|
||||
device_printf(sc->sc_dev, "cpu2 status: 0x%x\n",
|
||||
iwm_read_prph(sc, IWM_SB_CPU_2_STATUS));
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
IWM_DPRINTF(sc, IWM_DEBUG_INTR, "Enabling FW load interrupt\n");
|
||||
sc->sc_intmask = IWM_CSR_INT_BIT_FH_TX;
|
||||
IWM_WRITE(sc, IWM_CSR_INT_MASK, sc->sc_intmask);
|
||||
}
|
||||
|
||||
/* iwlwifi: pcie/trans.c */
|
||||
/* XXX Add proper rfkill support code */
|
||||
static int
|
||||
iwm_start_fw(struct iwm_softc *sc, enum iwm_ucode_type ucode_type)
|
||||
iwm_start_fw(struct iwm_softc *sc,
|
||||
const struct iwm_fw_sects *fw)
|
||||
{
|
||||
int error;
|
||||
int ret;
|
||||
|
||||
IWM_WRITE(sc, IWM_CSR_INT, ~0);
|
||||
|
||||
if ((error = iwm_nic_init(sc)) != 0) {
|
||||
device_printf(sc->sc_dev, "unable to init nic\n");
|
||||
return error;
|
||||
/* This may fail if AMT took ownership of the device */
|
||||
if (iwm_prepare_card_hw(sc)) {
|
||||
device_printf(sc->sc_dev,
|
||||
"%s: Exit HW not ready\n", __func__);
|
||||
ret = EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
IWM_WRITE(sc, IWM_CSR_INT, 0xFFFFFFFF);
|
||||
|
||||
iwm_disable_interrupts(sc);
|
||||
|
||||
/* make sure rfkill handshake bits are cleared */
|
||||
IWM_WRITE(sc, IWM_CSR_UCODE_DRV_GP1_CLR, IWM_CSR_UCODE_SW_BIT_RFKILL);
|
||||
IWM_WRITE(sc, IWM_CSR_UCODE_DRV_GP1_CLR,
|
||||
IWM_CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
|
||||
|
||||
/* clear (again), then enable host interrupts */
|
||||
IWM_WRITE(sc, IWM_CSR_INT, ~0);
|
||||
iwm_enable_interrupts(sc);
|
||||
IWM_WRITE(sc, IWM_CSR_INT, 0xFFFFFFFF);
|
||||
|
||||
ret = iwm_nic_init(sc);
|
||||
if (ret) {
|
||||
device_printf(sc->sc_dev, "%s: Unable to init nic\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now, we load the firmware and don't want to be interrupted, even
|
||||
* by the RF-Kill interrupt (hence mask all the interrupt besides the
|
||||
* FH_TX interrupt which is needed to load the firmware). If the
|
||||
* RF-Kill switch is toggled, we will find out after having loaded
|
||||
* the firmware and return the proper value to the caller.
|
||||
*/
|
||||
iwm_enable_fw_load_int(sc);
|
||||
|
||||
/* really make sure rfkill handshake bits are cleared */
|
||||
/* maybe we should write a few times more? just to make sure */
|
||||
@ -2771,7 +2796,15 @@ iwm_start_fw(struct iwm_softc *sc, enum iwm_ucode_type ucode_type)
|
||||
IWM_WRITE(sc, IWM_CSR_UCODE_DRV_GP1_CLR, IWM_CSR_UCODE_SW_BIT_RFKILL);
|
||||
|
||||
/* Load the given image to the HW */
|
||||
return iwm_load_firmware(sc, ucode_type);
|
||||
if (sc->cfg->device_family == IWM_DEVICE_FAMILY_8000)
|
||||
ret = iwm_pcie_load_given_ucode_8000(sc, fw);
|
||||
else
|
||||
ret = iwm_pcie_load_given_ucode(sc, fw);
|
||||
|
||||
/* XXX re-check RF-Kill state */
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -2790,7 +2823,7 @@ static int
|
||||
iwm_send_phy_cfg_cmd(struct iwm_softc *sc)
|
||||
{
|
||||
struct iwm_phy_cfg_cmd phy_cfg_cmd;
|
||||
enum iwm_ucode_type ucode_type = sc->sc_uc_current;
|
||||
enum iwm_ucode_type ucode_type = sc->cur_ucode;
|
||||
|
||||
/* Set parameters */
|
||||
phy_cfg_cmd.phy_cfg = htole32(iwm_mvm_get_phy_config(sc));
|
||||
@ -2805,6 +2838,83 @@ iwm_send_phy_cfg_cmd(struct iwm_softc *sc)
|
||||
sizeof(phy_cfg_cmd), &phy_cfg_cmd);
|
||||
}
|
||||
|
||||
static int
|
||||
iwm_alive_fn(struct iwm_softc *sc, struct iwm_rx_packet *pkt, void *data)
|
||||
{
|
||||
struct iwm_mvm_alive_data *alive_data = data;
|
||||
struct iwm_mvm_alive_resp_ver1 *palive1;
|
||||
struct iwm_mvm_alive_resp_ver2 *palive2;
|
||||
struct iwm_mvm_alive_resp *palive;
|
||||
|
||||
if (iwm_rx_packet_payload_len(pkt) == sizeof(*palive1)) {
|
||||
palive1 = (void *)pkt->data;
|
||||
|
||||
sc->support_umac_log = FALSE;
|
||||
sc->error_event_table =
|
||||
le32toh(palive1->error_event_table_ptr);
|
||||
sc->log_event_table =
|
||||
le32toh(palive1->log_event_table_ptr);
|
||||
alive_data->scd_base_addr = le32toh(palive1->scd_base_ptr);
|
||||
|
||||
alive_data->valid = le16toh(palive1->status) ==
|
||||
IWM_ALIVE_STATUS_OK;
|
||||
IWM_DPRINTF(sc, IWM_DEBUG_RESET,
|
||||
"Alive VER1 ucode status 0x%04x revision 0x%01X 0x%01X flags 0x%01X\n",
|
||||
le16toh(palive1->status), palive1->ver_type,
|
||||
palive1->ver_subtype, palive1->flags);
|
||||
} else if (iwm_rx_packet_payload_len(pkt) == sizeof(*palive2)) {
|
||||
palive2 = (void *)pkt->data;
|
||||
sc->error_event_table =
|
||||
le32toh(palive2->error_event_table_ptr);
|
||||
sc->log_event_table =
|
||||
le32toh(palive2->log_event_table_ptr);
|
||||
alive_data->scd_base_addr = le32toh(palive2->scd_base_ptr);
|
||||
sc->umac_error_event_table =
|
||||
le32toh(palive2->error_info_addr);
|
||||
|
||||
alive_data->valid = le16toh(palive2->status) ==
|
||||
IWM_ALIVE_STATUS_OK;
|
||||
if (sc->umac_error_event_table)
|
||||
sc->support_umac_log = TRUE;
|
||||
|
||||
IWM_DPRINTF(sc, IWM_DEBUG_RESET,
|
||||
"Alive VER2 ucode status 0x%04x revision 0x%01X 0x%01X flags 0x%01X\n",
|
||||
le16toh(palive2->status), palive2->ver_type,
|
||||
palive2->ver_subtype, palive2->flags);
|
||||
|
||||
IWM_DPRINTF(sc, IWM_DEBUG_RESET,
|
||||
"UMAC version: Major - 0x%x, Minor - 0x%x\n",
|
||||
palive2->umac_major, palive2->umac_minor);
|
||||
} else if (iwm_rx_packet_payload_len(pkt) == sizeof(*palive)) {
|
||||
palive = (void *)pkt->data;
|
||||
|
||||
sc->error_event_table =
|
||||
le32toh(palive->error_event_table_ptr);
|
||||
sc->log_event_table =
|
||||
le32toh(palive->log_event_table_ptr);
|
||||
alive_data->scd_base_addr = le32toh(palive->scd_base_ptr);
|
||||
sc->umac_error_event_table =
|
||||
le32toh(palive->error_info_addr);
|
||||
|
||||
alive_data->valid = le16toh(palive->status) ==
|
||||
IWM_ALIVE_STATUS_OK;
|
||||
if (sc->umac_error_event_table)
|
||||
sc->support_umac_log = TRUE;
|
||||
|
||||
IWM_DPRINTF(sc, IWM_DEBUG_RESET,
|
||||
"Alive VER3 ucode status 0x%04x revision 0x%01X 0x%01X flags 0x%01X\n",
|
||||
le16toh(palive->status), palive->ver_type,
|
||||
palive->ver_subtype, palive->flags);
|
||||
|
||||
IWM_DPRINTF(sc, IWM_DEBUG_RESET,
|
||||
"UMAC version: Major - 0x%x, Minor - 0x%x\n",
|
||||
le32toh(palive->umac_major),
|
||||
le32toh(palive->umac_minor));
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int
|
||||
iwm_wait_phy_db_entry(struct iwm_softc *sc,
|
||||
struct iwm_rx_packet *pkt, void *data)
|
||||
@ -2831,27 +2941,76 @@ static int
|
||||
iwm_mvm_load_ucode_wait_alive(struct iwm_softc *sc,
|
||||
enum iwm_ucode_type ucode_type)
|
||||
{
|
||||
enum iwm_ucode_type old_type = sc->sc_uc_current;
|
||||
struct iwm_notification_wait alive_wait;
|
||||
struct iwm_mvm_alive_data alive_data;
|
||||
const struct iwm_fw_sects *fw;
|
||||
enum iwm_ucode_type old_type = sc->cur_ucode;
|
||||
int error;
|
||||
static const uint16_t alive_cmd[] = { IWM_MVM_ALIVE };
|
||||
|
||||
if ((error = iwm_read_firmware(sc, ucode_type)) != 0) {
|
||||
device_printf(sc->sc_dev, "iwm_read_firmware: failed %d\n",
|
||||
error);
|
||||
return error;
|
||||
}
|
||||
fw = &sc->sc_fw.fw_sects[ucode_type];
|
||||
sc->cur_ucode = ucode_type;
|
||||
sc->ucode_loaded = FALSE;
|
||||
|
||||
sc->sc_uc_current = ucode_type;
|
||||
error = iwm_start_fw(sc, ucode_type);
|
||||
memset(&alive_data, 0, sizeof(alive_data));
|
||||
iwm_init_notification_wait(sc->sc_notif_wait, &alive_wait,
|
||||
alive_cmd, nitems(alive_cmd),
|
||||
iwm_alive_fn, &alive_data);
|
||||
|
||||
error = iwm_start_fw(sc, fw);
|
||||
if (error) {
|
||||
device_printf(sc->sc_dev, "iwm_start_fw: failed %d\n", error);
|
||||
sc->sc_uc_current = old_type;
|
||||
sc->cur_ucode = old_type;
|
||||
iwm_remove_notification(sc->sc_notif_wait, &alive_wait);
|
||||
return error;
|
||||
}
|
||||
|
||||
error = iwm_post_alive(sc);
|
||||
/*
|
||||
* Some things may run in the background now, but we
|
||||
* just wait for the ALIVE notification here.
|
||||
*/
|
||||
IWM_UNLOCK(sc);
|
||||
error = iwm_wait_notification(sc->sc_notif_wait, &alive_wait,
|
||||
IWM_MVM_UCODE_ALIVE_TIMEOUT);
|
||||
IWM_LOCK(sc);
|
||||
if (error) {
|
||||
device_printf(sc->sc_dev, "iwm_fw_alive: failed %d\n", error);
|
||||
if (sc->cfg->device_family == IWM_DEVICE_FAMILY_8000) {
|
||||
device_printf(sc->sc_dev,
|
||||
"SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\n",
|
||||
iwm_read_prph(sc, IWM_SB_CPU_1_STATUS),
|
||||
iwm_read_prph(sc, IWM_SB_CPU_2_STATUS));
|
||||
}
|
||||
sc->cur_ucode = old_type;
|
||||
return error;
|
||||
}
|
||||
|
||||
if (!alive_data.valid) {
|
||||
device_printf(sc->sc_dev, "%s: Loaded ucode is not valid\n",
|
||||
__func__);
|
||||
sc->cur_ucode = old_type;
|
||||
return EIO;
|
||||
}
|
||||
|
||||
iwm_trans_pcie_fw_alive(sc, alive_data.scd_base_addr);
|
||||
|
||||
/*
|
||||
* configure and operate fw paging mechanism.
|
||||
* driver configures the paging flow only once, CPU2 paging image
|
||||
* included in the IWM_UCODE_INIT image.
|
||||
*/
|
||||
if (fw->paging_mem_size) {
|
||||
/* XXX implement FW paging */
|
||||
device_printf(sc->sc_dev,
|
||||
"%s: XXX FW paging not implemented yet\n", __func__);
|
||||
}
|
||||
|
||||
if (!error)
|
||||
sc->ucode_loaded = TRUE;
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -5201,7 +5360,7 @@ iwm_nic_umac_error(struct iwm_softc *sc)
|
||||
struct iwm_umac_error_event_table table;
|
||||
uint32_t base;
|
||||
|
||||
base = sc->sc_uc.uc_umac_error_event_table;
|
||||
base = sc->umac_error_event_table;
|
||||
|
||||
if (base < 0x800000) {
|
||||
device_printf(sc->sc_dev, "Invalid error log pointer 0x%08x\n",
|
||||
@ -5256,7 +5415,7 @@ iwm_nic_error(struct iwm_softc *sc)
|
||||
uint32_t base;
|
||||
|
||||
device_printf(sc->sc_dev, "dumping device error log\n");
|
||||
base = sc->sc_uc.uc_error_event_table;
|
||||
base = sc->umac_error_event_table;
|
||||
if (base < 0x800000) {
|
||||
device_printf(sc->sc_dev,
|
||||
"Invalid error log pointer 0x%08x\n", base);
|
||||
@ -5318,7 +5477,7 @@ iwm_nic_error(struct iwm_softc *sc)
|
||||
device_printf(sc->sc_dev, "%08X | timestamp\n", table.u_timestamp);
|
||||
device_printf(sc->sc_dev, "%08X | flow_handler\n", table.flow_handler);
|
||||
|
||||
if (sc->sc_uc.uc_umac_error_event_table)
|
||||
if (sc->umac_error_event_table)
|
||||
iwm_nic_umac_error(sc);
|
||||
}
|
||||
#endif
|
||||
@ -5428,57 +5587,8 @@ iwm_notif_intr(struct iwm_softc *sc)
|
||||
case IWM_MFUART_LOAD_NOTIFICATION:
|
||||
break;
|
||||
|
||||
case IWM_MVM_ALIVE: {
|
||||
struct iwm_mvm_alive_resp_v1 *resp1;
|
||||
struct iwm_mvm_alive_resp_v2 *resp2;
|
||||
struct iwm_mvm_alive_resp_v3 *resp3;
|
||||
|
||||
if (iwm_rx_packet_payload_len(pkt) == sizeof(*resp1)) {
|
||||
resp1 = (void *)pkt->data;
|
||||
sc->sc_uc.uc_error_event_table
|
||||
= le32toh(resp1->error_event_table_ptr);
|
||||
sc->sc_uc.uc_log_event_table
|
||||
= le32toh(resp1->log_event_table_ptr);
|
||||
sc->sched_base = le32toh(resp1->scd_base_ptr);
|
||||
if (resp1->status == IWM_ALIVE_STATUS_OK)
|
||||
sc->sc_uc.uc_ok = 1;
|
||||
else
|
||||
sc->sc_uc.uc_ok = 0;
|
||||
}
|
||||
|
||||
if (iwm_rx_packet_payload_len(pkt) == sizeof(*resp2)) {
|
||||
resp2 = (void *)pkt->data;
|
||||
sc->sc_uc.uc_error_event_table
|
||||
= le32toh(resp2->error_event_table_ptr);
|
||||
sc->sc_uc.uc_log_event_table
|
||||
= le32toh(resp2->log_event_table_ptr);
|
||||
sc->sched_base = le32toh(resp2->scd_base_ptr);
|
||||
sc->sc_uc.uc_umac_error_event_table
|
||||
= le32toh(resp2->error_info_addr);
|
||||
if (resp2->status == IWM_ALIVE_STATUS_OK)
|
||||
sc->sc_uc.uc_ok = 1;
|
||||
else
|
||||
sc->sc_uc.uc_ok = 0;
|
||||
}
|
||||
|
||||
if (iwm_rx_packet_payload_len(pkt) == sizeof(*resp3)) {
|
||||
resp3 = (void *)pkt->data;
|
||||
sc->sc_uc.uc_error_event_table
|
||||
= le32toh(resp3->error_event_table_ptr);
|
||||
sc->sc_uc.uc_log_event_table
|
||||
= le32toh(resp3->log_event_table_ptr);
|
||||
sc->sched_base = le32toh(resp3->scd_base_ptr);
|
||||
sc->sc_uc.uc_umac_error_event_table
|
||||
= le32toh(resp3->error_info_addr);
|
||||
if (resp3->status == IWM_ALIVE_STATUS_OK)
|
||||
sc->sc_uc.uc_ok = 1;
|
||||
else
|
||||
sc->sc_uc.uc_ok = 0;
|
||||
}
|
||||
|
||||
sc->sc_uc.uc_intr = 1;
|
||||
wakeup(&sc->sc_uc);
|
||||
break; }
|
||||
case IWM_MVM_ALIVE:
|
||||
break;
|
||||
|
||||
case IWM_CALIB_RES_NOTIF_PHY_DB:
|
||||
break;
|
||||
@ -5730,8 +5840,8 @@ iwm_intr(void *arg)
|
||||
|
||||
IWM_WRITE(sc, IWM_CSR_INT, r1 | ~sc->sc_intmask);
|
||||
|
||||
/* ignored */
|
||||
handled |= (r1 & (IWM_CSR_INT_BIT_ALIVE /*| IWM_CSR_INT_BIT_SCD*/));
|
||||
/* Safely ignore these bits for debug checks below */
|
||||
r1 &= ~(IWM_CSR_INT_BIT_ALIVE | IWM_CSR_INT_BIT_SCD);
|
||||
|
||||
if (r1 & IWM_CSR_INT_BIT_SW_ERR) {
|
||||
int i;
|
||||
|
@ -2141,7 +2141,7 @@ enum {
|
||||
|
||||
#define IWM_ALIVE_FLG_RFKILL (1 << 0)
|
||||
|
||||
struct iwm_mvm_alive_resp_v1 {
|
||||
struct iwm_mvm_alive_resp_ver1 {
|
||||
uint16_t status;
|
||||
uint16_t flags;
|
||||
uint8_t ucode_minor;
|
||||
@ -2163,7 +2163,7 @@ struct iwm_mvm_alive_resp_v1 {
|
||||
uint32_t scd_base_ptr; /* SRAM address for SCD */
|
||||
} __packed; /* IWM_ALIVE_RES_API_S_VER_1 */
|
||||
|
||||
struct iwm_mvm_alive_resp_v2 {
|
||||
struct iwm_mvm_alive_resp_ver2 {
|
||||
uint16_t status;
|
||||
uint16_t flags;
|
||||
uint8_t ucode_minor;
|
||||
@ -2185,14 +2185,14 @@ struct iwm_mvm_alive_resp_v2 {
|
||||
uint32_t scd_base_ptr; /* SRAM address for SCD */
|
||||
uint32_t st_fwrd_addr; /* pointer to Store and forward */
|
||||
uint32_t st_fwrd_size;
|
||||
uint8_t umac_minor; /* UMAC version: minor */
|
||||
uint8_t umac_major; /* UMAC version: major */
|
||||
uint16_t umac_id; /* UMAC version: id */
|
||||
uint32_t error_info_addr; /* SRAM address for UMAC error log */
|
||||
uint8_t umac_minor; /* UMAC version: minor */
|
||||
uint8_t umac_major; /* UMAC version: major */
|
||||
uint16_t umac_id; /* UMAC version: id */
|
||||
uint32_t error_info_addr; /* SRAM address for UMAC error log */
|
||||
uint32_t dbg_print_buff_addr;
|
||||
} __packed; /* ALIVE_RES_API_S_VER_2 */
|
||||
|
||||
struct iwm_mvm_alive_resp_v3 {
|
||||
struct iwm_mvm_alive_resp {
|
||||
uint16_t status;
|
||||
uint16_t flags;
|
||||
uint32_t ucode_minor;
|
||||
@ -2212,7 +2212,7 @@ struct iwm_mvm_alive_resp_v3 {
|
||||
uint32_t st_fwrd_size;
|
||||
uint32_t umac_minor; /* UMAC version: minor */
|
||||
uint32_t umac_major; /* UMAC version: major */
|
||||
uint32_t error_info_addr; /* SRAM address for UMAC error log */
|
||||
uint32_t error_info_addr; /* SRAM address for UMAC error log */
|
||||
uint32_t dbg_print_buff_addr;
|
||||
} __packed; /* ALIVE_RES_API_S_VER_3 */
|
||||
|
||||
|
@ -299,15 +299,6 @@ struct iwm_rx_ring {
|
||||
int cur;
|
||||
};
|
||||
|
||||
struct iwm_ucode_status {
|
||||
uint32_t uc_error_event_table;
|
||||
uint32_t uc_umac_error_event_table;
|
||||
uint32_t uc_log_event_table;
|
||||
|
||||
int uc_ok;
|
||||
int uc_intr;
|
||||
};
|
||||
|
||||
#define IWM_CMD_RESP_MAX PAGE_SIZE
|
||||
|
||||
#define IWM_MVM_TE_SESSION_PROTECTION_MAX_TIME_MS 500
|
||||
@ -440,7 +431,7 @@ struct iwm_softc {
|
||||
|
||||
/* TX scheduler rings. */
|
||||
struct iwm_dma_info sched_dma;
|
||||
uint32_t sched_base;
|
||||
uint32_t scd_base_addr;
|
||||
|
||||
/* TX/RX rings. */
|
||||
struct iwm_tx_ring txq[IWM_MVM_MAX_QUEUES];
|
||||
@ -461,8 +452,8 @@ struct iwm_softc {
|
||||
|
||||
int sc_fw_chunk_done;
|
||||
|
||||
struct iwm_ucode_status sc_uc;
|
||||
enum iwm_ucode_type sc_uc_current;
|
||||
enum iwm_ucode_type cur_ucode;
|
||||
int ucode_loaded;
|
||||
char sc_fwver[32];
|
||||
|
||||
int sc_capaflags;
|
||||
@ -530,6 +521,12 @@ struct iwm_softc {
|
||||
struct iwm_notif_wait_data *sc_notif_wait;
|
||||
|
||||
int cmd_hold_nic_awake;
|
||||
|
||||
/* Firmware status */
|
||||
uint32_t error_event_table;
|
||||
uint32_t log_event_table;
|
||||
uint32_t umac_error_event_table;
|
||||
int support_umac_log;
|
||||
};
|
||||
|
||||
#define IWM_LOCK_INIT(_sc) \
|
||||
|
Loading…
x
Reference in New Issue
Block a user