From: Denis Vlasenko Update drivers/net/wireless/tiacx driver from version 0.3.14 to 0.3.23. [20051228] * Global s/acxlog/log/ [20051220] 0.3.23 * timeout handling fixed for high load case (patch by Andreas Mohr) [20051219] 0.3.22 * acx100 active scanning must be working now, thanks to Carlos Martin . [20051202] * acx_s_update_card_settings cosmetic change (but wasn't run tested) [20051201] 0.3.21 * Thanks Carlos Martin * Completely serialize USB rx. Tiny speed loss, but even more safe wrt reordering. * A few msleeps removed [20051128] 0.3.20 * we will use only 2 rx usb buffers now. No apparent speed loss, eliminates usb packet reordering risk. * two USB fixes for real bugs and one fix for possible leak of an urb on error path. Thanks Carlos Martin . [20051116] 0.3.19 * a few small fixes accumulated over time, nothing spectacular [20051031] 0.3.18 * hopefully a final touch on USB tx autorate [20051022] 0.3.17 * PCI command submission made simpler [20051021] 0.3.16 * Small changes mostly designed to break USB ;) * Auto rate handling for USB is still not confirmed to work. I need USB logs from the users. [20051020] 0.3.15 * Auto rate handling for USB is implemented. Untested. [20051019] * first step in proper auto rate handling for USB Signed-off-by: Andrew Morton --- drivers/net/wireless/tiacx/Changelog | 51 + drivers/net/wireless/tiacx/acx_config.h | 2 drivers/net/wireless/tiacx/acx_func.h | 173 ++- drivers/net/wireless/tiacx/acx_struct.h | 192 ++-- drivers/net/wireless/tiacx/common.c | 988 ++++++++++++++-------- drivers/net/wireless/tiacx/conv.c | 22 drivers/net/wireless/tiacx/ioctl.c | 403 ++++---- drivers/net/wireless/tiacx/pci.c | 949 ++++++--------------- drivers/net/wireless/tiacx/usb.c | 967 ++++++++++----------- drivers/net/wireless/tiacx/wlan.c | 5 drivers/net/wireless/tiacx/wlan_mgmt.h | 1 11 files changed, 1864 insertions(+), 1889 deletions(-) diff -puN drivers/net/wireless/tiacx/acx_config.h~acx-driver-update drivers/net/wireless/tiacx/acx_config.h --- devel/drivers/net/wireless/tiacx/acx_config.h~acx-driver-update 2006-01-06 22:44:21.000000000 -0800 +++ devel-akpm/drivers/net/wireless/tiacx/acx_config.h 2006-01-06 22:44:21.000000000 -0800 @@ -1,4 +1,4 @@ -#define WLAN_RELEASE "v0.3.13" +#define ACX_RELEASE "v0.3.23" /* set to 0 if you don't want any debugging code to be compiled in */ /* set to 1 if you want some debugging */ diff -puN drivers/net/wireless/tiacx/acx_func.h~acx-driver-update drivers/net/wireless/tiacx/acx_func.h --- devel/drivers/net/wireless/tiacx/acx_func.h~acx-driver-update 2006-01-06 22:44:21.000000000 -0800 +++ devel-akpm/drivers/net/wireless/tiacx/acx_func.h 2006-01-06 22:44:21.000000000 -0800 @@ -51,13 +51,13 @@ ** - Use printk_ratelimited() for messages which may flood ** (e.g. "rx DUP pkt!"). ** -** - Use acxlog() for messages which may be omitted (and they +** - Use log() for messages which may be omitted (and they ** _will_ be omitted in non-debug builds). Note that ** message levels may be disabled at compile-time selectively, ** thus select them wisely. Example: L_DEBUG is the lowest ** (most likely to be compiled out) -> use for less important stuff. ** -** - Do not print important stuff with acxlog(), or else people +** - Do not print important stuff with log(), or else people ** will never build non-debug driver. ** ** Style: @@ -101,7 +101,7 @@ void log_fn_exit_v(const char *funcname, #if ACX_DEBUG -#define acxlog(chan, args...) \ +#define log(chan, args...) \ do { \ if (acx_debug & (chan)) \ printk(args); \ @@ -110,7 +110,7 @@ void log_fn_exit_v(const char *funcname, #else /* Non-debug build: */ -#define acxlog(chan, args...) +#define log(chan, args...) /* Standard way of log flood prevention */ #define printk_ratelimited(args...) \ do { \ @@ -354,12 +354,12 @@ acx_up_helper(wlandevice_t *priv, const static inline void acx_stop_queue(netdevice_t *dev, const char *msg) { - if(netif_queue_stopped(dev)) + if (netif_queue_stopped(dev)) return; netif_stop_queue(dev); if (msg) - acxlog(L_BUFT, "tx: stop queue %s\n", msg); + log(L_BUFT, "tx: stop queue %s\n", msg); } static inline int @@ -368,20 +368,22 @@ acx_queue_stopped(netdevice_t *dev) return netif_queue_stopped(dev); } +/* static inline void acx_start_queue(netdevice_t *dev, const char *msg) { netif_start_queue(dev); if (msg) - acxlog(L_BUFT, "tx: start queue %s\n", msg); + log(L_BUFT, "tx: start queue %s\n", msg); } +*/ static inline void acx_wake_queue(netdevice_t *dev, const char *msg) { netif_wake_queue(dev); if (msg) - acxlog(L_BUFT, "tx: wake queue %s\n", msg); + log(L_BUFT, "tx: wake queue %s\n", msg); } static inline void @@ -389,7 +391,7 @@ acx_carrier_off(netdevice_t *dev, const { netif_carrier_off(dev); if (msg) - acxlog(L_BUFT, "tx: carrier off %s\n", msg); + log(L_BUFT, "tx: carrier off %s\n", msg); } static inline void @@ -397,7 +399,7 @@ acx_carrier_on(netdevice_t *dev, const c { netif_carrier_on(dev); if (msg) - acxlog(L_BUFT, "tx: carrier on %s\n", msg); + log(L_BUFT, "tx: carrier on %s\n", msg); } /* This function does not need locking UNLESS you call it @@ -493,6 +495,17 @@ acx_proc_unregister_entries(const struct /*********************************************************************** +*/ +#if USE_FW_LOADER_26 +firmware_image_t *acx_s_read_fw(struct device *dev, const char *file, u32 *size); +#else +firmware_image_t *acx_s_read_fw(const char *file, u32 *size); +#define acx_s_read_fw(dev, file, size) acx_s_read_fw(file, size) +#endif +int acxpci_s_upload_radio(wlandevice_t *priv); + + +/*********************************************************************** ** Unsorted yet :) */ int acxpci_s_read_phy_reg(wlandevice_t *priv, u32 reg, u8 *charbuf); @@ -515,64 +528,6 @@ acx_s_write_phy_reg(wlandevice_t *priv, return acxusb_s_write_phy_reg(priv, reg, value); } -void acx_s_msleep(int ms); -int acx_s_init_mac(netdevice_t *dev); -void acx_set_reg_domain(wlandevice_t *priv, unsigned char reg_dom_id); -void acx_set_timer(wlandevice_t *priv, int timeout_us); -void acx_update_capabilities(wlandevice_t *priv); -int acxpci_read_eeprom_byte(wlandevice_t *priv, u32 addr, u8 *charbuf); -void acx_s_start(wlandevice_t *priv); - -#if USE_FW_LOADER_26 -firmware_image_t *acx_s_read_fw(struct device *dev, const char *file, u32 *size); -#else -firmware_image_t *acx_s_read_fw(const char *file, u32 *size); -#define acx_s_read_fw(dev, file, size) acx_s_read_fw(file, size) -#endif -int acxpci_s_upload_radio(wlandevice_t *priv); - -void acx_s_initialize_rx_config(wlandevice_t *priv); -void acx_s_update_card_settings(wlandevice_t *priv, int get_all, int set_all); -void acx_read_configoption(wlandevice_t *priv); -void acx_l_update_ratevector(wlandevice_t *priv); - -void acx_init_task_scheduler(wlandevice_t *priv); -void acx_schedule_task(wlandevice_t *priv, unsigned int set_flag); - -int acx_e_ioctl_old(netdevice_t *dev, struct ifreq *ifr, int cmd); - -client_t *acx_l_sta_list_get(wlandevice_t *priv, const u8 *address); -void acx_l_sta_list_del(wlandevice_t *priv, client_t *clt); - -int acx_l_transmit_disassoc(wlandevice_t *priv, client_t *clt); -void acx_i_timer(unsigned long a); -int acx_s_complete_scan(wlandevice_t *priv); - -static inline wlan_hdr_t* -acx_get_wlan_hdr(wlandevice_t *priv, const rxbuffer_t *rxbuf) -{ - if (!(priv->rx_config_1 & RX_CFG1_INCLUDE_PHY_HDR)) - return (wlan_hdr_t*)&rxbuf->hdr_a3; - - /* take into account phy header in front of packet */ - if (IS_ACX111(priv)) - return (wlan_hdr_t*)((u8*)&rxbuf->hdr_a3 + 8); - - return (wlan_hdr_t*)((u8*)&rxbuf->hdr_a3 + 4); -} - -struct sk_buff *acx_rxbuf_to_ether(struct wlandevice *priv, rxbuffer_t *rxbuf); -int acx_ether_to_txbuf(wlandevice_t *priv, void *txbuf, const struct sk_buff *skb); - -void acxpci_l_power_led(wlandevice_t *priv, int enable); - -unsigned int acxpci_l_clean_txdesc(wlandevice_t *priv); -void acxpci_l_clean_txdesc_emergency(wlandevice_t *priv); - -u8 acx_signal_determine_quality(u8 signal, u8 noise); - -void acx_l_process_rxbuf(wlandevice_t *priv, rxbuffer_t *rxbuf); - tx_t* acxpci_l_alloc_tx(wlandevice_t *priv); tx_t* acxusb_l_alloc_tx(wlandevice_t *priv); static inline tx_t* @@ -583,6 +538,14 @@ acx_l_alloc_tx(wlandevice_t *priv) return acxusb_l_alloc_tx(priv); } +void acxusb_l_dealloc_tx(tx_t *tx_opaque); +static inline void +acx_l_dealloc_tx(wlandevice_t *priv, tx_t *tx_opaque) +{ + if (IS_USB(priv)) + acxusb_l_dealloc_tx(tx_opaque); +} + void* acxpci_l_get_txbuf(wlandevice_t *priv, tx_t *tx_opaque); void* acxusb_l_get_txbuf(wlandevice_t *priv, tx_t *tx_opaque); static inline void* @@ -604,15 +567,71 @@ acx_l_tx_data(wlandevice_t *priv, tx_t * acxusb_l_tx_data(priv, tx_opaque, len); } +static inline wlan_hdr_t* +acx_get_wlan_hdr(wlandevice_t *priv, const rxbuffer_t *rxbuf) +{ + if (!(priv->rx_config_1 & RX_CFG1_INCLUDE_PHY_HDR)) + return (wlan_hdr_t*)&rxbuf->hdr_a3; + + /* take into account phy header in front of packet */ + if (IS_ACX111(priv)) + return (wlan_hdr_t*)((u8*)&rxbuf->hdr_a3 + 8); + + return (wlan_hdr_t*)((u8*)&rxbuf->hdr_a3 + 4); +} + +void acxpci_l_power_led(wlandevice_t *priv, int enable); +int acxpci_read_eeprom_byte(wlandevice_t *priv, u32 addr, u8 *charbuf); +unsigned int acxpci_l_clean_txdesc(wlandevice_t *priv); +void acxpci_l_clean_txdesc_emergency(wlandevice_t *priv); +int acxpci_s_create_hostdesc_queues(wlandevice_t *priv); +void acxpci_create_desc_queues(wlandevice_t *priv, u32 tx_queue_start, u32 rx_queue_start); +void acxpci_free_desc_queues(wlandevice_t *priv); +char* acxpci_s_proc_diag_output(char *p, wlandevice_t *priv); +int acxpci_proc_eeprom_output(char *p, wlandevice_t *priv); +void acxpci_set_interrupt_mask(wlandevice_t *priv); +int acx100pci_s_set_tx_level(wlandevice_t *priv, u8 level_dbm); + +void acx_s_msleep(int ms); +int acx_s_init_mac(wlandevice_t *priv); +void acx_set_reg_domain(wlandevice_t *priv, unsigned char reg_dom_id); +void acx_set_timer(wlandevice_t *priv, int timeout_us); +void acx_update_capabilities(wlandevice_t *priv); +void acx_s_start(wlandevice_t *priv); + +void acx_s_initialize_rx_config(wlandevice_t *priv); +void acx_s_update_card_settings(wlandevice_t *priv); +void acx_read_configoption(wlandevice_t *priv); +void acx_l_update_ratevector(wlandevice_t *priv); + +void acx_init_task_scheduler(wlandevice_t *priv); +void acx_schedule_task(wlandevice_t *priv, unsigned int set_flag); + +int acx_e_ioctl_old(netdevice_t *dev, struct ifreq *ifr, int cmd); + +client_t *acx_l_sta_list_get(wlandevice_t *priv, const u8 *address); +void acx_l_sta_list_del(wlandevice_t *priv, client_t *clt); + +int acx_l_transmit_disassoc(wlandevice_t *priv, client_t *clt); +void acx_i_timer(unsigned long a); +int acx_s_complete_scan(wlandevice_t *priv); + +struct sk_buff *acx_rxbuf_to_ether(struct wlandevice *priv, rxbuffer_t *rxbuf); +int acx_ether_to_txbuf(wlandevice_t *priv, void *txbuf, const struct sk_buff *skb); + +u8 acx_signal_determine_quality(u8 signal, u8 noise); + +void acx_l_process_rxbuf(wlandevice_t *priv, rxbuffer_t *rxbuf); +void acx_l_handle_txrate_auto(wlandevice_t *priv, struct client *txc, + u16 intended_rate, u8 rate100, u16 rate111, u8 error, + int pkts_to_ignore); + void acx_dump_bytes(const void *, int); void acx_log_bad_eid(wlan_hdr_t* hdr, int len, wlan_ie_t* ie_ptr); u8 acx_rate111to100(u16); -void acx100usb_l_tx_data(wlandevice_t *priv, struct txdesc *desc); -int acx_s_set_defaults(wlandevice_t *priv); -void acxpci_init_mboxes(wlandevice_t *priv); - +void acx_s_set_defaults(wlandevice_t *priv); #if !ACX_DEBUG static inline const char* acx_get_packet_type_string(u16 fc) { return ""; } @@ -622,10 +641,6 @@ const char* acx_get_packet_type_string(u const char* acx_cmd_status_str(unsigned int state); int acx_i_start_xmit(struct sk_buff *skb, netdevice_t *dev); -void acxpci_free_desc_queues(wlandevice_t *priv); - -int acxpci_s_create_hostdesc_queues(wlandevice_t *priv); -void acxpci_create_desc_queues(wlandevice_t *priv, u32 tx_queue_start, u32 rx_queue_start); int acx100_s_init_wep(wlandevice_t *priv); int acx100_s_init_packet_templates(wlandevice_t *priv); @@ -633,10 +648,8 @@ int acx111_s_init_packet_templates(wland void great_inquisitor(wlandevice_t *priv); -char* acxpci_s_proc_diag_output(char *p, wlandevice_t *priv); -int acxpci_proc_eeprom_output(char *p, wlandevice_t *priv); -void acxpci_set_interrupt_mask(wlandevice_t *priv); -int acx100pci_s_set_tx_level(wlandevice_t *priv, u8 level_dbm); +void acx_s_get_firmware_version(wlandevice_t *priv); +void acx_display_hardware_details(wlandevice_t *priv); int acx_e_change_mtu(struct net_device *dev, int mtu); struct net_device_stats* acx_e_get_stats(netdevice_t *dev); diff -puN drivers/net/wireless/tiacx/acx_struct.h~acx-driver-update drivers/net/wireless/tiacx/acx_struct.h --- devel/drivers/net/wireless/tiacx/acx_struct.h~acx-driver-update 2006-01-06 22:44:21.000000000 -0800 +++ devel-akpm/drivers/net/wireless/tiacx/acx_struct.h 2006-01-06 22:44:21.000000000 -0800 @@ -71,14 +71,14 @@ enum { acx_debug = 0 }; #endif -/*============================================================================* - * Random helpers * - *============================================================================*/ +/*********************************************************************** +** Random helpers +*/ #define ACX_PACKED __WLAN_ATTRIB_PACK__ #define VEC_SIZE(a) (sizeof(a)/sizeof(a[0])) -/* Use worker_queues for 2.5/2.6 Kernels and queue tasks for 2.4 Kernels +/* Use worker_queues for 2.5/2.6 kernels and queue tasks for 2.4 kernels (used for the 'bottom half' of the interrupt routine) */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,41) @@ -104,9 +104,9 @@ enum { acx_debug = 0 }; #endif -/*============================================================================* - * Constants * - *============================================================================*/ +/*********************************************************************** +** Constants +*/ #define OK 0 #define NOT_OK 1 @@ -221,12 +221,13 @@ enum { acx_debug = 0 }; #define TX_CNT 16 /* we clean up txdescs when we have N free txdesc: */ -#define TX_START_CLEAN (TX_CNT - (TX_CNT/4)) +#define TX_CLEAN_BACKLOG (TX_CNT/4) +#define TX_START_CLEAN (TX_CNT - TX_CLEAN_BACKLOG) #define TX_EMERG_CLEAN 2 -/* we stop queue if we have less than N free txbufs: */ +/* we stop queue if we have < N free txbufs: */ #define TX_STOP_QUEUE 3 -/* we start queue if we have more than N free txbufs: */ -#define TX_START_QUEUE 6 +/* we start queue if we have >= N free txbufs: */ +#define TX_START_QUEUE 5 /*********************************************************************** ** Interrogate/Configure cmd constants @@ -447,9 +448,9 @@ DEF_IE(111_IE_DOT11_INVAL_1013, 0x1013 #endif -/*============================================================================* - * Information Frames Structures * - *============================================================================*/ +/*********************************************************************** +**Information Frames Structures +*/ /* Used in beacon frames and the like */ #define DOT11RATEBYTE_1 (1*2) @@ -495,10 +496,13 @@ typedef struct phy_hdr { #define RXBUF_BYTES_RCVD(rxbuf) (le16_to_cpu(rxbuf->mac_cnt_rcvd) & 0xfff) #define RXBUF_BYTES_USED(rxbuf) \ ((le16_to_cpu(rxbuf->mac_cnt_rcvd) & 0xfff) + RXBUF_HDRSIZE) +/* USBism */ +#define RXBUF_IS_TXSTAT(rxbuf) (le16_to_cpu(rxbuf->mac_cnt_rcvd) & 0x8000) /* mac_cnt_rcvd: 12 bits: length of frame from control field to last byte of FCS - 4 bits: reserved + 3 bits: reserved + 1 bit: 1 = it's a tx status info, not a rx packet (USB only) mac_cnt_mblks: 6 bits: number of memory block used to store frame in adapter memory @@ -680,9 +684,9 @@ struct client { }; -/*============================================================================* - * Hardware structures * - *============================================================================*/ +/*********************************************************************** +** Hardware structures +*/ /* An opaque typesafe helper type * @@ -763,9 +767,6 @@ typedef struct { #define DESC_CTL_ACXDONE 0x40 /* acx has finished processing */ /* host owns the desc [has to be released last, AFTER modifying all other desc fields!] */ #define DESC_CTL_HOSTOWN 0x80 - -#define DESC_CTL_INIT (DESC_CTL_HOSTOWN | DESC_CTL_RECLAIM | \ - DESC_CTL_AUTODMA | DESC_CTL_FIRSTFRAG) #define DESC_CTL_ACXDONE_HOSTOWN (DESC_CTL_ACXDONE | DESC_CTL_HOSTOWN) /* Descriptor Status field @@ -782,7 +783,7 @@ typedef struct { #define DESC_CTL2_WEP 0x40 /* encrypt this frame */ #define DESC_CTL2_DUR 0x80 /* don't increase duration field */ -/*************************************************************** +/*********************************************************************** ** PCI structures */ /* IRQ Constants @@ -955,67 +956,70 @@ struct rxhostdesc { #endif /* ACX_PCI */ -/*************************************************************** +/*********************************************************************** ** USB structures and constants */ #ifdef ACX_USB -/* Buffer size for fw upload */ -#define ACX100_USB_RWMEM_MAXLEN 2048 - -/* Should be sent to the ctrlout endpoint */ -#define ACX100_USB_ENBULKIN 6 - -/* The number of bulk URBs to use */ -#define ACX100_USB_NUM_BULK_URBS 8 - -/* Should be sent to the bulkout endpoint */ -#define ACX_USB_REQ_UPLOAD_FW 0x10 -#define ACX_USB_REQ_ACK_CS 0x11 -#define ACX_USB_REQ_CMD 0x12 - /* Used for usb_txbuffer.desc field */ #define USB_TXBUF_TXDESC 0xA -/* Used for usb_txbuffer.hostData field */ -#define USB_TXBUF_HD_ISDATA 0x10000 -#define USB_TXBUF_HD_DIRECTED 0x20000 -#define USB_TXBUF_HD_BROADCAST 0x40000 /* Size of header (everything up to data[]) */ #define USB_TXBUF_HDRSIZE 14 typedef struct usb_txbuffer { u16 desc ACX_PACKED; - u16 MPDUlen ACX_PACKED; - u8 index ACX_PACKED; - u8 txRate ACX_PACKED; - u32 hostData ACX_PACKED; + u16 mpdu_len ACX_PACKED; + u8 queue_index ACX_PACKED; + u8 rate ACX_PACKED; + u32 hostdata ACX_PACKED; u8 ctrl1 ACX_PACKED; u8 ctrl2 ACX_PACKED; - u16 dataLength ACX_PACKED; + u16 data_len ACX_PACKED; /* wlan packet content is placed here: */ u8 data[WLAN_A4FR_MAXLEN_WEP_FCS] ACX_PACKED; } usb_txbuffer_t; +/* USB returns either rx packets (see rxbuffer) or +** these "tx status" structs: */ +typedef struct usb_txstatus { + u16 mac_cnt_rcvd ACX_PACKED; /* only 12 bits are len! (0xfff) */ + u8 queue_index ACX_PACKED; + u8 mac_status ACX_PACKED; /* seen 0x20 on tx failure */ + u32 hostdata ACX_PACKED; + u8 rate ACX_PACKED; + u8 ack_failures ACX_PACKED; + u8 rts_failures ACX_PACKED; + u8 rts_ok ACX_PACKED; +} usb_txstatus_t; + typedef struct usb_tx { unsigned busy:1; struct urb *urb; wlandevice_t *priv; - client_t *txc; /* actual USB bulk output data block is here: */ usb_txbuffer_t bulkout; } usb_tx_t; +struct usb_rx_plain { + unsigned busy:1; + struct urb *urb; + wlandevice_t *priv; + rxbuffer_t bulkin; +}; + typedef struct usb_rx { unsigned busy:1; struct urb *urb; wlandevice_t *priv; rxbuffer_t bulkin; + /* Make entire structure 4k. Report if it breaks something. */ + u8 padding[4*1024 - sizeof(struct usb_rx_plain)]; } usb_rx_t; #endif /* ACX_USB */ -/*============================================================================* - * Main acx per-device data structure (netdev_priv(dev)) * - *============================================================================*/ +/*********************************************************************** +** Main acx per-device data structure (netdev_priv(dev)) +*/ #define ACX_STATE_FW_LOADED 0x01 #define ACX_STATE_IFACE_UP 0x02 @@ -1209,6 +1213,7 @@ struct wlandevice { u16 rx_config_2; u16 memblocksize; int tx_free; + int tx_head; /*** Unknown ***/ u8 dtim_interval; @@ -1239,12 +1244,12 @@ struct wlandevice { unsigned int rxbuf_area_size; unsigned int rxhostdesc_area_size; - unsigned int txdesc_size; /* size per tx descr; ACX111 = ACX100 + 4 */ - unsigned int tx_head; /* current ring buffer pool member index */ + unsigned int txdesc_size; /* size of txdesc; ACX111 = ACX100 + 4 */ unsigned int tx_tail; unsigned int rx_tail; client_t *txc[TX_CNT]; + u16 txr[TX_CNT]; u8 need_radio_fw; u8 irqs_active; /* whether irq sending is activated */ @@ -1255,8 +1260,11 @@ struct wlandevice { unsigned long membase; unsigned long membase2; - void *iobase; - void *iobase2; + void __iomem *iobase; + void __iomem *iobase2; + /* command interface */ + u8 __iomem *cmd_area; + u8 __iomem *info_area; #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 10) /* 2.6.9-rc3-mm2 (2.6.9-bk4, too) introduced a shorter API version, @@ -1267,14 +1275,6 @@ struct wlandevice { u16 irq_mask_off; /* interrupt types to mask out (not wanted) with IRQs off */ unsigned int irq_loops_this_jiffy; unsigned long irq_last_jiffies; - - /* command interface */ - void *cmd_area; /* points to PCI mapped memory */ - void *info_area; /* points to PCI mapped memory */ - u16 cmd_type; - u16 cmd_status; - u16 info_type; - u16 info_status; #endif /*** USB stuff ***/ @@ -1382,12 +1382,37 @@ struct wlandevice { #define SET_WEP_OPTIONS 0x00080000L #define SET_MSDU_LIFETIME 0x00100000L #define SET_RATE_FALLBACK 0x00200000L -#define GETSET_ALL 0x80000000L + +/* keep in sync with the above */ +#define GETSET_ALL (0 \ +/* GETSET_LED_POWER */ | 0x00000001L \ +/* GETSET_STATION_ID */ | 0x00000002L \ +/* SET_TEMPLATES */ | 0x00000004L \ +/* SET_STA_LIST */ | 0x00000008L \ +/* GETSET_TX */ | 0x00000010L \ +/* GETSET_RX */ | 0x00000020L \ +/* SET_RXCONFIG */ | 0x00000040L \ +/* GETSET_ANTENNA */ | 0x00000080L \ +/* GETSET_SENSITIVITY */| 0x00000100L \ +/* GETSET_TXPOWER */ | 0x00000200L \ +/* GETSET_ED_THRESH */ | 0x00000400L \ +/* GETSET_CCA */ | 0x00000800L \ +/* GETSET_POWER_80211 */| 0x00001000L \ +/* GETSET_RETRY */ | 0x00002000L \ +/* GETSET_REG_DOMAIN */ | 0x00004000L \ +/* GETSET_CHANNEL */ | 0x00008000L \ +/* GETSET_RESCAN */ | 0x00010000L \ +/* GETSET_MODE */ | 0x00020000L \ +/* GETSET_WEP */ | 0x00040000L \ +/* SET_WEP_OPTIONS */ | 0x00080000L \ +/* SET_MSDU_LIFETIME */ | 0x00100000L \ +/* SET_RATE_FALLBACK */ | 0x00200000L \ + ) -/*============================================================================* - * Firmware loading * - *============================================================================*/ +/*********************************************************************** +** Firmware loading +*/ /* Doh, 2.4.x also has CONFIG_FW_LOADER_MODULE * (but doesn't have the new device model yet which we require!) * FIXME: exact version that introduced new device handling? */ @@ -1562,6 +1587,7 @@ typedef struct acx111_ie_powermgmt { #define ACX_SCAN_RATE_5 55 #define ACX_SCAN_RATE_11 110 #define ACX_SCAN_RATE_22 220 +#define ACX_SCAN_RATE_PBCC 0x80 /* OR with this if needed */ #define ACX_SCAN_OPT_ACTIVE 0x00 /* a bit mask */ #define ACX_SCAN_OPT_PASSIVE 0x01 /* Background scan: we go into Power Save mode (by transmitting @@ -1653,23 +1679,7 @@ typedef struct acx_template_tim { u8 variable[0x100 - 1-1-1-1-1] ACX_PACKED; } acx_template_tim_t; -typedef struct acx100_template_probereq { - u16 size ACX_PACKED; - u16 fc ACX_PACKED; /* 00 2 fc */ - u16 dur ACX_PACKED; /* 02 2 Duration */ - u8 da[6] ACX_PACKED; /* 04 6 Destination Address * */ - u8 sa[6] ACX_PACKED; /* 0A 6 Source Address * */ - u8 bssid[6] ACX_PACKED; /* 10 6 BSSID * */ - u16 seq ACX_PACKED; /* 16 2 Sequence Control */ - u8 timestamp[8] ACX_PACKED;/* 18 8 Timestamp */ - u16 beacon_interval ACX_PACKED; /* 20 2 Beacon Interval * */ - u16 cap ACX_PACKED; /* 22 2 Capability Information * */ - /* 24 n SSID * */ - /* nn n Supported Rates * */ - u8 variable[0x44 - 2-2-6-6-6-2-8-2-2] ACX_PACKED; -} acx100_template_probereq_t; - -typedef struct acx111_template_probereq { +typedef struct acx_template_probereq { u16 size ACX_PACKED; u16 fc ACX_PACKED; /* 00 2 fc * */ u16 dur ACX_PACKED; /* 02 2 Duration */ @@ -1680,7 +1690,7 @@ typedef struct acx111_template_probereq /* 18 n SSID * */ /* nn n Supported Rates * */ u8 variable[0x44 - 2-2-6-6-6-2] ACX_PACKED; -} acx111_template_probereq_t; +} acx_template_probereq_t; typedef struct acx_template_proberesp { u16 size ACX_PACKED; @@ -1925,13 +1935,13 @@ acx_struct_size_check(void) } -/*============================================================================* - * Global data * - *============================================================================*/ -extern const u8 bitpos2ratebyte[]; -extern const u8 bitpos2rate100[]; +/*********************************************************************** +** Global data +*/ +extern const u8 acx_bitpos2ratebyte[]; +extern const u8 acx_bitpos2rate100[]; -extern const u8 reg_domain_ids[]; -extern const u8 reg_domain_ids_len; +extern const u8 acx_reg_domain_ids[]; +extern const u8 acx_reg_domain_ids_len; extern const struct iw_handler_def acx_ioctl_handler_def; diff -puN drivers/net/wireless/tiacx/Changelog~acx-driver-update drivers/net/wireless/tiacx/Changelog --- devel/drivers/net/wireless/tiacx/Changelog~acx-driver-update 2006-01-06 22:44:21.000000000 -0800 +++ devel-akpm/drivers/net/wireless/tiacx/Changelog 2006-01-06 22:44:21.000000000 -0800 @@ -104,6 +104,57 @@ TODO: from Efthym : 13:14:13 wlan0: tx error 0x20, buf 07! 13:14:13 wlan0: tx error 0x20, buf 08! +[20051228] +* Global s/acxlog/log/ + +[20051220] 0.3.23 +* timeout handling fixed for high load case + (patch by Andreas Mohr) + +[20051219] 0.3.22 +* acx100 active scanning must be working now, thanks to Carlos Martin + . + +[20051202] +* acx_s_update_card_settings cosmetic change + (but wasn't run tested) + +[20051201] 0.3.21 +* Thanks Carlos Martin +* Completely serialize USB rx. Tiny speed loss, + but even more safe wrt reordering. +* A few msleeps removed + +[20051128] 0.3.20 +* we will use only 2 rx usb buffers now. No apparent speed loss, + eliminates usb packet reordering risk. +* two USB fixes for real bugs and one fix for possible leak + of an urb on error path. Thanks Carlos Martin . + +[20051116] 0.3.19 +* a few small fixes accumulated over time, nothing spectacular + +[20051031] 0.3.18 +* hopefully a final touch on USB tx autorate + +[20051022] 0.3.17 +* PCI command submission made simpler + +[20051021] 0.3.16 +* Small changes mostly designed to break USB ;) +* Auto rate handling for USB is still not confirmed to work. + I need USB logs from the users. + +[20051020] 0.3.15 +* Auto rate handling for USB is implemented. Untested. + +[20051019] +* first step in proper auto rate handling for USB + +[20051018] 0.3.14 +* update for 2.6.14-rc4-mm1 +* Kconfig bug (error if ACX=y, ACX_USB=y, USB=m) fixed +* PARANOID_LOCKING off by default [20051016] 0.3.13 * Revert 20051013 fix, we have one which actually works. diff -puN drivers/net/wireless/tiacx/common.c~acx-driver-update drivers/net/wireless/tiacx/common.c --- devel/drivers/net/wireless/tiacx/common.c~acx-driver-update 2006-01-06 22:44:21.000000000 -0800 +++ devel-akpm/drivers/net/wireless/tiacx/common.c 2006-01-06 22:44:21.000000000 -0800 @@ -129,19 +129,6 @@ MODULE_PARM(card, "i"); MODULE_PARM_DESC(card, "Associate only with card-th acx100 card from this driver instance"); #endif -/* Shoundn't be needed now, acx.firmware_dir= should work */ -#if 0 /* USE_FW_LOADER_LEGACY */ -static int __init -acx_get_firmware_dir(const char *str) -{ - /* I've seen other drivers just pass the string pointer, - * so hopefully that's safe */ - firmware_dir = str; - return OK; -} -__setup("acx_firmware_dir=", acx_get_firmware_dir); -#endif - #ifdef MODULE_LICENSE MODULE_LICENSE("Dual MPL/GPL"); #endif @@ -165,11 +152,11 @@ MODULE_DESCRIPTION("Driver for TI ACX1xx /* minutes to wait until next radio recalibration: */ #define RECALIB_PAUSE 5 -const u8 reg_domain_ids[] = +const u8 acx_reg_domain_ids[] = { 0x10, 0x20, 0x30, 0x31, 0x32, 0x40, 0x41, 0x51 }; /* stupid workaround for the fact that in C the size of an external array * cannot be determined from within a second file */ -const u8 reg_domain_ids_len = sizeof(reg_domain_ids); +const u8 acx_reg_domain_ids_len = sizeof(acx_reg_domain_ids); static const u16 reg_domain_channel_masks[] = { 0x07ff, 0x07ff, 0x1fff, 0x0600, 0x1e00, 0x2000, 0x3fff, 0x01fc }; @@ -236,15 +223,18 @@ void acx_down_debug(wlandevice_t *priv, const char* where) { int sem_count; - int count = 5000/5; + unsigned long timeout = jiffies + 5*HZ; + where = sanitize_str(where); - while (--count) { + for (;;) { sem_count = atomic_read(&priv->sem.count); if (sem_count) break; + if (time_after(jiffies, timeout)) + break; msleep(5); } - if (!count) { + if (!sem_count) { printk(KERN_EMERG "D STATE at %s! last sem at %s\n", where, priv->last_sem); dump_stack(); @@ -392,7 +382,10 @@ acx_get_status_name(u16 status) "STOPPED", "SCANNING", "WAIT_AUTH", "AUTHENTICATED", "ASSOCIATED", "INVALID??" }; - return str[(status < VEC_SIZE(str)) ? status : VEC_SIZE(str)-1]; + if (status >= VEC_SIZE(str)) + status = VEC_SIZE(str)-1; + + return str[status]; } @@ -446,6 +439,43 @@ acx_get_packet_type_string(u16 fc) /*********************************************************************** +** acx_wlan_reason_str +*/ +static const char* +acx_wlan_reason_str(u16 reason) +{ + static const char* const reason_str[] = { + /* 0 */ "?", + /* 1 */ "unspecified", + /* 2 */ "prev auth is not valid", + /* 3 */ "leaving BBS", + /* 4 */ "due to inactivity", + /* 5 */ "AP is busy", + /* 6 */ "got class 2 frame from non-auth'ed STA", + /* 7 */ "got class 3 frame from non-assoc'ed STA", + /* 8 */ "STA has left BSS", + /* 9 */ "assoc without auth is not allowed", + /* 10 */ "bad power setting (802.11h)", + /* 11 */ "bad channel (802.11i)", + /* 12 */ "?", + /* 13 */ "invalid IE", + /* 14 */ "MIC failure", + /* 15 */ "four-way handshake timeout", + /* 16 */ "group key handshake timeout", + /* 17 */ "IE is different", + /* 18 */ "invalid group cipher", + /* 19 */ "invalid pairwise cipher", + /* 20 */ "invalid AKMP", + /* 21 */ "unsupported RSN version", + /* 22 */ "invalid RSN IE cap", + /* 23 */ "802.1x failed", + /* 24 */ "cipher suite rejected" + }; + return reason < VEC_SIZE(reason_str) ? reason_str[reason] : "?"; +} + + +/*********************************************************************** ** acx_cmd_status_str */ const char* @@ -471,7 +501,7 @@ acx_cmd_status_str(unsigned int state) "Failed" }; return state < VEC_SIZE(cmd_error_strings) ? - cmd_error_strings[state] : "UNKNOWN REASON"; + cmd_error_strings[state] : "?"; } @@ -569,6 +599,165 @@ acx_dump_bytes(const void *data, int num /*********************************************************************** +** acx_s_get_firmware_version +*/ +void +acx_s_get_firmware_version(wlandevice_t *priv) +{ + fw_ver_t fw; + u8 hexarr[4] = { 0, 0, 0, 0 }; + int hexidx = 0, val = 0; + const char *num; + char c; + + FN_ENTER; + + memset(fw.fw_id, 'E', FW_ID_SIZE); + acx_s_interrogate(priv, &fw, ACX1xx_IE_FWREV); + memcpy(priv->firmware_version, fw.fw_id, FW_ID_SIZE); + priv->firmware_version[FW_ID_SIZE] = '\0'; + + log(L_DEBUG, "fw_ver: fw_id='%s' hw_id=%08X\n", + priv->firmware_version, fw.hw_id); + + if (strncmp(fw.fw_id, "Rev ", 4) != 0) { + printk("acx: strange firmware version string " + "'%s', please report\n", priv->firmware_version); + priv->firmware_numver = 0x01090407; /* assume 1.9.4.7 */ + } else { + num = &fw.fw_id[4]; + while (1) { + c = *num++; + if ((c == '.') || (c == '\0')) { + hexarr[hexidx++] = val; + if ((hexidx > 3) || (c == '\0')) /* end? */ + break; + val = 0; + continue; + } + if ((c >= '0') && (c <= '9')) + c -= '0'; + else + c = c - 'a' + (char)10; + val = val*16 + c; + } + + priv->firmware_numver = (u32)( + (hexarr[0] << 24) + (hexarr[1] << 16) + + (hexarr[2] << 8) + hexarr[3]); + log(L_DEBUG, "firmware_numver 0x%08X\n", priv->firmware_numver); + } + if (IS_ACX111(priv)) { + if (priv->firmware_numver == 0x00010011) { + /* This one does not survive floodpinging */ + printk("acx: firmware '%s' is known to be buggy, " + "please upgrade\n", priv->firmware_version); + } + if (priv->firmware_numver == 0x02030131) { + /* With this one, all rx packets look mangled + ** Most probably we simply do not know how to use it + ** properly */ + printk("acx: firmware '%s' does not work well " + "with this driver\n", priv->firmware_version); + } + } + + priv->firmware_id = le32_to_cpu(fw.hw_id); + + /* we're able to find out more detailed chip names now */ + switch (priv->firmware_id & 0xffff0000) { + case 0x01010000: + case 0x01020000: + priv->chip_name = "TNETW1100A"; + break; + case 0x01030000: + priv->chip_name = "TNETW1100B"; + break; + case 0x03000000: + case 0x03010000: + priv->chip_name = "TNETW1130"; + break; + default: + printk("acx: unknown chip ID 0x%08X, " + "please report\n", priv->firmware_id); + break; + } + + FN_EXIT0; +} + + +/*********************************************************************** +** acx_display_hardware_details +** +** Displays hw/fw version, radio type etc... +*/ +void +acx_display_hardware_details(wlandevice_t *priv) +{ + const char *radio_str, *form_str; + + FN_ENTER; + + switch (priv->radio_type) { + case RADIO_MAXIM_0D: + /* hmm, the DWL-650+ seems to have two variants, + * according to a windows driver changelog comment: + * RFMD and Maxim. */ + radio_str = "Maxim"; + break; + case RADIO_RFMD_11: + radio_str = "RFMD"; + break; + case RADIO_RALINK_15: + radio_str = "Ralink"; + break; + case RADIO_RADIA_16: + radio_str = "Radia"; + break; + case RADIO_UNKNOWN_17: + /* TI seems to have a radio which is + * additionally 802.11a capable, too */ + radio_str = "802.11a/b/g radio?! Please report"; + break; + case RADIO_UNKNOWN_19: + radio_str = "A radio used by Safecom cards?! Please report"; + break; + default: + radio_str = "UNKNOWN, please report the radio type name!"; + break; + } + + switch (priv->form_factor) { + case 0x00: + form_str = "unspecified"; + break; + case 0x01: + form_str = "(mini-)PCI / CardBus"; + break; + case 0x02: + form_str = "USB"; + break; + case 0x03: + form_str = "Compact Flash"; + break; + default: + form_str = "UNKNOWN, please report"; + break; + } + + printk("acx: form factor 0x%02X (%s), " + "radio type 0x%02X (%s), EEPROM version 0x%02X, " + "uploaded firmware '%s' (0x%08X)\n", + priv->form_factor, form_str, priv->radio_type, radio_str, + priv->eeprom_version, priv->firmware_version, + priv->firmware_id); + + FN_EXIT0; +} + + +/*********************************************************************** */ int acx_e_change_mtu(struct net_device *dev, int mtu) @@ -608,7 +797,7 @@ acx_e_get_wireless_stats(netdevice_t *de ** maps acx111 tx descr rate field to acx100 one */ const u8 -bitpos2rate100[] = { +acx_bitpos2rate100[] = { RATE100_1 ,/* 0 */ RATE100_2 ,/* 1 */ RATE100_5 ,/* 2 */ @@ -629,7 +818,7 @@ bitpos2rate100[] = { u8 acx_rate111to100(u16 r) { - return bitpos2rate100[highest_bit(r)]; + return acx_bitpos2rate100[highest_bit(r)]; } @@ -735,15 +924,15 @@ acx_s_configure_debug(wlandevice_t *priv else len = CtlLengthDot11[type - 0x1000]; - acxlog(L_CTL, FUNC"(type:%s,len:%u)\n", typestr, len); + log(L_CTL, FUNC"(type:%s,len:%u)\n", typestr, len); if (unlikely(!len)) { - acxlog(L_DEBUG, "zero-length type %s?!\n", typestr); + log(L_DEBUG, "zero-length type %s?!\n", typestr); } ((acx_ie_generic_t *)pdr)->type = cpu_to_le16(type); ((acx_ie_generic_t *)pdr)->len = cpu_to_le16(len); res = acx_s_issue_cmd(priv, ACX1xx_CMD_CONFIGURE, pdr, len + 4); - if (OK != res) { + if (unlikely(OK != res)) { #if ACX_DEBUG printk("%s: "FUNC"(type:%s) FAILED\n", priv->netdev->name, typestr); #else @@ -773,12 +962,12 @@ acx_s_interrogate_debug(wlandevice_t *pr len = CtlLength[type]; else len = CtlLengthDot11[type-0x1000]; - acxlog(L_CTL, FUNC"(type:%s,len:%u)\n", typestr, len); + log(L_CTL, FUNC"(type:%s,len:%u)\n", typestr, len); ((acx_ie_generic_t *)pdr)->type = cpu_to_le16(type); ((acx_ie_generic_t *)pdr)->len = cpu_to_le16(len); res = acx_s_issue_cmd(priv, ACX1xx_CMD_INTERROGATE, pdr, len + 4); - if (OK != res) { + if (unlikely(OK != res)) { #if ACX_DEBUG printk("%s: "FUNC"(type:%s) FAILED\n", priv->netdev->name, typestr); #else @@ -841,7 +1030,7 @@ acx_l_proc_output(char *buf, wlandevice_ FN_ENTER; p += sprintf(p, - "acx driver version:\t\t" WLAN_RELEASE "\n" + "acx driver version:\t\t" ACX_RELEASE "\n" "Wireless extension version:\t" STRING(WIRELESS_EXT) "\n" "chip name:\t\t\t%s (0x%08X)\n" "radio type:\t\t\t0x%02X\n" @@ -1157,7 +1346,7 @@ static const char * const proc_files[] = { "", "_diag", "_eeprom", "_phy" }; static read_proc_t * const -acx_proc_funcs[] = { +proc_funcs[] = { acx_e_read_proc, acx_e_read_proc_diag, acx_e_read_proc_eeprom, @@ -1172,15 +1361,16 @@ manage_proc_entries(const struct net_dev char procbuf[80]; int i; - for (i = 0; i < 4; i++) { - sprintf(procbuf, "driver/acx_%s", dev->name); - strcat(procbuf, proc_files[i]); + for (i = 0; i < VEC_SIZE(proc_files); i++) { + sprintf(procbuf, "driver/acx_%s%s", dev->name, proc_files[i]); if (!remove) { - acxlog(L_INIT, "creating /proc entry %s\n", procbuf); - if (!create_proc_read_entry(procbuf, 0, 0, acx_proc_funcs[i], priv)) + log(L_INIT, "creating /proc entry %s\n", procbuf); + if (!create_proc_read_entry(procbuf, 0, 0, proc_funcs[i], priv)) { + printk("acx: cannot register /proc entry %s\n", procbuf); return NOT_OK; + } } else { - acxlog(L_INIT, "removing /proc entry %s\n", procbuf); + log(L_INIT, "removing /proc entry %s\n", procbuf); remove_proc_entry(procbuf, NULL); } } @@ -1230,7 +1420,7 @@ bitpos2genframe_txrate[] = { /* Looks scary, eh? ** Actually, each one compiled into one AND and one SHIFT, ** 31 bytes in x86 asm (more if uints are replaced by u16/u8) */ -static unsigned int +static inline unsigned int rate111to5bits(unsigned int rate) { return (rate & 0x7) @@ -1246,6 +1436,9 @@ acx_s_cmd_join_bssid(wlandevice_t *priv, int dtim_interval; int i; + if (mac_is_zero(bssid)) + return; + FN_ENTER; dtim_interval = (ACX_MODE_0_ADHOC == priv->mode) ? @@ -1259,7 +1452,7 @@ acx_s_cmd_join_bssid(wlandevice_t *priv, tmp.beacon_interval = cpu_to_le16(priv->beacon_interval); - /* basic rate set. Control frame responses (such as ACK or CTS frames) + /* Basic rate set. Control frame responses (such as ACK or CTS frames) ** are sent with one of these rates */ if (IS_ACX111(priv)) { /* It was experimentally determined that rates_basic @@ -1268,15 +1461,14 @@ acx_s_cmd_join_bssid(wlandevice_t *priv, ** Just use RATE111_nnn constants... */ tmp.u.acx111.dtim_interval = dtim_interval; tmp.u.acx111.rates_basic = cpu_to_le16(priv->rate_basic); - acxlog(L_ASSOC, "%s rates_basic %04X, rates_supported %04X\n", - __func__, priv->rate_basic, priv->rate_oper); + log(L_ASSOC, "rates_basic:%04X, rates_supported:%04X\n", + priv->rate_basic, priv->rate_oper); } else { tmp.u.acx100.dtim_interval = dtim_interval; tmp.u.acx100.rates_basic = rate111to5bits(priv->rate_basic); tmp.u.acx100.rates_supported = rate111to5bits(priv->rate_oper); - acxlog(L_ASSOC, "%s rates_basic %04X->%02X, " - "rates_supported %04X->%02X\n", - __func__, + log(L_ASSOC, "rates_basic:%04X->%02X, " + "rates_supported:%04X->%02X\n", priv->rate_basic, tmp.u.acx100.rates_basic, priv->rate_oper, tmp.u.acx100.rates_supported); } @@ -1300,7 +1492,7 @@ acx_s_cmd_join_bssid(wlandevice_t *priv, memcpy(tmp.essid, priv->essid, tmp.essid_len); acx_s_issue_cmd(priv, ACX1xx_CMD_JOIN, &tmp, tmp.essid_len + 0x11); - acxlog(L_ASSOC|L_DEBUG, "BSS_Type = %u\n", tmp.macmode); + log(L_ASSOC|L_DEBUG, "BSS_Type = %u\n", tmp.macmode); acxlog_mac(L_ASSOC|L_DEBUG, "JoinBSSID MAC:", priv->bssid, "\n"); acx_update_capabilities(priv); @@ -1364,12 +1556,12 @@ acx_s_cmd_start_scan(wlandevice_t *priv) if (!(priv->irq_status & HOST_INT_SCAN_COMPLETE) && time_before(jiffies, priv->scan_start + 10*HZ) ) { - acxlog(L_INIT, "start_scan: seems like previous scan " + log(L_INIT, "start_scan: seems like previous scan " "is still running. Not starting anew. Please report\n"); return; } - acxlog(L_INIT, "starting radio scan\n"); + log(L_INIT, "starting radio scan\n"); /* remember that fw is commanded to do scan */ priv->scan_start = jiffies; CLEAR_BIT(priv->irq_status, HOST_INT_SCAN_COMPLETE); @@ -1400,7 +1592,7 @@ acx111_s_get_feature_config(wlandevice_t if (OK != acx_s_interrogate(priv, &fc, ACX1xx_IE_FEATURE_CONFIG)) { return NOT_OK; } - acxlog(L_DEBUG, + log(L_DEBUG, "got Feature option:0x%X, DataFlow option: 0x%X\n", fc.feature_options, fc.data_flow_options); @@ -1444,7 +1636,7 @@ acx111_s_set_feature_config(wlandevice_t SET_BIT(fc.data_flow_options, cpu_to_le32(data_flow_options)); } - acxlog(L_DEBUG, + log(L_DEBUG, "old: feature 0x%08X dataflow 0x%08X. mode: %u\n" "new: feature 0x%08X dataflow 0x%08X\n", feature_options, data_flow_options, mode, @@ -1506,7 +1698,7 @@ acx100_s_init_memory_pools(wlandevice_t memory pointers, i.e.: end-start/size */ TotalMemoryBlocks = (le32_to_cpu(mmt->PoolEnd) - le32_to_cpu(mmt->PoolStart)) / priv->memblocksize; - acxlog(L_DEBUG, "TotalMemoryBlocks=%u (%u bytes)\n", + log(L_DEBUG, "TotalMemoryBlocks=%u (%u bytes)\n", TotalMemoryBlocks, TotalMemoryBlocks*priv->memblocksize); /* MemoryConfigOption.DMA_config bitmask: @@ -1521,7 +1713,7 @@ acx100_s_init_memory_pools(wlandevice_t MemoryConfigOption.DMA_config = cpu_to_le32(0x30000); /* Declare start of the Rx host pool */ MemoryConfigOption.pRxHostDesc = cpu2acx(priv->rxhostdesc_startphy); - acxlog(L_DEBUG, "pRxHostDesc 0x%08X, rxhostdesc_startphy 0x%lX\n", + log(L_DEBUG, "pRxHostDesc 0x%08X, rxhostdesc_startphy 0x%lX\n", acx2cpu(MemoryConfigOption.pRxHostDesc), (long)priv->rxhostdesc_startphy); } else { @@ -1539,7 +1731,7 @@ acx100_s_init_memory_pools(wlandevice_t /* size of the tx and rx descriptor queues */ TotalTxBlockSize = TxBlockNum * priv->memblocksize; TotalRxBlockSize = RxBlockNum * priv->memblocksize; - acxlog(L_DEBUG, "TxBlockNum %u RxBlockNum %u TotalTxBlockSize %u " + log(L_DEBUG, "TxBlockNum %u RxBlockNum %u TotalTxBlockSize %u " "TotalTxBlockSize %u\n", TxBlockNum, RxBlockNum, TotalTxBlockSize, TotalRxBlockSize); @@ -1552,7 +1744,7 @@ acx100_s_init_memory_pools(wlandevice_t * and offset it by the tx descriptor queue */ MemoryConfigOption.tx_mem = cpu_to_le32((le32_to_cpu(mmt->PoolStart) + TotalRxBlockSize + 0x1f) & ~0x1f); - acxlog(L_DEBUG, "rx_mem %08X rx_mem %08X\n", + log(L_DEBUG, "rx_mem %08X rx_mem %08X\n", MemoryConfigOption.tx_mem, MemoryConfigOption.rx_mem); /* alert the device to our decision */ @@ -1596,7 +1788,7 @@ acx100_s_create_dma_regions(wlandevice_t tx_queue_start = le32_to_cpu(memmap.QueueStart); rx_queue_start = tx_queue_start + TX_CNT * sizeof(txdesc_t); - acxlog(L_DEBUG, "initializing Queue Indicator\n"); + log(L_DEBUG, "initializing Queue Indicator\n"); memset(&queueconf, 0, sizeof(queueconf)); @@ -1638,13 +1830,6 @@ acx100_s_create_dma_regions(wlandevice_t goto fail; } -/* [20050901] seems to be bogus. remove if no one complains */ -#if 0 /* #ifdef ACX_USB */ - if (OK != acx_s_configure(priv, &memmap, ACX1xx_IE_MEMORY_MAP)) { - goto fail; - } -#endif - memmap.PoolStart = cpu_to_le32( (le32_to_cpu(memmap.QueueEnd) + 4 + 0x1f) & ~0x1f ); @@ -1741,7 +1926,7 @@ acx111_s_create_dma_regions(wlandevice_t tx_queue_start = le32_to_cpu(queueconf.tx1_queue_address); rx_queue_start = le32_to_cpu(queueconf.rx1_queue_address); - acxlog(L_INIT, "dump queue head (from card):\n" + log(L_INIT, "dump queue head (from card):\n" "len: %u\n" "tx_memory_block_address: %X\n" "rx_memory_block_address: %X\n" @@ -1769,9 +1954,8 @@ fail: /*********************************************************************** ** acx_s_set_defaults -** Called from acx_s_init_mac */ -int +void acx_s_set_defaults(wlandevice_t *priv) { unsigned long flags; @@ -1786,7 +1970,7 @@ acx_s_set_defaults(wlandevice_t *priv) if (IS_ACX100(priv)) priv->get_mask |= GETSET_CCA|GETSET_ED_THRESH; - acx_s_update_card_settings(priv, 0, 0); + acx_s_update_card_settings(priv); acx_lock(priv, flags); @@ -1808,7 +1992,7 @@ acx_s_set_defaults(wlandevice_t *priv) /* we have a nick field to waste, so why not abuse it * to announce the driver version? ;-) */ - strncpy(priv->nick, "acx " WLAN_RELEASE, IW_ESSID_MAX_SIZE); + strncpy(priv->nick, "acx " ACX_RELEASE, IW_ESSID_MAX_SIZE); if (IS_PCI(priv)) { if (IS_ACX111(priv)) { @@ -1825,11 +2009,8 @@ acx_s_set_defaults(wlandevice_t *priv) /* 0xffff would be better, but then we won't get a "scan complete" * interrupt, so our current infrastructure will fail: */ priv->scan_count = 1; - priv->scan_mode = ACX_SCAN_OPT_PASSIVE; - /* Doesn't work for acx100, do it only for acx111 for now */ - if (IS_ACX111(priv)) { - priv->scan_mode = ACX_SCAN_OPT_ACTIVE; - } + priv->scan_mode = ACX_SCAN_OPT_ACTIVE; + priv->scan_duration = 100; priv->scan_probe_delay = 200; priv->scan_rate = ACX_SCAN_RATE_1; @@ -1913,8 +2094,7 @@ acx_s_set_defaults(wlandevice_t *priv) acx_s_initialize_rx_config(priv); - FN_EXIT1(OK); - return OK; + FN_EXIT0; } @@ -1945,7 +2125,7 @@ acx111_s_set_tx_level(wlandevice_t *priv priv->tx_level_dbm = 15; } if (level_dbm != priv->tx_level_dbm) - acxlog(L_INIT, "acx111 firmware has specific " + log(L_INIT, "acx111 firmware has specific " "power levels only: adjusted %d dBm to %d dBm!\n", level_dbm, priv->tx_level_dbm); @@ -1985,16 +2165,14 @@ acx111_s_get_tx_level(wlandevice_t *priv ** acx_s_init_mac */ int -acx_s_init_mac(netdevice_t *dev) +acx_s_init_mac(wlandevice_t *priv) { - wlandevice_t *priv = netdev_priv(dev); int result = NOT_OK; FN_ENTER; if (IS_PCI(priv)) { priv->memblocksize = 256; /* 256 is default */ - acxpci_init_mboxes(priv); /* try to load radio for both ACX100 and ACX111, since both * chips have at least some firmware versions making use of an * external radio module */ @@ -2011,35 +2189,29 @@ acx_s_init_mac(netdevice_t *dev) */ if (OK != acx111_s_init_packet_templates(priv)) goto fail; - if (OK != acx111_s_create_dma_regions(priv)) { printk("%s: acx111_create_dma_regions FAILED\n", - dev->name); + priv->netdev->name); goto fail; } -#ifdef DEBUG_WEP - /* don't decrypt WEP in firmware */ - if (OK != acx111_s_feature_on(priv, 0, FEATURE2_SNIFFER)) - goto fail; -#endif } else { if (OK != acx100_s_init_wep(priv)) goto fail; - acxlog(L_DEBUG, "between init_wep and init_packet_templates\n"); if (OK != acx100_s_init_packet_templates(priv)) goto fail; - if (OK != acx100_s_create_dma_regions(priv)) { printk("%s: acx100_create_dma_regions FAILED\n", - dev->name); + priv->netdev->name); goto fail; } } - MAC_COPY(dev->dev_addr, priv->dev_addr); + MAC_COPY(priv->netdev->dev_addr, priv->dev_addr); result = OK; fail: + if (result) + printk("acx: init_mac() FAILED\n"); FN_EXIT1(result); return result; } @@ -2067,7 +2239,7 @@ acx_l_rxmonitor(wlandevice_t *priv, cons skb_len = RXBUF_BYTES_USED(rxbuf) - payload_offset; /* sanity check */ - if (skb_len > WLAN_A4FR_MAXLEN_WEP) { + if (unlikely(skb_len > WLAN_A4FR_MAXLEN_WEP)) { printk("%s: monitor mode panic: oversized frame!\n", priv->netdev->name); goto end; @@ -2078,7 +2250,7 @@ acx_l_rxmonitor(wlandevice_t *priv, cons /* allocate skb */ skb = dev_alloc_skb(skb_len); - if (!skb) { + if (unlikely(!skb)) { printk("%s: no memory for skb (%u bytes)\n", priv->netdev->name, skb_len); goto end; @@ -2226,7 +2398,7 @@ acx_l_rx_ieee802_11_frame(wlandevice_t * hdr = acx_get_wlan_hdr(priv, rxbuf); /* see IEEE 802.11-1999.pdf chapter 7 "MAC frame formats" */ - if ((hdr->fc & WF_FC_PVERi) != 0) { + if (unlikely((hdr->fc & WF_FC_PVERi) != 0)) { printk_ratelimited(KERN_INFO "rx: unsupported 802.11 protocol\n"); goto end; } @@ -2310,15 +2482,15 @@ acx_l_process_rxbuf(wlandevice_t *priv, hdr = acx_get_wlan_hdr(priv, rxbuf); /* length of frame from control field to last byte of FCS */ - buf_len = RXBUF_BYTES_RCVD(rxbuf); fc = le16_to_cpu(hdr->fc); + buf_len = RXBUF_BYTES_RCVD(rxbuf); if ( ((WF_FC_FSTYPE & fc) != WF_FSTYPE_BEACON) || (acx_debug & L_XFER_BEACON) ) { - acxlog(L_XFER|L_DATA, "rx: %s " - "time %u len %u signal %u SNR %u macstat %02X " - "phystat %02X phyrate %u status %u\n", + log(L_XFER|L_DATA, "rx: %s " + "time:%u len:%u signal:%u SNR:%u macstat:%02X " + "phystat:%02X phyrate:%u status:%u\n", acx_get_packet_type_string(fc), le32_to_cpu(rxbuf->time), buf_len, @@ -2344,7 +2516,7 @@ acx_l_process_rxbuf(wlandevice_t *priv, } else if (likely(buf_len >= WLAN_HDR_A3_LEN)) { acx_l_rx_ieee802_11_frame(priv, rxbuf); } else { - acxlog(L_DEBUG|L_XFER|L_DATA, + log(L_DEBUG|L_XFER|L_DATA, "rx: NOT receiving packet (%s): " "size too small (%u)\n", acx_get_packet_type_string(fc), @@ -2384,6 +2556,156 @@ acx_l_process_rxbuf(wlandevice_t *priv, /*********************************************************************** +** acx_l_handle_txrate_auto +** +** Theory of operation: +** client->rate_cap is a bitmask of rates client is capable of. +** client->rate_cfg is a bitmask of allowed (configured) rates. +** It is set as a result of iwconfig rate N [auto] +** or iwpriv set_rates "N,N,N N,N,N" commands. +** It can be fixed (e.g. 0x0080 == 18Mbit only), +** auto (0x00ff == 18Mbit or any lower value), +** and code handles any bitmask (0x1081 == try 54Mbit,18Mbit,1Mbit _only_). +** +** client->rate_cur is a value for rate111 field in tx descriptor. +** It is always set to txrate_cfg sans zero or more most significant +** bits. This routine handles selection of new rate_cur value depending on +** outcome of last tx event. +** +** client->rate_100 is a precalculated rate value for acx100 +** (we can do without it, but will need to calculate it on each tx). +** +** You cannot configure mixed usage of 5.5 and/or 11Mbit rate +** with PBCC and CCK modulation. Either both at CCK or both at PBCC. +** In theory you can implement it, but so far it is considered not worth doing. +** +** 22Mbit, of course, is PBCC always. */ + +/* maps acx100 tx descr rate field to acx111 one */ +static u16 +rate100to111(u8 r) +{ + switch (r) { + case RATE100_1: return RATE111_1; + case RATE100_2: return RATE111_2; + case RATE100_5: + case (RATE100_5 | RATE100_PBCC511): return RATE111_5; + case RATE100_11: + case (RATE100_11 | RATE100_PBCC511): return RATE111_11; + case RATE100_22: return RATE111_22; + default: + printk("acx: unexpected acx100 txrate: %u! " + "Please report\n", r); + return RATE111_1; + } +} + + +void +acx_l_handle_txrate_auto(wlandevice_t *priv, struct client *txc, + u16 cur, u8 rate100, u16 rate111, + u8 error, int pkts_to_ignore) +{ + u16 sent_rate; + int slower_rate_was_used; + + /* vda: hmm. current code will do this: + ** 1. send packets at 11 Mbit, stepup++ + ** 2. will try to send at 22Mbit. hardware will see no ACK, + ** retries at 11Mbit, success. code notes that used rate + ** is lower. stepup = 0, fallback++ + ** 3. repeat step 2 fallback_count times. Fall back to + ** 11Mbit. go to step 1. + ** If stepup_count is large (say, 16) and fallback_count + ** is small (3), this wouldn't be too bad wrt throughput */ + + if (unlikely(!cur)) { + printk("acx: BUG! ratemask is empty\n"); + return; /* or else we may lock up the box */ + } + + /* do some preparations, i.e. calculate the one rate that was + * used to send this packet */ + if (IS_ACX111(priv)) { + sent_rate = 1 << highest_bit(rate111 & RATE111_ALL); + } else { + sent_rate = rate100to111(rate100); + } + /* sent_rate has only one bit set now, corresponding to tx rate + * which was used by hardware to tx this particular packet */ + + /* now do the actual auto rate management */ + log(L_XFER, "tx: %sclient=%p/"MACSTR" used=%04X cur=%04X cfg=%04X " + "__=%u/%u ^^=%u/%u\n", + (txc->ignore_count > 0) ? "[IGN] " : "", + txc, MAC(txc->address), sent_rate, cur, txc->rate_cfg, + txc->fallback_count, priv->fallback_threshold, + txc->stepup_count, priv->stepup_threshold + ); + + /* we need to ignore old packets already in the tx queue since + * they use older rate bytes configured before our last rate change, + * otherwise our mechanism will get confused by interpreting old data. + * Do it after logging above */ + if (txc->ignore_count) { + txc->ignore_count--; + return; + } + + /* true only if the only nonzero bit in sent_rate is + ** less significant than highest nonzero bit in cur */ + slower_rate_was_used = ( cur > ((sent_rate<<1)-1) ); + + if (slower_rate_was_used || error) { + txc->stepup_count = 0; + if (++txc->fallback_count <= priv->fallback_threshold) + return; + txc->fallback_count = 0; + + /* clear highest 1 bit in cur */ + sent_rate = RATE111_54; + while (!(cur & sent_rate)) sent_rate >>= 1; + CLEAR_BIT(cur, sent_rate); + if (!cur) /* we can't disable all rates! */ + cur = sent_rate; + log(L_XFER, "tx: falling back to ratemask %04X\n", cur); + + } else { /* there was neither lower rate nor error */ + txc->fallback_count = 0; + if (++txc->stepup_count <= priv->stepup_threshold) + return; + txc->stepup_count = 0; + + /* Sanitize. Sort of not needed, but I dont trust hw that much... + ** what if it can report bogus tx rates sometimes? */ + while (!(cur & sent_rate)) sent_rate >>= 1; + + /* try to find a higher sent_rate that isn't yet in our + * current set, but is an allowed cfg */ + while (1) { + sent_rate <<= 1; + if (sent_rate > txc->rate_cfg) + /* no higher rates allowed by config */ + return; + if (!(cur & sent_rate) && (txc->rate_cfg & sent_rate)) + /* found */ + break; + /* not found, try higher one */ + } + SET_BIT(cur, sent_rate); + log(L_XFER, "tx: stepping up to ratemask %04X\n", cur); + } + + txc->rate_cur = cur; + txc->ignore_count = pkts_to_ignore; + /* calculate acx100 style rate byte if needed */ + if (IS_ACX100(priv)) { + txc->rate_100 = acx_bitpos2rate100[highest_bit(cur)]; + } +} + + +/*********************************************************************** ** acx_i_start_xmit ** ** Called by network core. Can be called outside of process context. @@ -2418,11 +2740,11 @@ acx_i_start_xmit(struct sk_buff *skb, ne goto end; } if (unlikely(acx_queue_stopped(dev))) { - acxlog(L_DEBUG, "%s: called when queue stopped\n", __func__); + log(L_DEBUG, "%s: called when queue stopped\n", __func__); goto end; } if (unlikely(ACX_STATUS_4_ASSOCIATED != priv->status)) { - acxlog(L_XFER, "trying to xmit, but not associated yet: " + log(L_XFER, "trying to xmit, but not associated yet: " "aborting...\n"); /* silently drop the packet, since we're not connected yet */ txresult = OK; @@ -2433,22 +2755,24 @@ acx_i_start_xmit(struct sk_buff *skb, ne tx = acx_l_alloc_tx(priv); if (unlikely(!tx)) { - printk("%s: start_xmit: txdesc ring is full, dropping tx\n", - dev->name); + printk_ratelimited("%s: start_xmit: txdesc ring is full, " + "dropping tx\n", dev->name); txresult = NOT_OK; goto end; } txbuf = acx_l_get_txbuf(priv, tx); - if (!txbuf) { + if (unlikely(!txbuf)) { /* Card was removed */ txresult = NOT_OK; + acx_l_dealloc_tx(priv, tx); goto end; } len = acx_ether_to_txbuf(priv, txbuf, skb); - if (len < 0) { + if (unlikely(len < 0)) { /* Error in packet conversion */ txresult = NOT_OK; + acx_l_dealloc_tx(priv, tx); goto end; } acx_l_tx_data(priv, tx, len); @@ -2476,7 +2800,7 @@ end_no_unlock: ** Updates priv->rate_supported[_len] according to rate_{basic,oper} */ const u8 -bitpos2ratebyte[] = { +acx_bitpos2ratebyte[] = { DOT11RATEBYTE_1, DOT11RATEBYTE_2, DOT11RATEBYTE_5_5, @@ -2498,7 +2822,7 @@ acx_l_update_ratevector(wlandevice_t *pr u16 bcfg = priv->rate_basic; u16 ocfg = priv->rate_oper; u8 *supp = priv->rate_supported; - const u8 *dot11 = bitpos2ratebyte; + const u8 *dot11 = acx_bitpos2ratebyte; FN_ENTER; @@ -2704,7 +3028,7 @@ acx_set_status(wlandevice_t *priv, u16 n FN_ENTER; - acxlog(L_ASSOC, "%s(%d):%s\n", + log(L_ASSOC, "%s(%d):%s\n", __func__, new_status, acx_get_status_name(new_status)); #if WIRELESS_EXT > 13 /* wireless_send_event() and SIOCGIWSCAN */ @@ -2781,7 +3105,7 @@ acx_i_timer(unsigned long address) acx_lock(priv, flags); - acxlog(L_DEBUG|L_ASSOC, "%s: priv->status=%d (%s)\n", + log(L_DEBUG|L_ASSOC, "%s: priv->status=%d (%s)\n", __func__, priv->status, acx_get_status_name(priv->status)); switch (priv->status) { @@ -2791,10 +3115,10 @@ acx_i_timer(unsigned long address) acx_set_timer(priv, 1000000); /* used to interrogate for scan status. ** We rely on SCAN_COMPLETE IRQ instead */ - acxlog(L_ASSOC, "continuing scan (%d sec)\n", + log(L_ASSOC, "continuing scan (%d sec)\n", priv->scan_retries); } else { - acxlog(L_ASSOC, "stopping scan\n"); + log(L_ASSOC, "stopping scan\n"); /* send stop_scan cmd when we leave the interrupt context, * and make a decision what to do next (COMPLETE_SCAN) */ acx_schedule_task(priv, @@ -2804,12 +3128,12 @@ acx_i_timer(unsigned long address) case ACX_STATUS_2_WAIT_AUTH: /* was set to 0 by set_status() */ if (++priv->auth_or_assoc_retries < 10) { - acxlog(L_ASSOC, "resend authen1 request (attempt %d)\n", + log(L_ASSOC, "resend authen1 request (attempt %d)\n", priv->auth_or_assoc_retries + 1); acx_l_transmit_authen1(priv); } else { /* time exceeded: fall back to scanning mode */ - acxlog(L_ASSOC, + log(L_ASSOC, "authen1 request reply timeout, giving up\n"); /* we are a STA, need to find AP anyhow */ acx_set_status(priv, ACX_STATUS_1_SCANNING); @@ -2821,12 +3145,12 @@ acx_i_timer(unsigned long address) case ACX_STATUS_3_AUTHENTICATED: /* was set to 0 by set_status() */ if (++priv->auth_or_assoc_retries < 10) { - acxlog(L_ASSOC, "resend assoc request (attempt %d)\n", + log(L_ASSOC, "resend assoc request (attempt %d)\n", priv->auth_or_assoc_retries + 1); acx_l_transmit_assoc_req(priv); } else { /* time exceeded: give up */ - acxlog(L_ASSOC, + log(L_ASSOC, "association request reply timeout, giving up\n"); /* we are a STA, need to find AP anyhow */ acx_set_status(priv, ACX_STATUS_1_SCANNING); @@ -2855,7 +3179,7 @@ acx_set_timer(wlandevice_t *priv, int ti { FN_ENTER; - acxlog(L_DEBUG|L_IRQ, "%s(%u ms)\n", __func__, timeout_us/1000); + log(L_DEBUG|L_IRQ, "%s(%u ms)\n", __func__, timeout_us/1000); if (!(priv->dev_state_mask & ACX_STATE_IFACE_UP)) { printk("attempt to set the timer " "when the card interface is not up!\n"); @@ -2894,7 +3218,7 @@ dot11ratebyte[] = { DOT11RATEBYTE_54_G, }; -static int +static inline int find_pos(const u8 *p, int size, u8 v) { int i; @@ -2951,10 +3275,10 @@ acx_l_transmit_assocresp(wlandevice_t *p clt->used = CLIENT_ASSOCIATED_3; - if (clt->aid == 0) { + if (clt->aid == 0) clt->aid = ++priv->aid; - } clt->cap_info = ieee2host16(*(req->cap_info)); + /* We cheat here a bit. We don't really care which rates are flagged ** as basic by the client, so we stuff them in single ratemask */ clt->rate_cap = 0; @@ -2969,6 +3293,8 @@ acx_l_transmit_assocresp(wlandevice_t *p clt->rate_cfg = clt->rate_cap & priv->rate_oper; if (!clt->rate_cfg) clt->rate_cfg = 1 << lowest_bit(priv->rate_oper); clt->rate_cur = 1 << lowest_bit(clt->rate_cfg); + if (IS_ACX100(priv)) + clt->rate_100 = acx_bitpos2rate100[lowest_bit(clt->rate_cfg)]; clt->fallback_count = clt->stepup_count = 0; clt->ignore_count = 16; @@ -2976,14 +3302,15 @@ acx_l_transmit_assocresp(wlandevice_t *p if (!tx) goto bad; head = acx_l_get_txbuf(priv, tx); - if (!head) + if (!head) { + acx_l_dealloc_tx(priv, tx); goto bad; + } body = (void*)(head + 1); head->fc = WF_FSTYPE_ASSOCRESPi; head->dur = req->hdr->dur; MAC_COPY(head->da, da); - /* MAC_COPY(head->sa, sa); */ MAC_COPY(head->sa, priv->dev_addr); MAC_COPY(head->bssid, bssid); head->seq = req->hdr->seq; @@ -3136,6 +3463,7 @@ acx_l_transmit_reassocresp(wlandevice_t } if (req->cap_info) clt->cap_info = ieee2host16(*(req->cap_info)); + /* We cheat here a bit. We don't really care which rates are flagged ** as basic by the client, so we stuff them in single ratemask */ clt->rate_cap = 0; @@ -3150,6 +3478,9 @@ acx_l_transmit_reassocresp(wlandevice_t clt->rate_cfg = clt->rate_cap & priv->rate_oper; if (!clt->rate_cfg) clt->rate_cfg = 1 << lowest_bit(priv->rate_oper); clt->rate_cur = 1 << lowest_bit(clt->rate_cfg); + if (IS_ACX100(priv)) + clt->rate_100 = acx_bitpos2rate100[lowest_bit(clt->rate_cfg)]; + clt->fallback_count = clt->stepup_count = 0; clt->ignore_count = 16; @@ -3157,14 +3488,15 @@ acx_l_transmit_reassocresp(wlandevice_t if (!tx) goto ok; head = acx_l_get_txbuf(priv, tx); - if (!head) + if (!head) { + acx_l_dealloc_tx(priv, tx); goto ok; + } body = (void*)(head + 1); head->fc = WF_FSTYPE_REASSOCRESPi; head->dur = req->hdr->dur; MAC_COPY(head->da, da); - /* MAC_COPY(head->sa, sa); */ MAC_COPY(head->sa, priv->dev_addr); MAC_COPY(head->bssid, bssid); head->seq = req->hdr->seq; @@ -3275,10 +3607,14 @@ acx_l_process_disassoc_from_ap(wlandevic /* Hrm, we aren't assoc'ed yet anyhow... */ goto end; } + + printk("%s: got disassoc frame with reason %d (%s)\n", + priv->netdev->name, *req->reason, + acx_wlan_reason_str(*req->reason)); + if (mac_is_equal(priv->dev_addr, req->hdr->a1)) { acx_l_transmit_deauthen(priv, priv->bssid, WLAN_MGMT_REASON_DEAUTH_LEAVING); - /* Start scan anew */ SET_BIT(priv->set_mask, GETSET_RESCAN); acx_schedule_task(priv, ACX_AFTER_IRQ_UPDATE_CARD_CFG); } @@ -3299,10 +3635,14 @@ acx_l_process_deauth_from_ap(wlandevice_ /* Hrm, we aren't assoc'ed yet anyhow... */ goto end; } + + printk("%s: got deauth frame with reason %d (%s)\n", + priv->netdev->name, *req->reason, + acx_wlan_reason_str(*req->reason)); + /* Chk: is ta is verified to be from our AP? */ if (mac_is_equal(priv->dev_addr, req->hdr->a1)) { - acxlog(L_DEBUG, "AP sent us deauth packet\n"); - /* not needed: acx_set_status(priv, ACX_STATUS_1_SCANNING) */ + log(L_DEBUG, "AP sent us deauth packet\n"); SET_BIT(priv->set_mask, GETSET_RESCAN); acx_schedule_task(priv, ACX_AFTER_IRQ_UPDATE_CARD_CFG); } @@ -3358,12 +3698,12 @@ acx_l_process_data_frame_master(wlandevi switch (WF_FC_FROMTODSi & hdr->fc) { case 0: case WF_FC_FROMDSi: - acxlog(L_DEBUG, "ap->sta or adhoc->adhoc data frame ignored\n"); + log(L_DEBUG, "ap->sta or adhoc->adhoc data frame ignored\n"); goto done; case WF_FC_TODSi: break; default: /* WF_FC_FROMTODSi */ - acxlog(L_DEBUG, "wds data frame ignored (todo)\n"); + log(L_DEBUG, "wds data frame ignored (todo)\n"); goto done; } @@ -3397,6 +3737,8 @@ acx_l_process_data_frame_master(wlandevi if (txbuf) { memcpy(txbuf, &rxbuf->hdr_a3, len); acx_l_tx_data(priv, tx, len); + } else { + acx_l_dealloc_tx(priv, tx); } } done: @@ -3428,23 +3770,23 @@ acx_l_process_data_frame_client(wlandevi switch (WF_FC_FROMTODSi & hdr->fc) { case 0: if (priv->mode != ACX_MODE_0_ADHOC) { - acxlog(L_DEBUG, "adhoc->adhoc data frame ignored\n"); + log(L_DEBUG, "adhoc->adhoc data frame ignored\n"); goto drop; } bssid = hdr->a3; break; case WF_FC_FROMDSi: if (priv->mode != ACX_MODE_2_STA) { - acxlog(L_DEBUG, "ap->sta data frame ignored\n"); + log(L_DEBUG, "ap->sta data frame ignored\n"); goto drop; } bssid = hdr->a2; break; case WF_FC_TODSi: - acxlog(L_DEBUG, "sta->ap data frame ignored\n"); + log(L_DEBUG, "sta->ap data frame ignored\n"); goto drop; default: /* WF_FC_FROMTODSi: wds->wds */ - acxlog(L_DEBUG, "wds data frame ignored (todo)\n"); + log(L_DEBUG, "wds data frame ignored (todo)\n"); goto drop; } @@ -3485,14 +3827,14 @@ acx_l_process_data_frame_client(wlandevi /* FIXME: check against the list of * multicast addresses that are configured * for the interface (ifconfig) */ - acxlog(L_XFER, "FIXME: multicast packet, need to check " + log(L_XFER, "FIXME: multicast packet, need to check " "against a list of multicast addresses " "(to be created!); accepting packet for now\n"); /* for now, just accept it here */ goto process; } - acxlog(L_DEBUG, "rx: foreign packet, dropping\n"); + log(L_DEBUG, "rx: foreign packet, dropping\n"); goto drop; process: /* receive packet */ @@ -3736,11 +4078,11 @@ acx_l_process_NULL_frame(wlandevice_t *p result = NOT_OK; else { #ifdef IS_IT_BROKEN - acxlog(L_DEBUG|L_XFER, "\n"); + log(L_DEBUG|L_XFER, "\n"); acx_l_transmit_deauthen(priv, ebx, WLAN_MGMT_REASON_CLASS2_NONAUTH); #else - acxlog(L_DEBUG, "received NULL frame from unknown client! " + log(L_DEBUG, "received NULL frame from unknown client! " "We really shouldn't send deauthen here, right?\n"); #endif result = OK; @@ -3766,7 +4108,7 @@ acx_l_process_probe_response(wlandevice_ hdr = req->hdr; if (mac_is_equal(hdr->a3, priv->dev_addr)) { - acxlog(L_ASSOC, "huh, scan found our own MAC!?\n"); + log(L_ASSOC, "huh, scan found our own MAC!?\n"); goto ok; /* just skip this one silently */ } @@ -3824,7 +4166,7 @@ acx_l_process_probe_response(wlandevice_ bss->rate_cur = 1 << lowest_bit(bss->rate_bas); /* People moan about this being too noisy at L_ASSOC */ - acxlog(L_DEBUG, + log(L_DEBUG, "found %s: ESSID='%s' ch=%d " "BSSID="MACSTR" caps=0x%04X SIR=%d SNR=%d\n", (bss->cap_info & WF_MGMT_CAP_IBSS) ? "Ad-Hoc peer" : "AP", @@ -3853,11 +4195,13 @@ acx_l_process_assocresp(wlandevice_t *pr u16 st = ieee2host16(*(req->status)); if (WLAN_MGMT_STATUS_SUCCESS == st) { priv->aid = ieee2host16(*(req->aid)); - /* tell the card we are associated when we are out of interrupt context */ + /* tell the card we are associated when + ** we are out of interrupt context */ acx_schedule_task(priv, ACX_AFTER_IRQ_CMD_ASSOCIATE); } else { - /* TODO: we shall delete peer from sta_list, and try other candidates... */ + /* TODO: we shall delete peer from sta_list, and try + ** other candidates... */ printk("%s: association FAILED: peer sent " "response code %d (%s)\n", @@ -3942,18 +4286,18 @@ acx_l_process_authen(wlandevice_t *priv, if (priv->auth_alg <= 1) { if (priv->auth_alg != alg) { - acxlog(L_ASSOC, "authentication algorithm mismatch: " - "want: %d, req: %d\n", priv->auth_alg, alg); + log(L_ASSOC, "auth algorithm mismatch: " + "our:%d peer:%d\n", priv->auth_alg, alg); result = NOT_OK; goto end; } } - acxlog(L_ASSOC, "algorithm is ok\n"); + log(L_ASSOC, "algorithm is ok\n"); if (ap) { clt = acx_l_sta_list_get_or_add(priv, hdr->a2); if (STA_LIST_ADD_CAN_FAIL && !clt) { - acxlog(L_ASSOC, "could not allocate room for client\n"); + log(L_ASSOC, "could not allocate room for client\n"); result = NOT_OK; goto end; } @@ -3969,7 +4313,7 @@ acx_l_process_authen(wlandevice_t *priv, /* now check which step in the authentication sequence we are * currently in, and act accordingly */ - acxlog(L_ASSOC, "acx_process_authen auth seq step %d\n", seq); + log(L_ASSOC, "acx_process_authen auth seq step %d\n", seq); switch (seq) { case 1: if (!ap) @@ -4021,7 +4365,7 @@ acx_l_process_authen(wlandevice_t *priv, break; /* ok, we're through: we're authenticated. Woohoo!! */ acx_set_status(priv, ACX_STATUS_3_AUTHENTICATED); - acxlog(L_ASSOC, "Authenticated!\n"); + log(L_ASSOC, "Authenticated!\n"); /* now that we're authenticated, request association */ acx_l_transmit_assoc_req(priv); break; @@ -4063,8 +4407,10 @@ acx_l_transmit_deauthen(wlandevice_t *pr if (!tx) goto bad; head = acx_l_get_txbuf(priv, tx); - if (!head) + if (!head) { + acx_l_dealloc_tx(priv, tx); goto bad; + } body = (void*)(head + 1); head->fc = (WF_FTYPE_MGMTi | WF_FSTYPE_DEAUTHENi); @@ -4074,7 +4420,7 @@ acx_l_transmit_deauthen(wlandevice_t *pr MAC_COPY(head->bssid, priv->bssid); head->seq = 0; - acxlog(L_DEBUG|L_ASSOC|L_XFER, + log(L_DEBUG|L_ASSOC|L_XFER, "sending deauthen to "MACSTR" for %d\n", MAC(addr), reason); @@ -4104,15 +4450,17 @@ acx_l_transmit_authen1(wlandevice_t *pri FN_ENTER; - acxlog(L_ASSOC, "Sending authentication1 request, " - "awaiting response!\n"); + log(L_ASSOC, "sending authentication1 request, " + "awaiting response\n"); tx = acx_l_alloc_tx(priv); if (!tx) goto bad; head = acx_l_get_txbuf(priv, tx); - if (!head) + if (!head) { + acx_l_dealloc_tx(priv, tx); goto bad; + } body = (void*)(head + 1); head->fc = WF_FSTYPE_AUTHENi; @@ -4165,14 +4513,15 @@ acx_l_transmit_authen2(wlandevice_t *pri if (!tx) goto bad; head = acx_l_get_txbuf(priv, tx); - if (!head) + if (!head) { + acx_l_dealloc_tx(priv, tx); goto bad; + } body = (void*)(head + 1); - head->fc = WF_FSTYPE_AUTHENi; /* 0xb0 */ + head->fc = WF_FSTYPE_AUTHENi; head->dur = req->hdr->dur; MAC_COPY(head->da, req->hdr->a2); - /* MAC_COPY(head->sa, req->hdr->a1); */ MAC_COPY(head->sa, priv->dev_addr); MAC_COPY(head->bssid, req->hdr->a3); head->seq = req->hdr->seq; @@ -4221,8 +4570,10 @@ acx_l_transmit_authen3(wlandevice_t *pri if (!tx) goto ok; head = acx_l_get_txbuf(priv, tx); - if (!head) + if (!head) { + acx_l_dealloc_tx(priv, tx); goto ok; + } body = (void*)(head + 1); head->fc = WF_FC_ISWEPi + WF_FSTYPE_AUTHENi; @@ -4241,7 +4592,7 @@ acx_l_transmit_authen3(wlandevice_t *pri memcpy(&body->challenge, req->challenge, req->challenge->len + 2); packet_len = WLAN_HDR_A3_LEN + 8 + req->challenge->len; - acxlog(L_ASSOC|L_XFER, "transmit_authen3!\n"); + log(L_ASSOC|L_XFER, "transmit_authen3!\n"); acx_l_tx_data(priv, tx, packet_len); ok: @@ -4266,14 +4617,15 @@ acx_l_transmit_authen4(wlandevice_t *pri if (!tx) goto ok; head = acx_l_get_txbuf(priv, tx); - if (!head) + if (!head) { + acx_l_dealloc_tx(priv, tx); goto ok; + } body = (void*)(head + 1); head->fc = WF_FSTYPE_AUTHENi; /* 0xb0 */ head->dur = req->hdr->dur; MAC_COPY(head->da, req->hdr->a2); - /* MAC_COPY(head->sa, req->hdr->a1); */ MAC_COPY(head->sa, priv->dev_addr); MAC_COPY(head->bssid, req->hdr->a3); head->seq = req->hdr->seq; @@ -4306,14 +4658,16 @@ acx_l_transmit_assoc_req(wlandevice_t *p FN_ENTER; - acxlog(L_ASSOC, "sending association request, " + log(L_ASSOC, "sending association request, " "awaiting response. NOT ASSOCIATED YET\n"); tx = acx_l_alloc_tx(priv); if (!tx) goto bad; head = acx_l_get_txbuf(priv, tx); - if (!head) + if (!head) { + acx_l_dealloc_tx(priv, tx); goto bad; + } body = (void*)(head + 1); head->fc = WF_FSTYPE_ASSOCREQi; @@ -4387,7 +4741,7 @@ acx_l_transmit_assoc_req(wlandevice_t *p /* calculate lengths */ packet_len = WLAN_HDR_A3_LEN + (p - body); - acxlog(L_ASSOC, "association: requesting caps 0x%04X, ESSID '%s'\n", + log(L_ASSOC, "association: requesting caps 0x%04X, ESSID '%s'\n", cap, priv->essid_for_assoc); acx_l_tx_data(priv, tx, packet_len); @@ -4420,8 +4774,10 @@ acx_l_transmit_disassoc(wlandevice_t *pr if (!tx) goto bad; head = acx_l_get_txbuf(priv, tx); - if (!head) + if (!head) { + acx_l_dealloc_tx(priv, tx); goto bad; + } body = (void*)(head + 1); /* clt->used = CLIENT_AUTHENTICATED_2; - not (yet?) associated */ @@ -4502,7 +4858,7 @@ acx_s_complete_scan(wlandevice_t *priv) bss = &priv->sta_list[i]; if (!bss->used) continue; - acxlog(L_ASSOC, "Scan Table: SSID='%s' CH=%d SIR=%d SNR=%d\n", + log(L_ASSOC, "scan table: SSID='%s' CH=%d SIR=%d SNR=%d\n", bss->essid, bss->channel, bss->sir, bss->snr); if (!mac_is_bcast(priv->ap)) @@ -4517,7 +4873,7 @@ acx_s_complete_scan(wlandevice_t *priv) priv->netdev->name, MAC(bss->address)); continue; } - acxlog(L_ASSOC, "peer_cap 0x%04X, needed_cap 0x%04X\n", + log(L_ASSOC, "peer_cap 0x%04X, needed_cap 0x%04X\n", bss->cap_info, needed_cap); /* does peer station support what we need? */ @@ -4564,7 +4920,7 @@ acx_s_complete_scan(wlandevice_t *priv) } if (!priv->essid_active || !strcmp(bss->essid, priv->essid)) { - acxlog(L_ASSOC, + log(L_ASSOC, "found station with matching ESSID! ('%s' " "station, '%s' config)\n", bss->essid, @@ -4592,12 +4948,12 @@ acx_s_complete_scan(wlandevice_t *priv) bss->used = CLIENT_JOIN_CANDIDATE; if (idx_found == -1) idx_found = i; - acxlog(L_ASSOC, "found station with empty or " + log(L_ASSOC, "found station with empty or " "single-space (hidden) SSID, considering " "for assoc attempt\n"); /* ...and keep looking for better matches */ } else { - acxlog(L_ASSOC, "ESSID doesn't match! ('%s' " + log(L_ASSOC, "ESSID doesn't match! ('%s' " "station, '%s' config)\n", bss->essid, (priv->essid_active) ? priv->essid : "[any]"); @@ -4663,7 +5019,7 @@ acx_s_complete_scan(wlandevice_t *priv) } else { /* we shall scan again, AP can be ** just temporarily powered off */ - acxlog(L_ASSOC, + log(L_ASSOC, "no matching station found in range yet\n"); acx_set_status(priv, ACX_STATUS_1_SCANNING); result = NOT_OK; @@ -4677,7 +5033,7 @@ acx_s_complete_scan(wlandevice_t *priv) /* need to update channel in beacon template */ SET_BIT(priv->set_mask, SET_TEMPLATES); if (ACX_STATE_IFACE_UP & priv->dev_state_mask) - acx_s_update_card_settings(priv, 0, 0); + acx_s_update_card_settings(priv); } /* Inform firmware on our decision to start or join BSS */ acx_s_cmd_join_bssid(priv, priv->bssid); @@ -4723,7 +5079,7 @@ acx_s_read_fw(const char *file, u32 *siz const struct firmware *fw_entry; res = NULL; - acxlog(L_INIT, "requesting firmware image '%s'\n", file); + log(L_INIT, "requesting firmware image '%s'\n", file); if (!request_firmware(&fw_entry, file, dev)) { *size = 8; if (fw_entry->size >= 8) @@ -4772,12 +5128,12 @@ release_ret: } if (!firmware_dir) { firmware_dir = "/usr/share/acx"; - acxlog(L_DEBUG, "no firmware directory specified " + log(L_DEBUG, "no firmware directory specified " "via module parameter firmware_dir, " "using default %s\n", firmware_dir); } snprintf(filename, PATH_MAX, "%s/%s", firmware_dir, file); - acxlog(L_INIT, "reading firmware image '%s'\n", filename); + log(L_INIT, "reading firmware image '%s'\n", filename); buffer = (char*)page; @@ -4843,7 +5199,7 @@ release_ret: *size); goto fail_close; } - acxlog(L_DEBUG, "allocated %u bytes " + log(L_DEBUG, "allocated %u bytes " "for firmware module loading\n", *size); } @@ -4919,7 +5275,7 @@ acx100_s_set_wepkey(wlandevice_t *priv) for (i = 0; i < DOT11_MAX_DEFAULT_WEP_KEYS; i++) { if (priv->wep_keys[i].size != 0) { - acxlog(L_INIT, "setting WEP key: %d with " + log(L_INIT, "setting WEP key: %d with " "total size: %d\n", i, (int) priv->wep_keys[i].size); dk.action = 1; dk.keySize = priv->wep_keys[i].size; @@ -4938,7 +5294,7 @@ acx111_s_set_wepkey(wlandevice_t *priv) for (i = 0; i < DOT11_MAX_DEFAULT_WEP_KEYS; i++) { if (priv->wep_keys[i].size != 0) { - acxlog(L_INIT, "setting WEP key: %d with " + log(L_INIT, "setting WEP key: %d with " "total size: %d\n", i, (int) priv->wep_keys[i].size); memset(&dk, 0, sizeof(dk)); dk.action = cpu_to_le16(1); /* "add key"; yes, that's a 16bit value */ @@ -4975,8 +5331,6 @@ acx_s_set_wepkey(wlandevice_t *priv) int acx100_s_init_wep(wlandevice_t *priv) { -/* int i; - acx100_cmd_wep_mgmt_t wep_mgmt; size = 37 bytes */ acx100_ie_wep_options_t options; ie_dot11WEPDefaultKeyID_t dk; acx_ie_memmap_t pt; @@ -4988,7 +5342,7 @@ acx100_s_init_wep(wlandevice_t *priv) goto fail; } - acxlog(L_DEBUG, "CodeEnd:%X\n", pt.CodeEnd); + log(L_DEBUG, "CodeEnd:%X\n", pt.CodeEnd); pt.WEPCacheStart = cpu_to_le32(le32_to_cpu(pt.CodeEnd) + 0x4); pt.WEPCacheEnd = cpu_to_le32(le32_to_cpu(pt.CodeEnd) + 0x4); @@ -5001,13 +5355,13 @@ acx100_s_init_wep(wlandevice_t *priv) options.NumKeys = cpu_to_le16(DOT11_MAX_DEFAULT_WEP_KEYS + 10); options.WEPOption = 0x00; - acxlog(L_ASSOC, "%s: writing WEP options\n", __func__); + log(L_ASSOC, "%s: writing WEP options\n", __func__); acx_s_configure(priv, &options, ACX100_IE_WEP_OPTIONS); acx100_s_set_wepkey(priv); if (priv->wep_keys[priv->wep_current_index].size != 0) { - acxlog(L_ASSOC, "setting active default WEP key number: %d\n", + log(L_ASSOC, "setting active default WEP key number: %d\n", priv->wep_current_index); dk.KeyID = priv->wep_current_index; acx_s_configure(priv, &dk, ACX1xx_IE_DOT11_WEP_DEFAULT_KEY_SET); /* 0x1010 */ @@ -5020,12 +5374,13 @@ acx100_s_init_wep(wlandevice_t *priv) wep_mgmt.KeySize = cpu_to_le16(priv->wep_key_struct[i].len); memcpy(&wep_mgmt.Key, priv->wep_key_struct[i].key, le16_to_cpu(wep_mgmt.KeySize)); wep_mgmt.Action = cpu_to_le16(1); - acxlog(L_ASSOC, "writing WEP key %d (len %d)\n", i, le16_to_cpu(wep_mgmt.KeySize)); + log(L_ASSOC, "writing WEP key %d (len %d)\n", i, le16_to_cpu(wep_mgmt.KeySize)); if (OK == acx_s_issue_cmd(priv, ACX1xx_CMD_WEP_MGMT, &wep_mgmt, sizeof(wep_mgmt))) { priv->wep_key_struct[i].index = i; } } - } */ + } +*/ /* now retrieve the updated WEPCacheEnd pointer... */ if (OK != acx_s_interrogate(priv, &pt, ACX1xx_IE_MEMORY_MAP)) { @@ -5120,15 +5475,12 @@ acx_s_init_max_probe_response_template(w static int acx_s_init_max_probe_request_template(wlandevice_t *priv) { - union { - acx100_template_probereq_t p100; - acx111_template_probereq_t p111; - } pr; int res; + acx_template_probereq_t pr; FN_ENTER; memset(&pr, 0, sizeof(pr)); - pr.p100.size = cpu_to_le16(sizeof(pr) - 2); + pr.size = cpu_to_le16(sizeof(pr) - 2); res = acx_s_issue_cmd(priv, ACX1xx_CMD_CONFIG_PROBE_REQUEST, &pr, sizeof(pr)); FN_EXIT1(res); return res; @@ -5329,20 +5681,13 @@ acx100_s_init_packet_templates(wlandevic FN_ENTER; - acxlog(L_DEBUG, "sizeof(memmap)=%d bytes\n", (int)sizeof(mm)); + log(L_DEBUG, "sizeof(memmap)=%d bytes\n", (int)sizeof(mm)); - /* acx100 still do not emit probe requests, thus this call - ** is sourt of not needed. But we want it to work someday */ if (OK != acx_s_init_max_probe_request_template(priv)) goto failed; -#ifdef NOT_WORKING_YET - /* FIXME: creating the NULL data template breaks - * communication right now, needs further testing. - * Also, need to set the template once we're joining a network. */ if (OK != acx_s_init_max_null_data_template(priv)) goto failed; -#endif if (OK != acx_s_init_max_beacon_template(priv)) goto failed; @@ -5369,9 +5714,9 @@ acx100_s_init_packet_templates(wlandevic goto success; failed: - acxlog(L_DEBUG|L_INIT, + log(L_DEBUG|L_INIT, /* "cb=0x%X\n" */ - "pACXMemoryMap:\n" + "ACXMemoryMap:\n" ".CodeStart=0x%X\n" ".CodeEnd=0x%X\n" ".WEPCacheStart=0x%X\n" @@ -5398,7 +5743,7 @@ acx111_s_init_packet_templates(wlandevic FN_ENTER; - acxlog(L_DEBUG|L_INIT, "initializing max packet templates\n"); + log(L_DEBUG|L_INIT, "initializing max packet templates\n"); if (OK != acx_s_init_max_probe_request_template(priv)) goto failed; @@ -5435,46 +5780,9 @@ success: /*********************************************************************** */ static int -acx100_s_set_probe_request_template(wlandevice_t *priv) -{ - struct acx100_template_probereq probereq; - char *p; - int res; - int frame_len; - - FN_ENTER; - - memset(&probereq, 0, sizeof(probereq)); - - probereq.fc = WF_FTYPE_MGMTi | WF_FSTYPE_PROBEREQi; - MAC_BCAST(probereq.da); - MAC_COPY(probereq.sa, priv->dev_addr); - MAC_BCAST(probereq.bssid); - - probereq.beacon_interval = cpu_to_le16(priv->beacon_interval); - acx_update_capabilities(priv); - probereq.cap = cpu_to_le16(priv->capabilities); - - p = probereq.variable; - acxlog(L_ASSOC, "SSID='%s' len=%d\n", priv->essid, priv->essid_len); - p = wlan_fill_ie_ssid(p, priv->essid_len, priv->essid); - p = wlan_fill_ie_rates(p, priv->rate_supported_len, priv->rate_supported); - /* FIXME: should these be here or AFTER ds_parms? */ - p = wlan_fill_ie_rates_ext(p, priv->rate_supported_len, priv->rate_supported); - /* HUH?? who said it must be here? I've found nothing in 802.11! --vda*/ - /* p = wlan_fill_ie_ds_parms(p, priv->channel); */ - frame_len = p - (char*)&probereq; - probereq.size = frame_len - 2; - - res = acx_s_issue_cmd(priv, ACX1xx_CMD_CONFIG_PROBE_REQUEST, &probereq, frame_len); - FN_EXIT0; - return res; -} - -static int -acx111_s_set_probe_request_template(wlandevice_t *priv) +acx_s_set_probe_request_template(wlandevice_t *priv) { - struct acx111_template_probereq probereq; + struct acx_template_probereq probereq; char *p; int res; int frame_len; @@ -5500,17 +5808,6 @@ acx111_s_set_probe_request_template(wlan return res; } -static int -acx_s_set_probe_request_template(wlandevice_t *priv) -{ - if (IS_ACX111(priv)) { - return acx111_s_set_probe_request_template(priv); - } else { - return acx100_s_set_probe_request_template(priv); - } -} - - /*********************************************************************** ** acx_s_update_card_settings ** @@ -5538,7 +5835,7 @@ acx111_s_sens_radio_16_17(wlandevice_t * } void -acx_s_update_card_settings(wlandevice_t *priv, int get_all, int set_all) +acx_s_update_card_settings(wlandevice_t *priv) { unsigned long flags; unsigned int start_scan = 0; @@ -5546,23 +5843,17 @@ acx_s_update_card_settings(wlandevice_t FN_ENTER; - if (get_all) - SET_BIT(priv->get_mask, GETSET_ALL); - if (set_all) - SET_BIT(priv->set_mask, GETSET_ALL); - /* Why not just set masks to 0xffffffff? We can get rid of GETSET_ALL */ - - acxlog(L_INIT, "get_mask 0x%08X, set_mask 0x%08X\n", + log(L_INIT, "get_mask 0x%08X, set_mask 0x%08X\n", priv->get_mask, priv->set_mask); /* Track dependencies betweed various settings */ if (priv->set_mask & (GETSET_MODE|GETSET_RESCAN|GETSET_WEP)) { - acxlog(L_INIT, "important setting has been changed. " + log(L_INIT, "important setting has been changed. " "Need to update packet templates, too\n"); SET_BIT(priv->set_mask, SET_TEMPLATES); } - if (priv->set_mask & (GETSET_CHANNEL|GETSET_ALL)) { + if (priv->set_mask & GETSET_CHANNEL) { /* This will actually tune RX/TX to the channel */ SET_BIT(priv->set_mask, GETSET_RX|GETSET_TX); switch (priv->mode) { @@ -5582,10 +5873,10 @@ acx_s_update_card_settings(wlandevice_t #ifdef WHY_SHOULD_WE_BOTHER /* imagine we were just powered off */ /* send a disassoc request in case it's required */ - if (priv->set_mask & (GETSET_MODE|GETSET_RESCAN|GETSET_CHANNEL|GETSET_WEP|GETSET_ALL)) { + if (priv->set_mask & (GETSET_MODE|GETSET_RESCAN|GETSET_CHANNEL|GETSET_WEP)) { if (ACX_MODE_2_STA == priv->mode) { if (ACX_STATUS_4_ASSOCIATED == priv->status) { - acxlog(L_ASSOC, "we were ASSOCIATED - " + log(L_ASSOC, "we were ASSOCIATED - " "sending disassoc request\n"); acx_lock(priv, flags); acx_l_transmit_disassoc(priv, NULL); @@ -5593,16 +5884,15 @@ acx_s_update_card_settings(wlandevice_t acx_unlock(priv, flags); } /* need to reset some other stuff as well */ - acxlog(L_DEBUG, "resetting bssid\n"); + log(L_DEBUG, "resetting bssid\n"); MAC_ZERO(priv->bssid); SET_BIT(priv->set_mask, SET_TEMPLATES|SET_STA_LIST); - /* FIXME: should start scanning */ start_scan = 1; } } #endif - if (priv->get_mask & (GETSET_STATION_ID|GETSET_ALL)) { + if (priv->get_mask & GETSET_STATION_ID) { u8 stationID[4 + ACX1xx_IE_DOT11_STATION_ID_LEN]; const u8 *paddr; @@ -5618,32 +5908,32 @@ acx_s_update_card_settings(wlandevice_t CLEAR_BIT(priv->get_mask, GETSET_STATION_ID); } - if (priv->get_mask & (GETSET_SENSITIVITY|GETSET_ALL)) { + if (priv->get_mask & GETSET_SENSITIVITY) { if ((RADIO_RFMD_11 == priv->radio_type) || (RADIO_MAXIM_0D == priv->radio_type) || (RADIO_RALINK_15 == priv->radio_type)) { acx_s_read_phy_reg(priv, 0x30, &priv->sensitivity); } else { - acxlog(L_INIT, "don't know how to get sensitivity " + log(L_INIT, "don't know how to get sensitivity " "for radio type 0x%02X\n", priv->radio_type); priv->sensitivity = 0; } - acxlog(L_INIT, "got sensitivity value %u\n", priv->sensitivity); + log(L_INIT, "got sensitivity value %u\n", priv->sensitivity); CLEAR_BIT(priv->get_mask, GETSET_SENSITIVITY); } - if (priv->get_mask & (GETSET_ANTENNA|GETSET_ALL)) { + if (priv->get_mask & GETSET_ANTENNA) { u8 antenna[4 + ACX1xx_IE_DOT11_CURRENT_ANTENNA_LEN]; memset(antenna, 0, sizeof(antenna)); acx_s_interrogate(priv, antenna, ACX1xx_IE_DOT11_CURRENT_ANTENNA); priv->antenna = antenna[4]; - acxlog(L_INIT, "got antenna value 0x%02X\n", priv->antenna); + log(L_INIT, "got antenna value 0x%02X\n", priv->antenna); CLEAR_BIT(priv->get_mask, GETSET_ANTENNA); } - if (priv->get_mask & (GETSET_ED_THRESH|GETSET_ALL)) { + if (priv->get_mask & GETSET_ED_THRESH) { if (IS_ACX100(priv)) { u8 ed_threshold[4 + ACX100_IE_DOT11_ED_THRESHOLD_LEN]; @@ -5651,14 +5941,14 @@ acx_s_update_card_settings(wlandevice_t acx_s_interrogate(priv, ed_threshold, ACX100_IE_DOT11_ED_THRESHOLD); priv->ed_threshold = ed_threshold[4]; } else { - acxlog(L_INIT, "acx111 doesn't support ED\n"); + log(L_INIT, "acx111 doesn't support ED\n"); priv->ed_threshold = 0; } - acxlog(L_INIT, "got Energy Detect (ED) threshold %u\n", priv->ed_threshold); + log(L_INIT, "got Energy Detect (ED) threshold %u\n", priv->ed_threshold); CLEAR_BIT(priv->get_mask, GETSET_ED_THRESH); } - if (priv->get_mask & (GETSET_CCA|GETSET_ALL)) { + if (priv->get_mask & GETSET_CCA) { if (IS_ACX100(priv)) { u8 cca[4 + ACX1xx_IE_DOT11_CURRENT_CCA_MODE_LEN]; @@ -5666,24 +5956,24 @@ acx_s_update_card_settings(wlandevice_t acx_s_interrogate(priv, cca, ACX1xx_IE_DOT11_CURRENT_CCA_MODE); priv->cca = cca[4]; } else { - acxlog(L_INIT, "acx111 doesn't support CCA\n"); + log(L_INIT, "acx111 doesn't support CCA\n"); priv->cca = 0; } - acxlog(L_INIT, "got Channel Clear Assessment (CCA) value %u\n", priv->cca); + log(L_INIT, "got Channel Clear Assessment (CCA) value %u\n", priv->cca); CLEAR_BIT(priv->get_mask, GETSET_CCA); } - if (priv->get_mask & (GETSET_REG_DOMAIN|GETSET_ALL)) { + if (priv->get_mask & GETSET_REG_DOMAIN) { acx_ie_generic_t dom; acx_s_interrogate(priv, &dom, ACX1xx_IE_DOT11_CURRENT_REG_DOMAIN); priv->reg_dom_id = dom.m.bytes[0]; /* FIXME: should also set chanmask somehow */ - acxlog(L_INIT, "got regulatory domain 0x%02X\n", priv->reg_dom_id); + log(L_INIT, "got regulatory domain 0x%02X\n", priv->reg_dom_id); CLEAR_BIT(priv->get_mask, GETSET_REG_DOMAIN); } - if (priv->set_mask & (GETSET_STATION_ID|GETSET_ALL)) { + if (priv->set_mask & GETSET_STATION_ID) { u8 stationID[4 + ACX1xx_IE_DOT11_STATION_ID_LEN]; u8 *paddr; @@ -5699,20 +5989,16 @@ acx_s_update_card_settings(wlandevice_t CLEAR_BIT(priv->set_mask, GETSET_STATION_ID); } - if (priv->set_mask & (SET_TEMPLATES|GETSET_ALL)) { - acxlog(L_INIT, "updating packet templates\n"); - /* Doesn't work for acx100, do it only for acx111 for now */ - if (IS_ACX111(priv)) { - switch (priv->mode) { - case ACX_MODE_0_ADHOC: - case ACX_MODE_2_STA: - acx_s_set_probe_request_template(priv); - } - } + if (priv->set_mask & SET_TEMPLATES) { + log(L_INIT, "updating packet templates\n"); switch (priv->mode) { + case ACX_MODE_2_STA: + acx_s_set_probe_request_template(priv); + break; case ACX_MODE_0_ADHOC: + acx_s_set_probe_request_template(priv); + /* fall through */ case ACX_MODE_3_AP: - /* FIXME: why only for AP? STA need probe req templates... */ acx_s_set_beacon_template(priv); acx_s_set_tim_template(priv); /* BTW acx111 firmware would not send probe responses @@ -5724,34 +6010,34 @@ acx_s_update_card_settings(wlandevice_t acx_s_set_probe_response_template(priv); } /* Needed if generated frames are to be emitted at different tx rate now */ - acxlog(L_IRQ, "redoing cmd_join_bssid() after template cfg\n"); + log(L_IRQ, "redoing cmd_join_bssid() after template cfg\n"); acx_s_cmd_join_bssid(priv, priv->bssid); CLEAR_BIT(priv->set_mask, SET_TEMPLATES); } - if (priv->set_mask & (SET_STA_LIST|GETSET_ALL)) { + if (priv->set_mask & SET_STA_LIST) { acx_lock(priv, flags); acx_l_sta_list_init(priv); CLEAR_BIT(priv->set_mask, SET_STA_LIST); acx_unlock(priv, flags); } - if (priv->set_mask & (SET_RATE_FALLBACK|GETSET_ALL)) { + if (priv->set_mask & SET_RATE_FALLBACK) { u8 rate[4 + ACX1xx_IE_RATE_FALLBACK_LEN]; /* configure to not do fallbacks when not in auto rate mode */ rate[4] = (priv->rate_auto) ? /* priv->txrate_fallback_retries */ 1 : 0; - acxlog(L_INIT, "updating Tx fallback to %u retries\n", rate[4]); + log(L_INIT, "updating Tx fallback to %u retries\n", rate[4]); acx_s_configure(priv, &rate, ACX1xx_IE_RATE_FALLBACK); CLEAR_BIT(priv->set_mask, SET_RATE_FALLBACK); } - if (priv->set_mask & (GETSET_TXPOWER|GETSET_ALL)) { - acxlog(L_INIT, "updating transmit power: %u dBm\n", + if (priv->set_mask & GETSET_TXPOWER) { + log(L_INIT, "updating transmit power: %u dBm\n", priv->tx_level_dbm); acx_s_set_tx_level(priv, priv->tx_level_dbm); CLEAR_BIT(priv->set_mask, GETSET_TXPOWER); } - if (priv->set_mask & (GETSET_SENSITIVITY|GETSET_ALL)) { - acxlog(L_INIT, "updating sensitivity value: %u\n", + if (priv->set_mask & GETSET_SENSITIVITY) { + log(L_INIT, "updating sensitivity value: %u\n", priv->sensitivity); switch (priv->radio_type) { case RADIO_RFMD_11: @@ -5764,27 +6050,27 @@ acx_s_update_card_settings(wlandevice_t acx111_s_sens_radio_16_17(priv); break; default: - acxlog(L_INIT, "don't know how to modify sensitivity " + log(L_INIT, "don't know how to modify sensitivity " "for radio type 0x%02X\n", priv->radio_type); } CLEAR_BIT(priv->set_mask, GETSET_SENSITIVITY); } - if (priv->set_mask & (GETSET_ANTENNA|GETSET_ALL)) { + if (priv->set_mask & GETSET_ANTENNA) { /* antenna */ u8 antenna[4 + ACX1xx_IE_DOT11_CURRENT_ANTENNA_LEN]; memset(antenna, 0, sizeof(antenna)); antenna[4] = priv->antenna; - acxlog(L_INIT, "updating antenna value: 0x%02X\n", + log(L_INIT, "updating antenna value: 0x%02X\n", priv->antenna); acx_s_configure(priv, &antenna, ACX1xx_IE_DOT11_CURRENT_ANTENNA); CLEAR_BIT(priv->set_mask, GETSET_ANTENNA); } - if (priv->set_mask & (GETSET_ED_THRESH|GETSET_ALL)) { + if (priv->set_mask & GETSET_ED_THRESH) { /* ed_threshold */ - acxlog(L_INIT, "updating Energy Detect (ED) threshold: %u\n", + log(L_INIT, "updating Energy Detect (ED) threshold: %u\n", priv->ed_threshold); if (IS_ACX100(priv)) { u8 ed_threshold[4 + ACX100_IE_DOT11_ED_THRESHOLD_LEN]; @@ -5794,13 +6080,13 @@ acx_s_update_card_settings(wlandevice_t acx_s_configure(priv, &ed_threshold, ACX100_IE_DOT11_ED_THRESHOLD); } else - acxlog(L_INIT, "acx111 doesn't support ED!\n"); + log(L_INIT, "acx111 doesn't support ED!\n"); CLEAR_BIT(priv->set_mask, GETSET_ED_THRESH); } - if (priv->set_mask & (GETSET_CCA|GETSET_ALL)) { + if (priv->set_mask & GETSET_CCA) { /* CCA value */ - acxlog(L_INIT, "updating Channel Clear Assessment " + log(L_INIT, "updating Channel Clear Assessment " "(CCA) value: 0x%02X\n", priv->cca); if (IS_ACX100(priv)) { u8 cca[4 + ACX1xx_IE_DOT11_CURRENT_CCA_MODE_LEN]; @@ -5810,13 +6096,13 @@ acx_s_update_card_settings(wlandevice_t acx_s_configure(priv, &cca, ACX1xx_IE_DOT11_CURRENT_CCA_MODE); } else - acxlog(L_INIT, "acx111 doesn't support CCA!\n"); + log(L_INIT, "acx111 doesn't support CCA!\n"); CLEAR_BIT(priv->set_mask, GETSET_CCA); } - if (priv->set_mask & (GETSET_LED_POWER|GETSET_ALL)) { + if (priv->set_mask & GETSET_LED_POWER) { /* Enable Tx */ - acxlog(L_INIT, "updating power LED status: %u\n", priv->led_power); + log(L_INIT, "updating power LED status: %u\n", priv->led_power); acx_lock(priv, flags); if (IS_PCI(priv)) @@ -5825,15 +6111,15 @@ acx_s_update_card_settings(wlandevice_t acx_unlock(priv, flags); } + if (priv->set_mask & GETSET_POWER_80211) { /* this seems to cause Tx lockup after some random time (Tx error 0x20), * so let's disable it for now until further investigation */ /* Maybe fixed now after locking is fixed. Need to retest */ #ifdef POWER_SAVE_80211 - if (priv->set_mask & (GETSET_POWER_80211|GETSET_ALL)) { acx100_ie_powermgmt_t pm; /* change 802.11 power save mode settings */ - acxlog(L_INIT, "updating 802.11 power save mode settings: " + log(L_INIT, "updating 802.11 power save mode settings: " "wakeup_cfg 0x%02X, listen interval %u, " "options 0x%02X, hangover period %u, " "enhanced_ps_transition_time %d\n", @@ -5841,7 +6127,7 @@ acx_s_update_card_settings(wlandevice_t priv->ps_options, priv->ps_hangover_period, priv->ps_enhanced_transition_time); acx_s_interrogate(priv, &pm, ACX100_IE_POWER_MGMT); - acxlog(L_INIT, "Previous PS mode settings: wakeup_cfg 0x%02X, " + log(L_INIT, "Previous PS mode settings: wakeup_cfg 0x%02X, " "listen interval %u, options 0x%02X, " "hangover period %u, " "enhanced_ps_transition_time %d\n", @@ -5854,52 +6140,50 @@ acx_s_update_card_settings(wlandevice_t pm.enhanced_ps_transition_time = cpu_to_le16(priv->ps_enhanced_transition_time); acx_s_configure(priv, &pm, ACX100_IE_POWER_MGMT); acx_s_interrogate(priv, &pm, ACX100_IE_POWER_MGMT); - acxlog(L_INIT, "wakeup_cfg: 0x%02X\n", pm.wakeup_cfg); + log(L_INIT, "wakeup_cfg: 0x%02X\n", pm.wakeup_cfg); acx_s_msleep(40); acx_s_interrogate(priv, &pm, ACX100_IE_POWER_MGMT); - acxlog(L_INIT, "power save mode change %s\n", + log(L_INIT, "power save mode change %s\n", (pm.wakeup_cfg & PS_CFG_PENDING) ? "FAILED" : "was successful"); /* FIXME: maybe verify via PS_CFG_PENDING bit here * that power save mode change was successful. */ /* FIXME: we shouldn't trigger a scan immediately after * fiddling with power save mode (since the firmware is sending * a NULL frame then). Does this need locking?? */ +#endif CLEAR_BIT(priv->set_mask, GETSET_POWER_80211); } -#endif - if (priv->set_mask & (GETSET_CHANNEL|GETSET_ALL)) { + if (priv->set_mask & GETSET_CHANNEL) { /* channel */ - acxlog(L_INIT, "updating channel to: %u\n", priv->channel); + log(L_INIT, "updating channel to: %u\n", priv->channel); CLEAR_BIT(priv->set_mask, GETSET_CHANNEL); } - if (priv->set_mask & (GETSET_TX|GETSET_ALL)) { + if (priv->set_mask & GETSET_TX) { /* set Tx */ - acxlog(L_INIT, "updating: %s Tx\n", + log(L_INIT, "updating: %s Tx\n", priv->tx_disabled ? "disable" : "enable"); if (priv->tx_disabled) acx_s_issue_cmd(priv, ACX1xx_CMD_DISABLE_TX, NULL, 0); - /* ^ */ - /* FIXME: this used to be 1, but since we don't transfer a parameter... */ else acx_s_issue_cmd(priv, ACX1xx_CMD_ENABLE_TX, &(priv->channel), 1); CLEAR_BIT(priv->set_mask, GETSET_TX); } - if (priv->set_mask & (GETSET_RX|GETSET_ALL)) { + if (priv->set_mask & GETSET_RX) { /* Enable Rx */ - acxlog(L_INIT, "updating: enable Rx on channel: %u\n", + log(L_INIT, "updating: enable Rx on channel: %u\n", priv->channel); acx_s_issue_cmd(priv, ACX1xx_CMD_ENABLE_RX, &(priv->channel), 1); CLEAR_BIT(priv->set_mask, GETSET_RX); } - if (priv->set_mask & (GETSET_RETRY|GETSET_ALL)) { + if (priv->set_mask & GETSET_RETRY) { u8 short_retry[4 + ACX1xx_IE_DOT11_SHORT_RETRY_LIMIT_LEN]; u8 long_retry[4 + ACX1xx_IE_DOT11_LONG_RETRY_LIMIT_LEN]; - acxlog(L_INIT, "updating short retry limit: %u, long retry limit: %u\n", + log(L_INIT, "updating short retry limit: %u, long retry limit: %u\n", priv->short_retry, priv->long_retry); short_retry[0x4] = priv->short_retry; long_retry[0x4] = priv->long_retry; @@ -5908,34 +6192,34 @@ acx_s_update_card_settings(wlandevice_t CLEAR_BIT(priv->set_mask, GETSET_RETRY); } - if (priv->set_mask & (SET_MSDU_LIFETIME|GETSET_ALL)) { + if (priv->set_mask & SET_MSDU_LIFETIME) { u8 xmt_msdu_lifetime[4 + ACX1xx_IE_DOT11_MAX_XMIT_MSDU_LIFETIME_LEN]; - acxlog(L_INIT, "updating tx MSDU lifetime: %u\n", + log(L_INIT, "updating tx MSDU lifetime: %u\n", priv->msdu_lifetime); *(u32 *)&xmt_msdu_lifetime[4] = cpu_to_le32((u32)priv->msdu_lifetime); acx_s_configure(priv, &xmt_msdu_lifetime, ACX1xx_IE_DOT11_MAX_XMIT_MSDU_LIFETIME); CLEAR_BIT(priv->set_mask, SET_MSDU_LIFETIME); } - if (priv->set_mask & (GETSET_REG_DOMAIN|GETSET_ALL)) { + if (priv->set_mask & GETSET_REG_DOMAIN) { /* reg_domain */ acx_ie_generic_t dom; unsigned mask; - acxlog(L_INIT, "updating regulatory domain: 0x%02X\n", + log(L_INIT, "updating regulatory domain: 0x%02X\n", priv->reg_dom_id); - for (i = 0; i < sizeof(reg_domain_ids); i++) - if (reg_domain_ids[i] == priv->reg_dom_id) + for (i = 0; i < sizeof(acx_reg_domain_ids); i++) + if (acx_reg_domain_ids[i] == priv->reg_dom_id) break; - if (sizeof(reg_domain_ids) == i) { - acxlog(L_INIT, "Invalid or unsupported regulatory " + if (sizeof(acx_reg_domain_ids) == i) { + log(L_INIT, "Invalid or unsupported regulatory " "domain 0x%02X specified, falling back to " "FCC (USA)! Please report if this sounds " "fishy!\n", priv->reg_dom_id); i = 0; - priv->reg_dom_id = reg_domain_ids[i]; + priv->reg_dom_id = acx_reg_domain_ids[i]; } priv->reg_dom_chanmask = reg_domain_channel_masks[i]; @@ -5962,7 +6246,7 @@ acx_s_update_card_settings(wlandevice_t CLEAR_BIT(priv->set_mask, GETSET_REG_DOMAIN); } - if (priv->set_mask & (GETSET_MODE|GETSET_ALL)) { + if (priv->set_mask & GETSET_MODE) { priv->netdev->type = ARPHRD_ETHER; switch (priv->mode) { @@ -5995,8 +6279,12 @@ acx_s_update_card_settings(wlandevice_t case ACX_MODE_0_ADHOC: case ACX_MODE_2_STA: acx111_s_feature_off(priv, 0, FEATURE2_NO_TXCRYPT|FEATURE2_SNIFFER); + + acx_lock(priv, flags); priv->aid = 0; priv->ap_client = NULL; + acx_unlock(priv, flags); + /* we want to start looking for peer or AP */ start_scan = 1; break; @@ -6013,12 +6301,12 @@ acx_s_update_card_settings(wlandevice_t CLEAR_BIT(priv->set_mask, GETSET_MODE); } - if (priv->set_mask & (SET_RXCONFIG|GETSET_ALL)) { + if (priv->set_mask & SET_RXCONFIG) { acx_s_initialize_rx_config(priv); CLEAR_BIT(priv->set_mask, SET_RXCONFIG); } - if (priv->set_mask & (GETSET_RESCAN|GETSET_ALL)) { + if (priv->set_mask & GETSET_RESCAN) { switch (priv->mode) { case ACX_MODE_0_ADHOC: case ACX_MODE_2_STA: @@ -6028,7 +6316,7 @@ acx_s_update_card_settings(wlandevice_t CLEAR_BIT(priv->set_mask, GETSET_RESCAN); } - if (priv->set_mask & (GETSET_WEP|GETSET_ALL)) { + if (priv->set_mask & GETSET_WEP) { /* encode */ ie_dot11WEPDefaultKeyID_t dkey; @@ -6039,12 +6327,12 @@ acx_s_update_card_settings(wlandevice_t u8 val ACX_PACKED; } keyindic; #endif - acxlog(L_INIT, "updating WEP key settings\n"); + log(L_INIT, "updating WEP key settings\n"); acx_s_set_wepkey(priv); dkey.KeyID = priv->wep_current_index; - acxlog(L_INIT, "setting WEP key %u as default\n", dkey.KeyID); + log(L_INIT, "setting WEP key %u as default\n", dkey.KeyID); acx_s_configure(priv, &dkey, ACX1xx_IE_DOT11_WEP_DEFAULT_KEY_SET); #ifdef DEBUG_WEP keyindic.val = 3; @@ -6054,13 +6342,13 @@ acx_s_update_card_settings(wlandevice_t CLEAR_BIT(priv->set_mask, GETSET_WEP); } - if (priv->set_mask & (SET_WEP_OPTIONS|GETSET_ALL)) { + if (priv->set_mask & SET_WEP_OPTIONS) { acx100_ie_wep_options_t options; if (IS_ACX111(priv)) { - acxlog(L_DEBUG, "setting WEP Options for acx111 is not supported\n"); + log(L_DEBUG, "setting WEP Options for acx111 is not supported\n"); } else { - acxlog(L_INIT, "setting WEP Options\n"); + log(L_INIT, "setting WEP Options\n"); /* let's choose maximum setting: 4 default keys, * plus 10 other keys: */ @@ -6100,7 +6388,7 @@ acx_s_update_card_settings(wlandevice_t /* debug, rate, and nick don't need any handling */ /* what about sniffing mode?? */ - acxlog(L_INIT, "get_mask 0x%08X, set_mask 0x%08X - after update\n", + log(L_INIT, "get_mask 0x%08X, set_mask 0x%08X - after update\n", priv->get_mask, priv->set_mask); /* end: */ @@ -6209,13 +6497,9 @@ acx_s_initialize_rx_config(wlandevice_t ); break; } -#ifdef DEBUG_WEP - if (IS_ACX100(priv)) - /* only ACX100 supports that */ -#endif - priv->rx_config_1 |= RX_CFG1_INCLUDE_RXBUF_HDR; + priv->rx_config_1 |= RX_CFG1_INCLUDE_RXBUF_HDR; - acxlog(L_INIT, "setting RXconfig to %04X:%04X\n", + log(L_INIT, "setting RXconfig to %04X:%04X\n", priv->rx_config_1, priv->rx_config_2); cfg.rx_cfg1 = cpu_to_le16(priv->rx_config_1); cfg.rx_cfg2 = cpu_to_le16(priv->rx_config_2); @@ -6236,7 +6520,7 @@ acx_s_recalib_radio(wlandevice_t *priv) /* automatic recalibration, choose all methods: */ cal.methods = cpu_to_le32(0x8000000f); /* automatic recalibration every 60 seconds (value in TUs) - * FIXME: what is the firmware default here?? */ + * I wonder what is the firmware default here? */ cal.interval = cpu_to_le32(58594); return acx_s_issue_cmd_timeo(priv, ACX111_CMD_RADIOCALIB, &cal, sizeof(cal), CMD_TIMEOUT_MS(100)); @@ -6341,14 +6625,14 @@ acx_e_after_interrupt_task(void *data) /* a poor interrupt code wanted to do update_card_settings() */ if (priv->after_interrupt_jobs & ACX_AFTER_IRQ_UPDATE_CARD_CFG) { if (ACX_STATE_IFACE_UP & priv->dev_state_mask) - acx_s_update_card_settings(priv, 0, 0); + acx_s_update_card_settings(priv); CLEAR_BIT(priv->after_interrupt_jobs, ACX_AFTER_IRQ_UPDATE_CARD_CFG); } /* 1) we detected that no Scan_Complete IRQ came from fw, or ** 2) we found too many STAs */ if (priv->after_interrupt_jobs & ACX_AFTER_IRQ_CMD_STOP_SCAN) { - acxlog(L_IRQ, "sending a stop scan cmd...\n"); + log(L_IRQ, "sending a stop scan cmd...\n"); acx_s_issue_cmd(priv, ACX1xx_CMD_STOP_SCAN, NULL, 0); /* HACK: set the IRQ bit, since we won't get a * scan complete IRQ any more on ACX111 (works on ACX100!), @@ -6377,7 +6661,7 @@ acx_e_after_interrupt_task(void *data) switch (priv->mode) { case ACX_MODE_0_ADHOC: case ACX_MODE_3_AP: - acxlog(L_IRQ, "redoing cmd_join_bssid() after scan\n"); + log(L_IRQ, "redoing cmd_join_bssid() after scan\n"); acx_s_cmd_join_bssid(priv, priv->bssid); } } @@ -6386,7 +6670,7 @@ acx_e_after_interrupt_task(void *data) /* STA auth or assoc timed out, start over again */ if (priv->after_interrupt_jobs & ACX_AFTER_IRQ_RESTART_SCAN) { - acxlog(L_IRQ, "sending a start_scan cmd...\n"); + log(L_IRQ, "sending a start_scan cmd...\n"); acx_s_cmd_start_scan(priv); CLEAR_BIT(priv->after_interrupt_jobs, ACX_AFTER_IRQ_RESTART_SCAN); } @@ -6400,7 +6684,7 @@ acx_e_after_interrupt_task(void *data) pdr.m.aid = cpu_to_le16(priv->aid); acx_s_configure(priv, &pdr, ACX1xx_IE_ASSOC_ID); acx_set_status(priv, ACX_STATUS_4_ASSOCIATED); - acxlog(L_ASSOC|L_DEBUG, "ASSOCIATED!\n"); + log(L_ASSOC|L_DEBUG, "ASSOCIATED!\n"); CLEAR_BIT(priv->after_interrupt_jobs, ACX_AFTER_IRQ_CMD_ASSOCIATE); } } @@ -6454,8 +6738,8 @@ acx_s_start(wlandevice_t *priv) |GETSET_REG_DOMAIN|GETSET_MODE|GETSET_CHANNEL |GETSET_TX|GETSET_RX); - acxlog(L_INIT, "updating initial settings on iface activation...\n"); - acx_s_update_card_settings(priv, 0, 0); + log(L_INIT, "updating initial settings on iface activation\n"); + acx_s_update_card_settings(priv); FN_EXIT0; } @@ -6489,7 +6773,7 @@ acx_update_capabilities(wlandevice_t *pr if (priv->capab_agility) { SET_BIT(cap, WF_MGMT_CAP_AGILITY); } - acxlog(L_DEBUG, "caps updated from 0x%04X to 0x%04X\n", + log(L_DEBUG, "caps updated from 0x%04X to 0x%04X\n", priv->capabilities, cap); priv->capabilities = cap; } diff -puN drivers/net/wireless/tiacx/conv.c~acx-driver-update drivers/net/wireless/tiacx/conv.c --- devel/drivers/net/wireless/tiacx/conv.c~acx-driver-update 2006-01-06 22:44:21.000000000 -0800 +++ devel-akpm/drivers/net/wireless/tiacx/conv.c 2006-01-06 22:44:21.000000000 -0800 @@ -61,7 +61,7 @@ static inline int proto_is_stt(unsigned int proto) { /* Always return found for now. This is the behavior used by the */ - /* Zoom Win95 driver when 802.1h mode is selected */ + /* Zoom Win95 driver when 802.1h mode is selected */ /* TODO: If necessary, add an actual search we'll probably need this to match the CMAC's way of doing things. Need to do some testing to confirm. @@ -150,7 +150,7 @@ acx_ether_to_txbuf(wlandevice_t *priv, v FN_ENTER; if (unlikely(!skb->len)) { - acxlog(L_DEBUG, "zero-length skb!\n"); + log(L_DEBUG, "zero-length skb!\n"); goto end; } @@ -174,7 +174,7 @@ acx_ether_to_txbuf(wlandevice_t *priv, v e_hdr = (wlan_ethhdr_t *)skb->data; proto = ntohs(e_hdr->type); if (proto <= 1500) { - acxlog(L_DEBUG, "tx: 802.3 len: %d\n", skb->len); + log(L_DEBUG, "tx: 802.3 len: %d\n", skb->len); /* codes <= 1500 reserved for 802.3 lengths */ /* it's 802.3, pass ether payload unchanged, */ /* trim off ethernet header and copy payload to txdesc */ @@ -183,7 +183,7 @@ acx_ether_to_txbuf(wlandevice_t *priv, v /* it's DIXII, time for some conversion */ /* Create 802.11 packet. Header also contains llc and snap. */ - acxlog(L_DEBUG, "tx: DIXII len: %d\n", skb->len); + log(L_DEBUG, "tx: DIXII len: %d\n", skb->len); /* size of header is 802.11 header + llc + snap */ header_len = WLAN_HDR_A3_LEN + sizeof(wlan_llc_t) + sizeof(wlan_snap_t); @@ -318,7 +318,7 @@ acx_rxbuf_to_ether(wlandevice_t *priv, r if ((WF_FC_ISWEPi & fc) && IS_ACX100(priv)) { /* chop off the IV+ICV WEP header and footer */ - acxlog(L_DATA|L_DEBUG, "rx: WEP packet, " + log(L_DATA|L_DEBUG, "rx: WEP packet, " "chopping off IV and ICV\n"); payload_offset += WLAN_WEP_IV_LEN; payload_length -= WLAN_WEP_IV_LEN + WLAN_WEP_ICV_LEN; @@ -335,9 +335,9 @@ acx_rxbuf_to_ether(wlandevice_t *priv, r e_payload = (u8*) (e_snap + 1); mtu = priv->netdev->mtu; - acxlog(L_DATA, "rx: payload_offset %d, payload_length %d\n", + log(L_DATA, "rx: payload_offset %d, payload_length %d\n", payload_offset, payload_length); - acxlog(L_XFER|L_DATA, + log(L_XFER|L_DATA, "rx: frame info: llc=%02X%02X%02X " "snap.oui=%02X%02X%02X snap.type=%04X\n", e_llc->dsap, e_llc->ssap, e_llc->ctl, @@ -353,7 +353,7 @@ acx_rxbuf_to_ether(wlandevice_t *priv, r ) { /* 802.3 Encapsulated: */ /* wlan frame body contains complete eth frame (header+body) */ - acxlog(L_DEBUG|L_DATA, "rx: 802.3 ENCAP len=%d\n", payload_length); + log(L_DEBUG|L_DATA, "rx: 802.3 ENCAP len=%d\n", payload_length); if (unlikely(payload_length > (mtu + ETH_HLEN))) { printk("%s: rx: ENCAP frame too large (%d > %d)\n", @@ -380,7 +380,7 @@ acx_rxbuf_to_ether(wlandevice_t *priv, r if ( !oui_is_rfc1042(e_snap) || (proto_is_stt(ieee2host16(e_snap->type)) /* && (ethconv == WLAN_ETHCONV_8021h) */)) { - acxlog(L_DEBUG|L_DATA, "rx: SNAP+RFC1042 len=%d\n", payload_length); + log(L_DEBUG|L_DATA, "rx: SNAP+RFC1042 len=%d\n", payload_length); /* wlan frame body contains: AA AA 03 !(00 00 00) ... -or- */ /* wlan frame body contains: AA AA 03 00 00 00 0x80f3 ... */ /* build eth hdr, type = len, copy AA AA 03... as eth body */ @@ -416,7 +416,7 @@ acx_rxbuf_to_ether(wlandevice_t *priv, r } else { /* wlan frame body contains: AA AA 03 00 00 00 [type] [tail] */ /* build eth hdr, type=[type], copy [tail] as eth body */ - acxlog(L_DEBUG|L_DATA, "rx: 802.1h/RFC1042 len=%d\n", + log(L_DEBUG|L_DATA, "rx: 802.1h/RFC1042 len=%d\n", payload_length); /* it's an 802.1h frame (an RFC1042 && protocol is not in STT) */ /* build a DIXII + RFC894 */ @@ -451,7 +451,7 @@ acx_rxbuf_to_ether(wlandevice_t *priv, r } } else { - acxlog(L_DEBUG|L_DATA, "rx: NON-ENCAP len=%d\n", payload_length); + log(L_DEBUG|L_DATA, "rx: NON-ENCAP len=%d\n", payload_length); /* build eth hdr, type=len, copy wlan body as eth body */ /* any NON-ENCAP */ /* it's a generic 80211+LLC or IPX 'Raw 802.3' */ diff -puN drivers/net/wireless/tiacx/ioctl.c~acx-driver-update drivers/net/wireless/tiacx/ioctl.c --- devel/drivers/net/wireless/tiacx/ioctl.c~acx-driver-update 2006-01-06 22:44:21.000000000 -0800 +++ devel-akpm/drivers/net/wireless/tiacx/ioctl.c 2006-01-06 22:44:21.000000000 -0800 @@ -46,7 +46,8 @@ #include "acx.h" -/*================================================================*/ +/*********************************************************************** +*/ /* if you plan to reorder something, make sure to reorder all other places * accordingly! */ @@ -198,9 +199,9 @@ static const struct iw_priv_args acx_ioc }; -/*------------------------------------------------------------------------------ - * acx_ioctl_commit - *----------------------------------------------------------------------------*/ +/*********************************************************************** +** acx_ioctl_commit +*/ static int acx_ioctl_commit(struct net_device *dev, struct iw_request_info *info, @@ -212,7 +213,7 @@ acx_ioctl_commit(struct net_device *dev, acx_sem_lock(priv); if (ACX_STATE_IFACE_UP & priv->dev_state_mask) - acx_s_update_card_settings(priv, 0, 0); + acx_s_update_card_settings(priv); acx_sem_unlock(priv); FN_EXIT0; @@ -238,9 +239,9 @@ acx_ioctl_get_name( } -/*---------------------------------------------------------------- -* acx_ioctl_set_freq -*----------------------------------------------------------------*/ +/*********************************************************************** +** acx_ioctl_set_freq +*/ static int acx_ioctl_set_freq( struct net_device *dev, @@ -280,7 +281,7 @@ acx_ioctl_set_freq( priv->channel = channel; /* hmm, the following code part is strange, but this is how * it was being done before... */ - acxlog(L_IOCTL, "Changing to channel %d\n", channel); + log(L_IOCTL, "Changing to channel %d\n", channel); SET_BIT(priv->set_mask, GETSET_CHANNEL); result = -EINPROGRESS; /* need to call commit handler */ @@ -308,9 +309,9 @@ acx_ioctl_get_freq( } -/*---------------------------------------------------------------- -* acx_ioctl_set_mode -*----------------------------------------------------------------*/ +/*********************************************************************** +** acx_ioctl_set_mode +*/ static int acx_ioctl_set_mode( struct net_device *dev, @@ -354,7 +355,7 @@ acx_ioctl_set_mode( goto end_unlock; } - acxlog(L_ASSOC, "new priv->mode=%d\n", priv->mode); + log(L_ASSOC, "new priv->mode=%d\n", priv->mode); SET_BIT(priv->set_mask, GETSET_MODE); result = -EINPROGRESS; @@ -443,11 +444,11 @@ acx_ioctl_get_sens( } -/*------------------------------------------------------------------------------ - * acx_ioctl_set_ap - * - * Sets the MAC address of the AP to associate with - *----------------------------------------------------------------------------*/ +/*********************************************************************** +** acx_ioctl_set_ap +** +** Sets the MAC address of the AP to associate with +*/ static int acx_ioctl_set_ap( struct net_device *dev, @@ -470,7 +471,7 @@ acx_ioctl_set_ap( } ap = awrq->sa_data; - acxlog_mac(L_IOCTL, "Set AP=", ap, "\n"); + acxlog_mac(L_IOCTL, "set AP=", ap, "\n"); MAC_COPY(priv->ap, ap); @@ -486,9 +487,9 @@ acx_ioctl_set_ap( if (mac_is_zero(ap)) { /* "off" == 00:00:00:00:00:00 */ MAC_BCAST(priv->ap); - acxlog(L_IOCTL, "Not reassociating\n"); + log(L_IOCTL, "Not reassociating\n"); } else { - acxlog(L_IOCTL, "Forcing reassociation\n"); + log(L_IOCTL, "Forcing reassociation\n"); SET_BIT(priv->set_mask, GETSET_RESCAN); } break; @@ -522,13 +523,13 @@ acx_ioctl_get_ap( } -/*---------------------------------------------------------------- -* acx_ioctl_get_aplist -* -* Comment: deprecated in favour of iwscan. -* We simply return the list of currently available stations in range, -* don't do a new scan. -*----------------------------------------------------------------*/ +/*********************************************************************** +** acx_ioctl_get_aplist +** +** Deprecated in favor of iwscan. +** We simply return the list of currently available stations in range, +** don't do a new scan. +*/ static int acx_ioctl_get_aplist( struct net_device *dev, @@ -644,7 +645,7 @@ acx_s_scan_add_station( iwe.cmd = SIOCGIWESSID; iwe.u.data.length = bss->essid_len; iwe.u.data.flags = 1; - acxlog(L_IOCTL, "scan, essid: %s\n", bss->essid); + log(L_IOCTL, "scan, essid: %s\n", bss->essid); ptr = iwe_stream_add_point(ptr, end_buf, &iwe, bss->essid); /* Add mode */ @@ -654,7 +655,7 @@ acx_s_scan_add_station( iwe.u.mode = IW_MODE_MASTER; else iwe.u.mode = IW_MODE_ADHOC; - acxlog(L_IOCTL, "scan, mode: %d\n", iwe.u.mode); + log(L_IOCTL, "scan, mode: %d\n", iwe.u.mode); ptr = iwe_stream_add_event(ptr, end_buf, &iwe, IW_EV_UINT_LEN); } @@ -662,7 +663,7 @@ acx_s_scan_add_station( iwe.cmd = SIOCGIWFREQ; iwe.u.freq.m = acx_channel_freq[bss->channel - 1] * 100000; iwe.u.freq.e = 1; - acxlog(L_IOCTL, "scan, frequency: %d\n", iwe.u.freq.m); + log(L_IOCTL, "scan, frequency: %d\n", iwe.u.freq.m); ptr = iwe_stream_add_event(ptr, end_buf, &iwe, IW_EV_FREQ_LEN); /* Add link quality */ @@ -679,7 +680,7 @@ acx_s_scan_add_station( 100 - iwe.u.qual.noise : 0; #endif iwe.u.qual.updated = 7; - acxlog(L_IOCTL, "scan, link quality: %d/%d/%d\n", + log(L_IOCTL, "scan, link quality: %d/%d/%d\n", iwe.u.qual.level, iwe.u.qual.noise, iwe.u.qual.qual); ptr = iwe_stream_add_event(ptr, end_buf, &iwe, IW_EV_QUAL_LEN); @@ -690,7 +691,7 @@ acx_s_scan_add_station( else iwe.u.data.flags = IW_ENCODE_DISABLED; iwe.u.data.length = 0; - acxlog(L_IOCTL, "scan, encryption flags: %X\n", iwe.u.data.flags); + log(L_IOCTL, "scan, encryption flags: %X\n", iwe.u.data.flags); ptr = iwe_stream_add_point(ptr, end_buf, &iwe, bss->essid); /* add rates */ @@ -700,11 +701,11 @@ acx_s_scan_add_station( { u16 rate = bss->rate_cap; - const u8* p = bitpos2ratebyte; + const u8* p = acx_bitpos2ratebyte; while (rate) { if (rate & 1) { iwe.u.bitrate.value = *p * 500000; /* units of 500kb/s */ - acxlog(L_IOCTL, "scan, rate: %d\n", iwe.u.bitrate.value); + log(L_IOCTL, "scan, rate: %d\n", iwe.u.bitrate.value); ptr = iwe_stream_add_value(ptr, ptr_rate, end_buf, &iwe, IW_EV_PARAM_LEN); } @@ -743,17 +744,10 @@ acx_ioctl_get_scan( /* no scan available if device is not up yet */ if (!(priv->dev_state_mask & ACX_STATE_IFACE_UP)) { - acxlog(L_IOCTL, "iface not up yet\n"); + log(L_IOCTL, "iface not up yet\n"); result = -EAGAIN; goto end_unlock; } -#if 0 /* Why is this needed? If needed, add a comment */ - if (priv->scan_start && time_before(jiffies, priv->scan_start + 3*HZ)) { - acxlog(L_IOCTL, "scan in progress, no results yet\n"); - result = -EAGAIN; - goto end_unlock; - } -#endif #ifdef ENODATA_TO_BE_USED_AFTER_SCAN_ERROR_ONLY if (priv->bss_table_count == 0) { @@ -797,14 +791,14 @@ acx_ioctl_set_essid( FN_ENTER; - acxlog(L_IOCTL, "Set ESSID '%*s', length %d, flags 0x%04X\n", - len, extra, len, dwrq->flags); - if (len < 0) { result = -EINVAL; goto end; } + log(L_IOCTL, "set ESSID '%*s', length %d, flags 0x%04X\n", + len, extra, len, dwrq->flags); + acx_sem_lock(priv); /* ESSID disabled? */ @@ -860,9 +854,9 @@ acx_ioctl_get_essid( } -/*---------------------------------------------------------------- -* acx_l_update_client_rates -*----------------------------------------------------------------*/ +/*********************************************************************** +** acx_l_update_client_rates +*/ static void acx_l_update_client_rates(wlandevice_t *priv, u16 rate) { @@ -883,6 +877,8 @@ acx_l_update_client_rates(wlandevice_t * /* current rate become invalid, choose a valid one */ clt->rate_cur = 1 << lowest_bit(clt->rate_cfg); } + if (IS_ACX100(priv)) + clt->rate_100 = acx_bitpos2rate100[highest_bit(clt->rate_cur)]; clt->fallback_count = clt->stepup_count = 0; clt->ignore_count = 16; } @@ -936,7 +932,7 @@ acx_ioctl_set_rate( int result = -EINVAL; FN_ENTER; - acxlog(L_IOCTL, "rate %d fixed 0x%X disabled 0x%X flags 0x%X\n", + log(L_IOCTL, "rate %d fixed 0x%X disabled 0x%X flags 0x%X\n", vwrq->value, vwrq->fixed, vwrq->disabled, vwrq->flags); if ((0 == vwrq->fixed) || (1 == vwrq->fixed)) { @@ -1008,9 +1004,9 @@ end: } -/*---------------------------------------------------------------- -* acx_ioctl_get_rate -*----------------------------------------------------------------*/ +/*********************************************************************** +** acx_ioctl_get_rate +*/ static int acx_ioctl_get_rate( struct net_device *dev, @@ -1018,11 +1014,19 @@ acx_ioctl_get_rate( struct iw_param *vwrq, char *extra) { - /* TODO: remember rate of last tx, show it. think about multiple peers... */ wlandevice_t *priv = netdev_priv(dev); - vwrq->value = acx111_rate_tbl[highest_bit(priv->rate_oper)]; + unsigned long flags; + u16 rate; + + acx_lock(priv, flags); + rate = priv->rate_oper; + if (priv->ap_client) + rate = priv->ap_client->rate_cur; + vwrq->value = acx111_rate_tbl[highest_bit(rate)]; vwrq->fixed = !priv->rate_auto; vwrq->disabled = 0; + acx_unlock(priv, flags); + return OK; } @@ -1061,9 +1065,9 @@ acx_ioctl_get_rts( } -/*---------------------------------------------------------------- -* acx_ioctl_set_encode -*----------------------------------------------------------------*/ +/*********************************************************************** +** acx_ioctl_set_encode +*/ static int acx_ioctl_set_encode( struct net_device *dev, @@ -1077,7 +1081,7 @@ acx_ioctl_set_encode( FN_ENTER; - acxlog(L_IOCTL, "Set Encoding flags=0x%04X, size=%d, key: %s\n", + log(L_IOCTL, "set encoding flags=0x%04X, size=%d, key: %s\n", dwrq->flags, dwrq->length, extra ? "set" : "No key"); acx_sem_lock(priv); @@ -1137,12 +1141,12 @@ acx_ioctl_set_encode( /* set flag to make sure the card WEP settings get updated */ SET_BIT(priv->set_mask, GETSET_WEP); - acxlog(L_IOCTL, "len=%d, key at 0x%p, flags=0x%X\n", + log(L_IOCTL, "len=%d, key at 0x%p, flags=0x%X\n", dwrq->length, extra, dwrq->flags); for (index = 0; index <= 3; index++) { if (priv->wep_keys[index].size) { - acxlog(L_IOCTL, "index=%d, size=%d, key at 0x%p\n", + log(L_IOCTL, "index=%d, size=%d, key at 0x%p\n", priv->wep_keys[index].index, (int) priv->wep_keys[index].size, priv->wep_keys[index].key); @@ -1158,9 +1162,9 @@ end_unlock: } -/*---------------------------------------------------------------- -* acx_ioctl_get_encode -*----------------------------------------------------------------*/ +/*********************************************************************** +** acx_ioctl_get_encode +*/ static int acx_ioctl_get_encode( struct net_device *dev, @@ -1190,7 +1194,7 @@ acx_ioctl_get_encode( /* set the current index */ SET_BIT(dwrq->flags, index + 1); - acxlog(L_IOCTL, "len=%d, key=%p, flags=0x%X\n", + log(L_IOCTL, "len=%d, key=%p, flags=0x%X\n", dwrq->length, dwrq->pointer, dwrq->flags); @@ -1213,7 +1217,7 @@ acx_ioctl_set_power( FN_ENTER; - acxlog(L_IOCTL, "Set 802.11 Power Save flags=0x%04X\n", vwrq->flags); + log(L_IOCTL, "set 802.11 powersave flags=0x%04X\n", vwrq->flags); acx_sem_lock(priv); @@ -1227,7 +1231,7 @@ acx_ioctl_set_power( if (ps_timeout > 255) ps_timeout = 255; - acxlog(L_IOCTL, "setting PS timeout value to %d time units " + log(L_IOCTL, "setting PS timeout value to %d time units " "due to %dus\n", ps_timeout, vwrq->value); priv->ps_hangover_period = ps_timeout; } else if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_PERIOD) { @@ -1235,7 +1239,7 @@ acx_ioctl_set_power( if (ps_periods > 255) ps_periods = 255; - acxlog(L_IOCTL, "setting PS period value to %d periods " + log(L_IOCTL, "setting PS period value to %d periods " "due to %dus\n", ps_periods, vwrq->value); priv->ps_listen_interval = ps_periods; CLEAR_BIT(priv->ps_wakeup_cfg, PS_CFG_WAKEUP_MODE_MASK); @@ -1256,7 +1260,7 @@ acx_ioctl_set_power( case IW_POWER_ON: break; default: - acxlog(L_IOCTL, "unknown PS mode\n"); + log(L_IOCTL, "unknown PS mode\n"); result = -EINVAL; goto end; } @@ -1284,10 +1288,11 @@ acx_ioctl_get_power( FN_ENTER; - acxlog(L_IOCTL, "Get 802.11 Power Save flags = 0x%04X\n", vwrq->flags); + log(L_IOCTL, "Get 802.11 Power Save flags = 0x%04X\n", vwrq->flags); vwrq->disabled = ((priv->ps_wakeup_cfg & PS_CFG_ENABLE) == 0); if (vwrq->disabled) - return OK; + goto end; + if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) { vwrq->value = priv->ps_hangover_period * 1000 / 1024; vwrq->flags = IW_POWER_TIMEOUT; @@ -1299,15 +1304,15 @@ acx_ioctl_get_power( SET_BIT(vwrq->flags, IW_POWER_ALL_R); else SET_BIT(vwrq->flags, IW_POWER_UNICAST_R); - +end: FN_EXIT1(OK); return OK; } -/*---------------------------------------------------------------- -* acx_ioctl_get_txpow -*----------------------------------------------------------------*/ +/*********************************************************************** +** acx_ioctl_get_txpow +*/ static inline int acx_ioctl_get_txpow( struct net_device *dev, @@ -1324,16 +1329,16 @@ acx_ioctl_get_txpow( vwrq->fixed = 1; vwrq->value = priv->tx_level_dbm; - acxlog(L_IOCTL, "get txpower:%d dBm\n", priv->tx_level_dbm); + log(L_IOCTL, "get txpower:%d dBm\n", priv->tx_level_dbm); FN_EXIT1(OK); return OK; } -/*---------------------------------------------------------------- -* acx_ioctl_set_txpow -*----------------------------------------------------------------*/ +/*********************************************************************** +** acx_ioctl_set_txpow +*/ static int acx_ioctl_set_txpow( struct net_device *dev, @@ -1346,7 +1351,7 @@ acx_ioctl_set_txpow( FN_ENTER; - acxlog(L_IOCTL, "set txpower:%d, disabled:%d, flags:0x%04X\n", + log(L_IOCTL, "set txpower:%d, disabled:%d, flags:0x%04X\n", vwrq->value, vwrq->disabled, vwrq->flags); acx_sem_lock(priv); @@ -1359,15 +1364,15 @@ acx_ioctl_set_txpow( if (vwrq->value == -1) { if (vwrq->disabled) { priv->tx_level_dbm = 0; - acxlog(L_IOCTL, "disable radio tx\n"); + log(L_IOCTL, "disable radio tx\n"); } else { /* priv->tx_level_auto = 1; */ - acxlog(L_IOCTL, "set tx power auto (NIY)\n"); + log(L_IOCTL, "set tx power auto (NIY)\n"); } } else { priv->tx_level_dbm = vwrq->value <= 20 ? vwrq->value : 20; /* priv->tx_level_auto = 0; */ - acxlog(L_IOCTL, "set txpower=%d dBm\n", priv->tx_level_dbm); + log(L_IOCTL, "set txpower=%d dBm\n", priv->tx_level_dbm); } SET_BIT(priv->set_mask, GETSET_TXPOWER); @@ -1380,9 +1385,9 @@ acx_ioctl_set_txpow( } -/*---------------------------------------------------------------- -* acx_ioctl_get_range -*----------------------------------------------------------------*/ +/*********************************************************************** +** acx_ioctl_get_range +*/ static int acx_ioctl_get_range( struct net_device *dev, @@ -1480,17 +1485,17 @@ end: } -/*================================================================*/ -/* Private functions */ -/*================================================================*/ +/*********************************************************************** +** Private functions +*/ #if WIRELESS_EXT < 13 -/*---------------------------------------------------------------- -* acx_ioctl_get_iw_priv -* -* Comment: I added the monitor mode and changed the stuff below -* to look more like the orinoco driver -*----------------------------------------------------------------*/ +/*********************************************************************** +** acx_ioctl_get_iw_priv +** +** I added the monitor mode and changed the stuff below +** to look more like the orinoco driver +*/ static int acx_ioctl_get_iw_priv(struct iwreq *iwr) { @@ -1513,9 +1518,9 @@ acx_ioctl_get_iw_priv(struct iwreq *iwr) #endif -/*---------------------------------------------------------------- -* acx_ioctl_get_nick -*----------------------------------------------------------------*/ +/*********************************************************************** +** acx_ioctl_get_nick +*/ static inline int acx_ioctl_get_nick( struct net_device *dev, @@ -1525,19 +1530,16 @@ acx_ioctl_get_nick( { wlandevice_t *priv = netdev_priv(dev); - /* FIXME : consider spinlock here */ strcpy(extra, priv->nick); - /* FIXME : consider spinlock here */ - dwrq->length = strlen(extra) + 1; return OK; } -/*---------------------------------------------------------------- -* acx_ioctl_set_nick -*----------------------------------------------------------------*/ +/*********************************************************************** +** acx_ioctl_set_nick +*/ static int acx_ioctl_set_nick( struct net_device *dev, @@ -1569,9 +1571,9 @@ end_unlock: } -/*------------------------------------------------------------------------------ - * acx_ioctl_get_retry - *----------------------------------------------------------------------------*/ +/*********************************************************************** +** acx_ioctl_get_retry +*/ static int acx_ioctl_get_retry( struct net_device *dev, @@ -1613,9 +1615,9 @@ acx_ioctl_get_retry( } -/*---------------------------------------------------------------- -* acx_ioctl_set_retry -*----------------------------------------------------------------*/ +/*********************************************************************** +** acx_ioctl_set_retry +*/ static int acx_ioctl_set_retry( struct net_device *dev, @@ -1671,12 +1673,12 @@ end: } -/******************************* private ioctls ******************************/ +/************************ private ioctls ******************************/ -/*---------------------------------------------------------------- -* acx_ioctl_set_debug -*----------------------------------------------------------------*/ +/*********************************************************************** +** acx_ioctl_set_debug +*/ #if ACX_DEBUG static int acx_ioctl_set_debug( @@ -1688,7 +1690,7 @@ acx_ioctl_set_debug( unsigned int debug_new = *((unsigned int *)extra); int result = -EINVAL; - acxlog(L_ANY, "setting debug from %04X to %04X\n", acx_debug, debug_new); + log(L_ANY, "setting debug from %04X to %04X\n", acx_debug, debug_new); acx_debug = debug_new; result = OK; @@ -1697,9 +1699,10 @@ acx_ioctl_set_debug( } #endif -/*---------------------------------------------------------------- -* acx_ioctl_list_reg_domain -*----------------------------------------------------------------*/ + +/*********************************************************************** +** acx_ioctl_list_reg_domain +*/ static const char * const reg_domain_strings[] = { " 1-11 FCC (USA)", @@ -1733,9 +1736,9 @@ acx_ioctl_list_reg_domain( } -/*---------------------------------------------------------------- -* acx_ioctl_set_reg_domain -*----------------------------------------------------------------*/ +/*********************************************************************** +** acx_ioctl_set_reg_domain +*/ static int acx_ioctl_set_reg_domain( struct net_device *dev, @@ -1748,14 +1751,14 @@ acx_ioctl_set_reg_domain( FN_ENTER; - if ((*extra < 1) || ((size_t)*extra > reg_domain_ids_len)) { + if ((*extra < 1) || ((size_t)*extra > acx_reg_domain_ids_len)) { result = -EINVAL; goto end; } acx_sem_lock(priv); - priv->reg_dom_id = reg_domain_ids[*extra - 1]; + priv->reg_dom_id = acx_reg_domain_ids[*extra - 1]; SET_BIT(priv->set_mask, GETSET_REG_DOMAIN); result = -EINPROGRESS; @@ -1767,9 +1770,9 @@ end: } -/*---------------------------------------------------------------- -* acx_ioctl_get_reg_domain -*----------------------------------------------------------------*/ +/*********************************************************************** +** acx_ioctl_get_reg_domain +*/ static int acx_ioctl_get_reg_domain( struct net_device *dev, @@ -1784,8 +1787,8 @@ acx_ioctl_get_reg_domain( dom = priv->reg_dom_id; for (i=1; i <= 7; i++) { - if (reg_domain_ids[i-1] == dom) { - acxlog(L_IOCTL, "regulatory domain is currently set " + if (acx_reg_domain_ids[i-1] == dom) { + log(L_IOCTL, "regulatory domain is currently set " "to %d (0x%X): %s\n", i, dom, reg_domain_strings[i-1]); *extra = i; @@ -1797,9 +1800,9 @@ acx_ioctl_get_reg_domain( } -/*---------------------------------------------------------------- -* acx_ioctl_set_short_preamble -*----------------------------------------------------------------*/ +/*********************************************************************** +** acx_ioctl_set_short_preamble +*/ static const char * const preamble_modes[] = { "off", @@ -1875,9 +1878,9 @@ end: } -/*---------------------------------------------------------------- -* acx_ioctl_get_short_preamble -*----------------------------------------------------------------*/ +/*********************************************************************** +** acx_ioctl_get_short_preamble +*/ static int acx_ioctl_get_short_preamble( struct net_device *dev, @@ -1901,12 +1904,12 @@ acx_ioctl_get_short_preamble( } -/*---------------------------------------------------------------- -* acx_ioctl_set_antenna -* -* Comment: TX and RX antenna can be set separately but this function good -* for testing 0-4 bits -*----------------------------------------------------------------*/ +/*********************************************************************** +** acx_ioctl_set_antenna +** +** TX and RX antenna can be set separately but this function good +** for testing 0-4 bits +*/ static int acx_ioctl_set_antenna( struct net_device *dev, @@ -1940,9 +1943,9 @@ acx_ioctl_set_antenna( } -/*---------------------------------------------------------------- -* acx_ioctl_get_antenna -*----------------------------------------------------------------*/ +/*********************************************************************** +** acx_ioctl_get_antenna +*/ static int acx_ioctl_get_antenna( struct net_device *dev, @@ -1967,14 +1970,12 @@ acx_ioctl_get_antenna( } -/*---------------------------------------------------------------- -* acx_ioctl_set_rx_antenna -* -* -* Arguments: -* 0 = antenna1; 1 = antenna2; 2 = full diversity; 3 = partial diversity -* Comment: Could anybody test which antenna is the external one -*----------------------------------------------------------------*/ +/*********************************************************************** +** acx_ioctl_set_rx_antenna +** +** 0 = antenna1; 1 = antenna2; 2 = full diversity; 3 = partial diversity +** Could anybody test which antenna is the external one? +*/ static int acx_ioctl_set_rx_antenna( struct net_device *dev, @@ -2009,13 +2010,12 @@ end: } -/*---------------------------------------------------------------- -* acx_ioctl_set_tx_antenna -* -* -* Arguments: 0 == antenna2; 1 == antenna1; -* Comment: Could anybody test which antenna is the external one -*----------------------------------------------------------------*/ +/*********************************************************************** +** acx_ioctl_set_tx_antenna +** +** Arguments: 0 == antenna2; 1 == antenna1; +** Could anybody test which antenna is the external one? +*/ static int acx_ioctl_set_tx_antenna( struct net_device *dev, @@ -2050,11 +2050,11 @@ end: } -/*---------------------------------------------------------------- -* acx_ioctl_wlansniff -* -* can we just remove this in favor of monitor mode? --vda -*----------------------------------------------------------------*/ +/*********************************************************************** +** acx_ioctl_wlansniff +** +** can we just remove this in favor of monitor mode? --vda +*/ static int acx_ioctl_wlansniff( struct net_device *dev, @@ -2073,7 +2073,7 @@ acx_ioctl_wlansniff( /* not using printk() here, since it distorts kismet display * when printk messages activated */ - acxlog(L_IOCTL, "setting monitor to: 0x%02X\n", params[0]); + log(L_IOCTL, "setting monitor to: 0x%02X\n", params[0]); switch (params[0]) { case 0: @@ -2105,10 +2105,10 @@ acx_ioctl_wlansniff( } -/*---------------------------------------------------------------- -* acx_ioctl_unknown11 -* FIXME: looks like some sort of "iwpriv kick_sta MAC" but it's broken -*----------------------------------------------------------------*/ +/*********************************************************************** +** acx_ioctl_unknown11 +** FIXME: looks like some sort of "iwpriv kick_sta MAC" but it's broken +*/ static int acx_ioctl_unknown11( struct net_device *dev, @@ -2153,14 +2153,14 @@ acx_ioctl_dbg_set_masks( acx_sem_lock(priv); - acxlog(L_IOCTL, "setting flags in settings mask: " + log(L_IOCTL, "setting flags in settings mask: " "get_mask %08X set_mask %08X\n" "before: get_mask %08X set_mask %08X\n", params[0], params[1], priv->get_mask, priv->set_mask); SET_BIT(priv->get_mask, params[0]); SET_BIT(priv->set_mask, params[1]); - acxlog(L_IOCTL, "after: get_mask %08X set_mask %08X\n", + log(L_IOCTL, "after: get_mask %08X set_mask %08X\n", priv->get_mask, priv->set_mask); result = -EINPROGRESS; /* immediately call commit handler */ @@ -2170,7 +2170,7 @@ acx_ioctl_dbg_set_masks( } -/*---------------------------------------------------------------- +/*********************************************************************** * acx_ioctl_set_rates * * This ioctl takes string parameter. Examples: @@ -2199,7 +2199,7 @@ acx_ioctl_dbg_set_masks( * (acx111 does not support CCK-OFDM, driver will reject this cmd) * iwpriv wlan0 SetRates "6,9,12 18,24,36,48,54" * 6,9,12 are basic, rest of 11g rates is enabled. Using OFDM -*----------------------------------------------------------------*/ +*/ #include "setrate.c" /* disallow: 33Mbit (unsupported by hw) */ @@ -2272,12 +2272,12 @@ acx_ioctl_set_rates(struct net_device *d FN_ENTER; - acxlog(L_IOCTL, "set_rates %s\n", extra); + log(L_IOCTL, "set_rates %s\n", extra); result = fill_ratemasks(extra, &brate, &orate, acx111_supported, acx111_gen_mask, 0); if (result) goto end; SET_BIT(orate, brate); - acxlog(L_IOCTL, "brate %08X orate %08X\n", brate, orate); + log(L_IOCTL, "brate %08X orate %08X\n", brate, orate); result = verify_rate(brate, priv->chip_type); if (result) goto end; @@ -2315,9 +2315,9 @@ end: } -/*---------------------------------------------------------------- -* acx_ioctl_get_phy_chan_busy_percentage -*----------------------------------------------------------------*/ +/*********************************************************************** +** acx_ioctl_get_phy_chan_busy_percentage +*/ static int acx_ioctl_get_phy_chan_busy_percentage( struct net_device *dev, @@ -2358,9 +2358,9 @@ end_unlock: } -/*---------------------------------------------------------------- -* acx_ioctl_set_ed_threshold -*----------------------------------------------------------------*/ +/*********************************************************************** +** acx_ioctl_set_ed_threshold +*/ static inline int acx_ioctl_set_ed_threshold( struct net_device *dev, @@ -2383,9 +2383,9 @@ acx_ioctl_set_ed_threshold( } -/*---------------------------------------------------------------- -* acx_ioctl_set_cca -*----------------------------------------------------------------*/ +/*********************************************************************** +** acx_ioctl_set_cca +*/ static inline int acx_ioctl_set_cca( struct net_device *dev, @@ -2612,7 +2612,7 @@ static const iw_handler acx_ioctl_handle #else /* IW_HANDLER_VERSION > 4 */ #ifdef WIRELESS_SPY (iw_handler) NULL /* acx_ioctl_set_spy FIXME */, /* SIOCSIWSPY */ - (iw_handler) NULL /* acx_ioctl_get_spy FIXME */, /* SIOCGIWSPY */ + (iw_handler) NULL /* acx_ioctl_get_spy */, /* SIOCGIWSPY */ #else /* WSPY */ (iw_handler) NULL, /* SIOCSIWSPY */ (iw_handler) NULL, /* SIOCGIWSPY */ @@ -2641,8 +2641,8 @@ static const iw_handler acx_ioctl_handle (iw_handler) acx_ioctl_get_rate, /* SIOCGIWRATE */ (iw_handler) acx_ioctl_set_rts, /* SIOCSIWRTS */ (iw_handler) acx_ioctl_get_rts, /* SIOCGIWRTS */ - (iw_handler) NULL /* acx_ioctl_set_frag FIXME */, /* SIOCSIWFRAG */ - (iw_handler) NULL /* acx_ioctl_get_frag FIXME */, /* SIOCGIWFRAG */ + (iw_handler) NULL /* acx_ioctl_set_frag FIXME*/, /* SIOCSIWFRAG */ + (iw_handler) NULL /* acx_ioctl_get_frag */, /* SIOCGIWFRAG */ (iw_handler) acx_ioctl_set_txpow, /* SIOCSIWTXPOW */ (iw_handler) acx_ioctl_get_txpow, /* SIOCGIWTXPOW */ (iw_handler) acx_ioctl_set_retry, /* SIOCSIWRETRY */ @@ -2698,17 +2698,15 @@ const struct iw_handler_def acx_ioctl_ha #if WIRELESS_EXT < 13 -/*================================================================*/ -/* Main function */ -/*================================================================*/ -/*---------------------------------------------------------------- -* acx_e_ioctl_old -* -* Comment: -* This is the *OLD* ioctl handler. -* Make sure to not only place your additions here, but instead mainly -* in the new one (acx_ioctl_handler[])! -*----------------------------------------------------------------*/ +/*********************************************************************** +** Main function +** +** acx_e_ioctl_old +** +** This is the *OLD* ioctl handler. +** Make sure to not only place your additions here, but instead mainly +** in the new one (acx_ioctl_handler[])! +*/ int acx_e_ioctl_old(netdevice_t *dev, struct ifreq *ifr, int cmd) { @@ -2716,7 +2714,7 @@ acx_e_ioctl_old(netdevice_t *dev, struct int result = 0; struct iwreq *iwr = (struct iwreq *)ifr; - acxlog(L_IOCTL, "%s cmd = 0x%04X\n", __func__, cmd); + log(L_IOCTL, "%s cmd = 0x%04X\n", __func__, cmd); /* This is the way it is done in the orinoco driver. * Check to see if device is present. @@ -2789,7 +2787,6 @@ acx_e_ioctl_old(netdevice_t *dev, struct result = acx_ioctl_get_iw_priv(iwr); break; - /* FIXME: */ /* case SIOCSIWSPY: */ /* case SIOCGIWSPY: */ /* case SIOCSIWTHRSPY: */ @@ -2814,7 +2811,6 @@ acx_e_ioctl_old(netdevice_t *dev, struct break; #if NOT_FINISHED_YET - /* FIXME: do proper interfacing to activate that! */ case SIOCSIWSCAN: /* start a station scan */ result = acx_ioctl_set_scan(iwr, priv); @@ -2915,7 +2911,6 @@ acx_e_ioctl_old(netdevice_t *dev, struct result = acx_ioctl_get_rts(dev, NULL, &(iwr->u.rts), NULL); break; - /* FIXME: */ /* case SIOCSIWFRAG: */ /* case SIOCGIWFRAG: */ @@ -3049,7 +3044,7 @@ acx_e_ioctl_old(netdevice_t *dev, struct break; case ACX100_IOCTL_MONITOR: /* set sniff (monitor) mode */ - acxlog(L_IOCTL, "%s: IWPRIV monitor\n", dev->name); + log(L_IOCTL, "%s: IWPRIV monitor\n", dev->name); /* can only be done by admin */ if (!capable(CAP_NET_ADMIN)) { @@ -3068,7 +3063,7 @@ acx_e_ioctl_old(netdevice_t *dev, struct break; default: - acxlog(L_IOCTL, "wireless ioctl 0x%04X queried " + log(L_IOCTL, "wireless ioctl 0x%04X queried " "but not implemented yet\n", cmd); result = -EOPNOTSUPP; break; @@ -3076,7 +3071,7 @@ acx_e_ioctl_old(netdevice_t *dev, struct if ((priv->dev_state_mask & ACX_STATE_IFACE_UP) && priv->set_mask) { acx_sem_lock(priv); - acx_s_update_card_settings(priv, 0, 0); + acx_s_update_card_settings(priv); acx_sem_unlock(priv); } diff -puN drivers/net/wireless/tiacx/pci.c~acx-driver-update drivers/net/wireless/tiacx/pci.c --- devel/drivers/net/wireless/tiacx/pci.c~acx-driver-update 2006-01-06 22:44:21.000000000 -0800 +++ devel-akpm/drivers/net/wireless/tiacx/pci.c 2006-01-06 22:44:21.000000000 -0800 @@ -192,7 +192,7 @@ get_txdesc(wlandevice_t* priv, int index } static inline txdesc_t* -move_txdesc(wlandevice_t* priv, txdesc_t* txdesc, int inc) +advance_txdesc(wlandevice_t* priv, txdesc_t* txdesc, int inc) { return (txdesc_t*) (((u8*)txdesc) + inc * priv->txdesc_size); } @@ -213,7 +213,7 @@ get_txhostdesc(wlandevice_t* priv, txdes return &priv->txhostdesc_start[index*2]; } -static client_t* +static inline client_t* get_txc(wlandevice_t* priv, txdesc_t* txdesc) { int index = (u8*)txdesc - (u8*)priv->txdesc_start; @@ -229,8 +229,16 @@ get_txc(wlandevice_t* priv, txdesc_t* tx return priv->txc[index]; } -static void -put_txc(wlandevice_t* priv, txdesc_t* txdesc, client_t* c) +static inline u16 +get_txr(wlandevice_t* priv, txdesc_t* txdesc) +{ + int index = (u8*)txdesc - (u8*)priv->txdesc_start; + index /= priv->txdesc_size; + return priv->txr[index]; +} + +static inline void +put_txcr(wlandevice_t* priv, txdesc_t* txdesc, client_t* c, u16 r111) { int index = (u8*)txdesc - (u8*)priv->txdesc_start; if (ACX_DEBUG && (index % priv->txdesc_size)) { @@ -243,6 +251,7 @@ put_txc(wlandevice_t* priv, txdesc_t* tx return; } priv->txc[index] = c; + priv->txr[index] = r111; } @@ -289,7 +298,7 @@ acxpci_read_eeprom_byte(wlandevice_t *pr } *charbuf = read_reg8(priv, IO_ACX_EEPROM_DATA); - acxlog(L_DEBUG, "EEPROM at 0x%04X = 0x%02X\n", addr, *charbuf); + log(L_DEBUG, "EEPROM at 0x%04X = 0x%02X\n", addr, *charbuf); result = OK; fail: @@ -298,22 +307,6 @@ fail: /*********************************************************************** -** Dummy EEPROM read? why?! -*/ -static int -acxpci_read_eeprom_area(wlandevice_t *priv) -{ - int offs; - u8 tmp[0x3b]; - - for (offs = 0x8c; offs < 0xb9; offs++) { - acxpci_read_eeprom_byte(priv, offs, &tmp[offs - 0x8c]); - } - return OK; -} - - -/*********************************************************************** ** We don't lock hw accesses here since we never r/w eeprom in IRQ ** Note: this function sleeps only because of GFP_KERNEL alloc */ @@ -437,10 +430,10 @@ acxpci_s_read_phy_reg(wlandevice_t *priv } } - acxlog(L_DEBUG, "count was %u\n", count); + log(L_DEBUG, "count was %u\n", count); *charbuf = read_reg8(priv, IO_ACX_PHY_DATA); - acxlog(L_DEBUG, "radio PHY at 0x%04X = 0x%02X\n", *charbuf, reg); + log(L_DEBUG, "radio PHY at 0x%04X = 0x%02X\n", *charbuf, reg); result = OK; goto fail; /* silence compiler warning */ fail: @@ -456,19 +449,14 @@ acxpci_s_write_phy_reg(wlandevice_t *pri { FN_ENTER; - /* FIXME: we didn't use 32bit access here since mprusko said that - * it results in distorted sensitivity on his card (huh!?!? - * doesn't happen with my setup...) - * But with the access reordering and flushing it - * shouldn't happen any more... - * FIXME: which radio is in the problematic card? My working one - * is 0x11 */ + /* mprusko said that 32bit accesses result in distorted sensitivity + * on his card. Unconfirmed, looks like it's not true. */ write_reg32(priv, IO_ACX_PHY_DATA, value); write_reg32(priv, IO_ACX_PHY_ADDR, reg); write_flush(priv); write_reg32(priv, IO_ACX_PHY_CTL, 1); write_flush(priv); - acxlog(L_DEBUG, "radio PHY write 0x%02X at 0x%04X\n", value, reg); + log(L_DEBUG, "radio PHY write 0x%02X at 0x%04X\n", value, reg); FN_EXIT1(OK); return OK; @@ -528,7 +516,7 @@ acxpci_s_write_fw(wlandevice_t *priv, co write_reg32(priv, IO_ACX_SLV_MEM_DATA, v32); } - acxlog(L_DEBUG, "firmware written, size:%d sum1:%x sum2:%x\n", + log(L_DEBUG, "firmware written, size:%d sum1:%x sum2:%x\n", size, sum, le32_to_cpu(apfw_image->chksum)); /* compare our checksum with the stored image checksum */ @@ -646,10 +634,10 @@ acxpci_s_upload_fw(wlandevice_t *priv) for (try = 1; try <= 5; try++) { res = acxpci_s_write_fw(priv, apfw_image, 0); - acxlog(L_DEBUG|L_INIT, "acx_write_fw (main/combined):%d\n", res); + log(L_DEBUG|L_INIT, "acx_write_fw (main/combined):%d\n", res); if (OK == res) { res = acxpci_s_validate_fw(priv, apfw_image, 0); - acxlog(L_DEBUG|L_INIT, "acx_validate_fw " + log(L_DEBUG|L_INIT, "acx_validate_fw " "(main/combined):%d\n", res); } @@ -678,7 +666,7 @@ int acxpci_s_upload_radio(wlandevice_t *priv) { acx_ie_memmap_t mm; - firmware_image_t *radio_image = NULL; + firmware_image_t *radio_image; acx_cmd_radioinit_t radioinit; int res = NOT_OK; int try; @@ -706,10 +694,10 @@ acxpci_s_upload_radio(wlandevice_t *priv for (try = 1; try <= 5; try++) { res = acxpci_s_write_fw(priv, radio_image, offset); - acxlog(L_DEBUG|L_INIT, "acx_write_fw (radio): %d\n", res); + log(L_DEBUG|L_INIT, "acx_write_fw (radio): %d\n", res); if (OK == res) { res = acxpci_s_validate_fw(priv, radio_image, offset); - acxlog(L_DEBUG|L_INIT, "acx_validate_fw (radio): %d\n", res); + log(L_DEBUG|L_INIT, "acx_validate_fw (radio): %d\n", res); } if (OK == res) @@ -765,12 +753,12 @@ acxpci_l_reset_mac(wlandevice_t *priv) /* now do soft reset of eCPU */ temp = read_reg16(priv, IO_ACX_SOFT_RESET) | 0x1; - acxlog(L_DEBUG, "%s: enable soft reset...\n", __func__); + log(L_DEBUG, "%s: enable soft reset...\n", __func__); write_reg16(priv, IO_ACX_SOFT_RESET, temp); write_flush(priv); /* now reset bit again */ - acxlog(L_DEBUG, "%s: disable soft reset and go to init mode...\n", __func__); + log(L_DEBUG, "%s: disable soft reset and go to init mode...\n", __func__); /* deassert eCPU reset */ write_reg16(priv, IO_ACX_SOFT_RESET, temp & ~0x1); @@ -790,17 +778,20 @@ static int acxpci_s_verify_init(wlandevice_t *priv) { int result = NOT_OK; - int timer; + unsigned long timeout; FN_ENTER; - for (timer = 40; timer > 0; timer--) { + timeout = jiffies + 2*HZ; + for (;;) { u16 irqstat = read_reg16(priv, IO_ACX_IRQ_STATUS_NON_DES); if (irqstat & HOST_INT_FCS_THRESHOLD) { result = OK; write_reg16(priv, IO_ACX_IRQ_ACK, HOST_INT_FCS_THRESHOLD); break; } + if (time_after(jiffies, timeout)) + break; /* Init may take up to ~0.5 sec total */ acx_s_msleep(50); } @@ -819,58 +810,34 @@ acxpci_s_verify_init(wlandevice_t *priv) */ /*********************************************************************** -** acxpci_write_cmd_type_or_status +** acxpci_write_cmd_type_status */ -static void -acxpci_write_cmd_type_or_status(wlandevice_t *priv, u32 val) -{ - write_reg32(priv, IO_ACX_SLV_END_CTL, 0x0); - write_reg32(priv, IO_ACX_SLV_MEM_CTL, 0x1); /* FIXME: why auto increment?? */ - write_reg32(priv, IO_ACX_SLV_MEM_ADDR, - read_reg32(priv, IO_ACX_CMD_MAILBOX_OFFS)); - - /* make sure we only write the data once all config registers are written */ - write_flush(priv); - write_reg32(priv, IO_ACX_SLV_MEM_DATA, val); - write_flush(priv); -} static inline void -acxpci_write_cmd_type(wlandevice_t *priv, u32 val) +acxpci_write_cmd_type_status(wlandevice_t *priv, u16 type, u16 status) { - acxpci_write_cmd_type_or_status(priv, val); -} -static inline void -acxpci_write_cmd_status(wlandevice_t *priv, u32 val) -{ - acxpci_write_cmd_type_or_status(priv, val<<16); + writel(type | (status << 16), priv->cmd_area); + write_flush(priv); } /*********************************************************************** -** acxpci_read_cmd_status +** acxpci_read_cmd_type_status */ -static void -acxpci_read_cmd_status(wlandevice_t *priv) +static u32 +acxpci_read_cmd_type_status(wlandevice_t *priv) { - u32 value; - - write_reg32(priv, IO_ACX_SLV_END_CTL, 0x0); - write_reg32(priv, IO_ACX_SLV_MEM_CTL, 0x1); /* FIXME: why auto increment?? */ + u32 cmd_type, cmd_status; - write_reg32(priv, IO_ACX_SLV_MEM_ADDR, - read_reg32(priv, IO_ACX_CMD_MAILBOX_OFFS)); - - /* make sure we only read the data once all config registers are written */ - write_flush(priv); - value = read_reg32(priv, IO_ACX_SLV_MEM_DATA); + cmd_type = readl(priv->cmd_area); + cmd_status = (cmd_type >> 16); + cmd_type = (u16)cmd_type; - priv->cmd_type = (u16)value; - priv->cmd_status = (value >> 16); + log(L_CTL, "cmd_type:%04X cmd_status:%04X [%s]\n", + cmd_type, cmd_status, + acx_cmd_status_str(cmd_status)); - acxlog(L_CTL, "cmd_type 0x%04X, cmd_status 0x%04X [%s]\n", - priv->cmd_type, priv->cmd_status, - acx_cmd_status_str(priv->cmd_status)); + return cmd_status; } @@ -890,10 +857,41 @@ acxpci_read_cmd_status(wlandevice_t *pri ** This resets the device using low level hardware calls ** as well as uploads and verifies the firmware to the card */ + +static inline void +init_mboxes(wlandevice_t *priv) +{ + u32 cmd_offs, info_offs; + + cmd_offs = read_reg32(priv, IO_ACX_CMD_MAILBOX_OFFS); + info_offs = read_reg32(priv, IO_ACX_INFO_MAILBOX_OFFS); + priv->cmd_area = (u8 *)priv->iobase2 + cmd_offs; + priv->info_area = (u8 *)priv->iobase2 + info_offs; + log(L_DEBUG, "iobase2=%p\n" + "cmd_mbox_offset=%X cmd_area=%p\n" + "info_mbox_offset=%X info_area=%p\n", + priv->iobase2, + cmd_offs, priv->cmd_area, + info_offs, priv->info_area); +} + + +static inline void +read_eeprom_area(wlandevice_t *priv) +{ +#if ACX_DEBUG > 1 + int offs; + u8 tmp; + + for (offs = 0x8c; offs < 0xb9; offs++) + acxpci_read_eeprom_byte(priv, offs, &tmp); +#endif +} + + static int -acxpci_s_reset_dev(netdevice_t *dev) +acxpci_s_reset_dev(wlandevice_t *priv) { - wlandevice_t *priv = netdev_priv(dev); const char* msg = ""; unsigned long flags; int result = NOT_OK; @@ -914,20 +912,20 @@ acxpci_s_reset_dev(netdevice_t *dev) ecpu_ctrl = read_reg16(priv, IO_ACX_ECPU_CTRL) & 1; if (!ecpu_ctrl) { msg = "eCPU is already running. "; - goto fail_unlock; + goto end_unlock; } #ifdef WE_DONT_NEED_THAT_DO_WE if (read_reg16(priv, IO_ACX_SOR_CFG) & 2) { /* eCPU most likely means "embedded CPU" */ msg = "eCPU did not start after boot from flash. "; - goto fail_unlock; + goto end_unlock; } /* check sense on reset flags */ if (read_reg16(priv, IO_ACX_SOR_CFG) & 0x10) { printk("%s: eCPU did not start after boot (SOR), " - "is this fatal?\n", dev->name); + "is this fatal?\n", priv->netdev->name); } #endif /* scan, if any, is stopped now, setting corresponding IRQ bit */ @@ -946,81 +944,42 @@ acxpci_s_reset_dev(netdevice_t *dev) /* load the firmware */ if (OK != acxpci_s_upload_fw(priv)) - goto fail; + goto end_fail; acx_s_msleep(10); /* now start eCPU by clearing bit */ - acxlog(L_DEBUG, "booted eCPU up and waiting for completion...\n"); + log(L_DEBUG, "booted eCPU up and waiting for completion...\n"); write_reg16(priv, IO_ACX_ECPU_CTRL, ecpu_ctrl & ~0x1); /* wait for eCPU bootup */ if (OK != acxpci_s_verify_init(priv)) { msg = "timeout waiting for eCPU. "; - goto fail; + goto end_fail; } + log(L_DEBUG, "eCPU has woken up, card is ready to be configured\n"); - acxlog(L_DEBUG, "eCPU has woken up, card is ready to be configured\n"); - - if (IS_ACX111(priv)) { - acxlog(L_DEBUG, "cleaning up cmd mailbox access area\n"); - acxpci_write_cmd_status(priv, 0); - acxpci_read_cmd_status(priv); - if (priv->cmd_status) { - msg = "error cleaning cmd mailbox area. "; - goto fail; - } - } + init_mboxes(priv); + acxpci_write_cmd_type_status(priv, 0, 0); /* Test that EEPROM is readable */ - if ((OK != acxpci_read_eeprom_area(priv)) && IS_ACX100(priv)) { - /* does "CIS" mean "Card Information Structure"? - * If so, then this would be a PCMCIA message... - */ - msg = "CIS error. "; - goto fail; - } + read_eeprom_area(priv); result = OK; - FN_EXIT1(result); - return result; + goto end; /* Finish error message. Indicate which function failed */ -fail_unlock: +end_unlock: acx_unlock(priv, flags); -fail: +end_fail: printk("acx: %sreset_dev() FAILED\n", msg); +end: FN_EXIT1(result); return result; } /*********************************************************************** -** acxpci_init_mboxes -*/ -void -acxpci_init_mboxes(wlandevice_t *priv) -{ - u32 cmd_offs, info_offs; - - FN_ENTER; - - cmd_offs = read_reg32(priv, IO_ACX_CMD_MAILBOX_OFFS); - info_offs = read_reg32(priv, IO_ACX_INFO_MAILBOX_OFFS); - priv->cmd_area = (u8 *)priv->iobase2 + cmd_offs + 0x4; - priv->info_area = (u8 *)priv->iobase2 + info_offs + 0x4; - acxlog(L_DEBUG, "iobase2=%p\n" - "cmd_mbox_offset=%X cmd_area=%p\n" - "info_mbox_offset=%X info_area=%p\n", - priv->iobase2, - cmd_offs, priv->cmd_area, - info_offs, priv->info_area); - - FN_EXIT0; -} - - -/*********************************************************************** ** acxpci_s_issue_cmd_timeo ** ** Sends command to fw, extract result @@ -1042,7 +1001,7 @@ acxpci_s_issue_cmd_timeo( unsigned int cmd, void *buffer, unsigned buflen, - unsigned timeout) + unsigned cmd_timeout) { #else int @@ -1051,7 +1010,7 @@ acxpci_s_issue_cmd_timeo_debug( unsigned cmd, void *buffer, unsigned buflen, - unsigned timeout, + unsigned cmd_timeout, const char* cmdstr) { unsigned long start = jiffies; @@ -1060,6 +1019,7 @@ acxpci_s_issue_cmd_timeo_debug( unsigned counter; u16 irqtype; u16 cmd_status; + unsigned long timeout; FN_ENTER; @@ -1067,8 +1027,8 @@ acxpci_s_issue_cmd_timeo_debug( if (!devname || !devname[0]) devname = "acx"; - acxlog(L_CTL, FUNC"(cmd:%s,buflen:%u,timeout:%ums,type:0x%04X)\n", - cmdstr, buflen, timeout, + log(L_CTL, FUNC"(cmd:%s,buflen:%u,timeout:%ums,type:0x%04X)\n", + cmdstr, buflen, cmd_timeout, buffer ? le16_to_cpu(((acx_ie_generic_t *)buffer)->type) : -1); if (!(priv->dev_state_mask & ACX_STATE_FW_LOADED)) { @@ -1083,25 +1043,32 @@ acxpci_s_issue_cmd_timeo_debug( } /* wait for firmware to become idle for our command submission */ - counter = 199; /* in ms */ + timeout = HZ/5; + counter = (timeout * 1000 / HZ) - 1; /* in ms */ + timeout += jiffies; do { - acxpci_read_cmd_status(priv); + cmd_status = acxpci_read_cmd_type_status(priv); /* Test for IDLE state */ - if (!priv->cmd_status) + if (!cmd_status) break; if (counter % 10 == 0) { + if (time_after(jiffies, timeout)) + { + counter = 0; + break; + } /* we waited 10 iterations, no luck. Sleep 10 ms */ acx_s_msleep(10); } - } while (--counter); + } while (likely(--counter)); if (!counter) { /* the card doesn't get idle, we're in trouble */ printk("%s: "FUNC"(): cmd_status is not IDLE: 0x%04X!=0\n", - devname, priv->cmd_status); + devname, cmd_status); goto bad; } else if (counter < 190) { /* if waited >10ms... */ - acxlog(L_CTL|L_DEBUG, FUNC"(): waited for IDLE %dms. " + log(L_CTL|L_DEBUG, FUNC"(): waited for IDLE %dms. " "Please report\n", 199 - counter); } @@ -1111,14 +1078,14 @@ acxpci_s_issue_cmd_timeo_debug( * of parameters to read, as data */ #if CMD_DISCOVERY if (cmd == ACX1xx_CMD_INTERROGATE) - memset(priv->cmd_area, 0xAA, buflen); + memset_io(priv->cmd_area + 4, 0xAA, buflen); #endif - memcpy(priv->cmd_area, buffer, + /* priv->cmd_area points to PCI device's memory, not to RAM! */ + memcpy_toio(priv->cmd_area + 4, buffer, (cmd == ACX1xx_CMD_INTERROGATE) ? 4 : buflen); } /* now write the actual command type */ - priv->cmd_type = cmd; - acxpci_write_cmd_type(priv, cmd); + acxpci_write_cmd_type_status(priv, cmd, 0); /* execute command */ write_reg16(priv, IO_ACX_INT_TRIG, INT_TRIG_CMD); write_flush(priv); @@ -1128,14 +1095,15 @@ acxpci_s_issue_cmd_timeo_debug( /* Ensure nonzero and not too large timeout. ** Also converts e.g. 100->99, 200->199 ** which is nice but not essential */ - timeout = (timeout-1) | 1; - if (unlikely(timeout > 1199)) - timeout = 1199; + cmd_timeout = (cmd_timeout-1) | 1; + if (unlikely(cmd_timeout > 1199)) + cmd_timeout = 1199; /* clear CMD_COMPLETE bit. can be set only by IRQ handler: */ priv->irq_status &= ~HOST_INT_CMD_COMPLETE; /* we schedule away sometimes (timeout can be large) */ - counter = timeout; + counter = cmd_timeout; + timeout = jiffies + cmd_timeout * HZ / 1000; do { if (!priv->irqs_active) { /* IRQ disabled: poll */ irqtype = read_reg16(priv, IO_ACX_IRQ_STATUS_NON_DES); @@ -1151,39 +1119,42 @@ acxpci_s_issue_cmd_timeo_debug( } if (counter % 10 == 0) { + if (time_after(jiffies, timeout)) + { + counter = 0; + break; + } /* we waited 10 iterations, no luck. Sleep 10 ms */ acx_s_msleep(10); } - } while (--counter); + } while (likely(--counter)); /* save state for debugging */ - acxpci_read_cmd_status(priv); - cmd_status = priv->cmd_status; + cmd_status = acxpci_read_cmd_type_status(priv); /* put the card in IDLE state */ - priv->cmd_status = 0; - acxpci_write_cmd_status(priv, 0); + acxpci_write_cmd_type_status(priv, 0, 0); if (!counter) { /* timed out! */ printk("%s: "FUNC"(): timed out %s for CMD_COMPLETE. " "irq bits:0x%04X irq_status:0x%04X timeout:%dms " "cmd_status:%d (%s)\n", devname, (priv->irqs_active) ? "waiting" : "polling", - irqtype, priv->irq_status, timeout, + irqtype, priv->irq_status, cmd_timeout, cmd_status, acx_cmd_status_str(cmd_status)); goto bad; - } else if (timeout - counter > 30) { /* if waited >30ms... */ - acxlog(L_CTL|L_DEBUG, FUNC"(): %s for CMD_COMPLETE %dms. " + } else if (cmd_timeout - counter > 30) { /* if waited >30ms... */ + log(L_CTL|L_DEBUG, FUNC"(): %s for CMD_COMPLETE %dms. " "count:%d. Please report\n", (priv->irqs_active) ? "waited" : "polled", - timeout - counter, counter); + cmd_timeout - counter, counter); } if (1 != cmd_status) { /* it is not a 'Success' */ printk("%s: "FUNC"(): cmd_status is not SUCCESS: %d (%s). " "Took %dms of %d\n", devname, cmd_status, acx_cmd_status_str(cmd_status), - timeout - counter, timeout); + cmd_timeout - counter, cmd_timeout); /* zero out result buffer */ if (buffer && buflen) memset(buffer, 0, buflen); @@ -1192,14 +1163,15 @@ acxpci_s_issue_cmd_timeo_debug( /* read in result parameters if needed */ if (buffer && buflen && (cmd == ACX1xx_CMD_INTERROGATE)) { - memcpy(buffer, priv->cmd_area, buflen); + /* priv->cmd_area points to PCI device's memory, not to RAM! */ + memcpy_fromio(buffer, priv->cmd_area + 4, buflen); if (acx_debug & L_DEBUG) { printk("output buffer (len=%u): ", buflen); acx_dump_bytes(buffer, buflen); } } /* ok: */ - acxlog(L_CTL, FUNC"(%s): took %ld jiffies to complete\n", + log(L_CTL, FUNC"(%s): took %ld jiffies to complete\n", cmdstr, jiffies - start); FN_EXIT1(OK); return OK; @@ -1219,168 +1191,6 @@ bad: /*********************************************************************** -** acx_s_get_firmware_version -** -** TODO: not pci-specific, move to common.c and use from usb.c too -*/ -static void -acx_s_get_firmware_version(wlandevice_t *priv) -{ - fw_ver_t fw; - u8 hexarr[4] = { 0, 0, 0, 0 }; - int hexidx = 0, val = 0; - const char *num; - char c; - - FN_ENTER; - - memset(fw.fw_id, 'E', FW_ID_SIZE); - acx_s_interrogate(priv, &fw, ACX1xx_IE_FWREV); - memcpy(priv->firmware_version, fw.fw_id, FW_ID_SIZE); - priv->firmware_version[FW_ID_SIZE] = '\0'; - - acxlog(L_DEBUG, "fw_ver: fw_id='%s' hw_id=%08X\n", - priv->firmware_version, fw.hw_id); - - if (strncmp(fw.fw_id, "Rev ", 4) != 0) { - printk("acx: strange firmware version string " - "'%s', please report\n", priv->firmware_version); - priv->firmware_numver = 0x01090407; /* assume 1.9.4.7 */ - } else { - num = &fw.fw_id[4]; - while (1) { - c = *num++; - if ((c == '.') || (c == '\0')) { - hexarr[hexidx++] = val; - if ((hexidx > 3) || (c == '\0')) /* end? */ - break; - val = 0; - continue; - } - if ((c >= '0') && (c <= '9')) - c -= '0'; - else - c = c - 'a' + (char)10; - val = val*16 + c; - } - - priv->firmware_numver = (u32)( - (hexarr[0] << 24) + (hexarr[1] << 16) - + (hexarr[2] << 8) + hexarr[3]); - acxlog(L_DEBUG, "firmware_numver 0x%08X\n", priv->firmware_numver); - } - if (IS_ACX111(priv)) { - if (priv->firmware_numver == 0x00010011) { - /* This one does not survive floodpinging */ - printk("acx: firmware '%s' is known to be buggy, " - "please upgrade\n", priv->firmware_version); - } - if (priv->firmware_numver == 0x02030131) { - /* With this one, all rx packets look mangled - ** Most probably we simply do not know how to use it - ** properly */ - printk("acx: firmware '%s' does not work well " - "with this driver\n", priv->firmware_version); - } - } - - priv->firmware_id = le32_to_cpu(fw.hw_id); - - /* we're able to find out more detailed chip names now */ - switch (priv->firmware_id & 0xffff0000) { - case 0x01010000: - case 0x01020000: - priv->chip_name = "TNETW1100A"; - break; - case 0x01030000: - priv->chip_name = "TNETW1100B"; - break; - case 0x03000000: - case 0x03010000: - priv->chip_name = "TNETW1130"; - break; - default: - printk("acx: unknown chip ID 0x%08X, " - "please report\n", priv->firmware_id); - break; - } - - FN_EXIT0; -} - - -/*********************************************************************** -** acx_display_hardware_details -** -** Displays hw/fw version, radio type etc... -** -** TODO: not pci-specific, move to common.c and use from usb.c too -*/ -static void -acx_display_hardware_details(wlandevice_t *priv) -{ - const char *radio_str, *form_str; - - FN_ENTER; - - switch (priv->radio_type) { - case RADIO_MAXIM_0D: - /* hmm, the DWL-650+ seems to have two variants, - * according to a windows driver changelog comment: - * RFMD and Maxim. */ - radio_str = "Maxim"; - break; - case RADIO_RFMD_11: - radio_str = "RFMD"; - break; - case RADIO_RALINK_15: - radio_str = "Ralink"; - break; - case RADIO_RADIA_16: - radio_str = "Radia"; - break; - case RADIO_UNKNOWN_17: - /* TI seems to have a radio which is - * additionally 802.11a capable, too */ - radio_str = "802.11a/b/g radio?! Please report"; - break; - case RADIO_UNKNOWN_19: - radio_str = "A radio used by Safecom cards?! Please report"; - break; - default: - radio_str = "UNKNOWN, please report the radio type name!"; - break; - } - - switch (priv->form_factor) { - case 0x00: - form_str = "unspecified"; - break; - case 0x01: - form_str = "(mini-)PCI / CardBus"; - break; - case 0x02: - form_str = "USB"; - break; - case 0x03: - form_str = "Compact Flash"; - break; - default: - form_str = "UNKNOWN, Please report"; - break; - } - - printk("acx: form factor 0x%02X (%s), " - "radio type 0x%02X (%s), EEPROM version 0x%02X, " - "uploaded firmware '%s' (0x%08X)\n", - priv->form_factor, form_str, priv->radio_type, radio_str, - priv->eeprom_version, priv->firmware_version, - priv->firmware_id); - - FN_EXIT0; -} - -/*********************************************************************** */ #ifdef NONESSENTIAL_FEATURES typedef struct device_id { @@ -1654,7 +1464,7 @@ IO_ACX111[] = 0x00b4, /* IO_ACX_INT_TRIG */ 0x00d4, /* IO_ACX_IRQ_MASK */ - /* we need NON_DES (0xf0), not NON_DES_MASK which is at 0xe0: */ + /* we do mean NON_DES (0xf0), not NON_DES_MASK which is at 0xe0: */ 0x00f0, /* IO_ACX_IRQ_STATUS_NON_DES */ 0x00e4, /* IO_ACX_IRQ_STATUS_CLEAR */ 0x00e8, /* IO_ACX_IRQ_ACK */ @@ -1769,38 +1579,33 @@ acxpci_e_probe(struct pci_dev *pdev, con /* Figure out our resources */ phymem1 = pci_resource_start(pdev, mem_region1); phymem2 = pci_resource_start(pdev, mem_region2); - - if (!request_mem_region(phymem1, pci_resource_len(pdev, mem_region1), "ACX1xx_1")) { + if (!request_mem_region(phymem1, pci_resource_len(pdev, mem_region1), "acx_1")) { printk("acx: cannot reserve PCI memory region 1 (are you sure " "you have CardBus support in kernel?)\n"); goto fail_request_mem_region1; } - - if (!request_mem_region(phymem2, pci_resource_len(pdev, mem_region2), "ACX1xx_2")) { + if (!request_mem_region(phymem2, pci_resource_len(pdev, mem_region2), "acx_2")) { printk("acx: cannot reserve PCI memory region 2\n"); goto fail_request_mem_region2; } - mem1 = ioremap(phymem1, mem_region1_size); - if (NULL == mem1) { + if (!mem1) { printk("acx: ioremap() FAILED\n"); goto fail_ioremap1; } - mem2 = ioremap(phymem2, mem_region2_size); - if (NULL == mem2) { + if (!mem2) { printk("acx: ioremap() #2 FAILED\n"); goto fail_ioremap2; } - /* Log the device */ printk("acx: found %s-based wireless network card at %s, irq:%d, " "phymem1:0x%lX, phymem2:0x%lX, mem1:0x%p, mem1_size:%ld, " "mem2:0x%p, mem2_size:%ld\n", chip_name, pci_name(pdev), pdev->irq, phymem1, phymem2, mem1, mem_region1_size, mem2, mem_region2_size); - acxlog(L_ANY, "initial debug setting is 0x%04X\n", acx_debug); + log(L_ANY, "initial debug setting is 0x%04X\n", acx_debug); if (0 == pdev->irq) { printk("acx: can't use IRQ 0\n"); @@ -1856,10 +1661,6 @@ acxpci_e_probe(struct pci_dev *pdev, con acx_show_card_eeprom_id(priv); #endif /* NONESSENTIAL_FEATURES */ - /* now we have our device, so make sure the kernel doesn't try - * to send packets even though we're not associated to a network yet */ - acx_stop_queue(dev, "after setup"); - #ifdef SET_MODULE_OWNER SET_MODULE_OWNER(dev); #endif @@ -1871,7 +1672,7 @@ acxpci_e_probe(struct pci_dev *pdev, con /* register new dev in linked list */ acxpci_s_device_chain_add(dev); - acxlog(L_IRQ|L_INIT, "using IRQ %d\n", pdev->irq); + log(L_IRQ|L_INIT, "using IRQ %d\n", pdev->irq); /* need to be able to restore PCI state after a suspend */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10) @@ -1881,36 +1682,26 @@ acxpci_e_probe(struct pci_dev *pdev, con #else pci_save_state(pdev, priv->pci_state); #endif + pci_set_drvdata(pdev, dev); + + /* ok, pci setup is finished, now start initialising the card */ /* NB: read_reg() reads may return bogus data before reset_dev(). ** acx100 seems to be more affected than acx111 */ - if (OK != acxpci_s_reset_dev(dev)) { + if (OK != acxpci_s_reset_dev(priv)) goto fail_reset; - } - - /* ok, basic setup is finished, now start initialising the card */ - if (OK != acxpci_read_eeprom_byte(priv, 0x05, &priv->eeprom_version)) { + if (OK != acxpci_read_eeprom_byte(priv, 0x05, &priv->eeprom_version)) goto fail_read_eeprom_version; - } - if (OK != acx_s_init_mac(dev)) { - printk("acx: init_mac() FAILED\n"); + if (OK != acx_s_init_mac(priv)) goto fail_init_mac; - } - if (OK != acx_s_set_defaults(priv)) { - printk("acx: set_defaults() FAILED\n"); - goto fail_set_defaults; - } - - /* needs to be after acx_s_init_mac() due to necessary init stuff */ - acx_s_get_firmware_version(priv); + acx_s_set_defaults(priv); + acx_s_get_firmware_version(priv); /* needs to be after acx_s_init_mac() */ acx_display_hardware_details(priv); - pci_set_drvdata(pdev, dev); - - /* ...and register the card, AFTER everything else has been set up, + /* Register the card, AFTER everything else has been set up, * since otherwise an ioctl could step on our feet due to * firmware operations happening in parallel or uninitialized data */ err = register_netdev(dev); @@ -1919,17 +1710,18 @@ acxpci_e_probe(struct pci_dev *pdev, con goto fail_register_netdev; } - acx_carrier_off(dev, "on probe"); + acx_proc_register_entries(dev); - if (OK != acx_proc_register_entries(dev)) { - goto fail_proc_register_entries; - } + /* Now we have our device, so make sure the kernel doesn't try + * to send packets even though we're not associated to a network yet */ + acx_stop_queue(dev, "on probe"); + acx_carrier_off(dev, "on probe"); /* after register_netdev() userspace may start working with dev * (in particular, on other CPUs), we only need to up the sem */ /* acx_sem_unlock(priv); */ - printk("acx "WLAN_RELEASE": net device %s, driver compiled " + printk("acx "ACX_RELEASE": net device %s, driver compiled " "against wireless extensions %d and Linux %s\n", dev->name, WIRELESS_EXT, UTS_RELEASE); @@ -1942,26 +1734,11 @@ acxpci_e_probe(struct pci_dev *pdev, con /* error paths: undo everything in reverse order... */ -#ifdef CONFIG_PROC_FS -fail_proc_register_entries: - - if (priv->dev_state_mask & ACX_STATE_IFACE_UP) - acxpci_s_down(dev); - - unregister_netdev(dev); - - /* after unregister_netdev() userspace is guaranteed to finish - * working with it. netdev does not exist anymore. - * For paranoid reasons I am taking sem anyway */ - acx_sem_lock(priv); -#endif - fail_register_netdev: acxpci_s_delete_dma_regions(priv); pci_set_drvdata(pdev, NULL); -fail_set_defaults: fail_init_mac: fail_read_eeprom_version: fail_reset: @@ -2019,7 +1796,7 @@ acxpci_e_remove(struct pci_dev *pdev) dev = (struct net_device *) pci_get_drvdata(pdev); if (!dev) { - acxlog(L_DEBUG, "%s: card is unused. Skipping any release code\n", + log(L_DEBUG, "%s: card is unused. Skipping any release code\n", __func__); goto end; } @@ -2030,7 +1807,7 @@ acxpci_e_remove(struct pci_dev *pdev) * (e.g. ioctls) access a half-deconfigured device * NB: this will cause acxpci_e_close() to be called, * thus we shouldn't call it under sem! */ - acxlog(L_INIT, "removing device %s\n", dev->name); + log(L_INIT, "removing device %s\n", dev->name); unregister_netdev(dev); /* unregister_netdev ensures that no references to us left. @@ -2092,7 +1869,11 @@ end: #ifdef CONFIG_PM static int if_was_up = 0; /* FIXME: HACK, do it correctly sometime instead */ static int +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11) acxpci_e_suspend(struct pci_dev *pdev, pm_message_t state) +#else +acxpci_e_suspend(struct pci_dev *pdev, u32 state) +#endif { struct net_device *dev = pci_get_drvdata(pdev); wlandevice_t *priv = netdev_priv(dev); @@ -2139,7 +1920,7 @@ acxpci_e_resume(struct pci_dev *pdev) FN_ENTER; printk("acx: experimental resume handler called for %p!\n", priv); pci_set_power_state(pdev, 0); - acxlog(L_DEBUG, "rsm: power state set\n"); + log(L_DEBUG, "rsm: power state set\n"); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10) /* 2.6.9-rc3-mm2 (2.6.9-bk4, too) introduced this shorter version, then it made its way into 2.6.10 */ @@ -2147,30 +1928,31 @@ acxpci_e_resume(struct pci_dev *pdev) #else pci_restore_state(pdev, priv->pci_state); #endif - acxlog(L_DEBUG, "rsm: PCI state restored\n"); - acxpci_s_reset_dev(dev); - acxlog(L_DEBUG, "rsm: device reset done\n"); + log(L_DEBUG, "rsm: PCI state restored\n"); + acxpci_s_reset_dev(priv); + log(L_DEBUG, "rsm: device reset done\n"); - if (OK != acx_s_init_mac(dev)) { - printk("rsm: init_mac FAILED\n"); + if (OK != acx_s_init_mac(priv)) goto fail; - } - acxlog(L_DEBUG, "rsm: init MAC done\n"); + log(L_DEBUG, "rsm: init MAC done\n"); if (1 == if_was_up) acxpci_s_up(dev); - acxlog(L_DEBUG, "rsm: acx up\n"); + log(L_DEBUG, "rsm: acx up\n"); /* now even reload all card parameters as they were before suspend, - * and possibly be back in the network again already :-) - * FIXME: should this be done in that scheduled task instead?? */ - if (ACX_STATE_IFACE_UP & priv->dev_state_mask) - acx_s_update_card_settings(priv, 0, 1); - acxlog(L_DEBUG, "rsm: settings updated\n"); + * and possibly be back in the network again already :-) */ + if (ACX_STATE_IFACE_UP & priv->dev_state_mask) { + priv->set_mask = GETSET_ALL; + acx_s_update_card_settings(priv); + } + log(L_DEBUG, "rsm: settings updated\n"); netif_device_attach(dev); - acxlog(L_DEBUG, "rsm: device attached\n"); + log(L_DEBUG, "rsm: device attached\n"); + fail: /* we need to return OK here anyway, right? */ acx_sem_unlock(priv); + FN_EXIT0; return OK; } @@ -2292,7 +2074,7 @@ acxpci_s_down(netdevice_t *dev) ** That's why we stop queue _after_ FLUSH_SCHEDULED_WORK ** lock/unlock is just paranoia, maybe not needed */ acx_lock(priv, flags); - acx_stop_queue(dev, "during close"); + acx_stop_queue(dev, "on ifdown"); acx_set_status(priv, ACX_STATUS_0_STOPPED); acx_unlock(priv, flags); @@ -2325,7 +2107,7 @@ acxpci_e_open(netdevice_t *dev) FN_ENTER; - acxlog(L_INIT, "module count++\n"); + log(L_INIT, "module count++\n"); WLAN_MOD_INC_USE_COUNT; acx_sem_lock(priv); @@ -2338,7 +2120,7 @@ acxpci_e_open(netdevice_t *dev) result = -EAGAIN; goto done; } - acxlog(L_DEBUG|L_IRQ, "request_irq %d successful\n", dev->irq); + log(L_DEBUG|L_IRQ, "request_irq %d successful\n", dev->irq); /* ifup device */ acxpci_s_up(dev); @@ -2394,12 +2176,12 @@ acxpci_e_close(netdevice_t *dev) * dev->tbusy==1. Our rx path knows to not pass up received * frames because of dev->flags&IFF_UP is false. */ - acxlog(L_INIT, "module count--\n"); + log(L_INIT, "module count--\n"); WLAN_MOD_DEC_USE_COUNT; acx_sem_unlock(priv); - acxlog(L_INIT, "closed device\n"); + log(L_INIT, "closed device\n"); FN_EXIT0; return OK; } @@ -2505,13 +2287,12 @@ static inline void log_rxbuffer(const wl static void log_rxbuffer(const wlandevice_t *priv) { - const struct rxhostdesc *rxhostdesc; + register const struct rxhostdesc *rxhostdesc; int i; - /* no FN_ENTER here, we don't want that */ rxhostdesc = priv->rxhostdesc_start; - if (!rxhostdesc) return; + if (unlikely(!rxhostdesc)) return; for (i = 0; i < RX_CNT; i++) { if ((rxhostdesc->Ctl_16 & cpu_to_le16(DESC_CTL_HOSTOWN)) && (rxhostdesc->Status & cpu_to_le32(DESC_STATUS_FULL))) @@ -2524,7 +2305,7 @@ log_rxbuffer(const wlandevice_t *priv) static void acxpci_l_process_rxdesc(wlandevice_t *priv) { - rxhostdesc_t *hostdesc; + register rxhostdesc_t *hostdesc; int count, tail; FN_ENTER; @@ -2535,8 +2316,8 @@ acxpci_l_process_rxdesc(wlandevice_t *pr /* First, have a loop to determine the first descriptor that's * full, just in case there's a mismatch between our current * rx_tail and the full descriptor we're supposed to handle. */ - count = RX_CNT; tail = priv->rx_tail; + count = RX_CNT; while (1) { hostdesc = &priv->rxhostdesc_start[tail]; /* advance tail regardless of outcome of the below test */ @@ -2546,13 +2327,13 @@ acxpci_l_process_rxdesc(wlandevice_t *pr && (hostdesc->Status & cpu_to_le32(DESC_STATUS_FULL))) break; /* found it! */ - if (--count) /* hmm, no luck: all descs empty, bail out */ + if (unlikely(!--count)) /* hmm, no luck: all descs empty, bail out */ goto end; } /* now process descriptors, starting with the first we figured out */ while (1) { - acxlog(L_BUFR, "rx: tail=%u Ctl_16=%04X Status=%08X\n", + log(L_BUFR, "rx: tail=%u Ctl_16=%04X Status=%08X\n", tail, hostdesc->Ctl_16, hostdesc->Status); acx_l_process_rxbuf(priv, hostdesc->data); @@ -2616,35 +2397,6 @@ more bytes may follow it does NOT clear bit 0x0001, and this bit will probably stay forever set after we set it once. Let's hope this will be fixed in firmware someday */ -static void -read_info_status(wlandevice_t *priv) -{ - u32 value; - - write_reg32(priv, IO_ACX_SLV_END_CTL, 0x0); - write_reg32(priv, IO_ACX_SLV_MEM_CTL, 0x1); - - write_reg32(priv, IO_ACX_SLV_MEM_ADDR, - read_reg32(priv, IO_ACX_INFO_MAILBOX_OFFS)); - - /* make sure we only read the data once all cfg registers are written: */ - write_flush(priv); - value = read_reg32(priv, IO_ACX_SLV_MEM_DATA); - - priv->info_type = (u16)value; - priv->info_status = (value >> 16); - - /* inform hw that we have read this info message */ - write_reg32(priv, IO_ACX_SLV_MEM_DATA, priv->info_type | 0x00010000); - write_flush(priv); - /* now bother hw to notice it: */ - write_reg16(priv, IO_ACX_INT_TRIG, INT_TRIG_INFOACK); - write_flush(priv); - - acxlog(L_CTL, "info_type 0x%04X, info_status 0x%04X\n", - priv->info_type, priv->info_status); -} - static void handle_info_irq(wlandevice_t *priv) @@ -2670,11 +2422,24 @@ handle_info_irq(wlandevice_t *priv) "TKIP IV value exceeds thresh" }; #endif - read_info_status(priv); - acxlog(L_IRQ, "got Info IRQ: status 0x%04X type 0x%04X: %s\n", - priv->info_status, priv->info_type, - info_type_msg[(priv->info_type >= VEC_SIZE(info_type_msg)) ? - 0 : priv->info_type] + u32 info_type, info_status; + + info_type = readl(priv->info_area); + info_status = (info_type >> 16); + info_type = (u16)info_type; + + /* inform fw that we have read this info message */ + writel(info_type | 0x00010000, priv->info_area); + write_reg16(priv, IO_ACX_INT_TRIG, INT_TRIG_INFOACK); + write_flush(priv); + + log(L_CTL, "info_type:%04X info_status:%04X\n", + info_type, info_status); + + log(L_IRQ, "got Info IRQ: status %04X type %04X: %s\n", + info_status, info_type, + info_type_msg[(info_type >= VEC_SIZE(info_type_msg)) ? + 0 : info_type] ); } @@ -2702,7 +2467,7 @@ log_unusual_irq(u16 irqtype) { printk(" Beacon"); } if (irqtype & HOST_INT_TIMER) { - acxlog(L_IRQ, " Timer"); + log(L_IRQ, " Timer"); } if (irqtype & HOST_INT_KEY_NOT_FOUND) { printk(" Key_Not_Found"); @@ -2755,7 +2520,8 @@ acxpci_i_interrupt(int irq, void *dev_id wlandevice_t *priv; unsigned long flags; unsigned int irqcount = MAX_IRQLOOPS_PER_JIFFY; - u16 irqtype, unmasked; + register u16 irqtype; + u16 unmasked; priv = (wlandevice_t *) (((netdevice_t *) dev_id)->priv); @@ -2767,11 +2533,8 @@ acxpci_i_interrupt(int irq, void *dev_id if (unlikely(0xffff == unmasked)) { /* 0xffff value hints at missing hardware, * so don't do anything. - * FIXME: that's not very clean - maybe we are able to - * establish a flag which definitely tells us that some - * hardware is absent and which we could check here? - * Hmm, but other drivers do the very same thing... */ - acxlog(L_IRQ, "IRQ type:FFFF - device removed? IRQ_NONE\n"); + * Not very clean, but other drivers do the same... */ + log(L_IRQ, "IRQ type:FFFF - device removed? IRQ_NONE\n"); goto none; } @@ -2779,7 +2542,7 @@ acxpci_i_interrupt(int irq, void *dev_id irqtype = unmasked & ~priv->irq_mask; if (!irqtype) { /* We are on a shared IRQ line and it wasn't our IRQ */ - acxlog(L_IRQ, "IRQ type:%04X, mask:%04X - all are masked, IRQ_NONE\n", + log(L_IRQ, "IRQ type:%04X, mask:%04X - all are masked, IRQ_NONE\n", unmasked, priv->irq_mask); goto none; } @@ -2797,21 +2560,21 @@ if (jiffies != priv->irq_last_jiffies) { /* safety condition; we'll normally abort loop below * in case no IRQ type occurred */ -while (--irqcount) { +while (likely(--irqcount)) { #endif - /* ACK all IRQs asap */ + /* ACK all IRQs ASAP */ write_reg16(priv, IO_ACX_IRQ_ACK, 0xffff); - acxlog(L_IRQ, "IRQ type:%04X, mask:%04X, type & ~mask:%04X\n", + log(L_IRQ, "IRQ type:%04X, mask:%04X, type & ~mask:%04X\n", unmasked, priv->irq_mask, irqtype); /* Handle most important IRQ types first */ if (irqtype & HOST_INT_RX_COMPLETE) { - acxlog(L_IRQ, "got Rx_Complete IRQ\n"); + log(L_IRQ, "got Rx_Complete IRQ\n"); acxpci_l_process_rxdesc(priv); } if (irqtype & HOST_INT_TX_COMPLETE) { - acxlog(L_IRQ, "got Tx_Complete IRQ\n"); + log(L_IRQ, "got Tx_Complete IRQ\n"); /* don't clean up on each Tx complete, wait a bit * unless we're going towards full, in which case * we do it immediately, too (otherwise we might lockup @@ -2834,7 +2597,7 @@ while (--irqcount) { | HOST_INT_SCAN_COMPLETE )) { if (irqtype & HOST_INT_CMD_COMPLETE) { - acxlog(L_IRQ, "got Command_Complete IRQ\n"); + log(L_IRQ, "got Command_Complete IRQ\n"); /* save the state for the running issue_cmd() */ SET_BIT(priv->irq_status, HOST_INT_CMD_COMPLETE); } @@ -2842,7 +2605,7 @@ while (--irqcount) { handle_info_irq(priv); } if (irqtype & HOST_INT_SCAN_COMPLETE) { - acxlog(L_IRQ, "got Scan_Complete IRQ\n"); + log(L_IRQ, "got Scan_Complete IRQ\n"); /* need to do that in process context */ acx_schedule_task(priv, ACX_AFTER_IRQ_COMPLETE_SCAN); /* remember that fw is not scanning anymore */ @@ -2920,7 +2683,7 @@ acxpci_l_power_led(wlandevice_t *priv, i static int rate_limit = 0; if (rate_limit++ < 3) - acxlog(L_IOCTL, "Please report in case toggling the power " + log(L_IOCTL, "Please report in case toggling the power " "LED doesn't work for your card!\n"); if (enable) write_reg16(priv, IO_ACX_GPIO_OUT, @@ -3175,7 +2938,7 @@ acx111pci_ioctl_info( txdesc->Ctl_8, txdesc->Ctl2_8, txdesc->error, txdesc->u.r1.rate); - txdesc = move_txdesc(priv, txdesc, 1); + txdesc = advance_txdesc(priv, txdesc, 1); } /* dump host tx descriptor ring buffer */ @@ -3252,7 +3015,7 @@ acx100pci_ioctl_set_phy_amp_bias( write_reg16(priv, IO_ACX_GPIO_OUT, (gpio_old & 0xf8ff) | ((u16)*extra << 8)); acx_unlock(priv, flags); - acxlog(L_DEBUG, "gpio_old: 0x%04X\n", gpio_old); + log(L_DEBUG, "gpio_old: 0x%04X\n", gpio_old); printk("%s: PHY power amplifier bias: old:%d, new:%d\n", dev->name, (gpio_old & 0x0700) >> 8, (unsigned char)*extra); @@ -3276,7 +3039,7 @@ acxpci_l_alloc_tx(wlandevice_t* priv) FN_ENTER; - if(!priv->tx_free) { + if (unlikely(!priv->tx_free)) { printk("acx: BUG: no free txdesc left\n"); txdesc = NULL; goto end; @@ -3301,13 +3064,12 @@ acxpci_l_alloc_tx(wlandevice_t* priv) txdesc->Ctl_8 = DESC_CTL_ACXDONE_HOSTOWN; priv->tx_free--; - acxlog(L_BUFT, "tx: got desc %u, %u remain\n", + log(L_BUFT, "tx: got desc %u, %u remain\n", head, priv->tx_free); - /* Keep a few free descs between head and tail of tx ring. ** It is not absolutely needed, just feels safer */ if (priv->tx_free < TX_STOP_QUEUE) { - acxlog(L_BUF, "stop queue (%u tx desc left)\n", + log(L_BUF, "stop queue (%u tx desc left)\n", priv->tx_free); acx_stop_queue(priv->netdev, NULL); } @@ -3342,6 +3104,7 @@ acxpci_l_tx_data(wlandevice_t *priv, tx_ txdesc_t *txdesc = (txdesc_t*)tx_opaque; txhostdesc_t *hostdesc1, *hostdesc2; client_t *clt; + u16 rate_cur; u8 Ctl_8, Ctl2_8; FN_ENTER; @@ -3351,14 +3114,14 @@ acxpci_l_tx_data(wlandevice_t *priv, tx_ goto end; hostdesc1 = get_txhostdesc(priv, txdesc); - hostdesc2 = hostdesc1 + 1; - /* modify flag status in separate variable to be able to write it back * in one big swoop later (also in order to have less device memory * accesses) */ Ctl_8 = txdesc->Ctl_8; Ctl2_8 = txdesc->Ctl2_8; + hostdesc2 = hostdesc1 + 1; + /* DON'T simply set Ctl field to 0 here globally, * it needs to maintain a consistent flag status (those are state flags!!), * otherwise it may lead to severe disruption. Only set or reset particular @@ -3372,13 +3135,6 @@ acxpci_l_tx_data(wlandevice_t *priv, tx_ else CLEAR_BIT(Ctl2_8, DESC_CTL2_RTS); -#ifdef DEBUG_WEP - if (priv->wep_enabled) - SET_BIT(Ctl2_8, DESC_CTL2_WEP); - else - CLEAR_BIT(Ctl2_8, DESC_CTL2_WEP); -#endif - switch (priv->mode) { case ACX_MODE_0_ADHOC: case ACX_MODE_3_AP: @@ -3413,18 +3169,18 @@ acxpci_l_tx_data(wlandevice_t *priv, tx_ break; } - if (unlikely(clt && !clt->rate_cur)) { + rate_cur = clt ? clt->rate_cur : priv->rate_bcast; + if (unlikely(!rate_cur)) { printk("acx: driver bug! bad ratemask\n"); goto end; } /* used in tx cleanup routine for auto rate and accounting: */ - put_txc(priv, txdesc, clt); + put_txcr(priv, txdesc, clt, rate_cur); txdesc->total_length = cpu_to_le16(len); hostdesc2->length = cpu_to_le16(len - WLAN_HDR_A3_LEN); if (IS_ACX111(priv)) { - u16 rate_cur = clt ? clt->rate_cur : priv->rate_bcast; /* note that if !txdesc->do_auto, txrate->cur ** has only one nonzero bit */ txdesc->u.r2.rate111 = cpu_to_le16( @@ -3471,11 +3227,10 @@ acxpci_l_tx_data(wlandevice_t *priv, tx_ /* write back modified flags */ txdesc->Ctl2_8 = Ctl2_8; txdesc->Ctl_8 = Ctl_8; - /* unused: txdesc->tx_time = cpu_to_le32(jiffies); */ -//TODO: should it be a mmiowb() instead? we are protecting against race with write[bwl]() + /* flush writes before we tell the adapter that it's its turn now */ - wmb(); + mmiowb(); write_reg16(priv, IO_ACX_INT_TRIG, INT_TRIG_TXPRC); write_flush(priv); @@ -3531,11 +3286,11 @@ log_txbuffer(wlandevice_t *priv) /* no FN_ENTER here, we don't want that */ /* no locks here, since it's entirely non-critical code */ txdesc = priv->txdesc_start; - if (!txdesc) return; + if (unlikely(!txdesc)) return; printk("tx: desc->Ctl8's:"); for (i = 0; i < TX_CNT; i++) { printk(" %02X", txdesc->Ctl_8); - txdesc = move_txdesc(priv, txdesc, 1); + txdesc = advance_txdesc(priv, txdesc, 1); } printk("\n"); } @@ -3636,162 +3391,10 @@ handle_tx_error(wlandevice_t *priv, u8 e } -/* maps acx100 tx descr rate field to acx111 one */ -static u16 -rate100to111(u8 r) -{ - switch (r) { - case RATE100_1: return RATE111_1; - case RATE100_2: return RATE111_2; - case RATE100_5: - case (RATE100_5 | RATE100_PBCC511): return RATE111_5; - case RATE100_11: - case (RATE100_11 | RATE100_PBCC511): return RATE111_11; - case RATE100_22: return RATE111_22; - default: - printk("acx: unexpected acx100 txrate: %u! " - "Please report\n", r); - return RATE111_2; - } -} - - -/* Theory of operation: -** client->rate_cap is a bitmask of rates client is capable of. -** client->rate_cfg is a bitmask of allowed (configured) rates. -** It is set as a result of iwconfig rate N [auto] -** or iwpriv set_rates "N,N,N N,N,N" commands. -** It can be fixed (e.g. 0x0080 == 18Mbit only), -** auto (0x00ff == 18Mbit or any lower value), -** and code handles any bitmask (0x1081 == try 54Mbit,18Mbit,1Mbit _only_). -** -** client->rate_cur is a value for rate111 field in tx descriptor. -** It is always set to txrate_cfg sans zero or more most significant -** bits. This routine handles selection of new rate_cur value depending on -** outcome of last tx event. -** -** client->rate_100 is a precalculated rate value for acx100 -** (we can do without it, but will need to calculate it on each tx). -** -** You cannot configure mixed usage of 5.5 and/or 11Mbit rate -** with PBCC and CCK modulation. Either both at CCK or both at PBCC. -** In theory you can implement it, but so far it is considered not worth doing. -** -** 22Mbit, of course, is PBCC always. */ - -static void -handle_txrate_auto(wlandevice_t *priv, struct client *txc, - unsigned int idx, u8 rate100, u16 rate111, u8 error) -{ - u16 sent_rate; - u16 cur = txc->rate_cur; - int slower_rate_was_used; - - /* FIXME: need to implement some kind of rate success memory - * which stores the success percentage per rate, to be taken - * into account when considering allowing a new rate, since it - * doesn't really help to stupidly count fallback/stepup, - * since one invalid rate will spoil the party anyway - * (such as 22M in case of 11M-only peers) */ - - /* vda: hmm. current code will do this: - ** 1. send packets at 11 Mbit, stepup++ - ** 2. will try to send at 22Mbit. hardware will see no ACK, - ** retries at 11Mbit, success. code notes that used rate - ** is lower. stepup = 0, fallback++ - ** 3. repeat step 2 fallback_count times. Fall back to - ** 11Mbit. go to step 1. - ** If stepup_count is large (say, 16) and fallback_count - ** is small (3), this wouldn't be too bad wrt throughput */ - - /* do some preparations, i.e. calculate the one rate that was - * used to send this packet */ - if (IS_ACX111(priv)) { - sent_rate = 1 << highest_bit(rate111 & RATE111_ALL); - } else { - sent_rate = rate100to111(rate100); - } - /* sent_rate has only one bit set now, corresponding to tx rate - * which was used by hardware to tx this particular packet */ - - /* now do the actual auto rate management */ - acxlog(L_DEBUG, "tx: %sclient=%p/"MACSTR" used=%04X cur=%04X cfg=%04X " - "__=%u/%u ^^=%u/%u\n", - (txc->ignore_count > 0) ? "[IGN] " : "", - txc, MAC(txc->address), sent_rate, cur, txc->rate_cfg, - txc->fallback_count, priv->fallback_threshold, - txc->stepup_count, priv->stepup_threshold - ); - - /* we need to ignore old packets already in the tx queue since - * they use older rate bytes configured before our last rate change, - * otherwise our mechanism will get confused by interpreting old data. - * Do it here only, in order to have the logging above */ - if (txc->ignore_count) { - txc->ignore_count--; - return; - } - - /* true only if the only nonzero bit in sent_rate is - ** less significant than highest nonzero bit in cur */ - slower_rate_was_used = ( cur > ((sent_rate<<1)-1) ); - - if (slower_rate_was_used || (error & 0x30)) { - txc->stepup_count = 0; - if (++txc->fallback_count <= priv->fallback_threshold) - return; - txc->fallback_count = 0; - - /* clear highest 1 bit in cur */ - sent_rate = RATE111_54; - while (!(cur & sent_rate)) sent_rate >>= 1; - CLEAR_BIT(cur, sent_rate); - - if (cur) { /* we can't disable all rates! */ - acxlog(L_XFER, "tx: falling back to ratemask %04X\n", cur); - txc->rate_cur = cur; - txc->ignore_count = TX_CNT - priv->tx_free; - } - } else if (!slower_rate_was_used) { - txc->fallback_count = 0; - if (++txc->stepup_count <= priv->stepup_threshold) - return; - txc->stepup_count = 0; - - /* sanitize. Sort of not needed, but I dont trust hw that much... - ** what if it can report bogus tx rates sometimes? */ - while (!(cur & sent_rate)) sent_rate >>= 1; - /* try to find a higher sent_rate that isn't yet in our - * current set, but is an allowed cfg */ - while (1) { - sent_rate <<= 1; - if (sent_rate > txc->rate_cfg) - /* no higher rates allowed by config */ - return; - if (!(cur & sent_rate) && (txc->rate_cfg & sent_rate)) - /* found */ - break; - /* not found, try higher one */ - } - SET_BIT(cur, sent_rate); - acxlog(L_XFER, "tx: stepping up to ratemask %04X\n", cur); - txc->rate_cur = cur; - /* FIXME: totally bogus - we could be sending to many peers at once... */ - txc->ignore_count = TX_CNT - priv->tx_free; - } - - /* calculate acx100 style rate byte if needed */ - if (IS_ACX100(priv)) { - txc->rate_100 = bitpos2rate100[highest_bit(cur)]; - } -} - - unsigned int acxpci_l_clean_txdesc(wlandevice_t *priv) { txdesc_t *txdesc; - struct client *txc; int finger; int num_cleaned; u16 r111; @@ -3802,7 +3405,7 @@ acxpci_l_clean_txdesc(wlandevice_t *priv if (unlikely(acx_debug & L_DEBUG)) log_txbuffer(priv); - acxlog(L_BUFT, "tx: cleaning up bufs from %u\n", priv->tx_tail); + log(L_BUFT, "tx: cleaning up bufs from %u\n", priv->tx_tail); /* We know first descr which is not free yet. We advance it as far ** as we see correct bits set in following descs (if next desc @@ -3812,7 +3415,7 @@ acxpci_l_clean_txdesc(wlandevice_t *priv finger = priv->tx_tail; num_cleaned = 0; - while (finger != priv->tx_head) { + while (likely(finger != priv->tx_head)) { txdesc = get_txdesc(priv, finger); /* If we allocated txdesc on tx path but then decided @@ -3821,14 +3424,11 @@ acxpci_l_clean_txdesc(wlandevice_t *priv ** We may meet it on the next ring pass here. */ /* stop if not marked as "tx finished" and "host owned" */ - if ((txdesc->Ctl_8 & DESC_CTL_ACXDONE_HOSTOWN) != DESC_CTL_ACXDONE_HOSTOWN) { - /* Moan a lot if none was cleaned */ - if (!num_cleaned) { - if (!(acx_debug & L_DEBUG)) - log_txbuffer(priv); - printk("%s: clean_tx_desc: tail is not free. " - "tail:%d head:%d. Please report\n", - priv->netdev->name, + if ((txdesc->Ctl_8 & DESC_CTL_ACXDONE_HOSTOWN) + != DESC_CTL_ACXDONE_HOSTOWN) { + if (unlikely(!num_cleaned)) { /* maybe remove completely */ + log(L_BUFT, "clean_txdesc: tail isn't free. " + "tail:%d head:%d\n", priv->tx_tail, priv->tx_head); } break; @@ -3874,7 +3474,7 @@ acxpci_l_clean_txdesc(wlandevice_t *priv && (priv->status == ACX_STATUS_4_ASSOCIATED) && (acx_queue_stopped(priv->netdev)) ) { - acxlog(L_BUF, "tx: wake queue (avail. Tx desc %u)\n", + log(L_BUF, "tx: wake queue (avail. Tx desc %u)\n", priv->tx_free); acx_wake_queue(priv->netdev, NULL); } @@ -3883,19 +3483,28 @@ acxpci_l_clean_txdesc(wlandevice_t *priv * AFTER having done the work, it's faster */ /* do rate handling */ - txc = get_txc(priv, txdesc); - if (txc && priv->rate_auto) { - handle_txrate_auto(priv, txc, finger, r100, r111, error); + if (priv->rate_auto) { + struct client *clt = get_txc(priv, txdesc); + if (clt) { + u16 cur = get_txr(priv, txdesc); + if (clt->rate_cur == cur) { + acx_l_handle_txrate_auto(priv, clt, + cur, /* intended rate */ + r100, r111, /* actually used rate */ + (error & 0x30), /* was there an error? */ + TX_CNT + TX_CLEAN_BACKLOG - priv->tx_free); + } + } } if (unlikely(error)) handle_tx_error(priv, error, finger); if (IS_ACX111(priv)) - acxlog(L_BUFT, "tx: cleaned %u: !ACK=%u !RTS=%u RTS=%u r111=%04X\n", + log(L_BUFT, "tx: cleaned %u: !ACK=%u !RTS=%u RTS=%u r111=%04X\n", finger, ack_failures, rts_failures, rts_ok, r111); else - acxlog(L_BUFT, "tx: cleaned %u: !ACK=%u !RTS=%u RTS=%u rate=%u\n", + log(L_BUFT, "tx: cleaned %u: !ACK=%u !RTS=%u RTS=%u rate=%u\n", finger, ack_failures, rts_failures, rts_ok, r100); /* update pointer for descr to be cleaned next */ @@ -3955,7 +3564,7 @@ allocate(wlandevice_t *priv, size_t size #endif if (ptr) { - acxlog(L_DEBUG, "%s sz=%d adr=0x%p phy=0x%08llx\n", + log(L_DEBUG, "%s sz=%d adr=0x%p phy=0x%08llx\n", msg, (int)size, ptr, (unsigned long long)*phy); memset(ptr, 0, size); return ptr; @@ -4195,7 +3804,7 @@ acxpci_create_tx_desc_queue(wlandevice_t priv->txdesc_start = (txdesc_t *) (priv->iobase2 + tx_queue_start); - acxlog(L_DEBUG, "priv->iobase2=%p\n" + log(L_DEBUG, "priv->iobase2=%p\n" "tx_queue_start=%08X\n" "priv->txdesc_start=%p\n", priv->iobase2, @@ -4220,7 +3829,7 @@ acxpci_create_tx_desc_queue(wlandevice_t /* reserve two (hdr desc and payload desc) */ hostdesc += 2; hostmemptr += 2 * sizeof(txhostdesc_t); - txdesc = move_txdesc(priv, txdesc, 1); + txdesc = advance_txdesc(priv, txdesc, 1); } } else { /* ACX100 Tx buffer needs to be initialized by us */ @@ -4229,16 +3838,15 @@ acxpci_create_tx_desc_queue(wlandevice_t /* loop over whole send pool */ for (i = 0; i < TX_CNT; i++) { - acxlog(L_DEBUG, "configure card tx descriptor: 0x%p, " + log(L_DEBUG, "configure card tx descriptor: 0x%p, " "size: 0x%X\n", txdesc, priv->txdesc_size); /* pointer to hostdesc memory */ - /* FIXME: type-incorrect assignment, might cause trouble - * in some cases */ txdesc->HostMemPtr = ptr2acx(hostmemptr); /* initialise ctl */ - txdesc->Ctl_8 = DESC_CTL_INIT; - txdesc->Ctl2_8 = 0; + txdesc->Ctl_8 = ( DESC_CTL_HOSTOWN | DESC_CTL_RECLAIM + | DESC_CTL_AUTODMA | DESC_CTL_FIRSTFRAG); + /* done by memset(0): txdesc->Ctl2_8 = 0; */ /* point to next txdesc */ txdesc->pNextDesc = cpu2acx(mem_offs + priv->txdesc_size); /* reserve two (hdr desc and payload desc) */ @@ -4281,7 +3889,7 @@ acxpci_create_rx_desc_queue(wlandevice_t rxdesc = priv->rxdesc_start; for (i = 0; i < RX_CNT; i++) { - acxlog(L_DEBUG, "rx descriptor %d @ 0x%p\n", i, rxdesc); + log(L_DEBUG, "rx descriptor %d @ 0x%p\n", i, rxdesc); rxdesc = priv->rxdesc_start = (rxdesc_t *) (priv->iobase2 + acx2cpu(rxdesc->pNextDesc)); } @@ -4291,7 +3899,7 @@ acxpci_create_rx_desc_queue(wlandevice_t priv->rxdesc_start = (rxdesc_t *) ((u8 *) priv->txdesc_start + (TX_CNT * sizeof(txdesc_t))); /* NB: sizeof(txdesc_t) above is valid because we know - ** we are in if(acx100) block. Beware of cut-n-pasting elsewhere! + ** we are in if (acx100) block. Beware of cut-n-pasting elsewhere! ** acx111's txdesc is larger! */ memset(priv->rxdesc_start, 0, RX_CNT * sizeof(rxdesc_t)); @@ -4300,7 +3908,7 @@ acxpci_create_rx_desc_queue(wlandevice_t rxdesc = priv->rxdesc_start; mem_offs = rx_queue_start; for (i = 0; i < RX_CNT; i++) { - acxlog(L_DEBUG, "rx descriptor @ 0x%p\n", rxdesc); + log(L_DEBUG, "rx descriptor @ 0x%p\n", rxdesc); rxdesc->Ctl_8 = DESC_CTL_RECLAIM | DESC_CTL_AUTODMA; /* point to next rxdesc */ rxdesc->pNextDesc = cpu2acx(mem_offs + sizeof(rxdesc_t)); @@ -4363,7 +3971,7 @@ acxpci_s_proc_diag_output(char *p, wland p += sprintf(p, "%02u free (%02X)%s%s\n", i, txdesc->Ctl_8, thd, ttl); else p += sprintf(p, "%02u tx (%02X)%s%s\n", i, txdesc->Ctl_8, thd, ttl); - txdesc = move_txdesc(priv, txdesc, 1); + txdesc = advance_txdesc(priv, txdesc, 1); } p += sprintf(p, "\n" @@ -4600,12 +4208,15 @@ acxpci_e_init_module(void) #endif #ifdef __LITTLE_ENDIAN - acxlog(L_INIT, "running on a little-endian CPU\n"); +#define ENDIANNESS_STRING "running on a little-endian CPU\n" #else - acxlog(L_INIT, "running on a BIG-ENDIAN CPU\n"); +#define ENDIANNESS_STRING "running on a BIG-ENDIAN CPU\n" #endif - acxlog(L_INIT, "PCI module " WLAN_RELEASE " initialized, " - "waiting for cards to probe...\n"); + log(L_INIT, + ENDIANNESS_STRING + "PCI module " ACX_RELEASE " initialized, " + "waiting for cards to probe...\n" + ); res = pci_module_init(&acxpci_drv_id); FN_EXIT1(res); @@ -4657,7 +4268,7 @@ acxpci_e_cleanup_module(void) acx_lock(priv, flags); /* disable power LED to save power :-) */ - acxlog(L_INIT, "switching off power LED to save power :-)\n"); + log(L_INIT, "switching off power LED to save power :-)\n"); acxpci_l_power_led(priv, 0); /* stop our eCPU */ diff -puN drivers/net/wireless/tiacx/usb.c~acx-driver-update drivers/net/wireless/tiacx/usb.c --- devel/drivers/net/wireless/tiacx/usb.c~acx-driver-update 2006-01-06 22:44:21.000000000 -0800 +++ devel-akpm/drivers/net/wireless/tiacx/usb.c 2006-01-06 22:44:21.000000000 -0800 @@ -38,10 +38,6 @@ ** Martin Wawro ** Andreas Mohr ** -** Issues: -** - Note that this driver relies on a native little-endian byteformat -** at some points -** ** LOCKING ** callback functions called by USB core are running in interrupt context ** and thus have names with _i_. @@ -90,30 +86,35 @@ #define ACX100_PRODUCT_ID_UNBOOTED 0x3B01 #define ACX100_PRODUCT_ID_BOOTED 0x3B00 -/* RX-Timeout: NONE (request waits forever) */ -#define ACX100_USB_RX_TIMEOUT (0) - -#define ACX100_USB_TX_TIMEOUT (4*HZ) +#define ACX_USB_CTRL_TIMEOUT 5500 /* steps in ms */ -#define USB_CTRL_HARD_TIMEOUT 5500 /* steps in ms */ +/* Buffer size for fw upload */ +#define ACX_USB_RWMEM_MAXLEN 2048 +/* The number of bulk URBs to use */ +#define ACX_TX_URB_CNT 8 +#define ACX_RX_URB_CNT 2 + +/* Should be sent to the bulkout endpoint */ +#define ACX_USB_REQ_UPLOAD_FW 0x10 +#define ACX_USB_REQ_ACK_CS 0x11 +#define ACX_USB_REQ_CMD 0x12 /*********************************************************************** ** Prototypes */ -static int acx100usb_e_probe(struct usb_interface *, const struct usb_device_id *); -static void acx100usb_e_disconnect(struct usb_interface *); -static void acx100usb_i_complete_tx(struct urb *, struct pt_regs *); -static void acx100usb_i_complete_rx(struct urb *, struct pt_regs *); -static int acx100usb_e_open(struct net_device *); -static int acx100usb_e_close(struct net_device *); -static void acx100usb_i_set_rx_mode(struct net_device *); -static int acx100usb_e_init_network_device(struct net_device *); -static int acx100usb_boot(struct usb_device *); +static int acxusb_e_probe(struct usb_interface *, const struct usb_device_id *); +static void acxusb_e_disconnect(struct usb_interface *); +static void acxusb_i_complete_tx(struct urb *, struct pt_regs *); +static void acxusb_i_complete_rx(struct urb *, struct pt_regs *); +static int acxusb_e_open(struct net_device *); +static int acxusb_e_close(struct net_device *); +static void acxusb_i_set_rx_mode(struct net_device *); +static int acxusb_boot(struct usb_device *); -static void acx100usb_l_poll_rx(wlandevice_t *, usb_rx_t* rx); +static void acxusb_l_poll_rx(wlandevice_t *, usb_rx_t* rx); -static void acx100usb_i_tx_timeout(struct net_device *); +static void acxusb_i_tx_timeout(struct net_device *); /* static void dump_device(struct usb_device *); */ /* static void dump_device_descriptor(struct usb_device_descriptor *); */ @@ -123,13 +124,16 @@ static void acx100usb_i_tx_timeout(struc ** Module Data */ #define TXBUFSIZE sizeof(usb_txbuffer_t) -//// Bogus! We CANNOT pretend that rxbuffer_t is larger than it is. -/* make it a multiply of 64 */ -/* #define RXBUFSIZE ((sizeof(rxbuffer_t)+63) & ~63) */ -#define RXBUFSIZE sizeof(rxbuffer_t) +/* + * Now, this is just plain lying, but the device insists in giving us + * huge packets. We supply extra space after rxbuffer. Need to understand + * it better... + */ +#define RXBUFSIZE (sizeof(rxbuffer_t) + \ + (sizeof(usb_rx_t) - sizeof(struct usb_rx_plain))) static const struct usb_device_id -acx100usb_ids[] = { +acxusb_ids[] = { { USB_DEVICE(ACX100_VENDOR_ID, ACX100_PRODUCT_ID_BOOTED) }, { USB_DEVICE(ACX100_VENDOR_ID, ACX100_PRODUCT_ID_UNBOOTED) }, {} @@ -138,11 +142,11 @@ acx100usb_ids[] = { /* USB driver data structure as required by the kernel's USB core */ static struct usb_driver -acx100usb_driver = { +acxusb_driver = { .name = "acx_usb", - .probe = acx100usb_e_probe, - .disconnect = acx100usb_e_disconnect, - .id_table = acx100usb_ids + .probe = acxusb_e_probe, + .disconnect = acxusb_e_disconnect, + .id_table = acxusb_ids }; @@ -208,7 +212,7 @@ acxusb_s_read_phy_reg(wlandevice_t *priv mem.len = cpu_to_le32(4); acx_s_issue_cmd(priv, ACX1xx_CMD_MEM_READ, &mem, sizeof(mem)); *charbuf = mem.data; - acxlog(L_DEBUG, "read radio PHY[0x%04X]=0x%02X\n", reg, *charbuf); + log(L_DEBUG, "read radio PHY[0x%04X]=0x%02X\n", reg, *charbuf); FN_EXIT1(OK); return OK; @@ -229,7 +233,7 @@ acxusb_s_write_phy_reg(wlandevice_t *pri mem.len = cpu_to_le32(4); mem.data = value; acx_s_issue_cmd(priv, ACX1xx_CMD_MEM_WRITE, &mem, sizeof(mem)); - acxlog(L_DEBUG, "write radio PHY[0x%04X]=0x%02X\n", reg, value); + log(L_DEBUG, "write radio PHY[0x%04X]=0x%02X\n", reg, value); FN_EXIT1(OK); return OK; @@ -237,7 +241,7 @@ acxusb_s_write_phy_reg(wlandevice_t *pri /*********************************************************************** -** acx_s_issue_cmd_timeo +** acxusb_s_issue_cmd_timeo ** Excecutes a command in the command mailbox ** ** buffer = a pointer to the data. @@ -287,10 +291,11 @@ acxusb_s_issue_cmd_timeo_debug( FN_ENTER; devname = priv->netdev->name; - if (!devname || !devname[0]) + /* no "wlan%%d: ..." please */ + if (!devname || !devname[0] || devname[4]=='%') devname = "acx"; - acxlog(L_CTL, FUNC"(cmd:%s,buflen:%u,type:0x%04X)\n", + log(L_CTL, FUNC"(cmd:%s,buflen:%u,type:0x%04X)\n", cmdstr, buflen, buffer ? le16_to_cpu(((acx_ie_generic_t *)buffer)->type) : -1); @@ -334,8 +339,8 @@ acxusb_s_issue_cmd_timeo_debug( /* obtain the I/O pipes */ outpipe = usb_sndctrlpipe(usbdev, 0); inpipe = usb_rcvctrlpipe(usbdev, 0); - acxlog(L_CTL, "ctrl inpipe=0x%X outpipe=0x%X\n", inpipe, outpipe); - acxlog(L_CTL, "sending USB control msg (out) (blocklen=%d)\n", blocklen); + log(L_CTL, "ctrl inpipe=0x%X outpipe=0x%X\n", inpipe, outpipe); + log(L_CTL, "sending USB control msg (out) (blocklen=%d)\n", blocklen); if (acx_debug & L_DATA) acx_dump_bytes(loc, blocklen); @@ -346,21 +351,21 @@ acxusb_s_issue_cmd_timeo_debug( 0, /* index */ loc, /* dataptr */ blocklen, /* size */ - USB_CTRL_HARD_TIMEOUT /* timeout in ms */ + ACX_USB_CTRL_TIMEOUT /* timeout in ms */ ); if (result == -ENODEV) { - acxlog(L_CTL, "no device present (unplug?)\n"); + log(L_CTL, "no device present (unplug?)\n"); goto good; } - acxlog(L_CTL, "wrote %d bytes\n", result); + log(L_CTL, "wrote %d bytes\n", result); if (result < 0) { goto bad; } /* check for device acknowledge */ - acxlog(L_CTL, "sending USB control msg (in) (acklen=%d)\n", acklen); + log(L_CTL, "sending USB control msg (in) (acklen=%d)\n", acklen); loc->status = 0; /* delete old status flag -> set to IDLE */ //shall we zero out the rest? result = usb_control_msg(usbdev, inpipe, @@ -370,7 +375,7 @@ acxusb_s_issue_cmd_timeo_debug( 0, /* index */ loc, /* dataptr */ acklen, /* size */ - USB_CTRL_HARD_TIMEOUT /* timeout in ms */ + ACX_USB_CTRL_TIMEOUT /* timeout in ms */ ); if (result < 0) { printk("%s: "FUNC"(): USB read error %d\n", devname, result); @@ -401,7 +406,7 @@ read 4 bytes <==== MUST BE 12!! } if ((cmd == ACX1xx_CMD_INTERROGATE) && buffer && buflen) { memcpy(buffer, loc->data, buflen); - acxlog(L_CTL, "response frame: cmd=0x%04X status=%d\n", + log(L_CTL, "response frame: cmd=0x%04X status=%d\n", le16_to_cpu(loc->cmd), cmd_status); } @@ -425,29 +430,141 @@ bad: /*********************************************************************** -** acx100usb_e_probe() -** +** acxusb_boot() ** Inputs: -** dev -> Pointer to usb_device structure that may or may not be claimed -** ifNum -> Interface number -** devID -> Device ID (vendor and product specific stuff) -************************************************************************ +** usbdev -> Pointer to kernel's usb_device structure +** ** Returns: -** (void *) Pointer to (custom) driver context or NULL if we are not interested -** or unable to handle the offered device. +** (int) Errorcode or 0 on success ** -** Description: -** This function is invoked by the kernel's USB core whenever a new device is -** attached to the system or the module is loaded. It is presented a usb_device -** structure from which information regarding the device is obtained and evaluated. -** In case this driver is able to handle one of the offered devices, it returns -** a non-null pointer to a driver context and thereby claims the device. +** This function triggers the loading of the firmware image from harddisk +** and then uploads the firmware to the USB device. After uploading the +** firmware and transmitting the checksum, the device resets and appears +** as a new device on the USB bus (the device we can finally deal with) */ +static int +acxusb_boot(struct usb_device *usbdev) +{ + static const char filename[] = "tiacx100usb"; + + char *firmware = NULL; + char *usbbuf; + unsigned int offset; + unsigned int len, inpipe, outpipe; + u32 checksum; + u32 size; + int result; + + FN_ENTER; + + usbbuf = kmalloc(ACX_USB_RWMEM_MAXLEN, GFP_KERNEL); + if (!usbbuf) { + printk(KERN_ERR "acx: no memory for USB transfer buffer (" + STRING(ACX_USB_RWMEM_MAXLEN)" bytes)\n"); + result = -ENOMEM; + goto end; + } + firmware = (char *)acx_s_read_fw(&usbdev->dev, filename, &size); + if (!firmware) { + result = -EIO; + goto end; + } + log(L_INIT, "firmware size: %d bytes\n", size); + + /* Obtain the I/O pipes */ + outpipe = usb_sndctrlpipe(usbdev, 0); + inpipe = usb_rcvctrlpipe(usbdev, 0); + + /* now upload the firmware, slice the data into blocks */ + offset = 8; + while (offset < size) { + len = size - offset; + if (len >= ACX_USB_RWMEM_MAXLEN) { + len = ACX_USB_RWMEM_MAXLEN; + } + log(L_INIT, "uploading firmware (%d bytes, offset=%d)\n", + len, offset); + result = 0; + memcpy(usbbuf, firmware + offset, len); + result = usb_control_msg(usbdev, outpipe, + ACX_USB_REQ_UPLOAD_FW, + USB_TYPE_VENDOR|USB_DIR_OUT, + size - 8, /* value */ + 0, /* index */ + usbbuf, /* dataptr */ + len, /* size */ + 3000 /* timeout in ms */ + ); + offset += len; + if (result < 0) { + printk(KERN_ERR "acx: error %d during upload " + "of firmware, aborting\n", result); + goto end; + } + } + + /* finally, send the checksum and reboot the device */ + checksum = le32_to_cpu(*(u32 *)firmware); + /* is this triggers the reboot? */ + result = usb_control_msg(usbdev, outpipe, + ACX_USB_REQ_UPLOAD_FW, + USB_TYPE_VENDOR|USB_DIR_OUT, + checksum & 0xffff, /* value */ + checksum >> 16, /* index */ + NULL, /* dataptr */ + 0, /* size */ + 3000 /* timeout in ms */ + ); + if (result < 0) { + printk(KERN_ERR "acx: error %d during tx of checksum, " + "aborting\n", result); + goto end; + } + result = usb_control_msg(usbdev, inpipe, + ACX_USB_REQ_ACK_CS, + USB_TYPE_VENDOR|USB_DIR_IN, + checksum & 0xffff, /* value */ + checksum >> 16, /* index */ + usbbuf, /* dataptr */ + 8, /* size */ + 3000 /* timeout in ms */ + ); + if (result < 0) { + printk(KERN_ERR "acx: error %d during ACK of checksum, " + "aborting\n", result); + goto end; + } + if (*usbbuf != 0x10) { + kfree(usbbuf); + printk(KERN_ERR "acx: invalid checksum?\n"); + result = -EINVAL; + goto end; + } + result = 0; +end: + vfree(firmware); + kfree(usbbuf); + + FN_EXIT1(result); + return result; +} + + +/*********************************************************************** +** acxusb_e_probe() +** +** This function is invoked by the kernel's USB core whenever a new device is +** attached to the system or the module is loaded. It is presented a usb_device +** structure from which information regarding the device is obtained and evaluated. +** In case this driver is able to handle one of the offered devices, it returns +** a non-null pointer to a driver context and thereby claims the device. +*/ + static void dummy_netdev_init(struct net_device *dev) {} static int -acx100usb_e_probe(struct usb_interface *intf, const struct usb_device_id *devID) +acxusb_e_probe(struct usb_interface *intf, const struct usb_device_id *devID) { struct usb_device *usbdev = interface_to_usbdev(intf); wlandevice_t *priv = NULL; @@ -469,14 +586,14 @@ acx100usb_e_probe(struct usb_interface * if ((usbdev->descriptor.idVendor == ACX100_VENDOR_ID) && (usbdev->descriptor.idProduct == ACX100_PRODUCT_ID_UNBOOTED)) { /* Boot the device (i.e. upload the firmware) */ - acx100usb_boot(usbdev); + acxusb_boot(usbdev); /* OK, we are done with booting. Normally, the ** ID for the unbooted device should disappear ** and it will not need a driver anyway...so ** return a NULL */ - acxlog(L_INIT, "finished booting, returning from probe()\n"); + log(L_INIT, "finished booting, returning from probe()\n"); result = OK; /* success */ goto end; } @@ -486,18 +603,40 @@ acx100usb_e_probe(struct usb_interface * goto end_nodev; } - /* Ok, so it's our device and it is already booted */ +/* Ok, so it's our device and it has already booted */ /* Allocate memory for a network device */ + dev = alloc_netdev(sizeof(wlandevice_t), "wlan%d", dummy_netdev_init); /* (NB: memsets to 0 entire area) */ if (!dev) { msg = "acx: no memory for netdev\n"; goto end_nomem; } - dev->init = (void *)&acx100usb_e_init_network_device; + + /* Register the callbacks for the network device functions */ + + ether_setup(dev); + dev->open = &acxusb_e_open; + dev->stop = &acxusb_e_close; + dev->hard_start_xmit = (void *)&acx_i_start_xmit; + dev->get_stats = (void *)&acx_e_get_stats; + dev->get_wireless_stats = (void *)&acx_e_get_wireless_stats; +#if WIRELESS_EXT >= 13 + dev->wireless_handlers = (struct iw_handler_def *)&acx_ioctl_handler_def; +#else + dev->do_ioctl = (void *)&acx_e_ioctl_old; +#endif + dev->set_multicast_list = (void *)&acxusb_i_set_rx_mode; +#ifdef HAVE_TX_TIMEOUT + dev->tx_timeout = &acxusb_i_tx_timeout; + dev->watchdog_timeo = 4 * HZ; +#endif + dev->change_mtu = &acx_e_change_mtu; + SET_MODULE_OWNER(dev); /* Setup private driver context */ + priv = netdev_priv(dev); priv->netdev = dev; priv->dev_type = DEVTYPE_USB; @@ -505,12 +644,10 @@ acx100usb_e_probe(struct usb_interface * /* FIXME: should be read from register (via firmware) using standard ACX code */ priv->radio_type = RADIO_MAXIM_0D; priv->usbdev = usbdev; - spin_lock_init(&priv->lock); /* initial state: unlocked */ sema_init(&priv->sem, 1); /* initial state: 1 (upped) */ - /* Initialize the device context and also check - ** if this is really the hardware we know about. + /* Check that this is really the hardware we know about. ** If not sure, at least notify the user that he ** may be in trouble... */ @@ -529,7 +666,7 @@ acx100usb_e_probe(struct usb_interface * ifdesc = &intf->altsetting->desc; numep = ifdesc->bNumEndpoints; - acxlog(L_DEBUG, "# of endpoints: %d\n", numep); + log(L_DEBUG, "# of endpoints: %d\n", numep); /* obtain information about the endpoint ** addresses, begin with some default values @@ -554,32 +691,27 @@ acx100usb_e_probe(struct usb_interface * priv->bulkoutep = epdesc->bEndpointAddress & 0xF; } } - acxlog(L_DEBUG, "bulkout ep: 0x%X\n", priv->bulkoutep); - acxlog(L_DEBUG, "bulkin ep: 0x%X\n", priv->bulkinep); + log(L_DEBUG, "bulkout ep: 0x%X\n", priv->bulkoutep); + log(L_DEBUG, "bulkin ep: 0x%X\n", priv->bulkinep); - /* Set the packet-size equivalent to the buffer size */ /* already done by memset: priv->rxtruncsize = 0; */ - acxlog(L_DEBUG, "TXBUFSIZE=%d RXBUFSIZE=%d\n", + log(L_DEBUG, "TXBUFSIZE=%d RXBUFSIZE=%d\n", (int) TXBUFSIZE, (int) RXBUFSIZE); - priv->tx_free = ACX100_USB_NUM_BULK_URBS; - /* Allocate the RX/TX containers. */ - priv->usb_tx = kmalloc(sizeof(usb_tx_t) * ACX100_USB_NUM_BULK_URBS, - GFP_KERNEL); + priv->usb_tx = kmalloc(sizeof(usb_tx_t) * ACX_TX_URB_CNT, GFP_KERNEL); if (!priv->usb_tx) { msg = "acx: no memory for tx container"; goto end_nomem; } - priv->usb_rx = kmalloc(sizeof(usb_rx_t) * ACX100_USB_NUM_BULK_URBS, - GFP_KERNEL); + priv->usb_rx = kmalloc(sizeof(usb_rx_t) * ACX_RX_URB_CNT, GFP_KERNEL); if (!priv->usb_rx) { msg = "acx: no memory for rx container"; goto end_nomem; } /* Setup URBs for bulk-in/out messages */ - for (i = 0; i < ACX100_USB_NUM_BULK_URBS; i++) { + for (i = 0; i < ACX_RX_URB_CNT; i++) { priv->usb_rx[i].urb = usb_alloc_urb(0, GFP_KERNEL); if (!priv->usb_rx[i].urb) { msg = "acx: no memory for input URB\n"; @@ -587,7 +719,10 @@ acx100usb_e_probe(struct usb_interface * } priv->usb_rx[i].urb->status = 0; priv->usb_rx[i].priv = priv; + priv->usb_rx[i].busy = 0; + } + for (i = 0; i< ACX_TX_URB_CNT; i++) { priv->usb_tx[i].urb = usb_alloc_urb(0, GFP_KERNEL); if (!priv->usb_tx[i].urb) { msg = "acx: no memory for output URB\n"; @@ -595,25 +730,41 @@ acx100usb_e_probe(struct usb_interface * } priv->usb_tx[i].urb->status = 0; priv->usb_tx[i].priv = priv; + priv->usb_tx[i].busy = 0; } + priv->tx_free = ACX_TX_URB_CNT; usb_set_intfdata(intf, priv); SET_NETDEV_DEV(dev, &intf->dev); +//TODO: move all of fw cmds to open()? But then we won't know our MAC addr +//until ifup (it's available via reading ACX1xx_IE_DOT11_STATION_ID)... + + /* put acx out of sleep mode and initialize it */ + acx_s_issue_cmd(priv, ACX1xx_CMD_WAKE, NULL, 0); + result = acx_s_init_mac(priv); + if (result) + goto end; + + acx_s_set_defaults(priv); + acx_s_get_firmware_version(priv); + acx_display_hardware_details(priv); + /* Register the network device */ - acxlog(L_INIT, "registering network device\n"); + log(L_INIT, "registering network device\n"); result = register_netdev(dev); - if (result != 0) { - msg = "acx: failed to register network device " - "for USB WLAN (errcode=%d)\n"; + if (result) { + msg = "acx: failed to register USB network device " + "(error %d)\n"; goto end_nomem; } - if (OK != acx_proc_register_entries(dev)) { - printk("acx: /proc registration failed\n"); - } + acx_proc_register_entries(dev); + + acx_stop_queue(dev, "on probe"); + acx_carrier_off(dev, "on probe"); - printk("acx: USB module " WLAN_RELEASE " loaded successfully\n"); + printk("acx: USB module " ACX_RELEASE " loaded successfully\n"); #if CMD_DISCOVERY great_inquisitor(priv); @@ -628,12 +779,12 @@ end_nomem: if (dev) { if (priv->usb_rx) { - for (i = 0; i < ACX100_USB_NUM_BULK_URBS; i++) + for (i = 0; i < ACX_RX_URB_CNT; i++) usb_free_urb(priv->usb_rx[i].urb); kfree(priv->usb_rx); } if (priv->usb_tx) { - for (i = 0; i < ACX100_USB_NUM_BULK_URBS; i++) + for (i = 0; i < ACX_TX_URB_CNT; i++) usb_free_urb(priv->usb_tx[i].urb); kfree(priv->usb_tx); } @@ -655,7 +806,7 @@ end: /*********************************************************************** -** acx100usb_e_disconnect() +** acxusb_e_disconnect() ** ** This function is invoked whenever the user pulls the plug from the USB ** device or the module is removed from the kernel. In these cases, the @@ -663,11 +814,11 @@ end: ** to be freed. */ static void -acx100usb_e_disconnect(struct usb_interface *intf) +acxusb_e_disconnect(struct usb_interface *intf) { wlandevice_t *priv = usb_get_intfdata(intf); - int i; unsigned long flags; + int i; FN_ENTER; @@ -694,15 +845,17 @@ acx100usb_e_disconnect(struct usb_interf acx_proc_unregister_entries(priv->netdev); /* - * Here we only free them. _close() takes care of + * Here we only free them. _close() took care of * unlinking them. */ - for (i = 0; i < ACX100_USB_NUM_BULK_URBS; ++i) { + for (i = 0; i < ACX_RX_URB_CNT; ++i) { usb_free_urb(priv->usb_rx[i].urb); + } + for (i = 0; i< ACX_TX_URB_CNT; ++i) { usb_free_urb(priv->usb_tx[i].urb); } - /* The the containers. */ + /* Freeing containers */ kfree(priv->usb_rx); kfree(priv->usb_tx); @@ -716,198 +869,66 @@ end: /*********************************************************************** -** acx100usb_boot(): -** Inputs: -** usbdev -> Pointer to kernel's usb_device structure -** endpoint -> Address of the endpoint for control transfers -************************************************************************ -** Returns: -** (int) Errorcode or 0 on success -** -** Description: -** This function triggers the loading of the firmware image from harddisk -** and then uploads the firmware to the USB device. After uploading the -** firmware and transmitting the checksum, the device resets and appears -** as a new device on the USB bus (the device we can finally deal with) +** acxusb_e_open() +** This function is called when the user sets up the network interface. +** It initializes a management timer, sets up the USB card and starts +** the network tx queue and USB receive. */ static int -acx100usb_boot(struct usb_device *usbdev) +acxusb_e_open(struct net_device *dev) { - static const char filename[] = "tiacx100usb"; - - char *firmware = NULL; - char *usbbuf; - unsigned int offset; - unsigned int len, inpipe, outpipe; - u32 checksum; - u32 size; - int result; + wlandevice_t *priv = netdev_priv(dev); + unsigned long flags; + int i; FN_ENTER; - usbbuf = kmalloc(ACX100_USB_RWMEM_MAXLEN, GFP_KERNEL); - if (!usbbuf) { - printk(KERN_ERR "acx: no memory for USB transfer buffer (" - STRING(ACX100_USB_RWMEM_MAXLEN)" bytes)\n"); - result = -ENOMEM; - goto end; - } - firmware = (char *)acx_s_read_fw(&usbdev->dev, filename, &size); - if (!firmware) { - result = -EIO; - goto end; - } - acxlog(L_INIT, "firmware size: %d bytes\n", size); - - /* Obtain the I/O pipes */ - outpipe = usb_sndctrlpipe(usbdev, 0); - inpipe = usb_rcvctrlpipe(usbdev, 0); - - /* now upload the firmware, slice the data into blocks */ - offset = 8; - while (offset < size) { - len = size - offset; - if (len >= ACX100_USB_RWMEM_MAXLEN) { - len = ACX100_USB_RWMEM_MAXLEN; - } - acxlog(L_INIT, "uploading firmware (%d bytes, offset=%d)\n", - len, offset); - result = 0; - memcpy(usbbuf, firmware + offset, len); - result = usb_control_msg(usbdev, outpipe, - ACX_USB_REQ_UPLOAD_FW, - USB_TYPE_VENDOR|USB_DIR_OUT, - size - 8, /* value */ - 0, /* index */ - usbbuf, /* dataptr */ - len, /* size */ - 3000 /* timeout in ms */ - ); - offset += len; - if (result < 0) { - printk(KERN_ERR "acx: error %d during upload " - "of firmware, aborting\n", result); - goto end; - } - } - - /* finally, send the checksum and reboot the device */ - checksum = le32_to_cpu(*(u32 *)firmware); - /* is this triggers the reboot? */ - result = usb_control_msg(usbdev, outpipe, - ACX_USB_REQ_UPLOAD_FW, - USB_TYPE_VENDOR|USB_DIR_OUT, - checksum & 0xffff, /* value */ - checksum >> 16, /* index */ - NULL, /* dataptr */ - 0, /* size */ - 3000 /* timeout in ms */ - ); - if (result < 0) { - printk(KERN_ERR "acx: error %d during tx of checksum, " - "aborting\n", result); - goto end; - } - result = usb_control_msg(usbdev, inpipe, - ACX_USB_REQ_ACK_CS, - USB_TYPE_VENDOR|USB_DIR_IN, - checksum & 0xffff, /* value */ - checksum >> 16, /* index */ - usbbuf, /* dataptr */ - 8, /* size */ - 3000 /* timeout in ms */ - ); - if (result < 0) { - printk(KERN_ERR "acx: error %d during ACK of checksum, " - "aborting\n", result); - goto end; - } - if (*usbbuf != 0x10) { - kfree(usbbuf); - printk(KERN_ERR "acx: invalid checksum?\n"); - result = -EINVAL; - goto end; - } - result = 0; -end: - vfree(firmware); - kfree(usbbuf); + acx_sem_lock(priv); - FN_EXIT1(result); - return result; -} + /* put the ACX100 out of sleep mode */ + acx_s_issue_cmd(priv, ACX1xx_CMD_WAKE, NULL, 0); + acx_init_task_scheduler(priv); -/*********************************************************************** -** acx100usb_e_init_network_device(): -** Inputs: -** dev -> Pointer to network device -************************************************************************ -** Description: -** Basic setup of a network device for use with the WLAN device. -*/ -static int -acx100usb_e_init_network_device(struct net_device *dev) -{ - wlandevice_t *priv; - int result = 0; + init_timer(&priv->mgmt_timer); + priv->mgmt_timer.function = acx_i_timer; + priv->mgmt_timer.data = (unsigned long)priv; - FN_ENTER; + /* acx_s_start needs it */ + SET_BIT(priv->dev_state_mask, ACX_STATE_IFACE_UP); + acx_s_start(priv); - /* Setup the device and stop the queue */ - ether_setup(dev); - acx_stop_queue(dev, "on init"); + /* don't acx_start_queue() here, we need to associate first */ - priv = netdev_priv(dev); + acx_lock(priv, flags); + for (i = 0; i < ACX_RX_URB_CNT; i++) { + priv->usb_rx[i].urb->status = 0; + } - acx_sem_lock(priv); + acxusb_l_poll_rx(priv, &priv->usb_rx[0]); - /* put the ACX100 out of sleep mode */ - acx_s_issue_cmd(priv, ACX1xx_CMD_WAKE, NULL, 0); + acx_unlock(priv, flags); - /* Register the callbacks for the network device functions */ - dev->open = &acx100usb_e_open; - dev->stop = &acx100usb_e_close; - dev->hard_start_xmit = (void *)&acx_i_start_xmit; - dev->get_stats = (void *)&acx_e_get_stats; - dev->get_wireless_stats = (void *)&acx_e_get_wireless_stats; -#if WIRELESS_EXT >= 13 - dev->wireless_handlers = (struct iw_handler_def *)&acx_ioctl_handler_def; -#else - dev->do_ioctl = (void *)&acx_e_ioctl_old; -#endif - dev->set_multicast_list = (void *)&acx100usb_i_set_rx_mode; -#ifdef HAVE_TX_TIMEOUT - dev->tx_timeout = &acx100usb_i_tx_timeout; - dev->watchdog_timeo = 4 * HZ; -#endif - dev->change_mtu = &acx_e_change_mtu; - result = acx_s_init_mac(dev); - if (OK != result) - goto end; - result = acx_s_set_defaults(priv); - if (OK != result) { - printk("%s: acx_set_defaults FAILED\n", dev->name); - goto end; - } + WLAN_MOD_INC_USE_COUNT; - SET_MODULE_OWNER(dev); -end: acx_sem_unlock(priv); - FN_EXIT1(result); - return result; + FN_EXIT0; + return 0; } /*********************************************************************** -** acx100usb_e_open -** This function is called when the user sets up the network interface. -** It initializes a management timer, sets up the USB card and starts -** the network tx queue and USB receive. +** acxusb_e_close() +** +** This function stops the network functionality of the interface (invoked +** when the user calls ifconfig down). The tx queue is halted and +** the device is marked as down. In case there were any pending USB bulk +** transfers, these are unlinked (asynchronously). The module in-use count +** is also decreased in this function. */ static int -acx100usb_e_open(struct net_device *dev) +acxusb_e_close(struct net_device *dev) { wlandevice_t *priv = netdev_priv(dev); unsigned long flags; @@ -915,44 +936,69 @@ acx100usb_e_open(struct net_device *dev) FN_ENTER; +#ifdef WE_STILL_DONT_CARE_ABOUT_IT + /* Transmit a disassociate frame */ + lock + acx_l_transmit_disassoc(priv, &client); + unlock +#endif + acx_sem_lock(priv); - /* put the ACX100 out of sleep mode */ - acx_s_issue_cmd(priv, ACX1xx_CMD_WAKE, NULL, 0); + CLEAR_BIT(priv->dev_state_mask, ACX_STATE_IFACE_UP); - acx_init_task_scheduler(priv); +//Code below is remarkably similar to acxpci_s_down(). Maybe we can merge them? - init_timer(&priv->mgmt_timer); - priv->mgmt_timer.function = acx_i_timer; - priv->mgmt_timer.data = (unsigned long)priv; + /* Make sure we don't get any more rx requests */ + acx_s_issue_cmd(priv, ACX1xx_CMD_DISABLE_RX, NULL, 0); + acx_s_issue_cmd(priv, ACX1xx_CMD_DISABLE_TX, NULL, 0); - /* acx_s_start needs it */ - SET_BIT(priv->dev_state_mask, ACX_STATE_IFACE_UP); - acx_s_start(priv); + /* + * We must do FLUSH *without* holding sem to avoid a deadlock. + * See pci.c:acxpci_s_down() for deails. + */ + acx_sem_unlock(priv); + FLUSH_SCHEDULED_WORK(); + acx_sem_lock(priv); - acx_start_queue(dev, "on open"); + /* Power down the device */ + acx_s_issue_cmd(priv, ACX1xx_CMD_SLEEP, NULL, 0); + /* Stop the transmit queue, mark the device as DOWN */ acx_lock(priv, flags); - for (i = 0; i < ACX100_USB_NUM_BULK_URBS; i++) { - acx100usb_l_poll_rx(priv, &priv->usb_rx[i]); + acx_stop_queue(dev, "on ifdown"); + acx_set_status(priv, ACX_STATUS_0_STOPPED); + /* stop pending rx/tx urb transfers */ + for (i = 0; i < ACX_TX_URB_CNT; i++) { + acxusb_unlink_urb(priv->usb_tx[i].urb); + priv->usb_tx[i].busy = 0; + } + for (i = 0; i < ACX_RX_URB_CNT; i++) { + acxusb_unlink_urb(priv->usb_rx[i].urb); + priv->usb_rx[i].busy = 0; } + priv->tx_free = ACX_TX_URB_CNT; acx_unlock(priv, flags); - WLAN_MOD_INC_USE_COUNT; + /* Must do this outside of lock */ + del_timer_sync(&priv->mgmt_timer); acx_sem_unlock(priv); + /* Decrease module-in-use count (if necessary) */ + WLAN_MOD_DEC_USE_COUNT; + FN_EXIT0; return 0; } /*********************************************************************** -** acx100usb_l_poll_rx -** This function (re)initiates a bulk-in USB transfer on given urb +** acxusb_l_poll_rx +** This function (re)initiates a bulk-in USB transfer on a given urb */ static void -acx100usb_l_poll_rx(wlandevice_t *priv, usb_rx_t* rx) +acxusb_l_poll_rx(wlandevice_t *priv, usb_rx_t* rx) { struct usb_device *usbdev; struct urb *rxurb; @@ -967,21 +1013,22 @@ acx100usb_l_poll_rx(wlandevice_t *priv, rxnum = rx - priv->usb_rx; inpipe = usb_rcvbulkpipe(usbdev, priv->bulkinep); - if (rxurb->status == -EINPROGRESS) { + if (unlikely(rxurb->status == -EINPROGRESS)) { printk(KERN_ERR "acx: error, rx triggered while rx urb in progress\n"); /* FIXME: this is nasty, receive is being cancelled by this code * on the other hand, this should not happen anyway... */ usb_unlink_urb(rxurb); - } else if (rxurb->status == -ECONNRESET) { - acxlog(L_USBRXTX, "acx_usb: _poll_rx: connection reset\n"); + } else + if (unlikely(rxurb->status == -ECONNRESET)) { + log(L_USBRXTX, "acx_usb: _poll_rx: connection reset\n"); goto end; } rxurb->actual_length = 0; usb_fill_bulk_urb(rxurb, usbdev, inpipe, &rx->bulkin, /* dataptr */ RXBUFSIZE, /* size */ - acx100usb_i_complete_rx, /* handler */ + acxusb_i_complete_rx, /* handler */ rx /* handler param */ ); rxurb->transfer_flags = URB_ASYNC_UNLINK; @@ -989,7 +1036,7 @@ acx100usb_l_poll_rx(wlandevice_t *priv, /* ATOMIC: we may be called from complete_rx() usb callback */ errcode = usb_submit_urb(rxurb, GFP_ATOMIC); /* FIXME: evaluate the error code! */ - acxlog(L_USBRXTX, "SUBMIT RX (%d) inpipe=0x%X size=%d errcode=%d\n", + log(L_USBRXTX, "SUBMIT RX (%d) inpipe=0x%X size=%d errcode=%d\n", rxnum, inpipe, (int) RXBUFSIZE, errcode); end: FN_EXIT0; @@ -997,19 +1044,18 @@ end: /*********************************************************************** -** acx100usb_i_complete_rx(): +** acxusb_i_complete_rx() ** Inputs: -** urb -> Pointer to USB request block -** regs -> Pointer to register-buffer for syscalls (see asm/ptrace.h) -************************************************************************ -** Description: -** This function is invoked by USB subsystem whenever a bulk receive -** request returns. -** The received data is then committed to the network stack and the next -** USB receive is triggered. +** urb -> pointer to USB request block +** regs -> pointer to register-buffer for syscalls (see asm/ptrace.h) +** +** This function is invoked by USB subsystem whenever a bulk receive +** request returns. +** The received data is then committed to the network stack and the next +** USB receive is triggered. */ static void -acx100usb_i_complete_rx(struct urb *urb, struct pt_regs *regs) +acxusb_i_complete_rx(struct urb *urb, struct pt_regs *regs) { wlandevice_t *priv; rxbuffer_t *ptr; @@ -1031,8 +1077,8 @@ acx100usb_i_complete_rx(struct urb *urb, * Happens on disconnect or close. Don't play with the urb. * Don't resubmit it. It will get unlinked by close() */ - if (!(priv->dev_state_mask & ACX_STATE_IFACE_UP)) { - acxlog(L_USBRXTX, "not doing anything.\n"); + if (unlikely(!(priv->dev_state_mask & ACX_STATE_IFACE_UP))) { + log(L_USBRXTX, "rx: device is down, not doing anything\n"); goto end_unlock; } @@ -1041,35 +1087,42 @@ acx100usb_i_complete_rx(struct urb *urb, remsize = size; rxnum = rx - priv->usb_rx; - acxlog(L_USBRXTX, "RETURN RX (%d) status=%d size=%d\n", + log(L_USBRXTX, "RETURN RX (%d) status=%d size=%d\n", rxnum, urb->status, size); - if(size > sizeof(rxbuffer_t)) - printk("acx_usb: rx too large: %d bytes, lease report\n", size); + /* Send the URB that's waiting. */ + log(L_USBRXTX, "rxnum=%d, sending=%d\n", rxnum, rxnum^1); + acxusb_l_poll_rx(priv, &priv->usb_rx[rxnum^1]); + + if (unlikely(size > sizeof(rxbuffer_t))) + printk("acx_usb: rx too large: %d, please report\n", size); /* check if the transfer was aborted */ switch (urb->status) { case 0: /* No error */ break; case -EOVERFLOW: - printk(KERN_ERR "acx: error in rx, data overrun -> emergency stop\n"); - /* LOCKING BUG! acx100usb_e_close(priv->netdev); */ + printk(KERN_ERR "acx: rx data overrun\n"); + priv->rxtruncsize = 0; /* Not valid anymore. */ goto end_unlock; case -ECONNRESET: + priv->rxtruncsize = 0; goto end_unlock; case -ESHUTDOWN: /* rmmod */ + priv->rxtruncsize = 0; goto end_unlock; default: + priv->rxtruncsize = 0; priv->stats.rx_errors++; printk("acx: rx error (urb status=%d)\n", urb->status); - goto do_poll_rx; + goto end_unlock; } - if (!size) + if (unlikely(!size)) printk("acx: warning, encountered zerolength rx packet\n"); if (urb->transfer_buffer != inbuf) - goto do_poll_rx; + goto end_unlock; /* check if previous frame was truncated ** FIXME: this code can only handle truncation @@ -1120,7 +1173,7 @@ acx100usb_i_complete_rx(struct urb *urb, ptr = (rxbuffer_t *) (((char *)inbuf) + tail_size); remsize -= tail_size; } - acxlog(L_USBRXTX, "post-merge size=%d remsize=%d\n", + log(L_USBRXTX, "post-merge size=%d remsize=%d\n", size, remsize); } @@ -1132,59 +1185,80 @@ acx100usb_i_complete_rx(struct urb *urb, if (remsize < RXBUF_HDRSIZE) { printk("acx: truncated rx header (%d bytes)!\n", remsize); + if (ACX_DEBUG) + acx_dump_bytes(ptr, remsize); break; } + packetsize = RXBUF_BYTES_USED(ptr); - acxlog(L_USBRXTX, "packet with packetsize=%d\n", packetsize); + log(L_USBRXTX, "packet with packetsize=%d\n", packetsize); + + if (RXBUF_IS_TXSTAT(ptr)) { + /* do rate handling */ + usb_txstatus_t *stat = (void*)ptr; + u16 client_no = (u16)stat->hostdata; + + log(L_USBRXTX, "tx: stat: mac_cnt_rcvd:%04X " + "queue_index:%02X mac_status:%02X hostdata:%08X " + "rate:%u ack_failures:%02X rts_failures:%02X " + "rts_ok:%02X\n", + stat->mac_cnt_rcvd, + stat->queue_index, stat->mac_status, stat->hostdata, + stat->rate, stat->ack_failures, stat->rts_failures, + stat->rts_ok); + + if (priv->rate_auto && client_no < VEC_SIZE(priv->sta_list)) { + client_t *clt = &priv->sta_list[client_no]; + u16 cur = stat->hostdata >> 16; + + if (clt && clt->rate_cur == cur) { + acx_l_handle_txrate_auto(priv, clt, + cur, /* intended rate */ + stat->rate, 0, /* actually used rate */ + stat->mac_status, /* error? */ + ACX_TX_URB_CNT - priv->tx_free); + } + } + goto next; + } + if (packetsize > sizeof(rxbuffer_t)) { printk("acx: packet exceeds max wlan " "frame size (%d > %d). size=%d\n", packetsize, (int) sizeof(rxbuffer_t), size); + if (ACX_DEBUG) + acx_dump_bytes(ptr, 16); /* FIXME: put some real error-handling in here! */ break; } - /* skip null packets (does this really happen?!) */ - if (packetsize == RXBUF_HDRSIZE) { - remsize -= RXBUF_HDRSIZE; - if (acx_debug & L_USBRXTX) { - printk("acx: null packet, new remsize=%d. " - "header follows:\n", remsize); - acx_dump_bytes(ptr, RXBUF_HDRSIZE); - } - ptr = (rxbuffer_t *)(((char *)ptr) + RXBUF_HDRSIZE); - continue; - } - if (packetsize > remsize) { /* frame truncation handling */ if (acx_debug & L_USBRXTX) { printk("need to truncate packet, " "packetsize=%d remsize=%d " - "size=%d\n", + "size=%d bytes:", packetsize, remsize, size); acx_dump_bytes(ptr, RXBUF_HDRSIZE); } memcpy(&priv->rxtruncbuf, ptr, remsize); priv->rxtruncsize = remsize; break; - } else { /* packetsize <= remsize */ - /* now handle the received data */ - acx_l_process_rxbuf(priv, ptr); + } - ptr = (rxbuffer_t *)(((char *)ptr) + packetsize); - remsize -= packetsize; - if ((acx_debug & L_USBRXTX) && remsize) { - printk("more than one packet in buffer, " - "second packet hdr follows\n"); - acx_dump_bytes(ptr, RXBUF_HDRSIZE); - } + /* packetsize <= remsize */ + /* now handle the received data */ + acx_l_process_rxbuf(priv, ptr); +next: + ptr = (rxbuffer_t *)(((char *)ptr) + packetsize); + remsize -= packetsize; + if ((acx_debug & L_USBRXTX) && remsize) { + printk("more than one packet in buffer, " + "second packet hdr:"); + acx_dump_bytes(ptr, RXBUF_HDRSIZE); } } -do_poll_rx: - /* receive of frame completed, now look for the next one */ - acx100usb_l_poll_rx(priv, rx); end_unlock: acx_unlock(priv, flags); /* end: */ @@ -1193,28 +1267,15 @@ end_unlock: /*********************************************************************** -** acx100usb_i_complete_tx(): +** acxusb_i_complete_tx() ** Inputs: -** urb -> Pointer to USB request block -** regs -> Pointer to register-buffer for syscalls (see asm/ptrace.h) -************************************************************************ -** Description: -** This function is invoked upon termination of a USB transfer. As the -** USB device is only capable of sending a limited amount of bytes per -** transfer to the bulk-out endpoint, this routine checks if there are -** more bytes to send and triggers subsequent transfers. In case the -** transfer size exactly matches the maximum bulk-out size, it triggers -** a transfer of a null-frame, telling the card that this is it. Upon -** completion of a frame, it checks whether the Tx ringbuffer contains -** more data to send and invokes the Tx routines if this is the case. -** If there are no more occupied Tx descriptors, the Tx Mutex is unlocked -** and the network queue is switched back to life again. +** urb -> pointer to USB request block +** regs -> pointer to register-buffer for syscalls (see asm/ptrace.h) ** -** FIXME: unlike PCI code, we do not analyze tx rate used, retries, etc... -** Thus we have no automatic rate control in USB! +** This function is invoked upon termination of a USB transfer. */ static void -acx100usb_i_complete_tx(struct urb *urb, struct pt_regs *regs) +acxusb_i_complete_tx(struct urb *urb, struct pt_regs *regs) { wlandevice_t *priv; usb_tx_t *tx; @@ -1236,13 +1297,12 @@ acx100usb_i_complete_tx(struct urb *urb, * If the iface isn't up, we don't have any right * to play with them. The urb may get unlinked. */ - if (!(priv->dev_state_mask & ACX_STATE_IFACE_UP)) { - acxlog(L_USBRXTX, "not doing anything\n"); + if (unlikely(!(priv->dev_state_mask & ACX_STATE_IFACE_UP))) { + log(L_USBRXTX, "tx: device is down, not doing anything\n"); goto end_unlock; - /*FIXME: Do the priv->tx_free++? */ } - acxlog(L_USBRXTX, "RETURN TX (%d): status=%d size=%d\n", + log(L_USBRXTX, "RETURN TX (%d): status=%d size=%d\n", txnum, urb->status, urb->actual_length); /* handle USB transfer errors */ @@ -1262,8 +1322,16 @@ acx100usb_i_complete_tx(struct urb *urb, } /* free the URB and check for more data */ - priv->tx_free++; tx->busy = 0; + priv->tx_free++; + if ((priv->tx_free >= TX_START_QUEUE) + && (priv->status == ACX_STATUS_4_ASSOCIATED) + && (acx_queue_stopped(priv->netdev)) + ) { + log(L_BUF, "tx: wake queue (%u free txbufs)\n", + priv->tx_free); + acx_wake_queue(priv->netdev, NULL); + } end_unlock: acx_unlock(priv, flags); @@ -1272,81 +1340,6 @@ end_unlock: } -/*********************************************************************** -** acx100usb_e_close() -** -** This function stops the network functionality of the interface (invoked -** when the user calls ifconfig down). The tx queue is halted and -** the device is marked as down. In case there were any pending USB bulk -** transfers, these are unlinked (asynchronously). The module in-use count -** is also decreased in this function. -*/ -static int -acx100usb_e_close(struct net_device *dev) -{ - wlandevice_t *priv = netdev_priv(dev); - unsigned long flags; - int i; - - FN_ENTER; - -#ifdef WE_STILL_DONT_CARE_ABOUT_IT - /* Transmit a disassociate frame */ - lock - acx_l_transmit_disassoc(priv, &client); - unlock -#endif - - acx_sem_lock(priv); - - /* Make sure we don't get any more rx requests */ - acx_s_issue_cmd(priv, ACX1xx_CMD_DISABLE_RX, NULL, 0); - acx_s_issue_cmd(priv, ACX1xx_CMD_DISABLE_TX, NULL, 0); - - /* - * We must do FLUSH *without* holding sem to avoid a deadlock. - * See pci.c:acxpci_s_down() for deails. - */ - acx_sem_unlock(priv); - FLUSH_SCHEDULED_WORK(); - acx_sem_lock(priv); - - /* Power down the device */ - acx_s_issue_cmd(priv, ACX1xx_CMD_SLEEP, NULL, 0); - - /* Stop the transmit queue, mark the device as DOWN */ - acx_lock(priv, flags); - acx_stop_queue(dev, "on iface stop"); - CLEAR_BIT(priv->dev_state_mask, ACX_STATE_IFACE_UP); - /* stop pending rx/tx urb transfers */ - /* Make sure you don't free them! */ - for (i = 0; i < ACX100_USB_NUM_BULK_URBS; i++) { - acxusb_unlink_urb(priv->usb_rx[i].urb); - acxusb_unlink_urb(priv->usb_tx[i].urb); - } - - del_timer_sync(&priv->mgmt_timer); - - priv->tx_free = ACX100_USB_NUM_BULK_URBS; - - for (i = 0; i< ACX100_USB_NUM_BULK_URBS; ++i) { - priv->usb_tx[i].busy = 0; - priv->usb_rx[i].busy = 0; - } - - acx_unlock(priv, flags); - - acx_sem_unlock(priv); - - /* Decrease module-in-use count (if necessary) */ - - WLAN_MOD_DEC_USE_COUNT; - - FN_EXIT0; - return 0; -} - - /*************************************************************** ** acxusb_l_alloc_tx ** Actually returns a usb_tx_t* ptr @@ -1354,30 +1347,50 @@ acx100usb_e_close(struct net_device *dev tx_t* acxusb_l_alloc_tx(wlandevice_t* priv) { - int i; - usb_tx_t *tx = NULL; + usb_tx_t *tx; + int head; FN_ENTER; - for (i = 0; i < ACX100_USB_NUM_BULK_URBS; i++) { - if (!priv->usb_tx[i].busy) { - acxlog(L_USBRXTX, "allocated tx %d\n", i); - tx = &priv->usb_tx[i]; + head = priv->tx_head; + do { + head = (head + 1) % ACX_TX_URB_CNT; + if (!priv->usb_tx[head].busy) { + log(L_USBRXTX, "allocated tx %d\n", head); + tx = &priv->usb_tx[head]; tx->busy = 1; - break; + priv->tx_free--; + /* Keep a few free descs between head and tail of tx ring. + ** It is not absolutely needed, just feels safer */ + if (priv->tx_free < TX_STOP_QUEUE) { + log(L_BUF, "tx: stop queue " + "(%u free txbufs)\n", priv->tx_free); + acx_stop_queue(priv->netdev, NULL); + } + goto end; } - } - if (i >= ACX100_USB_NUM_BULK_URBS) { - printk_ratelimited("acx: tx buffers full\n"); - } - + } while (likely(head!=priv->tx_head)); + tx = NULL; + printk_ratelimited("acx: tx buffers full\n"); +end: + priv->tx_head = head; FN_EXIT0; - return (tx_t*)tx; } /*************************************************************** +** Used if alloc_tx()'ed buffer needs to be cancelled without doing tx +*/ +void +acxusb_l_dealloc_tx(tx_t *tx_opaque) +{ + usb_tx_t* tx = (usb_tx_t*)tx_opaque; + tx->busy = 0; +} + + +/*************************************************************** */ void* acxusb_l_get_txbuf(wlandevice_t *priv, tx_t* tx_opaque) @@ -1403,8 +1416,7 @@ acxusb_l_tx_data(wlandevice_t *priv, tx_ client_t *clt; wlan_hdr_t* whdr; unsigned int outpipe; - int ucode; - u8 rate100; + int ucode, txnum; FN_ENTER; @@ -1412,11 +1424,10 @@ acxusb_l_tx_data(wlandevice_t *priv, tx_ txurb = tx->urb; txbuf = &tx->bulkout; whdr = (wlan_hdr_t *)txbuf->data; + txnum = tx - priv->usb_tx; - priv->tx_free--; - acxlog(L_DEBUG, "using buf#%d free=%d len=%d\n", - (int)(tx - priv->usb_tx), - priv->tx_free, wlanpkt_len); + log(L_DEBUG, "using buf#%d free=%d len=%d\n", + txnum, priv->tx_free, wlanpkt_len); switch (priv->mode) { case ACX_MODE_0_ADHOC: @@ -1436,38 +1447,29 @@ acxusb_l_tx_data(wlandevice_t *priv, tx_ goto end; } - /* used in tx cleanup routine for auto rate and accounting: */ -//TODO: currently unused - fix that - tx->txc = clt; - - rate100 = clt ? clt->rate_100 : priv->rate_bcast100; - /* fill the USB transfer header */ txbuf->desc = cpu_to_le16(USB_TXBUF_TXDESC); - txbuf->MPDUlen = cpu_to_le16(wlanpkt_len); - txbuf->ctrl1 = 0; - txbuf->ctrl2 = 0; - txbuf->hostData = cpu_to_le32(wlanpkt_len | (rate100 << 24)); + txbuf->mpdu_len = cpu_to_le16(wlanpkt_len); + txbuf->queue_index = 1; + if (clt) { + txbuf->rate = clt->rate_100; + txbuf->hostdata = (clt - priv->sta_list) | (clt->rate_cur << 16); + } else { + txbuf->rate = priv->rate_bcast100; + txbuf->hostdata = ((u16)-1) | (priv->rate_bcast << 16); + } + txbuf->ctrl1 = DESC_CTL_FIRSTFRAG; if (1 == priv->preamble_cur) SET_BIT(txbuf->ctrl1, DESC_CTL_SHORT_PREAMBLE); - SET_BIT(txbuf->ctrl1, DESC_CTL_FIRSTFRAG); - txbuf->txRate = rate100; - txbuf->index = 1; - txbuf->dataLength = cpu_to_le16(wlanpkt_len); - - if ( (WF_FC_FTYPEi & whdr->fc) == WF_FTYPE_DATAi ) - SET_BIT(txbuf->hostData, cpu_to_le32(USB_TXBUF_HD_ISDATA)); - if (mac_is_directed(whdr->a1)) - SET_BIT(txbuf->hostData, cpu_to_le32(USB_TXBUF_HD_DIRECTED)); - else if (mac_is_bcast(whdr->a1)) - SET_BIT(txbuf->hostData, cpu_to_le32(USB_TXBUF_HD_BROADCAST)); + txbuf->ctrl2 = 0; + txbuf->data_len = cpu_to_le16(wlanpkt_len); if (acx_debug & L_DATA) { printk("dump of bulk out urb:\n"); acx_dump_bytes(txbuf, wlanpkt_len + USB_TXBUF_HDRSIZE); } - if (txurb->status == -EINPROGRESS) { + if (unlikely(txurb->status == -EINPROGRESS)) { printk("acx: trying to submit tx urb while already in progress\n"); } @@ -1478,17 +1480,17 @@ acxusb_l_tx_data(wlandevice_t *priv, tx_ usb_fill_bulk_urb(txurb, usbdev, outpipe, txbuf, /* dataptr */ wlanpkt_len + USB_TXBUF_HDRSIZE, /* size */ - acx100usb_i_complete_tx, /* handler */ + acxusb_i_complete_tx, /* handler */ tx /* handler param */ ); txurb->transfer_flags = URB_ASYNC_UNLINK|URB_ZERO_PACKET; ucode = usb_submit_urb(txurb, GFP_ATOMIC); - acxlog(L_USBRXTX, "SUBMIT TX (%p): outpipe=0x%X buf=%p txsize=%d " - "errcode=%d\n", tx, outpipe, txbuf, - wlanpkt_len + USB_TXBUF_HDRSIZE, ucode); + log(L_USBRXTX, "SUBMIT TX (%d): outpipe=0x%X buf=%p txsize=%d " + "rate=%u errcode=%d\n", txnum, outpipe, txbuf, + wlanpkt_len + USB_TXBUF_HDRSIZE, txbuf->rate, ucode); - if (ucode) { + if (unlikely(ucode)) { printk(KERN_ERR "acx: submit_urb() error=%d txsize=%d\n", ucode, wlanpkt_len + USB_TXBUF_HDRSIZE); @@ -1498,6 +1500,7 @@ acxusb_l_tx_data(wlandevice_t *priv, tx_ priv->stats.tx_errors++; tx->busy = 0; priv->tx_free++; + /* needed? if (priv->tx_free > TX_START_QUEUE) acx_wake_queue(...) */ } end: FN_EXIT0; @@ -1507,7 +1510,7 @@ end: /*********************************************************************** */ static void -acx100usb_i_set_rx_mode(struct net_device *dev) +acxusb_i_set_rx_mode(struct net_device *dev) { } @@ -1516,7 +1519,7 @@ acx100usb_i_set_rx_mode(struct net_devic */ #ifdef HAVE_TX_TIMEOUT static void -acx100usb_i_tx_timeout(struct net_device *dev) +acxusb_i_tx_timeout(struct net_device *dev) { wlandevice_t *priv = netdev_priv(dev); unsigned long flags; @@ -1526,9 +1529,11 @@ acx100usb_i_tx_timeout(struct net_device acx_lock(priv, flags); /* unlink the URBs */ - for (i = 0; i < ACX100_USB_NUM_BULK_URBS; i++) { + for (i = 0; i < ACX_TX_URB_CNT; i++) { acxusb_unlink_urb(priv->usb_tx[i].urb); + priv->usb_tx[i].busy = 0; } + priv->tx_free = ACX_TX_URB_CNT; /* TODO: stats update */ acx_unlock(priv, flags); @@ -1538,7 +1543,7 @@ acx100usb_i_tx_timeout(struct net_device /*********************************************************************** -** init_module(): +** init_module() ** ** This function is invoked upon loading of the kernel module. ** It registers itself at the kernel's USB subsystem. @@ -1548,15 +1553,15 @@ acx100usb_i_tx_timeout(struct net_device int __init acxusb_e_init_module(void) { - acxlog(L_INIT, "USB module " WLAN_RELEASE " initialized, " + log(L_INIT, "USB module " ACX_RELEASE " initialized, " "probing for devices...\n"); - return usb_register(&acx100usb_driver); + return usb_register(&acxusb_driver); } /*********************************************************************** -** cleanup_module(): +** cleanup_module() ** ** This function is invoked as last step of the module unloading. It simply ** deregisters this module at the kernel's USB subsystem. @@ -1564,7 +1569,7 @@ acxusb_e_init_module(void) void __exit acxusb_e_cleanup_module() { - usb_deregister(&acx100usb_driver); + usb_deregister(&acxusb_driver); } diff -puN drivers/net/wireless/tiacx/wlan.c~acx-driver-update drivers/net/wireless/tiacx/wlan.c --- devel/drivers/net/wireless/tiacx/wlan.c~acx-driver-update 2006-01-06 22:44:21.000000000 -0800 +++ devel-akpm/drivers/net/wireless/tiacx/wlan.c 2006-01-06 22:44:21.000000000 -0800 @@ -135,6 +135,11 @@ wlan_mgmt_decode_beacon(wlan_fr_beacon_t /* was seen by David Bronaugh from ???? */ /* 85 1E 00 00 84 12 07 00 FF 00 11 00 61 70 63 31 */ /* 63 73 72 30 34 32 00 00 00 00 00 00 00 00 00 25 */ + + case WLAN_EID_UNKNOWN223: + /* was seen by Carlos Martin from ???? */ + /* DF 20 01 1E 04 00 00 00 06 63 09 02 FF 0F 30 30 */ + /* 30 42 36 42 33 34 30 39 46 31 00 00 00 00 00 00 00 00 */ case WLAN_EID_GENERIC: /* WPA: hostap code: if (pos[1] >= 4 && diff -puN drivers/net/wireless/tiacx/wlan_mgmt.h~acx-driver-update drivers/net/wireless/tiacx/wlan_mgmt.h --- devel/drivers/net/wireless/tiacx/wlan_mgmt.h~acx-driver-update 2006-01-06 22:44:21.000000000 -0800 +++ devel-akpm/drivers/net/wireless/tiacx/wlan_mgmt.h 2006-01-06 22:44:21.000000000 -0800 @@ -63,6 +63,7 @@ #define WLAN_EID_UNKNOWN128 128 #define WLAN_EID_UNKNOWN133 133 #define WLAN_EID_GENERIC 221 +#define WLAN_EID_UNKNOWN223 223 #if 0 #define WLAN_EID_PWR_CONSTRAINT 32 /* 11H PowerConstraint */ _