[PATCH] hostap: Remove experimental PCI bus master/DMA code

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>
This commit is contained in:
Jouni Malinen 2005-08-14 19:08:40 -07:00 коммит произвёл Jeff Garzik
Родитель 5bee720fd7
Коммит ea3f1865f3
6 изменённых файлов: 13 добавлений и 273 удалений

Просмотреть файл

@ -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,

Просмотреть файл

@ -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

Просмотреть файл

@ -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: "
@ -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)
@ -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
@ -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 */
@ -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)
@ -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) {
@ -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)
{
@ -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);
@ -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;
@ -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);
@ -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;
}
@ -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);

Просмотреть файл

@ -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" },
@ -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) {
@ -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;

Просмотреть файл

@ -305,10 +305,6 @@ static int prism2_pci_probe(struct pci_dev *pdev,
goto fail;
}
#ifdef PRISM2_BUS_MASTER
pci_set_master(pdev);
#endif /* PRISM2_BUS_MASTER */
dev = prism2_init_local_data(&prism2_pci_funcs, cards_found,
&pdev->dev);
if (dev == NULL)

Просмотреть файл

@ -787,10 +787,6 @@ struct local_info {
struct prism2_helper_functions *func;
int bus_master_threshold_tx;
int bus_master_threshold_rx;
u8 *bus_m1_buf;
u8 *pda;
int fw_ap;
#define PRISM2_FW_VER(major, minor, variant) \
@ -897,14 +893,6 @@ struct local_info {
#ifdef PRISM2_PCI
void __iomem *mem_start;
#ifdef PRISM2_BUS_MASTER
/* bus master for BAP0 (TX) */
int bus_m0_tx_idx;
u8 *bus_m0_buf;
/* bus master for BAP1 (RX) */
struct sk_buff *rx_skb;
#endif /* PRISM2_BUS_MASTER */
#endif /* PRISM2_PCI */
/* NOTE! Do not add common entries here after hardware version