net/smc: introduce sg-logic for RMBs
The follow-on patch makes use of ib_map_mr_sg() when introducing separate memory regions for RMBs. This function is based on scatterlists; thus this patch introduces scatterlists for RMBs. Signed-off-by: Ursula Braun <ubraun@linux.vnet.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
c45abf31e7
commit
a3fe3d01bd
@ -204,13 +204,13 @@ int smc_clc_send_confirm(struct smc_sock *smc)
|
|||||||
memcpy(&cclc.lcl.mac, &link->smcibdev->mac[link->ibport - 1], ETH_ALEN);
|
memcpy(&cclc.lcl.mac, &link->smcibdev->mac[link->ibport - 1], ETH_ALEN);
|
||||||
hton24(cclc.qpn, link->roce_qp->qp_num);
|
hton24(cclc.qpn, link->roce_qp->qp_num);
|
||||||
cclc.rmb_rkey =
|
cclc.rmb_rkey =
|
||||||
htonl(conn->rmb_desc->rkey[SMC_SINGLE_LINK]);
|
htonl(link->roce_pd->unsafe_global_rkey);
|
||||||
cclc.conn_idx = 1; /* for now: 1 RMB = 1 RMBE */
|
cclc.conn_idx = 1; /* for now: 1 RMB = 1 RMBE */
|
||||||
cclc.rmbe_alert_token = htonl(conn->alert_token_local);
|
cclc.rmbe_alert_token = htonl(conn->alert_token_local);
|
||||||
cclc.qp_mtu = min(link->path_mtu, link->peer_mtu);
|
cclc.qp_mtu = min(link->path_mtu, link->peer_mtu);
|
||||||
cclc.rmbe_size = conn->rmbe_size_short;
|
cclc.rmbe_size = conn->rmbe_size_short;
|
||||||
cclc.rmb_dma_addr =
|
cclc.rmb_dma_addr = cpu_to_be64(
|
||||||
cpu_to_be64((u64)conn->rmb_desc->dma_addr[SMC_SINGLE_LINK]);
|
(u64)sg_dma_address(conn->rmb_desc->sgt[SMC_SINGLE_LINK].sgl));
|
||||||
hton24(cclc.psn, link->psn_initial);
|
hton24(cclc.psn, link->psn_initial);
|
||||||
|
|
||||||
memcpy(cclc.trl.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER));
|
memcpy(cclc.trl.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER));
|
||||||
@ -256,13 +256,13 @@ int smc_clc_send_accept(struct smc_sock *new_smc, int srv_first_contact)
|
|||||||
memcpy(&aclc.lcl.mac, link->smcibdev->mac[link->ibport - 1], ETH_ALEN);
|
memcpy(&aclc.lcl.mac, link->smcibdev->mac[link->ibport - 1], ETH_ALEN);
|
||||||
hton24(aclc.qpn, link->roce_qp->qp_num);
|
hton24(aclc.qpn, link->roce_qp->qp_num);
|
||||||
aclc.rmb_rkey =
|
aclc.rmb_rkey =
|
||||||
htonl(conn->rmb_desc->rkey[SMC_SINGLE_LINK]);
|
htonl(link->roce_pd->unsafe_global_rkey);
|
||||||
aclc.conn_idx = 1; /* as long as 1 RMB = 1 RMBE */
|
aclc.conn_idx = 1; /* as long as 1 RMB = 1 RMBE */
|
||||||
aclc.rmbe_alert_token = htonl(conn->alert_token_local);
|
aclc.rmbe_alert_token = htonl(conn->alert_token_local);
|
||||||
aclc.qp_mtu = link->path_mtu;
|
aclc.qp_mtu = link->path_mtu;
|
||||||
aclc.rmbe_size = conn->rmbe_size_short,
|
aclc.rmbe_size = conn->rmbe_size_short,
|
||||||
aclc.rmb_dma_addr =
|
aclc.rmb_dma_addr = cpu_to_be64(
|
||||||
cpu_to_be64((u64)conn->rmb_desc->dma_addr[SMC_SINGLE_LINK]);
|
(u64)sg_dma_address(conn->rmb_desc->sgt[SMC_SINGLE_LINK].sgl));
|
||||||
hton24(aclc.psn, link->psn_initial);
|
hton24(aclc.psn, link->psn_initial);
|
||||||
memcpy(aclc.trl.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER));
|
memcpy(aclc.trl.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER));
|
||||||
|
|
||||||
|
@ -266,17 +266,16 @@ static void smc_lgr_free_sndbufs(struct smc_link_group *lgr)
|
|||||||
|
|
||||||
static void smc_lgr_free_rmbs(struct smc_link_group *lgr)
|
static void smc_lgr_free_rmbs(struct smc_link_group *lgr)
|
||||||
{
|
{
|
||||||
struct smc_buf_desc *rmb_desc, *bf_desc;
|
|
||||||
struct smc_link *lnk = &lgr->lnk[SMC_SINGLE_LINK];
|
struct smc_link *lnk = &lgr->lnk[SMC_SINGLE_LINK];
|
||||||
|
struct smc_buf_desc *rmb_desc, *bf_desc;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < SMC_RMBE_SIZES; i++) {
|
for (i = 0; i < SMC_RMBE_SIZES; i++) {
|
||||||
list_for_each_entry_safe(rmb_desc, bf_desc, &lgr->rmbs[i],
|
list_for_each_entry_safe(rmb_desc, bf_desc, &lgr->rmbs[i],
|
||||||
list) {
|
list) {
|
||||||
list_del(&rmb_desc->list);
|
list_del(&rmb_desc->list);
|
||||||
smc_ib_buf_unmap(lnk->smcibdev,
|
smc_ib_buf_unmap_sg(lnk->smcibdev, rmb_desc,
|
||||||
smc_uncompress_bufsize(i),
|
DMA_FROM_DEVICE);
|
||||||
rmb_desc, DMA_FROM_DEVICE);
|
|
||||||
kfree(rmb_desc->cpu_addr);
|
kfree(rmb_desc->cpu_addr);
|
||||||
kfree(rmb_desc);
|
kfree(rmb_desc);
|
||||||
}
|
}
|
||||||
@ -580,38 +579,54 @@ int smc_rmb_create(struct smc_sock *smc)
|
|||||||
for (bufsize_short = smc_compress_bufsize(smc->sk.sk_rcvbuf / 2);
|
for (bufsize_short = smc_compress_bufsize(smc->sk.sk_rcvbuf / 2);
|
||||||
bufsize_short >= 0; bufsize_short--) {
|
bufsize_short >= 0; bufsize_short--) {
|
||||||
bufsize = smc_uncompress_bufsize(bufsize_short);
|
bufsize = smc_uncompress_bufsize(bufsize_short);
|
||||||
|
if ((1 << get_order(bufsize)) > SG_MAX_SINGLE_ALLOC)
|
||||||
|
continue;
|
||||||
|
|
||||||
/* check for reusable rmb_slot in the link group */
|
/* check for reusable rmb_slot in the link group */
|
||||||
rmb_desc = smc_rmb_get_slot(lgr, bufsize_short);
|
rmb_desc = smc_rmb_get_slot(lgr, bufsize_short);
|
||||||
if (rmb_desc) {
|
if (rmb_desc) {
|
||||||
memset(rmb_desc->cpu_addr, 0, bufsize);
|
memset(rmb_desc->cpu_addr, 0, bufsize);
|
||||||
break; /* found reusable slot */
|
break; /* found reusable slot */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* try to alloc a new RMB */
|
/* try to alloc a new RMB */
|
||||||
rmb_desc = kzalloc(sizeof(*rmb_desc), GFP_KERNEL);
|
rmb_desc = kzalloc(sizeof(*rmb_desc), GFP_KERNEL);
|
||||||
if (!rmb_desc)
|
if (!rmb_desc)
|
||||||
break; /* give up with -ENOMEM */
|
break; /* give up with -ENOMEM */
|
||||||
rmb_desc->cpu_addr = kzalloc(bufsize,
|
rmb_desc->cpu_addr =
|
||||||
GFP_KERNEL | __GFP_NOWARN |
|
(void *)__get_free_pages(GFP_KERNEL | __GFP_NOWARN |
|
||||||
__GFP_NOMEMALLOC |
|
__GFP_NOMEMALLOC |
|
||||||
__GFP_NORETRY);
|
__GFP_NORETRY | __GFP_ZERO,
|
||||||
|
get_order(bufsize));
|
||||||
if (!rmb_desc->cpu_addr) {
|
if (!rmb_desc->cpu_addr) {
|
||||||
kfree(rmb_desc);
|
kfree(rmb_desc);
|
||||||
rmb_desc = NULL;
|
rmb_desc = NULL;
|
||||||
/* if RMB allocation has failed,
|
|
||||||
* try a smaller one
|
|
||||||
*/
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
rc = smc_ib_buf_map(lgr->lnk[SMC_SINGLE_LINK].smcibdev,
|
rmb_desc->order = get_order(bufsize);
|
||||||
bufsize, rmb_desc, DMA_FROM_DEVICE);
|
|
||||||
|
rc = sg_alloc_table(&rmb_desc->sgt[SMC_SINGLE_LINK], 1,
|
||||||
|
GFP_KERNEL);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
kfree(rmb_desc->cpu_addr);
|
free_pages((unsigned long)rmb_desc->cpu_addr,
|
||||||
|
rmb_desc->order);
|
||||||
|
kfree(rmb_desc);
|
||||||
|
rmb_desc = NULL;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
sg_set_buf(rmb_desc->sgt[SMC_SINGLE_LINK].sgl,
|
||||||
|
rmb_desc->cpu_addr, bufsize);
|
||||||
|
|
||||||
|
rc = smc_ib_buf_map_sg(lgr->lnk[SMC_SINGLE_LINK].smcibdev,
|
||||||
|
rmb_desc, DMA_FROM_DEVICE);
|
||||||
|
if (rc != 1) {
|
||||||
|
sg_free_table(&rmb_desc->sgt[SMC_SINGLE_LINK]);
|
||||||
|
free_pages((unsigned long)rmb_desc->cpu_addr,
|
||||||
|
rmb_desc->order);
|
||||||
kfree(rmb_desc);
|
kfree(rmb_desc);
|
||||||
rmb_desc = NULL;
|
rmb_desc = NULL;
|
||||||
continue; /* if mapping failed, try smaller one */
|
continue; /* if mapping failed, try smaller one */
|
||||||
}
|
}
|
||||||
rmb_desc->rkey[SMC_SINGLE_LINK] =
|
|
||||||
lgr->lnk[SMC_SINGLE_LINK].roce_pd->unsafe_global_rkey;
|
|
||||||
rmb_desc->used = 1;
|
rmb_desc->used = 1;
|
||||||
write_lock_bh(&lgr->rmbs_lock);
|
write_lock_bh(&lgr->rmbs_lock);
|
||||||
list_add(&rmb_desc->list, &lgr->rmbs[bufsize_short]);
|
list_add(&rmb_desc->list, &lgr->rmbs[bufsize_short]);
|
||||||
|
@ -93,10 +93,8 @@ struct smc_buf_desc {
|
|||||||
u64 dma_addr[SMC_LINKS_PER_LGR_MAX];
|
u64 dma_addr[SMC_LINKS_PER_LGR_MAX];
|
||||||
/* mapped address of buffer */
|
/* mapped address of buffer */
|
||||||
void *cpu_addr; /* virtual address of buffer */
|
void *cpu_addr; /* virtual address of buffer */
|
||||||
u32 rkey[SMC_LINKS_PER_LGR_MAX];
|
struct sg_table sgt[SMC_LINKS_PER_LGR_MAX];/* virtual buffer */
|
||||||
/* for rmb only:
|
u32 order; /* allocation order */
|
||||||
* rkey provided to peer
|
|
||||||
*/
|
|
||||||
u32 used; /* currently used / unused */
|
u32 used; /* currently used / unused */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -283,6 +283,37 @@ void smc_ib_buf_unmap(struct smc_ib_device *smcibdev, int buf_size,
|
|||||||
buf_slot->dma_addr[SMC_SINGLE_LINK] = 0;
|
buf_slot->dma_addr[SMC_SINGLE_LINK] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Map a new TX or RX buffer SG-table to DMA */
|
||||||
|
int smc_ib_buf_map_sg(struct smc_ib_device *smcibdev,
|
||||||
|
struct smc_buf_desc *buf_slot,
|
||||||
|
enum dma_data_direction data_direction)
|
||||||
|
{
|
||||||
|
int mapped_nents;
|
||||||
|
|
||||||
|
mapped_nents = ib_dma_map_sg(smcibdev->ibdev,
|
||||||
|
buf_slot->sgt[SMC_SINGLE_LINK].sgl,
|
||||||
|
buf_slot->sgt[SMC_SINGLE_LINK].orig_nents,
|
||||||
|
data_direction);
|
||||||
|
if (!mapped_nents)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
return mapped_nents;
|
||||||
|
}
|
||||||
|
|
||||||
|
void smc_ib_buf_unmap_sg(struct smc_ib_device *smcibdev,
|
||||||
|
struct smc_buf_desc *buf_slot,
|
||||||
|
enum dma_data_direction data_direction)
|
||||||
|
{
|
||||||
|
if (!buf_slot->sgt[SMC_SINGLE_LINK].sgl->dma_address)
|
||||||
|
return; /* already unmapped */
|
||||||
|
|
||||||
|
ib_dma_unmap_sg(smcibdev->ibdev,
|
||||||
|
buf_slot->sgt[SMC_SINGLE_LINK].sgl,
|
||||||
|
buf_slot->sgt[SMC_SINGLE_LINK].orig_nents,
|
||||||
|
data_direction);
|
||||||
|
buf_slot->sgt[SMC_SINGLE_LINK].sgl->dma_address = 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int smc_ib_fill_gid_and_mac(struct smc_ib_device *smcibdev, u8 ibport)
|
static int smc_ib_fill_gid_and_mac(struct smc_ib_device *smcibdev, u8 ibport)
|
||||||
{
|
{
|
||||||
struct net_device *ndev;
|
struct net_device *ndev;
|
||||||
|
@ -57,6 +57,12 @@ int smc_ib_buf_map(struct smc_ib_device *smcibdev, int buf_size,
|
|||||||
void smc_ib_buf_unmap(struct smc_ib_device *smcibdev, int bufsize,
|
void smc_ib_buf_unmap(struct smc_ib_device *smcibdev, int bufsize,
|
||||||
struct smc_buf_desc *buf_slot,
|
struct smc_buf_desc *buf_slot,
|
||||||
enum dma_data_direction data_direction);
|
enum dma_data_direction data_direction);
|
||||||
|
int smc_ib_buf_map_sg(struct smc_ib_device *smcibdev,
|
||||||
|
struct smc_buf_desc *buf_slot,
|
||||||
|
enum dma_data_direction data_direction);
|
||||||
|
void smc_ib_buf_unmap_sg(struct smc_ib_device *smcibdev,
|
||||||
|
struct smc_buf_desc *buf_slot,
|
||||||
|
enum dma_data_direction data_direction);
|
||||||
void smc_ib_dealloc_protection_domain(struct smc_link *lnk);
|
void smc_ib_dealloc_protection_domain(struct smc_link *lnk);
|
||||||
int smc_ib_create_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);
|
void smc_ib_destroy_queue_pair(struct smc_link *lnk);
|
||||||
|
Loading…
Reference in New Issue
Block a user