Exemple #1
0
static int setup_rings(struct xenbus_device *dev,
			   struct usbfront_info *info)
{
	usbif_urb_sring_t *urb_sring;
	usbif_conn_sring_t *conn_sring;
	int err;

	info->urb_ring_ref = GRANT_INVALID_REF;
	info->conn_ring_ref = GRANT_INVALID_REF;

	urb_sring = (usbif_urb_sring_t *)get_zeroed_page(GFP_NOIO|__GFP_HIGH);
	if (!urb_sring) {
		xenbus_dev_fatal(dev, -ENOMEM, "allocating urb ring");
		return -ENOMEM;
	}
	SHARED_RING_INIT(urb_sring);
	FRONT_RING_INIT(&info->urb_ring, urb_sring, PAGE_SIZE);

	err = xenbus_grant_ring(dev, virt_to_mfn(info->urb_ring.sring));
	if (err < 0) {
		free_page((unsigned long)urb_sring);
		info->urb_ring.sring = NULL;
		goto fail;
	}
	info->urb_ring_ref = err;

	conn_sring = (usbif_conn_sring_t *)get_zeroed_page(GFP_NOIO|__GFP_HIGH);
	if (!conn_sring) {
		xenbus_dev_fatal(dev, -ENOMEM, "allocating conn ring");
		return -ENOMEM;
	}
	SHARED_RING_INIT(conn_sring);
	FRONT_RING_INIT(&info->conn_ring, conn_sring, PAGE_SIZE);

	err = xenbus_grant_ring(dev, virt_to_mfn(info->conn_ring.sring));
	if (err < 0) {
		free_page((unsigned long)conn_sring);
		info->conn_ring.sring = NULL;
		goto fail;
	}
	info->conn_ring_ref = err;

	err = bind_listening_port_to_irqhandler(
		dev->otherend_id, xenhcd_int, SA_SAMPLE_RANDOM, "usbif", info);
	if (err <= 0) {
		xenbus_dev_fatal(dev, err,
				 "bind_listening_port_to_irqhandler");
		goto fail;
	}
	info->irq = err;

