Commit 4df7c015 authored by Jeff Garzik's avatar Jeff Garzik

Hand merge.

parents a925c40f 5c6c0af0
......@@ -156,6 +156,11 @@ if it was in suspended state. Please note that this function can fail.
which enables the bus master bit in PCI_COMMAND register and also fixes
the latency timer value if it's set to something bogus by the BIOS.
If you want to use the PCI Memory-Write-Invalidate transaction,
call pci_set_mwi(). This enables bit PCI_COMMAND bit for Mem-Wr-Inval
and also ensures that the cache line size register is set correctly.
Make sure to check the return value of pci_set_mwi(), not all architectures
may support Memory-Write-Invalidate.
4. How to access PCI config space
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
......@@ -202,6 +207,8 @@ pci_resource_end() Returns bus end address for a given PCI region
pci_resource_len() Returns the byte length of a PCI region
pci_set_drvdata() Set private driver data pointer for a pci_dev
pci_get_drvdata() Return private driver data pointer for a pci_dev
pci_set_mwi() Enable Memory-Write-Invalidate transactions.
pci_clear_mwi() Disable Memory-Write-Invalidate transactions.
7. Miscellaneous hints
......
......@@ -2,6 +2,7 @@
/*
Copyright 2001,2002 Jeff Garzik <jgarzik@mandrakesoft.com>
Copyright (C) 2001, 2002 David S. Miller (davem@redhat.com) [tg3.c]
Copyright (C) 2000, 2001 David S. Miller (davem@redhat.com) [sungem.c]
Copyright 2001 Manfred Spraul [natsemi.c]
Copyright 1999-2001 by Donald Becker. [natsemi.c]
......@@ -29,8 +30,8 @@
* Consider Rx interrupt mitigation using TimerIntr
* Implement 8139C+ statistics dump; maybe not...
h/w stats can be reset only by software reset
* Rx checksumming
* Tx checksumming
* Handle netif_rx return value
* ETHTOOL_GREGS, ETHTOOL_[GS]WOL,
* Investigate using skb->priority with h/w VLAN priority
* Investigate using High Priority Tx Queue with skb->priority
......@@ -38,8 +39,8 @@
* Adjust Tx FIFO threshold and Max Tx DMA burst on Tx FIFO error
* Implement Tx software interrupt mitigation via
Tx descriptor bit
* Determine correct value for CP_{MIN,MAX}_MTU, instead of
using conservative guesses.
* The real minimum of CP_MIN_MTU is 4 bytes. However,
for this to be supported, one must(?) turn on packet padding.
*/
......@@ -48,8 +49,10 @@
#define DRV_RELDATE "Feb 27, 2002"
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/compiler.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
......@@ -57,9 +60,15 @@
#include <linux/delay.h>
#include <linux/ethtool.h>
#include <linux/mii.h>
#include <linux/if_vlan.h>
#include <linux/crc32.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#define CP_VLAN_TAG_USED 0
#define CP_VLAN_TX_TAG(tx_desc,vlan_tag_value) \
do { (tx_desc)->opts2 = 0; } while (0)
/* These identify the driver base version and may not be removed. */
static char version[] __devinitdata =
KERN_INFO DRV_NAME " 10/100 PCI Ethernet driver v" DRV_VERSION " (" DRV_RELDATE ")\n";
......@@ -110,8 +119,8 @@ MODULE_PARM_DESC (multicast_filter_limit, "8139cp maximum number of filtered mul
#define TX_TIMEOUT (6*HZ)
/* hardware minimum and maximum for a single frame's data payload */
#define CP_MIN_MTU 60 /* FIXME: this is a guess */
#define CP_MAX_MTU 1500 /* FIXME: this is a guess */
#define CP_MIN_MTU 60 /* TODO: allow lower, but pad */
#define CP_MAX_MTU 4096
enum {
/* NIC register offsets */
......@@ -153,12 +162,17 @@ enum {
IPCS = (1 << 18), /* Calculate IP checksum */
UDPCS = (1 << 17), /* Calculate UDP/IP checksum */
TCPCS = (1 << 16), /* Calculate TCP/IP checksum */
TxVlanTag = (1 << 17), /* Add VLAN tag */
RxVlanTagged = (1 << 16), /* Rx VLAN tag available */
IPFail = (1 << 15), /* IP checksum failed */
UDPFail = (1 << 14), /* UDP/IP checksum failed */
TCPFail = (1 << 13), /* TCP/IP checksum failed */
NormalTxPoll = (1 << 6), /* One or more normal Tx packets to send */
PID1 = (1 << 17), /* 2 protocol id bits: 0==non-IP, */
PID0 = (1 << 16), /* 1==UDP/IP, 2==TCP/IP, 3==IP */
RxProtoTCP = 2,
RxProtoUDP = 1,
RxProtoIP = 3,
TxFIFOUnder = (1 << 25), /* Tx FIFO underrun */
TxOWC = (1 << 22), /* Tx Out-of-window collision */
TxLinkFail = (1 << 21), /* Link failed during Tx of packet */
......@@ -208,6 +222,7 @@ enum {
TxOn = (1 << 2), /* Tx mode enable */
/* C+ mode command register */
RxVlanOn = (1 << 6), /* Rx VLAN de-tagging enable */
RxChkSum = (1 << 5), /* Rx checksum offload enable */
PCIMulRW = (1 << 3), /* Enable PCI read/write multiple */
CpRxOn = (1 << 1), /* Rx mode enable */
......@@ -278,6 +293,10 @@ struct cp_private {
unsigned rx_buf_sz;
dma_addr_t ring_dma;
#if CP_VLAN_TAG_USED
struct vlan_group *vlgrp;
#endif
u32 msg_enable;
struct net_device_stats net_stats;
......@@ -335,14 +354,21 @@ static inline void cp_set_rxbufsize (struct cp_private *cp)
cp->rx_buf_sz = PKT_BUF_SZ;
}
static inline void cp_rx_skb (struct cp_private *cp, struct sk_buff *skb)
static inline void cp_rx_skb (struct cp_private *cp, struct sk_buff *skb,
struct cp_desc *desc)
{
skb->protocol = eth_type_trans (skb, cp->dev);
cp->net_stats.rx_packets++;
cp->net_stats.rx_bytes += skb->len;
cp->dev->last_rx = jiffies;
netif_rx (skb);
#if CP_VLAN_TAG_USED
if (cp->vlgrp && (desc->opts2 & RxVlanTagged)) {
vlan_hwaccel_rx(skb, cp->vlgrp, desc->opts2 & 0xffff);
} else
#endif
netif_rx(skb);
}
static void cp_rx_err_acct (struct cp_private *cp, unsigned rx_tail,
......@@ -425,13 +451,26 @@ static void cp_rx_frag (struct cp_private *cp, unsigned rx_tail,
cp_rx_err_acct(cp, rx_tail, status, len);
dev_kfree_skb_irq(copy_skb);
} else
cp_rx_skb(cp, copy_skb);
cp_rx_skb(cp, copy_skb, &cp->rx_ring[rx_tail]);
cp->frag_skb = NULL;
} else {
cp->frag_skb = copy_skb;
}
}
static inline unsigned int cp_rx_csum_ok (u32 status)
{
unsigned int protocol = (status >> 16) & 0x3;
if (likely((protocol == RxProtoTCP) && (!(status & TCPFail))))
return 1;
else if ((protocol == RxProtoUDP) && (!(status & UDPFail)))
return 1;
else if ((protocol == RxProtoIP) && (!(status & IPFail)))
return 1;
return 0;
}
static void cp_rx (struct cp_private *cp)
{
unsigned rx_tail = cp->rx_tail;
......@@ -441,13 +480,15 @@ static void cp_rx (struct cp_private *cp)
u32 status, len;
dma_addr_t mapping;
struct sk_buff *skb, *new_skb;
struct cp_desc *desc;
unsigned buflen;
skb = cp->rx_skb[rx_tail].skb;
if (!skb)
BUG();
rmb();
status = le32_to_cpu(cp->rx_ring[rx_tail].opts1);
desc = &cp->rx_ring[rx_tail];
status = le32_to_cpu(desc->opts1);
if (status & DescOwn)
break;
......@@ -480,7 +521,13 @@ static void cp_rx (struct cp_private *cp)
pci_unmap_single(cp->pdev, mapping,
buflen, PCI_DMA_FROMDEVICE);
skb->ip_summed = CHECKSUM_NONE;
/* Handle checksum offloading for incoming packets. */
if (cp_rx_csum_ok(status))
skb->ip_summed = CHECKSUM_UNNECESSARY;
else
skb->ip_summed = CHECKSUM_NONE;
skb_put(skb, len);
mapping =
......@@ -489,15 +536,14 @@ static void cp_rx (struct cp_private *cp)
buflen, PCI_DMA_FROMDEVICE);
cp->rx_skb[rx_tail].skb = new_skb;
cp_rx_skb(cp, skb);
cp_rx_skb(cp, skb, desc);
rx_next:
if (rx_tail == (CP_RX_RING_SIZE - 1))
cp->rx_ring[rx_tail].opts1 =
cpu_to_le32(DescOwn | RingEnd | cp->rx_buf_sz);
desc->opts1 = cpu_to_le32(DescOwn | RingEnd |
cp->rx_buf_sz);
else
cp->rx_ring[rx_tail].opts1 =
cpu_to_le32(DescOwn | cp->rx_buf_sz);
desc->opts1 = cpu_to_le32(DescOwn | cp->rx_buf_sz);
cp->rx_ring[rx_tail].opts2 = 0;
cp->rx_ring[rx_tail].addr_lo = cpu_to_le32(mapping);
rx_tail = NEXT_RX(rx_tail);
......@@ -606,6 +652,9 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
struct cp_private *cp = dev->priv;
unsigned entry;
u32 eor;
#if CP_VLAN_TAG_USED
u32 vlan_tag = 0;
#endif
spin_lock_irq(&cp->lock);
......@@ -615,6 +664,11 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
return 1;
}
#if CP_VLAN_TAG_USED
if (cp->vlgrp && vlan_tx_tag_present(skb))
vlan_tag = TxVlanTag | vlan_tx_tag_get(skb);
#endif
entry = cp->tx_head;
eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0;
if (skb_shinfo(skb)->nr_frags == 0) {
......@@ -624,7 +678,7 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
len = skb->len;
mapping = pci_map_single(cp->pdev, skb->data, len, PCI_DMA_TODEVICE);
eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0;
txd->opts2 = 0;
CP_VLAN_TX_TAG(txd, vlan_tag);
txd->addr_lo = cpu_to_le32(mapping);
wmb();
......@@ -677,7 +731,7 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
ctrl |= LastFrag;
txd = &cp->tx_ring[entry];
txd->opts2 = 0;
CP_VLAN_TX_TAG(txd, vlan_tag);
txd->addr_lo = cpu_to_le32(mapping);
wmb();
......@@ -691,7 +745,7 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
}
txd = &cp->tx_ring[first_entry];
txd->opts2 = 0;
CP_VLAN_TX_TAG(txd, vlan_tag);
txd->addr_lo = cpu_to_le32(first_mapping);
wmb();
......@@ -826,7 +880,7 @@ static void cp_reset_hw (struct cp_private *cp)
static inline void cp_start_hw (struct cp_private *cp)
{
cpw8(Cmd, RxOn | TxOn);
cpw16(CpCmd, PCIMulRW | CpRxOn | CpTxOn);
cpw16(CpCmd, PCIMulRW | RxChkSum | CpRxOn | CpTxOn);
}
static void cp_init_hw (struct cp_private *cp)
......@@ -1171,7 +1225,30 @@ static int cp_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
return rc;
}
#if CP_VLAN_TAG_USED
static int cp_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
{
struct cp_private *cp = dev->priv;
spin_lock_irq(&cp->lock);
cp->vlgrp = grp;
cpw16(CpCmd, cpr16(CpCmd) | RxVlanOn);
spin_unlock_irq(&cp->lock);
return 0;
}
static void cp_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
{
struct cp_private *cp = dev->priv;
spin_lock_irq(&cp->lock);
cpw16(CpCmd, cpr16(CpCmd) & ~RxVlanOn);
if (cp->vlgrp)
cp->vlgrp->vlan_devices[vid] = NULL;
spin_unlock_irq(&cp->lock);
}
#endif
/* Serial EEPROM section. */
......@@ -1337,6 +1414,11 @@ static int __devinit cp_init_one (struct pci_dev *pdev,
#ifdef CP_TX_CHECKSUM
dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
#endif
#if CP_VLAN_TAG_USED
dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
dev->vlan_rx_register = cp_vlan_rx_register;
dev->vlan_rx_kill_vid = cp_vlan_rx_kill_vid;
#endif
dev->irq = pdev->irq;
......
......@@ -148,7 +148,7 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
fi
if [ "$CONFIG_NET_PCI" = "y" ]; then
dep_tristate ' AMD PCnet32 PCI support' CONFIG_PCNET32 $CONFIG_PCI
dep_tristate ' Adaptec Starfire support (EXPERIMENTAL)' CONFIG_ADAPTEC_STARFIRE $CONFIG_PCI $CONFIG_EXPERIMENTAL
dep_tristate ' Adaptec Starfire/DuraLAN support' CONFIG_ADAPTEC_STARFIRE $CONFIG_PCI
if [ "$CONFIG_ISA" = "y" -o "$CONFIG_EISA" = "y" ]; then
dep_tristate ' Ansel Communications EISA 3200 support (EXPERIMENTAL)' CONFIG_AC3200 $CONFIG_EXPERIMENTAL
fi
......
......@@ -128,7 +128,7 @@ static char *e1000_strings[] = {
"IBM Mobile, Desktop & Server Adapters"
};
/* Local Function Prototypes */
/* e1000_main.c Function Prototypes */
int e1000_up(struct e1000_adapter *adapter);
void e1000_down(struct e1000_adapter *adapter);
......@@ -193,23 +193,6 @@ MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
MODULE_DESCRIPTION("Intel(R) PRO/1000 Network Driver");
MODULE_LICENSE("Dual BSD/GPL");
#ifdef EXPORT_SYMTAB
EXPORT_SYMBOL(e1000_init_module);
EXPORT_SYMBOL(e1000_exit_module);
EXPORT_SYMBOL(e1000_probe);
EXPORT_SYMBOL(e1000_remove);
EXPORT_SYMBOL(e1000_open);
EXPORT_SYMBOL(e1000_close);
EXPORT_SYMBOL(e1000_xmit_frame);
EXPORT_SYMBOL(e1000_intr);
EXPORT_SYMBOL(e1000_set_multi);
EXPORT_SYMBOL(e1000_change_mtu);
EXPORT_SYMBOL(e1000_set_mac);
EXPORT_SYMBOL(e1000_get_stats);
EXPORT_SYMBOL(e1000_watchdog);
EXPORT_SYMBOL(e1000_ioctl);
#endif
/**
* e1000_init_module - Driver Registration Routine
*
......
......@@ -96,13 +96,18 @@
LK1.3.5 (jgarzik)
- ethtool NWAY_RST, GLINK, [GS]MSGLVL support
LK1.3.6 (Ion Badulescu)
- Sparc64 support and fixes
- Better stats and error handling
TODO:
- implement tx_timeout() properly
- VLAN support
*/
#define DRV_NAME "starfire"
#define DRV_VERSION "1.03+LK1.3.5"
#define DRV_RELDATE "November 17, 2001"
#define DRV_VERSION "1.03+LK1.3.6"
#define DRV_RELDATE "March 6, 2002"
#include <linux/version.h>
#include <linux/module.h>
......@@ -128,8 +133,11 @@
* for this driver to really use the firmware. Note that Rx/Tx
* hardware TCP checksumming is not possible without the firmware.
*
* I'm currently [Feb 2001] talking to Adaptec about this redistribution
* issue. Stay tuned...
* If Adaptec could allow redistribution of the firmware (even in binary
* format), life would become a lot easier. Unfortunately, I've lost my
* Adaptec contacts, so progress on this front is rather unlikely to
* occur. If anybody from Adaptec reads this and can help with this matter,
* please let me know...
*/
#undef HAS_FIRMWARE
/*
......@@ -609,6 +617,7 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
long ioaddr;
int drv_flags, io_size;
int boguscnt;
u16 cmd;
u8 cache;
/* when built into the kernel, we only print version if device is found */
......@@ -644,14 +653,22 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
goto err_out_free_netdev;
}
ioaddr = (long) ioremap (ioaddr, io_size);
/* ioremap is borken in Linux-2.2.x/sparc64 */
#if !defined(CONFIG_SPARC64) || LINUX_VERSION_CODE > 0x20300
ioaddr = (long) ioremap(ioaddr, io_size);
if (!ioaddr) {
printk (KERN_ERR DRV_NAME " %d: cannot remap 0x%x @ 0x%lx, aborting\n",
card_idx, io_size, ioaddr);
goto err_out_free_res;
}
#endif /* !CONFIG_SPARC64 || Linux 2.3.0+ */
pci_set_master(pdev);
pci_set_master (pdev);
/* enable MWI -- it vastly improves Rx performance on sparc64 */
pci_read_config_word(pdev, PCI_COMMAND, &cmd);
cmd |= PCI_COMMAND_INVALIDATE;
pci_write_config_word(pdev, PCI_COMMAND, cmd);
/* set PCI cache size */
pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cache);
......@@ -670,7 +687,7 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
/* Serial EEPROM reads are hidden by the hardware. */
for (i = 0; i < 6; i++)
dev->dev_addr[i] = readb(ioaddr + EEPROMCtrl + 20-i);
dev->dev_addr[i] = readb(ioaddr + EEPROMCtrl + 20 - i);
#if ! defined(final_version) /* Dump the EEPROM contents during development. */
if (debug > 4)
......@@ -932,7 +949,7 @@ static int netdev_open(struct net_device *dev)
/* Fill both the unused Tx SA register and the Rx perfect filter. */
for (i = 0; i < 6; i++)
writeb(dev->dev_addr[i], ioaddr + StationAddr + 5-i);
writeb(dev->dev_addr[i], ioaddr + StationAddr + 5 - i);
for (i = 0; i < 16; i++) {
u16 *eaddrs = (u16 *)dev->dev_addr;
long setup_frm = ioaddr + PerfFilterTable + i * 16;
......@@ -979,9 +996,9 @@ static int netdev_open(struct net_device *dev)
#ifdef HAS_FIRMWARE
/* Load Rx/Tx firmware into the frame processors */
for (i = 0; i < FIRMWARE_RX_SIZE * 2; i++)
writel(cpu_to_le32(firmware_rx[i]), ioaddr + RxGfpMem + i * 4);
writel(firmware_rx[i], ioaddr + RxGfpMem + i * 4);
for (i = 0; i < FIRMWARE_TX_SIZE * 2; i++)
writel(cpu_to_le32(firmware_tx[i]), ioaddr + TxGfpMem + i * 4);
writel(firmware_tx[i], ioaddr + TxGfpMem + i * 4);
/* Enable the Rx and Tx units, and the Rx/Tx frame processors. */
writel(0x003F, ioaddr + GenCtrl);
#else /* not HAS_FIRMWARE */
......@@ -1156,8 +1173,8 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
np->tx_ring[entry].first_addr = cpu_to_le32(np->tx_info[entry].first_mapping);
#ifdef ZEROCOPY
np->tx_ring[entry].first_len = cpu_to_le32(skb_first_frag_len(skb));
np->tx_ring[entry].total_len = cpu_to_le32(skb->len);
np->tx_ring[entry].first_len = cpu_to_le16(skb_first_frag_len(skb));
np->tx_ring[entry].total_len = cpu_to_le16(skb->len);
/* Add "| TxDescIntr" to generate Tx-done interrupts. */
np->tx_ring[entry].status = cpu_to_le32(TxDescID | TxCRCEn);
np->tx_ring[entry].nbufs = cpu_to_le32(skb_shinfo(skb)->nr_frags + 1);
......@@ -1170,8 +1187,10 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
np->tx_ring[entry].status |= cpu_to_le32(TxRingWrap | TxDescIntr);
#ifdef ZEROCOPY
if (skb->ip_summed == CHECKSUM_HW)
if (skb->ip_summed == CHECKSUM_HW) {
np->tx_ring[entry].status |= cpu_to_le32(TxCalTCP);
np->stats.tx_compressed++;
}
#endif /* ZEROCOPY */
if (debug > 5) {
......@@ -1449,6 +1468,7 @@ static int netdev_rx(struct net_device *dev)
#if defined(full_rx_status) || defined(csum_rx_status)
if (le32_to_cpu(np->rx_done_q[np->rx_done].status2) & 0x01000000) {
skb->ip_summed = CHECKSUM_UNNECESSARY;
np->stats.rx_compressed++;
}
/*
* This feature doesn't seem to be working, at least
......@@ -1580,12 +1600,17 @@ static void netdev_error(struct net_device *dev, int intr_status)
printk(KERN_NOTICE "%s: Increasing Tx FIFO threshold to %d bytes\n",
dev->name, np->tx_threshold * 16);
}
if ((intr_status & ~(IntrNormalMask | IntrAbnormalSummary | IntrLinkChange | IntrStatsMax | IntrTxDataLow | IntrPCIPad)) && debug)
if (intr_status & IntrRxGFPDead) {
np->stats.rx_fifo_errors++;
np->stats.rx_errors++;
}
if (intr_status & (IntrNoTxCsum | IntrDMAErr)) {
np->stats.tx_fifo_errors++;
np->stats.tx_errors++;
}
if ((intr_status & ~(IntrNormalMask | IntrAbnormalSummary | IntrLinkChange | IntrStatsMax | IntrTxDataLow | IntrRxGFPDead | IntrNoTxCsum | IntrPCIPad)) && debug)
printk(KERN_ERR "%s: Something Wicked happened! %4.4x.\n",
dev->name, intr_status);
/* Hmmmmm, it's not clear how to recover from DMA faults. */
if (intr_status & IntrDMAErr)
np->stats.tx_fifo_errors++;
}
......
......@@ -23,6 +23,7 @@
#include <linux/kmod.h> /* for hotplug_path */
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/cache.h>
#include <asm/page.h>
#include <asm/dma.h> /* isa_dma_bridge_buggy */
......@@ -848,6 +849,100 @@ pci_set_master(struct pci_dev *dev)
pcibios_set_master(dev);
}
/**
* pdev_set_mwi - arch helper function for pcibios_set_mwi
* @dev: the PCI device for which MWI is enabled
*
* Helper function for implementation the arch-specific pcibios_set_mwi
* function. Originally copied from drivers/net/acenic.c.
* Copyright 1998-2001 by Jes Sorensen, <jes@trained-monkey.org>.
*
* RETURNS: An appriopriate -ERRNO error value on eror, or zero for success.
*/
int
pdev_set_mwi(struct pci_dev *dev)
{
int rc = 0;
u8 cache_size;
/*
* Looks like this is necessary to deal with on all architectures,
* even this %$#%$# N440BX Intel based thing doesn't get it right.
* Ie. having two NICs in the machine, one will have the cache
* line set at boot time, the other will not.
*/
pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &cache_size);
cache_size <<= 2;
if (cache_size != SMP_CACHE_BYTES) {
printk(KERN_WARNING "PCI: %s PCI cache line size set incorrectly "
"(%i bytes) by BIOS/FW, ",
dev->slot_name, cache_size);
if (cache_size > SMP_CACHE_BYTES) {
printk("expecting %i\n", SMP_CACHE_BYTES);
rc = -EINVAL;
} else {
printk("correcting to %i\n", SMP_CACHE_BYTES);
pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
SMP_CACHE_BYTES >> 2);
}
}
return rc;
}
/**
* pci_set_mwi - enables memory-write-validate PCI transaction
* @dev: the PCI device for which MWI is enabled
*
* Enables the Memory-Write-Invalidate transaction in %PCI_COMMAND,
* and then calls @pcibios_set_mwi to do the needed arch specific
* operations or a generic mwi-prep function.
*
* RETURNS: An appriopriate -ERRNO error value on eror, or zero for success.
*/
int
pci_set_mwi(struct pci_dev *dev)
{
int rc;
u16 cmd;
#ifdef HAVE_ARCH_PCI_MWI
rc = pcibios_set_mwi(dev);
#else
rc = pdev_set_mwi(dev);
#endif
if (rc)
return rc;
pci_read_config_word(dev, PCI_COMMAND, &cmd);
if (! (cmd & PCI_COMMAND_INVALIDATE)) {
DBG("PCI: Enabling Mem-Wr-Inval for device %s\n", dev->slot_name);
cmd |= PCI_COMMAND_INVALIDATE;
pci_write_config_word(dev, PCI_COMMAND, cmd);
}
return 0;
}
/**
* pci_clear_mwi - disables Memory-Write-Invalidate for device dev
* @dev: the PCI device to disable
*
* Disables PCI Memory-Write-Invalidate transaction on the device
*/
void
pci_clear_mwi(struct pci_dev *dev)
{
u16 cmd;
pci_read_config_word(dev, PCI_COMMAND, &cmd);
if (cmd & PCI_COMMAND_INVALIDATE) {
cmd &= ~PCI_COMMAND_INVALIDATE;
pci_write_config_word(dev, PCI_COMMAND, cmd);
}
}
int
pci_set_dma_mask(struct pci_dev *dev, u64 mask)
{
......@@ -2002,6 +2097,9 @@ EXPORT_SYMBOL(pci_find_device);
EXPORT_SYMBOL(pci_find_slot);
EXPORT_SYMBOL(pci_find_subsys);
EXPORT_SYMBOL(pci_set_master);
EXPORT_SYMBOL(pci_set_mwi);
EXPORT_SYMBOL(pci_clear_mwi);
EXPORT_SYMBOL(pdev_set_mwi);
EXPORT_SYMBOL(pci_set_dma_mask);
EXPORT_SYMBOL(pci_dac_set_dma_mask);
EXPORT_SYMBOL(pci_assign_resource);
......
......@@ -286,7 +286,7 @@ ctc_tty_tint(ctc_tty_info * info)
if (!info->netdev) {
if (skb)
kfree(skb);
kfree_skb(skb);
return 0;
}
if (info->flags & CTC_ASYNC_TX_LINESTAT) {
......
......@@ -564,6 +564,10 @@ int pci_write_config_dword(struct pci_dev *dev, int where, u32 val);
int pci_enable_device(struct pci_dev *dev);
void pci_disable_device(struct pci_dev *dev);
void pci_set_master(struct pci_dev *dev);
#define HAVE_PCI_SET_MWI
int pci_set_mwi(struct pci_dev *dev);
void pci_clear_mwi(struct pci_dev *dev);
int pdev_set_mwi(struct pci_dev *dev);
int pci_set_dma_mask(struct pci_dev *dev, u64 mask);
int pci_dac_set_dma_mask(struct pci_dev *dev, u64 mask);
int pci_assign_resource(struct pci_dev *dev, int i);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment