ESXi-5.5-GA

This commit is contained in:
unknown 2015-10-23 18:26:03 -04:00
parent 8564209306
commit 91e0d39c98
839 changed files with 589905 additions and 680866 deletions

View file

@ -6,5 +6,5 @@
* files for the driver's defineVmkDriver() rule. * files for the driver's defineVmkDriver() rule.
*/ */
VMK_NAMESPACE_PROVIDES("com.vmware.vmkplexer", "2.0"); VMK_NAMESPACE_PROVIDES("com.vmware.vmkplexer", "3.0");
#define VMKLNX_MY_NAMESPACE_VERSION "2.0" #define VMKLNX_MY_NAMESPACE_VERSION "3.0"

View file

@ -6,4 +6,4 @@
* files for the driver's defineVmkDriver() rule. * files for the driver's defineVmkDriver() rule.
*/ */
VMK_NAMESPACE_REQUIRED("com.vmware.libata", "9.2.1.0"); VMK_NAMESPACE_REQUIRED("com.vmware.libata", "9.2.2.0");

View file

@ -6,4 +6,4 @@
* files for the driver's defineVmkDriver() rule. * files for the driver's defineVmkDriver() rule.
*/ */
VMK_NAMESPACE_REQUIRED("com.vmware.libata", "9.2.1.0"); VMK_NAMESPACE_REQUIRED("com.vmware.libata", "9.2.2.0");

View file

@ -6,4 +6,6 @@
* files for the driver's defineVmkDriver() rule. * files for the driver's defineVmkDriver() rule.
*/ */
VMK_NAMESPACE_REQUIRED("com.broadcom.cnic_register", "9.2.1.0"); VMK_NAMESPACE_PROVIDES("com.broadcom.bnx2", "9.2.2.0");
#define VMKLNX_MY_NAMESPACE_VERSION "9.2.2.0"
VMK_NAMESPACE_REQUIRED("com.broadcom.cnic_register", "9.2.2.0");

View file

@ -0,0 +1,11 @@
/*
* DO NOT EDIT THIS FILE - IT IS GENERATED BY THE DRIVER BUILD.
*
* If you need to change the driver's name spaces, look in the scons
* files for the driver's defineVmkDriver() rule.
*/
VMK_NAMESPACE_REQUIRED("com.broadcom.cnic", "9.2.2.0");
VMK_NAMESPACE_REQUIRED("com.vmware.libfcoe", "9.2.2.0");
VMK_NAMESPACE_REQUIRED("com.vmware.libfc", "9.2.2.0");

View file

@ -6,5 +6,6 @@
* files for the driver's defineVmkDriver() rule. * files for the driver's defineVmkDriver() rule.
*/ */
VMK_NAMESPACE_REQUIRED("com.broadcom.cnic", "9.2.1.0"); VMK_NAMESPACE_REQUIRED("com.broadcom.cnic", "9.2.2.0");
VMK_NAMESPACE_REQUIRED("com.vmware.iscsi_linux", "9.2.1.0"); VMK_NAMESPACE_REQUIRED("com.broadcom.cnic_register", "9.2.2.0");
VMK_NAMESPACE_REQUIRED("com.vmware.iscsi_linux", "9.2.2.0");

View file

@ -6,4 +6,6 @@
* files for the driver's defineVmkDriver() rule. * files for the driver's defineVmkDriver() rule.
*/ */
VMK_NAMESPACE_REQUIRED("com.broadcom.cnic_register", "9.2.1.0"); VMK_NAMESPACE_PROVIDES("com.broadcom.bnx2x", "9.2.2.0");
#define VMKLNX_MY_NAMESPACE_VERSION "9.2.2.0"
VMK_NAMESPACE_REQUIRED("com.broadcom.cnic_register", "9.2.2.0");

View file

@ -6,6 +6,6 @@
* files for the driver's defineVmkDriver() rule. * files for the driver's defineVmkDriver() rule.
*/ */
VMK_NAMESPACE_PROVIDES("com.broadcom.cnic", "9.2.1.0"); VMK_NAMESPACE_PROVIDES("com.broadcom.cnic", "9.2.2.0");
#define VMKLNX_MY_NAMESPACE_VERSION "9.2.1.0" #define VMKLNX_MY_NAMESPACE_VERSION "9.2.2.0"
VMK_NAMESPACE_REQUIRED("com.broadcom.cnic_register", "9.2.1.0"); VMK_NAMESPACE_REQUIRED("com.broadcom.cnic_register", "9.2.2.0");

View file

@ -6,5 +6,5 @@
* files for the driver's defineVmkDriver() rule. * files for the driver's defineVmkDriver() rule.
*/ */
VMK_NAMESPACE_PROVIDES("com.broadcom.cnic_register", "9.2.1.0"); VMK_NAMESPACE_PROVIDES("com.broadcom.cnic_register", "9.2.2.0");
#define VMKLNX_MY_NAMESPACE_VERSION "9.2.1.0" #define VMKLNX_MY_NAMESPACE_VERSION "9.2.2.0"

View file

@ -6,5 +6,5 @@
* files for the driver's defineVmkDriver() rule. * files for the driver's defineVmkDriver() rule.
*/ */
VMK_NAMESPACE_REQUIRED("com.vmware.libfc", "9.2.1.0"); VMK_NAMESPACE_REQUIRED("com.vmware.libfc", "9.2.2.0");
VMK_NAMESPACE_REQUIRED("com.vmware.libfcoe", "9.2.1.0"); VMK_NAMESPACE_REQUIRED("com.vmware.libfcoe", "9.2.2.0");

View file

@ -6,4 +6,4 @@
* files for the driver's defineVmkDriver() rule. * files for the driver's defineVmkDriver() rule.
*/ */
VMK_NAMESPACE_REQUIRED("com.vmware.ipmi", "9.2.1.0"); VMK_NAMESPACE_REQUIRED("com.vmware.ipmi", "9.2.2.0");

View file

@ -6,5 +6,5 @@
* files for the driver's defineVmkDriver() rule. * files for the driver's defineVmkDriver() rule.
*/ */
VMK_NAMESPACE_PROVIDES("com.vmware.ipmi", "9.2.1.0"); VMK_NAMESPACE_PROVIDES("com.vmware.ipmi", "9.2.2.0");
#define VMKLNX_MY_NAMESPACE_VERSION "9.2.1.0" #define VMKLNX_MY_NAMESPACE_VERSION "9.2.2.0"

View file

@ -6,4 +6,4 @@
* files for the driver's defineVmkDriver() rule. * files for the driver's defineVmkDriver() rule.
*/ */
VMK_NAMESPACE_REQUIRED("com.vmware.ipmi", "9.2.1.0"); VMK_NAMESPACE_REQUIRED("com.vmware.ipmi", "9.2.2.0");

View file

@ -6,5 +6,5 @@
* files for the driver's defineVmkDriver() rule. * files for the driver's defineVmkDriver() rule.
*/ */
VMK_NAMESPACE_PROVIDES("com.lsi.megaraid_mbox", "9.2.1.0"); VMK_NAMESPACE_PROVIDES("com.lsi.megaraid_mbox", "9.2.2.0");
#define VMKLNX_MY_NAMESPACE_VERSION "9.2.1.0" #define VMKLNX_MY_NAMESPACE_VERSION "9.2.2.0"

View file

@ -0,0 +1,10 @@
/*
* DO NOT EDIT THIS FILE - IT IS GENERATED BY THE DRIVER BUILD.
*
* If you need to change the driver's name spaces, look in the scons
* files for the driver's defineVmkDriver() rule.
*/
VMK_NAMESPACE_PROVIDES("com.mellanox.mlx4_core", "9.2.2.0");
#define VMKLNX_MY_NAMESPACE_VERSION "9.2.2.0"

View file

@ -0,0 +1,9 @@
/*
* DO NOT EDIT THIS FILE - IT IS GENERATED BY THE DRIVER BUILD.
*
* If you need to change the driver's name spaces, look in the scons
* files for the driver's defineVmkDriver() rule.
*/
VMK_NAMESPACE_REQUIRED("com.mellanox.mlx4_core", "9.2.2.0");

View file

@ -6,5 +6,5 @@
* files for the driver's defineVmkDriver() rule. * files for the driver's defineVmkDriver() rule.
*/ */
VMK_NAMESPACE_PROVIDES("com.netxen.nx_nic", "9.2.1.0"); VMK_NAMESPACE_PROVIDES("com.netxen.nx_nic", "9.2.2.0");
#define VMKLNX_MY_NAMESPACE_VERSION "9.2.1.0" #define VMKLNX_MY_NAMESPACE_VERSION "9.2.2.0"

View file

@ -6,4 +6,4 @@
* files for the driver's defineVmkDriver() rule. * files for the driver's defineVmkDriver() rule.
*/ */
VMK_NAMESPACE_REQUIRED("com.vmware.libata", "9.2.1.0"); VMK_NAMESPACE_REQUIRED("com.vmware.libata", "9.2.2.0");

View file

@ -6,4 +6,4 @@
* files for the driver's defineVmkDriver() rule. * files for the driver's defineVmkDriver() rule.
*/ */
VMK_NAMESPACE_REQUIRED("com.vmware.libata", "9.2.1.0"); VMK_NAMESPACE_REQUIRED("com.vmware.libata", "9.2.2.0");

View file

@ -6,4 +6,4 @@
* files for the driver's defineVmkDriver() rule. * files for the driver's defineVmkDriver() rule.
*/ */
VMK_NAMESPACE_REQUIRED("com.vmware.libata", "9.2.1.0"); VMK_NAMESPACE_REQUIRED("com.vmware.libata", "9.2.2.0");

View file

@ -6,4 +6,4 @@
* files for the driver's defineVmkDriver() rule. * files for the driver's defineVmkDriver() rule.
*/ */
VMK_NAMESPACE_REQUIRED("com.vmware.libata", "9.2.1.0"); VMK_NAMESPACE_REQUIRED("com.vmware.libata", "9.2.2.0");

View file

@ -6,4 +6,4 @@
* files for the driver's defineVmkDriver() rule. * files for the driver's defineVmkDriver() rule.
*/ */
VMK_NAMESPACE_REQUIRED("com.vmware.libata", "9.2.1.0"); VMK_NAMESPACE_REQUIRED("com.vmware.libata", "9.2.2.0");

View file

@ -6,4 +6,4 @@
* files for the driver's defineVmkDriver() rule. * files for the driver's defineVmkDriver() rule.
*/ */
VMK_NAMESPACE_REQUIRED("com.vmware.libata", "9.2.1.0"); VMK_NAMESPACE_REQUIRED("com.vmware.libata", "9.2.2.0");

View file

@ -6,4 +6,4 @@
* files for the driver's defineVmkDriver() rule. * files for the driver's defineVmkDriver() rule.
*/ */
VMK_NAMESPACE_REQUIRED("com.vmware.libata", "9.2.1.0"); VMK_NAMESPACE_REQUIRED("com.vmware.libata", "9.2.2.0");

View file

@ -6,4 +6,4 @@
* files for the driver's defineVmkDriver() rule. * files for the driver's defineVmkDriver() rule.
*/ */
VMK_NAMESPACE_REQUIRED("com.vmware.libata", "9.2.1.0"); VMK_NAMESPACE_REQUIRED("com.vmware.libata", "9.2.2.0");

View file

@ -6,6 +6,6 @@
* files for the driver's defineVmkDriver() rule. * files for the driver's defineVmkDriver() rule.
*/ */
VMK_NAMESPACE_PROVIDES("com.vmware.qla4xxx", "9.2.1.0"); VMK_NAMESPACE_PROVIDES("com.vmware.qla4xxx", "9.2.2.0");
#define VMKLNX_MY_NAMESPACE_VERSION "9.2.1.0" #define VMKLNX_MY_NAMESPACE_VERSION "9.2.2.0"
VMK_NAMESPACE_REQUIRED("com.vmware.iscsi_linux", "9.2.1.0"); VMK_NAMESPACE_REQUIRED("com.vmware.iscsi_linux", "9.2.2.0");

View file

@ -6,5 +6,5 @@
* files for the driver's defineVmkDriver() rule. * files for the driver's defineVmkDriver() rule.
*/ */
VMK_NAMESPACE_PROVIDES("com.vmware.random", "9.2.1.0"); VMK_NAMESPACE_PROVIDES("com.vmware.random", "9.2.2.0");
#define VMKLNX_MY_NAMESPACE_VERSION "9.2.1.0" #define VMKLNX_MY_NAMESPACE_VERSION "9.2.2.0"

View file

@ -6,4 +6,4 @@
* files for the driver's defineVmkDriver() rule. * files for the driver's defineVmkDriver() rule.
*/ */
VMK_NAMESPACE_REQUIRED("com.vmware.libata", "9.2.1.0"); VMK_NAMESPACE_REQUIRED("com.vmware.libata", "9.2.2.0");

View file

@ -6,4 +6,4 @@
* files for the driver's defineVmkDriver() rule. * files for the driver's defineVmkDriver() rule.
*/ */
VMK_NAMESPACE_REQUIRED("com.vmware.libata", "9.2.1.0"); VMK_NAMESPACE_REQUIRED("com.vmware.libata", "9.2.2.0");

View file

@ -6,4 +6,4 @@
* files for the driver's defineVmkDriver() rule. * files for the driver's defineVmkDriver() rule.
*/ */
VMK_NAMESPACE_REQUIRED("com.vmware.libata", "9.2.1.0"); VMK_NAMESPACE_REQUIRED("com.vmware.libata", "9.2.2.0");

View file

@ -6,4 +6,4 @@
* files for the driver's defineVmkDriver() rule. * files for the driver's defineVmkDriver() rule.
*/ */
VMK_NAMESPACE_REQUIRED("com.vmware.libata", "9.2.1.0"); VMK_NAMESPACE_REQUIRED("com.vmware.libata", "9.2.2.0");

View file

@ -6,4 +6,4 @@
* files for the driver's defineVmkDriver() rule. * files for the driver's defineVmkDriver() rule.
*/ */
VMK_NAMESPACE_REQUIRED("com.vmware.libata", "9.2.1.0"); VMK_NAMESPACE_REQUIRED("com.vmware.libata", "9.2.2.0");

View file

@ -6,5 +6,5 @@
* files for the driver's defineVmkDriver() rule. * files for the driver's defineVmkDriver() rule.
*/ */
VMK_NAMESPACE_PROVIDES("com.broadcom.tg3", "9.2.1.0"); VMK_NAMESPACE_PROVIDES("com.broadcom.tg3", "9.2.2.0");
#define VMKLNX_MY_NAMESPACE_VERSION "9.2.1.0" #define VMKLNX_MY_NAMESPACE_VERSION "9.2.2.0"

View file

@ -44,7 +44,9 @@ static inline struct task_struct *get_current(void)
* Pointer to current task of type task_struct * Pointer to current task of type task_struct
* *
*/ */
/* _VMKLNX_CODECHECK_: current */ /* If the macro 'current' or its comments are changed please
* update the documentation for 'current' in vmkdrivers/src_92/doc/dummyDefs.doc
*/
#define current get_current() #define current get_current()
#else #else

View file

@ -185,11 +185,16 @@ static inline void * phys_to_virt(unsigned long address)
/** /**
* page_to_phys - page handle to machine address * page_to_phys - page handle to machine address
* @maddr : machine address * @page : page handle
*
* Gets the machine address that corresponds to the page parameter
* *
* ESX Deviation Notes: * ESX Deviation Notes:
* None. * None.
* *
* RETURN VALUE:
* A machine address
*
*/ */
/* _VMKLNX_CODECHECK_: page_to_phys */ /* _VMKLNX_CODECHECK_: page_to_phys */
#define page_to_phys(page) ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT) #define page_to_phys(page) ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT)

View file

@ -352,9 +352,6 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
/* _VMKLNX_CODECHECK_: rmb */ /* _VMKLNX_CODECHECK_: rmb */
#define rmb() asm volatile("lfence":::"memory") #define rmb() asm volatile("lfence":::"memory")
#ifdef CONFIG_UNORDERED_IO
#define wmb() asm volatile("sfence" ::: "memory")
#else
/** /**
* wmb - write memory barrier * wmb - write memory barrier
* *
@ -368,9 +365,16 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
* RETURN VALUE: * RETURN VALUE:
* NONE * NONE
*/ */
/*
* VMware : 2013
*
* As mentioned in PR 891237, CONFIG_UNORDERED_IO was removed from Linux
* on 03/25/2006 by Andi Kleen ("x86_64: Remove CONFIG_UNORDERED_IO"). Here
* wmb() is being changed to a real sfence instead of just a compile barrier.
*/
/* _VMKLNX_CODECHECK_: wmb */ /* _VMKLNX_CODECHECK_: wmb */
#define wmb() asm volatile("" ::: "memory") #define wmb() asm volatile("sfence" ::: "memory")
#endif
#define read_barrier_depends() do {} while(0) #define read_barrier_depends() do {} while(0)
#define set_mb(var, value) do { (void) xchg(&var, value); } while (0) #define set_mb(var, value) do { (void) xchg(&var, value); } while (0)

View file

@ -6,5 +6,5 @@
* files for the driver's defineVmkDriver() rule. * files for the driver's defineVmkDriver() rule.
*/ */
VMK_NAMESPACE_REQUIRED("com.vmware.usb", "9.2.1.0"); VMK_NAMESPACE_REQUIRED("com.vmware.usb", "9.2.2.0");
VMK_NAMESPACE_REQUIRED("com.vmware.usbnet", "9.2.1.0"); VMK_NAMESPACE_REQUIRED("com.vmware.usbnet", "9.2.2.0");

View file

@ -6,4 +6,4 @@
* files for the driver's defineVmkDriver() rule. * files for the driver's defineVmkDriver() rule.
*/ */
VMK_NAMESPACE_REQUIRED("com.vmware.usb", "9.2.1.0"); VMK_NAMESPACE_REQUIRED("com.vmware.usb", "9.2.2.0");

View file

@ -6,5 +6,5 @@
* files for the driver's defineVmkDriver() rule. * files for the driver's defineVmkDriver() rule.
*/ */
VMK_NAMESPACE_REQUIRED("com.vmware.libfcoe", "9.2.1.0"); VMK_NAMESPACE_REQUIRED("com.vmware.libfcoe", "9.2.2.0");
VMK_NAMESPACE_REQUIRED("com.vmware.libfc", "9.2.1.0"); VMK_NAMESPACE_REQUIRED("com.vmware.libfc", "9.2.2.0");

View file

@ -6,6 +6,6 @@
* files for the driver's defineVmkDriver() rule. * files for the driver's defineVmkDriver() rule.
*/ */
VMK_NAMESPACE_PROVIDES("com.vmware.usbhid", "9.2.1.0"); VMK_NAMESPACE_PROVIDES("com.vmware.usbhid", "9.2.2.0");
#define VMKLNX_MY_NAMESPACE_VERSION "9.2.1.0" #define VMKLNX_MY_NAMESPACE_VERSION "9.2.2.0"
VMK_NAMESPACE_REQUIRED("com.vmware.usb", "9.2.1.0"); VMK_NAMESPACE_REQUIRED("com.vmware.usb", "9.2.2.0");

View file

@ -8,4 +8,4 @@
VMK_NAMESPACE_PROVIDES("com.vmware.iscsi_linux", "9.2.0.0"); VMK_NAMESPACE_PROVIDES("com.vmware.iscsi_linux", "9.2.0.0");
#define VMKLNX_MY_NAMESPACE_VERSION "9.2.0.0" #define VMKLNX_MY_NAMESPACE_VERSION "9.2.0.0"
VMK_NAMESPACE_REQUIRED("com.vmware.iscsi_linux", "9.2.1.0"); VMK_NAMESPACE_REQUIRED("com.vmware.iscsi_linux", "9.2.2.0");

View file

@ -0,0 +1,11 @@
/*
* DO NOT EDIT THIS FILE - IT IS GENERATED BY THE DRIVER BUILD.
*
* If you need to change the driver's name spaces, look in the scons
* files for the driver's defineVmkDriver() rule.
*/
VMK_NAMESPACE_PROVIDES("com.vmware.iscsi_linux", "9.2.1.0");
#define VMKLNX_MY_NAMESPACE_VERSION "9.2.1.0"
VMK_NAMESPACE_REQUIRED("com.vmware.iscsi_linux", "9.2.2.0");

View file

@ -6,5 +6,5 @@
* files for the driver's defineVmkDriver() rule. * files for the driver's defineVmkDriver() rule.
*/ */
VMK_NAMESPACE_PROVIDES("com.vmware.libata", "9.2.1.0"); VMK_NAMESPACE_PROVIDES("com.vmware.libata", "9.2.2.0");
#define VMKLNX_MY_NAMESPACE_VERSION "9.2.1.0" #define VMKLNX_MY_NAMESPACE_VERSION "9.2.2.0"

View file

@ -8,4 +8,4 @@
VMK_NAMESPACE_PROVIDES("com.vmware.libata", "9.2.0.0"); VMK_NAMESPACE_PROVIDES("com.vmware.libata", "9.2.0.0");
#define VMKLNX_MY_NAMESPACE_VERSION "9.2.0.0" #define VMKLNX_MY_NAMESPACE_VERSION "9.2.0.0"
VMK_NAMESPACE_REQUIRED("com.vmware.libata", "9.2.1.0"); VMK_NAMESPACE_REQUIRED("com.vmware.libata", "9.2.2.0");

View file

@ -0,0 +1,11 @@
/*
* DO NOT EDIT THIS FILE - IT IS GENERATED BY THE DRIVER BUILD.
*
* If you need to change the driver's name spaces, look in the scons
* files for the driver's defineVmkDriver() rule.
*/
VMK_NAMESPACE_PROVIDES("com.vmware.libata", "9.2.1.0");
#define VMKLNX_MY_NAMESPACE_VERSION "9.2.1.0"
VMK_NAMESPACE_REQUIRED("com.vmware.libata", "9.2.2.0");

View file

@ -6,5 +6,5 @@
* files for the driver's defineVmkDriver() rule. * files for the driver's defineVmkDriver() rule.
*/ */
VMK_NAMESPACE_PROVIDES("com.vmware.libfc", "9.2.1.0"); VMK_NAMESPACE_PROVIDES("com.vmware.libfc", "9.2.2.0");
#define VMKLNX_MY_NAMESPACE_VERSION "9.2.1.0" #define VMKLNX_MY_NAMESPACE_VERSION "9.2.2.0"

View file

@ -8,4 +8,4 @@
VMK_NAMESPACE_PROVIDES("com.vmware.libfc", "9.2.0.0"); VMK_NAMESPACE_PROVIDES("com.vmware.libfc", "9.2.0.0");
#define VMKLNX_MY_NAMESPACE_VERSION "9.2.0.0" #define VMKLNX_MY_NAMESPACE_VERSION "9.2.0.0"
VMK_NAMESPACE_REQUIRED("com.vmware.libfc", "9.2.1.0"); VMK_NAMESPACE_REQUIRED("com.vmware.libfc", "9.2.2.0");

View file

@ -0,0 +1,11 @@
/*
* DO NOT EDIT THIS FILE - IT IS GENERATED BY THE DRIVER BUILD.
*
* If you need to change the driver's name spaces, look in the scons
* files for the driver's defineVmkDriver() rule.
*/
VMK_NAMESPACE_PROVIDES("com.vmware.libfc", "9.2.1.0");
#define VMKLNX_MY_NAMESPACE_VERSION "9.2.1.0"
VMK_NAMESPACE_REQUIRED("com.vmware.libfc", "9.2.2.0");

View file

@ -6,6 +6,6 @@
* files for the driver's defineVmkDriver() rule. * files for the driver's defineVmkDriver() rule.
*/ */
VMK_NAMESPACE_PROVIDES("com.vmware.libfcoe", "9.2.1.0"); VMK_NAMESPACE_PROVIDES("com.vmware.libfcoe", "9.2.2.0");
#define VMKLNX_MY_NAMESPACE_VERSION "9.2.1.0" #define VMKLNX_MY_NAMESPACE_VERSION "9.2.2.0"
VMK_NAMESPACE_REQUIRED("com.vmware.libfc", "9.2.1.0"); VMK_NAMESPACE_REQUIRED("com.vmware.libfc", "9.2.2.0");

View file

@ -8,4 +8,4 @@
VMK_NAMESPACE_PROVIDES("com.vmware.libfcoe", "9.2.0.0"); VMK_NAMESPACE_PROVIDES("com.vmware.libfcoe", "9.2.0.0");
#define VMKLNX_MY_NAMESPACE_VERSION "9.2.0.0" #define VMKLNX_MY_NAMESPACE_VERSION "9.2.0.0"
VMK_NAMESPACE_REQUIRED("com.vmware.libfcoe", "9.2.1.0"); VMK_NAMESPACE_REQUIRED("com.vmware.libfcoe", "9.2.2.0");

View file

@ -0,0 +1,11 @@
/*
* DO NOT EDIT THIS FILE - IT IS GENERATED BY THE DRIVER BUILD.
*
* If you need to change the driver's name spaces, look in the scons
* files for the driver's defineVmkDriver() rule.
*/
VMK_NAMESPACE_PROVIDES("com.vmware.libfcoe", "9.2.1.0");
#define VMKLNX_MY_NAMESPACE_VERSION "9.2.1.0"
VMK_NAMESPACE_REQUIRED("com.vmware.libfcoe", "9.2.2.0");

View file

@ -6,4 +6,4 @@
* files for the driver's defineVmkDriver() rule. * files for the driver's defineVmkDriver() rule.
*/ */
VMK_NAMESPACE_REQUIRED("com.vmware.usb", "9.2.1.0"); VMK_NAMESPACE_REQUIRED("com.vmware.usb", "9.2.2.0");

View file

@ -6,6 +6,6 @@
* files for the driver's defineVmkDriver() rule. * files for the driver's defineVmkDriver() rule.
*/ */
VMK_NAMESPACE_PROVIDES("com.vmware.usbstorage", "9.2.1.0"); VMK_NAMESPACE_PROVIDES("com.vmware.usbstorage", "9.2.2.0");
#define VMKLNX_MY_NAMESPACE_VERSION "9.2.1.0" #define VMKLNX_MY_NAMESPACE_VERSION "9.2.2.0"
VMK_NAMESPACE_REQUIRED("com.vmware.usb", "9.2.1.0"); VMK_NAMESPACE_REQUIRED("com.vmware.usb", "9.2.2.0");

View file

@ -6,4 +6,4 @@
* files for the driver's defineVmkDriver() rule. * files for the driver's defineVmkDriver() rule.
*/ */
VMK_NAMESPACE_REQUIRED("com.vmware.usb", "9.2.1.0"); VMK_NAMESPACE_REQUIRED("com.vmware.usb", "9.2.2.0");

View file

@ -6,5 +6,5 @@
* files for the driver's defineVmkDriver() rule. * files for the driver's defineVmkDriver() rule.
*/ */
VMK_NAMESPACE_PROVIDES("com.vmware.usb", "9.2.1.0"); VMK_NAMESPACE_PROVIDES("com.vmware.usb", "9.2.2.0");
#define VMKLNX_MY_NAMESPACE_VERSION "9.2.1.0" #define VMKLNX_MY_NAMESPACE_VERSION "9.2.2.0"

View file

@ -6,6 +6,6 @@
* files for the driver's defineVmkDriver() rule. * files for the driver's defineVmkDriver() rule.
*/ */
VMK_NAMESPACE_PROVIDES("com.vmware.usbnet", "9.2.1.0"); VMK_NAMESPACE_PROVIDES("com.vmware.usbnet", "9.2.2.0");
#define VMKLNX_MY_NAMESPACE_VERSION "9.2.1.0" #define VMKLNX_MY_NAMESPACE_VERSION "9.2.2.0"
VMK_NAMESPACE_REQUIRED("com.vmware.usb", "9.2.1.0"); VMK_NAMESPACE_REQUIRED("com.vmware.usb", "9.2.2.0");

View file

@ -8,4 +8,4 @@
VMK_NAMESPACE_PROVIDES("com.vmware.driverAPI", "9.2"); VMK_NAMESPACE_PROVIDES("com.vmware.driverAPI", "9.2");
#define VMKLNX_MY_NAMESPACE_VERSION "9.2" #define VMKLNX_MY_NAMESPACE_VERSION "9.2"
VMK_NAMESPACE_REQUIRED("com.vmware.vmkplexer", "2.0"); VMK_NAMESPACE_REQUIRED("com.vmware.vmkplexer", "3.0");

View file

@ -0,0 +1,11 @@
/*
* DO NOT EDIT THIS FILE - IT IS GENERATED BY THE DRIVER BUILD.
*
* If you need to change the driver's name spaces, look in the scons
* files for the driver's defineVmkDriver() rule.
*/
VMK_NAMESPACE_PROVIDES("com.vmware.driverAPI", "9.2.2.0");
#define VMKLNX_MY_NAMESPACE_VERSION "9.2.2.0"
VMK_NAMESPACE_REQUIRED("com.vmware.driverAPI", "9.2");

View file

