Skip to content

Commit 50982cd

Browse files
GuEe-GUIRbb666
authored andcommitted
[DM/PCI] Add memory window pool for EP
Signed-off-by: GuEe-GUI <[email protected]>
1 parent 0d2e677 commit 50982cd

File tree

3 files changed

+230
-1
lines changed

3 files changed

+230
-1
lines changed

components/drivers/include/drivers/pci_endpoint.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ struct rt_pci_ep_msix_tbl
7373
};
7474

7575
struct rt_pci_ep_ops;
76+
struct rt_pci_ep_mem;
7677

7778
struct rt_pci_ep
7879
{
@@ -84,6 +85,9 @@ struct rt_pci_ep
8485
const struct rt_device *rc_dev;
8586
const struct rt_pci_ep_ops *ops;
8687

88+
rt_size_t mems_nr;
89+
struct rt_pci_ep_mem *mems;
90+
8791
rt_uint8_t max_functions;
8892
RT_BITMAP_DECLARE(functions_map, 8);
8993
rt_list_t epf_nodes;
@@ -92,6 +96,16 @@ struct rt_pci_ep
9296
void *priv;
9397
};
9498

99+
struct rt_pci_ep_mem
100+
{
101+
rt_ubase_t cpu_addr;
102+
rt_size_t size;
103+
rt_size_t page_size;
104+
105+
rt_bitmap_t *map;
106+
rt_size_t bits;
107+
};
108+
95109
struct rt_pci_epf
96110
{
97111
rt_list_t list;
@@ -170,6 +184,16 @@ rt_err_t rt_pci_ep_stop(struct rt_pci_ep *ep);
170184
rt_err_t rt_pci_ep_register(struct rt_pci_ep *ep);
171185
rt_err_t rt_pci_ep_unregister(struct rt_pci_ep *ep);
172186

187+
rt_err_t rt_pci_ep_mem_array_init(struct rt_pci_ep *ep,
188+
struct rt_pci_ep_mem *mems, rt_size_t mems_nr);
189+
rt_err_t rt_pci_ep_mem_init(struct rt_pci_ep *ep,
190+
rt_ubase_t cpu_addr, rt_size_t size, rt_size_t page_size);
191+
192+
void *rt_pci_ep_mem_alloc(struct rt_pci_ep *ep,
193+
rt_ubase_t *out_cpu_addr, rt_size_t size);
194+
void rt_pci_ep_mem_free(struct rt_pci_ep *ep,
195+
void *vaddr, rt_ubase_t cpu_addr, rt_size_t size);
196+
173197
rt_err_t rt_pci_ep_add_epf(struct rt_pci_ep *ep, struct rt_pci_epf *epf);
174198
rt_err_t rt_pci_ep_remove_epf(struct rt_pci_ep *ep, struct rt_pci_epf *epf);
175199

components/drivers/pci/endpoint/SConscript

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ if not GetDepend(['RT_PCI_ENDPOINT']):
88
cwd = GetCurrentDir()
99
CPPPATH = [cwd + '/../../include']
1010

11-
src = ['endpoint.c']
11+
src = ['endpoint.c', 'mem.c']
1212

1313
group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
1414

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
/*
2+
* Copyright (c) 2006-2022, RT-Thread Development Team
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*
6+
* Change Logs:
7+
* Date Author Notes
8+
* 2022-08-25 GuEe-GUI first version
9+
*/
10+
11+
#include <drivers/pci_endpoint.h>
12+
13+
#define DBG_TAG "pci.ep.mem"
14+
#define DBG_LVL DBG_INFO
15+
#include <rtdbg.h>
16+
17+
rt_err_t rt_pci_ep_mem_array_init(struct rt_pci_ep *ep,
18+
struct rt_pci_ep_mem *mems, rt_size_t mems_nr)
19+
{
20+
rt_size_t idx;
21+
rt_err_t err = RT_EOK;
22+
23+
if (!ep || !mems)
24+
{
25+
return -RT_EINVAL;
26+
}
27+
28+
rt_mutex_take(&ep->lock, RT_WAITING_FOREVER);
29+
30+
ep->mems_nr = mems_nr;
31+
ep->mems = rt_calloc(mems_nr, sizeof(*ep->mems));
32+
33+
if (!ep->mems)
34+
{
35+
return -RT_ENOMEM;
36+
}
37+
38+
for (idx = 0; idx < mems_nr; ++idx)
39+
{
40+
struct rt_pci_ep_mem *mem = &ep->mems[idx];
41+
42+
mem->cpu_addr = mems->cpu_addr;
43+
mem->size = mems->size;
44+
mem->page_size = mems->page_size;
45+
mem->bits = mems->size / mems->page_size;
46+
mem->map = rt_calloc(RT_BITMAP_LEN(mem->bits), sizeof(*mem->map));
47+
48+
if (!mem->map)
49+
{
50+
err = -RT_ENOMEM;
51+
goto _out_lock;
52+
}
53+
}
54+
55+
_out_lock:
56+
if (err)
57+
{
58+
while (idx --> 0)
59+
{
60+
rt_free(ep->mems[idx].map);
61+
}
62+
rt_free(ep->mems);
63+
64+
ep->mems_nr = 0;
65+
ep->mems = RT_NULL;
66+
}
67+
68+
rt_mutex_release(&ep->lock);
69+
70+
return err;
71+
}
72+
73+
rt_err_t rt_pci_ep_mem_init(struct rt_pci_ep *ep,
74+
rt_ubase_t cpu_addr, rt_size_t size, rt_size_t page_size)
75+
{
76+
struct rt_pci_ep_mem mem;
77+
78+
if (!ep)
79+
{
80+
return -RT_EINVAL;
81+
}
82+
83+
mem.cpu_addr = cpu_addr;
84+
mem.size = size;
85+
mem.page_size = page_size;
86+
87+
return rt_pci_ep_mem_array_init(ep, &mem, 1);
88+
}
89+
90+
static rt_ubase_t bitmap_region_alloc(struct rt_pci_ep_mem *mem, rt_size_t size)
91+
{
92+
rt_size_t bit, next_bit, end_bit, max_bits;
93+
94+
size /= mem->page_size;
95+
max_bits = mem->bits - size;
96+
97+
rt_bitmap_for_each_clear_bit(mem->map, bit, max_bits)
98+
{
99+
end_bit = bit + size;
100+
101+
for (next_bit = bit + 1; next_bit < end_bit; ++next_bit)
102+
{
103+
if (rt_bitmap_test_bit(mem->map, next_bit))
104+
{
105+
bit = next_bit;
106+
goto _next;
107+
}
108+
}
109+
110+
if (next_bit == end_bit)
111+
{
112+
while (next_bit --> bit)
113+
{
114+
rt_bitmap_set_bit(mem->map, next_bit);
115+
}
116+
117+
return mem->cpu_addr + bit * mem->page_size;
118+
}
119+
_next:
120+
}
121+
122+
return ~0ULL;
123+
}
124+
125+
static void bitmap_region_free(struct rt_pci_ep_mem *mem,
126+
rt_ubase_t cpu_addr, rt_size_t size)
127+
{
128+
rt_size_t bit = (cpu_addr - mem->cpu_addr) / mem->page_size, end_bit;
129+
130+
size /= mem->page_size;
131+
end_bit = bit + size;
132+
133+
for (; bit < end_bit; ++bit)
134+
{
135+
rt_bitmap_clear_bit(mem->map, bit);
136+
}
137+
}
138+
139+
void *rt_pci_ep_mem_alloc(struct rt_pci_ep *ep,
140+
rt_ubase_t *out_cpu_addr, rt_size_t size)
141+
{
142+
void *vaddr = RT_NULL;
143+
144+
if (!ep || !out_cpu_addr)
145+
{
146+
return vaddr;
147+
}
148+
149+
rt_mutex_take(&ep->lock, RT_WAITING_FOREVER);
150+
151+
for (rt_size_t idx = 0; idx < ep->mems_nr; ++idx)
152+
{
153+
rt_ubase_t cpu_addr;
154+
struct rt_pci_ep_mem *mem = &ep->mems[idx];
155+
156+
cpu_addr = bitmap_region_alloc(mem, size);
157+
158+
if (cpu_addr != ~0ULL)
159+
{
160+
vaddr = rt_ioremap((void *)cpu_addr, size);
161+
162+
if (!vaddr)
163+
{
164+
bitmap_region_free(mem, cpu_addr, size);
165+
166+
/* Try next memory */
167+
continue;
168+
}
169+
170+
*out_cpu_addr = cpu_addr;
171+
break;
172+
}
173+
}
174+
175+
rt_mutex_release(&ep->lock);
176+
177+
return vaddr;
178+
}
179+
180+
void rt_pci_ep_mem_free(struct rt_pci_ep *ep,
181+
void *vaddr, rt_ubase_t cpu_addr, rt_size_t size)
182+
{
183+
if (!ep || !vaddr || !size)
184+
{
185+
return;
186+
}
187+
188+
rt_mutex_take(&ep->lock, RT_WAITING_FOREVER);
189+
190+
for (rt_size_t idx = 0; idx < ep->mems_nr; ++idx)
191+
{
192+
struct rt_pci_ep_mem *mem = &ep->mems[idx];
193+
194+
if (mem->cpu_addr > cpu_addr &&
195+
mem->cpu_addr + mem->size >= cpu_addr + size)
196+
{
197+
rt_iounmap(mem);
198+
bitmap_region_free(mem, cpu_addr, size);
199+
200+
break;
201+
}
202+
}
203+
204+
rt_mutex_release(&ep->lock);
205+
}

0 commit comments

Comments
 (0)