	return 0;
fail:
	destroy_rings(info);
	return err;
}
Exemple #2
0
static int svm_grant_ring(int arg)
{
	int ret, gnt_ref;
	struct xenbus_device dev;

	printk(KERN_ALERT "[svm]: arg is:%d\n", arg);
	dev.otherend_id = arg;

	if(NULL == vaddr){
		printk(KERN_ALERT "[svm]: wrong vaddr.\n");
		return -1;
	}

	gnt_ref = xenbus_grant_ring(&dev, virt_to_mfn(vaddr));
	if(gnt_ref < 0){
		printk(KERN_ALERT "[svm]: grant ring failed!\n");
		return -1;
	}
	
	xenbus_printf(XBT_NIL, "/vrv/svm/grant_table", "com", "pos:0 len:0");
	xenbus_printf(XBT_NIL, "/vrv/svm", "grant_table", "%d", gnt_ref);

	printk(KERN_ALERT "[svm]: grant table to %d, gnt_ref is:%d.\n", dev.otherend_id, gnt_ref);

	return 0;
}
Exemple #3
0
static int pvdrm_slot_ensure_ref(struct pvdrm_device* pvdrm, struct pvdrm_slot* slot)
{
	int ret = 0;
	uintptr_t addr = 0;
	struct xenbus_device* xbdev = pvdrm_to_xbdev(pvdrm);

	if (slot->ref >= 0) {
		return 0;
	}

	/* Allocate ref. */
	addr = get_zeroed_page(GFP_NOIO | __GFP_HIGH);
	if (!addr) {
		ret = -ENOMEM;
		xenbus_dev_fatal(xbdev, ret, "allocating ring page");
		return ret;
	}

	ret = xenbus_grant_ring(xbdev, virt_to_mfn(addr));
	if (ret < 0) {
		xenbus_dev_fatal(xbdev, ret, "granting ring page");
		free_page(addr);
		return ret;
	}

	slot->ref = ret;
	slot->addr = (void*)addr;

	return 0;
}
Exemple #4
0
static int pcifront_publish_info(struct pcifront_device *pdev)
{
	int err = 0;
	struct xenbus_transaction trans;

	err = xenbus_grant_ring(pdev->xdev, virt_to_mfn(pdev->sh_info));
	if (err < 0)
		goto out;

	pdev->gnt_ref = err;

	err = xenbus_alloc_evtchn(pdev->xdev, &pdev->evtchn);
	if (err)
		goto out;

	bind_caller_port_to_irqhandler(pdev->evtchn, pcifront_handler_aer, 
		IRQF_SAMPLE_RANDOM, "pcifront", pdev);

      do_publish:
	err = xenbus_transaction_start(&trans);
	if (err) {
		xenbus_dev_fatal(pdev->xdev, err,
				 "Error writing configuration for backend "
				 "(start transaction)");
		goto out;
	}

	err = xenbus_printf(trans, pdev->xdev->nodename,
			    "pci-op-ref", "%u", pdev->gnt_ref);
	if (!err)
		err = xenbus_printf(trans, pdev->xdev->nodename,
				    "event-channel", "%u", pdev->evtchn);
	if (!err)
		err = xenbus_printf(trans, pdev->xdev->nodename,
				    "magic", XEN_PCI_MAGIC);

	if (err) {
		xenbus_transaction_end(trans, 1);
		xenbus_dev_fatal(pdev->xdev, err,
				 "Error writing configuration for backend");
		goto out;
	} else {
		err = xenbus_transaction_end(trans, 0);
		if (err == -EAGAIN)
			goto do_publish;
		else if (err) {
			xenbus_dev_fatal(pdev->xdev, err,
					 "Error completing transaction "
					 "for backend");
			goto out;
		}
	}

	xenbus_switch_state(pdev->xdev, XenbusStateInitialised);

	dev_dbg(&pdev->xdev->dev, "publishing successful!\n");

      out:
	return err;
}
Exemple #5
0
/* Write to the xenbus info needed by backend */
static int
pcifront_publish_info(struct pcifront_device *pdev)
{
	int err = 0;
	struct xenbus_transaction *trans;

	err = xenbus_grant_ring(pdev->xdev, virt_to_mfn(pdev->sh_info));
	if (err < 0) {
		WPRINTF("error granting access to ring page\n");
		goto out;
	}

	pdev->gnt_ref = err;

	err = xenbus_alloc_evtchn(pdev->xdev, &pdev->evtchn);
	if (err)
		goto out;

 do_publish:
	trans = xenbus_transaction_start();
	if (IS_ERR(trans)) {
		xenbus_dev_fatal(pdev->xdev, err,
						 "Error writing configuration for backend "
						 "(start transaction)");
		goto out;
	}

	err = xenbus_printf(trans, pdev->xdev->nodename,
						"pci-op-ref", "%u", pdev->gnt_ref);
	if (!err)
		err = xenbus_printf(trans, pdev->xdev->nodename,
							"event-channel", "%u", pdev->evtchn);
	if (!err)
		err = xenbus_printf(trans, pdev->xdev->nodename,
							"magic", XEN_PCI_MAGIC);
	if (!err)
		err = xenbus_switch_state(pdev->xdev, trans,
								  XenbusStateInitialised);

	if (err) {
		xenbus_transaction_end(trans, 1);
		xenbus_dev_fatal(pdev->xdev, err,
						 "Error writing configuration for backend");
		goto out;
	} else {
		err = xenbus_transaction_end(trans, 0);
		if (err == -EAGAIN)
			goto do_publish;
		else if (err) {
			xenbus_dev_fatal(pdev->xdev, err,
							 "Error completing transaction for backend");
			goto out;
		}
	}

 out:
	return err;
}
Exemple #6
0
static int setup_ixpring(struct xenbus_device *dev,
			 struct ixpfront_info *info)
{
	struct ixp_sring *sring;
	int err;

	info->ring_ref = GRANT_INVALID_REF;

