* [PATCH 07/10] iwlwifi: mvm: handle FIF_ALLMULTI when setting multicast addresses
From: Luca Coelho @ 2017-09-08 9:12 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, Luca Coelho
In-Reply-To: <20170908091256.25279-1-luca@coelho.fi>
From: Luca Coelho <luciano.coelho@intel.com>
We were ignoring the FIF_ALLMULTI flag when setting the multicast
addresses with MCAST_FILTER_CMD. Check if this flag is set and enable
pass_all accordingly. We also need to set the count to 0 if pass_all
is enable so we don't pass addresses to the firmware when not needed
(as doing so causes an assert).
This fixes https://bugzilla.kernel.org/show_bug.cgi?id=196741
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 635db63f972e..3bcaa82f59b2 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -1643,6 +1643,12 @@ static void iwl_mvm_configure_filter(struct ieee80211_hw *hw,
if (!cmd)
goto out;
+ if (changed_flags & FIF_ALLMULTI)
+ cmd->pass_all = !!(*total_flags & FIF_ALLMULTI);
+
+ if (cmd->pass_all)
+ cmd->count = 0;
+
iwl_mvm_recalc_multicast(mvm);
out:
mutex_unlock(&mvm->mutex);
--
2.14.1
^ permalink raw reply related
* [PATCH 06/10] iwlwifi: mvm: use IWL_HCMD_NOCOPY for MCAST_FILTER_CMD
From: Luca Coelho @ 2017-09-08 9:12 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, Luca Coelho, stable
In-Reply-To: <20170908091256.25279-1-luca@coelho.fi>
From: Luca Coelho <luciano.coelho@intel.com>
The MCAST_FILTER_CMD can get quite large when we have many mcast
addresses to set (we support up to 255). So the command should be
send as NOCOPY to prevent a warning caused by too-long commands:
WARNING: CPU: 0 PID: 9700 at /root/iwlwifi/stack-dev/drivers/net/wireless/intel/iwlwifi/pcie/tx.c:1550 iwl_pcie_enqueue_hcmd+0x8c7/0xb40 [iwlwifi]
Command MCAST_FILTER_CMD (0x1d0) is too large (328 bytes)
This fixes: https://bugzilla.kernel.org/show_bug.cgi?id=196743
Cc: stable@vger.kernel.org
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 3a6ce4222ff5..635db63f972e 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -1546,6 +1546,11 @@ static void iwl_mvm_mc_iface_iterator(void *_data, u8 *mac,
struct iwl_mvm_mc_iter_data *data = _data;
struct iwl_mvm *mvm = data->mvm;
struct iwl_mcast_filter_cmd *cmd = mvm->mcast_filter_cmd;
+ struct iwl_host_cmd hcmd = {
+ .id = MCAST_FILTER_CMD,
+ .flags = CMD_ASYNC,
+ .dataflags[0] = IWL_HCMD_DFL_NOCOPY,
+ };
int ret, len;
/* if we don't have free ports, mcast frames will be dropped */
@@ -1560,7 +1565,10 @@ static void iwl_mvm_mc_iface_iterator(void *_data, u8 *mac,
memcpy(cmd->bssid, vif->bss_conf.bssid, ETH_ALEN);
len = roundup(sizeof(*cmd) + cmd->count * ETH_ALEN, 4);
- ret = iwl_mvm_send_cmd_pdu(mvm, MCAST_FILTER_CMD, CMD_ASYNC, len, cmd);
+ hcmd.len[0] = len;
+ hcmd.data[0] = cmd;
+
+ ret = iwl_mvm_send_cmd(mvm, &hcmd);
if (ret)
IWL_ERR(mvm, "mcast filter cmd error. ret=%d\n", ret);
}
--
2.14.1
^ permalink raw reply related
* [PATCH 08/10] iwlwifi: mvm: initialize status in iwl_mvm_add_int_sta_common()
From: Luca Coelho @ 2017-09-08 9:12 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, Luca Coelho
In-Reply-To: <20170908091256.25279-1-luca@coelho.fi>
From: Luca Coelho <luciano.coelho@intel.com>
We always need to initialize the status argument to the success case
before calling iwl_mvm_send_cmd_status() or
iwl_mvm_send_cmd_pdu_status() (which calls the former) otherwise we
may get an uninitialized value back. In this case, we use
ADD_STA_SUCCESS as success.
Fixes: 732d06e9d9cf ("iwlwifi: mvm: add station before allocating a queue")
Reported by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index 2dafe9bb4d8b..c4a343534c5e 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -1285,7 +1285,7 @@ static int iwl_mvm_add_int_sta_common(struct iwl_mvm *mvm,
{
struct iwl_mvm_add_sta_cmd cmd;
int ret;
- u32 status;
+ u32 status = ADD_STA_SUCCESS;
lockdep_assert_held(&mvm->mutex);
--
2.14.1
^ permalink raw reply related
* [PATCH 09/10] iwlwifi: mvm: set status before calling iwl_mvm_send_cmd_status()
From: Luca Coelho @ 2017-09-08 9:12 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, Luca Coelho
In-Reply-To: <20170908091256.25279-1-luca@coelho.fi>
From: Luca Coelho <luciano.coelho@intel.com>
We always must set the status to what we consider success before
calling iwl_mvm_send_cmd_status() (also iwl_mvm_send_cmd_pdu_status()
which calls it). Fix a few places where initialization is missing.
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
drivers/net/wireless/intel/iwlwifi/mvm/scan.c | 2 +-
drivers/net/wireless/intel/iwlwifi/mvm/tt.c | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
index 50983615dce6..774122fed454 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
@@ -555,7 +555,7 @@ static int iwl_mvm_lmac_scan_abort(struct iwl_mvm *mvm)
struct iwl_host_cmd cmd = {
.id = SCAN_OFFLOAD_ABORT_CMD,
};
- u32 status;
+ u32 status = CAN_ABORT_STATUS;
ret = iwl_mvm_send_cmd_status(mvm, &cmd, &status);
if (ret)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
index 8876c2abc440..4d907f60bce9 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
@@ -529,6 +529,7 @@ int iwl_mvm_ctdp_command(struct iwl_mvm *mvm, u32 op, u32 state)
lockdep_assert_held(&mvm->mutex);
+ status = 0;
ret = iwl_mvm_send_cmd_pdu_status(mvm, WIDE_ID(PHY_OPS_GROUP,
CTDP_CONFIG_CMD),
sizeof(cmd), &cmd, &status);
--
2.14.1
^ permalink raw reply related
* [PATCH 10/10] iwlwifi: mvm: fix reorder buffer for 9000 devices
From: Luca Coelho @ 2017-09-08 9:12 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, Sara Sharon, Luca Coelho
In-Reply-To: <20170908091256.25279-1-luca@coelho.fi>
From: Sara Sharon <sara.sharon@intel.com>
The condition to check if reorder buffer ran out of
space is faulty, as it takes into account only the
NSSN.
In case the head SN was too far behind the reorder
buffer should move forward, regardless of the NSSN
status.
This caused the driver to release packets out of order
in some scenarios.
Fixes: b915c10174fb ("iwlwifi: mvm: add reorder buffer per queue")
Signed-off-by: Sara Sharon <sara.sharon@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
index 67ffd9774712..77f77bc5d083 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
@@ -672,11 +672,12 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
* If there was a significant jump in the nssn - adjust.
* If the SN is smaller than the NSSN it might need to first go into
* the reorder buffer, in which case we just release up to it and the
- * rest of the function will take of storing it and releasing up to the
- * nssn
+ * rest of the function will take care of storing it and releasing up to
+ * the nssn
*/
if (!iwl_mvm_is_sn_less(nssn, buffer->head_sn + buffer->buf_size,
- buffer->buf_size)) {
+ buffer->buf_size) ||
+ !ieee80211_sn_less(sn, buffer->head_sn + buffer->buf_size)) {
u16 min_sn = ieee80211_sn_less(sn, nssn) ? sn : nssn;
iwl_mvm_release_frames(mvm, sta, napi, buffer, min_sn);
--
2.14.1
^ permalink raw reply related
* Re: Fwd: [PATCH v2] brcmfmac: feature check for multi-scheduled scan fails on bcm4345 devices
From: Kalle Valo @ 2017-09-08 9:15 UTC (permalink / raw)
To: Ian W MORRISON; +Cc: linux-wireless
In-Reply-To: <CAFXWsS-NxYqp-N9AFUCuQE-nknNorV25wevGJ7KkJuvMmHh6Og@mail.gmail.com>
Hi Ian,
please don't send me email privately, instead always send the questions
to the list. You get better answers faster and I get less email :)
Ian W MORRISON <ianwmorrison@gmail.com> writes:
> With the below patch how can I track when it has been merged into 4.13
> so I can check and start using it? For 4.14 I'm assuming I'll get an
> 'applied' email from you so I can track through git but as I've never
> had a patch go backwards into stable I'm unsure of how it works.
So if Greg applies a patch to one of stable his stable releases who
usually sends a private email to the patch author and anyone who has
signed off the patch. So you should get an email about that. You can
also follow the stable trees mentioned here:
https://www.kernel.org/doc/html/latest/process/stable-kernel-rules.html
But good that you brought up this as I almost missed your patch from
this week's pull request for 4.14. I'll apply it shortly.
--
Kalle Valo
^ permalink raw reply
* Re: [v2] brcmfmac: feature check for multi-scheduled scan fails on bcm4345 devices
From: Kalle Valo @ 2017-09-08 9:25 UTC (permalink / raw)
To: Ian W MORRISON; +Cc: arend.vanspriel, ian, linux-wireless
In-Reply-To: <3cfcb175-8031-f5a8-da51-d81fa2d331c8@gmail.com>
Ian W MORRISON <ianwmorrison@gmail.com> wrote:
> The firmware feature check introduced for multi-scheduled scan is also
> failing for bcm4345 devices resulting in a firmware crash.
> The reason for this crash has not yet been root cause so this patch avoids
> the feature check for those device as a short-term fix.
>
> Fixes: 9fe929aaace6 ("brcmfmac: add firmware feature detection for gscan feature")
> Cc: <stable@vger.kernel.org> # v4.13
> Signed-off-by: Ian W MORRISON <ianwmorrison@gmail.com>
> Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Patch applied to wireless-drivers.git, thanks.
f957dd3c8db2 brcmfmac: feature check for multi-scheduled scan fails on bcm4345 devices
--
https://patchwork.kernel.org/patch/9930929/
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
^ permalink raw reply
* Re: [PATCH 2/2] wireless: return correct mandatory rates
From: Simon Wunderlich @ 2017-09-08 9:33 UTC (permalink / raw)
To: Richard Schütz; +Cc: Johannes Berg, linux-wireless
In-Reply-To: <1f7e466e-2a68-b97a-ee2e-21c3e74a9fc5@uni-koblenz.de>
[-- Attachment #1: Type: text/plain, Size: 2069 bytes --]
Hi,
On Friday, September 8, 2017 10:53:37 AM CEST Richard Schütz wrote:
> Am 08.09.2017 um 10:43 schrieb Richard Schütz:
> > Am 08.09.2017 um 08:55 schrieb Johannes Berg:
> >> On Thu, 2017-09-07 at 17:47 +0200, Richard Schütz wrote:
> >>> Use IEEE80211_RATE_MANDATORY_G instead of IEEE80211_RATE_MANDATORY_B
> >>> for comparison to get all mandatory rates in 2.4 GHz band. It is safe
> >>> to do so because ERP mandatory rates are a superset of HR/DSSS
> >>> mandatory rates.
> >>
> >> This I don't understand - what "comparison" are you talking about?
> >
> > Sorry, I meant the condition that checks for the presence of
> > mandatory_flag at the bottom of the function.
> >
> >>> Also force IEEE80211_RATE_MANDATORY_A for 10 MHz and 5 MHz channels
> >>> as they use "half-clocked" respectively "quarter-clocked" operation
> >>> of the OFDM rates (IEEE Std 802.11-2016, 17.1.1).
> >>
> >> I don't think this is correct - the way the flags are used, anything on
> >> 2.4 GHz would never bother to check the MANDATORY_A flag.
> >
> > Do we actually allow 10 MHz and 5 MHz operation in the 2.4 GHz band? As
> > far as I can tell that has only been specified for OFDM PHYs, which use
> > the 5 GHz band and are covered by IEEE80211_RATE_MANDATORY_A, but I am
> > not a hundred per cent sure about that. Cc'ing Simon Wunderlich who
> > originally implemented checking of scan_width here.
>
> Looks like the old address is invalid now. New try.
>
Yeah, officially only OFDM has the half/quarter clock stuff defined, not ERP (2.4
GHz 11g) or DSSS, and also not HT.
However, technically, the Qualcomm/Atheros hardware (ath9k and ath5k) supports
DSSS or HT on quarter and half rates just fine, also on 2.4 GHz.
I believe we currently support the 5/10 MHz on 2.4 GHz, although we shouldn't
when we follow the standard strictly. The question is if we should follow the
standard strictly - this feature is already quite limited, and people tend to
use the ath9k/ath5k chanbw patch from OpenWRT/LEDE.
Cheers,
Simon
[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* [PATCH] mac80211: use offsetofend()
From: Johannes Berg @ 2017-09-08 9:54 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg
From: Johannes Berg <johannes.berg@intel.com>
This was created using the following spatch:
@find@
type S;
expression M, M2;
position p;
@@
offsetof(S, M) + sizeof(M2)@p
@script:python@
m << find.M;
m2 << find.M2;
@@
if not m2.endswith('-> ' + m):
cocci.include_match(False)
@change@
type find.S;
expression find.M, find.M2;
position find.p;
@@
-offsetof(S, M) + sizeof(M2)@p
+offsetofend(S, M)
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
net/mac80211/mesh.c | 3 +--
net/mac80211/mesh_hwmp.c | 8 ++++----
net/mac80211/mesh_plink.c | 3 +--
net/mac80211/util.c | 4 ++--
4 files changed, 8 insertions(+), 10 deletions(-)
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index a550c707cd8a..7a76c4a6df30 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -675,8 +675,7 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
enum nl80211_band band;
u8 *pos;
struct ieee80211_sub_if_data *sdata;
- int hdr_len = offsetof(struct ieee80211_mgmt, u.beacon) +
- sizeof(mgmt->u.beacon);
+ int hdr_len = offsetofend(struct ieee80211_mgmt, u.beacon);
sdata = container_of(ifmsh, struct ieee80211_sub_if_data, u.mesh);
rcu_read_lock();
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index d8bbd0d2225a..146ec6c0f12f 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -111,8 +111,8 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
struct sk_buff *skb;
struct ieee80211_mgmt *mgmt;
u8 *pos, ie_len;
- int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.mesh_action) +
- sizeof(mgmt->u.action.u.mesh_action);
+ int hdr_len = offsetofend(struct ieee80211_mgmt,
+ u.action.u.mesh_action);
skb = dev_alloc_skb(local->tx_headroom +
hdr_len +
@@ -242,8 +242,8 @@ int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata,
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
struct ieee80211_mgmt *mgmt;
u8 *pos, ie_len;
- int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.mesh_action) +
- sizeof(mgmt->u.action.u.mesh_action);
+ int hdr_len = offsetofend(struct ieee80211_mgmt,
+ u.action.u.mesh_action);
if (time_before(jiffies, ifmsh->next_perr))
return -EAGAIN;
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index f69c6c38ca43..dc8e10f87207 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -220,8 +220,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
bool include_plid = false;
u16 peering_proto = 0;
u8 *pos, ie_len = 4;
- int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.self_prot) +
- sizeof(mgmt->u.action.u.self_prot);
+ int hdr_len = offsetofend(struct ieee80211_mgmt, u.action.u.self_prot);
int err = -ENOMEM;
skb = dev_alloc_skb(local->tx_headroom +
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 259698de569f..23c548b5b71e 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -2980,8 +2980,8 @@ int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata,
struct ieee80211_mgmt *mgmt;
struct ieee80211_local *local = sdata->local;
int freq;
- int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.chan_switch) +
- sizeof(mgmt->u.action.u.chan_switch);
+ int hdr_len = offsetofend(struct ieee80211_mgmt,
+ u.action.u.chan_switch);
u8 *pos;
if (sdata->vif.type != NL80211_IFTYPE_ADHOC &&
--
2.14.1
^ permalink raw reply related
* Re: [PATCH 2/2] wireless: return correct mandatory rates
From: Richard Schütz @ 2017-09-08 10:10 UTC (permalink / raw)
To: Johannes Berg, linux-wireless; +Cc: Simon Wunderlich
In-Reply-To: <1504861413.6177.16.camel@sipsolutions.net>
Am 08.09.2017 um 11:03 schrieb Johannes Berg:
> On Fri, 2017-09-08 at 10:43 +0200, Richard Schütz wrote:
>> Am 08.09.2017 um 08:55 schrieb Johannes Berg:
>>> On Thu, 2017-09-07 at 17:47 +0200, Richard Schütz wrote:
>>>> Use IEEE80211_RATE_MANDATORY_G instead of
>>>> IEEE80211_RATE_MANDATORY_B
>>>> for comparison to get all mandatory rates in 2.4 GHz band. It is
>>>> safe
>>>> to do so because ERP mandatory rates are a superset of HR/DSSS
>>>> mandatory rates.
>>>
>>> This I don't understand - what "comparison" are you talking about?
>>
>> Sorry, I meant the condition that checks for the presence of
>> mandatory_flag at the bottom of the function.
>
> Ah, sorry, I got confused with the other patch.
>
>> Do we actually allow 10 MHz and 5 MHz operation in the 2.4 GHz band?
>> As far as I can tell that has only been specified for OFDM PHYs,
>> which use the 5 GHz band and are covered by
>> IEEE80211_RATE_MANDATORY_A, but I am not a hundred per cent sure
>> about that. Cc'ing Simon Wunderlich who originally implemented
>> checking of scan_width here.
>
> Clearly we do allow that, since the existing check is:
>
> if (sband->band == NL80211_BAND_2GHZ) {
> if (scan_width == NL80211_BSS_CHAN_WIDTH_5 ||
> scan_width == NL80211_BSS_CHAN_WIDTH_10)
> mandatory_flag = IEEE80211_RATE_MANDATORY_G;
>
> That wouldn't make any sense if we didn't have 5/10 MHz on 2.4 GHz.
>
>> The main intention of this patch series is to fix mandatory rates
>> returned for normal operation in 2.4 GHz band. Currently only 1 Mb/s
>> is returned here, which is wrong for both HR/DSSS and ERP PHYs.
>
> The patch is still wrong wrt. 5/10 MHz though.
>
> I think what you really wanted to do is the following:
>
> * rename RATE_MANDATORY_B to RATE_MANDATORY_HR_DSSS
> * combine RATE_MANDATORY_G/_A to RATE_MANDATORY_OFDM
>
> Then, what you need to do, is change the checks in
> ieee80211_mandatory_rates() to be
>
> if (sband->band == NL80211_BAND_2GHZ) {
> if (scan_width == NL80211_BSS_CHAN_WIDTH_5 ||
> scan_width == NL80211_BSS_CHAN_WIDTH_10)
> mandatory_flag = IEEE80211_RATE_MANDATORY_OFDM;
> else
> mandatory_flag = IEEE80211_RATE_MANDATORY_HR_DSSS;
This would leave us with 1, 2, 5.5 and 11 Mb/s for ERP PHYs again when
it really should be 1, 2, 5.5, 6, 11, 12 and 24 Mb/s.
> } else {
> mandatory_flag = IEEE80211_RATE_MANDATORY_OFDM;
> }
>
> That would actually fix a bug in a way because right now the code
> treats HR/DSSS rates (1, 2, 5.5, 11) for 2.4 GHz narrow-band operation
> as mandatory, which seems wrong.
--
Richard
^ permalink raw reply
* Re: [PATCH 2/2] wireless: return correct mandatory rates
From: Johannes Berg @ 2017-09-08 10:12 UTC (permalink / raw)
To: Richard Schütz, linux-wireless; +Cc: Simon Wunderlich
In-Reply-To: <f9e34cbf-e0e1-3faa-39dd-58ad6968d276@uni-koblenz.de>
On Fri, 2017-09-08 at 12:10 +0200, Richard Schütz wrote:
>
> This would leave us with 1, 2, 5.5 and 11 Mb/s for ERP PHYs again
> when it really should be 1, 2, 5.5, 6, 11, 12 and 24 Mb/s.
>
Yes, you're right - I had thought about that but forgot. The places
that check it would have to be amended to check both HR_DSSS and OFDM
where they want ERP PHY operation.
johannes
^ permalink raw reply
* [PATCH v2] rtl8xxxu: Don't printk raw binary if serial number is not burned in.
From: Adam Borowski @ 2017-09-08 10:30 UTC (permalink / raw)
To: Jes Sorensen, Kalle Valo, linux-wireless, netdev, Stefano Brivio
Cc: Adam Borowski
In-Reply-To: <20170908032706.1fa59da9@elisabeth>
I assume that a blank efuse comes with all ones, thus I did not bother
recognizing other possible junk values. This matches 100% of dongles
I've seen (a single Gembird 8192eu).
Signed-off-by: Adam Borowski <kilobyte@angband.pl>
---
v2: strncmp("goofy string") -> memchr_inv()
Stefano Brivio wrote:
> You might want to use memchr_inv():
>
> if (memchr_inv(efuse->serial, 0xff, 11))
> dev_info(&priv->udev->dev, "Serial: %.11s\n", efuse->serial);
> ...
>
> Mostly cosmetic though.
This looks much better, thanks!
drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c
index 80fee699f58a..38b2ba1ac6f8 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c
@@ -614,7 +614,10 @@ static int rtl8192eu_parse_efuse(struct rtl8xxxu_priv *priv)
dev_info(&priv->udev->dev, "Vendor: %.7s\n", efuse->vendor_name);
dev_info(&priv->udev->dev, "Product: %.11s\n", efuse->device_name);
- dev_info(&priv->udev->dev, "Serial: %.11s\n", efuse->serial);
+ if (memchr_inv(efuse->serial, 0xff, 11))
+ dev_info(&priv->udev->dev, "Serial: %.11s\n", efuse->serial);
+ else
+ dev_info(&priv->udev->dev, "Serial not available.\n");
if (rtl8xxxu_debug & RTL8XXXU_DEBUG_EFUSE) {
unsigned char *raw = priv->efuse_wifi.raw;
--
2.14.1
^ permalink raw reply related
* Update WiFi card by one that does not use _Private_ Firmware
From: Cristian @ 2017-09-08 12:44 UTC (permalink / raw)
To: linux-wireless; +Cc: Greg KH, Carlos Rojas R., fcalvo, Oscar Fernandez
Hello,
My name is Cristian Aravena Romero, [1]Free Software enthusiast in
Chile. My _Notebook_ has a WiFi card [2]"Intel=C2=AE Centrino=C2=AE Advance=
d-N
6235" running from version 3.2 of the Linux kernel and above; and also
occupies the firmware "iwlwifi-6000g2b-ucode-18.168.6.1.tgz". The
complete technical information of this WiFi card is [3]here.
[1] https://launchpad.net/~caravena
[2] https://www.intel.la/content/www/xl/en/support/network-and-i-o/wireless=
-networking/000005511.html
[3] https://ark.intel.com/en/products/66890/Intel-Centrino-Advanced-N-6235-=
Dual-Band
I am interested in buying on ebay.com or aliexpress.com a new WiFi
card that supports Bluetooh, 802.11ac and most importantly, only use
Free Software, without firmware *PRIVATIVE*
I was reviewing the internet and found an [0]"Intel -> 8265AC", and
found it on [2]aliexpress.com but Intel has a bad policy regarding its
firmware. That is why in the first instance you will be discarding.
[1] https://ark.intel.com/en/products/94150/Intel-Dual-Band-Wireless-AC-826=
5
[2] https://en.aliexpress.com/item/Fenvi-New-Dual-Band-laptop-Wlan-Wi-Fi-Ne=
twork-For-Intel-Wireless-AC-8265-8265NGW-802/32756150183.html
It's not what I'm looking for!!!...
You could give me a link of a modern WiFi card that works as I said,
with Bluetooh, 802.11ac and only use Free Software * I can buy on
ebay.com or aliexpress.com?
Thank you!
Attentive to their requirements,
-
Cristian
^ permalink raw reply
* [RFC 2/4] mac80211_hwsim: add hwsim_tx_rate_flags to Netlink Attributes
From: Benjamin Beichler @ 2017-09-08 14:11 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg, Benjamin Beichler
In-Reply-To: <20170908141137.3941-1-benjamin.beichler@uni-rostock.de>
For correct interpretation of a tx rate, the corresponding rate flags are needed (e.g. whether a HT-MCS rate or a legacy rate) and
moreover for more correct simulation the other infos of the flags are important (like short-GI). Keeping compability, the flags
are not integrated into the existing hwsim_tx_rate, but transmitted as an additional netlink attribute.
Signed-off-by: Benjamin Beichler <benjamin.beichler@uni-rostock.de>
---
drivers/net/wireless/mac80211_hwsim.c | 93 ++++++++++++++++++++++++++++++++++-
drivers/net/wireless/mac80211_hwsim.h | 67 +++++++++++++++++++++++++
2 files changed, 159 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index aeeea7a35404..62c5a00a76c3 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -1014,6 +1014,66 @@ static int hwsim_unicast_netgroup(struct mac80211_hwsim_data *data,
return res;
}
+static inline u16 transl_tx_rate_flags_ieee2hwsim(struct ieee80211_tx_rate *rate)
+{
+ u16 result=0;
+ if(rate->flags & IEEE80211_TX_RC_USE_RTS_CTS)
+ result |= MAC80211_HWSIM_TX_RC_USE_RTS_CTS;
+ if(rate->flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
+ result |= MAC80211_HWSIM_TX_RC_USE_CTS_PROTECT;
+ if(rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
+ result |= MAC80211_HWSIM_TX_RC_USE_SHORT_PREAMBLE;
+ if(rate->flags & IEEE80211_TX_RC_MCS)
+ result |= MAC80211_HWSIM_TX_RC_MCS;
+ if(rate->flags & IEEE80211_TX_RC_GREEN_FIELD)
+ result |= MAC80211_HWSIM_TX_RC_GREEN_FIELD;
+ if(rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+ result |= MAC80211_HWSIM_TX_RC_40_MHZ_WIDTH;
+ if(rate->flags & IEEE80211_TX_RC_DUP_DATA)
+ result |= MAC80211_HWSIM_TX_RC_DUP_DATA;
+ if(rate->flags & IEEE80211_TX_RC_SHORT_GI)
+ result |= MAC80211_HWSIM_TX_RC_SHORT_GI;
+ if(rate->flags & IEEE80211_TX_RC_VHT_MCS)
+ result |= MAC80211_HWSIM_TX_RC_VHT_MCS;
+ if(rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH)
+ result |= MAC80211_HWSIM_TX_RC_80_MHZ_WIDTH;
+ if(rate->flags & IEEE80211_TX_RC_160_MHZ_WIDTH)
+ result |= MAC80211_HWSIM_TX_RC_160_MHZ_WIDTH;
+
+ return result;
+}
+
+static inline u16 transl_rate_flags_hwsim2ieee(struct hwsim_tx_rate_flag *rate)
+{
+ u16 result=0;
+ if(rate->flags & MAC80211_HWSIM_TX_RC_USE_RTS_CTS)
+ result |= IEEE80211_TX_RC_USE_RTS_CTS;
+ if(rate->flags & MAC80211_HWSIM_TX_RC_USE_CTS_PROTECT)
+ result |= IEEE80211_TX_RC_USE_CTS_PROTECT;
+ if(rate->flags & MAC80211_HWSIM_TX_RC_USE_SHORT_PREAMBLE)
+ result |= IEEE80211_TX_RC_USE_SHORT_PREAMBLE;
+ if(rate->flags & MAC80211_HWSIM_TX_RC_MCS)
+ result |= IEEE80211_TX_RC_MCS;
+ if(rate->flags & MAC80211_HWSIM_TX_RC_GREEN_FIELD)
+ result |= IEEE80211_TX_RC_GREEN_FIELD;
+ if(rate->flags & MAC80211_HWSIM_TX_RC_40_MHZ_WIDTH)
+ result |= IEEE80211_TX_RC_40_MHZ_WIDTH;
+ if(rate->flags & MAC80211_HWSIM_TX_RC_DUP_DATA)
+ result |= IEEE80211_TX_RC_DUP_DATA;
+ if(rate->flags & MAC80211_HWSIM_TX_RC_SHORT_GI)
+ result |= IEEE80211_TX_RC_SHORT_GI;
+ if(rate->flags & MAC80211_HWSIM_TX_RC_VHT_MCS)
+ result |= IEEE80211_TX_RC_VHT_MCS;
+ if(rate->flags & MAC80211_HWSIM_TX_RC_80_MHZ_WIDTH)
+ result |= IEEE80211_TX_RC_80_MHZ_WIDTH;
+ if(rate->flags & MAC80211_HWSIM_TX_RC_160_MHZ_WIDTH)
+ result |= IEEE80211_TX_RC_160_MHZ_WIDTH;
+
+ return result;
+}
+
+
+
static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw,
struct sk_buff *my_skb,
int dst_portid)
@@ -1026,6 +1086,8 @@ static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw,
unsigned int hwsim_flags = 0;
int i;
struct hwsim_tx_rate tx_attempts[IEEE80211_TX_MAX_RATES];
+ struct hwsim_tx_rate_flag tx_attempts_flags[IEEE80211_TX_MAX_RATES];
+
uintptr_t cookie;
if (data->ps != PS_DISABLED)
@@ -1077,7 +1139,10 @@ static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw,
for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
tx_attempts[i].idx = info->status.rates[i].idx;
+ tx_attempts_flags[i].idx= info->status.rates[i].idx;
tx_attempts[i].count = info->status.rates[i].count;
+ tx_attempts_flags[i].flags =
+ transl_tx_rate_flags_ieee2hwsim(&info->status.rates[i]);
}
if (nla_put(skb, HWSIM_ATTR_TX_INFO,
@@ -1085,6 +1150,11 @@ static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw,
tx_attempts))
goto nla_put_failure;
+ if (nla_put(skb, HWSIM_ATTR_TX_INFO_FLAGS,
+ sizeof(struct hwsim_tx_rate_flag)*IEEE80211_TX_MAX_RATES,
+ tx_attempts_flags))
+ goto nla_put_failure;
+
/* We create a cookie to identify this skb */
data->pending_cookie++;
cookie = data->pending_cookie;
@@ -2973,6 +3043,8 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2,
struct mac80211_hwsim_data *data2;
struct ieee80211_tx_info *txi;
struct hwsim_tx_rate *tx_attempts;
+ struct hwsim_tx_rate_flag *tx_attempts_flags;
+
u64 ret_skb_cookie;
struct sk_buff *skb, *tmp;
const u8 *src;
@@ -3033,9 +3105,28 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2,
for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
txi->status.rates[i].idx = tx_attempts[i].idx;
txi->status.rates[i].count = tx_attempts[i].count;
- /*txi->status.rates[i].flags = 0;*/
+ /* txi->status.rates[i].flags = 0; */
}
+ if(info->attrs[HWSIM_ATTR_TX_INFO_FLAGS]){
+ tx_attempts_flags = (struct hwsim_tx_rate_flag *)nla_data(
+ info->attrs[HWSIM_ATTR_TX_INFO_FLAGS]);
+ for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
+
+ WARN(txi->status.rates[i].idx != tx_attempts_flags[i].idx,
+ "rate idx of tx_info received via netlink "
+ "does not match to rate idx of tx_info_flags");
+
+ txi->status.rates[i].flags =
+ transl_rate_flags_hwsim2ieee(&tx_attempts_flags[i]);
+ }
+ }
+ else{
+ WARN_ONCE(1,"received tx_info via netlink does not contain"
+ "rate flags, may cause statistic or rate control problems");
+ }
+
+
txi->status.ack_signal = nla_get_u32(info->attrs[HWSIM_ATTR_SIGNAL]);
if (!(hwsim_flags & HWSIM_TX_CTL_NO_ACK) &&
diff --git a/drivers/net/wireless/mac80211_hwsim.h b/drivers/net/wireless/mac80211_hwsim.h
index 3f5eda591dba..5f831fffcb13 100644
--- a/drivers/net/wireless/mac80211_hwsim.h
+++ b/drivers/net/wireless/mac80211_hwsim.h
@@ -123,6 +123,7 @@ enum {
* @HWSIM_ATTR_RADIO_NAME: Name of radio, e.g. phy666
* @HWSIM_ATTR_NO_VIF: Do not create vif (wlanX) when creating radio.
* @HWSIM_ATTR_FREQ: Frequency at which packet is transmitted or received.
+ * @HWSIM_ATTR_TX_INFO_FLAGS: additional flags for corresponding rates of %HWSIM_ATTR_TX_INFO
* @__HWSIM_ATTR_MAX: enum limit
*/
@@ -149,10 +150,76 @@ enum {
HWSIM_ATTR_NO_VIF,
HWSIM_ATTR_FREQ,
HWSIM_ATTR_PAD,
+ HWSIM_ATTR_TX_INFO_FLAGS,
__HWSIM_ATTR_MAX,
};
#define HWSIM_ATTR_MAX (__HWSIM_ATTR_MAX - 1)
+
+/**
+ * enum hwsim_tx_rate_flags - per-rate flags set by the
+ * Rate Control algorithm. Inspired by structure mac80211_rate_control_flags.
+ * New flags may be appended, but old flags not deleted, to keep compatibility
+ * for userspace.
+ *
+ * These flags are set by the Rate control algorithm for each rate during tx,
+ * in the @flags member of struct ieee80211_tx_rate.
+ *
+ * @MAC80211_HWSIM_TX_RC_USE_RTS_CTS: Use RTS/CTS exchange for this rate.
+ * @MAC80211_HWSIM_TX_RC_USE_CTS_PROTECT: CTS-to-self protection is required.
+ * This is set if the current BSS requires ERP protection.
+ * @MAC80211_HWSIM_TX_RC_USE_SHORT_PREAMBLE: Use short preamble.
+ * @MAC80211_HWSIM_TX_RC_MCS: HT rate.
+ * @MAC80211_HWSIM_TX_RC_VHT_MCS: VHT MCS rate, in this case the idx field is split
+ * into a higher 4 bits (Nss) and lower 4 bits (MCS number)
+ * @MAC80211_HWSIM_TX_RC_GREEN_FIELD: Indicates whether this rate should be used in
+ * Greenfield mode.
+ * @MAC80211_HWSIM_TX_RC_40_MHZ_WIDTH: Indicates if the Channel Width should be 40 MHz.
+ * @MAC80211_HWSIM_TX_RC_80_MHZ_WIDTH: Indicates 80 MHz transmission
+ * @MAC80211_HWSIM_TX_RC_160_MHZ_WIDTH: Indicates 160 MHz transmission
+ * (80+80 isn't supported yet)
+ * @MAC80211_HWSIM_TX_RC_DUP_DATA: The frame should be transmitted on both of the
+ * adjacent 20 MHz channels, if the current channel type is
+ * NL80211_CHAN_HT40MINUS or NL80211_CHAN_HT40PLUS.
+ * @MAC80211_HWSIM_TX_RC_SHORT_GI: Short Guard interval should be used for this rate.
+ */
+enum hwsim_tx_rate_flags {
+ MAC80211_HWSIM_TX_RC_USE_RTS_CTS = BIT(0),
+ MAC80211_HWSIM_TX_RC_USE_CTS_PROTECT = BIT(1),
+ MAC80211_HWSIM_TX_RC_USE_SHORT_PREAMBLE = BIT(2),
+
+ /* rate index is an HT/VHT MCS instead of an index */
+ MAC80211_HWSIM_TX_RC_MCS = BIT(3),
+ MAC80211_HWSIM_TX_RC_GREEN_FIELD = BIT(4),
+ MAC80211_HWSIM_TX_RC_40_MHZ_WIDTH = BIT(5),
+ MAC80211_HWSIM_TX_RC_DUP_DATA = BIT(6),
+ MAC80211_HWSIM_TX_RC_SHORT_GI = BIT(7),
+ MAC80211_HWSIM_TX_RC_VHT_MCS = BIT(8),
+ MAC80211_HWSIM_TX_RC_80_MHZ_WIDTH = BIT(9),
+ MAC80211_HWSIM_TX_RC_160_MHZ_WIDTH = BIT(10),
+};
+
+/**
+ * struct hwsim_tx_rate - rate selection/status
+ *
+ * @idx: rate index to attempt to send with
+ * @count: number of tries in this rate before going to the next rate
+ *
+ * A value of -1 for @idx indicates an invalid rate and, if used
+ * in an array of retry rates, that no more rates should be tried.
+ *
+ * When used for transmit status reporting, the driver should
+ * always report the rate and number of retries used.
+ *
+ */
+struct hwsim_tx_rate_flag {
+ s8 idx;
+ u16 flags;
+} __packed;
+
+
+
+
/**
* struct hwsim_tx_rate - rate selection/status
*
--
2.14.1
^ permalink raw reply related
* [RFC 3/4] mac80211_hwsim: explicitly set netlink parallel ops to false
From: Benjamin Beichler @ 2017-09-08 14:11 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg, Benjamin Beichler
In-Reply-To: <20170908141137.3941-1-benjamin.beichler@uni-rostock.de>
The ops field is zero initialized, therefore parallel ops is already false. This implicates that the netlink callbacks are not
processed in parallel. Maybe this could be utilized to reduce locking overhead or maybe also parallel ops could be implemented.
Signed-off-by: Benjamin Beichler <benjamin.beichler@uni-rostock.de>
---
drivers/net/wireless/mac80211_hwsim.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 62c5a00a76c3..5dd4be2a8487 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -3499,6 +3499,7 @@ static struct genl_family hwsim_genl_family __ro_after_init = {
.n_ops = ARRAY_SIZE(hwsim_ops),
.mcgrps = hwsim_mcgrps,
.n_mcgrps = ARRAY_SIZE(hwsim_mcgrps),
+ .parallel_ops = false
};
static void destroy_radio(struct work_struct *work)
--
2.14.1
^ permalink raw reply related
* [RFC 4/4] mac80211_hwsim: add radio idx param to netlink callback of radio creation
From: Benjamin Beichler @ 2017-09-08 14:11 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg, Benjamin Beichler
In-Reply-To: <20170908141137.3941-1-benjamin.beichler@uni-rostock.de>
Since the radio index is already a valid NL attribute, this patch simply
try to read it and create the radio specific to this index by the
previously used scheme.
Since this allows to create radios out of row, we need to search for a
free index for a new radio, when the index is not present as parameter.
Signed-off-by: Benjamin Beichler <benjamin.beichler@uni-rostock.de>
---
drivers/net/wireless/mac80211_hwsim.c | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 5dd4be2a8487..faa0e39523aa 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -2436,6 +2436,7 @@ struct hwsim_new_radio_params {
bool destroy_on_close;
const char *hwname;
bool no_vif;
+ int idx;
};
static void hwsim_mcast_config_msg(struct sk_buff *mcast_skb,
@@ -2645,13 +2646,9 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
skb_queue_head_init(&data->pending);
SET_IEEE80211_DEV(hw, data->dev);
- eth_zero_addr(addr);
- addr[0] = 0x02;
- addr[3] = idx >> 8;
- addr[4] = idx;
- memcpy(data->addresses[0].addr, addr, ETH_ALEN);
- memcpy(data->addresses[1].addr, addr, ETH_ALEN);
- data->addresses[1].addr[0] |= 0x40;
+ memcpy(data->addresses[0].addr, &mac.addr, ETH_ALEN);
+ memcpy(data->addresses[1].addr, &mac.addr, ETH_ALEN);
+ data->addresses[0].addr[0] = 0x02;
hw->wiphy->n_addresses = 2;
hw->wiphy->addresses = data->addresses;
@@ -3304,6 +3301,11 @@ static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info)
param.regd = hwsim_world_regdom_custom[idx];
}
+ if (info->attrs[HWSIM_ATTR_RADIO_ID])
+ param.idx = nla_get_u32(info->attrs[HWSIM_ATTR_RADIO_ID]);
+ else
+ param.idx = -1;
+
return mac80211_hwsim_new_radio(info, ¶m);
}
--
2.14.1
^ permalink raw reply related
* [RFC 1/4] mac80211_hwsim: changed hwsim_radios from list to hashlist keyed by MAC-Address
From: Benjamin Beichler @ 2017-09-08 14:11 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg, Benjamin Beichler
Use hashlist to improve lookup speed for every received NL-message,
especially for higher counts of radios, like 100 or more. The stringhash
should be neglible for 6 Bytes MAC-Address, could be improved by using
cast to 64bit integer and hash this instead.
For a more reliable implementation of radio dump, a generation count is inserted,
which indicates a change while dump (this was missing before and could lead into problems because of inconsistent NL-dumps).
Signed-off-by: Benjamin Beichler <benjamin.beichler@uni-rostock.de>
---
drivers/net/wireless/mac80211_hwsim.c | 180 +++++++++++++++++++++++++---------
1 file changed, 136 insertions(+), 44 deletions(-)
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index c8852acc1462..aeeea7a35404 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -32,6 +32,8 @@
#include <net/genetlink.h>
#include <net/net_namespace.h>
#include <net/netns/generic.h>
+#include <linux/hashtable.h>
+#include <linux/stringhash.h>
#include "mac80211_hwsim.h"
#define WARN_QUEUE 100
@@ -487,9 +489,19 @@ static const struct ieee80211_iface_combination hwsim_if_comb_p2p_dev[] = {
},
};
+#define HWSIM_HT_BITS 7
+static unsigned long mac_hash_salt = 0;
+
+static unsigned int hash_mac(const u8 *mac )
+{
+ return full_name_hash(&mac_hash_salt,mac,ETH_ALEN);
+}
+
+
static spinlock_t hwsim_radio_lock;
-static LIST_HEAD(hwsim_radios);
-static int hwsim_radio_idx;
+static DEFINE_HASHTABLE(hwsim_radios,HWSIM_HT_BITS);
+static int hwsim_radio_count;
+static int hwsim_radio_generation=1;
static struct platform_driver mac80211_hwsim_driver = {
.driver = {
@@ -498,7 +510,7 @@ static struct platform_driver mac80211_hwsim_driver = {
};
struct mac80211_hwsim_data {
- struct list_head list;
+ struct hlist_node list;
struct ieee80211_hw *hw;
struct device *dev;
struct ieee80211_supported_band bands[NUM_NL80211_BANDS];
@@ -1179,6 +1191,7 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
struct ieee80211_channel *chan)
{
struct mac80211_hwsim_data *data = hw->priv, *data2;
+ int bucket;
bool ack = false;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
@@ -1240,7 +1253,7 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
/* Copy skb to all enabled radios that are on the current frequency */
spin_lock(&hwsim_radio_lock);
- list_for_each_entry(data2, &hwsim_radios, list) {
+ hash_for_each( hwsim_radios, bucket, data2, list) {
struct sk_buff *nskb;
struct tx_iter_data tx_iter_data = {
.receive = false,
@@ -2458,23 +2471,68 @@ static void hwsim_mcast_new_radio(int id, struct genl_info *info,
nlmsg_free(mcast_skb);
}
+struct mac_address create_mac_from_idx(int idx)
+{
+ struct mac_address mac;
+ eth_zero_addr(mac.addr);
+ mac.addr[0] = 0x42;
+ mac.addr[3] = idx >> 8;
+ mac.addr[4] = idx;
+ return mac;
+
+}
+
static int mac80211_hwsim_new_radio(struct genl_info *info,
struct hwsim_new_radio_params *param)
{
int err;
- u8 addr[ETH_ALEN];
+ struct mac_address mac;
struct mac80211_hwsim_data *data;
struct ieee80211_hw *hw;
enum nl80211_band band;
const struct ieee80211_ops *ops = &mac80211_hwsim_ops;
struct net *net;
- int idx;
+ int idx,hashkey;
+ bool new_id_found=true;
+
if (WARN_ON(param->channels > 1 && !param->use_chanctx))
return -EINVAL;
spin_lock_bh(&hwsim_radio_lock);
- idx = hwsim_radio_idx++;
+
+
+ if(param->idx == -1){
+ idx = hwsim_radio_count;
+
+ }
+ else{
+ idx = param->idx;
+ }
+
+ do{
+ mac = create_mac_from_idx(idx);
+ hashkey = hash_mac(mac.addr);
+ hash_for_each_possible(hwsim_radios,data,list,hashkey){
+ if (data->idx == idx) {
+ if (param->idx != -1) {
+ printk(KERN_ERR "mac80211_hwsim: given idx %d "
+ "is already in use", param->idx);
+ spin_unlock_bh(&hwsim_radio_lock);
+ return -EINVAL;
+ }
+ else {
+ //try next index for new radio
+ ++idx;
+ new_id_found = false;
+ break;
+ }
+ }
+
+ }
+
+ } while (new_id_found);
+
spin_unlock_bh(&hwsim_radio_lock);
if (param->use_chanctx)
@@ -2727,7 +2785,9 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
spin_lock_bh(&hwsim_radio_lock);
- list_add_tail(&data->list, &hwsim_radios);
+ hash_add(hwsim_radios,&data->list,hash_mac(data->addresses[1].addr));
+ ++hwsim_radio_generation;
+ ++hwsim_radio_count;
spin_unlock_bh(&hwsim_radio_lock);
if (idx > 0)
@@ -2836,16 +2896,16 @@ static int mac80211_hwsim_get_radio(struct sk_buff *skb,
static void mac80211_hwsim_free(void)
{
struct mac80211_hwsim_data *data;
-
+ int bucket;
spin_lock_bh(&hwsim_radio_lock);
- while ((data = list_first_entry_or_null(&hwsim_radios,
- struct mac80211_hwsim_data,
- list))) {
- list_del(&data->list);
- spin_unlock_bh(&hwsim_radio_lock);
- mac80211_hwsim_del_radio(data, wiphy_name(data->hw->wiphy),
- NULL);
- spin_lock_bh(&hwsim_radio_lock);
+ if (!hash_empty(hwsim_radios)) {
+ hash_for_each(hwsim_radios, bucket, data, list){
+ hash_del(&data->list);
+ spin_unlock_bh(&hwsim_radio_lock);
+ mac80211_hwsim_del_radio(data, wiphy_name(data->hw->wiphy),
+ NULL);
+ spin_lock_bh(&hwsim_radio_lock);
+ }
}
spin_unlock_bh(&hwsim_radio_lock);
class_destroy(hwsim_class);
@@ -2873,8 +2933,10 @@ static struct mac80211_hwsim_data *get_hwsim_data_ref_from_addr(const u8 *addr)
struct mac80211_hwsim_data *data;
bool _found = false;
+ unsigned int hash = hash_mac(addr);
+
spin_lock_bh(&hwsim_radio_lock);
- list_for_each_entry(data, &hwsim_radios, list) {
+ hash_for_each_possible(hwsim_radios,data,list,hash){
if (memcmp(data->addresses[1].addr, addr, ETH_ALEN) == 0) {
_found = true;
break;
@@ -2891,11 +2953,12 @@ static struct mac80211_hwsim_data *get_hwsim_data_ref_from_addr(const u8 *addr)
static void hwsim_register_wmediumd(struct net *net, u32 portid)
{
struct mac80211_hwsim_data *data;
+ int bucket;
hwsim_net_set_wmediumd(net, portid);
spin_lock_bh(&hwsim_radio_lock);
- list_for_each_entry(data, &hwsim_radios, list) {
+ hash_for_each(hwsim_radios, bucket, data, list) {
if (data->netgroup == hwsim_net_get_netgroup(net))
data->wmediumd = portid;
}
@@ -3080,10 +3143,11 @@ static int hwsim_register_received_nl(struct sk_buff *skb_2,
{
struct net *net = genl_info_net(info);
struct mac80211_hwsim_data *data;
+ int bucket;
int chans = 1;
spin_lock_bh(&hwsim_radio_lock);
- list_for_each_entry(data, &hwsim_radios, list)
+ hash_for_each(hwsim_radios, bucket, data, list)
chans = max(chans, data->channels);
spin_unlock_bh(&hwsim_radio_lock);
@@ -3155,6 +3219,7 @@ static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info)
static int hwsim_del_radio_nl(struct sk_buff *msg, struct genl_info *info)
{
struct mac80211_hwsim_data *data;
+ int bucket;
s64 idx = -1;
const char *hwname = NULL;
@@ -3170,7 +3235,7 @@ static int hwsim_del_radio_nl(struct sk_buff *msg, struct genl_info *info)
return -EINVAL;
spin_lock_bh(&hwsim_radio_lock);
- list_for_each_entry(data, &hwsim_radios, list) {
+ hash_for_each(hwsim_radios, bucket, data, list) {
if (idx >= 0) {
if (data->idx != idx)
continue;
@@ -3183,7 +3248,9 @@ static int hwsim_del_radio_nl(struct sk_buff *msg, struct genl_info *info)
if (!net_eq(wiphy_net(data->hw->wiphy), genl_info_net(info)))
continue;
- list_del(&data->list);
+ hash_del(&data->list);
+ --hwsim_radio_count;
+ ++hwsim_radio_generation;
spin_unlock_bh(&hwsim_radio_lock);
mac80211_hwsim_del_radio(data, wiphy_name(data->hw->wiphy),
info);
@@ -3199,6 +3266,7 @@ static int hwsim_del_radio_nl(struct sk_buff *msg, struct genl_info *info)
static int hwsim_get_radio_nl(struct sk_buff *msg, struct genl_info *info)
{
struct mac80211_hwsim_data *data;
+ int bucket;
struct sk_buff *skb;
int idx, res = -ENODEV;
@@ -3207,7 +3275,7 @@ static int hwsim_get_radio_nl(struct sk_buff *msg, struct genl_info *info)
idx = nla_get_u32(info->attrs[HWSIM_ATTR_RADIO_ID]);
spin_lock_bh(&hwsim_radio_lock);
- list_for_each_entry(data, &hwsim_radios, list) {
+ hash_for_each(hwsim_radios,bucket, data, list) {
if (data->idx != idx)
continue;
@@ -3240,34 +3308,53 @@ static int hwsim_get_radio_nl(struct sk_buff *msg, struct genl_info *info)
static int hwsim_dump_radio_nl(struct sk_buff *skb,
struct netlink_callback *cb)
{
- int idx = cb->args[0];
+ int previous_idx = cb->args[0];
+ int bucket;
struct mac80211_hwsim_data *data = NULL;
int res;
+ bool previous_idx_reached;
spin_lock_bh(&hwsim_radio_lock);
- if (idx == hwsim_radio_idx)
+ cb->seq = hwsim_radio_generation;
+
+ /* cb->args[3] = #radios already dumped*/
+ if (cb->args[1] == hwsim_radio_count )
goto done;
- list_for_each_entry(data, &hwsim_radios, list) {
- if (data->idx < idx)
+ /* No radios dumped yet, send already first valid entry*/
+ if(cb->args[1]==0){
+ previous_idx_reached=true;
+ }
+ else{
+ previous_idx_reached=false;
+ }
+
+ hash_for_each(hwsim_radios,bucket,data,list){
+ if(!previous_idx_reached && data->idx != previous_idx){
continue;
+ }
+ else{
+ previous_idx_reached=true;
+ }
if (!net_eq(wiphy_net(data->hw->wiphy), sock_net(skb->sk)))
- continue;
+ continue;
res = mac80211_hwsim_get_radio(skb, data,
- NETLINK_CB(cb->skb).portid,
- cb->nlh->nlmsg_seq, cb,
- NLM_F_MULTI);
- if (res < 0)
- break;
-
- idx = data->idx + 1;
+ NETLINK_CB(cb->skb).portid,
+ cb->nlh->nlmsg_seq, cb,
+ NLM_F_MULTI);
+ if (res < 0){
+ cb->args[0]=data->idx;
+ goto done;
+ }
+ else{
+ ++cb->args[1];
+ }
}
-
- cb->args[0] = idx;
-
+ //leaving loop without goto, there is no radio left, cancel dump
+ cb->args[1] = hwsim_radio_count;
done:
spin_unlock_bh(&hwsim_radio_lock);
return skb->len;
@@ -3333,12 +3420,14 @@ static void destroy_radio(struct work_struct *work)
static void remove_user_radios(u32 portid)
{
- struct mac80211_hwsim_data *entry, *tmp;
+ struct mac80211_hwsim_data *entry;
+ struct hlist_node *tmp;
+ int bucket;
spin_lock_bh(&hwsim_radio_lock);
- list_for_each_entry_safe(entry, tmp, &hwsim_radios, list) {
+ hash_for_each_safe(hwsim_radios,bucket,tmp, entry, list) {
if (entry->destroy_on_close && entry->portid == portid) {
- list_del(&entry->list);
+ hash_del(&entry->list);
INIT_WORK(&entry->destroy_work, destroy_radio);
schedule_work(&entry->destroy_work);
}
@@ -3402,10 +3491,13 @@ static __net_init int hwsim_init_net(struct net *net)
static void __net_exit hwsim_exit_net(struct net *net)
{
- struct mac80211_hwsim_data *data, *tmp;
+ struct mac80211_hwsim_data *data;
+ struct hlist_node *tmp;
+ int bucket;
spin_lock_bh(&hwsim_radio_lock);
- list_for_each_entry_safe(data, tmp, &hwsim_radios, list) {
+
+ hash_for_each_safe(hwsim_radios,bucket,tmp,data,list) {
if (!net_eq(wiphy_net(data->hw->wiphy), net))
continue;
@@ -3413,7 +3505,7 @@ static void __net_exit hwsim_exit_net(struct net *net)
if (data->netgroup == hwsim_net_get_netgroup(&init_net))
continue;
- list_del(&data->list);
+ hash_del(&data->list);
INIT_WORK(&data->destroy_work, destroy_radio);
schedule_work(&data->destroy_work);
}
--
2.14.1
^ permalink raw reply related
* Re: [RFC 3/4] mac80211_hwsim: explicitly set netlink parallel ops to false
From: Johannes Berg @ 2017-09-08 14:19 UTC (permalink / raw)
To: Benjamin Beichler, linux-wireless
In-Reply-To: <593fec4f-fc0c-4610-b144-35760ee92102@MAIL1.uni-rostock.de>
On Fri, 2017-09-08 at 16:11 +0200, Benjamin Beichler wrote:
> The ops field is zero initialized, therefore parallel ops is already
> false.
Therefore this patch is completely pointless?
johannes
^ permalink raw reply
* Re: [RFC 1/4] mac80211_hwsim: changed hwsim_radios from list to hashlist keyed by MAC-Address
From: Johannes Berg @ 2017-09-08 14:25 UTC (permalink / raw)
To: Benjamin Beichler, linux-wireless
In-Reply-To: <9df35571-bc40-4af0-8a4f-01ba400dbb50@MAIL1.uni-rostock.de>
On Fri, 2017-09-08 at 16:11 +0200, Benjamin Beichler wrote:
> Use hashlist to improve lookup speed for every received NL-message,
> especially for higher counts of radios, like 100 or more. The
> stringhash
> should be neglible for 6 Bytes MAC-Address, could be improved by
> using
> cast to 64bit integer and hash this instead.
>
> For a more reliable implementation of radio dump, a generation count
> is inserted,
> which indicates a change while dump (this was missing before and
> could lead into problems because of inconsistent NL-dumps).
The idea seems reasonable, but you need major coding style fixes. You
should also correctly line-break your commit messages.
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
should be useful.
> +static unsigned int hash_mac(const u8 *mac )
> +{
> + return full_name_hash(&mac_hash_salt,mac,ETH_ALEN);
> +}
That really should just be using jhash() or so, why bother with string
hashing?
> +
> static spinlock_t hwsim_radio_lock;
> -static LIST_HEAD(hwsim_radios);
> -static int hwsim_radio_idx;
> +static DEFINE_HASHTABLE(hwsim_radios,HWSIM_HT_BITS);
> +static int hwsim_radio_count;
> +static int hwsim_radio_generation=1;
Why not use rhashtable? That will size itself automatically, no need
for the bits. In fact, that also removes the whole question of the hash
algorithm, I think.
Not sure about walking there, but there's rhashtable_walk_*.
> - list_for_each_entry(data2, &hwsim_radios, list) {
> + hash_for_each( hwsim_radios, bucket, data2, list) {
coding style
> +struct mac_address create_mac_from_idx(int idx)
> +{
> + struct mac_address mac;
> + eth_zero_addr(mac.addr);
> + mac.addr[0] = 0x42;
> + mac.addr[3] = idx >> 8;
> + mac.addr[4] = idx;
> + return mac;
> +
> +}
coding style
> static int mac80211_hwsim_new_radio(struct genl_info *info,
> struct hwsim_new_radio_params
> *param)
> {
> int err;
> - u8 addr[ETH_ALEN];
> + struct mac_address mac;
> struct mac80211_hwsim_data *data;
> struct ieee80211_hw *hw;
> enum nl80211_band band;
> const struct ieee80211_ops *ops = &mac80211_hwsim_ops;
> struct net *net;
> - int idx;
> + int idx,hashkey;
> + bool new_id_found=true;
> +
coding style
> if (WARN_ON(param->channels > 1 && !param->use_chanctx))
> return -EINVAL;
>
> spin_lock_bh(&hwsim_radio_lock);
> - idx = hwsim_radio_idx++;
> +
> +
+ if(param->idx == -1){
etc.
[snip]
johannes
^ permalink raw reply
* Re: [RFC 2/4] mac80211_hwsim: add hwsim_tx_rate_flags to Netlink Attributes
From: Johannes Berg @ 2017-09-08 14:26 UTC (permalink / raw)
To: Benjamin Beichler, linux-wireless
In-Reply-To: <fb18fe18-c780-4073-886f-9c16788391ee@MAIL1.uni-rostock.de>
On Fri, 2017-09-08 at 16:11 +0200, Benjamin Beichler wrote:
> For correct interpretation of a tx rate, the corresponding rate flags
> are needed (e.g. whether a HT-MCS rate or a legacy rate) and
> moreover for more correct simulation the other infos of the flags are
> important (like short-GI). Keeping compability, the flags
> are not integrated into the existing hwsim_tx_rate, but transmitted
> as an additional netlink attribute.
This still exposes a lot of internal detail - perhaps it'd be better to
convert to some sort of stable rate representation, like in cfg80211?
Not sure that's sufficient though, it's a bit less detailed.
johannes
^ permalink raw reply
* [RFC 0/4] mac80211_hwsim: improvements for wmediumd-like simulations and config enhancements
From: Benjamin Beichler @ 2017-09-08 14:28 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg, Benjamin Beichler
This patch series includes our efforts for more sophisticated simulations for
wifi-networks.
Especially Patch 2 and 4 add missing functionality.
The patch 1 adds an obvious performance improvement for many radios, since for
every received frame a linear search through all radios is done. Currently the
simple hashlist implementation without dynamic buckets is used, maybe the hash
size is discussable further, but I put no great effort into finding some
special value. Moreover, I didn't measured the utilization of the buckets, but
the worst case would be the same performance as before, if we don't count the
hashing.
Patch 2 adds the rate flags, as already discussed some time ago, to be able to
interpret the right Rate from the tx rates array (e.g. whether it is a MCS and
so on). Maybe some of the generated warnings are discussable, but I don't
know, what the aimed behavior is. Tx-info is a big union, where the rates stay
at the same memory position, therefore the corresponding flags may/should not
change in the driver, but what happens if they did? A short search showed, that
many drivers handle it different ways and the currently only user of
tx-attempts is minstrel_ht, which ignores the flags of a rate.
Patch 3 is only for clarification, but implications are, that currently the
locking of hwsim radios is not needed at all, since after creation of radios
only netlink messages may change the state and netlink callbacks are not
concurrently called, therefore we could reduce locking. On the other hand, we
could enable parallel execution, which may improve environments with multiple
wmediumd instances in different namespaces, since currently they are blocked
against each other.
Patch 4 helps to create conveniently new radios with specific IDs (with their
corresponding MAC-Addresses) since it is crucial in a setup with many mobile
nodes, to create the nodes when they are in the focus of the simulation and
remove them, if they leave and maybe recreate them if they re-arrive.
Signed-off-by: Benjamin Beichler <benjamin.beichler@uni-rostock.de>
--
drivers/net/wireless/mac80211_hwsim.c | 290 ++++++++++++++++++++++++++------
drivers/net/wireless/mac80211_hwsim.h | 67 ++++++++
2 files changed, 305 insertions(+), 52 deletions(-)
^ permalink raw reply
* Re: [RFC 4/4] mac80211_hwsim: add radio idx param to netlink callback of radio creation
From: Johannes Berg @ 2017-09-08 14:28 UTC (permalink / raw)
To: Benjamin Beichler, linux-wireless
In-Reply-To: <c6eda3a2-ad9b-4c33-b3c8-ddc36199ea3e@MAIL1.uni-rostock.de>
On Fri, 2017-09-08 at 16:11 +0200, Benjamin Beichler wrote:
> Since the radio index is already a valid NL attribute, this patch
> simply
> try to read it and create the radio specific to this index by the
> previously used scheme.
>
> Since this allows to create radios out of row, we need to search for
> a
> free index for a new radio, when the index is not present as
> parameter.
This seems like a bad idea, what's the point? You can always change the
MAC address later if you want.
Also, you don't seem to actually do what you said, with the -1.
johannes
^ permalink raw reply
* Re: [RFC 4/4] mac80211_hwsim: add radio idx param to netlink callback of radio creation
From: Benjamin Beichler @ 2017-09-08 14:43 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless
In-Reply-To: <1504880886.20347.4.camel@sipsolutions.net>
[-- Attachment #1: Type: text/plain, Size: 1414 bytes --]
>> Since the radio index is already a valid NL attribute, this patch >> simply try to read it and create the radio specific to this index >>
by the previously used scheme. >> >> Since this allows to create radios
out of row, we need to search >> for a free index for a new radio, when
the index is not present as >> parameter. > > This seems like a bad
idea, what's the point? You can always change > the MAC address later if
you want. AFAIK, you can change the MAC-Address of an interface on the
phy, but not the perm address of the phy. But for frames sent to a
wmediumd always the perm address is used to identify the sender and
receiver. It is really annoying to additionally keep a translation table
in userspace to manage between random ids/mac-addresses to them you use
in a simulation for this.
> > > Also, you don't seem to actually do what you said, with the -1.
OK, I see this is badly mixed up with patch 1, which introduces the
hashlist stuff.
--
M.Sc. Benjamin Beichler
Universität Rostock, Fakultät für Informatik und Elektrotechnik
Institut für Angewandte Mikroelektronik und Datentechnik
University of Rostock, Department of CS and EE
Institute of Applied Microelectronics and CE
Richard-Wagner-Straße 31
18119 Rostock
Deutschland/Germany
phone: +49 (0) 381 498 - 7278
email: Benjamin.Beichler@uni-rostock.de
www: http://www.imd.uni-rostock.de/
[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 5151 bytes --]
^ permalink raw reply
* Re: [RFC 4/4] mac80211_hwsim: add radio idx param to netlink callback of radio creation
From: Johannes Berg @ 2017-09-08 14:46 UTC (permalink / raw)
To: Benjamin Beichler; +Cc: linux-wireless
In-Reply-To: <5635378a-1d80-99f6-0538-9a9c9a7bc0fe@uni-rostock.de>
Uh. Is there anything you can do not to mangle your replies? I don't
even know what you're replying to etc.
> AFAIK, you can change the MAC-Address of an interface on
> the phy, but not the perm address of the phy. But for frames sent to
> a wmediumd always the perm address is used to identify the sender and
> receiver. It is really annoying to additionally keep a translation
> table in userspace to manage between random ids/mac-addresses to them
> you use in a simulation for this.
I think we tried to fix that once, but that caused more problems ...
I'd rather allow you to then specify the MAC address though - the
index/address mapping doesn't need to be the identity, after all.
johannes
^ permalink raw reply
* Re: [RFC 3/4] mac80211_hwsim: explicitly set netlink parallel ops to false
From: Benjamin Beichler @ 2017-09-08 15:07 UTC (permalink / raw)
To: linux-wireless, johannes
In-Reply-To: <1504880360.20347.0.camel@sipsolutions.net>
Am 8=2E September 2017 16:19:20 MESZ schrieb Johannes Berg <johannes@sipso=
lutions=2Enet>:
>On Fri, 2017-09-08 at 16:11 +0200, Benjamin Beichler wrote:
>> The ops field is zero initialized, therefore parallel ops is already
>> false=2E
>
>Therefore this patch is completely pointless?
Sorry my first message was missing regarding this=2E My question is, wheth=
er this is intentionally, and if it is parallel, whether we need extensive =
locking here=2E
>
>johannes
--=20
M=2ESc=2E Benjamin Beichler
Universit=C3=A4t Rostock, Fakult=C3=A4t f=C3=BCr Informatik und Elektrotec=
hnik
Institut f=C3=BCr Angewandte Mikroelektronik und Datentechnik
University of Rostock, Department of CS and EE
Institute of Applied Microelectronics and CE
Richard-Wagner-Stra=C3=9Fe 31
18119 Rostock
Deutschland/Germany
phone: +49 (0) 381 498 - 7278
email: Benjamin=2EBeichler@uni-rostock=2Ede
www: http://www=2Eimd=2Euni-rostock=2Ede/
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox