xen: import new ring macros in ring.h
Sync the ring.h file with upstream Xen, to introduce the new ring macros. They will be used by the Xen transport for 9pfs. CC: konrad.wilk@oracle.com CC: boris.ostrovsky@oracle.com CC: jgross@suse.com CC: groug@kaod.org Signed-off-by: Stefano Stabellini <stefano@aporeto.com> Acked-by: Juergen Gross <jgross@suse.com> Signed-off-by: Juergen Gross <jgross@suse.com>
This commit is contained in:
Родитель
ab1570a427
Коммит
564f7dfde2
|
@ -283,4 +283,147 @@ struct __name##_back_ring { \
|
|||
(_work_to_do) = RING_HAS_UNCONSUMED_RESPONSES(_r); \
|
||||
} while (0)
|
||||
|
||||
|
||||
/*
|
||||
* DEFINE_XEN_FLEX_RING_AND_INTF defines two monodirectional rings and
|
||||
* functions to check if there is data on the ring, and to read and
|
||||
* write to them.
|
||||
*
|
||||
* DEFINE_XEN_FLEX_RING is similar to DEFINE_XEN_FLEX_RING_AND_INTF, but
|
||||
* does not define the indexes page. As different protocols can have
|
||||
* extensions to the basic format, this macro allow them to define their
|
||||
* own struct.
|
||||
*
|
||||
* XEN_FLEX_RING_SIZE
|
||||
* Convenience macro to calculate the size of one of the two rings
|
||||
* from the overall order.
|
||||
*
|
||||
* $NAME_mask
|
||||
* Function to apply the size mask to an index, to reduce the index
|
||||
* within the range [0-size].
|
||||
*
|
||||
* $NAME_read_packet
|
||||
* Function to read data from the ring. The amount of data to read is
|
||||
* specified by the "size" argument.
|
||||
*
|
||||
* $NAME_write_packet
|
||||
* Function to write data to the ring. The amount of data to write is
|
||||
* specified by the "size" argument.
|
||||
*
|
||||
* $NAME_get_ring_ptr
|
||||
* Convenience function that returns a pointer to read/write to the
|
||||
* ring at the right location.
|
||||
*
|
||||
* $NAME_data_intf
|
||||
* Indexes page, shared between frontend and backend. It also
|
||||
* contains the array of grant refs.
|
||||
*
|
||||
* $NAME_queued
|
||||
* Function to calculate how many bytes are currently on the ring,
|
||||
* ready to be read. It can also be used to calculate how much free
|
||||
* space is currently on the ring (XEN_FLEX_RING_SIZE() -
|
||||
* $NAME_queued()).
|
||||
*/
|
||||
|
||||
#ifndef XEN_PAGE_SHIFT
|
||||
/* The PAGE_SIZE for ring protocols and hypercall interfaces is always
|
||||
* 4K, regardless of the architecture, and page granularity chosen by
|
||||
* operating systems.
|
||||
*/
|
||||
#define XEN_PAGE_SHIFT 12
|
||||
#endif
|
||||
#define XEN_FLEX_RING_SIZE(order) \
|
||||
(1UL << ((order) + XEN_PAGE_SHIFT - 1))
|
||||
|
||||
#define DEFINE_XEN_FLEX_RING(name) \
|
||||
static inline RING_IDX name##_mask(RING_IDX idx, RING_IDX ring_size) \
|
||||
{ \
|
||||
return idx & (ring_size - 1); \
|
||||
} \
|
||||
\
|
||||
static inline unsigned char *name##_get_ring_ptr(unsigned char *buf, \
|
||||
RING_IDX idx, \
|
||||
RING_IDX ring_size) \
|
||||
{ \
|
||||
return buf + name##_mask(idx, ring_size); \
|
||||
} \
|
||||
\
|
||||
static inline void name##_read_packet(void *opaque, \
|
||||
const unsigned char *buf, \
|
||||
size_t size, \
|
||||
RING_IDX masked_prod, \
|
||||
RING_IDX *masked_cons, \
|
||||
RING_IDX ring_size) \
|
||||
{ \
|
||||
if (*masked_cons < masked_prod || \
|
||||
size <= ring_size - *masked_cons) { \
|
||||
memcpy(opaque, buf + *masked_cons, size); \
|
||||
} else { \
|
||||
memcpy(opaque, buf + *masked_cons, ring_size - *masked_cons); \
|
||||
memcpy((unsigned char *)opaque + ring_size - *masked_cons, buf, \
|
||||
size - (ring_size - *masked_cons)); \
|
||||
} \
|
||||
*masked_cons = name##_mask(*masked_cons + size, ring_size); \
|
||||
} \
|
||||
\
|
||||
static inline void name##_write_packet(unsigned char *buf, \
|
||||
const void *opaque, \
|
||||
size_t size, \
|
||||
RING_IDX *masked_prod, \
|
||||
RING_IDX masked_cons, \
|
||||
RING_IDX ring_size) \
|
||||
{ \
|
||||
if (*masked_prod < masked_cons || \
|
||||
size <= ring_size - *masked_prod) { \
|
||||
memcpy(buf + *masked_prod, opaque, size); \
|
||||
} else { \
|
||||
memcpy(buf + *masked_prod, opaque, ring_size - *masked_prod); \
|
||||
memcpy(buf, (unsigned char *)opaque + (ring_size - *masked_prod), \
|
||||
size - (ring_size - *masked_prod)); \
|
||||
} \
|
||||
*masked_prod = name##_mask(*masked_prod + size, ring_size); \
|
||||
} \
|
||||
\
|
||||
static inline RING_IDX name##_queued(RING_IDX prod, \
|
||||
RING_IDX cons, \
|
||||
RING_IDX ring_size) \
|
||||
{ \
|
||||
RING_IDX size; \
|
||||
\
|
||||
if (prod == cons) \
|
||||
return 0; \
|
||||
\
|
||||
prod = name##_mask(prod, ring_size); \
|
||||
cons = name##_mask(cons, ring_size); \
|
||||
\
|
||||
if (prod == cons) \
|
||||
return ring_size; \
|
||||
\
|
||||
if (prod > cons) \
|
||||
size = prod - cons; \
|
||||
else \
|
||||
size = ring_size - (cons - prod); \
|
||||
return size; \
|
||||
} \
|
||||
\
|
||||
struct name##_data { \
|
||||
unsigned char *in; /* half of the allocation */ \
|
||||
unsigned char *out; /* half of the allocation */ \
|
||||
}
|
||||
|
||||
#define DEFINE_XEN_FLEX_RING_AND_INTF(name) \
|
||||
struct name##_data_intf { \
|
||||
RING_IDX in_cons, in_prod; \
|
||||
\
|
||||
uint8_t pad1[56]; \
|
||||
\
|
||||
RING_IDX out_cons, out_prod; \
|
||||
\
|
||||
uint8_t pad2[56]; \
|
||||
\
|
||||
RING_IDX ring_order; \
|
||||
grant_ref_t ref[]; \
|
||||
}; \
|
||||
DEFINE_XEN_FLEX_RING(name)
|
||||
|
||||
#endif /* __XEN_PUBLIC_IO_RING_H__ */
|
||||
|
|
Загрузка…
Ссылка в новой задаче