#ifndef _GPXE_INFINIBAND_H #define _GPXE_INFINIBAND_H /** @file * * Infiniband protocol * */ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include #include #include /** Subnet management interface QPN */ #define IB_QPN_SMI 0 /** Subnet management interface queue key */ #define IB_QKEY_SMI 0 /** General service interface QPN */ #define IB_QPN_GSI 1 /** General service interface queue key */ #define IB_QKEY_GSI 0x80010000UL /** Broadcast QPN */ #define IB_QPN_BROADCAST 0xffffffUL /** Default Infiniband partition key */ #define IB_PKEY_NONE 0xffff /** * Maximum payload size * * This is currently hard-coded in various places (drivers, subnet * management agent, etc.) to 2048. */ #define IB_MAX_PAYLOAD_SIZE 2048 struct ib_device; struct ib_queue_pair; struct ib_address_vector; struct ib_completion_queue; struct ib_mad_interface; /** Infiniband transmission rates */ enum ib_rate { IB_RATE_2_5 = 2, IB_RATE_10 = 3, IB_RATE_30 = 4, IB_RATE_5 = 5, IB_RATE_20 = 6, IB_RATE_40 = 7, IB_RATE_60 = 8, IB_RATE_80 = 9, IB_RATE_120 = 10, }; /** An Infiniband Address Vector */ struct ib_address_vector { /** Queue Pair Number */ unsigned long qpn; /** Queue key * * Not specified for received packets. */ unsigned long qkey; /** Local ID */ unsigned int lid; /** Rate * * Not specified for received packets. */ enum ib_rate rate; /** Service level */ unsigned int sl; /** GID is present */ unsigned int gid_present; /** GID, if present */ struct ib_gid gid; }; /** An Infiniband Work Queue */ struct ib_work_queue { /** Containing queue pair */ struct ib_queue_pair *qp; /** "Is a send queue" flag */ int is_send; /** Associated completion queue */ struct ib_completion_queue *cq; /** List of work queues on this completion queue */ struct list_head list; /** Packet sequence number */ uint32_t psn; /** Number of work queue entries */ unsigned int num_wqes; /** Number of occupied work queue entries */ unsigned int fill; /** Next work queue entry index * * This is the index of the next entry to be filled (i.e. the * first empty entry). This value is not bounded by num_wqes; * users must logical-AND with (num_wqes-1) to generate an * array index. */ unsigned long next_idx; /** I/O buffers assigned to work queue */ struct io_buffer **iobufs; /** Driver private data */ void *drv_priv; }; /** An Infiniband multicast GID */ struct ib_multicast_gid { /** List of multicast GIDs on this QP */ struct list_head list; /** Multicast GID */ struct ib_gid gid; }; /** An Infiniband queue pair type */ enum ib_queue_pair_type { IB_QPT_SMI, IB_QPT_GSI, IB_QPT_UD, IB_QPT_RC, }; /** An Infiniband Queue Pair */ struct ib_queue_pair { /** Containing Infiniband device */ struct ib_device *ibdev; /** List of queue pairs on this Infiniband device */ struct list_head list; /** Queue pair number */ unsigned long qpn; /** Externally-visible queue pair number * * This may differ from the real queue pair number (e.g. when * the HCA cannot use the management QPNs 0 and 1 as hardware * QPNs and needs to remap them). */ unsigned long ext_qpn; /** Queue pair type */ enum ib_queue_pair_type type; /** Queue key */ unsigned long qkey; /** Send queue */ struct ib_work_queue send; /** Receive queue */ struct ib_work_queue recv; /** List of multicast GIDs */ struct list_head mgids; /** Address vector */ struct ib_address_vector av; /** Driver private data */ void *drv_priv; /** Queue owner private data */ void *owner_priv; }; /** Infiniband completion queue operations */ struct ib_completion_queue_operations { /** * Complete Send WQE * * @v ibdev Infiniband device * @v qp Queue pair * @v iobuf I/O buffer * @v rc Completion status code */ void ( * complete_send ) ( struct ib_device *ibdev, struct ib_queue_pair *qp, struct io_buffer *iobuf, int rc ); /** * Complete Receive WQE * * @v ibdev Infiniband device * @v qp Queue pair * @v av Address vector, or NULL * @v iobuf I/O buffer * @v rc Completion status code */ void ( * complete_recv ) ( struct ib_device *ibdev, struct ib_queue_pair *qp, struct ib_address_vector *av, struct io_buffer *iobuf, int rc ); }; /** An Infiniband Completion Queue */ struct ib_completion_queue { /** Containing Infiniband device */ struct ib_device *ibdev; /** List of completion queues on this Infiniband device */ struct list_head list; /** Completion queue number */ unsigned long cqn; /** Number of completion queue entries */ unsigned int num_cqes; /** Next completion queue entry index * * This is the index of the next entry to be filled (i.e. the * first empty entry). This value is not bounded by num_wqes; * users must logical-AND with (num_wqes-1) to generate an * array index. */ unsigned long next_idx; /** List of work queues completing to this queue */ struct list_head work_queues; /** Completion queue operations */ struct ib_completion_queue_operations *op; /** Driver private data */ void *drv_priv; }; /** * Infiniband device operations * * These represent a subset of the Infiniband Verbs. */ struct ib_device_operations { /** Create completion queue * * @v ibdev Infiniband device * @v cq Completion queue * @ret rc Return status code */ int ( * create_cq ) ( struct ib_device *ibdev, struct ib_completion_queue *cq ); /** Destroy completion queue * * @v ibdev Infiniband device * @v cq Completion queue */ void ( * destroy_cq ) ( struct ib_device *ibdev, struct ib_completion_queue *cq ); /** Create queue pair * * @v ibdev Infiniband device * @v qp Queue pair * @ret rc Return status code */ int ( * create_qp ) ( struct ib_device *ibdev, struct ib_queue_pair *qp ); /** Modify queue pair * * @v ibdev Infiniband device * @v qp Queue pair * @ret rc Return status code */ int ( * modify_qp ) ( struct ib_device *ibdev, struct ib_queue_pair *qp ); /** Destroy queue pair * * @v ibdev Infiniband device * @v qp Queue pair */ void ( * destroy_qp ) ( struct ib_device *ibdev, struct ib_queue_pair *qp ); /** Post send work queue entry * * @v ibdev Infiniband device * @v qp Queue pair * @v av Address vector * @v iobuf I/O buffer * @ret rc Return status code * * If this method returns success, the I/O buffer remains * owned by the queue pair. If this method returns failure, * the I/O buffer is immediately released; the failure is * interpreted as "failure to enqueue buffer". */ int ( * post_send ) ( struct ib_device *ibdev, struct ib_queue_pair *qp, struct ib_address_vector *av, struct io_buffer *iobuf ); /** Post receive work queue entry * * @v ibdev Infiniband device * @v qp Queue pair * @v iobuf I/O buffer * @ret rc Return status code * * If this method returns success, the I/O buffer remains * owned by the queue pair. If this method returns failure, * the I/O buffer is immediately released; the failure is * interpreted as "failure to enqueue buffer". */ int ( * post_recv ) ( struct ib_device *ibdev, struct ib_queue_pair *qp, struct io_buffer *iobuf ); /** Poll completion queue * * @v ibdev Infiniband device * @v cq Completion queue * * The relevant completion handler (specified at completion * queue creation time) takes ownership of the I/O buffer. */ void ( * poll_cq ) ( struct ib_device *ibdev, struct ib_completion_queue *cq ); /** * Poll event queue * * @v ibdev Infiniband device */ void ( * poll_eq ) ( struct ib_device *ibdev ); /** * Open port * * @v ibdev Infiniband device * @ret rc Return status code */ int ( * open ) ( struct ib_device *ibdev ); /** * Close port * * @v ibdev Infiniband device */ void ( * close ) ( struct ib_device *ibdev ); /** Attach to multicast group * * @v ibdev Infiniband device * @v qp Queue pair * @v gid Multicast GID * @ret rc Return status code */ int ( * mcast_attach ) ( struct ib_device *ibdev, struct ib_queue_pair *qp, struct ib_gid *gid ); /** Detach from multicast group * * @v ibdev Infiniband device * @v qp Queue pair * @v gid Multicast GID */ void ( * mcast_detach ) ( struct ib_device *ibdev, struct ib_queue_pair *qp, struct ib_gid *gid ); /** Set port information * * @v ibdev Infiniband device * @v mad Set port information MAD * * This method is required only by adapters that do not have * an embedded SMA. */ int ( * set_port_info ) ( struct ib_device *ibdev, union ib_mad *mad ); /** Set partition key table * * @v ibdev Infiniband device * @v mad Set partition key table MAD * * This method is required only by adapters that do not have * an embedded SMA. */ int ( * set_pkey_table ) ( struct ib_device *ibdev, union ib_mad *mad ); }; /** An Infiniband device */ struct ib_device { /** Reference counter */ struct refcnt refcnt; /** List of Infiniband devices */ struct list_head list; /** List of open Infiniband devices */ struct list_head open_list; /** Underlying device */ struct device *dev; /** List of completion queues */ struct list_head cqs; /** List of queue pairs */ struct list_head qps; /** Infiniband operations */ struct ib_device_operations *op; /** Port number */ unsigned int port; /** Port open request counter */ unsigned int open_count; /** Port state */ uint8_t port_state; /** Link width supported */ uint8_t link_width_supported; /** Link width enabled */ uint8_t link_width_enabled; /** Link width active */ uint8_t link_width_active; /** Link speed supported */ uint8_t link_speed_supported; /** Link speed enabled */ uint8_t link_speed_enabled; /** Link speed active */ uint8_t link_speed_active; /** Port GID */ struct ib_gid gid; /** Port LID */ uint16_t lid; /** Subnet manager LID */ uint16_t sm_lid; /** Subnet manager SL */ uint8_t sm_sl; /** Partition key */ uint16_t pkey; /** RDMA key * * This is a single key allowing unrestricted access to * memory. */ uint32_t rdma_key; /** Subnet management interface */ struct ib_mad_interface *smi; /** General services interface */ struct ib_mad_interface *gsi; /** Driver private data */ void *drv_priv; /** Owner private data */ void *owner_priv; }; extern struct ib_completion_queue * ib_create_cq ( struct ib_device *ibdev, unsigned int num_cqes, struct ib_completion_queue_operations *op ); extern void ib_destroy_cq ( struct ib_device *ibdev, struct ib_completion_queue *cq ); extern void ib_poll_cq ( struct ib_device *ibdev, struct ib_completion_queue *cq ); extern struct ib_queue_pair * ib_create_qp ( struct ib_device *ibdev, enum ib_queue_pair_type type, unsigned int num_send_wqes, struct ib_completion_queue *send_cq, unsigned int num_recv_wqes, struct ib_completion_queue *recv_cq ); extern int ib_modify_qp ( struct ib_device *ibdev, struct ib_queue_pair *qp ); extern void ib_destroy_qp ( struct ib_device *ibdev, struct ib_queue_pair *qp ); extern struct ib_queue_pair * ib_find_qp_qpn ( struct ib_device *ibdev, unsigned long qpn ); extern struct ib_queue_pair * ib_find_qp_mgid ( struct ib_device *ibdev, struct ib_gid *gid ); extern struct ib_work_queue * ib_find_wq ( struct ib_completion_queue *cq, unsigned long qpn, int is_send ); extern int ib_post_send ( struct ib_device *ibdev, struct ib_queue_pair *qp, struct ib_address_vector *av, struct io_buffer *iobuf ); extern int ib_post_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp, struct io_buffer *iobuf ); extern void ib_complete_send ( struct ib_device *ibdev, struct ib_queue_pair *qp, struct io_buffer *iobuf, int rc ); extern void ib_complete_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp, struct ib_address_vector *av, struct io_buffer *iobuf, int rc ); extern void ib_refill_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp ); extern int ib_open ( struct ib_device *ibdev ); extern void ib_close ( struct ib_device *ibdev ); extern int ib_mcast_attach ( struct ib_device *ibdev, struct ib_queue_pair *qp, struct ib_gid *gid ); extern void ib_mcast_detach ( struct ib_device *ibdev, struct ib_queue_pair *qp, struct ib_gid *gid ); extern int ib_get_hca_info ( struct ib_device *ibdev, struct ib_gid_half *hca_guid ); extern int ib_set_port_info ( struct ib_device *ibdev, union ib_mad *mad ); extern int ib_set_pkey_table ( struct ib_device *ibdev, union ib_mad *mad ); extern struct ib_device * alloc_ibdev ( size_t priv_size ); extern int register_ibdev ( struct ib_device *ibdev ); extern void unregister_ibdev ( struct ib_device *ibdev ); extern struct ib_device * find_ibdev ( struct ib_gid *gid ); extern struct ib_device * last_opened_ibdev ( void ); extern void ib_link_state_changed ( struct ib_device *ibdev ); extern void ib_poll_eq ( struct ib_device *ibdev ); extern struct list_head ib_devices; /** Iterate over all network devices */ #define for_each_ibdev( ibdev ) \ list_for_each_entry ( (ibdev), &ib_devices, list ) /** * Check link state * * @v ibdev Infiniband device * @ret link_up Link is up */ static inline __always_inline int ib_link_ok ( struct ib_device *ibdev ) { return ( ibdev->port_state == IB_PORT_STATE_ACTIVE ); } /** * Get reference to Infiniband device * * @v ibdev Infiniband device * @ret ibdev Infiniband device */ static inline __always_inline struct ib_device * ibdev_get ( struct ib_device *ibdev ) { ref_get ( &ibdev->refcnt ); return ibdev; } /** * Drop reference to Infiniband device * * @v ibdev Infiniband device */ static inline __always_inline void ibdev_put ( struct ib_device *ibdev ) { ref_put ( &ibdev->refcnt ); } /** * Set Infiniband work queue driver-private data * * @v wq Work queue * @v priv Private data */ static inline __always_inline void ib_wq_set_drvdata ( struct ib_work_queue *wq, void *priv ) { wq->drv_priv = priv; } /** * Get Infiniband work queue driver-private data * * @v wq Work queue * @ret priv Private data */ static inline __always_inline void * ib_wq_get_drvdata ( struct ib_work_queue *wq ) { return wq->drv_priv; } /** * Set Infiniband queue pair driver-private data * * @v qp Queue pair * @v priv Private data */ static inline __always_inline void ib_qp_set_drvdata ( struct ib_queue_pair *qp, void *priv ) { qp->drv_priv = priv; } /** * Get Infiniband queue pair driver-private data * * @v qp Queue pair * @ret priv Private data */ static inline __always_inline void * ib_qp_get_drvdata ( struct ib_queue_pair *qp ) { return qp->drv_priv; } /** * Set Infiniband queue pair owner-private data * * @v qp Queue pair * @v priv Private data */ static inline __always_inline void ib_qp_set_ownerdata ( struct ib_queue_pair *qp, void *priv ) { qp->owner_priv = priv; } /** * Get Infiniband queue pair owner-private data * * @v qp Queue pair * @ret priv Private data */ static inline __always_inline void * ib_qp_get_ownerdata ( struct ib_queue_pair *qp ) { return qp->owner_priv; } /** * Set Infiniband completion queue driver-private data * * @v cq Completion queue * @v priv Private data */ static inline __always_inline void ib_cq_set_drvdata ( struct ib_completion_queue *cq, void *priv ) { cq->drv_priv = priv; } /** * Get Infiniband completion queue driver-private data * * @v cq Completion queue * @ret priv Private data */ static inline __always_inline void * ib_cq_get_drvdata ( struct ib_completion_queue *cq ) { return cq->drv_priv; } /** * Set Infiniband device driver-private data * * @v ibdev Infiniband device * @v priv Private data */ static inline __always_inline void ib_set_drvdata ( struct ib_device *ibdev, void *priv ) { ibdev->drv_priv = priv; } /** * Get Infiniband device driver-private data * * @v ibdev Infiniband device * @ret priv Private data */ static inline __always_inline void * ib_get_drvdata ( struct ib_device *ibdev ) { return ibdev->drv_priv; } /** * Set Infiniband device owner-private data * * @v ibdev Infiniband device * @v priv Private data */ static inline __always_inline void ib_set_ownerdata ( struct ib_device *ibdev, void *priv ) { ibdev->owner_priv = priv; } /** * Get Infiniband device owner-private data * * @v ibdev Infiniband device * @ret priv Private data */ static inline __always_inline void * ib_get_ownerdata ( struct ib_device *ibdev ) { return ibdev->owner_priv; } #endif /* _GPXE_INFINIBAND_H */