	sring = (struct ixp_sring *)__get_free_page(GFP_NOIO | __GFP_HIGH);
	if (!sring) {
		xenbus_dev_fatal(dev, -ENOMEM, "allocating shared ring");
		return -ENOMEM;
	}
	SHARED_RING_INIT(sring);
	FRONT_RING_INIT(&info->ring, sring, PAGE_SIZE);

	err = xenbus_grant_ring(dev, virt_to_mfn(info->ring.sring));
	if (err < 0) {
		free_page((unsigned long)sring);
		info->ring.sring = NULL;
		goto fail;
	}
	
  	info->ring_ref = err;

	err = xenbus_alloc_evtchn(dev, &info->evtchn);
	if (err)
		goto fail;

	err = bind_evtchn_to_irqhandler(info->evtchn,
					ixp_interrupt,
					IRQF_SAMPLE_RANDOM, "ixp", info);
	if (err <= 0) {
		xenbus_dev_fatal(dev, err,
				 "bind_evtchn_to_irqhandler failed");
		goto fail;
	}
	info->irq = err;

	return 0;
fail:
	ixp_free(info, 0);
	return err;
}
Exemple #7
0
/* caller must clean up in case of errors */
static int setup_ring(struct xenbus_device *dev, struct tpm_private *priv)
{
	struct xenbus_transaction xbt;
	const char *message = NULL;
	int rv;
	grant_ref_t gref;

	priv->shr = (void *)__get_free_page(GFP_KERNEL|__GFP_ZERO);
	if (!priv->shr) {
		xenbus_dev_fatal(dev, -ENOMEM, "allocating shared ring");
		return -ENOMEM;
	}

	rv = xenbus_grant_ring(dev, priv->shr, 1, &gref);
	if (rv < 0)
		return rv;

	priv->ring_ref = gref;

	rv = xenbus_alloc_evtchn(dev, &priv->evtchn);
	if (rv)
		return rv;

	rv = bind_evtchn_to_irqhandler(priv->evtchn, tpmif_interrupt, 0,
				       "tpmif", priv);
	if (rv <= 0) {
		xenbus_dev_fatal(dev, rv, "allocating TPM irq");
		return rv;
	}
	priv->irq = rv;

 again:
	rv = xenbus_transaction_start(&xbt);
	if (rv) {
		xenbus_dev_fatal(dev, rv, "starting transaction");
		return rv;
	}

	rv = xenbus_printf(xbt, dev->nodename,
			"ring-ref", "%u", priv->ring_ref);
	if (rv) {
		message = "writing ring-ref";
		goto abort_transaction;
	}

	rv = xenbus_printf(xbt, dev->nodename, "event-channel", "%u",
			priv->evtchn);
	if (rv) {
		message = "writing event-channel";
		goto abort_transaction;
	}

	rv = xenbus_printf(xbt, dev->nodename, "feature-protocol-v2", "1");
	if (rv) {
		message = "writing feature-protocol-v2";
		goto abort_transaction;
	}

	rv = xenbus_transaction_end(xbt, 0);
	if (rv == -EAGAIN)
		goto again;
	if (rv) {
		xenbus_dev_fatal(dev, rv, "completing transaction");
		return rv;
	}

	xenbus_switch_state(dev, XenbusStateInitialised);

	return 0;

 abort_transaction:
	xenbus_transaction_end(xbt, 1);
	if (message)
		xenbus_dev_error(dev, rv, "%s", message);

	return rv;
}
static int
xennet_xenbus_resume(void *p)
{
	struct xennet_xenbus_softc *sc = p;
	struct xenbus_transaction *xbt;
	int error;
	netif_tx_sring_t *tx_ring;
	netif_rx_sring_t *rx_ring;
	paddr_t ma;
	const char *errmsg;

	sc->sc_tx_ring_gntref = GRANT_INVALID_REF;
	sc->sc_rx_ring_gntref = GRANT_INVALID_REF;


	/* setup device: alloc event channel and shared rings */
	tx_ring = (void *)uvm_km_alloc(kernel_map, PAGE_SIZE, 0,
	     UVM_KMF_WIRED | UVM_KMF_ZERO);
	rx_ring = (void *)uvm_km_alloc(kernel_map, PAGE_SIZE, 0,
	    UVM_KMF_WIRED | UVM_KMF_ZERO);
	if (tx_ring == NULL || rx_ring == NULL)
		panic("xennet_xenbus_resume: can't alloc rings");

	SHARED_RING_INIT(tx_ring);
	FRONT_RING_INIT(&sc->sc_tx_ring, tx_ring, PAGE_SIZE);
	SHARED_RING_INIT(rx_ring);
	FRONT_RING_INIT(&sc->sc_rx_ring, rx_ring, PAGE_SIZE);

	(void)pmap_extract_ma(pmap_kernel(), (vaddr_t)tx_ring, &ma);
	error = xenbus_grant_ring(sc->sc_xbusd, ma, &sc->sc_tx_ring_gntref);
	if (error)
		return error;
	(void)pmap_extract_ma(pmap_kernel(), (vaddr_t)rx_ring, &ma);
	error = xenbus_grant_ring(sc->sc_xbusd, ma, &sc->sc_rx_ring_gntref);
	if (error)
		return error;
	error = xenbus_alloc_evtchn(sc->sc_xbusd, &sc->sc_evtchn);
	if (error)
		return error;
	aprint_verbose_dev(sc->sc_dev, "using event channel %d\n",
	    sc->sc_evtchn);
	event_set_handler(sc->sc_evtchn, &xennet_handler, sc,
	    IPL_NET, device_xname(sc->sc_dev));

again:
	xbt = xenbus_transaction_start();
	if (xbt == NULL)
		return ENOMEM;
	error = xenbus_printf(xbt, sc->sc_xbusd->xbusd_path,
	    "tx-ring-ref","%u", sc->sc_tx_ring_gntref);
	if (error) {
		errmsg = "writing tx ring-ref";
		goto abort_transaction;
	}
	error = xenbus_printf(xbt, sc->sc_xbusd->xbusd_path,
	    "rx-ring-ref","%u", sc->sc_rx_ring_gntref);
	if (error) {
		errmsg = "writing rx ring-ref";
		goto abort_transaction;
	}
	error = xenbus_printf(xbt, sc->sc_xbusd->xbusd_path,
	    "event-channel", "%u", sc->sc_evtchn);
	if (error) {
		errmsg = "writing event channel";
		goto abort_transaction;
	}
	error = xenbus_printf(xbt, sc->sc_xbusd->xbusd_path,
	    "state", "%d", XenbusStateConnected);
	if (error) {
		errmsg = "writing frontend XenbusStateConnected";
		goto abort_transaction;
	}
	error = xenbus_transaction_end(xbt, 0);
	if (error == EAGAIN)
		goto again;
	if (error) {
		xenbus_dev_fatal(sc->sc_xbusd, error, "completing transaction");
		return -1;
	}
	xennet_alloc_rx_buffer(sc);
	sc->sc_backend_status = BEST_CONNECTED;
	return 0;

abort_transaction:
	xenbus_transaction_end(xbt, 1);
	xenbus_dev_fatal(sc->sc_xbusd, error, "%s", errmsg);
	return error;
}
Exemple #9
0
static void scsifront_free(struct vscsifrnt_info *info)
{
	struct Scsi_Host *host = info->host;

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14)
	if (host->shost_state != SHOST_DEL) {
#else
	if (!test_bit(SHOST_DEL, &host->shost_state)) {
#endif
		scsi_remove_host(info->host);
	}

	if (info->ring_ref != GRANT_INVALID_REF) {
		gnttab_end_foreign_access(info->ring_ref,
					(unsigned long)info->ring.sring);
		info->ring_ref = GRANT_INVALID_REF;
		info->ring.sring = NULL;
	}

	if (info->irq)
		unbind_from_irqhandler(info->irq, info);
	info->irq = 0;

	scsi_host_put(info->host);
}


