Search Linux Wireless

Re: Linux 2.6.24-rc7

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



NACK

memmove will cause redundant high CPU utilization in 11n High Throughput.

Such changes, if done, should be wrapped with some
#ifdef CANT_HANDLE_UNALIGNED_....

And better be done in mac80211 and not at driver level. iwlwifi skb is
802.11 and 802.3 frame.

On 1/25/08, John W. Linville <linville@xxxxxxxxxxxxx> wrote:

> Alright, here is my whack at it...  The iwl_handle_data_packet_monitor
> bits are untested, as I appear to be too daft to figure-out how to
> exercise those paths.
>
> Anyway, this is mostly just so we can scope the driver change required
> in absence of a firmware change.  Persumably the changes required if
> we were to put such code in mac80211 would be similar.
>
> John
>
> -----
>
> From: John W. Linville <linville@xxxxxxxxxxxxx>
> Subject: [PATCH] iwlwifi: move data at CPU to ensure 4-byte alignment for payload
>
> Ugly, but if the firmware won't cooperate...
>
> Signed-off-by: John W. Linville <linville@xxxxxxxxxxxxx>
> ---
>  drivers/net/wireless/iwlwifi/iwl-3945.c     |   13 ++++++++++---
>  drivers/net/wireless/iwlwifi/iwl-4965.c     |   10 +++++++++-
>  drivers/net/wireless/iwlwifi/iwl3945-base.c |   10 +++++++++-
>  drivers/net/wireless/iwlwifi/iwl4965-base.c |   10 +++++++++-
>  4 files changed, 37 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
> index 3a45fe9..06cd28e 100644
> --- a/drivers/net/wireless/iwlwifi/iwl-3945.c
> +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
> @@ -252,6 +252,7 @@ static void iwl3945_handle_data_packet(struct iwl_priv *priv, int is_data,
>        struct iwl_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
>        struct iwl_rx_frame_end *rx_end = IWL_RX_END(pkt);
>        short len = le16_to_cpu(rx_hdr->len);
> +       int hdrlen, align;
>
>        /* We received data from the HW, so stop the watchdog */
>        if (unlikely((len + IWL_RX_FRAME_SIZE) > skb_tailroom(rxb->skb))) {
> @@ -275,11 +276,17 @@ static void iwl3945_handle_data_packet(struct iwl_priv *priv, int is_data,
>                return;
>        }
>
> -       skb_reserve(rxb->skb, (void *)rx_hdr->payload - (void *)pkt);
> +       hdr = (void *)rx_hdr->payload;
> +       hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control));
> +       align = hdrlen & 3;
> +
> +       skb_reserve(rxb->skb, (void *)rx_hdr->payload - (void *)pkt - align);
>        /* Set the size of the skb to the size of the frame */
> -       skb_put(rxb->skb, le16_to_cpu(rx_hdr->len));
> +       skb_put(rxb->skb, len);
>
> -       hdr = (void *)rxb->skb->data;
> +        /* align payload on 4-byte boundary if necessary */
> +       if (align)
> +               memmove((void *)hdr - align, hdr, len);
>
>        if (iwl_param_hwcrypto)
>                iwl_set_decrypted_flag(priv, rxb->skb,
> diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
> index 891f90d..11eb75b 100644
> --- a/drivers/net/wireless/iwlwifi/iwl-4965.c
> +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
> @@ -3496,6 +3496,7 @@ static void iwl4965_handle_data_packet(struct iwl_priv *priv, int is_data,
>        __le32 *rx_end;
>        unsigned int skblen;
>        u32 ampdu_status;
> +       int hdrlen, align;
>
>        if (!include_phy && priv->last_phy_res[0])
>                rx_start = (struct iwl4965_rx_phy_res *)&priv->last_phy_res[1];
> @@ -3533,10 +3534,17 @@ static void iwl4965_handle_data_packet(struct iwl_priv *priv, int is_data,
>        ampdu_status = le32_to_cpu(*rx_end);
>        skblen = ((u8 *) rx_end - (u8 *) & pkt->u.raw[0]) + sizeof(u32);
>
> +       hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control));
> +       align = hdrlen & 3;
> +
>        /* start from MAC */
> -       skb_reserve(rxb->skb, (void *)hdr - (void *)pkt);
> +       skb_reserve(rxb->skb, (void *)hdr - (void *)pkt - align);
>        skb_put(rxb->skb, len); /* end where data ends */
>
> +       /* align payload on 4-byte boundary if necessary */
> +       if (align)
> +               memmove(rxb->skb->data, hdr, len);
> +
>        /* We only process data packets if the interface is open */
>        if (unlikely(!priv->is_open)) {
>                IWL_DEBUG_DROP_LIMIT
> diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
> index 1a6b0e0..d6018bd 100644
> --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
> +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
> @@ -3056,7 +3056,9 @@ void iwl_handle_data_packet_monitor(struct iwl_priv *priv,
>                                    struct ieee80211_rx_status *stats,
>                                    u16 phy_flags)
>  {
> +       struct ieee80211_hdr *hdr;
>        struct iwl_rt_rx_hdr *iwl_rt;
> +       int hdrlen, align;
>
>        /* First cache any information we need before we overwrite
>         * the information provided in the skb from the hardware */
> @@ -3072,8 +3074,14 @@ void iwl_handle_data_packet_monitor(struct iwl_priv *priv,
>                return;
>        }
>
> +       /* determine payload alignment adjustment */
> +       hdr = data;
> +       hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control))
> +               + sizeof(*iwl_rt);
> +       align = 4 - (hdrlen & 3); /* invert align since already at skb head */
> +
>        /* copy the frame data to write after where the radiotap header goes */
> -       iwl_rt = (void *)rxb->skb->data;
> +       iwl_rt = (void *)rxb->skb->data + align;
>        memmove(iwl_rt->payload, data, len);
>
>        iwl_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION;
> diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
> index 6cd57c2..9ef9d14 100644
> --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
> +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
> @@ -3144,7 +3144,9 @@ void iwl_handle_data_packet_monitor(struct iwl_priv *priv,
>                                    struct ieee80211_rx_status *stats,
>                                    u16 phy_flags)
>  {
> +       struct ieee80211_hdr *hdr;
>        struct iwl_rt_rx_hdr *iwl_rt;
> +       int hdrlen, align;
>
>        /* First cache any information we need before we overwrite
>         * the information provided in the skb from the hardware */
> @@ -3160,8 +3162,14 @@ void iwl_handle_data_packet_monitor(struct iwl_priv *priv,
>                return;
>        }
>
> +       /* determine payload alignment adjustment */
> +       hdr = data;
> +       hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control))
> +               + sizeof(*iwl_rt);
> +       align = 4 - (hdrlen & 3); /* invert align since already at skb head */
> +
>        /* copy the frame data to write after where the radiotap header goes */
> -       iwl_rt = (void *)rxb->skb->data;
> +       iwl_rt = (void *)rxb->skb->data + align;
>        memmove(iwl_rt->payload, data, len);
>
>        iwl_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION;
> --
> 1.5.3.3
>
> --
> John W. Linville
> linville@xxxxxxxxxxxxx
> -
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
-
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]
  Powered by Linux