0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #define SOURCEFILE_NAME "hpioctl.c"
0011
0012 #include "hpi_internal.h"
0013 #include "hpi_version.h"
0014 #include "hpimsginit.h"
0015 #include "hpidebug.h"
0016 #include "hpimsgx.h"
0017 #include "hpioctl.h"
0018 #include "hpicmn.h"
0019
0020 #include <linux/fs.h>
0021 #include <linux/interrupt.h>
0022 #include <linux/slab.h>
0023 #include <linux/moduleparam.h>
0024 #include <linux/uaccess.h>
0025 #include <linux/pci.h>
0026 #include <linux/stringify.h>
0027 #include <linux/module.h>
0028 #include <linux/vmalloc.h>
0029 #include <linux/nospec.h>
0030
0031 #ifdef MODULE_FIRMWARE
0032 MODULE_FIRMWARE("asihpi/dsp5000.bin");
0033 MODULE_FIRMWARE("asihpi/dsp6200.bin");
0034 MODULE_FIRMWARE("asihpi/dsp6205.bin");
0035 MODULE_FIRMWARE("asihpi/dsp6400.bin");
0036 MODULE_FIRMWARE("asihpi/dsp6600.bin");
0037 MODULE_FIRMWARE("asihpi/dsp8700.bin");
0038 MODULE_FIRMWARE("asihpi/dsp8900.bin");
0039 #endif
0040
0041 static int prealloc_stream_buf;
0042 module_param(prealloc_stream_buf, int, 0444);
0043 MODULE_PARM_DESC(prealloc_stream_buf,
0044 "Preallocate size for per-adapter stream buffer");
0045
0046
0047
0048
0049 module_param(hpi_debug_level, int, 0644);
0050 MODULE_PARM_DESC(hpi_debug_level, "debug verbosity 0..5");
0051
0052
0053 static struct hpi_adapter adapters[HPI_MAX_ADAPTERS];
0054
0055
0056
0057
0058 static void hpi_send_recv_f(struct hpi_message *phm, struct hpi_response *phr,
0059 struct file *file)
0060 {
0061 if ((phm->adapter_index >= HPI_MAX_ADAPTERS)
0062 && (phm->object != HPI_OBJ_SUBSYSTEM))
0063 phr->error = HPI_ERROR_INVALID_OBJ_INDEX;
0064 else
0065 hpi_send_recv_ex(phm, phr, file);
0066 }
0067
0068
0069
0070
0071
0072 void hpi_send_recv(struct hpi_message *phm, struct hpi_response *phr)
0073 {
0074 hpi_send_recv_f(phm, phr, HOWNER_KERNEL);
0075 }
0076
0077 EXPORT_SYMBOL(hpi_send_recv);
0078
0079
0080 int asihpi_hpi_release(struct file *file)
0081 {
0082 struct hpi_message hm;
0083 struct hpi_response hr;
0084
0085
0086
0087 hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
0088 HPI_SUBSYS_CLOSE);
0089 hpi_send_recv_ex(&hm, &hr, file);
0090 return 0;
0091 }
0092
0093 long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
0094 {
0095 struct hpi_ioctl_linux __user *phpi_ioctl_data;
0096 void __user *puhm;
0097 void __user *puhr;
0098 union hpi_message_buffer_v1 *hm;
0099 union hpi_response_buffer_v1 *hr;
0100 u16 msg_size;
0101 u16 res_max_size;
0102 u32 uncopied_bytes;
0103 int err = 0;
0104
0105 if (cmd != HPI_IOCTL_LINUX)
0106 return -EINVAL;
0107
0108 hm = kmalloc(sizeof(*hm), GFP_KERNEL);
0109 hr = kzalloc(sizeof(*hr), GFP_KERNEL);
0110 if (!hm || !hr) {
0111 err = -ENOMEM;
0112 goto out;
0113 }
0114
0115 phpi_ioctl_data = (struct hpi_ioctl_linux __user *)arg;
0116
0117
0118 if (get_user(puhm, &phpi_ioctl_data->phm)
0119 || get_user(puhr, &phpi_ioctl_data->phr)) {
0120 err = -EFAULT;
0121 goto out;
0122 }
0123
0124
0125 if (get_user(msg_size, (u16 __user *)puhm)) {
0126 err = -EFAULT;
0127 goto out;
0128 }
0129 if (msg_size > sizeof(*hm))
0130 msg_size = sizeof(*hm);
0131
0132
0133
0134 uncopied_bytes = copy_from_user(hm, puhm, msg_size);
0135 if (uncopied_bytes) {
0136 HPI_DEBUG_LOG(ERROR, "uncopied bytes %d\n", uncopied_bytes);
0137 err = -EFAULT;
0138 goto out;
0139 }
0140
0141
0142 hm->h.size = msg_size;
0143
0144 if (get_user(res_max_size, (u16 __user *)puhr)) {
0145 err = -EFAULT;
0146 goto out;
0147 }
0148
0149 if (res_max_size < sizeof(struct hpi_response_header)) {
0150 HPI_DEBUG_LOG(WARNING, "small res size %d\n", res_max_size);
0151 err = -EFAULT;
0152 goto out;
0153 }
0154
0155 res_max_size = min_t(size_t, res_max_size, sizeof(*hr));
0156
0157 switch (hm->h.function) {
0158 case HPI_SUBSYS_CREATE_ADAPTER:
0159 case HPI_ADAPTER_DELETE:
0160
0161 hr->h.size = sizeof(hr->h);
0162 hr->h.error = HPI_ERROR_INVALID_OPERATION;
0163 hr->h.function = hm->h.function;
0164 uncopied_bytes = copy_to_user(puhr, hr, hr->h.size);
0165 if (uncopied_bytes)
0166 err = -EFAULT;
0167 else
0168 err = 0;
0169 goto out;
0170 }
0171
0172 hr->h.size = res_max_size;
0173 if (hm->h.object == HPI_OBJ_SUBSYSTEM) {
0174 hpi_send_recv_f(&hm->m0, &hr->r0, file);
0175 } else {
0176 u16 __user *ptr = NULL;
0177 u32 size = 0;
0178
0179 int wrflag = -1;
0180 struct hpi_adapter *pa = NULL;
0181
0182 if (hm->h.adapter_index < ARRAY_SIZE(adapters))
0183 pa = &adapters[array_index_nospec(hm->h.adapter_index,
0184 ARRAY_SIZE(adapters))];
0185
0186 if (!pa || !pa->adapter || !pa->adapter->type) {
0187 hpi_init_response(&hr->r0, hm->h.object,
0188 hm->h.function, HPI_ERROR_BAD_ADAPTER_NUMBER);
0189
0190 uncopied_bytes =
0191 copy_to_user(puhr, hr, sizeof(hr->h));
0192 if (uncopied_bytes)
0193 err = -EFAULT;
0194 else
0195 err = 0;
0196 goto out;
0197 }
0198
0199 if (mutex_lock_interruptible(&pa->mutex)) {
0200 err = -EINTR;
0201 goto out;
0202 }
0203
0204
0205 switch (hm->h.function) {
0206 case HPI_OSTREAM_WRITE:
0207 case HPI_ISTREAM_READ:{
0208
0209 ptr = (u16 __user *)hm->m0.u.d.u.data.pb_data;
0210 size = hm->m0.u.d.u.data.data_size;
0211
0212
0213
0214
0215
0216 if (pa->buffer_size < size) {
0217 HPI_DEBUG_LOG(DEBUG,
0218 "Realloc adapter %d stream "
0219 "buffer from %zd to %d\n",
0220 hm->h.adapter_index,
0221 pa->buffer_size, size);
0222 if (pa->p_buffer) {
0223 pa->buffer_size = 0;
0224 vfree(pa->p_buffer);
0225 }
0226 pa->p_buffer = vmalloc(size);
0227 if (pa->p_buffer)
0228 pa->buffer_size = size;
0229 else {
0230 HPI_DEBUG_LOG(ERROR,
0231 "HPI could not allocate "
0232 "stream buffer size %d\n",
0233 size);
0234
0235 mutex_unlock(&pa->mutex);
0236 err = -EINVAL;
0237 goto out;
0238 }
0239 }
0240
0241 hm->m0.u.d.u.data.pb_data = pa->p_buffer;
0242 if (hm->h.function == HPI_ISTREAM_READ)
0243
0244 wrflag = 1;
0245 else
0246 wrflag = 0;
0247 break;
0248 }
0249
0250 default:
0251 size = 0;
0252 break;
0253 }
0254
0255 if (size && (wrflag == 0)) {
0256 uncopied_bytes =
0257 copy_from_user(pa->p_buffer, ptr, size);
0258 if (uncopied_bytes)
0259 HPI_DEBUG_LOG(WARNING,
0260 "Missed %d of %d "
0261 "bytes from user\n", uncopied_bytes,
0262 size);
0263 }
0264
0265 hpi_send_recv_f(&hm->m0, &hr->r0, file);
0266
0267 if (size && (wrflag == 1)) {
0268 uncopied_bytes =
0269 copy_to_user(ptr, pa->p_buffer, size);
0270 if (uncopied_bytes)
0271 HPI_DEBUG_LOG(WARNING,
0272 "Missed %d of %d " "bytes to user\n",
0273 uncopied_bytes, size);
0274 }
0275
0276 mutex_unlock(&pa->mutex);
0277 }
0278
0279
0280
0281
0282 if (!hr->h.size) {
0283 HPI_DEBUG_LOG(ERROR, "response zero size\n");
0284 err = -EFAULT;
0285 goto out;
0286 }
0287
0288 if (hr->h.size > res_max_size) {
0289 HPI_DEBUG_LOG(ERROR, "response too big %d %d\n", hr->h.size,
0290 res_max_size);
0291 hr->h.error = HPI_ERROR_RESPONSE_BUFFER_TOO_SMALL;
0292 hr->h.specific_error = hr->h.size;
0293 hr->h.size = sizeof(hr->h);
0294 }
0295
0296 uncopied_bytes = copy_to_user(puhr, hr, hr->h.size);
0297 if (uncopied_bytes) {
0298 HPI_DEBUG_LOG(ERROR, "uncopied bytes %d\n", uncopied_bytes);
0299 err = -EFAULT;
0300 goto out;
0301 }
0302
0303 out:
0304 kfree(hm);
0305 kfree(hr);
0306 return err;
0307 }
0308
0309 static int asihpi_irq_count;
0310
0311 static irqreturn_t asihpi_isr(int irq, void *dev_id)
0312 {
0313 struct hpi_adapter *a = dev_id;
0314 int handled;
0315
0316 if (!a->adapter->irq_query_and_clear) {
0317 pr_err("asihpi_isr ASI%04X:%d no handler\n", a->adapter->type,
0318 a->adapter->index);
0319 return IRQ_NONE;
0320 }
0321
0322 handled = a->adapter->irq_query_and_clear(a->adapter, 0);
0323
0324 if (!handled)
0325 return IRQ_NONE;
0326
0327 asihpi_irq_count++;
0328
0329
0330
0331 if (a->interrupt_callback)
0332 return IRQ_WAKE_THREAD;
0333
0334 return IRQ_HANDLED;
0335 }
0336
0337 static irqreturn_t asihpi_isr_thread(int irq, void *dev_id)
0338 {
0339 struct hpi_adapter *a = dev_id;
0340
0341 if (a->interrupt_callback)
0342 a->interrupt_callback(a);
0343 return IRQ_HANDLED;
0344 }
0345
0346 int asihpi_adapter_probe(struct pci_dev *pci_dev,
0347 const struct pci_device_id *pci_id)
0348 {
0349 int idx, nm, low_latency_mode = 0, irq_supported = 0;
0350 int adapter_index;
0351 unsigned int memlen;
0352 struct hpi_message hm;
0353 struct hpi_response hr;
0354 struct hpi_adapter adapter;
0355 struct hpi_pci pci = { 0 };
0356
0357 memset(&adapter, 0, sizeof(adapter));
0358
0359 dev_printk(KERN_DEBUG, &pci_dev->dev,
0360 "probe %04x:%04x,%04x:%04x,%04x\n", pci_dev->vendor,
0361 pci_dev->device, pci_dev->subsystem_vendor,
0362 pci_dev->subsystem_device, pci_dev->devfn);
0363
0364 if (pci_enable_device(pci_dev) < 0) {
0365 dev_err(&pci_dev->dev,
0366 "pci_enable_device failed, disabling device\n");
0367 return -EIO;
0368 }
0369
0370 pci_set_master(pci_dev);
0371
0372 hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
0373 HPI_SUBSYS_CREATE_ADAPTER);
0374 hpi_init_response(&hr, HPI_OBJ_SUBSYSTEM, HPI_SUBSYS_CREATE_ADAPTER,
0375 HPI_ERROR_PROCESSING_MESSAGE);
0376
0377 hm.adapter_index = HPI_ADAPTER_INDEX_INVALID;
0378
0379 nm = HPI_MAX_ADAPTER_MEM_SPACES;
0380
0381 for (idx = 0; idx < nm; idx++) {
0382 HPI_DEBUG_LOG(INFO, "resource %d %pR\n", idx,
0383 &pci_dev->resource[idx]);
0384
0385 if (pci_resource_flags(pci_dev, idx) & IORESOURCE_MEM) {
0386 memlen = pci_resource_len(pci_dev, idx);
0387 pci.ap_mem_base[idx] =
0388 ioremap(pci_resource_start(pci_dev, idx),
0389 memlen);
0390 if (!pci.ap_mem_base[idx]) {
0391 HPI_DEBUG_LOG(ERROR,
0392 "ioremap failed, aborting\n");
0393
0394 goto err;
0395 }
0396 }
0397 }
0398
0399 pci.pci_dev = pci_dev;
0400 hm.u.s.resource.bus_type = HPI_BUS_PCI;
0401 hm.u.s.resource.r.pci = &pci;
0402
0403
0404 hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL);
0405 if (hr.error)
0406 goto err;
0407
0408 adapter_index = hr.u.s.adapter_index;
0409 adapter.adapter = hpi_find_adapter(adapter_index);
0410
0411 if (prealloc_stream_buf) {
0412 adapter.p_buffer = vmalloc(prealloc_stream_buf);
0413 if (!adapter.p_buffer) {
0414 HPI_DEBUG_LOG(ERROR,
0415 "HPI could not allocate "
0416 "kernel buffer size %d\n",
0417 prealloc_stream_buf);
0418 goto err;
0419 }
0420 }
0421
0422 hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
0423 HPI_ADAPTER_OPEN);
0424 hm.adapter_index = adapter.adapter->index;
0425 hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL);
0426
0427 if (hr.error) {
0428 HPI_DEBUG_LOG(ERROR, "HPI_ADAPTER_OPEN failed, aborting\n");
0429 goto err;
0430 }
0431
0432
0433 hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
0434 HPI_ADAPTER_GET_MODE);
0435 hm.adapter_index = adapter.adapter->index;
0436 hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL);
0437
0438 if (!hr.error
0439 && hr.u.ax.mode.adapter_mode == HPI_ADAPTER_MODE_LOW_LATENCY)
0440 low_latency_mode = 1;
0441 else
0442 dev_info(&pci_dev->dev,
0443 "Adapter at index %d is not in low latency mode\n",
0444 adapter.adapter->index);
0445
0446
0447 hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
0448 HPI_ADAPTER_GET_PROPERTY);
0449 hm.adapter_index = adapter.adapter->index;
0450 hm.u.ax.property_set.property = HPI_ADAPTER_PROPERTY_SUPPORTS_IRQ;
0451 hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL);
0452 if (hr.error || !hr.u.ax.property_get.parameter1) {
0453 dev_info(&pci_dev->dev,
0454 "IRQs not supported by adapter at index %d\n",
0455 adapter.adapter->index);
0456 } else {
0457 irq_supported = 1;
0458 }
0459
0460
0461
0462
0463 adapters[adapter_index] = adapter;
0464 mutex_init(&adapters[adapter_index].mutex);
0465 pci_set_drvdata(pci_dev, &adapters[adapter_index]);
0466
0467 if (low_latency_mode && irq_supported) {
0468 if (!adapter.adapter->irq_query_and_clear) {
0469 dev_err(&pci_dev->dev,
0470 "no IRQ handler for adapter %d, aborting\n",
0471 adapter.adapter->index);
0472 goto err;
0473 }
0474
0475
0476 hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
0477 HPI_ADAPTER_SET_PROPERTY);
0478 hm.adapter_index = adapter.adapter->index;
0479 hm.u.ax.property_set.property = HPI_ADAPTER_PROPERTY_IRQ_RATE;
0480 hm.u.ax.property_set.parameter1 = 0;
0481 hm.u.ax.property_set.parameter2 = 0;
0482 hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL);
0483 if (hr.error) {
0484 HPI_DEBUG_LOG(ERROR,
0485 "HPI_ADAPTER_GET_MODE failed, aborting\n");
0486 goto err;
0487 }
0488
0489
0490 if (request_threaded_irq(pci_dev->irq, asihpi_isr,
0491 asihpi_isr_thread, IRQF_SHARED,
0492 "asihpi", &adapters[adapter_index])) {
0493 dev_err(&pci_dev->dev, "request_irq(%d) failed\n",
0494 pci_dev->irq);
0495 goto err;
0496 }
0497
0498 adapters[adapter_index].interrupt_mode = 1;
0499
0500 dev_info(&pci_dev->dev, "using irq %d\n", pci_dev->irq);
0501 adapters[adapter_index].irq = pci_dev->irq;
0502 } else {
0503 dev_info(&pci_dev->dev, "using polled mode\n");
0504 }
0505
0506 dev_info(&pci_dev->dev, "probe succeeded for ASI%04X HPI index %d\n",
0507 adapter.adapter->type, adapter_index);
0508
0509 return 0;
0510
0511 err:
0512 while (--idx >= 0) {
0513 if (pci.ap_mem_base[idx]) {
0514 iounmap(pci.ap_mem_base[idx]);
0515 pci.ap_mem_base[idx] = NULL;
0516 }
0517 }
0518
0519 if (adapter.p_buffer) {
0520 adapter.buffer_size = 0;
0521 vfree(adapter.p_buffer);
0522 }
0523
0524 HPI_DEBUG_LOG(ERROR, "adapter_probe failed\n");
0525 return -ENODEV;
0526 }
0527
0528 void asihpi_adapter_remove(struct pci_dev *pci_dev)
0529 {
0530 int idx;
0531 struct hpi_message hm;
0532 struct hpi_response hr;
0533 struct hpi_adapter *pa;
0534 struct hpi_pci pci;
0535
0536 pa = pci_get_drvdata(pci_dev);
0537 pci = pa->adapter->pci;
0538
0539
0540 hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
0541 HPI_ADAPTER_SET_PROPERTY);
0542 hm.adapter_index = pa->adapter->index;
0543 hm.u.ax.property_set.property = HPI_ADAPTER_PROPERTY_IRQ_RATE;
0544 hm.u.ax.property_set.parameter1 = 0;
0545 hm.u.ax.property_set.parameter2 = 0;
0546 hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL);
0547
0548 hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
0549 HPI_ADAPTER_DELETE);
0550 hm.adapter_index = pa->adapter->index;
0551 hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL);
0552
0553
0554 for (idx = 0; idx < HPI_MAX_ADAPTER_MEM_SPACES; ++idx)
0555 iounmap(pci.ap_mem_base[idx]);
0556
0557 if (pa->irq)
0558 free_irq(pa->irq, pa);
0559
0560 vfree(pa->p_buffer);
0561
0562 if (1)
0563 dev_info(&pci_dev->dev,
0564 "remove %04x:%04x,%04x:%04x,%04x, HPI index %d\n",
0565 pci_dev->vendor, pci_dev->device,
0566 pci_dev->subsystem_vendor, pci_dev->subsystem_device,
0567 pci_dev->devfn, pa->adapter->index);
0568
0569 memset(pa, 0, sizeof(*pa));
0570 }
0571
0572 void __init asihpi_init(void)
0573 {
0574 struct hpi_message hm;
0575 struct hpi_response hr;
0576
0577 memset(adapters, 0, sizeof(adapters));
0578
0579 printk(KERN_INFO "ASIHPI driver " HPI_VER_STRING "\n");
0580
0581 hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
0582 HPI_SUBSYS_DRIVER_LOAD);
0583 hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL);
0584 }
0585
0586 void asihpi_exit(void)
0587 {
0588 struct hpi_message hm;
0589 struct hpi_response hr;
0590
0591 hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
0592 HPI_SUBSYS_DRIVER_UNLOAD);
0593 hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL);
0594 }