1b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie/* 2b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie * Copyright (C) 2017 The Android Open Source Project 3b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie * 4b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie * Licensed under the Apache License, Version 2.0 (the "License"); 5b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie * you may not use this file except in compliance with the License. 6b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie * You may obtain a copy of the License at 7b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie * 8b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie * http://www.apache.org/licenses/LICENSE-2.0 9b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie * 10b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie * Unless required by applicable law or agreed to in writing, software 11b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie * distributed under the License is distributed on an "AS IS" BASIS, 12b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie * See the License for the specific language governing permissions and 14b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie * limitations under the License. 15b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie */ 16b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie 17b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie#include "chre/platform/slpi/smr_helper.h" 18b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie 19b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie#include <inttypes.h> 20b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie 21b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie#include "chre/platform/assert.h" 22b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie#include "chre/platform/log.h" 238d0e0251dc82dec80d458dada7d5345c1967b556Arthur Ishiguro#include "chre/platform/slpi/power_control_util.h" 24b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie#include "chre/util/lock_guard.h" 25b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie 26b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddienamespace chre { 27b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie 28b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddiesmr_err SmrHelper::releaseSync(smr_client_hndl clientHandle, 29b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie Nanoseconds timeout) { 30b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie // smr_client_release is synchronous for SMR services in the current 31b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie // implementation, so we can't hold the lock while calling it otherwise we'll 32b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie // deadlock in the callback. 33b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie { 34b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie LockGuard<Mutex> lock(mMutex); 35b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie CHRE_ASSERT(!mWaiting); 36b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie mWaiting = true; 37b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie } 38b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie 39b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie smr_err result = smr_client_release( 40b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie clientHandle, SmrHelper::smrReleaseCb, this); 41b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie if (result == SMR_NO_ERR) { 42b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie LockGuard<Mutex> lock(mMutex); 43b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie bool waitSuccess = true; 44b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie while (mWaiting && waitSuccess) { 45b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie waitSuccess = mCond.wait_for(mMutex, timeout); 46b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie } 47b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie 48b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie if (!waitSuccess) { 49b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie LOGE("Releasing SMR client timed out"); 50b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie result = SMR_TIMEOUT_ERR; 51b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie mWaiting = false; 52b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie } 53b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie } 54b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie 55b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie return result; 56b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie} 57b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie 58e0653a607542819b492d789952159a528c9a5e4eArthur Ishigurosmr_err SmrHelper::waitForService(qmi_idl_service_object_type serviceObj, 59e0653a607542819b492d789952159a528c9a5e4eArthur Ishiguro Microseconds timeout) { 60e0653a607542819b492d789952159a528c9a5e4eArthur Ishiguro // smr_client_check_ext is synchronous if the service already exists, 61e0653a607542819b492d789952159a528c9a5e4eArthur Ishiguro // so don't hold the lock while calling to prevent deadlock in the callback. 62e0653a607542819b492d789952159a528c9a5e4eArthur Ishiguro { 63e0653a607542819b492d789952159a528c9a5e4eArthur Ishiguro LockGuard<Mutex> lock(mMutex); 64e0653a607542819b492d789952159a528c9a5e4eArthur Ishiguro CHRE_ASSERT(!mWaiting); 65e0653a607542819b492d789952159a528c9a5e4eArthur Ishiguro mWaiting = true; 66e0653a607542819b492d789952159a528c9a5e4eArthur Ishiguro } 67e0653a607542819b492d789952159a528c9a5e4eArthur Ishiguro 68e0653a607542819b492d789952159a528c9a5e4eArthur Ishiguro smr_err result = smr_client_check_ext(serviceObj, SMR_CLIENT_INSTANCE_ANY, 69e0653a607542819b492d789952159a528c9a5e4eArthur Ishiguro timeout.getMicroseconds(), 70e0653a607542819b492d789952159a528c9a5e4eArthur Ishiguro SmrHelper::smrWaitForServiceCb, this); 71e0653a607542819b492d789952159a528c9a5e4eArthur Ishiguro if (result == SMR_NO_ERR) { 72e0653a607542819b492d789952159a528c9a5e4eArthur Ishiguro LockGuard<Mutex> lock(mMutex); 73e0653a607542819b492d789952159a528c9a5e4eArthur Ishiguro while (mWaiting) { 74e0653a607542819b492d789952159a528c9a5e4eArthur Ishiguro mCond.wait(mMutex); 75e0653a607542819b492d789952159a528c9a5e4eArthur Ishiguro } 76e0653a607542819b492d789952159a528c9a5e4eArthur Ishiguro 77e0653a607542819b492d789952159a528c9a5e4eArthur Ishiguro if (mServiceTimedOut) { 78e0653a607542819b492d789952159a528c9a5e4eArthur Ishiguro LOGE("Wait for SMR service timed out"); 79e0653a607542819b492d789952159a528c9a5e4eArthur Ishiguro result = SMR_TIMEOUT_ERR; 80e0653a607542819b492d789952159a528c9a5e4eArthur Ishiguro mServiceTimedOut = false; 81e0653a607542819b492d789952159a528c9a5e4eArthur Ishiguro } 82e0653a607542819b492d789952159a528c9a5e4eArthur Ishiguro } 83e0653a607542819b492d789952159a528c9a5e4eArthur Ishiguro 84e0653a607542819b492d789952159a528c9a5e4eArthur Ishiguro return result; 85e0653a607542819b492d789952159a528c9a5e4eArthur Ishiguro} 86e0653a607542819b492d789952159a528c9a5e4eArthur Ishiguro 87b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddiebool SmrHelper::sendReqSyncUntyped( 88b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie smr_client_hndl client_handle, unsigned int msg_id, 89b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie void *req_c_struct, unsigned int req_c_struct_len, 90b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie void *resp_c_struct, unsigned int resp_c_struct_len, 91b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie Nanoseconds timeout, smr_err *result) { 92b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie LockGuard<Mutex> lock(mMutex); 93b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie CHRE_ASSERT(!mWaiting); 94b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie bool waitSuccess = true; 95b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie 968d0e0251dc82dec80d458dada7d5345c1967b556Arthur Ishiguro // Force big image since smr_client_send_req is not supported in micro-image 978d0e0251dc82dec80d458dada7d5345c1967b556Arthur Ishiguro slpiForceBigImage(); 988d0e0251dc82dec80d458dada7d5345c1967b556Arthur Ishiguro 99b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie // Note that null txn_handle means we can't abandon the transaction, but it's 100b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie // only supported for QMI (non-SMR) services, and we don't expect that anyway. 101b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie // SMR itself does not support canceling transactions made to SMR services. 102b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie *result = smr_client_send_req( 103b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie client_handle, msg_id, req_c_struct, req_c_struct_len, resp_c_struct, 104b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie resp_c_struct_len, SmrHelper::smrRespCb, this, nullptr /* txn_handle */); 105b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie if (*result != SMR_NO_ERR) { 106b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie LOGE("Failed to send request (msg_id 0x%02x): %d", msg_id, *result); 107b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie } else { 108b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie mWaiting = true; 109b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie mPendingRespBuf = resp_c_struct; 110b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie 111b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie while (mWaiting && waitSuccess) { 112b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie waitSuccess = mCond.wait_for(mMutex, timeout); 113b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie } 114b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie 115b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie if (waitSuccess) { 116b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie *result = mTranspErr; 117b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie } else { 118b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie LOGE("SMR request for msg_id 0x%02x timed out after %" PRIu64 " ms", 119b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie msg_id, Milliseconds(timeout).getMilliseconds()); 120b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie *result = SMR_TIMEOUT_ERR; 121b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie mWaiting = false; 122b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie } 123b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie mPendingRespBuf = nullptr; 124b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie } 125b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie 126b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie return waitSuccess; 127b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie} 128b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie 129b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddievoid SmrHelper::handleResp(smr_client_hndl client_handle, unsigned int msg_id, 130b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie void *resp_c_struct, unsigned int resp_c_struct_len, 131b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie smr_err transp_err) { 132b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie LockGuard<Mutex> lock(mMutex); 133b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie 134b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie if (!mWaiting) { 135b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie LOGE("Got SMR response when none pending!"); 136b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie } else if (mPendingRespBuf != resp_c_struct) { 137b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie LOGE("Got SMR response with unexpected buffer, msg_id 0x%02x: %p vs. %p", 138b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie msg_id, mPendingRespBuf, resp_c_struct); 139b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie } else { 140b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie // SMR will handle copying the response into the buffer passed in to 141b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie // smr_client_send_req(), so we just need to unblock the waiting thread 142b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie mTranspErr = transp_err; 143b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie mWaiting = false; 144b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie mCond.notify_one(); 145b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie } 146b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie} 147b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie 148b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddievoid SmrHelper::smrReleaseCb(void *release_cb_data) { 149b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie SmrHelper *obj = static_cast<SmrHelper *>(release_cb_data); 150b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie LockGuard<Mutex> lock(obj->mMutex); 151b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie obj->mWaiting = false; 152b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie obj->mCond.notify_one(); 153b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie} 154b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie 155b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddievoid SmrHelper::smrRespCb(smr_client_hndl client_handle, unsigned int msg_id, 156b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie void *resp_c_struct, unsigned int resp_c_struct_len, 157b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie void *resp_cb_data, smr_err transp_err) { 158b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie SmrHelper *obj = static_cast<SmrHelper *>(resp_cb_data); 159b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie obj->handleResp(client_handle, msg_id, resp_c_struct, resp_c_struct_len, 160b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie transp_err); 161b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie} 162b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie 163e0653a607542819b492d789952159a528c9a5e4eArthur Ishigurovoid SmrHelper::smrWaitForServiceCb(qmi_idl_service_object_type /* service_obj */, 164e0653a607542819b492d789952159a528c9a5e4eArthur Ishiguro qmi_service_instance /* instance_id */, 165e0653a607542819b492d789952159a528c9a5e4eArthur Ishiguro bool timeout_expired, 166e0653a607542819b492d789952159a528c9a5e4eArthur Ishiguro void *wait_for_service_cb_data) { 167e0653a607542819b492d789952159a528c9a5e4eArthur Ishiguro SmrHelper *obj = static_cast<SmrHelper *>(wait_for_service_cb_data); 168e0653a607542819b492d789952159a528c9a5e4eArthur Ishiguro LockGuard<Mutex> lock(obj->mMutex); 169e0653a607542819b492d789952159a528c9a5e4eArthur Ishiguro obj->mServiceTimedOut = timeout_expired; 170e0653a607542819b492d789952159a528c9a5e4eArthur Ishiguro obj->mWaiting = false; 171e0653a607542819b492d789952159a528c9a5e4eArthur Ishiguro obj->mCond.notify_one(); 172e0653a607542819b492d789952159a528c9a5e4eArthur Ishiguro} 173e0653a607542819b492d789952159a528c9a5e4eArthur Ishiguro 174b9d199936165f42ac7e7eabac1bdb4968d938f4fBrian Duddie} // namespace chre 175