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

Configure Feed

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

at v4.4-rc3 386 lines 9.8 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 * Intel MIC Host driver. 19 */ 20#include <linux/fs.h> 21#include <linux/module.h> 22#include <linux/pci.h> 23#include <linux/poll.h> 24 25#include <linux/mic_common.h> 26#include "../common/mic_dev.h" 27#include "mic_device.h" 28#include "mic_x100.h" 29#include "mic_smpt.h" 30#include "mic_fops.h" 31#include "mic_virtio.h" 32 33static const char mic_driver_name[] = "mic"; 34 35static const struct pci_device_id mic_pci_tbl[] = { 36 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2250)}, 37 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2251)}, 38 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2252)}, 39 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2253)}, 40 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2254)}, 41 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2255)}, 42 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2256)}, 43 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2257)}, 44 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2258)}, 45 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2259)}, 46 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_225a)}, 47 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_225b)}, 48 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_225c)}, 49 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_225d)}, 50 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_225e)}, 51 52 /* required last entry */ 53 { 0, } 54}; 55 56MODULE_DEVICE_TABLE(pci, mic_pci_tbl); 57 58/* ID allocator for MIC devices */ 59static struct ida g_mic_ida; 60/* Base device node number for MIC devices */ 61static dev_t g_mic_devno; 62 63static const struct file_operations mic_fops = { 64 .open = mic_open, 65 .release = mic_release, 66 .unlocked_ioctl = mic_ioctl, 67 .poll = mic_poll, 68 .mmap = mic_mmap, 69 .owner = THIS_MODULE, 70}; 71 72/* Initialize the device page */ 73static int mic_dp_init(struct mic_device *mdev) 74{ 75 mdev->dp = kzalloc(MIC_DP_SIZE, GFP_KERNEL); 76 if (!mdev->dp) 77 return -ENOMEM; 78 79 mdev->dp_dma_addr = mic_map_single(mdev, 80 mdev->dp, MIC_DP_SIZE); 81 if (mic_map_error(mdev->dp_dma_addr)) { 82 kfree(mdev->dp); 83 dev_err(&mdev->pdev->dev, "%s %d err %d\n", 84 __func__, __LINE__, -ENOMEM); 85 return -ENOMEM; 86 } 87 mdev->ops->write_spad(mdev, MIC_DPLO_SPAD, mdev->dp_dma_addr); 88 mdev->ops->write_spad(mdev, MIC_DPHI_SPAD, mdev->dp_dma_addr >> 32); 89 return 0; 90} 91 92/* Uninitialize the device page */ 93static void mic_dp_uninit(struct mic_device *mdev) 94{ 95 mic_unmap_single(mdev, mdev->dp_dma_addr, MIC_DP_SIZE); 96 kfree(mdev->dp); 97} 98 99/** 100 * mic_ops_init: Initialize HW specific operation tables. 101 * 102 * @mdev: pointer to mic_device instance 103 * 104 * returns none. 105 */ 106static void mic_ops_init(struct mic_device *mdev) 107{ 108 switch (mdev->family) { 109 case MIC_FAMILY_X100: 110 mdev->ops = &mic_x100_ops; 111 mdev->intr_ops = &mic_x100_intr_ops; 112 mdev->smpt_ops = &mic_x100_smpt_ops; 113 break; 114 default: 115 break; 116 } 117} 118 119/** 120 * mic_get_family - Determine hardware family to which this MIC belongs. 121 * 122 * @pdev: The pci device structure 123 * 124 * returns family. 125 */ 126static enum mic_hw_family mic_get_family(struct pci_dev *pdev) 127{ 128 enum mic_hw_family family; 129 130 switch (pdev->device) { 131 case MIC_X100_PCI_DEVICE_2250: 132 case MIC_X100_PCI_DEVICE_2251: 133 case MIC_X100_PCI_DEVICE_2252: 134 case MIC_X100_PCI_DEVICE_2253: 135 case MIC_X100_PCI_DEVICE_2254: 136 case MIC_X100_PCI_DEVICE_2255: 137 case MIC_X100_PCI_DEVICE_2256: 138 case MIC_X100_PCI_DEVICE_2257: 139 case MIC_X100_PCI_DEVICE_2258: 140 case MIC_X100_PCI_DEVICE_2259: 141 case MIC_X100_PCI_DEVICE_225a: 142 case MIC_X100_PCI_DEVICE_225b: 143 case MIC_X100_PCI_DEVICE_225c: 144 case MIC_X100_PCI_DEVICE_225d: 145 case MIC_X100_PCI_DEVICE_225e: 146 family = MIC_FAMILY_X100; 147 break; 148 default: 149 family = MIC_FAMILY_UNKNOWN; 150 break; 151 } 152 return family; 153} 154 155/** 156 * mic_device_init - Allocates and initializes the MIC device structure 157 * 158 * @mdev: pointer to mic_device instance 159 * @pdev: The pci device structure 160 * 161 * returns none. 162 */ 163static void 164mic_device_init(struct mic_device *mdev, struct pci_dev *pdev) 165{ 166 mdev->pdev = pdev; 167 mdev->family = mic_get_family(pdev); 168 mdev->stepping = pdev->revision; 169 mic_ops_init(mdev); 170 mutex_init(&mdev->mic_mutex); 171 mdev->irq_info.next_avail_src = 0; 172 INIT_LIST_HEAD(&mdev->vdev_list); 173} 174 175/** 176 * mic_probe - Device Initialization Routine 177 * 178 * @pdev: PCI device structure 179 * @ent: entry in mic_pci_tbl 180 * 181 * returns 0 on success, < 0 on failure. 182 */ 183static int mic_probe(struct pci_dev *pdev, 184 const struct pci_device_id *ent) 185{ 186 int rc; 187 struct mic_device *mdev; 188 189 mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); 190 if (!mdev) { 191 rc = -ENOMEM; 192 dev_err(&pdev->dev, "mdev kmalloc failed rc %d\n", rc); 193 goto mdev_alloc_fail; 194 } 195 mdev->id = ida_simple_get(&g_mic_ida, 0, MIC_MAX_NUM_DEVS, GFP_KERNEL); 196 if (mdev->id < 0) { 197 rc = mdev->id; 198 dev_err(&pdev->dev, "ida_simple_get failed rc %d\n", rc); 199 goto ida_fail; 200 } 201 202 mic_device_init(mdev, pdev); 203 204 rc = pci_enable_device(pdev); 205 if (rc) { 206 dev_err(&pdev->dev, "failed to enable pci device.\n"); 207 goto ida_remove; 208 } 209 210 pci_set_master(pdev); 211 212 rc = pci_request_regions(pdev, mic_driver_name); 213 if (rc) { 214 dev_err(&pdev->dev, "failed to get pci regions.\n"); 215 goto disable_device; 216 } 217 218 rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); 219 if (rc) { 220 dev_err(&pdev->dev, "Cannot set DMA mask\n"); 221 goto release_regions; 222 } 223 224 mdev->mmio.pa = pci_resource_start(pdev, mdev->ops->mmio_bar); 225 mdev->mmio.len = pci_resource_len(pdev, mdev->ops->mmio_bar); 226 mdev->mmio.va = pci_ioremap_bar(pdev, mdev->ops->mmio_bar); 227 if (!mdev->mmio.va) { 228 dev_err(&pdev->dev, "Cannot remap MMIO BAR\n"); 229 rc = -EIO; 230 goto release_regions; 231 } 232 233 mdev->aper.pa = pci_resource_start(pdev, mdev->ops->aper_bar); 234 mdev->aper.len = pci_resource_len(pdev, mdev->ops->aper_bar); 235 mdev->aper.va = ioremap_wc(mdev->aper.pa, mdev->aper.len); 236 if (!mdev->aper.va) { 237 dev_err(&pdev->dev, "Cannot remap Aperture BAR\n"); 238 rc = -EIO; 239 goto unmap_mmio; 240 } 241 242 mdev->intr_ops->intr_init(mdev); 243 rc = mic_setup_interrupts(mdev, pdev); 244 if (rc) { 245 dev_err(&pdev->dev, "mic_setup_interrupts failed %d\n", rc); 246 goto unmap_aper; 247 } 248 rc = mic_smpt_init(mdev); 249 if (rc) { 250 dev_err(&pdev->dev, "smpt_init failed %d\n", rc); 251 goto free_interrupts; 252 } 253 254 pci_set_drvdata(pdev, mdev); 255 256 rc = mic_dp_init(mdev); 257 if (rc) { 258 dev_err(&pdev->dev, "mic_dp_init failed rc %d\n", rc); 259 goto smpt_uninit; 260 } 261 mic_bootparam_init(mdev); 262 263 mic_create_debug_dir(mdev); 264 265 mdev->miscdev.minor = MISC_DYNAMIC_MINOR; 266 snprintf(mdev->name, sizeof(mdev->name), "mic%d", mdev->id); 267 mdev->miscdev.name = mdev->name; 268 mdev->miscdev.fops = &mic_fops; 269 mdev->miscdev.parent = &mdev->pdev->dev; 270 rc = misc_register(&mdev->miscdev); 271 if (rc) { 272 dev_err(&pdev->dev, "misc_register err id %d rc %d\n", 273 mdev->id, rc); 274 goto cleanup_debug_dir; 275 } 276 277 mdev->cosm_dev = cosm_register_device(&mdev->pdev->dev, &cosm_hw_ops); 278 if (IS_ERR(mdev->cosm_dev)) { 279 rc = PTR_ERR(mdev->cosm_dev); 280 dev_err(&pdev->dev, "cosm_add_device failed rc %d\n", rc); 281 goto misc_dereg; 282 } 283 return 0; 284misc_dereg: 285 misc_deregister(&mdev->miscdev); 286cleanup_debug_dir: 287 mic_delete_debug_dir(mdev); 288 mic_dp_uninit(mdev); 289smpt_uninit: 290 mic_smpt_uninit(mdev); 291free_interrupts: 292 mic_free_interrupts(mdev, pdev); 293unmap_aper: 294 iounmap(mdev->aper.va); 295unmap_mmio: 296 iounmap(mdev->mmio.va); 297release_regions: 298 pci_release_regions(pdev); 299disable_device: 300 pci_disable_device(pdev); 301ida_remove: 302 ida_simple_remove(&g_mic_ida, mdev->id); 303ida_fail: 304 kfree(mdev); 305mdev_alloc_fail: 306 dev_err(&pdev->dev, "Probe failed rc %d\n", rc); 307 return rc; 308} 309 310/** 311 * mic_remove - Device Removal Routine 312 * mic_remove is called by the PCI subsystem to alert the driver 313 * that it should release a PCI device. 314 * 315 * @pdev: PCI device structure 316 */ 317static void mic_remove(struct pci_dev *pdev) 318{ 319 struct mic_device *mdev; 320 321 mdev = pci_get_drvdata(pdev); 322 if (!mdev) 323 return; 324 325 cosm_unregister_device(mdev->cosm_dev); 326 misc_deregister(&mdev->miscdev); 327 mic_delete_debug_dir(mdev); 328 mic_dp_uninit(mdev); 329 mic_smpt_uninit(mdev); 330 mic_free_interrupts(mdev, pdev); 331 iounmap(mdev->aper.va); 332 iounmap(mdev->mmio.va); 333 pci_release_regions(pdev); 334 pci_disable_device(pdev); 335 ida_simple_remove(&g_mic_ida, mdev->id); 336 kfree(mdev); 337} 338 339static struct pci_driver mic_driver = { 340 .name = mic_driver_name, 341 .id_table = mic_pci_tbl, 342 .probe = mic_probe, 343 .remove = mic_remove 344}; 345 346static int __init mic_init(void) 347{ 348 int ret; 349 350 ret = alloc_chrdev_region(&g_mic_devno, 0, 351 MIC_MAX_NUM_DEVS, mic_driver_name); 352 if (ret) { 353 pr_err("alloc_chrdev_region failed ret %d\n", ret); 354 goto error; 355 } 356 357 mic_init_debugfs(); 358 ida_init(&g_mic_ida); 359 ret = pci_register_driver(&mic_driver); 360 if (ret) { 361 pr_err("pci_register_driver failed ret %d\n", ret); 362 goto cleanup_chrdev; 363 } 364 return ret; 365cleanup_chrdev: 366 ida_destroy(&g_mic_ida); 367 mic_exit_debugfs(); 368 unregister_chrdev_region(g_mic_devno, MIC_MAX_NUM_DEVS); 369error: 370 return ret; 371} 372 373static void __exit mic_exit(void) 374{ 375 pci_unregister_driver(&mic_driver); 376 ida_destroy(&g_mic_ida); 377 mic_exit_debugfs(); 378 unregister_chrdev_region(g_mic_devno, MIC_MAX_NUM_DEVS); 379} 380 381module_init(mic_init); 382module_exit(mic_exit); 383 384MODULE_AUTHOR("Intel Corporation"); 385MODULE_DESCRIPTION("Intel(R) MIC X100 Host driver"); 386MODULE_LICENSE("GPL v2");