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