static int scsifront_alloc_ring(struct vscsifrnt_info *info)
{
	struct xenbus_device *dev = info->dev;
	struct vscsiif_sring *sring;
	int err = -ENOMEM;


	info->ring_ref = GRANT_INVALID_REF;

	/***** Frontend to Backend ring start *****/
	sring = (struct vscsiif_sring *) __get_free_page(GFP_KERNEL);
	if (!sring) {
		xenbus_dev_fatal(dev, err, "fail to allocate shared ring (Front to Back)");
		return err;
	}
	SHARED_RING_INIT(sring);
	FRONT_RING_INIT(&info->ring, sring, PAGE_SIZE);

	err = xenbus_grant_ring(dev, virt_to_mfn(sring));
	if (err < 0) {
		free_page((unsigned long) sring);
		info->ring.sring = NULL;
		xenbus_dev_fatal(dev, err, "fail to grant shared ring (Front to Back)");
		goto free_sring;
	}
	info->ring_ref = err;

	err = bind_listening_port_to_irqhandler(
			dev->otherend_id, scsifront_intr,
			SA_SAMPLE_RANDOM, "scsifront", info);

	if (err <= 0) {
		xenbus_dev_fatal(dev, err, "bind_listening_port_to_irqhandler");
		goto free_sring;
	}
	info->irq = err;

	return 0;

/* free resource */
free_sring:
	scsifront_free(info);

	return err;
}


