Release 4.11 drivers/atm/idt77252.c
/*******************************************************************
*
* Copyright (c) 2000 ATecoM GmbH
*
* The author may be reached at ecd@atecom.com.
*
* 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*
*******************************************************************/
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/poison.h>
#include <linux/skbuff.h>
#include <linux/kernel.h>
#include <linux/vmalloc.h>
#include <linux/netdevice.h>
#include <linux/atmdev.h>
#include <linux/atm.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/bitops.h>
#include <linux/wait.h>
#include <linux/jiffies.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <asm/io.h>
#include <linux/uaccess.h>
#include <linux/atomic.h>
#include <asm/byteorder.h>
#ifdef CONFIG_ATM_IDT77252_USE_SUNI
#include "suni.h"
#endif /* CONFIG_ATM_IDT77252_USE_SUNI */
#include "idt77252.h"
#include "idt77252_tables.h"
static unsigned int vpibits = 1;
#define ATM_IDT77252_SEND_IDLE 1
/*
* Debug HACKs.
*/
#define DEBUG_MODULE 1
#undef HAVE_EEPROM
/* does not work, yet. */
#ifdef CONFIG_ATM_IDT77252_DEBUG
static unsigned long debug = DBG_GENERAL;
#endif
#define SAR_RX_DELAY (SAR_CFG_RXINT_NODELAY)
/*
* SCQ Handling.
*/
static struct scq_info *alloc_scq(struct idt77252_dev *, int);
static void free_scq(struct idt77252_dev *, struct scq_info *);
static int queue_skb(struct idt77252_dev *, struct vc_map *,
struct sk_buff *, int oam);
static void drain_scq(struct idt77252_dev *, struct vc_map *);
static unsigned long get_free_scd(struct idt77252_dev *, struct vc_map *);
static void fill_scd(struct idt77252_dev *, struct scq_info *, int);
/*
* FBQ Handling.
*/
static int push_rx_skb(struct idt77252_dev *,
struct sk_buff *, int queue);
static void recycle_rx_skb(struct idt77252_dev *, struct sk_buff *);
static void flush_rx_pool(struct idt77252_dev *, struct rx_pool *);
static void recycle_rx_pool_skb(struct idt77252_dev *,
struct rx_pool *);
static void add_rx_skb(struct idt77252_dev *, int queue,
unsigned int size, unsigned int count);
/*
* RSQ Handling.
*/
static int init_rsq(struct idt77252_dev *);
static void deinit_rsq(struct idt77252_dev *);
static void idt77252_rx(struct idt77252_dev *);
/*
* TSQ handling.
*/
static int init_tsq(struct idt77252_dev *);
static void deinit_tsq(struct idt77252_dev *);
static void idt77252_tx(struct idt77252_dev *);
/*
* ATM Interface.
*/
static void idt77252_dev_close(struct atm_dev *dev);
static int idt77252_open(struct atm_vcc *vcc);
static void idt77252_close(struct atm_vcc *vcc);
static int idt77252_send(struct atm_vcc *vcc, struct sk_buff *skb);
static int idt77252_send_oam(struct atm_vcc *vcc, void *cell,
int flags);
static void idt77252_phy_put(struct atm_dev *dev, unsigned char value,
unsigned long addr);
static unsigned char idt77252_phy_get(struct atm_dev *dev, unsigned long addr);
static int idt77252_change_qos(struct atm_vcc *vcc, struct atm_qos *qos,
int flags);
static int idt77252_proc_read(struct atm_dev *dev, loff_t * pos,
char *page);
static void idt77252_softint(struct work_struct *work);
static struct atmdev_ops idt77252_ops =
{
.dev_close = idt77252_dev_close,
.open = idt77252_open,
.close = idt77252_close,
.send = idt77252_send,
.send_oam = idt77252_send_oam,
.phy_put = idt77252_phy_put,
.phy_get = idt77252_phy_get,
.change_qos = idt77252_change_qos,
.proc_read = idt77252_proc_read,
.owner = THIS_MODULE
};
static struct idt77252_dev *idt77252_chain = NULL;
static unsigned int idt77252_sram_write_errors = 0;
/*****************************************************************************/
/* */
/* I/O and Utility Bus */
/* */
/*****************************************************************************/
static void
waitfor_idle(struct idt77252_dev *card)
{
u32 stat;
stat = readl(SAR_REG_STAT);
while (stat & SAR_STAT_CMDBZ)
stat = readl(SAR_REG_STAT);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds | 34 | 100.00% | 1 | 100.00% |
Total | 34 | 100.00% | 1 | 100.00% |
static u32
read_sram(struct idt77252_dev *card, unsigned long addr)
{
unsigned long flags;
u32 value;
spin_lock_irqsave(&card->cmd_lock, flags);
writel(SAR_CMD_READ_SRAM | (addr << 2), SAR_REG_CMD);
waitfor_idle(card);
value = readl(SAR_REG_DR0);
spin_unlock_irqrestore(&card->cmd_lock, flags);
return value;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds | 70 | 100.00% | 1 | 100.00% |
Total | 70 | 100.00% | 1 | 100.00% |
static void
write_sram(struct idt77252_dev *card, unsigned long addr, u32 value)
{
unsigned long flags;
if ((idt77252_sram_write_errors == 0) &&
(((addr > card->tst[0] + card->tst_size - 2) &&
(addr < card->tst[0] + card->tst_size)) ||
((addr > card->tst[1] + card->tst_size - 2) &&
(addr < card->tst[1] + card->tst_size)))) {
printk("%s: ERROR: TST JMP section at %08lx written: %08x\n",
card->name, addr, value);
}
spin_lock_irqsave(&card->cmd_lock, flags);
writel(value, SAR_REG_DR0);
writel(SAR_CMD_WRITE_SRAM | (addr << 2), SAR_REG_CMD);
waitfor_idle(card);
spin_unlock_irqrestore(&card->cmd_lock, flags);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds | 160 | 100.00% | 1 | 100.00% |
Total | 160 | 100.00% | 1 | 100.00% |
static u8
read_utility(void *dev, unsigned long ubus_addr)
{
struct idt77252_dev *card = dev;
unsigned long flags;
u8 value;
if (!card) {
printk("Error: No such device.\n");
return -1;
}
spin_lock_irqsave(&card->cmd_lock, flags);
writel(SAR_CMD_READ_UTILITY + ubus_addr, SAR_REG_CMD);
waitfor_idle(card);
value = readl(SAR_REG_DR0);
spin_unlock_irqrestore(&card->cmd_lock, flags);
return value;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds | 88 | 100.00% | 1 | 100.00% |
Total | 88 | 100.00% | 1 | 100.00% |
static void
write_utility(void *dev, unsigned long ubus_addr, u8 value)
{
struct idt77252_dev *card = dev;
unsigned long flags;
if (!card) {
printk("Error: No such device.\n");
return;
}
spin_lock_irqsave(&card->cmd_lock, flags);
writel((u32) value, SAR_REG_DR0);
writel(SAR_CMD_WRITE_UTILITY + ubus_addr, SAR_REG_CMD);
waitfor_idle(card);
spin_unlock_irqrestore(&card->cmd_lock, flags);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds | 85 | 100.00% | 1 | 100.00% |
Total | 85 | 100.00% | 1 | 100.00% |
#ifdef HAVE_EEPROM
static u32 rdsrtab[] =
{
SAR_GP_EECS | SAR_GP_EESCLK,
0,
SAR_GP_EESCLK, /* 0 */
0,
SAR_GP_EESCLK, /* 0 */
0,
SAR_GP_EESCLK, /* 0 */
0,
SAR_GP_EESCLK, /* 0 */
0,
SAR_GP_EESCLK, /* 0 */
SAR_GP_EEDO,
SAR_GP_EESCLK | SAR_GP_EEDO, /* 1 */
0,
SAR_GP_EESCLK, /* 0 */
SAR_GP_EEDO,
SAR_GP_EESCLK | SAR_GP_EEDO /* 1 */
};
static u32 wrentab[] =
{
SAR_GP_EECS | SAR_GP_EESCLK,
0,
SAR_GP_EESCLK, /* 0 */
0,
SAR_GP_EESCLK, /* 0 */
0,
SAR_GP_EESCLK, /* 0 */
0,
SAR_GP_EESCLK, /* 0 */
SAR_GP_EEDO,
SAR_GP_EESCLK | SAR_GP_EEDO, /* 1 */
SAR_GP_EEDO,
SAR_GP_EESCLK | SAR_GP_EEDO, /* 1 */
0,
SAR_GP_EESCLK, /* 0 */
0,
SAR_GP_EESCLK /* 0 */
};
static u32 rdtab[] =
{
SAR_GP_EECS | SAR_GP_EESCLK,
0,
SAR_GP_EESCLK, /* 0 */
0,
SAR_GP_EESCLK, /* 0 */
0,
SAR_GP_EESCLK, /* 0 */
0,
SAR_GP_EESCLK, /* 0 */
0,
SAR_GP_EESCLK, /* 0 */
0,
SAR_GP_EESCLK, /* 0 */
SAR_GP_EEDO,
SAR_GP_EESCLK | SAR_GP_EEDO, /* 1 */
SAR_GP_EEDO,
SAR_GP_EESCLK | SAR_GP_EEDO /* 1 */
};
static u32 wrtab[] =
{
SAR_GP_EECS | SAR_GP_EESCLK,
0,
SAR_GP_EESCLK, /* 0 */
0,
SAR_GP_EESCLK, /* 0 */
0,
SAR_GP_EESCLK, /* 0 */
0,
SAR_GP_EESCLK, /* 0 */
0,
SAR_GP_EESCLK, /* 0 */
0,
SAR_GP_EESCLK, /* 0 */
SAR_GP_EEDO,
SAR_GP_EESCLK | SAR_GP_EEDO, /* 1 */
0,
SAR_GP_EESCLK /* 0 */
};
static u32 clktab[] =
{
0,
SAR_GP_EESCLK,
0,
SAR_GP_EESCLK,
0,
SAR_GP_EESCLK,
0,
SAR_GP_EESCLK,
0,
SAR_GP_EESCLK,
0,
SAR_GP_EESCLK,
0,
SAR_GP_EESCLK,
0,
SAR_GP_EESCLK,
0
};
static u32
idt77252_read_gp(struct idt77252_dev *card)
{
u32 gp;
gp = readl(SAR_REG_GP);
#if 0
printk("RD: %s\n", gp & SAR_GP_EEDI ? "1" : "0");
#endif
return gp;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds | 30 | 100.00% | 1 | 100.00% |
Total | 30 | 100.00% | 1 | 100.00% |
static void
idt77252_write_gp(struct idt77252_dev *card, u32 value)
{
unsigned long flags;
#if 0
printk("WR: %s %s %s\n", value & SAR_GP_EECS ? " " : "/CS",
value & SAR_GP_EESCLK ? "HIGH" : "LOW ",
value & SAR_GP_EEDO ? "1" : "0");
#endif
spin_lock_irqsave(&card->cmd_lock, flags);
waitfor_idle(card);
writel(value, SAR_REG_GP);
spin_unlock_irqrestore(&card->cmd_lock, flags);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds | 56 | 100.00% | 1 | 100.00% |
Total | 56 | 100.00% | 1 | 100.00% |
static u8
idt77252_eeprom_read_status(struct idt77252_dev *card)
{
u8 byte;
u32 gp;
int i, j;
gp = idt77252_read_gp(card) & ~(SAR_GP_EESCLK|SAR_GP_EECS|SAR_GP_EEDO);
for (i = 0; i < ARRAY_SIZE(rdsrtab); i++) {
idt77252_write_gp(card, gp | rdsrtab[i]);
udelay(5);
}
idt77252_write_gp(card, gp | SAR_GP_EECS);
udelay(5);
byte = 0;
for (i = 0, j = 0; i < 8; i++) {
byte <<= 1;
idt77252_write_gp(card, gp | clktab[j++]);
udelay(5);
byte |= idt77252_read_gp(card) & SAR_GP_EEDI ? 1 : 0;
idt77252_write_gp(card, gp | clktab[j++]);
udelay(5);
}
idt77252_write_gp(card, gp | SAR_GP_EECS);
udelay(5);
return byte;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds | 179 | 99.44% | 1 | 50.00% |
Ahmed S. Darwish | 1 | 0.56% | 1 | 50.00% |
Total | 180 | 100.00% | 2 | 100.00% |
static u8
idt77252_eeprom_read_byte(struct idt77252_dev *card, u8 offset)
{
u8 byte;
u32 gp;
int i, j;
gp = idt77252_read_gp(card) & ~(SAR_GP_EESCLK|SAR_GP_EECS|SAR_GP_EEDO);
for (i = 0; i < ARRAY_SIZE(rdtab); i++) {
idt77252_write_gp(card, gp | rdtab[i]);
udelay(5);
}
idt77252_write_gp(card, gp | SAR_GP_EECS);
udelay(5);
for (i = 0, j = 0; i < 8; i++) {
idt77252_write_gp(card, gp | clktab[j++] |
(offset & 1 ? SAR_GP_EEDO : 0));
udelay(5);
idt77252_write_gp(card, gp | clktab[j++] |
(offset & 1 ? SAR_GP_EEDO : 0));
udelay(5);
offset >>= 1;
}
idt77252_write_gp(card, gp | SAR_GP_EECS);
udelay(5);
byte = 0;
for (i = 0, j = 0; i < 8; i++) {
byte <<= 1;
idt77252_write_gp(card, gp | clktab[j++]);
udelay(5);
byte |= idt77252_read_gp(card) & SAR_GP_EEDI ? 1 : 0;
idt77252_write_gp(card, gp | clktab[j++]);
udelay(5);
}
idt77252_write_gp(card, gp | SAR_GP_EECS);
udelay(5);
return byte;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds | 275 | 99.64% | 1 | 50.00% |
Ahmed S. Darwish | 1 | 0.36% | 1 | 50.00% |
Total | 276 | 100.00% | 2 | 100.00% |
static void
idt77252_eeprom_write_byte(struct idt77252_dev *card, u8 offset, u8 data)
{
u32 gp;
int i, j;
gp = idt77252_read_gp(card) & ~(SAR_GP_EESCLK|SAR_GP_EECS|SAR_GP_EEDO);
for (i = 0; i < ARRAY_SIZE(wrentab); i++) {
idt77252_write_gp(card, gp | wrentab[i]);
udelay(5);
}
idt77252_write_gp(card, gp | SAR_GP_EECS);
udelay(5);
for (i = 0; i < ARRAY_SIZE(wrtab); i++) {
idt77252_write_gp(card, gp | wrtab[i]);
udelay(5);
}
idt77252_write_gp(card, gp | SAR_GP_EECS);
udelay(5);
for (i = 0, j = 0; i < 8; i++) {
idt77252_write_gp(card, gp | clktab[j++] |
(offset & 1 ? SAR_GP_EEDO : 0));
udelay(5);
idt77252_write_gp(card, gp | clktab[j++] |
(offset & 1 ? SAR_GP_EEDO : 0));
udelay(5);
offset >>= 1;
}
idt77252_write_gp(card, gp | SAR_GP_EECS);
udelay(5);
for (i = 0, j = 0; i < 8; i++) {
idt77252_write_gp(card, gp | clktab[j++] |
(data & 1 ? SAR_GP_EEDO : 0));
udelay(5);
idt77252_write_gp(card, gp | clktab[j++] |
(data & 1 ? SAR_GP_EEDO : 0));
udelay(5);
data >>= 1;
}
idt77252_write_gp(card, gp | SAR_GP_EECS);
udelay(5);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds | 323 | 99.38% | 1 | 50.00% |
Ahmed S. Darwish | 2 | 0.62% | 1 | 50.00% |
Total | 325 | 100.00% | 2 | 100.00% |
static void
idt77252_eeprom_init(struct idt77252_dev *card)
{
u32 gp;
gp = idt77252_read_gp(card) & ~(SAR_GP_EESCLK|SAR_GP_EECS|SAR_GP_EEDO);
idt77252_write_gp(card, gp | SAR_GP_EECS | SAR_GP_EESCLK);
udelay(5);
idt77252_write_gp(card, gp | SAR_GP_EECS);
udelay(5);
idt77252_write_gp(card, gp | SAR_GP_EECS | SAR_GP_EESCLK);
udelay(5);
idt77252_write_gp(card, gp | SAR_GP_EECS);
udelay(5);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds | 90 | 100.00% | 1 | 100.00% |
Total | 90 | 100.00% | 1 | 100.00% |
#endif /* HAVE_EEPROM */
#ifdef CONFIG_ATM_IDT77252_DEBUG
static void
dump_tct(struct idt77252_dev *card, int index)
{
unsigned long tct;
int i;
tct = (unsigned long) (card->tct_base + index * SAR_SRAM_TCT_SIZE);
printk("%s: TCT %x:", card->name, index);
for (i = 0; i < 8; i++) {
printk(" %08x", read_sram(card, tct + i));
}
printk("\n");
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds | 82 | 100.00% | 1 | 100.00% |
Total | 82 | 100.00% | 1 | 100.00% |
static void
idt77252_tx_dump(struct idt77252_dev *card)
{
struct atm_vcc *vcc;
struct vc_map *vc;
int i;
printk("%s\n", __func__);
for (i = 0; i < card->tct_size; i++) {
vc = card->vcs[i];
if (!vc)
continue;
vcc = NULL;
if (vc->rx_vcc)
vcc = vc->rx_vcc;
else if (vc->tx_vcc)
vcc = vc->tx_vcc;
if (!vcc)
continue;
printk("%s: Connection %d:\n", card->name, vc->index);
dump_tct(card, vc->index);
}
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds | 119 | 99.17% | 1 | 50.00% |
Harvey Harrison | 1 | 0.83% | 1 | 50.00% |
Total | 120 | 100.00% | 2 | 100.00% |
#endif
/*****************************************************************************/
/* */
/* SCQ Handling */
/* */
/*****************************************************************************/
static int
sb_pool_add(struct idt77252_dev *card, struct sk_buff *skb, int queue)
{
struct sb_pool *pool = &card->sbpool[queue];
int index;
index = pool->index;
while (pool->skb[index]) {
index = (index + 1) & FBQ_MASK;
if (index == pool->index)
return -ENOBUFS;
}
pool->skb[index] = skb;
IDT77252_PRV_POOL(skb) = POOL_HANDLE(queue, index);
pool->index = (index + 1) & FBQ_MASK;
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds | 110 | 100.00% | 1 | 100.00% |
Total | 110 | 100.00% | 1 | 100.00% |
static void
sb_pool_remove(struct idt77252_dev *card, struct sk_buff *skb)
{
unsigned int queue, index;
u32 handle;
handle = IDT77252_PRV_POOL(skb);
queue = POOL_QUEUE(handle);
if (queue > 3)
return;
index = POOL_INDEX(handle);
if (index > FBQ_SIZE - 1)
return;
card->sbpool[queue].skb[index] = NULL;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds | 76 | 100.00% | 1 | 100.00% |
Total | 76 | 100.00% | 1 | 100.00% |
static struct sk_buff *
sb_pool_skb(struct idt77252_dev *card, u32 handle)
{
unsigned int queue, index;
queue = POOL_QUEUE(handle);
if (queue > 3)
return NULL;
index = POOL_INDEX(handle);
if (index > FBQ_SIZE - 1)
return NULL;
return card->sbpool[queue].skb[index];
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds | 69 | 100.00% | 1 | 100.00% |
Total | 69 | 100.00% | 1 | 100.00% |
static struct scq_info *
alloc_scq(struct idt77252_dev *card, int class)
{
struct scq_info *scq;
scq = kzalloc(sizeof(struct scq_info), GFP_KERNEL);
if (!scq)
return NULL;
scq->base = dma_zalloc_coherent(&card->pcidev->dev, SCQ_SIZE,
&scq->paddr, GFP_KERNEL);
if (scq->base == NULL) {
kfree(scq);
return NULL;
}
scq->next = scq->base;
scq->last = scq->base + (SCQ_ENTRIES - 1);
atomic_set(&scq->used, 0);
spin_lock_init(&scq->lock);
spin_lock_init(&scq->skblock);
skb_queue_head_init(&scq->transmit);
skb_queue_head_init(&scq->pending);
TXPRINTK("idt77252: SCQ: base 0x%p, next 0x%p, last 0x%p, paddr %08llx\n",
scq->base, scq->next, scq->last, (unsigned long long)scq->paddr);
return scq;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds | 163 | 92.61% | 1 | 25.00% |
Chas Williams | 12 | 6.82% | 2 | 50.00% |
Om Narasimhan | 1 | 0.57% | 1 | 25.00% |
Total | 176 | 100.00% | 4 | 100.00% |
static void
free_scq(struct idt77252_dev *card, struct scq_info *scq)
{
struct sk_buff *skb;
struct atm_vcc *vcc;
dma_free_coherent(&card->pcidev->dev, SCQ_SIZE,
scq->base, scq->paddr);
while ((skb = skb_dequeue(&scq->transmit))) {
dma_unmap_single(&card->pcidev->dev, IDT77252_PRV_PADDR(skb),
skb->len, DMA_TO_DEVICE);
vcc = ATM_SKB(skb)->vcc;
if (vcc->pop)
vcc->pop(vcc, skb);
else
dev_kfree_skb(skb);
}
while ((skb = skb_dequeue(&scq->pending))) {
dma_unmap_single(&card->pcidev->dev, IDT77252_PRV_PADDR(skb),
skb->len, DMA_TO_DEVICE);
vcc = ATM_SKB(skb)->vcc;
if (vcc->pop)
vcc->pop(vcc, skb);
else
dev_kfree_skb(skb);
}
kfree(scq);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds | 171 | 92.43% | 1 | 50.00% |
Chas Williams | 14 | 7.57% | 1 | 50.00% |
Total | 185 | 100.00% | 2 | 100.00% |
static int
push_on_scq(struct idt77252_dev *card, struct vc_map *vc, struct sk_buff *skb)
{
struct scq_info *scq = vc->scq;
unsigned long flags;
struct scqe *tbd;
int entries;
TXPRINTK("%s: SCQ: next 0x%p\n", card->name, scq->next);
atomic_inc(&scq->used);
entries = atomic_read(&scq->used);
if (entries > (SCQ_ENTRIES - 1)) {
atomic_dec(&scq->used);
goto out;
}
skb_queue_tail(&scq->transmit, skb);
spin_lock_irqsave(&vc->lock, flags);
if (vc->estimator) {
struct atm_vcc *vcc = vc->tx_vcc;
struct sock *sk = sk_atm(vcc);
vc->estimator->cells += (skb->len + 47) / 48;
if (atomic_read(&sk->sk_wmem_alloc) >
(sk->sk_sndbuf >> 1)) {
u32 cps = vc->estimator->maxcps;
vc->estimator->cps = cps;