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.17-rc2 347 lines 8.7 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 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");