Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v3.16 305 lines 7.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 * 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 32#include <linux/mic_common.h> 33#include "../common/mic_dev.h" 34#include "mic_device.h" 35#include "mic_virtio.h" 36 37static struct mic_driver *g_drv; 38static struct mic_irq *shutdown_cookie; 39 40static void mic_notify_host(u8 state) 41{ 42 struct mic_driver *mdrv = g_drv; 43 struct mic_bootparam __iomem *bootparam = mdrv->dp; 44 45 iowrite8(state, &bootparam->shutdown_status); 46 dev_dbg(mdrv->dev, "%s %d system_state %d\n", 47 __func__, __LINE__, state); 48 mic_send_intr(&mdrv->mdev, ioread8(&bootparam->c2h_shutdown_db)); 49} 50 51static int mic_panic_event(struct notifier_block *this, unsigned long event, 52 void *ptr) 53{ 54 struct mic_driver *mdrv = g_drv; 55 struct mic_bootparam __iomem *bootparam = mdrv->dp; 56 57 iowrite8(-1, &bootparam->h2c_config_db); 58 iowrite8(-1, &bootparam->h2c_shutdown_db); 59 mic_notify_host(MIC_CRASHED); 60 return NOTIFY_DONE; 61} 62 63static struct notifier_block mic_panic = { 64 .notifier_call = mic_panic_event, 65}; 66 67static irqreturn_t mic_shutdown_isr(int irq, void *data) 68{ 69 struct mic_driver *mdrv = g_drv; 70 struct mic_bootparam __iomem *bootparam = mdrv->dp; 71 72 mic_ack_interrupt(&g_drv->mdev); 73 if (ioread8(&bootparam->shutdown_card)) 74 orderly_poweroff(true); 75 return IRQ_HANDLED; 76} 77 78static int mic_shutdown_init(void) 79{ 80 int rc = 0; 81 struct mic_driver *mdrv = g_drv; 82 struct mic_bootparam __iomem *bootparam = mdrv->dp; 83 int shutdown_db; 84 85 shutdown_db = mic_next_card_db(); 86 shutdown_cookie = mic_request_card_irq(mic_shutdown_isr, 87 "Shutdown", mdrv, shutdown_db); 88 if (IS_ERR(shutdown_cookie)) 89 rc = PTR_ERR(shutdown_cookie); 90 else 91 iowrite8(shutdown_db, &bootparam->h2c_shutdown_db); 92 return rc; 93} 94 95static void mic_shutdown_uninit(void) 96{ 97 struct mic_driver *mdrv = g_drv; 98 struct mic_bootparam __iomem *bootparam = mdrv->dp; 99 100 iowrite8(-1, &bootparam->h2c_shutdown_db); 101 mic_free_card_irq(shutdown_cookie, mdrv); 102} 103 104static int __init mic_dp_init(void) 105{ 106 struct mic_driver *mdrv = g_drv; 107 struct mic_device *mdev = &mdrv->mdev; 108 struct mic_bootparam __iomem *bootparam; 109 u64 lo, hi, dp_dma_addr; 110 u32 magic; 111 112 lo = mic_read_spad(&mdrv->mdev, MIC_DPLO_SPAD); 113 hi = mic_read_spad(&mdrv->mdev, MIC_DPHI_SPAD); 114 115 dp_dma_addr = lo | (hi << 32); 116 mdrv->dp = mic_card_map(mdev, dp_dma_addr, MIC_DP_SIZE); 117 if (!mdrv->dp) { 118 dev_err(mdrv->dev, "Cannot remap Aperture BAR\n"); 119 return -ENOMEM; 120 } 121 bootparam = mdrv->dp; 122 magic = ioread32(&bootparam->magic); 123 if (MIC_MAGIC != magic) { 124 dev_err(mdrv->dev, "bootparam magic mismatch 0x%x\n", magic); 125 return -EIO; 126 } 127 return 0; 128} 129 130/* Uninitialize the device page */ 131static void mic_dp_uninit(void) 132{ 133 mic_card_unmap(&g_drv->mdev, g_drv->dp); 134} 135 136/** 137 * mic_request_card_irq - request an irq. 138 * 139 * @func: The callback function that handles the interrupt. 140 * @name: The ASCII name of the callee requesting the irq. 141 * @data: private data that is returned back when calling the 142 * function handler. 143 * @index: The doorbell index of the requester. 144 * 145 * returns: The cookie that is transparent to the caller. Passed 146 * back when calling mic_free_irq. An appropriate error code 147 * is returned on failure. Caller needs to use IS_ERR(return_val) 148 * to check for failure and PTR_ERR(return_val) to obtained the 149 * error code. 150 * 151 */ 152struct mic_irq *mic_request_card_irq(irqreturn_t (*func)(int irq, void *data), 153 const char *name, void *data, int index) 154{ 155 int rc = 0; 156 unsigned long cookie; 157 struct mic_driver *mdrv = g_drv; 158 159 rc = request_irq(mic_db_to_irq(mdrv, index), func, 160 0, name, data); 161 if (rc) { 162 dev_err(mdrv->dev, "request_irq failed rc = %d\n", rc); 163 goto err; 164 } 165 mdrv->irq_info.irq_usage_count[index]++; 166 cookie = index; 167 return (struct mic_irq *)cookie; 168err: 169 return ERR_PTR(rc); 170} 171 172/** 173 * mic_free_card_irq - free irq. 174 * 175 * @cookie: cookie obtained during a successful call to mic_request_irq 176 * @data: private data specified by the calling function during the 177 * mic_request_irq 178 * 179 * returns: none. 180 */ 181void mic_free_card_irq(struct mic_irq *cookie, void *data) 182{ 183 int index; 184 struct mic_driver *mdrv = g_drv; 185 186 index = (unsigned long)cookie & 0xFFFFU; 187 free_irq(mic_db_to_irq(mdrv, index), data); 188 mdrv->irq_info.irq_usage_count[index]--; 189} 190 191/** 192 * mic_next_card_db - Get the doorbell with minimum usage count. 193 * 194 * Returns the irq index. 195 */ 196int mic_next_card_db(void) 197{ 198 int i; 199 int index = 0; 200 struct mic_driver *mdrv = g_drv; 201 202 for (i = 0; i < mdrv->intr_info.num_intr; i++) { 203 if (mdrv->irq_info.irq_usage_count[i] < 204 mdrv->irq_info.irq_usage_count[index]) 205 index = i; 206 } 207 208 return index; 209} 210 211/** 212 * mic_init_irq - Initialize irq information. 213 * 214 * Returns 0 in success. Appropriate error code on failure. 215 */ 216static int mic_init_irq(void) 217{ 218 struct mic_driver *mdrv = g_drv; 219 220 mdrv->irq_info.irq_usage_count = kzalloc((sizeof(u32) * 221 mdrv->intr_info.num_intr), 222 GFP_KERNEL); 223 if (!mdrv->irq_info.irq_usage_count) 224 return -ENOMEM; 225 return 0; 226} 227 228/** 229 * mic_uninit_irq - Uninitialize irq information. 230 * 231 * None. 232 */ 233static void mic_uninit_irq(void) 234{ 235 struct mic_driver *mdrv = g_drv; 236 237 kfree(mdrv->irq_info.irq_usage_count); 238} 239 240/* 241 * mic_driver_init - MIC driver initialization tasks. 242 * 243 * Returns 0 in success. Appropriate error code on failure. 244 */ 245int __init mic_driver_init(struct mic_driver *mdrv) 246{ 247 int rc; 248 249 g_drv = mdrv; 250 /* 251 * Unloading the card module is not supported. The MIC card module 252 * handles fundamental operations like host/card initiated shutdowns 253 * and informing the host about card crashes and cannot be unloaded. 254 */ 255 if (!try_module_get(mdrv->dev->driver->owner)) { 256 rc = -ENODEV; 257 goto done; 258 } 259 rc = mic_dp_init(); 260 if (rc) 261 goto put; 262 rc = mic_init_irq(); 263 if (rc) 264 goto dp_uninit; 265 rc = mic_shutdown_init(); 266 if (rc) 267 goto irq_uninit; 268 rc = mic_devices_init(mdrv); 269 if (rc) 270 goto shutdown_uninit; 271 mic_create_card_debug_dir(mdrv); 272 atomic_notifier_chain_register(&panic_notifier_list, &mic_panic); 273done: 274 return rc; 275shutdown_uninit: 276 mic_shutdown_uninit(); 277irq_uninit: 278 mic_uninit_irq(); 279dp_uninit: 280 mic_dp_uninit(); 281put: 282 module_put(mdrv->dev->driver->owner); 283 return rc; 284} 285 286/* 287 * mic_driver_uninit - MIC driver uninitialization tasks. 288 * 289 * Returns None 290 */ 291void mic_driver_uninit(struct mic_driver *mdrv) 292{ 293 mic_delete_card_debug_dir(mdrv); 294 mic_devices_uninit(mdrv); 295 /* 296 * Inform the host about the shutdown status i.e. poweroff/restart etc. 297 * The module cannot be unloaded so the only code path to call 298 * mic_devices_uninit(..) is the shutdown callback. 299 */ 300 mic_notify_host(system_state); 301 mic_shutdown_uninit(); 302 mic_uninit_irq(); 303 mic_dp_uninit(); 304 module_put(mdrv->dev->driver->owner); 305}