Commit 67161779 authored by Stefan Raspl's avatar Stefan Raspl Committed by David S. Miller
Browse files

net/smc: Allow SMC-D 1MB DMB allocations



Commit a3fe3d01 ("net/smc: introduce sg-logic for RMBs") introduced
a restriction for RMB allocations as used by SMC-R. However, SMC-D does
not use scatter-gather lists to back its DMBs, yet it was limited by
this restriction, still.
This patch exempts SMC, but limits allocations to the maximum RMB/DMB
size respectively.

Signed-off-by: default avatarStefan Raspl <raspl@linux.ibm.com>
Signed-off-by: default avatarGuvenc Gulce <guvenc@linux.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 919d13a7
Loading
Loading
Loading
Loading
+16 −15
Original line number Diff line number Diff line
@@ -1752,21 +1752,30 @@ int smc_conn_create(struct smc_sock *smc, struct smc_init_info *ini)
	return rc;
}

/* convert the RMB size into the compressed notation - minimum 16K.
#define SMCD_DMBE_SIZES		6 /* 0 -> 16KB, 1 -> 32KB, .. 6 -> 1MB */
#define SMCR_RMBE_SIZES		5 /* 0 -> 16KB, 1 -> 32KB, .. 5 -> 512KB */

/* convert the RMB size into the compressed notation (minimum 16K, see
 * SMCD/R_DMBE_SIZES.
 * In contrast to plain ilog2, this rounds towards the next power of 2,
 * so the socket application gets at least its desired sndbuf / rcvbuf size.
 */
static u8 smc_compress_bufsize(int size)
static u8 smc_compress_bufsize(int size, bool is_smcd, bool is_rmb)
{
	const unsigned int max_scat = SG_MAX_SINGLE_ALLOC * PAGE_SIZE;
	u8 compressed;

	if (size <= SMC_BUF_MIN_SIZE)
		return 0;

	size = (size - 1) >> 14;
	compressed = ilog2(size) + 1;
	if (compressed >= SMC_RMBE_SIZES)
		compressed = SMC_RMBE_SIZES - 1;
	size = (size - 1) >> 14;  /* convert to 16K multiple */
	compressed = min_t(u8, ilog2(size) + 1,
			   is_smcd ? SMCD_DMBE_SIZES : SMCR_RMBE_SIZES);

	if (!is_smcd && is_rmb)
		/* RMBs are backed by & limited to max size of scatterlists */
		compressed = min_t(u8, compressed, ilog2(max_scat >> 14));

	return compressed;
}

@@ -1982,17 +1991,12 @@ static int smcr_buf_map_usable_links(struct smc_link_group *lgr,
	return rc;
}

#define SMCD_DMBE_SIZES		6 /* 0 -> 16KB, 1 -> 32KB, .. 6 -> 1MB */

static struct smc_buf_desc *smcd_new_buf_create(struct smc_link_group *lgr,
						bool is_dmb, int bufsize)
{
	struct smc_buf_desc *buf_desc;
	int rc;

	if (smc_compress_bufsize(bufsize) > SMCD_DMBE_SIZES)
		return ERR_PTR(-EAGAIN);

	/* try to alloc a new DMB */
	buf_desc = kzalloc(sizeof(*buf_desc), GFP_KERNEL);
	if (!buf_desc)
@@ -2041,9 +2045,8 @@ static int __smc_buf_create(struct smc_sock *smc, bool is_smcd, bool is_rmb)
		/* use socket send buffer size (w/o overhead) as start value */
		sk_buf_size = smc->sk.sk_sndbuf / 2;

	for (bufsize_short = smc_compress_bufsize(sk_buf_size);
	for (bufsize_short = smc_compress_bufsize(sk_buf_size, is_smcd, is_rmb);
	     bufsize_short >= 0; bufsize_short--) {

		if (is_rmb) {
			lock = &lgr->rmbs_lock;
			buf_list = &lgr->rmbs[bufsize_short];
@@ -2052,8 +2055,6 @@ static int __smc_buf_create(struct smc_sock *smc, bool is_smcd, bool is_rmb)
			buf_list = &lgr->sndbufs[bufsize_short];
		}
		bufsize = smc_uncompress_bufsize(bufsize_short);
		if ((1 << get_order(bufsize)) > SG_MAX_SINGLE_ALLOC)
			continue;

		/* check for reusable slot in the link group */
		buf_desc = smc_buf_get_slot(bufsize_short, lock, buf_list);