617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * Use is subject to license terms.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * Part of Intel(R) Manageability Engine Interface Linux driver
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * Copyright (c) 2003 - 2008 Intel Corp.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * All rights reserved.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * Redistribution and use in source and binary forms, with or without
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * modification, are permitted provided that the following conditions
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * are met:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * 1. Redistributions of source code must retain the above copyright
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * notice, this list of conditions, and the following disclaimer,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * without modification.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * 2. Redistributions in binary form must reproduce at minimum a disclaimer
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * substantially similar to the "NO WARRANTY" disclaimer below
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * ("Disclaimer") and any redistribution must be conditioned upon
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * including a substantially similar Disclaimer requirement for further
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * binary redistribution.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * 3. Neither the names of the above-listed copyright holders nor the names
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * of any contributors may be used to endorse or promote products derived
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * from this software without specific prior written permission.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * Alternatively, this software may be distributed under the terms of the
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * GNU General Public License ("GPL") version 2 as published by the Free
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * Software Foundation.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * NO WARRANTY
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * POSSIBILITY OF SUCH DAMAGES.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include <sys/types.h>
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include <sys/cmn_err.h>
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include <sys/conf.h>
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include <sys/ddi.h>
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include <sys/ddi_impldefs.h>
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include <sys/devops.h>
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include <sys/instance.h>
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include <sys/modctl.h>
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include <sys/open.h>
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include <sys/stat.h>
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include <sys/sunddi.h>
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include <sys/sunndi.h>
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include <sys/systm.h>
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include <sys/mkdev.h>
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include <sys/list.h>
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include <sys/note.h>
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include "heci_data_structures.h"
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include "heci.h"
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include "heci_interface.h"
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * interrupt function prototypes
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic void heci_bh_handler(void *data);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int heci_bh_read_handler(struct io_heci_list *complete_list,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct iamt_heci_device *dev,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan int32_t *slots);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int heci_bh_write_handler(struct io_heci_list *complete_list,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct iamt_heci_device *dev,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan int32_t *slots);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic void heci_bh_read_bus_message(struct iamt_heci_device *dev,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_msg_hdr *heci_hdr);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int heci_bh_read_pthi_message(struct io_heci_list *complete_list,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct iamt_heci_device *dev,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_msg_hdr *heci_hdr);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int heci_bh_read_client_message(struct io_heci_list *complete_list,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct iamt_heci_device *dev,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_msg_hdr *heci_hdr);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic void heci_client_connect_response(struct iamt_heci_device *dev,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct hbm_client_connect_response *connect_res);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic void heci_client_disconnect_response(struct iamt_heci_device *dev,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct hbm_client_connect_response *disconnect_res);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic void heci_client_flow_control_response(struct iamt_heci_device *dev,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct hbm_flow_control *flow_control);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic void heci_client_disconnect_request(struct iamt_heci_device *dev,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct hbm_client_disconnect_request *disconnect_req);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int heci_bh_process_device(struct iamt_heci_device *dev);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci_isr_interrupt - The ISR of the HECI device
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @irq: The irq number
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @dev_id: pointer to the device structure
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @return irqreturn_t
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganuint_t
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganheci_isr_interrupt(caddr_t arg1)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct iamt_heci_device *device =
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (struct iamt_heci_device *)(void *)arg1;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&device->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (device->heci_state == HECI_POWER_DOWN) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&device->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (DDI_INTR_UNCLAIMED);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan device->host_hw_state = read_heci_register(device, H_CSR);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((device->host_hw_state & H_IS) != H_IS) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&device->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (DDI_INTR_UNCLAIMED);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* disable interrupts */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_csr_disable_interrupts(device);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&device->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * Our device interrupted, schedule work the heci_bh_handler
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * to handle the interrupt processing. This needs to be a
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * taskq
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("schedule work the heci_bh_handler.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (ddi_taskq_dispatch(device->work, heci_bh_handler,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (void*)arg1, DDI_NOSLEEP) == DDI_FAILURE)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan cmn_err(CE_WARN, "taskq_dispatch failed for heci_bh_handler");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (DDI_INTR_CLAIMED);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * _heci_cmpl: process completed operation.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @file_ext: private data of the file object.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @priv_cb_pos: callback block.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic void _heci_cmpl(struct heci_file_private *file_ext,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_cb_private *priv_cb_pos)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (priv_cb_pos->major_file_operations == HECI_WRITE) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_free_cb_private(priv_cb_pos);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("completing write call back.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->writing_state = HECI_WRITE_COMPLETE;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan pollwakeup(&file_ext->tx_pollwait, POLL_IN|POLLRDNORM);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else if (priv_cb_pos->major_file_operations == HECI_READ &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan HECI_READING == file_ext->reading_state) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("completing read call back information= %lu\n",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb_pos->information);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->reading_state = HECI_READ_COMPLETE;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan cv_broadcast(&file_ext->rx_wait);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * _heci_cmpl_iamthif: process completed iamthif operation.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @dev: Device object for our driver.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @priv_cb_pos: callback block.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic void _heci_cmpl_iamthif(struct iamt_heci_device *dev,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_cb_private *priv_cb_pos)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->iamthif_canceled != 1) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_state = HECI_IAMTHIF_READ_COMPLETE;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_stall_timer = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (void) memcpy(priv_cb_pos->response_buffer.data,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_msg_buf,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_msg_buf_index);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_add_tail(&priv_cb_pos->cb_list,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &dev->pthi_read_complete_list.heci_cb.cb_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("pthi read completed.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan run_next_iamthif_cmd(dev);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (&dev->iamthif_file_ext.pollwait) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("completing pthi call back.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan pollwakeup(&dev->iamthif_file_ext.pollwait, POLL_IN|POLLRDNORM);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci_bh_handler - function called after ISR to handle the interrupt
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * processing.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @work: pointer to the work structure
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * NOTE: This function is called by schedule work
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic void
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganheci_bh_handler(void *data)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct iamt_heci_device *dev = (struct iamt_heci_device *)data;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#ifdef SUNOS
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan while (heci_bh_process_device(dev))
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#elif defined(LINUX)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (heci_bh_process_device(dev)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan PEPARE_WORK(&dev->work, heci_bh_handler);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("schedule work the heci_bh_handler.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan rets = schedule_work(&dev->work);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!rets) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan printk(KERN_ERR "heci: schedule the heci_bh_handler"
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan " failed error=%x\n", rets);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#else
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#error "Unknown platform!"
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#endif
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganheci_bh_process_device(struct iamt_heci_device *dev)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct io_heci_list complete_list;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan int32_t slots;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan int rets, isr_pending = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_cb_private *cb_pos = NULL, *cb_next = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file_private *file_ext;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan int bus_message_received = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("function called after ISR to handle the interrupt processing.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* initialize our complete list */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_initialize_list(&complete_list, dev);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->host_hw_state = read_heci_register(dev, H_CSR);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->me_hw_state = read_heci_register(dev, ME_CSR_HA);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* check if ME wants a reset */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (((dev->me_hw_state & ME_RDY_HRA) == 0) &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (dev->heci_state != HECI_RESETING) &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (dev->heci_state != HECI_INITIALIZING)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("FW not ready.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_reset(dev, 1);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (0);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* check if we need to start the dev */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((dev->host_hw_state & H_RDY) == 0) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((dev->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("we need to start the dev.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->host_hw_state |= (H_IE | H_IG | H_RDY);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_set_csr_register(dev);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->heci_state == HECI_INITIALIZING) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->recvd_msg = 1;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan cv_broadcast(&dev->wait_recvd_msg);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (0);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->reinit_tsk &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ddi_taskq_dispatch(dev->reinit_tsk,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_task_initialize_clients,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev, DDI_SLEEP) == DDI_FAILURE) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan cmn_err(CE_WARN, "taskq_dispatch "
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan "failed for reinit_tsk");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (0);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("enable interrupt FW not ready.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_csr_enable_interrupts(dev);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (0);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* check slots avalable for reading */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan slots = count_full_read_slots(dev);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("slots =%08x extra_write_index =%08x.\n",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan slots, dev->extra_write_index);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan while ((slots > 0) && (!dev->extra_write_index)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("slots =%08x extra_write_index =%08x.\n", slots,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->extra_write_index);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("call heci_bh_read_handler.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan rets = heci_bh_read_handler(&complete_list, dev, &slots);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (rets != 0)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan goto end;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan rets = heci_bh_write_handler(&complete_list, dev, &slots);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganend:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("end of bottom half function.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->host_hw_state = read_heci_register(dev, H_CSR);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->host_buffer_is_empty = host_buffer_is_empty(dev);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((dev->host_hw_state & H_IS) == H_IS) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* acknowledge interrupt and disable interrupts */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_csr_disable_interrupts(dev);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("schedule work the heci_bh_handler.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan isr_pending = 1;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_csr_enable_interrupts(dev);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->recvd_msg) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("received waiting bus message\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan bus_message_received = 1;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (bus_message_received) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("wake up dev->wait_recvd_msg\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan cv_broadcast(&dev->wait_recvd_msg);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan bus_message_received = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((complete_list.status != 0) ||
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_empty(&complete_list.heci_cb.cb_list)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (isr_pending);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_for_each_entry_safe(cb_pos, cb_next,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &complete_list.heci_cb.cb_list, cb_list, struct heci_cb_private) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext = (struct heci_file_private *)cb_pos->file_private;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_del(&cb_pos->cb_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (file_ext != NULL) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (file_ext != &dev->iamthif_file_ext) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("completing call back.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan _heci_cmpl(file_ext, cb_pos);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan cb_pos = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else if (file_ext == &dev->iamthif_file_ext) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan _heci_cmpl_iamthif(dev, cb_pos);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (isr_pending);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci_bh_read_handler - bottom half read routine after ISR to
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * handle the read processing.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @cmpl_list: An instance of our list structure
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @dev: Device object for our driver
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @slots: slots to read.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @return 0 on success, <0 on failure.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganheci_bh_read_handler(struct io_heci_list *cmpl_list,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct iamt_heci_device *dev,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan int32_t *slots)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_msg_hdr *heci_hdr;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan int ret = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file_private *file_pos = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file_private *file_next = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!dev->rd_msg_hdr) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->rd_msg_hdr = read_heci_register(dev, ME_CB_RW);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("slots=%08x.\n", *slots);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (*slots)--;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("slots=%08x.\n", *slots);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr = (struct heci_msg_hdr *)&dev->rd_msg_hdr;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("heci_hdr->length =%d\n", heci_hdr->length);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((heci_hdr->reserved) || !(dev->rd_msg_hdr)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("corrupted message header.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ret = -ECORRUPTED_MESSAGE_HEADER;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan goto end;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((heci_hdr->host_addr) || (heci_hdr->me_addr)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_for_each_entry_safe(file_pos, file_next,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &dev->file_list, link, struct heci_file_private) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("list_for_each_entry_safe read host"
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan " client = %d, ME client = %d\n",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_pos->host_client_id,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_pos->me_client_id);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((file_pos->host_client_id == heci_hdr->host_addr) &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (file_pos->me_client_id == heci_hdr->me_addr))
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan break;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (&file_pos->link == &dev->file_list) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("corrupted message header\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ret = -ECORRUPTED_MESSAGE_HEADER;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan goto end;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (((*slots) * sizeof (uint32_t)) < heci_hdr->length) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("we can't read the message slots=%08x.\n", *slots);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* we can't read the message */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ret = -ERANGE;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan goto end;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* decide where to read the message too */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!heci_hdr->host_addr) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("call heci_bh_read_bus_message.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_bh_read_bus_message(dev, heci_hdr);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("end heci_bh_read_bus_message.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else if ((heci_hdr->host_addr ==
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_file_ext.host_client_id) &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (HECI_FILE_CONNECTED == dev->iamthif_file_ext.state) &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (dev->iamthif_state == HECI_IAMTHIF_READING)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("call heci_bh_read_iamthif_message.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("heci_hdr->length =%d\n", heci_hdr->length);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ret = heci_bh_read_pthi_message(cmpl_list, dev, heci_hdr);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (ret != 0)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan goto end;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("call heci_bh_read_client_message.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ret = heci_bh_read_client_message(cmpl_list, dev, heci_hdr);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (ret != 0)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan goto end;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* reset the number of slots and header */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *slots = count_full_read_slots(dev);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->rd_msg_hdr = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (*slots == -ESLOTS_OVERFLOW) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* overflow - reset */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("reseting due to slots overflow.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* set the event since message has been read */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ret = -ERANGE;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan goto end;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganend:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (ret);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci_bh_read_bus_message - bottom half read routine after ISR to
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * handle the read bus message cmd processing.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @dev: Device object for our driver
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @heci_hdr: header of bus message
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic void heci_bh_read_bus_message(struct iamt_heci_device *dev,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_msg_hdr *heci_hdr)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_bus_message *heci_msg;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct hbm_host_version_response *version_res;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct hbm_client_connect_response *connect_res;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct hbm_client_connect_response *disconnect_res;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct hbm_flow_control *flow_control;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct hbm_props_response *props_res;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct hbm_host_enum_response *enum_res;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct hbm_client_disconnect_request *disconnect_req;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct hbm_host_stop_request *h_stop_req;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan int i;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan unsigned char *buffer;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* read the message to our buffer */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan buffer = (unsigned char *)dev->rd_msg_buf;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ASSERT(heci_hdr->length < sizeof (dev->rd_msg_buf));
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_read_slots(dev, buffer, heci_hdr->length);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_msg = (struct heci_bus_message *)buffer;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan switch (*(uint8_t *)heci_msg) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan case HOST_START_RES_CMD:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan version_res = (struct hbm_host_version_response *)heci_msg;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (version_res->host_version_supported) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->version.major_version = HBM_MAJOR_VERSION;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->version.minor_version = HBM_MINOR_VERSION;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->version = version_res->me_max_version;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->recvd_msg = 1;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("host start response message received.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan break;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan case CLIENT_CONNECT_RES_CMD:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan connect_res =
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (struct hbm_client_connect_response *)heci_msg;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_client_connect_response(dev, connect_res);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("client connect response message received.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan cv_broadcast(&dev->wait_recvd_msg);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan break;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan case CLIENT_DISCONNECT_RES_CMD:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan disconnect_res =
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (struct hbm_client_connect_response *)heci_msg;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_client_disconnect_response(dev, disconnect_res);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("client disconnect response message received.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan cv_broadcast(&dev->wait_recvd_msg);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan break;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan case HECI_FLOW_CONTROL_CMD:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan flow_control = (struct hbm_flow_control *)heci_msg;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_client_flow_control_response(dev, flow_control);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("client flow control response message received.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan break;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan case HOST_CLIENT_PROPERTEIS_RES_CMD:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan props_res = (struct hbm_props_response *)heci_msg;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (props_res->status != 0) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ASSERT(0);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan break;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan for (i = 0; i < dev->num_heci_me_clients; i++) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->me_clients[i].client_id ==
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan props_res->address) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->me_clients[i].props =
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan props_res->client_properties;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan break;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->recvd_msg = 1;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan break;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan case HOST_ENUM_RES_CMD:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan enum_res = (struct hbm_host_enum_response *)heci_msg;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (void) memcpy(dev->heci_me_clients,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan enum_res->valid_addresses, 32);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->recvd_msg = 1;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan break;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan case HOST_STOP_RES_CMD:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->heci_state = HECI_DISABLED;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("reseting because of FW stop response.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_reset(dev, 1);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan break;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan case CLIENT_DISCONNECT_REQ_CMD:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* search for client */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan disconnect_req =
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (struct hbm_client_disconnect_request *)heci_msg;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_client_disconnect_request(dev, disconnect_req);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan break;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan case ME_STOP_REQ_CMD:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* prepare stop request */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr = (struct heci_msg_hdr *)&dev->ext_msg_buf[0];
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->host_addr = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->me_addr = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->length = sizeof (struct hbm_host_stop_request);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->msg_complete = 1;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->reserved = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan h_stop_req =
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (struct hbm_host_stop_request *)&dev->ext_msg_buf[1];
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (void) memset(h_stop_req, 0,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan sizeof (struct hbm_host_stop_request));
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan h_stop_req->cmd.cmd = HOST_STOP_REQ_CMD;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan h_stop_req->reason = DRIVER_STOP_REQUEST;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan h_stop_req->reserved[0] = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan h_stop_req->reserved[1] = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->extra_write_index = 2;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan break;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan default:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ASSERT(0);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan break;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci_bh_read_pthi_message - bottom half read routine after ISR to
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * handle the read pthi message data processing.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @complete_list: An instance of our list structure
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @dev: Device object for our driver
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @heci_hdr: header of pthi message
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @return 0 on success, <0 on failure.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganheci_bh_read_pthi_message(struct io_heci_list *complete_list,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct iamt_heci_device *dev,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_msg_hdr *heci_hdr)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file_private *file_ext;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_cb_private *priv_cb;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan unsigned char *buffer;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ASSERT(heci_hdr->me_addr == dev->iamthif_file_ext.me_client_id);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ASSERT(dev->iamthif_state == HECI_IAMTHIF_READING);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan buffer = (unsigned char *)(dev->iamthif_msg_buf +
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_msg_buf_index);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ASSERT(sizeof (dev->iamthif_msg_buf) >=
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (dev->iamthif_msg_buf_index + heci_hdr->length));
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_read_slots(dev, buffer, heci_hdr->length);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_msg_buf_index += heci_hdr->length;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!(heci_hdr->msg_complete))
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (0);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("pthi_message_buffer_index=%d\n", heci_hdr->length);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("completed pthi read.\n ");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!dev->iamthif_current_cb)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ENODEV);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb = dev->iamthif_current_cb;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_current_cb = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext = (struct heci_file_private *)priv_cb->file_private;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!file_ext)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ENODEV);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_stall_timer = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb->information = dev->iamthif_msg_buf_index;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb->read_time = ddi_get_time();
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((dev->iamthif_ioctl) && (file_ext == &dev->iamthif_file_ext)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* found the iamthif cb */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("complete the pthi read cb.\n ");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (&dev->iamthif_file_ext) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("add the pthi read cb to complete.\n ");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_add_tail(&priv_cb->cb_list,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &complete_list->heci_cb.cb_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (0);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * _heci_bh_state_ok - check if heci header matches file private data
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @file_ext: private data of the file object
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @heci_hdr: header of heci client message
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @return !=0 if matches, 0 if no match.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan_heci_bh_state_ok(struct heci_file_private *file_ext,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_msg_hdr *heci_hdr)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return ((file_ext->host_client_id == heci_hdr->host_addr) &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (file_ext->me_client_id == heci_hdr->me_addr) &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (file_ext->state == HECI_FILE_CONNECTED) &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (HECI_READ_COMPLETE != file_ext->reading_state));
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci_bh_read_client_message - bottom half read routine after ISR to
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * handle the read heci client message data processing.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @complete_list: An instance of our list structure
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @dev: Device object for our driver
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @heci_hdr: header of heci client message
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @return 0 on success, <0 on failure.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganheci_bh_read_client_message(struct io_heci_list *complete_list,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct iamt_heci_device *dev,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_msg_hdr *heci_hdr)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file_private *file_ext;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_cb_private *priv_cb_pos = NULL, *priv_cb_next = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan unsigned char *buffer = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("start client msg\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!((dev->read_list.status == 0) &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan !list_empty(&dev->read_list.heci_cb.cb_list)))
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan goto quit;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_for_each_entry_safe(priv_cb_pos, priv_cb_next,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &dev->read_list.heci_cb.cb_list, cb_list, struct heci_cb_private) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext = (struct heci_file_private *)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb_pos->file_private;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((file_ext != NULL) &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (_heci_bh_state_ok(file_ext, heci_hdr))) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&file_ext->read_io_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->reading_state = HECI_READING;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan buffer = (unsigned char *)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (priv_cb_pos->response_buffer.data +
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb_pos->information);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ASSERT(priv_cb_pos->response_buffer.size >=
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->length +
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb_pos->information);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (priv_cb_pos->response_buffer.size <
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->length +
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb_pos->information) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("message overflow.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_del(&priv_cb_pos->cb_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&file_ext->read_io_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ENOMEM);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (buffer) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_read_slots(dev, buffer,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->length);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb_pos->information += heci_hdr->length;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (heci_hdr->msg_complete) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->status = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_del(&priv_cb_pos->cb_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&file_ext->read_io_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("completed read host client = %d,"
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan "ME client = %d, "
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan "data length = %lu\n",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->host_client_id,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->me_client_id,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb_pos->information);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("priv_cb_pos->res_buffer - %s\n",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb_pos->response_buffer.data);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_add_tail(&priv_cb_pos->cb_list,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &complete_list->heci_cb.cb_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&file_ext->read_io_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan break;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganquit:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("message read\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!buffer) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_read_slots(dev, (unsigned char *)dev->rd_msg_buf,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->length);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("discarding message, header=%08x.\n",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *(uint32_t *)dev->rd_msg_buf);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (0);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * _heci_bh_iamthif_read: prepare to read iamthif data.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @dev: Device object for our driver.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @slots: free slots.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @return 0, OK; otherwise, error.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan_heci_bh_iamthif_read(struct iamt_heci_device *dev, int32_t *slots)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (((*slots) * sizeof (uint32_t)) >= (sizeof (struct heci_msg_hdr)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan + sizeof (struct hbm_flow_control))) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *slots -= (sizeof (struct heci_msg_hdr) +
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan sizeof (struct hbm_flow_control) + 3) / 4;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!heci_send_flow_control(dev, &dev->iamthif_file_ext)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("iamthif flow control failed\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("iamthif flow control success\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_state = HECI_IAMTHIF_READING;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_flow_control_pending = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_msg_buf_index = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_msg_buf_size = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_stall_timer = IAMTHIF_STALL_TIMER;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->host_buffer_is_empty = host_buffer_is_empty(dev);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (0);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ECOMPLETE_MESSAGE);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * _heci_bh_close: process close related operation.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @dev: Device object for our driver.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @slots: free slots.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @priv_cb_pos: callback block.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @file_ext: private data of the file object.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @cmpl_list: complete list.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @return 0, OK; otherwise, error.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan_heci_bh_close(struct iamt_heci_device *dev, int32_t *slots,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_cb_private *priv_cb_pos,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file_private *file_ext,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct io_heci_list *cmpl_list)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((*slots * sizeof (uint32_t)) >= (sizeof (struct heci_msg_hdr) +
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan sizeof (struct hbm_client_disconnect_request))) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *slots -= (sizeof (struct heci_msg_hdr) +
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan sizeof (struct hbm_client_disconnect_request) + 3) / 4;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!heci_disconnect(dev, file_ext)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->status = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb_pos->information = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_relink_node(&priv_cb_pos->cb_list,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &cmpl_list->heci_cb.cb_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ECOMPLETE_MESSAGE);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->state = HECI_FILE_DISCONNECTING;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->status = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb_pos->information = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_relink_node(&priv_cb_pos->cb_list,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &dev->ctrl_rd_list.heci_cb.cb_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->timer_count = HECI_CONNECT_TIMEOUT;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* return the cancel routine */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ECORRUPTED_MESSAGE_HEADER);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (0);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * _heci_hb_close: process read related operation.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @dev: Device object for our driver.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @slots: free slots.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @priv_cb_pos: callback block.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @file_ext: private data of the file object.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @cmpl_list: complete list.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @return 0, OK; otherwise, error.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan_heci_bh_read(struct iamt_heci_device *dev, int32_t *slots,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_cb_private *priv_cb_pos,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file_private *file_ext,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct io_heci_list *cmpl_list)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((*slots * sizeof (uint32_t)) >= (sizeof (struct heci_msg_hdr) +
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan sizeof (struct hbm_flow_control))) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *slots -= (sizeof (struct heci_msg_hdr) +
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan sizeof (struct hbm_flow_control) + 3) / 4;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!heci_send_flow_control(dev, file_ext)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->status = -ENODEV;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb_pos->information = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_relink_node(&priv_cb_pos->cb_list,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &cmpl_list->heci_cb.cb_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ENODEV);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_relink_node(&priv_cb_pos->cb_list,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &dev->read_list.heci_cb.cb_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* return the cancel routine */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_del(&priv_cb_pos->cb_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ECORRUPTED_MESSAGE_HEADER);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (0);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * _heci_bh_ioctl: process ioctl related operation.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @dev: Device object for our driver.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @slots: free slots.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @priv_cb_pos: callback block.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @file_ext: private data of the file object.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @cmpl_list: complete list.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @return 0, OK; otherwise, error.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan_heci_bh_ioctl(struct iamt_heci_device *dev, int32_t *slots,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_cb_private *priv_cb_pos,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file_private *file_ext,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct io_heci_list *cmpl_list)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan _NOTE(ARGUNUSED(cmpl_list));
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((*slots * sizeof (uint32_t)) >= (sizeof (struct heci_msg_hdr) +
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan sizeof (struct hbm_client_connect_request))) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->state = HECI_FILE_CONNECTING;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *slots -= (sizeof (struct heci_msg_hdr) +
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan sizeof (struct hbm_client_connect_request) + 3) / 4;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!heci_connect(dev, file_ext)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->status = -ENODEV;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb_pos->information = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_del(&priv_cb_pos->cb_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ENODEV);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_relink_node(&priv_cb_pos->cb_list,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &dev->ctrl_rd_list.heci_cb.cb_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->timer_count = HECI_CONNECT_TIMEOUT;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* return the cancel routine */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_del(&priv_cb_pos->cb_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ECORRUPTED_MESSAGE_HEADER);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (0);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * _heci_bh_cmpl: process completed and no-iamthif operation.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @dev: Device object for our driver.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @slots: free slots.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @priv_cb_pos: callback block.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @file_ext: private data of the file object.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @cmpl_list: complete list.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @return 0, OK; otherwise, error.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan_heci_bh_cmpl(struct iamt_heci_device *dev, int32_t *slots,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_cb_private *priv_cb_pos,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file_private *file_ext,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct io_heci_list *cmpl_list)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_msg_hdr *heci_hdr;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((*slots * sizeof (uint32_t)) >= (sizeof (struct heci_msg_hdr) +
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (priv_cb_pos->request_buffer.size -
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb_pos->information))) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr = (struct heci_msg_hdr *)&dev->wr_msg_buf[0];
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->host_addr = file_ext->host_client_id;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->me_addr = file_ext->me_client_id;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->length = ((priv_cb_pos->request_buffer.size) -
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (priv_cb_pos->information));
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->msg_complete = 1;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->reserved = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("priv_cb_pos->request_buffer.size =%d"
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan "heci_hdr->msg_complete= %d\n",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb_pos->request_buffer.size,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->msg_complete);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("priv_cb_pos->information =%lu\n",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb_pos->information);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("heci_hdr->length =%d\n",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->length);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *slots -= (sizeof (struct heci_msg_hdr) +
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->length + 3) / 4;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!heci_write_message(dev, heci_hdr,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (unsigned char *)(priv_cb_pos->request_buffer.data +
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb_pos->information),
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->length)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->status = -ENODEV;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_relink_node(&priv_cb_pos->cb_list,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &cmpl_list->heci_cb.cb_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ENODEV);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan flow_ctrl_reduce(dev, file_ext);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->status = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb_pos->information += heci_hdr->length;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_relink_node(&priv_cb_pos->cb_list,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &dev->write_waiting_list.heci_cb.cb_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else if (*slots == ((dev->host_hw_state & H_CBD) >> 24)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* buffer is still empty */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr = (struct heci_msg_hdr *)&dev->wr_msg_buf[0];
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->host_addr = file_ext->host_client_id;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->me_addr = file_ext->me_client_id;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->length =
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (*slots * sizeof (uint32_t)) - sizeof (struct heci_msg_hdr);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->msg_complete = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->reserved = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (*slots) -= (sizeof (struct heci_msg_hdr) +
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->length + 3) / 4;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!heci_write_message(dev, heci_hdr,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (unsigned char *)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (priv_cb_pos->request_buffer.data +
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb_pos->information),
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->length)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->status = -ENODEV;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_relink_node(&priv_cb_pos->cb_list,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &cmpl_list->heci_cb.cb_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ENODEV);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb_pos->information += heci_hdr->length;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("priv_cb_pos->request_buffer.size =%d"
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan " heci_hdr->msg_complete= %d\n",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb_pos->request_buffer.size,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->msg_complete);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("priv_cb_pos->information =%lu\n",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb_pos->information);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("heci_hdr->length =%d\n", heci_hdr->length);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ECOMPLETE_MESSAGE);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ECORRUPTED_MESSAGE_HEADER);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (0);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * _heci_bh_cmpl_iamthif: process completed iamthif operation.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @dev: Device object for our driver.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @slots: free slots.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @priv_cb_pos: callback block.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @file_ext: private data of the file object.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @cmpl_list: complete list.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @return 0, OK; otherwise, error.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan_heci_bh_cmpl_iamthif(struct iamt_heci_device *dev, int32_t *slots,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_cb_private *priv_cb_pos,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file_private *file_ext,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct io_heci_list *cmpl_list)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_msg_hdr *heci_hdr;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan _NOTE(ARGUNUSED(cmpl_list));
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((*slots * sizeof (uint32_t)) >= (sizeof (struct heci_msg_hdr) +
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_msg_buf_size -
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_msg_buf_index)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr = (struct heci_msg_hdr *)&dev->wr_msg_buf[0];
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->host_addr = file_ext->host_client_id;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->me_addr = file_ext->me_client_id;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->length = dev->iamthif_msg_buf_size -
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_msg_buf_index;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->msg_complete = 1;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->reserved = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *slots -= (sizeof (struct heci_msg_hdr) +
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->length + 3) / 4;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!heci_write_message(dev, heci_hdr,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (dev->iamthif_msg_buf +
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_msg_buf_index),
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->length)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_state = HECI_IAMTHIF_IDLE;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->status = -ENODEV;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_del(&priv_cb_pos->cb_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ENODEV);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan flow_ctrl_reduce(dev, file_ext);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_msg_buf_index += heci_hdr->length;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb_pos->information = dev->iamthif_msg_buf_index;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->status = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_state = HECI_IAMTHIF_FLOW_CONTROL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_flow_control_pending = 1;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* save iamthif cb sent to pthi client */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_current_cb = priv_cb_pos;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_relink_node(&priv_cb_pos->cb_list,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &dev->write_waiting_list.heci_cb.cb_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else if (*slots == ((dev->host_hw_state & H_CBD) >> 24)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* buffer is still empty */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr = (struct heci_msg_hdr *)&dev->wr_msg_buf[0];
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->host_addr = file_ext->host_client_id;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->me_addr = file_ext->me_client_id;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->length =
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (*slots * sizeof (uint32_t)) - sizeof (struct heci_msg_hdr);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->msg_complete = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->reserved = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *slots -= (sizeof (struct heci_msg_hdr) +
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->length + 3) / 4;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!heci_write_message(dev, heci_hdr,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (dev->iamthif_msg_buf +
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_msg_buf_index),
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->length)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->status = -ENODEV;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_del(&priv_cb_pos->cb_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_msg_buf_index += heci_hdr->length;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ECOMPLETE_MESSAGE);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ECORRUPTED_MESSAGE_HEADER);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (0);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci_bh_write_handler - bottom half write routine after
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * ISR to handle the write processing.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @cmpl_list: An instance of our list structure
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @dev: Device object for our driver
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @slots: slots to write.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @return 0 on success, <0 on failure.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganheci_bh_write_handler(struct io_heci_list *cmpl_list,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct iamt_heci_device *dev,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan int32_t *slots)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file_private *file_ext;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_cb_private *priv_cb_pos = NULL, *priv_cb_next = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct io_heci_list *list;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan int ret;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!host_buffer_is_empty(dev)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("host buffer is not empty.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (0);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->write_hang = (uint8_t)-1;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *slots = count_empty_write_slots(dev);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* complete all waiting for write CB */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("complete all waiting for write cb.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list = &dev->write_waiting_list;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((list->status == 0) &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan !list_empty(&list->heci_cb.cb_list)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_for_each_entry_safe(priv_cb_pos, priv_cb_next,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &list->heci_cb.cb_list, cb_list, struct heci_cb_private) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext = (struct heci_file_private *)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb_pos->file_private;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (file_ext != NULL) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->status = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_del(&priv_cb_pos->cb_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((HECI_WRITING == file_ext->writing_state) &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (priv_cb_pos->major_file_operations ==
2c2d21e98a95cba5687ec6574c974a5c6c4a6adbRichard Lowe HECI_WRITE) &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (file_ext != &dev->iamthif_file_ext)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("HECI WRITE COMPLETE\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->writing_state =
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan HECI_WRITE_COMPLETE;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_add_tail(&priv_cb_pos->cb_list,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &cmpl_list->heci_cb.cb_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (file_ext == &dev->iamthif_file_ext) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("check iamthif flow control.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->iamthif_flow_control_pending) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ret = _heci_bh_iamthif_read(dev,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan slots);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (ret != 0)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (ret);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((dev->stop) && (!dev->wd_pending)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->wd_stoped = 1;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan cv_broadcast(&dev->wait_stop_wd);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (0);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->extra_write_index != 0) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("extra_write_index =%d.\n", dev->extra_write_index);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!heci_write_message(dev,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (struct heci_msg_hdr *)&dev->ext_msg_buf[0],
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (unsigned char *)&dev->ext_msg_buf[1],
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (dev->extra_write_index - 1) * sizeof (uint32_t))) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("heci_bh_handler: writing msg failed\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *slots -= dev->extra_write_index;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->extra_write_index = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->heci_state == HECI_ENABLED) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->wd_pending &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan flow_ctrl_creds(dev, &dev->wd_file_ext)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!heci_send_wd(dev)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("wd send failed.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan flow_ctrl_reduce(dev, &dev->wd_file_ext);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->wd_pending = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->wd_timeout != 0) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *slots -= (sizeof (struct heci_msg_hdr) +
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan HECI_START_WD_DATA_SIZE + 3) / 4;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->wd_due_counter = 2;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *slots -= (sizeof (struct heci_msg_hdr) +
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan HECI_WD_PARAMS_SIZE + 3) / 4;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->wd_due_counter = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->stop)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (~ENODEV);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* complete control write list CB */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->ctrl_wr_list.status == 0) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* complete control write list CB */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("complete control write list cb.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_for_each_entry_safe(priv_cb_pos, priv_cb_next,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &dev->ctrl_wr_list.heci_cb.cb_list,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan cb_list, struct heci_cb_private) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext = (struct heci_file_private *)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb_pos->file_private;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (file_ext == NULL) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_del(&priv_cb_pos->cb_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ENODEV);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan switch (priv_cb_pos->major_file_operations) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan case HECI_CLOSE:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* send disconnect message */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ret = _heci_bh_close(dev, slots,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb_pos,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext, cmpl_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (ret != 0)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (ret);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan break;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan case HECI_READ:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* send flow control message */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ret = _heci_bh_read(dev, slots,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb_pos,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext, cmpl_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (ret != 0)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (ret);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan break;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan case HECI_IOCTL:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* connect message */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!other_client_is_connecting(dev, file_ext))
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan continue;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ret = _heci_bh_ioctl(dev, slots,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb_pos,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext, cmpl_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (ret != 0)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (ret);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan break;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan default:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ASSERT(0);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* complete write list CB */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((dev->write_list.status == 0) &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan !list_empty(&dev->write_list.heci_cb.cb_list)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("complete write list cb.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_for_each_entry_safe(priv_cb_pos, priv_cb_next,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &dev->write_list.heci_cb.cb_list,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan cb_list, struct heci_cb_private) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext = (struct heci_file_private *)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb_pos->file_private;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (file_ext != NULL) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (file_ext != &dev->iamthif_file_ext) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!flow_ctrl_creds(dev, file_ext)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("No flow control"
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan " credentials for client"
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan " %d, not sending.\n",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->host_client_id);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan continue;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ret = _heci_bh_cmpl(dev, slots,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb_pos, file_ext, cmpl_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (ret != 0)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (ret);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else if (file_ext == &dev->iamthif_file_ext) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* IAMTHIF IOCTL */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("complete pthi write cb.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!flow_ctrl_creds(dev, file_ext)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("No flow control"
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan " credentials for pthi"
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan " client %d.\n",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->host_client_id);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan continue;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ret = _heci_bh_cmpl_iamthif(dev, slots,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb_pos, file_ext, cmpl_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (ret != 0)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (ret);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (0);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * is_treat_specially_client - check if the message belong
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * to the file private data.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @file_ext: private data of the file object
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @rs: connect response bus message
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @dev: Device object for our driver
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @return 0 on success, <0 on failure.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganis_treat_specially_client(struct heci_file_private *file_ext,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct hbm_client_connect_response *rs)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan int ret = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((file_ext->host_client_id == rs->host_addr) &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (file_ext->me_client_id == rs->me_addr)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (rs->status == 0) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("client connect status = 0x%08x.\n", rs->status);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->state = HECI_FILE_CONNECTED;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->status = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("client connect status = 0x%08x.\n", rs->status);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->state = HECI_FILE_DISCONNECTED;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->status = -ENODEV;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ret = 1;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("client state = %d.\n", file_ext->state);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (ret);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci_client_connect_response - connect response bh routine
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @dev: Device object for our driver
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @rs: connect response bus message
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic void
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganheci_client_connect_response(struct iamt_heci_device *dev,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct hbm_client_connect_response *rs)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file_private *file_ext;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_cb_private *priv_cb_pos = NULL, *priv_cb_next = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* if WD or iamthif client treat specially */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((is_treat_specially_client(&(dev->wd_file_ext), rs)) ||
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (is_treat_specially_client(&(dev->iamthif_file_ext), rs)))
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->ctrl_rd_list.status == 0 &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan !list_empty(&dev->ctrl_rd_list.heci_cb.cb_list)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_for_each_entry_safe(priv_cb_pos, priv_cb_next,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &dev->ctrl_rd_list.heci_cb.cb_list,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan cb_list, struct heci_cb_private) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext = (struct heci_file_private *)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb_pos->file_private;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (file_ext == NULL) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_del(&priv_cb_pos->cb_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (HECI_IOCTL == priv_cb_pos->major_file_operations) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (is_treat_specially_client(file_ext, rs)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_del(&priv_cb_pos->cb_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->status = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->timer_count = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan break;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci_client_disconnect_response - disconnect response bh routine
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @dev: Device object for our driver
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @rs: disconnect response bus message
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic void heci_client_disconnect_response(struct iamt_heci_device *dev,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct hbm_client_connect_response *rs)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file_private *file_ext;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_cb_private *priv_cb_pos = NULL, *priv_cb_next = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->ctrl_rd_list.status == 0 &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan !list_empty(&dev->ctrl_rd_list.heci_cb.cb_list)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_for_each_entry_safe(priv_cb_pos, priv_cb_next,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &dev->ctrl_rd_list.heci_cb.cb_list,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan cb_list, struct heci_cb_private) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext = (struct heci_file_private *)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb_pos->file_private;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (file_ext == NULL) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_del(&priv_cb_pos->cb_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("list_for_each_entry_safe in ctrl_rd_list.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((file_ext->host_client_id == rs->host_addr) &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (file_ext->me_client_id == rs->me_addr)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_del(&priv_cb_pos->cb_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (rs->status == 0) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->state =
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan HECI_FILE_DISCONNECTED;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->status = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->timer_count = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan break;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * same_flow_addr - tell they have same address.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @file: private data of the file object.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @flow: flow control.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @return !=0, same; 0,not.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logansame_flow_addr(struct heci_file_private *file,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct hbm_flow_control *flow)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return ((file->host_client_id == flow->host_addr) &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (file->me_client_id == flow->me_addr));
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * add_single_flow_creds - add single buffer credentials.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @file: private data ot the file object.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @flow: flow control.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic void
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganadd_single_flow_creds(struct iamt_heci_device *dev,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct hbm_flow_control *flow)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_me_client *client;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan int i;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan for (i = 0; i < dev->num_heci_me_clients; i++) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan client = &dev->me_clients[i];
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((client != NULL) &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (flow->me_addr == client->client_id)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (client->props.single_recv_buf != 0) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan client->flow_ctrl_creds++;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("recv flow ctrl msg ME %d (single).\n",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan flow->me_addr);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("flow control credentials=%d.\n",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan client->flow_ctrl_creds);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ASSERT(0); /* error in flow control */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci_client_flow_control_response - flow control response bh routine
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @dev: Device object for our driver
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @flow_control: flow control response bus message
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic void
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganheci_client_flow_control_response(struct iamt_heci_device *dev,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct hbm_flow_control *flow_control)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file_private *file_pos = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file_private *file_next = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (flow_control->host_addr == 0) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* single receive buffer */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan add_single_flow_creds(dev, flow_control);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* normal connection */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_for_each_entry_safe(file_pos, file_next,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &dev->file_list, link, struct heci_file_private) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("list_for_each_entry_safe in file_list\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("file_ext of host client %d ME client %d.\n",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_pos->host_client_id,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_pos->me_client_id);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("flow ctrl msg for host %d ME %d.\n",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan flow_control->host_addr,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan flow_control->me_addr);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (same_flow_addr(file_pos, flow_control)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("recv ctrl msg for host %d ME %d.\n",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan flow_control->host_addr,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan flow_control->me_addr);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_pos->flow_ctrl_creds++;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("flow control credentials=%d.\n",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_pos->flow_ctrl_creds);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan break;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * same_disconn_addr - tell they have same address
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @file: private data of the file object.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @disconn: disconnection request.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @return !=0, same; 0,not.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logansame_disconn_addr(struct heci_file_private *file,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct hbm_client_disconnect_request *disconn)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return ((file->host_client_id == disconn->host_addr) &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (file->me_client_id == disconn->me_addr));
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci_client_disconnect_request - disconnect request bh routine
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @dev: Device object for our driver.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @disconnect_req: disconnect request bus message.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic void
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganheci_client_disconnect_request(struct iamt_heci_device *dev,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct hbm_client_disconnect_request *disconnect_req)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_msg_hdr *heci_hdr;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct hbm_client_connect_response *disconnect_res;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file_private *file_pos = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file_private *file_next = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_for_each_entry_safe(file_pos, file_next, &dev->file_list,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan link, struct heci_file_private) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (same_disconn_addr(file_pos, disconnect_req)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("disconnect request host client %d ME client %d.\n",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan disconnect_req->host_addr,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan disconnect_req->me_addr);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_pos->state = HECI_FILE_DISCONNECTED;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_pos->timer_count = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (file_pos == &dev->wd_file_ext) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->wd_due_counter = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->wd_pending = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else if (file_pos == &dev->iamthif_file_ext)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_timer = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* prepare disconnect response */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr =
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (struct heci_msg_hdr *)&dev->ext_msg_buf[0];
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->host_addr = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->me_addr = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->length =
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan sizeof (struct hbm_client_connect_response);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->msg_complete = 1;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->reserved = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan disconnect_res =
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (struct hbm_client_connect_response *)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &dev->ext_msg_buf[1];
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan disconnect_res->host_addr = file_pos->host_client_id;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan disconnect_res->me_addr = file_pos->me_client_id;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *(uint8_t *)(&disconnect_res->cmd) =
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan CLIENT_DISCONNECT_RES_CMD;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan disconnect_res->status = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->extra_write_index = 2;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan break;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci_timer - timer function.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @data: pointer to the device structure
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * NOTE: This function is called by timer interrupt work
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganvoid
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganheci_wd_timer(void *data)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct iamt_heci_device *dev = (struct iamt_heci_device *)data;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("send watchdog.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->heci_state != HECI_ENABLED) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->wd_timer = timeout(heci_wd_timer, data, 2 * HZ);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->wd_file_ext.state != HECI_FILE_CONNECTED) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->wd_timer = timeout(heci_wd_timer, data, 2 * HZ);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* Watchdog */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((dev->wd_due_counter != 0) && (dev->wd_bypass == 0)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (--dev->wd_due_counter == 0) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->host_buffer_is_empty &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan flow_ctrl_creds(dev, &dev->wd_file_ext)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->host_buffer_is_empty = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!heci_send_wd(dev)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("wd send failed.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan flow_ctrl_reduce(dev,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &dev->wd_file_ext);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->wd_timeout != 0)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->wd_due_counter = 2;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan else
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->wd_due_counter = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->wd_pending = 1;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->iamthif_stall_timer != 0) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (--dev->iamthif_stall_timer == 0) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("reseting because of hang to PTHI.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_reset(dev, 1);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_msg_buf_size = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_msg_buf_index = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_canceled = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_ioctl = 1;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_state = HECI_IAMTHIF_IDLE;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_timer = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->iamthif_current_cb)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_free_cb_private(dev->iamthif_current_cb);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_file_object = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_current_cb = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan run_next_iamthif_cmd(dev);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->wd_timer = timeout(heci_wd_timer, data, 2 * HZ);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}