Commit 8a1a8450 authored by paul luse's avatar paul luse Committed by Tomasz Zawadzki
Browse files

idxd: simplification in re-balancing channels



For flow control reasons we have to resize the bit arrays we
use to manage flow as channels come and go.  However since
channels are assigned to devices, until the channel count
reaches the device count there's no sharing so no resize of
the array is needed. So, when we use a device for the first
time there's no need to run through the rest of the channels
and re-balance.

Same thing is done on destruction. The code to free idxd
specific resources was moved from the rebalance function to
the idxd put channel function which is a much more logical
place for it as well.

Signed-off-by: default avatarpaul luse <paul.e.luse@intel.com>
Change-Id: Ib4df163286906f413dd6429dc6833af7b68e208c
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/5846


Community-CI: Broadcom CI
Community-CI: Mellanox Build Bot
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
parent 15c0e780
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -10,6 +10,21 @@ suitable polling group.

## v21.01:

### idxd

A new API `spdk_idxd_get_rebalance` was added so that users of the library
can know whether they need to rebalance the flow control for the channel
that was just added/removed.  This is based on how the low level library
shares devices amongst channels.

The API `spdk_idxd_reconfigure_chan` had the `num_channels` removed as this
is now tracked in the library.  The app makes use the new API above to
determine whether to rebalance or not. This applies to `spdk_idxd_configure_chan`
as well.

The API `spdk_idxd_put_channel` now returns the rebalance state for the
underlying device.

### bdev

An `opts_size` element was added in the `spdk_bdev_opts` structure to solve the
+12 −4
Original line number Diff line number Diff line
@@ -64,7 +64,7 @@ struct idxd_batch;
/**
 * Signature for configuring a channel
 *
 * \param chan IDXD channel to be configured.
 * \param chan IDXD channel to be configured
 * \return 0 on success, negative errno on failure.
 */
int spdk_idxd_configure_chan(struct spdk_idxd_io_channel *chan);
@@ -73,10 +73,9 @@ int spdk_idxd_configure_chan(struct spdk_idxd_io_channel *chan);
 * Reconfigures this channel based on how many current channels there are.
 *
 * \param chan IDXD channel to be set.
 * \param num_channels total number of channels in use.
 * \return 0 on success, negative errno on failure.
 */
int spdk_idxd_reconfigure_chan(struct spdk_idxd_io_channel *chan, uint32_t num_channels);
int spdk_idxd_reconfigure_chan(struct spdk_idxd_io_channel *chan);

/**
 * Signature for callback function invoked when a request is completed.
@@ -408,8 +407,17 @@ struct spdk_idxd_io_channel *spdk_idxd_get_channel(struct spdk_idxd_device *idxd
 * Free an IDXD channel.
 *
 * \param chan IDXD channel to free.
 * \return true if the underlying device needs a rebalance
 */
void spdk_idxd_put_channel(struct spdk_idxd_io_channel *chan);
bool spdk_idxd_put_channel(struct spdk_idxd_io_channel *chan);

/**
 * Determine if the idxd device needs rebalancing.
 *
 * \param idxd IDXD device.
 * \return true if rebalance is needed, false if not.
 */
bool spdk_idxd_device_needs_rebalance(struct spdk_idxd_device *idxd);

#ifdef __cplusplus
}
+1 −1
Original line number Diff line number Diff line
@@ -34,7 +34,7 @@
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../..)
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk

SO_VER := 3
SO_VER := 4
SO_MINOR := 0

C_SRCS = idxd.c
+52 −16
Original line number Diff line number Diff line
@@ -100,6 +100,12 @@ _idxd_write_8(struct spdk_idxd_device *idxd, uint32_t offset, uint64_t value)
	spdk_mmio_write_8((uint64_t *)(idxd->reg_base + offset), value);
}

bool
spdk_idxd_device_needs_rebalance(struct spdk_idxd_device *idxd)
{
	return idxd->needs_rebalance;
}

struct spdk_idxd_io_channel *
spdk_idxd_get_channel(struct spdk_idxd_device *idxd)
{
@@ -130,13 +136,44 @@ spdk_idxd_get_channel(struct spdk_idxd_device *idxd)
		batch++;
	}

	pthread_mutex_lock(&chan->idxd->num_channels_lock);
	chan->idxd->num_channels++;
	if (chan->idxd->num_channels > 1) {
		chan->idxd->needs_rebalance = true;
	} else {
		chan->idxd->needs_rebalance = false;
	}
	pthread_mutex_unlock(&chan->idxd->num_channels_lock);

	return chan;
}

