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.3-rc1 362 lines 9.4 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/platform_device.h> 30 31#include "../common/mic_dev.h" 32#include "mic_device.h" 33#include "mic_x100.h" 34 35static const char mic_driver_name[] = "mic"; 36 37static struct mic_driver g_drv; 38 39/** 40 * mic_read_spad - read from the scratchpad register 41 * @mdev: pointer to mic_device instance 42 * @idx: index to scratchpad register, 0 based 43 * 44 * This function allows reading of the 32bit scratchpad register. 45 * 46 * RETURNS: An appropriate -ERRNO error value on error, or zero for success. 47 */ 48u32 mic_read_spad(struct mic_device *mdev, unsigned int idx) 49{ 50 return mic_mmio_read(&mdev->mmio, 51 MIC_X100_SBOX_BASE_ADDRESS + 52 MIC_X100_SBOX_SPAD0 + idx * 4); 53} 54 55/** 56 * __mic_send_intr - Send interrupt to Host. 57 * @mdev: pointer to mic_device instance 58 * @doorbell: Doorbell number. 59 */ 60void mic_send_intr(struct mic_device *mdev, int doorbell) 61{ 62 struct mic_mw *mw = &mdev->mmio; 63 64 if (doorbell > MIC_X100_MAX_DOORBELL_IDX) 65 return; 66 /* Ensure that the interrupt is ordered w.r.t previous stores. */ 67 wmb(); 68 mic_mmio_write(mw, MIC_X100_SBOX_SDBIC0_DBREQ_BIT, 69 MIC_X100_SBOX_BASE_ADDRESS + 70 (MIC_X100_SBOX_SDBIC0 + (4 * doorbell))); 71} 72 73/* 74 * mic_x100_send_sbox_intr - Send an MIC_X100_SBOX interrupt to MIC. 75 */ 76static void mic_x100_send_sbox_intr(struct mic_mw *mw, int doorbell) 77{ 78 u64 apic_icr_offset = MIC_X100_SBOX_APICICR0 + doorbell * 8; 79 u32 apicicr_low = mic_mmio_read(mw, MIC_X100_SBOX_BASE_ADDRESS + 80 apic_icr_offset); 81 82 /* for MIC we need to make sure we "hit" the send_icr bit (13) */ 83 apicicr_low = (apicicr_low | (1 << 13)); 84 /* 85 * Ensure that the interrupt is ordered w.r.t. previous stores 86 * to main memory. Fence instructions are not implemented in X100 87 * since execution is in order but a compiler barrier is still 88 * required. 89 */ 90 wmb(); 91 mic_mmio_write(mw, apicicr_low, 92 MIC_X100_SBOX_BASE_ADDRESS + apic_icr_offset); 93} 94 95static void mic_x100_send_rdmasr_intr(struct mic_mw *mw, int doorbell) 96{ 97 int rdmasr_offset = MIC_X100_SBOX_RDMASR0 + (doorbell << 2); 98 /* 99 * Ensure that the interrupt is ordered w.r.t. previous stores 100 * to main memory. Fence instructions are not implemented in X100 101 * since execution is in order but a compiler barrier is still 102 * required. 103 */ 104 wmb(); 105 mic_mmio_write(mw, 0, MIC_X100_SBOX_BASE_ADDRESS + rdmasr_offset); 106} 107 108/** 109 * mic_ack_interrupt - Device specific interrupt handling. 110 * @mdev: pointer to mic_device instance 111 * 112 * Returns: bitmask of doorbell events triggered. 113 */ 114u32 mic_ack_interrupt(struct mic_device *mdev) 115{ 116 return 0; 117} 118 119static inline int mic_get_sbox_irq(int db) 120{ 121 return MIC_X100_IRQ_BASE + db; 122} 123 124static inline int mic_get_rdmasr_irq(int index) 125{ 126 return MIC_X100_RDMASR_IRQ_BASE + index; 127} 128 129void mic_send_p2p_intr(int db, struct mic_mw *mw) 130{ 131 int rdmasr_index; 132 133 if (db < MIC_X100_NUM_SBOX_IRQ) { 134 mic_x100_send_sbox_intr(mw, db); 135 } else { 136 rdmasr_index = db - MIC_X100_NUM_SBOX_IRQ; 137 mic_x100_send_rdmasr_intr(mw, rdmasr_index); 138 } 139} 140 141/** 142 * mic_hw_intr_init - Initialize h/w specific interrupt 143 * information. 144 * @mdrv: pointer to mic_driver 145 */ 146void mic_hw_intr_init(struct mic_driver *mdrv) 147{ 148 mdrv->intr_info.num_intr = MIC_X100_NUM_SBOX_IRQ + 149 MIC_X100_NUM_RDMASR_IRQ; 150} 151 152/** 153 * mic_db_to_irq - Retrieve irq number corresponding to a doorbell. 154 * @mdrv: pointer to mic_driver 155 * @db: The doorbell obtained for which the irq is needed. Doorbell 156 * may correspond to an sbox doorbell or an rdmasr index. 157 * 158 * Returns the irq corresponding to the doorbell. 159 */ 160int mic_db_to_irq(struct mic_driver *mdrv, int db) 161{ 162 int rdmasr_index; 163 164 /* 165 * The total number of doorbell interrupts on the card are 16. Indices 166 * 0-8 falls in the SBOX category and 8-15 fall in the RDMASR category. 167 */ 168 if (db < MIC_X100_NUM_SBOX_IRQ) { 169 return mic_get_sbox_irq(db); 170 } else { 171 rdmasr_index = db - MIC_X100_NUM_SBOX_IRQ; 172 return mic_get_rdmasr_irq(rdmasr_index); 173 } 174} 175 176/* 177 * mic_card_map - Allocate virtual address for a remote memory region. 178 * @mdev: pointer to mic_device instance. 179 * @addr: Remote DMA address. 180 * @size: Size of the region. 181 * 182 * Returns: Virtual address backing the remote memory region. 183 */ 184void __iomem * 185mic_card_map(struct mic_device *mdev, dma_addr_t addr, size_t size) 186{ 187 return ioremap(addr, size); 188} 189 190/* 191 * mic_card_unmap - Unmap the virtual address for a remote memory region. 192 * @mdev: pointer to mic_device instance. 193 * @addr: Virtual address for remote memory region. 194 * 195 * Returns: None. 196 */ 197void mic_card_unmap(struct mic_device *mdev, void __iomem *addr) 198{ 199 iounmap(addr); 200} 201 202static inline struct mic_driver *mbdev_to_mdrv(struct mbus_device *mbdev) 203{ 204 return dev_get_drvdata(mbdev->dev.parent); 205} 206 207static struct mic_irq * 208_mic_request_threaded_irq(struct mbus_device *mbdev, 209 irq_handler_t handler, irq_handler_t thread_fn, 210 const char *name, void *data, int intr_src) 211{ 212 int rc = 0; 213 unsigned int irq = intr_src; 214 unsigned long cookie = irq; 215 216 rc = request_threaded_irq(irq, handler, thread_fn, 0, name, data); 217 if (rc) { 218 dev_err(mbdev_to_mdrv(mbdev)->dev, 219 "request_threaded_irq failed rc = %d\n", rc); 220 return ERR_PTR(rc); 221 } 222 return (struct mic_irq *)cookie; 223} 224 225static void _mic_free_irq(struct mbus_device *mbdev, 226 struct mic_irq *cookie, void *data) 227{ 228 unsigned long irq = (unsigned long)cookie; 229 free_irq(irq, data); 230} 231 232static void _mic_ack_interrupt(struct mbus_device *mbdev, int num) 233{ 234 mic_ack_interrupt(&mbdev_to_mdrv(mbdev)->mdev); 235} 236 237static struct mbus_hw_ops mbus_hw_ops = { 238 .request_threaded_irq = _mic_request_threaded_irq, 239 .free_irq = _mic_free_irq, 240 .ack_interrupt = _mic_ack_interrupt, 241}; 242 243static int __init mic_probe(struct platform_device *pdev) 244{ 245 struct mic_driver *mdrv = &g_drv; 246 struct mic_device *mdev = &mdrv->mdev; 247 int rc = 0; 248 249 mdrv->dev = &pdev->dev; 250 snprintf(mdrv->name, sizeof(mic_driver_name), mic_driver_name); 251 252 mdev->mmio.pa = MIC_X100_MMIO_BASE; 253 mdev->mmio.len = MIC_X100_MMIO_LEN; 254 mdev->mmio.va = devm_ioremap(&pdev->dev, MIC_X100_MMIO_BASE, 255 MIC_X100_MMIO_LEN); 256 if (!mdev->mmio.va) { 257 dev_err(&pdev->dev, "Cannot remap MMIO BAR\n"); 258 rc = -EIO; 259 goto done; 260 } 261 mic_hw_intr_init(mdrv); 262 platform_set_drvdata(pdev, mdrv); 263 mdrv->dma_mbdev = mbus_register_device(mdrv->dev, MBUS_DEV_DMA_MIC, 264 NULL, &mbus_hw_ops, 265 mdrv->mdev.mmio.va); 266 if (IS_ERR(mdrv->dma_mbdev)) { 267 rc = PTR_ERR(mdrv->dma_mbdev); 268 dev_err(&pdev->dev, "mbus_add_device failed rc %d\n", rc); 269 goto done; 270 } 271 rc = mic_driver_init(mdrv); 272 if (rc) { 273 dev_err(&pdev->dev, "mic_driver_init failed rc %d\n", rc); 274 goto remove_dma; 275 } 276done: 277 return rc; 278remove_dma: 279 mbus_unregister_device(mdrv->dma_mbdev); 280 return rc; 281} 282 283static int mic_remove(struct platform_device *pdev) 284{ 285 struct mic_driver *mdrv = &g_drv; 286 287 mic_driver_uninit(mdrv); 288 mbus_unregister_device(mdrv->dma_mbdev); 289 return 0; 290} 291 292static void mic_platform_shutdown(struct platform_device *pdev) 293{ 294 mic_remove(pdev); 295} 296 297static u64 mic_dma_mask = DMA_BIT_MASK(64); 298 299static struct platform_device mic_platform_dev = { 300 .name = mic_driver_name, 301 .id = 0, 302 .num_resources = 0, 303 .dev = { 304 .dma_mask = &mic_dma_mask, 305 .coherent_dma_mask = DMA_BIT_MASK(64), 306 }, 307}; 308 309static struct platform_driver __refdata mic_platform_driver = { 310 .probe = mic_probe, 311 .remove = mic_remove, 312 .shutdown = mic_platform_shutdown, 313 .driver = { 314 .name = mic_driver_name, 315 }, 316}; 317 318static int __init mic_init(void) 319{ 320 int ret; 321 struct cpuinfo_x86 *c = &cpu_data(0); 322 323 if (!(c->x86 == 11 && c->x86_model == 1)) { 324 ret = -ENODEV; 325 pr_err("%s not running on X100 ret %d\n", __func__, ret); 326 goto done; 327 } 328 329 mic_init_card_debugfs(); 330 ret = platform_device_register(&mic_platform_dev); 331 if (ret) { 332 pr_err("platform_device_register ret %d\n", ret); 333 goto cleanup_debugfs; 334 } 335 ret = platform_driver_register(&mic_platform_driver); 336 if (ret) { 337 pr_err("platform_driver_register ret %d\n", ret); 338 goto device_unregister; 339 } 340 return ret; 341 342device_unregister: 343 platform_device_unregister(&mic_platform_dev); 344cleanup_debugfs: 345 mic_exit_card_debugfs(); 346done: 347 return ret; 348} 349 350static void __exit mic_exit(void) 351{ 352 platform_driver_unregister(&mic_platform_driver); 353 platform_device_unregister(&mic_platform_dev); 354 mic_exit_card_debugfs(); 355} 356 357module_init(mic_init); 358module_exit(mic_exit); 359 360MODULE_AUTHOR("Intel Corporation"); 361MODULE_DESCRIPTION("Intel(R) MIC X100 Card driver"); 362MODULE_LICENSE("GPL v2");