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#include "heci_interface.h"
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include "heci.h"
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganconst uint8_t watch_dog_data[] = {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan 1, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan};
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganconst uint8_t start_wd_params[] = { 0x02, 0x12, 0x13, 0x10 };
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganconst uint8_t stop_wd_params[] = { 0x02, 0x02, 0x14, 0x10 };
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganconst uint8_t heci_wd_state_independence_msg[3][4] = {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan {0x05, 0x02, 0x51, 0x10},
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan {0x05, 0x02, 0x52, 0x10},
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan {0x07, 0x02, 0x01, 0x10}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan};
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganconst struct guid heci_asf_guid = {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan 0x75B30CD6, 0xA29E, 0x4AF7,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan {0xA7, 0x12, 0xE6, 0x17, 0x43, 0x93, 0xC8, 0xA6}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan};
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganconst struct guid heci_wd_guid = {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan 0x05B79A6F, 0x4628, 0x4D7F,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan {0x89, 0x9D, 0xA9, 0x15, 0x14, 0xCB, 0x32, 0xAB}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan};
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganconst struct guid heci_pthi_guid = {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan 0x12f80028, 0xb4b7, 0x4b2d,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan {0xac, 0xa8, 0x46, 0xe0, 0xff, 0x65, 0x81, 0x4c}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan};
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci init function prototypes
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic void heci_check_asf_mode(struct iamt_heci_device *dev);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int host_start_message(struct iamt_heci_device *dev);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int host_enum_clients_message(struct iamt_heci_device *dev);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int allocate_me_clients_storage(struct iamt_heci_device *dev);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic void host_init_wd(struct iamt_heci_device *dev);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic void host_init_iamthif(struct iamt_heci_device *dev);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic inline int heci_fe_same_id(struct heci_file_private *fe1,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file_private *fe2);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci_initialize_list - Sets up a queue list.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @list: An instance of our list structure
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @dev: Device object for our driver
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganvoid
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganheci_initialize_list(struct io_heci_list *list,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct iamt_heci_device *dev)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* initialize our queue list */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan LIST_INIT_HEAD(&list->heci_cb.cb_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list->status = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list->device_extension = dev;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci_flush_queues - flush our queues list belong to file_ext.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @dev: Device object for our driver
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @file_ext: private data of the file object
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganvoid
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganheci_flush_queues(struct iamt_heci_device *dev,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file_private *file_ext)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan int i;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!dev || !file_ext)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* flush our queue list belong to file_ext */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan for (i = 0; i < HECI_IO_LISTS_NUMBER; i++) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("remove list entry belong to file_ext\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_flush_list(dev->io_list_array[i], file_ext);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci_flush_list - remove list entry belong to file_ext.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @list: An instance of our list structure
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @file_ext: private data of the file object
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganvoid
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganheci_flush_list(struct io_heci_list *list,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file_private *file_ext)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file_private *file_ext_tmp;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_cb_private *priv_cb_pos = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_cb_private *priv_cb_next = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!list || !file_ext)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (list->status != 0)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (list_empty(&list->heci_cb.cb_list))
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
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 if (priv_cb_pos) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext_tmp = (struct heci_file_private *)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb_pos->file_private;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (file_ext_tmp) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (heci_fe_same_id(file_ext, file_ext_tmp))
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_del(&priv_cb_pos->cb_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci_reset_iamthif_params - initializes heci device iamthif
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @dev: The heci device structure
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic void heci_reset_iamthif_params(struct iamt_heci_device *dev)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* reset iamthif parameters. */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_current_cb = NULL;
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_file_ext.file = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_ioctl = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_state = HECI_IAMTHIF_IDLE;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_timer = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * fini_heci_device - release resources allocated in init_heci_device()
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganvoid
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganfini_heci_device(struct iamt_heci_device *device)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_destroy(&device->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan cv_destroy(&device->wait_recvd_msg);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan cv_destroy(&device->wait_stop_wd);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (device->work)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ddi_taskq_destroy(device->work);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (device->reinit_tsk)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ddi_taskq_destroy(device->reinit_tsk);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * init_heci_device - initializes the heci device structure
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganvoid
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganinit_heci_device(dev_info_t *dip,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct iamt_heci_device *device)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan int i;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!device)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* setup our list array */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan device->io_list_array[0] = &device->read_list;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan device->io_list_array[1] = &device->write_list;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan device->io_list_array[2] = &device->write_waiting_list;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan device->io_list_array[3] = &device->ctrl_wr_list;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan device->io_list_array[4] = &device->ctrl_rd_list;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan device->io_list_array[5] = &device->pthi_cmd_list;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan device->io_list_array[6] = &device->pthi_read_complete_list;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan LIST_INIT_HEAD(&device->file_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan LIST_INIT_HEAD(&device->wd_file_ext.link);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan LIST_INIT_HEAD(&device->iamthif_file_ext.link);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_init(&device->device_lock, NULL, MUTEX_DRIVER, NULL);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan cv_init(&device->wait_recvd_msg, NULL, CV_DRIVER, NULL);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan cv_init(&device->wait_stop_wd, NULL, CV_DRIVER, NULL);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan device->open_handle_count = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan device->num_heci_me_clients = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan device->extra_write_index = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan device->rd_msg_hdr = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan device->mem_addr = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan device->asf_mode = B_FALSE;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan device->need_reset = B_FALSE;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan device->recvd_msg = B_FALSE;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan device->heci_state = HECI_INITIALIZING;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan device->iamthif_state = HECI_IAMTHIF_IDLE;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan device->work = ddi_taskq_create(dip, "heci_bh_handler", 1,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan TASKQ_DEFAULTPRI, 0);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (device->work == NULL)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan cmn_err(CE_WARN, "taskq_create failed for heci_bh_handler");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan device->reinit_tsk = ddi_taskq_create(dip, "heci_reinit_tsk", 1,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan TASKQ_DEFAULTPRI, 0);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (device->reinit_tsk == NULL)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan cmn_err(CE_WARN, "taskq_create failed for reinit_tsk");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan device->wd_pending = B_FALSE;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan device->wd_stoped = B_FALSE;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan device->me_clients = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan for (i = 0; i < HECI_IO_LISTS_NUMBER; i++)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_initialize_list(device->io_list_array[i], device);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan device->dip = dip;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci_hw_init - init host and fw to start work.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @dev: Device object for our driver
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @return 0 on success, <0 on failure.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganint
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganheci_hw_init(struct iamt_heci_device *dev)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan int err = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&dev->device_lock);
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 DBG("host_hw_state = 0x%08x, mestate = 0x%08x.\n",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->host_hw_state, dev->me_hw_state);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((dev->host_hw_state & H_IS) == H_IS) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* acknowledge interrupt and stop interupts */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_set_csr_register(dev);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->recvd_msg = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("reset in start the heci device.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_reset(dev, 1);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->host_hw_state, dev->me_hw_state);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* wait for ME to turn on ME_RDY */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan err = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan while (!dev->recvd_msg && err != -1) {
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni err = cv_reltimedwait(&dev->wait_recvd_msg,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni &dev->device_lock, HECI_INTEROP_TIMEOUT, TR_CLOCK_TICK);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (err == -1 && !dev->recvd_msg) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->heci_state = HECI_DISABLED;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("wait_event_interruptible_timeout failed"
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan "on wait for ME to turn on ME_RDY.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ENODEV);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!(((dev->host_hw_state & H_RDY) == H_RDY) &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ((dev->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA))) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->heci_state = HECI_DISABLED;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->host_hw_state,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->me_hw_state);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!(dev->host_hw_state & H_RDY) != H_RDY)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("host turn off H_RDY.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!(dev->me_hw_state & ME_RDY_HRA) != ME_RDY_HRA)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("ME turn off ME_RDY.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan cmn_err(CE_WARN,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan "heci: link layer initialization failed.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ENODEV);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->recvd_msg = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->host_hw_state, dev->me_hw_state);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("ME turn on ME_RDY and host turn on H_RDY.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("heci: link layer has been established.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (0);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci_hw_reset - reset fw via heci csr register.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @dev: Device object for our driver
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @interrupts: if interrupt should be enable after reset.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic void heci_hw_reset(struct iamt_heci_device *dev, int interrupts)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->host_hw_state |= (H_RST | H_IG);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (interrupts)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_csr_enable_interrupts(dev);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan else
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_csr_disable_interrupts(dev);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci_reset - reset host and fw.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @dev: Device object for our driver
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @interrupts: if interrupt should be enable after reset.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganvoid
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganheci_reset(struct iamt_heci_device *dev, int interrupts)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file_private *file_pos = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file_private *file_next = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_cb_private *priv_cb_pos = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_cb_private *priv_cb_next = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan int unexpected = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->heci_state == HECI_RECOVERING_FROM_RESET) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->need_reset = 1;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->heci_state != HECI_INITIALIZING &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->heci_state != HECI_DISABLED &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->heci_state != HECI_POWER_DOWN &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->heci_state != HECI_POWER_UP)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan unexpected = 1;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->reinit_tsk != NULL) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (void) ddi_taskq_wait(dev->reinit_tsk);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->host_hw_state = read_heci_register(dev, H_CSR);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("before reset host_hw_state = 0x%08x.\n",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->host_hw_state);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hw_reset(dev, interrupts);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->host_hw_state &= ~H_RST;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->host_hw_state |= H_IG;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan write_heci_register(dev, H_CSR, dev->host_hw_state);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("currently saved host_hw_state = 0x%08x.\n",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->host_hw_state);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->need_reset = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->heci_state != HECI_INITIALIZING) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((dev->heci_state != HECI_DISABLED) &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (dev->heci_state != HECI_POWER_DOWN))
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->heci_state = HECI_RESETING;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_for_each_entry_safe(file_pos,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_next, &dev->file_list, link,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file_private) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_pos->state = HECI_FILE_DISCONNECTED;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_pos->flow_ctrl_creds = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_pos->read_cb = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_pos->timer_count = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* remove entry if already in list */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("list del iamthif and wd file list.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_remove_client_from_file_list(dev,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->wd_file_ext.host_client_id);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_remove_client_from_file_list(dev,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_file_ext.host_client_id);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_reset_iamthif_params(dev);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->wd_due_counter = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->extra_write_index = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->num_heci_me_clients = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->rd_msg_hdr = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->stop = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->wd_pending = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* update the state of the registers after reset */
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 DBG("after reset host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->host_hw_state, dev->me_hw_state);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (unexpected)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan cmn_err(CE_WARN, "unexpected heci reset.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* Wake up all readings so they can be interrupted */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_for_each_entry_safe(file_pos, file_next, &dev->file_list, link,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file_private) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan cmn_err(CE_NOTE, "heci: Waking up client!\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan cv_broadcast(&file_pos->rx_wait);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* remove all waiting requests */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->write_list.status == 0 &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan !list_empty(&dev->write_list.heci_cb.cb_list)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_for_each_entry_safe(priv_cb_pos, priv_cb_next,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &dev->write_list.heci_cb.cb_list, cb_list,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_cb_private) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (priv_cb_pos) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_del(&priv_cb_pos->cb_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_free_cb_private(priv_cb_pos);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci_initialize_clients - routine.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @dev: Device object for our driver
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganint
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganheci_initialize_clients(struct iamt_heci_device *dev)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan int status;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* msleep(100) FW needs time to be ready to talk with us */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan delay(drv_usectohz(100000));
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("link is established start sending messages.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* link is established start sending messages. */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan status = host_start_message(dev);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (status != 0) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->heci_state = HECI_DISABLED;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("start sending messages failed.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (status);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* enumerate clients */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan status = host_enum_clients_message(dev);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (status != 0) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->heci_state = HECI_DISABLED;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("enum clients failed.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (status);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* allocate storage for ME clients representation */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan status = allocate_me_clients_storage(dev);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (status != 0) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->num_heci_me_clients = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->heci_state = HECI_DISABLED;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("allocate clients failed.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (status);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_check_asf_mode(dev);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* heci initialization wd */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan host_init_wd(dev);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* heci initialization iamthif client */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan host_init_iamthif(dev);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->need_reset) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->need_reset = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->heci_state = HECI_DISABLED;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ENODEV);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (void) memset(dev->heci_host_clients, 0,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan sizeof (dev->heci_host_clients));
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->open_handle_count = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->heci_host_clients[0] |= 7;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->current_host_client_id = 3;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->heci_state = HECI_ENABLED;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("initialization heci clients successful.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (0);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci_task_initialize_clients - routine.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @data: Device object for our driver
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganvoid
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganheci_task_initialize_clients(void *data)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan int ret;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct iamt_heci_device *dev = (struct iamt_heci_device *)data;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ret = heci_initialize_clients(dev);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (ret)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan cmn_err(CE_WARN, "heci_initialize_clients() failed\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * host_start_message - heci host send start message.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
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 Loganhost_start_message(struct iamt_heci_device *dev)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan long timeout = 60; /* 60 second */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_msg_hdr *heci_hdr;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct hbm_host_version_request *host_start_req;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct hbm_host_stop_request *host_stop_req;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan int err = 0;
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni clock_t delta = (clock_t)(timeout * HZ);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* host start message */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr = (struct heci_msg_hdr *)&dev->wr_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_version_request);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->msg_complete = 1;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->reserved = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan host_start_req =
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (struct hbm_host_version_request *)&dev->wr_msg_buf[1];
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (void) memset(host_start_req, 0,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan sizeof (struct hbm_host_version_request));
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan host_start_req->cmd.cmd = HOST_START_REQ_CMD;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan host_start_req->host_version.major_version = HBM_MAJOR_VERSION;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan host_start_req->host_version.minor_version = HBM_MINOR_VERSION;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->recvd_msg = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!heci_write_message(dev, heci_hdr,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (unsigned char *)(host_start_req),
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->length)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("send version to fw fail.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ENODEV);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("call wait_event_interruptible_timeout for response message.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan err = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan while (err != -1 && !dev->recvd_msg) {
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni err = cv_reltimedwait(&dev->wait_recvd_msg, &dev->device_lock,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni delta, TR_CLOCK_TICK);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (err == -1 && !dev->recvd_msg) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("wait_timeout failed on host start response message.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ENODEV);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->recvd_msg = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("wait_timeout successful on host start response message.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((dev->version.major_version != HBM_MAJOR_VERSION) ||
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (dev->version.minor_version != HBM_MINOR_VERSION)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* send stop message */
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
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan host_stop_req =
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (struct hbm_host_stop_request *)&dev->wr_msg_buf[1];
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (void) memset(host_stop_req, 0,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan sizeof (struct hbm_host_stop_request));
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan host_stop_req->cmd.cmd = HOST_STOP_REQ_CMD;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan host_stop_req->reason = DRIVER_STOP_REQUEST;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!heci_write_message(dev, heci_hdr,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (unsigned char *)(host_stop_req),
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->length)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("sending stop msg to fw failed.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("version mismatch.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ENODEV);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (0);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * host_enum_clients_message - host send enumeration client request message.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @dev: Device object for our driver
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @return 0 on success, <0 on failure.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganhost_enum_clients_message(struct iamt_heci_device *dev)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan long timeout = 5; /* 5 second */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_msg_hdr *heci_hdr;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct hbm_host_enum_request *host_enum_req;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan int err = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan uint8_t i, j;
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni clock_t delta = (clock_t)(timeout * HZ);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr = (struct heci_msg_hdr *)&dev->wr_msg_buf[0];
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* enumerate clients */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->host_addr = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->me_addr = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->length = sizeof (struct hbm_host_enum_request);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->msg_complete = 1;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->reserved = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan host_enum_req = (struct hbm_host_enum_request *)&dev->wr_msg_buf[1];
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (void) memset(host_enum_req, 0, sizeof (struct hbm_host_enum_request));
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan host_enum_req->cmd.cmd = HOST_ENUM_REQ_CMD;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!heci_write_message(dev, heci_hdr,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (unsigned char *)(host_enum_req),
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->length)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("send enumeration request failed.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ENODEV);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* wait for response */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->recvd_msg = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan err = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan while (!dev->recvd_msg && err != -1) {
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni err = cv_reltimedwait(&dev->wait_recvd_msg, &dev->device_lock,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni delta, TR_CLOCK_TICK);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (err == -1 && !dev->recvd_msg) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("wait_event_interruptible_timeout failed "
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan "on enumeration clients response message.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ENODEV);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->recvd_msg = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* count how many ME clients we have */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan for (i = 0; i < sizeof (dev->heci_me_clients); i++) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan for (j = 0; j < 8; j++) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((dev->heci_me_clients[i] & (1 << j)) != 0)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->num_heci_me_clients++;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (0);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * host_client_properties - reads properties for client
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @dev: Device object for our driver
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @idx: client index in me client array
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @client_id: id of the client
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @return 0 on success, <0 on failure.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganhost_client_properties(struct iamt_heci_device *dev,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_me_client *client)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_msg_hdr *heci_hdr;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct hbm_props_request *host_cli_req;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan int err;
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni clock_t delta = 10 * HZ;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr = (struct heci_msg_hdr *)&dev->wr_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_props_request);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->msg_complete = 1;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr->reserved = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan host_cli_req = (struct hbm_props_request *)&dev->wr_msg_buf[1];
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (void) memset(host_cli_req, 0, sizeof (struct hbm_props_request));
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan host_cli_req->cmd.cmd = HOST_CLIENT_PROPERTEIS_REQ_CMD;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan host_cli_req->address = client->client_id;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!heci_write_message(dev, heci_hdr,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (unsigned char *)(host_cli_req), heci_hdr->length)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("send props request failed.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ENODEV);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* wait for response */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->recvd_msg = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan err = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan while (!dev->recvd_msg && err != -1) {
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni err = cv_reltimedwait(&dev->wait_recvd_msg, &dev->device_lock,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni delta, TR_CLOCK_TICK);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (err == -1 && !dev->recvd_msg) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("wait failed on props resp msg.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ENODEV);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->recvd_msg = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (0);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * allocate_me_clients_storage - allocate storage for me clients
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
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 Loganallocate_me_clients_storage(struct iamt_heci_device *dev)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_me_client *clients;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_me_client *client;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan uint8_t num, i, j;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan int err;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->num_heci_me_clients == 0)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (0);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->me_clients) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan kmem_free(dev->me_clients, dev->num_heci_me_clients*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan sizeof (struct heci_me_client));
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->me_clients = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* allocate storage for ME clients representation */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan clients = kmem_zalloc(dev->num_heci_me_clients*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan sizeof (struct heci_me_client), KM_SLEEP);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!clients) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("memory allocation for ME clients failed.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ENOMEM);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->me_clients = clients;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan num = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan for (i = 0; i < sizeof (dev->heci_me_clients); i++) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan for (j = 0; j < 8; j++) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((dev->heci_me_clients[i] & (1 << j)) != 0) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan client = &dev->me_clients[num];
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan client->client_id = (i * 8) + j;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan client->flow_ctrl_creds = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan err = host_client_properties(dev, client);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (err != 0) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan kmem_free(dev->me_clients,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->num_heci_me_clients*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan sizeof (struct heci_me_client));
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->me_clients = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (err);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan num++;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (0);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci_init_file_private - initializes private file structure.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @priv: private file structure to be initialized
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @file: the file structure
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic void
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganheci_init_file_private(struct heci_file_private *priv,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file *file)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan _NOTE(ARGUNUSED(file));
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (void) memset(priv, 0, sizeof (struct heci_file_private));
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_init(&priv->file_lock, NULL, MUTEX_DRIVER, NULL);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_init(&priv->read_io_lock, NULL, MUTEX_DRIVER, NULL);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_init(&priv->write_io_lock, NULL, MUTEX_DRIVER, NULL);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan cv_init(&priv->rx_wait, NULL, CV_DRIVER, NULL);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("priv->rx_wait =%p\n", (void *)&priv->rx_wait);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan LIST_INIT_HEAD(&priv->link);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv->reading_state = HECI_IDLE;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv->writing_state = HECI_IDLE;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci_find_me_client - search for ME client guid
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * sets client_id in heci_file_private if found
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @dev: Device object for our driver
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @priv: private file structure to set client_id in
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @cguid: searched guid of ME client
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @client_id: id of host client to be set in file private structure
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @return ME client index
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic uint8_t
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganheci_find_me_client(struct iamt_heci_device *dev,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file_private *priv,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan const struct guid *cguid, uint8_t client_id)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan uint8_t i;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((dev == NULL) || (priv == NULL) || (cguid == NULL))
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (0);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan for (i = 0; i < dev->num_heci_me_clients; i++) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (memcmp(cguid,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &dev->me_clients[i].props.protocol_name,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan sizeof (struct guid)) == 0) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv->me_client_id = dev->me_clients[i].client_id;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv->state = HECI_FILE_CONNECTING;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv->host_client_id = client_id;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_add_tail(&priv->link, &dev->file_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (i);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (0);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci_check_asf_mode - check for ASF client
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @dev: Device object for our driver
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic void
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganheci_check_asf_mode(struct iamt_heci_device *dev)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan uint8_t i;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->asf_mode = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* find ME ASF client - otherwise assume AMT mode */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("find ME ASF client - otherwise assume AMT mode.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan for (i = 0; i < dev->num_heci_me_clients; i++) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (memcmp(&heci_asf_guid,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &dev->me_clients[i].props.protocol_name,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan sizeof (struct guid)) == 0) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->asf_mode = 1;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("found ME ASF client.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("assume AMT mode.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci_connect_me_client - connect ME client
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @dev: Device object for our driver
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @priv: private file structure
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @timeout: connect timeout in seconds
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @return 1 - if connected, 0 - if not
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic uint8_t
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganheci_connect_me_client(struct iamt_heci_device *dev,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file_private *priv,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan long timeout)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan int err = 0;
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni clock_t delta = (clock_t)(timeout * HZ);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((dev == NULL) || (priv == NULL))
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (0);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!heci_connect(dev, priv)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("failed to call heci_connect for client_id=%d.\n",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv->host_client_id);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_remove_client_from_file_list(dev, priv->host_client_id);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv->state = HECI_FILE_DISCONNECTED;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (0);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan err = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan while (!(HECI_FILE_CONNECTED == priv->state ||
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan HECI_FILE_DISCONNECTED == priv->state) &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan err != -1) {
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni err = cv_reltimedwait(&dev->wait_recvd_msg, &dev->device_lock,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni delta, TR_CLOCK_TICK);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (HECI_FILE_CONNECTED != priv->state) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_remove_client_from_file_list(dev, priv->host_client_id);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("failed to connect client_id=%d state=%d.\n",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv->host_client_id, priv->state);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (err)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("failed connect err=%08x\n", err);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv->state = HECI_FILE_DISCONNECTED;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (0);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("successfully connected client_id=%d.\n",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv->host_client_id);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (1);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * host_init_wd - heci initialization wd.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @dev: Device object for our driver
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic void host_init_wd(struct iamt_heci_device *dev)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_init_file_private(&dev->wd_file_ext, NULL);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* look for WD client and connect to it */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->wd_file_ext.state = HECI_FILE_DISCONNECTED;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->wd_timeout = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->asf_mode) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (void) memcpy(dev->wd_data, stop_wd_params,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan HECI_WD_PARAMS_SIZE);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* AMT mode */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->wd_timeout = AMT_WD_VALUE;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("dev->wd_timeout=%d.\n", dev->wd_timeout);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (void) memcpy(dev->wd_data, start_wd_params,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan HECI_WD_PARAMS_SIZE);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (void) memcpy(dev->wd_data + HECI_WD_PARAMS_SIZE,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &dev->wd_timeout, sizeof (uint16_t));
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* find ME WD client */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (void) heci_find_me_client(dev, &dev->wd_file_ext,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &heci_wd_guid, HECI_WD_HOST_CLIENT_ID);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("check wd_file_ext\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (HECI_FILE_CONNECTING == dev->wd_file_ext.state) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (heci_connect_me_client(dev, &dev->wd_file_ext, 15) == 1) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("dev->wd_timeout=%d.\n", dev->wd_timeout);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->wd_timeout != 0)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->wd_due_counter = 1;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan else
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->wd_due_counter = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("successfully connected to WD client.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("failed to find WD client.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * host_init_iamthif - heci initialization iamthif client.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @dev: Device object for our driver
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic void
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganhost_init_iamthif(struct iamt_heci_device *dev)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan uint8_t i;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_init_file_private(&dev->iamthif_file_ext, NULL);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_file_ext.state = HECI_FILE_DISCONNECTED;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* find ME PTHI client */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan i = heci_find_me_client(dev, &dev->iamthif_file_ext,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &heci_pthi_guid, HECI_IAMTHIF_HOST_CLIENT_ID);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->iamthif_file_ext.state != HECI_FILE_CONNECTING) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("failed to find iamthif client.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ASSERT(dev->me_clients[i].props.max_msg_length == IAMTHIF_MTU);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (heci_connect_me_client(dev, &dev->iamthif_file_ext, 15) == 1) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("connected to iamthif client.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_state = HECI_IAMTHIF_IDLE;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci_alloc_file_private - allocates a private file structure and set it up.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @file: the file structure
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @return The allocated file or NULL on failure
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstruct heci_file_private *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganheci_alloc_file_private(struct heci_file *file)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file_private *priv;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv = kmem_zalloc(sizeof (struct heci_file_private), KM_SLEEP);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!priv)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (NULL);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_init_file_private(priv, file);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (priv);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci_free_file_private - free a private file structure that were previously
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * allocated by heci_alloc_file_private
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganvoid
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganheci_free_file_private(struct heci_file_private *priv)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_destroy(&priv->file_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_destroy(&priv->read_io_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_destroy(&priv->write_io_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan cv_destroy(&priv->rx_wait);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan kmem_free(priv, sizeof (struct heci_file_private));
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci_disconnect_host_client - send disconnect message to fw from host
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * client.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @dev: Device object for our driver
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @file_ext: private data of the file object
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @return 0 on success, <0 on failure.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganint
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganheci_disconnect_host_client(struct iamt_heci_device *dev,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file_private *file_ext)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan int rets, err;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan long timeout = 15; /* 15 seconds */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_cb_private *priv_cb;
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni clock_t delta = (clock_t)(timeout * HZ);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((!dev) || (!file_ext))
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ENODEV);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (file_ext->state != HECI_FILE_DISCONNECTING)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (0);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb = kmem_zalloc(sizeof (struct heci_cb_private), KM_SLEEP);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!priv_cb)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ENOMEM);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan LIST_INIT_HEAD(&priv_cb->cb_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb->file_private = file_ext;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb->major_file_operations = HECI_CLOSE;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->host_buffer_is_empty) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->host_buffer_is_empty = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (heci_disconnect(dev, file_ext)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_add_tail(&priv_cb->cb_list,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &dev->ctrl_rd_list.heci_cb.cb_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan rets = -ENODEV;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("failed to call heci_disconnect.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan goto free;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("add disconnect cb to control write list\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_add_tail(&priv_cb->cb_list,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &dev->ctrl_wr_list.heci_cb.cb_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan err = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan while (err != -1 &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (HECI_FILE_DISCONNECTED != file_ext->state)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni err = cv_reltimedwait(&dev->wait_recvd_msg, &dev->device_lock,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni delta, TR_CLOCK_TICK);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (HECI_FILE_DISCONNECTED == file_ext->state) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan rets = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("successfully disconnected from fw client."
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan " me_client_id:%d, host_client_id:%d\n",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->me_client_id,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->host_client_id);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan rets = -ENODEV;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (HECI_FILE_DISCONNECTED != file_ext->state)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("wrong status client disconnect.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (err)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("wait failed disconnect err=%08x\n", err);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("failed to disconnect from fw client.\n"
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan " me_client_id:%d, host_client_id:%d\n",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->me_client_id,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->host_client_id);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_flush_list(&dev->ctrl_rd_list, file_ext);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_flush_list(&dev->ctrl_wr_list, file_ext);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganfree:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_free_cb_private(priv_cb);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (rets);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci_remove_client_from_file_list -
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * remove file private data from device file list
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @dev: Device object for our driver
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @host_client_id: host client id to be removed
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganvoid
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganheci_remove_client_from_file_list(struct iamt_heci_device *dev,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan uint8_t host_client_id)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file_private *file_pos = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file_private *file_next = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_for_each_entry_safe(file_pos, file_next, &dev->file_list, link,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file_private) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (host_client_id == file_pos->host_client_id) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("remove host client = %d, ME client = %d\n",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_pos->host_client_id,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_pos->me_client_id);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_del_init(&file_pos->link);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan break;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci_fe_same_id - tell if file private data have same id
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @fe1: private data of 1. file object
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @fe2: private data of 2. file object
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @return !=0 - if ids are the same, 0 - if differ.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic inline int heci_fe_same_id(struct heci_file_private *fe1,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file_private *fe2)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return ((fe1->host_client_id == fe2->host_client_id) &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (fe1->me_client_id == fe2->me_client_id));
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}