static int scsifront_init_ring(struct vscsifrnt_info *info)
{
	struct xenbus_device *dev = info->dev;
	struct xenbus_transaction xbt;
	int err;

	DPRINTK("%s\n",__FUNCTION__);

	err = scsifront_alloc_ring(info);
	if (err)
		return err;
	DPRINTK("%u %u\n", info->ring_ref, info->evtchn);

again:
	err = xenbus_transaction_start(&xbt);
	if (err) {
		xenbus_dev_fatal(dev, err, "starting transaction");
	}

	err = xenbus_printf(xbt, dev->nodename, "ring-ref", "%u",
				info->ring_ref);
	if (err) {
		xenbus_dev_fatal(dev, err, "%s", "writing ring-ref");
		goto fail;
	}

	err = xenbus_printf(xbt, dev->nodename, "event-channel", "%u",
				irq_to_evtchn_port(info->irq));

	if (err) {
		xenbus_dev_fatal(dev, err, "%s", "writing event-channel");
		goto fail;
	}

	err = xenbus_transaction_end(xbt, 0);
	if (err) {
		if (err == -EAGAIN)
			goto again;
		xenbus_dev_fatal(dev, err, "completing transaction");
		goto free_sring;
	}

	return 0;

fail:
	xenbus_transaction_end(xbt, 1);
free_sring:
	/* free resource */
	scsifront_free(info);
	
	return err;
}


static int scsifront_probe(struct xenbus_device *dev,
				const struct xenbus_device_id *id)
{
	struct vscsifrnt_info *info;
	struct Scsi_Host *host;
	int i, err = -ENOMEM;
	char name[DEFAULT_TASK_COMM_LEN];

	host = scsi_host_alloc(&scsifront_sht, sizeof(*info));
	if (!host) {
		xenbus_dev_fatal(dev, err, "fail to allocate scsi host");
		return err;
	}
	info = (struct vscsifrnt_info *) host->hostdata;
	info->host = host;


	dev->dev.driver_data = info;
	info->dev  = dev;

	for (i = 0; i < VSCSIIF_MAX_REQS; i++) {
		info->shadow[i].next_free = i + 1;
		init_waitqueue_head(&(info->shadow[i].wq_reset));
		info->shadow[i].wait_reset = 0;
	}
	info->shadow[VSCSIIF_MAX_REQS - 1].next_free = 0x0fff;

	err = scsifront_init_ring(info);
	if (err) {
		scsi_host_put(host);
		return err;
	}

	init_waitqueue_head(&info->wq);
	spin_lock_init(&info->io_lock);
	spin_lock_init(&info->shadow_lock);

	snprintf(name, DEFAULT_TASK_COMM_LEN, "vscsiif.%d", info->host->host_no);

	info->kthread = kthread_run(scsifront_schedule, info, name);
	if (IS_ERR(info->kthread)) {
		err = PTR_ERR(info->kthread);
		info->kthread = NULL;
		printk(KERN_ERR "scsifront: kthread start err %d\n", err);
		goto free_sring;
	}

	host->max_id      = VSCSIIF_MAX_TARGET;
	host->max_channel = 0;
	host->max_lun     = VSCSIIF_MAX_LUN;
	host->max_sectors = (VSCSIIF_SG_TABLESIZE - 1) * PAGE_SIZE / 512;

	err = scsi_add_host(host, &dev->dev);
	if (err) {
		printk(KERN_ERR "scsifront: fail to add scsi host %d\n", err);
		goto free_sring;
	}

	xenbus_switch_state(dev, XenbusStateInitialised);

	return 0;

free_sring:
	/* free resource */
	scsifront_free(info);
	return err;
}