void
bool
spdk_idxd_put_channel(struct spdk_idxd_io_channel *chan)
{
	struct idxd_batch *batch;
	bool rebalance = false;

	pthread_mutex_lock(&chan->idxd->num_channels_lock);
	assert(chan->idxd->num_channels > 0);
	chan->idxd->num_channels--;
	if (chan->idxd->num_channels > 0) {
		rebalance = true;
	}
	pthread_mutex_unlock(&chan->idxd->num_channels_lock);

	spdk_free(chan->completions);
	spdk_free(chan->desc);
	spdk_bit_array_free(&chan->ring_slots);
	while ((batch = TAILQ_FIRST(&chan->batch_pool))) {
		TAILQ_REMOVE(&chan->batch_pool, batch, link);
		spdk_free(batch->user_completions);
		spdk_free(batch->user_desc);
	}
	free(chan->batch_base);
	free(chan);

	return rebalance;
}

int
@@ -151,7 +188,9 @@ spdk_idxd_configure_chan(struct spdk_idxd_io_channel *chan)
		chan->idxd->wq_id = 0;
	}

	num_ring_slots = chan->idxd->queues[chan->idxd->wq_id].wqcfg.wq_size;
	pthread_mutex_lock(&chan->idxd->num_channels_lock);
	num_ring_slots = chan->idxd->queues[chan->idxd->wq_id].wqcfg.wq_size / chan->idxd->num_channels;
	pthread_mutex_unlock(&chan->idxd->num_channels_lock);

	chan->ring_slots = spdk_bit_array_create(num_ring_slots);
	if (chan->ring_slots == NULL) {
@@ -272,30 +311,26 @@ _idxd_drain(struct spdk_idxd_io_channel *chan)
}

int
spdk_idxd_reconfigure_chan(struct spdk_idxd_io_channel *chan, uint32_t num_channels)
spdk_idxd_reconfigure_chan(struct spdk_idxd_io_channel *chan)
{
	uint32_t num_ring_slots;
	int rc;
	struct idxd_batch *batch;

	_idxd_drain(chan);

	assert(spdk_bit_array_count_set(chan->ring_slots) == 0);

	if (num_channels == 0) {
		spdk_free(chan->completions);
		spdk_free(chan->desc);
		spdk_bit_array_free(&chan->ring_slots);
		while ((batch = TAILQ_FIRST(&chan->batch_pool))) {
			TAILQ_REMOVE(&chan->batch_pool, batch, link);
			spdk_free(batch->user_completions);
			spdk_free(batch->user_desc);
		}
		free(chan->batch_base);
	pthread_mutex_lock(&chan->idxd->num_channels_lock);
	assert(chan->idxd->num_channels > 0);
	num_ring_slots = chan->ring_size / chan->idxd->num_channels;
	/* If no change (ie this was a call from another thread doing its for_each_channel,
	 * then we can just bail now.
	 */
	if (num_ring_slots == chan->max_ring_slots) {
		pthread_mutex_unlock(&chan->idxd->num_channels_lock);
		return 0;
	}

	num_ring_slots = chan->ring_size / num_channels;
	pthread_mutex_unlock(&chan->idxd->num_channels_lock);

	/* re-allocate our descriptor ring for hw flow control. */
	rc = spdk_bit_array_resize(&chan->ring_slots, num_ring_slots);
@@ -637,6 +672,7 @@ idxd_attach(struct spdk_pci_device *device)
	}

	idxd->device = device;
	pthread_mutex_init(&idxd->num_channels_lock, NULL);

	/* Enable PCI busmaster. */
	spdk_pci_device_cfg_read32(device, &cmd_reg, 4);
+3 −0
Original line number Diff line number Diff line
@@ -186,6 +186,9 @@ struct spdk_idxd_device {
	void				*portals;
	int				socket_id;
	int				wq_id;
	uint32_t			num_channels;
	bool				needs_rebalance;
	pthread_mutex_t			num_channels_lock;

	struct idxd_registers		registers;
	uint32_t			ims_offset;
Loading