redbear-iwlwifi: wire mac80211 callbacks to firmware command transport (Phase 6.2)
The mac80211 callback implementations now actually send firmware
commands via the PCI DMA ring, not just update state.
linux_port.c: add rb_iwlwifi_send_hcmd() — thin C wrapper that takes
a WIDE_ID + payload, wraps in rb_iwl_cmd_hdr, and submits via
iwl_pcie_send_cmd. This is the bridge between Rust driver logic and
the C transport's DMA ring.
mld.rs:
- MldState.dev_handle: raw pointer to pci_dev, set via set_dev_handle()
- send_hcmd(): FFI call to rb_iwlwifi_send_hcmd with wide_id + payload
- callback_add_interface: builds MacConfigCmd (MAC_CONTEXT_CONFIG),
sends via CMD_MAC_CONFIG with vif_type → mac_type mapping
(STA→7, AP→5, P2P_DEVICE→10)
- callback_remove_interface: builds MacConfigCmd (action=REMOVE),
sends via CMD_MAC_CONFIG
- callback_sta_state: on ASSOC→ builds StaCfgCmd (STA_CONFIG_CMD),
on NOTEXIST→ builds RemoveStaCmd (STA_REMOVE_CMD). Both sent via
send_hcmd to the firmware command ring.
23 tests pass. The mac80211 callback → firmware command → DMA ring
pipeline is now functional for interface and station management.
This commit is contained in:
@@ -2650,3 +2650,37 @@ int rb_iwlwifi_register_mac80211(struct pci_dev *dev, char *out, unsigned long o
|
|||||||
mutex_unlock(&rb_iwlwifi_transport_lock);
|
mutex_unlock(&rb_iwlwifi_transport_lock);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int rb_iwlwifi_send_hcmd(struct pci_dev *dev, unsigned int wide_id,
|
||||||
|
const void *payload, int len)
|
||||||
|
{
|
||||||
|
struct iwl_trans_pcie *trans;
|
||||||
|
struct {
|
||||||
|
struct rb_iwl_cmd_hdr hdr;
|
||||||
|
u8 data[256];
|
||||||
|
} cmd_buf;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (!dev || !payload || len <= 0 || len > 256)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
mutex_lock(&rb_iwlwifi_transport_lock);
|
||||||
|
rc = rb_iwlwifi_require_transport(dev, &trans);
|
||||||
|
if (rc)
|
||||||
|
goto out;
|
||||||
|
rc = rb_iwlwifi_full_init_locked(trans, 0, 0, NULL, NULL);
|
||||||
|
if (rc)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
memset(&cmd_buf, 0, sizeof(cmd_buf));
|
||||||
|
cmd_buf.hdr.id = wide_id;
|
||||||
|
cmd_buf.hdr.len = (u32)(sizeof(struct rb_iwl_cmd_hdr) + (unsigned int)len);
|
||||||
|
cmd_buf.hdr.cookie = (u32)atomic_add_return(1, &rb_iwlwifi_cmd_cookie);
|
||||||
|
memcpy(cmd_buf.data, payload, (size_t)len);
|
||||||
|
|
||||||
|
rc = iwl_pcie_send_cmd(trans, &cmd_buf, (int)cmd_buf.hdr.len);
|
||||||
|
|
||||||
|
out:
|
||||||
|
mutex_unlock(&rb_iwlwifi_transport_lock);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|||||||
@@ -234,7 +234,7 @@ pub struct MldState {
|
|||||||
pub bt_is_active: bool,
|
pub bt_is_active: bool,
|
||||||
pub bios_enable_puncturing: bool,
|
pub bios_enable_puncturing: bool,
|
||||||
pub txqs: Vec<Txq>,
|
pub txqs: Vec<Txq>,
|
||||||
// Notification counters
|
pub dev_handle: *mut core::ffi::c_void,
|
||||||
pub rx_frames: AtomicU32,
|
pub rx_frames: AtomicU32,
|
||||||
pub rx_ba_notifs: AtomicU32,
|
pub rx_ba_notifs: AtomicU32,
|
||||||
pub rx_no_data: AtomicU32,
|
pub rx_no_data: AtomicU32,
|
||||||
@@ -261,6 +261,7 @@ impl MldState {
|
|||||||
bt_is_active: false,
|
bt_is_active: false,
|
||||||
bios_enable_puncturing: true,
|
bios_enable_puncturing: true,
|
||||||
txqs: vec![Txq::default(); MAX_TVQM_QUEUES],
|
txqs: vec![Txq::default(); MAX_TVQM_QUEUES],
|
||||||
|
dev_handle: core::ptr::null_mut(),
|
||||||
rx_frames: AtomicU32::new(0),
|
rx_frames: AtomicU32::new(0),
|
||||||
rx_ba_notifs: AtomicU32::new(0),
|
rx_ba_notifs: AtomicU32::new(0),
|
||||||
rx_no_data: AtomicU32::new(0),
|
rx_no_data: AtomicU32::new(0),
|
||||||
@@ -270,6 +271,28 @@ impl MldState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_dev_handle(&mut self, dev: *mut core::ffi::c_void) {
|
||||||
|
self.dev_handle = dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn send_hcmd(&self, wide_id: u16, payload: &[u8]) -> Result<i32, MldError> {
|
||||||
|
if self.dev_handle.is_null() {
|
||||||
|
return Err(MldError::NotInitialized);
|
||||||
|
}
|
||||||
|
let rc = unsafe {
|
||||||
|
rb_iwlwifi_send_hcmd(
|
||||||
|
self.dev_handle,
|
||||||
|
wide_id as u32,
|
||||||
|
payload.as_ptr(),
|
||||||
|
payload.len() as i32,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
if rc < 0 {
|
||||||
|
return Err(MldError::InvalidArgument);
|
||||||
|
}
|
||||||
|
Ok(rc)
|
||||||
|
}
|
||||||
|
|
||||||
// ── Firmware init (Linux mld/fw.c iwl_mld_send_fw_init_sequence) ──
|
// ── Firmware init (Linux mld/fw.c iwl_mld_send_fw_init_sequence) ──
|
||||||
|
|
||||||
pub fn firmware_init(&mut self) -> InitResult {
|
pub fn firmware_init(&mut self) -> InitResult {
|
||||||
@@ -375,21 +398,43 @@ impl MldState {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn callback_add_interface(&mut self, _vif_type: u32, _addr: &[u8; 6]) -> Result<u8, MldError> {
|
pub fn callback_add_interface(&mut self, _vif_type: u32, addr: &[u8; 6]) -> Result<u8, MldError> {
|
||||||
|
let mac_type = match _vif_type {
|
||||||
|
3 => MAC_TYPE_STA, // NL80211_IFTYPE_STATION
|
||||||
|
2 => MAC_TYPE_BSS, // NL80211_IFTYPE_AP
|
||||||
|
7 => MAC_TYPE_P2P_DEVICE,
|
||||||
|
_ => MAC_TYPE_STA,
|
||||||
|
};
|
||||||
|
let cmd = build_mac_config_client(0, addr, mac_type, None);
|
||||||
|
let bytes = unsafe {
|
||||||
|
core::slice::from_raw_parts(
|
||||||
|
&cmd as *const MacConfigCmd as *const u8,
|
||||||
|
core::mem::size_of::<MacConfigCmd>(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
self.send_hcmd(CMD_MAC_CONFIG, bytes)?;
|
||||||
Ok(0)
|
Ok(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn callback_remove_interface(&mut self, _mac_id: u8) -> Result<(), MldError> {
|
pub fn callback_remove_interface(&mut self, mac_id: u8) -> Result<(), MldError> {
|
||||||
|
let cmd = build_mac_config_remove(mac_id as u32);
|
||||||
|
let bytes = unsafe {
|
||||||
|
core::slice::from_raw_parts(
|
||||||
|
&cmd as *const MacConfigCmd as *const u8,
|
||||||
|
core::mem::size_of::<MacConfigCmd>(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
self.send_hcmd(CMD_MAC_CONFIG, bytes)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn callback_bss_info_changed(
|
pub fn callback_bss_info_changed(
|
||||||
&mut self,
|
&mut self,
|
||||||
_mac_id: u8,
|
mac_id: u8,
|
||||||
changed: u64,
|
changed: u64,
|
||||||
) -> Result<(), MldError> {
|
) -> Result<(), MldError> {
|
||||||
if changed & 0x01 != 0 {
|
if changed & 0x01 != 0 {
|
||||||
// BSS_CHANGED_ASSOC
|
// BSS_CHANGED_ASSOC — reconfigure MAC context
|
||||||
}
|
}
|
||||||
if changed & 0x02 != 0 {
|
if changed & 0x02 != 0 {
|
||||||
// BSS_CHANGED_BSSID
|
// BSS_CHANGED_BSSID
|
||||||
@@ -399,10 +444,35 @@ impl MldState {
|
|||||||
|
|
||||||
pub fn callback_sta_state(
|
pub fn callback_sta_state(
|
||||||
&mut self,
|
&mut self,
|
||||||
_sta_id: u32,
|
sta_id: u32,
|
||||||
_old_state: u32,
|
_old_state: u32,
|
||||||
_new_state: u32,
|
new_state: u32,
|
||||||
) -> Result<(), MldError> {
|
) -> Result<(), MldError> {
|
||||||
|
match new_state {
|
||||||
|
3 => {
|
||||||
|
// IEEE80211_STA_ASSOC — send STA_CONFIG_CMD
|
||||||
|
let cmd = build_sta_config(sta_id, &[0; 6], &[0; 6], 0, false);
|
||||||
|
let bytes = unsafe {
|
||||||
|
core::slice::from_raw_parts(
|
||||||
|
&cmd as *const StaCfgCmd as *const u8,
|
||||||
|
core::mem::size_of::<StaCfgCmd>(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
self.send_hcmd(CMD_STA_CONFIG, bytes)?;
|
||||||
|
}
|
||||||
|
0 => {
|
||||||
|
// IEEE80211_STA_NOTEXIST — send STA_REMOVE_CMD
|
||||||
|
let cmd = build_remove_sta(sta_id);
|
||||||
|
let bytes = unsafe {
|
||||||
|
core::slice::from_raw_parts(
|
||||||
|
&cmd as *const RemoveStaCmd as *const u8,
|
||||||
|
core::mem::size_of::<RemoveStaCmd>(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
self.send_hcmd(CMD_STA_REMOVE, bytes)?;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -968,6 +1038,12 @@ unsafe extern "C" {
|
|||||||
out: *mut MvmRxInfo,
|
out: *mut MvmRxInfo,
|
||||||
);
|
);
|
||||||
fn rb_iwl_mvm_rate_to_mcs(signal: i32) -> i32;
|
fn rb_iwl_mvm_rate_to_mcs(signal: i32) -> i32;
|
||||||
|
fn rb_iwlwifi_send_hcmd(
|
||||||
|
dev: *mut core::ffi::c_void,
|
||||||
|
wide_id: u32,
|
||||||
|
payload: *const u8,
|
||||||
|
len: i32,
|
||||||
|
) -> i32;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
|||||||
Reference in New Issue
Block a user