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
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: acx-20060116_KERN_xxx.diff.gz
Description: GNU Zip compressed data

Reply via email to