idualwifi7260: Delete FreeBSD driver, import OpenBSD driver.

Again not wired into the build, nor yet modified in any way.
This commit is contained in:
Augustin Cavalier 2022-06-08 22:42:34 -04:00
parent 04171cfc5c
commit d87dd30a38
42 changed files with 14970 additions and 17900 deletions

View File

@ -1,138 +0,0 @@
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
******************************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2015 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2015 Intel Deutschland GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include "opt_iwm.h"
#include <sys/param.h>
#include "if_iwm_config.h"
#define IWM7260_FW "iwm7260fw"
#define IWM3160_FW "iwm3160fw"
#define IWM3168_FW "iwm3168fw"
#define IWM7265_FW "iwm7265fw"
#define IWM7265D_FW "iwm7265Dfw"
#define IWM_NVM_HW_SECTION_NUM_FAMILY_7000 0
#define IWM_DEVICE_7000_COMMON \
.device_family = IWM_DEVICE_FAMILY_7000, \
.eeprom_size = IWM_OTP_LOW_IMAGE_SIZE_FAMILY_7000, \
.nvm_hw_section_num = IWM_NVM_HW_SECTION_NUM_FAMILY_7000, \
.apmg_wake_up_wa = 1
const struct iwm_cfg iwm7260_cfg = {
.name = "Intel(R) Dual Band Wireless AC 7260",
.fw_name = IWM7260_FW,
IWM_DEVICE_7000_COMMON,
.host_interrupt_operation_mode = 1,
};
const struct iwm_cfg iwm3160_cfg = {
.name = "Intel(R) Dual Band Wireless AC 3160",
.fw_name = IWM3160_FW,
IWM_DEVICE_7000_COMMON,
.host_interrupt_operation_mode = 1,
};
const struct iwm_cfg iwm3165_cfg = {
.name = "Intel(R) Dual Band Wireless AC 3165",
.fw_name = IWM7265D_FW,
IWM_DEVICE_7000_COMMON,
.host_interrupt_operation_mode = 0,
};
const struct iwm_cfg iwm3168_cfg = {
.name = "Intel(R) Dual Band Wireless AC 3168",
.fw_name = IWM3168_FW,
IWM_DEVICE_7000_COMMON,
.host_interrupt_operation_mode = 0,
.nvm_type = IWM_NVM_SDP,
};
const struct iwm_cfg iwm7265_cfg = {
.name = "Intel(R) Dual Band Wireless AC 7265",
.fw_name = IWM7265_FW,
IWM_DEVICE_7000_COMMON,
.host_interrupt_operation_mode = 0,
};
const struct iwm_cfg iwm7265d_cfg = {
.name = "Intel(R) Dual Band Wireless AC 7265",
.fw_name = IWM7265D_FW,
IWM_DEVICE_7000_COMMON,
.host_interrupt_operation_mode = 0,
};

View File

@ -1,103 +0,0 @@
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
******************************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2014 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
*
* Copyright(c) 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2014 - 2015 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include "opt_iwm.h"
#include <sys/param.h>
#include "if_iwm_config.h"
#define IWM8000_FW "iwm8000Cfw"
#define IWM8265_FW "iwm8265fw"
#define IWM_NVM_HW_SECTION_NUM_FAMILY_8000 10
#define IWM_DEVICE_8000_COMMON \
.device_family = IWM_DEVICE_FAMILY_8000, \
.eeprom_size = IWM_OTP_LOW_IMAGE_SIZE_FAMILY_8000, \
.nvm_hw_section_num = IWM_NVM_HW_SECTION_NUM_FAMILY_8000
const struct iwm_cfg iwm8260_cfg = {
.name = "Intel(R) Dual Band Wireless AC 8260",
.fw_name = IWM8000_FW,
IWM_DEVICE_8000_COMMON,
.host_interrupt_operation_mode = 0,
};
const struct iwm_cfg iwm8265_cfg = {
.name = "Intel(R) Dual Band Wireless AC 8265",
.fw_name = IWM8265_FW,
IWM_DEVICE_8000_COMMON,
.host_interrupt_operation_mode = 0,
};

View File

@ -1,97 +0,0 @@
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
******************************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2014 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
*
* Copyright(c) 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2014 - 2015 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include "opt_iwm.h"
#include <sys/param.h>
#include "if_iwm_config.h"
#define IWM9000_FW "iwm9000fw"
#define IWM_NVM_HW_SECTION_NUM_FAMILY_9000 10
#define IWM_DEVICE_9000_COMMON \
.device_family = IWM_DEVICE_FAMILY_9000, \
.eeprom_size = IWM_OTP_LOW_IMAGE_SIZE_FAMILY_9000, \
.nvm_hw_section_num = IWM_NVM_HW_SECTION_NUM_FAMILY_9000
const struct iwm_cfg iwm9560_cfg = {
.name = "Intel(R) Dual Band Wireless AC 9560",
.fw_name = IWM9000_FW,
IWM_DEVICE_9000_COMMON,
.host_interrupt_operation_mode = 0,
.mqrx_supported = 1,
.integrated = 1,
};

View File

@ -1,96 +0,0 @@
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
******************************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2014 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
*
* Copyright(c) 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2014 - 2015 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include "opt_iwm.h"
#include <sys/param.h>
#include "if_iwm_config.h"
#define IWM9260_FW "iwm9260fw"
#define IWM_NVM_HW_SECTION_NUM_FAMILY_9260 10
#define IWM_DEVICE_9260_COMMON \
.device_family = IWM_DEVICE_FAMILY_9000, \
.eeprom_size = IWM_OTP_LOW_IMAGE_SIZE_FAMILY_9000, \
.nvm_hw_section_num = IWM_NVM_HW_SECTION_NUM_FAMILY_9260
const struct iwm_cfg iwm9260_cfg = {
.name = "Intel(R) Dual Band Wireless AC 9260",
.fw_name = IWM9260_FW,
IWM_DEVICE_9260_COMMON,
.host_interrupt_operation_mode = 0,
.mqrx_supported = 1,
};

View File

@ -1,254 +0,0 @@
/* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
/*
* Copyright (c) 2014 genua mbh <info@genua.de>
* Copyright (c) 2014 Fixup Software Ltd.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)
*
***********************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include "opt_iwm.h"
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/endian.h>
#include <sys/firmware.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/mutex.h>
#include <sys/module.h>
#include <sys/proc.h>
#include <sys/rman.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/sysctl.h>
#include <sys/linker.h>
#include <machine/bus.h>
#include <machine/endian.h>
#include <machine/resource.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <net/bpf.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_arp.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_types.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/if_ether.h>
#include <netinet/ip.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_regdomain.h>
#include <net80211/ieee80211_ratectl.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/iwm/if_iwmreg.h>
#include <dev/iwm/if_iwmvar.h>
#include <dev/iwm/if_iwm_debug.h>
#include <dev/iwm/if_iwm_util.h>
#include <dev/iwm/if_iwm_binding.h>
#include <dev/iwm/if_iwm_sf.h>
/*
* BEGIN iwlwifi/mvm/binding.c
*/
struct iwm_iface_iterator_data {
int idx;
struct iwm_phy_ctxt *phyctxt;
uint16_t ids[IWM_MAX_MACS_IN_BINDING];
int16_t colors[IWM_MAX_MACS_IN_BINDING];
};
static int
iwm_binding_cmd(struct iwm_softc *sc, uint32_t action,
struct iwm_iface_iterator_data *data)
{
struct iwm_binding_cmd cmd;
struct iwm_phy_ctxt *phyctxt = data->phyctxt;
int i, ret;
uint32_t status;
memset(&cmd, 0, sizeof(cmd));
cmd.id_and_color
= htole32(IWM_FW_CMD_ID_AND_COLOR(phyctxt->id, phyctxt->color));
cmd.action = htole32(action);
cmd.phy = htole32(IWM_FW_CMD_ID_AND_COLOR(phyctxt->id, phyctxt->color));
for (i = 0; i < IWM_MAX_MACS_IN_BINDING; i++)
cmd.macs[i] = htole32(IWM_FW_CTXT_INVALID);
for (i = 0; i < data->idx; i++)
cmd.macs[i] = htole32(IWM_FW_CMD_ID_AND_COLOR(data->ids[i],
data->colors[i]));
status = 0;
ret = iwm_send_cmd_pdu_status(sc, IWM_BINDING_CONTEXT_CMD,
sizeof(cmd), &cmd, &status);
if (ret) {
device_printf(sc->sc_dev,
"Failed to send binding (action:%d): %d\n", action, ret);
return ret;
}
if (status) {
device_printf(sc->sc_dev,
"Binding command failed: %u\n", status);
ret = EIO;
}
return ret;
}
static int
iwm_binding_update(struct iwm_softc *sc, struct iwm_vap *ivp,
struct iwm_phy_ctxt *phyctxt, boolean_t add)
{
struct iwm_iface_iterator_data data = {
.phyctxt = phyctxt,
};
uint32_t action;
if (add)
action = IWM_FW_CTXT_ACTION_ADD;
else
action = IWM_FW_CTXT_ACTION_REMOVE;
if (add) {
data.ids[0] = ivp->id;
data.colors[0] = ivp->color;
data.idx++;
}
return iwm_binding_cmd(sc, action, &data);
}
int
iwm_binding_add_vif(struct iwm_softc *sc, struct iwm_vap *ivp)
{
if (!ivp->phy_ctxt)
return EINVAL;
/*
* Update SF - Disable if needed. if this fails, SF might still be on
* while many macs are bound, which is forbidden - so fail the binding.
*/
if (iwm_sf_update(sc, &ivp->iv_vap, FALSE))
return EINVAL;
return iwm_binding_update(sc, ivp, ivp->phy_ctxt, TRUE);
}
int
iwm_binding_remove_vif(struct iwm_softc *sc, struct iwm_vap *ivp)
{
int ret;
if (!ivp->phy_ctxt)
return EINVAL;
ret = iwm_binding_update(sc, ivp, ivp->phy_ctxt, FALSE);
if (!ret) {
if (iwm_sf_update(sc, &ivp->iv_vap, TRUE))
device_printf(sc->sc_dev,
"Failed to update SF state\n");
}
return ret;
}

View File

@ -1,111 +0,0 @@
/* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
/* $FreeBSD$ */
/*
* Copyright (c) 2014 genua mbh <info@genua.de>
* Copyright (c) 2014 Fixup Software Ltd.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)
*
***********************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*-
* Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef __IF_IWM_BINDING_H__
#define __IF_IWM_BINDING_H__
extern int iwm_binding_add_vif(struct iwm_softc *sc, struct iwm_vap *ivp);
extern int iwm_binding_remove_vif(struct iwm_softc *sc, struct iwm_vap *ivp);
#endif /* __IF_IWM_BINDING_H__ */

View File

@ -1,159 +0,0 @@
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
******************************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
* Copyright (C) 2016 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
* Copyright (C) 2016 Intel Deutschland GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
/*
* $FreeBSD$
*/
#ifndef __IWM_CONFIG_H__
#define __IWM_CONFIG_H__
enum iwm_device_family {
IWM_DEVICE_FAMILY_UNDEFINED,
IWM_DEVICE_FAMILY_7000,
IWM_DEVICE_FAMILY_8000,
IWM_DEVICE_FAMILY_9000,
};
#define IWM_DEFAULT_MAX_TX_POWER 22
/* Antenna presence definitions */
#define IWM_ANT_NONE 0x0
#define IWM_ANT_A (1 << 0)
#define IWM_ANT_B (1 << 1)
#define IWM_ANT_C (1 << 2)
#define IWM_ANT_AB (IWM_ANT_A | IWM_ANT_B)
#define IWM_ANT_AC (IWM_ANT_A | IWM_ANT_C)
#define IWM_ANT_BC (IWM_ANT_B | IWM_ANT_C)
#define IWM_ANT_ABC (IWM_ANT_A | IWM_ANT_B | IWM_ANT_C)
static inline uint8_t num_of_ant(uint8_t mask)
{
return !!((mask) & IWM_ANT_A) +
!!((mask) & IWM_ANT_B) +
!!((mask) & IWM_ANT_C);
}
/* lower blocks contain EEPROM image and calibration data */
#define IWM_OTP_LOW_IMAGE_SIZE_FAMILY_7000 (16 * 512 * sizeof(uint16_t)) /* 16 KB */
#define IWM_OTP_LOW_IMAGE_SIZE_FAMILY_8000 (32 * 512 * sizeof(uint16_t)) /* 32 KB */
#define IWM_OTP_LOW_IMAGE_SIZE_FAMILY_9000 IWM_OTP_LOW_IMAGE_SIZE_FAMILY_8000
/**
* enum iwl_nvm_type - nvm formats
* @IWM_NVM: the regular format
* @IWM_NVM_EXT: extended NVM format
* @IWM_NVM_SDP: NVM format used by 3168 series
*/
enum iwm_nvm_type {
IWM_NVM,
IWM_NVM_EXT,
IWM_NVM_SDP,
};
/**
* struct iwm_cfg
* @name: Official name of the device
* @fw_name: Firmware filename.
* @host_interrupt_operation_mode: device needs host interrupt operation
* mode set
* @nvm_hw_section_num: the ID of the HW NVM section
* @apmg_wake_up_wa: should the MAC access REQ be asserted when a command
* is in flight. This is due to a HW bug in 7260, 3160 and 7265.
* @nvm_type: see &enum iwl_nvm_type
*/
struct iwm_cfg {
const char *name;
const char *fw_name;
uint16_t eeprom_size;
enum iwm_device_family device_family;
int host_interrupt_operation_mode;
int mqrx_supported;
int integrated;
uint8_t nvm_hw_section_num;
int apmg_wake_up_wa;
enum iwm_nvm_type nvm_type;
};
/*
* This list declares the config structures for all devices.
*/
extern const struct iwm_cfg iwm7260_cfg;
extern const struct iwm_cfg iwm3160_cfg;
extern const struct iwm_cfg iwm3165_cfg;
extern const struct iwm_cfg iwm3168_cfg;
extern const struct iwm_cfg iwm7265_cfg;
extern const struct iwm_cfg iwm7265d_cfg;
extern const struct iwm_cfg iwm8260_cfg;
extern const struct iwm_cfg iwm8265_cfg;
extern const struct iwm_cfg iwm9560_cfg;
extern const struct iwm_cfg iwm9260_cfg;
#endif /* __IWM_CONFIG_H__ */

View File

@ -1,154 +0,0 @@
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
******************************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2015 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
*
* Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2015 Intel Deutschland GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
/* $FreeBSD$ */
#ifndef __IF_IWM_CONSTANTS_H
#define __IF_IWM_CONSTANTS_H
/* <netproto/802_11/ieee80211_var.h> */
#define IWM_DEFAULT_PS_TX_DATA_TIMEOUT (100 * 1000)
#define IWM_DEFAULT_PS_RX_DATA_TIMEOUT (100 * 1000)
#define IWM_WOWLAN_PS_TX_DATA_TIMEOUT (10 * 1000)
#define IWM_WOWLAN_PS_RX_DATA_TIMEOUT (10 * 1000)
#define IWM_SHORT_PS_TX_DATA_TIMEOUT (2 * 1024) /* defined in TU */
#define IWM_SHORT_PS_RX_DATA_TIMEOUT (40 * 1024) /* defined in TU */
#define IWM_P2P_LOWLATENCY_PS_ENABLE 0
#define IWM_UAPSD_RX_DATA_TIMEOUT (50 * 1000)
#define IWM_UAPSD_TX_DATA_TIMEOUT (50 * 1000)
#ifdef notyet
/* XXX Find corresponding values from net80211 */
#define IWM_UAPSD_QUEUES (IEEE80211_WMM_IE_STA_QOSINFO_AC_VO |\
IEEE80211_WMM_IE_STA_QOSINFO_AC_VI |\
IEEE80211_WMM_IE_STA_QOSINFO_AC_BK |\
IEEE80211_WMM_IE_STA_QOSINFO_AC_BE)
#endif
#define IWM_PS_HEAVY_TX_THLD_PACKETS 20
#define IWM_PS_HEAVY_RX_THLD_PACKETS 8
#define IWM_PS_SNOOZE_HEAVY_TX_THLD_PACKETS 30
#define IWM_PS_SNOOZE_HEAVY_RX_THLD_PACKETS 20
#define IWM_PS_HEAVY_TX_THLD_PERCENT 50
#define IWM_PS_HEAVY_RX_THLD_PERCENT 50
#define IWM_PS_SNOOZE_INTERVAL 25
#define IWM_PS_SNOOZE_WINDOW 50
#define IWM_WOWLAN_PS_SNOOZE_WINDOW 25
#define IWM_LOWLAT_QUOTA_MIN_PERCENT 64
#define IWM_BT_COEX_EN_RED_TXP_THRESH 62
#define IWM_BT_COEX_DIS_RED_TXP_THRESH 65
#define IWM_BT_COEX_SYNC2SCO 1
#define IWM_BT_COEX_CORUNNING 0
#define IWM_BT_COEX_MPLUT 1
#define IWM_BT_COEX_RRC 1
#define IWM_BT_COEX_TTC 1
#define IWM_BT_COEX_MPLUT_REG0 0x22002200
#define IWM_BT_COEX_MPLUT_REG1 0x11118451
#define IWM_BT_COEX_ANTENNA_COUPLING_THRS 30
#define IWM_FW_MCAST_FILTER_PASS_ALL 0
#define IWM_FW_BCAST_FILTER_PASS_ALL 0
#define IWM_QUOTA_THRESHOLD 4
#define IWM_RS_RSSI_BASED_INIT_RATE 0
#define IWM_RS_80_20_FAR_RANGE_TWEAK 1
#define IWM_TOF_IS_RESPONDER 0
#define IWM_SW_TX_CSUM_OFFLOAD 0
#define IWM_HW_CSUM_DISABLE 0
#define IWM_COLLECT_FW_ERR_DUMP 1
#define IWM_RS_NUM_TRY_BEFORE_ANT_TOGGLE 1
#define IWM_RS_HT_VHT_RETRIES_PER_RATE 2
#define IWM_RS_HT_VHT_RETRIES_PER_RATE_TW 1
#define IWM_RS_INITIAL_MIMO_NUM_RATES 3
#define IWM_RS_INITIAL_SISO_NUM_RATES 3
#define IWM_RS_INITIAL_LEGACY_NUM_RATES 2
#define IWM_RS_INITIAL_LEGACY_RETRIES 2
#define IWM_RS_SECONDARY_LEGACY_RETRIES 1
#define IWM_RS_SECONDARY_LEGACY_NUM_RATES 16
#define IWM_RS_SECONDARY_SISO_NUM_RATES 3
#define IWM_RS_SECONDARY_SISO_RETRIES 1
#define IWM_RS_RATE_MIN_FAILURE_TH 3
#define IWM_RS_RATE_MIN_SUCCESS_TH 8
#define IWM_RS_STAY_IN_COLUMN_TIMEOUT 5 /* Seconds */
#define IWM_RS_IDLE_TIMEOUT 5 /* Seconds */
#define IWM_RS_MISSED_RATE_MAX 15
#define IWM_RS_LEGACY_FAILURE_LIMIT 160
#define IWM_RS_LEGACY_SUCCESS_LIMIT 480
#define IWM_RS_LEGACY_TABLE_COUNT 160
#define IWM_RS_NON_LEGACY_FAILURE_LIMIT 400
#define IWM_RS_NON_LEGACY_SUCCESS_LIMIT 4500
#define IWM_RS_NON_LEGACY_TABLE_COUNT 1500
#define IWM_RS_SR_FORCE_DECREASE 15 /* percent */
#define IWM_RS_SR_NO_DECREASE 85 /* percent */
#define IWM_RS_AGG_TIME_LIMIT 4000 /* 4 msecs. valid 100-8000 */
#define IWM_RS_AGG_DISABLE_START 3
#define IWM_RS_TPC_SR_FORCE_INCREASE 75 /* percent */
#define IWM_RS_TPC_SR_NO_INCREASE 85 /* percent */
#define IWM_RS_TPC_TX_POWER_STEP 3
#endif /* __IF_IWM_CONSTANTS_H */

View File

@ -1,62 +0,0 @@
/*-
* Copyright (c) 2015 Adrian Chadd <adrian@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $FreeBSD$
*/
#ifndef __IF_IWM_DEBUG_H__
#define __IF_IWM_DEBUG_H__
#ifdef IWM_DEBUG
enum {
IWM_DEBUG_XMIT = 0x00000001, /* basic xmit operation */
IWM_DEBUG_RECV = 0x00000002, /* basic recv operation */
IWM_DEBUG_STATE = 0x00000004, /* 802.11 state transitions */
IWM_DEBUG_TXPOW = 0x00000008, /* tx power processing */
IWM_DEBUG_RESET = 0x00000010, /* reset processing */
IWM_DEBUG_OPS = 0x00000020, /* iwm_ops processing */
IWM_DEBUG_BEACON = 0x00000040, /* beacon handling */
IWM_DEBUG_WATCHDOG = 0x00000080, /* watchdog timeout */
IWM_DEBUG_INTR = 0x00000100, /* ISR */
IWM_DEBUG_CALIBRATE = 0x00000200, /* periodic calibration */
IWM_DEBUG_NODE = 0x00000400, /* node management */
IWM_DEBUG_LED = 0x00000800, /* led management */
IWM_DEBUG_CMD = 0x00001000, /* cmd submission */
IWM_DEBUG_TXRATE = 0x00002000, /* TX rate debugging */
IWM_DEBUG_PWRSAVE = 0x00004000, /* Power save operations */
IWM_DEBUG_SCAN = 0x00008000, /* Scan related operations */
IWM_DEBUG_STATS = 0x00010000, /* Statistics updates */
IWM_DEBUG_FIRMWARE_TLV = 0x00020000, /* Firmware TLV parsing */
IWM_DEBUG_TRANS = 0x00040000, /* Transport layer (eg PCIe) */
IWM_DEBUG_EEPROM = 0x00080000, /* EEPROM/channel information */
IWM_DEBUG_TEMP = 0x00100000, /* Thermal Sensor handling */
IWM_DEBUG_FW = 0x00200000, /* Firmware management */
IWM_DEBUG_LAR = 0x00400000, /* Location Aware Regulatory */
IWM_DEBUG_TE = 0x00800000, /* Time Event handling */
IWM_DEBUG_REGISTER = 0x20000000, /* print chipset register */
IWM_DEBUG_TRACE = 0x40000000, /* Print begin and start driver function */
IWM_DEBUG_FATAL = 0x80000000, /* fatal errors */
IWM_DEBUG_ANY = 0xffffffff
};
#define IWM_DPRINTF(sc, m, fmt, ...) do { \
if (sc->sc_debug & (m)) \
device_printf(sc->sc_dev, fmt, ##__VA_ARGS__); \
} while (0)
#else
#define IWM_DPRINTF(sc, m, fmt, ...) do { (void) sc; } while (0)
#endif
#endif /* __IF_IWM_DEBUG_H__ */

View File

