aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mvp/commkm/comm_svc.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mvp/commkm/comm_svc.c')
-rw-r--r--arch/arm/mvp/commkm/comm_svc.c421
1 files changed, 421 insertions, 0 deletions
diff --git a/arch/arm/mvp/commkm/comm_svc.c b/arch/arm/mvp/commkm/comm_svc.c
new file mode 100644
index 0000000..18f62bd
--- /dev/null
+++ b/arch/arm/mvp/commkm/comm_svc.c
@@ -0,0 +1,421 @@
+/*
+ * Linux 2.6.32 and later Kernel module for VMware MVP Guest Communications
+ *
+ * Copyright (C) 2010-2012 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#line 5
+
+/**
+ * @file
+ *
+ * @brief Communication functions based on transport functionality.
+ */
+
+#include "comm_os.h"
+#include "comm_os_mod_ver.h"
+#include "comm_svc.h"
+
+
+/*
+ * Initialization of module entry and exit callbacks expected by module
+ * loading/unloading functions in comm_os.
+ */
+
+static int Init(void *args);
+static void Exit(void);
+
+COMM_OS_MOD_INIT(Init, Exit);
+
+static volatile int running; // Initialized and running.
+
+
+/**
+ * @brief Allocates and initializes comm global state.
+ * Starts input dispatch and aio threads.
+ * @param argsIn arguments
+ * @return zero if successful, non-zero otherwise.
+ */
+
+static int
+Init(void *argsIn)
+{
+ int rc = -1;
+ unsigned int maxChannels = 8;
+ /*
+ * Infinite timeout, 1 polling cycle
+ * see kernel/time.c: msecs_to_jiffies()
+ */
+ unsigned int pollingMillis = (unsigned int)-1;
+ unsigned int pollingCycles = 1;
+ const char *args = argsIn;
+
+ if (args && *args) {
+ /* coverity[secure_coding] */
+ sscanf(args,
+ "max_channels:%u,poll_millis:%u,poll_cycles:%u",
+ &maxChannels, &pollingMillis, &pollingCycles);
+ CommOS_Debug(("%s: arguments [%s].\n", __FUNCTION__, args));
+ }
+
+ rc = Comm_Init(maxChannels);
+ if (rc) {
+ goto out;
+ }
+
+ rc = CommOS_StartIO(COMM_OS_MOD_SHORT_NAME_STRING "-disp",
+ Comm_DispatchAll, pollingMillis, pollingCycles,
+ COMM_OS_MOD_SHORT_NAME_STRING "-aio");
+ if (rc) {
+ unsigned long long timeout = 0;
+
+ Comm_Finish(&timeout); /* Nothing started, guaranteed to succeed. */
+ goto out;
+ }
+ running = 1;
+ rc = 0;
+
+out:
+ return rc;
+}
+
+
+/**
+ * @brief Attempts to close all channels.
+ * @return zero if successful, non-zero otherwise.
+ */
+
+static int
+Halt(void)
+{
+ unsigned int maxTries = 10;
+ int rc = -1;
+
+ if (!running) {
+ rc = 0;
+ goto out;
+ }
+
+ for ( ; maxTries; maxTries--) {
+ unsigned long long timeout = 2000ULL;
+
+ CommOS_Debug(("%s: Attempting to halt...\n", __FUNCTION__));
+ if (!Comm_Finish(&timeout)) {
+ running = 0;
+ rc = 0;
+ break;
+ }
+ }
+
+out:
+ return rc;
+}
+
+
+/**
+ * @brief Stops the comm_rt module.
+ * If Halt() call successful, stops input dispatch and aio threads.
+ */
+
+static void
+Exit(void)
+{
+ if (!Halt()) {
+ CommOS_StopIO();
+ }
+}
+
+
+/**
+ * @brief Registers an implementation block used when attaching to channels
+ * in response to transport attach events.
+ * @param impl implementation block.
+ * @return 0 if successful, non-zero otherwise.
+ */
+
+int
+CommSvc_RegisterImpl(const CommImpl *impl)
+{
+ return Comm_RegisterImpl(impl);
+}
+
+
+/**
+ * @brief Unregisters an implementation block used when attaching to channels
+ * in response to transport attach events.
+ * @param impl implementation block.
+ */
+
+void
+CommSvc_UnregisterImpl(const CommImpl *impl)
+{
+ Comm_UnregisterImpl(impl);
+}
+
+
+/**
+ * @brief Finds a free entry and initializes it with the information provided.
+ * May be called from BH. It doesn't call potentially blocking functions.
+ * @param transpArgs transport initialization arguments.
+ * @param impl implementation block.
+ * @param inBH non-zero if called in bottom half.
+ * @param[out] newChannel newly allocated channel.
+ * @return zero if successful, non-zero otherwise.
+ * @sideeffects Initializes the communications channel with given parameters
+ */
+
+int
+CommSvc_Alloc(const CommTranspInitArgs *transpArgs,
+ const CommImpl *impl,
+ int inBH,
+ CommChannel *newChannel)
+{
+ return Comm_Alloc(transpArgs, impl, inBH, newChannel);
+}
+
+
+/**
+ * @brief Zombifies a channel. May fail if channel isn't active.
+ * @param channel channel to zombify.
+ * @param inBH non-zero if called in bottom half.
+ * @return zero if channel zombified, non-zero otherwise.
+ */
+
+int
+CommSvc_Zombify(CommChannel channel,
+ int inBH)
+{
+ return Comm_Zombify(channel, inBH);
+}
+
+
+/**
+ * @brief Reports whether a channel is active.
+ * @param channel channel to report on.
+ * @return non-zero if channel active, zero otherwise.
+ */
+
+int
+CommSvc_IsActive(CommChannel channel)
+{
+ return Comm_IsActive(channel);
+}
+
+
+/**
+ * @brief Retrieves a channel's transport initialization arguments.
+ * It doesn't lock, the caller must ensure the channel may be accessed.
+ * @param channel CommChannel structure to get initialization arguments from.
+ * @return initialization arguments used to allocate/attach to channel.
+ */
+
+CommTranspInitArgs
+CommSvc_GetTranspInitArgs(CommChannel channel)
+{
+ return Comm_GetTranspInitArgs(channel);
+}
+
+
+/**
+ * @brief Retrieves upper layer state (pointer). It doesn't lock, the caller
+ * must ensure the channel may be accessed.
+ * @param channel CommChannel structure to get state from.
+ * @return pointer to upper layer state.
+ */
+
+void *
+CommSvc_GetState(CommChannel channel)
+{
+ return Comm_GetState(channel);
+}
+
+
+/**
+ * @brief Writes a fully formatted packet (containing payload data, if
+ * applicable) to the specified channel.
+ *
+ * The operation may block until enough write space is available, but no
+ * more than the specified interval. The operation either writes the full
+ * amount of bytes, or it fails. Warning: callers must _not_ use the
+ * _Lock/_Unlock functions to bracket calls to this function.
+ * @param[in,out] channel channel to write to.
+ * @param packet packet to write.
+ * @param[in,out] timeoutMillis interval in milliseconds to wait.
+ * @return number of bytes written, 0 if it times out, -1 error.
+ * @sideeffects Data may be written to the channel.
+ */
+
+int
+CommSvc_Write(CommChannel channel,
+ const CommPacket *packet,
+ unsigned long long *timeoutMillis)
+{
+ return Comm_Write(channel, packet, timeoutMillis);
+}
+
+
+/**
+ * @brief Writes a packet and associated payload data to the specified channel.
+ *
+ * The operation may block until enough write space is available, but not
+ * more than the specified interval. The operation either writes the full
+ * amount of bytes, or it fails. Users may call this function successively
+ * to write several packets from large {io|k}vecs. If that's the case, the
+ * packet header needs to be updated in between calls, for the different
+ * (total) lengths. Warning: callers must _not_ use the _Lock/_Unlock
+ * functions to bracket calls to this function.
+ * @param[in,out] channel the specified channel
+ * @param packet packet to write
+ * @param[in,out] vec kvec to write from
+ * @param[in,out] vecLen length of kvec
+ * @param[in,out] timeoutMillis interval in milliseconds to wait
+ * @param[in,out] iovOffset must be set to 0 before first call (internal cookie)
+ * @return number of bytes written, 0 if it timed out, -1 error
+ * @sideeffects data may be written to the channel
+ */
+
+int
+CommSvc_WriteVec(CommChannel channel,
+ const CommPacket *packet,
+ struct kvec **vec,
+ unsigned int *vecLen,
+ unsigned long long *timeoutMillis,
+ unsigned int *iovOffset)
+{
+ return Comm_WriteVec(channel, packet, vec, vecLen, timeoutMillis, iovOffset);
+}
+
+
+/**
+ * @brief Releases channel ref count. This function is exported for the upper
+ * layer's 'activateNtf' callback which may be run asynchronously. The
+ * callback is protected from concurrent channel releases until it calls
+ * this function.
+ * @param[in,out] channel CommChannel structure to release.
+ */
+
+void
+CommSvc_Put(CommChannel channel)
+{
+ Comm_Put(channel);
+}
+
+
+/**
+ * @brief Uses the read lock. This function is exported for the upper layer
+ * such that it can order acquisition of a different lock (socket) with
+ * the release of the dispatch lock.
+ * @param[in,out] channel CommChannel structure to unlock.
+ */
+
+void
+CommSvc_DispatchUnlock(CommChannel channel)
+{
+ Comm_DispatchUnlock(channel);
+}
+
+
+/**
+ * @brief Lock the channel.
+ *
+ * Uses the writer lock. This function is exported for the upper layer
+ * to ensure that channel isn't closed while updating the layer state.
+ * It also guarantees that if the lock is taken, the entry is either ACTIVE
+ * or ZOMBIE. Operations using this function are expected to be short,
+ * since unlike the _Write functions, these callers cannot be signaled.
+ * @param[in,out] channel CommChannel structure to lock.
+ * @return zero if successful, -1 otherwise.
+ */
+
+int
+CommSvc_Lock(CommChannel channel)
+{
+ return Comm_Lock(channel);
+}
+
+
+/**
+ * @brief Unlock the channel.
+ *
+ * Uses the writer lock. This function is exported for the upper layer
+ * to ensure that channel isn't closed while updating the layer state.
+ * See Comm_WriteLock for details).
+ * @param[in,out] channel CommChannel structure to unlock.
+ */
+
+void
+CommSvc_Unlock(CommChannel channel)
+{
+ Comm_Unlock(channel);
+}
+
+
+/**
+ * @brief Schedules a work item on the AIO thread(s).
+ * @param[in,out] work work item to be scheduled.
+ * @return zero if successful, -1 otherwise.
+ */
+
+int
+CommSvc_ScheduleAIOWork(CommOSWork *work)
+{
+ return CommOS_ScheduleAIOWork(work);
+}
+
+
+/**
+ * @brief Requests events be posted in-line after the function completes.
+ * @param channel channel object.
+ * @return current number of requests for inline event posting, or -1 on error.
+ */
+
+unsigned int
+CommSvc_RequestInlineEvents(CommChannel channel)
+{
+ return Comm_RequestInlineEvents(channel);
+}
+
+
+/**
+ * @brief Requests events be posted out-of-band after the function completes.
+ * @param channel channel object.
+ * @return current number of requests for inline event posting, or -1 on error.
+ */
+
+unsigned int
+CommSvc_ReleaseInlineEvents(CommChannel channel)
+{
+ return Comm_ReleaseInlineEvents(channel);
+}
+
+
+#if defined(__linux__)
+EXPORT_SYMBOL(CommSvc_RegisterImpl);
+EXPORT_SYMBOL(CommSvc_UnregisterImpl);
+EXPORT_SYMBOL(CommSvc_Alloc);
+EXPORT_SYMBOL(CommSvc_Zombify);
+EXPORT_SYMBOL(CommSvc_IsActive);
+EXPORT_SYMBOL(CommSvc_GetTranspInitArgs);
+EXPORT_SYMBOL(CommSvc_GetState);
+EXPORT_SYMBOL(CommSvc_Write);
+EXPORT_SYMBOL(CommSvc_WriteVec);
+EXPORT_SYMBOL(CommSvc_Put);
+EXPORT_SYMBOL(CommSvc_DispatchUnlock);
+EXPORT_SYMBOL(CommSvc_Lock);
+EXPORT_SYMBOL(CommSvc_Unlock);
+EXPORT_SYMBOL(CommSvc_ScheduleAIOWork);
+EXPORT_SYMBOL(CommSvc_RequestInlineEvents);
+EXPORT_SYMBOL(CommSvc_ReleaseInlineEvents);
+#endif // defined(__linux__)