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

misc: mic: MIC host and card driver changes to enable VOP

This patch modifies the MIC host and card drivers to start using the
VOP driver. The MIC host and card drivers now implement the VOP bus
operations and register a VOP device on the VOP bus. MIC driver stack
documentation is also updated to include the new VOP driver.

Reviewed-by: Ashutosh Dixit <ashutosh.dixit@intel.com>
Signed-off-by: Sudeep Dutt <sudeep.dutt@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Sudeep Dutt and committed by
Greg Kroah-Hartman
c74c9318 8810df37

+247 -33
+30 -24
Documentation/mic/mic_overview.txt
··· 12 12 13 13 Since it is a PCIe card, it does not have the ability to host hardware 14 14 devices for networking, storage and console. We provide these devices 15 - on X100 coprocessors thus enabling a self-bootable equivalent environment 16 - for applications. A key benefit of our solution is that it leverages 17 - the standard virtio framework for network, disk and console devices, 18 - though in our case the virtio framework is used across a PCIe bus. 15 + on X100 coprocessors thus enabling a self-bootable equivalent 16 + environment for applications. A key benefit of our solution is that it 17 + leverages the standard virtio framework for network, disk and console 18 + devices, though in our case the virtio framework is used across a PCIe 19 + bus. A Virtio Over PCIe (VOP) driver allows creating user space 20 + backends or devices on the host which are used to probe virtio drivers 21 + for these devices on the MIC card. The existing VRINGH infrastructure 22 + in the kernel is used to access virtio rings from the host. The card 23 + VOP driver allows card virtio drivers to communicate with their user 24 + space backends on the host via a device page. Ring 3 apps on the host 25 + can add, remove and configure virtio devices. A thin MIC specific 26 + virtio_config_ops is implemented which is borrowed heavily from 27 + previous similar implementations in lguest and s390. 19 28 20 29 MIC PCIe card has a dma controller with 8 channels. These channels are 21 30 shared between the host s/w and the card s/w. 0 to 3 are used by host ··· 47 38 the host to initiate DMA's to/from the card using the MIC DMA engine and 48 39 the fact that the virtio block storage backend can only be on the host. 49 40 50 - | 51 41 +----------+ | +----------+ 52 42 | Card OS | | | Host OS | 53 43 +----------+ | +----------+ ··· 55 47 | Virtio| |Virtio | |Virtio| | |Virtio | |Virtio | |Virtio | 56 48 | Net | |Console | |Block | | |Net | |Console | |Block | 57 49 | Driver| |Driver | |Driver| | |backend | |backend | |backend | 58 - +-------+ +--------+ +------+ | +---------+ +--------+ +--------+ 50 + +---+---+ +---+----+ +--+---+ | +---------+ +----+---+ +--------+ 59 51 | | | | | | | 60 52 | | | |User | | | 61 - | | | |------|------------|---------|------- 62 - +-------------------+ |Kernel +--------------------------+ 63 - | | | Virtio over PCIe IOCTLs | 64 - | | +--------------------------+ 65 - +-----------+ | | | +-----------+ 66 - | MIC DMA | | +------+ | +------+ +------+ | | MIC DMA | 67 - | Driver | | | SCIF | | | SCIF | | COSM | | | Driver | 68 - +-----------+ | +------+ | +------+ +--+---+ | +-----------+ 69 - | | | | | | | | 70 - +---------------+ | +------+ | +--+---+ +--+---+ | +----------------+ 71 - |MIC virtual Bus| | |SCIF | | |SCIF | | COSM | | |MIC virtual Bus | 72 - +---------------+ | |HW Bus| | |HW Bus| | Bus | | +----------------+ 73 - | | +------+ | +--+---+ +------+ | | 74 - | | | | | | | | 75 - | +-----------+---+ | | | +---------------+ | 76 - | |Intel MIC | | | | |Intel MIC | | 77 - +---|Card Driver | | | | |Host Driver | | 78 - +------------+--------+ | +----+---------------+-----+ 53 + | | | |------|------------|--+------|------- 54 + +---------+---------+ |Kernel | 55 + | | | 56 + +---------+ +---+----+ +------+ | +------+ +------+ +--+---+ +-------+ 57 + |MIC DMA | | VOP | | SCIF | | | SCIF | | COSM | | VOP | |MIC DMA| 58 + +---+-----+ +---+----+ +--+---+ | +--+---+ +--+---+ +------+ +----+--+ 59 + | | | | | | | 60 + +---+-----+ +---+----+ +--+---+ | +--+---+ +--+---+ +------+ +----+--+ 61 + |MIC | | VOP | |SCIF | | |SCIF | | COSM | | VOP | | MIC | 62 + |HW Bus | | HW Bus| |HW Bus| | |HW Bus| | Bus | |HW Bus| |HW Bus | 63 + +---------+ +--------+ +--+---+ | +--+---+ +------+ +------+ +-------+ 64 + | | | | | | | 65 + | +-----------+--+ | | | +---------------+ | 66 + | |Intel MIC | | | | |Intel MIC | | 67 + | |Card Driver | | | | |Host Driver | | 68 + +---+--------------+------+ | +----+---------------+-----+ 79 69 | | | 80 70 +-------------------------------------------------------------+ 81 71 | |
+1 -1
Documentation/mic/mpssd/mpss
··· 35 35 36 36 exec=/usr/sbin/mpssd 37 37 sysfs="/sys/class/mic" 38 - mic_modules="mic_host mic_x100_dma scif" 38 + mic_modules="mic_host mic_x100_dma scif vop" 39 39 40 40 start() 41 41 {
+1 -1
Documentation/mic/mpssd/mpssd.c
··· 926 926 char path[PATH_MAX]; 927 927 int fd, err; 928 928 929 - snprintf(path, PATH_MAX, "/dev/mic%d", mic->id); 929 + snprintf(path, PATH_MAX, "/dev/vop_virtio%d", mic->id); 930 930 fd = open(path, O_RDWR); 931 931 if (fd < 0) { 932 932 mpsslog("Could not open %s %s\n", path, strerror(errno));
+4 -3
drivers/misc/mic/Kconfig
··· 53 53 54 54 config INTEL_MIC_HOST 55 55 tristate "Intel MIC Host Driver" 56 - depends on 64BIT && PCI && X86 && INTEL_MIC_BUS && SCIF_BUS && MIC_COSM 57 - select VHOST_RING 56 + depends on 64BIT && PCI && X86 57 + depends on INTEL_MIC_BUS && SCIF_BUS && MIC_COSM && VOP_BUS 58 58 help 59 59 This enables Host Driver support for the Intel Many Integrated 60 60 Core (MIC) family of PCIe form factor coprocessor devices that ··· 73 73 74 74 config INTEL_MIC_CARD 75 75 tristate "Intel MIC Card Driver" 76 - depends on 64BIT && X86 && INTEL_MIC_BUS && SCIF_BUS && MIC_COSM 76 + depends on 64BIT && X86 77 + depends on INTEL_MIC_BUS && SCIF_BUS && MIC_COSM && VOP_BUS 77 78 select VIRTIO 78 79 help 79 80 This enables card driver support for the Intel Many Integrated
+82 -2
drivers/misc/mic/card/mic_device.c
··· 249 249 .iounmap = ___mic_iounmap, 250 250 }; 251 251 252 + static inline struct mic_driver *vpdev_to_mdrv(struct vop_device *vpdev) 253 + { 254 + return dev_get_drvdata(vpdev->dev.parent); 255 + } 256 + 257 + static struct mic_irq * 258 + __mic_request_irq(struct vop_device *vpdev, 259 + irqreturn_t (*func)(int irq, void *data), 260 + const char *name, void *data, int intr_src) 261 + { 262 + return mic_request_card_irq(func, NULL, name, data, intr_src); 263 + } 264 + 265 + static void __mic_free_irq(struct vop_device *vpdev, 266 + struct mic_irq *cookie, void *data) 267 + { 268 + return mic_free_card_irq(cookie, data); 269 + } 270 + 271 + static void __mic_ack_interrupt(struct vop_device *vpdev, int num) 272 + { 273 + struct mic_driver *mdrv = vpdev_to_mdrv(vpdev); 274 + 275 + mic_ack_interrupt(&mdrv->mdev); 276 + } 277 + 278 + static int __mic_next_db(struct vop_device *vpdev) 279 + { 280 + return mic_next_card_db(); 281 + } 282 + 283 + static void __iomem *__mic_get_remote_dp(struct vop_device *vpdev) 284 + { 285 + struct mic_driver *mdrv = vpdev_to_mdrv(vpdev); 286 + 287 + return mdrv->dp; 288 + } 289 + 290 + static void __mic_send_intr(struct vop_device *vpdev, int db) 291 + { 292 + struct mic_driver *mdrv = vpdev_to_mdrv(vpdev); 293 + 294 + mic_send_intr(&mdrv->mdev, db); 295 + } 296 + 297 + static void __iomem *__mic_ioremap(struct vop_device *vpdev, 298 + dma_addr_t pa, size_t len) 299 + { 300 + struct mic_driver *mdrv = vpdev_to_mdrv(vpdev); 301 + 302 + return mic_card_map(&mdrv->mdev, pa, len); 303 + } 304 + 305 + static void __mic_iounmap(struct vop_device *vpdev, void __iomem *va) 306 + { 307 + struct mic_driver *mdrv = vpdev_to_mdrv(vpdev); 308 + 309 + mic_card_unmap(&mdrv->mdev, va); 310 + } 311 + 312 + static struct vop_hw_ops vop_hw_ops = { 313 + .request_irq = __mic_request_irq, 314 + .free_irq = __mic_free_irq, 315 + .ack_interrupt = __mic_ack_interrupt, 316 + .next_db = __mic_next_db, 317 + .get_remote_dp = __mic_get_remote_dp, 318 + .send_intr = __mic_send_intr, 319 + .ioremap = __mic_ioremap, 320 + .iounmap = __mic_iounmap, 321 + }; 322 + 252 323 static int mic_request_dma_chans(struct mic_driver *mdrv) 253 324 { 254 325 dma_cap_mask_t mask; 255 326 struct dma_chan *chan; 256 327 257 - request_module("mic_x100_dma"); 258 328 dma_cap_zero(mask); 259 329 dma_cap_set(DMA_MEMCPY, mask); 260 330 ··· 378 308 rc = -ENODEV; 379 309 goto irq_uninit; 380 310 } 311 + mdrv->vpdev = vop_register_device(mdrv->dev, VOP_DEV_TRNSP, 312 + NULL, &vop_hw_ops, 0, 313 + NULL, mdrv->dma_ch[0]); 314 + if (IS_ERR(mdrv->vpdev)) { 315 + rc = PTR_ERR(mdrv->vpdev); 316 + goto dma_free; 317 + } 381 318 bootparam = mdrv->dp; 382 319 node_id = ioread8(&bootparam->node_id); 383 320 mdrv->scdev = scif_register_device(mdrv->dev, MIC_SCIF_DEV, ··· 394 317 mdrv->num_dma_ch, true); 395 318 if (IS_ERR(mdrv->scdev)) { 396 319 rc = PTR_ERR(mdrv->scdev); 397 - goto dma_free; 320 + goto vop_remove; 398 321 } 399 322 mic_create_card_debug_dir(mdrv); 400 323 done: 401 324 return rc; 325 + vop_remove: 326 + vop_unregister_device(mdrv->vpdev); 402 327 dma_free: 403 328 mic_free_dma_chans(mdrv); 404 329 irq_uninit: ··· 421 342 { 422 343 mic_delete_card_debug_dir(mdrv); 423 344 scif_unregister_device(mdrv->scdev); 345 + vop_unregister_device(mdrv->vpdev); 424 346 mic_free_dma_chans(mdrv); 425 347 mic_uninit_irq(); 426 348 mic_dp_uninit();
+3
drivers/misc/mic/card/mic_device.h
··· 32 32 #include <linux/interrupt.h> 33 33 #include <linux/mic_bus.h> 34 34 #include "../bus/scif_bus.h" 35 + #include "../bus/vop_bus.h" 35 36 36 37 /** 37 38 * struct mic_intr_info - Contains h/w specific interrupt sources info ··· 77 76 * @dma_ch - Array of DMA channels 78 77 * @num_dma_ch - Number of DMA channels available 79 78 * @scdev: SCIF device on the SCIF virtual bus. 79 + * @vpdev: Virtio over PCIe device on the VOP virtual bus. 80 80 */ 81 81 struct mic_driver { 82 82 char name[20]; ··· 92 90 struct dma_chan *dma_ch[MIC_MAX_DMA_CHAN]; 93 91 int num_dma_ch; 94 92 struct scif_hw_dev *scdev; 93 + struct vop_device *vpdev; 95 94 }; 96 95 97 96 /**
+1
drivers/misc/mic/card/mic_x100.c
··· 326 326 goto done; 327 327 } 328 328 329 + request_module("mic_x100_dma"); 329 330 mic_init_card_debugfs(); 330 331 ret = platform_device_register(&mic_platform_dev); 331 332 if (ret) {
+121 -2
drivers/misc/mic/host/mic_boot.c
··· 25 25 #include <linux/mic_common.h> 26 26 #include <linux/mic_bus.h> 27 27 #include "../bus/scif_bus.h" 28 + #include "../bus/vop_bus.h" 28 29 #include "../common/mic_dev.h" 29 30 #include "mic_device.h" 30 31 #include "mic_smpt.h" 32 + 33 + static inline struct mic_device *vpdev_to_mdev(struct device *dev) 34 + { 35 + return dev_get_drvdata(dev->parent); 36 + } 37 + 38 + static dma_addr_t 39 + _mic_dma_map_page(struct device *dev, struct page *page, 40 + unsigned long offset, size_t size, 41 + enum dma_data_direction dir, struct dma_attrs *attrs) 42 + { 43 + void *va = phys_to_virt(page_to_phys(page)) + offset; 44 + struct mic_device *mdev = vpdev_to_mdev(dev); 45 + 46 + return mic_map_single(mdev, va, size); 47 + } 48 + 49 + static void _mic_dma_unmap_page(struct device *dev, dma_addr_t dma_addr, 50 + size_t size, enum dma_data_direction dir, 51 + struct dma_attrs *attrs) 52 + { 53 + struct mic_device *mdev = vpdev_to_mdev(dev); 54 + 55 + mic_unmap_single(mdev, dma_addr, size); 56 + } 57 + 58 + static const struct dma_map_ops _mic_dma_ops = { 59 + .map_page = _mic_dma_map_page, 60 + .unmap_page = _mic_dma_unmap_page, 61 + }; 62 + 63 + static struct mic_irq * 64 + __mic_request_irq(struct vop_device *vpdev, 65 + irqreturn_t (*func)(int irq, void *data), 66 + const char *name, void *data, int intr_src) 67 + { 68 + struct mic_device *mdev = vpdev_to_mdev(&vpdev->dev); 69 + 70 + return mic_request_threaded_irq(mdev, func, NULL, name, data, 71 + intr_src, MIC_INTR_DB); 72 + } 73 + 74 + static void __mic_free_irq(struct vop_device *vpdev, 75 + struct mic_irq *cookie, void *data) 76 + { 77 + struct mic_device *mdev = vpdev_to_mdev(&vpdev->dev); 78 + 79 + return mic_free_irq(mdev, cookie, data); 80 + } 81 + 82 + static void __mic_ack_interrupt(struct vop_device *vpdev, int num) 83 + { 84 + struct mic_device *mdev = vpdev_to_mdev(&vpdev->dev); 85 + 86 + mdev->ops->intr_workarounds(mdev); 87 + } 88 + 89 + static int __mic_next_db(struct vop_device *vpdev) 90 + { 91 + struct mic_device *mdev = vpdev_to_mdev(&vpdev->dev); 92 + 93 + return mic_next_db(mdev); 94 + } 95 + 96 + static void *__mic_get_dp(struct vop_device *vpdev) 97 + { 98 + struct mic_device *mdev = vpdev_to_mdev(&vpdev->dev); 99 + 100 + return mdev->dp; 101 + } 102 + 103 + static void __iomem *__mic_get_remote_dp(struct vop_device *vpdev) 104 + { 105 + return NULL; 106 + } 107 + 108 + static void __mic_send_intr(struct vop_device *vpdev, int db) 109 + { 110 + struct mic_device *mdev = vpdev_to_mdev(&vpdev->dev); 111 + 112 + mdev->ops->send_intr(mdev, db); 113 + } 114 + 115 + static void __iomem *__mic_ioremap(struct vop_device *vpdev, 116 + dma_addr_t pa, size_t len) 117 + { 118 + struct mic_device *mdev = vpdev_to_mdev(&vpdev->dev); 119 + 120 + return mdev->aper.va + pa; 121 + } 122 + 123 + static void __mic_iounmap(struct vop_device *vpdev, void __iomem *va) 124 + { 125 + /* nothing to do */ 126 + } 127 + 128 + static struct vop_hw_ops vop_hw_ops = { 129 + .request_irq = __mic_request_irq, 130 + .free_irq = __mic_free_irq, 131 + .ack_interrupt = __mic_ack_interrupt, 132 + .next_db = __mic_next_db, 133 + .get_dp = __mic_get_dp, 134 + .get_remote_dp = __mic_get_remote_dp, 135 + .send_intr = __mic_send_intr, 136 + .ioremap = __mic_ioremap, 137 + .iounmap = __mic_iounmap, 138 + }; 31 139 32 140 static inline struct mic_device *scdev_to_mdev(struct scif_hw_dev *scdev) 33 141 { ··· 422 314 dma_cap_mask_t mask; 423 315 struct dma_chan *chan; 424 316 425 - request_module("mic_x100_dma"); 426 317 dma_cap_zero(mask); 427 318 dma_cap_set(DMA_MEMCPY, mask); 428 319 ··· 493 386 goto dma_free; 494 387 } 495 388 389 + mdev->vpdev = vop_register_device(&mdev->pdev->dev, 390 + VOP_DEV_TRNSP, &_mic_dma_ops, 391 + &vop_hw_ops, id + 1, &mdev->aper, 392 + mdev->dma_ch[0]); 393 + if (IS_ERR(mdev->vpdev)) { 394 + rc = PTR_ERR(mdev->vpdev); 395 + goto scif_remove; 396 + } 397 + 496 398 rc = mdev->ops->load_mic_fw(mdev, NULL); 497 399 if (rc) 498 - goto scif_remove; 400 + goto vop_remove; 499 401 mic_smpt_restore(mdev); 500 402 mic_intr_restore(mdev); 501 403 mdev->intr_ops->enable_interrupts(mdev); ··· 512 396 mdev->ops->write_spad(mdev, MIC_DPHI_SPAD, mdev->dp_dma_addr >> 32); 513 397 mdev->ops->send_firmware_intr(mdev); 514 398 goto unlock_ret; 399 + vop_remove: 400 + vop_unregister_device(mdev->vpdev); 515 401 scif_remove: 516 402 scif_unregister_device(mdev->scdev); 517 403 dma_free: ··· 540 422 * will be the first to be registered and the last to be 541 423 * unregistered. 542 424 */ 425 + vop_unregister_device(mdev->vpdev); 543 426 scif_unregister_device(mdev->scdev); 544 427 mic_free_dma_chans(mdev); 545 428 mbus_unregister_device(mdev->dma_mbdev);
+3
drivers/misc/mic/host/mic_device.h
··· 29 29 #include <linux/miscdevice.h> 30 30 #include <linux/mic_bus.h> 31 31 #include "../bus/scif_bus.h" 32 + #include "../bus/vop_bus.h" 32 33 #include "../bus/cosm_bus.h" 33 34 #include "mic_intr.h" 34 35 ··· 69 68 * @dma_ch - Array of DMA channels 70 69 * @num_dma_ch - Number of DMA channels available 71 70 * @scdev: SCIF device on the SCIF virtual bus. 71 + * @vpdev: Virtio over PCIe device on the VOP virtual bus. 72 72 * @cosm_dev: COSM device 73 73 */ 74 74 struct mic_device { ··· 94 92 struct dma_chan *dma_ch[MIC_MAX_DMA_CHAN]; 95 93 int num_dma_ch; 96 94 struct scif_hw_dev *scdev; 95 + struct vop_device *vpdev; 97 96 struct cosm_device *cosm_dev; 98 97 }; 99 98
+1
drivers/misc/mic/host/mic_main.c
··· 317 317 { 318 318 int ret; 319 319 320 + request_module("mic_x100_dma"); 320 321 mic_init_debugfs(); 321 322 ida_init(&g_mic_ida); 322 323 ret = pci_register_driver(&mic_driver);