/* create an adapter object and initialise it based on resource information * passed in in the message * NOTE - you cannot use this function AND the FindAdapters function at the * same time, the application must use only one of them to get the adapters */ static void subsys_create_adapter(struct hpi_message *phm, struct hpi_response *phr) { /* create temp adapter obj, because we don't know what index yet */ struct hpi_adapter_obj ao; struct hpi_adapter_obj *pao; u32 os_error_code; u16 err = 0; u32 dsp_index = 0; HPI_DEBUG_LOG(VERBOSE, "subsys_create_adapter\n"); memset(&ao, 0, sizeof(ao)); ao.priv = kzalloc(sizeof(struct hpi_hw_obj), GFP_KERNEL); if (!ao.priv) { HPI_DEBUG_LOG(ERROR, "can't get mem for adapter object\n"); phr->error = HPI_ERROR_MEMORY_ALLOC; return; } /* create the adapter object based on the resource information */ ao.pci = *phm->u.s.resource.r.pci; err = create_adapter_obj(&ao, &os_error_code); if (err) { delete_adapter_obj(&ao); if (err >= HPI_ERROR_BACKEND_BASE) { phr->error = HPI_ERROR_DSP_BOOTLOAD; phr->specific_error = err; } else { phr->error = err; } phr->u.s.data = os_error_code; return; } /* need to update paParentAdapter */ pao = hpi_find_adapter(ao.index); if (!pao) { /* We just added this adapter, why can't we find it!? */ HPI_DEBUG_LOG(ERROR, "lost adapter after boot\n"); phr->error = HPI_ERROR_BAD_ADAPTER; return; } for (dsp_index = 0; dsp_index < MAX_DSPS; dsp_index++) { struct hpi_hw_obj *phw = pao->priv; phw->ado[dsp_index].pa_parent_adapter = pao; } phr->u.s.adapter_type = ao.type; phr->u.s.adapter_index = ao.index; phr->error = 0; }
static void subsys_delete_adapter(struct hpi_message *phm, struct hpi_response *phr) { struct hpi_adapter_obj *pao = NULL; pao = hpi_find_adapter(phm->obj_index); if (!pao) return; delete_adapter_obj(pao); hpi_delete_adapter(pao); phr->error = 0; }
static void subsys_delete_adapter(struct hpi_message *phm, struct hpi_response *phr) { struct hpi_adapter_obj *pao = NULL; struct hpi_hw_obj *phw; pao = hpi_find_adapter(phm->adapter_index); if (!pao) return; phw = (struct hpi_hw_obj *)pao->priv; if (pao->has_control_cache) hpi_free_control_cache(phw->p_cache); hpi_delete_adapter(pao); kfree(phw); phr->error = 0; }
int asihpi_adapter_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id) { int idx, nm; int adapter_index; unsigned int memlen; struct hpi_message hm; struct hpi_response hr; struct hpi_adapter adapter; struct hpi_pci pci; memset(&adapter, 0, sizeof(adapter)); dev_printk(KERN_DEBUG, &pci_dev->dev, "probe %04x:%04x,%04x:%04x,%04x\n", pci_dev->vendor, pci_dev->device, pci_dev->subsystem_vendor, pci_dev->subsystem_device, pci_dev->devfn); if (pci_enable_device(pci_dev) < 0) { dev_err(&pci_dev->dev, "pci_enable_device failed, disabling device\n"); return -EIO; } pci_set_master(pci_dev); /* also sets latency timer if < 16 */ hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM, HPI_SUBSYS_CREATE_ADAPTER); hpi_init_response(&hr, HPI_OBJ_SUBSYSTEM, HPI_SUBSYS_CREATE_ADAPTER, HPI_ERROR_PROCESSING_MESSAGE); hm.adapter_index = HPI_ADAPTER_INDEX_INVALID; nm = HPI_MAX_ADAPTER_MEM_SPACES; for (idx = 0; idx < nm; idx++) { HPI_DEBUG_LOG(INFO, "resource %d %pR\n", idx, &pci_dev->resource[idx]); if (pci_resource_flags(pci_dev, idx) & IORESOURCE_MEM) { memlen = pci_resource_len(pci_dev, idx); pci.ap_mem_base[idx] = ioremap(pci_resource_start(pci_dev, idx), memlen); if (!pci.ap_mem_base[idx]) { HPI_DEBUG_LOG(ERROR, "ioremap failed, aborting\n"); /* unmap previously mapped pci mem space */ goto err; } } } pci.pci_dev = pci_dev; hm.u.s.resource.bus_type = HPI_BUS_PCI; hm.u.s.resource.r.pci = &pci; /* call CreateAdapterObject on the relevant hpi module */ hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL); if (hr.error) goto err; adapter_index = hr.u.s.adapter_index; adapter.adapter = hpi_find_adapter(adapter_index); if (prealloc_stream_buf) { adapter.p_buffer = vmalloc(prealloc_stream_buf); if (!adapter.p_buffer) { HPI_DEBUG_LOG(ERROR, "HPI could not allocate " "kernel buffer size %d\n", prealloc_stream_buf); goto err; } } hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER, HPI_ADAPTER_OPEN); hm.adapter_index = adapter.adapter->index; hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL); if (hr.error) goto err; /* WARNING can't init mutex in 'adapter' * and then copy it to adapters[] ?!?! */ adapters[adapter_index] = adapter; mutex_init(&adapters[adapter_index].mutex); pci_set_drvdata(pci_dev, &adapters[adapter_index]); dev_info(&pci_dev->dev, "probe succeeded for ASI%04X HPI index %d\n", adapter.adapter->type, adapter_index); return 0; err: for (idx = 0; idx < HPI_MAX_ADAPTER_MEM_SPACES; idx++) { if (pci.ap_mem_base[idx]) { iounmap(pci.ap_mem_base[idx]); pci.ap_mem_base[idx] = NULL; } } if (adapter.p_buffer) { adapter.buffer_size = 0; vfree(adapter.p_buffer); } HPI_DEBUG_LOG(ERROR, "adapter_probe failed\n"); return -ENODEV; }
/** HPI_6000() * Entry point from HPIMAN * All calls to the HPI start here */ void HPI_6000(struct hpi_message *phm, struct hpi_response *phr) { struct hpi_adapter_obj *pao = NULL; if (phm->object != HPI_OBJ_SUBSYSTEM) { pao = hpi_find_adapter(phm->adapter_index); if (!pao) { hpi_init_response(phr, phm->object, phm->function, HPI_ERROR_BAD_ADAPTER_NUMBER); HPI_DEBUG_LOG(DEBUG, "invalid adapter index: %d \n", phm->adapter_index); return; } /* Don't even try to communicate with crashed DSP */ if (pao->dsp_crashed >= 10) { hpi_init_response(phr, phm->object, phm->function, HPI_ERROR_DSP_HARDWARE); HPI_DEBUG_LOG(DEBUG, "adapter %d dsp crashed\n", phm->adapter_index); return; } } /* Init default response including the size field */ if (phm->function != HPI_SUBSYS_CREATE_ADAPTER) hpi_init_response(phr, phm->object, phm->function, HPI_ERROR_PROCESSING_MESSAGE); switch (phm->type) { case HPI_TYPE_REQUEST: switch (phm->object) { case HPI_OBJ_SUBSYSTEM: subsys_message(phm, phr); break; case HPI_OBJ_ADAPTER: phr->size = sizeof(struct hpi_response_header) + sizeof(struct hpi_adapter_res); adapter_message(pao, phm, phr); break; case HPI_OBJ_CONTROL: control_message(pao, phm, phr); break; case HPI_OBJ_OSTREAM: outstream_message(pao, phm, phr); break; case HPI_OBJ_ISTREAM: instream_message(pao, phm, phr); break; default: hw_message(pao, phm, phr); break; } break; default: phr->error = HPI_ERROR_INVALID_TYPE; break; } }
/** HPI_6000() * Entry point from HPIMAN * All calls to the HPI start here */ void HPI_6000(struct hpi_message *phm, struct hpi_response *phr) { struct hpi_adapter_obj *pao = NULL; /* subsytem messages get executed by every HPI. */ /* All other messages are ignored unless the adapter index matches */ /* an adapter in the HPI */ /*HPI_DEBUG_LOG(DEBUG, "O %d,F %x\n", phm->wObject, phm->wFunction); */ /* if Dsp has crashed then do not communicate with it any more */ if (phm->object != HPI_OBJ_SUBSYSTEM) { pao = hpi_find_adapter(phm->adapter_index); if (!pao) { HPI_DEBUG_LOG(DEBUG, " %d,%d refused, for another HPI?\n", phm->object, phm->function); return; } if (pao->dsp_crashed >= 10) { hpi_init_response(phr, phm->object, phm->function, HPI_ERROR_DSP_HARDWARE); HPI_DEBUG_LOG(DEBUG, " %d,%d dsp crashed.\n", phm->object, phm->function); return; } } /* Init default response including the size field */ if (phm->function != HPI_SUBSYS_CREATE_ADAPTER) hpi_init_response(phr, phm->object, phm->function, HPI_ERROR_PROCESSING_MESSAGE); switch (phm->type) { case HPI_TYPE_MESSAGE: switch (phm->object) { case HPI_OBJ_SUBSYSTEM: subsys_message(phm, phr); break; case HPI_OBJ_ADAPTER: phr->size = sizeof(struct hpi_response_header) + sizeof(struct hpi_adapter_res); adapter_message(pao, phm, phr); break; case HPI_OBJ_CONTROL: control_message(pao, phm, phr); break; case HPI_OBJ_OSTREAM: outstream_message(pao, phm, phr); break; case HPI_OBJ_ISTREAM: instream_message(pao, phm, phr); break; default: hw_message(pao, phm, phr); break; } break; default: phr->error = HPI_ERROR_INVALID_TYPE; break; } }
int asihpi_adapter_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id) { int idx, nm, low_latency_mode = 0, irq_supported = 0; int adapter_index; unsigned int memlen; struct hpi_message hm; struct hpi_response hr; struct hpi_adapter adapter; struct hpi_pci pci; memset(&adapter, 0, sizeof(adapter)); dev_printk(KERN_DEBUG, &pci_dev->dev, "probe %04x:%04x,%04x:%04x,%04x\n", pci_dev->vendor, pci_dev->device, pci_dev->subsystem_vendor, pci_dev->subsystem_device, pci_dev->devfn); if (pci_enable_device(pci_dev) < 0) { dev_err(&pci_dev->dev, "pci_enable_device failed, disabling device\n"); return -EIO; } pci_set_master(pci_dev); /* also sets latency timer if < 16 */ hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM, HPI_SUBSYS_CREATE_ADAPTER); hpi_init_response(&hr, HPI_OBJ_SUBSYSTEM, HPI_SUBSYS_CREATE_ADAPTER, HPI_ERROR_PROCESSING_MESSAGE); hm.adapter_index = HPI_ADAPTER_INDEX_INVALID; nm = HPI_MAX_ADAPTER_MEM_SPACES; for (idx = 0; idx < nm; idx++) { HPI_DEBUG_LOG(INFO, "resource %d %pR\n", idx, &pci_dev->resource[idx]); if (pci_resource_flags(pci_dev, idx) & IORESOURCE_MEM) { memlen = pci_resource_len(pci_dev, idx); pci.ap_mem_base[idx] = ioremap(pci_resource_start(pci_dev, idx), memlen); if (!pci.ap_mem_base[idx]) { HPI_DEBUG_LOG(ERROR, "ioremap failed, aborting\n"); /* unmap previously mapped pci mem space */ goto err; } } } pci.pci_dev = pci_dev; hm.u.s.resource.bus_type = HPI_BUS_PCI; hm.u.s.resource.r.pci = &pci; /* call CreateAdapterObject on the relevant hpi module */ hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL); if (hr.error) goto err; adapter_index = hr.u.s.adapter_index; adapter.adapter = hpi_find_adapter(adapter_index); if (prealloc_stream_buf) { adapter.p_buffer = vmalloc(prealloc_stream_buf); if (!adapter.p_buffer) { HPI_DEBUG_LOG(ERROR, "HPI could not allocate " "kernel buffer size %d\n", prealloc_stream_buf); goto err; } } hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER, HPI_ADAPTER_OPEN); hm.adapter_index = adapter.adapter->index; hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL); if (hr.error) { HPI_DEBUG_LOG(ERROR, "HPI_ADAPTER_OPEN failed, aborting\n"); goto err; } /* Check if current mode == Low Latency mode */ hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER, HPI_ADAPTER_GET_MODE); hm.adapter_index = adapter.adapter->index; hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL); if (!hr.error && hr.u.ax.mode.adapter_mode == HPI_ADAPTER_MODE_LOW_LATENCY) low_latency_mode = 1; else dev_info(&pci_dev->dev, "Adapter at index %d is not in low latency mode\n", adapter.adapter->index); /* Check if IRQs are supported */ hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER, HPI_ADAPTER_GET_PROPERTY); hm.adapter_index = adapter.adapter->index; hm.u.ax.property_set.property = HPI_ADAPTER_PROPERTY_SUPPORTS_IRQ; hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL); if (hr.error || !hr.u.ax.property_get.parameter1) { dev_info(&pci_dev->dev, "IRQs not supported by adapter at index %d\n", adapter.adapter->index); } else { irq_supported = 1; } /* WARNING can't init mutex in 'adapter' * and then copy it to adapters[] ?!?! */ adapters[adapter_index] = adapter; mutex_init(&adapters[adapter_index].mutex); pci_set_drvdata(pci_dev, &adapters[adapter_index]); if (low_latency_mode && irq_supported) { if (!adapter.adapter->irq_query_and_clear) { dev_err(&pci_dev->dev, "no IRQ handler for adapter %d, aborting\n", adapter.adapter->index); goto err; } /* Disable IRQ generation on DSP side by setting the rate to 0 */ hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER, HPI_ADAPTER_SET_PROPERTY); hm.adapter_index = adapter.adapter->index; hm.u.ax.property_set.property = HPI_ADAPTER_PROPERTY_IRQ_RATE; hm.u.ax.property_set.parameter1 = 0; hm.u.ax.property_set.parameter2 = 0; hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL); if (hr.error) { HPI_DEBUG_LOG(ERROR, "HPI_ADAPTER_GET_MODE failed, aborting\n"); goto err; } /* Note: request_irq calls asihpi_isr here */ if (request_irq(pci_dev->irq, asihpi_isr, IRQF_SHARED, "asihpi", &adapters[adapter_index])) { dev_err(&pci_dev->dev, "request_irq(%d) failed\n", pci_dev->irq); goto err; } adapters[adapter_index].interrupt_mode = 1; dev_info(&pci_dev->dev, "using irq %d\n", pci_dev->irq); adapters[adapter_index].irq = pci_dev->irq; } else { dev_info(&pci_dev->dev, "using polled mode\n"); } dev_info(&pci_dev->dev, "probe succeeded for ASI%04X HPI index %d\n", adapter.adapter->type, adapter_index); return 0; err: for (idx = 0; idx < HPI_MAX_ADAPTER_MEM_SPACES; idx++) { if (pci.ap_mem_base[idx]) { iounmap(pci.ap_mem_base[idx]); pci.ap_mem_base[idx] = NULL; } } if (adapter.p_buffer) { adapter.buffer_size = 0; vfree(adapter.p_buffer); } HPI_DEBUG_LOG(ERROR, "adapter_probe failed\n"); return -ENODEV; }
/* create an adapter object and initialise it based on resource information * passed in in the message * NOTE - you cannot use this function AND the FindAdapters function at the * same time, the application must use only one of them to get the adapters */ static void subsys_create_adapter(struct hpi_message *phm, struct hpi_response *phr) { /* create temp adapter obj, because we don't know what index yet */ struct hpi_adapter_obj ao; struct hpi_adapter_obj *pao; u32 os_error_code; short error = 0; u32 dsp_index = 0; HPI_DEBUG_LOG(VERBOSE, "subsys_create_adapter\n"); memset(&ao, 0, sizeof(ao)); /* this HPI only creates adapters for TI/PCI2040 based devices */ if (phm->u.s.resource.bus_type != HPI_BUS_PCI) return; if (phm->u.s.resource.r.pci->vendor_id != HPI_PCI_VENDOR_ID_TI) return; if (phm->u.s.resource.r.pci->device_id != HPI_PCI_DEV_ID_PCI2040) return; ao.priv = kzalloc(sizeof(struct hpi_hw_obj), GFP_KERNEL); if (!ao.priv) { HPI_DEBUG_LOG(ERROR, "cant get mem for adapter object\n"); phr->error = HPI_ERROR_MEMORY_ALLOC; return; } /* create the adapter object based on the resource information */ /*? memcpy(&ao.Pci,&phm->u.s.Resource.r.Pci,sizeof(ao.Pci)); */ ao.pci = *phm->u.s.resource.r.pci; error = create_adapter_obj(&ao, &os_error_code); if (!error) error = hpi_add_adapter(&ao); if (error) { phr->u.s.data = os_error_code; kfree(ao.priv); phr->error = error; return; } /* need to update paParentAdapter */ pao = hpi_find_adapter(ao.index); if (!pao) { /* We just added this adapter, why can't we find it!? */ HPI_DEBUG_LOG(ERROR, "lost adapter after boot\n"); phr->error = 950; return; } for (dsp_index = 0; dsp_index < MAX_DSPS; dsp_index++) { struct hpi_hw_obj *phw = (struct hpi_hw_obj *)pao->priv; phw->ado[dsp_index].pa_parent_adapter = pao; } phr->u.s.aw_adapter_list[ao.index] = ao.adapter_type; phr->u.s.adapter_index = ao.index; phr->u.s.num_adapters++; phr->error = 0; }