Merge 895cfcbb7a on remote branch

Change-Id: I5b8da1cd03875baabbf5d4efbf5fb0864637a52f
This commit is contained in:
Linux Build Service Account 2026-01-05 04:44:47 -08:00
commit 4605f524fd
24 changed files with 705 additions and 82 deletions

View file

@ -265,6 +265,71 @@ Description: Specific uncompressed frame descriptors
bmCapabilities - still image support, fixed frame-rate
support
What: /config/usb-gadget/gadget/functions/uvc.name/streaming/framebased
Date: Oct 2025
KernelVersion: 5.4
Description: Framebased format descriptors
What: /config/usb-gadget/gadget/functions/uvc.name/streaming/framebased/name
Date: Oct 2025
KernelVersion: 5.4
Description: Specific framebased format descriptors
================== =======================================
bFormatIndex unique id for this format descriptor;
only defined after parent header is
linked into the streaming class;
read-only
bmaControls this format's data for bmaControls in
the streaming header
bmInterlaceFlags specifies interlace information,
read-only
bAspectRatioY the X dimension of the picture aspect
ratio, read-only
bAspectRatioX the Y dimension of the picture aspect
ratio, read-only
bDefaultFrameIndex optimum frame index for this stream
bBitsPerPixel number of bits per pixel used to
specify color in the decoded video
frame
guidFormat globally unique id used to identify
stream-encoding format
================== =======================================
What: /config/usb-gadget/gadget/functions/uvc.name/streaming/framebased/name/name
Date: Sept 2024
KernelVersion: 5.15
Description: Specific framebased frame descriptors
========================= =====================================
bFrameIndex unique id for this framedescriptor;
only defined after parent format is
linked into the streaming header;
read-only
dwFrameInterval indicates how frame interval can be
programmed; a number of values
separated by newline can be specified
dwDefaultFrameInterval the frame interval the device would
like to use as default
dwBytesPerLine Specifies the number of bytes per line
of video for packed fixed frame size
formats, allowing the receiver to
perform stride alignment of the video.
If the bVariableSize value (above) is
TRUE (1), or if the format does not
permit such alignment, this value shall
be set to zero (0).
dwMaxBitRate the maximum bit rate at the shortest
frame interval in bps
dwMinBitRate the minimum bit rate at the longest
frame interval in bps
wHeight height of decoded bitmap frame in px
wWidth width of decoded bitmam frame in px
bmCapabilities still image support, fixed frame-rate
support
========================= =====================================
What: /config/usb-gadget/gadget/functions/uvc.name/streaming/header
Date: Dec 2014
KernelVersion: 4.0

View file

