Hi all,

this patch does:
- implement much more flexible firmware statistics parsing
  (for /proc/driver/acx_wlanX_diag)
  This has the nice effect that we now get output for both the older
  TNETW1100 USB and TNETW1450.
  Since firmware statistics information has non-stable layout depending on
  firmware version, please report if you suspect any parsing mismatch!
  This improved version now uses 2kB more driver space, unfortunately.
- use "% 8" modulo instead of more complicated "% 5" calculation
- use
    if (++idx >= count)
      idx = 0;
  instead of more bloaty
    idx = (idx + 1) % count;
  We might want to add a kernel macro for this *very* common and
  performance-critical driver operation, say ring_advance_next or so,
  in order to have the most optimized version for each architecture;
  Or ($1 million question): Is there already such a beast somewhere!?
- tiny cleanup

Andreas Mohr

diff -urN acx-20060202/acx_func.h acx-20060202_stats/acx_func.h
--- acx-20060202/acx_func.h     2006-02-01 10:49:31.000000000 +0100
+++ acx-20060202_stats/acx_func.h       2006-02-05 06:21:35.000000000 +0100
@@ -257,7 +257,7 @@
 **             but may be run under lock
 **
 ** A small number of local helpers do not have acx_[eisl]_ prefix.
-** They are always close to caller and are to be revieved locally.
+** They are always close to caller and are to be reviewed locally.
 **
 ** Theory of operation:
 **
