From: Andreas Mohr <andim2@users.sourceforge.net>
To: acx100-devel@lists.sourceforge.net
Cc: netdev@vger.kernel.org
Subject: [PATCH] WLAN acx100: OOPS fix, KERN_xxx, misc.
Date: Mon, 16 Jan 2006 15:02:33 +0100 [thread overview]
Message-ID: <20060116140233.GA8170@rhlx01.fht-esslingen.de> (raw)
[-- Attachment #1: Type: text/plain, Size: 833 bytes --]
Hi all (and especially Denis),
acx-20060116_misc.diff:
- fix OOPS in acx_l_rxmonitor() (wrong ndev->type setting leading to memcpy
of negative size) by reworking monitor mode type setup and adding
missing sanity checks
- rename acx1XX_ie_powermgmt_t to more correct acx1XX_ie_powersave_t
- fix format string compile warnings
- add <linux/compiler.h> include apparently required for __iomem define
around Linux 2.6.8
- rework eCPU init by replacing static msleep with faster, more intelligent
(hopefully) busy-wait
acx-20060116_KERN_xxx.diff (too large: gzipped):
- add proper KERN_xxx prefixes to printk() as requested recently
Note that both patches are based on acx-20060116 proper (rediffed from
acx-20060113), smallish conflicts may result; apply acx-20060116_KERN_xxx.diff after acx-20060116_misc.diff.
Andreas Mohr
[-- Attachment #2: acx-20060116_misc.diff --]
[-- Type: text/plain, Size: 9559 bytes --]
diff -urN acx-20060116.orig/acx_struct.h acx-20060116_misc/acx_struct.h
--- acx-20060116.orig/acx_struct.h 2006-01-15 12:03:38.000000000 +0100
+++ acx-20060116_misc/acx_struct.h 2006-01-16 14:12:04.000000000 +0100
@@ -1202,6 +1202,7 @@
u8 ap[ETH_ALEN]; /* The AP we want, FF:FF:FF:FF:FF:FF is any */
u16 aid; /* The Association ID sent from the AP / last used AID if we're an AP */
u16 mode; /* mode from iwconfig */
+ int monitor_type; /* ARPHRD_IEEE80211 or ARPHRD_IEEE80211_PRISM */
u16 status; /* 802.11 association status */
u8 essid_active; /* specific ESSID active, or select any? */
u8 essid_len; /* to avoid dozens of strlen() */
@@ -1623,7 +1624,7 @@
#define PS_OPT_TX_PSPOLL 0x02 /* send PSPoll frame to fetch waiting frames from AP (on frame with matching AID) */
#define PS_OPT_STILL_RCV_BCASTS 0x01
-typedef struct acx100_ie_powermgmt {
+typedef struct acx100_ie_powersave {
u16 type ACX_PACKED;
u16 len ACX_PACKED;
u8 wakeup_cfg ACX_PACKED;
@@ -1631,9 +1632,9 @@
u8 options ACX_PACKED;
u8 hangover_period ACX_PACKED; /* remaining wake time after Tx MPDU w/ PS bit, in values of 1/1024 seconds */
u16 enhanced_ps_transition_time ACX_PACKED; /* rem. wake time for Enh. PS */
-} acx100_ie_powermgmt_t;
+} acx100_ie_powersave_t;
-typedef struct acx111_ie_powermgmt {
+typedef struct acx111_ie_powersave {
u16 type ACX_PACKED;
u16 len ACX_PACKED;
u8 wakeup_cfg ACX_PACKED;
@@ -1642,7 +1643,7 @@
u8 hangover_period ACX_PACKED; /* remaining wake time after Tx MPDU w/ PS bit, in values of 1/1024 seconds */
u32 beacon_rx_time ACX_PACKED;
u32 enhanced_ps_transition_time ACX_PACKED; /* rem. wake time for Enh. PS */
-} acx111_ie_powermgmt_t;
+} acx111_ie_powersave_t;
/***********************************************************************
diff -urN acx-20060116.orig/common.c acx-20060116_misc/common.c
--- acx-20060116.orig/common.c 2006-01-15 12:38:43.000000000 +0100
+++ acx-20060116_misc/common.c 2006-01-16 14:22:02.000000000 +0100
@@ -183,7 +183,7 @@
diff -= adev->lock_time;
if (diff > max_lock_time) {
where = sanitize_str(where);
- printk("max lock hold time %d CPU ticks from %s "
+ printk("max lock hold time %ld CPU ticks from %s "
"to %s\n", diff, adev->last_lock, where);
max_lock_time = diff;
}
@@ -230,7 +230,7 @@
unsigned long diff = jiffies - adev->sem_time;
if (diff > max_sem_time) {
where = sanitize_str(where);
- printk("max sem hold time %d jiffies from %s "
+ printk("max sem hold time %ld jiffies from %s "
"to %s\n", diff, adev->last_sem, where);
max_sem_time = diff;
}
@@ -838,7 +838,7 @@
acx100_ie_len[] = {
0,
ACX100_IE_ACX_TIMER_LEN,
- sizeof(acx100_ie_powermgmt_t)-4, /* is that 6 or 8??? */
+ sizeof(acx100_ie_powersave_t)-4, /* is that 6 or 8??? */
ACX1xx_IE_QUEUE_CONFIG_LEN,
ACX100_IE_BLOCK_SIZE_LEN,
ACX1xx_IE_MEMORY_CONFIG_OPTIONS_LEN,
@@ -889,7 +889,7 @@
acx111_ie_len[] = {
0,
ACX100_IE_ACX_TIMER_LEN,
- sizeof(acx111_ie_powermgmt_t)-4,
+ sizeof(acx111_ie_powersave_t)-4,
ACX1xx_IE_QUEUE_CONFIG_LEN,
ACX100_IE_BLOCK_SIZE_LEN,
ACX1xx_IE_MEMORY_CONFIG_OPTIONS_LEN,
@@ -2156,6 +2156,7 @@
adev->listen_interval = 100;
adev->beacon_interval = DEFAULT_BEACON_INTERVAL;
adev->mode = ACX_MODE_2_STA;
+ adev->monitor_type = ARPHRD_IEEE80211_PRISM;
adev->dtim_interval = DEFAULT_DTIM_INTERVAL;
adev->msdu_lifetime = DEFAULT_MSDU_LIFETIME;
@@ -2347,10 +2348,11 @@
skb_put(skb, skb_len);
+ if (adev->ndev->type == ARPHRD_IEEE80211) {
/* when in raw 802.11 mode, just copy frame as-is */
- if (adev->ndev->type == ARPHRD_IEEE80211)
datap = skb->data;
- else { /* otherwise, emulate prism header */
+ } else if (adev->ndev->type == ARPHRD_IEEE80211_PRISM) {
+ /* emulate prism header */
msg = (wlansniffrm_t*)skb->data;
datap = msg + 1;
@@ -2410,8 +2412,20 @@
msg->frmlen.status = WLANITEM_STATUS_data_ok;
msg->frmlen.len = 4;
msg->frmlen.data = skb_len;
+ } else {
+ printk(KERN_ERR "unsupported netdev type %d!\n",
+ adev->ndev->type);
+ dev_kfree_skb(skb);
+ return;
}
+ /* sanity check (keep it here) */
+ if (unlikely((int)skb_len < 0))
+ {
+ printk(KERN_ERR "skb_len bug (%d)!! Aborting...\n", (int)skb_len);
+ dev_kfree_skb(skb);
+ return;
+ }
memcpy(datap, ((unsigned char*)rxbuf)+payload_offset, skb_len);
skb->dev = adev->ndev;
@@ -2425,6 +2439,7 @@
adev->stats.rx_packets++;
adev->stats.rx_bytes += skb->len;
+
end:
FN_EXIT0;
}
@@ -5816,8 +5831,8 @@
{
/* merge both structs in a union to be able to have common code */
union {
- acx111_ie_powermgmt_t acx111;
- acx100_ie_powermgmt_t acx100;
+ acx111_ie_powersave_t acx111;
+ acx100_ie_powersave_t acx100;
} pm;
/* change 802.11 power save mode settings */
@@ -6246,7 +6261,8 @@
}
if (adev->set_mask & GETSET_MODE) {
- adev->ndev->type = ARPHRD_ETHER;
+ adev->ndev->type = (adev->mode == ACX_MODE_MONITOR) ?
+ adev->monitor_type : ARPHRD_ETHER;
switch (adev->mode) {
case ACX_MODE_3_AP:
@@ -6265,9 +6281,6 @@
acx_s_cmd_join_bssid(adev, adev->bssid);
break;
case ACX_MODE_MONITOR:
- /* adev->ndev->type = ARPHRD_ETHER; */
- /* adev->ndev->type = ARPHRD_IEEE80211; */
- adev->ndev->type = ARPHRD_IEEE80211_PRISM;
acx111_s_feature_on(adev, 0, FEATURE2_NO_TXCRYPT|FEATURE2_SNIFFER);
/* this stops beacons */
acx_s_cmd_join_bssid(adev, adev->bssid);
diff -urN acx-20060116.orig/ioctl.c acx-20060116_misc/ioctl.c
--- acx-20060116.orig/ioctl.c 2006-01-15 12:02:26.000000000 +0100
+++ acx-20060116_misc/ioctl.c 2006-01-16 14:21:46.000000000 +0100
@@ -2078,13 +2078,14 @@
switch (params[0]) {
case 0:
- adev->ndev->type = ARPHRD_ETHER;
+ /* no monitor mode. hmm, should we simply ignore it
+ * or go back to enabling adev->netdev->type ARPHRD_ETHER? */
break;
case 1:
- adev->ndev->type = ARPHRD_IEEE80211_PRISM;
+ adev->monitor_type = ARPHRD_IEEE80211_PRISM;
break;
case 2:
- adev->ndev->type = ARPHRD_IEEE80211;
+ adev->monitor_type = ARPHRD_IEEE80211;
break;
}
diff -urN acx-20060116.orig/pci.c acx-20060116_misc/pci.c
--- acx-20060116.orig/pci.c 2006-01-15 12:01:41.000000000 +0100
+++ acx-20060116_misc/pci.c 2006-01-16 14:21:13.000000000 +0100
@@ -33,6 +33,7 @@
#include <linux/config.h>
#include <linux/version.h>
+#include <linux/compiler.h> /* required for Lx 2.6.8 ?? */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
@@ -354,8 +355,9 @@
write_flush(adev);
write_reg32(adev, IO_ACX_EEPROM_CTL, 1);
+ count = 0xffff;
while (read_reg16(adev, IO_ACX_EEPROM_CTL)) {
- if (unlikely(++count > 0xffff)) {
+ if (unlikely(!--count)) {
printk("WARNING, DANGER!!! "
"Timeout waiting for EEPROM write\n");
goto end;
@@ -369,13 +371,13 @@
write_flush(adev);
/* now start a verification run */
- count = 0xffff;
for (i = 0; i < len; i++) {
write_reg32(adev, IO_ACX_EEPROM_CFG, 0);
write_reg32(adev, IO_ACX_EEPROM_ADDR, addr + i);
write_flush(adev);
write_reg32(adev, IO_ACX_EEPROM_CTL, 2);
+ count = 0xffff;
while (read_reg16(adev, IO_ACX_EEPROM_CTL)) {
if (unlikely(!--count)) {
printk("timeout waiting for EEPROM read\n");
@@ -747,18 +749,17 @@
temp = read_reg16(adev, IO_ACX_ECPU_CTRL) | 0x1;
write_reg16(adev, IO_ACX_ECPU_CTRL, temp);
- /* now do soft reset of eCPU */
+ /* now do soft reset of eCPU, set bit */
temp = read_reg16(adev, IO_ACX_SOFT_RESET) | 0x1;
log(L_DEBUG, "%s: enable soft reset...\n", __func__);
write_reg16(adev, IO_ACX_SOFT_RESET, temp);
write_flush(adev);
- /* now reset bit again */
+ /* now clear bit again: deassert eCPU reset */
log(L_DEBUG, "%s: disable soft reset and go to init mode...\n", __func__);
- /* deassert eCPU reset */
write_reg16(adev, IO_ACX_SOFT_RESET, temp & ~0x1);
- /* now start a burst read from initial flash EEPROM */
+ /* now start a burst read from initial EEPROM */
temp = read_reg16(adev, IO_ACX_EE_START) | 0x1;
write_reg16(adev, IO_ACX_EE_START, temp);
write_flush(adev);
@@ -893,6 +894,7 @@
int result = NOT_OK;
u16 hardware_info;
u16 ecpu_ctrl;
+ int count;
FN_ENTER;
@@ -927,12 +929,24 @@
acx_unlock(adev, flags);
- /* without this delay acx100 may fail to report hardware_info
- ** (see below). Most probably eCPU runs some init code */
- acx_s_msleep(10);
-
/* need to know radio type before fw load */
- hardware_info = read_reg16(adev, IO_ACX_EEPROM_INFORMATION);
+ /* Need to wait for arrival of this information in a loop,
+ * most probably since eCPU runs some init code from EEPROM
+ * (started burst read in reset_mac()) which also
+ * sets the radio type ID */
+
+ count = 0xffff;
+ do {
+ hardware_info = read_reg16(adev, IO_ACX_EEPROM_INFORMATION);
+ if (!--count)
+ {
+ msg = "eCPU didn't indicate radio type";
+ goto end_fail;
+ }
+ cpu_relax();
+ } while (!(hardware_info & 0xff00)); /* radio type still zero? */
+
+ /* printk("DEBUG: count %d\n", count); */
adev->form_factor = hardware_info & 0xff;
adev->radio_type = hardware_info >> 8;
@@ -940,11 +954,11 @@
if (OK != acxpci_s_upload_fw(adev))
goto end_fail;
- acx_s_msleep(10);
+ /* acx_s_msleep(10); this one really shouldn't be required */
/* now start eCPU by clearing bit */
- log(L_DEBUG, "booted eCPU up and waiting for completion...\n");
write_reg16(adev, IO_ACX_ECPU_CTRL, ecpu_ctrl & ~0x1);
+ log(L_DEBUG, "booted eCPU up and waiting for completion...\n");
/* wait for eCPU bootup */
if (OK != acxpci_s_verify_init(adev)) {
[-- Attachment #3: acx-20060116_KERN_xxx.diff.gz --]
[-- Type: application/x-gzip, Size: 18122 bytes --]
next reply other threads:[~2006-01-16 14:02 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-01-16 14:02 Andreas Mohr [this message]
2006-01-16 14:34 ` [PATCH] WLAN acx100: OOPS fix, KERN_xxx, misc Denis Vlasenko
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20060116140233.GA8170@rhlx01.fht-esslingen.de \
--to=andim2@users.sourceforge.net \
--cc=acx100-devel@lists.sourceforge.net \
--cc=netdev@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).