From: "Luis R. Rodriguez" 2004-03-18 Aurelien Alleaume islpci_eth.c, islpci_dev.h, isl_ioctl.c : iwspy support. Ran lindent. Signed-off-by: Andrew Morton --- 25-akpm/drivers/net/wireless/prism54/isl_ioctl.c | 43 ++++++++++++----- 25-akpm/drivers/net/wireless/prism54/isl_oid.h | 17 ++++++- 25-akpm/drivers/net/wireless/prism54/islpci_dev.h | 7 ++ 25-akpm/drivers/net/wireless/prism54/islpci_eth.c | 53 ++++++++++++++-------- 25-akpm/drivers/net/wireless/prism54/oid_mgt.c | 11 ++++ 25-akpm/drivers/net/wireless/prism54/oid_mgt.h | 4 + 6 files changed, 100 insertions(+), 35 deletions(-) diff -puN drivers/net/wireless/prism54/isl_ioctl.c~prism54-add-iwspy-support drivers/net/wireless/prism54/isl_ioctl.c --- 25/drivers/net/wireless/prism54/isl_ioctl.c~prism54-add-iwspy-support Wed May 26 16:16:57 2004 +++ 25-akpm/drivers/net/wireless/prism54/isl_ioctl.c Wed May 26 16:16:57 2004 @@ -1,4 +1,4 @@ -/* $Header: /var/lib/cvs/prism54-ng/ksrc/isl_ioctl.c,v 1.144 2004/03/18 11:16:23 ajfa Exp $ +/* $Header: /var/lib/cvs/prism54-ng/ksrc/isl_ioctl.c,v 1.145 2004/03/18 15:27:44 ajfa Exp $ * * Copyright (C) 2002 Intersil Americas Inc. * (C) 2003,2004 Aurelien Alleaume @@ -2098,6 +2098,31 @@ prism54_debug_set_oid(struct net_device return ret; } +static int +prism54_set_spy(struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *uwrq, char *extra) +{ + islpci_private *priv = netdev_priv(ndev); + u32 u, oid = OID_INL_CONFIG; + + down_write(&priv->mib_sem); + mgt_get(priv, OID_INL_CONFIG, &u); + + if ((uwrq->data.length == 0) && (priv->spy_data.spy_number > 0)) + /* disable spy */ + u &= ~INL_CONFIG_RXANNEX; + else if ((uwrq->data.length > 0) && (priv->spy_data.spy_number == 0)) + /* enable spy */ + u |= INL_CONFIG_RXANNEX; + + mgt_set(priv, OID_INL_CONFIG, &u); + mgt_commit_list(priv, &oid, 1); + up_write(&priv->mib_sem); + + return iw_handler_set_spy(ndev, info, uwrq, extra); +} + static const iw_handler prism54_handler[] = { (iw_handler) prism54_commit, /* SIOCSIWCOMMIT */ (iw_handler) prism54_get_name, /* SIOCGIWNAME */ @@ -2115,7 +2140,7 @@ static const iw_handler prism54_handler[ (iw_handler) NULL, /* SIOCGIWPRIV */ (iw_handler) NULL, /* SIOCSIWSTATS */ (iw_handler) NULL, /* SIOCGIWSTATS */ - iw_handler_set_spy, /* SIOCSIWSPY */ + prism54_set_spy, /* SIOCSIWSPY */ iw_handler_get_spy, /* SIOCGIWSPY */ iw_handler_set_thrspy, /* SIOCSIWTHRSPY */ iw_handler_get_thrspy, /* SIOCGIWTHRSPY */ @@ -2182,7 +2207,6 @@ static const iw_handler prism54_handler[ #define IWPRIV_SSID(n,x) IWPRIV_SET_SSID(n,x), IWPRIV_GET(n,x) #define IWPRIV_ADDR(n,x) IWPRIV_SET_ADDR(n,x), IWPRIV_GET(n,x) - /* Note : limited to 128 private ioctls */ static const struct iw_priv_args prism54_private_args[] = { @@ -2261,7 +2285,7 @@ static const struct iw_priv_args prism54 IWPRIV_GET(DOT11_OID_FREQUENCYACTIVITY, "freqactivity"), IWPRIV_U32(DOT11_OID_NONERPPROTECTION, "nonerpprotec"), IWPRIV_U32(DOT11_OID_PROFILES, "profile"), - IWPRIV_GET(DOT11_OID_EXTENDEDRATES,"extrates"), + IWPRIV_GET(DOT11_OID_EXTENDEDRATES, "extrates"), IWPRIV_U32(DOT11_OID_MLMEAUTOLEVEL, "mlmelevel"), IWPRIV_GET(DOT11_OID_BSSS, "bsss"), @@ -2308,20 +2332,13 @@ const struct iw_handler_def prism54_hand .standard = (iw_handler *) prism54_handler, .private = (iw_handler *) prism54_private_handler, .private_args = (struct iw_priv_args *) prism54_private_args, + .spy_offset = offsetof(islpci_private, spy_data), }; -/* These ioctls won't work with the new API */ +/* For ioctls that don't work with the new API */ int prism54_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) { - /*struct iwreq *wrq = (struct iwreq *) rq; - islpci_private *priv = netdev_priv(ndev); - int ret = 0; - - switch (cmd) { - - } - */ return -EOPNOTSUPP; } diff -puN drivers/net/wireless/prism54/isl_oid.h~prism54-add-iwspy-support drivers/net/wireless/prism54/isl_oid.h --- 25/drivers/net/wireless/prism54/isl_oid.h~prism54-add-iwspy-support Wed May 26 16:16:57 2004 +++ 25-akpm/drivers/net/wireless/prism54/isl_oid.h Wed May 26 16:16:57 2004 @@ -1,9 +1,9 @@ /* - * $Id: isl_oid.h,v 1.4 2004/03/18 11:16:23 ajfa Exp $ + * $Id: isl_oid.h,v 1.5 2004/03/18 15:27:44 ajfa Exp $ * * Copyright (C) 2003 Herbert Valerio Riedel * Copyright (C) 2004 Luis R. Rodriguez - * Copyright (C) 2004 Aurélien Alleaume + * Copyright (C) 2004 Aurelien Alleaume * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -91,6 +91,19 @@ struct obj_frequencies { u16 mhz[0]; } __attribute__ ((packed)); +struct obj_rx_annex { + u8 addr1[ETH_ALEN]; + u8 addr2[ETH_ALEN]; + u32 something0; + u32 time; + u16 something1; + u16 rate; + u16 freq; + u16 something2; + u8 rssi; + u8 pad[3]; +} __attribute__ ((packed)); + /* * in case everything's ok, the inlined function below will be * optimized away by the compiler... diff -puN drivers/net/wireless/prism54/islpci_dev.h~prism54-add-iwspy-support drivers/net/wireless/prism54/islpci_dev.h --- 25/drivers/net/wireless/prism54/islpci_dev.h~prism54-add-iwspy-support Wed May 26 16:16:57 2004 +++ 25-akpm/drivers/net/wireless/prism54/islpci_dev.h Wed May 26 16:16:57 2004 @@ -1,4 +1,4 @@ -/* $Header: /var/lib/cvs/prism54-ng/ksrc/islpci_dev.h,v 1.56 2004/03/18 11:44:17 ajfa Exp $ +/* $Header: /var/lib/cvs/prism54-ng/ksrc/islpci_dev.h,v 1.57 2004/03/18 15:27:44 ajfa Exp $ * * Copyright (C) 2002 Intersil Americas Inc. * Copyright (C) 2003 Herbert Valerio Riedel @@ -26,6 +26,7 @@ #include #include #include +#include #include #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,41) @@ -111,6 +112,8 @@ typedef struct { struct iw_statistics local_iwstatistics; struct iw_statistics iwstatistics; + struct iw_spy_data spy_data; /* iwspy support */ + struct islpci_acl acl; /* PCI bus allocation & configuration members */ @@ -182,7 +185,7 @@ typedef struct { islpci_state_t state; int state_off; /* enumeration of off-state, if 0 then * we're not in any off-state */ - + /* WPA stuff */ int wpa; /* WPA mode enabled */ struct list_head bss_wpa_list; diff -puN drivers/net/wireless/prism54/islpci_eth.c~prism54-add-iwspy-support drivers/net/wireless/prism54/islpci_eth.c --- 25/drivers/net/wireless/prism54/islpci_eth.c~prism54-add-iwspy-support Wed May 26 16:16:57 2004 +++ 25-akpm/drivers/net/wireless/prism54/islpci_eth.c Wed May 26 16:16:57 2004 @@ -1,7 +1,7 @@ -/* $Header: /var/lib/cvs/prism54-ng/ksrc/islpci_eth.c,v 1.30 2004/03/18 11:44:17 ajfa Exp $ +/* $Header: /var/lib/cvs/prism54-ng/ksrc/islpci_eth.c,v 1.31 2004/03/18 15:27:44 ajfa Exp $ * * Copyright (C) 2002 Intersil Americas Inc. - * + * Copyright (C) 2004 Aurelien Alleaume * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License @@ -205,7 +205,7 @@ islpci_eth_transmit(struct sk_buff *skb, priv->data_low_tx[index] = skb; /* set the proper fragment start address and size information */ fragment->size = cpu_to_le16(frame_size); - fragment->flags = cpu_to_le16(0); /* set to 1 if more fragments */ + fragment->flags = cpu_to_le16(0); /* set to 1 if more fragments */ fragment->address = cpu_to_le32(pci_map_address); curr_frag++; @@ -215,7 +215,7 @@ islpci_eth_transmit(struct sk_buff *skb, cb->driver_curr_frag[ISL38XX_CB_TX_DATA_LQ] = cpu_to_le32(curr_frag); if (curr_frag - priv->free_data_tx + ISL38XX_MIN_QTHRESHOLD - > ISL38XX_CB_TX_QSIZE) { + > ISL38XX_CB_TX_QSIZE) { /* stop sends from upper layers */ netif_stop_queue(ndev); @@ -236,7 +236,7 @@ islpci_eth_transmit(struct sk_buff *skb, return 0; - drop_free: + drop_free: /* free the skbuf structure before aborting */ dev_kfree_skb(skb); skb = NULL; @@ -266,7 +266,8 @@ islpci_eth_receive(islpci_private *priv) index = priv->free_data_rx % ISL38XX_CB_RX_QSIZE; size = le16_to_cpu(control_block->rx_data_low[index].size); skb = priv->data_low_rx[index]; - offset = ((unsigned long) le32_to_cpu(control_block->rx_data_low[index].address) - + offset = ((unsigned long) + le32_to_cpu(control_block->rx_data_low[index].address) - (unsigned long) skb->data) & 3; #if VERBOSE > SHOW_ERROR_MESSAGES @@ -320,15 +321,34 @@ islpci_eth_receive(islpci_private *priv) * header and without the FCS. But there a is a bit that * indicates if the packet is corrupted :-) */ if (skb->data[8] & 0x01) - /* This one is bad. Drop it !*/ + /* This one is bad. Drop it ! */ discard = 1; skb_pull(skb, 20); skb->protocol = htons(ETH_P_802_2); skb->mac.raw = skb->data; skb->pkt_type = PACKET_OTHERHOST; - } else + } else { + if (skb->data[2 * ETH_ALEN] == 0) { + /* The packet has a rx_annex. Read it for spy monitoring, Then + * remove it, while keeping the 2 leading MAC addr. + */ + struct iw_quality wstats; + struct obj_rx_annex *annex = + (struct obj_rx_annex *) skb->data; + wstats.level = annex->rssi; + /* The noise value can be a bit outdated if nobody's + * reading wireless stats... */ + wstats.noise = priv->iwstatistics.qual.noise; + wstats.qual = wstats.level - wstats.noise; + wstats.updated = 0x07; + /* Update spy records */ + wireless_spy_update(ndev, annex->addr2, &wstats); + /* 20 = sizeof(struct obj_rx_annex) - 2*ETH_ALEN */ + memcpy(skb->data + 20, skb->data, 2 * ETH_ALEN); + skb_pull(skb, 20); + } skb->protocol = eth_type_trans(skb, ndev); - + } skb->ip_summed = CHECKSUM_NONE; priv->statistics.rx_packets++; priv->statistics.rx_bytes += size; @@ -343,8 +363,7 @@ islpci_eth_receive(islpci_private *priv) if (discard) { dev_kfree_skb(skb); skb = NULL; - } - else + } else netif_rx(skb); /* increment the read index for the rx data low queue */ @@ -395,7 +414,7 @@ islpci_eth_receive(islpci_private *priv) wmb(); /* increment the driver read pointer */ - add_le32p((u32 *) & control_block-> + add_le32p((u32 *) &control_block-> driver_curr_frag[ISL38XX_CB_RX_DATA_LQ], 1); } @@ -408,10 +427,10 @@ islpci_eth_receive(islpci_private *priv) void islpci_do_reset_and_wake(void *data) { - islpci_private *priv = (islpci_private *) data; - islpci_reset(priv, 1); - netif_wake_queue(priv->ndev); - priv->reset_task_pending = 0; + islpci_private *priv = (islpci_private *) data; + islpci_reset(priv, 1); + netif_wake_queue(priv->ndev); + priv->reset_task_pending = 0; } void @@ -423,7 +442,7 @@ islpci_eth_tx_timeout(struct net_device /* increment the transmit error counter */ statistics->tx_errors++; - if(!priv->reset_task_pending) { + if (!priv->reset_task_pending) { priv->reset_task_pending = 1; netif_stop_queue(ndev); schedule_work(&priv->reset_task); diff -puN drivers/net/wireless/prism54/oid_mgt.c~prism54-add-iwspy-support drivers/net/wireless/prism54/oid_mgt.c --- 25/drivers/net/wireless/prism54/oid_mgt.c~prism54-add-iwspy-support Wed May 26 16:16:57 2004 +++ 25-akpm/drivers/net/wireless/prism54/oid_mgt.c Wed May 26 16:16:57 2004 @@ -570,6 +570,17 @@ mgt_set(islpci_private *priv, enum oid_n mgt_cpu_to_le(isl_oid[n].flags & OID_FLAG_TYPE, priv->mib[n]); } +void +mgt_get(islpci_private *priv, enum oid_num_t n, void *res) +{ + BUG_ON(OID_NUM_LAST <= n); + BUG_ON(priv->mib[n] == NULL); + BUG_ON(res == NULL); + + memcpy(res, priv->mib[n], isl_oid[n].size); + mgt_le_to_cpu(isl_oid[n].flags & OID_FLAG_TYPE, res); +} + /* Commits the cache. Lock outside. */ static enum oid_num_t commit_part1[] = { diff -puN drivers/net/wireless/prism54/oid_mgt.h~prism54-add-iwspy-support drivers/net/wireless/prism54/oid_mgt.h --- 25/drivers/net/wireless/prism54/oid_mgt.h~prism54-add-iwspy-support Wed May 26 16:16:57 2004 +++ 25-akpm/drivers/net/wireless/prism54/oid_mgt.h Wed May 26 16:16:57 2004 @@ -37,12 +37,14 @@ void mgt_le_to_cpu(int, void *); int mgt_set_request(islpci_private *, enum oid_num_t, int, void *); int mgt_get_request(islpci_private *, enum oid_num_t, int, void *, - union oid_res_t *); + union oid_res_t *); int mgt_commit_list(islpci_private *, enum oid_num_t *, int); void mgt_set(islpci_private *, enum oid_num_t, void *); +void mgt_get(islpci_private *, enum oid_num_t, void *); + void mgt_commit(islpci_private *); int mgt_mlme_answer(islpci_private *); _