]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/misc/mic/host/mic_intr.c
71a7521cf1a42305b2b9fd80e313afb61601c3ee
[karo-tx-linux.git] / drivers / misc / mic / host / mic_intr.c
1 /*
2  * Intel MIC Platform Software Stack (MPSS)
3  *
4  * Copyright(c) 2013 Intel Corporation.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License, version 2, as
8  * published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * General Public License for more details.
14  *
15  * The full GNU General Public License is included in this distribution in
16  * the file called "COPYING".
17  *
18  * Intel MIC Host driver.
19  *
20  */
21 #include <linux/pci.h>
22 #include <linux/interrupt.h>
23
24 #include "../common/mic_dev.h"
25 #include "mic_device.h"
26
27 /*
28  * mic_invoke_callback - Invoke callback functions registered for
29  * the corresponding source id.
30  *
31  * @mdev: pointer to the mic_device instance
32  * @idx: The interrupt source id.
33  *
34  * Returns none.
35  */
36 static inline void mic_invoke_callback(struct mic_device *mdev, int idx)
37 {
38         struct mic_intr_cb *intr_cb;
39         struct pci_dev *pdev = container_of(mdev->sdev->parent,
40                 struct pci_dev, dev);
41
42         spin_lock(&mdev->irq_info.mic_intr_lock);
43         list_for_each_entry(intr_cb, &mdev->irq_info.cb_list[idx], list)
44                 if (intr_cb->func)
45                         intr_cb->func(pdev->irq, intr_cb->data);
46         spin_unlock(&mdev->irq_info.mic_intr_lock);
47 }
48
49 /**
50  * mic_interrupt - Generic interrupt handler for
51  * MSI and INTx based interrupts.
52  */
53 static irqreturn_t mic_interrupt(int irq, void *dev)
54 {
55         struct mic_device *mdev = dev;
56         struct mic_intr_info *info = mdev->intr_info;
57         u32 mask;
58         int i;
59
60         mask = mdev->ops->ack_interrupt(mdev);
61         if (!mask)
62                 return IRQ_NONE;
63
64         for (i = info->intr_start_idx[MIC_INTR_DB];
65                         i < info->intr_len[MIC_INTR_DB]; i++)
66                 if (mask & BIT(i))
67                         mic_invoke_callback(mdev, i);
68
69         return IRQ_HANDLED;
70 }
71
72 /* Return the interrupt offset from the index. Index is 0 based. */
73 static u16 mic_map_src_to_offset(struct mic_device *mdev,
74                 int intr_src, enum mic_intr_type type) {
75
76         if (type >= MIC_NUM_INTR_TYPES)
77                 return MIC_NUM_OFFSETS;
78         if (intr_src >= mdev->intr_info->intr_len[type])
79                 return MIC_NUM_OFFSETS;
80
81         return mdev->intr_info->intr_start_idx[type] + intr_src;
82 }
83
84 /* Return next available msix_entry. */
85 static struct msix_entry *mic_get_available_vector(struct mic_device *mdev)
86 {
87         int i;
88         struct mic_irq_info *info = &mdev->irq_info;
89
90         for (i = 0; i < info->num_vectors; i++)
91                 if (!info->mic_msi_map[i])
92                         return &info->msix_entries[i];
93         return NULL;
94 }
95
96 /**
97  * mic_register_intr_callback - Register a callback handler for the
98  * given source id.
99  *
100  * @mdev: pointer to the mic_device instance
101  * @idx: The source id to be registered.
102  * @func: The function to be called when the source id receives
103  * the interrupt.
104  * @data: Private data of the requester.
105  * Return the callback structure that was registered or an
106  * appropriate error on failure.
107  */
108 static struct mic_intr_cb *mic_register_intr_callback(struct mic_device *mdev,
109                         u8 idx, irqreturn_t (*func) (int irq, void *dev),
110                         void *data)
111 {
112         struct mic_intr_cb *intr_cb;
113         unsigned long flags;
114         int rc;
115         intr_cb = kmalloc(sizeof(struct mic_intr_cb), GFP_KERNEL);
116
117         if (!intr_cb)
118                 return ERR_PTR(-ENOMEM);
119
120         intr_cb->func = func;
121         intr_cb->data = data;
122         intr_cb->cb_id = ida_simple_get(&mdev->irq_info.cb_ida,
123                 0, 0, GFP_KERNEL);
124         if (intr_cb->cb_id < 0) {
125                 rc = intr_cb->cb_id;
126                 goto ida_fail;
127         }
128
129         spin_lock_irqsave(&mdev->irq_info.mic_intr_lock, flags);
130         list_add_tail(&intr_cb->list, &mdev->irq_info.cb_list[idx]);
131         spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock, flags);
132
133         return intr_cb;
134 ida_fail:
135         kfree(intr_cb);
136         return ERR_PTR(rc);
137 }
138
139 /**
140  * mic_unregister_intr_callback - Unregister the callback handler
141  * identified by its callback id.
142  *
143  * @mdev: pointer to the mic_device instance
144  * @idx: The callback structure id to be unregistered.
145  * Return the source id that was unregistered or MIC_NUM_OFFSETS if no
146  * such callback handler was found.
147  */
148 static u8 mic_unregister_intr_callback(struct mic_device *mdev, u32 idx)
149 {
150         struct list_head *pos, *tmp;
151         struct mic_intr_cb *intr_cb;
152         unsigned long flags;
153         int i;
154
155         for (i = 0;  i < MIC_NUM_OFFSETS; i++) {
156                 spin_lock_irqsave(&mdev->irq_info.mic_intr_lock, flags);
157                 list_for_each_safe(pos, tmp, &mdev->irq_info.cb_list[i]) {
158                         intr_cb = list_entry(pos, struct mic_intr_cb, list);
159                         if (intr_cb->cb_id == idx) {
160                                 list_del(pos);
161                                 ida_simple_remove(&mdev->irq_info.cb_ida,
162                                         intr_cb->cb_id);
163                                 kfree(intr_cb);
164                                 spin_unlock_irqrestore(
165                                         &mdev->irq_info.mic_intr_lock, flags);
166                                 return i;
167                         }
168                 }
169                 spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock, flags);
170         }
171         return MIC_NUM_OFFSETS;
172 }
173
174 /**
175  * mic_setup_msix - Initializes MSIx interrupts.
176  *
177  * @mdev: pointer to mic_device instance
178  *
179  *
180  * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
181  */
182 static int mic_setup_msix(struct mic_device *mdev, struct pci_dev *pdev)
183 {
184         int rc, i;
185
186         mdev->irq_info.msix_entries = kmalloc(sizeof(struct msix_entry) *
187                         MIC_MIN_MSIX, GFP_KERNEL);
188         if (!mdev->irq_info.msix_entries) {
189                 rc = -ENOMEM;
190                 goto err_nomem1;
191         }
192
193         for (i = 0; i < MIC_MIN_MSIX; i++)
194                 mdev->irq_info.msix_entries[i].entry = i;
195
196         rc = pci_enable_msix(pdev, mdev->irq_info.msix_entries,
197                 MIC_MIN_MSIX);
198         if (rc) {
199                 dev_dbg(&pdev->dev, "Error enabling MSIx. rc = %d\n", rc);
200                 goto err_enable_msix;
201         }
202
203         mdev->irq_info.num_vectors = MIC_MIN_MSIX;
204         mdev->irq_info.mic_msi_map = kzalloc((sizeof(u32) *
205                 mdev->irq_info.num_vectors), GFP_KERNEL);
206
207         if (!mdev->irq_info.mic_msi_map) {
208                 rc = -ENOMEM;
209                 goto err_nomem2;
210         }
211
212         dev_dbg(mdev->sdev->parent,
213                 "%d MSIx irqs setup\n", mdev->irq_info.num_vectors);
214         return 0;
215 err_nomem2:
216         pci_disable_msix(pdev);
217 err_enable_msix:
218         kfree(mdev->irq_info.msix_entries);
219 err_nomem1:
220         mdev->irq_info.num_vectors = 0;
221         return rc;
222 }
223
224 /**
225  * mic_setup_callbacks - Initialize data structures needed
226  * to handle callbacks.
227  *
228  * @mdev: pointer to mic_device instance
229  */
230 static int mic_setup_callbacks(struct mic_device *mdev)
231 {
232         int i;
233
234         mdev->irq_info.cb_list = kmalloc(sizeof(struct list_head) *
235                 MIC_NUM_OFFSETS, GFP_KERNEL);
236         if (!mdev->irq_info.cb_list)
237                 return -ENOMEM;
238
239         for (i = 0; i < MIC_NUM_OFFSETS; i++)
240                 INIT_LIST_HEAD(&mdev->irq_info.cb_list[i]);
241         ida_init(&mdev->irq_info.cb_ida);
242         spin_lock_init(&mdev->irq_info.mic_intr_lock);
243         return 0;
244 }
245
246 /**
247  * mic_release_callbacks - Uninitialize data structures needed
248  * to handle callbacks.
249  *
250  * @mdev: pointer to mic_device instance
251  */
252 static void mic_release_callbacks(struct mic_device *mdev)
253 {
254         unsigned long flags;
255         struct list_head *pos, *tmp;
256         struct mic_intr_cb *intr_cb;
257         int i;
258
259         for (i = 0; i < MIC_NUM_OFFSETS; i++) {
260                 spin_lock_irqsave(&mdev->irq_info.mic_intr_lock, flags);
261
262                 if (list_empty(&mdev->irq_info.cb_list[i])) {
263                         spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock,
264                                 flags);
265                         break;
266                 }
267
268                 list_for_each_safe(pos, tmp, &mdev->irq_info.cb_list[i]) {
269                         intr_cb = list_entry(pos, struct mic_intr_cb, list);
270                         list_del(pos);
271                         ida_simple_remove(&mdev->irq_info.cb_ida,
272                                 intr_cb->cb_id);
273                         kfree(intr_cb);
274                 }
275                 spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock, flags);
276         }
277         ida_destroy(&mdev->irq_info.cb_ida);
278         kfree(mdev->irq_info.cb_list);
279 }
280
281 /**
282  * mic_setup_msi - Initializes MSI interrupts.
283  *
284  * @mdev: pointer to mic_device instance
285  * @pdev: PCI device structure
286  *
287  * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
288  */
289 static int mic_setup_msi(struct mic_device *mdev, struct pci_dev *pdev)
290 {
291         int rc;
292
293         rc = pci_enable_msi(pdev);
294         if (rc) {
295                 dev_dbg(&pdev->dev, "Error enabling MSI. rc = %d\n", rc);
296                 return rc;
297         }
298
299         mdev->irq_info.num_vectors = 1;
300         mdev->irq_info.mic_msi_map = kzalloc((sizeof(u32) *
301                 mdev->irq_info.num_vectors), GFP_KERNEL);
302
303         if (!mdev->irq_info.mic_msi_map) {
304                 rc = -ENOMEM;
305                 goto err_nomem1;
306         }
307
308         rc = mic_setup_callbacks(mdev);
309         if (rc) {
310                 dev_err(&pdev->dev, "Error setting up callbacks\n");
311                 goto err_nomem2;
312         }
313
314         rc = request_irq(pdev->irq, mic_interrupt, 0 , "mic-msi", mdev);
315         if (rc) {
316                 dev_err(&pdev->dev, "Error allocating MSI interrupt\n");
317                 goto err_irq_req_fail;
318         }
319
320         dev_dbg(&pdev->dev, "%d MSI irqs setup\n", mdev->irq_info.num_vectors);
321         return 0;
322 err_irq_req_fail:
323         mic_release_callbacks(mdev);
324 err_nomem2:
325         kfree(mdev->irq_info.mic_msi_map);
326 err_nomem1:
327         pci_disable_msi(pdev);
328         mdev->irq_info.num_vectors = 0;
329         return rc;
330 }
331
332 /**
333  * mic_setup_intx - Initializes legacy interrupts.
334  *
335  * @mdev: pointer to mic_device instance
336  * @pdev: PCI device structure
337  *
338  * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
339  */
340 static int mic_setup_intx(struct mic_device *mdev, struct pci_dev *pdev)
341 {
342         int rc;
343
344         pci_msi_off(pdev);
345
346         /* Enable intx */
347         pci_intx(pdev, 1);
348         rc = mic_setup_callbacks(mdev);
349         if (rc) {
350                 dev_err(&pdev->dev, "Error setting up callbacks\n");
351                 goto err_nomem;
352         }
353
354         rc = request_irq(pdev->irq, mic_interrupt,
355                 IRQF_SHARED, "mic-intx", mdev);
356         if (rc)
357                 goto err;
358
359         dev_dbg(&pdev->dev, "intx irq setup\n");
360         return 0;
361 err:
362         mic_release_callbacks(mdev);
363 err_nomem:
364         return rc;
365 }
366
367 /**
368  * mic_next_db - Retrieve the next doorbell interrupt source id.
369  * The id is picked sequentially from the available pool of
370  * doorlbell ids.
371  *
372  * @mdev: pointer to the mic_device instance.
373  *
374  * Returns the next doorbell interrupt source.
375  */
376 int mic_next_db(struct mic_device *mdev)
377 {
378         int next_db;
379
380         next_db = mdev->irq_info.next_avail_src %
381                 mdev->intr_info->intr_len[MIC_INTR_DB];
382         mdev->irq_info.next_avail_src++;
383         return next_db;
384 }
385
386 #define COOKIE_ID_SHIFT 16
387 #define GET_ENTRY(cookie) ((cookie) & 0xFFFF)
388 #define GET_OFFSET(cookie) ((cookie) >> COOKIE_ID_SHIFT)
389 #define MK_COOKIE(x, y) ((x) | (y) << COOKIE_ID_SHIFT)
390
391 /**
392  * mic_request_irq - request an irq. mic_mutex needs
393  * to be held before calling this function.
394  *
395  * @mdev: pointer to mic_device instance
396  * @func: The callback function that handles the interrupt.
397  * The function needs to call ack_interrupts
398  * (mdev->ops->ack_interrupt(mdev)) when handling the interrupts.
399  * @name: The ASCII name of the callee requesting the irq.
400  * @data: private data that is returned back when calling the
401  * function handler.
402  * @intr_src: The source id of the requester. Its the doorbell id
403  * for Doorbell interrupts and DMA channel id for DMA interrupts.
404  * @type: The type of interrupt. Values defined in mic_intr_type
405  *
406  * returns: The cookie that is transparent to the caller. Passed
407  * back when calling mic_free_irq. An appropriate error code
408  * is returned on failure. Caller needs to use IS_ERR(return_val)
409  * to check for failure and PTR_ERR(return_val) to obtained the
410  * error code.
411  *
412  */
413 struct mic_irq *mic_request_irq(struct mic_device *mdev,
414         irqreturn_t (*func)(int irq, void *dev),
415         const char *name, void *data, int intr_src,
416         enum mic_intr_type type)
417 {
418         u16 offset;
419         int rc = 0;
420         struct msix_entry *msix = NULL;
421         unsigned long cookie = 0;
422         u16 entry;
423         struct mic_intr_cb *intr_cb;
424         struct pci_dev *pdev = container_of(mdev->sdev->parent,
425                 struct pci_dev, dev);
426
427         offset = mic_map_src_to_offset(mdev, intr_src, type);
428         if (offset >= MIC_NUM_OFFSETS) {
429                 dev_err(mdev->sdev->parent,
430                                 "Error mapping index %d to a valid source id.\n",
431                                 intr_src);
432                 rc = -EINVAL;
433                 goto err;
434         }
435
436         if (mdev->irq_info.num_vectors > 1) {
437                 msix = mic_get_available_vector(mdev);
438                 if (!msix) {
439                         dev_err(mdev->sdev->parent,
440                         "No MSIx vectors available for use.\n");
441                         rc = -ENOSPC;
442                         goto err;
443                 }
444
445                 rc = request_irq(msix->vector, func, 0, name, data);
446                 if (rc) {
447                         dev_dbg(mdev->sdev->parent,
448                                 "request irq failed rc = %d\n", rc);
449                         goto err;
450                 }
451                 entry = msix->entry;
452                 mdev->irq_info.mic_msi_map[entry] |= BIT(offset);
453                 mdev->intr_ops->program_msi_to_src_map(mdev,
454                                 entry, offset, true);
455                 cookie = MK_COOKIE(entry, offset);
456                 dev_dbg(mdev->sdev->parent, "irq: %d assigned for src: %d\n",
457                         msix->vector, intr_src);
458         } else {
459                 intr_cb = mic_register_intr_callback(mdev,
460                                 offset, func, data);
461                 if (IS_ERR(intr_cb)) {
462                         dev_err(mdev->sdev->parent,
463                         "No available callback entries for use\n");
464                         rc = PTR_ERR(intr_cb);
465                         goto err;
466                 }
467
468                 entry = 0;
469                 if (pci_dev_msi_enabled(pdev)) {
470                         mdev->irq_info.mic_msi_map[entry] |= (1 << offset);
471                         mdev->intr_ops->program_msi_to_src_map(mdev,
472                                 entry, offset, true);
473                 }
474                 cookie = MK_COOKIE(entry, intr_cb->cb_id);
475                 dev_dbg(mdev->sdev->parent, "callback %d registered for src: %d\n",
476                         intr_cb->cb_id, intr_src);
477         }
478         return (struct mic_irq *)cookie;
479 err:
480         return ERR_PTR(rc);
481 }
482
483 /**
484  * mic_free_irq - free irq. mic_mutex
485  *  needs to be held before calling this function.
486  *
487  * @mdev: pointer to mic_device instance
488  * @cookie: cookie obtained during a successful call to mic_request_irq
489  * @data: private data specified by the calling function during the
490  * mic_request_irq
491  *
492  * returns: none.
493  */
494 void mic_free_irq(struct mic_device *mdev,
495         struct mic_irq *cookie, void *data)
496 {
497         u32 offset;
498         u32 entry;
499         u8 src_id;
500         unsigned int irq;
501         struct pci_dev *pdev = container_of(mdev->sdev->parent,
502                 struct pci_dev, dev);
503
504         entry = GET_ENTRY((unsigned long)cookie);
505         offset = GET_OFFSET((unsigned long)cookie);
506         if (mdev->irq_info.num_vectors > 1) {
507                 if (entry >= mdev->irq_info.num_vectors) {
508                         dev_warn(mdev->sdev->parent,
509                                 "entry %d should be < num_irq %d\n",
510                                 entry, mdev->irq_info.num_vectors);
511                         return;
512                 }
513                 irq = mdev->irq_info.msix_entries[entry].vector;
514                 free_irq(irq, data);
515                 mdev->irq_info.mic_msi_map[entry] &= ~(BIT(offset));
516                 mdev->intr_ops->program_msi_to_src_map(mdev,
517                         entry, offset, false);
518
519                 dev_dbg(mdev->sdev->parent, "irq: %d freed\n", irq);
520         } else {
521                 irq = pdev->irq;
522                 src_id = mic_unregister_intr_callback(mdev, offset);
523                 if (src_id >= MIC_NUM_OFFSETS) {
524                         dev_warn(mdev->sdev->parent, "Error unregistering callback\n");
525                         return;
526                 }
527                 if (pci_dev_msi_enabled(pdev)) {
528                         mdev->irq_info.mic_msi_map[entry] &= ~(BIT(src_id));
529                         mdev->intr_ops->program_msi_to_src_map(mdev,
530                                 entry, src_id, false);
531                 }
532                 dev_dbg(mdev->sdev->parent, "callback %d unregistered for src: %d\n",
533                         offset, src_id);
534         }
535 }
536
537 /**
538  * mic_setup_interrupts - Initializes interrupts.
539  *
540  * @mdev: pointer to mic_device instance
541  * @pdev: PCI device structure
542  *
543  * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
544  */
545 int mic_setup_interrupts(struct mic_device *mdev, struct pci_dev *pdev)
546 {
547         int rc;
548
549         rc = mic_setup_msix(mdev, pdev);
550         if (!rc)
551                 goto done;
552
553         rc = mic_setup_msi(mdev, pdev);
554         if (!rc)
555                 goto done;
556
557         rc = mic_setup_intx(mdev, pdev);
558         if (rc) {
559                 dev_err(mdev->sdev->parent, "no usable interrupts\n");
560                 return rc;
561         }
562 done:
563         mdev->intr_ops->enable_interrupts(mdev);
564         return 0;
565 }
566
567 /**
568  * mic_free_interrupts - Frees interrupts setup by mic_setup_interrupts
569  *
570  * @mdev: pointer to mic_device instance
571  * @pdev: PCI device structure
572  *
573  * returns none.
574  */
575 void mic_free_interrupts(struct mic_device *mdev, struct pci_dev *pdev)
576 {
577         int i;
578
579         mdev->intr_ops->disable_interrupts(mdev);
580         if (mdev->irq_info.num_vectors > 1) {
581                 for (i = 0; i < mdev->irq_info.num_vectors; i++) {
582                         if (mdev->irq_info.mic_msi_map[i])
583                                 dev_warn(&pdev->dev, "irq %d may still be in use.\n",
584                                         mdev->irq_info.msix_entries[i].vector);
585                 }
586                 kfree(mdev->irq_info.mic_msi_map);
587                 kfree(mdev->irq_info.msix_entries);
588                 pci_disable_msix(pdev);
589         } else {
590                 if (pci_dev_msi_enabled(pdev)) {
591                         free_irq(pdev->irq, mdev);
592                         kfree(mdev->irq_info.mic_msi_map);
593                         pci_disable_msi(pdev);
594                 } else {
595                         free_irq(pdev->irq, mdev);
596                 }
597                 mic_release_callbacks(mdev);
598         }
599 }
600
601 /**
602  * mic_intr_restore - Restore MIC interrupt registers.
603  *
604  * @mdev: pointer to mic_device instance.
605  *
606  * Restore the interrupt registers to values previously
607  * stored in the SW data structures. mic_mutex needs to
608  * be held before calling this function.
609  *
610  * returns None.
611  */
612 void mic_intr_restore(struct mic_device *mdev)
613 {
614         int entry, offset;
615         struct pci_dev *pdev = container_of(mdev->sdev->parent,
616                 struct pci_dev, dev);
617
618         if (!pci_dev_msi_enabled(pdev))
619                 return;
620
621         for (entry = 0; entry < mdev->irq_info.num_vectors; entry++) {
622                 for (offset = 0; offset < MIC_NUM_OFFSETS; offset++) {
623                         if (mdev->irq_info.mic_msi_map[entry] & BIT(offset))
624                                 mdev->intr_ops->program_msi_to_src_map(mdev,
625                                         entry, offset, true);
626                 }
627         }
628 }