@ -129,7 +129,7 @@ static inline void vmk_AtomicDec64(
{ {
vmk_AtomicPrologue(); vmk_AtomicPrologue();
__asm__ __volatile__( __asm__ __volatile__(
"lock; decl %0" "lock; decq %0"
: "+m" (*var) : "+m" (*var)
: :
: "cc" : "cc"
@ -158,7 +158,7 @@ static inline void vmk_AtomicAdd64(
__asm__ __volatile__( __asm__ __volatile__(
"lock; addq %1, %0" "lock; addq %1, %0"
: "+m" (*var) : "+m" (*var)
: "ri" (val) : "re" (val)
: "cc" : "cc"
); );
vmk_AtomicEpilogue(); vmk_AtomicEpilogue();
@ -184,7 +184,7 @@ static inline void vmk_AtomicSub64(
__asm__ __volatile__( __asm__ __volatile__(
"lock; subq %1, %0" "lock; subq %1, %0"
: "+m" (*var) : "+m" (*var)
: "ri" (val) : "re" (val)
: "cc" : "cc"
); );
vmk_AtomicEpilogue(); vmk_AtomicEpilogue();
@ -211,7 +211,7 @@ static inline void vmk_AtomicOr64(
__asm__ __volatile__( __asm__ __volatile__(
"lock; orq %1, %0" "lock; orq %1, %0"
: "+m" (*var) : "+m" (*var)
: "ri" (val) : "re" (val)
: "cc" : "cc"
); );
vmk_AtomicEpilogue(); vmk_AtomicEpilogue();
@ -237,7 +237,7 @@ static inline void vmk_AtomicAnd64(
__asm__ __volatile__( __asm__ __volatile__(
"lock; andq %1, %0" "lock; andq %1, %0"
: "+m" (*var) : "+m" (*var)
: "ri" (val) : "re" (val)
: "cc" : "cc"
); );
vmk_AtomicEpilogue(); vmk_AtomicEpilogue();
@ -263,7 +263,7 @@ static inline void vmk_AtomicXor64(
__asm__ __volatile__( __asm__ __volatile__(
"lock; xorq %1, %0" "lock; xorq %1, %0"
: "+m" (*var) : "+m" (*var)
: "ri" (val) : "re" (val)
: "cc" : "cc"
); );
vmk_AtomicEpilogue(); vmk_AtomicEpilogue();

View file

@ -1,5 +1,5 @@
/* ********************************************************** /* **********************************************************
* Copyright 1998 - 2010 VMware, Inc. All rights reserved. * Copyright 1998 - 2010,2012 VMware, Inc. All rights reserved.
* **********************************************************/ * **********************************************************/
/* /*
@ -51,8 +51,11 @@
/** \brief Don't block for file operations. */ /** \brief Don't block for file operations. */
#define VMK_CHARDEV_OFLAG_NONBLOCK 0x00000800 #define VMK_CHARDEV_OFLAG_NONBLOCK 0x00000800
/** \brief Synchronous file operations. */ /** \brief File integerity for synchronous file I/O. */
#define VMK_CHARDEV_OFLAG_SYNC 0x00001000 #define VMK_CHARDEV_OFLAG_SYNC 0x00101000
/** \brief Data integrity for synchronous file I/O. */
#define VMK_CHARDEV_OFLAG_DSYNC 0x00001000
/** \brief Use direct I/O. */ /** \brief Use direct I/O. */
#define VMK_CHARDEV_OFLAG_DIRECT 0x00004000 #define VMK_CHARDEV_OFLAG_DIRECT 0x00004000
@ -106,16 +109,6 @@ typedef struct vmk_CharDevFdAttr {
/* across open/ioctl/close calls */ /* across open/ioctl/close calls */
} vmk_CharDevFdAttr; } vmk_CharDevFdAttr;
/**
* \brief Opaque handle to a character device.
*/
typedef struct vmkCharDevInt* vmk_CharDev;
/**
* \brief A default initialization value for a vmk_CharDev.
*/
#define VMK_INVALID_CHARDEV (NULL)
/** /**
* \brief Opaque poll token handle. * \brief Opaque poll token handle.
*/ */
@ -126,6 +119,26 @@ typedef void *vmk_PollToken;
*/ */
typedef void *vmk_PollContext; typedef void *vmk_PollContext;
/**
* \brief Identifier for logical graphics devices.
*/
#define VMK_CHARDEV_IDENTIFIER_GRAPHICS "com.vmware.graphics"
/**
* \brief Character device driver's entry points.
*/
struct vmk_CharDevOps;
/** \brief Character device registration data. */
typedef struct vmk_CharDevRegData {
/** \brief Module creating this device. */
vmk_ModuleID moduleID;
/** \brief Device operations. */
const struct vmk_CharDevOps *fileOps;
/** \brief Device private data. */
vmk_AddrCookie devicePrivate;
} vmk_CharDevRegData;
/** /**
*********************************************************************** ***********************************************************************
* vmk_CharDevOpenFn -- */ /** * vmk_CharDevOpenFn -- */ /**
@ -330,93 +343,6 @@ typedef struct vmk_CharDevOps {
vmk_CharDevWriteFn write; vmk_CharDevWriteFn write;
} vmk_CharDevOps; } vmk_CharDevOps;
/**
***********************************************************************
* vmk_CharDevCleanupFn -- */ /**
*
* \brief Prototype for a character device driver's cleanup callback.
*
* \param[in] private Optional private data to be used by the callback
*
* \retval VMK_OK The cleanup function executed correctly.
* This is not an indicator of the success or failure of
* the operations in the function, but merely that they
* ran. Any other return value is not allowed.
*
***********************************************************************
*/
typedef VMK_ReturnStatus (*vmk_CharDevCleanupFn)(vmk_AddrCookie private);
/*
***********************************************************************
* vmk_CharDevRegister -- */ /**
*
* \brief Register the specified character device, to be invoked from
* user-space.
*
* \param[in] module Module that owns the character device.
* \param[in] name The name of the device - this must be unique.
* \param[in] fileOps Table of the driver file operations.
* Neither open nor close can be supplied
* without the other.
* If read or write operations are supplied,
* then open and close must also be supplied.
* \param[in] cleanup Function automatically invoked to clean up
* after all file ops have ceased and the
* device has been unregistered. May be NULL.
* \param[in] devicePrivate Data given to the driver for each file
* op and cleaned up after unregistration.
* \param[out] assignedHandle Handle to the registered character device.
*
* \retval VMK_EXISTS A device with that name is already registered
* \retval VMK_FAILURE Unable to allocate internal slot for the device
* \retval VMK_NO_MEMORY Unable to allocate memory for device metadata
* \retval VMK_BAD_PARAM Module ID was invalid, name was invalid,
* or one or more specified driver ops are NULL
*
***********************************************************************
*/
VMK_ReturnStatus vmk_CharDevRegister(
vmk_ModuleID module,
const char *name,
const vmk_CharDevOps *fileOps,
vmk_CharDevCleanupFn cleanup,
vmk_AddrCookie devicePrivate,
vmk_CharDev *assignedHandle);
/*
***********************************************************************
* vmk_CharDevUnregister -- */ /**
*
* \brief Unregister a character device.
*
* The character device will be unregistered automatically by
* the kernel only after all open files to the device have been
* closed. If no files are open when vmk_CharDevUnregister is
* called, the device may be unregistered immediately and have the
* cleanup function registered with it invoked. If the device has
* files open, vmk_CharDevUnregister internally defers the device for
* later automatic removal and returns to the caller immediately. When
* the last file is closed, the device will then be destroyed and the
* cleanup function invoked.
*
* \note No new open files to the device can be created after calling
* vmk_CharDevUnregister.
* \note The vmkernel will prevent a module from being unloaded while
* it has open files associated with a character device, even
* if that device has been requested to be unregistered.
*
* \param[in] deviceHandle Handle of device assigned during registration.
*
* \retval VMK_NOT_FOUND The device does not exist.
* \retval VMK_OK The device was either unregistered or internally
* deferred for unregistration once all associated files
* close.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_CharDevUnregister(vmk_CharDev deviceHandle);
/* /*
*********************************************************************** ***********************************************************************
* vmk_CharDevWakePollers -- */ /** * vmk_CharDevWakePollers -- */ /**

View file

@ -0,0 +1,131 @@
/* **********************************************************
* Copyright 2012 VMware, Inc. All rights reserved.
* **********************************************************/
/*
* @VMKAPIMOD_LICENSE@
*/
/*
***********************************************************************
* Character Devices */ /**
* \addtogroup CharDev
*
* Interfaces that allow registration of generic vmkernel character
* device nodes.
*
* @{
***********************************************************************
*/
#ifndef _VMKAPI_CHAR_LEGACY_H_
#define _VMKAPI_CHAR_LEGACY_H_
/** \cond never */
#ifndef VMK_HEADER_INCLUDED_FROM_VMKAPI_H
#error This vmkapi file should never be included directly but only via vmkapi.h
#endif
/** \endcond never */
/**
* \brief Opaque handle to a character device.
*/
typedef struct vmkCharDevInt* vmk_CharDev;
/**
* \brief A default initialization value for a vmk_CharDev.
*/
#define VMK_INVALID_CHARDEV (NULL)
/**
***********************************************************************
* vmk_CharDevCleanupFn -- */ /**
*
* \brief Prototype for a character device driver's cleanup callback.
*
* \param[in] private Optional private data to be used by the callback
*
* \retval VMK_OK The cleanup function executed correctly.
* This is not an indicator of the success or failure of
* the operations in the function, but merely that they
* ran. Any other return value is not allowed.
*
***********************************************************************
*/
typedef VMK_ReturnStatus (*vmk_CharDevCleanupFn)(vmk_AddrCookie private);
/*
***********************************************************************
* vmk_CharDevRegister -- */ /**
*
* \brief Register the specified character device, to be invoked from
* user-space.
*
* \nativedriversdisallowed
*
* \param[in] module Module that owns the character device.
* \param[in] name The name of the device - this must be unique.
* \param[in] fileOps Table of the driver file operations.
* Neither open nor close can be supplied
* without the other.
* If read or write operations are supplied,
* then open and close must also be supplied.
* \param[in] cleanup Function automatically invoked to clean up
* after all file ops have ceased and the
* device has been unregistered. May be NULL.
* \param[in] devicePrivate Data given to the driver for each file
* op and cleaned up after unregistration.
* \param[out] assignedHandle Handle to the registered character device.
*
* \retval VMK_EXISTS A device with that name is already registered
* \retval VMK_FAILURE Unable to allocate internal slot for the device
* \retval VMK_NO_MEMORY Unable to allocate memory for device metadata
* \retval VMK_BAD_PARAM Module ID was invalid, name was invalid,
* or one or more specified driver ops are NULL
*
***********************************************************************
*/
VMK_ReturnStatus vmk_CharDevRegister(
vmk_ModuleID module,
const char *name,
const vmk_CharDevOps *fileOps,
vmk_CharDevCleanupFn cleanup,
vmk_AddrCookie devicePrivate,
vmk_CharDev *assignedHandle);
/*
***********************************************************************
* vmk_CharDevUnregister -- */ /**
*
* \brief Unregister a character device.
*
* The character device will be unregistered automatically by
* the kernel only after all open files to the device have been
* closed. If no files are open when vmk_CharDevUnregister is
* called, the device may be unregistered immediately and have the
* cleanup function registered with it invoked. If the device has
* files open, vmk_CharDevUnregister internally defers the device for
* later automatic removal and returns to the caller immediately. When
* the last file is closed, the device will then be destroyed and the
* cleanup function invoked.
*
* \nativedriversdisallowed
* \note No new open files to the device can be created after calling
* vmk_CharDevUnregister.
* \note The vmkernel will prevent a module from being unloaded while
* it has open files associated with a character device, even
* if that device has been requested to be unregistered.
*
* \param[in] deviceHandle Handle of device assigned during registration.
*
* \retval VMK_NOT_FOUND The device does not exist.
* \retval VMK_OK The device was either unregistered or internally
* deferred for unregistration once all associated files
* close.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_CharDevUnregister(vmk_CharDev deviceHandle);
#endif /* _VMKAPI_CHAR_LEGACY_H_ */
/** @} */

View file

@ -188,6 +188,31 @@ VMK_ReturnStatus vmk_HeapCreate(vmk_HeapCreateProps *props,
*/ */
void vmk_HeapDestroy(vmk_HeapID heap); void vmk_HeapDestroy(vmk_HeapID heap);
/*
***********************************************************************
* vmk_HeapDestroySync -- */ /**
*
* \brief Destroy a dynamic heap. If the heap is non-empty, wait
* for it to become empty before destroying.
*
* \note This function may block if the heap is non-empty.
*
* \param[in] heap Heap to destroy.
* \param[in] timeoutMS Timeout in milliseconds. Zero means no timeout.
*
* \retval VMK_OK Heap was destroyed successfully.
* \retval VMK_DEATH_PENDING World was killed while waiting and the
* heap was not destroyed.
* \retval VMK_WAIT_INTERRUPTED The wait was interrupted and the heap
* was not destroyed.
* \retval VMK_TIMEOUT The wait timed out and the heap was
* not destroyed.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_HeapDestroySync(vmk_HeapID heap,
vmk_int64 timeoutMS);
/* /*
*********************************************************************** ***********************************************************************
* vmk_HeapFree -- */ /** * vmk_HeapFree -- */ /**

View file

@ -202,6 +202,20 @@ VMK_ReturnStatus vmk_LogRegister(
VMK_ReturnStatus vmk_LogUnregister( VMK_ReturnStatus vmk_LogUnregister(
vmk_LogComponent handle); vmk_LogComponent handle);
/*
***********************************************************************
* vmk_LogHeapAllocSize -- */ /**
*
* \brief Amount of heap space needed per registered log component
*
* \note This function will not block.
*
* \retval Number of bytes to set aside in a heap per log component
*
***********************************************************************
*/
vmk_ByteCount vmk_LogHeapAllocSize(void);
/* /*
*********************************************************************** ***********************************************************************
* vmk_LogGetName -- */ /** * vmk_LogGetName -- */ /**
@ -311,7 +325,7 @@ vmk_int32 vmk_LogGetCurrentLogLevel(
#define vmk_Warning(handle, fmt, args...) \ #define vmk_Warning(handle, fmt, args...) \
vmk_LogLevel(VMK_LOG_URGENCY_WARNING, \ vmk_LogLevel(VMK_LOG_URGENCY_WARNING, \
handle, vmk_LogGetCurrentLogLevel(handle), \ handle, vmk_LogGetCurrentLogLevel(handle), \
"%s: %s:%d:" fmt "\n", vmk_LogGetName(handle), \ "%s: %s:%d: " fmt "\n", vmk_LogGetName(handle), \
__FUNCTION__, __LINE__, ##args) __FUNCTION__, __LINE__, ##args)
/* /*
@ -335,7 +349,7 @@ vmk_int32 vmk_LogGetCurrentLogLevel(
#define vmk_Alert(handle, fmt, args...) \ #define vmk_Alert(handle, fmt, args...) \
vmk_LogLevel(VMK_LOG_URGENCY_ALERT, \ vmk_LogLevel(VMK_LOG_URGENCY_ALERT, \
handle, vmk_LogGetCurrentLogLevel(handle), \ handle, vmk_LogGetCurrentLogLevel(handle), \
"%s: %s:%d:" fmt "\n", vmk_LogGetName(handle), \ "%s: %s:%d: " fmt "\n", vmk_LogGetName(handle), \
__FUNCTION__, __LINE__, ##args) __FUNCTION__, __LINE__, ##args)
/* /*

View file

@ -0,0 +1,358 @@
/* **********************************************************
* Copyright 2012 - 2013 VMware, Inc. All rights reserved.
* **********************************************************/
/*
* @VMKAPIMOD_LICENSE@
*/
/*
***********************************************************************
* Management Interfaces */ /**
* \defgroup Mgmt Management
*
* Interfaces that allow management of vmkapi modules (runtime
* parameterization, notifications to modules from user space and
* to user space from modules).
*
* @{
***********************************************************************
*/
/*
* vmkapi_mgmt.h --
*
* vmkernel declarations for datatypes & functions used for
* enabling per-module management APIs between user-space and
* vmkernel modules.
*/
#ifndef _VMKAPI_MGMT_H_
#define _VMKAPI_MGMT_H_
/** \cond never */
#ifndef VMK_HEADER_INCLUDED_FROM_VMKAPI_H
#error This vmkapi file should never be included directly but only via vmkapi.h
#endif
/** \endcond never */
#include "base/vmkapi_mgmt_types.h"
/** \brief Opaque generic handle allocated by the API */
typedef struct vmkMgmtHandleInt * vmk_MgmtHandle;
/**
***********************************************************************
* vmk_MgmtCleanupFn -- */ /**
*
* \brief Prototype for a management interface's cleanup callback.
*
* \param[in] private Optional cookie data to be used by the callback,
* as was originally provided to vmk_MgmtInit().
*
***********************************************************************
*/
typedef void (*vmk_MgmtCleanupFn)(vmk_uint64 cookie);
/**
***********************************************************************
* vmk_MgmtKeyGetFn -- */ /**
*
* \brief Prototype for get-key function.
*
* \note This prototype is for a module-supplied "get" function
* for fetching a key's value, for a key that was registered
* using vmk_MgmtAddKey.
*
* \param[in] cookie Cookie supplied with vmk_MgmtInit.
* \param[out] keyVal Value of the key that was read. The type of
* pointer this represents depends on the type
* of key that was added using this function.
*
* \retval VMK_OK The 'get' function executed correctly.
* This is not an indicator of the success or failure of
* the operations in the function, but merely that they
* ran.
*
***********************************************************************
*/
typedef VMK_ReturnStatus (*vmk_MgmtKeyGetFn)(vmk_uint64 cookie,
void *keyVal);
/**
***********************************************************************
* vmk_MgmtKeySetFn -- */ /**
*
* \brief Prototype for set-key function.
*
* \note This prototype is for a module-supplied "set" function
* for storing a key's value, for a key that was registered
* using vmk_MgmtAddKey.
*
* \param[in] cookie Cookie supplied with vmk_MgmtKeyValueInit.
* \param[in] keyVal Value of the key to set. The type of
* pointer this represents depends on the type
* of key that was added using this function.
*
* \retval VMK_OK The 'set' function executed correctly.
* This is not an indicator of the success or failure of
* the operations in the function, but merely that they
* ran.
*
***********************************************************************
*/
typedef VMK_ReturnStatus (*vmk_MgmtKeySetFn)(vmk_uint64 cookie,
void *keyVal);
/**
***********************************************************************
* vmk_MgmtInit */ /**
*
* \brief Initialize the kernel side of a user/kernel management API
*
* \note The API passed must have an equivalent signature that is passed
* to the library interface in userland.
*
* \param[in] modId The module ID of the kernel module registering
* the API.
* \param[in] heapId The heap ID to use for allocating temporary
* metadata and parameter passing in event delivery.
* \param[in] sig The API signature of the API being registered.
* Callbacks 0 through VMK_MGMT_RESERVED_CALLBACKS
* are reserved and may not be used.
* \param[in] cleanupFn Optional cleanup function that is executed
* after the last in-flight operation
* concludes. Note that in-flight management
* operations can be going on during a vmk_MgmtDestroy.
* \param[in] cookie A data cookie that will be provided as the
* first argument to all kernel-space callbacks
* and the cleanup function that are invoked.
* \param[in,out] handle The handle that will be allocated for accessing
* this API.
*
* \retval VMK_OK Initialization succeeded.
* \retval VMK_BAD_PARAM Either the modId or signature were invalid.
* \retval VMK_NO_MEMORY Internal metadata for operation could not be
* allocated.
*
***********************************************************************
*/
VMK_ReturnStatus
vmk_MgmtInit(vmk_ModuleID modId,
vmk_HeapID heapId,
vmk_MgmtApiSignature *sig,
vmk_MgmtCleanupFn cleanupFn,
vmk_uint64 cookie,
vmk_MgmtHandle *handle);
/**
***********************************************************************
* vmk_MgmtRegisterInstanceCallbacks */ /**
*
* \brief Register instance-specific management callbacks.
*
* \note This API registers an instance and instance-specific callbacks
* that will be associated with a given management handle. If
* you provide instance-specific callbacks, those callbacks will
* be invoked instead of the default corresponding callbacks that
* were originally registered with the handle. Note that it is
* valid to supply a subset of instance-specific callbacks
* (or even none).
*
* \param[in] handle The management handle that was initialized.
* \param[in] instanceId The unique instance that will have its
* callbacks registered. Must be unique for
* the current handle, and must not be 0.
* \param[in] modId The modId of the module where the
* callbacks reside.
* \param[in] heapId The heapId from the module where the
* callbacks reside.
* \param[in] displayName The name that will be displayed for
* this instance when it's listed.
* \param[in] numCallbacks The number of instance-specific
* callbacks that are being registered. 0
* is valid, if the instance does not
* supply instance-specific callbacks.
* \param[in] callbacks The callback information for each
* instance-specific callback, corresponding
* to callbacks that override those
* registered in the API signature
* for this handle.
*
* \retval VMK_OK Initialization succeeded.
* \retval VMK_BAD_PARAM Parameters couldn't be validated.
* \retval VMK_NO_MEMORY Internal metadata for operation could not be
* allocated.
*
***********************************************************************
*/
VMK_ReturnStatus
vmk_MgmtRegisterInstanceCallbacks(vmk_MgmtHandle handle,
vmk_uint64 instanceId,
vmk_ModuleID modId,
vmk_HeapID heapId,
vmk_Name *displayName,
vmk_uint32 numCallbacks,
vmk_MgmtCallbackInfo *callbacks);
/**
***********************************************************************
* vmk_MgmtUnregisterInstanceCallbacks */ /**
*
* \brief Unregister an instance from being management handle.
*
* \param[in] handle The management handle that was initialized
* and to which this instance is associated.
* \param[in] instanceId The unique instance that was already
* registered for management.
*
* \retval VMK_OK Unregistration succeeded.
* \retval VMK_BAD_PARAM The instance was not already registered.
*
***********************************************************************
*/
VMK_ReturnStatus
vmk_MgmtUnregisterInstanceCallbacks(vmk_MgmtHandle handle,
vmk_uint64 instanceId);
/**
***********************************************************************
* vmk_MgmtDestroy */ /**
*
* \brief Destroy the kernel side of a user/kernel management API
*
* \param[in] handle The handle that was passed and initialized with
* vmk_MgmtInit
*
* \note The heap that was passed to vmk_MgmtInit should not be
* destroyed until all access to the management channel has stopped,
* and thus the cleanup function has run. If you call
* vmk_MgmtDestroy during module-unload, you are assured that the
* management channel is not in use & thus you can safely destroy
* the heap immediately.
*
* \retval VMK_BAD_PARAM The API has already been destroyed or has
* already been requested to be destroyed.
* \retval VMK_OK The API will be destroyed once all in-flight
* operations conclude (may be immediate, if
* none are currently in-flight).
*
***********************************************************************
*/
VMK_ReturnStatus
vmk_MgmtDestroy(vmk_MgmtHandle handle);
/*
***********************************************************************
* vmk_MgmtCallbackInvokeInt --
*
* This is used by vmk_MgmtCallbackInvoke(). VMKAPI clients should
* never call this function directly.
*
***********************************************************************
*/
/** \cond nodoc */
VMK_ReturnStatus
vmk_MgmtCallbackInvokeInt(vmk_MgmtHandle handle,
vmk_uint64 instanceId,
vmk_uint64 callbackId,
vmk_uint32 argCount,
...);
/** \endcond */
/**
***********************************************************************
* vmk_MgmtCallbackInvoke */ /**
*
* \brief Invoke a user-space callback that has zero or more parameters.
* \note The callback will be asynchronously delivered to user-space,
* but only if there currently is a user-space process associated
* with this management handle that is listening for callback
* requests. This call does not block.
* \note Parameters are immediately copied for delivery. Sizes are
* determined by the API signature that was registered with
* vmk_MgmtInit. Additionally, the data cookie that was
* registered with the receiver (in user space) will be provided
* as the first argument to the callback that is delivered in
* user space.
*
* \param[in] handle The handle that was passed and initialized with
* vmk_MgmtInit
* \param[in] instanceId The unique instance ID from which this callback
* is originating. If this is not an instance-
* specific invocation, use VMK_MGMT_NO_INSTANCE_ID.
* \param[in] callbackId The unique ID corresponding to the callback to
* invoke, as registered with the API signature.
* \param[in] ... Pointers to the parameters to copy and pass.
* The number of parameters passed here must match
* the number used by the callback indicated by
* callbackId.
*
* \retval VMK_OK The callback was prepared for delivery. This
does not indicate that it has run, however.
* \retval VMK_BAD_PARAM The callback or number of parameters supplied
* was invalid.
* \retval VMK_NO_MEMORY Temporary storage required to deliver the event
* was unavailable.
* \retval VMK_NOT_FOUND There is no listening user-space process
* running that can receive this callback request.
*
***********************************************************************
*/
#define vmk_MgmtCallbackInvoke( \
/* (vmk_MgmtHandle) */ handle, \
/* (vmk_uint64) */ instanceId, \
/* (vmk_uint64) */ callbackId, \
...) \
vmk_MgmtCallbackInvokeInt(handle, instanceId, callbackId, VMK_UTIL_NUM_ARGS(__VA_ARGS__), ##__VA_ARGS__)
/**
***********************************************************************
* vmk_MgmtAddKey */ /**
*
* \brief Add a key to be managed as a key-value pair.
*
* \note This creates a key-value pair that can be managed using
* the vmkmgmt_keyval utility. The name of the management
* handle that was initialized is the name of the key-value
* instance that would be the "instance" argument to
* vmkmgmt_keyval. For the get and set functions registered
* here, the cookie that is given back is the cookie that
* was initialized with vmk_MgmtInit.
*
* \param[in] handle The handle that was initialized by
* vmk_MgmtInit.
* \param[in] keyType The type of the key being added.
* \param[in] keyName The name of the key being added. Must be
* unique compared to other registered
* keys for this management handle.
* \param[in] getFn The function that will be used to get the key
* value at runtime.
* \param[in] setFn The function that will be used to set the key
* value at runtime.
*
* \note Both the getFn and setFn must be provided.
*
* \retval VMK_OK The key was added.
* \retval VMK_BAD_PARAM A bad parameter was given.
* \retval VMK_NO_MEMORY Memory was not available to allocate the required
* metadata structures.
*
***********************************************************************
*/
VMK_ReturnStatus
vmk_MgmtAddKey(vmk_MgmtHandle handle,
vmk_MgmtKeyType keyType,
vmk_Name *keyName,
vmk_MgmtKeyGetFn getFn,
vmk_MgmtKeySetFn setFn);
#endif /* _VMKAPI_MGMT_H_ */
/** @} */

View file

@ -0,0 +1,284 @@
/* **********************************************************
* Copyright 2012 - 2013 VMware, Inc. All rights reserved.
* **********************************************************/
/*
* @VMKAPIMOD_LICENSE@
*/
/*
*******************************************************************************
* Management Types */ /**
* \addtogroup Mgmt
*
* User-facing interfaces exported by vmkmgmt_lib, for use when communicating
* with vmkapi modules using vmk_Mgmt APIs.
*
* @{
*******************************************************************************
*/
/*
* vmkapi_mgmt_lib.h --
* user-space declarations for datatypes & functions used to interact
* with vmkapi modules that use the vmk_Mgmt APIs. Note that user-space
* management APIs and user-specific types are prefixed with "vmk_MgmtUser",
* even when they may be used to invoke actions in the kernel.
*/
#ifndef _VMKAPI_MGMT_LIB_H_
#define _VMKAPI_MGMT_LIB_H_
/** \cond never */
#ifndef VMK_HEADER_INCLUDED_FROM_VMKAPI_H
#error This vmkapi file should never be included directly but only via vmkapi.h
#endif
/** \endcond never */
#include "base/vmkapi_mgmt_types.h"
/** \brief An opaque handle that is allocated and managed by the library */
typedef struct vmkMgmtUserHandleInt * vmk_MgmtUserHandle;
/**
***********************************************************************
* vmk_MgmtUserInit */ /**
*
* \brief Initialize user-space management of a kernel module.
*
* \note This initializes your application for interaction with a
* kernel module that has an API signature matching the one you
* provide here with vmk_MgmtUserInit. Note that the kernel side
* of the API must be successfully registered with
* vmk_MgmtInit prior to attempting to initialize the
* user-space side. There can be multiple applications or
* threads using vmk_MgmtUserInit for the same API signature,
* but only one kernel module can service that API signature.
*
* \note The signature provided here must be compatible with the
* signature of the API that has been registered with the kernel.
* if "vendor" is specified (non-null) in the signature, a
* connection will only be made if the vendor matches.
*
* \param[in] sig The API signature describing the
* management operations that can be done.
* Must match a signature registered in the
* kernel.
* \param[in] userCookie A data cookie that will be provided as
* the first argument to all user-space
* callbacks.
* \param[out] handle An opaque handle that will be used for
* further interaction with the API.
*
* \retval 0 Initialization succeeded.
* \retval other A UNIX-style error code.
*
***********************************************************************
*/
int
vmk_MgmtUserInit(vmk_MgmtApiSignature *sig,
vmk_uint64 userCookie,
vmk_MgmtUserHandle *handle);
/**
***********************************************************************
* vmk_MgmtUserGetInstances */ /**
*
* \brief Get instance information for all kernel-registered instances.
*
* \note The instanceIds populated in the vmk_MgmtInstances structure
* can be subsequently used to send a callback request to a
* specific instance with vmk_MgmtUserCallbackInvoke
*
* \param[in] handle Management handle that was initialized
* \param[out] instances Current instance information for given handle
*
* \retval 0 Succeeded getting instances.
* \retval other A UNIX-style error code.
*
***********************************************************************
*/
int
vmk_MgmtUserGetInstances(vmk_MgmtUserHandle handle,
vmk_MgmtInstances *instances);
/**
***********************************************************************
* vmk_MgmtUserBegin */ /**
*
* \brief Begin execution of user callbacks.
*
* \note This call creates a separate thread to monitor incoming
* callback requests from the kernel for the given management
* handle and immediately begins execution of those callbacks
* as they arrive.
* \note This is not necessary if your application is not meant to
* handle callbacks delivered from the kernel.
*
*
* param[in] handle Management handle that was initialized
*
* \retval 0 Succeeded initializing callback execution
* \retval other A UNIX-style error code
*
***********************************************************************
*/
int
vmk_MgmtUserBegin(vmk_MgmtUserHandle handle);
/**
***********************************************************************
* vmk_MgmtUserContinue */ /**
*
* \brief Indefinitely continue monitoring and executing incoming kernel
* callback requests in user space.
*
* \note vmk_MgmtUserBegin must have been successfully executed prior
* to calling vmk_MgmtUserContinue.
* \note Invoking vmk_MgmtUserContinue effectively makes the current
* (calling) thread run indefinitely, in a monitoring mode. This
* is typically used by resident CIM providers. To terminate
* monitoring on a particular management handle after
* vmk_MgmtUserBegin or vmk_MgmtUserContinue has been executed,
* vmk_MgmtUserEnd. vmk_MgmtUserContinue does not return until
* vmk_MgmtUserEnd is separately executed on the same handle
* from within the same process. To use vmk_MgmtUserEnd after
* vmk_MgmtUserContinue, you must create a separate pthread that
* will invoke vmk_MgmtUserEnd sometime later after your main
* thread has invoked vmk_MgmtUserContinue.
*
* \param[in] handle Management handle that was initialized
*
* \retval 0 Execution succeeded and was ended without error.
* This will happen at some future moment in time,
* after vmk_MgmtUserEnd has been used.
* \retval Other A UNIX error code. Execution terminated,
* possibly early with error.
*
***********************************************************************
*/
int
vmk_MgmtUserContinue(vmk_MgmtUserHandle handle);
/**
***********************************************************************
* vmk_MgmtUserEnd */ /**
*
* \brief Terminate monitoring and execution of kernel-to-user callbacks.
*
* \note This may be called after either vmk_MgmtUserBegin or
* vmk_MgmtUserContinue.
* \note Because vmk_MgmtUserContinue does not return, a separate
* thread within the same process space is required to invoked
* vmk_MgmtUserEnd. The effect of vmk_MgmtUserEnd will be to
* cease processing of any additional incoming callback requests
* from the kernel, but the management handle will remain open.
* Processing of inbound callback requests from the kernel can
* be resumed if vmk_MgmtUserBegin is subsequently used on the
* given handle.
*
* \param[in] handle Management handle that was initialized.
*
* \retval 0 Execution was successfully ended.
* \retval Other A UNIX-style error code indicating the nature of
* an error that was encountered.
*
***********************************************************************
*/
int
vmk_MgmtUserEnd(vmk_MgmtUserHandle handle);
/**
***********************************************************************
* vmk_MgmtUserDestroy */ /**
*
* \brief Destroy the user side connection to a management handle.
*
* \note This will terminate receiving of callback requests from the
* kernel and terminate the ability to send new callback
* requests to the kernel.
*
* \param[in] handle Management handle that was initialized.
*
* \retval 0 Handle was destroyed completely without error.
* \retval Other A UNIX-style error code indicating the nature
* of the failure. The handle should not be used
* again even after a failure, however.
*
***********************************************************************
*/
int
vmk_MgmtUserDestroy(vmk_MgmtUserHandle handle);
/**
***********************************************************************
* vmk_MgmtUserCallbackInvoke */ /**
*
* \brief From user space, invoke a callback inside the kernel.
*
* \note Parameter handling: For asynchronous callbacks, all
* parameters are internally copied for delivery to the kernel.
* For synchronous callbacks, input and input-output parameters
* are copied internally and delivered to the kernel. For
* input-output and output parameters, such parameters are copied
* from the kernel back to user-space (to the pointer indicated
* by the corresponding parameter given to this function) after
* the callback has executed. In addition to the payload
* parameters passed here, the receiving callback in the kernel
* will be provided the kernel-side data cookie that the
* receiver registered with vmk_MgmtInit and the instanceId
* specificed here. If an instanceId is specified, the callback
* function invoked in the kernel will be the instance-specific
* callback (if it was specified when the instance was added) or
* the default callback function registered with the API
* signature (if no instance-specific callback was specified
* for this callback when the instance was added).
*
* \param[in] handle Management handle that was initialized.
* \param[in] instanceId The unique instance ID to send this callback
* to. If this is not an instance-specific
* invocation, use VMK_MGMT_NO_INSTANCE_ID.
* \param[in] callbackId The unique ID corresponding to the callback
* to invoke, as registered with the API
* signature.
* \param[in] ... A variable list of parameters, each one
* a (void *) pointer to the parameter
* being passed to the callback. The number
* of parameters must match that described for
* the given callbackId when the API signature
* was registered.
* \retval 0 For asynchronous callbacks, this means that the callback
* successfully was queued. For synchronous callbacks,
* this means that the callback has executed completely.
* \retval Other A UNIX-style error code corresponding to the error
* encountered when attempting to queue or execute the
* callback.
* \note The return value is not a indication or return code of the
* callback itself.
*
*/
#define vmk_MgmtUserCallbackInvoke( \
/* (vmk_MgmtHandle *) */ handle, \
/* (vmk_uint64) */ instanceId, \
/* (vmk_uint64) */ callbackId, \
...) \
vmk_MgmtUserCallbackInvokeInt(handle, instanceId, callbackId, VMK_UTIL_NUM_ARGS(__VA_ARGS__), ##__VA_ARGS__)
/*
***********************************************************************
* vmk_MgmtUserCallbackInvokeInt --
*
* This is used by vmk_MgmtUserCallbackInvoke(). VMKAPI clients should
* never call this function directly.
*
***********************************************************************
*/
int
vmk_MgmtUserCallbackInvokeInt(vmk_MgmtUserHandle handle,
vmk_uint64 instanceId,
vmk_uint64 callbackId,
vmk_uint32 argCount,
...);
#endif /* _VMKAPI_MGMT_LIB_H_ */
/** @} */

View file

@ -0,0 +1,228 @@
/* **********************************************************
* Copyright 2012 - 2013 VMware, Inc. All rights reserved.
* **********************************************************/
/*
* @VMKAPIMOD_LICENSE@
*/
/*
*******************************************************************************
* Management Types */ /**
* \addtogroup Mgmt
*
* Types used by user- and kernel-space when interacting with the vmkapi
* management interfaces and library.
*
* @{
*******************************************************************************
*/
/*
* vmkapi_mgmt_types.h --
*
* Interfaces for defining management APIs for vmkernel-based
* modules, which need to be shared with user-space.
*/
#ifndef _VMKAPI_MGMT_TYPES_H_
#define _VMKAPI_MGMT_TYPES_H_
/** \cond never */
#ifndef VMK_HEADER_INCLUDED_FROM_VMKAPI_H
#error This vmkapi file should never be included directly but only via vmkapi.h
#endif
/** \endcond never */
#include "lib/vmkapi_name.h"
#include "lib/vmkapi_revision.h"
/**
* The maximum number of data payload parameters per callback,
* excluding the cookie and instance parameters.
*/
#define VMK_MGMT_MAX_CALLBACK_PARMS 4
/**
* \brief Callback IDs 0 through VMK_MGMT_RESERVED_CALLBACKS inclusive
* are reserved by the system and may not be used by consumers
* of the API.
*/
#define VMK_MGMT_RESERVED_CALLBACKS 15
#define VMK_MGMT_NO_INSTANCE_ID 0
/**
* \brief The type of a key used in a key-value management channel.
*/
typedef enum vmk_MgmtKeyType {
/**
* \brief An 8-byte integer
*/
VMK_MGMT_KEY_TYPE_LONG = 1,
/**
* \brief A 4096-byte (including nul) character string.
*/
VMK_MGMT_KEY_TYPE_STRING = 2,
} vmk_MgmtKeyType;
/**
* \brief The maximum number of bytes in a VMK_MGMT_KEY_TYPE_STRING key.
*/
#define VMK_MGMT_KEY_STRING_MAXLEN 4096
/**
* \brief The maximum number of keys that can be added to a
* vmk_MgmtHandle instance.
*/
#define VMK_MGMT_MAX_KEYS_PER_INSTANCE 32
/**
* \brief The maximum number of instances that can be added to a management handle.
*/
#define VMK_MGMT_MAX_INSTANCES 32
/**
* \brief The location where a callback will execute.
*/
typedef enum vmk_MgmtCallbackLocation {
VMK_MGMT_CALLBACK_KERNEL = 1,
VMK_MGMT_CALLBACK_USER,
} vmk_MgmtCallbackLocation;
/**
* \brief The type of a parameter to a callback
*/
typedef enum vmk_MgmtParm {
/** \brief An input parameter to a callback. The contents of the
* parameter will be copied before invoking the callback.
*/
VMK_MGMT_PARMTYPE_IN = 0,
/**
* \brief An output parameter to a callback. Only valid for
* synchronous callbacks that are executed in the kernel. The
* contents of the parameter will be copied back to the caller
* after the callback has executed.
*/
VMK_MGMT_PARMTYPE_OUT,
/**
* \brief An input-output parameter to a callback. Only valid
* for synchronous callbacks that are executed in the kernel.
* The contents of the parameter will be copied before the
* callback has executed and again copied back to the caller after
* execution.
*/
VMK_MGMT_PARMTYPE_INOUT,
} vmk_MgmtParmType;
/**
* \brief A description of a single callback that is part of an overall API.
*/
typedef struct vmk_MgmtCallbackInfo {
/** \brief The location where the callback runs. */
vmk_MgmtCallbackLocation location;
/**
* \brief A function pointer to the callback.
* A callback function pointer only needs to be provided if this
* signature is being registered where this callback would run. For
* example, if the API is being registered with the kernel, only
* VMK_MGMT_CALLBACK_KERNEL callbacks require a value here.
* Callback functions must not assume that they execute with any kind of
* serialization. If multiple management handle instances specify the same
* callback function, then that callback function can be executed simultaneously.
* By separate callers. If your callback function requires synchronization
* among multiple potential callers, then your callback function must
* implement that synchronization.
*/
void *callback;
/** \brief Indicates if this callback is executed synchronously to the caller.
* As noted for the callback parameter, even if a callback is
* marked "synchronous", a callback could be invoked simultaneously
* by multiple callers. "synchronous" describes the semantics as
* viewed by the caller, not that the callee (the callback) can assume
* that it is invoked atomically.
*/
vmk_Bool synchronous;
/**
* Number of parameters to the callback, excluding the data
* cookie and instance parameters (which are provided as the first two
* arguments). For example, a numParms value of 0 means that the callback
* must take two arguments - the data cookie and instance ID - but no
* payload parameters.
*/
vmk_uint8 numParms;
/**
* \brief The size of each callback, in the order that they are passed.
* \note Excludes the data cookie and instance ID.
*/
int parmSizes[VMK_MGMT_MAX_CALLBACK_PARMS];
/**
* \brief The type of each callback, in the order that they are passed.
* \note Excludes the data cookie and instance ID.
*/
vmk_MgmtParmType parmTypes[VMK_MGMT_MAX_CALLBACK_PARMS];
/**
* \brief An identifier for this callback.
* \note Must be unique within the scope of call callbacks registered
* in an API signature. May not be 0.
*/
vmk_uint64 callbackId;
} vmk_MgmtCallbackInfo;
/**
* \brief The signature for an API being initialized at either the kernel
* or user layer
*/
typedef struct vmk_MgmtApiSignature {
/**
* \brief Version of the API. By default, versions of an API with the
* same major and minor are compatible with each other and will
* allow initialization and communication between the registered
* instances on the user or kernel side. The minor, update,
* and patch numbers will be used for distinguishing minor
* differences that can be shimmed by providers.
*/
vmk_revnum version;
/**
* \brief Name of the API. The version and name must be unique.
*/
vmk_Name name;
/**
* \brief Vendor implementing this side (user or kernel) of the API.
* Optional.
*/
vmk_Name vendor;
/** \brief The number of callbacks this API has. */
int numCallbacks;
/** \brief The information describing each callback */
vmk_MgmtCallbackInfo *callbacks;
} vmk_MgmtApiSignature;
/**
* \brief A description of specific instances registered to a management handle.
* \note An application can get the instances associated with a handle and
* then can subsequently send callbacks to instances using the
* instanceIds as reported in this structure.
*/
typedef struct vmk_MgmtInstances {
/**
* /brief The number of instances managed on this API handle.
*/
vmk_uint8 numInstances;
/**
* /brief The instance IDs that are managed.
*/
vmk_uint64 instanceIds[VMK_MGMT_MAX_INSTANCES];
/**
* \brief The presentation names for each of the instances.
*/
vmk_Name instanceNames[VMK_MGMT_MAX_INSTANCES];
} vmk_MgmtInstances;
#endif /* _VMKAPI_MGMT_TYPES_H_ */
/** @} */

View file

@ -48,7 +48,7 @@
* *
*********************************************************************** ***********************************************************************
*/ */
#define VMK_NAMESPACE_CURRENT_VERSION "v2_1_0_0" #define VMK_NAMESPACE_CURRENT_VERSION "v2_2_0_0"
#endif /* _VMKAPI_MODULE_NS_H_ */ #endif /* _VMKAPI_MODULE_NS_H_ */
/** @} */ /** @} */

View file

@ -53,6 +53,8 @@ typedef vmk_uintptr_t vmk_CPUFlags;
* *
* \note This function will not block. * \note This function will not block.
* *
* \nativedriversdisallowed
*
*********************************************************************** ***********************************************************************
*/ */
void vmk_CPUDisableInterrupts(void); void vmk_CPUDisableInterrupts(void);
@ -66,6 +68,8 @@ void vmk_CPUDisableInterrupts(void);
* *
* \note This function will not block. * \note This function will not block.
* *
* \nativedriversdisallowed
*
*********************************************************************** ***********************************************************************
*/ */
void vmk_CPUEnableInterrupts(void); void vmk_CPUEnableInterrupts(void);
@ -82,6 +86,8 @@ void vmk_CPUEnableInterrupts(void);
* \retval VMK_TRUE Interrupts are enabled on the current CPU. * \retval VMK_TRUE Interrupts are enabled on the current CPU.
* \retval VMK_FALSE Interrupts are disabled on the current CPU. * \retval VMK_FALSE Interrupts are disabled on the current CPU.
* *
* \nativedriversdisallowed
*
*********************************************************************** ***********************************************************************
*/ */
vmk_Bool vmk_CPUHasIntsEnabled(void); vmk_Bool vmk_CPUHasIntsEnabled(void);
@ -93,6 +99,8 @@ vmk_Bool vmk_CPUHasIntsEnabled(void);
* \ingroup Platform * \ingroup Platform
* \brief Assert that interrupts are enabled on the current CPU. * \brief Assert that interrupts are enabled on the current CPU.
* *
* \nativedriversdisallowed
*
*********************************************************************** ***********************************************************************
*/ */
#define VMK_ASSERT_CPU_HAS_INTS_ENABLED() \ #define VMK_ASSERT_CPU_HAS_INTS_ENABLED() \
@ -121,6 +129,8 @@ vmk_Bool vmk_CPUHasIntsEnabled(void);
* *
* \return The current CPU's interrupt flags. * \return The current CPU's interrupt flags.
* *
* \nativedriversdisallowed
*
*********************************************************************** ***********************************************************************
*/ */
vmk_CPUFlags vmk_CPUGetFlags(void); vmk_CPUFlags vmk_CPUGetFlags(void);
@ -134,6 +144,8 @@ vmk_CPUFlags vmk_CPUGetFlags(void);
* *
* \note This function will not block. * \note This function will not block.
* *
* \nativedriversdisallowed
*
*********************************************************************** ***********************************************************************
*/ */
void vmk_CPUSetFlags( void vmk_CPUSetFlags(
@ -200,5 +212,49 @@ static VMK_ALWAYS_INLINE void vmk_CPUMemFenceReadWrite(void)
asm volatile ("mfence" ::: "memory"); asm volatile ("mfence" ::: "memory");
} }
/*
***********************************************************************
* vmk_CPUCacheFlush -- */ /**
*
* \ingroup Platform
* \brief Flushes the cache lines on the local PCPU for the memory
* region specified.
*
* \note If a specific operation required flushing the cache line of
* the local PCPU, both that operation and this call should
* come within the same VMK_WITH_PCPU_DO region.
*
* \param[in] pcpu PCPU ID obtained from VMK_WITH_PCPU_DO.
* \param[in] va Starting virtual address of memory region.
* \param[in] size Size of memory region.
*
* \retval VMK_OK Cache lines successfully flushed.
* \retval VMK_BAD_PARAM An invalid parameter was specified.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_CPUCacheFlush(
vmk_PCPUID pcpu,
vmk_VA va,
vmk_ByteCount size);
/*
***********************************************************************
* vmk_CPUGlobalCacheFlush -- */ /**
*
* \ingroup Platform
* \brief Flushes all modified cache lines on all PCPUs.
*
* \note This function will block.
*
* \note This is an expensive operation that should be used rarely and
* not at all on fast paths.
*
* \retval VMK_OK Cachelines successfully flushed.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_CPUGlobalCacheFlush(void);
#endif /* _VMKAPI_PLATFORM_H_ */ #endif /* _VMKAPI_PLATFORM_H_ */
/* @} */ /* @} */

View file

@ -1,5 +1,5 @@
/* ********************************************************** /* **********************************************************
* Copyright 2004 - 2009 VMware, Inc. All rights reserved. * Copyright 2004 - 2012 VMware, Inc. All rights reserved.
* **********************************************************/ * **********************************************************/
/* /*
@ -216,7 +216,7 @@
DEFINE_VMK_ERR(VMK_MEM_MIN_GT_MEMSIZE, "Memory min exceeds memSize", EINVAL )\ DEFINE_VMK_ERR(VMK_MEM_MIN_GT_MEMSIZE, "Memory min exceeds memSize", EINVAL )\
DEFINE_VMK_ERR(VMK_NO_SUCH_VT, "No virtual terminal for number", ENXIO )\ DEFINE_VMK_ERR(VMK_NO_SUCH_VT, "No virtual terminal for number", ENXIO )\
DEFINE_VMK_ERR(VMK_TOO_MANY_ELEMENTS, "Too many elements for list", E2BIG )\ DEFINE_VMK_ERR(VMK_TOO_MANY_ELEMENTS, "Too many elements for list", E2BIG )\
DEFINE_VMK_ERR(VMK_SHAREDAREA_MISMATCH, "VMM<->VMK shared are mismatch", ENOSYS )\ DEFINE_VMK_ERR(VMK_SHAREDAREA_MISMATCH, "VMM<->VMK shared area mismatch", ENOSYS )\
DEFINE_VMK_ERR(VMK_EXEC_FAILURE, "Failure during exec while original state already lost", ESRCH )\ DEFINE_VMK_ERR(VMK_EXEC_FAILURE, "Failure during exec while original state already lost", ESRCH )\
DEFINE_VMK_ERR(VMK_INVALID_MODULE, "Invalid module", EINVAL )\ DEFINE_VMK_ERR(VMK_INVALID_MODULE, "Invalid module", EINVAL )\
DEFINE_VMK_ERR(VMK_UNALIGNED_ADDRESS, "Address is not aligned on required boundary", EINVAL )\ DEFINE_VMK_ERR(VMK_UNALIGNED_ADDRESS, "Address is not aligned on required boundary", EINVAL )\
@ -349,7 +349,7 @@
DEFINE_VMK_ERR(VMK_MODULE_NONAMESPACE, "Module tried to export a symbol but didn't provide a name space", ENOENT )\ DEFINE_VMK_ERR(VMK_MODULE_NONAMESPACE, "Module tried to export a symbol but didn't provide a name space", ENOENT )\
DEFINE_VMK_ERR(VMK_FS_OBJECT_UNLINKED, "File system object is unlinked", EINVAL )\ DEFINE_VMK_ERR(VMK_FS_OBJECT_UNLINKED, "File system object is unlinked", EINVAL )\
DEFINE_VMK_ERR(VMK_HBR_WIRE_INSTANCE_ABORTED, "Replication instance was aborted", ECANCELED )\ DEFINE_VMK_ERR(VMK_HBR_WIRE_INSTANCE_ABORTED, "Replication instance was aborted", ECANCELED )\
DEFINE_VMK_ERR(VMK_HBR_WIRE_NEED_FULL_SYNC, "Replicated disk needs full sync", EINVAL )\ DEFINE_VMK_ERR(VMK_HBR_WIRE_NEED_FULL_SYNC, "Replicated disk needs full synchronization", EINVAL )\
DEFINE_VMK_ERR(VMK_HBR_WIRE_DISK_SET_MISMATCH, "The set of disks on the replication server doesn't match", EINVAL )\ DEFINE_VMK_ERR(VMK_HBR_WIRE_DISK_SET_MISMATCH, "The set of disks on the replication server doesn't match", EINVAL )\
DEFINE_VMK_ERR(VMK_HBR_WIRE_REQUEST_CHECKSUM_MISMATCH, "The checksum for the replication request was invalid", EINVAL )\ DEFINE_VMK_ERR(VMK_HBR_WIRE_REQUEST_CHECKSUM_MISMATCH, "The checksum for the replication request was invalid", EINVAL )\
DEFINE_VMK_ERR(VMK_HBR_WIRE_RESPONSE_CHECKSUM_MISMATCH, "The checksum for the replication response was invalid", EINVAL )\ DEFINE_VMK_ERR(VMK_HBR_WIRE_RESPONSE_CHECKSUM_MISMATCH, "The checksum for the replication response was invalid", EINVAL )\
@ -362,7 +362,12 @@
DEFINE_VMK_ERR(VMK_EPROTOTYPE, "Invalid protocol for connection", EPROTOTYPE )\ DEFINE_VMK_ERR(VMK_EPROTOTYPE, "Invalid protocol for connection", EPROTOTYPE )\
DEFINE_VMK_ERR(VMK_MODULE_CONSUMED_RESOURCE_COUNT_NOT_ZERO, "Consumed resource count of module is not zero", EBUSY )\ DEFINE_VMK_ERR(VMK_MODULE_CONSUMED_RESOURCE_COUNT_NOT_ZERO, "Consumed resource count of module is not zero", EBUSY )\
DEFINE_VMK_ERR(VMK_HBR_SERVER_DOES_NOT_SUPPORT_REQUEST, "vSphere Replication Server does not support request", EOPNOTSUPP )\ DEFINE_VMK_ERR(VMK_HBR_SERVER_DOES_NOT_SUPPORT_REQUEST, "vSphere Replication Server does not support request", EOPNOTSUPP )\
DEFINE_VMK_ERR(VMK_STALE_FILEHANDLE, "Stale file handle", ESTALE)\ DEFINE_VMK_ERR(VMK_STALE_FILEHANDLE, "Stale file handle", ESTALE )\
DEFINE_VMK_ERR(VMK_VVOL_UNBOUND, "Virtual volume not bound", ENODEV )\
DEFINE_VMK_ERR(VMK_DEVICE_NOT_READY_FAIL_OPEN, "Device open failed with no-retry", EPERM )\
DEFINE_VMK_ERR(VMK_NOT_THIS_DEVICE, "Not for this device", EINVAL )\
DEFINE_VMK_ERR(VMK_IGNORE, "Ignore", EINVAL )\
DEFINE_VMK_ERR(VMK_OBJECT_DESTROYED, "Object is being or has been destroyed.", EINVAL )\
/* --- ADD NEW ERROR CODES ABOVE THIS COMMENT. VMK_GENERIC_LINUX_ERROR must be last. --- */ \ /* --- ADD NEW ERROR CODES ABOVE THIS COMMENT. VMK_GENERIC_LINUX_ERROR must be last. --- */ \
DEFINE_VMK_ERR_AT(VMK_GENERIC_LINUX_ERROR, "Generic service console error", 0x2bad0000, EIO ) DEFINE_VMK_ERR_AT(VMK_GENERIC_LINUX_ERROR, "Generic service console error", 0x2bad0000, EIO )
/* --- Don't add ERR_AT with negative value. --- */ /* --- Don't add ERR_AT with negative value. --- */

View file

@ -30,12 +30,15 @@
/** \brief Known invalid value for a timer */ /** \brief Known invalid value for a timer */
#define VMK_INVALID_TIMER ((vmk_Timer)NULL) #define VMK_INVALID_TIMER ((vmk_Timer)NULL)
/** \brief Known invalid value for a timer queue */
#define VMK_INVALID_TIMER_QUEUE ((vmk_TimerQueue)NULL)
typedef vmk_int64 vmk_TimerRelCycles; typedef vmk_int64 vmk_TimerRelCycles;
typedef vmk_uint64 vmk_TimerCycles; typedef vmk_uint64 vmk_TimerCycles;
typedef vmk_AddrCookie vmk_TimerCookie; typedef vmk_AddrCookie vmk_TimerCookie;
typedef void (*vmk_TimerCallback)(vmk_TimerCookie data);
typedef struct vmk_TimerInt *vmk_Timer; typedef struct vmk_TimerInt *vmk_Timer;
typedef struct vmk_TimerQueueInt *vmk_TimerQueue;
/** /**
* \brief Representation for Time * \brief Representation for Time
@ -45,6 +48,27 @@ typedef struct {
vmk_int64 usec; /* microseconds */ vmk_int64 usec; /* microseconds */
} vmk_TimeVal; } vmk_TimeVal;
/**
* \brief Attributes dictating timer queue behavior
*/
typedef vmk_uint64 vmk_TimerQueueAttributes;
/** normal timer queue */
#define VMK_TIMER_QUEUE_ATTR_NONE (0)
/** low latency timer queue */
#define VMK_TIMER_QUEUE_ATTR_LOW_LATENCY (1 << 0)
/**
* \brief Properties for a new timer queue
*/
typedef struct {
vmk_Name name;
vmk_ModuleID moduleID;
vmk_HeapID heapID;
vmk_TimerQueueAttributes attribs;
} vmk_TimerQueueProps;
/** /**
* \brief Timer Attributes * \brief Timer Attributes
*/ */
@ -54,6 +78,8 @@ typedef vmk_uint64 vmk_TimerAttributes;
#define VMK_TIMER_ATTR_NONE (0) #define VMK_TIMER_ATTR_NONE (0)
/** Periodic timer */ /** Periodic timer */
#define VMK_TIMER_ATTR_PERIODIC (1 << 0) #define VMK_TIMER_ATTR_PERIODIC (1 << 0)
/** Default tolerance value */
#define VMK_TIMER_DEFAULT_TOLERANCE (-1)
/* Convenient time constants */ /* Convenient time constants */
@ -74,6 +100,24 @@ typedef vmk_uint64 vmk_TimerAttributes;
#define VMK_TIMEOUT_UNLIMITED_MS (VMK_UINT32_MAX) #define VMK_TIMEOUT_UNLIMITED_MS (VMK_UINT32_MAX)
/*
***********************************************************************
* vmk_TimerCallback -- */ /**
*
* \brief Callback function invoked when timer fires.
*
* \note This callback is allowed to block; however, ready timers on
* the same vmk_TimerQueue will not fire until the firing timer
* has finished, so blocking in this callback may delay other
* scheduled timers.
*
* \param[in] data vmk_TimerCookie provided when timer scheduled.
*
***********************************************************************
*/
typedef void (*vmk_TimerCallback)(vmk_TimerCookie data);
/* /*
*********************************************************************** ***********************************************************************
* vmk_GetTimerCycles -- */ /** * vmk_GetTimerCycles -- */ /**
@ -286,7 +330,7 @@ void vmk_DelayUsecs(
/* /*
*********************************************************************** ***********************************************************************
* vmk_TimerSchedule -- */ /** * vmk_TimerScheduleCustom -- */ /**
* *
* \brief Schedule a timer * \brief Schedule a timer
* *
@ -300,10 +344,78 @@ void vmk_DelayUsecs(
* system-wide, and exceeding the limit is a fatal error. * system-wide, and exceeding the limit is a fatal error.
* *
* \param[in] moduleID ID of the module to which callback belongs * \param[in] moduleID ID of the module to which callback belongs
* \param[in] queue The timer queue to use for the timer
* \param[in] callback Timer callback. * \param[in] callback Timer callback.
* \param[in] data Argument passed to the timer callback on * \param[in] data Argument passed to the timer callback on
* timeout. * timeout.
* \param[in] timeoutUS Timeout in microseconds. * \param[in] timeoutUS Timeout in microseconds.
* \param[in] toleranceUS Tolerance in microseconds. Indicates a
* request that the timer fire approximately
* no later than the provided value from the
* requested time. The majority of callers
* should specify a tolerance of
* VMK_TIMER_DEFAULT_TOLERANCE and only use
* other values for timers that have strict
* timing requirements.
* \param[in] attributes Additional timer attributes
* \param[in] lockDomain Lock domain in which to check the lock rank.
* Note that if lockDomain is set to invalid
* then rank has to be set to unranked and if
* lockDomain is set to a valid value then
* rank has to contain a valid rank value.
* \param[in] lockRank Rank of the timer
* \param[out] wasPending If rescheduling a timer, was it previously
* pending? (optional)
* \param[out] timer Timer Handle
*
* \retval VMK_NO_RESOURCES Couldn't schedule the timer.
* \retval VMK_OK The timer was successfully scheduled.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_TimerScheduleCustom(
vmk_ModuleID moduleID,
vmk_TimerQueue queue,
vmk_TimerCallback callback,
vmk_TimerCookie data,
vmk_int64 timeoutUS,
vmk_int64 toleranceUS,
vmk_TimerAttributes attributes,
vmk_LockDomainID lockDomain,
vmk_LockRank lockRank,
vmk_Bool *wasPending,
vmk_Timer *timer);
/*
***********************************************************************
* vmk_TimerSchedule -- */ /**
*
* \brief Schedule a timer
*
* The VMKernel can schedule simultaneously a limited number of timers
* for each CPU.
*
* \note This function will not block.
*
* \warning Timers are a limited resource. The VMKernel does not
* guarantee to provide more than 100 concurrent timers per CPU
* system-wide, and exceeding the limit is a fatal error.
*
* \param[in] queue The timer queue to use for the timer
* \param[in] callback Timer callback.
* \param[in] data Argument passed to the timer callback on
* timeout.
* \param[in] timeoutUS Timeout in microseconds.
* \param[in] toleranceUS Tolerance in microseconds. Indicates a
* request that the timer fire approximately
* no later than the provided value from the
* requested time. The majority of callers
* should specify a tolerance of
* VMK_TIMER_DEFAULT_TOLERANCE and only use
* other values for timers that have strict
* timing requirements.
* \param[in] attributes Additional timer attributes * \param[in] attributes Additional timer attributes
* \param[in] lockDomain Lock domain in which to check the lock rank. * \param[in] lockDomain Lock domain in which to check the lock rank.
* Note that if lockDomain is set to invalid * Note that if lockDomain is set to invalid
@ -320,10 +432,11 @@ void vmk_DelayUsecs(
*/ */
VMK_ReturnStatus vmk_TimerSchedule( VMK_ReturnStatus vmk_TimerSchedule(
vmk_ModuleID moduleID, vmk_TimerQueue queue,
vmk_TimerCallback callback, vmk_TimerCallback callback,
vmk_TimerCookie data, vmk_TimerCookie data,
vmk_int64 timeoutUS, vmk_int64 timeoutUS,
vmk_int64 toleranceUS,
vmk_TimerAttributes attributes, vmk_TimerAttributes attributes,
vmk_LockDomainID lockDomain, vmk_LockDomainID lockDomain,
vmk_LockRank lockRank, vmk_LockRank lockRank,
@ -389,9 +502,63 @@ VMK_ReturnStatus vmk_TimerCancel(
* *
*********************************************************************** ***********************************************************************
*/ */
vmk_Bool vmk_TimerIsPending( vmk_Bool vmk_TimerIsPending(
vmk_Timer timer); vmk_Timer timer);
/*
***********************************************************************
* vmk_TimerQueueCreate -- */ /**
*
* \brief Create a timer queue.
*
* \note This function will may block.
*
* \param[in] props Properties of the new timer queue.
*
* \param[out] queue The newly created queue.
*
* \retval VMK_OK The timer queue was created successfuly,
* and can now be used to schedule timers.
*
* \retval VMK_BAD_PARAM Invalid parameters passed into the function.
* Make sure that all fields in the provided
* properties are valid.
*
* \retval VMK_NO_RESOURCES Ran out of resources to create the timer
* queue.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_TimerQueueCreate(
vmk_TimerQueueProps *props,
vmk_TimerQueue *queue);
/*
***********************************************************************
* vmk_TimerQueueDestroy -- */ /**
*
* \brief Destroy a timer queue. All timers in the queue are cancelled.
* Memory for the timer queue and associate timers is released
* back to the heap that the queue was allocated from.
*
* \note This function will may block.
*
* \param[in] queue The queue.
*
* \retval VMK_OK The timer queue is destroyed.
*
*
***********************************************************************
*/
VMK_ReturnStatus vmk_TimerQueueDestroy(
vmk_TimerQueue queue);
#endif /* _VMKAPI_TIME_H_ */ #endif /* _VMKAPI_TIME_H_ */
/** @} */ /** @} */
/** @} */ /** @} */

View file

@ -0,0 +1,192 @@
/* **********************************************************
* Copyright 1998 - 2012VMware, Inc. All rights reserved.
* **********************************************************/
/*
* @VMKAPIMOD_LICENSE@
*/
/*
***********************************************************************
* VersionedAtomic */ /**
* \defgroup VersionedAtomic Version Atomic
*
* \par Versioned atomic synchronization:
* These synchronization macros allow single-writer/many-reader access
* to data, based on Leslie Lamport's paper "Concurrent Reading and
* Writing", Communications of the ACM, November 1977.\n
* \n
* Many-writer/many-reader can be implemented on top of versioned
* atomics by using an additional spin lock to synchronize writers.
* This is preferable for cases where readers are expected to greatly
* outnumber writers.\n
* \n
* Multiple concurrent writers to the version variables are not allowed.
* Even if writers are working on lock-free or disjoint data, the
* version counters are not interlocked for read-modify-write.\n
* \n
* Recursive use of versioned atomics in writers is currently not
* supported.
*
* @{
***********************************************************************
*/
#ifndef _VMKAPI_VERSIONED_ATOMIC_H
#define _VMKAPI_VERSIONED_ATOMIC_H
/** \cond never */
#ifndef VMK_HEADER_INCLUDED_FROM_VMKAPI_H
#error This vmkapi file should never be included directly but only via vmkapi.h
#endif
/** \endcond never */
/**
* \brief Versioned Atomic
*/
typedef struct vmk_VersionedAtomic {
/** version 0 */
volatile vmk_uint32 v0;
/** version 1 */
volatile vmk_uint32 v1;
} VMK_ATTRIBUTE_ALIGN(4) vmk_VersionedAtomic;
/*
***********************************************************************
* vmk_VersionedAtomicInit -- */ /**
*
* \brief Intiialize a versioned atomic
* \param[in] versions Pointer to the versioned atomic to be
* initialized
*
***********************************************************************
*/
static VMK_ALWAYS_INLINE void
vmk_VersionedAtomicInit(vmk_VersionedAtomic *versions)
{
versions->v0 = 0;
versions->v1 = 0;
}
/*
***********************************************************************
* vmk_VersionedAtomicBeginWrite -- */ /**
*
* \brief Writer begins write to protected data
*
* Called by a writer to indicate that the data protected by a given
* atomic version is about to change. Effectively locks out all readers
* until EndWrite is called.
*
* \param[in] versions Pointer to the versioned atomic protecting
* the data
*
***********************************************************************
*/
static VMK_ALWAYS_INLINE void
vmk_VersionedAtomicBeginWrite(vmk_VersionedAtomic *versions)
{
VMK_ASSERT(((vmk_uint64)(&versions->v0) & (sizeof(versions->v0) - 1)) == 0);
VMK_ASSERT(versions->v1 == versions->v0);
versions->v0++;
vmk_CPUMemFenceReadWrite();
}
/*
***********************************************************************
* vmk_VersionedAtomicEndWrite -- */ /**
*
* \brief Writer finishes writing to protected data
*
* Called by a writer after it is done updating shared data. Lets
* pending and new readers proceed on shared data.
*
* \param[in] versions Pointer to the versioned atomic protecting
* the data
*
***********************************************************************
*/
static VMK_ALWAYS_INLINE void
vmk_VersionedAtomicEndWrite(vmk_VersionedAtomic *versions)
{
VMK_ASSERT(((vmk_uint64)(&versions->v1) & (sizeof(versions->v1) - 1)) == 0);
VMK_ASSERT(versions->v1 + 1 == versions->v0);
vmk_CPUMemFenceReadWrite();
versions->v1 = versions->v0;
}
/*
***********************************************************************
* vmk_VersionedAtomicBeginTryRead -- */ /**
*
* \brief Reader tries to read protected data
*
* Called by a reader before it tried to read shared data.
*
* \param[in] versions Pointer to the versioned atomic protecting
* the data
*
* \retval Returns a version number to the reader. This
* version number is required to confirm
* validity of the read operation when reader
* calls vmk_VersionedAtomicEndTryRead.
*
***********************************************************************
*/
static VMK_ALWAYS_INLINE vmk_uint32
vmk_VersionedAtomicBeginTryRead(const vmk_VersionedAtomic *versions)
{
vmk_uint32 readVersion;
readVersion = versions->v1;
vmk_CPUMemFenceReadWrite();
return readVersion;
}
/*
***********************************************************************
* vmk_VersionedAtomicEndTryRead -- */ /**
*
* \brief Reader finished reading protected data
*
* Called by a reader after it finishes reading shared data, to confirm
* validity of the data that was just read, to make sure that a writer
* did not intervene while the read was in progress.
*
* \param[in] versions Pointer to the versioned atomic protecting
* the data
* \param[in] readVersion The version number the reader just read,
* returned by vmk_VersionedAtomicBeginTryRead
*
* \retval VMK_TRUE if the data read between
* vmk_VersionedAtomicBeginTryRead() and this
* call is valid.
* \retval VMK_FALSE otherwise.
*
***********************************************************************
*/
static VMK_ALWAYS_INLINE vmk_Bool
vmk_VersionedAtomicEndTryRead(const vmk_VersionedAtomic *versions,
vmk_uint32 readVersion)
{
vmk_CPUMemFenceReadWrite();
return VMK_LIKELY(versions->v0 == readVersion);
}
#endif //__VMKAPI_VERSIONED_ATOMIC_H
/** @} */

View file

@ -1,5 +1,5 @@
/* ********************************************************** /* **********************************************************
* Copyright 2007 - 2009 VMware, Inc. All rights reserved. * Copyright 2007 - 2012 VMware, Inc. All rights reserved.
* **********************************************************/ * **********************************************************/
/* /*
@ -17,6 +17,15 @@
* system called the World ID. Worlds are blockable contexts; it is safe * system called the World ID. Worlds are blockable contexts; it is safe
* to call functions that may block from a world context. * to call functions that may block from a world context.
* *
* User processes also belong to cartels. A cartel is a group of worlds
* that share certain resources including but not limited to their
* address space. A cartel can be thought of as a user process and the
* individual worlds that make up the cartel can be thought of as user
* threads. Each user world will have a world ID and a cartel ID. Each
* world in a cartel will share the same cartel ID. Note that it is
* possible for a world's world ID and cartel ID to be equal, but
* this can only be true for at most one world in the cartel.
*
*@{ *@{
*********************************************************************** ***********************************************************************
*/ */
@ -30,6 +39,8 @@
#endif #endif
/** \endcond never */ /** \endcond never */
#include "device/vmkapi_vector_types.h"
/** /**
* \brief Event to block on. * \brief Event to block on.
* *
@ -45,11 +56,63 @@ typedef vmk_int32 vmk_WorldID;
#define VMK_INVALID_WORLD_ID ((vmk_WorldID)0) #define VMK_INVALID_WORLD_ID ((vmk_WorldID)0)
/** \brief Special vmk_WorldEventID for a no-event wait
*
* When used as the eventId parameter to vmk_WorldWait(),
* the world will wait without being added to the system's
* internal event queue. This allows for a lighter weight
* synchronization mechanism, though the world sleeping in
* this fashion can be awoken only by vmk_WorldForceWakeup(),
* by a timeout, or if the world is being destroyed.
*/
#define VMK_EVENT_NONE ((vmk_WorldEventID)0)
/** /**
* \brief Indication of unlimited CPU allocation (max) * \brief Indication of unlimited CPU allocation (max)
*/ */
#define VMK_CPU_ALLOC_UNLIMITED ((vmk_uint32) -1) #define VMK_CPU_ALLOC_UNLIMITED ((vmk_uint32) -1)
/**
* \brief Scheduler Class for a World
*
* Worlds of class VMK_WORLD_SCHED_CLASS_QUICK will be scheduled
* to run ahead of worlds of class VMK_WORLD_SCHED_CLASS_DEFAULT.
* Please be careful to use VMK_WORLD_SCHED_CLASS_QUICK only for
* small deferred tasks that must execute promptly.
*
* If unsure of what class to use, pick VMK_WORLD_SCHED_CLASS_DEFAULT.
*/
typedef enum {
/** Default scheduler class for kernel threads. */
VMK_WORLD_SCHED_CLASS_DEFAULT = 1,
/** Scheduler class for kernel threads that must execute prompty. */
VMK_WORLD_SCHED_CLASS_QUICK = 100,
} vmk_WorldSchedClass;
/**
* \brief Properties for creating a new world.
*/
typedef struct vmk_WorldProps {
/** \brief Name associated with this world. */
const char *name;
/** \brief Module ID of the module creating this world. */
vmk_ModuleID moduleID;
/** \brief Function that the world begins executing at creation. */
vmk_WorldStartFunc startFunction;
/** \brief Opaque argument to the startFunction. */
void *data;
/** \brief Scheduler class for the new world. */
vmk_WorldSchedClass schedClass;
} vmk_WorldProps;
/* /*
*********************************************************************** ***********************************************************************
* vmk_WorldCreate -- */ /** * vmk_WorldCreate -- */ /**
@ -59,35 +122,52 @@ typedef vmk_int32 vmk_WorldID;
* *
* \note This function may block. * \note This function may block.
* *
* \warning Code running inside a world should allow the scheduler to * \warning Code running inside a system world can be preempted by
* run as often as possible. This can be achieved by calling * default. Code should be careful not to access Per-PCPU
* vmk_WorldYield. At most code should run 30ms without calling * Storage, or to hold locks of type VMK_SPINLOCK_IRQ, for
* vmk_WorldYield. * a period time exceeding 10us - since these acquisitions
* block preemption.
* *
* \param[in] moduleID Module on whose behalf the world is running. * \param[in] props Properties of this world.
* \param[in] name A string that describes the world. The name
* will show up as debug information.
* \param[in] startFunction Function that the world begins executing
* on creation.
* \param[in] data Argument to be passed to startFunction.
* \param[out] worldId World ID associated with the newly * \param[out] worldId World ID associated with the newly
* created world. May be set to NULL if * created world. If caller sets this
* the caller does not need the World ID. * poitner to NULL, then the World ID is
* not returned.
* *
* \retval VMK_OK World created. * \retval VMK_OK World created.
* \retval VMK_NO_MEMORY Ran out of memory. * \retval VMK_NO_MEMORY Ran out of memory.
* \retval VMK_DEATH_PENDING World is in the process of dying. * \retval VMK_DEATH_PENDING World is in the process of dying.
* \retval VMK_NO_MODULE_HEAP The module's heap is not set. * \retval VMK_NO_MODULE_HEAP The module's heap is not set.
* \retval VMK_BAD_PARAM The priority specified is in the
* properties is invalid.
* *
*********************************************************************** ***********************************************************************
*/ */
VMK_ReturnStatus vmk_WorldCreate( VMK_ReturnStatus vmk_WorldCreate(vmk_WorldProps *props,
vmk_ModuleID moduleID,
const char *name,
vmk_WorldStartFunc startFunction,
void *data,
vmk_WorldID *worldId); vmk_WorldID *worldId);
/*
***********************************************************************
* vmk_WorldDestroy -- */ /**
*
* \ingroup Worlds
* \brief Destroy a world created by vmk_WorldCreate.
*
* \note This function may block.
*
* \note This function does not wait for the world to actually die.
* Use vmk_WorldWaitForDeath() to wait for death.
*
* \param[in] worldID vmk_WorldID of the world to destroy.
*
* \retval VMK_OK Kill was successfully posted.
* \retval VMK_NOT_FOUND Specified worldID was not found.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_WorldDestroy(
vmk_WorldID worldID);
/* /*
*********************************************************************** ***********************************************************************
* vmk_WorldExit -- */ /** * vmk_WorldExit -- */ /**
@ -121,6 +201,42 @@ void vmk_WorldExit(VMK_ReturnStatus status);
vmk_WorldID vmk_WorldGetID( vmk_WorldID vmk_WorldGetID(
void); void);
/*
***********************************************************************
* vmk_WorldGetCartelID -- */ /**
*
* \ingroup Worlds
* \brief Get the Cartel ID of the current world.
*
* \note This function will not block.
*
* \return WorldID of the cartel of the currently running world that
* this call was invoked from or VMK_INVALID_WORLD_ID if
* this call was not invoked from a user world context.
*
***********************************************************************
*/
vmk_WorldID vmk_WorldGetCartelID(
void);
/*
***********************************************************************
* vmk_WorldIDToCartelID -- */ /**
*
* \ingroup Worlds
* \brief Get the Cartel ID of the specified world.
*
* \note This function will not block.
*
* \return WorldID of the cartel of the provided world ID or
* VMK_INVALID_WORLD_ID if the provided world is not a user
* world context.
*
***********************************************************************
*/
vmk_WorldID vmk_WorldIDToCartelID(
vmk_WorldID worldID);
/* /*
*********************************************************************** ***********************************************************************
* vmk_WorldAssertIsSafeToBlockInt -- * vmk_WorldAssertIsSafeToBlockInt --
@ -168,16 +284,19 @@ vmk_WorldAssertIsSafeToBlock(
* *
* \note This function may block. * \note This function may block.
* *
* \note Spurious wakeups are possible * \note Spurious wakeups are possible. Specifially, users of this
* API must always verify that the condition on which they
* are waiting has actually occurred before taking action.
* *
* \note For worlds holding IRQ locks, use vmk_WorldWaitIRQ(). * \param[in] eventId Either a system wide unique identifier for the
* * event to sleep on, or VMK_EVENT_NONE. When
* \param[in] eventId System wide unique identifier of the event * VMK_EVENT_NONE is specified, the world can be
* to sleep on. * awoken only by vmk_WorldForceWakeup(), by a
* \param[in] lock Lock of type VMK_SPINLOCK or VMK_SPINLOCK_IRQ * timeout, or if the world is being destroyed.
* to release before descheduling the world. * \param[in] lock Lock of type VMK_SPINLOCK to release before
* VMK_LOCK_INVALID indicates that no lock needs * descheduling the world. VMK_LOCK_INVALID
* to be released before descheduling the world. * indicates that no lock needs to be released
* before descheduling the world.
* \param[in] timeoutMS Number of milliseconds before timeout * \param[in] timeoutMS Number of milliseconds before timeout
* VMK_TIMEOUT_UNLIMITED_MS indicates that the * VMK_TIMEOUT_UNLIMITED_MS indicates that the
* caller wants to block forever. * caller wants to block forever.
@ -213,63 +332,6 @@ VMK_ReturnStatus vmk_WorldWait(
const char *reason); const char *reason);
/*
***********************************************************************
* vmk_WorldWaitIRQ -- */ /**
*
* \brief Deschedule a World holding an IRQ Lock until awakened or until
* the specified timeout expires.
*
* \note This function may block.
*
* \note Spurious wakeups are possible
*
* \note For worlds holding non-IRQ locks, use vmk_WorldWait().
*
* \param[in] eventId System wide unique identifier of the event
* to sleep on.
* \param[in] lock Lock of type VMK_SPINLOCK or VMK_SPINLOCK_IRQ
* to release before descheduling the world.
* VMK_LOCK_INVALID indicates that no lock needs
* to be released before descheduling the world.
* \param[in] irql IRQ level of lock provided by
* vmk_SpinlockLockIRQ().
* \param[in] timeoutMS Number of milliseconds before timeout
* VMK_TIMEOUT_UNLIMITED_MS indicates that the
* caller wants to block forever.
* VMK_TIMEOUT_NONBLOCKING is not a valid value
* in this context.
* \param[in] reason A short string that explains the reason for
* the vmk_WorldWait call.
*
* \retval VMK_OK World was descheduled and awoken by a
* vmk_WorldWakeup on eventId.
* \retval VMK_BAD_PARAM World was not descheduled because a
* provided parameter was invalid. If a
* lock was provided then it was not
* released.
* \retval VMK_TIMEOUT World was descheduled and awoken
* because of timeout expiration.
* \retval VMK_DEATH_PENDING World was descheduled and awoken
* because the world is dying and being
* reaped by the scheduler. The caller is
* expected to return as soon as possible.
* \retval VMK_WAIT_INTERRUPTED World was descheduled and awoken for
* some other reason not specified by
* previous return codes. The caller is
* allowed to re-enter vmk_WorldWait.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_WorldWaitIRQ(
vmk_WorldEventID eventId,
vmk_Lock lock,
vmk_LockIRQL irql,
vmk_uint32 timeoutMS,
const char *reason);
/* /*
*********************************************************************** ***********************************************************************
* vmk_WorldWakeup -- */ /** * vmk_WorldWakeup -- */ /**
@ -289,6 +351,35 @@ VMK_ReturnStatus vmk_WorldWaitIRQ(
VMK_ReturnStatus vmk_WorldWakeup( VMK_ReturnStatus vmk_WorldWakeup(
vmk_WorldEventID eventId); vmk_WorldEventID eventId);
/*
***********************************************************************
* vmk_WorldForceWakeup -- */ /**
*
* \ingroup Worlds
* \brief Wake up a specific world directly, regardless of what
* event it is waiting on.
*
* \note This function may block.
*
* \note A forced wakeup is special, in that the wakeup it generates
* is "stateful" when used in conjuction with VMK_EVENT_NONE.
* Specifically, if a world is not waiting when a forced wakeup
* is generated, then the wakeup goes pending. If the world
* then attempts to wait on VMK_EVENT_NONE, the world will
* not sleep (and the pending is cleared).
*
* \param[in] worldID World ID of the world to wake up.
*
* \retval VMK_OK The world was awoken.
* \retval VMK_NOT_FOUND The world was not found to need wakeup.
* \retval VMK_INVALID_WORLD The world ID did not correspond to an
* existing world.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_WorldForceWakeup(
vmk_WorldID worldID);
/* /*
*********************************************************************** ***********************************************************************
* vmk_WorldSleep -- */ /** * vmk_WorldSleep -- */ /**
@ -414,7 +505,110 @@ vmk_uint32 vmk_WorldsMax(void);
* *
*********************************************************************** ***********************************************************************
*/ */
VMK_ReturnStatus vmk_WorldWaitForDeath(vmk_WorldID worldID); VMK_ReturnStatus vmk_WorldWaitForDeath(
vmk_WorldID worldID);
/*
***********************************************************************
* vmk_WorldInterruptSet -- */ /**
*
* \brief Sets an interrupt association for the specified world.
*
* Interrupts will be delivered to the same PCPU that this world is
* running on.
*
* \note This function will not block.
*
* \param[in] worldID ID of the world to set interrupt
* association for.
* \param[in] intrCookie Interrupt cookie previously retrieved via
* vmk_IntrRegister
*
* \retval VMK_OK The vector association has been set.
* \retval VMK_BAD_PARAM The specified vector is invalid.
* \retval VMK_LIMIT_EXCEEDED The specified vector cannot be added.
* \retval VMK_INVALID_WORLD The specified world id was invalid.
* \retval VMK_FAILURE The interrupt association cannot be set.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_WorldInterruptSet(
vmk_WorldID worldID,
vmk_IntrCookie intrCookie);
/*
***********************************************************************
* vmk_WorldInterruptUnset -- */ /**
*
* \ingroup Worlds
* \brief Unsets an interrupt association for the specified world.
*
* \note This function will not block.
*
* \param[in] worldID ID of the world to unset interrupt
* association for.
* \param[in] intrCookie Interrupt cookie previously retrieved via
* vmk_IntrRegister
*
* \retval VMK_OK The interrupt association has been unset.
* \retval VMK_NOT_FOUND The interrupt is currently not associated
* with the world.
* \retval VMK_INVALID_WORLD The specified world id was invalid.
* \retval VMK_FAILURE The interrupt association cannot be unset.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_WorldInterruptUnset(
vmk_WorldID worldID,
vmk_IntrCookie intrCookie);
/*
***********************************************************************
* vmk_WorldRelationAdd -- */ /**
*
* \brief Add a relationship between two worlds
*
* This interface should be used to give a hint to the scheduler that there is a
* communication flow from world A to world B. This is useful for multi-threaded
* producer-consumer implementations. World A would equal the producer and world
* B would equal the consumer. If both worlds can be a producer and consumer
* then the interface should be called twice.
* Establishing a relationship between worlds is an important performance
* optimization and should always be done for worlds that are part of a hot
* path.
*
* \note This function might block.
*
* \param[in] worldA ID of the world initiating the communication.
* \param[in] worldB ID of the world receiving the communication.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_WorldRelationAdd(
vmk_WorldID worldA,
vmk_WorldID worldB);
/*
***********************************************************************
* vmk_WorldRelationRemove -- */ /**
*
* \brief Remove a relationship between two worlds
*
* The relationship must have previously been set through vmk_WorldRelationAdd.
*
* \note This function might block.
*
* \param[in] worldA ID of the world initiating the communication.
* \param[in] worldB ID of the world receiving the communication.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_WorldRelationRemove(
vmk_WorldID worldA,
vmk_WorldID worldB);
#endif /* _VMKAPI_WORLD_H_ */ #endif /* _VMKAPI_WORLD_H_ */
/** @} */ /** @} */

View file

@ -0,0 +1,96 @@
/* **********************************************************
* Copyright 2012 VMware, Inc. All rights reserved.
* **********************************************************/
/*
* @VMKAPIMOD_LICENSE@
*/
/*
******************************************************************************
* Worlds */ /**
*
* \addtogroup Core
* @{
* \addtogroup Worlds
* @{
* \defgroup Deprecated Deprecated APIs
* @{
*
******************************************************************************
*/
#ifndef _VMKAPI_WORLDS_DEPRECATED_H_
#define _VMKAPI_WORLDS_DEPRECATED_H_
/** \cond never */
#ifndef VMK_HEADER_INCLUDED_FROM_VMKAPI_H
#error This vmkapi file should never be included directly but only via vmkapi.h
#endif
/** \endcond never */
/*
***********************************************************************
* vmk_WorldWaitIRQ -- */ /**
*
* \brief Deschedule a World holding an IRQ Lock until awakened or until
* the specified timeout expires.
*
* \deprecated
*
* \note This function may block.
*
* \note Spurious wakeups are possible
*
* \note For worlds holding non-IRQ locks, use vmk_WorldWait().
*
* \param[in] eventId System wide unique identifier of the event
* to sleep on.
* \param[in] lock Lock of type VMK_SPINLOCK or VMK_SPINLOCK_IRQ
* to release before descheduling the world.
* VMK_LOCK_INVALID indicates that no lock needs
* to be released before descheduling the world.
* \param[in] irql IRQ level of lock provided by
* vmk_SpinlockLockIRQ().
* \param[in] timeoutMS Number of milliseconds before timeout
* VMK_TIMEOUT_UNLIMITED_MS indicates that the
* caller wants to block forever.
* VMK_TIMEOUT_NONBLOCKING is not a valid value
* in this context.
* \param[in] reason A short string that explains the reason for
* the vmk_WorldWait call.
*
* \retval VMK_OK World was descheduled and awoken by a
* vmk_WorldWakeup on eventId.
* \retval VMK_BAD_PARAM World was not descheduled because a
* provided parameter was invalid. If a
* lock was provided then it was not
* released.
* \retval VMK_TIMEOUT World was descheduled and awoken
* because of timeout expiration.
* \retval VMK_DEATH_PENDING World was descheduled and awoken
* because the world is dying and being
* reaped by the scheduler. The caller is
* expected to return as soon as possible.
* \retval VMK_WAIT_INTERRUPTED World was descheduled and awoken for
* some other reason not specified by
* previous return codes. The caller is
* allowed to re-enter vmk_WorldWait.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_WorldWaitIRQ(
vmk_WorldEventID eventId,
vmk_Lock lock,
vmk_LockIRQL irql,
vmk_uint32 timeoutMS,
const char *reason);
#endif
/** @} */
/** @} */
/** @} */

View file

@ -40,8 +40,9 @@ typedef vmk_uint32 vmk_WorldletID;
/** \cond nodoc */ /** \cond nodoc */
#define VMK_WDT_OPT_LIST(action) \ #define VMK_WDT_OPT_LIST(action) \
action(WDT_OPT_FORCE_IPI_DISPATCH, "force IPI dispatch", ForceIPIDispatch) \ action(WDT_OPT_FORCE_IPI_DISPATCH, "force IPI dispatch", ForceIPIDispatch) \
action(WDT_OPT_NON_INTERFERING, "ignore interference effect", NonInterfering)\ action(WDT_OPT_NON_INTERFERING, "ignore interference effect", NonInterfering) \
action(WDT_OPT_ACTION_AFFINITY, "action affinity", ActionAffinity) action(WDT_OPT_ACTION_AFFINITY, "action affinity", ActionAffinity) \
action(WDT_OPT_ENABLED_VMKSTATS, "enable vmkstats", EnableVmkstats)
#define VMK_WDT_OPT_LIST_POPULATE(name, ignore1, ignore2) \ #define VMK_WDT_OPT_LIST_POPULATE(name, ignore1, ignore2) \
/** \brief Option name */ VMK_##name, /** \brief Option name */ VMK_##name,

View file

@ -34,6 +34,7 @@
*/ */
#define VMK_SERVICE_ACCT_NAME_KERNEL "kernel" #define VMK_SERVICE_ACCT_NAME_KERNEL "kernel"
#define VMK_SERVICE_ACCT_NAME_SCSI "scsi" #define VMK_SERVICE_ACCT_NAME_SCSI "scsi"
#define VMK_SERVICE_ACCT_NAME_NET "net"
/** /**
* \ingroup Accounting * \ingroup Accounting

View file

@ -1,5 +1,5 @@
/*************************************************************************** /***************************************************************************
* Copyright 2010 VMware, Inc. All rights reserved. * Copyright 2010,2012 VMware, Inc. All rights reserved.
***************************************************************************/ ***************************************************************************/
/* /*
@ -30,56 +30,6 @@ typedef struct vmkBusType* vmk_BusType;
/** \brief A null bustype handle. */ /** \brief A null bustype handle. */
#define VMK_BUSTYPE_NONE ((vmk_BusType)0) #define VMK_BUSTYPE_NONE ((vmk_BusType)0)
/** \brief Properties of a bus type needed for registration. */
typedef struct {
/** Module registering the bustype */
vmk_ModuleID moduleID;
/** Name of bustype */
vmk_Name name;
} vmk_BusTypeProps;
/*
***********************************************************************
* vmk_BusTypeRegister -- */ /**
*
* \brief Register a bus type with the device subsystem.
*
* \note This function will not block.
*
* \param[in] busProps Bus type description data.
* \param[out] busHandle Handle to registered bus type.
*
* \retval VMK_OK Success.
* \retval VMK_EXISTS Bus type is already registered.
* \retval VMK_NO_MEMORY Unable to allocate memory for bus type handle.
* \retval VMK_BAD_PARAM Input parameter is invalid.
*
***********************************************************************
*/
VMK_ReturnStatus
vmk_BusTypeRegister(vmk_BusTypeProps *busProps,
vmk_BusType *busHandle);
/*
***********************************************************************
* vmk_BusTypeUnregister -- */ /**
*
* \brief Unregister a bus type.
*
* \note This function will not block.
*
* \param[in] busHandle Handle to registered bus type.
*
* \retval VMK_OK Success
* \retval VMK_BAD_PARAM No bus type object matching given handle.
*
***********************************************************************
*/
VMK_ReturnStatus
vmk_BusTypeUnregister(vmk_BusType busHandle);
/* /*
*********************************************************************** ***********************************************************************
* vmk_BusTypeFind -- */ /** * vmk_BusTypeFind -- */ /**

View file

@ -97,6 +97,10 @@ void _vmk_PCPURelease(vmk_PCPUID pcpu,
* \note Callers are responsible for surrendering the PCPU by calling * \note Callers are responsible for surrendering the PCPU by calling
* VMK_END_WITH_PCPU as quickly as possible * VMK_END_WITH_PCPU as quickly as possible
* *
* \note No locks may be acquired in a VMK_WITH_PCPU_DO / VMK_END_WITH_PCPU
* block. If any locks are required, acquire them before entering the PCPU
* region.
*
****************************************************************************** ******************************************************************************
*/ */
#define VMK_WITH_PCPU_DO(_pcpu) \ #define VMK_WITH_PCPU_DO(_pcpu) \

View file

@ -1,5 +1,5 @@
/*************************************************************************** /***************************************************************************
* Copyright 2007 - 2009 VMware, Inc. All rights reserved. * Copyright 2007 - 2013 VMware, Inc. All rights reserved.
***************************************************************************/ ***************************************************************************/
/* /*
@ -23,19 +23,6 @@
#endif #endif
/** \endcond never */ /** \endcond never */
/**
* \brief Opaque device type
*/
typedef struct vmkDevice* vmk_Device;
/** \brief A null device handle. */
#define VMK_DEVICE_NONE ((vmk_Device )0)
/**
* \brief Opaque driver type.
*/
typedef struct vmkDriver* vmk_Driver;
/** /**
* \brief Device identification. * \brief Device identification.
*/ */
@ -44,11 +31,17 @@ typedef struct {
vmk_BusType busType; vmk_BusType busType;
/** Bus-specific address for device */ /** Bus-specific address for device */
char *busAddress; char *busAddress;
/** Length of bus-specific address */ /**
* String length of bus-specific address (excluding terminating NUL).
* The maximum length supported is 511.
*/
vmk_uint32 busAddressLen; vmk_uint32 busAddressLen;
/** Bus-specific identifier for device */ /** Bus-specific identifier for device */
char *busIdentifier; char *busIdentifier;
/** Length of bus-specific identifier */ /**
* String length of bus-specific identifier (excluding terminating NUL).
* The maximum length supported is 63.
*/
vmk_uint32 busIdentifierLen; vmk_uint32 busIdentifierLen;
} vmk_DeviceID; } vmk_DeviceID;
@ -59,13 +52,25 @@ typedef struct {
* \ingroup Device * \ingroup Device
* \brief Remove a device. * \brief Remove a device.
* *
* This callback is invoked only on devices in an unclaimed state.
* A device may be removed for operations such as system shutdown,
* driver unload, or explicit device removal.
*
* Driver should carry out any operations required for the physical * Driver should carry out any operations required for the physical
* removal of a device, and unregister the device object using * removal of the device, and the device object must be unregistered
* vmk_DeviceUnregister(). * by calling vmk_DeviceUnregister(). Driver's private data for the
* device, including registeringDriverData, must be freed only after
* successful unregistration of the device.
*
* If the device is not unregistered, this callback may be invoked
* again later.
* *
* \param[in] device Handle to device to be removed. * \param[in] device Handle to device to be removed.
* *
* \retval VMK_OK Success * \retval VMK_OK Device unregistered successfully.
* \retval VMK_FAILURE Driver could not unregister device.
* All other error codes are treated as
* VMK_FAILURE.
* *
*********************************************************************** ***********************************************************************
*/ */
@ -84,14 +89,16 @@ typedef struct {
* \brief Device registration data. * \brief Device registration data.
*/ */
typedef struct { typedef struct {
/** Module registering this device */ /** Driver registering this device */
vmk_ModuleID moduleID; vmk_Driver registeringDriver;
/** Device identification */ /** Device identification */
vmk_DeviceID *deviceID; vmk_DeviceID *deviceID;
/** Device operations */ /** Device operations */
vmk_DeviceOps *deviceOps; vmk_DeviceOps *deviceOps;
/** Opaque bus-specific data for this device */ /** Opaque data set by registering driver for its private use */
vmk_AddrCookie busDriverData; vmk_AddrCookie registeringDriverData;
/** Opaque data set by registering driver for attaching driver */
vmk_AddrCookie registrationData;
} vmk_DeviceProps; } vmk_DeviceProps;
/* /*
@ -99,12 +106,21 @@ typedef struct {
* vmk_DeviceRegister -- */ /** * vmk_DeviceRegister -- */ /**
* *
* \ingroup Device * \ingroup Device
* \brief Register a device with the device database and get a * \brief Register a device with the device database and get a device
* a device handle back. * handle back.
* *
* This function should be used only by a driver that discovers * A device can be physical (e.g. a PCI device) or logical
* new physical devices on any buses spawned from the device * (e.g. an uplink, or a similar software construct).
* that it is the driver for, e.g. a PCI bridge driver. *
* Devices can be registered only from a driver's scan callback.
*
* The '#' character is not permitted in the busAddress of the device,
* except if it is a logical device whose busAddress is generated using
* vmk_LogicalCreateBusAddress.
*
* The registering driver's module heap is used for temporary scratch
* purposes by this service. No memory allocated from this heap will
* persist after vmk_DeviceRegister returns.
* *
* \note This function will not block. * \note This function will not block.
* *
@ -112,11 +128,21 @@ typedef struct {
* \param[in] parent Parent device handle. * \param[in] parent Parent device handle.
* \param[out] newDevice New device handle. * \param[out] newDevice New device handle.
* *
* \retval VMK_BAD_PARAM Device ID is NULL or incomplete.
* \retval VMK_EXISTS Device with this data already registered.
* \retval VMK_NO_MEMORY Unable to allocate memory for device handle.
* \retval VMK_OK Successfully registered device. * \retval VMK_OK Successfully registered device.
* * \retval VMK_NOT_SUPPORTED Registration not from a driver's scan
* callback.
* \retval VMK_BAD_PARAM Device ID is NULL or incomplete.
* \retval VMK_BAD_PARAM The deviceID's busAddress is improperly
* formatted for the specified bus type.
* \retval VMK_EXISTS Device with this data already registered.
* \retval VMK_NO_MEMORY Unable to allocate memory for device
* handle.
* \retval VMK_NO_MODULE_HEAP The registeringDriver's module
* (specified in deviceProps) has no heap.
* \retval VMK_NAME_TOO_LONG The deviceID's busAddressLen is greater
* then the system defined maximum.
* \retval VMK_NAME_TOO_LONG The deviceID's busIdentifierLen is
* greater then the system defined maximum.
*********************************************************************** ***********************************************************************
*/ */
@ -130,19 +156,20 @@ vmk_DeviceRegister(vmk_DeviceProps *deviceProps,
* vmk_DeviceUnregister -- */ /** * vmk_DeviceUnregister -- */ /**
* *
* \ingroup Device * \ingroup Device
* \brief Remove a device from the device database. * \brief Unregister a device from the device database.
* *
* Devices should typically be unregistered only from the device * A device must be unregistered only from its device remove callback
* remove callback. * provided by the registering driver.
* *
* \note This function will not block. * \note This function will not block.
* *
* \param[in] device Device handle. * \param[in] device Device handle.
* *
* \retval VMK_OK Successfully unregistered device. * \retval VMK_OK Successfully unregistered device.
* \retval VMK_NOT_SUPPORTED Unregistration was not from the device's
* remove callback.
* \retval VMK_BAD_PARAM Device handle is invalid. * \retval VMK_BAD_PARAM Device handle is invalid.
* \retval VMK_BUSY Device has references. Will be freed after * \retval VMK_BUSY Device has references or resources allocated.
* last reference is released.
* *
*********************************************************************** ***********************************************************************
*/ */
@ -158,15 +185,19 @@ vmk_DeviceUnregister(vmk_Device device);
* *
* \note This function will not block. * \note This function will not block.
* *
* \param[in] heap Heap from which device ID should be allocated.
* \param[in] device Device handle. * \param[in] device Device handle.
* \param[out] devID Device identification data. * \param[out] devID Device identification data.
* *
* \retval VMK_OK Successfully returned device id. * \retval VMK_OK Successfully returned device id.
* \retval VMK_BAD_PARAM Device handle is invalid.
* \retval VMK_NO_MEMORY Unable to allocate memory for device ID.
* *
*********************************************************************** ***********************************************************************
*/ */
VMK_ReturnStatus VMK_ReturnStatus
vmk_DeviceGetDeviceID(vmk_Device device, vmk_DeviceGetDeviceID(vmk_HeapID heap,
vmk_Device device,
vmk_DeviceID **devID); vmk_DeviceID **devID);
/* /*
@ -174,10 +205,11 @@ vmk_DeviceGetDeviceID(vmk_Device device,
* vmk_DevicePutDeviceID -- */ /** * vmk_DevicePutDeviceID -- */ /**
* *
* \ingroup Device * \ingroup Device
* \brief Return a handle to device identification data. * \brief Release device identification data.
* *
* \note This function will not block. * \note This function will not block.
* *
* \param[in] heap Heap from which device ID was allocated.
* \param[in] devID Device identification data. * \param[in] devID Device identification data.
* *
* \retval VMK_OK Successfully released device id data. * \retval VMK_OK Successfully released device id data.
@ -185,120 +217,96 @@ vmk_DeviceGetDeviceID(vmk_Device device,
*********************************************************************** ***********************************************************************
*/ */
VMK_ReturnStatus VMK_ReturnStatus
vmk_DevicePutDeviceID(vmk_DeviceID *devID); vmk_DevicePutDeviceID(vmk_HeapID heap,
vmk_DeviceID *devID);
/* /*
*********************************************************************** ***********************************************************************
* vmk_DeviceGetBusDriverData -- */ /** * vmk_DeviceGetRegisteringDriverData -- */ /**
* *
* \ingroup Device * \ingroup Device
* \brief Get bus-driver data for device. * \brief Get registering driver's private data for device.
* *
* \note This function will not block. * \note This function will not block.
* *
* \param[in] device Device handle. * \param[in] device Device handle.
* \param[out] data Bus-specific data for device. * \param[out] data Registering driver's private data for device.
* *
* \retval VMK_OK Successfully returned device data. * \retval VMK_OK Successfully returned device data.
* \retval VMK_BAD_PARAM Invalid device handle.
* \retval VMK_BAD_PARAM data argument is NULL.
* *
*********************************************************************** ***********************************************************************
*/ */
VMK_ReturnStatus VMK_ReturnStatus
vmk_DeviceGetBusDriverData(vmk_Device device, vmk_DeviceGetRegisteringDriverData(vmk_Device device,
vmk_AddrCookie *data);
/*
***********************************************************************
* vmk_DeviceGetRegistrationData -- */ /**
*
* \ingroup Device
* \brief Get device registration data for attaching driver.
*
* \note This function will not block.
*
* \param[in] device Device handle.
* \param[out] data Device registration data.
*
* \retval VMK_OK Successfully returned device data.
* \retval VMK_BAD_PARAM Invalid device handle.
* \retval VMK_BAD_PARAM data argument is NULL.
*
***********************************************************************
*/
VMK_ReturnStatus
vmk_DeviceGetRegistrationData(vmk_Device device,
vmk_AddrCookie *data); vmk_AddrCookie *data);
/* /*
*********************************************************************** ***********************************************************************
* vmk_DeviceSetFunctionDriverData -- */ /** * vmk_DeviceGetAttachedDriverData -- */ /**
* *
* \ingroup Device * \ingroup Device
* \brief Set function-driver data for device. * \brief Get attached driver's private data for device.
* *
* \note This function will not block. * \note This function will not block.
* *
* \param[in] device Device handle. * \param[in] device Device handle.
* \param[in] data Device data. * \param[out] data Attached driver's private data for device.
*
* \retval VMK_OK Successfully set private data.
*
***********************************************************************
*/
VMK_ReturnStatus
vmk_DeviceSetFunctionDriverData(vmk_Device device,
vmk_AddrCookie data);
/*
***********************************************************************
* vmk_DeviceGetFunctionDriverData -- */ /**
*
* \ingroup Device
* \brief Get function-driver data for device.
*
* \note This function will not block.
*
* \param[in] device Device handle.
* \param[out] data Device data.
* *
* \retval VMK_OK Successfully returned private data. * \retval VMK_OK Successfully returned private data.
* \retval VMK_BAD_PARAM Invalid device handle.
* \retval VMK_BAD_PARAM data argument is NULL.
* *
*********************************************************************** ***********************************************************************
*/ */
VMK_ReturnStatus VMK_ReturnStatus
vmk_DeviceGetFunctionDriverData(vmk_Device device, vmk_DeviceGetAttachedDriverData(vmk_Device device,
vmk_AddrCookie *data); vmk_AddrCookie *data);
/* /*
*********************************************************************** ***********************************************************************
* vmk_DeviceFindDeviceByIdentifier -- */ /** * vmk_DeviceSetAttachedDriverData -- */ /**
* *
* \ingroup Device * \ingroup Device
* \brief Return a reference to the device that matches the bus type & * \brief Set attached driver's private data for device.
* identifier in the given identification data.
* *
* If device identifiers are not unique, this function will return * \note This function will not block.
* the first device found matching the given identifier.
* *
* \note Reference must be released using vmk_DeviceRelease. * \param[in] device Device handle.
* \note This function may block. * \param[in] data Attached driver's private data for device.
* *
* \param[in] deviceID Device identification. * \retval VMK_OK Successfully set private data.
* \param[out] device Reference to device matching requested * \retval VMK_BAD_PARAM Invalid device handle.
* identification.
*
* \retval VMK_OK Successfully returned reference to
* matching device.
* \retval VMK_NOT_FOUND No device with given identification.
* *
*********************************************************************** ***********************************************************************
*/ */
VMK_ReturnStatus VMK_ReturnStatus
vmk_DeviceFindDeviceByIdentifier(vmk_DeviceID *deviceID, vmk_DeviceSetAttachedDriverData(vmk_Device device,
vmk_Device *device); vmk_AddrCookie data);
/*
***********************************************************************
* vmk_DeviceFindDeviceByAddress -- */ /**
*
* \ingroup Device
* \brief Return a handle to the device that matches the bus & address
* in the given identification data.
*
* \note Reference must be released using vmk_DeviceRelease.
* \note This function may block.
*
* \param[in] deviceID Device identification.
* \param[out] device Reference to device matching requested
* identification.
*
* \retval VMK_OK Successfully returned reference to
* matching device.
* \retval VMK_NOT_FOUND No device with given identification.
*
***********************************************************************
*/
VMK_ReturnStatus
vmk_DeviceFindDeviceByAddress(vmk_DeviceID *deviceID,
vmk_Device *device);
/* /*
*********************************************************************** ***********************************************************************
@ -322,79 +330,26 @@ vmk_DeviceRelease(vmk_Device device);
/* /*
*********************************************************************** ***********************************************************************
* vmk_DeviceGetParent-- */ /** * vmk_DeviceRequestRescan -- */ /**
* *
* \ingroup Device * \ingroup Device
* \brief Obtain a handle to the parent device of the given device. * \brief Request a rescan of the device to register new children.
* *
* \note Parent device reference must be released using vmk_DeviceRelease. * This call submits a request to the device layer to schedule an
* \note This function may block. * invocation of the device driver's vmk_DriverScanDevice() callback.
* *
* \param[in] device Device handle * \param[in] driver Requesting driver
* \param[out] parent Parent handle * \param[in] device Device to be scanned
* *
* \retval VMK_OK Success * \retval VMK_OK Request accepted.
* \retval VMK_BAD_PARAM Invalid device handle. * \retval VMK_BAD_PARAM Invalid device handle.
* \retval VMK_NOT_FOUND Device has no parent. * \retval VMK_NO_PERMISSION Driver cannot submit this request.
* *
*********************************************************************** ***********************************************************************
*/ */
VMK_ReturnStatus VMK_ReturnStatus
vmk_DeviceGetParent(vmk_Device device, vmk_DeviceRequestRescan(vmk_Driver driver,
vmk_Device *parent); vmk_Device device);
/*
***********************************************************************
* vmk_DeviceGetSibling -- */ /**
*
* \ingroup Device
* \brief Obtain a handle to the immediate sibling device of the given
* device.
*
* This always returns a handle to the immediate sibling of a device
* even if the given device has multiple sibling devices.
*
* \note Sibling device reference must be released using vmk_DeviceRelease.
* \note This function may block.
*
* \param[in] device Device handle
* \param[out] sibling Sibling handle
*
* \retval VMK_OK Success
* \retval VMK_BAD_PARAM Invalid device handle.
* \retval VMK_NOT_FOUND Device has no siblings.
*
***********************************************************************
*/
VMK_ReturnStatus
vmk_DeviceGetSibling(vmk_Device device,
vmk_Device *sibling);
/*
***********************************************************************
* vmk_DeviceGetChild -- */ /**
*
* \ingroup Device
* \brief Obtain a handle to the first child device of the given device.
*
* This always returns a handle to the first child of a device even if
* the given device has multiple child devices.
*
* \note Child device reference must be released using vmk_DeviceRelease.
* \note This function may block.
*
* \param[in] device Device handle
* \param[out] child Child handle
*
* \retval VMK_OK Success
* \retval VMK_BAD_PARAM Invalid device handle.
* \retval VMK_NOT_FOUND Device has no children.
*
***********************************************************************
*/
VMK_ReturnStatus
vmk_DeviceGetChild(vmk_Device device,
vmk_Device *child);
#endif /* _VMKAPI_DEVICE_H_ */ #endif /* _VMKAPI_DEVICE_H_ */
/** @} */ /** @} */

View file

@ -0,0 +1,43 @@
/***************************************************************************
* Copyright 2007 - 2012 VMware, Inc. All rights reserved.
***************************************************************************/
/*
* @VMKAPIMOD_LICENSE@
*/
/*
***********************************************************************
* Devices */ /**
* \defgroup Device Device interface
* @{
***********************************************************************
*/
#ifndef _VMKAPI_DEVICE_TYPES_H_
#define _VMKAPI_DEVICE_TYPES_H_
/** \cond never */
#ifndef VMK_HEADER_INCLUDED_FROM_VMKAPI_H
#error This vmkapi file should never be included directly but only via vmkapi.h
#endif
/** \endcond never */
/**
* \brief Opaque device type
*/
typedef struct vmkDevice* vmk_Device;
/** \brief A null device handle. */
#define VMK_DEVICE_NONE ((vmk_Device )0)
/**
* \brief Opaque driver type.
*/
typedef struct vmkDriver* vmk_Driver;
/** \brief Invalid driver handle. */
#define VMK_DRIVER_NONE ((vmk_Driver)0)
#endif /* _VMKAPI_DEVICE_TYPES_H_ */
/** @} */

View file

@ -600,6 +600,147 @@ VMK_ReturnStatus vmk_DMAUnmapSg(vmk_DMAEngine engine,
vmk_SgOpsHandle sgOps, vmk_SgOpsHandle sgOps,
vmk_SgArray *sg); vmk_SgArray *sg);
/*
***********************************************************************
* vmk_DMAMapElem -- */ /**
*
* \brief Map machine memory of a single MA range to an IOA range.
*
* This call will attempt to map a single machine-address range and
* create a new IO-address address range that maps to it.
*
* \note The input range must not be freed or modified while it
* is mapped or the results are undefined.
*
* \note If the range is simultaneously mapped with multiple DMA
* directions, the contents of the memory the SG array represents
* are undefined.
*
* \note This function will not block.
*
* \param[in] engine A handle representing a DMA engine to map to.
* \param[in] direction Direction of the DMA transfer for the mapping.
* \param[in] in A single SG array element containing a single
* machine addresse range to map for the
* DMA engine.
* \param[in] lastElem Indicates if this is the last element in
* the transfer.
* \param[out] out A single SG array element to hold the mapped
* IO address for the range. Note that this
* may be the same SG element as the element
* passed in depending on choices made by the
* kernel's mapping code.
* \param[out] err If this call fails with VMK_DMA_MAPPING_FAILED,
* additional information about the failure may
* be found here. This may be set to NULL if the
* information is not desired.
*
* \retval VMK_BAD_PARAM The specified DMA engine is invalid.
* \retval VMK_DMA_MAPPING_FAILED The mapping failed because the
* DMA constraints could not be met.
* Additional information about the
* failure can be found in the "err"
* argument.
* \retval VMK_NO_MEMORY There is currently insufficient
* memory available to construct the
* mapping.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_DMAMapElem(vmk_DMAEngine engine,
vmk_DMADirection direction,
vmk_SgElem *in,
vmk_Bool lastElem,
vmk_SgElem *out,
vmk_DMAMapErrorInfo *err);
/*
***********************************************************************
* vmk_DMAFlushElem -- */ /**
*
* \brief Synchronize a DMA mapping for a single IO address range.
*
* This call is used to synchronize data if the CPU needs to read or
* write after an DMA mapping is active on a region of machine memory
* but before the DMA mapping is unmapped.
*
* If the specified memory is DMA-mapped this call must be invoked
* with VMK_DMA_DIRECTION_FROM_MEMORY after CPU writes are complete but
* before any new DMA read transactions occur on the memory.
*
* If the specified memory is DMA-mapped this call must be invoked
* with VMK_DMA_DIRECTION_TO_MEMORY before CPU reads but after
* any write DMA transactions complete on the memory.
*
* DMA map and unmap calls will implicitly perform a flush of the
* element.
*
* The code may flush bytes rounded up to the nearest page or other
* HW-imposed increment.
*
* \note The IO element supplied to this function must be an element
* output from vmk_DMAMapElem or the results of this call are
* undefined.
*
* Do not use this to flush a single element in an SG array
* that was mapped by vmk_DMAMapSg.
*
* \note The original element supplied to this function must be
* the one supplied to vmk_DMAMapElem when the IO element
* was created or the results of this call are undefined.
*
* \note This function will not block.
*
* \param[in] engine A handle representing the DMA engine used
* for the mapping.
* \param[in] direction Direction of the DMA transfer for the
* mapping.
* \param[in] IOElem Scatter-gather element contained the
* IO-address range to flush.
*
* \retval VMK_BAD_PARAM Unknown duration or direction, or
* unsupported direction.
* \retval VMK_INVALID_ADDRESS Memory in the specified element
* is not mapped.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_DMAFlushElem(vmk_DMAEngine engine,
vmk_DMADirection direction,
vmk_SgElem *IOElem);
/*
***********************************************************************
* vmk_DMAUnmapElem -- */ /**
*
* \brief Unmaps previously mapped IO address range.
*
* \note The direction must match the direction at the time of mapping
* or the results of this call are undefined.
*
* \note The element supplied to this function must be one mapped with
* vmk_DMAMapElem or the results of this call are undefined.
*
* \note This function will not block.
*
* \param[in] engine A handle representing a DMA engine
* to unmap from.
* \param[in] direction Direction of the DMA transfer for the
* mapping.
* \param[in] IOElem Scatter-gather element contained the
* IO-address range to unmap.
*
* \retval VMK_BAD_PARAM Unknown direction, or unsupported
* direction.
* \retval VMK_INVALID_ADDRESS One ore more pages in the specified
* machine address range are not mapped.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_DMAUnmapElem(vmk_DMAEngine engine,
vmk_DMADirection direction,
vmk_SgElem *IOElem);
/* /*
*********************************************************************** ***********************************************************************
* vmk_DMAGetAllocAddrConstraint -- */ /** * vmk_DMAGetAllocAddrConstraint -- */ /**

View file

@ -32,30 +32,121 @@
* *
* \brief Attach a device to a driver. * \brief Attach a device to a driver.
* *
* The driver should start driving this device. If the driver is not * This callback is invoked to offer an unclaimed device to a driver.
* capable of driving the given device, an appropriate error should be *
* returned, and the device must be restored to its original state at * The driver should check whether it is capable of driving the given
* entry. * device, and do initial device set up, e.g. allocate device resources.
* If the driver is not capable of driving the given device, the device
* must be restored to its original state at callback entry, and an
* error should be returned.
* *
* \param[in] device Handle to device to be added to the driver. * \param[in] device Handle to device to be added to the driver.
* *
* \retval VMK_OK Success * \retval VMK_OK Driver has claimed this device.
* \retval VMK_FAILURE Driver did not claim this device.
* All other error codes are treated as
* VMK_FAILURE.
* *
*********************************************************************** ***********************************************************************
*/ */
typedef VMK_ReturnStatus (*vmk_DriverAttachDevice)(vmk_Device device); typedef VMK_ReturnStatus (*vmk_DriverAttachDevice)(vmk_Device device);
/*
***********************************************************************
* vmk_DriverStartDevice-- */ /**
*
* \brief Prepare a device to accept IO.
*
* This callback is invoked to place the device in an IO-able state.
* This can be when the device is implicitly in a quiescent state after
* a successful driver attach operation, or at any other time when the
* device has been explicitly put in a quiescent state by the callback
* vmk_DriverQuiesceDevice().
*
* The driver should prepare the device for IO.
*
* \param[in] device Handle to device to prepare for IO.
*
* \retval VMK_OK Driver will accept IO for this device.
* \retval VMK_FAILURE Driver could not prepare device for IO.
* All other error codes are treated as
* VMK_FAILURE.
*
***********************************************************************
*/
typedef VMK_ReturnStatus (*vmk_DriverStartDevice)(vmk_Device device);
/*
***********************************************************************
* vmk_DriverScanDevice -- */ /**
*
* \brief Register any child devices.
*
* This callback is invoked only on devices in IO-able state. It is
* invoked at least once after a device has been successfully attached
* to a driver and started. It may be invoked for other device hotplug
* events as appropriate.
*
* The driver may register new devices by calling vmk_DeviceRegister()
* from this callback. New devices may be registered only from this
* callback.
*
* \param[in] device Handle to device whose children may be registered.
*
* \retval VMK_OK Devices registered, or nothing to register.
* \retval VMK_FAILURE Driver could not register a child device.
* All other error codes are treated as
* VMK_FAILURE.
*
***********************************************************************
*/
typedef VMK_ReturnStatus (*vmk_DriverScanDevice)(vmk_Device device);
/*
***********************************************************************
* vmk_DriverQuiesceDevice -- */ /**
*
* \brief Place a device in quiescent state.
*
* This callback may be invoked any time after a device is in an IO-able
* state, in preparation for operations such as system shutdown, driver
* unload, or device removal.
*
* The driver should complete any IO on the device and flush any device
* caches as necessary to place the device in a quiescent state. When a
* device is in quiescent state, the driver must not report any IO to,
* and will not receive any IO from, any kernel subsystem.
*
* \param[in] device Handle to device to be quiesced.
*
* \retval VMK_OK Device has been quiesced.
* \retval VMK_FAILURE Driver could not quiesce IO on device.
* All other error codes are treated as
* VMK_FAILURE.
*
***********************************************************************
*/
typedef VMK_ReturnStatus (*vmk_DriverQuiesceDevice)(vmk_Device device);
/* /*
*********************************************************************** ***********************************************************************
* vmk_DriverDetachDevice -- */ /** * vmk_DriverDetachDevice -- */ /**
* *
* \brief Detach a device from its driver. * \brief Detach a device from its driver.
* *
* The driver should stop driving this device, and release its resources. * This callback is invoked only on devices in a quiescent state.
* A device may be detached for operations such as system shutdown,
* driver unload, or device removal.
* *
* \param[in] device Handle to device to be removed from the driver. * The driver should stop driving this device, and undo all device setup
* performed in vmk_DriverAttachDevice. E.g. release device resources.
* *
* \retval VMK_OK Success * \param[in] device Handle to device to be detached.
*
* \retval VMK_OK Device has been released.
* \retval VMK_FAILURE Driver could not detach itself from device.
* All other error codes are treated as
* VMK_FAILURE.
* *
*********************************************************************** ***********************************************************************
*/ */
@ -64,41 +155,23 @@ typedef VMK_ReturnStatus (*vmk_DriverDetachDevice)(vmk_Device device);
/* /*
*********************************************************************** ***********************************************************************
* vmk_DriverQuiesceDevice -- */ /** * vmk_DriverForgetDevice-- */ /**
* *
* \brief Quiesce a device. * \brief Mark a device as inaccessible.
* *
* This callback is invoked in preparation for device removal or * This callback is a notification. It may be invoked at any time to
* system shutdown. The driver should complete any IO on the device * notify the driver that a device is inaccessible, so that the driver
* and flush any device caches as necessary to put the device in a * does not wait indefinitely for any subsequent device operations.
* quiescent state.
* *
* \param[in] device Handle to device to be quiesced. * The driver must note that the device is inaccessible. The driver must
* return successfully, in deterministic time, on any subsequent device
* callbacks, e.g. vmk_DriverQuiesceDevice, vmk_DriverDetachDevice.
* *
* \retval VMK_OK Success * \param[in] device Handle to device that is inaccessible.
* *
*********************************************************************** ***********************************************************************
*/ */
typedef VMK_ReturnStatus (*vmk_DriverQuiesceDevice)(vmk_Device device); typedef void (*vmk_DriverForgetDevice)(vmk_Device device);
/*
***********************************************************************
* vmk_DriverScanDevice -- */ /**
*
* \brief Scan a device for new children and register them.
*
* Only bus drivers will typically need to implement this entry.
* This function is called at least once after a device has been
* successfully attached to a driver. It may be called at other
* device hotplug events as appropriate.
*
* \param[in] device Handle to device to scan.
*
* \retval VMK_OK Success
*
***********************************************************************
*/
typedef VMK_ReturnStatus (*vmk_DriverScanDevice)(vmk_Device device);
/** /**
* \brief Driver operations. * \brief Driver operations.
@ -110,8 +183,12 @@ typedef struct {
vmk_DriverScanDevice scanDevice; vmk_DriverScanDevice scanDevice;
/** \brief Detach a device from its driver */ /** \brief Detach a device from its driver */
vmk_DriverDetachDevice detachDevice; vmk_DriverDetachDevice detachDevice;
/** \brief Quiesce a device for system shutdown */ /** \brief Quiesce a device */
vmk_DriverQuiesceDevice quiesceDevice; vmk_DriverQuiesceDevice quiesceDevice;
/** \brief Prepare device for IO */
vmk_DriverStartDevice startDevice;
/** \brief Notify driver of a lost device */
vmk_DriverForgetDevice forgetDevice;
} vmk_DriverOps; } vmk_DriverOps;
/** /**
@ -132,8 +209,11 @@ typedef struct {
*********************************************************************** ***********************************************************************
* vmk_DriverRegister -- */ /** * vmk_DriverRegister -- */ /**
* *
* \brief Register a driver with the driver database and get a * \brief Register a driver with the driver database
* a driver handle back. *
* vmk_DriverRegister must be called from within the driver module's
* initialization routine. A successful registration returns a
* a new driver handle to the caller.
* *
* \note This function will not block. * \note This function will not block.
* *
@ -141,8 +221,11 @@ typedef struct {
* \param[out] driver New driver handle. * \param[out] driver New driver handle.
* *
* \retval VMK_BAD_PARAM Name or ops argument is NULL. * \retval VMK_BAD_PARAM Name or ops argument is NULL.
* \retval VMK_EXISTS A driver by this name is already registered.
* \retval VMK_NO_MEMORY Unable to allocate memory for device handle. * \retval VMK_NO_MEMORY Unable to allocate memory for device handle.
* \retval VMK_NOT_FOUND Unable to find module registering this driver.
* \retval VMK_OK Successfully registered driver. * \retval VMK_OK Successfully registered driver.
* \retval VMK_MODULE_FAILED Call was not from the module's initialization routine.
* *
*********************************************************************** ***********************************************************************
*/ */
@ -156,11 +239,17 @@ vmk_DriverRegister(vmk_DriverProps *driverProps,
* *
* \brief Unregister a driver from the driver database. * \brief Unregister a driver from the driver database.
* *
* vmk_DriverUnregister is normally called from within the driver module's
* cleanup routine. A driver is also permitted to call it from its
* initialization routine if the module fails to initialize (load failure).
*
* \note This function will not block. * \note This function will not block.
* *
* \param[in] driver Driver handle * \param[in] driver Driver handle
* *
* \retval VMK_OK Successfully unregistered driver. * \retval VMK_OK Successfully unregistered driver.
* \retval VMK_MODULE_FAILED Call was not from the module's cleanup or
* initialization routines.
* *
*********************************************************************** ***********************************************************************
*/ */
@ -180,6 +269,7 @@ vmk_DriverUnregister(vmk_Driver driver);
* *
* \retval VMK_OK Successfully returned driver private data. * \retval VMK_OK Successfully returned driver private data.
* \retval VMK_BAD_PARAM Invalid driver handle. * \retval VMK_BAD_PARAM Invalid driver handle.
* \retval VMK_BAD_PARAM data argument is NULL.
* *
*********************************************************************** ***********************************************************************
*/ */
@ -191,3 +281,5 @@ vmk_DriverGetPrivateData(vmk_Driver driver,
/** @} */ /** @} */
/** @} */ /** @} */

View file

@ -0,0 +1,203 @@
/* **********************************************************
* Copyright 2012 VMware, Inc. All rights reserved.
* **********************************************************/
/*
* @VMKAPIMOD_LICENSE@
*/
/*
***********************************************************************
* Dump */ /**
* \addtogroup Core
* @{
* \defgroup Dump VMKernel Crash Dumps
*
* Functions related to VMKernel Crash Dumps. These functions allow
* vmkapi users to register files to be created in a zdump file.
*
* @{
***********************************************************************
*/
#ifndef _VMKAPI_DUMP_H_
#define _VMKAPI_DUMP_H_
/** \cond never */
#ifndef VMK_HEADER_INCLUDED_FROM_VMKAPI_H
#error This vmkapi file should never be included directly but only via vmkapi.h
#endif
/** \endcond never */
/**
* \brief Prototype for a dump callback function.
*
* After being registered for dump callback, this function is called during
* system dump time. There are two types of system dump. The first one
* is when the system crashes during normal operation and a core dump is
* written. The second type, called a live dump, occurs while the system
* is still operational and is an additional tool for diagnosing issues
* without bringing the whole system down.
*
* There are two functions a callback can use to add data to the dump.
* These are vmk_DumpRange() and vmk_DumpMPN(). vmk_DumpRange() may only
* be called on data currently known to be correctly mapped (consistently
* across all CPUs), as calls to unmapped spaces will generate page faults.
*
* For both functions it is also required that there are no side effects
* from reading the memory (e.g. a memory mapped PCI device should not
* treat reading any piece of memory as an acknowledge of some transaction
* for example).
*
* For the live dump type of call vmk_DumpMPN() is the only safe method
* of adding data that may not be currently mapped. This may happen when
* unmap events are not managed with any concurrency protection.
*
* \note This function may only block when liveDump is TRUE.
*
* \param[in] cookie Private data as specified vmk_DumpAddFileCallback().
* \param[in] liveDump TRUE only if the system is still currently functional.
* In this case concurrency issues should be considered
* as normal for the sub-system. This means that locking
* and/or other synchronization should only be performed
* when liveDump is TRUE.
*/
typedef VMK_ReturnStatus (*vmk_DumpFileCallback)(
void *cookie,
vmk_Bool liveDump);
/**
* \brief Dump file handle
*
* Returned as part of the vmk_DumpAddFileCallback() call. Used for
* all other calls.
*/
typedef void *vmk_DumpFileHandle;
/*
*******************************************************************************
* vmk_DumpAddFileCallback -- */ /**
*
* \brief Register a file to be created at kernel core dump time.
*
* This function registers a callback to allow memory to be dumped in a
* VMKernel core file under the specified name.
*
* \param[in] moduleID Module ID of the caller.
* \param[in] heapID Heap ID to be used for allocations.
* \param[in] name The name of the file to be created by vmkdump_extract.
* \param[in] func The callback function itself.
* \param[in] cookie Opaque cookie passed to the callback.
* \param[in] dumpName Tag used for error messages on this file.
* \param[out] outHandle Dump Handle is written here upon success.
*
* \note This function will not block.
*
* \retval VMK_OK Callback successfully added to dump-file table.
* \retval VMK_LIMIT_EXCEEDED Dump file table is full.
* \retval VMK_NAME_INVALID Specified name was invalid.
* \retval VMK_NO_MEMORY Allocation from heapID failed.
*
*******************************************************************************
*/
VMK_ReturnStatus vmk_DumpAddFileCallback(
vmk_ModuleID moduleID,
vmk_HeapID heapID,
const char *name,
vmk_DumpFileCallback func,
void *cookie,
char *dumpName,
vmk_DumpFileHandle *outHandle);
/*
*******************************************************************************
* vmk_DumpDeleteFileCallback -- */ /**
*
* \brief Unregister a file to be created at kernel core dump time.
*
* This function unregisters a callback to allow memory to be dumped in a
* VMKernel core file under the specified name.
*
* \param[in] handle Dump handle returned from vmk_DumpAddFileCallback().
*
* \note This function will not block.
*
* \retval VMK_OK Callback successfully removed to dump-file table.
* \retval VMK_NOT_FOUND Dump-file table entry could not be found.
*
*******************************************************************************
*/
VMK_ReturnStatus vmk_DumpDeleteFileCallback(
vmk_DumpFileHandle handle);
/*
*******************************************************************************
* vmk_DumpRange -- */ /**
*
* \brief Dump a region of memory into a VMKernel core file.
*
* All errors occurring in an invocation will be logged with the dumpName tag
* registered at dump handle creation.
*
* \param[in] handle Dump handle returned from vmk_DumpAddFileCallback().
* \param[in] va Virtual Address to begin dumping. If zero,
* dump zero-byte data upto one PAGE_SIZE.
* \param[in] size Length of region to dump.
*
* \note This function is only to be used in a call back registered via
* vmk_DumpAddFileCallback().
*
* \note This function may block when vmk_DumpAddFileCallback() was called
* with liveDump is TRUE.
*
* \retval VMK_OK Region was successfully dumped.
* \retval VMK_LIMIT_EXCEEDED More than PAGE_SIZE of zeros requested, or size
* of dump exceeded.
* \retval VMK_FAILURE Gzip deflate failed.
*
*******************************************************************************
*/
VMK_ReturnStatus vmk_DumpRange(
vmk_DumpFileHandle handle,
vmk_VA va,
vmk_uint32 size);
/*
*******************************************************************************
* vmk_DumpMPN -- */ /**
*
* \brief Dump a page of memory into a VMKernel core file.
*
* All errors occurring in an invocation will be logged with the dumpName tag
* registered at dump handle creation.
*
* \param[in] handle Dump handle returned from vmk_DumpAddFileCallback().
* \param[in] mpn VMKernel machine page number to dump.
*
* \note This function is only to be used in a call back registered via
* vmk_DumpAddFileCallback().
*
* \note This function may block when vmk_DumpAddFileCallback() was called
* with liveDump is TRUE.
*
* \retval VMK_OK Page was successfully dumped.
* \retval VMK_LIMIT_EXCEEDED More than PAGE_SIZE of zeros requested, or size
* of dump exceeded.
* \retval VMK_FAILURE Gzip deflate failed.
*
*******************************************************************************
*/
VMK_ReturnStatus vmk_DumpMPN(
vmk_DumpFileHandle handle,
vmk_MPN mpn);
#endif /* _VMKAPI_DUMP_H_ */
/** @} */
/** @} */

View file

@ -0,0 +1,123 @@
/***************************************************************************
* Copyright 2012 VMware, Inc. All rights reserved.
***************************************************************************/
/*
* @VMKAPIMOD_LICENSE@
*/
/*
***********************************************************************
* Logical */ /**
* \addtogroup Device
* @{
* \defgroup Logical Logical bus interface
* @{
***********************************************************************
*/
#ifndef _VMKAPI_LOGICAL_BUS_H_
#define _VMKAPI_LOGICAL_BUS_H_
/** \cond never */
#ifndef VMK_HEADER_INCLUDED_FROM_VMKAPI_H
#error This vmkapi file should never be included directly but only via vmkapi.h
#endif
/** \endcond never */
/** \brief Name of the logical bus type. */
#define VMK_LOGICAL_BUS_NAME "logical"
/*
***********************************************************************
* vmk_LogicalCreateBusAddress -- */ /**
*
* \brief Return a global address for a device on the logical bus.
*
* A driver registering a device on the logical bustype must use this
* call to obtain a globally unique and persistent busAddress for the
* device. Driver must provide a logical port component satisfying the
* following conditions.
*
* Locally unique: This means the logical port distinguishes this
* logical device from other logical devices created by the same driver
* under the same parent device.
*
* Locally persistent: This means the same logical port is used for
* a logical device every time that device is created by the driver.
* This is important if the logical device directly represents a
* physical hardware component in the system.
*
* Example : A network driver creates uplinks (logical devices) for a
* NIC addressable by a single PCI function (physical parent device).
*
* Case 1: Single uplink for a single-port NIC.
* Driver can use '0' as unique and persistent logical port.
*
* Case 2: Multiplexing two uplinks for a single-port NIC.
* Driver may use '0' and '1' as unique logical ports. As long
* as the driver manages multiplexing internally, and logical
* ports do not represent physical ports directly, shifting of
* logical port numbers is permitted. E.g. if driver is
* configured to register only one uplink at next driver load,
* logical port '0' may be used, whether it was '0' or '1'
* during the previous load.
*
* Case 3: Two uplinks for a two-port NIC, one per port.
* Driver may choose '0' and '1' as unique logical ports for the
* uplinks on the first and second port, respectively. Since the
* logical devices directly represent physical ports, the driver
* must also ensure that the logical ports are never shifted or
* mixed up. That is, '0' is always used as the logical port for
* the uplink for the first port, and '1' is always used as the
* logical port for the uplink for the second port, even if one
* of the physical ports fails or is disabled, or if the driver
* is configured to use only one port at next driver load.
*
* \note Memory is allocated for \em globalAddress.
* It must be freed using vmk_LogicalFreeBusAddress().
*
* \param[in] driver Driver creating the device.
* \param[in] parent Parent of device being created.
* \param[in] uniqueLogicalPort Unique and persistent logical port number.
* \param[out] globalAddress Globally unique and persistent address.
* \param[out] globalAddressLen Length of globally unique address.
*
* \retval VMK_OK Success.
* \retval VMK_NO_MODULE_HEAP Driver module has no heap to allocate memory.
* \retval VMK_NO_MEMORY Could not allocate memory to create address.
* \retval VMK_BAD_PARAM Invalid parameter.
*
***********************************************************************
*/
VMK_ReturnStatus
vmk_LogicalCreateBusAddress(vmk_Driver driver,
vmk_Device parent,
vmk_uint32 uniqueLogicalPort,
char* *globalAddress,
vmk_uint32 *globalAddressLen);
/*
***********************************************************************
* vmk_LogicalFreeBusAddress -- */ /**
*
* \brief Free memory for logical bus address created using
* vmk_LogicalCreateBusAddress().
*
* \param[in] driver Driver that allocated the bus address.
* \param[in] globalAddress Allocated global address.
*
* \retval VMK_OK Success
* \retval VMK_NO_MODULE_HEAP Driver module has no heap to free memory.
*
***********************************************************************
*/
VMK_ReturnStatus
vmk_LogicalFreeBusAddress(vmk_Driver driver,
char* globalAddress);
#endif /* _VMKAPI_LOGICAL_BUS_H_ */
/** @} */
/** @} */

View file

@ -0,0 +1,200 @@
/* **********************************************************
* Copyright 2012 VMware, Inc. All rights reserved.
* **********************************************************/
/*
* @VMKAPIMOD_LICENSE@
*/
/*
***********************************************************************
* PageSlab */ /**
* \addtogroup Core
* @{
* \defgroup PageSlab Slab page allocator
*
* Functions related to page slabs. A page slab is a page-wise
* allocator that allows for fast page allocations and freeing.
*
* @{
***********************************************************************
*/
#ifndef _VMKAPI_PAGESLAB_H_
#define _VMKAPI_PAGESLAB_H_
/** \cond never */
#ifndef VMK_HEADER_INCLUDED_FROM_VMKAPI_H
#error This vmkapi file should never be included directly but only via vmkapi.h
#endif
/** \endcond never */
/** \brief INVALID page slab ID */
#define VMK_INVALID_PAGESLAB_ID ((vmk_PageSlabID)NULL)
/** \brief Page slab ID */
typedef struct vmkPageSlabInt* vmk_PageSlabID;
/**
* \brief Properties of a page slab.
*/
typedef struct vmk_PageSlabCreateProps {
/** \brief Heap to allocate page slab metadata from. The size of the
* allocation can be retrieved via vmk_PageSlabAllocationSize.
*/
vmk_HeapID heapID;
/** \brief Name for this page slab. */
vmk_Name name;
/** \brief Minimum number of pages that should be held in the slab.
* Please be careful when sizing this number as any memory
* that is used for the minimum will be unavailable to VMs, etc.
*/
vmk_uint32 minPages;
/** \brief Maximum number of pages that the slab should provide for. */
vmk_uint32 maxPages;
/** \brief Restrictions on the physical address space that pages for
* the page slab are allocated from. Please choose the least
* restrictive constraint possible as memory below 2GB or 4GB
* is a scarce resource.
*/
vmk_MemPhysAddrConstraint physRange;
/** \brief Memory pool that the slab should allocate pages from. Set to
* VMK_MEMPOOL_INVALID to have vmk_PageSlabCreate create a new
* memory pool for the slab.
*/
vmk_MemPool memPool;
} vmk_PageSlabCreateProps;
/*
***********************************************************************
* vmk_PageSlabCreateCustom -- */ /**
*
* \brief Create a new page slab.
*
* This function creates a new page slab with the given properties.
*
* \note This function might block.
*
* \param[in] moduleID Module ID of the module that this
* page slab will belong to.
* \param[in] createProps Properties of the new page slab.
* \param[out] pageSlabID Handle to the newly created page slab.
*
***********************************************************************
*/
VMK_ReturnStatus
vmk_PageSlabCreateCustom(vmk_ModuleID moduleID,
vmk_PageSlabCreateProps *createProps,
vmk_PageSlabID *pageSlabID);
/*
***********************************************************************
* vmk_PageSlabCreate -- */ /**
*
* \brief Convenience wrapper around vmk_PageSlabCreateCustom
*
* This function creates a new page slab with the given properties.
*
* \note This function might block.
*
* \param[in] createProps Properties of the new page slab.
* \param[out] pageSlabID Handle to the newly created page slab.
*
***********************************************************************
*/
static VMK_INLINE VMK_ReturnStatus
vmk_PageSlabCreate(vmk_PageSlabCreateProps *createProps,
vmk_PageSlabID *pageSlabID)
{
return vmk_PageSlabCreateCustom(vmk_ModuleCurrentID, createProps, pageSlabID);
}
/*
***********************************************************************
* vmk_PageSlabDestroy -- */ /**
*
* \brief Destroy a page slab.
*
* \note The page slab must be empty meaning all previously allocated
* pages must have been freed back to the slab.
* \note This function might block.
*
* \param[in] pageSlabID Page slab identifier acquired through a
* preceding vmk_PageSlabCreate(Custom) call.
*
***********************************************************************
*/
void
vmk_PageSlabDestroy(vmk_PageSlabID pageSlabID);
/*
***********************************************************************
* vmk_PageSlabAllocationSize -- */ /**
*
* \brief Return the amount of memory that vmk_PageSlabCreate is going
* to allocate from the passed in heap for each call.
*
* \note This function will not block.
*
***********************************************************************
*/
vmk_ByteCountSmall
vmk_PageSlabAllocationSize(void);
/*
***********************************************************************
* vmk_PageSlabAlloc -- */ /**
*
* \brief Allocate a page from the given page slab.
*
* \note This function may block based on the blocking parameter
*
* \param[in] pageSlabID Page slab previously created via
* vmk_PageSlabCreate(Custom)
* \param[in] blocking Allow the page slab to block and wait for
* a page to become free if none are readily
* available.
* \param[out] mpn Machine page number of the new page. Only
* filled if return status was VMK_OK;
*
* \retval VMK_NO_MEMORY The slab was unable to allocate a page.
*
***********************************************************************
*/
VMK_ReturnStatus
vmk_PageSlabAlloc(vmk_PageSlabID pageSlabID,
vmk_Bool blocking,
vmk_MPN *mpn);
/*
***********************************************************************
* vmk_PageSlabFree -- */ /**
*
* \brief Free a page to the given page slab.
*
* \param[in] pageSlabID Page slab previously created via
* vmk_PageSlabCreate(Custom)
* \param[in] mpn An machine page number previously returned
* by vmk_PageSlabAlloc
*
***********************************************************************
*/
void
vmk_PageSlabFree(vmk_PageSlabID pageSlabID,
vmk_MPN mpn);
#endif /* _VMKAPI_PAGESLAB_H_ */
/** @} */
/** @} */

View file

@ -88,6 +88,11 @@ typedef struct vmk_SgArray {
*/ */
typedef struct vmk_SgOpsHandleInt *vmk_SgOpsHandle; typedef struct vmk_SgOpsHandleInt *vmk_SgOpsHandle;
/**
* \brief Opaque handle for scatter-gather component operations.
*/
typedef struct vmk_SgComponentOpsHandleInt *vmk_SgComponentOpsHandle;
/** /**
* \brief The type of position a vmk_SgPosition represents. * \brief The type of position a vmk_SgPosition represents.
*/ */
@ -140,6 +145,53 @@ typedef struct vmk_SgPosition {
}; };
} vmk_SgPosition; } vmk_SgPosition;
/**
* \brief Scatter-gather component
*
* A scatter gather component is a scatter gather array as well
* as a specific data object offset and length describing
* the start location and size of the I/O operation.
*/
typedef struct vmk_SgComponent {
/**
* Byte offset within a data object.
*/
vmk_ByteCount ioOffset;
/**
* Number of bytes of this I/O operation.
*/
vmk_ByteCount ioLength;
/**
* The scatter-gather array specifying the buffer addresses
* used to satisfy this piece of the I/O operation.
*/
vmk_SgArray *sg;
} vmk_SgComponent;
/**
* \brief Scatter-gather component array.
*
* A scatter gather component array is a set of I/O operations to
* a given data object where a unique data object offset, size,
* and scatter gather array can be specified for each piece of
* the operation.
*/
typedef struct vmk_SgComponentArray {
/** \brief The number of SgComponents this array has. */
vmk_int32 maxComponents;
/** \brief Number of SgComponents currently in-use. */
vmk_int32 numComponents;
/** \brief Reserved. */
vmk_uint64 reserved;
vmk_uint64 reserved2;
/** \brief Array of scatter gather components. Should be
* set to zero on init.
*/
vmk_SgComponent sgComponent[0];
} vmk_SgComponentArray;
/* /*
*********************************************************************** ***********************************************************************
* vmk_SgComputeAllocSize-- */ /** * vmk_SgComputeAllocSize-- */ /**
@ -193,6 +245,37 @@ typedef VMK_ReturnStatus (*vmk_SgArrayOpAlloc)(vmk_SgOpsHandle handle,
vmk_uint32 numElems, vmk_uint32 numElems,
void *private); void *private);
/*
***********************************************************************
* vmk_SgComponentArrayOpAlloc-- */ /**
*
* \ingroup ScatterGather
* \brief Callback to allocate and initialize a new scatter-gather
* component array.
*
* \note Callbacks of this type may not block.
*
* The returned array should have its maxLength field set correctly
* and length field set to zero.
*
* \param[in] handle Opaque scatter-gather ops handle.
* \param[out] sgComponent The new scatter gather component array.
* \param[in] maxComponents Max scatter-gather operations the new
* array must support.
* \param[in] private Private data from vmk_SgComponentCreateOpsHandle().
*
* \retval VMK_OK The allocation succeeded.
* \retval VMK_NO_MEMORY Not enough memory to allocate a new
* scatter-gather component array.
***********************************************************************
*/
typedef VMK_ReturnStatus (*vmk_SgComponentArrayOpAlloc)(
vmk_SgComponentOpsHandle handle,
vmk_SgComponentArray **sgComponent,
vmk_uint32 maxComponents,
void *private);
/* /*
*********************************************************************** ***********************************************************************
* vmk_SgArrayOpFree-- */ /** * vmk_SgArrayOpFree-- */ /**
@ -214,6 +297,28 @@ typedef VMK_ReturnStatus (*vmk_SgArrayOpFree)(vmk_SgOpsHandle handle,
vmk_SgArray *sg, vmk_SgArray *sg,
void *private); void *private);
/*
***********************************************************************
* vmk_SgComponentArrayOpFree-- */ /**
*
* \ingroup ScatterGather
* \brief Callback to free an existing scatter-gather component array.
*
* \note Callbacks of this type may not block.
*
* \param[in] handle Opaque scatter-gather ops handle.
* \param[in] sgComponent scatter-gather component array to free.
* \param[in] private Private data from vmk_SgCreateOpsHandle().
*
* \retval VMK_OK The free succeeded.
*
***********************************************************************
*/
typedef VMK_ReturnStatus (*vmk_SgComponentArrayOpFree)(
vmk_SgComponentOpsHandle handle,
vmk_SgComponentArray *sgComponent,
void *private);
/** /**
* \brief Scatter-gather array operations. * \brief Scatter-gather array operations.
* *
@ -230,6 +335,22 @@ typedef struct vmk_SgArrayOps {
vmk_SgArrayOpFree free; vmk_SgArrayOpFree free;
} vmk_SgArrayOps; } vmk_SgArrayOps;
/**
* \brief Scatter-gather components array operations.
*
* Routines not implemented by the caller must be set to NULL.
*
* Caller may override default behavior for any routine by supplying
* the routines.
*/
typedef struct vmk_SgComponentArrayOps {
/** Handler invoked when allocating scatter-gather component arrays. */
vmk_SgComponentArrayOpAlloc alloc;
/** Handler invoked when freeing scatter-gather component arrays. */
vmk_SgComponentArrayOpFree free;
} vmk_SgComponentArrayOps;
/* /*
*********************************************************************** ***********************************************************************
* vmk_SgComputeMaxEntries-- */ /** * vmk_SgComputeMaxEntries-- */ /**
@ -284,6 +405,45 @@ VMK_ReturnStatus vmk_SgCreateOpsHandle(vmk_HeapID heapId,
vmk_SgArrayOps *ops, vmk_SgArrayOps *ops,
void *private); void *private);
/*
***********************************************************************
* vmk_SgComponentCreateOpsHandle-- */ /**
*
* \ingroup ScatterGather
* \brief Create an opaque handle for scatter-gather component operations.
*
* The handle is used by other routines to invoke callbacks and track
* other state related to scatter-gather component operations.
*
* \note If ops is non-NULL, both an alloc and a free method must
* be provided.
* \note This function will not block.
*
* \param[in] heapId HeapID to allocate memory on.
* \param[out] handle Opaque scatter-gather component ops handle.
* \param[in] ops Scatter-gather compoents ops to associate with
* the opaque handle.
* If this argument is NULL, then the
* default set of scatter-gather component ops
* will be used and the supplied heap
* will be used to allocate scatter-gather
* component arrays.
* \param[in] private Private data passed to each
* vmk_SgComponentArrayOps method when it
* is invoked.
*
* \retval VMK_OK The handle creation succeeded.
* \retval VMK_BAD_PARAM The heapId or ops setting is invalid.
* \retval VMK_NO_MEMORY Not enough memory to allocate a new
* handle.
***********************************************************************
*/
VMK_ReturnStatus vmk_SgComponentCreateOpsHandle(
vmk_HeapID heapId,
vmk_SgComponentOpsHandle *handle,
vmk_SgComponentArrayOps *ops,
void *private);
/* /*
*********************************************************************** ***********************************************************************
* vmk_SgDestroyOpsHandle-- */ /** * vmk_SgDestroyOpsHandle-- */ /**
@ -299,6 +459,24 @@ VMK_ReturnStatus vmk_SgCreateOpsHandle(vmk_HeapID heapId,
*/ */
VMK_ReturnStatus vmk_SgDestroyOpsHandle(vmk_SgOpsHandle handle); VMK_ReturnStatus vmk_SgDestroyOpsHandle(vmk_SgOpsHandle handle);
/*
***********************************************************************
* vmk_SgComponentDestroyOpsHandle-- */ /**
*
* \ingroup ScatterGather
* \brief Destroy opaque handle for scatter-gather component operations.
*
* \note This function will not block.
*
* \param[in] handle Opaque scatter-gather component ops handle to
* be destroyed.
*
* \retval VMK_OK The handle was destroyed.
***********************************************************************
*/
VMK_ReturnStatus vmk_SgComponentDestroyOpsHandle(
vmk_SgComponentOpsHandle handle);
/* /*
*********************************************************************** ***********************************************************************
* vmk_SgAlloc-- */ /** * vmk_SgAlloc-- */ /**
@ -309,9 +487,9 @@ VMK_ReturnStatus vmk_SgDestroyOpsHandle(vmk_SgOpsHandle handle);
* \note This function will not block. * \note This function will not block.
* *
* \param[in] handle Opaque scatter-gather ops handle. * \param[in] handle Opaque scatter-gather ops handle.
* \param[in] sg New scatter-gather array. * \param[out] sg New scatter-gather array.
* \param[in] maxElements Maximum number of elements the new * \param[in] maxElements Maximum number of elements the new
* sactter-gather array should have. * scatter-gather array should have.
* *
*********************************************************************** ***********************************************************************
*/ */
@ -319,6 +497,29 @@ VMK_ReturnStatus vmk_SgAlloc(vmk_SgOpsHandle handle,
vmk_SgArray **sg, vmk_SgArray **sg,
vmk_uint32 maxElements); vmk_uint32 maxElements);
/*
***********************************************************************
* vmk_SgComponentAlloc-- */ /**
*
* \ingroup ScatterGather
* \brief Allocate a scatter-gather component array with a given number
* of component entries.
*
* \note This function will not block.
*
* \param[in] handle Opaque scatter-gather component ops handle.
* \param[out] sgComponent New scatter-gather component array.
* \param[in] maxLength Maximum number of components the new
* sactter-gather component array should have.
*
* \retval VMK_OK The allocation succeeded.
* \retval VMK_NO_MEMORY Not enough memory to allocate the array.
***********************************************************************
*/
VMK_ReturnStatus vmk_SgComponentAlloc(vmk_SgComponentOpsHandle handle,
vmk_SgComponentArray **sgComponent,
vmk_uint32 maxLength);
/* /*
*********************************************************************** ***********************************************************************
* vmk_SgAllocWithInit-- */ /** * vmk_SgAllocWithInit-- */ /**
@ -392,6 +593,28 @@ VMK_ReturnStatus vmk_SgInit(vmk_SgOpsHandle handle,
VMK_ReturnStatus vmk_SgFree(vmk_SgOpsHandle handle, VMK_ReturnStatus vmk_SgFree(vmk_SgOpsHandle handle,
vmk_SgArray *sgArray); vmk_SgArray *sgArray);
/*
***********************************************************************
* vmk_SgComponentFree -- */ /**
*
* \ingroup ScatterGather
* \brief Free a scatter-gather component array.
*
* \note This function will not block.
*
* \param[in] handle Opaque scatter-gather component ops handle.
* \param[in] sgComponentArray Pointer returned by
* vmk_SgAllocComponentArray().
*
* \retval VMK_OK The array was freed.
* \retval VMK_BAD_PARAM The handle is invalid.
***********************************************************************
*/
VMK_ReturnStatus vmk_SgComponentFree(
vmk_SgComponentOpsHandle handle,
vmk_SgComponentArray *sgComponentArray);
/* /*
*********************************************************************** ***********************************************************************
* vmk_SgCopyData -- */ /** * vmk_SgCopyData -- */ /**
@ -466,6 +689,21 @@ VMK_ReturnStatus vmk_SgFindPosition(vmk_SgArray *sgArray,
*/ */
vmk_ByteCount vmk_SgGetDataLen(vmk_SgArray *sgArray); vmk_ByteCount vmk_SgGetDataLen(vmk_SgArray *sgArray);
/*
***********************************************************************
* vmk_GetSgComponentDataLen -- */ /**
*
* \ingroup ScatterGather
* \brief Compute the size of a scatter-gather component list's
* payload in bytes.
*
* \note This function will not block.
*
***********************************************************************
*/
vmk_ByteCount vmk_SgComponentGetDataLen(
vmk_SgComponentArray *sgComponentArray);
/* /*
*********************************************************************** ***********************************************************************
* vmk_SgCopyTo-- */ /** * vmk_SgCopyTo-- */ /**

View file

@ -1,5 +1,5 @@
/* ********************************************************** /* **********************************************************
* Copyright 2010 VMware, Inc. All rights reserved. * Copyright 2010-2012 VMware, Inc. All rights reserved.
* **********************************************************/ * **********************************************************/
/* /*
@ -13,6 +13,14 @@
* \addtogroup Core * \addtogroup Core
* @{ * @{
* \defgroup SpinLocks Spin Locks * \defgroup SpinLocks Spin Locks
*
* \par Lock acquisition behavior for lock types VMK_SPINLOCK and
* VMK_SPINLOCK_RW:\n
* In the case of lock contention, locks of types VMK_SPINLOCK and
* VMK_SPINLOCK_RW will spin for a short amount of time. If the lock
* acquisition does not succeed during the spinning phase, the lock acquisition
* function will block.
*
* @{ * @{
* *
****************************************************************************** ******************************************************************************
@ -34,9 +42,6 @@
/** Invalid lock rank */ /** Invalid lock rank */
#define VMK_SPINLOCK_RANK_INVALID (0) #define VMK_SPINLOCK_RANK_INVALID (0)
/** Invalid lock irql */
#define VMK_SPINLOCK_IRQL_INVALID ((vmk_LockIRQL)-1)
/** Lock rank for unranked locks */ /** Lock rank for unranked locks */
#define VMK_SPINLOCK_UNRANKED (0xFFFF) #define VMK_SPINLOCK_UNRANKED (0xFFFF)
@ -48,16 +53,17 @@ typedef struct vmk_LockInt *vmk_Lock;
/** /**
* Spinlock Types * \brief Spinlock Types
* @{
*/ */
typedef enum vmk_SpinlockType { typedef vmk_uint8 vmk_SpinlockType;
/** Spinlock usable from a world context */
VMK_SPINLOCK = 1, /** Spinlock usable from a world context */
/** Spinlock usable from a world and interrupt handler context */ #define VMK_SPINLOCK (1)
VMK_SPINLOCK_IRQ = 2, /** RW Spinlock usable from a world context */
/** RW Spinlock usable from a world context */ #define VMK_SPINLOCK_RW (3)
VMK_SPINLOCK_RW = 3,
} vmk_SpinlockType; /** @} */
/** /**
@ -65,14 +71,9 @@ typedef enum vmk_SpinlockType {
*/ */
typedef vmk_uint16 vmk_LockRank; typedef vmk_uint16 vmk_LockRank;
/**
* \brief IRQ level of a VMK_SPINLOCK_IRQ lock.
*/
typedef vmk_uint32 vmk_LockIRQL;
/** /**
* Spinlock Creation Properties * \brief Spinlock Creation Properties
*/ */
typedef struct vmk_SpinlockCreateProps { typedef struct vmk_SpinlockCreateProps {
/** Module ID for which the spinlock is created */ /** Module ID for which the spinlock is created */
@ -157,19 +158,26 @@ vmk_SpinlockAllocSize(vmk_SpinlockType type);
****************************************************************************** ******************************************************************************
* vmk_SpinlockLock -- */ /** * vmk_SpinlockLock -- */ /**
* *
* Acquire a spinlock of type VMK_SPINLOCK * \brief Acquire a spinlock of type VMK_SPINLOCK
* *
* \param[in,out] lock Spinlock to be acquired * \param[in,out] lock Spinlock to be acquired
* *
* \return VMK_OK on success, error code otherwise
*
* \note Lock checks are only executed when enabled for a given build. They * \note Lock checks are only executed when enabled for a given build. They
* are always enabled for debug builds. * are always enabled for debug builds.
* \note A caller has to release the spinlock with a subsequent call to * \note A caller has to release the spinlock with a subsequent call to
* vmk_SpinlockUnlock * vmk_SpinlockUnlock
* \note Callers are required to minimize the time and code that is executed * \note Callers are required to minimize the time and code that is executed
* while any type of spinlock is held. * while any type of spinlock is held.
* \note This function will not block * \note This function might block in case of lock contention
* \note The lock acquisition might not succeed if the world receives a
* VMK_DEATH_PENDING signal while it is waiting for the lock.
*
* \retval VMK_OK World acquired the lock.
* \retval VMK_DEATH_PENDING World blocked during the lock acquisition
* and awoken because the world is dying and
* being reaped by the scheduler. The caller
* is expected to return as soon as possible.
* The lock has not been acquired.
* *
****************************************************************************** ******************************************************************************
*/ */
@ -178,50 +186,30 @@ VMK_ReturnStatus
vmk_SpinlockLock(vmk_Lock lock); vmk_SpinlockLock(vmk_Lock lock);
/*
******************************************************************************
* vmk_SpinlockLockIRQ -- */ /**
*
* Acquire a spinlock of type VMK_SPINLOCK_IRQ
*
* \param[in,out] lock IRQ Spinlock to be acquired
* \param[out] irql Previous IRQ level of spinlock
*
* \return VMK_OK on success, error code otherwise
*
* \note Lock checks are only executed when enabled for a given build. They
* are always enabled for debug builds.
* \note A caller has to release the spinlock with a subsequent call to
* vmk_SpinlockUnlockIRQ, providing the value returned in irql.
* \note Callers are required to minimize the time and code that is executed
* while any type of spinlock is held.
* \note This function will not block.
*
******************************************************************************
*/
VMK_ReturnStatus
vmk_SpinlockLockIRQ(vmk_Lock lock,
vmk_LockIRQL *irql);
/* /*
****************************************************************************** ******************************************************************************
* vmk_SpinlockReadLock -- */ /** * vmk_SpinlockReadLock -- */ /**
* *
* Acquire a spinlock of type VMK_SPINLOCK_RW for reading * \brief Acquire a spinlock of type VMK_SPINLOCK_RW for reading
* *
* \param[in,out] lock R/W Spinlock to be acquired * \param[in,out] lock R/W Spinlock to be acquired
* *
* \return VMK_OK on success, error code otherwise
*
* \note Lock checks are only executed when enabled for a given build. They * \note Lock checks are only executed when enabled for a given build. They
* are always enabled for debug builds. * are always enabled for debug builds.
* \note A caller has to release the spinlock with a subsequent call to * \note A caller has to release the spinlock with a subsequent call to
* vmk_SpinlockReadUnlock * vmk_SpinlockReadUnlock
* \note Callers are required to minimize the time and code that is executed * \note Callers are required to minimize the time and code that is executed
* while any type of spinlock is held. * while any type of spinlock is held.
* \note This function will not block * \note This function might block in case of lock contention
* \note The lock acquisition might not succeed if the world receives a
* VMK_DEATH_PENDING signal while it is waiting for the lock.
*
* \retval VMK_OK World acquired the read lock.
* \retval VMK_DEATH_PENDING World blocked during the lock acquisition
* and awoken because the world is dying and
* being reaped by the scheduler. The caller
* is expected to return as soon as possible.
* The read lock has not been acquired.
* *
****************************************************************************** ******************************************************************************
*/ */
@ -234,19 +222,27 @@ vmk_SpinlockReadLock(vmk_Lock lock);
****************************************************************************** ******************************************************************************
* vmk_SpinlockWriteLock -- */ /** * vmk_SpinlockWriteLock -- */ /**
* *
* Acquire a spinlock of type VMK_SPINLOCK_RW for an exclusive write operation * \brief Acquire a spinlock of type VMK_SPINLOCK_RW for an exclusive write
* operation
* *
* \param[in,out] lock R/W Spinlock to be acquired * \param[in,out] lock R/W Spinlock to be acquired
* *
* \return VMK_OK on success, error code otherwise
*
* \note Lock checks are only executed when enabled for a given build. They * \note Lock checks are only executed when enabled for a given build. They
* are always enabled for debug builds. * are always enabled for debug builds.
* \note A caller has to release the spinlock with a subsequent call to * \note A caller has to release the spinlock with a subsequent call to
* vmk_SpinlockUnlock * vmk_SpinlockWriteUnlock
* \note Callers are required to minimize the time and code that is executed * \note Callers are required to minimize the time and code that is executed
* while any type of spinlock is held. * while any type of spinlock is held.
* \note This function will not block * \note This function might block in case of lock contention
* \note The lock acquisition might not succeed if the world receives a
* VMK_DEATH_PENDING signal while it is waiting for the lock.
*
* \retval VMK_OK World acquired the write lock.
* \retval VMK_DEATH_PENDING World blocked during the lock acquisition
* and awoken because the world is dying and
* being reaped by the scheduler. The caller
* is expected to return as soon as possible.
* The write lock has not been acquired.
* *
****************************************************************************** ******************************************************************************
*/ */
@ -255,11 +251,90 @@ VMK_ReturnStatus
vmk_SpinlockWriteLock(vmk_Lock lock); vmk_SpinlockWriteLock(vmk_Lock lock);
/*
******************************************************************************
* vmk_SpinlockLockIgnoreDeathPending -- */ /**
*
* \brief Acquire a spinlock of type VMK_SPINLOCK
*
* \param[in,out] lock Spinlock to be acquired
*
* \note This functions should only be used by callers that must acquire a
* lock, for instance to perform clean up, even after a world has
* already received the VMK_DEATH_PENDING signal.
* \note Lock checks are only executed when enabled for a given build. They
* are always enabled for debug builds.
* \note A caller has to release the spinlock with a subsequent call to
* vmk_SpinlockUnlock
* \note Callers are required to minimize the time and code that is executed
* while any type of spinlock is held.
* \note This function might block in case of lock contention
*
******************************************************************************
*/
void
vmk_SpinlockLockIgnoreDeathPending(vmk_Lock lock);
/*
******************************************************************************
* vmk_SpinlockReadLockIgnoreDeathPending -- */ /**
*
* \brief Acquire a spinlock of type VMK_SPINLOCK_RW for reading
*
* \param[in,out] lock R/W Spinlock to be acquired
*
* \note This functions should only be used by callers that must acquire a
* lock, for instance to perform clean up, even after a world has
* already received the VMK_DEATH_PENDING signal.
* \note Lock checks are only executed when enabled for a given build. They
* are always enabled for debug builds.
* \note A caller has to release the spinlock with a subsequent call to
* vmk_SpinlockReadUnlock
* \note Callers are required to minimize the time and code that is executed
* while any type of spinlock is held.
* \note This function might block in case of lock contention
*
******************************************************************************
*/
void
vmk_SpinlockReadLockIgnoreDeathPending(vmk_Lock lock);
/*
******************************************************************************
* vmk_SpinlockWriteLockIgnoreDeathPending -- */ /**
*
* \brief Acquire a spinlock of type VMK_SPINLOCK_RW for an exclusive write
* operation
*
* \param[in,out] lock R/W Spinlock to be acquired
*
* \note This functions should only be used by callers that must acquire a
* lock, for instance to perform clean up, even after a world has
* already received the VMK_DEATH_PENDING signal.
* \note Lock checks are only executed when enabled for a given build. They
* are always enabled for debug builds.
* \note A caller has to release the spinlock with a subsequent call to
* vmk_SpinlockWriteUnlock
* \note Callers are required to minimize the time and code that is executed
* while any type of spinlock is held.
* \note This function might block in case of lock contention
*
******************************************************************************
*/
void
vmk_SpinlockWriteLockIgnoreDeathPending(vmk_Lock lock);
/* /*
****************************************************************************** ******************************************************************************
* vmk_SpinlockUnlock -- */ /** * vmk_SpinlockUnlock -- */ /**
* *
* Release a spinlock previously acquired via vmk_SpinlockLock * \brief Release a spinlock previously acquired via vmk_SpinlockLock
* *
* \param[in,out] lock Spinlock to be released * \param[in,out] lock Spinlock to be released
* *
@ -276,30 +351,32 @@ vmk_SpinlockUnlock(vmk_Lock lock);
/* /*
****************************************************************************** ******************************************************************************
* vmk_SpinlockUnlockIRQ -- */ /** * vmk_SpinlockUnlockOutOfOrder -- */ /**
* *
* Release a IRQ spinlock previously acquired via vmk_SpinlockLockIRQ * \brief Out of order release of a spinlock previously acquired via
* vmk_SpinlockLock
* *
* \param[in,out] lock IRQ Spinlock to be released * \param[in,out] lock Spinlock to be released
* \param[in] irql IRQ level of spinlock prior to locking
* *
* \note Callers are required to release spinlocks in the reverse order in which * \note Callers are normally required to release spinlocks in the reverse
* they were acquired * order in which they were acquired. This function allows for out
* of order releases but this should only be done when it is known to
* be safe. This function should only be used for out of order releases;
* in all other cases vmk_SpinlockUnlock should be used.
* \note This function will not block * \note This function will not block
* *
****************************************************************************** ******************************************************************************
*/ */
void void
vmk_SpinlockUnlockIRQ(vmk_Lock lock, vmk_SpinlockUnlockOutOfOrder(vmk_Lock lock);
vmk_LockIRQL irql);
/* /*
****************************************************************************** ******************************************************************************
* vmk_SpinlockReadUnlock -- */ /** * vmk_SpinlockReadUnlock -- */ /**
* *
* Release a R/W spinlock previously acquired via vmk_SpinlockReadLock * \brief Release a R/W spinlock previously acquired via vmk_SpinlockReadLock
* *
* \param[in,out] lock Spinlock to be released * \param[in,out] lock Spinlock to be released
* *
@ -314,11 +391,34 @@ void
vmk_SpinlockReadUnlock(vmk_Lock lock); vmk_SpinlockReadUnlock(vmk_Lock lock);
/*
******************************************************************************
* vmk_SpinlockReadUnlockOutOfOrder -- */ /**
*
* \brief Out of order release of a R/W spinlock previously acquired via
* vmk_SpinlockReadLock
*
* \param[in,out] lock Spinlock to be released
*
* \note Callers are normally required to release spinlocks in the reverse
* order in which they were acquired. This function allows for out
* of order releases but this should only be done when it is known to
* be safe. This function should only be used for out of order releases;
* in all other cases vmk_SpinlockReadUnlock should be used.
* \note This function will not block
*
******************************************************************************
*/
void
vmk_SpinlockReadUnlockOutOfOrder(vmk_Lock lock);
/* /*
****************************************************************************** ******************************************************************************
* vmk_SpinlockWriteUnlock -- */ /** * vmk_SpinlockWriteUnlock -- */ /**
* *
* Release a R/W spinlock previously acquired via vmk_SpinlockWriteLock * \brief Release a R/W spinlock previously acquired via vmk_SpinlockWriteLock
* *
* \param[in,out] lock Spinlock to be released * \param[in,out] lock Spinlock to be released
* *
@ -335,9 +435,31 @@ vmk_SpinlockWriteUnlock(vmk_Lock lock);
/* /*
****************************************************************************** ******************************************************************************
* vmk_SpinlockAssertHeldOnPCPUInt -- * vmk_SpinlockWriteUnlockOutOfOrder -- */ /**
* *
* This is used by vmk_SpinlockAssertHeldOnPCPU(). VMKAPI clients should not * \brief Out of order release of a R/W spinlock previously acquired via
* vmk_SpinlockWriteLock
*
* \param[in,out] lock Spinlock to be released
*
* \note Callers are normally required to release spinlocks in the reverse
* order in which they were acquired. This function allows for out
* of order releases but this should only be done when it is known to
* be safe. This function should only be used for out of order releases;
* in all other cases vmk_SpinlockWriteUnlock should be used.
* \note This function will not block
*
******************************************************************************
*/
void
vmk_SpinlockWriteUnlockOutOfOrder(vmk_Lock lock);
/*
******************************************************************************
* vmk_SpinlockAssertReaderHeldByWorldInt --
*
* This is used by vmk_SpinlockAssertHeldByWorld(). VMKAPI clients should not
* call this function directly. * call this function directly.
* *
* \note This function will not block * \note This function will not block
@ -347,29 +469,74 @@ vmk_SpinlockWriteUnlock(vmk_Lock lock);
/** \cond nodoc */ /** \cond nodoc */
void void
vmk_SpinlockAssertHeldOnPCPUInt(vmk_Lock lock); vmk_SpinlockAssertReaderHeldByWorldInt(vmk_Lock lock);
/** \endcond */ /** \endcond */
/* /*
****************************************************************************** ******************************************************************************
* vmk_SpinlockAssertHeldOnPCPU -- */ /** * vmk_SpinlockAssertReaderHeldByWorld -- */ /**
* *
* \brief Asserts that a lock is held on the current PCPU * \brief Asserts that a VMK_SPINLOCK_RW reader lock is held by the current world
* *
* \param[in] lock Lock to check * \param[in] lock VMK_SPINLOCK_RW reader lock to check
* *
* \note Checks are only executed on debug builds. * \note Checks are only executed on debug builds.
* \note This function should only be called with a lock of lock type
* VMK_SPINLOCK_RW which is holding a VMK_SPINLOCK_RW reader lock.
* \note This function will not block * \note This function will not block
* *
****************************************************************************** ******************************************************************************
*/ */
static VMK_ALWAYS_INLINE void static VMK_ALWAYS_INLINE void
vmk_SpinlockAssertHeldOnPCPU( vmk_SpinlockAssertReaderHeldByWorld(
vmk_Lock lock) vmk_Lock lock)
{ {
#ifdef VMX86_DEBUG #ifdef VMX86_DEBUG
vmk_SpinlockAssertHeldOnPCPUInt(lock); vmk_SpinlockAssertReaderHeldByWorldInt(lock);
#endif
}
/*
******************************************************************************
* vmk_SpinlockAssertHeldByWorldInt --
*
* This is used by vmk_SpinlockAssertHeldByWorld(). VMKAPI clients should not
* call this function directly.
*
* \note This function will not block
*
******************************************************************************
*/
/** \cond nodoc */
void
vmk_SpinlockAssertHeldByWorldInt(vmk_Lock lock);
/** \endcond */
/*
******************************************************************************
* vmk_SpinlockAssertHeldByWorld -- */ /**
*
* \brief Asserts that a lock is held by the current world
*
* \param[in] lock Lock to check
*
* \note Checks are only executed on debug builds.
* \note This function should only be called with a lock of lock type
* VMK_SPINLOCK or VMK_SPINLOCK_RW (RW locks that are writer locks only).
* For reader locks, use vmk_SpinlockAssertReaderHeldByWorld().
* \note This function will not block
*
******************************************************************************
*/
static VMK_ALWAYS_INLINE void
vmk_SpinlockAssertHeldByWorld(
vmk_Lock lock)
{
#ifdef VMX86_DEBUG
vmk_SpinlockAssertHeldByWorldInt(lock);
#endif #endif
} }

View file

@ -0,0 +1,193 @@
/* **********************************************************
* Copyright 2012 VMware, Inc. All rights reserved.
* **********************************************************/
/*
* @VMKAPIMOD_LICENSE@
*/
/*
******************************************************************************
* Spin Locks */ /**
*
* \addtogroup Core
* @{
* \addtogroup SpinLocks
* @{
* \defgroup Deprecated Deprecated APIs
* @{
*
******************************************************************************
*/
#ifndef _VMKAPI_SPINLOCK_DEPRECATED_H_
#define _VMKAPI_SPINLOCK_DEPRECATED_H_
/** \cond never */
#ifndef VMK_HEADER_INCLUDED_FROM_VMKAPI_H
#error This vmkapi file should never be included directly but only via vmkapi.h
#endif
/** \endcond never */
/** Invalid lock irql */
#define VMK_SPINLOCK_IRQL_INVALID ((vmk_LockIRQL)-1)
/**
* \brief Spinlock Types
* @{
*/
/** Spinlock usable from a world and interrupt handler context */
#define VMK_SPINLOCK_IRQ (2)
/** @} */
/**
* \brief IRQ level of a VMK_SPINLOCK_IRQ lock.
*/
typedef vmk_uint32 vmk_LockIRQL;
/*
******************************************************************************
* vmk_SpinlockLockIRQ -- */ /**
*
* \brief Acquire a spinlock of type VMK_SPINLOCK_IRQ
*
* \deprecated
*
* \param[in,out] lock IRQ Spinlock to be acquired
* \param[out] irql Previous IRQ level of spinlock
*
* \return VMK_OK on success, error code otherwise
*
* \note Lock checks are only executed when enabled for a given build. They
* are always enabled for debug builds.
* \note A caller has to release the spinlock with a subsequent call to
* vmk_SpinlockUnlockIRQ, providing the value returned in irql.
* \note Callers are required to minimize the time and code that is executed
* while any type of spinlock is held.
* \note This function will not block.
*
* \nativedriversdisallowed
*
******************************************************************************
*/
VMK_ReturnStatus
vmk_SpinlockLockIRQ(vmk_Lock lock,
vmk_LockIRQL *irql);
/*
******************************************************************************
* vmk_SpinlockUnlockIRQ -- */ /**
*
* \brief Release a IRQ spinlock previously acquired via vmk_SpinlockLockIRQ
*
* \deprecated
*
* \param[in,out] lock IRQ Spinlock to be released
* \param[in] irql IRQ level of spinlock prior to locking
*
* \note Callers are required to release spinlocks in the reverse order in which
* they were acquired
* \note This function will not block
*
* \nativedriversdisallowed
*
******************************************************************************
*/
void
vmk_SpinlockUnlockIRQ(vmk_Lock lock,
vmk_LockIRQL irql);
/*
******************************************************************************
* vmk_SpinlockUnlockIRQOutOfOrder -- */ /**
*
* \brief Out of order release of a IRQ spinlock previously acquired via
* vmk_SpinlockLockIRQ
*
* \deprecated
*
* \param[in,out] lock IRQ Spinlock to be released
* \param[in] irql IRQ level of spinlock prior to locking
*
* \note Callers are normally required to release spinlocks in the reverse
* order in which they were acquired. This function allows for out
* of order releases but this should only be done when it is known to
* be safe. This function should only be used for out of order releases;
* in all other cases vmk_SpinlockUnlockIRQ should be used.
* \note This function will not block
*
* \nativedriversdisallowed
*
******************************************************************************
*/
void
vmk_SpinlockUnlockIRQOutOfOrder(vmk_Lock lock,
vmk_LockIRQL irql);
/*
******************************************************************************
* vmk_SpinlockAssertHeldOnPCPUInt --
*
* This is used by vmk_SpinlockAssertHeldOnPCPU(). VMKAPI clients should not
* call this function directly.
*
* \deprecated
*
* \note This function will not block
*
* \nativedriversdisallowed
*
******************************************************************************
*/
/** \cond nodoc */
void
vmk_SpinlockAssertHeldOnPCPUInt(vmk_Lock lock);
/** \endcond */
/*
******************************************************************************
* vmk_SpinlockAssertHeldOnPCPU -- */ /**
*
* \brief Asserts that a lock is held on the current PCPU
*
* \deprecated
*
* \param[in] lock Lock to check
*
* \note Checks are only executed on debug builds.
* \note This function should only be called with a lock of lock type
* VMK_SPINLOCK_IRQ
* \note This function will not block
*
* \nativedriversdisallowed
*
******************************************************************************
*/
static VMK_ALWAYS_INLINE void
vmk_SpinlockAssertHeldOnPCPU(
vmk_Lock lock)
{
#ifdef VMX86_DEBUG
vmk_SpinlockAssertHeldOnPCPUInt(lock);
#endif
}
#endif
/** @} */
/** @} */
/** @} */

View file

@ -1,5 +1,5 @@
/* ********************************************************** /* **********************************************************
* Copyright 2010 VMware, Inc. All rights reserved. * Copyright 2010-2012 VMware, Inc. All rights reserved.
* **********************************************************/ * **********************************************************/
/* /*
@ -26,6 +26,171 @@
#endif #endif
/** \endcond never */ /** \endcond never */
/*
***********************************************************************
* vmk_UserMapCallback -- */ /**
*
* \brief Callback function invoked when user mapping is released.
*
* \param[in] callbackParam Opaque parameter for callback function.
*
***********************************************************************
*/
typedef void (*vmk_UserMapCallback)(void *);
/**
* \brief Properties of a vmk_UserMap() map request.
*/
typedef struct vmk_UserMapProps {
/** \brief Module ID of module requesting mapping. */
vmk_ModuleID moduleID;
/** \brief Function to call when mapping is released. */
vmk_UserMapCallback callbackFunction;
/** \brief Opaque parameter for callbackFunction. */
vmk_AddrCookie callbackParam;
/**
* \brief Pointer to map request structure.
*
* \note See Mapping section for description
* of map request structure.
*/
vmk_MapRequest *mapRequest;
} vmk_UserMapProps;
/*
***********************************************************************
* vmk_UserMap -- */ /**
*
* \brief Map the provided request into a contiguous virtual address
* space of current user world.
*
* \note The only supported mapping attributes are READONLY, READWRITE,
* WRITECOMBINE, and UNCACHED. Any other attribute will cause
* mapping to fail with return status VMK_BAD_PARAM.
*
* \param[in] props Properties of this mapping request.
* \param[in,out] vaddr Pointer to virtual address of mapping
* (non-zero to specify a virtual address,
* or zero for default address).
*
* \retval VMK_OK Map is successful.
* \retval VMK_BAD_PARAM Input parameter is invalid.
* \retval VMK_NO_MEMORY Unable to allocate mapping request.
* \retval VMK_NO_RESOURCES Unable to allocate mapping request.
* \retval VMK_INVALID_ADDRESS Requested address not in map range.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_UserMap(
vmk_UserMapProps *props,
vmk_VA *vaddr);
/*
***********************************************************************
* vmk_UserUnmap -- */ /**
*
* \brief Unmap user world virtual address space mapped by vmk_UserMap().
*
* \param[in] vaddr Virtual address to unmap.
* \param[in] length Length of address space in bytes.
*
* \retval VMK_OK Unmap is successful.
* \retval VMK_NOT_FOUND Virtual address and length not mapped.
* \retval VMK_INVALID_ADDRESS Requested address is not page aligned.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_UserUnmap(
vmk_VA vaddr,
vmk_ByteCount length);
/*
***********************************************************************
* vmk_UserAddValidMPNRange -- */ /**
*
* \brief Indicate a range of consecutive MPNs can be referenced by
* user worlds.
*
* \param[in] mpn First MPN in range.
* \param[in] numPages Number of machine pages in range.
*
* \retval VMK_OK MPNs added to user worlds.
* \retval VMK_BAD_PARAM Input parameter is invalid.
* \retval VMK_NO_MEMORY Unable to allocate memory for request.
* \retval VMK_INVALID_PAGE_NUMBER MPN range intersects with existing
* MPN range.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_UserAddValidMPNRange(
vmk_MPN mpn,
vmk_uint32 numPages);
/*
***********************************************************************
* vmk_UserRemoveValidMPNRange -- */ /**
*
* \brief Remove a range of consecutive MPNs from user worlds.
*
* \param[in] mpn First MPN in range.
* \param[in] numPages Number of machine pages in range.
*
* \retval VMK_OK MPNs removed from user worlds.
* \retval VMK_NOT_FOUND MPN range not found.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_UserRemoveValidMPNRange(
vmk_MPN mpn,
vmk_uint32 numPages);
/*
***********************************************************************
* vmk_UserPinPage -- */ /**
*
* \brief Marks the VPN in the specified world as not swappable.
*
* \param[in] worldID ID of world whose mapping will be pinned.
* \param[in] vpn VPN to pin.
* \param[out] mpn MPN backing this pinned VPN.
*
* \retval VMK_OK VPNs was pinned successfully.
* \retval VMK_BAD_PARAM An invalid argument was provided.
* \retval VMK_INVALID_WORLD An invalid worldID was provided.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_UserPinPage(
vmk_WorldID worldID,
vmk_VPN vpn,
vmk_MPN *mpn);
/*
***********************************************************************
* vmk_UserUnpinPage -- */ /**
*
* \brief Marks the specified VPN in the specified world as swappable.
*
* \note This VPN must have been pinned by a call to vmk_UserPinPage().
*
* \param[in] worldID ID of world whose mapping will be
* unpinned.
* \param[in] vpn VPN to unpin.
*
* \retval VMK_OK VPNs was unpinned successfully.
* \retval VMK_BAD_PARAM An invalid argument was provided.
* \retval VMK_INVALID_WORLD An invalid worldID was provided.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_UserUnpinPage(
vmk_WorldID worldID,
vmk_VPN vpn);
/* /*
****************************************************************************** ******************************************************************************
* vmk_CopyFromUser -- */ /** * vmk_CopyFromUser -- */ /**

View file

@ -0,0 +1,701 @@
/* **********************************************************
* Copyright 1998 - 2013 VMware, Inc. All rights reserved.
* **********************************************************/
/*
* @VMKAPIMOD_LICENSE@
*/
/*
* Please consult with the VMKernel hardware and core teams before making any
* binary incompatible changes to this file!
*/
/*
***********************************************************************
* PCI */ /**
* \addtogroup Device
* @{
* \defgroup PCI PCI
* @{
***********************************************************************
*/
#ifndef _VMKAPI_PCI_H_
#define _VMKAPI_PCI_H_
/** \cond never */
#ifndef VMK_HEADER_INCLUDED_FROM_VMKAPI_H
#error This vmkapi file should never be included directly but only via vmkapi.h
#endif
/** \endcond never */
#include "device/vmkapi_vector.h"
#define VMK_PCI_BUS_NAME "pci"
/** \brief Maximum number of characters in a PCI device name. */
#define VMK_PCI_DEVICE_NAME_LENGTH 32
/** \brief Per-system max for segments */
#define VMK_PCI_NUM_SEGS 256
/** \brief Per-system max for busses */
#define VMK_PCI_NUM_BUSES 256
/** \brief Per-bus max for slots */
#define VMK_PCI_NUM_SLOTS 32
/** \brief Per-slot max for functions */
#define VMK_PCI_NUM_FUNCS 8
/** \brief Per-device max for BARs */
#define VMK_PCI_NUM_BARS 6
/** \brief Per-device max for BARs on a bridge */
#define VMK_PCI_NUM_BARS_BRIDGE 2
/**
* \brief PCI BAR flags.
*/
typedef enum vmk_PCIBARFlags {
VMK_PCI_BAR_FLAGS_IO = 0x1,
VMK_PCI_BAR_FLAGS_MEM_64_BITS = 0x4,
VMK_PCI_BAR_FLAGS_MEM_PREFETCHABLE = 0x8,
VMK_PCI_BAR_FLAGS_IO_MASK = 0x3,
VMK_PCI_BAR_FLAGS_MEM_MASK = 0xF,
} vmk_PCIBARFlags;
/**
* \brief PCI device identifier.
*
*/
typedef struct vmk_PCIDeviceID {
vmk_uint16 vendorID;
vmk_uint16 deviceID;
vmk_uint16 subVendorID;
vmk_uint16 subDeviceID;
vmk_uint16 classCode;
vmk_uint16 progIFRevID;
} vmk_PCIDeviceID;
/**
* \brief PCI device Address (SBDF).
*
*/
typedef struct vmk_PCIDeviceAddr {
vmk_uint16 seg;
vmk_uint8 bus;
vmk_uint8 dev:5;
vmk_uint8 fn:3;
} vmk_PCIDeviceAddr;
/**
* \brief PCI device resource.
*
*/
typedef struct vmk_PCIResource {
/** \brief Resource's physical address. */
vmk_MA start;
/** \brief Resource size in bytes. */
vmk_ByteCount size;
/** \brief Resource flags. */
vmk_uint64 flags;
} vmk_PCIResource;
/**
* \brief Configuration space access types
*/
typedef enum vmk_PCIConfigAccess {
VMK_PCI_CONFIG_ACCESS_8 = 1,
VMK_PCI_CONFIG_ACCESS_16 = 2,
VMK_PCI_CONFIG_ACCESS_32 = 4
} vmk_PCIConfigAccess;
/*
***********************************************************************
* vmk_PCIRemoveVF -- */ /**
*
* \ingroup PCI
* \brief Remove a PCI virtual function (VF) device.
*
* Physical function (PF) driver should carry out any operations
* required for the removal of a virtual function device, and
* unregister the virtual function device using vmk_PCIUnregisterVF().
*
* \param[in] vf Handle to PCI VF to be removed.
*
* \retval VMK_OK Success
*
***********************************************************************
*/
typedef VMK_ReturnStatus (*vmk_PCIRemoveVF)(vmk_PCIDevice vf);
/**
* \brief PCI virtual function (VF) device operations.
*/
typedef struct {
/** \brief Remove a PCI virtual function from the system. */
vmk_PCIRemoveVF removeVF;
} vmk_PCIVFDeviceOps;
/**
***********************************************************************
* vmk_PCIQueryDeviceID -- */ /**
*
* \ingroup PCI
* \brief Query PCI Device's identifier information.
*
* Upon successful completion, devID structure is filled with the
* identifier information.
*
* \param[in] pciDevice Pointer to PCI device handle.
* \param[out] devID Pointer to PCI Device ID struct.
*
* \retval VMK_BAD_PARAM pciDevice or devID is invalid.
* \retval VMK_OK Query successfully processed.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_PCIQueryDeviceID(vmk_PCIDevice pciDevice,
vmk_PCIDeviceID *devID);
/**
***********************************************************************
* vmk_PCIQueryDeviceAddr -- */ /**
*
* \ingroup PCI
* \brief Query PCI Device's Address (SBDF) information.
*
* Upon successful operation, sbdf struct is filled with device's
* seg, bus, dev, fn information.
*
* \param[in] pciDevice Pointer to PCI device handle.
* \param[out] sbdf Pointer to PCI Device Addr struct.
*
* \retval VMK_BAD_PARAM pciDevice or sbdf is invalid.
* \retval VMK_OK Query successfully processed.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_PCIQueryDeviceAddr(vmk_PCIDevice pciDevice,
vmk_PCIDeviceAddr *sbdf);
/**
***********************************************************************
* vmk_PCIQueryIOResources -- */ /**
*
* \ingroup PCI
* \brief Query PCI Device's BAR resources information.
*
* Upon successful completion, resources array is filled with device's
* first numBars BARs [0 - numBars) information. The resources array
* passed in should be able to hold numBars resources.
*
* \param[in] pciDevice Pointer to PCI device handle.
* \param[in] numBars Number of resources queried.
* \param[out] resources Pointer to PCI resources array.
*
* \retval VMK_BAD_PARAM pciDevice or resources is invalid.
* \retval VMK_BAD_PARAM numBars is greater than VMK_PCI_NUM_BARS
* \retval VMK_OK Query successfully processed.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_PCIQueryIOResources(vmk_PCIDevice pciDevice,
vmk_uint8 numBars,
vmk_PCIResource resources[]);
/*
***********************************************************************
* vmk_PCIFindCapability -- */ /**
*
* \ingroup PCI
* \brief Returns the offset of the capability in device's config space.
*
* \param[in] device PCI device handle
* \param[in] capID Capability ID of interest
* \param[out] capOffset Pointer to the capability offset
*
* \retval VMK_BAD_PARAM If capOffset is NULL or device handle is invalid
* \retval VMK_NOT_FOUND capability is not found
*
***********************************************************************
*/
VMK_ReturnStatus vmk_PCIFindCapability(vmk_PCIDevice device,
vmk_uint8 capID,
vmk_uint16 *capOffset);
/*
***********************************************************************
* vmk_PCIReadConfig -- */ /**
*
* \ingroup PCI
* \brief Read config space of device at offset.
*
* \param[in] moduleID Module performing the config read.
* \param[in] device PCI device handle.
* \param[in] accessType Access 1, 2 or 4 bytes.
* \param[in] offset Offset to read.
* \param[out] data Pointer to the data read.
*
* \note Offset is expected to meet the alignment requirements of the
* specified access type.
*
* \retval VMK_BAD_PARAM Device handle is NULL/invalid.
* \retval VMK_BAD_PARAM Data pointer is NULL.
* \retval VMK_BAD_PARAM Offset is not aligned for the access type.
* \retval VMK_BAD_PARAM AccessType is not a valid access type.
* \retval VMK_NO_PERMISSION Device is not owned by module.
* \retval VMK_LIMIT_EXCEEDED Offset is beyond available config space.
* \retval VMK_FAILURE Failure to access config space.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_PCIReadConfig(vmk_ModuleID moduleID,
vmk_PCIDevice device,
vmk_PCIConfigAccess accessType,
vmk_uint16 offset,
vmk_uint32 *data);
/*
***********************************************************************
* vmk_PCIWriteConfig -- */ /**
*
* \ingroup PCI
* \brief Write data to config space of device at offset.
*
* \param[in] moduleID Module performing the config write.
* \param[in] device PCI device handle.
* \param[in] accessType Access 1, 2 or 4 bytes.
* \param[in] offset Offset to write at.
* \param[in] data Data to write.
*
* \note Offset is expected to meet the alignment requirements of the
* specified access type.
*
* \retval VMK_BAD_PARAM Device handle is NULL/invalid.
* \retval VMK_BAD_PARAM Offset is not aligned for the access type.
* \retval VMK_BAD_PARAM AccessType is not a valid access type.
* \retval VMK_NO_PERMISSION Device is not owned by module.
* \retval VMK_LIMIT_EXCEEDED Offset is beyond available config space.
* \retval VMK_FAILURE Failure to access config space.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_PCIWriteConfig(vmk_ModuleID moduleID,
vmk_PCIDevice device,
vmk_PCIConfigAccess accessType,
vmk_uint16 offset,
vmk_uint32 data);
/*
***********************************************************************
* vmk_PCIMapIOResource -- */ /**
*
* \ingroup PCI
* \brief Reserve and map PCI IO/Memory space described by pciBar.
*
* Reserves the specified BAR with resource manager and maps the memory
* described by pciBar to a virtual address.
*
* \param[in] moduleID Module requesting the resource.
* \param[in] device PCI device handle.
* \param[in] pciBar PCI bar to map, must be [0 - 5].
* \param[out] reservation IOReservation handle. Only necessary for
* VMK_PCI_BAR_FLAGS_IO type BARs.
* \param[out] mappedAddress Pointer to hold the virtual address of
* the mapping.
*
* \retval VMK_BAD_PARAM Device handle is NULL/invalid
* \retval VMK_BAD_PARAM PciBar is invalid
* \retval VMK_BAD_PARAM reservation is NULL for PIO BAR
* \retval VMK_BAD_PARAM MappedAddres is NULL
* \retval VMK_NO_RESOURCES Resource is not owned by device
* \retval VMK_NO_PERMISSION Device is not owned by module
* \retval VMK_BAD_PARAM PciBar is 2nd half of 64-bit MMIO BAR
* \retval VMK_BAD_PARAM PciBar addr/size too big for 32-bit MPN
*
***********************************************************************
*/
VMK_ReturnStatus vmk_PCIMapIOResource(vmk_ModuleID moduleID,
vmk_PCIDevice device,
vmk_uint8 pciBar,
vmk_IOReservation *reservation,
vmk_VA *mappedAddress);
/*
***********************************************************************
* vmk_PCIUnmapIOResource -- */ /**
*
* \ingroup PCI
* \brief Unmap and release the established PCI IO/Memory mapping.
*
* Upon successful return from the call, the mapping is no longer valid.
*
* \param[in] moduleID Module requested the resource.
* \param[in] device PCI device handle.
* \param[in] pciBar PCI bar to unmap.
*
* \retval VMK_BAD_PARAM Device handle is NULL/invalid
* \retval VMK_BAD_PARAM PciBar is invalid
* \retval VMK_BAD_PARAM Resource is not mapped
* \retval VMK_NO_PERMISSION Device is not owned by module
*
***********************************************************************
*/
VMK_ReturnStatus vmk_PCIUnmapIOResource(vmk_ModuleID moduleID,
vmk_PCIDevice device,
vmk_uint8 pciBar);
/**
* Interrupt related functions.
*
* Driver should first allocate interrupt(s), register and enable the
* interrupt(s).
*/
/*
***********************************************************************
* vmk_PCIAllocIntrCookie -- */ /**
*
* \ingroup PCI
* \brief Allocate interrupt resources for the specified device.
*
* On successful return, intrArray will contain the vmk_IntrCookie(s)
* representing the allocated interrupt resources. numIntrsAlloced
* will contain the number of interrupts actually allocated.
*
* \note If type is VMK_PCI_INTERRUPT_TYPE_LEGACY or type is
* VMK_PCI_INTERRUPT_TYPE_MSI then numIntrsDesired and
* numIntrsRequired must both be set to 1.
* \note The caller must provide memory for numIntrsDesired
* vmk_IntrCookie(s) in the space referenced by intrArray.
* \note The caller can specify the index into MSIX table for the
* desired interrupts using indexAarray. indexArray can be NULL
* if the caller does not care. If non-NULL, it should specify
* index for numIntrDesired entries, and intrArray is filled
* with allocated interrupt for requested index values.
*
* \param[in] moduleID Module allocating the interrupts.
* \param[in] device PCI device handle.
* \param[in] type Interrupt type.
* \param[in] numIntrsDesired Number of interrupts desired.
* \param[in] numIntrsRequired Number of interrupts required.
* \param[in] indexArray Array of MSIX table index.
* \param[out] intrArray Array of interrupts allocated.
* \param[out] numIntrsAlloced Number of interrupts allocated.
*
* \retval VMK_BAD_PARAM props argument is NULL.
* \retval VMK_BAD_PARAM Device handle is invalid/NULL.
* \retval VMK_BAD_PARAM Device is not interruptive.
* \retval VMK_BAD_PARAM type is VMK_INTERRUPT_TYPE_PCI_LEGACY
* the ioapic pin the device is connected
* to is not described in interrupt
* routing tables.
* \retval VMK_BAD_PARAM type is VMK_INTERRUPT_TYPE_PCI_LEGACY
* or VMK_INTERRUPT_TYPE_PCI_MSI and
* numIntrsDesired or numIntrsRequired
* is not equal to 1.
* \retval VMK_BAD_PARAM type is VMK_INTERRUPT_TYPE_PCI_MSIX and
* numIntrsAlloced is NULL.
* \retval VMK_BAD_PARAM type is VMK_INTERRUPT_TYPE_PCI_MSIX and
* numIntrsRequired > numIntrsDesired
* \retval VMK_BAD_PARAM All other mal-formed props.
* \retval VMK_NO_MEMORY Internal memory allocation failure
* \retval VMK_NOT_SUPPORTED Device/platform doesn't support MSI or
* MSIX if request is for MSI or MSIX type
* \retval VMK_NO_PERMISSION Device is not owned by module
* \retval VMK_IO_ERROR PCI Bus error, probably device is
* broken or unplugged
* \retval VMK_NO_RESOURCES For MSIX type, the number of interrupts
* available is less than numIntrsRequired.
* \retval VMK_FAILIURE All other errors.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_PCIAllocIntrCookie(vmk_ModuleID moduleID,
vmk_PCIDevice device,
vmk_PCIInterruptType type,
vmk_uint32 numIntrsDesired,
vmk_uint32 numIntrsRequired,
vmk_uint16 *indexArray,
vmk_IntrCookie *intrArray,
vmk_uint32 *numIntrsAlloced);
/*
***********************************************************************
* vmk_PCIFreeIntrCookie -- */ /**
*
* \ingroup PCI
* \brief Free all interrupts that were previously allocated by a call
* to vmk_PCIAllocIntrCookie().
*
* \param[in] moduleID Module that allocated the interrupts
* \param[in] device PCI device handle
*
* \retval VMK_BAD_PARAM Module ID is invalid.
* \retval VMK_BAD_PARAM Device handle is invalid/NULL.
* \retval VMK_NO_PERMISSION Device is not owned by module.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_PCIFreeIntrCookie(vmk_ModuleID moduleID,
vmk_PCIDevice device);
/*
***********************************************************************
* vmk_PCIEnableVFs -- */ /**
*
* \ingroup PCI
* \brief Enable virtual functions in an SR-IOV physical function.
*
* numVFs is the number of virtual functions to be enabled. Setting it to
* zero requests that all virtual functions (VFs) under the given physical
* function (PF) be enabled. The actual number of VFs successfully enabled
* is returned in numVFs upon success.
*
* \note For a native PF driver, this function must be called from the
* driver's vmk_DriverAttachDevice() callback. This will ensure VFs are
* enabled before the driver receives the vmk_DriverScanDevice() callback,
* and also prevent VFs from being re-enabled if the PF is quiesced
* and re-started.
*
* \note This function creates a vmk_PCIDevice handle for each VF. The
* handle of each VF can be retrieved via the function
* vmk_PCIGetVFPCIDevice().
*
* \param[in] pf PCI device handle of the SR-IOV PF.
* \param[in,out] numVFs Number of VFs to enable/enabled.
*
* \retval VMK_BAD_PARAM Device handle is invalid or device does not exist.
* \retval VMK_FAILURE Cannot enable virtual functions.
*
***********************************************************************
*/
VMK_ReturnStatus
vmk_PCIEnableVFs(vmk_PCIDevice pf,
vmk_uint16 *numVFs);
/*
***********************************************************************
* vmk_PCIDisableVFs -- */ /**
*
* \ingroup PCI
* \brief Disable all virtual functions in an SR-IOV physical function.
*
* \note For a native PF driver, this function must be called from the
* driver's vmk_DriverDetachDevice() callback. This will ensure that
* all virtual functions (VFs) being disabled have been un-registered
* with the vmkkernel's device layer (i.e., unregistration occurs in the
* PF driver's VF remove callback which occurs prior to
* vmkDriverDetachDevice()). In addition, this will also prevent VFs from
* being disabled if the PF is quiesced.
*
* \param[in] pf PCI device handle of physical function (PF).
*
* \retval VMK_BAD_PARAM Device handle is invalid or device does not exist.
* \retval VMK_FAILURE Device is not in SR-IOV mode.
*
***********************************************************************
*/
VMK_ReturnStatus
vmk_PCIDisableVFs(vmk_PCIDevice pf);
/*
***********************************************************************
* vmk_PCIGetVFPCIDevice -- */ /**
*
* \ingroup PCI
* \brief Retrieves the PCI device handle of a virtual function (VF).
*
* \note This function should only be called on enabled VFs (see
* vmk_PCIEnableVF()).
*
* \param[in] pf PCI device handle of the parent physical function.
* \param[in] vfIndex Index of the virtual function.
* \param[out] vf PCI device handle of the requested virtual function.
*
* \retval VMK_BAD_PARAM PF device handle is invalid or device does not exist.
* \retval VMK_BAD_PARAM VF device handle argument is NULL.
* \retval VMK_NOT_FOUND VF doesn't exist.
*
***********************************************************************
*/
VMK_ReturnStatus
vmk_PCIGetVFPCIDevice(vmk_PCIDevice pf,
vmk_uint16 vfIndex,
vmk_PCIDevice *vf);
/*
***********************************************************************
* vmk_PCIGetPFPCIDevice -- */ /**
*
* \ingroup PCI
* \brief Retrieve the PCI device handle of a PF, given the VF handle.
*
* \param[in] vf PCI device handle of the virtual function.
* \param[out] pf PCI device handle of the parent physical function.
*
* \retval VMK_BAD_PARAM VF device handle is invalid or device does not exist.
* \retval VMK_BAD_PARAM PF device handle argument is NULL.
*
***********************************************************************
*/
VMK_ReturnStatus
vmk_PCIGetPFPCIDevice(vmk_PCIDevice vf, vmk_PCIDevice *pf);
/*
************************************************************************
* vmk_PCIRegisterVF -- */ /**
*
* \ingroup PCI
* \brief Register virtual functions with the vmkernel's device layer.
*
* The devOps parameter is the vmk_DeviceOps structure associated with the
* registered virtual function (VF).
*
* \note This function is meant to be used by native PF drivers only.
* Since this function registers a VF with the vmkernel's device layer,
* all restrictions associated with device registration apply.
*
* \note Before this call returns, the vmkernel's device layer may attach
* the VF to a driver.
*
* \param[in] vf PCI device handle of the VF to be registered.
* \param[in] pf PCI device handle of the parent PF.
* \param[in] pfDriverHandle PF driver handle.
* \param[in] vfDevOps Device operations associated with a registered VF.
*
* \retval VMK_BAD_PARAM VF device handle is invalid.
* \retval VMK_BAD_PARAM PF device handle is invalid.
* \retval VMK_FAILURE VF registration failed.
*
************************************************************************
*/
VMK_ReturnStatus
vmk_PCIRegisterVF(vmk_PCIDevice vf,
vmk_PCIDevice pf,
vmk_Driver pfDriverHandle,
vmk_PCIVFDeviceOps *vfDevOps);
/*
************************************************************************
* vmk_PCIUnregisterVF -- */ /**
*
* \ingroup PCI
* \brief Unregister a virtual function from the vmkernel's device layer.
*
* \note Since this function unregisters a virtual function (VF) with the
* vmkernel's device layer, all restrictions associated with device
* unregistration apply (unregistration of the VF must be done
* by the physical function driver from the vmk_DeviceRemove function in the
* vmk_DeviceOps passed during VF registration).
*
* \param[in] vf PCI device handle of the VF to be unregistered.
*
* \retval VMK_BAD_PARAM VF device handle is invalid.
* \retval VMK_FAILURE VF unregistration failed.
*
*************************************************************************
*/
VMK_ReturnStatus
vmk_PCIUnregisterVF(vmk_PCIDevice vf);
/*
*************************************************************************
* vmk_PCISetVFPrivateData -- */ /**
*
* \ingroup PCI
* \brief Associate private data with a virtual function.
*
* Associates a pointer to the given user-defined private data with the
* given virtual function (VF). The pointer may retrieved via the
* function vmk_PCIGetVFPrivateData(). This provides a mechanism by which
* vmkernel components, typically a PF driver and a VF driver, can exchange
* private data.
*
* \param[in] vf PCI device handle of the VF.
* \param[in] privateData User-defined private data.
*
* \retval VMK_BAD_PARAM VF device handle is invalid.
*
************************************************************************
*/
VMK_ReturnStatus
vmk_PCISetVFPrivateData(vmk_PCIDevice vf,
vmk_AddrCookie privateData);
/*
*************************************************************************
* vmk_PCIGetVFPrivateData -- */ /**
*
* \ingroup PCI
* \brief Retrieve private data associated with a virtual function.
*
* Retrieves a pointer to the user-defined private data associated with
* the given virtual function (VF). See the description of
* vmk_PCISetVFPrivateData() for further details.
*
* \param[in] vf PCI device handle of the VF.
* \param[out] privateData User-defined private data.
*
* \retval VMK_BAD_PARAM VF device handle is invalid.
* \retval VMK_BAD_PARAM privateData pointer is NULL.
*
************************************************************************
*/
VMK_ReturnStatus
vmk_PCIGetVFPrivateData(vmk_PCIDevice vf,
vmk_AddrCookie *privateData);
/*
***********************************************************************
* vmk_PCIEnablePME -- */ /**
*
* \ingroup PCI
* \brief Enable PME# generation.
*
* Enable PME# generation if the device is capable of asserting
* the PME# signal from any of the power states.
*
* \param[in] moduleID Module requesting the operation.
* \param[in] device PCI device handle.
*
* \retval VMK_BAD_PARAM Module ID is invalid.
* \retval VMK_BAD_PARAM Device handle is NULL/invalid.
* \retval VMK_NO_PERMISSION Device is not owned by module.
* \retval VMK_NOT_SUPPORTED Device has no PM capability.
* \retval VMK_NOT_SUPPORTED Device doesn't support PME# generation
* from any power state.
*
***********************************************************************
*/
VMK_ReturnStatus
vmk_PCIEnablePME(vmk_ModuleID moduleID,
vmk_PCIDevice device);
/*
***********************************************************************
* vmk_PCIDisablePME -- */ /**
*
* \ingroup PCI
* \brief Disable PME# generation.
*
* Disable PME# generation if the device is capable of asserting
* the PME# signal from any of the power states.
*
* \param[in] moduleID Module requesting the operation.
* \param[in] device PCI device handle.
*
* \retval VMK_BAD_PARAM Module ID is invalid.
* \retval VMK_BAD_PARAM Device handle is NULL/invalid.
* \retval VMK_NO_PERMISSION Device is not owned by module.
* \retval VMK_NOT_SUPPORTED Device has no PM capability.
* \retval VMK_NOT_SUPPORTED Device doesn't support PME# generation
* from any power state.
*
***********************************************************************
*/
VMK_ReturnStatus
vmk_PCIDisablePME(vmk_ModuleID moduleID,
vmk_PCIDevice device);
#endif /* _VMKAPI_PCI_H_ */
/** @} */
/** @} */

View file

@ -42,7 +42,7 @@ typedef enum vmk_PCIInterruptType {
/** /**
* \brief Opaque PCI device handle * \brief Opaque PCI device handle
*/ */
typedef struct vmk_PCIDeviceInt *vmk_PCIDevice; typedef struct vmkPCIDevice *vmk_PCIDevice;
#endif #endif

View file

@ -0,0 +1,37 @@
/* **********************************************************
* Copyright 2012 VMware, Inc. All rights reserved.
* **********************************************************/
/*
* @VMKAPIMOD_LICENSE@
*/
/*
***********************************************************************
* PSA */ /**
* \addtogroup Device
* @{
* \defgroup PSA PSA Driver Interfaces
* @{
***********************************************************************
*/
#ifndef _VMKAPI_PSA_H_
#define _VMKAPI_PSA_H_
/** \cond never */
#ifndef VMK_HEADER_INCLUDED_FROM_VMKAPI_H
#error This vmkapi file should never be included directly but only via vmkapi.h
#endif
/** \endcond never */
/** \brief PSA Device Identifier */
#define VMK_SCSI_PSA_DRIVER_BUS_ID "com.vmware.HBAPort"
/** \brief PSA VPORT Device Identifier */
#define VMK_SCSI_PSA_DRIVER_VPORT_BUS_ID "com.vmware.Virtual_HBAPort"
#endif /* _VMKAPI_PSA_H_ */
/** @} */
/** @} */

View file

@ -0,0 +1,191 @@
/* **********************************************************
* Copyright 2008 - 2012 VMware, Inc. All rights reserved.
* **********************************************************/
/*
* Please consult with the VMKernel hardware and core teams before making any
* binary incompatible changes to this file!
*/
/*
* @VMKAPIMOD_LICENSE@
*/
/*
***********************************************************************
* Vector */ /**
* \addtogroup Device
* @{
* \defgroup Vector Interrupt Interfaces
* @{
***********************************************************************
*/
#ifndef _VMKAPI_VECTOR_H_
#define _VMKAPI_VECTOR_H_
/** \cond never */
#ifndef VMK_HEADER_INCLUDED_FROM_VMKAPI_H
#error This vmkapi file should never be included directly but only via vmkapi.h
#endif
/** \endcond never */
/** \brief Interrupt is an entropy source.
*
* Set this if device interrupts contributes to entropy pool.
*/
#define VMK_INTR_ATTRS_ENTROPY_SOURCE (1 << 0)
/**
* \brief Properties for registering the interrupt.
*/
typedef struct vmk_IntrProps {
/** \brief Device registering the interrupt. */
vmk_Device device;
/** \brief Name of the device registering the interrupt. */
vmk_Name deviceName;
/** \brief Interrupt acknowledging function */
vmk_IntrAcknowledge acknowledgeInterrupt;
/** \brief Interrupt handler function. */
vmk_IntrHandler handler;
/** \brief Interrupt handler client data. */
void *handlerData;
/** \brief Interrupt attributes.
*
* Interrupt attributes can be used to specify special attributes
* for a interrupt.
*/
vmk_uint64 attrs;
} vmk_IntrProps;
/** \brief Function to invoke with interrupts disabled. */
typedef void (*vmk_IntrDisabledFunc)(vmk_AddrCookie data);
/*
***********************************************************************
* vmk_IntrRegister -- */ /**
*
* \ingroup Vector
* \brief Register the interrupt with the system.
*
* \note Interrupt sharing is implicitly allowed for level-triggered
* interrupts.
*
* \param[in] moduleID Module registering the interrupt
* \param[in] intrCookie Interrupt cookie to register
* \param[in] props Properties of the interrupt being registered
*
* \retval VMK_BAD_PARAM props is NULL or mal-formed props
* \retval VMK_BAD_PARAM intrCookie is not valid
* \retval VMK_BAD_PARAM Null props->handlerData is specified for
* shared interrupt.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_IntrRegister(vmk_ModuleID moduleID,
vmk_IntrCookie intrCookie,
vmk_IntrProps *props);
/*
***********************************************************************
* vmk_IntrUnregister -- */ /**
*
* \ingroup Vector
* \brief Unregister a previously registered interrupt.
*
* \param[in] moduleID Module that registered interrupt before
* \param[in] intrCookie Interrupt to unregister
* \param[in] handlerData Interrupt handler data that was used while
* registering the interrupt
*
* \retval VMK_BAD_PARAM moduleID is not valid.
* \retval VMK_BAD_PARAM intrCookie is not valid.
* \retval VMK_BAD_PARAM If handlerData is NULL and the interrupt is
* shared.
* \retval VMK_FAILURE handlerData doesn't match with what's
* provided with vmk_IntrRegister().
*
***********************************************************************
*/
VMK_ReturnStatus vmk_IntrUnregister(vmk_ModuleID moduleID,
vmk_IntrCookie intrCookie,
void *handlerData);
/*
***********************************************************************
* vmk_IntrEnable -- */ /**
*
* \ingroup Vector
* \brief Start interrupt delivery. Kernel starts calling interrupt
* handlers registered for this interrupt.
*
* \note The interrupt is unmasked if needed.
*
* \param[in] intrCookie Interrupt that has to be started.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_IntrEnable(vmk_IntrCookie intrCookie);
/*
***********************************************************************
* vmk_IntrDisable -- */ /**
*
* \ingroup Vector
* \brief Stops interrupt delivery.
*
* \note The interrupt is masked if there are no registered handlers
* for this interrupt.
*
* \warning This API should not be used for indefinite periods for
* shared interrupts as this will block interrupts for other
* devices that may share the same interrupt line.
*
* \param[in] intrCookie Interrupt that has to be stopped.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_IntrDisable(vmk_IntrCookie intrCookie);
/*
***********************************************************************
* vmk_IntrSync -- */ /**
*
* \ingroup Vector
* \brief Blocks, waiting till interrupt is inactive on all CPUs.
*
* \param[in] intrCookie Interrupt to synchronize.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_IntrSync(vmk_IntrCookie intrCookie);
/*
***********************************************************************
* vmk_IntrWithAllDisabledInvoke -- */ /**
*
* \ingroup Vector
* \brief Invokes a function with all interrupts disabled.
*
* \warning The function invoked is not allowed to take more than 5us.
*
* \param[in] moduleID Module implementing function to invoke.
* \param[in] func Function to invoke
* \param[in] data Data to pass to function
*
* \retval VMK_BAD_PARAM moduleID is invalid
* \retval VMK_BAD_PARAM func is invalid
* \retval VMK_OK func was invoked
*
***********************************************************************
*/
VMK_ReturnStatus vmk_IntrWithAllDisabledInvoke(vmk_ModuleID moduleID,
vmk_IntrDisabledFunc func,
vmk_AddrCookie data);
#endif /* _VMKAPI_VECTOR_H_ */
/** @} */
/** @} */

View file

@ -1,5 +1,5 @@
/* ********************************************************** /* **********************************************************
* Copyright 2010 VMware, Inc. All rights reserved. * Copyright 2010 - 2012 VMware, Inc. All rights reserved.
* **********************************************************/ * **********************************************************/
/* /*
@ -26,6 +26,15 @@
#endif #endif
/** \endcond never */ /** \endcond never */
/**
* \brief Opaque handle to Interrupt.
*/
typedef vmk_uint32 vmk_IntrCookie;
/**
* \brief Invalid interrupt.
*/
#define VMK_INVALID_INTRCOOKIE ((vmk_IntrCookie)~0)
/* /*
****************************************************************************** ******************************************************************************
@ -45,7 +54,61 @@
*/ */
typedef void (*vmk_InterruptHandler)(void *clientData, typedef void (*vmk_InterruptHandler)(void *clientData,
vmk_uint32 vector); vmk_IntrCookie intrCookie);
/*
******************************************************************************
* vmk_IntrHandler -- */ /**
*
* \brief Interrupt callback function.
*
* \note Callback is allowed to block
*
* \param[in] handlerData Callback argument specified while adding
* the handler.
* \param[in] intrCookie Interrupt cookie associated with the interrupt.
*
* \retval None
*
******************************************************************************
*/
typedef void (*vmk_IntrHandler)(void *handlerData,
vmk_IntrCookie intrCookie);
/*
******************************************************************************
* vmk_IntrAcknowledge -- */ /**
*
* \brief Callback function for device drivers to acknowledge an interrupt
*
* This callback is called synchronously when an interrupt fires to do device
* specific interrupt acknowledgement. The handler is expected to acknowledge
* the interrupt with the device for example through device register writes but
* nothing more. All other interrupt work should be done in the interrupt
* handler which will be called in a world context. The vmkernel will enforce a
* very short execution time of 5us for this callback.
*
* \note Callback is not allowed to block
*
* \param[in] handlerData Callback argument specified while adding
* the handler.
* \param[in] intrCookie Interrupt cookie associated with the interrupt.
*
* \retval VMK_OK Interrupt has been acknowledged and handler
* should be called.
* \retval VMK_IGNORE Interrupt was for this device and has been
* acknowledged, but handler is not needed and
* should not be called.
* \retval VMK_NOT_THIS_DEVICE Interrupt was not for this device and has not
* been acknowledged; handler should not be called.
*
******************************************************************************
*/
typedef VMK_ReturnStatus (*vmk_IntrAcknowledge)(void *handlerData,
vmk_IntrCookie intrCookie);
#endif #endif
/** @} */ /** @} */

View file

@ -744,6 +744,11 @@ typedef enum vmk_DVFilterPropertyOpsFlags {
* *
* \retval VMK_OK DVFilter accepts value change of the * \retval VMK_OK DVFilter accepts value change of the
* property on the instance * property on the instance
* \retval VMK_NOT_READY DVFilter cannot accept value change of the
* property on the instance. Likely due to
* temporarily invalid filter. Write will be
* called again with same data after filter
* is established.
* \retval VMK_FAILURE DVFilter does not accept the value change * \retval VMK_FAILURE DVFilter does not accept the value change
* of the property on the instance * of the property on the instance
*********************************************************************** ***********************************************************************
@ -875,6 +880,8 @@ typedef struct vmk_DVFilterPropertyOps {
* \ingroup DVFilter * \ingroup DVFilter
* \brief Register a DVFilter fast path agent with the network stack. * \brief Register a DVFilter fast path agent with the network stack.
* *
* \nativedriversdisallowed
*
* \note This function may block. * \note This function may block.
* *
* \param[in] name Human readable name of the agent. * \param[in] name Human readable name of the agent.
@ -920,6 +927,8 @@ VMK_ReturnStatus vmk_DVFilterRegisterFastPath(
* \brief Unregister a DVFilter fast path agent previously registered * \brief Unregister a DVFilter fast path agent previously registered
* by vmk_DVFilterRegisterFastPath. * by vmk_DVFilterRegisterFastPath.
* *
* \nativedriversdisallowed
*
* \note This function may block. * \note This function may block.
* *
* \param[in] fastPathHandle Handle to the VMkernel fast path agent. * \param[in] fastPathHandle Handle to the VMkernel fast path agent.
@ -940,6 +949,8 @@ VMK_ReturnStatus vmk_DVFilterUnregisterFastPath(
* \ingroup DVFilter * \ingroup DVFilter
* \brief Associate a filter with the specified slow path agent. * \brief Associate a filter with the specified slow path agent.
* *
* \nativedriversdisallowed
*
* \note This function will not block. * \note This function will not block.
* *
* Once the association is established, packets can be forwarded to * Once the association is established, packets can be forwarded to
@ -992,6 +1003,8 @@ vmk_DVFilterSetSlowPath(
* \ingroup DVFilter * \ingroup DVFilter
* \brief Dissociate a filter from its slow path agent. * \brief Dissociate a filter from its slow path agent.
* *
* \nativedriversdisallowed
*
* \note This function will not block. * \note This function will not block.
* *
* This function has no effect if the filter has no associated slow * This function has no effect if the filter has no associated slow
@ -1028,6 +1041,8 @@ vmk_DVFilterClearSlowPath(
* \ingroup DVFilter * \ingroup DVFilter
* \brief Allocate metadata for this packet. * \brief Allocate metadata for this packet.
* *
* \nativedriversdisallowed
*
* \note This function will not block. * \note This function will not block.
* *
* The allocated metadata buffer can be used to store data * The allocated metadata buffer can be used to store data
@ -1074,6 +1089,8 @@ VMK_ReturnStatus vmk_DVFilterPktAllocMetadata(
* \ingroup DVFilter * \ingroup DVFilter
* \brief Release metadata for this packet. * \brief Release metadata for this packet.
* *
* \nativedriversdisallowed
*
* \note This function will not block. * \note This function will not block.
* *
* Releases the metadata of this packet. Afterwards, the scope of * Releases the metadata of this packet. Afterwards, the scope of
@ -1096,6 +1113,8 @@ void vmk_DVFilterPktReleaseMetadata(
* \ingroup DVFilter * \ingroup DVFilter
* \brief Get pointer to metadata of this packet. * \brief Get pointer to metadata of this packet.
* *
* \nativedriversdisallowed
*
* \note This function will not block. * \note This function will not block.
* *
* Gets the address of the metadata associated with this packet, * Gets the address of the metadata associated with this packet,
@ -1123,6 +1142,8 @@ vmk_VA vmk_DVFilterPktGetMetadata(
* \brief Fault specified packets to the slow path agent associated * \brief Fault specified packets to the slow path agent associated
* with the filter. * with the filter.
* *
* \nativedriversdisallowed
*
* \note This function will not block. * \note This function will not block.
* *
* \note Unless the VMK_DVFILTER_FAULTING_COPY flag is used, the * \note Unless the VMK_DVFILTER_FAULTING_COPY flag is used, the
@ -1157,6 +1178,8 @@ VMK_ReturnStatus vmk_DVFilterFaultPackets(
* \ingroup DVFilter * \ingroup DVFilter
* \brief Inject packets in a filter. * \brief Inject packets in a filter.
* *
* \nativedriversdisallowed
*
* \note This function will not block. * \note This function will not block.
* *
* Used to inject new packets, or resume processing of packets * Used to inject new packets, or resume processing of packets
@ -1215,6 +1238,8 @@ VMK_ReturnStatus vmk_DVFilterIssuePackets(
* \ingroup DVFilter * \ingroup DVFilter
* \brief Query the human readable name of the DVFilter. * \brief Query the human readable name of the DVFilter.
* *
* \nativedriversdisallowed
*
* \note This function will not block. * \note This function will not block.
* *
* \param[in] filter Handle to the VMkernel filter object * \param[in] filter Handle to the VMkernel filter object
@ -1240,6 +1265,8 @@ VMK_ReturnStatus vmk_DVFilterGetName(
* \ingroup DVFilter * \ingroup DVFilter
* \brief Query the VM UUID of the VM the DVFilter is attached to. * \brief Query the VM UUID of the VM the DVFilter is attached to.
* *
* \nativedriversdisallowed
*
* \note This function will not block. * \note This function will not block.
* *
* \note This function may fail with VMK_INVALID_WORLD in the * \note This function may fail with VMK_INVALID_WORLD in the
@ -1273,6 +1300,8 @@ VMK_ReturnStatus vmk_DVFilterGetVMUUID(
* \ingroup DVFilter * \ingroup DVFilter
* \brief Query a configuration parameter value of the DVFilter. * \brief Query a configuration parameter value of the DVFilter.
* *
* \nativedriversdisallowed
*
* \note This function will not block. * \note This function will not block.
* *
* These parameters may change at any time if the fastpath op * These parameters may change at any time if the fastpath op
@ -1309,6 +1338,8 @@ VMK_ReturnStatus vmk_DVFilterGetConfigParameter(
* \ingroup DVFilter * \ingroup DVFilter
* \brief Get the failure policy the user configured for this filter. * \brief Get the failure policy the user configured for this filter.
* *
* \nativedriversdisallowed
*
* \note This function will not block. * \note This function will not block.
* *
* \param[in] filter Handle to the VMkernel filter object. * \param[in] filter Handle to the VMkernel filter object.
@ -1332,6 +1363,8 @@ VMK_ReturnStatus vmk_DVFilterGetFailurePolicy(
* \ingroup DVFilter * \ingroup DVFilter
* \brief Get the MTU the switch has configured for this filter * \brief Get the MTU the switch has configured for this filter
* *
* \nativedriversdisallowed
*
* \note This function will not block. * \note This function will not block.
* *
* Value of *mtu is not defined in case the function was not successful. * Value of *mtu is not defined in case the function was not successful.
@ -1366,6 +1399,8 @@ VMK_ReturnStatus vmk_DVFilterGetSwitchMTU(
* \ingroup DVFilter * \ingroup DVFilter
* \brief Get the type of the filter's end-point. * \brief Get the type of the filter's end-point.
* *
* \nativedriversdisallowed
*
* \note This function will not block. * \note This function will not block.
* *
* The filter end-point might be a virtual nic of a VM, a VMkernel * The filter end-point might be a virtual nic of a VM, a VMkernel
@ -1394,6 +1429,8 @@ VMK_ReturnStatus vmk_DVFilterGetEndPointType(
* \ingroup DVFilter * \ingroup DVFilter
* \brief Get the portID that the filter is attached to. * \brief Get the portID that the filter is attached to.
* *
* \nativedriversdisallowed
*
* \note This function will not block. * \note This function will not block.
* *
* \param[in] filter Handle to the VMkernel filter object. * \param[in] filter Handle to the VMkernel filter object.
@ -1416,6 +1453,8 @@ VMK_ReturnStatus vmk_DVFilterGetPortID(
* \ingroup DVFilter * \ingroup DVFilter
* \brief Get the index of the vNic this filter is attached to. * \brief Get the index of the vNic this filter is attached to.
* *
* \nativedriversdisallowed
*
* \note This function will not block. * \note This function will not block.
* *
* This function is only supported for VM endpoints. * This function is only supported for VM endpoints.
@ -1442,6 +1481,8 @@ VMK_ReturnStatus vmk_DVFilterGetVnicIndex(
* \ingroup DVFilter * \ingroup DVFilter
* \brief Set the minimum mapped packet length required by this filter. * \brief Set the minimum mapped packet length required by this filter.
* *
* \nativedriversdisallowed
*
* \note This function will not block. * \note This function will not block.
* *
* The function requests new packets to have a specific * The function requests new packets to have a specific
@ -1480,6 +1521,8 @@ vmk_DVFilterSetMinPktMappedLen(
* \brief Send an ioctl request associated with a particular filter to * \brief Send an ioctl request associated with a particular filter to
* the slow path. * the slow path.
* *
* \nativedriversdisallowed
*
* \note This function will not block. * \note This function will not block.
* *
* Send an ioctl request to the slow path agent associated with the * Send an ioctl request to the slow path agent associated with the
@ -1537,6 +1580,8 @@ VMK_ReturnStatus vmk_DVFilterSendFilterIoctlRequest(
* \ingroup DVFilter * \ingroup DVFilter
* \brief Send an ioctl reply in filter context to the guest appliance. * \brief Send an ioctl reply in filter context to the guest appliance.
* *
* \nativedriversdisallowed
*
* \note This function will not block. * \note This function will not block.
* *
* Send an ioctl reply to the slow path agent associated with the * Send an ioctl reply to the slow path agent associated with the
@ -1575,6 +1620,8 @@ VMK_ReturnStatus vmk_DVFilterSendFilterIoctlReply(
* \ingroup DVFilter * \ingroup DVFilter
* \brief Send an ioctl request to a slow path agent. * \brief Send an ioctl request to a slow path agent.
* *
* \nativedriversdisallowed
*
* \note This function will not block. * \note This function will not block.
* *
* Send an ioctl request to the slow path agent. The provided * Send an ioctl request to the slow path agent. The provided
@ -1630,6 +1677,8 @@ VMK_ReturnStatus vmk_DVFilterSendSlowPathIoctlRequest(
* \ingroup DVFilter * \ingroup DVFilter
* \brief Send an ioctl reply to a slow path agent. * \brief Send an ioctl reply to a slow path agent.
* *
* \nativedriversdisallowed
*
* \note This function will not block. * \note This function will not block.
* *
* It is acceptable to send a slow path reply with a zero length. * It is acceptable to send a slow path reply with a zero length.
@ -1667,6 +1716,8 @@ VMK_ReturnStatus vmk_DVFilterSendSlowPathIoctlReply(
* \ingroup DVFilter * \ingroup DVFilter
* \brief Restore slow path state in the guest appliance * \brief Restore slow path state in the guest appliance
* *
* \nativedriversdisallowed
*
* \note This function will not block. * \note This function will not block.
* *
* The slow path's state is sent to the slow path agent. The provided * The slow path's state is sent to the slow path agent. The provided
@ -1717,6 +1768,8 @@ VMK_ReturnStatus vmk_DVFilterRestoreSlowPathState(
* \ingroup DVFilter * \ingroup DVFilter
* \brief Retrieve slow path state from the guest appliance. * \brief Retrieve slow path state from the guest appliance.
* *
* \nativedriversdisallowed
*
* \note This function will not block. * \note This function will not block.
* *
* The slow path agent is asked to provide its state. The provided * The slow path agent is asked to provide its state. The provided
@ -1763,6 +1816,8 @@ VMK_ReturnStatus vmk_DVFilterRetrieveSlowPathState(
* \ingroup DVFilter * \ingroup DVFilter
* \brief Set the src port to the port this filter is installed on. * \brief Set the src port to the port this filter is installed on.
* *
* \nativedriversdisallowed
*
* \note This function will not block. * \note This function will not block.
* *
* Set the packet source port identification field to the port * Set the packet source port identification field to the port
@ -1811,6 +1866,8 @@ VMK_ReturnStatus vmk_DVFilterPktSetSourcePort(
* \ingroup DVFilter * \ingroup DVFilter
* \brief Allocate a packet tag for the indicated fast path agent. * \brief Allocate a packet tag for the indicated fast path agent.
* *
* \nativedriversdisallowed
*
* \note This function will not block. * \note This function will not block.
* *
* DVFilter provides for tagging pkts as an aid in * DVFilter provides for tagging pkts as an aid in
@ -1843,6 +1900,8 @@ VMK_ReturnStatus vmk_DVFilterAllocPktTag(
* \ingroup DVFilter * \ingroup DVFilter
* \brief Free all the packet tags allocated by the supplied agent. * \brief Free all the packet tags allocated by the supplied agent.
* *
* \nativedriversdisallowed
*
* \note This function will not block. * \note This function will not block.
* *
* One or more pkt tags, each one bit, acquired from * One or more pkt tags, each one bit, acquired from
@ -1863,6 +1922,8 @@ void vmk_DVFilterFreePktTags(
* \ingroup DVFilter * \ingroup DVFilter
* \brief Tag the packet with the specified tag. * \brief Tag the packet with the specified tag.
* *
* \nativedriversdisallowed
*
* \note This function will not block. * \note This function will not block.
* *
* \pre The tag must belong to the supplied fast path agent. * \pre The tag must belong to the supplied fast path agent.
@ -1913,6 +1974,8 @@ VMK_ReturnStatus vmk_DVFilterPktSetTags(
* \ingroup DVFilter * \ingroup DVFilter
* \brief Clear a fast path's tags from a packet. * \brief Clear a fast path's tags from a packet.
* *
* \nativedriversdisallowed
*
* \note This function will not block. * \note This function will not block.
* *
* Clear the tag or tag bits of the pkt with respect to the * Clear the tag or tag bits of the pkt with respect to the
@ -1958,6 +2021,8 @@ VMK_ReturnStatus vmk_DVFilterPktClearTags(
* \ingroup DVFilter * \ingroup DVFilter
* \brief Query the values of one or more bits from the pkt tag. * \brief Query the values of one or more bits from the pkt tag.
* *
* \nativedriversdisallowed
*
* \note This function will not block. * \note This function will not block.
* *
* Query the tag bits set on a packet. * Query the tag bits set on a packet.
@ -1978,6 +2043,7 @@ VMK_ReturnStatus vmk_DVFilterPktClearTags(
* \retval VMK_NOT_FOUND fastPathHandle parameter invalid. * \retval VMK_NOT_FOUND fastPathHandle parameter invalid.
* \retval VMK_FAILURE getMask contains a bit not allocated for * \retval VMK_FAILURE getMask contains a bit not allocated for
* this agent. * this agent.
* \retval VMK_BAD_PARAM setMask is NULL
* *
*********************************************************************** ***********************************************************************
*/ */
@ -1994,6 +2060,8 @@ VMK_ReturnStatus vmk_DVFilterGetPktTags(
* *
* \brief Register property operations for a DVFilter * \brief Register property operations for a DVFilter
* *
* \nativedriversdisallowed
*
* DVFilter implementation calls this interface to register a property * DVFilter implementation calls this interface to register a property
* handler for a property of a given name. The property name must * handler for a property of a given name. The property name must
* start with the agent name pass to vmk_DVFilterRegisterFastPath(). * start with the agent name pass to vmk_DVFilterRegisterFastPath().
@ -2026,6 +2094,8 @@ VMK_ReturnStatus vmk_DVFilterPropertyRegister(
* *
* \brief Unregister a DVFilter Client * \brief Unregister a DVFilter Client
* *
* \nativedriversdisallowed
*
* The handle is the token obtained from vmk_DVFilterPropertyRegister(). * The handle is the token obtained from vmk_DVFilterPropertyRegister().
* *
* \param[in] handle Handle for DVFilter property registration * \param[in] handle Handle for DVFilter property registration
@ -2045,6 +2115,8 @@ VMK_ReturnStatus vmk_DVFilterPropertyUnregister(
* *
* \brief Increment a DVFilter client stat. * \brief Increment a DVFilter client stat.
* *
* \nativedriversdisallowed
*
* Updates the DVFilter's client stat of the specified type in the * Updates the DVFilter's client stat of the specified type in the
* specified direction. * specified direction.
* *
@ -2073,6 +2145,8 @@ VMK_ReturnStatus vmk_DVFilterStatInc(
* *
* \brief Get the current value of a DVFilter client stat. * \brief Get the current value of a DVFilter client stat.
* *
* \nativedriversdisallowed
*
* Fetches the DVFilter's client stat of the specified type in the * Fetches the DVFilter's client stat of the specified type in the
* specified direction. * specified direction.
* *

View file

@ -0,0 +1,653 @@
/* **********************************************************
* Copyright 2012 VMware, Inc. All rights reserved.
* **********************************************************/
/*
* @VMKAPIMOD_LICENSE@
*/
/*
***********************************************************************
* BitVector */ /**
*
* \addtogroup Lib
* @{
* \defgroup vmk_BitVector Bit Vector Manipulation
*
* Utility interfaces for managing a Bit Vector.
* \par Example - Using VMK_BITVECTOR_ITERATE or VMK_BITVECTOR_ITERATE_AND_CLEAR
* and VMK_BITVECTOR_ENDITERATE
*
* \code
* {
* vmk_uint32 n;
* VMK_BITVECTOR_ITERATE(_bv,n) {
* printf("%d is in set\n",n);
* }
* VMK_BITVECTOR_ENDITERATE()
* }
* \endcode
*
* @{
***********************************************************************
*/
#ifndef _VMKAPI_BITVECTOR_H_
#define _VMKAPI_BITVECTOR_H_
/** \cond never */
#ifndef VMK_HEADER_INCLUDED_FROM_VMKAPI_H
#error This vmkapi file should never be included directly but only via vmkapi.h
#endif
/** \endcond never */
/**
* \brief Incomplete Abstract Data type allocated to be larger than
* sizeof(vmk_BitVector). Should only be allocated by
* vmk_BitVectorAlloc.
* Clients should only use the returned pointer.
*/
typedef struct vmk_BitVector {
vmk_uint32 n;
vmk_uint32 nwords;
vmk_uint32 vector[1];
} vmk_BitVector;
/*
*******************************************************************************
* vmk_BitVectorSize -- */ /**
*
* \brief Size of vmk_BitVector for a given number of bits
*
* \param[in] n Number of bits to size for
*
* \retval size calculation of a vmk_BitVector
*
*******************************************************************************
*/
#define vmk_BitVectorSize(n) \
(sizeof(vmk_uint32) /* n */ + \
sizeof(vmk_uint32) /* nwords */ + \
((n + 31) / 32) * sizeof(vmk_uint32)) /* n bits rounded up to words */
/*
*******************************************************************************
* vmk_BitVectorAllocWithTimeout -- */ /**
*
* \brief Allocate a bitvector with timeout
*
* \param[in] heap vmk_HeapID to allocate the vmk_BitVector from
* \param[in] n Total number of bits to allocate for
* \param[in] timeoutMs vmk_BitVector to set a bit
*
* \note If timeoutMS is not 0 then the allocation may block if the
* heap needs to expand to accomodate the request.
*
* \retval vmk_BitVector pointer or NULL.
*
*******************************************************************************
*/
vmk_BitVector* vmk_BitVectorAllocWithTimeout(vmk_HeapID heap,
vmk_uint32 n,
vmk_uint32 timeoutMs);
/*
*******************************************************************************
* vmk_BitVectorAlloc -- */ /**
*
* \brief Allocate a bitvector
*
* \param[in] heap vmk_HeapID to allocate the vmk_BitVector from
* \param[in] n Total number of bits to allocate for
*
* \retval vmk_BitVector pointer or NULL.
*
*******************************************************************************
*/
vmk_BitVector* vmk_BitVectorAlloc(vmk_HeapID heap,
vmk_uint32 n);
/*
*******************************************************************************
* vmk_BitVectorDuplicate -- */ /**
*
* \brief Allocate a vmk_BitVector and initialise it from another vmk_BitVector
*
* \param[in] heap vmk_HeapID to allocate the vmk_BitVector from
* \param[in] src Source vmk_BitVector to copy into the new vmk_BitVector
*
* \retval new vmk_BitVector pointer
*
*******************************************************************************
*/
vmk_BitVector* vmk_BitVectorDuplicate(vmk_HeapID heap,
const vmk_BitVector *src);
/*
*******************************************************************************
* vmk_BitVectorFree -- */ /**
*
* \brief Free a vmk_BitVector
*
* \param[in] heap vmk_HeapID to free the vmk_BitVector to
* \param[in] bv vmk_BitVector to free
*
* \retval If the previous value of this bit was zero then zero is returned
* otherwise non-zero is returned.
*
*******************************************************************************
*/
void vmk_BitVectorFree(vmk_HeapID heap,
vmk_BitVector *bv);
/*
*******************************************************************************
* vmk_BitVectorSet -- */ /**
*
* \brief Set a bit in a vmk_BitVector
*
* \param[in] bv vmk_BitVector to set a bit
* \param[in] n Bit to set
*
*******************************************************************************
*/
static inline void
vmk_BitVectorSet(vmk_BitVector *bv,
vmk_uint32 n)
{
VMK_ASSERT(n < bv->n);
asm volatile("btsl %1, (%0)"
:: "r" (bv->vector), "r" (n)
: "cc", "memory");
}
/*
*******************************************************************************
* vmk_BitVectorClear -- */ /**
*
* \brief Clear a bit in a vmk_BitVector
*
* \param[in] bv vmk_BitVector to clear a bit
* \param[in] n Bit to set
*
*******************************************************************************
*/
static inline void
vmk_BitVectorClear(vmk_BitVector *bv,
vmk_uint32 n)
{
VMK_ASSERT(n < bv->n);
asm volatile("btrl %1, (%0)"
:: "r" (bv->vector), "r" (n)
: "cc", "memory");
}
/*
*******************************************************************************
* vmk_BitVectorTest -- */ /**
*
* \brief Test if a bit in a vmk_BitVector is set
*
* \param[in] bv vmk_BitVector to check
* \param[in] n Bit to check
*
* \retval If this bit is set, non-zero is returned.
*
*******************************************************************************
*/
static inline int
vmk_BitVectorTest(const vmk_BitVector *bv,
vmk_uint32 n)
{
VMK_ASSERT(n < bv->n);
{
vmk_uint32 tmp;
asm("btl %2, (%1); "
"sbbl %0, %0"
: "=r" (tmp)
: "r" (bv->vector), "r" (n)
: "cc");
return tmp;
}
}
/*
*******************************************************************************
* vmk_BitVectorAtomicTestAndSet -- */ /**
*
* \brief Atomically read bit n and set it
*
* \param[in] bv vmk_BitVector to set a bit
* \param[in] n Bit to set
*
* \retval If the previous value of this bit was zero then zero is returned
* otherwise non-zero is returned.
*
*******************************************************************************
*/
static inline int
vmk_BitVectorAtomicTestAndSet(const vmk_BitVector *bv,
vmk_uint32 n)
{
VMK_ASSERT(n < bv->n);
{
vmk_uint32 tmp;
asm volatile("lock; btsl %2, (%1); "
"sbbl %0, %0"
: "=r" (tmp)
: "r" (bv->vector), "r" (n)
: "cc", "memory");
return tmp;
}
}
/*
*******************************************************************************
* vmk_BitVectorAtomicTestAndClear -- */ /**
*
* \brief Atomically read bit n and clear it
*
* \param[in] bv vmk_BitVector to operate on
* \param[in] n Bit to clear
*
* \retval If the previous value of this bit was zero then zero is returned
* otherwise non-zero is returned.
*
*******************************************************************************
*/
static inline int
vmk_BitVectorAtomicTestAndClear(const vmk_BitVector *bv,
vmk_uint32 n)
{
VMK_ASSERT(n < bv->n);
{
vmk_uint32 tmp;
asm volatile("lock; btrl %2, (%1); "
"sbbl %0, %0"
: "=r" (tmp)
: "r" (bv->vector), "r" (n)
: "cc", "memory");
return tmp;
}
}
/*
*******************************************************************************
* vmk_BitVectorZap -- */ /**
*
* \brief Removes all entries from the set
*
* \param[in] bv vmk_BitVector to zap
*
*******************************************************************************
*/
static inline void
vmk_BitVectorZap(vmk_BitVector *bv)
{
vmk_Memset(bv->vector, 0, bv->nwords * sizeof(bv->vector[0]));
}
/*
*******************************************************************************
* vmk_BitVectorFill -- */ /**
*
* \brief Set all bits in a vmk_BitVector
*
* \param[in] bv vmk_BitVector to operate on
*
*******************************************************************************
*/
static inline void
vmk_BitVectorFill(vmk_BitVector *bv)
{
vmk_Memset(bv->vector, 0xff, bv->nwords * sizeof(bv->vector[0]));
}
/*
*******************************************************************************
* vmk_BitVectorGetRef -- */ /**
*
* \brief Get a pointer to a particular byte in vmk_BitVector
*
* \param[in] bv vmk_BitVector to look inside
* \param[in] start Starting byte return
* \param[in] nbytes Number of bytes expected to be used
*
* \note nbytes is only checked in debug builds
*
* \retval Pointer to a vmk_unit8.
*
*******************************************************************************
*/
static inline vmk_uint8 *
vmk_BitVectorGetRef(const vmk_BitVector *bv,
vmk_uint32 start,
vmk_uint32 nbytes)
{
vmk_uint8 *ptr = (vmk_uint8 *)bv->vector;
(void)nbytes;
VMK_ASSERT((start + nbytes) <= bv->nwords * sizeof(bv->vector[0]));
return &ptr[start];
}
/*
*******************************************************************************
* vmk_BitVectorNumBitsSet -- */ /**
*
* \brief Return the number of set bits in this vmk_BitVector
*
* \param[in] bv vmk_BitVector to count
*
* \retval number of bits set in this vmk_BitVector
*
*******************************************************************************
*/
vmk_uint32 vmk_BitVectorNumBitsSet(const vmk_BitVector *bv);
/*
*******************************************************************************
* vmk_BitVectorIsZero -- */ /**
*
* \brief Check if a vmk_BitVector has no bits set
*
* \param[in] bv vmk_BitVector to check
*
* \retval non-zero if any bit is set in the vmk_BitVector
*
*******************************************************************************
*/
vmk_uint32 vmk_BitVectorIsZero(const vmk_BitVector *bv);
/*
*******************************************************************************
* vmk_BitVectorNextBit -- */ /**
*
* \brief Find next bit set in a vmk_BitVector
*
* \param[in] bv vmk_BitVector to check
* \param[in] start Bit to start searching from
* \param[in] state VMK_TRUE if looking for set bits
* \param[out] pos Filled in with index of the next bit
*
* \retval VMK_TRUE if a bit was found
*
* \note The value of "pos" must not be used if VMK_FALSE is returned.
*
*******************************************************************************
*/
vmk_Bool vmk_BitVectorNextBit(const vmk_BitVector *bv,
vmk_uint32 start,
vmk_Bool state,
vmk_uint32 *pos);
/*
*******************************************************************************
* vmk_BitVectorPrevBit -- */ /**
*
* \brief Find previous bit set in a vmk_BitVector, searching backwards
*
* \param[in] bv vmk_BitVector to check
* \param[in] start Bit to start searching from
* \param[in] state VMK_TRUE if looking for set bits
* \param[out] pos Filled in with index of the next bit
*
* \retval VMK_TRUE if a bit was found
*
* \note BitVectors are implemented as an array of vmk_uint32 which affects
* byte ordering on little endian architectures, such as x86.
*
* \note The value of "pos" must not be used if VMK_FALSE is returned.
*
*******************************************************************************
*/
vmk_Bool vmk_BitVectorPrevBit(const vmk_BitVector *bv,
vmk_uint32 start,
vmk_Bool state,
vmk_uint32 *pos);
/*
*******************************************************************************
* vmk_BitVectorGetExtent -- */ /**
*
* \brief Find sequence of bits in a vmk_BitVector
*
* \param[in] bv vmk_BitVector to check
* \param[in] start Bit to start searching from
* \param[out] set Is start bit set or not
* \param[out] length Filled in with index of the next bit
*
* \note BitVectors are implemented as an array of vmk_uint32 which affects
* byte ordering on little endian architectures, such as x86.
*
*******************************************************************************
*/
void vmk_BitVectorGetExtent(const vmk_BitVector *bv,
vmk_uint32 start,
vmk_Bool *set,
vmk_uint32 *length);
/*
*******************************************************************************
* vmk_BitVectorNextExtent -- */ /**
*
* \brief Find next sequence of bits in a vmk_BitVector
*
* \param[in] bv vmk_BitVector to check
* \param[in] startSearch Bit to start searching from
* \param[in] set VMK_TRUE if looking for set bits
* \param[out] startRun Start index of extend found
* \param[out] length Length of extent found
*
* \retval VMK_TRUE if a bit was found
*
* \note BitVectors are implemented as an array of vmk_uint32 which affects
* byte ordering on little endian architectures, such as x86.
*
* \note The values of "startRun" and "length" must not be used if VMK_FALSE
* is returned.
*
*******************************************************************************
*/
vmk_Bool vmk_BitVectorNextExtent(const vmk_BitVector *bv,
vmk_uint32 startSearch,
vmk_Bool set,
vmk_uint32 *startRun,
vmk_uint32 *length);
/*
*******************************************************************************
* vmk_BitVectorSetExtent -- */ /**
*
* \brief Set an extent of a bitvector to a particular state
*
* \param[in] bv vmk_BitVector to set a bit
* \param[in] startRun Bit to start setting from
* \param[in] length Number of bits to set
* \param[in] state VMK_TRUE if setting to 1
*
* \retval If setting to 1, returns a positive count number of bits set,
* otherwise returns a negative count of the number of bits set.
*
*******************************************************************************
*/
int vmk_BitVectorSetExtent(vmk_BitVector *bv,
vmk_uint32 startRun,
vmk_uint32 length,
vmk_Bool state);
/*
*******************************************************************************
* vmk_BitVectorSetExtentFast -- */ /**
*
* \brief Set an extent of a bitvector to 1
*
* \param[in] bv vmk_BitVector to set a bit
* \param[in] startRun Bit to start setting from
* \param[in] length Number of bits to set
*
*******************************************************************************
*/
void vmk_BitVectorSetExtentFast(vmk_BitVector *bv,
vmk_uint32 startRun,
vmk_uint32 length);
/*
*******************************************************************************
* vmk_BitVectorMerge -- */ /**
*
* \brief Merge two sets of vmk_BitVector
*
* \param[in] src vmk_BitVector merged into dest
* \param[in,out] dest vmk_BitVector modified by src
*
* \retval number of bits merged from src to dest that were not previously set.
*
*******************************************************************************
*/
vmk_uint32 vmk_BitVectorMerge(vmk_BitVector *src,
vmk_BitVector *dest);
/*
*******************************************************************************
* vmk_BitVectorMergeAtOffset -- */ /**
*
* \brief Merge two sets of vmk_BitVector from specific offset
*
* This function merges bits from the start of one vmk_BitVector into another,
* starting the merge at a specific offset in the destination vector. Bits set
* in the source vector that would go beyond the size of dest are ignored.
*
* \param[in] src vmk_BitVector merged into dest
* \param[in,out] dest vmk_BitVector modified by src
* \param[in] offset Bit position to write bits from src into
*
*******************************************************************************
*/
void vmk_BitVectorMergeAtOffset(vmk_BitVector *src,
vmk_BitVector *dest,
vmk_uint32 offset);
/*
*******************************************************************************
* vmk_BitVectorMaxSize -- */ /**
*
* \brief Returns the maximum number of bits that can be held in a vmk_BitVector
*
* \retval maximum number of bits that can be held in a vmk_BitVector
*
*******************************************************************************
*/
vmk_uint32 vmk_BitVectorMaxSize(void);
/*
*******************************************************************************
* VMK_BITVECTOR_ITERATE -- */ /**
*
* \brief Macro to iterate a vmk_BitVector
*
* \param[in] _bv vmk_BitVector to iterate across
* \param[in] _n Variable set to each valid bit each iteration
*
* \retval If the previous value of this bit was zero then zero is returned
* otherwise non-zero is returned.
*
*******************************************************************************
*/
#define VMK_BITVECTOR_ITERATE(_bv,_n) { \
vmk_uint32 _index; \
for (_index=0;_index <(_bv)->nwords;_index++) { \
vmk_uint32 _off,_vals; \
_vals = (_bv)->vector[_index]; \
while(_vals) { \
__asm ("bsfl %1,%0\n\t" \
"btrl %0,%1" \
: "=r" (_off), "+g" (_vals) \
: : "cc" ); \
_n = (_index * 32) + _off; \
if (_n >= (_bv)->n) { \
break; \
} \
/*
*******************************************************************************
* VMK_BITVECTOR_ITERATE_AND_CLEAR -- */ /**
*
* \brief Macro to iterate a vmk_BitVector, clearing it as well
*
* \param[in] _bv vmk_BitVector to iterate across
* \param[in] _n Variable set to each valid bit each iteration
*
* \retval If the previous value of this bit was zero then zero is returned
* otherwise non-zero is returned.
*
* \note The state of the vmk_BitVector during the iteration is undefined
*
*******************************************************************************
*/
#define VMK_BITVECTOR_ITERATE_AND_CLEAR(_bv,_n) { \
vmk_uint32 _index; \
for (_index=0;_index <(_bv)->nwords;_index++) { \
vmk_uint32 _off,_vals; \
_vals = (_bv)->vector[_index]; \
(_bv)->vector[_index] = 0; \
while(_vals) { \
__asm ("bsfl %1,%0\n\t" \
"btrl %0,%1" \
: "=r" (_off), "+g" (_vals) \
: : "cc"); \
_n = (_index * 32) + _off; \
if (_n >= (_bv)->n) { \
break; \
} \
/*
*******************************************************************************
* VMK_BITVECTOR_ENDITERATE -- */ /**
*
* \brief Macro to end a iteration zone
*
* Can be used with either VMK_BITVECTOR_ITERATE() or
* VMK_BITVECTOR_ITERATE_AND_CLEAR()
*
*******************************************************************************
*/
#define VMK_BITVECTOR_ENDITERATE() }}}
#endif /* _VMKAPI_BITVECTOR_H_ */
/** @} */
/** @} */

View file

@ -192,6 +192,22 @@
#define VMK_UNLIKELY(_exp) (_exp) #define VMK_UNLIKELY(_exp) (_exp)
#endif #endif
/*
***********************************************************************
* VMK_IS_COMPILE_TIME -- */ /**
*
* \brief If a given expression is known to be constant at compile-time.
*
* \note This is used to enable some optimizations when an expression is
* known to be constant at compile time, and fall back to a more
* generic method when it is not.
*
* \param[in] _exp Expression that is tested.
*
***********************************************************************
*/
#define VMK_IS_COMPILE_TIME(_exp) __builtin_constant_p(_exp)
/* /*
*********************************************************************** ***********************************************************************
* VMK_PADDED_STRUCT -- */ /** * VMK_PADDED_STRUCT -- */ /**

View file

@ -101,6 +101,14 @@
#define VMK_UINT64_MAX ((vmk_uint64)VMK_CONST64U(0xffffffffffffffff)) #define VMK_UINT64_MAX ((vmk_uint64)VMK_CONST64U(0xffffffffffffffff))
/**
* \brief Bits per byte.
*/
#ifndef VMK_BITS_PER_BYTE
#define VMK_BITS_PER_BYTE (8)
#endif
#endif /* _VMKAPI_CONST_H_ */ #endif /* _VMKAPI_CONST_H_ */
/** @} */ /** @} */
/** @} */ /** @} */

View file

@ -240,6 +240,30 @@ VMK_ReturnStatus
vmk_HashRelease(vmk_HashTable hdl); vmk_HashRelease(vmk_HashTable hdl);
/*
*******************************************************************************
* vmk_HashDeleteAll -- */ /**
*
* \brief Delete every entry in a hash table.
*
* \note This won't actually release the values passed as part of the hash
* table insertion. Client should make sure the right clean up is done
* beforehand.
*
* \note A subsequent call to vmk_HashIsEmpty() on the given hash table should
* return VMK_TRUE.
*
* \param[in] hdl Hash handle.
*
* \retval VMK_OK Every single entry of the hash table was deleted.
* \retval VMK_BAD_PARAM If hdl equals to VMK_INVALID_HASH_HANDLE.
*
*******************************************************************************
*/
VMK_ReturnStatus
vmk_HashDeleteAll(vmk_HashTable hdl);
/* /*
******************************************************************************* *******************************************************************************
* vmk_HashIsEmpty -- */ /** * vmk_HashIsEmpty -- */ /**
@ -421,6 +445,30 @@ vmk_HashKeyFind(vmk_HashTable hdl,
vmk_HashKey key, vmk_HashKey key,
vmk_HashValue *value); vmk_HashValue *value);
/*
*******************************************************************************
* vmk_HashBytes -- */ /**
*
* \brief Calculate 64 bit hash for an array of bytes.
*
* \note This API is not used as part of a hash table allocated with the
* vmk_HashAlloc() function. It is provided as a helper routine for
* callers that need to calculate hashes for their own purpose.
*
* \param[in] key Byte array pointer.
* \param[in] keySize Array Size in byte.
* \param[out] hash The calculated hash value.
*
* \retval VMK_OK Hash calculated successfully.
* \retval VMK_BAD_PARAM If key or hash is NULL, or keySize equal zero.
*
*******************************************************************************
*/
VMK_ReturnStatus
vmk_HashBytes(const vmk_uint8 *key,
vmk_uint32 keySize,
vmk_uint64 *hash);
#endif /* _VMKAPI_HASH_H_ */ #endif /* _VMKAPI_HASH_H_ */
/** @} */ /** @} */

View file

@ -0,0 +1,395 @@
/* **********************************************************
* Copyright 2006 - 2012 VMware, Inc. All rights reserved.
* **********************************************************/
/*
* @VMKAPIMOD_LICENSE@
*/
/*
*******************************************************************************
* PriQ */ /**
* \addtogroup Lib
* @{
* \defgroup PriQ Priority Queue
*
* These are interfaces for priority queues.
*
* The keys can be duplicated, the ordering will be kept accross the elements,
* but the values are expected to be unique. The only reason for that is
* because the vmk_PriQRekey uses the value as an unique identifier to update
* the key of an element. If two elements with the same value are stored in the
* queue and the vmk_PriQRekey is used on this element, then the behavior is
* undefined.
*
* @{
*******************************************************************************
*/
#ifndef _VMKAPI_PRIQ_H_
#define _VMKAPI_PRIQ_H_
/** \cond never */
#ifndef VMK_HEADER_INCLUDED_FROM_VMKAPI_H
#error This vmkapi file should never be included directly but only via vmkapi.h
#endif
/** \endcond never */
/**
* \brief Type of the priority queue.
*
* \details A priority queue can have elements with the smallest or the biggest
* key on front. This enum is used to select the type of priority
* queue we use.
*/
typedef enum vmk_PriQType {
/**
* \brief The queue will be a "min priority queue", meaning that the elements
* with the lowest priority will be on the front.
*/
VMK_PRIQ_TYPE_MIN,
/**
* \brief The queue will be a "max priority queue", meaning that the elements
* with the highest priority will be on the front.
*/
VMK_PRIQ_TYPE_MAX,
} vmk_PriQType;
/**
* \brief Key used to insert an element into the priority queue.
*/
typedef vmk_uint64 vmk_PriQKey;
/**
* \brief Opaque data structure for the priority queue.
*/
typedef struct vmk_PriQInternal *vmk_PriQHandle;
/*
*******************************************************************************
* vmk_PriQCreate -- */ /**
*
* \brief Create a new priority queue.
*
* \note vmk_PriQDestroy() needs to be called once done with the priority queue.
*
* \note The priority queue returned does not come with locking, it is the
* caller's responsibility to provide such mechanism if needed.
*
* \param[in] moduleID Module ID requesting the priority queue.
* \param[in] heapID The heap used for priority queue internal allocation.
* \param[in] type Type of the priority queue.
* \param[in] numElems Number of elements in the priority queue. The queue
* can be later resized if needed.
* \param[out] priQ Handle on the priority queue.
*
* \retval VMK_OK Priority queue initialization and allocation was
* successful.
* \retval VMK_NO_MEMORY Memory allocation failure.
* \retval VMK_BAD_PARAM An invalid parameter was provided.
*
*******************************************************************************
*/
VMK_ReturnStatus
vmk_PriQCreate(vmk_ModuleID moduleID,
vmk_HeapID heapID,
vmk_PriQType type,
vmk_uint64 numElems,
vmk_PriQHandle *priQ);
/*
*******************************************************************************
* vmk_PriQDestroy -- */ /**
*
* \brief Destroy a priority queue and its associated resources.
*
* \param[in] priQ Handle on the priority queue.
*
* \retval VMK_OK Everything went fine, the priority queue is released.
* \retval VMK_BUSY The priority queue was not empty. Unable to release it.
* \retval VMK_BAD_PARAM An invalid parameter was provided.
*
*******************************************************************************
*/
VMK_ReturnStatus
vmk_PriQDestroy(vmk_PriQHandle priQ);
/*
*******************************************************************************
* vmk_PriQClear -- */ /**
*
* \brief Clear the contents of a priority queue.
*
* \param[in] priQ Handle on the priority queue.
*
* \retval VMK_OK Everything went fine, the priority queue was emptied.
* \retval VMK_BAD_PARAM An invalid parameter was provided.
*
*******************************************************************************
*/
VMK_ReturnStatus
vmk_PriQClear(vmk_PriQHandle priQ);
/*
*******************************************************************************
* vmk_PriQTotalElems -- */ /**
*
* \brief Get the total number of slots in the priority queue.
*
* \param[in] priQ Handle on the priority queue.
* \param[out] totalElems Pointer to the output data.
*
* \retval VMK_OK The operation was successful.
* \retval VMK_BAD_PARAM An invalid parameter was provided.
*
*******************************************************************************
*/
VMK_ReturnStatus
vmk_PriQTotalElems(vmk_PriQHandle priQ,
vmk_uint64 *totalElems);
/*
*******************************************************************************
* vmk_PriQUsedElems -- */ /**
*
* \brief Get the number of used slots in the priority queue.
*
* \param[in] priQ Handle on the priority queue.
* \param[out] usedElems Pointer to the output data.
*
* \retval VMK_OK The operation was successful.
* \retval VMK_BAD_PARAM An invalid parameter was provided.
*
*******************************************************************************
*/
VMK_ReturnStatus
vmk_PriQUsedElems(vmk_PriQHandle priQ,
vmk_uint64 *usedElems);
/*
*******************************************************************************
* vmk_PriQIsEmpty -- */ /**
*
* \brief Check whether or not a priority queue is empty.
*
* \param[in] priQ Handle on the priority queue.
*
* \retval VMK_TRUE The priority queue is empty.
* \retval VMK_FALSE The priority queue still contains some elements.
*
*******************************************************************************
*/
static inline vmk_Bool
vmk_PriQIsEmpty(vmk_PriQHandle priQ)
{
VMK_ReturnStatus status;
vmk_uint64 usedElems;
status = vmk_PriQUsedElems(priQ, &usedElems);
VMK_ASSERT(status == VMK_OK);
return (usedElems == 0);
}
/*
*******************************************************************************
* vmk_PriQResize -- */ /**
*
* \brief Resize a previously allocated priority queue.
*
* \param[in] priQ Handle on the priority queue.
* \param[in] numElems New number of elements of the priority queue.
*
* \retval VMK_OK Resize operation was successful.
* \retval VMK_BUSY Trying to shrink the queue to a size too small for the
* elements that are already in there.
* \retval VMK_NO_MEMORY Memory allocation failure. The priority queue is left
* unchanged.
* \retval VMK_BAD_PARAM An invalid parameter was provided.
*
*******************************************************************************
*/
VMK_ReturnStatus
vmk_PriQResize(vmk_PriQHandle priQ,
vmk_uint64 numElems);
/*
*******************************************************************************
* vmk_PriQInsert -- */ /**
*
* \brief Insert an element in the priority queue.
*
* \param[in] priQ Handle on the priority queue.
* \param[in] key Key of the new element. This is the actual "priority"
* that is used to sort elements in the queue.
* \param[in] value Opaque value to store with the key.
*
* \retval VMK_OK Insertion was successful.
* \retval VMK_LIMIT_EXCEEDED The priority queue is already full. The element
* was not inserted. The user needs to resize the queue.
* \retval VMK_BAD_PARAM An invalid parameter was provided.
*
*******************************************************************************
*/
VMK_ReturnStatus
vmk_PriQInsert(vmk_PriQHandle priQ,
vmk_PriQKey key,
void *value);
/*
*******************************************************************************
* vmk_PriQFirst -- */ /**
*
* \brief Get the first element of the priority queue and/or its associated key.
*
* \note This does not remove the first element from the priority queue. One
* needs to use vmk_PriQExtractFirst() for that purpose.
*
* \param[in] priQ Handle on the priority queue.
* \param[out] key Pointer to the output key. If this parameter is NULL,
* then it is ignored.
* \param[out] value Pointer to the output value. If this parameter is
* NULL, then it is ignored.
*
* \retval VMK_OK The first element of the queue has been "found" and
* stored in the output parameters.
* \retval VMK_BAD_PARAM An invalid parameter was provided.
* \retval VMK_NOT_FOUND The queue was empty.
*
*******************************************************************************
*/
VMK_ReturnStatus
vmk_PriQFirst(vmk_PriQHandle priQ,
vmk_PriQKey *key,
void **value);
/*
*******************************************************************************
* vmk_PriQExtractFirst -- */ /**
*
* \brief Returns and deletes the first element of the priority queue.
*
* \param[in] priQ Handle on the priority queue.
* \param[out] key Pointer to the output key. If this parameter is NULL,
* then it is ignored.
* \param[out] value Pointer to the output value. If this parameter is
* NULL, then it is ignored.
*
* \retval VMK_OK The first element of the queue has been stored in
* output parameters and deleted from the queue.
* \retval VMK_BAD_PARAM An invalid parameter was provided.
* \retval VMK_NOT_FOUND The queue was empty.
*
*******************************************************************************
*/
VMK_ReturnStatus
vmk_PriQExtractFirst(vmk_PriQHandle priQ,
vmk_PriQKey *key,
void **value);
/*
*******************************************************************************
* vmk_PriQExtract -- */ /**
*
* \brief Returns and deletes the element whose value is passed as argument.
*
* \note As keys in a priority queue can be duplicated, the only way to
* uniquely identify an element is to use the pointer referencing it.
*
* \param[in] priQ Handle on the priority queue.
* \param[in] value Value that was initially stored in the queue and that
* we want to extract.
* \param[out] key Pointer to the output key. If this parameter is NULL,
* then it is ignored.
*
* \retval VMK_OK The element of the queue has been stored in output
* parameters and deleted from the queue.
* \retval VMK_BAD_PARAM An invalid parameter was provided.
* \retval VMK_NOT_FOUND The element was not found in the queue.
*
*******************************************************************************
*/
VMK_ReturnStatus
vmk_PriQExtract(vmk_PriQHandle priQ,
void *value,
vmk_PriQKey *key);
/*
*******************************************************************************
* vmk_PriQFind -- */ /**
*
* \brief Returns the element whose value is passed as argument.
*
* \note As keys in a priority queue can be duplicated, the only way to
* uniquely identify an element is to use the pointer referencing it.
*
* \param[in] priQ Handle on the priority queue.
* \param[in] value Value that was initially stored in the queue and that
* we want to find.
* \param[out] key Pointer to the output key. If this parameter is NULL,
* then it is ignored.
*
* \retval VMK_OK The element of the queue has been stored in output
* parameters and deleted from the queue.
* \retval VMK_BAD_PARAM An invalid parameter was provided.
* \retval VMK_NOT_FOUND The element was not found in the queue.
*
*******************************************************************************
*/
VMK_ReturnStatus
vmk_PriQFind(vmk_PriQHandle priQ,
void *value,
vmk_PriQKey *key);
/*
*******************************************************************************
* vmk_PriQRekeyFirst -- */ /**
*
* \brief Update the key of the first element in the queue.
*
* \details This will lead to the first element beeing moved in the queue if
* needed.
*
* \param[in] priQ Handle on the priority queue.
* \param[in] newKey New key to apply to the first element in the queue.
*
* \retval VMK_OK The first element of the queue has been updated.
* \retval VMK_BAD_PARAM An invalid parameter was provided.
* \retval VMK_NOT_FOUND The queue was empty.
*
*******************************************************************************
*/
VMK_ReturnStatus
vmk_PriQRekeyFirst(vmk_PriQHandle priQ,
vmk_PriQKey newKey);
/*
*******************************************************************************
* vmk_PriQRekey -- */ /**
*
* \brief Update the key of the entry whose value is passed as argument.
*
* \details This will lead to the element being moved in the queue if needed.
*
* \note As keys in a priority queue can be duplicated, the only way to
* uniquely identify an element is to use the pointer referencing it.
*
* \param[in] priQ Handle on the priority queue.
* \param[in] value Value that was initially stored in the queue, for
* which we will update the key.
* \param[in] newKey New key to apply to the value.
*
* \retval VMK_OK The element's key has been updated.
* \retval VMK_BAD_PARAM An invalid parameter was provided.
* \retval VMK_NOT_FOUND The element was not found in the queue.
*
*******************************************************************************
*/
VMK_ReturnStatus
vmk_PriQRekey(vmk_PriQHandle priQ,
void *value,
vmk_PriQKey newKey);
#endif /* _PRIQ_MINMAXHEAP_H_ */
/** @} */
/** @} */

View file

@ -1,5 +1,5 @@
/* ********************************************************** /* **********************************************************
* Copyright 2008 - 2009 VMware, Inc. All rights reserved. * Copyright 2008 - 2009, 2013 VMware, Inc. All rights reserved.
* **********************************************************/ * **********************************************************/
/* /*
@ -58,6 +58,134 @@
*/ */
#define VMK_UTIL_ROUNDUP(x, y) ((((x)+(y)-1) / (y)) * (y)) #define VMK_UTIL_ROUNDUP(x, y) ((((x)+(y)-1) / (y)) * (y))
/**
* \brief A series of macros used to count parameters in a varargs list
*/
/*
***********************************************************************
* __VMK_UTIL_MASK_ARGS_INT__ -- */ /**
*
* \brief Internal macro to ignore the first 128 varargs parameters and
* evaluate as 129th.
*
* This is used as part of VMK_UTIL_NUM_ARGS(). VMKAPI clients should
* not call this macro directly.
*
***********************************************************************
*/
/** \cond nodoc */
#define __VMK_UTIL_MASK_ARGS_INT__( \
_ARG1, _ARG2, _ARG3, _ARG4, _ARG5, \
_ARG6, _ARG7, _ARG8, _ARG9, _ARG10, \
_ARG11, _ARG12, _ARG13, _ARG14, _ARG15, \
_ARG16, _ARG17, _ARG18, _ARG19, _ARG20, \
_ARG21, _ARG22, _ARG23, _ARG24, _ARG25, \
_ARG26, _ARG27, _ARG28, _ARG29, _ARG30, \
_ARG31, _ARG32, _ARG33, _ARG34, _ARG35, \
_ARG36, _ARG37, _ARG38, _ARG39, _ARG40, \
_ARG41, _ARG42, _ARG43, _ARG44, _ARG45, \
_ARG46, _ARG47, _ARG48, _ARG49, _ARG50, \
_ARG51, _ARG52, _ARG53, _ARG54, _ARG55, \
_ARG56, _ARG57, _ARG58, _ARG59, _ARG60, \
_ARG61, _ARG62, _ARG63, _ARG64, _ARG65, \
_ARG66, _ARG67, _ARG68, _ARG69, _ARG70, \
_ARG71, _ARG72, _ARG73, _ARG74, _ARG75, \
_ARG76, _ARG77, _ARG78, _ARG79, _ARG80, \
_ARG81, _ARG82, _ARG83, _ARG84, _ARG85, \
_ARG86, _ARG87, _ARG88, _ARG89, _ARG90, \
_ARG91, _ARG92, _ARG93, _ARG94, _ARG95, \
_ARG96, _ARG97, _ARG98, _ARG99, _ARG100, \
_ARG101, _ARG102, _ARG103, _ARG104, _ARG105, \
_ARG106, _ARG107, _ARG108, _ARG109, _ARG110, \
_ARG111, _ARG112, _ARG113, _ARG114, _ARG115, \
_ARG116, _ARG117, _ARG118, _ARG119, _ARG120, \
_ARG121, _ARG122, _ARG123, _ARG124, _ARG125, \
_ARG126, _ARG127, _ARG128, _ARG129, ...) _ARG129
/** \endcond */
/*
***********************************************************************
* __VMK_UTIL_ARG_COUNTS__ -- */ /**
*
* \brief A series of argument counts, used with VMK_UTIL_NUM_ARGS.
*
* This is used as part of VMK_UTIL_NUM_ARGS(). VMKAPI clients should
* no call this macro directly.
*
***********************************************************************
*/
/** \cond nodoc */
#define __VMK_UTIL_ARG_COUNTS__() \
128, 127, 126, 125, 124, 123, 122, 121, 120, \
119, 118, 117, 116, 115, 114, 113, 112, 111, 110, \
109, 108, 107, 106, 105, 104, 103, 102, 101, 100, \
99, 98, 97, 96, 95, 94, 93, 92, 91, 90, \
89, 88, 87, 86, 85, 84, 83, 82, 81, 80, \
79, 78, 77, 76, 75, 74, 73, 72, 71, 70, \
69, 68, 67, 66, 65, 64, 63, 62, 61, 60, \
59, 58, 57, 56, 55, 54, 53, 52, 51, 50, \
49, 48, 47, 46, 45, 44, 43, 42, 41, 40, \
39, 38, 37, 36, 35, 34, 33, 32, 31, 30, \
29, 28, 27, 26, 25, 24, 23, 22, 21, 20, \
19, 18, 17, 16, 15, 14, 13, 12, 11, 10, \
9, 8, 7, 6, 5, 4, 3, 2, 1, 0
/** \endcond */
/*
***********************************************************************
* __VMK_UTIL_MASK_ARGS__ -- */ /**
*
* \brief Variadic macro that masks the first 128 arguments, evaluating
* the 129th.
*
* This is used as part of VMK_UTIL_NUM_ARGS(). VMKAPI clients should
* no call this macro directly.
*
***********************************************************************
*/
/** \cond nodoc */
#define __VMK_UTIL_MASK_ARGS__(...) \
__VMK_UTIL_MASK_ARGS_INT__(__VA_ARGS__)
/** \endcond */
/*
***********************************************************************
* VMK_UTIL_NUM_ARGS -- */ /**
*
* \brief Macro to count the number of varargs parameters.
*
* \param[in] ... varargs parameters. There can be 0 to 127
* parameters. More than 127 produces an
* undefined result.
*
* \note This works by creating a larger varargs series of parameters
* around the passed series and using internal macros. The
* larger series is a dummy parameter (to support if the passed
* series has no parameters), the passed series, and then a
* decreasing series of numbers representing the parameter count.
* The internal macros effectively ignore the first 128
* parameters of this larger series and evaluates as the 129th,
* thus effectively evaluating as one plus the count of passed
* parameters. (The one is offset by subtraction in this
* macro).
* \note This macro relies on the special behavior of ##__VA_ARGS__,
* as described here:
* http://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html
* In the case that the passed varargs series has no elements,
* ##__VA_ARGS__ will also consume the comma preceding it,
* allowing this macro (VMK_UTIL_NUM_ARGS) to compile correctly
* and evaluate as 0.
*
***********************************************************************
*/
/** \cond nodoc */
#define VMK_UTIL_NUM_ARGS(...) \
(__VMK_UTIL_MASK_ARGS__(_DUMMY, ##__VA_ARGS__, __VMK_UTIL_ARG_COUNTS__()) - 1)
/** \endcond */
#endif /* _VMKAPI_UTIL_H_ */ #endif /* _VMKAPI_UTIL_H_ */
/** @} */ /** @} */
/** @} */ /** @} */

Some files were not shown because too many files have changed in this diff Show more