Skip to content

Commit

Permalink
[PATCH] hostap: Remove experimental PCI bus master/DMA code
Browse files Browse the repository at this point in the history
PCI version of Prism2.5/3 has undocumented DMA support for TX/RX data,
but this seems to have some hardware bugs that prevent it from being
used properly for TX. RX side could possibly be made to work reliably.

Even though DMA support would be very useful for saving host CPU (from
about 40% to 5-10% when operating at maximum throughput), it seems to
be best to just remove this code finally. The implementation has
always been commented out by default and has received very limited
testing. The code may have already been broken number of times and I
don't have much interested in trying to verify whether it works or
not. Getting this out makes it easier to maintain the driver and
allows some cleanups that have been partly postponed because of this
experimental bus master/DMA code.

Signed-off-by: Jouni Malinen <jkmaline@cc.hut.fi>
Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
  • Loading branch information
Jouni Malinen authored and Jeff Garzik committed Aug 15, 2005
1 parent 5bee720 commit ea3f186
Show file tree
Hide file tree
Showing 6 changed files with 13 additions and 273 deletions.
4 changes: 2 additions & 2 deletions drivers/net/wireless/hostap/hostap_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -343,8 +343,8 @@ enum {
PRISM2_PARAM_MONITOR_ALLOW_FCSERR = 16,
PRISM2_PARAM_HOST_ENCRYPT = 17,
PRISM2_PARAM_HOST_DECRYPT = 18,
PRISM2_PARAM_BUS_MASTER_THRESHOLD_RX = 19,
PRISM2_PARAM_BUS_MASTER_THRESHOLD_TX = 20,
/* PRISM2_PARAM_BUS_MASTER_THRESHOLD_RX = 19, REMOVED 2005-08-14 */
/* PRISM2_PARAM_BUS_MASTER_THRESHOLD_TX = 20, REMOVED 2005-08-14 */
PRISM2_PARAM_HOST_ROAMING = 21,
PRISM2_PARAM_BCRX_STA_KEY = 22,
PRISM2_PARAM_IEEE_802_1X = 23,
Expand Down
31 changes: 0 additions & 31 deletions drivers/net/wireless/hostap/hostap_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,37 +13,6 @@
/* Maximum number of events handler per one interrupt */
#define PRISM2_MAX_INTERRUPT_EVENTS 20

/* Use PCI bus master to copy data to/from BAP (only available for
* hostap_pci.o).
*
* Note! This is extremely experimental. PCI bus master is not supported by
* Intersil and it seems to have some problems at least on TX path (see below).
* The driver code for implementing bus master support is based on guessing
* and experimenting suitable control bits and these might not be correct.
* This code is included because using bus master makes a huge difference in
* host CPU load (something like 40% host CPU usage to 5-10% when sending or
* receiving at maximum throughput).
*
* Note2! Station firmware version 1.3.5 and primary firmware version 1.0.7
* have some fixes for PCI corruption and these (or newer) versions are
* recommended especially when using bus mastering.
*
* NOTE: PCI bus mastering code has not been updated for long time and it is
* not likely to compile and it will _not_ work as is. Only enable this if you
* are prepared to first fix the implementation..
*/
/* #define PRISM2_BUS_MASTER */

#ifdef PRISM2_BUS_MASTER

/* PCI bus master implementation seems to be broken in current
* hardware/firmware versions. Enable this to use enable command to fix
* something before starting bus master operation on TX path. This will add
* some latency and an extra interrupt to each TX packet. */
#define PRISM2_ENABLE_BEFORE_TX_BUS_MASTER

#endif /* PRISM2_BUS_MASTER */

/* Include code for downloading firmware images into volatile RAM. */
#define PRISM2_DOWNLOAD_SUPPORT

Expand Down
211 changes: 11 additions & 200 deletions drivers/net/wireless/hostap/hostap_hw.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,18 +83,6 @@ static int dtim_period[MAX_PARM_DEVICES] = { 1, DEF_INTS };
module_param_array(dtim_period, int, NULL, 0444);
MODULE_PARM_DESC(dtim_period, "DTIM period");

#if defined(PRISM2_PCI) && defined(PRISM2_BUS_MASTER)
static int bus_master_threshold_rx[MAX_PARM_DEVICES] = { 100, DEF_INTS };
module_param_array(bus_master_threshold_rx, int, NULL, 0444);
MODULE_PARM_DESC(bus_master_threshold_rx, "Packet length threshold for using "
"PCI bus master on RX");

static int bus_master_threshold_tx[MAX_PARM_DEVICES] = { 100, DEF_INTS };
module_param_array(bus_master_threshold_tx, int, NULL, 0444);
MODULE_PARM_DESC(bus_master_threshold_tx, "Packet length threshold for using "
"PCI bus master on TX");
#endif /* PRISM2_PCI and PRISM2_BUS_MASTER */

static char dev_template[16] = "wlan%d";
module_param_string(dev_template, dev_template, sizeof(dev_template), 0444);
MODULE_PARM_DESC(dev_template, "Prefix for network device name (default: "
Expand All @@ -107,12 +95,6 @@ MODULE_PARM_DESC(dev_template, "Prefix for network device name (default: "
#define EXTRA_EVENTS_WTERR HFA384X_EV_WTERR
#endif

#if defined(PRISM2_PCI) && defined(PRISM2_BUS_MASTER)
#define EXTRA_EVENTS_BUS_MASTER (HFA384X_EV_PCI_M0 | HFA384X_EV_PCI_M1)
#else
#define EXTRA_EVENTS_BUS_MASTER 0
#endif

/* Events that will be using BAP0 */
#define HFA384X_BAP0_EVENTS \
(HFA384X_EV_TXEXC | HFA384X_EV_RX | HFA384X_EV_INFO | HFA384X_EV_TX)
Expand All @@ -121,7 +103,7 @@ MODULE_PARM_DESC(dev_template, "Prefix for network device name (default: "
#define HFA384X_EVENT_MASK \
(HFA384X_BAP0_EVENTS | HFA384X_EV_ALLOC | HFA384X_EV_INFDROP | \
HFA384X_EV_CMD | HFA384X_EV_TICK | \
EXTRA_EVENTS_WTERR | EXTRA_EVENTS_BUS_MASTER)
EXTRA_EVENTS_WTERR)

/* Default TX control flags: use 802.11 headers and request interrupt for
* failed transmits. Frames that request ACK callback, will add
Expand Down Expand Up @@ -1827,34 +1809,6 @@ static int prism2_transmit(struct net_device *dev, int idx)
}


#if defined(PRISM2_PCI) && defined(PRISM2_BUS_MASTER)
/* Called only from hardware IRQ */
static void prism2_tx_cb(struct net_device *dev, void *context,
u16 resp0, u16 res)
{
struct hostap_interface *iface;
local_info_t *local;
unsigned long addr;
int buf_len = (int) context;

iface = netdev_priv(dev);
local = iface->local;

if (res) {
printk(KERN_DEBUG "%s: prism2_tx_cb - res=0x%02x\n",
dev->name, res);
return;
}

addr = virt_to_phys(local->bus_m0_buf);
HFA384X_OUTW((addr & 0xffff0000) >> 16, HFA384X_PCI_M0_ADDRH_OFF);
HFA384X_OUTW(addr & 0x0000ffff, HFA384X_PCI_M0_ADDRL_OFF);
HFA384X_OUTW(buf_len / 2, HFA384X_PCI_M0_LEN_OFF);
HFA384X_OUTW(HFA384X_PCI_CTL_TO_BAP, HFA384X_PCI_M0_CTL_OFF);
}
#endif /* PRISM2_PCI and PRISM2_BUS_MASTER */


/* Send IEEE 802.11 frame (convert the header into Prism2 TX descriptor and
* send the payload with this descriptor) */
/* Called only from software IRQ */
Expand Down Expand Up @@ -1920,53 +1874,6 @@ static int prism2_tx_80211(struct sk_buff *skb, struct net_device *dev)
spin_lock(&local->baplock);
res = hfa384x_setup_bap(dev, BAP0, local->txfid[idx], 0);

#if defined(PRISM2_PCI) && defined(PRISM2_BUS_MASTER)
if (!res && skb->len >= local->bus_master_threshold_tx) {
u8 *pos;
int buf_len;

local->bus_m0_tx_idx = idx;

/* FIX: BAP0 should be locked during bus master transfer, but
* baplock with BH's disabled is not OK for this; netif queue
* stopping is not enough since BAP0 is used also for RID
* read/write */

/* stop the queue for the time that bus mastering on BAP0 is
* in use */
netif_stop_queue(dev);

spin_unlock(&local->baplock);

/* Copy frame data to bus_m0_buf */
pos = local->bus_m0_buf;
memcpy(pos, &txdesc, sizeof(txdesc));
pos += sizeof(txdesc);
memcpy(pos, skb->data + hdr_len, skb->len - hdr_len);
pos += skb->len - hdr_len;
buf_len = pos - local->bus_m0_buf;
if (buf_len & 1)
buf_len++;

#ifdef PRISM2_ENABLE_BEFORE_TX_BUS_MASTER
/* Any RX packet seems to break something with TX bus
* mastering; enable command is enough to fix this.. */
if (hfa384x_cmd_callback(dev, HFA384X_CMDCODE_ENABLE, 0,
prism2_tx_cb, (long) buf_len)) {
printk(KERN_DEBUG "%s: TX: enable port0 failed\n",
dev->name);
}
#else /* PRISM2_ENABLE_BEFORE_TX_BUS_MASTER */
prism2_tx_cb(dev, (void *) buf_len, 0, 0);
#endif /* PRISM2_ENABLE_BEFORE_TX_BUS_MASTER */

/* Bus master transfer will be started from command completion
* event handler and TX handling will be finished by calling
* prism2_transmit() from bus master event handler */
goto tx_stats;
}
#endif /* PRISM2_PCI and PRISM2_BUS_MASTER */

if (!res)
res = hfa384x_to_bap(dev, BAP0, &txdesc, sizeof(txdesc));
if (!res)
Expand Down Expand Up @@ -2107,50 +2014,18 @@ static void prism2_rx(local_info_t *local)
skb->dev = dev;
memcpy(skb_put(skb, hdr_len), &rxdesc, hdr_len);

#if defined(PRISM2_PCI) && defined(PRISM2_BUS_MASTER)
if (len >= local->bus_master_threshold_rx) {
unsigned long addr;

hfa384x_events_no_bap1(dev);

local->rx_skb = skb;
/* Internal BAP0 offset points to the byte following rxdesc;
* copy rest of the data using bus master */
addr = virt_to_phys(skb_put(skb, len));
HFA384X_OUTW((addr & 0xffff0000) >> 16,
HFA384X_PCI_M0_ADDRH_OFF);
HFA384X_OUTW(addr & 0x0000ffff, HFA384X_PCI_M0_ADDRL_OFF);
if (len & 1)
len++;
HFA384X_OUTW(len / 2, HFA384X_PCI_M0_LEN_OFF);
HFA384X_OUTW(HFA384X_PCI_CTL_FROM_BAP, HFA384X_PCI_M0_CTL_OFF);

/* pci_bus_m1 event will be generated when data transfer is
* complete and the frame will then be added to rx_list and
* rx_tasklet is scheduled */
rx_pending = 1;

/* Have to release baplock before returning, although BAP0
* should really not be used before DMA transfer has been
* completed. */
spin_unlock(&local->baplock);
} else
#endif /* PRISM2_PCI and PRISM2_BUS_MASTER */
{
if (len > 0)
res = hfa384x_from_bap(dev, BAP0, skb_put(skb, len),
len);
spin_unlock(&local->baplock);
if (res) {
printk(KERN_DEBUG "%s: RX failed to read "
"frame data\n", dev->name);
goto rx_dropped;
}

skb_queue_tail(&local->rx_list, skb);
tasklet_schedule(&local->rx_tasklet);
if (len > 0)
res = hfa384x_from_bap(dev, BAP0, skb_put(skb, len), len);
spin_unlock(&local->baplock);
if (res) {
printk(KERN_DEBUG "%s: RX failed to read "
"frame data\n", dev->name);
goto rx_dropped;
}

skb_queue_tail(&local->rx_list, skb);
tasklet_schedule(&local->rx_tasklet);

rx_exit:
prism2_callback(local, PRISM2_CALLBACK_RX_END);
if (!rx_pending) {
Expand Down Expand Up @@ -2654,36 +2529,6 @@ static void hostap_bap_tasklet(unsigned long data)
}


#if defined(PRISM2_PCI) && defined(PRISM2_BUS_MASTER)
/* Called only from hardware IRQ */
static void prism2_bus_master_ev(struct net_device *dev, int bap)
{
struct hostap_interface *iface;
local_info_t *local;

iface = netdev_priv(dev);
local = iface->local;

if (bap == BAP1) {
/* FIX: frame payload was DMA'd to skb->data; might need to
* invalidate data cache for that memory area */
skb_queue_tail(&local->rx_list, local->rx_skb);
tasklet_schedule(&local->rx_tasklet);
HFA384X_OUTW(HFA384X_EV_RX, HFA384X_EVACK_OFF);
} else {
if (prism2_transmit(dev, local->bus_m0_tx_idx)) {
printk(KERN_DEBUG "%s: prism2_transmit() failed "
"when called from bus master event\n",
dev->name);
local->intransmitfid[local->bus_m0_tx_idx] =
PRISM2_TXFID_EMPTY;
schedule_work(&local->reset_queue);
}
}
}
#endif /* PRISM2_PCI and PRISM2_BUS_MASTER */


/* Called only from hardware IRQ */
static void prism2_infdrop(struct net_device *dev)
{
Expand Down Expand Up @@ -2852,21 +2697,6 @@ static irqreturn_t prism2_interrupt(int irq, void *dev_id, struct pt_regs *regs)
HFA384X_OUTW(HFA384X_EV_TICK, HFA384X_EVACK_OFF);
}

#if defined(PRISM2_PCI) && defined(PRISM2_BUS_MASTER)
if (ev & HFA384X_EV_PCI_M0) {
prism2_bus_master_ev(dev, BAP0);
HFA384X_OUTW(HFA384X_EV_PCI_M0, HFA384X_EVACK_OFF);
}

if (ev & HFA384X_EV_PCI_M1) {
/* previous RX has been copied can be ACKed now */
HFA384X_OUTW(HFA384X_EV_RX, HFA384X_EVACK_OFF);

prism2_bus_master_ev(dev, BAP1);
HFA384X_OUTW(HFA384X_EV_PCI_M1, HFA384X_EVACK_OFF);
}
#endif /* PRISM2_PCI and PRISM2_BUS_MASTER */

if (ev & HFA384X_EV_ALLOC) {
prism2_alloc_ev(dev);
HFA384X_OUTW(HFA384X_EV_ALLOC, HFA384X_EVACK_OFF);
Expand Down Expand Up @@ -3309,13 +3139,6 @@ prism2_init_local_data(struct prism2_helper_functions *funcs, int card_idx,
local->io_debug_enabled = 1;
#endif /* PRISM2_IO_DEBUG */

#if defined(PRISM2_PCI) && defined(PRISM2_BUS_MASTER)
local->bus_m0_buf = (u8 *) kmalloc(sizeof(struct hfa384x_tx_frame) +
PRISM2_DATA_MAXLEN, GFP_DMA);
if (local->bus_m0_buf == NULL)
goto fail;
#endif /* PRISM2_PCI and PRISM2_BUS_MASTER */

local->func = funcs;
local->func->cmd = hfa384x_cmd;
local->func->read_regs = hfa384x_read_regs;
Expand Down Expand Up @@ -3376,12 +3199,6 @@ prism2_init_local_data(struct prism2_helper_functions *funcs, int card_idx,
local->auth_algs = PRISM2_AUTH_OPEN | PRISM2_AUTH_SHARED_KEY;
local->sram_type = -1;
local->scan_channel_mask = 0xffff;
#if defined(PRISM2_PCI) && defined(PRISM2_BUS_MASTER)
local->bus_master_threshold_rx = GET_INT_PARM(bus_master_threshold_rx,
card_idx);
local->bus_master_threshold_tx = GET_INT_PARM(bus_master_threshold_tx,
card_idx);
#endif /* PRISM2_PCI and PRISM2_BUS_MASTER */

/* Initialize task queue structures */
INIT_WORK(&local->reset_queue, handle_reset_queue, local);
Expand Down Expand Up @@ -3462,9 +3279,6 @@ while (0)
return dev;

fail:
#if defined(PRISM2_PCI) && defined(PRISM2_BUS_MASTER)
kfree(local->bus_m0_buf);
#endif /* PRISM2_PCI and PRISM2_BUS_MASTER */
free_netdev(dev);
return NULL;
}
Expand Down Expand Up @@ -3586,9 +3400,6 @@ static void prism2_free_local_data(struct net_device *dev)
kfree(bss);
}

#if defined(PRISM2_PCI) && defined(PRISM2_BUS_MASTER)
kfree(local->bus_m0_buf);
#endif /* PRISM2_PCI and PRISM2_BUS_MASTER */
kfree(local->pda);
kfree(local->last_scan_results);
kfree(local->generic_elem);
Expand Down
24 changes: 0 additions & 24 deletions drivers/net/wireless/hostap/hostap_ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -2239,14 +2239,6 @@ static const struct iw_priv_args prism2_priv[] = {
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "host_decrypt" },
{ PRISM2_PARAM_HOST_DECRYPT,
0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethost_decrypt" },
{ PRISM2_PARAM_BUS_MASTER_THRESHOLD_RX,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "busmaster_rx" },
{ PRISM2_PARAM_BUS_MASTER_THRESHOLD_RX,
0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getbusmaster_rx" },
{ PRISM2_PARAM_BUS_MASTER_THRESHOLD_TX,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "busmaster_tx" },
{ PRISM2_PARAM_BUS_MASTER_THRESHOLD_TX,
0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getbusmaster_tx" },
#ifndef PRISM2_NO_STATION_MODES
{ PRISM2_PARAM_HOST_ROAMING,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "host_roaming" },
Expand Down Expand Up @@ -2495,14 +2487,6 @@ static int prism2_ioctl_priv_prism2_param(struct net_device *dev,
ret = -EINVAL;
break;

case PRISM2_PARAM_BUS_MASTER_THRESHOLD_RX:
local->bus_master_threshold_rx = value;
break;

case PRISM2_PARAM_BUS_MASTER_THRESHOLD_TX:
local->bus_master_threshold_tx = value;
break;

#ifndef PRISM2_NO_STATION_MODES
case PRISM2_PARAM_HOST_ROAMING:
if (value < 0 || value > 2) {
Expand Down Expand Up @@ -2799,14 +2783,6 @@ static int prism2_ioctl_priv_get_prism2_param(struct net_device *dev,
*param = local->host_decrypt;
break;

case PRISM2_PARAM_BUS_MASTER_THRESHOLD_RX:
*param = local->bus_master_threshold_rx;
break;

case PRISM2_PARAM_BUS_MASTER_THRESHOLD_TX:
*param = local->bus_master_threshold_tx;
break;

case PRISM2_PARAM_HOST_ROAMING:
*param = local->host_roaming;
break;
Expand Down
Loading

0 comments on commit ea3f186

Please sign in to comment.