Пример #1
0
static ssize_t tool_link_event_write(struct file *filep,
				     const char __user *ubuf,
				     size_t size, loff_t *offp)
{
	struct tool_ctx *tc = filep->private_data;
	char buf[32];
	size_t buf_size;
	bool val;
	int rc;

	buf_size = min(size, (sizeof(buf) - 1));
	if (copy_from_user(buf, ubuf, buf_size))
		return -EFAULT;

	buf[buf_size] = '\0';

	rc = strtobool(buf, &val);
	if (rc)
		return rc;

	if (wait_event_interruptible(tc->link_wq,
		ntb_link_is_up(tc->ntb, NULL, NULL) == val))
		return -ERESTART;

	return size;
}
Пример #2
0
static void perf_link_event(void *ctx)
{
	struct perf_ctx *perf = ctx;

	if (ntb_link_is_up(perf->ntb, NULL, NULL) == 1)
		schedule_delayed_work(&perf->link_work, 2*HZ);
	else
		schedule_work(&perf->link_cleanup);
}
Пример #3
0
static void perf_link_work(struct work_struct *work)
{
	struct perf_ctx *perf =
		container_of(work, struct perf_ctx, link_work.work);
	struct ntb_dev *ndev = perf->ntb;
	struct pci_dev *pdev = ndev->pdev;
	u32 val;
	u64 size;
	int rc;

	dev_dbg(&perf->ntb->pdev->dev, "%s called\n", __func__);

	size = perf->mw.phys_size;

	if (max_mw_size && size > max_mw_size)
		size = max_mw_size;

	ntb_peer_spad_write(ndev, MW_SZ_HIGH, upper_32_bits(size));
	ntb_peer_spad_write(ndev, MW_SZ_LOW, lower_32_bits(size));
	ntb_peer_spad_write(ndev, VERSION, PERF_VERSION);

	/* now read what peer wrote */
	val = ntb_spad_read(ndev, VERSION);
	if (val != PERF_VERSION) {
		dev_dbg(&pdev->dev, "Remote version = %#x\n", val);
		goto out;
	}

	val = ntb_spad_read(ndev, MW_SZ_HIGH);
	size = (u64)val << 32;

	val = ntb_spad_read(ndev, MW_SZ_LOW);
	size |= val;

	dev_dbg(&pdev->dev, "Remote MW size = %#llx\n", size);

	rc = perf_set_mw(perf, size);
	if (rc)
		goto out1;

	perf->link_is_up = true;
	wake_up(&perf->link_wq);

	return;

out1:
	perf_free_mw(perf);

out:
	if (ntb_link_is_up(ndev, NULL, NULL) == 1)
		schedule_delayed_work(&perf->link_work,
				      msecs_to_jiffies(PERF_LINK_DOWN_TIMEOUT));
}
Пример #4
0
static ssize_t tool_link_read(struct file *filep, char __user *ubuf,
			      size_t size, loff_t *offp)
{
	struct tool_ctx *tc = filep->private_data;
	char buf[3];

	buf[0] = ntb_link_is_up(tc->ntb, NULL, NULL) ? 'Y' : 'N';
	buf[1] = '\n';
	buf[2] = '\0';

	return simple_read_from_buffer(ubuf, size, offp, buf, 2);
}
Пример #5
0
/* Link Event handler */
static void
ntb_transport_event_callback(void *data)
{
	struct ntb_transport_ctx *nt = data;

	if (ntb_link_is_up(nt->ntb, NULL, NULL)) {
		ntb_printf(1, "HW link up\n");
		callout_reset(&nt->link_work, 0, ntb_transport_link_work, nt);
	} else {
		ntb_printf(1, "HW link down\n");
		taskqueue_enqueue(taskqueue_swi, &nt->link_cleanup);
	}
}
Пример #6
0
static void tool_link_event(void *ctx)
{
	struct tool_ctx *tc = ctx;
	enum ntb_speed speed;
	enum ntb_width width;
	int up;

	up = ntb_link_is_up(tc->ntb, &speed, &width);

	dev_dbg(&tc->ntb->dev, "link is %s speed %d width %d\n",
		up ? "up" : "down", speed, width);

	wake_up(&tc->link_wq);
}
Пример #7
0
static void perf_link_event(void *ctx)
{
	struct perf_ctx *perf = ctx;

	if (ntb_link_is_up(perf->ntb, NULL, NULL) == 1) {
		schedule_delayed_work(&perf->link_work, 2*HZ);
	} else {
		dev_dbg(&perf->ntb->pdev->dev, "link down\n");

		if (!perf->link_is_up)
			cancel_delayed_work_sync(&perf->link_work);

		perf->link_is_up = false;
	}
}
Пример #8
0
static int pp_find_next_peer(struct pp_ctx *pp)
{
	u64 link, out_db;
	int pidx;

	link = ntb_link_is_up(pp->ntb, NULL, NULL);

	/* Find next available peer */
	if (link & pp->nmask)
		pidx = __ffs64(link & pp->nmask);
	else if (link & pp->pmask)
		pidx = __ffs64(link & pp->pmask);
	else
		return -ENODEV;

	out_db = BIT_ULL(ntb_peer_port_number(pp->ntb, pidx));

	spin_lock(&pp->lock);
	pp->out_pidx = pidx;
	pp->out_db = out_db;
	spin_unlock(&pp->lock);

	return 0;
}
Пример #9
0
/* Link bring up */
static void
ntb_transport_link_work(void *arg)
{
	struct ntb_transport_ctx *nt = arg;
	struct ntb_softc *ntb = nt->ntb;
	struct ntb_transport_qp *qp;
	uint64_t val64, size;
	uint32_t val;
	unsigned i;
	int rc;

	/* send the local info, in the opposite order of the way we read it */
	for (i = 0; i < nt->mw_count; i++) {
		size = nt->mw_vec[i].phys_size;

		if (max_mw_size != 0 && size > max_mw_size)
			size = max_mw_size;

		ntb_peer_spad_write(ntb, IF_NTB_MW0_SZ_HIGH + (i * 2),
		    size >> 32);
		ntb_peer_spad_write(ntb, IF_NTB_MW0_SZ_LOW + (i * 2), size);
	}

	ntb_peer_spad_write(ntb, IF_NTB_NUM_MWS, nt->mw_count);

	ntb_peer_spad_write(ntb, IF_NTB_NUM_QPS, nt->qp_count);

	ntb_peer_spad_write(ntb, IF_NTB_VERSION, NTB_TRANSPORT_VERSION);

	/* Query the remote side for its info */
	val = 0;
	ntb_spad_read(ntb, IF_NTB_VERSION, &val);
	if (val != NTB_TRANSPORT_VERSION)
		goto out;

	ntb_spad_read(ntb, IF_NTB_NUM_QPS, &val);
	if (val != nt->qp_count)
		goto out;

	ntb_spad_read(ntb, IF_NTB_NUM_MWS, &val);
	if (val != nt->mw_count)
		goto out;

	for (i = 0; i < nt->mw_count; i++) {
		ntb_spad_read(ntb, IF_NTB_MW0_SZ_HIGH + (i * 2), &val);
		val64 = (uint64_t)val << 32;

		ntb_spad_read(ntb, IF_NTB_MW0_SZ_LOW + (i * 2), &val);
		val64 |= val;

		rc = ntb_set_mw(nt, i, val64);
		if (rc != 0)
			goto free_mws;
	}

	nt->link_is_up = true;
	ntb_printf(1, "transport link up\n");

	for (i = 0; i < nt->qp_count; i++) {
		qp = &nt->qp_vec[i];

		ntb_transport_setup_qp_mw(nt, i);

		if (qp->client_ready)
			callout_reset(&qp->link_work, 0, ntb_qp_link_work, qp);
	}

	return;

free_mws:
	for (i = 0; i < nt->mw_count; i++)
		ntb_free_mw(nt, i);
out:
	if (ntb_link_is_up(ntb, NULL, NULL))
		callout_reset(&nt->link_work,
		    NTB_LINK_DOWN_TIMEOUT * hz / 1000, ntb_transport_link_work, nt);
}