aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2005-06-18 19:28:06 -0400
committerJeff Garzik <jgarzik@pobox.com>2005-06-27 00:23:55 -0400
commit98c4cae1dafcf1abbfebc0189ff27df586a838b0 (patch)
treedbd2374d0acbc068bb2679a868c2929361f25eb4 /drivers/net
parent8f2abf4430ef2a131926a537ee6325dc43b0ec28 (diff)
[PATCH] orinoco: monitor mode support
Patch from Pavel Roskin
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/orinoco.c208
-rw-r--r--drivers/net/wireless/orinoco.h1
2 files changed, 180 insertions, 29 deletions
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
index 96df2885728f..05c2ad556506 100644
--- a/drivers/net/wireless/orinoco.c
+++ b/drivers/net/wireless/orinoco.c
@@ -499,6 +499,10 @@ static int ignore_disconnect; /* = 0 */
499module_param(ignore_disconnect, int, 0644); 499module_param(ignore_disconnect, int, 0644);
500MODULE_PARM_DESC(ignore_disconnect, "Don't report lost link to the network layer"); 500MODULE_PARM_DESC(ignore_disconnect, "Don't report lost link to the network layer");
501 501
502static int force_monitor; /* = 0 */
503module_param(force_monitor, int, 0644);
504MODULE_PARM_DESC(force_monitor, "Allow monitor mode for all firmware versions");
505
502/********************************************************************/ 506/********************************************************************/
503/* Compile time configuration and compatibility stuff */ 507/* Compile time configuration and compatibility stuff */
504/********************************************************************/ 508/********************************************************************/
@@ -670,6 +674,10 @@ static inline void set_port_type(struct orinoco_private *priv)
670 priv->createibss = 1; 674 priv->createibss = 1;
671 } 675 }
672 break; 676 break;
677 case IW_MODE_MONITOR:
678 priv->port_type = 3;
679 priv->createibss = 0;
680 break;
673 default: 681 default:
674 printk(KERN_ERR "%s: Invalid priv->iw_mode in set_port_type()\n", 682 printk(KERN_ERR "%s: Invalid priv->iw_mode in set_port_type()\n",
675 priv->ndev->name); 683 priv->ndev->name);
@@ -856,7 +864,7 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
856 return 1; 864 return 1;
857 } 865 }
858 866
859 if (! netif_carrier_ok(dev)) { 867 if (! netif_carrier_ok(dev) || (priv->iw_mode == IW_MODE_MONITOR)) {
860 /* Oops, the firmware hasn't established a connection, 868 /* Oops, the firmware hasn't established a connection,
861 silently drop the packet (this seems to be the 869 silently drop the packet (this seems to be the
862 safest approach). */ 870 safest approach). */
@@ -1118,6 +1126,117 @@ static void orinoco_stat_gather(struct net_device *dev,
1118 } 1126 }
1119} 1127}
1120 1128
1129/*
1130 * orinoco_rx_monitor - handle received monitor frames.
1131 *
1132 * Arguments:
1133 * dev network device
1134 * rxfid received FID
1135 * desc rx descriptor of the frame
1136 *
1137 * Call context: interrupt
1138 */
1139static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid,
1140 struct hermes_rx_descriptor *desc)
1141{
1142 u32 hdrlen = 30; /* return full header by default */
1143 u32 datalen = 0;
1144 u16 fc;
1145 int err;
1146 int len;
1147 struct sk_buff *skb;
1148 struct orinoco_private *priv = netdev_priv(dev);
1149 struct net_device_stats *stats = &priv->stats;
1150 hermes_t *hw = &priv->hw;
1151
1152 len = le16_to_cpu(desc->data_len);
1153
1154 /* Determine the size of the header and the data */
1155 fc = le16_to_cpu(desc->frame_ctl);
1156 switch (fc & IEEE80211_FCTL_FTYPE) {
1157 case IEEE80211_FTYPE_DATA:
1158 if ((fc & IEEE80211_FCTL_TODS)
1159 && (fc & IEEE80211_FCTL_FROMDS))
1160 hdrlen = 30;
1161 else
1162 hdrlen = 24;
1163 datalen = len;
1164 break;
1165 case IEEE80211_FTYPE_MGMT:
1166 hdrlen = 24;
1167 datalen = len;
1168 break;
1169 case IEEE80211_FTYPE_CTL:
1170 switch (fc & IEEE80211_FCTL_STYPE) {
1171 case IEEE80211_STYPE_PSPOLL:
1172 case IEEE80211_STYPE_RTS:
1173 case IEEE80211_STYPE_CFEND:
1174 case IEEE80211_STYPE_CFENDACK:
1175 hdrlen = 16;
1176 break;
1177 case IEEE80211_STYPE_CTS:
1178 case IEEE80211_STYPE_ACK:
1179 hdrlen = 10;
1180 break;
1181 }
1182 break;
1183 default:
1184 /* Unknown frame type */
1185 break;
1186 }
1187
1188 /* sanity check the length */
1189 if (datalen > IEEE80211_DATA_LEN + 12) {
1190 printk(KERN_DEBUG "%s: oversized monitor frame, "
1191 "data length = %d\n", dev->name, datalen);
1192 err = -EIO;
1193 stats->rx_length_errors++;
1194 goto update_stats;
1195 }
1196
1197 skb = dev_alloc_skb(hdrlen + datalen);
1198 if (!skb) {
1199 printk(KERN_WARNING "%s: Cannot allocate skb for monitor frame\n",
1200 dev->name);
1201 err = -ENOMEM;
1202 goto drop;
1203 }
1204
1205 /* Copy the 802.11 header to the skb */
1206 memcpy(skb_put(skb, hdrlen), &(desc->frame_ctl), hdrlen);
1207 skb->mac.raw = skb->data;
1208
1209 /* If any, copy the data from the card to the skb */
1210 if (datalen > 0) {
1211 err = hermes_bap_pread(hw, IRQ_BAP, skb_put(skb, datalen),
1212 ALIGN(datalen, 2), rxfid,
1213 HERMES_802_2_OFFSET);
1214 if (err) {
1215 printk(KERN_ERR "%s: error %d reading monitor frame\n",
1216 dev->name, err);
1217 goto drop;
1218 }
1219 }
1220
1221 skb->dev = dev;
1222 skb->ip_summed = CHECKSUM_NONE;
1223 skb->pkt_type = PACKET_OTHERHOST;
1224 skb->protocol = __constant_htons(ETH_P_802_2);
1225
1226 dev->last_rx = jiffies;
1227 stats->rx_packets++;
1228 stats->rx_bytes += skb->len;
1229
1230 netif_rx(skb);
1231 return;
1232
1233 drop:
1234 dev_kfree_skb_irq(skb);
1235 update_stats:
1236 stats->rx_errors++;
1237 stats->rx_dropped++;
1238}
1239
1121static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw) 1240static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
1122{ 1241{
1123 struct orinoco_private *priv = netdev_priv(dev); 1242 struct orinoco_private *priv = netdev_priv(dev);
@@ -1137,24 +1256,29 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
1137 if (err) { 1256 if (err) {
1138 printk(KERN_ERR "%s: error %d reading Rx descriptor. " 1257 printk(KERN_ERR "%s: error %d reading Rx descriptor. "
1139 "Frame dropped.\n", dev->name, err); 1258 "Frame dropped.\n", dev->name, err);
1140 stats->rx_errors++; 1259 goto update_stats;
1141 goto drop;
1142 } 1260 }
1143 1261
1144 status = le16_to_cpu(desc.status); 1262 status = le16_to_cpu(desc.status);
1145 1263
1146 if (status & HERMES_RXSTAT_ERR) { 1264 if (status & HERMES_RXSTAT_BADCRC) {
1147 if (status & HERMES_RXSTAT_UNDECRYPTABLE) { 1265 DEBUG(1, "%s: Bad CRC on Rx. Frame dropped.\n",
1148 wstats->discard.code++; 1266 dev->name);
1149 DEBUG(1, "%s: Undecryptable frame on Rx. Frame dropped.\n", 1267 stats->rx_crc_errors++;
1150 dev->name); 1268 goto update_stats;
1151 } else { 1269 }
1152 stats->rx_crc_errors++;
1153 DEBUG(1, "%s: Bad CRC on Rx. Frame dropped.\n", dev->name);
1154 }
1155 1270
1156 stats->rx_errors++; 1271 /* Handle frames in monitor mode */
1157 goto drop; 1272 if (priv->iw_mode == IW_MODE_MONITOR) {
1273 orinoco_rx_monitor(dev, rxfid, &desc);
1274 return;
1275 }
1276
1277 if (status & HERMES_RXSTAT_UNDECRYPTABLE) {
1278 DEBUG(1, "%s: Undecryptable frame on Rx. Frame dropped.\n",
1279 dev->name);
1280 wstats->discard.code++;
1281 goto update_stats;
1158 } 1282 }
1159 1283
1160 length = le16_to_cpu(desc.data_len); 1284 length = le16_to_cpu(desc.data_len);
@@ -1165,15 +1289,13 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
1165 /* At least on Symbol firmware with PCF we get quite a 1289 /* At least on Symbol firmware with PCF we get quite a
1166 lot of these legitimately - Poll frames with no 1290 lot of these legitimately - Poll frames with no
1167 data. */ 1291 data. */
1168 stats->rx_dropped++; 1292 return;
1169 goto drop;
1170 } 1293 }
1171 if (length > IEEE802_11_DATA_LEN) { 1294 if (length > IEEE802_11_DATA_LEN) {
1172 printk(KERN_WARNING "%s: Oversized frame received (%d bytes)\n", 1295 printk(KERN_WARNING "%s: Oversized frame received (%d bytes)\n",
1173 dev->name, length); 1296 dev->name, length);
1174 stats->rx_length_errors++; 1297 stats->rx_length_errors++;
1175 stats->rx_errors++; 1298 goto update_stats;
1176 goto drop;
1177 } 1299 }
1178 1300
1179 /* We need space for the packet data itself, plus an ethernet 1301 /* We need space for the packet data itself, plus an ethernet
@@ -1185,7 +1307,7 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
1185 if (!skb) { 1307 if (!skb) {
1186 printk(KERN_WARNING "%s: Can't allocate skb for Rx\n", 1308 printk(KERN_WARNING "%s: Can't allocate skb for Rx\n",
1187 dev->name); 1309 dev->name);
1188 goto drop; 1310 goto update_stats;
1189 } 1311 }
1190 1312
1191 /* We'll prepend the header, so reserve space for it. The worst 1313 /* We'll prepend the header, so reserve space for it. The worst
@@ -1199,7 +1321,6 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
1199 if (err) { 1321 if (err) {
1200 printk(KERN_ERR "%s: error %d reading frame. " 1322 printk(KERN_ERR "%s: error %d reading frame. "
1201 "Frame dropped.\n", dev->name, err); 1323 "Frame dropped.\n", dev->name, err);
1202 stats->rx_errors++;
1203 goto drop; 1324 goto drop;
1204 } 1325 }
1205 1326
@@ -1245,11 +1366,10 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
1245 return; 1366 return;
1246 1367
1247 drop: 1368 drop:
1369 dev_kfree_skb_irq(skb);
1370 update_stats:
1371 stats->rx_errors++;
1248 stats->rx_dropped++; 1372 stats->rx_dropped++;
1249
1250 if (skb)
1251 dev_kfree_skb_irq(skb);
1252 return;
1253} 1373}
1254 1374
1255/********************************************************************/ 1375/********************************************************************/
@@ -2065,6 +2185,20 @@ static int __orinoco_program_rids(struct net_device *dev)
2065 } 2185 }
2066 } 2186 }
2067 2187
2188 if (priv->iw_mode == IW_MODE_MONITOR) {
2189 /* Enable monitor mode */
2190 dev->type = ARPHRD_IEEE80211;
2191 err = hermes_docmd_wait(hw, HERMES_CMD_TEST |
2192 HERMES_TEST_MONITOR, 0, NULL);
2193 } else {
2194 /* Disable monitor mode */
2195 dev->type = ARPHRD_ETHER;
2196 err = hermes_docmd_wait(hw, HERMES_CMD_TEST |
2197 HERMES_TEST_STOP, 0, NULL);
2198 }
2199 if (err)
2200 return err;
2201
2068 /* Set promiscuity / multicast*/ 2202 /* Set promiscuity / multicast*/
2069 priv->promiscuous = 0; 2203 priv->promiscuous = 0;
2070 priv->mc_count = 0; 2204 priv->mc_count = 0;
@@ -2413,6 +2547,7 @@ static int determine_firmware(struct net_device *dev)
2413 priv->has_pm = (firmver >= 0x40020); /* Don't work in 7.52 ? */ 2547 priv->has_pm = (firmver >= 0x40020); /* Don't work in 7.52 ? */
2414 priv->ibss_port = 1; 2548 priv->ibss_port = 1;
2415 priv->has_hostscan = (firmver >= 0x8000a); 2549 priv->has_hostscan = (firmver >= 0x8000a);
2550 priv->broken_monitor = (firmver >= 0x80000);
2416 2551
2417 /* Tested with Agere firmware : 2552 /* Tested with Agere firmware :
2418 * 1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.16 ; 7.28 => Jean II 2553 * 1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.16 ; 7.28 => Jean II
@@ -2980,6 +3115,15 @@ static int orinoco_ioctl_setmode(struct net_device *dev,
2980 case IW_MODE_INFRA: 3115 case IW_MODE_INFRA:
2981 break; 3116 break;
2982 3117
3118 case IW_MODE_MONITOR:
3119 if (priv->broken_monitor && !force_monitor) {
3120 printk(KERN_WARNING "%s: Monitor mode support is "
3121 "buggy in this firmware, not enabling\n",
3122 dev->name);
3123 err = -EOPNOTSUPP;
3124 }
3125 break;
3126
2983 default: 3127 default:
2984 err = -EOPNOTSUPP; 3128 err = -EOPNOTSUPP;
2985 break; 3129 break;
@@ -3355,11 +3499,9 @@ static int orinoco_ioctl_setfreq(struct net_device *dev,
3355 unsigned long flags; 3499 unsigned long flags;
3356 int err = -EINPROGRESS; /* Call commit handler */ 3500 int err = -EINPROGRESS; /* Call commit handler */
3357 3501
3358 /* We can only use this in Ad-Hoc demo mode to set the operating 3502 /* In infrastructure mode the AP sets the channel */
3359 * frequency, or in IBSS mode to set the frequency where the IBSS 3503 if (priv->iw_mode == IW_MODE_INFRA)
3360 * will be created - Jean II */ 3504 return -EBUSY;
3361 if (priv->iw_mode != IW_MODE_ADHOC)
3362 return -EOPNOTSUPP;
3363 3505
3364 if ( (frq->e == 0) && (frq->m <= 1000) ) { 3506 if ( (frq->e == 0) && (frq->m <= 1000) ) {
3365 /* Setting by channel number */ 3507 /* Setting by channel number */
@@ -3383,7 +3525,15 @@ static int orinoco_ioctl_setfreq(struct net_device *dev,
3383 3525
3384 if (orinoco_lock(priv, &flags) != 0) 3526 if (orinoco_lock(priv, &flags) != 0)
3385 return -EBUSY; 3527 return -EBUSY;
3528
3386 priv->channel = chan; 3529 priv->channel = chan;
3530 if (priv->iw_mode == IW_MODE_MONITOR) {
3531 /* Fast channel change - no commit if successful */
3532 hermes_t *hw = &priv->hw;
3533 err = hermes_docmd_wait(hw, HERMES_CMD_TEST |
3534 HERMES_TEST_SET_CHANNEL,
3535 chan, NULL);
3536 }
3387 orinoco_unlock(priv, &flags); 3537 orinoco_unlock(priv, &flags);
3388 3538
3389 return err; 3539 return err;
diff --git a/drivers/net/wireless/orinoco.h b/drivers/net/wireless/orinoco.h
index 2a6b1c09b26d..0f4be5da46e7 100644
--- a/drivers/net/wireless/orinoco.h
+++ b/drivers/net/wireless/orinoco.h
@@ -94,6 +94,7 @@ struct orinoco_private {
94 unsigned int has_sensitivity:1; 94 unsigned int has_sensitivity:1;
95 unsigned int has_hostscan:1; 95 unsigned int has_hostscan:1;
96 unsigned int broken_disableport:1; 96 unsigned int broken_disableport:1;
97 unsigned int broken_monitor:1;
97 98
98 /* Configuration paramaters */ 99 /* Configuration paramaters */
99 u32 iw_mode; 100 u32 iw_mode;