@ -1,342 +0,0 @@
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 4.7.3 (tag id d7f6728f57e3ecbb7ef34eb7d9f564d514775d75)
*
***********************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include "opt_iwm.h"
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/endian.h>
#include <sys/firmware.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/mutex.h>
#include <sys/module.h>
#include <sys/proc.h>
#include <sys/rman.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/sysctl.h>
#include <sys/linker.h>
#include <machine/bus.h>
#include <machine/endian.h>
#include <machine/resource.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <net/bpf.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_arp.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_types.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/if_ether.h>
#include <netinet/ip.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_regdomain.h>
#include <net80211/ieee80211_ratectl.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/iwm/if_iwmreg.h>
#include <dev/iwm/if_iwmvar.h>
#include <dev/iwm/if_iwm_debug.h>
#include <dev/iwm/if_iwm_util.h>
#include <dev/iwm/if_iwm_fw.h>
void
iwm_free_fw_paging(struct iwm_softc *sc)
{
int i;
if (sc->fw_paging_db[0].fw_paging_block.vaddr == NULL)
return;
for (i = 0; i < IWM_NUM_OF_FW_PAGING_BLOCKS; i++) {
iwm_dma_contig_free(&sc->fw_paging_db[i].fw_paging_block);
}
memset(sc->fw_paging_db, 0, sizeof(sc->fw_paging_db));
}
static int
iwm_fill_paging_mem(struct iwm_softc *sc, const struct iwm_fw_img *image)
{
int sec_idx, idx;
uint32_t offset = 0;
/*
* find where is the paging image start point:
* if CPU2 exist and it's in paging format, then the image looks like:
* CPU1 sections (2 or more)
* CPU1_CPU2_SEPARATOR_SECTION delimiter - separate between CPU1 to CPU2
* CPU2 sections (not paged)
* PAGING_SEPARATOR_SECTION delimiter - separate between CPU2
* non paged to CPU2 paging sec
* CPU2 paging CSS
* CPU2 paging image (including instruction and data)
*/
for (sec_idx = 0; sec_idx < IWM_UCODE_SECTION_MAX; sec_idx++) {
if (image->sec[sec_idx].offset == IWM_PAGING_SEPARATOR_SECTION) {
sec_idx++;
break;
}
}
/*
* If paging is enabled there should be at least 2 more sections left
* (one for CSS and one for Paging data)
*/
if (sec_idx >= nitems(image->sec) - 1) {
device_printf(sc->sc_dev,
"Paging: Missing CSS and/or paging sections\n");
iwm_free_fw_paging(sc);
return EINVAL;
}
/* copy the CSS block to the dram */
IWM_DPRINTF(sc, IWM_DEBUG_FW,
"Paging: load paging CSS to FW, sec = %d\n",
sec_idx);
memcpy(sc->fw_paging_db[0].fw_paging_block.vaddr,
image->sec[sec_idx].data,
sc->fw_paging_db[0].fw_paging_size);
IWM_DPRINTF(sc, IWM_DEBUG_FW,
"Paging: copied %d CSS bytes to first block\n",
sc->fw_paging_db[0].fw_paging_size);
sec_idx++;
/*
* copy the paging blocks to the dram
* loop index start from 1 since that CSS block already copied to dram
* and CSS index is 0.
* loop stop at num_of_paging_blk since that last block is not full.
*/
for (idx = 1; idx < sc->num_of_paging_blk; idx++) {
memcpy(sc->fw_paging_db[idx].fw_paging_block.vaddr,
(const char *)image->sec[sec_idx].data + offset,
sc->fw_paging_db[idx].fw_paging_size);
IWM_DPRINTF(sc, IWM_DEBUG_FW,
"Paging: copied %d paging bytes to block %d\n",
sc->fw_paging_db[idx].fw_paging_size,
idx);
offset += sc->fw_paging_db[idx].fw_paging_size;
}
/* copy the last paging block */
if (sc->num_of_pages_in_last_blk > 0) {
memcpy(sc->fw_paging_db[idx].fw_paging_block.vaddr,
(const char *)image->sec[sec_idx].data + offset,
IWM_FW_PAGING_SIZE * sc->num_of_pages_in_last_blk);
IWM_DPRINTF(sc, IWM_DEBUG_FW,
"Paging: copied %d pages in the last block %d\n",
sc->num_of_pages_in_last_blk, idx);
}
return 0;
}
static int
iwm_alloc_fw_paging_mem(struct iwm_softc *sc, const struct iwm_fw_img *image)
{
int blk_idx = 0;
int error, num_of_pages;
if (sc->fw_paging_db[0].fw_paging_block.vaddr != NULL) {
int i;
/* Device got reset, and we setup firmware paging again */
for (i = 0; i < sc->num_of_paging_blk + 1; i++) {
bus_dmamap_sync(sc->sc_dmat,
sc->fw_paging_db[i].fw_paging_block.map,
BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
}
return 0;
}
/* ensure IWM_BLOCK_2_EXP_SIZE is power of 2 of IWM_PAGING_BLOCK_SIZE */
_Static_assert((1 << IWM_BLOCK_2_EXP_SIZE) == IWM_PAGING_BLOCK_SIZE,
"IWM_BLOCK_2_EXP_SIZE must be power of 2 of IWM_PAGING_BLOCK_SIZE");
num_of_pages = image->paging_mem_size / IWM_FW_PAGING_SIZE;
sc->num_of_paging_blk = ((num_of_pages - 1) /
IWM_NUM_OF_PAGE_PER_GROUP) + 1;
sc->num_of_pages_in_last_blk =
num_of_pages -
IWM_NUM_OF_PAGE_PER_GROUP * (sc->num_of_paging_blk - 1);
IWM_DPRINTF(sc, IWM_DEBUG_FW,
"Paging: allocating mem for %d paging blocks, each block holds 8 pages, last block holds %d pages\n",
sc->num_of_paging_blk,
sc->num_of_pages_in_last_blk);
/* allocate block of 4Kbytes for paging CSS */
error = iwm_dma_contig_alloc(sc->sc_dmat,
&sc->fw_paging_db[blk_idx].fw_paging_block, IWM_FW_PAGING_SIZE,
4096);
if (error) {
/* free all the previous pages since we failed */
iwm_free_fw_paging(sc);
return ENOMEM;
}
sc->fw_paging_db[blk_idx].fw_paging_size = IWM_FW_PAGING_SIZE;
IWM_DPRINTF(sc, IWM_DEBUG_FW,
"Paging: allocated 4K(CSS) bytes for firmware paging.\n");
/*
* allocate blocks in dram.
* since that CSS allocated in fw_paging_db[0] loop start from index 1
*/
for (blk_idx = 1; blk_idx < sc->num_of_paging_blk + 1; blk_idx++) {
/* allocate block of IWM_PAGING_BLOCK_SIZE (32K) */
/* XXX Use iwm_dma_contig_alloc for allocating */
error = iwm_dma_contig_alloc(sc->sc_dmat,
&sc->fw_paging_db[blk_idx].fw_paging_block,
IWM_PAGING_BLOCK_SIZE, 4096);
if (error) {
/* free all the previous pages since we failed */
iwm_free_fw_paging(sc);
return ENOMEM;
}
sc->fw_paging_db[blk_idx].fw_paging_size = IWM_PAGING_BLOCK_SIZE;
IWM_DPRINTF(sc, IWM_DEBUG_FW,
"Paging: allocated 32K bytes for firmware paging.\n");
}
return 0;
}
int
iwm_save_fw_paging(struct iwm_softc *sc, const struct iwm_fw_img *fw)
{
int ret;
ret = iwm_alloc_fw_paging_mem(sc, fw);
if (ret)
return ret;
return iwm_fill_paging_mem(sc, fw);
}
/* send paging cmd to FW in case CPU2 has paging image */
int
iwm_send_paging_cmd(struct iwm_softc *sc, const struct iwm_fw_img *fw)
{
int blk_idx;
uint32_t dev_phy_addr;
struct iwm_fw_paging_cmd fw_paging_cmd = {
.flags =
htole32(IWM_PAGING_CMD_IS_SECURED |
IWM_PAGING_CMD_IS_ENABLED |
(sc->num_of_pages_in_last_blk <<
IWM_PAGING_CMD_NUM_OF_PAGES_IN_LAST_GRP_POS)),
.block_size = htole32(IWM_BLOCK_2_EXP_SIZE),
.block_num = htole32(sc->num_of_paging_blk),
};
/* loop for for all paging blocks + CSS block */
for (blk_idx = 0; blk_idx < sc->num_of_paging_blk + 1; blk_idx++) {
dev_phy_addr = htole32(
sc->fw_paging_db[blk_idx].fw_paging_block.paddr >>
IWM_PAGE_2_EXP_SIZE);
fw_paging_cmd.device_phy_addr[blk_idx] = dev_phy_addr;
bus_dmamap_sync(sc->sc_dmat,
sc->fw_paging_db[blk_idx].fw_paging_block.map,
BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
}
return iwm_send_cmd_pdu(sc, iwm_cmd_id(IWM_FW_PAGING_BLOCK_CMD,
IWM_ALWAYS_LONG_GROUP, 0),
0, sizeof(fw_paging_cmd), &fw_paging_cmd);
}

View File

@ -1,113 +0,0 @@
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 4.7.3 (tag id d7f6728f57e3ecbb7ef34eb7d9f564d514775d75)
*
***********************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 Intel Deutschland GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* $FreeBSD$
*/
#ifndef __IF_IWM_FW_H__
#define __IF_IWM_FW_H__
/*
* Block paging calculations
*/
#define IWM_PAGE_2_EXP_SIZE 12 /* 4K == 2^12 */
#define IWM_FW_PAGING_SIZE (1 << IWM_PAGE_2_EXP_SIZE) /* page size is 4KB */
#define IWM_PAGE_PER_GROUP_2_EXP_SIZE 3
/* 8 pages per group */
#define IWM_NUM_OF_PAGE_PER_GROUP (1 << IWM_PAGE_PER_GROUP_2_EXP_SIZE)
/* don't change, support only 32KB size */
#define IWM_PAGING_BLOCK_SIZE (IWM_NUM_OF_PAGE_PER_GROUP * IWM_FW_PAGING_SIZE)
/* 32K == 2^15 */
#define IWM_BLOCK_2_EXP_SIZE (IWM_PAGE_2_EXP_SIZE + IWM_PAGE_PER_GROUP_2_EXP_SIZE)
/*
* Image paging calculations
*/
#define IWM_BLOCK_PER_IMAGE_2_EXP_SIZE 5
/* 2^5 == 32 blocks per image */
#define IWM_NUM_OF_BLOCK_PER_IMAGE (1 << IWM_BLOCK_PER_IMAGE_2_EXP_SIZE)
/* maximum image size 1024KB */
#define IWM_MAX_PAGING_IMAGE_SIZE (IWM_NUM_OF_BLOCK_PER_IMAGE * IWM_PAGING_BLOCK_SIZE)
/* Virtual address signature */
#define IWM_PAGING_ADDR_SIG 0xAA000000
#define IWM_PAGING_CMD_IS_SECURED (1 << 9)
#define IWM_PAGING_CMD_IS_ENABLED (1 << 8)
#define IWM_PAGING_CMD_NUM_OF_PAGES_IN_LAST_GRP_POS 0
#define IWM_PAGING_TLV_SECURE_MASK 1
extern void iwm_free_fw_paging(struct iwm_softc *);
extern int iwm_save_fw_paging(struct iwm_softc *, const struct iwm_fw_img *);
extern int iwm_send_paging_cmd(struct iwm_softc *, const struct iwm_fw_img *);
#endif /* __IF_IWM_FW_H__ */

View File

@ -1,188 +0,0 @@
/* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
/*
* Copyright (c) 2014 genua mbh <info@genua.de>
* Copyright (c) 2014 Fixup Software Ltd.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)
*
***********************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include "opt_iwm.h"
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/firmware.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/mutex.h>
#include <sys/module.h>
#include <sys/proc.h>
#include <sys/rman.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/sysctl.h>
#include <sys/linker.h>
#include <machine/endian.h>
#include <machine/bus.h>
#include <net/bpf.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_arp.h>
#include <net/ethernet.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_types.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/if_ether.h>
#include <netinet/ip.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_regdomain.h>
#include <net80211/ieee80211_ratectl.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/iwm/if_iwmreg.h>
#include <dev/iwm/if_iwmvar.h>
#include <dev/iwm/if_iwm_debug.h>
#include <dev/iwm/if_iwm_util.h>
#include <dev/iwm/if_iwm_led.h>
/* Set led register on */
void
iwm_led_enable(struct iwm_softc *sc)
{
IWM_WRITE(sc, IWM_CSR_LED_REG, IWM_CSR_LED_REG_TURN_ON);
}
/* Set led register off */
void
iwm_led_disable(struct iwm_softc *sc)
{
IWM_WRITE(sc, IWM_CSR_LED_REG, IWM_CSR_LED_REG_TURN_OFF);
}
static int
iwm_led_is_enabled(struct iwm_softc *sc)
{
return (IWM_READ(sc, IWM_CSR_LED_REG) == IWM_CSR_LED_REG_TURN_ON);
}
static void
iwm_led_blink_timeout(void *arg)
{
struct iwm_softc *sc = arg;
if (sc->sc_attached == 0)
return;
if (iwm_led_is_enabled(sc))
iwm_led_disable(sc);
else
iwm_led_enable(sc);
callout_reset(&sc->sc_led_blink_to, (200 * hz) / 1000,
iwm_led_blink_timeout, sc);
}
void
iwm_led_blink_start(struct iwm_softc *sc)
{
callout_reset(&sc->sc_led_blink_to, 0, iwm_led_blink_timeout, sc);
}
void
iwm_led_blink_stop(struct iwm_softc *sc)
{
callout_stop(&sc->sc_led_blink_to);
iwm_led_disable(sc);
}

View File

@ -1,99 +0,0 @@
/* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
/*
* Copyright (c) 2014 genua mbh <info@genua.de>
* Copyright (c) 2014 Fixup Software Ltd.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)
*
***********************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef __IF_IWM_LED_H__
#define __IF_IWM_LED_H__
extern void iwm_led_enable(struct iwm_softc *);
extern void iwm_led_disable(struct iwm_softc *);
extern void iwm_led_blink_start(struct iwm_softc *);
extern void iwm_led_blink_stop(struct iwm_softc *);
#endif /* __IF_IWM_LED_H__ */

View File

@ -1,561 +0,0 @@
/* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
/*
* Copyright (c) 2014 genua mbh <info@genua.de>
* Copyright (c) 2014 Fixup Software Ltd.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)
*
***********************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*-
* Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include "opt_iwm.h"
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/endian.h>
#include <sys/firmware.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/mutex.h>
#include <sys/module.h>
#include <sys/proc.h>
#include <sys/rman.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/sysctl.h>
#include <sys/linker.h>
#include <machine/bus.h>
#include <machine/endian.h>
#include <machine/resource.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <net/bpf.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_arp.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_types.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/if_ether.h>
#include <netinet/ip.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_regdomain.h>
#include <net80211/ieee80211_ratectl.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/iwm/if_iwmreg.h>
#include <dev/iwm/if_iwmvar.h>
#include <dev/iwm/if_iwm_debug.h>
#include <dev/iwm/if_iwm_util.h>
#include <dev/iwm/if_iwm_mac_ctxt.h>
/*
* BEGIN mvm/mac-ctxt.c
*/
const uint8_t iwm_ac_to_tx_fifo[] = {
IWM_TX_FIFO_BE,
IWM_TX_FIFO_BK,
IWM_TX_FIFO_VI,
IWM_TX_FIFO_VO,
};
static void
iwm_ack_rates(struct iwm_softc *sc, int is2ghz,
int *cck_rates, int *ofdm_rates, struct iwm_node *in)
{
int lowest_present_ofdm = 100;
int lowest_present_cck = 100;
uint8_t cck = 0;
uint8_t ofdm = 0;
int i;
struct ieee80211_rateset *rs = &in->in_ni.ni_rates;
if (is2ghz) {
for (i = IWM_FIRST_CCK_RATE; i <= IWM_LAST_CCK_RATE; i++) {
if ((iwm_ridx2rate(rs, i) & IEEE80211_RATE_BASIC) == 0)
continue;
cck |= (1 << i);
if (lowest_present_cck > i)
lowest_present_cck = i;
}
}
for (i = IWM_FIRST_OFDM_RATE; i <= IWM_LAST_NON_HT_RATE; i++) {
if ((iwm_ridx2rate(rs, i) & IEEE80211_RATE_BASIC) == 0)
continue;
ofdm |= (1 << (i - IWM_FIRST_OFDM_RATE));
if (lowest_present_ofdm > i)
lowest_present_ofdm = i;
}
/*
* Now we've got the basic rates as bitmaps in the ofdm and cck
* variables. This isn't sufficient though, as there might not
* be all the right rates in the bitmap. E.g. if the only basic
* rates are 5.5 Mbps and 11 Mbps, we still need to add 1 Mbps
* and 6 Mbps because the 802.11-2007 standard says in 9.6:
*
* [...] a STA responding to a received frame shall transmit
* its Control Response frame [...] at the highest rate in the
* BSSBasicRateSet parameter that is less than or equal to the
* rate of the immediately previous frame in the frame exchange
* sequence ([...]) and that is of the same modulation class
* ([...]) as the received frame. If no rate contained in the
* BSSBasicRateSet parameter meets these conditions, then the
* control frame sent in response to a received frame shall be
* transmitted at the highest mandatory rate of the PHY that is
* less than or equal to the rate of the received frame, and
* that is of the same modulation class as the received frame.
*
* As a consequence, we need to add all mandatory rates that are
* lower than all of the basic rates to these bitmaps.
*/
if (IWM_RATE_24M_INDEX < lowest_present_ofdm)
ofdm |= IWM_RATE_BIT_MSK(24) >> IWM_FIRST_OFDM_RATE;
if (IWM_RATE_12M_INDEX < lowest_present_ofdm)
ofdm |= IWM_RATE_BIT_MSK(12) >> IWM_FIRST_OFDM_RATE;
/* 6M already there or needed so always add */
ofdm |= IWM_RATE_BIT_MSK(6) >> IWM_FIRST_OFDM_RATE;
/*
* CCK is a bit more complex with DSSS vs. HR/DSSS vs. ERP.
* Note, however:
* - if no CCK rates are basic, it must be ERP since there must
* be some basic rates at all, so they're OFDM => ERP PHY
* (or we're in 5 GHz, and the cck bitmap will never be used)
* - if 11M is a basic rate, it must be ERP as well, so add 5.5M
* - if 5.5M is basic, 1M and 2M are mandatory
* - if 2M is basic, 1M is mandatory
* - if 1M is basic, that's the only valid ACK rate.
* As a consequence, it's not as complicated as it sounds, just add
* any lower rates to the ACK rate bitmap.
*/
if (IWM_RATE_11M_INDEX < lowest_present_cck)
cck |= IWM_RATE_BIT_MSK(11) >> IWM_FIRST_CCK_RATE;
if (IWM_RATE_5M_INDEX < lowest_present_cck)
cck |= IWM_RATE_BIT_MSK(5) >> IWM_FIRST_CCK_RATE;
if (IWM_RATE_2M_INDEX < lowest_present_cck)
cck |= IWM_RATE_BIT_MSK(2) >> IWM_FIRST_CCK_RATE;
/* 1M already there or needed so always add */
cck |= IWM_RATE_BIT_MSK(1) >> IWM_FIRST_CCK_RATE;
*cck_rates = cck;
*ofdm_rates = ofdm;
}
static void
iwm_mac_ctxt_cmd_common(struct iwm_softc *sc, struct iwm_node *in,
struct iwm_mac_ctx_cmd *cmd, uint32_t action)
{
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct ieee80211_node *ni = vap->iv_bss;
struct iwm_vap *ivp = IWM_VAP(vap);
int cck_ack_rates, ofdm_ack_rates;
int i;
int is2ghz;
/*
* id is the MAC address ID - something to do with MAC filtering.
* color - not sure.
*
* These are both functions of the vap, not of the node.
* So, for now, hard-code both to 0 (default).
*/
cmd->id_and_color = htole32(IWM_FW_CMD_ID_AND_COLOR(ivp->id,
ivp->color));
cmd->action = htole32(action);
cmd->mac_type = htole32(IWM_FW_MAC_TYPE_BSS_STA);
/*
* The TSF ID is one of four TSF tracking resources in the firmware.
* Read the iwlwifi/mvm code for more details.
*
* For now, just hard-code it to TSF tracking ID 0; we only support
* a single STA mode VAP.
*
* It's per-vap, not per-node.
*/
cmd->tsf_id = htole32(IWM_DEFAULT_TSFID);
IEEE80211_ADDR_COPY(cmd->node_addr, vap->iv_myaddr);
/*
* XXX should we error out if in_assoc is 1 and ni == NULL?
*/
#if 0
if (in->in_assoc) {
IEEE80211_ADDR_COPY(cmd->bssid_addr, ni->ni_bssid);
} else {
/* eth broadcast address */
IEEE80211_ADDR_COPY(cmd->bssid_addr, ieee80211broadcastaddr);
}
#else
/*
* XXX This workaround makes the firmware behave more correctly once
* we are associated, regularly giving us statistics notifications,
* as well as signaling missed beacons to us.
* Since we only call iwm_mac_ctxt_add() and
* iwm_mac_ctxt_changed() when already authenticating or
* associating, ni->ni_bssid should always make sense here.
*/
if (ivp->iv_auth) {
IEEE80211_ADDR_COPY(cmd->bssid_addr, ni->ni_bssid);
} else {
/* XXX Or maybe all zeroes address? */
IEEE80211_ADDR_COPY(cmd->bssid_addr, ieee80211broadcastaddr);
}
#endif
/*
* Default to 2ghz if no node information is given.
*/
if (in && in->in_ni.ni_chan != IEEE80211_CHAN_ANYC) {
is2ghz = !! IEEE80211_IS_CHAN_2GHZ(in->in_ni.ni_chan);
} else {
is2ghz = 1;
}
iwm_ack_rates(sc, is2ghz, &cck_ack_rates, &ofdm_ack_rates, in);
cmd->cck_rates = htole32(cck_ack_rates);
cmd->ofdm_rates = htole32(ofdm_ack_rates);
cmd->cck_short_preamble
= htole32((ic->ic_flags & IEEE80211_F_SHPREAMBLE)
? IWM_MAC_FLG_SHORT_PREAMBLE : 0);
cmd->short_slot
= htole32((ic->ic_flags & IEEE80211_F_SHSLOT)
? IWM_MAC_FLG_SHORT_SLOT : 0);
/*
* XXX TODO: if we're doing QOS..
* cmd->qos_flags |= cpu_to_le32(MAC_QOS_FLG_UPDATE_EDCA)
*/
for (i = 0; i < WME_NUM_AC; i++) {
uint8_t txf = iwm_ac_to_tx_fifo[i];
cmd->ac[txf].cw_min = htole16(ivp->queue_params[i].cw_min);
cmd->ac[txf].cw_max = htole16(ivp->queue_params[i].cw_max);
cmd->ac[txf].edca_txop =
htole16(ivp->queue_params[i].edca_txop);
cmd->ac[txf].aifsn = ivp->queue_params[i].aifsn;
cmd->ac[txf].fifos_mask = (1 << txf);
}
if (ivp->have_wme)
cmd->qos_flags |= htole32(IWM_MAC_QOS_FLG_UPDATE_EDCA);
if (ic->ic_flags & IEEE80211_F_USEPROT)
cmd->protection_flags |= htole32(IWM_MAC_PROT_FLG_TGG_PROTECT);
cmd->filter_flags = htole32(IWM_MAC_FILTER_ACCEPT_GRP);
}
static int
iwm_mac_ctxt_send_cmd(struct iwm_softc *sc, struct iwm_mac_ctx_cmd *cmd)
{
int ret = iwm_send_cmd_pdu(sc, IWM_MAC_CONTEXT_CMD, IWM_CMD_SYNC,
sizeof(*cmd), cmd);
if (ret)
device_printf(sc->sc_dev,
"%s: Failed to send MAC context (action:%d): %d\n",
__func__, le32toh(cmd->action), ret);
return ret;
}
/*
* Fill the specific data for mac context of type station or p2p client
*/
static void
iwm_mac_ctxt_cmd_fill_sta(struct iwm_softc *sc, struct iwm_node *in,
struct iwm_mac_data_sta *ctxt_sta, int force_assoc_off)
{
struct ieee80211_node *ni = &in->in_ni;
unsigned dtim_period, dtim_count;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
/* will this work? */
dtim_period = vap->iv_dtim_period;
dtim_count = vap->iv_dtim_count;
IWM_DPRINTF(sc, IWM_DEBUG_RESET | IWM_DEBUG_BEACON | IWM_DEBUG_CMD,
"%s: force_assoc_off=%d\n", __func__, force_assoc_off);
IWM_DPRINTF(sc, IWM_DEBUG_RESET | IWM_DEBUG_BEACON | IWM_DEBUG_CMD,
"DTIM: period=%d count=%d\n", dtim_period, dtim_count);
IWM_DPRINTF(sc, IWM_DEBUG_RESET | IWM_DEBUG_BEACON | IWM_DEBUG_CMD,
"BEACON: tsf: %llu, ni_intval=%d\n",
(unsigned long long) le64toh(ni->ni_tstamp.tsf),
ni->ni_intval);
/* We need the dtim_period to set the MAC as associated */
if (in->in_assoc && dtim_period && !force_assoc_off) {
uint64_t tsf;
uint32_t dtim_offs;
/*
* The DTIM count counts down, so when it is N that means N
* more beacon intervals happen until the DTIM TBTT. Therefore
* add this to the current time. If that ends up being in the
* future, the firmware will handle it.
*
* Also note that the system_timestamp (which we get here as
* "sync_device_ts") and TSF timestamp aren't at exactly the
* same offset in the frame -- the TSF is at the first symbol
* of the TSF, the system timestamp is at signal acquisition
* time. This means there's an offset between them of at most
* a few hundred microseconds (24 * 8 bits + PLCP time gives
* 384us in the longest case), this is currently not relevant
* as the firmware wakes up around 2ms before the TBTT.
*/
dtim_offs = dtim_count * ni->ni_intval;
/* convert TU to usecs */
dtim_offs *= 1024;
/*
* net80211: TSF is in 802.11 order, so convert up to local
* ordering before we manipulate things.
*/
tsf = le64toh(ni->ni_tstamp.tsf);
ctxt_sta->dtim_tsf = htole64(tsf + dtim_offs);
ctxt_sta->dtim_time = htole32(tsf + dtim_offs);
IWM_DPRINTF(sc, IWM_DEBUG_RESET | IWM_DEBUG_BEACON | IWM_DEBUG_CMD,
"DTIM TBTT is 0x%llx/0x%x, offset %d\n",
(long long)le64toh(ctxt_sta->dtim_tsf),
le32toh(ctxt_sta->dtim_time), dtim_offs);
ctxt_sta->is_assoc = htole32(1);
} else {
ctxt_sta->is_assoc = htole32(0);
}
IWM_DPRINTF(sc, IWM_DEBUG_RESET | IWM_DEBUG_CMD | IWM_DEBUG_BEACON,
"%s: ni_intval: %d, bi_reciprocal: %d, dtim_interval: %d, dtim_reciprocal: %d\n",
__func__,
ni->ni_intval,
iwm_reciprocal(ni->ni_intval),
ni->ni_intval * dtim_period,
iwm_reciprocal(ni->ni_intval * dtim_period));
ctxt_sta->bi = htole32(ni->ni_intval);
ctxt_sta->bi_reciprocal = htole32(iwm_reciprocal(ni->ni_intval));
ctxt_sta->dtim_interval = htole32(ni->ni_intval * dtim_period);
ctxt_sta->dtim_reciprocal =
htole32(iwm_reciprocal(ni->ni_intval * dtim_period));
/* 10 = CONN_MAX_LISTEN_INTERVAL */
ctxt_sta->listen_interval = htole32(10);
IWM_DPRINTF(sc, IWM_DEBUG_RESET | IWM_DEBUG_CMD | IWM_DEBUG_BEACON,
"%s: associd=%d\n", __func__, IEEE80211_AID(ni->ni_associd));
ctxt_sta->assoc_id = htole32(IEEE80211_AID(ni->ni_associd));
}
static int
iwm_mac_ctxt_cmd_station(struct iwm_softc *sc, struct ieee80211vap *vap,
uint32_t action)
{
struct ieee80211_node *ni = vap->iv_bss;
struct iwm_node *in = IWM_NODE(ni);
struct iwm_mac_ctx_cmd cmd = {};
IWM_DPRINTF(sc, IWM_DEBUG_RESET,
"%s: called; action=%d\n", __func__, action);
/* Fill the common data for all mac context types */
iwm_mac_ctxt_cmd_common(sc, in, &cmd, action);
/* Allow beacons to pass through as long as we are not associated,or we
* do not have dtim period information */
if (!in->in_assoc || !vap->iv_dtim_period)
cmd.filter_flags |= htole32(IWM_MAC_FILTER_IN_BEACON);
else
cmd.filter_flags &= ~htole32(IWM_MAC_FILTER_IN_BEACON);
/* Fill the data specific for station mode */
iwm_mac_ctxt_cmd_fill_sta(sc, in,
&cmd.sta, action == IWM_FW_CTXT_ACTION_ADD);
return iwm_mac_ctxt_send_cmd(sc, &cmd);
}
static int
iwm_mac_ctx_send(struct iwm_softc *sc, struct ieee80211vap *vap,
uint32_t action)
{
return iwm_mac_ctxt_cmd_station(sc, vap, action);
}
int
iwm_mac_ctxt_add(struct iwm_softc *sc, struct ieee80211vap *vap)
{
struct iwm_vap *iv = IWM_VAP(vap);
int ret;
if (iv->is_uploaded != 0) {
device_printf(sc->sc_dev, "%s: called; uploaded != 0\n",
__func__);
return (EIO);
}
ret = iwm_mac_ctx_send(sc, vap, IWM_FW_CTXT_ACTION_ADD);
if (ret)
return (ret);
iv->is_uploaded = 1;
return (0);
}
int
iwm_mac_ctxt_changed(struct iwm_softc *sc, struct ieee80211vap *vap)
{
struct iwm_vap *iv = IWM_VAP(vap);
if (iv->is_uploaded == 0) {
device_printf(sc->sc_dev, "%s: called; uploaded = 0\n",
__func__);
return (EIO);
}
return iwm_mac_ctx_send(sc, vap, IWM_FW_CTXT_ACTION_MODIFY);
}
#if 0
static int
iwm_mac_ctxt_remove(struct iwm_softc *sc, struct iwm_node *in)
{
struct iwm_mac_ctx_cmd cmd;
int ret;
if (!in->in_uploaded) {
device_printf(sc->sc_dev,
"attempt to remove !uploaded node %p", in);
return EIO;
}
memset(&cmd, 0, sizeof(cmd));
cmd.id_and_color = htole32(IWM_FW_CMD_ID_AND_COLOR(IWM_DEFAULT_MACID,
IWM_DEFAULT_COLOR));
cmd.action = htole32(IWM_FW_CTXT_ACTION_REMOVE);
ret = iwm_send_cmd_pdu(sc,
IWM_MAC_CONTEXT_CMD, IWM_CMD_SYNC, sizeof(cmd), &cmd);
if (ret) {
device_printf(sc->sc_dev,
"Failed to remove MAC context: %d\n", ret);
return ret;
}
in->in_uploaded = 0;
return 0;
}
#endif

View File

@ -1,115 +0,0 @@
/* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
/* $FreeBSD$ */
/*
* Copyright (c) 2014 genua mbh <info@genua.de>
* Copyright (c) 2014 Fixup Software Ltd.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)
*
***********************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*-
* Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef __IF_IWM_MAC_CTXT_H__
#define __IF_IWM_MAC_CTXT_H__
extern const uint8_t iwm_ac_to_tx_fifo[];
extern int iwm_mac_ctxt_add(struct iwm_softc *sc, struct ieee80211vap *vap);
extern int iwm_mac_ctxt_changed(struct iwm_softc *sc, struct ieee80211vap *vap);
extern int iwm_mac_ctxt_remove(struct iwm_softc *sc, struct ieee80211vap *vap);
#endif /* __IF_IWM_MAC_CTXT_H__ */

View File

@ -1,221 +0,0 @@
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
******************************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2015 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include "opt_iwm.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mutex.h>
#include <sys/queue.h>
#include <dev/iwm/if_iwm_notif_wait.h>
#define IWM_WAIT_LOCK_INIT(_n, _s) \
mtx_init(&(_n)->lk_mtx, (_s), "iwm wait_notif", MTX_DEF);
#define IWM_WAIT_LOCK(_n) mtx_lock(&(_n)->lk_mtx)
#define IWM_WAIT_UNLOCK(_n) mtx_unlock(&(_n)->lk_mtx)
#define IWM_WAIT_LOCK_DESTROY(_n) mtx_destroy(&(_n)->lk_mtx)
struct iwm_notif_wait_data {
struct mtx lk_mtx;
char lk_buf[32];
STAILQ_HEAD(, iwm_notification_wait) list;
struct iwm_softc *sc;
};
struct iwm_notif_wait_data *
iwm_notification_wait_init(struct iwm_softc *sc)
{
struct iwm_notif_wait_data *data;
data = malloc(sizeof(*data), M_DEVBUF, M_NOWAIT | M_ZERO);
if (data != NULL) {
snprintf(data->lk_buf, 32, "iwm wait_notif");
IWM_WAIT_LOCK_INIT(data, data->lk_buf);
STAILQ_INIT(&data->list);
data->sc = sc;
}
return data;
}
void
iwm_notification_wait_free(struct iwm_notif_wait_data *notif_data)
{
KASSERT(STAILQ_EMPTY(&notif_data->list), ("notif list isn't empty"));
IWM_WAIT_LOCK_DESTROY(notif_data);
free(notif_data, M_DEVBUF);
}
/* XXX Get rid of separate cmd argument, like in iwlwifi's code */
void
iwm_notification_wait_notify(struct iwm_notif_wait_data *notif_data,
uint16_t cmd, struct iwm_rx_packet *pkt)
{
struct iwm_notification_wait *wait_entry;
IWM_WAIT_LOCK(notif_data);
STAILQ_FOREACH(wait_entry, &notif_data->list, entry) {
int found = FALSE;
int i;
/*
* If it already finished (triggered) or has been
* aborted then don't evaluate it again to avoid races,
* Otherwise the function could be called again even
* though it returned true before
*/
if (wait_entry->triggered || wait_entry->aborted)
continue;
for (i = 0; i < wait_entry->n_cmds; i++) {
if (cmd == wait_entry->cmds[i]) {
found = TRUE;
break;
}
}
if (!found)
continue;
if (!wait_entry->fn ||
wait_entry->fn(notif_data->sc, pkt, wait_entry->fn_data)) {
wait_entry->triggered = 1;
wakeup(wait_entry);
}
}
IWM_WAIT_UNLOCK(notif_data);
}
void
iwm_abort_notification_waits(struct iwm_notif_wait_data *notif_data)
{
struct iwm_notification_wait *wait_entry;
IWM_WAIT_LOCK(notif_data);
STAILQ_FOREACH(wait_entry, &notif_data->list, entry) {
wait_entry->aborted = 1;
wakeup(wait_entry);
}
IWM_WAIT_UNLOCK(notif_data);
}
void
iwm_init_notification_wait(struct iwm_notif_wait_data *notif_data,
struct iwm_notification_wait *wait_entry, const uint16_t *cmds, int n_cmds,
int (*fn)(struct iwm_softc *sc, struct iwm_rx_packet *pkt, void *data),
void *fn_data)
{
KASSERT(n_cmds <= IWM_MAX_NOTIF_CMDS,
("n_cmds %d is too large", n_cmds));
wait_entry->fn = fn;
wait_entry->fn_data = fn_data;
wait_entry->n_cmds = n_cmds;
memcpy(wait_entry->cmds, cmds, n_cmds * sizeof(uint16_t));
wait_entry->triggered = 0;
wait_entry->aborted = 0;
IWM_WAIT_LOCK(notif_data);
STAILQ_INSERT_TAIL(&notif_data->list, wait_entry, entry);
IWM_WAIT_UNLOCK(notif_data);
}
int
iwm_wait_notification(struct iwm_notif_wait_data *notif_data,
struct iwm_notification_wait *wait_entry, int timeout)
{
int ret = 0;
IWM_WAIT_LOCK(notif_data);
if (!wait_entry->triggered && !wait_entry->aborted) {
ret = msleep(wait_entry, &notif_data->lk_mtx, 0, "iwm_notif",
timeout);
}
STAILQ_REMOVE(&notif_data->list, wait_entry, iwm_notification_wait,
entry);
IWM_WAIT_UNLOCK(notif_data);
return ret;
}
void
iwm_remove_notification(struct iwm_notif_wait_data *notif_data,
struct iwm_notification_wait *wait_entry)
{
IWM_WAIT_LOCK(notif_data);
STAILQ_REMOVE(&notif_data->list, wait_entry, iwm_notification_wait,
entry);
IWM_WAIT_UNLOCK(notif_data);
}

View File

@ -1,138 +0,0 @@
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
******************************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2015 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
/* $FreeBSD$ */
#ifndef __IF_IWN_NOTIF_WAIT_H__
#define __IF_IWN_NOTIF_WAIT_H__
#include <sys/queue.h>
#define IWM_MAX_NOTIF_CMDS 5
struct iwm_rx_packet;
struct iwm_softc;
/**
* struct iwm_notification_wait - notification wait entry
* @entry: link for global list
* @fn: Function called with the notification. If the function
* returns true, the wait is over, if it returns false then
* the waiter stays blocked. If no function is given, any
* of the listed commands will unblock the waiter.
* @cmds: command IDs
* @n_cmds: number of command IDs
* @triggered: waiter should be woken up
* @aborted: wait was aborted
*
* This structure is not used directly, to wait for a
* notification declare it on the stack, and call
* iwm_init_notification_wait() with appropriate
* parameters. Then do whatever will cause the ucode
* to notify the driver, and to wait for that then
* call iwm_wait_notification().
*
* Each notification is one-shot. If at some point we
* need to support multi-shot notifications (which
* can't be allocated on the stack) we need to modify
* the code for them.
*/
struct iwm_notification_wait {
STAILQ_ENTRY(iwm_notification_wait) entry;
int (*fn)(struct iwm_softc *sc, struct iwm_rx_packet *pkt, void *data);
void *fn_data;
uint16_t cmds[IWM_MAX_NOTIF_CMDS];
uint8_t n_cmds;
int triggered, aborted;
};
/* caller functions */
extern struct iwm_notif_wait_data *iwm_notification_wait_init(
struct iwm_softc *sc);
extern void iwm_notification_wait_free(struct iwm_notif_wait_data *notif_data);
extern void iwm_notification_wait_notify(
struct iwm_notif_wait_data *notif_data, uint16_t cmd,
struct iwm_rx_packet *pkt);
extern void iwm_abort_notification_waits(
struct iwm_notif_wait_data *notif_data);
/* user functions */
extern void iwm_init_notification_wait(struct iwm_notif_wait_data *notif_data,
struct iwm_notification_wait *wait_entry,
const uint16_t *cmds, int n_cmds,
int (*fn)(struct iwm_softc *sc,
struct iwm_rx_packet *pkt, void *data),
void *fn_data);
extern int iwm_wait_notification(struct iwm_notif_wait_data *notif_data,
struct iwm_notification_wait *wait_entry, int timeout);
extern void iwm_remove_notification(struct iwm_notif_wait_data *notif_data,
struct iwm_notification_wait *wait_entry);
#endif /* __IF_IWN_NOTIF_WAIT_H__ */

View File

@ -1,733 +0,0 @@
/* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
/*
* Copyright (c) 2014 genua mbh <info@genua.de>
* Copyright (c) 2014 Fixup Software Ltd.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)
*
***********************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*-
* Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include "opt_iwm.h"
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/endian.h>
#include <sys/firmware.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/mutex.h>
#include <sys/module.h>
#include <sys/proc.h>
#include <sys/rman.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/sysctl.h>
#include <sys/linker.h>
#include <machine/bus.h>
#include <machine/endian.h>
#include <machine/resource.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <net/bpf.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_arp.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_types.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/if_ether.h>
#include <netinet/ip.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_regdomain.h>
#include <net80211/ieee80211_ratectl.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/iwm/if_iwmreg.h>
#include <dev/iwm/if_iwmvar.h>
#include <dev/iwm/if_iwm_config.h>
#include <dev/iwm/if_iwm_debug.h>
#include <dev/iwm/if_iwm_pcie_trans.h>
/*
* This is a subset of what's in linux iwlwifi/pcie/trans.c.
* The rest can be migrated out into here once they're no longer in
* if_iwm.c.
*/
/*
* basic device access
*/
uint32_t
iwm_read_prph(struct iwm_softc *sc, uint32_t addr)
{
IWM_WRITE(sc,
IWM_HBUS_TARG_PRPH_RADDR, ((addr & 0x000fffff) | (3 << 24)));
IWM_BARRIER_READ_WRITE(sc);
return IWM_READ(sc, IWM_HBUS_TARG_PRPH_RDAT);
}
void
iwm_write_prph(struct iwm_softc *sc, uint32_t addr, uint32_t val)
{
IWM_WRITE(sc,
IWM_HBUS_TARG_PRPH_WADDR, ((addr & 0x000fffff) | (3 << 24)));
IWM_BARRIER_WRITE(sc);
IWM_WRITE(sc, IWM_HBUS_TARG_PRPH_WDAT, val);
}
void
iwm_write_prph64(struct iwm_softc *sc, uint64_t addr, uint64_t val)
{
iwm_write_prph(sc, (uint32_t)addr, val & 0xffffffff);
iwm_write_prph(sc, (uint32_t)addr + 4, val >> 32);
}
int
iwm_poll_prph(struct iwm_softc *sc, uint32_t addr, uint32_t bits, uint32_t mask,
int timeout)
{
do {
if ((iwm_read_prph(sc, addr) & mask) == (bits & mask))
return (0);
DELAY(10);
timeout -= 10;
} while (timeout > 0);
return (ETIMEDOUT);
}
#ifdef IWM_DEBUG
/* iwlwifi: pcie/trans.c */
int
iwm_read_mem(struct iwm_softc *sc, uint32_t addr, void *buf, int dwords)
{
int offs, ret = 0;
uint32_t *vals = buf;
if (iwm_nic_lock(sc)) {
IWM_WRITE(sc, IWM_HBUS_TARG_MEM_RADDR, addr);
for (offs = 0; offs < dwords; offs++)
vals[offs] = IWM_READ(sc, IWM_HBUS_TARG_MEM_RDAT);
iwm_nic_unlock(sc);
} else {
ret = EBUSY;
}
return ret;
}
#endif
/* iwlwifi: pcie/trans.c */
int
iwm_write_mem(struct iwm_softc *sc, uint32_t addr, const void *buf, int dwords)
{
int offs;
const uint32_t *vals = buf;
if (iwm_nic_lock(sc)) {
IWM_WRITE(sc, IWM_HBUS_TARG_MEM_WADDR, addr);
/* WADDR auto-increments */
for (offs = 0; offs < dwords; offs++) {
uint32_t val = vals ? vals[offs] : 0;
IWM_WRITE(sc, IWM_HBUS_TARG_MEM_WDAT, val);
}
iwm_nic_unlock(sc);
} else {
IWM_DPRINTF(sc, IWM_DEBUG_TRANS,
"%s: write_mem failed\n", __func__);
return EBUSY;
}
return 0;
}
int
iwm_write_mem32(struct iwm_softc *sc, uint32_t addr, uint32_t val)
{
return iwm_write_mem(sc, addr, &val, 1);
}
int
iwm_poll_bit(struct iwm_softc *sc, int reg,
uint32_t bits, uint32_t mask, int timo)
{
for (;;) {
if ((IWM_READ(sc, reg) & mask) == (bits & mask)) {
return 1;
}
if (timo < 10) {
return 0;
}
timo -= 10;
DELAY(10);
}
}
int
iwm_nic_lock(struct iwm_softc *sc)
{
int rv = 0;
if (sc->cmd_hold_nic_awake)
return 1;
IWM_SETBITS(sc, IWM_CSR_GP_CNTRL,
IWM_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
if (sc->cfg->device_family >= IWM_DEVICE_FAMILY_8000)
DELAY(2);
if (iwm_poll_bit(sc, IWM_CSR_GP_CNTRL,
IWM_CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
IWM_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY
| IWM_CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP, 15000)) {
rv = 1;
} else {
/* jolt */
IWM_DPRINTF(sc, IWM_DEBUG_RESET,
"%s: resetting device via NMI\n", __func__);
IWM_WRITE(sc, IWM_CSR_RESET, IWM_CSR_RESET_REG_FLAG_FORCE_NMI);
}
return rv;
}
void
iwm_nic_unlock(struct iwm_softc *sc)
{
if (sc->cmd_hold_nic_awake)
return;
IWM_CLRBITS(sc, IWM_CSR_GP_CNTRL,
IWM_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
}
void
iwm_set_bits_mask_prph(struct iwm_softc *sc,
uint32_t reg, uint32_t bits, uint32_t mask)
{
uint32_t val;
/* XXX: no error path? */
if (iwm_nic_lock(sc)) {
val = iwm_read_prph(sc, reg) & mask;
val |= bits;
iwm_write_prph(sc, reg, val);
iwm_nic_unlock(sc);
}
}
void
iwm_set_bits_prph(struct iwm_softc *sc, uint32_t reg, uint32_t bits)
{
iwm_set_bits_mask_prph(sc, reg, bits, ~0);
}
void
iwm_clear_bits_prph(struct iwm_softc *sc, uint32_t reg, uint32_t bits)
{
iwm_set_bits_mask_prph(sc, reg, 0, ~bits);
}
/*
* High-level hardware frobbing routines
*/
void
iwm_enable_rfkill_int(struct iwm_softc *sc)
{
sc->sc_intmask = IWM_CSR_INT_BIT_RF_KILL;
IWM_WRITE(sc, IWM_CSR_INT_MASK, sc->sc_intmask);
IWM_SETBITS(sc, IWM_CSR_GP_CNTRL,
IWM_CSR_GP_CNTRL_REG_FLAG_RFKILL_WAKE_L1A_EN);
}
int
iwm_check_rfkill(struct iwm_softc *sc)
{
uint32_t v;
int rv;
/*
* "documentation" is not really helpful here:
* 27: HW_RF_KILL_SW
* Indicates state of (platform's) hardware RF-Kill switch
*
* But apparently when it's off, it's on ...
*/
v = IWM_READ(sc, IWM_CSR_GP_CNTRL);
rv = (v & IWM_CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) == 0;
if (rv) {
sc->sc_flags |= IWM_FLAG_RFKILL;
} else {
sc->sc_flags &= ~IWM_FLAG_RFKILL;
}
return rv;
}
#define IWM_HW_READY_TIMEOUT 50
int
iwm_set_hw_ready(struct iwm_softc *sc)
{
int ready;
IWM_SETBITS(sc, IWM_CSR_HW_IF_CONFIG_REG,
IWM_CSR_HW_IF_CONFIG_REG_BIT_NIC_READY);
ready = iwm_poll_bit(sc, IWM_CSR_HW_IF_CONFIG_REG,
IWM_CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
IWM_CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
IWM_HW_READY_TIMEOUT);
if (ready) {
IWM_SETBITS(sc, IWM_CSR_MBOX_SET_REG,
IWM_CSR_MBOX_SET_REG_OS_ALIVE);
}
return ready;
}
#undef IWM_HW_READY_TIMEOUT
int
iwm_prepare_card_hw(struct iwm_softc *sc)
{
int rv = 0;
int t = 0;
IWM_DPRINTF(sc, IWM_DEBUG_RESET, "->%s\n", __func__);
if (iwm_set_hw_ready(sc))
goto out;
IWM_SETBITS(sc, IWM_CSR_DBG_LINK_PWR_MGMT_REG,
IWM_CSR_RESET_LINK_PWR_MGMT_DISABLED);
DELAY(1000);
/* If HW is not ready, prepare the conditions to check again */
IWM_SETBITS(sc, IWM_CSR_HW_IF_CONFIG_REG,
IWM_CSR_HW_IF_CONFIG_REG_PREPARE);
do {
if (iwm_set_hw_ready(sc))
goto out;
DELAY(200);
t += 200;
} while (t < 150000);
rv = ETIMEDOUT;
out:
IWM_DPRINTF(sc, IWM_DEBUG_RESET, "<-%s\n", __func__);
return rv;
}
void
iwm_apm_config(struct iwm_softc *sc)
{
uint16_t lctl, cap;
int pcie_ptr;
/*
* HW bug W/A for instability in PCIe bus L0S->L1 transition.
* Check if BIOS (or OS) enabled L1-ASPM on this device.
* If so (likely), disable L0S, so device moves directly L0->L1;
* costs negligible amount of power savings.
* If not (unlikely), enable L0S, so there is at least some
* power savings, even without L1.
*/
int error;
error = pci_find_cap(sc->sc_dev, PCIY_EXPRESS, &pcie_ptr);
if (error != 0)
return;
lctl = pci_read_config(sc->sc_dev, pcie_ptr + PCIER_LINK_CTL,
sizeof(lctl));
if (lctl & PCIEM_LINK_CTL_ASPMC_L1) {
IWM_SETBITS(sc, IWM_CSR_GIO_REG,
IWM_CSR_GIO_REG_VAL_L0S_ENABLED);
} else {
IWM_CLRBITS(sc, IWM_CSR_GIO_REG,
IWM_CSR_GIO_REG_VAL_L0S_ENABLED);
}
cap = pci_read_config(sc->sc_dev, pcie_ptr + PCIER_DEVICE_CTL2,
sizeof(cap));
sc->sc_ltr_enabled = (cap & PCIEM_CTL2_LTR_ENABLE) ? 1 : 0;
IWM_DPRINTF(sc, IWM_DEBUG_RESET | IWM_DEBUG_PWRSAVE,
"L1 %sabled - LTR %sabled\n",
(lctl & PCIEM_LINK_CTL_ASPMC_L1) ? "En" : "Dis",
sc->sc_ltr_enabled ? "En" : "Dis");
}
/*
* Start up NIC's basic functionality after it has been reset
* (e.g. after platform boot, or shutdown via iwm_pcie_apm_stop())
* NOTE: This does not load uCode nor start the embedded processor
*/
int
iwm_apm_init(struct iwm_softc *sc)
{
int error = 0;
IWM_DPRINTF(sc, IWM_DEBUG_RESET, "iwm apm start\n");
/* Disable L0S exit timer (platform NMI Work/Around) */
if (sc->cfg->device_family < IWM_DEVICE_FAMILY_8000) {
IWM_SETBITS(sc, IWM_CSR_GIO_CHICKEN_BITS,
IWM_CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
}
/*
* Disable L0s without affecting L1;
* don't wait for ICH L0s (ICH bug W/A)
*/
IWM_SETBITS(sc, IWM_CSR_GIO_CHICKEN_BITS,
IWM_CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX);
/* Set FH wait threshold to maximum (HW error during stress W/A) */
IWM_SETBITS(sc, IWM_CSR_DBG_HPET_MEM_REG, IWM_CSR_DBG_HPET_MEM_REG_VAL);
/*
* Enable HAP INTA (interrupt from management bus) to
* wake device's PCI Express link L1a -> L0s
*/
IWM_SETBITS(sc, IWM_CSR_HW_IF_CONFIG_REG,
IWM_CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A);
iwm_apm_config(sc);
#if 0 /* not for 7k/8k */
/* Configure analog phase-lock-loop before activating to D0A */
if (trans->cfg->base_params->pll_cfg_val)
IWM_SETBITS(trans, IWM_CSR_ANA_PLL_CFG,
trans->cfg->base_params->pll_cfg_val);
#endif
/*
* Set "initialization complete" bit to move adapter from
* D0U* --> D0A* (powered-up active) state.
*/
IWM_SETBITS(sc, IWM_CSR_GP_CNTRL, IWM_CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
/*
* Wait for clock stabilization; once stabilized, access to
* device-internal resources is supported, e.g. iwm_write_prph()
* and accesses to uCode SRAM.
*/
if (!iwm_poll_bit(sc, IWM_CSR_GP_CNTRL,
IWM_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
IWM_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000)) {
device_printf(sc->sc_dev,
"timeout waiting for clock stabilization\n");
error = ETIMEDOUT;
goto out;
}
if (sc->cfg->host_interrupt_operation_mode) {
/*
* This is a bit of an abuse - This is needed for 7260 / 3160
* only check host_interrupt_operation_mode even if this is
* not related to host_interrupt_operation_mode.
*
* Enable the oscillator to count wake up time for L1 exit. This
* consumes slightly more power (100uA) - but allows to be sure
* that we wake up from L1 on time.
*
* This looks weird: read twice the same register, discard the
* value, set a bit, and yet again, read that same register
* just to discard the value. But that's the way the hardware
* seems to like it.
*/
if (iwm_nic_lock(sc)) {
iwm_read_prph(sc, IWM_OSC_CLK);
iwm_read_prph(sc, IWM_OSC_CLK);
iwm_nic_unlock(sc);
}
iwm_set_bits_prph(sc, IWM_OSC_CLK, IWM_OSC_CLK_FORCE_CONTROL);
if (iwm_nic_lock(sc)) {
iwm_read_prph(sc, IWM_OSC_CLK);
iwm_read_prph(sc, IWM_OSC_CLK);
iwm_nic_unlock(sc);
}
}
/*
* Enable DMA clock and wait for it to stabilize.
*
* Write to "CLK_EN_REG"; "1" bits enable clocks, while "0" bits
* do not disable clocks. This preserves any hardware bits already
* set by default in "CLK_CTRL_REG" after reset.
*/
if (sc->cfg->device_family == IWM_DEVICE_FAMILY_7000) {
if (iwm_nic_lock(sc)) {
iwm_write_prph(sc, IWM_APMG_CLK_EN_REG,
IWM_APMG_CLK_VAL_DMA_CLK_RQT);
iwm_nic_unlock(sc);
}
DELAY(20);
/* Disable L1-Active */
iwm_set_bits_prph(sc, IWM_APMG_PCIDEV_STT_REG,
IWM_APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
/* Clear the interrupt in APMG if the NIC is in RFKILL */
if (iwm_nic_lock(sc)) {
iwm_write_prph(sc, IWM_APMG_RTC_INT_STT_REG,
IWM_APMG_RTC_INT_STT_RFKILL);
iwm_nic_unlock(sc);
}
}
out:
if (error)
device_printf(sc->sc_dev, "apm init error %d\n", error);
return error;
}
/* iwlwifi/pcie/trans.c */
void
iwm_apm_stop(struct iwm_softc *sc)
{
IWM_SETBITS(sc, IWM_CSR_DBG_LINK_PWR_MGMT_REG,
IWM_CSR_RESET_LINK_PWR_MGMT_DISABLED);
IWM_SETBITS(sc, IWM_CSR_HW_IF_CONFIG_REG,
IWM_CSR_HW_IF_CONFIG_REG_PREPARE |
IWM_CSR_HW_IF_CONFIG_REG_ENABLE_PME);
DELAY(1000);
IWM_CLRBITS(sc, IWM_CSR_DBG_LINK_PWR_MGMT_REG,
IWM_CSR_RESET_LINK_PWR_MGMT_DISABLED);
DELAY(5000);
/* stop device's busmaster DMA activity */
IWM_SETBITS(sc, IWM_CSR_RESET, IWM_CSR_RESET_REG_FLAG_STOP_MASTER);
if (!iwm_poll_bit(sc, IWM_CSR_RESET,
IWM_CSR_RESET_REG_FLAG_MASTER_DISABLED,
IWM_CSR_RESET_REG_FLAG_MASTER_DISABLED, 100))
device_printf(sc->sc_dev, "timeout waiting for master\n");
/*
* Clear "initialization complete" bit to move adapter from
* D0A* (powered-up Active) --> D0U* (Uninitialized) state.
*/
IWM_CLRBITS(sc, IWM_CSR_GP_CNTRL,
IWM_CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
IWM_DPRINTF(sc, IWM_DEBUG_TRANS, "%s: iwm apm stop\n", __func__);
}
/* iwlwifi pcie/trans.c */
int
iwm_start_hw(struct iwm_softc *sc)
{
int error;
if ((error = iwm_prepare_card_hw(sc)) != 0)
return error;
/* Reset the entire device */
IWM_WRITE(sc, IWM_CSR_RESET, IWM_CSR_RESET_REG_FLAG_SW_RESET);
DELAY(5000);
if ((error = iwm_apm_init(sc)) != 0)
return error;
/* On newer chipsets MSI is disabled by default. */
if (sc->cfg->mqrx_supported)
iwm_write_prph(sc, IWM_UREG_CHICK, IWM_UREG_CHICK_MSI_ENABLE);
iwm_enable_rfkill_int(sc);
iwm_check_rfkill(sc);
return 0;
}
/* iwlwifi pcie/trans.c (always main power) */
void
iwm_set_pwr(struct iwm_softc *sc)
{
iwm_set_bits_mask_prph(sc, IWM_APMG_PS_CTRL_REG,
IWM_APMG_PS_CTRL_VAL_PWR_SRC_VMAIN, ~IWM_APMG_PS_CTRL_MSK_PWR_SRC);
}
/* iwlwifi pcie/rx.c */
int
iwm_pcie_rx_stop(struct iwm_softc *sc)
{
int ret;
ret = 0;
if (iwm_nic_lock(sc)) {
if (sc->cfg->mqrx_supported) {
iwm_write_prph(sc, IWM_RFH_RXF_DMA_CFG, 0);
ret = iwm_poll_prph(sc, IWM_RFH_GEN_STATUS,
IWM_RXF_DMA_IDLE, IWM_RXF_DMA_IDLE, 1000);
} else {
IWM_WRITE(sc, IWM_FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
ret = iwm_poll_bit(sc, IWM_FH_MEM_RSSR_RX_STATUS_REG,
IWM_FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE,
IWM_FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE,
1000);
}
iwm_nic_unlock(sc);
}
return ret;
}
void
iwm_pcie_clear_cmd_in_flight(struct iwm_softc *sc)
{
if (!sc->cfg->apmg_wake_up_wa)
return;
if (!sc->cmd_hold_nic_awake) {
device_printf(sc->sc_dev,
"%s: cmd_hold_nic_awake not set\n", __func__);
return;
}
sc->cmd_hold_nic_awake = 0;
IWM_CLRBITS(sc, IWM_CSR_GP_CNTRL,
IWM_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
}
int
iwm_pcie_set_cmd_in_flight(struct iwm_softc *sc)
{
int ret;
/*
* wake up the NIC to make sure that the firmware will see the host
* command - we will let the NIC sleep once all the host commands
* returned. This needs to be done only on NICs that have
* apmg_wake_up_wa set.
*/
if (sc->cfg->apmg_wake_up_wa &&
!sc->cmd_hold_nic_awake) {
IWM_SETBITS(sc, IWM_CSR_GP_CNTRL,
IWM_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
ret = iwm_poll_bit(sc, IWM_CSR_GP_CNTRL,
IWM_CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
(IWM_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
IWM_CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP),
15000);
if (ret == 0) {
IWM_CLRBITS(sc, IWM_CSR_GP_CNTRL,
IWM_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
device_printf(sc->sc_dev,
"%s: Failed to wake NIC for hcmd\n", __func__);
return EIO;
}
sc->cmd_hold_nic_awake = 1;
}
return 0;
}

View File

@ -1,139 +0,0 @@
/* $FreeBSD$ */
/*
* Copyright (c) 2014 genua mbh <info@genua.de>
* Copyright (c) 2014 Fixup Software Ltd.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)
*
***********************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*-
* Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef __IWM_PCIE_TRANS_H__
#define __IWM_PCIE_TRANS_H__
extern uint32_t iwm_read_prph(struct iwm_softc *sc, uint32_t addr);
extern void iwm_write_prph(struct iwm_softc *sc, uint32_t addr, uint32_t val);
extern void iwm_write_prph64(struct iwm_softc *sc, uint64_t addr,
uint64_t val);
extern int iwm_poll_prph(struct iwm_softc *sc, uint32_t addr, uint32_t bits,
uint32_t mask, int timeout);
extern int iwm_read_mem(struct iwm_softc *sc, uint32_t addr, void *buf, int dwords);
extern int iwm_write_mem(struct iwm_softc *sc, uint32_t addr, const void *buf,
int dwords);
extern int iwm_write_mem32(struct iwm_softc *sc, uint32_t addr, uint32_t val);
extern int iwm_poll_bit(struct iwm_softc *sc, int reg,
uint32_t bits, uint32_t mask, int timo);
extern int iwm_nic_lock(struct iwm_softc *sc);
extern void iwm_nic_unlock(struct iwm_softc *sc);
extern void iwm_set_bits_mask_prph(struct iwm_softc *sc,
uint32_t reg, uint32_t bits, uint32_t mask);
extern void iwm_set_bits_prph(struct iwm_softc *sc, uint32_t reg, uint32_t bits);
extern void iwm_clear_bits_prph(struct iwm_softc *sc, uint32_t reg, uint32_t bits);
extern void iwm_enable_rfkill_int(struct iwm_softc *sc);
extern int iwm_check_rfkill(struct iwm_softc *sc);
extern int iwm_set_hw_ready(struct iwm_softc *sc);
extern int iwm_prepare_card_hw(struct iwm_softc *sc);
extern void iwm_apm_config(struct iwm_softc *sc);
extern int iwm_apm_init(struct iwm_softc *sc);
extern void iwm_apm_stop(struct iwm_softc *sc);
extern int iwm_start_hw(struct iwm_softc *sc);
extern void iwm_set_pwr(struct iwm_softc *sc);
extern int iwm_pcie_rx_stop(struct iwm_softc *sc);
extern int iwm_pcie_set_cmd_in_flight(struct iwm_softc *sc);
extern void iwm_pcie_clear_cmd_in_flight(struct iwm_softc *sc);
#endif

View File

@ -1,320 +0,0 @@
/* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
/*
* Copyright (c) 2014 genua mbh <info@genua.de>
* Copyright (c) 2014 Fixup Software Ltd.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)
*
***********************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*-
* Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include "opt_iwm.h"
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/endian.h>
#include <sys/firmware.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/mutex.h>
#include <sys/module.h>
#include <sys/proc.h>
#include <sys/rman.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/sysctl.h>
#include <sys/linker.h>
#include <machine/bus.h>
#include <machine/endian.h>
#include <machine/resource.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <net/bpf.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_arp.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_types.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/if_ether.h>
#include <netinet/ip.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_regdomain.h>
#include <net80211/ieee80211_ratectl.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/iwm/if_iwmreg.h>
#include <dev/iwm/if_iwmvar.h>
#include <dev/iwm/if_iwm_debug.h>
#include <dev/iwm/if_iwm_util.h>
#include <dev/iwm/if_iwm_phy_ctxt.h>
/*
* BEGIN iwlwifi/mvm/phy-ctxt.c
*/
/*
* Construct the generic fields of the PHY context command
*/
static void
iwm_phy_ctxt_cmd_hdr(struct iwm_softc *sc, struct iwm_phy_ctxt *ctxt,
struct iwm_phy_context_cmd *cmd, uint32_t action, uint32_t apply_time)
{
memset(cmd, 0, sizeof(struct iwm_phy_context_cmd));
IWM_DPRINTF(sc, IWM_DEBUG_RESET | IWM_DEBUG_CMD,
"%s: id=%d, colour=%d, action=%d, apply_time=%d\n",
__func__,
ctxt->id,
ctxt->color,
action,
apply_time);
cmd->id_and_color = htole32(IWM_FW_CMD_ID_AND_COLOR(ctxt->id,
ctxt->color));
cmd->action = htole32(action);
cmd->apply_time = htole32(apply_time);
}
/*
* Add the phy configuration to the PHY context command
*/
static void
iwm_phy_ctxt_cmd_data(struct iwm_softc *sc,
struct iwm_phy_context_cmd *cmd, struct ieee80211_channel *chan,
uint8_t chains_static, uint8_t chains_dynamic)
{
struct ieee80211com *ic = &sc->sc_ic;
uint8_t active_cnt, idle_cnt;
IWM_DPRINTF(sc, IWM_DEBUG_RESET | IWM_DEBUG_CMD,
"%s: 2ghz=%d, channel=%d, chains static=0x%x, dynamic=0x%x, "
"rx_ant=0x%x, tx_ant=0x%x\n",
__func__,
!! IEEE80211_IS_CHAN_2GHZ(chan),
ieee80211_chan2ieee(ic, chan),
chains_static,
chains_dynamic,
iwm_get_valid_rx_ant(sc),
iwm_get_valid_tx_ant(sc));
cmd->ci.band = IEEE80211_IS_CHAN_2GHZ(chan) ?
IWM_PHY_BAND_24 : IWM_PHY_BAND_5;
cmd->ci.channel = ieee80211_chan2ieee(ic, chan);
cmd->ci.width = IWM_PHY_VHT_CHANNEL_MODE20;
cmd->ci.ctrl_pos = IWM_PHY_VHT_CTRL_POS_1_BELOW;
/* Set rx the chains */
idle_cnt = chains_static;
active_cnt = chains_dynamic;
/* In scenarios where we only ever use a single-stream rates,
* i.e. legacy 11b/g/a associations, single-stream APs or even
* static SMPS, enable both chains to get diversity, improving
* the case where we're far enough from the AP that attenuation
* between the two antennas is sufficiently different to impact
* performance.
*/
if (active_cnt == 1 && iwm_rx_diversity_allowed(sc)) {
idle_cnt = 2;
active_cnt = 2;
}
cmd->rxchain_info = htole32(iwm_get_valid_rx_ant(sc) <<
IWM_PHY_RX_CHAIN_VALID_POS);
cmd->rxchain_info |= htole32(idle_cnt << IWM_PHY_RX_CHAIN_CNT_POS);
cmd->rxchain_info |= htole32(active_cnt <<
IWM_PHY_RX_CHAIN_MIMO_CNT_POS);
cmd->txchain_info = htole32(iwm_get_valid_tx_ant(sc));
}
/*
* Send a command
* only if something in the configuration changed: in case that this is the
* first time that the phy configuration is applied or in case that the phy
* configuration changed from the previous apply.
*/
static int
iwm_phy_ctxt_apply(struct iwm_softc *sc,
struct iwm_phy_ctxt *ctxt,
uint8_t chains_static, uint8_t chains_dynamic,
uint32_t action, uint32_t apply_time)
{
struct iwm_phy_context_cmd cmd;
int ret;
IWM_DPRINTF(sc, IWM_DEBUG_RESET | IWM_DEBUG_CMD,
"%s: called; channel=%p\n",
__func__,
ctxt->channel);
/* Set the command header fields */
iwm_phy_ctxt_cmd_hdr(sc, ctxt, &cmd, action, apply_time);
/* Set the command data */
iwm_phy_ctxt_cmd_data(sc, &cmd, ctxt->channel,
chains_static, chains_dynamic);
ret = iwm_send_cmd_pdu(sc, IWM_PHY_CONTEXT_CMD, IWM_CMD_SYNC,
sizeof(struct iwm_phy_context_cmd), &cmd);
if (ret) {
device_printf(sc->sc_dev,
"PHY ctxt cmd error. ret=%d\n", ret);
}
return ret;
}
/*
* Send a command to add a PHY context based on the current HW configuration.
*/
int
iwm_phy_ctxt_add(struct iwm_softc *sc, struct iwm_phy_ctxt *ctxt,
struct ieee80211_channel *chan,
uint8_t chains_static, uint8_t chains_dynamic)
{
ctxt->channel = chan;
IWM_DPRINTF(sc, IWM_DEBUG_RESET | IWM_DEBUG_CMD,
"%s: called; channel=%d\n",
__func__,
ieee80211_chan2ieee(&sc->sc_ic, chan));
return iwm_phy_ctxt_apply(sc, ctxt,
chains_static, chains_dynamic, IWM_FW_CTXT_ACTION_ADD, 0);
}
/*
* Send a command to modify the PHY context based on the current HW
* configuration. Note that the function does not check that the configuration
* changed.
*/
int
iwm_phy_ctxt_changed(struct iwm_softc *sc,
struct iwm_phy_ctxt *ctxt, struct ieee80211_channel *chan,
uint8_t chains_static, uint8_t chains_dynamic)
{
ctxt->channel = chan;
IWM_DPRINTF(sc, IWM_DEBUG_RESET | IWM_DEBUG_CMD,
"%s: called; channel=%d\n",
__func__,
ieee80211_chan2ieee(&sc->sc_ic, chan));
return iwm_phy_ctxt_apply(sc, ctxt,
chains_static, chains_dynamic, IWM_FW_CTXT_ACTION_MODIFY, 0);
}
/*
* END iwlwifi/mvm/phy-ctxt.c
*/

View File

@ -1,117 +0,0 @@
/* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
/* $FreeBSD$ */
/*
* Copyright (c) 2014 genua mbh <info@genua.de>
* Copyright (c) 2014 Fixup Software Ltd.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)
*
***********************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*-
* Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef __IF_IWM_PHY_CTXT_H__
#define __IF_IWM_PHY_CTXT_H__
extern int iwm_phy_ctxt_add(struct iwm_softc *sc,
struct iwm_phy_ctxt *ctxt,
struct ieee80211_channel *chan,
uint8_t chains_static, uint8_t chains_dynamic);
extern int iwm_phy_ctxt_changed(struct iwm_softc *sc,
struct iwm_phy_ctxt *ctxt, struct ieee80211_channel *chan,
uint8_t chains_static, uint8_t chains_dynamic);
#endif /* __IF_IWM_PHY_CTXT_H__ */

View File

@ -1,612 +0,0 @@
/* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
/*
* Copyright (c) 2014 genua mbh <info@genua.de>
* Copyright (c) 2014 Fixup Software Ltd.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)
*
***********************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*-
* Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include "opt_iwm.h"
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/endian.h>
#include <sys/firmware.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/mutex.h>
#include <sys/module.h>
#include <sys/proc.h>
#include <sys/rman.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/sysctl.h>
#include <sys/linker.h>
#include <machine/bus.h>
#include <machine/endian.h>
#include <machine/resource.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <net/bpf.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_arp.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_types.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/if_ether.h>
#include <netinet/ip.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_regdomain.h>
#include <net80211/ieee80211_ratectl.h>
#include <net80211/ieee80211_radiotap.h>
#include "if_iwmreg.h"
#include "if_iwmvar.h"
#include "if_iwm_debug.h"
#include "if_iwm_util.h"
#include "if_iwm_phy_db.h"
#define CHANNEL_NUM_SIZE 4 /* num of channels in calib_ch size */
struct iwm_phy_db_entry {
uint16_t size;
uint8_t *data;
};
/**
* struct iwm_phy_db - stores phy configuration and calibration data.
*
* @cfg: phy configuration.
* @calib_nch: non channel specific calibration data.
* @calib_ch: channel specific calibration data.
* @n_group_papd: number of entries in papd channel group.
* @calib_ch_group_papd: calibration data related to papd channel group.
* @n_group_txp: number of entries in tx power channel group.
* @calib_ch_group_txp: calibration data related to tx power chanel group.
*/
struct iwm_phy_db {
struct iwm_phy_db_entry cfg;
struct iwm_phy_db_entry calib_nch;
int n_group_papd;
struct iwm_phy_db_entry *calib_ch_group_papd;
int n_group_txp;
struct iwm_phy_db_entry *calib_ch_group_txp;
struct iwm_softc *sc;
};
enum iwm_phy_db_section_type {
IWM_PHY_DB_CFG = 1,
IWM_PHY_DB_CALIB_NCH,
IWM_PHY_DB_UNUSED,
IWM_PHY_DB_CALIB_CHG_PAPD,
IWM_PHY_DB_CALIB_CHG_TXP,
IWM_PHY_DB_MAX
};
#define PHY_DB_CMD 0x6c
/*
* phy db - configure operational ucode
*/
struct iwm_phy_db_cmd {
uint16_t type;
uint16_t length;
uint8_t data[0];
} __packed;
/* for parsing of tx power channel group data that comes from the firmware*/
struct iwm_phy_db_chg_txp {
uint32_t space;
uint16_t max_channel_idx;
} __packed;
/*
* phy db - Receive phy db chunk after calibrations
*/
struct iwm_calib_res_notif_phy_db {
uint16_t type;
uint16_t length;
uint8_t data[0];
} __packed;
struct iwm_phy_db *
iwm_phy_db_init(struct iwm_softc *sc)
{
struct iwm_phy_db *phy_db = malloc(sizeof(struct iwm_phy_db),
M_DEVBUF, M_NOWAIT | M_ZERO);
if (!phy_db)
return phy_db;
phy_db->sc = sc;
phy_db->n_group_txp = -1;
phy_db->n_group_papd = -1;
/* TODO: add default values of the phy db. */
return phy_db;
}
/*
* get phy db section: returns a pointer to a phy db section specified by
* type and channel group id.
*/
static struct iwm_phy_db_entry *
iwm_phy_db_get_section(struct iwm_phy_db *phy_db,
enum iwm_phy_db_section_type type,
uint16_t chg_id)
{
if (!phy_db || type >= IWM_PHY_DB_MAX)
return NULL;
switch (type) {
case IWM_PHY_DB_CFG:
return &phy_db->cfg;
case IWM_PHY_DB_CALIB_NCH:
return &phy_db->calib_nch;
case IWM_PHY_DB_CALIB_CHG_PAPD:
if (chg_id >= phy_db->n_group_papd)
return NULL;
return &phy_db->calib_ch_group_papd[chg_id];
case IWM_PHY_DB_CALIB_CHG_TXP:
if (chg_id >= phy_db->n_group_txp)
return NULL;
return &phy_db->calib_ch_group_txp[chg_id];
default:
return NULL;
}
return NULL;
}
static void
iwm_phy_db_free_section(struct iwm_phy_db *phy_db,
enum iwm_phy_db_section_type type, uint16_t chg_id)
{
struct iwm_phy_db_entry *entry =
iwm_phy_db_get_section(phy_db, type, chg_id);
if (!entry)
return;
if (entry->data != NULL)
free(entry->data, M_DEVBUF);
entry->data = NULL;
entry->size = 0;
}
void
iwm_phy_db_free(struct iwm_phy_db *phy_db)
{
int i;
if (!phy_db)
return;
iwm_phy_db_free_section(phy_db, IWM_PHY_DB_CFG, 0);
iwm_phy_db_free_section(phy_db, IWM_PHY_DB_CALIB_NCH, 0);
for (i = 0; i < phy_db->n_group_papd; i++)
iwm_phy_db_free_section(phy_db, IWM_PHY_DB_CALIB_CHG_PAPD, i);
if (phy_db->calib_ch_group_papd != NULL)
free(phy_db->calib_ch_group_papd, M_DEVBUF);
for (i = 0; i < phy_db->n_group_txp; i++)
iwm_phy_db_free_section(phy_db, IWM_PHY_DB_CALIB_CHG_TXP, i);
if (phy_db->calib_ch_group_txp != NULL)
free(phy_db->calib_ch_group_txp, M_DEVBUF);
free(phy_db, M_DEVBUF);
}
int
iwm_phy_db_set_section(struct iwm_phy_db *phy_db,
struct iwm_rx_packet *pkt)
{
struct iwm_calib_res_notif_phy_db *phy_db_notif =
(struct iwm_calib_res_notif_phy_db *)pkt->data;
enum iwm_phy_db_section_type type = le16toh(phy_db_notif->type);
uint16_t size = le16toh(phy_db_notif->length);
struct iwm_phy_db_entry *entry;
uint16_t chg_id = 0;
if (!phy_db)
return EINVAL;
if (type == IWM_PHY_DB_CALIB_CHG_PAPD) {
chg_id = le16toh(*(uint16_t *)phy_db_notif->data);
if (phy_db && !phy_db->calib_ch_group_papd) {
/*
* Firmware sends the largest index first, so we can use
* it to know how much we should allocate.
*/
phy_db->calib_ch_group_papd = malloc(
(chg_id + 1) * sizeof(struct iwm_phy_db_entry),
M_DEVBUF, M_NOWAIT | M_ZERO);
if (!phy_db->calib_ch_group_papd)
return ENOMEM;
phy_db->n_group_papd = chg_id + 1;
}
} else if (type == IWM_PHY_DB_CALIB_CHG_TXP) {
chg_id = le16toh(*(uint16_t *)phy_db_notif->data);
if (phy_db && !phy_db->calib_ch_group_txp) {
/*
* Firmware sends the largest index first, so we can use
* it to know how much we should allocate.
*/
phy_db->calib_ch_group_txp = malloc(
(chg_id + 1) * sizeof(struct iwm_phy_db_entry),
M_DEVBUF, M_NOWAIT | M_ZERO);
if (!phy_db->calib_ch_group_txp)
return ENOMEM;
phy_db->n_group_txp = chg_id + 1;
}
}
entry = iwm_phy_db_get_section(phy_db, type, chg_id);
if (!entry)
return EINVAL;
if (entry->data != NULL)
free(entry->data, M_DEVBUF);
entry->data = malloc(size, M_DEVBUF, M_NOWAIT);
if (!entry->data) {
entry->size = 0;
return ENOMEM;
}
memcpy(entry->data, phy_db_notif->data, size);
entry->size = size;
IWM_DPRINTF(phy_db->sc, IWM_DEBUG_RESET,
"%s(%d): [PHYDB]SET: Type %d , Size: %d\n",
__func__, __LINE__, type, size);
return 0;
}
static int
is_valid_channel(uint16_t ch_id)
{
if (ch_id <= 14 ||
(36 <= ch_id && ch_id <= 64 && ch_id % 4 == 0) ||
(100 <= ch_id && ch_id <= 140 && ch_id % 4 == 0) ||
(145 <= ch_id && ch_id <= 165 && ch_id % 4 == 1))
return 1;
return 0;
}
static uint8_t
ch_id_to_ch_index(uint16_t ch_id)
{
if (!is_valid_channel(ch_id))
return 0xff;
if (ch_id <= 14)
return ch_id - 1;
if (ch_id <= 64)
return (ch_id + 20) / 4;
if (ch_id <= 140)
return (ch_id - 12) / 4;
return (ch_id - 13) / 4;
}
static uint16_t
channel_id_to_papd(uint16_t ch_id)
{
if (!is_valid_channel(ch_id))
return 0xff;
if (1 <= ch_id && ch_id <= 14)
return 0;
if (36 <= ch_id && ch_id <= 64)
return 1;
if (100 <= ch_id && ch_id <= 140)
return 2;
return 3;
}
static uint16_t
channel_id_to_txp(struct iwm_phy_db *phy_db, uint16_t ch_id)
{
struct iwm_phy_db_chg_txp *txp_chg;
int i;
uint8_t ch_index = ch_id_to_ch_index(ch_id);
if (ch_index == 0xff)
return 0xff;
for (i = 0; i < phy_db->n_group_txp; i++) {
txp_chg = (void *)phy_db->calib_ch_group_txp[i].data;
if (!txp_chg)
return 0xff;
/*
* Looking for the first channel group that its max channel is
* higher then wanted channel.
*/
if (le16toh(txp_chg->max_channel_idx) >= ch_index)
return i;
}
return 0xff;
}
static int
iwm_phy_db_get_section_data(struct iwm_phy_db *phy_db,
uint32_t type, uint8_t **data, uint16_t *size,
uint16_t ch_id)
{
struct iwm_phy_db_entry *entry;
uint16_t ch_group_id = 0;
if (!phy_db)
return EINVAL;
/* find wanted channel group */
if (type == IWM_PHY_DB_CALIB_CHG_PAPD)
ch_group_id = channel_id_to_papd(ch_id);
else if (type == IWM_PHY_DB_CALIB_CHG_TXP)
ch_group_id = channel_id_to_txp(phy_db, ch_id);
entry = iwm_phy_db_get_section(phy_db, type, ch_group_id);
if (!entry)
return EINVAL;
*data = entry->data;
*size = entry->size;
IWM_DPRINTF(phy_db->sc, IWM_DEBUG_RESET,
"%s(%d): [PHYDB] GET: Type %d , Size: %d\n",
__func__, __LINE__, type, *size);
return 0;
}
static int
iwm_send_phy_db_cmd(struct iwm_phy_db *phy_db, uint16_t type,
uint16_t length, void *data)
{
struct iwm_phy_db_cmd phy_db_cmd;
struct iwm_host_cmd cmd = {
.id = PHY_DB_CMD,
};
IWM_DPRINTF(phy_db->sc, IWM_DEBUG_RESET,
"Sending PHY-DB hcmd of type %d, of length %d\n",
type, length);
/* Set phy db cmd variables */
phy_db_cmd.type = htole16(type);
phy_db_cmd.length = htole16(length);
/* Set hcmd variables */
cmd.data[0] = &phy_db_cmd;
cmd.len[0] = sizeof(struct iwm_phy_db_cmd);
cmd.data[1] = data;
cmd.len[1] = length;
#ifdef notyet
cmd.dataflags[1] = IWM_HCMD_DFL_NOCOPY;
#endif
return iwm_send_cmd(phy_db->sc, &cmd);
}
static int
iwm_phy_db_send_all_channel_groups(struct iwm_phy_db *phy_db,
enum iwm_phy_db_section_type type,
uint8_t max_ch_groups)
{
uint16_t i;
int err;
struct iwm_phy_db_entry *entry;
/* Send all the channel specific groups to operational fw */
for (i = 0; i < max_ch_groups; i++) {
entry = iwm_phy_db_get_section(phy_db,
type,
i);
if (!entry)
return EINVAL;
if (!entry->size)
continue;
/* Send the requested PHY DB section */
err = iwm_send_phy_db_cmd(phy_db,
type,
entry->size,
entry->data);
if (err) {
device_printf(phy_db->sc->sc_dev,
"Can't SEND phy_db section %d (%d), err %d\n",
type, i, err);
return err;
}
IWM_DPRINTF(phy_db->sc, IWM_DEBUG_CMD,
"Sent PHY_DB HCMD, type = %d num = %d\n", type, i);
}
return 0;
}
int
iwm_send_phy_db_data(struct iwm_phy_db *phy_db)
{
uint8_t *data = NULL;
uint16_t size = 0;
int err;
IWM_DPRINTF(phy_db->sc, IWM_DEBUG_CMD | IWM_DEBUG_RESET,
"%s: Sending phy db data and configuration to runtime image\n",
__func__);
/* Send PHY DB CFG section */
err = iwm_phy_db_get_section_data(phy_db, IWM_PHY_DB_CFG,
&data, &size, 0);
if (err) {
device_printf(phy_db->sc->sc_dev,
"%s: Cannot get Phy DB cfg section, %d\n",
__func__, err);
return err;
}
err = iwm_send_phy_db_cmd(phy_db, IWM_PHY_DB_CFG, size, data);
if (err) {
device_printf(phy_db->sc->sc_dev,
"%s: Cannot send HCMD of Phy DB cfg section, %d\n",
__func__, err);
return err;
}
err = iwm_phy_db_get_section_data(phy_db, IWM_PHY_DB_CALIB_NCH,
&data, &size, 0);
if (err) {
device_printf(phy_db->sc->sc_dev,
"%s: Cannot get Phy DB non specific channel section, "
"%d\n", __func__, err);
return err;
}
err = iwm_send_phy_db_cmd(phy_db, IWM_PHY_DB_CALIB_NCH, size, data);
if (err) {
device_printf(phy_db->sc->sc_dev,
"%s: Cannot send HCMD of Phy DB non specific channel "
"sect, %d\n", __func__, err);
return err;
}
/* Send all the TXP channel specific data */
err = iwm_phy_db_send_all_channel_groups(phy_db,
IWM_PHY_DB_CALIB_CHG_PAPD, phy_db->n_group_papd);
if (err) {
device_printf(phy_db->sc->sc_dev,
"%s: Cannot send channel specific PAPD groups, %d\n",
__func__, err);
return err;
}
/* Send all the TXP channel specific data */
err = iwm_phy_db_send_all_channel_groups(phy_db,
IWM_PHY_DB_CALIB_CHG_TXP, phy_db->n_group_txp);
if (err) {
device_printf(phy_db->sc->sc_dev,
"%s: Cannot send channel specific TX power groups, "
"%d\n", __func__, err);
return err;
}
IWM_DPRINTF(phy_db->sc, IWM_DEBUG_CMD | IWM_DEBUG_RESET,
"%s: Finished sending phy db non channel data\n",
__func__);
return 0;
}

View File

@ -1,117 +0,0 @@
/* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
/* $FreeBSD$ */
/*
* Copyright (c) 2014 genua mbh <info@genua.de>
* Copyright (c) 2014 Fixup Software Ltd.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)
*
***********************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*-
* Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef __IF_IWM_PHY_DB_H__
#define __IF_IWM_PHY_DB_H__
struct iwm_calib_res_notif_phy_db;
extern struct iwm_phy_db *iwm_phy_db_init(struct iwm_softc *sc);
extern void iwm_phy_db_free(struct iwm_phy_db *phy_db);
extern int iwm_phy_db_set_section(struct iwm_phy_db *phy_db,
struct iwm_rx_packet *pkt);
extern int iwm_send_phy_db_data(struct iwm_phy_db *phy_db);
#endif /* __IF_IWM_PHY_DB_H__ */

View File

@ -1,489 +0,0 @@
/* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
/*
* Copyright (c) 2014 genua mbh <info@genua.de>
* Copyright (c) 2014 Fixup Software Ltd.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)
*
***********************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include "opt_iwm.h"
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/endian.h>
#include <sys/firmware.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/mutex.h>
#include <sys/module.h>
#include <sys/proc.h>
#include <sys/rman.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/sysctl.h>
#include <sys/linker.h>
#include <machine/bus.h>
#include <machine/endian.h>
#include <machine/resource.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <net/bpf.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_arp.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_types.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/if_ether.h>
#include <netinet/ip.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_regdomain.h>
#include <net80211/ieee80211_ratectl.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/iwm/if_iwmreg.h>
#include <dev/iwm/if_iwmvar.h>
#include <dev/iwm/if_iwm_debug.h>
#include <dev/iwm/if_iwm_constants.h>
#include <dev/iwm/if_iwm_util.h>
#include <dev/iwm/if_iwm_power.h>
static int iwm_power_scheme = IWM_POWER_SCHEME_BPS;
TUNABLE_INT("hw.iwm.power_scheme", &iwm_power_scheme);
/*
* BEGIN mvm/power.c
*/
#define IWM_POWER_KEEP_ALIVE_PERIOD_SEC 25
static int
iwm_beacon_filter_send_cmd(struct iwm_softc *sc,
struct iwm_beacon_filter_cmd *cmd)
{
int ret;
ret = iwm_send_cmd_pdu(sc, IWM_REPLY_BEACON_FILTERING_CMD,
0, sizeof(struct iwm_beacon_filter_cmd), cmd);
if (!ret) {
IWM_DPRINTF(sc, IWM_DEBUG_PWRSAVE | IWM_DEBUG_CMD,
"ba_enable_beacon_abort is: %d\n",
le32toh(cmd->ba_enable_beacon_abort));
IWM_DPRINTF(sc, IWM_DEBUG_PWRSAVE | IWM_DEBUG_CMD,
"ba_escape_timer is: %d\n",
le32toh(cmd->ba_escape_timer));
IWM_DPRINTF(sc, IWM_DEBUG_PWRSAVE | IWM_DEBUG_CMD,
"bf_debug_flag is: %d\n",
le32toh(cmd->bf_debug_flag));
IWM_DPRINTF(sc, IWM_DEBUG_PWRSAVE | IWM_DEBUG_CMD,
"bf_enable_beacon_filter is: %d\n",
le32toh(cmd->bf_enable_beacon_filter));
IWM_DPRINTF(sc, IWM_DEBUG_PWRSAVE | IWM_DEBUG_CMD,
"bf_energy_delta is: %d\n",
le32toh(cmd->bf_energy_delta));
IWM_DPRINTF(sc, IWM_DEBUG_PWRSAVE | IWM_DEBUG_CMD,
"bf_escape_timer is: %d\n",
le32toh(cmd->bf_escape_timer));
IWM_DPRINTF(sc, IWM_DEBUG_PWRSAVE | IWM_DEBUG_CMD,
"bf_roaming_energy_delta is: %d\n",
le32toh(cmd->bf_roaming_energy_delta));
IWM_DPRINTF(sc, IWM_DEBUG_PWRSAVE | IWM_DEBUG_CMD,
"bf_roaming_state is: %d\n",
le32toh(cmd->bf_roaming_state));
IWM_DPRINTF(sc, IWM_DEBUG_PWRSAVE | IWM_DEBUG_CMD,
"bf_temp_threshold is: %d\n",
le32toh(cmd->bf_temp_threshold));
IWM_DPRINTF(sc, IWM_DEBUG_PWRSAVE | IWM_DEBUG_CMD,
"bf_temp_fast_filter is: %d\n",
le32toh(cmd->bf_temp_fast_filter));
IWM_DPRINTF(sc, IWM_DEBUG_PWRSAVE | IWM_DEBUG_CMD,
"bf_temp_slow_filter is: %d\n",
le32toh(cmd->bf_temp_slow_filter));
}
return ret;
}
static void
iwm_beacon_filter_set_cqm_params(struct iwm_softc *sc,
struct iwm_vap *ivp, struct iwm_beacon_filter_cmd *cmd)
{
cmd->ba_enable_beacon_abort = htole32(sc->sc_bf.ba_enabled);
}
static void
iwm_power_log(struct iwm_softc *sc, struct iwm_mac_power_cmd *cmd)
{
IWM_DPRINTF(sc, IWM_DEBUG_PWRSAVE | IWM_DEBUG_CMD,
"Sending power table command on mac id 0x%X for "
"power level %d, flags = 0x%X\n",
cmd->id_and_color, iwm_power_scheme, le16toh(cmd->flags));
IWM_DPRINTF(sc, IWM_DEBUG_PWRSAVE | IWM_DEBUG_CMD,
"Keep alive = %u sec\n", le16toh(cmd->keep_alive_seconds));
if (!(cmd->flags & htole16(IWM_POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK))) {
IWM_DPRINTF(sc, IWM_DEBUG_PWRSAVE | IWM_DEBUG_CMD,
"Disable power management\n");
return;
}
IWM_DPRINTF(sc, IWM_DEBUG_PWRSAVE | IWM_DEBUG_CMD,
"Rx timeout = %u usec\n", le32toh(cmd->rx_data_timeout));
IWM_DPRINTF(sc, IWM_DEBUG_PWRSAVE | IWM_DEBUG_CMD,
"Tx timeout = %u usec\n", le32toh(cmd->tx_data_timeout));
if (cmd->flags & htole16(IWM_POWER_FLAGS_SKIP_OVER_DTIM_MSK))
IWM_DPRINTF(sc, IWM_DEBUG_PWRSAVE | IWM_DEBUG_CMD,
"DTIM periods to skip = %u\n", cmd->skip_dtim_periods);
}
static boolean_t
iwm_power_is_radar(struct iwm_softc *sc)
{
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_channel *chan;
boolean_t radar_detect = FALSE;
chan = ic->ic_bsschan;
if (chan == IEEE80211_CHAN_ANYC ||
(chan->ic_flags & IEEE80211_CHAN_DFS) != 0) {
radar_detect = TRUE;
}
return radar_detect;
}
static void
iwm_power_config_skip_dtim(struct iwm_softc *sc,
struct iwm_mac_power_cmd *cmd)
{
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
int dtimper = vap->iv_dtim_period ?: 1;
int skip;
/* disable, in case we're supposed to override */
cmd->skip_dtim_periods = 0;
cmd->flags &= ~htole16(IWM_POWER_FLAGS_SKIP_OVER_DTIM_MSK);
if (iwm_power_is_radar(sc))
return;
if (dtimper >= 10)
return;
/* TODO: check that multicast wake lock is off */
if (iwm_power_scheme != IWM_POWER_SCHEME_LP)
return;
skip = 2;
/* the firmware really expects "look at every X DTIMs", so add 1 */
cmd->skip_dtim_periods = 1 + skip;
cmd->flags |= htole16(IWM_POWER_FLAGS_SKIP_OVER_DTIM_MSK);
}
static void
iwm_power_build_cmd(struct iwm_softc *sc, struct iwm_vap *ivp,
struct iwm_mac_power_cmd *cmd)
{
struct ieee80211vap *vap = &ivp->iv_vap;
struct ieee80211_node *ni = vap->iv_bss;
int dtimper, dtimper_msec;
int keep_alive;
boolean_t bss_conf_ps = FALSE;
cmd->id_and_color = htole32(IWM_FW_CMD_ID_AND_COLOR(ivp->id,
ivp->color));
dtimper = vap->iv_dtim_period ?: 1;
/*
* Regardless of power management state the driver must set
* keep alive period. FW will use it for sending keep alive NDPs
* immediately after association. Check that keep alive period
* is at least 3 * DTIM
*/
dtimper_msec = dtimper * ni->ni_intval;
keep_alive
= imax(3 * dtimper_msec, 1000 * IWM_POWER_KEEP_ALIVE_PERIOD_SEC);
keep_alive = roundup(keep_alive, 1000) / 1000;
cmd->keep_alive_seconds = htole16(keep_alive);
if (sc->sc_ps_disabled)
return;
cmd->flags |= htole16(IWM_POWER_FLAGS_POWER_SAVE_ENA_MSK);
if (IWM_NODE(ni)->in_assoc &&
(vap->iv_flags & IEEE80211_F_PMGTON) != 0) {
bss_conf_ps = TRUE;
}
if (!bss_conf_ps)
return;
cmd->flags |= htole16(IWM_POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK);
iwm_power_config_skip_dtim(sc, cmd);
cmd->rx_data_timeout =
htole32(IWM_DEFAULT_PS_RX_DATA_TIMEOUT);
cmd->tx_data_timeout =
htole32(IWM_DEFAULT_PS_TX_DATA_TIMEOUT);
}
static int
iwm_power_send_cmd(struct iwm_softc *sc, struct iwm_vap *ivp)
{
struct iwm_mac_power_cmd cmd = {};
iwm_power_build_cmd(sc, ivp, &cmd);
iwm_power_log(sc, &cmd);
return iwm_send_cmd_pdu(sc, IWM_MAC_PM_POWER_TABLE, 0,
sizeof(cmd), &cmd);
}
static int
_iwm_enable_beacon_filter(struct iwm_softc *sc, struct iwm_vap *ivp,
struct iwm_beacon_filter_cmd *cmd)
{
int ret;
iwm_beacon_filter_set_cqm_params(sc, ivp, cmd);
ret = iwm_beacon_filter_send_cmd(sc, cmd);
if (!ret)
sc->sc_bf.bf_enabled = 1;
return ret;
}
int
iwm_enable_beacon_filter(struct iwm_softc *sc, struct iwm_vap *ivp)
{
struct iwm_beacon_filter_cmd cmd = {
IWM_BF_CMD_CONFIG_DEFAULTS,
.bf_enable_beacon_filter = htole32(1),
};
return _iwm_enable_beacon_filter(sc, ivp, &cmd);
}
int
iwm_disable_beacon_filter(struct iwm_softc *sc)
{
struct iwm_beacon_filter_cmd cmd = {};
int ret;
ret = iwm_beacon_filter_send_cmd(sc, &cmd);
if (ret == 0)
sc->sc_bf.bf_enabled = 0;
return ret;
}
static int
iwm_power_set_ps(struct iwm_softc *sc)
{
struct ieee80211vap *vap;
boolean_t disable_ps;
int ret;
/* disable PS if CAM */
disable_ps = (iwm_power_scheme == IWM_POWER_SCHEME_CAM);
/* ...or if any of the vifs require PS to be off */
TAILQ_FOREACH(vap, &sc->sc_ic.ic_vaps, iv_next) {
struct iwm_vap *ivp = IWM_VAP(vap);
if (ivp->phy_ctxt != NULL && ivp->ps_disabled)
disable_ps = TRUE;
}
/* update device power state if it has changed */
if (sc->sc_ps_disabled != disable_ps) {
boolean_t old_ps_disabled = sc->sc_ps_disabled;
sc->sc_ps_disabled = disable_ps;
ret = iwm_power_update_device(sc);
if (ret) {
sc->sc_ps_disabled = old_ps_disabled;
return ret;
}
}
return 0;
}
static int
iwm_power_set_ba(struct iwm_softc *sc, struct iwm_vap *ivp)
{
struct iwm_beacon_filter_cmd cmd = {
IWM_BF_CMD_CONFIG_DEFAULTS,
.bf_enable_beacon_filter = htole32(1),
};
struct ieee80211vap *vap = &ivp->iv_vap;
struct ieee80211_node *ni = vap->iv_bss;
boolean_t bss_conf_ps = FALSE;
if (!sc->sc_bf.bf_enabled)
return 0;
if (ni != NULL && IWM_NODE(ni)->in_assoc &&
(vap->iv_flags & IEEE80211_F_PMGTON) != 0) {
bss_conf_ps = TRUE;
}
sc->sc_bf.ba_enabled = !sc->sc_ps_disabled && bss_conf_ps;
return _iwm_enable_beacon_filter(sc, ivp, &cmd);
}
int
iwm_power_update_ps(struct iwm_softc *sc)
{
struct ieee80211vap *vap = TAILQ_FIRST(&sc->sc_ic.ic_vaps);
int ret;
ret = iwm_power_set_ps(sc);
if (ret)
return ret;
if (vap != NULL)
return iwm_power_set_ba(sc, IWM_VAP(vap));
return 0;
}
int
iwm_power_update_mac(struct iwm_softc *sc)
{
struct ieee80211vap *vap = TAILQ_FIRST(&sc->sc_ic.ic_vaps);
int ret;
ret = iwm_power_set_ps(sc);
if (ret)
return ret;
if (vap != NULL) {
ret = iwm_power_send_cmd(sc, IWM_VAP(vap));
if (ret)
return ret;
}
if (vap != NULL)
return iwm_power_set_ba(sc, IWM_VAP(vap));
return 0;
}
int
iwm_power_update_device(struct iwm_softc *sc)
{
struct iwm_device_power_cmd cmd = {
.flags = 0,
};
if (iwm_power_scheme == IWM_POWER_SCHEME_CAM)
sc->sc_ps_disabled = TRUE;
if (!sc->sc_ps_disabled)
cmd.flags |= htole16(IWM_DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK);
IWM_DPRINTF(sc, IWM_DEBUG_PWRSAVE | IWM_DEBUG_CMD,
"Sending device power command with flags = 0x%X\n", cmd.flags);
return iwm_send_cmd_pdu(sc,
IWM_POWER_TABLE_CMD, 0, sizeof(cmd), &cmd);
}

View File

@ -1,100 +0,0 @@
/* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
/* $FreeBSD$ */
/*
* Copyright (c) 2014 genua mbh <info@genua.de>
* Copyright (c) 2014 Fixup Software Ltd.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)
*
***********************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __IF_IWM_POWER_H__
#define __IF_IWM_POWER_H__
extern int iwm_power_update_device(struct iwm_softc *sc);
extern int iwm_power_update_mac(struct iwm_softc *sc);
extern int iwm_power_update_ps(struct iwm_softc *sc);
extern int iwm_enable_beacon_filter(struct iwm_softc *sc,
struct iwm_vap *ivp);
extern int iwm_disable_beacon_filter(struct iwm_softc *sc);
#endif /* __IF_IWM_POWER_H__ */

View File

@ -1,919 +0,0 @@
/* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
/*
* Copyright (c) 2014 genua mbh <info@genua.de>
* Copyright (c) 2014 Fixup Software Ltd.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)
*
***********************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*-
* Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include "opt_iwm.h"
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/endian.h>
#include <sys/firmware.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/mutex.h>
#include <sys/module.h>
#include <sys/proc.h>
#include <sys/rman.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/sysctl.h>
#include <sys/linker.h>
#include <machine/bus.h>
#include <machine/endian.h>
#include <machine/resource.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <net/bpf.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_arp.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_types.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/if_ether.h>
#include <netinet/ip.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_regdomain.h>
#include <net80211/ieee80211_ratectl.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/iwm/if_iwmreg.h>
#include <dev/iwm/if_iwmvar.h>
#include <dev/iwm/if_iwm_debug.h>
#include <dev/iwm/if_iwm_notif_wait.h>
#include <dev/iwm/if_iwm_util.h>
#include <dev/iwm/if_iwm_scan.h>
/*
* BEGIN mvm/scan.c
*/
#define IWM_DENSE_EBS_SCAN_RATIO 5
#define IWM_SPARSE_EBS_SCAN_RATIO 1
static uint16_t
iwm_scan_rx_chain(struct iwm_softc *sc)
{
uint16_t rx_chain;
uint8_t rx_ant;
rx_ant = iwm_get_valid_rx_ant(sc);
rx_chain = rx_ant << IWM_PHY_RX_CHAIN_VALID_POS;
rx_chain |= rx_ant << IWM_PHY_RX_CHAIN_FORCE_MIMO_SEL_POS;
rx_chain |= rx_ant << IWM_PHY_RX_CHAIN_FORCE_SEL_POS;
rx_chain |= 0x1 << IWM_PHY_RX_CHAIN_DRIVER_FORCE_POS;
return htole16(rx_chain);
}
static uint32_t
iwm_scan_rxon_flags(struct ieee80211_channel *c)
{
if (IEEE80211_IS_CHAN_2GHZ(c))
return htole32(IWM_PHY_BAND_24);
else
return htole32(IWM_PHY_BAND_5);
}
static uint32_t
iwm_scan_rate_n_flags(struct iwm_softc *sc, int flags, int no_cck)
{
uint32_t tx_ant;
int i, ind;
for (i = 0, ind = sc->sc_scan_last_antenna;
i < IWM_RATE_MCS_ANT_NUM; i++) {
ind = (ind + 1) % IWM_RATE_MCS_ANT_NUM;
if (iwm_get_valid_tx_ant(sc) & (1 << ind)) {
sc->sc_scan_last_antenna = ind;
break;
}
}
tx_ant = (1 << sc->sc_scan_last_antenna) << IWM_RATE_MCS_ANT_POS;
if ((flags & IEEE80211_CHAN_2GHZ) && !no_cck)
return htole32(IWM_RATE_1M_PLCP | IWM_RATE_MCS_CCK_MSK |
tx_ant);
else
return htole32(IWM_RATE_6M_PLCP | tx_ant);
}
static inline boolean_t
iwm_rrm_scan_needed(struct iwm_softc *sc)
{
/* require rrm scan whenever the fw supports it */
return iwm_fw_has_capa(sc, IWM_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT);
}
#ifdef IWM_DEBUG
static const char *
iwm_ebs_status_str(enum iwm_scan_ebs_status status)
{
switch (status) {
case IWM_SCAN_EBS_SUCCESS:
return "successful";
case IWM_SCAN_EBS_INACTIVE:
return "inactive";
case IWM_SCAN_EBS_FAILED:
case IWM_SCAN_EBS_CHAN_NOT_FOUND:
default:
return "failed";
}
}
static const char *
iwm_offload_status_str(enum iwm_scan_offload_complete_status status)
{
return (status == IWM_SCAN_OFFLOAD_ABORTED) ? "aborted" : "completed";
}
#endif
void
iwm_rx_lmac_scan_complete_notif(struct iwm_softc *sc,
struct iwm_rx_packet *pkt)
{
struct iwm_periodic_scan_complete *scan_notif = (void *)pkt->data;
/* If this happens, the firmware has mistakenly sent an LMAC
* notification during UMAC scans -- warn and ignore it.
*/
if (iwm_fw_has_capa(sc, IWM_UCODE_TLV_CAPA_UMAC_SCAN)) {
device_printf(sc->sc_dev,
"%s: Mistakenly got LMAC notification during UMAC scan\n",
__func__);
return;
}
IWM_DPRINTF(sc, IWM_DEBUG_SCAN, "Regular scan %s, EBS status %s (FW)\n",
iwm_offload_status_str(scan_notif->status),
iwm_ebs_status_str(scan_notif->ebs_status));
sc->last_ebs_successful =
scan_notif->ebs_status == IWM_SCAN_EBS_SUCCESS ||
scan_notif->ebs_status == IWM_SCAN_EBS_INACTIVE;
}
void
iwm_rx_umac_scan_complete_notif(struct iwm_softc *sc,
struct iwm_rx_packet *pkt)
{
struct iwm_umac_scan_complete *notif = (void *)pkt->data;
IWM_DPRINTF(sc, IWM_DEBUG_SCAN,
"Scan completed, uid %u, status %s, EBS status %s\n",
le32toh(notif->uid),
iwm_offload_status_str(notif->status),
iwm_ebs_status_str(notif->ebs_status));
if (notif->ebs_status != IWM_SCAN_EBS_SUCCESS &&
notif->ebs_status != IWM_SCAN_EBS_INACTIVE)
sc->last_ebs_successful = FALSE;
}
static int
iwm_scan_skip_channel(struct ieee80211_channel *c)
{
if (IEEE80211_IS_CHAN_2GHZ(c) && IEEE80211_IS_CHAN_B(c))
return 0;
else if (IEEE80211_IS_CHAN_5GHZ(c) && IEEE80211_IS_CHAN_A(c))
return 0;
else
return 1;
}
static uint8_t
iwm_lmac_scan_fill_channels(struct iwm_softc *sc,
struct iwm_scan_channel_cfg_lmac *chan, int n_ssids)
{
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_scan_state *ss = ic->ic_scan;
struct ieee80211_channel *c;
uint8_t nchan;
int j;
for (nchan = j = 0;
j < ss->ss_last && nchan < sc->sc_fw.ucode_capa.n_scan_channels;
j++) {
c = ss->ss_chans[j];
/*
* Catch other channels, in case we have 900MHz channels or
* something in the chanlist.
*/
if (!IEEE80211_IS_CHAN_2GHZ(c) && !IEEE80211_IS_CHAN_5GHZ(c)) {
IWM_DPRINTF(sc, IWM_DEBUG_RESET | IWM_DEBUG_EEPROM,
"%s: skipping channel (freq=%d, ieee=%d, flags=0x%08x)\n",
__func__, c->ic_freq, c->ic_ieee, c->ic_flags);
continue;
}
IWM_DPRINTF(sc, IWM_DEBUG_RESET | IWM_DEBUG_EEPROM,
"Adding channel %d (%d Mhz) to the list\n",
nchan, c->ic_freq);
chan->channel_num = htole16(ieee80211_mhz2ieee(c->ic_freq, 0));
chan->iter_count = htole16(1);
chan->iter_interval = htole32(0);
chan->flags = htole32(IWM_UNIFIED_SCAN_CHANNEL_PARTIAL);
chan->flags |= htole32(IWM_SCAN_CHANNEL_NSSIDS(n_ssids));
/* XXX IEEE80211_SCAN_NOBCAST flag is never set. */
if (!IEEE80211_IS_CHAN_PASSIVE(c) &&
(!(ss->ss_flags & IEEE80211_SCAN_NOBCAST) || n_ssids != 0))
chan->flags |= htole32(IWM_SCAN_CHANNEL_TYPE_ACTIVE);
chan++;
nchan++;
}
return nchan;
}
static uint8_t
iwm_umac_scan_fill_channels(struct iwm_softc *sc,
struct iwm_scan_channel_cfg_umac *chan, int n_ssids)
{
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_scan_state *ss = ic->ic_scan;
struct ieee80211_channel *c;
uint8_t nchan;
int j;
for (nchan = j = 0;
j < ss->ss_last && nchan < sc->sc_fw.ucode_capa.n_scan_channels;
j++) {
c = ss->ss_chans[j];
/*
* Catch other channels, in case we have 900MHz channels or
* something in the chanlist.
*/
if (!IEEE80211_IS_CHAN_2GHZ(c) && !IEEE80211_IS_CHAN_5GHZ(c)) {
IWM_DPRINTF(sc, IWM_DEBUG_RESET | IWM_DEBUG_EEPROM,
"%s: skipping channel (freq=%d, ieee=%d, flags=0x%08x)\n",
__func__, c->ic_freq, c->ic_ieee, c->ic_flags);
continue;
}
IWM_DPRINTF(sc, IWM_DEBUG_RESET | IWM_DEBUG_EEPROM,
"Adding channel %d (%d Mhz) to the list\n",
nchan, c->ic_freq);
chan->channel_num = ieee80211_mhz2ieee(c->ic_freq, 0);
chan->iter_count = 1;
chan->iter_interval = htole16(0);
chan->flags = htole32(IWM_SCAN_CHANNEL_UMAC_NSSIDS(n_ssids));
chan++;
nchan++;
}
return nchan;
}
static int
iwm_fill_probe_req(struct iwm_softc *sc, struct iwm_scan_probe_req *preq)
{
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct ieee80211_frame *wh = (struct ieee80211_frame *)preq->buf;
struct ieee80211_rateset *rs;
size_t remain = sizeof(preq->buf);
uint8_t *frm, *pos;
memset(preq, 0, sizeof(*preq));
/* Ensure enough space for header and SSID IE. */
if (remain < sizeof(*wh) + 2)
return ENOBUFS;
/*
* Build a probe request frame. Most of the following code is a
* copy & paste of what is done in net80211.
*/
wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT |
IEEE80211_FC0_SUBTYPE_PROBE_REQ;
wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
IEEE80211_ADDR_COPY(wh->i_addr1, ieee80211broadcastaddr);
IEEE80211_ADDR_COPY(wh->i_addr2, vap ? vap->iv_myaddr : ic->ic_macaddr);
IEEE80211_ADDR_COPY(wh->i_addr3, ieee80211broadcastaddr);
*(uint16_t *)&wh->i_dur[0] = 0; /* filled by HW */
*(uint16_t *)&wh->i_seq[0] = 0; /* filled by HW */
frm = (uint8_t *)(wh + 1);
frm = ieee80211_add_ssid(frm, NULL, 0);
/* Tell the firmware where the MAC header is. */
preq->mac_header.offset = 0;
preq->mac_header.len = htole16(frm - (uint8_t *)wh);
remain -= frm - (uint8_t *)wh;
/* Fill in 2GHz IEs and tell firmware where they are. */
rs = &ic->ic_sup_rates[IEEE80211_MODE_11G];
if (rs->rs_nrates > IEEE80211_RATE_SIZE) {
if (remain < 4 + rs->rs_nrates)
return ENOBUFS;
} else if (remain < 2 + rs->rs_nrates) {
return ENOBUFS;
}
preq->band_data[0].offset = htole16(frm - (uint8_t *)wh);
pos = frm;
frm = ieee80211_add_rates(frm, rs);
if (rs->rs_nrates > IEEE80211_RATE_SIZE)
frm = ieee80211_add_xrates(frm, rs);
preq->band_data[0].len = htole16(frm - pos);
remain -= frm - pos;
if (iwm_rrm_scan_needed(sc)) {
if (remain < 3)
return ENOBUFS;
*frm++ = IEEE80211_ELEMID_DSPARMS;
*frm++ = 1;
*frm++ = 0;
remain -= 3;
}
if (sc->nvm_data->sku_cap_band_52GHz_enable) {
/* Fill in 5GHz IEs. */
rs = &ic->ic_sup_rates[IEEE80211_MODE_11A];
if (rs->rs_nrates > IEEE80211_RATE_SIZE) {
if (remain < 4 + rs->rs_nrates)
return ENOBUFS;
} else if (remain < 2 + rs->rs_nrates) {
return ENOBUFS;
}
preq->band_data[1].offset = htole16(frm - (uint8_t *)wh);
pos = frm;
frm = ieee80211_add_rates(frm, rs);
if (rs->rs_nrates > IEEE80211_RATE_SIZE)
frm = ieee80211_add_xrates(frm, rs);
preq->band_data[1].len = htole16(frm - pos);
remain -= frm - pos;
}
/* Send 11n IEs on both 2GHz and 5GHz bands. */
preq->common_data.offset = htole16(frm - (uint8_t *)wh);
pos = frm;
#if 0
if (ic->ic_flags & IEEE80211_F_HTON) {
if (remain < 28)
return ENOBUFS;
frm = ieee80211_add_htcaps(frm, ic);
/* XXX add WME info? */
}
#endif
preq->common_data.len = htole16(frm - pos);
return 0;
}
int
iwm_config_umac_scan(struct iwm_softc *sc)
{
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct iwm_scan_config *scan_config;
int ret, j, nchan;
size_t cmd_size;
struct ieee80211_channel *c;
struct iwm_host_cmd hcmd = {
.id = iwm_cmd_id(IWM_SCAN_CFG_CMD, IWM_ALWAYS_LONG_GROUP, 0),
.flags = IWM_CMD_SYNC,
};
static const uint32_t rates = (IWM_SCAN_CONFIG_RATE_1M |
IWM_SCAN_CONFIG_RATE_2M | IWM_SCAN_CONFIG_RATE_5M |
IWM_SCAN_CONFIG_RATE_11M | IWM_SCAN_CONFIG_RATE_6M |
IWM_SCAN_CONFIG_RATE_9M | IWM_SCAN_CONFIG_RATE_12M |
IWM_SCAN_CONFIG_RATE_18M | IWM_SCAN_CONFIG_RATE_24M |
IWM_SCAN_CONFIG_RATE_36M | IWM_SCAN_CONFIG_RATE_48M |
IWM_SCAN_CONFIG_RATE_54M);
cmd_size = sizeof(*scan_config) + sc->sc_fw.ucode_capa.n_scan_channels;
scan_config = malloc(cmd_size, M_DEVBUF, M_NOWAIT | M_ZERO);
if (scan_config == NULL)
return ENOMEM;
scan_config->tx_chains = htole32(iwm_get_valid_tx_ant(sc));
scan_config->rx_chains = htole32(iwm_get_valid_rx_ant(sc));
scan_config->legacy_rates = htole32(rates |
IWM_SCAN_CONFIG_SUPPORTED_RATE(rates));
/* These timings correspond to iwlwifi's UNASSOC scan. */
scan_config->dwell_active = 10;
scan_config->dwell_passive = 110;
scan_config->dwell_fragmented = 44;
scan_config->dwell_extended = 90;
scan_config->out_of_channel_time = htole32(0);
scan_config->suspend_time = htole32(0);
IEEE80211_ADDR_COPY(scan_config->mac_addr,
vap ? vap->iv_myaddr : ic->ic_macaddr);
scan_config->bcast_sta_id = sc->sc_aux_sta.sta_id;
scan_config->channel_flags = IWM_CHANNEL_FLAG_EBS |
IWM_CHANNEL_FLAG_ACCURATE_EBS | IWM_CHANNEL_FLAG_EBS_ADD |
IWM_CHANNEL_FLAG_PRE_SCAN_PASSIVE2ACTIVE;
for (nchan = j = 0;
j < ic->ic_nchans && nchan < sc->sc_fw.ucode_capa.n_scan_channels;
j++) {
c = &ic->ic_channels[j];
/* For 2GHz, only populate 11b channels */
/* For 5GHz, only populate 11a channels */
/*
* Catch other channels, in case we have 900MHz channels or
* something in the chanlist.
*/
if (iwm_scan_skip_channel(c))
continue;
scan_config->channel_array[nchan++] =
ieee80211_mhz2ieee(c->ic_freq, 0);
}
scan_config->flags = htole32(IWM_SCAN_CONFIG_FLAG_ACTIVATE |
IWM_SCAN_CONFIG_FLAG_ALLOW_CHUB_REQS |
IWM_SCAN_CONFIG_FLAG_SET_TX_CHAINS |
IWM_SCAN_CONFIG_FLAG_SET_RX_CHAINS |
IWM_SCAN_CONFIG_FLAG_SET_AUX_STA_ID |
IWM_SCAN_CONFIG_FLAG_SET_ALL_TIMES |
IWM_SCAN_CONFIG_FLAG_SET_LEGACY_RATES |
IWM_SCAN_CONFIG_FLAG_SET_MAC_ADDR |
IWM_SCAN_CONFIG_FLAG_SET_CHANNEL_FLAGS|
IWM_SCAN_CONFIG_N_CHANNELS(nchan) |
IWM_SCAN_CONFIG_FLAG_CLEAR_FRAGMENTED);
hcmd.data[0] = scan_config;
hcmd.len[0] = cmd_size;
IWM_DPRINTF(sc, IWM_DEBUG_SCAN, "Sending UMAC scan config\n");
ret = iwm_send_cmd(sc, &hcmd);
if (!ret)
IWM_DPRINTF(sc, IWM_DEBUG_SCAN,
"UMAC scan config was sent successfully\n");
free(scan_config, M_DEVBUF);
return ret;
}
static boolean_t
iwm_scan_use_ebs(struct iwm_softc *sc)
{
const struct iwm_ucode_capabilities *capa = &sc->sc_fw.ucode_capa;
/* We can only use EBS if:
* 1. the feature is supported;
* 2. the last EBS was successful;
* 3. if only single scan, the single scan EBS API is supported;
* 4. it's not a p2p find operation.
*/
return ((capa->flags & IWM_UCODE_TLV_FLAGS_EBS_SUPPORT) &&
sc->last_ebs_successful);
}
static int
iwm_scan_size(struct iwm_softc *sc)
{
int base_size;
if (iwm_fw_has_capa(sc, IWM_UCODE_TLV_CAPA_UMAC_SCAN)) {
if (iwm_fw_has_api(sc, IWM_UCODE_TLV_API_ADAPTIVE_DWELL))
base_size = IWM_SCAN_REQ_UMAC_SIZE_V7;
else
base_size = IWM_SCAN_REQ_UMAC_SIZE_V1;
return base_size +
sizeof(struct iwm_scan_channel_cfg_umac) *
sc->sc_fw.ucode_capa.n_scan_channels +
sizeof(struct iwm_scan_req_umac_tail);
} else {
return sizeof(struct iwm_scan_req_lmac) +
sizeof(struct iwm_scan_channel_cfg_lmac) *
sc->sc_fw.ucode_capa.n_scan_channels +
sizeof(struct iwm_scan_probe_req);
}
}
int
iwm_umac_scan(struct iwm_softc *sc)
{
struct iwm_host_cmd hcmd = {
.id = iwm_cmd_id(IWM_SCAN_REQ_UMAC, IWM_ALWAYS_LONG_GROUP, 0),
.len = { 0, },
.data = { NULL, },
.flags = IWM_CMD_SYNC,
};
struct ieee80211_scan_state *ss = sc->sc_ic.ic_scan;
struct iwm_scan_req_umac *req;
struct iwm_scan_req_umac_tail *tail;
size_t req_len;
uint16_t general_flags;
uint8_t channel_flags, i, nssid;
int ret;
req_len = iwm_scan_size(sc);
if (req_len > IWM_MAX_CMD_PAYLOAD_SIZE)
return ENOMEM;
req = malloc(req_len, M_DEVBUF, M_NOWAIT | M_ZERO);
if (req == NULL)
return ENOMEM;
hcmd.len[0] = (uint16_t)req_len;
hcmd.data[0] = (void *)req;
IWM_DPRINTF(sc, IWM_DEBUG_SCAN, "Handling ieee80211 scan request\n");
nssid = MIN(ss->ss_nssid, IWM_PROBE_OPTION_MAX);
general_flags = IWM_UMAC_SCAN_GEN_FLAGS_PASS_ALL |
IWM_UMAC_SCAN_GEN_FLAGS_ITER_COMPLETE;
if (!iwm_fw_has_api(sc, IWM_UCODE_TLV_API_ADAPTIVE_DWELL))
general_flags |= IWM_UMAC_SCAN_GEN_FLAGS_EXTENDED_DWELL;
if (iwm_rrm_scan_needed(sc))
general_flags |= IWM_UMAC_SCAN_GEN_FLAGS_RRM_ENABLED;
if (nssid != 0)
general_flags |= IWM_UMAC_SCAN_GEN_FLAGS_PRE_CONNECT;
else
general_flags |= IWM_UMAC_SCAN_GEN_FLAGS_PASSIVE;
channel_flags = 0;
if (iwm_scan_use_ebs(sc))
channel_flags = IWM_SCAN_CHANNEL_FLAG_EBS |
IWM_SCAN_CHANNEL_FLAG_EBS_ACCURATE |
IWM_SCAN_CHANNEL_FLAG_CACHE_ADD;
req->general_flags = htole16(general_flags);
req->ooc_priority = htole32(IWM_SCAN_PRIORITY_HIGH);
/* These timings correspond to iwlwifi's UNASSOC scan. */
if (iwm_fw_has_api(sc, IWM_UCODE_TLV_API_ADAPTIVE_DWELL)) {
req->v7.active_dwell = 10;
req->v7.passive_dwell = 110;
req->v7.fragmented_dwell = 44;
req->v7.adwell_default_n_aps_social = 10;
req->v7.adwell_default_n_aps = 2;
req->v7.adwell_max_budget = htole16(300);
req->v7.scan_priority = htole32(IWM_SCAN_PRIORITY_HIGH);
req->v7.channel.flags = channel_flags;
req->v7.channel.count = iwm_umac_scan_fill_channels(sc,
(struct iwm_scan_channel_cfg_umac *)req->v7.data, nssid);
tail = (void *)((char *)&req->v7.data +
sizeof(struct iwm_scan_channel_cfg_umac) *
sc->sc_fw.ucode_capa.n_scan_channels);
} else {
req->v1.active_dwell = 10;
req->v1.passive_dwell = 110;
req->v1.fragmented_dwell = 44;
req->v1.extended_dwell = 90;
req->v1.scan_priority = htole32(IWM_SCAN_PRIORITY_HIGH);
req->v1.channel.flags = channel_flags;
req->v1.channel.count = iwm_umac_scan_fill_channels(sc,
(struct iwm_scan_channel_cfg_umac *)req->v1.data, nssid);
tail = (void *)((char *)&req->v1.data +
sizeof(struct iwm_scan_channel_cfg_umac) *
sc->sc_fw.ucode_capa.n_scan_channels);
}
/* Check if we're doing an active directed scan. */
for (i = 0; i < nssid; i++) {
tail->direct_scan[i].id = IEEE80211_ELEMID_SSID;
tail->direct_scan[i].len = MIN(ss->ss_ssid[i].len,
IEEE80211_NWID_LEN);
memcpy(tail->direct_scan[i].ssid, ss->ss_ssid[i].ssid,
tail->direct_scan[i].len);
/* XXX debug */
}
ret = iwm_fill_probe_req(sc, &tail->preq);
if (ret) {
free(req, M_DEVBUF);
return ret;
}
/* Specify the scan plan: We'll do one iteration. */
tail->schedule[0].interval = 0;
tail->schedule[0].iter_count = 1;
ret = iwm_send_cmd(sc, &hcmd);
if (!ret)
IWM_DPRINTF(sc, IWM_DEBUG_SCAN,
"Scan request was sent successfully\n");
free(req, M_DEVBUF);
return ret;
}
int
iwm_lmac_scan(struct iwm_softc *sc)
{
struct iwm_host_cmd hcmd = {
.id = IWM_SCAN_OFFLOAD_REQUEST_CMD,
.len = { 0, },
.data = { NULL, },
.flags = IWM_CMD_SYNC,
};
struct ieee80211_scan_state *ss = sc->sc_ic.ic_scan;
struct iwm_scan_req_lmac *req;
size_t req_len;
uint8_t i, nssid;
int ret;
IWM_DPRINTF(sc, IWM_DEBUG_SCAN,
"Handling ieee80211 scan request\n");
req_len = iwm_scan_size(sc);
if (req_len > IWM_MAX_CMD_PAYLOAD_SIZE)
return ENOMEM;
req = malloc(req_len, M_DEVBUF, M_NOWAIT | M_ZERO);
if (req == NULL)
return ENOMEM;
hcmd.len[0] = (uint16_t)req_len;
hcmd.data[0] = (void *)req;
/* These timings correspond to iwlwifi's UNASSOC scan. */
req->active_dwell = 10;
req->passive_dwell = 110;
req->fragmented_dwell = 44;
req->extended_dwell = 90;
req->max_out_time = 0;
req->suspend_time = 0;
req->scan_prio = htole32(IWM_SCAN_PRIORITY_HIGH);
req->rx_chain_select = iwm_scan_rx_chain(sc);
req->iter_num = htole32(1);
req->delay = 0;
req->scan_flags = htole32(IWM_LMAC_SCAN_FLAG_PASS_ALL |
IWM_LMAC_SCAN_FLAG_ITER_COMPLETE |
IWM_LMAC_SCAN_FLAG_EXTENDED_DWELL);
if (iwm_rrm_scan_needed(sc))
req->scan_flags |= htole32(IWM_LMAC_SCAN_FLAGS_RRM_ENABLED);
req->flags = iwm_scan_rxon_flags(sc->sc_ic.ic_scan->ss_chans[0]);
req->filter_flags =
htole32(IWM_MAC_FILTER_ACCEPT_GRP | IWM_MAC_FILTER_IN_BEACON);
/* Tx flags 2 GHz. */
req->tx_cmd[0].tx_flags = htole32(IWM_TX_CMD_FLG_SEQ_CTL |
IWM_TX_CMD_FLG_BT_DIS);
req->tx_cmd[0].rate_n_flags =
iwm_scan_rate_n_flags(sc, IEEE80211_CHAN_2GHZ, 1/*XXX*/);
req->tx_cmd[0].sta_id = sc->sc_aux_sta.sta_id;
/* Tx flags 5 GHz. */
req->tx_cmd[1].tx_flags = htole32(IWM_TX_CMD_FLG_SEQ_CTL |
IWM_TX_CMD_FLG_BT_DIS);
req->tx_cmd[1].rate_n_flags =
iwm_scan_rate_n_flags(sc, IEEE80211_CHAN_5GHZ, 1/*XXX*/);
req->tx_cmd[1].sta_id = sc->sc_aux_sta.sta_id;
/* Check if we're doing an active directed scan. */
nssid = MIN(ss->ss_nssid, IWM_PROBE_OPTION_MAX);
for (i = 0; i < nssid; i++) {
req->direct_scan[i].id = IEEE80211_ELEMID_SSID;
req->direct_scan[i].len = MIN(ss->ss_ssid[i].len,
IEEE80211_NWID_LEN);
memcpy(req->direct_scan[i].ssid, ss->ss_ssid[i].ssid,
req->direct_scan[i].len);
/* XXX debug */
}
if (nssid != 0) {
req->scan_flags |=
htole32(IWM_LMAC_SCAN_FLAG_PRE_CONNECTION);
} else
req->scan_flags |= htole32(IWM_LMAC_SCAN_FLAG_PASSIVE);
req->n_channels = iwm_lmac_scan_fill_channels(sc,
(struct iwm_scan_channel_cfg_lmac *)req->data, nssid);
ret = iwm_fill_probe_req(sc,
(struct iwm_scan_probe_req *)(req->data +
(sizeof(struct iwm_scan_channel_cfg_lmac) *
sc->sc_fw.ucode_capa.n_scan_channels)));
if (ret) {
free(req, M_DEVBUF);
return ret;
}
/* Specify the scan plan: We'll do one iteration. */
req->schedule[0].iterations = 1;
req->schedule[0].full_scan_mul = 1;
if (iwm_scan_use_ebs(sc)) {
req->channel_opt[0].flags =
htole16(IWM_SCAN_CHANNEL_FLAG_EBS |
IWM_SCAN_CHANNEL_FLAG_EBS_ACCURATE |
IWM_SCAN_CHANNEL_FLAG_CACHE_ADD);
req->channel_opt[0].non_ebs_ratio =
htole16(IWM_DENSE_EBS_SCAN_RATIO);
req->channel_opt[1].flags =
htole16(IWM_SCAN_CHANNEL_FLAG_EBS |
IWM_SCAN_CHANNEL_FLAG_EBS_ACCURATE |
IWM_SCAN_CHANNEL_FLAG_CACHE_ADD);
req->channel_opt[1].non_ebs_ratio =
htole16(IWM_SPARSE_EBS_SCAN_RATIO);
}
ret = iwm_send_cmd(sc, &hcmd);
if (!ret) {
IWM_DPRINTF(sc, IWM_DEBUG_SCAN,
"Scan request was sent successfully\n");
}
free(req, M_DEVBUF);
return ret;
}
static int
iwm_lmac_scan_abort(struct iwm_softc *sc)
{
int ret;
struct iwm_host_cmd hcmd = {
.id = IWM_SCAN_OFFLOAD_ABORT_CMD,
.len = { 0, },
.data = { NULL, },
.flags = IWM_CMD_SYNC,
};
uint32_t status;
ret = iwm_send_cmd_status(sc, &hcmd, &status);
if (ret)
return ret;
if (status != IWM_CAN_ABORT_STATUS) {
/*
* The scan abort will return 1 for success or
* 2 for "failure". A failure condition can be
* due to simply not being in an active scan which
* can occur if we send the scan abort before the
* microcode has notified us that a scan is completed.
*/
IWM_DPRINTF(sc, IWM_DEBUG_SCAN,
"SCAN OFFLOAD ABORT ret %d.\n", status);
ret = ENOENT;
}
return ret;
}
static int
iwm_umac_scan_abort(struct iwm_softc *sc)
{
struct iwm_umac_scan_abort cmd = {};
int uid, ret;
uid = 0;
cmd.uid = htole32(uid);
IWM_DPRINTF(sc, IWM_DEBUG_SCAN, "Sending scan abort, uid %u\n", uid);
ret = iwm_send_cmd_pdu(sc,
iwm_cmd_id(IWM_SCAN_ABORT_UMAC,
IWM_ALWAYS_LONG_GROUP, 0),
0, sizeof(cmd), &cmd);
return ret;
}
int
iwm_scan_stop_wait(struct iwm_softc *sc)
{
struct iwm_notification_wait wait_scan_done;
static const uint16_t scan_done_notif[] = { IWM_SCAN_COMPLETE_UMAC,
IWM_SCAN_OFFLOAD_COMPLETE, };
int ret;
iwm_init_notification_wait(sc->sc_notif_wait, &wait_scan_done,
scan_done_notif, nitems(scan_done_notif),
NULL, NULL);
IWM_DPRINTF(sc, IWM_DEBUG_SCAN, "Preparing to stop scan\n");
if (iwm_fw_has_capa(sc, IWM_UCODE_TLV_CAPA_UMAC_SCAN))
ret = iwm_umac_scan_abort(sc);
else
ret = iwm_lmac_scan_abort(sc);
if (ret) {
IWM_DPRINTF(sc, IWM_DEBUG_SCAN, "couldn't stop scan\n");
iwm_remove_notification(sc->sc_notif_wait, &wait_scan_done);
return ret;
}
IWM_UNLOCK(sc);
ret = iwm_wait_notification(sc->sc_notif_wait, &wait_scan_done, hz);
IWM_LOCK(sc);
return ret;
}

View File

@ -1,118 +0,0 @@
/* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
/* $FreeBSD$ */
/*
* Copyright (c) 2014 genua mbh <info@genua.de>
* Copyright (c) 2014 Fixup Software Ltd.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)
*
***********************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*-
* Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef __IF_IWN_SCAN_H__
#define __IF_IWN_SCAN_H__
extern int iwm_lmac_scan(struct iwm_softc *);
extern int iwm_config_umac_scan(struct iwm_softc *);
extern int iwm_umac_scan(struct iwm_softc *);
extern int iwm_scan_stop_wait(struct iwm_softc *);
extern void iwm_rx_lmac_scan_complete_notif(struct iwm_softc *,
struct iwm_rx_packet *);
extern void iwm_rx_umac_scan_complete_notif(struct iwm_softc *,
struct iwm_rx_packet *);
#endif /* __IF_IWN_SCAN_H__ */

View File

@ -1,330 +0,0 @@
/*
* Copyright (c) 2014 genua mbh <info@genua.de>
* Copyright (c) 2014 Fixup Software Ltd.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 4.7.3 (tag id d7f6728f57e3ecbb7ef34eb7d9f564d514775d75)
*
******************************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
*
* Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include "opt_iwm.h"
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/endian.h>
#include <sys/firmware.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/mutex.h>
#include <sys/module.h>
#include <sys/proc.h>
#include <sys/rman.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/sysctl.h>
#include <sys/linker.h>
#include <machine/bus.h>
#include <machine/endian.h>
#include <machine/resource.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_arp.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_types.h>
#include <net/bpf.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/if_ether.h>
#include <netinet/ip.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_regdomain.h>
#include <net80211/ieee80211_ratectl.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/iwm/if_iwmreg.h>
#include <dev/iwm/if_iwmvar.h>
#include <dev/iwm/if_iwm_config.h>
#include <dev/iwm/if_iwm_debug.h>
#include <dev/iwm/if_iwm_util.h>
#include <dev/iwm/if_iwm_sf.h>
/*
* Aging and idle timeouts for the different possible scenarios
* in default configuration
*/
static const uint32_t
sf_full_timeout_def[IWM_SF_NUM_SCENARIO][IWM_SF_NUM_TIMEOUT_TYPES] = {
{
htole32(IWM_SF_SINGLE_UNICAST_AGING_TIMER_DEF),
htole32(IWM_SF_SINGLE_UNICAST_IDLE_TIMER_DEF)
},
{
htole32(IWM_SF_AGG_UNICAST_AGING_TIMER_DEF),
htole32(IWM_SF_AGG_UNICAST_IDLE_TIMER_DEF)
},
{
htole32(IWM_SF_MCAST_AGING_TIMER_DEF),
htole32(IWM_SF_MCAST_IDLE_TIMER_DEF)
},
{
htole32(IWM_SF_BA_AGING_TIMER_DEF),
htole32(IWM_SF_BA_IDLE_TIMER_DEF)
},
{
htole32(IWM_SF_TX_RE_AGING_TIMER_DEF),
htole32(IWM_SF_TX_RE_IDLE_TIMER_DEF)
},
};
/*
* Aging and idle timeouts for the different possible scenarios
* in single BSS MAC configuration.
*/
static const uint32_t
sf_full_timeout[IWM_SF_NUM_SCENARIO][IWM_SF_NUM_TIMEOUT_TYPES] = {
{
htole32(IWM_SF_SINGLE_UNICAST_AGING_TIMER),
htole32(IWM_SF_SINGLE_UNICAST_IDLE_TIMER)
},
{
htole32(IWM_SF_AGG_UNICAST_AGING_TIMER),
htole32(IWM_SF_AGG_UNICAST_IDLE_TIMER)
},
{
htole32(IWM_SF_MCAST_AGING_TIMER),
htole32(IWM_SF_MCAST_IDLE_TIMER)
},
{
htole32(IWM_SF_BA_AGING_TIMER),
htole32(IWM_SF_BA_IDLE_TIMER)
},
{
htole32(IWM_SF_TX_RE_AGING_TIMER),
htole32(IWM_SF_TX_RE_IDLE_TIMER)
},
};
static void
iwm_fill_sf_command(struct iwm_softc *sc, struct iwm_sf_cfg_cmd *sf_cmd,
struct ieee80211_node *ni)
{
int i, j, watermark;
sf_cmd->watermark[IWM_SF_LONG_DELAY_ON] = htole32(IWM_SF_W_MARK_SCAN);
/*
* If we are in association flow - check antenna configuration
* capabilities of the AP station, and choose the watermark accordingly.
*/
if (ni) {
if (ni->ni_flags & IEEE80211_NODE_HT) {
watermark = IWM_SF_W_MARK_SISO;
} else {
watermark = IWM_SF_W_MARK_LEGACY;
}
/* default watermark value for unassociated mode. */
} else {
watermark = IWM_SF_W_MARK_MIMO2;
}
sf_cmd->watermark[IWM_SF_FULL_ON] = htole32(watermark);
for (i = 0; i < IWM_SF_NUM_SCENARIO; i++) {
for (j = 0; j < IWM_SF_NUM_TIMEOUT_TYPES; j++) {
sf_cmd->long_delay_timeouts[i][j] =
htole32(IWM_SF_LONG_DELAY_AGING_TIMER);
}
}
if (ni) {
_Static_assert(sizeof(sf_full_timeout) == sizeof(uint32_t) *
IWM_SF_NUM_SCENARIO * IWM_SF_NUM_TIMEOUT_TYPES,
"sf_full_timeout has wrong size");
memcpy(sf_cmd->full_on_timeouts, sf_full_timeout,
sizeof(sf_full_timeout));
} else {
_Static_assert(sizeof(sf_full_timeout_def) == sizeof(uint32_t) *
IWM_SF_NUM_SCENARIO * IWM_SF_NUM_TIMEOUT_TYPES,
"sf_full_timeout_def has wrong size");
memcpy(sf_cmd->full_on_timeouts, sf_full_timeout_def,
sizeof(sf_full_timeout_def));
}
}
static int
iwm_sf_config(struct iwm_softc *sc, struct ieee80211_node *ni,
enum iwm_sf_state new_state)
{
struct iwm_sf_cfg_cmd sf_cmd = {
.state = htole32(new_state),
};
int ret = 0;
#ifdef notyet /* only relevant for sdio variants */
if (sc->cfg->disable_dummy_notification)
sf_cmd.state |= htole32(IWM_SF_CFG_DUMMY_NOTIF_OFF);
#endif
/*
* If an associated AP sta changed its antenna configuration, the state
* will remain FULL_ON but SF parameters need to be reconsidered.
*/
if (new_state != IWM_SF_FULL_ON && sc->sf_state == new_state)
return 0;
switch (new_state) {
case IWM_SF_UNINIT:
iwm_fill_sf_command(sc, &sf_cmd, NULL);
break;
case IWM_SF_FULL_ON:
iwm_fill_sf_command(sc, &sf_cmd, ni);
break;
case IWM_SF_INIT_OFF:
iwm_fill_sf_command(sc, &sf_cmd, NULL);
break;
default:
device_printf(sc->sc_dev,
"Invalid state: %d. not sending Smart Fifo cmd\n",
new_state);
return EINVAL;
}
ret = iwm_send_cmd_pdu(sc, IWM_REPLY_SF_CFG_CMD, IWM_CMD_ASYNC,
sizeof(sf_cmd), &sf_cmd);
if (!ret)
sc->sf_state = new_state;
return ret;
}
/*
* Update Smart fifo:
* Count bound interfaces that are not to be removed, ignoring p2p devices,
* and set new state accordingly.
*/
int
iwm_sf_update(struct iwm_softc *sc, struct ieee80211vap *changed_vif,
boolean_t remove_vif)
{
enum iwm_sf_state new_state;
struct ieee80211_node *ni = NULL;
int num_active_macs = 0;
/* If changed_vif exists and is not to be removed, add to the count */
if (changed_vif && !remove_vif)
num_active_macs++;
switch (num_active_macs) {
case 0:
/* If there are no active macs - change state to SF_INIT_OFF */
new_state = IWM_SF_INIT_OFF;
break;
case 1:
if (!changed_vif)
return EINVAL;
ni = changed_vif->iv_bss;
if (ni != NULL && IWM_NODE(ni)->in_assoc &&
changed_vif->iv_dtim_period) {
new_state = IWM_SF_FULL_ON;
} else {
new_state = IWM_SF_INIT_OFF;
}
break;
default:
/* If there are multiple active macs - change to SF_UNINIT */
new_state = IWM_SF_UNINIT;
}
return iwm_sf_config(sc, ni, new_state);
}

View File

@ -1,82 +0,0 @@
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 4.7.3 (tag id d7f6728f57e3ecbb7ef34eb7d9f564d514775d75)
*
***********************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2016 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2016 Intel Deutschland GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef __IF_IWM_SF_H__
#define __IF_IWM_SF_H__
extern int iwm_sf_update(struct iwm_softc *sc,
struct ieee80211vap *changed_vif,
boolean_t remove_vif);
#endif /* __IF_IWM_SF_H__ */

View File

@ -1,381 +0,0 @@
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 4.7.3 (tag id d7f6728f57e3ecbb7ef34eb7d9f564d514775d75)
*
***********************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2012 - 2015 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
*
* Copyright(c) 2012 - 2015 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 Intel Deutschland GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include "opt_iwm.h"
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/endian.h>
#include <sys/firmware.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/mutex.h>
#include <sys/module.h>
#include <sys/proc.h>
#include <sys/rman.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/sysctl.h>
#include <sys/linker.h>
#include <machine/bus.h>
#include <machine/endian.h>
#include <machine/resource.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <net/bpf.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_arp.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_types.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/if_ether.h>
#include <netinet/ip.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_regdomain.h>
#include <net80211/ieee80211_ratectl.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/iwm/if_iwmreg.h>
#include <dev/iwm/if_iwmvar.h>
#include <dev/iwm/if_iwm_config.h>
#include <dev/iwm/if_iwm_debug.h>
#include <dev/iwm/if_iwm_constants.h>
#include <dev/iwm/if_iwm_util.h>
#include <dev/iwm/if_iwm_mac_ctxt.h>
#include <dev/iwm/if_iwm_sta.h>
/*
* New version of ADD_STA_sta command added new fields at the end of the
* structure, so sending the size of the relevant API's structure is enough to
* support both API versions.
*/
static inline int
iwm_add_sta_cmd_size(struct iwm_softc *sc)
{
return sc->cfg->mqrx_supported ? sizeof(struct iwm_add_sta_cmd) :
sizeof(struct iwm_add_sta_cmd_v7);
}
/* send station add/update command to firmware */
int
iwm_sta_send_to_fw(struct iwm_softc *sc, struct iwm_node *in,
boolean_t update)
{
struct iwm_vap *ivp = IWM_VAP(in->in_ni.ni_vap);
struct iwm_add_sta_cmd add_sta_cmd = {
.sta_id = IWM_STATION_ID,
.mac_id_n_color =
htole32(IWM_FW_CMD_ID_AND_COLOR(ivp->id, ivp->color)),
.add_modify = update ? 1 : 0,
.station_flags_msk = htole32(IWM_STA_FLG_FAT_EN_MSK |
IWM_STA_FLG_MIMO_EN_MSK),
.tid_disable_tx = htole16(0xffff),
};
int ret;
uint32_t status;
uint32_t agg_size = 0, mpdu_dens = 0;
if (!update) {
int ac;
for (ac = 0; ac < WME_NUM_AC; ac++) {
add_sta_cmd.tfd_queue_msk |=
htole32(1 << iwm_ac_to_tx_fifo[ac]);
}
IEEE80211_ADDR_COPY(&add_sta_cmd.addr, in->in_ni.ni_bssid);
}
add_sta_cmd.station_flags |=
htole32(agg_size << IWM_STA_FLG_MAX_AGG_SIZE_SHIFT);
add_sta_cmd.station_flags |=
htole32(mpdu_dens << IWM_STA_FLG_AGG_MPDU_DENS_SHIFT);
status = IWM_ADD_STA_SUCCESS;
ret = iwm_send_cmd_pdu_status(sc, IWM_ADD_STA,
iwm_add_sta_cmd_size(sc),
&add_sta_cmd, &status);
if (ret)
return ret;
switch (status & IWM_ADD_STA_STATUS_MASK) {
case IWM_ADD_STA_SUCCESS:
IWM_DPRINTF(sc, IWM_DEBUG_NODE, "IWM_ADD_STA PASSED\n");
break;
default:
ret = EIO;
device_printf(sc->sc_dev, "IWM_ADD_STA failed\n");
break;
}
return ret;
}
int
iwm_add_sta(struct iwm_softc *sc, struct iwm_node *in)
{
return iwm_sta_send_to_fw(sc, in, FALSE);
}
int
iwm_update_sta(struct iwm_softc *sc, struct iwm_node *in)
{
return iwm_sta_send_to_fw(sc, in, TRUE);
}
int
iwm_drain_sta(struct iwm_softc *sc, struct iwm_vap *ivp, boolean_t drain)
{
struct iwm_add_sta_cmd cmd = {};
int ret;
uint32_t status;
cmd.mac_id_n_color =
htole32(IWM_FW_CMD_ID_AND_COLOR(ivp->id, ivp->color));
cmd.sta_id = IWM_STATION_ID;
cmd.add_modify = IWM_STA_MODE_MODIFY;
cmd.station_flags = drain ? htole32(IWM_STA_FLG_DRAIN_FLOW) : 0;
cmd.station_flags_msk = htole32(IWM_STA_FLG_DRAIN_FLOW);
status = IWM_ADD_STA_SUCCESS;
ret = iwm_send_cmd_pdu_status(sc, IWM_ADD_STA,
iwm_add_sta_cmd_size(sc),
&cmd, &status);
if (ret)
return ret;
switch (status & IWM_ADD_STA_STATUS_MASK) {
case IWM_ADD_STA_SUCCESS:
IWM_DPRINTF(sc, IWM_DEBUG_NODE,
"Frames for staid %d will drained in fw\n", IWM_STATION_ID);
break;
default:
ret = EIO;
device_printf(sc->sc_dev,
"Couldn't drain frames for staid %d\n", IWM_STATION_ID);
break;
}
return ret;
}
/*
* Remove a station from the FW table. Before sending the command to remove
* the station validate that the station is indeed known to the driver (sanity
* only).
*/
static int
iwm_rm_sta_common(struct iwm_softc *sc)
{
struct iwm_rm_sta_cmd rm_sta_cmd = {
.sta_id = IWM_STATION_ID,
};
int ret;
ret = iwm_send_cmd_pdu(sc, IWM_REMOVE_STA, 0,
sizeof(rm_sta_cmd), &rm_sta_cmd);
if (ret) {
device_printf(sc->sc_dev,
"Failed to remove station. Id=%d\n", IWM_STATION_ID);
return ret;
}
return 0;
}
int
iwm_rm_sta(struct iwm_softc *sc, struct ieee80211vap *vap,
boolean_t is_assoc)
{
uint32_t tfd_queue_msk = 0;
int ret;
int ac;
ret = iwm_drain_sta(sc, IWM_VAP(vap), TRUE);
if (ret)
return ret;
for (ac = 0; ac < WME_NUM_AC; ac++) {
tfd_queue_msk |= htole32(1 << iwm_ac_to_tx_fifo[ac]);
}
ret = iwm_flush_tx_path(sc, tfd_queue_msk, IWM_CMD_SYNC);
if (ret)
return ret;
#ifdef notyet /* function not yet implemented */
ret = iwl_trans_wait_tx_queue_empty(mvm->trans,
mvm_sta->tfd_queue_msk);
if (ret)
return ret;
#endif
ret = iwm_drain_sta(sc, IWM_VAP(vap), FALSE);
/* if we are associated - we can't remove the AP STA now */
if (is_assoc)
return ret;
/* XXX wait until STA is drained */
ret = iwm_rm_sta_common(sc);
return ret;
}
int
iwm_rm_sta_id(struct iwm_softc *sc, struct ieee80211vap *vap)
{
/* XXX wait until STA is drained */
return iwm_rm_sta_common(sc);
}
static int
iwm_add_int_sta_common(struct iwm_softc *sc, struct iwm_int_sta *sta,
const uint8_t *addr, uint16_t mac_id, uint16_t color)
{
struct iwm_add_sta_cmd cmd;
int ret;
uint32_t status;
memset(&cmd, 0, sizeof(cmd));
cmd.sta_id = sta->sta_id;
cmd.mac_id_n_color = htole32(IWM_FW_CMD_ID_AND_COLOR(mac_id, color));
if (sta->sta_id == IWM_AUX_STA_ID && sc->cfg->mqrx_supported)
cmd.station_type = IWM_STA_AUX_ACTIVITY;
cmd.tfd_queue_msk = htole32(sta->tfd_queue_msk);
cmd.tid_disable_tx = htole16(0xffff);
if (addr)
IEEE80211_ADDR_COPY(cmd.addr, addr);
ret = iwm_send_cmd_pdu_status(sc, IWM_ADD_STA,
iwm_add_sta_cmd_size(sc),
&cmd, &status);
if (ret)
return ret;
switch (status & IWM_ADD_STA_STATUS_MASK) {
case IWM_ADD_STA_SUCCESS:
IWM_DPRINTF(sc, IWM_DEBUG_NODE, "Internal station added.\n");
return 0;
default:
ret = EIO;
device_printf(sc->sc_dev,
"Add internal station failed, status=0x%x\n", status);
break;
}
return ret;
}
int
iwm_add_aux_sta(struct iwm_softc *sc)
{
int ret;
sc->sc_aux_sta.sta_id = IWM_AUX_STA_ID;
sc->sc_aux_sta.tfd_queue_msk = (1 << IWM_AUX_QUEUE);
/* Map Aux queue to fifo - needs to happen before adding Aux station */
ret = iwm_enable_txq(sc, IWM_AUX_STA_ID, IWM_AUX_QUEUE,
IWM_TX_FIFO_MCAST);
if (ret)
return ret;
ret = iwm_add_int_sta_common(sc, &sc->sc_aux_sta, NULL,
IWM_MAC_INDEX_AUX, 0);
if (ret) {
memset(&sc->sc_aux_sta, 0, sizeof(sc->sc_aux_sta));
sc->sc_aux_sta.sta_id = IWM_STATION_COUNT;
}
return ret;
}
void iwm_del_aux_sta(struct iwm_softc *sc)
{
memset(&sc->sc_aux_sta, 0, sizeof(sc->sc_aux_sta));
sc->sc_aux_sta.sta_id = IWM_STATION_COUNT;
}

View File

@ -1,223 +0,0 @@
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 4.7.3 (tag id d7f6728f57e3ecbb7ef34eb7d9f564d514775d75)
*
***********************************************************************
*
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2015 - 2016 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2015 - 2016 Intel Deutschland GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
/* $FreeBSD$ */
#ifndef __IF_IWM_STA_H__
#define __IF_IWM_STA_H__
/**
* DOC: station table - introduction
*
* The station table is a list of data structure that reprensent the stations.
* In STA/P2P client mode, the driver will hold one station for the AP/ GO.
* In GO/AP mode, the driver will have as many stations as associated clients.
* All these stations are reflected in the fw's station table. The driver
* keeps the fw's station table up to date with the ADD_STA command. Stations
* can be removed by the REMOVE_STA command.
*
* All the data related to a station is held in the structure %iwl_sta
* which is embed in the mac80211's %ieee80211_sta (in the drv_priv) area.
* This data includes the index of the station in the fw, per tid information
* (sequence numbers, Block-ack state machine, etc...). The stations are
* created and deleted by the %sta_state callback from %ieee80211_ops.
*
* The driver holds a map: %fw_id_to_mac_id that allows to fetch a
* %ieee80211_sta (and the %iwl_sta embedded into it) based on a fw
* station index. That way, the driver is able to get the tid related data in
* O(1) in time sensitive paths (Tx / Tx response / BA notification). These
* paths are triggered by the fw, and the driver needs to get a pointer to the
* %ieee80211 structure. This map helps to get that pointer quickly.
*/
/**
* DOC: station table - locking
*
* As stated before, the station is created / deleted by mac80211's %sta_state
* callback from %ieee80211_ops which can sleep. The next paragraph explains
* the locking of a single stations, the next ones relates to the station
* table.
*
* The station holds the sequence number per tid. So this data needs to be
* accessed in the Tx path (which is softIRQ). It also holds the Block-Ack
* information (the state machine / and the logic that checks if the queues
* were drained), so it also needs to be accessible from the Tx response flow.
* In short, the station needs to be access from sleepable context as well as
* from tasklets, so the station itself needs a spinlock.
*
* The writers of %fw_id_to_mac_id map are serialized by the global mutex of
* the mvm op_mode. This is possible since %sta_state can sleep.
* The pointers in this map are RCU protected, hence we won't replace the
* station while we have Tx / Tx response / BA notification running.
*
* If a station is deleted while it still has packets in its A-MPDU queues,
* then the reclaim flow will notice that there is no station in the map for
* sta_id and it will dump the responses.
*/
/**
* DOC: station table - internal stations
*
* The FW needs a few internal stations that are not reflected in
* mac80211, such as broadcast station in AP / GO mode, or AUX sta for
* scanning and P2P device (during the GO negotiation).
* For these kind of stations we have %iwl_int_sta struct which holds the
* data relevant for them from both %iwl_sta and %ieee80211_sta.
* Usually the data for these stations is static, so no locking is required,
* and no TID data as this is also not needed.
* One thing to note, is that these stations have an ID in the fw, but not
* in mac80211. In order to "reserve" them a sta_id in %fw_id_to_mac_id
* we fill ERR_PTR(EINVAL) in this mapping and all other dereferencing of
* pointers from this mapping need to check that the value is not error
* or NULL.
*
* Currently there is only one auxiliary station for scanning, initialized
* on init.
*/
/**
* DOC: station table - AP Station in STA mode
*
* %iwl_vif includes the index of the AP station in the fw's STA table:
* %ap_sta_id. To get the point to the corresponding %ieee80211_sta,
* &fw_id_to_mac_id can be used. Due to the way the fw works, we must not remove
* the AP station from the fw before setting the MAC context as unassociated.
* Hence, %fw_id_to_mac_id[%ap_sta_id] will be NULLed when the AP station is
* removed by mac80211, but the station won't be removed in the fw until the
* VIF is set as unassociated. Then, %ap_sta_id will be invalidated.
*/
/**
* DOC: station table - Drain vs. Flush
*
* Flush means that all the frames in the SCD queue are dumped regardless the
* station to which they were sent. We do that when we disassociate and before
* we remove the STA of the AP. The flush can be done synchronously against the
* fw.
* Drain means that the fw will drop all the frames sent to a specific station.
* This is useful when a client (if we are IBSS / GO or AP) disassociates. In
* that case, we need to drain all the frames for that client from the AC queues
* that are shared with the other clients. Only then, we can remove the STA in
* the fw. In order to do so, we track the non-AMPDU packets for each station.
* If mac80211 removes a STA and if it still has non-AMPDU packets pending in
* the queues, we mark this station as %EBUSY in %fw_id_to_mac_id, and drop all
* the frames for this STA (%iwl_rm_sta). When the last frame is dropped
* (we know about it with its Tx response), we remove the station in fw and set
* it as %NULL in %fw_id_to_mac_id: this is the purpose of
* %iwl_sta_drained_wk.
*/
/**
* DOC: station table - fw restart
*
* When the fw asserts, or we have any other issue that requires to reset the
* driver, we require mac80211 to reconfigure the driver. Since the private
* data of the stations is embed in mac80211's %ieee80211_sta, that data will
* not be zeroed and needs to be reinitialized manually.
* %IWL_STATUS_IN_HW_RESTART is set during restart and that will hint us
* that we must not allocate a new sta_id but reuse the previous one. This
* means that the stations being re-added after the reset will have the same
* place in the fw as before the reset. We do need to zero the %fw_id_to_mac_id
* map, since the stations aren't in the fw any more. Internal stations that
* are not added by mac80211 will be re-added in the init flow that is called
* after the restart: mac80211 call's %iwl_mac_start which calls to
* %iwl_up.
*/
/**
* Send the STA info to the FW.
*
* @sc: the iwm_softc* to use
* @sta: the STA
* @update: this is true if the FW is being updated about a STA it already knows
* about. Otherwise (if this is a new STA), this should be false.
* @flags: if update==true, this marks what is being changed via ORs of values
* from enum iwm_sta_modify_flag. Otherwise, this is ignored.
*/
extern int iwm_sta_send_to_fw(struct iwm_softc *sc, struct iwm_node *in,
boolean_t update);
extern int iwm_add_sta(struct iwm_softc *sc, struct iwm_node *in);
extern int iwm_update_sta(struct iwm_softc *sc, struct iwm_node *in);
extern int iwm_rm_sta(struct iwm_softc *sc, struct ieee80211vap *vap,
boolean_t is_assoc);
extern int iwm_rm_sta_id(struct iwm_softc *sc, struct ieee80211vap *vap);
extern int iwm_add_aux_sta(struct iwm_softc *sc);
extern void iwm_del_aux_sta(struct iwm_softc *sc);
extern int iwm_drain_sta(struct iwm_softc *sc, struct iwm_vap *ivp,
boolean_t drain);
#endif /* __IF_IWM_STA_H__ */

View File

@ -1,429 +0,0 @@
/* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
/*
* Copyright (c) 2014 genua mbh <info@genua.de>
* Copyright (c) 2014 Fixup Software Ltd.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)
*
***********************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*-
* Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include "opt_iwm.h"
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/endian.h>
#include <sys/firmware.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/mutex.h>
#include <sys/module.h>
#include <sys/proc.h>
#include <sys/rman.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/sysctl.h>
#include <sys/linker.h>
#include <machine/bus.h>
#include <machine/endian.h>
#include <machine/resource.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <net/bpf.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_arp.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_types.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/if_ether.h>
#include <netinet/ip.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_regdomain.h>
#include <net80211/ieee80211_ratectl.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/iwm/if_iwmreg.h>
#include <dev/iwm/if_iwmvar.h>
#include <dev/iwm/if_iwm_debug.h>
#include <dev/iwm/if_iwm_util.h>
#include <dev/iwm/if_iwm_notif_wait.h>
#include <dev/iwm/if_iwm_pcie_trans.h>
#include <dev/iwm/if_iwm_time_event.h>
#define TU_TO_HZ(tu) (((uint64_t)(tu) * 1024 * hz) / 1000000)
static void
iwm_te_clear_data(struct iwm_softc *sc)
{
sc->sc_time_event_uid = 0;
sc->sc_time_event_duration = 0;
sc->sc_time_event_end_ticks = 0;
sc->sc_flags &= ~IWM_FLAG_TE_ACTIVE;
}
/*
* Handles a FW notification for an event that is known to the driver.
*
* @mvm: the mvm component
* @te_data: the time event data
* @notif: the notification data corresponding the time event data.
*/
static void
iwm_te_handle_notif(struct iwm_softc *sc,
struct iwm_time_event_notif *notif)
{
IWM_DPRINTF(sc, IWM_DEBUG_TE,
"Handle time event notif - UID = 0x%x action %d\n",
le32toh(notif->unique_id),
le32toh(notif->action));
if (!le32toh(notif->status)) {
const char *msg;
if (notif->action & htole32(IWM_TE_V2_NOTIF_HOST_EVENT_START))
msg = "Time Event start notification failure";
else
msg = "Time Event end notification failure";
IWM_DPRINTF(sc, IWM_DEBUG_TE, "%s\n", msg);
}
if (le32toh(notif->action) & IWM_TE_V2_NOTIF_HOST_EVENT_END) {
IWM_DPRINTF(sc, IWM_DEBUG_TE,
"TE ended - current time %d, estimated end %d\n",
ticks, sc->sc_time_event_end_ticks);
iwm_te_clear_data(sc);
} else if (le32toh(notif->action) & IWM_TE_V2_NOTIF_HOST_EVENT_START) {
sc->sc_time_event_end_ticks =
ticks + TU_TO_HZ(sc->sc_time_event_duration);
} else {
device_printf(sc->sc_dev, "Got TE with unknown action\n");
}
}
/*
* The Rx handler for time event notifications
*/
void
iwm_rx_time_event_notif(struct iwm_softc *sc, struct iwm_rx_packet *pkt)
{
struct iwm_time_event_notif *notif = (void *)pkt->data;
IWM_DPRINTF(sc, IWM_DEBUG_TE,
"Time event notification - UID = 0x%x action %d\n",
le32toh(notif->unique_id),
le32toh(notif->action));
iwm_te_handle_notif(sc, notif);
}
static int
iwm_te_notif(struct iwm_softc *sc, struct iwm_rx_packet *pkt,
void *data)
{
struct iwm_time_event_notif *resp;
int resp_len = iwm_rx_packet_payload_len(pkt);
if (pkt->hdr.code != IWM_TIME_EVENT_NOTIFICATION ||
resp_len != sizeof(*resp)) {
IWM_DPRINTF(sc, IWM_DEBUG_TE,
"Invalid TIME_EVENT_NOTIFICATION response\n");
return 1;
}
resp = (void *)pkt->data;
/* te_data->uid is already set in the TIME_EVENT_CMD response */
if (le32toh(resp->unique_id) != sc->sc_time_event_uid)
return false;
IWM_DPRINTF(sc, IWM_DEBUG_TE,
"TIME_EVENT_NOTIFICATION response - UID = 0x%x\n",
sc->sc_time_event_uid);
if (!resp->status) {
IWM_DPRINTF(sc, IWM_DEBUG_TE,
"TIME_EVENT_NOTIFICATION received but not executed\n");
}
return 1;
}
static int
iwm_time_event_response(struct iwm_softc *sc, struct iwm_rx_packet *pkt,
void *data)
{
struct iwm_time_event_resp *resp;
int resp_len = iwm_rx_packet_payload_len(pkt);
if (pkt->hdr.code != IWM_TIME_EVENT_CMD ||
resp_len != sizeof(*resp)) {
IWM_DPRINTF(sc, IWM_DEBUG_TE,
"Invalid TIME_EVENT_CMD response\n");
return 1;
}
resp = (void *)pkt->data;
/* we should never get a response to another TIME_EVENT_CMD here */
if (le32toh(resp->id) != IWM_TE_BSS_STA_AGGRESSIVE_ASSOC) {
IWM_DPRINTF(sc, IWM_DEBUG_TE,
"Got TIME_EVENT_CMD response with wrong id: %d\n",
le32toh(resp->id));
return 0;
}
sc->sc_time_event_uid = le32toh(resp->unique_id);
IWM_DPRINTF(sc, IWM_DEBUG_TE,
"TIME_EVENT_CMD response - UID = 0x%x\n", sc->sc_time_event_uid);
return 1;
}
/* XXX Use the te_data function argument properly, like in iwlwifi's code. */
static int
iwm_time_event_send_add(struct iwm_softc *sc, struct iwm_vap *ivp,
void *te_data, struct iwm_time_event_cmd *te_cmd)
{
static const uint16_t time_event_response[] = { IWM_TIME_EVENT_CMD };
struct iwm_notification_wait wait_time_event;
int ret;
IWM_DPRINTF(sc, IWM_DEBUG_TE,
"Add new TE, duration %d TU\n", le32toh(te_cmd->duration));
sc->sc_time_event_duration = le32toh(te_cmd->duration);
/*
* Use a notification wait, which really just processes the
* command response and doesn't wait for anything, in order
* to be able to process the response and get the UID inside
* the RX path. Using CMD_WANT_SKB doesn't work because it
* stores the buffer and then wakes up this thread, by which
* time another notification (that the time event started)
* might already be processed unsuccessfully.
*/
iwm_init_notification_wait(sc->sc_notif_wait, &wait_time_event,
time_event_response,
nitems(time_event_response),
iwm_time_event_response, /*te_data*/NULL);
ret = iwm_send_cmd_pdu(sc, IWM_TIME_EVENT_CMD, 0, sizeof(*te_cmd),
te_cmd);
if (ret) {
IWM_DPRINTF(sc, IWM_DEBUG_TE,
"%s: Couldn't send IWM_TIME_EVENT_CMD: %d\n",
__func__, ret);
iwm_remove_notification(sc->sc_notif_wait, &wait_time_event);
return ret;
}
/* No need to wait for anything, so just pass 1 (0 isn't valid) */
IWM_UNLOCK(sc);
ret = iwm_wait_notification(sc->sc_notif_wait, &wait_time_event, 1);
IWM_LOCK(sc);
/* should never fail */
if (ret) {
IWM_DPRINTF(sc, IWM_DEBUG_TE,
"%s: Failed to get response for IWM_TIME_EVENT_CMD: %d\n",
__func__, ret);
}
return ret;
}
void
iwm_protect_session(struct iwm_softc *sc, struct iwm_vap *ivp,
uint32_t duration, uint32_t max_delay, boolean_t wait_for_notif)
{
const uint16_t te_notif_response[] = { IWM_TIME_EVENT_NOTIFICATION };
struct iwm_notification_wait wait_te_notif;
struct iwm_time_event_cmd time_cmd = {};
/* Do nothing if a time event is already scheduled. */
if (sc->sc_flags & IWM_FLAG_TE_ACTIVE)
return;
time_cmd.action = htole32(IWM_FW_CTXT_ACTION_ADD);
time_cmd.id_and_color =
htole32(IWM_FW_CMD_ID_AND_COLOR(ivp->id, ivp->color));
time_cmd.id = htole32(IWM_TE_BSS_STA_AGGRESSIVE_ASSOC);
time_cmd.apply_time = htole32(0);
time_cmd.max_frags = IWM_TE_V2_FRAG_NONE;
time_cmd.max_delay = htole32(max_delay);
/* TODO: why do we need to interval = bi if it is not periodic? */
time_cmd.interval = htole32(1);
time_cmd.duration = htole32(duration);
time_cmd.repeat = 1;
time_cmd.policy
= htole16(IWM_TE_V2_NOTIF_HOST_EVENT_START |
IWM_TE_V2_NOTIF_HOST_EVENT_END |
IWM_T2_V2_START_IMMEDIATELY);
if (!wait_for_notif) {
iwm_time_event_send_add(sc, ivp, /*te_data*/NULL, &time_cmd);
DELAY(100);
sc->sc_flags |= IWM_FLAG_TE_ACTIVE;
return;
}
/*
* Create notification_wait for the TIME_EVENT_NOTIFICATION to use
* right after we send the time event
*/
iwm_init_notification_wait(sc->sc_notif_wait, &wait_te_notif,
te_notif_response, nitems(te_notif_response),
iwm_te_notif, /*te_data*/NULL);
/* If TE was sent OK - wait for the notification that started */
if (iwm_time_event_send_add(sc, ivp, /*te_data*/NULL, &time_cmd)) {
IWM_DPRINTF(sc, IWM_DEBUG_TE,
"%s: Failed to add TE to protect session\n", __func__);
iwm_remove_notification(sc->sc_notif_wait, &wait_te_notif);
} else {
sc->sc_flags |= IWM_FLAG_TE_ACTIVE;
IWM_UNLOCK(sc);
if (iwm_wait_notification(sc->sc_notif_wait, &wait_te_notif,
TU_TO_HZ(max_delay))) {
IWM_DPRINTF(sc, IWM_DEBUG_TE,
"%s: Failed to protect session until TE\n",
__func__);
}
IWM_LOCK(sc);
}
}
void
iwm_stop_session_protection(struct iwm_softc *sc, struct iwm_vap *ivp)
{
struct iwm_time_event_cmd time_cmd = {};
/* Do nothing if the time event has already ended. */
if ((sc->sc_flags & IWM_FLAG_TE_ACTIVE) == 0)
return;
time_cmd.id = htole32(sc->sc_time_event_uid);
time_cmd.action = htole32(IWM_FW_CTXT_ACTION_REMOVE);
time_cmd.id_and_color =
htole32(IWM_FW_CMD_ID_AND_COLOR(ivp->id, ivp->color));
IWM_DPRINTF(sc, IWM_DEBUG_TE,
"%s: Removing TE 0x%x\n", __func__, le32toh(time_cmd.id));
if (iwm_send_cmd_pdu(sc, IWM_TIME_EVENT_CMD, 0, sizeof(time_cmd),
&time_cmd) == 0)
iwm_te_clear_data(sc);
DELAY(100);
}

View File

@ -1,117 +0,0 @@
/* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
/* $FreeBSD$ */
/*
* Copyright (c) 2014 genua mbh <info@genua.de>
* Copyright (c) 2014 Fixup Software Ltd.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)
*
***********************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*-
* Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef __IF_IWM_TIME_EVENT_H__
#define __IF_IWM_TIME_EVENT_H__
extern void iwm_rx_time_event_notif(struct iwm_softc *sc,
struct iwm_rx_packet *pkt);
extern void iwm_protect_session(struct iwm_softc *sc, struct iwm_vap *ivp,
uint32_t duration, uint32_t max_delay, boolean_t wait_for_notif);
extern void iwm_stop_session_protection(struct iwm_softc *sc,
struct iwm_vap *ivp);
#endif /* __IF_IWM_TIME_EVENT_H__ */

View File

@ -1,532 +0,0 @@
/* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
/*
* Copyright (c) 2014 genua mbh <info@genua.de>
* Copyright (c) 2014 Fixup Software Ltd.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)
*
***********************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*-
* Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include "opt_iwm.h"
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/endian.h>
#include <sys/firmware.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/mutex.h>
#include <sys/module.h>
#include <sys/proc.h>
#include <sys/rman.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/sysctl.h>
#include <sys/linker.h>
#include <machine/bus.h>
#include <machine/endian.h>
#include <machine/resource.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <net/bpf.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_arp.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_types.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/if_ether.h>
#include <netinet/ip.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_regdomain.h>
#include <net80211/ieee80211_ratectl.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/iwm/if_iwmreg.h>
#include <dev/iwm/if_iwmvar.h>
#include <dev/iwm/if_iwm_config.h>
#include <dev/iwm/if_iwm_debug.h>
#include <dev/iwm/if_iwm_binding.h>
#include <dev/iwm/if_iwm_util.h>
#include <dev/iwm/if_iwm_pcie_trans.h>
/*
* Send a command to the firmware. We try to implement the Linux
* driver interface for the routine.
* mostly from if_iwn (iwn_cmd()).
*
* For now, we always copy the first part and map the second one (if it exists).
*/
int
iwm_send_cmd(struct iwm_softc *sc, struct iwm_host_cmd *hcmd)
{
struct iwm_tx_ring *ring = &sc->txq[IWM_CMD_QUEUE];
struct iwm_tfd *desc;
struct iwm_tx_data *txdata = NULL;
struct iwm_device_cmd *cmd;
struct mbuf *m;
bus_dma_segment_t seg;
bus_addr_t paddr;
uint32_t addr_lo;
int error = 0, i, paylen, off;
int code;
int async, wantresp;
int group_id;
int nsegs;
size_t hdrlen, datasz;
uint8_t *data;
code = hcmd->id;
async = hcmd->flags & IWM_CMD_ASYNC;
wantresp = hcmd->flags & IWM_CMD_WANT_SKB;
data = NULL;
for (i = 0, paylen = 0; i < nitems(hcmd->len); i++) {
paylen += hcmd->len[i];
}
/* if the command wants an answer, busy sc_cmd_resp */
if (wantresp) {
KASSERT(!async, ("invalid async parameter"));
while (sc->sc_wantresp != -1)
msleep(&sc->sc_wantresp, &sc->sc_mtx, 0, "iwmcmdsl", 0);
sc->sc_wantresp = ring->qid << 16 | ring->cur;
IWM_DPRINTF(sc, IWM_DEBUG_CMD,
"wantresp is %x\n", sc->sc_wantresp);
}
/*
* Is the hardware still available? (after e.g. above wait).
*/
if (sc->sc_flags & IWM_FLAG_STOPPED) {
error = ENXIO;
goto out;
}
desc = &ring->desc[ring->cur];
txdata = &ring->data[ring->cur];
group_id = iwm_cmd_groupid(code);
if (group_id != 0) {
hdrlen = sizeof(cmd->hdr_wide);
datasz = sizeof(cmd->data_wide);
} else {
hdrlen = sizeof(cmd->hdr);
datasz = sizeof(cmd->data);
}
if (paylen > datasz) {
IWM_DPRINTF(sc, IWM_DEBUG_CMD,
"large command paylen=%u len0=%u\n",
paylen, hcmd->len[0]);
{
/* Command is too large */
size_t totlen = hdrlen + paylen;
if (paylen > IWM_MAX_CMD_PAYLOAD_SIZE) {
device_printf(sc->sc_dev,
"firmware command too long (%zd bytes)\n",
totlen);
error = EINVAL;
goto out;
}
m = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, IWM_RBUF_SIZE);
if (m == NULL) {
error = ENOBUFS;
goto out;
}
m->m_len = m->m_pkthdr.len = m->m_ext.ext_size;
error = bus_dmamap_load_mbuf_sg(ring->data_dmat,
txdata->map, m, &seg, &nsegs, BUS_DMA_NOWAIT);
if (error != 0) {
device_printf(sc->sc_dev,
"%s: can't map mbuf, error %d\n", __func__, error);
m_freem(m);
goto out;
}
txdata->m = m; /* mbuf will be freed in iwm_cmd_done() */
cmd = mtod(m, struct iwm_device_cmd *);
paddr = seg.ds_addr;
}
} else {
cmd = &ring->cmd[ring->cur];
paddr = txdata->cmd_paddr;
}
if (group_id != 0) {
cmd->hdr_wide.opcode = iwm_cmd_opcode(code);
cmd->hdr_wide.group_id = group_id;
cmd->hdr_wide.qid = ring->qid;
cmd->hdr_wide.idx = ring->cur;
cmd->hdr_wide.length = htole16(paylen);
cmd->hdr_wide.version = iwm_cmd_version(code);
data = cmd->data_wide;
} else {
cmd->hdr.code = iwm_cmd_opcode(code);
cmd->hdr.flags = 0;
cmd->hdr.qid = ring->qid;
cmd->hdr.idx = ring->cur;
data = cmd->data;
}
for (i = 0, off = 0; i < nitems(hcmd->data); i++) {
if (hcmd->len[i] == 0)
continue;
memcpy(data + off, hcmd->data[i], hcmd->len[i]);
off += hcmd->len[i];
}
KASSERT(off == paylen, ("off %d != paylen %d", off, paylen));
/* lo field is not aligned */
addr_lo = htole32((uint32_t)paddr);
memcpy(&desc->tbs[0].lo, &addr_lo, sizeof(uint32_t));
desc->tbs[0].hi_n_len = htole16(iwm_get_dma_hi_addr(paddr)
| ((hdrlen + paylen) << 4));
desc->num_tbs = 1;
IWM_DPRINTF(sc, IWM_DEBUG_CMD,
"iwm_send_cmd 0x%x size=%lu %s\n",
code,
(unsigned long) (hcmd->len[0] + hcmd->len[1] + hdrlen),
async ? " (async)" : "");
if (paylen > datasz) {
bus_dmamap_sync(ring->data_dmat, txdata->map,
BUS_DMASYNC_PREWRITE);
} else {
bus_dmamap_sync(ring->cmd_dma.tag, ring->cmd_dma.map,
BUS_DMASYNC_PREWRITE);
}
bus_dmamap_sync(ring->desc_dma.tag, ring->desc_dma.map,
BUS_DMASYNC_PREWRITE);
error = iwm_pcie_set_cmd_in_flight(sc);
if (error)
goto out;
ring->queued++;
#if 0
iwm_update_sched(sc, ring->qid, ring->cur, 0, 0);
#endif
IWM_DPRINTF(sc, IWM_DEBUG_CMD,
"sending command 0x%x qid %d, idx %d\n",
code, ring->qid, ring->cur);
/* Kick command ring. */
ring->cur = (ring->cur + 1) % IWM_TX_RING_COUNT;
IWM_WRITE(sc, IWM_HBUS_TARG_WRPTR, ring->qid << 8 | ring->cur);
if (!async) {
/* m..m-mmyy-mmyyyy-mym-ym m-my generation */
int generation = sc->sc_generation;
error = msleep(desc, &sc->sc_mtx, PCATCH, "iwmcmd", hz);
if (error == 0) {
/* if hardware is no longer up, return error */
if (generation != sc->sc_generation) {
error = ENXIO;
} else {
hcmd->resp_pkt = (void *)sc->sc_cmd_resp;
}
}
}
out:
if (wantresp && error != 0) {
iwm_free_resp(sc, hcmd);
}
return error;
}
/* iwlwifi: mvm/utils.c */
int
iwm_send_cmd_pdu(struct iwm_softc *sc, uint32_t id,
uint32_t flags, uint16_t len, const void *data)
{
struct iwm_host_cmd cmd = {
.id = id,
.len = { len, },
.data = { data, },
.flags = flags,
};
return iwm_send_cmd(sc, &cmd);
}
/* iwlwifi: mvm/utils.c */
int
iwm_send_cmd_status(struct iwm_softc *sc,
struct iwm_host_cmd *cmd, uint32_t *status)
{
struct iwm_rx_packet *pkt;
struct iwm_cmd_response *resp;
int error, resp_len;
KASSERT((cmd->flags & IWM_CMD_WANT_SKB) == 0,
("invalid command"));
cmd->flags |= IWM_CMD_SYNC | IWM_CMD_WANT_SKB;
if ((error = iwm_send_cmd(sc, cmd)) != 0)
return error;
pkt = cmd->resp_pkt;
/* Can happen if RFKILL is asserted */
if (!pkt) {
error = 0;
goto out_free_resp;
}
if (pkt->hdr.flags & IWM_CMD_FAILED_MSK) {
error = EIO;
goto out_free_resp;
}
resp_len = iwm_rx_packet_payload_len(pkt);
if (resp_len != sizeof(*resp)) {
error = EIO;
goto out_free_resp;
}
resp = (void *)pkt->data;
*status = le32toh(resp->status);
out_free_resp:
iwm_free_resp(sc, cmd);
return error;
}
/* iwlwifi/mvm/utils.c */
int
iwm_send_cmd_pdu_status(struct iwm_softc *sc, uint32_t id,
uint16_t len, const void *data, uint32_t *status)
{
struct iwm_host_cmd cmd = {
.id = id,
.len = { len, },
.data = { data, },
};
return iwm_send_cmd_status(sc, &cmd, status);
}
void
iwm_free_resp(struct iwm_softc *sc, struct iwm_host_cmd *hcmd)
{
KASSERT(sc->sc_wantresp != -1, ("already freed"));
KASSERT((hcmd->flags & (IWM_CMD_WANT_SKB|IWM_CMD_SYNC))
== (IWM_CMD_WANT_SKB|IWM_CMD_SYNC), ("invalid flags"));
sc->sc_wantresp = -1;
wakeup(&sc->sc_wantresp);
}
static void
iwm_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
{
if (error != 0)
return;
KASSERT(nsegs == 1, ("too many DMA segments, %d should be 1", nsegs));
*(bus_addr_t *)arg = segs[0].ds_addr;
}
int
iwm_dma_contig_alloc(bus_dma_tag_t tag, struct iwm_dma_info *dma,
bus_size_t size, bus_size_t alignment)
{
int error;
dma->tag = NULL;
dma->map = NULL;
dma->size = size;
dma->vaddr = NULL;
error = bus_dma_tag_create(tag, alignment,
0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, size,
1, size, 0, NULL, NULL, &dma->tag);
if (error != 0)
goto fail;
error = bus_dmamem_alloc(dma->tag, (void **)&dma->vaddr,
BUS_DMA_NOWAIT | BUS_DMA_ZERO | BUS_DMA_COHERENT, &dma->map);
if (error != 0)
goto fail;
error = bus_dmamap_load(dma->tag, dma->map, dma->vaddr, size,
iwm_dma_map_addr, &dma->paddr, BUS_DMA_NOWAIT);
if (error != 0) {
bus_dmamem_free(dma->tag, dma->vaddr, dma->map);
dma->vaddr = NULL;
goto fail;
}
bus_dmamap_sync(dma->tag, dma->map, BUS_DMASYNC_PREWRITE);
return 0;
fail:
iwm_dma_contig_free(dma);
return error;
}
void
iwm_dma_contig_free(struct iwm_dma_info *dma)
{
if (dma->vaddr != NULL) {
bus_dmamap_sync(dma->tag, dma->map,
BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(dma->tag, dma->map);
bus_dmamem_free(dma->tag, dma->vaddr, dma->map);
dma->vaddr = NULL;
}
if (dma->tag != NULL) {
bus_dma_tag_destroy(dma->tag);
dma->tag = NULL;
}
}
/**
* iwm_send_lq_cmd() - Send link quality command
* @init: This command is sent as part of station initialization right
* after station has been added.
*
* The link quality command is sent as the last step of station creation.
* This is the special case in which init is set and we call a callback in
* this case to clear the state indicating that station creation is in
* progress.
*/
int
iwm_send_lq_cmd(struct iwm_softc *sc, struct iwm_lq_cmd *lq, boolean_t init)
{
struct iwm_host_cmd cmd = {
.id = IWM_LQ_CMD,
.len = { sizeof(struct iwm_lq_cmd), },
.flags = init ? 0 : IWM_CMD_ASYNC,
.data = { lq, },
};
if (lq->sta_id == IWM_STATION_COUNT)
return EINVAL;
return iwm_send_cmd(sc, &cmd);
}
boolean_t
iwm_rx_diversity_allowed(struct iwm_softc *sc)
{
if (num_of_ant(iwm_get_valid_rx_ant(sc)) == 1)
return FALSE;
/*
* XXX Also return FALSE when SMPS (Spatial Multiplexing Powersave)
* is used on any vap (in the future).
*/
return TRUE;
}

View File

@ -1,163 +0,0 @@
/* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
/* $FreeBSD$ */
/*
* Copyright (c) 2014 genua mbh <info@genua.de>
* Copyright (c) 2014 Fixup Software Ltd.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)
*
***********************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*-
* Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef __IF_IWM_UTIL_H__
#define __IF_IWM_UTIL_H__
extern int iwm_send_cmd(struct iwm_softc *sc, struct iwm_host_cmd *hcmd);
extern int iwm_send_cmd_pdu(struct iwm_softc *sc, uint32_t id,
uint32_t flags, uint16_t len, const void *data);
extern int iwm_send_cmd_status(struct iwm_softc *sc,
struct iwm_host_cmd *cmd, uint32_t *status);
extern int iwm_send_cmd_pdu_status(struct iwm_softc *sc, uint32_t id,
uint16_t len, const void *data, uint32_t *status);
extern void iwm_free_resp(struct iwm_softc *sc, struct iwm_host_cmd *hcmd);
extern int iwm_dma_contig_alloc(bus_dma_tag_t tag, struct iwm_dma_info *dma,
bus_size_t size, bus_size_t alignment);
extern void iwm_dma_contig_free(struct iwm_dma_info *);
extern int iwm_send_lq_cmd(struct iwm_softc *sc, struct iwm_lq_cmd *lq,
boolean_t init);
extern boolean_t iwm_rx_diversity_allowed(struct iwm_softc *sc);
extern uint8_t iwm_ridx2rate(struct ieee80211_rateset *rs, int ridx);
extern int iwm_enable_txq(struct iwm_softc *sc, int sta_id, int qid, int fifo);
extern int iwm_flush_tx_path(struct iwm_softc *sc, uint32_t tfd_msk,
uint32_t flags);
static inline uint8_t
iwm_get_valid_tx_ant(struct iwm_softc *sc)
{
return sc->nvm_data && sc->nvm_data->valid_tx_ant ?
sc->sc_fw.valid_tx_ant & sc->nvm_data->valid_tx_ant :
sc->sc_fw.valid_tx_ant;
}
static inline uint8_t
iwm_get_valid_rx_ant(struct iwm_softc *sc)
{
return sc->nvm_data && sc->nvm_data->valid_rx_ant ?
sc->sc_fw.valid_rx_ant & sc->nvm_data->valid_rx_ant :
sc->sc_fw.valid_rx_ant;
}
static inline uint32_t
iwm_get_phy_config(struct iwm_softc *sc)
{
uint32_t phy_config = ~(IWM_FW_PHY_CFG_TX_CHAIN |
IWM_FW_PHY_CFG_RX_CHAIN);
uint32_t valid_rx_ant = iwm_get_valid_rx_ant(sc);
uint32_t valid_tx_ant = iwm_get_valid_tx_ant(sc);
phy_config |= valid_tx_ant << IWM_FW_PHY_CFG_TX_CHAIN_POS |
valid_rx_ant << IWM_FW_PHY_CFG_RX_CHAIN_POS;
return sc->sc_fw.phy_config & phy_config;
}
#endif /* __IF_IWM_UTIL_H__ */

View File

@ -1,585 +0,0 @@
/* $OpenBSD: if_iwmvar.h,v 1.7 2015/03/02 13:51:10 jsg Exp $ */
/* $FreeBSD$ */
/*
* Copyright (c) 2014 genua mbh <info@genua.de>
* Copyright (c) 2014 Fixup Software Ltd.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)
*
***********************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*-
* Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
struct iwm_rx_radiotap_header {
struct ieee80211_radiotap_header wr_ihdr;
uint64_t wr_tsft;
uint8_t wr_flags;
uint8_t wr_rate;
uint16_t wr_chan_freq;
uint16_t wr_chan_flags;
int8_t wr_dbm_antsignal;
int8_t wr_dbm_antnoise;
} __packed __aligned(8);
#define IWM_RX_RADIOTAP_PRESENT \
((1 << IEEE80211_RADIOTAP_TSFT) | \
(1 << IEEE80211_RADIOTAP_FLAGS) | \
(1 << IEEE80211_RADIOTAP_RATE) | \
(1 << IEEE80211_RADIOTAP_CHANNEL) | \
(1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | \
(1 << IEEE80211_RADIOTAP_DBM_ANTNOISE))
struct iwm_tx_radiotap_header {
struct ieee80211_radiotap_header wt_ihdr;
uint8_t wt_flags;
uint8_t wt_rate;
uint16_t wt_chan_freq;
uint16_t wt_chan_flags;
} __packed;
#define IWM_TX_RADIOTAP_PRESENT \
((1 << IEEE80211_RADIOTAP_FLAGS) | \
(1 << IEEE80211_RADIOTAP_RATE) | \
(1 << IEEE80211_RADIOTAP_CHANNEL))
#define IWM_UCODE_SECTION_MAX 16
/**
* enum iwm_ucode_type
*
* The type of ucode.
*
* @IWM_UCODE_REGULAR: Normal runtime ucode
* @IWM_UCODE_INIT: Initial ucode
* @IWM_UCODE_WOWLAN: Wake on Wireless enabled ucode
* @IWM_UCODE_REGULAR_USNIFFER: Normal runtime ucode when using usniffer image
*/
enum iwm_ucode_type {
IWM_UCODE_REGULAR,
IWM_UCODE_INIT,
IWM_UCODE_WOWLAN,
IWM_UCODE_REGULAR_USNIFFER,
IWM_UCODE_TYPE_MAX
};
struct iwm_ucode_capabilities {
uint32_t max_probe_length;
uint32_t n_scan_channels;
uint32_t flags;
uint8_t enabled_api[howmany(IWM_NUM_UCODE_TLV_API, NBBY)];
uint8_t enabled_capa[howmany(IWM_NUM_UCODE_TLV_CAPA, NBBY)];
};
/* one for each uCode image (inst/data, init/runtime/wowlan) */
struct iwm_fw_desc {
const void *data; /* vmalloc'ed data */
uint32_t len; /* size in bytes */
uint32_t offset; /* offset in the device */
};
struct iwm_fw_img {
struct iwm_fw_desc sec[IWM_UCODE_SECTION_MAX];
int fw_count;
int is_dual_cpus;
uint32_t paging_mem_size;
};
struct iwm_fw_info {
const struct firmware *fw_fp;
/* ucode images */
struct iwm_fw_img img[IWM_UCODE_TYPE_MAX];
struct iwm_ucode_capabilities ucode_capa;
uint32_t phy_config;
uint8_t valid_tx_ant;
uint8_t valid_rx_ant;
};
struct iwm_nvm_data {
int n_hw_addrs;
uint8_t hw_addr[IEEE80211_ADDR_LEN];
int sku_cap_band_24GHz_enable;
int sku_cap_band_52GHz_enable;
int sku_cap_11n_enable;
int sku_cap_amt_enable;
int sku_cap_ipan_enable;
uint8_t radio_cfg_type;
uint8_t radio_cfg_step;
uint8_t radio_cfg_dash;
uint8_t radio_cfg_pnum;
uint8_t valid_tx_ant, valid_rx_ant;
#define IWM_NUM_CHANNELS 39
#define IWM_NUM_CHANNELS_8000 51
uint16_t nvm_version;
uint8_t max_tx_pwr_half_dbm;
boolean_t lar_enabled;
uint16_t nvm_ch_flags[0];
};
/* max bufs per tfd the driver will use */
#define IWM_MAX_CMD_TBS_PER_TFD 2
struct iwm_rx_packet;
struct iwm_host_cmd {
const void *data[IWM_MAX_CMD_TBS_PER_TFD];
struct iwm_rx_packet *resp_pkt;
unsigned long _rx_page_addr;
uint32_t _rx_page_order;
int handler_status;
uint32_t flags;
uint32_t id;
uint16_t len[IWM_MAX_CMD_TBS_PER_TFD];
uint8_t dataflags[IWM_MAX_CMD_TBS_PER_TFD];
};
/*
* DMA glue is from iwn
*/
typedef caddr_t iwm_caddr_t;
typedef void *iwm_hookarg_t;
struct iwm_dma_info {
bus_dma_tag_t tag;
bus_dmamap_t map;
bus_dma_segment_t seg;
bus_addr_t paddr;
void *vaddr;
bus_size_t size;
};
/**
* struct iwm_fw_paging
* @fw_paging_block: dma memory info
* @fw_paging_size: page size
*/
struct iwm_fw_paging {
struct iwm_dma_info fw_paging_block;
uint32_t fw_paging_size;
};
#define IWM_TX_RING_COUNT 256
#define IWM_TX_RING_LOMARK 192
#define IWM_TX_RING_HIMARK 224
struct iwm_tx_data {
bus_dmamap_t map;
bus_addr_t cmd_paddr;
bus_addr_t scratch_paddr;
struct mbuf *m;
struct iwm_node *in;
int done;
};
struct iwm_tx_ring {
struct iwm_dma_info desc_dma;
struct iwm_dma_info cmd_dma;
struct iwm_tfd *desc;
struct iwm_device_cmd *cmd;
bus_dma_tag_t data_dmat;
struct iwm_tx_data data[IWM_TX_RING_COUNT];
int qid;
int queued;
int cur;
};
#define IWM_RX_LEGACY_RING_COUNT 256
#define IWM_RX_MQ_RING_COUNT 512
#define IWM_RBUF_SIZE 4096
#define IWM_MAX_SCATTER 20
struct iwm_rx_data {
struct mbuf *m;
bus_dmamap_t map;
};
struct iwm_rx_ring {
struct iwm_dma_info free_desc_dma;
struct iwm_dma_info used_desc_dma;
struct iwm_dma_info stat_dma;
struct iwm_dma_info buf_dma;
void *desc;
struct iwm_rb_status *stat;
struct iwm_rx_data data[512];
bus_dmamap_t spare_map; /* for iwm_rx_addbuf() */
bus_dma_tag_t data_dmat;
int cur;
};
#define IWM_CMD_RESP_MAX PAGE_SIZE
#define IWM_TE_SESSION_PROTECTION_MAX_TIME_MS 500
#define IWM_TE_SESSION_PROTECTION_MIN_TIME_MS 400
/*
* Command headers are in iwl-trans.h, which is full of all
* kinds of other junk, so we just replicate the structures here.
* First the software bits:
*/
enum IWM_CMD_MODE {
IWM_CMD_SYNC = 0,
IWM_CMD_ASYNC = (1 << 0),
IWM_CMD_WANT_SKB = (1 << 1),
IWM_CMD_SEND_IN_RFKILL = (1 << 2),
};
enum iwm_hcmd_dataflag {
IWM_HCMD_DFL_NOCOPY = (1 << 0),
IWM_HCMD_DFL_DUP = (1 << 1),
};
struct iwm_int_sta {
uint32_t sta_id;
uint32_t tfd_queue_msk;
};
struct iwm_phy_ctxt {
uint16_t id;
uint16_t color;
uint32_t ref;
struct ieee80211_channel *channel;
};
struct iwm_bf_data {
int bf_enabled; /* filtering */
int ba_enabled; /* abort */
int ave_beacon_signal;
int last_cqm_event;
};
struct iwm_vap {
struct ieee80211vap iv_vap;
int is_uploaded;
int iv_auth;
int (*iv_newstate)(struct ieee80211vap *,
enum ieee80211_state, int);
struct iwm_phy_ctxt *phy_ctxt;
uint16_t id;
uint16_t color;
boolean_t have_wme;
/*
* QoS data from net80211, need to store this here
* as net80211 has a separate callback but we need
* to have the data for the MAC context
*/
struct {
uint16_t cw_min;
uint16_t cw_max;
uint16_t edca_txop;
uint8_t aifsn;
} queue_params[WME_NUM_AC];
/* indicates that this interface requires PS to be disabled */
boolean_t ps_disabled;
};
#define IWM_VAP(_vap) ((struct iwm_vap *)(_vap))
struct iwm_node {
struct ieee80211_node in_ni;
/* status "bits" */
int in_assoc;
struct iwm_lq_cmd in_lq;
};
#define IWM_NODE(_ni) ((struct iwm_node *)(_ni))
#define IWM_STATION_ID 0
#define IWM_AUX_STA_ID 1
#define IWM_DEFAULT_MACID 0
#define IWM_DEFAULT_COLOR 0
#define IWM_DEFAULT_TSFID 0
#define IWM_ICT_SIZE 4096
#define IWM_ICT_COUNT (IWM_ICT_SIZE / sizeof (uint32_t))
#define IWM_ICT_PADDR_SHIFT 12
struct iwm_cfg;
struct iwm_softc {
device_t sc_dev;
uint32_t sc_debug;
int sc_attached;
struct mtx sc_mtx;
struct mbufq sc_snd;
struct ieee80211com sc_ic;
struct ieee80211_ratectl_tx_status sc_txs;
int sc_flags;
#define IWM_FLAG_USE_ICT (1 << 0)
#define IWM_FLAG_HW_INITED (1 << 1)
#define IWM_FLAG_STOPPED (1 << 2)
#define IWM_FLAG_RFKILL (1 << 3)
#define IWM_FLAG_BUSY (1 << 4)
#define IWM_FLAG_SCANNING (1 << 5)
#define IWM_FLAG_SCAN_RUNNING (1 << 6)
#define IWM_FLAG_TE_ACTIVE (1 << 7)
struct intr_config_hook sc_preinit_hook;
struct callout sc_watchdog_to;
struct callout sc_led_blink_to;
struct task init_task;
struct resource *sc_irq;
struct resource *sc_mem;
bus_space_tag_t sc_st;
bus_space_handle_t sc_sh;
bus_size_t sc_sz;
bus_dma_tag_t sc_dmat;
void *sc_ih;
/* TX scheduler rings. */
struct iwm_dma_info sched_dma;
uint32_t scd_base_addr;
/* TX/RX rings. */
struct iwm_tx_ring txq[IWM_MAX_QUEUES];
struct iwm_rx_ring rxq;
int qfullmsk;
/* ICT table. */
struct iwm_dma_info ict_dma;
int ict_cur;
int sc_hw_rev;
int sc_hw_id;
struct iwm_dma_info kw_dma;
struct iwm_dma_info fw_dma;
int sc_fw_chunk_done;
enum iwm_ucode_type cur_ucode;
int ucode_loaded;
char sc_fwver[32];
char sc_fw_mcc[3];
int sc_intmask;
/*
* So why do we need a separate stopped flag and a generation?
* the former protects the device from issuing commands when it's
* stopped (duh). The latter protects against race from a very
* fast stop/unstop cycle where threads waiting for responses do
* not have a chance to run in between. Notably: we want to stop
* the device from interrupt context when it craps out, so we
* don't have the luxury of waiting for quiescense.
*/
int sc_generation;
struct iwm_fw_info sc_fw;
struct iwm_tlv_calib_ctrl sc_default_calib[IWM_UCODE_TYPE_MAX];
const struct iwm_cfg *cfg;
struct iwm_nvm_data *nvm_data;
struct iwm_phy_db *sc_phy_db;
struct iwm_bf_data sc_bf;
int sc_tx_timer;
int sc_scan_last_antenna;
int sc_fixed_ridx;
int sc_staid;
int sc_nodecolor;
uint8_t sc_cmd_resp[IWM_CMD_RESP_MAX];
int sc_wantresp;
struct taskqueue *sc_tq;
struct task sc_es_task;
struct task sc_rftoggle_task;
struct iwm_rx_phy_info sc_last_phy_info;
int sc_ampdu_ref;
struct iwm_int_sta sc_aux_sta;
/* phy contexts. we only use the first one */
struct iwm_phy_ctxt sc_phyctxt[IWM_NUM_PHY_CTX];
struct iwm_notif_statistics_v10 sc_stats;
int sc_noise;
struct iwm_rx_radiotap_header sc_rxtap;
struct iwm_tx_radiotap_header sc_txtap;
int sc_max_rssi;
struct iwm_notif_wait_data *sc_notif_wait;
int cmd_hold_nic_awake;
/* Firmware status */
uint32_t error_event_table[2];
uint32_t log_event_table;
uint32_t umac_error_event_table;
int support_umac_log;
/*
* Paging parameters - All of the parameters should be set by the
* opmode when paging is enabled
*/
struct iwm_fw_paging fw_paging_db[IWM_NUM_OF_FW_PAGING_BLOCKS];
uint16_t num_of_paging_blk;
uint16_t num_of_pages_in_last_blk;
boolean_t last_ebs_successful;
/* last smart fifo state that was successfully sent to firmware */
enum iwm_sf_state sf_state;
/* Indicate if device power save is allowed */
boolean_t sc_ps_disabled;
int sc_ltr_enabled;
/* Track firmware state for STA association. */
int sc_firmware_state;
/* Unique ID (assigned by the firmware) of the current Time Event. */
uint32_t sc_time_event_uid;
/* Duration of the Time Event in TU. */
uint32_t sc_time_event_duration;
/* Expected end of the Time Event in HZ ticks. */
int sc_time_event_end_ticks;
#ifdef __HAIKU__
uint32_t sc_intr_status_1;
uint32_t sc_intr_status_2;
#endif
};
#define IWM_LOCK_INIT(_sc) \
mtx_init(&(_sc)->sc_mtx, device_get_nameunit((_sc)->sc_dev), \
MTX_NETWORK_LOCK, MTX_DEF);
#define IWM_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
#define IWM_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
#define IWM_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->sc_mtx)
static inline bool
iwm_fw_has_api(struct iwm_softc *sc, unsigned int api)
{
return isset(sc->sc_fw.ucode_capa.enabled_api, api);
}
static inline bool
iwm_fw_has_capa(struct iwm_softc *sc, unsigned int capa)
{
return isset(sc->sc_fw.ucode_capa.enabled_capa, capa);
}

View File

@ -1,2 +0,0 @@
//#define IEEE80211_SUPPORT_SUPERG 1
//#define IEEE80211_SUPPORT_TDMA 1

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,692 @@
/* $OpenBSD: if_iwmvar.h,v 1.77 2022/03/19 14:50:01 stsp Exp $ */
/*
* Copyright (c) 2014 genua mbh <info@genua.de>
* Copyright (c) 2014 Fixup Software Ltd.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)
*
***********************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*-
* Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
struct iwm_rx_radiotap_header {
struct ieee80211_radiotap_header wr_ihdr;
uint64_t wr_tsft;
uint8_t wr_flags;
uint8_t wr_rate;
uint16_t wr_chan_freq;
uint16_t wr_chan_flags;
int8_t wr_dbm_antsignal;
int8_t wr_dbm_antnoise;
} __packed;
#define IWM_RX_RADIOTAP_PRESENT \
((1 << IEEE80211_RADIOTAP_TSFT) | \
(1 << IEEE80211_RADIOTAP_FLAGS) | \
(1 << IEEE80211_RADIOTAP_RATE) | \
(1 << IEEE80211_RADIOTAP_CHANNEL) | \
(1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | \
(1 << IEEE80211_RADIOTAP_DBM_ANTNOISE))
struct iwm_tx_radiotap_header {
struct ieee80211_radiotap_header wt_ihdr;
uint8_t wt_flags;
uint8_t wt_rate;
uint16_t wt_chan_freq;
uint16_t wt_chan_flags;
} __packed;
#define IWM_TX_RADIOTAP_PRESENT \
((1 << IEEE80211_RADIOTAP_FLAGS) | \
(1 << IEEE80211_RADIOTAP_RATE) | \
(1 << IEEE80211_RADIOTAP_CHANNEL))
#define IWM_UCODE_SECT_MAX 16
#define IWM_FWDMASEGSZ (192*1024)
#define IWM_FWDMASEGSZ_8000 (320*1024)
/* sanity check value */
#define IWM_FWMAXSIZE (2*1024*1024)
/*
* fw_status is used to determine if we've already parsed the firmware file
*
* In addition to the following, status < 0 ==> -error
*/
#define IWM_FW_STATUS_NONE 0
#define IWM_FW_STATUS_INPROGRESS 1
#define IWM_FW_STATUS_DONE 2
enum iwm_ucode_type {
IWM_UCODE_TYPE_REGULAR,
IWM_UCODE_TYPE_INIT,
IWM_UCODE_TYPE_WOW,
IWM_UCODE_TYPE_REGULAR_USNIFFER,
IWM_UCODE_TYPE_MAX
};
struct iwm_fw_info {
void *fw_rawdata;
size_t fw_rawsize;
int fw_status;
struct iwm_fw_sects {
struct iwm_fw_onesect {
void *fws_data;
uint32_t fws_len;
uint32_t fws_devoff;
} fw_sect[IWM_UCODE_SECT_MAX];
size_t fw_totlen;
int fw_count;
uint32_t paging_mem_size;
} fw_sects[IWM_UCODE_TYPE_MAX];
};
struct iwm_nvm_data {
int n_hw_addrs;
uint8_t hw_addr[ETHER_ADDR_LEN];
uint8_t calib_version;
uint16_t calib_voltage;
uint16_t raw_temperature;
uint16_t kelvin_temperature;
uint16_t kelvin_voltage;
uint16_t xtal_calib[2];
int sku_cap_band_24GHz_enable;
int sku_cap_band_52GHz_enable;
int sku_cap_11n_enable;
int sku_cap_11ac_enable;
int sku_cap_amt_enable;
int sku_cap_ipan_enable;
int sku_cap_mimo_disable;
uint8_t radio_cfg_type;
uint8_t radio_cfg_step;
uint8_t radio_cfg_dash;
uint8_t radio_cfg_pnum;
uint8_t valid_tx_ant, valid_rx_ant;
uint16_t nvm_version;
uint8_t max_tx_pwr_half_dbm;
int lar_enabled;
};
/* max bufs per tfd the driver will use */
#define IWM_MAX_CMD_TBS_PER_TFD 2
struct iwm_host_cmd {
const void *data[IWM_MAX_CMD_TBS_PER_TFD];
struct iwm_rx_packet *resp_pkt;
size_t resp_pkt_len;
unsigned long _rx_page_addr;
uint32_t _rx_page_order;
int handler_status;
uint32_t flags;
uint16_t len[IWM_MAX_CMD_TBS_PER_TFD];
uint8_t dataflags[IWM_MAX_CMD_TBS_PER_TFD];
uint32_t id;
};
/*
* DMA glue is from iwn
*/
struct iwm_dma_info {
bus_dma_tag_t tag;
bus_dmamap_t map;
bus_dma_segment_t seg;
bus_addr_t paddr;
void *vaddr;
bus_size_t size;
};
/**
* struct iwm_fw_paging
* @fw_paging_block: dma memory info
* @fw_paging_size: page size
*/
struct iwm_fw_paging {
struct iwm_dma_info fw_paging_block;
uint32_t fw_paging_size;
};
#define IWM_TX_RING_COUNT 256
#define IWM_TX_RING_LOMARK 192
#define IWM_TX_RING_HIMARK 224
/* For aggregation queues, index must be aligned to frame sequence number. */
#define IWM_AGG_SSN_TO_TXQ_IDX(x) ((x) & (IWM_TX_RING_COUNT - 1))
struct iwm_tx_data {
bus_dmamap_t map;
bus_addr_t cmd_paddr;
bus_addr_t scratch_paddr;
struct mbuf *m;
struct iwm_node *in;
int txmcs;
int txrate;
/* A-MPDU subframes */
int ampdu_txmcs;
int ampdu_txnss;
int ampdu_nframes;
};
struct iwm_tx_ring {
struct iwm_dma_info desc_dma;
struct iwm_dma_info cmd_dma;
struct iwm_tfd *desc;
struct iwm_device_cmd *cmd;
struct iwm_tx_data data[IWM_TX_RING_COUNT];
int qid;
int queued;
int cur;
int tail;
};
#define IWM_RX_MQ_RING_COUNT 512
#define IWM_RX_RING_COUNT 256
/* Linux driver optionally uses 8k buffer */
#define IWM_RBUF_SIZE 4096
struct iwm_rx_data {
struct mbuf *m;
bus_dmamap_t map;
};
struct iwm_rx_ring {
struct iwm_dma_info free_desc_dma;
struct iwm_dma_info stat_dma;
struct iwm_dma_info used_desc_dma;
struct iwm_dma_info buf_dma;
void *desc;
struct iwm_rb_status *stat;
struct iwm_rx_data data[IWM_RX_MQ_RING_COUNT];
int cur;
};
#define IWM_FLAG_USE_ICT 0x01 /* using Interrupt Cause Table */
#define IWM_FLAG_RFKILL 0x02 /* radio kill switch is set */
#define IWM_FLAG_SCANNING 0x04 /* scan in progress */
#define IWM_FLAG_MAC_ACTIVE 0x08 /* MAC context added to firmware */
#define IWM_FLAG_BINDING_ACTIVE 0x10 /* MAC->PHY binding added to firmware */
#define IWM_FLAG_STA_ACTIVE 0x20 /* AP added to firmware station table */
#define IWM_FLAG_TE_ACTIVE 0x40 /* time event is scheduled */
#define IWM_FLAG_HW_ERR 0x80 /* hardware error occurred */
#define IWM_FLAG_SHUTDOWN 0x100 /* shutting down; new tasks forbidden */
#define IWM_FLAG_BGSCAN 0x200 /* background scan in progress */
#define IWM_FLAG_TXFLUSH 0x400 /* Tx queue flushing in progress */
struct iwm_ucode_status {
uint32_t uc_error_event_table;
uint32_t uc_umac_error_event_table;
uint32_t uc_log_event_table;
int uc_ok;
int uc_intr;
};
#define IWM_CMD_RESP_MAX PAGE_SIZE
/* lower blocks contain EEPROM image and calibration data */
#define IWM_OTP_LOW_IMAGE_SIZE_FAMILY_7000 16384
#define IWM_OTP_LOW_IMAGE_SIZE_FAMILY_8000 32768
#define IWM_TE_SESSION_PROTECTION_MAX_TIME_MS 1000
#define IWM_TE_SESSION_PROTECTION_MIN_TIME_MS 400
enum IWM_CMD_MODE {
IWM_CMD_ASYNC = (1 << 0),
IWM_CMD_WANT_RESP = (1 << 1),
IWM_CMD_SEND_IN_RFKILL = (1 << 2),
};
enum iwm_hcmd_dataflag {
IWM_HCMD_DFL_NOCOPY = (1 << 0),
IWM_HCMD_DFL_DUP = (1 << 1),
};
#define IWM_NUM_PAPD_CH_GROUPS 9
#define IWM_NUM_TXP_CH_GROUPS 9
struct iwm_phy_db_entry {
uint16_t size;
uint8_t *data;
};
struct iwm_phy_db {
struct iwm_phy_db_entry cfg;
struct iwm_phy_db_entry calib_nch;
struct iwm_phy_db_entry calib_ch_group_papd[IWM_NUM_PAPD_CH_GROUPS];
struct iwm_phy_db_entry calib_ch_group_txp[IWM_NUM_TXP_CH_GROUPS];
};
struct iwm_phy_ctxt {
uint16_t id;
uint16_t color;
uint32_t ref;
struct ieee80211_channel *channel;
uint8_t sco; /* 40 MHz secondary channel offset */
uint8_t vht_chan_width;
};
struct iwm_bf_data {
int bf_enabled; /* filtering */
int ba_enabled; /* abort */
int ave_beacon_signal;
int last_cqm_event;
};
/**
* struct iwm_reorder_buffer - per ra/tid/queue reorder buffer
* @head_sn: reorder window head sn
* @num_stored: number of mpdus stored in the buffer
* @buf_size: the reorder buffer size as set by the last addba request
* @queue: queue of this reorder buffer
* @last_amsdu: track last ASMDU SN for duplication detection
* @last_sub_index: track ASMDU sub frame index for duplication detection
* @reorder_timer: timer for frames are in the reorder buffer. For AMSDU
* it is the time of last received sub-frame
* @removed: prevent timer re-arming
* @valid: reordering is valid for this queue
* @consec_oldsn_drops: consecutive drops due to old SN
* @consec_oldsn_ampdu_gp2: A-MPDU GP2 timestamp to track
* when to apply old SN consecutive drop workaround
* @consec_oldsn_prev_drop: track whether or not an MPDU
* that was single/part of the previous A-MPDU was
* dropped due to old SN
*/
struct iwm_reorder_buffer {
uint16_t head_sn;
uint16_t num_stored;
uint16_t buf_size;
uint16_t last_amsdu;
uint8_t last_sub_index;
struct timeout reorder_timer;
int removed;
int valid;
unsigned int consec_oldsn_drops;
uint32_t consec_oldsn_ampdu_gp2;
unsigned int consec_oldsn_prev_drop;
#define IWM_AMPDU_CONSEC_DROPS_DELBA 10
};
/**
* struct iwm_reorder_buf_entry - reorder buffer entry per frame sequence number
* @frames: list of mbufs stored (A-MSDU subframes share a sequence number)
* @reorder_time: time the packet was stored in the reorder buffer
*/
struct iwm_reorder_buf_entry {
struct mbuf_list frames;
struct timeval reorder_time;
uint32_t rx_pkt_status;
int chanidx;
int is_shortpre;
uint32_t rate_n_flags;
uint32_t device_timestamp;
struct ieee80211_rxinfo rxi;
};
/**
* struct iwm_rxba_data - BA session data
* @sta_id: station id
* @tid: tid of the session
* @baid: baid of the session
* @timeout: the timeout set in the addba request
* @entries_per_queue: # of buffers per queue
* @last_rx: last rx timestamp, updated only if timeout passed from last update
* @session_timer: timer to check if BA session expired, runs at 2 * timeout
* @sc: softc pointer, needed for timer context
* @reorder_buf: reorder buffer
* @reorder_buf_data: buffered frames, one entry per sequence number
*/
struct iwm_rxba_data {
uint8_t sta_id;
uint8_t tid;
uint8_t baid;
uint16_t timeout;
uint16_t entries_per_queue;
struct timeval last_rx;
struct timeout session_timer;
struct iwm_softc *sc;
struct iwm_reorder_buffer reorder_buf;
struct iwm_reorder_buf_entry entries[IEEE80211_BA_MAX_WINSZ];
};
static inline struct iwm_rxba_data *
iwm_rxba_data_from_reorder_buf(struct iwm_reorder_buffer *buf)
{
return (void *)((uint8_t *)buf -
offsetof(struct iwm_rxba_data, reorder_buf));
}
/**
* struct iwm_rxq_dup_data - per station per rx queue data
* @last_seq: last sequence per tid for duplicate packet detection
* @last_sub_frame: last subframe packet
*/
struct iwm_rxq_dup_data {
uint16_t last_seq[IWM_MAX_TID_COUNT + 1];
uint8_t last_sub_frame[IWM_MAX_TID_COUNT + 1];
};
struct iwm_ba_task_data {
uint32_t start_tidmask;
uint32_t stop_tidmask;
};
struct iwm_softc {
struct device sc_dev;
struct ieee80211com sc_ic;
int (*sc_newstate)(struct ieee80211com *, enum ieee80211_state, int);
int sc_newstate_pending;
int attached;
struct ieee80211_amrr sc_amrr;
struct timeout sc_calib_to;
struct timeout sc_led_blink_to;
struct task init_task; /* NB: not reference-counted */
struct refcnt task_refs;
struct task newstate_task;
enum ieee80211_state ns_nstate;
int ns_arg;
/* Task for firmware BlockAck setup/teardown and its arguments. */
struct task ba_task;
struct iwm_ba_task_data ba_rx;
struct iwm_ba_task_data ba_tx;
/* Task for ERP/HT prot/slot-time/EDCA updates. */
struct task mac_ctxt_task;
/* Task for HT 20/40 MHz channel width updates. */
struct task phy_ctxt_task;
bus_space_tag_t sc_st;
bus_space_handle_t sc_sh;
bus_size_t sc_sz;
bus_dma_tag_t sc_dmat;
pci_chipset_tag_t sc_pct;
pcitag_t sc_pcitag;
const void *sc_ih;
int sc_msix;
/* TX scheduler rings. */
struct iwm_dma_info sched_dma;
uint32_t sched_base;
/* TX/RX rings. */
struct iwm_tx_ring txq[IWM_MAX_QUEUES];
struct iwm_rx_ring rxq;
int qfullmsk;
int qenablemsk;
int cmdqid;
int sc_sf_state;
/* ICT table. */
struct iwm_dma_info ict_dma;
int ict_cur;
int sc_hw_rev;
#define IWM_SILICON_A_STEP 0
#define IWM_SILICON_B_STEP 1
#define IWM_SILICON_C_STEP 2
#define IWM_SILICON_D_STEP 3
int sc_hw_id;
int sc_device_family;
#define IWM_DEVICE_FAMILY_7000 1
#define IWM_DEVICE_FAMILY_8000 2
#define IWM_DEVICE_FAMILY_9000 3
struct iwm_dma_info kw_dma;
struct iwm_dma_info fw_dma;
int sc_fw_chunk_done;
int sc_init_complete;
#define IWM_INIT_COMPLETE 0x01
#define IWM_CALIB_COMPLETE 0x02
struct iwm_ucode_status sc_uc;
enum iwm_ucode_type sc_uc_current;
char sc_fwver[32];
int sc_capaflags;
int sc_capa_max_probe_len;
int sc_capa_n_scan_channels;
uint8_t sc_ucode_api[howmany(IWM_NUM_UCODE_TLV_API, NBBY)];
uint8_t sc_enabled_capa[howmany(IWM_NUM_UCODE_TLV_CAPA, NBBY)];
#define IWM_MAX_FW_CMD_VERSIONS 64
struct iwm_fw_cmd_version cmd_versions[IWM_MAX_FW_CMD_VERSIONS];
int n_cmd_versions;
int sc_intmask;
int sc_flags;
uint32_t sc_fh_init_mask;
uint32_t sc_hw_init_mask;
uint32_t sc_fh_mask;
uint32_t sc_hw_mask;
/*
* So why do we need a separate stopped flag and a generation?
* the former protects the device from issuing commands when it's
* stopped (duh). The latter protects against race from a very
* fast stop/unstop cycle where threads waiting for responses do
* not have a chance to run in between. Notably: we want to stop
* the device from interrupt context when it craps out, so we
* don't have the luxury of waiting for quiescence.
*/
int sc_generation;
struct rwlock ioctl_rwl;
int sc_cap_off; /* PCIe caps */
const char *sc_fwname;
bus_size_t sc_fwdmasegsz;
size_t sc_nvm_max_section_size;
struct iwm_fw_info sc_fw;
uint32_t sc_fw_phy_config;
uint32_t sc_extra_phy_config;
struct iwm_tlv_calib_ctrl sc_default_calib[IWM_UCODE_TYPE_MAX];
struct iwm_nvm_data sc_nvm;
struct iwm_phy_db sc_phy_db;
struct iwm_bf_data sc_bf;
int sc_tx_timer[IWM_MAX_QUEUES];
int sc_rx_ba_sessions;
int tx_ba_queue_mask;
struct task bgscan_done_task;
struct ieee80211_node_switch_bss_arg *bgscan_unref_arg;
size_t bgscan_unref_arg_size;
int sc_scan_last_antenna;
int sc_fixed_ridx;
int sc_staid;
int sc_nodecolor;
uint8_t *sc_cmd_resp_pkt[IWM_TX_RING_COUNT];
size_t sc_cmd_resp_len[IWM_TX_RING_COUNT];
int sc_nic_locks;
struct taskq *sc_nswq;
struct iwm_rx_phy_info sc_last_phy_info;
int sc_ampdu_ref;
#define IWM_MAX_BAID 32
struct iwm_rxba_data sc_rxba_data[IWM_MAX_BAID];
uint32_t sc_time_event_uid;
/* phy contexts. we only use the first one */
struct iwm_phy_ctxt sc_phyctxt[IWM_NUM_PHY_CTX];
struct iwm_notif_statistics sc_stats;
int sc_noise;
int host_interrupt_operation_mode;
int sc_ltr_enabled;
enum iwm_nvm_type nvm_type;
int sc_mqrx_supported;
int sc_integrated;
int sc_ltr_delay;
int sc_xtal_latency;
int sc_low_latency_xtal;
/*
* Paging parameters - All of the parameters should be set by the
* opmode when paging is enabled
*/
struct iwm_fw_paging fw_paging_db[IWM_NUM_OF_FW_PAGING_BLOCKS];
uint16_t num_of_paging_blk;
uint16_t num_of_pages_in_last_blk;
#if NBPFILTER > 0
caddr_t sc_drvbpf;
union {
struct iwm_rx_radiotap_header th;
uint8_t pad[IEEE80211_RADIOTAP_HDRLEN];
} sc_rxtapu;
#define sc_rxtap sc_rxtapu.th
int sc_rxtap_len;
union {
struct iwm_tx_radiotap_header th;
uint8_t pad[IEEE80211_RADIOTAP_HDRLEN];
} sc_txtapu;
#define sc_txtap sc_txtapu.th
int sc_txtap_len;
#endif
};
struct iwm_node {
struct ieee80211_node in_ni;
struct iwm_phy_ctxt *in_phyctxt;
uint8_t in_macaddr[ETHER_ADDR_LEN];
uint16_t in_id;
uint16_t in_color;
struct ieee80211_amrr_node in_amn;
struct ieee80211_ra_node in_rn;
struct ieee80211_ra_vht_node in_rn_vht;
int lq_rate_mismatch;
struct iwm_rxq_dup_data dup_data;
/* For use with the ADD_STA command. */
uint32_t tfd_queue_msk;
uint16_t tid_disable_ampdu;
};
#define IWM_STATION_ID 0
#define IWM_AUX_STA_ID 1
#define IWM_MONITOR_STA_ID 2
#define IWM_ICT_SIZE 4096
#define IWM_ICT_COUNT (IWM_ICT_SIZE / sizeof (uint32_t))
#define IWM_ICT_PADDR_SHIFT 12