* RE: [PATCH 04/22] NTB: Add messaging NTB API
@ 2016-12-04 0:05 Allen Hubbe
0 siblings, 0 replies; 2+ messages in thread
From: Allen Hubbe @ 2016-12-04 0:05 UTC (permalink / raw)
To: 'Serge Semin', jdmason, dave.jiang, Xiangliang.Yu
Cc: Sergey.Semin, linux-ntb, linux-kernel
From: Serge Semin
> IDT PCIe-switches have message registers to communicate with peer devices.
> This patch adds new NTB API callback methods, which can be used to utilize
> these registers functionality.
>
Please split: add msg api; make spads optional.
See comments below on ntb_dev_ops_is_valid.
> Signed-off-by: Serge Semin <fancer.lancer@gmail.com>
>
> ---
> drivers/ntb/ntb.c | 13 +++
> include/linux/ntb.h | 236 ++++++++++++++++++++++++++++++++++++++++++++++++++--
> 2 files changed, 241 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/ntb/ntb.c b/drivers/ntb/ntb.c
> index 2e25307..4b2cc60 100644
> --- a/drivers/ntb/ntb.c
> +++ b/drivers/ntb/ntb.c
> @@ -191,6 +191,19 @@ void ntb_db_event(struct ntb_dev *ntb, int vector)
> }
> EXPORT_SYMBOL(ntb_db_event);
>
> +void ntb_msg_event(struct ntb_dev *ntb)
> +{
> + unsigned long irqflags;
> +
> + spin_lock_irqsave(&ntb->ctx_lock, irqflags);
> + {
> + if (ntb->ctx_ops && ntb->ctx_ops->msg_event)
> + ntb->ctx_ops->msg_event(ntb->ctx);
> + }
> + spin_unlock_irqrestore(&ntb->ctx_lock, irqflags);
> +}
> +EXPORT_SYMBOL(ntb_msg_event);
> +
> static int ntb_probe(struct device *dev)
> {
> struct ntb_dev *ntb;
> diff --git a/include/linux/ntb.h b/include/linux/ntb.h
> index 4a150b5..59de1f6 100644
> --- a/include/linux/ntb.h
> +++ b/include/linux/ntb.h
> @@ -146,10 +146,12 @@ static inline int ntb_client_ops_is_valid(const struct
> ntb_client_ops *ops)
> * struct ntb_ctx_ops - ntb driver context operations
> * @link_event: See ntb_link_event().
> * @db_event: See ntb_db_event().
> + * @msg_event: See ntb_msg_event().
> */
> struct ntb_ctx_ops {
> void (*link_event)(void *ctx);
> void (*db_event)(void *ctx, int db_vector);
> + void (*msg_event)(void *ctx);
> };
>
> static inline int ntb_ctx_ops_is_valid(const struct ntb_ctx_ops *ops)
> @@ -158,6 +160,7 @@ static inline int ntb_ctx_ops_is_valid(const struct ntb_ctx_ops *ops)
> return
> /* ops->link_event && */
> /* ops->db_event && */
> + /* ops->msg_event && */
> 1;
> }
>
> @@ -202,6 +205,15 @@ static inline int ntb_ctx_ops_is_valid(const struct ntb_ctx_ops *ops)
> * @peer_spad_addr: See ntb_peer_spad_addr().
> * @peer_spad_read: See ntb_peer_spad_read().
> * @peer_spad_write: See ntb_peer_spad_write().
> + * @msg_count: See ntb_msg_count().
> + * @msg_inbits: See ntb_msg_inbits().
> + * @msg_outbits: See ntb_msg_outbits().
> + * @msg_read_sts: See ntb_msg_read_sts().
> + * @msg_clear_sts: See ntb_msg_clear_sts().
> + * @msg_set_mask: See ntb_msg_set_mask().
> + * @msg_clear_mask: See ntb_msg_clear_mask().
> + * @msg_read: See ntb_msg_read().
> + * @msg_write: See ntb_msg_write().
> */
> struct ntb_dev_ops {
> int (*port_number)(struct ntb_dev *ntb);
> @@ -263,6 +275,16 @@ struct ntb_dev_ops {
> phys_addr_t *spad_addr);
> u32 (*peer_spad_read)(struct ntb_dev *ntb, int idx);
> int (*peer_spad_write)(struct ntb_dev *ntb, int idx, u32 val);
> +
> + int (*msg_count)(struct ntb_dev *ntb);
> + u64 (*msg_inbits)(struct ntb_dev *ntb);
> + u64 (*msg_outbits)(struct ntb_dev *ntb);
> + u64 (*msg_read_sts)(struct ntb_dev *ntb);
> + int (*msg_clear_sts)(struct ntb_dev *ntb, u64 sts_bits);
> + int (*msg_set_mask)(struct ntb_dev *ntb, u64 mask_bits);
> + int (*msg_clear_mask)(struct ntb_dev *ntb, u64 mask_bits);
> + int (*msg_read)(struct ntb_dev *ntb, int midx, int *pidx, u32 *msg);
> + int (*msg_write)(struct ntb_dev *ntb, int midx, int pidx, u32 msg);
> };
>
> static inline int ntb_dev_ops_is_valid(const struct ntb_dev_ops *ops)
> @@ -304,13 +326,22 @@ static inline int ntb_dev_ops_is_valid(const struct ntb_dev_ops
> *ops)
> /* ops->peer_db_read_mask && */
> /* ops->peer_db_set_mask && */
> /* ops->peer_db_clear_mask && */
> - /* ops->spad_is_unsafe && */
> - ops->spad_count &&
> - ops->spad_read &&
> - ops->spad_write &&
> - /* ops->peer_spad_addr && */
> - /* ops->peer_spad_read && */
> - ops->peer_spad_write &&
> + ((/* ops->spad_is_unsafe && */
> + ops->spad_count &&
> + ops->spad_read &&
> + ops->spad_write &&
> + /* ops->peer_spad_addr && */
> + /* ops->peer_spad_read && */
> + ops->peer_spad_write) ||
> + (ops->msg_count &&
> + ops->msg_inbits &&
> + ops->msg_outbits &&
> + ops->msg_read_sts &&
> + ops->msg_clear_sts &&
> + /* ops->msg_set_mask && */
> + /* ops->msg_clear_mask && */
> + ops->msg_read &&
> + ops->msg_write)) &&
Don't enforce "must have spad or msg" here, leave it to application to check spad_count != 0 or msg_count != 0 else fail. If an ntb doesn't have either, it may be rather limited, but let's not prevent the driver to register that device.
As written above has a subtle bug. We should say, if spad is implemented at all, then the basic spad api is fully implemented; likewise if msg is implemented at all, then the basic msg api is fully implemented.
As written below, the required basic api of spad ops must have the same truth-value of spad_count (and likewise for msg_count).
/* !ops->spad_is_unsafe == !ops->spad_count && */
!ops->spad_read == !ops->spad_count &&
!ops->spad_write == !ops->spad_count &&
/* !ops->peer_spad_addr == !ops->spad_count && */
/* !ops->peer_spad_read == !ops->spad_count && */
!ops->peer_spad_write == !ops->spad_count &&
!ops->msg_inbits == !ops->msg_count &&
!ops->msg_outbits == !ops->msg_count &&
!ops->msg_read_sts == !ops->msg_count &&
!ops->msg_clear_sts == !ops->msg_count &&
/* !ops->msg_set_mask == !ops->msg_count && */
/* !ops->msg_clear_mask == !ops->msg_count && */
!ops->msg_read == !ops->msg_count &&
!ops->msg_write == !ops->msg_count &&
> 1;
> }
>
> @@ -456,6 +487,18 @@ void ntb_link_event(struct ntb_dev *ntb);
> void ntb_db_event(struct ntb_dev *ntb, int vector);
>
> /**
> + * ntb_msg_event() - notify driver context of a message event
> + * @ntb: NTB device context.
> + *
> + * Notify the driver context of a message event. If hardware supports
> + * message registers, this event indicates, that a new message arrived in
> + * some incoming message register or last sent message couldn't be delivered.
> + * The events can be masked/unmasked by the methods ntb_msg_set_mask() and
> + * ntb_msg_clear_mask().
> + */
> +void ntb_msg_event(struct ntb_dev *ntb);
> +
> +/**
> * ntb_port_number() - get the local port number
> * @ntb: NTB device context.
> *
> @@ -1154,7 +1197,7 @@ static inline int ntb_spad_is_unsafe(struct ntb_dev *ntb)
> }
>
> /**
> - * ntb_mw_count() - get the number of scratchpads
> + * ntb_spad_count() - get the number of scratchpads
> * @ntb: NTB device context.
> *
> * Hardware and topology may support a different number of scratchpads.
> @@ -1163,6 +1206,9 @@ static inline int ntb_spad_is_unsafe(struct ntb_dev *ntb)
> */
> static inline int ntb_spad_count(struct ntb_dev *ntb)
> {
> + if (!ntb->ops->spad_count)
> + return 0;
> +
> return ntb->ops->spad_count(ntb);
> }
>
> @@ -1177,6 +1223,9 @@ static inline int ntb_spad_count(struct ntb_dev *ntb)
> */
> static inline u32 ntb_spad_read(struct ntb_dev *ntb, int idx)
> {
> + if (!ntb->ops->spad_read)
> + return ~(u32)0;
> +
> return ntb->ops->spad_read(ntb, idx);
> }
>
> @@ -1192,6 +1241,9 @@ static inline u32 ntb_spad_read(struct ntb_dev *ntb, int idx)
> */
> static inline int ntb_spad_write(struct ntb_dev *ntb, int idx, u32 val)
> {
> + if (!ntb->ops->spad_write)
> + return -EINVAL;
> +
> return ntb->ops->spad_write(ntb, idx, val);
> }
>
> @@ -1226,6 +1278,9 @@ static inline int ntb_peer_spad_addr(struct ntb_dev *ntb, int idx,
> */
> static inline u32 ntb_peer_spad_read(struct ntb_dev *ntb, int idx)
> {
> + if (!ntb->ops->peer_spad_read)
> + return ~(u32)0;
> +
> return ntb->ops->peer_spad_read(ntb, idx);
> }
>
> @@ -1241,7 +1296,172 @@ static inline u32 ntb_peer_spad_read(struct ntb_dev *ntb, int idx)
> */
> static inline int ntb_peer_spad_write(struct ntb_dev *ntb, int idx, u32 val)
> {
> + if (!ntb->ops->peer_spad_write)
> + return -EINVAL;
> +
> return ntb->ops->peer_spad_write(ntb, idx, val);
> }
>
> +/**
> + * ntb_msg_count() - get the number of message registers
> + * @ntb: NTB device context.
> + *
> + * Hardware may support a different number of messge registers.
> + *
> + * Return: the number of message registers.
> + */
> +static inline int ntb_msg_count(struct ntb_dev *ntb)
> +{
> + if (!ntb->ops->msg_count)
> + return 0;
> +
> + return ntb->ops->msg_count(ntb);
> +}
> +
> +/**
> + * ntb_msg_inbits() - get a bitsfield of inbound message registers status
> + * @ntb: NTB device context.
> + *
> + * The method returns the bitsfield of status and mask registers, which related
> + * to inbound message registers.
> + *
> + * Return: bitsfield of inbound message registers.
> + */
> +static inline u64 ntb_msg_inbits(struct ntb_dev *ntb)
> +{
> + if (!ntb->ops->msg_inbits)
> + return 0;
> +
> + return ntb->ops->msg_inbits(ntb);
> +}
> +
> +/**
> + * ntb_msg_outbits() - get a bitsfield of outbound message registers status
> + * @ntb: NTB device context.
> + *
> + * The method returns the bitsfield of status and mask registers, which related
> + * to outbound message registers.
> + *
> + * Return: bitsfield of outbound message registers.
> + */
> +static inline u64 ntb_msg_outbits(struct ntb_dev *ntb)
> +{
> + if (!ntb->ops->msg_outbits)
> + return 0;
> +
> + return ntb->ops->msg_outbits(ntb);
> +}
> +
> +/**
> + * ntb_msg_read_sts() - read the message registers status
> + * @ntb: NTB device context.
> + *
> + * Read the status of message register. Inbound and outbound message registers
> + * related bits can be filetered by masks retrieved from ntb_msg_inbits() and
> + * ntb_msg_outbits().
> + *
> + * Return: status bits of message registers
> + */
> +static inline u64 ntb_msg_read_sts(struct ntb_dev *ntb)
> +{
> + if (!ntb->ops->msg_read_sts)
> + return 0;
> +
> + return ntb->ops->msg_read_sts(ntb);
> +}
> +
> +/**
> + * ntb_msg_clear_sts() - clear status bits of message registers
> + * @ntb: NTB device context.
> + * @sts_bits: Status bits to clear.
> + *
> + * Clear bits in the status register.
> + *
> + * Return: Zero on success, otherwise a negative error number.
> + */
> +static inline int ntb_msg_clear_sts(struct ntb_dev *ntb, u64 sts_bits)
> +{
> + if (!ntb->ops->msg_clear_sts)
> + return -EINVAL;
> +
> + return ntb->ops->msg_clear_sts(ntb, sts_bits);
> +}
> +
> +/**
> + * ntb_msg_set_mask() - set mask of message register status bits
> + * @ntb: NTB device context.
> + * @mask_bits: Mask bits.
> + *
> + * Mask the message registers status bits from raising the message event.
> + *
> + * Return: Zero on success, otherwise a negative error number.
> + */
> +static inline int ntb_msg_set_mask(struct ntb_dev *ntb, u64 mask_bits)
> +{
> + if (!ntb->ops->msg_set_mask)
> + return -EINVAL;
> +
> + return ntb->ops->msg_set_mask(ntb, mask_bits);
> +}
> +
> +/**
> + * ntb_msg_clear_mask() - clear message registers mask
> + * @ntb: NTB device context.
> + * @mask_bits: Mask bits to clear.
> + *
> + * Clear bits in the message events mask register.
> + *
> + * Return: Zero on success, otherwise a negative error number.
> + */
> +static inline int ntb_msg_clear_mask(struct ntb_dev *ntb, u64 mask_bits)
> +{
> + if (!ntb->ops->msg_clear_mask)
> + return -EINVAL;
> +
> + return ntb->ops->msg_clear_mask(ntb, mask_bits);
> +}
> +
> +/**
> + * ntb_msg_read() - read message register with specified index
> + * @ntb: NTB device context.
> + * @midx: Message register index
> + * @pidx: OUT - Port index of peer device a message retrieved from
> + * @msg: OUT - Data
> + *
> + * Read data from the specified message register. Source port index of a
> + * message is retrieved as well.
> + *
> + * Return: Zero on success, otherwise a negative error number.
> + */
> +static inline int ntb_msg_read(struct ntb_dev *ntb, int midx, int *pidx,
> + u32 *msg)
> +{
> + if (!ntb->ops->msg_read)
> + return -EINVAL;
> +
> + return ntb->ops->msg_read(ntb, midx, pidx, msg);
> +}
> +
> +/**
> + * ntb_msg_write() - write data to the specified message register
> + * @ntb: NTB device context.
> + * @midx: Message register index
> + * @pidx: Port index of peer device a message being sent to
> + * @msg: Data to send
> + *
> + * Send data to a specified peer device using the defined message register.
> + * Message event can be raised if the midx registers isn't empty while
> + * calling this method and the corresponding interrupt isn't masked.
> + *
> + * Return: Zero on success, otherwise a negative error number.
> + */
> +static inline int ntb_msg_write(struct ntb_dev *ntb, int midx, int pidx,
> + u32 msg)
> +{
> + if (!ntb->ops->msg_write)
> + return -EINVAL;
> +
> + return ntb->ops->msg_write(ntb, midx, pidx, msg);
> +}
> +
> #endif
> --
> 2.6.6
^ permalink raw reply [flat|nested] 2+ messages in thread* [PATCH 00/22] NTB: Alter kernel API to support multi-port devices
@ 2016-11-29 17:15 Serge Semin
2016-11-29 17:15 ` [PATCH 04/22] NTB: Add messaging NTB API Serge Semin
0 siblings, 1 reply; 2+ messages in thread
From: Serge Semin @ 2016-11-29 17:15 UTC (permalink / raw)
To: jdmason, dave.jiang, Allen.Hubbe, Xiangliang.Yu
Cc: Sergey.Semin, linux-ntb, linux-kernel, Serge Semin
There are devices, like IDT PCIe-switches, which have more than just two ports.
Particularly one device can have up to eight ports with NTB-function activated.
In order to support such devices, NTB kernel API should be altered since
currently it's optimized to work with two-ports devices only.
Here are the changes I made to conform the design we discussed a few months ago:
1) Port-index-related methods are added to KAPI
ntb_port_number();
ntb_peer_port_count();
ntb_peer_port_number(pdix);
ntb_peer_port_idx(port);
2) Link state method returns bitfield of link states for each reachable port
u64 ntb_link_is_up();
3) Link enable/disable methods work with local link side of NTB
ntb_link_enable()/ntb_link_disable();
4) NTB memory window related interface does the following things
ntb_mw_count(pidx); - number of inbound memory windows, which can be allocated
for shared buffer with specified peer device.
ntb_mw_get_align(pidx, widx); - get alignment and size restrition parameters
to properly allocate inbound memory region.
ntb_peer_mw_count(); - get number of outbound memory windows.
ntb_peer_mw_get_addr(widx); - get mapping address of an outbound memory window
Inbound MW based hardware:
ntb_mw_set_trans(pidx, widx); - set translation address of allocated inbound
memory window so a peer device could access it.
ntb_mw_clear_trans(pidx, widx); - clear the translation address of an inbound
memory window.
Outbound MW based hardware:
ntb_peer_mw_set_trans(pidx, widx); - set translation address of a memory
window retrieved from a peer device
ntb_peer_mw_clear_trans(pidx, widx); - clear the translation address of an
outbound memory window
5) Scratchpad interface needs to support multi-port devices as well
ntb_spad_count() - return number of Scratchpad per each port
ntb_peer_spad_addr(pidx, sidx) - address of Scratchpad register of the
peer device with pidx-index
ntb_peer_spad_read(pidx, sidx) - read specified Scratchpad register of the
peer with pidx-index
ntb_peer_spad_write(pidx, sidx) - write data to Scratchpad register of the
peer with pidx-index
6) Introduce new messaging interface of NTB KAPI
ntb_msg_count(); - get number of message registers
ntb_msg_inbits(); - get bitfield of inbound message registers status
ntb_msg_outbits(); - get bitfield of outbound message registers status
ntb_msg_read_sts(); - read the inbound and outbound message registers status
ntb_msg_clear_sts(); - clear status bits of message registers
ntb_msg_set_mask(); - mask interrupts raised by status bits of message
registers.
ntb_msg_clear_mask(); - clear interrupts mask bits of message registers
ntb_msg_recv(midx, *pidx); - read message register with specified index,
additionally getting peer port index which data received from
ntb_msg_send(midx, pidx); - write data to the specified message register
sending it to the passed peer device connected over a pidx port
ntb_msg_event(); - notify driver context of a new message event
7) Topology reduced to be either P2P (port-to-port) or B2B (bridge-to-bridge).
Since there is port number introduced to be part of ntb_dev structure, real
port number can be used to determine Primary and Secondary sides. Intel and AMD
driver are altered to support this novation.
8) Standard test drivers: PingPong, Debugging tool and Raw Perf as well as NTB
Transport drivers don't support multi-port devices at the moment.
Since we haven't got any real multi-port hadrware driver, it's dangerous to
make any serious alterations in the debugging tools. So I have made those
drivers to work the way they wokred before, but using the new NTB API.
The situation will change when I finish porting my current IDT NTB driver to
support new API. Then I'll be able to refactor the tools and test them using
real multi-port hardware.
The changes are made on top of the NTB-fork of the kernel:
https://github.com/jonmason/ntb
of "ntb"-branch with last commit:
9c763584b7c8911106bb77af7e648bef09af9d80 Linux 4.9-rc6
Signed-off-by: Serge Semin <fancer.lancer@gmail.com>
Serge Semin (22):
NTB: Move link state API being first in sources
NTB: Add peer indexed ports NTB API
NTB: Alter NTB API to support both inbound and outbound MW based
interfaces
NTB: Add messaging NTB API
NTB: Alter Scratchpads NTB API to support multi-ports interface
NTB: Slightly alter link state NTB API
NTB: Fix a few ntb.h issues
NTB: Add T-Platforms copyrights to NTB API
NTB Intel: Move link-related methods being first in the driver
NTB Intel: Add port-related NTB API callback methods
NTB Intel: Alter MW interface to fit new NTB API
NTB Intel: Alter Scratchpads interface to fit new NTB API
NTB Intel: Add T-Platforms copyrights to Intel NTB driver
NTB AMD: Move link-related methods being first in the driver
NTB AMD: Add port-related NTB API callback methods
NTB AMD: Alter MW interface to fit new NTB API
NTB AMD: Alter Scratchpads interface to fit new NTB API
NTB AMD: Add T-Platforms copyrights to AMD NTB driver
NTB PingPong: Alter driver to work with two-ports NTB API
NTB Tool: Alter driver to work with two-ports NTB API
NTB Perf: Alter driver to work with two-ports NTB API
NTB Transport: Alter driver to work with two-ports NTB API
drivers/ntb/hw/amd/ntb_hw_amd.c | 310 +++++++++------
drivers/ntb/hw/amd/ntb_hw_amd.h | 12 +
drivers/ntb/hw/intel/ntb_hw_intel.c | 420 ++++++++++++--------
drivers/ntb/hw/intel/ntb_hw_intel.h | 12 +
drivers/ntb/ntb.c | 15 +
drivers/ntb/ntb_transport.c | 43 +-
drivers/ntb/test/ntb_perf.c | 27 +-
drivers/ntb/test/ntb_pingpong.c | 11 +-
drivers/ntb/test/ntb_tool.c | 87 +++--
include/linux/ntb.h | 753 +++++++++++++++++++++++++++++-------
10 files changed, 1221 insertions(+), 469 deletions(-)
--
2.6.6
^ permalink raw reply [flat|nested] 2+ messages in thread* [PATCH 04/22] NTB: Add messaging NTB API
2016-11-29 17:15 [PATCH 00/22] NTB: Alter kernel API to support multi-port devices Serge Semin
@ 2016-11-29 17:15 ` Serge Semin
0 siblings, 0 replies; 2+ messages in thread
From: Serge Semin @ 2016-11-29 17:15 UTC (permalink / raw)
To: jdmason, dave.jiang, Allen.Hubbe, Xiangliang.Yu
Cc: Sergey.Semin, linux-ntb, linux-kernel, Serge Semin
IDT PCIe-switches have message registers to communicate with peer devices.
This patch adds new NTB API callback methods, which can be used to utilize
these registers functionality.
Signed-off-by: Serge Semin <fancer.lancer@gmail.com>
---
drivers/ntb/ntb.c | 13 +++
include/linux/ntb.h | 236 ++++++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 241 insertions(+), 8 deletions(-)
diff --git a/drivers/ntb/ntb.c b/drivers/ntb/ntb.c
index 2e25307..4b2cc60 100644
--- a/drivers/ntb/ntb.c
+++ b/drivers/ntb/ntb.c
@@ -191,6 +191,19 @@ void ntb_db_event(struct ntb_dev *ntb, int vector)
}
EXPORT_SYMBOL(ntb_db_event);
+void ntb_msg_event(struct ntb_dev *ntb)
+{
+ unsigned long irqflags;
+
+ spin_lock_irqsave(&ntb->ctx_lock, irqflags);
+ {
+ if (ntb->ctx_ops && ntb->ctx_ops->msg_event)
+ ntb->ctx_ops->msg_event(ntb->ctx);
+ }
+ spin_unlock_irqrestore(&ntb->ctx_lock, irqflags);
+}
+EXPORT_SYMBOL(ntb_msg_event);
+
static int ntb_probe(struct device *dev)
{
struct ntb_dev *ntb;
diff --git a/include/linux/ntb.h b/include/linux/ntb.h
index 4a150b5..59de1f6 100644
--- a/include/linux/ntb.h
+++ b/include/linux/ntb.h
@@ -146,10 +146,12 @@ static inline int ntb_client_ops_is_valid(const struct ntb_client_ops *ops)
* struct ntb_ctx_ops - ntb driver context operations
* @link_event: See ntb_link_event().
* @db_event: See ntb_db_event().
+ * @msg_event: See ntb_msg_event().
*/
struct ntb_ctx_ops {
void (*link_event)(void *ctx);
void (*db_event)(void *ctx, int db_vector);
+ void (*msg_event)(void *ctx);
};
static inline int ntb_ctx_ops_is_valid(const struct ntb_ctx_ops *ops)
@@ -158,6 +160,7 @@ static inline int ntb_ctx_ops_is_valid(const struct ntb_ctx_ops *ops)
return
/* ops->link_event && */
/* ops->db_event && */
+ /* ops->msg_event && */
1;
}
@@ -202,6 +205,15 @@ static inline int ntb_ctx_ops_is_valid(const struct ntb_ctx_ops *ops)
* @peer_spad_addr: See ntb_peer_spad_addr().
* @peer_spad_read: See ntb_peer_spad_read().
* @peer_spad_write: See ntb_peer_spad_write().
+ * @msg_count: See ntb_msg_count().
+ * @msg_inbits: See ntb_msg_inbits().
+ * @msg_outbits: See ntb_msg_outbits().
+ * @msg_read_sts: See ntb_msg_read_sts().
+ * @msg_clear_sts: See ntb_msg_clear_sts().
+ * @msg_set_mask: See ntb_msg_set_mask().
+ * @msg_clear_mask: See ntb_msg_clear_mask().
+ * @msg_read: See ntb_msg_read().
+ * @msg_write: See ntb_msg_write().
*/
struct ntb_dev_ops {
int (*port_number)(struct ntb_dev *ntb);
@@ -263,6 +275,16 @@ struct ntb_dev_ops {
phys_addr_t *spad_addr);
u32 (*peer_spad_read)(struct ntb_dev *ntb, int idx);
int (*peer_spad_write)(struct ntb_dev *ntb, int idx, u32 val);
+
+ int (*msg_count)(struct ntb_dev *ntb);
+ u64 (*msg_inbits)(struct ntb_dev *ntb);
+ u64 (*msg_outbits)(struct ntb_dev *ntb);
+ u64 (*msg_read_sts)(struct ntb_dev *ntb);
+ int (*msg_clear_sts)(struct ntb_dev *ntb, u64 sts_bits);
+ int (*msg_set_mask)(struct ntb_dev *ntb, u64 mask_bits);
+ int (*msg_clear_mask)(struct ntb_dev *ntb, u64 mask_bits);
+ int (*msg_read)(struct ntb_dev *ntb, int midx, int *pidx, u32 *msg);
+ int (*msg_write)(struct ntb_dev *ntb, int midx, int pidx, u32 msg);
};
static inline int ntb_dev_ops_is_valid(const struct ntb_dev_ops *ops)
@@ -304,13 +326,22 @@ static inline int ntb_dev_ops_is_valid(const struct ntb_dev_ops *ops)
/* ops->peer_db_read_mask && */
/* ops->peer_db_set_mask && */
/* ops->peer_db_clear_mask && */
- /* ops->spad_is_unsafe && */
- ops->spad_count &&
- ops->spad_read &&
- ops->spad_write &&
- /* ops->peer_spad_addr && */
- /* ops->peer_spad_read && */
- ops->peer_spad_write &&
+ ((/* ops->spad_is_unsafe && */
+ ops->spad_count &&
+ ops->spad_read &&
+ ops->spad_write &&
+ /* ops->peer_spad_addr && */
+ /* ops->peer_spad_read && */
+ ops->peer_spad_write) ||
+ (ops->msg_count &&
+ ops->msg_inbits &&
+ ops->msg_outbits &&
+ ops->msg_read_sts &&
+ ops->msg_clear_sts &&
+ /* ops->msg_set_mask && */
+ /* ops->msg_clear_mask && */
+ ops->msg_read &&
+ ops->msg_write)) &&
1;
}
@@ -456,6 +487,18 @@ void ntb_link_event(struct ntb_dev *ntb);
void ntb_db_event(struct ntb_dev *ntb, int vector);
/**
+ * ntb_msg_event() - notify driver context of a message event
+ * @ntb: NTB device context.
+ *
+ * Notify the driver context of a message event. If hardware supports
+ * message registers, this event indicates, that a new message arrived in
+ * some incoming message register or last sent message couldn't be delivered.
+ * The events can be masked/unmasked by the methods ntb_msg_set_mask() and
+ * ntb_msg_clear_mask().
+ */
+void ntb_msg_event(struct ntb_dev *ntb);
+
+/**
* ntb_port_number() - get the local port number
* @ntb: NTB device context.
*
@@ -1154,7 +1197,7 @@ static inline int ntb_spad_is_unsafe(struct ntb_dev *ntb)
}
/**
- * ntb_mw_count() - get the number of scratchpads
+ * ntb_spad_count() - get the number of scratchpads
* @ntb: NTB device context.
*
* Hardware and topology may support a different number of scratchpads.
@@ -1163,6 +1206,9 @@ static inline int ntb_spad_is_unsafe(struct ntb_dev *ntb)
*/
static inline int ntb_spad_count(struct ntb_dev *ntb)
{
+ if (!ntb->ops->spad_count)
+ return 0;
+
return ntb->ops->spad_count(ntb);
}
@@ -1177,6 +1223,9 @@ static inline int ntb_spad_count(struct ntb_dev *ntb)
*/
static inline u32 ntb_spad_read(struct ntb_dev *ntb, int idx)
{
+ if (!ntb->ops->spad_read)
+ return ~(u32)0;
+
return ntb->ops->spad_read(ntb, idx);
}
@@ -1192,6 +1241,9 @@ static inline u32 ntb_spad_read(struct ntb_dev *ntb, int idx)
*/
static inline int ntb_spad_write(struct ntb_dev *ntb, int idx, u32 val)
{
+ if (!ntb->ops->spad_write)
+ return -EINVAL;
+
return ntb->ops->spad_write(ntb, idx, val);
}
@@ -1226,6 +1278,9 @@ static inline int ntb_peer_spad_addr(struct ntb_dev *ntb, int idx,
*/
static inline u32 ntb_peer_spad_read(struct ntb_dev *ntb, int idx)
{
+ if (!ntb->ops->peer_spad_read)
+ return ~(u32)0;
+
return ntb->ops->peer_spad_read(ntb, idx);
}
@@ -1241,7 +1296,172 @@ static inline u32 ntb_peer_spad_read(struct ntb_dev *ntb, int idx)
*/
static inline int ntb_peer_spad_write(struct ntb_dev *ntb, int idx, u32 val)
{
+ if (!ntb->ops->peer_spad_write)
+ return -EINVAL;
+
return ntb->ops->peer_spad_write(ntb, idx, val);
}
+/**
+ * ntb_msg_count() - get the number of message registers
+ * @ntb: NTB device context.
+ *
+ * Hardware may support a different number of messge registers.
+ *
+ * Return: the number of message registers.
+ */
+static inline int ntb_msg_count(struct ntb_dev *ntb)
+{
+ if (!ntb->ops->msg_count)
+ return 0;
+
+ return ntb->ops->msg_count(ntb);
+}
+
+/**
+ * ntb_msg_inbits() - get a bitsfield of inbound message registers status
+ * @ntb: NTB device context.
+ *
+ * The method returns the bitsfield of status and mask registers, which related
+ * to inbound message registers.
+ *
+ * Return: bitsfield of inbound message registers.
+ */
+static inline u64 ntb_msg_inbits(struct ntb_dev *ntb)
+{
+ if (!ntb->ops->msg_inbits)
+ return 0;
+
+ return ntb->ops->msg_inbits(ntb);
+}
+
+/**
+ * ntb_msg_outbits() - get a bitsfield of outbound message registers status
+ * @ntb: NTB device context.
+ *
+ * The method returns the bitsfield of status and mask registers, which related
+ * to outbound message registers.
+ *
+ * Return: bitsfield of outbound message registers.
+ */
+static inline u64 ntb_msg_outbits(struct ntb_dev *ntb)
+{
+ if (!ntb->ops->msg_outbits)
+ return 0;
+
+ return ntb->ops->msg_outbits(ntb);
+}
+
+/**
+ * ntb_msg_read_sts() - read the message registers status
+ * @ntb: NTB device context.
+ *
+ * Read the status of message register. Inbound and outbound message registers
+ * related bits can be filetered by masks retrieved from ntb_msg_inbits() and
+ * ntb_msg_outbits().
+ *
+ * Return: status bits of message registers
+ */
+static inline u64 ntb_msg_read_sts(struct ntb_dev *ntb)
+{
+ if (!ntb->ops->msg_read_sts)
+ return 0;
+
+ return ntb->ops->msg_read_sts(ntb);
+}
+
+/**
+ * ntb_msg_clear_sts() - clear status bits of message registers
+ * @ntb: NTB device context.
+ * @sts_bits: Status bits to clear.
+ *
+ * Clear bits in the status register.
+ *
+ * Return: Zero on success, otherwise a negative error number.
+ */
+static inline int ntb_msg_clear_sts(struct ntb_dev *ntb, u64 sts_bits)
+{
+ if (!ntb->ops->msg_clear_sts)
+ return -EINVAL;
+
+ return ntb->ops->msg_clear_sts(ntb, sts_bits);
+}
+
+/**
+ * ntb_msg_set_mask() - set mask of message register status bits
+ * @ntb: NTB device context.
+ * @mask_bits: Mask bits.
+ *
+ * Mask the message registers status bits from raising the message event.
+ *
+ * Return: Zero on success, otherwise a negative error number.
+ */
+static inline int ntb_msg_set_mask(struct ntb_dev *ntb, u64 mask_bits)
+{
+ if (!ntb->ops->msg_set_mask)
+ return -EINVAL;
+
+ return ntb->ops->msg_set_mask(ntb, mask_bits);
+}
+
+/**
+ * ntb_msg_clear_mask() - clear message registers mask
+ * @ntb: NTB device context.
+ * @mask_bits: Mask bits to clear.
+ *
+ * Clear bits in the message events mask register.
+ *
+ * Return: Zero on success, otherwise a negative error number.
+ */
+static inline int ntb_msg_clear_mask(struct ntb_dev *ntb, u64 mask_bits)
+{
+ if (!ntb->ops->msg_clear_mask)
+ return -EINVAL;
+
+ return ntb->ops->msg_clear_mask(ntb, mask_bits);
+}
+
+/**
+ * ntb_msg_read() - read message register with specified index
+ * @ntb: NTB device context.
+ * @midx: Message register index
+ * @pidx: OUT - Port index of peer device a message retrieved from
+ * @msg: OUT - Data
+ *
+ * Read data from the specified message register. Source port index of a
+ * message is retrieved as well.
+ *
+ * Return: Zero on success, otherwise a negative error number.
+ */
+static inline int ntb_msg_read(struct ntb_dev *ntb, int midx, int *pidx,
+ u32 *msg)
+{
+ if (!ntb->ops->msg_read)
+ return -EINVAL;
+
+ return ntb->ops->msg_read(ntb, midx, pidx, msg);
+}
+
+/**
+ * ntb_msg_write() - write data to the specified message register
+ * @ntb: NTB device context.
+ * @midx: Message register index
+ * @pidx: Port index of peer device a message being sent to
+ * @msg: Data to send
+ *
+ * Send data to a specified peer device using the defined message register.
+ * Message event can be raised if the midx registers isn't empty while
+ * calling this method and the corresponding interrupt isn't masked.
+ *
+ * Return: Zero on success, otherwise a negative error number.
+ */
+static inline int ntb_msg_write(struct ntb_dev *ntb, int midx, int pidx,
+ u32 msg)
+{
+ if (!ntb->ops->msg_write)
+ return -EINVAL;
+
+ return ntb->ops->msg_write(ntb, midx, pidx, msg);
+}
+
#endif
--
2.6.6
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2016-12-04 0:10 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-12-04 0:05 [PATCH 04/22] NTB: Add messaging NTB API Allen Hubbe
-- strict thread matches above, loose matches on Subject: below --
2016-11-29 17:15 [PATCH 00/22] NTB: Alter kernel API to support multi-port devices Serge Semin
2016-11-29 17:15 ` [PATCH 04/22] NTB: Add messaging NTB API Serge Semin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome