Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.4-rc7 482 lines 12 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#include <linux/kmod.h> 25#include <linux/mic_common.h> 26#include <linux/mic_bus.h> 27#include "../bus/scif_bus.h" 28#include "../common/mic_dev.h" 29#include "mic_device.h" 30#include "mic_smpt.h" 31#include "mic_virtio.h" 32 33static inline struct mic_device *scdev_to_mdev(struct scif_hw_dev *scdev) 34{ 35 return dev_get_drvdata(scdev->dev.parent); 36} 37 38static void *__mic_dma_alloc(struct device *dev, size_t size, 39 dma_addr_t *dma_handle, gfp_t gfp, 40 struct dma_attrs *attrs) 41{ 42 struct scif_hw_dev *scdev = dev_get_drvdata(dev); 43 struct mic_device *mdev = scdev_to_mdev(scdev); 44 dma_addr_t tmp; 45 void *va = kmalloc(size, gfp); 46 47 if (va) { 48 tmp = mic_map_single(mdev, va, size); 49 if (dma_mapping_error(dev, tmp)) { 50 kfree(va); 51 va = NULL; 52 } else { 53 *dma_handle = tmp; 54 } 55 } 56 return va; 57} 58 59static void __mic_dma_free(struct device *dev, size_t size, void *vaddr, 60 dma_addr_t dma_handle, struct dma_attrs *attrs) 61{ 62 struct scif_hw_dev *scdev = dev_get_drvdata(dev); 63 struct mic_device *mdev = scdev_to_mdev(scdev); 64 65 mic_unmap_single(mdev, dma_handle, size); 66 kfree(vaddr); 67} 68 69static dma_addr_t 70__mic_dma_map_page(struct device *dev, struct page *page, unsigned long offset, 71 size_t size, enum dma_data_direction dir, 72 struct dma_attrs *attrs) 73{ 74 void *va = phys_to_virt(page_to_phys(page)) + offset; 75 struct scif_hw_dev *scdev = dev_get_drvdata(dev); 76 struct mic_device *mdev = scdev_to_mdev(scdev); 77 78 return mic_map_single(mdev, va, size); 79} 80 81static void 82__mic_dma_unmap_page(struct device *dev, dma_addr_t dma_addr, 83 size_t size, enum dma_data_direction dir, 84 struct dma_attrs *attrs) 85{ 86 struct scif_hw_dev *scdev = dev_get_drvdata(dev); 87 struct mic_device *mdev = scdev_to_mdev(scdev); 88 89 mic_unmap_single(mdev, dma_addr, size); 90} 91 92static int __mic_dma_map_sg(struct device *dev, struct scatterlist *sg, 93 int nents, enum dma_data_direction dir, 94 struct dma_attrs *attrs) 95{ 96 struct scif_hw_dev *scdev = dev_get_drvdata(dev); 97 struct mic_device *mdev = scdev_to_mdev(scdev); 98 struct scatterlist *s; 99 int i, j, ret; 100 dma_addr_t da; 101 102 ret = dma_map_sg(&mdev->pdev->dev, sg, nents, dir); 103 if (ret <= 0) 104 return 0; 105 106 for_each_sg(sg, s, nents, i) { 107 da = mic_map(mdev, sg_dma_address(s) + s->offset, s->length); 108 if (!da) 109 goto err; 110 sg_dma_address(s) = da; 111 } 112 return nents; 113err: 114 for_each_sg(sg, s, i, j) { 115 mic_unmap(mdev, sg_dma_address(s), s->length); 116 sg_dma_address(s) = mic_to_dma_addr(mdev, sg_dma_address(s)); 117 } 118 dma_unmap_sg(&mdev->pdev->dev, sg, nents, dir); 119 return 0; 120} 121 122static void __mic_dma_unmap_sg(struct device *dev, 123 struct scatterlist *sg, int nents, 124 enum dma_data_direction dir, 125 struct dma_attrs *attrs) 126{ 127 struct scif_hw_dev *scdev = dev_get_drvdata(dev); 128 struct mic_device *mdev = scdev_to_mdev(scdev); 129 struct scatterlist *s; 130 dma_addr_t da; 131 int i; 132 133 for_each_sg(sg, s, nents, i) { 134 da = mic_to_dma_addr(mdev, sg_dma_address(s)); 135 mic_unmap(mdev, sg_dma_address(s), s->length); 136 sg_dma_address(s) = da; 137 } 138 dma_unmap_sg(&mdev->pdev->dev, sg, nents, dir); 139} 140 141static struct dma_map_ops __mic_dma_ops = { 142 .alloc = __mic_dma_alloc, 143 .free = __mic_dma_free, 144 .map_page = __mic_dma_map_page, 145 .unmap_page = __mic_dma_unmap_page, 146 .map_sg = __mic_dma_map_sg, 147 .unmap_sg = __mic_dma_unmap_sg, 148}; 149 150static struct mic_irq * 151___mic_request_irq(struct scif_hw_dev *scdev, 152 irqreturn_t (*func)(int irq, void *data), 153 const char *name, 154 void *data, int db) 155{ 156 struct mic_device *mdev = scdev_to_mdev(scdev); 157 158 return mic_request_threaded_irq(mdev, func, NULL, name, data, 159 db, MIC_INTR_DB); 160} 161 162static void 163___mic_free_irq(struct scif_hw_dev *scdev, 164 struct mic_irq *cookie, void *data) 165{ 166 struct mic_device *mdev = scdev_to_mdev(scdev); 167 168 return mic_free_irq(mdev, cookie, data); 169} 170 171static void ___mic_ack_interrupt(struct scif_hw_dev *scdev, int num) 172{ 173 struct mic_device *mdev = scdev_to_mdev(scdev); 174 175 mdev->ops->intr_workarounds(mdev); 176} 177 178static int ___mic_next_db(struct scif_hw_dev *scdev) 179{ 180 struct mic_device *mdev = scdev_to_mdev(scdev); 181 182 return mic_next_db(mdev); 183} 184 185static void ___mic_send_intr(struct scif_hw_dev *scdev, int db) 186{ 187 struct mic_device *mdev = scdev_to_mdev(scdev); 188 189 mdev->ops->send_intr(mdev, db); 190} 191 192static void __iomem *___mic_ioremap(struct scif_hw_dev *scdev, 193 phys_addr_t pa, size_t len) 194{ 195 struct mic_device *mdev = scdev_to_mdev(scdev); 196 197 return mdev->aper.va + pa; 198} 199 200static void ___mic_iounmap(struct scif_hw_dev *scdev, void __iomem *va) 201{ 202 /* nothing to do */ 203} 204 205static struct scif_hw_ops scif_hw_ops = { 206 .request_irq = ___mic_request_irq, 207 .free_irq = ___mic_free_irq, 208 .ack_interrupt = ___mic_ack_interrupt, 209 .next_db = ___mic_next_db, 210 .send_intr = ___mic_send_intr, 211 .ioremap = ___mic_ioremap, 212 .iounmap = ___mic_iounmap, 213}; 214 215static inline struct mic_device *mbdev_to_mdev(struct mbus_device *mbdev) 216{ 217 return dev_get_drvdata(mbdev->dev.parent); 218} 219 220static dma_addr_t 221mic_dma_map_page(struct device *dev, struct page *page, 222 unsigned long offset, size_t size, enum dma_data_direction dir, 223 struct dma_attrs *attrs) 224{ 225 void *va = phys_to_virt(page_to_phys(page)) + offset; 226 struct mic_device *mdev = dev_get_drvdata(dev->parent); 227 228 return mic_map_single(mdev, va, size); 229} 230 231static void 232mic_dma_unmap_page(struct device *dev, dma_addr_t dma_addr, 233 size_t size, enum dma_data_direction dir, 234 struct dma_attrs *attrs) 235{ 236 struct mic_device *mdev = dev_get_drvdata(dev->parent); 237 mic_unmap_single(mdev, dma_addr, size); 238} 239 240static struct dma_map_ops mic_dma_ops = { 241 .map_page = mic_dma_map_page, 242 .unmap_page = mic_dma_unmap_page, 243}; 244 245static struct mic_irq * 246_mic_request_threaded_irq(struct mbus_device *mbdev, 247 irq_handler_t handler, irq_handler_t thread_fn, 248 const char *name, void *data, int intr_src) 249{ 250 return mic_request_threaded_irq(mbdev_to_mdev(mbdev), handler, 251 thread_fn, name, data, 252 intr_src, MIC_INTR_DMA); 253} 254 255static void _mic_free_irq(struct mbus_device *mbdev, 256 struct mic_irq *cookie, void *data) 257{ 258 return mic_free_irq(mbdev_to_mdev(mbdev), cookie, data); 259} 260 261static void _mic_ack_interrupt(struct mbus_device *mbdev, int num) 262{ 263 struct mic_device *mdev = mbdev_to_mdev(mbdev); 264 mdev->ops->intr_workarounds(mdev); 265} 266 267static struct mbus_hw_ops mbus_hw_ops = { 268 .request_threaded_irq = _mic_request_threaded_irq, 269 .free_irq = _mic_free_irq, 270 .ack_interrupt = _mic_ack_interrupt, 271}; 272 273/* Initialize the MIC bootparams */ 274void mic_bootparam_init(struct mic_device *mdev) 275{ 276 struct mic_bootparam *bootparam = mdev->dp; 277 278 bootparam->magic = cpu_to_le32(MIC_MAGIC); 279 bootparam->h2c_config_db = -1; 280 bootparam->node_id = mdev->id + 1; 281 bootparam->scif_host_dma_addr = 0x0; 282 bootparam->scif_card_dma_addr = 0x0; 283 bootparam->c2h_scif_db = -1; 284 bootparam->h2c_scif_db = -1; 285} 286 287static inline struct mic_device *cosmdev_to_mdev(struct cosm_device *cdev) 288{ 289 return dev_get_drvdata(cdev->dev.parent); 290} 291 292static void _mic_reset(struct cosm_device *cdev) 293{ 294 struct mic_device *mdev = cosmdev_to_mdev(cdev); 295 296 mdev->ops->reset_fw_ready(mdev); 297 mdev->ops->reset(mdev); 298} 299 300static bool _mic_ready(struct cosm_device *cdev) 301{ 302 struct mic_device *mdev = cosmdev_to_mdev(cdev); 303 304 return mdev->ops->is_fw_ready(mdev); 305} 306 307/** 308 * mic_request_dma_chans - Request DMA channels 309 * @mdev: pointer to mic_device instance 310 * 311 * returns number of DMA channels acquired 312 */ 313static int mic_request_dma_chans(struct mic_device *mdev) 314{ 315 dma_cap_mask_t mask; 316 struct dma_chan *chan; 317 318 request_module("mic_x100_dma"); 319 dma_cap_zero(mask); 320 dma_cap_set(DMA_MEMCPY, mask); 321 322 do { 323 chan = dma_request_channel(mask, mdev->ops->dma_filter, 324 &mdev->pdev->dev); 325 if (chan) { 326 mdev->dma_ch[mdev->num_dma_ch++] = chan; 327 if (mdev->num_dma_ch >= MIC_MAX_DMA_CHAN) 328 break; 329 } 330 } while (chan); 331 dev_info(&mdev->pdev->dev, "DMA channels # %d\n", mdev->num_dma_ch); 332 return mdev->num_dma_ch; 333} 334 335/** 336 * mic_free_dma_chans - release DMA channels 337 * @mdev: pointer to mic_device instance 338 * 339 * returns none 340 */ 341static void mic_free_dma_chans(struct mic_device *mdev) 342{ 343 int i = 0; 344 345 for (i = 0; i < mdev->num_dma_ch; i++) { 346 dma_release_channel(mdev->dma_ch[i]); 347 mdev->dma_ch[i] = NULL; 348 } 349 mdev->num_dma_ch = 0; 350} 351 352/** 353 * _mic_start - Start the MIC. 354 * @cdev: pointer to cosm_device instance 355 * @id: MIC device id/index provided by COSM used in other drivers like SCIF 356 * 357 * This function prepares an MIC for boot and initiates boot. 358 * RETURNS: An appropriate -ERRNO error value on error, or zero for success. 359 * 360 * For all cosm_hw_ops the caller holds a mutex to ensure serialization. 361 */ 362static int _mic_start(struct cosm_device *cdev, int id) 363{ 364 struct mic_device *mdev = cosmdev_to_mdev(cdev); 365 int rc; 366 367 mic_bootparam_init(mdev); 368 mdev->dma_mbdev = mbus_register_device(&mdev->pdev->dev, 369 MBUS_DEV_DMA_HOST, &mic_dma_ops, 370 &mbus_hw_ops, id, mdev->mmio.va); 371 if (IS_ERR(mdev->dma_mbdev)) { 372 rc = PTR_ERR(mdev->dma_mbdev); 373 goto unlock_ret; 374 } 375 if (!mic_request_dma_chans(mdev)) { 376 rc = -ENODEV; 377 goto dma_remove; 378 } 379 mdev->scdev = scif_register_device(&mdev->pdev->dev, MIC_SCIF_DEV, 380 &__mic_dma_ops, &scif_hw_ops, 381 id + 1, 0, &mdev->mmio, 382 &mdev->aper, mdev->dp, NULL, 383 mdev->dma_ch, mdev->num_dma_ch, 384 true); 385 if (IS_ERR(mdev->scdev)) { 386 rc = PTR_ERR(mdev->scdev); 387 goto dma_free; 388 } 389 390 rc = mdev->ops->load_mic_fw(mdev, NULL); 391 if (rc) 392 goto scif_remove; 393 mic_smpt_restore(mdev); 394 mic_intr_restore(mdev); 395 mdev->intr_ops->enable_interrupts(mdev); 396 mdev->ops->write_spad(mdev, MIC_DPLO_SPAD, mdev->dp_dma_addr); 397 mdev->ops->write_spad(mdev, MIC_DPHI_SPAD, mdev->dp_dma_addr >> 32); 398 mdev->ops->send_firmware_intr(mdev); 399 goto unlock_ret; 400scif_remove: 401 scif_unregister_device(mdev->scdev); 402dma_free: 403 mic_free_dma_chans(mdev); 404dma_remove: 405 mbus_unregister_device(mdev->dma_mbdev); 406unlock_ret: 407 return rc; 408} 409 410/** 411 * _mic_stop - Prepare the MIC for reset and trigger reset. 412 * @cdev: pointer to cosm_device instance 413 * @force: force a MIC to reset even if it is already offline. 414 * 415 * RETURNS: None. 416 */ 417static void _mic_stop(struct cosm_device *cdev, bool force) 418{ 419 struct mic_device *mdev = cosmdev_to_mdev(cdev); 420 421 /* 422 * Since SCIF handles card shutdown and reset (using COSM), it will 423 * will be the first to be registered and the last to be 424 * unregistered. 425 */ 426 mic_virtio_reset_devices(mdev); 427 scif_unregister_device(mdev->scdev); 428 mic_free_dma_chans(mdev); 429 mbus_unregister_device(mdev->dma_mbdev); 430 mic_bootparam_init(mdev); 431} 432 433static ssize_t _mic_family(struct cosm_device *cdev, char *buf) 434{ 435 struct mic_device *mdev = cosmdev_to_mdev(cdev); 436 static const char *family[MIC_FAMILY_LAST] = { "x100", "Unknown" }; 437 438 return scnprintf(buf, PAGE_SIZE, "%s\n", family[mdev->family]); 439} 440 441static ssize_t _mic_stepping(struct cosm_device *cdev, char *buf) 442{ 443 struct mic_device *mdev = cosmdev_to_mdev(cdev); 444 const char *string = "??"; 445 446 switch (mdev->stepping) { 447 case MIC_A0_STEP: 448 string = "A0"; 449 break; 450 case MIC_B0_STEP: 451 string = "B0"; 452 break; 453 case MIC_B1_STEP: 454 string = "B1"; 455 break; 456 case MIC_C0_STEP: 457 string = "C0"; 458 break; 459 default: 460 break; 461 } 462 return scnprintf(buf, PAGE_SIZE, "%s\n", string); 463} 464 465static struct mic_mw *_mic_aper(struct cosm_device *cdev) 466{ 467 struct mic_device *mdev = cosmdev_to_mdev(cdev); 468 469 return &mdev->aper; 470} 471 472struct cosm_hw_ops cosm_hw_ops = { 473 .reset = _mic_reset, 474 .force_reset = _mic_reset, 475 .post_reset = NULL, 476 .ready = _mic_ready, 477 .start = _mic_start, 478 .stop = _mic_stop, 479 .family = _mic_family, 480 .stepping = _mic_stepping, 481 .aper = _mic_aper, 482};