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

misc: mic: MIC card driver specific changes to enable SCIF

MIC card driver specific changes to enable SCIF. This patch implements
the SCIF hardware bus operations and registers a SCIF device on the
SCIF hardware bus.

Reviewed-by: Nikhil Rao <nikhil.rao@intel.com>
Signed-off-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
dd8d8d44 74321d4c

+201 -6
+1 -1
drivers/misc/mic/Kconfig
··· 56 56 57 57 config INTEL_MIC_CARD 58 58 tristate "Intel MIC Card Driver" 59 - depends on 64BIT && X86 && INTEL_MIC_BUS 59 + depends on 64BIT && X86 && INTEL_MIC_BUS && SCIF_BUS 60 60 select VIRTIO 61 61 help 62 62 This enables card driver support for the Intel Many Integrated
+131 -1
drivers/misc/mic/card/mic_device.c
··· 28 28 #include <linux/pci.h> 29 29 #include <linux/interrupt.h> 30 30 #include <linux/reboot.h> 31 + #include <linux/dmaengine.h> 32 + #include <linux/kmod.h> 31 33 32 34 #include <linux/mic_common.h> 33 35 #include "../common/mic_dev.h" ··· 242 240 kfree(mdrv->irq_info.irq_usage_count); 243 241 } 244 242 243 + static inline struct mic_driver *scdev_to_mdrv(struct scif_hw_dev *scdev) 244 + { 245 + return dev_get_drvdata(scdev->dev.parent); 246 + } 247 + 248 + static struct mic_irq * 249 + ___mic_request_irq(struct scif_hw_dev *scdev, 250 + irqreturn_t (*func)(int irq, void *data), 251 + const char *name, void *data, 252 + int db) 253 + { 254 + return mic_request_card_irq(func, NULL, name, data, db); 255 + } 256 + 257 + static void 258 + ___mic_free_irq(struct scif_hw_dev *scdev, 259 + struct mic_irq *cookie, void *data) 260 + { 261 + return mic_free_card_irq(cookie, data); 262 + } 263 + 264 + static void ___mic_ack_interrupt(struct scif_hw_dev *scdev, int num) 265 + { 266 + struct mic_driver *mdrv = scdev_to_mdrv(scdev); 267 + 268 + mic_ack_interrupt(&mdrv->mdev); 269 + } 270 + 271 + static int ___mic_next_db(struct scif_hw_dev *scdev) 272 + { 273 + return mic_next_card_db(); 274 + } 275 + 276 + static void ___mic_send_intr(struct scif_hw_dev *scdev, int db) 277 + { 278 + struct mic_driver *mdrv = scdev_to_mdrv(scdev); 279 + 280 + mic_send_intr(&mdrv->mdev, db); 281 + } 282 + 283 + static void ___mic_send_p2p_intr(struct scif_hw_dev *scdev, int db, 284 + struct mic_mw *mw) 285 + { 286 + mic_send_p2p_intr(db, mw); 287 + } 288 + 289 + static void __iomem * 290 + ___mic_ioremap(struct scif_hw_dev *scdev, 291 + phys_addr_t pa, size_t len) 292 + { 293 + struct mic_driver *mdrv = scdev_to_mdrv(scdev); 294 + 295 + return mic_card_map(&mdrv->mdev, pa, len); 296 + } 297 + 298 + static void ___mic_iounmap(struct scif_hw_dev *scdev, void __iomem *va) 299 + { 300 + struct mic_driver *mdrv = scdev_to_mdrv(scdev); 301 + 302 + mic_card_unmap(&mdrv->mdev, va); 303 + } 304 + 305 + static struct scif_hw_ops scif_hw_ops = { 306 + .request_irq = ___mic_request_irq, 307 + .free_irq = ___mic_free_irq, 308 + .ack_interrupt = ___mic_ack_interrupt, 309 + .next_db = ___mic_next_db, 310 + .send_intr = ___mic_send_intr, 311 + .send_p2p_intr = ___mic_send_p2p_intr, 312 + .ioremap = ___mic_ioremap, 313 + .iounmap = ___mic_iounmap, 314 + }; 315 + 316 + static int mic_request_dma_chans(struct mic_driver *mdrv) 317 + { 318 + dma_cap_mask_t mask; 319 + struct dma_chan *chan; 320 + 321 + request_module("mic_x100_dma"); 322 + dma_cap_zero(mask); 323 + dma_cap_set(DMA_MEMCPY, mask); 324 + 325 + do { 326 + chan = dma_request_channel(mask, NULL, NULL); 327 + if (chan) { 328 + mdrv->dma_ch[mdrv->num_dma_ch++] = chan; 329 + if (mdrv->num_dma_ch >= MIC_MAX_DMA_CHAN) 330 + break; 331 + } 332 + } while (chan); 333 + dev_info(mdrv->dev, "DMA channels # %d\n", mdrv->num_dma_ch); 334 + return mdrv->num_dma_ch; 335 + } 336 + 337 + static void mic_free_dma_chans(struct mic_driver *mdrv) 338 + { 339 + int i = 0; 340 + 341 + for (i = 0; i < mdrv->num_dma_ch; i++) { 342 + dma_release_channel(mdrv->dma_ch[i]); 343 + mdrv->dma_ch[i] = NULL; 344 + } 345 + mdrv->num_dma_ch = 0; 346 + } 347 + 245 348 /* 246 349 * mic_driver_init - MIC driver initialization tasks. 247 350 * ··· 355 248 int __init mic_driver_init(struct mic_driver *mdrv) 356 249 { 357 250 int rc; 251 + struct mic_bootparam __iomem *bootparam; 252 + u8 node_id; 358 253 359 254 g_drv = mdrv; 360 255 /* ··· 377 268 rc = mic_shutdown_init(); 378 269 if (rc) 379 270 goto irq_uninit; 271 + if (!mic_request_dma_chans(mdrv)) { 272 + rc = -ENODEV; 273 + goto shutdown_uninit; 274 + } 380 275 rc = mic_devices_init(mdrv); 381 276 if (rc) 382 - goto shutdown_uninit; 277 + goto dma_free; 278 + bootparam = mdrv->dp; 279 + node_id = ioread8(&bootparam->node_id); 280 + mdrv->scdev = scif_register_device(mdrv->dev, MIC_SCIF_DEV, 281 + NULL, &scif_hw_ops, 282 + 0, node_id, &mdrv->mdev.mmio, NULL, 283 + NULL, mdrv->dp, mdrv->dma_ch, 284 + mdrv->num_dma_ch); 285 + if (IS_ERR(mdrv->scdev)) { 286 + rc = PTR_ERR(mdrv->scdev); 287 + goto device_uninit; 288 + } 383 289 mic_create_card_debug_dir(mdrv); 384 290 atomic_notifier_chain_register(&panic_notifier_list, &mic_panic); 385 291 done: 386 292 return rc; 293 + device_uninit: 294 + mic_devices_uninit(mdrv); 295 + dma_free: 296 + mic_free_dma_chans(mdrv); 387 297 shutdown_uninit: 388 298 mic_shutdown_uninit(); 389 299 irq_uninit: ··· 422 294 void mic_driver_uninit(struct mic_driver *mdrv) 423 295 { 424 296 mic_delete_card_debug_dir(mdrv); 297 + scif_unregister_device(mdrv->scdev); 425 298 mic_devices_uninit(mdrv); 299 + mic_free_dma_chans(mdrv); 426 300 /* 427 301 * Inform the host about the shutdown status i.e. poweroff/restart etc. 428 302 * The module cannot be unloaded so the only code path to call
+9 -2
drivers/misc/mic/card/mic_device.h
··· 29 29 30 30 #include <linux/workqueue.h> 31 31 #include <linux/io.h> 32 - #include <linux/irqreturn.h> 33 32 #include <linux/interrupt.h> 34 33 #include <linux/mic_bus.h> 34 + #include "../bus/scif_bus.h" 35 35 36 36 /** 37 37 * struct mic_intr_info - Contains h/w specific interrupt sources info ··· 73 73 * @irq_info: The OS specific irq information 74 74 * @intr_info: H/W specific interrupt information. 75 75 * @dma_mbdev: dma device on the MIC virtual bus. 76 + * @dma_ch - Array of DMA channels 77 + * @num_dma_ch - Number of DMA channels available 78 + * @scdev: SCIF device on the SCIF virtual bus. 76 79 */ 77 80 struct mic_driver { 78 81 char name[20]; ··· 87 84 struct mic_irq_info irq_info; 88 85 struct mic_intr_info intr_info; 89 86 struct mbus_device *dma_mbdev; 87 + struct dma_chan *dma_ch[MIC_MAX_DMA_CHAN]; 88 + int num_dma_ch; 89 + struct scif_hw_dev *scdev; 90 90 }; 91 91 92 92 /** ··· 128 122 int mic_next_card_db(void); 129 123 struct mic_irq * 130 124 mic_request_card_irq(irq_handler_t handler, irq_handler_t thread_fn, 131 - const char *name, void *data, int intr_src); 125 + const char *name, void *data, int db); 132 126 void mic_free_card_irq(struct mic_irq *cookie, void *data); 133 127 u32 mic_read_spad(struct mic_device *mdev, unsigned int idx); 134 128 void mic_send_intr(struct mic_device *mdev, int doorbell); 129 + void mic_send_p2p_intr(int doorbell, struct mic_mw *mw); 135 130 int mic_db_to_irq(struct mic_driver *mdrv, int db); 136 131 u32 mic_ack_interrupt(struct mic_device *mdev); 137 132 void mic_hw_intr_init(struct mic_driver *mdrv);
+59 -2
drivers/misc/mic/card/mic_x100.c
··· 70 70 (MIC_X100_SBOX_SDBIC0 + (4 * doorbell))); 71 71 } 72 72 73 + /* 74 + * mic_x100_send_sbox_intr - Send an MIC_X100_SBOX interrupt to MIC. 75 + */ 76 + static 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 + 95 + static 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 + 73 108 /** 74 109 * mic_ack_interrupt - Device specific interrupt handling. 75 110 * @mdev: pointer to mic_device instance ··· 124 89 static inline int mic_get_rdmasr_irq(int index) 125 90 { 126 91 return MIC_X100_RDMASR_IRQ_BASE + index; 92 + } 93 + 94 + void mic_send_p2p_intr(int db, struct mic_mw *mw) 95 + { 96 + int rdmasr_index; 97 + 98 + if (db < MIC_X100_NUM_SBOX_IRQ) { 99 + mic_x100_send_sbox_intr(mw, db); 100 + } else { 101 + rdmasr_index = db - MIC_X100_NUM_SBOX_IRQ; 102 + mic_x100_send_rdmasr_intr(mw, rdmasr_index); 103 + } 127 104 } 128 105 129 106 /** ··· 160 113 int mic_db_to_irq(struct mic_driver *mdrv, int db) 161 114 { 162 115 int rdmasr_index; 116 + 117 + /* 118 + * The total number of doorbell interrupts on the card are 16. Indices 119 + * 0-8 falls in the SBOX category and 8-15 fall in the RDMASR category. 120 + */ 163 121 if (db < MIC_X100_NUM_SBOX_IRQ) { 164 122 return mic_get_sbox_irq(db); 165 123 } else { 166 - rdmasr_index = db - MIC_X100_NUM_SBOX_IRQ + 167 - MIC_X100_RDMASR_IRQ_BASE; 124 + rdmasr_index = db - MIC_X100_NUM_SBOX_IRQ; 168 125 return mic_get_rdmasr_irq(rdmasr_index); 169 126 } 170 127 } ··· 294 243 mic_remove(pdev); 295 244 } 296 245 246 + static u64 mic_dma_mask = DMA_BIT_MASK(64); 247 + 297 248 static struct platform_device mic_platform_dev = { 298 249 .name = mic_driver_name, 299 250 .id = 0, 300 251 .num_resources = 0, 252 + .dev = { 253 + .dma_mask = &mic_dma_mask, 254 + .coherent_dma_mask = DMA_BIT_MASK(64), 255 + }, 301 256 }; 302 257 303 258 static struct platform_driver __refdata mic_platform_driver = {
+1
drivers/misc/mic/card/mic_x100.h
··· 35 35 #define MIC_X100_SBOX_SDBIC0 0x0000CC90 36 36 #define MIC_X100_SBOX_SDBIC0_DBREQ_BIT 0x80000000 37 37 #define MIC_X100_SBOX_RDMASR0 0x0000B180 38 + #define MIC_X100_SBOX_APICICR0 0x0000A9D0 38 39 39 40 #define MIC_X100_MAX_DOORBELL_IDX 8 40 41