Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.15-rc7 429 lines 10 kB view raw
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 * Disclaimer: The codes contained in these modules may be specific to 19 * the Intel Software Development Platform codenamed: Knights Ferry, and 20 * the Intel product codenamed: Knights Corner, and are not backward 21 * compatible with other Intel products. Additionally, Intel will NOT 22 * support the codes or instruction set in future products. 23 * 24 * Intel MIC Card driver. 25 * 26 */ 27#include <linux/module.h> 28#include <linux/pci.h> 29#include <linux/interrupt.h> 30#include <linux/reboot.h> 31#include <linux/dmaengine.h> 32#include <linux/kmod.h> 33 34#include <linux/mic_common.h> 35#include "../common/mic_dev.h" 36#include "mic_device.h" 37 38static struct mic_driver *g_drv; 39 40static int __init mic_dp_init(void) 41{ 42 struct mic_driver *mdrv = g_drv; 43 struct mic_device *mdev = &mdrv->mdev; 44 struct mic_bootparam __iomem *bootparam; 45 u64 lo, hi, dp_dma_addr; 46 u32 magic; 47 48 lo = mic_read_spad(&mdrv->mdev, MIC_DPLO_SPAD); 49 hi = mic_read_spad(&mdrv->mdev, MIC_DPHI_SPAD); 50 51 dp_dma_addr = lo | (hi << 32); 52 mdrv->dp = mic_card_map(mdev, dp_dma_addr, MIC_DP_SIZE); 53 if (!mdrv->dp) { 54 dev_err(mdrv->dev, "Cannot remap Aperture BAR\n"); 55 return -ENOMEM; 56 } 57 bootparam = mdrv->dp; 58 magic = ioread32(&bootparam->magic); 59 if (MIC_MAGIC != magic) { 60 dev_err(mdrv->dev, "bootparam magic mismatch 0x%x\n", magic); 61 return -EIO; 62 } 63 return 0; 64} 65 66/* Uninitialize the device page */ 67static void mic_dp_uninit(void) 68{ 69 mic_card_unmap(&g_drv->mdev, g_drv->dp); 70} 71 72/** 73 * mic_request_card_irq - request an irq. 74 * 75 * @handler: interrupt handler passed to request_threaded_irq. 76 * @thread_fn: thread fn. passed to request_threaded_irq. 77 * @name: The ASCII name of the callee requesting the irq. 78 * @data: private data that is returned back when calling the 79 * function handler. 80 * @index: The doorbell index of the requester. 81 * 82 * returns: The cookie that is transparent to the caller. Passed 83 * back when calling mic_free_irq. An appropriate error code 84 * is returned on failure. Caller needs to use IS_ERR(return_val) 85 * to check for failure and PTR_ERR(return_val) to obtained the 86 * error code. 87 * 88 */ 89struct mic_irq * 90mic_request_card_irq(irq_handler_t handler, 91 irq_handler_t thread_fn, const char *name, 92 void *data, int index) 93{ 94 int rc = 0; 95 unsigned long cookie; 96 struct mic_driver *mdrv = g_drv; 97 98 rc = request_threaded_irq(mic_db_to_irq(mdrv, index), handler, 99 thread_fn, 0, name, data); 100 if (rc) { 101 dev_err(mdrv->dev, "request_threaded_irq failed rc = %d\n", rc); 102 goto err; 103 } 104 mdrv->irq_info.irq_usage_count[index]++; 105 cookie = index; 106 return (struct mic_irq *)cookie; 107err: 108 return ERR_PTR(rc); 109} 110 111/** 112 * mic_free_card_irq - free irq. 113 * 114 * @cookie: cookie obtained during a successful call to mic_request_threaded_irq 115 * @data: private data specified by the calling function during the 116 * mic_request_threaded_irq 117 * 118 * returns: none. 119 */ 120void mic_free_card_irq(struct mic_irq *cookie, void *data) 121{ 122 int index; 123 struct mic_driver *mdrv = g_drv; 124 125 index = (unsigned long)cookie & 0xFFFFU; 126 free_irq(mic_db_to_irq(mdrv, index), data); 127 mdrv->irq_info.irq_usage_count[index]--; 128} 129 130/** 131 * mic_next_card_db - Get the doorbell with minimum usage count. 132 * 133 * Returns the irq index. 134 */ 135int mic_next_card_db(void) 136{ 137 int i; 138 int index = 0; 139 struct mic_driver *mdrv = g_drv; 140 141 for (i = 0; i < mdrv->intr_info.num_intr; i++) { 142 if (mdrv->irq_info.irq_usage_count[i] < 143 mdrv->irq_info.irq_usage_count[index]) 144 index = i; 145 } 146 147 return index; 148} 149 150/** 151 * mic_init_irq - Initialize irq information. 152 * 153 * Returns 0 in success. Appropriate error code on failure. 154 */ 155static int mic_init_irq(void) 156{ 157 struct mic_driver *mdrv = g_drv; 158 159 mdrv->irq_info.irq_usage_count = kzalloc((sizeof(u32) * 160 mdrv->intr_info.num_intr), 161 GFP_KERNEL); 162 if (!mdrv->irq_info.irq_usage_count) 163 return -ENOMEM; 164 return 0; 165} 166 167/** 168 * mic_uninit_irq - Uninitialize irq information. 169 * 170 * None. 171 */ 172static void mic_uninit_irq(void) 173{ 174 struct mic_driver *mdrv = g_drv; 175 176 kfree(mdrv->irq_info.irq_usage_count); 177} 178 179static inline struct mic_driver *scdev_to_mdrv(struct scif_hw_dev *scdev) 180{ 181 return dev_get_drvdata(scdev->dev.parent); 182} 183 184static struct mic_irq * 185___mic_request_irq(struct scif_hw_dev *scdev, 186 irqreturn_t (*func)(int irq, void *data), 187 const char *name, void *data, 188 int db) 189{ 190 return mic_request_card_irq(func, NULL, name, data, db); 191} 192 193static void 194___mic_free_irq(struct scif_hw_dev *scdev, 195 struct mic_irq *cookie, void *data) 196{ 197 return mic_free_card_irq(cookie, data); 198} 199 200static void ___mic_ack_interrupt(struct scif_hw_dev *scdev, int num) 201{ 202 struct mic_driver *mdrv = scdev_to_mdrv(scdev); 203 204 mic_ack_interrupt(&mdrv->mdev); 205} 206 207static int ___mic_next_db(struct scif_hw_dev *scdev) 208{ 209 return mic_next_card_db(); 210} 211 212static void ___mic_send_intr(struct scif_hw_dev *scdev, int db) 213{ 214 struct mic_driver *mdrv = scdev_to_mdrv(scdev); 215 216 mic_send_intr(&mdrv->mdev, db); 217} 218 219static void ___mic_send_p2p_intr(struct scif_hw_dev *scdev, int db, 220 struct mic_mw *mw) 221{ 222 mic_send_p2p_intr(db, mw); 223} 224 225static void __iomem * 226___mic_ioremap(struct scif_hw_dev *scdev, 227 phys_addr_t pa, size_t len) 228{ 229 struct mic_driver *mdrv = scdev_to_mdrv(scdev); 230 231 return mic_card_map(&mdrv->mdev, pa, len); 232} 233 234static void ___mic_iounmap(struct scif_hw_dev *scdev, void __iomem *va) 235{ 236 struct mic_driver *mdrv = scdev_to_mdrv(scdev); 237 238 mic_card_unmap(&mdrv->mdev, va); 239} 240 241static struct scif_hw_ops scif_hw_ops = { 242 .request_irq = ___mic_request_irq, 243 .free_irq = ___mic_free_irq, 244 .ack_interrupt = ___mic_ack_interrupt, 245 .next_db = ___mic_next_db, 246 .send_intr = ___mic_send_intr, 247 .send_p2p_intr = ___mic_send_p2p_intr, 248 .ioremap = ___mic_ioremap, 249 .iounmap = ___mic_iounmap, 250}; 251 252static inline struct mic_driver *vpdev_to_mdrv(struct vop_device *vpdev) 253{ 254 return dev_get_drvdata(vpdev->dev.parent); 255} 256 257static struct mic_irq * 258__mic_request_irq(struct vop_device *vpdev, 259 irqreturn_t (*func)(int irq, void *data), 260 const char *name, void *data, int intr_src) 261{ 262 return mic_request_card_irq(func, NULL, name, data, intr_src); 263} 264 265static void __mic_free_irq(struct vop_device *vpdev, 266 struct mic_irq *cookie, void *data) 267{ 268 return mic_free_card_irq(cookie, data); 269} 270 271static void __mic_ack_interrupt(struct vop_device *vpdev, int num) 272{ 273 struct mic_driver *mdrv = vpdev_to_mdrv(vpdev); 274 275 mic_ack_interrupt(&mdrv->mdev); 276} 277 278static int __mic_next_db(struct vop_device *vpdev) 279{ 280 return mic_next_card_db(); 281} 282 283static void __iomem *__mic_get_remote_dp(struct vop_device *vpdev) 284{ 285 struct mic_driver *mdrv = vpdev_to_mdrv(vpdev); 286 287 return mdrv->dp; 288} 289 290static void __mic_send_intr(struct vop_device *vpdev, int db) 291{ 292 struct mic_driver *mdrv = vpdev_to_mdrv(vpdev); 293 294 mic_send_intr(&mdrv->mdev, db); 295} 296 297static void __iomem *__mic_ioremap(struct vop_device *vpdev, 298 dma_addr_t pa, size_t len) 299{ 300 struct mic_driver *mdrv = vpdev_to_mdrv(vpdev); 301 302 return mic_card_map(&mdrv->mdev, pa, len); 303} 304 305static void __mic_iounmap(struct vop_device *vpdev, void __iomem *va) 306{ 307 struct mic_driver *mdrv = vpdev_to_mdrv(vpdev); 308 309 mic_card_unmap(&mdrv->mdev, va); 310} 311 312static struct vop_hw_ops vop_hw_ops = { 313 .request_irq = __mic_request_irq, 314 .free_irq = __mic_free_irq, 315 .ack_interrupt = __mic_ack_interrupt, 316 .next_db = __mic_next_db, 317 .get_remote_dp = __mic_get_remote_dp, 318 .send_intr = __mic_send_intr, 319 .ioremap = __mic_ioremap, 320 .iounmap = __mic_iounmap, 321}; 322 323static int mic_request_dma_chans(struct mic_driver *mdrv) 324{ 325 dma_cap_mask_t mask; 326 struct dma_chan *chan; 327 328 dma_cap_zero(mask); 329 dma_cap_set(DMA_MEMCPY, mask); 330 331 do { 332 chan = dma_request_channel(mask, NULL, NULL); 333 if (chan) { 334 mdrv->dma_ch[mdrv->num_dma_ch++] = chan; 335 if (mdrv->num_dma_ch >= MIC_MAX_DMA_CHAN) 336 break; 337 } 338 } while (chan); 339 dev_info(mdrv->dev, "DMA channels # %d\n", mdrv->num_dma_ch); 340 return mdrv->num_dma_ch; 341} 342 343static void mic_free_dma_chans(struct mic_driver *mdrv) 344{ 345 int i = 0; 346 347 for (i = 0; i < mdrv->num_dma_ch; i++) { 348 dma_release_channel(mdrv->dma_ch[i]); 349 mdrv->dma_ch[i] = NULL; 350 } 351 mdrv->num_dma_ch = 0; 352} 353 354/* 355 * mic_driver_init - MIC driver initialization tasks. 356 * 357 * Returns 0 in success. Appropriate error code on failure. 358 */ 359int __init mic_driver_init(struct mic_driver *mdrv) 360{ 361 int rc; 362 struct mic_bootparam __iomem *bootparam; 363 u8 node_id; 364 365 g_drv = mdrv; 366 /* Unloading the card module is not supported. */ 367 if (!try_module_get(mdrv->dev->driver->owner)) { 368 rc = -ENODEV; 369 goto done; 370 } 371 rc = mic_dp_init(); 372 if (rc) 373 goto put; 374 rc = mic_init_irq(); 375 if (rc) 376 goto dp_uninit; 377 if (!mic_request_dma_chans(mdrv)) { 378 rc = -ENODEV; 379 goto irq_uninit; 380 } 381 mdrv->vpdev = vop_register_device(mdrv->dev, VOP_DEV_TRNSP, 382 NULL, &vop_hw_ops, 0, 383 NULL, mdrv->dma_ch[0]); 384 if (IS_ERR(mdrv->vpdev)) { 385 rc = PTR_ERR(mdrv->vpdev); 386 goto dma_free; 387 } 388 bootparam = mdrv->dp; 389 node_id = ioread8(&bootparam->node_id); 390 mdrv->scdev = scif_register_device(mdrv->dev, MIC_SCIF_DEV, 391 NULL, &scif_hw_ops, 392 0, node_id, &mdrv->mdev.mmio, NULL, 393 NULL, mdrv->dp, mdrv->dma_ch, 394 mdrv->num_dma_ch, true); 395 if (IS_ERR(mdrv->scdev)) { 396 rc = PTR_ERR(mdrv->scdev); 397 goto vop_remove; 398 } 399 mic_create_card_debug_dir(mdrv); 400done: 401 return rc; 402vop_remove: 403 vop_unregister_device(mdrv->vpdev); 404dma_free: 405 mic_free_dma_chans(mdrv); 406irq_uninit: 407 mic_uninit_irq(); 408dp_uninit: 409 mic_dp_uninit(); 410put: 411 module_put(mdrv->dev->driver->owner); 412 return rc; 413} 414 415/* 416 * mic_driver_uninit - MIC driver uninitialization tasks. 417 * 418 * Returns None 419 */ 420void mic_driver_uninit(struct mic_driver *mdrv) 421{ 422 mic_delete_card_debug_dir(mdrv); 423 scif_unregister_device(mdrv->scdev); 424 vop_unregister_device(mdrv->vpdev); 425 mic_free_dma_chans(mdrv); 426 mic_uninit_irq(); 427 mic_dp_uninit(); 428 module_put(mdrv->dev->driver->owner); 429}