static int ps3_ehci_probe(struct ps3_system_bus_device *dev) { int result; struct usb_hcd *hcd; unsigned int virq; static u64 dummy_mask = DMA_32BIT_MASK; if (usb_disabled()) { result = -ENODEV; goto fail_start; } result = ps3_open_hv_device(dev); if (result) { dev_dbg(&dev->core, "%s:%d: ps3_open_hv_device failed\n", __func__, __LINE__); goto fail_open; } result = ps3_dma_region_create(dev->d_region); if (result) { dev_dbg(&dev->core, "%s:%d: ps3_dma_region_create failed: " "(%d)\n", __func__, __LINE__, result); BUG_ON("check region type"); goto fail_dma_region; } result = ps3_mmio_region_create(dev->m_region); if (result) { dev_dbg(&dev->core, "%s:%d: ps3_map_mmio_region failed\n", __func__, __LINE__); result = -EPERM; goto fail_mmio_region; } dev_dbg(&dev->core, "%s:%d: mmio mapped_addr %lxh\n", __func__, __LINE__, dev->m_region->lpar_addr); result = ps3_io_irq_setup(PS3_BINDING_CPU_ANY, dev->interrupt_id, &virq); if (result) { dev_dbg(&dev->core, "%s:%d: ps3_construct_io_irq(%d) failed.\n", __func__, __LINE__, virq); result = -EPERM; goto fail_irq; } dev->core.dma_mask = &dummy_mask; /* FIXME: for improper usb code */ hcd = usb_create_hcd(&ps3_ehci_hc_driver, &dev->core, dev_name(&dev->core)); if (!hcd) { dev_dbg(&dev->core, "%s:%d: usb_create_hcd failed\n", __func__, __LINE__); result = -ENOMEM; goto fail_create_hcd; } hcd->rsrc_start = dev->m_region->lpar_addr; hcd->rsrc_len = dev->m_region->len; if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) dev_dbg(&dev->core, "%s:%d: request_mem_region failed\n", __func__, __LINE__); hcd->regs = ioremap(dev->m_region->lpar_addr, dev->m_region->len); if (!hcd->regs) { dev_dbg(&dev->core, "%s:%d: ioremap failed\n", __func__, __LINE__); result = -EPERM; goto fail_ioremap; } dev_dbg(&dev->core, "%s:%d: hcd->rsrc_start %lxh\n", __func__, __LINE__, (unsigned long)hcd->rsrc_start); dev_dbg(&dev->core, "%s:%d: hcd->rsrc_len %lxh\n", __func__, __LINE__, (unsigned long)hcd->rsrc_len); dev_dbg(&dev->core, "%s:%d: hcd->regs %lxh\n", __func__, __LINE__, (unsigned long)hcd->regs); dev_dbg(&dev->core, "%s:%d: virq %lu\n", __func__, __LINE__, (unsigned long)virq); ps3_system_bus_set_driver_data(dev, hcd); result = usb_add_hcd(hcd, virq, IRQF_DISABLED); if (result) { dev_dbg(&dev->core, "%s:%d: usb_add_hcd failed (%d)\n", __func__, __LINE__, result); goto fail_add_hcd; } return result; fail_add_hcd: iounmap(hcd->regs); fail_ioremap: release_mem_region(hcd->rsrc_start, hcd->rsrc_len); usb_put_hcd(hcd); fail_create_hcd: ps3_io_irq_destroy(virq); fail_irq: ps3_free_mmio_region(dev->m_region); fail_mmio_region: ps3_dma_region_free(dev->d_region); fail_dma_region: ps3_close_hv_device(dev); fail_open: fail_start: return result; }
/** * ps3stor_setup - Setup a storage device before use * @dev: Pointer to a struct ps3_storage_device * @handler: Pointer to an interrupt handler * * Returns 0 for success, or an error code */ int ps3stor_setup(struct ps3_storage_device *dev, irq_handler_t handler) { int error, res, alignment; enum ps3_dma_page_size page_size; error = ps3_open_hv_device(&dev->sbd); if (error) { dev_err(&dev->sbd.core, "%s:%u: ps3_open_hv_device failed %d\n", __func__, __LINE__, error); goto fail; } error = ps3_sb_event_receive_port_setup(&dev->sbd, PS3_BINDING_CPU_ANY, &dev->irq); if (error) { dev_err(&dev->sbd.core, "%s:%u: ps3_sb_event_receive_port_setup failed %d\n", __func__, __LINE__, error); goto fail_close_device; } error = request_irq(dev->irq, handler, IRQF_DISABLED, dev->sbd.core.driver->name, dev); if (error) { dev_err(&dev->sbd.core, "%s:%u: request_irq failed %d\n", __func__, __LINE__, error); goto fail_sb_event_receive_port_destroy; } alignment = min(__ffs(dev->bounce_size), __ffs((unsigned long)dev->bounce_buf)); if (alignment < 12) { dev_err(&dev->sbd.core, "%s:%u: bounce buffer not aligned (%lx at 0x%p)\n", __func__, __LINE__, dev->bounce_size, dev->bounce_buf); error = -EINVAL; goto fail_free_irq; } else if (alignment < 16) page_size = PS3_DMA_4K; else page_size = PS3_DMA_64K; dev->sbd.d_region = &dev->dma_region; ps3_dma_region_init(&dev->sbd, &dev->dma_region, page_size, PS3_DMA_OTHER, dev->bounce_buf, dev->bounce_size); res = ps3_dma_region_create(&dev->dma_region); if (res) { dev_err(&dev->sbd.core, "%s:%u: cannot create DMA region\n", __func__, __LINE__); error = -ENOMEM; goto fail_free_irq; } dev->bounce_lpar = ps3_mm_phys_to_lpar(__pa(dev->bounce_buf)); dev->bounce_dma = dma_map_single(&dev->sbd.core, dev->bounce_buf, dev->bounce_size, DMA_BIDIRECTIONAL); if (!dev->bounce_dma) { dev_err(&dev->sbd.core, "%s:%u: map DMA region failed\n", __func__, __LINE__); error = -ENODEV; goto fail_free_dma; } error = ps3stor_probe_access(dev); if (error) { dev_err(&dev->sbd.core, "%s:%u: No accessible regions found\n", __func__, __LINE__); goto fail_unmap_dma; } return 0; fail_unmap_dma: dma_unmap_single(&dev->sbd.core, dev->bounce_dma, dev->bounce_size, DMA_BIDIRECTIONAL); fail_free_dma: ps3_dma_region_free(&dev->dma_region); fail_free_irq: free_irq(dev->irq, dev); fail_sb_event_receive_port_destroy: ps3_sb_event_receive_port_destroy(&dev->sbd, dev->irq); fail_close_device: ps3_close_hv_device(&dev->sbd); fail: return error; }
static int __devinit snd_ps3_driver_probe(struct ps3_system_bus_device *dev) { int i, ret; u64 lpar_addr, lpar_size; BUG_ON(!firmware_has_feature(FW_FEATURE_PS3_LV1)); BUG_ON(dev->match_id != PS3_MATCH_ID_SOUND); the_card.ps3_dev = dev; ret = ps3_open_hv_device(dev); if (ret) return -ENXIO; ret = lv1_gpu_device_map(2, &lpar_addr, &lpar_size); if (ret) { pr_info("%s: device map 2 failed %d\n", __func__, ret); goto clean_open; } ps3_mmio_region_init(dev, dev->m_region, lpar_addr, lpar_size, PAGE_SHIFT); ret = snd_ps3_map_mmio(); if (ret) goto clean_dev_map; ps3_dma_region_init(dev, dev->d_region, PAGE_SHIFT, 0, NULL, _ALIGN_UP(SND_PS3_DMA_REGION_SIZE, PAGE_SIZE)); dev->d_region->ioid = PS3_AUDIO_IOID; ret = ps3_dma_region_create(dev->d_region); if (ret) { pr_info("%s: region_create\n", __func__); goto clean_mmio; } snd_ps3_audio_set_base_addr(dev->d_region->bus_addr); the_card.start_delay = snd_ps3_start_delay; if (snd_ps3_allocate_irq()) { ret = -ENXIO; goto clean_dma_region; } ret = snd_card_create(index, id, THIS_MODULE, 0, &the_card.card); if (ret < 0) goto clean_irq; strcpy(the_card.card->driver, "PS3"); strcpy(the_card.card->shortname, "PS3"); strcpy(the_card.card->longname, "PS3 sound"); for (i = 0; i < ARRAY_SIZE(spdif_ctls); i++) { ret = snd_ctl_add(the_card.card, snd_ctl_new1(&spdif_ctls[i], &the_card)); if (ret < 0) goto clean_card; } ret = snd_pcm_new(the_card.card, "SPDIF", 0, 1, 0, &(the_card.pcm)); if (ret) goto clean_card; the_card.pcm->private_data = &the_card; strcpy(the_card.pcm->name, "SPDIF"); snd_pcm_set_ops(the_card.pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ps3_pcm_spdif_ops); the_card.pcm->info_flags = SNDRV_PCM_INFO_NONINTERLEAVED; ret = snd_pcm_lib_preallocate_pages_for_all(the_card.pcm, SNDRV_DMA_TYPE_DEV, &dev->core, SND_PS3_PCM_PREALLOC_SIZE, SND_PS3_PCM_PREALLOC_SIZE); if (ret < 0) { pr_info("%s: prealloc failed\n", __func__); goto clean_card; } the_card.null_buffer_start_vaddr = dma_alloc_coherent(&the_card.ps3_dev->core, PAGE_SIZE, &the_card.null_buffer_start_dma_addr, GFP_KERNEL); if (!the_card.null_buffer_start_vaddr) { pr_info("%s: nullbuffer alloc failed\n", __func__); goto clean_preallocate; } pr_debug("%s: null vaddr=%p dma=%#llx\n", __func__, the_card.null_buffer_start_vaddr, the_card.null_buffer_start_dma_addr); snd_ps3_init_avsetting(&the_card); snd_card_set_dev(the_card.card, &dev->core); ret = snd_card_register(the_card.card); if (ret < 0) goto clean_dma_map; pr_info("%s started. start_delay=%dms\n", the_card.card->longname, the_card.start_delay); return 0; clean_dma_map: dma_free_coherent(&the_card.ps3_dev->core, PAGE_SIZE, the_card.null_buffer_start_vaddr, the_card.null_buffer_start_dma_addr); clean_preallocate: snd_pcm_lib_preallocate_free_for_all(the_card.pcm); clean_card: snd_card_free(the_card.card); clean_irq: snd_ps3_free_irq(); clean_dma_region: ps3_dma_region_free(dev->d_region); clean_mmio: snd_ps3_unmap_mmio(); clean_dev_map: lv1_gpu_device_unmap(2); clean_open: ps3_close_hv_device(dev); return ret; };
static int __devinit snd_ps3_driver_probe(struct ps3_system_bus_device *dev) { int i, ret; u64 lpar_addr, lpar_size; BUG_ON(!firmware_has_feature(FW_FEATURE_PS3_LV1)); BUG_ON(dev->match_id != PS3_MATCH_ID_SOUND); the_card.ps3_dev = dev; ret = ps3_open_hv_device(dev); if (ret) return -ENXIO; /* setup MMIO */ ret = lv1_gpu_device_map(2, &lpar_addr, &lpar_size); if (ret) { pr_info("%s: device map 2 failed %d\n", __func__, ret); goto clean_open; } ps3_mmio_region_init(dev, dev->m_region, lpar_addr, lpar_size, PAGE_SHIFT); ret = snd_ps3_map_mmio(); if (ret) goto clean_dev_map; /* setup DMA area */ ps3_dma_region_init(dev, dev->d_region, PAGE_SHIFT, /* use system page size */ 0, /* dma type; not used */ NULL, _ALIGN_UP(SND_PS3_DMA_REGION_SIZE, PAGE_SIZE)); dev->d_region->ioid = PS3_AUDIO_IOID; ret = ps3_dma_region_create(dev->d_region); if (ret) { pr_info("%s: region_create\n", __func__); goto clean_mmio; } snd_ps3_audio_set_base_addr(dev->d_region->bus_addr); /* CONFIG_SND_PS3_DEFAULT_START_DELAY */ the_card.start_delay = snd_ps3_start_delay; /* irq */ if (snd_ps3_allocate_irq()) { ret = -ENXIO; goto clean_dma_region; } /* create card instance */ ret = snd_card_create(index, id, THIS_MODULE, 0, &the_card.card); if (ret < 0) goto clean_irq; strcpy(the_card.card->driver, "PS3"); strcpy(the_card.card->shortname, "PS3"); strcpy(the_card.card->longname, "PS3 sound"); /* create control elements */ for (i = 0; i < ARRAY_SIZE(spdif_ctls); i++) { ret = snd_ctl_add(the_card.card, snd_ctl_new1(&spdif_ctls[i], &the_card)); if (ret < 0) goto clean_card; } /* create PCM devices instance */ /* NOTE:this driver works assuming pcm:substream = 1:1 */ ret = snd_pcm_new(the_card.card, "SPDIF", 0, /* instance index, will be stored pcm.device*/ 1, /* output substream */ 0, /* input substream */ &(the_card.pcm)); if (ret) goto clean_card; the_card.pcm->private_data = &the_card; strcpy(the_card.pcm->name, "SPDIF"); /* set pcm ops */ snd_pcm_set_ops(the_card.pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ps3_pcm_spdif_ops); the_card.pcm->info_flags = SNDRV_PCM_INFO_NONINTERLEAVED; /* pre-alloc PCM DMA buffer*/ ret = snd_pcm_lib_preallocate_pages_for_all(the_card.pcm, SNDRV_DMA_TYPE_DEV, &dev->core, SND_PS3_PCM_PREALLOC_SIZE, SND_PS3_PCM_PREALLOC_SIZE); if (ret < 0) { pr_info("%s: prealloc failed\n", __func__); goto clean_card; } /* * allocate null buffer * its size should be lager than PS3_AUDIO_FIFO_STAGE_SIZE * 2 * PAGE_SIZE is enogh */ the_card.null_buffer_start_vaddr = dma_alloc_coherent(&the_card.ps3_dev->core, PAGE_SIZE, &the_card.null_buffer_start_dma_addr, GFP_KERNEL); if (!the_card.null_buffer_start_vaddr) { pr_info("%s: nullbuffer alloc failed\n", __func__); goto clean_preallocate; } pr_debug("%s: null vaddr=%p dma=%#llx\n", __func__, the_card.null_buffer_start_vaddr, the_card.null_buffer_start_dma_addr); /* set default sample rate/word width */ snd_ps3_init_avsetting(&the_card); /* register the card */ snd_card_set_dev(the_card.card, &dev->core); ret = snd_card_register(the_card.card); if (ret < 0) goto clean_dma_map; pr_info("%s started. start_delay=%dms\n", the_card.card->longname, the_card.start_delay); return 0; clean_dma_map: dma_free_coherent(&the_card.ps3_dev->core, PAGE_SIZE, the_card.null_buffer_start_vaddr, the_card.null_buffer_start_dma_addr); clean_preallocate: snd_pcm_lib_preallocate_free_for_all(the_card.pcm); clean_card: snd_card_free(the_card.card); clean_irq: snd_ps3_free_irq(); clean_dma_region: ps3_dma_region_free(dev->d_region); clean_mmio: snd_ps3_unmap_mmio(); clean_dev_map: lv1_gpu_device_unmap(2); clean_open: ps3_close_hv_device(dev); /* * there is no destructor function to pcm. * midlayer automatically releases if the card removed */ return ret; }; /* snd_ps3_probe */
/** * ps3_gelic_driver_probe - add a device to the control of this driver */ static int ps3_gelic_driver_probe (struct ps3_system_bus_device *dev) { struct gelic_net_card *card = gelic_net_alloc_card(); int result; if (!card) { dev_info(&dev->core, "gelic_net_alloc_card failed\n"); result = -ENOMEM; goto fail_alloc_card; } ps3_system_bus_set_driver_data(dev, card); card->dev = dev; result = ps3_open_hv_device(dev); if (result) { dev_dbg(&dev->core, "ps3_open_hv_device failed\n"); goto fail_open; } result = ps3_dma_region_create(dev->d_region); if (result) { dev_dbg(&dev->core, "ps3_dma_region_create failed(%d)\n", result); BUG_ON("check region type"); goto fail_dma_region; } result = lv1_net_set_interrupt_status_indicator(bus_id(card), dev_id(card), ps3_mm_phys_to_lpar(__pa(&card->irq_status)), 0); if (result) { dev_dbg(&dev->core, "lv1_net_set_interrupt_status_indicator failed: %s\n", ps3_result(result)); result = -EIO; goto fail_status_indicator; } result = gelic_net_setup_netdev(card); if (result) { dev_dbg(&dev->core, "%s:%d: ps3_dma_region_create failed: " "(%d)\n", __func__, __LINE__, result); goto fail_setup_netdev; } return 0; fail_setup_netdev: lv1_net_set_interrupt_status_indicator(bus_id(card), bus_id(card), 0 , 0); fail_status_indicator: ps3_dma_region_free(dev->d_region); fail_dma_region: ps3_close_hv_device(dev); fail_open: ps3_system_bus_set_driver_data(dev, NULL); free_netdev(card->netdev); fail_alloc_card: return result; }