Commit 62ad6449 authored by Jeff Garzik's avatar Jeff Garzik

Merge pobox.com:/garz/repo/netdev-2.6/misc

into pobox.com:/garz/repo/net-drivers-2.6
parents f1c6586b 76689184
......@@ -209,6 +209,9 @@ static int el3_pm_callback(struct pm_dev *pdev, pm_request_t rqst, void *data);
#if defined(CONFIG_EISA) || defined(CONFIG_MCA)
static int el3_device_remove (struct device *device);
#endif
#ifdef CONFIG_NET_POLL_CONTROLLER
static void el3_poll_controller(struct net_device *dev);
#endif
#ifdef CONFIG_EISA
struct eisa_device_id el3_eisa_ids[] = {
......@@ -321,6 +324,9 @@ static int __init el3_common_init(struct net_device *dev)
dev->set_multicast_list = &set_multicast_list;
dev->tx_timeout = el3_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
#ifdef CONFIG_NET_POLL_CONTROLLER
dev->poll_controller = el3_poll_controller;
#endif
SET_ETHTOOL_OPS(dev, &ethtool_ops);
err = register_netdev(dev);
......@@ -999,6 +1005,19 @@ el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
#ifdef CONFIG_NET_POLL_CONTROLLER
/*
* Polling receive - used by netconsole and other diagnostic tools
* to allow network i/o with interrupts disabled.
*/
static void el3_poll_controller(struct net_device *dev)
{
disable_irq(dev->irq);
el3_interrupt(dev->irq, dev, NULL);
enable_irq(dev->irq);
}
#endif
static struct net_device_stats *
el3_get_stats(struct net_device *dev)
{
......
......@@ -398,6 +398,8 @@ static void cp_clean_rings (struct cp_private *cp);
static struct pci_device_id cp_pci_tbl[] = {
{ PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8139,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
{ PCI_VENDOR_ID_TTTECH, PCI_DEVICE_ID_TTTECH_MC322,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
{ },
};
MODULE_DEVICE_TABLE(pci, cp_pci_tbl);
......
......@@ -81,6 +81,25 @@ int tulip_mdio_read(struct net_device *dev, int phy_id, int location)
return retval & 0xffff;
}
if(tp->chip_id == ULI526X && tp->revision >= 0x40) {
int value;
int i = 1000;
value = ioread32(ioaddr + CSR9);
iowrite32(value & 0xFFEFFFFF, ioaddr + CSR9);
value = (phy_id << 21) | (location << 16) | 0x80000000;
iowrite32(value, ioaddr + CSR10);
while(--i > 0) {
mdio_delay();
if(ioread32(ioaddr + CSR10) & 0x10000000)
break;
}
retval = ioread32(ioaddr + CSR10);
spin_unlock_irqrestore(&tp->mii_lock, flags);
return retval & 0xFFFF;
}
/* Establish sync by sending at least 32 logic ones. */
for (i = 32; i >= 0; i--) {
iowrite32(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr);
......@@ -140,7 +159,23 @@ void tulip_mdio_write(struct net_device *dev, int phy_id, int location, int val)
spin_unlock_irqrestore(&tp->mii_lock, flags);
return;
}
if (tp->chip_id == ULI526X && tp->revision >= 0x40) {
int value;
int i = 1000;
value = ioread32(ioaddr + CSR9);
iowrite32(value & 0xFFEFFFFF, ioaddr + CSR9);
value = (phy_id << 21) | (location << 16) | 0x40000000 | (val & 0xFFFF);
iowrite32(value, ioaddr + CSR10);
while(--i > 0) {
if (ioread32(ioaddr + CSR10) & 0x10000000)
break;
}
spin_unlock_irqrestore(&tp->mii_lock, flags);
}
/* Establish sync by sending 32 logic ones. */
for (i = 32; i >= 0; i--) {
iowrite32(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr);
......
......@@ -39,6 +39,7 @@ void tulip_timer(unsigned long data)
case MX98713:
case COMPEX9881:
case DM910X:
case ULI526X:
default: {
struct medialeaf *mleaf;
unsigned char *p;
......
......@@ -88,6 +88,7 @@ enum chips {
I21145,
DM910X,
CONEXANT,
ULI526X
};
......@@ -481,8 +482,11 @@ static inline void tulip_stop_rxtx(struct tulip_private *tp)
static inline void tulip_restart_rxtx(struct tulip_private *tp)
{
tulip_stop_rxtx(tp);
udelay(5);
if(!(tp->chip_id == ULI526X &&
(tp->revision == 0x40 || tp->revision == 0x50))) {
tulip_stop_rxtx(tp);
udelay(5);
}
tulip_start_rxtx(tp);
}
......
......@@ -88,9 +88,9 @@ static int rx_copybreak = 100;
ToDo: Non-Intel setting could be better.
*/
#if defined(__alpha__) || defined(__ia64__) || defined(__x86_64__)
#if defined(__alpha__) || defined(__ia64__)
static int csr0 = 0x01A00000 | 0xE000;
#elif defined(__i386__) || defined(__powerpc__)
#elif defined(__i386__) || defined(__powerpc__) || defined(__x86_64__)
static int csr0 = 0x01A00000 | 0x8000;
#elif defined(__sparc__) || defined(__hppa__)
/* The UltraSparc PCI controllers will disconnect at every 64-byte
......@@ -198,6 +198,10 @@ struct tulip_chip_table tulip_tbl[] = {
/* RS7112 */
{ "Conexant LANfinity", 256, 0x0001ebef,
HAS_MII | HAS_ACPI, tulip_timer },
/* ULi526X */
{ "ULi M5261/M5263", 128, 0x0001ebef,
HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | HAS_ACPI, tulip_timer },
};
......@@ -229,12 +233,14 @@ static struct pci_device_id tulip_pci_tbl[] = {
{ 0x1113, 0x9511, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
{ 0x1186, 0x1541, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
{ 0x1186, 0x1561, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
{ 0x1186, 0x1591, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
{ 0x14f1, 0x1803, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CONEXANT },
{ 0x1626, 0x8410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
{ 0x1737, 0xAB09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
{ 0x1737, 0xAB08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
{ 0x17B3, 0xAB08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
{ 0x10b9, 0x5261, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DM910X }, /* ALi 1563 integrated ethernet */
{ 0x10b9, 0x5261, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ULI526X }, /* ALi 1563 integrated ethernet */
{ 0x10b9, 0x5263, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ULI526X }, /* ALi 1563 integrated ethernet */
{ 0x10b7, 0x9300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, /* 3Com 3CSOHO100B-TX */
{ } /* terminate list */
};
......@@ -515,7 +521,7 @@ static void tulip_tx_timeout(struct net_device *dev)
dev->name);
} else if (tp->chip_id == DC21140 || tp->chip_id == DC21142
|| tp->chip_id == MX98713 || tp->chip_id == COMPEX9881
|| tp->chip_id == DM910X) {
|| tp->chip_id == DM910X || tp->chip_id == ULI526X) {
printk(KERN_WARNING "%s: 21140 transmit timed out, status %8.8x, "
"SIA %8.8x %8.8x %8.8x %8.8x, resetting...\n",
dev->name, ioread32(ioaddr + CSR5), ioread32(ioaddr + CSR12),
......@@ -1216,6 +1222,22 @@ static void __devinit tulip_mwi_config (struct pci_dev *pdev,
}
#endif
/*
* Chips that have the MRM/reserved bit quirk and the burst quirk. That
* is the DM910X and the on chip ULi devices
*/
static int tulip_uli_dm_quirk(struct pci_dev *pdev)
{
if (pdev->vendor == 0x1282 && pdev->device == 0x9102)
return 1;
if (pdev->vendor == 0x10b9 && pdev->device == 0x5261)
return 1;
if (pdev->vendor == 0x10b9 && pdev->device == 0x5263)
return 1;
return 0;
}
static int __devinit tulip_init_one (struct pci_dev *pdev,
const struct pci_device_id *ent)
{
......@@ -1304,17 +1326,12 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
csr0 &= ~0xfff10000; /* zero reserved bits 31:20, 16 */
/* DM9102A has troubles with MRM & clear reserved bits 24:22, 20, 16, 7:1 */
if ((pdev->vendor == 0x1282 && pdev->device == 0x9102)
|| (pdev->vendor == 0x10b9 && pdev->device == 0x5261))
if (tulip_uli_dm_quirk(pdev)) {
csr0 &= ~0x01f100ff;
#if defined(__sparc__)
/* DM9102A needs 32-dword alignment/burst length on sparc - chip bug? */
if ((pdev->vendor == 0x1282 && pdev->device == 0x9102)
|| (pdev->vendor == 0x10b9 && pdev->device == 0x5261))
csr0 = (csr0 & ~0xff00) | 0xe000;
#endif
}
/*
* And back to business
*/
......@@ -1659,6 +1676,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
switch (chip_idx) {
case DC21140:
case DM910X:
case ULI526X:
default:
if (tp->mtable)
iowrite32(tp->mtable->csr12dir | 0x100, ioaddr + CSR12);
......
......@@ -33,6 +33,13 @@
/* A few user-configurable values. */
#define xircom_debug debug
#ifdef XIRCOM_DEBUG
static int xircom_debug = XIRCOM_DEBUG;
#else
static int xircom_debug = 1;
#endif
/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
static int max_interrupt_work = 25;
......@@ -124,19 +131,11 @@ module_param(max_interrupt_work, int, 0);
module_param(rx_copybreak, int, 0);
module_param(csr0, int, 0);
static int num_units;
module_param_array(options, num_units, int, 0);
module_param_array(full_duplex, num_units, int, 0);
module_param_array(options, int, NULL, 0);
module_param_array(full_duplex, int, NULL, 0);
#define RUN_AT(x) (jiffies + (x))
#define xircom_debug debug
#ifdef XIRCOM_DEBUG
static int xircom_debug = XIRCOM_DEBUG;
#else
static int xircom_debug = 1;
#endif
/*
Theory of Operation
......
......@@ -41,6 +41,7 @@
#include <linux/if_arp.h>
#include <linux/if_ether.h>
#include <linux/if_tun.h>
#include <linux/crc32.h>
#include <asm/system.h>
#include <asm/uaccess.h>
......@@ -104,11 +105,42 @@ static int tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
return 0;
}
static void tun_net_mclist(struct net_device *dev)
/** Add the specified Ethernet address to this multicast filter. */
static void
add_multi(u32* filter, const u8* addr)
{
/* Nothing to do for multicast filters.
* We always accept all frames. */
return;
int bit_nr = ether_crc(ETH_ALEN, addr) >> 26;
filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
}
/** Remove the specified Ethernet addres from this multicast filter. */
static void
del_multi(u32* filter, const u8* addr)
{
int bit_nr = ether_crc(ETH_ALEN, addr) >> 26;
filter[bit_nr >> 5] &= ~(1 << (bit_nr & 31));
}
/** Update the list of multicast groups to which the network device belongs.
* This list is used to filter packets being sent from the character device to
* the network device. */
static void
tun_net_mclist(struct net_device *dev)
{
struct tun_struct *tun = netdev_priv(dev);
const struct dev_mc_list *mclist;
int i;
DBG(KERN_DEBUG "%s: tun_net_mclist: mc_count %d\n",
dev->name, dev->mc_count);
memset(tun->chr_filter, 0, sizeof tun->chr_filter);
for (i = 0, mclist = dev->mc_list; i < dev->mc_count && mclist != NULL;
i++, mclist = mclist->next) {
add_multi(tun->net_filter, mclist->dmi_addr);
DBG(KERN_DEBUG "%s: tun_net_mclist: %x:%x:%x:%x:%x:%x\n",
dev->name,
mclist->dmi_addr[0], mclist->dmi_addr[1], mclist->dmi_addr[2],
mclist->dmi_addr[3], mclist->dmi_addr[4], mclist->dmi_addr[5]);
}
}
static struct net_device_stats *tun_net_stats(struct net_device *dev)
......@@ -301,6 +333,10 @@ static ssize_t tun_chr_readv(struct file *file, const struct iovec *iv,
add_wait_queue(&tun->read_wait, &wait);
while (len) {
const u8 ones[ ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
u8 addr[ ETH_ALEN];
int bit_nr;
current->state = TASK_INTERRUPTIBLE;
/* Read frames from the queue */
......@@ -320,10 +356,37 @@ static ssize_t tun_chr_readv(struct file *file, const struct iovec *iv,
}
netif_start_queue(tun->dev);
ret = tun_put_user(tun, skb, (struct iovec *) iv, len);
kfree_skb(skb);
break;
/** Decide whether to accept this packet. This code is designed to
* behave identically to an Ethernet interface. Accept the packet if
* - we are promiscuous.
* - the packet is addressed to us.
* - the packet is broadcast.
* - the packet is multicast and
* - we are multicast promiscous.
* - we belong to the multicast group.
*/
memcpy(addr, skb->data, min(sizeof addr, skb->len));
bit_nr = ether_crc(sizeof addr, addr) >> 26;
if ((tun->if_flags & IFF_PROMISC) ||
memcmp(addr, tun->dev_addr, sizeof addr) == 0 ||
memcmp(addr, ones, sizeof addr) == 0 ||
(((addr[0] == 1 && addr[1] == 0 && addr[2] == 0x5e) ||
(addr[0] == 0x33 && addr[1] == 0x33)) &&
((tun->if_flags & IFF_ALLMULTI) ||
(tun->chr_filter[bit_nr >> 5] & (1 << (bit_nr & 31)))))) {
DBG(KERN_DEBUG "%s: tun_chr_readv: accepted: %x:%x:%x:%x:%x:%x\n",
tun->dev->name, addr[0], addr[1], addr[2],
addr[3], addr[4], addr[5]);
ret = tun_put_user(tun, skb, (struct iovec *) iv, len);
kfree_skb(skb);
break;
} else {
DBG(KERN_DEBUG "%s: tun_chr_readv: rejected: %x:%x:%x:%x:%x:%x\n",
tun->dev->name, addr[0], addr[1], addr[2],
addr[3], addr[4], addr[5]);
kfree_skb(skb);
continue;
}
}
current->state = TASK_RUNNING;
......@@ -417,6 +480,12 @@ static int tun_set_iff(struct file *file, struct ifreq *ifr)
tun = netdev_priv(dev);
tun->dev = dev;
tun->flags = flags;
/* Be promiscuous by default to maintain previous behaviour. */
tun->if_flags = IFF_PROMISC;
/* Generate random Ethernet address. */
*(u16 *)tun->dev_addr = htons(0x00FF);
get_random_bytes(tun->dev_addr + sizeof(u16), 4);
memset(tun->chr_filter, 0, sizeof tun->chr_filter);
tun_net_init(dev);
......@@ -457,13 +526,16 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct tun_struct *tun = file->private_data;
void __user* argp = (void __user*)arg;
struct ifreq ifr;
if (cmd == TUNSETIFF || _IOC_TYPE(cmd) == 0x89)
if (copy_from_user(&ifr, argp, sizeof ifr))
return -EFAULT;
if (cmd == TUNSETIFF && !tun) {
struct ifreq ifr;
int err;
if (copy_from_user(&ifr, (void __user *)arg, sizeof(ifr)))
return -EFAULT;
ifr.ifr_name[IFNAMSIZ-1] = '\0';
rtnl_lock();
......@@ -473,7 +545,7 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
if (err)
return err;
if (copy_to_user((void __user *)arg, &ifr, sizeof(ifr)))
if (copy_to_user(argp, &ifr, sizeof(ifr)))
return -EFAULT;
return 0;
}
......@@ -519,6 +591,61 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
break;
#endif
case SIOCGIFFLAGS:
ifr.ifr_flags = tun->if_flags;
if (copy_to_user( argp, &ifr, sizeof ifr))
return -EFAULT;
return 0;
case SIOCSIFFLAGS:
/** Set the character device's interface flags. Currently only
* IFF_PROMISC and IFF_ALLMULTI are used. */
tun->if_flags = ifr.ifr_flags;
DBG(KERN_INFO "%s: interface flags 0x%lx\n",
tun->dev->name, tun->if_flags);
return 0;
case SIOCGIFHWADDR:
memcpy(ifr.ifr_hwaddr.sa_data, tun->dev_addr,
min(sizeof ifr.ifr_hwaddr.sa_data, sizeof tun->dev_addr));
if (copy_to_user( argp, &ifr, sizeof ifr))
return -EFAULT;
return 0;
case SIOCSIFHWADDR:
/** Set the character device's hardware address. This is used when
* filtering packets being sent from the network device to the character
* device. */
memcpy(tun->dev_addr, ifr.ifr_hwaddr.sa_data,
min(sizeof ifr.ifr_hwaddr.sa_data, sizeof tun->dev_addr));
DBG(KERN_DEBUG "%s: set hardware address: %x:%x:%x:%x:%x:%x\n",
tun->dev->name,
tun->dev_addr[0], tun->dev_addr[1], tun->dev_addr[2],
tun->dev_addr[3], tun->dev_addr[4], tun->dev_addr[5]);
return 0;
case SIOCADDMULTI:
/** Add the specified group to the character device's multicast filter
* list. */
add_multi(tun->chr_filter, ifr.ifr_hwaddr.sa_data);
DBG(KERN_DEBUG "%s: add multi: %x:%x:%x:%x:%x:%x\n",
tun->dev->name,
(u8)ifr.ifr_hwaddr.sa_data[0], (u8)ifr.ifr_hwaddr.sa_data[1],
(u8)ifr.ifr_hwaddr.sa_data[2], (u8)ifr.ifr_hwaddr.sa_data[3],
(u8)ifr.ifr_hwaddr.sa_data[4], (u8)ifr.ifr_hwaddr.sa_data[5]);
return 0;
case SIOCDELMULTI:
/** Remove the specified group from the character device's multicast
* filter list. */
del_multi(tun->chr_filter, ifr.ifr_hwaddr.sa_data);
DBG(KERN_DEBUG "%s: del multi: %x:%x:%x:%x:%x:%x\n",
tun->dev->name,
(u8)ifr.ifr_hwaddr.sa_data[0], (u8)ifr.ifr_hwaddr.sa_data[1],
(u8)ifr.ifr_hwaddr.sa_data[2], (u8)ifr.ifr_hwaddr.sa_data[3],
(u8)ifr.ifr_hwaddr.sa_data[4], (u8)ifr.ifr_hwaddr.sa_data[5]);
return 0;
default:
return -EINVAL;
};
......
......@@ -859,7 +859,7 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
#ifdef USE_MMIO
memaddr
#else
ioaddr
(long)ioaddr
#endif
);
......
......@@ -100,8 +100,8 @@ MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("VIA Networking Velocity Family Gigabit Ethernet Adapter Driver");
#define VELOCITY_PARAM(N,D) \
static const int N[MAX_UNITS]=OPTION_DEFAULT;\
MODULE_PARM(N, "1-" __MODULE_STRING(MAX_UNITS) "i");\
static int N[MAX_UNITS]=OPTION_DEFAULT;\
module_param_array(N, int, NULL, 0); \
MODULE_PARM_DESC(N, D);
#define RX_DESC_MIN 64
......@@ -229,7 +229,7 @@ VELOCITY_PARAM(wol_opts, "Wake On Lan options");
VELOCITY_PARAM(int_works, "Number of packets per interrupt services");
static int rx_copybreak = 200;
MODULE_PARM(rx_copybreak, "i");
module_param(rx_copybreak, int, 0644);
MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames");
static void velocity_init_info(struct pci_dev *pdev, struct velocity_info *vptr, struct velocity_info_tbl *info);
......
......@@ -45,6 +45,11 @@ struct tun_struct {
struct fasync_struct *fasync;
unsigned long if_flags;
u8 dev_addr[ETH_ALEN];
u32 chr_filter[2];
u32 net_filter[2];
#ifdef TUN_DEBUG
int debug;
#endif
......
......@@ -2397,6 +2397,9 @@
#define PCI_DEVICE_ID_TIGERJET_300 0x0001
#define PCI_DEVICE_ID_TIGERJET_100 0x0002
#define PCI_VENDOR_ID_TTTECH 0x0357
#define PCI_DEVICE_ID_TTTECH_MC322 0x000A
#define PCI_VENDOR_ID_ARK 0xedd8
#define PCI_DEVICE_ID_ARK_STING 0xa091
#define PCI_DEVICE_ID_ARK_STINGARK 0xa099
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment