/*
Broadcom BCM43xx wireless driver
DMA ringbuffer and descriptor allocation/management
Copyright (c) 2005, 2006 Michael Buesch <mbuesch@freenet.de>
Some code in this file is derived from the b44.c driver
Copyright (C) 2002 David S. Miller
Copyright (C) Pekka Pietikainen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "bcm43xx.h"
#include "bcm43xx_dma.h"
#include "bcm43xx_main.h"
#include "bcm43xx_debugfs.h"
#include "bcm43xx_power.h"
#include "bcm43xx_xmit.h"
#include <linux/dma-mapping.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/skbuff.h>
static inline int free_slots(struct bcm43xx_dmaring *ring)
{
return (ring->nr_slots - ring->used_slots);
}
static inline int next_slot(struct bcm43xx_dmaring *ring, int slot)
{
assert(slot >= -1 && slot <= ring->nr_slots - 1);
if (slot == ring->nr_slots - 1)
return 0;
return slot + 1;
}
static inline int prev_slot(struct bcm43xx_dmaring *ring, int slot)
{
assert(slot >= 0 && slot <= ring->nr_slots - 1);
if (slot == 0)
return ring->nr_slots - 1;
return slot - 1;
}
/* Request a slot for usage. */
static inline
int request_slot(struct bcm43xx_dmaring *ring)
{
int slot;
assert(ring->tx);
assert(!ring->suspended);
assert(free_slots(ring) != 0);
slot = next_slot(ring, ring->current_slot);
ring->current_slot = slot;
ring->used_slots++;
/* Check the number of available slots and suspend TX,
* if we are running low on free slots.
*/
if (unlikely(free_slots(ring) < ring->suspend_mark)) {
netif_stop_queue(ring->bcm->net_dev);
ring->suspended = 1;
}
#ifdef CONFIG_BCM43XX_DEBUG
if (ring->used_slots > ring->max_used_slots)
ring->max_used_slots = ring->used_slots;
#endif /* CONFIG_BCM43XX_DEBUG*/
return slot;
}
/* Return a slot to the free slots. */
static inline
void return_slot(struct bcm43xx_dmaring *ring, int slot)
{
assert(ring->tx);
ring->used_slots--;
/* Check if TX is suspended and check if we have
* enough free slots to resume it again.
*/
if (unlikely(ring->suspended)) {
if