/** * md_mic_dma_chan_unmask_intr - Unmask or enable interrupts * @chan: The DMA channel handle */ void md_mic_dma_chan_unmask_intr(struct mic_dma_device *dma_dev, struct md_mic_dma_chan *chan) { uint32_t dcar; uint32_t chan_num; CHECK_CHAN(chan); chan_num = chan->ch_num; dcar = md_mic_dma_read_mmio(dma_dev, chan_num, REG_DCAR); if (MIC_DMA_CHAN_MIC_OWNED == chan->owner) dcar &= ~SBOX_DCAR_IM0; else dcar &= ~SBOX_DCAR_IM1; md_mic_dma_write_mmio(dma_dev, chan_num, REG_DCAR, dcar); /* * This read is completed only after previous write is completed. * It guarantees that, interrupts has been acknowledged to SBOX DMA * This read forces previous write to be commited in memory. * This is the actual fix for HSD# 3497216 based on theoretical * hypothesis that somehow previous write is not truly completed * since for writes as long as transactions are accepted by SBOX * ( not necessarily commited in memory) those write transactions * reported as complete. */ dcar = md_mic_dma_read_mmio(dma_dev, chan_num, REG_DCAR); }
/** * md_mic_dma_chan_get_dstatwb_phys - Compute the value of the DSTAT write back * physical address. * @dma_dev: DMA device. * @chan: The DMA channel handle */ phys_addr_t md_mic_dma_chan_get_dstatwb_phys(struct mic_dma_device *dma_dev, struct md_mic_dma_chan *chan) { uint32_t reg, chan_num; phys_addr_t phys; CHECK_CHAN(chan); chan_num = chan->ch_num; reg = md_mic_dma_read_mmio(dma_dev, chan_num, REG_DSTATWB_HI); phys = reg; reg = md_mic_dma_read_mmio(dma_dev, chan_num, REG_DSTATWB_LO); phys = phys << 32 | reg; return phys; }
/** * md_mic_dma_chan_get_desc_ring_phys - Compute the value of the descriptor ring * base physical address from the descriptor ring attributes register. * @dma_dev: DMA device. * @chan: The DMA channel handle */ phys_addr_t md_mic_dma_chan_get_desc_ring_phys(struct mic_dma_device *dma_dev, struct md_mic_dma_chan *chan) { phys_addr_t phys, phys_hi; uint32_t phys_lo, chan_num, drar_hi; CHECK_CHAN(chan); chan_num = chan->ch_num; phys_lo = md_mic_dma_read_mmio(dma_dev, chan_num, REG_DRAR_LO); drar_hi = md_mic_dma_read_mmio(dma_dev, chan_num, REG_DRAR_HI); phys_hi = drar_hi_to_ba_bits(drar_hi); phys_hi |= drar_hi_to_smpt(drar_hi, chan_num) << 2; phys = phys_lo | (phys_hi << 32); return phys; }
void md_mic_dma_chan_set_dcherr(struct mic_dma_device *dma_dev, struct md_mic_dma_chan *chan, uint32_t value) { CHECK_CHAN(chan); md_mic_dma_write_mmio(dma_dev, chan->ch_num, REG_DCHERR, value); printk("dcherr = %d\n", md_mic_dma_read_mmio(dma_dev, chan->ch_num, REG_DCHERR)); }
/** * md_mic_dma_chan_intr_pending - Reads interrupt status to figure out * if an interrupt is pending. * @chan: The DMA channel handle. */ bool md_mic_dma_chan_intr_pending(struct mic_dma_device *dma_dev, struct md_mic_dma_chan *chan) { uint32_t dcar; CHECK_CHAN(chan); dcar = md_mic_dma_read_mmio(dma_dev, chan->ch_num, REG_DCAR); return (dcar >> 26) & 0x1; }
/** * md_mic_dma_print_debug - Print channel debug information * @chan: The DMA channel handle * @sbuf: Print to an sbuf if not NULL else prints to console */ void md_mic_dma_print_debug(struct mic_dma_device *dma_dev, struct md_mic_dma_chan *chan) { uint32_t dcr; uint32_t dcar; uint32_t dtpr; uint32_t dhpr; uint32_t drar_lo; uint32_t drar_hi; uint32_t dstat; uint32_t chan_num = chan->ch_num; dcr = mic_sbox_read_mmio(dma_dev->mm_sbox, SBOX_DCR); dcar = md_mic_dma_read_mmio(dma_dev, chan_num, REG_DCAR); dtpr = md_mic_dma_read_mmio(dma_dev, chan_num, REG_DTPR); dhpr = md_mic_dma_read_mmio(dma_dev, chan_num, REG_DHPR); drar_lo = md_mic_dma_read_mmio(dma_dev, chan_num, REG_DRAR_LO); drar_hi = md_mic_dma_read_mmio(dma_dev, chan_num, REG_DRAR_HI); dstat = md_mic_dma_read_mmio(dma_dev, chan_num, REG_DSTAT); pr_debug(PR_PREFIX "Chan_Num 0x%x DCR 0x%x DCAR 0x%x DTPR 0x%x" "DHPR 0x%x DRAR_HI 0x%x DRAR_LO 0x%x DSTAT 0x%x\n", chan_num, dcr, dcar, dtpr, dhpr, drar_hi, drar_lo, dstat); pr_debug(PR_PREFIX "DCR 0x%x\n", dcr); }
static int mic_dma_reg_show(struct seq_file *m, void *v) { int i, j, chan_num, size, dtpr; struct mic_dma_ctx_t *dma_ctx = m->private; struct mic_dma_device *dma_dev = &dma_ctx->dma_dev; struct dma_channel *curr_chan; union md_mic_dma_desc desc; seq_printf(m, "========================================" "=======================================\n"); seq_printf(m, "SBOX_DCR: %#x\n", mic_sbox_read_mmio(dma_dev->mm_sbox, SBOX_DCR)); seq_printf(m, "DMA Channel Registers\n"); seq_printf(m, "========================================" "=======================================\n"); seq_printf(m, "%-10s| %-10s %-10s %-10s %-10s %-10s %-10s" #ifdef CONFIG_MK1OM " %-10s %-11s %-14s %-10s" #endif "\n", "Channel", "DCAR", "DTPR", "DHPR", "DRAR_HI", "DRAR_LO", #ifdef CONFIG_MK1OM "DSTATWB_LO", "DSTATWB_HI", "DSTAT_CHERR", "DSTAT_CHERRMSK", #endif "DSTAT"); seq_printf(m, "========================================" "=======================================\n"); #ifdef _MIC_SCIF_ for (i = 0; i < MAX_NUM_DMA_CHAN; i++) { #else for (i = first_dma_chan(); i <= last_dma_chan(); i++) { #endif curr_chan = &dma_ctx->dma_channels[i]; chan_num = curr_chan->ch_num; seq_printf(m, "%-10i| %-#10x %-#10x %-#10x %-#10x" " %-#10x" #ifdef CONFIG_MK1OM " %-#10x %-#11x %-#10x %-#14x" #endif " %-#10x\n", chan_num, md_mic_dma_read_mmio(dma_dev, chan_num, REG_DCAR), md_mic_dma_read_mmio(dma_dev, chan_num, REG_DTPR), md_mic_dma_read_mmio(dma_dev, chan_num, REG_DHPR), md_mic_dma_read_mmio(dma_dev, chan_num, REG_DRAR_HI), md_mic_dma_read_mmio(dma_dev, chan_num, REG_DRAR_LO), #ifdef CONFIG_MK1OM md_mic_dma_read_mmio(dma_dev, chan_num, REG_DSTATWB_LO), md_mic_dma_read_mmio(dma_dev, chan_num, REG_DSTATWB_HI), md_mic_dma_read_mmio(dma_dev, chan_num, REG_DCHERR), md_mic_dma_read_mmio(dma_dev, chan_num, REG_DCHERRMSK), #endif md_mic_dma_read_mmio(dma_dev, chan_num, REG_DSTAT)); } seq_printf(m, "\nDMA Channel Descriptor Rings\n"); seq_printf(m, "========================================" "=======================================\n"); for (i = first_dma_chan(); i <= last_dma_chan(); i++) { curr_chan = &dma_ctx->dma_channels[i]; chan_num = curr_chan->ch_num; dtpr = md_mic_dma_read_mmio(dma_dev, chan_num, REG_DTPR); seq_printf(m, "Channel %i: [", chan_num); size = ((int) md_mic_dma_read_mmio(dma_dev, chan_num, REG_DHPR) - dtpr) % curr_chan->chan->num_desc_in_ring; /* * In KNC B0, empty condition is tail = head -1 */ if (mic_hw_family(dma_ctx->device_num) == FAMILY_KNC && mic_hw_stepping(dma_ctx->device_num) >= KNC_B0_STEP) size -= 1; for (j = 0; j < size; j++) { desc = curr_chan->desc_ring[(j+dtpr) % curr_chan->chan->num_desc_in_ring]; switch (desc.desc.nop.type){ case NOP: seq_printf(m," {Type: NOP, 0x%#llx" " %#llx} ", desc.qwords.qw0, desc.qwords.qw1); case MEMCOPY: seq_printf(m," {Type: MEMCOPY, SAP:" " 0x%#llx, DAP: %#llx, length: %#llx} ", (uint64_t) desc.desc.memcopy.sap, (uint64_t) desc.desc.memcopy.dap, (uint64_t) desc.desc.memcopy.length); break; case STATUS: seq_printf(m," {Type: STATUS, data:" " 0x%#llx, DAP: %#llx, intr: %lli} ", (uint64_t) desc.desc.status.data, (uint64_t) desc.desc.status.dap, (uint64_t) desc.desc.status.intr); break; case GENERAL: seq_printf(m," {Type: GENERAL, " "DAP: %#llx, dword: %#llx} ", (uint64_t) desc.desc.general.dap, (uint64_t) desc.desc.general.data); break; case KEYNONCECNT: seq_printf(m," {Type: KEYNONCECNT, sel: " "%lli, h: %lli, index: %lli, cs: %lli," " value: %#llx} ", (uint64_t) desc.desc.keynoncecnt.sel, (uint64_t) desc.desc.keynoncecnt.h, (uint64_t) desc.desc.keynoncecnt.index, (uint64_t) desc.desc.keynoncecnt.cs, (uint64_t) desc.desc.keynoncecnt.data); break; case KEY: seq_printf(m," {Type: KEY, dest_ind" "ex: %lli, ski: %lli, skap: %#llx ", (uint64_t) desc.desc.key.di, (uint64_t) desc.desc.key.ski, (uint64_t) desc.desc.key.skap); break; default: seq_printf(m," {Uknown Type=%lli ," "%#llx %#llx} ",(uint64_t) desc.desc.nop.type, (uint64_t) desc.qwords.qw0, (uint64_t) desc.qwords.qw1); } } seq_printf(m, "]\n"); if (mic_hw_family(dma_ctx->device_num) == FAMILY_KNC && mic_hw_stepping(dma_ctx->device_num) >= KNC_B0_STEP && curr_chan->chan->dstat_wb_loc) seq_printf(m, "DSTAT_WB = 0x%x\n", *((uint32_t*)curr_chan->chan->dstat_wb_loc)); } return 0; } static int mic_dma_reg_open(struct inode *inode, struct file *file) { return single_open(file, mic_dma_reg_show, PDE_DATA(inode)); } static const struct file_operations mic_dma_reg_fops = { .owner = THIS_MODULE, .open = mic_dma_reg_open, .read = seq_read, .llseek = seq_lseek, .release = single_release }; static void mic_dma_proc_init(struct mic_dma_ctx_t *dma_ctx) { char name[64]; snprintf(name, 63, "%s%d", proc_dma_ring, dma_ctx->device_num); proc_create_data(name, S_IFREG | S_IRUGO, NULL, &mic_dma_ring_fops, dma_ctx); snprintf(name, 63, "%s%d", proc_dma_reg, dma_ctx->device_num); proc_create_data(name, S_IFREG | S_IRUGO, NULL, &mic_dma_reg_fops, dma_ctx); }
uint32_t md_mic_dma_chan_read_tail(struct mic_dma_device *dma_dev, struct md_mic_dma_chan *chan) { CHECK_CHAN(chan); return md_mic_dma_read_mmio(dma_dev, chan->ch_num, REG_DTPR); }
uint32_t md_mic_dma_chan_get_dcherr(struct mic_dma_device *dma_dev, struct md_mic_dma_chan *chan) { CHECK_CHAN(chan); return md_mic_dma_read_mmio(dma_dev, chan->ch_num, REG_DCHERR); }
uint32_t md_mic_dma_chan_read_completion_count(struct mic_dma_device *dma_dev, struct md_mic_dma_chan *chan) { CHECK_CHAN(chan); return (md_mic_dma_read_mmio(dma_dev, chan->ch_num, REG_DSTAT) & 0xffff); }