diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c index f6709faa2d77ca7fb3ae2fa9d9656ac9ac48a544..64d5b431aa1d70a5ac95b5e20f7248974dd0ec3b 100644 --- a/drivers/char/diag/diag_masks.c +++ b/drivers/char/diag/diag_masks.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -308,7 +308,12 @@ static void diag_send_msg_mask_update(uint8_t peripheral, int first, int last) if (!mask_info) return; + mutex_lock(&driver->msg_mask_lock); mask = (struct diag_msg_mask_t *)mask_info->ptr; + if (!mask->ptr) { + mutex_unlock(&driver->msg_mask_lock); + return; + } buf = mask_info->update_buf; mutex_lock(&mask_info->lock); switch (mask_info->status) { @@ -381,6 +386,7 @@ proceed: } err: mutex_unlock(&mask_info->lock); + mutex_unlock(&driver->msg_mask_lock); } static void diag_send_time_sync_update(uint8_t peripheral) @@ -493,6 +499,7 @@ static int diag_cmd_get_ssid_range(unsigned char *src_buf, int src_len, if (!diag_apps_responds()) return 0; + mutex_lock(&driver->msg_mask_lock); rsp.cmd_code = DIAG_CMD_MSG_CONFIG; rsp.sub_cmd = DIAG_CMD_OP_GET_SSID_RANGE; rsp.status = MSG_STATUS_SUCCESS; @@ -500,7 +507,6 @@ static int diag_cmd_get_ssid_range(unsigned char *src_buf, int src_len, rsp.count = driver->msg_mask_tbl_count; memcpy(dest_buf, &rsp, sizeof(rsp)); write_len += sizeof(rsp); - mask_ptr = (struct diag_msg_mask_t *)mask_info->ptr; for (i = 0; i < driver->msg_mask_tbl_count; i++, mask_ptr++) { if (write_len + sizeof(ssid_range) > dest_len) { @@ -513,6 +519,7 @@ static int diag_cmd_get_ssid_range(unsigned char *src_buf, int src_len, memcpy(dest_buf + write_len, &ssid_range, sizeof(ssid_range)); write_len += sizeof(ssid_range); } + mutex_unlock(&driver->msg_mask_lock); return write_len; } @@ -538,6 +545,7 @@ static int diag_cmd_get_build_mask(unsigned char *src_buf, int src_len, if (!diag_apps_responds()) return 0; + mutex_lock(&driver->msg_mask_lock); req = (struct diag_build_mask_req_t *)src_buf; rsp.cmd_code = DIAG_CMD_MSG_CONFIG; rsp.sub_cmd = DIAG_CMD_OP_GET_BUILD_MASK; @@ -545,9 +553,8 @@ static int diag_cmd_get_build_mask(unsigned char *src_buf, int src_len, rsp.ssid_last = req->ssid_last; rsp.status = MSG_STATUS_FAIL; rsp.padding = 0; - build_mask = (struct diag_msg_mask_t *)msg_bt_mask.ptr; - for (i = 0; i < driver->msg_mask_tbl_count; i++, build_mask++) { + for (i = 0; i < driver->bt_msg_mask_tbl_count; i++, build_mask++) { if (build_mask->ssid_first != req->ssid_first) continue; num_entries = req->ssid_last - req->ssid_first + 1; @@ -568,6 +575,7 @@ static int diag_cmd_get_build_mask(unsigned char *src_buf, int src_len, } memcpy(dest_buf, &rsp, sizeof(rsp)); write_len += sizeof(rsp); + mutex_unlock(&driver->msg_mask_lock); return write_len; } @@ -596,6 +604,7 @@ static int diag_cmd_get_msg_mask(unsigned char *src_buf, int src_len, if (!diag_apps_responds()) return 0; + mutex_lock(&driver->msg_mask_lock); req = (struct diag_build_mask_req_t *)src_buf; rsp.cmd_code = DIAG_CMD_MSG_CONFIG; rsp.sub_cmd = DIAG_CMD_OP_GET_MSG_MASK; @@ -603,7 +612,6 @@ static int diag_cmd_get_msg_mask(unsigned char *src_buf, int src_len, rsp.ssid_last = req->ssid_last; rsp.status = MSG_STATUS_FAIL; rsp.padding = 0; - mask = (struct diag_msg_mask_t *)mask_info->ptr; for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) { if ((req->ssid_first < mask->ssid_first) || @@ -621,6 +629,7 @@ static int diag_cmd_get_msg_mask(unsigned char *src_buf, int src_len, } memcpy(dest_buf, &rsp, sizeof(rsp)); write_len += sizeof(rsp); + mutex_unlock(&driver->msg_mask_lock); return write_len; } @@ -652,7 +661,7 @@ static int diag_cmd_set_msg_mask(unsigned char *src_buf, int src_len, } req = (struct diag_msg_build_mask_t *)src_buf; - + mutex_lock(&driver->msg_mask_lock); mutex_lock(&mask_info->lock); mask = (struct diag_msg_mask_t *)mask_info->ptr; for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) { @@ -712,6 +721,7 @@ static int diag_cmd_set_msg_mask(unsigned char *src_buf, int src_len, break; } mutex_unlock(&mask_info->lock); + mutex_unlock(&driver->msg_mask_lock); if (diag_check_update(APPS_DATA)) diag_update_userspace_clients(MSG_MASKS_TYPE); @@ -766,6 +776,7 @@ static int diag_cmd_set_all_msg_mask(unsigned char *src_buf, int src_len, req = (struct diag_msg_config_rsp_t *)src_buf; + mutex_lock(&driver->msg_mask_lock); mask = (struct diag_msg_mask_t *)mask_info->ptr; mutex_lock(&mask_info->lock); mask_info->status = (req->rt_mask) ? DIAG_CTRL_MASK_ALL_ENABLED : @@ -777,6 +788,7 @@ static int diag_cmd_set_all_msg_mask(unsigned char *src_buf, int src_len, mutex_unlock(&mask->lock); } mutex_unlock(&mask_info->lock); + mutex_unlock(&driver->msg_mask_lock); if (diag_check_update(APPS_DATA)) diag_update_userspace_clients(MSG_MASKS_TYPE); @@ -1280,6 +1292,7 @@ static int diag_create_msg_mask_table(void) struct diag_msg_mask_t *mask = (struct diag_msg_mask_t *)msg_mask.ptr; struct diag_ssid_range_t range; + mutex_lock(&driver->msg_mask_lock); mutex_lock(&msg_mask.lock); driver->msg_mask_tbl_count = MSG_MASK_TBL_CNT; for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) { @@ -1290,6 +1303,8 @@ static int diag_create_msg_mask_table(void) break; } mutex_unlock(&msg_mask.lock); + mutex_unlock(&driver->msg_mask_lock); + return err; } @@ -1302,9 +1317,11 @@ static int diag_create_build_time_mask(void) struct diag_msg_mask_t *build_mask = NULL; struct diag_ssid_range_t range; + mutex_lock(&driver->msg_mask_lock); mutex_lock(&msg_bt_mask.lock); + driver->bt_msg_mask_tbl_count = MSG_MASK_TBL_CNT; build_mask = (struct diag_msg_mask_t *)msg_bt_mask.ptr; - for (i = 0; i < driver->msg_mask_tbl_count; i++, build_mask++) { + for (i = 0; i < driver->bt_msg_mask_tbl_count; i++, build_mask++) { range.ssid_first = msg_mask_tbl[i].ssid_first; range.ssid_last = msg_mask_tbl[i].ssid_last; err = diag_create_msg_mask_table_entry(build_mask, &range); @@ -1415,6 +1432,7 @@ static int diag_create_build_time_mask(void) memcpy(build_mask->ptr, tbl, tbl_size); } mutex_unlock(&msg_bt_mask.lock); + mutex_unlock(&driver->msg_mask_lock); return err; } @@ -1562,10 +1580,11 @@ static int diag_msg_mask_init(void) pr_err("diag: Unable to create msg masks, err: %d\n", err); return err; } + mutex_lock(&driver->msg_mask_lock); driver->msg_mask = &msg_mask; - for (i = 0; i < NUM_PERIPHERALS; i++) driver->max_ssid_count[i] = 0; + mutex_unlock(&driver->msg_mask_lock); return 0; } @@ -1584,7 +1603,7 @@ int diag_msg_mask_copy(struct diag_mask_info *dest, struct diag_mask_info *src) err = __diag_mask_init(dest, MSG_MASK_SIZE, APPS_BUF_SIZE); if (err) return err; - + mutex_lock(&driver->msg_mask_lock); mutex_lock(&dest->lock); src_mask = (struct diag_msg_mask_t *)src->ptr; dest_mask = (struct diag_msg_mask_t *)dest->ptr; @@ -1603,6 +1622,7 @@ int diag_msg_mask_copy(struct diag_mask_info *dest, struct diag_mask_info *src) dest_mask++; } mutex_unlock(&dest->lock); + mutex_unlock(&driver->msg_mask_lock); return err; } @@ -1614,7 +1634,7 @@ void diag_msg_mask_free(struct diag_mask_info *mask_info) if (!mask_info) return; - + mutex_lock(&driver->msg_mask_lock); mutex_lock(&mask_info->lock); mask = (struct diag_msg_mask_t *)mask_info->ptr; for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) { @@ -1622,7 +1642,7 @@ void diag_msg_mask_free(struct diag_mask_info *mask_info) mask->ptr = NULL; } mutex_unlock(&mask_info->lock); - + mutex_unlock(&driver->msg_mask_lock); __diag_mask_exit(mask_info); } @@ -1630,15 +1650,17 @@ static void diag_msg_mask_exit(void) { int i; struct diag_msg_mask_t *mask = NULL; - + mutex_lock(&driver->msg_mask_lock); mask = (struct diag_msg_mask_t *)(msg_mask.ptr); if (mask) { for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) kfree(mask->ptr); kfree(msg_mask.ptr); + msg_mask.ptr = NULL; } - kfree(msg_mask.update_buf); + msg_mask.update_buf = NULL; + mutex_unlock(&driver->msg_mask_lock); } static int diag_build_time_mask_init(void) @@ -1663,13 +1685,15 @@ static void diag_build_time_mask_exit(void) { int i; struct diag_msg_mask_t *mask = NULL; - + mutex_lock(&driver->msg_mask_lock); mask = (struct diag_msg_mask_t *)(msg_bt_mask.ptr); if (mask) { - for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) + for (i = 0; i < driver->bt_msg_mask_tbl_count; i++, mask++) kfree(mask->ptr); - kfree(msg_mask.ptr); + kfree(msg_bt_mask.ptr); + msg_bt_mask.ptr = NULL; } + mutex_unlock(&driver->msg_mask_lock); } static int diag_log_mask_init(void) @@ -1787,7 +1811,7 @@ int diag_copy_to_user_msg_mask(char __user *buf, size_t count, return -EIO; } mutex_unlock(&driver->diag_maskclear_mutex); - + mutex_lock(&driver->msg_mask_lock); mutex_lock(&mask_info->lock); mask = (struct diag_msg_mask_t *)(mask_info->ptr); for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) { @@ -1826,6 +1850,7 @@ int diag_copy_to_user_msg_mask(char __user *buf, size_t count, total_len += len; } mutex_unlock(&mask_info->lock); + mutex_unlock(&driver->msg_mask_lock); return err ? err : total_len; } diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h index 43331190c5823278fa0e1894ec3364ca6681de83..c1749d3435732a26dfc65623c88c0b262289e32b 100644 --- a/drivers/char/diag/diagchar.h +++ b/drivers/char/diag/diagchar.h @@ -537,6 +537,7 @@ struct diagchar_dev { unsigned char *buf_feature_mask_update; uint8_t hdlc_disabled; struct mutex hdlc_disable_mutex; + struct mutex hdlc_recovery_mutex; struct timer_list hdlc_reset_timer; struct mutex diag_hdlc_mutex; unsigned char *hdlc_buf; @@ -582,8 +583,10 @@ struct diagchar_dev { struct diag_mask_info *event_mask; struct diag_mask_info *build_time_mask; uint8_t msg_mask_tbl_count; + uint8_t bt_msg_mask_tbl_count; uint16_t event_mask_size; uint16_t last_event_id; + struct mutex msg_mask_lock; /* Variables for Mask Centralization */ uint16_t num_event_id[NUM_PERIPHERALS]; uint32_t num_equip_id[NUM_PERIPHERALS]; diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c index 10a38dcd812b77a81640f81df5aa42af05744836..048e1fd60b8057a4151011bd02b1e058edb8e896 100644 --- a/drivers/char/diag/diagchar_core.c +++ b/drivers/char/diag/diagchar_core.c @@ -3390,7 +3390,9 @@ static int __init diagchar_init(void) mutex_init(&driver->diag_file_mutex); mutex_init(&driver->delayed_rsp_mutex); mutex_init(&apps_data_mutex); + mutex_init(&driver->msg_mask_lock); mutex_init(&driver->diagfwd_channel_mutex); + mutex_init(&driver->hdlc_recovery_mutex); init_waitqueue_head(&driver->wait_q); INIT_WORK(&(driver->diag_drain_work), diag_drain_work_fn); INIT_WORK(&(driver->update_user_clients), diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c index 65bbe7cdd83475e9867e531b678b7293c06e4ee1..60d126acae99ab4e13e569926b39f86f8915c40f 100644 --- a/drivers/char/diag/diagfwd.c +++ b/drivers/char/diag/diagfwd.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1348,7 +1348,9 @@ static void diag_hdlc_start_recovery(unsigned char *buf, int len, if (start_ptr) { /* Discard any partial packet reads */ + mutex_lock(&driver->hdlc_recovery_mutex); driver->incoming_pkt.processing = 0; + mutex_unlock(&driver->hdlc_recovery_mutex); diag_process_non_hdlc_pkt(start_ptr, len - i, info); } } @@ -1362,18 +1364,24 @@ void diag_process_non_hdlc_pkt(unsigned char *buf, int len, const uint32_t header_len = sizeof(struct diag_pkt_frame_t); struct diag_pkt_frame_t *actual_pkt = NULL; unsigned char *data_ptr = NULL; - struct diag_partial_pkt_t *partial_pkt = &driver->incoming_pkt; + struct diag_partial_pkt_t *partial_pkt = NULL; - if (!buf || len <= 0) + mutex_lock(&driver->hdlc_recovery_mutex); + if (!buf || len <= 0) { + mutex_unlock(&driver->hdlc_recovery_mutex); return; - - if (!partial_pkt->processing) + } + partial_pkt = &driver->incoming_pkt; + if (!partial_pkt->processing) { + mutex_unlock(&driver->hdlc_recovery_mutex); goto start; + } if (partial_pkt->remaining > len) { if ((partial_pkt->read_len + len) > partial_pkt->capacity) { pr_err("diag: Invalid length %d, %d received in %s\n", partial_pkt->read_len, len, __func__); + mutex_unlock(&driver->hdlc_recovery_mutex); goto end; } memcpy(partial_pkt->data + partial_pkt->read_len, buf, len); @@ -1387,6 +1395,7 @@ void diag_process_non_hdlc_pkt(unsigned char *buf, int len, pr_err("diag: Invalid length during partial read %d, %d received in %s\n", partial_pkt->read_len, partial_pkt->remaining, __func__); + mutex_unlock(&driver->hdlc_recovery_mutex); goto end; } memcpy(partial_pkt->data + partial_pkt->read_len, buf, @@ -1400,20 +1409,27 @@ void diag_process_non_hdlc_pkt(unsigned char *buf, int len, if (partial_pkt->remaining == 0) { actual_pkt = (struct diag_pkt_frame_t *)(partial_pkt->data); data_ptr = partial_pkt->data + header_len; - if (*(uint8_t *)(data_ptr + actual_pkt->length) != CONTROL_CHAR) + if (*(uint8_t *)(data_ptr + actual_pkt->length) != + CONTROL_CHAR) { + mutex_unlock(&driver->hdlc_recovery_mutex); diag_hdlc_start_recovery(buf, len, info); + mutex_lock(&driver->hdlc_recovery_mutex); + } err = diag_process_apps_pkt(data_ptr, actual_pkt->length, info); if (err) { pr_err("diag: In %s, unable to process incoming data packet, err: %d\n", __func__, err); + mutex_unlock(&driver->hdlc_recovery_mutex); goto end; } partial_pkt->read_len = 0; partial_pkt->total_len = 0; partial_pkt->processing = 0; + mutex_unlock(&driver->hdlc_recovery_mutex); goto start; } + mutex_unlock(&driver->hdlc_recovery_mutex); goto end; start: @@ -1426,14 +1442,14 @@ start: diag_send_error_rsp(buf, len); goto end; } - + mutex_lock(&driver->hdlc_recovery_mutex); if (pkt_len + header_len > partial_pkt->capacity) { pr_err("diag: In %s, incoming data is too large for the request buffer %d\n", __func__, pkt_len); + mutex_unlock(&driver->hdlc_recovery_mutex); diag_hdlc_start_recovery(buf, len, info); break; } - if ((pkt_len + header_len) > (len - read_bytes)) { partial_pkt->read_len = len - read_bytes; partial_pkt->total_len = pkt_len + header_len; @@ -1441,19 +1457,27 @@ start: partial_pkt->read_len; partial_pkt->processing = 1; memcpy(partial_pkt->data, buf, partial_pkt->read_len); + mutex_unlock(&driver->hdlc_recovery_mutex); break; } data_ptr = buf + header_len; - if (*(uint8_t *)(data_ptr + actual_pkt->length) != CONTROL_CHAR) + if (*(uint8_t *)(data_ptr + actual_pkt->length) != + CONTROL_CHAR) { + mutex_unlock(&driver->hdlc_recovery_mutex); diag_hdlc_start_recovery(buf, len, info); + mutex_lock(&driver->hdlc_recovery_mutex); + } else hdlc_reset = 0; err = diag_process_apps_pkt(data_ptr, actual_pkt->length, info); - if (err) + if (err) { + mutex_unlock(&driver->hdlc_recovery_mutex); break; + } read_bytes += header_len + pkt_len + 1; buf += header_len + pkt_len + 1; /* advance to next pkt */ + mutex_unlock(&driver->hdlc_recovery_mutex); } end: return; diff --git a/drivers/char/diag/diagfwd_cntl.c b/drivers/char/diag/diagfwd_cntl.c index 594d3b1bf3b5815dc599e1d72b26f84b62e3d704..410790e1169157772753a4dead1428f48d4199ef 100644 --- a/drivers/char/diag/diagfwd_cntl.c +++ b/drivers/char/diag/diagfwd_cntl.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -508,6 +508,7 @@ static void process_ssid_range_report(uint8_t *buf, uint32_t len, /* Don't account for pkt_id and length */ read_len += header_len - (2 * sizeof(uint32_t)); + mutex_lock(&driver->msg_mask_lock); driver->max_ssid_count[peripheral] = header->count; for (i = 0; i < header->count && read_len < len; i++) { ssid_range = (struct diag_ssid_range_t *)ptr; @@ -551,6 +552,7 @@ static void process_ssid_range_report(uint8_t *buf, uint32_t len, } driver->msg_mask_tbl_count += 1; } + mutex_unlock(&driver->msg_mask_lock); } static void diag_build_time_mask_update(uint8_t *buf, @@ -575,11 +577,11 @@ static void diag_build_time_mask_update(uint8_t *buf, __func__, range->ssid_first, range->ssid_last); return; } - + mutex_lock(&driver->msg_mask_lock); build_mask = (struct diag_msg_mask_t *)(driver->build_time_mask->ptr); num_items = range->ssid_last - range->ssid_first + 1; - for (i = 0; i < driver->msg_mask_tbl_count; i++, build_mask++) { + for (i = 0; i < driver->bt_msg_mask_tbl_count; i++, build_mask++) { if (build_mask->ssid_first != range->ssid_first) continue; found = 1; @@ -598,7 +600,7 @@ static void diag_build_time_mask_update(uint8_t *buf, if (found) goto end; - new_size = (driver->msg_mask_tbl_count + 1) * + new_size = (driver->bt_msg_mask_tbl_count + 1) * sizeof(struct diag_msg_mask_t); temp = krealloc(driver->build_time_mask->ptr, new_size, GFP_KERNEL); if (!temp) { @@ -613,8 +615,10 @@ static void diag_build_time_mask_update(uint8_t *buf, __func__, err); goto end; } - driver->msg_mask_tbl_count += 1; + driver->bt_msg_mask_tbl_count += 1; end: + mutex_unlock(&driver->msg_mask_lock); + return; } diff --git a/drivers/gpu/msm/adreno_debugfs.c b/drivers/gpu/msm/adreno_debugfs.c index 680827e5b848c73e0315eae9f46cb34f609cb513..28e8e8f5497a91499ddfc35c00bec2079f2bff54 100644 --- a/drivers/gpu/msm/adreno_debugfs.c +++ b/drivers/gpu/msm/adreno_debugfs.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2002,2008-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2002,2008-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -131,6 +131,8 @@ typedef void (*reg_read_fill_t)(struct kgsl_device *device, int i, static void sync_event_print(struct seq_file *s, struct kgsl_cmdbatch_sync_event *sync_event) { + unsigned long flags; + switch (sync_event->type) { case KGSL_CMD_SYNCPOINT_TYPE_TIMESTAMP: { seq_printf(s, "sync: ctx: %d ts: %d", @@ -138,9 +140,13 @@ static void sync_event_print(struct seq_file *s, break; } case KGSL_CMD_SYNCPOINT_TYPE_FENCE: + spin_lock_irqsave(&sync_event->handle_lock, flags); + seq_printf(s, "sync: [%pK] %s", sync_event->handle, (sync_event->handle && sync_event->handle->fence) ? sync_event->handle->fence->name : "NULL"); + + spin_unlock_irqrestore(&sync_event->handle_lock, flags); break; default: seq_printf(s, "sync: type: %d", sync_event->type); diff --git a/drivers/gpu/msm/kgsl_cmdbatch.c b/drivers/gpu/msm/kgsl_cmdbatch.c index 6272410ce544b56a5c5aa0e559e2020315e6aa0b..c2683d0712f9518bd2e801e29942c57664cc2e4d 100644 --- a/drivers/gpu/msm/kgsl_cmdbatch.c +++ b/drivers/gpu/msm/kgsl_cmdbatch.c @@ -57,6 +57,7 @@ void kgsl_dump_syncpoints(struct kgsl_device *device, { struct kgsl_cmdbatch_sync_event *event; unsigned int i; + unsigned long flags; for (i = 0; i < cmdbatch->numsyncs; i++) { event = &cmdbatch->synclist[i]; @@ -79,12 +80,16 @@ void kgsl_dump_syncpoints(struct kgsl_device *device, break; } case KGSL_CMD_SYNCPOINT_TYPE_FENCE: + spin_lock_irqsave(&event->handle_lock, flags); + if (event->handle) dev_err(device->dev, " fence: [%pK] %s\n", event->handle->fence, event->handle->name); else dev_err(device->dev, " fence: invalid\n"); + + spin_unlock_irqrestore(&event->handle_lock, flags); break; } } @@ -96,6 +101,7 @@ static void _kgsl_cmdbatch_timer(unsigned long data) struct kgsl_cmdbatch *cmdbatch = (struct kgsl_cmdbatch *) data; struct kgsl_cmdbatch_sync_event *event; unsigned int i; + unsigned long flags; if (cmdbatch == NULL || cmdbatch->context == NULL) return; @@ -124,12 +130,16 @@ static void _kgsl_cmdbatch_timer(unsigned long data) i, event->context->id, event->timestamp); break; case KGSL_CMD_SYNCPOINT_TYPE_FENCE: + spin_lock_irqsave(&event->handle_lock, flags); + if (event->handle != NULL) { dev_err(device->dev, " [%d] FENCE %s\n", i, event->handle->fence ? event->handle->fence->name : "NULL"); kgsl_sync_fence_log(event->handle->fence); } + + spin_unlock_irqrestore(&event->handle_lock, flags); break; } } @@ -221,7 +231,7 @@ static inline void _free_memobj_list(struct list_head *list) void kgsl_cmdbatch_destroy(struct kgsl_cmdbatch *cmdbatch) { unsigned int i; - unsigned long pending; + unsigned long pending, flags; if (IS_ERR_OR_NULL(cmdbatch)) return; @@ -255,8 +265,17 @@ void kgsl_cmdbatch_destroy(struct kgsl_cmdbatch *cmdbatch) kgsl_cmdbatch_sync_func, event); break; case KGSL_CMD_SYNCPOINT_TYPE_FENCE: - if (kgsl_sync_fence_async_cancel(event->handle)) + spin_lock_irqsave(&event->handle_lock, flags); + + if (kgsl_sync_fence_async_cancel(event->handle)) { + event->handle = NULL; + spin_unlock_irqrestore( + &event->handle_lock, flags); kgsl_cmdbatch_put(cmdbatch); + } else { + spin_unlock_irqrestore( + &event->handle_lock, flags); + } break; } } @@ -293,12 +312,23 @@ EXPORT_SYMBOL(kgsl_cmdbatch_destroy); */ static void kgsl_cmdbatch_sync_fence_func(void *priv) { + unsigned long flags; struct kgsl_cmdbatch_sync_event *event = priv; + kgsl_cmdbatch_sync_expire(event->device, event); + trace_syncpoint_fence_expire(event->cmdbatch, event->handle ? event->handle->name : "unknown"); - kgsl_cmdbatch_sync_expire(event->device, event); + spin_lock_irqsave(&event->handle_lock, flags); + + /* + * Setting the event->handle to NULL here make sure that + * other function does not dereference a invalid pointer. + */ + event->handle = NULL; + + spin_unlock_irqrestore(&event->handle_lock, flags); kgsl_cmdbatch_put(event->cmdbatch); } @@ -316,6 +346,7 @@ static int kgsl_cmdbatch_add_sync_fence(struct kgsl_device *device, struct kgsl_cmd_syncpoint_fence *sync = priv; struct kgsl_cmdbatch_sync_event *event; unsigned int id; + unsigned long flags; kref_get(&cmdbatch->refcount); @@ -329,7 +360,9 @@ static int kgsl_cmdbatch_add_sync_fence(struct kgsl_device *device, event->device = device; event->context = NULL; + spin_lock_init(&event->handle_lock); set_bit(event->id, &cmdbatch->pending); + spin_lock_irqsave(&event->handle_lock, flags); event->handle = kgsl_sync_fence_async_wait(sync->fd, kgsl_cmdbatch_sync_fence_func, event); @@ -337,9 +370,10 @@ static int kgsl_cmdbatch_add_sync_fence(struct kgsl_device *device, if (IS_ERR_OR_NULL(event->handle)) { int ret = PTR_ERR(event->handle); - clear_bit(event->id, &cmdbatch->pending); event->handle = NULL; + spin_unlock_irqrestore(&event->handle_lock, flags); + clear_bit(event->id, &cmdbatch->pending); kgsl_cmdbatch_put(cmdbatch); /* @@ -350,6 +384,8 @@ static int kgsl_cmdbatch_add_sync_fence(struct kgsl_device *device, trace_syncpoint_fence_expire(cmdbatch, "signaled"); return ret; + } else { + spin_unlock_irqrestore(&event->handle_lock, flags); } trace_syncpoint_fence(cmdbatch, event->handle->name); diff --git a/drivers/gpu/msm/kgsl_cmdbatch.h b/drivers/gpu/msm/kgsl_cmdbatch.h index d5cbf375b5d35098d579ed0dbe625a2f6cfa47fd..b37f432f3e7d10b0f92ec0528beb768a2c917a5b 100644 --- a/drivers/gpu/msm/kgsl_cmdbatch.h +++ b/drivers/gpu/msm/kgsl_cmdbatch.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -84,6 +84,7 @@ struct kgsl_cmdbatch { * @context: Pointer to the KGSL context that owns the cmdbatch * @timestamp: Pending timestamp for the event * @handle: Pointer to a sync fence handle + * @handle_lock: Spin lock to protect handle * @device: Pointer to the KGSL device */ struct kgsl_cmdbatch_sync_event { @@ -93,6 +94,7 @@ struct kgsl_cmdbatch_sync_event { struct kgsl_context *context; unsigned int timestamp; struct kgsl_sync_fence_waiter *handle; + spinlock_t handle_lock; struct kgsl_device *device; }; diff --git a/drivers/input/misc/keychord.c b/drivers/input/misc/keychord.c index a5ea27ad0e16c658d7ac2e3629e647c1b9f9cff2..f580edf1c87ce45f5c072fd489b464dd0fbbe69c 100644 --- a/drivers/input/misc/keychord.c +++ b/drivers/input/misc/keychord.c @@ -300,8 +300,10 @@ static ssize_t keychord_write(struct file *file, const char __user *buffer, ret = input_register_handler(&kdev->input_handler); if (ret) { - kfree(keychords); + spin_lock_irqsave(&kdev->lock, flags); + kfree(kdev->keychords); kdev->keychords = 0; + spin_unlock_irqrestore(&kdev->lock, flags); return ret; } kdev->registered = 1; diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c index 739bcbc91ec61b6f2f3d7c3e7dd26cd7f5140579..d01e8299187d62e7420add446992251786df1b2c 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -3488,6 +3488,14 @@ int msm_isp_update_axi_stream(struct vfe_device *vfe_dev, void *arg) case UPDATE_STREAM_REQUEST_FRAMES_VER2: { struct msm_vfe_axi_stream_cfg_update_info_req_frm *req_frm = &update_cmd->req_frm_ver2; + if (HANDLE_TO_IDX(req_frm->stream_handle) >= VFE_AXI_SRC_MAX) { + pr_err("%s: Invalid stream handle \n", __func__); + rc = -EINVAL; + break; + } + stream_info = &axi_data->stream_info[HANDLE_TO_IDX( + req_frm->stream_handle)]; + rc = msm_isp_request_frame(vfe_dev, stream_info, req_frm->user_stream_id, req_frm->frame_id, diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c index 697b3f7f5b4ed579300c4851349890fbd36e4ebb..ca37cc8cc3581ce1251f1319c08a9a63c70f65a9 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c @@ -886,6 +886,12 @@ int msm_isp_update_stats_stream(struct vfe_device *vfe_dev, void *arg) struct msm_vfe_axi_stream_cfg_update_info *update_info = NULL; struct msm_isp_sw_framskip *sw_skip_info = NULL; + if (update_cmd->num_streams > MSM_ISP_STATS_MAX) { + pr_err("%s: Invalid num_streams %d\n", + __func__, update_cmd->num_streams); + return -EINVAL; + } + /*validate request*/ for (i = 0; i < update_cmd->num_streams; i++) { update_info = (struct msm_vfe_axi_stream_cfg_update_info *) diff --git a/drivers/media/platform/msm/camera_v2/msm.c b/drivers/media/platform/msm/camera_v2/msm.c index 6747cecfa89286e1f4e970e05272e9b1d4fd1535..715898ce7ecbc3807e1619b35c374b51bbe60238 100644 --- a/drivers/media/platform/msm/camera_v2/msm.c +++ b/drivers/media/platform/msm/camera_v2/msm.c @@ -383,6 +383,11 @@ static void msm_add_sd_in_position(struct msm_sd_subdev *msm_subdev, struct msm_sd_subdev *temp_sd; list_for_each_entry(temp_sd, sd_list, list) { + if (temp_sd == msm_subdev) { + pr_err("%s :Fail to add the same sd %d\n", + __func__, __LINE__); + return; + } if (msm_subdev->close_seq < temp_sd->close_seq) { list_add_tail(&msm_subdev->list, &temp_sd->list); return; diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c index 4bf05de443e081711280e495be5aa074bb3798bc..7f7a5ce3e85cac0b92fd2f56e5d692f70ef17120 100644 --- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c +++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c @@ -2696,13 +2696,15 @@ end: return rc; } -static int msm_cpp_validate_input(unsigned int cmd, void *arg, +static int msm_cpp_validate_ioctl_input(unsigned int cmd, void *arg, struct msm_camera_v4l2_ioctl_t **ioctl_ptr) { switch (cmd) { case MSM_SD_SHUTDOWN: case MSM_SD_NOTIFY_FREEZE: case MSM_SD_UNNOTIFY_FREEZE: + case VIDIOC_MSM_CPP_IOMMU_ATTACH: + case VIDIOC_MSM_CPP_IOMMU_DETACH: break; default: { if (ioctl_ptr == NULL) { @@ -2711,8 +2713,9 @@ static int msm_cpp_validate_input(unsigned int cmd, void *arg, } *ioctl_ptr = arg; - if ((*ioctl_ptr == NULL) || - (*ioctl_ptr)->ioctl_ptr == NULL) { + if (((*ioctl_ptr) == NULL) || + ((*ioctl_ptr)->ioctl_ptr == NULL) || + ((*ioctl_ptr)->len == 0)) { pr_err("Error invalid ioctl argument cmd %u", cmd); return -EINVAL; } @@ -2744,7 +2747,7 @@ long msm_cpp_subdev_ioctl(struct v4l2_subdev *sd, return -EINVAL; } - rc = msm_cpp_validate_input(cmd, arg, &ioctl_ptr); + rc = msm_cpp_validate_ioctl_input(cmd, arg, &ioctl_ptr); if (rc != 0) { pr_err("input validation failed\n"); return rc; @@ -3234,7 +3237,7 @@ STREAM_BUFF_END: (cpp_dev->stream_cnt == 0)) { rc = cam_smmu_ops(cpp_dev->iommu_hdl, CAM_SMMU_DETACH); if (rc < 0) { - pr_err("%s:%dError iommu atach failed\n", + pr_err("%s:%dError iommu detach failed\n", __func__, __LINE__); rc = -EINVAL; break; @@ -3243,6 +3246,7 @@ STREAM_BUFF_END: } else { pr_err("%s:%d IOMMMU attach triggered in invalid state\n", __func__, __LINE__); + rc = -EINVAL; } break; } @@ -3869,7 +3873,8 @@ static long msm_cpp_subdev_fops_compat_ioctl(struct file *file, default: pr_err_ratelimited("%s: unsupported compat type :%x LOAD %lu\n", __func__, cmd, VIDIOC_MSM_CPP_LOAD_FIRMWARE); - break; + mutex_unlock(&cpp_dev->mutex); + return -EINVAL; } mutex_unlock(&cpp_dev->mutex); @@ -3900,7 +3905,7 @@ static long msm_cpp_subdev_fops_compat_ioctl(struct file *file, default: pr_err_ratelimited("%s: unsupported compat type :%d\n", __func__, cmd); - break; + return -EINVAL; } up32_ioctl.id = kp_ioctl.id; diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c index be7954c3d2c969de3d5a9d060efc1cb6e5c8feaa..260c8a3de8f5a3b992dfd22dc2c24de5a0d58f63 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c +++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -17,13 +17,15 @@ #undef CDBG #define CDBG(fmt, args...) pr_debug(fmt, ##args) #define S_I2C_DBG(fmt, args...) pr_debug(fmt, ##args) +#define MAX_I2C_ADDR_TYPE_SIZE (MSM_CAMERA_I2C_3B_ADDR + 1) +#define MAX_I2C_DATA_TYPE_SIZE (MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA + 1) int32_t msm_camera_cci_i2c_read(struct msm_camera_i2c_client *client, uint32_t addr, uint16_t *data, enum msm_camera_i2c_data_type data_type) { int32_t rc = -EFAULT; - unsigned char buf[client->addr_type+data_type]; + unsigned char buf[MAX_I2C_ADDR_TYPE_SIZE + MAX_I2C_DATA_TYPE_SIZE]; struct msm_camera_cci_ctrl cci_ctrl; if ((client->addr_type != MSM_CAMERA_I2C_BYTE_ADDR diff --git a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c index a9a8682d298b66ed9f5afd38667c30e6eb19b661..da8cd4f9cae1547bb83d24665a5ce51503ac13a0 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c +++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c @@ -105,7 +105,11 @@ static int32_t msm_sensor_driver_create_i2c_v4l_subdev s_ctrl->msm_sd.sd.entity.name = s_ctrl->msm_sd.sd.name; s_ctrl->sensordata->sensor_info->session_id = session_id; s_ctrl->msm_sd.close_seq = MSM_SD_CLOSE_2ND_CATEGORY | 0x3; - msm_sd_register(&s_ctrl->msm_sd); + rc = msm_sd_register(&s_ctrl->msm_sd); + if (rc < 0) { + pr_err("failed: msm_sd_register rc %d", rc); + return rc; + } msm_sensor_v4l2_subdev_fops = v4l2_subdev_fops; #ifdef CONFIG_COMPAT msm_sensor_v4l2_subdev_fops.compat_ioctl32 = @@ -142,7 +146,11 @@ static int32_t msm_sensor_driver_create_v4l_subdev s_ctrl->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_SENSOR; s_ctrl->msm_sd.sd.entity.name = s_ctrl->msm_sd.sd.name; s_ctrl->msm_sd.close_seq = MSM_SD_CLOSE_2ND_CATEGORY | 0x3; - msm_sd_register(&s_ctrl->msm_sd); + rc = msm_sd_register(&s_ctrl->msm_sd); + if (rc < 0) { + pr_err("failed: msm_sd_register rc %d", rc); + return rc; + } msm_cam_copy_v4l2_subdev_fops(&msm_sensor_v4l2_subdev_fops); #ifdef CONFIG_COMPAT msm_sensor_v4l2_subdev_fops.compat_ioctl32 = @@ -890,12 +898,6 @@ CSID_TG: pr_err("%s probe succeeded", slave_info->sensor_name); - /* - Set probe succeeded flag to 1 so that no other camera shall - * probed on this slot - */ - s_ctrl->is_probe_succeed = 1; - /* * Update the subdevice id of flash-src based on availability in kernel. */ @@ -948,6 +950,11 @@ CSID_TG: msm_sensor_fill_sensor_info(s_ctrl, probed_info, entity_name); + /* + * Set probe succeeded flag to 1 so that no other camera shall + * probed on this slot + */ + s_ctrl->is_probe_succeed = 1; return rc; camera_power_down: diff --git a/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c b/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c index bb4d710ea3cbe88eda3340b9d28b15d2db839b5d..6e8e00e26a95ccf61df57b150c87c2a5db8d1abe 100644 --- a/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c +++ b/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c @@ -148,6 +148,8 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, case AUDIO_START: { pr_debug("%s: AUDIO_START\n", __func__); + mutex_lock(&effects->lock); + rc = q6asm_open_read_write_v2(effects->ac, FORMAT_LINEAR_PCM, FORMAT_MULTI_CHANNEL_LINEAR_PCM, @@ -159,6 +161,7 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, pr_err("%s: Open failed for hw accelerated effects:rc=%d\n", __func__, rc); rc = -EINVAL; + mutex_unlock(&effects->lock); goto ioctl_fail; } effects->opened = 1; @@ -175,6 +178,7 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, pr_err("%s: Write buffer Allocation failed rc = %d\n", __func__, rc); rc = -ENOMEM; + mutex_unlock(&effects->lock); goto ioctl_fail; } atomic_set(&effects->in_count, effects->config.input.num_buf); @@ -185,6 +189,7 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, pr_err("%s: Read buffer Allocation failed rc = %d\n", __func__, rc); rc = -ENOMEM; + mutex_unlock(&effects->lock); goto readbuf_fail; } atomic_set(&effects->out_count, effects->config.output.num_buf); @@ -199,6 +204,7 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, if (rc < 0) { pr_err("%s: pcm read block config failed\n", __func__); rc = -EINVAL; + mutex_unlock(&effects->lock); goto cfg_fail; } pr_debug("%s: dec: sample_rate: %d, num_channels: %d, bit_width: %d\n", @@ -213,6 +219,7 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, pr_err("%s: pcm write format block config failed\n", __func__); rc = -EINVAL; + mutex_unlock(&effects->lock); goto cfg_fail; } @@ -225,6 +232,7 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, effects->started = 0; pr_err("%s: ASM run state failed\n", __func__); } + mutex_unlock(&effects->lock); break; } case AUDIO_EFFECTS_WRITE: { @@ -286,8 +294,11 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, uint32_t idx = 0; uint32_t size = 0; + mutex_lock(&effects->lock); + if (!effects->started) { rc = -EFAULT; + mutex_unlock(&effects->lock); goto ioctl_fail; } @@ -304,11 +315,13 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, if (!rc) { pr_err("%s: read wait_event_timeout\n", __func__); rc = -EFAULT; + mutex_unlock(&effects->lock); goto ioctl_fail; } if (!atomic_read(&effects->in_count)) { pr_err("%s: pcm stopped in_count 0\n", __func__); rc = -EFAULT; + mutex_unlock(&effects->lock); goto ioctl_fail; } @@ -316,15 +329,18 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, if (bufptr) { if (!((void *)arg)) { rc = -EFAULT; + mutex_unlock(&effects->lock); goto ioctl_fail; } if ((effects->config.buf_cfg.input_len > size) || copy_to_user((void *)arg, bufptr, effects->config.buf_cfg.input_len)) { rc = -EFAULT; + mutex_unlock(&effects->lock); goto ioctl_fail; } } + mutex_unlock(&effects->lock); break; } default: @@ -456,6 +472,7 @@ static long audio_effects_ioctl(struct file *file, unsigned int cmd, switch (cmd) { case AUDIO_SET_EFFECTS_CONFIG: { pr_debug("%s: AUDIO_SET_EFFECTS_CONFIG\n", __func__); + mutex_lock(&effects->lock); memset(&effects->config, 0, sizeof(effects->config)); if (copy_from_user(&effects->config, (void *)arg, sizeof(effects->config))) { @@ -473,6 +490,7 @@ static long audio_effects_ioctl(struct file *file, unsigned int cmd, effects->config.input.num_buf, effects->config.input.sample_rate, effects->config.input.num_channels); + mutex_unlock(&effects->lock); break; } case AUDIO_EFFECTS_SET_BUF_LEN: { @@ -494,6 +512,7 @@ static long audio_effects_ioctl(struct file *file, unsigned int cmd, buf_avail.input_num_avail = atomic_read(&effects->in_count); buf_avail.output_num_avail = atomic_read(&effects->out_count); + mutex_lock(&effects->lock); pr_debug("%s: write buf avail: %d, read buf avail: %d\n", __func__, buf_avail.output_num_avail, buf_avail.input_num_avail); @@ -503,16 +522,20 @@ static long audio_effects_ioctl(struct file *file, unsigned int cmd, __func__); rc = -EFAULT; } + mutex_unlock(&effects->lock); break; } case AUDIO_EFFECTS_SET_PP_PARAMS: { + mutex_lock(&effects->lock); if (copy_from_user(argvalues, (void *)arg, MAX_PP_PARAMS_SZ*sizeof(long))) { pr_err("%s: copy from user for pp params failed\n", __func__); + mutex_unlock(&effects->lock); return -EFAULT; } rc = audio_effects_set_pp_param(effects, argvalues); + mutex_unlock(&effects->lock); break; } default: @@ -578,12 +601,14 @@ static long audio_effects_compat_ioctl(struct file *file, unsigned int cmd, case AUDIO_SET_EFFECTS_CONFIG32: { struct msm_hwacc_effects_config32 config32; struct msm_hwacc_effects_config *config = &effects->config; + mutex_lock(&effects->lock); memset(&effects->config, 0, sizeof(effects->config)); if (copy_from_user(&config32, (void *)arg, sizeof(config32))) { pr_err("%s: copy to user for AUDIO_SET_EFFECTS_CONFIG failed\n", __func__); rc = -EFAULT; + mutex_unlock(&effects->lock); break; } config->input.buf_size = config32.input.buf_size; @@ -620,16 +645,19 @@ static long audio_effects_compat_ioctl(struct file *file, unsigned int cmd, effects->config.input.num_buf, effects->config.input.sample_rate, effects->config.input.num_channels); + mutex_unlock(&effects->lock); break; } case AUDIO_EFFECTS_SET_BUF_LEN32: { struct msm_hwacc_buf_cfg32 buf_cfg32; struct msm_hwacc_effects_config *config = &effects->config; + mutex_lock(&effects->lock); if (copy_from_user(&buf_cfg32, (void *)arg, sizeof(buf_cfg32))) { pr_err("%s: copy from user for AUDIO_EFFECTS_SET_BUF_LEN failed\n", __func__); rc = -EFAULT; + mutex_unlock(&effects->lock); break; } config->buf_cfg.input_len = buf_cfg32.input_len; @@ -637,6 +665,7 @@ static long audio_effects_compat_ioctl(struct file *file, unsigned int cmd, pr_debug("%s: write buf len: %d, read buf len: %d\n", __func__, effects->config.buf_cfg.output_len, effects->config.buf_cfg.input_len); + mutex_unlock(&effects->lock); break; } case AUDIO_EFFECTS_GET_BUF_AVAIL32: { @@ -644,6 +673,7 @@ static long audio_effects_compat_ioctl(struct file *file, unsigned int cmd, memset(&buf_avail, 0, sizeof(buf_avail)); + mutex_lock(&effects->lock); buf_avail.input_num_avail = atomic_read(&effects->in_count); buf_avail.output_num_avail = atomic_read(&effects->out_count); pr_debug("%s: write buf avail: %d, read buf avail: %d\n", @@ -655,22 +685,26 @@ static long audio_effects_compat_ioctl(struct file *file, unsigned int cmd, __func__); rc = -EFAULT; } + mutex_unlock(&effects->lock); break; } case AUDIO_EFFECTS_SET_PP_PARAMS32: { long argvalues[MAX_PP_PARAMS_SZ] = {0}; int argvalues32[MAX_PP_PARAMS_SZ] = {0}; + mutex_lock(&effects->lock); if (copy_from_user(argvalues32, (void *)arg, MAX_PP_PARAMS_SZ*sizeof(int))) { pr_err("%s: copy from user failed for pp params\n", __func__); + mutex_unlock(&effects->lock); return -EFAULT; } for (i = 0; i < MAX_PP_PARAMS_SZ; i++) argvalues[i] = argvalues32[i]; rc = audio_effects_set_pp_param(effects, argvalues); + mutex_unlock(&effects->lock); break; } case AUDIO_START32: { diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index 8a69d00dd44643f96c345eff434c44c041c399a3..b471fa377af34b6aa83c35f11d4d850bc11e144b 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -4109,6 +4109,11 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, true, GFP_KERNEL); } else if (ieee80211_is_action(mgmt->frame_control)) { + if (len > BRCMF_FIL_ACTION_FRAME_SIZE + DOT11_MGMT_HDR_LEN) { + brcmf_err("invalid action frame length\n"); + err = -EINVAL; + goto exit; + } af_params = kzalloc(sizeof(*af_params), GFP_KERNEL); if (af_params == NULL) { brcmf_err("unable to allocate frame\n"); diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_wext.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_wext.c index 17695ce2c1f9cc6e2ebf78474f47381a557ea67d..56fed65a1f334354cd8c4fa1dceeab0a4da3616e 100644 --- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_wext.c +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_wext.c @@ -12143,6 +12143,10 @@ static const struct iw_priv_args we_private_args[] = { { WE_DUMP_DP_TRACE_LEVEL, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "dump_dp_trace"}, + { + WLAN_PRIV_SET_FTIES, + IW_PRIV_TYPE_CHAR | MAX_FTIE_SIZE, + 0, "set_ft_ies"}, }; diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/inc/sirMacProtDef.h b/drivers/staging/qcacld-2.0/CORE/MAC/inc/sirMacProtDef.h index 5e0a6d0ed7bfd40a76f07139e811d9411b164ca0..834cfe2831a339acda70ddd2e11a92a0394c8c10 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/inc/sirMacProtDef.h +++ b/drivers/staging/qcacld-2.0/CORE/MAC/inc/sirMacProtDef.h @@ -585,7 +585,7 @@ #define SIR_MAC_MAX_NUMBER_OF_RATES 12 #define SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS 4 #define SIR_MAC_KEY_LENGTH 13 // WEP Maximum key length size -#define SIR_MAC_AUTH_CHALLENGE_LENGTH 128 +#define SIR_MAC_AUTH_CHALLENGE_LENGTH 253 #define SIR_MAC_WEP_IV_LENGTH 4 #define SIR_MAC_WEP_ICV_LENGTH 4 diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/include/dot11f.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/include/dot11f.h index 1b07c3a2a84e23cbfa358d0c39f6156c4bab8e3c..686786ff15fedcf0699c25a2e53a7f76049b4984 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/src/include/dot11f.h +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/include/dot11f.h @@ -24,7 +24,6 @@ * under proprietary terms before Copyright ownership was assigned * to the Linux Foundation. */ - #ifndef DOT11F_H #define DOT11F_H /** @@ -37,7 +36,7 @@ * * * This file was automatically generated by 'framesc' - * Thu Oct 8 17:27:11 2015 from the following file(s): + * Tue Jul 4 11:07:27 2017 from the following file(s): * * dot11f.frms * @@ -91,8 +90,8 @@ typedef tANI_U32 tDOT11F_U64[2]; #define DOT11F_BUFFER_OVERFLOW ( 0x10000005 ) #define DOT11F_MANDATORY_TLV_MISSING ( 0x00001000 ) #define DOT11F_FAILED(code) ( (code) & 0x10000000 ) -#define DOT11F_WARNED(code) ( ( ( 0 == (code) ) & 0x10000000 ) && code) #define DOT11F_SUCCEEDED(code) ( (code) == 0 ) +#define DOT11F_WARNED(code) (!DOT11F_SUCCEEDED(code) && !DOT11F_FAILED(code)) /********************************************************************* * Fixed Fields * diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSecurityUtils.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSecurityUtils.c index 0241dc010adce002f14ea58a72b89d13cb66b1c2..049c86aa55f7870be232425c2af0e353f71048a2 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSecurityUtils.c +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSecurityUtils.c @@ -647,7 +647,7 @@ limEncryptAuthFrame(tpAniSirGlobal pMac, tANI_U8 keyId, tANI_U8 *pKey, tANI_U8 * */ void -limComputeCrc32(tANI_U8 *pDest, tANI_U8 * pSrc, tANI_U8 len) +limComputeCrc32(tANI_U8 *pDest, tANI_U8 * pSrc, tANI_U16 len) { tANI_U32 crc; int i; diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSecurityUtils.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSecurityUtils.h index 4ede5005b556f2063c5708fe932708e78e98b146..9139ce20f3b4c09d44dfc95b9c0299eff84d70ad 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSecurityUtils.h +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSecurityUtils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2015, 2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -59,7 +59,7 @@ tANI_U8 limDeleteOpenAuthPreAuthNode(tpAniSirGlobal pMac); // Encryption/Decryption related functions tCfgWepKeyEntry *limLookUpKeyMappings(tSirMacAddr); -void limComputeCrc32(tANI_U8 *, tANI_U8 *, tANI_U8); +void limComputeCrc32(tANI_U8 *, tANI_U8 *, tANI_U16); void limRC4(tANI_U8 *, tANI_U8 *, tANI_U8 *, tANI_U32, tANI_U16); void limEncryptAuthFrame(tpAniSirGlobal, tANI_U8, tANI_U8 *, tANI_U8 *, tANI_U8 *, tANI_U32); tANI_U8 limDecryptAuthFrame(tpAniSirGlobal, tANI_U8 *, tANI_U8 *, tANI_U8 *, tANI_U32, tANI_U16); diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/rrm/rrmApi.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/rrm/rrmApi.c index d42cedabbbedc28d1ecf7dfd7bb7028ca1dd9e7c..904e2b6a52792b3f6944fdb82e0eb00e4e391539 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/rrm/rrmApi.c +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/rrm/rrmApi.c @@ -628,14 +628,21 @@ rrmProcessBeaconReportReq( tpAniSirGlobal pMac, pSmeBcnReportReq->channelList.numChannels = num_channels; if( pBeaconReq->measurement_request.Beacon.num_APChannelReport ) { - tANI_U8 *pChanList = pSmeBcnReportReq->channelList.channelNumber; + tANI_U8 *ch_lst = pSmeBcnReportReq->channelList.channelNumber; + uint8_t len; + uint16_t ch_ctr = 0; for( num_APChanReport = 0 ; num_APChanReport < pBeaconReq->measurement_request.Beacon.num_APChannelReport ; num_APChanReport++ ) { - vos_mem_copy(pChanList, - pBeaconReq->measurement_request.Beacon.APChannelReport[num_APChanReport].channelList, - pBeaconReq->measurement_request.Beacon.APChannelReport[num_APChanReport].num_channelList); + len = pBeaconReq->measurement_request.Beacon. + APChannelReport[num_APChanReport].num_channelList; + if(ch_ctr + len > sizeof(pSmeBcnReportReq->channelList.channelNumber)) + break; + + vos_mem_copy(&ch_lst[ch_ctr], + pBeaconReq->measurement_request.Beacon. + APChannelReport[num_APChanReport].channelList, len); - pChanList += pBeaconReq->measurement_request.Beacon.APChannelReport[num_APChanReport].num_channelList; + ch_ctr += len; } } diff --git a/drivers/staging/qcacld-2.0/CORE/SME/src/sme_common/sme_FTApi.c b/drivers/staging/qcacld-2.0/CORE/SME/src/sme_common/sme_FTApi.c index 3947b83ac18193be51e51bfb0fa63095de7a2613..e4136722f9eb41deb98306e43937b4d6bdcd5034 100644 --- a/drivers/staging/qcacld-2.0/CORE/SME/src/sme_common/sme_FTApi.c +++ b/drivers/staging/qcacld-2.0/CORE/SME/src/sme_common/sme_FTApi.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2014, 2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2014, 2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -163,6 +163,9 @@ void sme_SetFTIEs(tHalHandle hHal, tANI_U32 sessionId, const tANI_U8 *ft_ies, { case eFT_START_READY: case eFT_AUTH_REQ_READY: +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + smsLog( pMac, LOG1, FL("ft_ies_length: %d"), ft_ies_length); +#endif if ((pSession->ftSmeContext.auth_ft_ies) && (pSession->ftSmeContext.auth_ft_ies_length)) { @@ -171,7 +174,7 @@ void sme_SetFTIEs(tHalHandle hHal, tANI_U32 sessionId, const tANI_U8 *ft_ies, pSession->ftSmeContext.auth_ft_ies_length = 0; pSession->ftSmeContext.auth_ft_ies = NULL; } - + ft_ies_length = VOS_MIN(ft_ies_length, MAX_FTIE_SIZE); // Save the FT IEs pSession->ftSmeContext.auth_ft_ies = vos_mem_malloc(ft_ies_length); @@ -187,9 +190,6 @@ void sme_SetFTIEs(tHalHandle hHal, tANI_U32 sessionId, const tANI_U8 *ft_ies, ft_ies,ft_ies_length); pSession->ftSmeContext.FTState = eFT_AUTH_REQ_READY; -#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG - smsLog( pMac, LOG1, "ft_ies_length=%d", ft_ies_length); -#endif break; case eFT_AUTH_COMPLETE: diff --git a/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/dot11f.c b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/dot11f.c index 2580c43b9be9b9e7e851f6020a9fcfac6f798125..ae53eceedbf87245a6796c7ece30cc65cc23101d 100644 --- a/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/dot11f.c +++ b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/dot11f.c @@ -35,7 +35,7 @@ * * * This file was automatically generated by 'framesc' - * Thu Oct 8 17:27:11 2015 from the following file(s): + * Tue Jul 4 11:07:27 2017 from the following file(s): * * dot11f.frms * @@ -19269,6 +19269,10 @@ static tANI_U32 UnpackCore(tpAniSirGlobal pCtx, } countOffset = ( (0 != pIe->arraybound) * ( *(tANI_U16* )(pFrm + pIe->countOffset))); + if (0 != pIe->arraybound && countOffset >= pIe->arraybound) { + status |= DOT11F_DUPLICATE_IE; + goto skip_dup_ie; + } switch (pIe->sig) { case SigIeCondensedCountryStr: @@ -19706,6 +19710,7 @@ static tANI_U32 UnpackCore(tpAniSirGlobal pCtx, status |= DOT11F_UNKNOWN_IES; } +skip_dup_ie: pBufRemaining += len; if (len > nBufRemaining) diff --git a/drivers/staging/qcacld-2.0/CORE/UTILS/PKTLOG/linux_ac.c b/drivers/staging/qcacld-2.0/CORE/UTILS/PKTLOG/linux_ac.c index 173ed4e8eec1a477f339b33cdbba204a8a35f84c..ec61b77e827cf4b34ada40426d7ab93f74a9f81b 100644 --- a/drivers/staging/qcacld-2.0/CORE/UTILS/PKTLOG/linux_ac.c +++ b/drivers/staging/qcacld-2.0/CORE/UTILS/PKTLOG/linux_ac.c @@ -82,14 +82,12 @@ static int pktlog_attach(struct ol_softc *sc); static void pktlog_detach(struct ol_softc *sc); static int pktlog_open(struct inode *i, struct file *f); static int pktlog_release(struct inode *i, struct file *f); -static int pktlog_mmap(struct file *f, struct vm_area_struct *vma); static ssize_t pktlog_read(struct file *file, char *buf, size_t nbytes, loff_t * ppos); static struct file_operations pktlog_fops = { open:pktlog_open, release:pktlog_release, - mmap:pktlog_mmap, read:pktlog_read, }; @@ -921,106 +919,6 @@ static volatile void *pktlog_virt_to_logical(volatile void *addr) } #endif -/* vma operations for mapping vmalloced area to user space */ -static void pktlog_vopen(struct vm_area_struct *vma) -{ - PKTLOG_MOD_INC_USE_COUNT; -} - -static void pktlog_vclose(struct vm_area_struct *vma) -{ - PKTLOG_MOD_DEC_USE_COUNT; -} - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25) -int pktlog_fault(struct vm_area_struct *vma, struct vm_fault *vmf) -{ - unsigned long address = (unsigned long)vmf->virtual_address; - - if (address == 0UL) - return VM_FAULT_NOPAGE; - - if (vmf->pgoff > vma->vm_end) - return VM_FAULT_SIGBUS; - - get_page(virt_to_page((void *)address)); - vmf->page = virt_to_page((void *)address); - return VM_FAULT_MINOR; -} -#else -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -struct page *pktlog_vmmap(struct vm_area_struct *vma, unsigned long addr, - int *type) -#else -struct page *pktlog_vmmap(struct vm_area_struct *vma, unsigned long addr, - int write_access) -#endif -{ - unsigned long offset, vaddr; - struct proc_dir_entry *proc_entry; - struct ath_pktlog_info *pl_info = - - proc_entry = PDE(vma->vm_file->f_dentry->d_inode); - pl_info = (struct ath_pktlog_info *)proc_entry->data; - - offset = addr - vma->vm_start + (vma->vm_pgoff << PAGE_SHIFT); - vaddr = (unsigned long) pktlog_virt_to_logical( - (void *)(pl_info->buf) + offset); - - if (vaddr == 0UL) { - printk(PKTLOG_TAG "%s: page fault out of range\n", __func__); - return ((struct page *) 0UL); - } - - /* increment the usage count of the page */ - get_page(virt_to_page((void*)vaddr)); - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - if (type) - *type = VM_FAULT_MINOR; -#endif - - return virt_to_page((void *)vaddr); -} -#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25) */ - -static struct vm_operations_struct pktlog_vmops = { - open:pktlog_vopen, - close:pktlog_vclose, -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25) - fault:pktlog_fault, -#else - nopage:pktlog_vmmap, -#endif -}; - -static int pktlog_mmap(struct file *file, struct vm_area_struct *vma) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) - struct ath_pktlog_info *pl_info = (struct ath_pktlog_info *) - PDE_DATA(file->f_path.dentry->d_inode); -#else - struct proc_dir_entry *proc_entry = PDE(file->f_dentry->d_inode); - struct ath_pktlog_info *pl_info = (struct ath_pktlog_info *) - proc_entry->data; -#endif - - if (vma->vm_pgoff != 0) { - /* Entire buffer should be mapped */ - return -EINVAL; - } - - if (!pl_info->buf) { - printk(PKTLOG_TAG "%s: Log buffer unavailable\n", __func__); - return -ENOMEM; - } - - vma->vm_flags |= VM_LOCKED; - vma->vm_ops = &pktlog_vmops; - pktlog_vopen(vma); - return 0; -} - int pktlogmod_init(void *context) { int ret; diff --git a/drivers/video/msm/mdss/mdss_hdmi_cec.c b/drivers/video/msm/mdss/mdss_hdmi_cec.c index a424d987bb6386f13e2414f73dc07a9270f346c7..a4ed01210e04c4f9d7e3c997bfe2c75569f39611 100644 --- a/drivers/video/msm/mdss/mdss_hdmi_cec.c +++ b/drivers/video/msm/mdss/mdss_hdmi_cec.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -196,7 +196,7 @@ static void hdmi_cec_msg_recv(struct work_struct *work) msg.sender_id, msg.recvr_id, msg.frame_size); - if (msg.frame_size < 1) { + if (msg.frame_size < 1 || msg.frame_size > MAX_CEC_FRAME_SIZE) { DEV_ERR("%s: invalid message (frame length = %d)\n", __func__, msg.frame_size); return; @@ -216,7 +216,7 @@ static void hdmi_cec_msg_recv(struct work_struct *work) msg.operand[i] = data & 0xFF; } - for (; i < 14; i++) + for (; i < MAX_OPERAND_SIZE; i++) msg.operand[i] = 0; DEV_DBG("%s: opcode 0x%x, wakup_en %d, device_suspend %d\n", __func__, diff --git a/drivers/video/msm/mdss/mdss_hdmi_edid.c b/drivers/video/msm/mdss/mdss_hdmi_edid.c index 36c24302658d83b1ac657afa0e47426397f402f4..5c8f52c42302cfbc83342057ef3ededb80500706 100644 --- a/drivers/video/msm/mdss/mdss_hdmi_edid.c +++ b/drivers/video/msm/mdss/mdss_hdmi_edid.c @@ -2180,6 +2180,13 @@ int hdmi_edid_parser(void *input) goto bail; } + /* Find out if CEA extension blocks exceeding max limit */ + if (num_of_cea_blocks >= MAX_EDID_BLOCKS) { + DEV_WARN("%s: HDMI EDID exceeded max CEA blocks limit\n", + __func__); + num_of_cea_blocks = MAX_EDID_BLOCKS - 1; + } + /* check for valid CEA block */ if (edid_buf[EDID_BLOCK_SIZE] != 2) { DEV_ERR("%s: Invalid CEA block\n", __func__); diff --git a/drivers/video/msm/mdss/mdss_rotator.c b/drivers/video/msm/mdss/mdss_rotator.c index ddbdf5a8f10bfdfd928fbbd4cc6d4d5820ca4c4b..0f2d285dcef6bd126227edd5aaafda741e803a3c 100644 --- a/drivers/video/msm/mdss/mdss_rotator.c +++ b/drivers/video/msm/mdss/mdss_rotator.c @@ -375,6 +375,15 @@ static bool mdss_rotator_is_work_pending(struct mdss_rot_mgr *mgr, return false; } +static void mdss_rotator_install_fence_fd(struct mdss_rot_entry_container *req) +{ + int i = 0; + + for (i = 0; i < req->count; i++) + sync_fence_install(req->entries[i].output_fence, + req->entries[i].output_fence_fd); +} + static int mdss_rotator_create_fence(struct mdss_rot_entry *entry) { int ret = 0, fd; @@ -413,7 +422,6 @@ static int mdss_rotator_create_fence(struct mdss_rot_entry *entry) goto get_fd_err; } - sync_fence_install(fence, fd); rot_timeline->next_value++; mutex_unlock(&rot_timeline->lock); @@ -2250,6 +2258,7 @@ static int mdss_rotator_handle_request(struct mdss_rot_mgr *mgr, goto handle_request_err1; } + mdss_rotator_install_fence_fd(req); mdss_rotator_queue_request(mgr, private, req); mutex_unlock(&mgr->lock); @@ -2410,6 +2419,7 @@ static int mdss_rotator_handle_request32(struct mdss_rot_mgr *mgr, goto handle_request32_err1; } + mdss_rotator_install_fence_fd(req); mdss_rotator_queue_request(mgr, private, req); mutex_unlock(&mgr->lock); diff --git a/include/linux/pid.h b/include/linux/pid.h index 23705a53abbaad29347a2724f24e80c7f44e9341..97b745ddece50889a61be5d3db1474e7c4fed14e 100644 --- a/include/linux/pid.h +++ b/include/linux/pid.h @@ -8,7 +8,9 @@ enum pid_type PIDTYPE_PID, PIDTYPE_PGID, PIDTYPE_SID, - PIDTYPE_MAX + PIDTYPE_MAX, + /* only valid to __task_pid_nr_ns() */ + __PIDTYPE_TGID }; /* diff --git a/include/linux/sched.h b/include/linux/sched.h index 32ca79fce9ad99c77e96a78f4de0a322aa3b6473..03951bc1b1b7e9722e1a817864885d4099cfb848 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1914,14 +1914,16 @@ static inline pid_t task_tgid_nr(struct task_struct *tsk) return tsk->tgid; } -pid_t task_tgid_nr_ns(struct task_struct *tsk, struct pid_namespace *ns); +static inline pid_t task_tgid_nr_ns(struct task_struct *tsk, struct pid_namespace *ns) +{ + return __task_pid_nr_ns(tsk, __PIDTYPE_TGID, ns); +} static inline pid_t task_tgid_vnr(struct task_struct *tsk) { - return pid_vnr(task_tgid(tsk)); + return __task_pid_nr_ns(tsk, __PIDTYPE_TGID, NULL); } - static inline int pid_alive(const struct task_struct *p); static inline pid_t task_ppid_nr_ns(const struct task_struct *tsk, struct pid_namespace *ns) { diff --git a/kernel/events/core.c b/kernel/events/core.c index 2bf9ebcbef4849929fcb0f3b5addea103cc003bd..b25fcc74a53112ebd7dd4c2904aff998cac9aa31 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -7414,6 +7414,37 @@ static void mutex_lock_double(struct mutex *a, struct mutex *b) mutex_lock_nested(b, SINGLE_DEPTH_NESTING); } +/* + * Variation on perf_event_ctx_lock_nested(), except we take two context + * mutexes. + */ +static struct perf_event_context * +__perf_event_ctx_lock_double(struct perf_event *group_leader, + struct perf_event_context *ctx) +{ + struct perf_event_context *gctx; + +again: + rcu_read_lock(); + gctx = ACCESS_ONCE(group_leader->ctx); + if (!atomic_inc_not_zero(&gctx->refcount)) { + rcu_read_unlock(); + goto again; + } + rcu_read_unlock(); + + mutex_lock_double(&gctx->mutex, &ctx->mutex); + + if (group_leader->ctx != gctx) { + mutex_unlock(&ctx->mutex); + mutex_unlock(&gctx->mutex); + put_ctx(gctx); + goto again; + } + + return gctx; +} + /** * sys_perf_event_open - open a performance event, associate it to a task/cpu * @@ -7643,14 +7674,31 @@ SYSCALL_DEFINE5(perf_event_open, } if (move_group) { - gctx = group_leader->ctx; + gctx = __perf_event_ctx_lock_double(group_leader, ctx); + + /* + * Check if we raced against another sys_perf_event_open() call + * moving the software group underneath us. + */ + if (!(group_leader->group_flags & PERF_GROUP_SOFTWARE)) { + /* + * If someone moved the group out from under us, check + * if this new event wound up on the same ctx, if so + * its the regular !move_group case, otherwise fail. + */ + if (gctx != ctx) { + err = -EINVAL; + goto err_locked; + } else { + perf_event_ctx_unlock(group_leader, gctx); + move_group = 0; + } + } /* * See perf_event_ctx_lock() for comments on the details * of swizzling perf_event::ctx. */ - mutex_lock_double(&gctx->mutex, &ctx->mutex); - perf_remove_from_context(group_leader, false); /* @@ -7691,7 +7739,7 @@ SYSCALL_DEFINE5(perf_event_open, perf_unpin_context(ctx); if (move_group) { - mutex_unlock(&gctx->mutex); + perf_event_ctx_unlock(group_leader, gctx); put_ctx(gctx); } mutex_unlock(&ctx->mutex); @@ -7722,6 +7770,11 @@ SYSCALL_DEFINE5(perf_event_open, fd_install(event_fd, event_file); return event_fd; +err_locked: + if (move_group) + perf_event_ctx_unlock(group_leader, gctx); + mutex_unlock(&ctx->mutex); + fput(event_file); err_context: perf_unpin_context(ctx); put_ctx(ctx); diff --git a/kernel/pid.c b/kernel/pid.c index 82430c858d6970317cd71a3770cce9f723673b22..65a386e248110120b25253e80524bf34af5fe2ad 100644 --- a/kernel/pid.c +++ b/kernel/pid.c @@ -523,8 +523,11 @@ pid_t __task_pid_nr_ns(struct task_struct *task, enum pid_type type, if (!ns) ns = task_active_pid_ns(current); if (likely(pid_alive(task))) { - if (type != PIDTYPE_PID) + if (type != PIDTYPE_PID) { + if (type == __PIDTYPE_TGID) + type = PIDTYPE_PID; task = task->group_leader; + } nr = pid_nr_ns(task->pids[type].pid, ns); } rcu_read_unlock(); @@ -533,12 +536,6 @@ pid_t __task_pid_nr_ns(struct task_struct *task, enum pid_type type, } EXPORT_SYMBOL(__task_pid_nr_ns); -pid_t task_tgid_nr_ns(struct task_struct *tsk, struct pid_namespace *ns) -{ - return pid_nr_ns(task_tgid(tsk), ns); -} -EXPORT_SYMBOL(task_tgid_nr_ns); - struct pid_namespace *task_active_pid_ns(struct task_struct *tsk) { return ns_of_pid(task_pid(tsk)); diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index cb860a5042ea49f7f652890f18585cd8b5ecd2fe..86e8031eed0debb08cb9091445a1cd9a3cca1881 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -301,8 +301,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { [NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 }, [NL80211_ATTR_PID] = { .type = NLA_U32 }, [NL80211_ATTR_4ADDR] = { .type = NLA_U8 }, - [NL80211_ATTR_PMKID] = { .type = NLA_BINARY, - .len = WLAN_PMKID_LEN }, + [NL80211_ATTR_PMKID] = { .len = WLAN_PMKID_LEN }, [NL80211_ATTR_DURATION] = { .type = NLA_U32 }, [NL80211_ATTR_COOKIE] = { .type = NLA_U64 }, [NL80211_ATTR_TX_RATES] = { .type = NLA_NESTED }, @@ -358,6 +357,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { [NL80211_ATTR_SCAN_FLAGS] = { .type = NLA_U32 }, [NL80211_ATTR_P2P_CTWINDOW] = { .type = NLA_U8 }, [NL80211_ATTR_P2P_OPPPS] = { .type = NLA_U8 }, + [NL80211_ATTR_LOCAL_MESH_POWER_MODE] = {. type = NLA_U32 }, [NL80211_ATTR_ACL_POLICY] = {. type = NLA_U32 }, [NL80211_ATTR_MAC_ADDRS] = { .type = NLA_NESTED }, [NL80211_ATTR_STA_CAPABILITY] = { .type = NLA_U16 }, diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 4ea4e6ff7bb1f038982471e9b1950ea085ccb4ca..f8049adbbb2e95e57682054bb3cafa399213dadd 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -150,7 +150,9 @@ static int snd_pcm_control_ioctl(struct snd_card *card, err = -ENXIO; goto _error; } + mutex_lock(&pcm->open_mutex); err = snd_pcm_info_user(substream, info); + mutex_unlock(&pcm->open_mutex); _error: mutex_unlock(®ister_mutex); return err; diff --git a/sound/soc/msm/qdsp6v2/msm-audio-effects-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-audio-effects-q6-v2.c index 8c250f6166052fc5e14a91be8ea980aa7b5d4fe4..f72c15a5e54790245e5ab23a02cb8e8fb5570a0e 100644 --- a/sound/soc/msm/qdsp6v2/msm-audio-effects-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-audio-effects-q6-v2.c @@ -177,7 +177,7 @@ int msm_audio_effects_virtualizer_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "VIRT ENABLE", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_VIRTUALIZER; *updt_params++ = @@ -205,7 +205,7 @@ int msm_audio_effects_virtualizer_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "VIRT STRENGTH", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_VIRTUALIZER; *updt_params++ = @@ -233,7 +233,7 @@ int msm_audio_effects_virtualizer_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "VIRT OUT_TYPE", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_VIRTUALIZER; *updt_params++ = @@ -261,7 +261,7 @@ int msm_audio_effects_virtualizer_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "VIRT GAIN_ADJUST", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_VIRTUALIZER; *updt_params++ = @@ -340,7 +340,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "REVERB_ENABLE", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_REVERB; *updt_params++ = @@ -368,7 +368,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "REVERB_MODE", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_REVERB; *updt_params++ = @@ -396,7 +396,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "REVERB_PRESET", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_REVERB; *updt_params++ = @@ -424,7 +424,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "REVERB_WET_MIX", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_REVERB; *updt_params++ = @@ -452,7 +452,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "REVERB_GAIN_ADJUST", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_REVERB; *updt_params++ = @@ -480,7 +480,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "REVERB_ROOM_LEVEL", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_REVERB; *updt_params++ = @@ -508,7 +508,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "REVERB_ROOM_HF_LEVEL", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_REVERB; *updt_params++ = @@ -536,7 +536,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "REVERB_DECAY_TIME", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_REVERB; *updt_params++ = @@ -564,7 +564,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "REVERB_DECAY_HF_RATIO", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_REVERB; *updt_params++ = @@ -592,7 +592,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "REVERB_REFLECTIONS_LEVEL", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_REVERB; *updt_params++ = @@ -620,7 +620,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "REVERB_REFLECTIONS_DELAY", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_REVERB; *updt_params++ = @@ -648,7 +648,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "REVERB_LEVEL", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_REVERB; *updt_params++ = @@ -676,7 +676,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "REVERB_DELAY", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_REVERB; *updt_params++ = @@ -704,7 +704,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "REVERB_DIFFUSION", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_REVERB; *updt_params++ = @@ -732,7 +732,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "REVERB_DENSITY", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_REVERB; *updt_params++ = @@ -812,7 +812,7 @@ int msm_audio_effects_bass_boost_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "BASS_BOOST_ENABLE", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_BASS_BOOST; *updt_params++ = @@ -840,7 +840,7 @@ int msm_audio_effects_bass_boost_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "BASS_BOOST_MODE", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_BASS_BOOST; *updt_params++ = @@ -868,7 +868,7 @@ int msm_audio_effects_bass_boost_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "BASS_BOOST_STRENGTH", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_BASS_BOOST; *updt_params++ = @@ -946,7 +946,7 @@ int msm_audio_effects_pbe_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "PBE_ENABLE", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_PBE; *updt_params++ = @@ -972,7 +972,7 @@ int msm_audio_effects_pbe_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "PBE_PARAM", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_PBE; *updt_params++ = @@ -1057,7 +1057,7 @@ int msm_audio_effects_popless_eq_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "EQ_ENABLE", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_POPLESS_EQUALIZER; *updt_params++ = @@ -1125,7 +1125,7 @@ int msm_audio_effects_popless_eq_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "EQ_CONFIG", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_POPLESS_EQUALIZER; *updt_params++ = @@ -1176,7 +1176,7 @@ int msm_audio_effects_popless_eq_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "EQ_BAND_INDEX", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_POPLESS_EQUALIZER; *updt_params++ = @@ -1208,7 +1208,7 @@ int msm_audio_effects_popless_eq_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "EQ_SINGLE_BAND_FREQ", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_POPLESS_EQUALIZER; *updt_params++ = @@ -1298,7 +1298,7 @@ static int __msm_audio_effects_volume_handler(struct audio_client *ac, "VOLUME/VOLUME2_GAIN_2CH", rc); if (rc != 0) - break; + goto invalid_config; if (instance == SOFT_VOLUME_INSTANCE_2) *updt_params++ = ASM_MODULE_ID_VOL_CTRL2; @@ -1347,7 +1347,7 @@ static int __msm_audio_effects_volume_handler(struct audio_client *ac, "VOLUME/VOLUME2_GAIN_MASTER", rc); if (rc != 0) - break; + goto invalid_config; if (instance == SOFT_VOLUME_INSTANCE_2) *updt_params++ = ASM_MODULE_ID_VOL_CTRL2;