static int scsifront_remove(struct xenbus_device *dev)
{
	struct vscsifrnt_info *info = dev->dev.driver_data;

	DPRINTK("%s: %s removed\n",__FUNCTION__ ,dev->nodename);

	if (info->kthread) {
		kthread_stop(info->kthread);
		info->kthread = NULL;
	}

	scsifront_free(info);
	
	return 0;
}


static int scsifront_disconnect(struct vscsifrnt_info *info)
{
	struct xenbus_device *dev = info->dev;
	struct Scsi_Host *host = info->host;

	DPRINTK("%s: %s disconnect\n",__FUNCTION__ ,dev->nodename);

	/* 
	  When this function is executed,  all devices of 
	  Frontend have been deleted. 
	  Therefore, it need not block I/O before remove_host.
	*/

	scsi_remove_host(host);
	xenbus_frontend_closed(dev);

	return 0;
}

#define VSCSIFRONT_OP_ADD_LUN	1
#define VSCSIFRONT_OP_DEL_LUN	2

static void scsifront_do_lun_hotplug(struct vscsifrnt_info *info, int op)
{
	struct xenbus_device *dev = info->dev;
	int i, err = 0;
	char str[64], state_str[64];
	char **dir;
	unsigned int dir_n = 0;
	unsigned int device_state;
	unsigned int hst, chn, tgt, lun;
	struct scsi_device *sdev;

	dir = xenbus_directory(XBT_NIL, dev->otherend, "vscsi-devs", &dir_n);
	if (IS_ERR(dir))
		return;

	for (i = 0; i < dir_n; i++) {
		/* read status */
		snprintf(str, sizeof(str), "vscsi-devs/%s/state", dir[i]);
		err = xenbus_scanf(XBT_NIL, dev->otherend, str, "%u",
			&device_state);
		if (XENBUS_EXIST_ERR(err))
			continue;
		
		/* virtual SCSI device */
		snprintf(str, sizeof(str), "vscsi-devs/%s/v-dev", dir[i]);
		err = xenbus_scanf(XBT_NIL, dev->otherend, str,
			"%u:%u:%u:%u", &hst, &chn, &tgt, &lun);
		if (XENBUS_EXIST_ERR(err))
			continue;

		/* front device state path */
		snprintf(state_str, sizeof(state_str), "vscsi-devs/%s/state", dir[i]);

		switch (op) {
		case VSCSIFRONT_OP_ADD_LUN:
			if (device_state == XenbusStateInitialised) {
				sdev = scsi_device_lookup(info->host, chn, tgt, lun);
				if (sdev) {
					printk(KERN_ERR "scsifront: Device already in use.\n");
					scsi_device_put(sdev);
					xenbus_printf(XBT_NIL, dev->nodename,
						state_str, "%d", XenbusStateClosed);
				} else {
					scsi_add_device(info->host, chn, tgt, lun);
					xenbus_printf(XBT_NIL, dev->nodename,
						state_str, "%d", XenbusStateConnected);
				}
			}
			break;
		case VSCSIFRONT_OP_DEL_LUN:
			if (device_state == XenbusStateClosing) {
				sdev = scsi_device_lookup(info->host, chn, tgt, lun);
				if (sdev) {
					scsi_remove_device(sdev);
					scsi_device_put(sdev);
					xenbus_printf(XBT_NIL, dev->nodename,
						state_str, "%d", XenbusStateClosed);
				}
			}
			break;
		default:
			break;
		}
	}
	
	kfree(dir);
	return;
}




