/** * heci_reset - resets host and fw. * * @dev: the device structure * @interrupts_enabled: if interrupt should be enabled after reset. */ void heci_reset(struct heci_device *dev, int interrupts_enabled) { bool unexpected; int ret; unexpected = (dev->dev_state != HECI_DEV_INITIALIZING && dev->dev_state != HECI_DEV_DISABLED && dev->dev_state != HECI_DEV_POWER_DOWN && dev->dev_state != HECI_DEV_POWER_UP); ret = heci_hw_reset(dev, interrupts_enabled); if (ret) { dev_err(&dev->pdev->dev, "hw reset failed disabling the device\n"); interrupts_enabled = false; dev->dev_state = HECI_DEV_DISABLED; } dev->hbm_state = HECI_HBM_IDLE; if (dev->dev_state != HECI_DEV_INITIALIZING) { if (dev->dev_state != HECI_DEV_DISABLED && dev->dev_state != HECI_DEV_POWER_DOWN) dev->dev_state = HECI_DEV_RESETTING; heci_cl_all_disconnect(dev); memset(&dev->wr_ext_msg, 0, sizeof(dev->wr_ext_msg)); } dev->me_clients_num = 0; dev->rd_msg_hdr = 0; if (unexpected) dev_warn(&dev->pdev->dev, "unexpected reset: dev_state = %s\n", heci_dev_state_str(dev->dev_state)); if (!interrupts_enabled) { dev_dbg(&dev->pdev->dev, "intr not enabled end of reset\n"); return; } dev_dbg(&dev->pdev->dev, "before sending HOST start\n"); ret = heci_hw_start(dev); if (ret) { dev_err(&dev->pdev->dev, "hw_start failed disabling the device\n"); dev->dev_state = HECI_DEV_DISABLED; return; } dev_dbg(&dev->pdev->dev, "link is established start sending messages.\n"); /* link is established * start sending messages. */ dev->dev_state = HECI_DEV_INIT_CLIENTS; dev->hbm_state = HECI_HBM_START; heci_hbm_start_req(dev); /* wake up all readings so they can be interrupted */ heci_cl_all_read_wakeup(dev); /* remove all waiting requests */ heci_cl_all_write_clear(dev); }
/* * heci_reset - reset host and fw. * * @dev: Device object for our driver * @interrupts: if interrupt should be enable after reset. */ void heci_reset(struct iamt_heci_device *dev, int interrupts) { struct heci_file_private *file_pos = NULL; struct heci_file_private *file_next = NULL; struct heci_cb_private *priv_cb_pos = NULL; struct heci_cb_private *priv_cb_next = NULL; int unexpected = 0; if (dev->heci_state == HECI_RECOVERING_FROM_RESET) { dev->need_reset = 1; return; } if (dev->heci_state != HECI_INITIALIZING && dev->heci_state != HECI_DISABLED && dev->heci_state != HECI_POWER_DOWN && dev->heci_state != HECI_POWER_UP) unexpected = 1; if (dev->reinit_tsk != NULL) { mutex_exit(&dev->device_lock); (void) ddi_taskq_wait(dev->reinit_tsk); mutex_enter(&dev->device_lock); } dev->host_hw_state = read_heci_register(dev, H_CSR); DBG("before reset host_hw_state = 0x%08x.\n", dev->host_hw_state); heci_hw_reset(dev, interrupts); dev->host_hw_state &= ~H_RST; dev->host_hw_state |= H_IG; write_heci_register(dev, H_CSR, dev->host_hw_state); DBG("currently saved host_hw_state = 0x%08x.\n", dev->host_hw_state); dev->need_reset = 0; if (dev->heci_state != HECI_INITIALIZING) { if ((dev->heci_state != HECI_DISABLED) && (dev->heci_state != HECI_POWER_DOWN)) dev->heci_state = HECI_RESETING; list_for_each_entry_safe(file_pos, file_next, &dev->file_list, link, struct heci_file_private) { file_pos->state = HECI_FILE_DISCONNECTED; file_pos->flow_ctrl_creds = 0; file_pos->read_cb = NULL; file_pos->timer_count = 0; } /* remove entry if already in list */ DBG("list del iamthif and wd file list.\n"); heci_remove_client_from_file_list(dev, dev->wd_file_ext.host_client_id); heci_remove_client_from_file_list(dev, dev->iamthif_file_ext.host_client_id); heci_reset_iamthif_params(dev); dev->wd_due_counter = 0; dev->extra_write_index = 0; } dev->num_heci_me_clients = 0; dev->rd_msg_hdr = 0; dev->stop = 0; dev->wd_pending = 0; /* update the state of the registers after reset */ dev->host_hw_state = read_heci_register(dev, H_CSR); dev->me_hw_state = read_heci_register(dev, ME_CSR_HA); DBG("after reset host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n", dev->host_hw_state, dev->me_hw_state); if (unexpected) cmn_err(CE_WARN, "unexpected heci reset.\n"); /* Wake up all readings so they can be interrupted */ list_for_each_entry_safe(file_pos, file_next, &dev->file_list, link, struct heci_file_private) { cmn_err(CE_NOTE, "heci: Waking up client!\n"); cv_broadcast(&file_pos->rx_wait); } /* remove all waiting requests */ if (dev->write_list.status == 0 && !list_empty(&dev->write_list.heci_cb.cb_list)) { list_for_each_entry_safe(priv_cb_pos, priv_cb_next, &dev->write_list.heci_cb.cb_list, cb_list, struct heci_cb_private) { if (priv_cb_pos) { list_del(&priv_cb_pos->cb_list); heci_free_cb_private(priv_cb_pos); } } }