From: <mar...@us...> - 2008-07-22 17:12:57
|
Revision: 206 http://openamt.svn.sourceforge.net/openamt/?rev=206&view=rev Author: marcin_obara Date: 2008-07-22 17:13:05 +0000 (Tue, 22 Jul 2008) Log Message: ----------- 5.0 base for testing code Modified Paths: -------------- heci/branches/testing/COPYING heci/branches/testing/README heci/branches/testing/src/Makefile heci/branches/testing/src/heci.h heci/branches/testing/src/heci_data_structures.h heci/branches/testing/src/heci_init.c heci/branches/testing/src/heci_interface.c heci/branches/testing/src/heci_interface.h heci/branches/testing/src/heci_main.c heci/branches/testing/src/interrupt.c heci/branches/testing/src/io_heci.c heci/branches/testing/src/kcompat.h Added Paths: ----------- heci/branches/testing/src/heci_version.h Removed Paths: ------------- heci/branches/testing/scripts/ heci/branches/testing/src/version.h Modified: heci/branches/testing/COPYING =================================================================== --- heci/branches/testing/COPYING 2008-07-22 16:25:37 UTC (rev 205) +++ heci/branches/testing/COPYING 2008-07-22 17:13:05 UTC (rev 206) @@ -1,7 +1,7 @@ /* * Part of "Intel(R) Manageability Engine Interface" Linux driver * - * Copyright (c) 2007 Intel Corp. + * Copyright (c) 2003 - 2008 Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without Modified: heci/branches/testing/README =================================================================== --- heci/branches/testing/README 2008-07-22 16:25:37 UTC (rev 205) +++ heci/branches/testing/README 2008-07-22 17:13:05 UTC (rev 206) @@ -1,6 +1,6 @@ /+--------------------------------------------------------------------------- // -// Copyright (C) Intel Corporation, 2003 - 2007. +// Copyright (C) Intel Corporation, 2003 - 2008. // // File: README // @@ -26,17 +26,14 @@ Building and installing the Intel(R) Manageability Engine Interface driver: ----------------------------- In order to build and install the Intel(R) Manageability Engine Interface driver, -call "make install" from the /src directory. This builds the Intel(R) -Manageability Engine Interface driver, installs it and the startup script. +call "make install". Call "make uninstall" to uninstall and remove the Intel(R) Manageability Engine -Interface driver and the startup script. In order to load and use the driver -call "modprobe heci" or "insmod heci.ko" and call make_node script from -scripts/ directory. To start heci driver at system boot, startup script need -to be added to desired runlevel. +Interface driver. +In order to load and use the driver call "modprobe heci" or "insmod heci.ko". The Intel(R) Manageability Engine Interface driver may also be built and -installed manually, by first calling "make", then "insmod heci.ko", followed -by "./make_node". Remove by calling "rmmod heci.ko". +installed manually, by first calling "make", then "insmod heci.ko". +Remove by calling "rmmod heci.ko". Accessing The FW Via Intel(R) Manageability Engine Interface driver: ----------------------------- Modified: heci/branches/testing/src/Makefile =================================================================== --- heci/branches/testing/src/Makefile 2008-07-22 16:25:37 UTC (rev 205) +++ heci/branches/testing/src/Makefile 2008-07-22 17:13:05 UTC (rev 206) @@ -3,7 +3,7 @@ # # Part of Intel(R) Manageability Engine Interface Linux driver # -# Copyright (c) 2003 - 2007 Intel Corp. +# Copyright (c) 2003 - 2008 Intel Corp. # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -45,15 +45,11 @@ # core driver files CFILES = heci_init.c interrupt.c heci_interface.c io_heci.c heci_main.c -HFILES = heci.h heci_interface.h +HFILES = heci.h heci_interface.h heci_structures,h heci_version.h kcompat.h ifeq (,$(BUILD_KERNEL)) BUILD_KERNEL = $(shell uname -r) endif -INIT_SCRIPT_PATH = /etc/init.d -INIT_SCRIPT_SRC = ../scripts/heci.sh -INIT_SCRIPT = heci - ########################################################################### # Environment tests @@ -129,27 +125,27 @@ # some additional features are only built on Intel platforms ARCH := $(shell uname -m | sed 's/i.86/i386/') ifeq ($(ARCH),alpha) - CFLAGS += -ffixed-8 -mno-fp-regs + EXTRA_CFLAGS += -ffixed-8 -mno-fp-regs endif ifeq ($(ARCH),x86_64) - CFLAGS += -mcmodel=kernel -mno-red-zone + EXTRA_CFLAGS += -mcmodel=kernel -mno-red-zone endif ifeq ($(ARCH),ppc) - CFLAGS += -msoft-float + EXTRA_CFLAGS += -msoft-float endif ifeq ($(ARCH),ppc64) - CFLAGS += -m64 -msoft-float + EXTRA_CFLAGS += -m64 -msoft-float LDFLAGS += -melf64ppc endif # standard flags for module builds -CFLAGS += -DLINUX -D__KERNEL__ -DMODULE -O2 -pipe -Wall -CFLAGS += -I$(KSRC)/include -I. -CFLAGS += $(shell [ -f $(KSRC)/include/linux/modversions.h ] && \ +EXTRA_CFLAGS += -DLINUX -D__KERNEL__ -DMODULE -O2 -pipe -Wall +EXTRA_CFLAGS += -I$(KSRC)/include -I. +EXTRA_CFLAGS += $(shell [ -f $(KSRC)/include/linux/modversions.h ] && \ echo "-DMODVERSIONS -DEXPORT_SYMTAB \ -include $(KSRC)/include/linux/modversions.h") -CFLAGS += $(CFLAGS_EXTRA) +EXTRA_CFLAGS += $(CFLAGS_EXTRA) RHC := $(KSRC)/include/linux/rhconfig.h ifneq (,$(wildcard $(RHC))) @@ -200,7 +196,7 @@ endif ifeq ($(SMP),1) - CFLAGS += -D__SMP__ + EXTRA_CFLAGS += -D__SMP__ endif @@ -233,6 +229,9 @@ # remove all old versions of the driver find $(INSTALL_MOD_PATH)/lib/modules/$(KVER) -name $(TARGET) -exec rm -f {} \; || true find $(INSTALL_MOD_PATH)/lib/modules/$(KVER) -name $(TARGET).gz -exec rm -f {} \; || true + if [ -e /etc/init.d/heci ] ; then \ + rm -f /etc/init.d/heci ; \ + fi install -D -m 644 $(TARGET) $(INSTALL_MOD_PATH)$(INSTDIR)/$(TARGET) ifeq (,$(INSTALL_MOD_PATH)) /sbin/depmod -a || true @@ -243,13 +242,11 @@ /sbin/depmod -b $(INSTALL_MOD_PATH) -a -n > /dev/null || true endif endif - #copy init script to init.d - install ${INIT_SCRIPT_SRC} ${INIT_SCRIPT_PATH}/${INIT_SCRIPT} .PHONY: clean install uninstall test clean: - rm -rf $(TARGET) $(TARGET:.ko=.o) $(TARGET:.ko=.mod.o) $(TARGET:.ko=.mod.c) $(CFILES:.c=.o) .*cmd .tmp_versions Module.symvers + rm -rf $(TARGET) $(TARGET:.ko=.o) $(TARGET:.ko=.mod.o) $(TARGET:.ko=.mod.c) $(CFILES:.c=.o) .*cmd .tmp_versions Module.symvers Modules.symvers test: @echo $(KVER) @@ -258,7 +255,3 @@ if [ -e $(INSTDIR)/$(TARGET) ]; then \ rm -f ${INSTDIR}/$(TARGET) ; \ fi - #remove init script from init.d - if [ -e ${INIT_SCRIPT_PATH}/${INIT_SCRIPT} ] ; then \ - rm -f ${INIT_SCRIPT_PATH}/${INIT_SCRIPT} ; \ - fi Modified: heci/branches/testing/src/heci.h =================================================================== --- heci/branches/testing/src/heci.h 2008-07-22 16:25:37 UTC (rev 205) +++ heci/branches/testing/src/heci.h 2008-07-22 17:13:05 UTC (rev 206) @@ -1,7 +1,7 @@ /* * Part of Intel(R) Manageability Engine Interface Linux driver * - * Copyright (c) 2003 - 2007 Intel Corp. + * Copyright (c) 2003 - 2008 Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -53,82 +53,124 @@ #include <linux/types.h> #include "heci_data_structures.h" - extern const struct guid heci_pthi_guid; -extern const __u8 start_wd_params[]; -extern const __u8 stop_wd_params[]; +extern const struct guid heci_wd_guid; +extern const __u8 heci_start_wd_params[]; +extern const __u8 heci_stop_wd_params[]; +extern const __u8 heci_wd_state_independence_msg[3][4]; -/** - * memory IO BAR definition +/* + * heci device ID */ -#define BAR_0 0 -#define BAR_1 1 -#define BAR_5 5 -/** - * Number of queue lists used by this driver - */ -#define PCI_HECI_DEVICE_ID1 0x2974 -#define PCI_HECI_DEVICE_ID2 0x2984 -#define PCI_HECI_DEVICE_ID3 0x2994 -#define PCI_HECI_DEVICE_ID4 0x29A4 -#define PCI_HECI_DEVICE_ID5 0x29B4 -#define PCI_HECI_DEVICE_ID6 0x29C4 +#define HECI_DEV_ID_82946GZ 0x2974 /* 82946GZ/GL */ +#define HECI_DEV_ID_82G35 0x2984 /* 82G35 Express */ +#define HECI_DEV_ID_82Q965 0x2994 /* 82Q963/Q965 */ +#define HECI_DEV_ID_82G965 0x29A4 /* 82P965/G965 */ -/** +#define HECI_DEV_ID_82GM965 0x2A04 /* Mobile PM965/GM965 */ +#define HECI_DEV_ID_82GME965 0x2A14 /* Mobile GME965/GLE960 */ + +#define HECI_DEV_ID_ICH9_82Q35 0x29B4 /* 82Q35 Express */ +#define HECI_DEV_ID_ICH9_82G33 0x29C4 /* 82G33/G31/P35/P31 Express */ +#define HECI_DEV_ID_ICH9_82Q33 0x29D4 /* 82Q33 Express */ +#define HECI_DEV_ID_ICH9_82X38 0x29E4 /* 82X38/X48 Express */ +#define HECI_DEV_ID_ICH9_3200 0x29F4 /* 3200/3210 Server */ + +#define HECI_DEV_ID_ICH9_6 0x28B4 /* Bearlake */ +#define HECI_DEV_ID_ICH9_7 0x28C4 /* Bearlake */ +#define HECI_DEV_ID_ICH9_8 0x28D4 /* Bearlake */ +#define HECI_DEV_ID_ICH9_9 0x28E4 /* Bearlake */ +#define HECI_DEV_ID_ICH9_10 0x28F4 /* Bearlake */ + +#define HECI_DEV_ID_ICH9M_1 0x2A44 /* Cantiga */ +#define HECI_DEV_ID_ICH9M_2 0x2A54 /* Cantiga */ +#define HECI_DEV_ID_ICH9M_3 0x2A64 /* Cantiga */ +#define HECI_DEV_ID_ICH9M_4 0x2A74 /* Cantiga */ + +#define HECI_DEV_ID_ICH10_1 0x2E04 /* Eaglelake */ +#define HECI_DEV_ID_ICH10_2 0x2E14 /* Eaglelake */ +#define HECI_DEV_ID_ICH10_3 0x2E24 /* Eaglelake */ +#define HECI_DEV_ID_ICH10_4 0x2E34 /* Eaglelake */ + +/* * heci init function prototypes */ struct iamt_heci_device *init_heci_device(struct pci_dev *pdev); -void heci_reset(struct iamt_heci_device * device_object, int interrupts); -int heci_hw_init(struct iamt_heci_device * device_object); -int heci_initialize_clients(void *data); -struct heci_file_private *alloc_priv(struct file *file); -int heci_disconnect_host_client(struct iamt_heci_device * device_object, - struct heci_file_private * file_extension); +void heci_reset(struct iamt_heci_device *dev, int interrupts); +int heci_hw_init(struct iamt_heci_device *dev); +int heci_task_initialize_clients(void *data); +int heci_initialize_clients(struct iamt_heci_device *dev); +struct heci_file_private *heci_alloc_file_private(struct file *file); +int heci_disconnect_host_client(struct iamt_heci_device *dev, + struct heci_file_private *file_ext); void heci_initialize_list(struct io_heci_list *list, - struct iamt_heci_device * device_object); + struct iamt_heci_device *dev); void heci_flush_list(struct io_heci_list *list, - struct heci_file_private * file_extension); -void heci_flush_queues(struct iamt_heci_device * device_object, - struct heci_file_private * file_extension); + struct heci_file_private *file_ext); +void heci_flush_queues(struct iamt_heci_device *dev, + struct heci_file_private *file_ext); -void heci_remove_client_from_file_list(struct iamt_heci_device * device_object, +void heci_remove_client_from_file_list(struct iamt_heci_device *dev, __u8 host_client_id); -/** +/* * interrupt function prototype */ irqreturn_t heci_isr_interrupt(int irq, void *dev_id); + void heci_wd_timer(unsigned long data); -void heci_bh_handler(struct work_struct *work); -/** + +/* * input output function prototype */ -int heci_ioctl_get_version(struct iamt_heci_device * device, int if_num, +int heci_ioctl_get_version(struct iamt_heci_device *dev, int if_num, struct heci_message_data *u_msg, struct heci_message_data k_msg, - struct heci_file_private * file_extension); -int heci_ioctl_connect_client(struct iamt_heci_device * device, int if_num, + struct heci_file_private *file_ext); + +int heci_ioctl_connect_client(struct iamt_heci_device *dev, int if_num, struct heci_message_data *u_msg, struct heci_message_data k_msg, struct file *file); -int heci_ioctl_wd(struct iamt_heci_device * device, int if_num, + +int heci_ioctl_wd(struct iamt_heci_device *dev, int if_num, struct heci_message_data k_msg, - struct heci_file_private * file_extension); -int legacy_ioctl_send_message(struct iamt_heci_device * device, int if_num, - struct heci_message_data k_msg, - struct file *file); -int legacy_ioctl_receive_message(struct iamt_heci_device * device, int if_num, - struct heci_message_data *u_msg, - struct heci_message_data k_msg, - struct file *file); -int heci_start_read(struct iamt_heci_device * device, int if_num, - struct heci_file_private * file_extension); -int pthi_write(struct iamt_heci_device * device, - struct heci_cb_private *kernel_priv_cb); -int pthi_read(struct iamt_heci_device * device, int if_num, struct file *file, - char *ubuf, size_t length, loff_t* offset); -struct heci_cb_private* find_pthi_read_list_entry(struct iamt_heci_device* device, - struct file* file, struct heci_file_private* file_extension); -void run_next_legacy_cmd(struct iamt_heci_device * device); + struct heci_file_private *file_ext); -#endif /* _HECI_H_ */ +int heci_ioctl_bypass_wd(struct iamt_heci_device *dev, int if_num, + struct heci_message_data k_msg, + struct heci_file_private *file_ext); + +int heci_start_read(struct iamt_heci_device *dev, int if_num, + struct heci_file_private *file_ext); + +int pthi_write(struct iamt_heci_device *dev, + struct heci_cb_private *priv_cb); + +int pthi_read(struct iamt_heci_device *dev, int if_num, struct file *file, + char *ubuf, size_t length, loff_t *offset); + +struct heci_cb_private *find_pthi_read_list_entry( + struct iamt_heci_device *dev, + struct file *file); + +void run_next_iamthif_cmd(struct iamt_heci_device *dev); + +void heci_free_cb_private(struct heci_cb_private *priv_cb); + +/** + * heci_fe_same_id - tell if file private data have same id + * + * @fe1: private data of 1. file object + * @fe2: private data of 2. file object + * + * returns !=0 - if ids are the same, 0 - if differ. + */ +static inline int heci_fe_same_id(const struct heci_file_private *fe1, + const struct heci_file_private *fe2) +{ + return ((fe1->host_client_id == fe2->host_client_id) + && (fe1->me_client_id == fe2->me_client_id)); +} + +#endif /* _HECI_H_ */ Modified: heci/branches/testing/src/heci_data_structures.h =================================================================== --- heci/branches/testing/src/heci_data_structures.h 2008-07-22 16:25:37 UTC (rev 205) +++ heci/branches/testing/src/heci_data_structures.h 2008-07-22 17:13:05 UTC (rev 206) @@ -1,7 +1,7 @@ /* * Part of Intel(R) Manageability Engine Interface Linux driver * - * Copyright (c) 2003 - 2007 Intel Corp. + * Copyright (c) 2003 - 2008 Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -52,116 +52,112 @@ #include <linux/aio.h> #include <linux/types.h> -/** +/* * error code definition */ -#define ESUCCESS 0 #define ESLOTS_OVERFLOW 1 #define ECORRUPTED_MESSAGE_HEADER 1000 #define ECOMPLETE_MESSAGE 1001 -#define FC_MESSAGE_RESERVED_LENGTH 5 -/** +#define HECI_FC_MESSAGE_RESERVED_LENGTH 5 + +/* * Number of queue lists used by this driver */ -#define NUMBER_OF_LISTS 7 +#define HECI_IO_LISTS_NUMBER 7 -#define LEGACY_MTU 4160 -#pragma pack(1) +/* + * Maximum transmission unit (MTU) of heci messages + */ +#define IAMTHIF_MTU 4160 -/** +/* * HECI HW Section */ -/* HECI addresses and defines */ +/* HECI registers */ +/* H_CB_WW - Host Circular Buffer (CB) Write Window register */ #define H_CB_WW 0 +/* H_CSR - Host Control Status register */ #define H_CSR 4 +/* ME_CB_RW - ME Circular Buffer Read Window register (read only) */ #define ME_CB_RW 8 +/* ME_CSR_HA - ME Control Status Host Access register (read only) */ #define ME_CSR_HA 0xC -/* register bits - H_CSR */ - +/* register bits of H_CSR (Host Control Status register) */ +/* Host Circular Buffer Depth - maximum number of 32-bit entries in CB */ #define H_CBD 0xFF000000 +/* Host Circular Buffer Write Pointer */ #define H_CBWP 0x00FF0000 +/* Host Circular Buffer Read Pointer */ #define H_CBRP 0x0000FF00 +/* Host Reset */ #define H_RST 0x00000010 +/* Host Ready */ #define H_RDY 0x00000008 +/* Host Interrupt Generate */ #define H_IG 0x00000004 +/* Host Interrupt Status */ #define H_IS 0x00000002 +/* Host Interrupt Enable */ #define H_IE 0x00000001 -/* register bits - ME_CSR_HA */ +/* register bits of ME_CSR_HA (ME Control Status Host Access register) */ +/* ME CB (Circular Buffer) Depth HRA (Host Read Access) + * - host read only access to ME_CBD */ #define ME_CBD_HRA 0xFF000000 +/* ME CB Write Pointer HRA - host read only access to ME_CBWP */ #define ME_CBWP_HRA 0x00FF0000 +/* ME CB Read Pointer HRA - host read only access to ME_CBRP */ #define ME_CBRP_HRA 0x0000FF00 +/* ME Reset HRA - host read only access to ME_RST */ #define ME_RST_HRA 0x00000010 +/* ME Ready HRA - host read only access to ME_RDY */ #define ME_RDY_HRA 0x00000008 +/* ME Interrupt Generate HRA - host read only access to ME_IG */ #define ME_IG_HRA 0x00000004 +/* ME Interrupt Status HRA - host read only access to ME_IS */ #define ME_IS_HRA 0x00000002 +/* ME Interrupt Enable HRA - host read only access to ME_IE */ #define ME_IE_HRA 0x00000001 -/** - * heci driver use additional char device for legacy mode - */ -#define MINORS_COUNT 2 +#define HECI_MINORS_BASE 1 +#define HECI_MINORS_COUNT 1 -#define LEGACY_MINOR_NUMBER 0 #define HECI_MINOR_NUMBER 1 -#define MAX_OPEN_HANDLE_COUNT 253 -/** +#define HECI_MAX_OPEN_HANDLE_COUNT 253 + +/* * debug kernel print macro define */ -#define INFO(format, arg...) printk(KERN_INFO "%s: " format, THIS_MODULE->name, ## arg) -#define ERR(format, arg...) printk(KERN_ERR "%s: " format, THIS_MODULE->name, ## arg) -#define WARN(format, arg...) printk(KERN_WARNING "%s: " format, THIS_MODULE->name, ## arg) +extern int heci_debug; - -/* Module Parameters */ -#define DEF_PARM(type, name, init, perm, desc) \ - type name = (init); \ - MODULE_PARM_DESC(name, desc); \ - module_param(name, type, perm) - -extern int debug; - -#define DBG(format, arg...) do {if (debug) \ -printk(KERN_ERR "%s: " format , __func__ , ## arg); \ +#define DBG(format, arg...) do { \ + if (heci_debug) \ + printk(KERN_INFO "heci: %s: " format, __func__, ## arg); \ } while (0) -#ifdef HECI_DEBUG -#define assert(expr) do {} while (0) -#else -#define assert(expr) \ - if (!(expr)) { \ - printk("Assertion failed! %s, %s, %s, line=%d\n", \ - #expr, __FILE__, __func__, __LINE__); \ - } -#endif -/** - * time to wait event +/* + * time to wait HECI become ready after init */ #define HECI_INTEROP_TIMEOUT (HZ * 7) -/** +/* * watch dog definition */ #define HECI_WATCHDOG_DATA_SIZE 16 #define HECI_START_WD_DATA_SIZE 20 #define HECI_WD_PARAMS_SIZE 4 +#define HECI_WD_STATE_INDEPENDENCE_MSG_SENT (1 << 0) - #define HECI_WD_HOST_CLIENT_ID 1 -#define HECI_LEGACY_HOST_CLIENT_ID 2 +#define HECI_IAMTHIF_HOST_CLIENT_ID 2 -#undef FALSE -#undef TRUE -#define TRUE 1 -#define FALSE 0 - struct guid { __u32 data1; __u16 data2; @@ -178,8 +174,8 @@ HECI_FILE_DISCONNECTED }; -/* HECI states */ -enum heci_states{ +/* HECI device states */ +enum heci_states { HECI_INITIALIZING = 0, HECI_ENABLED, HECI_RESETING, @@ -189,12 +185,12 @@ HECI_POWER_UP }; -enum legacy_states { - HECI_LEGACY_IDLE, - HECI_LEGACY_WRITING, - HECI_LEGACY_FLOW_CONTROL, - HECI_LEGACY_READING, - HECI_LEGACY_READ_COMPLETE +enum iamthif_states { + HECI_IAMTHIF_IDLE, + HECI_IAMTHIF_WRITING, + HECI_IAMTHIF_FLOW_CONTROL, + HECI_IAMTHIF_READING, + HECI_IAMTHIF_READ_COMPLETE }; enum heci_file_transaction_states { @@ -219,14 +215,12 @@ struct heci_message_data { __u32 size; char *data; -}; -#define SECOND_TO_MILLI 1000 -#define SECOND_TO_MICRO SECOND_TO_MILLI * 1000 -#define SECOND_TO_100NANO SECOND_TO_MICRO * 10 +} __attribute__((packed)); -#define CONNECT_TIMEOUT 3 /* at least 2 seconds */ +#define HECI_CONNECT_TIMEOUT 3 /* at least 2 seconds */ -#define LEGACY_STALL_TIMER 12 /* seconds */ +#define IAMTHIF_STALL_TIMER 12 /* seconds */ +#define IAMTHIF_READ_TIMER 15 /* seconds */ struct heci_cb_private { struct list_head cb_list; @@ -235,6 +229,7 @@ struct heci_message_data request_buffer; struct heci_message_data response_buffer; unsigned long information; + unsigned long read_time; struct file *file_object; }; @@ -246,18 +241,19 @@ wait_queue_head_t tx_wait; wait_queue_head_t rx_wait; wait_queue_head_t wait; - spinlock_t file_lock; - spinlock_t read_io_lock; - spinlock_t write_io_lock; + spinlock_t file_lock; /* file lock */ + spinlock_t read_io_lock; /* read lock */ + spinlock_t write_io_lock; /* write lock */ int read_pending; int status; /* ID of client connected */ __u8 host_client_id; __u8 me_client_id; - __u8 flow_control_credentials; + __u8 flow_ctrl_creds; __u8 timer_count; enum heci_file_transaction_states reading_state; enum heci_file_transaction_states writing_state; + int sm_state; struct heci_cb_private *read_cb; }; @@ -272,138 +268,139 @@ __u8 minor; __u8 hotfix; __u16 build; -}; +} __attribute__((packed)); struct heci_client { - __u32 max_message_length; + __u32 max_msg_length; __u8 protocol_version; -}; +} __attribute__((packed)); + /* * HECI BUS Interface Section */ -struct heci_message_header { - __u32 me_address:8; - __u32 host_address:8; +struct heci_msg_hdr { + __u32 me_addr:8; + __u32 host_addr:8; __u32 length:9; __u32 reserved:6; - __u32 message_complete:1; -}; + __u32 msg_complete:1; +} __attribute__((packed)); -struct hbm_command { - __u8 command:7; +struct hbm_cmd { + __u8 cmd:7; __u8 is_response:1; -}; +} __attribute__((packed)); struct heci_bus_message { - struct hbm_command command; + struct hbm_cmd cmd; __u8 command_specific_data[]; -}; +} __attribute__((packed)); struct hbm_version { __u8 minor_version; __u8 major_version; -}; +} __attribute__((packed)); struct hbm_host_version_request { - struct hbm_command command; + struct hbm_cmd cmd; __u8 reserved; struct hbm_version host_version; -}; +} __attribute__((packed)); struct hbm_host_version_response { - struct hbm_command command; + struct hbm_cmd cmd; int host_version_supported; struct hbm_version me_max_version; -}; +} __attribute__((packed)); struct hbm_host_stop_request { - struct hbm_command command; + struct hbm_cmd cmd; __u8 reason; __u8 reserved[2]; -}; +} __attribute__((packed)); struct hbm_host_stop_response { - struct hbm_command command; + struct hbm_cmd cmd; __u8 reserved[3]; -}; +} __attribute__((packed)); struct hbm_me_stop_request { - struct hbm_command command; + struct hbm_cmd cmd; __u8 reason; __u8 reserved[2]; -}; +} __attribute__((packed)); -struct hbm_host_enumeration_request { - struct hbm_command command; +struct hbm_host_enum_request { + struct hbm_cmd cmd; __u8 reserved[3]; -}; +} __attribute__((packed)); -struct hbm_host_enumeration_response { - struct hbm_command command; +struct hbm_host_enum_response { + struct hbm_cmd cmd; __u8 reserved[3]; __u8 valid_addresses[32]; -}; +} __attribute__((packed)); struct heci_client_properties { struct guid protocol_name; __u8 protocol_version; __u8 max_number_of_connections; __u8 fixed_address; - __u8 single_receive_buffer; - __u32 max_message_length; -}; + __u8 single_recv_buf; + __u32 max_msg_length; +} __attribute__((packed)); -struct hbm_host_client_properties_request { - struct hbm_command command; +struct hbm_props_request { + struct hbm_cmd cmd; __u8 address; __u8 reserved[2]; -}; +} __attribute__((packed)); -struct hbm_host_client_properties_response { - struct hbm_command command; +struct hbm_props_response { + struct hbm_cmd cmd; __u8 address; __u8 status; __u8 reserved[1]; struct heci_client_properties client_properties; -}; +} __attribute__((packed)); struct hbm_client_connect_request { - struct hbm_command command; - __u8 me_address; - __u8 host_address; + struct hbm_cmd cmd; + __u8 me_addr; + __u8 host_addr; __u8 reserved; -}; +} __attribute__((packed)); struct hbm_client_connect_response { - struct hbm_command command; - __u8 me_address; - __u8 host_address; + struct hbm_cmd cmd; + __u8 me_addr; + __u8 host_addr; __u8 status; -}; +} __attribute__((packed)); struct hbm_client_disconnect_request { - struct hbm_command command; - __u8 me_address; - __u8 host_address; + struct hbm_cmd cmd; + __u8 me_addr; + __u8 host_addr; __u8 reserved[1]; -}; +} __attribute__((packed)); struct hbm_flow_control { - struct hbm_command command; - __u8 me_address; - __u8 host_address; - __u8 reserved[FC_MESSAGE_RESERVED_LENGTH]; -}; + struct hbm_cmd cmd; + __u8 me_addr; + __u8 host_addr; + __u8 reserved[HECI_FC_MESSAGE_RESERVED_LENGTH]; +} __attribute__((packed)); struct heci_me_client { - struct heci_client_properties properteis; + struct heci_client_properties props; __u8 client_id; - __u8 flow_control_credentials; -}; + __u8 flow_ctrl_creds; +} __attribute__((packed)); /* private device struct */ struct iamt_heci_device { @@ -411,14 +408,17 @@ /* * lists of queues */ - struct io_heci_list *io_list_array[NUMBER_OF_LISTS]; /* array of pointers to aio lists */ - struct io_heci_list read_list; /* driver read queue */ + /* array of pointers to aio lists */ + struct io_heci_list *io_list_array[HECI_IO_LISTS_NUMBER]; + struct io_heci_list read_list; /* driver read queue */ struct io_heci_list write_list; /* driver write queue */ - struct io_heci_list write_waiting_list; /* driver write waiting queue */ - struct io_heci_list control_write_list; /* driver managed write IOCTL list */ - struct io_heci_list control_read_list; /* driver managed read IOCTL list */ - struct io_heci_list pthi_cmd_list; /* driver managed PTHI list for cmd waiting */ - struct io_heci_list pthi_read_complete_list; /* driver managed PTHI list for read completed pthi command data */ + struct io_heci_list write_waiting_list; /* write waiting queue */ + struct io_heci_list ctrl_wr_list; /* managed write IOCTL list */ + struct io_heci_list ctrl_rd_list; /* managed read IOCTL list */ + struct io_heci_list pthi_cmd_list; /* PTHI list for cmd waiting */ + + /* driver managed PTHI list for reading completed pthi cmd data */ + struct io_heci_list pthi_read_complete_list; /* * list of files */ @@ -432,16 +432,12 @@ /* * lock for the device */ - spinlock_t device_lock; - spinlock_t extra_lock; - /* - * intterupts - */ - int irq; + spinlock_t device_lock; /* device lock*/ struct work_struct work; - int received_message; + int recvd_msg; - struct timer_list timer; + struct task_struct *reinit_tsk; + struct timer_list wd_timer; /* * hw states of host and fw(ME) @@ -451,28 +447,25 @@ /* * waiting queue for receive message from FW */ - wait_queue_head_t wait_received_message; + wait_queue_head_t wait_recvd_msg; wait_queue_head_t wait_stop_wd; /* * heci device states */ enum heci_states heci_state; int stop; - /** - * virtual void GetParam(const char* UserParam); - * read write messages to/from heci fw - */ + __u32 extra_write_index; - __u32 read_message_buffer[128]; /* used for control messages */ - __u32 write_message_buffer[128]; /* used for control messages */ - __u32 extra_message_buffer[8]; /* for control responses */ - __u32 read_message_header; + __u32 rd_msg_buf[128]; /* used for control messages */ + __u32 wr_msg_buf[128]; /* used for control messages */ + __u32 ext_msg_buf[8]; /* for control responses */ + __u32 rd_msg_hdr; struct hbm_version version; int host_buffer_is_empty; - struct heci_file_private wd_file_extension; - struct heci_me_client *me_clients; /* Note: memory has to be allocated */ + struct heci_file_private wd_file_ext; + struct heci_me_client *me_clients; /* Note: memory has to be allocated*/ __u8 heci_me_clients[32]; /* list of existing clients */ __u8 num_heci_me_clients; __u8 heci_host_clients[32]; /* list of existing clients */ @@ -486,21 +479,21 @@ __u16 wd_due_counter; int asf_mode; + int wd_bypass; /* if 1, don't refresh watchdog ME client */ - /* maybe this is not required */ - struct file *legacy_file_object; - struct heci_file_private legacy_file_extension; - int legacy_ioctl; - int legacy_canceled; - __u32 legacy_timer; - __u32 legacy_stall_timer; - unsigned char legacy_message_buffer[LEGACY_MTU]; - __u32 legacy_message_buffer_size; - __u32 legacy_message_buffer_index; - int legacy_flow_control_pending; - enum legacy_states legacy_state; + struct file *iamthif_file_object; + struct heci_file_private iamthif_file_ext; + int iamthif_ioctl; + int iamthif_canceled; + __u32 iamthif_timer; + __u32 iamthif_stall_timer; + unsigned char iamthif_msg_buf[IAMTHIF_MTU]; + __u32 iamthif_msg_buf_size; + __u32 iamthif_msg_buf_index; + int iamthif_flow_control_pending; + enum iamthif_states iamthif_state; - struct heci_cb_private *legacy_current_cb; + struct heci_cb_private *iamthif_current_cb; __u8 write_hang; int need_reset; long open_handle_count; @@ -509,23 +502,29 @@ /** * read_heci_register - Read a byte from the heci device - * @device: the device structure + * + * @dev: the device structure * @offset: offset from which to read the data * - * Return: - * the byte read. + * returns the byte read. */ -__u32 read_heci_register(struct iamt_heci_device * device, - unsigned long offset); +static inline __u32 read_heci_register(struct iamt_heci_device *dev, + unsigned long offset) +{ + return readl(dev->mem_addr + offset); +} /** * write_heci_register - Write 4 bytes to the heci device - * @device: the device structure - * @offset: offset from which to write the data * + * @dev: the device structure + * @offset: offset from which to write the data * @value: the byte to write */ -void write_heci_register(struct iamt_heci_device * device, unsigned long offset, - __u32 value); +static inline void write_heci_register(struct iamt_heci_device *dev, + unsigned long offset, __u32 value) +{ + writel(value, dev->mem_addr + offset); +} -#endif /* _HECI_DATA_STRUCTURES_H_ */ +#endif /* _HECI_DATA_STRUCTURES_H_ */ Modified: heci/branches/testing/src/heci_init.c =================================================================== --- heci/branches/testing/src/heci_init.c 2008-07-22 16:25:37 UTC (rev 205) +++ heci/branches/testing/src/heci_init.c 2008-07-22 17:13:05 UTC (rev 206) @@ -1,7 +1,7 @@ /* * Part of Intel(R) Manageability Engine Interface Linux driver * - * Copyright (c) 2007 Intel Corp. + * Copyright (c) 2003 - 2008 Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -41,919 +41,932 @@ #include <linux/module.h> #include <linux/pci.h> #include <linux/reboot.h> -#include <asm/uaccess.h> #include <linux/poll.h> #include <linux/init.h> #include <linux/kdev_t.h> #include <linux/moduleparam.h> #include <linux/wait.h> #include <linux/delay.h> - +#include <linux/kthread.h> #include "kcompat.h" + #include "heci_data_structures.h" #include "heci_interface.h" #include "heci.h" -const __u8 watch_dog_data[] = - { 1, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 }; -const __u8 start_wd_params[] = { 0x02, 0x12, 0x13, 0x10 }; -const __u8 stop_wd_params[] = { 0x02, 0x02, 0x14, 0x10 }; -const struct guid heci_asf_guid = - { 0x75B30CD6, 0xA29E, 0x4AF7, {0xA7, 0x12, 0xE6, 0x17, 0x43, 0x93, - 0xC8, 0xA6} }; -const struct guid heci_wd_guid = - { 0x05B79A6F, 0x4628, 0x4D7F, {0x89, 0x9D, 0xA9, 0x15, 0x14, 0xCB, - 0x32, 0xAB} }; -const struct guid heci_pthi_guid = - { 0x12f80028, 0xb4b7, 0x4b2d, {0xac, 0xa8, 0x46, 0xe0, 0xff, 0x65, - 0x81, 0x4c} }; +const __u8 heci_start_wd_params[] = { 0x02, 0x12, 0x13, 0x10 }; +const __u8 heci_stop_wd_params[] = { 0x02, 0x02, 0x14, 0x10 }; +const __u8 heci_wd_state_independence_msg[3][4] = { + {0x05, 0x02, 0x51, 0x10}, + {0x05, 0x02, 0x52, 0x10}, + {0x07, 0x02, 0x01, 0x10} +}; -/** +const struct guid heci_asf_guid = { + 0x75B30CD6, 0xA29E, 0x4AF7, + {0xA7, 0x12, 0xE6, 0x17, 0x43, 0x93, 0xC8, 0xA6} +}; +const struct guid heci_wd_guid = { + 0x05B79A6F, 0x4628, 0x4D7F, + {0x89, 0x9D, 0xA9, 0x15, 0x14, 0xCB, 0x32, 0xAB} +}; +const struct guid heci_pthi_guid = { + 0x12f80028, 0xb4b7, 0x4b2d, + {0xac, 0xa8, 0x46, 0xe0, 0xff, 0x65, 0x81, 0x4c} +}; + + +/* * heci init function prototypes */ -int host_start_message(struct iamt_heci_device * device_object); -int host_enum_clients_message(struct iamt_heci_device * device_object); -int allocate_me_clents_storage(struct iamt_heci_device * device_object); -void heci_disable(struct iamt_heci_device * device_object); -void host_init_wd(struct iamt_heci_device * device_object); -void host_init_legacy(struct iamt_heci_device * device_object); +static void heci_check_asf_mode(struct iamt_heci_device *dev); +static int host_start_message(struct iamt_heci_device *dev); +static int host_enum_clients_message(struct iamt_heci_device *dev); +static int allocate_me_clients_storage(struct iamt_heci_device *dev); +static void host_init_wd(struct iamt_heci_device *dev); +static void host_init_iamthif(struct iamt_heci_device *dev); +static int heci_wait_event_int_timeout(struct iamt_heci_device *dev, + long timeout); /** - * heci_initialize_list - Sets up a queue list. + * heci_initialize_list - Sets up a queue list. * - * @list - An instance of our list structure - * @device_object -Device object for our driver - * - * @return : - * none; + * @list: An instance of our list structure + * @dev: Device object for our driver */ void heci_initialize_list(struct io_heci_list *list, - struct iamt_heci_device * device_object) + struct iamt_heci_device *dev) { /* initialize our queue list */ INIT_LIST_HEAD(&list->heci_cb.cb_list); - list->status = ESUCCESS; - list->device_extension = device_object; - return; + list->status = 0; + list->device_extension = dev; } /** - * heci_flush_queues - flush our queues list belong to file_extension. + * heci_flush_queues - flush our queues list belong to file_ext. * - * @device_object -Device object for our driver - * - * @return : - * none; + * @dev: Device object for our driver + * @file_ext: private data of the file object */ -void heci_flush_queues(struct iamt_heci_device * device_object, - struct heci_file_private * file_extension) +void heci_flush_queues(struct iamt_heci_device *dev, + struct heci_file_private *file_ext) { int i; - if (!device_object || !file_extension) + + if (!dev || !file_ext) return; - /* flush our queue list belong to file_extension */ - for (i = 0; i < NUMBER_OF_LISTS; i++) { - DBG("remove list etnry belong to file_extension\n"); - heci_flush_list(device_object->io_list_array[i], - file_extension); - } + /* flush our queue list belong to file_ext */ + for (i = 0; i < HECI_IO_LISTS_NUMBER; i++) { + DBG("remove list entry belong to file_ext\n"); + heci_flush_list(dev->io_list_array[i], file_ext); + } } /** - * heci_flush_list - remove list etnry belong to file_extension. + * heci_flush_list - remove list entry belong to file_ext. * - * @list - An instance of our list structure - * @file_extension -extension of the file object - - * @return : - * none; + * @list: An instance of our list structure + * @file_ext: private data of the file object */ void heci_flush_list(struct io_heci_list *list, - struct heci_file_private * file_extension) + struct heci_file_private *file_ext) { - struct heci_file_private *file_extension_temp = NULL; - struct heci_cb_private *kernel_priv_cb_pos = NULL, *kernel_priv_cb_next = NULL; + struct heci_file_private *file_ext_tmp; + struct heci_cb_private *priv_cb_pos = NULL; + struct heci_cb_private *priv_cb_next = NULL; - if (!list || !file_extension) + if (!list || !file_ext) return; - if (list->status == ESUCCESS - && !list_empty(&list->heci_cb.cb_list)) { - list_for_each_entry_safe(kernel_priv_cb_pos, kernel_priv_cb_next, &list->heci_cb.cb_list, cb_list){ - if (kernel_priv_cb_pos) { - file_extension_temp = - (struct heci_file_private *) - kernel_priv_cb_pos->file_private; - } - if (file_extension_temp) { - if ((file_extension->host_client_id == file_extension_temp-> host_client_id) - && (file_extension->me_client_id == file_extension_temp-> me_client_id)) - list_del(&kernel_priv_cb_pos->cb_list); - } + if (list->status != 0) + return; + if (list_empty(&list->heci_cb.cb_list)) + return; + + list_for_each_entry_safe(priv_cb_pos, priv_cb_next, + &list->heci_cb.cb_list, cb_list) { + if (priv_cb_pos) { + file_ext_tmp = (struct heci_file_private *) + priv_cb_pos->file_private; + if (file_ext_tmp) { + if (heci_fe_same_id(file_ext, file_ext_tmp)) + list_del(&priv_cb_pos->cb_list); + } } } - return; } /** + * heci_reset_iamthif_params - initializes heci device iamthif + * + * @dev: The heci device structure + */ +static void heci_reset_iamthif_params(struct iamt_heci_device *dev) +{ + /* reset iamthif parameters. */ + dev->iamthif_current_cb = NULL; + dev->iamthif_msg_buf_size = 0; + dev->iamthif_msg_buf_index = 0; + dev->iamthif_canceled = 0; + dev->iamthif_file_ext.file = NULL; + dev->iamthif_ioctl = 0; + dev->iamthif_state = HECI_IAMTHIF_IDLE; + dev->iamthif_timer = 0; +} + +/** * init_heci_device - allocates and initializes the heci device structure + * * @pdev: The pci device structure * - * @return : - * The heci_device_device pointer on success, NULL on failure. + * returns The heci_device_device pointer on success, NULL on failure. */ -struct iamt_heci_device *init_heci_device(struct pci_dev * pdev) +struct iamt_heci_device *init_heci_device(struct pci_dev *pdev) { int i; - struct iamt_heci_device *device; - device = kmalloc(sizeof(struct iamt_heci_device), GFP_KERNEL); - if (!device) { + struct iamt_heci_device *dev; + + dev = kzalloc(sizeof(struct iamt_heci_device), GFP_KERNEL); + if (!dev) return NULL; - } /* setup our list array */ - device->io_list_array[0] = &device->read_list; - device->io_list_array[1] = &device->write_list; - device->io_list_array[2] = &device->write_waiting_list; - device->io_list_array[3] = &device->control_write_list; - device->io_list_array[4] = &device->control_read_list; - device->io_list_array[5] = &device->pthi_cmd_list; - device->io_list_array[6] = &device->pthi_read_complete_list; - INIT_LIST_HEAD(&device->file_list); - INIT_LIST_HEAD(&device->wd_file_extension.link); - INIT_LIST_HEAD(&device->legacy_file_extension.link); - spin_lock_init(&device->device_lock); - init_waitqueue_head(&device->wait_received_message); - init_waitqueue_head(&device->wait_stop_wd); - device->open_handle_count = 0; - device->num_heci_me_clients = 0; - device->mem_base = 0; - device->mem_length = 0; - device->extra_write_index = 0; - device->read_message_header = 0; - device->mem_addr = NULL; - device->asf_mode = FALSE; - device->need_reset = FALSE; - device->received_message = FALSE; - device->heci_state = HECI_INITIALIZING; + dev->io_list_array[0] = &dev->read_list; + dev->io_list_array[1] = &dev->write_list; + dev->io_list_array[2] = &dev->write_waiting_list; + dev->io_list_array[3] = &dev->ctrl_wr_list; + dev->io_list_array[4] = &dev->ctrl_rd_list; + dev->io_list_array[5] = &dev->pthi_cmd_list; + dev->io_list_array[6] = &dev->pthi_read_complete_list; + INIT_LIST_HEAD(&dev->file_list); + INIT_LIST_HEAD(&dev->wd_file_ext.link); + INIT_LIST_HEAD(&dev->iamthif_file_ext.link); + spin_lock_init(&dev->device_lock); + init_waitqueue_head(&dev->wait_recvd_msg); + init_waitqueue_head(&dev->wait_stop_wd); + dev->heci_state = HECI_INITIALIZING; + dev->iamthif_state = HECI_IAMTHIF_IDLE; - device->num_heci_me_clients = 0; - device->legacy_current_cb = NULL; - device->legacy_file_object = NULL; - device->legacy_canceled = FALSE; - device->legacy_flow_control_pending = FALSE; - device->legacy_state = HECI_LEGACY_IDLE; - device->legacy_message_buffer_index = 0; - device->wd_pending = FALSE; - device->wd_stoped = FALSE; - - device->me_clients = NULL; /* init work for schedule work */ - INIT_WORK(&device->work, NULL); - for (i = 0; i < NUMBER_OF_LISTS; i++) - heci_initialize_list(device->io_list_array[i], device); - device->pdev = pdev; - return device; + INIT_WORK(&dev->work, NULL); + for (i = 0; i < HECI_IO_LISTS_NUMBER; i++) + heci_initialize_list(dev->io_list_array[i], dev); + dev->pdev = pdev; + return dev; } + + + +static int heci_wait_event_int_timeout(struct iamt_heci_device *dev, + long timeout) +{ + return wait_event_interruptible_timeout(dev->wait_recvd_msg, + (dev->recvd_msg), timeout); +} + /** * heci_hw_init - init host and fw to start work. * - * @device_object -Device object for our driver + * @dev: Device object for our driver * - *@return: - * 0 on success. - * negative on failure + * returns 0 on success, <0 on failure. */ -int heci_hw_init(struct iamt_heci_device * device_object) +int heci_hw_init(struct iamt_heci_device *dev) { int err = 0; - device_object->host_hw_state = - read_heci_register(device_object, H_CSR); - device_object->me_hw_state = - read_heci_register(device_object, ME_CSR_HA); + + dev->host_hw_state = read_heci_register(dev, H_CSR); + dev->me_hw_state = read_heci_register(dev, ME_CSR_HA); DBG("host_hw_state = 0x%08x, mestate = 0x%08x.\n", - device_object->host_hw_state, device_object->me_hw_state); + dev->host_hw_state, dev->me_hw_state); - if ((device_object->host_hw_state & H_IS) == H_IS) { + if ((dev->host_hw_state & H_IS) == H_IS) { /* acknowledge interrupt and stop interupts */ - write_heci_register(device_object, H_CSR, - device_object->host_hw_state); + heci_set_csr_register(dev); } - device_object->received_message = FALSE; + dev->recvd_msg = 0; DBG("reset in start the heci device.\n"); - heci_reset(device_object, TRUE); + heci_reset(dev, 1); DBG("host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n", - device_object->host_hw_state, device_object->me_hw_state); + dev->host_hw_state, dev->me_hw_state); /* wait for ME to turn on ME_RDY */ - if (!device_object->received_message) { - err = - wait_event_interruptible_timeout(device_object-> - wait_received_message, - (device_object-> - received_message), - HECI_INTEROP_TIMEOUT); - } + if (!dev->recvd_msg) + err = heci_wait_event_int_timeout(dev, HECI_INTEROP_TIMEOUT); - if (!err && !device_object->received_message) { - device_object->heci_state = HECI_DISABLED; - DBG("wait_event_interruptible_timeout failed on wait for ME to turn on ME_RDY.\n"); + if (!err && !dev->recvd_msg) { + dev->heci_state = HECI_DISABLED; + DBG("wait_event_interruptible_timeout failed" + "on wait for ME to turn on ME_RDY.\n"); return -ENODEV; } else { - if (!(((device_object->host_hw_state & H_RDY) == H_RDY) - && ((device_object->me_hw_state & ME_RDY_HRA) == - ME_RDY_HRA))) { - device_object->heci_state = HECI_DISABLED; + if (!(((dev->host_hw_state & H_RDY) == H_RDY) + && ((dev->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA))) { + dev->heci_state = HECI_DISABLED; DBG("host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n", - device_object->host_hw_state, - device_object->me_hw_state); + dev->host_hw_state, + dev->me_hw_state); - if (!(device_object->host_hw_state & H_RDY) != H_RDY) + if (!(dev->host_hw_state & H_RDY) != H_RDY) DBG("host turn off H_RDY.\n"); - if (!(device_object->me_hw_state & ME_RDY_HRA) != ME_RDY_HRA) + + if (!(dev->me_hw_state & ME_RDY_HRA) != ME_RDY_HRA) DBG("ME turn off ME_RDY.\n"); - ERR("link layer initialization failed.\n"); + + printk(KERN_ERR + "heci: link layer initialization failed.\n"); return -ENODEV; } } - device_object->received_message = FALSE; + dev->recvd_msg = 0; DBG("host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n", - device_object->host_hw_state, device_object->me_hw_state); + dev->host_hw_state, dev->me_hw_state); DBG("ME turn on ME_RDY and host turn on H_RDY.\n"); - INFO("link layer has been established.\n"); - return ESUCCESS; + printk(KERN_INFO "heci: link layer has been established.\n"); + return 0; } /** - * heci_reset - reset host and fw. + * heci_hw_reset - reset fw via heci csr register. * - * @device_object -Device object for our driver - * @interrupts - if interrupt should be enable after reset. + * @dev: Device object for our driver + * @interrupts: if interrupt should be enable after reset. + */ +static void heci_hw_reset(struct iamt_heci_device *dev, int interrupts) +{ + dev->host_hw_state |= (H_RST | H_IG); + + if (interrupts) + heci_csr_enable_interrupts(dev); + else + heci_csr_disable_interrupts(dev); + + BUG_ON((dev->host_hw_state & H_RST) != H_RST); + BUG_ON((dev->host_hw_state & H_RDY) != 0); +} + +/** + * heci_reset - reset host and fw. * - * @return: - * none; + * @dev: Device object for our driver + * @interrupts: if interrupt should be enable after reset. */ -void heci_reset(struct iamt_heci_device * device_object, int interrupts) +void heci_reset(struct iamt_heci_device *dev, int interrupts) { - struct heci_file_private *file_extension_pos = NULL; - struct heci_file_private *file_extension_next = NULL; - struct heci_cb_private *kernel_priv_cb_pos = NULL, - *kernel_priv_cb_next = NULL; + struct heci_file_private *file_pos = NULL; + struct heci_file_private *file_next = NULL; + struct heci_cb_private *priv_cb_pos = NULL; + struct heci_cb_private *priv_cb_next = NULL; + int unexpected = 0; - if (device_object->heci_state == HECI_RECOVERING_FROM_RESET) { - device_object->need_reset = TRUE; + if (dev->heci_state == HECI_RECOVERING_FROM_RESET) { + dev->need_reset = 1; return; } - device_object->host_hw_state = - read_heci_register(device_object, H_CSR); - DBG("before reset host_hw_state = 0x%08x.\n", - device_object->host_hw_state); + if (dev->heci_state != HECI_INITIALIZING && + dev->heci_state != HECI_DISABLED && + dev->heci_state != HECI_POWER_DOWN && + dev->heci_state != HECI_POWER_UP) + unexpected = 1; - device_object->host_hw_state |= (H_RST | H_IG); + if (dev->reinit_tsk != NULL) { + kthread_stop(dev->reinit_tsk); + dev->reinit_tsk = NULL; + } - if (interrupts) - device_object->host_hw_state |= (H_IE); - else - device_object->host_hw_state &= ~(H_IE); + dev->host_hw_state = read_heci_register(dev, H_CSR); - write_heci_register(device_object, H_CSR, - device_object->host_hw_state); + DBG("before reset host_hw_state = 0x%08x.\n", + dev->host_hw_state); - device_object->host_hw_state = - read_heci_register(device_object, H_CSR); - BUG_ON((device_object->host_hw_state & H_RST) != H_RST); - BUG_ON((device_object->host_hw_state & H_RDY) != 0); + heci_hw_reset(dev, interrupts); - device_object->host_hw_state &= ~H_RST; - device_object->host_hw_state |= H_IG; + dev->host_hw_state &= ~H_RST; + dev->host_hw_state |= H_IG; - write_heci_register(device_object, H_CSR, - device_object->host_hw_state); + write_heci_register(dev, H_CSR, dev->host_hw_state); DBG("currently saved host_hw_state = 0x%08x.\n", - device_object->host_hw_state); + dev->host_hw_state); - device_object->need_reset = FALSE; + dev->need_reset = 0; - if (device_object->heci_state != HECI_INITIALIZING) { - if (device_object->heci_state != HECI_DISABLED) { - device_object->heci_state = HECI_RESETING; + if (dev->heci_state != HECI_INITIALIZING) { + if ((dev->heci_state != HECI_DISABLED) && + (dev->heci_state != HECI_POWER_DOWN)) + dev->heci_state = HECI_RESETING; + + list_for_each_entry_safe(file_pos, + file_next, &dev->file_list, link) { + file_pos->state = HECI_FILE_DISCONNECTED; + file_pos->flow_ctrl_creds = 0; + file_pos->read_cb = NULL; + file_pos->timer_count = 0; } - list_for_each_entry_safe(file_extension_pos, file_extension_next, &device_object->file_list, link) { - file_extension_pos->state = HECI_FILE_DISCONNECTED; - file_extension_pos->flow_control_credentials = 0; - file_extension_pos->read_cb = NULL; - file_extension_pos->timer_count = 0; - } /* remove entry if already in list */ - DBG("list del legacy and wd file list.\n"); - heci_remove_client_from_file_list(device_object, - device_object-> - wd_file_extension. - host_client_id); + DBG("list del iamthif and wd file list.\n"); + heci_remove_client_from_file_list(dev, + dev->wd_file_ext.host_client_id); - heci_remove_client_from_file_list(device_object, - device_object-> - legacy_file_extension. - host_client_id); - /* reset legacy parameters. */ - device_object->legacy_current_cb = NULL; - device_object->legacy_message_buffer_size = 0; - device_object->legacy_message_buffer_index = 0; - device_object->legacy_canceled = FALSE; - device_object->legacy_file_extension.file = NULL; - device_object->legacy_ioctl = FALSE; - device_object->legacy_state = HECI_LEGACY_IDLE; - device_object->legacy_timer = 0; - device_object->wd_due_counter = 0; - device_object->extra_write_index = 0; - device_object->wd_pending = FALSE; + heci_remove_client_from_file_list(dev, + dev->iamthif_file_ext.host_client_id); + + heci_reset_iamthif_params(dev); + dev->wd_due_counter = 0; + dev->extra_write_index = 0; } - device_object->num_heci_me_clients = 0; - device_object->read_message_header = 0; - device_object->stop = FALSE; - device_object->wd_pending = 0; + dev->num_heci_me_clients = 0; + dev->rd_msg_hdr = 0; + dev->stop = 0; + dev->wd_pending = 0; /* update the state of the registers after reset */ - device_object->host_hw_state = - read_heci_register(device_object, H_CSR); - device_object->me_hw_state = - read_heci_register(device_object, ME_CSR_HA); + dev->host_hw_state = read_heci_register(dev, H_CSR); + dev->me_hw_state = read_heci_register(dev, ME_CSR_HA); DBG("after reset host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n", - device_object->host_hw_state, device_object->me_hw_state); + dev->host_hw_state, dev->me_hw_state); - if (device_object->heci_state != HECI_INITIALIZING && - device_object->heci_state != HECI_DISABLED) - ERR("unexpected heci reset.\n"); - //Wake up all readings so they can be interrupted - list_for_each_entry_safe(file_extension_pos,file_extension_next, &device_object->file_list,link) { - if (&file_extension_pos->rx_wait && - waitqueue_active (&file_extension_pos->rx_wait)) { - INFO("Waking up client!\n"); - wake_up_interruptible(&file_extension_pos->rx_wait); - } + if (unexpected) + printk(KERN_WARNING "heci: unexpected reset.\n"); + + /* Wake up all readings so they can be interrupted */ + list_for_each_entry_safe(file_pos, file_next, &dev->file_list, link) { + if (&file_pos->rx_wait && + waitqueue_active(&file_pos->rx_wait)) { + printk(KERN_INFO "heci: Waking up client!\n"); + wake_up_interruptible(&file_pos->rx_wait); } - // remove all waiting requests - if (device_object->write_list.status == ESUCCESS && !list_empty(&device_object->write_list.heci_cb.cb_list)) { - list_for_each_entry_safe(kernel_priv_cb_pos, kernel_priv_cb_next, &device_object->write_list.heci_cb.cb_list, cb_list){ - if (kernel_priv_cb_pos) { - list_del(&kernel_priv_cb_pos->cb_list); - kfree(kernel_priv_cb_pos->request_buffer.data); - kernel_priv_cb_pos->request_buffer.data = NULL; - kfree(kernel_priv_cb_pos->response_buffer.data); - kernel_priv_cb_pos->response_buffer.data = NULL; - kfree(kernel_priv_cb_pos); - kernel_priv_cb_pos = NULL; + } + /* remove all waiting requests */ + if (dev->write_list.status == 0 && + !list_empty(&dev->write_list.heci_cb.cb_list)) { + list_for_each_entry_safe(priv_cb_pos, priv_cb_next, + &dev->write_list.heci_cb.cb_list, cb_list) { + if (priv_cb_pos) { + list_del(&priv_cb_pos->cb_list); + heci_free_cb_private(priv_cb_pos); } } } - - } /** - * heci_disable - reseting in disable routine. + * heci_initialize_clients - heci communication initialization. * - * @device_object -Device object for our driver - * - * @return: - * none; + * @dev: Device object for our driver */ -void heci_disable(struct iamt_heci_device * device_object) +int heci_initialize_clients(struct iamt_heci_device *dev) { - if (device_object->heci_state != HECI_INITIALIZING) - ERR("driver stop request heci state is disable.\n"); - device_object->heci_state = HECI_DISABLED; -} - -/** - * heci_initialize_clients - routine. - * - * @device_object -Device object for our driver - * - * @return: - * none; - */ -int heci_initialize_clients(void *data) -{ - int status; - struct iamt_heci_device *device_object = (struct iamt_heci_device *) data; + + msleep(100); /* FW needs time to be ready to talk with us */ DBG("link is established start sending messages.\n"); /* link is established start sending messages. */ - status = host_start_message(device_object); - if (status) { + status = host_start_message(dev); + if (status != 0) { + spin_lock_bh(&dev->device_lock); + dev->heci_state = HECI_DISABLED; + spin_unlock_bh(&dev->device_lock); DBG("start sending messages failed.\n"); - return -ENODEV; + return status; } - /* enumerate clients */ - status = host_enum_clients_message(device_object); - if (status) { + /* enumerate clients */ + status = host_enum_clients_message(dev); + if (status != 0) { + spin_lock_bh(&dev->device_lock); + dev->heci_state = HECI_DISABLED; + spin_unlock_bh(&dev->device_lock); DBG("enum clients failed.\n"); - return -ENODEV; + return status; } /* allocate storage for ME clients representation */ - status = allocate_me_clents_storage(device_object); - if (status) { + status = allocate_me_clients_storage(dev); + if (status != 0) { + spin_lock_bh(&dev->device_lock); + dev->num_heci_me_clients = 0; + dev->heci_state = HECI_DISABLED; + spin_unlock_bh(&dev->device_lock); DBG("allocate clients failed.\n"); - return -ENODEV; + return status; } + + heci_check_asf_mode(dev); /*heci initialization wd */ - host_init_wd(device_object); - /*heci initialization legacy client */ - host_init_legacy(device_object); - if (device_object->need_reset) { - device_object->need_reset = FALSE; - device_object->heci_state = HECI_DISABLED; + host_init_wd(dev); + /*heci initialization iamthif client */ + host_init_iamthif(dev); + + spin_lock_bh(&dev->device_lock); + if (dev->need_reset) { + dev->need_reset = 0; + dev->heci_state = HECI_DISABLED; + spin_unlock_bh(&dev->device_lock); return -ENODEV; } - memset(device_object->heci_host_clients, 0, - sizeof(device_object->heci_host_clients)); - device_object->open_handle_count = 0; - device_object->heci_host_clients[0] |= 7; - device_object->current_host_client_id = 3; - device_object->heci_state = HECI_ENABLED; + memset(dev->heci_host_clients, 0, sizeof(dev->heci_host_clients)); + dev->open_handle_count = 0; + dev->heci_host_clients[0] |= 7; + dev->current_host_client_id = 3; + dev->heci_state = HECI_ENABLED; + spin_unlock_bh(&dev->device_lock); DBG("initialization heci clients successful.\n"); - return ESUCCESS; + return 0; } /** + * heci_task_initialize_clients - heci reinitialization task + * + * @data: Device object for our driver + */ +int heci_task_initialize_clients(void *data) +{ + int ret; + struct iamt_heci_device *dev = (struct iamt_heci_device *) data; + + spin_lock_bh(&dev->device_lock); + if (dev->reinit_tsk != NULL) { + spin_unlock_bh(&dev->device_lock); + DBG("reinit task already started.\n"); + return 0; + } + dev->reinit_tsk = current; + current->flags |= PF_NOFREEZE; + spin_unlock_bh(&dev->device_lock); + + ret = heci_initialize_clients(dev); + + spin_lock_bh(&dev->device_lock); + dev->reinit_tsk = NULL; + spin_unlock_bh(&dev->device_lock); + + return ret; +} + +/** * host_start_message - heci host send start message. * - * @device_object - Device object for our driver + * @dev: Device object for our driver * - * @return : - * 0 on success, - * negative on failure. + * returns 0 on success, <0 on failure. */ -int host_start_message(struct iamt_heci_device * device_object) +static int host_start_message(struct iamt_heci_device *dev) { - long timeout = 10; /* 10 second */ + long timeout = 60; /* 60 second */ - struct heci_message_header *heci_header; + struct heci_msg_hdr *heci_hdr; struct hbm_host_version_request *host_start_req; struct hbm_host_stop_request *host_stop_req; int err = 0; + /* host start message */ - msleep(100); - heci_header = - (struct heci_message_header *) & device_object-> - write_message_buffer[0]; - heci_header->host_address = 0; - heci_header->me_address = 0; - heci_header->length = sizeof(struct hbm_host_version_request); - heci_header->message_complete = 1; - heci_header->reserved = 0; + heci_hdr = (struct heci_msg_hdr *) &dev->wr_msg_buf[0]; + heci_hdr->host_addr = 0; + heci_hdr->me_addr = 0; + heci_hdr->length = sizeof(struct hbm_host_version_request); + heci_hdr->msg_complete = 1; + heci_hdr->reserved = 0; host_start_req = - (struct hbm_host_version_request *) & device_object-> - write_message_buffer[1]; - memset(host_start_req, 0, sizeof(host_start_req)); - host_start_req->command.command = HOST_START_REQ_CMD; - host_start_req->reserved = 0; + (struct hbm_host_version_request *) &dev->wr_msg_buf[1]; + memset(host_start_req, 0, sizeof(struct hbm_host_version_request)); + host_start_req->cmd.cmd = HOST_START_REQ_CMD; host_start_req->host_version.major_version = HBM_MAJOR_VERSION; host_start_req->host_version.minor_version = HBM_MINOR_VERSION; - device_object->received_message = FALSE; - if (!heci_write_message(device_object, heci_header, + dev->recvd_msg = 0; + if (!heci_write_message(dev, heci_hdr, (unsigned char *) (host_start_req), - heci_header->length)) { - device_object->heci_state = HECI_DISABLED; + heci_hdr->length)) { DBG("send version to fw fail.\n"); return -ENODEV; } - DBG("call wait_event_interruptible_timeout for response message. \n"); + DBG("call wait_event_interruptible_timeout for response message.\n"); /* wait for response */ - err = - wait_event_interruptible_timeout(device_object-> - wait_received_message, - (device_object-> - received_message), - timeout * HZ); - if (!err && !device_object->received_message) { - device_object->heci_state = HECI_DISABLED; - DBG("wait_event_interruptible_timeout failed on host start response message. \n"); + err = heci_wait_event_int_timeout(dev, timeout * HZ); + if (!err && !dev->recvd_msg) { + DBG("wait_timeout failed on host start response message.\n"); return -ENODEV; } - device_object->received_message = FALSE; - DBG("wait_event_interruptible_timeout successful on host start response message. \n"); - if ((device_object->version.major_version != HBM_MAJOR_VERSION) || - (device_object->version.minor_version != HBM_MINOR_VERSION)) { + dev->recvd_msg = 0; + DBG("wait_timeout successful on host start response message.\n"); + if ((dev->version.major_version != HBM_MAJOR_VERSION) || + (dev->version.minor_version != HBM_MINOR_VERSION)) { /* send stop message */ - heci_header->host_address = 0; - heci_header->me_address = 0; - heci_header->length = sizeof(struct hbm_host_stop_request); - heci_header->message_complete = 1; - heci_header->reserved = 0; + heci_hdr->host_addr = 0; + heci_hdr->me_addr = 0; + heci_hdr->length = sizeof(struct hbm_host_stop_request); + heci_hdr->msg_complete = 1; + heci_hdr->reserved = 0; host_stop_req = - (struct hbm_host_stop_request *) & device_object-> - write_message_buffer[1]; + (struct hbm_host_stop_request *) &dev->wr_msg_buf[1]; - memset(host_stop_req, 0, sizeof(host_stop_req)); - host_st... [truncated message content] |
From: <mar...@us...> - 2008-07-22 17:20:18
|
Revision: 207 http://openamt.svn.sourceforge.net/openamt/?rev=207&view=rev Author: marcin_obara Date: 2008-07-22 17:20:27 +0000 (Tue, 22 Jul 2008) Log Message: ----------- experimental code with changed driver architecture Modified Paths: -------------- heci/branches/testing/README heci/branches/testing/src/Makefile heci/branches/testing/src/heci.h heci/branches/testing/src/heci_data_structures.h heci/branches/testing/src/heci_init.c heci/branches/testing/src/heci_interface.c heci/branches/testing/src/heci_interface.h heci/branches/testing/src/heci_main.c heci/branches/testing/src/heci_version.h heci/branches/testing/src/interrupt.c heci/branches/testing/src/io_heci.c heci/branches/testing/src/kcompat.h Modified: heci/branches/testing/README =================================================================== --- heci/branches/testing/README 2008-07-22 17:13:05 UTC (rev 206) +++ heci/branches/testing/README 2008-07-22 17:20:27 UTC (rev 207) @@ -8,6 +8,11 @@ // //---------------------------------------------------------------------------- + THIS IS EXPERIMENTAL, UNTESTED AND POSSIBLY UNSTABLE + version of MEI driver + USE OFFICIAL ONE INSTEAD OF THIS + + Intel(R) Manageability Engine Interface Driver =========================== Modified: heci/branches/testing/src/Makefile =================================================================== --- heci/branches/testing/src/Makefile 2008-07-22 17:13:05 UTC (rev 206) +++ heci/branches/testing/src/Makefile 2008-07-22 17:20:27 UTC (rev 207) @@ -40,6 +40,15 @@ # ################################################################################ +$(warning **************************************************************) +$(warning *** ***) +$(warning *** THIS IS EXPERIMENTAL, UNTESTED AND POSSIBLY UNSTABLE ***) +$(warning *** version of MEI driver ***) +$(warning *** ***) +$(warning *** USE OFFICIAL ONE INSTEAD OF THIS ***) +$(warning *** ***) +$(warning **************************************************************) + ########################################################################### # Driver files @@ -223,6 +232,8 @@ endif endif +else + $(error Linux kernel 2.6 (>=2.6.16) required) endif # ifeq ($(K_VERSION),2.6) install: default Modified: heci/branches/testing/src/heci.h =================================================================== --- heci/branches/testing/src/heci.h 2008-07-22 17:13:05 UTC (rev 206) +++ heci/branches/testing/src/heci.h 2008-07-22 17:20:27 UTC (rev 207) @@ -41,17 +41,8 @@ #ifndef _HECI_H_ #define _HECI_H_ -#include <linux/version.h> -#include <linux/spinlock.h> -#include <linux/list.h> -#include <linux/pci.h> -#include <linux/timer.h> -#include <linux/interrupt.h> -#include <linux/workqueue.h> -#include <linux/module.h> -#include <linux/aio.h> -#include <linux/types.h> #include "heci_data_structures.h" +#include "heci_interface.h" extern const struct guid heci_pthi_guid; extern const struct guid heci_wd_guid; @@ -91,6 +82,7 @@ #define HECI_DEV_ID_ICH10_2 0x2E14 /* Eaglelake */ #define HECI_DEV_ID_ICH10_3 0x2E24 /* Eaglelake */ #define HECI_DEV_ID_ICH10_4 0x2E34 /* Eaglelake */ +#define HECI_DEV_ID_ICH10_5 0x2E44 /* Eaglelake */ /* * heci init function prototypes @@ -100,19 +92,19 @@ int heci_hw_init(struct iamt_heci_device *dev); int heci_task_initialize_clients(void *data); int heci_initialize_clients(struct iamt_heci_device *dev); -struct heci_file_private *heci_alloc_file_private(struct file *file); -int heci_disconnect_host_client(struct iamt_heci_device *dev, - struct heci_file_private *file_ext); -void heci_initialize_list(struct io_heci_list *list, +struct heci_file_priv *heci_alloc_file_priv(struct file *file); +struct heci_connection *heci_alloc_heci_connection(struct file *file); +void heci_put_heci_connection(struct heci_connection *conn); +#define heci_free_heci_connection heci_put_heci_connection +void put_heci_device(struct iamt_heci_device *dev); +#define get_heci_device(dev) atomic_inc(&dev->refcnt) +#define free_heci_device put_heci_device +void heci_initialize_list(struct heci_io_list *list, struct iamt_heci_device *dev); -void heci_flush_list(struct io_heci_list *list, - struct heci_file_private *file_ext); -void heci_flush_queues(struct iamt_heci_device *dev, - struct heci_file_private *file_ext); +int heci_flush_list(struct heci_io_list *list, + struct heci_connection *conn, + struct heci_cb_private *priv_cb); -void heci_remove_client_from_file_list(struct iamt_heci_device *dev, - __u8 host_client_id); - /* * interrupt function prototype */ @@ -120,54 +112,69 @@ void heci_wd_timer(unsigned long data); +int heci_isr_thread(void *data); + /* * input output function prototype */ -int heci_ioctl_get_version(struct iamt_heci_device *dev, int if_num, +int heci_ioctl_get_version(struct iamt_heci_device *dev, struct heci_message_data *u_msg, - struct heci_message_data k_msg, - struct heci_file_private *file_ext); + struct heci_message_data k_msg); -int heci_ioctl_connect_client(struct iamt_heci_device *dev, int if_num, +int heci_ioctl_connect_client(struct iamt_heci_device *dev, struct heci_message_data *u_msg, struct heci_message_data k_msg, - struct file *file); + struct heci_file_priv *file_ext); -int heci_ioctl_wd(struct iamt_heci_device *dev, int if_num, - struct heci_message_data k_msg, - struct heci_file_private *file_ext); +int heci_ioctl_wd(struct iamt_heci_device *dev, + struct heci_message_data k_msg); -int heci_ioctl_bypass_wd(struct iamt_heci_device *dev, int if_num, - struct heci_message_data k_msg, - struct heci_file_private *file_ext); +int heci_ioctl_bypass_wd(struct iamt_heci_device *dev, + struct heci_message_data k_msg); -int heci_start_read(struct iamt_heci_device *dev, int if_num, - struct heci_file_private *file_ext); +int heci_have_slots(__s32 *slots, __u32 datalen); -int pthi_write(struct iamt_heci_device *dev, - struct heci_cb_private *priv_cb); +int heci_start_read_flow(struct iamt_heci_device *dev, + struct heci_connection *conn, + struct heci_cb_private *priv_cb, + __s32 *slots); -int pthi_read(struct iamt_heci_device *dev, int if_num, struct file *file, - char *ubuf, size_t length, loff_t *offset); +__u32 heci_len_to_slots(__u32 datalen); -struct heci_cb_private *find_pthi_read_list_entry( - struct iamt_heci_device *dev, - struct file *file); +int heci_write_buf(struct iamt_heci_device *dev, + struct heci_cb_private *priv_cb, + struct heci_connection *conn, + __u32 wrspace, __u32 maxwrspace, __s32 *slots); -void run_next_iamthif_cmd(struct iamt_heci_device *dev); +int heci_read_raw(struct iamt_heci_device *dev, + struct heci_file_priv *file_ext, + struct heci_cb_private *priv_cb, + char *ubuf, size_t length, loff_t *offset, + unsigned long timeout, int *needfree); -void heci_free_cb_private(struct heci_cb_private *priv_cb); +struct heci_cb_private *heci_find_list_conn_entry( + struct heci_io_list *list, + struct heci_connection *conn); +struct heci_cb_private *heci_find_list_file_entry( + struct heci_io_list *list, + struct file *file); + +struct heci_cb_private *heci_find_read_entry(struct iamt_heci_device *dev, + struct file *file, __u8 *rcomplete); + +int heci_wd(struct iamt_heci_device *dev, __s32 *slots); + /** - * heci_fe_same_id - tell if file private data have same id + * heci_fe_same_id - tell if file connection data have same id * - * @fe1: private data of 1. file object - * @fe2: private data of 2. file object + * @fe1: connection data of 1. file object + * @fe2: connection data of 2. file object * * returns !=0 - if ids are the same, 0 - if differ. */ -static inline int heci_fe_same_id(const struct heci_file_private *fe1, - const struct heci_file_private *fe2) +static inline int heci_fe_same_id(const struct heci_connection *fe1, + const struct heci_connection *fe2) { return ((fe1->host_client_id == fe2->host_client_id) && (fe1->me_client_id == fe2->me_client_id)); Modified: heci/branches/testing/src/heci_data_structures.h =================================================================== --- heci/branches/testing/src/heci_data_structures.h 2008-07-22 17:13:05 UTC (rev 206) +++ heci/branches/testing/src/heci_data_structures.h 2008-07-22 17:20:27 UTC (rev 207) @@ -41,32 +41,36 @@ #ifndef _HECI_DATA_STRUCTURES_H_ #define _HECI_DATA_STRUCTURES_H_ -#include <linux/version.h> +#include <linux/module.h> +#include <linux/kernel.h> #include <linux/spinlock.h> #include <linux/list.h> -#include <linux/pci.h> #include <linux/timer.h> #include <linux/interrupt.h> #include <linux/workqueue.h> -#include <linux/module.h> -#include <linux/aio.h> #include <linux/types.h> +#include <linux/errno.h> +#include <linux/ioctl.h> +#include <linux/pci.h> +#include <linux/delay.h> +#include <linux/kthread.h> +#include <linux/poll.h> +#include <linux/cdev.h> +#include <linux/device.h> +#include <linux/moduleparam.h> +#include "kcompat.h" /* * error code definition */ #define ESLOTS_OVERFLOW 1 #define ECORRUPTED_MESSAGE_HEADER 1000 -#define ECOMPLETE_MESSAGE 1001 +#define EMESSAGE_NOT_COMPLETE 1001 +#define EMESSAGE_WILL_SPLIT 1002 #define HECI_FC_MESSAGE_RESERVED_LENGTH 5 /* - * Number of queue lists used by this driver - */ -#define HECI_IO_LISTS_NUMBER 7 - -/* * Maximum transmission unit (MTU) of heci messages */ #define IAMTHIF_MTU 4160 @@ -129,16 +133,21 @@ #define HECI_MINORS_COUNT 1 #define HECI_MINOR_NUMBER 1 -#define HECI_MAX_OPEN_HANDLE_COUNT 253 /* * debug kernel print macro define */ extern int heci_debug; +extern struct device *heci_dev; #define DBG(format, arg...) do { \ - if (heci_debug) \ - printk(KERN_INFO "heci: %s: " format, __func__, ## arg); \ + if (heci_debug) { \ + if (heci_dev) \ + dev_info(heci_dev, "%s: " format, __func__, ## arg); \ + else \ + printk(KERN_INFO "heci: %s: " format, \ + __func__, ## arg); \ + } \ } while (0) @@ -153,10 +162,14 @@ #define HECI_WATCHDOG_DATA_SIZE 16 #define HECI_START_WD_DATA_SIZE 20 #define HECI_WD_PARAMS_SIZE 4 -#define HECI_WD_STATE_INDEPENDENCE_MSG_SENT (1 << 0) +#define HECI_WD_STATE_INDEP 1 +/* reserved host client ids (0,1,2) */ #define HECI_WD_HOST_CLIENT_ID 1 #define HECI_IAMTHIF_HOST_CLIENT_ID 2 +#define HECI_LAST_FIX_HOST_CLIENT_ID HECI_IAMTHIF_HOST_CLIENT_ID +/* 256 - 3 reserved */ +#define HECI_MAX_OPEN_HANDLE_COUNT 253 struct guid { __u32 data1; @@ -182,24 +195,19 @@ HECI_DISABLED, HECI_RECOVERING_FROM_RESET, HECI_POWER_DOWN, - HECI_POWER_UP + HECI_POWER_UP, + HECI_REMOVING }; -enum iamthif_states { - HECI_IAMTHIF_IDLE, - HECI_IAMTHIF_WRITING, - HECI_IAMTHIF_FLOW_CONTROL, - HECI_IAMTHIF_READING, - HECI_IAMTHIF_READ_COMPLETE -}; - +/* file operation states */ enum heci_file_transaction_states { - HECI_IDLE, + HECI_IDLE = 0, HECI_WRITING, HECI_WRITE_COMPLETE, HECI_FLOW_CONTROL, HECI_READING, - HECI_READ_COMPLETE + HECI_READ_COMPLETE, + HECI_CANCELED }; /* HECI CB */ @@ -211,58 +219,85 @@ HECI_CLOSE }; +/* received HECI init message types */ +enum heci_received_init_msg_types { + HECI_MSGINIT_NONE = 0, + HECI_MSGINIT_INTEROP, + HECI_MSGINIT_START, + HECI_MSGINIT_ENUM_CLIENTS, + HECI_MSGINIT_CLIENT_PROPS +}; + +/* read completion states */ +enum heci_completion_states { + HECI_WAIT_START = 0, + HECI_IN_PROGRESS, + HECI_COMPLETED +}; + /* HECI user data struct */ struct heci_message_data { __u32 size; char *data; } __attribute__((packed)); -#define HECI_CONNECT_TIMEOUT 3 /* at least 2 seconds */ -#define IAMTHIF_STALL_TIMER 12 /* seconds */ +#define HECI_CONNECT_TIMEOUT 15 /* seconds */ +#define HECI_STALL_TIMER 12 /* seconds */ #define IAMTHIF_READ_TIMER 15 /* seconds */ -struct heci_cb_private { - struct list_head cb_list; - enum heci_cb_major_types major_file_operations; - void *file_private; - struct heci_message_data request_buffer; - struct heci_message_data response_buffer; - unsigned long information; - unsigned long read_time; - struct file *file_object; -}; -/* Private file struct */ -struct heci_file_private { +/* heci connection struct */ +struct heci_connection { struct list_head link; - struct file *file; - enum file_state state; - wait_queue_head_t tx_wait; - wait_queue_head_t rx_wait; - wait_queue_head_t wait; + atomic_t state; spinlock_t file_lock; /* file lock */ - spinlock_t read_io_lock; /* read lock */ - spinlock_t write_io_lock; /* write lock */ - int read_pending; - int status; /* ID of client connected */ __u8 host_client_id; __u8 me_client_id; __u8 flow_ctrl_creds; - __u8 timer_count; + __u8 canceled; + int status; enum heci_file_transaction_states reading_state; - enum heci_file_transaction_states writing_state; - int sm_state; + enum heci_file_transaction_states wr_state; + struct file *file; struct heci_cb_private *read_cb; + __u32 stall_timer; + __u32 max_msg_length; + atomic_t refcnt; + wait_queue_head_t cc_wait; /* wait for connect or close */ }; -struct io_heci_list { - struct heci_cb_private heci_cb; +struct heci_file_priv { + struct list_head link; + struct file *file; + struct heci_connection *conn; + wait_queue_head_t tx_wait; + wait_queue_head_t rx_wait; + atomic_t sm_state; int status; - struct iamt_heci_device *device_extension; + atomic_t r_state; + atomic_t w_state; + __u8 host_client_id; }; +struct heci_cb_private { + struct list_head cb_list; + enum heci_cb_major_types major_file_operations; + struct heci_connection *conn; + struct file *file_object; + struct heci_file_priv *file_ext; + struct heci_message_data request_buffer; + struct heci_message_data response_buffer; + unsigned long information; + unsigned long read_time; + atomic_t refcnt; +}; + +struct heci_io_list { + struct list_head cb_list; +}; + struct heci_driver_version { __u8 major; __u8 minor; @@ -404,127 +439,90 @@ /* private device struct */ struct iamt_heci_device { + atomic_t refcnt; struct pci_dev *pdev; /* pointer to pci device struct */ /* - * lists of queues - */ - /* array of pointers to aio lists */ - struct io_heci_list *io_list_array[HECI_IO_LISTS_NUMBER]; - struct io_heci_list read_list; /* driver read queue */ - struct io_heci_list write_list; /* driver write queue */ - struct io_heci_list write_waiting_list; /* write waiting queue */ - struct io_heci_list ctrl_wr_list; /* managed write IOCTL list */ - struct io_heci_list ctrl_rd_list; /* managed read IOCTL list */ - struct io_heci_list pthi_cmd_list; /* PTHI list for cmd waiting */ - - /* driver managed PTHI list for reading completed pthi cmd data */ - struct io_heci_list pthi_read_complete_list; - /* - * list of files - */ - struct list_head file_list; - /* * memory of device */ unsigned int mem_base; unsigned int mem_length; char *mem_addr; /* - * lock for the device + * heci device state */ - spinlock_t device_lock; /* device lock*/ - struct work_struct work; - int recvd_msg; - - struct task_struct *reinit_tsk; - - struct timer_list wd_timer; + atomic_t heci_state; + struct hbm_version version; /* * hw states of host and fw(ME) */ __u32 host_hw_state; __u32 me_hw_state; - /* - * waiting queue for receive message from FW - */ - wait_queue_head_t wait_recvd_msg; - wait_queue_head_t wait_stop_wd; - /* - * heci device states - */ - enum heci_states heci_state; - int stop; + atomic_t host_buffer_is_empty; + spinlock_t hw_lock; /* device hw access lock */ - __u32 extra_write_index; - __u32 rd_msg_buf[128]; /* used for control messages */ - __u32 wr_msg_buf[128]; /* used for control messages */ - __u32 ext_msg_buf[8]; /* for control responses */ - __u32 rd_msg_hdr; - - struct hbm_version version; - - int host_buffer_is_empty; - struct heci_file_private wd_file_ext; - struct heci_me_client *me_clients; /* Note: memory has to be allocated*/ - __u8 heci_me_clients[32]; /* list of existing clients */ + struct heci_me_client *me_clients; /* Note:memory has to be allocated */ __u8 num_heci_me_clients; - __u8 heci_host_clients[32]; /* list of existing clients */ + __u8 heci_me_clients[32]; /* list of existing clients */ + spinlock_t mecl_lock; /* lock for me_clients */ + + long open_handle_count; __u8 current_host_client_id; + __u8 heci_host_clients[32]; /* bit list of existing clients (32*8) */ + struct list_head conn_list; /* list of heci connections */ + struct list_head file_list; /* list of connected files */ + spinlock_t conn_lock; /* lock for host_clients, conn_list, file_list */ - int wd_pending; - int wd_stoped; - __u16 wd_timeout; /* seconds ((wd_data[1] << 8) + wd_data[0]) */ - unsigned char wd_data[HECI_START_WD_DATA_SIZE]; + struct heci_io_list pthi_cmd_list; /* PTHI list for cmd waiting */ + struct heci_io_list heci_cmd_list; /* write waiting cmd list */ + spinlock_t cmdl_lock; /* lock for *_cmd_list */ + struct heci_io_list ctrl_wr_list; /* managed write IOCTL list */ + struct heci_io_list ctrl_rd_list; /* managed read IOCTL list */ + struct heci_io_list read_list; /* driver read queue */ + spinlock_t crrdl_lock; /* lock for ctrl_*_list and read_list */ + + struct heci_io_list read_cmpl_list; /* read completed list */ + spinlock_t rdcpl_lock; /* lock for read_cmpl_list */ + + struct heci_io_list write_list; /* driver write queue */ + struct heci_io_list cmpl_list; /* nonread completed list */ + + __u8 need_reset; + __u8 asf_mode; + spinlock_t device_lock; /* device lock */ + + struct heci_connection wd_conn; + struct timer_list wd_timer; + wait_queue_head_t wait_stop_wd; + atomic_t wd_stoped; + atomic_t wd_bypass; /* if 1, don't refresh watchdog ME client */ + __u8 wd_pending; + __u8 wd_stop; + __u16 wd_timeout; /* seconds ((wd_data[1] << 8) + wd_data[0]) */ __u16 wd_due_counter; - int asf_mode; - int wd_bypass; /* if 1, don't refresh watchdog ME client */ + unsigned char wd_data[HECI_START_WD_DATA_SIZE]; - struct file *iamthif_file_object; - struct heci_file_private iamthif_file_ext; - int iamthif_ioctl; - int iamthif_canceled; - __u32 iamthif_timer; - __u32 iamthif_stall_timer; - unsigned char iamthif_msg_buf[IAMTHIF_MTU]; - __u32 iamthif_msg_buf_size; - __u32 iamthif_msg_buf_index; - int iamthif_flow_control_pending; - enum iamthif_states iamthif_state; + struct heci_connection iamthif_conn; - struct heci_cb_private *iamthif_current_cb; - __u8 write_hang; - int need_reset; - long open_handle_count; -}; + struct task_struct *isr_thread; /* isr processing thread */ + wait_queue_head_t wait_isr; /* wait queue for isr */ + atomic_t recvd_isr; /* isr process request counter */ + atomic_t recvd_wrr; /* write request counter */ -/** - * read_heci_register - Read a byte from the heci device - * - * @dev: the device structure - * @offset: offset from which to read the data - * - * returns the byte read. - */ -static inline __u32 read_heci_register(struct iamt_heci_device *dev, - unsigned long offset) -{ - return readl(dev->mem_addr + offset); -} + struct task_struct *reinit_tsk; /* device reinitialization task */ + struct semaphore reinit_sem; /* reinit task semaphore */ + wait_queue_head_t wait_recvd_msg; /* wait queue for messages from FW */ + atomic_t recvd_msg; -/** - * write_heci_register - Write 4 bytes to the heci device - * - * @dev: the device structure - * @offset: offset from which to write the data - * @value: the byte to write - */ -static inline void write_heci_register(struct iamt_heci_device *dev, - unsigned long offset, __u32 value) -{ - writel(value, dev->mem_addr + offset); -} + spinlock_t write_lock; /* device msg write lock */ + __u32 rd_msg_hdr; /* read message header */ + __u32 extra_write_index; /* size of extra control messages */ + __u32 wr_msg_buf[128]; /* msg write buffer used for control messages */ + __u32 rd_msg_buf[128]; /* read buffer used for control messages */ + __u32 ext_msg_buf[8]; /* write buffer for extra control messages */ +}; + #endif /* _HECI_DATA_STRUCTURES_H_ */ Modified: heci/branches/testing/src/heci_init.c =================================================================== --- heci/branches/testing/src/heci_init.c 2008-07-22 17:13:05 UTC (rev 206) +++ heci/branches/testing/src/heci_init.c 2008-07-22 17:20:27 UTC (rev 207) @@ -38,20 +38,6 @@ * */ -#include <linux/module.h> -#include <linux/pci.h> -#include <linux/reboot.h> -#include <linux/poll.h> -#include <linux/init.h> -#include <linux/kdev_t.h> -#include <linux/moduleparam.h> -#include <linux/wait.h> -#include <linux/delay.h> -#include <linux/kthread.h> -#include "kcompat.h" - -#include "heci_data_structures.h" -#include "heci_interface.h" #include "heci.h" @@ -87,7 +73,7 @@ static int allocate_me_clients_storage(struct iamt_heci_device *dev); static void host_init_wd(struct iamt_heci_device *dev); static void host_init_iamthif(struct iamt_heci_device *dev); -static int heci_wait_event_int_timeout(struct iamt_heci_device *dev, +static int heci_wait_msg_timeout(struct iamt_heci_device *dev, long timeout); @@ -97,91 +83,162 @@ * @list: An instance of our list structure * @dev: Device object for our driver */ -void heci_initialize_list(struct io_heci_list *list, +void heci_initialize_list(struct heci_io_list *list, struct iamt_heci_device *dev) { /* initialize our queue list */ - INIT_LIST_HEAD(&list->heci_cb.cb_list); - list->status = 0; - list->device_extension = dev; + INIT_LIST_HEAD(&list->cb_list); } /** - * heci_flush_queues - flush our queues list belong to file_ext. + * heci_flush_list - remove list entry belong to heci connection. * - * @dev: Device object for our driver - * @file_ext: private data of the file object + * @list: An instance of our list structure + * @conn: connection data of the file object + * @priv_cb: callback block + * + * returns 1 if flushed, 0 if not */ -void heci_flush_queues(struct iamt_heci_device *dev, - struct heci_file_private *file_ext) +int heci_flush_list(struct heci_io_list *list, + struct heci_connection *conn, + struct heci_cb_private *priv_cb) { - int i; + struct heci_cb_private *priv_cb_pos = NULL; + struct heci_cb_private *priv_cb_next = NULL; + int ret = 0; - if (!dev || !file_ext) - return; + if ((list == NULL) || (conn == NULL)) + return 0; - /* flush our queue list belong to file_ext */ - for (i = 0; i < HECI_IO_LISTS_NUMBER; i++) { - DBG("remove list entry belong to file_ext\n"); - heci_flush_list(dev->io_list_array[i], file_ext); + if (list_empty(&list->cb_list)) + return 0; + + list_for_each_entry_safe(priv_cb_pos, priv_cb_next, + &list->cb_list, cb_list) { + if (priv_cb_pos->conn == conn) { + if ((priv_cb == NULL) || (priv_cb_pos == priv_cb)) { + list_del_init(&priv_cb_pos->cb_list); + ret = 1; + } + } } + return ret; } +/** + * heci_reset_file_priv - resets private file structure. + * + * @file_ext: private data of the file object to be reset + * @file: the file structure + */ +static void heci_reset_file_priv(struct heci_file_priv *file_ext, + struct file *file) +{ + INIT_LIST_HEAD(&file_ext->link); + init_waitqueue_head(&file_ext->rx_wait); + init_waitqueue_head(&file_ext->tx_wait); + DBG("file_ext->rx_wait =%p\n", &file_ext->rx_wait); + atomic_set(&file_ext->sm_state, 0); + file_ext->file = file; + atomic_set(&file_ext->r_state, HECI_IDLE); + atomic_set(&file_ext->w_state, HECI_IDLE); +} /** - * heci_flush_list - remove list entry belong to file_ext. + * heci_reset_heci_connection - resets connection structure. * - * @list: An instance of our list structure - * @file_ext: private data of the file object + * @conn: connection data of the file object to be reset + * @file: the file structure */ -void heci_flush_list(struct io_heci_list *list, - struct heci_file_private *file_ext) +static void heci_reset_heci_connection(struct heci_connection *conn, + struct file *file) { - struct heci_file_private *file_ext_tmp; - struct heci_cb_private *priv_cb_pos = NULL; - struct heci_cb_private *priv_cb_next = NULL; + INIT_LIST_HEAD(&conn->link); + init_waitqueue_head(&conn->cc_wait); + atomic_set(&conn->state, HECI_FILE_INITIALIZING); + atomic_set(&conn->refcnt, 0); + conn->reading_state = HECI_IDLE; + conn->wr_state = HECI_IDLE; + conn->file = file; +} - if (!list || !file_ext) - return; +/** + * heci_init_file_priv - initializes private file structure. + * + * @file_ext: private data of the file object to be initialized + * @file: the file structure + */ +static void heci_init_file_priv(struct heci_file_priv *file_ext, + struct file *file) +{ + memset(file_ext, 0, sizeof(struct heci_file_priv)); + heci_reset_file_priv(file_ext, file); +} - if (list->status != 0) - return; +/** + * heci_init_heci_connection - initializes connection structure. + * + * @conn: connection data of the file object to be initialized + * @file: the file structure + */ +static void heci_init_heci_connection(struct heci_connection *conn, + struct file *file) +{ + memset(conn, 0, sizeof(struct heci_connection)); + spin_lock_init(&conn->file_lock); + heci_reset_heci_connection(conn, file); +} - if (list_empty(&list->heci_cb.cb_list)) - return; +/** + * heci_alloc_file_priv - allocates a private file structure and set it up. + * @file: the file structure + * + * returns The allocated file connection data or NULL on failure + */ +struct heci_file_priv *heci_alloc_file_priv(struct file *file) +{ + struct heci_file_priv *file_ext; - list_for_each_entry_safe(priv_cb_pos, priv_cb_next, - &list->heci_cb.cb_list, cb_list) { - if (priv_cb_pos) { - file_ext_tmp = (struct heci_file_private *) - priv_cb_pos->file_private; - if (file_ext_tmp) { - if (heci_fe_same_id(file_ext, file_ext_tmp)) - list_del(&priv_cb_pos->cb_list); - } - } - } + file_ext = kmalloc(sizeof(struct heci_file_priv), GFP_KERNEL); + if (file_ext == NULL) + return NULL; + + heci_init_file_priv(file_ext, file); + + return file_ext; } /** - * heci_reset_iamthif_params - initializes heci device iamthif + * heci_alloc_heci_connection - allocates connection structure and set it up. + * @file: the file structure * - * @dev: The heci device structure + * returns The allocated file connection data or NULL on failure */ -static void heci_reset_iamthif_params(struct iamt_heci_device *dev) +struct heci_connection *heci_alloc_heci_connection(struct file *file) { - /* reset iamthif parameters. */ - dev->iamthif_current_cb = NULL; - dev->iamthif_msg_buf_size = 0; - dev->iamthif_msg_buf_index = 0; - dev->iamthif_canceled = 0; - dev->iamthif_file_ext.file = NULL; - dev->iamthif_ioctl = 0; - dev->iamthif_state = HECI_IAMTHIF_IDLE; - dev->iamthif_timer = 0; + struct heci_connection *conn; + + conn = kmalloc(sizeof(struct heci_connection), GFP_KERNEL); + if (conn == NULL) + return NULL; + + heci_init_heci_connection(conn, file); + + return conn; } /** + * heci_put_heci_connection - free connection structure. + * + * @conn: connection data of the file object + */ +void heci_put_heci_connection(struct heci_connection *conn) +{ + if (atomic_dec_and_test(&conn->refcnt)) + kfree(conn); +} + +/** * init_heci_device - allocates and initializes the heci device structure * * @pdev: The pci device structure @@ -190,46 +247,86 @@ */ struct iamt_heci_device *init_heci_device(struct pci_dev *pdev) { - int i; struct iamt_heci_device *dev; dev = kzalloc(sizeof(struct iamt_heci_device), GFP_KERNEL); - if (!dev) + if (dev == NULL) return NULL; - /* setup our list array */ - dev->io_list_array[0] = &dev->read_list; - dev->io_list_array[1] = &dev->write_list; - dev->io_list_array[2] = &dev->write_waiting_list; - dev->io_list_array[3] = &dev->ctrl_wr_list; - dev->io_list_array[4] = &dev->ctrl_rd_list; - dev->io_list_array[5] = &dev->pthi_cmd_list; - dev->io_list_array[6] = &dev->pthi_read_complete_list; - INIT_LIST_HEAD(&dev->file_list); - INIT_LIST_HEAD(&dev->wd_file_ext.link); - INIT_LIST_HEAD(&dev->iamthif_file_ext.link); spin_lock_init(&dev->device_lock); + spin_lock_init(&dev->crrdl_lock); + spin_lock_init(&dev->rdcpl_lock); + spin_lock_init(&dev->cmdl_lock); + spin_lock_init(&dev->mecl_lock); + spin_lock_init(&dev->conn_lock); + spin_lock_init(&dev->hw_lock); + spin_lock_init(&dev->write_lock); init_waitqueue_head(&dev->wait_recvd_msg); init_waitqueue_head(&dev->wait_stop_wd); - dev->heci_state = HECI_INITIALIZING; - dev->iamthif_state = HECI_IAMTHIF_IDLE; + init_waitqueue_head(&dev->wait_isr); + atomic_set(&dev->recvd_isr, 0); + atomic_set(&dev->recvd_msg, 0); + atomic_set(&dev->recvd_wrr, 0); + init_MUTEX(&dev->reinit_sem); + atomic_set(&dev->heci_state, HECI_INITIALIZING); + atomic_set(&dev->host_buffer_is_empty, 1); - /* init work for schedule work */ - INIT_WORK(&dev->work, NULL); - for (i = 0; i < HECI_IO_LISTS_NUMBER; i++) - heci_initialize_list(dev->io_list_array[i], dev); + INIT_LIST_HEAD(&dev->conn_list); + INIT_LIST_HEAD(&dev->file_list); + + heci_initialize_list(&dev->read_list, dev); + heci_initialize_list(&dev->read_cmpl_list, dev); + heci_initialize_list(&dev->ctrl_rd_list, dev); + heci_initialize_list(&dev->ctrl_wr_list, dev); + heci_initialize_list(&dev->write_list, dev); + heci_initialize_list(&dev->cmpl_list, dev); + heci_initialize_list(&dev->pthi_cmd_list, dev); + heci_initialize_list(&dev->heci_cmd_list, dev); + + atomic_set(&dev->wd_stoped, 0); + atomic_set(&dev->wd_bypass, 0); + heci_init_heci_connection(&dev->wd_conn, NULL); + atomic_inc(&dev->wd_conn.refcnt); + heci_init_heci_connection(&dev->iamthif_conn, NULL); + atomic_inc(&dev->iamthif_conn.refcnt); + + atomic_set(&dev->refcnt, 1); + dev->pdev = pdev; return dev; } +/** + * put_heci_device - free unreferenced heci device structure + * + * @dev: Device object for our driver + */ +void put_heci_device(struct iamt_heci_device *dev) +{ + if (dev == NULL) + return; + if (!atomic_dec_and_test(&dev->refcnt)) + return; + if (dev->mem_addr != NULL) + iounmap(dev->mem_addr); + kfree(dev); +} -static int heci_wait_event_int_timeout(struct iamt_heci_device *dev, - long timeout) +/** + * heci_wait_msg_timeout - wait for heci response + * + * @dev: Device object for our driver + * @timeout: maximum wait timeout + * + * returns 0 if timeout, >0 if received, <0 on error + */ +static int heci_wait_msg_timeout(struct iamt_heci_device *dev, long timeout) { return wait_event_interruptible_timeout(dev->wait_recvd_msg, - (dev->recvd_msg), timeout); + (atomic_read(&dev->recvd_msg) != HECI_MSGINIT_NONE), + timeout); } /** @@ -243,64 +340,88 @@ { int err = 0; + spin_lock_bh(&dev->device_lock); + spin_lock(&dev->hw_lock); dev->host_hw_state = read_heci_register(dev, H_CSR); dev->me_hw_state = read_heci_register(dev, ME_CSR_HA); DBG("host_hw_state = 0x%08x, mestate = 0x%08x.\n", dev->host_hw_state, dev->me_hw_state); if ((dev->host_hw_state & H_IS) == H_IS) { - /* acknowledge interrupt and stop interupts */ + /* acknowledge interrupt */ heci_set_csr_register(dev); } - dev->recvd_msg = 0; + spin_unlock(&dev->hw_lock); + + atomic_set(&dev->recvd_msg, HECI_MSGINIT_NONE); + DBG("reset in start the heci device.\n"); - heci_reset(dev, 1); DBG("host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n", dev->host_hw_state, dev->me_hw_state); + spin_unlock_bh(&dev->device_lock); /* wait for ME to turn on ME_RDY */ - if (!dev->recvd_msg) - err = heci_wait_event_int_timeout(dev, HECI_INTEROP_TIMEOUT); + if (atomic_read(&dev->recvd_msg) != HECI_MSGINIT_INTEROP) + err = heci_wait_msg_timeout(dev, HECI_INTEROP_TIMEOUT); - if (!err && !dev->recvd_msg) { - dev->heci_state = HECI_DISABLED; + if (err == -ERESTARTSYS) { + atomic_set(&dev->heci_state, HECI_DISABLED); + atomic_set(&dev->recvd_msg, HECI_MSGINIT_NONE); + DBG("wait_event_interruptible_timeout interrupted" + " on wait for ME to turn on ME_RDY.\n"); + return -EINTR; + } + if ((err == 0) + || (atomic_read(&dev->recvd_msg) != HECI_MSGINIT_INTEROP)) { + if (err == 0) + atomic_set(&dev->heci_state, HECI_DISABLED); + atomic_set(&dev->recvd_msg, HECI_MSGINIT_NONE); DBG("wait_event_interruptible_timeout failed" - "on wait for ME to turn on ME_RDY.\n"); + " on wait for ME to turn on ME_RDY.\n"); return -ENODEV; - } else { - if (!(((dev->host_hw_state & H_RDY) == H_RDY) - && ((dev->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA))) { - dev->heci_state = HECI_DISABLED; - DBG("host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n", - dev->host_hw_state, - dev->me_hw_state); + } + atomic_set(&dev->recvd_msg, HECI_MSGINIT_NONE); - if (!(dev->host_hw_state & H_RDY) != H_RDY) - DBG("host turn off H_RDY.\n"); + spin_lock_bh(&dev->hw_lock); + dev->host_hw_state = read_heci_register(dev, H_CSR); + dev->me_hw_state = read_heci_register(dev, ME_CSR_HA); + if (((dev->host_hw_state & H_RDY) != H_RDY) + || ((dev->me_hw_state & ME_RDY_HRA) != ME_RDY_HRA)) { + atomic_set(&dev->heci_state, HECI_DISABLED); + DBG("host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n", + dev->host_hw_state, + dev->me_hw_state); - if (!(dev->me_hw_state & ME_RDY_HRA) != ME_RDY_HRA) - DBG("ME turn off ME_RDY.\n"); + if ((dev->host_hw_state & H_RDY) != H_RDY) + DBG("host turn off H_RDY.\n"); - printk(KERN_ERR - "heci: link layer initialization failed.\n"); - return -ENODEV; - } + if ((dev->me_hw_state & ME_RDY_HRA) != ME_RDY_HRA) + DBG("ME turn off ME_RDY.\n"); + + spin_unlock_bh(&dev->hw_lock); + printk(KERN_ERR + "heci: link layer initialization failed.\n"); + return -ENODEV; } - dev->recvd_msg = 0; + DBG("host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n", dev->host_hw_state, dev->me_hw_state); + spin_unlock_bh(&dev->hw_lock); + DBG("ME turn on ME_RDY and host turn on H_RDY.\n"); printk(KERN_INFO "heci: link layer has been established.\n"); return 0; } /** - * heci_hw_reset - reset fw via heci csr register. + * heci_hw_reset - reset fw via heci csr register. * * @dev: Device object for our driver * @interrupts: if interrupt should be enable after reset. + * + * NOTE: called under hw_lock */ static void heci_hw_reset(struct iamt_heci_device *dev, int interrupts) { @@ -316,37 +437,99 @@ } /** - * heci_reset - reset host and fw. + * heci_reset_io_list - clear list and free entries. * + * @list: An instance of our list structure + */ +static void heci_reset_io_list(struct heci_io_list *list) +{ + struct heci_cb_private *priv_cb_pos = NULL; + struct heci_cb_private *priv_cb_next = NULL; + + if (list_empty(&list->cb_list)) + return; + + list_for_each_entry_safe(priv_cb_pos, priv_cb_next, + &list->cb_list, cb_list) { + list_del_init(&priv_cb_pos->cb_list); + heci_free_io_cb(priv_cb_pos); + } +} + +/** + * heci_reset_io - resets IO operations. + * * @dev: Device object for our driver + * + * NOTE: called under device_lock + */ +static void heci_reset_io(struct iamt_heci_device *dev) +{ + struct heci_connection *conn_pos = NULL; + struct heci_connection *conn_next = NULL; + + spin_lock(&dev->conn_lock); + list_for_each_entry_safe(conn_pos, conn_next, &dev->conn_list, link) { + spin_lock(&conn_pos->file_lock); + atomic_set(&conn_pos->state, HECI_FILE_DISCONNECTED); + conn_pos->flow_ctrl_creds = 0; + conn_pos->canceled = 1; + conn_pos->read_cb = NULL; + conn_pos->reading_state = HECI_IDLE; + conn_pos->wr_state = HECI_IDLE; + if (conn_pos == &dev->iamthif_conn) + conn_pos->file = NULL; + spin_unlock(&conn_pos->file_lock); + } + /* remove entry if already in list */ + DBG("list del iamthif and wd conn list.\n"); + list_del_init(&dev->wd_conn.link); + list_del_init(&dev->iamthif_conn.link); + spin_unlock(&dev->conn_lock); + + /* remove all waiting requests */ + heci_reset_io_list(&dev->write_list); + spin_lock(&dev->crrdl_lock); + heci_reset_io_list(&dev->read_list); + spin_unlock(&dev->crrdl_lock); +} + +/** + * heci_reset - reset host and fw. + * + * @dev: Device object for our driver * @interrupts: if interrupt should be enable after reset. + * + * NOTE: called under device_lock */ void heci_reset(struct iamt_heci_device *dev, int interrupts) { - struct heci_file_private *file_pos = NULL; - struct heci_file_private *file_next = NULL; - struct heci_cb_private *priv_cb_pos = NULL; - struct heci_cb_private *priv_cb_next = NULL; + struct heci_file_priv *file_pos = NULL; + struct heci_file_priv *file_next = NULL; int unexpected = 0; + enum heci_states heci_state; - if (dev->heci_state == HECI_RECOVERING_FROM_RESET) { + heci_state = atomic_read(&dev->heci_state); + if (heci_state == HECI_RECOVERING_FROM_RESET) { dev->need_reset = 1; return; } + if ((heci_state != HECI_INITIALIZING) && + (heci_state != HECI_DISABLED) && + (heci_state != HECI_POWER_DOWN) && + (heci_state != HECI_REMOVING)) { + if (heci_state != HECI_POWER_UP) + unexpected = 1; + atomic_set(&dev->heci_state, HECI_RESETING); + } - if (dev->heci_state != HECI_INITIALIZING && - dev->heci_state != HECI_DISABLED && - dev->heci_state != HECI_POWER_DOWN && - dev->heci_state != HECI_POWER_UP) - unexpected = 1; - if (dev->reinit_tsk != NULL) { - kthread_stop(dev->reinit_tsk); - dev->reinit_tsk = NULL; + set_tsk_thread_flag(dev->reinit_tsk, TIF_SIGPENDING); + wake_up_process(dev->reinit_tsk); } + spin_lock(&dev->hw_lock); dev->host_hw_state = read_heci_register(dev, H_CSR); - DBG("before reset host_hw_state = 0x%08x.\n", dev->host_hw_state); @@ -354,166 +537,148 @@ dev->host_hw_state &= ~H_RST; dev->host_hw_state |= H_IG; - write_heci_register(dev, H_CSR, dev->host_hw_state); - DBG("currently saved host_hw_state = 0x%08x.\n", dev->host_hw_state); + spin_unlock(&dev->hw_lock); dev->need_reset = 0; - if (dev->heci_state != HECI_INITIALIZING) { - if ((dev->heci_state != HECI_DISABLED) && - (dev->heci_state != HECI_POWER_DOWN)) - dev->heci_state = HECI_RESETING; + if (atomic_read(&dev->heci_state) != HECI_INITIALIZING) + heci_reset_io(dev); - list_for_each_entry_safe(file_pos, - file_next, &dev->file_list, link) { - file_pos->state = HECI_FILE_DISCONNECTED; - file_pos->flow_ctrl_creds = 0; - file_pos->read_cb = NULL; - file_pos->timer_count = 0; - } - /* remove entry if already in list */ - DBG("list del iamthif and wd file list.\n"); - heci_remove_client_from_file_list(dev, - dev->wd_file_ext.host_client_id); + spin_lock(&dev->mecl_lock); + dev->num_heci_me_clients = 0; + spin_unlock(&dev->mecl_lock); - heci_remove_client_from_file_list(dev, - dev->iamthif_file_ext.host_client_id); - - heci_reset_iamthif_params(dev); - dev->wd_due_counter = 0; - dev->extra_write_index = 0; - } - - dev->num_heci_me_clients = 0; dev->rd_msg_hdr = 0; - dev->stop = 0; + dev->wd_stop = 0; dev->wd_pending = 0; + dev->wd_due_counter = 0; + dev->extra_write_index = 0; + spin_lock(&dev->hw_lock); /* update the state of the registers after reset */ - dev->host_hw_state = read_heci_register(dev, H_CSR); - dev->me_hw_state = read_heci_register(dev, ME_CSR_HA); - + dev->host_hw_state = read_heci_register(dev, H_CSR); + dev->me_hw_state = read_heci_register(dev, ME_CSR_HA); DBG("after reset host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n", dev->host_hw_state, dev->me_hw_state); + spin_unlock(&dev->hw_lock); if (unexpected) printk(KERN_WARNING "heci: unexpected reset.\n"); - /* Wake up all readings so they can be interrupted */ + spin_lock(&dev->conn_lock); + /* Wake up all readings and writings so they can be interrupted */ list_for_each_entry_safe(file_pos, file_next, &dev->file_list, link) { - if (&file_pos->rx_wait && - waitqueue_active(&file_pos->rx_wait)) { - printk(KERN_INFO "heci: Waking up client!\n"); + if (waitqueue_active(&file_pos->rx_wait)) { + printk(KERN_INFO "heci: waking up client\n"); wake_up_interruptible(&file_pos->rx_wait); } - } - /* remove all waiting requests */ - if (dev->write_list.status == 0 && - !list_empty(&dev->write_list.heci_cb.cb_list)) { - list_for_each_entry_safe(priv_cb_pos, priv_cb_next, - &dev->write_list.heci_cb.cb_list, cb_list) { - if (priv_cb_pos) { - list_del(&priv_cb_pos->cb_list); - heci_free_cb_private(priv_cb_pos); - } + if (waitqueue_active(&file_pos->tx_wait)) { + printk(KERN_INFO "heci: waking up writing client\n"); + wake_up_interruptible(&file_pos->tx_wait); } } + spin_unlock(&dev->conn_lock); } /** - * heci_initialize_clients - heci communication initialization. + * heci_initialize_clients - initializes heci communication. * * @dev: Device object for our driver + * + * returns 0 on success, !=0 on failure */ int heci_initialize_clients(struct iamt_heci_device *dev) { - int status; + int ret; msleep(100); /* FW needs time to be ready to talk with us */ DBG("link is established start sending messages.\n"); /* link is established start sending messages. */ - status = host_start_message(dev); - if (status != 0) { - spin_lock_bh(&dev->device_lock); - dev->heci_state = HECI_DISABLED; - spin_unlock_bh(&dev->device_lock); + ret = host_start_message(dev); + if (ret != 0) { DBG("start sending messages failed.\n"); - return status; + return ret; } + /* enumerate clients */ - /* enumerate clients */ - status = host_enum_clients_message(dev); - if (status != 0) { - spin_lock_bh(&dev->device_lock); - dev->heci_state = HECI_DISABLED; - spin_unlock_bh(&dev->device_lock); + ret = host_enum_clients_message(dev); + if (ret != 0) { DBG("enum clients failed.\n"); - return status; + return ret; } /* allocate storage for ME clients representation */ - status = allocate_me_clients_storage(dev); - if (status != 0) { - spin_lock_bh(&dev->device_lock); - dev->num_heci_me_clients = 0; - dev->heci_state = HECI_DISABLED; - spin_unlock_bh(&dev->device_lock); + ret = allocate_me_clients_storage(dev); + if (ret != 0) { DBG("allocate clients failed.\n"); - return status; + return ret; } heci_check_asf_mode(dev); - /*heci initialization wd */ + /* heci initialization wd */ host_init_wd(dev); - /*heci initialization iamthif client */ + /* heci initialization iamthif client */ host_init_iamthif(dev); spin_lock_bh(&dev->device_lock); - if (dev->need_reset) { + if (dev->need_reset == 1) { dev->need_reset = 0; - dev->heci_state = HECI_DISABLED; + atomic_set(&dev->heci_state, HECI_DISABLED); spin_unlock_bh(&dev->device_lock); return -ENODEV; } + spin_lock(&dev->conn_lock); memset(dev->heci_host_clients, 0, sizeof(dev->heci_host_clients)); dev->open_handle_count = 0; dev->heci_host_clients[0] |= 7; - dev->current_host_client_id = 3; - dev->heci_state = HECI_ENABLED; + dev->current_host_client_id = HECI_LAST_FIX_HOST_CLIENT_ID; + spin_unlock(&dev->conn_lock); + + atomic_set(&dev->heci_state, HECI_ENABLED); spin_unlock_bh(&dev->device_lock); DBG("initialization heci clients successful.\n"); return 0; } + +#ifndef HECI_TASK_NONFREEZABLE +#define HECI_TASK_NONFREEZABLE +#endif + /** - * heci_task_initialize_clients - heci reinitialization task + * heci_task_initialize_clients - heci reinitialization task. * * @data: Device object for our driver + * + * returns 0 on success, !=0 on failure */ int heci_task_initialize_clients(void *data) { int ret; struct iamt_heci_device *dev = (struct iamt_heci_device *) data; - spin_lock_bh(&dev->device_lock); - if (dev->reinit_tsk != NULL) { - spin_unlock_bh(&dev->device_lock); + if (down_trylock(&dev->reinit_sem)) { DBG("reinit task already started.\n"); return 0; } + + spin_lock_bh(&dev->device_lock); dev->reinit_tsk = current; - current->flags |= PF_NOFREEZE; spin_unlock_bh(&dev->device_lock); + HECI_TASK_NONFREEZABLE; + ret = heci_initialize_clients(dev); spin_lock_bh(&dev->device_lock); dev->reinit_tsk = NULL; spin_unlock_bh(&dev->device_lock); + up(&dev->reinit_sem); + return ret; } @@ -533,6 +698,7 @@ struct hbm_host_stop_request *host_stop_req; int err = 0; + spin_lock_bh(&dev->write_lock); /* host start message */ heci_hdr = (struct heci_msg_hdr *) &dev->wr_msg_buf[0]; heci_hdr->host_addr = 0; @@ -547,22 +713,41 @@ host_start_req->cmd.cmd = HOST_START_REQ_CMD; host_start_req->host_version.major_version = HBM_MAJOR_VERSION; host_start_req->host_version.minor_version = HBM_MINOR_VERSION; - dev->recvd_msg = 0; + + atomic_set(&dev->recvd_msg, HECI_MSGINIT_NONE); if (!heci_write_message(dev, heci_hdr, - (unsigned char *) (host_start_req), - heci_hdr->length)) { + (unsigned char *) (host_start_req), + heci_hdr->length)) { + atomic_set(&dev->heci_state, HECI_DISABLED); + spin_unlock_bh(&dev->write_lock); DBG("send version to fw fail.\n"); return -ENODEV; } + spin_unlock_bh(&dev->write_lock); + DBG("call wait_event_interruptible_timeout for response message.\n"); /* wait for response */ - err = heci_wait_event_int_timeout(dev, timeout * HZ); - if (!err && !dev->recvd_msg) { - DBG("wait_timeout failed on host start response message.\n"); + err = heci_wait_msg_timeout(dev, timeout * HZ); + if (err == -ERESTARTSYS) { + atomic_set(&dev->heci_state, HECI_DISABLED); + atomic_set(&dev->recvd_msg, HECI_MSGINIT_NONE); + DBG("wait_event_interruptible_timeout interrupted" + " on host start response message.\n"); + return -EINTR; + } + if ((err == 0) + || (atomic_read(&dev->recvd_msg) != HECI_MSGINIT_START)) { + if (err == 0) + atomic_set(&dev->heci_state, HECI_DISABLED); + atomic_set(&dev->recvd_msg, HECI_MSGINIT_NONE); + DBG("wait_event_interruptible_timeout failed" + " on host start response message.\n"); return -ENODEV; } - dev->recvd_msg = 0; + atomic_set(&dev->recvd_msg, HECI_MSGINIT_NONE); DBG("wait_timeout successful on host start response message.\n"); + + spin_lock_bh(&dev->write_lock); if ((dev->version.major_version != HBM_MAJOR_VERSION) || (dev->version.minor_version != HBM_MINOR_VERSION)) { /* send stop message */ @@ -581,9 +766,12 @@ heci_write_message(dev, heci_hdr, (unsigned char *) (host_stop_req), heci_hdr->length); + atomic_set(&dev->heci_state, HECI_DISABLED); + spin_unlock_bh(&dev->write_lock); DBG("version mismatch.\n"); return -ENODEV; } + spin_unlock_bh(&dev->write_lock); return 0; } @@ -597,12 +785,13 @@ */ static int host_enum_clients_message(struct iamt_heci_device *dev) { - long timeout = 5; /*5 second */ + long timeout = 5; /* 5 second */ struct heci_msg_hdr *heci_hdr; struct hbm_host_enum_request *host_enum_req; int err = 0; __u8 i, j; + spin_lock_bh(&dev->write_lock); heci_hdr = (struct heci_msg_hdr *) &dev->wr_msg_buf[0]; /* enumerate clients */ heci_hdr->host_addr = 0; @@ -614,23 +803,39 @@ host_enum_req = (struct hbm_host_enum_request *) &dev->wr_msg_buf[1]; memset(host_enum_req, 0, sizeof(struct hbm_host_enum_request)); host_enum_req->cmd.cmd = HOST_ENUM_REQ_CMD; + + atomic_set(&dev->recvd_msg, HECI_MSGINIT_NONE); if (!heci_write_message(dev, heci_hdr, - (unsigned char *) (host_enum_req), - heci_hdr->length)) { + (unsigned char *) (host_enum_req), + heci_hdr->length)) { + atomic_set(&dev->heci_state, HECI_DISABLED); + spin_unlock_bh(&dev->write_lock); DBG("send enumeration request failed.\n"); return -ENODEV; } + spin_unlock_bh(&dev->write_lock); + /* wait for response */ - dev->recvd_msg = 0; - err = heci_wait_event_int_timeout(dev, timeout * HZ); - if (!err && !dev->recvd_msg) { - DBG("wait_event_interruptible_timeout failed " - "on enumeration clients response message.\n"); + err = heci_wait_msg_timeout(dev, timeout * HZ); + if (err == -ERESTARTSYS) { + atomic_set(&dev->heci_state, HECI_DISABLED); + atomic_set(&dev->recvd_msg, HECI_MSGINIT_NONE); + DBG("wait_event_interruptible_timeout interrupted" + " on enumeration clients response message.\n"); + return -EINTR; + } + if ((err == 0) + || (atomic_read(&dev->recvd_msg) != HECI_MSGINIT_ENUM_CLIENTS)) { + if (err == 0) + atomic_set(&dev->heci_state, HECI_DISABLED); + atomic_set(&dev->recvd_msg, HECI_MSGINIT_NONE); + DBG("wait_event_interruptible_timeout failed" + " on enumeration clients response message.\n"); return -ENODEV; } - dev->recvd_msg = 0; + atomic_set(&dev->recvd_msg, HECI_MSGINIT_NONE); - spin_lock_bh(&dev->device_lock); + spin_lock_bh(&dev->mecl_lock); /* count how many ME clients we have */ for (i = 0; i < sizeof(dev->heci_me_clients); i++) { for (j = 0; j < 8; j++) { @@ -639,7 +844,7 @@ } } - spin_unlock_bh(&dev->device_lock); + spin_unlock_bh(&dev->mecl_lock); return 0; } @@ -656,10 +861,12 @@ static int host_client_properties(struct iamt_heci_device *dev, struct heci_me_client *client) { + long timeout = 10; /* 10 second */ struct heci_msg_hdr *heci_hdr; struct hbm_props_request *host_cli_req; int err; + spin_lock_bh(&dev->write_lock); heci_hdr = (struct heci_msg_hdr *) &dev->wr_msg_buf[0]; heci_hdr->host_addr = 0; heci_hdr->me_addr = 0; @@ -671,20 +878,38 @@ memset(host_cli_req, 0, sizeof(struct hbm_props_request)); host_cli_req->cmd.cmd = HOST_CLIENT_PROPERTEIS_REQ_CMD; host_cli_req->address = client->client_id; + + atomic_set(&dev->recvd_msg, HECI_MSGINIT_NONE); if (!heci_write_message(dev, heci_hdr, (unsigned char *) (host_cli_req), heci_hdr->length)) { + atomic_set(&dev->heci_state, HECI_DISABLED); + spin_unlock_bh(&dev->write_lock); DBG("send props request failed.\n"); return -ENODEV; } + spin_unlock_bh(&dev->write_lock); + /* wait for response */ - dev->recvd_msg = 0; - err = heci_wait_event_int_timeout(dev, 10 * HZ); - if (!err && !dev->recvd_msg) { - DBG("wait failed on props resp msg.\n"); + err = heci_wait_msg_timeout(dev, timeout * HZ); + if (err == -ERESTARTSYS) { + atomic_set(&dev->heci_state, HECI_DISABLED); + atomic_set(&dev->recvd_msg, HECI_MSGINIT_NONE); + DBG("wait_event_interruptible_timeout interrupted" + " on props resp msg.\n"); + return -EINTR; + } + if ((err == 0) + || (atomic_read(&dev->recvd_msg) != HECI_MSGINIT_CLIENT_PROPS)) { + if (err == 0) + atomic_set(&dev->heci_state, HECI_DISABLED); + atomic_set(&dev->recvd_msg, HECI_MSGINIT_NONE); + DBG("wait_event_interruptible_timeout failed" + " on props resp msg.\n"); return -ENODEV; } - dev->recvd_msg = 0; + atomic_set(&dev->recvd_msg, HECI_MSGINIT_NONE); + return 0; } @@ -702,26 +927,32 @@ __u8 num, i, j; int err; - if (dev->num_heci_me_clients <= 0) + spin_lock_bh(&dev->mecl_lock); + if (dev->num_heci_me_clients <= 0) { + kfree(dev->me_clients); + dev->me_clients = NULL; + dev->num_heci_me_clients = 0; + atomic_set(&dev->heci_state, HECI_DISABLED); + spin_unlock_bh(&dev->mecl_lock); return 0; + } + spin_unlock_bh(&dev->mecl_lock); - spin_lock_bh(&dev->device_lock); - kfree(dev->me_clients); - dev->me_clients = NULL; - spin_unlock_bh(&dev->device_lock); - /* allocate storage for ME clients representation */ clients = kcalloc(dev->num_heci_me_clients, sizeof(struct heci_me_client), GFP_KERNEL); - if (!clients) { + + spin_lock_bh(&dev->mecl_lock); + kfree(dev->me_clients); + dev->me_clients = clients; + if (clients == NULL) { + dev->num_heci_me_clients = 0; + atomic_set(&dev->heci_state, HECI_DISABLED); + spin_unlock_bh(&dev->mecl_lock); DBG("memory allocation for ME clients failed.\n"); return -ENOMEM; } - spin_lock_bh(&dev->device_lock); - dev->me_clients = clients; - spin_unlock_bh(&dev->device_lock); - num = 0; for (i = 0; i < sizeof(dev->heci_me_clients); i++) { for (j = 0; j < 8; j++) { @@ -729,72 +960,57 @@ client = &dev->me_clients[num]; client->client_id = (i * 8) + j; client->flow_ctrl_creds = 0; + spin_unlock_bh(&dev->mecl_lock); err = host_client_properties(dev, client); + spin_lock_bh(&dev->mecl_lock); if (err != 0) { - spin_lock_bh(&dev->device_lock); kfree(dev->me_clients); dev->me_clients = NULL; - spin_unlock_bh(&dev->device_lock); + dev->num_heci_me_clients = 0; + spin_unlock_bh(&dev->mecl_lock); return err; } num++; } } } - + spin_unlock_bh(&dev->mecl_lock); return 0; } /** - * heci_init_file_private - initializes private file structure. + * heci_find_me_client - search for ME client guid + * sets client_id in heci_heci_connection if found * - * @priv: private file structure to be initialized - * @file: the file structure - */ -static void heci_init_file_private(struct heci_file_private *priv, - struct file *file) -{ - memset(priv, 0, sizeof(struct heci_file_private)); - spin_lock_init(&priv->file_lock); - spin_lock_init(&priv->read_io_lock); - spin_lock_init(&priv->write_io_lock); - init_waitqueue_head(&priv->wait); - init_waitqueue_head(&priv->rx_wait); - DBG("priv->rx_wait =%p\n", &priv->rx_wait); - init_waitqueue_head(&priv->tx_wait); - INIT_LIST_HEAD(&priv->link); - priv->reading_state = HECI_IDLE; - priv->writing_state = HECI_IDLE; -} - -/** - * heci_find_me_client - search for ME client guid - * sets client_id in heci_file_private if found * @dev: Device object for our driver - * @priv: private file structure to set client_id in + * @conn: connection data of the file object to set client_id in * @cguid: searched guid of ME client * @client_id: id of host client to be set in file private structure * * returns ME client index */ static __u8 heci_find_me_client(struct iamt_heci_device *dev, - struct heci_file_private *priv, + struct heci_connection *conn, const struct guid *cguid, __u8 client_id) { __u8 i; - if ((dev == NULL) || (priv == NULL) || (cguid == NULL)) + if ((dev == NULL) || (conn == NULL) || (cguid == NULL)) return 0; for (i = 0; i < dev->num_heci_me_clients; i++) { if (memcmp(cguid, &dev->me_clients[i].props.protocol_name, sizeof(struct guid)) == 0) { - priv->me_client_id = dev->me_clients[i].client_id; - priv->state = HECI_FILE_CONNECTING; - priv->host_client_id = client_id; + conn->me_client_id = dev->me_clients[i].client_id; + conn->max_msg_length = + dev->me_clients[i].props.max_msg_length; + atomic_set(&conn->state, HECI_FILE_CONNECTING); + conn->host_client_id = client_id; - list_add_tail(&priv->link, &dev->file_list); + spin_lock(&dev->conn_lock); + list_add_tail(&conn->link, &dev->conn_list); + spin_unlock(&dev->conn_lock); return i; } } @@ -810,7 +1026,7 @@ { __u8 i; - spin_lock_bh(&dev->device_lock); + spin_lock_bh(&dev->mecl_lock); dev->asf_mode = 0; /* find ME ASF client - otherwise assume AMT mode */ DBG("find ME ASF client - otherwise assume AMT mode.\n"); @@ -819,77 +1035,86 @@ &dev->me_clients[i].props.protocol_name, sizeof(struct guid)) == 0) { dev->asf_mode = 1; - spin_unlock_bh(&dev->device_lock); + spin_unlock_bh(&dev->mecl_lock); DBG("found ME ASF client.\n"); return; } } - spin_unlock_bh(&dev->device_lock); + spin_unlock_bh(&dev->mecl_lock); DBG("assume AMT mode.\n"); } /** * heci_connect_me_client - connect ME client + * * @dev: Device object for our driver - * @priv: private file structure + * @conn: connection data of the file object * @timeout: connect timeout in seconds * * returns 1 - if connected, 0 - if not */ static __u8 heci_connect_me_client(struct iamt_heci_device *dev, - struct heci_file_private *priv, + struct heci_connection *conn, long timeout) { int err = 0; - if ((dev == NULL) || (priv == NULL)) + if ((dev == NULL) || (conn == NULL)) return 0; - if (!heci_connect(dev, priv)) { + if (!heci_connect(dev, conn)) { DBG("failed to call heci_connect for client_id=%d.\n", - priv->host_client_id); - spin_lock_bh(&dev->device_lock); - heci_remove_client_from_file_list(dev, priv->host_client_id); - priv->state = HECI_FILE_DISCONNECTED; - spin_unlock_bh(&dev->device_lock); + conn->host_client_id); + spin_lock_bh(&dev->conn_lock); + list_del_init(&conn->link); + spin_unlock_bh(&dev->conn_lock); + atomic_set(&conn->state, HECI_FILE_DISCONNECTED); return 0; } - err = wait_event_timeout(dev->wait_recvd_msg, - (HECI_FILE_CONNECTED == priv->state || - HECI_FILE_DISCONNECTED == priv->state), - timeout * HZ); - if (HECI_FILE_CONNECTED != priv->state) { - spin_lock_bh(&dev->device_lock); - heci_remove_client_from_file_list(dev, priv->host_client_id); + err = wait_event_interruptible_timeout(conn->cc_wait, + ((atomic_read(&conn->state) == HECI_FILE_CONNECTED) || + (atomic_read(&conn->state) == HECI_FILE_DISCONNECTED)), + timeout * HZ); + if (atomic_read(&conn->state) != HECI_FILE_CONNECTED) { + spin_lock_bh(&dev->conn_lock); + list_del_init(&conn->link); + spin_unlock_bh(&dev->conn_lock); DBG("failed to connect client_id=%d state=%d.\n", - priv->host_client_id, priv->state); + conn->host_client_id, atomic_read(&conn->state)); if (err) DBG("failed connect err=%08x\n", err); - priv->state = HECI_FILE_DISCONNECTED; - spin_unlock_bh(&dev->device_lock); + atomic_set(&conn->state, HECI_FILE_DISCONNECTED); return 0; } DBG("successfully connected client_id=%d.\n", - priv->host_client_id); + conn->host_client_id); + spin_lock_bh(&conn->file_lock); + conn->reading_state = HECI_IDLE; + conn->wr_state = HECI_IDLE; + spin_unlock_bh(&conn->file_lock); return 1; } /** - * host_init_wd - heci initialization wd. + * host_init_wd - heci watchdog initialization * * @dev: Device object for our driver */ static void host_init_wd(struct iamt_heci_device *dev) { - spin_lock_bh(&dev->device_lock); + __u8 cres = 0; + struct heci_connection *conn = &dev->wd_conn; - heci_init_file_private(&dev->wd_file_ext, NULL); + spin_lock_bh(&conn->file_lock); + heci_reset_heci_connection(conn, NULL); + atomic_inc(&conn->refcnt); + atomic_set(&conn->state, HECI_FILE_DISCONNECTED); /* look for WD client and connect to it */ - dev->wd_file_ext.state = HECI_FILE_DISCONNECTED; dev->wd_timeout = 0; + memset(dev->wd_data, 0, HECI_START_WD_DATA_SIZE); if (dev->asf_mode) { memcpy(dev->wd_data, heci_stop_wd_params, HECI_WD_PARAMS_SIZE); } else { @@ -901,14 +1126,16 @@ &dev->wd_timeout, sizeof(__u16)); } + spin_lock(&dev->mecl_lock); /* find ME WD client */ - heci_find_me_client(dev, &dev->wd_file_ext, - &heci_wd_guid, HECI_WD_HOST_CLIENT_ID); - spin_unlock_bh(&dev->device_lock); - - DBG("check wd_file_ext\n"); - if (HECI_FILE_CONNECTING == dev->wd_file_ext.state) { - if (heci_connect_me_client(dev, &dev->wd_file_ext, 15) == 1) { + heci_find_me_client(dev, conn, &heci_wd_guid, HECI_WD_HOST_CLIENT_ID); + spin_unlock(&dev->mecl_lock); + DBG("check wd_conn\n"); + if (atomic_read(&conn->state) == HECI_FILE_CONNECTING) { + spin_unlock_bh(&conn->file_lock); + cres = heci_connect_me_client(dev, conn, HECI_CONNECT_TIMEOUT); + spin_lock_bh(&conn->file_lock); + if (cres == 1) { DBG("dev->wd_timeout=%d.\n", dev->wd_timeout); if (dev->wd_timeout != 0) dev->wd_due_counter = 1; @@ -919,160 +1146,40 @@ } else DBG("failed to find WD client.\n"); - - spin_lock_bh(&dev->device_lock); dev->wd_timer.function = &heci_wd_timer; dev->wd_timer.data = (unsigned long) dev; - spin_unlock_bh(&dev->device_lock); + spin_unlock_bh(&conn->file_lock); } - /** - * host_init_iamthif - heci initialization iamthif client. + * host_init_iamthif - heci iamthif client initialization * * @dev: Device object for our driver - * */ static void host_init_iamthif(struct iamt_heci_device *dev) { __u8 i; + struct heci_connection *conn = &dev->iamthif_conn; - spin_lock_bh(&dev->device_lock); + spin_lock_bh(&conn->file_lock); + heci_reset_heci_connection(conn, NULL); + atomic_inc(&conn->refcnt); + atomic_set(&conn->state, HECI_FILE_DISCONNECTED); - heci_init_file_private(&dev->iamthif_file_ext, NULL); - dev->iamthif_file_ext.state = HECI_FILE_DISCONNECTED; - + spin_lock(&dev->mecl_loc... [truncated message content] |