From: Serge Semin
> Some IDT NTB-capable 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:
>  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_read(midx, *pidx); - read message register with specified index,
> additionally getting peer port index which data received from
>  ntb_msg_write(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
> 
> Of course there is hadrware which doesn't support Message registers, so

s/hadrware/hardware/

> this API is made optional.
> 
> Signed-off-by: Serge Semin <fancer.lan...@gmail.com>

Acked-by: Allen Hubbe <allen.hu...@dell.com>

> 
> ---
>  drivers/ntb/ntb.c   |  13 ++++
>  include/linux/ntb.h | 205 
> ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 218 insertions(+)
> 
> diff --git a/drivers/ntb/ntb.c b/drivers/ntb/ntb.c
> index f6153af..06574f8 100644
> --- a/drivers/ntb/ntb.c
> +++ b/drivers/ntb/ntb.c
> @@ -193,6 +193,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 a6bf15d..90746df 100644
> --- a/include/linux/ntb.h
> +++ b/include/linux/ntb.h
> @@ -164,10 +164,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)
> @@ -176,6 +178,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;
>  }
> 
> @@ -220,6 +223,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);
> @@ -282,6 +294,16 @@ struct ntb_dev_ops {
>       u32 (*peer_spad_read)(struct ntb_dev *ntb, int pidx, int sidx);
>       int (*peer_spad_write)(struct ntb_dev *ntb, int pidx, int sidx,
>                              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)
> @@ -329,6 +351,15 @@ static inline int ntb_dev_ops_is_valid(const struct 
> ntb_dev_ops *ops)
>               /* !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;
>  }
> 
> @@ -472,6 +503,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.
>   *
> @@ -1197,4 +1240,166 @@ static inline int ntb_peer_spad_write(struct ntb_dev 
> *ntb, int
> pidx, int sidx,
>       return ntb->ops->peer_spad_write(ntb, pidx, sidx, 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


Reply via email to