diff -urN acx-20060202/acx_struct.h acx-20060202_stats/acx_struct.h
--- acx-20060202/acx_struct.h   2006-02-01 10:49:38.000000000 +0100
+++ acx-20060202_stats/acx_struct.h     2006-02-03 23:21:35.000000000 +0100
@@ -582,21 +582,34 @@
 
 
 /*--- Firmware statistics 
----------------------------------------------------*/
-typedef struct fw_stats {
-       u32     val0x0 ACX_PACKED;              /* hdr; */
+
+/* define a random 100 bytes more to catch firmware versions which
+ * provide a bigger struct */
+#define FW_STATS_FUTURE_EXTENSION      100
+
+typedef struct fw_stats_tx {
        u32     tx_desc_of ACX_PACKED;
+} fw_stats_tx_t;
+
+typedef struct fw_stats_rx {
        u32     rx_oom ACX_PACKED;
        u32     rx_hdr_of ACX_PACKED;
-       u32     rx_hdr_use_next ACX_PACKED;
+       u32     rx_hw_stuck ACX_PACKED; /* old: u32     rx_hdr_use_next */
        u32     rx_dropped_frame ACX_PACKED;
        u32     rx_frame_ptr_err ACX_PACKED;
        u32     rx_xfr_hint_trig ACX_PACKED;
+       u32     rx_aci_events ACX_PACKED; /* later versions only */
+       u32     rx_aci_resets ACX_PACKED; /* later versions only */
+} fw_stats_rx_t;
 
+typedef struct fw_stats_dma {
        u32     rx_dma_req ACX_PACKED;
        u32     rx_dma_err ACX_PACKED;
        u32     tx_dma_req ACX_PACKED;
        u32     tx_dma_err ACX_PACKED;
+} fw_stats_dma_t;
 
+typedef struct fw_stats_irq {
        u32     cmd_cplt ACX_PACKED;
        u32     fiq ACX_PACKED;
        u32     rx_hdrs ACX_PACKED;
@@ -604,23 +617,78 @@
        u32     rx_mem_of ACX_PACKED;
        u32     rx_rdys ACX_PACKED;
        u32     irqs ACX_PACKED;
-       u32     acx_trans_procs ACX_PACKED;
+       u32     tx_procs ACX_PACKED;
        u32     decrypt_done ACX_PACKED;
        u32     dma_0_done ACX_PACKED;
        u32     dma_1_done ACX_PACKED;
        u32     tx_exch_complet ACX_PACKED;
        u32     commands ACX_PACKED;
-       u32     acx_rx_procs ACX_PACKED;
+       u32     rx_procs ACX_PACKED;
        u32     hw_pm_mode_changes ACX_PACKED;
        u32     host_acks ACX_PACKED;
        u32     pci_pm ACX_PACKED;
        u32     acm_wakeups ACX_PACKED;
+} fw_stats_irq_t;
 
+typedef struct fw_stats_wep {
        u32     wep_key_count ACX_PACKED;
        u32     wep_default_key_count ACX_PACKED;
        u32     dot11_def_key_mib ACX_PACKED;
        u32     wep_key_not_found ACX_PACKED;
        u32     wep_decrypt_fail ACX_PACKED;
+       u32     wep_pkt_decrypt ACX_PACKED;
+       u32     wep_decrypt_irqs ACX_PACKED;
+} fw_stats_wep_t;
+
+typedef struct fw_stats_pwr {
+       u32     tx_start_ctr ACX_PACKED;
+       u32     no_ps_tx_too_short ACX_PACKED;
+       u32     rx_start_ctr ACX_PACKED;
+       u32     no_ps_rx_too_short ACX_PACKED;
+       u32     lppd_started ACX_PACKED;
+       u32     no_lppd_too_noisy ACX_PACKED;
+       u32     no_lppd_too_short ACX_PACKED;
+       u32     no_lppd_matching_frame ACX_PACKED;
+} fw_stats_pwr_t;
+
+typedef struct fw_stats_mic {
+       u32 mic_rx_pkts ACX_PACKED;
+       u32 mic_calc_fail ACX_PACKED;
+} fw_stats_mic_t;
+
+typedef struct fw_stats_aes {
+       u32 aes_enc_fail ACX_PACKED;
+       u32 aes_dec_fail ACX_PACKED;
+       u32 aes_enc_pkts ACX_PACKED;
+       u32 aes_dec_pkts ACX_PACKED;
+       u32 aes_enc_irq ACX_PACKED;
+       u32 aes_dec_irq ACX_PACKED;
+} fw_stats_aes_t;
+
+typedef struct fw_stats_event {
+       u32 heartbeat ACX_PACKED;
+       u32 calibration ACX_PACKED;
+       u32 rx_mismatch ACX_PACKED;
+       u32 rx_mem_empty ACX_PACKED;
+       u32 rx_pool ACX_PACKED;
+       u32 oom_late ACX_PACKED;
+       u32 phy_tx_err ACX_PACKED;
+       u32 tx_stuck ACX_PACKED;
+} fw_stats_event_t;
+
+/* mainly for size calculation only */
+typedef struct fw_stats {
+       u16                     type;
+       u16                     len;
+       fw_stats_tx_t           tx;
+       fw_stats_rx_t           rx;
+       fw_stats_dma_t          dma;
+       fw_stats_irq_t          irq;
+       fw_stats_wep_t          wep;
+       fw_stats_pwr_t          pwr;
+       fw_stats_mic_t          mic;
+       fw_stats_aes_t          aes;
+       fw_stats_event_t        evt;
 } fw_stats_t;
 
 /* Firmware version struct */
diff -urN acx-20060202/common.c acx-20060202_stats/common.c
--- acx-20060202/common.c       2006-02-01 10:49:37.000000000 +0100
+++ acx-20060202_stats/common.c 2006-02-05 06:23:21.000000000 +0100
@@ -851,7 +851,7 @@
        ACX1xx_IE_RXCONFIG_LEN,
        0,
        0,
-       ACX1xx_IE_FIRMWARE_STATISTICS_LEN,
+       sizeof(fw_stats_t)-4+FW_STATS_FUTURE_EXTENSION,
        0,
        ACX1xx_IE_FEATURE_CONFIG_LEN,
        ACX111_IE_KEY_CHOOSE_LEN,
@@ -928,7 +928,7 @@
        ACX1xx_IE_RXCONFIG_LEN,
        0,
        0,
-       ACX1xx_IE_FIRMWARE_STATISTICS_LEN,
+       sizeof(fw_stats_t)-4+FW_STATS_FUTURE_EXTENSION,
        0,
        ACX1xx_IE_FEATURE_CONFIG_LEN,
        ACX111_IE_KEY_CHOOSE_LEN,
@@ -1148,20 +1148,27 @@
 acx_s_proc_diag_output(char *buf, acx_device_t *adev)
 {
        char *p = buf;
-       fw_stats_t *fw_stats;
        unsigned long flags;
+       unsigned int len = 0, partlen;
+       u32 temp1, temp2;
+       u8 *st, *st_end;
+#ifdef __BIG_ENDIAN
+       u8 *st2;
+#endif
+       fw_stats_t *fw_stats;
+       char *part_str = NULL;
+       fw_stats_tx_t *tx = NULL;
+       fw_stats_rx_t *rx = NULL;
+       fw_stats_dma_t *dma = NULL;
+       fw_stats_irq_t *irq = NULL;
+       fw_stats_wep_t *wep = NULL;
+       fw_stats_pwr_t *pwr = NULL;
+       fw_stats_mic_t *mic = NULL;
+       fw_stats_aes_t *aes = NULL;
+       fw_stats_event_t *evt = NULL;
 
        FN_ENTER;
 
-       /* TODO: may replace kmalloc/memset with kzalloc once
-        * Linux 2.6.14 is widespread */
-       fw_stats = kmalloc(sizeof(*fw_stats), GFP_KERNEL);
-       if (!fw_stats) {
-               FN_EXIT1(0);
-               return 0;
-       }
-       memset(fw_stats, 0, sizeof(*fw_stats));
-
        acx_lock(adev, flags);
 
        if (IS_PCI(adev))
@@ -1205,63 +1212,322 @@
 
        acx_unlock(adev, flags);
 
-       if (OK != acx_s_interrogate(adev, fw_stats, 
ACX1xx_IE_FIRMWARE_STATISTICS))
-               p += sprintf(p,
-                       "\n"
-                       "** Firmware **\n"
-                       "QUERY FAILED!!\n");
-       else {
-               p += sprintf(p,
-                       "\n"
-                       "** Firmware **\n"
-                       "version \"%s\"\n"
-                       "tx_desc_overfl %u, rx_OutOfMem %u, rx_hdr_overfl %u, 
rx_hdr_use_next %u\n"
-                       "rx_dropped_frame %u, rx_frame_ptr_err %u, 
rx_xfr_hint_trig %u, rx_dma_req %u\n"
-                       "rx_dma_err %u, tx_dma_req %u, tx_dma_err %u, cmd_cplt 
%u, fiq %u\n"
-                       "rx_hdrs %u, rx_cmplt %u, rx_mem_overfl %u, rx_rdys %u, 
irqs %u\n"
-                       "acx_trans_procs %u, decrypt_done %u, dma_0_done %u, 
dma_1_done %u\n",
-                       adev->firmware_version,
-                       le32_to_cpu(fw_stats->tx_desc_of),
-                       le32_to_cpu(fw_stats->rx_oom),
-                       le32_to_cpu(fw_stats->rx_hdr_of),
-                       le32_to_cpu(fw_stats->rx_hdr_use_next),
-                       le32_to_cpu(fw_stats->rx_dropped_frame),
-                       le32_to_cpu(fw_stats->rx_frame_ptr_err),
-                       le32_to_cpu(fw_stats->rx_xfr_hint_trig),
-                       le32_to_cpu(fw_stats->rx_dma_req),
-                       le32_to_cpu(fw_stats->rx_dma_err),
-                       le32_to_cpu(fw_stats->tx_dma_req),
-                       le32_to_cpu(fw_stats->tx_dma_err),
-                       le32_to_cpu(fw_stats->cmd_cplt),
-                       le32_to_cpu(fw_stats->fiq),
-                       le32_to_cpu(fw_stats->rx_hdrs),
-                       le32_to_cpu(fw_stats->rx_cmplt),
-                       le32_to_cpu(fw_stats->rx_mem_of),
-                       le32_to_cpu(fw_stats->rx_rdys),
-                       le32_to_cpu(fw_stats->irqs),
-                       le32_to_cpu(fw_stats->acx_trans_procs),
-                       le32_to_cpu(fw_stats->decrypt_done),
-                       le32_to_cpu(fw_stats->dma_0_done),
-                       le32_to_cpu(fw_stats->dma_1_done));
+       p += sprintf(p,
+               "\n"
+               "** Firmware **\n"
+               "NOTE: version dependent statistics layout, "
+               "please report if you suspect wrong parsing!\n"
+               "\n"
+               "version \"%s\"\n", adev->firmware_version);
+
+       /* TODO: may replace kmalloc/memset with kzalloc once
+        * Linux 2.6.14 is widespread */
+       fw_stats = kmalloc(sizeof(*fw_stats)+FW_STATS_FUTURE_EXTENSION, 
GFP_KERNEL);
+       if (!fw_stats) {
+               FN_EXIT1(0);
+               return 0;
+       }
+       memset(fw_stats, 0, sizeof(*fw_stats)+FW_STATS_FUTURE_EXTENSION);
+
+       st = (u8 *)fw_stats;
+
+       part_str = "statistics query command";
+
+       if (OK != acx_s_interrogate(adev, st, ACX1xx_IE_FIRMWARE_STATISTICS))
+               goto fw_stats_end;
+
+       st += sizeof(u16);
+       len = *(u16 *)st;
+
+       if (len > sizeof(*fw_stats)) {
                p += sprintf(p,
-                       "tx_exch_complet %u, commands %u, acx_rx_procs %u\n"
-                       "hw_pm_mode_changes %u, host_acks %u, pci_pm %u, 
acm_wakeups %u\n"
-                       "wep_key_count %u, wep_default_key_count %u, 
dot11_def_key_mib %u\n"
-                       "wep_key_not_found %u, wep_decrypt_fail %u\n",
-                       le32_to_cpu(fw_stats->tx_exch_complet),
-                       le32_to_cpu(fw_stats->commands),
-                       le32_to_cpu(fw_stats->acx_rx_procs),
-                       le32_to_cpu(fw_stats->hw_pm_mode_changes),
-                       le32_to_cpu(fw_stats->host_acks),
-                       le32_to_cpu(fw_stats->pci_pm),
-                       le32_to_cpu(fw_stats->acm_wakeups),
-                       le32_to_cpu(fw_stats->wep_key_count),
-                       le32_to_cpu(fw_stats->wep_default_key_count),
-                       le32_to_cpu(fw_stats->dot11_def_key_mib),
-                       le32_to_cpu(fw_stats->wep_key_not_found),
-                       le32_to_cpu(fw_stats->wep_decrypt_fail));
+                       "firmware version with bigger fw_stats struct 
detected\n"
+                       "(%u vs. %u), PLEASE REPORT!!\n", len, 
sizeof(fw_stats_t));
+               if (len > sizeof(*fw_stats)+FW_STATS_FUTURE_EXTENSION) {
+                       p += sprintf(p, "struct size exceeded allocation!\n");
+                       len = sizeof(*fw_stats)+FW_STATS_FUTURE_EXTENSION;
+               }
+       }
+       st += sizeof(u16);
+       st_end = st - 2*sizeof(u16) + len;
+
+#ifdef __BIG_ENDIAN
+       /* let's make one bold assumption here:
+        * (hopefully!) *all* statistics fields are u32 only,
+        * thus if we need to make endianness corrections
+        * we can simply do them in one go, in advance */
+       st2 = (u8 *)fw_stats;
+       for (temp1 = 0; temp1 < len; temp1 += 4, st2 += 4)
+               *(u32 *)st2 = le32_to_cpu(*(u32 *)st2);
+#endif
+
+       part_str = "Rx/Tx";
+
+       /* directly at end of a struct part? --> no error! */
+       if (st == st_end)
+               goto fw_stats_end;
+
+       tx = (fw_stats_tx_t *)st;
+       st += sizeof(fw_stats_tx_t);
+       rx = (fw_stats_rx_t *)st;
+       st += sizeof(fw_stats_rx_t);
+       partlen = sizeof(fw_stats_tx_t) + sizeof(fw_stats_rx_t);
+
+       if (
+           (IS_PCI(adev) && IS_ACX100(adev))
+       ||  (IS_USB(adev) && IS_ACX100(adev))
+       ) {
+               /* at least ACX100 PCI F/W 1.9.8.b
+                * and ACX100 USB F/W 1.0.7-USB
+                * don't have those two fields... */
+               st -= 2*sizeof(u32);
+
+               /* our parsing doesn't quite match this firmware yet,
+                * log failure */
+               if (st > st_end)
+                       goto fw_stats_fail;
+               temp1 = temp2 = 999999999;
+       } else {
+               if (st > st_end)
+                       goto fw_stats_fail;
+               temp1 = rx->rx_aci_events;
+               temp2 = rx->rx_aci_resets;
        }
 
+       p += sprintf(p,
+               "%s:\n"
+               "  tx_desc_overfl %u\n"
+               "  rx_OutOfMem %u, rx_hdr_overfl %u, rx_hw_stuck %u\n"
+               "  rx_dropped_frame %u, rx_frame_ptr_err %u, rx_xfr_hint_trig 
%u\n"
+               "  rx_aci_events %u, rx_aci_resets %u\n",
+               part_str,
+               tx->tx_desc_of,
+               rx->rx_oom,
+               rx->rx_hdr_of,
+               rx->rx_hw_stuck,
+               rx->rx_dropped_frame,
+               rx->rx_frame_ptr_err,
+               rx->rx_xfr_hint_trig,
+               temp1,
+               temp2);
+
+       part_str = "DMA";
+
+       if (st == st_end)
+               goto fw_stats_end;
+
+       dma = (fw_stats_dma_t *)st;
+       partlen = sizeof(fw_stats_dma_t);
+       st += partlen;
+
+       if (st > st_end)
+               goto fw_stats_fail;
+
+       p += sprintf(p,
+               "%s:\n"
+               "  rx_dma_req %u, rx_dma_err %u, tx_dma_req %u, tx_dma_err 
%u\n",
+               part_str,
+               dma->rx_dma_req,
+               dma->rx_dma_err,
+               dma->tx_dma_req,
+               dma->tx_dma_err);
+
+       part_str = "IRQ";
+
+       if (st == st_end)
+               goto fw_stats_end;
+
+       irq = (fw_stats_irq_t *)st;
+       partlen = sizeof(fw_stats_irq_t);
+       st += partlen;
+       
+       if (st > st_end)
+               goto fw_stats_fail;
+
+       p += sprintf(p,
+               "%s:\n"
+               "  cmd_cplt %u, fiq %u\n"
+               "  rx_hdrs %u, rx_cmplt %u, rx_mem_overfl %u, rx_rdys %u\n"
+               "  irqs %u, tx_procs %u, decrypt_done %u\n"
+               "  dma_0_done %u, dma_1_done %u, tx_exch_complet %u\n"
+               "  commands %u, rx_procs %u, hw_pm_mode_changes %u\n"
+               "  host_acks %u, pci_pm %u, acm_wakeups %u\n",
+               part_str,
+               irq->cmd_cplt,
+               irq->fiq,
+               irq->rx_hdrs,
+               irq->rx_cmplt,
+               irq->rx_mem_of,
+               irq->rx_rdys,
+               irq->irqs,
+               irq->tx_procs,
+               irq->decrypt_done,
+               irq->dma_0_done,
+               irq->dma_1_done,
+               irq->tx_exch_complet,
+               irq->commands,
+               irq->rx_procs,
+               irq->hw_pm_mode_changes,
+               irq->host_acks,
+               irq->pci_pm,
+               irq->acm_wakeups);
+
+       part_str = "WEP";
+
+       if (st == st_end)
+               goto fw_stats_end;
+
+       wep = (fw_stats_wep_t *)st;
+       partlen = sizeof(fw_stats_wep_t);
+       st += partlen;
+       
+       if (
+           (IS_PCI(adev) && IS_ACX100(adev))
+       ||  (IS_USB(adev) && IS_ACX100(adev))
+       ) {
+               /* at least ACX100 PCI F/W 1.9.8.b
+                * and ACX100 USB F/W 1.0.7-USB
+                * don't have those two fields... */
+               st -= 2*sizeof(u32);
+               if (st > st_end)
+                       goto fw_stats_fail;
+               temp1 = temp2 = 999999999;
+       } else {
+               if (st > st_end)
+                       goto fw_stats_fail;
+               temp1 = wep->wep_pkt_decrypt;
+               temp2 = wep->wep_decrypt_irqs;
+       }
+
+       p += sprintf(p,
+               "%s:\n"
+               "  wep_key_count %u, wep_default_key_count %u, 
dot11_def_key_mib %u\n"
+               "  wep_key_not_found %u, wep_decrypt_fail %u\n"
+               "  wep_pkt_decrypt %u, wep_decrypt_irqs %u\n",
+               part_str,
+               wep->wep_key_count,
+               wep->wep_default_key_count,
+               wep->dot11_def_key_mib,
+               wep->wep_key_not_found,
+               wep->wep_decrypt_fail,
+               temp1,
+               temp2);
+
+       part_str = "power";
+       
+       if (st == st_end)
+               goto fw_stats_end;
+
+       pwr = (fw_stats_pwr_t *)st;
+       partlen = sizeof(fw_stats_pwr_t);
+       st += partlen;
+
+       if (st > st_end)
+               goto fw_stats_fail;
+
+       p += sprintf(p,
+               "%s:\n"
+               "  tx_start_ctr %u, no_ps_tx_too_short %u\n"
+               "  rx_start_ctr %u, no_ps_rx_too_short %u\n"
+               "  lppd_started %u\n"
+               "  no_lppd_too_noisy %u, no_lppd_too_short %u, 
no_lppd_matching_frame %u\n",
+               part_str,
+               pwr->tx_start_ctr,
+               pwr->no_ps_tx_too_short,
+               pwr->rx_start_ctr,
+               pwr->no_ps_rx_too_short,
+               pwr->lppd_started,
+               pwr->no_lppd_too_noisy,
+               pwr->no_lppd_too_short,
+               pwr->no_lppd_matching_frame);
+
+       part_str = "MIC";
+       
+       if (st == st_end)
+               goto fw_stats_end;
+
+       mic = (fw_stats_mic_t *)st;
+       partlen = sizeof(fw_stats_mic_t);
+       st += partlen;
+
+       if (st > st_end)
+               goto fw_stats_fail;
+
+       p += sprintf(p,
+               "%s:\n"
+               "  mic_rx_pkts %u, mic_calc_fail %u\n",
+               part_str,
+               mic->mic_rx_pkts,
+               mic->mic_calc_fail);
+       
+       part_str = "AES";
+       
+       if (st == st_end)
+               goto fw_stats_end;
+
+       aes = (fw_stats_aes_t *)st;
+       partlen = sizeof(fw_stats_aes_t);
+       st += partlen;
+
+       if (st > st_end)
+               goto fw_stats_fail;
+
+       p += sprintf(p,
+               "%s:\n"
+               "  aes_enc_fail %u, aes_dec_fail %u\n"
+               "  aes_enc_pkts %u, aes_dec_pkts %u\n"
+               "  aes_enc_irq %u, aes_dec_irq %u\n",
+               part_str,
+               aes->aes_enc_fail,
+               aes->aes_dec_fail,
+               aes->aes_enc_pkts,
+               aes->aes_dec_pkts,
+               aes->aes_enc_irq,
+               aes->aes_dec_irq);
+
+       part_str = "event";
+       
+       if (st == st_end)
+               goto fw_stats_end;
+
+       evt = (fw_stats_event_t *)st;
+       partlen = sizeof(fw_stats_event_t);
+       st += partlen;
+
+       if (st > st_end)
+               goto fw_stats_fail;
+
+       p += sprintf(p,
+               "%s:\n"
+               "  heartbeat %u, calibration %u\n"
+               "  rx_mismatch %u, rx_mem_empty %u, rx_pool %u\n"
+               "  oom_late %u\n"
+               "  phy_tx_err %u, tx_stuck %u\n",
+               part_str,
+               evt->heartbeat,
+               evt->calibration,
+               evt->rx_mismatch,
+               evt->rx_mem_empty,
+               evt->rx_pool,
+               evt->oom_late,
+               evt->phy_tx_err,
+               evt->tx_stuck);
+
+       if (st < st_end)
+               goto fw_stats_bigger;
+
+       goto fw_stats_end;
+
+fw_stats_fail:
+       st -= partlen;
+       p += sprintf(p,
+               "failed at %s part (size %u), offset %u (struct size %u), 
PLEASE REPORT!\n", part_str, partlen, (int)st - (int)fw_stats, len);
+fw_stats_bigger:
+       for (; st < st_end; st += 4)
+               p += sprintf(p,
+                       "UNKN%3d: %u\n", (int)st - (int)fw_stats, *(u32 *)st);
+       
+fw_stats_end:
        kfree(fw_stats);
 
        FN_EXIT1(p - buf);
diff -urN acx-20060202/pci.c acx-20060202_stats/pci.c
--- acx-20060202/pci.c  2006-02-01 10:49:33.000000000 +0100
+++ acx-20060202_stats/pci.c    2006-02-04 19:30:29.000000000 +0100
@@ -1058,13 +1058,13 @@
                /* Test for IDLE state */
                if (!cmd_status)
                        break;
-               if (counter % 5 == 0) {
+               if (counter % 8 == 0) {
                        if (time_after(jiffies, timeout)) {
                                counter = 0;
                                break;
                        }
-                       /* we waited 5 iterations, no luck. Sleep 5 ms */
-                       acx_s_msleep(5);
+                       /* we waited 8 iterations, no luck. Sleep 8 ms */
+                       acx_s_msleep(8);
                }
        } while (likely(--counter));
 
@@ -1124,13 +1124,13 @@
                                break;
                }
 
-               if (counter % 5 == 0) {
+               if (counter % 8 == 0) {
                        if (time_after(jiffies, timeout)) {
                                counter = 0;
                                break;
                        }
-                       /* we waited 5 iterations, no luck. Sleep 5 ms */
-                       acx_s_msleep(5);
+                       /* we waited 8 iterations, no luck. Sleep 8 ms */
+                       acx_s_msleep(8);
                }
        } while (likely(--counter));
 
@@ -2307,7 +2307,9 @@
        while (1) {
                hostdesc = &adev->rxhostdesc_start[tail];
                /* advance tail regardless of outcome of the below test */
-               tail = (tail + 1) % RX_CNT;
+               /* smaller/less writes than: tail = (tail + 1) % RX_CNT; */
+               if (++tail >= RX_CNT)
+                       tail = 0;
 
                if ((hostdesc->Ctl_16 & cpu_to_le16(DESC_CTL_HOSTOWN))
                 && (hostdesc->Status & cpu_to_le32(DESC_STATUS_FULL)))
@@ -2338,7 +2340,9 @@
                 || !(hostdesc->Status & cpu_to_le32(DESC_STATUS_FULL)))
                        break;
 
-               tail = (tail + 1) % RX_CNT;
+               /* slower: tail = (tail + 1) % RX_CNT; */
+               if (++tail >= RX_CNT)
+                       tail = 0;
        }
 end:
        adev->rx_tail = tail;
@@ -3065,7 +3069,10 @@
        }
 
        /* returning current descriptor, so advance to next free one */
