mirror of
https://github.com/torvalds/linux.git
synced 2026-05-31 18:43:33 +02:00
Merge branch 'net-enetc-fix-command-bd-ring-issues'
Wei Fang says: ==================== net: enetc: fix command BD ring issues Currently, the implementation of command BD ring has two issues, one is that the driver may obtain wrong consumer index of the ring, because the driver does not mask out the SBE bit of the CIR value, so a wrong index will be obtained when a SBE error ouccrs. The other one is that the DMA buffer may be used after free. If netc_xmit_ntmp_cmd() times out and returns an error, the pending command is not explicitly aborted, while ntmp_free_data_mem() unconditionally frees the DMA buffer. If the buffer has already been reallocated elsewhere, this may lead to silent memory corruption. Because the hardware eventually processes the pending command and perform a DMA write of the response to the physical address of the freed buffer. So this patch set is to fix these two issues. ==================== Link: https://patch.msgid.link/20260415060833.2303846-1-wei.fang@nxp.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
d2dced26bc
|
|
@ -7,6 +7,7 @@
|
|||
#include <linux/dma-mapping.h>
|
||||
#include <linux/fsl/netc_global.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/vmalloc.h>
|
||||
|
||||
#include "ntmp_private.h"
|
||||
|
||||
|
|
@ -42,6 +43,12 @@ int ntmp_init_cbdr(struct netc_cbdr *cbdr, struct device *dev,
|
|||
if (!cbdr->addr_base)
|
||||
return -ENOMEM;
|
||||
|
||||
cbdr->swcbd = vcalloc(cbd_num, sizeof(struct netc_swcbd));
|
||||
if (!cbdr->swcbd) {
|
||||
dma_free_coherent(dev, size, cbdr->addr_base, cbdr->dma_base);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
cbdr->dma_size = size;
|
||||
cbdr->bd_num = cbd_num;
|
||||
cbdr->regs = *regs;
|
||||
|
|
@ -52,10 +59,10 @@ int ntmp_init_cbdr(struct netc_cbdr *cbdr, struct device *dev,
|
|||
cbdr->addr_base_align = PTR_ALIGN(cbdr->addr_base,
|
||||
NTMP_BASE_ADDR_ALIGN);
|
||||
|
||||
spin_lock_init(&cbdr->ring_lock);
|
||||
mutex_init(&cbdr->ring_lock);
|
||||
|
||||
cbdr->next_to_use = netc_read(cbdr->regs.pir);
|
||||
cbdr->next_to_clean = netc_read(cbdr->regs.cir);
|
||||
cbdr->next_to_clean = netc_read(cbdr->regs.cir) & NETC_CBDRCIR_INDEX;
|
||||
|
||||
/* Step 1: Configure the base address of the Control BD Ring */
|
||||
netc_write(cbdr->regs.bar0, lower_32_bits(cbdr->dma_base_align));
|
||||
|
|
@ -71,10 +78,24 @@ int ntmp_init_cbdr(struct netc_cbdr *cbdr, struct device *dev,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(ntmp_init_cbdr);
|
||||
|
||||
static void ntmp_free_data_mem(struct device *dev, struct netc_swcbd *swcbd)
|
||||
{
|
||||
if (unlikely(!swcbd->buf))
|
||||
return;
|
||||
|
||||
dma_free_coherent(dev, swcbd->size + NTMP_DATA_ADDR_ALIGN,
|
||||
swcbd->buf, swcbd->dma);
|
||||
}
|
||||
|
||||
void ntmp_free_cbdr(struct netc_cbdr *cbdr)
|
||||
{
|
||||
/* Disable the Control BD Ring */
|
||||
netc_write(cbdr->regs.mr, 0);
|
||||
|
||||
for (int i = 0; i < cbdr->bd_num; i++)
|
||||
ntmp_free_data_mem(cbdr->dev, &cbdr->swcbd[i]);
|
||||
|
||||
vfree(cbdr->swcbd);
|
||||
dma_free_coherent(cbdr->dev, cbdr->dma_size, cbdr->addr_base,
|
||||
cbdr->dma_base);
|
||||
memset(cbdr, 0, sizeof(*cbdr));
|
||||
|
|
@ -94,40 +115,59 @@ static union netc_cbd *ntmp_get_cbd(struct netc_cbdr *cbdr, int index)
|
|||
|
||||
static void ntmp_clean_cbdr(struct netc_cbdr *cbdr)
|
||||
{
|
||||
union netc_cbd *cbd;
|
||||
int i;
|
||||
int i = cbdr->next_to_clean;
|
||||
|
||||
i = cbdr->next_to_clean;
|
||||
while (netc_read(cbdr->regs.cir) != i) {
|
||||
cbd = ntmp_get_cbd(cbdr, i);
|
||||
while ((netc_read(cbdr->regs.cir) & NETC_CBDRCIR_INDEX) != i) {
|
||||
union netc_cbd *cbd = ntmp_get_cbd(cbdr, i);
|
||||
struct netc_swcbd *swcbd = &cbdr->swcbd[i];
|
||||
|
||||
ntmp_free_data_mem(cbdr->dev, swcbd);
|
||||
memset(swcbd, 0, sizeof(*swcbd));
|
||||
memset(cbd, 0, sizeof(*cbd));
|
||||
i = (i + 1) % cbdr->bd_num;
|
||||
}
|
||||
|
||||
dma_wmb();
|
||||
cbdr->next_to_clean = i;
|
||||
}
|
||||
|
||||
static int netc_xmit_ntmp_cmd(struct ntmp_user *user, union netc_cbd *cbd)
|
||||
static void ntmp_select_and_lock_cbdr(struct ntmp_user *user,
|
||||
struct netc_cbdr **cbdr)
|
||||
{
|
||||
/* Currently only ENETC is supported, and it has only one command
|
||||
* BD ring.
|
||||
*/
|
||||
*cbdr = &user->ring[0];
|
||||
|
||||
mutex_lock(&(*cbdr)->ring_lock);
|
||||
}
|
||||
|
||||
static void ntmp_unlock_cbdr(struct netc_cbdr *cbdr)
|
||||
{
|
||||
mutex_unlock(&cbdr->ring_lock);
|
||||
}
|
||||
|
||||
static int netc_xmit_ntmp_cmd(struct netc_cbdr *cbdr, union netc_cbd *cbd,
|
||||
struct netc_swcbd *swcbd)
|
||||
{
|
||||
union netc_cbd *cur_cbd;
|
||||
struct netc_cbdr *cbdr;
|
||||
int i, err;
|
||||
int i, err, used_bds;
|
||||
u16 status;
|
||||
u32 val;
|
||||
|
||||
/* Currently only i.MX95 ENETC is supported, and it only has one
|
||||
* command BD ring
|
||||
*/
|
||||
cbdr = &user->ring[0];
|
||||
|
||||
spin_lock_bh(&cbdr->ring_lock);
|
||||
|
||||
if (unlikely(!ntmp_get_free_cbd_num(cbdr)))
|
||||
used_bds = cbdr->bd_num - ntmp_get_free_cbd_num(cbdr);
|
||||
if (unlikely(used_bds >= NETC_CBDR_CLEAN_WORK)) {
|
||||
ntmp_clean_cbdr(cbdr);
|
||||
if (unlikely(!ntmp_get_free_cbd_num(cbdr))) {
|
||||
ntmp_free_data_mem(cbdr->dev, swcbd);
|
||||
return -EBUSY;
|
||||
}
|
||||
}
|
||||
|
||||
i = cbdr->next_to_use;
|
||||
cur_cbd = ntmp_get_cbd(cbdr, i);
|
||||
*cur_cbd = *cbd;
|
||||
cbdr->swcbd[i] = *swcbd;
|
||||
dma_wmb();
|
||||
|
||||
/* Update producer index of both software and hardware */
|
||||
|
|
@ -135,11 +175,17 @@ static int netc_xmit_ntmp_cmd(struct ntmp_user *user, union netc_cbd *cbd)
|
|||
cbdr->next_to_use = i;
|
||||
netc_write(cbdr->regs.pir, i);
|
||||
|
||||
err = read_poll_timeout_atomic(netc_read, val, val == i,
|
||||
NETC_CBDR_DELAY_US, NETC_CBDR_TIMEOUT,
|
||||
true, cbdr->regs.cir);
|
||||
err = read_poll_timeout(netc_read, val,
|
||||
(val & NETC_CBDRCIR_INDEX) == i,
|
||||
NETC_CBDR_DELAY_US, NETC_CBDR_TIMEOUT,
|
||||
true, cbdr->regs.cir);
|
||||
if (unlikely(err))
|
||||
goto cbdr_unlock;
|
||||
return err;
|
||||
|
||||
if (unlikely(val & NETC_CBDRCIR_SBE)) {
|
||||
dev_err(cbdr->dev, "Command BD system bus error\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
dma_rmb();
|
||||
/* Get the writeback command BD, because the caller may need
|
||||
|
|
@ -150,38 +196,27 @@ static int netc_xmit_ntmp_cmd(struct ntmp_user *user, union netc_cbd *cbd)
|
|||
/* Check the writeback error status */
|
||||
status = le16_to_cpu(cbd->resp_hdr.error_rr) & NTMP_RESP_ERROR;
|
||||
if (unlikely(status)) {
|
||||
err = -EIO;
|
||||
dev_err(user->dev, "Command BD error: 0x%04x\n", status);
|
||||
dev_err(cbdr->dev, "Command BD error: 0x%04x\n", status);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
ntmp_clean_cbdr(cbdr);
|
||||
dma_wmb();
|
||||
|
||||
cbdr_unlock:
|
||||
spin_unlock_bh(&cbdr->ring_lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ntmp_alloc_data_mem(struct ntmp_dma_buf *data, void **buf_align)
|
||||
{
|
||||
void *buf;
|
||||
|
||||
buf = dma_alloc_coherent(data->dev, data->size + NTMP_DATA_ADDR_ALIGN,
|
||||
&data->dma, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
data->buf = buf;
|
||||
*buf_align = PTR_ALIGN(buf, NTMP_DATA_ADDR_ALIGN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ntmp_free_data_mem(struct ntmp_dma_buf *data)
|
||||
static int ntmp_alloc_data_mem(struct device *dev, struct netc_swcbd *swcbd,
|
||||
void **buf_align)
|
||||
{
|
||||
dma_free_coherent(data->dev, data->size + NTMP_DATA_ADDR_ALIGN,
|
||||
data->buf, data->dma);
|
||||
void *buf;
|
||||
|
||||
buf = dma_alloc_coherent(dev, swcbd->size + NTMP_DATA_ADDR_ALIGN,
|
||||
&swcbd->dma, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
swcbd->buf = buf;
|
||||
*buf_align = PTR_ALIGN(buf, NTMP_DATA_ADDR_ALIGN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ntmp_fill_request_hdr(union netc_cbd *cbd, dma_addr_t dma,
|
||||
|
|
@ -234,37 +269,39 @@ static int ntmp_delete_entry_by_id(struct ntmp_user *user, int tbl_id,
|
|||
u8 tbl_ver, u32 entry_id, u32 req_len,
|
||||
u32 resp_len)
|
||||
{
|
||||
struct ntmp_dma_buf data = {
|
||||
.dev = user->dev,
|
||||
struct netc_swcbd swcbd = {
|
||||
.size = max(req_len, resp_len),
|
||||
};
|
||||
struct ntmp_req_by_eid *req;
|
||||
struct netc_cbdr *cbdr;
|
||||
union netc_cbd cbd;
|
||||
int err;
|
||||
|
||||
err = ntmp_alloc_data_mem(&data, (void **)&req);
|
||||
err = ntmp_alloc_data_mem(user->dev, &swcbd, (void **)&req);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
ntmp_fill_crd_eid(req, tbl_ver, 0, 0, entry_id);
|
||||
ntmp_fill_request_hdr(&cbd, data.dma, NTMP_LEN(req_len, resp_len),
|
||||
ntmp_fill_request_hdr(&cbd, swcbd.dma, NTMP_LEN(req_len, resp_len),
|
||||
tbl_id, NTMP_CMD_DELETE, NTMP_AM_ENTRY_ID);
|
||||
|
||||
err = netc_xmit_ntmp_cmd(user, &cbd);
|
||||
ntmp_select_and_lock_cbdr(user, &cbdr);
|
||||
err = netc_xmit_ntmp_cmd(cbdr, &cbd, &swcbd);
|
||||
if (err)
|
||||
dev_err(user->dev,
|
||||
"Failed to delete entry 0x%x of %s, err: %pe",
|
||||
entry_id, ntmp_table_name(tbl_id), ERR_PTR(err));
|
||||
|
||||
ntmp_free_data_mem(&data);
|
||||
ntmp_unlock_cbdr(cbdr);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ntmp_query_entry_by_id(struct ntmp_user *user, int tbl_id,
|
||||
u32 len, struct ntmp_req_by_eid *req,
|
||||
dma_addr_t dma, bool compare_eid)
|
||||
static int ntmp_query_entry_by_id(struct netc_cbdr *cbdr, int tbl_id,
|
||||
struct ntmp_req_by_eid *req,
|
||||
struct netc_swcbd *swcbd,
|
||||
bool compare_eid)
|
||||
{
|
||||
u32 len = NTMP_LEN(sizeof(*req), swcbd->size);
|
||||
struct ntmp_cmn_resp_query *resp;
|
||||
int cmd = NTMP_CMD_QUERY;
|
||||
union netc_cbd cbd;
|
||||
|
|
@ -276,10 +313,11 @@ static int ntmp_query_entry_by_id(struct ntmp_user *user, int tbl_id,
|
|||
cmd = NTMP_CMD_QU;
|
||||
|
||||
/* Request header */
|
||||
ntmp_fill_request_hdr(&cbd, dma, len, tbl_id, cmd, NTMP_AM_ENTRY_ID);
|
||||
err = netc_xmit_ntmp_cmd(user, &cbd);
|
||||
ntmp_fill_request_hdr(&cbd, swcbd->dma, len, tbl_id, cmd,
|
||||
NTMP_AM_ENTRY_ID);
|
||||
err = netc_xmit_ntmp_cmd(cbdr, &cbd, swcbd);
|
||||
if (err) {
|
||||
dev_err(user->dev,
|
||||
dev_err(cbdr->dev,
|
||||
"Failed to query entry 0x%x of %s, err: %pe\n",
|
||||
entry_id, ntmp_table_name(tbl_id), ERR_PTR(err));
|
||||
return err;
|
||||
|
|
@ -293,7 +331,7 @@ static int ntmp_query_entry_by_id(struct ntmp_user *user, int tbl_id,
|
|||
|
||||
resp = (struct ntmp_cmn_resp_query *)req;
|
||||
if (unlikely(le32_to_cpu(resp->entry_id) != entry_id)) {
|
||||
dev_err(user->dev,
|
||||
dev_err(cbdr->dev,
|
||||
"%s: query EID 0x%x doesn't match response EID 0x%x\n",
|
||||
ntmp_table_name(tbl_id), entry_id, le32_to_cpu(resp->entry_id));
|
||||
return -EIO;
|
||||
|
|
@ -305,15 +343,15 @@ static int ntmp_query_entry_by_id(struct ntmp_user *user, int tbl_id,
|
|||
int ntmp_maft_add_entry(struct ntmp_user *user, u32 entry_id,
|
||||
struct maft_entry_data *maft)
|
||||
{
|
||||
struct ntmp_dma_buf data = {
|
||||
.dev = user->dev,
|
||||
struct netc_swcbd swcbd = {
|
||||
.size = sizeof(struct maft_req_add),
|
||||
};
|
||||
struct maft_req_add *req;
|
||||
struct netc_cbdr *cbdr;
|
||||
union netc_cbd cbd;
|
||||
int err;
|
||||
|
||||
err = ntmp_alloc_data_mem(&data, (void **)&req);
|
||||
err = ntmp_alloc_data_mem(user->dev, &swcbd, (void **)&req);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
|
@ -322,14 +360,15 @@ int ntmp_maft_add_entry(struct ntmp_user *user, u32 entry_id,
|
|||
req->keye = maft->keye;
|
||||
req->cfge = maft->cfge;
|
||||
|
||||
ntmp_fill_request_hdr(&cbd, data.dma, NTMP_LEN(data.size, 0),
|
||||
ntmp_fill_request_hdr(&cbd, swcbd.dma, NTMP_LEN(swcbd.size, 0),
|
||||
NTMP_MAFT_ID, NTMP_CMD_ADD, NTMP_AM_ENTRY_ID);
|
||||
err = netc_xmit_ntmp_cmd(user, &cbd);
|
||||
|
||||
ntmp_select_and_lock_cbdr(user, &cbdr);
|
||||
err = netc_xmit_ntmp_cmd(cbdr, &cbd, &swcbd);
|
||||
if (err)
|
||||
dev_err(user->dev, "Failed to add MAFT entry 0x%x, err: %pe\n",
|
||||
entry_id, ERR_PTR(err));
|
||||
|
||||
ntmp_free_data_mem(&data);
|
||||
ntmp_unlock_cbdr(cbdr);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
@ -338,31 +377,31 @@ EXPORT_SYMBOL_GPL(ntmp_maft_add_entry);
|
|||
int ntmp_maft_query_entry(struct ntmp_user *user, u32 entry_id,
|
||||
struct maft_entry_data *maft)
|
||||
{
|
||||
struct ntmp_dma_buf data = {
|
||||
.dev = user->dev,
|
||||
struct netc_swcbd swcbd = {
|
||||
.size = sizeof(struct maft_resp_query),
|
||||
};
|
||||
struct maft_resp_query *resp;
|
||||
struct ntmp_req_by_eid *req;
|
||||
struct netc_cbdr *cbdr;
|
||||
int err;
|
||||
|
||||
err = ntmp_alloc_data_mem(&data, (void **)&req);
|
||||
err = ntmp_alloc_data_mem(user->dev, &swcbd, (void **)&req);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
ntmp_fill_crd_eid(req, user->tbl.maft_ver, 0, 0, entry_id);
|
||||
err = ntmp_query_entry_by_id(user, NTMP_MAFT_ID,
|
||||
NTMP_LEN(sizeof(*req), data.size),
|
||||
req, data.dma, true);
|
||||
|
||||
ntmp_select_and_lock_cbdr(user, &cbdr);
|
||||
err = ntmp_query_entry_by_id(cbdr, NTMP_MAFT_ID, req, &swcbd, true);
|
||||
if (err)
|
||||
goto end;
|
||||
goto unlock_cbdr;
|
||||
|
||||
resp = (struct maft_resp_query *)req;
|
||||
maft->keye = resp->keye;
|
||||
maft->cfge = resp->cfge;
|
||||
|
||||
end:
|
||||
ntmp_free_data_mem(&data);
|
||||
unlock_cbdr:
|
||||
ntmp_unlock_cbdr(cbdr);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
@ -378,8 +417,9 @@ EXPORT_SYMBOL_GPL(ntmp_maft_delete_entry);
|
|||
int ntmp_rsst_update_entry(struct ntmp_user *user, const u32 *table,
|
||||
int count)
|
||||
{
|
||||
struct ntmp_dma_buf data = {.dev = user->dev};
|
||||
struct rsst_req_update *req;
|
||||
struct netc_swcbd swcbd;
|
||||
struct netc_cbdr *cbdr;
|
||||
union netc_cbd cbd;
|
||||
int err, i;
|
||||
|
||||
|
|
@ -387,8 +427,8 @@ int ntmp_rsst_update_entry(struct ntmp_user *user, const u32 *table,
|
|||
/* HW only takes in a full 64 entry table */
|
||||
return -EINVAL;
|
||||
|
||||
data.size = struct_size(req, groups, count);
|
||||
err = ntmp_alloc_data_mem(&data, (void **)&req);
|
||||
swcbd.size = struct_size(req, groups, count);
|
||||
err = ntmp_alloc_data_mem(user->dev, &swcbd, (void **)&req);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
|
@ -398,15 +438,15 @@ int ntmp_rsst_update_entry(struct ntmp_user *user, const u32 *table,
|
|||
for (i = 0; i < count; i++)
|
||||
req->groups[i] = (u8)(table[i]);
|
||||
|
||||
ntmp_fill_request_hdr(&cbd, data.dma, NTMP_LEN(data.size, 0),
|
||||
ntmp_fill_request_hdr(&cbd, swcbd.dma, NTMP_LEN(swcbd.size, 0),
|
||||
NTMP_RSST_ID, NTMP_CMD_UPDATE, NTMP_AM_ENTRY_ID);
|
||||
|
||||
err = netc_xmit_ntmp_cmd(user, &cbd);
|
||||
ntmp_select_and_lock_cbdr(user, &cbdr);
|
||||
err = netc_xmit_ntmp_cmd(cbdr, &cbd, &swcbd);
|
||||
if (err)
|
||||
dev_err(user->dev, "Failed to update RSST entry, err: %pe\n",
|
||||
ERR_PTR(err));
|
||||
|
||||
ntmp_free_data_mem(&data);
|
||||
ntmp_unlock_cbdr(cbdr);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
@ -414,8 +454,9 @@ EXPORT_SYMBOL_GPL(ntmp_rsst_update_entry);
|
|||
|
||||
int ntmp_rsst_query_entry(struct ntmp_user *user, u32 *table, int count)
|
||||
{
|
||||
struct ntmp_dma_buf data = {.dev = user->dev};
|
||||
struct ntmp_req_by_eid *req;
|
||||
struct netc_swcbd swcbd;
|
||||
struct netc_cbdr *cbdr;
|
||||
union netc_cbd cbd;
|
||||
int err, i;
|
||||
u8 *group;
|
||||
|
|
@ -424,21 +465,23 @@ int ntmp_rsst_query_entry(struct ntmp_user *user, u32 *table, int count)
|
|||
/* HW only takes in a full 64 entry table */
|
||||
return -EINVAL;
|
||||
|
||||
data.size = NTMP_ENTRY_ID_SIZE + RSST_STSE_DATA_SIZE(count) +
|
||||
RSST_CFGE_DATA_SIZE(count);
|
||||
err = ntmp_alloc_data_mem(&data, (void **)&req);
|
||||
swcbd.size = NTMP_ENTRY_ID_SIZE + RSST_STSE_DATA_SIZE(count) +
|
||||
RSST_CFGE_DATA_SIZE(count);
|
||||
err = ntmp_alloc_data_mem(user->dev, &swcbd, (void **)&req);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Set the request data buffer */
|
||||
ntmp_fill_crd_eid(req, user->tbl.rsst_ver, 0, 0, 0);
|
||||
ntmp_fill_request_hdr(&cbd, data.dma, NTMP_LEN(sizeof(*req), data.size),
|
||||
ntmp_fill_request_hdr(&cbd, swcbd.dma, NTMP_LEN(sizeof(*req), swcbd.size),
|
||||
NTMP_RSST_ID, NTMP_CMD_QUERY, NTMP_AM_ENTRY_ID);
|
||||
err = netc_xmit_ntmp_cmd(user, &cbd);
|
||||
|
||||
ntmp_select_and_lock_cbdr(user, &cbdr);
|
||||
err = netc_xmit_ntmp_cmd(cbdr, &cbd, &swcbd);
|
||||
if (err) {
|
||||
dev_err(user->dev, "Failed to query RSST entry, err: %pe\n",
|
||||
ERR_PTR(err));
|
||||
goto end;
|
||||
goto unlock_cbdr;
|
||||
}
|
||||
|
||||
group = (u8 *)req;
|
||||
|
|
@ -446,8 +489,8 @@ int ntmp_rsst_query_entry(struct ntmp_user *user, u32 *table, int count)
|
|||
for (i = 0; i < count; i++)
|
||||
table[i] = group[i];
|
||||
|
||||
end:
|
||||
ntmp_free_data_mem(&data);
|
||||
unlock_cbdr:
|
||||
ntmp_unlock_cbdr(cbdr);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,9 @@
|
|||
|
||||
#define NTMP_EID_REQ_LEN 8
|
||||
#define NETC_CBDR_BD_NUM 256
|
||||
#define NETC_CBDRCIR_INDEX GENMASK(9, 0)
|
||||
#define NETC_CBDRCIR_SBE BIT(31)
|
||||
#define NETC_CBDR_CLEAN_WORK 16
|
||||
|
||||
union netc_cbd {
|
||||
struct {
|
||||
|
|
@ -54,13 +57,6 @@ union netc_cbd {
|
|||
} resp_hdr; /* NTMP Response Message Header Format */
|
||||
};
|
||||
|
||||
struct ntmp_dma_buf {
|
||||
struct device *dev;
|
||||
size_t size;
|
||||
void *buf;
|
||||
dma_addr_t dma;
|
||||
};
|
||||
|
||||
struct ntmp_cmn_req_data {
|
||||
__le16 update_act;
|
||||
u8 dbg_opt;
|
||||
|
|
|
|||
|
|
@ -31,6 +31,12 @@ struct netc_tbl_vers {
|
|||
u8 rsst_ver;
|
||||
};
|
||||
|
||||
struct netc_swcbd {
|
||||
void *buf;
|
||||
dma_addr_t dma;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
struct netc_cbdr {
|
||||
struct device *dev;
|
||||
struct netc_cbdr_regs regs;
|
||||
|
|
@ -44,9 +50,10 @@ struct netc_cbdr {
|
|||
void *addr_base_align;
|
||||
dma_addr_t dma_base;
|
||||
dma_addr_t dma_base_align;
|
||||
struct netc_swcbd *swcbd;
|
||||
|
||||
/* Serialize the order of command BD ring */
|
||||
spinlock_t ring_lock;
|
||||
struct mutex ring_lock;
|
||||
};
|
||||
|
||||
struct ntmp_user {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user