Example #1
0
static int connect_rings(struct backend_info *be)
{
	struct xenvif *vif = be->vif;
	struct xenbus_device *dev = be->dev;
	unsigned long tx_ring_ref, rx_ring_ref;
	unsigned int evtchn, rx_copy;
	int err;
	int val;

	err = xenbus_gather(XBT_NIL, dev->otherend,
			    "tx-ring-ref", "%lu", &tx_ring_ref,
			    "rx-ring-ref", "%lu", &rx_ring_ref,
			    "event-channel", "%u", &evtchn, NULL);
	if (err) {
		xenbus_dev_fatal(dev, err,
				 "reading %s/ring-ref and event-channel",
				 dev->otherend);
		return err;
	}

	err = xenbus_scanf(XBT_NIL, dev->otherend, "request-rx-copy", "%u",
			   &rx_copy);
	if (err == -ENOENT) {
		err = 0;
		rx_copy = 0;
	}
	if (err < 0) {
		xenbus_dev_fatal(dev, err, "reading %s/request-rx-copy",
				 dev->otherend);
		return err;
	}
	if (!rx_copy)
		return -EOPNOTSUPP;

	if (vif->dev->tx_queue_len != 0) {
		if (xenbus_scanf(XBT_NIL, dev->otherend,
				 "feature-rx-notify", "%d", &val) < 0)
			val = 0;
		if (val)
			vif->can_queue = 1;
		else
			/* Must be non-zero for pfifo_fast to work. */
			vif->dev->tx_queue_len = 1;
	}

	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-sg",
			 "%d", &val) < 0)
		val = 0;
	vif->can_sg = !!val;

	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-gso-tcpv4",
			 "%d", &val) < 0)
		val = 0;
	vif->gso = !!val;

	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-gso-tcpv4-prefix",
			 "%d", &val) < 0)
		val = 0;
	vif->gso_prefix = !!val;

	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-no-csum-offload",
			 "%d", &val) < 0)
		val = 0;
	vif->csum = !val;

	/* Map the shared frame, irq etc. */
	err = xenvif_connect(vif, tx_ring_ref, rx_ring_ref, evtchn);
	if (err) {
		xenbus_dev_fatal(dev, err,
				 "mapping shared-frames %lu/%lu port %u",
				 tx_ring_ref, rx_ring_ref, evtchn);
		return err;
	}
	return 0;
}
static int connect_rings(struct backend_info *be)
{
	struct xenvif *vif = be->vif;
	struct xenbus_device *dev = be->dev;
	unsigned long tx_ring_ref, rx_ring_ref;
	unsigned int tx_evtchn, rx_evtchn, rx_copy;
	int err;
	int val;

	err = xenbus_gather(XBT_NIL, dev->otherend,
			    "tx-ring-ref", "%lu", &tx_ring_ref,
			    "rx-ring-ref", "%lu", &rx_ring_ref, NULL);
	if (err) {
		xenbus_dev_fatal(dev, err,
				 "reading %s/ring-ref",
				 dev->otherend);
		return err;
	}

	/* Try split event channels first, then single event channel. */
	err = xenbus_gather(XBT_NIL, dev->otherend,
			    "event-channel-tx", "%u", &tx_evtchn,
			    "event-channel-rx", "%u", &rx_evtchn, NULL);
	if (err < 0) {
		err = xenbus_scanf(XBT_NIL, dev->otherend,
				   "event-channel", "%u", &tx_evtchn);
		if (err < 0) {
			xenbus_dev_fatal(dev, err,
					 "reading %s/event-channel(-tx/rx)",
					 dev->otherend);
			return err;
		}
		rx_evtchn = tx_evtchn;
	}

	err = xenbus_scanf(XBT_NIL, dev->otherend, "request-rx-copy", "%u",
			   &rx_copy);
	if (err == -ENOENT) {
		err = 0;
		rx_copy = 0;
	}
	if (err < 0) {
		xenbus_dev_fatal(dev, err, "reading %s/request-rx-copy",
				 dev->otherend);
		return err;
	}
	if (!rx_copy)
		return -EOPNOTSUPP;

	if (vif->dev->tx_queue_len != 0) {
		if (xenbus_scanf(XBT_NIL, dev->otherend,
				 "feature-rx-notify", "%d", &val) < 0)
			val = 0;
		if (val)
			vif->can_queue = 1;
		else
			/* Must be non-zero for pfifo_fast to work. */
			vif->dev->tx_queue_len = 1;
	}

	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-sg",
			 "%d", &val) < 0)
		val = 0;
	vif->can_sg = !!val;

	vif->gso_mask = 0;
	vif->gso_prefix_mask = 0;

	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-gso-tcpv4",
			 "%d", &val) < 0)
		val = 0;
	if (val)
		vif->gso_mask |= GSO_BIT(TCPV4);

	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-gso-tcpv4-prefix",
			 "%d", &val) < 0)
		val = 0;
	if (val)
		vif->gso_prefix_mask |= GSO_BIT(TCPV4);

	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-gso-tcpv6",
			 "%d", &val) < 0)
		val = 0;
	if (val)
		vif->gso_mask |= GSO_BIT(TCPV6);

	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-gso-tcpv6-prefix",
			 "%d", &val) < 0)
		val = 0;
	if (val)
		vif->gso_prefix_mask |= GSO_BIT(TCPV6);

	if (vif->gso_mask & vif->gso_prefix_mask) {
		xenbus_dev_fatal(dev, err,
				 "%s: gso and gso prefix flags are not "
				 "mutually exclusive",
				 dev->otherend);
		return -EOPNOTSUPP;
	}

	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-no-csum-offload",
			 "%d", &val) < 0)
		val = 0;
	vif->ip_csum = !val;

	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-ipv6-csum-offload",
			 "%d", &val) < 0)
		val = 0;
	vif->ipv6_csum = !!val;

	/* Map the shared frame, irq etc. */
	err = xenvif_connect(vif, tx_ring_ref, rx_ring_ref,
			     tx_evtchn, rx_evtchn);
	if (err) {
		xenbus_dev_fatal(dev, err,
				 "mapping shared-frames %lu/%lu port tx %u rx %u",
				 tx_ring_ref, rx_ring_ref,
				 tx_evtchn, rx_evtchn);
		return err;
	}
	return 0;
}
Example #3
0
static int connect_rings(struct backend_info *be, struct xenvif_queue *queue)
{
	struct xenbus_device *dev = be->dev;
	unsigned int num_queues = queue->vif->num_queues;
	unsigned long tx_ring_ref, rx_ring_ref;
	unsigned int tx_evtchn, rx_evtchn;
	int err;
	char *xspath;
	size_t xspathsize;
	const size_t xenstore_path_ext_size = 11; /* sufficient for "/queue-NNN" */

	/* If the frontend requested 1 queue, or we have fallen back
	 * to single queue due to lack of frontend support for multi-
	 * queue, expect the remaining XenStore keys in the toplevel
	 * directory. Otherwise, expect them in a subdirectory called
	 * queue-N.
	 */
	if (num_queues == 1) {
		xspath = kzalloc(strlen(dev->otherend) + 1, GFP_KERNEL);
		if (!xspath) {
			xenbus_dev_fatal(dev, -ENOMEM,
					 "reading ring references");
			return -ENOMEM;
		}
		strcpy(xspath, dev->otherend);
	} else {
		xspathsize = strlen(dev->otherend) + xenstore_path_ext_size;
		xspath = kzalloc(xspathsize, GFP_KERNEL);
		if (!xspath) {
			xenbus_dev_fatal(dev, -ENOMEM,
					 "reading ring references");
			return -ENOMEM;
		}
		snprintf(xspath, xspathsize, "%s/queue-%u", dev->otherend,
			 queue->id);
	}

	err = xenbus_gather(XBT_NIL, xspath,
			    "tx-ring-ref", "%lu", &tx_ring_ref,
			    "rx-ring-ref", "%lu", &rx_ring_ref, NULL);
	if (err) {
		xenbus_dev_fatal(dev, err,
				 "reading %s/ring-ref",
				 xspath);
		goto err;
	}

	/* Try split event channels first, then single event channel. */
	err = xenbus_gather(XBT_NIL, xspath,
			    "event-channel-tx", "%u", &tx_evtchn,
			    "event-channel-rx", "%u", &rx_evtchn, NULL);
	if (err < 0) {
		err = xenbus_scanf(XBT_NIL, xspath,
				   "event-channel", "%u", &tx_evtchn);
		if (err < 0) {
			xenbus_dev_fatal(dev, err,
					 "reading %s/event-channel(-tx/rx)",
					 xspath);
			goto err;
		}
		rx_evtchn = tx_evtchn;
	}

	/* Map the shared frame, irq etc. */
	err = xenvif_connect(queue, tx_ring_ref, rx_ring_ref,
			     tx_evtchn, rx_evtchn);
	if (err) {
		xenbus_dev_fatal(dev, err,
				 "mapping shared-frames %lu/%lu port tx %u rx %u",
				 tx_ring_ref, rx_ring_ref,
				 tx_evtchn, rx_evtchn);
		goto err;
	}

	err = 0;
err: /* Regular return falls through with err == 0 */
	kfree(xspath);
	return err;
}
Example #4
0
static int connect_rings(struct backend_info *be)
{
	struct xenvif *vif = be->vif;
	struct xenbus_device *dev = be->dev;
	grant_ref_t tx_ring_refs[MAX_PAGES_PER_RING], rx_ring_refs[MAX_PAGES_PER_RING];
	unsigned int evtchn, rx_copy, nr_ring_pages;
	unsigned multipage;
	int i;
	int err;
	int val;
	char pathbuf[64];

	err = xenbus_scanf(XBT_NIL, dev->otherend, "nr-ring-pages", "%u",
			   &nr_ring_pages);
	if (err == -ENOENT) {
		err = 0;
		nr_ring_pages = 1;
		multipage = 0;
	} else {
		multipage = 1;
	}
	if (err < 0) {
		xenbus_dev_fatal(dev, err, "reading %s/nr-ring-pages",
				 dev->otherend);
		return err;
	}
	if (nr_ring_pages < 1 ||
	    nr_ring_pages > MAX_PAGES_PER_RING ||
	    (!xen_pv_domain() && nr_ring_pages > 1) ||
	    (nr_ring_pages & (nr_ring_pages - 1))) {
		xenbus_dev_fatal(dev,
				 err,
				 "error in %s/nr-ring-pages: should be a power of two between 1 and %d, was %u",
				 dev->otherend,
				 xen_pv_domain() ? MAX_PAGES_PER_RING : 1, nr_ring_pages);
		return -EINVAL;
	}
	vif->nr_ring_pages = nr_ring_pages;

	err = xenbus_scanf(XBT_NIL, dev->otherend, "event-channel", "%u", &evtchn);
	if (err < 0) {
		xenbus_dev_fatal(dev, err, "reading %s/event-channel", dev->otherend);
		return err;
	}

	if (multipage) {
		for (i = 0; i < nr_ring_pages; i++) {
			sprintf(pathbuf, "tx-ring-ref-%d", i);
			err = xenbus_scanf(XBT_NIL, dev->otherend, pathbuf, "%u", &tx_ring_refs[i]);
			if (err < 0) {
				xenbus_dev_fatal(dev, err, "reading %s/%s", dev->otherend, pathbuf);
				return err;
			}
			sprintf(pathbuf, "rx-ring-ref-%d", i);
			err = xenbus_scanf(XBT_NIL, dev->otherend, pathbuf, "%u", &rx_ring_refs[i]);
			if (err < 0) {
				xenbus_dev_fatal(dev, err, "reading %s/%s", dev->otherend, pathbuf);
				return err;
			}
		}
	} else {
		err = xenbus_gather(XBT_NIL, dev->otherend,
				    "tx-ring-ref", "%lu", &tx_ring_refs[0],
				    "rx-ring-ref", "%lu", &rx_ring_refs[0],
				    NULL);
		if (err) {
			xenbus_dev_fatal(dev, err,
					 "reading %s/ring-refs",
					 dev->otherend);
			return err;
		}
	}

	err = xenbus_scanf(XBT_NIL, dev->otherend, "request-rx-copy", "%u",
			   &rx_copy);
	if (err == -ENOENT) {
		err = 0;
		rx_copy = 0;
	}
	if (err < 0) {
		xenbus_dev_fatal(dev, err, "reading %s/request-rx-copy",
				 dev->otherend);
		return err;
	}
	if (!rx_copy)
		return -EOPNOTSUPP;

	if (vif->dev->tx_queue_len != 0) {
		if (xenbus_scanf(XBT_NIL, dev->otherend,
				 "feature-rx-notify", "%d", &val) < 0)
			val = 0;
		if (val)
			vif->can_queue = 1;
		else
			/* Must be non-zero for pfifo_fast to work. */
			vif->dev->tx_queue_len = 1;
	}

	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-sg",
			 "%d", &val) < 0)
		val = 0;
	vif->can_sg = !!val;

	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-gso-tcpv4",
			 "%d", &val) < 0)
		val = 0;
	vif->gso = !!val;

	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-gso-tcpv4-prefix",
			 "%d", &val) < 0)
		val = 0;
	vif->gso_prefix = !!val;

	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-no-csum-offload",
			 "%d", &val) < 0)
		val = 0;
	vif->csum = !val;

	/* Map the shared frame, irq etc. */
	err = xenvif_connect(vif, tx_ring_refs, rx_ring_refs, evtchn, nr_ring_pages);
	if (err) {
		xenbus_dev_fatal(dev, err,
				 "mapping shared-frames %u/%u port %u",
				 tx_ring_refs[0], rx_ring_refs[0], evtchn);
		return err;
	}
	return 0;
}