Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v3.13-rc7 300 lines 7.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 */ 21#include <linux/delay.h> 22#include <linux/firmware.h> 23#include <linux/pci.h> 24 25#include <linux/mic_common.h> 26#include "../common/mic_dev.h" 27#include "mic_device.h" 28#include "mic_smpt.h" 29#include "mic_virtio.h" 30 31/** 32 * mic_reset - Reset the MIC device. 33 * @mdev: pointer to mic_device instance 34 */ 35static void mic_reset(struct mic_device *mdev) 36{ 37 int i; 38 39#define MIC_RESET_TO (45) 40 41 reinit_completion(&mdev->reset_wait); 42 mdev->ops->reset_fw_ready(mdev); 43 mdev->ops->reset(mdev); 44 45 for (i = 0; i < MIC_RESET_TO; i++) { 46 if (mdev->ops->is_fw_ready(mdev)) 47 goto done; 48 /* 49 * Resets typically take 10s of seconds to complete. 50 * Since an MMIO read is required to check if the 51 * firmware is ready or not, a 1 second delay works nicely. 52 */ 53 msleep(1000); 54 } 55 mic_set_state(mdev, MIC_RESET_FAILED); 56done: 57 complete_all(&mdev->reset_wait); 58} 59 60/* Initialize the MIC bootparams */ 61void mic_bootparam_init(struct mic_device *mdev) 62{ 63 struct mic_bootparam *bootparam = mdev->dp; 64 65 bootparam->magic = cpu_to_le32(MIC_MAGIC); 66 bootparam->c2h_shutdown_db = mdev->shutdown_db; 67 bootparam->h2c_shutdown_db = -1; 68 bootparam->h2c_config_db = -1; 69 bootparam->shutdown_status = 0; 70 bootparam->shutdown_card = 0; 71} 72 73/** 74 * mic_start - Start the MIC. 75 * @mdev: pointer to mic_device instance 76 * @buf: buffer containing boot string including firmware/ramdisk path. 77 * 78 * This function prepares an MIC for boot and initiates boot. 79 * RETURNS: An appropriate -ERRNO error value on error, or zero for success. 80 */ 81int mic_start(struct mic_device *mdev, const char *buf) 82{ 83 int rc; 84 mutex_lock(&mdev->mic_mutex); 85retry: 86 if (MIC_OFFLINE != mdev->state) { 87 rc = -EINVAL; 88 goto unlock_ret; 89 } 90 if (!mdev->ops->is_fw_ready(mdev)) { 91 mic_reset(mdev); 92 /* 93 * The state will either be MIC_OFFLINE if the reset succeeded 94 * or MIC_RESET_FAILED if the firmware reset failed. 95 */ 96 goto retry; 97 } 98 rc = mdev->ops->load_mic_fw(mdev, buf); 99 if (rc) 100 goto unlock_ret; 101 mic_smpt_restore(mdev); 102 mic_intr_restore(mdev); 103 mdev->intr_ops->enable_interrupts(mdev); 104 mdev->ops->write_spad(mdev, MIC_DPLO_SPAD, mdev->dp_dma_addr); 105 mdev->ops->write_spad(mdev, MIC_DPHI_SPAD, mdev->dp_dma_addr >> 32); 106 mdev->ops->send_firmware_intr(mdev); 107 mic_set_state(mdev, MIC_ONLINE); 108unlock_ret: 109 mutex_unlock(&mdev->mic_mutex); 110 return rc; 111} 112 113/** 114 * mic_stop - Prepare the MIC for reset and trigger reset. 115 * @mdev: pointer to mic_device instance 116 * @force: force a MIC to reset even if it is already offline. 117 * 118 * RETURNS: None. 119 */ 120void mic_stop(struct mic_device *mdev, bool force) 121{ 122 mutex_lock(&mdev->mic_mutex); 123 if (MIC_OFFLINE != mdev->state || force) { 124 mic_virtio_reset_devices(mdev); 125 mic_bootparam_init(mdev); 126 mic_reset(mdev); 127 if (MIC_RESET_FAILED == mdev->state) 128 goto unlock; 129 mic_set_shutdown_status(mdev, MIC_NOP); 130 if (MIC_SUSPENDED != mdev->state) 131 mic_set_state(mdev, MIC_OFFLINE); 132 } 133unlock: 134 mutex_unlock(&mdev->mic_mutex); 135} 136 137/** 138 * mic_shutdown - Initiate MIC shutdown. 139 * @mdev: pointer to mic_device instance 140 * 141 * RETURNS: None. 142 */ 143void mic_shutdown(struct mic_device *mdev) 144{ 145 struct mic_bootparam *bootparam = mdev->dp; 146 s8 db = bootparam->h2c_shutdown_db; 147 148 mutex_lock(&mdev->mic_mutex); 149 if (MIC_ONLINE == mdev->state && db != -1) { 150 bootparam->shutdown_card = 1; 151 mdev->ops->send_intr(mdev, db); 152 mic_set_state(mdev, MIC_SHUTTING_DOWN); 153 } 154 mutex_unlock(&mdev->mic_mutex); 155} 156 157/** 158 * mic_shutdown_work - Handle shutdown interrupt from MIC. 159 * @work: The work structure. 160 * 161 * This work is scheduled whenever the host has received a shutdown 162 * interrupt from the MIC. 163 */ 164void mic_shutdown_work(struct work_struct *work) 165{ 166 struct mic_device *mdev = container_of(work, struct mic_device, 167 shutdown_work); 168 struct mic_bootparam *bootparam = mdev->dp; 169 170 mutex_lock(&mdev->mic_mutex); 171 mic_set_shutdown_status(mdev, bootparam->shutdown_status); 172 bootparam->shutdown_status = 0; 173 174 /* 175 * if state is MIC_SUSPENDED, OSPM suspend is in progress. We do not 176 * change the state here so as to prevent users from booting the card 177 * during and after the suspend operation. 178 */ 179 if (MIC_SHUTTING_DOWN != mdev->state && 180 MIC_SUSPENDED != mdev->state) 181 mic_set_state(mdev, MIC_SHUTTING_DOWN); 182 mutex_unlock(&mdev->mic_mutex); 183} 184 185/** 186 * mic_reset_trigger_work - Trigger MIC reset. 187 * @work: The work structure. 188 * 189 * This work is scheduled whenever the host wants to reset the MIC. 190 */ 191void mic_reset_trigger_work(struct work_struct *work) 192{ 193 struct mic_device *mdev = container_of(work, struct mic_device, 194 reset_trigger_work); 195 196 mic_stop(mdev, false); 197} 198 199/** 200 * mic_complete_resume - Complete MIC Resume after an OSPM suspend/hibernate 201 * event. 202 * @mdev: pointer to mic_device instance 203 * 204 * RETURNS: None. 205 */ 206void mic_complete_resume(struct mic_device *mdev) 207{ 208 if (mdev->state != MIC_SUSPENDED) { 209 dev_warn(mdev->sdev->parent, "state %d should be %d\n", 210 mdev->state, MIC_SUSPENDED); 211 return; 212 } 213 214 /* Make sure firmware is ready */ 215 if (!mdev->ops->is_fw_ready(mdev)) 216 mic_stop(mdev, true); 217 218 mutex_lock(&mdev->mic_mutex); 219 mic_set_state(mdev, MIC_OFFLINE); 220 mutex_unlock(&mdev->mic_mutex); 221} 222 223/** 224 * mic_prepare_suspend - Handle suspend notification for the MIC device. 225 * @mdev: pointer to mic_device instance 226 * 227 * RETURNS: None. 228 */ 229void mic_prepare_suspend(struct mic_device *mdev) 230{ 231 int rc; 232 233#define MIC_SUSPEND_TIMEOUT (60 * HZ) 234 235 mutex_lock(&mdev->mic_mutex); 236 switch (mdev->state) { 237 case MIC_OFFLINE: 238 /* 239 * Card is already offline. Set state to MIC_SUSPENDED 240 * to prevent users from booting the card. 241 */ 242 mic_set_state(mdev, MIC_SUSPENDED); 243 mutex_unlock(&mdev->mic_mutex); 244 break; 245 case MIC_ONLINE: 246 /* 247 * Card is online. Set state to MIC_SUSPENDING and notify 248 * MIC user space daemon which will issue card 249 * shutdown and reset. 250 */ 251 mic_set_state(mdev, MIC_SUSPENDING); 252 mutex_unlock(&mdev->mic_mutex); 253 rc = wait_for_completion_timeout(&mdev->reset_wait, 254 MIC_SUSPEND_TIMEOUT); 255 /* Force reset the card if the shutdown completion timed out */ 256 if (!rc) { 257 mutex_lock(&mdev->mic_mutex); 258 mic_set_state(mdev, MIC_SUSPENDED); 259 mutex_unlock(&mdev->mic_mutex); 260 mic_stop(mdev, true); 261 } 262 break; 263 case MIC_SHUTTING_DOWN: 264 /* 265 * Card is shutting down. Set state to MIC_SUSPENDED 266 * to prevent further boot of the card. 267 */ 268 mic_set_state(mdev, MIC_SUSPENDED); 269 mutex_unlock(&mdev->mic_mutex); 270 rc = wait_for_completion_timeout(&mdev->reset_wait, 271 MIC_SUSPEND_TIMEOUT); 272 /* Force reset the card if the shutdown completion timed out */ 273 if (!rc) 274 mic_stop(mdev, true); 275 break; 276 default: 277 mutex_unlock(&mdev->mic_mutex); 278 break; 279 } 280} 281 282/** 283 * mic_suspend - Initiate MIC suspend. Suspend merely issues card shutdown. 284 * @mdev: pointer to mic_device instance 285 * 286 * RETURNS: None. 287 */ 288void mic_suspend(struct mic_device *mdev) 289{ 290 struct mic_bootparam *bootparam = mdev->dp; 291 s8 db = bootparam->h2c_shutdown_db; 292 293 mutex_lock(&mdev->mic_mutex); 294 if (MIC_SUSPENDING == mdev->state && db != -1) { 295 bootparam->shutdown_card = 1; 296 mdev->ops->send_intr(mdev, db); 297 mic_set_state(mdev, MIC_SUSPENDED); 298 } 299 mutex_unlock(&mdev->mic_mutex); 300}