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