From 8d91c1e411f55d7ea91b1183a2e9f8088fb4d5be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Fabian=20Silva=20Delgado?= Date: Tue, 15 Dec 2015 14:52:16 -0300 Subject: Linux-libre 4.3.2-gnu --- arch/mips/cavium-octeon/dma-octeon.c | 8 -- .../cavium-octeon/executive/cvmx-helper-board.c | 6 + .../cavium-octeon/executive/cvmx-helper-util.c | 20 ++- .../cavium-octeon/executive/cvmx-helper-xaui.c | 14 +- arch/mips/cavium-octeon/executive/cvmx-helper.c | 17 +++ arch/mips/cavium-octeon/executive/cvmx-pko.c | 149 ++++++++++++++++++++- arch/mips/cavium-octeon/octeon-irq.c | 38 +++--- arch/mips/cavium-octeon/setup.c | 2 +- 8 files changed, 217 insertions(+), 37 deletions(-) (limited to 'arch/mips/cavium-octeon') diff --git a/arch/mips/cavium-octeon/dma-octeon.c b/arch/mips/cavium-octeon/dma-octeon.c index d8960d464..2cd45f5f9 100644 --- a/arch/mips/cavium-octeon/dma-octeon.c +++ b/arch/mips/cavium-octeon/dma-octeon.c @@ -161,9 +161,6 @@ static void *octeon_dma_alloc_coherent(struct device *dev, size_t size, { void *ret; - if (dma_alloc_from_coherent(dev, size, dma_handle, &ret)) - return ret; - /* ignore region specifiers */ gfp &= ~(__GFP_DMA | __GFP_DMA32 | __GFP_HIGHMEM); @@ -194,11 +191,6 @@ static void *octeon_dma_alloc_coherent(struct device *dev, size_t size, static void octeon_dma_free_coherent(struct device *dev, size_t size, void *vaddr, dma_addr_t dma_handle, struct dma_attrs *attrs) { - int order = get_order(size); - - if (dma_release_from_coherent(dev, order, vaddr)) - return; - swiotlb_free_coherent(dev, size, vaddr, dma_handle); } diff --git a/arch/mips/cavium-octeon/executive/cvmx-helper-board.c b/arch/mips/cavium-octeon/executive/cvmx-helper-board.c index 9eb0feef4..36e30d65b 100644 --- a/arch/mips/cavium-octeon/executive/cvmx-helper-board.c +++ b/arch/mips/cavium-octeon/executive/cvmx-helper-board.c @@ -195,6 +195,12 @@ int cvmx_helper_board_get_mii_address(int ipd_port) return 8; else return -1; + case CVMX_BOARD_TYPE_KONTRON_S1901: + if (ipd_port == CVMX_HELPER_BOARD_MGMT_IPD_PORT) + return 1; + else + return -1; + } /* Some unknown board. Somebody forgot to update this function... */ diff --git a/arch/mips/cavium-octeon/executive/cvmx-helper-util.c b/arch/mips/cavium-octeon/executive/cvmx-helper-util.c index 453d7f664..b45b29757 100644 --- a/arch/mips/cavium-octeon/executive/cvmx-helper-util.c +++ b/arch/mips/cavium-octeon/executive/cvmx-helper-util.c @@ -95,9 +95,9 @@ int cvmx_helper_dump_packet(cvmx_wqe_t *work) uint8_t *data_address; uint8_t *end_of_data; - cvmx_dprintf("Packet Length: %u\n", work->len); - cvmx_dprintf(" Input Port: %u\n", work->ipprt); - cvmx_dprintf(" QoS: %u\n", work->qos); + cvmx_dprintf("Packet Length: %u\n", work->word1.len); + cvmx_dprintf(" Input Port: %u\n", cvmx_wqe_get_port(work)); + cvmx_dprintf(" QoS: %u\n", cvmx_wqe_get_qos(work)); cvmx_dprintf(" Buffers: %u\n", work->word2.s.bufs); if (work->word2.s.bufs == 0) { @@ -127,7 +127,7 @@ int cvmx_helper_dump_packet(cvmx_wqe_t *work) } } else buffer_ptr = work->packet_ptr; - remaining_bytes = work->len; + remaining_bytes = work->word1.len; while (remaining_bytes) { start_of_buffer = @@ -382,6 +382,10 @@ int cvmx_helper_get_ipd_port(int interface, int port) return port + 32; case 3: return port + 36; + case 4: + return port + 40; + case 5: + return port + 44; } return -1; } @@ -404,6 +408,10 @@ int cvmx_helper_get_interface_num(int ipd_port) return 2; else if (ipd_port < 40) return 3; + else if (ipd_port < 44) + return 4; + else if (ipd_port < 48) + return 5; else cvmx_dprintf("cvmx_helper_get_interface_num: Illegal IPD " "port number\n"); @@ -428,6 +436,10 @@ int cvmx_helper_get_interface_index_num(int ipd_port) return ipd_port & 3; else if (ipd_port < 40) return ipd_port & 3; + else if (ipd_port < 44) + return ipd_port & 3; + else if (ipd_port < 48) + return ipd_port & 3; else cvmx_dprintf("cvmx_helper_get_interface_index_num: " "Illegal IPD port number\n"); diff --git a/arch/mips/cavium-octeon/executive/cvmx-helper-xaui.c b/arch/mips/cavium-octeon/executive/cvmx-helper-xaui.c index 7653b7e92..a56ee590d 100644 --- a/arch/mips/cavium-octeon/executive/cvmx-helper-xaui.c +++ b/arch/mips/cavium-octeon/executive/cvmx-helper-xaui.c @@ -124,6 +124,13 @@ int __cvmx_helper_xaui_enable(int interface) union cvmx_gmxx_tx_int_en gmx_tx_int_en; union cvmx_pcsxx_int_en_reg pcsx_int_en_reg; + /* Setup PKND */ + if (octeon_has_feature(OCTEON_FEATURE_PKND)) { + gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(0, interface)); + gmx_cfg.s.pknd = cvmx_helper_get_ipd_port(interface, 0); + cvmx_write_csr(CVMX_GMXX_PRTX_CFG(0, interface), gmx_cfg.u64); + } + /* (1) Interface has already been enabled. */ /* (2) Disable GMX. */ @@ -151,7 +158,12 @@ int __cvmx_helper_xaui_enable(int interface) /* (4)c Aply reset sequence */ xauiCtl.u64 = cvmx_read_csr(CVMX_PCSXX_CONTROL1_REG(interface)); xauiCtl.s.lo_pwr = 0; - xauiCtl.s.reset = 1; + + /* Issuing a reset here seems to hang some CN68XX chips. */ + if (!OCTEON_IS_MODEL(OCTEON_CN68XX_PASS1_X) && + !OCTEON_IS_MODEL(OCTEON_CN68XX_PASS2_X)) + xauiCtl.s.reset = 1; + cvmx_write_csr(CVMX_PCSXX_CONTROL1_REG(interface), xauiCtl.u64); /* Wait for PCS to come out of reset */ diff --git a/arch/mips/cavium-octeon/executive/cvmx-helper.c b/arch/mips/cavium-octeon/executive/cvmx-helper.c index 7e5cf7a5e..376701f41 100644 --- a/arch/mips/cavium-octeon/executive/cvmx-helper.c +++ b/arch/mips/cavium-octeon/executive/cvmx-helper.c @@ -83,6 +83,8 @@ static cvmx_helper_link_info_t */ int cvmx_helper_get_number_of_interfaces(void) { + if (OCTEON_IS_MODEL(OCTEON_CN68XX)) + return 9; if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX)) return 4; else @@ -656,6 +658,21 @@ static int __cvmx_helper_global_setup_pko(void) fau_to.s.tout_val = 0xfff; fau_to.s.tout_enb = 0; cvmx_write_csr(CVMX_IOB_FAU_TIMEOUT, fau_to.u64); + + if (OCTEON_IS_MODEL(OCTEON_CN68XX)) { + union cvmx_pko_reg_min_pkt min_pkt; + + min_pkt.u64 = 0; + min_pkt.s.size1 = 59; + min_pkt.s.size2 = 59; + min_pkt.s.size3 = 59; + min_pkt.s.size4 = 59; + min_pkt.s.size5 = 59; + min_pkt.s.size6 = 59; + min_pkt.s.size7 = 59; + cvmx_write_csr(CVMX_PKO_REG_MIN_PKT, min_pkt.u64); + } + return 0; } diff --git a/arch/mips/cavium-octeon/executive/cvmx-pko.c b/arch/mips/cavium-octeon/executive/cvmx-pko.c index 008b881cd..87be167a7 100644 --- a/arch/mips/cavium-octeon/executive/cvmx-pko.c +++ b/arch/mips/cavium-octeon/executive/cvmx-pko.c @@ -39,6 +39,143 @@ * Internal state of packet output */ +static int __cvmx_pko_int(int interface, int index) +{ + switch (interface) { + case 0: + return index; + case 1: + return 4; + case 2: + return index + 0x08; + case 3: + return index + 0x0c; + case 4: + return index + 0x10; + case 5: + return 0x1c; + case 6: + return 0x1d; + case 7: + return 0x1e; + case 8: + return 0x1f; + default: + return -1; + } +} + +static void __cvmx_pko_iport_config(int pko_port) +{ + int queue; + const int num_queues = 1; + const int base_queue = pko_port; + const int static_priority_end = 1; + const int static_priority_base = 1; + + for (queue = 0; queue < num_queues; queue++) { + union cvmx_pko_mem_iqueue_ptrs config; + cvmx_cmd_queue_result_t cmd_res; + uint64_t *buf_ptr; + + config.u64 = 0; + config.s.index = queue; + config.s.qid = base_queue + queue; + config.s.ipid = pko_port; + config.s.tail = (queue == (num_queues - 1)); + config.s.s_tail = (queue == static_priority_end); + config.s.static_p = (static_priority_base >= 0); + config.s.static_q = (queue <= static_priority_end); + config.s.qos_mask = 0xff; + + cmd_res = cvmx_cmd_queue_initialize( + CVMX_CMD_QUEUE_PKO(base_queue + queue), + CVMX_PKO_MAX_QUEUE_DEPTH, + CVMX_FPA_OUTPUT_BUFFER_POOL, + (CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE - + CVMX_PKO_COMMAND_BUFFER_SIZE_ADJUST * 8)); + + WARN(cmd_res, + "%s: cmd_res=%d pko_port=%d base_queue=%d num_queues=%d queue=%d\n", + __func__, (int)cmd_res, pko_port, base_queue, + num_queues, queue); + + buf_ptr = (uint64_t *)cvmx_cmd_queue_buffer( + CVMX_CMD_QUEUE_PKO(base_queue + queue)); + config.s.buf_ptr = cvmx_ptr_to_phys(buf_ptr) >> 7; + CVMX_SYNCWS; + cvmx_write_csr(CVMX_PKO_MEM_IQUEUE_PTRS, config.u64); + } +} + +static void __cvmx_pko_queue_alloc_o68(void) +{ + int port; + + for (port = 0; port < 48; port++) + __cvmx_pko_iport_config(port); +} + +static void __cvmx_pko_port_map_o68(void) +{ + int port; + int interface, index; + cvmx_helper_interface_mode_t mode; + union cvmx_pko_mem_iport_ptrs config; + + /* + * Initialize every iport with the invalid eid. + */ + config.u64 = 0; + config.s.eid = 31; /* Invalid */ + for (port = 0; port < 128; port++) { + config.s.ipid = port; + cvmx_write_csr(CVMX_PKO_MEM_IPORT_PTRS, config.u64); + } + + /* + * Set up PKO_MEM_IPORT_PTRS + */ + for (port = 0; port < 48; port++) { + interface = cvmx_helper_get_interface_num(port); + index = cvmx_helper_get_interface_index_num(port); + mode = cvmx_helper_interface_get_mode(interface); + if (mode == CVMX_HELPER_INTERFACE_MODE_DISABLED) + continue; + + config.s.ipid = port; + config.s.qos_mask = 0xff; + config.s.crc = 1; + config.s.min_pkt = 1; + config.s.intr = __cvmx_pko_int(interface, index); + config.s.eid = config.s.intr; + config.s.pipe = (mode == CVMX_HELPER_INTERFACE_MODE_LOOP) ? + index : port; + cvmx_write_csr(CVMX_PKO_MEM_IPORT_PTRS, config.u64); + } +} + +static void __cvmx_pko_chip_init(void) +{ + int i; + + if (OCTEON_IS_MODEL(OCTEON_CN68XX)) { + __cvmx_pko_port_map_o68(); + __cvmx_pko_queue_alloc_o68(); + return; + } + + /* + * Initialize queues + */ + for (i = 0; i < CVMX_PKO_MAX_OUTPUT_QUEUES; i++) { + const uint64_t priority = 8; + + cvmx_pko_config_port(CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID, i, 1, + &priority); + } +} + /** * Call before any other calls to initialize the packet * output system. This does chip global config, and should only be @@ -47,8 +184,6 @@ void cvmx_pko_initialize_global(void) { - int i; - uint64_t priority = 8; union cvmx_pko_reg_cmd_buf config; /* @@ -62,9 +197,10 @@ void cvmx_pko_initialize_global(void) cvmx_write_csr(CVMX_PKO_REG_CMD_BUF, config.u64); - for (i = 0; i < CVMX_PKO_MAX_OUTPUT_QUEUES; i++) - cvmx_pko_config_port(CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID, i, 1, - &priority); + /* + * Chip-specific setup. + */ + __cvmx_pko_chip_init(); /* * If we aren't using all of the queues optimize PKO's @@ -212,6 +348,9 @@ cvmx_pko_status_t cvmx_pko_config_port(uint64_t port, uint64_t base_queue, int static_priority_base = -1; int static_priority_end = -1; + if (OCTEON_IS_MODEL(OCTEON_CN68XX)) + return CVMX_PKO_SUCCESS; + if ((port >= CVMX_PKO_NUM_OUTPUT_PORTS) && (port != CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID)) { cvmx_dprintf("ERROR: cvmx_pko_config_port: Invalid port %llu\n", diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c index d8124a3c5..0352bc8d5 100644 --- a/arch/mips/cavium-octeon/octeon-irq.c +++ b/arch/mips/cavium-octeon/octeon-irq.c @@ -225,13 +225,14 @@ static int next_cpu_for_irq(struct irq_data *data) #ifdef CONFIG_SMP int cpu; - int weight = cpumask_weight(data->affinity); + struct cpumask *mask = irq_data_get_affinity_mask(data); + int weight = cpumask_weight(mask); struct octeon_ciu_chip_data *cd = irq_data_get_irq_chip_data(data); if (weight > 1) { cpu = cd->current_cpu; for (;;) { - cpu = cpumask_next(cpu, data->affinity); + cpu = cpumask_next(cpu, mask); if (cpu >= nr_cpu_ids) { cpu = -1; continue; @@ -240,7 +241,7 @@ static int next_cpu_for_irq(struct irq_data *data) } } } else if (weight == 1) { - cpu = cpumask_first(data->affinity); + cpu = cpumask_first(mask); } else { cpu = smp_processor_id(); } @@ -662,6 +663,11 @@ static int octeon_irq_ciu_gpio_set_type(struct irq_data *data, unsigned int t) irqd_set_trigger_type(data, t); octeon_irq_gpio_setup(data); + if (irqd_get_trigger_type(data) & IRQ_TYPE_EDGE_BOTH) + irq_set_handler_locked(data, handle_edge_irq); + else + irq_set_handler_locked(data, handle_level_irq); + return IRQ_SET_MASK_OK; } @@ -696,32 +702,23 @@ static void octeon_irq_ciu_gpio_ack(struct irq_data *data) cvmx_write_csr(CVMX_GPIO_INT_CLR, mask); } -static void octeon_irq_handle_trigger(unsigned int irq, struct irq_desc *desc) -{ - struct irq_data *data = irq_desc_get_irq_data(desc); - - if (irqd_get_trigger_type(data) & IRQ_TYPE_EDGE_BOTH) - handle_edge_irq(irq, desc); - else - handle_level_irq(irq, desc); -} - #ifdef CONFIG_SMP static void octeon_irq_cpu_offline_ciu(struct irq_data *data) { int cpu = smp_processor_id(); cpumask_t new_affinity; + struct cpumask *mask = irq_data_get_affinity_mask(data); - if (!cpumask_test_cpu(cpu, data->affinity)) + if (!cpumask_test_cpu(cpu, mask)) return; - if (cpumask_weight(data->affinity) > 1) { + if (cpumask_weight(mask) > 1) { /* * It has multi CPU affinity, just remove this CPU * from the affinity set. */ - cpumask_copy(&new_affinity, data->affinity); + cpumask_copy(&new_affinity, mask); cpumask_clear_cpu(cpu, &new_affinity); } else { /* Otherwise, put it on lowest numbered online CPU. */ @@ -1227,8 +1224,13 @@ static int octeon_irq_gpio_map(struct irq_domain *d, octeon_irq_ciu_to_irq[line][bit] != 0) return -EINVAL; + /* + * Default to handle_level_irq. If the DT contains a different + * trigger type, it will call the irq_set_type callback and + * the handler gets updated. + */ r = octeon_irq_set_ciu_mapping(virq, line, bit, hw, - octeon_irq_gpio_chip, octeon_irq_handle_trigger); + octeon_irq_gpio_chip, handle_level_irq); return r; } @@ -2219,7 +2221,7 @@ static irqreturn_t octeon_irq_cib_handler(int my_irq, void *data) if (irqd_get_trigger_type(irq_data) & IRQ_TYPE_EDGE_BOTH) cvmx_write_csr(host_data->raw_reg, 1ull << i); - generic_handle_irq_desc(irq, desc); + generic_handle_irq_desc(desc); } } diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c index 89a628455..bd634259e 100644 --- a/arch/mips/cavium-octeon/setup.c +++ b/arch/mips/cavium-octeon/setup.c @@ -933,7 +933,7 @@ void __init plat_mem_setup(void) while ((boot_mem_map.nr_map < BOOT_MEM_MAP_MAX) && (total < MAX_MEMORY)) { memory = cvmx_bootmem_phy_alloc(mem_alloc_size, - __pa_symbol(&__init_end), -1, + __pa_symbol(&_end), -1, 0x100000, CVMX_BOOTMEM_FLAG_NO_LOCKING); if (memory >= 0) { -- cgit v1.2.3