* Re: Davicom DM9000C driver
From: Bruno Prémont @ 2012-09-19 16:39 UTC (permalink / raw)
To: Allen Huang
Cc: linux-kernel, 'Michael Chen', 'Charles',
'Joseph Chang', Linux network list
In-Reply-To: <20120919055333.3ECF95F94D@mail.davicom.com.tw>
[-- Attachment #1: Type: text/plain, Size: 1252 bytes --]
Hi Allen,
[CCing netdev, keeping .c/.h source attached]
On Wed, 19 September 2012 Allen Huang (黃偉格) <allen_huang@davicom.com.tw> wrote:
> I'm Allen Huang from Davicom. We are hereby opensourcing the linux
> driver for our DM9000C.
Ah, from looking at the code DM9000C looks like it is some nerwork chip,
what platforms does it show up on?
> We would appreciate any comments that you have on our driver and
> whether it is ready to go into the kernel. Please see DM9000C driver in the
> attachment.
It would be nice if you could include the changes to Kconfig/Makefile
including a description as it's not clear on what kind of devices the
chip can be encountered.
Also please properly tag the source files attachments as text/plain.
With a quick glance at the code:
- your comments are often single-line C++ style //
and should be changed to /* */.
- comments that look like author/revision tags
- there are blocks of code commented or inside if (1) {}
- some printk calls missing KERN_ severity tag
- indentation issues
Please fix above issues (and have a look at scripts/checkpatch.pl) and
respin (as a patch) taking care to CC netdev so network people have to
chance to see it.
Bruno
[-- Attachment #2: dm9000_KT2.6.31.c --]
[-- Type: text/plain, Size: 37105 bytes --]
/*
* Davicom DM9000 Fast Ethernet driver for Linux.
* Copyright (C) 1997 Sten Wang
*
* 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.
*
* (C) Copyright 1997-1998 DAVICOM Semiconductor,Inc. All Rights Reserved.
*
* Additional updates, Copyright:
* Ben Dooks <ben@simtec.co.uk>
* Sascha Hauer <s.hauer@pengutronix.de>
*
* 2010.07.20 V_R1 1.Write PHY Reg27 = 0xE100
* 2.Just enable PHY once after GPIO setting in dm9000_init_dm9000()
* 3.Remove power down PHY in dm9000_shutdown()
* 2010.07.20 V_R2 1.Delay 20ms after PHY power on
* 2.Reset PHY after PHY power on in dm9000_init_dm9000()
* 2012.06.05 KT2.6.31_R2 1. Add the solution to fix the power-on FIFO data bytes shift issue! (Wr NCR 0x03)
*/
#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
#include <linux/skbuff.h>
#include <linux/version.h>
#include <linux/spinlock.h>
#include <linux/crc32.h>
#include <linux/mii.h>
#include <linux/ethtool.h>
#include <linux/dm9000.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/irq.h>
#include <asm/delay.h>
#include <asm/irq.h>
#include <asm/io.h>
#include "dm9000.h"
/* Board/System/Debug information/definition ---------------- */
#define DM9000_PHY 0x40 /* PHY address 0x01 */
#define CARDNAME "dm9000"
#define DRV_VERSION "2.6.31"
/*
* Transmit timeout, default 5 seconds.
*/
static int watchdog = 5000;
module_param(watchdog, int, 0400);
MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds");
/* DM9000 register address locking.
*
* The DM9000 uses an address register to control where data written
* to the data register goes. This means that the address register
* must be preserved over interrupts or similar calls.
*
* During interrupt and other critical calls, a spinlock is used to
* protect the system, but the calls themselves save the address
* in the address register in case they are interrupting another
* access to the device.
*
* For general accesses a lock is provided so that calls which are
* allowed to sleep are serialised so that the address register does
* not need to be saved. This lock also serves to serialise access
* to the EEPROM and PHY access registers which are shared between
* these two devices.
*/
/* The driver supports the original DM9000E, and now the two newer
* devices, DM9000A and DM9000B.
*/
enum dm9000_type {
TYPE_DM9000E, /* original DM9000 */
TYPE_DM9000A,
TYPE_DM9000B
};
/* Structure/enum declaration ------------------------------- */
typedef struct board_info {
void __iomem *io_addr; /* Register I/O base address */
void __iomem *io_data; /* Data I/O address */
u16 irq; /* IRQ */
u16 tx_pkt_cnt;
u16 queue_pkt_len;
u16 queue_start_addr;
u16 dbug_cnt;
u8 io_mode; /* 0:word, 2:byte */
u8 phy_addr;
u8 imr_all;
unsigned int flags;
unsigned int in_suspend :1;
int debug_level;
enum dm9000_type type;
void (*inblk)(void __iomem *port, void *data, int length);
void (*outblk)(void __iomem *port, void *data, int length);
void (*dumpblk)(void __iomem *port, int length);
struct device *dev; /* parent device */
struct resource *addr_res; /* resources found */
struct resource *data_res;
struct resource *addr_req; /* resources requested */
struct resource *data_req;
struct resource *irq_res;
struct mutex addr_lock; /* phy and eeprom access lock */
struct delayed_work phy_poll;
struct net_device *ndev;
spinlock_t lock;
struct mii_if_info mii;
u32 msg_enable;
} board_info_t;
static void
dm9000_phy_write(struct net_device *dev,
int phyaddr_unused, int reg, int value);
/* debug code */
#define dm9000_dbg(db, lev, msg...) do { \
if ((lev) < CONFIG_DM9000_DEBUGLEVEL && \
(lev) < db->debug_level) { \
dev_dbg(db->dev, msg); \
} \
} while (0)
static inline board_info_t *to_dm9000_board(struct net_device *dev)
{
return netdev_priv(dev);
}
/* DM9000 network board routine ---------------------------- */
static void
dm9000_reset(board_info_t * db)
{
dev_dbg(db->dev, "resetting device\n");
/* RESET device */
writeb(DM9000_NCR, db->io_addr);
udelay(200);
writeb(NCR_RST, db->io_data);
udelay(200);
}
/*
* Read a byte from I/O port
*/
static u8
ior(board_info_t * db, int reg)
{
writeb(reg, db->io_addr);
return readb(db->io_data);
}
/*
* Write a byte to I/O port
*/
static void
iow(board_info_t * db, int reg, int value)
{
writeb(reg, db->io_addr);
writeb(value, db->io_data);
}
/* routines for sending block to chip */
static void dm9000_outblk_8bit(void __iomem *reg, void *data, int count)
{
writesb(reg, data, count);
}
static void dm9000_outblk_16bit(void __iomem *reg, void *data, int count)
{
writesw(reg, data, (count+1) >> 1);
}
static void dm9000_outblk_32bit(void __iomem *reg, void *data, int count)
{
writesl(reg, data, (count+3) >> 2);
}
/* input block from chip to memory */
static void dm9000_inblk_8bit(void __iomem *reg, void *data, int count)
{
readsb(reg, data, count);
}
static void dm9000_inblk_16bit(void __iomem *reg, void *data, int count)
{
readsw(reg, data, (count+1) >> 1);
}
static void dm9000_inblk_32bit(void __iomem *reg, void *data, int count)
{
readsl(reg, data, (count+3) >> 2);
}
/* dump block from chip to null */
static void dm9000_dumpblk_8bit(void __iomem *reg, int count)
{
int i;
int tmp;
for (i = 0; i < count; i++)
tmp = readb(reg);
}
static void dm9000_dumpblk_16bit(void __iomem *reg, int count)
{
int i;
int tmp;
count = (count + 1) >> 1;
for (i = 0; i < count; i++)
tmp = readw(reg);
}
static void dm9000_dumpblk_32bit(void __iomem *reg, int count)
{
int i;
int tmp;
count = (count + 3) >> 2;
for (i = 0; i < count; i++)
tmp = readl(reg);
}
/* dm9000_set_io
*
* select the specified set of io routines to use with the
* device
*/
static void dm9000_set_io(struct board_info *db, int byte_width)
{
/* use the size of the data resource to work out what IO
* routines we want to use
*/
switch (byte_width) {
case 1:
db->dumpblk = dm9000_dumpblk_8bit;
db->outblk = dm9000_outblk_8bit;
db->inblk = dm9000_inblk_8bit;
break;
case 3:
dev_dbg(db->dev, ": 3 byte IO, falling back to 16bit\n");
case 2:
db->dumpblk = dm9000_dumpblk_16bit;
db->outblk = dm9000_outblk_16bit;
db->inblk = dm9000_inblk_16bit;
break;
case 4:
default:
db->dumpblk = dm9000_dumpblk_32bit;
db->outblk = dm9000_outblk_32bit;
db->inblk = dm9000_inblk_32bit;
break;
}
}
static void dm9000_schedule_poll(board_info_t *db)
{
if (db->type == TYPE_DM9000E)
schedule_delayed_work(&db->phy_poll, HZ * 2);
}
static int dm9000_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
{
board_info_t *dm = to_dm9000_board(dev);
if (!netif_running(dev))
return -EINVAL;
return generic_mii_ioctl(&dm->mii, if_mii(req), cmd, NULL);
}
static unsigned int
dm9000_read_locked(board_info_t *db, int reg)
{
unsigned long flags;
unsigned int ret;
spin_lock_irqsave(&db->lock, flags);
ret = ior(db, reg);
spin_unlock_irqrestore(&db->lock, flags);
return ret;
}
static int dm9000_wait_eeprom(board_info_t *db)
{
unsigned int status;
int timeout = 8; /* wait max 8msec */
/* The DM9000 data sheets say we should be able to
* poll the ERRE bit in EPCR to wait for the EEPROM
* operation. From testing several chips, this bit
* does not seem to work.
*
* We attempt to use the bit, but fall back to the
* timeout (which is why we do not return an error
* on expiry) to say that the EEPROM operation has
* completed.
*/
while (1) {
status = dm9000_read_locked(db, DM9000_EPCR);
if ((status & EPCR_ERRE) == 0)
break;
msleep(1);
if (timeout-- < 0) {
dev_dbg(db->dev, "timeout waiting EEPROM\n");
break;
}
}
return 0;
}
/*
* Read a word data from EEPROM
*/
static void
dm9000_read_eeprom(board_info_t *db, int offset, u8 *to)
{
unsigned long flags;
if (db->flags & DM9000_PLATF_NO_EEPROM) {
to[0] = 0xff;
to[1] = 0xff;
return;
}
mutex_lock(&db->addr_lock);
spin_lock_irqsave(&db->lock, flags);
iow(db, DM9000_EPAR, offset);
iow(db, DM9000_EPCR, EPCR_ERPRR);
spin_unlock_irqrestore(&db->lock, flags);
dm9000_wait_eeprom(db);
/* delay for at-least 150uS */
msleep(1);
spin_lock_irqsave(&db->lock, flags);
iow(db, DM9000_EPCR, 0x0);
to[0] = ior(db, DM9000_EPDRL);
to[1] = ior(db, DM9000_EPDRH);
spin_unlock_irqrestore(&db->lock, flags);
mutex_unlock(&db->addr_lock);
}
/*
* Write a word data to SROM
*/
static void
dm9000_write_eeprom(board_info_t *db, int offset, u8 *data)
{
unsigned long flags;
if (db->flags & DM9000_PLATF_NO_EEPROM)
return;
mutex_lock(&db->addr_lock);
spin_lock_irqsave(&db->lock, flags);
iow(db, DM9000_EPAR, offset);
iow(db, DM9000_EPDRH, data[1]);
iow(db, DM9000_EPDRL, data[0]);
iow(db, DM9000_EPCR, EPCR_WEP | EPCR_ERPRW);
spin_unlock_irqrestore(&db->lock, flags);
dm9000_wait_eeprom(db);
mdelay(1); /* wait at least 150uS to clear */
spin_lock_irqsave(&db->lock, flags);
iow(db, DM9000_EPCR, 0);
spin_unlock_irqrestore(&db->lock, flags);
mutex_unlock(&db->addr_lock);
}
/* ethtool ops */
static void dm9000_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *info)
{
board_info_t *dm = to_dm9000_board(dev);
strcpy(info->driver, CARDNAME);
strcpy(info->version, DRV_VERSION);
strcpy(info->bus_info, to_platform_device(dm->dev)->name);
}
static u32 dm9000_get_msglevel(struct net_device *dev)
{
board_info_t *dm = to_dm9000_board(dev);
return dm->msg_enable;
}
static void dm9000_set_msglevel(struct net_device *dev, u32 value)
{
board_info_t *dm = to_dm9000_board(dev);
dm->msg_enable = value;
}
static int dm9000_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
board_info_t *dm = to_dm9000_board(dev);
mii_ethtool_gset(&dm->mii, cmd);
return 0;
}
static int dm9000_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
board_info_t *dm = to_dm9000_board(dev);
return mii_ethtool_sset(&dm->mii, cmd);
}
static int dm9000_nway_reset(struct net_device *dev)
{
board_info_t *dm = to_dm9000_board(dev);
return mii_nway_restart(&dm->mii);
}
static u32 dm9000_get_link(struct net_device *dev)
{
board_info_t *dm = to_dm9000_board(dev);
u32 ret;
if (dm->flags & DM9000_PLATF_EXT_PHY)
ret = mii_link_ok(&dm->mii);
else
ret = dm9000_read_locked(dm, DM9000_NSR) & NSR_LINKST ? 1 : 0;
return ret;
}
#define DM_EEPROM_MAGIC (0x444D394B)
static int dm9000_get_eeprom_len(struct net_device *dev)
{
return 128;
}
static int dm9000_get_eeprom(struct net_device *dev,
struct ethtool_eeprom *ee, u8 *data)
{
board_info_t *dm = to_dm9000_board(dev);
int offset = ee->offset;
int len = ee->len;
int i;
/* EEPROM access is aligned to two bytes */
if ((len & 1) != 0 || (offset & 1) != 0)
return -EINVAL;
if (dm->flags & DM9000_PLATF_NO_EEPROM)
return -ENOENT;
ee->magic = DM_EEPROM_MAGIC;
for (i = 0; i < len; i += 2)
dm9000_read_eeprom(dm, (offset + i) / 2, data + i);
return 0;
}
static int dm9000_set_eeprom(struct net_device *dev,
struct ethtool_eeprom *ee, u8 *data)
{
board_info_t *dm = to_dm9000_board(dev);
int offset = ee->offset;
int len = ee->len;
int i;
/* EEPROM access is aligned to two bytes */
if ((len & 1) != 0 || (offset & 1) != 0)
return -EINVAL;
if (dm->flags & DM9000_PLATF_NO_EEPROM)
return -ENOENT;
if (ee->magic != DM_EEPROM_MAGIC)
return -EINVAL;
for (i = 0; i < len; i += 2)
dm9000_write_eeprom(dm, (offset + i) / 2, data + i);
return 0;
}
static const struct ethtool_ops dm9000_ethtool_ops = {
.get_drvinfo = dm9000_get_drvinfo,
.get_settings = dm9000_get_settings,
.set_settings = dm9000_set_settings,
.get_msglevel = dm9000_get_msglevel,
.set_msglevel = dm9000_set_msglevel,
.nway_reset = dm9000_nway_reset,
.get_link = dm9000_get_link,
.get_eeprom_len = dm9000_get_eeprom_len,
.get_eeprom = dm9000_get_eeprom,
.set_eeprom = dm9000_set_eeprom,
};
static void dm9000_show_carrier(board_info_t *db,
unsigned carrier, unsigned nsr)
{
struct net_device *ndev = db->ndev;
unsigned ncr = dm9000_read_locked(db, DM9000_NCR);
if (carrier)
dev_info(db->dev, "%s: link up, %dMbps, %s-duplex, no LPA\n",
ndev->name, (nsr & NSR_SPEED) ? 10 : 100,
(ncr & NCR_FDX) ? "full" : "half");
else
dev_info(db->dev, "%s: link down\n", ndev->name);
}
static unsigned char dm9000_type_to_char(enum dm9000_type type)
{
switch (type) {
case TYPE_DM9000E: return 'e';
case TYPE_DM9000A: return 'a';
case TYPE_DM9000B: return 'b';
}
return '?';
}
static void
dm9000_poll_work(struct work_struct *w)
{
struct delayed_work *dw = container_of(w, struct delayed_work, work);
board_info_t *db = container_of(dw, board_info_t, phy_poll);
struct net_device *ndev = db->ndev;
//JJ2
// if (db->flags & DM9000_PLATF_SIMPLE_PHY &&
// !(db->flags & DM9000_PLATF_EXT_PHY)) {
// =
if(1){
unsigned nsr = dm9000_read_locked(db, DM9000_NSR);
unsigned old_carrier = netif_carrier_ok(ndev) ? 1 : 0;
unsigned new_carrier;
new_carrier = (nsr & NSR_LINKST) ? 1 : 0;
if (old_carrier != new_carrier) {
if (new_carrier)
printk(KERN_INFO "[dm9000%c %s Ethernet Driver, V%s]: Link-Up!!\n",dm9000_type_to_char(db->type), CARDNAME, DRV_VERSION); //JJ2
else
printk(KERN_INFO "[%s Ethernet Driver, V%s]: Link-Down!!\n", CARDNAME, DRV_VERSION); //JJ2
if (netif_msg_link(db))
dm9000_show_carrier(db, new_carrier, nsr);
if (!new_carrier)
netif_carrier_off(ndev);
else
netif_carrier_on(ndev);
}
} else
mii_check_media(&db->mii, netif_msg_link(db), 0);
if (netif_running(ndev))
dm9000_schedule_poll(db);
}
/* dm9000_release_board
*
* release a board, and any mapped resources
*/
static void
dm9000_release_board(struct platform_device *pdev, struct board_info *db)
{
/* unmap our resources */
iounmap(db->io_addr);
iounmap(db->io_data);
/* release the resources */
release_resource(db->data_req);
kfree(db->data_req);
release_resource(db->addr_req);
kfree(db->addr_req);
}
/*
* Set DM9000 multicast address
*/
static void
dm9000_hash_table(struct net_device *dev)
{
board_info_t *db = netdev_priv(dev);
struct dev_mc_list *mcptr = dev->mc_list;
int mc_cnt = dev->mc_count;
int i, oft;
u32 hash_val;
u16 hash_table[4];
u8 rcr = RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN;
unsigned long flags;
dm9000_dbg(db, 1, "entering %s\n", __func__);
spin_lock_irqsave(&db->lock, flags);
for (i = 0, oft = DM9000_PAR; i < 6; i++, oft++)
iow(db, oft, dev->dev_addr[i]);
/* Clear Hash Table */
for (i = 0; i < 4; i++)
hash_table[i] = 0x0;
/* broadcast address */
hash_table[3] = 0x8000;
if (dev->flags & IFF_PROMISC)
rcr |= RCR_PRMSC;
if (dev->flags & IFF_ALLMULTI)
rcr |= RCR_ALL;
/* the multicast address in Hash Table : 64 bits */
for (i = 0; i < mc_cnt; i++, mcptr = mcptr->next) {
hash_val = ether_crc_le(6, mcptr->dmi_addr) & 0x3f;
hash_table[hash_val / 16] |= (u16) 1 << (hash_val % 16);
}
/* Write the hash table to MAC MD table */
for (i = 0, oft = DM9000_MAR; i < 4; i++) {
iow(db, oft++, hash_table[i]);
iow(db, oft++, hash_table[i] >> 8);
}
iow(db, DM9000_RCR, rcr);
spin_unlock_irqrestore(&db->lock, flags);
}
/*
* Initilize dm9000 board
*/
static void
dm9000_init_dm9000(struct net_device *dev)
{
board_info_t *db = netdev_priv(dev);
unsigned int imr;
dm9000_dbg(db, 1, "entering %s\n", __func__);
/* I/O mode */
db->io_mode = ior(db, DM9000_ISR) >> 6; /* ISR bit7:6 keeps I/O mode */
/* GPIO0 on pre-activate PHY */
//V_R1 iow(db, DM9000_GPR, 0); /* REG_1F bit0 activate phyxcer */
iow(db, DM9000_GPCR, GPCR_GEP_CNTL); /* Let GPIO0 output */
iow(db, DM9000_GPR, 0); /* Enable PHY */
mdelay(20); //V_R2
dm9000_phy_write(dev, 0, 0, 0x8000); //V_R2 reset PHY
mdelay (20);
// if (db->flags & DM9000_PLATF_EXT_PHY)
// iow(db, DM9000_NCR, NCR_EXT_PHY);
/* Program operating register */
iow(db, DM9000_TCR, 0); /* TX Polling clear */
iow(db, DM9000_BPTR, 0x3f); /* Less 3Kb, 200us */
iow(db, DM9000_FCR, 0xff); /* Flow Control */
iow(db, DM9000_SMCR, 0); /* Special Mode */
/* clear TX status */
iow(db, DM9000_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END);
iow(db, DM9000_ISR, ISR_CLR_STATUS); /* Clear interrupt status */
/* Set address filter table */
dm9000_hash_table(dev);
imr = IMR_PAR | IMR_PTM | IMR_PRM;
if (db->type != TYPE_DM9000E)
imr |= IMR_LNKCHNG;
db->imr_all = imr;
/* Enable TX/RX interrupt mask */
iow(db, DM9000_IMR, imr);
/* Init Driver variable */
db->tx_pkt_cnt = 0;
db->queue_pkt_len = 0;
dev->trans_start = 0;
dm9000_phy_write(dev, 0, 27, 0xE100); //V_R1
}
/* Our watchdog timed out. Called by the networking layer */
static void dm9000_timeout(struct net_device *dev)
{
board_info_t *db = netdev_priv(dev);
u8 reg_save;
unsigned long flags;
/* Save previous register address */
reg_save = readb(db->io_addr);
spin_lock_irqsave(&db->lock, flags);
netif_stop_queue(dev);
printk(KERN_INFO "[%s Ethernet Driver, V%s]: Timeout!!\n", CARDNAME, DRV_VERSION); //JJ1
dm9000_reset(db);
dm9000_init_dm9000(dev);
/* We can accept TX packets again */
dev->trans_start = jiffies;
netif_wake_queue(dev);
/* Restore previous register address */
writeb(reg_save, db->io_addr);
spin_unlock_irqrestore(&db->lock, flags);
}
/*
* Hardware start transmission.
* Send a packet to media from the upper layer.
*/
static int
dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
unsigned long flags;
board_info_t *db = netdev_priv(dev);
dm9000_dbg(db, 3, "%s:\n", __func__);
if (db->tx_pkt_cnt > 1)
return 1;
spin_lock_irqsave(&db->lock, flags);
/* Move data to DM9000 TX RAM */
writeb(DM9000_MWCMD, db->io_addr);
(db->outblk)(db->io_data, skb->data, skb->len);
dev->stats.tx_bytes += skb->len;
db->tx_pkt_cnt++;
/* TX control: First packet immediately send, second packet queue */
if (db->tx_pkt_cnt == 1) {
/* Set TX length to DM9000 */
iow(db, DM9000_TXPLL, skb->len);
iow(db, DM9000_TXPLH, skb->len >> 8);
/* Issue TX polling command */
iow(db, DM9000_TCR, TCR_TXREQ); /* Cleared after TX complete */
dev->trans_start = jiffies; /* save the time stamp */
} else {
/* Second packet */
db->queue_pkt_len = skb->len;
netif_stop_queue(dev);
}
spin_unlock_irqrestore(&db->lock, flags);
/* free this SKB */
dev_kfree_skb(skb);
return 0;
}
/*
* DM9000 interrupt handler
* receive the packet to upper layer, free the transmitted packet
*/
static void dm9000_tx_done(struct net_device *dev, board_info_t *db)
{
int tx_status = ior(db, DM9000_NSR); /* Got TX status */
if (tx_status & (NSR_TX2END | NSR_TX1END)) {
/* One packet sent complete */
db->tx_pkt_cnt--;
dev->stats.tx_packets++;
if (netif_msg_tx_done(db))
dev_dbg(db->dev, "tx done, NSR %02x\n", tx_status);
/* Queue packet check & send */
if (db->tx_pkt_cnt > 0) {
iow(db, DM9000_TXPLL, db->queue_pkt_len);
iow(db, DM9000_TXPLH, db->queue_pkt_len >> 8);
iow(db, DM9000_TCR, TCR_TXREQ);
dev->trans_start = jiffies;
}
netif_wake_queue(dev);
}
}
struct dm9000_rxhdr {
u8 RxPktReady;
u8 RxStatus;
__le16 RxLen;
} __attribute__((__packed__));
/*
* Received a packet and pass to upper layer
*/
static void
dm9000_rx(struct net_device *dev)
{
board_info_t *db = netdev_priv(dev);
struct dm9000_rxhdr rxhdr;
struct sk_buff *skb;
u8 rxbyte, *rdptr;
bool GoodPacket;
int RxLen;
/* Check packet ready or not */
do {
ior(db, DM9000_MRCMDX); /* Dummy read */
/* Get most updated data */
rxbyte = readb(db->io_data);
/* Status check: this byte must be 0 or 1 */
if (rxbyte > DM9000_PKT_RDY) {
dev_warn(db->dev, "status check fail: %d\n", rxbyte);
iow(db, DM9000_RCR, 0x00); /* Stop Device */
iow(db, DM9000_ISR, IMR_PAR); /* Stop INT request */
return;
}
if (rxbyte != DM9000_PKT_RDY)
return;
/* A packet ready now & Get status/length */
GoodPacket = true;
writeb(DM9000_MRCMD, db->io_addr);
(db->inblk)(db->io_data, &rxhdr, sizeof(rxhdr));
RxLen = le16_to_cpu(rxhdr.RxLen);
if (netif_msg_rx_status(db))
dev_dbg(db->dev, "RX: status %02x, length %04x\n",
rxhdr.RxStatus, RxLen);
/* Packet Status check */
if (RxLen < 0x40) {
GoodPacket = false;
if (netif_msg_rx_err(db))
dev_dbg(db->dev, "RX: Bad Packet (runt)\n");
}
if (RxLen > DM9000_PKT_MAX) {
dev_dbg(db->dev, "RST: RX Len:%x\n", RxLen);
}
/* rxhdr.RxStatus is identical to RSR register. */
if (rxhdr.RxStatus & (RSR_FOE | RSR_CE | RSR_AE |
RSR_PLE | RSR_RWTO |
RSR_LCS | RSR_RF)) {
GoodPacket = false;
if (rxhdr.RxStatus & RSR_FOE) {
if (netif_msg_rx_err(db))
dev_dbg(db->dev, "fifo error\n");
dev->stats.rx_fifo_errors++;
printk(KERN_INFO "[%s Ethernet Driver, V%s]: FIFO Over Flow!!\n", CARDNAME, DRV_VERSION); //JJ1
}
if (rxhdr.RxStatus & RSR_CE) {
if (netif_msg_rx_err(db))
dev_dbg(db->dev, "crc error\n");
dev->stats.rx_crc_errors++;
}
if (rxhdr.RxStatus & RSR_RF) {
if (netif_msg_rx_err(db))
dev_dbg(db->dev, "length error\n");
dev->stats.rx_length_errors++;
}
}
/* Move data from DM9000 */
if (GoodPacket
&& ((skb = dev_alloc_skb(RxLen + 4)) != NULL)) {
skb_reserve(skb, 2);
rdptr = (u8 *) skb_put(skb, RxLen - 4);
/* Read received packet from RX SRAM */
(db->inblk)(db->io_data, rdptr, RxLen);
dev->stats.rx_bytes += RxLen;
/* Pass to upper layer */
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
dev->stats.rx_packets++;
} else {
/* need to dump the packet's data */
(db->dumpblk)(db->io_data, RxLen);
}
} while (rxbyte == DM9000_PKT_RDY);
}
static irqreturn_t dm9000_interrupt(int irq, void *dev_id)
{
struct net_device *dev = dev_id;
board_info_t *db = netdev_priv(dev);
int int_status;
unsigned long flags;
u8 reg_save;
dm9000_dbg(db, 3, "entering %s\n", __func__);
/* A real interrupt coming */
/* holders of db->lock must always block IRQs */
spin_lock_irqsave(&db->lock, flags);
/* Save previous register address */
reg_save = readb(db->io_addr);
/* Disable all interrupts */
iow(db, DM9000_IMR, IMR_PAR);
/* Got DM9000 interrupt status */
int_status = ior(db, DM9000_ISR); /* Got ISR */
iow(db, DM9000_ISR, int_status); /* Clear ISR status */
if (netif_msg_intr(db))
dev_dbg(db->dev, "interrupt status %02x\n", int_status);
/* Received the coming packet */
if (int_status & ISR_PRS)
dm9000_rx(dev);
/* Trnasmit Interrupt check */
if (int_status & ISR_PTS)
dm9000_tx_done(dev, db);
if (db->type != TYPE_DM9000E) {
if (int_status & ISR_LNKCHNG) {
/* fire a link-change request */
schedule_delayed_work(&db->phy_poll, 1);
}
}
/* Re-enable interrupt mask */
iow(db, DM9000_IMR, db->imr_all);
/* Restore previous register address */
writeb(reg_save, db->io_addr);
spin_unlock_irqrestore(&db->lock, flags);
return IRQ_HANDLED;
}
#ifdef CONFIG_NET_POLL_CONTROLLER
/*
*Used by netconsole
*/
static void dm9000_poll_controller(struct net_device *dev)
{
disable_irq(dev->irq);
dm9000_interrupt(dev->irq, dev);
enable_irq(dev->irq);
}
#endif
/*
* Open the interface.
* The interface is opened whenever "ifconfig" actives it.
*/
static int
dm9000_open(struct net_device *dev)
{
board_info_t *db = netdev_priv(dev);
unsigned long irqflags = db->irq_res->flags & IRQF_TRIGGER_MASK;
if (netif_msg_ifup(db))
dev_dbg(db->dev, "enabling %s\n", dev->name);
/* If there is no IRQ type specified, default to something that
* may work, and tell the user that this is a problem */
if (irqflags == IRQF_TRIGGER_NONE)
dev_warn(db->dev, "WARNING: no IRQ resource flags set.\n");
irqflags |= IRQF_SHARED;
if (request_irq(dev->irq, &dm9000_interrupt, irqflags, dev->name, dev))
return -EAGAIN;
/* Initialize DM9000 board */
dm9000_reset(db);
dm9000_init_dm9000(dev);
/* Init driver variable */
db->dbug_cnt = 0;
mii_check_media(&db->mii, netif_msg_link(db), 1);
netif_start_queue(dev);
dm9000_schedule_poll(db);
return 0;
}
/*
* Sleep, either by using msleep() or if we are suspending, then
* use mdelay() to sleep.
*/
static void dm9000_msleep(board_info_t *db, unsigned int ms)
{
if (db->in_suspend)
mdelay(ms);
else
msleep(ms);
}
/*
* Read a word from phyxcer
*/
static int
dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg)
{
board_info_t *db = netdev_priv(dev);
unsigned long flags;
unsigned int reg_save;
int ret;
mutex_lock(&db->addr_lock);
spin_lock_irqsave(&db->lock,flags);
/* Save previous register address */
reg_save = readb(db->io_addr);
/* Fill the phyxcer register into REG_0C */
iow(db, DM9000_EPAR, DM9000_PHY | reg);
iow(db, DM9000_EPCR, EPCR_ERPRR | EPCR_EPOS); /* Issue phyxcer read command */
writeb(reg_save, db->io_addr);
spin_unlock_irqrestore(&db->lock,flags);
dm9000_msleep(db, 1); /* Wait read complete */
spin_lock_irqsave(&db->lock,flags);
reg_save = readb(db->io_addr);
iow(db, DM9000_EPCR, 0x0); /* Clear phyxcer read command */
/* The read data keeps on REG_0D & REG_0E */
ret = (ior(db, DM9000_EPDRH) << 8) | ior(db, DM9000_EPDRL);
/* restore the previous address */
writeb(reg_save, db->io_addr);
spin_unlock_irqrestore(&db->lock,flags);
mutex_unlock(&db->addr_lock);
dm9000_dbg(db, 5, "phy_read[%02x] -> %04x\n", reg, ret);
return ret;
}
/*
* Write a word to phyxcer
*/
static void
dm9000_phy_write(struct net_device *dev,
int phyaddr_unused, int reg, int value)
{
board_info_t *db = netdev_priv(dev);
unsigned long flags;
unsigned long reg_save;
dm9000_dbg(db, 5, "phy_write[%02x] = %04x\n", reg, value);
mutex_lock(&db->addr_lock);
spin_lock_irqsave(&db->lock,flags);
/* Save previous register address */
reg_save = readb(db->io_addr);
/* Fill the phyxcer register into REG_0C */
iow(db, DM9000_EPAR, DM9000_PHY | reg);
/* Fill the written data into REG_0D & REG_0E */
iow(db, DM9000_EPDRL, value);
iow(db, DM9000_EPDRH, value >> 8);
iow(db, DM9000_EPCR, EPCR_EPOS | EPCR_ERPRW); /* Issue phyxcer write command */
writeb(reg_save, db->io_addr);
spin_unlock_irqrestore(&db->lock, flags);
dm9000_msleep(db, 1); /* Wait write complete */
spin_lock_irqsave(&db->lock,flags);
reg_save = readb(db->io_addr);
iow(db, DM9000_EPCR, 0x0); /* Clear phyxcer write command */
/* restore the previous address */
writeb(reg_save, db->io_addr);
spin_unlock_irqrestore(&db->lock, flags);
mutex_unlock(&db->addr_lock);
}
static void
dm9000_shutdown(struct net_device *dev)
{
board_info_t *db = netdev_priv(dev);
/* RESET device */
dm9000_phy_write(dev, 0, MII_BMCR, BMCR_RESET); /* PHY RESET */
//V_R1 iow(db, DM9000_GPR, 0x01); /* Power-Down PHY */
iow(db, DM9000_IMR, IMR_PAR); /* Disable all interrupt */
iow(db, DM9000_RCR, 0x00); /* Disable RX */
}
/*
* Stop the interface.
* The interface is stopped when it is brought.
*/
static int
dm9000_stop(struct net_device *ndev)
{
board_info_t *db = netdev_priv(ndev);
if (netif_msg_ifdown(db))
dev_dbg(db->dev, "shutting down %s\n", ndev->name);
cancel_delayed_work_sync(&db->phy_poll);
netif_stop_queue(ndev);
netif_carrier_off(ndev);
/* free interrupt */
free_irq(ndev->irq, ndev);
dm9000_shutdown(ndev);
return 0;
}
#define res_size(_r) (((_r)->end - (_r)->start) + 1)
static const struct net_device_ops dm9000_netdev_ops = {
.ndo_open = dm9000_open,
.ndo_stop = dm9000_stop,
.ndo_start_xmit = dm9000_start_xmit,
.ndo_tx_timeout = dm9000_timeout,
.ndo_set_multicast_list = dm9000_hash_table,
.ndo_do_ioctl = dm9000_ioctl,
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = dm9000_poll_controller,
#endif
};
/*
* Search DM9000 board, allocate space and register it
*/
static int __devinit
dm9000_probe(struct platform_device *pdev)
{
struct dm9000_plat_data *pdata = pdev->dev.platform_data;
struct board_info *db; /* Point a board information structure */
struct net_device *ndev;
const unsigned char *mac_src;
int ret = 0;
int iosize;
int i;
u32 id_val;
/* Init network device */
ndev = alloc_etherdev(sizeof(struct board_info));
if (!ndev) {
dev_err(&pdev->dev, "could not allocate device.\n");
return -ENOMEM;
}
SET_NETDEV_DEV(ndev, &pdev->dev);
dev_dbg(&pdev->dev, "dm9000_probe()\n");
ndev->netdev_ops = &dm9000_netdev_ops;
/* setup board info structure */
db = netdev_priv(ndev);
memset(db, 0, sizeof(*db));
db->dev = &pdev->dev;
db->ndev = ndev;
spin_lock_init(&db->lock);
mutex_init(&db->addr_lock);
INIT_DELAYED_WORK(&db->phy_poll, dm9000_poll_work);
db->addr_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
db->data_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
db->irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (db->addr_res == NULL || db->data_res == NULL ||
db->irq_res == NULL) {
dev_err(db->dev, "insufficient resources\n");
ret = -ENOENT;
goto out;
}
iosize = res_size(db->addr_res);
db->addr_req = request_mem_region(db->addr_res->start, iosize,
pdev->name);
if (db->addr_req == NULL) {
dev_err(db->dev, "cannot claim address reg area\n");
ret = -EIO;
goto out;
}
db->io_addr = ioremap(db->addr_res->start, iosize);
if (db->io_addr == NULL) {
dev_err(db->dev, "failed to ioremap address reg\n");
ret = -EINVAL;
goto out;
}
iosize = res_size(db->data_res);
db->data_req = request_mem_region(db->data_res->start, iosize,
pdev->name);
if (db->data_req == NULL) {
dev_err(db->dev, "cannot claim data reg area\n");
ret = -EIO;
goto out;
}
db->io_data = ioremap(db->data_res->start, iosize);
if (db->io_data == NULL) {
dev_err(db->dev, "failed to ioremap data reg\n");
ret = -EINVAL;
goto out;
}
/* fill in parameters for net-dev structure */
ndev->base_addr = (unsigned long)db->io_addr;
ndev->irq = db->irq_res->start;
//Stone add
printk("[dm9] %s ndev->irq=%x \n",__func__,ndev->irq);
/* ensure at least we have a default set of IO routines */
dm9000_set_io(db, iosize);
/* check to see if anything is being over-ridden */
if (pdata != NULL) {
/* check to see if the driver wants to over-ride the
* default IO width */
if (pdata->flags & DM9000_PLATF_8BITONLY)
dm9000_set_io(db, 1);
if (pdata->flags & DM9000_PLATF_16BITONLY)
dm9000_set_io(db, 2);
if (pdata->flags & DM9000_PLATF_32BITONLY)
dm9000_set_io(db, 4);
/* check to see if there are any IO routine
* over-rides */
if (pdata->inblk != NULL)
db->inblk = pdata->inblk;
if (pdata->outblk != NULL)
db->outblk = pdata->outblk;
if (pdata->dumpblk != NULL)
db->dumpblk = pdata->dumpblk;
db->flags = pdata->flags;
}
#ifdef CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL
db->flags |= DM9000_PLATF_SIMPLE_PHY;
#endif
//Stone add
// dm9000_reset(db);
iow(db, DM9000_NCR, 0x03);
/* try multiple times, DM9000 sometimes gets the read wrong */
for (i = 0; i < 8; i++) {
id_val = ior(db, DM9000_VIDL);
id_val |= (u32)ior(db, DM9000_VIDH) << 8;
id_val |= (u32)ior(db, DM9000_PIDL) << 16;
id_val |= (u32)ior(db, DM9000_PIDH) << 24;
printk("[dm9].%d read id 0x%08x\n", i+1, id_val);
if (id_val == DM9000_ID)
break;
dev_err(db->dev, "read wrong id 0x%08x\n", id_val);
}
printk(KERN_INFO "[%s Ethernet Driver, V%s]: KV= %d.%d.%d !!\n", CARDNAME, DRV_VERSION, //JJ1
(LINUX_VERSION_CODE>>16 & 0xff),
(LINUX_VERSION_CODE>>8 & 0xff),
(LINUX_VERSION_CODE & 0xff) ); //#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
printk(KERN_INFO "[%s Ethernet Driver, V%s]: ChipID= 0x%x !!\n", CARDNAME, DRV_VERSION, id_val ); // JJ1
if (id_val != DM9000_ID) {
dev_err(db->dev, "wrong id: 0x%08x\n", id_val);
ret = -ENODEV;
goto out;
}
/* Identify what type of DM9000 we are working on */
id_val = ior(db, DM9000_CHIPR);
dev_dbg(db->dev, "dm9000 revision 0x%02x\n", id_val);
printk(KERN_INFO "[DM9000]dm9000 revision 0x%02x\n", id_val); //V_R1
switch (id_val) {
case CHIPR_DM9000A:
db->type = TYPE_DM9000A;
break;
case CHIPR_DM9000B:
db->type = TYPE_DM9000B;
break;
default:
dev_dbg(db->dev, "ID %02x => defaulting to DM9000E\n", id_val);
db->type = TYPE_DM9000E;
}
/* from this point we assume that we have found a DM9000 */
/* driver system function */
ether_setup(ndev);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31)
ndev->netdev_ops = &dm9000_netdev_ops; // new kernel 2.6.31
ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
ndev->ethtool_ops = &dm9000_ethtool_ops;
#else
ndev->open = &dm9000_open;
ndev->hard_start_xmit = &dm9000_start_xmit;
ndev->tx_timeout = &dm9000_timeout;
ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
ndev->stop = &dm9000_stop;
ndev->set_multicast_list = &dm9000_hash_table;
ndev->ethtool_ops = &dm9000_ethtool_ops;
ndev->do_ioctl = &dm9000_ioctl;
#endif
#ifdef CONFIG_NET_POLL_CONTROLLER
ndev->poll_controller = &dm9000_poll_controller;
#endif
db->msg_enable = NETIF_MSG_LINK;
db->mii.phy_id_mask = 0x1f;
db->mii.reg_num_mask = 0x1f;
db->mii.force_media = 0;
db->mii.full_duplex = 0;
db->mii.dev = ndev;
db->mii.mdio_read = dm9000_phy_read;
db->mii.mdio_write = dm9000_phy_write;
mac_src = "eeprom";
/* try reading the node address from the attached EEPROM */
for (i = 0; i < 6; i += 2)
dm9000_read_eeprom(db, i / 2, ndev->dev_addr+i);
if (!is_valid_ether_addr(ndev->dev_addr) && pdata != NULL) {
mac_src = "platform data";
memcpy(ndev->dev_addr, pdata->dev_addr, 6);
}
if (!is_valid_ether_addr(ndev->dev_addr)) {
/* try reading from mac */
mac_src = "chip";
static unsigned char mac_addr[6] = {0x00,0x11,0x22,0x33,0x44,0x55};
static unsigned char mac_tmp[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
for (i = 0; i < 6; i++)
ndev->dev_addr[i] = ior(db, i+DM9000_PAR);
// Mark Chang 20100521
// -------------------
if (!memcmp(ndev->dev_addr, mac_tmp, 6))
memcpy(ndev->dev_addr, mac_addr, 6);
}
if (!is_valid_ether_addr(ndev->dev_addr))
dev_warn(db->dev, "%s: Invalid ethernet MAC address. Please "
"set using ifconfig\n", ndev->name);
platform_set_drvdata(pdev, ndev);
ret = register_netdev(ndev);
if (ret == 0)
printk(KERN_INFO "%s: dm9000%c at %p,%p IRQ %d MAC: %pM (%s)\n",
ndev->name, dm9000_type_to_char(db->type),
db->io_addr, db->io_data, ndev->irq,
ndev->dev_addr, mac_src);
return 0;
out:
dev_err(db->dev, "not found (%d).\n", ret);
dm9000_release_board(pdev, db);
free_netdev(ndev);
return ret;
}
static int
dm9000_drv_suspend(struct platform_device *dev, pm_message_t state)
{
struct net_device *ndev = platform_get_drvdata(dev);
board_info_t *db;
if (ndev) {
db = netdev_priv(ndev);
db->in_suspend = 1;
if (netif_running(ndev)) {
netif_device_detach(ndev);
dm9000_shutdown(ndev);
}
}
return 0;
}
static int
dm9000_drv_resume(struct platform_device *dev)
{
struct net_device *ndev = platform_get_drvdata(dev);
board_info_t *db = netdev_priv(ndev);
if (ndev) {
if (netif_running(ndev)) {
dm9000_reset(db);
dm9000_init_dm9000(ndev);
netif_device_attach(ndev);
}
db->in_suspend = 0;
}
return 0;
}
static int __devexit
dm9000_drv_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
platform_set_drvdata(pdev, NULL);
unregister_netdev(ndev);
dm9000_release_board(pdev, (board_info_t *) netdev_priv(ndev));
free_netdev(ndev); /* free device structure */
dev_dbg(&pdev->dev, "released and freed device\n");
return 0;
}
static struct platform_driver dm9000_driver = {
.driver = {
.name = "dm9000",
.owner = THIS_MODULE,
},
.probe = dm9000_probe,
.remove = __devexit_p(dm9000_drv_remove),
.suspend = dm9000_drv_suspend,
.resume = dm9000_drv_resume,
};
static int __init
dm9000_init(void)
{
printk(KERN_INFO "%s Ethernet Driver, V%s\n", CARDNAME, DRV_VERSION);
return platform_driver_register(&dm9000_driver);
}
static void __exit
dm9000_cleanup(void)
{
platform_driver_unregister(&dm9000_driver);
}
module_init(dm9000_init);
module_exit(dm9000_cleanup);
MODULE_AUTHOR("Sascha Hauer, Ben Dooks");
MODULE_DESCRIPTION("Davicom DM9000 network driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:dm9000");
[-- Attachment #3: dm9000_KT2.6.31.h --]
[-- Type: text/plain, Size: 4180 bytes --]
/*
* dm9000 Ethernet
*/
#ifndef _DM9000X_H_
#define _DM9000X_H_
#define DM9000_ID 0x90000A46
/* although the registers are 16 bit, they are 32-bit aligned.
*/
#define DM9000_NCR 0x00
#define DM9000_NSR 0x01
#define DM9000_TCR 0x02
#define DM9000_TSR1 0x03
#define DM9000_TSR2 0x04
#define DM9000_RCR 0x05
#define DM9000_RSR 0x06
#define DM9000_ROCR 0x07
#define DM9000_BPTR 0x08
#define DM9000_FCTR 0x09
#define DM9000_FCR 0x0A
#define DM9000_EPCR 0x0B
#define DM9000_EPAR 0x0C
#define DM9000_EPDRL 0x0D
#define DM9000_EPDRH 0x0E
#define DM9000_WCR 0x0F
#define DM9000_PAR 0x10
#define DM9000_MAR 0x16
#define DM9000_GPCR 0x1e
#define DM9000_GPR 0x1f
#define DM9000_TRPAL 0x22
#define DM9000_TRPAH 0x23
#define DM9000_RWPAL 0x24
#define DM9000_RWPAH 0x25
#define DM9000_VIDL 0x28
#define DM9000_VIDH 0x29
#define DM9000_PIDL 0x2A
#define DM9000_PIDH 0x2B
#define DM9000_CHIPR 0x2C
#define DM9000_SMCR 0x2F
#define CHIPR_DM9000A 0x19
#define CHIPR_DM9000B 0x1A //V_R1 0x1B
#define DM9000_MRCMDX 0xF0
#define DM9000_MRCMD 0xF2
#define DM9000_MRRL 0xF4
#define DM9000_MRRH 0xF5
#define DM9000_MWCMDX 0xF6
#define DM9000_MWCMD 0xF8
#define DM9000_MWRL 0xFA
#define DM9000_MWRH 0xFB
#define DM9000_TXPLL 0xFC
#define DM9000_TXPLH 0xFD
#define DM9000_ISR 0xFE
#define DM9000_IMR 0xFF
#define NCR_EXT_PHY (1<<7)
#define NCR_WAKEEN (1<<6)
#define NCR_FCOL (1<<4)
#define NCR_FDX (1<<3)
#define NCR_LBK (3<<1)
#define NCR_RST (1<<0)
#define NSR_SPEED (1<<7)
#define NSR_LINKST (1<<6)
#define NSR_WAKEST (1<<5)
#define NSR_TX2END (1<<3)
#define NSR_TX1END (1<<2)
#define NSR_RXOV (1<<1)
#define TCR_TJDIS (1<<6)
#define TCR_EXCECM (1<<5)
#define TCR_PAD_DIS2 (1<<4)
#define TCR_CRC_DIS2 (1<<3)
#define TCR_PAD_DIS1 (1<<2)
#define TCR_CRC_DIS1 (1<<1)
#define TCR_TXREQ (1<<0)
#define TSR_TJTO (1<<7)
#define TSR_LC (1<<6)
#define TSR_NC (1<<5)
#define TSR_LCOL (1<<4)
#define TSR_COL (1<<3)
#define TSR_EC (1<<2)
#define RCR_WTDIS (1<<6)
#define RCR_DIS_LONG (1<<5)
#define RCR_DIS_CRC (1<<4)
#define RCR_ALL (1<<3)
#define RCR_RUNT (1<<2)
#define RCR_PRMSC (1<<1)
#define RCR_RXEN (1<<0)
#define RSR_RF (1<<7)
#define RSR_MF (1<<6)
#define RSR_LCS (1<<5)
#define RSR_RWTO (1<<4)
#define RSR_PLE (1<<3)
#define RSR_AE (1<<2)
#define RSR_CE (1<<1)
#define RSR_FOE (1<<0)
#define FCTR_HWOT(ot) (( ot & 0xf ) << 4 )
#define FCTR_LWOT(ot) ( ot & 0xf )
#define IMR_PAR (1<<7)
#define IMR_ROOM (1<<3)
#define IMR_ROM (1<<2)
#define IMR_PTM (1<<1)
#define IMR_PRM (1<<0)
#define ISR_ROOS (1<<3)
#define ISR_ROS (1<<2)
#define ISR_PTS (1<<1)
#define ISR_PRS (1<<0)
#define ISR_CLR_STATUS (ISR_ROOS | ISR_ROS | ISR_PTS | ISR_PRS)
#define EPCR_REEP (1<<5)
#define EPCR_WEP (1<<4)
#define EPCR_EPOS (1<<3)
#define EPCR_ERPRR (1<<2)
#define EPCR_ERPRW (1<<1)
#define EPCR_ERRE (1<<0)
#define GPCR_GEP_CNTL (1<<0)
#define DM9000_PKT_RDY 0x01 /* Packet ready to receive */
#define DM9000_PKT_MAX 1536 /* Received packet max size */
/* DM9000A / DM9000B definitions */
#define IMR_LNKCHNG (1<<5)
#define IMR_UNDERRUN (1<<4)
#define ISR_LNKCHNG (1<<5)
#define ISR_UNDERRUN (1<<4)
#endif /* _DM9000X_H_ */
^ permalink raw reply
* [PATCH net-next v1] net: use a per task frag allocator
From: Eric Dumazet @ 2012-09-19 16:56 UTC (permalink / raw)
To: David Miller; +Cc: linux-kernel, netdev
From: Eric Dumazet <edumazet@google.com>
We currently use a per socket page reserve for tcp_sendmsg() operations.
This page is used to build fragments for skbs.
Its done to increase probability of coalescing small write() into
single segments in skbs still in write queue (not yet sent)
But it wastes a lot of memory for applications handling many mostly
idle sockets, since each socket holds one page in sk->sk_sndmsg_page
Its also quite inefficient to build TSO packets of 64KB, because we need
about 16 pages per skb on arches where PAGE_SIZE = 4096, so we hit
page allocator more than wanted.
This patch switches this frag allocator from socket to task structure,
and uses bigger pages.
(up to 32768 bytes per frag, thats order-3 pages on x86)
This increases TCP stream performance by 20% on loopback device,
but also benefits on other network devices, since 8x less frags are
mapped on transmit and unmapped on tx completion.
Its possible some TSO enabled hardware cant cope with bigger fragments,
but their ndo_start_xmit() should already handle this, splitting a
fragment in sub fragments, since some arches have PAGE_SIZE=65536
Successfully tested on various ethernet devices.
(ixgbe, igb, bnx2x, tg3, mellanox mlx4)
Followup patches can use this infrastructure in two other spots
and get rid of the socket sk_sndmsg_page.
Open for discussion : Should we fallback to smaller pages
if order-3 page allocations fail ?
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
include/linux/sched.h | 6 ++++++
include/net/sock.h | 12 +++++++++---
kernel/exit.c | 3 +++
kernel/fork.c | 1 +
net/ipv4/tcp.c | 34 +++++++++++++++++-----------------
net/ipv4/tcp_ipv4.c | 4 +---
6 files changed, 37 insertions(+), 23 deletions(-)
diff --git a/include/linux/sched.h b/include/linux/sched.h
index b8c8664..ad61100 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1530,6 +1530,12 @@ struct task_struct {
* cache last used pipe for splice
*/
struct pipe_inode_info *splice_pipe;
+ /*
+ * cache for page frag allocator
+ */
+ struct page *sndmsg_page;
+ unsigned int sndmsg_off;
+
#ifdef CONFIG_TASK_DELAY_ACCT
struct task_delay_info *delays;
#endif
diff --git a/include/net/sock.h b/include/net/sock.h
index 181b711..431122c 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -247,8 +247,8 @@ struct cg_proto;
* @sk_stamp: time stamp of last packet received
* @sk_socket: Identd and reporting IO signals
* @sk_user_data: RPC layer private data
- * @sk_sndmsg_page: cached page for sendmsg
- * @sk_sndmsg_off: cached offset for sendmsg
+ * @sk_sndmsg_page: cached page for splice/ip6_append_data()
+ * @sk_sndmsg_off: cached offset for splice/ip6_append_data()
* @sk_peek_off: current peek_offset value
* @sk_send_head: front of stuff to transmit
* @sk_security: used by security modules
@@ -2034,11 +2034,17 @@ static inline void sk_stream_moderate_sndbuf(struct sock *sk)
struct sk_buff *sk_stream_alloc_skb(struct sock *sk, int size, gfp_t gfp);
+/* On 32bit arches, an skb frag is limited to 2^15, because
+ * (struct skb_frag_struct)->size/offset are u16
+ */
+#define SNDMSG_PAGE_ORDER min(get_order(32768), PAGE_ALLOC_COSTLY_ORDER)
+#define SNDMSG_PAGE_SIZE (PAGE_SIZE << SNDMSG_PAGE_ORDER)
+
static inline struct page *sk_stream_alloc_page(struct sock *sk)
{
struct page *page = NULL;
- page = alloc_pages(sk->sk_allocation, 0);
+ page = alloc_pages(sk->sk_allocation | __GFP_COMP, SNDMSG_PAGE_ORDER);
if (!page) {
sk_enter_memory_pressure(sk);
sk_stream_moderate_sndbuf(sk);
diff --git a/kernel/exit.c b/kernel/exit.c
index f65345f..487b81a 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -1046,6 +1046,9 @@ void do_exit(long code)
if (tsk->splice_pipe)
__free_pipe_info(tsk->splice_pipe);
+ if (tsk->sndmsg_page)
+ put_page(tsk->sndmsg_page);
+
validate_creds_for_do_exit(tsk);
preempt_disable();
diff --git a/kernel/fork.c b/kernel/fork.c
index 2c8857e..60b58af 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -330,6 +330,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
tsk->btrace_seq = 0;
#endif
tsk->splice_pipe = NULL;
+ tsk->sndmsg_page = NULL;
account_kernel_stack(ti, 1);
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index df83d74..7942d82 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -1152,16 +1152,16 @@ new_segment:
} else {
bool merge = false;
int i = skb_shinfo(skb)->nr_frags;
- struct page *page = sk->sk_sndmsg_page;
+ struct page *page = current->sndmsg_page;
int off;
if (page && page_count(page) == 1)
- sk->sk_sndmsg_off = 0;
+ current->sndmsg_off = 0;
- off = sk->sk_sndmsg_off;
+ off = current->sndmsg_off;
if (skb_can_coalesce(skb, i, page, off) &&
- off != PAGE_SIZE) {
+ off != SNDMSG_PAGE_SIZE) {
/* We can extend the last page
* fragment. */
merge = true;
@@ -1173,16 +1173,16 @@ new_segment:
tcp_mark_push(tp, skb);
goto new_segment;
} else if (page) {
- if (off == PAGE_SIZE) {
+ if (off == SNDMSG_PAGE_SIZE) {
put_page(page);
- sk->sk_sndmsg_page = page = NULL;
+ current->sndmsg_page = page = NULL;
off = 0;
}
} else
off = 0;
- if (copy > PAGE_SIZE - off)
- copy = PAGE_SIZE - off;
+ if (copy > SNDMSG_PAGE_SIZE - off)
+ copy = SNDMSG_PAGE_SIZE - off;
if (!sk_wmem_schedule(sk, copy))
goto wait_for_memory;
@@ -1198,12 +1198,12 @@ new_segment:
err = skb_copy_to_page_nocache(sk, from, skb,
page, off, copy);
if (err) {
- /* If this page was new, give it to the
- * socket so it does not get leaked.
+ /* If this page was new, remember it
+ * so it does not get leaked.
*/
- if (!sk->sk_sndmsg_page) {
- sk->sk_sndmsg_page = page;
- sk->sk_sndmsg_off = 0;
+ if (!current->sndmsg_page) {
+ current->sndmsg_page = page;
+ current->sndmsg_off = 0;
}
goto do_error;
}
@@ -1213,15 +1213,15 @@ new_segment:
skb_frag_size_add(&skb_shinfo(skb)->frags[i - 1], copy);
} else {
skb_fill_page_desc(skb, i, page, off, copy);
- if (sk->sk_sndmsg_page) {
+ if (current->sndmsg_page) {
get_page(page);
- } else if (off + copy < PAGE_SIZE) {
+ } else if (off + copy < SNDMSG_PAGE_SIZE) {
get_page(page);
- sk->sk_sndmsg_page = page;
+ current->sndmsg_page = page;
}
}
- sk->sk_sndmsg_off = off + copy;
+ current->sndmsg_off = off + copy;
}
if (!copied)
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index e64abed..e457d65 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -2196,9 +2196,7 @@ void tcp_v4_destroy_sock(struct sock *sk)
if (inet_csk(sk)->icsk_bind_hash)
inet_put_port(sk);
- /*
- * If sendmsg cached page exists, toss it.
- */
+ /* If cached page exists, toss it. */
if (sk->sk_sndmsg_page) {
__free_page(sk->sk_sndmsg_page);
sk->sk_sndmsg_page = NULL;
^ permalink raw reply related
* Re: HTB vs CoDel performance
From: Rick Jones @ 2012-09-19 17:00 UTC (permalink / raw)
To: Lin Ming; +Cc: Eric Dumazet, networking
In-Reply-To: <CAF1ivSYQiXBOtzZdDUKEqWWsW5cgLgSkLs88Dvkppb02yN6wTg@mail.gmail.com>
On 09/18/2012 06:26 PM, Lin Ming wrote:
> On Tue, Sep 18, 2012 at 6:15 PM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
>> Are you really cpu limited ? You might hit some clocks artifacts.
>
> Did you mean the cpu speed? It's an ARMv5 processor.
> BogoMIPS : 1196.03
At the risk of typing into Eric's keyboard, he was asking if you were
saturating the CPU - was it getting to 100% utilization, that sort of thing.
>> rate limiting to 1Gbps probably need high resolution timers.
>
> High resolution timer is enabled.
When you are running your tests, what sort of CPU utilization do you see
on the CPU of your router with HTB on vs off. Some "quick and dirty"
netperf tests on an Centrino-based laptop suggested that as an end
system at least, HTB at 1 GbE (using your tc commands) increases service
demand (what netperf calculates as CPU consumed per unit of work
performed) ~15% for bulk transfer (netperf TCP_STREAM) and ~18% for
small packet request/response (TCP_RR).
rick jones
^ permalink raw reply
* [PATCH] USB: remove dbg() usage in USB networking drivers
From: Greg Kroah-Hartman @ 2012-09-19 17:13 UTC (permalink / raw)
To: netdev-u79uwXL29TY76Z2rM5mHXA
Cc: linux-usb-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
From: Greg Kroah-Hartman <gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org>
The dbg() USB macro is so old, it predates me. The USB networking drivers are
the last hold-out using this macro, and we want to get rid of it, so replace
the usage of it with the proper netdev_dbg() or dev_dbg() (depending on the
context) calls.
Signed-off-by: Greg Kroah-Hartman <gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org>
---
drivers/net/usb/asix_devices.c | 36 ++++++-----
drivers/net/usb/catc.c | 55 +++++++++-------
drivers/net/usb/gl620a.c | 10 ++-
drivers/net/usb/kaweth.c | 134 ++++++++++++++++++++---------------------
drivers/net/usb/net1080.c | 46 +++++++-------
drivers/net/usb/rtl8150.c | 6 -
6 files changed, 152 insertions(+), 135 deletions(-)
Dave, if I can take this through my usb-next tree, I can finally get rid of the
dbg() macro for good. Or you can take it, and I can wait to drop dbg() until
after 3.7-rc1, which is also fine with me, which ever is easiest for you.
diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c
index 4fd48df..8d5fdf1 100644
--- a/drivers/net/usb/asix_devices.c
+++ b/drivers/net/usb/asix_devices.c
@@ -221,7 +221,8 @@ static int ax88172_bind(struct usbnet *dev, struct usb_interface *intf)
/* Get the MAC address */
ret = asix_read_cmd(dev, AX88172_CMD_READ_NODE_ID, 0, 0, ETH_ALEN, buf);
if (ret < 0) {
- dbg("read AX_CMD_READ_NODE_ID failed: %d", ret);
+ netdev_dbg(dev->net, "read AX_CMD_READ_NODE_ID failed: %d\n",
+ ret);
goto out;
}
memcpy(dev->net->dev_addr, buf, ETH_ALEN);
@@ -303,7 +304,7 @@ static int ax88772_reset(struct usbnet *dev)
ret = asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT, embd_phy, 0, 0, NULL);
if (ret < 0) {
- dbg("Select PHY #1 failed: %d", ret);
+ netdev_dbg(dev->net, "Select PHY #1 failed: %d\n", ret);
goto out;
}
@@ -331,13 +332,13 @@ static int ax88772_reset(struct usbnet *dev)
msleep(150);
rx_ctl = asix_read_rx_ctl(dev);
- dbg("RX_CTL is 0x%04x after software reset", rx_ctl);
+ netdev_dbg(dev->net, "RX_CTL is 0x%04x after software reset\n", rx_ctl);
ret = asix_write_rx_ctl(dev, 0x0000);
if (ret < 0)
goto out;
rx_ctl = asix_read_rx_ctl(dev);
- dbg("RX_CTL is 0x%04x setting to 0x0000", rx_ctl);
+ netdev_dbg(dev->net, "RX_CTL is 0x%04x setting to 0x0000\n", rx_ctl);
ret = asix_sw_reset(dev, AX_SWRESET_PRL);
if (ret < 0)
@@ -364,7 +365,7 @@ static int ax88772_reset(struct usbnet *dev)
AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT,
AX88772_IPG2_DEFAULT, 0, NULL);
if (ret < 0) {
- dbg("Write IPG,IPG1,IPG2 failed: %d", ret);
+ netdev_dbg(dev->net, "Write IPG,IPG1,IPG2 failed: %d\n", ret);
goto out;
}
@@ -381,10 +382,13 @@ static int ax88772_reset(struct usbnet *dev)
goto out;
rx_ctl = asix_read_rx_ctl(dev);
- dbg("RX_CTL is 0x%04x after all initializations", rx_ctl);
+ netdev_dbg(dev->net, "RX_CTL is 0x%04x after all initializations\n",
+ rx_ctl);
rx_ctl = asix_read_medium_status(dev);
- dbg("Medium Status is 0x%04x after all initializations", rx_ctl);
+ netdev_dbg(dev->net,
+ "Medium Status is 0x%04x after all initializations\n",
+ rx_ctl);
return 0;
@@ -416,7 +420,7 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
/* Get the MAC address */
ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID, 0, 0, ETH_ALEN, buf);
if (ret < 0) {
- dbg("Failed to read MAC address: %d", ret);
+ netdev_dbg(dev->net, "Failed to read MAC address: %d\n", ret);
return ret;
}
memcpy(dev->net->dev_addr, buf, ETH_ALEN);
@@ -439,7 +443,7 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
/* Reset the PHY to normal operation mode */
ret = asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT, embd_phy, 0, 0, NULL);
if (ret < 0) {
- dbg("Select PHY #1 failed: %d", ret);
+ netdev_dbg(dev->net, "Select PHY #1 failed: %d\n", ret);
return ret;
}
@@ -459,7 +463,7 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
/* Read PHYID register *AFTER* the PHY was reset properly */
phyid = asix_get_phyid(dev);
- dbg("PHYID=0x%08x", phyid);
+ netdev_dbg(dev->net, "PHYID=0x%08x\n", phyid);
/* Asix framing packs multiple eth frames into a 2K usb bulk transfer */
if (dev->driver_info->flags & FLAG_FRAMING_AX) {
@@ -575,13 +579,13 @@ static int ax88178_reset(struct usbnet *dev)
u32 phyid;
asix_read_cmd(dev, AX_CMD_READ_GPIOS, 0, 0, 1, &status);
- dbg("GPIO Status: 0x%04x", status);
+ netdev_dbg(dev->net, "GPIO Status: 0x%04x\n", status);
asix_write_cmd(dev, AX_CMD_WRITE_ENABLE, 0, 0, 0, NULL);
asix_read_cmd(dev, AX_CMD_READ_EEPROM, 0x0017, 0, 2, &eeprom);
asix_write_cmd(dev, AX_CMD_WRITE_DISABLE, 0, 0, 0, NULL);
- dbg("EEPROM index 0x17 is 0x%04x", eeprom);
+ netdev_dbg(dev->net, "EEPROM index 0x17 is 0x%04x\n", eeprom);
if (eeprom == cpu_to_le16(0xffff)) {
data->phymode = PHY_MODE_MARVELL;
@@ -592,7 +596,7 @@ static int ax88178_reset(struct usbnet *dev)
data->ledmode = le16_to_cpu(eeprom) >> 8;
gpio0 = (le16_to_cpu(eeprom) & 0x80) ? 0 : 1;
}
- dbg("GPIO0: %d, PhyMode: %d", gpio0, data->phymode);
+ netdev_dbg(dev->net, "GPIO0: %d, PhyMode: %d\n", gpio0, data->phymode);
/* Power up external GigaPHY through AX88178 GPIO pin */
asix_write_gpio(dev, AX_GPIO_RSE | AX_GPIO_GPO_1 | AX_GPIO_GPO1EN, 40);
@@ -601,14 +605,14 @@ static int ax88178_reset(struct usbnet *dev)
asix_write_gpio(dev, 0x001c, 300);
asix_write_gpio(dev, 0x003c, 30);
} else {
- dbg("gpio phymode == 1 path");
+ netdev_dbg(dev->net, "gpio phymode == 1 path\n");
asix_write_gpio(dev, AX_GPIO_GPO1EN, 30);
asix_write_gpio(dev, AX_GPIO_GPO1EN | AX_GPIO_GPO_1, 30);
}
/* Read PHYID register *AFTER* powering up PHY */
phyid = asix_get_phyid(dev);
- dbg("PHYID=0x%08x", phyid);
+ netdev_dbg(dev->net, "PHYID=0x%08x\n", phyid);
/* Set AX88178 to enable MII/GMII/RGMII interface for external PHY */
asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT, 0, 0, 0, NULL);
@@ -770,7 +774,7 @@ static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf)
/* Get the MAC address */
ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID, 0, 0, ETH_ALEN, buf);
if (ret < 0) {
- dbg("Failed to read MAC address: %d", ret);
+ netdev_dbg(dev->net, "Failed to read MAC address: %d\n", ret);
return ret;
}
memcpy(dev->net->dev_addr, buf, ETH_ALEN);
diff --git a/drivers/net/usb/catc.c b/drivers/net/usb/catc.c
index 26c5beb..6bf5672 100644
--- a/drivers/net/usb/catc.c
+++ b/drivers/net/usb/catc.c
@@ -236,7 +236,8 @@ static void catc_rx_done(struct urb *urb)
}
if (status) {
- dbg("rx_done, status %d, length %d", status, urb->actual_length);
+ dev_dbg(&urb->dev->dev, "rx_done, status %d, length %d",
+ status, urb->actual_length);
return;
}
@@ -275,10 +276,11 @@ static void catc_rx_done(struct urb *urb)
if (atomic_read(&catc->recq_sz)) {
int state;
atomic_dec(&catc->recq_sz);
- dbg("getting extra packet");
+ netdev_dbg(catc->netdev, "getting extra packet\n");
urb->dev = catc->usbdev;
if ((state = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
- dbg("submit(rx_urb) status %d", state);
+ netdev_dbg(catc->netdev,
+ "submit(rx_urb) status %d\n", state);
}
} else {
clear_bit(RX_RUNNING, &catc->flags);
@@ -317,18 +319,20 @@ static void catc_irq_done(struct urb *urb)
return;
/* -EPIPE: should clear the halt */
default: /* error */
- dbg("irq_done, status %d, data %02x %02x.", status, data[0], data[1]);
+ dev_dbg(&urb->dev->dev,
+ "irq_done, status %d, data %02x %02x.\n",
+ status, data[0], data[1]);
goto resubmit;
}
if (linksts == LinkGood) {
netif_carrier_on(catc->netdev);
- dbg("link ok");
+ netdev_dbg(catc->netdev, "link ok\n");
}
if (linksts == LinkBad) {
netif_carrier_off(catc->netdev);
- dbg("link bad");
+ netdev_dbg(catc->netdev, "link bad\n");
}
if (hasdata) {
@@ -385,7 +389,7 @@ static void catc_tx_done(struct urb *urb)
int r, status = urb->status;
if (status == -ECONNRESET) {
- dbg("Tx Reset.");
+ dev_dbg(&urb->dev->dev, "Tx Reset.\n");
urb->status = 0;
catc->netdev->trans_start = jiffies;
catc->netdev->stats.tx_errors++;
@@ -395,7 +399,8 @@ static void catc_tx_done(struct urb *urb)
}
if (status) {
- dbg("tx_done, status %d, length %d", status, urb->actual_length);
+ dev_dbg(&urb->dev->dev, "tx_done, status %d, length %d\n",
+ status, urb->actual_length);
return;
}
@@ -511,7 +516,8 @@ static void catc_ctrl_done(struct urb *urb)
int status = urb->status;
if (status)
- dbg("ctrl_done, status %d, len %d.", status, urb->actual_length);
+ dev_dbg(&urb->dev->dev, "ctrl_done, status %d, len %d.\n",
+ status, urb->actual_length);
spin_lock_irqsave(&catc->ctrl_lock, flags);
@@ -667,7 +673,9 @@ static void catc_set_multicast_list(struct net_device *netdev)
f5u011_mchash_async(catc, catc->multicast);
if (catc->rxmode[0] != rx) {
catc->rxmode[0] = rx;
- dbg("Setting RX mode to %2.2X %2.2X", catc->rxmode[0], catc->rxmode[1]);
+ netdev_dbg(catc->netdev,
+ "Setting RX mode to %2.2X %2.2X\n",
+ catc->rxmode[0], catc->rxmode[1]);
f5u011_rxmode_async(catc, catc->rxmode);
}
}
@@ -766,6 +774,7 @@ static const struct net_device_ops catc_netdev_ops = {
static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
+ struct device *dev = &intf->dev;
struct usb_device *usbdev = interface_to_usbdev(intf);
struct net_device *netdev;
struct catc *catc;
@@ -774,7 +783,7 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id
if (usb_set_interface(usbdev,
intf->altsetting->desc.bInterfaceNumber, 1)) {
- dev_err(&intf->dev, "Can't set altsetting 1.\n");
+ dev_err(dev, "Can't set altsetting 1.\n");
return -EIO;
}
@@ -817,7 +826,7 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id
if (le16_to_cpu(usbdev->descriptor.idVendor) == 0x0423 &&
le16_to_cpu(usbdev->descriptor.idProduct) == 0xa &&
le16_to_cpu(catc->usbdev->descriptor.bcdDevice) == 0x0130) {
- dbg("Testing for f5u011");
+ dev_dbg(dev, "Testing for f5u011\n");
catc->is_f5u011 = 1;
atomic_set(&catc->recq_sz, 0);
pktsz = RX_PKT_SZ;
@@ -838,7 +847,7 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id
catc->irq_buf, 2, catc_irq_done, catc, 1);
if (!catc->is_f5u011) {
- dbg("Checking memory size\n");
+ dev_dbg(dev, "Checking memory size\n");
i = 0x12345678;
catc_write_mem(catc, 0x7a80, &i, 4);
@@ -850,7 +859,7 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id
case 0x12345678:
catc_set_reg(catc, TxBufCount, 8);
catc_set_reg(catc, RxBufCount, 32);
- dbg("64k Memory\n");
+ dev_dbg(dev, "64k Memory\n");
break;
default:
dev_warn(&intf->dev,
@@ -858,49 +867,49 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id
case 0x87654321:
catc_set_reg(catc, TxBufCount, 4);
catc_set_reg(catc, RxBufCount, 16);
- dbg("32k Memory\n");
+ dev_dbg(dev, "32k Memory\n");
break;
}
- dbg("Getting MAC from SEEROM.");
+ dev_dbg(dev, "Getting MAC from SEEROM.\n");
catc_get_mac(catc, netdev->dev_addr);
- dbg("Setting MAC into registers.");
+ dev_dbg(dev, "Setting MAC into registers.\n");
for (i = 0; i < 6; i++)
catc_set_reg(catc, StationAddr0 - i, netdev->dev_addr[i]);
- dbg("Filling the multicast list.");
+ dev_dbg(dev, "Filling the multicast list.\n");
memset(broadcast, 0xff, 6);
catc_multicast(broadcast, catc->multicast);
catc_multicast(netdev->dev_addr, catc->multicast);
catc_write_mem(catc, 0xfa80, catc->multicast, 64);
- dbg("Clearing error counters.");
+ dev_dbg(dev, "Clearing error counters.\n");
for (i = 0; i < 8; i++)
catc_set_reg(catc, EthStats + i, 0);
catc->last_stats = jiffies;
- dbg("Enabling.");
+ dev_dbg(dev, "Enabling.\n");
catc_set_reg(catc, MaxBurst, RX_MAX_BURST);
catc_set_reg(catc, OpModes, OpTxMerge | OpRxMerge | OpLenInclude | Op3MemWaits);
catc_set_reg(catc, LEDCtrl, LEDLink);
catc_set_reg(catc, RxUnit, RxEnable | RxPolarity | RxMultiCast);
} else {
- dbg("Performing reset\n");
+ dev_dbg(dev, "Performing reset\n");
catc_reset(catc);
catc_get_mac(catc, netdev->dev_addr);
- dbg("Setting RX Mode");
+ dev_dbg(dev, "Setting RX Mode\n");
catc->rxmode[0] = RxEnable | RxPolarity | RxMultiCast;
catc->rxmode[1] = 0;
f5u011_rxmode(catc, catc->rxmode);
}
- dbg("Init done.");
+ dev_dbg(dev, "Init done.\n");
printk(KERN_INFO "%s: %s USB Ethernet at usb-%s-%s, %pM.\n",
netdev->name, (catc->is_f5u011) ? "Belkin F5U011" : "CATC EL1210A NetMate",
usbdev->bus->bus_name, usbdev->devpath, netdev->dev_addr);
diff --git a/drivers/net/usb/gl620a.c b/drivers/net/usb/gl620a.c
index db3c802..a7e3f4e 100644
--- a/drivers/net/usb/gl620a.c
+++ b/drivers/net/usb/gl620a.c
@@ -91,7 +91,9 @@ static int genelink_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
// get the packet count of the received skb
count = le32_to_cpu(header->packet_count);
if (count > GL_MAX_TRANSMIT_PACKETS) {
- dbg("genelink: invalid received packet count %u", count);
+ netdev_dbg(dev->net,
+ "genelink: invalid received packet count %u\n",
+ count);
return 0;
}
@@ -107,7 +109,8 @@ static int genelink_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
// this may be a broken packet
if (size > GL_MAX_PACKET_LEN) {
- dbg("genelink: invalid rx length %d", size);
+ netdev_dbg(dev->net, "genelink: invalid rx length %d\n",
+ size);
return 0;
}
@@ -133,7 +136,8 @@ static int genelink_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
skb_pull(skb, 4);
if (skb->len > GL_MAX_PACKET_LEN) {
- dbg("genelink: invalid rx length %d", skb->len);
+ netdev_dbg(dev->net, "genelink: invalid rx length %d\n",
+ skb->len);
return 0;
}
return 1;
diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c
index c3d0349..c75e11e 100644
--- a/drivers/net/usb/kaweth.c
+++ b/drivers/net/usb/kaweth.c
@@ -267,19 +267,16 @@ static int kaweth_control(struct kaweth_device *kaweth,
struct usb_ctrlrequest *dr;
int retval;
- dbg("kaweth_control()");
+ netdev_dbg(kaweth->net, "kaweth_control()\n");
if(in_interrupt()) {
- dbg("in_interrupt()");
+ netdev_dbg(kaweth->net, "in_interrupt()\n");
return -EBUSY;
}
dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC);
-
- if (!dr) {
- dbg("kmalloc() failed");
+ if (!dr)
return -ENOMEM;
- }
dr->bRequestType = requesttype;
dr->bRequest = request;
@@ -305,7 +302,7 @@ static int kaweth_read_configuration(struct kaweth_device *kaweth)
{
int retval;
- dbg("Reading kaweth configuration");
+ netdev_dbg(kaweth->net, "Reading kaweth configuration\n");
retval = kaweth_control(kaweth,
usb_rcvctrlpipe(kaweth->dev, 0),
@@ -327,7 +324,7 @@ static int kaweth_set_urb_size(struct kaweth_device *kaweth, __u16 urb_size)
{
int retval;
- dbg("Setting URB size to %d", (unsigned)urb_size);
+ netdev_dbg(kaweth->net, "Setting URB size to %d\n", (unsigned)urb_size);
retval = kaweth_control(kaweth,
usb_sndctrlpipe(kaweth->dev, 0),
@@ -349,7 +346,7 @@ static int kaweth_set_sofs_wait(struct kaweth_device *kaweth, __u16 sofs_wait)
{
int retval;
- dbg("Set SOFS wait to %d", (unsigned)sofs_wait);
+ netdev_dbg(kaweth->net, "Set SOFS wait to %d\n", (unsigned)sofs_wait);
retval = kaweth_control(kaweth,
usb_sndctrlpipe(kaweth->dev, 0),
@@ -372,7 +369,8 @@ static int kaweth_set_receive_filter(struct kaweth_device *kaweth,
{
int retval;
- dbg("Set receive filter to %d", (unsigned)receive_filter);
+ netdev_dbg(kaweth->net, "Set receive filter to %d\n",
+ (unsigned)receive_filter);
retval = kaweth_control(kaweth,
usb_sndctrlpipe(kaweth->dev, 0),
@@ -421,12 +419,13 @@ static int kaweth_download_firmware(struct kaweth_device *kaweth,
kaweth->firmware_buf[4] = type;
kaweth->firmware_buf[5] = interrupt;
- dbg("High: %i, Low:%i", kaweth->firmware_buf[3],
+ netdev_dbg(kaweth->net, "High: %i, Low:%i\n", kaweth->firmware_buf[3],
kaweth->firmware_buf[2]);
- dbg("Downloading firmware at %p to kaweth device at %p",
- fw->data, kaweth);
- dbg("Firmware length: %d", data_len);
+ netdev_dbg(kaweth->net,
+ "Downloading firmware at %p to kaweth device at %p\n",
+ fw->data, kaweth);
+ netdev_dbg(kaweth->net, "Firmware length: %d\n", data_len);
return kaweth_control(kaweth,
usb_sndctrlpipe(kaweth->dev, 0),
@@ -454,7 +453,7 @@ static int kaweth_trigger_firmware(struct kaweth_device *kaweth,
kaweth->firmware_buf[6] = 0x00;
kaweth->firmware_buf[7] = 0x00;
- dbg("Triggering firmware");
+ netdev_dbg(kaweth->net, "Triggering firmware\n");
return kaweth_control(kaweth,
usb_sndctrlpipe(kaweth->dev, 0),
@@ -474,11 +473,11 @@ static int kaweth_reset(struct kaweth_device *kaweth)
{
int result;
- dbg("kaweth_reset(%p)", kaweth);
+ netdev_dbg(kaweth->net, "kaweth_reset(%p)\n", kaweth);
result = usb_reset_configuration(kaweth->dev);
mdelay(10);
- dbg("kaweth_reset() returns %d.",result);
+ netdev_dbg(kaweth->net, "kaweth_reset() returns %d.\n", result);
return result;
}
@@ -595,6 +594,7 @@ static void kaweth_async_set_rx_mode(struct kaweth_device *kaweth);
****************************************************************/
static void kaweth_usb_receive(struct urb *urb)
{
+ struct device *dev = &urb->dev->dev;
struct kaweth_device *kaweth = urb->context;
struct net_device *net = kaweth->net;
int status = urb->status;
@@ -610,25 +610,25 @@ static void kaweth_usb_receive(struct urb *urb)
kaweth->stats.rx_errors++;
kaweth->end = 1;
wake_up(&kaweth->term_wait);
- dbg("Status was -EPIPE.");
+ dev_dbg(dev, "Status was -EPIPE.\n");
return;
}
if (unlikely(status == -ECONNRESET || status == -ESHUTDOWN)) {
/* we are killed - set a flag and wake the disconnect handler */
kaweth->end = 1;
wake_up(&kaweth->term_wait);
- dbg("Status was -ECONNRESET or -ESHUTDOWN.");
+ dev_dbg(dev, "Status was -ECONNRESET or -ESHUTDOWN.\n");
return;
}
if (unlikely(status == -EPROTO || status == -ETIME ||
status == -EILSEQ)) {
kaweth->stats.rx_errors++;
- dbg("Status was -EPROTO, -ETIME, or -EILSEQ.");
+ dev_dbg(dev, "Status was -EPROTO, -ETIME, or -EILSEQ.\n");
return;
}
if (unlikely(status == -EOVERFLOW)) {
kaweth->stats.rx_errors++;
- dbg("Status was -EOVERFLOW.");
+ dev_dbg(dev, "Status was -EOVERFLOW.\n");
}
spin_lock(&kaweth->device_lock);
if (IS_BLOCKED(kaweth->status)) {
@@ -687,7 +687,7 @@ static int kaweth_open(struct net_device *net)
struct kaweth_device *kaweth = netdev_priv(net);
int res;
- dbg("Opening network device.");
+ netdev_dbg(kaweth->net, "Opening network device.\n");
res = usb_autopm_get_interface(kaweth->intf);
if (res) {
@@ -787,7 +787,8 @@ static void kaweth_usb_transmit_complete(struct urb *urb)
if (unlikely(status != 0))
if (status != -ENOENT)
- dbg("%s: TX status %d.", kaweth->net->name, status);
+ dev_dbg(&urb->dev->dev, "%s: TX status %d.\n",
+ kaweth->net->name, status);
netif_wake_queue(kaweth->net);
dev_kfree_skb_irq(skb);
@@ -871,7 +872,7 @@ static void kaweth_set_rx_mode(struct net_device *net)
KAWETH_PACKET_FILTER_BROADCAST |
KAWETH_PACKET_FILTER_MULTICAST;
- dbg("Setting Rx mode to %d", packet_filter_bitmap);
+ netdev_dbg(net, "Setting Rx mode to %d\n", packet_filter_bitmap);
netif_stop_queue(net);
@@ -916,7 +917,8 @@ static void kaweth_async_set_rx_mode(struct kaweth_device *kaweth)
result);
}
else {
- dbg("Set Rx mode to %d", packet_filter_bitmap);
+ netdev_dbg(kaweth->net, "Set Rx mode to %d\n",
+ packet_filter_bitmap);
}
}
@@ -951,7 +953,7 @@ static int kaweth_suspend(struct usb_interface *intf, pm_message_t message)
struct kaweth_device *kaweth = usb_get_intfdata(intf);
unsigned long flags;
- dbg("Suspending device");
+ dev_dbg(&intf->dev, "Suspending device\n");
spin_lock_irqsave(&kaweth->device_lock, flags);
kaweth->status |= KAWETH_STATUS_SUSPENDING;
spin_unlock_irqrestore(&kaweth->device_lock, flags);
@@ -968,7 +970,7 @@ static int kaweth_resume(struct usb_interface *intf)
struct kaweth_device *kaweth = usb_get_intfdata(intf);
unsigned long flags;
- dbg("Resuming device");
+ dev_dbg(&intf->dev, "Resuming device\n");
spin_lock_irqsave(&kaweth->device_lock, flags);
kaweth->status &= ~KAWETH_STATUS_SUSPENDING;
spin_unlock_irqrestore(&kaweth->device_lock, flags);
@@ -1003,36 +1005,37 @@ static int kaweth_probe(
const struct usb_device_id *id /* from id_table */
)
{
- struct usb_device *dev = interface_to_usbdev(intf);
+ struct device *dev = &intf->dev;
+ struct usb_device *udev = interface_to_usbdev(intf);
struct kaweth_device *kaweth;
struct net_device *netdev;
const eth_addr_t bcast_addr = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
int result = 0;
- dbg("Kawasaki Device Probe (Device number:%d): 0x%4.4x:0x%4.4x:0x%4.4x",
- dev->devnum,
- le16_to_cpu(dev->descriptor.idVendor),
- le16_to_cpu(dev->descriptor.idProduct),
- le16_to_cpu(dev->descriptor.bcdDevice));
+ dev_dbg(dev,
+ "Kawasaki Device Probe (Device number:%d): 0x%4.4x:0x%4.4x:0x%4.4x\n",
+ udev->devnum, le16_to_cpu(udev->descriptor.idVendor),
+ le16_to_cpu(udev->descriptor.idProduct),
+ le16_to_cpu(udev->descriptor.bcdDevice));
- dbg("Device at %p", dev);
+ dev_dbg(dev, "Device at %p\n", udev);
- dbg("Descriptor length: %x type: %x",
- (int)dev->descriptor.bLength,
- (int)dev->descriptor.bDescriptorType);
+ dev_dbg(dev, "Descriptor length: %x type: %x\n",
+ (int)udev->descriptor.bLength,
+ (int)udev->descriptor.bDescriptorType);
netdev = alloc_etherdev(sizeof(*kaweth));
if (!netdev)
return -ENOMEM;
kaweth = netdev_priv(netdev);
- kaweth->dev = dev;
+ kaweth->dev = udev;
kaweth->net = netdev;
spin_lock_init(&kaweth->device_lock);
init_waitqueue_head(&kaweth->term_wait);
- dbg("Resetting.");
+ dev_dbg(dev, "Resetting.\n");
kaweth_reset(kaweth);
@@ -1041,17 +1044,17 @@ static int kaweth_probe(
* downloaded. Don't try to do it again, or we'll hang the device.
*/
- if (le16_to_cpu(dev->descriptor.bcdDevice) >> 8) {
- dev_info(&intf->dev, "Firmware present in device.\n");
+ if (le16_to_cpu(udev->descriptor.bcdDevice) >> 8) {
+ dev_info(dev, "Firmware present in device.\n");
} else {
/* Download the firmware */
- dev_info(&intf->dev, "Downloading firmware...\n");
+ dev_info(dev, "Downloading firmware...\n");
kaweth->firmware_buf = (__u8 *)__get_free_page(GFP_KERNEL);
if ((result = kaweth_download_firmware(kaweth,
"kaweth/new_code.bin",
100,
2)) < 0) {
- dev_err(&intf->dev, "Error downloading firmware (%d)\n",
+ dev_err(dev, "Error downloading firmware (%d)\n",
result);
goto err_fw;
}
@@ -1060,8 +1063,7 @@ static int kaweth_probe(
"kaweth/new_code_fix.bin",
100,
3)) < 0) {
- dev_err(&intf->dev,
- "Error downloading firmware fix (%d)\n",
+ dev_err(dev, "Error downloading firmware fix (%d)\n",
result);
goto err_fw;
}
@@ -1070,8 +1072,7 @@ static int kaweth_probe(
"kaweth/trigger_code.bin",
126,
2)) < 0) {
- dev_err(&intf->dev,
- "Error downloading trigger code (%d)\n",
+ dev_err(dev, "Error downloading trigger code (%d)\n",
result);
goto err_fw;
@@ -1081,19 +1082,18 @@ static int kaweth_probe(
"kaweth/trigger_code_fix.bin",
126,
3)) < 0) {
- dev_err(&intf->dev, "Error downloading trigger code fix (%d)\n", result);
+ dev_err(dev, "Error downloading trigger code fix (%d)\n", result);
goto err_fw;
}
if ((result = kaweth_trigger_firmware(kaweth, 126)) < 0) {
- dev_err(&intf->dev, "Error triggering firmware (%d)\n",
- result);
+ dev_err(dev, "Error triggering firmware (%d)\n", result);
goto err_fw;
}
/* Device will now disappear for a moment... */
- dev_info(&intf->dev, "Firmware loaded. I'll be back...\n");
+ dev_info(dev, "Firmware loaded. I'll be back...\n");
err_fw:
free_page((unsigned long)kaweth->firmware_buf);
free_netdev(netdev);
@@ -1103,29 +1103,29 @@ err_fw:
result = kaweth_read_configuration(kaweth);
if(result < 0) {
- dev_err(&intf->dev, "Error reading configuration (%d), no net device created\n", result);
+ dev_err(dev, "Error reading configuration (%d), no net device created\n", result);
goto err_free_netdev;
}
- dev_info(&intf->dev, "Statistics collection: %x\n", kaweth->configuration.statistics_mask);
- dev_info(&intf->dev, "Multicast filter limit: %x\n", kaweth->configuration.max_multicast_filters & ((1 << 15) - 1));
- dev_info(&intf->dev, "MTU: %d\n", le16_to_cpu(kaweth->configuration.segment_size));
- dev_info(&intf->dev, "Read MAC address %pM\n", kaweth->configuration.hw_addr);
+ dev_info(dev, "Statistics collection: %x\n", kaweth->configuration.statistics_mask);
+ dev_info(dev, "Multicast filter limit: %x\n", kaweth->configuration.max_multicast_filters & ((1 << 15) - 1));
+ dev_info(dev, "MTU: %d\n", le16_to_cpu(kaweth->configuration.segment_size));
+ dev_info(dev, "Read MAC address %pM\n", kaweth->configuration.hw_addr);
if(!memcmp(&kaweth->configuration.hw_addr,
&bcast_addr,
sizeof(bcast_addr))) {
- dev_err(&intf->dev, "Firmware not functioning properly, no net device created\n");
+ dev_err(dev, "Firmware not functioning properly, no net device created\n");
goto err_free_netdev;
}
if(kaweth_set_urb_size(kaweth, KAWETH_BUF_SIZE) < 0) {
- dbg("Error setting URB size");
+ dev_dbg(dev, "Error setting URB size\n");
goto err_free_netdev;
}
if(kaweth_set_sofs_wait(kaweth, KAWETH_SOFS_TO_WAIT) < 0) {
- dev_err(&intf->dev, "Error setting SOFS wait\n");
+ dev_err(dev, "Error setting SOFS wait\n");
goto err_free_netdev;
}
@@ -1135,11 +1135,11 @@ err_fw:
KAWETH_PACKET_FILTER_MULTICAST);
if(result < 0) {
- dev_err(&intf->dev, "Error setting receive filter\n");
+ dev_err(dev, "Error setting receive filter\n");
goto err_free_netdev;
}
- dbg("Initializing net device.");
+ dev_dbg(dev, "Initializing net device.\n");
kaweth->intf = intf;
@@ -1181,20 +1181,20 @@ err_fw:
#if 0
// dma_supported() is deeply broken on almost all architectures
- if (dma_supported (&intf->dev, 0xffffffffffffffffULL))
+ if (dma_supported (dev, 0xffffffffffffffffULL))
kaweth->net->features |= NETIF_F_HIGHDMA;
#endif
- SET_NETDEV_DEV(netdev, &intf->dev);
+ SET_NETDEV_DEV(netdev, dev);
if (register_netdev(netdev) != 0) {
- dev_err(&intf->dev, "Error registering netdev.\n");
+ dev_err(dev, "Error registering netdev.\n");
goto err_intfdata;
}
- dev_info(&intf->dev, "kaweth interface created at %s\n",
+ dev_info(dev, "kaweth interface created at %s\n",
kaweth->net->name);
- dbg("Kaweth probe returning.");
+ dev_dbg(dev, "Kaweth probe returning.\n");
return 0;
@@ -1232,7 +1232,7 @@ static void kaweth_disconnect(struct usb_interface *intf)
}
netdev = kaweth->net;
- dbg("Unregistering net device");
+ netdev_dbg(kaweth->net, "Unregistering net device\n");
unregister_netdev(netdev);
usb_free_urb(kaweth->rx_urb);
diff --git a/drivers/net/usb/net1080.c b/drivers/net/usb/net1080.c
index 28c4d51..aad7abe 100644
--- a/drivers/net/usb/net1080.c
+++ b/drivers/net/usb/net1080.c
@@ -156,11 +156,11 @@ static void nc_dump_registers(struct usbnet *dev)
u16 *vp = kmalloc(sizeof (u16));
if (!vp) {
- dbg("no memory?");
+ netdev_dbg(dev->net, "no memory?\n");
return;
}
- dbg("%s registers:", dev->net->name);
+ netdev_dbg(dev->net, "registers:\n");
for (reg = 0; reg < 0x20; reg++) {
int retval;
@@ -172,11 +172,10 @@ static void nc_dump_registers(struct usbnet *dev)
retval = nc_register_read(dev, reg, vp);
if (retval < 0)
- dbg("%s reg [0x%x] ==> error %d",
- dev->net->name, reg, retval);
+ netdev_dbg(dev->net, "reg [0x%x] ==> error %d\n",
+ reg, retval);
else
- dbg("%s reg [0x%x] = 0x%x",
- dev->net->name, reg, *vp);
+ netdev_dbg(dev->net, "reg [0x%x] = 0x%x\n", reg, *vp);
}
kfree(vp);
}
@@ -300,15 +299,15 @@ static int net1080_reset(struct usbnet *dev)
// nc_dump_registers(dev);
if ((retval = nc_register_read(dev, REG_STATUS, vp)) < 0) {
- dbg("can't read %s-%s status: %d",
- dev->udev->bus->bus_name, dev->udev->devpath, retval);
+ netdev_dbg(dev->net, "can't read %s-%s status: %d\n",
+ dev->udev->bus->bus_name, dev->udev->devpath, retval);
goto done;
}
status = *vp;
nc_dump_status(dev, status);
if ((retval = nc_register_read(dev, REG_USBCTL, vp)) < 0) {
- dbg("can't read USBCTL, %d", retval);
+ netdev_dbg(dev->net, "can't read USBCTL, %d\n", retval);
goto done;
}
usbctl = *vp;
@@ -318,7 +317,7 @@ static int net1080_reset(struct usbnet *dev)
USBCTL_FLUSH_THIS | USBCTL_FLUSH_OTHER);
if ((retval = nc_register_read(dev, REG_TTL, vp)) < 0) {
- dbg("can't read TTL, %d", retval);
+ netdev_dbg(dev->net, "can't read TTL, %d\n", retval);
goto done;
}
ttl = *vp;
@@ -326,7 +325,7 @@ static int net1080_reset(struct usbnet *dev)
nc_register_write(dev, REG_TTL,
MK_TTL(NC_READ_TTL_MS, TTL_OTHER(ttl)) );
- dbg("%s: assigned TTL, %d ms", dev->net->name, NC_READ_TTL_MS);
+ netdev_dbg(dev->net, "assigned TTL, %d ms\n", NC_READ_TTL_MS);
netif_info(dev, link, dev->net, "port %c, peer %sconnected\n",
(status & STATUS_PORT_A) ? 'A' : 'B',
@@ -350,7 +349,7 @@ static int net1080_check_connect(struct usbnet *dev)
status = *vp;
kfree(vp);
if (retval != 0) {
- dbg("%s net1080_check_conn read - %d", dev->net->name, retval);
+ netdev_dbg(dev->net, "net1080_check_conn read - %d\n", retval);
return retval;
}
if ((status & STATUS_CONN_OTHER) != STATUS_CONN_OTHER)
@@ -422,8 +421,9 @@ static int net1080_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
if (!(skb->len & 0x01)) {
#ifdef DEBUG
struct net_device *net = dev->net;
- dbg("rx framesize %d range %d..%d mtu %d", skb->len,
- net->hard_header_len, dev->hard_mtu, net->mtu);
+ netdev_dbg(dev->net, "rx framesize %d range %d..%d mtu %d\n",
+ skb->len, net->hard_header_len, dev->hard_mtu,
+ net->mtu);
#endif
dev->net->stats.rx_frame_errors++;
nc_ensure_sync(dev);
@@ -435,17 +435,17 @@ static int net1080_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
packet_len = le16_to_cpup(&header->packet_len);
if (FRAMED_SIZE(packet_len) > NC_MAX_PACKET) {
dev->net->stats.rx_frame_errors++;
- dbg("packet too big, %d", packet_len);
+ netdev_dbg(dev->net, "packet too big, %d\n", packet_len);
nc_ensure_sync(dev);
return 0;
} else if (hdr_len < MIN_HEADER) {
dev->net->stats.rx_frame_errors++;
- dbg("header too short, %d", hdr_len);
+ netdev_dbg(dev->net, "header too short, %d\n", hdr_len);
nc_ensure_sync(dev);
return 0;
} else if (hdr_len > MIN_HEADER) {
// out of band data for us?
- dbg("header OOB, %d bytes", hdr_len - MIN_HEADER);
+ netdev_dbg(dev->net, "header OOB, %d bytes\n", hdr_len - MIN_HEADER);
nc_ensure_sync(dev);
// switch (vendor/product ids) { ... }
}
@@ -458,23 +458,23 @@ static int net1080_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
if ((packet_len & 0x01) == 0) {
if (skb->data [packet_len] != PAD_BYTE) {
dev->net->stats.rx_frame_errors++;
- dbg("bad pad");
+ netdev_dbg(dev->net, "bad pad\n");
return 0;
}
skb_trim(skb, skb->len - 1);
}
if (skb->len != packet_len) {
dev->net->stats.rx_frame_errors++;
- dbg("bad packet len %d (expected %d)",
- skb->len, packet_len);
+ netdev_dbg(dev->net, "bad packet len %d (expected %d)\n",
+ skb->len, packet_len);
nc_ensure_sync(dev);
return 0;
}
if (header->packet_id != get_unaligned(&trailer->packet_id)) {
dev->net->stats.rx_fifo_errors++;
- dbg("(2+ dropped) rx packet_id mismatch 0x%x 0x%x",
- le16_to_cpu(header->packet_id),
- le16_to_cpu(trailer->packet_id));
+ netdev_dbg(dev->net, "(2+ dropped) rx packet_id mismatch 0x%x 0x%x\n",
+ le16_to_cpu(header->packet_id),
+ le16_to_cpu(trailer->packet_id));
return 0;
}
#if 0
diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c
index 0e2c92e..5f39a3b 100644
--- a/drivers/net/usb/rtl8150.c
+++ b/drivers/net/usb/rtl8150.c
@@ -275,7 +275,7 @@ static int rtl8150_set_mac_address(struct net_device *netdev, void *p)
return -EBUSY;
memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
- dbg("%s: Setting MAC address to %pM\n", netdev->name, netdev->dev_addr);
+ netdev_dbg(netdev, "Setting MAC address to %pM\n", netdev->dev_addr);
/* Set the IDR registers. */
set_registers(dev, IDR, netdev->addr_len, netdev->dev_addr);
#ifdef EEPROM_WRITE
@@ -503,12 +503,12 @@ static void intr_callback(struct urb *urb)
if ((d[INT_MSR] & MSR_LINK) == 0) {
if (netif_carrier_ok(dev->netdev)) {
netif_carrier_off(dev->netdev);
- dbg("%s: LINK LOST\n", __func__);
+ netdev_dbg(dev->netdev, "%s: LINK LOST\n", __func__);
}
} else {
if (!netif_carrier_ok(dev->netdev)) {
netif_carrier_on(dev->netdev);
- dbg("%s: LINK CAME BACK\n", __func__);
+ netdev_dbg(dev->netdev, "%s: LINK CAME BACK\n", __func__);
}
}
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* Re: [RFC] tcp: use order-3 pages in tcp_sendmsg()
From: Rick Jones @ 2012-09-19 17:28 UTC (permalink / raw)
To: Eric Dumazet; +Cc: David Miller, netdev
In-Reply-To: <1348067659.26523.949.camel@edumazet-glaptop>
On 09/19/2012 08:14 AM, Eric Dumazet wrote:
> I did some tests and got no problem so far, even using splice() [ this
> one was tricky because it only deals with order-0 pages at this moment ]
>
> NIC tested : ixgbe, igb, bnx2x, tg3, mellanox mlx4
>
> On loopback, performance of netperf goes from 31900 Mb/s to 38500 Mb/s,
> thats a 20 % increase.
I guess Brutus will need a new baseline for his TCP Friends patch then :)
BTW, what is the change, if any for TCP_RR?
happy benchmarking,
rick jones
^ permalink raw reply
* [RFC] new connection-oriented layer 3+4 protocol
From: michi1 @ 2012-09-19 17:08 UTC (permalink / raw)
To: netdev, davem
Hi!
I am programming a new layer 3+4 protocol for mesh networks. Basically it is
- connection oriented
- source (+optional onion) routed
- doing windowing between each neighbor on every connection (no congestion
avoidance)
- using credits as a metric for QoS
The protocol especially tries to withstand DoS attacks and rough
users/application without human interference. This includes protection against
inserting bogus routes, blackholing/throttling, addressing conflicts (node
address can be a hashed public crypto key) and ressource contention. In theory
it could provide Byzantine robustness, but in practice the overhead for
calculating routes and ressource contention will limit how far this gets.
Right now the layer 3 is running somehow (without any crypto). The layer 4 is
currently rather incomplete and broken.
Project home:
http://michaelblizek.homelinux.net/projects/cor/index.html
Code:
http://repo.or.cz/w/cor.git/tree/HEAD:/net/cor
-Michi
^ permalink raw reply
* Re: [PATCH] netxen: check for root bus in netxen_mask_aer_correctable
From: David Miller @ 2012-09-19 17:40 UTC (permalink / raw)
To: rajesh.borundia; +Cc: nikolay, sony.chacko, netdev
In-Reply-To: <13A253B3F9BEFE43B93C09CF75F63CAA827E3AEA05@MNEXMB1.qlogic.org>
From: Rajesh Borundia <rajesh.borundia@qlogic.com>
Date: Wed, 19 Sep 2012 02:24:29 -0500
>
> ________________________________________
> From: David Miller [davem@davemloft.net]
> Sent: Wednesday, September 19, 2012 1:53 AM
> To: Rajesh Borundia
> Cc: nikolay@redhat.com; Sony Chacko; netdev
> Subject: Re: [PATCH] netxen: check for root bus in netxen_mask_aer_correctable
>
> No, this is not the correct way to submit patches written by other
> people.
>
> Look at how people like Jeff Kirsher submits Intel driver patches
> written by people other than himself.
>
> Apologies, will follow the guideline.
This is also not the correct way to reply to people in email.
You haven't properly quoted me, so it's impossible to discern the text
that I wrote from the text that you have written in response.
If you look at how other people respond in email, you'll see that the
respondee is properly quoted using prefix characters in the initial
columns of the quoted test.
> Like
> this.
This is a function of your email client, please learn how to configure
it so that you can reply properly on these mailing lists. Don't try
to force it and do the quoting by hand.
It is extremely frustrating to communicate with contributors who
cannot write email that conforms to accepted practices and conventions
on the mailing list. Please get your act together, or you will find
that your postings will get less attention and care than you would
like.
^ permalink raw reply
* Re: [PATCH net-next] ipv6: recursive check rt->dst.from when call rt6_check_expired
From: David Miller @ 2012-09-19 17:41 UTC (permalink / raw)
To: gaofeng; +Cc: roy.qing.li, netdev
In-Reply-To: <505980BE.5060300@cn.fujitsu.com>
From: Gao feng <gaofeng@cn.fujitsu.com>
Date: Wed, 19 Sep 2012 16:22:22 +0800
> 于 2012年09月14日 13:54, roy.qing.li@gmail.com 写道:
>> From: Li RongQing <roy.qing.li@gmail.com>
>>
>> If dst cache dst_a copies from dst_b, and dst_b copies from dst_c, check
>> if dst_a is expired or not, we should not end with dst_a->dst.from, dst_b,
>> we should check dst_c.
>>
>> CC: Gao feng <gaofeng@cn.fujitsu.com>
>> Signed-off-by: Li RongQing <roy.qing.li@gmail.com>
>> ---
>
> Looks good to me,thanks rongqing :)
An explicit "Acked-by: " is more useful to us than simply saying
it looks good.
^ permalink raw reply
* Re: [PATCH net-next] net: only run neigh_forced_gc() from one cpu
From: David Miller @ 2012-09-19 17:45 UTC (permalink / raw)
To: eric.dumazet; +Cc: netdev, maze, therbert, lorenzo
In-Reply-To: <1348046827.26523.571.camel@edumazet-glaptop>
From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Wed, 19 Sep 2012 11:27:07 +0200
> From: Eric Dumazet <edumazet@google.com>
>
> With multiqueue NIC or RPS, we can have situation where all cpus are
> spending huge amount of cycles in neigh_forced_gc(), and machine can
> crash.
>
> Since we are under probable attack, its better to let only one cpu
> do the scan, and other cpus immediately return from neigh_forced_gc()
>
> Signed-off-by: Eric Dumazet <edumazet@google.com>
I suspect you're only seeing this with ipv6 traffic present.
And you should mention that because it determines how we really
should handle this.
I seriously doubt you can trigger this with a pure-ipv4 workload
because all neigh entries are ref-less and thus trivially reclaimable.
If you can trigger it with ipv4, then reclaim needs to be rewritten so
that for ref-less entries it's more efficient and scalable.
I'm not applying this patch.
^ permalink raw reply
* Re: New commands to configure IOV features
From: David Miller @ 2012-09-19 17:49 UTC (permalink / raw)
To: yuvalmin; +Cc: netdev, ariele, eilong
In-Reply-To: <5059A767.2090307@broadcom.com>
From: "Yuval Mintz" <yuvalmin@broadcom.com>
Date: Wed, 19 Sep 2012 14:07:19 +0300
> 3. Implement a module param in our bnx2x code.
Just because I was a moron and didn't notice the other cases
doesn't mean I should let you guys do it too.
So I just want to say that #3 is absolutely not an option.
^ permalink raw reply
* Re: [PATCH v2 0/9] net/macb: driver enhancement concerning GEM support, ring logic and cleanup
From: David Miller @ 2012-09-19 17:50 UTC (permalink / raw)
To: nicolas.ferre
Cc: netdev, havard, bhutchings, linux-arm-kernel, plagnioj,
patrice.vilchez, linux-kernel
In-Reply-To: <cover.1348055112.git.nicolas.ferre@atmel.com>
From: Nicolas Ferre <nicolas.ferre@atmel.com>
Date: Wed, 19 Sep 2012 13:55:13 +0200
> This is an enhancement work that began several years ago. I try to catchup with
> some performance improvement that has been implemented then by Havard.
> The ring index logic and the TX error path modification are the biggest changes
> but some cleanup/debugging have been added along the way.
> The GEM revision will benefit from the Gigabit support.
>
> The series has been tested on several Atmel AT91 SoC with the two MACB/GEM
> flavors.
>
> v2: - modify the tx error handling: now uses a workqueue
> - information provided by ethtool -i were not accurate: removed
Don't submit patches like this.
When you put an RFC right in the middle of the series, it screws everything
up.
It means that I can't only apply the parts that are not RFC.
^ permalink raw reply
* Re: [PATCH] USB: remove dbg() usage in USB networking drivers
From: Joe Perches @ 2012-09-19 17:53 UTC (permalink / raw)
To: Greg Kroah-Hartman; +Cc: netdev, linux-usb, linux-kernel
In-Reply-To: <20120919171316.GA12248@kroah.com>
On Wed, 2012-09-19 at 18:13 +0100, Greg Kroah-Hartman wrote:
> The dbg() USB macro is so old, it predates me. The USB networking drivers are
> the last hold-out using this macro, and we want to get rid of it, so replace
> the usage of it with the proper netdev_dbg() or dev_dbg() (depending on the
> context) calls.
There's a missing newline.
There are several dev_err(&intf-dev, ...) to dev_err(dev, ...)
conversions.
Either those should be in a separate patch or you should mention
those changes in the commit message.
> diff --git a/drivers/net/usb/catc.c b/drivers/net/usb/catc.c
> index 26c5beb..6bf5672 100644
> --- a/drivers/net/usb/catc.c
> +++ b/drivers/net/usb/catc.c
> @@ -236,7 +236,8 @@ static void catc_rx_done(struct urb *urb)
> }
>
> if (status) {
> - dbg("rx_done, status %d, length %d", status, urb->actual_length);
> + dev_dbg(&urb->dev->dev, "rx_done, status %d, length %d",
> + status, urb->actual_length);
newline
> @@ -774,7 +783,7 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id
>
> if (usb_set_interface(usbdev,
> intf->altsetting->desc.bInterfaceNumber, 1)) {
> - dev_err(&intf->dev, "Can't set altsetting 1.\n");
> + dev_err(dev, "Can't set altsetting 1.\n");
? Odd conversion.
> diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c
[]
> @@ -787,7 +787,8 @@ static void kaweth_usb_transmit_complete(struct urb *urb)
>
> if (unlikely(status != 0))
> if (status != -ENOENT)
> - dbg("%s: TX status %d.", kaweth->net->name, status);
> + dev_dbg(&urb->dev->dev, "%s: TX status %d.\n",
> + kaweth->net->name, status);
probably
netdev_dbg(kaweth->net, "TX status %d\n", status);
[]
> @@ -1003,36 +1005,37 @@ static int kaweth_probe(
> const struct usb_device_id *id /* from id_table */
> )
> {
> - struct usb_device *dev = interface_to_usbdev(intf);
> + struct device *dev = &intf->dev;
> + struct usb_device *udev = interface_to_usbdev(intf);
Miscellaneous renaming.
[]
> diff --git a/drivers/net/usb/net1080.c b/drivers/net/usb/net1080.c
> index 28c4d51..aad7abe 100644
> --- a/drivers/net/usb/net1080.c
> +++ b/drivers/net/usb/net1080.c
> @@ -156,11 +156,11 @@ static void nc_dump_registers(struct usbnet *dev)
> u16 *vp = kmalloc(sizeof (u16));
>
> if (!vp) {
> - dbg("no memory?");
> + netdev_dbg(dev->net, "no memory?\n");
could delete altogether.
^ permalink raw reply
* Re: Macvtap bug: contractor wanted
From: David Miller @ 2012-09-19 17:54 UTC (permalink / raw)
To: richard, chris; +Cc: netdev, qemu-devel, mst, jasowang, arnd
In-Reply-To: <20120919151133.GA23987@arachsys.com>
Solicitation of paid services or employment is absolutely not
appropriate on the vger.kernel.org mailing lists.
Please do not do this ever again.
^ permalink raw reply
* Re: [RFC] tcp: use order-3 pages in tcp_sendmsg()
From: Eric Dumazet @ 2012-09-19 17:55 UTC (permalink / raw)
To: Rick Jones; +Cc: David Miller, netdev
In-Reply-To: <505A00C8.5050302@hp.com>
On Wed, 2012-09-19 at 10:28 -0700, Rick Jones wrote:
> On 09/19/2012 08:14 AM, Eric Dumazet wrote:
> > I did some tests and got no problem so far, even using splice() [ this
> > one was tricky because it only deals with order-0 pages at this moment ]
> >
> > NIC tested : ixgbe, igb, bnx2x, tg3, mellanox mlx4
> >
> > On loopback, performance of netperf goes from 31900 Mb/s to 38500 Mb/s,
> > thats a 20 % increase.
>
> I guess Brutus will need a new baseline for his TCP Friends patch then :)
>
> BTW, what is the change, if any for TCP_RR?
>
> happy benchmarking,
>
> rick jones
>
No difference, because I already optimized this case last year ;)
commit f07d960df33c5aef8f513efce0fd201f962f94a1
Author: Eric Dumazet <eric.dumazet@gmail.com>
Date: Mon Nov 28 22:41:47 2011 +0000
tcp: avoid frag allocation for small frames
tcp_sendmsg() uses select_size() helper to choose skb head size when a
new skb must be allocated.
If GSO is enabled for the socket, current strategy is to force all
payload data to be outside of headroom, in PAGE fragments.
This strategy is not welcome for small packets, wasting memory.
Experiments show that best results are obtained when using 2048 bytes
for skb head (This includes the skb overhead and various headers)
This patch provides better len/truesize ratios for packets sent to
loopback device, and reduce memory needs for in-flight loopback packets,
particularly on arches with big pages.
If a sender sends many 1-byte packets to an unresponsive application,
receiver rmem_alloc will grow faster and will stop queuing these packets
sooner, or will collapse its receive queue to free excess memory.
netperf -t TCP_RR results are improved by ~4 %, and many workloads are
improved as well (tbench, mysql...)
^ permalink raw reply
* Re: [RFC] tcp: use order-3 pages in tcp_sendmsg()
From: David Miller @ 2012-09-19 17:56 UTC (permalink / raw)
To: eric.dumazet; +Cc: netdev
In-Reply-To: <1348067659.26523.949.camel@edumazet-glaptop>
From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Wed, 19 Sep 2012 17:14:19 +0200
> I did some tests and got no problem so far, even using splice() [ this
> one was tricky because it only deals with order-0 pages at this moment ]
>
> NIC tested : ixgbe, igb, bnx2x, tg3, mellanox mlx4
>
> On loopback, performance of netperf goes from 31900 Mb/s to 38500 Mb/s,
> thats a 20 % increase.
That's really a lot more than I expected, nice.
^ permalink raw reply
* Re: [PATCH net-next] net: more accurate network taps in transmit path
From: David Miller @ 2012-09-19 18:16 UTC (permalink / raw)
To: eric.dumazet; +Cc: jamie.gloudon, netdev
In-Reply-To: <1348037089.26523.397.camel@edumazet-glaptop>
From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Wed, 19 Sep 2012 08:44:49 +0200
> From: Eric Dumazet <edumazet@google.com>
>
> dev_queue_xmit_nit() should be called right before ndo_start_xmit()
> calls or we might give wrong packet contents to taps users :
>
> Packet checksum can be changed, or packet can be linearized or
> segmented, and segments partially sent for the later case.
>
> Also a memory allocation can fail and packet never really hit the
> driver entry point.
>
> Reported-by: Jamie Gloudon <jamie.gloudon@gmail.com>
> Signed-off-by: Eric Dumazet <edumazet@google.com>
Are you really sure that all the network tap implementations can
handle software GSO segmented skbs using skb->next linkage?
Because that is what they can potentially see after this change.
^ permalink raw reply
* Re: [PATCH net-next] net: more accurate network taps in transmit path
From: Eric Dumazet @ 2012-09-19 18:21 UTC (permalink / raw)
To: David Miller; +Cc: jamie.gloudon, netdev
In-Reply-To: <20120919.141637.531173978256020103.davem@davemloft.net>
On Wed, 2012-09-19 at 14:16 -0400, David Miller wrote:
> Are you really sure that all the network tap implementations can
> handle software GSO segmented skbs using skb->next linkage?
>
> Because that is what they can potentially see after this change.
I dont think so, because skb->next is NULL at the points I call the
network tap.
Or did I miss something ?
^ permalink raw reply
* Opportunity to backport pch_gbe patches to stable 3.2.x
From: Erwan Velu @ 2012-09-19 18:41 UTC (permalink / raw)
To: netdev
Hi there,
I'm using on a daily use and in production 3.2.x kernels (.29 currently) on a Kontron Nano-etx board that features the pch_gbe network driver.
I've been experiencing lots of troubles on this kernel series but since I've backported the following commits back to my 3.2.x, it works far better.
So from the history of next the following commits apply perfectly and runs very well.
I do think that other users of pch_gbe will appreciate this.
1a0bdadb4e36abac63b0a9787f372aac30c11a9e
5481c8cd83b4cb0f9f0746e1f477ac231e7eedb6
eefc48b078e1c74c701e8b44a56717418e9cd2bb
93c8acb599b72ca7da42e36d7971a28dce273665
32127a0a0a35706c18df11cd7ad69e96214b3c68
d89bdff152acc0c1e1c8093832547a553b69b45c
62ecc37986414ff98ba863f8f4b8c3fa9c8fb808
3ab77bf271e6a41512e366dfa5110edb981ed1d3
913f53e4c8a464c46a70898c88f2291ade28c196
f2c31662762b9e82b9891d6b385b17f9e5ef0ed2
Cheers,
Erwan
^ permalink raw reply
* Re: [PATCH 1/2] Added information about which firmware file is being requested.
From: Michael Tokarev @ 2012-09-19 18:42 UTC (permalink / raw)
To: Jarl Friis
Cc: Stefano Brivio, Gábor Stefanik, linux-wireless, b43-dev,
netdev, John W. Linville
In-Reply-To: <1348053493-22955-1-git-send-email-jarl@softace.dk>
On 19.09.2012 15:18, Jarl Friis wrote:
> + b43info(ctx->dev->wl, "Requesting firmware file '%s'\n", ctx->fwname);
> err = request_firmware(&blob, ctx->fwname, ctx->dev->dev->dev);
Hmm. I wonder if this should be printed in request_firmware()
itself instead of in all callers?
/mjt
^ permalink raw reply
* Re: [PATCH 2/2] Using LP firmware for taking advantage of the low-power capabilities.
From: Jarl Friis @ 2012-09-19 18:54 UTC (permalink / raw)
To: Larry Finger
Cc: Stefano Brivio, Gábor Stefanik,
netdev-u79uwXL29TY76Z2rM5mHXA,
linux-wireless-u79uwXL29TY76Z2rM5mHXA,
b43-dev-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <5059DFF1.4060405-tQ5ms3gMjBLk1uMJSBkQmQ@public.gmane.org>
Thanks for feed back.
2012/9/19 Larry Finger <Larry.Finger-tQ5ms3gMjBLk1uMJSBkQmQ@public.gmane.org>:
>
>
> I have some questions about this patch. Where did you get the information
> needed to make these changes?
To be completely honest: I didn't get any information, it is based
purely on practical experiments: I experienced some inconsistency wrt.
performance on my hp6735b. I had some time to look at the driver (it's
15 years since I patched the kernel last time). Anyway I saw the
filename pattern for firmware and saw that `b43-fwcutter
broadcom-wl-5.100.138/linux/wl_apsta.o -w` contained similar files
ending on "16". So I simple tried it out (for version 16), and so far
it seems to work better. It also seems to wake up faster after a
sleep.
> Did it come from reverse engineering some
> Broadcom code
No!
> or did you look at their actual code?
No!
> There is a great deal
> of difference relative to our "clean-room" status. Anyone that has seen
> non-GPL Broadcom material cannot contribute code to b43.
I have not seen any Broadcom code at all (apart from the stuff that is
already in the linux source tree)
>
> Have you tested this code on devices with rev>=16?
Yes on my HP6735b having this chip integrated:
[ 1577.549270] b43-phy1: Broadcom 4322 WLAN found (core revision 16)
[ 1577.592117] b43-phy1 debug: Found PHY: Analog 8, Type 4, Revision 4
[ 1577.592158] b43-phy1 debug: Found Radio: Manuf 0x17F, Version
0x2056, Revision 3
I guess the part of the patch for PHY_LP has not been reached. I will
submit a new series of patches that separates things
>
> Now for some comments: This patch also needs the "b43:" added to the
> subject.
Sorry. It's long ago I have submitted patches to the kernel.
> In addition, you appear to have at least one white-space error in
> the MODULE_FIRMWARE line.
I am not sure what you mean here. Is this a mail issue... (I wrote it
just like the other ones around it)
> Is the addition of your copyright to the driver
> warranted by this change?
As far as I understand the copyright law: Yes, but I'm not an expert.
Neither am I 100% sure what you mean.
> For example, I have made much larger contributions
> to b43 over the years before I started doing reverse-engineering on this
> driver, but I never added my copyright.
I suggest you do.
> Your "Signed-off-by" implies
> copyright for the patch.
The fact that I authored the patch implies copyright (even without
Signed-off-by)
Jarl
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 1/2] Added information about which firmware file is being requested.
From: Jarl Friis @ 2012-09-19 18:56 UTC (permalink / raw)
To: Michael Tokarev
Cc: Stefano Brivio, netdev-u79uwXL29TY76Z2rM5mHXA,
linux-wireless-u79uwXL29TY76Z2rM5mHXA,
b43-dev-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <505A1206.4020606-Gdu+ltImwkhes2APU0mLOQ@public.gmane.org>
2012/9/19 Michael Tokarev <mjt-XAri/EZa3C4vJsYlp49lxw@public.gmane.org>:
> On 19.09.2012 15:18, Jarl Friis wrote:
>
>> + b43info(ctx->dev->wl, "Requesting firmware file '%s'\n", ctx->fwname);
>> err = request_firmware(&blob, ctx->fwname, ctx->dev->dev->dev);
>
> Hmm. I wonder if this should be printed in request_firmware()
> itself instead of in all callers?
Now that you mention it, I also think that is a much better idea.
However that would be a much more central place to do the change, so I
would gladly see somebody else do that patch (in replacement of mine)
Jarl
^ permalink raw reply
* Re: [RFC] tcp: use order-3 pages in tcp_sendmsg()
From: Alexander Duyck @ 2012-09-19 19:04 UTC (permalink / raw)
To: David Miller; +Cc: eric.dumazet, netdev
In-Reply-To: <20120919.135655.381209248813843140.davem@davemloft.net>
On 09/19/2012 10:56 AM, David Miller wrote:
> From: Eric Dumazet <eric.dumazet@gmail.com>
> Date: Wed, 19 Sep 2012 17:14:19 +0200
>
>> I did some tests and got no problem so far, even using splice() [ this
>> one was tricky because it only deals with order-0 pages at this moment ]
>>
>> NIC tested : ixgbe, igb, bnx2x, tg3, mellanox mlx4
>>
>> On loopback, performance of netperf goes from 31900 Mb/s to 38500 Mb/s,
>> thats a 20 % increase.
> That's really a lot more than I expected, nice.
When I get some time I will test this patch on a system with an iommu
enabled. I suspect it will have a huge performance impact there since
now you would be looking at roughly 1/8th the total number of map/unmap
calls on a system with 4K pages.
Thanks,
Alex
^ permalink raw reply
* Pull request: sfc-next 2012-09-19
From: Ben Hutchings @ 2012-09-19 19:09 UTC (permalink / raw)
To: David Miller
Cc: Richard Cochran, Rodolfo Giometti, linux-net-drivers, netdev,
Andrew Jackson
The following changes since commit b4516a288e71c64d7e214902250baf78b7b3cdcf:
llc: Remove stray reference to sysctl_llc_station_ack_timeout. (2012-09-17 13:13:24 -0400)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/bwh/sfc-next.git for-davem
(commit 450783747f42dfa3883920acfad4acdd93ce69af)
1. Extension to PPS/PTP to allow for PHC devices where pulses are
subject to a variable but measurable delay.
2. PPS/PTP/PHC support for Solarflare boards with a timestamping
peripheral.
3. MTD support for updating the timestamping peripheral on those boards.
4. Fix for potential over-length requests to firmware.
Ben.
Ben Hutchings (7):
pps/ptp: Allow PHC devices to adjust PPS events for known delay
sfc: Fix maximum array sizes for various MCDI commands
sfc: Convert firmware subtypes to native byte order in efx_mcdi_get_board_cfg()
sfc: Support variable-length response to MCDI GET_BOARD_CFG
sfc: Expose FPGA bitfile partition through MTD
sfc: Bump version to 3.2
sfc: Avoid generating over-length MC_CMD_FLUSH_RX_QUEUES request
Stuart Hodgson (4):
sfc: Add explicit RX queue flag to channel
sfc: Add channel specific receive_skb handler and post_remove callback
sfc: Allow efx_mcdi_rpc to be called in two parts
sfc: Add support for IEEE-1588 PTP
drivers/net/ethernet/sfc/Kconfig | 7 +
drivers/net/ethernet/sfc/Makefile | 1 +
drivers/net/ethernet/sfc/efx.c | 17 +-
drivers/net/ethernet/sfc/efx.h | 1 +
drivers/net/ethernet/sfc/ethtool.c | 1 +
drivers/net/ethernet/sfc/mcdi.c | 49 +-
drivers/net/ethernet/sfc/mcdi.h | 6 +
drivers/net/ethernet/sfc/mcdi_pcol.h | 29 +-
drivers/net/ethernet/sfc/mtd.c | 7 +-
drivers/net/ethernet/sfc/net_driver.h | 29 +-
drivers/net/ethernet/sfc/nic.h | 36 +
drivers/net/ethernet/sfc/ptp.c | 1483 ++++++++++++++++++++++++++++++++
drivers/net/ethernet/sfc/rx.c | 20 +-
drivers/net/ethernet/sfc/siena.c | 1 +
drivers/net/ethernet/sfc/siena_sriov.c | 7 +
drivers/net/ethernet/sfc/tx.c | 6 +
drivers/ptp/ptp_clock.c | 5 +
include/linux/pps_kernel.h | 9 +
include/linux/ptp_clock_kernel.h | 10 +-
19 files changed, 1688 insertions(+), 36 deletions(-)
create mode 100644 drivers/net/ethernet/sfc/ptp.c
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply
* [PATCH net-next 01/11] pps/ptp: Allow PHC devices to adjust PPS events for known delay
From: Ben Hutchings @ 2012-09-19 19:13 UTC (permalink / raw)
To: David Miller
Cc: netdev, linux-net-drivers, Richard Cochran, Rodolfo Giometti,
Andrew Jackson
In-Reply-To: <1348081775.2636.15.camel@bwh-desktop.uk.solarflarecom.com>
Initial version by Stuart Hodgson <smhodgson@solarflare.com>
Some PHC device drivers may deliver PPS events with a significant
and variable delay, but still be able to measure precisely what
that delay is.
Add a pps_sub_ts() function for subtracting a delay from the
timestamp(s) in a PPS event, and a PTP event type (PTP_CLOCK_PPSUSR)
for which the caller provides a complete PPS event.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
drivers/ptp/ptp_clock.c | 5 +++++
include/linux/pps_kernel.h | 9 +++++++++
include/linux/ptp_clock_kernel.h | 10 ++++++++--
3 files changed, 22 insertions(+), 2 deletions(-)
diff --git a/drivers/ptp/ptp_clock.c b/drivers/ptp/ptp_clock.c
index 1e528b5..966875d 100644
--- a/drivers/ptp/ptp_clock.c
+++ b/drivers/ptp/ptp_clock.c
@@ -300,6 +300,11 @@ void ptp_clock_event(struct ptp_clock *ptp, struct ptp_clock_event *event)
pps_get_ts(&evt);
pps_event(ptp->pps_source, &evt, PTP_PPS_EVENT, NULL);
break;
+
+ case PTP_CLOCK_PPSUSR:
+ pps_event(ptp->pps_source, &event->pps_times,
+ PTP_PPS_EVENT, NULL);
+ break;
}
}
EXPORT_SYMBOL(ptp_clock_event);
diff --git a/include/linux/pps_kernel.h b/include/linux/pps_kernel.h
index 9404854..0cc45ae 100644
--- a/include/linux/pps_kernel.h
+++ b/include/linux/pps_kernel.h
@@ -116,5 +116,14 @@ static inline void pps_get_ts(struct pps_event_time *ts)
#endif /* CONFIG_NTP_PPS */
+/* Subtract known time delay from PPS event time(s) */
+static inline void pps_sub_ts(struct pps_event_time *ts, struct timespec delta)
+{
+ ts->ts_real = timespec_sub(ts->ts_real, delta);
+#ifdef CONFIG_NTP_PPS
+ ts->ts_raw = timespec_sub(ts->ts_raw, delta);
+#endif
+}
+
#endif /* LINUX_PPS_KERNEL_H */
diff --git a/include/linux/ptp_clock_kernel.h b/include/linux/ptp_clock_kernel.h
index 945704c..a644b29 100644
--- a/include/linux/ptp_clock_kernel.h
+++ b/include/linux/ptp_clock_kernel.h
@@ -21,6 +21,7 @@
#ifndef _PTP_CLOCK_KERNEL_H_
#define _PTP_CLOCK_KERNEL_H_
+#include <linux/pps_kernel.h>
#include <linux/ptp_clock.h>
@@ -110,6 +111,7 @@ enum ptp_clock_events {
PTP_CLOCK_ALARM,
PTP_CLOCK_EXTTS,
PTP_CLOCK_PPS,
+ PTP_CLOCK_PPSUSR,
};
/**
@@ -117,13 +119,17 @@ enum ptp_clock_events {
*
* @type: One of the ptp_clock_events enumeration values.
* @index: Identifies the source of the event.
- * @timestamp: When the event occured.
+ * @timestamp: When the event occurred (%PTP_CLOCK_EXTTS only).
+ * @pps_times: When the event occurred (%PTP_CLOCK_PPSUSR only).
*/
struct ptp_clock_event {
int type;
int index;
- u64 timestamp;
+ union {
+ u64 timestamp;
+ struct pps_event_time pps_times;
+ };
};
/**
--
1.7.7.6
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply related
* [PATCH net-next 02/11] sfc: Add explicit RX queue flag to channel
From: Ben Hutchings @ 2012-09-19 19:14 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-net-drivers
In-Reply-To: <1348081775.2636.15.camel@bwh-desktop.uk.solarflarecom.com>
The PTP channel will have its own RX queue even though it's not
a regular traffic channel.
Original work by Ben Hutchings <bhutchings@solarflare.com>
Signed-off-by: Stuart Hodgson <smhodgson@solarflare.com>
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
drivers/net/ethernet/sfc/efx.c | 8 +++++++-
drivers/net/ethernet/sfc/net_driver.h | 5 ++++-
drivers/net/ethernet/sfc/rx.c | 7 +++++--
3 files changed, 16 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index a606db4..342a1f3 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -1451,10 +1451,16 @@ static void efx_set_channels(struct efx_nic *efx)
efx->tx_channel_offset =
separate_tx_channels ? efx->n_channels - efx->n_tx_channels : 0;
- /* We need to adjust the TX queue numbers if we have separate
+ /* We need to mark which channels really have RX and TX
+ * queues, and adjust the TX queue numbers if we have separate
* RX-only and TX-only channels.
*/
efx_for_each_channel(channel, efx) {
+ if (channel->channel < efx->n_rx_channels)
+ channel->rx_queue.core_index = channel->channel;
+ else
+ channel->rx_queue.core_index = -1;
+
efx_for_each_channel_tx_queue(tx_queue, channel)
tx_queue->queue -= (efx->tx_channel_offset *
EFX_TXQ_TYPES);
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index 7ab1232..24a78a3 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -242,6 +242,8 @@ struct efx_rx_page_state {
/**
* struct efx_rx_queue - An Efx RX queue
* @efx: The associated Efx NIC
+ * @core_index: Index of network core RX queue. Will be >= 0 iff this
+ * is associated with a real RX queue.
* @buffer: The software buffer ring
* @rxd: The hardware descriptor ring
* @ptr_mask: The size of the ring minus 1.
@@ -263,6 +265,7 @@ struct efx_rx_page_state {
*/
struct efx_rx_queue {
struct efx_nic *efx;
+ int core_index;
struct efx_rx_buffer *buffer;
struct efx_special_buffer rxd;
unsigned int ptr_mask;
@@ -1047,7 +1050,7 @@ static inline bool efx_tx_queue_used(struct efx_tx_queue *tx_queue)
static inline bool efx_channel_has_rx_queue(struct efx_channel *channel)
{
- return channel->channel < channel->efx->n_rx_channels;
+ return channel->rx_queue.core_index >= 0;
}
static inline struct efx_rx_queue *
diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c
index 719319b..e997f83 100644
--- a/drivers/net/ethernet/sfc/rx.c
+++ b/drivers/net/ethernet/sfc/rx.c
@@ -479,7 +479,7 @@ static void efx_rx_packet_gro(struct efx_channel *channel,
skb->ip_summed = ((rx_buf->flags & EFX_RX_PKT_CSUMMED) ?
CHECKSUM_UNNECESSARY : CHECKSUM_NONE);
- skb_record_rx_queue(skb, channel->channel);
+ skb_record_rx_queue(skb, channel->rx_queue.core_index);
gro_result = napi_gro_frags(napi);
} else {
@@ -571,6 +571,9 @@ static void efx_rx_deliver(struct efx_channel *channel,
/* Set the SKB flags */
skb_checksum_none_assert(skb);
+ /* Record the rx_queue */
+ skb_record_rx_queue(skb, channel->rx_queue.core_index);
+
/* Pass the packet up */
netif_receive_skb(skb);
@@ -608,7 +611,7 @@ void __efx_rx_packet(struct efx_channel *channel, struct efx_rx_buffer *rx_buf)
* at the ethernet header */
skb->protocol = eth_type_trans(skb, efx->net_dev);
- skb_record_rx_queue(skb, channel->channel);
+ skb_record_rx_queue(skb, channel->rx_queue.core_index);
}
if (unlikely(!(efx->net_dev->features & NETIF_F_RXCSUM)))
--
1.7.7.6
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox