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; }
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; }
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; }