Skip to content

Commit

Permalink
smc: work request (WR) base for use by LLC and CDC
Browse files Browse the repository at this point in the history
The base containers for RDMA transport are work requests and completion
queue entries processed through Infiniband verbs:
* allocate and initialize these areas
* map these areas to DMA
* implement the basic communication consisting of work request posting
  and receival of completion queue events

Signed-off-by: Ursula Braun <ubraun@linux.vnet.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Ursula Braun authored and davem330 committed Jan 9, 2017
1 parent cd6851f commit f38ba17
Show file tree
Hide file tree
Showing 8 changed files with 790 additions and 1 deletion.
2 changes: 1 addition & 1 deletion net/smc/Makefile
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
obj-$(CONFIG_SMC) += smc.o
smc-y := af_smc.o smc_pnet.o smc_ib.o smc_clc.o smc_core.o
smc-y := af_smc.o smc_pnet.o smc_ib.o smc_clc.o smc_core.o smc_wr.o
5 changes: 5 additions & 0 deletions net/smc/smc.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#include <linux/socket.h>
#include <linux/types.h>
#include <linux/compiler.h> /* __aligned */
#include <net/sock.h>

#include "smc_ib.h"
Expand All @@ -29,6 +30,10 @@ enum smc_state { /* possible states of an SMC socket */

struct smc_link_group;

struct smc_wr_rx_hdr { /* common prefix part of LLC and CDC to demultiplex */
u8 type;
} __aligned(1);

struct smc_connection {
struct rb_node alert_node;
struct smc_link_group *lgr; /* link group of connection */
Expand Down
11 changes: 11 additions & 0 deletions net/smc/smc_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "smc_clc.h"
#include "smc_core.h"
#include "smc_ib.h"
#include "smc_wr.h"

#define SMC_LGR_FREE_DELAY (600 * HZ)

Expand Down Expand Up @@ -161,12 +162,20 @@ static int smc_lgr_create(struct smc_sock *smc, __be32 peer_in_addr,
lnk->path_mtu = smcibdev->pattr[ibport - 1].active_mtu;
get_random_bytes(rndvec, sizeof(rndvec));
lnk->psn_initial = rndvec[0] + (rndvec[1] << 8) + (rndvec[2] << 16);
rc = smc_wr_alloc_link_mem(lnk);
if (rc)
goto free_lgr;
init_waitqueue_head(&lnk->wr_tx_wait);

smc->conn.lgr = lgr;
rwlock_init(&lgr->conns_lock);
spin_lock_bh(&smc_lgr_list.lock);
list_add(&lgr->list, &smc_lgr_list.list);
spin_unlock_bh(&smc_lgr_list.lock);
return 0;

free_lgr:
kfree(lgr);
out:
return rc;
}
Expand Down Expand Up @@ -202,6 +211,8 @@ void smc_conn_free(struct smc_connection *conn)
static void smc_link_clear(struct smc_link *lnk)
{
lnk->peer_qpn = 0;
smc_wr_free_link(lnk);
smc_wr_free_link_mem(lnk);
}

static void smc_lgr_free_sndbufs(struct smc_link_group *lgr)
Expand Down
30 changes: 30 additions & 0 deletions net/smc/smc_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#ifndef _SMC_CORE_H
#define _SMC_CORE_H

#include <linux/atomic.h>
#include <rdma/ib_verbs.h>

#include "smc.h"
Expand All @@ -30,11 +31,40 @@ enum smc_lgr_role { /* possible roles of a link group */
SMC_SERV /* server */
};

#define SMC_WR_BUF_SIZE 48 /* size of work request buffer */

struct smc_wr_buf {
u8 raw[SMC_WR_BUF_SIZE];
};

struct smc_link {
struct smc_ib_device *smcibdev; /* ib-device */
u8 ibport; /* port - values 1 | 2 */
struct ib_pd *roce_pd; /* IB protection domain,
* unique for every RoCE QP
*/
struct ib_qp *roce_qp; /* IB queue pair */
struct ib_qp_attr qp_attr; /* IB queue pair attributes */

struct smc_wr_buf *wr_tx_bufs; /* WR send payload buffers */
struct ib_send_wr *wr_tx_ibs; /* WR send meta data */
struct ib_sge *wr_tx_sges; /* WR send gather meta data */
struct smc_wr_tx_pend *wr_tx_pends; /* WR send waiting for CQE */
/* above four vectors have wr_tx_cnt elements and use the same index */
dma_addr_t wr_tx_dma_addr; /* DMA address of wr_tx_bufs */
atomic_long_t wr_tx_id; /* seq # of last sent WR */
unsigned long *wr_tx_mask; /* bit mask of used indexes */
u32 wr_tx_cnt; /* number of WR send buffers */
wait_queue_head_t wr_tx_wait; /* wait for free WR send buf */

struct smc_wr_buf *wr_rx_bufs; /* WR recv payload buffers */
struct ib_recv_wr *wr_rx_ibs; /* WR recv meta data */
struct ib_sge *wr_rx_sges; /* WR recv scatter meta data */
/* above three vectors have wr_rx_cnt elements and use the same index */
dma_addr_t wr_rx_dma_addr; /* DMA address of wr_rx_bufs */
u64 wr_rx_id; /* seq # of last recv WR */
u32 wr_rx_cnt; /* number of WR recv buffers */

union ib_gid gid; /* gid matching used vlan id */
u32 peer_qpn; /* QP number of peer */
enum ib_mtu path_mtu; /* used mtu */
Expand Down
73 changes: 73 additions & 0 deletions net/smc/smc_ib.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "smc_pnet.h"
#include "smc_ib.h"
#include "smc_core.h"
#include "smc_wr.h"
#include "smc.h"

struct smc_ib_devices smc_ib_devices = { /* smc-registered ib devices */
Expand All @@ -30,6 +31,78 @@ u8 local_systemid[SMC_SYSTEMID_LEN] = SMC_LOCAL_SYSTEMID_RESET; /* unique system
* identifier
*/

void smc_ib_dealloc_protection_domain(struct smc_link *lnk)
{
ib_dealloc_pd(lnk->roce_pd);
lnk->roce_pd = NULL;
}

int smc_ib_create_protection_domain(struct smc_link *lnk)
{
int rc;

lnk->roce_pd = ib_alloc_pd(lnk->smcibdev->ibdev, 0);
rc = PTR_ERR_OR_ZERO(lnk->roce_pd);
if (IS_ERR(lnk->roce_pd))
lnk->roce_pd = NULL;
return rc;
}

static void smc_ib_qp_event_handler(struct ib_event *ibevent, void *priv)
{
switch (ibevent->event) {
case IB_EVENT_DEVICE_FATAL:
case IB_EVENT_GID_CHANGE:
case IB_EVENT_PORT_ERR:
case IB_EVENT_QP_ACCESS_ERR:
/* tbd in follow-on patch:
* abnormal close of corresponding connections
*/
break;
default:
break;
}
}

void smc_ib_destroy_queue_pair(struct smc_link *lnk)
{
ib_destroy_qp(lnk->roce_qp);
lnk->roce_qp = NULL;
}

/* create a queue pair within the protection domain for a link */
int smc_ib_create_queue_pair(struct smc_link *lnk)
{
struct ib_qp_init_attr qp_attr = {
.event_handler = smc_ib_qp_event_handler,
.qp_context = lnk,
.send_cq = lnk->smcibdev->roce_cq_send,
.recv_cq = lnk->smcibdev->roce_cq_recv,
.srq = NULL,
.cap = {
.max_send_wr = SMC_WR_BUF_CNT,
/* include unsolicited rdma_writes as well,
* there are max. 2 RDMA_WRITE per 1 WR_SEND
*/
.max_recv_wr = SMC_WR_BUF_CNT * 3,
.max_send_sge = SMC_IB_MAX_SEND_SGE,
.max_recv_sge = 1,
.max_inline_data = SMC_WR_TX_SIZE,
},
.sq_sig_type = IB_SIGNAL_REQ_WR,
.qp_type = IB_QPT_RC,
};
int rc;

lnk->roce_qp = ib_create_qp(lnk->roce_pd, &qp_attr);
rc = PTR_ERR_OR_ZERO(lnk->roce_qp);
if (IS_ERR(lnk->roce_qp))
lnk->roce_qp = NULL;
else
smc_wr_remember_qp_attr(lnk);
return rc;
}

/* map a new TX or RX buffer to DMA */
int smc_ib_buf_map(struct smc_ib_device *smcibdev, int buf_size,
struct smc_buf_desc *buf_slot,
Expand Down
11 changes: 11 additions & 0 deletions net/smc/smc_ib.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
#define SMC_MAX_PORTS 2 /* Max # of ports */
#define SMC_GID_SIZE sizeof(union ib_gid)

#define SMC_IB_MAX_SEND_SGE 2

struct smc_ib_devices { /* list of smc ib devices definition */
struct list_head list;
spinlock_t lock; /* protects list of smc ib devices */
Expand All @@ -27,12 +29,17 @@ struct smc_ib_device { /* ib-device infos for smc */
struct list_head list;
struct ib_device *ibdev;
struct ib_port_attr pattr[SMC_MAX_PORTS]; /* ib dev. port attrs */
struct ib_cq *roce_cq_send; /* send completion queue */
struct ib_cq *roce_cq_recv; /* recv completion queue */
struct tasklet_struct send_tasklet; /* called by send cq handler */
struct tasklet_struct recv_tasklet; /* called by recv cq handler */
char mac[SMC_MAX_PORTS][6]; /* mac address per port*/
union ib_gid gid[SMC_MAX_PORTS]; /* gid per port */
u8 initialized : 1; /* ib dev CQ, evthdl done */
};

struct smc_buf_desc;
struct smc_link;

int smc_ib_register_client(void) __init;
void smc_ib_unregister_client(void);
Expand All @@ -41,5 +48,9 @@ int smc_ib_remember_port_attr(struct smc_ib_device *smcibdev, u8 ibport);
int smc_ib_buf_map(struct smc_ib_device *smcibdev, int buf_size,
struct smc_buf_desc *buf_slot,
enum dma_data_direction data_direction);
void smc_ib_dealloc_protection_domain(struct smc_link *lnk);
int smc_ib_create_protection_domain(struct smc_link *lnk);
void smc_ib_destroy_queue_pair(struct smc_link *lnk);
int smc_ib_create_queue_pair(struct smc_link *lnk);

#endif
Loading

0 comments on commit f38ba17

Please sign in to comment.