1 /*- 2 * BSD LICENSE 3 * 4 * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include <unistd.h> 35 #include <stdio.h> 36 #include <stdlib.h> 37 #include <stdint.h> 38 #include <signal.h> 39 #include <errno.h> 40 #include <string.h> 41 #include <sys/types.h> 42 #include <sys/epoll.h> 43 #include <sys/queue.h> 44 45 #include <rte_log.h> 46 #include <rte_memory.h> 47 #include <rte_malloc.h> 48 #include <rte_atomic.h> 49 50 51 #include "channel_monitor.h" 52 #include "channel_commands.h" 53 #include "channel_manager.h" 54 #include "power_manager.h" 55 56 #define RTE_LOGTYPE_CHANNEL_MONITOR RTE_LOGTYPE_USER1 57 58 #define MAX_EVENTS 256 59 60 61 static volatile unsigned run_loop = 1; 62 static int global_event_fd; 63 static struct epoll_event *global_events_list; 64 65 void channel_monitor_exit(void) 66 { 67 run_loop = 0; 68 rte_free(global_events_list); 69 } 70 71 static int 72 process_request(struct channel_packet *pkt, struct channel_info *chan_info) 73 { 74 uint64_t core_mask; 75 76 if (chan_info == NULL) 77 return -1; 78 79 if (rte_atomic32_cmpset(&(chan_info->status), CHANNEL_MGR_CHANNEL_CONNECTED, 80 CHANNEL_MGR_CHANNEL_PROCESSING) == 0) 81 return -1; 82 83 if (pkt->command == CPU_POWER) { 84 core_mask = get_pcpus_mask(chan_info, pkt->resource_id); 85 if (core_mask == 0) { 86 RTE_LOG(ERR, CHANNEL_MONITOR, "Error get physical CPU mask for " 87 "channel '%s' using vCPU(%u)\n", chan_info->channel_path, 88 (unsigned)pkt->unit); 89 return -1; 90 } 91 if (__builtin_popcountll(core_mask) == 1) { 92 93 unsigned core_num = __builtin_ffsll(core_mask) - 1; 94 95 switch (pkt->unit) { 96 case(CPU_POWER_SCALE_MIN): 97 power_manager_scale_core_min(core_num); 98 break; 99 case(CPU_POWER_SCALE_MAX): 100 power_manager_scale_core_max(core_num); 101 break; 102 case(CPU_POWER_SCALE_DOWN): 103 power_manager_scale_core_down(core_num); 104 break; 105 case(CPU_POWER_SCALE_UP): 106 power_manager_scale_core_up(core_num); 107 break; 108 default: 109 break; 110 } 111 } else { 112 switch (pkt->unit) { 113 case(CPU_POWER_SCALE_MIN): 114 power_manager_scale_mask_min(core_mask); 115 break; 116 case(CPU_POWER_SCALE_MAX): 117 power_manager_scale_mask_max(core_mask); 118 break; 119 case(CPU_POWER_SCALE_DOWN): 120 power_manager_scale_mask_down(core_mask); 121 break; 122 case(CPU_POWER_SCALE_UP): 123 power_manager_scale_mask_up(core_mask); 124 break; 125 default: 126 break; 127 } 128 129 } 130 } 131 /* Return is not checked as channel status may have been set to DISABLED 132 * from management thread 133 */ 134 rte_atomic32_cmpset(&(chan_info->status), CHANNEL_MGR_CHANNEL_PROCESSING, 135 CHANNEL_MGR_CHANNEL_CONNECTED); 136 return 0; 137 138 } 139 140 int 141 add_channel_to_monitor(struct channel_info **chan_info) 142 { 143 struct channel_info *info = *chan_info; 144 struct epoll_event event; 145 146 event.events = EPOLLIN; 147 event.data.ptr = info; 148 if (epoll_ctl(global_event_fd, EPOLL_CTL_ADD, info->fd, &event) < 0) { 149 RTE_LOG(ERR, CHANNEL_MONITOR, "Unable to add channel '%s' " 150 "to epoll\n", info->channel_path); 151 return -1; 152 } 153 return 0; 154 } 155 156 int 157 remove_channel_from_monitor(struct channel_info *chan_info) 158 { 159 if (epoll_ctl(global_event_fd, EPOLL_CTL_DEL, chan_info->fd, NULL) < 0) { 160 RTE_LOG(ERR, CHANNEL_MONITOR, "Unable to remove channel '%s' " 161 "from epoll\n", chan_info->channel_path); 162 return -1; 163 } 164 return 0; 165 } 166 167 int 168 channel_monitor_init(void) 169 { 170 global_event_fd = epoll_create1(0); 171 if (global_event_fd == 0) { 172 RTE_LOG(ERR, CHANNEL_MONITOR, "Error creating epoll context with " 173 "error %s\n", strerror(errno)); 174 return -1; 175 } 176 global_events_list = rte_malloc("epoll_events", sizeof(*global_events_list) 177 * MAX_EVENTS, RTE_CACHE_LINE_SIZE); 178 if (global_events_list == NULL) { 179 RTE_LOG(ERR, CHANNEL_MONITOR, "Unable to rte_malloc for " 180 "epoll events\n"); 181 return -1; 182 } 183 return 0; 184 } 185 186 void 187 run_channel_monitor(void) 188 { 189 while (run_loop) { 190 int n_events, i; 191 192 n_events = epoll_wait(global_event_fd, global_events_list, 193 MAX_EVENTS, 1); 194 if (!run_loop) 195 break; 196 for (i = 0; i < n_events; i++) { 197 struct channel_info *chan_info = (struct channel_info *) 198 global_events_list[i].data.ptr; 199 if ((global_events_list[i].events & EPOLLERR) || 200 (global_events_list[i].events & EPOLLHUP)) { 201 RTE_LOG(DEBUG, CHANNEL_MONITOR, "Remote closed connection for " 202 "channel '%s'\n", chan_info->channel_path); 203 remove_channel(&chan_info); 204 continue; 205 } 206 if (global_events_list[i].events & EPOLLIN) { 207 208 int n_bytes, err = 0; 209 struct channel_packet pkt; 210 void *buffer = &pkt; 211 int buffer_len = sizeof(pkt); 212 213 while (buffer_len > 0) { 214 n_bytes = read(chan_info->fd, buffer, buffer_len); 215 if (n_bytes == buffer_len) 216 break; 217 if (n_bytes == -1) { 218 err = errno; 219 RTE_LOG(DEBUG, CHANNEL_MONITOR, "Received error on " 220 "channel '%s' read: %s\n", 221 chan_info->channel_path, strerror(err)); 222 remove_channel(&chan_info); 223 break; 224 } 225 buffer = (char *)buffer + n_bytes; 226 buffer_len -= n_bytes; 227 } 228 if (!err) 229 process_request(&pkt, chan_info); 230 } 231 } 232 } 233 } 234