mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-24 21:20:50 +07:00
Merge branch 'upstream' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6
This commit is contained in:
commit
e5dfa9282f
@ -777,7 +777,7 @@ doing so is the same as described in the "Configuring Multiple Bonds
|
||||
Manually" section, below.
|
||||
|
||||
NOTE: It has been observed that some Red Hat supplied kernels
|
||||
are apparently unable to rename modules at load time (the "-obonding1"
|
||||
are apparently unable to rename modules at load time (the "-o bond1"
|
||||
part). Attempts to pass that option to modprobe will produce an
|
||||
"Operation not permitted" error. This has been reported on some
|
||||
Fedora Core kernels, and has been seen on RHEL 4 as well. On kernels
|
||||
@ -883,7 +883,8 @@ the above does not work, and the second bonding instance never sees
|
||||
its options. In that case, the second options line can be substituted
|
||||
as follows:
|
||||
|
||||
install bonding1 /sbin/modprobe bonding -obond1 mode=balance-alb miimon=50
|
||||
install bond1 /sbin/modprobe --ignore-install bonding -o bond1 \
|
||||
mode=balance-alb miimon=50
|
||||
|
||||
This may be repeated any number of times, specifying a new and
|
||||
unique name in place of bond1 for each subsequent instance.
|
||||
|
@ -1027,8 +1027,7 @@ static void cp_reset_hw (struct cp_private *cp)
|
||||
if (!(cpr8(Cmd) & CmdReset))
|
||||
return;
|
||||
|
||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
schedule_timeout(10);
|
||||
schedule_timeout_uninterruptible(10);
|
||||
}
|
||||
|
||||
printk(KERN_ERR "%s: hardware reset timeout\n", cp->dev->name);
|
||||
@ -1575,6 +1574,7 @@ static struct ethtool_ops cp_ethtool_ops = {
|
||||
.set_wol = cp_set_wol,
|
||||
.get_strings = cp_get_strings,
|
||||
.get_ethtool_stats = cp_get_ethtool_stats,
|
||||
.get_perm_addr = ethtool_op_get_perm_addr,
|
||||
};
|
||||
|
||||
static int cp_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
|
||||
@ -1773,6 +1773,7 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
for (i = 0; i < 3; i++)
|
||||
((u16 *) (dev->dev_addr))[i] =
|
||||
le16_to_cpu (read_eeprom (regs, i + 7, addr_len));
|
||||
memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
|
||||
|
||||
dev->open = cp_open;
|
||||
dev->stop = cp_close;
|
||||
|
@ -552,7 +552,8 @@ const static struct {
|
||||
|
||||
{ "RTL-8100B/8139D",
|
||||
HW_REVID(1, 1, 1, 0, 1, 0, 1),
|
||||
HasLWake,
|
||||
HasHltClk /* XXX undocumented? */
|
||||
| HasLWake,
|
||||
},
|
||||
|
||||
{ "RTL-8101",
|
||||
@ -970,6 +971,7 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
|
||||
for (i = 0; i < 3; i++)
|
||||
((u16 *) (dev->dev_addr))[i] =
|
||||
le16_to_cpu (read_eeprom (ioaddr, i + 7, addr_len));
|
||||
memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
|
||||
|
||||
/* The Rtl8139-specific entries in the device structure. */
|
||||
dev->open = rtl8139_open;
|
||||
@ -2465,6 +2467,7 @@ static struct ethtool_ops rtl8139_ethtool_ops = {
|
||||
.get_strings = rtl8139_get_strings,
|
||||
.get_stats_count = rtl8139_get_stats_count,
|
||||
.get_ethtool_stats = rtl8139_get_ethtool_stats,
|
||||
.get_perm_addr = ethtool_op_get_perm_addr,
|
||||
};
|
||||
|
||||
static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
|
||||
|
@ -475,6 +475,14 @@ config SGI_IOC3_ETH_HW_TX_CSUM
|
||||
the moment only acceleration of IPv4 is supported. This option
|
||||
enables offloading for checksums on transmit. If unsure, say Y.
|
||||
|
||||
config MIPS_SIM_NET
|
||||
tristate "MIPS simulator Network device (EXPERIMENTAL)"
|
||||
depends on NETDEVICES && MIPS_SIM && EXPERIMENTAL
|
||||
help
|
||||
The MIPSNET device is a simple Ethernet network device which is
|
||||
emulated by the MIPS Simulator.
|
||||
If you are not using a MIPSsim or are unsure, say N.
|
||||
|
||||
config SGI_O2MACE_ETH
|
||||
tristate "SGI O2 MACE Fast Ethernet support"
|
||||
depends on NET_ETHERNET && SGI_IP32=y
|
||||
@ -2083,6 +2091,7 @@ config SPIDER_NET
|
||||
config GIANFAR
|
||||
tristate "Gianfar Ethernet"
|
||||
depends on 85xx || 83xx
|
||||
select PHYLIB
|
||||
help
|
||||
This driver supports the Gigabit TSEC on the MPC85xx
|
||||
family of chips, and the FEC on the 8540
|
||||
@ -2243,6 +2252,20 @@ config ISERIES_VETH
|
||||
tristate "iSeries Virtual Ethernet driver support"
|
||||
depends on PPC_ISERIES
|
||||
|
||||
config RIONET
|
||||
tristate "RapidIO Ethernet over messaging driver support"
|
||||
depends on NETDEVICES && RAPIDIO
|
||||
|
||||
config RIONET_TX_SIZE
|
||||
int "Number of outbound queue entries"
|
||||
depends on RIONET
|
||||
default "128"
|
||||
|
||||
config RIONET_RX_SIZE
|
||||
int "Number of inbound queue entries"
|
||||
depends on RIONET
|
||||
default "128"
|
||||
|
||||
config FDDI
|
||||
bool "FDDI driver support"
|
||||
depends on (PCI || EISA)
|
||||
|
@ -13,7 +13,7 @@ obj-$(CONFIG_CHELSIO_T1) += chelsio/
|
||||
obj-$(CONFIG_BONDING) += bonding/
|
||||
obj-$(CONFIG_GIANFAR) += gianfar_driver.o
|
||||
|
||||
gianfar_driver-objs := gianfar.o gianfar_ethtool.o gianfar_phy.o
|
||||
gianfar_driver-objs := gianfar.o gianfar_ethtool.o gianfar_mii.o
|
||||
|
||||
#
|
||||
# link order important here
|
||||
@ -64,6 +64,7 @@ obj-$(CONFIG_SKFP) += skfp/
|
||||
obj-$(CONFIG_VIA_RHINE) += via-rhine.o
|
||||
obj-$(CONFIG_VIA_VELOCITY) += via-velocity.o
|
||||
obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o
|
||||
obj-$(CONFIG_RIONET) += rionet.o
|
||||
|
||||
#
|
||||
# end link order section
|
||||
@ -166,6 +167,7 @@ obj-$(CONFIG_EQUALIZER) += eql.o
|
||||
obj-$(CONFIG_MIPS_JAZZ_SONIC) += jazzsonic.o
|
||||
obj-$(CONFIG_MIPS_GT96100ETH) += gt96100eth.o
|
||||
obj-$(CONFIG_MIPS_AU1X00_ENET) += au1000_eth.o
|
||||
obj-$(CONFIG_MIPS_SIM_NET) += mipsnet.o
|
||||
obj-$(CONFIG_SGI_IOC3_ETH) += ioc3-eth.o
|
||||
obj-$(CONFIG_DECLANCE) += declance.o
|
||||
obj-$(CONFIG_ATARILANCE) += atarilance.o
|
||||
|
@ -151,13 +151,6 @@ struct au1000_private *au_macs[NUM_ETH_INTERFACES];
|
||||
SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | \
|
||||
SUPPORTED_Autoneg
|
||||
|
||||
static char *phy_link[] =
|
||||
{ "unknown",
|
||||
"10Base2", "10BaseT",
|
||||
"AUI",
|
||||
"100BaseT", "100BaseTX", "100BaseFX"
|
||||
};
|
||||
|
||||
int bcm_5201_init(struct net_device *dev, int phy_addr)
|
||||
{
|
||||
s16 data;
|
||||
@ -785,6 +778,7 @@ static struct mii_chip_info {
|
||||
{"Broadcom BCM5201 10/100 BaseT PHY",0x0040,0x6212, &bcm_5201_ops,0},
|
||||
{"Broadcom BCM5221 10/100 BaseT PHY",0x0040,0x61e4, &bcm_5201_ops,0},
|
||||
{"Broadcom BCM5222 10/100 BaseT PHY",0x0040,0x6322, &bcm_5201_ops,1},
|
||||
{"NS DP83847 PHY", 0x2000, 0x5c30, &bcm_5201_ops ,0},
|
||||
{"AMD 79C901 HomePNA PHY",0x0000,0x35c8, &am79c901_ops,0},
|
||||
{"AMD 79C874 10/100 BaseT PHY",0x0022,0x561b, &am79c874_ops,0},
|
||||
{"LSI 80227 10/100 BaseT PHY",0x0016,0xf840, &lsi_80227_ops,0},
|
||||
@ -1045,7 +1039,7 @@ static int mii_probe (struct net_device * dev)
|
||||
#endif
|
||||
|
||||
if (aup->mii->chip_info == NULL) {
|
||||
printk(KERN_ERR "%s: Au1x No MII transceivers found!\n",
|
||||
printk(KERN_ERR "%s: Au1x No known MII transceivers found!\n",
|
||||
dev->name);
|
||||
return -1;
|
||||
}
|
||||
@ -1546,6 +1540,9 @@ au1000_probe(u32 ioaddr, int irq, int port_num)
|
||||
printk(KERN_ERR "%s: out of memory\n", dev->name);
|
||||
goto err_out;
|
||||
}
|
||||
aup->mii->next = NULL;
|
||||
aup->mii->chip_info = NULL;
|
||||
aup->mii->status = 0;
|
||||
aup->mii->mii_control_reg = 0;
|
||||
aup->mii->mii_data_reg = 0;
|
||||
|
||||
|
@ -106,6 +106,29 @@ static int b44_poll(struct net_device *dev, int *budget);
|
||||
static void b44_poll_controller(struct net_device *dev);
|
||||
#endif
|
||||
|
||||
static int dma_desc_align_mask;
|
||||
static int dma_desc_sync_size;
|
||||
|
||||
static inline void b44_sync_dma_desc_for_device(struct pci_dev *pdev,
|
||||
dma_addr_t dma_base,
|
||||
unsigned long offset,
|
||||
enum dma_data_direction dir)
|
||||
{
|
||||
dma_sync_single_range_for_device(&pdev->dev, dma_base,
|
||||
offset & dma_desc_align_mask,
|
||||
dma_desc_sync_size, dir);
|
||||
}
|
||||
|
||||
static inline void b44_sync_dma_desc_for_cpu(struct pci_dev *pdev,
|
||||
dma_addr_t dma_base,
|
||||
unsigned long offset,
|
||||
enum dma_data_direction dir)
|
||||
{
|
||||
dma_sync_single_range_for_cpu(&pdev->dev, dma_base,
|
||||
offset & dma_desc_align_mask,
|
||||
dma_desc_sync_size, dir);
|
||||
}
|
||||
|
||||
static inline unsigned long br32(const struct b44 *bp, unsigned long reg)
|
||||
{
|
||||
return readl(bp->regs + reg);
|
||||
@ -668,6 +691,11 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
|
||||
dp->ctrl = cpu_to_le32(ctrl);
|
||||
dp->addr = cpu_to_le32((u32) mapping + bp->rx_offset + bp->dma_offset);
|
||||
|
||||
if (bp->flags & B44_FLAG_RX_RING_HACK)
|
||||
b44_sync_dma_desc_for_device(bp->pdev, bp->rx_ring_dma,
|
||||
dest_idx * sizeof(dp),
|
||||
DMA_BIDIRECTIONAL);
|
||||
|
||||
return RX_PKT_BUF_SZ;
|
||||
}
|
||||
|
||||
@ -692,6 +720,11 @@ static void b44_recycle_rx(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
|
||||
pci_unmap_addr_set(dest_map, mapping,
|
||||
pci_unmap_addr(src_map, mapping));
|
||||
|
||||
if (bp->flags & B44_FLAG_RX_RING_HACK)
|
||||
b44_sync_dma_desc_for_cpu(bp->pdev, bp->rx_ring_dma,
|
||||
src_idx * sizeof(src_desc),
|
||||
DMA_BIDIRECTIONAL);
|
||||
|
||||
ctrl = src_desc->ctrl;
|
||||
if (dest_idx == (B44_RX_RING_SIZE - 1))
|
||||
ctrl |= cpu_to_le32(DESC_CTRL_EOT);
|
||||
@ -700,8 +733,14 @@ static void b44_recycle_rx(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
|
||||
|
||||
dest_desc->ctrl = ctrl;
|
||||
dest_desc->addr = src_desc->addr;
|
||||
|
||||
src_map->skb = NULL;
|
||||
|
||||
if (bp->flags & B44_FLAG_RX_RING_HACK)
|
||||
b44_sync_dma_desc_for_device(bp->pdev, bp->rx_ring_dma,
|
||||
dest_idx * sizeof(dest_desc),
|
||||
DMA_BIDIRECTIONAL);
|
||||
|
||||
pci_dma_sync_single_for_device(bp->pdev, src_desc->addr,
|
||||
RX_PKT_BUF_SZ,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
@ -959,6 +998,11 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
bp->tx_ring[entry].ctrl = cpu_to_le32(ctrl);
|
||||
bp->tx_ring[entry].addr = cpu_to_le32((u32) mapping+bp->dma_offset);
|
||||
|
||||
if (bp->flags & B44_FLAG_TX_RING_HACK)
|
||||
b44_sync_dma_desc_for_device(bp->pdev, bp->tx_ring_dma,
|
||||
entry * sizeof(bp->tx_ring[0]),
|
||||
DMA_TO_DEVICE);
|
||||
|
||||
entry = NEXT_TX(entry);
|
||||
|
||||
bp->tx_prod = entry;
|
||||
@ -1064,6 +1108,16 @@ static void b44_init_rings(struct b44 *bp)
|
||||
memset(bp->rx_ring, 0, B44_RX_RING_BYTES);
|
||||
memset(bp->tx_ring, 0, B44_TX_RING_BYTES);
|
||||
|
||||
if (bp->flags & B44_FLAG_RX_RING_HACK)
|
||||
dma_sync_single_for_device(&bp->pdev->dev, bp->rx_ring_dma,
|
||||
DMA_TABLE_BYTES,
|
||||
PCI_DMA_BIDIRECTIONAL);
|
||||
|
||||
if (bp->flags & B44_FLAG_TX_RING_HACK)
|
||||
dma_sync_single_for_device(&bp->pdev->dev, bp->tx_ring_dma,
|
||||
DMA_TABLE_BYTES,
|
||||
PCI_DMA_TODEVICE);
|
||||
|
||||
for (i = 0; i < bp->rx_pending; i++) {
|
||||
if (b44_alloc_rx_skb(bp, -1, i) < 0)
|
||||
break;
|
||||
@ -1085,14 +1139,28 @@ static void b44_free_consistent(struct b44 *bp)
|
||||
bp->tx_buffers = NULL;
|
||||
}
|
||||
if (bp->rx_ring) {
|
||||
pci_free_consistent(bp->pdev, DMA_TABLE_BYTES,
|
||||
bp->rx_ring, bp->rx_ring_dma);
|
||||
if (bp->flags & B44_FLAG_RX_RING_HACK) {
|
||||
dma_unmap_single(&bp->pdev->dev, bp->rx_ring_dma,
|
||||
DMA_TABLE_BYTES,
|
||||
DMA_BIDIRECTIONAL);
|
||||
kfree(bp->rx_ring);
|
||||
} else
|
||||
pci_free_consistent(bp->pdev, DMA_TABLE_BYTES,
|
||||
bp->rx_ring, bp->rx_ring_dma);
|
||||
bp->rx_ring = NULL;
|
||||
bp->flags &= ~B44_FLAG_RX_RING_HACK;
|
||||
}
|
||||
if (bp->tx_ring) {
|
||||
pci_free_consistent(bp->pdev, DMA_TABLE_BYTES,
|
||||
bp->tx_ring, bp->tx_ring_dma);
|
||||
if (bp->flags & B44_FLAG_TX_RING_HACK) {
|
||||
dma_unmap_single(&bp->pdev->dev, bp->tx_ring_dma,
|
||||
DMA_TABLE_BYTES,
|
||||
DMA_TO_DEVICE);
|
||||
kfree(bp->tx_ring);
|
||||
} else
|
||||
pci_free_consistent(bp->pdev, DMA_TABLE_BYTES,
|
||||
bp->tx_ring, bp->tx_ring_dma);
|
||||
bp->tx_ring = NULL;
|
||||
bp->flags &= ~B44_FLAG_TX_RING_HACK;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1118,12 +1186,56 @@ static int b44_alloc_consistent(struct b44 *bp)
|
||||
|
||||
size = DMA_TABLE_BYTES;
|
||||
bp->rx_ring = pci_alloc_consistent(bp->pdev, size, &bp->rx_ring_dma);
|
||||
if (!bp->rx_ring)
|
||||
goto out_err;
|
||||
if (!bp->rx_ring) {
|
||||
/* Allocation may have failed due to pci_alloc_consistent
|
||||
insisting on use of GFP_DMA, which is more restrictive
|
||||
than necessary... */
|
||||
struct dma_desc *rx_ring;
|
||||
dma_addr_t rx_ring_dma;
|
||||
|
||||
if (!(rx_ring = (struct dma_desc *)kmalloc(size, GFP_KERNEL)))
|
||||
goto out_err;
|
||||
|
||||
memset(rx_ring, 0, size);
|
||||
rx_ring_dma = dma_map_single(&bp->pdev->dev, rx_ring,
|
||||
DMA_TABLE_BYTES,
|
||||
DMA_BIDIRECTIONAL);
|
||||
|
||||
if (rx_ring_dma + size > B44_DMA_MASK) {
|
||||
kfree(rx_ring);
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
bp->rx_ring = rx_ring;
|
||||
bp->rx_ring_dma = rx_ring_dma;
|
||||
bp->flags |= B44_FLAG_RX_RING_HACK;
|
||||
}
|
||||
|
||||
bp->tx_ring = pci_alloc_consistent(bp->pdev, size, &bp->tx_ring_dma);
|
||||
if (!bp->tx_ring)
|
||||
goto out_err;
|
||||
if (!bp->tx_ring) {
|
||||
/* Allocation may have failed due to pci_alloc_consistent
|
||||
insisting on use of GFP_DMA, which is more restrictive
|
||||
than necessary... */
|
||||
struct dma_desc *tx_ring;
|
||||
dma_addr_t tx_ring_dma;
|
||||
|
||||
if (!(tx_ring = (struct dma_desc *)kmalloc(size, GFP_KERNEL)))
|
||||
goto out_err;
|
||||
|
||||
memset(tx_ring, 0, size);
|
||||
tx_ring_dma = dma_map_single(&bp->pdev->dev, tx_ring,
|
||||
DMA_TABLE_BYTES,
|
||||
DMA_TO_DEVICE);
|
||||
|
||||
if (tx_ring_dma + size > B44_DMA_MASK) {
|
||||
kfree(tx_ring);
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
bp->tx_ring = tx_ring;
|
||||
bp->tx_ring_dma = tx_ring_dma;
|
||||
bp->flags |= B44_FLAG_TX_RING_HACK;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@ -1676,6 +1788,7 @@ static struct ethtool_ops b44_ethtool_ops = {
|
||||
.set_pauseparam = b44_set_pauseparam,
|
||||
.get_msglevel = b44_get_msglevel,
|
||||
.set_msglevel = b44_set_msglevel,
|
||||
.get_perm_addr = ethtool_op_get_perm_addr,
|
||||
};
|
||||
|
||||
static int b44_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
|
||||
@ -1718,6 +1831,7 @@ static int __devinit b44_get_invariants(struct b44 *bp)
|
||||
bp->dev->dev_addr[3] = eeprom[80];
|
||||
bp->dev->dev_addr[4] = eeprom[83];
|
||||
bp->dev->dev_addr[5] = eeprom[82];
|
||||
memcpy(bp->dev->perm_addr, bp->dev->dev_addr, bp->dev->addr_len);
|
||||
|
||||
bp->phy_addr = eeprom[90] & 0x1f;
|
||||
|
||||
@ -1971,6 +2085,12 @@ static struct pci_driver b44_driver = {
|
||||
|
||||
static int __init b44_init(void)
|
||||
{
|
||||
unsigned int dma_desc_align_size = dma_get_cache_alignment();
|
||||
|
||||
/* Setup paramaters for syncing RX/TX DMA descriptors */
|
||||
dma_desc_align_mask = ~(dma_desc_align_size - 1);
|
||||
dma_desc_sync_size = max(dma_desc_align_size, sizeof(struct dma_desc));
|
||||
|
||||
return pci_module_init(&b44_driver);
|
||||
}
|
||||
|
||||
|
@ -400,6 +400,8 @@ struct b44 {
|
||||
#define B44_FLAG_ADV_100HALF 0x04000000
|
||||
#define B44_FLAG_ADV_100FULL 0x08000000
|
||||
#define B44_FLAG_INTERNAL_PHY 0x10000000
|
||||
#define B44_FLAG_RX_RING_HACK 0x20000000
|
||||
#define B44_FLAG_TX_RING_HACK 0x40000000
|
||||
|
||||
u32 rx_offset;
|
||||
|
||||
|
@ -4241,6 +4241,43 @@ static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *bond_dev
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bond_activebackup_xmit_copy(struct sk_buff *skb,
|
||||
struct bonding *bond,
|
||||
struct slave *slave)
|
||||
{
|
||||
struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
|
||||
struct ethhdr *eth_data;
|
||||
u8 *hwaddr;
|
||||
int res;
|
||||
|
||||
if (!skb2) {
|
||||
printk(KERN_ERR DRV_NAME ": Error: "
|
||||
"bond_activebackup_xmit_copy(): skb_copy() failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
skb2->mac.raw = (unsigned char *)skb2->data;
|
||||
eth_data = eth_hdr(skb2);
|
||||
|
||||
/* Pick an appropriate source MAC address
|
||||
* -- use slave's perm MAC addr, unless used by bond
|
||||
* -- otherwise, borrow active slave's perm MAC addr
|
||||
* since that will not be used
|
||||
*/
|
||||
hwaddr = slave->perm_hwaddr;
|
||||
if (!memcmp(eth_data->h_source, hwaddr, ETH_ALEN))
|
||||
hwaddr = bond->curr_active_slave->perm_hwaddr;
|
||||
|
||||
/* Set source MAC address appropriately */
|
||||
memcpy(eth_data->h_source, hwaddr, ETH_ALEN);
|
||||
|
||||
res = bond_dev_queue_xmit(bond, skb2, slave->dev);
|
||||
if (res)
|
||||
dev_kfree_skb(skb2);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* in active-backup mode, we know that bond->curr_active_slave is always valid if
|
||||
* the bond has a usable interface.
|
||||
@ -4257,10 +4294,26 @@ static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *bond_d
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (bond->curr_active_slave) { /* one usable interface */
|
||||
res = bond_dev_queue_xmit(bond, skb, bond->curr_active_slave->dev);
|
||||
if (!bond->curr_active_slave)
|
||||
goto out;
|
||||
|
||||
/* Xmit IGMP frames on all slaves to ensure rapid fail-over
|
||||
for multicast traffic on snooping switches */
|
||||
if (skb->protocol == __constant_htons(ETH_P_IP) &&
|
||||
skb->nh.iph->protocol == IPPROTO_IGMP) {
|
||||
struct slave *slave, *active_slave;
|
||||
int i;
|
||||
|
||||
active_slave = bond->curr_active_slave;
|
||||
bond_for_each_slave_from_to(bond, slave, i, active_slave->next,
|
||||
active_slave->prev)
|
||||
if (IS_UP(slave->dev) &&
|
||||
(slave->link == BOND_LINK_UP))
|
||||
bond_activebackup_xmit_copy(skb, bond, slave);
|
||||
}
|
||||
|
||||
res = bond_dev_queue_xmit(bond, skb, bond->curr_active_slave->dev);
|
||||
|
||||
out:
|
||||
if (res) {
|
||||
/* no suitable interface, frame not sent */
|
||||
|
@ -5,7 +5,7 @@
|
||||
*
|
||||
* adopted from sunlance.c by Richard van den Berg
|
||||
*
|
||||
* Copyright (C) 2002, 2003 Maciej W. Rozycki
|
||||
* Copyright (C) 2002, 2003, 2005 Maciej W. Rozycki
|
||||
*
|
||||
* additional sources:
|
||||
* - PMAD-AA TURBOchannel Ethernet Module Functional Specification,
|
||||
@ -57,13 +57,15 @@
|
||||
#include <linux/string.h>
|
||||
|
||||
#include <asm/addrspace.h>
|
||||
#include <asm/system.h>
|
||||
|
||||
#include <asm/dec/interrupts.h>
|
||||
#include <asm/dec/ioasic.h>
|
||||
#include <asm/dec/ioasic_addrs.h>
|
||||
#include <asm/dec/kn01.h>
|
||||
#include <asm/dec/machtype.h>
|
||||
#include <asm/dec/system.h>
|
||||
#include <asm/dec/tc.h>
|
||||
#include <asm/system.h>
|
||||
|
||||
static char version[] __devinitdata =
|
||||
"declance.c: v0.009 by Linux MIPS DECstation task force\n";
|
||||
@ -79,10 +81,6 @@ MODULE_LICENSE("GPL");
|
||||
#define PMAD_LANCE 2
|
||||
#define PMAX_LANCE 3
|
||||
|
||||
#ifndef CONFIG_TC
|
||||
unsigned long system_base;
|
||||
unsigned long dmaptr;
|
||||
#endif
|
||||
|
||||
#define LE_CSR0 0
|
||||
#define LE_CSR1 1
|
||||
@ -237,7 +235,7 @@ struct lance_init_block {
|
||||
/*
|
||||
* This works *only* for the ring descriptors
|
||||
*/
|
||||
#define LANCE_ADDR(x) (PHYSADDR(x) >> 1)
|
||||
#define LANCE_ADDR(x) (CPHYSADDR(x) >> 1)
|
||||
|
||||
struct lance_private {
|
||||
struct net_device *next;
|
||||
@ -697,12 +695,13 @@ static void lance_tx(struct net_device *dev)
|
||||
spin_unlock(&lp->lock);
|
||||
}
|
||||
|
||||
static void lance_dma_merr_int(const int irq, void *dev_id,
|
||||
struct pt_regs *regs)
|
||||
static irqreturn_t lance_dma_merr_int(const int irq, void *dev_id,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
struct net_device *dev = (struct net_device *) dev_id;
|
||||
|
||||
printk("%s: DMA error\n", dev->name);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t
|
||||
@ -1026,10 +1025,6 @@ static int __init dec_lance_init(const int type, const int slot)
|
||||
unsigned long esar_base;
|
||||
unsigned char *esar;
|
||||
|
||||
#ifndef CONFIG_TC
|
||||
system_base = KN01_LANCE_BASE;
|
||||
#endif
|
||||
|
||||
if (dec_lance_debug && version_printed++ == 0)
|
||||
printk(version);
|
||||
|
||||
@ -1062,16 +1057,16 @@ static int __init dec_lance_init(const int type, const int slot)
|
||||
switch (type) {
|
||||
#ifdef CONFIG_TC
|
||||
case ASIC_LANCE:
|
||||
dev->base_addr = system_base + IOASIC_LANCE;
|
||||
dev->base_addr = CKSEG1ADDR(dec_kn_slot_base + IOASIC_LANCE);
|
||||
|
||||
/* buffer space for the on-board LANCE shared memory */
|
||||
/*
|
||||
* FIXME: ugly hack!
|
||||
*/
|
||||
dev->mem_start = KSEG1ADDR(0x00020000);
|
||||
dev->mem_start = CKSEG1ADDR(0x00020000);
|
||||
dev->mem_end = dev->mem_start + 0x00020000;
|
||||
dev->irq = dec_interrupt[DEC_IRQ_LANCE];
|
||||
esar_base = system_base + IOASIC_ESAR;
|
||||
esar_base = CKSEG1ADDR(dec_kn_slot_base + IOASIC_ESAR);
|
||||
|
||||
/* Workaround crash with booting KN04 2.1k from Disk */
|
||||
memset((void *)dev->mem_start, 0,
|
||||
@ -1101,14 +1096,14 @@ static int __init dec_lance_init(const int type, const int slot)
|
||||
/* Setup I/O ASIC LANCE DMA. */
|
||||
lp->dma_irq = dec_interrupt[DEC_IRQ_LANCE_MERR];
|
||||
ioasic_write(IO_REG_LANCE_DMA_P,
|
||||
PHYSADDR(dev->mem_start) << 3);
|
||||
CPHYSADDR(dev->mem_start) << 3);
|
||||
|
||||
break;
|
||||
|
||||
case PMAD_LANCE:
|
||||
claim_tc_card(slot);
|
||||
|
||||
dev->mem_start = get_tc_base_addr(slot);
|
||||
dev->mem_start = CKSEG1ADDR(get_tc_base_addr(slot));
|
||||
dev->base_addr = dev->mem_start + 0x100000;
|
||||
dev->irq = get_tc_irq_nr(slot);
|
||||
esar_base = dev->mem_start + 0x1c0002;
|
||||
@ -1137,9 +1132,9 @@ static int __init dec_lance_init(const int type, const int slot)
|
||||
|
||||
case PMAX_LANCE:
|
||||
dev->irq = dec_interrupt[DEC_IRQ_LANCE];
|
||||
dev->base_addr = KN01_LANCE_BASE;
|
||||
dev->mem_start = KN01_LANCE_BASE + 0x01000000;
|
||||
esar_base = KN01_RTC_BASE + 1;
|
||||
dev->base_addr = CKSEG1ADDR(KN01_SLOT_BASE + KN01_LANCE);
|
||||
dev->mem_start = CKSEG1ADDR(KN01_SLOT_BASE + KN01_LANCE_MEM);
|
||||
esar_base = CKSEG1ADDR(KN01_SLOT_BASE + KN01_ESAR + 1);
|
||||
lp->dma_irq = -1;
|
||||
|
||||
/*
|
||||
|
@ -2201,6 +2201,7 @@ static struct ethtool_ops e100_ethtool_ops = {
|
||||
.phys_id = e100_phys_id,
|
||||
.get_stats_count = e100_get_stats_count,
|
||||
.get_ethtool_stats = e100_get_ethtool_stats,
|
||||
.get_perm_addr = ethtool_op_get_perm_addr,
|
||||
};
|
||||
|
||||
static int e100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
|
||||
@ -2351,7 +2352,8 @@ static int __devinit e100_probe(struct pci_dev *pdev,
|
||||
e100_phy_init(nic);
|
||||
|
||||
memcpy(netdev->dev_addr, nic->eeprom, ETH_ALEN);
|
||||
if(!is_valid_ether_addr(netdev->dev_addr)) {
|
||||
memcpy(netdev->perm_addr, nic->eeprom, ETH_ALEN);
|
||||
if(!is_valid_ether_addr(netdev->perm_addr)) {
|
||||
DPRINTK(PROBE, ERR, "Invalid MAC address from "
|
||||
"EEPROM, aborting.\n");
|
||||
err = -EAGAIN;
|
||||
|
@ -72,6 +72,10 @@
|
||||
#include <linux/mii.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/if_vlan.h>
|
||||
#ifdef CONFIG_E1000_MQ
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/smp.h>
|
||||
#endif
|
||||
|
||||
#define BAR_0 0
|
||||
#define BAR_1 1
|
||||
@ -165,10 +169,33 @@ struct e1000_buffer {
|
||||
uint16_t next_to_watch;
|
||||
};
|
||||
|
||||
struct e1000_ps_page { struct page *ps_page[MAX_PS_BUFFERS]; };
|
||||
struct e1000_ps_page_dma { uint64_t ps_page_dma[MAX_PS_BUFFERS]; };
|
||||
struct e1000_ps_page { struct page *ps_page[PS_PAGE_BUFFERS]; };
|
||||
struct e1000_ps_page_dma { uint64_t ps_page_dma[PS_PAGE_BUFFERS]; };
|
||||
|
||||
struct e1000_desc_ring {
|
||||
struct e1000_tx_ring {
|
||||
/* pointer to the descriptor ring memory */
|
||||
void *desc;
|
||||
/* physical address of the descriptor ring */
|
||||
dma_addr_t dma;
|
||||
/* length of descriptor ring in bytes */
|
||||
unsigned int size;
|
||||
/* number of descriptors in the ring */
|
||||
unsigned int count;
|
||||
/* next descriptor to associate a buffer with */
|
||||
unsigned int next_to_use;
|
||||
/* next descriptor to check for DD status bit */
|
||||
unsigned int next_to_clean;
|
||||
/* array of buffer information structs */
|
||||
struct e1000_buffer *buffer_info;
|
||||
|
||||
struct e1000_buffer previous_buffer_info;
|
||||
spinlock_t tx_lock;
|
||||
uint16_t tdh;
|
||||
uint16_t tdt;
|
||||
uint64_t pkt;
|
||||
};
|
||||
|
||||
struct e1000_rx_ring {
|
||||
/* pointer to the descriptor ring memory */
|
||||
void *desc;
|
||||
/* physical address of the descriptor ring */
|
||||
@ -186,6 +213,10 @@ struct e1000_desc_ring {
|
||||
/* arrays of page information for packet split */
|
||||
struct e1000_ps_page *ps_page;
|
||||
struct e1000_ps_page_dma *ps_page_dma;
|
||||
|
||||
uint16_t rdh;
|
||||
uint16_t rdt;
|
||||
uint64_t pkt;
|
||||
};
|
||||
|
||||
#define E1000_DESC_UNUSED(R) \
|
||||
@ -227,9 +258,10 @@ struct e1000_adapter {
|
||||
unsigned long led_status;
|
||||
|
||||
/* TX */
|
||||
struct e1000_desc_ring tx_ring;
|
||||
struct e1000_buffer previous_buffer_info;
|
||||
spinlock_t tx_lock;
|
||||
struct e1000_tx_ring *tx_ring; /* One per active queue */
|
||||
#ifdef CONFIG_E1000_MQ
|
||||
struct e1000_tx_ring **cpu_tx_ring; /* per-cpu */
|
||||
#endif
|
||||
uint32_t txd_cmd;
|
||||
uint32_t tx_int_delay;
|
||||
uint32_t tx_abs_int_delay;
|
||||
@ -246,19 +278,33 @@ struct e1000_adapter {
|
||||
|
||||
/* RX */
|
||||
#ifdef CONFIG_E1000_NAPI
|
||||
boolean_t (*clean_rx) (struct e1000_adapter *adapter, int *work_done,
|
||||
int work_to_do);
|
||||
boolean_t (*clean_rx) (struct e1000_adapter *adapter,
|
||||
struct e1000_rx_ring *rx_ring,
|
||||
int *work_done, int work_to_do);
|
||||
#else
|
||||
boolean_t (*clean_rx) (struct e1000_adapter *adapter);
|
||||
boolean_t (*clean_rx) (struct e1000_adapter *adapter,
|
||||
struct e1000_rx_ring *rx_ring);
|
||||
#endif
|
||||
void (*alloc_rx_buf) (struct e1000_adapter *adapter);
|
||||
struct e1000_desc_ring rx_ring;
|
||||
void (*alloc_rx_buf) (struct e1000_adapter *adapter,
|
||||
struct e1000_rx_ring *rx_ring);
|
||||
struct e1000_rx_ring *rx_ring; /* One per active queue */
|
||||
#ifdef CONFIG_E1000_NAPI
|
||||
struct net_device *polling_netdev; /* One per active queue */
|
||||
#endif
|
||||
#ifdef CONFIG_E1000_MQ
|
||||
struct net_device **cpu_netdev; /* per-cpu */
|
||||
struct call_async_data_struct rx_sched_call_data;
|
||||
int cpu_for_queue[4];
|
||||
#endif
|
||||
int num_queues;
|
||||
|
||||
uint64_t hw_csum_err;
|
||||
uint64_t hw_csum_good;
|
||||
uint64_t rx_hdr_split;
|
||||
uint32_t rx_int_delay;
|
||||
uint32_t rx_abs_int_delay;
|
||||
boolean_t rx_csum;
|
||||
boolean_t rx_ps;
|
||||
unsigned int rx_ps_pages;
|
||||
uint32_t gorcl;
|
||||
uint64_t gorcl_old;
|
||||
uint16_t rx_ps_bsize0;
|
||||
@ -278,8 +324,8 @@ struct e1000_adapter {
|
||||
struct e1000_phy_stats phy_stats;
|
||||
|
||||
uint32_t test_icr;
|
||||
struct e1000_desc_ring test_tx_ring;
|
||||
struct e1000_desc_ring test_rx_ring;
|
||||
struct e1000_tx_ring test_tx_ring;
|
||||
struct e1000_rx_ring test_rx_ring;
|
||||
|
||||
|
||||
int msg_enable;
|
||||
|
@ -39,10 +39,10 @@ extern int e1000_up(struct e1000_adapter *adapter);
|
||||
extern void e1000_down(struct e1000_adapter *adapter);
|
||||
extern void e1000_reset(struct e1000_adapter *adapter);
|
||||
extern int e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx);
|
||||
extern int e1000_setup_rx_resources(struct e1000_adapter *adapter);
|
||||
extern int e1000_setup_tx_resources(struct e1000_adapter *adapter);
|
||||
extern void e1000_free_rx_resources(struct e1000_adapter *adapter);
|
||||
extern void e1000_free_tx_resources(struct e1000_adapter *adapter);
|
||||
extern int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
|
||||
extern int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
|
||||
extern void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
|
||||
extern void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
|
||||
extern void e1000_update_stats(struct e1000_adapter *adapter);
|
||||
|
||||
struct e1000_stats {
|
||||
@ -91,7 +91,8 @@ static const struct e1000_stats e1000_gstrings_stats[] = {
|
||||
{ "tx_flow_control_xoff", E1000_STAT(stats.xofftxc) },
|
||||
{ "rx_long_byte_count", E1000_STAT(stats.gorcl) },
|
||||
{ "rx_csum_offload_good", E1000_STAT(hw_csum_good) },
|
||||
{ "rx_csum_offload_errors", E1000_STAT(hw_csum_err) }
|
||||
{ "rx_csum_offload_errors", E1000_STAT(hw_csum_err) },
|
||||
{ "rx_header_split", E1000_STAT(rx_hdr_split) },
|
||||
};
|
||||
#define E1000_STATS_LEN \
|
||||
sizeof(e1000_gstrings_stats) / sizeof(struct e1000_stats)
|
||||
@ -546,8 +547,10 @@ e1000_set_eeprom(struct net_device *netdev,
|
||||
ret_val = e1000_write_eeprom(hw, first_word,
|
||||
last_word - first_word + 1, eeprom_buff);
|
||||
|
||||
/* Update the checksum over the first part of the EEPROM if needed */
|
||||
if((ret_val == 0) && first_word <= EEPROM_CHECKSUM_REG)
|
||||
/* Update the checksum over the first part of the EEPROM if needed
|
||||
* and flush shadow RAM for 82573 conrollers */
|
||||
if((ret_val == 0) && ((first_word <= EEPROM_CHECKSUM_REG) ||
|
||||
(hw->mac_type == e1000_82573)))
|
||||
e1000_update_eeprom_checksum(hw);
|
||||
|
||||
kfree(eeprom_buff);
|
||||
@ -576,8 +579,8 @@ e1000_get_ringparam(struct net_device *netdev,
|
||||
{
|
||||
struct e1000_adapter *adapter = netdev_priv(netdev);
|
||||
e1000_mac_type mac_type = adapter->hw.mac_type;
|
||||
struct e1000_desc_ring *txdr = &adapter->tx_ring;
|
||||
struct e1000_desc_ring *rxdr = &adapter->rx_ring;
|
||||
struct e1000_tx_ring *txdr = adapter->tx_ring;
|
||||
struct e1000_rx_ring *rxdr = adapter->rx_ring;
|
||||
|
||||
ring->rx_max_pending = (mac_type < e1000_82544) ? E1000_MAX_RXD :
|
||||
E1000_MAX_82544_RXD;
|
||||
@ -597,20 +600,40 @@ e1000_set_ringparam(struct net_device *netdev,
|
||||
{
|
||||
struct e1000_adapter *adapter = netdev_priv(netdev);
|
||||
e1000_mac_type mac_type = adapter->hw.mac_type;
|
||||
struct e1000_desc_ring *txdr = &adapter->tx_ring;
|
||||
struct e1000_desc_ring *rxdr = &adapter->rx_ring;
|
||||
struct e1000_desc_ring tx_old, tx_new, rx_old, rx_new;
|
||||
int err;
|
||||
struct e1000_tx_ring *txdr, *tx_old, *tx_new;
|
||||
struct e1000_rx_ring *rxdr, *rx_old, *rx_new;
|
||||
int i, err, tx_ring_size, rx_ring_size;
|
||||
|
||||
tx_ring_size = sizeof(struct e1000_tx_ring) * adapter->num_queues;
|
||||
rx_ring_size = sizeof(struct e1000_rx_ring) * adapter->num_queues;
|
||||
|
||||
if (netif_running(adapter->netdev))
|
||||
e1000_down(adapter);
|
||||
|
||||
tx_old = adapter->tx_ring;
|
||||
rx_old = adapter->rx_ring;
|
||||
|
||||
adapter->tx_ring = kmalloc(tx_ring_size, GFP_KERNEL);
|
||||
if (!adapter->tx_ring) {
|
||||
err = -ENOMEM;
|
||||
goto err_setup_rx;
|
||||
}
|
||||
memset(adapter->tx_ring, 0, tx_ring_size);
|
||||
|
||||
adapter->rx_ring = kmalloc(rx_ring_size, GFP_KERNEL);
|
||||
if (!adapter->rx_ring) {
|
||||
kfree(adapter->tx_ring);
|
||||
err = -ENOMEM;
|
||||
goto err_setup_rx;
|
||||
}
|
||||
memset(adapter->rx_ring, 0, rx_ring_size);
|
||||
|
||||
txdr = adapter->tx_ring;
|
||||
rxdr = adapter->rx_ring;
|
||||
|
||||
if((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
|
||||
return -EINVAL;
|
||||
|
||||
if(netif_running(adapter->netdev))
|
||||
e1000_down(adapter);
|
||||
|
||||
rxdr->count = max(ring->rx_pending,(uint32_t)E1000_MIN_RXD);
|
||||
rxdr->count = min(rxdr->count,(uint32_t)(mac_type < e1000_82544 ?
|
||||
E1000_MAX_RXD : E1000_MAX_82544_RXD));
|
||||
@ -621,11 +644,16 @@ e1000_set_ringparam(struct net_device *netdev,
|
||||
E1000_MAX_TXD : E1000_MAX_82544_TXD));
|
||||
E1000_ROUNDUP(txdr->count, REQ_TX_DESCRIPTOR_MULTIPLE);
|
||||
|
||||
for (i = 0; i < adapter->num_queues; i++) {
|
||||
txdr[i].count = txdr->count;
|
||||
rxdr[i].count = rxdr->count;
|
||||
}
|
||||
|
||||
if(netif_running(adapter->netdev)) {
|
||||
/* Try to get new resources before deleting old */
|
||||
if((err = e1000_setup_rx_resources(adapter)))
|
||||
if ((err = e1000_setup_all_rx_resources(adapter)))
|
||||
goto err_setup_rx;
|
||||
if((err = e1000_setup_tx_resources(adapter)))
|
||||
if ((err = e1000_setup_all_tx_resources(adapter)))
|
||||
goto err_setup_tx;
|
||||
|
||||
/* save the new, restore the old in order to free it,
|
||||
@ -635,8 +663,10 @@ e1000_set_ringparam(struct net_device *netdev,
|
||||
tx_new = adapter->tx_ring;
|
||||
adapter->rx_ring = rx_old;
|
||||
adapter->tx_ring = tx_old;
|
||||
e1000_free_rx_resources(adapter);
|
||||
e1000_free_tx_resources(adapter);
|
||||
e1000_free_all_rx_resources(adapter);
|
||||
e1000_free_all_tx_resources(adapter);
|
||||
kfree(tx_old);
|
||||
kfree(rx_old);
|
||||
adapter->rx_ring = rx_new;
|
||||
adapter->tx_ring = tx_new;
|
||||
if((err = e1000_up(adapter)))
|
||||
@ -645,7 +675,7 @@ e1000_set_ringparam(struct net_device *netdev,
|
||||
|
||||
return 0;
|
||||
err_setup_tx:
|
||||
e1000_free_rx_resources(adapter);
|
||||
e1000_free_all_rx_resources(adapter);
|
||||
err_setup_rx:
|
||||
adapter->rx_ring = rx_old;
|
||||
adapter->tx_ring = tx_old;
|
||||
@ -696,6 +726,11 @@ e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data)
|
||||
* Some bits that get toggled are ignored.
|
||||
*/
|
||||
switch (adapter->hw.mac_type) {
|
||||
/* there are several bits on newer hardware that are r/w */
|
||||
case e1000_82571:
|
||||
case e1000_82572:
|
||||
toggle = 0x7FFFF3FF;
|
||||
break;
|
||||
case e1000_82573:
|
||||
toggle = 0x7FFFF033;
|
||||
break;
|
||||
@ -898,8 +933,8 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
|
||||
static void
|
||||
e1000_free_desc_rings(struct e1000_adapter *adapter)
|
||||
{
|
||||
struct e1000_desc_ring *txdr = &adapter->test_tx_ring;
|
||||
struct e1000_desc_ring *rxdr = &adapter->test_rx_ring;
|
||||
struct e1000_tx_ring *txdr = &adapter->test_tx_ring;
|
||||
struct e1000_rx_ring *rxdr = &adapter->test_rx_ring;
|
||||
struct pci_dev *pdev = adapter->pdev;
|
||||
int i;
|
||||
|
||||
@ -941,8 +976,8 @@ e1000_free_desc_rings(struct e1000_adapter *adapter)
|
||||
static int
|
||||
e1000_setup_desc_rings(struct e1000_adapter *adapter)
|
||||
{
|
||||
struct e1000_desc_ring *txdr = &adapter->test_tx_ring;
|
||||
struct e1000_desc_ring *rxdr = &adapter->test_rx_ring;
|
||||
struct e1000_tx_ring *txdr = &adapter->test_tx_ring;
|
||||
struct e1000_rx_ring *rxdr = &adapter->test_rx_ring;
|
||||
struct pci_dev *pdev = adapter->pdev;
|
||||
uint32_t rctl;
|
||||
int size, i, ret_val;
|
||||
@ -1245,6 +1280,8 @@ e1000_set_phy_loopback(struct e1000_adapter *adapter)
|
||||
case e1000_82541_rev_2:
|
||||
case e1000_82547:
|
||||
case e1000_82547_rev_2:
|
||||
case e1000_82571:
|
||||
case e1000_82572:
|
||||
case e1000_82573:
|
||||
return e1000_integrated_phy_loopback(adapter);
|
||||
break;
|
||||
@ -1340,8 +1377,8 @@ e1000_check_lbtest_frame(struct sk_buff *skb, unsigned int frame_size)
|
||||
static int
|
||||
e1000_run_loopback_test(struct e1000_adapter *adapter)
|
||||
{
|
||||
struct e1000_desc_ring *txdr = &adapter->test_tx_ring;
|
||||
struct e1000_desc_ring *rxdr = &adapter->test_rx_ring;
|
||||
struct e1000_tx_ring *txdr = &adapter->test_tx_ring;
|
||||
struct e1000_rx_ring *rxdr = &adapter->test_rx_ring;
|
||||
struct pci_dev *pdev = adapter->pdev;
|
||||
int i, j, k, l, lc, good_cnt, ret_val=0;
|
||||
unsigned long time;
|
||||
@ -1509,6 +1546,7 @@ e1000_diag_test(struct net_device *netdev,
|
||||
data[2] = 0;
|
||||
data[3] = 0;
|
||||
}
|
||||
msleep_interruptible(4 * 1000);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1625,7 +1663,7 @@ e1000_phys_id(struct net_device *netdev, uint32_t data)
|
||||
if(!data || data > (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ))
|
||||
data = (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ);
|
||||
|
||||
if(adapter->hw.mac_type < e1000_82573) {
|
||||
if(adapter->hw.mac_type < e1000_82571) {
|
||||
if(!adapter->blink_timer.function) {
|
||||
init_timer(&adapter->blink_timer);
|
||||
adapter->blink_timer.function = e1000_led_blink_callback;
|
||||
@ -1739,6 +1777,7 @@ struct ethtool_ops e1000_ethtool_ops = {
|
||||
.phys_id = e1000_phys_id,
|
||||
.get_stats_count = e1000_get_stats_count,
|
||||
.get_ethtool_stats = e1000_get_ethtool_stats,
|
||||
.get_perm_addr = ethtool_op_get_perm_addr,
|
||||
};
|
||||
|
||||
void e1000_set_ethtool_ops(struct net_device *netdev)
|
||||
|
@ -83,14 +83,14 @@ uint16_t e1000_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] =
|
||||
|
||||
static const
|
||||
uint16_t e1000_igp_2_cable_length_table[IGP02E1000_AGC_LENGTH_TABLE_SIZE] =
|
||||
{ 8, 13, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43,
|
||||
22, 24, 27, 30, 32, 35, 37, 40, 42, 44, 47, 49, 51, 54, 56, 58,
|
||||
32, 35, 38, 41, 44, 47, 50, 53, 55, 58, 61, 63, 66, 69, 71, 74,
|
||||
43, 47, 51, 54, 58, 61, 64, 67, 71, 74, 77, 80, 82, 85, 88, 90,
|
||||
57, 62, 66, 70, 74, 77, 81, 85, 88, 91, 94, 97, 100, 103, 106, 108,
|
||||
73, 78, 82, 87, 91, 95, 98, 102, 105, 109, 112, 114, 117, 119, 122, 124,
|
||||
91, 96, 101, 105, 109, 113, 116, 119, 122, 125, 127, 128, 128, 128, 128, 128,
|
||||
108, 113, 117, 121, 124, 127, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128};
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21,
|
||||
0, 0, 0, 3, 6, 10, 13, 16, 19, 23, 26, 29, 32, 35, 38, 41,
|
||||
6, 10, 14, 18, 22, 26, 30, 33, 37, 41, 44, 48, 51, 54, 58, 61,
|
||||
21, 26, 31, 35, 40, 44, 49, 53, 57, 61, 65, 68, 72, 75, 79, 82,
|
||||
40, 45, 51, 56, 61, 66, 70, 75, 79, 83, 87, 91, 94, 98, 101, 104,
|
||||
60, 66, 72, 77, 82, 87, 92, 96, 100, 104, 108, 111, 114, 117, 119, 121,
|
||||
83, 89, 95, 100, 105, 109, 113, 116, 119, 122, 124,
|
||||
104, 109, 114, 118, 121, 124};
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
@ -286,7 +286,6 @@ e1000_set_mac_type(struct e1000_hw *hw)
|
||||
case E1000_DEV_ID_82546GB_FIBER:
|
||||
case E1000_DEV_ID_82546GB_SERDES:
|
||||
case E1000_DEV_ID_82546GB_PCIE:
|
||||
case E1000_DEV_ID_82546GB_QUAD_COPPER:
|
||||
hw->mac_type = e1000_82546_rev_3;
|
||||
break;
|
||||
case E1000_DEV_ID_82541EI:
|
||||
@ -305,8 +304,19 @@ e1000_set_mac_type(struct e1000_hw *hw)
|
||||
case E1000_DEV_ID_82547GI:
|
||||
hw->mac_type = e1000_82547_rev_2;
|
||||
break;
|
||||
case E1000_DEV_ID_82571EB_COPPER:
|
||||
case E1000_DEV_ID_82571EB_FIBER:
|
||||
case E1000_DEV_ID_82571EB_SERDES:
|
||||
hw->mac_type = e1000_82571;
|
||||
break;
|
||||
case E1000_DEV_ID_82572EI_COPPER:
|
||||
case E1000_DEV_ID_82572EI_FIBER:
|
||||
case E1000_DEV_ID_82572EI_SERDES:
|
||||
hw->mac_type = e1000_82572;
|
||||
break;
|
||||
case E1000_DEV_ID_82573E:
|
||||
case E1000_DEV_ID_82573E_IAMT:
|
||||
case E1000_DEV_ID_82573L:
|
||||
hw->mac_type = e1000_82573;
|
||||
break;
|
||||
default:
|
||||
@ -315,6 +325,8 @@ e1000_set_mac_type(struct e1000_hw *hw)
|
||||
}
|
||||
|
||||
switch(hw->mac_type) {
|
||||
case e1000_82571:
|
||||
case e1000_82572:
|
||||
case e1000_82573:
|
||||
hw->eeprom_semaphore_present = TRUE;
|
||||
/* fall through */
|
||||
@ -351,6 +363,8 @@ e1000_set_media_type(struct e1000_hw *hw)
|
||||
switch (hw->device_id) {
|
||||
case E1000_DEV_ID_82545GM_SERDES:
|
||||
case E1000_DEV_ID_82546GB_SERDES:
|
||||
case E1000_DEV_ID_82571EB_SERDES:
|
||||
case E1000_DEV_ID_82572EI_SERDES:
|
||||
hw->media_type = e1000_media_type_internal_serdes;
|
||||
break;
|
||||
default:
|
||||
@ -523,6 +537,8 @@ e1000_reset_hw(struct e1000_hw *hw)
|
||||
E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
|
||||
E1000_WRITE_FLUSH(hw);
|
||||
/* fall through */
|
||||
case e1000_82571:
|
||||
case e1000_82572:
|
||||
ret_val = e1000_get_auto_rd_done(hw);
|
||||
if(ret_val)
|
||||
/* We don't want to continue accessing MAC registers. */
|
||||
@ -683,6 +699,9 @@ e1000_init_hw(struct e1000_hw *hw)
|
||||
switch (hw->mac_type) {
|
||||
default:
|
||||
break;
|
||||
case e1000_82571:
|
||||
case e1000_82572:
|
||||
ctrl |= (1 << 22);
|
||||
case e1000_82573:
|
||||
ctrl |= E1000_TXDCTL_COUNT_DESC;
|
||||
break;
|
||||
@ -694,6 +713,26 @@ e1000_init_hw(struct e1000_hw *hw)
|
||||
e1000_enable_tx_pkt_filtering(hw);
|
||||
}
|
||||
|
||||
switch (hw->mac_type) {
|
||||
default:
|
||||
break;
|
||||
case e1000_82571:
|
||||
case e1000_82572:
|
||||
ctrl = E1000_READ_REG(hw, TXDCTL1);
|
||||
ctrl &= ~E1000_TXDCTL_WTHRESH;
|
||||
ctrl |= E1000_TXDCTL_COUNT_DESC | E1000_TXDCTL_FULL_TX_DESC_WB;
|
||||
ctrl |= (1 << 22);
|
||||
E1000_WRITE_REG(hw, TXDCTL1, ctrl);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (hw->mac_type == e1000_82573) {
|
||||
uint32_t gcr = E1000_READ_REG(hw, GCR);
|
||||
gcr |= E1000_GCR_L1_ACT_WITHOUT_L0S_RX;
|
||||
E1000_WRITE_REG(hw, GCR, gcr);
|
||||
}
|
||||
|
||||
/* Clear all of the statistics registers (clear on read). It is
|
||||
* important that we do this after we have tried to establish link
|
||||
@ -878,6 +917,14 @@ e1000_setup_fiber_serdes_link(struct e1000_hw *hw)
|
||||
|
||||
DEBUGFUNC("e1000_setup_fiber_serdes_link");
|
||||
|
||||
/* On 82571 and 82572 Fiber connections, SerDes loopback mode persists
|
||||
* until explicitly turned off or a power cycle is performed. A read to
|
||||
* the register does not indicate its status. Therefore, we ensure
|
||||
* loopback mode is disabled during initialization.
|
||||
*/
|
||||
if (hw->mac_type == e1000_82571 || hw->mac_type == e1000_82572)
|
||||
E1000_WRITE_REG(hw, SCTL, E1000_DISABLE_SERDES_LOOPBACK);
|
||||
|
||||
/* On adapters with a MAC newer than 82544, SW Defineable pin 1 will be
|
||||
* set when the optics detect a signal. On older adapters, it will be
|
||||
* cleared when there is a signal. This applies to fiber media only.
|
||||
@ -2943,6 +2990,8 @@ e1000_phy_reset(struct e1000_hw *hw)
|
||||
|
||||
switch (hw->mac_type) {
|
||||
case e1000_82541_rev_2:
|
||||
case e1000_82571:
|
||||
case e1000_82572:
|
||||
ret_val = e1000_phy_hw_reset(hw);
|
||||
if(ret_val)
|
||||
return ret_val;
|
||||
@ -2981,6 +3030,16 @@ e1000_detect_gig_phy(struct e1000_hw *hw)
|
||||
|
||||
DEBUGFUNC("e1000_detect_gig_phy");
|
||||
|
||||
/* The 82571 firmware may still be configuring the PHY. In this
|
||||
* case, we cannot access the PHY until the configuration is done. So
|
||||
* we explicitly set the PHY values. */
|
||||
if(hw->mac_type == e1000_82571 ||
|
||||
hw->mac_type == e1000_82572) {
|
||||
hw->phy_id = IGP01E1000_I_PHY_ID;
|
||||
hw->phy_type = e1000_phy_igp_2;
|
||||
return E1000_SUCCESS;
|
||||
}
|
||||
|
||||
/* Read the PHY ID Registers to identify which PHY is onboard. */
|
||||
ret_val = e1000_read_phy_reg(hw, PHY_ID1, &phy_id_high);
|
||||
if(ret_val)
|
||||
@ -3334,6 +3393,21 @@ e1000_init_eeprom_params(struct e1000_hw *hw)
|
||||
eeprom->use_eerd = FALSE;
|
||||
eeprom->use_eewr = FALSE;
|
||||
break;
|
||||
case e1000_82571:
|
||||
case e1000_82572:
|
||||
eeprom->type = e1000_eeprom_spi;
|
||||
eeprom->opcode_bits = 8;
|
||||
eeprom->delay_usec = 1;
|
||||
if (eecd & E1000_EECD_ADDR_BITS) {
|
||||
eeprom->page_size = 32;
|
||||
eeprom->address_bits = 16;
|
||||
} else {
|
||||
eeprom->page_size = 8;
|
||||
eeprom->address_bits = 8;
|
||||
}
|
||||
eeprom->use_eerd = FALSE;
|
||||
eeprom->use_eewr = FALSE;
|
||||
break;
|
||||
case e1000_82573:
|
||||
eeprom->type = e1000_eeprom_spi;
|
||||
eeprom->opcode_bits = 8;
|
||||
@ -3543,25 +3617,26 @@ e1000_acquire_eeprom(struct e1000_hw *hw)
|
||||
eecd = E1000_READ_REG(hw, EECD);
|
||||
|
||||
if (hw->mac_type != e1000_82573) {
|
||||
/* Request EEPROM Access */
|
||||
if(hw->mac_type > e1000_82544) {
|
||||
eecd |= E1000_EECD_REQ;
|
||||
E1000_WRITE_REG(hw, EECD, eecd);
|
||||
eecd = E1000_READ_REG(hw, EECD);
|
||||
while((!(eecd & E1000_EECD_GNT)) &&
|
||||
(i < E1000_EEPROM_GRANT_ATTEMPTS)) {
|
||||
i++;
|
||||
udelay(5);
|
||||
eecd = E1000_READ_REG(hw, EECD);
|
||||
}
|
||||
if(!(eecd & E1000_EECD_GNT)) {
|
||||
eecd &= ~E1000_EECD_REQ;
|
||||
/* Request EEPROM Access */
|
||||
if(hw->mac_type > e1000_82544) {
|
||||
eecd |= E1000_EECD_REQ;
|
||||
E1000_WRITE_REG(hw, EECD, eecd);
|
||||
DEBUGOUT("Could not acquire EEPROM grant\n");
|
||||
return -E1000_ERR_EEPROM;
|
||||
eecd = E1000_READ_REG(hw, EECD);
|
||||
while((!(eecd & E1000_EECD_GNT)) &&
|
||||
(i < E1000_EEPROM_GRANT_ATTEMPTS)) {
|
||||
i++;
|
||||
udelay(5);
|
||||
eecd = E1000_READ_REG(hw, EECD);
|
||||
}
|
||||
if(!(eecd & E1000_EECD_GNT)) {
|
||||
eecd &= ~E1000_EECD_REQ;
|
||||
E1000_WRITE_REG(hw, EECD, eecd);
|
||||
DEBUGOUT("Could not acquire EEPROM grant\n");
|
||||
e1000_put_hw_eeprom_semaphore(hw);
|
||||
return -E1000_ERR_EEPROM;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Setup EEPROM for Read/Write */
|
||||
|
||||
@ -4064,7 +4139,7 @@ e1000_write_eeprom(struct e1000_hw *hw,
|
||||
return -E1000_ERR_EEPROM;
|
||||
}
|
||||
|
||||
/* 82573 reads only through eerd */
|
||||
/* 82573 writes only through eewr */
|
||||
if(eeprom->use_eewr == TRUE)
|
||||
return e1000_write_eeprom_eewr(hw, offset, words, data);
|
||||
|
||||
@ -4353,9 +4428,16 @@ e1000_read_mac_addr(struct e1000_hw * hw)
|
||||
hw->perm_mac_addr[i] = (uint8_t) (eeprom_data & 0x00FF);
|
||||
hw->perm_mac_addr[i+1] = (uint8_t) (eeprom_data >> 8);
|
||||
}
|
||||
if(((hw->mac_type == e1000_82546) || (hw->mac_type == e1000_82546_rev_3)) &&
|
||||
(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1))
|
||||
switch (hw->mac_type) {
|
||||
default:
|
||||
break;
|
||||
case e1000_82546:
|
||||
case e1000_82546_rev_3:
|
||||
case e1000_82571:
|
||||
if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)
|
||||
hw->perm_mac_addr[5] ^= 0x01;
|
||||
break;
|
||||
}
|
||||
|
||||
for(i = 0; i < NODE_ADDRESS_SIZE; i++)
|
||||
hw->mac_addr[i] = hw->perm_mac_addr[i];
|
||||
@ -4385,6 +4467,12 @@ e1000_init_rx_addrs(struct e1000_hw *hw)
|
||||
e1000_rar_set(hw, hw->mac_addr, 0);
|
||||
|
||||
rar_num = E1000_RAR_ENTRIES;
|
||||
|
||||
/* Reserve a spot for the Locally Administered Address to work around
|
||||
* an 82571 issue in which a reset on one port will reload the MAC on
|
||||
* the other port. */
|
||||
if ((hw->mac_type == e1000_82571) && (hw->laa_is_present == TRUE))
|
||||
rar_num -= 1;
|
||||
/* Zero out the other 15 receive addresses. */
|
||||
DEBUGOUT("Clearing RAR[1-15]\n");
|
||||
for(i = 1; i < rar_num; i++) {
|
||||
@ -4427,6 +4515,12 @@ e1000_mc_addr_list_update(struct e1000_hw *hw,
|
||||
/* Clear RAR[1-15] */
|
||||
DEBUGOUT(" Clearing RAR[1-15]\n");
|
||||
num_rar_entry = E1000_RAR_ENTRIES;
|
||||
/* Reserve a spot for the Locally Administered Address to work around
|
||||
* an 82571 issue in which a reset on one port will reload the MAC on
|
||||
* the other port. */
|
||||
if ((hw->mac_type == e1000_82571) && (hw->laa_is_present == TRUE))
|
||||
num_rar_entry -= 1;
|
||||
|
||||
for(i = rar_used_count; i < num_rar_entry; i++) {
|
||||
E1000_WRITE_REG_ARRAY(hw, RA, (i << 1), 0);
|
||||
E1000_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0);
|
||||
@ -4984,7 +5078,6 @@ e1000_clear_hw_cntrs(struct e1000_hw *hw)
|
||||
temp = E1000_READ_REG(hw, ICTXQEC);
|
||||
temp = E1000_READ_REG(hw, ICTXQMTC);
|
||||
temp = E1000_READ_REG(hw, ICRXDMTC);
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
@ -5151,6 +5244,8 @@ e1000_get_bus_info(struct e1000_hw *hw)
|
||||
hw->bus_speed = e1000_bus_speed_unknown;
|
||||
hw->bus_width = e1000_bus_width_unknown;
|
||||
break;
|
||||
case e1000_82571:
|
||||
case e1000_82572:
|
||||
case e1000_82573:
|
||||
hw->bus_type = e1000_bus_type_pci_express;
|
||||
hw->bus_speed = e1000_bus_speed_2500;
|
||||
@ -5250,6 +5345,7 @@ e1000_get_cable_length(struct e1000_hw *hw,
|
||||
int32_t ret_val;
|
||||
uint16_t agc_value = 0;
|
||||
uint16_t cur_agc, min_agc = IGP01E1000_AGC_LENGTH_TABLE_SIZE;
|
||||
uint16_t max_agc = 0;
|
||||
uint16_t i, phy_data;
|
||||
uint16_t cable_length;
|
||||
|
||||
@ -5338,6 +5434,40 @@ e1000_get_cable_length(struct e1000_hw *hw,
|
||||
IGP01E1000_AGC_RANGE) : 0;
|
||||
*max_length = e1000_igp_cable_length_table[agc_value] +
|
||||
IGP01E1000_AGC_RANGE;
|
||||
} else if (hw->phy_type == e1000_phy_igp_2) {
|
||||
uint16_t agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] =
|
||||
{IGP02E1000_PHY_AGC_A,
|
||||
IGP02E1000_PHY_AGC_B,
|
||||
IGP02E1000_PHY_AGC_C,
|
||||
IGP02E1000_PHY_AGC_D};
|
||||
/* Read the AGC registers for all channels */
|
||||
for (i = 0; i < IGP02E1000_PHY_CHANNEL_NUM; i++) {
|
||||
ret_val = e1000_read_phy_reg(hw, agc_reg_array[i], &phy_data);
|
||||
if (ret_val)
|
||||
return ret_val;
|
||||
|
||||
/* Getting bits 15:9, which represent the combination of course and
|
||||
* fine gain values. The result is a number that can be put into
|
||||
* the lookup table to obtain the approximate cable length. */
|
||||
cur_agc = (phy_data >> IGP02E1000_AGC_LENGTH_SHIFT) &
|
||||
IGP02E1000_AGC_LENGTH_MASK;
|
||||
|
||||
/* Remove min & max AGC values from calculation. */
|
||||
if (e1000_igp_2_cable_length_table[min_agc] > e1000_igp_2_cable_length_table[cur_agc])
|
||||
min_agc = cur_agc;
|
||||
if (e1000_igp_2_cable_length_table[max_agc] < e1000_igp_2_cable_length_table[cur_agc])
|
||||
max_agc = cur_agc;
|
||||
|
||||
agc_value += e1000_igp_2_cable_length_table[cur_agc];
|
||||
}
|
||||
|
||||
agc_value -= (e1000_igp_2_cable_length_table[min_agc] + e1000_igp_2_cable_length_table[max_agc]);
|
||||
agc_value /= (IGP02E1000_PHY_CHANNEL_NUM - 2);
|
||||
|
||||
/* Calculate cable length with the error range of +/- 10 meters. */
|
||||
*min_length = ((agc_value - IGP02E1000_AGC_RANGE) > 0) ?
|
||||
(agc_value - IGP02E1000_AGC_RANGE) : 0;
|
||||
*max_length = agc_value + IGP02E1000_AGC_RANGE;
|
||||
}
|
||||
|
||||
return E1000_SUCCESS;
|
||||
@ -6465,6 +6595,8 @@ e1000_get_auto_rd_done(struct e1000_hw *hw)
|
||||
default:
|
||||
msec_delay(5);
|
||||
break;
|
||||
case e1000_82571:
|
||||
case e1000_82572:
|
||||
case e1000_82573:
|
||||
while(timeout) {
|
||||
if (E1000_READ_REG(hw, EECD) & E1000_EECD_AUTO_RD) break;
|
||||
@ -6494,10 +6626,31 @@ e1000_get_auto_rd_done(struct e1000_hw *hw)
|
||||
int32_t
|
||||
e1000_get_phy_cfg_done(struct e1000_hw *hw)
|
||||
{
|
||||
int32_t timeout = PHY_CFG_TIMEOUT;
|
||||
uint32_t cfg_mask = E1000_EEPROM_CFG_DONE;
|
||||
|
||||
DEBUGFUNC("e1000_get_phy_cfg_done");
|
||||
|
||||
/* Simply wait for 10ms */
|
||||
msec_delay(10);
|
||||
switch (hw->mac_type) {
|
||||
default:
|
||||
msec_delay(10);
|
||||
break;
|
||||
case e1000_82571:
|
||||
case e1000_82572:
|
||||
while (timeout) {
|
||||
if (E1000_READ_REG(hw, EEMNGCTL) & cfg_mask)
|
||||
break;
|
||||
else
|
||||
msec_delay(1);
|
||||
timeout--;
|
||||
}
|
||||
|
||||
if (!timeout) {
|
||||
DEBUGOUT("MNG configuration cycle has not completed.\n");
|
||||
return -E1000_ERR_RESET;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return E1000_SUCCESS;
|
||||
}
|
||||
@ -6569,8 +6722,7 @@ e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw)
|
||||
return;
|
||||
|
||||
swsm = E1000_READ_REG(hw, SWSM);
|
||||
/* Release both semaphores. */
|
||||
swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI);
|
||||
swsm &= ~(E1000_SWSM_SWESMBI);
|
||||
E1000_WRITE_REG(hw, SWSM, swsm);
|
||||
}
|
||||
|
||||
@ -6606,6 +6758,8 @@ e1000_arc_subsystem_valid(struct e1000_hw *hw)
|
||||
* if this is the case. We read FWSM to determine the manageability mode.
|
||||
*/
|
||||
switch (hw->mac_type) {
|
||||
case e1000_82571:
|
||||
case e1000_82572:
|
||||
case e1000_82573:
|
||||
fwsm = E1000_READ_REG(hw, FWSM);
|
||||
if((fwsm & E1000_FWSM_MODE_MASK) != 0)
|
||||
|
@ -57,6 +57,8 @@ typedef enum {
|
||||
e1000_82541_rev_2,
|
||||
e1000_82547,
|
||||
e1000_82547_rev_2,
|
||||
e1000_82571,
|
||||
e1000_82572,
|
||||
e1000_82573,
|
||||
e1000_num_macs
|
||||
} e1000_mac_type;
|
||||
@ -478,10 +480,16 @@ uint8_t e1000_arc_subsystem_valid(struct e1000_hw *hw);
|
||||
#define E1000_DEV_ID_82546GB_SERDES 0x107B
|
||||
#define E1000_DEV_ID_82546GB_PCIE 0x108A
|
||||
#define E1000_DEV_ID_82547EI 0x1019
|
||||
#define E1000_DEV_ID_82571EB_COPPER 0x105E
|
||||
#define E1000_DEV_ID_82571EB_FIBER 0x105F
|
||||
#define E1000_DEV_ID_82571EB_SERDES 0x1060
|
||||
#define E1000_DEV_ID_82572EI_COPPER 0x107D
|
||||
#define E1000_DEV_ID_82572EI_FIBER 0x107E
|
||||
#define E1000_DEV_ID_82572EI_SERDES 0x107F
|
||||
#define E1000_DEV_ID_82573E 0x108B
|
||||
#define E1000_DEV_ID_82573E_IAMT 0x108C
|
||||
#define E1000_DEV_ID_82573L 0x109A
|
||||
|
||||
#define E1000_DEV_ID_82546GB_QUAD_COPPER 0x1099
|
||||
|
||||
#define NODE_ADDRESS_SIZE 6
|
||||
#define ETH_LENGTH_OF_ADDRESS 6
|
||||
@ -833,6 +841,8 @@ struct e1000_ffvt_entry {
|
||||
#define E1000_FFMT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX
|
||||
#define E1000_FFVT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX
|
||||
|
||||
#define E1000_DISABLE_SERDES_LOOPBACK 0x0400
|
||||
|
||||
/* Register Set. (82543, 82544)
|
||||
*
|
||||
* Registers are defined to be 32 bits and should be accessed as 32 bit values.
|
||||
@ -853,6 +863,7 @@ struct e1000_ffvt_entry {
|
||||
#define E1000_CTRL_EXT 0x00018 /* Extended Device Control - RW */
|
||||
#define E1000_FLA 0x0001C /* Flash Access - RW */
|
||||
#define E1000_MDIC 0x00020 /* MDI Control - RW */
|
||||
#define E1000_SCTL 0x00024 /* SerDes Control - RW */
|
||||
#define E1000_FCAL 0x00028 /* Flow Control Address Low - RW */
|
||||
#define E1000_FCAH 0x0002C /* Flow Control Address High -RW */
|
||||
#define E1000_FCT 0x00030 /* Flow Control Type - RW */
|
||||
@ -864,6 +875,12 @@ struct e1000_ffvt_entry {
|
||||
#define E1000_IMC 0x000D8 /* Interrupt Mask Clear - WO */
|
||||
#define E1000_IAM 0x000E0 /* Interrupt Acknowledge Auto Mask */
|
||||
#define E1000_RCTL 0x00100 /* RX Control - RW */
|
||||
#define E1000_RDTR1 0x02820 /* RX Delay Timer (1) - RW */
|
||||
#define E1000_RDBAL1 0x02900 /* RX Descriptor Base Address Low (1) - RW */
|
||||
#define E1000_RDBAH1 0x02904 /* RX Descriptor Base Address High (1) - RW */
|
||||
#define E1000_RDLEN1 0x02908 /* RX Descriptor Length (1) - RW */
|
||||
#define E1000_RDH1 0x02910 /* RX Descriptor Head (1) - RW */
|
||||
#define E1000_RDT1 0x02918 /* RX Descriptor Tail (1) - RW */
|
||||
#define E1000_FCTTV 0x00170 /* Flow Control Transmit Timer Value - RW */
|
||||
#define E1000_TXCW 0x00178 /* TX Configuration Word - RW */
|
||||
#define E1000_RXCW 0x00180 /* RX Configuration Word - RO */
|
||||
@ -895,6 +912,12 @@ struct e1000_ffvt_entry {
|
||||
#define E1000_RDH 0x02810 /* RX Descriptor Head - RW */
|
||||
#define E1000_RDT 0x02818 /* RX Descriptor Tail - RW */
|
||||
#define E1000_RDTR 0x02820 /* RX Delay Timer - RW */
|
||||
#define E1000_RDBAL0 E1000_RDBAL /* RX Desc Base Address Low (0) - RW */
|
||||
#define E1000_RDBAH0 E1000_RDBAH /* RX Desc Base Address High (0) - RW */
|
||||
#define E1000_RDLEN0 E1000_RDLEN /* RX Desc Length (0) - RW */
|
||||
#define E1000_RDH0 E1000_RDH /* RX Desc Head (0) - RW */
|
||||
#define E1000_RDT0 E1000_RDT /* RX Desc Tail (0) - RW */
|
||||
#define E1000_RDTR0 E1000_RDTR /* RX Delay Timer (0) - RW */
|
||||
#define E1000_RXDCTL 0x02828 /* RX Descriptor Control - RW */
|
||||
#define E1000_RADV 0x0282C /* RX Interrupt Absolute Delay Timer - RW */
|
||||
#define E1000_RSRPD 0x02C00 /* RX Small Packet Detect - RW */
|
||||
@ -980,15 +1003,15 @@ struct e1000_ffvt_entry {
|
||||
#define E1000_BPTC 0x040F4 /* Broadcast Packets TX Count - R/clr */
|
||||
#define E1000_TSCTC 0x040F8 /* TCP Segmentation Context TX - R/clr */
|
||||
#define E1000_TSCTFC 0x040FC /* TCP Segmentation Context TX Fail - R/clr */
|
||||
#define E1000_IAC 0x4100 /* Interrupt Assertion Count */
|
||||
#define E1000_ICRXPTC 0x4104 /* Interrupt Cause Rx Packet Timer Expire Count */
|
||||
#define E1000_ICRXATC 0x4108 /* Interrupt Cause Rx Absolute Timer Expire Count */
|
||||
#define E1000_ICTXPTC 0x410C /* Interrupt Cause Tx Packet Timer Expire Count */
|
||||
#define E1000_ICTXATC 0x4110 /* Interrupt Cause Tx Absolute Timer Expire Count */
|
||||
#define E1000_ICTXQEC 0x4118 /* Interrupt Cause Tx Queue Empty Count */
|
||||
#define E1000_ICTXQMTC 0x411C /* Interrupt Cause Tx Queue Minimum Threshold Count */
|
||||
#define E1000_ICRXDMTC 0x4120 /* Interrupt Cause Rx Descriptor Minimum Threshold Count */
|
||||
#define E1000_ICRXOC 0x4124 /* Interrupt Cause Receiver Overrun Count */
|
||||
#define E1000_IAC 0x04100 /* Interrupt Assertion Count */
|
||||
#define E1000_ICRXPTC 0x04104 /* Interrupt Cause Rx Packet Timer Expire Count */
|
||||
#define E1000_ICRXATC 0x04108 /* Interrupt Cause Rx Absolute Timer Expire Count */
|
||||
#define E1000_ICTXPTC 0x0410C /* Interrupt Cause Tx Packet Timer Expire Count */
|
||||
#define E1000_ICTXATC 0x04110 /* Interrupt Cause Tx Absolute Timer Expire Count */
|
||||
#define E1000_ICTXQEC 0x04118 /* Interrupt Cause Tx Queue Empty Count */
|
||||
#define E1000_ICTXQMTC 0x0411C /* Interrupt Cause Tx Queue Minimum Threshold Count */
|
||||
#define E1000_ICRXDMTC 0x04120 /* Interrupt Cause Rx Descriptor Minimum Threshold Count */
|
||||
#define E1000_ICRXOC 0x04124 /* Interrupt Cause Receiver Overrun Count */
|
||||
#define E1000_RXCSUM 0x05000 /* RX Checksum Control - RW */
|
||||
#define E1000_RFCTL 0x05008 /* Receive Filter Control*/
|
||||
#define E1000_MTA 0x05200 /* Multicast Table Array - RW Array */
|
||||
@ -1018,6 +1041,14 @@ struct e1000_ffvt_entry {
|
||||
#define E1000_FWSM 0x05B54 /* FW Semaphore */
|
||||
#define E1000_FFLT_DBG 0x05F04 /* Debug Register */
|
||||
#define E1000_HICR 0x08F00 /* Host Inteface Control */
|
||||
|
||||
/* RSS registers */
|
||||
#define E1000_CPUVEC 0x02C10 /* CPU Vector Register - RW */
|
||||
#define E1000_MRQC 0x05818 /* Multiple Receive Control - RW */
|
||||
#define E1000_RETA 0x05C00 /* Redirection Table - RW Array */
|
||||
#define E1000_RSSRK 0x05C80 /* RSS Random Key - RW Array */
|
||||
#define E1000_RSSIM 0x05864 /* RSS Interrupt Mask */
|
||||
#define E1000_RSSIR 0x05868 /* RSS Interrupt Request */
|
||||
/* Register Set (82542)
|
||||
*
|
||||
* Some of the 82542 registers are located at different offsets than they are
|
||||
@ -1032,6 +1063,7 @@ struct e1000_ffvt_entry {
|
||||
#define E1000_82542_CTRL_EXT E1000_CTRL_EXT
|
||||
#define E1000_82542_FLA E1000_FLA
|
||||
#define E1000_82542_MDIC E1000_MDIC
|
||||
#define E1000_82542_SCTL E1000_SCTL
|
||||
#define E1000_82542_FCAL E1000_FCAL
|
||||
#define E1000_82542_FCAH E1000_FCAH
|
||||
#define E1000_82542_FCT E1000_FCT
|
||||
@ -1049,6 +1081,18 @@ struct e1000_ffvt_entry {
|
||||
#define E1000_82542_RDLEN 0x00118
|
||||
#define E1000_82542_RDH 0x00120
|
||||
#define E1000_82542_RDT 0x00128
|
||||
#define E1000_82542_RDTR0 E1000_82542_RDTR
|
||||
#define E1000_82542_RDBAL0 E1000_82542_RDBAL
|
||||
#define E1000_82542_RDBAH0 E1000_82542_RDBAH
|
||||
#define E1000_82542_RDLEN0 E1000_82542_RDLEN
|
||||
#define E1000_82542_RDH0 E1000_82542_RDH
|
||||
#define E1000_82542_RDT0 E1000_82542_RDT
|
||||
#define E1000_82542_RDTR1 0x00130
|
||||
#define E1000_82542_RDBAL1 0x00138
|
||||
#define E1000_82542_RDBAH1 0x0013C
|
||||
#define E1000_82542_RDLEN1 0x00140
|
||||
#define E1000_82542_RDH1 0x00148
|
||||
#define E1000_82542_RDT1 0x00150
|
||||
#define E1000_82542_FCRTH 0x00160
|
||||
#define E1000_82542_FCRTL 0x00168
|
||||
#define E1000_82542_FCTTV E1000_FCTTV
|
||||
@ -1197,6 +1241,13 @@ struct e1000_ffvt_entry {
|
||||
#define E1000_82542_ICRXOC E1000_ICRXOC
|
||||
#define E1000_82542_HICR E1000_HICR
|
||||
|
||||
#define E1000_82542_CPUVEC E1000_CPUVEC
|
||||
#define E1000_82542_MRQC E1000_MRQC
|
||||
#define E1000_82542_RETA E1000_RETA
|
||||
#define E1000_82542_RSSRK E1000_RSSRK
|
||||
#define E1000_82542_RSSIM E1000_RSSIM
|
||||
#define E1000_82542_RSSIR E1000_RSSIR
|
||||
|
||||
/* Statistics counters collected by the MAC */
|
||||
struct e1000_hw_stats {
|
||||
uint64_t crcerrs;
|
||||
@ -1336,6 +1387,7 @@ struct e1000_hw {
|
||||
boolean_t serdes_link_down;
|
||||
boolean_t tbi_compatibility_en;
|
||||
boolean_t tbi_compatibility_on;
|
||||
boolean_t laa_is_present;
|
||||
boolean_t phy_reset_disable;
|
||||
boolean_t fc_send_xon;
|
||||
boolean_t fc_strict_ieee;
|
||||
@ -1374,6 +1426,7 @@ struct e1000_hw {
|
||||
#define E1000_CTRL_BEM32 0x00000400 /* Big Endian 32 mode */
|
||||
#define E1000_CTRL_FRCSPD 0x00000800 /* Force Speed */
|
||||
#define E1000_CTRL_FRCDPX 0x00001000 /* Force Duplex */
|
||||
#define E1000_CTRL_D_UD_EN 0x00002000 /* Dock/Undock enable */
|
||||
#define E1000_CTRL_D_UD_POLARITY 0x00004000 /* Defined polarity of Dock/Undock indication in SDP[0] */
|
||||
#define E1000_CTRL_SWDPIN0 0x00040000 /* SWDPIN 0 value */
|
||||
#define E1000_CTRL_SWDPIN1 0x00080000 /* SWDPIN 1 value */
|
||||
@ -1491,6 +1544,8 @@ struct e1000_hw {
|
||||
#define E1000_CTRL_EXT_WR_WMARK_320 0x01000000
|
||||
#define E1000_CTRL_EXT_WR_WMARK_384 0x02000000
|
||||
#define E1000_CTRL_EXT_WR_WMARK_448 0x03000000
|
||||
#define E1000_CTRL_EXT_CANC 0x04000000 /* Interrupt delay cancellation */
|
||||
#define E1000_CTRL_EXT_DRV_LOAD 0x10000000 /* Driver loaded bit for FW */
|
||||
#define E1000_CTRL_EXT_IAME 0x08000000 /* Interrupt acknowledge Auto-mask */
|
||||
#define E1000_CTRL_EXT_INT_TIMER_CLR 0x20000000 /* Clear Interrupt timers after IMS clear */
|
||||
|
||||
@ -1524,6 +1579,7 @@ struct e1000_hw {
|
||||
#define E1000_LEDCTL_LED2_BLINK 0x00800000
|
||||
#define E1000_LEDCTL_LED3_MODE_MASK 0x0F000000
|
||||
#define E1000_LEDCTL_LED3_MODE_SHIFT 24
|
||||
#define E1000_LEDCTL_LED3_BLINK_RATE 0x20000000
|
||||
#define E1000_LEDCTL_LED3_IVRT 0x40000000
|
||||
#define E1000_LEDCTL_LED3_BLINK 0x80000000
|
||||
|
||||
@ -1784,6 +1840,16 @@ struct e1000_hw {
|
||||
#define E1000_RXCSUM_IPPCSE 0x00001000 /* IP payload checksum enable */
|
||||
#define E1000_RXCSUM_PCSD 0x00002000 /* packet checksum disabled */
|
||||
|
||||
/* Multiple Receive Queue Control */
|
||||
#define E1000_MRQC_ENABLE_MASK 0x00000003
|
||||
#define E1000_MRQC_ENABLE_RSS_2Q 0x00000001
|
||||
#define E1000_MRQC_ENABLE_RSS_INT 0x00000004
|
||||
#define E1000_MRQC_RSS_FIELD_MASK 0xFFFF0000
|
||||
#define E1000_MRQC_RSS_FIELD_IPV4_TCP 0x00010000
|
||||
#define E1000_MRQC_RSS_FIELD_IPV4 0x00020000
|
||||
#define E1000_MRQC_RSS_FIELD_IPV6_TCP 0x00040000
|
||||
#define E1000_MRQC_RSS_FIELD_IPV6_EX 0x00080000
|
||||
#define E1000_MRQC_RSS_FIELD_IPV6 0x00100000
|
||||
|
||||
/* Definitions for power management and wakeup registers */
|
||||
/* Wake Up Control */
|
||||
@ -1928,6 +1994,7 @@ struct e1000_host_command_info {
|
||||
#define E1000_MDALIGN 4096
|
||||
|
||||
#define E1000_GCR_BEM32 0x00400000
|
||||
#define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000
|
||||
/* Function Active and Power State to MNG */
|
||||
#define E1000_FACTPS_FUNC0_POWER_STATE_MASK 0x00000003
|
||||
#define E1000_FACTPS_LAN0_VALID 0x00000004
|
||||
@ -1980,6 +2047,7 @@ struct e1000_host_command_info {
|
||||
/* EEPROM Word Offsets */
|
||||
#define EEPROM_COMPAT 0x0003
|
||||
#define EEPROM_ID_LED_SETTINGS 0x0004
|
||||
#define EEPROM_VERSION 0x0005
|
||||
#define EEPROM_SERDES_AMPLITUDE 0x0006 /* For SERDES output amplitude adjustment. */
|
||||
#define EEPROM_PHY_CLASS_WORD 0x0007
|
||||
#define EEPROM_INIT_CONTROL1_REG 0x000A
|
||||
@ -1990,6 +2058,8 @@ struct e1000_host_command_info {
|
||||
#define EEPROM_FLASH_VERSION 0x0032
|
||||
#define EEPROM_CHECKSUM_REG 0x003F
|
||||
|
||||
#define E1000_EEPROM_CFG_DONE 0x00040000 /* MNG config cycle done */
|
||||
|
||||
/* Word definitions for ID LED Settings */
|
||||
#define ID_LED_RESERVED_0000 0x0000
|
||||
#define ID_LED_RESERVED_FFFF 0xFFFF
|
||||
@ -2108,6 +2178,8 @@ struct e1000_host_command_info {
|
||||
#define E1000_PBA_22K 0x0016
|
||||
#define E1000_PBA_24K 0x0018
|
||||
#define E1000_PBA_30K 0x001E
|
||||
#define E1000_PBA_32K 0x0020
|
||||
#define E1000_PBA_38K 0x0026
|
||||
#define E1000_PBA_40K 0x0028
|
||||
#define E1000_PBA_48K 0x0030 /* 48KB, default RX allocation */
|
||||
|
||||
@ -2592,11 +2664,11 @@ struct e1000_host_command_info {
|
||||
|
||||
/* 7 bits (3 Coarse + 4 Fine) --> 128 optional values */
|
||||
#define IGP01E1000_AGC_LENGTH_TABLE_SIZE 128
|
||||
#define IGP02E1000_AGC_LENGTH_TABLE_SIZE 128
|
||||
#define IGP02E1000_AGC_LENGTH_TABLE_SIZE 113
|
||||
|
||||
/* The precision error of the cable length is +/- 10 meters */
|
||||
#define IGP01E1000_AGC_RANGE 10
|
||||
#define IGP02E1000_AGC_RANGE 10
|
||||
#define IGP02E1000_AGC_RANGE 15
|
||||
|
||||
/* IGP01E1000 PCS Initialization register */
|
||||
/* bits 3:6 in the PCS registers stores the channels polarity */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -306,7 +306,8 @@ e1000_check_options(struct e1000_adapter *adapter)
|
||||
.def = E1000_DEFAULT_TXD,
|
||||
.arg = { .r = { .min = E1000_MIN_TXD }}
|
||||
};
|
||||
struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
|
||||
struct e1000_tx_ring *tx_ring = adapter->tx_ring;
|
||||
int i;
|
||||
e1000_mac_type mac_type = adapter->hw.mac_type;
|
||||
opt.arg.r.max = mac_type < e1000_82544 ?
|
||||
E1000_MAX_TXD : E1000_MAX_82544_TXD;
|
||||
@ -319,6 +320,8 @@ e1000_check_options(struct e1000_adapter *adapter)
|
||||
} else {
|
||||
tx_ring->count = opt.def;
|
||||
}
|
||||
for (i = 0; i < adapter->num_queues; i++)
|
||||
tx_ring[i].count = tx_ring->count;
|
||||
}
|
||||
{ /* Receive Descriptor Count */
|
||||
struct e1000_option opt = {
|
||||
@ -329,7 +332,8 @@ e1000_check_options(struct e1000_adapter *adapter)
|
||||
.def = E1000_DEFAULT_RXD,
|
||||
.arg = { .r = { .min = E1000_MIN_RXD }}
|
||||
};
|
||||
struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
|
||||
struct e1000_rx_ring *rx_ring = adapter->rx_ring;
|
||||
int i;
|
||||
e1000_mac_type mac_type = adapter->hw.mac_type;
|
||||
opt.arg.r.max = mac_type < e1000_82544 ? E1000_MAX_RXD :
|
||||
E1000_MAX_82544_RXD;
|
||||
@ -342,6 +346,8 @@ e1000_check_options(struct e1000_adapter *adapter)
|
||||
} else {
|
||||
rx_ring->count = opt.def;
|
||||
}
|
||||
for (i = 0; i < adapter->num_queues; i++)
|
||||
rx_ring[i].count = rx_ring->count;
|
||||
}
|
||||
{ /* Checksum Offload Enable/Disable */
|
||||
struct e1000_option opt = {
|
||||
|
@ -1334,7 +1334,7 @@ static void epic_rx_err(struct net_device *dev, struct epic_private *ep)
|
||||
static int epic_poll(struct net_device *dev, int *budget)
|
||||
{
|
||||
struct epic_private *ep = dev->priv;
|
||||
int work_done, orig_budget;
|
||||
int work_done = 0, orig_budget;
|
||||
long ioaddr = dev->base_addr;
|
||||
|
||||
orig_budget = (*budget > dev->quota) ? dev->quota : *budget;
|
||||
@ -1343,7 +1343,7 @@ static int epic_poll(struct net_device *dev, int *budget)
|
||||
|
||||
epic_tx(dev, ep);
|
||||
|
||||
work_done = epic_rx(dev, *budget);
|
||||
work_done += epic_rx(dev, *budget);
|
||||
|
||||
epic_rx_err(dev, ep);
|
||||
|
||||
|
@ -95,6 +95,8 @@
|
||||
* of nv_remove
|
||||
* 0.42: 06 Aug 2005: Fix lack of link speed initialization
|
||||
* in the second (and later) nv_open call
|
||||
* 0.43: 10 Aug 2005: Add support for tx checksum.
|
||||
* 0.44: 20 Aug 2005: Add support for scatter gather and segmentation.
|
||||
*
|
||||
* Known bugs:
|
||||
* We suspect that on some hardware no TX done interrupts are generated.
|
||||
@ -106,7 +108,7 @@
|
||||
* DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few
|
||||
* superfluous timer interrupts from the nic.
|
||||
*/
|
||||
#define FORCEDETH_VERSION "0.41"
|
||||
#define FORCEDETH_VERSION "0.44"
|
||||
#define DRV_NAME "forcedeth"
|
||||
|
||||
#include <linux/module.h>
|
||||
@ -145,6 +147,7 @@
|
||||
#define DEV_NEED_LINKTIMER 0x0002 /* poll link settings. Relies on the timer irq */
|
||||
#define DEV_HAS_LARGEDESC 0x0004 /* device supports jumbo frames and needs packet format 2 */
|
||||
#define DEV_HAS_HIGH_DMA 0x0008 /* device supports 64bit dma */
|
||||
#define DEV_HAS_CHECKSUM 0x0010 /* device supports tx and rx checksum offloads */
|
||||
|
||||
enum {
|
||||
NvRegIrqStatus = 0x000,
|
||||
@ -241,6 +244,9 @@ enum {
|
||||
#define NVREG_TXRXCTL_IDLE 0x0008
|
||||
#define NVREG_TXRXCTL_RESET 0x0010
|
||||
#define NVREG_TXRXCTL_RXCHECK 0x0400
|
||||
#define NVREG_TXRXCTL_DESC_1 0
|
||||
#define NVREG_TXRXCTL_DESC_2 0x02100
|
||||
#define NVREG_TXRXCTL_DESC_3 0x02200
|
||||
NvRegMIIStatus = 0x180,
|
||||
#define NVREG_MIISTAT_ERROR 0x0001
|
||||
#define NVREG_MIISTAT_LINKCHANGE 0x0008
|
||||
@ -335,6 +341,10 @@ typedef union _ring_type {
|
||||
/* error and valid are the same for both */
|
||||
#define NV_TX2_ERROR (1<<30)
|
||||
#define NV_TX2_VALID (1<<31)
|
||||
#define NV_TX2_TSO (1<<28)
|
||||
#define NV_TX2_TSO_SHIFT 14
|
||||
#define NV_TX2_CHECKSUM_L3 (1<<27)
|
||||
#define NV_TX2_CHECKSUM_L4 (1<<26)
|
||||
|
||||
#define NV_RX_DESCRIPTORVALID (1<<16)
|
||||
#define NV_RX_MISSEDFRAME (1<<17)
|
||||
@ -417,14 +427,14 @@ typedef union _ring_type {
|
||||
|
||||
/*
|
||||
* desc_ver values:
|
||||
* This field has two purposes:
|
||||
* - Newer nics uses a different ring layout. The layout is selected by
|
||||
* comparing np->desc_ver with DESC_VER_xy.
|
||||
* - It contains bits that are forced on when writing to NvRegTxRxControl.
|
||||
* The nic supports three different descriptor types:
|
||||
* - DESC_VER_1: Original
|
||||
* - DESC_VER_2: support for jumbo frames.
|
||||
* - DESC_VER_3: 64-bit format.
|
||||
*/
|
||||
#define DESC_VER_1 0x0
|
||||
#define DESC_VER_2 (0x02100|NVREG_TXRXCTL_RXCHECK)
|
||||
#define DESC_VER_3 (0x02200|NVREG_TXRXCTL_RXCHECK)
|
||||
#define DESC_VER_1 1
|
||||
#define DESC_VER_2 2
|
||||
#define DESC_VER_3 3
|
||||
|
||||
/* PHY defines */
|
||||
#define PHY_OUI_MARVELL 0x5043
|
||||
@ -491,6 +501,7 @@ struct fe_priv {
|
||||
u32 orig_mac[2];
|
||||
u32 irqmask;
|
||||
u32 desc_ver;
|
||||
u32 txrxctl_bits;
|
||||
|
||||
void __iomem *base;
|
||||
|
||||
@ -534,7 +545,7 @@ static inline struct fe_priv *get_nvpriv(struct net_device *dev)
|
||||
|
||||
static inline u8 __iomem *get_hwbase(struct net_device *dev)
|
||||
{
|
||||
return get_nvpriv(dev)->base;
|
||||
return ((struct fe_priv *)netdev_priv(dev))->base;
|
||||
}
|
||||
|
||||
static inline void pci_push(u8 __iomem *base)
|
||||
@ -623,7 +634,7 @@ static int mii_rw(struct net_device *dev, int addr, int miireg, int value)
|
||||
|
||||
static int phy_reset(struct net_device *dev)
|
||||
{
|
||||
struct fe_priv *np = get_nvpriv(dev);
|
||||
struct fe_priv *np = netdev_priv(dev);
|
||||
u32 miicontrol;
|
||||
unsigned int tries = 0;
|
||||
|
||||
@ -726,7 +737,7 @@ static int phy_init(struct net_device *dev)
|
||||
|
||||
static void nv_start_rx(struct net_device *dev)
|
||||
{
|
||||
struct fe_priv *np = get_nvpriv(dev);
|
||||
struct fe_priv *np = netdev_priv(dev);
|
||||
u8 __iomem *base = get_hwbase(dev);
|
||||
|
||||
dprintk(KERN_DEBUG "%s: nv_start_rx\n", dev->name);
|
||||
@ -782,14 +793,14 @@ static void nv_stop_tx(struct net_device *dev)
|
||||
|
||||
static void nv_txrx_reset(struct net_device *dev)
|
||||
{
|
||||
struct fe_priv *np = get_nvpriv(dev);
|
||||
struct fe_priv *np = netdev_priv(dev);
|
||||
u8 __iomem *base = get_hwbase(dev);
|
||||
|
||||
dprintk(KERN_DEBUG "%s: nv_txrx_reset\n", dev->name);
|
||||
writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->desc_ver, base + NvRegTxRxControl);
|
||||
writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->txrxctl_bits, base + NvRegTxRxControl);
|
||||
pci_push(base);
|
||||
udelay(NV_TXRX_RESET_DELAY);
|
||||
writel(NVREG_TXRXCTL_BIT2 | np->desc_ver, base + NvRegTxRxControl);
|
||||
writel(NVREG_TXRXCTL_BIT2 | np->txrxctl_bits, base + NvRegTxRxControl);
|
||||
pci_push(base);
|
||||
}
|
||||
|
||||
@ -801,7 +812,7 @@ static void nv_txrx_reset(struct net_device *dev)
|
||||
*/
|
||||
static struct net_device_stats *nv_get_stats(struct net_device *dev)
|
||||
{
|
||||
struct fe_priv *np = get_nvpriv(dev);
|
||||
struct fe_priv *np = netdev_priv(dev);
|
||||
|
||||
/* It seems that the nic always generates interrupts and doesn't
|
||||
* accumulate errors internally. Thus the current values in np->stats
|
||||
@ -817,7 +828,7 @@ static struct net_device_stats *nv_get_stats(struct net_device *dev)
|
||||
*/
|
||||
static int nv_alloc_rx(struct net_device *dev)
|
||||
{
|
||||
struct fe_priv *np = get_nvpriv(dev);
|
||||
struct fe_priv *np = netdev_priv(dev);
|
||||
unsigned int refill_rx = np->refill_rx;
|
||||
int nr;
|
||||
|
||||
@ -861,7 +872,7 @@ static int nv_alloc_rx(struct net_device *dev)
|
||||
static void nv_do_rx_refill(unsigned long data)
|
||||
{
|
||||
struct net_device *dev = (struct net_device *) data;
|
||||
struct fe_priv *np = get_nvpriv(dev);
|
||||
struct fe_priv *np = netdev_priv(dev);
|
||||
|
||||
disable_irq(dev->irq);
|
||||
if (nv_alloc_rx(dev)) {
|
||||
@ -875,7 +886,7 @@ static void nv_do_rx_refill(unsigned long data)
|
||||
|
||||
static void nv_init_rx(struct net_device *dev)
|
||||
{
|
||||
struct fe_priv *np = get_nvpriv(dev);
|
||||
struct fe_priv *np = netdev_priv(dev);
|
||||
int i;
|
||||
|
||||
np->cur_rx = RX_RING;
|
||||
@ -889,15 +900,17 @@ static void nv_init_rx(struct net_device *dev)
|
||||
|
||||
static void nv_init_tx(struct net_device *dev)
|
||||
{
|
||||
struct fe_priv *np = get_nvpriv(dev);
|
||||
struct fe_priv *np = netdev_priv(dev);
|
||||
int i;
|
||||
|
||||
np->next_tx = np->nic_tx = 0;
|
||||
for (i = 0; i < TX_RING; i++)
|
||||
for (i = 0; i < TX_RING; i++) {
|
||||
if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
|
||||
np->tx_ring.orig[i].FlagLen = 0;
|
||||
else
|
||||
np->tx_ring.ex[i].FlagLen = 0;
|
||||
np->tx_skbuff[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int nv_init_ring(struct net_device *dev)
|
||||
@ -907,21 +920,44 @@ static int nv_init_ring(struct net_device *dev)
|
||||
return nv_alloc_rx(dev);
|
||||
}
|
||||
|
||||
static void nv_release_txskb(struct net_device *dev, unsigned int skbnr)
|
||||
{
|
||||
struct fe_priv *np = netdev_priv(dev);
|
||||
struct sk_buff *skb = np->tx_skbuff[skbnr];
|
||||
unsigned int j, entry, fragments;
|
||||
|
||||
dprintk(KERN_INFO "%s: nv_release_txskb for skbnr %d, skb %p\n",
|
||||
dev->name, skbnr, np->tx_skbuff[skbnr]);
|
||||
|
||||
entry = skbnr;
|
||||
if ((fragments = skb_shinfo(skb)->nr_frags) != 0) {
|
||||
for (j = fragments; j >= 1; j--) {
|
||||
skb_frag_t *frag = &skb_shinfo(skb)->frags[j-1];
|
||||
pci_unmap_page(np->pci_dev, np->tx_dma[entry],
|
||||
frag->size,
|
||||
PCI_DMA_TODEVICE);
|
||||
entry = (entry - 1) % TX_RING;
|
||||
}
|
||||
}
|
||||
pci_unmap_single(np->pci_dev, np->tx_dma[entry],
|
||||
skb->len - skb->data_len,
|
||||
PCI_DMA_TODEVICE);
|
||||
dev_kfree_skb_irq(skb);
|
||||
np->tx_skbuff[skbnr] = NULL;
|
||||
}
|
||||
|
||||
static void nv_drain_tx(struct net_device *dev)
|
||||
{
|
||||
struct fe_priv *np = get_nvpriv(dev);
|
||||
int i;
|
||||
struct fe_priv *np = netdev_priv(dev);
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < TX_RING; i++) {
|
||||
if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
|
||||
np->tx_ring.orig[i].FlagLen = 0;
|
||||
else
|
||||
np->tx_ring.ex[i].FlagLen = 0;
|
||||
if (np->tx_skbuff[i]) {
|
||||
pci_unmap_single(np->pci_dev, np->tx_dma[i],
|
||||
np->tx_skbuff[i]->len,
|
||||
PCI_DMA_TODEVICE);
|
||||
dev_kfree_skb(np->tx_skbuff[i]);
|
||||
np->tx_skbuff[i] = NULL;
|
||||
nv_release_txskb(dev, i);
|
||||
np->stats.tx_dropped++;
|
||||
}
|
||||
}
|
||||
@ -929,7 +965,7 @@ static void nv_drain_tx(struct net_device *dev)
|
||||
|
||||
static void nv_drain_rx(struct net_device *dev)
|
||||
{
|
||||
struct fe_priv *np = get_nvpriv(dev);
|
||||
struct fe_priv *np = netdev_priv(dev);
|
||||
int i;
|
||||
for (i = 0; i < RX_RING; i++) {
|
||||
if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
|
||||
@ -959,28 +995,69 @@ static void drain_ring(struct net_device *dev)
|
||||
*/
|
||||
static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
struct fe_priv *np = get_nvpriv(dev);
|
||||
int nr = np->next_tx % TX_RING;
|
||||
|
||||
np->tx_skbuff[nr] = skb;
|
||||
np->tx_dma[nr] = pci_map_single(np->pci_dev, skb->data,skb->len,
|
||||
PCI_DMA_TODEVICE);
|
||||
|
||||
if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
|
||||
np->tx_ring.orig[nr].PacketBuffer = cpu_to_le32(np->tx_dma[nr]);
|
||||
else {
|
||||
np->tx_ring.ex[nr].PacketBufferHigh = cpu_to_le64(np->tx_dma[nr]) >> 32;
|
||||
np->tx_ring.ex[nr].PacketBufferLow = cpu_to_le64(np->tx_dma[nr]) & 0x0FFFFFFFF;
|
||||
}
|
||||
struct fe_priv *np = netdev_priv(dev);
|
||||
u32 tx_flags_extra = (np->desc_ver == DESC_VER_1 ? NV_TX_LASTPACKET : NV_TX2_LASTPACKET);
|
||||
unsigned int fragments = skb_shinfo(skb)->nr_frags;
|
||||
unsigned int nr = (np->next_tx + fragments) % TX_RING;
|
||||
unsigned int i;
|
||||
|
||||
spin_lock_irq(&np->lock);
|
||||
wmb();
|
||||
if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
|
||||
np->tx_ring.orig[nr].FlagLen = cpu_to_le32( (skb->len-1) | np->tx_flags );
|
||||
|
||||
if ((np->next_tx - np->nic_tx + fragments) > TX_LIMIT_STOP) {
|
||||
spin_unlock_irq(&np->lock);
|
||||
netif_stop_queue(dev);
|
||||
return NETDEV_TX_BUSY;
|
||||
}
|
||||
|
||||
np->tx_skbuff[nr] = skb;
|
||||
|
||||
if (fragments) {
|
||||
dprintk(KERN_DEBUG "%s: nv_start_xmit: buffer contains %d fragments\n", dev->name, fragments);
|
||||
/* setup descriptors in reverse order */
|
||||
for (i = fragments; i >= 1; i--) {
|
||||
skb_frag_t *frag = &skb_shinfo(skb)->frags[i-1];
|
||||
np->tx_dma[nr] = pci_map_page(np->pci_dev, frag->page, frag->page_offset, frag->size,
|
||||
PCI_DMA_TODEVICE);
|
||||
|
||||
if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
|
||||
np->tx_ring.orig[nr].PacketBuffer = cpu_to_le32(np->tx_dma[nr]);
|
||||
np->tx_ring.orig[nr].FlagLen = cpu_to_le32( (frag->size-1) | np->tx_flags | tx_flags_extra);
|
||||
} else {
|
||||
np->tx_ring.ex[nr].PacketBufferHigh = cpu_to_le64(np->tx_dma[nr]) >> 32;
|
||||
np->tx_ring.ex[nr].PacketBufferLow = cpu_to_le64(np->tx_dma[nr]) & 0x0FFFFFFFF;
|
||||
np->tx_ring.ex[nr].FlagLen = cpu_to_le32( (frag->size-1) | np->tx_flags | tx_flags_extra);
|
||||
}
|
||||
|
||||
nr = (nr - 1) % TX_RING;
|
||||
|
||||
if (np->desc_ver == DESC_VER_1)
|
||||
tx_flags_extra &= ~NV_TX_LASTPACKET;
|
||||
else
|
||||
tx_flags_extra &= ~NV_TX2_LASTPACKET;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef NETIF_F_TSO
|
||||
if (skb_shinfo(skb)->tso_size)
|
||||
tx_flags_extra |= NV_TX2_TSO | (skb_shinfo(skb)->tso_size << NV_TX2_TSO_SHIFT);
|
||||
else
|
||||
np->tx_ring.ex[nr].FlagLen = cpu_to_le32( (skb->len-1) | np->tx_flags );
|
||||
dprintk(KERN_DEBUG "%s: nv_start_xmit: packet packet %d queued for transmission.\n",
|
||||
dev->name, np->next_tx);
|
||||
#endif
|
||||
tx_flags_extra |= (skb->ip_summed == CHECKSUM_HW ? (NV_TX2_CHECKSUM_L3|NV_TX2_CHECKSUM_L4) : 0);
|
||||
|
||||
np->tx_dma[nr] = pci_map_single(np->pci_dev, skb->data, skb->len-skb->data_len,
|
||||
PCI_DMA_TODEVICE);
|
||||
|
||||
if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
|
||||
np->tx_ring.orig[nr].PacketBuffer = cpu_to_le32(np->tx_dma[nr]);
|
||||
np->tx_ring.orig[nr].FlagLen = cpu_to_le32( (skb->len-skb->data_len-1) | np->tx_flags | tx_flags_extra);
|
||||
} else {
|
||||
np->tx_ring.ex[nr].PacketBufferHigh = cpu_to_le64(np->tx_dma[nr]) >> 32;
|
||||
np->tx_ring.ex[nr].PacketBufferLow = cpu_to_le64(np->tx_dma[nr]) & 0x0FFFFFFFF;
|
||||
np->tx_ring.ex[nr].FlagLen = cpu_to_le32( (skb->len-skb->data_len-1) | np->tx_flags | tx_flags_extra);
|
||||
}
|
||||
|
||||
dprintk(KERN_DEBUG "%s: nv_start_xmit: packet packet %d queued for transmission. tx_flags_extra: %x\n",
|
||||
dev->name, np->next_tx, tx_flags_extra);
|
||||
{
|
||||
int j;
|
||||
for (j=0; j<64; j++) {
|
||||
@ -991,15 +1068,13 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
dprintk("\n");
|
||||
}
|
||||
|
||||
np->next_tx++;
|
||||
np->next_tx += 1 + fragments;
|
||||
|
||||
dev->trans_start = jiffies;
|
||||
if (np->next_tx - np->nic_tx >= TX_LIMIT_STOP)
|
||||
netif_stop_queue(dev);
|
||||
spin_unlock_irq(&np->lock);
|
||||
writel(NVREG_TXRXCTL_KICK|np->desc_ver, get_hwbase(dev) + NvRegTxRxControl);
|
||||
writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl);
|
||||
pci_push(get_hwbase(dev));
|
||||
return 0;
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1009,9 +1084,10 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
*/
|
||||
static void nv_tx_done(struct net_device *dev)
|
||||
{
|
||||
struct fe_priv *np = get_nvpriv(dev);
|
||||
struct fe_priv *np = netdev_priv(dev);
|
||||
u32 Flags;
|
||||
int i;
|
||||
unsigned int i;
|
||||
struct sk_buff *skb;
|
||||
|
||||
while (np->nic_tx != np->next_tx) {
|
||||
i = np->nic_tx % TX_RING;
|
||||
@ -1026,35 +1102,38 @@ static void nv_tx_done(struct net_device *dev)
|
||||
if (Flags & NV_TX_VALID)
|
||||
break;
|
||||
if (np->desc_ver == DESC_VER_1) {
|
||||
if (Flags & (NV_TX_RETRYERROR|NV_TX_CARRIERLOST|NV_TX_LATECOLLISION|
|
||||
NV_TX_UNDERFLOW|NV_TX_ERROR)) {
|
||||
if (Flags & NV_TX_UNDERFLOW)
|
||||
np->stats.tx_fifo_errors++;
|
||||
if (Flags & NV_TX_CARRIERLOST)
|
||||
np->stats.tx_carrier_errors++;
|
||||
np->stats.tx_errors++;
|
||||
} else {
|
||||
np->stats.tx_packets++;
|
||||
np->stats.tx_bytes += np->tx_skbuff[i]->len;
|
||||
if (Flags & NV_TX_LASTPACKET) {
|
||||
skb = np->tx_skbuff[i];
|
||||
if (Flags & (NV_TX_RETRYERROR|NV_TX_CARRIERLOST|NV_TX_LATECOLLISION|
|
||||
NV_TX_UNDERFLOW|NV_TX_ERROR)) {
|
||||
if (Flags & NV_TX_UNDERFLOW)
|
||||
np->stats.tx_fifo_errors++;
|
||||
if (Flags & NV_TX_CARRIERLOST)
|
||||
np->stats.tx_carrier_errors++;
|
||||
np->stats.tx_errors++;
|
||||
} else {
|
||||
np->stats.tx_packets++;
|
||||
np->stats.tx_bytes += skb->len;
|
||||
}
|
||||
nv_release_txskb(dev, i);
|
||||
}
|
||||
} else {
|
||||
if (Flags & (NV_TX2_RETRYERROR|NV_TX2_CARRIERLOST|NV_TX2_LATECOLLISION|
|
||||
NV_TX2_UNDERFLOW|NV_TX2_ERROR)) {
|
||||
if (Flags & NV_TX2_UNDERFLOW)
|
||||
np->stats.tx_fifo_errors++;
|
||||
if (Flags & NV_TX2_CARRIERLOST)
|
||||
np->stats.tx_carrier_errors++;
|
||||
np->stats.tx_errors++;
|
||||
} else {
|
||||
np->stats.tx_packets++;
|
||||
np->stats.tx_bytes += np->tx_skbuff[i]->len;
|
||||
if (Flags & NV_TX2_LASTPACKET) {
|
||||
skb = np->tx_skbuff[i];
|
||||
if (Flags & (NV_TX2_RETRYERROR|NV_TX2_CARRIERLOST|NV_TX2_LATECOLLISION|
|
||||
NV_TX2_UNDERFLOW|NV_TX2_ERROR)) {
|
||||
if (Flags & NV_TX2_UNDERFLOW)
|
||||
np->stats.tx_fifo_errors++;
|
||||
if (Flags & NV_TX2_CARRIERLOST)
|
||||
np->stats.tx_carrier_errors++;
|
||||
np->stats.tx_errors++;
|
||||
} else {
|
||||
np->stats.tx_packets++;
|
||||
np->stats.tx_bytes += skb->len;
|
||||
}
|
||||
nv_release_txskb(dev, i);
|
||||
}
|
||||
}
|
||||
pci_unmap_single(np->pci_dev, np->tx_dma[i],
|
||||
np->tx_skbuff[i]->len,
|
||||
PCI_DMA_TODEVICE);
|
||||
dev_kfree_skb_irq(np->tx_skbuff[i]);
|
||||
np->tx_skbuff[i] = NULL;
|
||||
np->nic_tx++;
|
||||
}
|
||||
if (np->next_tx - np->nic_tx < TX_LIMIT_START)
|
||||
@ -1067,7 +1146,7 @@ static void nv_tx_done(struct net_device *dev)
|
||||
*/
|
||||
static void nv_tx_timeout(struct net_device *dev)
|
||||
{
|
||||
struct fe_priv *np = get_nvpriv(dev);
|
||||
struct fe_priv *np = netdev_priv(dev);
|
||||
u8 __iomem *base = get_hwbase(dev);
|
||||
|
||||
printk(KERN_INFO "%s: Got tx_timeout. irq: %08x\n", dev->name,
|
||||
@ -1200,7 +1279,7 @@ static int nv_getlen(struct net_device *dev, void *packet, int datalen)
|
||||
|
||||
static void nv_rx_process(struct net_device *dev)
|
||||
{
|
||||
struct fe_priv *np = get_nvpriv(dev);
|
||||
struct fe_priv *np = netdev_priv(dev);
|
||||
u32 Flags;
|
||||
|
||||
for (;;) {
|
||||
@ -1355,7 +1434,7 @@ static void set_bufsize(struct net_device *dev)
|
||||
*/
|
||||
static int nv_change_mtu(struct net_device *dev, int new_mtu)
|
||||
{
|
||||
struct fe_priv *np = get_nvpriv(dev);
|
||||
struct fe_priv *np = netdev_priv(dev);
|
||||
int old_mtu;
|
||||
|
||||
if (new_mtu < 64 || new_mtu > np->pkt_limit)
|
||||
@ -1408,7 +1487,7 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu)
|
||||
writel( ((RX_RING-1) << NVREG_RINGSZ_RXSHIFT) + ((TX_RING-1) << NVREG_RINGSZ_TXSHIFT),
|
||||
base + NvRegRingSizes);
|
||||
pci_push(base);
|
||||
writel(NVREG_TXRXCTL_KICK|np->desc_ver, get_hwbase(dev) + NvRegTxRxControl);
|
||||
writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl);
|
||||
pci_push(base);
|
||||
|
||||
/* restart rx engine */
|
||||
@ -1440,7 +1519,7 @@ static void nv_copy_mac_to_hw(struct net_device *dev)
|
||||
*/
|
||||
static int nv_set_mac_address(struct net_device *dev, void *addr)
|
||||
{
|
||||
struct fe_priv *np = get_nvpriv(dev);
|
||||
struct fe_priv *np = netdev_priv(dev);
|
||||
struct sockaddr *macaddr = (struct sockaddr*)addr;
|
||||
|
||||
if(!is_valid_ether_addr(macaddr->sa_data))
|
||||
@ -1475,7 +1554,7 @@ static int nv_set_mac_address(struct net_device *dev, void *addr)
|
||||
*/
|
||||
static void nv_set_multicast(struct net_device *dev)
|
||||
{
|
||||
struct fe_priv *np = get_nvpriv(dev);
|
||||
struct fe_priv *np = netdev_priv(dev);
|
||||
u8 __iomem *base = get_hwbase(dev);
|
||||
u32 addr[2];
|
||||
u32 mask[2];
|
||||
@ -1535,7 +1614,7 @@ static void nv_set_multicast(struct net_device *dev)
|
||||
|
||||
static int nv_update_linkspeed(struct net_device *dev)
|
||||
{
|
||||
struct fe_priv *np = get_nvpriv(dev);
|
||||
struct fe_priv *np = netdev_priv(dev);
|
||||
u8 __iomem *base = get_hwbase(dev);
|
||||
int adv, lpa;
|
||||
int newls = np->linkspeed;
|
||||
@ -1705,7 +1784,7 @@ static void nv_link_irq(struct net_device *dev)
|
||||
static irqreturn_t nv_nic_irq(int foo, void *data, struct pt_regs *regs)
|
||||
{
|
||||
struct net_device *dev = (struct net_device *) data;
|
||||
struct fe_priv *np = get_nvpriv(dev);
|
||||
struct fe_priv *np = netdev_priv(dev);
|
||||
u8 __iomem *base = get_hwbase(dev);
|
||||
u32 events;
|
||||
int i;
|
||||
@ -1777,7 +1856,7 @@ static irqreturn_t nv_nic_irq(int foo, void *data, struct pt_regs *regs)
|
||||
static void nv_do_nic_poll(unsigned long data)
|
||||
{
|
||||
struct net_device *dev = (struct net_device *) data;
|
||||
struct fe_priv *np = get_nvpriv(dev);
|
||||
struct fe_priv *np = netdev_priv(dev);
|
||||
u8 __iomem *base = get_hwbase(dev);
|
||||
|
||||
disable_irq(dev->irq);
|
||||
@ -1801,7 +1880,7 @@ static void nv_poll_controller(struct net_device *dev)
|
||||
|
||||
static void nv_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
|
||||
{
|
||||
struct fe_priv *np = get_nvpriv(dev);
|
||||
struct fe_priv *np = netdev_priv(dev);
|
||||
strcpy(info->driver, "forcedeth");
|
||||
strcpy(info->version, FORCEDETH_VERSION);
|
||||
strcpy(info->bus_info, pci_name(np->pci_dev));
|
||||
@ -1809,7 +1888,7 @@ static void nv_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
|
||||
|
||||
static void nv_get_wol(struct net_device *dev, struct ethtool_wolinfo *wolinfo)
|
||||
{
|
||||
struct fe_priv *np = get_nvpriv(dev);
|
||||
struct fe_priv *np = netdev_priv(dev);
|
||||
wolinfo->supported = WAKE_MAGIC;
|
||||
|
||||
spin_lock_irq(&np->lock);
|
||||
@ -1820,7 +1899,7 @@ static void nv_get_wol(struct net_device *dev, struct ethtool_wolinfo *wolinfo)
|
||||
|
||||
static int nv_set_wol(struct net_device *dev, struct ethtool_wolinfo *wolinfo)
|
||||
{
|
||||
struct fe_priv *np = get_nvpriv(dev);
|
||||
struct fe_priv *np = netdev_priv(dev);
|
||||
u8 __iomem *base = get_hwbase(dev);
|
||||
|
||||
spin_lock_irq(&np->lock);
|
||||
@ -2021,7 +2100,7 @@ static int nv_get_regs_len(struct net_device *dev)
|
||||
|
||||
static void nv_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *buf)
|
||||
{
|
||||
struct fe_priv *np = get_nvpriv(dev);
|
||||
struct fe_priv *np = netdev_priv(dev);
|
||||
u8 __iomem *base = get_hwbase(dev);
|
||||
u32 *rbuf = buf;
|
||||
int i;
|
||||
@ -2035,7 +2114,7 @@ static void nv_get_regs(struct net_device *dev, struct ethtool_regs *regs, void
|
||||
|
||||
static int nv_nway_reset(struct net_device *dev)
|
||||
{
|
||||
struct fe_priv *np = get_nvpriv(dev);
|
||||
struct fe_priv *np = netdev_priv(dev);
|
||||
int ret;
|
||||
|
||||
spin_lock_irq(&np->lock);
|
||||
@ -2065,11 +2144,12 @@ static struct ethtool_ops ops = {
|
||||
.get_regs_len = nv_get_regs_len,
|
||||
.get_regs = nv_get_regs,
|
||||
.nway_reset = nv_nway_reset,
|
||||
.get_perm_addr = ethtool_op_get_perm_addr,
|
||||
};
|
||||
|
||||
static int nv_open(struct net_device *dev)
|
||||
{
|
||||
struct fe_priv *np = get_nvpriv(dev);
|
||||
struct fe_priv *np = netdev_priv(dev);
|
||||
u8 __iomem *base = get_hwbase(dev);
|
||||
int ret, oom, i;
|
||||
|
||||
@ -2114,9 +2194,9 @@ static int nv_open(struct net_device *dev)
|
||||
/* 5) continue setup */
|
||||
writel(np->linkspeed, base + NvRegLinkSpeed);
|
||||
writel(NVREG_UNKSETUP3_VAL1, base + NvRegUnknownSetupReg3);
|
||||
writel(np->desc_ver, base + NvRegTxRxControl);
|
||||
writel(np->txrxctl_bits, base + NvRegTxRxControl);
|
||||
pci_push(base);
|
||||
writel(NVREG_TXRXCTL_BIT1|np->desc_ver, base + NvRegTxRxControl);
|
||||
writel(NVREG_TXRXCTL_BIT1|np->txrxctl_bits, base + NvRegTxRxControl);
|
||||
reg_delay(dev, NvRegUnknownSetupReg5, NVREG_UNKSETUP5_BIT31, NVREG_UNKSETUP5_BIT31,
|
||||
NV_SETUP5_DELAY, NV_SETUP5_DELAYMAX,
|
||||
KERN_INFO "open: SetupReg5, Bit 31 remained off\n");
|
||||
@ -2205,7 +2285,7 @@ static int nv_open(struct net_device *dev)
|
||||
|
||||
static int nv_close(struct net_device *dev)
|
||||
{
|
||||
struct fe_priv *np = get_nvpriv(dev);
|
||||
struct fe_priv *np = netdev_priv(dev);
|
||||
u8 __iomem *base;
|
||||
|
||||
spin_lock_irq(&np->lock);
|
||||
@ -2261,7 +2341,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
|
||||
if (!dev)
|
||||
goto out;
|
||||
|
||||
np = get_nvpriv(dev);
|
||||
np = netdev_priv(dev);
|
||||
np->pci_dev = pci_dev;
|
||||
spin_lock_init(&np->lock);
|
||||
SET_MODULE_OWNER(dev);
|
||||
@ -2313,19 +2393,32 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
|
||||
if (pci_set_dma_mask(pci_dev, 0x0000007fffffffffULL)) {
|
||||
printk(KERN_INFO "forcedeth: 64-bit DMA failed, using 32-bit addressing for device %s.\n",
|
||||
pci_name(pci_dev));
|
||||
} else {
|
||||
dev->features |= NETIF_F_HIGHDMA;
|
||||
}
|
||||
np->txrxctl_bits = NVREG_TXRXCTL_DESC_3;
|
||||
} else if (id->driver_data & DEV_HAS_LARGEDESC) {
|
||||
/* packet format 2: supports jumbo frames */
|
||||
np->desc_ver = DESC_VER_2;
|
||||
np->txrxctl_bits = NVREG_TXRXCTL_DESC_2;
|
||||
} else {
|
||||
/* original packet format */
|
||||
np->desc_ver = DESC_VER_1;
|
||||
np->txrxctl_bits = NVREG_TXRXCTL_DESC_1;
|
||||
}
|
||||
|
||||
np->pkt_limit = NV_PKTLIMIT_1;
|
||||
if (id->driver_data & DEV_HAS_LARGEDESC)
|
||||
np->pkt_limit = NV_PKTLIMIT_2;
|
||||
|
||||
if (id->driver_data & DEV_HAS_CHECKSUM) {
|
||||
np->txrxctl_bits |= NVREG_TXRXCTL_RXCHECK;
|
||||
dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG;
|
||||
#ifdef NETIF_F_TSO
|
||||
dev->features |= NETIF_F_TSO;
|
||||
#endif
|
||||
}
|
||||
|
||||
err = -ENOMEM;
|
||||
np->base = ioremap(addr, NV_PCI_REGSZ);
|
||||
if (!np->base)
|
||||
@ -2377,8 +2470,9 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
|
||||
dev->dev_addr[3] = (np->orig_mac[0] >> 16) & 0xff;
|
||||
dev->dev_addr[4] = (np->orig_mac[0] >> 8) & 0xff;
|
||||
dev->dev_addr[5] = (np->orig_mac[0] >> 0) & 0xff;
|
||||
memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
|
||||
|
||||
if (!is_valid_ether_addr(dev->dev_addr)) {
|
||||
if (!is_valid_ether_addr(dev->perm_addr)) {
|
||||
/*
|
||||
* Bad mac address. At least one bios sets the mac address
|
||||
* to 01:23:45:67:89:ab
|
||||
@ -2403,9 +2497,9 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
|
||||
np->wolenabled = 0;
|
||||
|
||||
if (np->desc_ver == DESC_VER_1) {
|
||||
np->tx_flags = NV_TX_LASTPACKET|NV_TX_VALID;
|
||||
np->tx_flags = NV_TX_VALID;
|
||||
} else {
|
||||
np->tx_flags = NV_TX2_LASTPACKET|NV_TX2_VALID;
|
||||
np->tx_flags = NV_TX2_VALID;
|
||||
}
|
||||
np->irqmask = NVREG_IRQMASK_WANTED;
|
||||
if (id->driver_data & DEV_NEED_TIMERIRQ)
|
||||
@ -2494,7 +2588,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
|
||||
static void __devexit nv_remove(struct pci_dev *pci_dev)
|
||||
{
|
||||
struct net_device *dev = pci_get_drvdata(pci_dev);
|
||||
struct fe_priv *np = get_nvpriv(dev);
|
||||
struct fe_priv *np = netdev_priv(dev);
|
||||
|
||||
unregister_netdev(dev);
|
||||
|
||||
@ -2525,35 +2619,35 @@ static struct pci_device_id pci_tbl[] = {
|
||||
},
|
||||
{ /* nForce3 Ethernet Controller */
|
||||
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_4),
|
||||
.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
|
||||
.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM,
|
||||
},
|
||||
{ /* nForce3 Ethernet Controller */
|
||||
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_5),
|
||||
.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
|
||||
.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM,
|
||||
},
|
||||
{ /* nForce3 Ethernet Controller */
|
||||
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_6),
|
||||
.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
|
||||
.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM,
|
||||
},
|
||||
{ /* nForce3 Ethernet Controller */
|
||||
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_7),
|
||||
.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
|
||||
.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM,
|
||||
},
|
||||
{ /* CK804 Ethernet Controller */
|
||||
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_8),
|
||||
.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA,
|
||||
.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA,
|
||||
},
|
||||
{ /* CK804 Ethernet Controller */
|
||||
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_9),
|
||||
.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA,
|
||||
.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA,
|
||||
},
|
||||
{ /* MCP04 Ethernet Controller */
|
||||
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_10),
|
||||
.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA,
|
||||
.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA,
|
||||
},
|
||||
{ /* MCP04 Ethernet Controller */
|
||||
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_11),
|
||||
.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA,
|
||||
.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA,
|
||||
},
|
||||
{ /* MCP51 Ethernet Controller */
|
||||
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_12),
|
||||
@ -2565,11 +2659,11 @@ static struct pci_device_id pci_tbl[] = {
|
||||
},
|
||||
{ /* MCP55 Ethernet Controller */
|
||||
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_14),
|
||||
.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA,
|
||||
.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA,
|
||||
},
|
||||
{ /* MCP55 Ethernet Controller */
|
||||
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_15),
|
||||
.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA,
|
||||
.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA,
|
||||
},
|
||||
{0,},
|
||||
};
|
||||
|
@ -29,12 +29,7 @@
|
||||
* define the configuration needed by the board are defined in a
|
||||
* board structure in arch/ppc/platforms (though I do not
|
||||
* discount the possibility that other architectures could one
|
||||
* day be supported. One assumption the driver currently makes
|
||||
* is that the PHY is configured in such a way to advertise all
|
||||
* capabilities. This is a sensible default, and on certain
|
||||
* PHYs, changing this default encounters substantial errata
|
||||
* issues. Future versions may remove this requirement, but for
|
||||
* now, it is best for the firmware to ensure this is the case.
|
||||
* day be supported.
|
||||
*
|
||||
* The Gianfar Ethernet Controller uses a ring of buffer
|
||||
* descriptors. The beginning is indicated by a register
|
||||
@ -47,7 +42,7 @@
|
||||
* corresponding bit in the IMASK register is also set (if
|
||||
* interrupt coalescing is active, then the interrupt may not
|
||||
* happen immediately, but will wait until either a set number
|
||||
* of frames or amount of time have passed.). In NAPI, the
|
||||
* of frames or amount of time have passed). In NAPI, the
|
||||
* interrupt handler will signal there is work to be done, and
|
||||
* exit. Without NAPI, the packet(s) will be handled
|
||||
* immediately. Both methods will start at the last known empty
|
||||
@ -75,6 +70,7 @@
|
||||
#include <linux/sched.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/unistd.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/init.h>
|
||||
@ -97,9 +93,11 @@
|
||||
#include <linux/version.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/crc32.h>
|
||||
#include <linux/mii.h>
|
||||
#include <linux/phy.h>
|
||||
|
||||
#include "gianfar.h"
|
||||
#include "gianfar_phy.h"
|
||||
#include "gianfar_mii.h"
|
||||
|
||||
#define TX_TIMEOUT (1*HZ)
|
||||
#define SKB_ALLOC_TIMEOUT 1000000
|
||||
@ -113,9 +111,8 @@
|
||||
#endif
|
||||
|
||||
const char gfar_driver_name[] = "Gianfar Ethernet";
|
||||
const char gfar_driver_version[] = "1.1";
|
||||
const char gfar_driver_version[] = "1.2";
|
||||
|
||||
int startup_gfar(struct net_device *dev);
|
||||
static int gfar_enet_open(struct net_device *dev);
|
||||
static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev);
|
||||
static void gfar_timeout(struct net_device *dev);
|
||||
@ -126,17 +123,13 @@ static int gfar_set_mac_address(struct net_device *dev);
|
||||
static int gfar_change_mtu(struct net_device *dev, int new_mtu);
|
||||
static irqreturn_t gfar_error(int irq, void *dev_id, struct pt_regs *regs);
|
||||
static irqreturn_t gfar_transmit(int irq, void *dev_id, struct pt_regs *regs);
|
||||
static irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs);
|
||||
static irqreturn_t gfar_interrupt(int irq, void *dev_id, struct pt_regs *regs);
|
||||
static irqreturn_t phy_interrupt(int irq, void *dev_id, struct pt_regs *regs);
|
||||
static void gfar_phy_change(void *data);
|
||||
static void gfar_phy_timer(unsigned long data);
|
||||
static void adjust_link(struct net_device *dev);
|
||||
static void init_registers(struct net_device *dev);
|
||||
static int init_phy(struct net_device *dev);
|
||||
static int gfar_probe(struct device *device);
|
||||
static int gfar_remove(struct device *device);
|
||||
void free_skb_resources(struct gfar_private *priv);
|
||||
static void free_skb_resources(struct gfar_private *priv);
|
||||
static void gfar_set_multi(struct net_device *dev);
|
||||
static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr);
|
||||
#ifdef CONFIG_GFAR_NAPI
|
||||
@ -144,7 +137,6 @@ static int gfar_poll(struct net_device *dev, int *budget);
|
||||
#endif
|
||||
int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit);
|
||||
static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, int length);
|
||||
static void gfar_phy_startup_timer(unsigned long data);
|
||||
static void gfar_vlan_rx_register(struct net_device *netdev,
|
||||
struct vlan_group *grp);
|
||||
static void gfar_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid);
|
||||
@ -162,6 +154,9 @@ int gfar_uses_fcb(struct gfar_private *priv)
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set up the ethernet device structure, private data,
|
||||
* and anything else we need before we start */
|
||||
static int gfar_probe(struct device *device)
|
||||
{
|
||||
u32 tempval;
|
||||
@ -175,7 +170,7 @@ static int gfar_probe(struct device *device)
|
||||
|
||||
einfo = (struct gianfar_platform_data *) pdev->dev.platform_data;
|
||||
|
||||
if (einfo == NULL) {
|
||||
if (NULL == einfo) {
|
||||
printk(KERN_ERR "gfar %d: Missing additional data!\n",
|
||||
pdev->id);
|
||||
|
||||
@ -185,7 +180,7 @@ static int gfar_probe(struct device *device)
|
||||
/* Create an ethernet device instance */
|
||||
dev = alloc_etherdev(sizeof (*priv));
|
||||
|
||||
if (dev == NULL)
|
||||
if (NULL == dev)
|
||||
return -ENOMEM;
|
||||
|
||||
priv = netdev_priv(dev);
|
||||
@ -207,20 +202,11 @@ static int gfar_probe(struct device *device)
|
||||
priv->regs = (struct gfar *)
|
||||
ioremap(r->start, sizeof (struct gfar));
|
||||
|
||||
if (priv->regs == NULL) {
|
||||
if (NULL == priv->regs) {
|
||||
err = -ENOMEM;
|
||||
goto regs_fail;
|
||||
}
|
||||
|
||||
/* Set the PHY base address */
|
||||
priv->phyregs = (struct gfar *)
|
||||
ioremap(einfo->phy_reg_addr, sizeof (struct gfar));
|
||||
|
||||
if (priv->phyregs == NULL) {
|
||||
err = -ENOMEM;
|
||||
goto phy_regs_fail;
|
||||
}
|
||||
|
||||
spin_lock_init(&priv->lock);
|
||||
|
||||
dev_set_drvdata(device, dev);
|
||||
@ -386,12 +372,10 @@ static int gfar_probe(struct device *device)
|
||||
return 0;
|
||||
|
||||
register_fail:
|
||||
iounmap((void *) priv->phyregs);
|
||||
phy_regs_fail:
|
||||
iounmap((void *) priv->regs);
|
||||
regs_fail:
|
||||
free_netdev(dev);
|
||||
return -ENOMEM;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int gfar_remove(struct device *device)
|
||||
@ -402,108 +386,41 @@ static int gfar_remove(struct device *device)
|
||||
dev_set_drvdata(device, NULL);
|
||||
|
||||
iounmap((void *) priv->regs);
|
||||
iounmap((void *) priv->phyregs);
|
||||
free_netdev(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Configure the PHY for dev.
|
||||
* returns 0 if success. -1 if failure
|
||||
/* Initializes driver's PHY state, and attaches to the PHY.
|
||||
* Returns 0 on success.
|
||||
*/
|
||||
static int init_phy(struct net_device *dev)
|
||||
{
|
||||
struct gfar_private *priv = netdev_priv(dev);
|
||||
struct phy_info *curphy;
|
||||
unsigned int timeout = PHY_INIT_TIMEOUT;
|
||||
struct gfar *phyregs = priv->phyregs;
|
||||
struct gfar_mii_info *mii_info;
|
||||
int err;
|
||||
uint gigabit_support =
|
||||
priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT ?
|
||||
SUPPORTED_1000baseT_Full : 0;
|
||||
struct phy_device *phydev;
|
||||
|
||||
priv->oldlink = 0;
|
||||
priv->oldspeed = 0;
|
||||
priv->oldduplex = -1;
|
||||
|
||||
mii_info = kmalloc(sizeof(struct gfar_mii_info),
|
||||
GFP_KERNEL);
|
||||
phydev = phy_connect(dev, priv->einfo->bus_id, &adjust_link, 0);
|
||||
|
||||
if(NULL == mii_info) {
|
||||
if (netif_msg_ifup(priv))
|
||||
printk(KERN_ERR "%s: Could not allocate mii_info\n",
|
||||
dev->name);
|
||||
return -ENOMEM;
|
||||
if (IS_ERR(phydev)) {
|
||||
printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
|
||||
return PTR_ERR(phydev);
|
||||
}
|
||||
|
||||
mii_info->speed = SPEED_1000;
|
||||
mii_info->duplex = DUPLEX_FULL;
|
||||
mii_info->pause = 0;
|
||||
mii_info->link = 1;
|
||||
/* Remove any features not supported by the controller */
|
||||
phydev->supported &= (GFAR_SUPPORTED | gigabit_support);
|
||||
phydev->advertising = phydev->supported;
|
||||
|
||||
mii_info->advertising = (ADVERTISED_10baseT_Half |
|
||||
ADVERTISED_10baseT_Full |
|
||||
ADVERTISED_100baseT_Half |
|
||||
ADVERTISED_100baseT_Full |
|
||||
ADVERTISED_1000baseT_Full);
|
||||
mii_info->autoneg = 1;
|
||||
|
||||
spin_lock_init(&mii_info->mdio_lock);
|
||||
|
||||
mii_info->mii_id = priv->einfo->phyid;
|
||||
|
||||
mii_info->dev = dev;
|
||||
|
||||
mii_info->mdio_read = &read_phy_reg;
|
||||
mii_info->mdio_write = &write_phy_reg;
|
||||
|
||||
priv->mii_info = mii_info;
|
||||
|
||||
/* Reset the management interface */
|
||||
gfar_write(&phyregs->miimcfg, MIIMCFG_RESET);
|
||||
|
||||
/* Setup the MII Mgmt clock speed */
|
||||
gfar_write(&phyregs->miimcfg, MIIMCFG_INIT_VALUE);
|
||||
|
||||
/* Wait until the bus is free */
|
||||
while ((gfar_read(&phyregs->miimind) & MIIMIND_BUSY) &&
|
||||
timeout--)
|
||||
cpu_relax();
|
||||
|
||||
if(timeout <= 0) {
|
||||
printk(KERN_ERR "%s: The MII Bus is stuck!\n",
|
||||
dev->name);
|
||||
err = -1;
|
||||
goto bus_fail;
|
||||
}
|
||||
|
||||
/* get info for this PHY */
|
||||
curphy = get_phy_info(priv->mii_info);
|
||||
|
||||
if (curphy == NULL) {
|
||||
if (netif_msg_ifup(priv))
|
||||
printk(KERN_ERR "%s: No PHY found\n", dev->name);
|
||||
err = -1;
|
||||
goto no_phy;
|
||||
}
|
||||
|
||||
mii_info->phyinfo = curphy;
|
||||
|
||||
/* Run the commands which initialize the PHY */
|
||||
if(curphy->init) {
|
||||
err = curphy->init(priv->mii_info);
|
||||
|
||||
if (err)
|
||||
goto phy_init_fail;
|
||||
}
|
||||
priv->phydev = phydev;
|
||||
|
||||
return 0;
|
||||
|
||||
phy_init_fail:
|
||||
no_phy:
|
||||
bus_fail:
|
||||
kfree(mii_info);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void init_registers(struct net_device *dev)
|
||||
@ -603,24 +520,13 @@ void stop_gfar(struct net_device *dev)
|
||||
struct gfar *regs = priv->regs;
|
||||
unsigned long flags;
|
||||
|
||||
phy_stop(priv->phydev);
|
||||
|
||||
/* Lock it down */
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
|
||||
/* Tell the kernel the link is down */
|
||||
priv->mii_info->link = 0;
|
||||
adjust_link(dev);
|
||||
|
||||
gfar_halt(dev);
|
||||
|
||||
if (priv->einfo->board_flags & FSL_GIANFAR_BRD_HAS_PHY_INTR) {
|
||||
/* Clear any pending interrupts */
|
||||
mii_clear_phy_interrupt(priv->mii_info);
|
||||
|
||||
/* Disable PHY Interrupts */
|
||||
mii_configure_phy_interrupt(priv->mii_info,
|
||||
MII_INTERRUPT_DISABLED);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
/* Free the IRQs */
|
||||
@ -629,13 +535,7 @@ void stop_gfar(struct net_device *dev)
|
||||
free_irq(priv->interruptTransmit, dev);
|
||||
free_irq(priv->interruptReceive, dev);
|
||||
} else {
|
||||
free_irq(priv->interruptTransmit, dev);
|
||||
}
|
||||
|
||||
if (priv->einfo->board_flags & FSL_GIANFAR_BRD_HAS_PHY_INTR) {
|
||||
free_irq(priv->einfo->interruptPHY, dev);
|
||||
} else {
|
||||
del_timer_sync(&priv->phy_info_timer);
|
||||
free_irq(priv->interruptTransmit, dev);
|
||||
}
|
||||
|
||||
free_skb_resources(priv);
|
||||
@ -649,7 +549,7 @@ void stop_gfar(struct net_device *dev)
|
||||
|
||||
/* If there are any tx skbs or rx skbs still around, free them.
|
||||
* Then free tx_skbuff and rx_skbuff */
|
||||
void free_skb_resources(struct gfar_private *priv)
|
||||
static void free_skb_resources(struct gfar_private *priv)
|
||||
{
|
||||
struct rxbd8 *rxbdp;
|
||||
struct txbd8 *txbdp;
|
||||
@ -770,7 +670,7 @@ int startup_gfar(struct net_device *dev)
|
||||
(struct sk_buff **) kmalloc(sizeof (struct sk_buff *) *
|
||||
priv->tx_ring_size, GFP_KERNEL);
|
||||
|
||||
if (priv->tx_skbuff == NULL) {
|
||||
if (NULL == priv->tx_skbuff) {
|
||||
if (netif_msg_ifup(priv))
|
||||
printk(KERN_ERR "%s: Could not allocate tx_skbuff\n",
|
||||
dev->name);
|
||||
@ -785,7 +685,7 @@ int startup_gfar(struct net_device *dev)
|
||||
(struct sk_buff **) kmalloc(sizeof (struct sk_buff *) *
|
||||
priv->rx_ring_size, GFP_KERNEL);
|
||||
|
||||
if (priv->rx_skbuff == NULL) {
|
||||
if (NULL == priv->rx_skbuff) {
|
||||
if (netif_msg_ifup(priv))
|
||||
printk(KERN_ERR "%s: Could not allocate rx_skbuff\n",
|
||||
dev->name);
|
||||
@ -879,13 +779,7 @@ int startup_gfar(struct net_device *dev)
|
||||
}
|
||||
}
|
||||
|
||||
/* Set up the PHY change work queue */
|
||||
INIT_WORK(&priv->tq, gfar_phy_change, dev);
|
||||
|
||||
init_timer(&priv->phy_info_timer);
|
||||
priv->phy_info_timer.function = &gfar_phy_startup_timer;
|
||||
priv->phy_info_timer.data = (unsigned long) priv->mii_info;
|
||||
mod_timer(&priv->phy_info_timer, jiffies + HZ);
|
||||
phy_start(priv->phydev);
|
||||
|
||||
/* Configure the coalescing support */
|
||||
if (priv->txcoalescing)
|
||||
@ -933,11 +827,6 @@ int startup_gfar(struct net_device *dev)
|
||||
priv->tx_bd_base,
|
||||
gfar_read(®s->tbase0));
|
||||
|
||||
if (priv->mii_info->phyinfo->close)
|
||||
priv->mii_info->phyinfo->close(priv->mii_info);
|
||||
|
||||
kfree(priv->mii_info);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -1035,7 +924,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
txbdp->status &= TXBD_WRAP;
|
||||
|
||||
/* Set up checksumming */
|
||||
if ((dev->features & NETIF_F_IP_CSUM)
|
||||
if ((dev->features & NETIF_F_IP_CSUM)
|
||||
&& (CHECKSUM_HW == skb->ip_summed)) {
|
||||
fcb = gfar_add_fcb(skb, txbdp);
|
||||
gfar_tx_checksum(skb, fcb);
|
||||
@ -1103,11 +992,9 @@ static int gfar_close(struct net_device *dev)
|
||||
struct gfar_private *priv = netdev_priv(dev);
|
||||
stop_gfar(dev);
|
||||
|
||||
/* Shutdown the PHY */
|
||||
if (priv->mii_info->phyinfo->close)
|
||||
priv->mii_info->phyinfo->close(priv->mii_info);
|
||||
|
||||
kfree(priv->mii_info);
|
||||
/* Disconnect from the PHY */
|
||||
phy_disconnect(priv->phydev);
|
||||
priv->phydev = NULL;
|
||||
|
||||
netif_stop_queue(dev);
|
||||
|
||||
@ -1343,7 +1230,7 @@ struct sk_buff * gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp)
|
||||
while ((!skb) && timeout--)
|
||||
skb = dev_alloc_skb(priv->rx_buffer_size + RXBUF_ALIGNMENT);
|
||||
|
||||
if (skb == NULL)
|
||||
if (NULL == skb)
|
||||
return NULL;
|
||||
|
||||
/* We need the data buffer to be aligned properly. We will reserve
|
||||
@ -1490,7 +1377,7 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb,
|
||||
struct gfar_private *priv = netdev_priv(dev);
|
||||
struct rxfcb *fcb = NULL;
|
||||
|
||||
if (skb == NULL) {
|
||||
if (NULL == skb) {
|
||||
if (netif_msg_rx_err(priv))
|
||||
printk(KERN_WARNING "%s: Missing skb!!.\n", dev->name);
|
||||
priv->stats.rx_dropped++;
|
||||
@ -1718,131 +1605,9 @@ static irqreturn_t gfar_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t phy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
struct net_device *dev = (struct net_device *) dev_id;
|
||||
struct gfar_private *priv = netdev_priv(dev);
|
||||
|
||||
/* Clear the interrupt */
|
||||
mii_clear_phy_interrupt(priv->mii_info);
|
||||
|
||||
/* Disable PHY interrupts */
|
||||
mii_configure_phy_interrupt(priv->mii_info,
|
||||
MII_INTERRUPT_DISABLED);
|
||||
|
||||
/* Schedule the phy change */
|
||||
schedule_work(&priv->tq);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/* Scheduled by the phy_interrupt/timer to handle PHY changes */
|
||||
static void gfar_phy_change(void *data)
|
||||
{
|
||||
struct net_device *dev = (struct net_device *) data;
|
||||
struct gfar_private *priv = netdev_priv(dev);
|
||||
int result = 0;
|
||||
|
||||
/* Delay to give the PHY a chance to change the
|
||||
* register state */
|
||||
msleep(1);
|
||||
|
||||
/* Update the link, speed, duplex */
|
||||
result = priv->mii_info->phyinfo->read_status(priv->mii_info);
|
||||
|
||||
/* Adjust the known status as long as the link
|
||||
* isn't still coming up */
|
||||
if((0 == result) || (priv->mii_info->link == 0))
|
||||
adjust_link(dev);
|
||||
|
||||
/* Reenable interrupts, if needed */
|
||||
if (priv->einfo->board_flags & FSL_GIANFAR_BRD_HAS_PHY_INTR)
|
||||
mii_configure_phy_interrupt(priv->mii_info,
|
||||
MII_INTERRUPT_ENABLED);
|
||||
}
|
||||
|
||||
/* Called every so often on systems that don't interrupt
|
||||
* the core for PHY changes */
|
||||
static void gfar_phy_timer(unsigned long data)
|
||||
{
|
||||
struct net_device *dev = (struct net_device *) data;
|
||||
struct gfar_private *priv = netdev_priv(dev);
|
||||
|
||||
schedule_work(&priv->tq);
|
||||
|
||||
mod_timer(&priv->phy_info_timer, jiffies +
|
||||
GFAR_PHY_CHANGE_TIME * HZ);
|
||||
}
|
||||
|
||||
/* Keep trying aneg for some time
|
||||
* If, after GFAR_AN_TIMEOUT seconds, it has not
|
||||
* finished, we switch to forced.
|
||||
* Either way, once the process has completed, we either
|
||||
* request the interrupt, or switch the timer over to
|
||||
* using gfar_phy_timer to check status */
|
||||
static void gfar_phy_startup_timer(unsigned long data)
|
||||
{
|
||||
int result;
|
||||
static int secondary = GFAR_AN_TIMEOUT;
|
||||
struct gfar_mii_info *mii_info = (struct gfar_mii_info *)data;
|
||||
struct gfar_private *priv = netdev_priv(mii_info->dev);
|
||||
|
||||
/* Configure the Auto-negotiation */
|
||||
result = mii_info->phyinfo->config_aneg(mii_info);
|
||||
|
||||
/* If autonegotiation failed to start, and
|
||||
* we haven't timed out, reset the timer, and return */
|
||||
if (result && secondary--) {
|
||||
mod_timer(&priv->phy_info_timer, jiffies + HZ);
|
||||
return;
|
||||
} else if (result) {
|
||||
/* Couldn't start autonegotiation.
|
||||
* Try switching to forced */
|
||||
mii_info->autoneg = 0;
|
||||
result = mii_info->phyinfo->config_aneg(mii_info);
|
||||
|
||||
/* Forcing failed! Give up */
|
||||
if(result) {
|
||||
if (netif_msg_link(priv))
|
||||
printk(KERN_ERR "%s: Forcing failed!\n",
|
||||
mii_info->dev->name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Kill the timer so it can be restarted */
|
||||
del_timer_sync(&priv->phy_info_timer);
|
||||
|
||||
/* Grab the PHY interrupt, if necessary/possible */
|
||||
if (priv->einfo->board_flags & FSL_GIANFAR_BRD_HAS_PHY_INTR) {
|
||||
if (request_irq(priv->einfo->interruptPHY,
|
||||
phy_interrupt,
|
||||
SA_SHIRQ,
|
||||
"phy_interrupt",
|
||||
mii_info->dev) < 0) {
|
||||
if (netif_msg_intr(priv))
|
||||
printk(KERN_ERR "%s: Can't get IRQ %d (PHY)\n",
|
||||
mii_info->dev->name,
|
||||
priv->einfo->interruptPHY);
|
||||
} else {
|
||||
mii_configure_phy_interrupt(priv->mii_info,
|
||||
MII_INTERRUPT_ENABLED);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Start the timer again, this time in order to
|
||||
* handle a change in status */
|
||||
init_timer(&priv->phy_info_timer);
|
||||
priv->phy_info_timer.function = &gfar_phy_timer;
|
||||
priv->phy_info_timer.data = (unsigned long) mii_info->dev;
|
||||
mod_timer(&priv->phy_info_timer, jiffies +
|
||||
GFAR_PHY_CHANGE_TIME * HZ);
|
||||
}
|
||||
|
||||
/* Called every time the controller might need to be made
|
||||
* aware of new link state. The PHY code conveys this
|
||||
* information through variables in the priv structure, and this
|
||||
* information through variables in the phydev structure, and this
|
||||
* function converts those variables into the appropriate
|
||||
* register values, and can bring down the device if needed.
|
||||
*/
|
||||
@ -1850,84 +1615,68 @@ static void adjust_link(struct net_device *dev)
|
||||
{
|
||||
struct gfar_private *priv = netdev_priv(dev);
|
||||
struct gfar *regs = priv->regs;
|
||||
u32 tempval;
|
||||
struct gfar_mii_info *mii_info = priv->mii_info;
|
||||
unsigned long flags;
|
||||
struct phy_device *phydev = priv->phydev;
|
||||
int new_state = 0;
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
if (phydev->link) {
|
||||
u32 tempval = gfar_read(®s->maccfg2);
|
||||
|
||||
if (mii_info->link) {
|
||||
/* Now we make sure that we can be in full duplex mode.
|
||||
* If not, we operate in half-duplex mode. */
|
||||
if (mii_info->duplex != priv->oldduplex) {
|
||||
if (!(mii_info->duplex)) {
|
||||
tempval = gfar_read(®s->maccfg2);
|
||||
if (phydev->duplex != priv->oldduplex) {
|
||||
new_state = 1;
|
||||
if (!(phydev->duplex))
|
||||
tempval &= ~(MACCFG2_FULL_DUPLEX);
|
||||
gfar_write(®s->maccfg2, tempval);
|
||||
|
||||
if (netif_msg_link(priv))
|
||||
printk(KERN_INFO "%s: Half Duplex\n",
|
||||
dev->name);
|
||||
} else {
|
||||
tempval = gfar_read(®s->maccfg2);
|
||||
else
|
||||
tempval |= MACCFG2_FULL_DUPLEX;
|
||||
gfar_write(®s->maccfg2, tempval);
|
||||
|
||||
if (netif_msg_link(priv))
|
||||
printk(KERN_INFO "%s: Full Duplex\n",
|
||||
dev->name);
|
||||
}
|
||||
|
||||
priv->oldduplex = mii_info->duplex;
|
||||
priv->oldduplex = phydev->duplex;
|
||||
}
|
||||
|
||||
if (mii_info->speed != priv->oldspeed) {
|
||||
switch (mii_info->speed) {
|
||||
if (phydev->speed != priv->oldspeed) {
|
||||
new_state = 1;
|
||||
switch (phydev->speed) {
|
||||
case 1000:
|
||||
tempval = gfar_read(®s->maccfg2);
|
||||
tempval =
|
||||
((tempval & ~(MACCFG2_IF)) | MACCFG2_GMII);
|
||||
gfar_write(®s->maccfg2, tempval);
|
||||
break;
|
||||
case 100:
|
||||
case 10:
|
||||
tempval = gfar_read(®s->maccfg2);
|
||||
tempval =
|
||||
((tempval & ~(MACCFG2_IF)) | MACCFG2_MII);
|
||||
gfar_write(®s->maccfg2, tempval);
|
||||
break;
|
||||
default:
|
||||
if (netif_msg_link(priv))
|
||||
printk(KERN_WARNING
|
||||
"%s: Ack! Speed (%d) is not 10/100/1000!\n",
|
||||
dev->name, mii_info->speed);
|
||||
"%s: Ack! Speed (%d) is not 10/100/1000!\n",
|
||||
dev->name, phydev->speed);
|
||||
break;
|
||||
}
|
||||
|
||||
if (netif_msg_link(priv))
|
||||
printk(KERN_INFO "%s: Speed %dBT\n", dev->name,
|
||||
mii_info->speed);
|
||||
|
||||
priv->oldspeed = mii_info->speed;
|
||||
priv->oldspeed = phydev->speed;
|
||||
}
|
||||
|
||||
gfar_write(®s->maccfg2, tempval);
|
||||
|
||||
if (!priv->oldlink) {
|
||||
if (netif_msg_link(priv))
|
||||
printk(KERN_INFO "%s: Link is up\n", dev->name);
|
||||
new_state = 1;
|
||||
priv->oldlink = 1;
|
||||
netif_carrier_on(dev);
|
||||
netif_schedule(dev);
|
||||
}
|
||||
} else {
|
||||
if (priv->oldlink) {
|
||||
if (netif_msg_link(priv))
|
||||
printk(KERN_INFO "%s: Link is down\n",
|
||||
dev->name);
|
||||
priv->oldlink = 0;
|
||||
priv->oldspeed = 0;
|
||||
priv->oldduplex = -1;
|
||||
netif_carrier_off(dev);
|
||||
}
|
||||
} else if (priv->oldlink) {
|
||||
new_state = 1;
|
||||
priv->oldlink = 0;
|
||||
priv->oldspeed = 0;
|
||||
priv->oldduplex = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (new_state && netif_msg_link(priv))
|
||||
phy_print_status(phydev);
|
||||
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
}
|
||||
|
||||
/* Update the hash table based on the current list of multicast
|
||||
* addresses we subscribe to. Also, change the promiscuity of
|
||||
@ -2122,12 +1871,23 @@ static struct device_driver gfar_driver = {
|
||||
|
||||
static int __init gfar_init(void)
|
||||
{
|
||||
return driver_register(&gfar_driver);
|
||||
int err = gfar_mdio_init();
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = driver_register(&gfar_driver);
|
||||
|
||||
if (err)
|
||||
gfar_mdio_exit();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void __exit gfar_exit(void)
|
||||
{
|
||||
driver_unregister(&gfar_driver);
|
||||
gfar_mdio_exit();
|
||||
}
|
||||
|
||||
module_init(gfar_init);
|
||||
|
@ -17,7 +17,6 @@
|
||||
*
|
||||
* Still left to do:
|
||||
* -Add support for module parameters
|
||||
* -Add support for ethtool -s
|
||||
* -Add patch for ethtool phys id
|
||||
*/
|
||||
#ifndef __GIANFAR_H
|
||||
@ -37,7 +36,8 @@
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/fsl_devices.h>
|
||||
#include <linux/mii.h>
|
||||
#include <linux/phy.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
@ -48,7 +48,8 @@
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include "gianfar_phy.h"
|
||||
#include <linux/fsl_devices.h>
|
||||
#include "gianfar_mii.h"
|
||||
|
||||
/* The maximum number of packets to be handled in one call of gfar_poll */
|
||||
#define GFAR_DEV_WEIGHT 64
|
||||
@ -73,7 +74,7 @@
|
||||
#define PHY_INIT_TIMEOUT 100000
|
||||
#define GFAR_PHY_CHANGE_TIME 2
|
||||
|
||||
#define DEVICE_NAME "%s: Gianfar Ethernet Controller Version 1.1, "
|
||||
#define DEVICE_NAME "%s: Gianfar Ethernet Controller Version 1.2, "
|
||||
#define DRV_NAME "gfar-enet"
|
||||
extern const char gfar_driver_name[];
|
||||
extern const char gfar_driver_version[];
|
||||
@ -578,12 +579,7 @@ struct gfar {
|
||||
u32 hafdup; /* 0x.50c - Half Duplex Register */
|
||||
u32 maxfrm; /* 0x.510 - Maximum Frame Length Register */
|
||||
u8 res18[12];
|
||||
u32 miimcfg; /* 0x.520 - MII Management Configuration Register */
|
||||
u32 miimcom; /* 0x.524 - MII Management Command Register */
|
||||
u32 miimadd; /* 0x.528 - MII Management Address Register */
|
||||
u32 miimcon; /* 0x.52c - MII Management Control Register */
|
||||
u32 miimstat; /* 0x.530 - MII Management Status Register */
|
||||
u32 miimind; /* 0x.534 - MII Management Indicator Register */
|
||||
u8 gfar_mii_regs[24]; /* See gianfar_phy.h */
|
||||
u8 res19[4];
|
||||
u32 ifstat; /* 0x.53c - Interface Status Register */
|
||||
u32 macstnaddr1; /* 0x.540 - Station Address Part 1 Register */
|
||||
@ -688,9 +684,6 @@ struct gfar_private {
|
||||
struct gfar *regs; /* Pointer to the GFAR memory mapped Registers */
|
||||
u32 *hash_regs[16];
|
||||
int hash_width;
|
||||
struct gfar *phyregs;
|
||||
struct work_struct tq;
|
||||
struct timer_list phy_info_timer;
|
||||
struct net_device_stats stats; /* linux network statistics */
|
||||
struct gfar_extra_stats extra_stats;
|
||||
spinlock_t lock;
|
||||
@ -710,7 +703,8 @@ struct gfar_private {
|
||||
unsigned int interruptError;
|
||||
struct gianfar_platform_data *einfo;
|
||||
|
||||
struct gfar_mii_info *mii_info;
|
||||
struct phy_device *phydev;
|
||||
struct mii_bus *mii_bus;
|
||||
int oldspeed;
|
||||
int oldduplex;
|
||||
int oldlink;
|
||||
@ -732,4 +726,12 @@ extern inline void gfar_write(volatile unsigned *addr, u32 val)
|
||||
|
||||
extern struct ethtool_ops *gfar_op_array[];
|
||||
|
||||
extern irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs);
|
||||
extern int startup_gfar(struct net_device *dev);
|
||||
extern void stop_gfar(struct net_device *dev);
|
||||
extern void gfar_halt(struct net_device *dev);
|
||||
extern void gfar_phy_test(struct mii_bus *bus, struct phy_device *phydev,
|
||||
int enable, u32 regnum, u32 read);
|
||||
void gfar_setup_stashing(struct net_device *dev);
|
||||
|
||||
#endif /* __GIANFAR_H */
|
||||
|
@ -39,17 +39,18 @@
|
||||
#include <asm/types.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/mii.h>
|
||||
#include <linux/phy.h>
|
||||
|
||||
#include "gianfar.h"
|
||||
|
||||
#define is_power_of_2(x) ((x) != 0 && (((x) & ((x) - 1)) == 0))
|
||||
|
||||
extern int startup_gfar(struct net_device *dev);
|
||||
extern void stop_gfar(struct net_device *dev);
|
||||
extern void gfar_halt(struct net_device *dev);
|
||||
extern void gfar_start(struct net_device *dev);
|
||||
extern int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit);
|
||||
|
||||
#define GFAR_MAX_COAL_USECS 0xffff
|
||||
#define GFAR_MAX_COAL_FRAMES 0xff
|
||||
static void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy,
|
||||
u64 * buf);
|
||||
static void gfar_gstrings(struct net_device *dev, u32 stringset, u8 * buf);
|
||||
@ -182,38 +183,32 @@ static void gfar_gdrvinfo(struct net_device *dev, struct
|
||||
drvinfo->eedump_len = 0;
|
||||
}
|
||||
|
||||
|
||||
static int gfar_ssettings(struct net_device *dev, struct ethtool_cmd *cmd)
|
||||
{
|
||||
struct gfar_private *priv = netdev_priv(dev);
|
||||
struct phy_device *phydev = priv->phydev;
|
||||
|
||||
if (NULL == phydev)
|
||||
return -ENODEV;
|
||||
|
||||
return phy_ethtool_sset(phydev, cmd);
|
||||
}
|
||||
|
||||
|
||||
/* Return the current settings in the ethtool_cmd structure */
|
||||
static int gfar_gsettings(struct net_device *dev, struct ethtool_cmd *cmd)
|
||||
{
|
||||
struct gfar_private *priv = netdev_priv(dev);
|
||||
uint gigabit_support =
|
||||
priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT ?
|
||||
SUPPORTED_1000baseT_Full : 0;
|
||||
uint gigabit_advert =
|
||||
priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT ?
|
||||
ADVERTISED_1000baseT_Full: 0;
|
||||
struct phy_device *phydev = priv->phydev;
|
||||
|
||||
cmd->supported = (SUPPORTED_10baseT_Half
|
||||
| SUPPORTED_100baseT_Half
|
||||
| SUPPORTED_100baseT_Full
|
||||
| gigabit_support | SUPPORTED_Autoneg);
|
||||
|
||||
/* For now, we always advertise everything */
|
||||
cmd->advertising = (ADVERTISED_10baseT_Half
|
||||
| ADVERTISED_100baseT_Half
|
||||
| ADVERTISED_100baseT_Full
|
||||
| gigabit_advert | ADVERTISED_Autoneg);
|
||||
|
||||
cmd->speed = priv->mii_info->speed;
|
||||
cmd->duplex = priv->mii_info->duplex;
|
||||
cmd->port = PORT_MII;
|
||||
cmd->phy_address = priv->mii_info->mii_id;
|
||||
cmd->transceiver = XCVR_EXTERNAL;
|
||||
cmd->autoneg = AUTONEG_ENABLE;
|
||||
if (NULL == phydev)
|
||||
return -ENODEV;
|
||||
|
||||
cmd->maxtxpkt = priv->txcount;
|
||||
cmd->maxrxpkt = priv->rxcount;
|
||||
|
||||
return 0;
|
||||
return phy_ethtool_gset(phydev, cmd);
|
||||
}
|
||||
|
||||
/* Return the length of the register structure */
|
||||
@ -241,14 +236,14 @@ static unsigned int gfar_usecs2ticks(struct gfar_private *priv, unsigned int use
|
||||
unsigned int count;
|
||||
|
||||
/* The timer is different, depending on the interface speed */
|
||||
switch (priv->mii_info->speed) {
|
||||
case 1000:
|
||||
switch (priv->phydev->speed) {
|
||||
case SPEED_1000:
|
||||
count = GFAR_GBIT_TIME;
|
||||
break;
|
||||
case 100:
|
||||
case SPEED_100:
|
||||
count = GFAR_100_TIME;
|
||||
break;
|
||||
case 10:
|
||||
case SPEED_10:
|
||||
default:
|
||||
count = GFAR_10_TIME;
|
||||
break;
|
||||
@ -265,14 +260,14 @@ static unsigned int gfar_ticks2usecs(struct gfar_private *priv, unsigned int tic
|
||||
unsigned int count;
|
||||
|
||||
/* The timer is different, depending on the interface speed */
|
||||
switch (priv->mii_info->speed) {
|
||||
case 1000:
|
||||
switch (priv->phydev->speed) {
|
||||
case SPEED_1000:
|
||||
count = GFAR_GBIT_TIME;
|
||||
break;
|
||||
case 100:
|
||||
case SPEED_100:
|
||||
count = GFAR_100_TIME;
|
||||
break;
|
||||
case 10:
|
||||
case SPEED_10:
|
||||
default:
|
||||
count = GFAR_10_TIME;
|
||||
break;
|
||||
@ -292,6 +287,9 @@ static int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals
|
||||
if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (NULL == priv->phydev)
|
||||
return -ENODEV;
|
||||
|
||||
cvals->rx_coalesce_usecs = gfar_ticks2usecs(priv, priv->rxtime);
|
||||
cvals->rx_max_coalesced_frames = priv->rxcount;
|
||||
|
||||
@ -348,6 +346,22 @@ static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals
|
||||
else
|
||||
priv->rxcoalescing = 1;
|
||||
|
||||
if (NULL == priv->phydev)
|
||||
return -ENODEV;
|
||||
|
||||
/* Check the bounds of the values */
|
||||
if (cvals->rx_coalesce_usecs > GFAR_MAX_COAL_USECS) {
|
||||
pr_info("Coalescing is limited to %d microseconds\n",
|
||||
GFAR_MAX_COAL_USECS);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (cvals->rx_max_coalesced_frames > GFAR_MAX_COAL_FRAMES) {
|
||||
pr_info("Coalescing is limited to %d frames\n",
|
||||
GFAR_MAX_COAL_FRAMES);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
priv->rxtime = gfar_usecs2ticks(priv, cvals->rx_coalesce_usecs);
|
||||
priv->rxcount = cvals->rx_max_coalesced_frames;
|
||||
|
||||
@ -358,6 +372,19 @@ static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals
|
||||
else
|
||||
priv->txcoalescing = 1;
|
||||
|
||||
/* Check the bounds of the values */
|
||||
if (cvals->tx_coalesce_usecs > GFAR_MAX_COAL_USECS) {
|
||||
pr_info("Coalescing is limited to %d microseconds\n",
|
||||
GFAR_MAX_COAL_USECS);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (cvals->tx_max_coalesced_frames > GFAR_MAX_COAL_FRAMES) {
|
||||
pr_info("Coalescing is limited to %d frames\n",
|
||||
GFAR_MAX_COAL_FRAMES);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
priv->txtime = gfar_usecs2ticks(priv, cvals->tx_coalesce_usecs);
|
||||
priv->txcount = cvals->tx_max_coalesced_frames;
|
||||
|
||||
@ -536,6 +563,7 @@ static void gfar_set_msglevel(struct net_device *dev, uint32_t data)
|
||||
|
||||
struct ethtool_ops gfar_ethtool_ops = {
|
||||
.get_settings = gfar_gsettings,
|
||||
.set_settings = gfar_ssettings,
|
||||
.get_drvinfo = gfar_gdrvinfo,
|
||||
.get_regs_len = gfar_reglen,
|
||||
.get_regs = gfar_get_regs,
|
||||
|
219
drivers/net/gianfar_mii.c
Normal file
219
drivers/net/gianfar_mii.c
Normal file
@ -0,0 +1,219 @@
|
||||
/*
|
||||
* drivers/net/gianfar_mii.c
|
||||
*
|
||||
* Gianfar Ethernet Driver -- MIIM bus implementation
|
||||
* Provides Bus interface for MIIM regs
|
||||
*
|
||||
* Author: Andy Fleming
|
||||
* Maintainer: Kumar Gala (kumar.gala@freescale.com)
|
||||
*
|
||||
* Copyright (c) 2002-2004 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/unistd.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#include <asm/ocp.h>
|
||||
#include <linux/crc32.h>
|
||||
#include <linux/mii.h>
|
||||
#include <linux/phy.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
#include "gianfar.h"
|
||||
#include "gianfar_mii.h"
|
||||
|
||||
/* Write value to the PHY at mii_id at register regnum,
|
||||
* on the bus, waiting until the write is done before returning.
|
||||
* All PHY configuration is done through the TSEC1 MIIM regs */
|
||||
int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value)
|
||||
{
|
||||
struct gfar_mii *regs = bus->priv;
|
||||
|
||||
/* Set the PHY address and the register address we want to write */
|
||||
gfar_write(®s->miimadd, (mii_id << 8) | regnum);
|
||||
|
||||
/* Write out the value we want */
|
||||
gfar_write(®s->miimcon, value);
|
||||
|
||||
/* Wait for the transaction to finish */
|
||||
while (gfar_read(®s->miimind) & MIIMIND_BUSY)
|
||||
cpu_relax();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read the bus for PHY at addr mii_id, register regnum, and
|
||||
* return the value. Clears miimcom first. All PHY
|
||||
* configuration has to be done through the TSEC1 MIIM regs */
|
||||
int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
|
||||
{
|
||||
struct gfar_mii *regs = bus->priv;
|
||||
u16 value;
|
||||
|
||||
/* Set the PHY address and the register address we want to read */
|
||||
gfar_write(®s->miimadd, (mii_id << 8) | regnum);
|
||||
|
||||
/* Clear miimcom, and then initiate a read */
|
||||
gfar_write(®s->miimcom, 0);
|
||||
gfar_write(®s->miimcom, MII_READ_COMMAND);
|
||||
|
||||
/* Wait for the transaction to finish */
|
||||
while (gfar_read(®s->miimind) & (MIIMIND_NOTVALID | MIIMIND_BUSY))
|
||||
cpu_relax();
|
||||
|
||||
/* Grab the value of the register from miimstat */
|
||||
value = gfar_read(®s->miimstat);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
/* Reset the MIIM registers, and wait for the bus to free */
|
||||
int gfar_mdio_reset(struct mii_bus *bus)
|
||||
{
|
||||
struct gfar_mii *regs = bus->priv;
|
||||
unsigned int timeout = PHY_INIT_TIMEOUT;
|
||||
|
||||
spin_lock_bh(&bus->mdio_lock);
|
||||
|
||||
/* Reset the management interface */
|
||||
gfar_write(®s->miimcfg, MIIMCFG_RESET);
|
||||
|
||||
/* Setup the MII Mgmt clock speed */
|
||||
gfar_write(®s->miimcfg, MIIMCFG_INIT_VALUE);
|
||||
|
||||
/* Wait until the bus is free */
|
||||
while ((gfar_read(®s->miimind) & MIIMIND_BUSY) &&
|
||||
timeout--)
|
||||
cpu_relax();
|
||||
|
||||
spin_unlock_bh(&bus->mdio_lock);
|
||||
|
||||
if(timeout <= 0) {
|
||||
printk(KERN_ERR "%s: The MII Bus is stuck!\n",
|
||||
bus->name);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int gfar_mdio_probe(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct gianfar_mdio_data *pdata;
|
||||
struct gfar_mii *regs;
|
||||
struct mii_bus *new_bus;
|
||||
int err = 0;
|
||||
|
||||
if (NULL == dev)
|
||||
return -EINVAL;
|
||||
|
||||
new_bus = kmalloc(sizeof(struct mii_bus), GFP_KERNEL);
|
||||
|
||||
if (NULL == new_bus)
|
||||
return -ENOMEM;
|
||||
|
||||
new_bus->name = "Gianfar MII Bus",
|
||||
new_bus->read = &gfar_mdio_read,
|
||||
new_bus->write = &gfar_mdio_write,
|
||||
new_bus->reset = &gfar_mdio_reset,
|
||||
new_bus->id = pdev->id;
|
||||
|
||||
pdata = (struct gianfar_mdio_data *)pdev->dev.platform_data;
|
||||
|
||||
if (NULL == pdata) {
|
||||
printk(KERN_ERR "gfar mdio %d: Missing platform data!\n", pdev->id);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Set the PHY base address */
|
||||
regs = (struct gfar_mii *) ioremap(pdata->paddr,
|
||||
sizeof (struct gfar_mii));
|
||||
|
||||
if (NULL == regs) {
|
||||
err = -ENOMEM;
|
||||
goto reg_map_fail;
|
||||
}
|
||||
|
||||
new_bus->priv = regs;
|
||||
|
||||
new_bus->irq = pdata->irq;
|
||||
|
||||
new_bus->dev = dev;
|
||||
dev_set_drvdata(dev, new_bus);
|
||||
|
||||
err = mdiobus_register(new_bus);
|
||||
|
||||
if (0 != err) {
|
||||
printk (KERN_ERR "%s: Cannot register as MDIO bus\n",
|
||||
new_bus->name);
|
||||
goto bus_register_fail;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
bus_register_fail:
|
||||
iounmap((void *) regs);
|
||||
reg_map_fail:
|
||||
kfree(new_bus);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int gfar_mdio_remove(struct device *dev)
|
||||
{
|
||||
struct mii_bus *bus = dev_get_drvdata(dev);
|
||||
|
||||
mdiobus_unregister(bus);
|
||||
|
||||
dev_set_drvdata(dev, NULL);
|
||||
|
||||
iounmap((void *) (&bus->priv));
|
||||
bus->priv = NULL;
|
||||
kfree(bus);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct device_driver gianfar_mdio_driver = {
|
||||
.name = "fsl-gianfar_mdio",
|
||||
.bus = &platform_bus_type,
|
||||
.probe = gfar_mdio_probe,
|
||||
.remove = gfar_mdio_remove,
|
||||
};
|
||||
|
||||
int __init gfar_mdio_init(void)
|
||||
{
|
||||
return driver_register(&gianfar_mdio_driver);
|
||||
}
|
||||
|
||||
void __exit gfar_mdio_exit(void)
|
||||
{
|
||||
driver_unregister(&gianfar_mdio_driver);
|
||||
}
|
45
drivers/net/gianfar_mii.h
Normal file
45
drivers/net/gianfar_mii.h
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* drivers/net/gianfar_mii.h
|
||||
*
|
||||
* Gianfar Ethernet Driver -- MII Management Bus Implementation
|
||||
* Driver for the MDIO bus controller in the Gianfar register space
|
||||
*
|
||||
* Author: Andy Fleming
|
||||
* Maintainer: Kumar Gala (kumar.gala@freescale.com)
|
||||
*
|
||||
* Copyright (c) 2002-2004 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
#ifndef __GIANFAR_MII_H
|
||||
#define __GIANFAR_MII_H
|
||||
|
||||
#define MIIMIND_BUSY 0x00000001
|
||||
#define MIIMIND_NOTVALID 0x00000004
|
||||
|
||||
#define MII_READ_COMMAND 0x00000001
|
||||
|
||||
#define GFAR_SUPPORTED (SUPPORTED_10baseT_Half \
|
||||
| SUPPORTED_100baseT_Half \
|
||||
| SUPPORTED_100baseT_Full \
|
||||
| SUPPORTED_Autoneg \
|
||||
| SUPPORTED_MII)
|
||||
|
||||
struct gfar_mii {
|
||||
u32 miimcfg; /* 0x.520 - MII Management Config Register */
|
||||
u32 miimcom; /* 0x.524 - MII Management Command Register */
|
||||
u32 miimadd; /* 0x.528 - MII Management Address Register */
|
||||
u32 miimcon; /* 0x.52c - MII Management Control Register */
|
||||
u32 miimstat; /* 0x.530 - MII Management Status Register */
|
||||
u32 miimind; /* 0x.534 - MII Management Indicator Register */
|
||||
};
|
||||
|
||||
int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum);
|
||||
int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value);
|
||||
int __init gfar_mdio_init(void);
|
||||
void __exit gfar_mdio_exit(void);
|
||||
#endif /* GIANFAR_PHY_H */
|
@ -1,661 +0,0 @@
|
||||
/*
|
||||
* drivers/net/gianfar_phy.c
|
||||
*
|
||||
* Gianfar Ethernet Driver -- PHY handling
|
||||
* Driver for FEC on MPC8540 and TSEC on MPC8540/MPC8560
|
||||
* Based on 8260_io/fcc_enet.c
|
||||
*
|
||||
* Author: Andy Fleming
|
||||
* Maintainer: Kumar Gala (kumar.gala@freescale.com)
|
||||
*
|
||||
* Copyright (c) 2002-2004 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/mm.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/crc32.h>
|
||||
#include <linux/mii.h>
|
||||
|
||||
#include "gianfar.h"
|
||||
#include "gianfar_phy.h"
|
||||
|
||||
static void config_genmii_advert(struct gfar_mii_info *mii_info);
|
||||
static void genmii_setup_forced(struct gfar_mii_info *mii_info);
|
||||
static void genmii_restart_aneg(struct gfar_mii_info *mii_info);
|
||||
static int gbit_config_aneg(struct gfar_mii_info *mii_info);
|
||||
static int genmii_config_aneg(struct gfar_mii_info *mii_info);
|
||||
static int genmii_update_link(struct gfar_mii_info *mii_info);
|
||||
static int genmii_read_status(struct gfar_mii_info *mii_info);
|
||||
u16 phy_read(struct gfar_mii_info *mii_info, u16 regnum);
|
||||
void phy_write(struct gfar_mii_info *mii_info, u16 regnum, u16 val);
|
||||
|
||||
/* Write value to the PHY for this device to the register at regnum, */
|
||||
/* waiting until the write is done before it returns. All PHY */
|
||||
/* configuration has to be done through the TSEC1 MIIM regs */
|
||||
void write_phy_reg(struct net_device *dev, int mii_id, int regnum, int value)
|
||||
{
|
||||
struct gfar_private *priv = netdev_priv(dev);
|
||||
struct gfar *regbase = priv->phyregs;
|
||||
|
||||
/* Set the PHY address and the register address we want to write */
|
||||
gfar_write(®base->miimadd, (mii_id << 8) | regnum);
|
||||
|
||||
/* Write out the value we want */
|
||||
gfar_write(®base->miimcon, value);
|
||||
|
||||
/* Wait for the transaction to finish */
|
||||
while (gfar_read(®base->miimind) & MIIMIND_BUSY)
|
||||
cpu_relax();
|
||||
}
|
||||
|
||||
/* Reads from register regnum in the PHY for device dev, */
|
||||
/* returning the value. Clears miimcom first. All PHY */
|
||||
/* configuration has to be done through the TSEC1 MIIM regs */
|
||||
int read_phy_reg(struct net_device *dev, int mii_id, int regnum)
|
||||
{
|
||||
struct gfar_private *priv = netdev_priv(dev);
|
||||
struct gfar *regbase = priv->phyregs;
|
||||
u16 value;
|
||||
|
||||
/* Set the PHY address and the register address we want to read */
|
||||
gfar_write(®base->miimadd, (mii_id << 8) | regnum);
|
||||
|
||||
/* Clear miimcom, and then initiate a read */
|
||||
gfar_write(®base->miimcom, 0);
|
||||
gfar_write(®base->miimcom, MII_READ_COMMAND);
|
||||
|
||||
/* Wait for the transaction to finish */
|
||||
while (gfar_read(®base->miimind) & (MIIMIND_NOTVALID | MIIMIND_BUSY))
|
||||
cpu_relax();
|
||||
|
||||
/* Grab the value of the register from miimstat */
|
||||
value = gfar_read(®base->miimstat);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void mii_clear_phy_interrupt(struct gfar_mii_info *mii_info)
|
||||
{
|
||||
if(mii_info->phyinfo->ack_interrupt)
|
||||
mii_info->phyinfo->ack_interrupt(mii_info);
|
||||
}
|
||||
|
||||
|
||||
void mii_configure_phy_interrupt(struct gfar_mii_info *mii_info, u32 interrupts)
|
||||
{
|
||||
mii_info->interrupts = interrupts;
|
||||
if(mii_info->phyinfo->config_intr)
|
||||
mii_info->phyinfo->config_intr(mii_info);
|
||||
}
|
||||
|
||||
|
||||
/* Writes MII_ADVERTISE with the appropriate values, after
|
||||
* sanitizing advertise to make sure only supported features
|
||||
* are advertised
|
||||
*/
|
||||
static void config_genmii_advert(struct gfar_mii_info *mii_info)
|
||||
{
|
||||
u32 advertise;
|
||||
u16 adv;
|
||||
|
||||
/* Only allow advertising what this PHY supports */
|
||||
mii_info->advertising &= mii_info->phyinfo->features;
|
||||
advertise = mii_info->advertising;
|
||||
|
||||
/* Setup standard advertisement */
|
||||
adv = phy_read(mii_info, MII_ADVERTISE);
|
||||
adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
|
||||
if (advertise & ADVERTISED_10baseT_Half)
|
||||
adv |= ADVERTISE_10HALF;
|
||||
if (advertise & ADVERTISED_10baseT_Full)
|
||||
adv |= ADVERTISE_10FULL;
|
||||
if (advertise & ADVERTISED_100baseT_Half)
|
||||
adv |= ADVERTISE_100HALF;
|
||||
if (advertise & ADVERTISED_100baseT_Full)
|
||||
adv |= ADVERTISE_100FULL;
|
||||
phy_write(mii_info, MII_ADVERTISE, adv);
|
||||
}
|
||||
|
||||
static void genmii_setup_forced(struct gfar_mii_info *mii_info)
|
||||
{
|
||||
u16 ctrl;
|
||||
u32 features = mii_info->phyinfo->features;
|
||||
|
||||
ctrl = phy_read(mii_info, MII_BMCR);
|
||||
|
||||
ctrl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_SPEED1000|BMCR_ANENABLE);
|
||||
ctrl |= BMCR_RESET;
|
||||
|
||||
switch(mii_info->speed) {
|
||||
case SPEED_1000:
|
||||
if(features & (SUPPORTED_1000baseT_Half
|
||||
| SUPPORTED_1000baseT_Full)) {
|
||||
ctrl |= BMCR_SPEED1000;
|
||||
break;
|
||||
}
|
||||
mii_info->speed = SPEED_100;
|
||||
case SPEED_100:
|
||||
if (features & (SUPPORTED_100baseT_Half
|
||||
| SUPPORTED_100baseT_Full)) {
|
||||
ctrl |= BMCR_SPEED100;
|
||||
break;
|
||||
}
|
||||
mii_info->speed = SPEED_10;
|
||||
case SPEED_10:
|
||||
if (features & (SUPPORTED_10baseT_Half
|
||||
| SUPPORTED_10baseT_Full))
|
||||
break;
|
||||
default: /* Unsupported speed! */
|
||||
printk(KERN_ERR "%s: Bad speed!\n",
|
||||
mii_info->dev->name);
|
||||
break;
|
||||
}
|
||||
|
||||
phy_write(mii_info, MII_BMCR, ctrl);
|
||||
}
|
||||
|
||||
|
||||
/* Enable and Restart Autonegotiation */
|
||||
static void genmii_restart_aneg(struct gfar_mii_info *mii_info)
|
||||
{
|
||||
u16 ctl;
|
||||
|
||||
ctl = phy_read(mii_info, MII_BMCR);
|
||||
ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
|
||||
phy_write(mii_info, MII_BMCR, ctl);
|
||||
}
|
||||
|
||||
|
||||
static int gbit_config_aneg(struct gfar_mii_info *mii_info)
|
||||
{
|
||||
u16 adv;
|
||||
u32 advertise;
|
||||
|
||||
if(mii_info->autoneg) {
|
||||
/* Configure the ADVERTISE register */
|
||||
config_genmii_advert(mii_info);
|
||||
advertise = mii_info->advertising;
|
||||
|
||||
adv = phy_read(mii_info, MII_1000BASETCONTROL);
|
||||
adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP |
|
||||
MII_1000BASETCONTROL_HALFDUPLEXCAP);
|
||||
if (advertise & SUPPORTED_1000baseT_Half)
|
||||
adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP;
|
||||
if (advertise & SUPPORTED_1000baseT_Full)
|
||||
adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP;
|
||||
phy_write(mii_info, MII_1000BASETCONTROL, adv);
|
||||
|
||||
/* Start/Restart aneg */
|
||||
genmii_restart_aneg(mii_info);
|
||||
} else
|
||||
genmii_setup_forced(mii_info);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int marvell_config_aneg(struct gfar_mii_info *mii_info)
|
||||
{
|
||||
/* The Marvell PHY has an errata which requires
|
||||
* that certain registers get written in order
|
||||
* to restart autonegotiation */
|
||||
phy_write(mii_info, MII_BMCR, BMCR_RESET);
|
||||
|
||||
phy_write(mii_info, 0x1d, 0x1f);
|
||||
phy_write(mii_info, 0x1e, 0x200c);
|
||||
phy_write(mii_info, 0x1d, 0x5);
|
||||
phy_write(mii_info, 0x1e, 0);
|
||||
phy_write(mii_info, 0x1e, 0x100);
|
||||
|
||||
gbit_config_aneg(mii_info);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int genmii_config_aneg(struct gfar_mii_info *mii_info)
|
||||
{
|
||||
if (mii_info->autoneg) {
|
||||
config_genmii_advert(mii_info);
|
||||
genmii_restart_aneg(mii_info);
|
||||
} else
|
||||
genmii_setup_forced(mii_info);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int genmii_update_link(struct gfar_mii_info *mii_info)
|
||||
{
|
||||
u16 status;
|
||||
|
||||
/* Do a fake read */
|
||||
phy_read(mii_info, MII_BMSR);
|
||||
|
||||
/* Read link and autonegotiation status */
|
||||
status = phy_read(mii_info, MII_BMSR);
|
||||
if ((status & BMSR_LSTATUS) == 0)
|
||||
mii_info->link = 0;
|
||||
else
|
||||
mii_info->link = 1;
|
||||
|
||||
/* If we are autonegotiating, and not done,
|
||||
* return an error */
|
||||
if (mii_info->autoneg && !(status & BMSR_ANEGCOMPLETE))
|
||||
return -EAGAIN;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int genmii_read_status(struct gfar_mii_info *mii_info)
|
||||
{
|
||||
u16 status;
|
||||
int err;
|
||||
|
||||
/* Update the link, but return if there
|
||||
* was an error */
|
||||
err = genmii_update_link(mii_info);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (mii_info->autoneg) {
|
||||
status = phy_read(mii_info, MII_LPA);
|
||||
|
||||
if (status & (LPA_10FULL | LPA_100FULL))
|
||||
mii_info->duplex = DUPLEX_FULL;
|
||||
else
|
||||
mii_info->duplex = DUPLEX_HALF;
|
||||
if (status & (LPA_100FULL | LPA_100HALF))
|
||||
mii_info->speed = SPEED_100;
|
||||
else
|
||||
mii_info->speed = SPEED_10;
|
||||
mii_info->pause = 0;
|
||||
}
|
||||
/* On non-aneg, we assume what we put in BMCR is the speed,
|
||||
* though magic-aneg shouldn't prevent this case from occurring
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int marvell_read_status(struct gfar_mii_info *mii_info)
|
||||
{
|
||||
u16 status;
|
||||
int err;
|
||||
|
||||
/* Update the link, but return if there
|
||||
* was an error */
|
||||
err = genmii_update_link(mii_info);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* If the link is up, read the speed and duplex */
|
||||
/* If we aren't autonegotiating, assume speeds
|
||||
* are as set */
|
||||
if (mii_info->autoneg && mii_info->link) {
|
||||
int speed;
|
||||
status = phy_read(mii_info, MII_M1011_PHY_SPEC_STATUS);
|
||||
|
||||
#if 0
|
||||
/* If speed and duplex aren't resolved,
|
||||
* return an error. Isn't this handled
|
||||
* by checking aneg?
|
||||
*/
|
||||
if ((status & MII_M1011_PHY_SPEC_STATUS_RESOLVED) == 0)
|
||||
return -EAGAIN;
|
||||
#endif
|
||||
|
||||
/* Get the duplexity */
|
||||
if (status & MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX)
|
||||
mii_info->duplex = DUPLEX_FULL;
|
||||
else
|
||||
mii_info->duplex = DUPLEX_HALF;
|
||||
|
||||
/* Get the speed */
|
||||
speed = status & MII_M1011_PHY_SPEC_STATUS_SPD_MASK;
|
||||
switch(speed) {
|
||||
case MII_M1011_PHY_SPEC_STATUS_1000:
|
||||
mii_info->speed = SPEED_1000;
|
||||
break;
|
||||
case MII_M1011_PHY_SPEC_STATUS_100:
|
||||
mii_info->speed = SPEED_100;
|
||||
break;
|
||||
default:
|
||||
mii_info->speed = SPEED_10;
|
||||
break;
|
||||
}
|
||||
mii_info->pause = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int cis820x_read_status(struct gfar_mii_info *mii_info)
|
||||
{
|
||||
u16 status;
|
||||
int err;
|
||||
|
||||
/* Update the link, but return if there
|
||||
* was an error */
|
||||
err = genmii_update_link(mii_info);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* If the link is up, read the speed and duplex */
|
||||
/* If we aren't autonegotiating, assume speeds
|
||||
* are as set */
|
||||
if (mii_info->autoneg && mii_info->link) {
|
||||
int speed;
|
||||
|
||||
status = phy_read(mii_info, MII_CIS8201_AUX_CONSTAT);
|
||||
if (status & MII_CIS8201_AUXCONSTAT_DUPLEX)
|
||||
mii_info->duplex = DUPLEX_FULL;
|
||||
else
|
||||
mii_info->duplex = DUPLEX_HALF;
|
||||
|
||||
speed = status & MII_CIS8201_AUXCONSTAT_SPEED;
|
||||
|
||||
switch (speed) {
|
||||
case MII_CIS8201_AUXCONSTAT_GBIT:
|
||||
mii_info->speed = SPEED_1000;
|
||||
break;
|
||||
case MII_CIS8201_AUXCONSTAT_100:
|
||||
mii_info->speed = SPEED_100;
|
||||
break;
|
||||
default:
|
||||
mii_info->speed = SPEED_10;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int marvell_ack_interrupt(struct gfar_mii_info *mii_info)
|
||||
{
|
||||
/* Clear the interrupts by reading the reg */
|
||||
phy_read(mii_info, MII_M1011_IEVENT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int marvell_config_intr(struct gfar_mii_info *mii_info)
|
||||
{
|
||||
if(mii_info->interrupts == MII_INTERRUPT_ENABLED)
|
||||
phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_INIT);
|
||||
else
|
||||
phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cis820x_init(struct gfar_mii_info *mii_info)
|
||||
{
|
||||
phy_write(mii_info, MII_CIS8201_AUX_CONSTAT,
|
||||
MII_CIS8201_AUXCONSTAT_INIT);
|
||||
phy_write(mii_info, MII_CIS8201_EXT_CON1,
|
||||
MII_CIS8201_EXTCON1_INIT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cis820x_ack_interrupt(struct gfar_mii_info *mii_info)
|
||||
{
|
||||
phy_read(mii_info, MII_CIS8201_ISTAT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cis820x_config_intr(struct gfar_mii_info *mii_info)
|
||||
{
|
||||
if(mii_info->interrupts == MII_INTERRUPT_ENABLED)
|
||||
phy_write(mii_info, MII_CIS8201_IMASK, MII_CIS8201_IMASK_MASK);
|
||||
else
|
||||
phy_write(mii_info, MII_CIS8201_IMASK, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define DM9161_DELAY 10
|
||||
|
||||
static int dm9161_read_status(struct gfar_mii_info *mii_info)
|
||||
{
|
||||
u16 status;
|
||||
int err;
|
||||
|
||||
/* Update the link, but return if there
|
||||
* was an error */
|
||||
err = genmii_update_link(mii_info);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* If the link is up, read the speed and duplex */
|
||||
/* If we aren't autonegotiating, assume speeds
|
||||
* are as set */
|
||||
if (mii_info->autoneg && mii_info->link) {
|
||||
status = phy_read(mii_info, MII_DM9161_SCSR);
|
||||
if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_100H))
|
||||
mii_info->speed = SPEED_100;
|
||||
else
|
||||
mii_info->speed = SPEED_10;
|
||||
|
||||
if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_10F))
|
||||
mii_info->duplex = DUPLEX_FULL;
|
||||
else
|
||||
mii_info->duplex = DUPLEX_HALF;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int dm9161_config_aneg(struct gfar_mii_info *mii_info)
|
||||
{
|
||||
struct dm9161_private *priv = mii_info->priv;
|
||||
|
||||
if(0 == priv->resetdone)
|
||||
return -EAGAIN;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dm9161_timer(unsigned long data)
|
||||
{
|
||||
struct gfar_mii_info *mii_info = (struct gfar_mii_info *)data;
|
||||
struct dm9161_private *priv = mii_info->priv;
|
||||
u16 status = phy_read(mii_info, MII_BMSR);
|
||||
|
||||
if (status & BMSR_ANEGCOMPLETE) {
|
||||
priv->resetdone = 1;
|
||||
} else
|
||||
mod_timer(&priv->timer, jiffies + DM9161_DELAY * HZ);
|
||||
}
|
||||
|
||||
static int dm9161_init(struct gfar_mii_info *mii_info)
|
||||
{
|
||||
struct dm9161_private *priv;
|
||||
|
||||
/* Allocate the private data structure */
|
||||
priv = kmalloc(sizeof(struct dm9161_private), GFP_KERNEL);
|
||||
|
||||
if (NULL == priv)
|
||||
return -ENOMEM;
|
||||
|
||||
mii_info->priv = priv;
|
||||
|
||||
/* Reset is not done yet */
|
||||
priv->resetdone = 0;
|
||||
|
||||
/* Isolate the PHY */
|
||||
phy_write(mii_info, MII_BMCR, BMCR_ISOLATE);
|
||||
|
||||
/* Do not bypass the scrambler/descrambler */
|
||||
phy_write(mii_info, MII_DM9161_SCR, MII_DM9161_SCR_INIT);
|
||||
|
||||
/* Clear 10BTCSR to default */
|
||||
phy_write(mii_info, MII_DM9161_10BTCSR, MII_DM9161_10BTCSR_INIT);
|
||||
|
||||
/* Reconnect the PHY, and enable Autonegotiation */
|
||||
phy_write(mii_info, MII_BMCR, BMCR_ANENABLE);
|
||||
|
||||
/* Start a timer for DM9161_DELAY seconds to wait
|
||||
* for the PHY to be ready */
|
||||
init_timer(&priv->timer);
|
||||
priv->timer.function = &dm9161_timer;
|
||||
priv->timer.data = (unsigned long) mii_info;
|
||||
mod_timer(&priv->timer, jiffies + DM9161_DELAY * HZ);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dm9161_close(struct gfar_mii_info *mii_info)
|
||||
{
|
||||
struct dm9161_private *priv = mii_info->priv;
|
||||
|
||||
del_timer_sync(&priv->timer);
|
||||
kfree(priv);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int dm9161_ack_interrupt(struct gfar_mii_info *mii_info)
|
||||
{
|
||||
phy_read(mii_info, MII_DM9161_INTR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Cicada 820x */
|
||||
static struct phy_info phy_info_cis820x = {
|
||||
0x000fc440,
|
||||
"Cicada Cis8204",
|
||||
0x000fffc0,
|
||||
.features = MII_GBIT_FEATURES,
|
||||
.init = &cis820x_init,
|
||||
.config_aneg = &gbit_config_aneg,
|
||||
.read_status = &cis820x_read_status,
|
||||
.ack_interrupt = &cis820x_ack_interrupt,
|
||||
.config_intr = &cis820x_config_intr,
|
||||
};
|
||||
|
||||
static struct phy_info phy_info_dm9161 = {
|
||||
.phy_id = 0x0181b880,
|
||||
.name = "Davicom DM9161E",
|
||||
.phy_id_mask = 0x0ffffff0,
|
||||
.init = dm9161_init,
|
||||
.config_aneg = dm9161_config_aneg,
|
||||
.read_status = dm9161_read_status,
|
||||
.close = dm9161_close,
|
||||
};
|
||||
|
||||
static struct phy_info phy_info_marvell = {
|
||||
.phy_id = 0x01410c00,
|
||||
.phy_id_mask = 0xffffff00,
|
||||
.name = "Marvell 88E1101/88E1111",
|
||||
.features = MII_GBIT_FEATURES,
|
||||
.config_aneg = &marvell_config_aneg,
|
||||
.read_status = &marvell_read_status,
|
||||
.ack_interrupt = &marvell_ack_interrupt,
|
||||
.config_intr = &marvell_config_intr,
|
||||
};
|
||||
|
||||
static struct phy_info phy_info_genmii= {
|
||||
.phy_id = 0x00000000,
|
||||
.phy_id_mask = 0x00000000,
|
||||
.name = "Generic MII",
|
||||
.features = MII_BASIC_FEATURES,
|
||||
.config_aneg = genmii_config_aneg,
|
||||
.read_status = genmii_read_status,
|
||||
};
|
||||
|
||||
static struct phy_info *phy_info[] = {
|
||||
&phy_info_cis820x,
|
||||
&phy_info_marvell,
|
||||
&phy_info_dm9161,
|
||||
&phy_info_genmii,
|
||||
NULL
|
||||
};
|
||||
|
||||
u16 phy_read(struct gfar_mii_info *mii_info, u16 regnum)
|
||||
{
|
||||
u16 retval;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&mii_info->mdio_lock, flags);
|
||||
retval = mii_info->mdio_read(mii_info->dev, mii_info->mii_id, regnum);
|
||||
spin_unlock_irqrestore(&mii_info->mdio_lock, flags);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
void phy_write(struct gfar_mii_info *mii_info, u16 regnum, u16 val)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&mii_info->mdio_lock, flags);
|
||||
mii_info->mdio_write(mii_info->dev,
|
||||
mii_info->mii_id,
|
||||
regnum, val);
|
||||
spin_unlock_irqrestore(&mii_info->mdio_lock, flags);
|
||||
}
|
||||
|
||||
/* Use the PHY ID registers to determine what type of PHY is attached
|
||||
* to device dev. return a struct phy_info structure describing that PHY
|
||||
*/
|
||||
struct phy_info * get_phy_info(struct gfar_mii_info *mii_info)
|
||||
{
|
||||
u16 phy_reg;
|
||||
u32 phy_ID;
|
||||
int i;
|
||||
struct phy_info *theInfo = NULL;
|
||||
struct net_device *dev = mii_info->dev;
|
||||
|
||||
/* Grab the bits from PHYIR1, and put them in the upper half */
|
||||
phy_reg = phy_read(mii_info, MII_PHYSID1);
|
||||
phy_ID = (phy_reg & 0xffff) << 16;
|
||||
|
||||
/* Grab the bits from PHYIR2, and put them in the lower half */
|
||||
phy_reg = phy_read(mii_info, MII_PHYSID2);
|
||||
phy_ID |= (phy_reg & 0xffff);
|
||||
|
||||
/* loop through all the known PHY types, and find one that */
|
||||
/* matches the ID we read from the PHY. */
|
||||
for (i = 0; phy_info[i]; i++)
|
||||
if (phy_info[i]->phy_id ==
|
||||
(phy_ID & phy_info[i]->phy_id_mask)) {
|
||||
theInfo = phy_info[i];
|
||||
break;
|
||||
}
|
||||
|
||||
/* This shouldn't happen, as we have generic PHY support */
|
||||
if (theInfo == NULL) {
|
||||
printk("%s: PHY id %x is not supported!\n", dev->name, phy_ID);
|
||||
return NULL;
|
||||
} else {
|
||||
printk("%s: PHY is %s (%x)\n", dev->name, theInfo->name,
|
||||
phy_ID);
|
||||
}
|
||||
|
||||
return theInfo;
|
||||
}
|
@ -1,213 +0,0 @@
|
||||
/*
|
||||
* drivers/net/gianfar_phy.h
|
||||
*
|
||||
* Gianfar Ethernet Driver -- PHY handling
|
||||
* Driver for FEC on MPC8540 and TSEC on MPC8540/MPC8560
|
||||
* Based on 8260_io/fcc_enet.c
|
||||
*
|
||||
* Author: Andy Fleming
|
||||
* Maintainer: Kumar Gala (kumar.gala@freescale.com)
|
||||
*
|
||||
* Copyright (c) 2002-2004 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
#ifndef __GIANFAR_PHY_H
|
||||
#define __GIANFAR_PHY_H
|
||||
|
||||
#define MII_end ((u32)-2)
|
||||
#define MII_read ((u32)-1)
|
||||
|
||||
#define MIIMIND_BUSY 0x00000001
|
||||
#define MIIMIND_NOTVALID 0x00000004
|
||||
|
||||
#define GFAR_AN_TIMEOUT 2000
|
||||
|
||||
/* 1000BT control (Marvell & BCM54xx at least) */
|
||||
#define MII_1000BASETCONTROL 0x09
|
||||
#define MII_1000BASETCONTROL_FULLDUPLEXCAP 0x0200
|
||||
#define MII_1000BASETCONTROL_HALFDUPLEXCAP 0x0100
|
||||
|
||||
/* Cicada Extended Control Register 1 */
|
||||
#define MII_CIS8201_EXT_CON1 0x17
|
||||
#define MII_CIS8201_EXTCON1_INIT 0x0000
|
||||
|
||||
/* Cicada Interrupt Mask Register */
|
||||
#define MII_CIS8201_IMASK 0x19
|
||||
#define MII_CIS8201_IMASK_IEN 0x8000
|
||||
#define MII_CIS8201_IMASK_SPEED 0x4000
|
||||
#define MII_CIS8201_IMASK_LINK 0x2000
|
||||
#define MII_CIS8201_IMASK_DUPLEX 0x1000
|
||||
#define MII_CIS8201_IMASK_MASK 0xf000
|
||||
|
||||
/* Cicada Interrupt Status Register */
|
||||
#define MII_CIS8201_ISTAT 0x1a
|
||||
#define MII_CIS8201_ISTAT_STATUS 0x8000
|
||||
#define MII_CIS8201_ISTAT_SPEED 0x4000
|
||||
#define MII_CIS8201_ISTAT_LINK 0x2000
|
||||
#define MII_CIS8201_ISTAT_DUPLEX 0x1000
|
||||
|
||||
/* Cicada Auxiliary Control/Status Register */
|
||||
#define MII_CIS8201_AUX_CONSTAT 0x1c
|
||||
#define MII_CIS8201_AUXCONSTAT_INIT 0x0004
|
||||
#define MII_CIS8201_AUXCONSTAT_DUPLEX 0x0020
|
||||
#define MII_CIS8201_AUXCONSTAT_SPEED 0x0018
|
||||
#define MII_CIS8201_AUXCONSTAT_GBIT 0x0010
|
||||
#define MII_CIS8201_AUXCONSTAT_100 0x0008
|
||||
|
||||
/* 88E1011 PHY Status Register */
|
||||
#define MII_M1011_PHY_SPEC_STATUS 0x11
|
||||
#define MII_M1011_PHY_SPEC_STATUS_1000 0x8000
|
||||
#define MII_M1011_PHY_SPEC_STATUS_100 0x4000
|
||||
#define MII_M1011_PHY_SPEC_STATUS_SPD_MASK 0xc000
|
||||
#define MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX 0x2000
|
||||
#define MII_M1011_PHY_SPEC_STATUS_RESOLVED 0x0800
|
||||
#define MII_M1011_PHY_SPEC_STATUS_LINK 0x0400
|
||||
|
||||
#define MII_M1011_IEVENT 0x13
|
||||
#define MII_M1011_IEVENT_CLEAR 0x0000
|
||||
|
||||
#define MII_M1011_IMASK 0x12
|
||||
#define MII_M1011_IMASK_INIT 0x6400
|
||||
#define MII_M1011_IMASK_CLEAR 0x0000
|
||||
|
||||
#define MII_DM9161_SCR 0x10
|
||||
#define MII_DM9161_SCR_INIT 0x0610
|
||||
|
||||
/* DM9161 Specified Configuration and Status Register */
|
||||
#define MII_DM9161_SCSR 0x11
|
||||
#define MII_DM9161_SCSR_100F 0x8000
|
||||
#define MII_DM9161_SCSR_100H 0x4000
|
||||
#define MII_DM9161_SCSR_10F 0x2000
|
||||
#define MII_DM9161_SCSR_10H 0x1000
|
||||
|
||||
/* DM9161 Interrupt Register */
|
||||
#define MII_DM9161_INTR 0x15
|
||||
#define MII_DM9161_INTR_PEND 0x8000
|
||||
#define MII_DM9161_INTR_DPLX_MASK 0x0800
|
||||
#define MII_DM9161_INTR_SPD_MASK 0x0400
|
||||
#define MII_DM9161_INTR_LINK_MASK 0x0200
|
||||
#define MII_DM9161_INTR_MASK 0x0100
|
||||
#define MII_DM9161_INTR_DPLX_CHANGE 0x0010
|
||||
#define MII_DM9161_INTR_SPD_CHANGE 0x0008
|
||||
#define MII_DM9161_INTR_LINK_CHANGE 0x0004
|
||||
#define MII_DM9161_INTR_INIT 0x0000
|
||||
#define MII_DM9161_INTR_STOP \
|
||||
(MII_DM9161_INTR_DPLX_MASK | MII_DM9161_INTR_SPD_MASK \
|
||||
| MII_DM9161_INTR_LINK_MASK | MII_DM9161_INTR_MASK)
|
||||
|
||||
/* DM9161 10BT Configuration/Status */
|
||||
#define MII_DM9161_10BTCSR 0x12
|
||||
#define MII_DM9161_10BTCSR_INIT 0x7800
|
||||
|
||||
#define MII_BASIC_FEATURES (SUPPORTED_10baseT_Half | \
|
||||
SUPPORTED_10baseT_Full | \
|
||||
SUPPORTED_100baseT_Half | \
|
||||
SUPPORTED_100baseT_Full | \
|
||||
SUPPORTED_Autoneg | \
|
||||
SUPPORTED_TP | \
|
||||
SUPPORTED_MII)
|
||||
|
||||
#define MII_GBIT_FEATURES (MII_BASIC_FEATURES | \
|
||||
SUPPORTED_1000baseT_Half | \
|
||||
SUPPORTED_1000baseT_Full)
|
||||
|
||||
#define MII_READ_COMMAND 0x00000001
|
||||
|
||||
#define MII_INTERRUPT_DISABLED 0x0
|
||||
#define MII_INTERRUPT_ENABLED 0x1
|
||||
/* Taken from mii_if_info and sungem_phy.h */
|
||||
struct gfar_mii_info {
|
||||
/* Information about the PHY type */
|
||||
/* And management functions */
|
||||
struct phy_info *phyinfo;
|
||||
|
||||
/* forced speed & duplex (no autoneg)
|
||||
* partner speed & duplex & pause (autoneg)
|
||||
*/
|
||||
int speed;
|
||||
int duplex;
|
||||
int pause;
|
||||
|
||||
/* The most recently read link state */
|
||||
int link;
|
||||
|
||||
/* Enabled Interrupts */
|
||||
u32 interrupts;
|
||||
|
||||
u32 advertising;
|
||||
int autoneg;
|
||||
int mii_id;
|
||||
|
||||
/* private data pointer */
|
||||
/* For use by PHYs to maintain extra state */
|
||||
void *priv;
|
||||
|
||||
/* Provided by host chip */
|
||||
struct net_device *dev;
|
||||
|
||||
/* A lock to ensure that only one thing can read/write
|
||||
* the MDIO bus at a time */
|
||||
spinlock_t mdio_lock;
|
||||
|
||||
/* Provided by ethernet driver */
|
||||
int (*mdio_read) (struct net_device *dev, int mii_id, int reg);
|
||||
void (*mdio_write) (struct net_device *dev, int mii_id, int reg, int val);
|
||||
};
|
||||
|
||||
/* struct phy_info: a structure which defines attributes for a PHY
|
||||
*
|
||||
* id will contain a number which represents the PHY. During
|
||||
* startup, the driver will poll the PHY to find out what its
|
||||
* UID--as defined by registers 2 and 3--is. The 32-bit result
|
||||
* gotten from the PHY will be ANDed with phy_id_mask to
|
||||
* discard any bits which may change based on revision numbers
|
||||
* unimportant to functionality
|
||||
*
|
||||
* There are 6 commands which take a gfar_mii_info structure.
|
||||
* Each PHY must declare config_aneg, and read_status.
|
||||
*/
|
||||
struct phy_info {
|
||||
u32 phy_id;
|
||||
char *name;
|
||||
unsigned int phy_id_mask;
|
||||
u32 features;
|
||||
|
||||
/* Called to initialize the PHY */
|
||||
int (*init)(struct gfar_mii_info *mii_info);
|
||||
|
||||
/* Called to suspend the PHY for power */
|
||||
int (*suspend)(struct gfar_mii_info *mii_info);
|
||||
|
||||
/* Reconfigures autonegotiation (or disables it) */
|
||||
int (*config_aneg)(struct gfar_mii_info *mii_info);
|
||||
|
||||
/* Determines the negotiated speed and duplex */
|
||||
int (*read_status)(struct gfar_mii_info *mii_info);
|
||||
|
||||
/* Clears any pending interrupts */
|
||||
int (*ack_interrupt)(struct gfar_mii_info *mii_info);
|
||||
|
||||
/* Enables or disables interrupts */
|
||||
int (*config_intr)(struct gfar_mii_info *mii_info);
|
||||
|
||||
/* Clears up any memory if needed */
|
||||
void (*close)(struct gfar_mii_info *mii_info);
|
||||
};
|
||||
|
||||
struct phy_info *get_phy_info(struct gfar_mii_info *mii_info);
|
||||
int read_phy_reg(struct net_device *dev, int mii_id, int regnum);
|
||||
void write_phy_reg(struct net_device *dev, int mii_id, int regnum, int value);
|
||||
void mii_clear_phy_interrupt(struct gfar_mii_info *mii_info);
|
||||
void mii_configure_phy_interrupt(struct gfar_mii_info *mii_info, u32 interrupts);
|
||||
|
||||
struct dm9161_private {
|
||||
struct timer_list timer;
|
||||
int resetdone;
|
||||
};
|
||||
|
||||
#endif /* GIANFAR_PHY_H */
|
@ -1,6 +1,7 @@
|
||||
config MKISS
|
||||
tristate "Serial port KISS driver"
|
||||
depends on AX25
|
||||
select CRC16
|
||||
---help---
|
||||
KISS is a protocol used for the exchange of data between a computer
|
||||
and a Terminal Node Controller (a small embedded system commonly
|
||||
|
@ -144,7 +144,7 @@ static inline struct net_device *bpq_get_ax25_dev(struct net_device *dev)
|
||||
{
|
||||
struct bpqdev *bpq;
|
||||
|
||||
list_for_each_entry(bpq, &bpq_devices, bpq_list) {
|
||||
list_for_each_entry_rcu(bpq, &bpq_devices, bpq_list) {
|
||||
if (bpq->ethdev == dev)
|
||||
return bpq->axdev;
|
||||
}
|
||||
@ -399,7 +399,7 @@ static void *bpq_seq_start(struct seq_file *seq, loff_t *pos)
|
||||
if (*pos == 0)
|
||||
return SEQ_START_TOKEN;
|
||||
|
||||
list_for_each_entry(bpqdev, &bpq_devices, bpq_list) {
|
||||
list_for_each_entry_rcu(bpqdev, &bpq_devices, bpq_list) {
|
||||
if (i == *pos)
|
||||
return bpqdev;
|
||||
}
|
||||
@ -418,7 +418,7 @@ static void *bpq_seq_next(struct seq_file *seq, void *v, loff_t *pos)
|
||||
p = ((struct bpqdev *)v)->bpq_list.next;
|
||||
|
||||
return (p == &bpq_devices) ? NULL
|
||||
: list_entry(p, struct bpqdev, bpq_list);
|
||||
: rcu_dereference(list_entry(p, struct bpqdev, bpq_list));
|
||||
}
|
||||
|
||||
static void bpq_seq_stop(struct seq_file *seq, void *v)
|
||||
@ -561,8 +561,6 @@ static int bpq_device_event(struct notifier_block *this,unsigned long event, voi
|
||||
if (!dev_is_ethdev(dev))
|
||||
return NOTIFY_DONE;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
switch (event) {
|
||||
case NETDEV_UP: /* new ethernet device -> new BPQ interface */
|
||||
if (bpq_get_ax25_dev(dev) == NULL)
|
||||
@ -581,7 +579,6 @@ static int bpq_device_event(struct notifier_block *this,unsigned long event, voi
|
||||
default:
|
||||
break;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
@ -14,13 +14,14 @@
|
||||
*
|
||||
* Copyright (C) Hans Alblas PE1AYX <hans@esrac.ele.tue.nl>
|
||||
* Copyright (C) 2004, 05 Ralf Baechle DL5RB <ralf@linux-mips.org>
|
||||
* Copyright (C) 2004, 05 Thomas Osterried DL9SAU <thomas@x-berg.in-berlin.de>
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/module.h>
|
||||
#include <asm/system.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/crc16.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/interrupt.h>
|
||||
@ -39,11 +40,6 @@
|
||||
|
||||
#include <net/ax25.h>
|
||||
|
||||
#ifdef CONFIG_INET
|
||||
#include <linux/ip.h>
|
||||
#include <linux/tcp.h>
|
||||
#endif
|
||||
|
||||
#define AX_MTU 236
|
||||
|
||||
/* SLIP/KISS protocol characters. */
|
||||
@ -80,9 +76,13 @@ struct mkiss {
|
||||
|
||||
int mode;
|
||||
int crcmode; /* MW: for FlexNet, SMACK etc. */
|
||||
#define CRC_MODE_NONE 0
|
||||
#define CRC_MODE_FLEX 1
|
||||
#define CRC_MODE_SMACK 2
|
||||
int crcauto; /* CRC auto mode */
|
||||
|
||||
#define CRC_MODE_NONE 0
|
||||
#define CRC_MODE_FLEX 1
|
||||
#define CRC_MODE_SMACK 2
|
||||
#define CRC_MODE_FLEX_TEST 3
|
||||
#define CRC_MODE_SMACK_TEST 4
|
||||
|
||||
atomic_t refcnt;
|
||||
struct semaphore dead_sem;
|
||||
@ -151,6 +151,21 @@ static int check_crc_flex(unsigned char *cp, int size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int check_crc_16(unsigned char *cp, int size)
|
||||
{
|
||||
unsigned short crc = 0x0000;
|
||||
|
||||
if (size < 3)
|
||||
return -1;
|
||||
|
||||
crc = crc16(0, cp, size);
|
||||
|
||||
if (crc != 0x0000)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Standard encapsulation
|
||||
*/
|
||||
@ -237,19 +252,42 @@ static void ax_bump(struct mkiss *ax)
|
||||
|
||||
spin_lock_bh(&ax->buflock);
|
||||
if (ax->rbuff[0] > 0x0f) {
|
||||
if (ax->rbuff[0] & 0x20) {
|
||||
ax->crcmode = CRC_MODE_FLEX;
|
||||
if (check_crc_flex(ax->rbuff, ax->rcount) < 0) {
|
||||
ax->stats.rx_errors++;
|
||||
if (ax->rbuff[0] & 0x80) {
|
||||
if (check_crc_16(ax->rbuff, ax->rcount) < 0) {
|
||||
ax->stats.rx_errors++;
|
||||
spin_unlock_bh(&ax->buflock);
|
||||
|
||||
return;
|
||||
}
|
||||
if (ax->crcmode != CRC_MODE_SMACK && ax->crcauto) {
|
||||
printk(KERN_INFO
|
||||
"mkiss: %s: Switchting to crc-smack\n",
|
||||
ax->dev->name);
|
||||
ax->crcmode = CRC_MODE_SMACK;
|
||||
}
|
||||
ax->rcount -= 2;
|
||||
/* dl9sau bugfix: the trailling two bytes flexnet crc
|
||||
* will not be passed to the kernel. thus we have
|
||||
* to correct the kissparm signature, because it
|
||||
* indicates a crc but there's none
|
||||
*ax->rbuff &= ~0x80;
|
||||
} else if (ax->rbuff[0] & 0x20) {
|
||||
if (check_crc_flex(ax->rbuff, ax->rcount) < 0) {
|
||||
ax->stats.rx_errors++;
|
||||
spin_unlock_bh(&ax->buflock);
|
||||
return;
|
||||
}
|
||||
if (ax->crcmode != CRC_MODE_FLEX && ax->crcauto) {
|
||||
printk(KERN_INFO
|
||||
"mkiss: %s: Switchting to crc-flexnet\n",
|
||||
ax->dev->name);
|
||||
ax->crcmode = CRC_MODE_FLEX;
|
||||
}
|
||||
ax->rcount -= 2;
|
||||
|
||||
/*
|
||||
* dl9sau bugfix: the trailling two bytes flexnet crc
|
||||
* will not be passed to the kernel. thus we have to
|
||||
* correct the kissparm signature, because it indicates
|
||||
* a crc but there's none
|
||||
*/
|
||||
*ax->rbuff &= ~0x20;
|
||||
*ax->rbuff &= ~0x20;
|
||||
}
|
||||
}
|
||||
spin_unlock_bh(&ax->buflock);
|
||||
@ -417,20 +455,69 @@ static void ax_encaps(struct net_device *dev, unsigned char *icp, int len)
|
||||
p = icp;
|
||||
|
||||
spin_lock_bh(&ax->buflock);
|
||||
switch (ax->crcmode) {
|
||||
unsigned short crc;
|
||||
if ((*p & 0x0f) != 0) {
|
||||
/* Configuration Command (kissparms(1).
|
||||
* Protocol spec says: never append CRC.
|
||||
* This fixes a very old bug in the linux
|
||||
* kiss driver. -- dl9sau */
|
||||
switch (*p & 0xff) {
|
||||
case 0x85:
|
||||
/* command from userspace especially for us,
|
||||
* not for delivery to the tnc */
|
||||
if (len > 1) {
|
||||
int cmd = (p[1] & 0xff);
|
||||
switch(cmd) {
|
||||
case 3:
|
||||
ax->crcmode = CRC_MODE_SMACK;
|
||||
break;
|
||||
case 2:
|
||||
ax->crcmode = CRC_MODE_FLEX;
|
||||
break;
|
||||
case 1:
|
||||
ax->crcmode = CRC_MODE_NONE;
|
||||
break;
|
||||
case 0:
|
||||
default:
|
||||
ax->crcmode = CRC_MODE_SMACK_TEST;
|
||||
cmd = 0;
|
||||
}
|
||||
ax->crcauto = (cmd ? 0 : 1);
|
||||
printk(KERN_INFO "mkiss: %s: crc mode %s %d\n", ax->dev->name, (len) ? "set to" : "is", cmd);
|
||||
}
|
||||
spin_unlock_bh(&ax->buflock);
|
||||
netif_start_queue(dev);
|
||||
|
||||
case CRC_MODE_FLEX:
|
||||
*p |= 0x20;
|
||||
crc = calc_crc_flex(p, len);
|
||||
count = kiss_esc_crc(p, (unsigned char *)ax->xbuff, crc, len+2);
|
||||
break;
|
||||
return;
|
||||
default:
|
||||
count = kiss_esc(p, (unsigned char *)ax->xbuff, len);
|
||||
}
|
||||
} else {
|
||||
unsigned short crc;
|
||||
switch (ax->crcmode) {
|
||||
case CRC_MODE_SMACK_TEST:
|
||||
ax->crcmode = CRC_MODE_FLEX_TEST;
|
||||
printk(KERN_INFO "mkiss: %s: Trying crc-smack\n", ax->dev->name);
|
||||
// fall through
|
||||
case CRC_MODE_SMACK:
|
||||
*p |= 0x80;
|
||||
crc = swab16(crc16(0, p, len));
|
||||
count = kiss_esc_crc(p, (unsigned char *)ax->xbuff, crc, len+2);
|
||||
break;
|
||||
case CRC_MODE_FLEX_TEST:
|
||||
ax->crcmode = CRC_MODE_NONE;
|
||||
printk(KERN_INFO "mkiss: %s: Trying crc-flexnet\n", ax->dev->name);
|
||||
// fall through
|
||||
case CRC_MODE_FLEX:
|
||||
*p |= 0x20;
|
||||
crc = calc_crc_flex(p, len);
|
||||
count = kiss_esc_crc(p, (unsigned char *)ax->xbuff, crc, len+2);
|
||||
break;
|
||||
|
||||
default:
|
||||
count = kiss_esc(p, (unsigned char *)ax->xbuff, len);
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
count = kiss_esc(p, (unsigned char *)ax->xbuff, len);
|
||||
break;
|
||||
}
|
||||
|
||||
set_bit(TTY_DO_WRITE_WAKEUP, &ax->tty->flags);
|
||||
actual = ax->tty->driver->write(ax->tty, ax->xbuff, count);
|
||||
ax->stats.tx_packets++;
|
||||
@ -439,8 +526,6 @@ static void ax_encaps(struct net_device *dev, unsigned char *icp, int len)
|
||||
ax->dev->trans_start = jiffies;
|
||||
ax->xleft = count - actual;
|
||||
ax->xhead = ax->xbuff + actual;
|
||||
|
||||
spin_unlock_bh(&ax->buflock);
|
||||
}
|
||||
|
||||
/* Encapsulate an AX.25 packet and kick it into a TTY queue. */
|
||||
@ -622,7 +707,7 @@ static void ax_setup(struct net_device *dev)
|
||||
* best way to fix this is to use a rwlock in the tty struct, but for now we
|
||||
* use a single global rwlock for all ttys in ppp line discipline.
|
||||
*/
|
||||
static rwlock_t disc_data_lock = RW_LOCK_UNLOCKED;
|
||||
static DEFINE_RWLOCK(disc_data_lock);
|
||||
|
||||
static struct mkiss *mkiss_get(struct tty_struct *tty)
|
||||
{
|
||||
@ -643,6 +728,8 @@ static void mkiss_put(struct mkiss *ax)
|
||||
up(&ax->dead_sem);
|
||||
}
|
||||
|
||||
static int crc_force = 0; /* Can be overridden with insmod */
|
||||
|
||||
static int mkiss_open(struct tty_struct *tty)
|
||||
{
|
||||
struct net_device *dev;
|
||||
@ -682,6 +769,33 @@ static int mkiss_open(struct tty_struct *tty)
|
||||
if (register_netdev(dev))
|
||||
goto out_free_buffers;
|
||||
|
||||
/* after register_netdev() - because else printk smashes the kernel */
|
||||
switch (crc_force) {
|
||||
case 3:
|
||||
ax->crcmode = CRC_MODE_SMACK;
|
||||
printk(KERN_INFO "mkiss: %s: crc mode smack forced.\n",
|
||||
ax->dev->name);
|
||||
break;
|
||||
case 2:
|
||||
ax->crcmode = CRC_MODE_FLEX;
|
||||
printk(KERN_INFO "mkiss: %s: crc mode flexnet forced.\n",
|
||||
ax->dev->name);
|
||||
break;
|
||||
case 1:
|
||||
ax->crcmode = CRC_MODE_NONE;
|
||||
printk(KERN_INFO "mkiss: %s: crc mode disabled.\n",
|
||||
ax->dev->name);
|
||||
break;
|
||||
case 0:
|
||||
/* fall through */
|
||||
default:
|
||||
crc_force = 0;
|
||||
printk(KERN_INFO "mkiss: %s: crc mode is auto.\n",
|
||||
ax->dev->name);
|
||||
ax->crcmode = CRC_MODE_SMACK_TEST;
|
||||
}
|
||||
ax->crcauto = (crc_force ? 0 : 1);
|
||||
|
||||
netif_start_queue(dev);
|
||||
|
||||
/* Done. We have linked the TTY line to a channel. */
|
||||
@ -765,7 +879,6 @@ static int mkiss_ioctl(struct tty_struct *tty, struct file *file,
|
||||
|
||||
case SIOCSIFHWADDR: {
|
||||
char addr[AX25_ADDR_LEN];
|
||||
printk(KERN_INFO "In SIOCSIFHWADDR");
|
||||
|
||||
if (copy_from_user(&addr,
|
||||
(void __user *) arg, AX25_ADDR_LEN)) {
|
||||
@ -864,6 +977,7 @@ static void mkiss_write_wakeup(struct tty_struct *tty)
|
||||
}
|
||||
|
||||
static struct tty_ldisc ax_ldisc = {
|
||||
.owner = THIS_MODULE,
|
||||
.magic = TTY_LDISC_MAGIC,
|
||||
.name = "mkiss",
|
||||
.open = mkiss_open,
|
||||
@ -904,6 +1018,8 @@ static void __exit mkiss_exit_driver(void)
|
||||
|
||||
MODULE_AUTHOR("Ralf Baechle DL5RB <ralf@linux-mips.org>");
|
||||
MODULE_DESCRIPTION("KISS driver for AX.25 over TTYs");
|
||||
MODULE_PARM(crc_force, "i");
|
||||
MODULE_PARM_DESC(crc_force, "crc [0 = auto | 1 = none | 2 = flexnet | 3 = smack]");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS_LDISC(N_AX25);
|
||||
|
||||
|
@ -1,62 +0,0 @@
|
||||
/****************************************************************************
|
||||
* Defines for the Multi-KISS driver.
|
||||
****************************************************************************/
|
||||
|
||||
#define AX25_MAXDEV 16 /* MAX number of AX25 channels;
|
||||
This can be overridden with
|
||||
insmod -oax25_maxdev=nnn */
|
||||
#define AX_MTU 236
|
||||
|
||||
/* SLIP/KISS protocol characters. */
|
||||
#define END 0300 /* indicates end of frame */
|
||||
#define ESC 0333 /* indicates byte stuffing */
|
||||
#define ESC_END 0334 /* ESC ESC_END means END 'data' */
|
||||
#define ESC_ESC 0335 /* ESC ESC_ESC means ESC 'data' */
|
||||
|
||||
struct ax_disp {
|
||||
int magic;
|
||||
|
||||
/* Various fields. */
|
||||
struct tty_struct *tty; /* ptr to TTY structure */
|
||||
struct net_device *dev; /* easy for intr handling */
|
||||
|
||||
/* These are pointers to the malloc()ed frame buffers. */
|
||||
unsigned char *rbuff; /* receiver buffer */
|
||||
int rcount; /* received chars counter */
|
||||
unsigned char *xbuff; /* transmitter buffer */
|
||||
unsigned char *xhead; /* pointer to next byte to XMIT */
|
||||
int xleft; /* bytes left in XMIT queue */
|
||||
|
||||
/* SLIP interface statistics. */
|
||||
unsigned long rx_packets; /* inbound frames counter */
|
||||
unsigned long tx_packets; /* outbound frames counter */
|
||||
unsigned long rx_bytes; /* inbound bytes counter */
|
||||
unsigned long tx_bytes; /* outbound bytes counter */
|
||||
unsigned long rx_errors; /* Parity, etc. errors */
|
||||
unsigned long tx_errors; /* Planned stuff */
|
||||
unsigned long rx_dropped; /* No memory for skb */
|
||||
unsigned long tx_dropped; /* When MTU change */
|
||||
unsigned long rx_over_errors; /* Frame bigger then SLIP buf. */
|
||||
|
||||
/* Detailed SLIP statistics. */
|
||||
int mtu; /* Our mtu (to spot changes!) */
|
||||
int buffsize; /* Max buffers sizes */
|
||||
|
||||
|
||||
unsigned long flags; /* Flag values/ mode etc */
|
||||
/* long req'd: used by set_bit --RR */
|
||||
#define AXF_INUSE 0 /* Channel in use */
|
||||
#define AXF_ESCAPE 1 /* ESC received */
|
||||
#define AXF_ERROR 2 /* Parity, etc. error */
|
||||
#define AXF_KEEPTEST 3 /* Keepalive test flag */
|
||||
#define AXF_OUTWAIT 4 /* is outpacket was flag */
|
||||
|
||||
int mode;
|
||||
int crcmode; /* MW: for FlexNet, SMACK etc. */
|
||||
#define CRC_MODE_NONE 0
|
||||
#define CRC_MODE_FLEX 1
|
||||
#define CRC_MODE_SMACK 2
|
||||
spinlock_t buflock; /* lock for rbuf and xbuf */
|
||||
};
|
||||
|
||||
#define AX25_MAGIC 0x5316
|
@ -2517,10 +2517,8 @@ static int hp100_down_vg_link(struct net_device *dev)
|
||||
do {
|
||||
if (hp100_inb(VG_LAN_CFG_1) & HP100_LINK_CABLE_ST)
|
||||
break;
|
||||
if (!in_interrupt()) {
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
schedule_timeout(1);
|
||||
}
|
||||
if (!in_interrupt())
|
||||
schedule_timeout_interruptible(1);
|
||||
} while (time_after(time, jiffies));
|
||||
|
||||
if (time_after_eq(jiffies, time)) /* no signal->no logout */
|
||||
@ -2536,10 +2534,8 @@ static int hp100_down_vg_link(struct net_device *dev)
|
||||
do {
|
||||
if (!(hp100_inb(VG_LAN_CFG_1) & HP100_LINK_UP_ST))
|
||||
break;
|
||||
if (!in_interrupt()) {
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
schedule_timeout(1);
|
||||
}
|
||||
if (!in_interrupt())
|
||||
schedule_timeout_interruptible(1);
|
||||
} while (time_after(time, jiffies));
|
||||
|
||||
#ifdef HP100_DEBUG
|
||||
@ -2577,10 +2573,8 @@ static int hp100_down_vg_link(struct net_device *dev)
|
||||
do {
|
||||
if (!(hp100_inb(MAC_CFG_4) & HP100_MAC_SEL_ST))
|
||||
break;
|
||||
if (!in_interrupt()) {
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
schedule_timeout(1);
|
||||
}
|
||||
if (!in_interrupt())
|
||||
schedule_timeout_interruptible(1);
|
||||
} while (time_after(time, jiffies));
|
||||
|
||||
hp100_orb(HP100_AUTO_MODE, MAC_CFG_3); /* Autosel back on */
|
||||
@ -2591,10 +2585,8 @@ static int hp100_down_vg_link(struct net_device *dev)
|
||||
do {
|
||||
if ((hp100_inb(VG_LAN_CFG_1) & HP100_LINK_CABLE_ST) == 0)
|
||||
break;
|
||||
if (!in_interrupt()) {
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
schedule_timeout(1);
|
||||
}
|
||||
if (!in_interrupt())
|
||||
schedule_timeout_interruptible(1);
|
||||
} while (time_after(time, jiffies));
|
||||
|
||||
if (time_before_eq(time, jiffies)) {
|
||||
@ -2606,10 +2598,8 @@ static int hp100_down_vg_link(struct net_device *dev)
|
||||
|
||||
time = jiffies + (2 * HZ); /* This seems to take a while.... */
|
||||
do {
|
||||
if (!in_interrupt()) {
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
schedule_timeout(1);
|
||||
}
|
||||
if (!in_interrupt())
|
||||
schedule_timeout_interruptible(1);
|
||||
} while (time_after(time, jiffies));
|
||||
|
||||
return 0;
|
||||
@ -2659,10 +2649,8 @@ static int hp100_login_to_vg_hub(struct net_device *dev, u_short force_relogin)
|
||||
do {
|
||||
if (~(hp100_inb(VG_LAN_CFG_1) & HP100_LINK_UP_ST))
|
||||
break;
|
||||
if (!in_interrupt()) {
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
schedule_timeout(1);
|
||||
}
|
||||
if (!in_interrupt())
|
||||
schedule_timeout_interruptible(1);
|
||||
} while (time_after(time, jiffies));
|
||||
|
||||
/* Start an addressed training and optionally request promiscuous port */
|
||||
@ -2697,10 +2685,8 @@ static int hp100_login_to_vg_hub(struct net_device *dev, u_short force_relogin)
|
||||
do {
|
||||
if (hp100_inb(VG_LAN_CFG_1) & HP100_LINK_CABLE_ST)
|
||||
break;
|
||||
if (!in_interrupt()) {
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
schedule_timeout(1);
|
||||
}
|
||||
if (!in_interrupt())
|
||||
schedule_timeout_interruptible(1);
|
||||
} while (time_before(jiffies, time));
|
||||
|
||||
if (time_after_eq(jiffies, time)) {
|
||||
@ -2723,10 +2709,8 @@ static int hp100_login_to_vg_hub(struct net_device *dev, u_short force_relogin)
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
if (!in_interrupt()) {
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
schedule_timeout(1);
|
||||
}
|
||||
if (!in_interrupt())
|
||||
schedule_timeout_interruptible(1);
|
||||
} while (time_after(time, jiffies));
|
||||
}
|
||||
|
||||
|
@ -678,10 +678,9 @@ static void turnaround_delay(const struct stir_cb *stir, long us)
|
||||
return;
|
||||
|
||||
ticks = us / (1000000 / HZ);
|
||||
if (ticks > 0) {
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule_timeout(1 + ticks);
|
||||
} else
|
||||
if (ticks > 0)
|
||||
schedule_timeout_interruptible(1 + ticks);
|
||||
else
|
||||
udelay(us);
|
||||
}
|
||||
|
||||
|
@ -645,11 +645,10 @@ ixgb_phys_id(struct net_device *netdev, uint32_t data)
|
||||
|
||||
mod_timer(&adapter->blink_timer, jiffies);
|
||||
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
if(data)
|
||||
schedule_timeout(data * HZ);
|
||||
if (data)
|
||||
schedule_timeout_interruptible(data * HZ);
|
||||
else
|
||||
schedule_timeout(MAX_SCHEDULE_TIMEOUT);
|
||||
schedule_timeout_interruptible(MAX_SCHEDULE_TIMEOUT);
|
||||
|
||||
del_timer_sync(&adapter->blink_timer);
|
||||
ixgb_led_off(&adapter->hw);
|
||||
@ -723,6 +722,7 @@ struct ethtool_ops ixgb_ethtool_ops = {
|
||||
.phys_id = ixgb_phys_id,
|
||||
.get_stats_count = ixgb_get_stats_count,
|
||||
.get_ethtool_stats = ixgb_get_ethtool_stats,
|
||||
.get_perm_addr = ethtool_op_get_perm_addr,
|
||||
};
|
||||
|
||||
void ixgb_set_ethtool_ops(struct net_device *netdev)
|
||||
|
@ -460,8 +460,9 @@ ixgb_probe(struct pci_dev *pdev,
|
||||
}
|
||||
|
||||
ixgb_get_ee_mac_addr(&adapter->hw, netdev->dev_addr);
|
||||
memcpy(netdev->perm_addr, netdev->dev_addr, netdev->addr_len);
|
||||
|
||||
if(!is_valid_ether_addr(netdev->dev_addr)) {
|
||||
if(!is_valid_ether_addr(netdev->perm_addr)) {
|
||||
err = -EIO;
|
||||
goto err_eeprom;
|
||||
}
|
||||
|
@ -298,7 +298,7 @@ static int __init lne390_probe1(struct net_device *dev, int ioaddr)
|
||||
return 0;
|
||||
unmap:
|
||||
if (ei_status.reg0)
|
||||
iounmap((void *)dev->mem_start);
|
||||
iounmap(ei_status.mem);
|
||||
cleanup:
|
||||
free_irq(dev->irq, dev);
|
||||
return ret;
|
||||
|
@ -207,6 +207,20 @@ int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mii_check_gmii_support(struct mii_if_info *mii)
|
||||
{
|
||||
int reg;
|
||||
|
||||
reg = mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR);
|
||||
if (reg & BMSR_ESTATEN) {
|
||||
reg = mii->mdio_read(mii->dev, mii->phy_id, MII_ESTATUS);
|
||||
if (reg & (ESTATUS_1000_TFULL | ESTATUS_1000_THALF))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mii_link_ok (struct mii_if_info *mii)
|
||||
{
|
||||
/* first, a dummy read, needed to latch some MII phys */
|
||||
@ -394,5 +408,6 @@ EXPORT_SYMBOL(mii_ethtool_gset);
|
||||
EXPORT_SYMBOL(mii_ethtool_sset);
|
||||
EXPORT_SYMBOL(mii_check_link);
|
||||
EXPORT_SYMBOL(mii_check_media);
|
||||
EXPORT_SYMBOL(mii_check_gmii_support);
|
||||
EXPORT_SYMBOL(generic_mii_ioctl);
|
||||
|
||||
|
371
drivers/net/mipsnet.c
Normal file
371
drivers/net/mipsnet.c
Normal file
@ -0,0 +1,371 @@
|
||||
/*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#define DEBUG
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/mips-boards/simint.h>
|
||||
|
||||
#include "mipsnet.h" /* actual device IO mapping */
|
||||
|
||||
#define MIPSNET_VERSION "2005-06-20"
|
||||
|
||||
#define mipsnet_reg_address(dev, field) (dev->base_addr + field_offset(field))
|
||||
|
||||
struct mipsnet_priv {
|
||||
struct net_device_stats stats;
|
||||
};
|
||||
|
||||
static struct platform_device *mips_plat_dev;
|
||||
|
||||
static char mipsnet_string[] = "mipsnet";
|
||||
|
||||
/*
|
||||
* Copy data from the MIPSNET rx data port
|
||||
*/
|
||||
static int ioiocpy_frommipsnet(struct net_device *dev, unsigned char *kdata,
|
||||
int len)
|
||||
{
|
||||
uint32_t available_len = inl(mipsnet_reg_address(dev, rxDataCount));
|
||||
if (available_len < len)
|
||||
return -EFAULT;
|
||||
|
||||
for (; len > 0; len--, kdata++) {
|
||||
*kdata = inb(mipsnet_reg_address(dev, rxDataBuffer));
|
||||
}
|
||||
|
||||
return inl(mipsnet_reg_address(dev, rxDataCount));
|
||||
}
|
||||
|
||||
static inline ssize_t mipsnet_put_todevice(struct net_device *dev,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
int count_to_go = skb->len;
|
||||
char *buf_ptr = skb->data;
|
||||
struct mipsnet_priv *mp = netdev_priv(dev);
|
||||
|
||||
pr_debug("%s: %s(): telling MIPSNET txDataCount(%d)\n",
|
||||
dev->name, __FUNCTION__, skb->len);
|
||||
|
||||
outl(skb->len, mipsnet_reg_address(dev, txDataCount));
|
||||
|
||||
pr_debug("%s: %s(): sending data to MIPSNET txDataBuffer(%d)\n",
|
||||
dev->name, __FUNCTION__, skb->len);
|
||||
|
||||
for (; count_to_go; buf_ptr++, count_to_go--) {
|
||||
outb(*buf_ptr, mipsnet_reg_address(dev, txDataBuffer));
|
||||
}
|
||||
|
||||
mp->stats.tx_packets++;
|
||||
mp->stats.tx_bytes += skb->len;
|
||||
|
||||
return skb->len;
|
||||
}
|
||||
|
||||
static int mipsnet_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
pr_debug("%s:%s(): transmitting %d bytes\n",
|
||||
dev->name, __FUNCTION__, skb->len);
|
||||
|
||||
/* Only one packet at a time. Once TXDONE interrupt is serviced, the
|
||||
* queue will be restarted.
|
||||
*/
|
||||
netif_stop_queue(dev);
|
||||
mipsnet_put_todevice(dev, skb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline ssize_t mipsnet_get_fromdev(struct net_device *dev, size_t count)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
size_t len = count;
|
||||
struct mipsnet_priv *mp = netdev_priv(dev);
|
||||
|
||||
if (!(skb = alloc_skb(len + 2, GFP_KERNEL))) {
|
||||
mp->stats.rx_dropped++;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
skb_reserve(skb, 2);
|
||||
if (ioiocpy_frommipsnet(dev, skb_put(skb, len), len))
|
||||
return -EFAULT;
|
||||
|
||||
skb->dev = dev;
|
||||
skb->protocol = eth_type_trans(skb, dev);
|
||||
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
|
||||
pr_debug("%s:%s(): pushing RXed data to kernel\n",
|
||||
dev->name, __FUNCTION__);
|
||||
netif_rx(skb);
|
||||
|
||||
mp->stats.rx_packets++;
|
||||
mp->stats.rx_bytes += len;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static irqreturn_t
|
||||
mipsnet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
struct net_device *dev = dev_id;
|
||||
|
||||
irqreturn_t retval = IRQ_NONE;
|
||||
uint64_t interruptFlags;
|
||||
|
||||
if (irq == dev->irq) {
|
||||
pr_debug("%s:%s(): irq %d for device\n",
|
||||
dev->name, __FUNCTION__, irq);
|
||||
|
||||
retval = IRQ_HANDLED;
|
||||
|
||||
interruptFlags =
|
||||
inl(mipsnet_reg_address(dev, interruptControl));
|
||||
pr_debug("%s:%s(): intCtl=0x%016llx\n", dev->name,
|
||||
__FUNCTION__, interruptFlags);
|
||||
|
||||
if (interruptFlags & MIPSNET_INTCTL_TXDONE) {
|
||||
pr_debug("%s:%s(): got TXDone\n",
|
||||
dev->name, __FUNCTION__);
|
||||
outl(MIPSNET_INTCTL_TXDONE,
|
||||
mipsnet_reg_address(dev, interruptControl));
|
||||
// only one packet at a time, we are done.
|
||||
netif_wake_queue(dev);
|
||||
} else if (interruptFlags & MIPSNET_INTCTL_RXDONE) {
|
||||
pr_debug("%s:%s(): got RX data\n",
|
||||
dev->name, __FUNCTION__);
|
||||
mipsnet_get_fromdev(dev,
|
||||
inl(mipsnet_reg_address(dev, rxDataCount)));
|
||||
pr_debug("%s:%s(): clearing RX int\n",
|
||||
dev->name, __FUNCTION__);
|
||||
outl(MIPSNET_INTCTL_RXDONE,
|
||||
mipsnet_reg_address(dev, interruptControl));
|
||||
|
||||
} else if (interruptFlags & MIPSNET_INTCTL_TESTBIT) {
|
||||
pr_debug("%s:%s(): got test interrupt\n",
|
||||
dev->name, __FUNCTION__);
|
||||
// TESTBIT is cleared on read.
|
||||
// And takes effect after a write with 0
|
||||
outl(0, mipsnet_reg_address(dev, interruptControl));
|
||||
} else {
|
||||
pr_debug("%s:%s(): no valid fags 0x%016llx\n",
|
||||
dev->name, __FUNCTION__, interruptFlags);
|
||||
// Maybe shared IRQ, just ignore, no clearing.
|
||||
retval = IRQ_NONE;
|
||||
}
|
||||
|
||||
} else {
|
||||
printk(KERN_INFO "%s: %s(): irq %d for unknown device\n",
|
||||
dev->name, __FUNCTION__, irq);
|
||||
retval = IRQ_NONE;
|
||||
}
|
||||
return retval;
|
||||
} //mipsnet_interrupt()
|
||||
|
||||
static int mipsnet_open(struct net_device *dev)
|
||||
{
|
||||
int err;
|
||||
pr_debug("%s: mipsnet_open\n", dev->name);
|
||||
|
||||
err = request_irq(dev->irq, &mipsnet_interrupt,
|
||||
SA_SHIRQ, dev->name, (void *) dev);
|
||||
|
||||
if (err) {
|
||||
pr_debug("%s: %s(): can't get irq %d\n",
|
||||
dev->name, __FUNCTION__, dev->irq);
|
||||
release_region(dev->base_addr, MIPSNET_IO_EXTENT);
|
||||
return err;
|
||||
}
|
||||
|
||||
pr_debug("%s: %s(): got IO region at 0x%04lx and irq %d for dev.\n",
|
||||
dev->name, __FUNCTION__, dev->base_addr, dev->irq);
|
||||
|
||||
|
||||
netif_start_queue(dev);
|
||||
|
||||
// test interrupt handler
|
||||
outl(MIPSNET_INTCTL_TESTBIT,
|
||||
mipsnet_reg_address(dev, interruptControl));
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mipsnet_close(struct net_device *dev)
|
||||
{
|
||||
pr_debug("%s: %s()\n", dev->name, __FUNCTION__);
|
||||
netif_stop_queue(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct net_device_stats *mipsnet_get_stats(struct net_device *dev)
|
||||
{
|
||||
struct mipsnet_priv *mp = netdev_priv(dev);
|
||||
|
||||
return &mp->stats;
|
||||
}
|
||||
|
||||
static void mipsnet_set_mclist(struct net_device *dev)
|
||||
{
|
||||
// we don't do anything
|
||||
return;
|
||||
}
|
||||
|
||||
static int __init mipsnet_probe(struct device *dev)
|
||||
{
|
||||
struct net_device *netdev;
|
||||
int err;
|
||||
|
||||
netdev = alloc_etherdev(sizeof(struct mipsnet_priv));
|
||||
if (!netdev) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev_set_drvdata(dev, netdev);
|
||||
|
||||
netdev->open = mipsnet_open;
|
||||
netdev->stop = mipsnet_close;
|
||||
netdev->hard_start_xmit = mipsnet_xmit;
|
||||
netdev->get_stats = mipsnet_get_stats;
|
||||
netdev->set_multicast_list = mipsnet_set_mclist;
|
||||
|
||||
/*
|
||||
* TODO: probe for these or load them from PARAM
|
||||
*/
|
||||
netdev->base_addr = 0x4200;
|
||||
netdev->irq = MIPSCPU_INT_BASE + MIPSCPU_INT_MB0 +
|
||||
inl(mipsnet_reg_address(netdev, interruptInfo));
|
||||
|
||||
// Get the io region now, get irq on open()
|
||||
if (!request_region(netdev->base_addr, MIPSNET_IO_EXTENT, "mipsnet")) {
|
||||
pr_debug("%s: %s(): IO region {start: 0x%04lux, len: %d} "
|
||||
"for dev is not availble.\n", netdev->name,
|
||||
__FUNCTION__, netdev->base_addr, MIPSNET_IO_EXTENT);
|
||||
err = -EBUSY;
|
||||
goto out_free_netdev;
|
||||
}
|
||||
|
||||
/*
|
||||
* Lacking any better mechanism to allocate a MAC address we use a
|
||||
* random one ...
|
||||
*/
|
||||
random_ether_addr(netdev->dev_addr);
|
||||
|
||||
err = register_netdev(netdev);
|
||||
if (err) {
|
||||
printk(KERN_ERR "MIPSNet: failed to register netdev.\n");
|
||||
goto out_free_region;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out_free_region:
|
||||
release_region(netdev->base_addr, MIPSNET_IO_EXTENT);
|
||||
|
||||
out_free_netdev:
|
||||
free_netdev(netdev);
|
||||
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __devexit mipsnet_device_remove(struct device *device)
|
||||
{
|
||||
struct net_device *dev = dev_get_drvdata(device);
|
||||
|
||||
unregister_netdev(dev);
|
||||
release_region(dev->base_addr, MIPSNET_IO_EXTENT);
|
||||
free_netdev(dev);
|
||||
dev_set_drvdata(device, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct device_driver mipsnet_driver = {
|
||||
.name = mipsnet_string,
|
||||
.bus = &platform_bus_type,
|
||||
.probe = mipsnet_probe,
|
||||
.remove = __devexit_p(mipsnet_device_remove),
|
||||
};
|
||||
|
||||
static void mipsnet_platform_release(struct device *device)
|
||||
{
|
||||
struct platform_device *pldev;
|
||||
|
||||
/* free device */
|
||||
pldev = to_platform_device(device);
|
||||
kfree(pldev);
|
||||
}
|
||||
|
||||
static int __init mipsnet_init_module(void)
|
||||
{
|
||||
struct platform_device *pldev;
|
||||
int err;
|
||||
|
||||
printk(KERN_INFO "MIPSNet Ethernet driver. Version: %s. "
|
||||
"(c)2005 MIPS Technologies, Inc.\n", MIPSNET_VERSION);
|
||||
|
||||
if (driver_register(&mipsnet_driver)) {
|
||||
printk(KERN_ERR "Driver registration failed\n");
|
||||
err = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!(pldev = kmalloc (sizeof (*pldev), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto out_unregister_driver;
|
||||
}
|
||||
|
||||
memset (pldev, 0, sizeof (*pldev));
|
||||
pldev->name = mipsnet_string;
|
||||
pldev->id = 0;
|
||||
pldev->dev.release = mipsnet_platform_release;
|
||||
|
||||
if (platform_device_register(pldev)) {
|
||||
err = -ENODEV;
|
||||
goto out_free_pldev;
|
||||
}
|
||||
|
||||
if (!pldev->dev.driver) {
|
||||
/*
|
||||
* The driver was not bound to this device, there was
|
||||
* no hardware at this address. Unregister it, as the
|
||||
* release fuction will take care of freeing the
|
||||
* allocated structure
|
||||
*/
|
||||
platform_device_unregister (pldev);
|
||||
}
|
||||
|
||||
mips_plat_dev = pldev;
|
||||
|
||||
return 0;
|
||||
|
||||
out_free_pldev:
|
||||
kfree(pldev);
|
||||
|
||||
out_unregister_driver:
|
||||
driver_unregister(&mipsnet_driver);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static void __exit mipsnet_exit_module(void)
|
||||
{
|
||||
pr_debug("MIPSNet Ethernet driver exiting\n");
|
||||
|
||||
driver_unregister(&mipsnet_driver);
|
||||
}
|
||||
|
||||
module_init(mipsnet_init_module);
|
||||
module_exit(mipsnet_exit_module);
|
127
drivers/net/mipsnet.h
Normal file
127
drivers/net/mipsnet.h
Normal file
@ -0,0 +1,127 @@
|
||||
//
|
||||
// <COPYRIGHT CLASS="1B" YEAR="2005">
|
||||
// Unpublished work (c) MIPS Technologies, Inc. All rights reserved.
|
||||
// Unpublished rights reserved under the copyright laws of the U.S.A. and
|
||||
// other countries.
|
||||
//
|
||||
// PROPRIETARY / SECRET CONFIDENTIAL INFORMATION OF MIPS TECHNOLOGIES, INC.
|
||||
// FOR INTERNAL USE ONLY.
|
||||
//
|
||||
// Under no circumstances (contract or otherwise) may this information be
|
||||
// disclosed to, or copied, modified or used by anyone other than employees
|
||||
// or contractors of MIPS Technologies having a need to know.
|
||||
// </COPYRIGHT>
|
||||
//
|
||||
//++
|
||||
// File: MIPS_Net.h
|
||||
//
|
||||
// Description:
|
||||
// The definition of the emulated MIPSNET device's interface.
|
||||
//
|
||||
// Notes: This include file needs to work from a Linux device drivers.
|
||||
//
|
||||
//--
|
||||
//
|
||||
|
||||
#ifndef __MIPSNET_H
|
||||
#define __MIPSNET_H
|
||||
|
||||
/*
|
||||
* Id of this Net device, as seen by the core.
|
||||
*/
|
||||
#define MIPS_NET_DEV_ID ((uint64_t) \
|
||||
((uint64_t)'M'<< 0)| \
|
||||
((uint64_t)'I'<< 8)| \
|
||||
((uint64_t)'P'<<16)| \
|
||||
((uint64_t)'S'<<24)| \
|
||||
((uint64_t)'N'<<32)| \
|
||||
((uint64_t)'E'<<40)| \
|
||||
((uint64_t)'T'<<48)| \
|
||||
((uint64_t)'0'<<56))
|
||||
|
||||
/*
|
||||
* Net status/control block as seen by sw in the core.
|
||||
* (Why not use bit fields? can't be bothered with cross-platform struct
|
||||
* packing.)
|
||||
*/
|
||||
typedef struct _net_control_block {
|
||||
/// dev info for probing
|
||||
/// reads as MIPSNET%d where %d is some form of version
|
||||
uint64_t devId; /*0x00 */
|
||||
|
||||
/*
|
||||
* read only busy flag.
|
||||
* Set and cleared by the Net Device to indicate that an rx or a tx
|
||||
* is in progress.
|
||||
*/
|
||||
uint32_t busy; /*0x08 */
|
||||
|
||||
/*
|
||||
* Set by the Net Device.
|
||||
* The device will set it once data has been received.
|
||||
* The value is the number of bytes that should be read from
|
||||
* rxDataBuffer. The value will decrease till 0 until all the data
|
||||
* from rxDataBuffer has been read.
|
||||
*/
|
||||
uint32_t rxDataCount; /*0x0c */
|
||||
#define MIPSNET_MAX_RXTX_DATACOUNT (1<<16)
|
||||
|
||||
/*
|
||||
* Settable from the MIPS core, cleared by the Net Device.
|
||||
* The core should set the number of bytes it wants to send,
|
||||
* then it should write those bytes of data to txDataBuffer.
|
||||
* The device will clear txDataCount has been processed (not necessarily sent).
|
||||
*/
|
||||
uint32_t txDataCount; /*0x10 */
|
||||
|
||||
/*
|
||||
* Interrupt control
|
||||
*
|
||||
* Used to clear the interrupted generated by this dev.
|
||||
* Write a 1 to clear the interrupt. (except bit31).
|
||||
*
|
||||
* Bit0 is set if it was a tx-done interrupt.
|
||||
* Bit1 is set when new rx-data is available.
|
||||
* Until this bit is cleared there will be no other RXs.
|
||||
*
|
||||
* Bit31 is used for testing, it clears after a read.
|
||||
* Writing 1 to this bit will cause an interrupt to be generated.
|
||||
* To clear the test interrupt, write 0 to this register.
|
||||
*/
|
||||
uint32_t interruptControl; /*0x14 */
|
||||
#define MIPSNET_INTCTL_TXDONE ((uint32_t)(1<< 0))
|
||||
#define MIPSNET_INTCTL_RXDONE ((uint32_t)(1<< 1))
|
||||
#define MIPSNET_INTCTL_TESTBIT ((uint32_t)(1<<31))
|
||||
#define MIPSNET_INTCTL_ALLSOURCES (MIPSNET_INTCTL_TXDONE|MIPSNET_INTCTL_RXDONE|MIPSNET_INTCTL_TESTBIT)
|
||||
|
||||
/*
|
||||
* Readonly core-specific interrupt info for the device to signal the core.
|
||||
* The meaning of the contents of this field might change.
|
||||
*/
|
||||
/*###\todo: the whole memIntf interrupt scheme is messy: the device should have
|
||||
* no control what so ever of what VPE/register set is being used.
|
||||
* The MemIntf should only expose interrupt lines, and something in the
|
||||
* config should be responsible for the line<->core/vpe bindings.
|
||||
*/
|
||||
uint32_t interruptInfo; /*0x18 */
|
||||
|
||||
/*
|
||||
* This is where the received data is read out.
|
||||
* There is more data to read until rxDataReady is 0.
|
||||
* Only 1 byte at this regs offset is used.
|
||||
*/
|
||||
uint32_t rxDataBuffer; /*0x1c */
|
||||
|
||||
/*
|
||||
* This is where the data to transmit is written.
|
||||
* Data should be written for the amount specified in the txDataCount register.
|
||||
* Only 1 byte at this regs offset is used.
|
||||
*/
|
||||
uint32_t txDataBuffer; /*0x20 */
|
||||
} MIPS_T_NetControl;
|
||||
|
||||
#define MIPSNET_IO_EXTENT 0x40 /* being generous */
|
||||
|
||||
#define field_offset(field) ((int)&((MIPS_T_NetControl*)(0))->field)
|
||||
|
||||
#endif /* __MIPSNET_H */
|
@ -54,6 +54,10 @@ static const char version2[] =
|
||||
#include <asm/system.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#if defined(CONFIG_TOSHIBA_RBTX4927) || defined(CONFIG_TOSHIBA_RBTX4938)
|
||||
#include <asm/tx4938/rbtx4938.h>
|
||||
#endif
|
||||
|
||||
#include "8390.h"
|
||||
|
||||
#define DRV_NAME "ne"
|
||||
@ -111,6 +115,9 @@ bad_clone_list[] __initdata = {
|
||||
{"E-LAN100", "E-LAN200", {0x00, 0x00, 0x5d}}, /* Broken ne1000 clones */
|
||||
{"PCM-4823", "PCM-4823", {0x00, 0xc0, 0x6c}}, /* Broken Advantech MoBo */
|
||||
{"REALTEK", "RTL8019", {0x00, 0x00, 0xe8}}, /* no-name with Realtek chip */
|
||||
#if defined(CONFIG_TOSHIBA_RBTX4927) || defined(CONFIG_TOSHIBA_RBTX4938)
|
||||
{"RBHMA4X00-RTL8019", "RBHMA4X00/RTL8019", {0x00, 0x60, 0x0a}}, /* Toshiba built-in */
|
||||
#endif
|
||||
{"LCS-8834", "LCS-8836", {0x04, 0x04, 0x37}}, /* ShinyNet (SET) */
|
||||
{NULL,}
|
||||
};
|
||||
@ -226,6 +233,10 @@ struct net_device * __init ne_probe(int unit)
|
||||
sprintf(dev->name, "eth%d", unit);
|
||||
netdev_boot_setup_check(dev);
|
||||
|
||||
#ifdef CONFIG_TOSHIBA_RBTX4938
|
||||
dev->base_addr = 0x07f20280;
|
||||
dev->irq = RBTX4938_RTL_8019_IRQ;
|
||||
#endif
|
||||
err = do_ne_probe(dev);
|
||||
if (err)
|
||||
goto out;
|
||||
@ -506,6 +517,10 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr)
|
||||
ei_status.name = name;
|
||||
ei_status.tx_start_page = start_page;
|
||||
ei_status.stop_page = stop_page;
|
||||
#if defined(CONFIG_TOSHIBA_RBTX4927) || defined(CONFIG_TOSHIBA_RBTX4938)
|
||||
wordlength = 1;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PLAT_OAKS32R
|
||||
ei_status.word16 = 0;
|
||||
#else
|
||||
|
@ -372,6 +372,7 @@ static int __devinit ne2k_pci_init_one (struct pci_dev *pdev,
|
||||
printk("%2.2X%s", SA_prom[i], i == 5 ? ".\n": ":");
|
||||
dev->dev_addr[i] = SA_prom[i];
|
||||
}
|
||||
memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
|
||||
|
||||
return 0;
|
||||
|
||||
@ -637,6 +638,7 @@ static struct ethtool_ops ne2k_pci_ethtool_ops = {
|
||||
.get_drvinfo = ne2k_pci_get_drvinfo,
|
||||
.get_tx_csum = ethtool_op_get_tx_csum,
|
||||
.get_sg = ethtool_op_get_sg,
|
||||
.get_perm_addr = ethtool_op_get_perm_addr,
|
||||
};
|
||||
|
||||
static void __devexit ne2k_pci_remove_one (struct pci_dev *pdev)
|
||||
|
@ -1632,8 +1632,7 @@ static void ns83820_run_bist(struct net_device *ndev, const char *name, u32 enab
|
||||
timed_out = 1;
|
||||
break;
|
||||
}
|
||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
schedule_timeout(1);
|
||||
schedule_timeout_uninterruptible(1);
|
||||
}
|
||||
|
||||
if (status & fail)
|
||||
|
@ -22,8 +22,8 @@
|
||||
*************************************************************************/
|
||||
|
||||
#define DRV_NAME "pcnet32"
|
||||
#define DRV_VERSION "1.30j"
|
||||
#define DRV_RELDATE "29.04.2005"
|
||||
#define DRV_VERSION "1.31a"
|
||||
#define DRV_RELDATE "12.Sep.2005"
|
||||
#define PFX DRV_NAME ": "
|
||||
|
||||
static const char *version =
|
||||
@ -257,6 +257,9 @@ static int homepna[MAX_UNITS];
|
||||
* v1.30h 24 Jun 2004 Don Fry correctly select auto, speed, duplex in bcr32.
|
||||
* v1.30i 28 Jun 2004 Don Fry change to use module_param.
|
||||
* v1.30j 29 Apr 2005 Don Fry fix skb/map leak with loopback test.
|
||||
* v1.31 02 Sep 2005 Hubert WS Lin <wslin@tw.ibm.c0m> added set_ringparam().
|
||||
* v1.31a 12 Sep 2005 Hubert WS Lin <wslin@tw.ibm.c0m> set min ring size to 4
|
||||
* to allow loopback test to work unchanged.
|
||||
*/
|
||||
|
||||
|
||||
@ -266,17 +269,17 @@ static int homepna[MAX_UNITS];
|
||||
* That translates to 2 (4 == 2^^2) and 4 (16 == 2^^4).
|
||||
*/
|
||||
#ifndef PCNET32_LOG_TX_BUFFERS
|
||||
#define PCNET32_LOG_TX_BUFFERS 4
|
||||
#define PCNET32_LOG_RX_BUFFERS 5
|
||||
#define PCNET32_LOG_TX_BUFFERS 4
|
||||
#define PCNET32_LOG_RX_BUFFERS 5
|
||||
#define PCNET32_LOG_MAX_TX_BUFFERS 9 /* 2^9 == 512 */
|
||||
#define PCNET32_LOG_MAX_RX_BUFFERS 9
|
||||
#endif
|
||||
|
||||
#define TX_RING_SIZE (1 << (PCNET32_LOG_TX_BUFFERS))
|
||||
#define TX_RING_MOD_MASK (TX_RING_SIZE - 1)
|
||||
#define TX_RING_LEN_BITS ((PCNET32_LOG_TX_BUFFERS) << 12)
|
||||
#define TX_MAX_RING_SIZE (1 << (PCNET32_LOG_MAX_TX_BUFFERS))
|
||||
|
||||
#define RX_RING_SIZE (1 << (PCNET32_LOG_RX_BUFFERS))
|
||||
#define RX_RING_MOD_MASK (RX_RING_SIZE - 1)
|
||||
#define RX_RING_LEN_BITS ((PCNET32_LOG_RX_BUFFERS) << 4)
|
||||
#define RX_MAX_RING_SIZE (1 << (PCNET32_LOG_MAX_RX_BUFFERS))
|
||||
|
||||
#define PKT_BUF_SZ 1544
|
||||
|
||||
@ -334,14 +337,14 @@ struct pcnet32_access {
|
||||
};
|
||||
|
||||
/*
|
||||
* The first three fields of pcnet32_private are read by the ethernet device
|
||||
* so we allocate the structure should be allocated by pci_alloc_consistent().
|
||||
* The first field of pcnet32_private is read by the ethernet device
|
||||
* so the structure should be allocated using pci_alloc_consistent().
|
||||
*/
|
||||
struct pcnet32_private {
|
||||
/* The Tx and Rx ring entries must be aligned on 16-byte boundaries in 32bit mode. */
|
||||
struct pcnet32_rx_head rx_ring[RX_RING_SIZE];
|
||||
struct pcnet32_tx_head tx_ring[TX_RING_SIZE];
|
||||
struct pcnet32_init_block init_block;
|
||||
/* The Tx and Rx ring entries must be aligned on 16-byte boundaries in 32bit mode. */
|
||||
struct pcnet32_rx_head *rx_ring;
|
||||
struct pcnet32_tx_head *tx_ring;
|
||||
dma_addr_t dma_addr; /* DMA address of beginning of this
|
||||
object, returned by
|
||||
pci_alloc_consistent */
|
||||
@ -349,13 +352,21 @@ struct pcnet32_private {
|
||||
structure */
|
||||
const char *name;
|
||||
/* The saved address of a sent-in-place packet/buffer, for skfree(). */
|
||||
struct sk_buff *tx_skbuff[TX_RING_SIZE];
|
||||
struct sk_buff *rx_skbuff[RX_RING_SIZE];
|
||||
dma_addr_t tx_dma_addr[TX_RING_SIZE];
|
||||
dma_addr_t rx_dma_addr[RX_RING_SIZE];
|
||||
struct sk_buff **tx_skbuff;
|
||||
struct sk_buff **rx_skbuff;
|
||||
dma_addr_t *tx_dma_addr;
|
||||
dma_addr_t *rx_dma_addr;
|
||||
struct pcnet32_access a;
|
||||
spinlock_t lock; /* Guard lock */
|
||||
unsigned int cur_rx, cur_tx; /* The next free ring entry */
|
||||
unsigned int rx_ring_size; /* current rx ring size */
|
||||
unsigned int tx_ring_size; /* current tx ring size */
|
||||
unsigned int rx_mod_mask; /* rx ring modular mask */
|
||||
unsigned int tx_mod_mask; /* tx ring modular mask */
|
||||
unsigned short rx_len_bits;
|
||||
unsigned short tx_len_bits;
|
||||
dma_addr_t rx_ring_dma_addr;
|
||||
dma_addr_t tx_ring_dma_addr;
|
||||
unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */
|
||||
struct net_device_stats stats;
|
||||
char tx_full;
|
||||
@ -397,6 +408,9 @@ static int pcnet32_get_regs_len(struct net_device *dev);
|
||||
static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs,
|
||||
void *ptr);
|
||||
static void pcnet32_purge_tx_ring(struct net_device *dev);
|
||||
static int pcnet32_alloc_ring(struct net_device *dev);
|
||||
static void pcnet32_free_ring(struct net_device *dev);
|
||||
|
||||
|
||||
enum pci_flags_bit {
|
||||
PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
|
||||
@ -613,10 +627,62 @@ static void pcnet32_get_ringparam(struct net_device *dev, struct ethtool_ringpar
|
||||
{
|
||||
struct pcnet32_private *lp = dev->priv;
|
||||
|
||||
ering->tx_max_pending = TX_RING_SIZE - 1;
|
||||
ering->tx_pending = lp->cur_tx - lp->dirty_tx;
|
||||
ering->rx_max_pending = RX_RING_SIZE - 1;
|
||||
ering->rx_pending = lp->cur_rx & RX_RING_MOD_MASK;
|
||||
ering->tx_max_pending = TX_MAX_RING_SIZE - 1;
|
||||
ering->tx_pending = lp->tx_ring_size - 1;
|
||||
ering->rx_max_pending = RX_MAX_RING_SIZE - 1;
|
||||
ering->rx_pending = lp->rx_ring_size - 1;
|
||||
}
|
||||
|
||||
static int pcnet32_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
|
||||
{
|
||||
struct pcnet32_private *lp = dev->priv;
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
if (ering->rx_mini_pending || ering->rx_jumbo_pending)
|
||||
return -EINVAL;
|
||||
|
||||
if (netif_running(dev))
|
||||
pcnet32_close(dev);
|
||||
|
||||
spin_lock_irqsave(&lp->lock, flags);
|
||||
pcnet32_free_ring(dev);
|
||||
lp->tx_ring_size = min(ering->tx_pending, (unsigned int) TX_MAX_RING_SIZE);
|
||||
lp->rx_ring_size = min(ering->rx_pending, (unsigned int) RX_MAX_RING_SIZE);
|
||||
|
||||
/* set the minimum ring size to 4, to allow the loopback test to work
|
||||
* unchanged.
|
||||
*/
|
||||
for (i = 2; i <= PCNET32_LOG_MAX_TX_BUFFERS; i++) {
|
||||
if (lp->tx_ring_size <= (1 << i))
|
||||
break;
|
||||
}
|
||||
lp->tx_ring_size = (1 << i);
|
||||
lp->tx_mod_mask = lp->tx_ring_size - 1;
|
||||
lp->tx_len_bits = (i << 12);
|
||||
|
||||
for (i = 2; i <= PCNET32_LOG_MAX_RX_BUFFERS; i++) {
|
||||
if (lp->rx_ring_size <= (1 << i))
|
||||
break;
|
||||
}
|
||||
lp->rx_ring_size = (1 << i);
|
||||
lp->rx_mod_mask = lp->rx_ring_size - 1;
|
||||
lp->rx_len_bits = (i << 4);
|
||||
|
||||
if (pcnet32_alloc_ring(dev)) {
|
||||
pcnet32_free_ring(dev);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&lp->lock, flags);
|
||||
|
||||
if (pcnet32_debug & NETIF_MSG_DRV)
|
||||
printk(KERN_INFO PFX "Ring Param Settings: RX: %d, TX: %d\n", lp->rx_ring_size, lp->tx_ring_size);
|
||||
|
||||
if (netif_running(dev))
|
||||
pcnet32_open(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pcnet32_get_strings(struct net_device *dev, u32 stringset, u8 *data)
|
||||
@ -948,6 +1014,7 @@ static struct ethtool_ops pcnet32_ethtool_ops = {
|
||||
.nway_reset = pcnet32_nway_reset,
|
||||
.get_link = pcnet32_get_link,
|
||||
.get_ringparam = pcnet32_get_ringparam,
|
||||
.set_ringparam = pcnet32_set_ringparam,
|
||||
.get_tx_csum = ethtool_op_get_tx_csum,
|
||||
.get_sg = ethtool_op_get_sg,
|
||||
.get_tso = ethtool_op_get_tso,
|
||||
@ -957,6 +1024,7 @@ static struct ethtool_ops pcnet32_ethtool_ops = {
|
||||
.phys_id = pcnet32_phys_id,
|
||||
.get_regs_len = pcnet32_get_regs_len,
|
||||
.get_regs = pcnet32_get_regs,
|
||||
.get_perm_addr = ethtool_op_get_perm_addr,
|
||||
};
|
||||
|
||||
/* only probes for non-PCI devices, the rest are handled by
|
||||
@ -1185,9 +1253,10 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
|
||||
memcpy(dev->dev_addr, promaddr, 6);
|
||||
}
|
||||
}
|
||||
memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
|
||||
|
||||
/* if the ethernet address is not valid, force to 00:00:00:00:00:00 */
|
||||
if (!is_valid_ether_addr(dev->dev_addr))
|
||||
if (!is_valid_ether_addr(dev->perm_addr))
|
||||
memset(dev->dev_addr, 0, sizeof(dev->dev_addr));
|
||||
|
||||
if (pcnet32_debug & NETIF_MSG_PROBE) {
|
||||
@ -1239,6 +1308,12 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
|
||||
dev->priv = lp;
|
||||
lp->name = chipname;
|
||||
lp->shared_irq = shared;
|
||||
lp->tx_ring_size = TX_RING_SIZE; /* default tx ring size */
|
||||
lp->rx_ring_size = RX_RING_SIZE; /* default rx ring size */
|
||||
lp->tx_mod_mask = lp->tx_ring_size - 1;
|
||||
lp->rx_mod_mask = lp->rx_ring_size - 1;
|
||||
lp->tx_len_bits = (PCNET32_LOG_TX_BUFFERS << 12);
|
||||
lp->rx_len_bits = (PCNET32_LOG_RX_BUFFERS << 4);
|
||||
lp->mii_if.full_duplex = fdx;
|
||||
lp->mii_if.phy_id_mask = 0x1f;
|
||||
lp->mii_if.reg_num_mask = 0x1f;
|
||||
@ -1265,21 +1340,23 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
|
||||
}
|
||||
lp->a = *a;
|
||||
|
||||
if (pcnet32_alloc_ring(dev)) {
|
||||
ret = -ENOMEM;
|
||||
goto err_free_ring;
|
||||
}
|
||||
/* detect special T1/E1 WAN card by checking for MAC address */
|
||||
if (dev->dev_addr[0] == 0x00 && dev->dev_addr[1] == 0xe0
|
||||
&& dev->dev_addr[2] == 0x75)
|
||||
lp->options = PCNET32_PORT_FD | PCNET32_PORT_GPSI;
|
||||
|
||||
lp->init_block.mode = le16_to_cpu(0x0003); /* Disable Rx and Tx. */
|
||||
lp->init_block.tlen_rlen = le16_to_cpu(TX_RING_LEN_BITS | RX_RING_LEN_BITS);
|
||||
lp->init_block.tlen_rlen = le16_to_cpu(lp->tx_len_bits | lp->rx_len_bits);
|
||||
for (i = 0; i < 6; i++)
|
||||
lp->init_block.phys_addr[i] = dev->dev_addr[i];
|
||||
lp->init_block.filter[0] = 0x00000000;
|
||||
lp->init_block.filter[1] = 0x00000000;
|
||||
lp->init_block.rx_ring = (u32)le32_to_cpu(lp->dma_addr +
|
||||
offsetof(struct pcnet32_private, rx_ring));
|
||||
lp->init_block.tx_ring = (u32)le32_to_cpu(lp->dma_addr +
|
||||
offsetof(struct pcnet32_private, tx_ring));
|
||||
lp->init_block.rx_ring = (u32)le32_to_cpu(lp->rx_ring_dma_addr);
|
||||
lp->init_block.tx_ring = (u32)le32_to_cpu(lp->tx_ring_dma_addr);
|
||||
|
||||
/* switch pcnet32 to 32bit mode */
|
||||
a->write_bcr(ioaddr, 20, 2);
|
||||
@ -1310,7 +1387,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
|
||||
if (pcnet32_debug & NETIF_MSG_PROBE)
|
||||
printk(", failed to detect IRQ line.\n");
|
||||
ret = -ENODEV;
|
||||
goto err_free_consistent;
|
||||
goto err_free_ring;
|
||||
}
|
||||
if (pcnet32_debug & NETIF_MSG_PROBE)
|
||||
printk(", probed IRQ %d.\n", dev->irq);
|
||||
@ -1341,7 +1418,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
|
||||
|
||||
/* Fill in the generic fields of the device structure. */
|
||||
if (register_netdev(dev))
|
||||
goto err_free_consistent;
|
||||
goto err_free_ring;
|
||||
|
||||
if (pdev) {
|
||||
pci_set_drvdata(pdev, dev);
|
||||
@ -1359,6 +1436,8 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_ring:
|
||||
pcnet32_free_ring(dev);
|
||||
err_free_consistent:
|
||||
pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr);
|
||||
err_free_netdev:
|
||||
@ -1369,6 +1448,86 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
|
||||
}
|
||||
|
||||
|
||||
static int pcnet32_alloc_ring(struct net_device *dev)
|
||||
{
|
||||
struct pcnet32_private *lp = dev->priv;
|
||||
|
||||
if ((lp->tx_ring = pci_alloc_consistent(lp->pci_dev, sizeof(struct pcnet32_tx_head) * lp->tx_ring_size,
|
||||
&lp->tx_ring_dma_addr)) == NULL) {
|
||||
if (pcnet32_debug & NETIF_MSG_DRV)
|
||||
printk(KERN_ERR PFX "Consistent memory allocation failed.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if ((lp->rx_ring = pci_alloc_consistent(lp->pci_dev, sizeof(struct pcnet32_rx_head) * lp->rx_ring_size,
|
||||
&lp->rx_ring_dma_addr)) == NULL) {
|
||||
if (pcnet32_debug & NETIF_MSG_DRV)
|
||||
printk(KERN_ERR PFX "Consistent memory allocation failed.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (!(lp->tx_dma_addr = kmalloc(sizeof(dma_addr_t) * lp->tx_ring_size, GFP_ATOMIC))) {
|
||||
if (pcnet32_debug & NETIF_MSG_DRV)
|
||||
printk(KERN_ERR PFX "Memory allocation failed.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(lp->tx_dma_addr, 0, sizeof(dma_addr_t) * lp->tx_ring_size);
|
||||
|
||||
if (!(lp->rx_dma_addr = kmalloc(sizeof(dma_addr_t) * lp->rx_ring_size, GFP_ATOMIC))) {
|
||||
if (pcnet32_debug & NETIF_MSG_DRV)
|
||||
printk(KERN_ERR PFX "Memory allocation failed.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(lp->rx_dma_addr, 0, sizeof(dma_addr_t) * lp->rx_ring_size);
|
||||
|
||||
if (!(lp->tx_skbuff = kmalloc(sizeof(struct sk_buff *) * lp->tx_ring_size, GFP_ATOMIC))) {
|
||||
if (pcnet32_debug & NETIF_MSG_DRV)
|
||||
printk(KERN_ERR PFX "Memory allocation failed.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(lp->tx_skbuff, 0, sizeof(struct sk_buff *) * lp->tx_ring_size);
|
||||
|
||||
if (!(lp->rx_skbuff = kmalloc(sizeof(struct sk_buff *) * lp->rx_ring_size, GFP_ATOMIC))) {
|
||||
if (pcnet32_debug & NETIF_MSG_DRV)
|
||||
printk(KERN_ERR PFX "Memory allocation failed.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(lp->rx_skbuff, 0, sizeof(struct sk_buff *) * lp->rx_ring_size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void pcnet32_free_ring(struct net_device *dev)
|
||||
{
|
||||
struct pcnet32_private *lp = dev->priv;
|
||||
|
||||
kfree(lp->tx_skbuff);
|
||||
lp->tx_skbuff = NULL;
|
||||
|
||||
kfree(lp->rx_skbuff);
|
||||
lp->rx_skbuff = NULL;
|
||||
|
||||
kfree(lp->tx_dma_addr);
|
||||
lp->tx_dma_addr = NULL;
|
||||
|
||||
kfree(lp->rx_dma_addr);
|
||||
lp->rx_dma_addr = NULL;
|
||||
|
||||
if (lp->tx_ring) {
|
||||
pci_free_consistent(lp->pci_dev, sizeof(struct pcnet32_tx_head) * lp->tx_ring_size,
|
||||
lp->tx_ring, lp->tx_ring_dma_addr);
|
||||
lp->tx_ring = NULL;
|
||||
}
|
||||
|
||||
if (lp->rx_ring) {
|
||||
pci_free_consistent(lp->pci_dev, sizeof(struct pcnet32_rx_head) * lp->rx_ring_size,
|
||||
lp->rx_ring, lp->rx_ring_dma_addr);
|
||||
lp->rx_ring = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
pcnet32_open(struct net_device *dev)
|
||||
{
|
||||
@ -1400,8 +1559,8 @@ pcnet32_open(struct net_device *dev)
|
||||
if (netif_msg_ifup(lp))
|
||||
printk(KERN_DEBUG "%s: pcnet32_open() irq %d tx/rx rings %#x/%#x init %#x.\n",
|
||||
dev->name, dev->irq,
|
||||
(u32) (lp->dma_addr + offsetof(struct pcnet32_private, tx_ring)),
|
||||
(u32) (lp->dma_addr + offsetof(struct pcnet32_private, rx_ring)),
|
||||
(u32) (lp->tx_ring_dma_addr),
|
||||
(u32) (lp->rx_ring_dma_addr),
|
||||
(u32) (lp->dma_addr + offsetof(struct pcnet32_private, init_block)));
|
||||
|
||||
/* set/reset autoselect bit */
|
||||
@ -1521,7 +1680,7 @@ pcnet32_open(struct net_device *dev)
|
||||
|
||||
err_free_ring:
|
||||
/* free any allocated skbuffs */
|
||||
for (i = 0; i < RX_RING_SIZE; i++) {
|
||||
for (i = 0; i < lp->rx_ring_size; i++) {
|
||||
lp->rx_ring[i].status = 0;
|
||||
if (lp->rx_skbuff[i]) {
|
||||
pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i], PKT_BUF_SZ-2,
|
||||
@ -1531,6 +1690,9 @@ pcnet32_open(struct net_device *dev)
|
||||
lp->rx_skbuff[i] = NULL;
|
||||
lp->rx_dma_addr[i] = 0;
|
||||
}
|
||||
|
||||
pcnet32_free_ring(dev);
|
||||
|
||||
/*
|
||||
* Switch back to 16bit mode to avoid problems with dumb
|
||||
* DOS packet driver after a warm reboot
|
||||
@ -1562,7 +1724,7 @@ pcnet32_purge_tx_ring(struct net_device *dev)
|
||||
struct pcnet32_private *lp = dev->priv;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < TX_RING_SIZE; i++) {
|
||||
for (i = 0; i < lp->tx_ring_size; i++) {
|
||||
lp->tx_ring[i].status = 0; /* CPU owns buffer */
|
||||
wmb(); /* Make sure adapter sees owner change */
|
||||
if (lp->tx_skbuff[i]) {
|
||||
@ -1587,7 +1749,7 @@ pcnet32_init_ring(struct net_device *dev)
|
||||
lp->cur_rx = lp->cur_tx = 0;
|
||||
lp->dirty_rx = lp->dirty_tx = 0;
|
||||
|
||||
for (i = 0; i < RX_RING_SIZE; i++) {
|
||||
for (i = 0; i < lp->rx_ring_size; i++) {
|
||||
struct sk_buff *rx_skbuff = lp->rx_skbuff[i];
|
||||
if (rx_skbuff == NULL) {
|
||||
if (!(rx_skbuff = lp->rx_skbuff[i] = dev_alloc_skb (PKT_BUF_SZ))) {
|
||||
@ -1611,20 +1773,18 @@ pcnet32_init_ring(struct net_device *dev)
|
||||
}
|
||||
/* The Tx buffer address is filled in as needed, but we do need to clear
|
||||
* the upper ownership bit. */
|
||||
for (i = 0; i < TX_RING_SIZE; i++) {
|
||||
for (i = 0; i < lp->tx_ring_size; i++) {
|
||||
lp->tx_ring[i].status = 0; /* CPU owns buffer */
|
||||
wmb(); /* Make sure adapter sees owner change */
|
||||
lp->tx_ring[i].base = 0;
|
||||
lp->tx_dma_addr[i] = 0;
|
||||
}
|
||||
|
||||
lp->init_block.tlen_rlen = le16_to_cpu(TX_RING_LEN_BITS | RX_RING_LEN_BITS);
|
||||
lp->init_block.tlen_rlen = le16_to_cpu(lp->tx_len_bits | lp->rx_len_bits);
|
||||
for (i = 0; i < 6; i++)
|
||||
lp->init_block.phys_addr[i] = dev->dev_addr[i];
|
||||
lp->init_block.rx_ring = (u32)le32_to_cpu(lp->dma_addr +
|
||||
offsetof(struct pcnet32_private, rx_ring));
|
||||
lp->init_block.tx_ring = (u32)le32_to_cpu(lp->dma_addr +
|
||||
offsetof(struct pcnet32_private, tx_ring));
|
||||
lp->init_block.rx_ring = (u32)le32_to_cpu(lp->rx_ring_dma_addr);
|
||||
lp->init_block.tx_ring = (u32)le32_to_cpu(lp->tx_ring_dma_addr);
|
||||
wmb(); /* Make sure all changes are visible */
|
||||
return 0;
|
||||
}
|
||||
@ -1682,13 +1842,13 @@ pcnet32_tx_timeout (struct net_device *dev)
|
||||
printk(KERN_DEBUG " Ring data dump: dirty_tx %d cur_tx %d%s cur_rx %d.",
|
||||
lp->dirty_tx, lp->cur_tx, lp->tx_full ? " (full)" : "",
|
||||
lp->cur_rx);
|
||||
for (i = 0 ; i < RX_RING_SIZE; i++)
|
||||
for (i = 0 ; i < lp->rx_ring_size; i++)
|
||||
printk("%s %08x %04x %08x %04x", i & 1 ? "" : "\n ",
|
||||
le32_to_cpu(lp->rx_ring[i].base),
|
||||
(-le16_to_cpu(lp->rx_ring[i].buf_length)) & 0xffff,
|
||||
le32_to_cpu(lp->rx_ring[i].msg_length),
|
||||
le16_to_cpu(lp->rx_ring[i].status));
|
||||
for (i = 0 ; i < TX_RING_SIZE; i++)
|
||||
for (i = 0 ; i < lp->tx_ring_size; i++)
|
||||
printk("%s %08x %04x %08x %04x", i & 1 ? "" : "\n ",
|
||||
le32_to_cpu(lp->tx_ring[i].base),
|
||||
(-le16_to_cpu(lp->tx_ring[i].length)) & 0xffff,
|
||||
@ -1729,7 +1889,7 @@ pcnet32_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
/* Fill in a Tx ring entry */
|
||||
|
||||
/* Mask to ring buffer boundary. */
|
||||
entry = lp->cur_tx & TX_RING_MOD_MASK;
|
||||
entry = lp->cur_tx & lp->tx_mod_mask;
|
||||
|
||||
/* Caution: the write order is important here, set the status
|
||||
* with the "ownership" bits last. */
|
||||
@ -1753,7 +1913,7 @@ pcnet32_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
|
||||
dev->trans_start = jiffies;
|
||||
|
||||
if (lp->tx_ring[(entry+1) & TX_RING_MOD_MASK].base != 0) {
|
||||
if (lp->tx_ring[(entry+1) & lp->tx_mod_mask].base != 0) {
|
||||
lp->tx_full = 1;
|
||||
netif_stop_queue(dev);
|
||||
}
|
||||
@ -1806,7 +1966,7 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
|
||||
int delta;
|
||||
|
||||
while (dirty_tx != lp->cur_tx) {
|
||||
int entry = dirty_tx & TX_RING_MOD_MASK;
|
||||
int entry = dirty_tx & lp->tx_mod_mask;
|
||||
int status = (short)le16_to_cpu(lp->tx_ring[entry].status);
|
||||
|
||||
if (status < 0)
|
||||
@ -1864,18 +2024,18 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
|
||||
dirty_tx++;
|
||||
}
|
||||
|
||||
delta = (lp->cur_tx - dirty_tx) & (TX_RING_MOD_MASK + TX_RING_SIZE);
|
||||
if (delta > TX_RING_SIZE) {
|
||||
delta = (lp->cur_tx - dirty_tx) & (lp->tx_mod_mask + lp->tx_ring_size);
|
||||
if (delta > lp->tx_ring_size) {
|
||||
if (netif_msg_drv(lp))
|
||||
printk(KERN_ERR "%s: out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
|
||||
dev->name, dirty_tx, lp->cur_tx, lp->tx_full);
|
||||
dirty_tx += TX_RING_SIZE;
|
||||
delta -= TX_RING_SIZE;
|
||||
dirty_tx += lp->tx_ring_size;
|
||||
delta -= lp->tx_ring_size;
|
||||
}
|
||||
|
||||
if (lp->tx_full &&
|
||||
netif_queue_stopped(dev) &&
|
||||
delta < TX_RING_SIZE - 2) {
|
||||
delta < lp->tx_ring_size - 2) {
|
||||
/* The ring is no longer full, clear tbusy. */
|
||||
lp->tx_full = 0;
|
||||
netif_wake_queue (dev);
|
||||
@ -1932,8 +2092,8 @@ static int
|
||||
pcnet32_rx(struct net_device *dev)
|
||||
{
|
||||
struct pcnet32_private *lp = dev->priv;
|
||||
int entry = lp->cur_rx & RX_RING_MOD_MASK;
|
||||
int boguscnt = RX_RING_SIZE / 2;
|
||||
int entry = lp->cur_rx & lp->rx_mod_mask;
|
||||
int boguscnt = lp->rx_ring_size / 2;
|
||||
|
||||
/* If we own the next entry, it's a new packet. Send it up. */
|
||||
while ((short)le16_to_cpu(lp->rx_ring[entry].status) >= 0) {
|
||||
@ -1998,12 +2158,12 @@ pcnet32_rx(struct net_device *dev)
|
||||
if (netif_msg_drv(lp))
|
||||
printk(KERN_ERR "%s: Memory squeeze, deferring packet.\n",
|
||||
dev->name);
|
||||
for (i = 0; i < RX_RING_SIZE; i++)
|
||||
for (i = 0; i < lp->rx_ring_size; i++)
|
||||
if ((short)le16_to_cpu(lp->rx_ring[(entry+i)
|
||||
& RX_RING_MOD_MASK].status) < 0)
|
||||
& lp->rx_mod_mask].status) < 0)
|
||||
break;
|
||||
|
||||
if (i > RX_RING_SIZE -2) {
|
||||
if (i > lp->rx_ring_size -2) {
|
||||
lp->stats.rx_dropped++;
|
||||
lp->rx_ring[entry].status |= le16_to_cpu(0x8000);
|
||||
wmb(); /* Make sure adapter sees owner change */
|
||||
@ -2041,7 +2201,7 @@ pcnet32_rx(struct net_device *dev)
|
||||
lp->rx_ring[entry].buf_length = le16_to_cpu(2-PKT_BUF_SZ);
|
||||
wmb(); /* Make sure owner changes after all others are visible */
|
||||
lp->rx_ring[entry].status |= le16_to_cpu(0x8000);
|
||||
entry = (++lp->cur_rx) & RX_RING_MOD_MASK;
|
||||
entry = (++lp->cur_rx) & lp->rx_mod_mask;
|
||||
if (--boguscnt <= 0) break; /* don't stay in loop forever */
|
||||
}
|
||||
|
||||
@ -2084,7 +2244,7 @@ pcnet32_close(struct net_device *dev)
|
||||
spin_lock_irqsave(&lp->lock, flags);
|
||||
|
||||
/* free all allocated skbuffs */
|
||||
for (i = 0; i < RX_RING_SIZE; i++) {
|
||||
for (i = 0; i < lp->rx_ring_size; i++) {
|
||||
lp->rx_ring[i].status = 0;
|
||||
wmb(); /* Make sure adapter sees owner change */
|
||||
if (lp->rx_skbuff[i]) {
|
||||
@ -2096,7 +2256,7 @@ pcnet32_close(struct net_device *dev)
|
||||
lp->rx_dma_addr[i] = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < TX_RING_SIZE; i++) {
|
||||
for (i = 0; i < lp->tx_ring_size; i++) {
|
||||
lp->tx_ring[i].status = 0; /* CPU owns buffer */
|
||||
wmb(); /* Make sure adapter sees owner change */
|
||||
if (lp->tx_skbuff[i]) {
|
||||
@ -2265,6 +2425,7 @@ static void __devexit pcnet32_remove_one(struct pci_dev *pdev)
|
||||
struct pcnet32_private *lp = dev->priv;
|
||||
|
||||
unregister_netdev(dev);
|
||||
pcnet32_free_ring(dev);
|
||||
release_region(dev->base_addr, PCNET32_TOTAL_SIZE);
|
||||
pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr);
|
||||
free_netdev(dev);
|
||||
@ -2340,6 +2501,7 @@ static void __exit pcnet32_cleanup_module(void)
|
||||
struct pcnet32_private *lp = pcnet32_dev->priv;
|
||||
next_dev = lp->next;
|
||||
unregister_netdev(pcnet32_dev);
|
||||
pcnet32_free_ring(pcnet32_dev);
|
||||
release_region(pcnet32_dev->base_addr, PCNET32_TOTAL_SIZE);
|
||||
pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr);
|
||||
free_netdev(pcnet32_dev);
|
||||
|
@ -12,14 +12,6 @@ config PHYLIB
|
||||
devices. This option provides infrastructure for
|
||||
managing PHY devices.
|
||||
|
||||
config PHYCONTROL
|
||||
bool " Support for automatically handling PHY state changes"
|
||||
depends on PHYLIB
|
||||
help
|
||||
Adds code to perform all the work for keeping PHY link
|
||||
state (speed/duplex/etc) up-to-date. Also handles
|
||||
interrupts.
|
||||
|
||||
comment "MII PHY device drivers"
|
||||
depends on PHYLIB
|
||||
|
||||
|
@ -242,10 +242,6 @@ EXPORT_SYMBOL(phy_sanitize_settings);
|
||||
* choose the next best ones from the ones selected, so we don't
|
||||
* care if ethtool tries to give us bad values
|
||||
*
|
||||
* A note about the PHYCONTROL Layer. If you turn off
|
||||
* CONFIG_PHYCONTROL, you will need to read the PHY status
|
||||
* registers after this function completes, and update your
|
||||
* controller manually.
|
||||
*/
|
||||
int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd)
|
||||
{
|
||||
@ -380,7 +376,6 @@ int phy_start_aneg(struct phy_device *phydev)
|
||||
|
||||
err = phydev->drv->config_aneg(phydev);
|
||||
|
||||
#ifdef CONFIG_PHYCONTROL
|
||||
if (err < 0)
|
||||
goto out_unlock;
|
||||
|
||||
@ -395,14 +390,12 @@ int phy_start_aneg(struct phy_device *phydev)
|
||||
}
|
||||
|
||||
out_unlock:
|
||||
#endif
|
||||
spin_unlock(&phydev->lock);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(phy_start_aneg);
|
||||
|
||||
|
||||
#ifdef CONFIG_PHYCONTROL
|
||||
static void phy_change(void *data);
|
||||
static void phy_timer(unsigned long data);
|
||||
|
||||
@ -868,4 +861,3 @@ static void phy_timer(unsigned long data)
|
||||
mod_timer(&phydev->phy_timer, jiffies + PHY_STATE_TIME * HZ);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PHYCONTROL */
|
||||
|
@ -101,7 +101,6 @@ struct phy_device * get_phy_device(struct mii_bus *bus, int addr)
|
||||
return dev;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PHYCONTROL
|
||||
/* phy_prepare_link:
|
||||
*
|
||||
* description: Tells the PHY infrastructure to handle the
|
||||
@ -160,8 +159,6 @@ void phy_disconnect(struct phy_device *phydev)
|
||||
}
|
||||
EXPORT_SYMBOL(phy_disconnect);
|
||||
|
||||
#endif /* CONFIG_PHYCONTROL */
|
||||
|
||||
/* phy_attach:
|
||||
*
|
||||
* description: Called by drivers to attach to a particular PHY
|
||||
|
@ -1027,6 +1027,7 @@ static struct ethtool_ops rtl8169_ethtool_ops = {
|
||||
.get_strings = rtl8169_get_strings,
|
||||
.get_stats_count = rtl8169_get_stats_count,
|
||||
.get_ethtool_stats = rtl8169_get_ethtool_stats,
|
||||
.get_perm_addr = ethtool_op_get_perm_addr,
|
||||
};
|
||||
|
||||
static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg, int bitnum,
|
||||
@ -1511,6 +1512,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
/* Get MAC address. FIXME: read EEPROM */
|
||||
for (i = 0; i < MAC_ADDR_LEN; i++)
|
||||
dev->dev_addr[i] = RTL_R8(MAC0 + i);
|
||||
memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
|
||||
|
||||
dev->open = rtl8169_open;
|
||||
dev->hard_start_xmit = rtl8169_start_xmit;
|
||||
|
574
drivers/net/rionet.c
Normal file
574
drivers/net/rionet.c
Normal file
@ -0,0 +1,574 @@
|
||||
/*
|
||||
* rionet - Ethernet driver over RapidIO messaging services
|
||||
*
|
||||
* Copyright 2005 MontaVista Software, Inc.
|
||||
* Matt Porter <mporter@kernel.crashing.org>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/rio.h>
|
||||
#include <linux/rio_drv.h>
|
||||
#include <linux/rio_ids.h>
|
||||
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/crc32.h>
|
||||
#include <linux/ethtool.h>
|
||||
|
||||
#define DRV_NAME "rionet"
|
||||
#define DRV_VERSION "0.2"
|
||||
#define DRV_AUTHOR "Matt Porter <mporter@kernel.crashing.org>"
|
||||
#define DRV_DESC "Ethernet over RapidIO"
|
||||
|
||||
MODULE_AUTHOR(DRV_AUTHOR);
|
||||
MODULE_DESCRIPTION(DRV_DESC);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
#define RIONET_DEFAULT_MSGLEVEL \
|
||||
(NETIF_MSG_DRV | \
|
||||
NETIF_MSG_LINK | \
|
||||
NETIF_MSG_RX_ERR | \
|
||||
NETIF_MSG_TX_ERR)
|
||||
|
||||
#define RIONET_DOORBELL_JOIN 0x1000
|
||||
#define RIONET_DOORBELL_LEAVE 0x1001
|
||||
|
||||
#define RIONET_MAILBOX 0
|
||||
|
||||
#define RIONET_TX_RING_SIZE CONFIG_RIONET_TX_SIZE
|
||||
#define RIONET_RX_RING_SIZE CONFIG_RIONET_RX_SIZE
|
||||
|
||||
static LIST_HEAD(rionet_peers);
|
||||
|
||||
struct rionet_private {
|
||||
struct rio_mport *mport;
|
||||
struct sk_buff *rx_skb[RIONET_RX_RING_SIZE];
|
||||
struct sk_buff *tx_skb[RIONET_TX_RING_SIZE];
|
||||
struct net_device_stats stats;
|
||||
int rx_slot;
|
||||
int tx_slot;
|
||||
int tx_cnt;
|
||||
int ack_slot;
|
||||
spinlock_t lock;
|
||||
spinlock_t tx_lock;
|
||||
u32 msg_enable;
|
||||
};
|
||||
|
||||
struct rionet_peer {
|
||||
struct list_head node;
|
||||
struct rio_dev *rdev;
|
||||
struct resource *res;
|
||||
};
|
||||
|
||||
static int rionet_check = 0;
|
||||
static int rionet_capable = 1;
|
||||
|
||||
/*
|
||||
* This is a fast lookup table for for translating TX
|
||||
* Ethernet packets into a destination RIO device. It
|
||||
* could be made into a hash table to save memory depending
|
||||
* on system trade-offs.
|
||||
*/
|
||||
static struct rio_dev *rionet_active[RIO_MAX_ROUTE_ENTRIES];
|
||||
|
||||
#define is_rionet_capable(pef, src_ops, dst_ops) \
|
||||
((pef & RIO_PEF_INB_MBOX) && \
|
||||
(pef & RIO_PEF_INB_DOORBELL) && \
|
||||
(src_ops & RIO_SRC_OPS_DOORBELL) && \
|
||||
(dst_ops & RIO_DST_OPS_DOORBELL))
|
||||
#define dev_rionet_capable(dev) \
|
||||
is_rionet_capable(dev->pef, dev->src_ops, dev->dst_ops)
|
||||
|
||||
#define RIONET_MAC_MATCH(x) (*(u32 *)x == 0x00010001)
|
||||
#define RIONET_GET_DESTID(x) (*(u16 *)(x + 4))
|
||||
|
||||
static struct net_device_stats *rionet_stats(struct net_device *ndev)
|
||||
{
|
||||
struct rionet_private *rnet = ndev->priv;
|
||||
return &rnet->stats;
|
||||
}
|
||||
|
||||
static int rionet_rx_clean(struct net_device *ndev)
|
||||
{
|
||||
int i;
|
||||
int error = 0;
|
||||
struct rionet_private *rnet = ndev->priv;
|
||||
void *data;
|
||||
|
||||
i = rnet->rx_slot;
|
||||
|
||||
do {
|
||||
if (!rnet->rx_skb[i])
|
||||
continue;
|
||||
|
||||
if (!(data = rio_get_inb_message(rnet->mport, RIONET_MAILBOX)))
|
||||
break;
|
||||
|
||||
rnet->rx_skb[i]->data = data;
|
||||
skb_put(rnet->rx_skb[i], RIO_MAX_MSG_SIZE);
|
||||
rnet->rx_skb[i]->dev = ndev;
|
||||
rnet->rx_skb[i]->protocol =
|
||||
eth_type_trans(rnet->rx_skb[i], ndev);
|
||||
error = netif_rx(rnet->rx_skb[i]);
|
||||
|
||||
if (error == NET_RX_DROP) {
|
||||
rnet->stats.rx_dropped++;
|
||||
} else if (error == NET_RX_BAD) {
|
||||
if (netif_msg_rx_err(rnet))
|
||||
printk(KERN_WARNING "%s: bad rx packet\n",
|
||||
DRV_NAME);
|
||||
rnet->stats.rx_errors++;
|
||||
} else {
|
||||
rnet->stats.rx_packets++;
|
||||
rnet->stats.rx_bytes += RIO_MAX_MSG_SIZE;
|
||||
}
|
||||
|
||||
} while ((i = (i + 1) % RIONET_RX_RING_SIZE) != rnet->rx_slot);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static void rionet_rx_fill(struct net_device *ndev, int end)
|
||||
{
|
||||
int i;
|
||||
struct rionet_private *rnet = ndev->priv;
|
||||
|
||||
i = rnet->rx_slot;
|
||||
do {
|
||||
rnet->rx_skb[i] = dev_alloc_skb(RIO_MAX_MSG_SIZE);
|
||||
|
||||
if (!rnet->rx_skb[i])
|
||||
break;
|
||||
|
||||
rio_add_inb_buffer(rnet->mport, RIONET_MAILBOX,
|
||||
rnet->rx_skb[i]->data);
|
||||
} while ((i = (i + 1) % RIONET_RX_RING_SIZE) != end);
|
||||
|
||||
rnet->rx_slot = i;
|
||||
}
|
||||
|
||||
static int rionet_queue_tx_msg(struct sk_buff *skb, struct net_device *ndev,
|
||||
struct rio_dev *rdev)
|
||||
{
|
||||
struct rionet_private *rnet = ndev->priv;
|
||||
|
||||
rio_add_outb_message(rnet->mport, rdev, 0, skb->data, skb->len);
|
||||
rnet->tx_skb[rnet->tx_slot] = skb;
|
||||
|
||||
rnet->stats.tx_packets++;
|
||||
rnet->stats.tx_bytes += skb->len;
|
||||
|
||||
if (++rnet->tx_cnt == RIONET_TX_RING_SIZE)
|
||||
netif_stop_queue(ndev);
|
||||
|
||||
++rnet->tx_slot;
|
||||
rnet->tx_slot &= (RIONET_TX_RING_SIZE - 1);
|
||||
|
||||
if (netif_msg_tx_queued(rnet))
|
||||
printk(KERN_INFO "%s: queued skb %8.8x len %8.8x\n", DRV_NAME,
|
||||
(u32) skb, skb->len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
||||
{
|
||||
int i;
|
||||
struct rionet_private *rnet = ndev->priv;
|
||||
struct ethhdr *eth = (struct ethhdr *)skb->data;
|
||||
u16 destid;
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
if (!spin_trylock(&rnet->tx_lock)) {
|
||||
local_irq_restore(flags);
|
||||
return NETDEV_TX_LOCKED;
|
||||
}
|
||||
|
||||
if ((rnet->tx_cnt + 1) > RIONET_TX_RING_SIZE) {
|
||||
netif_stop_queue(ndev);
|
||||
spin_unlock_irqrestore(&rnet->tx_lock, flags);
|
||||
printk(KERN_ERR "%s: BUG! Tx Ring full when queue awake!\n",
|
||||
ndev->name);
|
||||
return NETDEV_TX_BUSY;
|
||||
}
|
||||
|
||||
if (eth->h_dest[0] & 0x01) {
|
||||
for (i = 0; i < RIO_MAX_ROUTE_ENTRIES; i++)
|
||||
if (rionet_active[i])
|
||||
rionet_queue_tx_msg(skb, ndev,
|
||||
rionet_active[i]);
|
||||
} else if (RIONET_MAC_MATCH(eth->h_dest)) {
|
||||
destid = RIONET_GET_DESTID(eth->h_dest);
|
||||
if (rionet_active[destid])
|
||||
rionet_queue_tx_msg(skb, ndev, rionet_active[destid]);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&rnet->tx_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rionet_dbell_event(struct rio_mport *mport, void *dev_id, u16 sid, u16 tid,
|
||||
u16 info)
|
||||
{
|
||||
struct net_device *ndev = dev_id;
|
||||
struct rionet_private *rnet = ndev->priv;
|
||||
struct rionet_peer *peer;
|
||||
|
||||
if (netif_msg_intr(rnet))
|
||||
printk(KERN_INFO "%s: doorbell sid %4.4x tid %4.4x info %4.4x",
|
||||
DRV_NAME, sid, tid, info);
|
||||
if (info == RIONET_DOORBELL_JOIN) {
|
||||
if (!rionet_active[sid]) {
|
||||
list_for_each_entry(peer, &rionet_peers, node) {
|
||||
if (peer->rdev->destid == sid)
|
||||
rionet_active[sid] = peer->rdev;
|
||||
}
|
||||
rio_mport_send_doorbell(mport, sid,
|
||||
RIONET_DOORBELL_JOIN);
|
||||
}
|
||||
} else if (info == RIONET_DOORBELL_LEAVE) {
|
||||
rionet_active[sid] = NULL;
|
||||
} else {
|
||||
if (netif_msg_intr(rnet))
|
||||
printk(KERN_WARNING "%s: unhandled doorbell\n",
|
||||
DRV_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
static void rionet_inb_msg_event(struct rio_mport *mport, void *dev_id, int mbox, int slot)
|
||||
{
|
||||
int n;
|
||||
struct net_device *ndev = dev_id;
|
||||
struct rionet_private *rnet = (struct rionet_private *)ndev->priv;
|
||||
|
||||
if (netif_msg_intr(rnet))
|
||||
printk(KERN_INFO "%s: inbound message event, mbox %d slot %d\n",
|
||||
DRV_NAME, mbox, slot);
|
||||
|
||||
spin_lock(&rnet->lock);
|
||||
if ((n = rionet_rx_clean(ndev)) != rnet->rx_slot)
|
||||
rionet_rx_fill(ndev, n);
|
||||
spin_unlock(&rnet->lock);
|
||||
}
|
||||
|
||||
static void rionet_outb_msg_event(struct rio_mport *mport, void *dev_id, int mbox, int slot)
|
||||
{
|
||||
struct net_device *ndev = dev_id;
|
||||
struct rionet_private *rnet = ndev->priv;
|
||||
|
||||
spin_lock(&rnet->lock);
|
||||
|
||||
if (netif_msg_intr(rnet))
|
||||
printk(KERN_INFO
|
||||
"%s: outbound message event, mbox %d slot %d\n",
|
||||
DRV_NAME, mbox, slot);
|
||||
|
||||
while (rnet->tx_cnt && (rnet->ack_slot != slot)) {
|
||||
/* dma unmap single */
|
||||
dev_kfree_skb_irq(rnet->tx_skb[rnet->ack_slot]);
|
||||
rnet->tx_skb[rnet->ack_slot] = NULL;
|
||||
++rnet->ack_slot;
|
||||
rnet->ack_slot &= (RIONET_TX_RING_SIZE - 1);
|
||||
rnet->tx_cnt--;
|
||||
}
|
||||
|
||||
if (rnet->tx_cnt < RIONET_TX_RING_SIZE)
|
||||
netif_wake_queue(ndev);
|
||||
|
||||
spin_unlock(&rnet->lock);
|
||||
}
|
||||
|
||||
static int rionet_open(struct net_device *ndev)
|
||||
{
|
||||
int i, rc = 0;
|
||||
struct rionet_peer *peer, *tmp;
|
||||
u32 pwdcsr;
|
||||
struct rionet_private *rnet = ndev->priv;
|
||||
|
||||
if (netif_msg_ifup(rnet))
|
||||
printk(KERN_INFO "%s: open\n", DRV_NAME);
|
||||
|
||||
if ((rc = rio_request_inb_dbell(rnet->mport,
|
||||
(void *)ndev,
|
||||
RIONET_DOORBELL_JOIN,
|
||||
RIONET_DOORBELL_LEAVE,
|
||||
rionet_dbell_event)) < 0)
|
||||
goto out;
|
||||
|
||||
if ((rc = rio_request_inb_mbox(rnet->mport,
|
||||
(void *)ndev,
|
||||
RIONET_MAILBOX,
|
||||
RIONET_RX_RING_SIZE,
|
||||
rionet_inb_msg_event)) < 0)
|
||||
goto out;
|
||||
|
||||
if ((rc = rio_request_outb_mbox(rnet->mport,
|
||||
(void *)ndev,
|
||||
RIONET_MAILBOX,
|
||||
RIONET_TX_RING_SIZE,
|
||||
rionet_outb_msg_event)) < 0)
|
||||
goto out;
|
||||
|
||||
/* Initialize inbound message ring */
|
||||
for (i = 0; i < RIONET_RX_RING_SIZE; i++)
|
||||
rnet->rx_skb[i] = NULL;
|
||||
rnet->rx_slot = 0;
|
||||
rionet_rx_fill(ndev, 0);
|
||||
|
||||
rnet->tx_slot = 0;
|
||||
rnet->tx_cnt = 0;
|
||||
rnet->ack_slot = 0;
|
||||
|
||||
netif_carrier_on(ndev);
|
||||
netif_start_queue(ndev);
|
||||
|
||||
list_for_each_entry_safe(peer, tmp, &rionet_peers, node) {
|
||||
if (!(peer->res = rio_request_outb_dbell(peer->rdev,
|
||||
RIONET_DOORBELL_JOIN,
|
||||
RIONET_DOORBELL_LEAVE)))
|
||||
{
|
||||
printk(KERN_ERR "%s: error requesting doorbells\n",
|
||||
DRV_NAME);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* If device has initialized inbound doorbells,
|
||||
* send a join message
|
||||
*/
|
||||
rio_read_config_32(peer->rdev, RIO_WRITE_PORT_CSR, &pwdcsr);
|
||||
if (pwdcsr & RIO_DOORBELL_AVAIL)
|
||||
rio_send_doorbell(peer->rdev, RIONET_DOORBELL_JOIN);
|
||||
}
|
||||
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int rionet_close(struct net_device *ndev)
|
||||
{
|
||||
struct rionet_private *rnet = (struct rionet_private *)ndev->priv;
|
||||
struct rionet_peer *peer, *tmp;
|
||||
int i;
|
||||
|
||||
if (netif_msg_ifup(rnet))
|
||||
printk(KERN_INFO "%s: close\n", DRV_NAME);
|
||||
|
||||
netif_stop_queue(ndev);
|
||||
netif_carrier_off(ndev);
|
||||
|
||||
for (i = 0; i < RIONET_RX_RING_SIZE; i++)
|
||||
if (rnet->rx_skb[i])
|
||||
kfree_skb(rnet->rx_skb[i]);
|
||||
|
||||
list_for_each_entry_safe(peer, tmp, &rionet_peers, node) {
|
||||
if (rionet_active[peer->rdev->destid]) {
|
||||
rio_send_doorbell(peer->rdev, RIONET_DOORBELL_LEAVE);
|
||||
rionet_active[peer->rdev->destid] = NULL;
|
||||
}
|
||||
rio_release_outb_dbell(peer->rdev, peer->res);
|
||||
}
|
||||
|
||||
rio_release_inb_dbell(rnet->mport, RIONET_DOORBELL_JOIN,
|
||||
RIONET_DOORBELL_LEAVE);
|
||||
rio_release_inb_mbox(rnet->mport, RIONET_MAILBOX);
|
||||
rio_release_outb_mbox(rnet->mport, RIONET_MAILBOX);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rionet_remove(struct rio_dev *rdev)
|
||||
{
|
||||
struct net_device *ndev = NULL;
|
||||
struct rionet_peer *peer, *tmp;
|
||||
|
||||
unregister_netdev(ndev);
|
||||
kfree(ndev);
|
||||
|
||||
list_for_each_entry_safe(peer, tmp, &rionet_peers, node) {
|
||||
list_del(&peer->node);
|
||||
kfree(peer);
|
||||
}
|
||||
}
|
||||
|
||||
static void rionet_get_drvinfo(struct net_device *ndev,
|
||||
struct ethtool_drvinfo *info)
|
||||
{
|
||||
struct rionet_private *rnet = ndev->priv;
|
||||
|
||||
strcpy(info->driver, DRV_NAME);
|
||||
strcpy(info->version, DRV_VERSION);
|
||||
strcpy(info->fw_version, "n/a");
|
||||
strcpy(info->bus_info, rnet->mport->name);
|
||||
}
|
||||
|
||||
static u32 rionet_get_msglevel(struct net_device *ndev)
|
||||
{
|
||||
struct rionet_private *rnet = ndev->priv;
|
||||
|
||||
return rnet->msg_enable;
|
||||
}
|
||||
|
||||
static void rionet_set_msglevel(struct net_device *ndev, u32 value)
|
||||
{
|
||||
struct rionet_private *rnet = ndev->priv;
|
||||
|
||||
rnet->msg_enable = value;
|
||||
}
|
||||
|
||||
static struct ethtool_ops rionet_ethtool_ops = {
|
||||
.get_drvinfo = rionet_get_drvinfo,
|
||||
.get_msglevel = rionet_get_msglevel,
|
||||
.set_msglevel = rionet_set_msglevel,
|
||||
.get_link = ethtool_op_get_link,
|
||||
};
|
||||
|
||||
static int rionet_setup_netdev(struct rio_mport *mport)
|
||||
{
|
||||
int rc = 0;
|
||||
struct net_device *ndev = NULL;
|
||||
struct rionet_private *rnet;
|
||||
u16 device_id;
|
||||
|
||||
/* Allocate our net_device structure */
|
||||
ndev = alloc_etherdev(sizeof(struct rionet_private));
|
||||
if (ndev == NULL) {
|
||||
printk(KERN_INFO "%s: could not allocate ethernet device.\n",
|
||||
DRV_NAME);
|
||||
rc = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Set up private area */
|
||||
rnet = (struct rionet_private *)ndev->priv;
|
||||
rnet->mport = mport;
|
||||
|
||||
/* Set the default MAC address */
|
||||
device_id = rio_local_get_device_id(mport);
|
||||
ndev->dev_addr[0] = 0x00;
|
||||
ndev->dev_addr[1] = 0x01;
|
||||
ndev->dev_addr[2] = 0x00;
|
||||
ndev->dev_addr[3] = 0x01;
|
||||
ndev->dev_addr[4] = device_id >> 8;
|
||||
ndev->dev_addr[5] = device_id & 0xff;
|
||||
|
||||
/* Fill in the driver function table */
|
||||
ndev->open = &rionet_open;
|
||||
ndev->hard_start_xmit = &rionet_start_xmit;
|
||||
ndev->stop = &rionet_close;
|
||||
ndev->get_stats = &rionet_stats;
|
||||
ndev->mtu = RIO_MAX_MSG_SIZE - 14;
|
||||
ndev->features = NETIF_F_LLTX;
|
||||
SET_ETHTOOL_OPS(ndev, &rionet_ethtool_ops);
|
||||
|
||||
SET_MODULE_OWNER(ndev);
|
||||
|
||||
spin_lock_init(&rnet->lock);
|
||||
spin_lock_init(&rnet->tx_lock);
|
||||
|
||||
rnet->msg_enable = RIONET_DEFAULT_MSGLEVEL;
|
||||
|
||||
rc = register_netdev(ndev);
|
||||
if (rc != 0)
|
||||
goto out;
|
||||
|
||||
printk("%s: %s %s Version %s, MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||
ndev->name,
|
||||
DRV_NAME,
|
||||
DRV_DESC,
|
||||
DRV_VERSION,
|
||||
ndev->dev_addr[0], ndev->dev_addr[1], ndev->dev_addr[2],
|
||||
ndev->dev_addr[3], ndev->dev_addr[4], ndev->dev_addr[5]);
|
||||
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX Make multi-net safe
|
||||
*/
|
||||
static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id)
|
||||
{
|
||||
int rc = -ENODEV;
|
||||
u32 lpef, lsrc_ops, ldst_ops;
|
||||
struct rionet_peer *peer;
|
||||
|
||||
/* If local device is not rionet capable, give up quickly */
|
||||
if (!rionet_capable)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* First time through, make sure local device is rionet
|
||||
* capable, setup netdev, and set flags so this is skipped
|
||||
* on later probes
|
||||
*/
|
||||
if (!rionet_check) {
|
||||
rio_local_read_config_32(rdev->net->hport, RIO_PEF_CAR, &lpef);
|
||||
rio_local_read_config_32(rdev->net->hport, RIO_SRC_OPS_CAR,
|
||||
&lsrc_ops);
|
||||
rio_local_read_config_32(rdev->net->hport, RIO_DST_OPS_CAR,
|
||||
&ldst_ops);
|
||||
if (!is_rionet_capable(lpef, lsrc_ops, ldst_ops)) {
|
||||
printk(KERN_ERR
|
||||
"%s: local device is not network capable\n",
|
||||
DRV_NAME);
|
||||
rionet_check = 1;
|
||||
rionet_capable = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = rionet_setup_netdev(rdev->net->hport);
|
||||
rionet_check = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the remote device has mailbox/doorbell capabilities,
|
||||
* add it to the peer list.
|
||||
*/
|
||||
if (dev_rionet_capable(rdev)) {
|
||||
if (!(peer = kmalloc(sizeof(struct rionet_peer), GFP_KERNEL))) {
|
||||
rc = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
peer->rdev = rdev;
|
||||
list_add_tail(&peer->node, &rionet_peers);
|
||||
}
|
||||
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static struct rio_device_id rionet_id_table[] = {
|
||||
{RIO_DEVICE(RIO_ANY_ID, RIO_ANY_ID)}
|
||||
};
|
||||
|
||||
static struct rio_driver rionet_driver = {
|
||||
.name = "rionet",
|
||||
.id_table = rionet_id_table,
|
||||
.probe = rionet_probe,
|
||||
.remove = rionet_remove,
|
||||
};
|
||||
|
||||
static int __init rionet_init(void)
|
||||
{
|
||||
return rio_register_driver(&rionet_driver);
|
||||
}
|
||||
|
||||
static void __exit rionet_exit(void)
|
||||
{
|
||||
rio_unregister_driver(&rionet_driver);
|
||||
}
|
||||
|
||||
module_init(rionet_init);
|
||||
module_exit(rionet_exit);
|
@ -814,6 +814,17 @@ typedef struct _XENA_dev_config {
|
||||
u64 rxgxs_ber_0; /* CHANGED */
|
||||
u64 rxgxs_ber_1; /* CHANGED */
|
||||
|
||||
u64 spi_control;
|
||||
#define SPI_CONTROL_KEY(key) vBIT(key,0,4)
|
||||
#define SPI_CONTROL_BYTECNT(cnt) vBIT(cnt,29,3)
|
||||
#define SPI_CONTROL_CMD(cmd) vBIT(cmd,32,8)
|
||||
#define SPI_CONTROL_ADDR(addr) vBIT(addr,40,24)
|
||||
#define SPI_CONTROL_SEL1 BIT(4)
|
||||
#define SPI_CONTROL_REQ BIT(7)
|
||||
#define SPI_CONTROL_NACK BIT(5)
|
||||
#define SPI_CONTROL_DONE BIT(6)
|
||||
u64 spi_data;
|
||||
#define SPI_DATA_WRITE(data,len) vBIT(data,0,len)
|
||||
} XENA_dev_config_t;
|
||||
|
||||
#define XENA_REG_SPACE sizeof(XENA_dev_config_t)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -652,6 +652,30 @@ typedef struct {
|
||||
#define SMALL_BLK_CNT 30
|
||||
#define LARGE_BLK_CNT 100
|
||||
|
||||
/*
|
||||
* Structure to keep track of the MSI-X vectors and the corresponding
|
||||
* argument registered against each vector
|
||||
*/
|
||||
#define MAX_REQUESTED_MSI_X 17
|
||||
struct s2io_msix_entry
|
||||
{
|
||||
u16 vector;
|
||||
u16 entry;
|
||||
void *arg;
|
||||
|
||||
u8 type;
|
||||
#define MSIX_FIFO_TYPE 1
|
||||
#define MSIX_RING_TYPE 2
|
||||
|
||||
u8 in_use;
|
||||
#define MSIX_REGISTERED_SUCCESS 0xAA
|
||||
};
|
||||
|
||||
struct msix_info_st {
|
||||
u64 addr;
|
||||
u64 data;
|
||||
};
|
||||
|
||||
/* Structure representing one instance of the NIC */
|
||||
struct s2io_nic {
|
||||
#ifdef CONFIG_S2IO_NAPI
|
||||
@ -719,13 +743,8 @@ struct s2io_nic {
|
||||
* a schedule task that will set the correct Link state once the
|
||||
* NIC's PHY has stabilized after a state change.
|
||||
*/
|
||||
#ifdef INIT_TQUEUE
|
||||
struct tq_struct rst_timer_task;
|
||||
struct tq_struct set_link_task;
|
||||
#else
|
||||
struct work_struct rst_timer_task;
|
||||
struct work_struct set_link_task;
|
||||
#endif
|
||||
|
||||
/* Flag that can be used to turn on or turn off the Rx checksum
|
||||
* offload feature.
|
||||
@ -748,10 +767,23 @@ struct s2io_nic {
|
||||
atomic_t card_state;
|
||||
volatile unsigned long link_state;
|
||||
struct vlan_group *vlgrp;
|
||||
#define MSIX_FLG 0xA5
|
||||
struct msix_entry *entries;
|
||||
struct s2io_msix_entry *s2io_entries;
|
||||
char desc1[35];
|
||||
char desc2[35];
|
||||
|
||||
struct msix_info_st msix_info[0x3f];
|
||||
|
||||
#define XFRAME_I_DEVICE 1
|
||||
#define XFRAME_II_DEVICE 2
|
||||
u8 device_type;
|
||||
|
||||
#define INTA 0
|
||||
#define MSI 1
|
||||
#define MSI_X 2
|
||||
u8 intr_type;
|
||||
|
||||
spinlock_t rx_lock;
|
||||
atomic_t isr_cnt;
|
||||
};
|
||||
@ -886,6 +918,13 @@ static int s2io_poll(struct net_device *dev, int *budget);
|
||||
static void s2io_init_pci(nic_t * sp);
|
||||
int s2io_set_mac_addr(struct net_device *dev, u8 * addr);
|
||||
static void s2io_alarm_handle(unsigned long data);
|
||||
static int s2io_enable_msi(nic_t *nic);
|
||||
static irqreturn_t s2io_msi_handle(int irq, void *dev_id, struct pt_regs *regs);
|
||||
static irqreturn_t
|
||||
s2io_msix_ring_handle(int irq, void *dev_id, struct pt_regs *regs);
|
||||
static irqreturn_t
|
||||
s2io_msix_fifo_handle(int irq, void *dev_id, struct pt_regs *regs);
|
||||
int s2io_enable_msi_x(nic_t *nic);
|
||||
static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs);
|
||||
static int verify_xena_quiescence(nic_t *sp, u64 val64, int flag);
|
||||
static struct ethtool_ops netdev_ethtool_ops;
|
||||
@ -894,4 +933,5 @@ int s2io_set_swapper(nic_t * sp);
|
||||
static void s2io_card_down(nic_t *nic);
|
||||
static int s2io_card_up(nic_t *nic);
|
||||
int get_xena_rev_id(struct pci_dev *pdev);
|
||||
void restore_xmsi_data(nic_t *nic);
|
||||
#endif /* _S2IO_H */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -32,8 +32,6 @@
|
||||
|
||||
#include "sgiseeq.h"
|
||||
|
||||
static char *version = "sgiseeq.c: David S. Miller (dm@engr.sgi.com)\n";
|
||||
|
||||
static char *sgiseeqstr = "SGI Seeq8003";
|
||||
|
||||
/*
|
||||
@ -113,9 +111,9 @@ static struct net_device *root_sgiseeq_dev;
|
||||
|
||||
static inline void hpc3_eth_reset(struct hpc3_ethregs *hregs)
|
||||
{
|
||||
hregs->rx_reset = HPC3_ERXRST_CRESET | HPC3_ERXRST_CLRIRQ;
|
||||
hregs->reset = HPC3_ERST_CRESET | HPC3_ERST_CLRIRQ;
|
||||
udelay(20);
|
||||
hregs->rx_reset = 0;
|
||||
hregs->reset = 0;
|
||||
}
|
||||
|
||||
static inline void reset_hpc3_and_seeq(struct hpc3_ethregs *hregs,
|
||||
@ -252,7 +250,6 @@ void sgiseeq_dump_rings(void)
|
||||
|
||||
#define TSTAT_INIT_SEEQ (SEEQ_TCMD_IPT|SEEQ_TCMD_I16|SEEQ_TCMD_IC|SEEQ_TCMD_IUF)
|
||||
#define TSTAT_INIT_EDLC ((TSTAT_INIT_SEEQ) | SEEQ_TCMD_RB2)
|
||||
#define RDMACFG_INIT (HPC3_ERXDCFG_FRXDC | HPC3_ERXDCFG_FEOP | HPC3_ERXDCFG_FIRQ)
|
||||
|
||||
static int init_seeq(struct net_device *dev, struct sgiseeq_private *sp,
|
||||
struct sgiseeq_regs *sregs)
|
||||
@ -274,8 +271,6 @@ static int init_seeq(struct net_device *dev, struct sgiseeq_private *sp,
|
||||
sregs->tstat = TSTAT_INIT_SEEQ;
|
||||
}
|
||||
|
||||
hregs->rx_dconfig |= RDMACFG_INIT;
|
||||
|
||||
hregs->rx_ndptr = CPHYSADDR(sp->rx_desc);
|
||||
hregs->tx_ndptr = CPHYSADDR(sp->tx_desc);
|
||||
|
||||
@ -446,7 +441,7 @@ static irqreturn_t sgiseeq_interrupt(int irq, void *dev_id, struct pt_regs *regs
|
||||
spin_lock(&sp->tx_lock);
|
||||
|
||||
/* Ack the IRQ and set software state. */
|
||||
hregs->rx_reset = HPC3_ERXRST_CLRIRQ;
|
||||
hregs->reset = HPC3_ERST_CLRIRQ;
|
||||
|
||||
/* Always check for received packets. */
|
||||
sgiseeq_rx(dev, sp, hregs, sregs);
|
||||
@ -493,11 +488,13 @@ static int sgiseeq_close(struct net_device *dev)
|
||||
{
|
||||
struct sgiseeq_private *sp = netdev_priv(dev);
|
||||
struct sgiseeq_regs *sregs = sp->sregs;
|
||||
unsigned int irq = dev->irq;
|
||||
|
||||
netif_stop_queue(dev);
|
||||
|
||||
/* Shutdown the Seeq. */
|
||||
reset_hpc3_and_seeq(sp->hregs, sregs);
|
||||
free_irq(irq, dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -644,7 +641,7 @@ static inline void setup_rx_ring(struct sgiseeq_rx_desc *buf, int nbufs)
|
||||
|
||||
#define ALIGNED(x) ((((unsigned long)(x)) + 0xf) & ~(0xf))
|
||||
|
||||
static int sgiseeq_init(struct hpc3_regs* regs, int irq)
|
||||
static int sgiseeq_init(struct hpc3_regs* hpcregs, int irq)
|
||||
{
|
||||
struct sgiseeq_init_block *sr;
|
||||
struct sgiseeq_private *sp;
|
||||
@ -680,8 +677,8 @@ static int sgiseeq_init(struct hpc3_regs* regs, int irq)
|
||||
gpriv = sp;
|
||||
gdev = dev;
|
||||
#endif
|
||||
sp->sregs = (struct sgiseeq_regs *) &hpc3c0->eth_ext[0];
|
||||
sp->hregs = &hpc3c0->ethregs;
|
||||
sp->sregs = (struct sgiseeq_regs *) &hpcregs->eth_ext[0];
|
||||
sp->hregs = &hpcregs->ethregs;
|
||||
sp->name = sgiseeqstr;
|
||||
sp->mode = SEEQ_RCMD_RBCAST;
|
||||
|
||||
@ -698,6 +695,11 @@ static int sgiseeq_init(struct hpc3_regs* regs, int irq)
|
||||
setup_rx_ring(sp->rx_desc, SEEQ_RX_BUFFERS);
|
||||
setup_tx_ring(sp->tx_desc, SEEQ_TX_BUFFERS);
|
||||
|
||||
/* Setup PIO and DMA transfer timing */
|
||||
sp->hregs->pconfig = 0x161;
|
||||
sp->hregs->dconfig = HPC3_EDCFG_FIRQ | HPC3_EDCFG_FEOP |
|
||||
HPC3_EDCFG_FRXDC | HPC3_EDCFG_PTO | 0x026;
|
||||
|
||||
/* Reset the chip. */
|
||||
hpc3_eth_reset(sp->hregs);
|
||||
|
||||
@ -724,7 +726,7 @@ static int sgiseeq_init(struct hpc3_regs* regs, int irq)
|
||||
goto err_out_free_page;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "%s: SGI Seeq8003 ", dev->name);
|
||||
printk(KERN_INFO "%s: %s ", dev->name, sgiseeqstr);
|
||||
for (i = 0; i < 6; i++)
|
||||
printk("%2.2x%c", dev->dev_addr[i], i == 5 ? '\n' : ':');
|
||||
|
||||
@ -734,7 +736,7 @@ static int sgiseeq_init(struct hpc3_regs* regs, int irq)
|
||||
return 0;
|
||||
|
||||
err_out_free_page:
|
||||
free_page((unsigned long) sp);
|
||||
free_page((unsigned long) sp->srings);
|
||||
err_out_free_dev:
|
||||
kfree(dev);
|
||||
|
||||
@ -744,8 +746,6 @@ static int sgiseeq_init(struct hpc3_regs* regs, int irq)
|
||||
|
||||
static int __init sgiseeq_probe(void)
|
||||
{
|
||||
printk(version);
|
||||
|
||||
/* On board adapter on 1st HPC is always present */
|
||||
return sgiseeq_init(hpc3c0, SGI_ENET_IRQ);
|
||||
}
|
||||
@ -754,15 +754,12 @@ static void __exit sgiseeq_exit(void)
|
||||
{
|
||||
struct net_device *next, *dev;
|
||||
struct sgiseeq_private *sp;
|
||||
int irq;
|
||||
|
||||
for (dev = root_sgiseeq_dev; dev; dev = next) {
|
||||
sp = (struct sgiseeq_private *) netdev_priv(dev);
|
||||
next = sp->next_module;
|
||||
irq = dev->irq;
|
||||
unregister_netdev(dev);
|
||||
free_irq(irq, dev);
|
||||
free_page((unsigned long) sp);
|
||||
free_page((unsigned long) sp->srings);
|
||||
free_netdev(dev);
|
||||
}
|
||||
}
|
||||
@ -770,4 +767,6 @@ static void __exit sgiseeq_exit(void)
|
||||
module_init(sgiseeq_probe);
|
||||
module_exit(sgiseeq_exit);
|
||||
|
||||
MODULE_DESCRIPTION("SGI Seeq 8003 driver");
|
||||
MODULE_AUTHOR("Linux/MIPS Mailing List <linux-mips@linux-mips.org>");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -730,6 +730,7 @@ static struct ethtool_ops skge_ethtool_ops = {
|
||||
.phys_id = skge_phys_id,
|
||||
.get_stats_count = skge_get_stats_count,
|
||||
.get_ethtool_stats = skge_get_ethtool_stats,
|
||||
.get_perm_addr = ethtool_op_get_perm_addr,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -3096,6 +3097,7 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port,
|
||||
|
||||
/* read the mac address */
|
||||
memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port*8, ETH_ALEN);
|
||||
memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
|
||||
|
||||
/* device is off until link detection */
|
||||
netif_carrier_off(dev);
|
||||
|
@ -518,6 +518,7 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
|
||||
#else
|
||||
int bar = 1;
|
||||
#endif
|
||||
int phy, phy_idx = 0;
|
||||
|
||||
|
||||
/* when built into the kernel, we only print version if device is found */
|
||||
@ -549,6 +550,7 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
|
||||
for (i = 0; i < 3; i++)
|
||||
((u16 *)dev->dev_addr)[i] =
|
||||
le16_to_cpu(eeprom_read(ioaddr, i + EEPROM_SA_OFFSET));
|
||||
memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
|
||||
|
||||
dev->base_addr = (unsigned long)ioaddr;
|
||||
dev->irq = irq;
|
||||
@ -605,32 +607,30 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
|
||||
printk("%2.2x:", dev->dev_addr[i]);
|
||||
printk("%2.2x, IRQ %d.\n", dev->dev_addr[i], irq);
|
||||
|
||||
if (1) {
|
||||
int phy, phy_idx = 0;
|
||||
np->phys[0] = 1; /* Default setting */
|
||||
np->mii_preamble_required++;
|
||||
for (phy = 1; phy < 32 && phy_idx < MII_CNT; phy++) {
|
||||
int mii_status = mdio_read(dev, phy, MII_BMSR);
|
||||
if (mii_status != 0xffff && mii_status != 0x0000) {
|
||||
np->phys[phy_idx++] = phy;
|
||||
np->mii_if.advertising = mdio_read(dev, phy, MII_ADVERTISE);
|
||||
if ((mii_status & 0x0040) == 0)
|
||||
np->mii_preamble_required++;
|
||||
printk(KERN_INFO "%s: MII PHY found at address %d, status "
|
||||
"0x%4.4x advertising %4.4x.\n",
|
||||
dev->name, phy, mii_status, np->mii_if.advertising);
|
||||
}
|
||||
np->phys[0] = 1; /* Default setting */
|
||||
np->mii_preamble_required++;
|
||||
for (phy = 1; phy <= 32 && phy_idx < MII_CNT; phy++) {
|
||||
int mii_status = mdio_read(dev, phy, MII_BMSR);
|
||||
int phyx = phy & 0x1f;
|
||||
if (mii_status != 0xffff && mii_status != 0x0000) {
|
||||
np->phys[phy_idx++] = phyx;
|
||||
np->mii_if.advertising = mdio_read(dev, phyx, MII_ADVERTISE);
|
||||
if ((mii_status & 0x0040) == 0)
|
||||
np->mii_preamble_required++;
|
||||
printk(KERN_INFO "%s: MII PHY found at address %d, status "
|
||||
"0x%4.4x advertising %4.4x.\n",
|
||||
dev->name, phyx, mii_status, np->mii_if.advertising);
|
||||
}
|
||||
np->mii_preamble_required--;
|
||||
|
||||
if (phy_idx == 0) {
|
||||
printk(KERN_INFO "%s: No MII transceiver found, aborting. ASIC status %x\n",
|
||||
dev->name, ioread32(ioaddr + ASICCtrl));
|
||||
goto err_out_unregister;
|
||||
}
|
||||
|
||||
np->mii_if.phy_id = np->phys[0];
|
||||
}
|
||||
np->mii_preamble_required--;
|
||||
|
||||
if (phy_idx == 0) {
|
||||
printk(KERN_INFO "%s: No MII transceiver found, aborting. ASIC status %x\n",
|
||||
dev->name, ioread32(ioaddr + ASICCtrl));
|
||||
goto err_out_unregister;
|
||||
}
|
||||
|
||||
np->mii_if.phy_id = np->phys[0];
|
||||
|
||||
/* Parse override configuration */
|
||||
np->an_enable = 1;
|
||||
@ -692,7 +692,7 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
|
||||
/* Reset the chip to erase previous misconfiguration. */
|
||||
if (netif_msg_hw(np))
|
||||
printk("ASIC Control is %x.\n", ioread32(ioaddr + ASICCtrl));
|
||||
iowrite16(0x007f, ioaddr + ASICCtrl + 2);
|
||||
iowrite16(0x00ff, ioaddr + ASICCtrl + 2);
|
||||
if (netif_msg_hw(np))
|
||||
printk("ASIC Control is now %x.\n", ioread32(ioaddr + ASICCtrl));
|
||||
|
||||
@ -1619,6 +1619,7 @@ static struct ethtool_ops ethtool_ops = {
|
||||
.get_link = get_link,
|
||||
.get_msglevel = get_msglevel,
|
||||
.set_msglevel = set_msglevel,
|
||||
.get_perm_addr = ethtool_op_get_perm_addr,
|
||||
};
|
||||
|
||||
static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
|
||||
|
@ -318,7 +318,7 @@ static void ibmtr_cleanup_card(struct net_device *dev)
|
||||
if (dev->base_addr) {
|
||||
outb(0,dev->base_addr+ADAPTRESET);
|
||||
|
||||
schedule_timeout(TR_RST_TIME); /* wait 50ms */
|
||||
schedule_timeout_uninterruptible(TR_RST_TIME); /* wait 50ms */
|
||||
|
||||
outb(0,dev->base_addr+ADAPTRESETREL);
|
||||
}
|
||||
@ -854,8 +854,7 @@ static int tok_init_card(struct net_device *dev)
|
||||
writeb(~INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_RESET + ISRP_EVEN);
|
||||
outb(0, PIOaddr + ADAPTRESET);
|
||||
|
||||
current->state=TASK_UNINTERRUPTIBLE;
|
||||
schedule_timeout(TR_RST_TIME); /* wait 50ms */
|
||||
schedule_timeout_uninterruptible(TR_RST_TIME); /* wait 50ms */
|
||||
|
||||
outb(0, PIOaddr + ADAPTRESETREL);
|
||||
#ifdef ENABLE_PAGING
|
||||
@ -903,8 +902,8 @@ static int tok_open(struct net_device *dev)
|
||||
DPRINTK("Adapter is up and running\n");
|
||||
return 0;
|
||||
}
|
||||
current->state=TASK_INTERRUPTIBLE;
|
||||
i=schedule_timeout(TR_RETRY_INTERVAL); /* wait 30 seconds */
|
||||
i=schedule_timeout_interruptible(TR_RETRY_INTERVAL);
|
||||
/* wait 30 seconds */
|
||||
if(i!=0) break; /*prob. a signal, like the i>24*HZ case above */
|
||||
}
|
||||
outb(0, dev->base_addr + ADAPTRESET);/* kill pending interrupts*/
|
||||
|
@ -1101,7 +1101,7 @@ static int olympic_close(struct net_device *dev)
|
||||
|
||||
while(olympic_priv->srb_queued) {
|
||||
|
||||
t = schedule_timeout(60*HZ);
|
||||
t = schedule_timeout_interruptible(60*HZ);
|
||||
|
||||
if(signal_pending(current)) {
|
||||
printk(KERN_WARNING "%s: SRB timed out.\n",dev->name);
|
||||
|
@ -1243,8 +1243,7 @@ void tms380tr_wait(unsigned long time)
|
||||
|
||||
tmp = jiffies + time/(1000000/HZ);
|
||||
do {
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
tmp = schedule_timeout(tmp);
|
||||
tmp = schedule_timeout_interruptible(tmp);
|
||||
} while(time_after(tmp, jiffies));
|
||||
#else
|
||||
udelay(time);
|
||||
|
@ -1787,10 +1787,15 @@ static void __init de21041_get_srom_info (struct de_private *de)
|
||||
/* DEC now has a specification but early board makers
|
||||
just put the address in the first EEPROM locations. */
|
||||
/* This does memcmp(eedata, eedata+16, 8) */
|
||||
|
||||
#ifndef CONFIG_MIPS_COBALT
|
||||
|
||||
for (i = 0; i < 8; i ++)
|
||||
if (ee_data[i] != ee_data[16+i])
|
||||
sa_offset = 20;
|
||||
|
||||
#endif
|
||||
|
||||
/* store MAC address */
|
||||
for (i = 0; i < 6; i ++)
|
||||
de->dev->dev_addr[i] = ee_data[i + sa_offset];
|
||||
|
@ -419,10 +419,9 @@ typhoon_reset(void __iomem *ioaddr, int wait_type)
|
||||
TYPHOON_STATUS_WAITING_FOR_HOST)
|
||||
goto out;
|
||||
|
||||
if(wait_type == WaitSleep) {
|
||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
schedule_timeout(1);
|
||||
} else
|
||||
if(wait_type == WaitSleep)
|
||||
schedule_timeout_uninterruptible(1);
|
||||
else
|
||||
udelay(TYPHOON_UDELAY);
|
||||
}
|
||||
|
||||
|
@ -490,6 +490,8 @@ struct rhine_private {
|
||||
u8 tx_thresh, rx_thresh;
|
||||
|
||||
struct mii_if_info mii_if;
|
||||
struct work_struct tx_timeout_task;
|
||||
struct work_struct check_media_task;
|
||||
void __iomem *base;
|
||||
};
|
||||
|
||||
@ -497,6 +499,8 @@ static int mdio_read(struct net_device *dev, int phy_id, int location);
|
||||
static void mdio_write(struct net_device *dev, int phy_id, int location, int value);
|
||||
static int rhine_open(struct net_device *dev);
|
||||
static void rhine_tx_timeout(struct net_device *dev);
|
||||
static void rhine_tx_timeout_task(struct net_device *dev);
|
||||
static void rhine_check_media_task(struct net_device *dev);
|
||||
static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev);
|
||||
static irqreturn_t rhine_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
|
||||
static void rhine_tx(struct net_device *dev);
|
||||
@ -814,8 +818,9 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
|
||||
|
||||
for (i = 0; i < 6; i++)
|
||||
dev->dev_addr[i] = ioread8(ioaddr + StationAddr + i);
|
||||
memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
|
||||
|
||||
if (!is_valid_ether_addr(dev->dev_addr)) {
|
||||
if (!is_valid_ether_addr(dev->perm_addr)) {
|
||||
rc = -EIO;
|
||||
printk(KERN_ERR "Invalid MAC address\n");
|
||||
goto err_out_unmap;
|
||||
@ -850,6 +855,12 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
|
||||
if (rp->quirks & rqRhineI)
|
||||
dev->features |= NETIF_F_SG|NETIF_F_HW_CSUM;
|
||||
|
||||
INIT_WORK(&rp->tx_timeout_task,
|
||||
(void (*)(void *))rhine_tx_timeout_task, dev);
|
||||
|
||||
INIT_WORK(&rp->check_media_task,
|
||||
(void (*)(void *))rhine_check_media_task, dev);
|
||||
|
||||
/* dev->name not defined before register_netdev()! */
|
||||
rc = register_netdev(dev);
|
||||
if (rc)
|
||||
@ -1076,6 +1087,11 @@ static void rhine_check_media(struct net_device *dev, unsigned int init_media)
|
||||
ioaddr + ChipCmd1);
|
||||
}
|
||||
|
||||
static void rhine_check_media_task(struct net_device *dev)
|
||||
{
|
||||
rhine_check_media(dev, 0);
|
||||
}
|
||||
|
||||
static void init_registers(struct net_device *dev)
|
||||
{
|
||||
struct rhine_private *rp = netdev_priv(dev);
|
||||
@ -1129,8 +1145,8 @@ static void rhine_disable_linkmon(void __iomem *ioaddr, u32 quirks)
|
||||
if (quirks & rqRhineI) {
|
||||
iowrite8(0x01, ioaddr + MIIRegAddr); // MII_BMSR
|
||||
|
||||
/* Can be called from ISR. Evil. */
|
||||
mdelay(1);
|
||||
/* Do not call from ISR! */
|
||||
msleep(1);
|
||||
|
||||
/* 0x80 must be set immediately before turning it off */
|
||||
iowrite8(0x80, ioaddr + MIICmd);
|
||||
@ -1218,6 +1234,16 @@ static int rhine_open(struct net_device *dev)
|
||||
}
|
||||
|
||||
static void rhine_tx_timeout(struct net_device *dev)
|
||||
{
|
||||
struct rhine_private *rp = netdev_priv(dev);
|
||||
|
||||
/*
|
||||
* Move bulk of work outside of interrupt context
|
||||
*/
|
||||
schedule_work(&rp->tx_timeout_task);
|
||||
}
|
||||
|
||||
static void rhine_tx_timeout_task(struct net_device *dev)
|
||||
{
|
||||
struct rhine_private *rp = netdev_priv(dev);
|
||||
void __iomem *ioaddr = rp->base;
|
||||
@ -1625,7 +1651,7 @@ static void rhine_error(struct net_device *dev, int intr_status)
|
||||
spin_lock(&rp->lock);
|
||||
|
||||
if (intr_status & IntrLinkChange)
|
||||
rhine_check_media(dev, 0);
|
||||
schedule_work(&rp->check_media_task);
|
||||
if (intr_status & IntrStatsMax) {
|
||||
rp->stats.rx_crc_errors += ioread16(ioaddr + RxCRCErrs);
|
||||
rp->stats.rx_missed_errors += ioread16(ioaddr + RxMissed);
|
||||
@ -1829,6 +1855,7 @@ static struct ethtool_ops netdev_ethtool_ops = {
|
||||
.set_wol = rhine_set_wol,
|
||||
.get_sg = ethtool_op_get_sg,
|
||||
.get_tx_csum = ethtool_op_get_tx_csum,
|
||||
.get_perm_addr = ethtool_op_get_perm_addr,
|
||||
};
|
||||
|
||||
static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
|
||||
@ -1872,6 +1899,9 @@ static int rhine_close(struct net_device *dev)
|
||||
spin_unlock_irq(&rp->lock);
|
||||
|
||||
free_irq(rp->pdev->irq, dev);
|
||||
|
||||
flush_scheduled_work();
|
||||
|
||||
free_rbufs(dev);
|
||||
free_tbufs(dev);
|
||||
free_ring(dev);
|
||||
|
@ -1617,8 +1617,7 @@ static int get_wait_data(struct cosa_data *cosa)
|
||||
return r;
|
||||
}
|
||||
/* sleep if not ready to read */
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
schedule_timeout(1);
|
||||
schedule_timeout_interruptible(1);
|
||||
}
|
||||
printk(KERN_INFO "cosa: timeout in get_wait_data (status 0x%x)\n",
|
||||
cosa_getstatus(cosa));
|
||||
@ -1644,8 +1643,7 @@ static int put_wait_data(struct cosa_data *cosa, int data)
|
||||
}
|
||||
#if 0
|
||||
/* sleep if not ready to read */
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule_timeout(1);
|
||||
schedule_timeout_interruptible(1);
|
||||
#endif
|
||||
}
|
||||
printk(KERN_INFO "cosa%d: timeout in put_wait_data (status 0x%x)\n",
|
||||
|
@ -109,7 +109,7 @@ static long cycx_2x_irq_options[] = { 7, 3, 5, 9, 10, 11, 12, 15 };
|
||||
* < 0 error.
|
||||
* Context: process */
|
||||
|
||||
int __init cycx_drv_init(void)
|
||||
static int __init cycx_drv_init(void)
|
||||
{
|
||||
printk(KERN_INFO "%s v%u.%u %s\n", fullname, MOD_VERSION, MOD_RELEASE,
|
||||
copyright);
|
||||
@ -119,7 +119,7 @@ int __init cycx_drv_init(void)
|
||||
|
||||
/* Module 'remove' entry point.
|
||||
* o release all remaining system resources */
|
||||
void cycx_drv_cleanup(void)
|
||||
static void cycx_drv_cleanup(void)
|
||||
{
|
||||
}
|
||||
|
||||
@ -184,8 +184,7 @@ int cycx_down(struct cycx_hw *hw)
|
||||
}
|
||||
|
||||
/* Enable interrupt generation. */
|
||||
EXPORT_SYMBOL(cycx_inten);
|
||||
void cycx_inten(struct cycx_hw *hw)
|
||||
static void cycx_inten(struct cycx_hw *hw)
|
||||
{
|
||||
writeb(0, hw->dpmbase);
|
||||
}
|
||||
|
@ -103,7 +103,7 @@ static struct cycx_device *cycx_card_array; /* adapter data space */
|
||||
* < 0 error.
|
||||
* Context: process
|
||||
*/
|
||||
int __init cycx_init(void)
|
||||
static int __init cycx_init(void)
|
||||
{
|
||||
int cnt, err = -ENOMEM;
|
||||
|
||||
|
@ -78,6 +78,7 @@
|
||||
|
||||
#define CYCLOMX_X25_DEBUG 1
|
||||
|
||||
#include <linux/ctype.h> /* isdigit() */
|
||||
#include <linux/errno.h> /* return codes */
|
||||
#include <linux/if_arp.h> /* ARPHRD_HWX25 */
|
||||
#include <linux/kernel.h> /* printk(), and other useful stuff */
|
||||
@ -418,7 +419,7 @@ static int cycx_wan_new_if(struct wan_device *wandev, struct net_device *dev,
|
||||
|
||||
/* Set channel timeouts (default if not specified) */
|
||||
chan->idle_tmout = conf->idle_timeout ? conf->idle_timeout : 90;
|
||||
} else if (is_digit(conf->addr[0])) { /* PVC */
|
||||
} else if (isdigit(conf->addr[0])) { /* PVC */
|
||||
s16 lcn = dec_to_uint(conf->addr, 0);
|
||||
|
||||
if (lcn >= card->u.x.lo_pvc && lcn <= card->u.x.hi_pvc)
|
||||
@ -1531,7 +1532,7 @@ static unsigned dec_to_uint(u8 *str, int len)
|
||||
if (!len)
|
||||
len = strlen(str);
|
||||
|
||||
for (; len && is_digit(*str); ++str, --len)
|
||||
for (; len && isdigit(*str); ++str, --len)
|
||||
val = (val * 10) + (*str - (unsigned) '0');
|
||||
|
||||
return val;
|
||||
|
@ -446,8 +446,8 @@ static inline unsigned int dscc4_tx_quiescent(struct dscc4_dev_priv *dpriv,
|
||||
return readl(dpriv->base_addr + CH0FTDA + dpriv->dev_id*4) == dpriv->ltda;
|
||||
}
|
||||
|
||||
int state_check(u32 state, struct dscc4_dev_priv *dpriv, struct net_device *dev,
|
||||
const char *msg)
|
||||
static int state_check(u32 state, struct dscc4_dev_priv *dpriv,
|
||||
struct net_device *dev, const char *msg)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
@ -466,8 +466,9 @@ int state_check(u32 state, struct dscc4_dev_priv *dpriv, struct net_device *dev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
void dscc4_tx_print(struct net_device *dev, struct dscc4_dev_priv *dpriv,
|
||||
char *msg)
|
||||
static void dscc4_tx_print(struct net_device *dev,
|
||||
struct dscc4_dev_priv *dpriv,
|
||||
char *msg)
|
||||
{
|
||||
printk(KERN_DEBUG "%s: tx_current=%02d tx_dirty=%02d (%s)\n",
|
||||
dev->name, dpriv->tx_current, dpriv->tx_dirty, msg);
|
||||
@ -507,7 +508,8 @@ static void dscc4_release_ring(struct dscc4_dev_priv *dpriv)
|
||||
}
|
||||
}
|
||||
|
||||
inline int try_get_rx_skb(struct dscc4_dev_priv *dpriv, struct net_device *dev)
|
||||
static inline int try_get_rx_skb(struct dscc4_dev_priv *dpriv,
|
||||
struct net_device *dev)
|
||||
{
|
||||
unsigned int dirty = dpriv->rx_dirty%RX_RING_SIZE;
|
||||
struct RxFD *rx_fd = dpriv->rx_fd + dirty;
|
||||
@ -542,8 +544,7 @@ static int dscc4_wait_ack_cec(struct dscc4_dev_priv *dpriv,
|
||||
msg, i);
|
||||
goto done;
|
||||
}
|
||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
schedule_timeout(10);
|
||||
schedule_timeout_uninterruptible(10);
|
||||
rmb();
|
||||
} while (++i > 0);
|
||||
printk(KERN_ERR "%s: %s timeout\n", dev->name, msg);
|
||||
@ -588,8 +589,7 @@ static inline int dscc4_xpr_ack(struct dscc4_dev_priv *dpriv)
|
||||
(dpriv->iqtx[cur] & Xpr))
|
||||
break;
|
||||
smp_rmb();
|
||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
schedule_timeout(10);
|
||||
schedule_timeout_uninterruptible(10);
|
||||
} while (++i > 0);
|
||||
|
||||
return (i >= 0 ) ? i : -EAGAIN;
|
||||
@ -1035,8 +1035,7 @@ static void dscc4_pci_reset(struct pci_dev *pdev, void __iomem *ioaddr)
|
||||
/* Flush posted writes */
|
||||
readl(ioaddr + GSTAR);
|
||||
|
||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
schedule_timeout(10);
|
||||
schedule_timeout_uninterruptible(10);
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
pci_write_config_dword(pdev, i << 2, dscc4_pci_config_store[i]);
|
||||
@ -1894,7 +1893,7 @@ static void dscc4_rx_irq(struct dscc4_pci_priv *priv,
|
||||
* It failed and locked solid. Thus the introduction of a dummy skb.
|
||||
* Problem is acknowledged in errata sheet DS5. Joy :o/
|
||||
*/
|
||||
struct sk_buff *dscc4_init_dummy_skb(struct dscc4_dev_priv *dpriv)
|
||||
static struct sk_buff *dscc4_init_dummy_skb(struct dscc4_dev_priv *dpriv)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
|
||||
|
@ -74,11 +74,11 @@ MODULE_LICENSE("GPL");
|
||||
/*
|
||||
* Modules parameters and associated varaibles
|
||||
*/
|
||||
int fst_txq_low = FST_LOW_WATER_MARK;
|
||||
int fst_txq_high = FST_HIGH_WATER_MARK;
|
||||
int fst_max_reads = 7;
|
||||
int fst_excluded_cards = 0;
|
||||
int fst_excluded_list[FST_MAX_CARDS];
|
||||
static int fst_txq_low = FST_LOW_WATER_MARK;
|
||||
static int fst_txq_high = FST_HIGH_WATER_MARK;
|
||||
static int fst_max_reads = 7;
|
||||
static int fst_excluded_cards = 0;
|
||||
static int fst_excluded_list[FST_MAX_CARDS];
|
||||
|
||||
module_param(fst_txq_low, int, 0);
|
||||
module_param(fst_txq_high, int, 0);
|
||||
@ -572,13 +572,13 @@ static void do_bottom_half_rx(struct fst_card_info *card);
|
||||
static void fst_process_tx_work_q(unsigned long work_q);
|
||||
static void fst_process_int_work_q(unsigned long work_q);
|
||||
|
||||
DECLARE_TASKLET(fst_tx_task, fst_process_tx_work_q, 0);
|
||||
DECLARE_TASKLET(fst_int_task, fst_process_int_work_q, 0);
|
||||
static DECLARE_TASKLET(fst_tx_task, fst_process_tx_work_q, 0);
|
||||
static DECLARE_TASKLET(fst_int_task, fst_process_int_work_q, 0);
|
||||
|
||||
struct fst_card_info *fst_card_array[FST_MAX_CARDS];
|
||||
spinlock_t fst_work_q_lock;
|
||||
u64 fst_work_txq;
|
||||
u64 fst_work_intq;
|
||||
static struct fst_card_info *fst_card_array[FST_MAX_CARDS];
|
||||
static spinlock_t fst_work_q_lock;
|
||||
static u64 fst_work_txq;
|
||||
static u64 fst_work_intq;
|
||||
|
||||
static void
|
||||
fst_q_work_item(u64 * queue, int card_index)
|
||||
@ -980,8 +980,7 @@ fst_issue_cmd(struct fst_port_info *port, unsigned short cmd)
|
||||
/* Wait for any previous command to complete */
|
||||
while (mbval > NAK) {
|
||||
spin_unlock_irqrestore(&card->card_lock, flags);
|
||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
schedule_timeout(1);
|
||||
schedule_timeout_uninterruptible(1);
|
||||
spin_lock_irqsave(&card->card_lock, flags);
|
||||
|
||||
if (++safety > 2000) {
|
||||
@ -1498,7 +1497,7 @@ do_bottom_half_rx(struct fst_card_info *card)
|
||||
* The interrupt service routine
|
||||
* Dev_id is our fst_card_info pointer
|
||||
*/
|
||||
irqreturn_t
|
||||
static irqreturn_t
|
||||
fst_intr(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
struct fst_card_info *card;
|
||||
|
@ -330,7 +330,7 @@ static int pvc_close(struct net_device *dev)
|
||||
|
||||
|
||||
|
||||
int pvc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
|
||||
static int pvc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
|
||||
{
|
||||
pvc_device *pvc = dev_to_pvc(dev);
|
||||
fr_proto_pvc_info info;
|
||||
|
@ -8,10 +8,10 @@
|
||||
/*
|
||||
* Prints out len, max to 80 octets using printk, 20 per line
|
||||
*/
|
||||
void lmcConsoleLog(char *type, unsigned char *ucData, int iLen)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
#ifdef LMC_PACKET_LOG
|
||||
void lmcConsoleLog(char *type, unsigned char *ucData, int iLen)
|
||||
{
|
||||
int iNewLine = 1;
|
||||
char str[80], *pstr;
|
||||
|
||||
@ -43,26 +43,24 @@ void lmcConsoleLog(char *type, unsigned char *ucData, int iLen)
|
||||
}
|
||||
sprintf(pstr, "\n");
|
||||
printk(str);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
u_int32_t lmcEventLogIndex = 0;
|
||||
u_int32_t lmcEventLogBuf[LMC_EVENTLOGSIZE * LMC_EVENTLOGARGS];
|
||||
#endif
|
||||
|
||||
void lmcEventLog (u_int32_t EventNum, u_int32_t arg2, u_int32_t arg3)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
lmcEventLogBuf[lmcEventLogIndex++] = EventNum;
|
||||
lmcEventLogBuf[lmcEventLogIndex++] = arg2;
|
||||
lmcEventLogBuf[lmcEventLogIndex++] = arg3;
|
||||
lmcEventLogBuf[lmcEventLogIndex++] = jiffies;
|
||||
|
||||
lmcEventLogIndex &= (LMC_EVENTLOGSIZE * LMC_EVENTLOGARGS) - 1;
|
||||
#endif
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
void lmc_trace(struct net_device *dev, char *msg){
|
||||
#ifdef LMC_TRACE
|
||||
|
@ -47,14 +47,6 @@
|
||||
* of the GNU General Public License version 2, incorporated herein by reference.
|
||||
*/
|
||||
|
||||
/*
|
||||
* For lack of a better place, put the SSI cable stuff here.
|
||||
*/
|
||||
char *lmc_t1_cables[] = {
|
||||
"V.10/RS423", "EIA530A", "reserved", "X.21", "V.35",
|
||||
"EIA449/EIA530/V.36", "V.28/EIA232", "none", NULL
|
||||
};
|
||||
|
||||
/*
|
||||
* protocol independent method.
|
||||
*/
|
||||
|
@ -472,24 +472,8 @@ enum pc300_loopback_cmds {
|
||||
|
||||
#ifdef __KERNEL__
|
||||
/* Function Prototypes */
|
||||
int dma_buf_write(pc300_t *, int, ucchar *, int);
|
||||
int dma_buf_read(pc300_t *, int, struct sk_buff *);
|
||||
void tx_dma_start(pc300_t *, int);
|
||||
void rx_dma_start(pc300_t *, int);
|
||||
void tx_dma_stop(pc300_t *, int);
|
||||
void rx_dma_stop(pc300_t *, int);
|
||||
int cpc_queue_xmit(struct sk_buff *, struct net_device *);
|
||||
void cpc_net_rx(struct net_device *);
|
||||
void cpc_sca_status(pc300_t *, int);
|
||||
int cpc_change_mtu(struct net_device *, int);
|
||||
int cpc_ioctl(struct net_device *, struct ifreq *, int);
|
||||
int ch_config(pc300dev_t *);
|
||||
int rx_config(pc300dev_t *);
|
||||
int tx_config(pc300dev_t *);
|
||||
void cpc_opench(pc300dev_t *);
|
||||
void cpc_closech(pc300dev_t *);
|
||||
int cpc_open(struct net_device *dev);
|
||||
int cpc_close(struct net_device *dev);
|
||||
int cpc_set_media(hdlc_device *, int);
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
|
@ -291,6 +291,7 @@ static uclong detect_ram(pc300_t *);
|
||||
static void plx_init(pc300_t *);
|
||||
static void cpc_trace(struct net_device *, struct sk_buff *, char);
|
||||
static int cpc_attach(struct net_device *, unsigned short, unsigned short);
|
||||
static int cpc_close(struct net_device *dev);
|
||||
|
||||
#ifdef CONFIG_PC300_MLPPP
|
||||
void cpc_tty_init(pc300dev_t * dev);
|
||||
@ -437,7 +438,7 @@ static void rx_dma_buf_check(pc300_t * card, int ch)
|
||||
printk("\n");
|
||||
}
|
||||
|
||||
int dma_get_rx_frame_size(pc300_t * card, int ch)
|
||||
static int dma_get_rx_frame_size(pc300_t * card, int ch)
|
||||
{
|
||||
volatile pcsca_bd_t __iomem *ptdescr;
|
||||
ucshort first_bd = card->chan[ch].rx_first_bd;
|
||||
@ -462,7 +463,7 @@ int dma_get_rx_frame_size(pc300_t * card, int ch)
|
||||
* dma_buf_write: writes a frame to the Tx DMA buffers
|
||||
* NOTE: this function writes one frame at a time.
|
||||
*/
|
||||
int dma_buf_write(pc300_t * card, int ch, ucchar * ptdata, int len)
|
||||
static int dma_buf_write(pc300_t * card, int ch, ucchar * ptdata, int len)
|
||||
{
|
||||
int i, nchar;
|
||||
volatile pcsca_bd_t __iomem *ptdescr;
|
||||
@ -503,7 +504,7 @@ int dma_buf_write(pc300_t * card, int ch, ucchar * ptdata, int len)
|
||||
* dma_buf_read: reads a frame from the Rx DMA buffers
|
||||
* NOTE: this function reads one frame at a time.
|
||||
*/
|
||||
int dma_buf_read(pc300_t * card, int ch, struct sk_buff *skb)
|
||||
static int dma_buf_read(pc300_t * card, int ch, struct sk_buff *skb)
|
||||
{
|
||||
int nchar;
|
||||
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
|
||||
@ -560,7 +561,7 @@ int dma_buf_read(pc300_t * card, int ch, struct sk_buff *skb)
|
||||
return (rcvd);
|
||||
}
|
||||
|
||||
void tx_dma_stop(pc300_t * card, int ch)
|
||||
static void tx_dma_stop(pc300_t * card, int ch)
|
||||
{
|
||||
void __iomem *scabase = card->hw.scabase;
|
||||
ucchar drr_ena_bit = 1 << (5 + 2 * ch);
|
||||
@ -571,7 +572,7 @@ void tx_dma_stop(pc300_t * card, int ch)
|
||||
cpc_writeb(scabase + DRR, drr_rst_bit & ~drr_ena_bit);
|
||||
}
|
||||
|
||||
void rx_dma_stop(pc300_t * card, int ch)
|
||||
static void rx_dma_stop(pc300_t * card, int ch)
|
||||
{
|
||||
void __iomem *scabase = card->hw.scabase;
|
||||
ucchar drr_ena_bit = 1 << (4 + 2 * ch);
|
||||
@ -582,7 +583,7 @@ void rx_dma_stop(pc300_t * card, int ch)
|
||||
cpc_writeb(scabase + DRR, drr_rst_bit & ~drr_ena_bit);
|
||||
}
|
||||
|
||||
void rx_dma_start(pc300_t * card, int ch)
|
||||
static void rx_dma_start(pc300_t * card, int ch)
|
||||
{
|
||||
void __iomem *scabase = card->hw.scabase;
|
||||
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
|
||||
@ -607,7 +608,7 @@ void rx_dma_start(pc300_t * card, int ch)
|
||||
/*************************/
|
||||
/*** FALC Routines ***/
|
||||
/*************************/
|
||||
void falc_issue_cmd(pc300_t * card, int ch, ucchar cmd)
|
||||
static void falc_issue_cmd(pc300_t * card, int ch, ucchar cmd)
|
||||
{
|
||||
void __iomem *falcbase = card->hw.falcbase;
|
||||
unsigned long i = 0;
|
||||
@ -622,7 +623,7 @@ void falc_issue_cmd(pc300_t * card, int ch, ucchar cmd)
|
||||
cpc_writeb(falcbase + F_REG(CMDR, ch), cmd);
|
||||
}
|
||||
|
||||
void falc_intr_enable(pc300_t * card, int ch)
|
||||
static void falc_intr_enable(pc300_t * card, int ch)
|
||||
{
|
||||
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
|
||||
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
|
||||
@ -672,7 +673,7 @@ void falc_intr_enable(pc300_t * card, int ch)
|
||||
}
|
||||
}
|
||||
|
||||
void falc_open_timeslot(pc300_t * card, int ch, int timeslot)
|
||||
static void falc_open_timeslot(pc300_t * card, int ch, int timeslot)
|
||||
{
|
||||
void __iomem *falcbase = card->hw.falcbase;
|
||||
ucchar tshf = card->chan[ch].falc.offset;
|
||||
@ -688,7 +689,7 @@ void falc_open_timeslot(pc300_t * card, int ch, int timeslot)
|
||||
(0x80 >> (timeslot & 0x07)));
|
||||
}
|
||||
|
||||
void falc_close_timeslot(pc300_t * card, int ch, int timeslot)
|
||||
static void falc_close_timeslot(pc300_t * card, int ch, int timeslot)
|
||||
{
|
||||
void __iomem *falcbase = card->hw.falcbase;
|
||||
ucchar tshf = card->chan[ch].falc.offset;
|
||||
@ -704,7 +705,7 @@ void falc_close_timeslot(pc300_t * card, int ch, int timeslot)
|
||||
~(0x80 >> (timeslot & 0x07)));
|
||||
}
|
||||
|
||||
void falc_close_all_timeslots(pc300_t * card, int ch)
|
||||
static void falc_close_all_timeslots(pc300_t * card, int ch)
|
||||
{
|
||||
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
|
||||
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
|
||||
@ -726,7 +727,7 @@ void falc_close_all_timeslots(pc300_t * card, int ch)
|
||||
}
|
||||
}
|
||||
|
||||
void falc_open_all_timeslots(pc300_t * card, int ch)
|
||||
static void falc_open_all_timeslots(pc300_t * card, int ch)
|
||||
{
|
||||
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
|
||||
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
|
||||
@ -758,7 +759,7 @@ void falc_open_all_timeslots(pc300_t * card, int ch)
|
||||
}
|
||||
}
|
||||
|
||||
void falc_init_timeslot(pc300_t * card, int ch)
|
||||
static void falc_init_timeslot(pc300_t * card, int ch)
|
||||
{
|
||||
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
|
||||
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
|
||||
@ -776,7 +777,7 @@ void falc_init_timeslot(pc300_t * card, int ch)
|
||||
}
|
||||
}
|
||||
|
||||
void falc_enable_comm(pc300_t * card, int ch)
|
||||
static void falc_enable_comm(pc300_t * card, int ch)
|
||||
{
|
||||
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
|
||||
falc_t *pfalc = (falc_t *) & chan->falc;
|
||||
@ -792,7 +793,7 @@ void falc_enable_comm(pc300_t * card, int ch)
|
||||
~((CPLD_REG1_FALC_DCD | CPLD_REG1_FALC_CTS) << (2 * ch)));
|
||||
}
|
||||
|
||||
void falc_disable_comm(pc300_t * card, int ch)
|
||||
static void falc_disable_comm(pc300_t * card, int ch)
|
||||
{
|
||||
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
|
||||
falc_t *pfalc = (falc_t *) & chan->falc;
|
||||
@ -806,7 +807,7 @@ void falc_disable_comm(pc300_t * card, int ch)
|
||||
((CPLD_REG1_FALC_DCD | CPLD_REG1_FALC_CTS) << (2 * ch)));
|
||||
}
|
||||
|
||||
void falc_init_t1(pc300_t * card, int ch)
|
||||
static void falc_init_t1(pc300_t * card, int ch)
|
||||
{
|
||||
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
|
||||
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
|
||||
@ -975,7 +976,7 @@ void falc_init_t1(pc300_t * card, int ch)
|
||||
falc_close_all_timeslots(card, ch);
|
||||
}
|
||||
|
||||
void falc_init_e1(pc300_t * card, int ch)
|
||||
static void falc_init_e1(pc300_t * card, int ch)
|
||||
{
|
||||
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
|
||||
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
|
||||
@ -1155,7 +1156,7 @@ void falc_init_e1(pc300_t * card, int ch)
|
||||
falc_close_all_timeslots(card, ch);
|
||||
}
|
||||
|
||||
void falc_init_hdlc(pc300_t * card, int ch)
|
||||
static void falc_init_hdlc(pc300_t * card, int ch)
|
||||
{
|
||||
void __iomem *falcbase = card->hw.falcbase;
|
||||
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
|
||||
@ -1181,7 +1182,7 @@ void falc_init_hdlc(pc300_t * card, int ch)
|
||||
falc_intr_enable(card, ch);
|
||||
}
|
||||
|
||||
void te_config(pc300_t * card, int ch)
|
||||
static void te_config(pc300_t * card, int ch)
|
||||
{
|
||||
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
|
||||
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
|
||||
@ -1241,7 +1242,7 @@ void te_config(pc300_t * card, int ch)
|
||||
CPC_UNLOCK(card, flags);
|
||||
}
|
||||
|
||||
void falc_check_status(pc300_t * card, int ch, unsigned char frs0)
|
||||
static void falc_check_status(pc300_t * card, int ch, unsigned char frs0)
|
||||
{
|
||||
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
|
||||
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
|
||||
@ -1397,7 +1398,7 @@ void falc_check_status(pc300_t * card, int ch, unsigned char frs0)
|
||||
}
|
||||
}
|
||||
|
||||
void falc_update_stats(pc300_t * card, int ch)
|
||||
static void falc_update_stats(pc300_t * card, int ch)
|
||||
{
|
||||
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
|
||||
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
|
||||
@ -1450,7 +1451,7 @@ void falc_update_stats(pc300_t * card, int ch)
|
||||
* the synchronizer and then sent to the system interface.
|
||||
*----------------------------------------------------------------------------
|
||||
*/
|
||||
void falc_remote_loop(pc300_t * card, int ch, int loop_on)
|
||||
static void falc_remote_loop(pc300_t * card, int ch, int loop_on)
|
||||
{
|
||||
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
|
||||
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
|
||||
@ -1495,7 +1496,7 @@ void falc_remote_loop(pc300_t * card, int ch, int loop_on)
|
||||
* coding must be identical.
|
||||
*----------------------------------------------------------------------------
|
||||
*/
|
||||
void falc_local_loop(pc300_t * card, int ch, int loop_on)
|
||||
static void falc_local_loop(pc300_t * card, int ch, int loop_on)
|
||||
{
|
||||
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
|
||||
falc_t *pfalc = (falc_t *) & chan->falc;
|
||||
@ -1522,7 +1523,7 @@ void falc_local_loop(pc300_t * card, int ch, int loop_on)
|
||||
* looped. They are originated by the FALC-LH transmitter.
|
||||
*----------------------------------------------------------------------------
|
||||
*/
|
||||
void falc_payload_loop(pc300_t * card, int ch, int loop_on)
|
||||
static void falc_payload_loop(pc300_t * card, int ch, int loop_on)
|
||||
{
|
||||
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
|
||||
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
|
||||
@ -1576,7 +1577,7 @@ void falc_payload_loop(pc300_t * card, int ch, int loop_on)
|
||||
* Description: Turns XLU bit off in the proper register
|
||||
*----------------------------------------------------------------------------
|
||||
*/
|
||||
void turn_off_xlu(pc300_t * card, int ch)
|
||||
static void turn_off_xlu(pc300_t * card, int ch)
|
||||
{
|
||||
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
|
||||
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
|
||||
@ -1597,7 +1598,7 @@ void turn_off_xlu(pc300_t * card, int ch)
|
||||
* Description: Turns XLD bit off in the proper register
|
||||
*----------------------------------------------------------------------------
|
||||
*/
|
||||
void turn_off_xld(pc300_t * card, int ch)
|
||||
static void turn_off_xld(pc300_t * card, int ch)
|
||||
{
|
||||
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
|
||||
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
|
||||
@ -1619,7 +1620,7 @@ void turn_off_xld(pc300_t * card, int ch)
|
||||
* to generate a LOOP activation code over a T1/E1 line.
|
||||
*----------------------------------------------------------------------------
|
||||
*/
|
||||
void falc_generate_loop_up_code(pc300_t * card, int ch)
|
||||
static void falc_generate_loop_up_code(pc300_t * card, int ch)
|
||||
{
|
||||
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
|
||||
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
|
||||
@ -1652,7 +1653,7 @@ void falc_generate_loop_up_code(pc300_t * card, int ch)
|
||||
* to generate a LOOP deactivation code over a T1/E1 line.
|
||||
*----------------------------------------------------------------------------
|
||||
*/
|
||||
void falc_generate_loop_down_code(pc300_t * card, int ch)
|
||||
static void falc_generate_loop_down_code(pc300_t * card, int ch)
|
||||
{
|
||||
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
|
||||
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
|
||||
@ -1682,7 +1683,7 @@ void falc_generate_loop_down_code(pc300_t * card, int ch)
|
||||
* it on the reception side.
|
||||
*----------------------------------------------------------------------------
|
||||
*/
|
||||
void falc_pattern_test(pc300_t * card, int ch, unsigned int activate)
|
||||
static void falc_pattern_test(pc300_t * card, int ch, unsigned int activate)
|
||||
{
|
||||
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
|
||||
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
|
||||
@ -1729,7 +1730,7 @@ void falc_pattern_test(pc300_t * card, int ch, unsigned int activate)
|
||||
* Description: This routine returns the bit error counter value
|
||||
*----------------------------------------------------------------------------
|
||||
*/
|
||||
ucshort falc_pattern_test_error(pc300_t * card, int ch)
|
||||
static ucshort falc_pattern_test_error(pc300_t * card, int ch)
|
||||
{
|
||||
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
|
||||
falc_t *pfalc = (falc_t *) & chan->falc;
|
||||
@ -1769,7 +1770,7 @@ cpc_trace(struct net_device *dev, struct sk_buff *skb_main, char rx_tx)
|
||||
netif_rx(skb);
|
||||
}
|
||||
|
||||
void cpc_tx_timeout(struct net_device *dev)
|
||||
static void cpc_tx_timeout(struct net_device *dev)
|
||||
{
|
||||
pc300dev_t *d = (pc300dev_t *) dev->priv;
|
||||
pc300ch_t *chan = (pc300ch_t *) d->chan;
|
||||
@ -1797,7 +1798,7 @@ void cpc_tx_timeout(struct net_device *dev)
|
||||
netif_wake_queue(dev);
|
||||
}
|
||||
|
||||
int cpc_queue_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
static int cpc_queue_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
pc300dev_t *d = (pc300dev_t *) dev->priv;
|
||||
pc300ch_t *chan = (pc300ch_t *) d->chan;
|
||||
@ -1880,7 +1881,7 @@ int cpc_queue_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cpc_net_rx(struct net_device *dev)
|
||||
static void cpc_net_rx(struct net_device *dev)
|
||||
{
|
||||
pc300dev_t *d = (pc300dev_t *) dev->priv;
|
||||
pc300ch_t *chan = (pc300ch_t *) d->chan;
|
||||
@ -2403,7 +2404,7 @@ static irqreturn_t cpc_intr(int irq, void *dev_id, struct pt_regs *regs)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
void cpc_sca_status(pc300_t * card, int ch)
|
||||
static void cpc_sca_status(pc300_t * card, int ch)
|
||||
{
|
||||
ucchar ilar;
|
||||
void __iomem *scabase = card->hw.scabase;
|
||||
@ -2495,7 +2496,7 @@ void cpc_sca_status(pc300_t * card, int ch)
|
||||
}
|
||||
}
|
||||
|
||||
void cpc_falc_status(pc300_t * card, int ch)
|
||||
static void cpc_falc_status(pc300_t * card, int ch)
|
||||
{
|
||||
pc300ch_t *chan = &card->chan[ch];
|
||||
falc_t *pfalc = (falc_t *) & chan->falc;
|
||||
@ -2523,7 +2524,7 @@ void cpc_falc_status(pc300_t * card, int ch)
|
||||
CPC_UNLOCK(card, flags);
|
||||
}
|
||||
|
||||
int cpc_change_mtu(struct net_device *dev, int new_mtu)
|
||||
static int cpc_change_mtu(struct net_device *dev, int new_mtu)
|
||||
{
|
||||
if ((new_mtu < 128) || (new_mtu > PC300_DEF_MTU))
|
||||
return -EINVAL;
|
||||
@ -2531,7 +2532,7 @@ int cpc_change_mtu(struct net_device *dev, int new_mtu)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
|
||||
static int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
|
||||
{
|
||||
hdlc_device *hdlc = dev_to_hdlc(dev);
|
||||
pc300dev_t *d = (pc300dev_t *) dev->priv;
|
||||
@ -2856,7 +2857,7 @@ static int clock_rate_calc(uclong rate, uclong clock, int *br_io)
|
||||
}
|
||||
}
|
||||
|
||||
int ch_config(pc300dev_t * d)
|
||||
static int ch_config(pc300dev_t * d)
|
||||
{
|
||||
pc300ch_t *chan = (pc300ch_t *) d->chan;
|
||||
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
|
||||
@ -3004,7 +3005,7 @@ int ch_config(pc300dev_t * d)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rx_config(pc300dev_t * d)
|
||||
static int rx_config(pc300dev_t * d)
|
||||
{
|
||||
pc300ch_t *chan = (pc300ch_t *) d->chan;
|
||||
pc300_t *card = (pc300_t *) chan->card;
|
||||
@ -3035,7 +3036,7 @@ int rx_config(pc300dev_t * d)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tx_config(pc300dev_t * d)
|
||||
static int tx_config(pc300dev_t * d)
|
||||
{
|
||||
pc300ch_t *chan = (pc300ch_t *) d->chan;
|
||||
pc300_t *card = (pc300_t *) chan->card;
|
||||
@ -3098,7 +3099,7 @@ static int cpc_attach(struct net_device *dev, unsigned short encoding,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cpc_opench(pc300dev_t * d)
|
||||
static void cpc_opench(pc300dev_t * d)
|
||||
{
|
||||
pc300ch_t *chan = (pc300ch_t *) d->chan;
|
||||
pc300_t *card = (pc300_t *) chan->card;
|
||||
@ -3116,7 +3117,7 @@ void cpc_opench(pc300dev_t * d)
|
||||
cpc_readb(scabase + M_REG(CTL, ch)) & ~(CTL_RTS | CTL_DTR));
|
||||
}
|
||||
|
||||
void cpc_closech(pc300dev_t * d)
|
||||
static void cpc_closech(pc300dev_t * d)
|
||||
{
|
||||
pc300ch_t *chan = (pc300ch_t *) d->chan;
|
||||
pc300_t *card = (pc300_t *) chan->card;
|
||||
@ -3173,7 +3174,7 @@ int cpc_open(struct net_device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cpc_close(struct net_device *dev)
|
||||
static int cpc_close(struct net_device *dev)
|
||||
{
|
||||
hdlc_device *hdlc = dev_to_hdlc(dev);
|
||||
pc300dev_t *d = (pc300dev_t *) dev->priv;
|
||||
|
@ -112,10 +112,10 @@ typedef struct _st_cpc_tty_area {
|
||||
static struct tty_driver serial_drv;
|
||||
|
||||
/* local variables */
|
||||
st_cpc_tty_area cpc_tty_area[CPC_TTY_NPORTS];
|
||||
static st_cpc_tty_area cpc_tty_area[CPC_TTY_NPORTS];
|
||||
|
||||
int cpc_tty_cnt=0; /* number of intrfaces configured with MLPPP */
|
||||
int cpc_tty_unreg_flag = 0;
|
||||
static int cpc_tty_cnt = 0; /* number of intrfaces configured with MLPPP */
|
||||
static int cpc_tty_unreg_flag = 0;
|
||||
|
||||
/* TTY functions prototype */
|
||||
static int cpc_tty_open(struct tty_struct *tty, struct file *flip);
|
||||
@ -132,9 +132,9 @@ static void cpc_tty_trace(pc300dev_t *dev, char* buf, int len, char rxtx);
|
||||
static void cpc_tty_signal_off(pc300dev_t *pc300dev, unsigned char);
|
||||
static void cpc_tty_signal_on(pc300dev_t *pc300dev, unsigned char);
|
||||
|
||||
int pc300_tiocmset(struct tty_struct *, struct file *,
|
||||
unsigned int, unsigned int);
|
||||
int pc300_tiocmget(struct tty_struct *, struct file *);
|
||||
static int pc300_tiocmset(struct tty_struct *, struct file *,
|
||||
unsigned int, unsigned int);
|
||||
static int pc300_tiocmget(struct tty_struct *, struct file *);
|
||||
|
||||
/* functions called by PC300 driver */
|
||||
void cpc_tty_init(pc300dev_t *dev);
|
||||
@ -538,8 +538,8 @@ static int cpc_tty_chars_in_buffer(struct tty_struct *tty)
|
||||
return(0);
|
||||
}
|
||||
|
||||
int pc300_tiocmset(struct tty_struct *tty, struct file *file,
|
||||
unsigned int set, unsigned int clear)
|
||||
static int pc300_tiocmset(struct tty_struct *tty, struct file *file,
|
||||
unsigned int set, unsigned int clear)
|
||||
{
|
||||
st_cpc_tty_area *cpc_tty;
|
||||
|
||||
@ -565,7 +565,7 @@ int pc300_tiocmset(struct tty_struct *tty, struct file *file,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pc300_tiocmget(struct tty_struct *tty, struct file *file)
|
||||
static int pc300_tiocmget(struct tty_struct *tty, struct file *file)
|
||||
{
|
||||
unsigned int result;
|
||||
unsigned char status;
|
||||
|
@ -182,7 +182,7 @@ static char sdla_byte(struct net_device *dev, int addr)
|
||||
return(byte);
|
||||
}
|
||||
|
||||
void sdla_stop(struct net_device *dev)
|
||||
static void sdla_stop(struct net_device *dev)
|
||||
{
|
||||
struct frad_local *flp;
|
||||
|
||||
@ -209,7 +209,7 @@ void sdla_stop(struct net_device *dev)
|
||||
}
|
||||
}
|
||||
|
||||
void sdla_start(struct net_device *dev)
|
||||
static void sdla_start(struct net_device *dev)
|
||||
{
|
||||
struct frad_local *flp;
|
||||
|
||||
@ -247,7 +247,7 @@ void sdla_start(struct net_device *dev)
|
||||
*
|
||||
***************************************************/
|
||||
|
||||
int sdla_z80_poll(struct net_device *dev, int z80_addr, int jiffs, char resp1, char resp2)
|
||||
static int sdla_z80_poll(struct net_device *dev, int z80_addr, int jiffs, char resp1, char resp2)
|
||||
{
|
||||
unsigned long start, done, now;
|
||||
char resp, *temp;
|
||||
@ -505,7 +505,7 @@ static int sdla_cmd(struct net_device *dev, int cmd, short dlci, short flags,
|
||||
|
||||
static int sdla_reconfig(struct net_device *dev);
|
||||
|
||||
int sdla_activate(struct net_device *slave, struct net_device *master)
|
||||
static int sdla_activate(struct net_device *slave, struct net_device *master)
|
||||
{
|
||||
struct frad_local *flp;
|
||||
int i;
|
||||
@ -527,7 +527,7 @@ int sdla_activate(struct net_device *slave, struct net_device *master)
|
||||
return(0);
|
||||
}
|
||||
|
||||
int sdla_deactivate(struct net_device *slave, struct net_device *master)
|
||||
static int sdla_deactivate(struct net_device *slave, struct net_device *master)
|
||||
{
|
||||
struct frad_local *flp;
|
||||
int i;
|
||||
@ -549,7 +549,7 @@ int sdla_deactivate(struct net_device *slave, struct net_device *master)
|
||||
return(0);
|
||||
}
|
||||
|
||||
int sdla_assoc(struct net_device *slave, struct net_device *master)
|
||||
static int sdla_assoc(struct net_device *slave, struct net_device *master)
|
||||
{
|
||||
struct frad_local *flp;
|
||||
int i;
|
||||
@ -585,7 +585,7 @@ int sdla_assoc(struct net_device *slave, struct net_device *master)
|
||||
return(0);
|
||||
}
|
||||
|
||||
int sdla_deassoc(struct net_device *slave, struct net_device *master)
|
||||
static int sdla_deassoc(struct net_device *slave, struct net_device *master)
|
||||
{
|
||||
struct frad_local *flp;
|
||||
int i;
|
||||
@ -613,7 +613,7 @@ int sdla_deassoc(struct net_device *slave, struct net_device *master)
|
||||
return(0);
|
||||
}
|
||||
|
||||
int sdla_dlci_conf(struct net_device *slave, struct net_device *master, int get)
|
||||
static int sdla_dlci_conf(struct net_device *slave, struct net_device *master, int get)
|
||||
{
|
||||
struct frad_local *flp;
|
||||
struct dlci_local *dlp;
|
||||
@ -1324,7 +1324,7 @@ NOTE: This is rather a useless action right now, as the
|
||||
return(0);
|
||||
}
|
||||
|
||||
int sdla_change_mtu(struct net_device *dev, int new_mtu)
|
||||
static int sdla_change_mtu(struct net_device *dev, int new_mtu)
|
||||
{
|
||||
struct frad_local *flp;
|
||||
|
||||
@ -1337,7 +1337,7 @@ int sdla_change_mtu(struct net_device *dev, int new_mtu)
|
||||
return(-EOPNOTSUPP);
|
||||
}
|
||||
|
||||
int sdla_set_config(struct net_device *dev, struct ifmap *map)
|
||||
static int sdla_set_config(struct net_device *dev, struct ifmap *map)
|
||||
{
|
||||
struct frad_local *flp;
|
||||
int i;
|
||||
|
@ -822,7 +822,7 @@ static int new_if(struct wan_device* wandev, struct net_device* dev,
|
||||
chan->card = card;
|
||||
|
||||
/* verify media address */
|
||||
if (is_digit(conf->addr[0])) {
|
||||
if (isdigit(conf->addr[0])) {
|
||||
|
||||
dlci = dec_to_uint(conf->addr, 0);
|
||||
|
||||
@ -3456,7 +3456,7 @@ static unsigned int dec_to_uint (unsigned char* str, int len)
|
||||
if (!len)
|
||||
len = strlen(str);
|
||||
|
||||
for (val = 0; len && is_digit(*str); ++str, --len)
|
||||
for (val = 0; len && isdigit(*str); ++str, --len)
|
||||
val = (val * 10) + (*str - (unsigned)'0');
|
||||
|
||||
return val;
|
||||
|
@ -957,7 +957,7 @@ static int new_if(struct wan_device* wandev, struct net_device* dev,
|
||||
chan->hold_timeout = (conf->hold_timeout) ?
|
||||
conf->hold_timeout : 10;
|
||||
|
||||
}else if (is_digit(conf->addr[0])){ /* PVC */
|
||||
}else if (isdigit(conf->addr[0])){ /* PVC */
|
||||
int lcn = dec_to_uint(conf->addr, 0);
|
||||
|
||||
if ((lcn >= card->u.x.lo_pvc) && (lcn <= card->u.x.hi_pvc)){
|
||||
@ -3875,7 +3875,7 @@ static unsigned int dec_to_uint (unsigned char* str, int len)
|
||||
if (!len)
|
||||
len = strlen(str);
|
||||
|
||||
for (val = 0; len && is_digit(*str); ++str, --len)
|
||||
for (val = 0; len && isdigit(*str); ++str, --len)
|
||||
val = (val * 10) + (*str - (unsigned)'0');
|
||||
|
||||
return val;
|
||||
@ -3896,9 +3896,9 @@ static unsigned int hex_to_uint (unsigned char* str, int len)
|
||||
for (val = 0; len; ++str, --len)
|
||||
{
|
||||
ch = *str;
|
||||
if (is_digit(ch))
|
||||
if (isdigit(ch))
|
||||
val = (val << 4) + (ch - (unsigned)'0');
|
||||
else if (is_hex_digit(ch))
|
||||
else if (isxdigit(ch))
|
||||
val = (val << 4) + ((ch & 0xDF) - (unsigned)'A' + 10);
|
||||
else break;
|
||||
}
|
||||
|
@ -642,9 +642,7 @@ int sdla_mapmem (sdlahw_t* hw, unsigned long addr)
|
||||
* Enable interrupt generation.
|
||||
*/
|
||||
|
||||
EXPORT_SYMBOL(sdla_inten);
|
||||
|
||||
int sdla_inten (sdlahw_t* hw)
|
||||
static int sdla_inten (sdlahw_t* hw)
|
||||
{
|
||||
unsigned port = hw->port;
|
||||
int tmp, i;
|
||||
@ -698,8 +696,7 @@ int sdla_inten (sdlahw_t* hw)
|
||||
* Disable interrupt generation.
|
||||
*/
|
||||
|
||||
EXPORT_SYMBOL(sdla_intde);
|
||||
|
||||
#if 0
|
||||
int sdla_intde (sdlahw_t* hw)
|
||||
{
|
||||
unsigned port = hw->port;
|
||||
@ -748,14 +745,13 @@ int sdla_intde (sdlahw_t* hw)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* 0 */
|
||||
|
||||
/*============================================================================
|
||||
* Acknowledge SDLA hardware interrupt.
|
||||
*/
|
||||
|
||||
EXPORT_SYMBOL(sdla_intack);
|
||||
|
||||
int sdla_intack (sdlahw_t* hw)
|
||||
static int sdla_intack (sdlahw_t* hw)
|
||||
{
|
||||
unsigned port = hw->port;
|
||||
int tmp;
|
||||
@ -827,8 +823,7 @@ void read_S514_int_stat (sdlahw_t* hw, u32* int_status)
|
||||
* Generate an interrupt to adapter's CPU.
|
||||
*/
|
||||
|
||||
EXPORT_SYMBOL(sdla_intr);
|
||||
|
||||
#if 0
|
||||
int sdla_intr (sdlahw_t* hw)
|
||||
{
|
||||
unsigned port = hw->port;
|
||||
@ -863,6 +858,7 @@ int sdla_intr (sdlahw_t* hw)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* 0 */
|
||||
|
||||
/*============================================================================
|
||||
* Execute Adapter Command.
|
||||
|
@ -221,7 +221,7 @@ static void sppp_clear_timeout(struct sppp *p)
|
||||
* here.
|
||||
*/
|
||||
|
||||
void sppp_input (struct net_device *dev, struct sk_buff *skb)
|
||||
static void sppp_input (struct net_device *dev, struct sk_buff *skb)
|
||||
{
|
||||
struct ppp_header *h;
|
||||
struct sppp *sp = (struct sppp *)sppp_of(dev);
|
||||
@ -355,8 +355,6 @@ void sppp_input (struct net_device *dev, struct sk_buff *skb)
|
||||
return;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(sppp_input);
|
||||
|
||||
/*
|
||||
* Handle transmit packets.
|
||||
*/
|
||||
@ -990,7 +988,7 @@ EXPORT_SYMBOL(sppp_reopen);
|
||||
* the mtu is out of range.
|
||||
*/
|
||||
|
||||
int sppp_change_mtu(struct net_device *dev, int new_mtu)
|
||||
static int sppp_change_mtu(struct net_device *dev, int new_mtu)
|
||||
{
|
||||
if(new_mtu<128||new_mtu>PPP_MTU||(dev->flags&IFF_UP))
|
||||
return -EINVAL;
|
||||
@ -998,8 +996,6 @@ int sppp_change_mtu(struct net_device *dev, int new_mtu)
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(sppp_change_mtu);
|
||||
|
||||
/**
|
||||
* sppp_do_ioctl - Ioctl handler for ppp/hdlc
|
||||
* @dev: Device subject to ioctl
|
||||
@ -1456,7 +1452,7 @@ static int sppp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_t
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct packet_type sppp_packet_type = {
|
||||
static struct packet_type sppp_packet_type = {
|
||||
.type = __constant_htons(ETH_P_WAN_PPP),
|
||||
.func = sppp_rcv,
|
||||
};
|
||||
|
@ -1046,7 +1046,6 @@ static WifiCtlHdr wifictlhdr8023 = {
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef WIRELESS_EXT
|
||||
// Frequency list (map channels to frequencies)
|
||||
static const long frequency_list[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442,
|
||||
2447, 2452, 2457, 2462, 2467, 2472, 2484 };
|
||||
@ -1067,7 +1066,6 @@ typedef struct wep_key_t {
|
||||
|
||||
/* List of Wireless Handlers (new API) */
|
||||
static const struct iw_handler_def airo_handler_def;
|
||||
#endif /* WIRELESS_EXT */
|
||||
|
||||
static const char version[] = "airo.c 0.6 (Ben Reed & Javier Achirica)";
|
||||
|
||||
@ -1110,10 +1108,8 @@ static irqreturn_t airo_interrupt( int irq, void* dev_id, struct pt_regs
|
||||
static int airo_thread(void *data);
|
||||
static void timer_func( struct net_device *dev );
|
||||
static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
|
||||
#ifdef WIRELESS_EXT
|
||||
static struct iw_statistics *airo_get_wireless_stats (struct net_device *dev);
|
||||
static void airo_read_wireless_stats (struct airo_info *local);
|
||||
#endif /* WIRELESS_EXT */
|
||||
#ifdef CISCO_EXT
|
||||
static int readrids(struct net_device *dev, aironet_ioctl *comp);
|
||||
static int writerids(struct net_device *dev, aironet_ioctl *comp);
|
||||
@ -1187,12 +1183,10 @@ struct airo_info {
|
||||
int fid;
|
||||
} xmit, xmit11;
|
||||
struct net_device *wifidev;
|
||||
#ifdef WIRELESS_EXT
|
||||
struct iw_statistics wstats; // wireless stats
|
||||
unsigned long scan_timestamp; /* Time started to scan */
|
||||
struct iw_spy_data spy_data;
|
||||
struct iw_public_data wireless_data;
|
||||
#endif /* WIRELESS_EXT */
|
||||
#ifdef MICSUPPORT
|
||||
/* MIC stuff */
|
||||
struct crypto_tfm *tfm;
|
||||
@ -2527,7 +2521,8 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci,
|
||||
unsigned long mem_start, mem_len, aux_start, aux_len;
|
||||
int rc = -1;
|
||||
int i;
|
||||
unsigned char *busaddroff,*vpackoff;
|
||||
dma_addr_t busaddroff;
|
||||
unsigned char *vpackoff;
|
||||
unsigned char __iomem *pciaddroff;
|
||||
|
||||
mem_start = pci_resource_start(pci, 1);
|
||||
@ -2570,7 +2565,7 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci,
|
||||
/*
|
||||
* Setup descriptor RX, TX, CONFIG
|
||||
*/
|
||||
busaddroff = (unsigned char *)ai->shared_dma;
|
||||
busaddroff = ai->shared_dma;
|
||||
pciaddroff = ai->pciaux + AUX_OFFSET;
|
||||
vpackoff = ai->shared;
|
||||
|
||||
@ -2579,7 +2574,7 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci,
|
||||
ai->rxfids[i].pending = 0;
|
||||
ai->rxfids[i].card_ram_off = pciaddroff;
|
||||
ai->rxfids[i].virtual_host_addr = vpackoff;
|
||||
ai->rxfids[i].rx_desc.host_addr = (dma_addr_t) busaddroff;
|
||||
ai->rxfids[i].rx_desc.host_addr = busaddroff;
|
||||
ai->rxfids[i].rx_desc.valid = 1;
|
||||
ai->rxfids[i].rx_desc.len = PKTSIZE;
|
||||
ai->rxfids[i].rx_desc.rdy = 0;
|
||||
@ -2594,7 +2589,7 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci,
|
||||
ai->txfids[i].card_ram_off = pciaddroff;
|
||||
ai->txfids[i].virtual_host_addr = vpackoff;
|
||||
ai->txfids[i].tx_desc.valid = 1;
|
||||
ai->txfids[i].tx_desc.host_addr = (dma_addr_t) busaddroff;
|
||||
ai->txfids[i].tx_desc.host_addr = busaddroff;
|
||||
memcpy(ai->txfids[i].virtual_host_addr,
|
||||
&wifictlhdr8023, sizeof(wifictlhdr8023));
|
||||
|
||||
@ -2607,8 +2602,8 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci,
|
||||
/* Rid descriptor setup */
|
||||
ai->config_desc.card_ram_off = pciaddroff;
|
||||
ai->config_desc.virtual_host_addr = vpackoff;
|
||||
ai->config_desc.rid_desc.host_addr = (dma_addr_t) busaddroff;
|
||||
ai->ridbus = (dma_addr_t)busaddroff;
|
||||
ai->config_desc.rid_desc.host_addr = busaddroff;
|
||||
ai->ridbus = busaddroff;
|
||||
ai->config_desc.rid_desc.rid = 0;
|
||||
ai->config_desc.rid_desc.len = RIDSIZE;
|
||||
ai->config_desc.rid_desc.valid = 1;
|
||||
@ -2647,9 +2642,7 @@ static void wifi_setup(struct net_device *dev)
|
||||
dev->get_stats = &airo_get_stats;
|
||||
dev->set_mac_address = &airo_set_mac_address;
|
||||
dev->do_ioctl = &airo_ioctl;
|
||||
#ifdef WIRELESS_EXT
|
||||
dev->wireless_handlers = &airo_handler_def;
|
||||
#endif /* WIRELESS_EXT */
|
||||
dev->change_mtu = &airo_change_mtu;
|
||||
dev->open = &airo_open;
|
||||
dev->stop = &airo_close;
|
||||
@ -2675,9 +2668,7 @@ static struct net_device *init_wifidev(struct airo_info *ai,
|
||||
dev->priv = ethdev->priv;
|
||||
dev->irq = ethdev->irq;
|
||||
dev->base_addr = ethdev->base_addr;
|
||||
#ifdef WIRELESS_EXT
|
||||
dev->wireless_data = ethdev->wireless_data;
|
||||
#endif /* WIRELESS_EXT */
|
||||
memcpy(dev->dev_addr, ethdev->dev_addr, dev->addr_len);
|
||||
err = register_netdev(dev);
|
||||
if (err<0) {
|
||||
@ -2755,11 +2746,9 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
|
||||
dev->set_multicast_list = &airo_set_multicast_list;
|
||||
dev->set_mac_address = &airo_set_mac_address;
|
||||
dev->do_ioctl = &airo_ioctl;
|
||||
#ifdef WIRELESS_EXT
|
||||
dev->wireless_handlers = &airo_handler_def;
|
||||
ai->wireless_data.spy_data = &ai->spy_data;
|
||||
dev->wireless_data = &ai->wireless_data;
|
||||
#endif /* WIRELESS_EXT */
|
||||
dev->change_mtu = &airo_change_mtu;
|
||||
dev->open = &airo_open;
|
||||
dev->stop = &airo_close;
|
||||
@ -5515,12 +5504,13 @@ static int airo_pci_resume(struct pci_dev *pdev)
|
||||
struct net_device *dev = pci_get_drvdata(pdev);
|
||||
struct airo_info *ai = dev->priv;
|
||||
Resp rsp;
|
||||
pci_power_t prev_state = pdev->current_state;
|
||||
|
||||
pci_set_power_state(pdev, 0);
|
||||
pci_set_power_state(pdev, PCI_D0);
|
||||
pci_restore_state(pdev);
|
||||
pci_enable_wake(pdev, pci_choose_state(pdev, ai->power), 0);
|
||||
pci_enable_wake(pdev, PCI_D0, 0);
|
||||
|
||||
if (ai->power.event > 1) {
|
||||
if (prev_state != PCI_D1) {
|
||||
reset_card(dev, 0);
|
||||
mpi_init_descriptors(ai);
|
||||
setup_card(ai, dev->dev_addr, 0);
|
||||
@ -5598,7 +5588,6 @@ static void __exit airo_cleanup_module( void )
|
||||
remove_proc_entry("aironet", proc_root_driver);
|
||||
}
|
||||
|
||||
#ifdef WIRELESS_EXT
|
||||
/*
|
||||
* Initial Wireless Extension code for Aironet driver by :
|
||||
* Jean Tourrilhes <jt@hpl.hp.com> - HPL - 17 November 00
|
||||
@ -7107,8 +7096,6 @@ static const struct iw_handler_def airo_handler_def =
|
||||
.get_wireless_stats = airo_get_wireless_stats,
|
||||
};
|
||||
|
||||
#endif /* WIRELESS_EXT */
|
||||
|
||||
/*
|
||||
* This defines the configuration part of the Wireless Extensions
|
||||
* Note : irq and spinlock protection will occur in the subroutines
|
||||
@ -7187,7 +7174,6 @@ static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
|
||||
return rc;
|
||||
}
|
||||
|
||||
#ifdef WIRELESS_EXT
|
||||
/*
|
||||
* Get the Wireless stats out of the driver
|
||||
* Note : irq and spinlock protection will occur in the subroutines
|
||||
@ -7260,7 +7246,6 @@ static struct iw_statistics *airo_get_wireless_stats(struct net_device *dev)
|
||||
|
||||
return &local->wstats;
|
||||
}
|
||||
#endif /* WIRELESS_EXT */
|
||||
|
||||
#ifdef CISCO_EXT
|
||||
/*
|
||||
|
@ -15,28 +15,11 @@
|
||||
#define PFX DRIVER_NAME ": "
|
||||
|
||||
#include <linux/config.h>
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/if_arp.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/wireless.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/current.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <linux/delay.h>
|
||||
#include <asm/pmac_feature.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
#include "orinoco.h"
|
||||
|
||||
|
@ -618,12 +618,12 @@ static int atmel_lock_mac(struct atmel_private *priv);
|
||||
static void atmel_wmem32(struct atmel_private *priv, u16 pos, u32 data);
|
||||
static void atmel_command_irq(struct atmel_private *priv);
|
||||
static int atmel_validate_channel(struct atmel_private *priv, int channel);
|
||||
static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_hdr *header,
|
||||
static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_hdr_4addr *header,
|
||||
u16 frame_len, u8 rssi);
|
||||
static void atmel_management_timer(u_long a);
|
||||
static void atmel_send_command(struct atmel_private *priv, int command, void *cmd, int cmd_size);
|
||||
static int atmel_send_command_wait(struct atmel_private *priv, int command, void *cmd, int cmd_size);
|
||||
static void atmel_transmit_management_frame(struct atmel_private *priv, struct ieee80211_hdr *header,
|
||||
static void atmel_transmit_management_frame(struct atmel_private *priv, struct ieee80211_hdr_4addr *header,
|
||||
u8 *body, int body_len);
|
||||
|
||||
static u8 atmel_get_mib8(struct atmel_private *priv, u8 type, u8 index);
|
||||
@ -827,7 +827,7 @@ static void tx_update_descriptor(struct atmel_private *priv, int is_bcast, u16 l
|
||||
static int start_tx (struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
struct atmel_private *priv = netdev_priv(dev);
|
||||
struct ieee80211_hdr header;
|
||||
struct ieee80211_hdr_4addr header;
|
||||
unsigned long flags;
|
||||
u16 buff, frame_ctl, len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
|
||||
u8 SNAP_RFC1024[6] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
|
||||
@ -902,7 +902,7 @@ static int start_tx (struct sk_buff *skb, struct net_device *dev)
|
||||
}
|
||||
|
||||
static void atmel_transmit_management_frame(struct atmel_private *priv,
|
||||
struct ieee80211_hdr *header,
|
||||
struct ieee80211_hdr_4addr *header,
|
||||
u8 *body, int body_len)
|
||||
{
|
||||
u16 buff;
|
||||
@ -917,7 +917,7 @@ static void atmel_transmit_management_frame(struct atmel_private *priv,
|
||||
tx_update_descriptor(priv, header->addr1[0] & 0x01, len, buff, TX_PACKET_TYPE_MGMT);
|
||||
}
|
||||
|
||||
static void fast_rx_path(struct atmel_private *priv, struct ieee80211_hdr *header,
|
||||
static void fast_rx_path(struct atmel_private *priv, struct ieee80211_hdr_4addr *header,
|
||||
u16 msdu_size, u16 rx_packet_loc, u32 crc)
|
||||
{
|
||||
/* fast path: unfragmented packet copy directly into skbuf */
|
||||
@ -990,7 +990,7 @@ static int probe_crc(struct atmel_private *priv, u16 packet_loc, u16 msdu_size)
|
||||
return (crc ^ 0xffffffff) == netcrc;
|
||||
}
|
||||
|
||||
static void frag_rx_path(struct atmel_private *priv, struct ieee80211_hdr *header,
|
||||
static void frag_rx_path(struct atmel_private *priv, struct ieee80211_hdr_4addr *header,
|
||||
u16 msdu_size, u16 rx_packet_loc, u32 crc, u16 seq_no, u8 frag_no, int more_frags)
|
||||
{
|
||||
u8 mac4[6];
|
||||
@ -1082,7 +1082,7 @@ static void frag_rx_path(struct atmel_private *priv, struct ieee80211_hdr *heade
|
||||
static void rx_done_irq(struct atmel_private *priv)
|
||||
{
|
||||
int i;
|
||||
struct ieee80211_hdr header;
|
||||
struct ieee80211_hdr_4addr header;
|
||||
|
||||
for (i = 0;
|
||||
atmel_rmem8(priv, atmel_rx(priv, RX_DESC_FLAGS_OFFSET, priv->rx_desc_head)) == RX_DESC_FLAG_VALID &&
|
||||
@ -2650,7 +2650,7 @@ static void handle_beacon_probe(struct atmel_private *priv, u16 capability, u8 c
|
||||
|
||||
static void send_authentication_request(struct atmel_private *priv, u8 *challenge, int challenge_len)
|
||||
{
|
||||
struct ieee80211_hdr header;
|
||||
struct ieee80211_hdr_4addr header;
|
||||
struct auth_body auth;
|
||||
|
||||
header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH);
|
||||
@ -2688,7 +2688,7 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc)
|
||||
{
|
||||
u8 *ssid_el_p;
|
||||
int bodysize;
|
||||
struct ieee80211_hdr header;
|
||||
struct ieee80211_hdr_4addr header;
|
||||
struct ass_req_format {
|
||||
u16 capability;
|
||||
u16 listen_interval;
|
||||
@ -2738,7 +2738,7 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc)
|
||||
atmel_transmit_management_frame(priv, &header, (void *)&body, bodysize);
|
||||
}
|
||||
|
||||
static int is_frame_from_current_bss(struct atmel_private *priv, struct ieee80211_hdr *header)
|
||||
static int is_frame_from_current_bss(struct atmel_private *priv, struct ieee80211_hdr_4addr *header)
|
||||
{
|
||||
if (le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_FROMDS)
|
||||
return memcmp(header->addr3, priv->CurrentBSSID, 6) == 0;
|
||||
@ -2788,7 +2788,7 @@ static int retrieve_bss(struct atmel_private *priv)
|
||||
}
|
||||
|
||||
|
||||
static void store_bss_info(struct atmel_private *priv, struct ieee80211_hdr *header,
|
||||
static void store_bss_info(struct atmel_private *priv, struct ieee80211_hdr_4addr *header,
|
||||
u16 capability, u16 beacon_period, u8 channel, u8 rssi,
|
||||
u8 ssid_len, u8 *ssid, int is_beacon)
|
||||
{
|
||||
@ -3072,7 +3072,7 @@ static void atmel_smooth_qual(struct atmel_private *priv)
|
||||
}
|
||||
|
||||
/* deals with incoming managment frames. */
|
||||
static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_hdr *header,
|
||||
static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_hdr_4addr *header,
|
||||
u16 frame_len, u8 rssi)
|
||||
{
|
||||
u16 subtype;
|
||||
|
@ -39,17 +39,10 @@
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/threads.h>
|
||||
#include <linux/smp.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/net.h>
|
||||
#include <asm/errno.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include "hermes.h"
|
||||
|
||||
|
@ -30,9 +30,8 @@
|
||||
* access to the hermes_t structure, and to the hardware
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
/*
|
||||
* Limits and constants
|
||||
@ -192,13 +191,13 @@
|
||||
#define HERMES_RXSTAT_WMP (0x6000) /* Wavelan-II Management Protocol frame */
|
||||
|
||||
struct hermes_tx_descriptor {
|
||||
u16 status;
|
||||
u16 reserved1;
|
||||
u16 reserved2;
|
||||
u32 sw_support;
|
||||
__le16 status;
|
||||
__le16 reserved1;
|
||||
__le16 reserved2;
|
||||
__le32 sw_support;
|
||||
u8 retry_count;
|
||||
u8 tx_rate;
|
||||
u16 tx_control;
|
||||
__le16 tx_control;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define HERMES_TXSTAT_RETRYERR (0x0001)
|
||||
@ -222,60 +221,60 @@ struct hermes_tx_descriptor {
|
||||
#define HERMES_INQ_SEC_STAT_AGERE (0xF202)
|
||||
|
||||
struct hermes_tallies_frame {
|
||||
u16 TxUnicastFrames;
|
||||
u16 TxMulticastFrames;
|
||||
u16 TxFragments;
|
||||
u16 TxUnicastOctets;
|
||||
u16 TxMulticastOctets;
|
||||
u16 TxDeferredTransmissions;
|
||||
u16 TxSingleRetryFrames;
|
||||
u16 TxMultipleRetryFrames;
|
||||
u16 TxRetryLimitExceeded;
|
||||
u16 TxDiscards;
|
||||
u16 RxUnicastFrames;
|
||||
u16 RxMulticastFrames;
|
||||
u16 RxFragments;
|
||||
u16 RxUnicastOctets;
|
||||
u16 RxMulticastOctets;
|
||||
u16 RxFCSErrors;
|
||||
u16 RxDiscards_NoBuffer;
|
||||
u16 TxDiscardsWrongSA;
|
||||
u16 RxWEPUndecryptable;
|
||||
u16 RxMsgInMsgFragments;
|
||||
u16 RxMsgInBadMsgFragments;
|
||||
__le16 TxUnicastFrames;
|
||||
__le16 TxMulticastFrames;
|
||||
__le16 TxFragments;
|
||||
__le16 TxUnicastOctets;
|
||||
__le16 TxMulticastOctets;
|
||||
__le16 TxDeferredTransmissions;
|
||||
__le16 TxSingleRetryFrames;
|
||||
__le16 TxMultipleRetryFrames;
|
||||
__le16 TxRetryLimitExceeded;
|
||||
__le16 TxDiscards;
|
||||
__le16 RxUnicastFrames;
|
||||
__le16 RxMulticastFrames;
|
||||
__le16 RxFragments;
|
||||
__le16 RxUnicastOctets;
|
||||
__le16 RxMulticastOctets;
|
||||
__le16 RxFCSErrors;
|
||||
__le16 RxDiscards_NoBuffer;
|
||||
__le16 TxDiscardsWrongSA;
|
||||
__le16 RxWEPUndecryptable;
|
||||
__le16 RxMsgInMsgFragments;
|
||||
__le16 RxMsgInBadMsgFragments;
|
||||
/* Those last are probably not available in very old firmwares */
|
||||
u16 RxDiscards_WEPICVError;
|
||||
u16 RxDiscards_WEPExcluded;
|
||||
__le16 RxDiscards_WEPICVError;
|
||||
__le16 RxDiscards_WEPExcluded;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Grabbed from wlan-ng - Thanks Mark... - Jean II
|
||||
* This is the result of a scan inquiry command */
|
||||
/* Structure describing info about an Access Point */
|
||||
struct prism2_scan_apinfo {
|
||||
u16 channel; /* Channel where the AP sits */
|
||||
u16 noise; /* Noise level */
|
||||
u16 level; /* Signal level */
|
||||
__le16 channel; /* Channel where the AP sits */
|
||||
__le16 noise; /* Noise level */
|
||||
__le16 level; /* Signal level */
|
||||
u8 bssid[ETH_ALEN]; /* MAC address of the Access Point */
|
||||
u16 beacon_interv; /* Beacon interval */
|
||||
u16 capabilities; /* Capabilities */
|
||||
u16 essid_len; /* ESSID length */
|
||||
__le16 beacon_interv; /* Beacon interval */
|
||||
__le16 capabilities; /* Capabilities */
|
||||
__le16 essid_len; /* ESSID length */
|
||||
u8 essid[32]; /* ESSID of the network */
|
||||
u8 rates[10]; /* Bit rate supported */
|
||||
u16 proberesp_rate; /* Data rate of the response frame */
|
||||
u16 atim; /* ATIM window time, Kus (hostscan only) */
|
||||
__le16 proberesp_rate; /* Data rate of the response frame */
|
||||
__le16 atim; /* ATIM window time, Kus (hostscan only) */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Same stuff for the Lucent/Agere card.
|
||||
* Thanks to h1kari <h1kari AT dachb0den.com> - Jean II */
|
||||
struct agere_scan_apinfo {
|
||||
u16 channel; /* Channel where the AP sits */
|
||||
u16 noise; /* Noise level */
|
||||
u16 level; /* Signal level */
|
||||
__le16 channel; /* Channel where the AP sits */
|
||||
__le16 noise; /* Noise level */
|
||||
__le16 level; /* Signal level */
|
||||
u8 bssid[ETH_ALEN]; /* MAC address of the Access Point */
|
||||
u16 beacon_interv; /* Beacon interval */
|
||||
u16 capabilities; /* Capabilities */
|
||||
__le16 beacon_interv; /* Beacon interval */
|
||||
__le16 capabilities; /* Capabilities */
|
||||
/* bits: 0-ess, 1-ibss, 4-privacy [wep] */
|
||||
u16 essid_len; /* ESSID length */
|
||||
__le16 essid_len; /* ESSID length */
|
||||
u8 essid[32]; /* ESSID of the network */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
@ -283,16 +282,16 @@ struct agere_scan_apinfo {
|
||||
struct symbol_scan_apinfo {
|
||||
u8 channel; /* Channel where the AP sits */
|
||||
u8 unknown1; /* 8 in 2.9x and 3.9x f/w, 0 otherwise */
|
||||
u16 noise; /* Noise level */
|
||||
u16 level; /* Signal level */
|
||||
__le16 noise; /* Noise level */
|
||||
__le16 level; /* Signal level */
|
||||
u8 bssid[ETH_ALEN]; /* MAC address of the Access Point */
|
||||
u16 beacon_interv; /* Beacon interval */
|
||||
u16 capabilities; /* Capabilities */
|
||||
__le16 beacon_interv; /* Beacon interval */
|
||||
__le16 capabilities; /* Capabilities */
|
||||
/* bits: 0-ess, 1-ibss, 4-privacy [wep] */
|
||||
u16 essid_len; /* ESSID length */
|
||||
__le16 essid_len; /* ESSID length */
|
||||
u8 essid[32]; /* ESSID of the network */
|
||||
u16 rates[5]; /* Bit rate supported */
|
||||
u16 basic_rates; /* Basic rates bitmask */
|
||||
__le16 rates[5]; /* Bit rate supported */
|
||||
__le16 basic_rates; /* Basic rates bitmask */
|
||||
u8 unknown2[6]; /* Always FF:FF:FF:FF:00:00 */
|
||||
u8 unknown3[8]; /* Always 0, appeared in f/w 3.91-68 */
|
||||
} __attribute__ ((packed));
|
||||
@ -312,7 +311,7 @@ union hermes_scan_info {
|
||||
#define HERMES_LINKSTATUS_ASSOC_FAILED (0x0006)
|
||||
|
||||
struct hermes_linkstatus {
|
||||
u16 linkstatus; /* Link status */
|
||||
__le16 linkstatus; /* Link status */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct hermes_response {
|
||||
@ -321,8 +320,8 @@ struct hermes_response {
|
||||
|
||||
/* "ID" structure - used for ESSID and station nickname */
|
||||
struct hermes_idstring {
|
||||
u16 len;
|
||||
u16 val[16];
|
||||
__le16 len;
|
||||
__le16 val[16];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct hermes_multicast {
|
||||
@ -447,7 +446,7 @@ static inline void hermes_clear_words(struct hermes *hw, int off, unsigned count
|
||||
|
||||
static inline int hermes_read_wordrec(hermes_t *hw, int bap, u16 rid, u16 *word)
|
||||
{
|
||||
u16 rec;
|
||||
__le16 rec;
|
||||
int err;
|
||||
|
||||
err = HERMES_READ_RECORD(hw, bap, rid, &rec);
|
||||
@ -457,7 +456,7 @@ static inline int hermes_read_wordrec(hermes_t *hw, int bap, u16 rid, u16 *word)
|
||||
|
||||
static inline int hermes_write_wordrec(hermes_t *hw, int bap, u16 rid, u16 word)
|
||||
{
|
||||
u16 rec = cpu_to_le16(word);
|
||||
__le16 rec = cpu_to_le16(word);
|
||||
return HERMES_WRITE_RECORD(hw, bap, rid, &rec);
|
||||
}
|
||||
|
||||
|
@ -716,9 +716,6 @@ static int prism2_close(struct net_device *dev)
|
||||
hostap_deauth_all_stas(dev, local->ap, 1);
|
||||
#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
|
||||
|
||||
if (local->func->dev_close && local->func->dev_close(local))
|
||||
return 0;
|
||||
|
||||
if (dev == local->dev) {
|
||||
local->func->hw_shutdown(dev, HOSTAP_HW_ENABLE_CMDCOMPL);
|
||||
}
|
||||
@ -766,9 +763,6 @@ static int prism2_open(struct net_device *dev)
|
||||
local->hw_downloading)
|
||||
return -ENODEV;
|
||||
|
||||
if (local->func->dev_open && local->func->dev_open(local))
|
||||
return 1;
|
||||
|
||||
if (!try_module_get(local->hw_module))
|
||||
return -ENODEV;
|
||||
local->num_dev_open++;
|
||||
|
@ -6,10 +6,10 @@
|
||||
void hostap_dump_rx_80211(const char *name, struct sk_buff *skb,
|
||||
struct hostap_80211_rx_status *rx_stats)
|
||||
{
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct ieee80211_hdr_4addr *hdr;
|
||||
u16 fc;
|
||||
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
hdr = (struct ieee80211_hdr_4addr *) skb->data;
|
||||
|
||||
printk(KERN_DEBUG "%s: RX signal=%d noise=%d rate=%d len=%d "
|
||||
"jiffies=%ld\n",
|
||||
@ -51,7 +51,7 @@ int prism2_rx_80211(struct net_device *dev, struct sk_buff *skb,
|
||||
int hdrlen, phdrlen, head_need, tail_need;
|
||||
u16 fc;
|
||||
int prism_header, ret;
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct ieee80211_hdr_4addr *hdr;
|
||||
|
||||
iface = netdev_priv(dev);
|
||||
local = iface->local;
|
||||
@ -70,7 +70,7 @@ int prism2_rx_80211(struct net_device *dev, struct sk_buff *skb,
|
||||
phdrlen = 0;
|
||||
}
|
||||
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
hdr = (struct ieee80211_hdr_4addr *) skb->data;
|
||||
fc = le16_to_cpu(hdr->frame_ctl);
|
||||
|
||||
if (type == PRISM2_RX_MGMT && (fc & IEEE80211_FCTL_VERS)) {
|
||||
@ -215,7 +215,7 @@ prism2_frag_cache_find(local_info_t *local, unsigned int seq,
|
||||
|
||||
/* Called only as a tasklet (software IRQ) */
|
||||
static struct sk_buff *
|
||||
prism2_frag_cache_get(local_info_t *local, struct ieee80211_hdr *hdr)
|
||||
prism2_frag_cache_get(local_info_t *local, struct ieee80211_hdr_4addr *hdr)
|
||||
{
|
||||
struct sk_buff *skb = NULL;
|
||||
u16 sc;
|
||||
@ -229,7 +229,7 @@ prism2_frag_cache_get(local_info_t *local, struct ieee80211_hdr *hdr)
|
||||
if (frag == 0) {
|
||||
/* Reserve enough space to fit maximum frame length */
|
||||
skb = dev_alloc_skb(local->dev->mtu +
|
||||
sizeof(struct ieee80211_hdr) +
|
||||
sizeof(struct ieee80211_hdr_4addr) +
|
||||
8 /* LLC */ +
|
||||
2 /* alignment */ +
|
||||
8 /* WEP */ + ETH_ALEN /* WDS */);
|
||||
@ -267,7 +267,7 @@ prism2_frag_cache_get(local_info_t *local, struct ieee80211_hdr *hdr)
|
||||
|
||||
/* Called only as a tasklet (software IRQ) */
|
||||
static int prism2_frag_cache_invalidate(local_info_t *local,
|
||||
struct ieee80211_hdr *hdr)
|
||||
struct ieee80211_hdr_4addr *hdr)
|
||||
{
|
||||
u16 sc;
|
||||
unsigned int seq;
|
||||
@ -441,7 +441,7 @@ hostap_rx_frame_mgmt(local_info_t *local, struct sk_buff *skb,
|
||||
u16 stype)
|
||||
{
|
||||
if (local->iw_mode == IW_MODE_MASTER) {
|
||||
hostap_update_sta_ps(local, (struct ieee80211_hdr *)
|
||||
hostap_update_sta_ps(local, (struct ieee80211_hdr_4addr *)
|
||||
skb->data);
|
||||
}
|
||||
|
||||
@ -520,7 +520,7 @@ static inline struct net_device *prism2_rx_get_wds(local_info_t *local,
|
||||
|
||||
|
||||
static inline int
|
||||
hostap_rx_frame_wds(local_info_t *local, struct ieee80211_hdr *hdr,
|
||||
hostap_rx_frame_wds(local_info_t *local, struct ieee80211_hdr_4addr *hdr,
|
||||
u16 fc, struct net_device **wds)
|
||||
{
|
||||
/* FIX: is this really supposed to accept WDS frames only in Master
|
||||
@ -579,13 +579,13 @@ static int hostap_is_eapol_frame(local_info_t *local, struct sk_buff *skb)
|
||||
{
|
||||
struct net_device *dev = local->dev;
|
||||
u16 fc, ethertype;
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct ieee80211_hdr_4addr *hdr;
|
||||
u8 *pos;
|
||||
|
||||
if (skb->len < 24)
|
||||
return 0;
|
||||
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
hdr = (struct ieee80211_hdr_4addr *) skb->data;
|
||||
fc = le16_to_cpu(hdr->frame_ctl);
|
||||
|
||||
/* check that the frame is unicast frame to us */
|
||||
@ -619,13 +619,13 @@ static inline int
|
||||
hostap_rx_frame_decrypt(local_info_t *local, struct sk_buff *skb,
|
||||
struct ieee80211_crypt_data *crypt)
|
||||
{
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct ieee80211_hdr_4addr *hdr;
|
||||
int res, hdrlen;
|
||||
|
||||
if (crypt == NULL || crypt->ops->decrypt_mpdu == NULL)
|
||||
return 0;
|
||||
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
hdr = (struct ieee80211_hdr_4addr *) skb->data;
|
||||
hdrlen = hostap_80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
|
||||
|
||||
if (local->tkip_countermeasures &&
|
||||
@ -658,13 +658,13 @@ static inline int
|
||||
hostap_rx_frame_decrypt_msdu(local_info_t *local, struct sk_buff *skb,
|
||||
int keyidx, struct ieee80211_crypt_data *crypt)
|
||||
{
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct ieee80211_hdr_4addr *hdr;
|
||||
int res, hdrlen;
|
||||
|
||||
if (crypt == NULL || crypt->ops->decrypt_msdu == NULL)
|
||||
return 0;
|
||||
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
hdr = (struct ieee80211_hdr_4addr *) skb->data;
|
||||
hdrlen = hostap_80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
|
||||
|
||||
atomic_inc(&crypt->refcnt);
|
||||
@ -689,7 +689,7 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
|
||||
{
|
||||
struct hostap_interface *iface;
|
||||
local_info_t *local;
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct ieee80211_hdr_4addr *hdr;
|
||||
size_t hdrlen;
|
||||
u16 fc, type, stype, sc;
|
||||
struct net_device *wds = NULL;
|
||||
@ -716,7 +716,7 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
|
||||
dev = local->ddev;
|
||||
iface = netdev_priv(dev);
|
||||
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
hdr = (struct ieee80211_hdr_4addr *) skb->data;
|
||||
stats = hostap_get_stats(dev);
|
||||
|
||||
if (skb->len < 10)
|
||||
@ -737,7 +737,8 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
|
||||
struct iw_quality wstats;
|
||||
wstats.level = rx_stats->signal;
|
||||
wstats.noise = rx_stats->noise;
|
||||
wstats.updated = 6; /* No qual value */
|
||||
wstats.updated = IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_UPDATED
|
||||
| IW_QUAL_QUAL_INVALID | IW_QUAL_DBM;
|
||||
/* Update spy records */
|
||||
wireless_spy_update(dev, hdr->addr2, &wstats);
|
||||
}
|
||||
@ -889,7 +890,7 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
|
||||
if (local->host_decrypt && (fc & IEEE80211_FCTL_PROTECTED) &&
|
||||
(keyidx = hostap_rx_frame_decrypt(local, skb, crypt)) < 0)
|
||||
goto rx_dropped;
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
hdr = (struct ieee80211_hdr_4addr *) skb->data;
|
||||
|
||||
/* skb: hdr + (possibly fragmented) plaintext payload */
|
||||
|
||||
@ -941,7 +942,7 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
|
||||
/* this was the last fragment and the frame will be
|
||||
* delivered, so remove skb from fragment cache */
|
||||
skb = frag_skb;
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
hdr = (struct ieee80211_hdr_4addr *) skb->data;
|
||||
prism2_frag_cache_invalidate(local, hdr);
|
||||
}
|
||||
|
||||
@ -952,7 +953,7 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
|
||||
hostap_rx_frame_decrypt_msdu(local, skb, keyidx, crypt))
|
||||
goto rx_dropped;
|
||||
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
hdr = (struct ieee80211_hdr_4addr *) skb->data;
|
||||
if (crypt && !(fc & IEEE80211_FCTL_PROTECTED) && !local->open_wep) {
|
||||
if (local->ieee_802_1x &&
|
||||
hostap_is_eapol_frame(local, skb)) {
|
||||
|
@ -1,9 +1,9 @@
|
||||
void hostap_dump_tx_80211(const char *name, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct ieee80211_hdr_4addr *hdr;
|
||||
u16 fc;
|
||||
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
hdr = (struct ieee80211_hdr_4addr *) skb->data;
|
||||
|
||||
printk(KERN_DEBUG "%s: TX len=%d jiffies=%ld\n",
|
||||
name, skb->len, jiffies);
|
||||
@ -41,7 +41,7 @@ int hostap_data_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
struct hostap_interface *iface;
|
||||
local_info_t *local;
|
||||
int need_headroom, need_tailroom = 0;
|
||||
struct ieee80211_hdr hdr;
|
||||
struct ieee80211_hdr_4addr hdr;
|
||||
u16 fc, ethertype = 0;
|
||||
enum {
|
||||
WDS_NO = 0, WDS_OWN_FRAME, WDS_COMPLIANT_FRAME
|
||||
@ -244,7 +244,7 @@ int hostap_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
struct hostap_interface *iface;
|
||||
local_info_t *local;
|
||||
struct hostap_skb_tx_data *meta;
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct ieee80211_hdr_4addr *hdr;
|
||||
u16 fc;
|
||||
|
||||
iface = netdev_priv(dev);
|
||||
@ -266,7 +266,7 @@ int hostap_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
meta->iface = iface;
|
||||
|
||||
if (skb->len >= IEEE80211_DATA_HDR3_LEN + sizeof(rfc1042_header) + 2) {
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
hdr = (struct ieee80211_hdr_4addr *) skb->data;
|
||||
fc = le16_to_cpu(hdr->frame_ctl);
|
||||
if (WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA &&
|
||||
WLAN_FC_GET_STYPE(fc) == IEEE80211_STYPE_DATA) {
|
||||
@ -289,7 +289,7 @@ struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb,
|
||||
{
|
||||
struct hostap_interface *iface;
|
||||
local_info_t *local;
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct ieee80211_hdr_4addr *hdr;
|
||||
u16 fc;
|
||||
int hdr_len, res;
|
||||
|
||||
@ -303,7 +303,7 @@ struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb,
|
||||
|
||||
if (local->tkip_countermeasures &&
|
||||
crypt && crypt->ops && strcmp(crypt->ops->name, "TKIP") == 0) {
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
hdr = (struct ieee80211_hdr_4addr *) skb->data;
|
||||
if (net_ratelimit()) {
|
||||
printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
|
||||
"TX packet to " MACSTR "\n",
|
||||
@ -317,15 +317,15 @@ struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb,
|
||||
if (skb == NULL)
|
||||
return NULL;
|
||||
|
||||
if ((skb_headroom(skb) < crypt->ops->extra_prefix_len ||
|
||||
skb_tailroom(skb) < crypt->ops->extra_postfix_len) &&
|
||||
pskb_expand_head(skb, crypt->ops->extra_prefix_len,
|
||||
crypt->ops->extra_postfix_len, GFP_ATOMIC)) {
|
||||
if ((skb_headroom(skb) < crypt->ops->extra_mpdu_prefix_len ||
|
||||
skb_tailroom(skb) < crypt->ops->extra_mpdu_postfix_len) &&
|
||||
pskb_expand_head(skb, crypt->ops->extra_mpdu_prefix_len,
|
||||
crypt->ops->extra_mpdu_postfix_len, GFP_ATOMIC)) {
|
||||
kfree_skb(skb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
hdr = (struct ieee80211_hdr_4addr *) skb->data;
|
||||
fc = le16_to_cpu(hdr->frame_ctl);
|
||||
hdr_len = hostap_80211_get_hdrlen(fc);
|
||||
|
||||
@ -360,7 +360,7 @@ int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
ap_tx_ret tx_ret;
|
||||
struct hostap_skb_tx_data *meta;
|
||||
int no_encrypt = 0;
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct ieee80211_hdr_4addr *hdr;
|
||||
|
||||
iface = netdev_priv(dev);
|
||||
local = iface->local;
|
||||
@ -403,7 +403,7 @@ int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
tx_ret = hostap_handle_sta_tx(local, &tx);
|
||||
skb = tx.skb;
|
||||
meta = (struct hostap_skb_tx_data *) skb->cb;
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
hdr = (struct ieee80211_hdr_4addr *) skb->data;
|
||||
fc = le16_to_cpu(hdr->frame_ctl);
|
||||
switch (tx_ret) {
|
||||
case AP_TX_CONTINUE:
|
||||
|
@ -591,14 +591,14 @@ static void hostap_ap_tx_cb(struct sk_buff *skb, int ok, void *data)
|
||||
{
|
||||
struct ap_data *ap = data;
|
||||
u16 fc;
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct ieee80211_hdr_4addr *hdr;
|
||||
|
||||
if (!ap->local->hostapd || !ap->local->apdev) {
|
||||
dev_kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
hdr = (struct ieee80211_hdr_4addr *) skb->data;
|
||||
fc = le16_to_cpu(hdr->frame_ctl);
|
||||
|
||||
/* Pass the TX callback frame to the hostapd; use 802.11 header version
|
||||
@ -623,7 +623,7 @@ static void hostap_ap_tx_cb_auth(struct sk_buff *skb, int ok, void *data)
|
||||
{
|
||||
struct ap_data *ap = data;
|
||||
struct net_device *dev = ap->local->dev;
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct ieee80211_hdr_4addr *hdr;
|
||||
u16 fc, *pos, auth_alg, auth_transaction, status;
|
||||
struct sta_info *sta = NULL;
|
||||
char *txt = NULL;
|
||||
@ -633,7 +633,7 @@ static void hostap_ap_tx_cb_auth(struct sk_buff *skb, int ok, void *data)
|
||||
return;
|
||||
}
|
||||
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
hdr = (struct ieee80211_hdr_4addr *) skb->data;
|
||||
fc = le16_to_cpu(hdr->frame_ctl);
|
||||
if (WLAN_FC_GET_TYPE(fc) != IEEE80211_FTYPE_MGMT ||
|
||||
WLAN_FC_GET_STYPE(fc) != IEEE80211_STYPE_AUTH ||
|
||||
@ -692,7 +692,7 @@ static void hostap_ap_tx_cb_assoc(struct sk_buff *skb, int ok, void *data)
|
||||
{
|
||||
struct ap_data *ap = data;
|
||||
struct net_device *dev = ap->local->dev;
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct ieee80211_hdr_4addr *hdr;
|
||||
u16 fc, *pos, status;
|
||||
struct sta_info *sta = NULL;
|
||||
char *txt = NULL;
|
||||
@ -702,7 +702,7 @@ static void hostap_ap_tx_cb_assoc(struct sk_buff *skb, int ok, void *data)
|
||||
return;
|
||||
}
|
||||
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
hdr = (struct ieee80211_hdr_4addr *) skb->data;
|
||||
fc = le16_to_cpu(hdr->frame_ctl);
|
||||
if (WLAN_FC_GET_TYPE(fc) != IEEE80211_FTYPE_MGMT ||
|
||||
(WLAN_FC_GET_STYPE(fc) != IEEE80211_STYPE_ASSOC_RESP &&
|
||||
@ -757,12 +757,12 @@ static void hostap_ap_tx_cb_assoc(struct sk_buff *skb, int ok, void *data)
|
||||
static void hostap_ap_tx_cb_poll(struct sk_buff *skb, int ok, void *data)
|
||||
{
|
||||
struct ap_data *ap = data;
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct ieee80211_hdr_4addr *hdr;
|
||||
struct sta_info *sta;
|
||||
|
||||
if (skb->len < 24)
|
||||
goto fail;
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
hdr = (struct ieee80211_hdr_4addr *) skb->data;
|
||||
if (ok) {
|
||||
spin_lock(&ap->sta_table_lock);
|
||||
sta = ap_get_sta(ap, hdr->addr1);
|
||||
@ -918,7 +918,7 @@ static void prism2_send_mgmt(struct net_device *dev,
|
||||
{
|
||||
struct hostap_interface *iface;
|
||||
local_info_t *local;
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct ieee80211_hdr_4addr *hdr;
|
||||
u16 fc;
|
||||
struct sk_buff *skb;
|
||||
struct hostap_skb_tx_data *meta;
|
||||
@ -944,7 +944,7 @@ static void prism2_send_mgmt(struct net_device *dev,
|
||||
|
||||
fc = type_subtype;
|
||||
hdrlen = hostap_80211_get_hdrlen(fc);
|
||||
hdr = (struct ieee80211_hdr *) skb_put(skb, hdrlen);
|
||||
hdr = (struct ieee80211_hdr_4addr *) skb_put(skb, hdrlen);
|
||||
if (body)
|
||||
memcpy(skb_put(skb, body_len), body, body_len);
|
||||
|
||||
@ -1256,14 +1256,14 @@ static char * ap_auth_make_challenge(struct ap_data *ap)
|
||||
}
|
||||
|
||||
skb = dev_alloc_skb(WLAN_AUTH_CHALLENGE_LEN +
|
||||
ap->crypt->extra_prefix_len +
|
||||
ap->crypt->extra_postfix_len);
|
||||
ap->crypt->extra_mpdu_prefix_len +
|
||||
ap->crypt->extra_mpdu_postfix_len);
|
||||
if (skb == NULL) {
|
||||
kfree(tmpbuf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
skb_reserve(skb, ap->crypt->extra_prefix_len);
|
||||
skb_reserve(skb, ap->crypt->extra_mpdu_prefix_len);
|
||||
memset(skb_put(skb, WLAN_AUTH_CHALLENGE_LEN), 0,
|
||||
WLAN_AUTH_CHALLENGE_LEN);
|
||||
if (ap->crypt->encrypt_mpdu(skb, 0, ap->crypt_priv)) {
|
||||
@ -1272,7 +1272,7 @@ static char * ap_auth_make_challenge(struct ap_data *ap)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(tmpbuf, skb->data + ap->crypt->extra_prefix_len,
|
||||
memcpy(tmpbuf, skb->data + ap->crypt->extra_mpdu_prefix_len,
|
||||
WLAN_AUTH_CHALLENGE_LEN);
|
||||
dev_kfree_skb(skb);
|
||||
|
||||
@ -1285,7 +1285,7 @@ static void handle_authen(local_info_t *local, struct sk_buff *skb,
|
||||
struct hostap_80211_rx_status *rx_stats)
|
||||
{
|
||||
struct net_device *dev = local->dev;
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
||||
struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *) skb->data;
|
||||
size_t hdrlen;
|
||||
struct ap_data *ap = local->ap;
|
||||
char body[8 + WLAN_AUTH_CHALLENGE_LEN], *challenge = NULL;
|
||||
@ -1498,7 +1498,7 @@ static void handle_assoc(local_info_t *local, struct sk_buff *skb,
|
||||
struct hostap_80211_rx_status *rx_stats, int reassoc)
|
||||
{
|
||||
struct net_device *dev = local->dev;
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
||||
struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *) skb->data;
|
||||
char body[12], *p, *lpos;
|
||||
int len, left;
|
||||
u16 *pos;
|
||||
@ -1705,7 +1705,7 @@ static void handle_deauth(local_info_t *local, struct sk_buff *skb,
|
||||
struct hostap_80211_rx_status *rx_stats)
|
||||
{
|
||||
struct net_device *dev = local->dev;
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
||||
struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *) skb->data;
|
||||
char *body = (char *) (skb->data + IEEE80211_MGMT_HDR_LEN);
|
||||
int len;
|
||||
u16 reason_code, *pos;
|
||||
@ -1746,7 +1746,7 @@ static void handle_disassoc(local_info_t *local, struct sk_buff *skb,
|
||||
struct hostap_80211_rx_status *rx_stats)
|
||||
{
|
||||
struct net_device *dev = local->dev;
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
||||
struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *) skb->data;
|
||||
char *body = skb->data + IEEE80211_MGMT_HDR_LEN;
|
||||
int len;
|
||||
u16 reason_code, *pos;
|
||||
@ -1784,7 +1784,7 @@ static void handle_disassoc(local_info_t *local, struct sk_buff *skb,
|
||||
|
||||
/* Called only as a scheduled task for pending AP frames. */
|
||||
static void ap_handle_data_nullfunc(local_info_t *local,
|
||||
struct ieee80211_hdr *hdr)
|
||||
struct ieee80211_hdr_4addr *hdr)
|
||||
{
|
||||
struct net_device *dev = local->dev;
|
||||
|
||||
@ -1801,7 +1801,7 @@ static void ap_handle_data_nullfunc(local_info_t *local,
|
||||
|
||||
/* Called only as a scheduled task for pending AP frames. */
|
||||
static void ap_handle_dropped_data(local_info_t *local,
|
||||
struct ieee80211_hdr *hdr)
|
||||
struct ieee80211_hdr_4addr *hdr)
|
||||
{
|
||||
struct net_device *dev = local->dev;
|
||||
struct sta_info *sta;
|
||||
@ -1860,7 +1860,7 @@ static void pspoll_send_buffered(local_info_t *local, struct sta_info *sta,
|
||||
|
||||
/* Called only as a scheduled task for pending AP frames. */
|
||||
static void handle_pspoll(local_info_t *local,
|
||||
struct ieee80211_hdr *hdr,
|
||||
struct ieee80211_hdr_4addr *hdr,
|
||||
struct hostap_80211_rx_status *rx_stats)
|
||||
{
|
||||
struct net_device *dev = local->dev;
|
||||
@ -1979,7 +1979,7 @@ static void handle_wds_oper_queue(void *data)
|
||||
static void handle_beacon(local_info_t *local, struct sk_buff *skb,
|
||||
struct hostap_80211_rx_status *rx_stats)
|
||||
{
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
||||
struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *) skb->data;
|
||||
char *body = skb->data + IEEE80211_MGMT_HDR_LEN;
|
||||
int len, left;
|
||||
u16 *pos, beacon_int, capability;
|
||||
@ -2137,11 +2137,11 @@ static void handle_ap_item(local_info_t *local, struct sk_buff *skb,
|
||||
struct net_device *dev = local->dev;
|
||||
#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
|
||||
u16 fc, type, stype;
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct ieee80211_hdr_4addr *hdr;
|
||||
|
||||
/* FIX: should give skb->len to handler functions and check that the
|
||||
* buffer is long enough */
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
hdr = (struct ieee80211_hdr_4addr *) skb->data;
|
||||
fc = le16_to_cpu(hdr->frame_ctl);
|
||||
type = WLAN_FC_GET_TYPE(fc);
|
||||
stype = WLAN_FC_GET_STYPE(fc);
|
||||
@ -2258,7 +2258,7 @@ void hostap_rx(struct net_device *dev, struct sk_buff *skb,
|
||||
struct hostap_interface *iface;
|
||||
local_info_t *local;
|
||||
u16 fc;
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct ieee80211_hdr_4addr *hdr;
|
||||
|
||||
iface = netdev_priv(dev);
|
||||
local = iface->local;
|
||||
@ -2268,7 +2268,7 @@ void hostap_rx(struct net_device *dev, struct sk_buff *skb,
|
||||
|
||||
local->stats.rx_packets++;
|
||||
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
hdr = (struct ieee80211_hdr_4addr *) skb->data;
|
||||
fc = le16_to_cpu(hdr->frame_ctl);
|
||||
|
||||
if (local->ap->ap_policy == AP_OTHER_AP_SKIP_ALL &&
|
||||
@ -2289,7 +2289,7 @@ void hostap_rx(struct net_device *dev, struct sk_buff *skb,
|
||||
static void schedule_packet_send(local_info_t *local, struct sta_info *sta)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct ieee80211_hdr_4addr *hdr;
|
||||
struct hostap_80211_rx_status rx_stats;
|
||||
|
||||
if (skb_queue_empty(&sta->tx_buf))
|
||||
@ -2302,7 +2302,7 @@ static void schedule_packet_send(local_info_t *local, struct sta_info *sta)
|
||||
return;
|
||||
}
|
||||
|
||||
hdr = (struct ieee80211_hdr *) skb_put(skb, 16);
|
||||
hdr = (struct ieee80211_hdr_4addr *) skb_put(skb, 16);
|
||||
|
||||
/* Generate a fake pspoll frame to start packet delivery */
|
||||
hdr->frame_ctl = __constant_cpu_to_le16(
|
||||
@ -2349,7 +2349,7 @@ static int prism2_ap_get_sta_qual(local_info_t *local, struct sockaddr addr[],
|
||||
qual[count].noise = HFA384X_LEVEL_TO_dBm(sta->last_rx_silence);
|
||||
qual[count].updated = sta->last_rx_updated;
|
||||
|
||||
sta->last_rx_updated = 0;
|
||||
sta->last_rx_updated = IW_QUAL_DBM;
|
||||
|
||||
count++;
|
||||
if (count >= buf_size)
|
||||
@ -2467,7 +2467,7 @@ static int prism2_ap_translate_scan(struct net_device *dev, char *buffer)
|
||||
}
|
||||
#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
|
||||
|
||||
sta->last_rx_updated = 0;
|
||||
sta->last_rx_updated = IW_QUAL_DBM;
|
||||
|
||||
/* To be continued, we should make good use of IWEVCUSTOM */
|
||||
}
|
||||
@ -2685,7 +2685,7 @@ ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx)
|
||||
struct sta_info *sta = NULL;
|
||||
struct sk_buff *skb = tx->skb;
|
||||
int set_tim, ret;
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct ieee80211_hdr_4addr *hdr;
|
||||
struct hostap_skb_tx_data *meta;
|
||||
|
||||
meta = (struct hostap_skb_tx_data *) skb->cb;
|
||||
@ -2694,7 +2694,7 @@ ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx)
|
||||
meta->iface->type == HOSTAP_INTERFACE_STA)
|
||||
goto out;
|
||||
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
hdr = (struct ieee80211_hdr_4addr *) skb->data;
|
||||
|
||||
if (hdr->addr1[0] & 0x01) {
|
||||
/* broadcast/multicast frame - no AP related processing */
|
||||
@ -2821,10 +2821,10 @@ void hostap_handle_sta_release(void *ptr)
|
||||
void hostap_handle_sta_tx_exc(local_info_t *local, struct sk_buff *skb)
|
||||
{
|
||||
struct sta_info *sta;
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct ieee80211_hdr_4addr *hdr;
|
||||
struct hostap_skb_tx_data *meta;
|
||||
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
hdr = (struct ieee80211_hdr_4addr *) skb->data;
|
||||
meta = (struct hostap_skb_tx_data *) skb->cb;
|
||||
|
||||
spin_lock(&local->ap->sta_table_lock);
|
||||
@ -2892,7 +2892,7 @@ static void hostap_update_sta_ps2(local_info_t *local, struct sta_info *sta,
|
||||
|
||||
/* Called only as a tasklet (software IRQ). Called for each RX frame to update
|
||||
* STA power saving state. pwrmgt is a flag from 802.11 frame_ctl field. */
|
||||
int hostap_update_sta_ps(local_info_t *local, struct ieee80211_hdr *hdr)
|
||||
int hostap_update_sta_ps(local_info_t *local, struct ieee80211_hdr_4addr *hdr)
|
||||
{
|
||||
struct sta_info *sta;
|
||||
u16 fc;
|
||||
@ -2925,12 +2925,12 @@ ap_rx_ret hostap_handle_sta_rx(local_info_t *local, struct net_device *dev,
|
||||
int ret;
|
||||
struct sta_info *sta;
|
||||
u16 fc, type, stype;
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct ieee80211_hdr_4addr *hdr;
|
||||
|
||||
if (local->ap == NULL)
|
||||
return AP_RX_CONTINUE;
|
||||
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
hdr = (struct ieee80211_hdr_4addr *) skb->data;
|
||||
|
||||
fc = le16_to_cpu(hdr->frame_ctl);
|
||||
type = WLAN_FC_GET_TYPE(fc);
|
||||
@ -3058,7 +3058,7 @@ ap_rx_ret hostap_handle_sta_rx(local_info_t *local, struct net_device *dev,
|
||||
|
||||
/* Called only as a tasklet (software IRQ) */
|
||||
int hostap_handle_sta_crypto(local_info_t *local,
|
||||
struct ieee80211_hdr *hdr,
|
||||
struct ieee80211_hdr_4addr *hdr,
|
||||
struct ieee80211_crypt_data **crypt,
|
||||
void **sta_ptr)
|
||||
{
|
||||
@ -3160,7 +3160,7 @@ int hostap_add_sta(struct ap_data *ap, u8 *sta_addr)
|
||||
|
||||
/* Called only as a tasklet (software IRQ) */
|
||||
int hostap_update_rx_stats(struct ap_data *ap,
|
||||
struct ieee80211_hdr *hdr,
|
||||
struct ieee80211_hdr_4addr *hdr,
|
||||
struct hostap_80211_rx_status *rx_stats)
|
||||
{
|
||||
struct sta_info *sta;
|
||||
@ -3174,7 +3174,7 @@ int hostap_update_rx_stats(struct ap_data *ap,
|
||||
sta->last_rx_silence = rx_stats->noise;
|
||||
sta->last_rx_signal = rx_stats->signal;
|
||||
sta->last_rx_rate = rx_stats->rate;
|
||||
sta->last_rx_updated = 7;
|
||||
sta->last_rx_updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
|
||||
if (rx_stats->rate == 10)
|
||||
sta->rx_count[0]++;
|
||||
else if (rx_stats->rate == 20)
|
||||
|
@ -233,7 +233,7 @@ struct hostap_tx_data {
|
||||
ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx);
|
||||
void hostap_handle_sta_release(void *ptr);
|
||||
void hostap_handle_sta_tx_exc(local_info_t *local, struct sk_buff *skb);
|
||||
int hostap_update_sta_ps(local_info_t *local, struct ieee80211_hdr *hdr);
|
||||
int hostap_update_sta_ps(local_info_t *local, struct ieee80211_hdr_4addr *hdr);
|
||||
typedef enum {
|
||||
AP_RX_CONTINUE, AP_RX_DROP, AP_RX_EXIT, AP_RX_CONTINUE_NOT_AUTHORIZED
|
||||
} ap_rx_ret;
|
||||
@ -241,13 +241,13 @@ ap_rx_ret hostap_handle_sta_rx(local_info_t *local, struct net_device *dev,
|
||||
struct sk_buff *skb,
|
||||
struct hostap_80211_rx_status *rx_stats,
|
||||
int wds);
|
||||
int hostap_handle_sta_crypto(local_info_t *local, struct ieee80211_hdr *hdr,
|
||||
int hostap_handle_sta_crypto(local_info_t *local, struct ieee80211_hdr_4addr *hdr,
|
||||
struct ieee80211_crypt_data **crypt,
|
||||
void **sta_ptr);
|
||||
int hostap_is_sta_assoc(struct ap_data *ap, u8 *sta_addr);
|
||||
int hostap_is_sta_authorized(struct ap_data *ap, u8 *sta_addr);
|
||||
int hostap_add_sta(struct ap_data *ap, u8 *sta_addr);
|
||||
int hostap_update_rx_stats(struct ap_data *ap, struct ieee80211_hdr *hdr,
|
||||
int hostap_update_rx_stats(struct ap_data *ap, struct ieee80211_hdr_4addr *hdr,
|
||||
struct hostap_80211_rx_status *rx_stats);
|
||||
void hostap_update_rates(local_info_t *local);
|
||||
void hostap_add_wds_links(local_info_t *local);
|
||||
|
@ -492,42 +492,10 @@ static void prism2_pccard_genesis_reset(local_info_t *local, int hcr)
|
||||
}
|
||||
|
||||
|
||||
static int prism2_pccard_dev_open(local_info_t *local)
|
||||
{
|
||||
struct hostap_cs_priv *hw_priv = local->hw_priv;
|
||||
hw_priv->link->open++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int prism2_pccard_dev_close(local_info_t *local)
|
||||
{
|
||||
struct hostap_cs_priv *hw_priv;
|
||||
|
||||
if (local == NULL || local->hw_priv == NULL)
|
||||
return 1;
|
||||
hw_priv = local->hw_priv;
|
||||
if (hw_priv->link == NULL)
|
||||
return 1;
|
||||
|
||||
if (!hw_priv->link->open) {
|
||||
printk(KERN_WARNING "%s: prism2_pccard_dev_close(): "
|
||||
"link not open?!\n", local->dev->name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
hw_priv->link->open--;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static struct prism2_helper_functions prism2_pccard_funcs =
|
||||
{
|
||||
.card_present = prism2_pccard_card_present,
|
||||
.cor_sreset = prism2_pccard_cor_sreset,
|
||||
.dev_open = prism2_pccard_dev_open,
|
||||
.dev_close = prism2_pccard_dev_close,
|
||||
.genesis_reset = prism2_pccard_genesis_reset,
|
||||
.hw_type = HOSTAP_HW_PCCARD,
|
||||
};
|
||||
@ -597,13 +565,14 @@ static void prism2_detach(dev_link_t *link)
|
||||
*linkp = link->next;
|
||||
/* release net devices */
|
||||
if (link->priv) {
|
||||
struct hostap_cs_priv *hw_priv;
|
||||
struct net_device *dev;
|
||||
struct hostap_interface *iface;
|
||||
dev = link->priv;
|
||||
iface = netdev_priv(dev);
|
||||
kfree(iface->local->hw_priv);
|
||||
iface->local->hw_priv = NULL;
|
||||
hw_priv = iface->local->hw_priv;
|
||||
prism2_free_local_data(dev);
|
||||
kfree(hw_priv);
|
||||
}
|
||||
kfree(link);
|
||||
}
|
||||
@ -883,6 +852,13 @@ static int prism2_event(event_t event, int priority,
|
||||
{
|
||||
dev_link_t *link = args->client_data;
|
||||
struct net_device *dev = (struct net_device *) link->priv;
|
||||
int dev_open = 0;
|
||||
|
||||
if (link->state & DEV_CONFIG) {
|
||||
struct hostap_interface *iface = netdev_priv(dev);
|
||||
if (iface && iface->local)
|
||||
dev_open = iface->local->num_dev_open > 0;
|
||||
}
|
||||
|
||||
switch (event) {
|
||||
case CS_EVENT_CARD_INSERTION:
|
||||
@ -911,7 +887,7 @@ static int prism2_event(event_t event, int priority,
|
||||
case CS_EVENT_RESET_PHYSICAL:
|
||||
PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_RESET_PHYSICAL\n", dev_info);
|
||||
if (link->state & DEV_CONFIG) {
|
||||
if (link->open) {
|
||||
if (dev_open) {
|
||||
netif_stop_queue(dev);
|
||||
netif_device_detach(dev);
|
||||
}
|
||||
@ -931,8 +907,8 @@ static int prism2_event(event_t event, int priority,
|
||||
pcmcia_request_configuration(link->handle,
|
||||
&link->conf);
|
||||
prism2_hw_shutdown(dev, 1);
|
||||
prism2_hw_config(dev, link->open ? 0 : 1);
|
||||
if (link->open) {
|
||||
prism2_hw_config(dev, dev_open ? 0 : 1);
|
||||
if (dev_open) {
|
||||
netif_device_attach(dev);
|
||||
netif_start_queue(dev);
|
||||
}
|
||||
|
@ -3322,6 +3322,18 @@ static void prism2_free_local_data(struct net_device *dev)
|
||||
iface = netdev_priv(dev);
|
||||
local = iface->local;
|
||||
|
||||
/* Unregister all netdevs before freeing local data. */
|
||||
list_for_each_safe(ptr, n, &local->hostap_interfaces) {
|
||||
iface = list_entry(ptr, struct hostap_interface, list);
|
||||
if (iface->type == HOSTAP_INTERFACE_MASTER) {
|
||||
/* special handling for this interface below */
|
||||
continue;
|
||||
}
|
||||
hostap_remove_interface(iface->dev, 0, 1);
|
||||
}
|
||||
|
||||
unregister_netdev(local->dev);
|
||||
|
||||
flush_scheduled_work();
|
||||
|
||||
if (timer_pending(&local->crypt_deinit_timer))
|
||||
@ -3382,15 +3394,6 @@ static void prism2_free_local_data(struct net_device *dev)
|
||||
prism2_download_free_data(local->dl_sec);
|
||||
#endif /* PRISM2_DOWNLOAD_SUPPORT */
|
||||
|
||||
list_for_each_safe(ptr, n, &local->hostap_interfaces) {
|
||||
iface = list_entry(ptr, struct hostap_interface, list);
|
||||
if (iface->type == HOSTAP_INTERFACE_MASTER) {
|
||||
/* special handling for this interface below */
|
||||
continue;
|
||||
}
|
||||
hostap_remove_interface(iface->dev, 0, 1);
|
||||
}
|
||||
|
||||
prism2_clear_set_tim_queue(local);
|
||||
|
||||
list_for_each_safe(ptr, n, &local->bss_list) {
|
||||
@ -3403,7 +3406,6 @@ static void prism2_free_local_data(struct net_device *dev)
|
||||
kfree(local->last_scan_results);
|
||||
kfree(local->generic_elem);
|
||||
|
||||
unregister_netdev(local->dev);
|
||||
free_netdev(local->dev);
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,8 @@ static struct iw_statistics *hostap_get_wireless_stats(struct net_device *dev)
|
||||
#endif /* in_atomic */
|
||||
|
||||
if (update && prism2_update_comms_qual(dev) == 0)
|
||||
wstats->qual.updated = 7;
|
||||
wstats->qual.updated = IW_QUAL_ALL_UPDATED |
|
||||
IW_QUAL_DBM;
|
||||
|
||||
wstats->qual.qual = local->comms_qual;
|
||||
wstats->qual.level = local->avg_signal;
|
||||
@ -59,7 +60,7 @@ static struct iw_statistics *hostap_get_wireless_stats(struct net_device *dev)
|
||||
wstats->qual.qual = 0;
|
||||
wstats->qual.level = 0;
|
||||
wstats->qual.noise = 0;
|
||||
wstats->qual.updated = 0;
|
||||
wstats->qual.updated = IW_QUAL_ALL_INVALID;
|
||||
}
|
||||
|
||||
return wstats;
|
||||
@ -1827,13 +1828,6 @@ static char * __prism2_translate_scan(local_info_t *local,
|
||||
iwe.cmd = SIOCGIWAP;
|
||||
iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
|
||||
memcpy(iwe.u.ap_addr.sa_data, bssid, ETH_ALEN);
|
||||
/* FIX:
|
||||
* I do not know how this is possible, but iwe_stream_add_event
|
||||
* seems to re-order memcpy execution so that len is set only
|
||||
* after copying.. Pre-setting len here "fixes" this, but real
|
||||
* problems should be solved (after which these iwe.len
|
||||
* settings could be removed from this function). */
|
||||
iwe.len = IW_EV_ADDR_LEN;
|
||||
current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
|
||||
IW_EV_ADDR_LEN);
|
||||
|
||||
@ -1843,7 +1837,6 @@ static char * __prism2_translate_scan(local_info_t *local,
|
||||
iwe.cmd = SIOCGIWESSID;
|
||||
iwe.u.data.length = ssid_len;
|
||||
iwe.u.data.flags = 1;
|
||||
iwe.len = IW_EV_POINT_LEN + iwe.u.data.length;
|
||||
current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, ssid);
|
||||
|
||||
memset(&iwe, 0, sizeof(iwe));
|
||||
@ -1859,7 +1852,6 @@ static char * __prism2_translate_scan(local_info_t *local,
|
||||
iwe.u.mode = IW_MODE_MASTER;
|
||||
else
|
||||
iwe.u.mode = IW_MODE_ADHOC;
|
||||
iwe.len = IW_EV_UINT_LEN;
|
||||
current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
|
||||
IW_EV_UINT_LEN);
|
||||
}
|
||||
@ -1877,7 +1869,6 @@ static char * __prism2_translate_scan(local_info_t *local,
|
||||
if (chan > 0) {
|
||||
iwe.u.freq.m = freq_list[le16_to_cpu(chan - 1)] * 100000;
|
||||
iwe.u.freq.e = 1;
|
||||
iwe.len = IW_EV_FREQ_LEN;
|
||||
current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
|
||||
IW_EV_FREQ_LEN);
|
||||
}
|
||||
@ -1894,7 +1885,10 @@ static char * __prism2_translate_scan(local_info_t *local,
|
||||
iwe.u.qual.noise =
|
||||
HFA384X_LEVEL_TO_dBm(le16_to_cpu(scan->anl));
|
||||
}
|
||||
iwe.len = IW_EV_QUAL_LEN;
|
||||
iwe.u.qual.updated = IW_QUAL_LEVEL_UPDATED
|
||||
| IW_QUAL_NOISE_UPDATED
|
||||
| IW_QUAL_QUAL_INVALID
|
||||
| IW_QUAL_DBM;
|
||||
current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
|
||||
IW_EV_QUAL_LEN);
|
||||
}
|
||||
@ -1906,7 +1900,6 @@ static char * __prism2_translate_scan(local_info_t *local,
|
||||
else
|
||||
iwe.u.data.flags = IW_ENCODE_DISABLED;
|
||||
iwe.u.data.length = 0;
|
||||
iwe.len = IW_EV_POINT_LEN + iwe.u.data.length;
|
||||
current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, "");
|
||||
|
||||
/* TODO: add SuppRates into BSS table */
|
||||
@ -1930,7 +1923,7 @@ static char * __prism2_translate_scan(local_info_t *local,
|
||||
}
|
||||
|
||||
/* TODO: add BeaconInt,resp_rate,atim into BSS table */
|
||||
buf = kmalloc(MAX_WPA_IE_LEN * 2 + 30, GFP_KERNEL);
|
||||
buf = kmalloc(MAX_WPA_IE_LEN * 2 + 30, GFP_ATOMIC);
|
||||
if (buf && scan) {
|
||||
memset(&iwe, 0, sizeof(iwe));
|
||||
iwe.cmd = IWEVCUSTOM;
|
||||
|
@ -59,11 +59,13 @@ static struct pci_device_id prism2_pci_id_table[] __devinitdata = {
|
||||
static inline void hfa384x_outb_debug(struct net_device *dev, int a, u8 v)
|
||||
{
|
||||
struct hostap_interface *iface;
|
||||
struct hostap_pci_priv *hw_priv;
|
||||
local_info_t *local;
|
||||
unsigned long flags;
|
||||
|
||||
iface = netdev_priv(dev);
|
||||
local = iface->local;
|
||||
hw_priv = local->hw_priv;
|
||||
|
||||
spin_lock_irqsave(&local->lock, flags);
|
||||
prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTB, a, v);
|
||||
@ -74,12 +76,14 @@ static inline void hfa384x_outb_debug(struct net_device *dev, int a, u8 v)
|
||||
static inline u8 hfa384x_inb_debug(struct net_device *dev, int a)
|
||||
{
|
||||
struct hostap_interface *iface;
|
||||
struct hostap_pci_priv *hw_priv;
|
||||
local_info_t *local;
|
||||
unsigned long flags;
|
||||
u8 v;
|
||||
|
||||
iface = netdev_priv(dev);
|
||||
local = iface->local;
|
||||
hw_priv = local->hw_priv;
|
||||
|
||||
spin_lock_irqsave(&local->lock, flags);
|
||||
v = readb(hw_priv->mem_start + a);
|
||||
@ -91,11 +95,13 @@ static inline u8 hfa384x_inb_debug(struct net_device *dev, int a)
|
||||
static inline void hfa384x_outw_debug(struct net_device *dev, int a, u16 v)
|
||||
{
|
||||
struct hostap_interface *iface;
|
||||
struct hostap_pci_priv *hw_priv;
|
||||
local_info_t *local;
|
||||
unsigned long flags;
|
||||
|
||||
iface = netdev_priv(dev);
|
||||
local = iface->local;
|
||||
hw_priv = local->hw_priv;
|
||||
|
||||
spin_lock_irqsave(&local->lock, flags);
|
||||
prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTW, a, v);
|
||||
@ -106,12 +112,14 @@ static inline void hfa384x_outw_debug(struct net_device *dev, int a, u16 v)
|
||||
static inline u16 hfa384x_inw_debug(struct net_device *dev, int a)
|
||||
{
|
||||
struct hostap_interface *iface;
|
||||
struct hostap_pci_priv *hw_priv;
|
||||
local_info_t *local;
|
||||
unsigned long flags;
|
||||
u16 v;
|
||||
|
||||
iface = netdev_priv(dev);
|
||||
local = iface->local;
|
||||
hw_priv = local->hw_priv;
|
||||
|
||||
spin_lock_irqsave(&local->lock, flags);
|
||||
v = readw(hw_priv->mem_start + a);
|
||||
@ -277,8 +285,6 @@ static struct prism2_helper_functions prism2_pci_funcs =
|
||||
{
|
||||
.card_present = NULL,
|
||||
.cor_sreset = prism2_pci_cor_sreset,
|
||||
.dev_open = NULL,
|
||||
.dev_close = NULL,
|
||||
.genesis_reset = prism2_pci_genesis_reset,
|
||||
.hw_type = HOSTAP_HW_PCI,
|
||||
};
|
||||
@ -352,8 +358,6 @@ static int prism2_pci_probe(struct pci_dev *pdev,
|
||||
return hostap_hw_ready(dev);
|
||||
|
||||
fail:
|
||||
kfree(hw_priv);
|
||||
|
||||
if (irq_registered && dev)
|
||||
free_irq(dev->irq, dev);
|
||||
|
||||
@ -364,10 +368,8 @@ static int prism2_pci_probe(struct pci_dev *pdev,
|
||||
|
||||
err_out_disable:
|
||||
pci_disable_device(pdev);
|
||||
kfree(hw_priv);
|
||||
if (local)
|
||||
local->hw_priv = NULL;
|
||||
prism2_free_local_data(dev);
|
||||
kfree(hw_priv);
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
@ -392,9 +394,8 @@ static void prism2_pci_remove(struct pci_dev *pdev)
|
||||
free_irq(dev->irq, dev);
|
||||
|
||||
mem_start = hw_priv->mem_start;
|
||||
kfree(hw_priv);
|
||||
iface->local->hw_priv = NULL;
|
||||
prism2_free_local_data(dev);
|
||||
kfree(hw_priv);
|
||||
|
||||
iounmap(mem_start);
|
||||
|
||||
@ -441,7 +442,7 @@ static int prism2_pci_resume(struct pci_dev *pdev)
|
||||
MODULE_DEVICE_TABLE(pci, prism2_pci_id_table);
|
||||
|
||||
static struct pci_driver prism2_pci_drv_id = {
|
||||
.name = "prism2_pci",
|
||||
.name = "hostap_pci",
|
||||
.id_table = prism2_pci_id_table,
|
||||
.probe = prism2_pci_probe,
|
||||
.remove = prism2_pci_remove,
|
||||
|
@ -328,8 +328,6 @@ static struct prism2_helper_functions prism2_plx_funcs =
|
||||
{
|
||||
.card_present = NULL,
|
||||
.cor_sreset = prism2_plx_cor_sreset,
|
||||
.dev_open = NULL,
|
||||
.dev_close = NULL,
|
||||
.genesis_reset = prism2_plx_genesis_reset,
|
||||
.hw_type = HOSTAP_HW_PLX,
|
||||
};
|
||||
@ -570,10 +568,8 @@ static int prism2_plx_probe(struct pci_dev *pdev,
|
||||
return hostap_hw_ready(dev);
|
||||
|
||||
fail:
|
||||
kfree(hw_priv);
|
||||
if (local)
|
||||
local->hw_priv = NULL;
|
||||
prism2_free_local_data(dev);
|
||||
kfree(hw_priv);
|
||||
|
||||
if (irq_registered && dev)
|
||||
free_irq(dev->irq, dev);
|
||||
@ -606,9 +602,8 @@ static void prism2_plx_remove(struct pci_dev *pdev)
|
||||
if (dev->irq)
|
||||
free_irq(dev->irq, dev);
|
||||
|
||||
kfree(iface->local->hw_priv);
|
||||
iface->local->hw_priv = NULL;
|
||||
prism2_free_local_data(dev);
|
||||
kfree(hw_priv);
|
||||
pci_disable_device(pdev);
|
||||
}
|
||||
|
||||
@ -616,7 +611,7 @@ static void prism2_plx_remove(struct pci_dev *pdev)
|
||||
MODULE_DEVICE_TABLE(pci, prism2_plx_id_table);
|
||||
|
||||
static struct pci_driver prism2_plx_drv_id = {
|
||||
.name = "prism2_plx",
|
||||
.name = "hostap_plx",
|
||||
.id_table = prism2_plx_id_table,
|
||||
.probe = prism2_plx_probe,
|
||||
.remove = prism2_plx_remove,
|
||||
|
@ -552,8 +552,6 @@ struct prism2_helper_functions {
|
||||
* (hostap_{cs,plx,pci}.c */
|
||||
int (*card_present)(local_info_t *local);
|
||||
void (*cor_sreset)(local_info_t *local);
|
||||
int (*dev_open)(local_info_t *local);
|
||||
int (*dev_close)(local_info_t *local);
|
||||
void (*genesis_reset)(local_info_t *local, int hcr);
|
||||
|
||||
/* the following functions are from hostap_hw.c, but they may have some
|
||||
|
@ -800,8 +800,7 @@ static int ipw2100_hw_send_command(struct ipw2100_priv *priv,
|
||||
* doesn't seem to have as many firmware restart cycles...
|
||||
*
|
||||
* As a test, we're sticking in a 1/100s delay here */
|
||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
schedule_timeout(HZ / 100);
|
||||
schedule_timeout_uninterruptible(msecs_to_jiffies(10));
|
||||
|
||||
return 0;
|
||||
|
||||
@ -1256,8 +1255,7 @@ static int ipw2100_start_adapter(struct ipw2100_priv *priv)
|
||||
IPW_DEBUG_FW("Waiting for f/w initialization to complete...\n");
|
||||
i = 5000;
|
||||
do {
|
||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
schedule_timeout(40 * HZ / 1000);
|
||||
schedule_timeout_uninterruptible(msecs_to_jiffies(40));
|
||||
/* Todo... wait for sync command ... */
|
||||
|
||||
read_register(priv->net_dev, IPW_REG_INTA, &inta);
|
||||
@ -1411,8 +1409,7 @@ static int ipw2100_hw_phy_off(struct ipw2100_priv *priv)
|
||||
(val2 & IPW2100_COMMAND_PHY_OFF))
|
||||
return 0;
|
||||
|
||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
schedule_timeout(HW_PHY_OFF_LOOP_DELAY);
|
||||
schedule_timeout_uninterruptible(HW_PHY_OFF_LOOP_DELAY);
|
||||
}
|
||||
|
||||
return -EIO;
|
||||
@ -1466,7 +1463,7 @@ static int ipw2100_enable_adapter(struct ipw2100_priv *priv)
|
||||
|
||||
static int ipw2100_hw_stop_adapter(struct ipw2100_priv *priv)
|
||||
{
|
||||
#define HW_POWER_DOWN_DELAY (HZ / 10)
|
||||
#define HW_POWER_DOWN_DELAY (msecs_to_jiffies(100))
|
||||
|
||||
struct host_command cmd = {
|
||||
.host_command = HOST_PRE_POWER_DOWN,
|
||||
@ -1520,10 +1517,8 @@ static int ipw2100_hw_stop_adapter(struct ipw2100_priv *priv)
|
||||
printk(KERN_WARNING DRV_NAME ": "
|
||||
"%s: Power down command failed: Error %d\n",
|
||||
priv->net_dev->name, err);
|
||||
else {
|
||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
schedule_timeout(HW_POWER_DOWN_DELAY);
|
||||
}
|
||||
else
|
||||
schedule_timeout_uninterruptible(HW_POWER_DOWN_DELAY);
|
||||
}
|
||||
|
||||
priv->status &= ~STATUS_ENABLED;
|
||||
@ -2953,7 +2948,7 @@ static void ipw2100_tx_send_data(struct ipw2100_priv *priv)
|
||||
int next = txq->next;
|
||||
int i = 0;
|
||||
struct ipw2100_data_header *ipw_hdr;
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct ieee80211_hdr_3addr *hdr;
|
||||
|
||||
while (!list_empty(&priv->tx_pend_list)) {
|
||||
/* if there isn't enough space in TBD queue, then
|
||||
@ -2989,7 +2984,7 @@ static void ipw2100_tx_send_data(struct ipw2100_priv *priv)
|
||||
packet->index = txq->next;
|
||||
|
||||
ipw_hdr = packet->info.d_struct.data;
|
||||
hdr = (struct ieee80211_hdr *)packet->info.d_struct.txb->
|
||||
hdr = (struct ieee80211_hdr_3addr *)packet->info.d_struct.txb->
|
||||
fragments[0]->data;
|
||||
|
||||
if (priv->ieee->iw_mode == IW_MODE_INFRA) {
|
||||
@ -3274,7 +3269,8 @@ static irqreturn_t ipw2100_interrupt(int irq, void *data,
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
static int ipw2100_tx(struct ieee80211_txb *txb, struct net_device *dev)
|
||||
static int ipw2100_tx(struct ieee80211_txb *txb, struct net_device *dev,
|
||||
int pri)
|
||||
{
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct list_head *element;
|
||||
|
@ -808,7 +808,7 @@ struct ipw2100_priv {
|
||||
struct ipw2100_rx {
|
||||
union {
|
||||
unsigned char payload[IPW_RX_NIC_BUFFER_LENGTH];
|
||||
struct ieee80211_hdr header;
|
||||
struct ieee80211_hdr_4addr header;
|
||||
u32 status;
|
||||
struct ipw2100_notification notification;
|
||||
struct ipw2100_cmd_header command;
|
||||
|
@ -4904,7 +4904,7 @@ static void ipw_rx(struct ipw_priv *priv)
|
||||
{
|
||||
struct ipw_rx_mem_buffer *rxb;
|
||||
struct ipw_rx_packet *pkt;
|
||||
struct ieee80211_hdr *header;
|
||||
struct ieee80211_hdr_4addr *header;
|
||||
u32 r, w, i;
|
||||
u8 network_packet;
|
||||
|
||||
@ -4967,8 +4967,9 @@ static void ipw_rx(struct ipw_priv *priv)
|
||||
#endif
|
||||
|
||||
header =
|
||||
(struct ieee80211_hdr *)(rxb->skb->data +
|
||||
IPW_RX_FRAME_SIZE);
|
||||
(struct ieee80211_hdr_4addr *)(rxb->skb->
|
||||
data +
|
||||
IPW_RX_FRAME_SIZE);
|
||||
/* TODO: Check Ad-Hoc dest/source and make sure
|
||||
* that we are actually parsing these packets
|
||||
* correctly -- we should probably use the
|
||||
@ -5317,8 +5318,6 @@ static int ipw_wx_set_freq(struct net_device *dev,
|
||||
|
||||
IPW_DEBUG_WX("SET Freq/Channel -> %d \n", fwrq->m);
|
||||
return ipw_set_channel(priv, (u8) fwrq->m);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ipw_wx_get_freq(struct net_device *dev,
|
||||
@ -6010,12 +6009,12 @@ static int ipw_wx_set_wireless_mode(struct net_device *dev,
|
||||
}
|
||||
|
||||
if (priv->adapter == IPW_2915ABG) {
|
||||
priv->ieee->abg_ture = 1;
|
||||
priv->ieee->abg_true = 1;
|
||||
if (mode & IEEE_A) {
|
||||
band |= IEEE80211_52GHZ_BAND;
|
||||
modulation |= IEEE80211_OFDM_MODULATION;
|
||||
} else
|
||||
priv->ieee->abg_ture = 0;
|
||||
priv->ieee->abg_true = 0;
|
||||
} else {
|
||||
if (mode & IEEE_A) {
|
||||
IPW_WARNING("Attempt to set 2200BG into "
|
||||
@ -6023,20 +6022,20 @@ static int ipw_wx_set_wireless_mode(struct net_device *dev,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
priv->ieee->abg_ture = 0;
|
||||
priv->ieee->abg_true = 0;
|
||||
}
|
||||
|
||||
if (mode & IEEE_B) {
|
||||
band |= IEEE80211_24GHZ_BAND;
|
||||
modulation |= IEEE80211_CCK_MODULATION;
|
||||
} else
|
||||
priv->ieee->abg_ture = 0;
|
||||
priv->ieee->abg_true = 0;
|
||||
|
||||
if (mode & IEEE_G) {
|
||||
band |= IEEE80211_24GHZ_BAND;
|
||||
modulation |= IEEE80211_OFDM_MODULATION;
|
||||
} else
|
||||
priv->ieee->abg_ture = 0;
|
||||
priv->ieee->abg_true = 0;
|
||||
|
||||
priv->ieee->mode = mode;
|
||||
priv->ieee->freq_band = band;
|
||||
@ -6325,7 +6324,7 @@ we need to heavily modify the ieee80211_skb_to_txb.
|
||||
|
||||
static inline void ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb)
|
||||
{
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)
|
||||
struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *)
|
||||
txb->fragments[0]->data;
|
||||
int i = 0;
|
||||
struct tfd_frame *tfd;
|
||||
@ -6448,7 +6447,7 @@ static inline void ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb)
|
||||
}
|
||||
|
||||
static int ipw_net_hard_start_xmit(struct ieee80211_txb *txb,
|
||||
struct net_device *dev)
|
||||
struct net_device *dev, int pri)
|
||||
{
|
||||
struct ipw_priv *priv = ieee80211_priv(dev);
|
||||
unsigned long flags;
|
||||
@ -7108,7 +7107,7 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
printk(KERN_INFO DRV_NAME
|
||||
": Detected Intel PRO/Wireless 2915ABG Network "
|
||||
"Connection\n");
|
||||
priv->ieee->abg_ture = 1;
|
||||
priv->ieee->abg_true = 1;
|
||||
band = IEEE80211_52GHZ_BAND | IEEE80211_24GHZ_BAND;
|
||||
modulation = IEEE80211_OFDM_MODULATION |
|
||||
IEEE80211_CCK_MODULATION;
|
||||
@ -7124,7 +7123,7 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
": Detected Intel PRO/Wireless 2200BG Network "
|
||||
"Connection\n");
|
||||
|
||||
priv->ieee->abg_ture = 0;
|
||||
priv->ieee->abg_true = 0;
|
||||
band = IEEE80211_24GHZ_BAND;
|
||||
modulation = IEEE80211_OFDM_MODULATION |
|
||||
IEEE80211_CCK_MODULATION;
|
||||
|
@ -1654,12 +1654,12 @@ static const long ipw_frequencies[] = {
|
||||
|
||||
#define IPW_MAX_CONFIG_RETRIES 10
|
||||
|
||||
static inline u32 frame_hdr_len(struct ieee80211_hdr *hdr)
|
||||
static inline u32 frame_hdr_len(struct ieee80211_hdr_4addr *hdr)
|
||||
{
|
||||
u32 retval;
|
||||
u16 fc;
|
||||
|
||||
retval = sizeof(struct ieee80211_hdr);
|
||||
retval = sizeof(struct ieee80211_hdr_3addr);
|
||||
fc = le16_to_cpu(hdr->frame_ctl);
|
||||
|
||||
/*
|
||||
|
@ -57,9 +57,7 @@
|
||||
#include <linux/bitops.h>
|
||||
#ifdef CONFIG_NET_RADIO
|
||||
#include <linux/wireless.h>
|
||||
#if WIRELESS_EXT > 12
|
||||
#include <net/iw_handler.h>
|
||||
#endif /* WIRELESS_EXT > 12 */
|
||||
#endif
|
||||
|
||||
#include <pcmcia/cs_types.h>
|
||||
@ -225,10 +223,7 @@ static void update_stats(struct net_device *dev);
|
||||
static struct net_device_stats *netwave_get_stats(struct net_device *dev);
|
||||
|
||||
/* Wireless extensions */
|
||||
#ifdef WIRELESS_EXT
|
||||
static struct iw_statistics* netwave_get_wireless_stats(struct net_device *dev);
|
||||
#endif
|
||||
static int netwave_ioctl(struct net_device *, struct ifreq *, int);
|
||||
|
||||
static void set_multicast_list(struct net_device *dev);
|
||||
|
||||
@ -260,26 +255,7 @@ static dev_link_t *dev_list;
|
||||
because they generally can't be allocated dynamically.
|
||||
*/
|
||||
|
||||
#if WIRELESS_EXT <= 12
|
||||
/* Wireless extensions backward compatibility */
|
||||
|
||||
/* Part of iw_handler prototype we need */
|
||||
struct iw_request_info
|
||||
{
|
||||
__u16 cmd; /* Wireless Extension command */
|
||||
__u16 flags; /* More to come ;-) */
|
||||
};
|
||||
|
||||
/* Wireless Extension Backward compatibility - Jean II
|
||||
* If the new wireless device private ioctl range is not defined,
|
||||
* default to standard device private ioctl range */
|
||||
#ifndef SIOCIWFIRSTPRIV
|
||||
#define SIOCIWFIRSTPRIV SIOCDEVPRIVATE
|
||||
#endif /* SIOCIWFIRSTPRIV */
|
||||
|
||||
#else /* WIRELESS_EXT <= 12 */
|
||||
static const struct iw_handler_def netwave_handler_def;
|
||||
#endif /* WIRELESS_EXT <= 12 */
|
||||
|
||||
#define SIOCGIPSNAP SIOCIWFIRSTPRIV + 1 /* Site Survey Snapshot */
|
||||
|
||||
@ -319,9 +295,7 @@ typedef struct netwave_private {
|
||||
struct timer_list watchdog; /* To avoid blocking state */
|
||||
struct site_survey nss;
|
||||
struct net_device_stats stats;
|
||||
#ifdef WIRELESS_EXT
|
||||
struct iw_statistics iw_stats; /* Wireless stats */
|
||||
#endif
|
||||
} netwave_private;
|
||||
|
||||
#ifdef NETWAVE_STATS
|
||||
@ -353,7 +327,6 @@ static inline void wait_WOC(unsigned int iobase)
|
||||
while ((inb(iobase + NETWAVE_REG_ASR) & 0x8) != 0x8) ;
|
||||
}
|
||||
|
||||
#ifdef WIRELESS_EXT
|
||||
static void netwave_snapshot(netwave_private *priv, u_char __iomem *ramBase,
|
||||
kio_addr_t iobase) {
|
||||
u_short resultBuffer;
|
||||
@ -376,9 +349,7 @@ static void netwave_snapshot(netwave_private *priv, u_char __iomem *ramBase,
|
||||
sizeof(struct site_survey));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WIRELESS_EXT
|
||||
/*
|
||||
* Function netwave_get_wireless_stats (dev)
|
||||
*
|
||||
@ -411,7 +382,6 @@ static struct iw_statistics *netwave_get_wireless_stats(struct net_device *dev)
|
||||
|
||||
return &priv->iw_stats;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Function netwave_attach (void)
|
||||
@ -471,13 +441,7 @@ static dev_link_t *netwave_attach(void)
|
||||
dev->get_stats = &netwave_get_stats;
|
||||
dev->set_multicast_list = &set_multicast_list;
|
||||
/* wireless extensions */
|
||||
#if WIRELESS_EXT <= 16
|
||||
dev->get_wireless_stats = &netwave_get_wireless_stats;
|
||||
#endif /* WIRELESS_EXT <= 16 */
|
||||
#if WIRELESS_EXT > 12
|
||||
dev->wireless_handlers = (struct iw_handler_def *)&netwave_handler_def;
|
||||
#endif /* WIRELESS_EXT > 12 */
|
||||
dev->do_ioctl = &netwave_ioctl;
|
||||
|
||||
dev->tx_timeout = &netwave_watchdog;
|
||||
dev->watchdog_timeo = TX_TIMEOUT;
|
||||
@ -576,13 +540,8 @@ static int netwave_set_nwid(struct net_device *dev,
|
||||
/* Disable interrupts & save flags */
|
||||
spin_lock_irqsave(&priv->spinlock, flags);
|
||||
|
||||
#if WIRELESS_EXT > 8
|
||||
if(!wrqu->nwid.disabled) {
|
||||
domain = wrqu->nwid.value;
|
||||
#else /* WIRELESS_EXT > 8 */
|
||||
if(wrqu->nwid.on) {
|
||||
domain = wrqu->nwid.nwid;
|
||||
#endif /* WIRELESS_EXT > 8 */
|
||||
printk( KERN_DEBUG "Setting domain to 0x%x%02x\n",
|
||||
(domain >> 8) & 0x01, domain & 0xff);
|
||||
wait_WOC(iobase);
|
||||
@ -606,15 +565,9 @@ static int netwave_get_nwid(struct net_device *dev,
|
||||
union iwreq_data *wrqu,
|
||||
char *extra)
|
||||
{
|
||||
#if WIRELESS_EXT > 8
|
||||
wrqu->nwid.value = domain;
|
||||
wrqu->nwid.disabled = 0;
|
||||
wrqu->nwid.fixed = 1;
|
||||
#else /* WIRELESS_EXT > 8 */
|
||||
wrqu->nwid.nwid = domain;
|
||||
wrqu->nwid.on = 1;
|
||||
#endif /* WIRELESS_EXT > 8 */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -657,17 +610,11 @@ static int netwave_get_scramble(struct net_device *dev,
|
||||
{
|
||||
key[1] = scramble_key & 0xff;
|
||||
key[0] = (scramble_key>>8) & 0xff;
|
||||
#if WIRELESS_EXT > 8
|
||||
wrqu->encoding.flags = IW_ENCODE_ENABLED;
|
||||
wrqu->encoding.length = 2;
|
||||
#else /* WIRELESS_EXT > 8 */
|
||||
wrqu->encoding.method = 1;
|
||||
#endif /* WIRELESS_EXT > 8 */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if WIRELESS_EXT > 8
|
||||
/*
|
||||
* Wireless Handler : get mode
|
||||
*/
|
||||
@ -683,7 +630,6 @@ static int netwave_get_mode(struct net_device *dev,
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* WIRELESS_EXT > 8 */
|
||||
|
||||
/*
|
||||
* Wireless Handler : get range info
|
||||
@ -702,11 +648,9 @@ static int netwave_get_range(struct net_device *dev,
|
||||
/* Set all the info we don't care or don't know about to zero */
|
||||
memset(range, 0, sizeof(struct iw_range));
|
||||
|
||||
#if WIRELESS_EXT > 10
|
||||
/* Set the Wireless Extension versions */
|
||||
range->we_version_compiled = WIRELESS_EXT;
|
||||
range->we_version_source = 9; /* Nothing for us in v10 and v11 */
|
||||
#endif /* WIRELESS_EXT > 10 */
|
||||
|
||||
/* Set information in the range struct */
|
||||
range->throughput = 450 * 1000; /* don't argue on this ! */
|
||||
@ -720,16 +664,12 @@ static int netwave_get_range(struct net_device *dev,
|
||||
range->max_qual.level = 255;
|
||||
range->max_qual.noise = 0;
|
||||
|
||||
#if WIRELESS_EXT > 7
|
||||
range->num_bitrates = 1;
|
||||
range->bitrate[0] = 1000000; /* 1 Mb/s */
|
||||
#endif /* WIRELESS_EXT > 7 */
|
||||
|
||||
#if WIRELESS_EXT > 8
|
||||
range->encoding_size[0] = 2; /* 16 bits scrambling */
|
||||
range->num_encoding_sizes = 1;
|
||||
range->max_encoding_tokens = 1; /* Only one key possible */
|
||||
#endif /* WIRELESS_EXT > 8 */
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -775,8 +715,6 @@ static const struct iw_priv_args netwave_private_args[] = {
|
||||
"getsitesurvey" },
|
||||
};
|
||||
|
||||
#if WIRELESS_EXT > 12
|
||||
|
||||
static const iw_handler netwave_handler[] =
|
||||
{
|
||||
NULL, /* SIOCSIWNAME */
|
||||
@ -839,131 +777,8 @@ static const struct iw_handler_def netwave_handler_def =
|
||||
.standard = (iw_handler *) netwave_handler,
|
||||
.private = (iw_handler *) netwave_private_handler,
|
||||
.private_args = (struct iw_priv_args *) netwave_private_args,
|
||||
#if WIRELESS_EXT > 16
|
||||
.get_wireless_stats = netwave_get_wireless_stats,
|
||||
#endif /* WIRELESS_EXT > 16 */
|
||||
};
|
||||
#endif /* WIRELESS_EXT > 12 */
|
||||
|
||||
/*
|
||||
* Function netwave_ioctl (dev, rq, cmd)
|
||||
*
|
||||
* Perform ioctl : config & info stuff
|
||||
* This is the stuff that are treated the wireless extensions (iwconfig)
|
||||
*
|
||||
*/
|
||||
static int netwave_ioctl(struct net_device *dev, /* ioctl device */
|
||||
struct ifreq *rq, /* Data passed */
|
||||
int cmd) /* Ioctl number */
|
||||
{
|
||||
int ret = 0;
|
||||
#ifdef WIRELESS_EXT
|
||||
#if WIRELESS_EXT <= 12
|
||||
struct iwreq *wrq = (struct iwreq *) rq;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
DEBUG(0, "%s: ->netwave_ioctl(cmd=0x%X)\n", dev->name, cmd);
|
||||
|
||||
/* Look what is the request */
|
||||
switch(cmd) {
|
||||
/* --------------- WIRELESS EXTENSIONS --------------- */
|
||||
#ifdef WIRELESS_EXT
|
||||
#if WIRELESS_EXT <= 12
|
||||
case SIOCGIWNAME:
|
||||
netwave_get_name(dev, NULL, &(wrq->u), NULL);
|
||||
break;
|
||||
case SIOCSIWNWID:
|
||||
ret = netwave_set_nwid(dev, NULL, &(wrq->u), NULL);
|
||||
break;
|
||||
case SIOCGIWNWID:
|
||||
ret = netwave_get_nwid(dev, NULL, &(wrq->u), NULL);
|
||||
break;
|
||||
#if WIRELESS_EXT > 8 /* Note : The API did change... */
|
||||
case SIOCGIWENCODE:
|
||||
/* Get scramble key */
|
||||
if(wrq->u.encoding.pointer != (caddr_t) 0)
|
||||
{
|
||||
char key[2];
|
||||
ret = netwave_get_scramble(dev, NULL, &(wrq->u), key);
|
||||
if(copy_to_user(wrq->u.encoding.pointer, key, 2))
|
||||
ret = -EFAULT;
|
||||
}
|
||||
break;
|
||||
case SIOCSIWENCODE:
|
||||
/* Set scramble key */
|
||||
if(wrq->u.encoding.pointer != (caddr_t) 0)
|
||||
{
|
||||
char key[2];
|
||||
if(copy_from_user(key, wrq->u.encoding.pointer, 2))
|
||||
{
|
||||
ret = -EFAULT;
|
||||
break;
|
||||
}
|
||||
ret = netwave_set_scramble(dev, NULL, &(wrq->u), key);
|
||||
}
|
||||
break;
|
||||
case SIOCGIWMODE:
|
||||
/* Mode of operation */
|
||||
ret = netwave_get_mode(dev, NULL, &(wrq->u), NULL);
|
||||
break;
|
||||
#else /* WIRELESS_EXT > 8 */
|
||||
case SIOCGIWENCODE:
|
||||
/* Get scramble key */
|
||||
ret = netwave_get_scramble(dev, NULL, &(wrq->u),
|
||||
(char *) &wrq->u.encoding.code);
|
||||
break;
|
||||
case SIOCSIWENCODE:
|
||||
/* Set scramble key */
|
||||
ret = netwave_set_scramble(dev, NULL, &(wrq->u),
|
||||
(char *) &wrq->u.encoding.code);
|
||||
break;
|
||||
#endif /* WIRELESS_EXT > 8 */
|
||||
case SIOCGIWRANGE:
|
||||
/* Basic checking... */
|
||||
if(wrq->u.data.pointer != (caddr_t) 0) {
|
||||
struct iw_range range;
|
||||
ret = netwave_get_range(dev, NULL, &(wrq->u), (char *) &range);
|
||||
if (copy_to_user(wrq->u.data.pointer, &range,
|
||||
sizeof(struct iw_range)))
|
||||
ret = -EFAULT;
|
||||
}
|
||||
break;
|
||||
case SIOCGIWPRIV:
|
||||
/* Basic checking... */
|
||||
if(wrq->u.data.pointer != (caddr_t) 0) {
|
||||
/* Set the number of ioctl available */
|
||||
wrq->u.data.length = sizeof(netwave_private_args) / sizeof(netwave_private_args[0]);
|
||||
|
||||
/* Copy structure to the user buffer */
|
||||
if(copy_to_user(wrq->u.data.pointer,
|
||||
(u_char *) netwave_private_args,
|
||||
sizeof(netwave_private_args)))
|
||||
ret = -EFAULT;
|
||||
}
|
||||
break;
|
||||
case SIOCGIPSNAP:
|
||||
if(wrq->u.data.pointer != (caddr_t) 0) {
|
||||
char buffer[sizeof( struct site_survey)];
|
||||
ret = netwave_get_snap(dev, NULL, &(wrq->u), buffer);
|
||||
/* Copy structure to the user buffer */
|
||||
if(copy_to_user(wrq->u.data.pointer,
|
||||
buffer,
|
||||
sizeof( struct site_survey)))
|
||||
{
|
||||
printk(KERN_DEBUG "Bad buffer!\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif /* WIRELESS_EXT <= 12 */
|
||||
#endif /* WIRELESS_EXT */
|
||||
default:
|
||||
ret = -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function netwave_pcmcia_config (link)
|
||||
|
@ -77,30 +77,16 @@
|
||||
#define DRIVER_NAME "orinoco"
|
||||
|
||||
#include <linux/config.h>
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/if_arp.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/wireless.h>
|
||||
#include <net/iw_handler.h>
|
||||
#include <net/ieee80211.h>
|
||||
|
||||
#include <net/ieee80211.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/system.h>
|
||||
|
||||
#include "hermes.h"
|
||||
#include "hermes_rid.h"
|
||||
#include "orinoco.h"
|
||||
|
||||
@ -137,7 +123,7 @@ MODULE_PARM_DESC(force_monitor, "Allow monitor mode for all firmware versions");
|
||||
|
||||
/* We do this this way to avoid ifdefs in the actual code */
|
||||
#ifdef WIRELESS_SPY
|
||||
#define SPY_NUMBER(priv) (priv->spy_number)
|
||||
#define SPY_NUMBER(priv) (priv->spy_data.spy_number)
|
||||
#else
|
||||
#define SPY_NUMBER(priv) 0
|
||||
#endif /* WIRELESS_SPY */
|
||||
@ -216,31 +202,32 @@ static struct {
|
||||
/********************************************************************/
|
||||
|
||||
/* Used in Event handling.
|
||||
* We avoid nested structres as they break on ARM -- Moustafa */
|
||||
* We avoid nested structures as they break on ARM -- Moustafa */
|
||||
struct hermes_tx_descriptor_802_11 {
|
||||
/* hermes_tx_descriptor */
|
||||
u16 status;
|
||||
u16 reserved1;
|
||||
u16 reserved2;
|
||||
u32 sw_support;
|
||||
__le16 status;
|
||||
__le16 reserved1;
|
||||
__le16 reserved2;
|
||||
__le32 sw_support;
|
||||
u8 retry_count;
|
||||
u8 tx_rate;
|
||||
u16 tx_control;
|
||||
__le16 tx_control;
|
||||
|
||||
/* ieee802_11_hdr */
|
||||
u16 frame_ctl;
|
||||
u16 duration_id;
|
||||
/* ieee80211_hdr */
|
||||
__le16 frame_ctl;
|
||||
__le16 duration_id;
|
||||
u8 addr1[ETH_ALEN];
|
||||
u8 addr2[ETH_ALEN];
|
||||
u8 addr3[ETH_ALEN];
|
||||
u16 seq_ctl;
|
||||
__le16 seq_ctl;
|
||||
u8 addr4[ETH_ALEN];
|
||||
u16 data_len;
|
||||
|
||||
__le16 data_len;
|
||||
|
||||
/* ethhdr */
|
||||
unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
|
||||
unsigned char h_source[ETH_ALEN]; /* source ether addr */
|
||||
unsigned short h_proto; /* packet type ID field */
|
||||
u8 h_dest[ETH_ALEN]; /* destination eth addr */
|
||||
u8 h_source[ETH_ALEN]; /* source ether addr */
|
||||
__be16 h_proto; /* packet type ID field */
|
||||
|
||||
/* p8022_hdr */
|
||||
u8 dsap;
|
||||
@ -248,31 +235,31 @@ struct hermes_tx_descriptor_802_11 {
|
||||
u8 ctrl;
|
||||
u8 oui[3];
|
||||
|
||||
u16 ethertype;
|
||||
__be16 ethertype;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Rx frame header except compatibility 802.3 header */
|
||||
struct hermes_rx_descriptor {
|
||||
/* Control */
|
||||
u16 status;
|
||||
u32 time;
|
||||
__le16 status;
|
||||
__le32 time;
|
||||
u8 silence;
|
||||
u8 signal;
|
||||
u8 rate;
|
||||
u8 rxflow;
|
||||
u32 reserved;
|
||||
__le32 reserved;
|
||||
|
||||
/* 802.11 header */
|
||||
u16 frame_ctl;
|
||||
u16 duration_id;
|
||||
__le16 frame_ctl;
|
||||
__le16 duration_id;
|
||||
u8 addr1[ETH_ALEN];
|
||||
u8 addr2[ETH_ALEN];
|
||||
u8 addr3[ETH_ALEN];
|
||||
u16 seq_ctl;
|
||||
__le16 seq_ctl;
|
||||
u8 addr4[ETH_ALEN];
|
||||
|
||||
/* Data length */
|
||||
u16 data_len;
|
||||
__le16 data_len;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/********************************************************************/
|
||||
@ -396,14 +383,14 @@ static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
|
||||
/* If a spy address is defined, we report stats of the
|
||||
* first spy address - Jean II */
|
||||
if (SPY_NUMBER(priv)) {
|
||||
wstats->qual.qual = priv->spy_stat[0].qual;
|
||||
wstats->qual.level = priv->spy_stat[0].level;
|
||||
wstats->qual.noise = priv->spy_stat[0].noise;
|
||||
wstats->qual.updated = priv->spy_stat[0].updated;
|
||||
wstats->qual.qual = priv->spy_data.spy_stat[0].qual;
|
||||
wstats->qual.level = priv->spy_data.spy_stat[0].level;
|
||||
wstats->qual.noise = priv->spy_data.spy_stat[0].noise;
|
||||
wstats->qual.updated = priv->spy_data.spy_stat[0].updated;
|
||||
}
|
||||
} else {
|
||||
struct {
|
||||
u16 qual, signal, noise;
|
||||
__le16 qual, signal, noise;
|
||||
} __attribute__ ((packed)) cq;
|
||||
|
||||
err = HERMES_READ_RECORD(hw, USER_BAP,
|
||||
@ -505,11 +492,9 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
|
||||
/* Check packet length, pad short packets, round up odd length */
|
||||
len = max_t(int, ALIGN(skb->len, 2), ETH_ZLEN);
|
||||
if (skb->len < len) {
|
||||
skb = skb_padto(skb, len);
|
||||
if (skb == NULL)
|
||||
goto fail;
|
||||
}
|
||||
skb = skb_padto(skb, len);
|
||||
if (skb == NULL)
|
||||
goto fail;
|
||||
len -= ETH_HLEN;
|
||||
|
||||
eh = (struct ethhdr *)skb->data;
|
||||
@ -634,16 +619,17 @@ static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw)
|
||||
struct orinoco_private *priv = netdev_priv(dev);
|
||||
struct net_device_stats *stats = &priv->stats;
|
||||
u16 fid = hermes_read_regn(hw, TXCOMPLFID);
|
||||
u16 status;
|
||||
struct hermes_tx_descriptor_802_11 hdr;
|
||||
int err = 0;
|
||||
|
||||
if (fid == DUMMY_FID)
|
||||
return; /* Nothing's really happened */
|
||||
|
||||
/* Read the frame header */
|
||||
/* Read part of the frame header - we need status and addr1 */
|
||||
err = hermes_bap_pread(hw, IRQ_BAP, &hdr,
|
||||
sizeof(struct hermes_tx_descriptor) +
|
||||
sizeof(struct ieee80211_hdr),
|
||||
offsetof(struct hermes_tx_descriptor_802_11,
|
||||
addr2),
|
||||
fid, 0);
|
||||
|
||||
hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
|
||||
@ -663,8 +649,8 @@ static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw)
|
||||
* exceeded, because that's the only status that really mean
|
||||
* that this particular node went away.
|
||||
* Other errors means that *we* screwed up. - Jean II */
|
||||
hdr.status = le16_to_cpu(hdr.status);
|
||||
if (hdr.status & (HERMES_TXSTAT_RETRYERR | HERMES_TXSTAT_AGEDERR)) {
|
||||
status = le16_to_cpu(hdr.status);
|
||||
if (status & (HERMES_TXSTAT_RETRYERR | HERMES_TXSTAT_AGEDERR)) {
|
||||
union iwreq_data wrqu;
|
||||
|
||||
/* Copy 802.11 dest address.
|
||||
@ -723,18 +709,13 @@ static inline int is_ethersnap(void *_hdr)
|
||||
static inline void orinoco_spy_gather(struct net_device *dev, u_char *mac,
|
||||
int level, int noise)
|
||||
{
|
||||
struct orinoco_private *priv = netdev_priv(dev);
|
||||
int i;
|
||||
|
||||
/* Gather wireless spy statistics: for each packet, compare the
|
||||
* source address with out list, and if match, get the stats... */
|
||||
for (i = 0; i < priv->spy_number; i++)
|
||||
if (!memcmp(mac, priv->spy_address[i], ETH_ALEN)) {
|
||||
priv->spy_stat[i].level = level - 0x95;
|
||||
priv->spy_stat[i].noise = noise - 0x95;
|
||||
priv->spy_stat[i].qual = (level > noise) ? (level - noise) : 0;
|
||||
priv->spy_stat[i].updated = 7;
|
||||
}
|
||||
struct iw_quality wstats;
|
||||
wstats.level = level - 0x95;
|
||||
wstats.noise = noise - 0x95;
|
||||
wstats.qual = (level > noise) ? (level - noise) : 0;
|
||||
wstats.updated = 7;
|
||||
/* Update spy records */
|
||||
wireless_spy_update(dev, mac, &wstats);
|
||||
}
|
||||
|
||||
static void orinoco_stat_gather(struct net_device *dev,
|
||||
@ -1055,7 +1036,7 @@ static void orinoco_join_ap(struct net_device *dev)
|
||||
unsigned long flags;
|
||||
struct join_req {
|
||||
u8 bssid[ETH_ALEN];
|
||||
u16 channel;
|
||||
__le16 channel;
|
||||
} __attribute__ ((packed)) req;
|
||||
const int atom_len = offsetof(struct prism2_scan_apinfo, atim);
|
||||
struct prism2_scan_apinfo *atom = NULL;
|
||||
@ -1070,7 +1051,7 @@ static void orinoco_join_ap(struct net_device *dev)
|
||||
return;
|
||||
|
||||
if (orinoco_lock(priv, &flags) != 0)
|
||||
goto out;
|
||||
goto fail_lock;
|
||||
|
||||
/* Sanity checks in case user changed something in the meantime */
|
||||
if (! priv->bssid_fixed)
|
||||
@ -1115,8 +1096,10 @@ static void orinoco_join_ap(struct net_device *dev)
|
||||
printk(KERN_ERR "%s: Error issuing join request\n", dev->name);
|
||||
|
||||
out:
|
||||
kfree(buf);
|
||||
orinoco_unlock(priv, &flags);
|
||||
|
||||
fail_lock:
|
||||
kfree(buf);
|
||||
}
|
||||
|
||||
/* Send new BSSID to userspace */
|
||||
@ -1134,12 +1117,14 @@ static void orinoco_send_wevents(struct net_device *dev)
|
||||
err = hermes_read_ltv(hw, IRQ_BAP, HERMES_RID_CURRENTBSSID,
|
||||
ETH_ALEN, NULL, wrqu.ap_addr.sa_data);
|
||||
if (err != 0)
|
||||
return;
|
||||
goto out;
|
||||
|
||||
wrqu.ap_addr.sa_family = ARPHRD_ETHER;
|
||||
|
||||
/* Send event to user space */
|
||||
wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
|
||||
|
||||
out:
|
||||
orinoco_unlock(priv, &flags);
|
||||
}
|
||||
|
||||
@ -1148,8 +1133,8 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
|
||||
struct orinoco_private *priv = netdev_priv(dev);
|
||||
u16 infofid;
|
||||
struct {
|
||||
u16 len;
|
||||
u16 type;
|
||||
__le16 len;
|
||||
__le16 type;
|
||||
} __attribute__ ((packed)) info;
|
||||
int len, type;
|
||||
int err;
|
||||
@ -2464,6 +2449,10 @@ struct net_device *alloc_orinocodev(int sizeof_card,
|
||||
dev->get_stats = orinoco_get_stats;
|
||||
dev->ethtool_ops = &orinoco_ethtool_ops;
|
||||
dev->wireless_handlers = (struct iw_handler_def *)&orinoco_handler_def;
|
||||
#ifdef WIRELESS_SPY
|
||||
priv->wireless_data.spy_data = &priv->spy_data;
|
||||
dev->wireless_data = &priv->wireless_data;
|
||||
#endif
|
||||
dev->change_mtu = orinoco_change_mtu;
|
||||
dev->set_multicast_list = orinoco_set_multicast_list;
|
||||
/* we use the default eth_mac_addr for setting the MAC addr */
|
||||
@ -2835,7 +2824,7 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev,
|
||||
}
|
||||
}
|
||||
|
||||
if ((priv->iw_mode == IW_MODE_ADHOC) && (priv->spy_number == 0)){
|
||||
if ((priv->iw_mode == IW_MODE_ADHOC) && (!SPY_NUMBER(priv))){
|
||||
/* Quality stats meaningless in ad-hoc mode */
|
||||
} else {
|
||||
range->max_qual.qual = 0x8b - 0x2f;
|
||||
@ -2882,6 +2871,14 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev,
|
||||
range->min_r_time = 0;
|
||||
range->max_r_time = 65535 * 1000; /* ??? */
|
||||
|
||||
/* Event capability (kernel) */
|
||||
IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
|
||||
/* Event capability (driver) */
|
||||
IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWTHRSPY);
|
||||
IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
|
||||
IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
|
||||
IW_EVENT_CAPA_SET(range->event_capa, IWEVTXDROP);
|
||||
|
||||
TRACE_EXIT(dev->name);
|
||||
|
||||
return 0;
|
||||
@ -3841,92 +3838,6 @@ static int orinoco_ioctl_getrid(struct net_device *dev,
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Spy is used for link quality/strength measurements in Ad-Hoc mode
|
||||
* Jean II */
|
||||
static int orinoco_ioctl_setspy(struct net_device *dev,
|
||||
struct iw_request_info *info,
|
||||
struct iw_point *srq,
|
||||
char *extra)
|
||||
|
||||
{
|
||||
struct orinoco_private *priv = netdev_priv(dev);
|
||||
struct sockaddr *address = (struct sockaddr *) extra;
|
||||
int number = srq->length;
|
||||
int i;
|
||||
unsigned long flags;
|
||||
|
||||
/* Make sure nobody mess with the structure while we do */
|
||||
if (orinoco_lock(priv, &flags) != 0)
|
||||
return -EBUSY;
|
||||
|
||||
/* orinoco_lock() doesn't disable interrupts, so make sure the
|
||||
* interrupt rx path don't get confused while we copy */
|
||||
priv->spy_number = 0;
|
||||
|
||||
if (number > 0) {
|
||||
/* Extract the addresses */
|
||||
for (i = 0; i < number; i++)
|
||||
memcpy(priv->spy_address[i], address[i].sa_data,
|
||||
ETH_ALEN);
|
||||
/* Reset stats */
|
||||
memset(priv->spy_stat, 0,
|
||||
sizeof(struct iw_quality) * IW_MAX_SPY);
|
||||
/* Set number of addresses */
|
||||
priv->spy_number = number;
|
||||
}
|
||||
|
||||
/* Now, let the others play */
|
||||
orinoco_unlock(priv, &flags);
|
||||
|
||||
/* Do NOT call commit handler */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int orinoco_ioctl_getspy(struct net_device *dev,
|
||||
struct iw_request_info *info,
|
||||
struct iw_point *srq,
|
||||
char *extra)
|
||||
{
|
||||
struct orinoco_private *priv = netdev_priv(dev);
|
||||
struct sockaddr *address = (struct sockaddr *) extra;
|
||||
int number;
|
||||
int i;
|
||||
unsigned long flags;
|
||||
|
||||
if (orinoco_lock(priv, &flags) != 0)
|
||||
return -EBUSY;
|
||||
|
||||
number = priv->spy_number;
|
||||
/* Create address struct */
|
||||
for (i = 0; i < number; i++) {
|
||||
memcpy(address[i].sa_data, priv->spy_address[i], ETH_ALEN);
|
||||
address[i].sa_family = AF_UNIX;
|
||||
}
|
||||
if (number > 0) {
|
||||
/* Create address struct */
|
||||
for (i = 0; i < number; i++) {
|
||||
memcpy(address[i].sa_data, priv->spy_address[i],
|
||||
ETH_ALEN);
|
||||
address[i].sa_family = AF_UNIX;
|
||||
}
|
||||
/* Copy stats */
|
||||
/* In theory, we should disable irqs while copying the stats
|
||||
* because the rx path might update it in the middle...
|
||||
* Bah, who care ? - Jean II */
|
||||
memcpy(extra + (sizeof(struct sockaddr) * number),
|
||||
priv->spy_stat, sizeof(struct iw_quality) * number);
|
||||
}
|
||||
/* Reset updated flags. */
|
||||
for (i = 0; i < number; i++)
|
||||
priv->spy_stat[i].updated = 0;
|
||||
|
||||
orinoco_unlock(priv, &flags);
|
||||
|
||||
srq->length = number;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Trigger a scan (look for other cells in the vicinity */
|
||||
static int orinoco_ioctl_setscan(struct net_device *dev,
|
||||
struct iw_request_info *info,
|
||||
@ -3999,7 +3910,7 @@ static int orinoco_ioctl_setscan(struct net_device *dev,
|
||||
HERMES_HOSTSCAN_SYMBOL_BCAST);
|
||||
break;
|
||||
case FIRMWARE_TYPE_INTERSIL: {
|
||||
u16 req[3];
|
||||
__le16 req[3];
|
||||
|
||||
req[0] = cpu_to_le16(0x3fff); /* All channels */
|
||||
req[1] = cpu_to_le16(0x0001); /* rate 1 Mbps */
|
||||
@ -4073,7 +3984,7 @@ static inline int orinoco_translate_scan(struct net_device *dev,
|
||||
case FIRMWARE_TYPE_INTERSIL:
|
||||
offset = 4;
|
||||
if (priv->has_hostscan) {
|
||||
atom_len = le16_to_cpup((u16 *)scan);
|
||||
atom_len = le16_to_cpup((__le16 *)scan);
|
||||
/* Sanity check for atom_len */
|
||||
if (atom_len < sizeof(struct prism2_scan_apinfo)) {
|
||||
printk(KERN_ERR "%s: Invalid atom_len in scan data: %d\n",
|
||||
@ -4357,8 +4268,10 @@ static const iw_handler orinoco_handler[] = {
|
||||
[SIOCSIWSENS -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setsens,
|
||||
[SIOCGIWSENS -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getsens,
|
||||
[SIOCGIWRANGE -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getiwrange,
|
||||
[SIOCSIWSPY -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setspy,
|
||||
[SIOCGIWSPY -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getspy,
|
||||
[SIOCSIWSPY -SIOCIWFIRST] = (iw_handler) iw_handler_set_spy,
|
||||
[SIOCGIWSPY -SIOCIWFIRST] = (iw_handler) iw_handler_get_spy,
|
||||
[SIOCSIWTHRSPY-SIOCIWFIRST] = (iw_handler) iw_handler_set_thrspy,
|
||||
[SIOCGIWTHRSPY-SIOCIWFIRST] = (iw_handler) iw_handler_get_thrspy,
|
||||
[SIOCSIWAP -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setwap,
|
||||
[SIOCGIWAP -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getwap,
|
||||
[SIOCSIWSCAN -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setscan,
|
||||
|
@ -7,12 +7,11 @@
|
||||
#ifndef _ORINOCO_H
|
||||
#define _ORINOCO_H
|
||||
|
||||
#define DRIVER_VERSION "0.15rc2"
|
||||
#define DRIVER_VERSION "0.15rc3"
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/wireless.h>
|
||||
#include <net/iw_handler.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
#include "hermes.h"
|
||||
@ -28,7 +27,7 @@
|
||||
#define ORINOCO_MAX_KEYS 4
|
||||
|
||||
struct orinoco_key {
|
||||
u16 len; /* always stored as little-endian */
|
||||
__le16 len; /* always stored as little-endian */
|
||||
char data[ORINOCO_MAX_KEY_SIZE];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
@ -36,14 +35,14 @@ struct header_struct {
|
||||
/* 802.3 */
|
||||
u8 dest[ETH_ALEN];
|
||||
u8 src[ETH_ALEN];
|
||||
u16 len;
|
||||
__be16 len;
|
||||
/* 802.2 */
|
||||
u8 dsap;
|
||||
u8 ssap;
|
||||
u8 ctrl;
|
||||
/* SNAP */
|
||||
u8 oui[3];
|
||||
u16 ethertype;
|
||||
unsigned short ethertype;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
typedef enum {
|
||||
@ -112,9 +111,8 @@ struct orinoco_private {
|
||||
u16 pm_on, pm_mcast, pm_period, pm_timeout;
|
||||
u16 preamble;
|
||||
#ifdef WIRELESS_SPY
|
||||
int spy_number;
|
||||
u_char spy_address[IW_MAX_SPY][ETH_ALEN];
|
||||
struct iw_quality spy_stat[IW_MAX_SPY];
|
||||
struct iw_spy_data spy_data; /* iwspy support */
|
||||
struct iw_public_data wireless_data;
|
||||
#endif
|
||||
|
||||
/* Configuration dependent variables */
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user