static void scsifront_backend_changed(struct xenbus_device *dev,
				enum xenbus_state backend_state)
{
	struct vscsifrnt_info *info = dev->dev.driver_data;

	DPRINTK("%p %u %u\n", dev, dev->state, backend_state);

	switch (backend_state) {
	case XenbusStateUnknown:
	case XenbusStateInitialising:
	case XenbusStateInitWait:
	case XenbusStateClosed:
		break;

	case XenbusStateInitialised:
		break;

	case XenbusStateConnected:
		if (xenbus_read_driver_state(dev->nodename) ==
			XenbusStateInitialised) {
			scsifront_do_lun_hotplug(info, VSCSIFRONT_OP_ADD_LUN);
		}
		
		if (dev->state == XenbusStateConnected)
			break;
			
		xenbus_switch_state(dev, XenbusStateConnected);
		break;

	case XenbusStateClosing:
		scsifront_disconnect(info);
		break;

	case XenbusStateReconfiguring:
		scsifront_do_lun_hotplug(info, VSCSIFRONT_OP_DEL_LUN);
		xenbus_switch_state(dev, XenbusStateReconfiguring);
		break;

	case XenbusStateReconfigured:
		scsifront_do_lun_hotplug(info, VSCSIFRONT_OP_ADD_LUN);
		xenbus_switch_state(dev, XenbusStateConnected);
		break;
	}
}


static struct xenbus_device_id scsifront_ids[] = {
	{ "vscsi" },
	{ "" }
};
MODULE_ALIAS("xen:vscsi");

static struct xenbus_driver scsifront_driver = {
	.name			= "vscsi",
	.owner			= THIS_MODULE,
	.ids			= scsifront_ids,
	.probe			= scsifront_probe,
	.remove			= scsifront_remove,
/* 	.resume			= scsifront_resume, */
	.otherend_changed	= scsifront_backend_changed,
};

int scsifront_xenbus_init(void)
{
	return xenbus_register_frontend(&scsifront_driver);
}