@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/clk/qcom.h>
@ -2523,6 +2524,7 @@ int a6xx_perfcounter_update(struct adreno_device *adreno_dev,
struct cpu_gpu_lock *lock = ptr;
u32 *data = ptr + sizeof(*lock);
int i, offset = 0;
u32 pending_pairs = 2; /* No of pairs to add: <select,value> and <cntl,1> */
if (cpu_gpu_lock(lock)) {
cpu_gpu_unlock(lock);
@ -2546,6 +2548,13 @@ int a6xx_perfcounter_update(struct adreno_device *adreno_dev,
offset += 2;
}
/* Ensure there is enough space in the reglist buffer for new pairs */
if ((offset + (pending_pairs * 2)) >=
(adreno_dev->pwrup_reglist->size / sizeof(u32))) {
cpu_gpu_unlock(lock);
return -ENOSPC;
}
/*
* For all targets A6XX_RBBM_PERFCTR_CNTL needs to be the last entry,
* so overwrite the existing A6XX_RBBM_PERFCNTL_CTRL and add it back to

View file

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/debugfs.h>
@ -135,6 +135,8 @@ static int msm_cvp_initialize_core(struct platform_device *pdev,
INIT_LIST_HEAD(&core->instances);
mutex_init(&core->lock);
mutex_init(&core->clk_lock);
mutex_init(&core->idr_mtx);
idr_init(&core->sess_idr);
core->state = CVP_CORE_UNINIT;
for (i = SYS_MSG_INDEX(SYS_MSG_START);
@ -506,6 +508,8 @@ static int msm_cvp_remove(struct platform_device *pdev)
msm_cvp_free_platform_resources(&core->resources);
sysfs_remove_group(&pdev->dev.kobj, &msm_cvp_core_attr_group);
dev_set_drvdata(&pdev->dev, NULL);
idr_destroy(&core->sess_idr);
mutex_destroy(&core->idr_mtx);
mutex_destroy(&core->lock);
mutex_destroy(&core->clk_lock);
kfree(core);

View file

@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <asm/memory.h>
@ -29,6 +30,7 @@
#include "cvp_hfi_helper.h"
#include "cvp_hfi_io.h"
#include "msm_cvp_dsp.h"
#include "msm_cvp.h"
#define FIRMWARE_SIZE 0X00A00000
#define REG_ADDR_OFFSET_BITMASK 0x000FFFFF
@ -469,6 +471,7 @@ static int __dsp_suspend(struct iris_hfi_device *device, bool force, u32 flags)
{
int rc;
struct cvp_hal_session *temp;
struct msm_cvp_inst *inst = NULL;
if (msm_cvp_dsp_disable)
return 0;
@ -480,9 +483,10 @@ static int __dsp_suspend(struct iris_hfi_device *device, bool force, u32 flags)
/* don't suspend if cvp session is not paused */
if (!(temp->flags & SESSION_PAUSE)) {
inst = (struct msm_cvp_inst *)temp->session_id;
dprintk(CVP_DSP,
"%s: cvp session %x not paused\n",
__func__, hash32_ptr(temp));
__func__, inst->sess_id);
return -EBUSY;
}
}
@ -2224,12 +2228,17 @@ static void __session_clean(struct cvp_hal_session *session)
{
struct cvp_hal_session *temp, *next;
struct iris_hfi_device *device;
struct msm_cvp_core *core = NULL;
struct msm_cvp_inst *inst = NULL;
void *tmp = NULL;
if (!session || !session->device) {
dprintk(CVP_WARN, "%s: invalid params\n", __func__);
return;
}
device = session->device;
core = list_first_entry(&cvp_driver->cores, struct msm_cvp_core, list);
inst = (struct msm_cvp_inst *) session->session_id;
dprintk(CVP_SESS, "deleted the session: %pK\n", session);
/*
* session might have been removed from the device list in
@ -2241,6 +2250,13 @@ static void __session_clean(struct cvp_hal_session *session)
break;
}
}
/* Remove the IDR id assigned to this session */
mutex_lock(&core->idr_mtx);
tmp = idr_remove(&core->sess_idr, inst->sess_id);
if (tmp != session)
dprintk(CVP_WARN, "%s: session\n", __func__);
mutex_unlock(&core->idr_mtx);
/* Poison the session handle with zeros */
*session = (struct cvp_hal_session){ {0} };
kfree(session);
@ -2278,6 +2294,9 @@ static int iris_hfi_session_init(void *device, void *session_id,
struct cvp_hfi_cmd_sys_session_init_packet pkt;
struct iris_hfi_device *dev;
struct cvp_hal_session *s;
struct msm_cvp_core *core;
struct msm_cvp_inst *inst;
int id = 0;
if (!device || !new_session) {
dprintk(CVP_ERR, "%s - invalid input\n", __func__);
@ -2285,6 +2304,8 @@ static int iris_hfi_session_init(void *device, void *session_id,
}
dev = device;
core = list_first_entry(&cvp_driver->cores, struct msm_cvp_core, list);
inst = session_id;
mutex_lock(&dev->lock);
s = kzalloc(sizeof(*s), GFP_KERNEL);
@ -2295,15 +2316,35 @@ static int iris_hfi_session_init(void *device, void *session_id,
s->session_id = session_id;
s->device = dev;
mutex_lock(&core->idr_mtx);
idr_preload(GFP_KERNEL);
/* Need to think if we can use core->lock or dev->lock or need a
* different new lock for this?
*/
id = idr_alloc(&core->sess_idr, (void *)s, 0x7FFF0000, INT_MAX, GFP_NOWAIT);
idr_preload_end();
mutex_unlock(&core->idr_mtx);
if (id < 0) {
dprintk(CVP_ERR,
"%s: idr allocation failed for session %pK of inst %pK\n",
__func__, s, session_id);
goto err_session_init_fail;
}
dprintk(CVP_SESS,
"%s: inst %pK, session %pK\n", __func__, session_id, s);
"%s: inst %pK, session %pK, idr_id = 0x%x\n", __func__, session_id, s, id);
list_add_tail(&s->list, &dev->sess_head);
__set_default_sys_properties(device);
inst->sess_id = id;
if (call_hfi_pkt_op(dev, session_init, &pkt, s)) {
dprintk(CVP_ERR, "session_init: failed to create packet\n");
inst->sess_id = 0x0000DEAD;
goto err_session_init_fail;
}
@ -2317,6 +2358,7 @@ static int iris_hfi_session_init(void *device, void *session_id,
err_session_init_fail:
if (s)
__session_clean(s);
inst->sess_id = 0;
*new_session = NULL;
mutex_unlock(&dev->lock);
return -EINVAL;
@ -2878,9 +2920,11 @@ static struct cvp_hal_session *__get_session(struct iris_hfi_device *device,
u32 session_id)
{
struct cvp_hal_session *temp = NULL;
struct msm_cvp_inst *inst = NULL;
list_for_each_entry(temp, &device->sess_head, list) {
if (session_id == hash32_ptr(temp))
inst = (struct msm_cvp_inst *)temp->session_id;
if (session_id == inst->sess_id)
return temp;
}
@ -3059,6 +3103,7 @@ static int __response_handler(struct iris_hfi_device *device)
/* Process the packet types that we're interested in */
process_system_msg(info, device, raw_packet);
/* This session_id is a double pointer to the idr_id of session */
session_id = get_session_id(info);
/*
* hfi_process_msg_packet provides a session_id that's a hashed
@ -3070,11 +3115,6 @@ static int __response_handler(struct iris_hfi_device *device)
if (session_id) {
struct cvp_hal_session *session = NULL;
if (upper_32_bits((uintptr_t)*session_id) != 0) {
dprintk(CVP_ERR,
"Upper 32-bits != 0 for sess_id=%pK\n",
*session_id);
}
session = __get_session(device,
(u32)(uintptr_t)*session_id);
if (!session) {

View file

@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include "hfi_packetization.h"
@ -208,7 +209,7 @@ inline int cvp_create_pkt_cmd_sys_session_init(
pkt->size = sizeof(struct cvp_hfi_cmd_sys_session_init_packet);
pkt->packet_type = HFI_CMD_SYS_SESSION_INIT;
pkt->session_id = hash32_ptr(session);
pkt->session_id = inst->sess_id;
pkt->session_type = inst->prop.type;
pkt->session_kmask = inst->prop.kernel_mask;
pkt->session_prio = inst->prop.priority;
@ -266,13 +267,14 @@ int cvp_create_pkt_cmd_session_cmd(struct cvp_hal_session_cmd_pkt *pkt,
int pkt_type, struct cvp_hal_session *session)
{
int rc = 0;
struct msm_cvp_inst *inst = session->session_id;
if (!pkt)
return -EINVAL;
pkt->size = sizeof(struct cvp_hal_session_cmd_pkt);
pkt->packet_type = pkt_type;
pkt->session_id = hash32_ptr(session);
pkt->session_id = inst->sess_id;
return rc;
}
@ -305,13 +307,14 @@ int cvp_create_pkt_cmd_session_set_buffers(
{
int rc = 0;
struct cvp_hfi_cmd_session_set_buffers_packet *pkt;
struct msm_cvp_inst *inst = session->session_id;
if (!cmd || !session)
if (!cmd || !session || !inst)
return -EINVAL;
pkt = (struct cvp_hfi_cmd_session_set_buffers_packet *)cmd;
pkt->packet_type = HFI_CMD_SESSION_CVP_SET_BUFFERS;
pkt->session_id = hash32_ptr(session);
pkt->session_id = inst->sess_id;
pkt->buf_type.iova = iova;
pkt->buf_type.size = size;
pkt->size = sizeof(struct cvp_hfi_cmd_session_set_buffers_packet);
@ -324,13 +327,14 @@ int cvp_create_pkt_cmd_session_release_buffers(
struct cvp_hal_session *session)
{
struct cvp_session_release_buffers_packet *pkt;
struct msm_cvp_inst *inst = session->session_id;
if (!cmd || !session)
if (!cmd || !session || !inst)
return -EINVAL;
pkt = (struct cvp_session_release_buffers_packet *)cmd;
pkt->packet_type = HFI_CMD_SESSION_CVP_RELEASE_BUFFERS;
pkt->session_id = hash32_ptr(session);
pkt->session_id = inst->sess_id;
pkt->num_buffers = 1;
pkt->buffer_type = 0;
pkt->size = sizeof(struct cvp_session_release_buffers_packet) +
@ -347,6 +351,7 @@ int cvp_create_pkt_cmd_session_send(
int def_idx;
struct cvp_hal_session_cmd_pkt *ptr =
(struct cvp_hal_session_cmd_pkt *)in_pkt;
struct msm_cvp_inst *inst = session->session_id;
if (!out_pkt || !in_pkt || !session)
return -EINVAL;
@ -354,7 +359,7 @@ int cvp_create_pkt_cmd_session_send(
if (ptr->size > MAX_HFI_PKT_SIZE * sizeof(unsigned int))
goto error_hfi_packet;
if (ptr->session_id != hash32_ptr(session))
if (ptr->session_id != inst->sess_id)
goto error_hfi_packet;
def_idx = get_pkt_index(ptr);

View file

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
* Copyright (c) 2022-2024, Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/bitops.h>
@ -462,7 +462,7 @@ static struct msm_cvp_inst *cvp_get_inst_from_id(struct msm_cvp_core *core,
retry:
if (mutex_trylock(&core->lock)) {
list_for_each_entry(inst, &core->instances, list) {
if (hash32_ptr(inst->session) == session_id) {
if (inst->sess_id == session_id) {
match = true;
break;
}

View file

@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include "msm_cvp.h"
@ -14,6 +15,47 @@ struct cvp_power_level {
unsigned long bw_sum;
};
void *get_sessObj_from_idr(struct msm_cvp_inst *inst)
{
void *sessObj = NULL;
struct msm_cvp_core *core = NULL;
if (!inst || !inst->core) {
dprintk(CVP_ERR, "%s: invalid params\n", __func__);
return NULL;
}
core = inst->core;
mutex_lock(&core->idr_mtx);
sessObj = idr_find(&core->sess_idr, inst->sess_id);
mutex_unlock(&core->idr_mtx);
if (!sessObj)
dprintk(CVP_ERR, "%s: Could not find the sess obj for given idr id\n",
__func__);
return sessObj;
}
u32 get_sessId_from_idr(void *session)
{
void *ptr = NULL;
u32 sess_id = -1;
struct msm_cvp_core *core = NULL;
core = list_first_entry(&cvp_driver->cores, struct msm_cvp_core, list);
if (!session || !core)
return -EINVAL;
mutex_lock(&core->idr_mtx);
idr_for_each_entry(&core->sess_idr, ptr, sess_id) {
if (ptr == session) {
mutex_unlock(&core->idr_mtx);
return sess_id;
}
}
mutex_unlock(&core->idr_mtx);
return sess_id;
}
static int msm_cvp_get_session_info(struct msm_cvp_inst *inst,
struct cvp_kmd_session_info *session)
{
@ -30,7 +72,7 @@ static int msm_cvp_get_session_info(struct msm_cvp_inst *inst,
return -ECONNRESET;
s->cur_cmd_type = CVP_KMD_GET_SESSION_INFO;
session->session_id = hash32_ptr(inst->session);
session->session_id = inst->sess_id;
dprintk(CVP_SESS, "%s: id 0x%x\n", __func__, session->session_id);
s->cur_cmd_type = 0;
@ -1227,7 +1269,7 @@ static int msm_cvp_session_stop(struct msm_cvp_inst *inst,
sq->state = QUEUE_STOP;
pr_info(CVP_DBG_TAG "Stop session: %pK session_id = %d\n",
"sess", inst, hash32_ptr(inst->session));
"sess", inst, inst->sess_id);
spin_unlock(&sq->lock);
wake_up_all(&inst->session_queue.wq);
@ -1251,7 +1293,7 @@ int msm_cvp_session_queue_stop(struct msm_cvp_inst *inst)
sq->state = QUEUE_STOP;
dprintk(CVP_SESS, "Stop session queue: %pK session_id = %d\n",
inst, hash32_ptr(inst->session));
inst, inst->sess_id);
spin_unlock(&sq->lock);
wake_up_all(&inst->session_queue.wq);
@ -1551,7 +1593,7 @@ static void cvp_clean_fence_queue(struct msm_cvp_inst *inst, int synx_state)
ktid = f->pkt->client_data.kdata & (FENCE_BIT - 1);
dprintk(CVP_SYNX, "%s: (%#x) flush frame %llu %llu wait_list\n",
__func__, hash32_ptr(inst->session), ktid, f->frame_id);
__func__, inst->sess_id, ktid, f->frame_id);
list_del_init(&f->list);
msm_cvp_unmap_frame(inst, f->pkt->client_data.kdata);
@ -1564,7 +1606,7 @@ static void cvp_clean_fence_queue(struct msm_cvp_inst *inst, int synx_state)
ktid = f->pkt->client_data.kdata & (FENCE_BIT - 1);
dprintk(CVP_SYNX, "%s: (%#x)flush frame %llu %llu sched_list\n",
__func__, hash32_ptr(inst->session), ktid, f->frame_id);
__func__, inst->sess_id, ktid, f->frame_id);
cvp_cancel_synx(inst, CVP_INPUT_SYNX, f, synx_state);
}
@ -1612,14 +1654,14 @@ static int cvp_flush_all(struct msm_cvp_inst *inst)
return -ECONNRESET;
dprintk(CVP_SESS, "session %llx (%#x)flush all starts\n",
inst, hash32_ptr(inst->session));
inst, inst->sess_id);
q = &inst->fence_cmd_queue;
hdev = inst->core->device;
cvp_clean_fence_queue(inst, SYNX_STATE_SIGNALED_CANCEL);
dprintk(CVP_SESS, "%s: (%#x) send flush to fw\n",
__func__, hash32_ptr(inst->session));
__func__, inst->sess_id);
/* Send flush to FW */
rc = call_hfi_op(hdev, session_flush, (void *)inst->session);
@ -1636,7 +1678,7 @@ static int cvp_flush_all(struct msm_cvp_inst *inst)
__func__, rc);
dprintk(CVP_SESS, "%s: (%#x) received flush from fw\n",
__func__, hash32_ptr(inst->session));
__func__, inst->sess_id);
exit:
rc = cvp_drain_fence_sched_list(inst);
@ -1859,10 +1901,10 @@ int msm_cvp_session_deinit(struct msm_cvp_inst *inst)
return -EINVAL;
}
dprintk(CVP_SESS, "%s: inst %pK (%#x)\n", __func__,
inst, hash32_ptr(inst->session));
inst, inst->sess_id);
session = (struct cvp_hal_session *)inst->session;
if (!session)
session = (struct cvp_hal_session *)get_sessObj_from_idr(inst);
if (!session || session != inst->session)
return rc;
rc = msm_cvp_comm_try_state(inst, MSM_CVP_CLOSE_DONE);
@ -1883,7 +1925,7 @@ int msm_cvp_session_init(struct msm_cvp_inst *inst)
}
dprintk(CVP_SESS, "%s: inst %pK (%#x)\n", __func__,
inst, hash32_ptr(inst->session));
inst, inst->sess_id);
/* set default frequency */
inst->clk_data.core_id = 0;

