1use crate::gdma_driver::GdmaDriver;
7use crate::mana::ResourceArena;
8use crate::resources::Resource;
9use gdma_defs::GdmaDevId;
10use gdma_defs::GdmaQueueType;
11use gdma_defs::GdmaReqHdr;
12use gdma_defs::bnic::MANA_VTL2_ASSIGN_SERIAL_NUMBER_REQUEST_V1;
13use gdma_defs::bnic::MANA_VTL2_ASSIGN_SERIAL_NUMBER_RESPONSE_V1;
14use gdma_defs::bnic::MANA_VTL2_MOVE_FILTER_REQUEST_V2;
15use gdma_defs::bnic::MANA_VTL2_MOVE_FILTER_RESPONSE_V1;
16use gdma_defs::bnic::ManaCfgRxSteerReq;
17use gdma_defs::bnic::ManaCommandCode;
18use gdma_defs::bnic::ManaConfigVportReq;
19use gdma_defs::bnic::ManaConfigVportResp;
20use gdma_defs::bnic::ManaCreateWqobjReq;
21use gdma_defs::bnic::ManaCreateWqobjResp;
22use gdma_defs::bnic::ManaDestroyWqobjReq;
23use gdma_defs::bnic::ManaMoveFilterVTL2PrivilegedReq;
24use gdma_defs::bnic::ManaQueryDeviceCfgReq;
25use gdma_defs::bnic::ManaQueryDeviceCfgResp;
26use gdma_defs::bnic::ManaQueryFilterStateReq;
27use gdma_defs::bnic::ManaQueryFilterStateResponse;
28use gdma_defs::bnic::ManaQueryStatisticsRequest;
29use gdma_defs::bnic::ManaQueryStatisticsResponse;
30use gdma_defs::bnic::ManaQueryVportCfgReq;
31use gdma_defs::bnic::ManaQueryVportCfgResp;
32use gdma_defs::bnic::ManaSetVportSerialNo;
33use user_driver::DeviceBacking;
34use zerocopy::FromBytes;
35use zerocopy::FromZeros;
36use zerocopy::Immutable;
37use zerocopy::IntoBytes;
38use zerocopy::KnownLayout;
39
40pub struct BnicDriver<'a, T: DeviceBacking> {
41 gdma: &'a mut GdmaDriver<T>,
42 dev_id: GdmaDevId,
43}
44
45impl<'a, T: DeviceBacking> BnicDriver<'a, T> {
46 pub fn new(gdma: &'a mut GdmaDriver<T>, dev_id: GdmaDevId) -> Self {
47 Self { gdma, dev_id }
48 }
49
50 #[tracing::instrument(skip(self), level = "debug", err)]
51 pub async fn query_dev_config(&mut self) -> anyhow::Result<ManaQueryDeviceCfgResp> {
52 let resp: ManaQueryDeviceCfgResp = self
53 .gdma
54 .request(
55 ManaCommandCode::MANA_QUERY_DEV_CONFIG.0,
56 self.dev_id,
57 ManaQueryDeviceCfgReq {
58 mn_drv_cap_flags1: 0,
59 mn_drv_cap_flags2: 0,
60 mn_drv_cap_flags3: 0,
61 mn_drv_cap_flags4: 0,
62 proto_major_ver: 1,
63 proto_minor_ver: 0,
64 proto_micro_ver: 0,
65 reserved: 0,
66 },
67 )
68 .await?;
69 Ok(resp)
70 }
71
72 #[tracing::instrument(skip(self), level = "debug", err)]
73 pub async fn config_vport_tx(
74 &mut self,
75 vport: u64,
76 pdid: u32,
77 doorbell_pageid: u32,
78 ) -> anyhow::Result<ManaConfigVportResp> {
79 let resp: ManaConfigVportResp = self
80 .gdma
81 .request(
82 ManaCommandCode::MANA_CONFIG_VPORT_TX.0,
83 self.dev_id,
84 ManaConfigVportReq {
85 vport,
86 pdid,
87 doorbell_pageid,
88 },
89 )
90 .await?;
91 Ok(resp)
92 }
93
94 #[tracing::instrument(skip(self, arena, config), level = "debug", err)]
95 pub async fn create_wq_obj(
96 &mut self,
97 arena: &mut ResourceArena,
98 vport: u64,
99 wq_type: GdmaQueueType,
100 config: &WqConfig,
101 ) -> anyhow::Result<ManaCreateWqobjResp> {
102 let resp: ManaCreateWqobjResp = self
103 .gdma
104 .request(
105 ManaCommandCode::MANA_CREATE_WQ_OBJ.0,
106 self.dev_id,
107 ManaCreateWqobjReq {
108 vport,
109 wq_type,
110 reserved: 0,
111 wq_gdma_region: config.wq_gdma_region,
112 cq_gdma_region: config.cq_gdma_region,
113 wq_size: config.wq_size,
114 cq_size: config.cq_size,
115 cq_moderation_ctx_id: config.cq_moderation_ctx_id,
116 cq_parent_qid: config.eq_id,
117 },
118 )
119 .await?;
120
121 arena.take_dma_region(config.wq_gdma_region);
123 arena.take_dma_region(config.cq_gdma_region);
124
125 arena.push(Resource::BnicQueue {
126 dev_id: self.dev_id,
127 wq_type,
128 wq_obj: resp.wq_obj,
129 });
130 Ok(resp)
131 }
132
133 #[tracing::instrument(skip(self), level = "debug", err)]
134 pub async fn destroy_wq_obj(
135 &mut self,
136 wq_type: GdmaQueueType,
137 wq_obj_handle: u64,
138 ) -> anyhow::Result<()> {
139 self.gdma
140 .request(
141 ManaCommandCode::MANA_DESTROY_WQ_OBJ.0,
142 self.dev_id,
143 ManaDestroyWqobjReq {
144 wq_type,
145 reserved: 0,
146 wq_obj_handle,
147 },
148 )
149 .await
150 }
151
152 #[tracing::instrument(skip(self, config), level = "debug", err)]
153 pub async fn config_vport_rx(
154 &mut self,
155 vport: u64,
156 config: &RxConfig<'_>,
157 ) -> anyhow::Result<()> {
158 #[repr(C)]
159 #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
160 struct Req {
161 req: ManaCfgRxSteerReq,
162 table: [u64; 128],
163 }
164
165 let mut req = Req {
166 req: ManaCfgRxSteerReq {
167 vport,
168 num_indir_entries: config.indirection_table.map_or(0, |t| t.len() as u16),
169 indir_tab_offset: (size_of::<GdmaReqHdr>() + size_of::<ManaCfgRxSteerReq>()) as u16,
170 rx_enable: config.rx_enable.into(),
171 rss_enable: config.rss_enable.into(),
172 update_default_rxobj: config.default_rxobj.is_some().into(),
173 update_hashkey: config.hash_key.is_some().into(),
174 update_indir_tab: config.indirection_table.is_some().into(),
175 reserved: 0,
176 default_rxobj: config.default_rxobj.unwrap_or(0),
177 hashkey: *config.hash_key.unwrap_or(&[0; 40]),
178 },
179 table: FromZeros::new_zeroed(),
180 };
181 if let Some(table) = config.indirection_table {
182 req.table[..table.len()].copy_from_slice(table);
183 }
184
185 self.gdma
186 .request(ManaCommandCode::MANA_CONFIG_VPORT_RX.0, self.dev_id, req)
187 .await
188 }
189
190 #[tracing::instrument(skip(self), level = "debug", err)]
191 pub async fn query_vport_config(
192 &mut self,
193 vport_index: u32,
194 ) -> anyhow::Result<ManaQueryVportCfgResp> {
195 let resp: ManaQueryVportCfgResp = self
196 .gdma
197 .request(
198 ManaCommandCode::MANA_QUERY_VPORT_CONFIG.0,
199 self.dev_id,
200 ManaQueryVportCfgReq { vport_index },
201 )
202 .await?;
203 Ok(resp)
204 }
205
206 pub async fn query_stats(
207 &mut self,
208 requested_statistics: u64,
209 ) -> anyhow::Result<ManaQueryStatisticsResponse> {
210 let resp: ManaQueryStatisticsResponse = self
211 .gdma
212 .request(
213 ManaCommandCode::MANA_QUERY_STATS.0,
214 self.dev_id,
215 ManaQueryStatisticsRequest {
216 requested_statistics,
217 },
218 )
219 .await?;
220 Ok(resp)
221 }
222
223 pub async fn query_filter_state(
224 &mut self,
225 vport: u64,
226 ) -> anyhow::Result<ManaQueryFilterStateResponse> {
227 let resp: ManaQueryFilterStateResponse = self
228 .gdma
229 .request(
230 ManaCommandCode::MANA_VTL2_QUERY_FILTER_STATE.0,
231 self.dev_id,
232 ManaQueryFilterStateReq { vport },
233 )
234 .await?;
235 Ok(resp)
236 }
237
238 #[tracing::instrument(skip(self), level = "debug", err)]
239 pub async fn move_vport_filter(
240 &mut self,
241 vport: u64,
242 direction_to_vtl0: u8,
243 ) -> anyhow::Result<u32> {
244 let ((), activity_id) = self
245 .gdma
246 .request_version(
247 ManaCommandCode::MANA_VTL2_MOVE_FILTER.0,
248 MANA_VTL2_MOVE_FILTER_REQUEST_V2,
249 ManaCommandCode::MANA_VTL2_MOVE_FILTER.0,
250 MANA_VTL2_MOVE_FILTER_RESPONSE_V1,
251 self.dev_id,
252 ManaMoveFilterVTL2PrivilegedReq {
253 vport,
254 direction_to_vtl0,
255 reserved: [0, 0, 0],
256 reserved2: 0,
257 },
258 )
259 .await?;
260 Ok(activity_id)
261 }
262
263 #[tracing::instrument(skip(self), level = "debug", err)]
264 pub async fn set_vport_serial_no(&mut self, vport: u64, serial_no: u32) -> anyhow::Result<()> {
265 let ((), _) = self
266 .gdma
267 .request_version(
268 ManaCommandCode::MANA_VTL2_ASSIGN_SERIAL_NUMBER.0,
269 MANA_VTL2_ASSIGN_SERIAL_NUMBER_REQUEST_V1,
270 ManaCommandCode::MANA_VTL2_ASSIGN_SERIAL_NUMBER.0,
271 MANA_VTL2_ASSIGN_SERIAL_NUMBER_RESPONSE_V1,
272 self.dev_id,
273 ManaSetVportSerialNo {
274 vport,
275 serial_no,
276 reserved: 0,
277 },
278 )
279 .await?;
280 Ok(())
281 }
282}
283
284pub struct RxConfig<'a> {
286 pub rx_enable: Option<bool>,
288 pub rss_enable: Option<bool>,
290 pub hash_key: Option<&'a [u8; 40]>,
292 pub default_rxobj: Option<u64>,
294 pub indirection_table: Option<&'a [u64]>,
296}
297
298pub struct WqConfig {
299 pub wq_gdma_region: u64,
300 pub cq_gdma_region: u64,
301 pub wq_size: u32,
302 pub cq_size: u32,
303 pub cq_moderation_ctx_id: u32,
304 pub eq_id: u32,
305}