void scsifront_xenbus_unregister(void)
{
	xenbus_unregister_driver(&scsifront_driver);
}
Exemple #10
0
int pvdrm_slots_init(struct pvdrm_device* pvdrm)
{
	int i;
	int ret;
	struct pvdrm_slots* slots;
	struct xenbus_device* xbdev;
        struct pvdrm_mapped* mapped;
        spinlock_t* lock;
	struct semaphore* sema;

        BUILD_BUG_ON(sizeof(struct pvdrm_mapped) > PAGE_SIZE);

        PVDRM_INFO("Initializing pvdrm slots.\n");
	ret = 0;

	slots = kzalloc(sizeof(struct pvdrm_slots), GFP_KERNEL);
	if (!slots) {
		return -ENOMEM;
	}
	pvdrm->slots = slots;

	xbdev = pvdrm_to_xbdev(pvdrm);

        sema = &slots->sema;
	sema_init(sema, PVDRM_SLOT_NR);

        lock = &slots->lock;
        spin_lock_init(lock);

	/* Allocate slot and counter ref. */
	{
		const uintptr_t vaddr = get_zeroed_page(GFP_NOIO | __GFP_HIGH);
		if (!vaddr) {
			ret = -ENOMEM;
			xenbus_dev_fatal(xbdev, ret, "allocating ring page");
			return ret;
		}

		ret = xenbus_grant_ring(xbdev, virt_to_mfn(vaddr));
		if (ret < 0) {
			xenbus_dev_fatal(xbdev, ret, "granting ring page");
			free_page(vaddr);
			return ret;
		}

		slots->ref = ret;
		slots->mapped = (void*)vaddr;
	}
	PVDRM_INFO("Initialising pvdrm counter reference %u.\n", slots->ref);

        mapped = slots->mapped;

	/* Init counter. */
        atomic_set(&mapped->count, 0);
        atomic_set(&slots->put, UINT32_MAX);

        PVDRM_INFO("Initialized pvdrm counter.\n");

	/* Init slots. */
	for (i = 0; i < PVDRM_SLOT_NR; ++i) {
                struct pvdrm_slot* slot = &mapped->slot[i];
                slot->code = PVDRM_UNUSED;
		slot->ref = -EINVAL;
                mapped->ring[i] = (uint8_t)-1;
		ret = pvdrm_slot_ensure_ref(pvdrm, slot);
		if (ret) {
			BUG();
		}
	}
        wmb();

        PVDRM_INFO("Initialized pvdrm slots.\n");

	return 0;
}
Exemple #11
0
static int omx_xenfront_probe(struct xenbus_device *dev,
			      const struct xenbus_device_id *id)
{
	struct omx_xenfront_info *fe;
	struct omx_xenif_sring *sring, *recv_sring;
	int err = 0;
	int i = 0;

	dprintk_in();

	dprintk_deb("Frontend Probe Fired!\n");
	fe = kzalloc(sizeof(*fe), GFP_KERNEL);
	dprintk_deb("fe info is @%#llx!\n", (unsigned long long)fe);
	if (!fe) {
		xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure");
		err = -ENOMEM;
		goto out;
	}
	__omx_xen_frontend = fe;

	for (i = 0; i < OMX_XEN_MAX_ENDPOINTS; i++) {
		fe->endpoints[i] = NULL;
	}

        fe->requests = kzalloc(OMX_MAX_INFLIGHT_REQUESTS * sizeof(enum frontend_status), GFP_KERNEL);

        spin_lock_init(&fe->status_lock);

	fe->xbdev = dev;
	fe->connected = OMXIF_STATE_DISCONNECTED;

        init_waitqueue_head(&fe->wq);
        fe->msg_workq =
            create_singlethread_workqueue("ReQ_FE");
        if (unlikely(!fe->msg_workq)) {
                printk_err("Couldn't create msg_workq!\n");
                err = -ENOMEM;
                goto out;
        }

        INIT_WORK(&fe->msg_workq_task, omx_xenif_interrupt);


	spin_lock_init(&fe->lock);
	dprintk_deb("Setting up shared ring\n");

	sring =
	    (struct omx_xenif_sring *)get_zeroed_page(GFP_NOIO | __GFP_HIGH);
	if (!sring) {
		xenbus_dev_fatal(dev, -ENOMEM, "allocating shared ring");
		err = -ENOMEM;
		goto out;
	}
	SHARED_RING_INIT(sring);
	FRONT_RING_INIT(&fe->ring, sring, PAGE_SIZE);

	err = xenbus_grant_ring(dev, virt_to_mfn(fe->ring.sring));
	if (err < 0) {
		free_page((unsigned long)sring);
		fe->ring.sring = NULL;
		printk_err("Failed to grant ring\n");
		goto out;
	}
	fe->ring_ref = err;


	recv_sring =
	    (struct omx_xenif_sring *)get_zeroed_page(GFP_NOIO | __GFP_HIGH);
	if (!sring) {
		xenbus_dev_fatal(dev, -ENOMEM, "allocating shared ring");
		err = -ENOMEM;
		goto out;
	}
	SHARED_RING_INIT(recv_sring);
	FRONT_RING_INIT(&fe->recv_ring, recv_sring, PAGE_SIZE);

	err = xenbus_grant_ring(dev, virt_to_mfn(fe->recv_ring.sring));
	if (err < 0) {
		free_page((unsigned long)recv_sring);
		fe->recv_ring.sring = NULL;
		printk_err("Failed to grant recv_ring\n");
		goto out;
	}
	fe->recv_ring_ref = err;

	fe->handle = simple_strtoul(strrchr(dev->nodename, '/') + 1, NULL, 0);
	dprintk_deb("setting handle = %u\n", fe->handle);
	dev_set_drvdata(&dev->dev, fe);
	err = 0;
	//omx_xenfront_dev->info = info;
	//fe->endpoints = kzalloc(sizeof(struct omx_endpoint*) * OMX_XEN_MAX_ENDPOINTS, GFP_KERNEL);
	xenbus_switch_state(dev, XenbusStateInitialising);

out:
	dprintk_out();
	return err;

}