View file

@ -1,6 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef _MSM_CVP_H_
@ -34,4 +35,6 @@ int msm_cvp_session_init(struct msm_cvp_inst *inst);
int msm_cvp_session_deinit(struct msm_cvp_inst *inst);
int msm_cvp_session_queue_stop(struct msm_cvp_inst *inst);
int cvp_stop_clean_fence_queue(struct msm_cvp_inst *inst);
void *get_sessObj_from_idr(struct msm_cvp_inst *inst);
u32 get_sessId_from_idr(void *session);
#endif

View file

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include "msm_cvp_common.h"
@ -14,7 +14,7 @@
do { \
clear_bit(idx, &inst->dma_cache.usage_bitmap); \
dprintk(CVP_MEM, "clear %x bit %d dma_cache bitmap 0x%llx\n", \
hash32_ptr(inst->session), smem->bitmap_index, \
inst->sess_id, smem->bitmap_index, \
inst->dma_cache.usage_bitmap); \
} while (0)
@ -22,7 +22,7 @@
do { \
set_bit(idx, &inst->dma_cache.usage_bitmap); \
dprintk(CVP_MEM, "Set %x bit %d dma_cache bitmap 0x%llx\n", \
hash32_ptr(inst->session), idx, \
inst->sess_id, idx, \
inst->dma_cache.usage_bitmap); \
} while (0)
@ -36,7 +36,7 @@ void print_smem(u32 tag, const char *str, struct msm_cvp_inst *inst,
if (smem->dma_buf) {
dprintk(tag,
"%s: %x : %s size %d flags %#x iova %#x idx %d ref %d",
str, hash32_ptr(inst->session), smem->dma_buf->name,
str, inst->sess_id, smem->dma_buf->name,
smem->size, smem->flags, smem->device_addr,
smem->bitmap_index, smem->refcount);
}
@ -51,13 +51,13 @@ static void print_internal_buffer(u32 tag, const char *str,
if (cbuf->smem->dma_buf) {
dprintk(tag,
"%s: %x : fd %d off %d %s size %d iova %#x",
str, hash32_ptr(inst->session), cbuf->fd,
str, inst->sess_id, cbuf->fd,
cbuf->offset, cbuf->smem->dma_buf->name, cbuf->size,
cbuf->smem->device_addr);
} else {
dprintk(tag,
"%s: %x : idx %2d fd %d off %d size %d iova %#x",
str, hash32_ptr(inst->session), cbuf->fd,
str, inst->sess_id, cbuf->fd,
cbuf->offset, cbuf->size, cbuf->smem->device_addr);
}
}
@ -77,7 +77,7 @@ void print_client_buffer(u32 tag, const char *str,
dprintk(tag,
"%s: %x : idx %2d fd %d off %d size %d type %d flags 0x%x\n",
str, hash32_ptr(inst->session), cbuf->index, cbuf->fd,
str, inst->sess_id, cbuf->index, cbuf->fd,
cbuf->offset, cbuf->size, cbuf->type, cbuf->flags);
}
@ -154,7 +154,7 @@ int msm_cvp_map_buf_dsp(struct msm_cvp_inst *inst, struct cvp_kmd_buffer *buf)
}
if (buf->index) {
rc = cvp_dsp_register_buffer(hash32_ptr(session), buf->fd,
rc = cvp_dsp_register_buffer(inst->sess_id, buf->fd,
smem->dma_buf->size, buf->size, buf->offset,
buf->index, (uint32_t)smem->device_addr);
if (rc) {
@ -227,7 +227,7 @@ int msm_cvp_unmap_buf_dsp(struct msm_cvp_inst *inst, struct cvp_kmd_buffer *buf)
}
if (buf->index) {
rc = cvp_dsp_deregister_buffer(hash32_ptr(session), buf->fd,
rc = cvp_dsp_deregister_buffer(inst->sess_id, buf->fd,
cbuf->smem->dma_buf->size, buf->size, buf->offset,
buf->index, (uint32_t)cbuf->smem->device_addr);
if (rc) {
@ -545,7 +545,7 @@ void msm_cvp_unmap_frame(struct msm_cvp_inst *inst, u64 ktid)
ktid &= (FENCE_BIT - 1);
dprintk(CVP_MEM, "%s: (%#x) unmap frame %llu\n",
__func__, hash32_ptr(inst->session), ktid);
__func__, inst->sess_id, ktid);
found = false;
mutex_lock(&inst->frames.lock);
@ -587,7 +587,7 @@ int msm_cvp_unmap_user_persist(struct msm_cvp_inst *inst,
smem = pbuf->smem;
dprintk(CVP_MEM, "unmap persist: %x %d %d %#x",
hash32_ptr(inst->session), pbuf->fd,
inst->sess_id, pbuf->fd,
pbuf->size, smem->device_addr);
if (smem->bitmap_index >= MAX_DMABUF_NUMS) {
@ -785,7 +785,7 @@ int msm_cvp_session_deinit_buffers(struct msm_cvp_inst *inst)
list_for_each_entry_safe(cbuf, dummy, &inst->cvpdspbufs.list,
list) {
print_internal_buffer(CVP_MEM, "remove dspbufs", inst, cbuf);
rc = cvp_dsp_deregister_buffer(hash32_ptr(session),
rc = cvp_dsp_deregister_buffer(inst->sess_id,
cbuf->fd, cbuf->smem->dma_buf->size, cbuf->size,
cbuf->offset, cbuf->index,
(uint32_t)cbuf->smem->device_addr);
@ -955,7 +955,7 @@ int cvp_release_arp_buffers(struct msm_cvp_inst *inst)
if (buf->ownership == DRIVER) {
dprintk(CVP_MEM,
"%s: %x : fd %d %s size %d",
"free arp", hash32_ptr(inst->session), buf->fd,
"free arp", inst->sess_id, buf->fd,
smem->dma_buf->name, buf->size);
msm_cvp_smem_free(smem);
kmem_cache_free(cvp_driver->smem_cache, smem);

View file

@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/jiffies.h>
@ -195,23 +196,31 @@ struct msm_cvp_inst *cvp_get_inst_validate(struct msm_cvp_core *core,
{
int rc = 0;
struct cvp_hfi_device *hdev;
struct msm_cvp_inst *s;
struct msm_cvp_inst *inst;
void *sessObj = NULL;
s = cvp_get_inst(core, session_id);
if (!s) {
dprintk(CVP_ERR, "%s session doesn't exit\n",
inst = cvp_get_inst(core, session_id);
if (!inst) {
dprintk(CVP_ERR, "%s Inst doesn't exit\n",
__builtin_return_address(0));
return NULL;
}
hdev = s->core->device;
rc = call_hfi_op(hdev, validate_session, s->session, __func__);
if (rc) {
cvp_put_inst(s);
s = NULL;
sessObj = get_sessObj_from_idr(inst);
if (!sessObj || sessObj != inst->session) {
dprintk(CVP_ERR,
"Either sessionObj is null or not matching with inst->session\n");
return NULL;
}
return s;
hdev = inst->core->device;
rc = call_hfi_op(hdev, validate_session, sessObj, __func__);
if (rc) {
cvp_put_inst(inst);
inst = NULL;
}
return inst;
}
static void cvp_handle_session_cmd_done(enum hal_command_response cmd,
@ -486,7 +495,7 @@ static void handle_session_init_done(enum hal_command_response cmd, void *data)
}
dprintk(CVP_SESS, "%s: cvp session %#x\n", __func__,
hash32_ptr(inst->session));
inst->sess_id);
signal_session_msg_receipt(cmd, inst);
cvp_put_inst(inst);
@ -568,7 +577,7 @@ static void handle_session_error(enum hal_command_response cmd, void *data)
hdev = inst->core->device;
dprintk(CVP_ERR, "Session error received for inst %pK session %x\n",
inst, hash32_ptr(inst->session));
inst, inst->sess_id);
if (response->status == CVP_ERR_MAX_CLIENTS) {
dprintk(CVP_WARN, "Too many clients, rejecting %pK", inst);
@ -901,7 +910,7 @@ static int msm_comm_session_abort(struct msm_cvp_inst *inst)
abort_completion = SESSION_MSG_INDEX(HAL_SESSION_ABORT_DONE);
dprintk(CVP_WARN, "%s: inst %pK session %x\n", __func__,
inst, hash32_ptr(inst->session));
inst, inst->sess_id);
rc = call_hfi_op(hdev, session_abort, (void *)inst->session);
if (rc) {
dprintk(CVP_ERR,
@ -914,7 +923,7 @@ static int msm_comm_session_abort(struct msm_cvp_inst *inst)
inst->core->resources.msm_cvp_hw_rsp_timeout));
if (!rc) {
dprintk(CVP_ERR, "%s: inst %pK session %x abort timed out\n",
__func__, inst, hash32_ptr(inst->session));
__func__, inst, inst->sess_id);
call_hfi_op(hdev, flush_debug_queue, hdev->hfi_device_data);
dump_hfi_queue(hdev->hfi_device_data);
msm_cvp_comm_generate_sys_error(inst);
@ -1268,7 +1277,7 @@ int msm_cvp_comm_try_state(struct msm_cvp_inst *inst, int state)
}
dprintk(CVP_SESS,
"Trying to move inst: %pK (%#x) from: %#x to %#x\n",
inst, hash32_ptr(inst->session), inst->state, state);
inst, inst->sess_id, inst->state, state);
mutex_lock(&inst->sync_lock);
if (inst->state == MSM_CVP_CORE_INVALID) {
@ -1281,7 +1290,7 @@ int msm_cvp_comm_try_state(struct msm_cvp_inst *inst, int state)
flipped_state = get_flipped_state(inst->state, state);
dprintk(CVP_SESS,
"inst: %pK (%#x) flipped_state = %#x %x\n",
inst, hash32_ptr(inst->session), flipped_state, state);
inst, inst->sess_id, flipped_state, state);
switch (flipped_state) {
case MSM_CVP_CORE_UNINIT_DONE:
case MSM_CVP_CORE_INIT:
@ -1491,7 +1500,7 @@ int msm_cvp_comm_kill_session(struct msm_cvp_inst *inst)
return 0;
}
dprintk(CVP_WARN, "%s: inst %pK, session %x state %d\n", __func__,
inst, hash32_ptr(inst->session), inst->state);
inst, inst->sess_id, inst->state);
/*
* We're internally forcibly killing the session, if fw is aware of
* the session send session_abort to firmware to clean up and release
@ -1503,7 +1512,7 @@ int msm_cvp_comm_kill_session(struct msm_cvp_inst *inst)
if (rc) {
dprintk(CVP_ERR,
"%s: inst %pK session %x abort failed\n",
__func__, inst, hash32_ptr(inst->session));
__func__, inst, inst->sess_id);
change_cvp_inst_state(inst, MSM_CVP_CORE_INVALID);
} else {
change_cvp_inst_state(inst, MSM_CVP_CORE_UNINIT);

View file

@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/dma-direction.h>
@ -165,7 +166,7 @@ void *msm_cvp_open(int core_id, int session_type)
list_for_each_entry(inst, &core->instances, list)
dprintk(CVP_ERR, "inst %pK, cmd %d id %d\n",
inst, inst->cur_cmd_type,
hash32_ptr(inst->session));
inst->sess_id);
mutex_unlock(&core->lock);
return NULL;
@ -369,7 +370,7 @@ int msm_cvp_destroy(struct msm_cvp_inst *inst)
synx_uninitialize(inst->synx_session_id);
pr_info(CVP_DBG_TAG "Closed cvp instance: %pK session_id = %d\n",
"sess", inst, hash32_ptr(inst->session));
"sess", inst, inst->sess_id);
if (inst->cur_cmd_type)
dprintk(CVP_ERR, "deleted instance has pending cmd %d\n",
inst->cur_cmd_type);

View file

@ -1,6 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef _MSM_CVP_INTERNAL_H_
@ -290,6 +291,8 @@ struct msm_cvp_core {
unsigned long curr_freq;
struct cvp_cycle_info dyn_clk;
atomic64_t kernel_trans_id;
struct idr sess_idr;
struct mutex idr_mtx;
};
struct msm_cvp_inst {
@ -301,6 +304,7 @@ struct msm_cvp_inst {
struct cvp_session_queue session_queue_fence;
struct cvp_session_event event_handler;
void *session;
u32 sess_id;
enum instance_state state;
struct msm_cvp_list freqs;
struct msm_cvp_list persistbufs;

View file

@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include "msm_cvp_common.h"
@ -20,7 +21,7 @@ void cvp_dump_fence_queue(struct msm_cvp_inst *inst)
ssid = inst->synx_session_id;
mutex_lock(&q->lock);
dprintk(CVP_WARN, "inst %x fence q mode %d, ssid %d\n",
hash32_ptr(inst->session), q->mode, ssid.client_id);
inst->sess_id, q->mode, ssid.client_id);
dprintk(CVP_WARN, "fence cmdq wait list:\n");
list_for_each_entry(f, &q->wait_list, list) {

View file

@ -808,9 +808,9 @@ static struct usb_function_instance *uvc_alloc_inst(void)
cd->wObjectiveFocalLengthMax = cpu_to_le16(0);
cd->wOcularFocalLength = cpu_to_le16(0);
cd->bControlSize = 3;
cd->bmControls[0] = 2;
cd->bmControls[1] = 0;
cd->bmControls[2] = 0;
cd->bmControls[0] = 62;
cd->bmControls[1] = 126;
cd->bmControls[2] = 10;
pd = &opts->uvc_processing;
pd->bLength = UVC_DT_PROCESSING_UNIT_SIZE(2);
@ -820,8 +820,8 @@ static struct usb_function_instance *uvc_alloc_inst(void)
pd->bSourceID = 1;
pd->wMaxMultiplier = cpu_to_le16(16*1024);
pd->bControlSize = 2;
pd->bmControls[0] = 1;
pd->bmControls[1] = 0;
pd->bmControls[0] = 91;
pd->bmControls[1] = 23;
pd->iProcessing = 0;
pd->bmVideoStandards = 0;

View file

@ -762,16 +762,19 @@ static const struct uvcg_config_group_type uvcg_control_grp_type = {
/* -----------------------------------------------------------------------------
* streaming/uncompressed
* streaming/mjpeg
* streaming/framebased
*/
static const char * const uvcg_format_names[] = {
"uncompressed",
"mjpeg",
"framebased"
};
enum uvcg_format_type {
UVCG_UNCOMPRESSED = 0,
UVCG_MJPEG,
UVCG_FRAMEBASED,
};
struct uvcg_format {
@ -1080,6 +1083,7 @@ struct uvcg_frame {
u32 dw_max_video_frame_buffer_size;
u32 dw_default_frame_interval;
u8 b_frame_interval_type;
u32 dw_bytes_perline;
} __attribute__((packed)) frame;
u32 *dw_frame_interval;
};
@ -1190,6 +1194,7 @@ UVCG_FRAME_ATTR(dw_min_bit_rate, dwMinBitRate, 32);
UVCG_FRAME_ATTR(dw_max_bit_rate, dwMaxBitRate, 32);
UVCG_FRAME_ATTR(dw_max_video_frame_buffer_size, dwMaxVideoFrameBufferSize, 32);
UVCG_FRAME_ATTR(dw_default_frame_interval, dwDefaultFrameInterval, 32);
UVCG_FRAME_ATTR(dw_bytes_perline, dwBytesPerLine, 32);
#undef UVCG_FRAME_ATTR
@ -1324,7 +1329,7 @@ end:
UVC_ATTR(uvcg_frame_, dw_frame_interval, dwFrameInterval);
static struct configfs_attribute *uvcg_frame_attrs[] = {
static struct configfs_attribute *uvcg_frame_attrs1[] = {
&uvcg_frame_attr_b_frame_index,
&uvcg_frame_attr_bm_capabilities,
&uvcg_frame_attr_w_width,
@ -1337,12 +1342,32 @@ static struct configfs_attribute *uvcg_frame_attrs[] = {
NULL,
};
static const struct config_item_type uvcg_frame_type = {
static struct configfs_attribute *uvcg_frame_attrs2[] = {
&uvcg_frame_attr_b_frame_index,
&uvcg_frame_attr_bm_capabilities,
&uvcg_frame_attr_w_width,
&uvcg_frame_attr_w_height,
&uvcg_frame_attr_dw_min_bit_rate,
&uvcg_frame_attr_dw_max_bit_rate,
&uvcg_frame_attr_dw_max_video_frame_buffer_size,
&uvcg_frame_attr_dw_default_frame_interval,
&uvcg_frame_attr_dw_frame_interval,
&uvcg_frame_attr_dw_bytes_perline,
NULL,
};
static const struct config_item_type uvcg_frame_type1 = {
.ct_item_ops = &uvcg_config_item_ops,
.ct_attrs = uvcg_frame_attrs,
.ct_attrs = uvcg_frame_attrs1,
.ct_owner = THIS_MODULE,
};
static const struct config_item_type uvcg_frame_type2 = {
.ct_item_ops = &uvcg_config_item_ops,
.ct_attrs = uvcg_frame_attrs2,
.ct_owner = THIS_MODULE,
};
static struct config_item *uvcg_frame_make(struct config_group *group,
const char *name)
{
@ -1363,6 +1388,7 @@ static struct config_item *uvcg_frame_make(struct config_group *group,
h->frame.dw_max_bit_rate = 55296000;
h->frame.dw_max_video_frame_buffer_size = 460800;
h->frame.dw_default_frame_interval = 666666;
h->frame.dw_bytes_perline = 0;
opts_item = group->cg_item.ci_parent->ci_parent->ci_parent;
opts = to_f_uvc_opts(opts_item);
@ -1375,6 +1401,9 @@ static struct config_item *uvcg_frame_make(struct config_group *group,
} else if (fmt->type == UVCG_MJPEG) {
h->frame.b_descriptor_subtype = UVC_VS_FRAME_MJPEG;
h->fmt_type = UVCG_MJPEG;
} else if (fmt->type == UVCG_FRAMEBASED) {
h->frame.b_descriptor_subtype = UVC_VS_FRAME_FRAME_BASED;
h->fmt_type = UVCG_FRAMEBASED;
} else {
mutex_unlock(&opts->lock);
kfree(h);
@ -1383,7 +1412,10 @@ static struct config_item *uvcg_frame_make(struct config_group *group,
++fmt->num_frames;
mutex_unlock(&opts->lock);
config_item_init_type_name(&h->item, name, &uvcg_frame_type);
if (fmt->type == UVCG_FRAMEBASED)
config_item_init_type_name(&h->item, name, &uvcg_frame_type2);
else
config_item_init_type_name(&h->item, name, &uvcg_frame_type1);
return &h->item;
}
@ -1413,9 +1445,6 @@ static void uvcg_format_set_indices(struct config_group *fmt)
list_for_each_entry(ci, &fmt->cg_children, ci_entry) {
struct uvcg_frame *frm;
if (ci->ci_type != &uvcg_frame_type)
continue;
frm = to_uvcg_frame(ci);
frm->frame.b_frame_index = i++;
}
@ -1856,6 +1885,260 @@ static const struct uvcg_config_group_type uvcg_mjpeg_grp_type = {
.name = "mjpeg",
};
/* -----------------------------------------------------------------------------
* streaming/framebased/<NAME>
*/
struct uvcg_framebased {
struct uvcg_format fmt;
struct uvc_format_framebased desc;
};
static inline struct uvcg_framebased *to_uvcg_framebased(struct config_item *item)
{
return container_of(to_uvcg_format(item), struct uvcg_framebased, fmt);
}
static struct configfs_group_operations uvcg_framebased_group_ops = {
.make_item = uvcg_frame_make,
.drop_item = uvcg_frame_drop,
};
#define UVCG_FRAMEBASED_ATTR_RO(cname, aname, bits) \
static ssize_t uvcg_framebased_##cname##_show(struct config_item *item, \
char *page) \
{ \
struct uvcg_framebased *u = to_uvcg_framebased(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
int result; \
\
mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
\
opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent; \
opts = to_f_uvc_opts(opts_item); \
\
mutex_lock(&opts->lock); \
result = scnprintf(page, PAGE_SIZE, "%u\n", le##bits##_to_cpu(u->desc.aname));\
mutex_unlock(&opts->lock); \
\
mutex_unlock(su_mutex); \
return result; \
} \
\
UVC_ATTR_RO(uvcg_framebased_, cname, aname)
#define UVCG_FRAMEBASED_ATTR(cname, aname, bits) \
static ssize_t uvcg_framebased_##cname##_show(struct config_item *item, \
char *page) \
{ \
struct uvcg_framebased *u = to_uvcg_framebased(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
int result; \
\
mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
\
opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
opts = to_f_uvc_opts(opts_item); \
\
mutex_lock(&opts->lock); \
result = scnprintf(page, PAGE_SIZE, "%u\n", le##bits##_to_cpu(u->desc.aname));\
mutex_unlock(&opts->lock); \
\
mutex_unlock(su_mutex); \
return result; \
} \
\
static ssize_t \
uvcg_framebased_##cname##_store(struct config_item *item, \
const char *page, size_t len) \
{ \
struct uvcg_framebased *u = to_uvcg_framebased(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
int ret; \
u8 num; \
\
mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
\
opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
opts = to_f_uvc_opts(opts_item); \
\
mutex_lock(&opts->lock); \
if (u->fmt.linked || opts->refcnt) { \
ret = -EBUSY; \
goto end; \
} \
\
ret = kstrtou8(page, 0, &num); \
if (ret) \
goto end; \
\
if (num > 255) { \
ret = -EINVAL; \
goto end; \
} \
u->desc.aname = num; \
ret = len; \
end: \
mutex_unlock(&opts->lock); \
mutex_unlock(su_mutex); \
return ret; \
} \
\
UVC_ATTR(uvcg_framebased_, cname, aname)
UVCG_FRAMEBASED_ATTR_RO(b_format_index, bFormatIndex, 8);
UVCG_FRAMEBASED_ATTR_RO(b_bits_per_pixel, bBitsPerPixel, 8);
UVCG_FRAMEBASED_ATTR(b_default_frame_index, bDefaultFrameIndex, 8);
UVCG_FRAMEBASED_ATTR_RO(b_aspect_ratio_x, bAspectRatioX, 8);
UVCG_FRAMEBASED_ATTR_RO(b_aspect_ratio_y, bAspectRatioY, 8);
UVCG_FRAMEBASED_ATTR_RO(bm_interface_flags, bmInterfaceFlags, 8);
#undef UVCG_FRAMEBASED_ATTR
#undef UVCG_FRAMEBASED_ATTR_RO
static ssize_t uvcg_framebased_guid_format_show(struct config_item *item,
char *page)
{
struct uvcg_framebased *ch = to_uvcg_framebased(item);
struct f_uvc_opts *opts;
struct config_item *opts_item;
struct mutex *su_mutex = &ch->fmt.group.cg_subsys->su_mutex;
mutex_lock(su_mutex); /* for navigating configfs hierarchy */
opts_item = ch->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;
opts = to_f_uvc_opts(opts_item);
mutex_lock(&opts->lock);
memcpy(page, ch->desc.guidFormat, sizeof(ch->desc.guidFormat));
mutex_unlock(&opts->lock);
mutex_unlock(su_mutex);
return sizeof(ch->desc.guidFormat);
}
static ssize_t uvcg_framebased_guid_format_store(struct config_item *item,
const char *page, size_t len)
{
struct uvcg_framebased *ch = to_uvcg_framebased(item);
struct f_uvc_opts *opts;
struct config_item *opts_item;
struct mutex *su_mutex = &ch->fmt.group.cg_subsys->su_mutex;
int ret;
mutex_lock(su_mutex); /* for navigating configfs hierarchy */
opts_item = ch->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;
opts = to_f_uvc_opts(opts_item);
mutex_lock(&opts->lock);
if (ch->fmt.linked || opts->refcnt) {
ret = -EBUSY;
goto end;
}
memcpy(ch->desc.guidFormat, page,
min(sizeof(ch->desc.guidFormat), len));
ret = sizeof(ch->desc.guidFormat);
end:
mutex_unlock(&opts->lock);
mutex_unlock(su_mutex);
return ret;
}
UVC_ATTR(uvcg_framebased_, guid_format, guidFormat);
static inline ssize_t
uvcg_framebased_bma_controls_show(struct config_item *item, char *page)
{
struct uvcg_framebased *u = to_uvcg_framebased(item);
return uvcg_format_bma_controls_show(&u->fmt, page);
}
static inline ssize_t
uvcg_framebased_bma_controls_store(struct config_item *item,
const char *page, size_t len)
{
struct uvcg_framebased *u = to_uvcg_framebased(item);
return uvcg_format_bma_controls_store(&u->fmt, page, len);
}
UVC_ATTR(uvcg_framebased_, bma_controls, bmaControls);
static struct configfs_attribute *uvcg_framebased_attrs[] = {
&uvcg_framebased_attr_b_format_index,
&uvcg_framebased_attr_b_default_frame_index,
&uvcg_framebased_attr_b_bits_per_pixel,
&uvcg_framebased_attr_b_aspect_ratio_x,
&uvcg_framebased_attr_b_aspect_ratio_y,
&uvcg_framebased_attr_bm_interface_flags,
&uvcg_framebased_attr_bma_controls,
&uvcg_framebased_attr_guid_format,
NULL,
};
static const struct config_item_type uvcg_framebased_type = {
.ct_item_ops = &uvcg_config_item_ops,
.ct_group_ops = &uvcg_framebased_group_ops,
.ct_attrs = uvcg_framebased_attrs,
.ct_owner = THIS_MODULE,
};
static struct config_group *uvcg_framebased_make(struct config_group *group,
const char *name)
{
static char guid[] = { /*Declear frame based as H264 format*/
'H', '2', '6', '4', 0x00, 0x00, 0x10, 0x00,
0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71
};
struct uvcg_framebased *h;
h = kzalloc(sizeof(*h), GFP_KERNEL);
if (!h)
return ERR_PTR(-ENOMEM);
h->desc.bLength = UVC_DT_FORMAT_FRAMEBASED_SIZE;
h->desc.bDescriptorType = USB_DT_CS_INTERFACE;
h->desc.bDescriptorSubType = UVC_VS_FORMAT_FRAME_BASED;
memcpy(h->desc.guidFormat, guid, sizeof(guid));
h->desc.bBitsPerPixel = 0;
h->desc.bDefaultFrameIndex = 1;
h->desc.bAspectRatioX = 0;
h->desc.bAspectRatioY = 0;
h->desc.bmInterfaceFlags = 0;
h->desc.bCopyProtect = 0;
h->desc.bVariableSize = 1;
h->fmt.type = UVCG_FRAMEBASED;
config_group_init_type_name(&h->fmt.group, name,
&uvcg_framebased_type);
return &h->fmt.group;
}
static struct configfs_group_operations uvcg_framebased_grp_ops = {
.make_group = uvcg_framebased_make,
};
static const struct uvcg_config_group_type uvcg_framebased_grp_type = {
.type = {
.ct_item_ops = &uvcg_config_item_ops,
.ct_group_ops = &uvcg_framebased_grp_ops,
.ct_owner = THIS_MODULE,
},
.name = "framebased",
};
/* -----------------------------------------------------------------------------
* streaming/color_matching/default
*/
@ -2001,6 +2284,7 @@ static int __uvcg_iter_strm_cls(struct uvcg_streaming_header *h,
if (ret)
return ret;
grp = &f->fmt->group;
j = 0;
list_for_each_entry(item, &grp->cg_children, ci_entry) {
frm = to_uvcg_frame(item);
ret = fun(frm, priv2, priv3, j++, UVCG_FRAME);
@ -2049,6 +2333,11 @@ static int __uvcg_cnt_strm(void *priv1, void *priv2, void *priv3, int n,
container_of(fmt, struct uvcg_mjpeg, fmt);
*size += sizeof(m->desc);
} else if (fmt->type == UVCG_FRAMEBASED) {
struct uvcg_framebased *f =
container_of(fmt, struct uvcg_framebased, fmt);
*size += sizeof(f->desc);
} else {
return -EINVAL;
}
@ -2059,6 +2348,11 @@ static int __uvcg_cnt_strm(void *priv1, void *priv2, void *priv3, int n,
int sz = sizeof(frm->dw_frame_interval);
*size += sizeof(frm->frame);
/*
* framebased has duplicate member with uncompressed and
* mjpeg, so minus it
*/
*size -= sizeof(u32);
*size += frm->frame.b_frame_interval_type * sz;
}
break;
@ -2069,6 +2363,27 @@ static int __uvcg_cnt_strm(void *priv1, void *priv2, void *priv3, int n,
return 0;
}
static int __uvcg_copy_framebased_desc(void *dest, struct uvcg_frame *frm,
int sz)
{
struct uvc_frame_framebased *desc = dest;
desc->bLength = frm->frame.b_length;
desc->bDescriptorType = frm->frame.b_descriptor_type;
desc->bDescriptorSubType = frm->frame.b_descriptor_subtype;
desc->bFrameIndex = frm->frame.b_frame_index;
desc->bmCapabilities = frm->frame.bm_capabilities;
desc->wWidth = frm->frame.w_width;
desc->wHeight = frm->frame.w_height;
desc->dwMinBitRate = frm->frame.dw_min_bit_rate;
desc->dwMaxBitRate = frm->frame.dw_max_bit_rate;
desc->dwDefaultFrameInterval = frm->frame.dw_default_frame_interval;
desc->bFrameIntervalType = frm->frame.b_frame_interval_type;
desc->dwBytesPerLine = frm->frame.dw_bytes_perline;
return 0;
}
/*
* Fill an array of streaming descriptors.
*
@ -2123,6 +2438,15 @@ static int __uvcg_fill_strm(void *priv1, void *priv2, void *priv3, int n,
m->desc.bNumFrameDescriptors = fmt->num_frames;
memcpy(*dest, &m->desc, sizeof(m->desc));
*dest += sizeof(m->desc);
} else if (fmt->type == UVCG_FRAMEBASED) {
struct uvcg_framebased *f =
container_of(fmt, struct uvcg_framebased,
fmt);
f->desc.bFormatIndex = n + 1;
f->desc.bNumFrameDescriptors = fmt->num_frames;
memcpy(*dest, &f->desc, sizeof(f->desc));
*dest += sizeof(f->desc);
} else {
return -EINVAL;
}
@ -2132,8 +2456,11 @@ static int __uvcg_fill_strm(void *priv1, void *priv2, void *priv3, int n,
struct uvcg_frame *frm = priv1;
struct uvc_descriptor_header *h = *dest;
sz = sizeof(frm->frame);
memcpy(*dest, &frm->frame, sz);
sz = sizeof(frm->frame) - 4;
if (frm->fmt_type != UVCG_FRAMEBASED)
memcpy(*dest, &frm->frame, sz);
else
__uvcg_copy_framebased_desc(*dest, frm, sz);
*dest += sz;
sz = frm->frame.b_frame_interval_type *
sizeof(*frm->dw_frame_interval);
@ -2145,6 +2472,9 @@ static int __uvcg_fill_strm(void *priv1, void *priv2, void *priv3, int n,
else if (frm->fmt_type == UVCG_MJPEG)
h->bLength = UVC_DT_FRAME_MJPEG_SIZE(
frm->frame.b_frame_interval_type);
else if (frm->fmt_type == UVCG_FRAMEBASED)
h->bLength = UVC_DT_FRAME_FRAMEBASED_SIZE(
frm->frame.b_frame_interval_type);
}
break;
}
@ -2357,6 +2687,7 @@ static const struct uvcg_config_group_type uvcg_streaming_grp_type = {
&uvcg_streaming_header_grp_type,
&uvcg_uncompressed_grp_type,
&uvcg_mjpeg_grp_type,
&uvcg_framebased_grp_type,
&uvcg_color_matching_grp_type,
&uvcg_streaming_class_grp_type,
NULL,

View file

@ -58,6 +58,7 @@ struct uvc_format {
static struct uvc_format uvc_formats[] = {
{ 16, V4L2_PIX_FMT_YUYV },
{ 0, V4L2_PIX_FMT_MJPEG },
{ 0, V4L2_PIX_FMT_H264 },
{ 12, V4L2_PIX_FMT_YUV420 },
{ 8, V4L2_PIX_FMT_GREY },
};

View file

@ -162,5 +162,9 @@ extern br_notify_hook_t __rcu *br_notify_hook;
typedef int (br_multicast_handle_hook_t)(const struct net_bridge_port *src,
struct sk_buff *skb);
extern br_multicast_handle_hook_t __rcu *br_multicast_handle_hook;
typedef struct net_bridge_port *br_get_dst_hook_t(
const struct net_bridge_port *src,
struct sk_buff **skb);
extern br_get_dst_hook_t __rcu *br_get_dst_hook;
#endif
#endif

View file

@ -2554,6 +2554,8 @@ enum netdev_cmd {
NETDEV_CVLAN_FILTER_DROP_INFO,
NETDEV_SVLAN_FILTER_PUSH_INFO,
NETDEV_SVLAN_FILTER_DROP_INFO,
NETDEV_BR_JOIN,
NETDEV_BR_LEAVE,
};
const char *netdev_cmd_to_name(enum netdev_cmd cmd);

View file

@ -597,5 +597,63 @@ struct UVC_FRAME_MJPEG(n) { \
__le32 dwFrameInterval[n]; \
} __attribute__ ((packed))
/* Frame Based Payload - 3.1.1. Frame Based Video Format Descriptor */
struct uvc_format_framebased {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubType;
__u8 bFormatIndex;
__u8 bNumFrameDescriptors;
__u8 guidFormat[16];
__u8 bBitsPerPixel;
__u8 bDefaultFrameIndex;
__u8 bAspectRatioX;
__u8 bAspectRatioY;
__u8 bmInterfaceFlags;
__u8 bCopyProtect;
__u8 bVariableSize;
} __attribute__((__packed__));
#define UVC_DT_FORMAT_FRAMEBASED_SIZE 28
/* Frame Based Payload - 3.1.2. Frame Based Video Frame Descriptor */
struct uvc_frame_framebased {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubType;
__u8 bFrameIndex;
__u8 bmCapabilities;
__u16 wWidth;
__u16 wHeight;
__u32 dwMinBitRate;
__u32 dwMaxBitRate;
__u32 dwDefaultFrameInterval;
__u8 bFrameIntervalType;
__u32 dwBytesPerLine;
__u32 dwFrameInterval[];
} __attribute__((__packed__));
#define UVC_DT_FRAME_FRAMEBASED_SIZE(n) (26+4*(n))
#define UVC_FRAME_FRAMEBASED(n) \
uvc_frame_framebased_##n
#define DECLARE_UVC_FRAME_FRAMEBASED(n) \
struct UVC_FRAME_FRAMEBASED(n) { \
__u8 bLength; \
__u8 bDescriptorType; \
__u8 bDescriptorSubType; \
__u8 bFrameIndex; \
__u8 bmCapabilities; \
__u16 wWidth; \
__u16 wHeight; \
__u32 dwMinBitRate; \
__u32 dwMaxBitRate; \
__u32 dwDefaultFrameInterval; \
__u8 bFrameIntervalType; \
__u32 dwBytesPerLine; \
__u32 dwFrameInterval[n]; \
} __attribute__ ((packed))
#endif /* __LINUX_USB_VIDEO_H */

View file

@ -34,6 +34,10 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
const struct nf_br_ops *nf_ops;
const unsigned char *dest;
u16 vid = 0;
#ifdef CONFIG_HYFI_BRIDGE_HOOKS
struct net_bridge_port *pdst;
br_get_dst_hook_t *get_dst_hook;
#endif
if (unlikely(!pskb_may_pull(skb, ETH_HLEN))) {
kfree_skb(skb);
@ -82,6 +86,10 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
br_do_suppress_nd(skb, br, vid, NULL, msg);
}
#ifdef CONFIG_HYFI_BRIDGE_HOOKS
get_dst_hook = rcu_dereference(br_get_dst_hook);
#endif
dest = eth_hdr(skb)->h_dest;
if (is_broadcast_ether_addr(dest)) {
br_flood(br, skb, BR_PKT_BROADCAST, false, true);
@ -107,11 +115,24 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
br_multicast_flood(mdst, skb, false, true);
else
br_flood(br, skb, BR_PKT_MULTICAST, false, true);
} else if ((dst = br_fdb_find_rcu(br, dest, vid)) != NULL) {
br_forward(dst->dst, skb, false, true);
} else {
br_flood(br, skb, BR_PKT_UNICAST, false, true);
#ifdef CONFIG_HYFI_BRIDGE_HOOKS
pdst = __br_get(get_dst_hook, NULL, NULL, &skb);
if (pdst) {
if (!skb)
goto out;
br_forward(pdst, skb, false, true);
} else
#endif
{
dst = br_fdb_find_rcu(br, dest, vid);
if (dst)
br_forward(dst->dst, skb, false, true);
else
br_flood(br, skb, BR_PKT_UNICAST, false, true);
}
}
out:
rcu_read_unlock();
return NETDEV_TX_OK;

View file

@ -695,6 +695,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev,
br_set_gso_limits(br);
kobject_uevent(&p->kobj, KOBJ_ADD);
call_netdevice_notifiers(NETDEV_BR_JOIN, dev);
return 0;
@ -732,6 +733,8 @@ int br_del_if(struct net_bridge *br, struct net_device *dev)
if (!p || p->br != br)
return -EINVAL;
call_netdevice_notifiers(NETDEV_BR_LEAVE, dev);
/* Since more than one interface can be attached to a bridge,
* there still maybe an alternate path for netconsole to use;
* therefore there is no reason for a NETDEV_RELEASE event.

View file

@ -33,6 +33,11 @@ br_netif_receive_skb(struct net *net, struct sock *sk, struct sk_buff *skb)
/* Hook for external Multicast handler */
br_multicast_handle_hook_t __rcu *br_multicast_handle_hook __read_mostly;
EXPORT_SYMBOL(br_multicast_handle_hook);
/* Hook for external forwarding logic */
br_get_dst_hook_t __rcu *br_get_dst_hook __read_mostly;
EXPORT_SYMBOL_GPL(br_get_dst_hook);
#endif
int br_pass_frame_up(struct sk_buff *skb)
@ -94,6 +99,8 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
struct net_bridge *br;
#ifdef CONFIG_HYFI_BRIDGE_HOOKS
br_multicast_handle_hook_t *multicast_handle_hook;
struct net_bridge_port *pdst = NULL;
br_get_dst_hook_t *get_dst_hook = rcu_dereference(br_get_dst_hook);
#endif
u16 vid = 0;
@ -168,7 +175,17 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
}
break;
case BR_PKT_UNICAST:
dst = br_fdb_find_rcu(br, eth_hdr(skb)->h_dest, vid);
#ifdef CONFIG_HYFI_BRIDGE_HOOKS
pdst = __br_get(get_dst_hook, NULL, p, &skb);
if (pdst) {
if (!skb)
goto out;
} else
#endif
{
dst = br_fdb_find_rcu(br, eth_hdr(skb)->h_dest, vid);
}
break;
default:
break;
}

View file

@ -195,6 +195,9 @@ struct net_bridge_fdb_entry {
struct net_bridge_fdb_key key;
struct hlist_node fdb_node;
unsigned char is_local:1,
is_static:1;
unsigned long flags;
unsigned char offloaded:1;

View file

@ -1521,7 +1521,7 @@ const char *netdev_cmd_to_name(enum netdev_cmd cmd)
N(UDP_TUNNEL_DROP_INFO) N(CHANGE_TX_QUEUE_LEN)
N(CVLAN_FILTER_PUSH_INFO) N(CVLAN_FILTER_DROP_INFO)
N(SVLAN_FILTER_PUSH_INFO) N(SVLAN_FILTER_DROP_INFO)
N(PRE_CHANGEADDR)
N(PRE_CHANGEADDR) N(BR_JOIN) N(BR_LEAVE)
}
#undef N
return "UNKNOWN_NETDEV_EVENT";