-       adev->tx_head = (head + 1) % TX_CNT;
+       /* slower: adev->tx_head = (head + 1) % TX_CNT; */
+       adev->tx_head = head + 1;
+       if (adev->tx_head >= TX_CNT)
+               adev->tx_head = 0;
 end:
        FN_EXIT0;
 
@@ -3497,7 +3504,9 @@
                                finger, ack_failures, rts_failures, rts_ok, 
r100);
 
                /* update pointer for descr to be cleaned next */
-               finger = (finger + 1) % TX_CNT;
+               /* slower: finger = (finger + 1) % TX_CNT; */
+               if (++finger >= TX_CNT)
+                       finger = 0;
        }
 
        /* remember last position */
diff -urN acx-20060202/usb.c acx-20060202_stats/usb.c
--- acx-20060202/usb.c  2006-02-01 10:49:34.000000000 +0100
+++ acx-20060202_stats/usb.c    2006-02-03 10:24:07.000000000 +0100
@@ -1576,7 +1576,10 @@
 
        head = adev->tx_head;
        do {
-               head = (head + 1) % ACX_TX_URB_CNT;
+               /* slower: head = (head + 1) % ACX_TX_URB_CNT; */
+               if (++head >= ACX_TX_URB_CNT)
+                       head = 0;
+
                if (!adev->usb_tx[head].busy) {
                        log(L_USBRXTX, "allocated tx %d\n", head);
                        tx = &adev->usb_tx[head];
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to