static int hvc_tile_probe(struct platform_device *pdev) { struct hvc_struct *hp; int tile_hvc_irq; /* Create our IRQ and register it. */ tile_hvc_irq = irq_alloc_hwirq(-1); if (!tile_hvc_irq) return -ENXIO; tile_irq_activate(tile_hvc_irq, TILE_IRQ_PERCPU); hp = hvc_alloc(0, tile_hvc_irq, &hvc_tile_get_put_ops, 128); if (IS_ERR(hp)) { irq_free_hwirq(tile_hvc_irq); return PTR_ERR(hp); } dev_set_drvdata(&pdev->dev, hp); return 0; }
static int ohci_hcd_tilegx_drv_probe(struct platform_device *pdev) { struct usb_hcd *hcd; struct tilegx_usb_platform_data *pdata = dev_get_platdata(&pdev->dev); pte_t pte = { 0 }; int my_cpu = smp_processor_id(); int ret; if (usb_disabled()) return -ENODEV; /* * Try to initialize our GXIO context; if we can't, the device * doesn't exist. */ if (gxio_usb_host_init(&pdata->usb_ctx, pdata->dev_index, 0) != 0) return -ENXIO; hcd = usb_create_hcd(&ohci_tilegx_hc_driver, &pdev->dev, dev_name(&pdev->dev)); if (!hcd) { ret = -ENOMEM; goto err_hcd; } /* * We don't use rsrc_start to map in our registers, but seems like * we ought to set it to something, so we use the register VA. */ hcd->rsrc_start = (ulong) gxio_usb_host_get_reg_start(&pdata->usb_ctx); hcd->rsrc_len = gxio_usb_host_get_reg_len(&pdata->usb_ctx); hcd->regs = gxio_usb_host_get_reg_start(&pdata->usb_ctx); tilegx_start_ohc(); /* Create our IRQs and register them. */ pdata->irq = create_irq(); if (pdata->irq < 0) { ret = -ENXIO; goto err_no_irq; } tile_irq_activate(pdata->irq, TILE_IRQ_PERCPU); /* Configure interrupts. */ ret = gxio_usb_host_cfg_interrupt(&pdata->usb_ctx, cpu_x(my_cpu), cpu_y(my_cpu), KERNEL_PL, pdata->irq); if (ret) { ret = -ENXIO; goto err_have_irq; } /* Register all of our memory. */ pte = pte_set_home(pte, PAGE_HOME_HASH); ret = gxio_usb_host_register_client_memory(&pdata->usb_ctx, pte, 0); if (ret) { ret = -ENXIO; goto err_have_irq; } ohci_hcd_init(hcd_to_ohci(hcd)); ret = usb_add_hcd(hcd, pdata->irq, IRQF_SHARED); if (ret == 0) { platform_set_drvdata(pdev, hcd); return ret; } err_have_irq: destroy_irq(pdata->irq); err_no_irq: tilegx_stop_ohc(); usb_put_hcd(hcd); err_hcd: gxio_usb_host_destroy(&pdata->usb_ctx); return ret; }
/* * Perform initialization and enable port for reception. */ static int tilegx_startup(struct uart_port *port) { struct tile_uart_port *tile_uart; gxio_uart_context_t *context; int ret = 0; int cpu = raw_smp_processor_id(); /* pick an arbitrary cpu */ tile_uart = container_of(port, struct tile_uart_port, uart); if (mutex_lock_interruptible(&tile_uart->mutex)) return -EBUSY; context = &tile_uart->context; /* Now open the hypervisor device if we haven't already. */ if (context->fd < 0) { UART_INTERRUPT_MASK_t intr_mask; /* Initialize UART device. */ ret = gxio_uart_init(context, port->line); if (ret) { ret = -ENXIO; goto err; } /* Create our IRQs. */ port->irq = irq_alloc_hwirq(-1); if (!port->irq) goto err_uart_dest; tile_irq_activate(port->irq, TILE_IRQ_PERCPU); /* Register our IRQs. */ ret = request_irq(port->irq, tilegx_interrupt, 0, tilegx_uart_driver.driver_name, port); if (ret) goto err_dest_irq; /* Request that the hardware start sending us interrupts. */ tile_uart->irq_cpu = cpu; ret = gxio_uart_cfg_interrupt(context, cpu_x(cpu), cpu_y(cpu), KERNEL_PL, port->irq); if (ret) goto err_free_irq; /* Enable UART Tx/Rx Interrupt. */ intr_mask.word = gxio_uart_read(context, UART_INTERRUPT_MASK); intr_mask.wfifo_re = 0; intr_mask.rfifo_we = 0; gxio_uart_write(context, UART_INTERRUPT_MASK, intr_mask.word); /* Reset the Tx/Rx interrupt in case it's set. */ gxio_uart_write(context, UART_INTERRUPT_STATUS, UART_INTERRUPT_MASK__WFIFO_RE_MASK | UART_INTERRUPT_MASK__RFIFO_WE_MASK); } mutex_unlock(&tile_uart->mutex); return ret; err_free_irq: free_irq(port->irq, port); err_dest_irq: irq_free_hwirq(port->irq); err_uart_dest: gxio_uart_destroy(context); ret = -ENXIO; err: mutex_unlock(&tile_uart->mutex); return ret; }
/* * This routine finds the first virtqueue described in the configuration of * this device and sets it up. */ static struct virtqueue *kvm_find_vq(struct virtio_device *vdev, unsigned index, void (*callback)(struct virtqueue *vq), const char *name) { struct kvm_device *kdev = to_kvmdev(vdev); struct kvm_vqinfo *vqi; struct kvm_vqconfig *config; struct virtqueue *vq; long irq; int err = -EINVAL; if (index >= kdev->desc->num_vq) return ERR_PTR(-ENOENT); vqi = kzalloc(sizeof(*vqi), GFP_KERNEL); if (!vqi) return ERR_PTR(-ENOMEM); config = kvm_vq_config(kdev->desc)+index; vqi->config = config; vqi->pages = generic_remap_prot(config->pa, vring_size(config->num, KVM_TILE_VIRTIO_RING_ALIGN), 0, io_prot()); if (!vqi->pages) { err = -ENOMEM; goto out; } vq = vring_new_virtqueue(config->num, KVM_TILE_VIRTIO_RING_ALIGN, vdev, 0, vqi->pages, kvm_notify, callback, name); if (!vq) { err = -ENOMEM; goto unmap; } /* * Trigger the IPI interrupt in SW way. * TODO: We do not need to create one irq for each vq. A bit wasteful. */ irq = create_irq(); if (irq < 0) { err = -ENXIO; goto del_virtqueue; } tile_irq_activate(irq, TILE_IRQ_SW_CLEAR); if (request_irq(irq, vring_interrupt, 0, dev_name(&vdev->dev), vq)) { err = -ENXIO; destroy_irq(irq); goto del_virtqueue; } config->irq = irq; vq->priv = vqi; return vq; del_virtqueue: vring_del_virtqueue(vq); unmap: vunmap(vqi->pages); out: return ERR_PTR(err); }
static int ehci_hcd_tilegx_drv_probe(struct platform_device *pdev) { struct usb_hcd *hcd; struct ehci_hcd *ehci; struct tilegx_usb_platform_data *pdata = dev_get_platdata(&pdev->dev); pte_t pte = { 0 }; int my_cpu = smp_processor_id(); int ret; if (usb_disabled()) return -ENODEV; /* * Try to initialize our GXIO context; if we can't, the device * doesn't exist. */ if (gxio_usb_host_init(&pdata->usb_ctx, pdata->dev_index, 1) != 0) return -ENXIO; hcd = usb_create_hcd(&ehci_tilegx_hc_driver, &pdev->dev, dev_name(&pdev->dev)); if (!hcd) { ret = -ENOMEM; goto err_hcd; } /* * We don't use rsrc_start to map in our registers, but seems like * we ought to set it to something, so we use the register VA. */ hcd->rsrc_start = (ulong) gxio_usb_host_get_reg_start(&pdata->usb_ctx); hcd->rsrc_len = gxio_usb_host_get_reg_len(&pdata->usb_ctx); hcd->regs = gxio_usb_host_get_reg_start(&pdata->usb_ctx); tilegx_start_ehc(); ehci = hcd_to_ehci(hcd); ehci->caps = hcd->regs; ehci->regs = hcd->regs + HC_LENGTH(ehci, readl(&ehci->caps->hc_capbase)); /* cache this readonly data; minimize chip reads */ ehci->hcs_params = readl(&ehci->caps->hcs_params); /* Create our IRQs and register them. */ pdata->irq = irq_alloc_hwirq(-1); if (!pdata->irq) { ret = -ENXIO; goto err_no_irq; } tile_irq_activate(pdata->irq, TILE_IRQ_PERCPU); /* Configure interrupts. */ ret = gxio_usb_host_cfg_interrupt(&pdata->usb_ctx, cpu_x(my_cpu), cpu_y(my_cpu), KERNEL_PL, pdata->irq); if (ret) { ret = -ENXIO; goto err_have_irq; } /* Register all of our memory. */ pte = pte_set_home(pte, PAGE_HOME_HASH); ret = gxio_usb_host_register_client_memory(&pdata->usb_ctx, pte, 0); if (ret) { ret = -ENXIO; goto err_have_irq; } ret = usb_add_hcd(hcd, pdata->irq, IRQF_SHARED); if (ret == 0) { platform_set_drvdata(pdev, hcd); device_wakeup_enable(hcd->self.controller); return ret; } err_have_irq: irq_free_hwirq(pdata->irq); err_no_irq: tilegx_stop_ehc(); usb_put_hcd(hcd); err_hcd: gxio_usb_host_destroy(&pdata->usb_ctx); return ret; }